diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-09-01 00:37:02 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-09-01 00:37:02 +0000 |
commit | cc29364f06178f8f6b457384f2ec37a042bd9d43 (patch) | |
tree | 7c77a3184c698bbf9d98cef09fb1ba8124daceba /korganizer | |
parent | 4f6c584bacc8c3c694228f36ada3de77a76614a6 (diff) | |
download | tdepim-cc29364f06178f8f6b457384f2ec37a042bd9d43.tar.gz tdepim-cc29364f06178f8f6b457384f2ec37a042bd9d43.zip |
* Massive set of changes to bring in all fixes and enhancements from the Enterprise PIM branch
* Ensured that the Trinity changes were applied on top of those enhancements, and any redundancy removed
* Added journal read support to the CalDAV resource
* Fixed CalDAV resource to use events URL for tasks and journals when separate URL checkbox unchecked
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1170461 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'korganizer')
172 files changed, 8785 insertions, 3713 deletions
diff --git a/korganizer/Makefile.am b/korganizer/Makefile.am index 8b6e4d91e..6b434ab8a 100644 --- a/korganizer/Makefile.am +++ b/korganizer/Makefile.am @@ -90,7 +90,7 @@ libkorganizer_la_SOURCES = komessagebox.cpp \ koeventview.cpp \ korganizeriface.skel kcalendariface.skel \ filtereditdialog.cpp filteredit_base.ui \ - kowhatsnextview.cpp kocounterdialog.cpp \ + kowhatsnextview.cpp \ kojournalview.cpp journalentry.cpp \ kocore.cpp mailscheduler.cpp \ kodaymatrix.cpp docprefs.cpp statusdialog.cpp\ @@ -101,6 +101,7 @@ libkorganizer_la_SOURCES = komessagebox.cpp \ koprefs_base.kcfgc \ koincidencetooltip.cpp aboutdata.cpp \ importdialog.cpp \ + previewdialog.cpp \ korganizerifaceimpl.cpp \ freebusymanager.cpp freebusyurldialog.cpp \ eventarchiver.cpp koidentitymanager.cpp \ @@ -174,10 +175,10 @@ KDE_ICON = AUTO META_INCLUDES = $(srcdir)/interfaces/korganizer messages: rc.cpp - $(PREPARETIPS) > tips.txt + $(PREPARETIPS) > tips.cpp $(EXTRACTRC) `find . -name "*.rc" -o -name "*.ui" -o -name "*.kcfg"` >> rc.cpp - $(XGETTEXT) `find . -name "*.cpp" -o -name "*.h" -o -name "*.txt"` -o $(podir)/korganizer.pot - rm -f tips.txt + $(XGETTEXT) `find . -name "*.cpp" -o -name "*.h"` -o $(podir)/korganizer.pot + rm -f tips.cpp xdg_apps_DATA = korganizer.desktop diff --git a/korganizer/Todo-info.text b/korganizer/Todo-info.text new file mode 100644 index 000000000..19d911163 --- /dev/null +++ b/korganizer/Todo-info.text @@ -0,0 +1,18 @@ + + TODO's behavior in agenda and month views + + +Here are the rules for how/when/where should to-dos be displayed in agenda/month view: + +* startDt doesn't influence to-do behavior, it's irrelevant +* To-dos without dueDt aren't shown +* The time component doesn't influence the behavior in month view, only agenda +* Overdue to-dos appear today, and not at dtDue, so we don't forget them +* In agenda, if the to-do is overdue and has time, it should appear in the all + day area because, since it's overdue, you must do it ASAP and not wait for the + original time. + +* In agenda, a not-overdue to-do, with time, is drawn with the rectangle ending + at dtDue, and not starting at dtDue. If dtDue is at 00h00, then it should be + displayed in the previous day, ending at 23:59:59 + diff --git a/korganizer/aboutdata.cpp b/korganizer/aboutdata.cpp index f372d11fc..b5fb98c31 100644 --- a/korganizer/aboutdata.cpp +++ b/korganizer/aboutdata.cpp @@ -34,10 +34,11 @@ AboutData::AboutData() KAboutData::License_GPL, "(c) 1997-1999 Preston Brown\n" "(c) 2000-2004 Cornelius Schumacher\n" - "(c) 2004-2005 Reinhold Kainhofer", 0, + "(c) 2004-2005 Reinhold Kainhofer\n" + "(c) 2009-2010 Timothy Pearson", 0, "http://korganizer.kde.org" ) { - addAuthor("Timothy Pearson",I18N_NOOP("Current Maintainer"), + addAuthor("Timothy Pearson",I18N_NOOP("Current Developer/Maintainer"), "kb9vqf@pearsoncomputing.net"); addAuthor("Reinhold Kainhofer",I18N_NOOP("Previous maintainer"), "reinhold@kainhofer.com"); diff --git a/korganizer/actionmanager.cpp b/korganizer/actionmanager.cpp index 99939ef1c..b9df9e869 100644 --- a/korganizer/actionmanager.cpp +++ b/korganizer/actionmanager.cpp @@ -26,7 +26,7 @@ */ #include "actionmanager.h" - +#include "previewdialog.h" #include "alarmclient.h" #include "calendarview.h" #include "kocore.h" @@ -34,13 +34,15 @@ #include "koglobals.h" #include "koprefs.h" #include "koviewmanager.h" +#include "koagendaview.h" +#include "multiagendaview.h" #include "kowindowlist.h" #include "kprocess.h" #include "konewstuff.h" #include "history.h" #include "kogroupware.h" #include "resourceview.h" -#include "importdialog.h" +#include "previewdialog.h" #include "eventarchiver.h" #include "stdcalendar.h" #include "freebusymanager.h" @@ -68,13 +70,13 @@ #include <kstdguiitem.h> #include <kdeversion.h> #include <kactionclasses.h> +#include <kcmdlineargs.h> #include <tqapplication.h> #include <tqcursor.h> #include <tqtimer.h> #include <tqlabel.h> - // FIXME: Several places in the file don't use KConfigXT yet! KOWindowList *ActionManager::mWindowList = 0; @@ -153,12 +155,12 @@ void ActionManager::init() connect( mCalendarView, TQT_SIGNAL( modifiedChanged( bool ) ), TQT_SLOT( setTitle() ) ); connect( mCalendarView, TQT_SIGNAL( configChanged() ), TQT_SLOT( updateConfig() ) ); - connect( mCalendarView, TQT_SIGNAL( incidenceSelected( Incidence * ) ), - this, TQT_SLOT( processIncidenceSelection( Incidence * ) ) ); + connect( mCalendarView, TQT_SIGNAL( incidenceSelected( Incidence *,const TQDate & ) ), + this, TQT_SLOT( processIncidenceSelection( Incidence *,const TQDate & ) ) ); connect( mCalendarView, TQT_SIGNAL( exportHTML( HTMLExportSettings * ) ), this, TQT_SLOT( exportHTML( HTMLExportSettings * ) ) ); - processIncidenceSelection( 0 ); + processIncidenceSelection( 0, TQDate() ); // Update state of paste action mCalendarView->checkClipboard(); @@ -197,7 +199,7 @@ void ActionManager::createCalendarResources() mResourceView = factory.resourceView(); connect( mCalendarResources, TQT_SIGNAL( calendarChanged() ), - mCalendarView, TQT_SLOT(resourcesChanged() ) ); + mCalendarView, TQT_SLOT( resourcesChanged() ) ); connect( mCalendarResources, TQT_SIGNAL( signalErrorMessage( const TQString & ) ), mCalendarView, TQT_SLOT( showErrorMessage( const TQString & ) ) ); @@ -250,9 +252,9 @@ void ActionManager::initActions() //~~~~~~~~~~~~~~~~~~~~~~~~ IMPORT / EXPORT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - new KAction( i18n("Import &Calendar..."), 0, this, TQT_SLOT( file_merge() ), + new KAction( i18n("Import &Event/Calendar (ICS-/VCS-File)..."), 0, this, TQT_SLOT( file_merge() ), mACollection, "import_icalendar" ); - new KAction( i18n("&Import From UNIX Ical tool"), 0, this, TQT_SLOT( file_icalimport() ), + new KAction( i18n("&Import From UNIX Ical tool (.calendar-File)"), 0, this, TQT_SLOT( file_icalimport() ), mACollection, "import_ical" ); new KAction( i18n("Get &Hot New Stuff..."), 0, this, TQT_SLOT( downloadNewStuff() ), mACollection, @@ -312,10 +314,10 @@ void ActionManager::initActions() mACollection, "edit_delete" ); if ( mIsPart ) { KStdAction::find( mCalendarView->dialogManager(), TQT_SLOT( showSearchDialog() ), - mACollection, "korganizer_find" ); + mACollection, "korganizer_find" ); } else { KStdAction::find( mCalendarView->dialogManager(), TQT_SLOT( showSearchDialog() ), - mACollection ); + mACollection ); } pasteAction->setEnabled( false ); mUndoAction->setEnabled( false ); @@ -447,11 +449,11 @@ void ActionManager::initActions() //************************** Actions MENU ********************************* new KAction( i18n("New E&vent..."), KOGlobals::self()->smallIcon( "newappointment" ), 0, - mCalendarView, TQT_SLOT( newEvent() ), + mCalendarView, TQT_SLOT(newEvent()), mACollection, "new_event" ); new KAction( i18n("New &To-do..."), KOGlobals::self()->smallIcon( "newtodo" ), 0, - mCalendarView, TQT_SLOT( newTodo() ), + mCalendarView, TQT_SLOT(newTodo()), mACollection, "new_todo" ); action = new KAction( i18n("New Su&b-to-do..."), 0, mCalendarView,TQT_SLOT( newSubTodo() ), @@ -461,7 +463,7 @@ void ActionManager::initActions() action,TQT_SLOT( setEnabled( bool ) ) ); new KAction( i18n("New &Journal..."), KOGlobals::self()->smallIcon( "newjournal" ), 0, - mCalendarView, TQT_SLOT( newJournal() ), + mCalendarView, TQT_SLOT(newJournal()), mACollection, "new_journal" ); mShowIncidenceAction = new KAction( i18n("&Show"), 0, @@ -498,40 +500,42 @@ void ActionManager::initActions() mACollection, "schedule_publish" ); mPublishEvent->setEnabled( false ); - action = new KAction( i18n("Send &Invitation to Attendees"),"mail_generic",0, - mCalendarView,TQT_SLOT( schedule_request() ), - mACollection,"schedule_request" ); - action->setEnabled( false ); - connect( mCalendarView, TQT_SIGNAL( organizerEventsSelected( bool ) ), - action, TQT_SLOT( setEnabled( bool ) ) ); - - action = new KAction( i18n("Re&quest Update"), 0, - mCalendarView, TQT_SLOT( schedule_refresh() ), - mACollection, "schedule_refresh" ); - action->setEnabled( false ); - connect( mCalendarView,TQT_SIGNAL( groupEventsSelected( bool ) ), - action,TQT_SLOT( setEnabled( bool ) ) ); - - action = new KAction( i18n("Send &Cancelation to Attendees"), 0, - mCalendarView, TQT_SLOT( schedule_cancel() ), - mACollection, "schedule_cancel" ); - action->setEnabled( false ); - connect( mCalendarView,TQT_SIGNAL( organizerEventsSelected( bool ) ), - action,TQT_SLOT( setEnabled( bool ) ) ); - - action = new KAction( i18n("Send Status &Update"),"mail_reply",0, - mCalendarView,TQT_SLOT( schedule_reply() ), - mACollection,"schedule_reply" ); - action->setEnabled( false ); - connect( mCalendarView,TQT_SIGNAL( groupEventsSelected( bool ) ), - action,TQT_SLOT( setEnabled( bool ) ) ); - - action = new KAction( i18n("counter proposal","Request Chan&ge"),0, - mCalendarView,TQT_SLOT( schedule_counter() ), - mACollection, "schedule_counter" ); - action->setEnabled( false ); - connect( mCalendarView,TQT_SIGNAL( groupEventsSelected( bool ) ), - action,TQT_SLOT( setEnabled( bool ) ) ); + mSendInvitation = new KAction( i18n( "Send &Invitation to Attendees" ), + "mail_generic", 0, + mCalendarView, TQT_SLOT(schedule_request()), + mACollection, "schedule_request" ); + mSendInvitation->setEnabled( false ); + connect( mCalendarView, TQT_SIGNAL(organizerEventsSelected(bool)), + mSendInvitation, TQT_SLOT(setEnabled(bool)) ); + + mRequestUpdate = new KAction( i18n( "Re&quest Update" ), 0, + mCalendarView, TQT_SLOT(schedule_refresh()), + mACollection, "schedule_refresh" ); + mRequestUpdate->setEnabled( false ); + connect( mCalendarView, TQT_SIGNAL(groupEventsSelected(bool)), + mRequestUpdate, TQT_SLOT(setEnabled(bool)) ); + + mSendCancel = new KAction( i18n( "Send &Cancelation to Attendees" ), 0, + mCalendarView, TQT_SLOT(schedule_cancel()), + mACollection, "schedule_cancel" ); + mSendCancel->setEnabled( false ); + connect( mCalendarView, TQT_SIGNAL(organizerEventsSelected(bool)), + mSendCancel, TQT_SLOT(setEnabled(bool)) ); + + mSendStatusUpdate = new KAction( i18n( "Send Status &Update" ), + "mail_reply", 0, + mCalendarView,TQT_SLOT(schedule_reply()), + mACollection, "schedule_reply" ); + mSendStatusUpdate->setEnabled( false ); + connect( mCalendarView, TQT_SIGNAL(groupEventsSelected(bool)), + mSendStatusUpdate, TQT_SLOT(setEnabled(bool)) ); + + mRequestChange = new KAction( i18n( "counter proposal", "Request Chan&ge" ), 0, + mCalendarView, TQT_SLOT(schedule_counter()), + mACollection, "schedule_counter" ); + mRequestChange->setEnabled( false ); + connect( mCalendarView, TQT_SIGNAL(groupEventsSelected(bool)), + mRequestChange, TQT_SLOT(setEnabled(bool)) ); mForwardEvent = new KAction( i18n("&Send as iCalendar..."), "mail_forward", 0, mCalendarView, TQT_SLOT(schedule_forward()), @@ -719,7 +723,7 @@ void ActionManager::file_open( const KURL &url ) // is that URL already opened somewhere else? Activate that window KOrg::MainWindow *korg=ActionManager::findInstance( url ); if ( ( 0 != korg )&&( korg != mMainWindow ) ) { - KWin::setActiveWindow( korg->topLevelWidget()->winId() ); + KWin::activateWindow( korg->topLevelWidget()->winId() ); return; } @@ -745,7 +749,7 @@ void ActionManager::file_icalimport() if ( !TQFile::exists( homeDir ) ) { KMessageBox::error( dialogParent(), - i18n( "You have no ical file in your home directory.\n" + i18n( "You have no .calendar file in your home directory.\n" "Import cannot proceed.\n" ) ); return; } @@ -1055,6 +1059,11 @@ void ActionManager::exportHTML( HTMLExportSettings *settings ) { if ( !settings || settings->outputFile().isEmpty() ) return; + kdDebug()<<" settings->outputFile() :"<<settings->outputFile()<<endl; + if ( TQFileInfo( settings->outputFile() ).exists() ) { + if(KMessageBox::questionYesNo( dialogParent(), i18n("Do you want to overwrite file \"%1\"").arg( settings->outputFile()) ) == KMessageBox::No) + return; + } settings->setEMail( KOPrefs::instance()->email() ); settings->setName( KOPrefs::instance()->fullName() ); @@ -1376,11 +1385,16 @@ TQString ActionManager::getCurrentURLasString() const return mURL.url(); } -bool ActionManager::editIncidence( const TQString& uid ) +bool ActionManager::editIncidence( const TQString &uid ) { return mCalendarView->editIncidence( uid ); } +bool ActionManager::editIncidence( const TQString &uid, const TQDate &date ) +{ + return mCalendarView->editIncidence( uid, date ); +} + bool ActionManager::deleteIncidence( const TQString& uid, bool force ) { return mCalendarView->deleteIncidence( uid, force ); @@ -1454,7 +1468,7 @@ class ActionManager::ActionStringsVisitor : public IncidenceBase::Visitor KAction *mDelete; }; -void ActionManager::processIncidenceSelection( Incidence *incidence ) +void ActionManager::processIncidenceSelection( Incidence *incidence, const TQDate & ) { // kdDebug(5850) << "ActionManager::processIncidenceSelection()" << endl; @@ -1490,6 +1504,11 @@ void ActionManager::enableIncidenceActions( bool enabled ) mDeleteAction->setEnabled( enabled ); mPublishEvent->setEnabled( enabled ); mForwardEvent->setEnabled( enabled ); + mSendInvitation->setEnabled( enabled ); + mSendCancel->setEnabled( enabled ); + mSendStatusUpdate->setEnabled( enabled ); + mRequestChange->setEnabled( enabled ); + mRequestUpdate->setEnabled( enabled ); } void ActionManager::keyBindings() @@ -1525,16 +1544,108 @@ KCalendarIface::ResourceRequestReply ActionManager::resourceRequest( const TQVal return reply; } +QPair<ResourceCalendar *, TQString> ActionManager::viewSubResourceCalendar() +{ + QPair<ResourceCalendar *, TQString> p( 0, TQString() ); + + // return now if we are running as a part and we aren't the currently active part + if ( mIsPart && !mMainWindow->isCurrentlyActivePart() ) { + return p; + } + + KOrg::BaseView *cV = mCalendarView->viewManager()->currentView(); + if ( cV && cV == mCalendarView->viewManager()->multiAgendaView() ) { + cV = mCalendarView->viewManager()->multiAgendaView()->selectedAgendaView(); + } + if ( cV ) { + p = qMakePair( cV->resourceCalendar(), cV->subResourceCalendar() ); + } + return p; +} + +bool ActionManager::isWritable( ResourceCalendar *res, const TQString &subRes, + const TQString &contentsType ) +{ + + if ( res && res->isActive() ) { + // Check specified resource for writability. + if ( res->readOnly() || !res->subresourceWritable( subRes ) ) { + TQString resName = res->resourceName(); + if ( res->canHaveSubresources() ) { + resName = res->labelForSubresource( subRes ); + } + KMessageBox::sorry( + dialogParent(), + i18n( "\"%1\" is read-only. " + "Please select a writable calendar before attempting to create a new item." ). + arg( resName ), + i18n( "Read-only calendar" ) ); + return false; + } else { + return true; + } + } else { + // No specific resource so let's check all possible calendars for writability. + CalendarResourceManager *m = mCalendarResources->resourceManager(); + CalendarResourceManager::ActiveIterator it; + for ( it = m->activeBegin(); it != m->activeEnd(); ++it ) { + ResourceCalendar *res = (*it); + if ( res->canHaveSubresources() ) { + TQStringList subResources = res->subresources(); + for ( TQStringList::ConstIterator subit = subResources.constBegin(); + subit != subResources.constEnd(); ++subit ) { + if ( res->subresourceWritable( (*subit) ) && res->subresourceActive( (*subit) ) ) { + if ( res->subresourceType( *subit ).isEmpty() || + res->subresourceType( *subit ) == contentsType ) { + return true; + } + } + } + } else if ( !res->readOnly() ) { + return true; + } + } + // we don't have any writable calendars + TQString errorText; + if ( contentsType == "event" ) { + errorText = + i18n( "You have no active, writable event folder so saving will not be possible.\n" + "Please create or activate at least one writable event folder and try again." ); + } else if ( contentsType == "todo" ) { + errorText = + i18n( "You have no active, writable to-do (task) folders so saving will not be possible.\n" + "Please create or activate at least one writable to-do folder and try again." ); + } else if ( contentsType == "journal" ) { + errorText = + i18n( "You have no active, writable journal folder so saving will not be possible.\n" + "Please create or activate at least one writable journal folder and try again." ); + } else { + errorText = + i18n( "You have no active, writable calendar folder so saving will not be possible.\n" + "Please create or activate at least one writable calendar folder and try again." ); + } + KMessageBox::sorry( + dialogParent(), + errorText, + i18n( "No writable calendar" ) ); + return false; + } +} + void ActionManager::openEventEditor( const TQString& text ) { - mCalendarView->newEvent( text ); + QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); + if ( isWritable( p.first, p.second, "event" ) ) { + mCalendarView->newEvent( p.first, p.second, text ); + } } void ActionManager::openEventEditor( const TQString& summary, const TQString& description, const TQString& attachment ) { - mCalendarView->newEvent( summary, description, attachment ); + QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); + mCalendarView->newEvent( p.first, p.second, summary, description, attachment ); } void ActionManager::openEventEditor( const TQString& summary, @@ -1542,7 +1653,7 @@ void ActionManager::openEventEditor( const TQString& summary, const TQString& attachment, const TQStringList& attendees ) { - mCalendarView->newEvent( summary, description, attachment, attendees ); + mCalendarView->newEvent( 0, TQString(), summary, description, attachment, attendees ); } void ActionManager::openEventEditor( const TQString & summary, @@ -1637,19 +1748,25 @@ void ActionManager::openEventEditor( const TQString & summary, return; } - mCalendarView->newEvent( summary, description, attData, attendees, attachmentMimetype, action != KOPrefs::Link ); + QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); + mCalendarView->newEvent( p.first, p.second, summary, description, attData, + attendees, attachmentMimetype, action != KOPrefs::Link ); } void ActionManager::openTodoEditor( const TQString& text ) { - mCalendarView->newTodo( text ); + QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); + if ( isWritable( p.first, p.second, "todo" ) ) { + mCalendarView->newTodo( p.first, p.second, text ); + } } void ActionManager::openTodoEditor( const TQString& summary, const TQString& description, const TQString& attachment ) { - mCalendarView->newTodo( summary, description, attachment ); + QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); + mCalendarView->newTodo( p.first, p.second, summary, description, attachment ); } void ActionManager::openTodoEditor( const TQString& summary, @@ -1657,7 +1774,8 @@ void ActionManager::openTodoEditor( const TQString& summary, const TQString& attachment, const TQStringList& attendees ) { - mCalendarView->newTodo( summary, description, attachment, attendees ); + QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); + mCalendarView->newTodo( p.first, p.second, summary, description, attachment, attendees ); } void ActionManager::openTodoEditor(const TQString & summary, @@ -1665,7 +1783,8 @@ void ActionManager::openTodoEditor(const TQString & summary, const TQString & uri, const TQString & file, const TQStringList & attendees, - const TQString & attachmentMimetype) + const TQString & attachmentMimetype, + bool isTask ) { int action = KOPrefs::instance()->defaultTodoAttachMethod(); if ( attachmentMimetype != "message/rfc822" ) { @@ -1680,37 +1799,48 @@ void ActionManager::openTodoEditor(const TQString & summary, delete menu; } - TQString attData; + TQStringList attData; switch ( action ) { case KOPrefs::TodoAttachAsk: return; case KOPrefs::TodoAttachLink: - attData = uri; + attData << uri; break; - case KOPrefs::TodoAttachInlineFull: - attData = file; + case KOPrefs::TodoAttachInlineFull: + attData << file; break; default: // menu could have been closed by cancel, if so, do nothing return; } - mCalendarView->newTodo( summary, description, attData, attendees, attachmentMimetype, action != KOPrefs::Link ); + QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); + mCalendarView->newTodo( p.first, p.second, + summary, description, + attData, attendees, + TQStringList( attachmentMimetype ), + action != KOPrefs::TodoAttachLink, + isTask ); } void ActionManager::openJournalEditor( const TQDate& date ) { - mCalendarView->newJournal( date ); + QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); + mCalendarView->newJournal( p.first, p.second, date ); } void ActionManager::openJournalEditor( const TQString& text, const TQDate& date ) { - mCalendarView->newJournal( text, date ); + QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); + mCalendarView->newJournal( p.first, p.second, text, date ); } void ActionManager::openJournalEditor( const TQString& text ) { - mCalendarView->newJournal( text ); + QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); + if ( isWritable( p.first, p.second, "journal" ) ) { + mCalendarView->newJournal( p.first, p.second, text ); + } } //TODO: @@ -1718,7 +1848,8 @@ void ActionManager::openJournalEditor( const TQString& text ) // const TQString& description, // const TQString& attachment ) // { -// mCalendarView->newJournal( summary, description, attachment ); +// QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); +// mCalendarView->newJournal( p.first, p.second, summary, description, attachment ); // } @@ -1879,21 +2010,23 @@ void ActionManager::importCalendar( const KURL &url ) return; } - ImportDialog *dialog; - dialog = new ImportDialog( url, mMainWindow->topLevelWidget() ); - connect( dialog, TQT_SIGNAL( dialogFinished( ImportDialog * ) ), - TQT_SLOT( slotImportDialogFinished( ImportDialog * ) ) ); + PreviewDialog *dialog; + dialog = new PreviewDialog( url, mMainWindow->topLevelWidget() ); + connect( dialog, TQT_SIGNAL( dialogFinished( PreviewDialog * ) ), + TQT_SLOT( slotPreviewDialogFinished( PreviewDialog * ) ) ); connect( dialog, TQT_SIGNAL( openURL( const KURL &, bool ) ), TQT_SLOT( openURL( const KURL &, bool ) ) ); - connect( dialog, TQT_SIGNAL( newWindow( const KURL & ) ), - TQT_SIGNAL( actionNew( const KURL & ) ) ); connect( dialog, TQT_SIGNAL( addResource( const KURL & ) ), TQT_SLOT( addResource( const KURL & ) ) ); - dialog->show(); + if ( dialog->loadCalendar() ) { + dialog->show(); + } else { + KMessageBox::error( dialogParent(), i18n("Unable to open the calendar") ); + } } -void ActionManager::slotImportDialogFinished( ImportDialog *dlg ) +void ActionManager::slotPreviewDialogFinished( PreviewDialog *dlg ) { dlg->deleteLater(); mCalendarView->updateView(); @@ -1959,6 +2092,42 @@ void ActionManager::saveToProfile( const TQString & path ) const ::copyConfigEntry( cfg, &profile, "Views", "Agenda View Calendar Display" ); } +bool ActionManager::handleCommandLine() +{ + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + KOrg::MainWindow *mainWindow = ActionManager::findInstance( KURL() ); + + bool ret = true; + + if ( !mainWindow ) { + kdError() << "Unable to find default calendar resources view." << endl; + ret = false; + } else if ( args->count() <= 0 ) { + // No filenames given => all other args are meaningless, show main Window + mainWindow->topLevelWidget()->show(); + } else if ( !args->isSet( "open" ) ) { + // Import, merge, or ask => we need the resource calendar window anyway. + mainWindow->topLevelWidget()->show(); + + // Check for import, merge or ask + if ( args->isSet( "import" ) ) { + for( int i = 0; i < args->count(); ++i ) { + mainWindow->actionManager()->addResource( args->url( i ) ); + } + } else if ( args->isSet( "merge" ) ) { + for( int i = 0; i < args->count(); ++i ) { + mainWindow->actionManager()->mergeURL( args->url( i ).url() ); + } + } else { + for( int i = 0; i < args->count(); ++i ) { + mainWindow->actionManager()->importCalendar( args->url( i ) ); + } + } + } + + return ret; +} + TQWidget *ActionManager::dialogParent() { return mCalendarView->topLevelWidget(); diff --git a/korganizer/actionmanager.h b/korganizer/actionmanager.h index 25fd6fabb..555d4e7db 100644 --- a/korganizer/actionmanager.h +++ b/korganizer/actionmanager.h @@ -41,8 +41,7 @@ namespace KCal class Incidence; class ResourceCalendar; } -namespace KOrg -{ +namespace KOrg { class MainWindow; } @@ -59,7 +58,7 @@ class CalendarView; class KOrganizer; class KONewStuff; class KOWindowList; -class ImportDialog; +class PreviewDialog; class ResourceView; class HTMLExportSettings; @@ -152,7 +151,8 @@ class KDE_EXPORT ActionManager : public TQObject, public KCalendarIface */ virtual bool deleteIncidence( const TQString& uid, bool force = false ); - bool editIncidence( const TQString& uid ); + bool editIncidence( const TQString &uid ); + bool editIncidence( const TQString &uid, const TQDate &date ); /** Add an incidence to the active calendar. @@ -194,7 +194,8 @@ class KDE_EXPORT ActionManager : public TQObject, public KCalendarIface const TQString& uri, const TQString& file, const TQStringList& attendees, - const TQString& attachmentMimetype ); + const TQString& attachmentMimetype, + bool isTask ); void openJournalEditor( const TQDate& date ); void openJournalEditor( const TQString& text, const TQDate& date ); @@ -220,6 +221,8 @@ class KDE_EXPORT ActionManager : public TQObject, public KCalendarIface void saveToProfile( const TQString & path ) const; + bool handleCommandLine(); + signals: /** Emitted when the "New" action is activated. @@ -251,7 +254,7 @@ class KDE_EXPORT ActionManager : public TQObject, public KCalendarIface void setDestinationPolicy(); - void processIncidenceSelection( Incidence * ); + void processIncidenceSelection( Incidence *incidence, const TQDate &date ); void keyBindings(); /** @@ -342,7 +345,7 @@ class KDE_EXPORT ActionManager : public TQObject, public KCalendarIface void updateRedoAction( const TQString & ); - void slotImportDialogFinished( ImportDialog * ); + void slotPreviewDialogFinished( PreviewDialog * ); protected: /** Get URL for saving. Opens FileDialog. */ @@ -367,6 +370,9 @@ class KDE_EXPORT ActionManager : public TQObject, public KCalendarIface void initActions(); void enableIncidenceActions( bool enable ); + QPair<ResourceCalendar *, TQString> viewSubResourceCalendar(); + bool isWritable( ResourceCalendar *res, const TQString &subRes, const TQString &contentsType ); + KOrg::Part::List mParts; // List of parts loaded KURL mURL; // URL of calendar file TQString mFile; // Local name of calendar file @@ -401,6 +407,13 @@ class KDE_EXPORT ActionManager : public TQObject, public KCalendarIface KAction *mPublishEvent; KAction *mForwardEvent; + KAction *mSendInvitation; + KAction *mSendCancel; + KAction *mSendStatusUpdate; + + KAction *mRequestChange; + KAction *mRequestUpdate; + KAction *mUndoAction; KAction *mRedoAction; diff --git a/korganizer/archivedialog.cpp b/korganizer/archivedialog.cpp index 88d20fded..48c299e0a 100644 --- a/korganizer/archivedialog.cpp +++ b/korganizer/archivedialog.cpp @@ -130,11 +130,11 @@ ArchiveDialog::ArchiveDialog(Calendar *cal,TQWidget *parent, const char *name) l->setBuddy(mArchiveFile->lineEdit()); fileLayout->addWidget(mArchiveFile); topLayout->addLayout(fileLayout); - - TQHGroupBox *typeBox = new TQHGroupBox( i18n("Type of Items to Archive"), + + TQHGroupBox *typeBox = new TQHGroupBox( i18n("Type of Items to Archive"), topFrame); mEvents = new TQCheckBox( i18n("&Events"), typeBox ); - mTodos = new TQCheckBox( i18n("&To-dos"), typeBox ); + mTodos = new TQCheckBox( i18n("Completed &To-dos"), typeBox ); topLayout->addWidget( typeBox ); TQWhatsThis::add( typeBox, i18n("Here you can select which items " "should be archived. Events are archived if they " diff --git a/korganizer/calendarview.cpp b/korganizer/calendarview.cpp index eb294fe74..ba1bbe6e3 100644 --- a/korganizer/calendarview.cpp +++ b/korganizer/calendarview.cpp @@ -65,6 +65,7 @@ #include "komailclient.h" #include "multiagendaview.h" +#include <libkcal/calhelper.h> #include <libkcal/vcaldrag.h> #include <libkcal/icaldrag.h> #include <libkcal/icalformat.h> @@ -130,7 +131,7 @@ CalendarView::CalendarView( TQWidget *parent, const char *name ) mExtensions.setAutoDelete( true ); - mNavigator = new DateNavigator( this ); + mDateNavigator = new DateNavigator( this ); mDateChecker = new DateChecker( this ); TQBoxLayout *topLayout = new TQVBoxLayout( this ); @@ -145,14 +146,14 @@ CalendarView::CalendarView( TQWidget *parent, const char *name ) "CalendarView::LeftFrame" ); // mPanner->setResizeMode( mLeftSplitter, TQSplitter::Stretch ); - mDateNavigator = new DateNavigatorContainer( mLeftSplitter, + mDateNavigatorContainer = new DateNavigatorContainer( mLeftSplitter, "CalendarView::DateNavigator" ); -// mLeftSplitter->setResizeMode( mDateNavigator, TQSplitter::Stretch ); - mLeftSplitter->setCollapsible( mDateNavigator, true ); +// mLeftSplitter->setResizeMode( mDateNavigatorContainer, TQSplitter::Stretch ); + mLeftSplitter->setCollapsible( mDateNavigatorContainer, true ); mTodoList = new KOTodoView( CalendarNull::self(), mLeftSplitter, "todolist" ); - mEventViewer = new KOEventViewer( mLeftSplitter,"EventViewer" ); + mEventViewer = new KOEventViewer( CalendarNull::self(), mLeftSplitter,"EventViewer" ); TQVBox *rightBox = new TQVBox( mPanner ); mNavigatorBar = new NavigatorBar( rightBox ); @@ -174,12 +175,12 @@ CalendarView::CalendarView( TQWidget *parent, const char *name ) topLayout->addWidget( mainBox ); - mDateNavigator = new KDateNavigator( leftFrame, true, + mDateNavigatorContainer = new KDateNavigator( leftFrame, true, "CalendarView::DateNavigator", TQDate::currentDate() ); mTodoList = new KOTodoView( CalendarNull::self(), leftFrame, "todolist" ); - mEventViewer = new KOEventViewer ( leftFrame, "EventViewer" ); + mEventViewer = new KOEventViewer ( CalendarNull::self(), leftFrame, "EventViewer" ); TQWidget *rightBox = new TQWidget( mainBox ); TQBoxLayout *rightLayout = new TQVBoxLayout( rightBox ); @@ -193,55 +194,56 @@ CalendarView::CalendarView( TQWidget *parent, const char *name ) mLeftFrame = leftFrame; if ( KOPrefs::instance()->mVerticalScreen ) { -// mTodoList->setFixedHeight( 60 ); - mTodoList->setFixedHeight( mDateNavigator->sizeHint().height() ); + // mTodoList->setFixedHeight( 60 ); + mTodoList->setFixedHeight( mDateNavigatorContainer->sizeHint().height() ); } #endif - connect( mNavigator, TQT_SIGNAL( datesSelected( const KCal::DateList & ) ), - TQT_SLOT( showDates( const KCal::DateList & ) ) ); - connect( mNavigator, TQT_SIGNAL( datesSelected( const KCal::DateList & ) ), + // Signals emited by mDateNavigator + connect( mDateNavigator, TQT_SIGNAL( datesSelected( const KCal::DateList &, const TQDate & ) ), + TQT_SLOT( showDates( const KCal::DateList &, const TQDate & ) ) ); + + // Signals emited by mNavigatorBar + connect( mNavigatorBar, TQT_SIGNAL( prevYearClicked() ), + mDateNavigator, TQT_SLOT( selectPreviousYear() ) ); + connect( mNavigatorBar, TQT_SIGNAL( nextYearClicked() ), + mDateNavigator, TQT_SLOT( selectNextYear() ) ); + connect( mNavigatorBar, TQT_SIGNAL( prevMonthClicked() ), + mDateNavigator, TQT_SLOT( selectPreviousMonth() ) ); + connect( mNavigatorBar, TQT_SIGNAL( nextMonthClicked() ), + mDateNavigator, TQT_SLOT( selectNextMonth() ) ); + connect( mNavigatorBar, TQT_SIGNAL( monthSelected(int) ), + mDateNavigator, TQT_SLOT( selectMonth(int) ) ); + connect( mNavigatorBar, TQT_SIGNAL( yearSelected(int)), + mDateNavigator, TQT_SLOT(selectYear(int)) ); + + + // Signals emited by mDateNavigatorContainer + connect( mDateNavigatorContainer, TQT_SIGNAL( weekClicked( const TQDate & ) ), + this, TQT_SLOT( selectWeek( const TQDate & ) ) ); + connect( mDateNavigatorContainer, TQT_SIGNAL( prevMonthClicked(const TQDate &, const TQDate &, const TQDate &) ), + mDateNavigator, TQT_SLOT( selectPreviousMonth(const TQDate &, const TQDate &, const TQDate &) ) ); + connect( mDateNavigatorContainer, TQT_SIGNAL( nextMonthClicked(const TQDate &, const TQDate &, const TQDate &) ), + mDateNavigator, TQT_SLOT( selectNextMonth(const TQDate &, const TQDate &, const TQDate &) ) ); + connect( mDateNavigatorContainer, TQT_SIGNAL( prevYearClicked() ), + mDateNavigator, TQT_SLOT( selectPreviousYear() ) ); + connect( mDateNavigatorContainer, TQT_SIGNAL( nextYearClicked() ), + mDateNavigator, TQT_SLOT( selectNextYear() ) ); + connect( mDateNavigatorContainer, TQT_SIGNAL( monthSelected(int) ), + mDateNavigator, TQT_SLOT( selectMonth(int) ) ); + connect( mDateNavigatorContainer, TQT_SIGNAL(yearSelected(int)), + mDateNavigator, TQT_SLOT(selectYear(int)) ); + connect( mDateNavigatorContainer, TQT_SIGNAL( goPrevious() ), + mDateNavigator, TQT_SLOT( selectPrevious() ) ); + connect( mDateNavigatorContainer, TQT_SIGNAL( goNext() ), + mDateNavigator, TQT_SLOT( selectNext() ) ); + + connect( mDateNavigatorContainer, TQT_SIGNAL( datesSelected( const KCal::DateList & ) ), mDateNavigator, TQT_SLOT( selectDates( const KCal::DateList & ) ) ); - connect( mNavigatorBar, TQT_SIGNAL( goPrevYear() ), - mNavigator, TQT_SLOT( selectPreviousYear() ) ); - connect( mNavigatorBar, TQT_SIGNAL( goNextYear() ), - mNavigator, TQT_SLOT( selectNextYear() ) ); - connect( mNavigatorBar, TQT_SIGNAL( goPrevMonth() ), - mNavigator, TQT_SLOT( selectPreviousMonth() ) ); - connect( mNavigatorBar, TQT_SIGNAL( goNextMonth() ), - mNavigator, TQT_SLOT( selectNextMonth() ) ); - connect( mNavigatorBar, TQT_SIGNAL( goMonth(int) ), - mNavigator, TQT_SLOT( selectMonth(int) ) ); - - connect( mNavigator, TQT_SIGNAL( datesSelected( const KCal::DateList & ) ), - mNavigatorBar, TQT_SLOT( selectDates( const KCal::DateList & ) ) ); - - connect( mDateNavigator, TQT_SIGNAL( weekClicked( const TQDate & ) ), - mNavigator, TQT_SLOT( selectWeek( const TQDate & ) ) ); - - connect( mDateNavigator, TQT_SIGNAL( goPrevYear() ), - mNavigator, TQT_SLOT( selectPreviousYear() ) ); - connect( mDateNavigator, TQT_SIGNAL( goNextYear() ), - mNavigator, TQT_SLOT( selectNextYear() ) ); - connect( mDateNavigator, TQT_SIGNAL( goPrevMonth() ), - mNavigator, TQT_SLOT( selectPreviousMonth() ) ); - connect( mDateNavigator, TQT_SIGNAL( goNextMonth() ), - mNavigator, TQT_SLOT( selectNextMonth() ) ); - connect( mDateNavigator, TQT_SIGNAL( goMonth(int) ), - mNavigator, TQT_SLOT( selectMonth(int) ) ); - - connect( mDateNavigator, TQT_SIGNAL( goPrevious() ), - mNavigator, TQT_SLOT( selectPrevious() ) ); - connect( mDateNavigator, TQT_SIGNAL( goNext() ), - mNavigator, TQT_SLOT( selectNext() ) ); - - connect( mDateNavigator, TQT_SIGNAL( datesSelected( const KCal::DateList & ) ), - mNavigator, TQT_SLOT( selectDates( const KCal::DateList & ) ) ); - - connect( mDateNavigator, TQT_SIGNAL(incidenceDropped(Incidence*, const TQDate&)), + connect( mDateNavigatorContainer, TQT_SIGNAL(incidenceDropped(Incidence*, const TQDate&)), TQT_SLOT( addIncidenceOn( Incidence *, const TQDate & ) ) ); - connect( mDateNavigator, TQT_SIGNAL(incidenceDroppedMove(Incidence*,const TQDate&)), + connect( mDateNavigatorContainer, TQT_SIGNAL(incidenceDroppedMove(Incidence*,const TQDate&)), TQT_SLOT( moveIncidenceTo( Incidence *, const TQDate & ) ) ); connect( mDateChecker, TQT_SIGNAL( dayPassed( const TQDate & ) ), @@ -249,13 +251,13 @@ CalendarView::CalendarView( TQWidget *parent, const char *name ) connect( mDateChecker, TQT_SIGNAL( dayPassed( const TQDate & ) ), TQT_SIGNAL( dayPassed( const TQDate & ) ) ); connect( mDateChecker, TQT_SIGNAL( dayPassed( const TQDate & ) ), - mDateNavigator, TQT_SLOT( updateToday() ) ); + mDateNavigatorContainer, TQT_SLOT( updateToday() ) ); connect( this, TQT_SIGNAL( configChanged() ), - mDateNavigator, TQT_SLOT( updateConfig() ) ); + mDateNavigatorContainer, TQT_SLOT( updateConfig() ) ); - connect( this, TQT_SIGNAL( incidenceSelected(Incidence *) ), - mEventViewer, TQT_SLOT ( setIncidence (Incidence *) ) ); + connect( this, TQT_SIGNAL( incidenceSelected(Incidence *, const TQDate &) ), + mEventViewer, TQT_SLOT ( setIncidence (Incidence *, const TQDate &) ) ); //TODO: do a pretty Summary, TQString s; @@ -267,7 +269,7 @@ CalendarView::CalendarView( TQWidget *parent, const char *name ) TQWhatsThis::add( mEventViewer, i18n( "View the details of events, journal entries or to-dos " "selected in KOrganizer's main view here." ) ); - mEventViewer->setIncidence( 0 ); + mEventViewer->setIncidence( 0, TQDate() ); mViewManager->connectTodoView( mTodoList ); mViewManager->connectView( mTodoList ); @@ -278,10 +280,10 @@ CalendarView::CalendarView( TQWidget *parent, const char *name ) connect( TQApplication::clipboard(), TQT_SIGNAL( dataChanged() ), TQT_SLOT( checkClipboard() ) ); - connect( mTodoList, TQT_SIGNAL( incidenceSelected( Incidence * ) ), - TQT_SLOT( processTodoListSelection( Incidence * ) ) ); - disconnect( mTodoList, TQT_SIGNAL( incidenceSelected( Incidence * ) ), - this, TQT_SLOT( processMainViewSelection( Incidence * ) ) ); + connect( mTodoList, TQT_SIGNAL( incidenceSelected( Incidence *,const TQDate & ) ), + TQT_SLOT( processTodoListSelection( Incidence *,const TQDate & ) ) ); + disconnect( mTodoList, TQT_SIGNAL( incidenceSelected( Incidence *,const TQDate & ) ), + this, TQT_SLOT( processMainViewSelection( Incidence *,const TQDate & ) ) ); kdDebug(5850) << "CalendarView::CalendarView() done" << endl; } @@ -313,9 +315,11 @@ void CalendarView::setCalendar( Calendar *cal ) mCalendar->registerObserver( this ); - mDateNavigator->setCalendar( mCalendar ); + mDateNavigatorContainer->setCalendar( mCalendar ); mTodoList->setCalendar( mCalendar ); + + mEventViewer->setCalendar( mCalendar ); } void CalendarView::setIncidenceChanger( IncidenceChangerBase *changer ) @@ -324,10 +328,8 @@ void CalendarView::setIncidenceChanger( IncidenceChangerBase *changer ) emit newIncidenceChanger( mChanger ); connect( mChanger, TQT_SIGNAL( incidenceAdded( Incidence* ) ), this, TQT_SLOT( incidenceAdded( Incidence* ) ) ); - connect( mChanger, TQT_SIGNAL( incidenceChanged( Incidence*, Incidence*, int ) ), - this, TQT_SLOT( incidenceChanged( Incidence*, Incidence*, int ) ) ); - connect( mChanger, TQT_SIGNAL( incidenceChanged( Incidence*, Incidence* ) ), - this, TQT_SLOT( incidenceChanged( Incidence*, Incidence* ) ) ); + connect( mChanger, TQT_SIGNAL( incidenceChanged( Incidence*, Incidence*, KOGlobals::WhatChanged ) ), + this, TQT_SLOT( incidenceChanged( Incidence*, Incidence*, KOGlobals::WhatChanged ) ) ); connect( mChanger, TQT_SIGNAL( incidenceToBeDeleted( Incidence * ) ), this, TQT_SLOT( incidenceToBeDeleted( Incidence * ) ) ); connect( mChanger, TQT_SIGNAL( incidenceDeleted( Incidence * ) ), @@ -347,6 +349,19 @@ Calendar *CalendarView::calendar() else return CalendarNull::self(); } +QPair<ResourceCalendar *, TQString> CalendarView::viewSubResourceCalendar() +{ + QPair<ResourceCalendar *, TQString> p( 0, TQString() ); + KOrg::BaseView *cV = mViewManager->currentView(); + if ( cV && cV == mViewManager->multiAgendaView() ) { + cV = mViewManager->multiAgendaView()->selectedAgendaView(); + } + if ( cV ) { + p = qMakePair( cV->resourceCalendar(), cV->subResourceCalendar() ); + } + return p; +} + KOIncidenceEditor *CalendarView::editorDialog( Incidence *incidence ) const { if (mDialogList.find(incidence) != mDialogList.end ()) @@ -354,16 +369,53 @@ KOIncidenceEditor *CalendarView::editorDialog( Incidence *incidence ) const else return 0; } +TQDate CalendarView::activeDate( bool fallbackToToday ) +{ + KOrg::BaseView *curView = mViewManager->currentView(); + if ( curView ) { + if ( curView->selectionStart().isValid() ) { + return curView->selectionStart().date(); + } + + // Try the view's selectedDates() + if ( !curView->selectedIncidenceDates().isEmpty() ) { + if ( curView->selectedIncidenceDates().first().isValid() ) { + return curView->selectedIncidenceDates().first(); + } + } + } + + // When all else fails, use the navigator start date, or today. + if ( fallbackToToday ) { + return TQDate::currentDate(); + } else { + return mDateNavigator->selectedDates().first(); + } +} + +TQDate CalendarView::activeIncidenceDate() +{ + KOrg::BaseView *curView = mViewManager->currentView(); + if ( curView ) { + DateList dates = curView->selectedIncidenceDates(); + if ( !dates.isEmpty() ) { + return dates.first(); + } + } + + return TQDate(); +} + TQDate CalendarView::startDate() { - DateList dates = mNavigator->selectedDates(); + DateList dates = mDateNavigator->selectedDates(); return dates.first(); } TQDate CalendarView::endDate() { - DateList dates = mNavigator->selectedDates(); + DateList dates = mDateNavigator->selectedDates(); return dates.last(); } @@ -397,6 +449,23 @@ bool CalendarView::openCalendar(const TQString& filename, bool merge) } } else { // merge in a file + CalendarResources *cl = dynamic_cast<CalendarResources *>( mCalendar ); + if ( cl && !cl->hasCalendarResources() ) { + KMessageBox::sorry( + this, + i18n( "No calendars found, unable to merge the file into your calendar." ) ); + return false; + } + // FIXME: This is a nasty hack, since we need to set a parent for the + // resource selection dialog. However, we don't have any UI methods + // in the calendar, only in the CalendarResources::DestinationPolicy + // So we need to type-cast it and extract it from the CalendarResources + TQWidget *tmpparent = 0; + if ( cl ) { + tmpparent = cl->dialogParentWidget(); + cl->setDialogParentWidget( this ); + } + FileStorage storage( mCalendar ); storage.setFileName( filename ); loadedSuccesfully = storage.load(); @@ -478,7 +547,7 @@ void CalendarView::readSettings() TQValueList<int> sizes = config->readIntListEntry( "Separator1" ); if ( sizes.count() != 2 ) { - sizes << mDateNavigator->minimumSizeHint().width(); + sizes << mDateNavigatorContainer->minimumSizeHint().width(); sizes << 300; } mPanner->setSizes( sizes ); @@ -495,9 +564,12 @@ void CalendarView::readSettings() readFilterSettings( config ); config->setGroup( "Views" ); - int dateCount = config->readNumEntry( "ShownDatesCount", 7 ); - if ( dateCount == 7 ) mNavigator->selectWeek(); - else mNavigator->selectDates( mNavigator->selectedDates().first(), dateCount ); + const int dateCount = config->readNumEntry( "ShownDatesCount", 7 ); + if ( dateCount == 7 ) { + mDateNavigator->selectWeek(); + } else { + mDateNavigator->selectDates( mDateNavigator->selectedDates().first(), dateCount ); + } } @@ -525,7 +597,7 @@ void CalendarView::writeSettings() writeFilterSettings( config ); config->setGroup( "Views" ); - config->writeEntry( "ShownDatesCount", mNavigator->selectedDates().count() ); + config->writeEntry( "ShownDatesCount", mDateNavigator->selectedDates().count() ); config->sync(); } @@ -593,39 +665,42 @@ void CalendarView::writeFilterSettings( KConfig *config ) } -void CalendarView::goDate( const TQDate& date ) +void CalendarView::goDate( const TQDate &date ) { - mNavigator->selectDate( date ); + mDateNavigator->selectDate( date ); } -void CalendarView::showDate(const TQDate & date) +void CalendarView::showDate( const TQDate &date ) { - int dateCount = mNavigator->datesCount(); - if ( dateCount == 7 ) - mNavigator->selectWeek( date ); - else - mNavigator->selectDates( date, dateCount ); + int dateCount = mDateNavigator->datesCount(); + if ( dateCount == 7 ) { + mDateNavigator->selectWeek( date ); + } else { + mDateNavigator->selectDates( date, dateCount ); + } } void CalendarView::goToday() { - mNavigator->selectToday(); + mDateNavigator->selectToday(); } void CalendarView::goNext() { - if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) ) - mNavigator->selectNextMonth(); - else - mNavigator->selectNext(); + if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) ) { + mDateNavigator->selectNextMonth(); + } else { + mDateNavigator->selectNext(); + } } void CalendarView::goPrevious() { - if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) ) - mNavigator->selectPreviousMonth(); - else - mNavigator->selectPrevious(); + if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) ) { + mDateNavigator->selectPreviousMonth(); + } else { + mDateNavigator->selectPrevious(); + } } void CalendarView::updateConfig( const TQCString& receiver) @@ -660,16 +735,8 @@ void CalendarView::updateConfig( const TQCString& receiver) } emit configChanged(); - // force reload and handle agenda view type switch - const bool showMerged = KOPrefs::instance()->agendaViewCalendarDisplay() == KOPrefs::CalendarsMerged; - const bool showSideBySide = KOPrefs::instance()->agendaViewCalendarDisplay() == KOPrefs::CalendarsSideBySide; - KOrg::BaseView *view = mViewManager->currentView(); - mViewManager->showAgendaView(); - if ( view == mViewManager->agendaView() && showSideBySide ) - view = mViewManager->multiAgendaView(); - else if ( view == mViewManager->multiAgendaView() && showMerged ) - view = mViewManager->agendaView(); - mViewManager->showView( view ); + //switch beetween merged, side by side and tabbed agenda if needed + mViewManager->updateMultiCalendarDisplay(); // To make the "fill window" configurations work mViewManager->raiseCurrentView(); @@ -686,19 +753,13 @@ void CalendarView::incidenceAdded( Incidence *incidence ) } void CalendarView::incidenceChanged( Incidence *oldIncidence, - Incidence *newIncidence ) -{ - incidenceChanged( oldIncidence, newIncidence, KOGlobals::UNKNOWN_MODIFIED ); -} - -void CalendarView::incidenceChanged( Incidence *oldIncidence, - Incidence *newIncidence, int what ) + Incidence *newIncidence, + KOGlobals::WhatChanged modification ) { - // FIXME: Make use of the what flag, which indicates which parts of the incidence have changed! KOIncidenceEditor *tmp = editorDialog( newIncidence ); if ( tmp ) { kdDebug(5850) << "Incidence modified and open" << endl; - tmp->modified( what ); + tmp->modified(); } setModified( true ); history()->recordEdit( oldIncidence, newIncidence ); @@ -706,14 +767,14 @@ void CalendarView::incidenceChanged( Incidence *oldIncidence, // Record completed todos in journals, if enabled. we should to this here in // favour of the todolist. users can mark a task as completed in an editor // as well. - if ( newIncidence->type() == "Todo" - && KOPrefs::instance()->recordTodosInJournals() - && ( what == KOGlobals::COMPLETION_MODIFIED - || what == KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ) ) { + if ( newIncidence->type() == "Todo" && + KOPrefs::instance()->recordTodosInJournals() && + ( modification == KOGlobals::COMPLETION_MODIFIED || + modification == KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ) ) { Todo *todo = static_cast<Todo *>(newIncidence); - if ( todo->isCompleted() - || what == KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ) { + if ( todo->isCompleted() || + modification == KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ) { TQString timeStr = KGlobal::locale()->formatTime( TQTime::currentTime() ); TQString description = i18n( "To-do completed: %1 (%2)" ).arg( newIncidence->summary() ).arg( timeStr ); @@ -729,7 +790,8 @@ void CalendarView::incidenceChanged( Incidence *oldIncidence, journal->setSummary( i18n("Journal of %1").arg( dateStr ) ); journal->setDescription( description ); - if ( !mChanger->addIncidence( journal, this ) ) { + //TODO: recorded to-dos should save into the standard resource always + if ( !mChanger->addIncidence( journal, 0, TQString(), this ) ) { KODialogManager::errorSaveIncidence( this, journal ); delete journal; return; @@ -740,7 +802,8 @@ void CalendarView::incidenceChanged( Incidence *oldIncidence, Journal *oldJournal = journal->clone(); journal->setDescription( journal->description().append( "\n" + description ) ); - if ( !mChanger->changeIncidence( oldJournal, journal ) ) { + if ( !mChanger->changeIncidence( oldJournal, journal, + KOGlobals::DESCRIPTION_MODIFIED, this ) ) { KODialogManager::errorSaveIncidence( this, journal ); delete journal; return; @@ -799,14 +862,14 @@ void CalendarView::endMultiModify() void CalendarView::changeIncidenceDisplay( Incidence *incidence, int action ) { - mDateNavigator->updateView(); + mDateNavigatorContainer->updateView(); mDialogManager->updateSearchDialog(); if ( incidence ) { // If there is an event view visible update the display mViewManager->currentView()->changeIncidenceDisplay( incidence, action ); if ( mTodoList ) mTodoList->changeIncidenceDisplay( incidence, action ); - mEventViewer->changeIncidenceDisplay( incidence, action ); + mEventViewer->changeIncidenceDisplay( incidence, activeDate( true ), action ); } else { mViewManager->currentView()->updateView(); if ( mTodoList ) mTodoList->updateView(); @@ -818,12 +881,12 @@ void CalendarView::updateView(const TQDate &start, const TQDate &end) { mTodoList->updateView(); mViewManager->updateView(start, end); - mDateNavigator->updateView(); + mDateNavigatorContainer->updateView(); } void CalendarView::updateView() { - DateList tmpList = mNavigator->selectedDates(); + DateList tmpList = mDateNavigator->selectedDates(); // We assume that the navigator only selects consecutive days. updateView( tmpList.first(), tmpList.last() ); @@ -831,7 +894,7 @@ void CalendarView::updateView() void CalendarView::updateUnmanagedViews() { - mDateNavigator->updateDayMatrix(); + mDateNavigatorContainer->updateDayMatrix(); updateView(); } @@ -845,83 +908,205 @@ int CalendarView::msgItemDelete( Incidence *incidence ) void CalendarView::edit_cut() { - Incidence *incidence = selectedIncidence(); + Incidence *incidence = incToSendToClipboard( true ); if ( !incidence || !mChanger ) { KNotifyClient::beep(); return; } - mChanger->cutIncidence( incidence ); + + Incidence::List incidences; + int km = KMessageBox::Yes; + + if ( !incidence->relations().isEmpty() && + incidence->type() == "Todo" ) { // Only todos (yet?) + km = KMessageBox::questionYesNoCancel( this, + i18n("The item \"%1\" has sub-to-dos. " + "Do you want to cut just this item and " + "make all its sub-to-dos independent, or " + "cut the to-do with all its sub-to-dos?" + ).arg( incidence->summary() ), + i18n("KOrganizer Confirmation"), + i18n("Cut Only This"), + i18n("Cut All")); + } + + if ( km == KMessageBox::Yes ) { // only one + incidences.append( incidence ); + makeChildrenIndependent( incidence ); + } else if ( km == KMessageBox::No ) { // all + // load incidence + children + grandchildren... + getIncidenceHierarchy( incidence, incidences ); + } + + if ( km != KMessageBox::Cancel ) { + mChanger->cutIncidences( incidences, this ); + } } void CalendarView::edit_copy() { - Incidence *incidence = selectedIncidence(); + Incidence *incidence = incToSendToClipboard( false ); - if (!incidence) { + if ( !incidence ) { KNotifyClient::beep(); return; } - DndFactory factory( mCalendar ); - if ( !factory.copyIncidence( incidence ) ) { - KNotifyClient::beep(); + + Incidence::List incidences; + int km = KMessageBox::Yes; + + if ( !incidence->relations().isEmpty() && + incidence->type() == "Todo" ) { // only todos. + km = KMessageBox::questionYesNoCancel( this, + i18n("The item \"%1\" has sub-to-dos. " + "Do you want to copy just this item or " + "copy the to-do with all its sub-to-dos?" + ).arg( incidence->summary() ), + i18n("KOrganizer Confirmation"), + i18n("Copy Only This"), + i18n("Copy All")); + } + + if ( km == KMessageBox::Yes ) { // only one + incidences.append( incidence ); + } else if ( km == KMessageBox::No ) { // all + // load incidence + children + grandchildren... + getIncidenceHierarchy( incidence, incidences ); + } + + if ( km != KMessageBox::Cancel ) { + DndFactory factory( mCalendar ); + if ( !factory.copyIncidences( incidences ) ) { + KNotifyClient::beep(); + } + } +} + +Incidence* CalendarView::incToSendToClipboard( bool cut ) +{ + Incidence *originalInc = selectedIncidence(); + + if ( originalInc && originalInc->doesRecur() && + originalInc->type() == "Event" ) { // temporary, until recurring to-dos are fixed + + Incidence *inc; + KOGlobals::WhichOccurrences chosenOption; + if ( cut ) { + inc = singleOccurrenceOrAll( originalInc, KOGlobals::CUT, chosenOption, TQDate(), true ); + } else { + // The user is copying, the original incidence can't be changed + // we can only dissociate a copy + Incidence *originalIncSaved = originalInc->clone(); + inc = singleOccurrenceOrAll( originalIncSaved, KOGlobals::COPY, chosenOption, TQDate(), false ); + + // no dissociation, no need to leak our clone + if ( chosenOption == KOGlobals::ALL ) { + inc = originalInc; + delete originalIncSaved; + } + + // no need to leak our clone + if ( chosenOption == KOGlobals::NONE ) { + delete originalIncSaved; + } + } + + return inc; + } else { + return originalInc; } } void CalendarView::edit_paste() { -// If in agenda view, use the selected time and date from there. -// In all other cases, paste the event on the first day of the -// selection in the day matrix on the left +// If in agenda and month view, use the selected time and date from there. +// In all other cases, use the navigator's selected date. - TQDate date; - // create an invalid time to check if we got a new time for the eevent - TQTime time(-1,-1); - TQDateTime startDT, endDT; + TQDate date; // null dates are invalid, that's what we want + bool timeSet = false;// flag denoting if the time has been set. + TQTime time; // null dates are valid, so rely on the timeSet flag + TQDateTime endDT; // null datetimes are invalid, that's what we want bool useEndTime = false; + KOrg::BaseView *curView = mViewManager->currentView(); + KOAgendaView *aView = mViewManager->agendaView(); - if (aView && aView->selectionStart().isValid()) { - date = aView->selectionStart().date(); - startDT = aView->selectionStart(); + KOMonthView *mView = mViewManager->monthView(); + if ( curView == mViewManager->multiAgendaView() ) { + aView = mViewManager->multiAgendaView()->selectedAgendaView(); + curView = aView; + } + + if ( !curView ) { + return; + } + + if ( curView == aView && aView->selectionStart().isValid() ) { + date = aView->selectionStart().date(); endDT = aView->selectionEnd(); useEndTime = !aView->selectedIsSingleCell(); - if (!aView->selectedIsAllDay()) { - time = aView->selectionStart().time(); + if ( !aView->selectedIsAllDay() ) { + time = aView->selectionStart().time(); + timeSet = true; } + } else if ( curView == mView && mView->selectionStart().isValid() ) { + date = mView->selectionStart().date(); + } else if ( !mDateNavigator->selectedDates().isEmpty() && + curView->supportsDateNavigation() ) { + // default to the selected date from the navigator + date = mDateNavigator->selectedDates().first(); + } + + if ( !date.isValid() && curView->supportsDateNavigation() ) { + KMessageBox::sorry( + this, + i18n( "Paste failed: unable to determine a valid target date." ) ); + return; + } + DndFactory factory( mCalendar ); + Incidence::List pastedIncidences; + if ( timeSet && time.isValid() ) { + pastedIncidences = factory.pasteIncidences( date, &time ); } else { - date = mNavigator->selectedDates().first(); + pastedIncidences = factory.pasteIncidences( date ); } - DndFactory factory( mCalendar ); - Incidence *pastedIncidence; - if (time.isValid()) - pastedIncidence = factory.pasteIncidence( date, &time ); - else - pastedIncidence = factory.pasteIncidence( date ); - if ( !pastedIncidence ) return; - - // FIXME: use a visitor here - if (pastedIncidence->type() == "Event" ) { - - Event* pastedEvent = static_cast<Event*>(pastedIncidence); - // only use selected area if event is of the same type (all-day or non-all-day - // as the current selection is - if ( aView && endDT.isValid() && useEndTime ) { - if ( (pastedEvent->doesFloat() && aView->selectedIsAllDay()) || - (!pastedEvent->doesFloat() && ! aView->selectedIsAllDay()) ) { - pastedEvent->setDtEnd(endDT); + Incidence::List::Iterator it; + for ( it = pastedIncidences.begin(); it != pastedIncidences.end(); ++it ) { + QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); + + // FIXME: use a visitor here + if ( ( *it )->type() == "Event" ) { + Event *pastedEvent = static_cast<Event*>( *it ); + // only use selected area if event is of the same type + // (all-day or non-all-day) as the current selection is + if ( aView && endDT.isValid() && useEndTime ) { + if ( ( pastedEvent->doesFloat() && aView->selectedIsAllDay() ) || + ( !pastedEvent->doesFloat() && !aView->selectedIsAllDay() ) ) { + pastedEvent->setDtEnd( endDT ); + } } - } - mChanger->addIncidence( pastedEvent, this ); - } else if ( pastedIncidence->type() == "Todo" ) { - Todo* pastedTodo = static_cast<Todo*>(pastedIncidence); - Todo* _selectedTodo = selectedTodo(); - if ( _selectedTodo ) - pastedTodo->setRelatedTo( _selectedTodo ); - mChanger->addIncidence( pastedTodo, this ); + // KCal supports events with relations, but korganizer doesn't + // so unset it. It can even come from other application. + pastedEvent->setRelatedTo( 0 ); + pastedEvent->setRelatedToUid( TQString() ); + + mChanger->addIncidence( pastedEvent, p.first, p.second, this ); + + } else if ( ( *it )->type() == "Todo" ) { + Todo *pastedTodo = static_cast<Todo*>( *it ); + Todo *_selectedTodo = selectedTodo(); + + // if we are cutting a hierarchy only the root + // should be son of _selectedTodo + if ( _selectedTodo && !pastedTodo->relatedTo() ) { + pastedTodo->setRelatedTo( _selectedTodo ); + } + mChanger->addIncidence( pastedTodo, p.first, p.second, this ); + } } } @@ -932,26 +1117,22 @@ void CalendarView::edit_options() void CalendarView::dateTimesForNewEvent( TQDateTime &startDt, TQDateTime &endDt, bool &allDay ) { - if ( !startDt.isValid() ) { - // Default start is the first selected date with the preferred time as set - // in the config dlg. - if ( !startDt.date().isValid() ) { - startDt.setDate( mNavigator->selectedDates().first() ); - } - if ( !startDt.time().isValid() ) { - startDt.setTime( KOPrefs::instance()->mStartTime.time() ); - } - } - if ( !endDt.isValid() ) { - int addSecs = ( KOPrefs::instance()->mDefaultDuration.time().hour()*3600 ) + - ( KOPrefs::instance()->mDefaultDuration.time().minute()*60 ); + mViewManager->currentView()->eventDurationHint( startDt, endDt, allDay ); + + if ( !startDt.isValid() || !endDt.isValid() ) { + startDt.setDate( activeDate( true ) ); + startDt.setTime( KOPrefs::instance()->mStartTime.time() ); + + int addSecs = ( KOPrefs::instance()->mDefaultDuration.time().hour() * 3600 ) + + ( KOPrefs::instance()->mDefaultDuration.time().minute() * 60 ); + endDt = startDt.addSecs( addSecs ); } - mViewManager->currentView()->eventDurationHint( startDt, endDt, allDay ); } -KOEventEditor *CalendarView::newEventEditor( const TQDateTime &startDtParam, - const TQDateTime &endDtParam, bool allDayParam) +KOEventEditor *CalendarView::newEventEditor( ResourceCalendar *res, const TQString &subRes, + const TQDateTime &startDtParam, + const TQDateTime &endDtParam, bool allDayParam ) { // let the current view change the default start/end datetime bool allDay = allDayParam; @@ -963,111 +1144,164 @@ KOEventEditor *CalendarView::newEventEditor( const TQDateTime &startDtParam, KOEventEditor *eventEditor = mDialogManager->getEventEditor(); eventEditor->newEvent(); connectIncidenceEditor( eventEditor ); + eventEditor->setResource( res, subRes ); eventEditor->setDates( startDt, endDt, allDay ); mDialogManager->connectTypeAhead( eventEditor, dynamic_cast<KOrg::AgendaView*>(viewManager()->currentView()) ); return eventEditor; } +void CalendarView::newEvent() +{ + KOrg::BaseView *currentView = mViewManager->currentView(); + if ( currentView == mViewManager->multiAgendaView() ) { + currentView = mViewManager->multiAgendaView()->selectedAgendaView(); + } + if ( currentView ) { + newEvent( currentView->resourceCalendar(), + currentView->subResourceCalendar() ); + } +} -void CalendarView::newEvent() +void CalendarView::newEvent( ResourceCalendar *res, const TQString &subRes ) { kdDebug(5850) << "CalendarView::newEvent()" << endl; - newEvent( TQDateTime(), TQDateTime() ); + newEvent( res, subRes, TQDateTime(), TQDateTime() ); } -void CalendarView::newEvent( const TQDate &dt ) +void CalendarView::newEvent( ResourceCalendar *res, const TQString &subRes, + const TQDate &dt ) { TQDateTime startDt( dt, KOPrefs::instance()->mStartTime.time() ); - return newEvent( TQDateTime( dt ), TQDateTime() ); + newEvent( res, subRes, TQDateTime( dt ), TQDateTime() ); } -void CalendarView::newEvent( const TQDateTime &startDt ) +void CalendarView::newEvent( ResourceCalendar *res, const TQString &subRes, + const TQDateTime &startDt ) { - return newEvent( startDt, TQDateTime() ); + newEvent( res, subRes, startDt, TQDateTime() ); } -void CalendarView::newEvent( const TQDateTime &startDt, const TQDateTime &endDt, +void CalendarView::newEvent( ResourceCalendar *res, const TQString &subRes, + const TQDateTime &startDt, const TQDateTime &endDt, bool allDay ) { - KOEventEditor *eventEditor = newEventEditor( startDt, endDt, allDay ); + KOEventEditor *eventEditor = newEventEditor( res, subRes, + startDt, endDt, allDay ); eventEditor->show(); } -void CalendarView::newEvent( const TQString &summary, const TQString &description, +void CalendarView::newEvent( ResourceCalendar *res, const TQString &subRes, + const TQString &summary, const TQString &description, const TQStringList &attachments, const TQStringList &attendees, const TQStringList &attachmentMimetypes, bool inlineAttachment ) { - KOEventEditor *eventEditor = newEventEditor(); + KOEventEditor *eventEditor = newEventEditor( res, subRes ); eventEditor->setTexts( summary, description ); // if attach or attendee list is empty, these methods don't do anything, so - // it's save to call them in every case + // it's safe to call them in every case eventEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment ); eventEditor->addAttendees( attendees ); eventEditor->show(); } -void CalendarView::newTodo( const TQString &summary, const TQString &description, +void CalendarView::newTodo( ResourceCalendar *res, const TQString &subRes, + const TQString &summary, const TQString &description, const TQStringList &attachments, const TQStringList &attendees, - const TQStringList &attachmentMimetypes, bool inlineAttachment ) + const TQStringList &attachmentMimetypes, + bool inlineAttachment, bool isTask ) { kdDebug(5850) << k_funcinfo << endl; KOTodoEditor *todoEditor = mDialogManager->getTodoEditor(); connectIncidenceEditor( todoEditor ); todoEditor->newTodo(); + todoEditor->setResource( res, subRes ); todoEditor->setTexts( summary, description ); todoEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment ); todoEditor->addAttendees( attendees ); + todoEditor->selectCreateTask( isTask ); todoEditor->show(); } void CalendarView::newTodo() { + KOrg::BaseView *currentView = mViewManager->currentView(); + + if ( currentView == mViewManager->multiAgendaView() ) { + currentView = mViewManager->multiAgendaView()->selectedAgendaView(); + } + if ( currentView ) { + newTodo( currentView->resourceCalendar(), + currentView->subResourceCalendar() ); + } +} + +void CalendarView::newTodo( ResourceCalendar *res, const TQString &subRes ) +{ kdDebug(5850) << k_funcinfo << endl; TQDateTime dtDue; bool allday = true; KOTodoEditor *todoEditor = mDialogManager->getTodoEditor(); connectIncidenceEditor( todoEditor ); todoEditor->newTodo(); + todoEditor->setResource( res, subRes ); if ( mViewManager->currentView()->isEventView() ) { - dtDue.setDate( mNavigator->selectedDates().first() ); + dtDue.setDate( mDateNavigator->selectedDates().first() ); TQDateTime dtDummy = TQDateTime::currentDateTime(); - mViewManager->currentView()-> - eventDurationHint( dtDue, dtDummy, allday ); + mViewManager->currentView()->eventDurationHint( dtDue, dtDummy, allday ); todoEditor->setDates( dtDue, allday ); } todoEditor->show(); } -void CalendarView::newTodo( const TQDate &date ) +void CalendarView::newTodo( ResourceCalendar *res, const TQString &subRes, + const TQDate &date ) { KOTodoEditor *todoEditor = mDialogManager->getTodoEditor(); connectIncidenceEditor( todoEditor ); todoEditor->newTodo(); + todoEditor->setResource( res, subRes ); todoEditor->setDates( TQDateTime( date, TQTime::currentTime() ), true ); todoEditor->show(); } void CalendarView::newJournal() { + KOrg::BaseView *currentView = mViewManager->currentView(); + + if ( currentView == mViewManager->multiAgendaView() ) { + currentView = mViewManager->multiAgendaView()->selectedAgendaView(); + } + + if ( currentView ) { + newJournal( currentView->resourceCalendar(), + currentView->subResourceCalendar() ); + } +} + +void CalendarView::newJournal( ResourceCalendar *res, const TQString &subRes ) +{ kdDebug(5850) << "CalendarView::newJournal()" << endl; - newJournal( TQString::null, TQDate() ); + newJournal( res, subRes, TQString::null, TQDate() ); } -void CalendarView::newJournal( const TQDate &date) +void CalendarView::newJournal( ResourceCalendar *res, const TQString &subRes, + const TQDate &date) { - newJournal( TQString::null, date ); + newJournal( res, subRes, TQString::null, date ); } -void CalendarView::newJournal( const TQString &text, const TQDate &date ) +void CalendarView::newJournal( ResourceCalendar *res, const TQString &subRes, + const TQString &text, const TQDate &date ) { KOJournalEditor *journalEditor = mDialogManager->getJournalEditor(); connectIncidenceEditor( journalEditor ); journalEditor->newJournal(); + journalEditor->setResource( res, subRes ); journalEditor->setTexts( text ); if ( !date.isValid() ) { - journalEditor->setDate( mNavigator->selectedDates().first() ); + journalEditor->setDate( mDateNavigator->selectedDates().first() ); } else { journalEditor->setDate( date ); } @@ -1089,15 +1323,6 @@ void CalendarView::newSubTodo(Todo *parentEvent) todoEditor->show(); } -void CalendarView::newFloatingEvent() -{ - DateList tmpList = mNavigator->selectedDates(); - TQDate date = tmpList.first(); - - newEvent( TQDateTime( date, TQTime( 12, 0, 0 ) ), - TQDateTime( date, TQTime( 12, 0, 0 ) ), true ); -} - bool CalendarView::addIncidence( const TQString &ical ) { kdDebug(5850) << "CalendarView::addIncidence:\n" << ical << endl; @@ -1105,7 +1330,7 @@ bool CalendarView::addIncidence( const TQString &ical ) format.setTimeZone( mCalendar->timeZoneId(), true ); Incidence *incidence = format.fromString( ical ); if ( !incidence ) return false; - if ( !mChanger->addIncidence( incidence, this ) ) { + if ( !mChanger->addIncidence( incidence, 0, TQString(), this ) ) { delete incidence; return false; } @@ -1115,19 +1340,21 @@ bool CalendarView::addIncidence( const TQString &ical ) void CalendarView::appointment_show() { Incidence *incidence = selectedIncidence(); - if (incidence) - showIncidence( incidence ); - else + if ( incidence ) { + showIncidence( incidence, activeIncidenceDate() ); + } else { KNotifyClient::beep(); + } } void CalendarView::appointment_edit() { Incidence *incidence = selectedIncidence(); - if (incidence) - editIncidence( incidence ); - else + if ( incidence ) { + editIncidence( incidence, activeIncidenceDate() ); + } else { KNotifyClient::beep(); + } } void CalendarView::appointment_delete() @@ -1142,22 +1369,24 @@ void CalendarView::appointment_delete() void CalendarView::todo_unsub() { Todo *anTodo = selectedTodo(); - if( todo_unsub (anTodo ) ) { + if( incidence_unsub ( anTodo ) ) { updateView(); } } -bool CalendarView::todo_unsub( Todo *todo ) +bool CalendarView::incidence_unsub( Incidence *inc ) { - bool status= false; - if ( !todo || !todo->relatedTo() ) return false; + bool status = false; + if ( !inc || !inc->relatedTo() ) { + return false; + } - if ( mChanger->beginChange( todo ) ) { - Todo *oldTodo = todo->clone(); - todo->setRelatedTo(0); - mChanger->changeIncidence( oldTodo, todo, KOGlobals::RELATION_MODIFIED ); - mChanger->endChange( todo ); - delete oldTodo; + if ( mChanger->beginChange( inc, 0, TQString() ) ) { + Incidence *oldInc = inc->clone(); + inc->setRelatedTo( 0 ); + mChanger->changeIncidence( oldInc, inc, KOGlobals::RELATION_MODIFIED, this ); + mChanger->endChange( inc, 0, TQString() ); + delete oldInc; setModified(true); status = true; } @@ -1169,34 +1398,30 @@ bool CalendarView::todo_unsub( Todo *todo ) return status; } -bool CalendarView::makeSubTodosIndependents ( ) +bool CalendarView::makeSubTodosIndependent ( ) { bool status = false; - Todo *anTodo = selectedTodo(); + Todo *aTodo = selectedTodo(); - if( makeSubTodosIndependents( anTodo ) ) { + if ( makeChildrenIndependent( aTodo ) ) { updateView(); status = true; } return status; } -bool CalendarView::makeSubTodosIndependents ( Todo *todo ) +bool CalendarView::makeChildrenIndependent ( Incidence *inc ) { - if( !todo || todo->relations().isEmpty() ) return false; + if ( !inc || inc->relations().isEmpty() ) { + return false; + } startMultiModify ( i18n( "Make sub-to-dos independent" ) ); - Incidence::List subTodos( todo->relations() ); + Incidence::List subIncs( inc->relations() ); Incidence::List::Iterator it; - Incidence *aIncidence; - Todo *aTodo; - for ( it= subTodos.begin(); it != subTodos.end(); ++it ) { - aIncidence = *it; - if( aIncidence && aIncidence->type() == "Todo" ) { - aTodo = static_cast<Todo*>( aIncidence ); - todo_unsub ( aTodo ); - } + for ( it= subIncs.begin(); it != subIncs.end(); ++it ) { + incidence_unsub ( *it ); } endMultiModify(); return true; @@ -1220,7 +1445,7 @@ void CalendarView::toggleAlarm( Incidence *incidence ) return; } Incidence*oldincidence = incidence->clone(); - if ( !mChanger->beginChange( incidence ) ) { + if ( !mChanger->beginChange( incidence, 0, TQString() ) ) { kdDebug(5850) << "Unable to lock incidence " << endl; delete oldincidence; return; @@ -1228,15 +1453,35 @@ void CalendarView::toggleAlarm( Incidence *incidence ) Alarm::List alarms = incidence->alarms(); Alarm::List::ConstIterator it; - for( it = alarms.begin(); it != alarms.end(); ++it ) + for ( it = alarms.begin(); it != alarms.end(); ++it ) { (*it)->toggleAlarm(); - if (alarms.isEmpty()) { + } + if ( alarms.isEmpty() ) { // Add an alarm if it didn't have one - Alarm*alm = incidence->newAlarm(); - alm->setEnabled(true); + Alarm *alm = incidence->newAlarm(); + alm->setType( Alarm::Display ); + alm->setEnabled( true ); + int duration; // in secs + switch( KOPrefs::instance()->mReminderTimeUnits ) { + default: + case 0: // mins + duration = KOPrefs::instance()->mReminderTime * 60; + break; + case 1: // hours + duration = KOPrefs::instance()->mReminderTime * 60 * 60; + break; + case 2: // days + duration = KOPrefs::instance()->mReminderTime * 60 * 60 * 24; + break; + } + if ( incidence->type() == "Event" ) { + alm->setStartOffset( KCal::Duration( -duration ) ); + } else { + alm->setEndOffset( KCal::Duration( -duration ) ); + } } - mChanger->changeIncidence( oldincidence, incidence, KOGlobals::ALARM_MODIFIED ); - mChanger->endChange( incidence ); + mChanger->changeIncidence( oldincidence, incidence, KOGlobals::ALARM_MODIFIED, this ); + mChanger->endChange( incidence, 0, TQString() ); delete oldincidence; // mClickedItem->updateIcons(); @@ -1248,7 +1493,11 @@ void CalendarView::dissociateOccurrence( Incidence *incidence, const TQDate &dat kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl; return; } - if ( !mChanger->beginChange( incidence ) ) { + + QPair<ResourceCalendar *, TQString>p = + CalHelper::incSubResourceCalendar( calendar(), incidence ); + + if ( !mChanger->beginChange( incidence, p.first, p.second ) ) { kdDebug(5850) << "Unable to lock incidence " << endl; return; } @@ -1260,14 +1509,14 @@ void CalendarView::dissociateOccurrence( Incidence *incidence, const TQDate &dat if ( newInc ) { // TODO [FIXME]: Use the same resource instead of asking again! // See also koagenda.cpp: endItemAction() - bool success = mChanger->addIncidence( newInc, this ); + bool success = mChanger->addIncidence( newInc, p.first, p.second, this ); if ( success ) - mChanger->changeIncidence( oldincidence, incidence ); + mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this ); } else { KMessageBox::sorry( this, i18n("Dissociating the occurrence failed."), i18n("Dissociating Failed") ); } - mChanger->endChange( incidence ); + mChanger->endChange( incidence, p.first, p.second ); endMultiModify(); delete oldincidence; } @@ -1278,7 +1527,11 @@ void CalendarView::dissociateFutureOccurrence( Incidence *incidence, const TQDat kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl; return; } - if ( !mChanger->beginChange( incidence ) ) { + + QPair<ResourceCalendar *, TQString>p = + CalHelper::incSubResourceCalendar( calendar(), incidence ); + + if ( !mChanger->beginChange( incidence, p.first, p.second ) ) { kdDebug(5850) << "Unable to lock incidence " << endl; return; } @@ -1287,15 +1540,14 @@ void CalendarView::dissociateFutureOccurrence( Incidence *incidence, const TQDat Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true ); if ( newInc ) { - // TODO: Use the same resource instead of asking again! - mChanger->changeIncidence( oldincidence, incidence ); - mChanger->addIncidence( newInc, this ); + mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this ); + mChanger->addIncidence( newInc, p.first, p.second, this ); } else { KMessageBox::sorry( this, i18n("Dissociating the future occurrences failed."), i18n("Dissociating Failed") ); } endMultiModify(); - mChanger->endChange( incidence ); + mChanger->endChange( incidence, p.first, p.second ); delete oldincidence; } @@ -1374,29 +1626,43 @@ void CalendarView::schedule_declinecounter(Incidence *incidence) schedule(Scheduler::Declinecounter,incidence); } -void CalendarView::schedule_forward(Incidence * incidence) +void CalendarView::schedule_forward( Incidence *incidence ) { - if (incidence == 0) + if ( !incidence ) { incidence = selectedIncidence(); + } - if (!incidence) { - KMessageBox::information( this, i18n("No item selected."), - "ForwardNoEventSelected" ); + if ( !incidence ) { + KMessageBox::information( + this, + i18n( "No item selected." ), + i18n( "Forwarding" ), + "ForwardNoEventSelected" ); return; } PublishDialog publishdlg; if ( publishdlg.exec() == TQDialog::Accepted ) { TQString recipients = publishdlg.addresses(); + if ( incidence->organizer().isEmpty() ) { + incidence->setOrganizer( Person( KOPrefs::instance()->fullName(), + KOPrefs::instance()->email() ) ); + } + ICalFormat format; TQString messageText = format.createScheduleMessage( incidence, Scheduler::Request ); KOMailClient mailer; if ( mailer.mailTo( incidence, recipients, messageText ) ) { - - KMessageBox::information( this, i18n("The item information was successfully sent."), - i18n("Forwarding"), "IncidenceForwardSuccess" ); + KMessageBox::information( + this, + i18n( "The item information was successfully sent." ), + i18n( "Forwarding" ), + "IncidenceForwardSuccess" ); } else { - KMessageBox::error( this, i18n("Unable to forward the item '%1'").arg( incidence->summary() ) ); + KMessageBox::error( + this, + i18n( "Unable to forward the item '%1'" ).arg( incidence->summary() ), + i18n( "Forwarding Error" ) ); } } } @@ -1458,7 +1724,7 @@ void CalendarView::schedule(Scheduler::Method method, Incidence *incidence) // Send the mail KCal::MailScheduler scheduler( mCalendar ); - if ( !scheduler.performTransaction( incidence, method ) ) { + if ( scheduler.performTransaction( incidence, method ) ) { KMessageBox::information( this, i18n("The groupware message for item '%1'" "was successfully sent.\nMethod: %2") .arg( incidence->summary() ) @@ -1515,9 +1781,11 @@ void CalendarView::print() KOrg::BaseView *currentView = mViewManager->currentView(); CalPrinterBase::PrintType printType = CalPrinterBase::Month; - if ( currentView ) printType = currentView->printType(); + if ( currentView ) { + printType = currentView->printType(); + } - DateList tmpDateList = mNavigator->selectedDates(); + DateList tmpDateList = mDateNavigator->selectedDates(); Incidence::List selectedIncidences; if ( mViewManager->currentView() ) { selectedIncidences = mViewManager->currentView()->selectedIncidences(); @@ -1542,12 +1810,20 @@ void CalendarView::exportWeb() void CalendarView::exportICalendar() { TQString filename = KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this); - - // Force correct extension - if (filename.right(4) != ".ics") filename += ".ics"; - - FileStorage storage( mCalendar, filename, new ICalFormat ); - storage.save(); + if ( !filename.isEmpty() ) + { + // Force correct extension + if (filename.right(4) != ".ics") filename += ".ics"; + if ( TQFile( filename ).exists() ) { + if ( KMessageBox::No == KMessageBox::warningYesNo( + this, + i18n( "Do you want to overwrite %1?").arg(filename) ) ) { + return; + } + } + FileStorage storage( mCalendar, filename, new ICalFormat ); + storage.save(); + } } void CalendarView::exportVCalendar() @@ -1561,13 +1837,21 @@ void CalendarView::exportVCalendar() } TQString filename = KFileDialog::getSaveFileName("vcalout.vcs",i18n("*.vcs|vCalendars"),this); - - // TODO: I don't like forcing extensions: - // Force correct extension - if (filename.right(4) != ".vcs") filename += ".vcs"; - - FileStorage storage( mCalendar, filename, new VCalFormat ); - storage.save(); + if ( !filename.isEmpty() ) + { + // TODO: I don't like forcing extensions: + // Force correct extension + if (filename.right(4) != ".vcs") filename += ".vcs"; + if ( TQFile( filename ).exists() ) { + if ( KMessageBox::No == KMessageBox::warningYesNo( + this, + i18n( "Do you want to overwrite %1?").arg(filename ) ) ) { + return; + } + } + FileStorage storage( mCalendar, filename, new VCalFormat ); + storage.save(); + } } void CalendarView::eventUpdated(Incidence *) @@ -1592,41 +1876,54 @@ void CalendarView::adaptNavigationUnits() } } -void CalendarView::processMainViewSelection( Incidence *incidence ) +void CalendarView::processMainViewSelection( Incidence *incidence, const TQDate &date ) { if ( incidence ) mTodoList->clearSelection(); - processIncidenceSelection( incidence ); + processIncidenceSelection( incidence, date ); } -void CalendarView::processTodoListSelection( Incidence *incidence ) +void CalendarView::processTodoListSelection( Incidence *incidence, const TQDate &date ) { if ( incidence && mViewManager->currentView() ) { mViewManager->currentView()->clearSelection(); } - processIncidenceSelection( incidence ); + processIncidenceSelection( incidence, date ); } -void CalendarView::processIncidenceSelection( Incidence *incidence ) +void CalendarView::processIncidenceSelection( Incidence *incidence, const TQDate &date ) { - if ( incidence == mSelectedIncidence ) return; + if ( incidence != mSelectedIncidence ) { + // This signal also must be emitted if incidence is 0 + emit incidenceSelected( incidence, date ); + } + + if ( !incidence ) { + mSelectedIncidence = incidence; + return; + } + if ( incidence == mSelectedIncidence ) { + if ( !incidence->doesRecur() || mSaveDate == date ) { + return; + } + } mSelectedIncidence = incidence; + mSaveDate = date; - emit incidenceSelected( mSelectedIncidence ); + emit incidenceSelected( mSelectedIncidence, date ); bool organizerEvents = false; bool groupEvents = false; bool todo = false; bool subtodo = false; - if ( incidence ) { - organizerEvents = KOPrefs::instance()->thatIsMe( incidence->organizer().email() ); - groupEvents = incidence->attendeeByMails( KOPrefs::instance()->allEmails() ); + organizerEvents = KOPrefs::instance()->thatIsMe( incidence->organizer().email() ); + groupEvents = incidence->attendeeByMails( KOPrefs::instance()->allEmails() ); - if ( incidence && incidence->type() == "Todo" ) { - todo = true; - subtodo = ( incidence->relatedTo() != 0 ); - } + if ( incidence->type() == "Todo" ) { + todo = true; + subtodo = ( incidence->relatedTo() != 0 ); } + emit todoSelected( todo ); emit subtodoSelected( subtodo ); emit organizerEventsSelected( organizerEvents ); @@ -1647,9 +1944,10 @@ void CalendarView::checkClipboard() #endif } -void CalendarView::showDates(const DateList &selectedDates) +void CalendarView::showDates( const DateList &selectedDates, const TQDate &preferredMonth ) { -// kdDebug(5850) << "CalendarView::selectDates()" << endl; + mDateNavigatorContainer->selectDates( selectedDates, preferredMonth ); + mNavigatorBar->selectDates( selectedDates ); if ( mViewManager->currentView() ) { updateView( selectedDates.first(), selectedDates.last() ); @@ -1663,7 +1961,7 @@ void CalendarView::editFilters() kdDebug(5850) << "CalendarView::editFilters()" << endl; CalFilter *filter = mFilters.first(); - while(filter) { + while( filter ) { kdDebug(5850) << " Filter: " << filter->name() << endl; filter = mFilters.next(); } @@ -1755,9 +2053,9 @@ void CalendarView::showIntro() void CalendarView::showDateNavigator( bool show ) { if( show ) - mDateNavigator->show(); + mDateNavigatorContainer->show(); else - mDateNavigator->hide(); + mDateNavigatorContainer->hide(); } void CalendarView::showTodoView( bool show ) @@ -1835,7 +2133,7 @@ Todo *CalendarView::selectedTodo() void CalendarView::dialogClosing( Incidence *in ) { // FIXME: this doesn't work, because if it's a new incidence, it's not locked! - mChanger->endChange( in ); + mChanger->endChange( in, 0, TQString() ); mDialogList.remove( in ); } @@ -1857,18 +2155,22 @@ Incidence* CalendarView::selectedIncidence() void CalendarView::showIncidence() { - showIncidence( selectedIncidence() ); + showIncidence( selectedIncidence(), activeIncidenceDate() ); } void CalendarView::editIncidence() { - editIncidence( selectedIncidence() ); + editIncidence( selectedIncidence(), activeIncidenceDate() ); } -bool CalendarView::editIncidence( const TQString& uid ) +bool CalendarView::editIncidence( const TQString &uid ) { - kdDebug(5850) << "CalendarView::editIncidence()" << endl; - return editIncidence( mCalendar->incidence( uid ) ); + return editIncidence( mCalendar->incidence( uid ), TQDate() ); +} + +bool CalendarView::editIncidence( const TQString &uid, const TQDate &date ) +{ + return editIncidence( mCalendar->incidence( uid ), date ); } void CalendarView::deleteIncidence() @@ -1891,21 +2193,51 @@ void CalendarView::pasteIncidence() edit_paste(); } -void CalendarView::showIncidence( Incidence *incidence ) +void CalendarView::showIncidence( Incidence *incidence, const TQDate &date ) { - KOEventViewerDialog *eventViewer = new KOEventViewerDialog( this ); - eventViewer->setIncidence( incidence ); + if ( !incidence ) { + return; + } + + KOEventViewerDialog *eventViewer = new KOEventViewerDialog( calendar(), this ); + eventViewer->setIncidence( incidence, date ); eventViewer->show(); } -bool CalendarView::editIncidence( Incidence *incidence, bool isCounter ) +bool CalendarView::editIncidence( Incidence *incidence, const TQDate &date, bool isCounter ) { kdDebug(5850) << "CalendarView::editEvent()" << endl; - if ( !incidence || !mChanger ) { + CalendarResources *stdcal = dynamic_cast<CalendarResources *>( mCalendar ); + if( stdcal && !stdcal->hasCalendarResources() ) { + KMessageBox::sorry( + this, + i18n( "No resources found. We can not edit the item." ) ); + return false; + } + + // FIXME: This is a nasty hack, since we need to set a parent for the + // resource selection dialog. However, we don't have any UI methods + // in the calendar, only in the CalendarResources::DestinationPolicy + // So we need to type-cast it and extract it from the CalendarResources + TQWidget *tmpparent = 0; + if ( stdcal ) { + tmpparent = stdcal->dialogParentWidget(); + stdcal->setDialogParentWidget( this ); + } + + if ( !incidence ) { + kdDebug(5850) << "Empty Incidence" << endl; KNotifyClient::beep(); return false; } + + if ( !mChanger ) { + kdDebug(5850) << "Empty Changer" << endl; + KNotifyClient::beep(); + return false; + } + KOIncidenceEditor *tmp = editorDialog( incidence ); if ( tmp ) { kdDebug(5850) << "CalendarView::editIncidence() in List" << endl; @@ -1916,24 +2248,47 @@ bool CalendarView::editIncidence( Incidence *incidence, bool isCounter ) } if ( incidence->isReadOnly() ) { - showIncidence( incidence ); + showIncidence( incidence, date ); return true; } - if ( !isCounter && !mChanger->beginChange( incidence ) ) { - warningChangeFailed( incidence ); - showIncidence( incidence ); - return false; + QPair<ResourceCalendar *, TQString>p = + CalHelper::incSubResourceCalendar( calendar(), incidence ); + + Incidence *savedIncidence = incidence->clone(); + Incidence *incToChange; + + if ( incidence->doesRecur() ) { + KOGlobals::WhichOccurrences chosenOption; + incToChange = singleOccurrenceOrAll( incidence, KOGlobals::EDIT, chosenOption, date ); + } else { + incToChange = incidence; } - kdDebug(5850) << "CalendarView::editIncidence() new IncidenceEditor" << endl; - KOIncidenceEditor *incidenceEditor = mDialogManager->getEditor( incidence ); - connectIncidenceEditor( incidenceEditor ); + // If the user pressed cancel incToChange is 0 + if ( incToChange ) { + if ( !isCounter && !mChanger->beginChange( incToChange, p.first, p.second ) ) { + warningChangeFailed( incToChange ); + showIncidence( incToChange, date ); - mDialogList.insert( incidence, incidenceEditor ); - incidenceEditor->editIncidence( incidence, mCalendar ); - incidenceEditor->show(); - return true; + return false; + } + + kdDebug(5850) << "CalendarView::editIncidence() new IncidenceEditor" << endl; + KOIncidenceEditor *incidenceEditor = mDialogManager->getEditor( incToChange ); + connectIncidenceEditor( incidenceEditor ); + + mDialogList.insert( incToChange, incidenceEditor ); + if ( incidence != incToChange ) { + incidenceEditor->setRecurringIncidence( savedIncidence, incidence ); + } + incidenceEditor->setResource( p.first, p.second ); + incidenceEditor->editIncidence( incToChange, date, mCalendar ); + incidenceEditor->show(); + return true; + } else { + return false; + } } void CalendarView::deleteSubTodosIncidence ( Todo *todo ) @@ -1952,7 +2307,7 @@ void CalendarView::deleteSubTodosIncidence ( Todo *todo ) deleteSubTodosIncidence ( aTodo ); } } - mChanger->deleteIncidence ( todo ); + mChanger->deleteIncidence ( todo, this ); } void CalendarView::deleteTodoIncidence ( Todo *todo, bool force ) @@ -1966,29 +2321,31 @@ void CalendarView::deleteTodoIncidence ( Todo *todo, bool force ) doDelete = ( msgItemDelete( todo ) == KMessageBox::Continue ); } if ( doDelete ) - mChanger->deleteIncidence( todo ); + mChanger->deleteIncidence( todo, this ); return; } /* Ok, this to-do has sub-to-dos, ask what to do */ int km = KMessageBox::No; if ( !force ) { - km=KMessageBox::questionYesNoCancel( this, - i18n("The item \"%1\" has sub-to-dos. " - "Do you want to delete just this item and " - "make all its sub-to-dos independent, or " - "delete the to-do with all its sub-to-dos?" - ).arg( todo->summary() ), - i18n("KOrganizer Confirmation"), - i18n("Delete Only This"), - i18n("Delete All")); + km = KMessageBox::questionYesNoCancel( + this, + i18n("The item \"%1\" has sub-to-dos. " + "Do you want to delete just this item and " + "make all its sub-to-dos independent, or " + "delete the to-do with all its sub-to-dos?" + ).arg( todo->summary() ), + i18n("KOrganizer Confirmation"), + i18n("Delete Only This"), + i18n("Delete All")); } startMultiModify( i18n("Deleting sub-to-dos" ) ); // Delete only the father if( km == KMessageBox::Yes ) { - - makeSubTodosIndependents ( todo ); - mChanger->deleteIncidence( todo ); + // Instead of making a subto-do independent, why not relate + // it to it's dead father's parent? + makeChildrenIndependent ( todo ); + mChanger->deleteIncidence( todo, this ); } else if ( km == KMessageBox::No ) { // Delete all // we have to hide the delete confirmation for each itemDate @@ -2054,14 +2411,18 @@ void CalendarView::deleteIncidence(Incidence *incidence, bool force) i18n("Delete &All")); } } + + QPair<ResourceCalendar *, TQString>p = + CalHelper::incSubResourceCalendar( calendar(), incidence ); + switch(km) { case KMessageBox::Ok: // Continue // all case KMessageBox::Continue: - mChanger->deleteIncidence( incidence ); + mChanger->deleteIncidence( incidence, this ); break; case KMessageBox::Yes: // just this one - if ( mChanger->beginChange( incidence ) ) { + if ( mChanger->beginChange( incidence, p.first, p.second ) ) { Incidence *oldIncidence = incidence->clone(); if (incidence->recurrence()->startDate() == itemDate) { // Moving the first in a series...don't bother with the nonstandard exclusion list @@ -2079,18 +2440,18 @@ void CalendarView::deleteIncidence(Incidence *incidence, bool force) // No choice but to use the exclusion list incidence->recurrence()->addExDate( itemDate ); } - mChanger->changeIncidence( oldIncidence, incidence ); - mChanger->endChange( incidence ); + mChanger->changeIncidence( oldIncidence, incidence, KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY, this ); + mChanger->endChange( incidence, p.first, p.second ); delete oldIncidence; } break; case KMessageBox::No: // all future items - if ( mChanger->beginChange( incidence ) ) { + if ( mChanger->beginChange( incidence, p.first, p.second ) ) { Incidence *oldIncidence = incidence->clone(); Recurrence *recur = incidence->recurrence(); recur->setEndDate( itemDate.addDays(-1) ); - mChanger->changeIncidence( oldIncidence, incidence ); - mChanger->endChange( incidence ); + mChanger->changeIncidence( oldIncidence, incidence, KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY, this ); + mChanger->endChange( incidence, p.first, p.second ); delete oldIncidence; } break; @@ -2101,8 +2462,8 @@ void CalendarView::deleteIncidence(Incidence *incidence, bool force) doDelete = ( msgItemDelete( incidence ) == KMessageBox::Continue ); } if ( doDelete ) { - mChanger->deleteIncidence( incidence ); - processIncidenceSelection( 0 ); + mChanger->deleteIncidence( incidence, this ); + processIncidenceSelection( 0, TQDate() ); } } @@ -2134,7 +2495,7 @@ bool CalendarView::purgeCompletedSubTodos( Todo* todo, bool &allPurged ) if ( deleteThisTodo ) { if ( todo->isCompleted() ) { - if ( !mChanger->deleteIncidence( todo ) ) + if ( !mChanger->deleteIncidence( todo, this ) ) allPurged = false; } else { deleteThisTodo = false; @@ -2176,20 +2537,19 @@ void CalendarView::purgeCompleted() } } -void CalendarView::slotCalendarChanged() +void CalendarView::warningChangeFailed( Incidence *incidence ) { - kdDebug(5850) << "CalendarView::slotCalendarChanged()" << endl; -} - -void CalendarView::warningChangeFailed( Incidence * ) -{ - KMessageBox::sorry( this, i18n("Unable to edit item: " - "it is locked by another process.") ); + if ( incidence ) { + KMessageBox::sorry( + this, + i18n( "Unable to edit \"%1\" because it is locked by another process." ). + arg( incidence->summary() ) ); + } } -void CalendarView::editCanceled( Incidence *i ) +void CalendarView::editCanceled( Incidence *incidence ) { - mCalendar->endChange( i ); + mCalendar->endChange( incidence ); } void CalendarView::showErrorMessage( const TQString &msg ) @@ -2249,7 +2609,9 @@ void CalendarView::addIncidenceOn( Incidence *incadd, const TQDate &dt ) todo->setHasDueDate( true ); } - if ( !mChanger->addIncidence( incidence, this ) ) { + QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); + + if ( !mChanger->addIncidence( incidence, p.first, p.second, this ) ) { KODialogManager::errorSaveIncidence( this, incidence ); delete incidence; } @@ -2267,8 +2629,11 @@ void CalendarView::moveIncidenceTo( Incidence *incmove, const TQDate &dt ) addIncidenceOn( incidence, dt ); return; } + Incidence *oldIncidence = incidence->clone(); - if ( !mChanger->beginChange( incidence ) ) { + QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); + + if ( !mChanger->beginChange( incidence, p.first, p.second ) ) { delete oldIncidence; return; } @@ -2295,15 +2660,151 @@ void CalendarView::moveIncidenceTo( Incidence *incmove, const TQDate &dt ) todo->setDtDue( due ); todo->setHasDueDate( true ); } - mChanger->changeIncidence( oldIncidence, incidence ); - mChanger->endChange( incidence ); + mChanger->changeIncidence( oldIncidence, incidence, KOGlobals::DATE_MODIFIED,this ); + mChanger->endChange( incidence, p.first, p.second ); delete oldIncidence; } void CalendarView::resourcesChanged() { mViewManager->resourcesChanged(); + mDateNavigatorContainer->setUpdateNeeded(); updateView(); } +Incidence* CalendarView::singleOccurrenceOrAll( Incidence *inc, + KOGlobals::OccurrenceAction userAction, + KOGlobals::WhichOccurrences &chosenOption, + const TQDate &itemDate, + const bool commitToCalendar ) +{ + + // temporary, until recurring to-dos are fixed + if ( inc->type() != "Event" ) { + chosenOption = KOGlobals::ALL; + return inc; + } + + Incidence *incToReturn = 0; + Incidence *incSaved = 0; + KOGlobals::WhatChanged whatChanged; + + bool dissociationOccurred = false; + const TQDate &dt = itemDate.isValid() ? itemDate : activeIncidenceDate(); + + TQString dialogTitle; + TQString dialogText; + + if ( userAction == KOGlobals::CUT ) { + dialogTitle = i18n( "Cutting Recurring Item" ); + + dialogText = i18n("The item you try to cut is a recurring item. Do you want to cut " + "only this single occurrence, only future items, " + "or all items in the recurrence?"); + + } else if ( userAction == KOGlobals::COPY ) { + dialogTitle = i18n( "Copying Recurring Item" ); + + dialogText = i18n("The item you try to copy is a recurring item. Do you want to copy " + "only this single occurrence, only future items, " + "or all items in the recurrence?"); + } else { + dialogTitle = i18n( "Changing Recurring Item" ); + + dialogText = i18n( "The item you try to change is a recurring item. Shall the changes " + "be applied only to this single occurrence, only to the future items, " + "or to all items in the recurrence?" ); + } + + int res = KOMessageBox::fourBtnMsgBox( this, TQMessageBox::Question, + dialogText, + dialogTitle, + i18n("Only &This Item"), i18n("Only &Future Items"), i18n("&All Occurrences") ); + switch ( res ) { + case KMessageBox::Ok: // All occurrences + incToReturn = inc; + chosenOption = KOGlobals::ALL; + break; + case KMessageBox::Yes: { // Just this occurrence + // Dissociate this occurrence: + // create clone of event, set relation to old event, set cloned event + // for mActionItem, add exception date to old event, changeIncidence + // for the old event, remove the recurrence from the new copy and then just + // go on with the newly adjusted mActionItem and let the usual code take + // care of the new time! + + chosenOption = KOGlobals::ONLY_THIS_ONE; + whatChanged = KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY; + startMultiModify( i18n("Dissociate event from recurrence") ); + incSaved = inc->clone(); + incToReturn = mCalendar->dissociateOccurrence( inc, dt ); + if ( incToReturn ) { + dissociationOccurred = true; + } else { + KMessageBox::sorry( this, i18n("Unable to add the exception item to the " + "calendar. No change will be done."), i18n("Error Occurred") ); + incToReturn = 0; + } + + break; } + case KMessageBox::No/*Future*/: { // All future occurrences + // Dissociate this occurrence: + // create clone of event, set relation to old event, set cloned event + // for mActionItem, add recurrence end date to old event, changeIncidence + // for the old event, adjust the recurrence for the new copy and then just + // go on with the newly adjusted mActionItem and let the usual code take + // care of the new time! + chosenOption = KOGlobals::ONLY_FUTURE; + whatChanged = KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE; + startMultiModify( i18n("Split future recurrences") ); + incSaved = inc->clone(); + incToReturn = mCalendar->dissociateOccurrence( inc, dt, false ); + if ( incToReturn ) { + dissociationOccurred = true; + } else { + KMessageBox::sorry( this, i18n("Unable to add the future items to the " + "calendar. No change will be done."), i18n("Error Occurred") ); + + incToReturn = 0; + } + + break; } + default: + chosenOption = KOGlobals::NONE; + } + + if ( dissociationOccurred && commitToCalendar ) { + QPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); + mChanger->addIncidence( incToReturn, p.first, p.second, this ); + mChanger->changeIncidence( incSaved, inc, whatChanged, this ); + } + + return incToReturn; +} + +void CalendarView::selectWeek( const TQDate &date ) +{ + if ( KOPrefs::instance()->mWeekNumbersShowWork && + mViewManager->agendaIsSelected() && + mViewManager->agendaMode() == KOViewManager::AGENDA_WORK_WEEK ) { + mDateNavigator->selectWorkWeek( date ); + } else { + mDateNavigator->selectWeek( date ); + } +} + +void CalendarView::getIncidenceHierarchy( Incidence *inc, + Incidence::List &children ) +{ + // protecion against looping hierarchies + if ( inc && !children.contains( inc ) ) { + Incidence::List::ConstIterator it; + Incidence::List immediateChildren = inc->relations(); + for ( it = immediateChildren.constBegin(); it != immediateChildren.constEnd(); ++it ) { + getIncidenceHierarchy( *it, children ); + } + children.append( inc ); + } +} + #include "calendarview.moc" diff --git a/korganizer/calendarview.h b/korganizer/calendarview.h index dfcc75ef3..5922e8f2d 100644 --- a/korganizer/calendarview.h +++ b/korganizer/calendarview.h @@ -33,7 +33,8 @@ #include <libkcal/scheduler.h> #include <kdepimmacros.h> -#include <korganizer/calendarviewbase.h> +#include "koglobals.h" +#include "interfaces/korganizer/calendarviewbase.h" class TQWidgetStack; class TQSplitter; @@ -90,7 +91,6 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: CalendarView( TQWidget *parent = 0, const char *name = 0 ); virtual ~CalendarView(); - class CalendarViewVisitor : public IncidenceBase::Visitor { public: @@ -112,10 +112,11 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: bool visit( Journal *journal ) { return mView->deleteJournal( journal ); } }; - void setCalendar( Calendar * ); Calendar *calendar(); + QPair<ResourceCalendar *, TQString> viewSubResourceCalendar(); + KOrg::History *history() const { return mHistory; } KOViewManager *viewManager() const { return mViewManager; } @@ -124,7 +125,7 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: TQWidgetStack *viewStack() const { return mRightFrame; } TQWidget *leftFrame() const { return mLeftFrame; } NavigatorBar *navigatorBar() const { return mNavigatorBar; } - DateNavigator *dateNavigator() const { return mNavigator; } + DateNavigator *dateNavigator() const { return mDateNavigator; } KOIncidenceEditor *editorDialog( Incidence* ) const; IncidenceChangerBase *incidenceChanger() const { return mChanger; } @@ -182,7 +183,7 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: Emitted when an incidence gets selected. If the selection is cleared the signal is emitted with 0 as argument. */ - void incidenceSelected( Incidence * ); + void incidenceSelected( Incidence *incidence, const TQDate &date ); /** Emitted, when a todoitem is selected or deselected. the connected slots enables/disables the corresponding menu items */ void todoSelected( bool ); @@ -252,7 +253,8 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: void showIncidence(); void editIncidence(); - bool editIncidence( const TQString& uid ); + bool editIncidence( const TQString &uid ); + bool editIncidence( const TQString &uid, const TQDate &date ); void deleteIncidence(); /** @@ -265,29 +267,37 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: */ bool addIncidence( const TQString &ical ); - void connectIncidenceEditor( KOIncidenceEditor * ); + void connectIncidenceEditor( KOIncidenceEditor *editor ); /** create new event without having a date hint. Takes current date as default hint. */ void newEvent(); + void newEvent( ResourceCalendar *res, const TQString &subRes ); /** create an editeventwin with supplied date/time, and if bool is true, * make the event take all day. */ - void newEvent( const TQDate &startDt ); - void newEvent( const TQDateTime &startDt ); - void newEvent( const TQDateTime &startDt, const TQDateTime &EndDt, bool allDay = false ); + void newEvent( ResourceCalendar *res, const TQString &subRes, + const TQDate &startDt ); + void newEvent( ResourceCalendar *res, const TQString &subRes, + const TQDateTime &startDt ); + void newEvent( ResourceCalendar *res, const TQString &subRes, + const TQDateTime &startDt, const TQDateTime &EndDt, + bool allDay = false ); /** Create new Event from given summary, description, attachment list and attendees list */ - void newEvent( const TQString &summary, const TQString &description = TQString::null, - const TQStringList &attachment = TQStringList(), const TQStringList &attendees = TQStringList(), - const TQStringList &attachmentMimetypes = TQStringList(), bool inlineAttachment = false ); - void newFloatingEvent(); + void newEvent( ResourceCalendar *res, const TQString &subRes, + const TQString &summary, + const TQString &description = TQString::null, + const TQStringList &attachment = TQStringList(), + const TQStringList &attendees = TQStringList(), + const TQStringList &attachmentMimetypes = TQStringList(), + bool inlineAttachment = false ); /** Create a read-only viewer dialog for the supplied incidence. It calls the correct showXXX method*/ - void showIncidence( Incidence * ); + void showIncidence( Incidence *, const TQDate & ); /** Create an editor for the supplied incidence. It calls the correct editXXX method*/ - bool editIncidence( Incidence *incidence, bool isCounter = false ); + bool editIncidence( Incidence *incidence, const TQDate &date, bool isCounter = false ); /** Delete the supplied incidence. It calls the correct deleteXXX method @param force If true, all recurrences and sub-todos (if applicable) will be @@ -331,20 +341,29 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: /** create new todo */ void newTodo(); + void newTodo( ResourceCalendar *res, const TQString &subRes ); /** create new todo, due on date */ - void newTodo( const TQDate &date ); + void newTodo( ResourceCalendar *res, const TQString &subRes, + const TQDate &date ); /** create new todo with a parent todo */ void newSubTodo(); /** create new todo with a parent todo */ void newSubTodo( Todo * ); - void newTodo( const TQString &summary, const TQString &description = TQString::null, - const TQStringList &attachments = TQStringList(), const TQStringList &attendees = TQStringList(), - const TQStringList &attachmentMimetypes = TQStringList(), bool inlineAttachment = false ); + void newTodo( ResourceCalendar *res, const TQString &subRes, + const TQString &summary, + const TQString &description = TQString::null, + const TQStringList &attachments = TQStringList(), + const TQStringList &attendees = TQStringList(), + const TQStringList &attachmentMimetypes = TQStringList(), + bool inlineAttachment = false, bool createTask = false ); void newJournal(); - void newJournal( const TQDate &date ); - void newJournal( const TQString &text, const TQDate &date = TQDate() ); + void newJournal( ResourceCalendar *res, const TQString &subRes ); + void newJournal( ResourceCalendar *res, const TQString &subRes, + const TQDate &date ); + void newJournal( ResourceCalendar *res, const TQString &subRes, + const TQString &text, const TQDate &date = TQDate() ); void toggleAlarm( Incidence * ); void dissociateOccurrence( Incidence *, const TQDate & ); @@ -379,8 +398,8 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: void changeIncidenceDisplay( Incidence *, int ); void incidenceAdded( Incidence * ); - void incidenceChanged( Incidence *oldEvent, Incidence *newEvent ); - void incidenceChanged( Incidence *oldEvent, Incidence *newEvent, int what ); + void incidenceChanged( Incidence *oldEvent, Incidence *newEvent, + KOGlobals::WhatChanged modification ); void incidenceToBeDeleted( Incidence *incidence ); void incidenceDeleted( Incidence * ); void startMultiModify( const TQString &text ); @@ -434,14 +453,21 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: */ void appointment_delete(); - /* frees a subtodo from it's relation, update the view */ + /* frees the selected to-do's children from it's relation, update the view */ void todo_unsub(); - /* Free a subtodo from it's relation, without update the view */ - bool todo_unsub( Todo *todo ); - /** Make all sub-to-dos of todo independents, update the view*/ - bool makeSubTodosIndependents ( ); - /** Make all sub-to-dos of todo independents, not update the view*/ - bool makeSubTodosIndependents ( Todo *todo ); + + /* frees an incidence's children from it's relation, without update the view + Works with any incidence type, although currently we only pass to-dos + */ + bool incidence_unsub( Incidence *inc ); + + /** Make all sub-to-dos of the selected todo independent, update the view */ + bool makeSubTodosIndependent ( ); + + /** Make all children of incidence independent, not update the view + Works with any incidence type, although currently we only pass to-dos + */ + bool makeChildrenIndependent( Incidence *inc ); /** Take ownership of selected event. */ void takeOverEvent(); @@ -506,15 +532,13 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: void dialogClosing( Incidence * ); - void processMainViewSelection( Incidence * ); - void processTodoListSelection( Incidence * ); + void processMainViewSelection( Incidence *incidence, const TQDate &date ); + void processTodoListSelection( Incidence *incidence, const TQDate &date ); - void processIncidenceSelection( Incidence * ); + void processIncidenceSelection( Incidence *incidence, const TQDate &date ); void purgeCompleted(); - void slotCalendarChanged(); - void slotAutoArchivingSettingsModified() { emit autoArchivingSettingsModified(); } void showErrorMessage( const TQString & ); @@ -525,9 +549,20 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: void resourcesChanged(); + /** + The user clicked on a week number in the date navigator + + Lets select a week or a work week depending on the user's + config option. + */ + void selectWeek( const TQDate & ); + protected slots: - /** Select a view or adapt the current view to display the specified dates. */ - void showDates( const KCal::DateList & ); + /** Select a view or adapt the current view to display the specified dates. + preferredMonth is useful when the datelist crosses months, if valid, + any month-like component should honour this + */ + void showDates( const KCal::DateList &, const TQDate &preferredMonth = TQDate() ); public: // show a standard warning @@ -539,7 +574,52 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: */ void adaptNavigationUnits(); - //Attendee* getYourAttendee( Event *event ); + /** + Returns the date of the selected incidence. + + If the selected incidence is recurring, it will return + the date of the selected occurrence + */ + TQDate activeIncidenceDate(); + + /** + Returns the best guess at the current active date in the view. + This has nothing to do with selected incidences, use activeIncidenceDate() + for that, for example, agenda supports time selection and incidence selection + and they can have diferent dates. + + @param fallbackToToday If guessing doesn't work, some views will prefer + today to be returned instead of the first select date in the day matrix, + Journal view for example. + */ + TQDate activeDate( bool fallbackToToday = false ); + + /** + Asks the user if he wants to edit only this occurrence, all + occurrences or only future occurrences, and then dissociates + the incidence if needed. + + @param inc The recurring incidence that's about to be edited. + @param userAction Specifies what the user is doing with the occurrence, + like cutting, pasting or editing, it only influences the strings + in the message box. + @param chosenOption After calling this function, it will hold the user's + chosen option. + @param itemDate The date of the selected view item + @param commitToCalendar If true, mChanger is called and the dissociation + is saved to the calendar. If false, it's up to the caller to do that. + + @return A pointer to the incidence that should be edited which is + 0 if the user pressed cancel, inc if the user pressed + "All Occurrences", or points to a newly created incidence + when dissociation is involved in which case the caller + is responsible to add it to the calendar and freeing it. + **/ + Incidence* singleOccurrenceOrAll( Incidence *inc, + KOGlobals::OccurrenceAction userAction, + KOGlobals::WhichOccurrences &chosenOption, + const TQDate &itemDate = TQDate(), + const bool commitToCalendar = false ); protected: void setIncidenceChanger( IncidenceChangerBase *changer ); @@ -555,18 +635,33 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: defaults, if invalid values are given) and allow the view to adjust the type. */ void dateTimesForNewEvent( TQDateTime &startDt, TQDateTime &endDt, bool &allDay ); - KOEventEditor *newEventEditor( const TQDateTime &startDtParam = TQDateTime(), - const TQDateTime &endDtParam = TQDateTime() , bool allDayParam = false ); + KOEventEditor *newEventEditor( ResourceCalendar *res, const TQString &subRes, + const TQDateTime &startDtParam = TQDateTime(), + const TQDateTime &endDtParam = TQDateTime() , + bool allDayParam = false ); private: void init(); + /** + Returns the incidence that should be sent to clipboard. + Usually it's just returns the selected incidence, but, if + the incidence is recurring, it will ask the user what he wants to + cut/paste and dissociate the incidence if necesssary. + **/ + Incidence *incToSendToClipboard( bool cut ); + void calendarModified( bool, Calendar * ); // Helper function for purgeCompleted that recursively purges a todo and // its subitems. If it cannot delete a completed todo (because it has // uncompleted subitems), notAllPurged is set to true. bool purgeCompletedSubTodos( Todo* todo, bool ¬AllPurged ); + /** Returns all incidences having inc has their parent (or grand parent, etc.) + inc is included in the list too. + */ + void getIncidenceHierarchy( Incidence *inc, Incidence::List &incidences ); + KOrg::History *mHistory; TQSplitter *mPanner; @@ -574,16 +669,18 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: TQWidget *mLeftFrame; TQWidgetStack *mRightFrame; + // This navigator bar is used when in full window month view + // It has nothing to do with the date navigator NavigatorBar *mNavigatorBar; - DateNavigatorContainer *mDateNavigator; + DateNavigatorContainer *mDateNavigatorContainer; TQPtrList<CalendarViewExtension> mExtensions; Calendar *mCalendar; - DateNavigator *mNavigator; + DateNavigator *mDateNavigator; DateChecker *mDateChecker; KOEventViewer *mEventViewer; @@ -597,9 +694,9 @@ class KDE_EXPORT CalendarView : public KOrg::CalendarViewBase, public Calendar:: // various housekeeping variables. bool mModified; // flag indicating if calendar is modified bool mReadOnly; // flag indicating if calendar is read-only - TQDate mSaveSingleDate; Incidence *mSelectedIncidence; + TQDate mSaveDate; KOTodoView *mTodoList; TQMap<Incidence*,KOIncidenceEditor*> mDialogList; diff --git a/korganizer/datenavigator.cpp b/korganizer/datenavigator.cpp index 6f5570a10..edc036ce4 100644 --- a/korganizer/datenavigator.cpp +++ b/korganizer/datenavigator.cpp @@ -54,11 +54,11 @@ int DateNavigator::datesCount() const return mSelectedDates.count(); } -void DateNavigator::selectDates( const DateList& dateList ) +void DateNavigator::selectDates( const DateList &dateList ) { - if (dateList.count() > 0) { + if ( dateList.count() > 0 ) { mSelectedDates = dateList; - + emitSelected(); } } @@ -83,26 +83,33 @@ void DateNavigator::selectDates( int count ) selectDates( mSelectedDates.first(), count ); } -void DateNavigator::selectDates( const TQDate &d, int count ) +void DateNavigator::selectDates( const TQDate &d, int count, const TQDate &preferredMonth ) { + if ( count > MAX_SELECTABLE_DAYS ) { + count = MAX_SELECTABLE_DAYS; + } + DateList dates; int i; for( i = 0; i < count; ++i ) { dates.append( d.addDays( i ) ); } - + mSelectedDates = dates; - - emitSelected(); + + emitSelected( preferredMonth ); } -void DateNavigator::selectWeekByDay( int weekDay, const TQDate &d ) +void DateNavigator::selectWeekByDay( int weekDay, const TQDate &d, const TQDate &preferredMonth ) { int dateCount = mSelectedDates.count(); bool weekStart = ( weekDay == KGlobal::locale()->weekStartDay() ); - if ( weekStart && dateCount == 7 ) selectWeek( d ); - else selectDates( d, dateCount ); + if ( weekStart && dateCount == 7 ) { + selectWeek( d, preferredMonth ); + } else { + selectDates( d, dateCount, preferredMonth ); + } } void DateNavigator::selectWeek() @@ -110,7 +117,7 @@ void DateNavigator::selectWeek() selectWeek( mSelectedDates.first() ); } -void DateNavigator::selectWeek( const TQDate &d ) +void DateNavigator::selectWeek( const TQDate &d, const TQDate &preferredMonth ) { int dayOfWeek = KOGlobals::self()->calendarSystem()->dayOfWeek( d ); @@ -122,7 +129,7 @@ void DateNavigator::selectWeek( const TQDate &d ) firstDate = firstDate.addDays( -7 ); } - selectDates( firstDate, 7 ); + selectDates( firstDate, 7, preferredMonth ); } void DateNavigator::selectWorkWeek() @@ -133,7 +140,7 @@ void DateNavigator::selectWorkWeek() void DateNavigator::selectWorkWeek( const TQDate &d ) { int weekStart = KGlobal::locale()->weekStartDay(); - + int dayOfWeek = KOGlobals::self()->calendarSystem()->dayOfWeek( d ); TQDate currentDate = d.addDays( weekStart - dayOfWeek ); @@ -147,10 +154,10 @@ void DateNavigator::selectWorkWeek( const TQDate &d ) for ( int i = 0; i < 7; ++i ) { if( (1<< ((i + weekStart + 6) % 7)) & (mask) ) { - mSelectedDates.append(currentDate.addDays(i)); + mSelectedDates.append( currentDate.addDays(i) ); } } - + emitSelected(); } @@ -160,8 +167,13 @@ void DateNavigator::selectToday() int dateCount = mSelectedDates.count(); - if ( dateCount == 7 ) selectWeek( d ); - else selectDates( d, dateCount ); + if ( dateCount == 7 ) { + selectWeek( d ); + } else if ( dateCount == 5 ) { + selectWorkWeek( d ); + } else { + selectDates( d, dateCount ); + } } void DateNavigator::selectPreviousYear() @@ -173,13 +185,14 @@ void DateNavigator::selectPreviousYear() selectWeekByDay( weekDay, firstSelected ); } -void DateNavigator::selectPreviousMonth() +void DateNavigator::selectPreviousMonth( const TQDate ¤tMonth, + const TQDate &selectionLowerLimit, + const TQDate &selectionUpperLimit ) { - TQDate firstSelected = mSelectedDates.first(); - int weekDay = firstSelected.dayOfWeek(); - firstSelected = KOGlobals::self()->calendarSystem()->addMonths( firstSelected, -1 ); - - selectWeekByDay( weekDay, firstSelected ); + shiftMonth( currentMonth, + selectionLowerLimit, + selectionUpperLimit, + -1 ); } void DateNavigator::selectPreviousWeek() @@ -201,14 +214,46 @@ void DateNavigator::selectNextWeek() selectWeekByDay( weekDay, firstSelected ); } -void DateNavigator::selectNextMonth() +void DateNavigator::shiftMonth( const TQDate ¤tMonth, + const TQDate &selectionLowerLimit, + const TQDate &selectionUpperLimit, + int offset ) { + const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); + TQDate firstSelected = mSelectedDates.first(); int weekDay = firstSelected.dayOfWeek(); + firstSelected = calSys->addMonths( firstSelected, offset ); + + /* Don't trust firstSelected to calculate the nextMonth. firstSelected + can belong to a month other than currentMonth because KDateNavigator + displays 7*6 days. firstSelected should only be used for selection + purposes */ + const TQDate nextMonth = currentMonth.isValid() ? + calSys->addMonths( currentMonth, offset ) : firstSelected; + + /* When firstSelected doesn't belong to currentMonth it can happen + that the new selection won't be visible on our KDateNavigators + so we must adjust it */ + if ( selectionLowerLimit.isValid() && + firstSelected < selectionLowerLimit ) { + firstSelected = selectionLowerLimit; + } else if ( selectionUpperLimit.isValid() && + firstSelected > selectionUpperLimit ) { + firstSelected = selectionUpperLimit.addDays( -6 ); + } - firstSelected = KOGlobals::self()->calendarSystem()->addMonths( firstSelected, 1 ); + selectWeekByDay( weekDay, firstSelected, nextMonth ); +} - selectWeekByDay( weekDay, firstSelected ); +void DateNavigator::selectNextMonth( const TQDate ¤tMonth, + const TQDate &selectionLowerLimit, + const TQDate &selectionUpperLimit ) +{ + shiftMonth( currentMonth, + selectionLowerLimit, + selectionUpperLimit, + 1 ); } void DateNavigator::selectNextYear() @@ -240,26 +285,41 @@ void DateNavigator::selectNext() selectDates( mSelectedDates.first().addDays( offset ), datesCount() ); } -void DateNavigator::selectMonth(int month) +void DateNavigator::selectMonth( int month ) { + const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); + TQDate firstSelected = mSelectedDates.first(); int weekDay = firstSelected.dayOfWeek(); - const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); int day = calSys->day( firstSelected ); - calSys->setYMD( firstSelected, calSys->year(firstSelected), month, 1 ); + calSys->setYMD( firstSelected, calSys->year( firstSelected ), month, 1 ); int days = calSys->daysInMonth( firstSelected ); // As day we use either the selected date, or if the month has less days // than that, we use the max day of that month - if ( day > days ) day = days; + if ( day > days ) { + day = days; + } + TQDate requestedMonth; calSys->setYMD( firstSelected, calSys->year( firstSelected ), month, day ); + calSys->setYMD( requestedMonth, calSys->year( firstSelected ), month, 1 ); + + selectWeekByDay( weekDay, firstSelected, requestedMonth ); +} +void DateNavigator::selectYear( int year ) +{ + TQDate firstSelected = mSelectedDates.first(); + int deltaYear = year - KOGlobals::self()->calendarSystem()->year( firstSelected ); + firstSelected = KOGlobals::self()->calendarSystem()->addYears( firstSelected, deltaYear ); + + int weekDay = firstSelected.dayOfWeek(); selectWeekByDay( weekDay, firstSelected ); } -void DateNavigator::emitSelected() +void DateNavigator::emitSelected( const TQDate &preferredMonth ) { - emit datesSelected( mSelectedDates ); + emit datesSelected( mSelectedDates, preferredMonth ); } #include "datenavigator.moc" diff --git a/korganizer/datenavigator.h b/korganizer/datenavigator.h index d91bad318..ddb6cf2c8 100644 --- a/korganizer/datenavigator.h +++ b/korganizer/datenavigator.h @@ -49,38 +49,61 @@ class DateNavigator : public QObject void selectDate( const TQDate & ); void selectDates( int count ); - void selectDates( const TQDate &, int count ); + void selectDates( const TQDate &, int count, const TQDate &preferredMonth = TQDate() ); void selectWeek(); - void selectWeek( const TQDate & ); + void selectWeek( const TQDate &, const TQDate &preferredMonth = TQDate() ); void selectWorkWeek(); void selectWorkWeek( const TQDate & ); - void selectWeekByDay( int weekDay, const TQDate & ); - + void selectWeekByDay( int weekDay, const TQDate &, const TQDate &preferredMonth = TQDate() ); + void selectToday(); - + void selectPreviousYear(); - void selectPreviousMonth(); + void selectPreviousMonth( const TQDate ¤tMonth = TQDate(), + const TQDate &selectionLowerLimit = TQDate(), + const TQDate &selectionUpperLimit = TQDate() ); void selectPreviousWeek(); void selectNextWeek(); - void selectNextMonth(); + void selectNextMonth( const TQDate ¤tMonth = TQDate(), + const TQDate &selectionLowerLimit = TQDate(), + const TQDate &selectionUpperLimit = TQDate() ); void selectNextYear(); - + void selectPrevious(); void selectNext(); - void selectMonth(int month); - + void selectMonth( int month ); + void selectYear( int year ); + signals: - void datesSelected( const KCal::DateList & ); + /* preferredMonth is useful when the datelist crosses months, + if valid, any month-like component should honour it + */ + void datesSelected( const KCal::DateList &, const TQDate &preferredMonth ); protected: - void emitSelected(); + void emitSelected( const TQDate &preferredMonth = TQDate() ); private: + + /* + Selects next month if offset equals 1, or previous month + if offset equals -1. + Bigger offsets are accepted. + */ + void shiftMonth( const TQDate &date, + const TQDate &selectionLowerLimit, + const TQDate &selectionUpperLimit, + int offset ); + KCal::DateList mSelectedDates; + + enum { + MAX_SELECTABLE_DAYS = 50 + }; }; #endif diff --git a/korganizer/datenavigatorcontainer.cpp b/korganizer/datenavigatorcontainer.cpp index e3c092fc0..ac0892947 100644 --- a/korganizer/datenavigatorcontainer.cpp +++ b/korganizer/datenavigatorcontainer.cpp @@ -29,6 +29,7 @@ #include "koglobals.h" #include "navigatorbar.h" #include "kdatenavigator.h" +#include "kodaymatrix.h" #include <kcalendarsystem.h> #include <kdialog.h> @@ -79,12 +80,14 @@ void DateNavigatorContainer::connectNavigatorView( KDateNavigator *v ) connect( v, TQT_SIGNAL( goPrevious() ), TQT_SIGNAL( goPrevious() ) ); connect( v, TQT_SIGNAL( goNext() ), TQT_SIGNAL( goNext() ) ); - connect( v, TQT_SIGNAL( goNextMonth() ), TQT_SIGNAL( goNextMonth() ) ); - connect( v, TQT_SIGNAL( goPrevMonth() ), TQT_SIGNAL( goPrevMonth() ) ); - connect( v, TQT_SIGNAL( goNextYear() ), TQT_SIGNAL( goNextYear() ) ); - connect( v, TQT_SIGNAL( goPrevYear() ), TQT_SIGNAL( goPrevYear() ) ); + connect( v, TQT_SIGNAL( nextYearClicked() ), TQT_SIGNAL( nextYearClicked() ) ); + connect( v, TQT_SIGNAL( prevYearClicked() ), TQT_SIGNAL( prevYearClicked() ) ); - connect( v, TQT_SIGNAL( goMonth( int ) ), TQT_SIGNAL( goMonth( int ) ) ); + connect( v, TQT_SIGNAL( prevMonthClicked() ), this, TQT_SLOT( goPrevMonth() ) ); + connect( v, TQT_SIGNAL( nextMonthClicked() ), this, TQT_SLOT( goNextMonth() ) ); + + connect( v, TQT_SIGNAL( monthSelected( int ) ), TQT_SIGNAL( monthSelected( int ) ) ); + connect( v, TQT_SIGNAL( yearSelected( int ) ), TQT_SIGNAL( yearSelected( int ) ) ); } void DateNavigatorContainer::setCalendar( Calendar *cal ) @@ -118,12 +121,21 @@ void DateNavigatorContainer::updateToday() } } +void DateNavigatorContainer::setUpdateNeeded() +{ + mNavigatorView->setUpdateNeeded(); + KDateNavigator *n; + for ( n = mExtraViews.first(); n; n = mExtraViews.next() ) { + n->setUpdateNeeded(); + } +} + void DateNavigatorContainer::updateView() { mNavigatorView->updateView(); KDateNavigator *n; - for( n = mExtraViews.first(); n; n = mExtraViews.next() ) { - n->updateView(); + for ( n = mExtraViews.first(); n; n = mExtraViews.next() ) { + n->setUpdateNeeded(); } } @@ -136,7 +148,7 @@ void DateNavigatorContainer::updateConfig() } } -void DateNavigatorContainer::selectDates( const DateList &dateList ) +void DateNavigatorContainer::selectDates( const DateList &dateList, const TQDate &preferredMonth ) { if ( !dateList.isEmpty() ) { TQDate start( dateList.first() ); @@ -151,11 +163,24 @@ void DateNavigatorContainer::selectDates( const DateList &dateList ) navlast = mNavigatorView->endDate(); navsecond = navfirst; } + + const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); + + // If the datelist crosses months we won't know which month to show + // so we read what's in preferredMonth + const bool changingMonth = ( preferredMonth.isValid() && + calSys->month( mNavigatorView->month() ) != calSys->month( preferredMonth ) ); + if ( start < navfirst // <- start should always be visible // end is not visible and we have a spare month at the beginning: - || ( end > navlast && start >= navsecond ) ) { - // Change the shown months so that the beginning of the date list is visible - setBaseDates( start ); + || ( end > navlast && start >= navsecond ) + || changingMonth ) { + + if ( preferredMonth.isValid() ) { + setBaseDates( preferredMonth ); + } else { + setBaseDates( start ); + } } mNavigatorView->selectDates( dateList ); @@ -202,7 +227,9 @@ void DateNavigatorContainer::resizeAllContents() if ( horizontalCount != mHorizontalCount || verticalCount != mVerticalCount ) { uint count = horizontalCount * verticalCount; - if ( count == 0 ) return; + if ( count == 0 ) { + return; + } while ( count > ( mExtraViews.count() + 1 ) ) { KDateNavigator *n = new KDateNavigator( this ); @@ -228,22 +255,30 @@ void DateNavigatorContainer::resizeAllContents() int width = (size().width() - margin*2) / horizontalCount; NavigatorBar *bar = mNavigatorView->navigatorBar(); - if ( horizontalCount > 1 ) bar->showButtons( true, false ); - else bar->showButtons( true, true ); + if ( horizontalCount > 1 ) { + bar->showButtons( true, false ); + } else { + bar->showButtons( true, true ); + } mNavigatorView->setGeometry( ( ( (KOGlobals::self()->reverseLayout())?(horizontalCount-1):0) * width ) + margin, margin, width, height ); + for( uint i = 0; i < mExtraViews.count(); ++i ) { int x = ( i + 1 ) % horizontalCount; int y = ( i + 1 ) / horizontalCount; KDateNavigator *view = mExtraViews.at( i ); bar = view->navigatorBar(); - if ( y > 0 ) bar->showButtons( false, false ); - else { - if ( x + 1 == horizontalCount ) bar->showButtons( false, true ); - else bar->showButtons( false, false ); + if ( y > 0 ) { + bar->showButtons( false, false ); + } else { + if ( x + 1 == horizontalCount ) { + bar->showButtons( false, true ); + } else { + bar->showButtons( false, false ); + } } view->setGeometry( ( ( (KOGlobals::self()->reverseLayout())?(horizontalCount-1-x):x) * width ) + margin, @@ -263,4 +298,41 @@ TQSize DateNavigatorContainer::sizeHint() const return mNavigatorView->sizeHint() + TQSize( margin, margin ); } +void DateNavigatorContainer::goNextMonth() +{ + const QPair<TQDate,TQDate> p = dateLimits( 1 ); + + emit nextMonthClicked( mNavigatorView->month(), + p.first, + p.second); +} + +void DateNavigatorContainer::goPrevMonth() +{ + const QPair<TQDate,TQDate> p = dateLimits( -1 ); + + emit prevMonthClicked( mNavigatorView->month(), + p.first, + p.second ); +} + +QPair<TQDate,TQDate> DateNavigatorContainer::dateLimits( int offset ) +{ + const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); + TQDate firstMonth, lastMonth; + if ( mExtraViews.isEmpty() ) { + lastMonth = mNavigatorView->month(); + } else { + lastMonth = mExtraViews.last()->month(); + } + + firstMonth = calSys->addMonths( mNavigatorView->month(), offset ); + lastMonth = calSys->addMonths( lastMonth, offset ); + + QPair<TQDate,TQDate> firstMonthBoundary = KODayMatrix::matrixLimits( firstMonth ); + QPair<TQDate,TQDate> lastMonthBoundary = KODayMatrix::matrixLimits( lastMonth ); + + return qMakePair( firstMonthBoundary.first, lastMonthBoundary.second ); +} + #include "datenavigatorcontainer.moc" diff --git a/korganizer/datenavigatorcontainer.h b/korganizer/datenavigatorcontainer.h index 2facad303..e30f19b42 100644 --- a/korganizer/datenavigatorcontainer.h +++ b/korganizer/datenavigatorcontainer.h @@ -43,29 +43,53 @@ class DateNavigatorContainer: public QFrame TQSize minimumSizeHint() const; TQSize sizeHint() const; - + void setUpdateNeeded(); public slots: - void selectDates( const KCal::DateList & ); + /** + preferredMonth is useful when the datelist crosses months, if different + from -1, it has the month that the kdatenavigator should show in case + of ambiguity + */ + void selectDates( const KCal::DateList &, const TQDate &preferredMonth = TQDate() ); void updateView(); void updateConfig(); void updateDayMatrix(); void updateToday(); + void goPrevMonth(); + void goNextMonth(); + signals: void datesSelected( const KCal::DateList & ); void incidenceDropped( Incidence *, const TQDate & ); void incidenceDroppedMove( Incidence *, const TQDate & ); - void weekClicked( const TQDate &); + void weekClicked( const TQDate & ); void goPrevious(); void goNext(); - void goNextMonth(); - void goPrevMonth(); - void goNextYear(); - void goPrevYear(); + void nextYearClicked(); + void prevYearClicked(); - void goMonth( int month ); + /** Signals that the previous month button has been clicked. + + @param currentMonth The month displayed on the first KDateNavigator. + DateNavigator doesn't know anything abouts months, it just has + a list of selected dates, so we must send this. + @param selectionLowerLimit The first date of the first KDateNavigator. + @param selectionUpperLimit The last date of the last KDateNavigator. + */ + void prevMonthClicked( const TQDate ¤tMonth, + const TQDate &selectionLowerLimit, + const TQDate &selectionUpperLimit ); + + void nextMonthClicked( const TQDate ¤tMonth, + const TQDate &selectionLowerLimit, + const TQDate &selectionUpperLimit ); + + void monthSelected( int month ); + + void yearSelected( int year ); protected: void resizeEvent( TQResizeEvent * ); @@ -79,6 +103,15 @@ class DateNavigatorContainer: public QFrame void resizeAllContents(); private: + /* Returns the first day of the first KDateNavigator, and the last day + of the last KDateNavigator. + + @param monthOffset If you have two KDateNavigators displaying January and February + and want to know the boundaries of, for e.g. displaying February and March, + use monthOffset = 1. + */ + QPair<TQDate,TQDate> dateLimits( int monthOffset = 0 ); + KDateNavigator *mNavigatorView; KCal::Calendar *mCalendar; diff --git a/korganizer/dcopcalendar.desktop b/korganizer/dcopcalendar.desktop index df5c098a8..ac1ccf4ee 100644 --- a/korganizer/dcopcalendar.desktop +++ b/korganizer/dcopcalendar.desktop @@ -29,7 +29,6 @@ Comment[hu]=HatáridÅ‘napló DCOP-felülettel Comment[is]=Skipuleggjari með DCOP viðmóti Comment[it]=Organizer con un'interfaccia DCOP Comment[ja]=DCOP インターフェースをæŒã¤ã‚ªãƒ¼ã‚¬ãƒŠã‚¤ã‚¶ -Comment[ka]=áƒáƒ გáƒáƒœáƒ˜áƒ–áƒáƒ¢áƒáƒ ი DCOP ინტერფეისით Comment[kk]=DCOP интерфейÑÑ‚Ñ– ҰйымдаÑтырғыш Comment[km]=កម្មវិធី​រៀបចំ​ដែល​មាន​ចំណុច​ប្រទាក់ DCOP Comment[lt]=TvarkyklÄ— su DCOP sÄ…saja diff --git a/korganizer/eventarchiver.cpp b/korganizer/eventarchiver.cpp index b5a9c0c98..c4adbf820 100644 --- a/korganizer/eventarchiver.cpp +++ b/korganizer/eventarchiver.cpp @@ -70,14 +70,15 @@ void EventArchiver::runAuto( Calendar* calendar, TQWidget* widget, bool withGUI run( calendar, limitDate, widget, withGUI, false ); } -void EventArchiver::run( Calendar* calendar, const TQDate& limitDate, TQWidget* widget, bool withGUI, bool errorIfNone ) +void EventArchiver::run( Calendar* calendar, const TQDate& limitDate, TQWidget* widget, bool withGUI, + bool errorIfNone ) { // We need to use rawEvents, otherwise events hidden by filters will not be archived. Incidence::List incidences; Event::List events; Todo::List todos; Journal::List journals; - + if ( KOPrefs::instance()->mArchiveEvents ) { events = calendar->rawEvents( TQDate( 1769, 12, 1 ), @@ -89,21 +90,37 @@ void EventArchiver::run( Calendar* calendar, const TQDate& limitDate, TQWidget* Todo::List t = calendar->rawTodos(); Todo::List::ConstIterator it; for( it = t.begin(); it != t.end(); ++it ) { - if ( (*it) && ( (*it)->isCompleted() ) && ( (*it)->completed().date() < limitDate ) ) { + const bool todoComplete = (*it) && + (*it)->isCompleted() && + ( (*it)->completed().date() < limitDate ); + + if ( todoComplete && !isSubTreeComplete( *it, limitDate ) ) { + // The to-do is complete but some sub-todos are not. + KMessageBox::information( + widget, + i18n( "Unable to archive to-do \"%1\" because at least one of its " + "sub-to-dos does not meet the archival requirements." ).arg( (*it)->summary() ), + i18n( "Archive To-do" ), + "UncompletedChildrenArchiveTodos" ); + } else if ( todoComplete ) { todos.append( *it ); } } } - + incidences = Calendar::mergeIncidenceList( events, todos, journals ); - - kdDebug(5850) << "EventArchiver: archiving incidences before " << limitDate << " -> " << incidences.count() << " incidences found." << endl; + + kdDebug(5850) << "EventArchiver: archiving incidences before " << limitDate << " -> " + << incidences.count() << " incidences found." << endl; if ( incidences.isEmpty() ) { - if ( withGUI && errorIfNone ) - KMessageBox::information( widget, i18n("There are no items before %1") - .arg(KGlobal::locale()->formatDate(limitDate)), - "ArchiverNoIncidences" ); + if ( withGUI && errorIfNone ) { + KMessageBox::information( + widget, + i18n( "There are no incidences available to archive before the specified cut-off date %1. " + "Archiving will not be performed." ).arg( KGlobal::locale()->formatDate( limitDate ) ), + "ArchiverNoIncidences" ); + } return; } @@ -222,4 +239,35 @@ void EventArchiver::archiveIncidences( Calendar* calendar, const TQDate& /*limit emit eventsDeleted(); } +bool EventArchiver::isSubTreeComplete( const Todo *todo, const TQDate &limitDate, + TQStringList checkedUids ) const +{ + if ( !todo || !todo->isCompleted() || todo->completed().date() >= limitDate ) { + return false; + } + + // This QList is only to prevent infinit recursion + if ( checkedUids.contains( todo->uid() ) ) { + // Probably will never happen, calendar.cpp checks for this + kdWarning() << "To-do hierarchy loop detected!"; + return false; + } + + checkedUids.append( todo->uid() ); + + Incidence::List::ConstIterator it; + const Incidence::List relations = todo->relations(); + + for( it = relations.begin(); it != relations.end(); ++it ) { + if ( (*it)->type() == "Todo" ) { + const Todo *t = static_cast<const Todo*>( *it ); + if ( !isSubTreeComplete( t, limitDate, checkedUids ) ) { + return false; + } + } + } + + return true; +} + #include "eventarchiver.moc" diff --git a/korganizer/eventarchiver.h b/korganizer/eventarchiver.h index 4d5a8544d..01897b7ec 100644 --- a/korganizer/eventarchiver.h +++ b/korganizer/eventarchiver.h @@ -77,8 +77,20 @@ class EventArchiver : public QObject private: void run( Calendar* calendar, const TQDate& limitDate, TQWidget* widget, bool withGUI, bool errorIfNone ); - void deleteIncidences( Calendar* calendar, const TQDate& limitDate, TQWidget* widget, const Incidence::List& incidences, bool withGUI ); - void archiveIncidences( Calendar* calendar, const TQDate& limitDate, TQWidget* widget, const Incidence::List& incidences, bool withGUI ); + void deleteIncidences( Calendar* calendar, const TQDate& limitDate, TQWidget* widget, + const Incidence::List& incidences, bool withGUI ); + void archiveIncidences( Calendar* calendar, const TQDate& limitDate, TQWidget* widget, + const Incidence::List& incidences, bool withGUI ); + + /** + * Checks if all to-dos under @p todo and including @p todo were completed before @p limitDate. + * If not, we can't archive this to-do. + * @param todo root of the sub-tree we are checking + * @param limitDate + * @param checkedUids used internaly to prevent infinit recursion due to invalid calendar files + */ + bool isSubTreeComplete( const Todo *todo, const TQDate &limitDate, + TQStringList checkedUids = TQStringList() ) const; }; #endif /* EVENTARCHIVER_H */ diff --git a/korganizer/exportwebdialog.cpp b/korganizer/exportwebdialog.cpp index c926ad053..869c5b963 100644 --- a/korganizer/exportwebdialog.cpp +++ b/korganizer/exportwebdialog.cpp @@ -85,6 +85,7 @@ ExportWebDialog::ExportWebDialog( HTMLExportSettings *settings, TQWidget *parent connect( this, TQT_SIGNAL( cancelClicked() ), TQT_SLOT( reject() ) ); readConfig(); + updateState(); } ExportWebDialog::~ExportWebDialog() @@ -139,16 +140,18 @@ void ExportWebDialog::setupGeneralPage() mGeneralPage = addPage( i18n("General") ); TQVBoxLayout *topLayout = new TQVBoxLayout(mGeneralPage, 10); - TQGroupBox *rangeGroup = new TQHGroupBox( i18n("Date Range"), mGeneralPage ); - topLayout->addWidget( rangeGroup ); - addWidDate( mSettings->dateStartItem(), rangeGroup ); - addWidDate( mSettings->dateEndItem(), rangeGroup ); + mDateRangeBox = new TQHGroupBox( i18n("Date Range"), mGeneralPage ); + topLayout->addWidget( mDateRangeBox ); + addWidDate( mSettings->dateStartItem(), mDateRangeBox ); + addWidDate( mSettings->dateEndItem(), mDateRangeBox ); TQButtonGroup *typeGroup = new TQVButtonGroup( i18n("View Type"), mGeneralPage ); topLayout->addWidget( typeGroup ); // addWidBool( mSettings->weekViewItem(), typeGroup ); - addWidBool( mSettings->monthViewItem(), typeGroup ); - addWidBool( mSettings->eventViewItem(), typeGroup ); + mMonthViewCheckBox = addWidBool( mSettings->monthViewItem(), typeGroup )->checkBox(); + connect( mMonthViewCheckBox, TQT_SIGNAL(toggled(bool)), TQT_SLOT(updateState()) ); + mEventListCheckBox = addWidBool( mSettings->eventViewItem(), typeGroup )->checkBox(); + connect( mEventListCheckBox, TQT_SIGNAL(toggled(bool)), TQT_SLOT(updateState()) ); addWidBool( mSettings->todoViewItem(), typeGroup ); // addWidBool( mSettings->journalViewItem(), typeGroup ); // addWidBool( mSettings->freeBusyViewItem(), typeGroup ); @@ -255,3 +258,11 @@ void ExportWebDialog::setupAdvancedPage() topLayout->addStretch(1); } */ + +void ExportWebDialog::updateState() +{ + const bool exportEvents = mMonthViewCheckBox->isChecked() || mEventListCheckBox->isChecked(); + mDateRangeBox->setEnabled( exportEvents ); + mEventPage->setEnabled( exportEvents ); +} + diff --git a/korganizer/exportwebdialog.h b/korganizer/exportwebdialog.h index 4d2dcd39c..27a0a9860 100644 --- a/korganizer/exportwebdialog.h +++ b/korganizer/exportwebdialog.h @@ -27,6 +27,7 @@ #include <libkdepim/kprefsdialog.h> class HTMLExportSettings; +class TQGroupBox; using namespace KCal; @@ -70,6 +71,9 @@ class ExportWebDialog : public KDialogBase, public KPrefsWidManager protected: virtual void usrReadConfig() {} virtual void usrWriteConfig() {} + + private slots: + void updateState(); private: HTMLExportSettings* mSettings; @@ -79,6 +83,10 @@ class ExportWebDialog : public KDialogBase, public KPrefsWidManager // TQFrame *mJournalPage; // TQFrame *mFreeBusyPage; // TQFrame *mAdvancedPage; + + TQCheckBox *mMonthViewCheckBox; + TQCheckBox *mEventListCheckBox; + TQGroupBox *mDateRangeBox; }; #endif // _EXPORTWEBDIALOG_H diff --git a/korganizer/freebusymanager.cpp b/korganizer/freebusymanager.cpp index 81b65a3b7..65f945bad 100644 --- a/korganizer/freebusymanager.cpp +++ b/korganizer/freebusymanager.cpp @@ -39,6 +39,8 @@ #include "koprefs.h" #include "mailscheduler.h" +#include "actionmanager.h" +#include "korganizer.h" #include <libkcal/incidencebase.h> #include <libkcal/attendee.h> @@ -76,6 +78,10 @@ FreeBusyDownloadJob::FreeBusyDownloadJob( const TQString &email, const KURL &url : TQObject( manager, name ), mManager( manager ), mEmail( email ) { KIO::TransferJob *job = KIO::get( url, false, false ); + //pass the mainwindow to the job so any prompts are active + KOrg::MainWindow *korg = ActionManager::findInstance( KURL() ); + job->setWindow( korg->topLevelWidget() ); + connect( job, TQT_SIGNAL( result( KIO::Job * ) ), TQT_SLOT( slotResult( KIO::Job * ) ) ); connect( job, TQT_SIGNAL( data( KIO::Job *, const TQByteArray & ) ), @@ -224,7 +230,7 @@ void FreeBusyManager::publishFreeBusy() // Already uploading? Skip this one then. if ( mUploadingFreeBusy ) return; - KURL targetURL ( KOPrefs::instance()->freeBusyPublishUrl() ); + KURL targetURL( KOPrefs::instance()->freeBusyPublishUrl() ); if ( targetURL.isEmpty() ) { KMessageBox::sorry( 0, i18n( "<qt>No URL configured for uploading your free/busy list. Please " @@ -329,6 +335,10 @@ void FreeBusyManager::publishFreeBusy() true /*overwrite*/, false /*don't resume*/, false /*don't show progress info*/ ); + //pass the mainwindow to the job so any prompts are active + KOrg::MainWindow *korg = ActionManager::findInstance( KURL() ); + job->setWindow( korg->topLevelWidget() ); + connect( job, TQT_SIGNAL( result( KIO::Job * ) ), TQT_SLOT( slotUploadFreeBusyResult( KIO::Job * ) ) ); } @@ -386,11 +396,10 @@ bool FreeBusyManager::processRetrieveQueue() KURL sourceURL = freeBusyUrl( email ); - DEBUG_5850 << "FreeBusyManager::processRetrieveQueue(): url: " << sourceURL - << endl; + kdDebug(5850) << "FreeBusyManager::processRetrieveQueue(): url: " << sourceURL << endl; if ( !sourceURL.isValid() ) { - DEBUG_5850 << "Invalid FB URL\n"; + kdDebug(5850) << "Invalid FB URL\n"; slotFreeBusyDownloadError( email ); return false; } @@ -429,6 +438,43 @@ void FreeBusyManager::cancelRetrieval() mRetrieveQueue.clear(); } +KURL replaceVariablesURL( const KURL &url, const TQString &email ) +{ + TQString emailName, emailHost; + int emailpos = email.find( '@' ); + if( emailpos >= 0 ) { + emailName = email.left( emailpos ); + emailHost = email.mid( emailpos + 1 ); + } + + TQString saveStr = url.path(); + saveStr.replace( TQRegExp( "%[Ee][Mm][Aa][Ii][Ll]%" ), email ); + saveStr.replace( TQRegExp( "%[Nn][Aa][Mm][Ee]%" ), emailName ); + saveStr.replace( TQRegExp( "%[Ss][Ee][Rr][Vv][Ee][Rr]%" ), emailHost ); + + KURL retUrl( url ); + retUrl.setPath( saveStr ); + return retUrl; +} + +bool fbExists( const KURL &url ) +{ + // We need this function because using KIO::NetAccess::exists() + // is useless for the http and https protocols. And getting back + // arbitrary data is also useless because a server can respond back + // with a "no such document" page. So we need smart checking. + + KIO::Job *job = KIO::get( url, false, false ); + TQByteArray data; + if ( KIO::NetAccess::synchronousRun( job, 0, &data ) ) { + TQString dataStr ( data ); + if ( dataStr.contains( "BEGIN:VCALENDAR" ) ) { + return true; + } + } + return false; +} + KURL FreeBusyManager::freeBusyUrl( const TQString &email ) { DEBUG_5850 << "FreeBusyManager::freeBusyUrl(): " << email << endl; @@ -440,9 +486,15 @@ KURL FreeBusyManager::freeBusyUrl( const TQString &email ) cfg.setGroup( email ); TQString url = cfg.readEntry( "url" ); if ( !url.isEmpty() ) { - DEBUG_5850 << "found cached url: " << url << endl; - return KURL( url ); + kdDebug(5850) << "found cached url: " << url << endl; + KURL cachedURL( url ); + if ( KOPrefs::instance()->thatIsMe( email ) ) { + cachedURL.setUser( KOPrefs::instance()->mFreeBusyRetrieveUser ); + cachedURL.setPass( KOPrefs::instance()->mFreeBusyRetrievePassword ); + } + return replaceVariablesURL( cachedURL, email ); } + // Try with the url configurated by preferred email in kaddressbook KABC::Addressee::List list= KABC::StdAddressBook::self( true )->findByEmail( email ); KABC::Addressee::List::Iterator it; @@ -450,14 +502,14 @@ KURL FreeBusyManager::freeBusyUrl( const TQString &email ) for ( it = list.begin(); it != list.end(); ++it ) { pref = (*it).preferredEmail(); if ( !pref.isEmpty() && pref != email ) { - kdDebug( 5850 ) << "FreeBusyManager::freeBusyUrl():" << - "Preferred email of " << email << " is " << pref << endl; + kdDebug(5850) << "FreeBusyManager::freeBusyUrl():" + << "Preferred email of " << email << " is " << pref << endl; cfg.setGroup( pref ); url = cfg.readEntry ( "url" ); if ( !url.isEmpty() ) { - kdDebug( 5850 ) << "FreeBusyManager::freeBusyUrl():" << - "Taken url from preferred email:" << url << endl; - return KURL( url ); + kdDebug(5850) << "FreeBusyManager::freeBusyUrl():" + << "Taken url from preferred email:" << url << endl; + return replaceVariablesURL( KURL( url ), email ); } } } @@ -487,54 +539,81 @@ KURL FreeBusyManager::freeBusyUrl( const TQString &email ) // Don't try to fetch free/busy data for users not on the specified servers // This tests if the hostnames match, or one is a subset of the other const TQString hostDomain = sourceURL.host(); - if ( hostDomain != emailHost && !hostDomain.endsWith( '.' + emailHost ) - && !emailHost.endsWith( '.' + hostDomain ) ) { + if ( hostDomain != emailHost && + !hostDomain.endsWith( '.' + emailHost ) && + !emailHost.endsWith( '.' + hostDomain ) ) { // Host names do not match - DEBUG_5850 << "Host '" << sourceURL.host() << "' doesn't match email '" - << email << '\'' << endl; + kdDebug(5850) << "Host '" << sourceURL.host() << "' doesn't match email '" << email << endl; return KURL(); } } - // This should work with anything thrown at it, not just Kolab - // Notice that Kolab URLs are just entered as the base address, e.g. http://server.com/mykolab/ - // This means that if the trailing slash is not entered, we can treat this as a custom, non-Kolab URL! - // In that case, just pass it on through with substitution for %u and %d - // TODO: May want an explicit configuration option in kogroupwareprefspage.ui for this - if ((sourceURL.url().endsWith("/", true) == false) || (sourceURL.url().contains("%25u", true)) || (sourceURL.url().contains("%25d", true))) { - // A generic URL, substitute %u and %d - sourceURL = sourceURL.url().replace("%25u", emailName, true); - sourceURL = sourceURL.url().replace("%25d", emailHost, true); - sourceURL.setUser( KOPrefs::instance()->mFreeBusyRetrieveUser ); - sourceURL.setPass( KOPrefs::instance()->mFreeBusyRetrievePassword ); - return sourceURL; + if ( sourceURL.url().contains( TQRegExp( "\\.[xiv]fb$" ) ) ) { // user specified a fullpath + // do variable string replacements to the URL (MS Outlook style) + KURL fullpathURL = replaceVariablesURL( sourceURL, email ); + + // This should work with anything thrown at it, not just Kolab + // Notice that Kolab URLs are just entered as the base address, e.g. http://server.com/mykolab/ + // This means that if the trailing slash is not entered, we can treat this as a custom, non-Kolab URL! + // In that case, just pass it on through with substitution for %u and %d + // TODO: May want an explicit configuration option in kogroupwareprefspage.ui for this + if ((fullpathURL.url().endsWith("/", true) == false) || (fullpathURL.url().contains("%25u", true)) || (fullpathURL.url().contains("%25d", true))) { + // A generic URL, substitute %u and %d + fullpathURL = fullpathURL.url().replace("%25u", emailName, true); + fullpathURL = fullpathURL.url().replace("%25d", emailHost, true); + } + else { + // This is (probably) a Kolab URL! + } + + // set the User and Password part of the URL + fullpathURL.setUser( KOPrefs::instance()->mFreeBusyRetrieveUser ); + fullpathURL.setPass( KOPrefs::instance()->mFreeBusyRetrievePassword ); + + // no need to cache this URL as this is pretty fast to get from the config value. + + // return the fullpath URL + return fullpathURL; } - else { - // This is (probably) a Kolab URL! - DEBUG_5850 << "Server FreeBusy url: " << sourceURL << endl; - if ( KOPrefs::instance()->mFreeBusyFullDomainRetrieval ) - sourceURL.setFileName( email + ".ifb" ); - else - sourceURL.setFileName( emailName + ".ifb" ); - sourceURL.setUser( KOPrefs::instance()->mFreeBusyRetrieveUser ); - sourceURL.setPass( KOPrefs::instance()->mFreeBusyRetrievePassword ); - - DEBUG_5850 << "Results in generated: " << sourceURL << endl; - return sourceURL; + + // else we search for a fb file in the specified URL with known possible extensions + + TQStringList extensions; + extensions << "xfb" << "ifb" << "vfb"; + TQStringList::ConstIterator ext; + for ( ext = extensions.constBegin(); ext != extensions.constEnd(); ++ext ) { + // build a url for this extension + sourceURL = KOPrefs::instance()->mFreeBusyRetrieveUrl; + KURL dirURL = replaceVariablesURL( sourceURL, email ); + if ( KOPrefs::instance()->mFreeBusyFullDomainRetrieval ) { + dirURL.addPath( email + '.' + (*ext) ); + } else { + dirURL.addPath( emailName + '.' + (*ext ) ); + } + dirURL.setUser( KOPrefs::instance()->mFreeBusyRetrieveUser ); + dirURL.setPass( KOPrefs::instance()->mFreeBusyRetrievePassword ); + if ( fbExists( dirURL ) ) { + // write the URL to the cache + cfg.setGroup( email ); + cfg.writeEntry( "url", dirURL.prettyURL() ); // prettyURL() does not write user nor password + return dirURL; + } } + + return KURL(); } KCal::FreeBusy *FreeBusyManager::iCalToFreeBusy( const TQCString &data ) { - DEBUG_5850 << "FreeBusyManager::iCalToFreeBusy()" << endl; - DEBUG_5850 << data << endl; + kdDebug(5850) << "FreeBusyManager::iCalToFreeBusy()" << endl; + kdDebug(5850) << data << endl; TQString freeBusyVCal = TQString::fromUtf8( data ); KCal::FreeBusy *fb = mFormat.parseFreeBusy( freeBusyVCal ); if ( !fb ) { - DEBUG_5850 << "FreeBusyManager::iCalToFreeBusy(): Error parsing free/busy" + kdDebug(5850) << "FreeBusyManager::iCalToFreeBusy(): Error parsing free/busy" << endl; - DEBUG_5850 << freeBusyVCal << endl; + kdDebug(5850) << freeBusyVCal << endl; } return fb; } @@ -553,7 +632,7 @@ FreeBusy *FreeBusyManager::loadFreeBusy( const TQString &email ) TQFile f( fbd + "/" + email + ".ifb" ); if ( !f.exists() ) { DEBUG_5850 << "FreeBusyManager::loadFreeBusy() " << f.name() - << " doesn't exist." << endl; + << " doesn't exist." << endl; return 0; } diff --git a/korganizer/freebusymanager.h b/korganizer/freebusymanager.h index a91d9f36d..a6f4f6cec 100644 --- a/korganizer/freebusymanager.h +++ b/korganizer/freebusymanager.h @@ -117,7 +117,7 @@ class FreeBusyManager : public TQObject, public KCal::FreeBusyCache KURL freeBusyUrl( const TQString &email ); /** - Return directory used for stroing free/busy information. + Return directory used for storing free/busy information. */ TQString freeBusyDir(); @@ -173,7 +173,6 @@ class FreeBusyManager : public TQObject, public KCal::FreeBusyCache int mTimerID; bool mUploadingFreeBusy; bool mBrokenUrl; - }; #endif diff --git a/korganizer/importdialog.cpp b/korganizer/importdialog.cpp index f1181225d..5f4dce6a5 100644 --- a/korganizer/importdialog.cpp +++ b/korganizer/importdialog.cpp @@ -37,15 +37,15 @@ using namespace KCal; -ImportDialog::ImportDialog( const KURL &url, TQWidget *parent ) - : KDialogBase( Plain, i18n("Import Calendar"), Ok | Cancel, Ok, parent, +ImportDialog::ImportDialog( const KURL &url, TQWidget *parent, bool isPart ) + : KDialogBase( Plain, i18n("Import Calendar/Event"), Ok | Cancel, Ok, parent, 0, true, true ), mUrl( url ) { TQFrame *topFrame = plainPage(); TQVBoxLayout *topLayout = new TQVBoxLayout( topFrame, 0, spacingHint() ); - TQString txt = i18n("Import calendar at '%1' into KOrganizer.") + TQString txt = i18n("Import calendar/event at '%1' into KOrganizer.") .arg( mUrl.prettyURL() ); topLayout->addWidget( new TQLabel( txt, topFrame ) ); @@ -59,7 +59,7 @@ ImportDialog::ImportDialog( const KURL &url, TQWidget *parent ) mMergeButton = new TQRadioButton( i18n("Merge into existing calendar"), radioBox ); - mOpenButton = new TQRadioButton( i18n("Open in separate window"), radioBox ); + mOpenButton = isPart ? 0 : new TQRadioButton( i18n("Open in separate window"), radioBox ); mAddButton->setChecked( true ); } @@ -77,7 +77,7 @@ void ImportDialog::slotOk() } else if ( mMergeButton->isChecked() ) { // emit a signal to action manager to merge mUrl into the current calendar emit openURL( mUrl, true ); - } else if ( mOpenButton->isChecked() ) { + } else if ( mOpenButton && mOpenButton->isChecked() ) { // emit a signal to the action manager to open mUrl in a separate window emit newWindow( mUrl ); } else { diff --git a/korganizer/importdialog.h b/korganizer/importdialog.h index ae92ae0b6..75d5cb1a7 100644 --- a/korganizer/importdialog.h +++ b/korganizer/importdialog.h @@ -36,7 +36,7 @@ class ImportDialog : public KDialogBase { Q_OBJECT public: - ImportDialog( const KURL &url, TQWidget *parent ); + ImportDialog( const KURL &url, TQWidget *parent, bool isPart ); ~ImportDialog(); public slots: diff --git a/korganizer/incidencechanger.cpp b/korganizer/incidencechanger.cpp index 46be25ba7..1c41c5cd9 100644 --- a/korganizer/incidencechanger.cpp +++ b/korganizer/incidencechanger.cpp @@ -23,6 +23,7 @@ */ #include "incidencechanger.h" +#include "koglobals.h" #include "koprefs.h" #include "kogroupware.h" #include "mailscheduler.h" @@ -33,24 +34,36 @@ #include <kmessagebox.h> #include <klocale.h> +bool IncidenceChanger::beginChange( Incidence *incidence, + ResourceCalendar *res, const TQString &subRes ) +{ + if ( !incidence ) { + return false; + } + kdDebug(5850) << "IncidenceChanger::beginChange for incidence \"" + << incidence->summary() << "\"" << endl; -bool IncidenceChanger::beginChange( Incidence * incidence ) -{ - if ( !incidence ) return false; -kdDebug(5850)<<"IncidenceChanger::beginChange for incidence \""<<incidence->summary()<<"\""<<endl; - return mCalendar->beginChange( incidence ); + CalendarResources *calRes = dynamic_cast<CalendarResources*>( mCalendar ); + if ( !calRes ) { + return false; + } + + return calRes->beginChange( incidence, res, subRes ); } -bool IncidenceChanger::sendGroupwareMessage( Incidence *incidence, KCal::Scheduler::Method method, bool deleting ) +bool IncidenceChanger::sendGroupwareMessage( Incidence *incidence, + KCal::Scheduler::Method method, + KOGlobals::HowChanged action, + TQWidget *parent ) { if ( KOPrefs::instance()->thatIsMe( incidence->organizer().email() ) && incidence->attendeeCount()>0 && !KOPrefs::instance()->mUseGroupwareCommunication ) { emit schedule( method, incidence ); return true; } else if( KOPrefs::instance()->mUseGroupwareCommunication ) { - // FIXME: Find a widget to use as parent, instead of 0 - return KOGroupware::instance()->sendICalMessage( 0, method, incidence, deleting ); + return + KOGroupware::instance()->sendICalMessage( parent, method, incidence, action, false ); } return true; } @@ -66,7 +79,7 @@ void IncidenceChanger::cancelAttendees( Incidence *incidence ) // them?", which isn't helpful at all in this situation. Afterwards, it // would only call the MailScheduler::performTransaction, so do this // manually. - // FIXME: Groupware schedulling should be factored out to it's own class + // FIXME: Groupware scheduling should be factored out to it's own class // anyway KCal::MailScheduler scheduler( mCalendar ); scheduler.performTransaction( incidence, Scheduler::Cancel ); @@ -74,23 +87,36 @@ void IncidenceChanger::cancelAttendees( Incidence *incidence ) } } -bool IncidenceChanger::endChange( Incidence *incidence ) +bool IncidenceChanger::endChange( Incidence *incidence, + ResourceCalendar *res, const TQString &subRes ) { // FIXME: if that's a groupware incidence, and I'm not the organizer, // send out a mail to the organizer with a counterproposal instead // of actually changing the incidence. Then no locking is needed. // FIXME: if that's a groupware incidence, and the incidence was // never locked, we can't unlock it with endChange(). - if ( !incidence ) return false; - // kdDebug(5850)<<"IncidenceChanger::endChange for incidence \""<<incidence->summary()<<"\""<<endl; - return mCalendar->endChange( incidence ); + + if ( !incidence ) { + return false; + } + + kdDebug(5850) << "IncidenceChanger::endChange for incidence \"" + << incidence->summary() << "\"" << endl; + + CalendarResources *calRes = dynamic_cast<CalendarResources*>( mCalendar ); + if ( !calRes ) { + return false; + } + + return calRes->endChange( incidence, res, subRes ); } -bool IncidenceChanger::deleteIncidence( Incidence *incidence ) +bool IncidenceChanger::deleteIncidence( Incidence *incidence, TQWidget *parent ) { if ( !incidence ) return true; kdDebug(5850)<<"IncidenceChanger::deleteIncidence for incidence \""<<incidence->summary()<<"\""<<endl; - bool doDelete = sendGroupwareMessage( incidence, KCal::Scheduler::Cancel ); + bool doDelete = sendGroupwareMessage( incidence, KCal::Scheduler::Cancel, + KOGlobals::INCIDENCEDELETED, parent ); if( doDelete ) { // @TODO: let Calendar::deleteIncidence do the locking... Incidence* tmp = incidence->clone(); @@ -113,29 +139,52 @@ kdDebug(5850)<<"IncidenceChanger::deleteIncidence for incidence \""<<incidence-> } } - if ( notifyOrganizer ) { + if ( !KOGroupware::instance()->doNotNotify() && notifyOrganizer ) { KCal::MailScheduler scheduler( mCalendar ); scheduler.performTransaction( tmp, Scheduler::Reply ); } + //reset the doNotNotify flag + KOGroupware::instance()->setDoNotNotify( false ); } + emit incidenceDeleted( incidence ); } - emit incidenceDeleted( incidence ); return doDelete; } -bool IncidenceChanger::cutIncidence( Incidence *incidence ) +bool IncidenceChanger::cutIncidences( const Incidence::List &incidences, + TQWidget *parent ) { - if ( !incidence ) return true; -kdDebug(5850)<<"IncidenceChanger::deleteIncidence for incidence \""<<incidence->summary()<<"\""<<endl; - bool doDelete = sendGroupwareMessage( incidence, KCal::Scheduler::Cancel ); - if( doDelete ) { - // @TODO: the factory needs to do the locking! - DndFactory factory( mCalendar ); - emit incidenceToBeDeleted( incidence ); - factory.cutIncidence( incidence ); - emit incidenceDeleted( incidence ); + Incidence::List::ConstIterator it; + bool doDelete = true; + Incidence::List incsToCut; + for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) { + if ( *it ) { + doDelete = sendGroupwareMessage( *it, KCal::Scheduler::Cancel, + KOGlobals::INCIDENCEDELETED, parent ); + if ( doDelete ) { + emit incidenceToBeDeleted( *it ); + incsToCut.append( *it ); + } + } + } + + DndFactory factory( mCalendar ); + + if ( factory.cutIncidences( incsToCut ) ) { + for ( it = incsToCut.constBegin(); it != incsToCut.constEnd(); ++it ) { + emit incidenceDeleted( *it ); + } + return !incsToCut.isEmpty(); + } else { + return false; } - return doDelete; +} + +bool IncidenceChanger::cutIncidence( Incidence *incidence, TQWidget *parent ) +{ + Incidence::List incidences; + incidences.append( incidence ); + return cutIncidences( incidences, parent ); } class IncidenceChanger::ComparisonVisitor : public IncidenceBase::Visitor @@ -277,37 +326,35 @@ bool IncidenceChanger::myAttendeeStatusChanged( Incidence *oldInc, Incidence *ne } bool IncidenceChanger::changeIncidence( Incidence *oldinc, Incidence *newinc, - int action ) + KOGlobals::WhatChanged action, + TQWidget *parent ) { kdDebug(5850)<<"IncidenceChanger::changeIncidence for incidence \""<<newinc->summary()<<"\" ( old one was \""<<oldinc->summary()<<"\")"<<endl; - if( incidencesEqual( newinc, oldinc ) ) { + if ( incidencesEqual( newinc, oldinc ) ) { // Don't do anything kdDebug(5850) << "Incidence not changed\n"; } else { kdDebug(5850) << "Incidence changed\n"; - bool statusChanged = myAttendeeStatusChanged( oldinc, newinc ); + bool attendeeStatusChanged = myAttendeeStatusChanged( oldinc, newinc ); int revision = newinc->revision(); newinc->setRevision( revision + 1 ); // FIXME: Use a generic method for this! Ideally, have an interface class // for group scheduling. Each implementation could then just do what // it wants with the event. If no groupware is used,use the null // pattern... - bool revert = KOPrefs::instance()->mUseGroupwareCommunication; - if ( revert && - KOGroupware::instance()->sendICalMessage( 0, - KCal::Scheduler::Request, - newinc, false, statusChanged ) ) { - // Accept the event changes - revert = false; + bool success = true; + if ( KOPrefs::instance()->mUseGroupwareCommunication ) { + success = KOGroupware::instance()->sendICalMessage( + parent, + KCal::Scheduler::Request, + newinc, KOGlobals::INCIDENCEEDITED, attendeeStatusChanged ); } - if ( action<0 ) { - emit incidenceChanged( oldinc, newinc ); - } else { + if ( success ) { + // Accept the event changes emit incidenceChanged( oldinc, newinc, action ); - } - - if ( revert ) { + } else { + // revert changes assignIncidence( newinc, oldinc ); return false; } @@ -315,41 +362,97 @@ kdDebug(5850)<<"IncidenceChanger::changeIncidence for incidence \""<<newinc->sum return true; } -bool IncidenceChanger::addIncidence( Incidence *incidence, TQWidget *parent ) +bool IncidenceChanger::addIncidence( Incidence *incidence, + ResourceCalendar *res, const TQString &subRes, + TQWidget *parent ) { -kdDebug(5850)<<"IncidenceChanger::addIncidence for incidence \""<<incidence->summary()<<"\""<<endl; - if ( KOPrefs::instance()->mUseGroupwareCommunication ) { - if ( !KOGroupware::instance()->sendICalMessage( parent, - KCal::Scheduler::Request, - incidence ) ) { - kdError() << "sendIcalMessage failed." << endl; - } + CalendarResources *stdcal = dynamic_cast<CalendarResources *>( mCalendar ); + if( stdcal && !stdcal->hasCalendarResources() ) { + KMessageBox::sorry( + parent, + i18n( "No calendars found, unable to save %1 \"%2\"." ). + arg( i18n( incidence->type() ) ). + arg( incidence->summary() ) ); + kdDebug(5850) << "IncidenceChanger: No calendars found" << endl; + return false; } + // FIXME: This is a nasty hack, since we need to set a parent for the // resource selection dialog. However, we don't have any UI methods // in the calendar, only in the CalendarResources::DestinationPolicy // So we need to type-cast it and extract it from the CalendarResources - CalendarResources *stdcal = dynamic_cast<CalendarResources*>(mCalendar); TQWidget *tmpparent = 0; if ( stdcal ) { tmpparent = stdcal->dialogParentWidget(); stdcal->setDialogParentWidget( parent ); } - bool success = mCalendar->addIncidence( incidence ); - if ( stdcal ) { - // Reset the parent widget, otherwise we'll end up with pointers to deleted - // widgets sooner or later - stdcal->setDialogParentWidget( tmpparent ); + + // If a ResourceCalendar isn't provided, then try to compute one + // along with any subResource from the incidence. + ResourceCalendar *pRes = res; + TQString pSubRes = subRes; + TQString pResName; + if ( !pRes ) { + if ( stdcal ) { + pRes = stdcal->resource( incidence ); + if ( pRes ) { + pResName = pRes->resourceName(); + if ( pRes->canHaveSubresources() ) { + pSubRes = pRes->subresourceIdentifier( incidence ); + pResName = pRes->labelForSubresource( pSubRes ); + } + } + } + } + + bool success = false; + if ( stdcal && pRes && !pRes->readOnly() && pRes->subresourceWritable( pSubRes ) ) { + success = stdcal->addIncidence( incidence, pRes, pSubRes ); + } else { + success = mCalendar->addIncidence( incidence ); } + if ( !success ) { - KMessageBox::sorry( parent, i18n("Unable to save %1 \"%2\".") - .arg( i18n( incidence->type() ) ) - .arg( incidence->summary() ) ); + // We can have a failure if the user pressed [cancel] in the resource + // selectdialog, so check the exception. + ErrorFormat *e = stdcal ? stdcal->exception() : 0; + if ( !e || + ( e && ( e->errorCode() != KCal::ErrorFormat::UserCancel && + e->errorCode() != KCal::ErrorFormat::NoWritableFound ) ) ) { + TQString errMessage; + if ( pResName.isEmpty() ) { + errMessage = i18n( "Unable to save %1 \"%2\"." ). + arg( i18n( incidence->type() ) ). + arg( incidence->summary() ); + } else { + errMessage = i18n( "Unable to save %1 \"%2\" to calendar %3." ). + arg( i18n( incidence->type() ) ). + arg( incidence->summary() ). + arg( pResName ); + } + KMessageBox::sorry( parent, errMessage ); + } + kdDebug(5850) << "IncidenceChanger: Can't add incidence" << endl; return false; } + + if ( KOPrefs::instance()->mUseGroupwareCommunication ) { + if ( !KOGroupware::instance()->sendICalMessage( + parent, + KCal::Scheduler::Request, + incidence, KOGlobals::INCIDENCEADDED, false ) ) { + KMessageBox::sorry( + parent, + i18n( "Attempt to send the scheduling message failed. " + "Please check your Group Scheduling settings. " + "Contact your system administrator for more help.") ); + } + } + emit incidenceAdded( incidence ); return true; } + #include "incidencechanger.moc" #include "incidencechangerbase.moc" diff --git a/korganizer/incidencechanger.h b/korganizer/incidencechanger.h index 1423b4888..afa550646 100644 --- a/korganizer/incidencechanger.h +++ b/korganizer/incidencechanger.h @@ -26,33 +26,53 @@ #include "korganizer/incidencechangerbase.h" +namespace KCal { + class ResourceCalendar; +} + class IncidenceChanger : public KOrg::IncidenceChangerBase { -Q_OBJECT -public: - IncidenceChanger( Calendar*cal, TQObject *parent ) : IncidenceChangerBase( cal, parent ) {} - ~IncidenceChanger() {} - - bool beginChange( Incidence * incidence ); - bool sendGroupwareMessage( Incidence *incidence, KCal::Scheduler::Method method, bool deleting = false ); - bool endChange( Incidence *incidence ); - - bool addIncidence( Incidence *incidence, TQWidget *parent = 0 ); - bool changeIncidence( Incidence *oldinc, Incidence *newinc, int action = -1 ); - bool deleteIncidence( Incidence *incidence ); - - bool cutIncidence( Incidence *incidence ); - static bool incidencesEqual( Incidence *inc1, Incidence *inc2 ); - static bool assignIncidence( Incidence *inc1, Incidence *inc2 ); -public slots: - void cancelAttendees( Incidence *incidence ); - -protected: - bool myAttendeeStatusChanged( Incidence *oldInc, Incidence *newInc ); - -private: - class ComparisonVisitor; - class AssignmentVisitor; + Q_OBJECT + public: + IncidenceChanger( Calendar *cal, TQObject *parent ) + : IncidenceChangerBase( cal, parent ) {} + ~IncidenceChanger() {} + + bool beginChange( Incidence *incidence, + ResourceCalendar *res, const TQString &subRes ); + + bool sendGroupwareMessage( Incidence *incidence, + KCal::Scheduler::Method method, + KOGlobals::HowChanged action, + TQWidget *parent ); + + bool endChange( Incidence *incidence, + ResourceCalendar *res, const TQString &subRes ); + + bool addIncidence( Incidence *incidence, + ResourceCalendar *res, const TQString &subRes, + TQWidget *parent ); + + bool changeIncidence( Incidence *oldinc, Incidence *newinc, + KOGlobals::WhatChanged, TQWidget *parent ); + + bool deleteIncidence( Incidence *incidence, TQWidget *parent ); + + bool cutIncidences( const Incidence::List &incidences, TQWidget *parent ); + bool cutIncidence( Incidence *incidence, TQWidget *parent ); + + static bool incidencesEqual( Incidence *inc1, Incidence *inc2 ); + static bool assignIncidence( Incidence *inc1, Incidence *inc2 ); + + public slots: + void cancelAttendees( Incidence *incidence ); + + protected: + bool myAttendeeStatusChanged( Incidence *oldInc, Incidence *newInc ); + + private: + class ComparisonVisitor; + class AssignmentVisitor; }; #endif diff --git a/korganizer/interfaces/calendar/calendardecoration.desktop b/korganizer/interfaces/calendar/calendardecoration.desktop index e9763878e..b44db80ad 100644 --- a/korganizer/interfaces/calendar/calendardecoration.desktop +++ b/korganizer/interfaces/calendar/calendardecoration.desktop @@ -28,7 +28,6 @@ Comment[hu]=Naptármegjelenési bÅ‘vÃtÅ‘modul Comment[is]=Ãforrit til að skreyta texta dagatals Comment[it]=Plugin di decorazione del calendario Comment[ja]=カレンダー装飾プラグイン -Comment[ka]=კáƒáƒšáƒ”ნდრის გáƒáƒ¤áƒáƒ მების მáƒáƒ“ული Comment[kk]=Күнтізбені безендіру модулі Comment[km]=កម្មវិធី​ជំនួយ​សម្រាប់​ážáž»áž”ážáŸ‚ង​ប្រážáž·áž‘áž·áž“ Comment[lt]=vCalendar dekoracijų priedas diff --git a/korganizer/interfaces/calendar/calendarplugin.desktop b/korganizer/interfaces/calendar/calendarplugin.desktop index 765fced76..d5c0ab560 100644 --- a/korganizer/interfaces/calendar/calendarplugin.desktop +++ b/korganizer/interfaces/calendar/calendarplugin.desktop @@ -30,7 +30,6 @@ Comment[hu]=NaptárkezelÅ‘ bÅ‘vÃtÅ‘modul Comment[is]=Dagatals Ãforrit Comment[it]=Plugin calendario Comment[ja]=カレンダープラグイン -Comment[ka]=კáƒáƒšáƒ”ნდრის მáƒáƒ“ული Comment[kk]=Күнтізбе модулі Comment[km]=កម្មវិធី​ជំនួយ​ប្រážáž·áž‘áž·áž“ Comment[ko]=ë‹¬ë ¥ í”ŒëŸ¬ê·¸ì¸ @@ -61,8 +60,7 @@ Comment[tg]=Модул барои тақвимот Comment[th]=โปรà¹à¸à¸£à¸¡à¹€à¸ªà¸£à¸´à¸¡à¸šà¸±à¸™à¸—ึà¸à¸›à¸£à¸°à¸ˆà¸³à¸§à¸±à¸™ Comment[tr]=Takvim Eklentisi Comment[uk]=Втулок ÐºÐ°Ð»ÐµÐ½Ð´Ð°Ñ€Ñ -Comment[uz]=Kalendar plagini -Comment[uz@cyrillic]=Календар плагини +Comment[uz]=Календар плагини Comment[ven]=U pulaga ha khalenda Comment[vi]=Plugin lịch Comment[xh]=Ikhalenda ye Plugin diff --git a/korganizer/interfaces/korganizer/baseview.h b/korganizer/interfaces/korganizer/baseview.h index 64fbd72b5..6d60a0a5f 100644 --- a/korganizer/interfaces/korganizer/baseview.h +++ b/korganizer/interfaces/korganizer/baseview.h @@ -2,7 +2,7 @@ This file is part of the KOrganizer interfaces. Copyright (c) 1999,2001,2003 Cornelius Schumacher <schumacher@kde.org> - Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -38,17 +38,19 @@ using namespace KCal; -namespace KCal { class Calendar; } +namespace KCal { + class Calendar; + class ResourceCalendar; +} namespace KOrg { - /** - This class provides an interface for all views being displayed within the main - calendar view. It has functions to update the view, to specify date range and - other display parameter and to return selected objects. An important class, - which inherits KOBaseView is KOEventView, which provides the interface for all - views of event data like the agenda or the month view. + This class provides an interface for all views being displayed within the + main calendar view. It has functions to update the view, to specify date + range and other display parameter and to return selected objects. An + important class, which inherits KOBaseView is KOEventView, which provides + the interface for all views of event data like the agenda or the month view. @short Base class for calendar views @author Preston Brown, Cornelius Schumacher @@ -56,7 +58,7 @@ namespace KOrg { */ class KDE_EXPORT BaseView : public QWidget { - Q_OBJECT + Q_OBJECT public: /** Constructs a view. @@ -66,21 +68,41 @@ class KDE_EXPORT BaseView : public QWidget @param parent parent widget. @param name name of this widget. */ - BaseView( Calendar *cal, TQWidget *parent = 0, - const char *name = 0 ) - : TQWidget( parent, name ), mCalendar( cal ), mChanger( 0 ) {} + BaseView( Calendar *cal, TQWidget *parent = 0, const char *name = 0 ) + : TQWidget( parent, name ), + mReadOnly( false ), mCalendar( cal ), mResource( 0 ), mChanger( 0 ) {} /** Destructor. Views will do view-specific cleanups here. */ virtual ~BaseView() {} + /** Flag indicating if the view is read-only */ + void setReadOnly( bool readonly ) { mReadOnly = readonly; } + bool readOnly() { return mReadOnly; } + virtual void setCalendar( Calendar *cal ) { mCalendar = cal; } /** Return calendar object of this view. */ virtual Calendar *calendar() { return mCalendar; } + virtual void setResource( ResourceCalendar *res, const TQString &subResource ) + { + mResource = res; + mSubResource = subResource; + } + + /** + Return resourceCalendar of this view. + */ + ResourceCalendar *resourceCalendar() { return mResource; } + + /** + Return subResourceCalendar of this view. + */ + TQString subResourceCalendar() const { return mSubResource; } + /** @return a list of selected events. Most views can probably only select a single event at a time, but some may be able to select @@ -93,7 +115,19 @@ class KDE_EXPORT BaseView : public QWidget select a single event at a time, but some may be able to select more than one. */ - virtual DateList selectedDates() = 0; + virtual DateList selectedIncidenceDates() = 0; + + /** + Returns the start of the selection, or an invalid TQDateTime if there is no selection + or the view doesn't support selecting cells. + */ + virtual TQDateTime selectionStart() { return TQDateTime(); } + + /** + Returns the end of the selection, or an invalid TQDateTime if there is no selection + or the view doesn't support selecting cells. + */ + virtual TQDateTime selectionEnd() { return TQDateTime(); } virtual CalPrinterBase::PrintType printType() { @@ -108,6 +142,11 @@ class KDE_EXPORT BaseView : public QWidget /** Return if this view is a view for displaying events. */ virtual bool isEventView() { return false; } + /** Returns true if the view supports navigation through the date navigator + ( selecting a date range, changing month, changing year, etc. ) + */ + virtual bool supportsDateNavigation() const { return false; } + public slots: /** Show incidences for the given date range. The date range actually shown may be @@ -124,8 +163,9 @@ class KDE_EXPORT BaseView : public QWidget show all given events. @param incidenceList a list of incidences to show. + @param date is the TQDate on which the incidences are being shown. */ - virtual void showIncidences( const Incidence::List &incidenceList ) = 0; + virtual void showIncidences( const Incidence::List &incidenceList, const TQDate &date ) = 0; /** Updates the current display to reflect changes that may have happened @@ -166,19 +206,19 @@ class KDE_EXPORT BaseView : public QWidget virtual bool eventDurationHint(TQDateTime &/*startDt*/, TQDateTime &/*endDt*/, bool &/*allDay*/) { return false; } signals: - void incidenceSelected( Incidence * ); + void incidenceSelected( Incidence *, const TQDate & ); /** * instructs the receiver to show the incidence in read-only mode. */ - void showIncidenceSignal(Incidence *); + void showIncidenceSignal( Incidence *, const TQDate & ); /** * instructs the receiver to begin editing the incidence specified in * some manner. Doesn't make sense to connect to more than one * receiver. */ - void editIncidenceSignal(Incidence *); + void editIncidenceSignal( Incidence *, const TQDate & ); /** * instructs the receiver to delete the Incidence in some manner; some @@ -220,31 +260,40 @@ class KDE_EXPORT BaseView : public QWidget * instructs the receiver to create a new event. Doesn't make * sense to connect to more than one receiver. */ - void newEventSignal(); + void newEventSignal( ResourceCalendar *res, const TQString &subResource ); /** * instructs the receiver to create a new event with the specified beginning * time. Doesn't make sense to connect to more than one receiver. */ - void newEventSignal( const TQDate & ); + void newEventSignal( ResourceCalendar *res, const TQString &subResource, + const TQDate & ); /** * instructs the receiver to create a new event with the specified beginning * time. Doesn't make sense to connect to more than one receiver. */ - void newEventSignal( const TQDateTime & ); + void newEventSignal( ResourceCalendar *res, const TQString &subResource, + const TQDateTime & ); /** * instructs the receiver to create a new event, with the specified * beginning end ending times. Doesn't make sense to connect to more * than one receiver. */ - void newEventSignal( const TQDateTime &, const TQDateTime & ); + void newEventSignal( ResourceCalendar *res, const TQString &subResource, + const TQDateTime &, const TQDateTime & ); - void newTodoSignal( const TQDate & ); + void newTodoSignal( ResourceCalendar *res,const TQString &subResource, + const TQDate & ); void newSubTodoSignal( Todo * ); - void newJournalSignal( const TQDate & ); + void newJournalSignal( ResourceCalendar *res,const TQString &subResource, + const TQDate & ); private: + bool mReadOnly; Calendar *mCalendar; + ResourceCalendar *mResource; + TQString mSubResource; + protected: IncidenceChangerBase *mChanger; }; diff --git a/korganizer/interfaces/korganizer/corehelper.h b/korganizer/interfaces/korganizer/corehelper.h index 53b5d9fb2..8c69a1adc 100644 --- a/korganizer/interfaces/korganizer/corehelper.h +++ b/korganizer/interfaces/korganizer/corehelper.h @@ -37,8 +37,7 @@ class CoreHelper public: CoreHelper() {} virtual ~CoreHelper() {} - - virtual TQColor defaultEventColor() = 0; + virtual TQColor textColor( const TQColor &bgColor ) = 0; virtual TQColor categoryColor( const TQStringList &cats ) = 0; virtual TQString holidayString( const TQDate &dt ) = 0; diff --git a/korganizer/interfaces/korganizer/incidencechangerbase.h b/korganizer/interfaces/korganizer/incidencechangerbase.h index f482388c5..e7c133056 100644 --- a/korganizer/interfaces/korganizer/incidencechangerbase.h +++ b/korganizer/interfaces/korganizer/incidencechangerbase.h @@ -21,13 +21,16 @@ #ifndef KORG_INCIDENCECHANGERBASE_H #define KORG_INCIDENCECHANGERBASE_H +#include "korganizer/koglobals.h" #include <libkcal/scheduler.h> +#include <libkcal/incidence.h> #include <tqobject.h> class TQWidget; namespace KCal { -class Calendar; -class Incidence; + class Calendar; + class Incidence; + class ResourceCalendar; } using namespace KCal; @@ -42,25 +45,29 @@ public: virtual ~IncidenceChangerBase() {} virtual bool sendGroupwareMessage( Incidence *incidence, - KCal::Scheduler::Method method, bool deleting = false ) = 0; + KCal::Scheduler::Method method, + KOGlobals::HowChanged action, + TQWidget *parent ) = 0; - virtual bool beginChange( Incidence * incidence ) = 0; - virtual bool endChange( Incidence *incidence ) = 0; + virtual bool beginChange( Incidence *incidence, + ResourceCalendar *res, const TQString &subRes ) = 0; + virtual bool endChange( Incidence *incidence, + ResourceCalendar *res, const TQString &subRes ) = 0; - virtual bool addIncidence( Incidence *incidence, TQWidget *parent = 0 ) = 0; - virtual bool changeIncidence( Incidence *newinc, Incidence *oldinc, - int action = -1 ) = 0; - virtual bool deleteIncidence( Incidence *incidence ) = 0; - virtual bool cutIncidence( Incidence *incidence ) = 0; + virtual bool addIncidence( Incidence *incidence, + ResourceCalendar *res, const TQString &subRes, + TQWidget *parent ) = 0; + + virtual bool changeIncidence( Incidence *oldinc, Incidence *newinc, + KOGlobals::WhatChanged, TQWidget *parent ) = 0; + virtual bool deleteIncidence( Incidence *incidence, TQWidget *parent ) = 0; + + virtual bool cutIncidences( const Incidence::List &incidences, TQWidget *parent ) = 0; + virtual bool cutIncidence( Incidence *incidence, TQWidget *parent ) = 0; -/* - static bool incidencesEqual( Incidence *inc1, Incidence *inc2 ); - static bool assignIncidence( Incidence *inc1, Incidence *inc2 ); -*/ signals: void incidenceAdded( Incidence * ); - void incidenceChanged( Incidence *oldInc, Incidence *newInc, int ); - void incidenceChanged( Incidence *oldInc, Incidence *newInc ); + void incidenceChanged( Incidence *oldInc, Incidence *newInc, KOGlobals::WhatChanged ); void incidenceToBeDeleted( Incidence * ); void incidenceDeleted( Incidence * ); diff --git a/korganizer/interfaces/korganizer/korganizerpart.desktop b/korganizer/interfaces/korganizer/korganizerpart.desktop index 7cb419dea..c1b84659d 100644 --- a/korganizer/interfaces/korganizer/korganizerpart.desktop +++ b/korganizer/interfaces/korganizer/korganizerpart.desktop @@ -25,7 +25,6 @@ Comment[hu]=KOrganizer objektum Comment[is]=KOrganizer hluti Comment[it]=Parte di KOrganizer Comment[ja]=KOrganizer パート -Comment[ka]=KOrganizer კáƒáƒ›áƒžáƒáƒœáƒ”ნტი Comment[kk]=KOrganizer бөлшегі Comment[km]=ផ្នែក​របស់ KOrganizer Comment[lt]=KOrganizer dalis diff --git a/korganizer/interfaces/korganizer/korgprintplugin.desktop b/korganizer/interfaces/korganizer/korgprintplugin.desktop index ffa520d36..05cbd1b91 100644 --- a/korganizer/interfaces/korganizer/korgprintplugin.desktop +++ b/korganizer/interfaces/korganizer/korgprintplugin.desktop @@ -25,7 +25,6 @@ Comment[hu]=KOrganizer objektum Comment[is]=KOrganizer hluti Comment[it]=Parte di KOrganizer Comment[ja]=KOrganizer パート -Comment[ka]=KOrganizer კáƒáƒ›áƒžáƒáƒœáƒ”ნტი Comment[kk]=KOrganizer бөлшегі Comment[km]=ផ្នែក​របស់ KOrganizer Comment[lt]=KOrganizer dalis diff --git a/korganizer/interfaces/korganizer/mainwindow.h b/korganizer/interfaces/korganizer/mainwindow.h index 3343470aa..dcda1bee5 100644 --- a/korganizer/interfaces/korganizer/mainwindow.h +++ b/korganizer/interfaces/korganizer/mainwindow.h @@ -87,9 +87,11 @@ class MainWindow */ virtual void setTitle() = 0; - void setHasDocument( bool d ) { mDocument = d; } + void setHasDocument( bool d ) { mDocument = d; } bool hasDocument() const { return mDocument; } + virtual bool isCurrentlyActivePart() = 0; + private: bool mDocument; }; diff --git a/korganizer/journalentry.cpp b/korganizer/journalentry.cpp index ae80a8d6f..c107d6189 100644 --- a/korganizer/journalentry.cpp +++ b/korganizer/journalentry.cpp @@ -128,8 +128,8 @@ void JournalDateEntry::addJournal( Journal *j ) entry, TQT_SLOT( flushEntry() ) ); connect( entry, TQT_SIGNAL( deleteIncidence( Incidence* ) ), this, TQT_SIGNAL( deleteIncidence( Incidence* ) ) ); - connect( entry, TQT_SIGNAL( editIncidence( Incidence* ) ), - this, TQT_SIGNAL( editIncidence( Incidence* ) ) ); + connect( entry, TQT_SIGNAL( editIncidence( Incidence*, const TQDate& ) ), + this, TQT_SIGNAL( editIncidence( Incidence*, const TQDate& ) ) ); } Journal::List JournalDateEntry::journals() const @@ -151,7 +151,7 @@ void JournalDateEntry::setIncidenceChanger( IncidenceChangerBase *changer ) void JournalDateEntry::emitNewJournal() { - emit newJournal( mDate ); + emit newJournal( 0/*ResourceCalendar*/, TQString()/*subResource*/, mDate ); } void JournalDateEntry::journalEdited( Journal *journal ) @@ -271,8 +271,9 @@ void JournalEntry::deleteItem() void JournalEntry::editItem() { writeJournal(); - if ( mJournal ) - emit editIncidence( mJournal ); + if ( mJournal ) { + emit editIncidence( mJournal, mJournal->dtStart().date() ); + } } void JournalEntry::printItem() @@ -381,17 +382,17 @@ void JournalEntry::writeJournal() newJournal = true; mJournal = new Journal; writeJournalPrivate( mJournal ); - if ( !mChanger->addIncidence( mJournal, this ) ) { + if ( !mChanger->addIncidence( mJournal, 0, TQString(), this ) ) { KODialogManager::errorSaveIncidence( this, mJournal ); delete mJournal; mJournal = 0; } } else { oldJournal = mJournal->clone(); - if ( mChanger->beginChange( mJournal ) ) { + if ( mChanger->beginChange( mJournal, 0, TQString() ) ) { writeJournalPrivate( mJournal ); - mChanger->changeIncidence( oldJournal, mJournal, KOGlobals::DESCRIPTION_MODIFIED ); - mChanger->endChange( mJournal ); + mChanger->changeIncidence( oldJournal, mJournal, KOGlobals::DESCRIPTION_MODIFIED, this ); + mChanger->endChange( mJournal, 0, TQString() ); } delete oldJournal; } diff --git a/korganizer/journalentry.h b/korganizer/journalentry.h index 090909f39..9350d5ead 100644 --- a/korganizer/journalentry.h +++ b/korganizer/journalentry.h @@ -26,6 +26,7 @@ // // Widget showing one Journal entry +#include <libkcal/resourcecalendar.h> #include <tqvbox.h> class TQLabel; @@ -78,7 +79,7 @@ class JournalEntry : public TQWidget { signals: void deleteIncidence( Incidence * ); - void editIncidence( Incidence * ); + void editIncidence( Incidence *, const TQDate& ); protected: void clearFields(); @@ -131,9 +132,9 @@ class JournalDateEntry : public TQVBox { void setIncidenceChangerSignal( IncidenceChangerBase *changer ); void setDateSignal( const TQDate & ); void flushEntries(); - void editIncidence( Incidence * ); + void editIncidence( Incidence *, const TQDate& ); void deleteIncidence( Incidence * ); - void newJournal( const TQDate & ); + void newJournal( ResourceCalendar *, const TQString &, const TQDate & ); public slots: void emitNewJournal(); diff --git a/korganizer/kcalendariface.h b/korganizer/kcalendariface.h index a63f3f1c7..f4a20d7ad 100644 --- a/korganizer/kcalendariface.h +++ b/korganizer/kcalendariface.h @@ -86,7 +86,8 @@ class KCalendarIface : public DCOPObject const TQString& uri, const TQString& file, const TQStringList& attendees, - const TQString& attachmentMimetype ) = 0; + const TQString& attachmentMimetype, + bool isTask ) = 0; virtual void openJournalEditor( const TQDate& date ) = 0; virtual void openJournalEditor( const TQString& text, diff --git a/korganizer/kdatenavigator.cpp b/korganizer/kdatenavigator.cpp index 1dea017a2..6fe794592 100644 --- a/korganizer/kdatenavigator.cpp +++ b/korganizer/kdatenavigator.cpp @@ -53,11 +53,12 @@ KDateNavigator::KDateNavigator( TQWidget *parent, const char *name ) mNavigatorBar = new NavigatorBar( this ); topLayout->addMultiCellWidget( mNavigatorBar, 0, 0, 0, 7 ); - connect( mNavigatorBar, TQT_SIGNAL( goPrevYear() ), TQT_SIGNAL( goPrevYear() ) ); - connect( mNavigatorBar, TQT_SIGNAL( goPrevMonth() ), TQT_SIGNAL( goPrevMonth() ) ); - connect( mNavigatorBar, TQT_SIGNAL( goNextMonth() ), TQT_SIGNAL( goNextMonth() ) ); - connect( mNavigatorBar, TQT_SIGNAL( goNextYear() ), TQT_SIGNAL( goNextYear() ) ); - connect( mNavigatorBar, TQT_SIGNAL( goMonth( int ) ), TQT_SIGNAL( goMonth( int ) ) ); + connect( mNavigatorBar, TQT_SIGNAL( prevYearClicked() ), TQT_SIGNAL( prevYearClicked() ) ); + connect( mNavigatorBar, TQT_SIGNAL( prevMonthClicked() ), TQT_SIGNAL( prevMonthClicked() ) ); + connect( mNavigatorBar, TQT_SIGNAL( nextMonthClicked() ), TQT_SIGNAL( nextMonthClicked() ) ); + connect( mNavigatorBar, TQT_SIGNAL( nextYearClicked() ), TQT_SIGNAL( nextYearClicked() ) ); + connect( mNavigatorBar, TQT_SIGNAL( monthSelected( int ) ), TQT_SIGNAL( monthSelected( int ) ) ); + connect( mNavigatorBar, TQT_SIGNAL( yearSelected( int ) ), TQT_SIGNAL( yearSelected( int ) ) ); int i; TQString generalFont = KGlobalSettings::generalFont().family(); @@ -136,6 +137,7 @@ void KDateNavigator::updateToday() mDayMatrix->recalculateToday(); mDayMatrix->repaint(); } + TQDate KDateNavigator::startDate() const { // Find the first day of the week of the current month. @@ -160,6 +162,7 @@ TQDate KDateNavigator::startDate() const return dayone; } + TQDate KDateNavigator::endDate() const { return startDate().addDays( 6*7 ); @@ -202,6 +205,23 @@ void KDateNavigator::updateDayMatrix() mDayMatrix->repaint(); } +void KDateNavigator::setUpdateNeeded() +{ + mDayMatrix->setUpdateNeeded(); +} + +TQDate KDateNavigator::month() const +{ + TQDate firstCell = startDate(); + const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); + + if ( calSys->day( firstCell ) == 1 ) { + return firstCell; + } else { + calSys->setYMD( firstCell, calSys->year( firstCell ), calSys->month( firstCell ), 1 ); + return calSys->addMonths( firstCell, 1 ); + } +} void KDateNavigator::updateView() { @@ -230,10 +250,11 @@ void KDateNavigator::updateConfig() void KDateNavigator::setShowWeekNums( bool enabled ) { for( int i = 0; i < 6; i++ ) { - if( enabled ) + if ( enabled ) { mWeeknos[i]->show(); - else + } else { mWeeknos[i]->hide(); + } } } @@ -251,15 +272,18 @@ void KDateNavigator::selectDates( const DateList &dateList ) } } -void KDateNavigator::wheelEvent ( TQWheelEvent *e ) +void KDateNavigator::wheelEvent( TQWheelEvent *e ) { - if( e->delta() > 0 ) emit goPrevious(); - else emit goNext(); + if ( e->delta() > 0 ) { + emit goPrevious(); + } else { + emit goNext(); + } e->accept(); } -bool KDateNavigator::eventFilter ( TQObject *o, TQEvent *e ) +bool KDateNavigator::eventFilter( TQObject *o, TQEvent *e ) { if ( e->type() == TQEvent::MouseButtonPress ) { int i; diff --git a/korganizer/kdatenavigator.h b/korganizer/kdatenavigator.h index 047925895..682a93588 100644 --- a/korganizer/kdatenavigator.h +++ b/korganizer/kdatenavigator.h @@ -63,6 +63,14 @@ class KDateNavigator: public QFrame NavigatorBar *navigatorBar() const { return mNavigatorBar; } TQDate startDate() const; TQDate endDate() const; + void setUpdateNeeded(); + + /** + Returns the current displayed month. + It's a TQDate instead of uint so it can be easily feed to KCalendarSystem's + functions. + */ + TQDate month() const; public slots: void selectDates( const KCal::DateList & ); @@ -75,24 +83,24 @@ class KDateNavigator: public QFrame void datesSelected( const KCal::DateList & ); void incidenceDropped( Incidence *, const TQDate & ); void incidenceDroppedMove( Incidence *, const TQDate & ); - void weekClicked( const TQDate &); + void weekClicked( const TQDate & ); void goPrevious(); void goNext(); + void nextMonthClicked(); + void prevMonthClicked(); + void nextYearClicked(); + void prevYearClicked(); - void goNextMonth(); - void goPrevMonth(); - void goNextYear(); - void goPrevYear(); - - void goMonth( int month ); + void monthSelected( int month ); + void yearSelected( int year ); protected: void updateDates(); void wheelEvent( TQWheelEvent * ); - bool eventFilter( TQObject *,TQEvent * ); + bool eventFilter( TQObject *, TQEvent * ); void setShowWeekNums( bool enabled ); diff --git a/korganizer/koagenda.cpp b/korganizer/koagenda.cpp index 589c13285..8329d161c 100644 --- a/korganizer/koagenda.cpp +++ b/korganizer/koagenda.cpp @@ -58,11 +58,12 @@ #include <libkcal/vcaldrag.h> #include <libkcal/calendar.h> #include <libkcal/calendarresources.h> +#include <libkcal/calhelper.h> #include <math.h> //////////////////////////////////////////////////////////////////////////// -MarcusBains::MarcusBains(KOAgenda *_agenda,const char *name) - : TQFrame(_agenda->viewport(),name), agenda(_agenda) +MarcusBains::MarcusBains(KOAgenda *_agenda,const char *name ) + : TQFrame(_agenda->viewport(), name), agenda(_agenda) { setLineWidth(0); setMargin(0); @@ -80,7 +81,8 @@ MarcusBains::MarcusBains(KOAgenda *_agenda,const char *name) agenda->addChild(mTimeBox); - oldToday = -1; + mOldTime = TQTime( 0, 0 ); + mOldToday = -1; } MarcusBains::~MarcusBains() @@ -99,33 +101,41 @@ int MarcusBains::todayColumn() if((*it) == currentDate) return KOGlobals::self()->reverseLayout() ? agenda->columns() - 1 - col : col; - ++col; + ++col; } return -1; } -void MarcusBains::updateLocation(bool recalculate) +void MarcusBains::updateLocation() +{ + updateLocationRecalc(); +} + +void MarcusBains::updateLocationRecalc( bool recalculate ) { TQTime tim = TQTime::currentTime(); - if((tim.hour() == 0) && (oldTime.hour()==23)) + if((tim.hour() == 0) && (mOldTime.hour()==23)) recalculate = true; int mins = tim.hour()*60 + tim.minute(); int minutesPerCell = 24 * 60 / agenda->rows(); int y = int( mins * agenda->gridSpacingY() / minutesPerCell ); - int today = recalculate ? todayColumn() : oldToday; + int today = recalculate ? todayColumn() : mOldToday; int x = int( agenda->gridSpacingX() * today ); - bool disabled = !(KOPrefs::instance()->mMarcusBainsEnabled); - oldTime = tim; - oldToday = today; + mOldTime = tim; + mOldToday = today; - if(disabled || (today<0)) { + bool hideIt = !( KOPrefs::instance()->mMarcusBainsEnabled ); + + if ( !isHidden() && ( hideIt || ( today < 0 ) ) ) { hide(); mTimeBox->hide(); return; - } else { + } + + if ( isHidden() && !hideIt ) { show(); mTimeBox->show(); } @@ -137,8 +147,12 @@ void MarcusBains::updateLocation(bool recalculate) if(recalculate) mTimeBox->setFont(KOPrefs::instance()->mMarcusBainsFont); - mTimeBox->setText(KGlobal::locale()->formatTime(tim, KOPrefs::instance()->mMarcusBainsShowSeconds)); - mTimeBox->adjustSize(); + TQString timeStr = KGlobal::locale()->formatTime(tim, KOPrefs::instance()->mMarcusBainsShowSeconds); + TQFontMetrics fm = fontMetrics(); + mTimeBox->setText( timeStr ); + TQSize sz( fm.width( timeStr + ' ' ), fm.height() ); + mTimeBox->setFixedSize( sz ); + if (y-mTimeBox->height()>=0) y-=mTimeBox->height(); else y++; if (x-mTimeBox->width()+agenda->gridSpacingX() > 0) x += int( agenda->gridSpacingX() - mTimeBox->width() - 1 ); @@ -157,13 +171,19 @@ void MarcusBains::updateLocation(bool recalculate) /* Create an agenda widget with rows rows and columns columns. */ -KOAgenda::KOAgenda( int columns, int rows, int rowSize, TQWidget *parent, - const char *name, WFlags f ) +KOAgenda::KOAgenda( int columns, int rows, int rowSize, CalendarView *calendarView, + TQWidget *parent, const char *name, WFlags f ) : TQScrollView( parent, name, f ), mChanger( 0 ) { mColumns = columns; mRows = rows; mGridSpacingY = rowSize; + if ( mGridSpacingY < 4 || mGridSpacingY > 30 ) { + mGridSpacingY = 10; + } + + mCalendarView = calendarView; + mAllDayMode = false; init(); @@ -175,13 +195,14 @@ KOAgenda::KOAgenda( int columns, int rows, int rowSize, TQWidget *parent, Create an agenda widget with columns columns and one row. This is used for all-day events. */ -KOAgenda::KOAgenda( int columns, TQWidget *parent, const char *name, WFlags f ) - : TQScrollView( parent, name, f ) +KOAgenda::KOAgenda( int columns, CalendarView *calendarView, TQWidget *parent, + const char *name, WFlags f ) : TQScrollView( parent, name, f ) { mColumns = columns; mRows = 1; mGridSpacingY = 24; mAllDayMode = true; + mCalendarView = calendarView; setVScrollBarMode( AlwaysOff ); init(); @@ -214,6 +235,16 @@ const TQString KOAgenda::lastSelectedUid() const void KOAgenda::init() { mGridSpacingX = 100; + mDesiredGridSpacingY = KOPrefs::instance()->mHourSize; + if ( mDesiredGridSpacingY < 4 || mDesiredGridSpacingY > 30 ) { + mDesiredGridSpacingY = 10; + } + + // make sure that there are not more than 24 per day + mGridSpacingY = (double)height() / (double)mRows; + if ( mGridSpacingY < mDesiredGridSpacingY ) { + mGridSpacingY = mDesiredGridSpacingY; + } mResizeBorderWidth = 8; mScrollBorderWidth = 8; @@ -243,6 +274,7 @@ void KOAgenda::init() mClickedItem = 0; mActionItem = 0; + mResPair = qMakePair( static_cast<ResourceCalendar *>( 0 ), TQString() ); mActionType = NOP; mItemMoved = false; @@ -317,7 +349,7 @@ void KOAgenda::clearSelection() void KOAgenda::marcus_bains() { - if(mMarcusBains) mMarcusBains->updateLocation(true); + if(mMarcusBains) mMarcusBains->updateLocationRecalc( true ); } @@ -510,7 +542,8 @@ bool KOAgenda::eventFilter_key( TQObject *, TQKeyEvent *ke ) void KOAgenda::emitNewEventForSelection() { - emit newEventSignal(); + QPair<ResourceCalendar *, TQString>p = mCalendarView->viewSubResourceCalendar(); + emit newEventSignal( p.first, p.second ); } void KOAgenda::finishTypeAhead() @@ -572,14 +605,17 @@ bool KOAgenda::eventFilter_mouse(TQObject *object, TQMouseEvent *me) switch (me->type()) { case TQEvent::MouseButtonPress: -// kdDebug(5850) << "koagenda: filtered button press" << endl; +// kdDebug(5850) << "koagenda: filtered button press" << endl; if (object != viewport()) { if (me->button() == RightButton) { mClickedItem = dynamic_cast<KOAgendaItem *>(object); if (mClickedItem) { selectItem(mClickedItem); - emit showIncidencePopupSignal( mClickedItem->incidence(), + emit showIncidencePopupSignal( mCalendar, + mClickedItem->incidence(), mClickedItem->itemDate() ); + } else { + return TQScrollView::eventFilter( object, me ); // pass through for use by multiagenda } } else { KOAgendaItem* item = dynamic_cast<KOAgendaItem *>(object); @@ -587,8 +623,10 @@ bool KOAgenda::eventFilter_mouse(TQObject *object, TQMouseEvent *me) Incidence *incidence = item->incidence(); if ( incidence->isReadOnly() ) { mActionItem = 0; + mResPair = qMakePair( static_cast<ResourceCalendar *>( 0 ), TQString() ); } else { mActionItem = item; + mResPair = CalHelper::incSubResourceCalendar( mCalendar, incidence ); startItemAction(viewportPos); } // Warning: do selectItem() as late as possible, since all @@ -596,11 +634,12 @@ bool KOAgenda::eventFilter_mouse(TQObject *object, TQMouseEvent *me) // this filter being run again and mActionItem being set to // null. selectItem( item ); + } else { + return TQScrollView::eventFilter( object, me ); // pass through for use by multiagenda } } } else { - if (me->button() == RightButton) - { + if ( me->button() == RightButton ) { // if mouse pointer is not in selection, select the cell below the cursor TQPoint gpos = contentsToGrid( viewportToContents( viewportPos ) ); if ( !ptInSelection( gpos ) ) { @@ -612,18 +651,18 @@ bool KOAgenda::eventFilter_mouse(TQObject *object, TQMouseEvent *me) updateContents(); } showNewEventPopupSignal(); - } - else - { + } else { // if mouse pointer is in selection, don't change selection TQPoint gpos = contentsToGrid( viewportToContents( viewportPos ) ); if ( !ptInSelection( gpos ) ) { selectItem(0); mActionItem = 0; + mResPair = qMakePair( static_cast<ResourceCalendar *>( 0 ), TQString() ); setCursor(arrowCursor); startSelectAction(viewportPos); } } + return TQScrollView::eventFilter( object, me ); // pass through for use by multiagenda } break; @@ -668,29 +707,30 @@ bool KOAgenda::eventFilter_mouse(TQObject *object, TQMouseEvent *me) } // If we have an action item } // If move item && !read only } else { - if ( mActionType == SELECT ) { - performSelectAction( viewportPos ); - - // show cursor at end of timespan - if ( ((mStartCell.y() < mEndCell.y()) && (mEndCell.x() >= mStartCell.x())) || - (mEndCell.x() > mStartCell.x()) ) - indicatorPos = gridToContents( TQPoint(mEndCell.x(), mEndCell.y()+1) ); - else - indicatorPos = gridToContents( mEndCell ); - } + if ( mActionType == SELECT ) { + performSelectAction( viewportPos ); + + // show cursor at end of timespan + if ( ((mStartCell.y() < mEndCell.y()) && (mEndCell.x() >= mStartCell.x())) || + (mEndCell.x() > mStartCell.x()) ) + indicatorPos = gridToContents( TQPoint(mEndCell.x(), mEndCell.y()+1) ); + else + indicatorPos = gridToContents( mEndCell ); } + } emit mousePosSignal( indicatorPos ); break; } case TQEvent::MouseButtonDblClick: if (object == viewport()) { selectItem(0); - emit newEventSignal(); + QPair<ResourceCalendar *, TQString>p = mCalendarView->viewSubResourceCalendar(); + emit newEventSignal( p.first, p.second ); } else { - KOAgendaItem *doubleClickedItem = dynamic_cast<KOAgendaItem *>(object); - if (doubleClickedItem) { - selectItem(doubleClickedItem); - emit editIncidenceSignal(doubleClickedItem->incidence()); + KOAgendaItem *doubleClickedItem = dynamic_cast<KOAgendaItem *>( object ); + if ( doubleClickedItem ) { + selectItem( doubleClickedItem ); + emit editIncidenceSignal( doubleClickedItem->incidence(), doubleClickedItem->itemDate() ); } } break; @@ -878,10 +918,9 @@ void KOAgenda::performItemAction(const TQPoint& viewportPos) emit startDragSignal( mActionItem->incidence() ); setCursor( arrowCursor ); mActionItem = 0; + mResPair = qMakePair( static_cast<ResourceCalendar *>( 0 ), TQString() ); mActionType = NOP; mItemMoved = false; - if ( mItemMoved && mChanger ) - mChanger->endChange( mActionItem->incidence() ); return; } } else { @@ -902,7 +941,8 @@ void KOAgenda::performItemAction(const TQPoint& viewportPos) // Move or resize item if necessary if ( mEndCell != gpos ) { if ( !mItemMoved ) { - if ( !mChanger || !mChanger->beginChange( mActionItem->incidence() ) ) { + if ( !mChanger || + !mChanger->beginChange( mActionItem->incidence(), mResPair.first, mResPair.second ) ) { KMessageBox::information( this, i18n("Unable to lock item for " "modification. You cannot make any changes."), i18n("Locking Failed"), "AgendaLockingFailed" ); @@ -912,6 +952,7 @@ void KOAgenda::performItemAction(const TQPoint& viewportPos) placeSubCells( mActionItem ); setCursor( arrowCursor ); mActionItem = 0; + mResPair = qMakePair( static_cast<ResourceCalendar *>( 0 ), TQString() ); mActionType = NOP; mItemMoved = false; return; @@ -951,7 +992,7 @@ void KOAgenda::performItemAction(const TQPoint& viewportPos) addChild( newFirst, cpos.x(), cpos.y() ); } else { newFirst = insertItem( moveItem->incidence(), moveItem->itemDate(), - moveItem->cellXLeft()-1, rows()+newY, rows()-1 ) ; + moveItem->cellXLeft()-1, rows()+newY, rows()-1, moveItem->itemPos(), moveItem->itemCount() ) ; } if (newFirst) newFirst->show(); moveItem->prependMoveItem(newFirst); @@ -996,7 +1037,7 @@ void KOAgenda::performItemAction(const TQPoint& viewportPos) addChild( newLast, cpos.x(), cpos.y() ); } else { newLast = insertItem( moveItem->incidence(), moveItem->itemDate(), - moveItem->cellXLeft()+1, 0, newY-rows()-1 ) ; + moveItem->cellXLeft()+1, 0, newY-rows()-1, moveItem->itemPos(), moveItem->itemCount() ) ; } moveItem->appendMoveItem( newLast ); newLast->show(); @@ -1046,98 +1087,45 @@ void KOAgenda::endItemAction() bool multiModify = false; // FIXME: do the cloning here... Incidence* inc = mActionItem->incidence(); - // Store modification information in case it is needed to recreate the changes with a new actionitem... - int mai_xl = mActionItem->cellXLeft(); - int mai_xr = mActionItem->cellXRight(); - int mai_yt = mActionItem->cellYTop(); - int mai_yb = mActionItem->cellYBottom(); - Incidence* newInc; + + if ( mStartCell.x() == mEndCell.x() && mStartCell.y() == mEndCell.y() ) { + // not really moved, so stop any change + if ( mItemMoved ) { + mItemMoved = false; + mChanger->endChange( inc, mResPair.first, mResPair.second ); + } + } if ( mItemMoved ) { - bool modify = true; + Incidence *incToChange = inc; if ( mActionItem->incidence()->doesRecur() ) { - int res = KOMessageBox::fourBtnMsgBox( this, TQMessageBox::Question, - i18n("The item you try to change is a recurring item. Shall the changes " - "be applied only to this single occurrence, only to the future items, " - "or to all items in the recurrence?"), - i18n("Changing Recurring Item"), - i18n("Only &This Item"), i18n("Only &Future Items"), i18n("&All Occurrences") ); - switch ( res ) { - case KMessageBox::Ok: // All occurrences - // Moving the whole sequene of events is handled by the itemModified below. - modify = true; - break; - // FIXME: The following two cases do the following bad things: - // 1. Pop up a message box asking which resource to save the disassociated event to (!) - // 2. Crash at mActionItem->endMove(); below. - case KMessageBox::Yes: { // Just this occurrence - // Dissociate this occurrence: - // create clone of event, set relation to old event, set cloned event - // for mActionItem, add exception date to old event, changeIncidence - // for the old event, remove the recurrence from the new copy and then just - // go on with the newly adjusted mActionItem and let the usual code take - // care of the new time! - modify = true; - multiModify = true; - emit startMultiModify( i18n("Dissociate event from recurrence") ); - Incidence* oldInc = mActionItem->incidence(); - Incidence* oldIncSaved = mActionItem->incidence()->clone(); - newInc = mCalendar->dissociateOccurrence( - oldInc, mActionItem->itemDate() ); - if ( newInc ) { - // don't recreate items, they already have the correct position - emit enableAgendaUpdate( false ); - mActionItem->dissociateFromMultiItem(); - mActionItem->setIncidence( newInc ); - bool success = mChanger->addIncidence( newInc, this ); - emit enableAgendaUpdate( true ); - if ( success ) { - mChanger->changeIncidence( oldIncSaved, oldInc ); - } - } else { - KMessageBox::sorry( this, i18n("Unable to add the exception item to the " - "calendar. No change will be done."), i18n("Error Occurred") ); - } - delete oldIncSaved; - break; } - case KMessageBox::No/*Future*/: { // All future occurrences - // Dissociate this occurrence: - // create clone of event, set relation to old event, set cloned event - // for mActionItem, add recurrence end date to old event, changeIncidence - // for the old event, adjust the recurrence for the new copy and then just - // go on with the newly adjusted mActionItem and let the usual code take - // care of the new time! - modify = true; - multiModify = true; - emit startMultiModify( i18n("Split future recurrences") ); - Incidence* oldInc = mActionItem->incidence(); - Incidence* oldIncSaved = mActionItem->incidence()->clone(); - newInc = mCalendar->dissociateOccurrence( - oldInc, mActionItem->itemDate(), false ); - if ( newInc ) { - emit enableAgendaUpdate( false ); - mActionItem->dissociateFromMultiItem(); - mActionItem->setIncidence( newInc ); - bool success = mChanger->addIncidence( newInc, this ); - emit enableAgendaUpdate( true ); - if ( success ) { - mChanger->changeIncidence( oldIncSaved, oldInc ); - } - } else { - KMessageBox::sorry( this, i18n("Unable to add the future items to the " - "calendar. No change will be done."), i18n("Error Occurred") ); - } - delete oldIncSaved; - break; } - default: - modify = false; - mActionItem->resetMove(); - placeSubCells( mActionItem ); - } - } + Incidence* oldIncSaved = inc->clone(); + KOGlobals::WhichOccurrences chosenOption; + incToChange = mCalendarView->singleOccurrenceOrAll( inc, + KOGlobals::EDIT, + chosenOption, + mActionItem->itemDate() ); + + if ( chosenOption == KOGlobals::ONLY_THIS_ONE || + chosenOption == KOGlobals::ONLY_FUTURE ) { + + // Store modification information in case it is needed to recreate the changes with a new actionitem... + int mai_xl = mActionItem->cellXLeft(); + int mai_xr = mActionItem->cellXRight(); + int mai_yt = mActionItem->cellYTop(); + int mai_yb = mActionItem->cellYBottom(); + + multiModify = true; + enableAgendaUpdate( false ); + + mChanger->addIncidence( incToChange, mResPair.first, mResPair.second, this ); + enableAgendaUpdate( true ); + KOGlobals::WhatChanged wc = chosenOption == KOGlobals::ONLY_THIS_ONE ? + KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY : + KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE; + + mChanger->changeIncidence( oldIncSaved, inc, wc, this ); - if ( modify ) { - if ( multiModify ) { // mActionItem does not exist any more, seeing as we just got done deleting it // (by deleting/replacing the original incidence it was created from through // user modification of said incidence) above! @@ -1146,7 +1134,7 @@ void KOAgenda::endItemAction() KOAgendaItem *koai_insertedItem; for ( koai_insertedItem = mItems.first(); koai_insertedItem; koai_insertedItem = mItems.next() ) { - if (koai_insertedItem->incidence() == newInc) { + if (koai_insertedItem->incidence() == incToChange) { selectItem( koai_insertedItem ); mSelectedItem->startMove(); mSelectedItem->setCellY(mai_yt, mai_yb); @@ -1157,15 +1145,12 @@ void KOAgenda::endItemAction() } } -// mActionItem->startMove(); -// mActionItem->setCellY(mai_yt, mai_yb); -// mActionItem->setCellX(mai_xl, mai_xr); -// mActionItem->endMove(); + mActionItem->dissociateFromMultiItem(); + mActionItem->setIncidence( incToChange ); } } - if ( modify ) { -// if ( !multiModify ) { + if ( incToChange ) { mActionItem->endMove(); KOAgendaItem *placeItem = mActionItem->firstMultiItem(); if ( !placeItem ) { @@ -1187,17 +1172,27 @@ void KOAgenda::endItemAction() // Notify about change // the agenda view will apply the changes to the actual Incidence*! + mChanger->endChange( inc, mResPair.first, mResPair.second ); emit itemModified( modif ); -// } + } else { + + mActionItem->resetMove(); + placeSubCells( mActionItem ); + + // the item was moved, but not further modified, since it's not recurring + // make sure the view updates anyhow, with the right item + mChanger->endChange( inc, mResPair.first, mResPair.second ); + emit itemModified( mActionItem ); } - // FIXME: If the change failed, we need to update the view! - mChanger->endChange( inc ); } mActionItem = 0; + mResPair = qMakePair( static_cast<ResourceCalendar *>( 0 ), TQString() ); mItemMoved = false; - if ( multiModify ) emit endMultiModify(); + if ( multiModify ) { + emit endMultiModify(); + } kdDebug(5850) << "KOAgenda::endItemAction() done" << endl; } @@ -1280,7 +1275,7 @@ void KOAgenda::placeAgendaItem( KOAgendaItem *item, double subCellWidth ) TQPoint pt = gridToContents( TQPoint( item->cellXLeft(), item->cellYTop() ) ); // right lower corner TQPoint pt1 = gridToContents( TQPoint( item->cellXLeft() + item->cellWidth(), - item->cellYBottom()+1 ) ); + item->cellYBottom()+1 ) ); double subCellPos = item->subCell() * subCellWidth; @@ -1594,23 +1589,16 @@ void KOAgenda::setStartTime( const TQTime &startHour ) Insert KOAgendaItem into agenda. */ KOAgendaItem *KOAgenda::insertItem( Incidence *incidence, const TQDate &qd, int X, - int YTop, int YBottom ) + int YTop, int YBottom, int itemPos, int itemCount ) { -#if 0 - kdDebug(5850) << "KOAgenda::insertItem:" << incidence->summary() << "-" - << qd.toString() << " ;top, bottom:" << YTop << "," << YBottom - << endl; -#endif - if ( mAllDayMode ) { kdDebug(5850) << "KOAgenda: calling insertItem in all-day mode is illegal." << endl; return 0; } - mActionType = NOP; - KOAgendaItem *agendaItem = new KOAgendaItem( incidence, qd, viewport() ); + KOAgendaItem *agendaItem = new KOAgendaItem( mCalendar, incidence, qd, viewport(), itemPos, itemCount ); connect( agendaItem, TQT_SIGNAL( removeAgendaItem( KOAgendaItem * ) ), TQT_SLOT( removeAgendaItem( KOAgendaItem * ) ) ); connect( agendaItem, TQT_SIGNAL( showAgendaItem( KOAgendaItem * ) ), @@ -1655,7 +1643,7 @@ KOAgendaItem *KOAgenda::insertAllDayItem( Incidence *event, const TQDate &qd, mActionType = NOP; - KOAgendaItem *agendaItem = new KOAgendaItem( event, qd, viewport() ); + KOAgendaItem *agendaItem = new KOAgendaItem( mCalendar, event, qd, viewport(), 1, 1 ); connect( agendaItem, TQT_SIGNAL( removeAgendaItem( KOAgendaItem* ) ), TQT_SLOT( removeAgendaItem( KOAgendaItem* ) ) ); connect( agendaItem, TQT_SIGNAL( showAgendaItem( KOAgendaItem* ) ), @@ -1683,10 +1671,10 @@ KOAgendaItem *KOAgenda::insertAllDayItem( Incidence *event, const TQDate &qd, } -void KOAgenda::insertMultiItem (Event *event,const TQDate &qd,int XBegin,int XEnd, - int YTop,int YBottom) +void KOAgenda::insertMultiItem( Event *event, const TQDate &qd, int XBegin, int XEnd, + int YTop, int YBottom ) { - if (mAllDayMode) { + if ( mAllDayMode ) { kdDebug(5850) << "KOAgenda: calling insertMultiItem in all-day mode is illegal." << endl; return; } @@ -1698,40 +1686,50 @@ void KOAgenda::insertMultiItem (Event *event,const TQDate &qd,int XBegin,int XEn int count = 0; KOAgendaItem *current = 0; TQPtrList<KOAgendaItem> multiItems; - int visibleCount = mSelectedDates.first().daysTo(mSelectedDates.last()); + const int visibleCount = mSelectedDates.first().daysTo( mSelectedDates.last() ); for ( cellX = XBegin; cellX <= XEnd; ++cellX ) { ++count; //Only add the items that are visible. - if( cellX >=0 && cellX <= visibleCount ) { - if ( cellX == XBegin ) cellYTop = YTop; - else cellYTop = 0; - if ( cellX == XEnd ) cellYBottom = YBottom; - else cellYBottom = rows() - 1; + if( cellX >= 0 && cellX <= visibleCount ) { + if ( cellX == XBegin ) { + cellYTop = YTop; + } else { + cellYTop = 0; + } + + if ( cellX == XEnd ) { + cellYBottom = YBottom; + } else { + cellYBottom = rows() - 1; + } + newtext = TQString("(%1/%2): ").arg( count ).arg( width ); newtext.append( event->summary() ); - current = insertItem( event, qd, cellX, cellYTop, cellYBottom ); + current = insertItem( event, qd, cellX, cellYTop, cellYBottom, count, width ); current->setText( newtext ); multiItems.append( current ); } } - - KOAgendaItem *next = 0; - KOAgendaItem *prev = 0; - KOAgendaItem *last = multiItems.last(); - KOAgendaItem *first = multiItems.first(); - KOAgendaItem *setFirst,*setLast; - current = first; - while (current) { - next = multiItems.next(); - if (current == first) setFirst = 0; - else setFirst = first; - if (current == last) setLast = 0; - else setLast = last; - - current->setMultiItem(setFirst, prev, next, setLast); - prev=current; - current = next; + TQPtrList<KOAgendaItem>::iterator it = multiItems.begin(); + TQPtrList<KOAgendaItem>::iterator e = multiItems.end(); + + if ( it != e ) { // .first asserts if the list is empty + KOAgendaItem *first = multiItems.first(); + KOAgendaItem *last = multiItems.last(); + KOAgendaItem *prev = 0, *next = 0; + + while ( it != e ) { + KOAgendaItem *item = *it; + ++it; + next = ( it == e ) ? 0 : (*it); + if ( item ) { + item->setMultiItem( ( item == first ) ? 0 : first, + prev, next, + ( item == last ) ? 0 : last ); + } + prev = item; + } } marcus_bains(); @@ -1760,11 +1758,15 @@ void KOAgenda::removeIncidence( Incidence *incidence ) void KOAgenda::showAgendaItem( KOAgendaItem *agendaItem ) { - if ( !agendaItem ) return; + if ( !agendaItem ) { + return; + } + agendaItem->hide(); addChild( agendaItem ); - if ( !mItems.containsRef( agendaItem ) ) + if ( !mItems.containsRef( agendaItem ) ) { mItems.append( agendaItem ); + } placeSubCells( agendaItem ); agendaItem->show(); @@ -1777,8 +1779,9 @@ bool KOAgenda::removeAgendaItem( KOAgendaItem *item ) KOAgendaItem *thisItem = item; TQPtrList<KOAgendaItem> conflictItems = thisItem->conflictItems(); removeChild( thisItem ); + int pos = mItems.find( thisItem ); - if ( pos>=0 ) { + if ( pos >= 0 ) { mItems.take( pos ); taken = true; } @@ -1843,23 +1846,24 @@ void KOAgenda::resizeEvent ( TQResizeEvent *ev ) void KOAgenda::resizeAllContents() { double subCellWidth; - KOAgendaItem *item; - if (mAllDayMode) { - for ( item=mItems.first(); item != 0; item=mItems.next() ) { - subCellWidth = calcSubCellWidth( item ); - placeAgendaItem( item, subCellWidth ); - } - } else { - for ( item=mItems.first(); item != 0; item=mItems.next() ) { - subCellWidth = calcSubCellWidth( item ); - placeAgendaItem( item, subCellWidth ); + if ( mItems.count() > 0 ) { + KOAgendaItem *item; + if (mAllDayMode) { + for ( item=mItems.first(); item != 0; item=mItems.next() ) { + subCellWidth = calcSubCellWidth( item ); + placeAgendaItem( item, subCellWidth ); + } + } else { + for ( item=mItems.first(); item != 0; item=mItems.next() ) { + subCellWidth = calcSubCellWidth( item ); + placeAgendaItem( item, subCellWidth ); + } } } checkScrollBoundaries(); marcus_bains(); } - void KOAgenda::scrollUp() { scrollBy(0,-mScrollOffset); @@ -1886,15 +1890,23 @@ int KOAgenda::minimumWidth() const void KOAgenda::updateConfig() { double oldGridSpacingY = mGridSpacingY; + mDesiredGridSpacingY = KOPrefs::instance()->mHourSize; - // make sure that there are not more than 24 per day - mGridSpacingY = (double)height()/(double)mRows; - if (mGridSpacingY<mDesiredGridSpacingY) mGridSpacingY=mDesiredGridSpacingY; + if ( mDesiredGridSpacingY < 4 || mDesiredGridSpacingY > 30 ) { + mDesiredGridSpacingY = 10; + } + + // make sure that there are not more than 24 per day + mGridSpacingY = (double)height() / (double)mRows; + if ( mGridSpacingY < mDesiredGridSpacingY ) { + mGridSpacingY = mDesiredGridSpacingY; + } //can be two doubles equal?, it's better to compare them with an epsilon - if ( fabs( oldGridSpacingY - mGridSpacingY ) > 0.1 ) + if ( fabs( oldGridSpacingY - mGridSpacingY ) > 0.1 ) { resizeContents( int( mGridSpacingX * mColumns ), - int( mGridSpacingY * mRows ) ); + int( mGridSpacingY * mRows ) ); + } calculateWorkingHours(); @@ -1941,7 +1953,9 @@ int KOAgenda::visibleContentsYMax() void KOAgenda::deselectItem() { - if (mSelectedItem.isNull()) return; + if ( mSelectedItem.isNull() ) { + return; + } mSelectedItem->select(false); mSelectedItem = 0; } @@ -1951,15 +1965,14 @@ void KOAgenda::selectItem(KOAgendaItem *item) if ((KOAgendaItem *)mSelectedItem == item) return; deselectItem(); if (item == 0) { - emit incidenceSelected( 0 ); + emit incidenceSelected( 0, TQDate() ); return; } mSelectedItem = item; mSelectedItem->select(); - Incidence *incidence = mSelectedItem->incidence(); - assert( incidence ); - mSelectedUid = incidence->uid(); - emit incidenceSelected( incidence ); + assert( mSelectedItem->incidence() ); + mSelectedUid = mSelectedItem->incidence()->uid(); + emit incidenceSelected( mSelectedItem->incidence(), mSelectedItem->itemDate() ); } void KOAgenda::selectItemByUID( const TQString& uid ) diff --git a/korganizer/koagenda.h b/korganizer/koagenda.h index a6d06d006..223ea1aa3 100644 --- a/korganizer/koagenda.h +++ b/korganizer/koagenda.h @@ -29,6 +29,7 @@ #include <tqguardedptr.h> #include <libkcal/incidencebase.h> +#include "calendarview.h" class TQPopupMenu; class TQTime; @@ -37,44 +38,46 @@ class KConfig; class KOAgenda; class KOAgendaItem; -using namespace KOrg; namespace KOrg { -class IncidenceChangerBase; + class IncidenceChangerBase; } +using namespace KOrg; -using namespace KCal; namespace KCal { -class Event; -class Todo; -class Calendar; + class Event; + class Todo; + class Calendar; } +using namespace KCal; -class MarcusBains : public TQFrame { - Q_OBJECT +class MarcusBains : public TQFrame +{ + Q_OBJECT public: MarcusBains( KOAgenda *agenda = 0, const char *name = 0 ); + void updateLocationRecalc( bool recalculate = false ); virtual ~MarcusBains(); public slots: - void updateLocation( bool recalculate = false ); + void updateLocation(); private: int todayColumn(); TQTimer *minutes; TQLabel *mTimeBox; KOAgenda *agenda; - TQTime oldTime; - int oldToday; + TQTime mOldTime; + int mOldToday; }; - -class KOAgenda : public QScrollView +class KOAgenda : public TQScrollView { - Q_OBJECT + Q_OBJECT public: - KOAgenda ( int columns, int rows, int columnSize, TQWidget *parent=0, - const char *name = 0, WFlags f = 0 ); - KOAgenda ( int columns, TQWidget *parent = 0, + KOAgenda ( int columns, int rows, int columnSize, CalendarView *calendarView, + TQWidget *parent=0, const char *name = 0, WFlags f = 0 ); + + KOAgenda ( int columns, CalendarView *calendarView, TQWidget *parent = 0, const char *name = 0, WFlags f = 0 ); virtual ~KOAgenda(); @@ -103,7 +106,7 @@ class KOAgenda : public QScrollView void setStartTime( const TQTime &startHour ); KOAgendaItem *insertItem ( Incidence *incidence, const TQDate &qd, int X, int YTop, - int YBottom ); + int YBottom, int itemPos, int itemCount ); KOAgendaItem *insertAllDayItem ( Incidence *event, const TQDate &qd, int XBegin, int XEnd ); void insertMultiItem ( Event *event, const TQDate &qd, int XBegin, int XEnd, @@ -171,18 +174,18 @@ class KOAgenda : public QScrollView void showAgendaItem( KOAgendaItem *item ); signals: - void newEventSignal(); + void newEventSignal( ResourceCalendar *res, const TQString &subResource ); void newTimeSpanSignal( const TQPoint &, const TQPoint & ); void newStartSelectSignal(); - void showIncidenceSignal( Incidence * ); - void editIncidenceSignal( Incidence * ); + void showIncidenceSignal( Incidence *, const TQDate & ); + void editIncidenceSignal( Incidence *, const TQDate & ); void deleteIncidenceSignal( Incidence * ); - void showIncidencePopupSignal( Incidence *, const TQDate &); + void showIncidencePopupSignal( Calendar *, Incidence *, const TQDate &); void showNewEventPopupSignal(); void itemModified( KOAgendaItem *item ); - void incidenceSelected( Incidence * ); + void incidenceSelected( Incidence *, const TQDate & ); void startMultiModify( const TQString & ); void endMultiModify(); @@ -343,6 +346,7 @@ class KOAgenda : public QScrollView // The KOAgendaItem, which is being moved/resized TQGuardedPtr<KOAgendaItem> mActionItem; + QPair<ResourceCalendar *, TQString> mResPair; // Currently selected item TQGuardedPtr<KOAgendaItem> mSelectedItem; @@ -373,6 +377,8 @@ class KOAgenda : public QScrollView bool mReturnPressed; KOrg::IncidenceChangerBase *mChanger; + + CalendarView *mCalendarView; }; #endif // KOAGENDA_H diff --git a/korganizer/koagendaitem.cpp b/korganizer/koagendaitem.cpp index 629f59c31..de1f4ef87 100644 --- a/korganizer/koagendaitem.cpp +++ b/korganizer/koagendaitem.cpp @@ -63,12 +63,16 @@ TQPixmap *KOAgendaItem::organizerPxmp = 0; //-------------------------------------------------------------------------- -KOAgendaItem::KOAgendaItem( Incidence *incidence, const TQDate &qd, TQWidget *parent, +KOAgendaItem::KOAgendaItem( Calendar *calendar, Incidence *incidence, + const TQDate &qd, TQWidget *parent, + int itemPos, int itemCount, const char *name, WFlags f ) : - TQWidget( parent, name, f ), mIncidence( incidence ), mDate( qd ), + TQWidget( parent, name, f ), mCalendar( calendar ), mIncidence( incidence ), mDate( qd ), mLabelText( mIncidence->summary() ), mIconAlarm( false ), mIconRecur( false ), mIconReadonly( false ), mIconReply( false ), mIconGroup( false ), mIconGroupTentative( false ), mIconOrganizer( false ), + mSpecialEvent( false ), + mItemPos( itemPos ), mItemCount( itemCount ), mMultiItemInfo( 0 ), mStartMoveInfo( 0 ) { setBackgroundMode( Qt::NoBackground ); @@ -83,7 +87,7 @@ KOAgendaItem::KOAgendaItem( Incidence *incidence, const TQDate &qd, TQWidget *pa mSelected = true; select( false ); - KOIncidenceToolTip::add( this, incidence, toolTipGroup() ); + KOIncidenceToolTip::add( this, mCalendar, incidence, mDate, toolTipGroup() ); setAcceptDrops( true ); } @@ -93,7 +97,7 @@ void KOAgendaItem::updateIcons() mIconReadonly = mIncidence->isReadOnly(); mIconRecur = mIncidence->doesRecur(); mIconAlarm = mIncidence->isAlarmEnabled(); - if ( mIncidence->attendeeCount() > 0 ) { + if ( mIncidence->attendeeCount() > 1 ) { if ( KOPrefs::instance()->thatIsMe( mIncidence->organizer().email() ) ) { mIconReply = false; mIconGroup = false; @@ -171,7 +175,6 @@ bool KOAgendaItem::setIncidence( Incidence *i ) return true; } - /* Return height of item in units of agenda cells */ @@ -217,10 +220,12 @@ void KOAgendaItem::setCellY( int YTop, int YBottom ) mCellYBottom = YBottom; } -void KOAgendaItem::setMultiItem(KOAgendaItem *first, KOAgendaItem *prev, - KOAgendaItem *next, KOAgendaItem *last) +void KOAgendaItem::setMultiItem( KOAgendaItem *first, KOAgendaItem *prev, + KOAgendaItem *next, KOAgendaItem *last ) { - if (!mMultiItemInfo) mMultiItemInfo=new MultiItemInfo; + if ( !mMultiItemInfo ) { + mMultiItemInfo = new MultiItemInfo; + } mMultiItemInfo->mFirstMultiItem = first; mMultiItemInfo->mPrevMultiItem = prev; mMultiItemInfo->mNextMultiItem = next; @@ -575,18 +580,16 @@ void KOAgendaItem::dropEvent( TQDropEvent *e ) } #ifndef KORG_NOKABC - TQString vcards; - KABC::VCardConverter converter; - - KVCardDrag::decode( e, vcards ); - KABC::Addressee::List list = converter.parseVCards( vcards ); - KABC::Addressee::List::Iterator it; - for ( it = list.begin(); it != list.end(); ++it ) { - TQString em( (*it).fullEmail() ); - if (em.isEmpty()) { - em=(*it).realName(); + KABC::Addressee::List list; + if ( KVCardDrag::decode( e, list ) ) { + KABC::Addressee::List::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + TQString em( (*it).fullEmail() ); + if ( em.isEmpty() ) { + em = (*it).realName(); + } + addAttendee( em ); } - addAttendee( em ); } #else if( decoded ) { @@ -665,11 +668,21 @@ static void conditionalPaint( TQPainter *p, bool cond, int &x, int ft, void KOAgendaItem::paintEventIcon( TQPainter *p, int &x, int ft ) { if ( !mIncidence ) return; - static const TQPixmap eventPxmp = - KOGlobals::self()->smallIcon( "appointment" ); - if ( mIncidence->type() != "Event" ) - return; - conditionalPaint( p, true, x, ft, eventPxmp ); + + if ( mIncidence->type() == "Event" ) { + TQPixmap eventPxmp; + if ( mIncidence->customProperty( "KABC", "BIRTHDAY" ) == "YES" ) { + mSpecialEvent = true; + if ( mIncidence->customProperty( "KABC", "ANNIVERSARY" ) == "YES" ) { + eventPxmp = KOGlobals::self()->smallIcon( "calendaranniversary" ); + } else { + eventPxmp = KOGlobals::self()->smallIcon( "calendarbirthday" ); + } + conditionalPaint( p, true, x, ft, eventPxmp ); + } + // per kolab/issue4349 we don't draw a regular appointment icon (to save space) + } + } void KOAgendaItem::paintTodoIcon( TQPainter *p, int &x, int ft ) @@ -702,9 +715,11 @@ void KOAgendaItem::paintIcons( TQPainter *p, int &x, int ft ) { paintEventIcon( p, x, ft ); paintTodoIcon( p, x, ft ); - paintAlarmIcon( p, x, ft ); - conditionalPaint( p, mIconRecur, x, ft, *recurPxmp ); - conditionalPaint( p, mIconReadonly, x, ft, *readonlyPxmp ); + if ( !mSpecialEvent ) { + paintAlarmIcon( p, x, ft ); + } + conditionalPaint( p, mIconRecur && !mSpecialEvent, x, ft, *recurPxmp ); + conditionalPaint( p, mIconReadonly && !mSpecialEvent, x, ft, *readonlyPxmp ); conditionalPaint( p, mIconReply, x, ft, *replyPxmp ); conditionalPaint( p, mIconGroup, x, ft, *groupPxmp ); conditionalPaint( p, mIconGroupTentative, x, ft, *groupPxmpTentative ); @@ -762,7 +777,7 @@ void KOAgendaItem::paintEvent( TQPaintEvent *ev ) TQStringList categories = mIncidence->categories(); TQString cat = categories.first(); if (cat.isEmpty()) - categoryColor = KOPrefs::instance()->mEventColor; + categoryColor = KOPrefs::instance()->unsetCategoryColor(); else categoryColor = *(KOPrefs::instance()->categoryColor(cat)); @@ -770,9 +785,6 @@ void KOAgendaItem::paintEvent( TQPaintEvent *ev ) if ( !resourceColor.isValid() ) resourceColor = categoryColor; - if (!KOPrefs::instance()->hasCategoryColor(cat)) - categoryColor = resourceColor; - TQColor frameColor; if ( KOPrefs::instance()->agendaViewColors() == KOPrefs::ResourceOnly || KOPrefs::instance()->agendaViewColors() == KOPrefs::CategoryInsideResourceOutside ) { @@ -790,6 +802,16 @@ void KOAgendaItem::paintEvent( TQPaintEvent *ev ) } } + if ( cat.isEmpty() && + KOPrefs::instance()->agendaViewColors() == KOPrefs::ResourceInsideCategoryOutside ) { + frameColor = bgColor; + } + + if ( cat.isEmpty() && + KOPrefs::instance()->agendaViewColors() == KOPrefs::CategoryInsideResourceOutside ) { + bgColor = frameColor; + } + if ( mSelected ) { frameColor = TQColor( 85 + frameColor.red() * 2/3, 85 + frameColor.green() * 2/3, diff --git a/korganizer/koagendaitem.h b/korganizer/koagendaitem.h index fc774dd1f..f15594428 100644 --- a/korganizer/koagendaitem.h +++ b/korganizer/koagendaitem.h @@ -34,6 +34,7 @@ class TQDragEnterEvent; class TQDropEvent; namespace KCal { +class Calendar; class Incidence; } using namespace KCal; @@ -75,8 +76,10 @@ class KOAgendaItem : public TQWidget, public KOrg::CellItem { Q_OBJECT public: - KOAgendaItem(Incidence *incidence, const TQDate &qd, TQWidget *parent, const char *name=0, - WFlags f=0 ); + KOAgendaItem( Calendar *calendar, Incidence *incidence, const TQDate &qd, + TQWidget *parent, + int itemPos, int itemCount, + const char *name = 0, WFlags f = 0 ); int cellXLeft() const { return mCellXLeft; } int cellXRight() const { return mCellXRight; } @@ -85,6 +88,9 @@ class KOAgendaItem : public TQWidget, public KOrg::CellItem int cellHeight() const; int cellWidth() const; + int itemPos() const { return mItemPos; } + int itemCount() const { return mItemCount; } + void setCellXY(int X, int YTop, int YBottom); void setCellY(int YTop, int YBottom); void setCellX(int XLeft, int XRight); @@ -173,15 +179,19 @@ class KOAgendaItem : public TQWidget, public KOrg::CellItem private: int mCellXLeft, mCellXRight; int mCellYTop, mCellYBottom; - int mSubCell; // subcell number of this item - int mSubCells; // Total number of subcells in cell of this item + Calendar *mCalendar; Incidence *mIncidence; // corresponding event or todo TQDate mDate; //date this events occurs (for recurrence) TQString mLabelText; bool mIconAlarm, mIconRecur, mIconReadonly; bool mIconReply, mIconGroup, mIconGroupTentative; - bool mIconOrganizer; + bool mIconOrganizer, mSpecialEvent; + + // For incidences that expand through more than 1 day + // Will be 1 for single day incidences + int mItemPos; + int mItemCount; // Multi item pointers MultiItemInfo* mMultiItemInfo; diff --git a/korganizer/koagendaview.cpp b/korganizer/koagendaview.cpp index e45493ab2..c60546f7b 100644 --- a/korganizer/koagendaview.cpp +++ b/korganizer/koagendaview.cpp @@ -152,6 +152,7 @@ void KOAlternateLabel::useShortText() TQLabel::setText( mShortText ); TQToolTip::remove( this ); TQToolTip::add( this, mExtensiveText ); + update(); // for kolab/issue4350 } void KOAlternateLabel::useLongText() @@ -160,6 +161,7 @@ void KOAlternateLabel::useLongText() TQLabel::setText( mLongText ); TQToolTip::remove( this ); TQToolTip::add( this, mExtensiveText ); + update(); // for kolab/issue4350 } void KOAlternateLabel::useExtensiveText() @@ -167,7 +169,8 @@ void KOAlternateLabel::useExtensiveText() mTextTypeFixed = true; TQLabel::setText( mExtensiveText ); TQToolTip::remove( this ); - TQToolTip::hide(); + TQToolTip::add( this, "" ); + update(); // for kolab/issue4350 } void KOAlternateLabel::useDefaultText() @@ -176,27 +179,55 @@ void KOAlternateLabel::useDefaultText() squeezeTextToLabel(); } +KOAlternateLabel::TextType KOAlternateLabel::largestFittingTextType() const +{ + TQFontMetrics fm( fontMetrics() ); + const int labelWidth = size().width(); + const int longTextWidth = fm.width( mLongText ); + const int extensiveTextWidth = fm.width( mExtensiveText ); + if ( extensiveTextWidth <= labelWidth ) + return Extensive; + else if ( longTextWidth <= labelWidth ) + return Long; + else + return Short; +} + +void KOAlternateLabel::setFixedType( TextType type ) +{ + switch ( type ) + { + case Extensive: useExtensiveText(); break; + case Long: useLongText(); break; + case Short: useShortText(); break; + } +} + void KOAlternateLabel::squeezeTextToLabel() { - if (mTextTypeFixed) return; - - TQFontMetrics fm(fontMetrics()); - int labelWidth = size().width(); - int textWidth = fm.width(mLongText); - int longTextWidth = fm.width(mExtensiveText); - if (longTextWidth <= labelWidth) { - TQLabel::setText( mExtensiveText ); - TQToolTip::remove( this ); - TQToolTip::hide(); - } else if (textWidth <= labelWidth) { - TQLabel::setText( mLongText ); - TQToolTip::remove( this ); - TQToolTip::add( this, mExtensiveText ); - } else { - TQLabel::setText( mShortText ); - TQToolTip::remove( this ); - TQToolTip::add( this, mExtensiveText ); + if ( mTextTypeFixed ) + return; + + const TextType type = largestFittingTextType(); + switch ( type ) + { + case Extensive: + TQLabel::setText( mExtensiveText ); + TQToolTip::remove( this ); + TQToolTip::add( this, "" ); + break; + case Long: + TQLabel::setText( mLongText ); + TQToolTip::remove( this ); + TQToolTip::add( this, mExtensiveText ); + break; + case Short: + TQLabel::setText( mShortText ); + TQToolTip::remove( this ); + TQToolTip::add( this, mExtensiveText ); + break; } + update(); // for kolab/issue4350 } void KOAlternateLabel::resizeEvent( TQResizeEvent * ) @@ -211,22 +242,21 @@ TQSize KOAlternateLabel::minimumSizeHint() const return sh; } -void KOAlternateLabel::setText( const TQString &text ) { - mLongText = text; - squeezeTextToLabel(); -} - - //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// -KOAgendaView::KOAgendaView(Calendar *cal,TQWidget *parent,const char *name, bool isSideBySide ) : - KOrg::AgendaView (cal,parent,name), mExpandButton( 0 ), mAllowAgendaUpdate( true ), +KOAgendaView::KOAgendaView( Calendar *cal, + CalendarView *calendarView, + TQWidget *parent, + const char *name, + bool isSideBySide ) : + KOrg::AgendaView (cal, parent,name), mExpandButton( 0 ), + mAllowAgendaUpdate( true ), mUpdateItem( 0 ), - mResource( 0 ), mIsSideBySide( isSideBySide ), - mPendingChanges( true ) + mPendingChanges( true ), + mAreDatesInitialized( false ) { mSelectedDates.append(TQDate::currentDate()); @@ -291,7 +321,8 @@ KOAgendaView::KOAgendaView(Calendar *cal,TQWidget *parent,const char *name, bool label->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::WordBreak ); } - mAllDayAgenda = new KOAgenda(1,mAllDayFrame); + mAllDayAgenda = new KOAgenda( 1, calendarView, mAllDayFrame ); + mAllDayAgenda->setCalendar( calendar() ); TQWidget *dummyAllDayRight = new TQWidget(mAllDayFrame); // Create agenda frame @@ -312,7 +343,8 @@ KOAgendaView::KOAgendaView(Calendar *cal,TQWidget *parent,const char *name, bool agendaLayout->addWidget(mTimeLabels,1,0); // Create agenda - mAgenda = new KOAgenda(1,96,KOPrefs::instance()->mHourSize,agendaFrame); + mAgenda = new KOAgenda( 1, 96, KOPrefs::instance()->mHourSize, calendarView, agendaFrame ); + mAgenda->setCalendar( calendar() ); agendaLayout->addMultiCellWidget(mAgenda,1,1,1,2); agendaLayout->setColStretch(1,1); @@ -330,7 +362,7 @@ KOAgendaView::KOAgendaView(Calendar *cal,TQWidget *parent,const char *name, bool // Update widgets to reflect user preferences // updateConfig(); - createDayLabels(); + createDayLabels( true ); if ( !isSideBySide ) { // these blank widgets make the All Day Event box line up with the agenda @@ -363,17 +395,13 @@ KOAgendaView::KOAgendaView(Calendar *cal,TQWidget *parent,const char *name, bool connect( mAgenda, TQT_SIGNAL(upperYChanged(int)), TQT_SLOT(updateEventIndicatorBottom(int))); - connectAgenda( mAgenda, mAgendaPopup, mAllDayAgenda ); - connectAgenda( mAllDayAgenda, mAllDayAgendaPopup, mAgenda); + if ( !readOnly() ) { + connectAgenda( mAgenda, mAgendaPopup, mAllDayAgenda ); + connectAgenda( mAllDayAgenda, mAllDayAgendaPopup, mAgenda); + } - if ( cal ) + if ( cal ) { cal->registerObserver( this ); - - CalendarResources *calres = dynamic_cast<CalendarResources*>( cal ); - if ( calres ) { - connect( calres, TQT_SIGNAL(signalResourceAdded(ResourceCalendar *)), TQT_SLOT(resourcesChanged()) ); - connect( calres, TQT_SIGNAL(signalResourceModified( ResourceCalendar *)), TQT_SLOT(resourcesChanged()) ); - connect( calres, TQT_SIGNAL(signalResourceDeleted(ResourceCalendar *)), TQT_SLOT(resourcesChanged()) ); } } @@ -389,52 +417,53 @@ KOAgendaView::~KOAgendaView() void KOAgendaView::connectAgenda( KOAgenda *agenda, TQPopupMenu *popup, KOAgenda *otherAgenda ) { - connect( agenda, TQT_SIGNAL( showIncidencePopupSignal( Incidence *, const TQDate & ) ), - popup, TQT_SLOT( showIncidencePopup( Incidence *, const TQDate & ) ) ); + connect( agenda, TQT_SIGNAL(showIncidencePopupSignal(Calendar *,Incidence *,const TQDate &)), + popup, TQT_SLOT(showIncidencePopup(Calendar *,Incidence *,const TQDate &)) ); - connect( agenda, TQT_SIGNAL( showNewEventPopupSignal() ), - TQT_SLOT( showNewEventPopup() ) ); + connect( agenda, TQT_SIGNAL(showNewEventPopupSignal()), + TQT_SLOT(showNewEventPopup()) ); - agenda->setCalendar( calendar() ); // Create/Show/Edit/Delete Event - connect( agenda, TQT_SIGNAL( newEventSignal() ), TQT_SIGNAL( newEventSignal() ) ); - - connect( agenda, TQT_SIGNAL( newStartSelectSignal() ), - otherAgenda, TQT_SLOT( clearSelection() ) ); - connect( agenda, TQT_SIGNAL( newStartSelectSignal() ), - TQT_SIGNAL( timeSpanSelectionChanged()) ); - - connect( agenda, TQT_SIGNAL( editIncidenceSignal( Incidence * ) ), - TQT_SIGNAL( editIncidenceSignal( Incidence * ) ) ); - connect( agenda, TQT_SIGNAL( showIncidenceSignal( Incidence * ) ), - TQT_SIGNAL( showIncidenceSignal( Incidence * ) ) ); - connect( agenda, TQT_SIGNAL( deleteIncidenceSignal( Incidence * ) ), - TQT_SIGNAL( deleteIncidenceSignal( Incidence * ) ) ); - - connect( agenda, TQT_SIGNAL( startMultiModify( const TQString & ) ), - TQT_SIGNAL( startMultiModify( const TQString & ) ) ); - connect( agenda, TQT_SIGNAL( endMultiModify() ), - TQT_SIGNAL( endMultiModify() ) ); - - connect( agenda, TQT_SIGNAL( itemModified( KOAgendaItem * ) ), - TQT_SLOT( updateEventDates( KOAgendaItem * ) ) ); - connect( agenda, TQT_SIGNAL( enableAgendaUpdate( bool ) ), - TQT_SLOT( enableAgendaUpdate( bool ) ) ); + connect( agenda, TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &)), + TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &)) ); + + connect( agenda, TQT_SIGNAL(newStartSelectSignal()), + otherAgenda, TQT_SLOT(clearSelection()) ); + connect( agenda, TQT_SIGNAL(newStartSelectSignal()), + TQT_SIGNAL(timeSpanSelectionChanged()) ); + + connect( agenda, TQT_SIGNAL(editIncidenceSignal(Incidence *,const TQDate &)), + TQT_SIGNAL(editIncidenceSignal(Incidence *,const TQDate &)) ); + connect( agenda, TQT_SIGNAL(showIncidenceSignal(Incidence *,const TQDate &)), + TQT_SIGNAL(showIncidenceSignal(Incidence *,const TQDate &)) ); + connect( agenda, TQT_SIGNAL(deleteIncidenceSignal(Incidence *)), + TQT_SIGNAL(deleteIncidenceSignal(Incidence *)) ); + + connect( agenda, TQT_SIGNAL(startMultiModify(const TQString &)), + TQT_SIGNAL(startMultiModify(const TQString &)) ); + connect( agenda, TQT_SIGNAL(endMultiModify()), + TQT_SIGNAL(endMultiModify()) ); + + connect( agenda, TQT_SIGNAL(itemModified(KOAgendaItem *)), + TQT_SLOT(updateEventDates(KOAgendaItem *)) ); + + connect( agenda, TQT_SIGNAL(enableAgendaUpdate(bool)), + TQT_SLOT(enableAgendaUpdate(bool)) ); // drag signals - connect( agenda, TQT_SIGNAL( startDragSignal( Incidence * ) ), - TQT_SLOT( startDrag( Incidence * ) ) ); + connect( agenda, TQT_SIGNAL(startDragSignal(Incidence *)), + TQT_SLOT(startDrag(Incidence *)) ); // synchronize selections - connect( agenda, TQT_SIGNAL( incidenceSelected( Incidence * ) ), - otherAgenda, TQT_SLOT( deselectItem() ) ); - connect( agenda, TQT_SIGNAL( incidenceSelected( Incidence * ) ), - TQT_SIGNAL( incidenceSelected( Incidence * ) ) ); + connect( agenda, TQT_SIGNAL(incidenceSelected(Incidence *,const TQDate &)), + otherAgenda, TQT_SLOT(deselectItem()) ); + connect( agenda, TQT_SIGNAL(incidenceSelected(Incidence *,const TQDate &)), + TQT_SIGNAL(incidenceSelected(Incidence *,const TQDate &)) ); // rescheduling of todos by d'n'd - connect( agenda, TQT_SIGNAL( droppedToDo( Todo *, const TQPoint &, bool ) ), - TQT_SLOT( slotTodoDropped( Todo *, const TQPoint &, bool ) ) ); + connect( agenda, TQT_SIGNAL(droppedToDo(Todo *,const TQPoint &,bool)), + TQT_SLOT(slotTodoDropped(Todo *,const TQPoint &,bool)) ); } @@ -567,14 +596,19 @@ void KOAgendaView::zoomView( const int delta, const TQPoint &pos, } } -void KOAgendaView::createDayLabels() +void KOAgendaView::createDayLabels( bool force ) { // kdDebug(5850) << "KOAgendaView::createDayLabels()" << endl; - // ### Before deleting and recreating we could check if mSelectedDates changed... - // It would remove some flickering and gain speed (since this is called by - // each updateView() call) + // Check if mSelectedDates has changed, if not just return + // Removes some flickering and gains speed (since this is called by each updateView()) + if ( !force && mSaveSelectedDates == mSelectedDates ) { + return; + } + mSaveSelectedDates = mSelectedDates; + delete mDayLabels; + mDateDayLabels.clear(); mDayLabels = new TQFrame (mDayLabelsFrame); mLayoutDayLabels = new TQHBoxLayout(mDayLabels); @@ -598,7 +632,8 @@ void KOAgendaView::createDayLabels() TQString shortstr = TQString::number(calsys->day(date)); KOAlternateLabel *dayLabel = new KOAlternateLabel(shortstr, - longstr, veryLongStr, mDayLabels); + longstr, veryLongStr, mDayLabels); + dayLabel->useShortText(); // will be recalculated in updateDayLabelSizes() anyway dayLabel->setMinimumWidth(1); dayLabel->setAlignment(TQLabel::AlignHCenter); if (date == TQDate::currentDate()) { @@ -607,6 +642,7 @@ void KOAgendaView::createDayLabels() dayLabel->setFont(font); } dayLayout->addWidget(dayLabel); + mDateDayLabels.append( dayLabel ); // if a holiday region is selected, show the holiday name TQStringList texts = KOGlobals::self()->holiday( date ); @@ -646,6 +682,7 @@ void KOAgendaView::createDayLabels() if ( !mIsSideBySide ) mLayoutDayLabels->addSpacing(mAgenda->verticalScrollBar()->width()); mDayLabels->show(); + TQTimer::singleShot( 0, this, TQT_SLOT( updateDayLabelSizes() ) ); } void KOAgendaView::enableAgendaUpdate( bool enable ) @@ -678,7 +715,7 @@ Incidence::List KOAgendaView::selectedIncidences() return selected; } -DateList KOAgendaView::selectedDates() +DateList KOAgendaView::selectedIncidenceDates() { DateList selected; TQDate qd; @@ -766,7 +803,7 @@ void KOAgendaView::updateConfig() setHolidayMasks(); - createDayLabels(); + createDayLabels( true ); updateView(); } @@ -782,12 +819,41 @@ void KOAgendaView::updateTimeBarWidth() mTimeLabels->setFixedWidth( width ); } +void KOAgendaView::updateDayLabelSizes() +{ + // First, calculate the maximum text type that fits for all labels + KOAlternateLabel::TextType overallType = KOAlternateLabel::Extensive; + TQPtrList<KOAlternateLabel>::const_iterator it = mDateDayLabels.constBegin(); + for( ; it != mDateDayLabels.constEnd(); it++ ) { + KOAlternateLabel::TextType type = (*it)->largestFittingTextType(); + if ( type < overallType ) + overallType = type; + } + + // Then, set that maximum text type to all the labels + it = mDateDayLabels.constBegin(); + for( ; it != mDateDayLabels.constEnd(); it++ ) { + (*it)->setFixedType( overallType ); + } +} + +void KOAgendaView::resizeEvent( TQResizeEvent *resizeEvent ) +{ + updateDayLabelSizes(); + KOrg::AgendaView::resizeEvent( resizeEvent ); +} void KOAgendaView::updateEventDates( KOAgendaItem *item ) { - kdDebug(5850) << "KOAgendaView::updateEventDates(): " << item->text() << endl; + kdDebug(5850) << "KOAgendaView::updateEventDates(): " << item->text() + << "; item->cellXLeft(): " << item->cellXLeft() + << "; item->cellYTop(): " << item->cellYTop() + << "; item->lastMultiItem(): " << item->lastMultiItem() + << "; item->itemPos(): " << item->itemPos() + << "; item->itemCount(): " << item->itemCount() + << endl; - TQDateTime startDt,endDt; + TQDateTime startDt, endDt; // Start date of this incidence, calculate the offset from it (so recurring and // non-recurring items can be treated exactly the same, we never need to check @@ -800,17 +866,22 @@ void KOAgendaView::updateEventDates( KOAgendaItem *item ) thisDate = mSelectedDates[ item->cellXLeft() ]; } TQDate oldThisDate( item->itemDate() ); - int daysOffset = oldThisDate.daysTo( thisDate ); + const int daysOffset = oldThisDate.daysTo( thisDate ); int daysLength = 0; -// startDt.setDate( startDate ); + // startDt.setDate( startDate ); Incidence *incidence = item->incidence(); - if ( !incidence ) return; - if ( !mChanger || !mChanger->beginChange(incidence) ) return; + if ( !incidence ) { + return; + } + if ( !mChanger || + !mChanger->beginChange( incidence, resourceCalendar(), subResourceCalendar() ) ) { + return; + } Incidence *oldIncidence = incidence->clone(); - TQTime startTime(0,0,0), endTime(0,0,0); + TQTime startTime( 0, 0, 0 ), endTime( 0, 0, 0 ); if ( incidence->doesFloat() ) { daysLength = item->cellWidth() - 1; } else { @@ -818,12 +889,35 @@ void KOAgendaView::updateEventDates( KOAgendaItem *item ) if ( item->lastMultiItem() ) { endTime = mAgenda->gyToTime( item->lastMultiItem()->cellYBottom() + 1 ); daysLength = item->lastMultiItem()->cellXLeft() - item->cellXLeft(); + kdDebug(5850) << "item->lastMultiItem()->cellXLeft(): " << item->lastMultiItem()->cellXLeft() + << endl; + } else if ( item->itemPos() == item->itemCount() && item->itemCount() > 1 ) { + /* multiitem handling in agenda assumes two things: + - The start (first KOAgendaItem) is always visible. + - The first KOAgendaItem of the incidence has a non-null item->lastMultiItem() + pointing to the last KOagendaItem. + + But those aren't always met, for example when in day-view. + kolab/issue4417 + */ + + // Cornercase 1: - Resizing the end of the event but the start isn't visible + endTime = mAgenda->gyToTime( item->cellYBottom() + 1 ); + daysLength = item->itemCount() - 1; + startTime = incidence->dtStart().time(); + } else if ( item->itemPos() == 1 && item->itemCount() > 1 ) { + // Cornercase 2: - Resizing the start of the event but the end isn't visible + endTime = incidence->dtEnd().time(); + daysLength = item->itemCount() - 1; } else { endTime = mAgenda->gyToTime( item->cellYBottom() + 1 ); } } -// kdDebug(5850) << "KOAgendaView::updateEventDates(): now setting dates" << endl; + kdDebug(5850) << "daysLength: " << daysLength << "; startTime: " << startTime + << "; endTime: " << endTime << "; thisDate: " << thisDate + << "; incidence->dtStart(): " << incidence->dtStart() << endl; + // FIXME: use a visitor here if ( incidence->type() == "Event" ) { startDt = incidence->dtStart(); @@ -831,8 +925,8 @@ void KOAgendaView::updateEventDates( KOAgendaItem *item ) startDt.setTime( startTime ); endDt = startDt.addDays( daysLength ); endDt.setTime( endTime ); - Event*ev = static_cast<Event*>(incidence); - if( incidence->dtStart() == startDt && ev->dtEnd() == endDt ) { + Event* ev = static_cast<Event*>( incidence ); + if ( incidence->dtStart() == startDt && ev->dtEnd() == endDt ) { // No change delete oldIncidence; return; @@ -840,7 +934,7 @@ void KOAgendaView::updateEventDates( KOAgendaItem *item ) incidence->setDtStart( startDt ); ev->setDtEnd( endDt ); } else if ( incidence->type() == "Todo" ) { - Todo *td = static_cast<Todo*>(incidence); + Todo *td = static_cast<Todo*>( incidence ); startDt = td->hasStartDate() ? td->dtStart() : td->dtDue(); startDt = thisDate.addDays( td->dtDue().daysTo( startDt ) ); startDt.setTime( startTime ); @@ -857,8 +951,9 @@ void KOAgendaView::updateEventDates( KOAgendaItem *item ) // functionality will also be available in other views! // TODO_Recurrence: This does not belong here, and I'm not really sure // how it's supposed to work anyway. - Recurrence *recur = incidence->recurrence(); -/* if ( recur->doesRecur() && daysOffset != 0 ) { +/* + Recurrence *recur = incidence->recurrence(); + if ( recur->doesRecur() && daysOffset != 0 ) { switch ( recur->recurrenceType() ) { case Recurrence::rYearlyPos: { int freq = recur->frequency(); @@ -1001,23 +1096,31 @@ void KOAgendaView::updateEventDates( KOAgendaItem *item ) // FIXME: use a visitor here if ( incidence->type() == "Event" ) { incidence->setDtStart( startDt ); - (static_cast<Event*>( incidence ) )->setDtEnd( endDt ); + static_cast<Event*>( incidence )->setDtEnd( endDt ); } else if ( incidence->type() == "Todo" ) { Todo *td = static_cast<Todo*>( incidence ); - if ( td->hasStartDate() ) + if ( td->hasStartDate() ) { td->setDtStart( startDt ); + } td->setDtDue( endDt ); } item->setItemDate( startDt.date() ); KOIncidenceToolTip::remove( item ); - KOIncidenceToolTip::add( item, incidence, KOAgendaItem::toolTipGroup() ); + KOIncidenceToolTip::add( item, calendar(), incidence, thisDate, KOAgendaItem::toolTipGroup() ); - mChanger->changeIncidence( oldIncidence, incidence ); - mChanger->endChange(incidence); + const bool result = mChanger->changeIncidence( oldIncidence, incidence, + KOGlobals::DATE_MODIFIED, this ); + mChanger->endChange( incidence, resourceCalendar(), subResourceCalendar() ); delete oldIncidence; + if ( !result ) { + mPendingChanges = true; + TQTimer::singleShot( 0, this, TQT_SLOT(updateView()) ); + return; + } + // don't update the agenda as the item already has the correct coordinates. // an update would delete the current item and recreate it, but we are still // using a pointer to that item! => CRASH @@ -1056,99 +1159,141 @@ void KOAgendaView::showDates( const TQDate &start, const TQDate &end ) mSelectedDates.clear(); TQDate d = start; - while (d <= end) { - mSelectedDates.append(d); + while ( d <= end ) { + mSelectedDates.append( d ); d = d.addDays( 1 ); } + mAreDatesInitialized = true; + // and update the view fillAgenda(); } -void KOAgendaView::showIncidences( const Incidence::List & ) +void KOAgendaView::showIncidences( const Incidence::List &, const TQDate & ) { kdDebug(5850) << "KOAgendaView::showIncidences( const Incidence::List & ) is not yet implemented" << endl; } -void KOAgendaView::insertIncidence( Incidence *incidence, const TQDate &curDate, - int curCol ) +void KOAgendaView::insertIncidence( Incidence *incidence, const TQDate &curDate ) { - if ( !filterByResource( incidence ) ) + if ( !filterByResource( incidence ) ) { return; + } // FIXME: Use a visitor here, or some other method to get rid of the dynamic_cast's Event *event = dynamic_cast<Event *>( incidence ); Todo *todo = dynamic_cast<Todo *>( incidence ); + int curCol = mSelectedDates.first().daysTo( curDate ); + + // In case incidence->dtStart() isn't visible (crosses bounderies) if ( curCol < 0 ) { - curCol = mSelectedDates.findIndex( curDate ); + curCol = 0; } + // The date for the event is not displayed, just ignore it - if ( curCol < 0 || curCol > int( mSelectedDates.size() ) ) + if ( curCol >= int( mSelectedDates.count() ) ) { return; + } + + // Default values, which can never be reached + mMinY[curCol] = mAgenda->timeToY( TQTime( 23, 59 ) ) + 1; + mMaxY[curCol] = mAgenda->timeToY( TQTime( 0, 0 ) ) - 1; int beginX; int endX; + TQDate columnDate; if ( event ) { - beginX = curDate.daysTo( incidence->dtStart().date() ) + curCol; - endX = curDate.daysTo( event->dateEnd() ) + curCol; + TQDate firstVisibleDate = mSelectedDates.first(); + // its crossing bounderies, lets calculate beginX and endX + if ( curDate < firstVisibleDate ) { + beginX = curCol + firstVisibleDate.daysTo( curDate ); + endX = beginX + event->dtStart().daysTo( event->dtEnd() ); + columnDate = firstVisibleDate; + } else { + beginX = curCol; + endX = beginX + event->dtStart().daysTo( event->dtEnd() ); + columnDate = curDate; + } } else if ( todo ) { - if ( ! todo->hasDueDate() ) return; // todo shall not be displayed if it has no date - beginX = curDate.daysTo( todo->dtDue().date() ) + curCol; - endX = beginX; + if ( !todo->hasDueDate() ) { + return; // todo shall not be displayed if it has no date + } + columnDate = curDate; + beginX = endX = curCol; + } else { return; } - if ( todo && todo->isOverdue() ) { - mAllDayAgenda->insertAllDayItem( incidence, curDate, curCol, curCol ); - } else if ( incidence->doesFloat() ) { -// FIXME: This breaks with recurring multi-day events! - if ( incidence->recurrence()->doesRecur() ) { - mAllDayAgenda->insertAllDayItem( incidence, curDate, curCol, curCol ); - } else { - // Insert multi-day events only on the first day, otherwise it will - // appear multiple times - if ( ( beginX <= 0 && curCol == 0 ) || beginX == curCol ) { - mAllDayAgenda->insertAllDayItem( incidence, curDate, beginX, endX ); - } - } + mAllDayAgenda->insertAllDayItem( incidence, columnDate, curCol, curCol ); + } else if ( incidence->doesFloat() || + ( todo && + !todo->dtDue().isValid() ) ) { + mAllDayAgenda->insertAllDayItem( incidence, columnDate, beginX, endX ); } else if ( event && event->isMultiDay() ) { int startY = mAgenda->timeToY( event->dtStart().time() ); - TQTime endtime( event->dtEnd().time() ); - if ( endtime == TQTime( 0, 0, 0 ) ) endtime = TQTime( 23, 59, 59 ); + TQTime endtime = event->dtEnd().time(); + if ( endtime == TQTime( 0, 0, 0 ) ) { + endtime = TQTime( 23, 59, 59 ); + } int endY = mAgenda->timeToY( endtime ) - 1; - if ( (beginX <= 0 && curCol == 0) || beginX == curCol ) { - mAgenda->insertMultiItem( event, curDate, beginX, endX, startY, endY ); + if ( ( beginX <= 0 && curCol == 0 ) || beginX == curCol ) { + mAgenda->insertMultiItem( event, columnDate, beginX, endX, startY, endY ); + } if ( beginX == curCol ) { - mMaxY[curCol] = mAgenda->timeToY( TQTime(23,59) ); - if ( startY < mMinY[curCol] ) mMinY[curCol] = startY; + mMaxY[curCol] = mAgenda->timeToY( TQTime( 23, 59 ) ); + if ( startY < mMinY[curCol] ) { + mMinY[curCol] = startY; + } } else if ( endX == curCol ) { - mMinY[curCol] = mAgenda->timeToY( TQTime(0,0) ); - if ( endY > mMaxY[curCol] ) mMaxY[curCol] = endY; + mMinY[curCol] = mAgenda->timeToY( TQTime( 0, 0 ) ); + if ( endY > mMaxY[curCol] ) { + mMaxY[curCol] = endY; + } } else { - mMinY[curCol] = mAgenda->timeToY( TQTime(0,0) ); - mMaxY[curCol] = mAgenda->timeToY( TQTime(23,59) ); + mMinY[curCol] = mAgenda->timeToY( TQTime( 0, 0 ) ); + mMaxY[curCol] = mAgenda->timeToY( TQTime( 23, 59 ) ); } } else { int startY = 0, endY = 0; if ( event ) { startY = mAgenda->timeToY( incidence->dtStart().time() ); - TQTime endtime( event->dtEnd().time() ); - if ( endtime == TQTime( 0, 0, 0 ) ) endtime = TQTime( 23, 59, 59 ); + TQTime endtime = event->dtEnd().time(); + if ( endtime == TQTime( 0, 0, 0 ) ) { + endtime = TQTime( 23, 59, 59 ); + } endY = mAgenda->timeToY( endtime ) - 1; } if ( todo ) { TQTime t = todo->dtDue().time(); - endY = mAgenda->timeToY( t ) - 1; - startY = mAgenda->timeToY( t.addSecs( -1800 ) ); + + if ( t == TQTime( 0, 0 ) ) { + t = TQTime( 23, 59 ); + } + + int halfHour = 1800; + if ( t.addSecs( -halfHour ) < t ) { + startY = mAgenda->timeToY( t.addSecs( -halfHour ) ); + endY = mAgenda->timeToY( t ) - 1; + } else { + startY = 0; + endY = mAgenda->timeToY( t.addSecs( halfHour ) ) - 1; + } + } + if ( endY < startY ) { + endY = startY; + } + mAgenda->insertItem( incidence, columnDate, curCol, startY, endY, 1, 1 ); + if ( startY < mMinY[curCol] ) { + mMinY[curCol] = startY; + } + if ( endY > mMaxY[curCol] ) { + mMaxY[curCol] = endY; } - if ( endY < startY ) endY = startY; - mAgenda->insertItem( incidence, curDate, curCol, startY, endY ); - if ( startY < mMinY[curCol] ) mMinY[curCol] = startY; - if ( endY > mMaxY[curCol] ) mMaxY[curCol] = endY; } } @@ -1156,75 +1301,53 @@ void KOAgendaView::changeIncidenceDisplayAdded( Incidence *incidence ) { Todo *todo = dynamic_cast<Todo *>(incidence); CalFilter *filter = calendar()->filter(); - if ( filter && !filter->filterIncidence( incidence ) || - ( todo && !KOPrefs::instance()->showAllDayTodo() ) ) - return; - - TQDate f = mSelectedDates.first(); - TQDate l = mSelectedDates.last(); - TQDate startDt = incidence->dtStart().date(); - - if ( incidence->doesRecur() ) { - DateList::ConstIterator dit; - TQDate curDate; - for( dit = mSelectedDates.begin(); dit != mSelectedDates.end(); ++dit ) { - curDate = *dit; -// FIXME: This breaks with recurring multi-day events! - if ( incidence->recursOn( curDate, calendar() ) ) { - insertIncidence( incidence, curDate ); - } - } + if ( ( filter && !filter->filterIncidence( incidence ) ) || + ( ( todo && !KOPrefs::instance()->showAllDayTodo() ) ) ) { return; } - TQDate endDt; - if ( incidence->type() == "Event" ) - endDt = (static_cast<Event *>(incidence))->dateEnd(); - if ( todo ) { - endDt = todo->isOverdue() ? TQDate::currentDate() - : todo->dtDue().date(); - - if ( endDt >= f && endDt <= l ) { - insertIncidence( incidence, endDt ); - return; - } - } - - if ( startDt >= f && startDt <= l ) { - insertIncidence( incidence, startDt ); - } + displayIncidence( incidence ); } void KOAgendaView::changeIncidenceDisplay( Incidence *incidence, int mode ) { switch ( mode ) { - case KOGlobals::INCIDENCEADDED: { - // Add an event. No need to recreate the whole view! - // recreating everything even causes troubles: dropping to the day matrix - // recreates the agenda items, but the evaluation is still in an agendaItems' code, - // which was deleted in the mean time. Thus KOrg crashes... - if ( mAllowAgendaUpdate ) - changeIncidenceDisplayAdded( incidence ); + case KOGlobals::INCIDENCEADDED: + { + // Add an event. No need to recreate the whole view! + // recreating everything even causes troubles: dropping to the + // day matrix recreates the agenda items, but the evaluation is + // still in an agendaItems' code, which was deleted in the mean time. + // Thus KOrg crashes... + changeIncidenceDisplayAdded( incidence ); + updateEventIndicators(); break; } - case KOGlobals::INCIDENCEEDITED: { - if ( !mAllowAgendaUpdate ) { - updateEventIndicators(); - } else { + case KOGlobals::INCIDENCEEDITED: + { + if ( mAllowAgendaUpdate ) { removeIncidence( incidence ); - updateEventIndicators(); changeIncidenceDisplayAdded( incidence ); } + updateEventIndicators(); break; } - case KOGlobals::INCIDENCEDELETED: { - mAgenda->removeIncidence( incidence ); - mAllDayAgenda->removeIncidence( incidence ); + case KOGlobals::INCIDENCEDELETED: + { + removeIncidence( incidence ); updateEventIndicators(); break; } default: - updateView(); + return; + } + + // HACK: Update the view if the all-day agenda has been modified. + // Do this because there are some layout problems in the + // all-day agenda that are not easily solved, but clearing + // and redrawing works ok. + if ( incidence->doesFloat() ) { + updateView(); } } @@ -1235,6 +1358,10 @@ void KOAgendaView::fillAgenda( const TQDate & ) void KOAgendaView::fillAgenda() { + if ( !mAreDatesInitialized ) { + return; + } + mPendingChanges = false; /* Remember the uids of the selected items. In case one of the @@ -1245,115 +1372,146 @@ void KOAgendaView::fillAgenda() enableAgendaUpdate( true ); clearView(); - mAllDayAgenda->changeColumns(mSelectedDates.count()); - mAgenda->changeColumns(mSelectedDates.count()); - mEventIndicatorTop->changeColumns(mSelectedDates.count()); - mEventIndicatorBottom->changeColumns(mSelectedDates.count()); + mAllDayAgenda->changeColumns( mSelectedDates.count() ); + mAgenda->changeColumns( mSelectedDates.count() ); + mEventIndicatorTop->changeColumns( mSelectedDates.count() ); + mEventIndicatorBottom->changeColumns( mSelectedDates.count() ); - createDayLabels(); + createDayLabels( false ); setHolidayMasks(); - mMinY.resize(mSelectedDates.count()); - mMaxY.resize(mSelectedDates.count()); + mMinY.resize( mSelectedDates.count() ); + mMaxY.resize( mSelectedDates.count() ); - Event::List dayEvents; + mAgenda->setDateList( mSelectedDates ); - // ToDo items shall be displayed for the day they are due, but only shown today if they are already overdue. - // Therefore, get all of them. - Todo::List todos = calendar()->todos(); - - mAgenda->setDateList(mSelectedDates); + bool somethingReselected = false; + Incidence::List incidences = calendar()->incidences(); - TQDate today = TQDate::currentDate(); + for ( Incidence::List::ConstIterator it = incidences.begin(); it!=incidences.constEnd(); ++it ) { + Incidence *incidence = (*it); + displayIncidence( incidence ); - bool somethingReselected = false; - DateList::ConstIterator dit; - int curCol = 0; - for( dit = mSelectedDates.begin(); dit != mSelectedDates.end(); ++dit ) { - TQDate currentDate = *dit; -// kdDebug(5850) << "KOAgendaView::fillAgenda(): " << currentDate.toString() -// << endl; - - dayEvents = calendar()->events(currentDate, - EventSortStartDate, - SortDirectionAscending); - - // Default values, which can never be reached - mMinY[curCol] = mAgenda->timeToY(TQTime(23,59)) + 1; - mMaxY[curCol] = mAgenda->timeToY(TQTime(0,0)) - 1; - - unsigned int numEvent; - for(numEvent=0;numEvent<dayEvents.count();++numEvent) { - Event *event = *dayEvents.at(numEvent); -// kdDebug(5850) << " Event: " << event->summary() << endl; - insertIncidence( event, currentDate, curCol ); - if( event->uid() == selectedAgendaUid && !selectedAgendaUid.isNull() ) { - mAgenda->selectItemByUID( event->uid() ); - somethingReselected = true; - } - if( event->uid() == selectedAllDayAgendaUid && !selectedAllDayAgendaUid.isNull() ) { - mAllDayAgenda->selectItemByUID( event->uid() ); - somethingReselected = true; - } + if( incidence->uid() == selectedAgendaUid && !selectedAgendaUid.isNull() ) { + mAgenda->selectItemByUID( incidence->uid() ); + somethingReselected = true; + } + if( incidence->uid() == selectedAllDayAgendaUid && !selectedAllDayAgendaUid.isNull() ) { + mAllDayAgenda->selectItemByUID( incidence->uid() ); + somethingReselected = true; } -// if (numEvent == 0) kdDebug(5850) << " No events" << endl; + } + + mAgenda->checkScrollBoundaries(); + updateEventIndicators(); + + // mAgenda->viewport()->update(); + // mAllDayAgenda->viewport()->update(); - // ---------- [display Todos -------------- - if ( KOPrefs::instance()->showAllDayTodo() ) { - unsigned int numTodo; - for (numTodo = 0; numTodo < todos.count(); ++numTodo) { - Todo *todo = *todos.at(numTodo); + // make invalid + deleteSelectedDateTime(); - if ( ! todo->hasDueDate() ) continue; // todo shall not be displayed if it has no date + if( !somethingReselected ) { + emit incidenceSelected( 0, TQDate() ); + } +} - if ( !filterByResource( todo ) ) continue; +void KOAgendaView::displayIncidence( Incidence *incidence ) +{ + TQDate today = TQDate::currentDate(); + DateTimeList::iterator t; - // ToDo items shall be displayed for the day they are due, but only showed today if they are already overdue. - // Already completed items can be displayed on their original due date - bool overdue = todo->isOverdue(); + // FIXME: use a visitor here + Todo *todo = dynamic_cast<Todo *>( incidence ); + Event *event = dynamic_cast<Event *>( incidence ); - if ( (( todo->dtDue().date() == currentDate) && !overdue) || - (( currentDate == today) && overdue) || - ( todo->recursOn( currentDate ) ) ) { - if ( todo->doesFloat() || overdue ) { // Todo has no due-time set or is already overdue - //kdDebug(5850) << "todo without time:" << todo->dtDueDateStr() << ";" << todo->summary() << endl; + TQDateTime firstVisibleDateTime = mSelectedDates.first(); + TQDateTime lastVisibleDateTime = mSelectedDates.last(); - mAllDayAgenda->insertAllDayItem(todo, currentDate, curCol, curCol); - } else { - //kdDebug(5850) << "todo with time:" << todo->dtDueStr() << ";" << todo->summary() << endl; + lastVisibleDateTime.setTime( TQTime( 23, 59, 59, 59 ) ); + firstVisibleDateTime.setTime( TQTime( 0, 0 ) ); + DateTimeList dateTimeList; - int endY = mAgenda->timeToY(todo->dtDue().time()) - 1; - int startY = endY - 1; + TQDateTime incDtStart = incidence->dtStart(); + TQDateTime incDtEnd = incidence->dtEnd(); - mAgenda->insertItem(todo,currentDate,curCol,startY,endY); + if ( todo && + ( !KOPrefs::instance()->showAllDayTodo() || !todo->hasDueDate() ) ) { + return; + } - if (startY < mMinY[curCol]) mMinY[curCol] = startY; - if (endY > mMaxY[curCol]) mMaxY[curCol] = endY; - } - } + if ( incidence->doesRecur() ) { + int eventDuration = event ? incDtStart.daysTo( incDtEnd ) : 0; + + // if there's a multiday event that starts before firstVisibleDateTime but ends after + // lets include it. timesInInterval() ignores incidences that aren't totaly inside + // the range + TQDateTime startDateTimeWithOffset = firstVisibleDateTime.addDays( -eventDuration ); + dateTimeList = + incidence->recurrence()->timesInInterval( startDateTimeWithOffset, + lastVisibleDateTime ); + } else { + TQDateTime dateToAdd; // date to add to our date list + TQDateTime incidenceStart; + TQDateTime incidenceEnd; + + if ( todo && todo->hasDueDate() && !todo->isOverdue() ) { + // If it's not overdue it will be shown at the original date (not today) + dateToAdd = todo->dtDue(); + + // To-dos are drawn with the bottom of the rectangle at dtDue + // if dtDue is at 00:00, then it should be displayed in the previous day, at 23:59 + if ( !todo->doesFloat() && dateToAdd.time() == TQTime( 0, 0 ) ) { + dateToAdd = dateToAdd.addSecs( -1 ); } - } - // ---------- display Todos] -------------- - ++curCol; - } + incidenceEnd = dateToAdd; + } else if ( event ) { + dateToAdd = incDtStart; + incidenceEnd = incDtEnd; + } - mAgenda->checkScrollBoundaries(); - updateEventIndicators(); + if ( incidence->doesFloat() ) { + // so comparisons with < > actually work + dateToAdd.setTime( TQTime( 0, 0 ) ); + incidenceEnd.setTime( TQTime( 23, 59, 59, 59 ) ); + } -// mAgenda->viewport()->update(); -// mAllDayAgenda->viewport()->update(); + if ( dateToAdd <= lastVisibleDateTime && incidenceEnd > firstVisibleDateTime ) { + dateTimeList += dateToAdd; + } + } -// make invalid - deleteSelectedDateTime(); + // ToDo items shall be displayed today if they are already overdude + TQDateTime dateTimeToday = today; + if ( todo && + todo->isOverdue() && + dateTimeToday >= firstVisibleDateTime && + dateTimeToday <= lastVisibleDateTime ) { + + bool doAdd = true; + + if ( todo->doesRecur() ) { + /* If there's a recurring instance showing up today don't add "today" again + * we don't want the event to appear duplicated */ + for ( t = dateTimeList.begin(); t != dateTimeList.end(); ++t ) { + if ( (*t).date() == today ) { + doAdd = false; + break; + } + } + } - if( !somethingReselected ) { - emit incidenceSelected( 0 ); + if ( doAdd ) { + dateTimeList += dateTimeToday; + } } -// kdDebug(5850) << "Fill Agenda done" << endl; + for ( t = dateTimeList.begin(); t != dateTimeList.end(); ++t ) { + insertIncidence( incidence, (*t).date() ); + } } void KOAgendaView::clearView() @@ -1373,7 +1531,7 @@ void KOAgendaView::updateEventIndicatorTop( int newY ) { uint i; for( i = 0; i < mMinY.size(); ++i ) { - mEventIndicatorTop->enableColumn( i, newY >= mMinY[i] ); + mEventIndicatorTop->enableColumn( i, newY > mMinY[i] ); } mEventIndicatorTop->update(); } @@ -1399,12 +1557,14 @@ void KOAgendaView::slotTodoDropped( Todo *todo, const TQPoint &gpos, bool allDay if ( existingTodo ) { kdDebug(5850) << "Drop existing Todo" << endl; Todo *oldTodo = existingTodo->clone(); - if ( mChanger && mChanger->beginChange( existingTodo ) ) { + if ( mChanger && + mChanger->beginChange( existingTodo, resourceCalendar(), subResourceCalendar() ) ) { existingTodo->setDtDue( newTime ); existingTodo->setFloats( allDay ); existingTodo->setHasDueDate( true ); - mChanger->changeIncidence( oldTodo, existingTodo ); - mChanger->endChange( existingTodo ); + mChanger->changeIncidence( oldTodo, existingTodo, + KOGlobals::DATE_MODIFIED, this ); + mChanger->endChange( existingTodo, resourceCalendar(), subResourceCalendar() ); } else { KMessageBox::sorry( this, i18n("Unable to modify this to-do, " "because it cannot be locked.") ); @@ -1415,7 +1575,7 @@ void KOAgendaView::slotTodoDropped( Todo *todo, const TQPoint &gpos, bool allDay todo->setDtDue( newTime ); todo->setFloats( allDay ); todo->setHasDueDate( true ); - if ( !mChanger->addIncidence( todo, this ) ) { + if ( !mChanger->addIncidence( todo, 0, TQString(), this ) ) { KODialogManager::errorSaveIncidence( this, todo ); } } @@ -1468,6 +1628,10 @@ void KOAgendaView::writeSettings(KConfig *config) void KOAgendaView::setHolidayMasks() { + if ( mSelectedDates.isEmpty() || !mSelectedDates[0].isValid() ) { + return; + } + mHolidayMask.resize( mSelectedDates.count() + 1 ); for( uint i = 0; i < mSelectedDates.count(); ++i ) { @@ -1579,23 +1743,34 @@ void KOAgendaView::clearTimeSpanSelection() deleteSelectedDateTime(); } -void KOAgendaView::setResource(KCal::ResourceCalendar * res, const TQString & subResource) -{ - mResource = res; - mSubResource = subResource; -} +bool KOAgendaView::filterByResource( Incidence *incidence ) +{ + // Special handling for groupware to-dos that are in Task folders. + // Put them in the top-level "Calendar" folder for lack of a better + // place since we never show Task type folders even in the + // multiagenda view. + if ( resourceCalendar() && incidence->type() == "Todo" ) { + TQString subRes = resourceCalendar()->subresourceIdentifier( incidence ); + if ( resourceCalendar()->subresourceType( subRes ) == "todo" ) { + TQString calmatch = "/.INBOX.directory/Calendar"; + TQString i18nmatch = "/.INBOX.directory/" + i18n( "Calendar" ); + if ( subResourceCalendar().contains( calmatch ) || + subResourceCalendar().contains( i18nmatch ) ) { + return true; + } + } + } -bool KOAgendaView::filterByResource(Incidence * incidence) -{ - if ( !mResource ) + // Normal handling + if ( !resourceCalendar() ) return true; CalendarResources *calRes = dynamic_cast<CalendarResources*>( calendar() ); if ( !calRes ) return true; - if ( calRes->resource( incidence ) != mResource ) + if ( calRes->resource( incidence ) != resourceCalendar() ) return false; - if ( !mSubResource.isEmpty() ) { - if ( mResource->subresourceIdentifier( incidence ) != mSubResource ) + if ( !subResourceCalendar().isEmpty() ) { + if ( resourceCalendar()->subresourceIdentifier( incidence ) != subResourceCalendar() ) return false; } return true; @@ -1618,7 +1793,7 @@ void KOAgendaView::calendarIncidenceChanged(Incidence * incidence) mPendingChanges = true; } -void KOAgendaView::calendarIncidenceRemoved(Incidence * incidence) +void KOAgendaView::calendarIncidenceDeleted(Incidence * incidence) { Q_UNUSED( incidence ); mPendingChanges = true; diff --git a/korganizer/koagendaview.h b/korganizer/koagendaview.h index 1a16b2bb7..a31581a01 100644 --- a/korganizer/koagendaview.h +++ b/korganizer/koagendaview.h @@ -31,6 +31,7 @@ #include <libkcal/calendar.h> #include "calprinter.h" +#include "calendarview.h" #include "agendaview.h" @@ -43,10 +44,6 @@ class KOAgendaItem; class TimeLabels; class KConfig; -namespace KCal { - class ResourceCalendar; -} - namespace KOrg { class IncidenceChangerBase; } @@ -85,8 +82,11 @@ class KOAlternateLabel : public QLabel virtual TQSize minimumSizeHint() const; + enum TextType { Short = 0, Long = 1, Extensive = 2 }; + TextType largestFittingTextType() const; + void setFixedType( TextType type ); + public slots: - void setText( const TQString & ); void useShortText(); void useLongText(); void useExtensiveText(); @@ -107,11 +107,13 @@ class KOAgendaView : public KOrg::AgendaView, public KCal::Calendar::Observer { Q_OBJECT public: - KOAgendaView( Calendar *cal, TQWidget *parent = 0, const char *name = 0, bool isSideBySide = false ); + KOAgendaView( Calendar *cal, + CalendarView *calendarView, + TQWidget *parent = 0, + const char *name = 0, + bool isSideBySide = false ); virtual ~KOAgendaView(); - - /** Returns maximum number of days supported by the koagendaview */ virtual int maxDatesHint(); @@ -122,7 +124,7 @@ class KOAgendaView : public KOrg::AgendaView, public KCal::Calendar::Observer virtual Incidence::List selectedIncidences(); /** returns the currently selected events */ - virtual DateList selectedDates(); + virtual DateList selectedIncidenceDates(); /** return the default start/end date/time for new events */ virtual bool eventDurationHint(TQDateTime &startDt, TQDateTime &endDt, bool &allDay); @@ -145,24 +147,22 @@ class KOAgendaView : public KOrg::AgendaView, public KCal::Calendar::Observer void setTypeAheadReceiver( TQObject * ); - /** Show only incidences from the given resource. */ - void setResource( KCal::ResourceCalendar *res, const TQString &subResource = TQString::null ); - KOAgenda* agenda() const { return mAgenda; } TQSplitter* splitter() const { return mSplitterAgenda; } + TQFrame *dayLabels() const { return mDayLabels; } /* reimplmented from KCal::Calendar::Observer */ void calendarIncidenceAdded( Incidence *incidence ); void calendarIncidenceChanged( Incidence *incidence ); - void calendarIncidenceRemoved( Incidence *incidence ); + void calendarIncidenceDeleted( Incidence *incidence ); public slots: virtual void updateView(); virtual void updateConfig(); virtual void showDates( const TQDate &start, const TQDate &end ); - virtual void showIncidences( const Incidence::List &incidenceList ); + virtual void showIncidences( const Incidence::List &incidenceList, const TQDate &date ); - void insertIncidence( Incidence *incidence, const TQDate &curDate, int curCol = -1 ); + void insertIncidence( Incidence *incidence, const TQDate &curDate ); void changeIncidenceDisplayAdded( Incidence *incidence ); void changeIncidenceDisplay( Incidence *incidence, int mode ); @@ -215,7 +215,7 @@ class KOAgendaView : public KOrg::AgendaView, public KCal::Calendar::Observer void connectAgenda( KOAgenda*agenda, TQPopupMenu*popup, KOAgenda* otherAgenda ); /** Create labels for the selected dates. */ - void createDayLabels(); + void createDayLabels( bool force ); /** Set the masks on the agenda widgets indicating, which days are holidays. @@ -231,6 +231,8 @@ class KOAgendaView : public KOrg::AgendaView, public KCal::Calendar::Observer void updateTimeBarWidth(); + virtual void resizeEvent( TQResizeEvent *resizeEvent ); + protected slots: /** Update event belonging to agenda item */ void updateEventDates( KOAgendaItem *item ); @@ -245,14 +247,18 @@ class KOAgendaView : public KOrg::AgendaView, public KCal::Calendar::Observer /** Updates data for selected timespan for all day event*/ void newTimeSpanSelectedAllDay( const TQPoint &start, const TQPoint &end ); + void updateDayLabelSizes(); + private: bool filterByResource( Incidence *incidence ); + void displayIncidence( Incidence *incidence ); private: // view widgets TQFrame *mDayLabels; TQHBox *mDayLabelsFrame; TQBoxLayout *mLayoutDayLabels; + TQPtrList<KOAlternateLabel> mDateDayLabels; TQFrame *mAllDayFrame; KOAgenda *mAllDayAgenda; KOAgenda *mAgenda; @@ -262,6 +268,7 @@ class KOAgendaView : public KOrg::AgendaView, public KCal::Calendar::Observer TQPushButton *mExpandButton; DateList mSelectedDates; // List of dates to be displayed + DateList mSaveSelectedDates; // Save the list of dates between updateViews int mViewType; KOEventPopupMenu *mAgendaPopup; @@ -285,11 +292,16 @@ class KOAgendaView : public KOrg::AgendaView, public KCal::Calendar::Observer Incidence *mUpdateItem; - KCal::ResourceCalendar *mResource; - TQString mSubResource; - bool mIsSideBySide; bool mPendingChanges; + + // the current date is inserted into mSelectedDates in the constructor + // however whe should only show events when setDates is called, otherwise + // we see day view with current date for a few milisecs, then we see something else + // because someone called setDates with the real dates that should be displayed. + // Other solution would be not initializing mSelectedDates in the ctor, but that requires + // lots of changes in koagenda.cpp and koagendaview.cpp + bool mAreDatesInitialized; }; #endif diff --git a/korganizer/koattendeeeditor.cpp b/korganizer/koattendeeeditor.cpp index 370ac3b32..8766a3338 100644 --- a/korganizer/koattendeeeditor.cpp +++ b/korganizer/koattendeeeditor.cpp @@ -18,6 +18,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include <config.h> // for KDEPIM_NEW_DISTRLISTS + #include "koattendeeeditor.h" #include "koprefs.h" #include "koglobals.h" @@ -32,8 +34,16 @@ #include <libemailfunctions/email.h> +#ifdef KDEPIM_NEW_DISTRLISTS +#include "distributionlist.h" +#else +#include <kabc/distributionlist.h> +#endif +#include <kabc/stdaddressbook.h> + #include <kiconloader.h> #include <klocale.h> +#include <kmessagebox.h> #include <tqcheckbox.h> #include <tqcombobox.h> @@ -101,6 +111,7 @@ void KOAttendeeEditor::initEditWidgets(TQWidget * parent, TQBoxLayout * layout) mNameEdit->installEventFilter( this ); connect( mNameEdit, TQT_SIGNAL( textChanged( const TQString & ) ), TQT_SLOT( updateAttendee() ) ); + connect( mNameEdit, TQT_SIGNAL(returnPressed()), TQT_SLOT(expandAttendee()) ); topLayout->addMultiCellWidget( mNameEdit, 0, 0, 1, 2 ); whatsThis = i18n("Edits the role of the attendee selected " @@ -206,20 +217,6 @@ void KOAttendeeEditor::openAddressBook() } delete dia; return; -#if 0 - // old code - KABC::Addressee a = KABC::AddresseeDialog::getAddressee(this); - if (!a.isEmpty()) { - // If this is myself, I don't want to get a response but instead - // assume I will be available - bool myself = KOPrefs::instance()->thatIsMe( a.preferredEmail() ); - KCal::Attendee::PartStat partStat = - myself ? KCal::Attendee::Accepted : KCal::Attendee::NeedsAction; - insertAttendee( new Attendee( a.realName(), a.preferredEmail(), - !myself, partStat, - KCal::Attendee::ReqParticipant, a.uid() ) ); - } -#endif #endif } @@ -236,12 +233,13 @@ void KOAttendeeEditor::insertAttendeeFromAddressee(const KABC::Addressee &a, con rsvp = false; } Attendee *newAt = new Attendee( a.realName(), - a.preferredEmail(), - !myself, partStat, - at ? at->role() : Attendee::ReqParticipant, - a.uid() ); + a.preferredEmail(), + !myself, partStat, + at ? at->role() : Attendee::ReqParticipant, + a.uid() ); newAt->setRSVP( rsvp ); insertAttendee( newAt, true ); + mnewAttendees.append( newAt ); } void KOAttendeeEditor::fillOrganizerCombo() @@ -260,10 +258,21 @@ void KOAttendeeEditor::fillOrganizerCombo() void KOAttendeeEditor::addNewAttendee() { + // check if there's still an unchanged example entry, and if so + // suggest to edit that first + if ( TQListViewItem* item = hasExampleAttendee() ) { + KMessageBox::information( this, + i18n( "Please edit the example attendee, before adding more." ), TQString::null, + "EditExistingExampleAttendeeFirst" ); + // make sure the example attendee is selected + item->setSelected( true ); + item->listView()->setCurrentItem( item ); + return; + } Attendee *a = new Attendee( i18n("Firstname Lastname"), i18n("name") + "@example.net", true ); insertAttendee( a, false ); - mnewAttendees.append(a); + mnewAttendees.append( a ); updateAttendeeInput(); // We don't want the hint again mNameEdit->setClickMessage( "" ); @@ -275,7 +284,7 @@ void KOAttendeeEditor::readEvent(KCal::Incidence * incidence) { mdelAttendees.clear(); mnewAttendees.clear(); - if ( KOPrefs::instance()->thatIsMe( incidence->organizer().email() ) ) { + if ( KOPrefs::instance()->thatIsMe( incidence->organizer().email() ) || incidence->organizer().isEmpty() ) { if ( !mOrganizerCombo ) { mOrganizerCombo = new TQComboBox( mOrganizerHBox ); fillOrganizerCombo(); @@ -305,8 +314,36 @@ void KOAttendeeEditor::readEvent(KCal::Incidence * incidence) Attendee::List al = incidence->attendees(); Attendee::List::ConstIterator it; - for( it = al.begin(); it != al.end(); ++it ) - insertAttendee( new Attendee( **it ), true ); + Attendee *first = 0; + for( it = al.begin(); it != al.end(); ++it ) { + Attendee *a = new Attendee( **it ); + if ( !first ) { + first = a; + } + insertAttendee( a, true ); + } + + // Set the initial editing values to the first attendee in the list. + if ( first ) { + // Don't update the item here, the user didn't edit it, so it's not needed. + // Also, AttendeeEditor's subclasses didn't set the current Item at this point + // so if updateAttendee is called now what will happen is that a random item + // will get the text of "first". + mDisableItemUpdate = true; + + setSelected( 0 ); + mNameEdit->setText( first->fullName() ); + mUid = first->uid(); + mRoleCombo->setCurrentItem( first->role() ); + if ( first->status() != KCal::Attendee::None ) { + mStatusCombo->setCurrentItem( first->status() ); + } else { + mStatusCombo->setCurrentItem( KCal::Attendee::NeedsAction ); + } + mRsvpButton->setChecked( first->RSVP() ); + mRsvpButton->setEnabled( true ); + mDisableItemUpdate = false; + } } void KOAttendeeEditor::writeEvent(KCal::Incidence * incidence) @@ -338,15 +375,39 @@ void KOAttendeeEditor::clearAttendeeInput() mDelegateLabel->setText( TQString() ); } +void KOAttendeeEditor::expandAttendee() +{ + KABC::Addressee::List aList = expandDistList( mNameEdit->text() ); + if ( !aList.isEmpty() ) { + int index = selectedIndex(); + for ( KABC::Addressee::List::iterator itr = aList.begin(); itr != aList.end(); ++itr ) { + insertAttendeeFromAddressee( (*itr) ); + } + setSelected( index ); + removeAttendee( currentAttendee() ); + } +} + void KOAttendeeEditor::updateAttendee() { Attendee *a = currentAttendee(); if ( !a || mDisableItemUpdate ) return; - TQString name; - TQString email; - KPIM::getNameAndMail(mNameEdit->text(), name, email); + TQString text = mNameEdit->text(); + if ( !mNameEdit->text().startsWith( "\"" ) ) { + // Quote the text as it might contain commas and other quotable chars. + text = KPIM::quoteNameIfNecessary( text ); + } + + TQString name, email; + if ( KPIM::getNameAndMail( text, name, email ) ) { + name.remove( '"' ); + email.remove( '"' ).remove( '>' ); + } else { + name = TQString(); + email = mNameEdit->text(); + } bool iAmTheOrganizer = mOrganizerCombo && KOPrefs::instance()->thatIsMe( mOrganizerCombo->currentText() ); @@ -356,7 +417,6 @@ void KOAttendeeEditor::updateAttendee() bool wasMyself = KPIM::compareEmail( a->email(), mOrganizerCombo->currentText(), false ); if ( myself ) { - mStatusCombo->setCurrentItem( KCal::Attendee::Accepted ); mRsvpButton->setChecked( false ); mRsvpButton->setEnabled( false ); } else if ( wasMyself ) { @@ -380,16 +440,37 @@ void KOAttendeeEditor::fillAttendeeInput( KCal::Attendee *a ) { mDisableItemUpdate = true; - TQString name = a->name(); - if (!a->email().isEmpty()) { - name = KPIM::quoteNameIfNecessary( name ); - name += " <" + a->email() + ">"; + TQString tname, temail; + TQString username = a->name(); + if ( !a->email().isEmpty() ) { + username = KPIM::quoteNameIfNecessary( username ); + + KPIM::getNameAndMail( username, tname, temail ); // ignore return value + // which is always false + tname += " <" + a->email() + '>'; + } + + bool myself = KOPrefs::instance()->thatIsMe( a->email() ); + bool sameAsOrganizer = mOrganizerCombo && + KPIM::compareEmail( a->email(), + mOrganizerCombo->currentText(), false ); + KCal::Attendee::PartStat partStat = a->status(); + bool rsvp = a->RSVP(); + + if ( myself && sameAsOrganizer && a->status() == KCal::Attendee::None ) { + partStat = KCal::Attendee::Accepted; + rsvp = false; } - mNameEdit->setText(name); + + mNameEdit->setText(tname); mUid = a->uid(); mRoleCombo->setCurrentItem(a->role()); - mStatusCombo->setCurrentItem(a->status()); - mRsvpButton->setChecked(a->RSVP()); + if ( partStat != KCal::Attendee::None ) { + mStatusCombo->setCurrentItem( partStat ); + } else { + mStatusCombo->setCurrentItem( KCal::Attendee::NeedsAction ); + } + mRsvpButton->setChecked( rsvp ); mDisableItemUpdate = false; setEnableAttendeeInput( true ); @@ -402,6 +483,9 @@ void KOAttendeeEditor::fillAttendeeInput( KCal::Attendee *a ) else mDelegateLabel->setText( i18n( "Not delegated" ) ); } + if( myself ) + mRsvpButton->setEnabled( false ); + } void KOAttendeeEditor::updateAttendeeInput() @@ -418,17 +502,24 @@ void KOAttendeeEditor::updateAttendeeInput() void KOAttendeeEditor::cancelAttendeeEvent( KCal::Incidence *incidence ) { incidence->clearAttendees(); - Attendee * att; - for (att=mdelAttendees.first();att;att=mdelAttendees.next()) { + + if ( mdelAttendees.isEmpty() ) { + return; + } + + Attendee *att; + for ( att = mdelAttendees.first(); att; att = mdelAttendees.next() ) { bool isNewAttendee = false; - for (Attendee *newAtt=mnewAttendees.first();newAtt;newAtt=mnewAttendees.next()) { - if (*att==*newAtt) { - isNewAttendee = true; - break; + if ( !mnewAttendees.isEmpty() ) { + for ( Attendee *newAtt = mnewAttendees.first(); newAtt; newAtt = mnewAttendees.next() ) { + if ( *att == *newAtt ) { + isNewAttendee = true; + break; + } } } - if (!isNewAttendee) { - incidence->addAttendee(new Attendee(*att)); + if ( !isNewAttendee ) { + incidence->addAttendee( new Attendee( *att ) ); } } mdelAttendees.clear(); @@ -454,4 +545,51 @@ bool KOAttendeeEditor::eventFilter(TQObject *watched, TQEvent *ev) return TQWidget::eventFilter( watched, ev ); } +bool KOAttendeeEditor::isExampleAttendee( const KCal::Attendee* attendee ) const +{ + if ( !attendee ) return false; + if ( attendee->name() == i18n( "Firstname Lastname" ) + && attendee->email().endsWith( "example.net" ) ) { + return true; + } + return false; +} + +KABC::Addressee::List KOAttendeeEditor::expandDistList( const TQString &text ) const +{ + KABC::Addressee::List aList; + KABC::AddressBook *abook = KABC::StdAddressBook::self( true ); + +#ifdef KDEPIM_NEW_DISTRLISTS + const TQValueList<KPIM::DistributionList::Entry> eList = + KPIM::DistributionList::findByName( abook, text ).entries( abook ); + TQValueList<KPIM::DistributionList::Entry>::ConstIterator eit; + for ( eit = eList.begin(); eit != eList.end(); ++eit ) { + KABC::Addressee a = (*eit).addressee; + if ( !a.preferredEmail().isEmpty() && aList.find( a ) == aList.end() ) { + aList.append( a ) ; + } + } + +#else + KABC::DistributionListManager manager( abook ); + manager.load(); + const TQStringList dList = manager.listNames(); + for ( TQStringList::ConstIterator it = dList.begin(); it != dList.end(); ++it ) { + if ( (*it) == text ) { + const TQValueList<KABC::DistributionList::Entry> eList = manager.list( *it )->entries(); + TQValueList<KABC::DistributionList::Entry>::ConstIterator eit; + for ( eit = eList.begin(); eit != eList.end(); ++eit ) { + KABC::Addressee a = (*eit).addressee; + if ( !a.preferredEmail().isEmpty() && aList.find( a ) == aList.end() ) { + aList.append( a ) ; + } + } + } + } +#endif + return aList; +} + + #include "koattendeeeditor.moc" diff --git a/korganizer/koattendeeeditor.h b/korganizer/koattendeeeditor.h index 5f1dfb977..e75d994e5 100644 --- a/korganizer/koattendeeeditor.h +++ b/korganizer/koattendeeeditor.h @@ -23,6 +23,7 @@ #include <tqwidget.h> #include <libkcal/attendee.h> +#include <kabc/addressee.h> class TQBoxLayout; class TQComboBox; @@ -30,15 +31,12 @@ class TQCheckBox; class TQLabel; class TQPushButton; class TQHBox; +class TQListViewItem; namespace KPIM { class AddresseeLineEdit; } -namespace KABC { - class Addressee; -} - namespace KCal { class Incidence; } @@ -52,7 +50,8 @@ class KOAttendeeEditor : public QWidget public: KOAttendeeEditor( TQWidget *parent, const char *name = 0 ); - virtual void insertAttendee( KCal::Attendee* attendee, bool fetchFB = true ) = 0; + virtual void insertAttendee( KCal::Attendee *attendee, bool fetchFB = true ) = 0; + virtual void removeAttendee( KCal::Attendee *attendee ) = 0; virtual void readEvent( KCal::Incidence *incidence ); virtual void writeEvent( KCal::Incidence *incidence ); @@ -79,10 +78,13 @@ class KOAttendeeEditor : public QWidget void insertAttendeeFromAddressee( const KABC::Addressee &a, const KCal::Attendee* at=0 ); void fillOrganizerCombo(); - + virtual TQListViewItem* hasExampleAttendee() const = 0; + bool isExampleAttendee( const KCal::Attendee* ) const; virtual KCal::Attendee* currentAttendee() const = 0; virtual void updateCurrentItem() = 0; + virtual void setSelected ( int index ) = 0; + virtual int selectedIndex() = 0; virtual void changeStatusForMe( KCal::Attendee::PartStat status ) = 0; virtual bool eventFilter( TQObject *, TQEvent *); @@ -95,6 +97,7 @@ class KOAttendeeEditor : public QWidget void updateAttendeeInput(); void clearAttendeeInput(); void fillAttendeeInput( KCal::Attendee *a ); + void expandAttendee(); void updateAttendee(); protected: @@ -118,6 +121,7 @@ class KOAttendeeEditor : public QWidget TQPtrList<KCal::Attendee> mnewAttendees; private: + KABC::Addressee::List expandDistList( const TQString &text ) const; bool mDisableItemUpdate; }; diff --git a/korganizer/kocorehelper.cpp b/korganizer/kocorehelper.cpp index 374c7107b..5538d9c33 100644 --- a/korganizer/kocorehelper.cpp +++ b/korganizer/kocorehelper.cpp @@ -26,13 +26,17 @@ #include "koglobals.h" -TQColor KOCoreHelper::categoryColor( const TQStringList &categories ) +TQColor KOCoreHelper::categoryColor( const TQStringList &categories ) { + if ( categories.isEmpty() ) { + return KOPrefs::instance()->unsetCategoryColor(); + } + // FIXME: Correctly treat events with multiple categories TQString cat = categories.first(); TQColor bgColor; if (cat.isEmpty()) - bgColor = defaultEventColor(); + bgColor = KOPrefs::instance()->unsetCategoryColor(); else bgColor = *( KOPrefs::instance()->categoryColor( cat ) ); return bgColor; diff --git a/korganizer/kocorehelper.h b/korganizer/kocorehelper.h index 609278563..ff3c55a35 100644 --- a/korganizer/kocorehelper.h +++ b/korganizer/kocorehelper.h @@ -40,7 +40,6 @@ class KOCoreHelper : public KOrg::CoreHelper KOCoreHelper() {} virtual ~KOCoreHelper() {} - virtual TQColor defaultEventColor() { return KOPrefs::instance()->mEventColor; } virtual TQColor textColor( const TQColor &bgColor ) { return getTextColor( bgColor ); } virtual TQColor categoryColor( const TQStringList &cats ); virtual TQString holidayString( const TQDate &dt ); diff --git a/korganizer/kocounterdialog.cpp b/korganizer/kocounterdialog.cpp index bf3f736ff..a8a581d06 100644 --- a/korganizer/kocounterdialog.cpp +++ b/korganizer/kocounterdialog.cpp @@ -32,11 +32,11 @@ #include "kocounterdialog.h" #include "kocounterdialog.moc" -KOCounterDialog::KOCounterDialog( TQWidget *parent, const char *name ) +KOCounterDialog::KOCounterDialog( Calendar *calendar, TQWidget *parent, const char *name ) : KDialogBase( parent, name, false, i18n("Counter-Event Viewer"), User1 | User2, User1, false, i18n("Decline"), i18n("Accept") ) { - mEventViewer = new KOEventViewer( this ); + mEventViewer = new KOEventViewer( calendar, this ); setMainWidget( mEventViewer ); connect( this, TQT_SIGNAL( user1Clicked() ), TQT_SLOT( slotCancel() ) ); diff --git a/korganizer/kocounterdialog.h b/korganizer/kocounterdialog.h index cedb9dabb..64757e987 100644 --- a/korganizer/kocounterdialog.h +++ b/korganizer/kocounterdialog.h @@ -27,8 +27,7 @@ #include <kdialogbase.h> namespace KCal { -class Event; -class Todo; +class Calendar; } using namespace KCal; @@ -41,7 +40,7 @@ class KOCounterDialog : public KDialogBase { Q_OBJECT public: - KOCounterDialog(TQWidget *parent = 0, const char *name = 0 ); + KOCounterDialog(Calendar *calendar, TQWidget *parent = 0, const char *name = 0 ); virtual ~KOCounterDialog(); void setIncidence( Incidence *incidence ); diff --git a/korganizer/kodaymatrix.cpp b/korganizer/kodaymatrix.cpp index ff82ada9c..065e44e7c 100644 --- a/korganizer/kodaymatrix.cpp +++ b/korganizer/kodaymatrix.cpp @@ -228,11 +228,15 @@ void KODayMatrix::recalculateToday() updateView( mStartDate ); } +void KODayMatrix::setUpdateNeeded() +{ + mPendingChanges = true; +} + void KODayMatrix::updateView( const TQDate &actdate ) { kdDebug(5850) << "KODayMatrix::updateView() " << actdate << ", day start="<<mStartDate<< endl; if ( !actdate.isValid() ) return; - //flag to indicate if the starting day of the matrix has changed by this call bool daychanged = false; @@ -340,16 +344,19 @@ int KODayMatrix::getDayIndexFrom( int x, int y ) void KODayMatrix::calendarIncidenceAdded(Incidence * incidence) { + Q_UNUSED( incidence ); mPendingChanges = true; } void KODayMatrix::calendarIncidenceChanged(Incidence * incidence) { + Q_UNUSED( incidence ); mPendingChanges = true; } -void KODayMatrix::calendarIncidenceRemoved(Incidence * incidence) +void KODayMatrix::calendarIncidenceDeleted(Incidence * incidence) { + Q_UNUSED( incidence ); mPendingChanges = true; } @@ -406,7 +413,7 @@ void KODayMatrix::mouseMoveEvent( TQMouseEvent *e ) if (mSelInit > tmp) { mSelEnd = mSelInit; - if (tmp != mSelStart) { + if ( tmp != mSelStart ) { mSelStart = tmp; repaint(); } @@ -414,7 +421,7 @@ void KODayMatrix::mouseMoveEvent( TQMouseEvent *e ) mSelStart = mSelInit; //repaint only if selection has changed - if (tmp != mSelEnd) { + if ( tmp != mSelEnd ) { mSelEnd = tmp; repaint(); } @@ -669,8 +676,7 @@ void KODayMatrix::paintEvent( TQPaintEvent * ) } // draw selected days with special color - // DO NOT specially highlight holidays in selection ! - if (i >= mSelStart && i <= mSelEnd) { + if ( i >= mSelStart && i <= mSelEnd && !holiday ) { p.setPen( TQColor( "white" ) ); } @@ -678,7 +684,7 @@ void KODayMatrix::paintEvent( TQPaintEvent * ) Qt::AlignHCenter | Qt::AlignVCenter, mDayLabels[i]); // reset color to actual color - if (holiday) { + if ( holiday ) { p.setPen(actcol); } // reset bold font to plain font @@ -689,7 +695,7 @@ void KODayMatrix::paintEvent( TQPaintEvent * ) } } p.end(); - bitBlt( this, 0, 0, &pm ); + bitBlt( this, 0, 0, &pm ); } // ---------------------------------------------------------------------------- @@ -702,3 +708,22 @@ void KODayMatrix::resizeEvent( TQResizeEvent * ) mDaySize.setHeight( sz.height() * 7 / NUMDAYS ); mDaySize.setWidth( sz.width() / 7 ); } + +/* static */ +QPair<TQDate,TQDate> KODayMatrix::matrixLimits( const TQDate &month ) +{ + const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); + TQDate d = month; + calSys->setYMD( d, calSys->year( month ), calSys->month( month ), 1 ); + + const int dayOfWeek = calSys->dayOfWeek( d ); + const int weekstart = KGlobal::locale()->weekStartDay(); + + d = d.addDays( weekstart - dayOfWeek ); + + if ( dayOfWeek == weekstart ) { + d = d.addDays( -7 ); // Start on the second line + } + + return qMakePair( d, d.addDays( NUMDAYS-1 ) ); +} diff --git a/korganizer/kodaymatrix.h b/korganizer/kodaymatrix.h index 7dcf830e1..b8354f799 100644 --- a/korganizer/kodaymatrix.h +++ b/korganizer/kodaymatrix.h @@ -118,6 +118,11 @@ class KODayMatrix: public TQFrame, public KCal::Calendar::Observer */ ~KODayMatrix(); + /** returns the first and last date of the 6*7 matrix that displays @p month + * @param month The month we want to get matrix boundaries + */ + static QPair<TQDate,TQDate> matrixLimits( const TQDate &month ); + /** Associate a calendar with this day matrix. If there is a calendar, the day matrix will accept drops and days with events will be highlighted. @@ -182,7 +187,9 @@ class KODayMatrix: public TQFrame, public KCal::Calendar::Observer /* reimplmented from KCal::Calendar::Observer */ void calendarIncidenceAdded( Incidence *incidence ); void calendarIncidenceChanged( Incidence *incidence ); - void calendarIncidenceRemoved( Incidence *incidence ); + void calendarIncidenceDeleted( Incidence *incidence ); + + void setUpdateNeeded(); public slots: /** Recalculates all the flags of the days in the matrix like holidays or events diff --git a/korganizer/kodialogmanager.cpp b/korganizer/kodialogmanager.cpp index e17f03409..11f01aa58 100644 --- a/korganizer/kodialogmanager.cpp +++ b/korganizer/kodialogmanager.cpp @@ -170,15 +170,15 @@ void KODialogManager::showCategoryEditDialog() void KODialogManager::showSearchDialog() { - if (!mSearchDialog) { - mSearchDialog = new SearchDialog(mMainView->calendar(),mMainView); - connect(mSearchDialog,TQT_SIGNAL(showIncidenceSignal(Incidence *)), - mMainView,TQT_SLOT(showIncidence(Incidence *))); - connect(mSearchDialog,TQT_SIGNAL(editIncidenceSignal(Incidence *)), - mMainView,TQT_SLOT(editIncidence(Incidence *))); - connect(mSearchDialog,TQT_SIGNAL(deleteIncidenceSignal(Incidence *)), - mMainView, TQT_SLOT(deleteIncidence(Incidence *))); - connect(mMainView,TQT_SIGNAL(closingDown()),mSearchDialog,TQT_SLOT(reject())); + if ( !mSearchDialog ) { + mSearchDialog = new SearchDialog( mMainView->calendar(), mMainView ); + connect( mSearchDialog, TQT_SIGNAL(showIncidenceSignal(Incidence *,const TQDate &)), + mMainView, TQT_SLOT(showIncidence(Incidence *,const TQDate &)) ); + connect( mSearchDialog, TQT_SIGNAL(editIncidenceSignal(Incidence *,const TQDate &)), + mMainView, TQT_SLOT(editIncidence(Incidence *,const TQDate &)) ); + connect( mSearchDialog, TQT_SIGNAL(deleteIncidenceSignal(Incidence *)), + mMainView, TQT_SLOT(deleteIncidence(Incidence *)) ); + connect( mMainView, TQT_SIGNAL(closingDown()),mSearchDialog,TQT_SLOT(reject()) ); } // make sure the widget is on top again mSearchDialog->show(); diff --git a/korganizer/koeditoralarms.cpp b/korganizer/koeditoralarms.cpp index 0a2c7399a..8f3cb4648 100644 --- a/korganizer/koeditoralarms.cpp +++ b/korganizer/koeditoralarms.cpp @@ -25,6 +25,9 @@ #include "koeditoralarms_base.h" #include "koeditoralarms.h" +#include "koprefs.h" + +#include <libkcal/duration.h> #include <tqlayout.h> #include <tqlistview.h> @@ -35,6 +38,9 @@ #include <tqbuttongroup.h> #include <tqtextedit.h> #include <tqwidgetstack.h> +#include <tqradiobutton.h> +#include <tqtooltip.h> +#include <tqwhatsthis.h> #include <kurlrequester.h> #include <klocale.h> @@ -48,22 +54,46 @@ class AlarmListViewItem : public QListViewItem { public: - AlarmListViewItem( TQListView *parent, KCal::Alarm *alarm ); + AlarmListViewItem( TQListView *parent, KCal::Alarm *alarm, const TQCString &inctype ); virtual ~AlarmListViewItem(); KCal::Alarm *alarm() const { return mAlarm; } void construct(); enum AlarmViewColumns { ColAlarmType=0, ColAlarmOffset, ColAlarmRepeat }; + protected: KCal::Alarm *mAlarm; + + private: + TQCString mIncType; }; -AlarmListViewItem::AlarmListViewItem( TQListView *parent, KCal::Alarm *alarm ) - : TQListViewItem( parent ) +AlarmListViewItem::AlarmListViewItem( TQListView *parent, KCal::Alarm *alarm, + const TQCString &inctype ) + : TQListViewItem( parent ), mIncType( inctype ) { if ( alarm ) { mAlarm = new KCal::Alarm( *alarm ); } else { mAlarm = new KCal::Alarm( 0 ); + mAlarm->setType( KCal::Alarm::Display ); + int duration; // in secs + switch( KOPrefs::instance()->mReminderTimeUnits ) { + default: + case 0: // mins + duration = KOPrefs::instance()->mReminderTime * 60; + break; + case 1: // hours + duration = KOPrefs::instance()->mReminderTime * 60 * 60; + break; + case 2: // days + duration = KOPrefs::instance()->mReminderTime * 60 * 60 * 24; + break; + } + if ( mIncType == "Event" ) { + mAlarm->setStartOffset( KCal::Duration( -duration ) ); + } else { + mAlarm->setEndOffset( KCal::Duration( -duration ) ); + } } construct(); } @@ -102,19 +132,33 @@ void AlarmListViewItem::construct() int offset = 0; if ( mAlarm->hasStartOffset() ) { offset = mAlarm->startOffset().asSeconds(); - if ( offset < 0 ) { - offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 before the start"); + if ( offset <= 0 ) { + offsetstr = i18n( "N days/hours/minutes before/after the start/end", + "%1 before the start" ); offset = -offset; } else { - offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 after the start"); + offsetstr = i18n( "N days/hours/minutes before/after the start/end", + "%1 after the start" ); } } else if ( mAlarm->hasEndOffset() ) { offset = mAlarm->endOffset().asSeconds(); - if ( offset < 0 ) { - offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 before the end"); + if ( offset <= 0 ) { + if ( mIncType == "Todo" ) { + offsetstr = i18n( "N days/hours/minutes before/after the due date", + "%1 before the to-do is due" ); + } else { + offsetstr = i18n( "N days/hours/minutes before/after the start/end", + "%1 before the end" ); + } offset = -offset; } else { - offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 after the end"); + if ( mIncType == "Todo" ) { + offsetstr = i18n( "N days/hours/minutes before/after the due date", + "%1 after the to-do is due" ); + } else { + offsetstr = i18n( "N days/hours/minutes before/after the start/end", + "%1 after the end" ); + } } } @@ -143,11 +187,23 @@ void AlarmListViewItem::construct() } -KOEditorAlarms::KOEditorAlarms( KCal::Alarm::List *alarms, TQWidget *parent, +KOEditorAlarms::KOEditorAlarms( const TQCString &type, + KCal::Alarm::List *alarms, TQWidget *parent, const char *name ) - : KDialogBase( parent, name, true, i18n("Edit Reminders"), Ok | Cancel ), mAlarms( alarms ),mCurrentItem(0L) + : KDialogBase( parent, name, true, i18n("Advanced Reminders"), Ok | Cancel ), + mType( type ), mAlarms( alarms ),mCurrentItem( 0 ) { + if ( mType != "Todo" ) { + // only Todos and Events can have reminders + mType = "Event"; + } setMainWidget( mWidget = new KOEditorAlarms_base( this ) ); + + // The text is set here, and not in the UI file, because the i18n context is not + // properly extracted from the UI file. + mWidget->mAddButton->setText( i18n( "Add a new alarm to the alarm list.", "&Add" ) ); + + mWidget->mAlarmList->setResizeMode( TQListView::LastColumn ); mWidget->mAlarmList->setColumnWidthMode( 0, TQListView::Maximum ); mWidget->mAlarmList->setColumnWidthMode( 1, TQListView::Maximum ); connect( mWidget->mAlarmList, TQT_SIGNAL( selectionChanged( TQListViewItem * ) ), @@ -171,6 +227,11 @@ KOEditorAlarms::KOEditorAlarms( KCal::Alarm::List *alarms, TQWidget *parent, connect( mWidget->mEmailText, TQT_SIGNAL( textChanged() ), TQT_SLOT( changed() ) ); init(); + + //TODO: backport email reminders from trunk + mWidget->mTypeEmailRadio->hide(); //email reminders not implemented yet + + mWidget->setMinimumSize( 500, 500 ); } KOEditorAlarms::~KOEditorAlarms() @@ -180,7 +241,16 @@ KOEditorAlarms::~KOEditorAlarms() void KOEditorAlarms::changed() { if ( !mInitializing && mCurrentItem ) { - writeAlarm( mCurrentItem->alarm() ); + KCal::Alarm *alarm = mCurrentItem->alarm(); + + // Based on settings, provide default sound file for audio alarms + if ( alarm->audioFile().isEmpty() && + KOPrefs::instance()->defaultAudioFileReminders() ) { + alarm->setAudioFile( KOPrefs::instance()->audioFilePath() ); + mWidget->mSoundFile->setURL( KOPrefs::instance()->audioFilePath() ); + } + + writeAlarm( alarm ); mCurrentItem->construct(); } } @@ -194,6 +264,11 @@ void KOEditorAlarms::readAlarm( KCal::Alarm *alarm ) // Offsets int offset; int beforeafterpos = 0; + if ( mType == "Todo" ) { + if ( !alarm->hasStartOffset() ) { + beforeafterpos = 2; + } + } if ( alarm->hasEndOffset() ) { beforeafterpos = 2; offset = alarm->endOffset().asSeconds(); @@ -202,7 +277,7 @@ void KOEditorAlarms::readAlarm( KCal::Alarm *alarm ) offset = alarm->startOffset().asSeconds(); } // Negative offset means before the start/end... - if ( offset < 0 ) { + if ( offset <= 0 ) { offset = -offset; } else { ++beforeafterpos; @@ -229,7 +304,7 @@ void KOEditorAlarms::readAlarm( KCal::Alarm *alarm ) mWidget->mRepeats->setChecked( alarm->repeatCount()>0 ); if ( alarm->repeatCount()>0 ) { mWidget->mRepeatCount->setValue( alarm->repeatCount() ); - mWidget->mRepeatInterval->setValue( alarm->snoozeTime() ); + mWidget->mRepeatInterval->setValue( alarm->snoozeTime().asSeconds() / 60 ); // show as minutes } switch ( alarm->type() ) { @@ -290,7 +365,7 @@ void KOEditorAlarms::writeAlarm( KCal::Alarm *alarm ) // Repeating if ( mWidget->mRepeats->isChecked() ) { alarm->setRepeatCount( mWidget->mRepeatCount->value() ); - alarm->setSnoozeTime( mWidget->mRepeatInterval->value() ); + alarm->setSnoozeTime( KCal::Duration( mWidget->mRepeatInterval->value() * 60 ) ); // convert back to seconds } else { alarm->setRepeatCount( 0 ); } @@ -333,6 +408,9 @@ void KOEditorAlarms::selectionChanged( TQListViewItem *listviewitem ) void KOEditorAlarms::slotOk() { + // save the current item settings, if any + changed(); + // copy the mAlarms list if ( mAlarms ) { mAlarms->clear(); @@ -350,17 +428,15 @@ void KOEditorAlarms::slotOk() void KOEditorAlarms::slotAdd() { - mCurrentItem = new AlarmListViewItem( mWidget->mAlarmList, 0 ); + mCurrentItem = new AlarmListViewItem( mWidget->mAlarmList, 0, mType ); mWidget->mAlarmList->setCurrentItem( mCurrentItem ); -// selectionChanged( mCurrentItem ); } void KOEditorAlarms::slotDuplicate() { if ( mCurrentItem ) { - mCurrentItem = new AlarmListViewItem( mWidget->mAlarmList, mCurrentItem->alarm() ); + mCurrentItem = new AlarmListViewItem( mWidget->mAlarmList, mCurrentItem->alarm(), mType ); mWidget->mAlarmList->setCurrentItem( mCurrentItem ); -// selectionChanged( mCurrentItem ); } } @@ -370,16 +446,36 @@ void KOEditorAlarms::slotRemove() delete mCurrentItem; mCurrentItem = dynamic_cast<AlarmListViewItem*>( mWidget->mAlarmList->currentItem() ); mWidget->mAlarmList->setSelected( mCurrentItem, true ); - } } void KOEditorAlarms::init() { mInitializing = true; + + // Tweak some UI stuff depending on the Incidence type + if ( mType == "Todo" ) { + // Replace before/after end datetime with before/after due datetime + mWidget->mBeforeAfter->clear(); + mWidget->mBeforeAfter->insertItem( i18n( "before the to-do starts" ), 0 ); + mWidget->mBeforeAfter->insertItem( i18n( "after the to-do starts" ), 1 ); + mWidget->mBeforeAfter->insertItem( i18n( "before the to-do is due" ), 2 ); + mWidget->mBeforeAfter->insertItem( i18n( "after the to-do is due" ), 3 ); + TQToolTip::add( + mWidget->mBeforeAfter, + i18n( "Select the reminder trigger relative to the start or due time" ) ); + TQWhatsThis::add( + mWidget->mBeforeAfter, + i18n( "Use this combobox to specify if you want the reminder to " + "trigger before or after the start or due time." ) ); + + mWidget->mBeforeAfter->setCurrentItem( 2 ); // default is before due start + } + + // Fill-in existing alarms KCal::Alarm::List::ConstIterator it; for ( it = mAlarms->begin(); it != mAlarms->end(); ++it ) { - new AlarmListViewItem( mWidget->mAlarmList, *it ); + new AlarmListViewItem( mWidget->mAlarmList, *it, mType ); } mWidget->mAlarmList->setSelected( mWidget->mAlarmList->firstChild(), true ); mInitializing = false; diff --git a/korganizer/koeditoralarms.h b/korganizer/koeditoralarms.h index ed01d656b..971df799b 100644 --- a/korganizer/koeditoralarms.h +++ b/korganizer/koeditoralarms.h @@ -35,7 +35,8 @@ class KOEditorAlarms : public KDialogBase { Q_OBJECT public: - KOEditorAlarms( KCal::Alarm::List *alarms, TQWidget *parent = 0, + KOEditorAlarms( const TQCString &type, + KCal::Alarm::List *alarms, TQWidget *parent = 0, const char *name = 0 ); ~KOEditorAlarms(); @@ -46,11 +47,14 @@ class KOEditorAlarms : public KDialogBase void slotRemove(); void changed(); void selectionChanged( TQListViewItem *listviewitem ); + protected: void init(); void readAlarm( KCal::Alarm *alarm ); void writeAlarm( KCal::Alarm *alarm ); + private: + TQCString mType; // as in the Incidence::type KCal::Alarm::List *mAlarms; KOEditorAlarms_base *mWidget; bool mInitializing; diff --git a/korganizer/koeditoralarms_base.ui b/korganizer/koeditoralarms_base.ui index 68e8d5bc9..1da104404 100644 --- a/korganizer/koeditoralarms_base.ui +++ b/korganizer/koeditoralarms_base.ui @@ -45,6 +45,12 @@ <property name="name"> <cstring>mAlarmOffset</cstring> </property> + <property name="maxValue"> + <number>99999</number> + </property> + <property name="minValue"> + <number>0</number> + </property> <property name="sizePolicy"> <sizepolicy> <hsizetype>4</hsizetype> @@ -381,7 +387,7 @@ <cstring>mSoundFile</cstring> </property> <property name="filter"> - <string>audio/x-wav audio/x-mp3 application/ogg</string> + <string>audio/x-wav audio/x-mp3 application/ogg</string> </property> </widget> <spacer> @@ -535,7 +541,7 @@ <cstring>mRemoveButton</cstring> </property> <property name="text"> - <string>&Remove...</string> + <string>&Remove</string> </property> </widget> <widget class="QPushButton" row="0" column="1"> @@ -543,7 +549,7 @@ <cstring>mAddButton</cstring> </property> <property name="text"> - <string>&Add</string> + <string></string> </property> </widget> <widget class="QPushButton" row="1" column="1"> diff --git a/korganizer/koeditorattachments.cpp b/korganizer/koeditorattachments.cpp index adcd871e6..99d775e69 100644 --- a/korganizer/koeditorattachments.cpp +++ b/korganizer/koeditorattachments.cpp @@ -25,15 +25,19 @@ #include "koeditorattachments.h" +#include <libkcal/attachmenthandler.h> #include <libkcal/incidence.h> #include <libkdepim/kpimurlrequesterdlg.h> #include <libkdepim/kfileio.h> +#include <libkdepim/kdepimprotocols.h> +#include <libkdepim/maillistdrag.h> +#include <libkdepim/kvcarddrag.h> +#include <libkdepim/kdepimprotocols.h> #include <klocale.h> #include <kdebug.h> #include <kmdcodec.h> #include <kmessagebox.h> -#include <kiconview.h> #include <krun.h> #include <kurldrag.h> #include <ktempfile.h> @@ -45,7 +49,13 @@ #include <kstdaction.h> #include <kactioncollection.h> #include <kpopupmenu.h> +#include <kprotocolinfo.h> +#include <klineedit.h> +#include <kseparator.h> +#include <kurlrequester.h> +#include <libkmime/kmime_message.h> +#include <tqcheckbox.h> #include <tqfile.h> #include <tqlabel.h> #include <tqlayout.h> @@ -58,7 +68,7 @@ #include <tqclipboard.h> #include <cassert> -#include <set> +#include <cstdlib> class AttachmentListItem : public KIconViewItem { @@ -69,7 +79,8 @@ class AttachmentListItem : public KIconViewItem if ( att ) { mAttachment = new KCal::Attachment( *att ); } else { - mAttachment = new KCal::Attachment( TQString::null ); + mAttachment = new KCal::Attachment( '\0' ); //use the non-uri constructor + //as we want inline by default } readAttachment(); setDragEnabled( true ); @@ -77,112 +88,364 @@ class AttachmentListItem : public KIconViewItem ~AttachmentListItem() { delete mAttachment; } KCal::Attachment *attachment() const { return mAttachment; } + const TQString uri() const + { + return mAttachment->uri(); + } void setUri( const TQString &uri ) { mAttachment->setUri( uri ); readAttachment(); } - void setData( const char *base64 ) + void setData( const TQByteArray data ) { - mAttachment->setData( base64 ); + mAttachment->setDecodedData( data ); readAttachment(); } + const TQString mimeType() const + { + return mAttachment->mimeType(); + } void setMimeType( const TQString &mime ) { mAttachment->setMimeType( mime ); readAttachment(); } + const TQString label() const + { + return mAttachment->label(); + } void setLabel( const TQString &label ) { mAttachment->setLabel( label ); readAttachment(); } - + bool isBinary() const + { + return mAttachment->isBinary(); + } + TQPixmap icon() const + { + return icon( KMimeType::mimeType( mAttachment->mimeType() ), + mAttachment->uri() ); + } + static TQPixmap icon( KMimeType::Ptr mimeType, const TQString &uri ) + { + TQString iconStr = mimeType->icon( uri, false ); + return KGlobal::iconLoader()->loadIcon( iconStr, KIcon::Small ); + } void readAttachment() { - if ( mAttachment->isUri() ) - setText( mAttachment->uri() ); - else { - if ( mAttachment->label().isEmpty() ) - setText( i18n("[Binary data]") ); - else - setText( mAttachment->label() ); + if ( mAttachment->label().isEmpty() ) { + if ( mAttachment->isUri() ) { + setText( mAttachment->uri() ); + } else { + setText( i18n( "[Binary data]" ) ); + } + } else { + setText( mAttachment->label() ); } - KMimeType::Ptr mt = KMimeType::mimeType( mAttachment->mimeType() ); - if ( mt ) { - const TQString iconName( mt->icon( TQString(), false ) ); - TQPixmap pix = KGlobal::iconLoader( )->loadIcon( iconName, KIcon::Small ); - if ( pix.isNull() ) - pix = KGlobal::iconLoader( )->loadIcon( "unknown", KIcon::Small ); - if ( !pix.isNull() ) - setPixmap( pix ); + if ( mAttachment->mimeType().isEmpty() || + !( KMimeType::mimeType( mAttachment->mimeType() ) ) ) { + KMimeType::Ptr mimeType; + if ( mAttachment->isUri() ) { + mimeType = KMimeType::findByURL( mAttachment->uri() ); + } else { + mimeType = KMimeType::findByContent( mAttachment->decodedData() ); + } + mAttachment->setMimeType( mimeType->name() ); } + + setPixmap( icon() ); } private: KCal::Attachment *mAttachment; }; -class AttachmentIconView : public KIconView -{ - friend class KOEditorAttachments; - public: - AttachmentIconView( KOEditorAttachments* parent=0 ) - :KIconView( parent ), - mParent( parent ) - { - setAcceptDrops( true ); - setSelectionMode( TQIconView::Extended ); - setMode( KIconView::Select ); - setItemTextPos( TQIconView::Right ); - setArrangement( TQIconView::LeftToRight ); - setMaxItemWidth( QMAX(maxItemWidth(), 250) ); - setMinimumHeight( QMAX(fontMetrics().height(), 16) + 12 ); - } - ~AttachmentIconView() - { - for ( std::set<KTempDir*>::iterator it = mTempDirs.begin() ; it != mTempDirs.end() ; ++it ) { - delete *it; - } - } - protected: - TQDragObject * dragObject() - { - KURL::List urls; - for ( TQIconViewItem *it = firstItem( ); it; it = it->nextItem( ) ) { - if ( !it->isSelected() ) continue; - AttachmentListItem * item = dynamic_cast<AttachmentListItem*>( it ); - if ( !item ) return 0; - KCal::Attachment * att = item->attachment(); - assert( att ); - KURL url; - if ( att->isUri() ) { - url.setPath( att->uri() ); - } else { - KTempDir * tempDir = new KTempDir(); // will be deleted on editor close - tempDir->setAutoDelete( true ); - mTempDirs.insert( tempDir ); - TQByteArray encoded; - encoded.duplicate( att->data(), strlen(att->data()) ); - TQByteArray decoded; - KCodecs::base64Decode( encoded, decoded ); - const TQString fileName = tempDir->name( ) + "/" + att->label(); - KPIM::kByteArrayToFile( decoded, fileName, false, false, false ); - url.setPath( fileName ); - } - urls << url; - } - KURLDrag *drag = new KURLDrag( urls, this ); - return drag; - } - void contentsDropEvent( TQDropEvent* event ) - { - mParent->handlePasteOrDrop( event ); +AttachmentEditDialog::AttachmentEditDialog( AttachmentListItem *item, + TQWidget *parent ) + : KDialogBase ( Plain, i18n( "Add Attachment" ), Ok|Cancel, Ok, parent, 0, false, false ), + mItem( item ), mURLRequester( 0 ) +{ + TQFrame *topFrame = plainPage(); + TQVBoxLayout *vbl = new TQVBoxLayout( topFrame, 0, spacingHint() ); + + TQGridLayout *grid = new TQGridLayout(); + grid->setColStretch( 0, 0 ); + grid->setColStretch( 1, 0 ); + grid->setColStretch( 2, 1 ); + vbl->addLayout( grid ); + + mIcon = new TQLabel( topFrame ); + mIcon->setPixmap( item->icon() ); + grid->addWidget( mIcon, 0, 0 ); + + mLabelEdit = new KLineEdit( topFrame ); + mLabelEdit->setText( item->label().isEmpty() ? item->uri() : item->label() ); + mLabelEdit->setClickMessage( i18n( "Attachment name" ) ); + TQToolTip::add( mLabelEdit, i18n( "Give the attachment a name" ) ); + TQWhatsThis::add( mLabelEdit, + i18n( "Type any string you desire here for the name of the attachment" ) ); + grid->addMultiCellWidget( mLabelEdit, 0, 0, 1, 2 ); + + KSeparator *sep = new KSeparator( TQt::Horizontal, topFrame ); + grid->addMultiCellWidget( sep, 1, 1, 0, 2 ); + + TQLabel *label = new TQLabel( i18n( "Type:" ), topFrame ); + grid->addWidget( label, 2, 0 ); + TQString typecomment = item->mimeType().isEmpty() ? + i18n( "Unknown" ) : + KMimeType::mimeType( item->mimeType() )->comment(); + mTypeLabel = new TQLabel( typecomment, topFrame ); + grid->addWidget( mTypeLabel, 2, 1 ); + mMimeType = KMimeType::mimeType( item->mimeType() ); + + mInline = new TQCheckBox( i18n( "Store attachment inline" ), topFrame ); + grid->addMultiCellWidget( mInline, 3, 3, 0, 2 ); + mInline->setChecked( item->isBinary() ); + TQToolTip::add( mInline, i18n( "Store the attachment file inside the calendar" ) ); + TQWhatsThis::add( + mInline, + i18n( "Checking this option will cause the attachment to be stored inside " + "your calendar, which can take a lot of space depending on the size " + "of the attachment. If this option is not checked, then only a link " + "pointing to the attachment will be stored. Do not use a link for " + "attachments that change often or may be moved (or removed) from " + "their current location." ) ); + + if ( item->attachment()->isUri() || !item->attachment()->data() ) { + label = new TQLabel( i18n( "Location:" ), topFrame ); + grid->addWidget( label, 4, 0 ); + mURLRequester = new KURLRequester( item->uri(), topFrame ); + TQToolTip::add( mURLRequester, i18n( "Provide a location for the attachment file" ) ); + TQWhatsThis::add( + mURLRequester, + i18n( "Enter the path to the attachment file or use the " + "file browser by pressing the adjacent button" ) ); + grid->addMultiCellWidget( mURLRequester, 4, 4, 1, 2 ); + connect( mURLRequester, TQT_SIGNAL(urlSelected(const TQString &)), + TQT_SLOT(urlSelected(const TQString &)) ); + connect( mURLRequester, TQT_SIGNAL( textChanged( const TQString& ) ), + TQT_SLOT( urlChanged( const TQString& ) ) ); + urlChanged( item->uri() ); + } else { + uint size = item->attachment()->size(); + grid->addWidget( new TQLabel( i18n( "Size:" ), topFrame ), 4, 0 ); + grid->addWidget( new TQLabel( TQString::fromLatin1( "%1 (%2)" ). + arg( KIO::convertSize( size ) ). + arg( KGlobal::locale()->formatNumber( + size, 0 ) ), topFrame ), 4, 2 ); + } + vbl->addStretch( 10 ); +} + +void AttachmentEditDialog::slotApply() +{ + if ( !mLabelEdit->text().isEmpty() ) { + mItem->setLabel( mLabelEdit->text() ); + } else { + if ( mURLRequester ) { + KURL url( mURLRequester->url() ); + if ( url.isLocalFile() ) { + mItem->setLabel( url.fileName() ); + } else { + mItem->setLabel( url.url() ); + } + } + } + if ( mItem->label().isEmpty() ) { + mItem->setLabel( i18n( "New attachment" ) ); + } + mItem->setMimeType( mMimeType->name() ); + if ( mURLRequester ) { + KURL url( mURLRequester->url() ); + + TQString correctedUrl = mURLRequester->url(); + if ( !url.isValid() ) { + // If the user used KURLRequester's KURLCompletion + // (used the line edit instead of the file dialog) + // the returned url is not absolute and is always relative + // to the home directory (not pwd), so we must prepend home + + correctedUrl = TQDir::home().filePath( mURLRequester->url() ); + url = KURL( correctedUrl ); + if ( url.isValid() ) { + urlSelected( correctedUrl ); + mItem->setMimeType( mMimeType->name() ); + } + } + + if ( mInline->isChecked() ) { + TQString tmpFile; + if ( KIO::NetAccess::download( correctedUrl, tmpFile, this ) ) { + TQFile f( tmpFile ); + if ( !f.open( IO_ReadOnly ) ) { + return; } - private: - std::set<KTempDir*> mTempDirs; - KOEditorAttachments* mParent; -}; + TQByteArray data = f.readAll(); + f.close(); + mItem->setData( data ); + } + KIO::NetAccess::removeTempFile( tmpFile ); + } else { + mItem->setUri( url.url() ); + } + } +} + +void AttachmentEditDialog::accept() +{ + slotApply(); + KDialog::accept(); +} + +void AttachmentEditDialog::urlChanged( const TQString &url ) +{ + enableButton( Ok, !url.isEmpty() ); +} + +void AttachmentEditDialog::urlSelected( const TQString &url ) +{ + KURL kurl( url ); + mMimeType = KMimeType::findByURL( kurl ); + mTypeLabel->setText( mMimeType->comment() ); + mIcon->setPixmap( AttachmentListItem::icon( mMimeType, kurl.path() ) ); +} + +AttachmentIconView::AttachmentIconView( KOEditorAttachments* parent ) + : KIconView( parent ), + mParent( parent ) +{ + setSelectionMode( TQIconView::Extended ); + setMode( KIconView::Select ); + setItemTextPos( TQIconView::Right ); + setArrangement( TQIconView::LeftToRight ); + setMaxItemWidth( QMAX(maxItemWidth(), 250) ); + setMinimumHeight( QMAX(fontMetrics().height(), 16) + 12 ); + + connect( this, TQT_SIGNAL( dropped ( TQDropEvent *, const TQValueList<TQIconDragItem> & ) ), + this, TQT_SLOT( handleDrop( TQDropEvent *, const TQValueList<TQIconDragItem> & ) ) ); +} + +KURL AttachmentIconView::tempFileForAttachment( KCal::Attachment *attachment ) +{ + if ( mTempFiles.contains( attachment ) ) { + return mTempFiles[attachment]; + } + TQStringList patterns = KMimeType::mimeType( attachment->mimeType() )->patterns(); + + KTempFile *file; + if ( !patterns.empty() ) { + file = new KTempFile( TQString::null, + TQString( patterns.first() ).remove( '*' ),0600 ); + } else { + file = new KTempFile( TQString::null, TQString::null, 0600 ); + } + file->setAutoDelete( true ); + file->file()->open( IO_WriteOnly ); + TQTextStream stream( file->file() ); + stream.writeRawBytes( attachment->decodedData().data(), attachment->size() ); + KURL url( file->name() ); + mTempFiles.insert( attachment, url ); + file->close(); + return mTempFiles[attachment]; +} + +TQDragObject *AttachmentIconView::mimeData() +{ + // create a list of the URL:s that we want to drag + KURL::List urls; + TQStringList labels; + for ( TQIconViewItem *it = firstItem(); it; it = it->nextItem() ) { + if ( it->isSelected() ) { + AttachmentListItem *item = static_cast<AttachmentListItem *>( it ); + if ( item->isBinary() ) { + urls.append( tempFileForAttachment( item->attachment() ) ); + } else { + urls.append( item->uri() ); + } + labels.append( KURL::encode_string( item->label() ) ); + } + } + if ( selectionMode() == TQIconView::NoSelection ) { + AttachmentListItem *item = static_cast<AttachmentListItem *>( currentItem() ); + if ( item ) { + urls.append( item->uri() ); + labels.append( KURL::encode_string( item->label() ) ); + } + } + + TQMap<TQString, TQString> metadata; + metadata["labels"] = labels.join( ":" ); + + KURLDrag *drag = new KURLDrag( urls, metadata ); + return drag; +} + +AttachmentIconView::~AttachmentIconView() +{ + for ( std::set<KTempDir*>::iterator it = mTempDirs.begin() ; it != mTempDirs.end() ; ++it ) { + delete *it; + } +} + +TQDragObject * AttachmentIconView::dragObject() +{ + KURL::List urls; + for ( TQIconViewItem *it = firstItem( ); it; it = it->nextItem( ) ) { + if ( !it->isSelected() ) continue; + AttachmentListItem * item = dynamic_cast<AttachmentListItem*>( it ); + if ( !item ) return 0; + KCal::Attachment * att = item->attachment(); + assert( att ); + KURL url; + if ( att->isUri() ) { + url.setPath( att->uri() ); + } else { + KTempDir *tempDir = new KTempDir(); // will be deleted on editor close + tempDir->setAutoDelete( true ); + mTempDirs.insert( tempDir ); + TQByteArray encoded; + encoded.duplicate( att->data(), strlen( att->data() ) ); + TQByteArray decoded; + KCodecs::base64Decode( encoded, decoded ); + const TQString fileName = tempDir->name( ) + '/' + att->label(); + KPIM::kByteArrayToFile( decoded, fileName, false, false, false ); + url.setPath( fileName ); + } + urls << url; + } + KURLDrag *drag = new KURLDrag( urls, this ); + return drag; +} + +void AttachmentIconView::handleDrop( TQDropEvent *event, const TQValueList<TQIconDragItem> & list ) +{ + Q_UNUSED( list ); + mParent->handlePasteOrDrop( event ); +} + + +void AttachmentIconView::dragMoveEvent( TQDragMoveEvent *event ) +{ + mParent->dragMoveEvent( event ); +} + +void AttachmentIconView::contentsDragMoveEvent( TQDragMoveEvent *event ) +{ + mParent->dragMoveEvent( event ); +} + +void AttachmentIconView::contentsDragEnterEvent( TQDragEnterEvent *event ) +{ + mParent->dragMoveEvent( event ); +} + +void AttachmentIconView::dragEnterEvent( TQDragEnterEvent *event ) +{ + mParent->dragEnterEvent( event ); +} KOEditorAttachments::KOEditorAttachments( int spacing, TQWidget *parent, const char *name ) @@ -206,44 +469,51 @@ KOEditorAttachments::KOEditorAttachments( int spacing, TQWidget *parent, connect( mAttachments, TQT_SIGNAL(contextMenuRequested(TQIconViewItem*,const TQPoint&)), TQT_SLOT(contextMenu(TQIconViewItem*,const TQPoint&)) ); - mAddMenu = new KPopupMenu( this ); + TQPushButton *addButton = new TQPushButton( this ); + addButton->setIconSet( SmallIconSet( "add" ) ); + TQToolTip::add( addButton, i18n( "Add an attachment" ) ); + TQWhatsThis::add( addButton, + i18n( "Shows a dialog used to select an attachment " + "to add to this event or to-do as link or as " + "inline data." ) ); + topLayout->addWidget( addButton ); + connect( addButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotAdd()) ); + + mRemoveBtn = new TQPushButton( this ); + mRemoveBtn->setIconSet( SmallIconSet( "remove" ) ); + TQToolTip::add( mRemoveBtn, i18n("&Remove") ); + TQWhatsThis::add( mRemoveBtn, + i18n("Removes the attachment selected in the list above " + "from this event or to-do.") ); + topLayout->addWidget( mRemoveBtn ); + connect( mRemoveBtn, TQT_SIGNAL(clicked()), TQT_SLOT(slotRemove()) ); + mContextMenu = new KPopupMenu( this ); KActionCollection* ac = new KActionCollection( this, this ); - mOpenAction = new KAction( i18n("View"), 0, this, TQT_SLOT(slotShow()), ac ); + mOpenAction = new KAction( i18n("Open"), 0, this, TQT_SLOT(slotShow()), ac ); mOpenAction->plug( mContextMenu ); + + mSaveAsAction = new KAction( i18n( "Save As..." ), 0, this, TQT_SLOT(slotSaveAs()), ac ); + mSaveAsAction->plug( mContextMenu ); mContextMenu->insertSeparator(); - mCopyAction = KStdAction::copy(this, TQT_SLOT(slotCopy( ) ), ac ); + mCopyAction = KStdAction::copy(this, TQT_SLOT(slotCopy()), ac ); mCopyAction->plug( mContextMenu ); - mCutAction = KStdAction::cut(this, TQT_SLOT(slotCut( ) ), ac ); + mCutAction = KStdAction::cut(this, TQT_SLOT(slotCut()), ac ); mCutAction->plug( mContextMenu ); - KAction *action = KStdAction::paste(this, TQT_SLOT(slotPaste( ) ), ac ); + KAction *action = KStdAction::paste(this, TQT_SLOT(slotPaste()), ac ); action->plug( mContextMenu ); + mContextMenu->insertSeparator(); - action = new KAction( i18n("&Attach File..."), 0, this, TQT_SLOT(slotAddData()), ac ); - action->setWhatsThis( i18n("Shows a dialog used to select an attachment " - "to add to this event or to-do as link as inline data.") ); - action->plug( mAddMenu ); - action = new KAction( i18n("Attach &Link..."), 0, this, TQT_SLOT(slotAdd()), ac ); - action->setWhatsThis( i18n("Shows a dialog used to select an attachment " - "to add to this event or to-do as link.") ); - action->plug( mAddMenu ); + mDeleteAction = new KAction( i18n( "&Remove" ), 0, this, TQT_SLOT(slotRemove()), ac ); + mDeleteAction->plug( mContextMenu ); + mDeleteAction->setShortcut( Key_Delete ); + mContextMenu->insertSeparator(); - TQPushButton *addButton = new TQPushButton( this ); - addButton->setIconSet( SmallIconSet( "add" ) ); - addButton->setPopup( mAddMenu ); - topLayout->addWidget( addButton ); - - mRemoveBtn = new TQPushButton( this ); - mRemoveBtn->setIconSet( SmallIconSet( "remove" ) ); - TQToolTip::add( mRemoveBtn, i18n("&Remove") ); - TQWhatsThis::add( mRemoveBtn, - i18n("Removes the attachment selected in the list above " - "from this event or to-do.") ); - topLayout->addWidget( mRemoveBtn ); - connect( mRemoveBtn, TQT_SIGNAL( clicked() ), TQT_SLOT( slotRemove() ) ); + mEditAction = new KAction( i18n( "&Properties..." ), 0, this, TQT_SLOT(slotEdit()), ac ); + mEditAction->plug( mContextMenu ); selectionChanged(); setAcceptDrops( true ); @@ -258,26 +528,106 @@ bool KOEditorAttachments::hasAttachments() return mAttachments->count() != 0; } +void KOEditorAttachments::dragMoveEvent( TQDragMoveEvent *event ) +{ + event->accept( KURLDrag::canDecode( event ) || + TQTextDrag::canDecode( event ) || + KPIM::MailListDrag::canDecode( event ) || + KVCardDrag::canDecode( event ) ); +} + void KOEditorAttachments::dragEnterEvent( TQDragEnterEvent* event ) { - event->accept( KURLDrag::canDecode( event ) | TQTextDrag::canDecode( event ) ); + dragMoveEvent( event ); } void KOEditorAttachments::handlePasteOrDrop( TQMimeSource* source ) { KURL::List urls; - TQString text; - if ( KURLDrag::decode( source, urls ) ) { - const bool asUri = KMessageBox::questionYesNo( this, - i18n("Do you want to link to the attachments, or include them in the event?"), - i18n("Attach as link?"), i18n("As Link"), i18n("As File") ) == KMessageBox::Yes; - for ( KURL::List::ConstIterator it = urls.begin(); it != urls.end(); ++it ) { - addAttachment( (*it).url(), TQString::null, asUri ); - } - } else if ( TQTextDrag::decode( source, text ) ) { - TQStringList lst = TQStringList::split( '\n', text ); - for ( TQStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it ) { - addAttachment( (*it) ); + bool probablyWeHaveUris = false; + bool weCanCopy = true; + TQStringList labels; + + if ( KVCardDrag::canDecode( source ) ) { + KABC::Addressee::List addressees; + KVCardDrag::decode( source, addressees ); + for ( KABC::Addressee::List::ConstIterator it = addressees.constBegin(); + it != addressees.constEnd(); ++it ) { + urls.append( KDEPIMPROTOCOL_CONTACT + ( *it ).uid() ); + // there is some weirdness about realName(), hence fromUtf8 + labels.append( TQString::fromUtf8( ( *it ).realName().latin1() ) ); + } + probablyWeHaveUris = true; + } else if ( KURLDrag::canDecode( source ) ) { + TQMap<TQString,TQString> metadata; + if ( KURLDrag::decode( source, urls, metadata ) ) { + probablyWeHaveUris = true; + labels = TQStringList::split( ':', metadata["labels"], FALSE ); + for ( TQStringList::Iterator it = labels.begin(); it != labels.end(); ++it ) { + *it = KURL::decode_string( (*it).latin1() ); + } + + } + } else if ( TQTextDrag::canDecode( source ) ) { + TQString text; + TQTextDrag::decode( source, text ); + TQStringList lst = TQStringList::split( '\n', text, FALSE ); + for ( TQStringList::ConstIterator it = lst.constBegin(); it != lst.constEnd(); ++it ) { + urls.append( *it ); + labels.append( TQString::null ); + } + probablyWeHaveUris = true; + } + + KPopupMenu menu; + int items=0; + if ( probablyWeHaveUris ) { + menu.insertItem( i18n( "&Link here" ), DRAG_LINK, items++ ); + // we need to check if we can reasonably expect to copy the objects + for ( KURL::List::ConstIterator it = urls.constBegin(); it != urls.constEnd(); ++it ) { + if ( !( weCanCopy = KProtocolInfo::supportsReading( *it ) ) ) { + break; // either we can copy them all, or no copying at all + } + } + if ( weCanCopy ) { + menu.insertItem( SmallIcon( "editcopy" ), i18n( "&Copy Here" ), DRAG_COPY, items++ ); + } + } else { + menu.insertItem( SmallIcon( "editcopy" ), i18n( "&Copy Here" ), DRAG_COPY, items++ ); + } + + menu.insertSeparator(); + items++; + menu.insertItem( SmallIcon( "cancel" ), i18n( "C&ancel" ), DRAG_CANCEL, items ); + int action = menu.exec( TQCursor::pos(), 0 ); + + if ( action == DRAG_LINK ) { + TQStringList::ConstIterator jt = labels.constBegin(); + for ( KURL::List::ConstIterator it = urls.constBegin(); + it != urls.constEnd(); ++it ) { + TQString label = (*jt++); + if ( mAttachments->findItem( label ) ) { + label += '~' + randomString( 3 ); + } + addUriAttachment( (*it).url(), TQString::null, label, true ); + } + } else if ( action != DRAG_CANCEL ) { + if ( probablyWeHaveUris ) { + for ( KURL::List::ConstIterator it = urls.constBegin(); + it != urls.constEnd(); ++it ) { + TQString label = (*it).fileName(); + if ( label.isEmpty() ) { + label = (*it).prettyURL(); + } + if ( mAttachments->findItem( label ) ) { + label += '~' + randomString( 3 ); + } + addUriAttachment( (*it).url(), TQString::null, label, true ); + } + } else { // we take anything + addDataAttachment( source->encodedData( source->format() ), + source->format(), + KMimeType::mimeType( source->format() )->name() ); } } } @@ -293,95 +643,98 @@ void KOEditorAttachments::showAttachment( TQIconViewItem *item ) if ( !attitem || !attitem->attachment() ) return; KCal::Attachment *att = attitem->attachment(); - if ( att->isUri() ) { - emit openURL( att->uri() ); - } else { - KTempFile f; - if ( !f.file() ) - return; - TQByteArray encoded; - encoded.duplicate( att->data(), strlen(att->data()) ); - TQByteArray decoded; - KCodecs::base64Decode( encoded, decoded ); - f.file()->writeBlock( decoded ); - f.file()->close(); - KRun::runURL( f.name(), att->mimeType(), true, false ); - } + KCal::AttachmentHandler::view( this, att ); +} + +void KOEditorAttachments::saveAttachment( TQIconViewItem *item ) +{ + AttachmentListItem *attitem = static_cast<AttachmentListItem*>(item); + if ( !attitem || !attitem->attachment() ) return; + + KCal::Attachment *att = attitem->attachment(); + KCal::AttachmentHandler::saveAs( this, att ); } void KOEditorAttachments::slotAdd() { - KURL uri = KPimURLRequesterDlg::getURL( TQString::null, i18n( - "URL (e.g. a web page) or file to be attached (only " - "the link will be attached, not the file itself):"), this, - i18n("Add Attachment") ); - if ( !uri.isEmpty() ) { - addAttachment( uri ); + AttachmentListItem *item = new AttachmentListItem( 0, mAttachments ); + + AttachmentEditDialog *dlg = new AttachmentEditDialog( item, mAttachments ) +; + if ( dlg->exec() == KDialog::Rejected ) { + delete item; } + delete dlg; } void KOEditorAttachments::slotAddData() { KURL uri = KFileDialog::getOpenFileName( TQString(), TQString(), this, i18n("Add Attachment") ); if ( !uri.isEmpty() ) { - addAttachment( uri, TQString::null, false ); + TQString label = uri.fileName(); + if ( label.isEmpty() ) { + label = uri.prettyURL(); + } + addUriAttachment( uri.url(), TQString::null, label, true ); } } void KOEditorAttachments::slotEdit() { - TQIconViewItem *item = mAttachments->currentItem(); - AttachmentListItem *attitem = static_cast<AttachmentListItem*>(item); - if ( !attitem || !attitem->attachment() ) return; - - KCal::Attachment *att = attitem->attachment(); - if ( att->isUri() ) { - KURL uri = KPimURLRequesterDlg::getURL( att->uri(), i18n( - "URL (e.g. a web page) or file to be attached (only " - "the link will be attached, not the file itself):"), this, - i18n("Edit Attachment") ); - - if ( !uri.isEmpty() ) - attitem->setUri( uri.url() ); - } else { - KURL uri = KPimURLRequesterDlg::getURL( TQString::null, i18n( - "File to be attached:"), this, i18n("Add Attachment") ); - if ( !uri.isEmpty() ) { - TQString tmpFile; - if ( KIO::NetAccess::download( uri, tmpFile, this ) ) { - TQFile f( tmpFile ); - if ( !f.open( IO_ReadOnly ) ) - return; - TQByteArray data = f.readAll(); - f.close(); - attitem->setData( KCodecs::base64Encode( data ) ); - attitem->setMimeType( KIO::NetAccess::mimetype( uri, this ) ); - TQString label = uri.fileName(); - if ( label.isEmpty() ) - label = uri.prettyURL(); - attitem->setLabel( label ); - KIO::NetAccess::removeTempFile( tmpFile ); + for ( TQIconViewItem *item = mAttachments->firstItem(); item; item = item->nextItem() ) { + if ( item->isSelected() ) { + AttachmentListItem *attitem = static_cast<AttachmentListItem*>( item ); + if ( !attitem || !attitem->attachment() ) { + return; } + + AttachmentEditDialog *dialog = new AttachmentEditDialog( attitem, mAttachments ); + dialog->mInline->setEnabled( false ); + dialog->setModal( false ); + connect( dialog, TQT_SIGNAL(hidden()), dialog, TQT_SLOT(delayedDestruct()) ); + dialog->show(); } } } void KOEditorAttachments::slotRemove() { - TQValueList<TQIconViewItem*> selected; - for ( TQIconViewItem *it = mAttachments->firstItem( ); it; it = it->nextItem( ) ) { - if ( !it->isSelected() ) continue; - selected << it; - } - if ( selected.isEmpty() || KMessageBox::warningContinueCancel(this, - selected.count() == 1?i18n("This item will be permanently deleted."): - i18n("The selected items will be permanently deleted."), - i18n("KOrganizer Confirmation"),KStdGuiItem::del()) != KMessageBox::Continue ) - return; + TQValueList<TQIconViewItem*> selected; + TQStringList labels; + for ( TQIconViewItem *it = mAttachments->firstItem( ); it; it = it->nextItem( ) ) { + if ( !it->isSelected() ) continue; + selected << it; + + AttachmentListItem *attitem = static_cast<AttachmentListItem*>(it); + KCal::Attachment *att = attitem->attachment(); + labels << att->label(); + } - for ( TQValueList<TQIconViewItem*>::iterator it( selected.begin() ), end( selected.end() ); it != end ; ++it ) { - delete *it; + if ( selected.isEmpty() ) { + return; + } + + TQString labelsStr = labels.join( "<br>" ); + + if ( KMessageBox::questionYesNo( + this, + i18n( "<qt>Do you really want to remove these attachments?<p>%1</qt>" ).arg( labelsStr ), + i18n( "Remove Attachment?" ), + KStdGuiItem::yes(), KStdGuiItem::no(), + "calendarRemoveAttachments" ) != KMessageBox::Yes ) { + return; + } + + for ( TQValueList<TQIconViewItem*>::iterator it( selected.begin() ), end( selected.end() ); + it != end ; ++it ) { + if ( (*it)->nextItem() ) { + (*it)->nextItem()->setSelected( true ); + } else if ( (*it)->prevItem() ) { + (*it)->prevItem()->setSelected( true ); } + delete *it; + } + mAttachments->slotUpdate(); } void KOEditorAttachments::slotShow() @@ -393,40 +746,98 @@ void KOEditorAttachments::slotShow() } } +void KOEditorAttachments::slotSaveAs() +{ + for ( TQIconViewItem *it = mAttachments->firstItem(); it; it = it->nextItem() ) { + if ( !it->isSelected() ) + continue; + saveAttachment( it ); + } +} + void KOEditorAttachments::setDefaults() { mAttachments->clear(); } -void KOEditorAttachments::addAttachment( const KURL &uri, - const TQString &mimeType, bool asUri ) +TQString KOEditorAttachments::randomString(int length) const { - AttachmentListItem *item = new AttachmentListItem( 0, mAttachments ); - if ( asUri ) { - item->setUri( uri.url() ); - if ( !mimeType.isEmpty() ) item->setMimeType( mimeType ); + if (length <=0 ) return TQString(); + + TQString str; str.setLength( length ); + int i = 0; + while (length--) + { + int r=random() % 62; + r+=48; + if (r>57) r+=7; + if (r>90) r+=6; + str[i++] = char(r); + // so what if I work backwards? + } + return str; +} + +void KOEditorAttachments::addUriAttachment( const TQString &uri, + const TQString &mimeType, + const TQString &label, + bool inLine ) +{ + if ( !inLine ) { + AttachmentListItem *item = new AttachmentListItem( 0, mAttachments ); + item->setUri( uri ); + item->setLabel( label ); + if ( mimeType.isEmpty() ) { + if ( uri.startsWith( KDEPIMPROTOCOL_CONTACT ) ) { + item->setMimeType( "text/directory" ); + } else if ( uri.startsWith( KDEPIMPROTOCOL_EMAIL ) ) { + item->setMimeType( "message/rfc822" ); + } else if ( uri.startsWith( KDEPIMPROTOCOL_INCIDENCE ) ) { + item->setMimeType( "text/calendar" ); + } else if ( uri.startsWith( KDEPIMPROTOCOL_NEWSARTICLE ) ) { + item->setMimeType( "message/news" ); + } else { + item->setMimeType( KMimeType::findByURL( uri )->name() ); + } + } } else { TQString tmpFile; if ( KIO::NetAccess::download( uri, tmpFile, this ) ) { TQFile f( tmpFile ); - if ( !f.open( IO_ReadOnly ) ) + if ( !f.open( IO_ReadOnly ) ) { return; - TQByteArray data = f.readAll(); + } + const TQByteArray data = f.readAll(); f.close(); - item->setData( KCodecs::base64Encode( data ) ); - if ( !mimeType.isEmpty() ) - item->setMimeType( mimeType ); - else - item->setMimeType( KIO::NetAccess::mimetype( uri, this ) ); - TQString label = uri.fileName(); - if ( label.isEmpty() ) - label = uri.prettyURL(); - item->setLabel( label ); - KIO::NetAccess::removeTempFile( tmpFile ); + addDataAttachment( data, mimeType, label ); } + KIO::NetAccess::removeTempFile( tmpFile ); } } +void KOEditorAttachments::addDataAttachment( const TQByteArray &data, + const TQString &mimeType, + const TQString &label ) +{ + AttachmentListItem *item = new AttachmentListItem( 0, mAttachments ); + + TQString nlabel = label; + if ( mimeType == "message/rfc822" ) { + // mail message. try to set the label from the mail Subject: + KMime::Message msg; + msg.setContent( data.data() ); + msg.parse(); + nlabel = msg.subject()->asUnicodeString(); + } + + item->setData( data ); + item->setLabel( nlabel ); + if ( mimeType.isEmpty() ) { + item->setMimeType( KMimeType::findByContent( data )->name() ); + } else { + item->setMimeType( mimeType ); + } +} void KOEditorAttachments::addAttachment( KCal::Attachment *attachment ) { @@ -463,7 +874,7 @@ void KOEditorAttachments::writeIncidence( KCal::Incidence *i ) void KOEditorAttachments::slotCopy() { - TQApplication::clipboard()->setData( mAttachments->dragObject(), QClipboard::Clipboard ); + TQApplication::clipboard()->setData( mAttachments->mimeData(), QClipboard::Clipboard ); } void KOEditorAttachments::slotCut() @@ -492,9 +903,21 @@ void KOEditorAttachments::selectionChanged() void KOEditorAttachments::contextMenu(TQIconViewItem * item, const TQPoint & pos) { const bool enable = item != 0; + + int numSelected = 0; + for ( TQIconViewItem *item = mAttachments->firstItem(); item; item = item->nextItem() ) { + if ( item->isSelected() ) { + numSelected++; + } + } + mOpenAction->setEnabled( enable ); - mCopyAction->setEnabled( enable ); - mCutAction->setEnabled( enable ); + //TODO: support saving multiple attachments into a directory + mSaveAsAction->setEnabled( enable && numSelected == 1 ); + mCopyAction->setEnabled( enable && numSelected == 1 ); + mCutAction->setEnabled( enable && numSelected == 1 ); + mDeleteAction->setEnabled( enable ); + mEditAction->setEnabled( enable ); mContextMenu->exec( pos ); } diff --git a/korganizer/koeditorattachments.h b/korganizer/koeditorattachments.h index 09b2c48ea..dfcdb2b5f 100644 --- a/korganizer/koeditorattachments.h +++ b/korganizer/koeditorattachments.h @@ -26,19 +26,56 @@ #define KOEDITORATTACHMENTS_H #include <tqwidget.h> +#include <tqmap.h> +#include <kdialogbase.h> +#include <kmimetype.h> #include <kurl.h> +#include <kiconview.h> + +#include <set> + +class AttachmentListItem; +class AttachmentIconView; namespace KCal { class Incidence; class Attachment; } +class TQCheckBox; class TQIconViewItem; -class AttachmentIconView; +class TQLabel; class TQMimeSource; class TQPushButton; class TQPopupMenu; + class KAction; +class KLineEdit; +class KURLRequester; +class KTempDir; + +class AttachmentEditDialog : public KDialogBase +{ + Q_OBJECT + public: + AttachmentEditDialog( AttachmentListItem *item, TQWidget *parent=0 ); + + void accept(); + + protected slots: + void urlSelected( const TQString &url ); + void urlChanged( const TQString & url ); + virtual void slotApply(); + + private: + friend class KOEditorAttachments; + KMimeType::Ptr mMimeType; + AttachmentListItem *mItem; + TQLabel *mTypeLabel, *mIcon; + TQCheckBox *mInline; + KLineEdit *mLabelEdit; + KURLRequester *mURLRequester; +}; class KOEditorAttachments : public QWidget { @@ -48,9 +85,14 @@ class KOEditorAttachments : public QWidget const char *name = 0 ); ~KOEditorAttachments(); - void addAttachment( const KURL &uri, - const TQString &mimeType = TQString::null, bool asUri = true ); + void addUriAttachment( const TQString &uri, + const TQString &mimeType = TQString(), + const TQString &label = TQString(), + bool inLine = false ); void addAttachment( KCal::Attachment *attachment ); + void addDataAttachment( const TQByteArray &data, + const TQString &mimeType = TQString(), + const TQString &label = TQString() ); /** Set widgets to default values */ void setDefaults(); @@ -63,29 +105,75 @@ class KOEditorAttachments : public QWidget protected slots: void showAttachment( TQIconViewItem *item ); + void saveAttachment( TQIconViewItem *item ); void slotAdd(); void slotAddData(); void slotEdit(); void slotRemove(); void slotShow(); + void slotSaveAs(); void dragEnterEvent( TQDragEnterEvent *event ); + void dragMoveEvent( TQDragMoveEvent *event ); void dropEvent( TQDropEvent *event ); void slotCopy(); void slotCut(); void slotPaste(); void selectionChanged(); void contextMenu( TQIconViewItem* item, const TQPoint &pos ); + signals: void openURL( const KURL &url ); + protected: + enum { + DRAG_COPY = 0, + DRAG_LINK = 1, + DRAG_CANCEL = 2 + }; + private: friend class AttachmentIconView; void handlePasteOrDrop( TQMimeSource* source ); - + TQString randomString( int length ) const; AttachmentIconView *mAttachments; TQPushButton *mRemoveBtn; TQPopupMenu *mContextMenu, *mAddMenu; - KAction *mOpenAction, *mCopyAction, *mCutAction; + KAction *mOpenAction; + KAction *mSaveAsAction; + KAction *mCopyAction; + KAction *mCutAction; + KAction *mDeleteAction; + KAction *mEditAction; +}; + + +class AttachmentIconView : public KIconView +{ + Q_OBJECT + + friend class KOEditorAttachments; + public: + AttachmentIconView( KOEditorAttachments* parent=0 ); + KURL tempFileForAttachment( KCal::Attachment *attachment ); + TQDragObject *mimeData(); + ~AttachmentIconView(); + + protected: + TQDragObject * dragObject(); + + void dragMoveEvent( TQDragMoveEvent *event ); + void contentsDragMoveEvent( TQDragMoveEvent *event ); + void contentsDragEnterEvent( TQDragEnterEvent *event ); + void dragEnterEvent( TQDragEnterEvent *event ); + + protected slots: + + void handleDrop( TQDropEvent *event, const TQValueList<TQIconDragItem> & list ); + + private: + std::set<KTempDir*> mTempDirs; + TQMap<KCal::Attachment *, KURL> mTempFiles; + KOEditorAttachments* mParent; }; #endif diff --git a/korganizer/koeditordetails.cpp b/korganizer/koeditordetails.cpp index 0b8c6159f..a882363da 100644 --- a/korganizer/koeditordetails.cpp +++ b/korganizer/koeditordetails.cpp @@ -72,7 +72,8 @@ template <> CustomListViewItem<KCal::Attendee *>::~CustomListViewItem() { - delete mData; + // do not delete mData here +// delete mData; } template <> @@ -152,18 +153,15 @@ void KOAttendeeListView::dropEvent( TQDropEvent *e ) { #ifndef KORG_NODND TQString text; - TQString vcards; #ifndef KORG_NOKABC - if ( KVCardDrag::decode( e, vcards ) ) { - KABC::VCardConverter converter; - - KABC::Addressee::List list = converter.parseVCards( vcards ); + KABC::Addressee::List list; + if ( KVCardDrag::decode( e, list ) ) { KABC::Addressee::List::Iterator it; for ( it = list.begin(); it != list.end(); ++it ) { TQString em( (*it).fullEmail() ); - if (em.isEmpty()) { - em=(*it).realName(); + if ( em.isEmpty() ) { + em = (*it).realName(); } addAttendee( em ); } @@ -240,13 +238,22 @@ void KOEditorDetails::removeAttendee() static_cast<AttendeeListItem *>( mListView->selectedItem() ); if ( !aItem ) return; - Attendee *delA = new Attendee( aItem->data()->name(), aItem->data()->email(), - aItem->data()->RSVP(), aItem->data()->status(), - aItem->data()->role(), aItem->data()->uid() ); - mdelAttendees.append( delA ); + AttendeeListItem *nextSelectedItem = static_cast<AttendeeListItem*>( aItem->nextSibling() ); + if( mListView->childCount() == 1 ) + nextSelectedItem = 0; + if( mListView->childCount() > 1 && aItem == mListView->lastItem() ) + nextSelectedItem = static_cast<AttendeeListItem*>( mListView->firstChild() ); + Attendee *attendee = aItem->data(); + Attendee *delA = new Attendee( attendee->name(), attendee->email(), + attendee->RSVP(), attendee->status(), + attendee->role(), attendee->uid() ); + mdelAttendees.append( delA ); delete aItem; + if( nextSelectedItem ) { + mListView->setSelected( nextSelectedItem, true ); + } updateAttendeeInput(); emit updateAttendeeSummary( mListView->childCount() ); } @@ -257,12 +264,25 @@ void KOEditorDetails::insertAttendee( Attendee *a, bool goodEmailAddress ) Q_UNUSED( goodEmailAddress ); // lastItem() is O(n), but for n very small that should be fine - AttendeeListItem *item = new AttendeeListItem( a, mListView, - static_cast<KListViewItem*>( mListView->lastItem() ) ); + AttendeeListItem *item = new AttendeeListItem( + a, mListView, static_cast<KListViewItem*>( mListView->lastItem() ) ); mListView->setSelected( item, true ); emit updateAttendeeSummary( mListView->childCount() ); } +void KOEditorDetails::removeAttendee( Attendee *attendee ) +{ + TQListViewItem *item; + for ( item = mListView->firstChild(); item; item = item->nextSibling() ) { + AttendeeListItem *anItem = static_cast<AttendeeListItem *>( item ); + Attendee *att = anItem->data(); + if ( att == attendee ) { + delete anItem; + break; + } + } +} + void KOEditorDetails::setDefaults() { mRsvpButton->setChecked( true ); @@ -350,9 +370,34 @@ void KOEditorDetails::updateCurrentItem() item->updateItem(); } -void KOEditorDetails::slotInsertAttendee(Attendee * a) +void KOEditorDetails::slotInsertAttendee( Attendee *a ) { insertAttendee( a ); + mnewAttendees.append( a ); +} + +void KOEditorDetails::setSelected( int index ) +{ + int count = 0; + for ( TQListViewItemIterator it( mListView ); it.current(); ++it ) { + if ( count == index ) { + mListView->setSelected( *it, true ); + return; + } + count++; + } +} + +int KOEditorDetails::selectedIndex() +{ + int index = 0; + for ( TQListViewItemIterator it( mListView ); it.current(); ++it ) { + if ( mListView->isSelected( *it ) ) { + break; + } + index++; + } + return index; } void KOEditorDetails::changeStatusForMe(Attendee::PartStat status) @@ -369,4 +414,16 @@ void KOEditorDetails::changeStatusForMe(Attendee::PartStat status) } } +TQListViewItem* KOEditorDetails::hasExampleAttendee() const +{ + for ( TQListViewItemIterator it( mListView ); it.current(); ++it ) { + AttendeeListItem *item = static_cast<AttendeeListItem*>( it.current() ); + Attendee *attendee = item->data(); + Q_ASSERT( attendee ); + if ( isExampleAttendee( attendee ) ) + return item; + } + return 0; +} + #include "koeditordetails.moc" diff --git a/korganizer/koeditordetails.h b/korganizer/koeditordetails.h index 92a271644..890841f6e 100644 --- a/korganizer/koeditordetails.h +++ b/korganizer/koeditordetails.h @@ -95,16 +95,21 @@ class KOEditorDetails : public KOAttendeeEditor /** Returns whether at least one attendee was added */ bool hasAttendees(); - void insertAttendee( Attendee*, bool goodEmailAddress = true ); + void insertAttendee( Attendee *a, bool goodEmailAddress = true ); + void removeAttendee( Attendee *a ); protected slots: void removeAttendee(); void slotInsertAttendee( Attendee *a ); protected: + void setSelected ( int index ); + int selectedIndex(); void changeStatusForMe( Attendee::PartStat status ); KCal::Attendee* currentAttendee() const; + /* reimpl */ + TQListViewItem* hasExampleAttendee() const; void updateCurrentItem(); private: diff --git a/korganizer/koeditorfreebusy.cpp b/korganizer/koeditorfreebusy.cpp index 19691e807..c56ff033f 100644 --- a/korganizer/koeditorfreebusy.cpp +++ b/korganizer/koeditorfreebusy.cpp @@ -130,7 +130,8 @@ class FreeBusyItem : public KDGanttViewTaskItem void FreeBusyItem::updateItem() { - setListViewText( 0, mAttendee->fullName() ); + TQString text = mAttendee->name() + " <" + mAttendee->email() + '>'; + setListViewText( 0, text ); switch ( mAttendee->status() ) { case Attendee::Accepted: setPixmap( 0, KOGlobals::self()->smallIcon( "ok" ) ); @@ -166,17 +167,34 @@ void FreeBusyItem::setFreeBusyPeriods( FreeBusy* fb ) TQValueList<KCal::Period> busyPeriods = fb->busyPeriods(); for( TQValueList<KCal::Period>::Iterator it = busyPeriods.begin(); it != busyPeriods.end(); ++it ) { - KDGanttViewTaskItem* newSubItem = new KDGanttViewTaskItem( this ); - newSubItem->setStartTime( (*it).start() ); - newSubItem->setEndTime( (*it).end() ); + Period per = *it; + + KDGanttViewTaskItem *newSubItem = new KDGanttViewTaskItem( this ); + newSubItem->setStartTime( per.start() ); + newSubItem->setEndTime( per.end() ); newSubItem->setColors( Qt::red, Qt::red, Qt::red ); - TQString toolTip; - if ( !(*it).summary().isEmpty() ) - toolTip += "<b>" + (*it).summary() + "</b><br/>"; - if ( !(*it).location().isEmpty() ) - toolTip += i18n( "Location: %1" ).arg( (*it).location() ); - if ( !toolTip.isEmpty() ) - newSubItem->setTooltipText( toolTip ); + + TQString toolTip = "<qt>"; + toolTip += "<b>" + i18n( "Freebusy Period" ) + "</b>"; + toolTip += "<br>----------------------<br>"; + if ( !per.summary().isEmpty() ) { + toolTip += "<i>" + i18n( "Summary:" ) + "</i>" + " "; + toolTip += per.summary(); + toolTip += "<br>"; + } + if ( !per.location().isEmpty() ) { + toolTip += "<i>" + i18n( "Location:" ) + "</i>" + " "; + toolTip += per.location(); + toolTip += "<br>"; + } + toolTip += "<i>" + i18n( "Start:" ) + "</i>" + " "; + toolTip += KGlobal::locale()->formatDateTime( per.start() ); + toolTip += "<br>"; + toolTip += "<i>" + i18n( "End:" ) + "</i>" + " "; + toolTip += KGlobal::locale()->formatDateTime( per.end() ); + toolTip += "<br>"; + toolTip += "</qt>"; + newSubItem->setTooltipText( toolTip ); } setFreeBusy( fb ); setShowNoInformation( false ); @@ -529,12 +547,18 @@ void KOEditorFreeBusy::slotPickDate() i18n( "The meeting already has suitable start/end times." ), TQString::null, "MeetingTimeOKFreeBusy" ); } else { - emit dateTimesChanged( start, end ); - slotUpdateGanttView( start, end ); - KMessageBox::information( this, - i18n( "The meeting has been moved to\nStart: %1\nEnd: %2." ) - .arg( start.toString() ).arg( end.toString() ), TQString::null, - "MeetingMovedFreeBusy" ); + if ( KMessageBox::questionYesNo( + this, + i18n( "<qt>The next available time slot for the meeting is:<br>" + "Start: %1<br>End: %2<br>" + "Would you like to move the meeting to this time slot?</qt>" ). + arg( start.toString(), end.toString() ), + TQString::null, + KStdGuiItem::yes(), KStdGuiItem::no(), + "MeetingMovedFreeBusy" ) == KMessageBox::Yes ) { + emit dateTimesChanged( start, end ); + slotUpdateGanttView( start, end ); + } } } else KMessageBox::sorry( this, i18n( "No suitable date found." ) ); @@ -664,6 +688,7 @@ void KOEditorFreeBusy::updateStatusSummary() case Attendee::Delegated: case Attendee::Completed: case Attendee::InProcess: + case Attendee::None: /* just to shut up the compiler */ break; } @@ -803,6 +828,12 @@ void KOEditorFreeBusy::removeAttendee() if ( !item ) return; + FreeBusyItem *nextSelectedItem = static_cast<FreeBusyItem*>( item->nextSibling() ); + if( mGanttView->childCount() == 1 ) + nextSelectedItem = 0; + if( mGanttView->childCount() > 1 && item == mGanttView->lastItem() ) + nextSelectedItem = static_cast<FreeBusyItem*>( mGanttView->firstChild() ); + Attendee *delA = new Attendee( item->attendee()->name(), item->attendee()->email(), item->attendee()->RSVP(), item->attendee()->status(), item->attendee()->role(), item->attendee()->uid() ); @@ -810,6 +841,8 @@ void KOEditorFreeBusy::removeAttendee() delete item; updateStatusSummary(); + if( nextSelectedItem ) + mGanttView->setSelected( nextSelectedItem, true ); updateAttendeeInput(); emit updateAttendeeSummary( mGanttView->childCount() ); } @@ -823,6 +856,32 @@ void KOEditorFreeBusy::clearSelection() const item->repaint(); } +void KOEditorFreeBusy::setSelected( int index ) +{ + int count = 0; + for( KDGanttViewItem *it = mGanttView->firstChild(); it; it = it->nextSibling() ) { + FreeBusyItem *item = static_cast<FreeBusyItem*>( it ); + if ( count == index ) { + mGanttView->setSelected( item, true ); + return; + } + count++; + } +} + +int KOEditorFreeBusy::selectedIndex() +{ + int index = 0; + for ( KDGanttViewItem *it = mGanttView->firstChild(); it; it = it->nextSibling() ) { + FreeBusyItem *item = static_cast<FreeBusyItem*>( it ); + if ( item->isSelected() ) { + break; + } + index++; + } + return index; +} + void KOEditorFreeBusy::changeStatusForMe(KCal::Attendee::PartStat status) { const TQStringList myEmails = KOPrefs::instance()->allEmails(); @@ -911,6 +970,7 @@ void KOEditorFreeBusy::slotOrganizerChanged(const TQString & newOrganizer) if (!newOrganizerAttendee) { Attendee *a = new Attendee( name, email, true ); insertAttendee( a, false ); + mnewAttendees.append( a ); updateAttendee(); } } @@ -928,4 +988,16 @@ bool KOEditorFreeBusy::eventFilter( TQObject *watched, TQEvent *event ) } } +TQListViewItem* KOEditorFreeBusy::hasExampleAttendee() const +{ + for ( FreeBusyItem *item = static_cast<FreeBusyItem *>( mGanttView->firstChild() ); item; + item = static_cast<FreeBusyItem*>( item->nextSibling() ) ) { + Attendee *attendee = item->attendee(); + Q_ASSERT( attendee ); + if ( isExampleAttendee( attendee ) ) + return item; + } + return 0; +} + #include "koeditorfreebusy.moc" diff --git a/korganizer/koeditorfreebusy.h b/korganizer/koeditorfreebusy.h index 4e561cfa2..72ce6e7d4 100644 --- a/korganizer/koeditorfreebusy.h +++ b/korganizer/koeditorfreebusy.h @@ -93,8 +93,12 @@ class KOEditorFreeBusy : public KOAttendeeEditor protected: void timerEvent( TQTimerEvent* ); KCal::Attendee* currentAttendee() const; + /* reimpl */ + TQListViewItem* hasExampleAttendee() const; void updateCurrentItem(); void clearSelection() const; + void setSelected ( int index ); + int selectedIndex(); void changeStatusForMe( KCal::Attendee::PartStat status ); virtual bool eventFilter( TQObject *watched, TQEvent *event ); diff --git a/korganizer/koeditorgeneral.cpp b/korganizer/koeditorgeneral.cpp index 816806e3a..e1d8db245 100644 --- a/korganizer/koeditorgeneral.cpp +++ b/korganizer/koeditorgeneral.cpp @@ -30,7 +30,6 @@ #include <tqhbox.h> #include <tqbuttongroup.h> #include <tqvgroupbox.h> -#include <tqwidgetstack.h> #include <tqdatetime.h> #include <tqlineedit.h> #include <tqlabel.h> @@ -54,6 +53,7 @@ #include <libkcal/todo.h> #include <libkcal/event.h> +#include <libkcal/incidenceformatter.h> #include <libkcal/resourcecached.h> #include <libkdepim/kdateedit.h> @@ -68,9 +68,10 @@ #include "koeditorgeneral.moc" #include "kohelper.h" -KOEditorGeneral::KOEditorGeneral(TQObject* parent, const char* name) : +KOEditorGeneral::KOEditorGeneral( TQObject *parent, const char* name) : TQObject( parent, name ), mAttachments(0) { + mType = "Event"; ResourceCached::setEditorWindowOpen(true); mAlarmList.setAutoDelete( true ); } @@ -103,11 +104,6 @@ void KOEditorGeneral::initHeader( TQWidget *parent,TQBoxLayout *topLayout) headerLayout->setSpacing( topLayout->spacing() ); topLayout->addLayout( headerLayout ); -#if 0 - mOwnerLabel = new TQLabel(i18n("Owner:"),parent); - headerLayout->addMultiCellWidget(mOwnerLabel,0,0,0,1); -#endif - TQString whatsThis = i18n("Sets the Title of this event or to-do."); TQLabel *summaryLabel = new TQLabel( i18n("T&itle:"), parent ); TQWhatsThis::add( summaryLabel, whatsThis ); @@ -198,52 +194,63 @@ void KOEditorGeneral::initDescription(TQWidget *parent,TQBoxLayout *topLayout) topLayout->addWidget(mDescriptionEdit, 4); } -void KOEditorGeneral::initAlarm(TQWidget *parent,TQBoxLayout *topLayout) +void KOEditorGeneral::initAlarm( TQWidget *parent, TQBoxLayout *topLayout ) { - TQBoxLayout *alarmLayout = new TQHBoxLayout(topLayout); - - mAlarmBell = new TQLabel(parent); - mAlarmBell->setPixmap(KOGlobals::self()->smallIcon("bell")); - alarmLayout->addWidget( mAlarmBell ); - - - mAlarmStack = new TQWidgetStack( parent ); - alarmLayout->addWidget( mAlarmStack ); - - mAlarmInfoLabel = new TQLabel( i18n("No reminders configured"), mAlarmStack ); - mAlarmStack->addWidget( mAlarmInfoLabel, AdvancedAlarmLabel ); - - TQHBox *simpleAlarmBox = new TQHBox( mAlarmStack ); - mAlarmStack->addWidget( simpleAlarmBox, SimpleAlarmPage ); - - mAlarmButton = new TQCheckBox(i18n("&Reminder:"), simpleAlarmBox ); - TQWhatsThis::add( mAlarmButton, - i18n("Activates a reminder for this event or to-do.") ); - - TQString whatsThis = i18n("Sets how long before the event occurs " - "the reminder will be triggered."); - mAlarmTimeEdit = new TQSpinBox( 0, 99999, 1, simpleAlarmBox, "alarmTimeEdit" ); + TQBoxLayout *alarmLayout = new TQHBoxLayout( topLayout ); + + mAlarmButton = new TQCheckBox( parent ); + TQWhatsThis::add( mAlarmButton, i18n( "Enable reminders for this event or to-do." ) ); + TQToolTip::add( mAlarmButton, i18n( "Enable reminders" ) ); + alarmLayout->addWidget( mAlarmButton ); + + mAlarmAdvancedButton = new TQPushButton( parent ); + mAlarmAdvancedButton->setIconSet( KOGlobals::self()->smallIconSet( "bell", 16 ) ); + TQWhatsThis::add( mAlarmAdvancedButton, + i18n( "Push this button to create an advanced set of reminders " + "for this event or to-do." ) ); + TQToolTip::add( mAlarmAdvancedButton, i18n( "Set an advanced reminder" ) ); + connect( mAlarmAdvancedButton, TQT_SIGNAL(clicked()), TQT_SLOT(editAlarms()) ); + alarmLayout->addWidget( mAlarmAdvancedButton ); + + mSimpleAlarmBox = new TQHBox( parent ); + alarmLayout->addWidget( mSimpleAlarmBox ); + + TQString whatsThis, toolTip; + if ( mType == "Event" ) { + whatsThis = i18n( "Set the time before the event starts when the reminder will be triggered." ); + toolTip = i18n( "Set the start time trigger offset" ); + } else { + whatsThis = i18n( "Set the time before the to-do is due when the reminder will be triggered." ); + toolTip = i18n( "Set the due time trigger offset" ); + } + mAlarmTimeEdit = new TQSpinBox( 0, 99999, 1, mSimpleAlarmBox, "alarmTimeEdit" ); mAlarmTimeEdit->setValue( 0 ); TQWhatsThis::add( mAlarmTimeEdit, whatsThis ); + TQToolTip::add( mAlarmTimeEdit, toolTip ); - mAlarmIncrCombo = new TQComboBox( false, simpleAlarmBox ); - TQWhatsThis::add( mAlarmIncrCombo, whatsThis ); + mAlarmIncrCombo = new TQComboBox( false, mSimpleAlarmBox ); mAlarmIncrCombo->insertItem( i18n("minute(s)") ); mAlarmIncrCombo->insertItem( i18n("hour(s)") ); mAlarmIncrCombo->insertItem( i18n("day(s)") ); -// mAlarmIncrCombo->setMinimumHeight(20); - connect(mAlarmButton, TQT_SIGNAL(toggled(bool)), mAlarmTimeEdit, TQT_SLOT(setEnabled(bool))); - connect(mAlarmButton, TQT_SIGNAL(toggled(bool)), mAlarmIncrCombo, TQT_SLOT(setEnabled(bool))); - mAlarmTimeEdit->setEnabled( false ); - mAlarmIncrCombo->setEnabled( false ); + TQWhatsThis::add( mAlarmIncrCombo, whatsThis ); + TQToolTip::add( mAlarmIncrCombo, toolTip ); - mAlarmEditButton = new TQPushButton( i18n("Advanced"), parent ); - mAlarmEditButton->setEnabled( false ); - alarmLayout->addWidget( mAlarmEditButton ); - connect( mAlarmButton, TQT_SIGNAL(toggled(bool)), mAlarmEditButton, TQT_SLOT(setEnabled( bool))); - connect( mAlarmEditButton, TQT_SIGNAL( clicked() ), - TQT_SLOT( editAlarms() ) ); + mAlarmInfoLabel = new TQLabel( parent ); + if ( mType == "Event" ) { + mAlarmInfoLabel->setText( i18n( "before the start" ) ); + } else { + mAlarmInfoLabel->setText( i18n( "before the due time" ) ); + } + alarmLayout->addWidget( mAlarmInfoLabel ); + mAlarmAdvancedButton->setEnabled( false ); + mAlarmTimeEdit->setEnabled( false ); + mAlarmIncrCombo->setEnabled( false ); + mAlarmInfoLabel->setEnabled( false ); + connect( mAlarmButton, TQT_SIGNAL(toggled(bool)), mAlarmAdvancedButton, TQT_SLOT(setEnabled(bool)) ); + connect( mAlarmButton, TQT_SIGNAL(toggled(bool)), mAlarmTimeEdit, TQT_SLOT(setEnabled(bool)) ); + connect( mAlarmButton, TQT_SIGNAL(toggled(bool)), mAlarmIncrCombo, TQT_SLOT(setEnabled(bool)) ); + connect( mAlarmButton, TQT_SIGNAL(toggled(bool)), mAlarmInfoLabel, TQT_SLOT(setEnabled(bool)) ); } void KOEditorGeneral::initAttachments(TQWidget *parent,TQBoxLayout *topLayout) @@ -254,6 +261,12 @@ void KOEditorGeneral::initAttachments(TQWidget *parent,TQBoxLayout *topLayout) topLayout->addWidget( mAttachments, 1 ); } +void KOEditorGeneral::setType( const TQCString &type ) +{ + // must be "Event", "Todo", "Journal", etc. + mType = type; +} + void KOEditorGeneral::addAttachments( const TQStringList &attachments, const TQStringList &mimeTypes, bool inlineAttachments ) @@ -261,10 +274,13 @@ void KOEditorGeneral::addAttachments( const TQStringList &attachments, TQStringList::ConstIterator it; uint i = 0; for ( it = attachments.begin(); it != attachments.end(); ++it, ++i ) { - TQString mimeType; - if ( mimeTypes.count() > i ) - mimeType = mimeTypes[ i ]; - mAttachments->addAttachment( *it, mimeType, !inlineAttachments ); + if ( !(*it).isEmpty() ) { + TQString mimeType; + if ( mimeTypes.count() > i ) { + mimeType = mimeTypes[ i ]; + } + mAttachments->addUriAttachment( *it, mimeType, TQString(), inlineAttachments ); + } } } @@ -286,31 +302,48 @@ void KOEditorGeneral::selectCategories() void KOEditorGeneral::editAlarms() { - if ( mAlarmStack->id( mAlarmStack->visibleWidget() ) == SimpleAlarmPage ) { + if ( mAlarmIsSimple ) { mAlarmList.clear(); - Alarm *al = alarmFromSimplePage(); + Alarm *al = alarmFromSimplePage( 0 ); if ( al ) { mAlarmList.append( al ); } } - KOEditorAlarms *dlg = new KOEditorAlarms( &mAlarmList, mAlarmEditButton ); + KOEditorAlarms *dlg = new KOEditorAlarms( mType, &mAlarmList, mAlarmAdvancedButton ); if ( dlg->exec() != KDialogBase::Cancel ) { - updateAlarmWidgets(); + if ( mType == "Event" ) { + Event *e = new Event; + Alarm::List::ConstIterator it; + for( it = mAlarmList.begin(); it != mAlarmList.end(); ++it ) { + Alarm *a = (*it)->clone(); + a->setParent( e ); + e->addAlarm( a ); + } + updateAlarmWidgets( e ); + delete e; + } else { + Todo *t = new Todo; + Alarm::List::ConstIterator it; + for( it = mAlarmList.begin(); it != mAlarmList.end(); ++it ) { + Alarm *a = (*it)->clone(); + a->setParent( t ); + t->addAlarm( a ); + } + updateAlarmWidgets( t ); + delete t; + } } } - void KOEditorGeneral::enableAlarm( bool enable ) { - mAlarmStack->setEnabled( enable ); - mAlarmEditButton->setEnabled( enable ); + mAlarmAdvancedButton->setEnabled( enable ); } - void KOEditorGeneral::toggleAlarm( bool on ) { - mAlarmButton->setChecked( on ); + mAlarmButton->setChecked( on ); } void KOEditorGeneral::setCategories( const TQStringList &categories ) @@ -321,65 +354,104 @@ void KOEditorGeneral::setCategories( const TQStringList &categories ) void KOEditorGeneral::setDefaults(bool /*allDay*/) { -#if 0 - mOwnerLabel->setText(i18n("Owner: ") + KOPrefs::instance()->fullName()); -#endif - mAlarmList.clear(); updateDefaultAlarmTime(); - updateAlarmWidgets(); + updateAlarmWidgets( 0 ); - mSecrecyCombo->setCurrentItem(Incidence::SecrecyPublic); + mSecrecyCombo->setCurrentItem( Incidence::SecrecyPublic ); mAttachments->setDefaults(); } void KOEditorGeneral::updateDefaultAlarmTime() { - // FIXME: Implement a KPrefsComboItem to solve this in a clean way. -// FIXME: Use an int value for minutes instead of 5 hardcoded values - int alarmTime; - int a[] = { 1,5,10,15,30 }; - int index = KOPrefs::instance()->mAlarmTime; - if (index < 0 || index > 4) { - alarmTime = 0; - } else { - alarmTime = a[index]; + int reminderTime = KOPrefs::instance()->mReminderTime; + int index = KOPrefs::instance()->mReminderTimeUnits; + if ( index < 0 || index > 2 ) { + index = 0; } - mAlarmTimeEdit->setValue(alarmTime); + mAlarmTimeEdit->setValue( reminderTime ); + mAlarmIncrCombo->setCurrentItem( index ); } -void KOEditorGeneral::updateAlarmWidgets() +bool KOEditorGeneral::isSimpleAlarm( Alarm *alarm ) const { - if ( mAlarmList.isEmpty() ) { - mAlarmStack->raiseWidget( SimpleAlarmPage ); - if (KOPrefs::instance()->mAlarmsEnabledByDefault == true) { - mAlarmButton->setChecked( true ); + // Check if its the trivial type of alarm, which can be + // configured with a simply spin box... + + bool simple = false; + if ( alarm->type() == Alarm::Display && alarm->text().isEmpty() && + alarm->repeatCount() == 0 && !alarm->hasTime() ) { + if ( mType == "Event" && + alarm->hasStartOffset() && alarm->startOffset().asSeconds() <= 0 ) { + simple = true; } - else { - mAlarmButton->setChecked( false ); + if ( mType == "Todo" && + alarm->hasEndOffset() && alarm->endOffset().asSeconds() <= 0 ) { + simple = true; } - mAlarmEditButton->setEnabled( false ); - } else if ( mAlarmList.count() > 1 ) { - mAlarmStack->raiseWidget( AdvancedAlarmLabel ); - mAlarmInfoLabel->setText( i18n("1 advanced reminder configured", - "%n advanced reminders configured", - mAlarmList.count() ) ); - mAlarmEditButton->setEnabled( true ); - } else { - Alarm *alarm = mAlarmList.first(); - // Check if its the trivial type of alarm, which can be - // configured with a simply spin box... + } + return simple; +} - if ( alarm->type() == Alarm::Display && alarm->text().isEmpty() - && alarm->repeatCount() == 0 && !alarm->hasTime() - && alarm->hasStartOffset() && alarm->startOffset().asSeconds() < 0 ) { - mAlarmStack->raiseWidget( SimpleAlarmPage ); - mAlarmButton->setChecked( true ); - int offset = alarm->startOffset().asSeconds(); +static TQString etc = i18n( "elipsis", "..." ); +void KOEditorGeneral::updateAlarmWidgets( Incidence *incidence ) +{ + uint maxLen = 75; //TODO: compute from the font and dialog width + + if ( incidence ) { + mAlarmButton->setChecked( incidence->isAlarmEnabled() ); + } + if ( mAlarmList.isEmpty() ) { + mAlarmIsSimple = true; + mSimpleAlarmBox->show(); + bool on; + if ( mType == "Event" ) { + on = KOPrefs::instance()->defaultEventReminders(); + } else if ( mType == "Todo" ) { + on = KOPrefs::instance()->defaultTodoReminders(); + } else { + on = false; + } + mAlarmButton->setChecked( on ); + mAlarmAdvancedButton->setEnabled( on ); + } else if ( mAlarmList.count() > 1 ) { + mAlarmIsSimple = false; + mAlarmAdvancedButton->setEnabled( true ); + mSimpleAlarmBox->hide(); + if ( incidence ) { + TQString remStr = IncidenceFormatter::reminderStringList( incidence ).join( ", " ); + if ( remStr.length() > maxLen ) { + maxLen -= etc.length(); + remStr = remStr.left( maxLen ); + remStr += etc; + } + mAlarmInfoLabel->setText( i18n( "Triggers %1" ).arg( remStr ) ); + } + } else { // alarm count is 1 + Alarm *alarm = mAlarmList.first(); + if ( isSimpleAlarm( alarm ) ) { + mAlarmIsSimple = true; + mSimpleAlarmBox->show(); + int offset; + if ( mType == "Event" ) { + offset = alarm->startOffset().asSeconds(); + mAlarmInfoLabel->setText( i18n( "before the start" ) ); + } + if ( mType == "Todo" ) { + if ( alarm->hasStartOffset() ) { + offset = alarm->startOffset().asSeconds(); + mAlarmInfoLabel->setText( i18n( "before the start" ) ); + } else { + offset = alarm->endOffset().asSeconds(); + mAlarmInfoLabel->setText( i18n( "before the due time" ) ); + } + } offset = offset / -60; // make minutes int useoffset = offset; - if (offset % (24*60) == 0) { // divides evenly into days? + if ( offset == 0 ) { + mAlarmIncrCombo->setCurrentItem( 0 ); // use minute units for 0 offset + } else if (offset % (24*60) == 0) { // divides evenly into days? useoffset = offset / (24*60); mAlarmIncrCombo->setCurrentItem(2); } else if (offset % 60 == 0) { // divides evenly into hours? @@ -388,97 +460,105 @@ void KOEditorGeneral::updateAlarmWidgets() } mAlarmTimeEdit->setValue( useoffset ); } else { - mAlarmStack->raiseWidget( AdvancedAlarmLabel ); - mAlarmInfoLabel->setText( i18n("1 advanced reminder configured") ); - mAlarmEditButton->setEnabled( true ); + mAlarmIsSimple = false; + mAlarmAdvancedButton->setEnabled( true ); + mSimpleAlarmBox->hide(); + if ( incidence ) { + TQString remStr = IncidenceFormatter::reminderStringList( incidence ).first(); + mAlarmInfoLabel->setText( i18n( "Triggers %1" ).arg( remStr ) ); + } } } } -void KOEditorGeneral::readIncidence(Incidence *event, Calendar *calendar) +void KOEditorGeneral::readIncidence( Incidence *incidence, Calendar *calendar ) { - mSummaryEdit->setText(event->summary()); - mLocationEdit->setText(event->location()); + mSummaryEdit->setText( incidence->summary() ); + mLocationEdit->setText( incidence->location() ); + mDescriptionEdit->setText( incidence->description() ); - mDescriptionEdit->setText(event->description()); - -#if 0 - // organizer information - mOwnerLabel->setText(i18n("Owner: ") + event->organizer().fullName() ); -#endif - - mSecrecyCombo->setCurrentItem(event->secrecy()); + mSecrecyCombo->setCurrentItem( incidence->secrecy() ); // set up alarm stuff mAlarmList.clear(); Alarm::List::ConstIterator it; - Alarm::List alarms = event->alarms(); + Alarm::List alarms = incidence->alarms(); for( it = alarms.begin(); it != alarms.end(); ++it ) { Alarm *al = new Alarm( *(*it) ); al->setParent( 0 ); mAlarmList.append( al ); } updateDefaultAlarmTime(); - updateAlarmWidgets(); + updateAlarmWidgets( incidence ); - setCategories(event->categories()); + setCategories( incidence->categories() ); - mAttachments->readIncidence( event ); + mAttachments->readIncidence( incidence ); - TQString resLabel = KOHelper::resourceLabel( calendar, event ); + TQString resLabel = IncidenceFormatter::resourceString( calendar, incidence ); if ( !resLabel.isEmpty() ) { mResourceLabel->setText( i18n( "Calendar: %1" ).arg( resLabel ) ); mResourceLabel->show(); } } -Alarm *KOEditorGeneral::alarmFromSimplePage() const +Alarm *KOEditorGeneral::alarmFromSimplePage( Incidence *incidence ) const { if ( mAlarmButton->isChecked() ) { Alarm *alarm = new Alarm( 0 ); - alarm->setDisplayAlarm(""); + alarm->setDisplayAlarm( "" ); alarm->setEnabled(true); TQString tmpStr = mAlarmTimeEdit->text(); int j = mAlarmTimeEdit->value() * -60; - if (mAlarmIncrCombo->currentItem() == 1) + if ( mAlarmIncrCombo->currentItem() == 1 ) { j = j * 60; - else if (mAlarmIncrCombo->currentItem() == 2) + } else if ( mAlarmIncrCombo->currentItem() == 2 ) { j = j * (60 * 24); - alarm->setStartOffset( j ); + } + if ( mType == "Event" ) { + alarm->setStartOffset( j ); + } + if ( mType == "Todo" ) { + Todo *todo = static_cast<Todo *>( incidence ); + if ( todo && todo->hasStartDate() && !todo->hasDueDate() ) { + alarm->setStartOffset( j ); + } else { + alarm->setEndOffset( j ); + } + } return alarm; } else { return 0; } } -void KOEditorGeneral::writeIncidence(Incidence *event) +void KOEditorGeneral::writeIncidence( Incidence *incidence ) { -// kdDebug(5850) << "KOEditorGeneral::writeEvent()" << endl; - - event->setSummary(mSummaryEdit->text()); - event->setLocation(mLocationEdit->text()); - event->setDescription(mDescriptionEdit->text()); - event->setCategories(mCategories); - event->setSecrecy(mSecrecyCombo->currentItem()); + incidence->setSummary(mSummaryEdit->text()); + incidence->setLocation(mLocationEdit->text()); + incidence->setDescription(mDescriptionEdit->text()); + incidence->setCategories(mCategories); + incidence->setSecrecy(mSecrecyCombo->currentItem()); // alarm stuff - event->clearAlarms(); - if ( mAlarmStack->id( mAlarmStack->visibleWidget() ) == SimpleAlarmPage ) { - Alarm *al = alarmFromSimplePage(); + incidence->clearAlarms(); + if ( mAlarmIsSimple ) { + Alarm *al = alarmFromSimplePage( incidence ); if ( al ) { - al->setParent( event ); - event->addAlarm( al ); + al->setParent( incidence ); + al->setEnabled( mAlarmButton->isChecked() ); + incidence->addAlarm( al ); } } else { // simply assign the list of alarms Alarm::List::ConstIterator it; for( it = mAlarmList.begin(); it != mAlarmList.end(); ++it ) { Alarm *al = new Alarm( *(*it) ); - al->setParent( event ); - al->setEnabled( true ); - event->addAlarm( al ); + al->setParent( incidence ); + al->setEnabled( mAlarmButton->isChecked() ); + incidence->addAlarm( al ); } } - mAttachments->writeIncidence( event ); + mAttachments->writeIncidence( incidence ); } void KOEditorGeneral::setSummary( const TQString &text ) @@ -499,7 +579,7 @@ TQObject *KOEditorGeneral::typeAheadReceiver() const void KOEditorGeneral::updateAttendeeSummary(int count) { if ( count <= 0 ) - mAttendeeSummaryLabel->setText( "No attendees" ); + mAttendeeSummaryLabel->setText( i18n("No attendees") ); else mAttendeeSummaryLabel->setText( i18n( "One attendee", "%n attendees", count ) ); } diff --git a/korganizer/koeditorgeneral.h b/korganizer/koeditorgeneral.h index b1fffc26c..1a9d6017c 100644 --- a/korganizer/koeditorgeneral.h +++ b/korganizer/koeditorgeneral.h @@ -28,10 +28,10 @@ class TQWidget; class TQBoxLayout; +class TQHBox; class TQLineEdit; class TQLabel; class TQCheckBox; -class TQWidgetStack; class TQSpinBox; class TQPushButton; class TQComboBox; @@ -41,8 +41,8 @@ class KURL; class KOEditorAttachments; namespace KCal { -class Incidence; -class Calendar; + class Incidence; + class Calendar; } using namespace KCal; @@ -77,10 +77,10 @@ class KOEditorGeneral : public QObject /** Set widgets to default values */ void setDefaults(bool allDay); - /** Read event object and setup widgets accordingly */ - void readIncidence(Incidence *event, Calendar *calendar); - /** Write event settings to event object */ - void writeIncidence(Incidence *); + /** Read incidence object and setup widgets accordingly */ + void readIncidence( Incidence *incidence, Calendar *calendar ); + /** Write incidence settings to incidence object */ + void writeIncidence( Incidence *incidence ); /** Check if the input is valid. */ bool validateInput() { return true; } @@ -96,14 +96,14 @@ class KOEditorGeneral : public QObject public slots: void setCategories(const TQStringList &categories); void selectCategories(); + void setType( const TQCString &type ); void addAttachments( const TQStringList &attachments, const TQStringList& mimeTypes = TQStringList(), bool inlineAttachment = false ); - protected slots: void editAlarms(); - void updateAlarmWidgets(); + void updateAlarmWidgets( Incidence *incidence ); void updateDefaultAlarmTime(); void updateAttendeeSummary( int count ); @@ -112,19 +112,19 @@ class KOEditorGeneral : public QObject void updateCategoryConfig(); void focusReceivedSignal(); void openURL( const KURL & ); - protected: - Alarm *alarmFromSimplePage() const; + protected: TQLineEdit *mSummaryEdit; TQLineEdit *mLocationEdit; TQLabel *mAttendeeSummaryLabel; + TQLabel *mRecEditLabel; + TQPushButton *mRecEditButton; TQLabel *mAlarmBell; - TQWidgetStack *mAlarmStack; TQLabel *mAlarmInfoLabel; TQCheckBox *mAlarmButton; TQSpinBox *mAlarmTimeEdit; TQComboBox *mAlarmIncrCombo; - TQPushButton *mAlarmEditButton; + TQPushButton *mAlarmAdvancedButton; KTextEdit *mDescriptionEdit; TQLabel *mOwnerLabel; TQComboBox *mSecrecyCombo; @@ -133,10 +133,14 @@ class KOEditorGeneral : public QObject KOEditorAttachments *mAttachments; TQLabel *mResourceLabel; - enum AlarmStackPages { SimpleAlarmPage, AdvancedAlarmLabel }; - private: + Alarm *alarmFromSimplePage( Incidence *incidence ) const; + bool isSimpleAlarm( Alarm *alarm ) const; + + bool mAlarmIsSimple; + TQHBox *mSimpleAlarmBox; TQStringList mCategories; + TQCString mType; // as in Incidence::type() KCal::Alarm::List mAlarmList; }; diff --git a/korganizer/koeditorgeneralevent.cpp b/korganizer/koeditorgeneralevent.cpp index 24e8b4ca2..0411c2f8e 100644 --- a/korganizer/koeditorgeneralevent.cpp +++ b/korganizer/koeditorgeneralevent.cpp @@ -39,7 +39,6 @@ #include <kdebug.h> #include <kglobal.h> #include <klocale.h> -#include <kiconloader.h> #include <kmessagebox.h> #include <kfiledialog.h> #include <kstandarddirs.h> @@ -52,6 +51,7 @@ #include <libkdepim/kdateedit.h> #include "koprefs.h" +#include "koglobals.h" #include "koeditorgeneralevent.h" #include "koeditorgeneralevent.moc" @@ -78,18 +78,15 @@ void KOEditorGeneralEvent::finishSetup() TQWidget::setTabOrder( mStartTimeEdit, mEndDateEdit ); TQWidget::setTabOrder( mEndDateEdit, mEndTimeEdit ); TQWidget::setTabOrder( mEndTimeEdit, mAlldayEventCheckbox ); - TQWidget::setTabOrder( mAlldayEventCheckbox, mAlarmButton ); + TQWidget::setTabOrder( mAlldayEventCheckbox, mRecEditButton ); + TQWidget::setTabOrder( mRecEditButton, mAlarmButton ); TQWidget::setTabOrder( mAlarmButton, mAlarmTimeEdit ); TQWidget::setTabOrder( mAlarmTimeEdit, mAlarmIncrCombo ); -// TQWidget::setTabOrder( mAlarmIncrCombo, mAlarmSoundButton ); - TQWidget::setTabOrder( mAlarmIncrCombo, mAlarmEditButton ); -// TQWidget::setTabOrder( mAlarmSoundButton, mAlarmProgramButton ); -// TQWidget::setTabOrder( mAlarmProgramButton, mFreeTimeCombo ); - TQWidget::setTabOrder( mAlarmEditButton, mFreeTimeCombo ); + TQWidget::setTabOrder( mAlarmIncrCombo, mAlarmAdvancedButton ); + TQWidget::setTabOrder( mAlarmAdvancedButton, mFreeTimeCombo ); TQWidget::setTabOrder( mFreeTimeCombo, mDescriptionEdit ); TQWidget::setTabOrder( mDescriptionEdit, mCategoriesButton ); TQWidget::setTabOrder( mCategoriesButton, mSecrecyCombo ); -// TQWidget::setTabOrder( mSecrecyCombo, mDescriptionEdit ); mSummaryEdit->setFocus(); } @@ -121,7 +118,6 @@ void KOEditorGeneralEvent::initTime(TQWidget *parent,TQBoxLayout *topLayout) mStartTimeEdit = new KTimeEdit(timeBoxFrame); layoutTimeBox->addWidget(mStartTimeEdit,0,2); - mEndDateLabel = new TQLabel(i18n("&End:"),timeBoxFrame); layoutTimeBox->addWidget(mEndDateLabel,1,0); @@ -151,16 +147,19 @@ void KOEditorGeneralEvent::initTime(TQWidget *parent,TQBoxLayout *topLayout) connect(mEndDateEdit, TQT_SIGNAL(dateChanged(const TQDate&)), this, TQT_SLOT(endDateChanged(const TQDate&))); + TQLabel *label = new TQLabel( i18n( "Recurrence:" ), timeBoxFrame ); + layoutTimeBox->addWidget( label, 2, 0 ); TQBoxLayout *recLayout = new TQHBoxLayout(); layoutTimeBox->addMultiCellLayout( recLayout, 2, 2, 1, 4 ); - mRecurrenceSummary = new TQLabel( TQString(), timeBoxFrame ); - recLayout->addWidget( mRecurrenceSummary ); - TQPushButton *recEditButton = new TQPushButton( i18n("Edit..."), timeBoxFrame ); - recLayout->addWidget( recEditButton ); - connect( recEditButton, TQT_SIGNAL(clicked()), TQT_SIGNAL(editRecurrence()) ); + mRecEditButton = new TQPushButton( timeBoxFrame ); + mRecEditButton->setIconSet( KOGlobals::self()->smallIconSet( "recur", 16 ) ); + recLayout->addWidget( mRecEditButton ); + connect( mRecEditButton, TQT_SIGNAL(clicked()), TQT_SIGNAL(editRecurrence()) ); + mRecEditLabel = new TQLabel( TQString(), timeBoxFrame ); + recLayout->addWidget( mRecEditLabel ); recLayout->addStretch( 1 ); - TQLabel *label = new TQLabel( i18n("Reminder:"), timeBoxFrame ); + label = new TQLabel( i18n("Reminder:"), timeBoxFrame ); layoutTimeBox->addWidget( label, 3, 0 ); TQBoxLayout *alarmLineLayout = new TQHBoxLayout(); layoutTimeBox->addMultiCellLayout( alarmLineLayout, 3, 3, 1, 4 ); @@ -230,7 +229,6 @@ void KOEditorGeneralEvent::timeStuffDisable(bool disable) void KOEditorGeneralEvent::associateTime(bool time) { timeStuffDisable(time); - //if(alarmButton->isChecked()) alarmStuffDisable(noTime); allDayChanged(time); } @@ -317,7 +315,7 @@ void KOEditorGeneralEvent::setDefaults( const TQDateTime &from, setDateTimes(from,to); } -void KOEditorGeneralEvent::readEvent( Event *event, Calendar *calendar, bool tmpl ) +void KOEditorGeneralEvent::readEvent( Event *event, Calendar *calendar, const TQDate &date, bool tmpl ) { TQString tmpStr; @@ -325,8 +323,26 @@ void KOEditorGeneralEvent::readEvent( Event *event, Calendar *calendar, bool tmp timeStuffDisable(event->doesFloat()); if ( !tmpl ) { + TQDateTime startDT = event->dtStart(); + TQDateTime endDT = event->dtEnd(); + if ( event->doesRecur() && date.isValid() ) { + // Consider the active date when editing recurring Events. + TQDateTime kdt( date, TQTime( 0, 0, 0 ) ); + const int eventLength = startDT.daysTo( endDT ); + kdt = kdt.addSecs( -1 ); + startDT.setDate( event->recurrence()->getNextDateTime( kdt ).date() ); + if ( event->hasEndDate() ) { + endDT.setDate( startDT.addDays( eventLength ).date() ); + } else { + if ( event->hasDuration() ) { + endDT = startDT.addSecs( event->duration() ); + } else { + endDT = startDT; + } + } + } // the rest is for the events only - setDateTimes(event->dtStart(),event->dtEnd()); + setDateTimes( startDT, endDT ); } switch( event->transparency() ) { @@ -338,11 +354,13 @@ void KOEditorGeneralEvent::readEvent( Event *event, Calendar *calendar, bool tmp break; } - mRecurrenceSummary->setText( IncidenceFormatter::recurrenceString( event ) ); + updateRecurrenceSummary( event ); Attendee *me = event->attendeeByMails( KOPrefs::instance()->allEmails() ); - if ( me && (me->status() == Attendee::NeedsAction || me->status() == Attendee::Tentative || - me->status() == Attendee::InProcess) ) { + if ( event->attendeeCount() > 1 && + me && ( me->status() == Attendee::NeedsAction || + me->status() == Attendee::Tentative || + me->status() == Attendee::InProcess ) ) { mInvitationBar->show(); } else { mInvitationBar->hide(); @@ -509,16 +527,22 @@ bool KOEditorGeneralEvent::validateInput() endDt.setTime(mEndTimeEdit->getTime()); } - if (startDt > endDt) { - KMessageBox::sorry(0,i18n("The event ends before it starts.\n" - "Please correct dates and times.")); + if ( startDt > endDt ) { + KMessageBox::sorry( + 0, + i18n( "The event ends before it starts.\n" + "Please correct dates and times." ) ); return false; } return KOEditorGeneral::validateInput(); } -void KOEditorGeneralEvent::updateRecurrenceSummary(const TQString & summary) +void KOEditorGeneralEvent::updateRecurrenceSummary( Event *event ) { - mRecurrenceSummary->setText( summary ); + if ( event->doesRecur() ) { + mRecEditLabel->setText( IncidenceFormatter::recurrenceString( event ) ); + } else { + mRecEditLabel->setText( TQString() ); + } } diff --git a/korganizer/koeditorgeneralevent.h b/korganizer/koeditorgeneralevent.h index a13fa47c6..57ffba8df 100644 --- a/korganizer/koeditorgeneralevent.h +++ b/korganizer/koeditorgeneralevent.h @@ -58,14 +58,14 @@ class KOEditorGeneralEvent : public KOEditorGeneral Read event object and setup widgets accordingly. If templ is true, the event is read as template, i.e. the time and date information isn't set. */ - void readEvent( Event *event, Calendar *calendar, bool tmpl = false ); + void readEvent( Event *event, Calendar *calendar, const TQDate &date, bool tmpl = false ); /** Write event settings to event object */ void writeEvent( Event * ); /** Check if the input is valid. */ bool validateInput(); - void updateRecurrenceSummary( const TQString &summary ); + void updateRecurrenceSummary( Event *event ); TQFrame* invitationBar() const { return mInvitationBar; } @@ -102,7 +102,6 @@ class KOEditorGeneralEvent : public KOEditorGeneral TQLabel *mDurationLabel; TQCheckBox *mAlldayEventCheckbox; TQComboBox *mFreeTimeCombo; - TQLabel *mRecurrenceSummary; TQFrame *mInvitationBar; // current start and end date and time diff --git a/korganizer/koeditorgeneraljournal.cpp b/korganizer/koeditorgeneraljournal.cpp index 620417194..0a4e5ec36 100644 --- a/korganizer/koeditorgeneraljournal.cpp +++ b/korganizer/koeditorgeneraljournal.cpp @@ -45,10 +45,11 @@ #include <tqwhatsthis.h> -KOEditorGeneralJournal::KOEditorGeneralJournal( TQObject *parent, +KOEditorGeneralJournal::KOEditorGeneralJournal( TQWidget *parent, const char *name ) - : TQObject( parent, name ) + : KOEditorGeneral( parent, name ) { + setType( "Journal" ); } KOEditorGeneralJournal::~KOEditorGeneralJournal() @@ -58,7 +59,7 @@ KOEditorGeneralJournal::~KOEditorGeneralJournal() void KOEditorGeneralJournal::initTitle( TQWidget *parent, TQBoxLayout *topLayout ) { TQHBoxLayout *hbox = new TQHBoxLayout( topLayout ); - + TQString whatsThis = i18n("Sets the title of this journal."); TQLabel *summaryLabel = new TQLabel( i18n("T&itle:"), parent ); TQWhatsThis::add( summaryLabel, whatsThis ); @@ -78,19 +79,19 @@ void KOEditorGeneralJournal::initDate( TQWidget *parent, TQBoxLayout *topLayout { // TQBoxLayout *dateLayout = new TQVBoxLayout(topLayout); TQBoxLayout *dateLayout = new TQHBoxLayout( topLayout ); - + mDateLabel = new TQLabel( i18n("&Date:"), parent); dateLayout->addWidget( mDateLabel ); mDateEdit = new KDateEdit( parent ); dateLayout->addWidget( mDateEdit ); mDateLabel->setBuddy( mDateEdit ); - + dateLayout->addStretch(); - + mTimeCheckBox = new TQCheckBox( i18n("&Time: "), parent ); dateLayout->addWidget( mTimeCheckBox ); - + mTimeEdit = new KTimeEdit( parent ); dateLayout->addWidget( mTimeEdit ); connect( mTimeCheckBox, TQT_SIGNAL(toggled(bool)), @@ -135,7 +136,7 @@ void KOEditorGeneralJournal::setDefaults( const TQDate &date ) setDate( date ); } -void KOEditorGeneralJournal::readJournal( Journal *journal, bool tmpl ) +void KOEditorGeneralJournal::readJournal( Journal *journal, const TQDate &, bool tmpl ) { setSummary( journal->summary() ); if ( !tmpl ) { @@ -143,10 +144,10 @@ void KOEditorGeneralJournal::readJournal( Journal *journal, bool tmpl ) if ( !journal->doesFloat() ) { kdDebug()<<"KOEditorGeneralJournal::readJournal, does not float, time="<<(journal->dtStart().time().toString())<<endl; setTime( journal->dtStart().time() ); - } else { + } else { kdDebug()<<"KOEditorGeneralJournal::readJournal, does float"<<endl; setTime( TQTime( -1, -1, -1 ) ); - } + } } setDescription( journal->description() ); } @@ -156,7 +157,7 @@ void KOEditorGeneralJournal::writeJournal( Journal *journal ) // kdDebug(5850) << "KOEditorGeneralJournal::writeIncidence()" << endl; journal->setSummary( mSummaryEdit->text() ); journal->setDescription( mDescriptionEdit->text() ); - + TQDateTime tmpDT( mDateEdit->date(), TQTime(0,0,0) ); bool hasTime = mTimeCheckBox->isChecked(); journal->setFloats( !hasTime ); diff --git a/korganizer/koeditorgeneraljournal.h b/korganizer/koeditorgeneraljournal.h index 28827c8c8..649a6d345 100644 --- a/korganizer/koeditorgeneraljournal.h +++ b/korganizer/koeditorgeneraljournal.h @@ -25,6 +25,8 @@ #ifndef KOEDITORGENERALJOURNAL_H #define KOEDITORGENERALJOURNAL_H +#include "koeditorgeneral.h" + #include <tqobject.h> #include <tqdatetime.h> @@ -43,11 +45,11 @@ class Journal; } using namespace KCal; -class KOEditorGeneralJournal : public QObject +class KOEditorGeneralJournal : public KOEditorGeneral { - Q_OBJECT + Q_OBJECT public: - KOEditorGeneralJournal ( TQObject* parent=0, const char* name=0 ); + KOEditorGeneralJournal ( TQWidget *parent=0, const char* name=0 ); virtual ~KOEditorGeneralJournal(); void initDate( TQWidget *, TQBoxLayout * ); @@ -59,7 +61,7 @@ class KOEditorGeneralJournal : public QObject void setDate( const TQDate &date ); void setTime( const TQTime &time ); /** Read journal object and setup widgets accordingly */ - void readJournal( Journal *, bool tmpl = false ); + void readJournal( Journal *, const TQDate &, bool tmpl = false ); /** Write journal settings to event object */ void writeJournal( Journal * ); diff --git a/korganizer/koeditorgeneraltodo.cpp b/korganizer/koeditorgeneraltodo.cpp index dd2a77b5c..d659e8e95 100644 --- a/korganizer/koeditorgeneraltodo.cpp +++ b/korganizer/koeditorgeneraltodo.cpp @@ -38,13 +38,13 @@ #include <kglobal.h> #include <klocale.h> -#include <kiconloader.h> #include <kmessagebox.h> #include <kdebug.h> #include <kstandarddirs.h> #include <kfiledialog.h> #include <ktextedit.h> +#include <libkcal/incidenceformatter.h> #include <libkcal/todo.h> #include <libkdepim/kdateedit.h> @@ -56,10 +56,10 @@ #include "koeditorgeneraltodo.h" #include "koeditorgeneraltodo.moc" -KOEditorGeneralTodo::KOEditorGeneralTodo(TQObject* parent, - const char* name) - : KOEditorGeneral( parent, name) +KOEditorGeneralTodo::KOEditorGeneralTodo( TQObject *parent, const char *name ) + : KOEditorGeneral( parent, name ) { + setType( "Todo" ); } KOEditorGeneralTodo::~KOEditorGeneralTodo() @@ -76,19 +76,17 @@ void KOEditorGeneralTodo::finishSetup() TQWidget::setTabOrder( mDueCheck, mDueDateEdit ); TQWidget::setTabOrder( mDueDateEdit, mDueTimeEdit ); TQWidget::setTabOrder( mDueTimeEdit, mTimeButton ); - TQWidget::setTabOrder( mTimeButton, mCompletedCombo ); + TQWidget::setTabOrder( mTimeButton, mRecEditButton ); + TQWidget::setTabOrder( mRecEditButton, mCompletedToggle ); + TQWidget::setTabOrder( mCompletedToggle, mCompletedCombo ); TQWidget::setTabOrder( mCompletedCombo, mPriorityCombo ); TQWidget::setTabOrder( mPriorityCombo, mAlarmButton ); TQWidget::setTabOrder( mAlarmButton, mAlarmTimeEdit ); TQWidget::setTabOrder( mAlarmTimeEdit, mAlarmIncrCombo ); -// TQWidget::setTabOrder( mAlarmIncrCombo, mAlarmSoundButton ); - TQWidget::setTabOrder( mAlarmIncrCombo, mAlarmEditButton ); -// TQWidget::setTabOrder( mAlarmSoundButton, mAlarmProgramButton ); -// TQWidget::setTabOrder( mAlarmProgramButton, mDescriptionEdit ); - TQWidget::setTabOrder( mAlarmEditButton, mDescriptionEdit ); + TQWidget::setTabOrder( mAlarmIncrCombo, mAlarmAdvancedButton ); + TQWidget::setTabOrder( mAlarmAdvancedButton, mDescriptionEdit ); TQWidget::setTabOrder( mDescriptionEdit, mCategoriesButton ); TQWidget::setTabOrder( mCategoriesButton, mSecrecyCombo ); -// TQWidget::setTabOrder( mSecrecyCombo, mDescriptionEdit ); mSummaryEdit->setFocus(); } @@ -134,7 +132,6 @@ void KOEditorGeneralTodo::initTime(TQWidget *parent,TQBoxLayout *topLayout) TQWhatsThis::add( mDueCheck, whatsThis ); layoutTimeBox->addWidget(mDueCheck,1,0); connect(mDueCheck,TQT_SIGNAL(toggled(bool)),TQT_SLOT(enableDueEdit(bool))); - connect(mDueCheck,TQT_SIGNAL(toggled(bool)),TQT_SLOT(showAlarm())); connect(mDueCheck,TQT_SIGNAL(toggled(bool)),TQT_SIGNAL(dueDateEditToggle(bool))); connect(mDueCheck,TQT_SIGNAL(toggled(bool)),TQT_SLOT(dateChanged())); @@ -153,13 +150,31 @@ void KOEditorGeneralTodo::initTime(TQWidget *parent,TQBoxLayout *topLayout) TQWhatsThis::add( mTimeButton, i18n("Sets whether or not this to-do's start and due dates " "have times associated with them.") ); - layoutTimeBox->addMultiCellWidget(mTimeButton,2,2,0,2); - + layoutTimeBox->addWidget( mTimeButton, 0, 3 ); connect(mTimeButton,TQT_SIGNAL(toggled(bool)),TQT_SLOT(enableTimeEdits(bool))); connect(mTimeButton,TQT_SIGNAL(toggled(bool)),TQT_SLOT(dateChanged())); + TQLabel *label = new TQLabel( i18n( "Recurrence:" ), timeBoxFrame ); + layoutTimeBox->addWidget( label, 3, 0 ); + TQBoxLayout *recLayout = new TQHBoxLayout(); + layoutTimeBox->addMultiCellLayout( recLayout, 3, 3, 1, 4 ); + mRecEditButton = new TQPushButton( timeBoxFrame ); + mRecEditButton->setIconSet( KOGlobals::self()->smallIconSet( "recur", 16 ) ); + recLayout->addWidget( mRecEditButton ); + connect( mRecEditButton, TQT_SIGNAL(clicked()), TQT_SIGNAL(editRecurrence()) ); + mRecEditLabel = new TQLabel( TQString(), timeBoxFrame ); + recLayout->addWidget( mRecEditLabel ); + recLayout->addStretch( 1 ); + + label = new TQLabel( i18n("Reminder:"), timeBoxFrame ); + layoutTimeBox->addWidget( label, 4, 0 ); + TQBoxLayout *alarmLineLayout = new TQHBoxLayout(); + layoutTimeBox->addMultiCellLayout( alarmLineLayout, 4, 4, 1, 4 ); + initAlarm( timeBoxFrame, alarmLineLayout ); + alarmLineLayout->addStretch( 1 ); + // some more layouting - layoutTimeBox->setColStretch(3,1); + layoutTimeBox->setColStretch( 3, 1 ); TQBoxLayout *secLayout = new TQHBoxLayout(); layoutTimeBox->addLayout( secLayout, 0, 4 ); @@ -167,54 +182,73 @@ void KOEditorGeneralTodo::initTime(TQWidget *parent,TQBoxLayout *topLayout) } -void KOEditorGeneralTodo::initCompletion(TQWidget *parent, TQBoxLayout *topLayout) +void KOEditorGeneralTodo::initCompletion( TQWidget *parent, TQBoxLayout *topLayout ) { - TQString whatsThis = i18n("Sets the current completion status of this to-do " - "as a percentage."); - mCompletedCombo = new TQComboBox(parent); - TQWhatsThis::add( mCompletedCombo, whatsThis ); - for (int i = 0; i <= 100; i+=10) { + TQHBoxLayout *completionLayout = new TQHBoxLayout( topLayout ); + + TQLabel *label = new TQLabel( i18n( "&Completed:" ), parent ); + completionLayout->addWidget( label ); + + mCompletedToggle = new TQCheckBox( parent ); + TQToolTip::add( mCompletedToggle, + i18n( "Toggle between 0% and 100% complete" ) ); + TQWhatsThis::add( mCompletedToggle, + i18n( "Click this checkbox to toggle the completed percentage of the to-do " + "between 0% or 100%" ) ); + connect( mCompletedToggle, TQT_SIGNAL(clicked()), TQT_SLOT(completedChanged()) ); + completionLayout->addWidget( mCompletedToggle ); + label->setBuddy( mCompletedToggle ); + + mCompletedCombo = new TQComboBox( parent ); + TQToolTip::add( mCompletedCombo, + i18n( "Select the completed percentage" ) ); + TQWhatsThis::add( mCompletedCombo, + i18n( "Use this combobox to set the completion percentage of the to-do." ) ); + for ( int i = 0; i <= 100; i+=10 ) { // xgettext:no-c-format - TQString label = i18n("Percent complete", "%1 %").arg (i); - mCompletedCombo->insertItem(label); + TQString label = i18n( "Percent complete", "%1 %" ).arg( i ); + mCompletedCombo->insertItem( label ); } - connect(mCompletedCombo,TQT_SIGNAL(activated(int)),TQT_SLOT(completedChanged(int))); - topLayout->addWidget(mCompletedCombo); + connect( mCompletedCombo, TQT_SIGNAL(activated(int)), TQT_SLOT(completedChanged(int)) ); + completionLayout->addWidget( mCompletedCombo ); + + mCompletedLabel = new TQLabel( i18n( "completed on", "on" ), parent ); + mCompletedLabel->hide(); + completionLayout->addWidget( mCompletedLabel ); - mCompletedLabel = new TQLabel(i18n("co&mpleted"),parent); - topLayout->addWidget(mCompletedLabel); - mCompletedLabel->setBuddy( mCompletedCombo ); mCompletionDateEdit = new KDateEdit( parent ); mCompletionDateEdit->hide(); - topLayout->addWidget( mCompletionDateEdit ); + completionLayout->addWidget( mCompletionDateEdit ); + mCompletionTimeEdit = new KTimeEdit( parent, TQTime() ); mCompletionTimeEdit->hide(); - topLayout->addWidget( mCompletionTimeEdit ); + completionLayout->addWidget( mCompletionTimeEdit ); } void KOEditorGeneralTodo::initPriority(TQWidget *parent, TQBoxLayout *topLayout) { - TQString whatsThis = i18n("Sets the priority of this to-do on a scale " - "from one to nine, with one being the highest " - "priority, five being a medium priority, and " - "nine being the lowest. In programs that have a " - "different scale, the numbers will be adjusted " - "to match the appropriate scale."); - TQLabel *priorityLabel = new TQLabel(i18n("&Priority:"),parent); - topLayout->addWidget(priorityLabel); - - mPriorityCombo = new TQComboBox(parent); - mPriorityCombo->insertItem(i18n("unspecified")); - mPriorityCombo->insertItem(i18n("1 (highest)")); - mPriorityCombo->insertItem(i18n("2")); - mPriorityCombo->insertItem(i18n("3")); - mPriorityCombo->insertItem(i18n("4")); - mPriorityCombo->insertItem(i18n("5 (medium)")); - mPriorityCombo->insertItem(i18n("6")); - mPriorityCombo->insertItem(i18n("7")); - mPriorityCombo->insertItem(i18n("8")); - mPriorityCombo->insertItem(i18n("9 (lowest)")); - topLayout->addWidget(mPriorityCombo); + TQLabel *priorityLabel = new TQLabel( i18n( "&Priority:" ), parent ); + topLayout->addWidget( priorityLabel ); + + mPriorityCombo = new TQComboBox( parent ); + TQToolTip::add( mPriorityCombo, + i18n( "Set the priority of the to-do" ) ); + TQWhatsThis::add( mPriorityCombo, + i18n( "Sets the priority of this to-do on a scale from one to nine, " + "with one being the highest priority, five being a medium priority, " + "and nine being the lowest. In programs that have a different scale, " + "the numbers will be adjusted to match the appropriate scale." ) ); + mPriorityCombo->insertItem( i18n( "unspecified" ) ); + mPriorityCombo->insertItem( i18n( "1 (highest)" ) ); + mPriorityCombo->insertItem( i18n( "2" ) ); + mPriorityCombo->insertItem( i18n( "3" ) ); + mPriorityCombo->insertItem( i18n( "4" ) ); + mPriorityCombo->insertItem( i18n( "5 (medium)" ) ); + mPriorityCombo->insertItem( i18n( "6" ) ); + mPriorityCombo->insertItem( i18n( "7" ) ); + mPriorityCombo->insertItem( i18n( "8" ) ); + mPriorityCombo->insertItem( i18n( "9 (lowest)" ) ); + topLayout->addWidget( mPriorityCombo ); priorityLabel->setBuddy( mPriorityCombo ); } @@ -263,25 +297,29 @@ void KOEditorGeneralTodo::setDefaults( const TQDateTime &due, bool allDay ) } mStartDateModified = false; - mPriorityCombo->setCurrentItem(5); + mPriorityCombo->setCurrentItem( 5 ); - mCompletedCombo->setCurrentItem(0); + mCompletedToggle->setChecked( false ); + mCompletedCombo->setCurrentItem( 0 ); } -void KOEditorGeneralTodo::readTodo(Todo *todo, Calendar *calendar) +void KOEditorGeneralTodo::readTodo(Todo *todo, Calendar *calendar, const TQDate &date ) { KOEditorGeneral::readIncidence(todo, calendar); TQDateTime dueDT; if (todo->hasDueDate()) { - enableAlarm( true ); dueDT = todo->dtDue(); - mDueDateEdit->setDate(todo->dtDue().date()); - mDueTimeEdit->setTime(todo->dtDue().time()); + if ( todo->doesRecur() && date.isValid() ) { + TQDateTime dt( date, TQTime( 0, 0, 0 ) ); + dt = dt.addSecs( -1 ); + dueDT.setDate( todo->recurrence()->getNextDateTime( dt ).date() ); + } + mDueDateEdit->setDate(dueDT.date()); + mDueTimeEdit->setTime(dueDT.time()); mDueCheck->setChecked(true); } else { - enableAlarm( false ); mDueDateEdit->setEnabled(false); mDueTimeEdit->setEnabled(false); mDueDateEdit->setDate(TQDate::currentDate()); @@ -290,8 +328,13 @@ void KOEditorGeneralTodo::readTodo(Todo *todo, Calendar *calendar) } if (todo->hasStartDate()) { - mStartDateEdit->setDate(todo->dtStart().date()); - mStartTimeEdit->setTime(todo->dtStart().time()); + TQDateTime startDT = todo->dtStart(); + if ( todo->doesRecur() && date.isValid() && todo->hasDueDate() ) { + int days = todo->dtStart( true ).daysTo( todo->dtDue( true ) ); + startDT.setDate( date.addDays( -days ) ); + } + mStartDateEdit->setDate(startDT.date()); + mStartTimeEdit->setTime(startDT.time()); mStartCheck->setChecked(true); } else { mStartDateEdit->setEnabled(false); @@ -303,10 +346,13 @@ void KOEditorGeneralTodo::readTodo(Todo *todo, Calendar *calendar) mTimeButton->setChecked( !todo->doesFloat() ); + updateRecurrenceSummary( todo ); + mAlreadyComplete = false; - mCompletedCombo->setCurrentItem(todo->percentComplete() / 10); - if (todo->isCompleted() && todo->hasCompletedDate()) { - mCompleted = todo->completed(); + mCompletedCombo->setCurrentItem( todo->percentComplete() / 10 ); + if ( todo->isCompleted() && todo->hasCompletedDate() ) { + mCompletedDateTime = todo->completed(); + mCompletedToggle->setChecked( true ); mAlreadyComplete = true; } setCompletedDate(); @@ -369,25 +415,25 @@ void KOEditorGeneralTodo::writeTodo(Todo *todo) if ( todo->doesRecur() && !mStartDateModified ) { todo->setDtDue( tmpDueDT ); } else { - todo->setDtDue( tmpDueDT, true ); - todo->setDtStart( tmpStartDT ); - todo->setDtRecurrence( tmpDueDT ); + todo->setDtDue( tmpDueDT, true ); + todo->setDtStart( tmpStartDT ); + todo->setDtRecurrence( tmpDueDT ); } todo->setPriority( mPriorityCombo->currentItem() ); // set completion state - todo->setPercentComplete(mCompletedCombo->currentItem() * 10); + todo->setPercentComplete( mCompletedCombo->currentItem() * 10 ); - if (mCompletedCombo->currentItem() == 10 && mCompleted.isValid()) { + if (mCompletedCombo->currentItem() == 10 && mCompletedDateTime.isValid()) { TQDateTime completed( mCompletionDateEdit->date(), mCompletionTimeEdit->getTime() ); - int difference = mCompleted.secsTo( completed ); + int difference = mCompletedDateTime.secsTo( completed ); if ( (difference < 60) && (difference > -60) && - (completed.time().minute() == mCompleted.time().minute() ) ) { + (completed.time().minute() == mCompletedDateTime.time().minute() ) ) { // completion time wasn't changed substantially (only the seconds // truncated, but that's an effect done by KTimeEdit automatically). - completed = mCompleted; + completed = mCompletedDateTime; } todo->setCompleted( completed ); } @@ -439,11 +485,6 @@ void KOEditorGeneralTodo::enableTimeEdits(bool enable) } } -void KOEditorGeneralTodo::showAlarm() -{ - enableAlarm( mDueCheck->isChecked() ); -} - bool KOEditorGeneralTodo::validateInput() { if (mDueCheck->isChecked()) { @@ -491,10 +532,33 @@ bool KOEditorGeneralTodo::validateInput() return KOEditorGeneral::validateInput(); } -void KOEditorGeneralTodo::completedChanged(int index) +void KOEditorGeneralTodo::updateRecurrenceSummary( Todo *todo ) +{ + if ( todo->doesRecur() ) { + mRecEditLabel->setText( IncidenceFormatter::recurrenceString( todo ) ); + } else { + mRecEditLabel->setText( TQString() ); + } +} + +void KOEditorGeneralTodo::completedChanged( int index ) { - if (index == 10) { - mCompleted = TQDateTime::currentDateTime(); + if ( index == 10 ) { + mCompletedToggle->setChecked( true ); + mCompletedDateTime = TQDateTime::currentDateTime(); + } else { + mCompletedToggle->setChecked( false ); + } + setCompletedDate(); +} + +void KOEditorGeneralTodo::completedChanged() +{ + if ( mCompletedToggle->isChecked() ) { + mCompletedCombo->setCurrentItem( 10 ); + mCompletedDateTime = TQDateTime::currentDateTime(); + } else { + mCompletedCombo->setCurrentItem( 0 ); } setCompletedDate(); } @@ -533,21 +597,20 @@ void KOEditorGeneralTodo::startDateModified() void KOEditorGeneralTodo::setCompletedDate() { - if (mCompletedCombo->currentItem() == 10 && mCompleted.isValid()) { - mCompletedLabel->setText(i18n("co&mpleted on")); -// .arg(KGlobal::locale()->formatDateTime(mCompleted))); + if ( mCompletedCombo->currentItem() == 10 && mCompletedDateTime.isValid() ) { + mCompletedLabel->show(); mCompletionDateEdit->show(); mCompletionTimeEdit->show(); - mCompletionDateEdit->setDate( mCompleted.date() ); - mCompletionTimeEdit->setTime( mCompleted.time() ); + mCompletionDateEdit->setDate( mCompletedDateTime.date() ); + mCompletionTimeEdit->setTime( mCompletedDateTime.time() ); } else { - mCompletedLabel->setText(i18n("co&mpleted")); + mCompletedLabel->hide(); mCompletionDateEdit->hide(); mCompletionTimeEdit->hide(); } } -void KOEditorGeneralTodo::modified (Todo* todo, int modification) +void KOEditorGeneralTodo::modified (Todo* todo, KOGlobals::HowChanged modification) { switch (modification) { case KOGlobals::PRIORITY_MODIFIED: @@ -556,7 +619,8 @@ void KOEditorGeneralTodo::modified (Todo* todo, int modification) case KOGlobals::COMPLETION_MODIFIED: mCompletedCombo->setCurrentItem(todo->percentComplete() / 10); if (todo->isCompleted() && todo->hasCompletedDate()) { - mCompleted = todo->completed(); + mCompletedDateTime = todo->completed(); + mCompletedToggle->setChecked( true ); } setCompletedDate(); break; @@ -565,7 +629,7 @@ void KOEditorGeneralTodo::modified (Todo* todo, int modification) break; case KOGlobals::UNKNOWN_MODIFIED: // fall through default: - readTodo( todo, 0 ); + readTodo( todo, 0, TQDate() ); break; } } diff --git a/korganizer/koeditorgeneraltodo.h b/korganizer/koeditorgeneraltodo.h index 7ebc1f7ef..2d07cecac 100644 --- a/korganizer/koeditorgeneraltodo.h +++ b/korganizer/koeditorgeneraltodo.h @@ -25,6 +25,8 @@ #define _KOEDITORGENERALTODO_H #include "koeditorgeneral.h" +#include "koglobals.h" + #include <tqdatetime.h> class KRestrictedLine; @@ -54,30 +56,33 @@ class KOEditorGeneralTodo : public KOEditorGeneral /** Set widgets to default values */ void setDefaults( const TQDateTime &due, bool allDay ); /** Read todo object and setup widgets accordingly */ - void readTodo(Todo *todo, Calendar *calendar); + void readTodo( Todo *todo, Calendar *calendar, const TQDate &date ); /** Write todo settings to event object */ void writeTodo(Todo *); /** Check if the input is valid. */ bool validateInput(); + void updateRecurrenceSummary( Todo *todo ); + /** The todo has been modified externally */ - void modified (Todo*, int); + void modified( Todo *todo, KOGlobals::HowChanged modification ); signals: void dueDateEditToggle( bool ); void dateTimeStrChanged( const TQString & ); void signalDateTimeChanged( const TQDateTime &, const TQDateTime & ); + void editRecurrence(); protected slots: - void completedChanged(int); + void completedChanged( int ); + void completedChanged(); void dateChanged(); void startDateModified(); void enableDueEdit( bool enable ); void enableStartEdit( bool enable ); void enableTimeEdits( bool enable ); - void showAlarm(); protected: void setCompletedDate(); @@ -92,6 +97,7 @@ class KOEditorGeneralTodo : public KOEditorGeneral TQCheckBox *mDueCheck; KDateEdit *mDueDateEdit; KTimeEdit *mDueTimeEdit; + TQCheckBox *mCompletedToggle; TQComboBox *mCompletedCombo; TQLabel *mCompletedLabel; TQLabel *mPriorityLabel; @@ -102,7 +108,7 @@ class KOEditorGeneralTodo : public KOEditorGeneral TQCheckBox *mStartCheck; - TQDateTime mCompleted; + TQDateTime mCompletedDateTime; }; diff --git a/korganizer/koeditorrecurrence.cpp b/korganizer/koeditorrecurrence.cpp index 6f24446c2..564c39534 100644 --- a/korganizer/koeditorrecurrence.cpp +++ b/korganizer/koeditorrecurrence.cpp @@ -593,7 +593,8 @@ ExceptionsWidget::ExceptionsWidget( TQWidget *parent, const char *name ) : mExceptionDateEdit->setDate( TQDate::currentDate() ); boxLayout->addWidget( mExceptionDateEdit, 0, 0 ); - TQPushButton *addExceptionButton = new TQPushButton( i18n("&Add"), box ); + TQPushButton *addExceptionButton = new TQPushButton( + i18n( "Add a new recurrence to the recurrence list", "&Add" ), box ); TQWhatsThis::add( addExceptionButton, i18n("Add this date as an exception " "to the recurrence rules for this event or to-do.") ); @@ -1073,6 +1074,9 @@ KOEditorRecurrence::KOEditorRecurrence( TQWidget* parent, const char *name ) : mExceptionsButton = 0; topLayout->addWidget( mExceptionsWidget, 3, 1 ); } + + // set some initial defaults for the saved recurrence + mSaveRec.setDuration( -1 ); // never ending } KOEditorRecurrence::~KOEditorRecurrence() @@ -1083,6 +1087,7 @@ void KOEditorRecurrence::setRecurrenceEnabled( bool enabled ) { // kdDebug(5850) << "KOEditorRecurrence::setRecurrenceEnabled(): " << (enabled ? "on" : "off") << endl; + mEnabledCheck->setChecked( enabled ); mTimeGroupBox->setEnabled( enabled ); mRuleBox->setEnabled( enabled ); if ( mRecurrenceRangeWidget ) mRecurrenceRangeWidget->setEnabled( enabled ); @@ -1147,9 +1152,7 @@ void KOEditorRecurrence::setDefaults( const TQDateTime &from, const TQDateTime & { setDateTimes( from, to ); - bool enabled = false; - mEnabledCheck->setChecked( enabled ); - setRecurrenceEnabled( enabled ); + setRecurrenceEnabled( false ); mRecurrenceRange->setDefaults( from ); @@ -1200,8 +1203,6 @@ void KOEditorRecurrence::readIncidence(Incidence *incidence) f = r->frequency(); } - - mEnabledCheck->setChecked( recurs ); setRecurrenceEnabled( recurs ); int recurrenceType = RecurrenceChooser::Weekly; @@ -1438,10 +1439,218 @@ bool KOEditorRecurrence::doesRecur() return mEnabledCheck->isChecked(); } +void KOEditorRecurrence::saveValues() +{ + int duration = mRecurrenceRange->duration(); + TQDate endDate; + if ( duration == 0 ) { + endDate = mRecurrenceRange->endDate(); + } + + int recurrenceType = mRecurrenceChooser->type(); + if ( recurrenceType == RecurrenceChooser::Daily ) { + mSaveRec.setDaily( mDaily->frequency() ); + } else if ( recurrenceType == RecurrenceChooser::Weekly ) { + mSaveRec.setWeekly( mWeekly->frequency(), mWeekly->days() ); + } else if ( recurrenceType == RecurrenceChooser::Monthly ) { + mSaveRec.setMonthly( mMonthly->frequency() ); + + if ( mMonthly->byPos() ) { + int pos = mMonthly->count(); + + TQBitArray days( 7 ); + days.fill( false ); + days.setBit( mMonthly->weekday() - 1 ); + mSaveRec.addMonthlyPos( pos, days ); + } else { + // it's by day + mSaveRec.addMonthlyDate( mMonthly->day() ); + } + } else if ( recurrenceType == RecurrenceChooser::Yearly ) { + mSaveRec.setYearly( mYearly->frequency() ); + + switch ( mYearly->getType() ) { + case RecurYearly::byMonth: + mSaveRec.addYearlyDate( mYearly->monthDay() ); + mSaveRec.addYearlyMonth( mYearly->month() ); + break; + + case RecurYearly::byPos: + { + mSaveRec.addYearlyMonth( mYearly->posMonth() ); + TQBitArray days( 7 ); + days.fill( false ); + days.setBit( mYearly->posWeekday() - 1 ); + mSaveRec.addYearlyPos( mYearly->posCount(), days ); + break; + } + + case RecurYearly::byDay: + mSaveRec.addYearlyDay( mYearly->day() ); + break; + } + } + + if ( duration > 0 ) { + mSaveRec.setDuration( duration ); + } else if ( duration == 0 ) { + mSaveRec.setEndDate( endDate ); + } + + mSaveRec.setExDates( mExceptions->dates() ); +} -KOEditorRecurrenceDialog::KOEditorRecurrenceDialog(TQWidget * parent) : - KDialogBase( parent, 0, false, i18n("Recurrence"), Ok ) +void KOEditorRecurrence::restoreValues() +{ + TQBitArray rDays( 7 ); + int day = 0; + int count = 0; + int month = 0; + + if ( mSaveRec.startDateTime().isValid() && mSaveRec.endDateTime().isValid() ) { + setDefaults( mSaveRec.startDateTime(), mSaveRec.endDateTime(), mSaveRec.doesFloat() ); + } + + int recurrenceType; + switch ( mSaveRec.recurrenceType() ) { + case Recurrence::rNone: + recurrenceType = RecurrenceChooser::Weekly; + break; + + case Recurrence::rDaily: + recurrenceType = RecurrenceChooser::Daily; + mDaily->setFrequency( mSaveRec.frequency() ); + break; + + case Recurrence::rWeekly: + recurrenceType = RecurrenceChooser::Weekly; + + mWeekly->setFrequency( mSaveRec.frequency() ); + mWeekly->setDays( mSaveRec.days() ); + break; + + case Recurrence::rMonthlyPos: + { + // TODO: we only handle one possibility in the list right now, + // so I have hardcoded calls with first(). If we make the GUI + // more extended, this can be changed. + recurrenceType = RecurrenceChooser::Monthly; + + TQValueList<RecurrenceRule::WDayPos> rmp = mSaveRec.monthPositions(); + if ( !rmp.isEmpty() ) { + mMonthly->setByPos( rmp.first().pos(), rmp.first().day() ); + } + mMonthly->setFrequency( mSaveRec.frequency() ); + break; + } + + case Recurrence::rMonthlyDay: + { + recurrenceType = RecurrenceChooser::Monthly; + + TQValueList<int> rmd = mSaveRec.monthDays(); + // check if we have any setting for which day (vcs import is broken and + // does not set any day, thus we need to check) + if ( !rmd.isEmpty() ) { + day = rmd.first(); + } + if ( day > 0 ) { + mMonthly->setByDay( day ); + mMonthly->setFrequency( mSaveRec.frequency() ); + } + break; + } + + case Recurrence::rYearlyMonth: + { + recurrenceType = RecurrenceChooser::Yearly; + + TQValueList<int> rmd = mSaveRec.yearDates(); + if ( !rmd.isEmpty() ) { + day = rmd.first(); + } + rmd = mSaveRec.yearMonths(); + if ( !rmd.isEmpty() ) { + month = rmd.first(); + } + if ( day > 0 && month > 0 ) { + mYearly->setByMonth( day, month ); + mYearly->setFrequency( mSaveRec.frequency() ); + } + break; + } + + case Recurrence::rYearlyPos: + { + recurrenceType = RecurrenceChooser::Yearly; + + TQValueList<int> months = mSaveRec.yearMonths(); + if ( !months.isEmpty() ) { + month = months.first(); + } + TQValueList<RecurrenceRule::WDayPos> pos = mSaveRec.yearPositions(); + if ( !pos.isEmpty() ) { + count = pos.first().pos(); + day = pos.first().day(); + } + if ( count > 0 && day > 0 && month > 0 ) { + mYearly->setByPos( count, day, month ); + mYearly->setFrequency( mSaveRec.frequency() ); + } + break; + } + + case Recurrence::rYearlyDay: + { + recurrenceType = RecurrenceChooser::Yearly; + + TQValueList<int> days = mSaveRec.yearDays(); + if ( !days.isEmpty() ) { + day = days.first(); + } + if ( day > 0 ) { + mYearly->setByDay( day ); + mYearly->setFrequency( mSaveRec.frequency() ); + } + break; + } + default: + break; + } + + mRecurrenceChooser->setType( recurrenceType ); + showCurrentRule( recurrenceType ); + + if ( mSaveRec.startDateTime().isValid() ) { + mRecurrenceRange->setDateTimes( mSaveRec.startDateTime() ); + } + + mRecurrenceRange->setDuration( mSaveRec.duration() ); + if ( mSaveRec.duration() == 0 && mSaveRec.endDate().isValid() ) { + mRecurrenceRange->setEndDate( mSaveRec.endDate() ); + } + + mExceptions->setDates( mSaveRec.exDates() ); +} + +KOEditorRecurrenceDialog::KOEditorRecurrenceDialog(TQWidget * parent) + : KDialogBase( parent, 0, false, i18n("Recurrence"), Ok|Cancel ), mRecurEnabled( false ) { mRecurrence = new KOEditorRecurrence( this ); setMainWidget( mRecurrence ); } + +void KOEditorRecurrenceDialog::slotOk() +{ + mRecurEnabled = mRecurrence->doesRecur(); + mRecurrence->saveValues(); + emit okClicked(); // tell the incidence editor to update the recurrenceString + accept(); +} + +void KOEditorRecurrenceDialog::slotCancel() +{ + mRecurrence->setRecurrenceEnabled( mRecurEnabled ); + mRecurrence->restoreValues(); + reject(); +} diff --git a/korganizer/koeditorrecurrence.h b/korganizer/koeditorrecurrence.h index 0ce9c6dda..05074cdd9 100644 --- a/korganizer/koeditorrecurrence.h +++ b/korganizer/koeditorrecurrence.h @@ -297,6 +297,9 @@ class KOEditorRecurrence : public QWidget bool doesRecur(); + void saveValues(); + void restoreValues(); + public slots: void setRecurrenceEnabled( bool ); void setDateTimes( const TQDateTime &start, const TQDateTime &end ); @@ -311,6 +314,7 @@ class KOEditorRecurrence : public QWidget void showRecurrenceRangeDialog(); private: + Recurrence mSaveRec; TQCheckBox *mEnabledCheck; TQGroupBox *mTimeGroupBox; @@ -345,8 +349,13 @@ class KOEditorRecurrenceDialog : public KDialogBase KOEditorRecurrenceDialog( TQWidget *parent ); KOEditorRecurrence* editor() const { return mRecurrence; } + protected slots: + void slotOk(); + void slotCancel(); + private: KOEditorRecurrence *mRecurrence; + bool mRecurEnabled; }; #endif diff --git a/korganizer/koeventeditor.cpp b/korganizer/koeventeditor.cpp index 5cc7041ee..8a8340fc0 100644 --- a/korganizer/koeventeditor.cpp +++ b/korganizer/koeventeditor.cpp @@ -41,7 +41,6 @@ #include "koprefs.h" #include "koeditorgeneralevent.h" -#include "koeditoralarms.h" #include "koeditorrecurrence.h" #include "koeditordetails.h" #include "koeditorfreebusy.h" @@ -66,7 +65,6 @@ KOEventEditor::~KOEventEditor() void KOEventEditor::init() { setupGeneral(); -// setupAlarmsTab(); setupRecurrence(); setupFreeBusy(); setupDesignerTabs( "event" ); @@ -111,7 +109,9 @@ void KOEventEditor::reload() { kdDebug(5850) << "KOEventEditor::reload()" << endl; - if ( mEvent ) readEvent( mEvent, mCalendar ); + if ( mEvent ) { + readEvent( mEvent, mCalendar, TQDate() ); + } } void KOEventEditor::setupGeneral() @@ -129,9 +129,6 @@ void KOEventEditor::setupGeneral() mGeneral->initHeader( topFrame, topLayout ); mGeneral->initTime(topFrame,topLayout); -// TQBoxLayout *alarmLineLayout = new TQHBoxLayout(topLayout); - mGeneral->initAlarm(topFrame,topLayout); - mGeneral->enableAlarm( false ); topLayout->addStretch( 1 ); @@ -166,27 +163,15 @@ void KOEventEditor::setupGeneral() mGeneral->finishSetup(); } -void KOEventEditor::modified (int /*modification*/) +void KOEventEditor::modified() { - // Play dump, just reload the event. This dialog has become so complicated + // Play dumb, just reload the event. This dialog has become so complicated // that there is no point in trying to be smart here... reload(); } void KOEventEditor::setupRecurrence() { -#if 0 - TQFrame *topFrame = addPage( i18n("Rec&urrence") ); - - TQWhatsThis::add( topFrame, - i18n("The Recurrence tab allows you to set options on " - "how often this event recurs.") ); - - TQBoxLayout *topLayout = new TQVBoxLayout( topFrame ); - - mRecurrence = new KOEditorRecurrence( topFrame ); - topLayout->addWidget( mRecurrence ); -#endif mRecurrenceDialog = new KOEditorRecurrenceDialog( this ); mRecurrenceDialog->hide(); mRecurrence = mRecurrenceDialog->editor(); @@ -205,7 +190,9 @@ void KOEventEditor::setupFreeBusy() topLayout->addWidget( mFreeBusy ); } -void KOEventEditor::editIncidence( Incidence *incidence, Calendar *calendar ) +void KOEventEditor::editIncidence( Incidence *incidence, + const TQDate &date, + Calendar *calendar ) { Event*event = dynamic_cast<Event*>(incidence); if ( event ) { @@ -213,7 +200,9 @@ void KOEventEditor::editIncidence( Incidence *incidence, Calendar *calendar ) mEvent = event; mCalendar = calendar; - readEvent( mEvent, mCalendar ); + + const TQDate &dt = mRecurIncidence && date.isValid() ? date : incidence->dtStart().date(); + readEvent( mEvent, mCalendar, dt ); } setCaption( i18n("Edit Event") ); @@ -263,9 +252,12 @@ void KOEventEditor::loadDefaults() bool KOEventEditor::processInput() { - kdDebug(5850) << "KOEventEditor::processInput()" << endl; + kdDebug(5850) << "KOEventEditor::processInput(); event is " << mEvent << endl; - if ( !validateInput() || !mChanger ) return false; + if ( !validateInput() || !mChanger ) { + kdDebug(5850) << " mChanger is " << mChanger << endl; + return false; + } TQGuardedPtr<KOEditorFreeBusy> freeBusy( mFreeBusy ); @@ -280,11 +272,12 @@ bool KOEventEditor::processInput() if( *event == *mEvent ) { // Don't do anything - kdDebug(5850) << "Event not changed\n"; - if ( mIsCounter ) + kdDebug(5850) << "Event not changed" << endl; + if ( mIsCounter ) { KMessageBox::information( this, i18n("You didn't change the event, thus no counter proposal has been sent to the organizer."), i18n("No changes") ); + } } else { - kdDebug(5850) << "Event changed\n"; + kdDebug(5850) << "Event changed" << endl; //IncidenceChanger::assignIncidence( mEvent, event ); writeEvent( mEvent ); if ( mIsCounter ) { @@ -293,9 +286,17 @@ bool KOEventEditor::processInput() Event *event = mEvent->clone(); event->clearAttendees(); event->setSummary( i18n("My counter proposal for: %1").arg( mEvent->summary() ) ); - mChanger->addIncidence( event ); + mChanger->addIncidence( event, mResource, mSubResource, this ); } else { - mChanger->changeIncidence( oldEvent, mEvent ); + if ( mRecurIncidence && mRecurIncidenceAfterDissoc ) { + mChanger->addIncidence( mEvent, mResource, mSubResource, this ); + + mChanger->changeIncidence( mRecurIncidence, mRecurIncidenceAfterDissoc, + KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE, this ); + + } else { + mChanger->changeIncidence( oldEvent, mEvent, KOGlobals::NOTHING_MODIFIED, this ); + } } } delete event; @@ -307,14 +308,16 @@ bool KOEventEditor::processInput() KOPrefs::instance()->email() ) ); writeEvent( mEvent ); // NOTE: triggered by addIncidence, the kolab resource might open a non-modal dialog (parent is not available in the resource) to select a resource folder. Thus the user can close this dialog before addIncidence() returns. - if ( !mChanger->addIncidence( mEvent, this ) ) { + if ( !mChanger->addIncidence( mEvent, mResource, mSubResource, this ) ) { delete mEvent; mEvent = 0; return false; } } // if "this" was deleted, freeBusy is 0 (being a guardedptr) - if ( freeBusy ) freeBusy->cancelReload(); + if ( freeBusy ) { + freeBusy->cancelReload(); + } return true; } @@ -324,6 +327,11 @@ void KOEventEditor::processCancel() kdDebug(5850) << "KOEventEditor::processCancel()" << endl; if ( mFreeBusy ) mFreeBusy->cancelReload(); + + if ( mRecurIncidence && mRecurIncidenceAfterDissoc ) { + *mRecurIncidenceAfterDissoc = *mRecurIncidence; + } + } void KOEventEditor::deleteEvent() @@ -336,11 +344,11 @@ void KOEventEditor::deleteEvent() reject(); } -void KOEventEditor::readEvent( Event *event, Calendar *calendar, bool tmpl ) +void KOEventEditor::readEvent( Event *event, Calendar *calendar, const TQDate &date, bool tmpl ) { - mGeneral->readEvent( event, calendar, tmpl ); + mGeneral->readEvent( event, calendar, date, tmpl ); mRecurrence->readIncidence( event ); -// mAlarms->readIncidence( event ); + if ( mFreeBusy ) { mFreeBusy->readEvent( event ); mFreeBusy->triggerReload(); @@ -368,11 +376,14 @@ void KOEventEditor::writeEvent( Event *event ) bool KOEventEditor::validateInput() { - if ( !mGeneral->validateInput() ) return false; - if ( !mDetails->validateInput() ) return false; - if ( !mRecurrence->validateInput() ) return false; - - return true; + if ( !mGeneral->validateInput() || + !mDetails->validateInput() || + !mRecurrence->validateInput() ) { + kdDebug(5850) << "ValidateInput returns false" << endl; + return false; + } else { + return true; + } } int KOEventEditor::msgItemDelete() @@ -390,7 +401,7 @@ void KOEventEditor::loadTemplate( /*const*/ CalendarLocal& cal ) i18n("Template does not contain a valid event.") ); } else { kdDebug(5850) << "KOEventEditor::slotLoadTemplate(): readTemplate" << endl; - readEvent( events.first(), 0, true ); + readEvent( events.first(), 0, TQDate(), true ); } } @@ -414,9 +425,9 @@ TQObject *KOEventEditor::typeAheadReceiver() const void KOEventEditor::updateRecurrenceSummary() { - Event *ev = new Event(); + Event *ev = new Event(); writeEvent( ev ); - mGeneral->updateRecurrenceSummary( IncidenceFormatter::recurrenceString( ev ) ); + mGeneral->updateRecurrenceSummary( ev ); delete ev; } diff --git a/korganizer/koeventeditor.h b/korganizer/koeventeditor.h index ba0974793..dbcec875f 100644 --- a/korganizer/koeventeditor.h +++ b/korganizer/koeventeditor.h @@ -57,7 +57,7 @@ class KOEventEditor : public KOIncidenceEditor void init(); /** This event has been modified externally */ - void modified (int change=0); + void modified(); void reload(); /** @@ -74,7 +74,7 @@ class KOEventEditor : public KOIncidenceEditor /** Edit an existing event. */ - void editIncidence( Incidence *incidence, Calendar *calendar ); + void editIncidence( Incidence *incidence, const TQDate &date, Calendar *calendar ); /** Set widgets to the given date/time values @@ -85,7 +85,7 @@ class KOEventEditor : public KOIncidenceEditor Read event object and setup widgets accordingly. If tmpl is true, the event is read as template, i.e. the time and date information isn't set. */ - void readEvent( Event *event, Calendar *calendar, bool tmpl = false ); + void readEvent( Event *event, Calendar *calendar, const TQDate &date, bool tmpl = false ); /** Write event settings to event object */ diff --git a/korganizer/koeventpopupmenu.cpp b/korganizer/koeventpopupmenu.cpp index 75c96d205..b0326ee52 100644 --- a/korganizer/koeventpopupmenu.cpp +++ b/korganizer/koeventpopupmenu.cpp @@ -45,6 +45,7 @@ KOEventPopupMenu::KOEventPopupMenu() { + mCalendar = 0; mCurrentIncidence = 0; mCurrentDate = TQDate(); mHasAdditionalItems = false; @@ -89,8 +90,9 @@ KOEventPopupMenu::KOEventPopupMenu() this, TQT_SLOT(forward()) ); } -void KOEventPopupMenu::showIncidencePopup( Incidence *incidence, const TQDate &qd ) +void KOEventPopupMenu::showIncidencePopup( Calendar *cal, Incidence *incidence, const TQDate &qd ) { + mCalendar = cal; mCurrentIncidence = incidence; mCurrentDate = qd; @@ -123,19 +125,23 @@ void KOEventPopupMenu::addAdditionalItem(const TQIconSet &icon,const TQString &t void KOEventPopupMenu::popupShow() { - if (mCurrentIncidence) emit showIncidenceSignal(mCurrentIncidence); + if ( mCurrentIncidence ) { + emit showIncidenceSignal( mCurrentIncidence, mCurrentDate ); + } } void KOEventPopupMenu::popupEdit() { - if (mCurrentIncidence) emit editIncidenceSignal(mCurrentIncidence); + if ( mCurrentIncidence ) { + emit editIncidenceSignal( mCurrentIncidence, mCurrentDate ); + } } void KOEventPopupMenu::print() { #ifndef KORG_NOPRINTER KOCoreHelper helper; - CalPrinter printer( this, 0, &helper ); + CalPrinter printer( this, mCalendar, &helper ); connect( this, TQT_SIGNAL(configChanged()), &printer, TQT_SLOT(updateConfig()) ); Incidence::List selectedIncidences; diff --git a/korganizer/koeventpopupmenu.h b/korganizer/koeventpopupmenu.h index 8d4f2df26..96911b8cb 100644 --- a/korganizer/koeventpopupmenu.h +++ b/korganizer/koeventpopupmenu.h @@ -31,6 +31,7 @@ #include <tqdatetime.h> namespace KCal { +class Calendar; class Incidence; } using namespace KCal; @@ -46,7 +47,7 @@ class KOEventPopupMenu : public TQPopupMenu { public slots: - void showIncidencePopup( Incidence *, const TQDate & ); + void showIncidencePopup( Calendar *, Incidence *, const TQDate & ); protected slots: void popupShow(); @@ -62,17 +63,19 @@ class KOEventPopupMenu : public TQPopupMenu { void forward(); signals: - void editIncidenceSignal(Incidence *); - void showIncidenceSignal(Incidence *); - void deleteIncidenceSignal(Incidence *); - void cutIncidenceSignal(Incidence *); - void copyIncidenceSignal(Incidence *); + void configChanged(); + void editIncidenceSignal( Incidence *, const TQDate & ); + void showIncidenceSignal( Incidence *, const TQDate & ); + void deleteIncidenceSignal( Incidence * ); + void cutIncidenceSignal( Incidence * ); + void copyIncidenceSignal( Incidence * ); void pasteIncidenceSignal(); - void toggleAlarmSignal(Incidence *); + void toggleAlarmSignal( Incidence * ); void dissociateOccurrenceSignal( Incidence *, const TQDate & ); void dissociateFutureOccurrenceSignal( Incidence *, const TQDate & ); private: + Calendar *mCalendar; Incidence *mCurrentIncidence; TQDate mCurrentDate; diff --git a/korganizer/koeventview.cpp b/korganizer/koeventview.cpp index 17708953b..9e01ea4e0 100644 --- a/korganizer/koeventview.cpp +++ b/korganizer/koeventview.cpp @@ -60,25 +60,25 @@ KOEventView::~KOEventView() KOEventPopupMenu *KOEventView::eventPopup() { KOEventPopupMenu *eventPopup = new KOEventPopupMenu; - - connect(eventPopup,TQT_SIGNAL(editIncidenceSignal(Incidence *)), - TQT_SIGNAL(editIncidenceSignal(Incidence *))); - connect(eventPopup,TQT_SIGNAL(showIncidenceSignal(Incidence *)), - TQT_SIGNAL(showIncidenceSignal(Incidence *))); - connect(eventPopup,TQT_SIGNAL(deleteIncidenceSignal(Incidence *)), - TQT_SIGNAL(deleteIncidenceSignal(Incidence *))); - connect(eventPopup,TQT_SIGNAL(cutIncidenceSignal(Incidence *)), - TQT_SIGNAL(cutIncidenceSignal(Incidence *))); - connect(eventPopup,TQT_SIGNAL(copyIncidenceSignal(Incidence *)), - TQT_SIGNAL(copyIncidenceSignal(Incidence *))); - connect(eventPopup,TQT_SIGNAL(pasteIncidenceSignal()), - TQT_SIGNAL(pasteIncidenceSignal())); - connect(eventPopup,TQT_SIGNAL(toggleAlarmSignal(Incidence *)), - TQT_SIGNAL(toggleAlarmSignal(Incidence*))); - connect(eventPopup,TQT_SIGNAL(dissociateOccurrenceSignal( Incidence *, const TQDate & )), - TQT_SIGNAL(dissociateOccurrenceSignal( Incidence *, const TQDate & ))); - connect(eventPopup,TQT_SIGNAL(dissociateFutureOccurrenceSignal( Incidence *, const TQDate & )), - TQT_SIGNAL(dissociateFutureOccurrenceSignal( Incidence *, const TQDate & ))); + + connect( eventPopup, TQT_SIGNAL(editIncidenceSignal(Incidence *,const TQDate &)), + TQT_SIGNAL(editIncidenceSignal(Incidence *,const TQDate &)) ); + connect( eventPopup, TQT_SIGNAL(showIncidenceSignal(Incidence *,const TQDate &)), + TQT_SIGNAL(showIncidenceSignal(Incidence *,const TQDate &)) ); + connect( eventPopup, TQT_SIGNAL(deleteIncidenceSignal(Incidence *)), + TQT_SIGNAL(deleteIncidenceSignal(Incidence *)) ); + connect( eventPopup, TQT_SIGNAL(cutIncidenceSignal(Incidence *)), + TQT_SIGNAL(cutIncidenceSignal(Incidence *)) ); + connect( eventPopup, TQT_SIGNAL(copyIncidenceSignal(Incidence *)), + TQT_SIGNAL(copyIncidenceSignal(Incidence *)) ); + connect( eventPopup, TQT_SIGNAL(pasteIncidenceSignal()), + TQT_SIGNAL(pasteIncidenceSignal()) ); + connect( eventPopup, TQT_SIGNAL(toggleAlarmSignal(Incidence *)), + TQT_SIGNAL(toggleAlarmSignal(Incidence*)) ); + connect( eventPopup, TQT_SIGNAL(dissociateOccurrenceSignal(Incidence *,const TQDate &)), + TQT_SIGNAL(dissociateOccurrenceSignal(Incidence *,const TQDate &)) ); + connect( eventPopup, TQT_SIGNAL(dissociateFutureOccurrenceSignal(Incidence *,const TQDate &)), + TQT_SIGNAL(dissociateFutureOccurrenceSignal(Incidence *,const TQDate &)) ); return eventPopup; } @@ -102,14 +102,14 @@ TQPopupMenu *KOEventView::newEventPopup() void KOEventView::popupShow() { - emit showIncidenceSignal(mCurrentIncidence); + emit showIncidenceSignal(mCurrentIncidence, TQDate() ); } //--------------------------------------------------------------------------- void KOEventView::popupEdit() { - emit editIncidenceSignal(mCurrentIncidence); + emit editIncidenceSignal( mCurrentIncidence, TQDate() ); } //--------------------------------------------------------------------------- @@ -137,14 +137,16 @@ void KOEventView::popupCopy() void KOEventView::showNewEventPopup() { - TQPopupMenu *popup = newEventPopup(); - if ( !popup ) { - kdError() << "KOEventView::showNewEventPopup(): popup creation failed" - << endl; - return; + if ( !readOnly() ) { + TQPopupMenu *popup = newEventPopup(); + if ( !popup ) { + kdError() << "KOEventView::showNewEventPopup(): popup creation failed" + << endl; + return; + } + + popup->popup( TQCursor::pos() ); } - - popup->popup( TQCursor::pos() ); } //--------------------------------------------------------------------------- @@ -157,10 +159,11 @@ void KOEventView::defaultAction( Incidence *incidence ) kdDebug(5850) << " type: " << incidence->type() << endl; - if ( incidence->isReadOnly() ) - emit showIncidenceSignal(incidence); - else - emit editIncidenceSignal(incidence); + if ( incidence->isReadOnly() ) { + emit showIncidenceSignal( incidence, TQDate() ); + } else { + emit editIncidenceSignal( incidence, TQDate() ); + } } //--------------------------------------------------------------------------- diff --git a/korganizer/koeventview.h b/korganizer/koeventview.h index c33348813..69f6377f9 100644 --- a/korganizer/koeventview.h +++ b/korganizer/koeventview.h @@ -90,6 +90,8 @@ class KOEventView : public KOrg::BaseView /** This view is an view for displaying events. */ bool isEventView() { return true; } + bool supportsDateNavigation() const { return true; } + public slots: /** @@ -126,6 +128,7 @@ class KOEventView : public KOrg::BaseView protected: Incidence *mCurrentIncidence; // Incidence selected e.g. for a context menu + }; #endif diff --git a/korganizer/koeventviewer.cpp b/korganizer/koeventviewer.cpp index 47ac5b7a4..83534d6aa 100644 --- a/korganizer/koeventviewer.cpp +++ b/korganizer/koeventviewer.cpp @@ -23,24 +23,62 @@ */ #include "koeventviewer.h" - +#include "koglobals.h" #include "urihandler.h" +#include <libkcal/attachmenthandler.h> +#include <libkcal/calendar.h> #include <libkcal/incidence.h> #include <libkcal/incidenceformatter.h> + #include <kdebug.h> -#include <koglobals.h> +#include <klocale.h> +#include <kpopupmenu.h> + +#include <tqcursor.h> +#include <tqregexp.h> +#include <tqtooltip.h> -KOEventViewer::KOEventViewer( TQWidget *parent, const char *name ) - : TQTextBrowser( parent, name ), mDefaultText("") +KOEventViewer::KOEventViewer( Calendar *calendar, TQWidget *parent, const char *name ) + : TQTextBrowser( parent, name ), mCalendar( calendar ), mDefaultText("") { mIncidence = 0; + connect( this, TQT_SIGNAL(highlighted(const TQString &)), TQT_SLOT(message(const TQString &)) ); } KOEventViewer::~KOEventViewer() { } +void KOEventViewer::message( const TQString &link ) +{ + mAttachLink = TQString(); + if ( link.isEmpty() ) { + TQToolTip::remove( this ); + return; + } + + TQString ttStr; + if ( link.startsWith( "kmail:" ) ) { + ttStr = i18n( "Open the message in KMail" ); + } else if ( link.startsWith( "mailto:" ) ) { + ttStr = i18n( "Send an email message to %1" ).arg( link.mid( 7 ) ); + } else if ( link.startsWith( "uid:" ) ) { + ttStr = i18n( "Lookup the contact in KAddressbook" ); + } else if ( link.startsWith( "ATTACH:" ) ) { + TQString tmp = link; + tmp.remove( TQRegExp( "^ATTACH://" ) ); + TQString uid = tmp.section( ':', 0, 0 ); + TQString name = tmp.section( ':', -1, -1 ); + ttStr = i18n( "View attachment \"%1\"" ).arg( name ); + mAttachLink = link; + } else { // no special URI, let KDE handle it + ttStr = i18n( "Launch a viewer on the link" ); + } + + TQToolTip::add( this, ttStr ); +} + void KOEventViewer::readSettings( KConfig * config ) { if ( config ) { @@ -50,7 +88,7 @@ void KOEventViewer::readSettings( KConfig * config ) config->setGroup( TQString("EventViewer-%1").arg( name() ) ); int zoomFactor = config->readNumEntry("ZoomFactor", pointSize() ); zoomTo( zoomFactor/2 ); - kdDebug(5850) << " KOEventViewer: restoring the pointSize: "<< pointSize() + kdDebug(5850) << " KOEventViewer: restoring the pointSize: "<< pointSize() << ", zoomFactor: " << zoomFactor << endl; #endif } @@ -67,20 +105,25 @@ void KOEventViewer::writeSettings( KConfig * config ) void KOEventViewer::setSource( const TQString &n ) { - UriHandler::process( n ); + UriHandler::process( parentWidget(), n ); } -bool KOEventViewer::appendIncidence( Incidence *incidence ) +bool KOEventViewer::appendIncidence( Incidence *incidence, const TQDate &date ) { - addText( IncidenceFormatter::extensiveDisplayString( incidence ) ); + addText( IncidenceFormatter::extensiveDisplayStr( mCalendar, incidence, date ) ); return true; } -void KOEventViewer::setIncidence( Incidence *incidence ) +void KOEventViewer::setCalendar( Calendar *calendar ) +{ + mCalendar = calendar; +} + +void KOEventViewer::setIncidence( Incidence *incidence, const TQDate &date ) { clearEvents(); if( incidence ) { - appendIncidence( incidence ); + appendIncidence( incidence, date ); mIncidence = incidence; } else { clearEvents( true ); @@ -105,20 +148,43 @@ void KOEventViewer::setDefaultText( const TQString &text ) mDefaultText = text; } -void KOEventViewer::changeIncidenceDisplay( Incidence *incidence, int action ) +void KOEventViewer::changeIncidenceDisplay( Incidence *incidence, const TQDate &date, int action ) { if ( mIncidence && ( incidence->uid() == mIncidence->uid() ) ) { - switch (action ) { - case KOGlobals::INCIDENCEEDITED:{ - setIncidence( incidence ); - break; - } - case KOGlobals::INCIDENCEDELETED: { - setIncidence( 0 ); - break; - } + switch ( action ) { + case KOGlobals::INCIDENCEEDITED: + setIncidence( incidence, date ); + break; + case KOGlobals::INCIDENCEDELETED: + setIncidence( 0, date ); + break; } } } +void KOEventViewer::contentsContextMenuEvent( TQContextMenuEvent *e ) +{ + TQString name = UriHandler::attachmentNameFromUri( mAttachLink ); + TQString uid = UriHandler::uidFromUri( mAttachLink ); + if ( name.isEmpty() || uid.isEmpty() ) { + TQTextBrowser::contentsContextMenuEvent( e ); + return; + } + + KPopupMenu *menu = new KPopupMenu(); + menu->insertItem( i18n( "Open Attachment" ), 0 ); + menu->insertItem( i18n( "Save Attachment As..." ), 1 ); + + switch( menu->exec( TQCursor::pos(), 0 ) ) { + case 0: // open + AttachmentHandler::view( parentWidget(), name, uid ); + break; + case 1: // save as + AttachmentHandler::saveAs( parentWidget(), name, uid ); + break; + default: + break; + } +} + #include "koeventviewer.moc" diff --git a/korganizer/koeventviewer.h b/korganizer/koeventviewer.h index 80b1ef772..c4022d026 100644 --- a/korganizer/koeventviewer.h +++ b/korganizer/koeventviewer.h @@ -24,15 +24,13 @@ #ifndef KOEVENTVIEWER_H #define KOEVENTVIEWER_H -#include <tqtextbrowser.h> #include <kdepimmacros.h> - #include <kconfig.h> +#include <tqtextbrowser.h> + namespace KCal { -class Incidence; -class Todo; -class Event; -class Journal; + class Calendar; + class Incidence; } using namespace KCal; @@ -41,18 +39,23 @@ using namespace KCal; */ class KDE_EXPORT KOEventViewer : public QTextBrowser { - Q_OBJECT + Q_OBJECT public: - KOEventViewer( TQWidget *parent = 0, const char *name = 0 ); + explicit KOEventViewer( Calendar *calendar, TQWidget *parent = 0, const char *name = 0 ); virtual ~KOEventViewer(); /** Reimplemented from TQTextBrowser to handle links. */ void setSource( const TQString & ); - - virtual bool appendIncidence( Incidence * ); - + + virtual bool appendIncidence( Incidence *incidence, const TQDate &date ); + + /** + Set the Calendar associated with this viewer. + */ + void setCalendar ( Calendar *calendar ); + /** Clear viewer. If \a now is set to true delete view immediately. If set to false delete it with next call to appendIncidence(). @@ -61,30 +64,35 @@ class KDE_EXPORT KOEventViewer : public QTextBrowser /** Add given text to currently shown content. - */ - + */ + void addText( const TQString &text ); - + /** - Set the default text that is showed when + Set the default text that is showed when there aren't a incidence to show */ void setDefaultText( const TQString &text ); - - void readSettings( KConfig *config); - void writeSettings ( KConfig *config); - + + void readSettings( KConfig *config ); + void writeSettings ( KConfig *config ); + public slots: /** Show given incidence in viewer. Clear all previously shown incidences. */ - virtual void setIncidence( Incidence * ); - void changeIncidenceDisplay( Incidence *incidence, int action ); + void setIncidence( Incidence *incidence, const TQDate &date ); + void changeIncidenceDisplay( Incidence *incidence, const TQDate &date, int action ); + void message( const TQString &link ); + void contentsContextMenuEvent( TQContextMenuEvent * ); + private: + Calendar *mCalendar; Incidence *mIncidence; TQTextBrowser *mEventTextView; TQString mDefaultText; TQString mText; + TQString mAttachLink; }; #endif diff --git a/korganizer/koeventviewerdialog.cpp b/korganizer/koeventviewerdialog.cpp index a51e5bccb..d88aa31c2 100644 --- a/korganizer/koeventviewerdialog.cpp +++ b/korganizer/koeventviewerdialog.cpp @@ -28,21 +28,20 @@ #include <klocale.h> -KOEventViewerDialog::KOEventViewerDialog( TQWidget *parent, const char *name, - bool compact ) +KOEventViewerDialog::KOEventViewerDialog( Calendar *calendar, TQWidget *parent, + const char *name, bool compact ) : KDialogBase( parent, name, false, i18n("Event Viewer"), Ok, Ok, false, i18n("Edit") ) { - mEventViewer = new KOEventViewer( this ); + mEventViewer = new KOEventViewer( calendar, this ); setMainWidget( mEventViewer ); - // FIXME: Set a sensible size (based on the content?). if ( compact ) { setFixedSize( 240,284 ); move( 0, 15 ); } else { - setMinimumSize( 300, 200 ); - resize( 320, 300 ); + setMinimumSize( 500, 500 ); + resize( 520, 500 ); } connect( this, TQT_SIGNAL(finished()), this, TQT_SLOT(delayedDestruct()) ); } @@ -51,9 +50,14 @@ KOEventViewerDialog::~KOEventViewerDialog() { } +void KOEventViewerDialog::setCalendar( Calendar *calendar ) +{ + mEventViewer->setCalendar( calendar ); +} + void KOEventViewerDialog::addText( const TQString &text ) { - mEventViewer->addText(text); + mEventViewer->addText( text ); } #include "koeventviewerdialog.moc" diff --git a/korganizer/koeventviewerdialog.h b/korganizer/koeventviewerdialog.h index e14c6bafd..dc0ceb7b7 100644 --- a/korganizer/koeventviewerdialog.h +++ b/korganizer/koeventviewerdialog.h @@ -42,13 +42,20 @@ class KDE_EXPORT KOEventViewerDialog : public KDialogBase { Q_OBJECT public: - KOEventViewerDialog( TQWidget *parent = 0, const char *name = 0, - bool compact = false ); + explicit KOEventViewerDialog( Calendar *calendar, TQWidget *parent = 0, + const char *name = 0, bool compact = false ); virtual ~KOEventViewerDialog(); - void setIncidence( Incidence *incidence ) { mEventViewer->setIncidence( incidence ); } - void appendIncidence( Incidence *incidence ) { mEventViewer->appendIncidence( incidence ); } + void setIncidence( Incidence *incidence, const TQDate &date ) + { + mEventViewer->setIncidence( incidence, date ); + } + void appendIncidence( Incidence *incidence, const TQDate &date ) + { + mEventViewer->appendIncidence( incidence, date ); + } + void setCalendar( Calendar *calendar ); void addText( const TQString &text ); private: diff --git a/korganizer/koglobals.h b/korganizer/koglobals.h index 771588101..119eb6c1d 100644 --- a/korganizer/koglobals.h +++ b/korganizer/koglobals.h @@ -24,7 +24,9 @@ #define KORG_GLOBALS_H #include <kdepimmacros.h> +#include <tqwidget.h> +class TQDate; class TQPixmap; class TQIconSet; class KCalendarSystem; @@ -39,11 +41,40 @@ class KDE_EXPORT KOGlobals public: static KOGlobals *self(); - enum { INCIDENCEADDED, INCIDENCEEDITED, INCIDENCEDELETED }; - enum { PRIORITY_MODIFIED, COMPLETION_MODIFIED, CATEGORY_MODIFIED, - DATE_MODIFIED, RELATION_MODIFIED, ALARM_MODIFIED, - DESCRIPTION_MODIFIED, SUMMARY_MODIFIED, - COMPLETION_MODIFIED_WITH_RECURRENCE, UNKNOWN_MODIFIED }; + enum HowChanged { + INCIDENCEADDED, + INCIDENCEEDITED, + INCIDENCEDELETED, + NOCHANGE + }; + enum WhatChanged { + PRIORITY_MODIFIED, + COMPLETION_MODIFIED, + CATEGORY_MODIFIED, + DATE_MODIFIED, + RELATION_MODIFIED, + ALARM_MODIFIED, + DESCRIPTION_MODIFIED, + SUMMARY_MODIFIED, + COMPLETION_MODIFIED_WITH_RECURRENCE, + RECURRENCE_MODIFIED_ONE_ONLY, + RECURRENCE_MODIFIED_ALL_FUTURE, + UNKNOWN_MODIFIED, + NOTHING_MODIFIED + }; + + enum WhichOccurrences { + NONE, + ONLY_THIS_ONE, + ONLY_FUTURE, + ALL + }; + + enum OccurrenceAction { + CUT, + COPY, + EDIT + }; static void fitDialogToScreen( TQWidget *widget, bool force=false ); KConfig *config() const; diff --git a/korganizer/kogroupware.cpp b/korganizer/kogroupware.cpp index 7b017cc4d..0edcdc9c7 100644 --- a/korganizer/kogroupware.cpp +++ b/korganizer/kogroupware.cpp @@ -73,8 +73,8 @@ KOGroupware *KOGroupware::instance() } - KOGroupware::KOGroupware( CalendarView* view, KCal::CalendarResources* cal ) - : TQObject( 0, "kmgroupware_instance" ), mView( view ), mCalendar( cal ) +KOGroupware::KOGroupware( CalendarView* view, KCal::CalendarResources* cal ) + : TQObject( 0, "kmgroupware_instance" ), mView( view ), mCalendar( cal ), mDoNotNotify( false ) { // Set up the dir watch of the three incoming dirs KDirWatch* watcher = KDirWatch::self(); @@ -105,10 +105,8 @@ void KOGroupware::slotViewNewIncidenceChanger( IncidenceChangerBase* changer ) // Call slot perhapsUploadFB if an incidence was added, changed or removed connect( changer, TQT_SIGNAL( incidenceAdded( Incidence* ) ), mFreeBusyManager, TQT_SLOT( slotPerhapsUploadFB() ) ); - connect( changer, TQT_SIGNAL( incidenceChanged( Incidence*, Incidence*, int ) ), + connect( changer, TQT_SIGNAL( incidenceChanged( Incidence*, Incidence*, KOGlobals::WhatChanged ) ), mFreeBusyManager, TQT_SLOT( slotPerhapsUploadFB() ) ); - connect( changer, TQT_SIGNAL( incidenceChanged( Incidence*, Incidence* ) ), - mFreeBusyManager, TQT_SLOT( slotPerhapsUploadFB() ) ) ; connect( changer, TQT_SIGNAL( incidenceDeleted( Incidence * ) ), mFreeBusyManager, TQT_SLOT( slotPerhapsUploadFB() ) ); } @@ -179,6 +177,10 @@ void KOGroupware::incomingDirChanged( const TQString& path ) KCal::ScheduleMessage::Status status = message->status(); KCal::Incidence* incidence = dynamic_cast<KCal::Incidence*>( message->event() ); + if(!incidence) { + delete message; + return; + } KCal::MailScheduler scheduler( mCalendar ); if ( action.startsWith( "accepted" ) || action.startsWith( "tentative" ) || action.startsWith( "delegated" ) || action.startsWith( "counter" ) ) { @@ -200,10 +202,10 @@ void KOGroupware::incomingDirChanged( const TQString& path ) } } if ( KOPrefs::instance()->outlookCompatCounterProposals() || !action.startsWith( "counter" ) ) - scheduler.acceptTransaction( incidence, method, status ); + scheduler.acceptTransaction( incidence, method, status, receiver ); } else if ( action.startsWith( "cancel" ) ) // Delete the old incidence, if one is present - scheduler.acceptTransaction( incidence, KCal::Scheduler::Cancel, status ); + scheduler.acceptTransaction( incidence, KCal::Scheduler::Cancel, status, receiver ); else if ( action.startsWith( "reply" ) ) { if ( method != Scheduler::Counter ) { scheduler.acceptTransaction( incidence, method, status ); @@ -211,13 +213,13 @@ void KOGroupware::incomingDirChanged( const TQString& path ) // accept counter proposal scheduler.acceptCounterProposal( incidence ); // send update to all attendees - sendICalMessage( mView, Scheduler::Request, incidence ); + sendICalMessage( mView, Scheduler::Request, incidence, KOGlobals::INCIDENCEEDITED, false ); } } else kdError(5850) << "Unknown incoming action " << action << endl; if ( action.startsWith( "counter" ) ) { - mView->editIncidence( incidence, true ); + mView->editIncidence( incidence, TQDate(), true ); KOIncidenceEditor *tmp = mView->editorDialog( incidence ); tmp->selectInvitationCounterProposal( true ); } @@ -238,8 +240,9 @@ class KOInvitationFormatterHelper : public InvitationFormatterHelper */ bool KOGroupware::sendICalMessage( TQWidget* parent, KCal::Scheduler::Method method, - Incidence* incidence, bool isDeleting, - bool statusChanged ) + Incidence* incidence, + KOGlobals::HowChanged action, + bool attendeeStatusChanged ) { // If there are no attendees, don't bother if( incidence->attendees().isEmpty() ) @@ -267,16 +270,48 @@ bool KOGroupware::sendICalMessage( TQWidget* parent, * mail. */ if ( incidence->attendees().count() > 1 || incidence->attendees().first()->email() != incidence->organizer().email() ) { - TQString type; - if( incidence->type() == "Event") type = i18n("event"); - else if( incidence->type() == "Todo" ) type = i18n("task"); - else if( incidence->type() == "Journal" ) type = i18n("journal entry"); - else type = incidence->type(); - TQString txt = i18n( "This %1 includes other people. " - "Should email be sent out to the attendees?" ) - .arg( type ); - rc = KMessageBox::questionYesNoCancel( parent, txt, - i18n("Group Scheduling Email"), i18n("Send Email"), i18n("Do Not Send") ); + + TQString txt; + switch( action ) { + case KOGlobals::INCIDENCEEDITED: + txt = i18n( "You changed the invitation \"%1\".\n" + "Do you want to email the attendees an update message?" ). + arg( incidence->summary() ); + break; + case KOGlobals::INCIDENCEDELETED: + Q_ASSERT( incidence->type() == "Event" || incidence->type() == "Todo" ); + if ( incidence->type() == "Event" ) { + txt = i18n( "You removed the invitation \"%1\".\n" + "Do you want to email the attendees that the event is canceled?" ). + arg( incidence->summary() ); + } else if ( incidence->type() == "Todo" ) { + txt = i18n( "You removed the invitation \"%1\".\n" + "Do you want to email the attendees that the todo is canceled?" ). + arg( incidence->summary() ); + } + break; + case KOGlobals::INCIDENCEADDED: + if ( incidence->type() == "Event" ) { + txt = i18n( "The event \"%1\" includes other people.\n" + "Do you want to email the invitation to the attendees?" ). + arg( incidence->summary() ); + } else if ( incidence->type() == "Todo" ) { + txt = i18n( "The todo \"%1\" includes other people.\n" + "Do you want to email the invitation to the attendees?" ). + arg( incidence->summary() ); + } else { + txt = i18n( "This incidence includes other people. " + "Should an email be sent to the attendees?" ); + } + break; + default: + kdError() << "Unsupported HowChanged action" << int( action ) << endl; + break; + } + + rc = KMessageBox::questionYesNo( + parent, txt, i18n( "Group Scheduling Email" ), + KGuiItem( i18n( "Send Email" ) ), KGuiItem( i18n( "Do Not Send" ) ) ); } else { return true; } @@ -291,32 +326,49 @@ bool KOGroupware::sendICalMessage( TQWidget* parent, rc = KMessageBox::questionYesNo( parent, txt, TQString::null, i18n("Send Update"), i18n("Do Not Send") ); } else if( incidence->type() == "Event" ) { TQString txt; - if ( statusChanged && method == Scheduler::Request ) { - txt = i18n( "Your status as an attendee of this event " - "changed. Do you want to send a status update to the " - "organizer of this event?" ); + if ( attendeeStatusChanged && method == Scheduler::Request ) { + txt = i18n( "Your status as an attendee of this event changed. " + "Do you want to send a status update to the event organizer?" ); method = Scheduler::Reply; rc = KMessageBox::questionYesNo( parent, txt, TQString::null, i18n("Send Update"), i18n("Do Not Send") ); } else { - if( isDeleting ) - txt = i18n( "You are not the organizer of this event. " - "Deleting it will bring your calendar out of sync " - "with the organizers calendar. Do you really want " - "to delete it?" ); - else - txt = i18n( "You are not the organizer of this event. " - "Editing it will bring your calendar out of sync " - "with the organizers calendar. Do you really want " - "to edit it?" ); - rc = KMessageBox::warningYesNo( parent, txt ); - return ( rc == KMessageBox::Yes ); + if( action == KOGlobals::INCIDENCEDELETED ) { + const TQStringList myEmails = KOPrefs::instance()->allEmails(); + bool askConfirmation = false; + for ( TQStringList::ConstIterator it = myEmails.begin(); it != myEmails.end(); ++it ) { + TQString email = *it; + Attendee *me = incidence->attendeeByMail(email); + if (me && (me->status()==KCal::Attendee::Accepted || me->status()==KCal::Attendee::Delegated)) { + askConfirmation = true; + break; + } + } + + if ( !askConfirmation ) { + return true; + } + + txt = i18n( "You had previously accepted an invitation to this event. " + "Do you want to send an updated response to the organizer " + "declining the invitation?" ); + rc = KMessageBox::questionYesNo( + parent, txt, i18n( "Group Scheduling Email" ), + KGuiItem( i18n( "Send Update" ) ), KGuiItem( i18n( "Do Not Send" ) ) ); + setDoNotNotify( rc == KMessageBox::No ); + } else { + txt = i18n( "You are not the organizer of this event. Editing it will " + "bring your calendar out of sync with the organizer's calendar. " + "Do you really want to edit it?" ); + rc = KMessageBox::warningYesNo( parent, txt ); + return ( rc == KMessageBox::Yes ); + } } } else { kdWarning(5850) << "Groupware messages for Journals are not implemented yet!" << endl; return true; } - if( rc == KMessageBox::Yes ) { + if ( rc == KMessageBox::Yes ) { // We will be sending out a message here. Now make sure there is // some summary if( incidence->summary().isEmpty() ) @@ -327,10 +379,11 @@ bool KOGroupware::sendICalMessage( TQWidget* parent, scheduler.performTransaction( incidence, method ); return true; - } else if( rc == KMessageBox::No ) + } else if ( rc == KMessageBox::No ) { return true; - else + } else { return false; + } } void KOGroupware::sendCounterProposal(KCal::Calendar *calendar, KCal::Event * oldEvent, KCal::Event * newEvent) const @@ -341,7 +394,9 @@ void KOGroupware::sendCounterProposal(KCal::Calendar *calendar, KCal::Event * ol Incidence* tmp = oldEvent->clone(); tmp->setSummary( i18n("Counter proposal: %1").arg( newEvent->summary() ) ); tmp->setDescription( newEvent->description() ); - tmp->addComment( i18n("Proposed new meeting time: %1 - %2").arg( newEvent->dtStartStr(), newEvent->dtEndStr() ) ); + tmp->addComment( i18n("Proposed new meeting time: %1 - %2"). + arg( IncidenceFormatter::dateToString( newEvent->dtStart() ), + IncidenceFormatter::dateToString( newEvent->dtEnd() ) ) ); KCal::MailScheduler scheduler( calendar ); scheduler.performTransaction( tmp, Scheduler::Reply ); delete tmp; diff --git a/korganizer/kogroupware.h b/korganizer/kogroupware.h index 0af6a3c42..f6695de07 100644 --- a/korganizer/kogroupware.h +++ b/korganizer/kogroupware.h @@ -37,13 +37,16 @@ #ifndef KOGROUPWARE_H #define KOGROUPWARE_H +#include "koglobals.h" + #include <libkcal/calendarresources.h> #include <libkcal/icalformat.h> #include <libkcal/scheduler.h> -#include <tqstring.h> #include <kio/job.h> +#include <tqstring.h> + using namespace KCal; namespace KCal { @@ -72,9 +75,10 @@ class KOGroupware : public QObject Returns false if the user cancels the dialog, and true if the user presses Yes og or No. */ - bool sendICalMessage( TQWidget* parent, KCal::Scheduler::Method method, - Incidence* incidence, bool isDeleting = false, - bool statusChanged = false ); + bool sendICalMessage( TQWidget *parent, KCal::Scheduler::Method method, + Incidence* incidence, + KOGlobals::HowChanged action, + bool attendeeStatusChanged ); /** Send counter proposal message. @@ -83,12 +87,14 @@ class KOGroupware : public QObject */ void sendCounterProposal( KCal::Calendar* calendar, KCal::Event* oldEvent, KCal::Event *newEvent ) const; - // THIS IS THE ACTUAL KM/KO API - enum EventState { Accepted, ConditionallyAccepted, Declined, Request }; - // convert the TNEF attachment to a vCard or iCalendar part TQString msTNEFToVPart( const TQByteArray& tnef ); + // DoNotNotify is a flag indicating that the user does not want + // updates sent back to the organizer. + void setDoNotNotify( bool notify ) { mDoNotNotify = notify; } + bool doNotNotify() { return mDoNotNotify; } + private slots: /** Handle iCals given by KMail. */ void incomingDirChanged( const TQString& path ); @@ -106,6 +112,7 @@ class KOGroupware : public QObject CalendarView *mView; KCal::CalendarResources *mCalendar; static FreeBusyManager *mFreeBusyManager; + bool mDoNotNotify; }; #endif diff --git a/korganizer/kogroupwareprefspage.ui b/korganizer/kogroupwareprefspage.ui index d6f14f9ad..a4e558fbf 100644 --- a/korganizer/kogroupwareprefspage.ui +++ b/korganizer/kogroupwareprefspage.ui @@ -39,7 +39,7 @@ <cstring>TextLabel1</cstring> </property> <property name="text"> - <string>By publishing Free/Busy information, you allow others to take your calendar into account when inviting you for a meeting. Only the times you have already busy are published, not why they are busy.</string> + <string>By publishing Free/Busy information, you allow others to take your calendar into account when inviting you for a meeting. Only the times you have already busy are published, not why they are busy. For Kolab2 Server leave this disabled (the information is generated on the server).</string> </property> <property name="alignment"> <set>WordBreak|AlignVCenter</set> @@ -182,8 +182,7 @@ Note: If KOrganizer is acting as a KDE Kolab client, this is not required, as th </property> <property name="whatsThis" stdset="0"> <string>Enter the URL for the server on which your Free/Busy information shall be published here. -Ask the server administrator for this information. -Here is a Kolab2 server URL example: "webdavs://kolab2.com/freebusy/joe@kolab2.com.ifb"</string> +Ask the server administrator for this information.</string> </property> </widget> <widget class="QCheckBox" row="7" column="0" rowspan="1" colspan="2"> @@ -278,8 +277,7 @@ A Kolab2 server specificity: Registered your UID (Unique IDentifier). By default </property> <property name="whatsThis" stdset="0"> <string>Enter the URL for the server on which your Free/Busy information shall be published here. -Ask the server administrator for this information. -Here is a Kolab2 server URL example: "webdavs://kolab2.com/freebusy/joe@kolab2.com.ifb"</string> +Ask the server administrator for this information.</string> </property> </widget> </grid> @@ -385,9 +383,11 @@ Here is a Kolab2 server URL example: "webdavs://kolab2.com/freebusy/joe@kolab2.c <property name="whatsThis" stdset="0"> <string>Enter the URL for the server on which the Free/Busy information is published here. Ask the server administrator for this information. -Here is a Kolab2 server URL example: "webdavs://kolab2.com/freebusy/" +Here is a Kolab2 Server URL example: "https://kolab2.example.com/freebusy/" Here is a generic server example: "http://myserver.net/%u@%d/?internal.ics" -%u expands to the username, and %d expands to the domain name.</string> +%u expands to the username, and %d expands to the domain name. +Alternatively, you can specify a full path to the Free/Busy file, +For example: "https://kolab2.example.com/freebusy/user.xfb"</string> </property> </widget> <widget class="QLineEdit"> @@ -400,9 +400,11 @@ Here is a generic server example: "http://myserver.net/%u@%d/?internal.ics" <property name="whatsThis" stdset="0"> <string>Enter the URL for the server on which the Free/Busy information is published here. Ask the server administrator for this information. -Here is a Kolab2 server URL example: "webdavs://kolab2.com/freebusy/" +Here is a Kolab2 Server URL example: "https://kolab2.example.com/freebusy/" Here is a generic server example: "http://myserver.net/%u@%d/?internal.ics" -%u expands to the username, and %d expands to the domain name.</string> +%u expands to the username, and %d expands to the domain name. +Alternatively, you can specify a full path to the Free/Busy file, +For example: "https://kolab2.example.com/freebusy/user.xfb"</string> </property> </widget> </hbox> diff --git a/korganizer/kohelper.cpp b/korganizer/kohelper.cpp index 827279fe4..3b7bd8776 100644 --- a/korganizer/kohelper.cpp +++ b/korganizer/kohelper.cpp @@ -62,23 +62,3 @@ TQColor KOHelper::resourceColor( KCal::Calendar*calendar, KCal::Incidence*incide } return resourceColor; } - -TQString KOHelper::resourceLabel(KCal::Calendar * calendar, KCal::Incidence * incidence) -{ - KCal::CalendarResources *calendarResource = dynamic_cast<KCal::CalendarResources*>( calendar ); - if ( !calendarResource || ! incidence ) - return TQString(); - - KCal::ResourceCalendar *resourceCalendar = calendarResource->resource( incidence ); - if( resourceCalendar ) { - if ( !resourceCalendar->subresources().isEmpty() ) { - TQString subRes = resourceCalendar->subresourceIdentifier( incidence ); - if ( subRes.isEmpty() ) - return resourceCalendar->resourceName(); - return resourceCalendar->labelForSubresource( subRes ); - } - return resourceCalendar->resourceName(); - } - - return TQString(); -} diff --git a/korganizer/kohelper.h b/korganizer/kohelper.h index b7f61b796..07d91058b 100644 --- a/korganizer/kohelper.h +++ b/korganizer/kohelper.h @@ -42,12 +42,6 @@ class KDE_EXPORT KOHelper to a subresource, the color for the subresource is returned (if set). */ static TQColor resourceColor( KCal::Calendar*calendar, KCal::Incidence*incidence ); - - /** - Returns the resource label the given incidence belongs to. - */ - static TQString resourceLabel( KCal::Calendar *calendar, KCal::Incidence *incidence ); - }; #endif diff --git a/korganizer/koincidenceeditor.cpp b/korganizer/koincidenceeditor.cpp index 3eb4920f8..240497e19 100644 --- a/korganizer/koincidenceeditor.cpp +++ b/korganizer/koincidenceeditor.cpp @@ -45,6 +45,7 @@ #include <libkcal/calendarlocal.h> #include <libkcal/incidence.h> #include <libkcal/icalformat.h> +#include <libkcal/resourcecalendar.h> #include "koprefs.h" #include "koglobals.h" @@ -58,7 +59,8 @@ KOIncidenceEditor::KOIncidenceEditor( const TQString &caption, Calendar *calendar, TQWidget *parent ) : KDialogBase( Tabbed, caption, Ok | Apply | Cancel | Default, Ok, parent, 0, false, false ), - mAttendeeEditor( 0 ), mIsCounter( false ) + mAttendeeEditor( 0 ), mResource( 0 ), mIsCounter( false ), mIsCreateTask( false ), + mRecurIncidence( 0 ), mRecurIncidenceAfterDissoc( 0 ) { // Set this to be the group leader for all subdialogs - this means // modal subdialogs will only affect this dialog, not the other windows @@ -349,14 +351,14 @@ void KOIncidenceEditor::createEmbeddedURLPages( Incidence *i ) void KOIncidenceEditor::openURL( const KURL &url ) { TQString uri = url.url(); - UriHandler::process( uri ); + UriHandler::process( this, uri ); } void KOIncidenceEditor::addAttachments( const TQStringList &attachments, const TQStringList &mimeTypes, bool inlineAttachments ) { - emit signalAddAttachments( attachments, mimeTypes, inlineAttachments ); + emit signalAddAttachments( attachments, mimeTypes, inlineAttachments ); } void KOIncidenceEditor::addAttendees( const TQStringList &attendees ) @@ -365,7 +367,33 @@ void KOIncidenceEditor::addAttendees( const TQStringList &attendees ) for ( it = attendees.begin(); it != attendees.end(); ++it ) { TQString name, email; KABC::Addressee::parseEmailAddress( *it, name, email ); - mAttendeeEditor->insertAttendee( new Attendee( name, email ) ); + mAttendeeEditor->insertAttendee( new Attendee( name, email, true, Attendee::NeedsAction ) ); + } +} + +void KOIncidenceEditor::setResource( ResourceCalendar *res, const TQString &subRes ) +{ + TQString label; + if ( res ) { + if ( !res->subresources().isEmpty() && !subRes.isEmpty() ) { + label = res->labelForSubresource( subRes ); + } else { + label = res->resourceName(); + } + } + + mResource = res; + mSubResource = subRes; +} + + +void KOIncidenceEditor::selectCreateTask( bool enable ) +{ + mIsCreateTask = enable; + if ( mIsCreateTask ) { + setCaption( i18n( "Create to-do" ) ); + setButtonOK( i18n( "Create to-do" ) ); + showButtonApply( false ); } } @@ -375,9 +403,16 @@ void KOIncidenceEditor::selectInvitationCounterProposal(bool enable) if ( mIsCounter ) { setCaption( i18n( "Counter proposal" ) ); setButtonOK( i18n( "Counter proposal" ) ); - enableButtonApply( false ); + showButtonApply( false ); } } +void KOIncidenceEditor::setRecurringIncidence ( Incidence *originalIncidence, + Incidence *incAfterDissociation ) +{ + mRecurIncidence = originalIncidence; + mRecurIncidenceAfterDissoc = incAfterDissociation; +} + #include "koincidenceeditor.moc" diff --git a/korganizer/koincidenceeditor.h b/korganizer/koincidenceeditor.h index 35c4c45ba..91f22afdd 100644 --- a/korganizer/koincidenceeditor.h +++ b/korganizer/koincidenceeditor.h @@ -28,6 +28,7 @@ #include <kdialogbase.h> #include <kurl.h> +class TQDate; class TQDateTime; namespace KPIM { @@ -42,9 +43,10 @@ class KOEditorDetails; class KOAttendeeEditor; namespace KCal { -class Calendar; -class CalendarLocal; -class Incidence; + class Calendar; + class CalendarLocal; + class Incidence; + class ResourceCalendar; } using namespace KCal; using namespace KOrg; @@ -54,7 +56,7 @@ using namespace KOrg; */ class KOIncidenceEditor : public KDialogBase { - Q_OBJECT + Q_OBJECT public: /** Construct new IncidenceEditor. @@ -64,15 +66,31 @@ class KOIncidenceEditor : public KDialogBase virtual ~KOIncidenceEditor(); /** This incidence has been modified externally */ - virtual void modified (int /*change*/=0) {} + virtual void modified() {} virtual void reload() = 0; + virtual void setResource( ResourceCalendar *res, const TQString &subRes ); virtual void selectInvitationCounterProposal( bool enable ); + virtual void selectCreateTask( bool enable ); + + /** + This should be called when editing only one occurrence of a recurring incidence, + before showing the editor. + + It gives the editor a pointer to the original incidence, which contains all occurrences + and a pointer to the original incidence already dissociated from the event (mEvent). + + If the user presses ok/apply the changes made to the incAfterDissociation are commited + to the callendar through mChanger. + + If the user presses cancel we restore originalIncidence and all dissociations are discarded + */ + void setRecurringIncidence( Incidence *originalIncidence, Incidence *incAfterDissociation ); public slots: /** Edit an existing todo. */ - virtual void editIncidence(Incidence *, Calendar *) = 0; + virtual void editIncidence(Incidence *, const TQDate &, Calendar *) = 0; virtual void setIncidenceChanger( IncidenceChangerBase *changer ) { mChanger = changer; } /** Initialize editor. This function creates the tab widgets. */ @@ -88,7 +106,6 @@ class KOIncidenceEditor : public KDialogBase */ void addAttendees( const TQStringList &attendees ); - signals: void deleteAttendee( Incidence * ); @@ -153,7 +170,14 @@ class KOIncidenceEditor : public KDialogBase TQMap<TQWidget*, KPIM::DesignerFields*> mDesignerFieldForWidget; TQPtrList<TQWidget> mEmbeddedURLPages; TQPtrList<TQWidget> mAttachedDesignerFields; + ResourceCalendar *mResource; + TQString mSubResource; bool mIsCounter; + bool mIsCreateTask; + + Incidence *mRecurIncidence; + Incidence *mRecurIncidenceAfterDissoc; + }; #endif diff --git a/korganizer/koincidencetooltip.cpp b/korganizer/koincidencetooltip.cpp index 8b3f11756..2b2a80f29 100644 --- a/korganizer/koincidencetooltip.cpp +++ b/korganizer/koincidencetooltip.cpp @@ -33,19 +33,24 @@ some improvements by Mikolaj Machowski */ -void KOIncidenceToolTip::add ( TQWidget * widget, Incidence *incidence, - TQToolTipGroup * group, const TQString & longText ) +void KOIncidenceToolTip::add ( TQWidget *widget, Calendar *calendar, + Incidence *incidence, const TQDate &date, + TQToolTipGroup *group, const TQString &longText ) { - if ( !widget || !incidence ) return; - TQToolTip::add(widget, IncidenceFormatter::toolTipString( incidence ), group, longText); + if ( !widget || !incidence ) { + return; + } + TQToolTip::add( widget, IncidenceFormatter::toolTipStr( calendar, incidence, date ), group, longText ); } -void KOIncidenceToolTip::add(KOAgendaItem * item, Incidence * incidence, TQToolTipGroup * group) +void KOIncidenceToolTip::add( KOAgendaItem *item, Calendar *calendar, + Incidence *incidence, const TQDate &date, + TQToolTipGroup *group ) { Q_UNUSED( incidence ); Q_UNUSED( group ); TQToolTip::remove( item ); - new KOIncidenceToolTip( item ); + new KOIncidenceToolTip( item, calendar, date ); } void KOIncidenceToolTip::maybeTip(const TQPoint & pos) @@ -55,6 +60,6 @@ void KOIncidenceToolTip::maybeTip(const TQPoint & pos) if ( !item ) return; if ( !mText ) - mText = IncidenceFormatter::toolTipString( item->incidence() ); + mText = IncidenceFormatter::toolTipStr( mCalendar, item->incidence(), mDate ); tip( TQRect( TQPoint( 0, 0 ), item->size() ), mText ); } diff --git a/korganizer/koincidencetooltip.h b/korganizer/koincidencetooltip.h index 11b5d39a3..348ab890b 100644 --- a/korganizer/koincidencetooltip.h +++ b/korganizer/koincidencetooltip.h @@ -27,6 +27,7 @@ namespace KCal { +class Calendar; class Incidence; } using namespace KCal; @@ -39,19 +40,24 @@ class KOAgendaItem; class KOIncidenceToolTip : public QToolTip { public: - KOIncidenceToolTip(TQWidget * widget, TQToolTipGroup * group = 0 ):TQToolTip (widget, group),mText(0) {} + KOIncidenceToolTip( TQWidget *widget, Calendar *calendar, const TQDate &date, TQToolTipGroup *group = 0 ) + : TQToolTip (widget, group), mCalendar( calendar ), mDate( date ), mText(0) {} /* ~KOIncidenceToolTip();*/ public: - static void add ( TQWidget * widget, Incidence *incidence, - TQToolTipGroup * group = 0, const TQString & longText = "" ); - static void add( KOAgendaItem *item, Incidence *incidence = 0, + static void add ( TQWidget *widget, Calendar *calendar, + Incidence *incidence, const TQDate &date=TQDate(), + TQToolTipGroup *group = 0, const TQString &longText = "" ); + static void add( KOAgendaItem *item, Calendar *calendar, + Incidence *incidence = 0, const TQDate &date=TQDate(), TQToolTipGroup *group = 0 ); /* reimplmented from TQToolTip */ void maybeTip( const TQPoint &pos ); private: + Calendar *mCalendar; + TQDate mDate; TQString mText; }; diff --git a/korganizer/kojournaleditor.cpp b/korganizer/kojournaleditor.cpp index a50ba1fe2..b53e071ee 100644 --- a/korganizer/kojournaleditor.cpp +++ b/korganizer/kojournaleditor.cpp @@ -62,8 +62,10 @@ void KOJournalEditor::init() void KOJournalEditor::reload() { - kdDebug(5851)<<"reloading Journal"<<endl; - if ( mJournal ) readJournal( mJournal ); + kdDebug(5851) << "reloading Journal" << endl; + if ( mJournal ) { + readJournal( mJournal, TQDate() ); + } } void KOJournalEditor::setupGeneral() @@ -94,7 +96,7 @@ void KOJournalEditor::setupGeneral() mGeneral->finishSetup(); } -void KOJournalEditor::editIncidence( Incidence *incidence, Calendar * ) +void KOJournalEditor::editIncidence( Incidence *incidence, const TQDate &date, Calendar * ) { Journal *journal=dynamic_cast<Journal*>(incidence); if (journal) @@ -102,7 +104,7 @@ void KOJournalEditor::editIncidence( Incidence *incidence, Calendar * ) init(); mJournal = journal; - readJournal(mJournal); + readJournal(mJournal, date); } } @@ -140,7 +142,7 @@ bool KOJournalEditor::processInput() if ( mJournal ) { Journal *oldJournal = mJournal->clone(); writeJournal( mJournal ); - mChanger->changeIncidence( oldJournal, mJournal ); + mChanger->changeIncidence( oldJournal, mJournal, KOGlobals::NOTHING_MODIFIED, this ); delete oldJournal; } else { mJournal = new Journal; @@ -149,8 +151,7 @@ bool KOJournalEditor::processInput() writeJournal( mJournal ); - if ( !mChanger->addIncidence( mJournal, this ) ) { - KODialogManager::errorSaveIncidence( this, mJournal ); + if ( !mChanger->addIncidence( mJournal, mResource, mSubResource, this ) ) { delete mJournal; mJournal = 0; return false; @@ -176,10 +177,10 @@ void KOJournalEditor::setDate( const TQDate &date ) mDetails->setDefaults(); } -void KOJournalEditor::readJournal( Journal *journal ) +void KOJournalEditor::readJournal( Journal *journal, const TQDate &date ) { kdDebug(5851)<<"read Journal"<<endl; - mGeneral->readJournal( journal ); + mGeneral->readJournal( journal, date ); mDetails->readEvent( journal ); } @@ -201,10 +202,10 @@ int KOJournalEditor::msgItemDelete() i18n("KOrganizer Confirmation"), KGuiItem( i18n("Delete"), "editdelete" )); } -void KOJournalEditor::modified( int /*modification*/) +void KOJournalEditor::modified() { - // Play dump, just reload the Journal. This dialog has become so complicated that - // there is no point in trying to be smart here... + // Play dump, just reload the Journal. This dialog has become so complicated + // that there is no point in trying to be smart here... reload(); } @@ -215,7 +216,7 @@ void KOJournalEditor::loadTemplate( /*const*/ CalendarLocal& cal) KMessageBox::error( this, i18n("Template does not contain a valid journal.") ); } else { - readJournal( journals.first() ); + readJournal( journals.first(), TQDate() ); } } diff --git a/korganizer/kojournaleditor.h b/korganizer/kojournaleditor.h index 75edb1829..291940cf0 100644 --- a/korganizer/kojournaleditor.h +++ b/korganizer/kojournaleditor.h @@ -69,12 +69,12 @@ class KOJournalEditor : public KOIncidenceEditor */ void setTexts( const TQString &summary, const TQString &description = TQString::null ); /** Edit an existing Journal. */ - void editIncidence(Incidence *, Calendar *); + void editIncidence(Incidence *, const TQDate &date, Calendar *); /** Set widgets to default values */ void setDate( const TQDate &date ); /** Read event object and setup widgets accordingly */ - void readJournal( Journal * ); + void readJournal( Journal *, const TQDate &date ); /** Write event settings to event object */ void writeJournal( Journal * ); @@ -86,7 +86,7 @@ class KOJournalEditor : public KOIncidenceEditor bool processInput(); /** This Journal has been modified externally */ - void modified (int change=0); + void modified(); protected slots: void loadDefaults(); diff --git a/korganizer/kojournalview.cpp b/korganizer/kojournalview.cpp index e8de3daed..74a0f17cd 100644 --- a/korganizer/kojournalview.cpp +++ b/korganizer/kojournalview.cpp @@ -71,20 +71,24 @@ void KOJournalView::appendJournal( Journal*journal, const TQDate &dt) entry->setDate( dt ); entry->setIncidenceChanger( mChanger ); entry->show(); - connect( this, TQT_SIGNAL(flushEntries()), entry, TQT_SIGNAL(flushEntries()) ); - connect( this, TQT_SIGNAL(setIncidenceChangerSignal( IncidenceChangerBase * ) ), - entry, TQT_SLOT(setIncidenceChanger( IncidenceChangerBase * ) ) ); - connect( this, TQT_SIGNAL( journalEdited( Journal* ) ), - entry, TQT_SLOT( journalEdited( Journal* ) ) ); - connect( this, TQT_SIGNAL( journalDeleted( Journal* ) ), - entry, TQT_SLOT( journalDeleted( Journal* ) ) ); - - connect( entry, TQT_SIGNAL( editIncidence( Incidence* ) ), - this, TQT_SIGNAL( editIncidenceSignal( Incidence* ) ) ); - connect( entry, TQT_SIGNAL( deleteIncidence( Incidence* ) ), - this, TQT_SIGNAL( deleteIncidenceSignal( Incidence* ) ) ); - connect( entry, TQT_SIGNAL( newJournal( const TQDate & ) ), - this, TQT_SIGNAL( newJournalSignal( const TQDate & ) ) ); + connect( this, TQT_SIGNAL(flushEntries()), + entry, TQT_SIGNAL(flushEntries()) ); + + connect( this, TQT_SIGNAL(setIncidenceChangerSignal(IncidenceChangerBase *)), + entry, TQT_SLOT(setIncidenceChanger( IncidenceChangerBase *)) ); + + connect( this, TQT_SIGNAL(journalEdited(Journal *)), + entry, TQT_SLOT(journalEdited(Journal *)) ); + connect( this, TQT_SIGNAL(journalDeleted(Journal *)), + entry, TQT_SLOT(journalDeleted(Journal *)) ); + + connect( entry, TQT_SIGNAL(editIncidence(Incidence *,const TQDate &)), + this, TQT_SIGNAL(editIncidenceSignal(Incidence *,const TQDate &)) ); + connect( entry, TQT_SIGNAL(deleteIncidence(Incidence *)), + this, TQT_SIGNAL(deleteIncidenceSignal(Incidence *)) ); + + connect( entry, TQT_SIGNAL(newJournal(ResourceCalendar *,const TQString &,const TQDate &)), + this, TQT_SIGNAL(newJournalSignal(ResourceCalendar *,const TQString &,const TQDate &)) ); mEntries.insert( dt, entry ); } @@ -134,16 +138,18 @@ void KOJournalView::flushView() emit flushEntries(); } -void KOJournalView::showDates(const TQDate &start, const TQDate &end) +void KOJournalView::showDates( const TQDate &start, const TQDate &end ) { // kdDebug(5850) << "KOJournalView::showDates(): "<<start.toString().latin1()<<" - "<<end.toString().latin1() << endl; clearEntries(); - if ( end<start ) return; + if ( end < start ) { + return; + } Journal::List::ConstIterator it; Journal::List jnls; - TQDate d=start; - for ( TQDate d=start; d<=end; d=d.addDays(1) ) { + TQDate d = start; + for ( TQDate d = start; d <= end; d = d.addDays( 1 ) ) { jnls = calendar()->journals( d ); for ( it = jnls.begin(); it != jnls.end(); ++it ) { appendJournal( *it, d ); @@ -155,15 +161,17 @@ void KOJournalView::showDates(const TQDate &start, const TQDate &end) } } -void KOJournalView::showIncidences( const Incidence::List &incidences ) +void KOJournalView::showIncidences( const Incidence::List &incidences, const TQDate & ) { // kdDebug(5850) << "KOJournalView::showIncidences(): "<< endl; clearEntries(); Incidence::List::const_iterator it; - for ( it=incidences.constBegin(); it!=incidences.constEnd(); ++it) { - if ((*it) && ( (*it)->type()=="Journal" ) ) { - Journal*j = static_cast<Journal*>(*it); - if ( j ) appendJournal( j, j->dtStart().date() ); + for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) { + if ( (*it) && ( (*it)->type() == "Journal" ) ) { + Journal *j = static_cast<Journal*>(*it); + if ( j ) { + appendJournal( j, j->dtStart().date() ); + } } } } @@ -202,7 +210,8 @@ void KOJournalView::setIncidenceChanger( IncidenceChangerBase *changer ) void KOJournalView::newJournal() { - emit newJournalSignal( TQDate::currentDate() ); + emit newJournalSignal( 0/*ResourceCalendar*/, TQString()/*subResource*/, + TQDate::currentDate() ); } #include "kojournalview.moc" diff --git a/korganizer/kojournalview.h b/korganizer/kojournalview.h index 9af95537e..fbc38efb1 100644 --- a/korganizer/kojournalview.h +++ b/korganizer/kojournalview.h @@ -25,8 +25,8 @@ #define KOJOURNALVIEW_H #include <korganizer/baseview.h> -#include "journalentry.h" +class JournalDateEntry; class JournalEntry; class TQScrollView; class TQVBox; @@ -48,7 +48,7 @@ class KOJournalView : public KOrg::BaseView virtual int currentDateCount(); virtual Incidence::List selectedIncidences(); - DateList selectedDates() { return DateList(); } + DateList selectedIncidenceDates() { return DateList(); } void appendJournal( Journal*journal, const TQDate &dt); CalPrinterBase::PrintType printType(); @@ -60,7 +60,7 @@ class KOJournalView : public KOrg::BaseView void flushView(); void showDates( const TQDate &start, const TQDate &end ); - void showIncidences( const Incidence::List &incidenceList ); + void showIncidences( const Incidence::List &incidenceList, const TQDate &date ); void changeIncidenceDisplay( Incidence *, int ); void setIncidenceChanger( IncidenceChangerBase *changer ); diff --git a/korganizer/kolistview.cpp b/korganizer/kolistview.cpp index 7ca342e87..59b7f17e1 100644 --- a/korganizer/kolistview.cpp +++ b/korganizer/kolistview.cpp @@ -28,6 +28,7 @@ #include <tqlayout.h> #include <tqpopupmenu.h> #include <tqcursor.h> +#include <tqstyle.h> #include <klocale.h> #include <kdebug.h> @@ -45,30 +46,39 @@ #include "kolistview.h" #include "kolistview.moc" +enum { + Summary_Column = 0, + Reminder_Column, + Recurs_Column, + StartDateTime_Column, + EndDateTime_Column, + Categories_Column +}; + KOListViewToolTip::KOListViewToolTip( TQWidget* parent, - KListView* lv ) - :TQToolTip(parent) + Calendar *calendar, + KListView *lv ) + :TQToolTip( parent ), mCalendar( calendar ) { - eventlist=lv; + eventlist = lv; } -void KOListViewToolTip::maybeTip( const TQPoint & pos) +void KOListViewToolTip::maybeTip( const TQPoint &pos ) { TQRect r; - TQListViewItem *it = eventlist->itemAt(pos); - KOListViewItem *i = static_cast<KOListViewItem*>(it); + TQListViewItem *it = eventlist->itemAt( pos ); + KOListViewItem *i = static_cast<KOListViewItem*>( it ); - if( i && KOPrefs::instance()->mEnableToolTips ) { + if ( i && KOPrefs::instance()->mEnableToolTips ) { /* Calculate the rectangle. */ - r=eventlist->itemRect( it ); + r = eventlist->itemRect( it ); /* Show the tip */ - TQString tipText( IncidenceFormatter::toolTipString( i->data() ) ); + TQString tipText( IncidenceFormatter::toolTipStr( mCalendar, i->data() ) ); if ( !tipText.isEmpty() ) { - tip(r, tipText); + tip( r, tipText ); } } - } /** @@ -91,132 +101,127 @@ class KOListView::ListItemVisitor : public IncidenceBase::Visitor bool KOListView::ListItemVisitor::visit( Event *e ) { - mItem->setText(0,e->summary()); + mItem->setText( Summary_Column, e->summary() ); if ( e->isAlarmEnabled() ) { static const TQPixmap alarmPxmp = KOGlobals::self()->smallIcon( "bell" ); - mItem->setPixmap(1,alarmPxmp); - mItem->setSortKey(1,"1"); + mItem->setPixmap( Reminder_Column, alarmPxmp ); + mItem->setSortKey( Reminder_Column, "1" ); + } else { + mItem->setSortKey( Reminder_Column, "0" ); } - else - mItem->setSortKey(1,"0"); if ( e->doesRecur() ) { static const TQPixmap recurPxmp = KOGlobals::self()->smallIcon( "recur" ); - mItem->setPixmap(2,recurPxmp); - mItem->setSortKey(2,"1"); + mItem->setPixmap( Recurs_Column, recurPxmp ); + mItem->setSortKey( Recurs_Column, "1" ); + } else { + mItem->setSortKey( Recurs_Column, "0" ); } - else - mItem->setSortKey(2,"0"); - - static const TQPixmap eventPxmp = KOGlobals::self()->smallIcon( "appointment" ); - mItem->setPixmap(0, eventPxmp); - mItem->setText( 3,e->dtStartDateStr()); - mItem->setSortKey( 3, e->dtStart().toString(Qt::ISODate)); - if (e->doesFloat()) mItem->setText(4, "---"); else { - mItem->setText( 4, e->dtStartTimeStr() ); - mItem->setSortKey( 4,e->dtStart().time().toString(Qt::ISODate)); - } - mItem->setText( 5,e->dtEndDateStr()); - mItem->setSortKey( 5, e->dtEnd().toString(Qt::ISODate)); - if (e->doesFloat()) mItem->setText(6, "---"); else { - mItem->setText( 6, e->dtEndTimeStr() ); - mItem->setSortKey( 6, e->dtEnd().time().toString(Qt::ISODate)); + TQPixmap eventPxmp; + if ( e->customProperty( "KABC", "BIRTHDAY" ) == "YES" ) { + if ( e->customProperty( "KABC", "ANNIVERSARY" ) == "YES" ) { + eventPxmp = KOGlobals::self()->smallIcon( "calendaranniversary" ); + } else { + eventPxmp = KOGlobals::self()->smallIcon( "calendarbirthday" ); + } + } else { + eventPxmp = KOGlobals::self()->smallIcon( "appointment" ); } - mItem->setText( 7,e->categoriesStr()); + + mItem->setPixmap( Summary_Column, eventPxmp ); + + TQString startDateTime; + TQString endDateTime; + + mItem->setText( StartDateTime_Column, IncidenceFormatter::dateTimeToString( e->dtStart(), e->doesFloat() ) ); + mItem->setSortKey( StartDateTime_Column, e->dtStart().toString( Qt::ISODate ) ); + mItem->setText( EndDateTime_Column, IncidenceFormatter::dateTimeToString( e->dtEnd(), e->doesFloat() ) ); + mItem->setSortKey( EndDateTime_Column, e->dtEnd().toString( Qt::ISODate ) ); + mItem->setText( Categories_Column, e->categoriesStr() ); return true; } -bool KOListView::ListItemVisitor::visit(Todo *t) +bool KOListView::ListItemVisitor::visit( Todo *t ) { static const TQPixmap todoPxmp = KOGlobals::self()->smallIcon( "todo" ); static const TQPixmap todoDonePxmp = KOGlobals::self()->smallIcon( "checkedbox" ); - mItem->setPixmap(0, t->isCompleted() ? todoDonePxmp : todoPxmp ); - mItem->setText(0,t->summary()); + mItem->setPixmap(Summary_Column, t->isCompleted() ? todoDonePxmp : todoPxmp ); + mItem->setText(Summary_Column, t->summary()); if ( t->isAlarmEnabled() ) { static const TQPixmap alarmPxmp = KOGlobals::self()->smallIcon( "bell" ); - mItem->setPixmap(1,alarmPxmp); - mItem->setSortKey(1, "1"); + mItem->setPixmap( Reminder_Column, alarmPxmp ); + mItem->setSortKey( Reminder_Column, "1" ); + } else { + mItem->setSortKey( Reminder_Column, "0" ); } - else - mItem->setSortKey(1, "0"); if ( t->doesRecur() ) { static const TQPixmap recurPxmp = KOGlobals::self()->smallIcon( "recur" ); - mItem->setPixmap(2,recurPxmp); - mItem->setSortKey(2, "1"); - } - else - mItem->setSortKey(2, "0"); - - if (t->hasStartDate()) { - mItem->setText(3,t->dtStartDateStr()); - mItem->setSortKey(3,t->dtStart().toString(Qt::ISODate)); - if (t->doesFloat()) { - mItem->setText(4,"---"); - } else { - mItem->setText(4,t->dtStartTimeStr()); - mItem->setSortKey( 4, t->dtStart().time().toString(Qt::ISODate) ); - } + mItem->setPixmap( Recurs_Column, recurPxmp ); + mItem->setSortKey( Recurs_Column, "1" ); } else { - mItem->setText(3,"---"); - mItem->setText(4,"---"); + mItem->setSortKey( Recurs_Column, "0" ); } - if (t->hasDueDate()) { - mItem->setText(5,t->dtDueDateStr()); - mItem->setSortKey( 5, t->dtDue().toString(Qt::ISODate) ); - if (t->doesFloat()) { - mItem->setText(6,"---"); - } else { - mItem->setText(6,t->dtDueTimeStr()); - mItem->setSortKey( 6, t->dtDue().time().toString(Qt::ISODate) ); - } + if ( t->hasStartDate() ) { + mItem->setText( StartDateTime_Column, IncidenceFormatter::dateTimeToString( t->dtStart(), t->doesFloat() ) ); + mItem->setSortKey( StartDateTime_Column, t->dtStart().toString( Qt::ISODate ) ); } else { - mItem->setText(5,"---"); - mItem->setText(6,"---"); + mItem->setText( StartDateTime_Column, "---" ); } - mItem->setText(7,t->categoriesStr()); + if ( t->hasDueDate() ) { + mItem->setText( EndDateTime_Column, IncidenceFormatter::dateTimeToString( t->dtDue(), t->doesFloat() ) ); + mItem->setSortKey( EndDateTime_Column, t->dtDue().toString( Qt::ISODate ) ); + } else { + mItem->setText( EndDateTime_Column, "---" ); + } + mItem->setText( Categories_Column, t->categoriesStr() ); return true; } -bool KOListView::ListItemVisitor::visit(Journal *t) +bool KOListView::ListItemVisitor::visit( Journal *j ) { - static const TQPixmap jrnalPxmp = KOGlobals::self()->smallIcon( "journal" ); - mItem->setPixmap(0,jrnalPxmp); + static const TQPixmap jornalPxmp = KOGlobals::self()->smallIcon( "journal" ); + mItem->setPixmap( Summary_Column, jornalPxmp ); // Just use the first line - mItem->setText( 0, t->description().section( "\n", 0, 0 ) ); - mItem->setText( 3, t->dtStartDateStr() ); - mItem->setSortKey( 3, t->dtStart().toString(Qt::ISODate) ); + mItem->setText( Summary_Column, j->description().section( "\n", 0, 0 ) ); + mItem->setText( StartDateTime_Column, IncidenceFormatter::dateTimeToString( j->dtStart(), j->doesFloat() ) ); + mItem->setSortKey( StartDateTime_Column, j->dtStart().toString( Qt::ISODate ) ); return true; } -KOListView::KOListView( Calendar *calendar, TQWidget *parent, - const char *name) - : KOEventView(calendar, parent, name) +KOListView::KOListView( Calendar *calendar, + TQWidget *parent, + const char *name, + bool nonInteractive ) + : KOEventView( calendar, parent, name ) { mActiveItem = 0; + mIsNonInteractive = nonInteractive; - mListView = new KListView(this); - mListView->addColumn(i18n("Summary")); - mListView->addColumn(i18n("Reminder")); // alarm set? - mListView->addColumn(i18n("Recurs")); // recurs? - mListView->addColumn(i18n("Start Date")); - mListView->setColumnAlignment(3,AlignHCenter); - mListView->addColumn(i18n("Start Time")); - mListView->setColumnAlignment(4,AlignHCenter); - mListView->addColumn(i18n("End Date")); - mListView->setColumnAlignment(5,AlignHCenter); - mListView->addColumn(i18n("End Time")); - mListView->setColumnAlignment(6,AlignHCenter); - mListView->addColumn(i18n("Categories")); - - TQBoxLayout *layoutTop = new TQVBoxLayout(this); - layoutTop->addWidget(mListView); + mListView = new KListView( this ); + mListView->addColumn( i18n("Summary") ); + mListView->addColumn( i18n("Reminder") ); // alarm set? + mListView->setColumnAlignment( Reminder_Column, AlignHCenter ); + + mListView->addColumn( i18n("Recurs") ); // recurs? + mListView->setColumnAlignment( Recurs_Column, AlignHCenter ); + + mListView->addColumn( i18n("Start Date/Time") ); + mListView->setColumnAlignment( StartDateTime_Column, AlignHCenter ); + + mListView->addColumn( i18n("End Date/Time") ); + mListView->setColumnAlignment( EndDateTime_Column, AlignHCenter ); + + mListView->addColumn( i18n("Categories") ); + + TQBoxLayout *layoutTop = new TQVBoxLayout( this ); + layoutTop->addWidget( mListView ); mPopupMenu = eventPopup(); /* @@ -239,9 +244,9 @@ KOListView::KOListView( Calendar *calendar, TQWidget *parent, TQT_SLOT( processSelectionChange() ) ); // setMinimumSize(100,100); - mListView->restoreLayout(KOGlobals::self()->config(),"KOListView Layout"); + mListView->restoreLayout( KOGlobals::self()->config(), "KOListView Layout" ); - new KOListViewToolTip( mListView->viewport(), mListView ); + new KOListViewToolTip( mListView->viewport(), calendar, mListView ); mSelectedDates.append( TQDate::currentDate() ); } @@ -266,43 +271,45 @@ Incidence::List KOListView::selectedIncidences() Incidence::List eventList; TQListViewItem *item = mListView->selectedItem(); - if (item) eventList.append(((KOListViewItem *)item)->data()); + if ( item ) { + eventList.append( static_cast<KOListViewItem *>( item )->data() ); + } return eventList; } -DateList KOListView::selectedDates() +DateList KOListView::selectedIncidenceDates() { return mSelectedDates; } -void KOListView::showDates(bool show) +void KOListView::showDates( bool show ) { // Shouldn't we set it to a value greater 0? When showDates is called with // show == true at first, then the columnwidths are set to zero. static int oldColWidth1 = 0; static int oldColWidth3 = 0; - if (!show) { - oldColWidth1 = mListView->columnWidth(1); - oldColWidth3 = mListView->columnWidth(3); - mListView->setColumnWidth(1, 0); - mListView->setColumnWidth(3, 0); + if ( !show ) { + oldColWidth1 = mListView->columnWidth( 1 ); + oldColWidth3 = mListView->columnWidth( 3 ); + mListView->setColumnWidth( 1, 0 ); + mListView->setColumnWidth( 3, 0 ); } else { - mListView->setColumnWidth(1, oldColWidth1); - mListView->setColumnWidth(3, oldColWidth3); + mListView->setColumnWidth( 1, oldColWidth1 ); + mListView->setColumnWidth( 3, oldColWidth3 ); } mListView->repaint(); } void KOListView::showDates() { - showDates(true); + showDates( true ); } void KOListView::hideDates() { - showDates(false); + showDates( false ); } void KOListView::updateView() @@ -310,82 +317,103 @@ void KOListView::updateView() kdDebug(5850) << "KOListView::updateView() does nothing" << endl; } -void KOListView::showDates(const TQDate &start, const TQDate &end) +void KOListView::showDates( const TQDate &start, const TQDate &end ) { clear(); TQDate date = start; while( date <= end ) { - addIncidences( calendar()->incidences(date) ); + addIncidences( calendar()->incidences( date ), date ); mSelectedDates.append( date ); date = date.addDays( 1 ); } - emit incidenceSelected( 0 ); + emit incidenceSelected( 0, TQDate() ); } -void KOListView::addIncidences( const Incidence::List &incidenceList ) +void KOListView::showAll() +{ + Incidence::List incidenceList = calendar()->incidences(); + + Incidence::List::ConstIterator it; + for( it = incidenceList.begin(); it != incidenceList.end(); ++it ) { + // we don't need the date, using showAll in non interactive mode for now + addIncidence( *it, TQDate() ); + } +} + +void KOListView::addIncidences( const Incidence::List &incidenceList, const TQDate &date ) { Incidence::List::ConstIterator it; for( it = incidenceList.begin(); it != incidenceList.end(); ++it ) { - addIncidence( *it ); + addIncidence( *it, date ); } } -void KOListView::addIncidence(Incidence *incidence) +void KOListView::addIncidence( Incidence *incidence, const TQDate &date ) { - if ( mUidDict.find( incidence->uid() ) ) return; + if ( mUidDict.find( incidence->uid() ) ) { + return; + } + mDateList[incidence->uid()] = date; mUidDict.insert( incidence->uid(), incidence ); KOListViewItem *item = new KOListViewItem( incidence, mListView ); - ListItemVisitor v(item); - if (incidence->accept(v)) return; - else delete item; + ListItemVisitor v( item ); + if (incidence->accept( v ) ) { + return; + } else { + delete item; + } } -void KOListView::showIncidences( const Incidence::List &incidenceList ) +void KOListView::showIncidences( const Incidence::List &incidenceList, const TQDate &date ) { clear(); - addIncidences( incidenceList ); + addIncidences( incidenceList, date ); // After new creation of list view no events are selected. - emit incidenceSelected( 0 ); + emit incidenceSelected( 0, date ); } -void KOListView::changeIncidenceDisplay(Incidence *incidence, int action) +void KOListView::changeIncidenceDisplay( Incidence *incidence, int action ) { KOListViewItem *item; TQDate f = mSelectedDates.first(); TQDate l = mSelectedDates.last(); TQDate date; - if ( incidence->type() == "Todo" ) - date = static_cast<Todo *>(incidence)->dtDue().date(); - else + if ( incidence->type() == "Todo" ) { + date = static_cast<Todo *>( incidence )->dtDue().date(); + } else { date = incidence->dtStart().date(); + } - switch(action) { + switch( action ) { case KOGlobals::INCIDENCEADDED: { if ( date >= f && date <= l ) - addIncidence( incidence ); + addIncidence( incidence, date ); break; } case KOGlobals::INCIDENCEEDITED: { - item = getItemForIncidence(incidence); - if (item) { + item = getItemForIncidence( incidence ); + if ( item ) { delete item; mUidDict.remove( incidence->uid() ); + mDateList.remove( incidence->uid() ); + } + if ( date >= f && date <= l ) { + addIncidence( incidence, date ); } - if ( date >= f && date <= l ) - addIncidence( incidence ); } break; case KOGlobals::INCIDENCEDELETED: { - item = getItemForIncidence(incidence); - if (item) + item = getItemForIncidence( incidence ); + if ( item ) { delete item; + } break; } default: @@ -393,58 +421,68 @@ void KOListView::changeIncidenceDisplay(Incidence *incidence, int action) } } -KOListViewItem *KOListView::getItemForIncidence(Incidence *incidence) +KOListViewItem *KOListView::getItemForIncidence( Incidence *incidence ) { - KOListViewItem *item = (KOListViewItem *)mListView->firstChild(); - while (item) { + KOListViewItem *item = static_cast<KOListViewItem *>( mListView->firstChild() ); + while ( item ) { // kdDebug(5850) << "Item " << item->text(0) << " found" << endl; - if (item->data() == incidence) return item; - item = (KOListViewItem *)item->nextSibling(); + if ( item->data() == incidence ) { + return item; + } + item = static_cast<KOListViewItem *>( item->nextSibling() ); } return 0; } -void KOListView::defaultItemAction(TQListViewItem *i) +void KOListView::defaultItemAction( TQListViewItem *i ) { - KOListViewItem *item = static_cast<KOListViewItem *>( i ); - if ( item ) defaultAction( item->data() ); + if ( !mIsNonInteractive ) { + KOListViewItem *item = static_cast<KOListViewItem *>( i ); + if ( item ) { + defaultAction( item->data() ); + } + } } -void KOListView::popupMenu(TQListViewItem *item,const TQPoint &,int) +void KOListView::popupMenu( TQListViewItem *item,const TQPoint &, int ) { - mActiveItem = (KOListViewItem *)item; - if (mActiveItem) { - Incidence *incidence = mActiveItem->data(); - // FIXME: For recurring incidences we don't know the date of this - // occurrence, there's no reference to it at all! - mPopupMenu->showIncidencePopup( incidence, TQDate() ); - } - else { - showNewEventPopup(); + if ( !mIsNonInteractive ) { + mActiveItem = static_cast<KOListViewItem *>( item ); + if ( mActiveItem ) { + Incidence *incidence = mActiveItem->data(); + // FIXME: For recurring incidences we don't know the date of this + // occurrence, there's no reference to it at all! + mPopupMenu->showIncidencePopup( calendar(), incidence, TQDate() ); + } else { + showNewEventPopup(); + } } } -void KOListView::readSettings(KConfig *config) +void KOListView::readSettings( KConfig *config ) { - mListView->restoreLayout(config,"KOListView Layout"); + mListView->restoreLayout( config,"KOListView Layout" ); } -void KOListView::writeSettings(KConfig *config) +void KOListView::writeSettings( KConfig *config ) { - mListView->saveLayout(config,"KOListView Layout"); + mListView->saveLayout( config, "KOListView Layout" ); } void KOListView::processSelectionChange() { - kdDebug(5850) << "KOListView::processSelectionChange()" << endl; + if ( !mIsNonInteractive ) { + kdDebug(5850) << "KOListView::processSelectionChange()" << endl; - KOListViewItem *item = - static_cast<KOListViewItem *>( mListView->selectedItem() ); + KOListViewItem *item = + static_cast<KOListViewItem *>( mListView->selectedItem() ); - if ( !item ) { - emit incidenceSelected( 0 ); - } else { - emit incidenceSelected( item->data() ); + if ( !item ) { + emit incidenceSelected( 0, TQDate() ); + } else { + Incidence *incidence = static_cast<Incidence *>( item->data() ); + emit incidenceSelected( incidence, mDateList[incidence->uid()] ); + } } } @@ -458,4 +496,12 @@ void KOListView::clear() mSelectedDates.clear(); mListView->clear(); mUidDict.clear(); + mDateList.clear(); +} + +TQSize KOListView::sizeHint() const +{ + const TQSize s = KOEventView::sizeHint(); + return TQSize( s.width() + style().pixelMetric( TQStyle::PM_ScrollBarExtent ) + 1, + s.height() ); } diff --git a/korganizer/kolistview.h b/korganizer/kolistview.h index 6da6988a8..5a5c40d8f 100644 --- a/korganizer/kolistview.h +++ b/korganizer/kolistview.h @@ -27,6 +27,7 @@ #define _KOLISTVIEW_H #include <tqdict.h> +#include <tqmap.h> #include <tqtooltip.h> #include <libkcal/incidence.h> @@ -43,12 +44,13 @@ class KOListView; class KOListViewToolTip : public QToolTip { public: - KOListViewToolTip (TQWidget* parent, KListView* lv ); + KOListViewToolTip ( TQWidget* parent, Calendar *calendar, KListView* lv ); protected: - void maybeTip( const TQPoint & pos); + void maybeTip( const TQPoint &pos ); private: + Calendar *mCalendar; KListView* eventlist; }; @@ -67,26 +69,32 @@ class KOListView : public KOEventView { Q_OBJECT public: - KOListView(Calendar *calendar, TQWidget *parent = 0, - const char *name = 0); + explicit KOListView( Calendar *calendar, + TQWidget *parent = 0, + const char *name = 0, + bool nonInteractive = false ); ~KOListView(); virtual int maxDatesHint(); virtual int currentDateCount(); virtual Incidence::List selectedIncidences(); - virtual DateList selectedDates(); + virtual DateList selectedIncidenceDates(); - void showDates(bool show); + void showDates( bool show ); + + // Shows all incidences of the calendar + void showAll(); void readSettings(KConfig *config); void writeSettings(KConfig *config); void clear(); + TQSize sizeHint() const; public slots: virtual void updateView(); virtual void showDates( const TQDate &start, const TQDate &end ); - virtual void showIncidences( const Incidence::List &incidenceList ); + virtual void showIncidences( const Incidence::List &incidenceList, const TQDate &date ); void clearSelection(); @@ -102,8 +110,8 @@ class KOListView : public KOEventView void processSelectionChange(); protected: - void addIncidences( const Incidence::List & ); - void addIncidence(Incidence *); + void addIncidences(const Incidence::List &, const TQDate &date); + void addIncidence(Incidence *, const TQDate &date); KOListViewItem *getItemForIncidence(Incidence *incidence); private: @@ -112,7 +120,11 @@ class KOListView : public KOEventView KOEventPopupMenu *mPopupMenu; KOListViewItem *mActiveItem; TQDict<Incidence> mUidDict; + TQMap<TQString, TQDate>mDateList; DateList mSelectedDates; + + // if it's non interactive we disable context menu, and incidence editing + bool mIsNonInteractive; }; #endif diff --git a/korganizer/komailclient.cpp b/korganizer/komailclient.cpp index 946331fde..1b3215c09 100644 --- a/korganizer/komailclient.cpp +++ b/korganizer/komailclient.cpp @@ -34,12 +34,18 @@ #include <dcopclient.h> #include <kprocess.h> +#include <libemailfunctions/email.h> + +#include <libkpimidentities/identity.h> +#include <libkpimidentities/identitymanager.h> + #include <libkcal/event.h> #include <libkcal/todo.h> #include <libkcal/incidenceformatter.h> #include "version.h" #include "koprefs.h" +#include "kocore.h" #include "komailclient.h" @@ -54,23 +60,59 @@ KOMailClient::~KOMailClient() bool KOMailClient::mailAttendees(IncidenceBase *incidence,const TQString &attachment) { Attendee::List attendees = incidence->attendees(); - if (attendees.count() == 0) return false; + if ( attendees.count() == 0 ) { + return false; + } const TQString from = incidence->organizer().fullName(); const TQString organizerEmail = incidence->organizer().email(); + TQStringList toList; - for(uint i=0; i<attendees.count();++i) { - const TQString email = (*attendees.at(i))->email(); - // In case we (as one of our identities) are the organizer we are sending this - // mail. We could also have added ourselves as an attendee, in which case we - // don't want to send ourselves a notification mail. - if( organizerEmail != email ) - toList << email; + TQStringList ccList; + for ( uint i=0; i<attendees.count(); ++i ) { + Attendee *a = (*attendees.at(i)); + + const TQString email = a->email(); + if ( email.isEmpty() ) { + continue; + } + + // In case we (as one of our identities) are the organizer we are sending + // this mail. We could also have added ourselves as an attendee, in which + // case we don't want to send ourselves a notification mail. + if ( organizerEmail == email ) { + continue; + } + + // Build a nice address for this attendee including the CN. + TQString tname, temail; + const TQString username = KPIM::quoteNameIfNecessary( a->name() ); + KPIM::getNameAndMail( username, tname, temail ); // ignore return value + // which is always false + tname += " <" + email + '>'; + + + // Optional Participants and Non-Participants are copied on the email + if ( a->role() == Attendee::OptParticipant || + a->role() == Attendee::NonParticipant ) { + ccList << tname; + } else { + toList << tname; + } } - if( toList.count() == 0 ) + + if( toList.count() == 0 && ccList.count() == 0 ) { // Not really to be called a groupware meeting, eh return false; - TQString to = toList.join( ", " ); + } + TQString to; + if ( toList.count() > 0 ) { + to = toList.join( ", " ); + } + TQString cc; + if ( ccList.count() > 0 ) { + cc = ccList.join( ", " ); + } TQString subject; if(incidence->type()!="FreeBusy") { @@ -84,7 +126,7 @@ bool KOMailClient::mailAttendees(IncidenceBase *incidence,const TQString &attach bool bcc = KOPrefs::instance()->mBcc; - return send(from,to,subject,body,bcc,attachment); + return send(from,to,cc,subject,body,bcc,attachment); } bool KOMailClient::mailOrganizer(IncidenceBase *incidence,const TQString &attachment, const TQString &sub) @@ -106,7 +148,7 @@ bool KOMailClient::mailOrganizer(IncidenceBase *incidence,const TQString &attach bool bcc = KOPrefs::instance()->mBcc; - return send(from,to,subject,body,bcc,attachment); + return send(from,to,TQString::null,subject,body,bcc,attachment); } bool KOMailClient::mailTo(IncidenceBase *incidence,const TQString &recipients, @@ -123,16 +165,25 @@ bool KOMailClient::mailTo(IncidenceBase *incidence,const TQString &recipients, TQString body = IncidenceFormatter::mailBodyString(incidence); bool bcc = KOPrefs::instance()->mBcc; kdDebug () << "KOMailClient::mailTo " << recipients << endl; - return send(from,recipients,subject,body,bcc,attachment); + return send(from,recipients,TQString::null,subject,body,bcc,attachment); } -bool KOMailClient::send(const TQString &from,const TQString &to, +bool KOMailClient::send(const TQString &from,const TQString &_to,const TQString &cc, const TQString &subject,const TQString &body,bool bcc, const TQString &attachment) { - kdDebug(5850) << "KOMailClient::sendMail():\nFrom: " << from << "\nTo: " << to - << "\nSubject: " << subject << "\nBody: \n" << body - << "\nAttachment:\n" << attachment << endl; + // We must have a recipients list for most MUAs. Thus, if the 'to' list + // is empty simply use the 'from' address as the recipient. + TQString to = _to; + if ( to.isEmpty() ) { + to = from; + } + + kdDebug(5850) << "KOMailClient::sendMail():\nFrom: " << from + << "\nTo: " << to + << "\nCC: " << cc + << "\nSubject: " << subject << "\nBody: \n" << body + << "\nAttachment:\n" << attachment << endl; if (KOPrefs::instance()->mMailClient == KOPrefs::MailClientSendmail) { bool needHeaders = true; @@ -152,6 +203,11 @@ bool KOMailClient::send(const TQString &from,const TQString &to, command.append(KProcess::quote(from)); } + if ( !cc.isEmpty() ) { + command.append(" -c "); + command.append(KProcess::quote(cc)); + } + command.append(" "); command.append(KProcess::quote(to)); @@ -170,6 +226,9 @@ bool KOMailClient::send(const TQString &from,const TQString &to, { textComplete += TQString::fromLatin1("From: ") + from + '\n'; textComplete += TQString::fromLatin1("To: ") + to + '\n'; + if ( !cc.isEmpty() ) { + textComplete += TQString::fromLatin1("Cc: " ) + cc + '\n'; + } if (bcc) textComplete += TQString::fromLatin1("Bcc: ") + from + '\n'; textComplete += TQString::fromLatin1("Subject: ") + subject + '\n'; textComplete += TQString::fromLatin1("X-Mailer: KOrganizer") + korgVersion + '\n'; @@ -184,14 +243,14 @@ bool KOMailClient::send(const TQString &from,const TQString &to, pclose(fd); } else { if (!kapp->dcopClient()->isApplicationRegistered("kmail")) { - if (KApplication::startServiceByDesktopName("kmail")) { + if (KApplication::startServiceByDesktopName("kmail")) { KMessageBox::error(0,i18n("No running instance of KMail found.")); return false; - } + } } if (attachment.isEmpty()) { - if (!kMailOpenComposer(to,"",bcc ? from : "",subject,body,0,KURL())) return false; + if (!kMailOpenComposer(to,cc,bcc ? from : "",subject,body,0,KURL())) return false; } else { TQString meth; int idx = attachment.find("METHOD"); @@ -203,9 +262,12 @@ bool KOMailClient::send(const TQString &from,const TQString &to, } else { meth = "publish"; } - if (!kMailOpenComposer(to,"",bcc ? from : "",subject,body,0,"cal.ics","7bit", + if (!kMailOpenComposer(to,cc,bcc ? from : "",subject,body,0,"cal.ics","7bit", attachment.utf8(),"text","calendar","method",meth, - "attachment","utf-8")) return false; + "attachment","utf-8", + KOCore::self()->identityManager()->identityForAddress( from ).uoid())) { + return false; + } } } return true; @@ -252,7 +314,7 @@ int KOMailClient::kMailOpenComposer( const TQString& arg0, const TQString& arg1, const TQCString& arg7, const TQCString& arg8, const TQCString& arg9, const TQCString& arg10, const TQCString& arg11, const TQString& arg12, - const TQCString& arg13, const TQCString& arg14 ) + const TQCString& arg13, const TQCString& arg14, uint identity ) { //kdDebug(5850) << "KOMailClient::kMailOpenComposer( " // << arg0 << " , " << arg1 << arg2 << " , " << arg3 @@ -281,11 +343,12 @@ int KOMailClient::kMailOpenComposer( const TQString& arg0, const TQString& arg1, arg << arg12; arg << arg13; arg << arg14; + arg << identity; #if KDE_IS_VERSION( 3, 2, 90 ) kapp->updateRemoteUserTimestamp("kmail"); #endif if ( kapp->dcopClient()->call("kmail","KMailIface", - "openComposer(TQString,TQString,TQString,TQString,TQString,int,TQString,TQCString,TQCString,TQCString,TQCString,TQCString,TQString,TQCString,TQCString)", data, replyType, replyData ) ) { + "openComposer(TQString,TQString,TQString,TQString,TQString,int,TQString,TQCString,TQCString,TQCString,TQCString,TQCString,TQString,TQCString,TQCString,uint)", data, replyType, replyData ) ) { if ( replyType == "int" ) { TQDataStream _reply_stream( replyData, IO_ReadOnly ); _reply_stream >> result; diff --git a/korganizer/komailclient.h b/korganizer/komailclient.h index da71ecec1..3051bab7e 100644 --- a/korganizer/komailclient.h +++ b/korganizer/komailclient.h @@ -45,8 +45,8 @@ class KOMailClient protected: /** Send mail with specified from, to and subject field and body as text. If * bcc is set, send a blind carbon copy to the sender from */ - bool send(const TQString &from,const TQString &to,const TQString &subject, - const TQString &body,bool bcc=false, + bool send(const TQString &from,const TQString &to,const TQString &cc, + const TQString &subject,const TQString &body,bool bcc=false, const TQString &attachment=TQString::null); int kMailOpenComposer(const TQString& to, const TQString& cc, @@ -59,7 +59,8 @@ class KOMailClient const TQCString& attachParamAttr, const TQString& attachParamValue, const TQCString& attachContDisp, - const TQCString& attachCharset); + const TQCString& attachCharset, + uint identity); int kMailOpenComposer(const TQString& arg0,const TQString& arg1, const TQString& arg2,const TQString& arg3, const TQString& arg4,int arg5,const KURL& arg6); diff --git a/korganizer/komonthview.cpp b/korganizer/komonthview.cpp index 85d9049b6..264525418 100644 --- a/korganizer/komonthview.cpp +++ b/korganizer/komonthview.cpp @@ -62,13 +62,15 @@ //-------------------------------------------------------------------------- KOMonthCellToolTip::KOMonthCellToolTip( TQWidget *parent, + Calendar *calendar, + const TQDate &date, KNoScrollListBox *lv ) - : TQToolTip( parent ) + : TQToolTip( parent ), mCalendar( calendar ), mDate( date ) { eventlist = lv; } -void KOMonthCellToolTip::maybeTip( const TQPoint & pos ) +void KOMonthCellToolTip::maybeTip( const TQPoint &pos ) { TQRect r; TQListBoxItem *it = eventlist->itemAt( pos ); @@ -78,7 +80,7 @@ void KOMonthCellToolTip::maybeTip( const TQPoint & pos ) /* Calculate the rectangle. */ r=eventlist->itemRect( it ); /* Show the tip */ - TQString tipText( IncidenceFormatter::toolTipString( i->incidence() ) ); + TQString tipText( IncidenceFormatter::toolTipStr( mCalendar, i->incidence(), mDate ) ); if ( !tipText.isEmpty() ) { tip( r, tipText ); } @@ -199,13 +201,14 @@ MonthViewItem::MonthViewItem( Incidence *incidence, const TQDateTime &qd, mDateTime = qd; mEventPixmap = KOGlobals::self()->smallIcon( "appointment" ); + mBirthdayPixmap = KOGlobals::self()->smallIcon( "calendarbirthday" ); + mAnniversaryPixmap= KOGlobals::self()->smallIcon( "calendaranniversary" ); mTodoPixmap = KOGlobals::self()->smallIcon( "todo" ); mTodoDonePixmap = KOGlobals::self()->smallIcon( "checkedbox" ); mAlarmPixmap = KOGlobals::self()->smallIcon( "bell" ); mRecurPixmap = KOGlobals::self()->smallIcon( "recur" ); mReplyPixmap = KOGlobals::self()->smallIcon( "mail_reply" ); - mResourceColor = TQColor(); mEvent = false; mTodo = false; mTodoDone = false; @@ -214,6 +217,26 @@ MonthViewItem::MonthViewItem( Incidence *incidence, const TQDateTime &qd, mReply = false; } +TQColor MonthViewItem::catColor() const +{ + TQColor retColor; + if ( !mIncidence ) { + return retColor; + } + + TQStringList categories = mIncidence->categories(); + TQString cat; + if ( !categories.isEmpty() ) { + cat = categories.first(); + } + if ( cat.isEmpty() ) { + retColor = KOPrefs::instance()->unsetCategoryColor(); + } else { + retColor = *( KOPrefs::instance()->categoryColor( cat ) ); + } + return retColor; +} + void MonthViewItem::paint( TQPainter *p ) { #if QT_VERSION >= 0x030000 @@ -222,25 +245,86 @@ void MonthViewItem::paint( TQPainter *p ) bool sel = selected(); #endif - TQColor bgColor = palette().color( TQPalette::Normal, - sel ? TQColorGroup::Highlight : TQColorGroup::Background ); - int offset=0; - if ( KOPrefs::instance()->monthViewUsesResourceColor() && - mResourceColor.isValid() ) { - p->setBackgroundColor( mResourceColor ); - p->eraseRect( 0, 0, listBox()->maxItemWidth(), height( listBox() ) ); - offset=2; + TQColor bgColor = TQColor(); // Default invalid color; + if ( mIncidence && mTodo ) { + if ( static_cast<Todo*>( mIncidence )->isOverdue() ) { + bgColor = KOPrefs::instance()->todoOverdueColor(); + } else if ( static_cast<Todo*>( mIncidence )->dtDue().date() == TQDate::currentDate() ) { + bgColor = KOPrefs::instance()->todoDueTodayColor(); + } + } + + if ( !bgColor.isValid() ) { + if ( KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemResourceOnly || + KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemResourceInsideCategoryOutside ) { + bgColor = resourceColor(); + } else { + bgColor = catColor(); + } + + if ( !bgColor.isValid() ) { + bgColor = palette().color( TQPalette::Normal, + sel ? TQColorGroup::Highlight : + TQColorGroup::Background ); + } + } + + TQColor frameColor; + if ( KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemResourceOnly || + KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemCategoryInsideResourceOutside ) { + frameColor = resourceColor(); + } else { + frameColor = catColor(); + } + + if ( mIncidence ) { + if ( mIncidence->categories().isEmpty() && + KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemResourceInsideCategoryOutside ) { + frameColor = bgColor; + } + + if ( mIncidence->categories().isEmpty() && + KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemCategoryInsideResourceOutside ) { + bgColor = frameColor; + } } - if ( KOPrefs::instance()->monthViewUsesCategoryColor() ) { - p->setBackgroundColor( bgColor ); - p->eraseRect( offset, offset, listBox()->maxItemWidth()-2*offset, height( listBox() )-2*offset ); + + if ( !frameColor.isValid() ) { + frameColor = palette().color( TQPalette::Normal, + sel ? TQColorGroup::Highlight : + TQColorGroup::Foreground ); + } else { + frameColor = frameColor.dark( 115 ); } + + // draw the box for the item + p->setBackgroundColor( frameColor ); + p->eraseRect( 0, 0, listBox()->maxItemWidth(), height( listBox() ) ); + int offset = 2; + p->setBackgroundColor( bgColor ); + p->eraseRect( offset, offset, listBox()->maxItemWidth()-2*offset, height( listBox() )-2*offset ); + int x = 3; -// Do NOT put on the event pixmap because it takes up too much space -// if ( mEvent ) { -// p->drawPixmap( x, 0, mEventPixmap ); -// x += mEventPixmap.width() + 2; -// } + + bool specialEvent = false; + if ( mEvent ) { + if ( mIncidence->customProperty( "KABC", "BIRTHDAY" ) == "YES" ) { + specialEvent = true; + if ( mIncidence->customProperty( "KABC", "ANNIVERSARY" ) == "YES" ) { + p->drawPixmap( x, 0, mAnniversaryPixmap ); + x += mAnniversaryPixmap.width() + 2; + } else { + p->drawPixmap( x, 0, mBirthdayPixmap ); + x += mBirthdayPixmap.width() + 2; + } + // Do NOT put on the event pixmap because it takes up too much space + //} else { + // p->drawPixmap( x, 0, mEventPixmap ); + // x += mEventPixmap.width() + 2; + // + } + } + if ( mTodo ) { p->drawPixmap( x, 0, mTodoPixmap ); x += mTodoPixmap.width() + 2; @@ -249,11 +333,11 @@ void MonthViewItem::paint( TQPainter *p ) p->drawPixmap( x, 0, mTodoDonePixmap ); x += mTodoPixmap.width() + 2; } - if ( mRecur ) { + if ( mRecur && !specialEvent ) { p->drawPixmap( x, 0, mRecurPixmap ); x += mRecurPixmap.width() + 2; } - if ( mAlarm ) { + if ( mAlarm && !specialEvent ) { p->drawPixmap( x, 0, mAlarmPixmap ); x += mAlarmPixmap.width() + 2; } @@ -300,7 +384,8 @@ int MonthViewItem::width( const TQListBox *lb ) const MonthViewCell::MonthViewCell( KOMonthView *parent) : TQWidget( parent ), - mMonthView( parent ), mPrimary( false ), mHoliday( false ) + mMonthView( parent ), mPrimary( false ), mHoliday( false ), + isSelected( false ) { TQVBoxLayout *topLayout = new TQVBoxLayout( this ); @@ -314,9 +399,6 @@ MonthViewCell::MonthViewCell( KOMonthView *parent) mItemList->setFrameStyle( TQFrame::Panel | TQFrame::Plain ); mItemList->setLineWidth( 1 ); - new KOMonthCellToolTip( mItemList->viewport(), - static_cast<KNoScrollListBox *>( mItemList ) ); - topLayout->addWidget( mItemList ); mLabel->raise(); @@ -357,6 +439,11 @@ void MonthViewCell::setDate( const TQDate &date ) } mLabel->setText( text ); + new KOMonthCellToolTip( mItemList->viewport(), + monthView()->calendar(), + mDate, + static_cast<KNoScrollListBox *>( mItemList ) ); + resizeEvent( 0 ); } @@ -368,10 +455,11 @@ TQDate MonthViewCell::date() const void MonthViewCell::setFrameWidth() { // show current day with a thicker frame - if ( mDate == TQDate::currentDate() ) + if ( mDate == TQDate::currentDate() ) { mItemList->setLineWidth( 3 ); - else + } else if ( !isSelected ) { mItemList->setLineWidth( 1 ); + } } void MonthViewCell::setPrimary( bool primary ) @@ -490,13 +578,16 @@ class MonthViewCell::CreateItemVisitor : mItem = new MonthViewItem( event, dt, text ); mItem->setEvent( true ); - if (KOPrefs::instance()->monthViewUsesCategoryColor()) { + if ( KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemCategoryOnly || + KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemCategoryInsideResourceOutside ) { TQStringList categories = event->categories(); TQString cat = categories.first(); if (cat.isEmpty()) { - mItem->setPalette(TQPalette(KOPrefs::instance()->mEventColor, KOPrefs::instance()->mEventColor)); + mItem->setPalette(TQPalette(KOPrefs::instance()->unsetCategoryColor(), + KOPrefs::instance()->unsetCategoryColor()) ); } else { - mItem->setPalette(TQPalette(*(KOPrefs::instance()->categoryColor(cat)), *(KOPrefs::instance()->categoryColor(cat)))); + mItem->setPalette(TQPalette(*(KOPrefs::instance()->categoryColor(cat)), + *(KOPrefs::instance()->categoryColor(cat)))); } } else { mItem->setPalette( mStandardPalette ); @@ -514,7 +605,8 @@ class MonthViewCell::CreateItemVisitor : if ( !KOPrefs::instance()->showAllDayTodo() ) return false; TQDateTime dt( mDate ); - if ( todo->hasDueDate() && !todo->doesFloat() ) { + if ( todo->hasDueDate() && !todo->doesFloat() && + todo->dtDue().time() != TQTime( 0,0 ) && todo->dtDue().time().isValid() ) { text += KGlobal::locale()->formatTime( todo->dtDue().time() ); text += ' '; dt.setTime( todo->dtDue().time() ); @@ -547,9 +639,9 @@ void MonthViewCell::addIncidence( Incidence *incidence, CreateItemVisitor& v, in item->setAlarm( incidence->isAlarmEnabled() ); item->setRecur( incidence->recurrenceType() ); - TQColor resourceColor = KOHelper::resourceColor( mCalendar, incidence ); + TQColor resourceColor = KOHelper::resourceColor( monthView()->calendar(), incidence ); if ( !resourceColor.isValid() ) - resourceColor = KOPrefs::instance()->mEventColor; + resourceColor = KOPrefs::instance()->unsetCategoryColor(); item->setResourceColor( resourceColor ); // FIXME: Find the correct position (time-wise) to insert the item. @@ -661,6 +753,9 @@ TQDate MonthViewCell::selectedIncidenceDate() void MonthViewCell::select() { + + isSelected = true; + // setSelectedCell will deselect currently selected cells mMonthView->setSelectedCell( this ); @@ -676,6 +771,8 @@ void MonthViewCell::select() void MonthViewCell::deselect() { + isSelected = false; + mItemList->clearSelection(); mItemList->setFrameStyle( TQFrame::Plain | TQFrame::Panel ); setFrameWidth(); @@ -693,7 +790,7 @@ void MonthViewCell::defaultAction( TQListBoxItem *item ) select(); if ( !item ) { - emit newEventSignal( date() ); + emit newEventSignal( 0/*ResourceCalendar*/, TQString()/*subResource*/, date() ); } else { MonthViewItem *eventItem = static_cast<MonthViewItem *>( item ); Incidence *incidence = eventItem->incidence(); @@ -708,9 +805,10 @@ void MonthViewCell::contextMenu( TQListBoxItem *item ) if ( item ) { MonthViewItem *eventItem = static_cast<MonthViewItem *>( item ); Incidence *incidence = eventItem->incidence(); - if ( incidence ) mMonthView->showEventContextMenu( incidence, date() ); - } - else { + if ( incidence ) { + mMonthView->showEventContextMenu( monthView()->calendar(), incidence, mDate ); + } + } else { mMonthView->showGeneralContextMenu(); } } @@ -764,14 +862,13 @@ KOMonthView::KOMonthView( Calendar *calendar, TQWidget *parent, const char *name for( row = 0; row < mNumWeeks; ++row ) { for( col = 0; col < mDaysPerWeek; ++col ) { MonthViewCell *cell = new MonthViewCell( this ); - cell->setCalendar(calendar); mCells.insert( row * mDaysPerWeek + col, cell ); dayLayout->addWidget( cell, row + 2, col ); - connect( cell, TQT_SIGNAL( defaultAction( Incidence * ) ), - TQT_SLOT( defaultAction( Incidence * ) ) ); - connect( cell, TQT_SIGNAL( newEventSignal( const TQDate & ) ), - TQT_SIGNAL( newEventSignal( const TQDate & ) ) ); + connect( cell, TQT_SIGNAL(defaultAction(Incidence *)), + TQT_SLOT(defaultAction(Incidence *)) ); + connect( cell, TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &,const TQDate &)), + TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &,const TQDate &)) ); } dayLayout->setRowStretch( row + 2, 1 ); } @@ -780,7 +877,7 @@ KOMonthView::KOMonthView( Calendar *calendar, TQWidget *parent, const char *name updateConfig(); - emit incidenceSelected( 0 ); + emit incidenceSelected( 0, TQDate() ); } KOMonthView::~KOMonthView() @@ -810,7 +907,7 @@ Incidence::List KOMonthView::selectedIncidences() return selected; } -DateList KOMonthView::selectedDates() +DateList KOMonthView::selectedIncidenceDates() { DateList selected; @@ -851,6 +948,8 @@ void KOMonthView::updateConfig() for ( uint i = 0; i < mCells.count(); ++i ) { mCells[i]->updateConfig(); } + + showLabel( !KOPrefs::instance()->fullViewMonth() ); } void KOMonthView::updateDayLabels() @@ -883,11 +982,8 @@ void KOMonthView::showDates( const TQDate &start, const TQDate & ) mLabel->setText( i18n( "monthname year", "%1 %2" ) .arg( calSys->monthName( start ) ) .arg( calSys->year( start ) ) ); - if ( !KOPrefs::instance()->fullViewMonth() ) { - mLabel->show(); - } else { - mLabel->hide(); - } + + showLabel( !KOPrefs::instance()->fullViewMonth() ); bool primary = false; uint i; @@ -899,8 +995,9 @@ void KOMonthView::showDates( const TQDate &start, const TQDate & ) mCells[i]->setDate( date ); mDateToCell[ date ] = mCells[ i ]; - if( date == start ) + if( date == start ) { mCells[i]->select(); + } mCells[i]->setPrimary( primary ); @@ -916,7 +1013,22 @@ void KOMonthView::showDates( const TQDate &start, const TQDate & ) updateView(); } -void KOMonthView::showIncidences( const Incidence::List & ) +TQDateTime KOMonthView::selectionStart() +{ + if ( mSelectedCell) { + return TQDateTime( mSelectedCell->date() ); + } else { + return TQDateTime(); + } +} + +TQDateTime KOMonthView::selectionEnd() +{ + // Only one cell can be selected (for now) + return selectionStart(); +} + +void KOMonthView::showIncidences( const Incidence::List &, const TQDate & ) { kdDebug(5850) << "KOMonthView::showIncidences( const Incidence::List & ) is not implemented yet." << endl; } @@ -941,8 +1053,14 @@ class KOMonthView::GetDateVisitor : public IncidenceBase::Visitor } bool visit( Todo *todo ) { if ( todo->hasDueDate() ) { - mStartDate = todo->dtDue(); - mEndDate = todo->dtDue(); + if ( todo->dtDue().time() != TQTime( 0, 0 ) && + todo->dtDue().time().isValid() ) { + mStartDate = todo->dtDue(); + mEndDate = todo->dtDue(); + } else { + mStartDate = TQDateTime( todo->dtDue().date(), TQTime( 23,59 ) ); + mEndDate = mStartDate; + } }// else // return false; return true; @@ -1048,9 +1166,9 @@ void KOMonthView::resizeEvent( TQResizeEvent * ) } } -void KOMonthView::showEventContextMenu( Incidence *incidence, const TQDate &qd ) +void KOMonthView::showEventContextMenu( Calendar *cal, Incidence *incidence, const TQDate &qd ) { - mEventContextMenu->showIncidencePopup( incidence, qd ); + mEventContextMenu->showIncidencePopup( cal, incidence, qd ); } void KOMonthView::showGeneralContextMenu() @@ -1066,18 +1184,26 @@ void KOMonthView::setSelectedCell( MonthViewCell *cell ) mSelectedCell = cell; if ( !mSelectedCell ) - emit incidenceSelected( 0 ); + emit incidenceSelected( 0, TQDate() ); else - emit incidenceSelected( mSelectedCell->selectedIncidence() ); + if ( selectedIncidenceDates().isEmpty() ) { + emit incidenceSelected( mSelectedCell->selectedIncidence(), TQDate() ); + } else { + emit incidenceSelected( mSelectedCell->selectedIncidence(), selectedIncidenceDates().first() ); + } } void KOMonthView::processSelectionChange() { Incidence::List incidences = selectedIncidences(); if (incidences.count() > 0) { - emit incidenceSelected( incidences.first() ); + if ( selectedIncidenceDates().isEmpty() ) { + emit incidenceSelected( incidences.first(), TQDate() ); + } else { + emit incidenceSelected( incidences.first(), selectedIncidenceDates().first() ); + } } else { - emit incidenceSelected( 0 ); + emit incidenceSelected( 0, TQDate() ); } } @@ -1088,3 +1214,12 @@ void KOMonthView::clearSelection() mSelectedCell = 0; } } + +void KOMonthView::showLabel( bool show ) +{ + if ( show ) { + mLabel->show(); + } else { + mLabel->hide(); + } +} diff --git a/korganizer/komonthview.h b/korganizer/komonthview.h index 9a3015d03..dafce597f 100644 --- a/korganizer/komonthview.h +++ b/korganizer/komonthview.h @@ -36,12 +36,14 @@ class KNoScrollListBox; class KOMonthCellToolTip : public QToolTip { public: - KOMonthCellToolTip (TQWidget* parent, KNoScrollListBox* lv ); + KOMonthCellToolTip (TQWidget* parent, Calendar *calendar, const TQDate &date, KNoScrollListBox* lv ); protected: void maybeTip( const TQPoint & pos); private: + Calendar *mCalendar; + TQDate mDate; KNoScrollListBox* eventlist; }; @@ -107,6 +109,8 @@ class MonthViewItem: public QListBoxItem bool mReply; TQPixmap mEventPixmap; + TQPixmap mBirthdayPixmap; + TQPixmap mAnniversaryPixmap; TQPixmap mTodoPixmap; TQPixmap mTodoDonePixmap; TQPixmap mAlarmPixmap; @@ -117,6 +121,7 @@ class MonthViewItem: public QListBoxItem TQDateTime mDateTime; Incidence *mIncidence; + TQColor catColor() const; }; @@ -138,6 +143,9 @@ class MonthViewCell : public QWidget /** @return Date of cell */ TQDate date() const; + /** @return MonthView parent */ + KOMonthView *monthView() { return mMonthView; } + /** Set this cell as primary if @p primary is true. A primary cell belongs to the current month. A non-primary cell belongs to the month before or @@ -184,7 +192,6 @@ class MonthViewCell : public QWidget void deselect(); - void setCalendar( Calendar*cal ) { mCalendar = cal; } signals: void defaultAction( Incidence * ); /** @@ -192,7 +199,8 @@ class MonthViewCell : public QWidget will pop up. @param date The date of the event we want create. */ - void newEventSignal( const TQDate &date ); + void newEventSignal( ResourceCalendar *res,const TQString &subResource, + const TQDate &date ); public slots: void select(); @@ -207,8 +215,6 @@ class MonthViewCell : public QWidget private: KOMonthView *mMonthView; - // We need the calendar for paint the ResourceColor - Calendar *mCalendar; TQDate mDate; bool mPrimary; @@ -218,6 +224,8 @@ class MonthViewCell : public QWidget TQLabel *mLabel; KNoScrollListBox *mItemList; + bool isSelected; + TQSize mLabelSize; // TQPalette mOriginalPalette; TQPalette mHolidayPalette; @@ -249,7 +257,11 @@ class KOMonthView: public KOEventView virtual Incidence::List selectedIncidences(); /** Returns dates of the currently selected events */ - virtual DateList selectedDates(); + virtual DateList selectedIncidenceDates(); + + virtual TQDateTime selectionStart(); + + virtual TQDateTime selectionEnd(); virtual bool eventDurationHint(TQDateTime &startDt, TQDateTime &endDt, bool &allDay); @@ -257,14 +269,14 @@ class KOMonthView: public KOEventView virtual void updateView(); virtual void updateConfig(); virtual void showDates(const TQDate &start, const TQDate &end); - virtual void showIncidences( const Incidence::List &incidenceList ); + virtual void showIncidences( const Incidence::List &incidenceList, const TQDate &date ); void changeIncidenceDisplay(Incidence *, int); void changeIncidenceDisplayAdded(Incidence *, MonthViewCell::CreateItemVisitor&); void clearSelection(); - void showEventContextMenu( Incidence *, const TQDate & ); + void showEventContextMenu( Calendar *, Incidence *, const TQDate & ); void showGeneralContextMenu(); void setSelectedCell( MonthViewCell * ); @@ -279,6 +291,8 @@ class KOMonthView: public KOEventView void updateDayLabels(); private: + void showLabel( bool show ); + class GetDateVisitor; int mDaysPerWeek; int mNumWeeks; diff --git a/korganizer/koprefs.cpp b/korganizer/koprefs.cpp index 3532b1cc1..535fe1045 100644 --- a/korganizer/koprefs.cpp +++ b/korganizer/koprefs.cpp @@ -88,12 +88,9 @@ KOPrefs::KOPrefs() : timeBarFontItem()->setDefaultValue( mDefaultTimeBarFont ); monthViewFontItem()->setDefaultValue( mDefaultMonthViewFont ); - eventColorItem()->setDefaultValue( mDefaultCategoryColor ); // Load it now, not deep within some painting code mMyAddrBookMails = KABC::StdAddressBook::self()->whoAmI().emails(); - - mAlarmsEnabledByDefault = false; } @@ -202,8 +199,8 @@ void KOPrefs::usrReadConfig() TQMapIterator<TQString, TQString> it3; for( it3 = map.begin(); it3 != map.end(); ++it3 ) { - kdDebug(5850)<< "KOPrefs::usrReadConfig: key: " << it3.key() << " value: " - << it3.data()<<endl; + // kdDebug(5850)<< "KOPrefs::usrReadConfig: key: " << it3.key() << " value: " + // << it3.data()<<endl; setResourceColor( it3.key(), config()->readColorEntry( it3.key(), &mDefaultResourceColor ) ); } @@ -213,9 +210,6 @@ void KOPrefs::usrReadConfig() setTimeZoneIdDefault(); } - config()->setGroup("Event Dialogs"); - mAlarmsEnabledByDefault = config()->readBoolEntry( "Alarm Enabled By Default" ); - #if 0 config()->setGroup("FreeBusy"); if( mRememberRetrievePw ) @@ -256,9 +250,6 @@ void KOPrefs::usrWriteConfig() i->writeConfig( config() ); } - config()->setGroup("Event Dialogs"); - config()->writeEntry( "Alarm Enabled By Default", mAlarmsEnabledByDefault ); - #if 0 if( mRememberRetrievePw ) config()->writeEntry( "Retrieve Server Password", KStringHandler::obscure( mRetrievePassword ) ); @@ -292,8 +283,8 @@ bool KOPrefs::hasCategoryColor( const TQString& cat ) const void KOPrefs::setResourceColor ( const TQString &cal, const TQColor &color ) { - kdDebug(5850)<<"KOPrefs::setResourceColor: " << cal << " color: "<< - color.name()<<endl; + // kdDebug(5850)<<"KOPrefs::setResourceColor: " << cal << " color: "<< + // color.name()<<endl; mResourceColors.replace( cal, new TQColor( color ) ); } @@ -327,12 +318,21 @@ TQColor* KOPrefs::resourceColor( const TQString &cal ) TQString KOPrefs::fullName() { + TQString tusername; if ( mEmailControlCenter ) { KEMailSettings settings; - return settings.getSetting( KEMailSettings::RealName ); + tusername = settings.getSetting( KEMailSettings::RealName ); } else { - return userName(); + tusername = userName(); } + + // Quote the username as it might contain commas and other quotable chars. + tusername = KPIM::quoteNameIfNecessary( tusername ); + + TQString tname, temail; + KPIM::getNameAndMail( tusername, tname, temail ); // ignore return value + // which is always false + return tname; } TQString KOPrefs::email() @@ -415,8 +415,11 @@ bool KOPrefs::thatIsMe( const TQString& _email ) for ( KPIM::IdentityManager::ConstIterator it = KOCore::self()->identityManager()->begin(); it != KOCore::self()->identityManager()->end(); ++it ) { - if ( email == (*it).emailAddr() ) + if ( email == (*it).primaryEmailAddress() ) return true; + const TQStringList & aliases = (*it).emailAliases(); + if ( aliases.find( email ) != aliases.end() ) + return true; } if ( mAdditionalMails.find( email ) != mAdditionalMails.end() ) diff --git a/korganizer/koprefs.h b/korganizer/koprefs.h index 48a42cbd5..fcda71437 100644 --- a/korganizer/koprefs.h +++ b/korganizer/koprefs.h @@ -91,7 +91,6 @@ class KDE_EXPORT KOPrefs : public KOPrefsBase TQColor* resourceColor( const TQString & ); TQString mHtmlExportFile; - bool mAlarmsEnabledByDefault; // Groupware passwords TQString mPublishPassword; diff --git a/korganizer/koprefsdialog.cpp b/korganizer/koprefsdialog.cpp index 0205b59ea..37f889cfb 100644 --- a/korganizer/koprefsdialog.cpp +++ b/korganizer/koprefsdialog.cpp @@ -44,20 +44,24 @@ #include <tqwhatsthis.h> #include <kcolorbutton.h> +#include <kcombobox.h> #include <kdebug.h> #include <klocale.h> #include <kglobal.h> #include <kmessagebox.h> #include <kiconloader.h> +#include <knuminput.h> #include <kemailsettings.h> #include <kcalendarsystem.h> #include <ktrader.h> #include <kpushbutton.h> #include <kocore.h> -#include <libkcal/calendarresources.h> #include <kstandarddirs.h> #include <ksimpleconfig.h> #include <kholidays.h> +#include <kurlrequester.h> + +#include <libkcal/calendarresources.h> #if defined(USE_SOLARIS) #include <sys/param.h> @@ -315,21 +319,46 @@ class KOPrefsDialogTime : public KPrefsModule topLayout->addWidget( defaultDuration->label(), 4, 0 ); topLayout->addWidget( defaultDuration->timeEdit(), 4, 1 ); - TQStringList alarmList; - alarmList << i18n( "1 minute" ) << i18n( "5 minutes" ) - << i18n( "10 minutes" ) << i18n( "15 minutes" ) - << i18n( "30 minutes" ); - TQLabel *alarmLabel = new TQLabel( i18n( "Default reminder time:" ), topFrame); - topLayout->addWidget( alarmLabel, 5, 0 ); - TQWhatsThis::add( alarmLabel, - i18n( "Enter the default reminder time here." ) ); - mAlarmTimeCombo = new TQComboBox( topFrame ); - TQWhatsThis::add( mAlarmTimeCombo, - i18n( "Enter the default reminder time here." ) ); - connect( mAlarmTimeCombo, TQT_SIGNAL( activated( int ) ), - TQT_SLOT( slotWidChanged() ) ); - mAlarmTimeCombo->insertStringList( alarmList ); - topLayout->addWidget( mAlarmTimeCombo, 5, 1 ); + TQGroupBox *remindersGroupBox = new TQGroupBox( 1, Horizontal, + i18n( "Reminders" ), + topFrame ); + topLayout->addMultiCellWidget( remindersGroupBox, 5, 5, 0, 1 ); + + TQHBox *remindersBox = new TQHBox( remindersGroupBox ); + new TQLabel( i18n( "Default reminder time:" ), remindersBox ); + + mReminderTimeSpin = new KIntSpinBox( remindersBox ); + connect( mReminderTimeSpin, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotWidChanged()) ); + + mReminderUnitsCombo = new KComboBox( remindersBox ); + connect( mReminderUnitsCombo, TQT_SIGNAL(activated(int)), TQT_SLOT(slotWidChanged()) ); + mReminderUnitsCombo->insertItem( i18n( "minute(s)" ) ); + mReminderUnitsCombo->insertItem( i18n( "hour(s)" ) ); + mReminderUnitsCombo->insertItem( i18n( "day(s)" ) ); + + TQHBox *audioFileRemindersBox = new TQHBox( remindersGroupBox ); + + TQCheckBox *cb = addWidBool( KOPrefs::instance()->defaultAudioFileRemindersItem(), + audioFileRemindersBox )->checkBox(); + cb->setText( TQString::null ); + + if ( KOPrefs::instance()->audioFilePathItem()->value().isEmpty() ) { + TQString defAudioFile = KGlobal::dirs()->findResourceDir( "sound", "KDE-Sys-Warning.ogg"); + KOPrefs::instance()->audioFilePathItem()->setValue( defAudioFile + "KDE-Sys-Warning.ogg" ); + } + TQString filter = i18n( "*.ogg *.wav *.mp3 *.wma *.flac *.aiff *.raw *.au *.ra|" + "Audio Files (*.ogg *.wav *.mp3 *.wma *.flac *.aiff *.raw *.au *.ra)" ); + KURLRequester *rq = addWidPath( KOPrefs::instance()->audioFilePathItem(), + audioFileRemindersBox, filter )->urlRequester(); + rq->setEnabled( cb->isChecked() ); + connect( cb, TQT_SIGNAL(toggled(bool)), + rq, TQT_SLOT(setEnabled( bool)) ); + + TQHBox *eventRemindersBox = new TQHBox( remindersGroupBox ); + addWidBool( KOPrefs::instance()->defaultEventRemindersItem(), eventRemindersBox )->checkBox(); + + TQHBox *todoRemindersBox = new TQHBox( remindersGroupBox ); + addWidBool( KOPrefs::instance()->defaultTodoRemindersItem(), todoRemindersBox )->checkBox(); TQLabel *alarmDefaultLabel = new TQLabel( i18n( "Enable reminders by default:" ), topFrame); topLayout->addWidget( alarmDefaultLabel, 6, 0 ); @@ -386,8 +415,9 @@ class KOPrefsDialogTime : public KPrefsModule setCombo( mTimeZoneCombo, i18n( KOPrefs::instance()->mTimeZoneId.utf8() ) ); - mAlarmTimeCombo->setCurrentItem( KOPrefs::instance()->mAlarmTime ); - mAlarmTimeDefaultCheckBox->setChecked ( KOPrefs::instance()->mAlarmsEnabledByDefault ); + mReminderTimeSpin->setValue( KOPrefs::instance()->mReminderTime ); + mReminderUnitsCombo->setCurrentItem( KOPrefs::instance()->mReminderTimeUnits ); + for ( int i = 0; i < 7; ++i ) { mWorkDays[i]->setChecked( (1<<i) & (KOPrefs::instance()->mWorkWeekMask) ); } @@ -409,8 +439,9 @@ class KOPrefsDialogTime : public KPrefsModule TQString::null : mRegionMap[mHolidayCombo->currentText()]; - KOPrefs::instance()->mAlarmTime = mAlarmTimeCombo->currentItem(); - KOPrefs::instance()->mAlarmsEnabledByDefault = mAlarmTimeDefaultCheckBox->isChecked(); + KOPrefs::instance()->mReminderTime = mReminderTimeSpin->value(); + KOPrefs::instance()->mReminderTimeUnits = mReminderUnitsCombo->currentItem(); + int mask = 0; for ( int i = 0; i < 7; ++i ) { if (mWorkDays[i]->isChecked()) mask = mask | (1<<i); @@ -440,7 +471,8 @@ class KOPrefsDialogTime : public KPrefsModule TQStringList tzonenames; TQComboBox *mHolidayCombo; TQMap<TQString,TQString> mRegionMap; - TQComboBox *mAlarmTimeCombo; + KIntSpinBox *mReminderTimeSpin; + KComboBox *mReminderUnitsCombo; TQCheckBox *mAlarmTimeDefaultCheckBox; TQCheckBox *mWorkDays[7]; }; @@ -483,6 +515,7 @@ class KOPrefsDialogViews : public KPrefsModule topFrame ); addWidBool( KOPrefs::instance()->dailyRecurItem(), dateNavGroup ); addWidBool( KOPrefs::instance()->weeklyRecurItem(), dateNavGroup ); + addWidBool( KOPrefs::instance()->weekNumbersShowWorkItem(), dateNavGroup ); topLayout->addWidget( dateNavGroup ); @@ -520,20 +553,14 @@ class KOPrefsDialogViews : public KPrefsModule topLayout->addWidget( agendaGroup ); - /*** Month and Todo view groups side by side, to save space. ***/ - TQHBoxLayout *hbox = new TQHBoxLayout(); - topLayout->addLayout( hbox ); - /*** Month View Group ***/ TQGroupBox *monthGroup = new TQGroupBox( 1, Horizontal, i18n("Month View"), topFrame ); addWidBool( KOPrefs::instance()->enableMonthScrollItem(), monthGroup ); addWidBool( KOPrefs::instance()->fullViewMonthItem(), monthGroup ); - addWidBool( KOPrefs::instance()->monthViewUsesCategoryColorItem(), - monthGroup ); - addWidBool( KOPrefs::instance()->monthViewUsesResourceColorItem(), monthGroup ); - hbox->addWidget( monthGroup ); + addWidCombo( KOPrefs::instance()->monthItemColorsItem(), monthGroup ); + topLayout->addWidget( monthGroup ); /*** Todo View Group ***/ @@ -542,7 +569,7 @@ class KOPrefsDialogViews : public KPrefsModule topFrame ); addWidBool( KOPrefs::instance()->fullViewTodoItem(), todoGroup ); addWidBool( KOPrefs::instance()->recordTodosInJournalsItem(), todoGroup ); - hbox->addWidget( todoGroup ); + topLayout->addWidget( todoGroup ); topLayout->addStretch( 1 ); @@ -642,40 +669,42 @@ KOPrefsDialogColors::KOPrefsDialogColors( TQWidget *parent, const char *name ) topLayout->addWidget(highlightColor->label(),1,0); topLayout->addWidget(highlightColor->button(),1,1); - KPrefsWidColor *eventColor = - addWidColor( KOPrefs::instance()->eventColorItem(), topFrame ); - topLayout->addWidget(eventColor->label(),2,0); - topLayout->addWidget(eventColor->button(),2,1); - // agenda view background color KPrefsWidColor *agendaBgColor = addWidColor( KOPrefs::instance()->agendaBgColorItem(), topFrame ); - topLayout->addWidget(agendaBgColor->label(),3,0); - topLayout->addWidget(agendaBgColor->button(),3,1); + topLayout->addWidget(agendaBgColor->label(),2,0); + topLayout->addWidget(agendaBgColor->button(),2,1); // working hours color KPrefsWidColor *workingHoursColor = addWidColor( KOPrefs::instance()->workingHoursColorItem(), topFrame ); - topLayout->addWidget(workingHoursColor->label(),4,0); - topLayout->addWidget(workingHoursColor->button(),4,1); + topLayout->addWidget(workingHoursColor->label(),3,0); + topLayout->addWidget(workingHoursColor->button(),3,1); // Todo due today color KPrefsWidColor *todoDueTodayColor = addWidColor( KOPrefs::instance()->todoDueTodayColorItem(), topFrame ); - topLayout->addWidget(todoDueTodayColor->label(),5,0); - topLayout->addWidget(todoDueTodayColor->button(),5,1); + topLayout->addWidget(todoDueTodayColor->label(),4,0); + topLayout->addWidget(todoDueTodayColor->button(),4,1); // Todo overdue color KPrefsWidColor *todoOverdueColor = addWidColor( KOPrefs::instance()->todoOverdueColorItem(), topFrame ); - topLayout->addWidget(todoOverdueColor->label(),6,0); - topLayout->addWidget(todoOverdueColor->button(),6,1); + topLayout->addWidget(todoOverdueColor->label(),5,0); + topLayout->addWidget(todoOverdueColor->button(),5,1); + + // "No Category" color + KPrefsWidColor *unsetCategoryColor = + addWidColor( KOPrefs::instance()->unsetCategoryColorItem(), topFrame ); + topLayout->addWidget( unsetCategoryColor->label(), 6, 0 ); + topLayout->addWidget( unsetCategoryColor->button(), 6, 1 ); // categories colors TQGroupBox *categoryGroup = new TQGroupBox(1,Horizontal,i18n("Categories"), topFrame); topLayout->addMultiCellWidget(categoryGroup,7,7,0,1); + mCategoryCombo = new TQComboBox(categoryGroup); mCategoryCombo->insertStringList(KOPrefs::instance()->mCustomCategories); TQWhatsThis::add( mCategoryCombo, @@ -1031,6 +1060,11 @@ void KOPrefsDialogGroupwareScheduling::usrWriteConfig() KOPrefs::instance()->mFreeBusyRetrieveUser = mGroupwarePage->retrieveUser->text(); KOPrefs::instance()->mFreeBusyRetrievePassword = mGroupwarePage->retrievePassword->text(); KOPrefs::instance()->mFreeBusyRetrieveSavePassword = mGroupwarePage->retrieveSavePassword->isChecked(); + + // clear the url cache for our user + TQString configFile = locateLocal( "data", "korganizer/freebusyurls" ); + KConfig cfg( configFile ); + cfg.deleteGroup( KOPrefs::instance()->email() ); } extern "C" diff --git a/korganizer/korgac/alarmdialog.cpp b/korganizer/korgac/alarmdialog.cpp index 6c9d62e90..839d463a9 100644 --- a/korganizer/korgac/alarmdialog.cpp +++ b/korganizer/korgac/alarmdialog.cpp @@ -2,6 +2,7 @@ This file is part of the KOrganizer alarm daemon. Copyright (c) 2000,2003 Cornelius Schumacher <schumacher@kde.org> + Copyright (c) 2009-2010 Klar�lvdalens Datakonsult AB, a KDAB Group company <info@kdab.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,11 +32,14 @@ #include <tqpushbutton.h> #include <tqcstring.h> #include <tqdatastream.h> +#include <tqsplitter.h> +#include <dcopclient.h> +#include <dcopref.h> #include <kapplication.h> #include <kconfig.h> +#include <kdcopservicestarter.h> #include <kiconloader.h> -#include <dcopclient.h> #include <klocale.h> #include <kprocess.h> #include <kaudioplayer.h> @@ -48,64 +52,97 @@ #include <klockfile.h> #include <libkcal/event.h> +#include <libkcal/incidenceformatter.h> #include "koeventviewer.h" #include "alarmdialog.h" #include "alarmdialog.moc" +static int defSuspendVal = 5; +static int defSuspendUnit = 0; // 0=>minutes, 1=>hours, 2=>days, 3=>weeks + class AlarmListItem : public KListViewItem { public: - AlarmListItem( Incidence *incidence, TQListView *parent ) : - KListViewItem( parent ), - mIncidence( incidence->clone() ), - mNotified( false ) - {} + AlarmListItem( const TQString &uid, TQListView *parent ) + : KListViewItem( parent ), mUid( uid ), mNotified( false ) + { + } ~AlarmListItem() { - delete mIncidence; } - Incidence *mIncidence; + int compare( TQListViewItem *item, int iCol, bool bAscending ) const; + + TQString mDisplayText; + + TQString mUid; TQDateTime mRemindAt; + TQDateTime mHappening; bool mNotified; }; +int AlarmListItem::compare( TQListViewItem *item, int iCol, bool bAscending ) const +{ + if ( iCol == 1 ) { + AlarmListItem *pItem = static_cast<AlarmListItem *>( item ); + return pItem->mHappening.secsTo( mHappening ); + } else { + return KListViewItem::compare( item, iCol, bAscending ); + } +} + typedef TQValueList<AlarmListItem*> ItemList; -AlarmDialog::AlarmDialog( TQWidget *parent, const char *name ) - : KDialogBase( Plain, WType_TopLevel | WStyle_Customize | WStyle_StaysOnTop | - WStyle_DialogBorder, - parent, name, false, i18n("Reminder"), Ok | User1 | User2 | User3, User1/*3*/, - false, i18n("Dismiss all"), i18n("Edit..."), i18n("Suspend") ), - mSuspendTimer(this) +AlarmDialog::AlarmDialog( KCal::CalendarResources *calendar, TQWidget *parent, const char *name ) + : KDialogBase( Plain, + WType_TopLevel | WStyle_Customize | WStyle_StaysOnTop | WStyle_DialogBorder, + parent, name, false, i18n("Reminder"), + Ok | User1 | User2 | User3, NoDefault, + false, i18n("Edit..."), i18n("Dismiss All"), i18n("Dismiss Reminder") ), + mCalendar( calendar ), mSuspendTimer(this) { + // User1 => Edit... + // User2 => Dismiss All + // User3 => Dismiss Selected + // Ok => Suspend + + connect( calendar, TQT_SIGNAL(calendarChanged()), + this, TQT_SLOT(slotCalendarChanged()) ); + KGlobal::iconLoader()->addAppDir( "kdepim" ); - setButtonOK( i18n( "Dismiss" ) ); + setButtonOK( i18n( "Suspend" ) ); TQWidget *topBox = plainPage(); TQBoxLayout *topLayout = new TQVBoxLayout( topBox ); topLayout->setSpacing( spacingHint() ); - TQLabel *label = new TQLabel( i18n("The following events triggered reminders:"), - topBox ); + TQLabel *label = new TQLabel( i18n("The following items triggered reminders:"), topBox ); topLayout->addWidget( label ); - mIncidenceListView = new KListView( topBox ); + mSplitter = new TQSplitter( TQt::Vertical, topBox ); + mSplitter->setOpaqueResize( KGlobalSettings::opaqueResize() ); + topLayout->addWidget( mSplitter ); + + mIncidenceListView = new KListView( mSplitter ); mIncidenceListView->addColumn( i18n( "Summary" ) ); - mIncidenceListView->addColumn( i18n( "Due" ) ); + mIncidenceListView->addColumn( i18n( "Date, Time" ) ); + mIncidenceListView->setSorting( 0, true ); + mIncidenceListView->setSorting( 1, true ); + mIncidenceListView->setSortColumn( 1 ); + mIncidenceListView->setShowSortIndicator( true ); mIncidenceListView->setAllColumnsShowFocus( true ); mIncidenceListView->setSelectionMode( TQListView::Extended ); - topLayout->addWidget( mIncidenceListView ); connect( mIncidenceListView, TQT_SIGNAL(selectionChanged()), TQT_SLOT(updateButtons()) ); - connect( mIncidenceListView, TQT_SIGNAL(doubleClicked(TQListViewItem*)), TQT_SLOT(slotUser2()) ); + connect( mIncidenceListView, TQT_SIGNAL(doubleClicked(TQListViewItem*)), TQT_SLOT(edit()) ); connect( mIncidenceListView, TQT_SIGNAL(currentChanged(TQListViewItem*)), TQT_SLOT(showDetails()) ); connect( mIncidenceListView, TQT_SIGNAL(selectionChanged()), TQT_SLOT(showDetails()) ); - mDetailView = new KOEventViewer( topBox ); - topLayout->addWidget( mDetailView ); + mDetailView = new KOEventViewer( mCalendar, mSplitter ); + mDetailView->setFocus(); // set focus here to start with to make it harder + // to hit return by mistake and dismiss a reminder. TQHBox *suspendBox = new TQHBox( topBox ); suspendBox->setSpacing( spacingHint() ); @@ -113,7 +150,7 @@ AlarmDialog::AlarmDialog( TQWidget *parent, const char *name ) TQLabel *l = new TQLabel( i18n("Suspend &duration:"), suspendBox ); mSuspendSpin = new TQSpinBox( 1, 9999, 1, suspendBox ); - mSuspendSpin->setValue( 5 ); // default suspend duration + mSuspendSpin->setValue( defSuspendVal ); // default suspend duration l->setBuddy( mSuspendSpin ); mSuspendUnit = new KComboBox( suspendBox ); @@ -121,11 +158,14 @@ AlarmDialog::AlarmDialog( TQWidget *parent, const char *name ) mSuspendUnit->insertItem( i18n("hour(s)") ); mSuspendUnit->insertItem( i18n("day(s)") ); mSuspendUnit->insertItem( i18n("week(s)") ); + mSuspendUnit->setCurrentItem( defSuspendUnit ); + connect( &mSuspendTimer, TQT_SIGNAL(timeout()), TQT_SLOT(wakeUp()) ); - // showButton( User2/*3*/, false ); + setMainWidget( mIncidenceListView ); + mIncidenceListView->setMinimumSize( 500, 50 ); - setMinimumSize( 300, 200 ); + readLayout(); } AlarmDialog::~AlarmDialog() @@ -133,26 +173,82 @@ AlarmDialog::~AlarmDialog() mIncidenceListView->clear(); } -void AlarmDialog::addIncidence( Incidence *incidence, const TQDateTime &reminderAt ) +AlarmListItem *AlarmDialog::searchByUid( const TQString &uid ) +{ + AlarmListItem *found = 0; + for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ) { + AlarmListItem *item = static_cast<AlarmListItem*>( it.current() ); + if ( item->mUid == uid ) { + found = item; + break; + } + ++it; + } + return found; +} + +static TQString etc = i18n( "elipsis", "..." ); +static TQString cleanSummary( const TQString &summary ) { - AlarmListItem *item = new AlarmListItem( incidence, mIncidenceListView ); - item->setText( 0, incidence->summary() ); + uint maxLen = 45; + TQString retStr = summary; + retStr.replace( '\n', ' ' ); + if ( retStr.length() > maxLen ) { + maxLen -= etc.length(); + retStr = retStr.left( maxLen ); + retStr += etc; + } + return retStr; +} + +void AlarmDialog::readLayout() +{ + KConfig *config = kapp->config(); + config->setGroup( "Layout" ); + TQValueList<int> sizes = config->readIntListEntry( "SplitterSizes" ); + if ( sizes.count() == 2 ) { + mSplitter->setSizes( sizes ); + } + mSplitter->setCollapsible( mIncidenceListView, false ); + mSplitter->setCollapsible( mDetailView, false ); +} + +void AlarmDialog::writeLayout() +{ + KConfig *config = kapp->config(); + config->setGroup( "Layout" ); + TQValueList<int> list = mSplitter->sizes(); + config->writeEntry( "SplitterSizes", list ); +} + +void AlarmDialog::addIncidence( Incidence *incidence, + const TQDateTime &reminderAt, + const TQString &displayText ) +{ + AlarmListItem *item = searchByUid( incidence->uid() ); + if ( !item ) { + item = new AlarmListItem( incidence->uid(), mIncidenceListView ); + } + item->mNotified = false; + item->mHappening = TQDateTime(); item->mRemindAt = reminderAt; - Todo *todo; - if ( dynamic_cast<Event*>( incidence ) ) { + item->mDisplayText = displayText; + item->setText( 0, cleanSummary( incidence->summary() ) ); + item->setText( 1, TQString() ); + + TQString displayStr; + const TQDateTime dateTime = triggerDateForIncidence( incidence, reminderAt, displayStr ); + + item->mHappening = dateTime; + item->setText( 1, displayStr ); + + if ( incidence->type() == "Event" ) { item->setPixmap( 0, SmallIcon( "appointment" ) ); - if ( incidence->doesRecur() ) { - TQDateTime nextStart = incidence->recurrence()->getNextDateTime( reminderAt ); - if ( nextStart.isValid() ) - item->setText( 1, KGlobal::locale()->formatDateTime( nextStart ) ); - } - if ( item->text( 1 ).isEmpty() ) - item->setText( 1, incidence->dtStartStr() ); - } else if ( (todo = dynamic_cast<Todo*>( incidence )) ) { + } else { item->setPixmap( 0, SmallIcon( "todo" ) ); - item->setText( 1, todo->dtDueStr() ); } - if ( activeCount() == 1 ) {// previously empty + + if ( activeCount() == 1 ) { // previously empty mIncidenceListView->clearSelection(); item->setSelected( true ); } @@ -161,6 +257,26 @@ void AlarmDialog::addIncidence( Incidence *incidence, const TQDateTime &reminder void AlarmDialog::slotOk() { + suspend(); +} + +void AlarmDialog::slotUser1() +{ + edit(); +} + +void AlarmDialog::slotUser2() +{ + dismissAll(); +} + +void AlarmDialog::slotUser3() +{ + dismissCurrent(); +} + +void AlarmDialog::dismissCurrent() +{ ItemList selection = selectedItems(); for ( ItemList::Iterator it = selection.begin(); it != selection.end(); ++it ) { if ( (*it)->itemBelow() ) @@ -169,18 +285,96 @@ void AlarmDialog::slotOk() (*it)->itemAbove()->setSelected( true ); delete *it; } - if ( activeCount() == 0 ) + if ( activeCount() == 0 ) { + writeLayout(); accept(); - else { + } else { updateButtons(); showDetails(); } emit reminderCount( activeCount() ); } -void AlarmDialog::slotUser1() +void AlarmDialog::dismissAll() { - dismissAll(); + for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ) { + AlarmListItem *item = static_cast<AlarmListItem*>( it.current() ); + if ( !item->isVisible() ) { + ++it; + continue; + } + mIncidenceListView->takeItem( item ); + delete item; + } + setTimer(); + writeLayout(); + accept(); + emit reminderCount( activeCount() ); +} + +void AlarmDialog::edit() +{ + ItemList selection = selectedItems(); + if ( selection.count() != 1 ) { + return; + } + Incidence *incidence = mCalendar->incidence( selection.first()->mUid ); + if ( !incidence ) { + return; + } + TQDate dt = selection.first()->mRemindAt.date(); + + if ( incidence->isReadOnly() ) { + KMessageBox::sorry( + this, + i18n( "\"%1\" is a read-only item so modifications are not possible." ). + arg( cleanSummary( incidence->summary() ) ) ); + return; + } + + if ( !ensureKorganizerRunning() ) { + KMessageBox::error( + this, + i18n( "Could not start KOrganizer so editing is not possible." ) ); + return; + } + + TQByteArray data; + TQDataStream arg( data, IO_WriteOnly ); + arg << incidence->uid(); + arg << dt; + //kdDebug(5890) << "editing incidence " << incidence->summary() << endl; + if ( !kapp->dcopClient()->send( "korganizer", "KOrganizerIface", + "editIncidence(TQString,TQDate)", + data ) ) { + KMessageBox::error( + this, + i18n( "An internal KOrganizer error occurred attempting to start the incidence editor" ) ); + return; + } + + // get desktop # where korganizer (or kontact) runs + TQByteArray replyData; + TQCString object, replyType; + object = kapp->dcopClient()->isApplicationRegistered( "kontact" ) ? + "kontact-mainwindow#1" : "KOrganizer MainWindow"; + if (!kapp->dcopClient()->call( "korganizer", object, + "getWinID()", 0, replyType, replyData, true, -1 ) ) { + } + + if ( replyType == "int" ) { + int desktop, window; + TQDataStream ds( replyData, IO_ReadOnly ); + ds >> window; + desktop = KWin::windowInfo( window ).desktop(); + + if ( KWin::currentDesktop() == desktop ) { + KWin::iconifyWindow( winId(), false ); + } else { + KWin::setCurrentDesktop( desktop ); + } + KWin::activateWindow( KWin::transientFor( window ) ); + } } void AlarmDialog::suspend() @@ -202,6 +396,7 @@ void AlarmDialog::suspend() break; } + AlarmListItem *selitem = 0; for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) { AlarmListItem * item = static_cast<AlarmListItem*>( it.current() ); if ( item->isSelected() && item->isVisible() ) { @@ -209,13 +404,26 @@ void AlarmDialog::suspend() item->setSelected( false ); item->mRemindAt = TQDateTime::currentDateTime().addSecs( unit * mSuspendSpin->value() ); item->mNotified = false; + selitem = item; } } + if ( selitem ) { + if ( selitem->itemBelow() ) { + selitem->itemBelow()->setSelected( true ); + } else if ( selitem->itemAbove() ) { + selitem->itemAbove()->setSelected( true ); + } + } + + // save suspended alarms too so they can be restored on restart + // kolab/issue4108 + slotSave(); setTimer(); - if ( activeCount() == 0 ) + if ( activeCount() == 0 ) { + writeLayout(); accept(); - else { + } else { updateButtons(); showDetails(); } @@ -239,76 +447,37 @@ void AlarmDialog::setTimer() } } -void AlarmDialog::slotUser2() -{ - ItemList selection = selectedItems(); - if ( selection.count() != 1 ) - return; - Incidence *incidence = selection.first()->mIncidence; - - if ( !kapp->dcopClient()->isApplicationRegistered( "korganizer" ) ) { - if ( kapp->startServiceByDesktopName( "korganizer", TQString::null ) ) - KMessageBox::error( 0, i18n("Could not start KOrganizer.") ); - } - - kapp->dcopClient()->send( "korganizer", "KOrganizerIface", - "editIncidence(TQString)", - incidence->uid() ); - - // get desktop # where korganizer (or kontact) runs - TQByteArray replyData; - TQCString object, replyType; - object = kapp->dcopClient()->isApplicationRegistered( "kontact" ) ? - "kontact-mainwindow#1" : "KOrganizer MainWindow"; - if (!kapp->dcopClient()->call( "korganizer", object, - "getWinID()", 0, replyType, replyData, true, -1 ) ) { - } - - if ( replyType == "int" ) { - int desktop, window; - TQDataStream ds( replyData, IO_ReadOnly ); - ds >> window; - desktop = KWin::windowInfo( window ).desktop(); - - if ( KWin::currentDesktop() == desktop ) { - KWin::iconifyWindow( winId(), false ); - } - else - KWin::setCurrentDesktop( desktop ); - - KWin::activateWindow( KWin::transientFor( window ) ); - } -} - -void AlarmDialog::slotUser3() +void AlarmDialog::show() { - suspend(); -} + mIncidenceListView->sort(); -void AlarmDialog::dismissAll() -{ - for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ) { + // select the first item that hasn't already been notified + mIncidenceListView->clearSelection(); + for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) { AlarmListItem *item = static_cast<AlarmListItem*>( it.current() ); - if ( !item->isVisible() ) { - ++it; - continue; + if ( !item->mNotified ) { + (*it)->setSelected( true ); + break; } - delete item; } - setTimer(); - accept(); - emit reminderCount( activeCount() ); -} -void AlarmDialog::show() -{ - mIncidenceListView->clearSelection(); - if ( mIncidenceListView->firstChild() ) - mIncidenceListView->firstChild()->setSelected( true ); updateButtons(); + showDetails(); + + // reset the default suspend time + mSuspendSpin->setValue( defSuspendVal ); + mSuspendUnit->setCurrentItem( defSuspendUnit ); + KDialogBase::show(); - KWin::setState( winId(), NET::KeepAbove ); + KWin::deIconifyWindow( winId(), false ); + KWin::setState( winId(), NET::KeepAbove | NET::DemandsAttention ); KWin::setOnAllDesktops( winId(), true ); + KWin::activateWindow( winId() ); + raise(); + setActiveWindow(); + if ( isMinimized() ) { + showNormal(); + } eventNotification(); } @@ -319,11 +488,16 @@ void AlarmDialog::eventNotification() TQValueList<AlarmListItem*> list; for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) { AlarmListItem *item = static_cast<AlarmListItem*>( it.current() ); - if ( !item->isVisible() || item->mNotified ) + if ( !item->isVisible() || item->mNotified ) { + continue; + } + Incidence *incidence = mCalendar->incidence( item->mUid ); + if ( !incidence ) { continue; + } found = true; item->mNotified = true; - Alarm::List alarms = item->mIncidence->alarms(); + Alarm::List alarms = incidence->alarms(); Alarm::List::ConstIterator it; for ( it = alarms.begin(); it != alarms.end(); ++it ) { Alarm *alarm = *it; @@ -351,7 +525,13 @@ void AlarmDialog::wakeUp() { bool activeReminders = false; for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) { - AlarmListItem * item = static_cast<AlarmListItem*>( it.current() ); + AlarmListItem *item = static_cast<AlarmListItem*>( it.current() ); + Incidence *incidence = mCalendar->incidence( item->mUid ); + if ( !incidence ) { + delete item; + continue; + } + if ( item->mRemindAt <= TQDateTime::currentDateTime() ) { if ( !item->isVisible() ) { item->setVisible( true ); @@ -381,9 +561,13 @@ void AlarmDialog::slotSave() int numReminders = config->readNumEntry("Reminders", 0); for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) { - AlarmListItem * item = static_cast<AlarmListItem*>( it.current() ); - config->setGroup( TQString("Incidence-%1").arg(numReminders) ); - config->writeEntry( "UID", item->mIncidence->uid() ); + AlarmListItem *item = static_cast<AlarmListItem*>( it.current() ); + Incidence *incidence = mCalendar->incidence( item->mUid ); + if ( !incidence ) { + continue; + } + config->setGroup( TQString("Incidence-%1").arg(numReminders + 1) ); + config->writeEntry( "UID", incidence->uid() ); config->writeEntry( "RemindAt", item->mRemindAt ); ++numReminders; } @@ -394,12 +578,19 @@ void AlarmDialog::slotSave() lock.data()->unlock(); } +void AlarmDialog::closeEvent( TQCloseEvent * ) +{ + slotSave(); + writeLayout(); + accept(); +} + void AlarmDialog::updateButtons() { ItemList selection = selectedItems(); - enableButton( User2, selection.count() == 1 ); - enableButton( Ok, selection.count() > 0 ); - enableButton( User3, selection.count() > 0 ); + enableButton( User1, selection.count() == 1 ); // can only edit 1 at a time + enableButton( User3, selection.count() > 0 ); // dismiss 1 or more + enableButton( Ok, selection.count() > 0 ); // suspend 1 or more } TQValueList< AlarmListItem * > AlarmDialog::selectedItems() const @@ -437,8 +628,113 @@ void AlarmDialog::showDetails() { mDetailView->clearEvents( true ); mDetailView->clear(); - AlarmListItem *item = static_cast<AlarmListItem*>( mIncidenceListView->currentItem() ); + AlarmListItem *item = static_cast<AlarmListItem*>( mIncidenceListView->selectedItems().first() ); if ( !item || !item->isVisible() ) return; - mDetailView->appendIncidence( item->mIncidence ); + + Incidence *incidence = mCalendar->incidence( item->mUid ); + if ( !incidence ) { + return; + } + + if ( !item->mDisplayText.isEmpty() ) { + TQString txt = "<qt><p><b>" + item->mDisplayText + "</b></p></qt>"; + mDetailView->addText( txt ); + } + item->setText( 0, cleanSummary( incidence->summary() ) ); + mDetailView->appendIncidence( incidence, item->mRemindAt.date() ); +} + +bool AlarmDialog::ensureKorganizerRunning() const +{ + TQString error; + TQCString dcopService; + + int result = KDCOPServiceStarter::self()->findServiceFor( + "DCOP/Organizer", TQString::null, TQString::null, &error, &dcopService ); + + if ( result == 0 ) { + // OK, so korganizer (or kontact) is running. Now ensure the object we + // want is available [that's not the case when kontact was already running, + // but korganizer not loaded into it...] + static const char* const dcopObjectId = "KOrganizerIface"; + TQCString dummy; + if ( !kapp->dcopClient()->findObject( + dcopService, dcopObjectId, "", TQByteArray(), dummy, dummy ) ) { + DCOPRef ref( dcopService, dcopService ); // talk to KUniqueApplication or its kontact wrapper + DCOPReply reply = ref.call( "load()" ); + if ( reply.isValid() && (bool)reply ) { + Q_ASSERT( kapp->dcopClient()->findObject( + dcopService, dcopObjectId, "", TQByteArray(), dummy, dummy ) ); + } else { + kdWarning() << "Error loading " << dcopService << endl; + } + } + + // We don't do anything with it we just need it to be running + return true; + + } else { + kdWarning() << "Couldn't start DCOP/Organizer: " << dcopService + << " " << error << endl; + } + return false; +} + +/** static */ +TQDateTime AlarmDialog::triggerDateForIncidence( Incidence *incidence, + const TQDateTime &reminderAt, + TQString &displayStr ) +{ + // Will be simplified in trunk, with roles. + TQDateTime result; + + Alarm *alarm = incidence->alarms().first(); + + if ( incidence->doesRecur() ) { + result = incidence->recurrence()->getNextDateTime( reminderAt ); + displayStr = KGlobal::locale()->formatDateTime( result ); + } + + if ( incidence->type() == "Event" ) { + if ( !result.isValid() ) { + Event *event = static_cast<Event *>( incidence ); + result = alarm->hasStartOffset() ? event->dtStart() : + event->dtEnd(); + displayStr = IncidenceFormatter::dateTimeToString( result, false, true ); + } + } else if ( incidence->type() == "Todo" ) { + if ( !result.isValid() ) { + Todo *todo = static_cast<Todo *>( incidence ); + result = alarm->hasStartOffset() && todo->dtStart().isValid() ? todo->dtStart(): + todo->dtDue(); + displayStr = IncidenceFormatter::dateTimeToString( result, false, true ); + } + } + + return result; +} + +void AlarmDialog::slotCalendarChanged() +{ + Incidence::List incidences = mCalendar->incidences(); + for ( Incidence::List::ConstIterator it = incidences.begin(); + it != incidences.constEnd(); ++it ) { + Incidence *incidence = *it; + AlarmListItem *item = searchByUid( incidence->uid() ); + + if ( item ) { + TQString displayStr; + const TQDateTime dateTime = triggerDateForIncidence( incidence, + item->mRemindAt, + displayStr ); + + const TQString summary = cleanSummary( incidence->summary() ); + + if ( displayStr != item->text( 1 ) || summary != item->text( 0 ) ) { + item->setText( 1, displayStr ); + item->setText( 0, summary ); + } + } + } } diff --git a/korganizer/korgac/alarmdialog.h b/korganizer/korgac/alarmdialog.h index 4c2162a54..75208f654 100644 --- a/korganizer/korgac/alarmdialog.h +++ b/korganizer/korgac/alarmdialog.h @@ -31,36 +31,48 @@ #include <kdialogbase.h> #include <libkcal/event.h> -#include <libkcal/calendarlocal.h> +#include <libkcal/calendarresources.h> using namespace KCal; +class AlarmListItem; class KOEventViewer; -class TQSpinBox; class KComboBox; class KListView; -class AlarmListItem; +class TQSpinBox; +class TQSplitter; class AlarmDialog : public KDialogBase { - Q_OBJECT + Q_OBJECT public: - AlarmDialog( TQWidget *parent = 0, const char *name = 0 ); - virtual ~AlarmDialog(); + explicit AlarmDialog( CalendarResources *calendar, TQWidget *parent = 0, const char *name = 0 ); + + ~AlarmDialog(); - void addIncidence( Incidence *incidence, const TQDateTime &reminderAt ); + void addIncidence( Incidence *incidence, const TQDateTime &reminderAt, + const TQString &displayText ); void eventNotification(); public slots: - void slotOk(); - void slotUser1(); - void slotUser2(); - void slotUser3(); + + void slotOk(); // suspend + void slotUser1(); // edit + void slotUser2(); // dismiss all + void slotUser3(); // dismiss selected void slotSave(); void wakeUp(); void show(); + void edit(); void suspend(); void suspendAll(); void dismissAll(); + void dismissCurrent(); + + /** + If an incidence changed, for example in korg, we must update + the date and summary shown in the list view. + */ + void slotCalendarChanged(); signals: void reminderCount( int count ); @@ -69,16 +81,29 @@ class AlarmDialog : public KDialogBase { void updateButtons(); void showDetails(); + protected: + void closeEvent( TQCloseEvent * ); + private: - bool startKOrganizer(); + + static TQDateTime triggerDateForIncidence( Incidence *inc, + const TQDateTime &reminderAt, + TQString &displayStr ); + + void readLayout(); + void writeLayout(); + AlarmListItem *searchByUid( const TQString &uid ); + bool ensureKorganizerRunning() const; void setTimer(); int activeCount(); TQValueList<AlarmListItem*> selectedItems() const; + CalendarResources *mCalendar; KListView *mIncidenceListView; KOEventViewer *mDetailView; TQSpinBox *mSuspendSpin; + TQSplitter *mSplitter; KComboBox *mSuspendUnit; TQTimer mSuspendTimer; }; diff --git a/korganizer/korgac/koalarmclient.cpp b/korganizer/korgac/koalarmclient.cpp index a4298d7aa..ec19ce9aa 100644 --- a/korganizer/korgac/koalarmclient.cpp +++ b/korganizer/korgac/koalarmclient.cpp @@ -70,14 +70,17 @@ KOAlarmClient::KOAlarmClient( TQObject *parent, const char *name ) // load reminders that were active when quitting config->setGroup( "General" ); int numReminders = config->readNumEntry( "Reminders", 0 ); - for ( int i=1; i<=numReminders; ++i ) - { + for ( int i = 1; i <= numReminders; ++i ) { TQString group( TQString( "Incidence-%1" ).arg( i ) ); config->setGroup( group ); TQString uid = config->readEntry( "UID" ); TQDateTime dt = config->readDateTimeEntry( "RemindAt" ); - if ( !uid.isEmpty() ) - createReminder( mCalendar->incidence( uid ), dt ); + if ( !uid.isEmpty() ) { + Incidence *i = mCalendar->incidence( uid ); + if ( i && !i->alarms().isEmpty() ) { + createReminder( mCalendar, i, dt, TQString() ); + } + } config->deleteGroup( group ); } config->setGroup( "General" ); @@ -115,24 +118,27 @@ void KOAlarmClient::checkAlarms() for( it = alarms.begin(); it != alarms.end(); ++it ) { kdDebug(5891) << "REMINDER: " << (*it)->parent()->summary() << endl; Incidence *incidence = mCalendar->incidence( (*it)->parent()->uid() ); - createReminder( incidence, TQDateTime::currentDateTime() ); + createReminder( mCalendar, incidence, from, (*it)->text() ); } } -void KOAlarmClient::createReminder( KCal::Incidence *incidence, TQDateTime dt ) +void KOAlarmClient::createReminder( KCal::CalendarResources *calendar, + KCal::Incidence *incidence, + const TQDateTime &dt, + const TQString &displayText ) { if ( !incidence ) return; if ( !mDialog ) { - mDialog = new AlarmDialog(); + mDialog = new AlarmDialog( calendar ); connect( mDialog, TQT_SIGNAL(reminderCount(int)), mDocker, TQT_SLOT(slotUpdate(int)) ); connect( mDocker, TQT_SIGNAL(suspendAllSignal()), mDialog, TQT_SLOT(suspendAll()) ); connect( mDocker, TQT_SIGNAL(dismissAllSignal()), mDialog, TQT_SLOT(dismissAll()) ); connect( this, TQT_SIGNAL( saveAllSignal() ), mDialog, TQT_SLOT( slotSave() ) ); } - mDialog->addIncidence( incidence, dt ); + mDialog->addIncidence( incidence, dt, displayText ); mDialog->wakeUp(); saveLastCheckTime(); } diff --git a/korganizer/korgac/koalarmclient.h b/korganizer/korgac/koalarmclient.h index 89c122c39..c8eee984e 100644 --- a/korganizer/korgac/koalarmclient.h +++ b/korganizer/korgac/koalarmclient.h @@ -69,7 +69,8 @@ class KOAlarmClient : public TQObject, virtual public AlarmClientIface, public K void saveAllSignal(); private: - void createReminder( KCal::Incidence *incidence, TQDateTime dt ); + void createReminder( KCal::CalendarResources *calendar, KCal::Incidence *incidence, + const TQDateTime &dt, const TQString &displayText ); void saveLastCheckTime(); AlarmDockWindow *mDocker; // the panel icon diff --git a/korganizer/korgac/korgac.desktop b/korganizer/korgac/korgac.desktop index cad7d7e5e..6420a120f 100644 --- a/korganizer/korgac/korgac.desktop +++ b/korganizer/korgac/korgac.desktop @@ -22,7 +22,6 @@ Name[hu]=KOrganizer-emlékeztetÅ‘ kliens Name[is]=Ãminningarforrit fyrir KOrganizer Name[it]=Client degli avvisi di KOrganizer Name[ja]=KOrganizer リマインダクライアント -Name[ka]=KOrganizer შემხსენებელის კლიენტი Name[kk]=KOrganizer-дің еÑке Ñалу клиенті Name[km]=កម្មវិធី​រំលឹក​របស់ KOrganizer Name[lt]=KOrganizer priminimų klientas @@ -69,7 +68,6 @@ GenericName[hu]=KOrganizer emlékeztetÅ‘ szolgáltatás kliense GenericName[is]=Ãminningarpúki fyrir KOrganizer GenericName[it]=Client del demone degli avvisi di KOrganizer GenericName[ja]=KOrganizer リマインダデーモンクライアント -GenericName[ka]=KOrganizer შემხსენებელის დემáƒáƒœáƒ˜áƒ¡ კლიენტი GenericName[kk]=Organizer-дің еÑке Ñалу қызметінің клиенті GenericName[km]=កម្មវិធី​ដáŸáž˜áž·áž“​អ្នក​រំលឹក​របស់ KOrganizer GenericName[lt]=KOrganizer priminimų tarnybos klientas diff --git a/korganizer/korgac/testalarmdlg.cpp b/korganizer/korgac/testalarmdlg.cpp index 84fa51ed6..5a3ba5a18 100644 --- a/korganizer/korgac/testalarmdlg.cpp +++ b/korganizer/korgac/testalarmdlg.cpp @@ -29,6 +29,8 @@ #include <kdebug.h> #include <klocale.h> #include <kcmdlineargs.h> +#include <kconfig.h> +#include <kstandarddirs.h> #include "alarmdialog.h" @@ -39,6 +41,11 @@ int main(int argc,char **argv) KApplication app; + KConfig c( locate( "config", "korganizerrc" ) ); + c.setGroup( "Time & Date" ); + TQString tz = c.readEntry( "TimeZoneId" ); + CalendarResources *mCalendar = new CalendarResources( tz ); + Event *e1 = new Event; e1->setSummary( "This is a summary." ); TQDateTime now = TQDateTime::currentDateTime(); @@ -46,24 +53,64 @@ int main(int argc,char **argv) e1->setDtEnd( now.addDays( 1 ) ); Alarm *a = e1->newAlarm(); // a->setProcedureAlarm( "/usr/X11R6/bin/xeyes" ); - a->setAudioAlarm( "/opt/kde/share/apps/korganizer/sounds/spinout.wav" ); + a->setAudioAlarm( "/data/kde/share/apps/korganizer/sounds/spinout.wav" ); + mCalendar->addEvent( e1 ); Todo *t1 = new Todo; t1->setSummary( "To-do A" ); t1->setDtDue( now ); t1->newAlarm(); + mCalendar->addTodo( t1 ); Event *e2 = new Event; e2->setSummary( "This is another summary." ); - e2->setDtStart( now ); - e2->setDtEnd( now.addDays( 1 ) ); + e2->setDtStart( now.addDays( 1 ) ); + e2->setDtEnd( now.addDays( 2 ) ); e2->newAlarm(); + mCalendar->addEvent( e2 ); + + Event *e3 = new Event; + e3->setSummary( "Meet with Fred" ); + e3->setDtStart( now.addDays( 2 ) ); + e3->setDtEnd( now.addDays( 3 ) ); + e3->newAlarm(); + mCalendar->addEvent( e3 ); + + Todo *t2 = new Todo; + t2->setSummary( "Something big is due today" ); + t2->setDtDue( now ); + t2->newAlarm(); + mCalendar->addTodo( t2 ); + + Todo *t3 = new Todo; + t3->setSummary( "Be lazy" ); + t3->setDtDue( now ); + t3->newAlarm(); + mCalendar->addTodo( t3 ); + + Event *e4 = new Event; + e4->setSummary( "Watch TV" ); + e4->setDtStart( now.addSecs( 120 ) ); + e4->setDtEnd( now.addSecs( 180 ) ); + e4->newAlarm(); + mCalendar->addEvent( e4 ); - AlarmDialog dlg; + AlarmDialog dlg( mCalendar, 0 ); app.setMainWidget( &dlg ); - dlg.addIncidence( e1, TQDateTime::currentDateTime() ); - dlg.addIncidence( t1, TQDateTime::currentDateTime() ); - dlg.addIncidence( e2, TQDateTime::currentDateTime() ); + dlg.addIncidence( e2, TQDateTime::currentDateTime().addSecs( 60 ), + TQString() ); + dlg.addIncidence( t1, TQDateTime::currentDateTime().addSecs( 300 ), + TQString( "THIS IS DISPLAY TEXT" ) ); + dlg.addIncidence( e4, TQDateTime::currentDateTime().addSecs( 120 ), + TQString( "Fred and Barney get cloned" ) ); + dlg.addIncidence( e3, TQDateTime::currentDateTime().addSecs( 240 ), + TQString() ); + dlg.addIncidence( e1, TQDateTime::currentDateTime().addSecs( 180 ), + TQString() ); + dlg.addIncidence( t2, TQDateTime::currentDateTime().addSecs( 600 ), + TQString( "THIS IS DISPLAY TEXT" ) ); + dlg.addIncidence( t3, TQDateTime::currentDateTime().addSecs( 360 ), + TQString() ); dlg.show(); dlg.eventNotification(); diff --git a/korganizer/korganizer.cpp b/korganizer/korganizer.cpp index fae21bff1..69ab0f4a3 100644 --- a/korganizer/korganizer.cpp +++ b/korganizer/korganizer.cpp @@ -308,3 +308,9 @@ void KOrganizer::setTitle() setCaption( title, !mCalendarView->isReadOnly() && mCalendarView->isModified() ); } + +bool KOrganizer::isCurrentlyActivePart() +{ + return false; +} + diff --git a/korganizer/korganizer.desktop b/korganizer/korganizer.desktop index 2f717f7a4..b3337dd0f 100644 --- a/korganizer/korganizer.desktop +++ b/korganizer/korganizer.desktop @@ -27,7 +27,6 @@ Comment[hu]=HatáridÅ‘napló és eseményszervezÅ‘ Comment[is]=Dagbók og skipulag Comment[it]=Programma di calendario e di agenda Comment[ja]=カレンダーã¨ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ç®¡ç†ãƒ—ãƒã‚°ãƒ©ãƒ -Comment[ka]=კáƒáƒšáƒ”ნდრის დრმგეგმáƒáƒ•áƒ˜áƒ¡ პრáƒáƒ’რáƒáƒ›áƒ Comment[kk]=Күнтізбе және ЖоÑпарлау бағдарламаÑÑ‹ Comment[km]=កម្មវិធី​ប្រážáž·áž‘áž·áž“ និង​កាលវិភាគ Comment[lt]=Kalendoriaus ir planavimo programa @@ -57,8 +56,7 @@ Comment[tg]=Тақвимот ва ҷадвали шахÑÓ£ Comment[th]=โปรà¹à¸à¸£à¸¡à¸ˆà¸±à¸”à¸à¸²à¸£à¸šà¸±à¸™à¸—ึà¸à¸›à¸£à¸°à¸ˆà¸³à¸§à¸±à¸™à¹à¸¥à¸°à¸•à¸²à¸£à¸²à¸‡à¸à¸²à¸£à¸™à¸±à¸”หมาย Comment[tr]=Takvim ve Zamanlama Programı Comment[uk]=Програма ÐºÐ°Ð»ÐµÐ½Ð´Ð°Ñ€Ñ Ñ‚Ð° розкладу -Comment[uz]=Kalendar va rejalashtirish dasturi -Comment[uz@cyrillic]=Календар ва режалаштириш даÑтури +Comment[uz]=Календар ва режалаштириш даÑтури Comment[ven]=Khalenda na mbekanyamushumo ya u shedula Comment[vi]=ChÆ°Æ¡ng trình lịch và kế hoạch Comment[xh]=Ikhalenda no Dweliso lwenkqubo Yokucwangcisa @@ -113,7 +111,6 @@ GenericName[hu]=HatáridÅ‘napló GenericName[is]=Persónuleg skipulagsbók GenericName[it]=Organizzatore personale GenericName[ja]=個人å‘ã‘ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ç®¡ç† -GenericName[ka]=პირáƒáƒ“ი áƒáƒ გáƒáƒœáƒ˜áƒ–áƒáƒ¢áƒáƒ ი GenericName[kk]=Ð”ÐµÑ€Ð±ÐµÑ Ò±Ð¹Ñ‹Ð¼Ð´Ð°Ñтырғышы GenericName[km]=កម្មវិធី​រៀបចំ​ផ្ទាល់​ážáŸ’លួន GenericName[lt]=AsmeninÄ—s informacijos tvarkyklÄ— @@ -138,8 +135,7 @@ GenericName[ta]=தனிபà¯à®ªà®¯à®©à¯ அமைபà¯à®ªà®¾à®³à®°à¯ GenericName[tg]=Органайзери инфиродӣ GenericName[tr]=KiÅŸisel Bilgi Yöneticisi GenericName[uk]=ПерÑональний тижневик -GenericName[uz]=Shaxsiy organayzer -GenericName[uz@cyrillic]=ШахÑий органайзер +GenericName[uz]=ШахÑий органайзер GenericName[zh_CN]=个人日程安排 GenericName[zh_TW]=個人行程組織軟體 ServiceTypes=Browser/View,DCOP/Organizer diff --git a/korganizer/korganizer.h b/korganizer/korganizer.h index 3ad0952a1..d088becba 100644 --- a/korganizer/korganizer.h +++ b/korganizer/korganizer.h @@ -95,6 +95,8 @@ class KOrganizer : public KPartsMainWindow, public KOrgMainWindow virtual KXMLGUIClient *mainGuiClient() { return this; } virtual TQWidget *topLevelWidget() { return this; } + virtual bool isCurrentlyActivePart(); + public slots: /** show status message */ void showStatusMessage( const TQString & ); diff --git a/korganizer/korganizer.kcfg b/korganizer/korganizer.kcfg index eaf23fb34..c299aa75c 100644 --- a/korganizer/korganizer.kcfg +++ b/korganizer/korganizer.kcfg @@ -148,10 +148,38 @@ <whatsthis>Enter default duration for events here. The default is used if you do not supply an end time.</whatsthis> <default>QDateTime(QDate(), QTime(2,0))</default> </entry> - <entry type="Int" key="Default Alarm Time" name="AlarmTime"> - <label>Default Reminder Time</label> - <whatsthis>Enter the reminder time here.</whatsthis> - <default>3</default> + + <entry type="Int" key="Default Reminder Time" name="ReminderTime"> + <label>Default reminder time</label> + <whatsthis>Enter the default reminder time for all newly created items. The time unit is specified in the adjacent combobox.</whatsthis> + <tooltip>Default time for reminders</tooltip> + <default>15</default> + </entry> + <entry type="Int" key="Default Reminder Time Units" name="ReminderTimeUnits"> + <whatsthis>Enter the default reminder time units for all newly created items. The time is specified in the adjacent spinbox.</whatsthis> + <tooltip>Default time unit for reminders</tooltip> + <default>0</default> + </entry> + <entry type="Bool" key="Enable Default Audio File" name="defaultAudioFileReminders"> + <label>Enable a default sound file for audio reminders</label> + <whatsthis>Check this box if you want to enable the specified file to be used as the default sound file for new reminders. You can always specify another file in the Advanced Reminder accessible from the Event or To-do editors.</whatsthis> + <default>false</default> + </entry> + <entry type="Path" key="Reminder Audio File" name="audioFilePath"> + <label>Default audio file</label> + <whatsthis>Set a file to be used as the default sound file for new reminders. You can always specify another file in the Advanced Reminder accessible from the Event or To-do editors.</whatsthis> + </entry> + <entry type="Bool" key="Enable Event Reminders" name="defaultEventReminders"> + <label>Enable reminders for new Events</label> + <whatsthis>Check this box if you want to enable reminders for all newly created Events. You can always turn-off the reminders in the Event editor dialog.</whatsthis> + <tooltip>By default, enable reminders for new events</tooltip> + <default>false</default> + </entry> + <entry type="Bool" key="Enable To-do Reminders" name="defaultTodoReminders"> + <label>Enable reminders for new To-dos</label> + <whatsthis>Check this box if you want to enable reminders for all newly created To-dos. You can always turn-off the reminders in the To-do editor dialog.</whatsthis> + <tooltip>By default, enable reminders for new to-dos</tooltip> + <default>false</default> </entry> </group> @@ -173,6 +201,11 @@ <whatsthis>Check this box to show the days containing weekly recurring events in bold typeface in the Date Navigator, or uncheck it to give more prominence to other (non weekly recurring) events.</whatsthis> <default>true</default> </entry> + <entry type="Bool" key="Week Numbers Show Work Week" name="weekNumbersShowWork"> + <label>Week numbers select a work week when in work week view</label> + <whatsthis>Check this box to select a work week when clicking on date navigator's week numbers or uncheck it to chose the whole week.</whatsthis> + <default>false</default> + </entry> <entry type="Bool" key="Enable ToolTips"> <label>Enable tooltips displaying summary of events</label> <whatsthis>Check this box to display an event summary tooltip when hovering the mouse over an event.</whatsthis> @@ -222,7 +255,7 @@ <label>Only calendar</label> </choice> </choices> - <default>CategoryInsideResourceOutside</default> + <default>ResourceInsideCategoryOutside</default> </entry> <entry type="Enum" name="Agenda View Calendar Display"> @@ -241,8 +274,6 @@ <default>CalendarsMerged</default> </entry> - - <entry type="DateTime" name="DayBegins"> <label>Day begins at</label> <whatsthis>Enter the start time for events here. This time should be the earliest time that you use for events, as it will be displayed at the top.</whatsthis> @@ -268,16 +299,24 @@ <default>true</default> </entry> - <entry type="Bool" key="Month View Uses Category Color"> - <label>Month view uses category colors</label> - <whatsthis>Check this box to make the month view use the category colors of an item.</whatsthis> - <default>true</default> - </entry> - - <entry type="Bool" key="Month View Uses Resource Color"> - <label>Month view uses resource colors</label> - <whatsthis>Check this box to make the month view use the resource colors of an item.</whatsthis> - <default>true</default> + <entry type="Enum" key="MonthItemColors"> + <label>Colors used in month view</label> + <whatsthis>Choose the colors of the month view items.</whatsthis> + <choices> + <choice name="MonthItemCategoryInsideResourceOutside"> + <label>Category inside, calendar outside</label> + </choice> + <choice name="MonthItemResourceInsideCategoryOutside"> + <label>Calendar inside, category outside</label> + </choice> + <choice name="MonthItemCategoryOnly"> + <label>Only category</label> + </choice> + <choice name="MonthItemResourceOnly"> + <label>Only calendar</label> + </choice> + </choices> + <default>MonthItemResourceInsideCategoryOutside</default> </entry> <entry type="Bool" key="Full View Month"> @@ -391,9 +430,9 @@ <whatsthis>Select the to-do overdue color here.</whatsthis> <default>255, 100, 100</default> </entry> - <entry type="Color" key="EventColor"> - <label>Default event color</label> - <whatsthis>Select the default event color here. The default event color will be used for events categories in your agenda. Note that you can specify a separate color for each event category below.</whatsthis> + <entry type="Color" key="Unset Category Color"> + <label>"No category" color (for "Only category" drawing schemes)</label> + <whatsthis>Select a color to use for the "no category" or "unset category" situation, when an item does not belong to any category. This color is used when drawing items in the agenda or month views using the "Only category" scheme.</whatsthis> <default>151, 235, 121</default> </entry> @@ -465,7 +504,7 @@ <entry type="Bool" name="FreeBusyCheckHostname"> <label>Check whether hostname and retrieval email address match</label> <whatsthis>With this setting you can configure whether the domain part of the free/busy url has to match the domain part of the user id you are looking for. For example if this option is 'true' then looking for the free/busy data of joe@mydomain.com on the server www.yourdomain.com won't work.</whatsthis> - <default>true</default> + <default>false</default> </entry> <entry type="Bool" name="FreeBusyFullDomainRetrieval"> diff --git a/korganizer/korganizer_configcolors.desktop b/korganizer/korganizer_configcolors.desktop index 59582a536..9a2c7f158 100644 --- a/korganizer/korganizer_configcolors.desktop +++ b/korganizer/korganizer_configcolors.desktop @@ -43,7 +43,6 @@ Name[id]=Warna Name[is]=Litir Name[it]=Colori Name[ja]=色 -Name[ka]=ფერები Name[kk]=ТүÑтері Name[km]=ពណ៌ Name[lt]=Spalvos @@ -73,8 +72,7 @@ Name[tg]=Рангҳо Name[th]=สี Name[tr]=Renkler Name[uk]=Кольори -Name[uz]=Ranglar -Name[uz@cyrillic]=Ранглар +Name[uz]=Ранглар Name[ven]=Mivhala Name[vi]=Mà u Name[xh]=Imibala @@ -109,7 +107,6 @@ Comment[hu]=KOrganizer szÃnbeállÃtások Comment[is]=KOrganizer litastillingar Comment[it]=Configurazione dei colori di Korganizer Comment[ja]=KOrganizer 色è¨å®š -Comment[ka]=KDE-ს áƒáƒ გáƒáƒœáƒ˜áƒ–áƒáƒ¢áƒáƒ ის ფერთრკáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ Comment[kk]=KOrganizer-дің Ñ‚Ò¯Ñтер параметрлері Comment[km]=ការ​កំណážáŸ‹â€‹ážšáž…នាសម្ពáŸáž“្ធ​ពណ៌ KOrganizer Comment[lt]=KOrganizer spalvų konfigÅ«ravimas @@ -154,7 +151,7 @@ Keywords[et]=korganizer,värvid Keywords[eu]=korganizer,koloreak Keywords[fa]=korganizer،رنگها Keywords[fi]=korganizer,värit -Keywords[fr]=korganizer,couleurs +Keywords[fr]=KOrganizer,couleurs Keywords[fy]=korganizer,colors,kleuren Keywords[ga]=korganizer,dathanna Keywords[gl]=korganizer,cores @@ -164,7 +161,6 @@ Keywords[hu]=korganizer,szÃnek Keywords[is]=korganizer,litir Keywords[it]=korganizer,colori Keywords[ja]=korganizer,色 -Keywords[ka]=korganizer,ფერები Keywords[km]=korganizer,ពណ៌ Keywords[lt]=korganizer,colors, spalvos Keywords[mk]=korganizer,colors,корганизатор,бои @@ -188,6 +184,5 @@ Keywords[ta]=கேஅமைபà¯à®ªà®¾à®³à®°à¯, வணà¯à®£à®™à¯à®•à®³à¯ Keywords[tg]=korganizer,colors,органайзер,рангҳо Keywords[tr]=korganizer,renkler Keywords[uk]=korganizer,кольори -Keywords[uz]=korganizer,organayzer,ranglar -Keywords[uz@cyrillic]=korganizer,органайзер,ранглар +Keywords[uz]=korganizer,органайзер,ранглар Keywords[zh_CN]=korganizer,colors,颜色 diff --git a/korganizer/korganizer_configdesignerfields.desktop b/korganizer/korganizer_configdesignerfields.desktop index 99f9e4b58..5263f22d3 100644 --- a/korganizer/korganizer_configdesignerfields.desktop +++ b/korganizer/korganizer_configdesignerfields.desktop @@ -37,7 +37,6 @@ Name[hu]=Egyéni lapok Name[is]=Sérsniðnar sÃður Name[it]=Pagine personalizzate Name[ja]=カスタムページ -Name[ka]=სáƒáƒ›áƒáƒ›áƒ®áƒ›áƒáƒ ებლრგვერდები Name[kk]=ҚоÑымша парақтар Name[km]=ទំពáŸážšâ€‹áž•áŸ’ទាល់​ážáŸ’លួន Name[lt]=Pasirinkti puslapiai @@ -89,7 +88,6 @@ Comment[hu]=Az egyéni lapok beállÃtása Comment[is]=Stilla sérsniðnu sÃðurnar Comment[it]=Configura le pagine personalizzate Comment[ja]=カスタムページã®è¨å®š -Comment[ka]=სáƒáƒ›áƒáƒ›áƒ®áƒ›áƒáƒ ებლრგვერდების კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ Comment[kk]=ҚоÑымша парақтарды баптау Comment[km]=កំណážáŸ‹â€‹ážšáž…នាសម្ពáŸáž“្ធ​ទំពáŸážšâ€‹áž•áŸ’ទាល់​ážáŸ’លួន Comment[lt]=KonfigÅ«ruoti darbastalių skaiÄių ir pavadinimus @@ -128,7 +126,7 @@ Keywords[et]=korganizer, seadistamine, seadistused, omaloodud väljad Keywords[eu]=korganizer, konfiguratu, ezarpenak, eremu pertsonalizatuak Keywords[fa]=korganizerØŒ پیکربندی، تنظیمات، Øوزه‌های سÙارشی Keywords[fi]=kaddressbook, aseta, asetukset,omat kentät -Keywords[fr]=korganizer, configuration, configurer, champs personnalisés +Keywords[fr]=KOrganizer, configuration, configurer, champs personnalisés Keywords[fy]=korganizer, configuratie, instellingen, ynstellings, oanpaste fjilden, aangepaste velden Keywords[ga]=korganizer, cumraigh, socruithe, réimsà saincheaptha Keywords[gl]=korganizer, configurar, opcións, campos personalizados @@ -137,7 +135,6 @@ Keywords[hu]=korganizer,beállÃtás,beállÃtások,egyéni mezÅ‘k Keywords[is]=korganizer, stillingar, stilla, sérsniðnir reitir Keywords[it]=korganizer, configura, impostazioni, campi personalizzati Keywords[ja]=korganizerã€è¨å®šã€è¨å®š,カスタムフィールド -Keywords[ka]=korganizer, კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ,პáƒáƒ áƒáƒ›áƒ”ტრები,სáƒáƒ›áƒáƒ›áƒ®áƒ›áƒáƒ ებლრველები Keywords[km]=korganizer,កំណážáŸ‹â€‹ážšáž…នាសម្ពáŸáž“្ធ,ការ​កំណážáŸ‹,វាល​ផ្ទាល់​ážáŸ’លួន Keywords[lt]=korganizer, configure, settings, custom fields, konfigÅ«ruoti, nustatymai, pasirinkti laukai Keywords[mk]=korganizer, configure, settings, custom fields, корганизатор, конфигурација, конфигурирање, поÑтавувања, ÑопÑтвени полиња diff --git a/korganizer/korganizer_configfonts.desktop b/korganizer/korganizer_configfonts.desktop index c1c1a1f25..cacdc75f5 100644 --- a/korganizer/korganizer_configfonts.desktop +++ b/korganizer/korganizer_configfonts.desktop @@ -42,7 +42,6 @@ Name[hu]=BetűtÃpusok Name[is]=Letur Name[it]=Tipi di carattere Name[ja]=フォント -Name[ka]=შრიფტები Name[kk]=Қаріптері Name[km]=ពុម្ពអក្សរ Name[lt]=Å riftai @@ -71,8 +70,7 @@ Name[tg]=Ҳарфҳо Name[th]=รูปà¹à¸šà¸šà¸•à¸±à¸§à¸à¸±à¸à¸©à¸£ Name[tr]=Yazı tipleri Name[uk]=Шрифти -Name[uz]=Shriftlar -Name[uz@cyrillic]=Шрифтлар +Name[uz]=Шрифтлар Name[ven]=Fontu Name[vi]=Phông Name[xh]=Ubungakanani bamagama @@ -105,7 +103,6 @@ Comment[hu]=KOrganizer betűtÃpus-beállÃtások Comment[is]=KOrganizer leturstillingar Comment[it]=Configurazione font di KOrganizer Comment[ja]=KOrganizer フォントè¨å®š -Comment[ka]=KOrganizer შრიფტთრკáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ Comment[kk]=KOrganizer-дің қаріптер параметрлері Comment[km]=ការ​កំណážáŸ‹â€‹ážšáž…នាសម្ពáŸáž“្ធ​ពុម្ពអក្សរ KOrganizer Comment[lt]=KOrganizer Å¡riftų konfigÅ«ravimas @@ -151,7 +148,7 @@ Keywords[et]=korganizer,fondid Keywords[eu]=korganizer,letra-tipoak Keywords[fa]=korganizer،قلمها Keywords[fi]=korganizer,kirjasimet -Keywords[fr]=korganizer,polices +Keywords[fr]=KOrganizer,polices Keywords[fy]=korganizer,fonts,lettertypen Keywords[ga]=korganizer,clónna,clófhoirne Keywords[gl]=korganizer,fontes @@ -161,7 +158,6 @@ Keywords[hu]=korganizer,betűtÃpusok Keywords[is]=korganizer,letur Keywords[it]=korganizer,font Keywords[ja]=korganizer,フォント -Keywords[ka]=korganizer,შრიფტები Keywords[km]=korganizer,ពុម្ពអក្សរ Keywords[lt]=korganizer,fonts, Å¡riftai Keywords[mk]=korganizer,fonts,корганизатор,фонтови @@ -185,6 +181,5 @@ Keywords[ta]=கேஅமைபà¯à®ªà®¾à®³à®°à¯,எழà¯à®¤à¯à®¤à¯à®°à¯ Keywords[tg]=korganizer,fonts,органайзер,ҳуруфҳо Keywords[tr]=korganizer,yazıtipleri Keywords[uk]=korganizer,шрифти -Keywords[uz]=korganizer,organayzer,shriftlar -Keywords[uz@cyrillic]=korganizer,органайзер,шрифтлар +Keywords[uz]=korganizer,органайзер,шрифтлар Keywords[zh_CN]=korganizer,fonts,å—体 diff --git a/korganizer/korganizer_configfreebusy.desktop b/korganizer/korganizer_configfreebusy.desktop index 84640ab8f..2bae305c8 100644 --- a/korganizer/korganizer_configfreebusy.desktop +++ b/korganizer/korganizer_configfreebusy.desktop @@ -35,7 +35,6 @@ Name[hu]=Foglaltság Name[is]=TÃmaráðstöfun Name[it]=Libero/Occupato Name[ja]=å‹•é™æƒ…å ± -Name[ka]=თáƒáƒ•áƒ˜áƒ¡áƒ£áƒ¤áƒáƒšáƒ˜/დáƒáƒ™áƒáƒ•áƒ”ბული Name[kk]=БоÑ/ІÑте Name[km]=ទំនáŸážš/រវល់ Name[lt]=Užimtumas @@ -59,8 +58,7 @@ Name[ta]=சà¯à®¤à®¨à¯à®¤à®¿à®°à®®à®¾à®©/வேலையில௠இரà¯à®• Name[tg]=Озод/машғул аÑÑ‚ Name[tr]=BoÅŸ/MeÅŸgul Name[uk]=Вільний/зайнÑтий Ñ‡Ð°Ñ -Name[uz]=BoÊ»sh/Band -Name[uz@cyrillic]=Бўш/Банд +Name[uz]=Бўш/Банд Name[zh_CN]=å¿™/é—² Name[zh_TW]=行程資訊 Comment=KOrganizer Free/Busy Configuration @@ -87,7 +85,6 @@ Comment[hu]=KOrganizer foglaltsági beállÃtások Comment[is]=KOrganizer stillingar fyrir tÃmaráðstöfun Comment[it]=Configurazione Libero/Occupato di KOrganizer Comment[ja]=KOrganizer å‹•é™æƒ…å ±ã®è¨å®š -Comment[ka]=KOrganizer-ის თáƒáƒ•áƒ˜áƒ¡áƒ£áƒ¤áƒáƒšáƒ˜/დáƒáƒ™áƒáƒ•áƒ”ბულáƒáƒ‘ის კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ Comment[kk]=KOrganizer--дің БоÑ/ІÑте мәлімет параметрлері Comment[km]=ការ​កំណážáŸ‹â€‹ážšáž…នាសម្ពáŸáž“្ធ​ទំនáŸážš/រវល់ របស់ KOrganizer Comment[lt]=KOrganizer užimtumo konfigÅ«ravimas @@ -128,7 +125,7 @@ Keywords[et]=korganizer,vaba,hõivatud,ajakava Keywords[eu]=korganizer,libre, lanpetuta,antolaketa Keywords[fa]=korganizer،آزاد اشغال، زمان‌بندی Keywords[fi]=korganizer,vapaa,varattu,ajastus -Keywords[fr]=korganizer,disponibilité, planification +Keywords[fr]=KOrganizer,disponibilité, planification Keywords[fy]=korganizer,freebusy,scheduling,plannen,frij,beset,roaster Keywords[gl]=korganizer,dispoñibilidade,axenda Keywords[hi]=के-आरà¥à¤—ेनाइज़र,फà¥à¤°à¥€-बिज़ी,समय-सारणी @@ -136,7 +133,6 @@ Keywords[hu]=korganizer,foglaltság,szervezés Keywords[is]=korganizer,tÃmaráðstöfun,áætlun Keywords[it]=korganizer,libero/occupato,pianificazione Keywords[ja]=korganizer,å‹•é™,スケジューラ -Keywords[ka]=korganizer,თáƒáƒ•áƒ˜áƒ¡áƒ£áƒ¤áƒáƒšáƒ˜áƒ“áƒáƒ™áƒáƒ•áƒ”ბული,დáƒáƒ’ეგმვრKeywords[km]=korganizer,ទំនáŸážš,រវល់,កាលវិភាគ Keywords[mk]=korganizer,freebusy,scheduling,корганизатор,Ñлободно,зафатено,закажување Keywords[ms]=korganizer,lapang sibuk,penjadualan diff --git a/korganizer/korganizer_configgroupautomation.desktop b/korganizer/korganizer_configgroupautomation.desktop index 8e3227bc7..6386deda6 100644 --- a/korganizer/korganizer_configgroupautomation.desktop +++ b/korganizer/korganizer_configgroupautomation.desktop @@ -35,7 +35,6 @@ Name[hu]=Csoportmunka Name[is]=Hópsjálfvirkni Name[it]=Automazione gruppi Name[ja]=グループ自動化 -Name[ka]=ჯგუფური áƒáƒ•áƒ¢áƒáƒ›áƒáƒ¢áƒ˜áƒ–áƒáƒªáƒ˜áƒ Name[kk]=Топтың біріккен жұмыÑÑ‹ Name[km]=ស្វáŸáž™áž”្រážáž·áž€áž˜áŸ’ម​ក្រុម Name[lt]=Grupių automatizavimas @@ -86,7 +85,6 @@ Comment[hu]=KOrganizer csoportmunka-beállÃtások Comment[is]=Stillingar KOrganizer hópsjálfvirkni Comment[it]=Configurazione automazione gruppi di KOrganizer Comment[ja]=KOrganizer グループ自動化è¨å®š -Comment[ka]=KOrganizer-ის ჯგუფური áƒáƒ•áƒ¢áƒáƒ›áƒáƒ¢áƒ˜áƒ–áƒáƒªáƒ˜áƒ˜áƒ¡ კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ Comment[kk]=KOrganizer топтық жұмыÑының параметрлері Comment[km]=ការ​កំណážáŸ‹â€‹ážšáž…នាសម្ពáŸáž“្ធ​ស្វáŸáž™áž”្រážáž·áž€áž˜áŸ’ម​ក្រុម​របស់ KOrganizer Comment[lt]=KOrganizer grupių automatizavimo konfigÅ«ravimas @@ -129,7 +127,7 @@ Keywords[et]=korganizer,grupid,grupitöö Keywords[eu]=korganizer,taldea,automatizazioa Keywords[fa]=korganizer،گروه، خودکارسازی Keywords[fi]=korganizer,ryhmä,automaatio -Keywords[fr]=korganizer,groupes,automatisation +Keywords[fr]=KOrganizer,groupes,automatisation Keywords[fy]=korganizer,groep,automatisearring Keywords[gl]=korganizer,grupo,automatización Keywords[hi]=के-आरà¥à¤—ेनाइज़र,समूह,सà¥à¤µà¤šà¤¾à¤²à¤¨ @@ -137,7 +135,6 @@ Keywords[hu]=korganizer,csoport,csoportmunka Keywords[is]=korganizer,hópar,sjálfvirkni Keywords[it]=korganizer,gruppi,automazione Keywords[ja]=korganizer,グループ,自動化 -Keywords[ka]=korganizer,ჯგუფი,áƒáƒ•áƒ¢áƒáƒ›áƒáƒ¢áƒ˜áƒ–áƒáƒªáƒ˜áƒ Keywords[km]=korganizer,ក្រុម,ស្វáŸáž™áž”្រážáž·áž€áž˜áŸ’ម Keywords[lt]=korganizer,group,automation, grupÄ—s,automatizavimas Keywords[mk]=korganizer,group,automation,корганизатор,група,групи,автоматизација diff --git a/korganizer/korganizer_configgroupscheduling.desktop b/korganizer/korganizer_configgroupscheduling.desktop index d5fe9975e..710f6df7b 100644 --- a/korganizer/korganizer_configgroupscheduling.desktop +++ b/korganizer/korganizer_configgroupscheduling.desktop @@ -35,7 +35,6 @@ Name[hu]=Szervezés Name[is]=Hópáætlun Name[it]=Programmazione gruppi Name[ja]=グループスケジューリング -Name[ka]=ჯგუფის დáƒáƒ’ეგმვრName[kk]=Топтың жұмыÑын жоÑпарлау Name[km]=រៀបចំ​កាលវិភាគ​ក្រុម Name[lt]=Grupių tvarkaraÅ¡Äių tvarkymas @@ -87,7 +86,6 @@ Comment[hu]=KOrganizer szervezési beállÃtások Comment[is]=Stillingar fyrir KOrganizer hópáætlun Comment[it]=Configurazione del programmatore gruppi di KOrganizer Comment[ja]=KOrganizer グループスケジューリングè¨å®š -Comment[ka]=KOrganizer გჯუფის დáƒáƒ’ეგმვის კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ Comment[kk]=KOrganizer топтық жұмыÑÑ‚Ñ‹ жоÑпрлаудың параметрлері Comment[km]=ការ​កំណážáŸ‹â€‹ážšáž…នាសម្ពáŸáž“្ធ​ការ​រៀបចំ​កាលវិភាគ​ក្រុម​របស់ KOrganizer Comment[lt]=KOrganizer grupių tvarkaraÅ¡Äių tvarkymo konfigÅ«ravimas @@ -128,14 +126,13 @@ Keywords[et]=korganizer,grupid,grupitöö,ajakavad Keywords[eu]=korganizer,taldea,antolaketa Keywords[fa]=korganizer،گروه، زمان‌بندی Keywords[fi]=korganizer,ryhmä,ajastus -Keywords[fr]=korganizer,groupes,planification +Keywords[fr]=KOrganizer,groupes,planification Keywords[fy]=korganizer,group,scheduling,plannen,groep Keywords[gl]=korganizer,grupo,programar Keywords[hu]=korganizer,csoport,szervezés Keywords[is]=korganizer,hóp,áætlun Keywords[it]=korganizer,gruppo,programmazione Keywords[ja]=korganizer,グループ,スケジューリング -Keywords[ka]=korganizer,გჯუფი,დáƒáƒ’ეგმვრKeywords[km]=korganizer,ក្រុម,កាលវិភាគ Keywords[lt]=korganizer,group,scheduling,tvarkaraÅ¡tis, grupÄ— Keywords[mk]=korganizer,group,scheduling,корганизатор,група,групи,закажување diff --git a/korganizer/korganizer_configmain.desktop b/korganizer/korganizer_configmain.desktop index 52e70ee05..1f5c5bde0 100644 --- a/korganizer/korganizer_configmain.desktop +++ b/korganizer/korganizer_configmain.desktop @@ -38,7 +38,6 @@ Name[hu]=AlapbeállÃtások Name[is]=Persónulegt Name[it]=Personale Name[ja]=個人è¨å®š -Name[ka]=პირáƒáƒ“ი Name[kk]=Ð”ÐµÑ€Ð±ÐµÑ Name[km]=ផ្ទាល់​ážáŸ’លួន Name[lt]=Suasmeninimas @@ -63,8 +62,7 @@ Name[ta]=அநà¯à®¤à®°à®™à¯à®•à®®à®¾à®© Name[tg]=Танзимотҳои шахÑÓ£ Name[tr]=KiÅŸisel Name[uk]=ОÑобиÑÑ‚Ñ– -Name[uz]=Shaxsiy -Name[uz@cyrillic]=ШахÑий +Name[uz]=ШахÑий Name[zh_CN]=个人 Name[zh_TW]=個人 Comment=KOrganizer Main Configuration @@ -94,7 +92,6 @@ Comment[hu]=A KOrganizer alapbeállÃtásai Comment[is]=Aðalstillingar KOrganizer Comment[it]=Configurazione principale di KOrganizer Comment[ja]=KOrganizer 主è¦è¨å®š -Comment[ka]=KOrganizer ძირითáƒáƒ“ი კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ Comment[kk]=KOrganizer-дің негізгі параметрлері Comment[km]=ការ​កំណážáŸ‹â€‹ážšáž…នាសម្ពáŸáž“្ធ​សំážáž¶áž“់ៗ​របស់ KOrganizer Comment[lt]=KOrganizer bendroji konfigÅ«ravimas @@ -135,7 +132,7 @@ Keywords[et]=korganizer,peamine,isiklik Keywords[eu]=korganizer,nagusia,pertsonala Keywords[fa]=korganizer،اصلی، شخصی Keywords[fi]=korganizer,pää,henkilökohtainen -Keywords[fr]=korganizer,principal,personnel +Keywords[fr]=KOrganizer,principal,personnel Keywords[fy]=korganizer,algemien, persoanlik Keywords[gl]=korganizer,principal,persoal Keywords[he]=korganizer,main,personal,××¨×’×•× ×™×ª,תצורה,הגדרה,הגדרות @@ -144,7 +141,6 @@ Keywords[hu]=korganizer,alapbeállÃtások,személyes Keywords[is]=korganizer,aðal,persónulegt Keywords[it]=korganizer,principale,personale Keywords[ja]=korganizer,メイン,個人 -Keywords[ka]=korganizer,ძირითáƒáƒ“ი,პირáƒáƒ“ი Keywords[km]=korganizer,សំážáž¶áž“់,ផ្ទាល់​ážáŸ’លួន Keywords[lt]=korganizer,main,personal,pagrindinis,asmeninis,bendroji Keywords[mk]=korganizer,main,personal,корганизатор,главно,лично @@ -168,6 +164,5 @@ Keywords[ta]=கேஅமைபà¯à®ªà®¾à®³à®°à¯,à®®à¯à®•à¯à®•à®¿à®¯, தனà Keywords[tg]=korganizer,main,personal,почта,танзимотҳои шахÑÓ£,органайзер Keywords[tr]=korganizer,temel,kiÅŸisel Keywords[uk]=korganizer,оÑобиÑтий,ПерÑональний -Keywords[uz]=korganizer,organayzer,asosiy,shaxsiy -Keywords[uz@cyrillic]=korganizer,органайзер,аÑоÑий,шахÑий +Keywords[uz]=korganizer,органайзер,аÑоÑий,шахÑий Keywords[zh_CN]=korganizer,main,personal,主è¦,个人 diff --git a/korganizer/korganizer_configplugins.desktop b/korganizer/korganizer_configplugins.desktop index 7e4c332a2..2488f1ade 100644 --- a/korganizer/korganizer_configplugins.desktop +++ b/korganizer/korganizer_configplugins.desktop @@ -37,7 +37,6 @@ Name[hu]=BÅ‘vÃtÅ‘modulok Name[is]=Ãforrit Name[it]=Plugin Name[ja]=プラグイン -Name[ka]=მáƒáƒ“ულები Name[kk]=Плагин модульдері Name[km]=កម្មវិធី​ជំនួយ Name[lt]=Priedai @@ -59,8 +58,7 @@ Name[sv]=Insticksprogram Name[ta]=சொரà¯à®•à¯à®ªà¯à®ªà¯Šà®°à¯à®³à¯à®•à®³à¯ Name[tr]=Eklentiler Name[uk]=Втулки -Name[uz]=Plaginlar -Name[uz@cyrillic]=Плагинлар +Name[uz]=Плагинлар Name[zh_CN]=æ’件 Name[zh_TW]=å¤–æŽ›ç¨‹å¼ Comment=KOrganizer Plugin Configuration @@ -87,7 +85,6 @@ Comment[hu]=A KOrganizer bÅ‘vÃtÅ‘modul beállÃtásai Comment[is]=Stillingar KOrganizer Ãforrita Comment[it]=Configurazione plugin KOrganizer Comment[ja]=KOrganizer プラグインè¨å®š -Comment[ka]=KOrganizer მáƒáƒ“ულების კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ Comment[kk]=KOrganizer-дің плагин модульдерінің параметрлері Comment[km]=ការ​កំណážáŸ‹â€‹ážšáž…នាសម្ពáŸáž“្ធ​កម្មវិធី​ជំនួយ KOrganizer Comment[lt]=KOrganizer priedų konfigÅ«ravimas @@ -125,7 +122,7 @@ Keywords[et]=korganizer,plugin,moodul Keywords[eu]=korganizer,plugin-a,modulua Keywords[fa]=korganizer،وصله، پیمانه Keywords[fi]=korganizer,liitännäinen,moduuli -Keywords[fr]=korganizer,module +Keywords[fr]=KOrganizer,module Keywords[ga]=korganizer,breiseán,modúl Keywords[gl]=korganizer,extensión,módulo Keywords[he]=korganizer,plugin,module,מודול,תוסף,××¨×’×•× ×™×ª @@ -133,7 +130,6 @@ Keywords[hu]=korganizer,bÅ‘vÃtÅ‘modul,modul Keywords[is]=korganizer,Ãforrit,eining Keywords[it]=korganizer,plugin,modulo Keywords[ja]=korganizer,プラグイン,モジュール -Keywords[ka]=korganizer,მáƒáƒ“ული Keywords[km]=korganizer,កម្មវិធី​ជំនួយ,ម៉ូឌុល Keywords[lt]=korganizer,plugin,module,modulis,priedas Keywords[mk]=korganizer,plugin,module,корганизатор,приклучок,приклучоци,модул.модули diff --git a/korganizer/korganizer_configtime.desktop b/korganizer/korganizer_configtime.desktop index 72d7629a1..a1eebdbc9 100644 --- a/korganizer/korganizer_configtime.desktop +++ b/korganizer/korganizer_configtime.desktop @@ -40,7 +40,6 @@ Name[hu]=Dátum és idÅ‘ Name[is]=TÃmi og dagsetning Name[it]=Data e ora Name[ja]=日付ã¨æ™‚é–“ -Name[ka]=დრრდრთáƒáƒ იღი Name[kk]=Уақыт пен Күн Name[km]=កាលបរិច្ឆáŸáž‘ & áž–áŸáž›ážœáŸáž›áž¶ Name[lt]=Laikas ir data @@ -66,8 +65,7 @@ Name[ta]=நேரம௠& தேதி Name[tg]=Сана ва вақт Name[tr]=Saat & Tarih Name[uk]=Ð§Ð°Ñ Ñ‚Ð° дата -Name[uz]=Sana va vaqt -Name[uz@cyrillic]=Сана ва вақт +Name[uz]=Сана ва вақт Name[zh_CN]=时间和日期 Name[zh_TW]=時間與日期 Comment=KOrganizer Time Configuration @@ -97,7 +95,6 @@ Comment[hu]=KOrganizer dátum- és idÅ‘beállÃtások Comment[is]=KOrganizer tÃmastillingar Comment[it]=Configurazione data di KOrganizer Comment[ja]=KOrganizer 時間è¨å®š -Comment[ka]=KOrganizer დრáƒáƒ˜áƒ¡ კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ Comment[kk]=KOrganizer-дің уақыт параметрлері Comment[km]=ការ​កំណážáŸ‹â€‹ážšáž…នាសម្ពáŸáž“្ធ​ពáŸáž›ážœáŸáž›áž¶â€‹ážšáž”ស់ KOrganizer Comment[lt]=KOrganizer laiko konfigÅ«ravimas @@ -141,7 +138,7 @@ Keywords[et]=korganizer,aeg Keywords[eu]=korganizer,ordua,data Keywords[fa]=korganizer،زمان Keywords[fi]=korganizer,aika -Keywords[fr]=korganizer,date +Keywords[fr]=KOrganizer,date Keywords[fy]=datum,tijd,tiid,korganizer Keywords[ga]=korganizer,am Keywords[gl]=korganizer,hora @@ -151,7 +148,6 @@ Keywords[hu]=korganizer,idÅ‘ Keywords[is]=korganizer,tÃmi Keywords[it]=korganizer,data,ora Keywords[ja]=korganizer,時間 -Keywords[ka]=korganizer,დრრKeywords[km]=korganizer,áž–áŸáž›ážœáŸáž›áž¶ Keywords[lt]=korganizer,time,laikas Keywords[mk]=korganizer,time,корганизатор,датум,време @@ -175,6 +171,5 @@ Keywords[ta]=கேஅமைபà¯à®ªà®¾à®³à®°à¯,நேரம௠Keywords[tg]=korganizer,time,органайзер,вақт Keywords[tr]=korganizer,zaman Keywords[uk]=korganizer,чаÑ,дата -Keywords[uz]=korganizer,organayzer,sana,vaqt -Keywords[uz@cyrillic]=korganizer,органайзер,Ñана,вақт +Keywords[uz]=korganizer,органайзер,Ñана,вақт Keywords[zh_CN]=korganizer,time,时间 diff --git a/korganizer/korganizer_configviews.desktop b/korganizer/korganizer_configviews.desktop index dd20819ac..d46f352a7 100644 --- a/korganizer/korganizer_configviews.desktop +++ b/korganizer/korganizer_configviews.desktop @@ -37,10 +37,9 @@ Name[gl]=Vistas Name[he]=תצוגות Name[hi]=दृशà¥à¤¯ Name[hu]=Nézetek -Name[is]=Sýnir +Name[is]=Sýn Name[it]=Viste Name[ja]=ビューア -Name[ka]=ხედები Name[kk]=КөрініÑтері Name[km]=ទិដ្ឋភាព Name[lt]=ŽiÅ«rikliai @@ -66,8 +65,7 @@ Name[ta]=காடà¯à®šà®¿à®•à®³à¯ Name[tg]=Ðамудҳо Name[tr]=Görünümler Name[uk]=ПереглÑди -Name[uz]=KoÊ»rinishlar -Name[uz@cyrillic]=Кўринишлар +Name[uz]=Кўринишлар Name[zh_CN]=视图 Name[zh_TW]=檢視 Comment=KOrganizer View Configuration @@ -95,7 +93,6 @@ Comment[hu]=KOrganizer nézeti beállÃtások Comment[is]=Stillingar KOrganizer sýna Comment[it]=Configurazione viste di KOrganizer Comment[ja]=KOrganizer ビューアè¨å®š -Comment[ka]=KOrganizer ხედის კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ Comment[kk]=KOrganizer-дің көрініÑінің параметрлері Comment[km]=ការ​កំណážáŸ‹â€‹ážšáž…នាសម្ពáŸáž“្ធ​ទិដ្ឋភាព​របស់ KOrganizer Comment[lt]=KOrganizer žiÅ«riklių konfigÅ«ravimas @@ -138,7 +135,7 @@ Keywords[et]=korganizer,vaade Keywords[eu]=korganizer,ikuspegia Keywords[fa]=korganizer،نما Keywords[fi]=korganizer,näkymä -Keywords[fr]=korganizer,vues +Keywords[fr]=KOrganizer,vues Keywords[fy]=korganizer,weergave, werjefte Keywords[ga]=korganizer,amharc Keywords[gl]=korganizer,vista @@ -146,7 +143,6 @@ Keywords[hi]=के-आरà¥à¤—ेनाइज़र,दृशà¥à¤¯ Keywords[hu]=korganizer,nézet Keywords[is]=korganizer,sýn Keywords[it]=korganizer,viste -Keywords[ka]=korganizer,ხედი Keywords[km]=korganizer,ទិដ្ឋភាព Keywords[lt]=korganizer,view,žiÅ«rikliai Keywords[mk]=korganizer,view,корганизатор,приказ @@ -170,6 +166,5 @@ Keywords[ta]=கேஅமைபà¯à®ªà®¾à®³à®°à¯,காடà¯à®šà®¿ Keywords[tg]=korganizer,view,органайзер,намудҳо Keywords[tr]=korganizer,görünüm Keywords[uk]=korganizer,переглÑд -Keywords[uz]=korganizer,organayzer,koÊ»rinish -Keywords[uz@cyrillic]=korganizer,органайзер,кўриниш +Keywords[uz]=korganizer,органайзер,кўриниш Keywords[zh_CN]=korganizer,view,视图 diff --git a/korganizer/korganizer_part.cpp b/korganizer/korganizer_part.cpp index 572255494..65511bd18 100644 --- a/korganizer/korganizer_part.cpp +++ b/korganizer/korganizer_part.cpp @@ -52,7 +52,7 @@ #include <ktempfile.h> #include <kstatusbar.h> #include <kparts/genericfactory.h> - +#include <kparts/partmanager.h> #include <kparts/statusbarextension.h> #include <sidebarextension.h> @@ -109,8 +109,8 @@ KOrganizerPart::KOrganizerPart( TQWidget *parentWidget, const char *widgetName, KParts::InfoExtension *ie = new KParts::InfoExtension( this, "KOrganizerInfo" ); - connect( mView, TQT_SIGNAL( incidenceSelected( Incidence * ) ), - TQT_SLOT( slotChangeInfo( Incidence * ) ) ); + connect( mView, TQT_SIGNAL( incidenceSelected( Incidence *,const TQDate & ) ), + TQT_SLOT( slotChangeInfo( Incidence *,const TQDate & ) ) ); connect( this, TQT_SIGNAL( textChanged( const TQString & ) ), ie, TQT_SIGNAL( textChanged( const TQString & ) ) ); @@ -145,7 +145,7 @@ void KOrganizerPart::startCompleted( KProcess *process ) delete process; } -void KOrganizerPart::slotChangeInfo( Incidence *incidence ) +void KOrganizerPart::slotChangeInfo( Incidence *incidence, const TQDate & ) { if ( incidence ) { emit textChanged( incidence->summary() + " / " + @@ -234,4 +234,13 @@ void KOrganizerPart::setTitle() emit setWindowCaption( title );*/ } +bool KOrganizerPart::isCurrentlyActivePart() +{ + if ( manager() ) { + return ( manager()->activePart() == this ); + } else { + return false; + } +} + #include "korganizer_part.moc" diff --git a/korganizer/korganizer_part.h b/korganizer/korganizer_part.h index 25a4b9c4b..ad6a45081 100644 --- a/korganizer/korganizer_part.h +++ b/korganizer/korganizer_part.h @@ -51,6 +51,8 @@ namespace KOrg { class CalendarViewBase; } +class TQDate; + class KOrganizerPart: public KParts::ReadOnlyPart, public KOrg::MainWindow { @@ -81,10 +83,12 @@ class KOrganizerPart: public KParts::ReadOnlyPart, virtual KActionCollection *getActionCollection() const { return actionCollection(); } virtual void showStatusMessage( const TQString &message ); + virtual bool isCurrentlyActivePart(); + void setTitle(); public slots: - void slotChangeInfo( Incidence * ); + void slotChangeInfo( Incidence *incidence, const TQDate & ); protected: virtual bool openFile(); diff --git a/korganizer/korganizeriface.h b/korganizer/korganizeriface.h index f3d8a15ea..88ab61d50 100644 --- a/korganizer/korganizeriface.h +++ b/korganizer/korganizeriface.h @@ -21,7 +21,7 @@ #define KORGANIZERIFACE_H #include <dcopobject.h> - +#include <tqdatetime.h> class KOrganizerIface : virtual public DCOPObject { @@ -35,6 +35,7 @@ class KOrganizerIface : virtual public DCOPObject virtual bool saveAsURL(const TQString &url) = 0; virtual TQString getCurrentURLasString() const = 0; virtual bool editIncidence(const TQString &uid) = 0; + virtual bool editIncidence( const TQString &uid, const TQDate &date ) = 0; virtual bool deleteIncidence(const TQString &uid) = 0; virtual void syncAllResources() = 0; /** @@ -56,6 +57,13 @@ class KOrganizerIface : virtual public DCOPObject virtual void loadProfile( const TQString& path ) = 0; virtual void saveToProfile( const TQString& path ) const = 0; + + /** + * DCOP-enabled for KOrganizerUniqueAppHandler in the kontact plugin + * Returns true if the command line was successfully handled + * false otherwise. + */ + virtual bool handleCommandLine() = 0; }; #endif diff --git a/korganizer/korganizerifaceimpl.cpp b/korganizer/korganizerifaceimpl.cpp index 77db1afc7..e482e0f4a 100644 --- a/korganizer/korganizerifaceimpl.cpp +++ b/korganizer/korganizerifaceimpl.cpp @@ -91,6 +91,11 @@ bool KOrganizerIfaceImpl::editIncidence( const TQString &uid ) return mActionManager->editIncidence( uid ); } +bool KOrganizerIfaceImpl::editIncidence( const TQString &uid, const TQDate &date ) +{ + return mActionManager->editIncidence( uid, date ); +} + bool KOrganizerIfaceImpl::addIncidence( const TQString &ical ) { return mActionManager->addIncidence( ical ); @@ -103,12 +108,14 @@ bool KOrganizerIfaceImpl::canQueryClose() void KOrganizerIfaceImpl::loadProfile( const TQString& path ) { - mActionManager->loadProfile( path ); + mActionManager->loadProfile( path ); } void KOrganizerIfaceImpl::saveToProfile( const TQString& path ) const { - mActionManager->saveToProfile( path ); + mActionManager->saveToProfile( path ); } - +bool KOrganizerIfaceImpl::handleCommandLine() { + return mActionManager->handleCommandLine(); +} diff --git a/korganizer/korganizerifaceimpl.h b/korganizer/korganizerifaceimpl.h index 03f02a9e8..3efa4b17a 100644 --- a/korganizer/korganizerifaceimpl.h +++ b/korganizer/korganizerifaceimpl.h @@ -55,6 +55,8 @@ public: void syncAllResources(); bool editIncidence( const TQString &uid ); + bool editIncidence( const TQString &uid, const TQDate &date ); + /** @reimp from KOrganizerIface::deleteIncidence() */ bool deleteIncidence( const TQString &uid ) { return deleteIncidence( uid, false ); } /** @reimp from KOrganizerIface::deleteIncidence() */ @@ -69,6 +71,9 @@ public: /** @reimp from KOrganizerIface::saveToProfile() */ void saveToProfile( const TQString& path ) const; + /** @reimp from KOrganizerIface::handleCommandLine() */ + bool handleCommandLine(); + private: ActionManager* mActionManager; }; diff --git a/korganizer/kotimelineview.cpp b/korganizer/kotimelineview.cpp index ac40e2a31..1eb1084de 100644 --- a/korganizer/kotimelineview.cpp +++ b/korganizer/kotimelineview.cpp @@ -88,7 +88,7 @@ KCal::ListBase<KCal::Incidence> KOTimelineView::selectedIncidences() } /*virtual*/ -KCal::DateList KOTimelineView::selectedDates() +KCal::DateList KOTimelineView::selectedIncidenceDates() { return KCal::DateList(); } @@ -120,7 +120,7 @@ void KOTimelineView::showDates(const TQDate& start, const TQDate& end) TimelineItem *item = 0; CalendarResources *calres = dynamic_cast<CalendarResources*>( calendar() ); if ( !calres ) { - item = new TimelineItem( i18n("Calendar"), mGantt ); + item = new TimelineItem( i18n("Calendar"), calendar(), mGantt ); mCalendarItemMap[0][TQString()] = item; } else { CalendarResourceManager *manager = calres->resourceManager(); @@ -132,7 +132,7 @@ void KOTimelineView::showDates(const TQDate& start, const TQDate& end) TQString type = (*it)->subresourceType( *subit ); if ( !(*it)->subresourceActive( *subit ) || (!type.isEmpty() && type != "event") ) continue; - item = new TimelineItem( (*it)->labelForSubresource( *subit ), mGantt ); + item = new TimelineItem( (*it)->labelForSubresource( *subit ), calendar(), mGantt ); resourceColor = *KOPrefs::instance()->resourceColor( (*it)->identifier() ); TQColor subrescol = *KOPrefs::instance()->resourceColor( *subit ); if ( subrescol.isValid() ) @@ -142,7 +142,7 @@ void KOTimelineView::showDates(const TQDate& start, const TQDate& end) mCalendarItemMap[*it][*subit] = item; } } else { - item = new TimelineItem( (*it)->resourceName(), mGantt ); + item = new TimelineItem( (*it)->resourceName(), calendar(), mGantt ); if ( resourceColor.isValid() ) item->setColors( resourceColor, resourceColor, resourceColor ); mCalendarItemMap[*it][TQString()] = item; @@ -163,7 +163,7 @@ void KOTimelineView::showDates(const TQDate& start, const TQDate& end) } /*virtual*/ -void KOTimelineView::showIncidences(const KCal::ListBase<KCal::Incidence>&) +void KOTimelineView::showIncidences(const KCal::ListBase<KCal::Incidence>&, const TQDate &) { } @@ -198,14 +198,15 @@ void KOTimelineView::itemSelected( KDGanttViewItem *item ) { TimelineSubItem *tlitem = dynamic_cast<TimelineSubItem*>( item ); if ( tlitem ) - emit incidenceSelected( tlitem->incidence() ); + emit incidenceSelected( tlitem->incidence(), tlitem->originalStart().date() ); } void KOTimelineView::itemDoubleClicked( KDGanttViewItem *item ) { TimelineSubItem *tlitem = dynamic_cast<TimelineSubItem*>( item ); - if ( tlitem ) - emit editIncidenceSignal( tlitem->incidence() ); + if ( tlitem ) { + emit editIncidenceSignal( tlitem->incidence(), TQDate() ); + } } void KOTimelineView::itemRightClicked( KDGanttViewItem *item ) @@ -218,7 +219,7 @@ void KOTimelineView::itemRightClicked( KDGanttViewItem *item ) } if ( !mEventPopup ) mEventPopup = eventPopup(); - mEventPopup->showIncidencePopup( tlitem->incidence(), TQDate() ); + mEventPopup->showIncidencePopup( calendar(), tlitem->incidence(), TQDate() ); } bool KOTimelineView::eventDurationHint(TQDateTime & startDt, TQDateTime & endDt, bool & allDay) @@ -233,7 +234,7 @@ bool KOTimelineView::eventDurationHint(TQDateTime & startDt, TQDateTime & endDt, void KOTimelineView::newEventWithHint( const TQDateTime& dt ) { mHintDate = dt; - emit newEventSignal( dt ); + emit newEventSignal( 0/*ResourceCalendar*/, TQString()/*subResource*/, dt ); } TimelineItem * KOTimelineView::calendarItemForIncidence(KCal::Incidence * incidence) @@ -323,7 +324,7 @@ void KOTimelineView::itemMoved(KDGanttViewItem * item) if ( !tlit ) return; Incidence *i = tlit->incidence(); - mChanger->beginChange( i ); + mChanger->beginChange( i, 0, TQString() ); TQDateTime newStart = tlit->startTime(); if ( i->doesFloat() ) newStart = TQDateTime( newStart.date() ); @@ -341,7 +342,7 @@ void KOTimelineView::itemMoved(KDGanttViewItem * item) i->setDuration( duration ); TimelineItem *parent = static_cast<TimelineItem*>( tlit->parent() ); parent->moveItems( i, tlit->originalStart().secsTo( newStart ), duration + allDayOffset ); - mChanger->endChange( i ); + mChanger->endChange( i, 0, TQString() ); } void KOTimelineView::overscale(KDGanttView::Scale scale) diff --git a/korganizer/kotimelineview.h b/korganizer/kotimelineview.h index 5c3ec6a7c..81e1eef40 100644 --- a/korganizer/kotimelineview.h +++ b/korganizer/kotimelineview.h @@ -50,10 +50,10 @@ class KOTimelineView : public KOEventView ~KOTimelineView(); virtual KCal::ListBase<KCal::Incidence> selectedIncidences(); - virtual KCal::DateList selectedDates(); + virtual KCal::DateList selectedIncidenceDates(); virtual int currentDateCount(); virtual void showDates(const TQDate&, const TQDate&); - virtual void showIncidences(const KCal::ListBase<KCal::Incidence>&); + virtual void showIncidences(const KCal::ListBase<KCal::Incidence>&, const TQDate &date); virtual void updateView(); virtual void changeIncidenceDisplay(KCal::Incidence* incidence, int mode); virtual int maxDatesHint() { return 0; } diff --git a/korganizer/kotodoeditor.cpp b/korganizer/kotodoeditor.cpp index fe749c9c9..9d273b3a0 100644 --- a/korganizer/kotodoeditor.cpp +++ b/korganizer/kotodoeditor.cpp @@ -52,11 +52,9 @@ #include "kocore.h" KOTodoEditor::KOTodoEditor( Calendar *calendar, TQWidget *parent ) : - KOIncidenceEditor( TQString::null, calendar, parent ) + KOIncidenceEditor( TQString::null, calendar, parent ), + mTodo( 0 ), mCalendar( 0 ), mRelatedTodo( 0 ), mGeneral( 0 ), mRecurrence( 0 ) { - mTodo = 0; - mCalendar = 0; - mRelatedTodo = 0; } KOTodoEditor::~KOTodoEditor() @@ -66,11 +64,9 @@ KOTodoEditor::~KOTodoEditor() void KOTodoEditor::init() { - kdDebug(5850) << k_funcinfo << endl; setupGeneral(); setupRecurrence(); setupAttendeesTab(); -// setupAttachmentsTab(); connect( mGeneral, TQT_SIGNAL( dateTimeStrChanged( const TQString & ) ), mRecurrence, TQT_SLOT( setDateTimeStr( const TQString & ) ) ); @@ -82,11 +78,18 @@ void KOTodoEditor::init() connect( mDetails, TQT_SIGNAL(updateAttendeeSummary(int)), mGeneral, TQT_SLOT(updateAttendeeSummary(int)) ); + + connect( mGeneral, TQT_SIGNAL(editRecurrence()), + mRecurrenceDialog, TQT_SLOT(show()) ); + connect( mRecurrenceDialog, TQT_SIGNAL(okClicked()), + TQT_SLOT(updateRecurrenceSummary()) ); } void KOTodoEditor::reload() { - if ( mTodo ) readTodo( mTodo, mCalendar ); + if ( mTodo ) { + readTodo( mTodo, mCalendar, TQDate() ); + } } void KOTodoEditor::setupGeneral() @@ -115,8 +118,6 @@ void KOTodoEditor::setupGeneral() TQHBoxLayout *completionLayout = new TQHBoxLayout( topLayout2 ); mGeneral->initCompletion(topFrame2,completionLayout); - mGeneral->initAlarm(topFrame,topLayout); - mGeneral->initSecrecy( topFrame2, topLayout2 ); mGeneral->initDescription(topFrame2,topLayout2); } else { @@ -128,9 +129,6 @@ void KOTodoEditor::setupGeneral() mGeneral->initHeader( topFrame, topLayout ); mGeneral->initTime(topFrame,topLayout); mGeneral->initStatus(topFrame,topLayout); - TQBoxLayout *alarmLineLayout = new TQHBoxLayout(topLayout); - mGeneral->initAlarm(topFrame,alarmLineLayout); - alarmLineLayout->addStretch( 1 ); mGeneral->initDescription(topFrame,topLayout); mGeneral->initAttachments(topFrame,topLayout); connect( mGeneral, TQT_SIGNAL( openURL( const KURL& ) ), @@ -138,36 +136,25 @@ void KOTodoEditor::setupGeneral() connect( this, TQT_SIGNAL( signalAddAttachments( const TQStringList&, const TQStringList&, bool ) ), mGeneral, TQT_SLOT( addAttachments( const TQStringList&, const TQStringList&, bool ) ) ); } - mGeneral->enableAlarm( true ); - mGeneral->finishSetup(); } void KOTodoEditor::setupRecurrence() { - TQFrame *topFrame = addPage( i18n("Rec&urrence") ); - - TQBoxLayout *topLayout = new TQVBoxLayout( topFrame ); - - mRecurrence = new KOEditorRecurrence( topFrame ); - topLayout->addWidget( mRecurrence ); - - mRecurrence->setEnabled( false ); - connect(mGeneral,TQT_SIGNAL(dueDateEditToggle( bool ) ), - mRecurrence, TQT_SLOT( setEnabled( bool ) ) ); + mRecurrenceDialog = new KOEditorRecurrenceDialog( this ); + mRecurrenceDialog->hide(); + mRecurrence = mRecurrenceDialog->editor(); } -void KOTodoEditor::editIncidence(Incidence *incidence, Calendar *calendar) +void KOTodoEditor::editIncidence( Incidence *incidence, const TQDate &date, Calendar *calendar ) { kdDebug(5850) << k_funcinfo << endl; - Todo *todo=dynamic_cast<Todo*>(incidence); - if (todo) - { + Todo *todo = dynamic_cast<Todo*>( incidence ); + if ( todo ) { init(); - mTodo = todo; mCalendar = calendar; - readTodo( mTodo, mCalendar ); + readTodo( mTodo, mCalendar, date ); } setCaption( i18n("Edit To-do") ); @@ -195,18 +182,18 @@ void KOTodoEditor::setTexts( const TQString &summary, const TQString &descriptio } } - - void KOTodoEditor::loadDefaults() { kdDebug(5850) << k_funcinfo << endl; - setDates( TQDateTime::currentDateTime().addDays(7), true, 0 ); - mGeneral->toggleAlarm( true ); + setDates( TQDateTime::currentDateTime().addDays( 7 ), true, 0 ); + mGeneral->toggleAlarm( KOPrefs::instance()->defaultTodoReminders() ); } bool KOTodoEditor::processInput() { - if ( !validateInput() ) return false; + if ( !validateInput() ) { + return false; + } if ( mTodo ) { bool rc = true; @@ -217,14 +204,23 @@ bool KOTodoEditor::processInput() writeTodo( todo ); kdDebug(5850) << "KOTodoEditor::processInput() event written." << endl; - if( *mTodo == *todo ) + if ( *mTodo == *todo ) { // Don't do anything kdDebug(5850) << "Todo not changed\n"; - else { + } else { kdDebug(5850) << "Todo changed\n"; //IncidenceChanger::assignIncidence( mTodo, todo ); writeTodo( mTodo ); - mChanger->changeIncidence( oldTodo, mTodo ); + + KOGlobals::WhatChanged whatChanged; + + if ( !oldTodo->isCompleted() && todo->isCompleted() ) { + whatChanged = KOGlobals::COMPLETION_MODIFIED; + } else { + whatChanged = KOGlobals::NOTHING_MODIFIED; + } + + mChanger->changeIncidence( oldTodo, mTodo, whatChanged, this ); } delete todo; delete oldTodo; @@ -237,7 +233,7 @@ bool KOTodoEditor::processInput() writeTodo( mTodo ); - if ( !mChanger->addIncidence( mTodo, this ) ) { + if ( !mChanger->addIncidence( mTodo, mResource, mSubResource, this ) ) { delete mTodo; mTodo = 0; return false; @@ -250,9 +246,10 @@ bool KOTodoEditor::processInput() void KOTodoEditor::deleteTodo() { - if (mTodo) + if ( mTodo ) { emit deleteIncidenceSignal( mTodo ); - emit dialogClose(mTodo); + } + emit dialogClose( mTodo ); reject(); } @@ -271,18 +268,21 @@ void KOTodoEditor::setDates( const TQDateTime &due, bool allDay, Todo *relatedEv } mDetails->setDefaults(); - if ( mTodo ) + if ( mTodo ) { mRecurrence->setDefaults( mTodo->dtStart(), due, false ); - else + } else { mRecurrence->setDefaults( TQDateTime::currentDateTime(), due, false ); + } } -void KOTodoEditor::readTodo( Todo *todo, Calendar *calendar ) +void KOTodoEditor::readTodo( Todo *todo, Calendar *calendar, const TQDate &date ) { - if ( !todo ) return; + if ( !todo ) { + return; + } // mRelatedTodo = todo->relatedTo(); - kdDebug(5850)<<"read todo"<<endl; - mGeneral->readTodo( todo, calendar ); + + mGeneral->readTodo( todo, calendar, date ); mDetails->readEvent( todo ); mRecurrence->readIncidence( todo ); @@ -300,8 +300,9 @@ void KOTodoEditor::writeTodo( Todo *todo ) if ( *(oldIncidence->recurrence()) != *(todo->recurrence() ) ) { todo->setDtDue( todo->dtDue(), true ); - if ( todo->hasStartDate() ) + if ( todo->hasStartDate() ) { todo->setDtStart( todo->dtStart() ); + } } writeDesignerFields( todo ); @@ -328,10 +329,10 @@ int KOTodoEditor::msgItemDelete() i18n("KOrganizer Confirmation"), KStdGuiItem::del() ); } -void KOTodoEditor::modified (int /*modification*/) +void KOTodoEditor::modified() { - // Play dump, just reload the todo. This dialog has become so complicated that - // there is no point in trying to be smart here... + // Play dump, just reload the todo. This dialog has become so complicated + // that there is no point in trying to be smart here... reload(); } @@ -342,7 +343,7 @@ void KOTodoEditor::loadTemplate( /*const*/ CalendarLocal& cal ) KMessageBox::error( this, i18n("Template does not contain a valid to-do.") ); } else { - readTodo( todos.first(), 0 ); + readTodo( todos.first(), 0, TQDate() ); } } @@ -358,4 +359,12 @@ TQStringList& KOTodoEditor::templates() const return KOPrefs::instance()->mTodoTemplates; } +void KOTodoEditor::updateRecurrenceSummary() +{ + Todo *todo = new Todo(); + writeTodo( todo ); + mGeneral->updateRecurrenceSummary( todo ); + delete todo; +} + #include "kotodoeditor.moc" diff --git a/korganizer/kotodoeditor.h b/korganizer/kotodoeditor.h index 3b6df5b38..5ab3e36dd 100644 --- a/korganizer/kotodoeditor.h +++ b/korganizer/kotodoeditor.h @@ -60,12 +60,12 @@ class KOTodoEditor : public KOIncidenceEditor */ void setTexts( const TQString &summary, const TQString &description = TQString::null ); /** Edit an existing todo. */ - void editIncidence(Incidence *incidence, Calendar* calendar); + void editIncidence(Incidence *incidence, const TQDate &date, Calendar* calendar); /** Set widgets to default values */ void setDates( const TQDateTime &due, bool allDay = true, Todo *relatedTodo = 0 ); /** Read event object and setup widgets accordingly */ - void readTodo(Todo *todo, Calendar *calendar); + void readTodo(Todo *todo, Calendar *calendar, const TQDate &date); /** Write event settings to event object */ void writeTodo(Todo *); @@ -76,12 +76,14 @@ class KOTodoEditor : public KOIncidenceEditor bool processInput(); /** This todo has been modified externally */ - void modified (int change=0); + void modified(); protected slots: void loadDefaults(); void deleteTodo(); + void slotSaveTemplate( const TQString & ); + void updateRecurrenceSummary(); protected: void loadTemplate( /*const*/ CalendarLocal& ); @@ -98,6 +100,7 @@ class KOTodoEditor : public KOIncidenceEditor Todo *mRelatedTodo; KOEditorGeneralTodo *mGeneral; + KOEditorRecurrenceDialog *mRecurrenceDialog; KOEditorRecurrence *mRecurrence; }; diff --git a/korganizer/kotodoview.cpp b/korganizer/kotodoview.cpp index 3736bf29c..5951d8bc4 100644 --- a/korganizer/kotodoview.cpp +++ b/korganizer/kotodoview.cpp @@ -35,6 +35,7 @@ #include <kiconloader.h> #include <kmessagebox.h> +#include <libkcal/calhelper.h> #include <libkcal/icaldrag.h> #include <libkcal/vcaldrag.h> #include <libkcal/dndfactory.h> @@ -63,9 +64,10 @@ using namespace KOrg; #include "calprinter.h" #endif -KOTodoListViewToolTip::KOTodoListViewToolTip (TQWidget* parent, - KOTodoListView* lv ) - :TQToolTip(parent) +KOTodoListViewToolTip::KOTodoListViewToolTip (TQWidget *parent, + Calendar *calendar, + KOTodoListView *lv ) + :TQToolTip(parent), mCalendar( calendar ) { todolist=lv; } @@ -88,7 +90,7 @@ void KOTodoListViewToolTip::maybeTip( const TQPoint & pos) r.setRight(headerPos + todolist->header()->sectionSize(col)); /* Show the tip */ - TQString tipText( IncidenceFormatter::toolTipString( i->todo() ) );; + TQString tipText( IncidenceFormatter::toolTipStr( mCalendar, i->todo(), TQDate(), true ) );; if ( !tipText.isEmpty() ) { tip(r, tipText); } @@ -103,14 +105,10 @@ KOTodoListView::KOTodoListView( TQWidget *parent, const char *name ) { mOldCurrent = 0; mMousePressed = false; - - /* Create a Tooltip */ - tooltip = new KOTodoListViewToolTip( viewport(), this ); } KOTodoListView::~KOTodoListView() { - delete tooltip; } void KOTodoListView::setCalendar( Calendar *cal ) @@ -222,11 +220,12 @@ void KOTodoListView::contentsDropEvent( TQDropEvent *e ) } to = to->relatedTo(); } + Todo*oldTodo = existingTodo->clone(); - if ( mChanger->beginChange( existingTodo ) ) { + if ( mChanger->beginChange( existingTodo, 0, TQString() ) ) { existingTodo->setRelatedTo( destinationEvent ); - mChanger->changeIncidence( oldTodo, existingTodo, KOGlobals::RELATION_MODIFIED ); - mChanger->endChange( existingTodo ); + mChanger->changeIncidence( oldTodo, existingTodo, KOGlobals::RELATION_MODIFIED, this ); + mChanger->endChange( existingTodo, 0, TQString() ); } else { KMessageBox::sorry( this, i18n("Unable to change to-do's parent, " "because the to-do cannot be locked.") ); @@ -236,14 +235,13 @@ void KOTodoListView::contentsDropEvent( TQDropEvent *e ) } else { // kdDebug(5850) << "Drop new Todo" << endl; todo->setRelatedTo(destinationEvent); - if ( !mChanger->addIncidence( todo, this ) ) { + if ( !mChanger->addIncidence( todo, 0, TQString(), this ) ) { KODialogManager::errorSaveIncidence( this, todo ); delete todo; return; } } - } - else { + } else { TQString text; KOTodoViewItem *todoi = dynamic_cast<KOTodoViewItem *>(itemAt( contentsToViewport(e->pos()) )); if ( ! todoi ) { @@ -256,7 +254,7 @@ void KOTodoListView::contentsDropEvent( TQDropEvent *e ) //TQListViewItem *qlvi = itemAt( contentsToViewport(e->pos()) ); kdDebug(5850) << "Dropped : " << text << endl; Todo*todo = todoi->todo(); - if( mChanger->beginChange( todo ) ) { + if( mChanger->beginChange( todo, 0, TQString() ) ) { Todo*oldtodo = todo->clone(); if( text.startsWith( "file:" ) ) { @@ -273,8 +271,9 @@ void KOTodoListView::contentsDropEvent( TQDropEvent *e ) } } } - mChanger->changeIncidence( oldtodo, todo ); - mChanger->endChange( todo ); + //FIXME: attendees or attachment added, so there is something modified + mChanger->changeIncidence( oldtodo, todo, KOGlobals::NOTHING_MODIFIED, this ); + mChanger->endChange( todo, 0, TQString() ); } else { KMessageBox::sorry( this, i18n("Unable to add attendees to the to-do, " "because the to-do cannot be locked.") ); @@ -393,6 +392,7 @@ KOTodoView::KOTodoView( Calendar *calendar, TQWidget *parent, const char* name) mTodoListView->addColumn( i18n("Due Date/Time") ); mTodoListView->setColumnAlignment( eDueDateColumn, AlignLeft ); mTodoListView->addColumn( i18n("Categories") ); + mTodoListView->addColumn( i18n( "Calendar" ) ); #if 0 mTodoListView->addColumn( i18n("Sort Id") ); mTodoListView->setColumnAlignment( 4, AlignHCenter ); @@ -408,6 +408,7 @@ KOTodoView::KOTodoView( Calendar *calendar, TQWidget *parent, const char* name) mTodoListView->setColumnWidthMode( ePercentColumn, TQListView::Manual ); mTodoListView->setColumnWidthMode( eDueDateColumn, TQListView::Manual ); mTodoListView->setColumnWidthMode( eCategoriesColumn, TQListView::Manual ); + mTodoListView->setColumnWidthMode( eFolderColumn, TQListView::Manual ); #if 0 mTodoListView->setColumnWidthMode( eDescriptionColumn, TQListView::Manual ); #endif @@ -461,7 +462,7 @@ KOTodoView::KOTodoView( Calendar *calendar, TQWidget *parent, const char* name) TQT_SLOT (deleteTodo()), 0, ePopupDelete ); mItemPopupMenu->insertSeparator(); mItemPopupMenu->insertItem(KOGlobals::self()->smallIconSet("todo"), i18n("New &To-do..."), this, - TQT_SLOT (newTodo())); + TQT_SLOT (newTodo()) ); mItemPopupMenu->insertItem(i18n("New Su&b-to-do..."), this, TQT_SLOT (newSubTodo())); mItemPopupMenu->insertItem( i18n("&Make this To-do Independent"), this, @@ -482,7 +483,7 @@ KOTodoView::KOTodoView( Calendar *calendar, TQWidget *parent, const char* name) mPopupMenu = new TQPopupMenu(this); mPopupMenu->insertItem(KOGlobals::self()->smallIconSet("todo"), i18n("&New To-do..."), this, - TQT_SLOT (newTodo())); + TQT_SLOT(newTodo()) ); mPopupMenu->insertItem(i18n("delete completed to-dos","&Purge Completed"), this, TQT_SLOT(purgeCompleted())); @@ -514,6 +515,8 @@ KOTodoView::KOTodoView( Calendar *calendar, TQWidget *parent, const char* name) TQT_SLOT( processSelectionChange() ) ); connect( mQuickAdd, TQT_SIGNAL( returnPressed () ), TQT_SLOT( addQuickTodo() ) ); + + new KOTodoListViewToolTip( mTodoListView->viewport(), calendar, mTodoListView ); } KOTodoView::~KOTodoView() @@ -742,24 +745,21 @@ void KOTodoView::showDates(const TQDate &, const TQDate &) { } -void KOTodoView::showIncidences( const Incidence::List & ) +void KOTodoView::showIncidences( const Incidence::List &, const TQDate & ) { kdDebug(5850) << "KOTodoView::showIncidences( const Incidence::List & ): not yet implemented" << endl; } CalPrinterBase::PrintType KOTodoView::printType() { - if ( mTodoListView->selectedItem() ) { - return CalPrinterBase::Incidence; - } else { - return CalPrinterBase::Todolist; - } + return CalPrinterBase::Todolist; } void KOTodoView::editItem( TQListViewItem *item ) { - if (item) - emit editIncidenceSignal( static_cast<KOTodoViewItem *>( item )->todo() ); + if ( item ) { + emit editIncidenceSignal( static_cast<KOTodoViewItem *>( item )->todo(), TQDate () ); + } } void KOTodoView::editItem( TQListViewItem *item, const TQPoint &, int ) @@ -769,8 +769,9 @@ void KOTodoView::editItem( TQListViewItem *item, const TQPoint &, int ) void KOTodoView::showItem( TQListViewItem *item ) { - if (item) - emit showIncidenceSignal( static_cast<KOTodoViewItem *>( item )->todo() ); + if ( item ) { + emit showIncidenceSignal( static_cast<KOTodoViewItem *>( item )->todo(), TQDate() ); + } } void KOTodoView::showItem( TQListViewItem *item, const TQPoint &, int ) @@ -830,7 +831,8 @@ void KOTodoView::popupMenu( TQListViewItem *item, const TQPoint &, int column ) void KOTodoView::newTodo() { kdDebug() << k_funcinfo << endl; - emit newTodoSignal( TQDate::currentDate().addDays(7) ); + emit newTodoSignal( 0/*ResourceCalendar*/, TQString()/*subResource*/, + TQDate::currentDate().addDays(7) ); } void KOTodoView::newSubTodo() @@ -860,8 +862,15 @@ void KOTodoView::printTodo() Incidence::List selectedIncidences; selectedIncidences.append( mActiveItem->todo() ); + TQDateTime todoDate; + if ( mActiveItem->todo() && mActiveItem->todo()->hasStartDate() ) { + todoDate = mActiveItem->todo()->dtStart(); + } else { + todoDate = mActiveItem->todo()->dtDue(); + } + printer.print( KOrg::CalPrinterBase::Incidence, - TQDate(), TQDate(), selectedIncidences ); + todoDate.date(), todoDate.date(), selectedIncidences ); #endif } @@ -877,13 +886,13 @@ void KOTodoView::setNewPriority(int index) if ( !mActiveItem || !mChanger ) return; Todo *todo = mActiveItem->todo(); if ( !todo->isReadOnly () && - mChanger->beginChange( todo ) ) { + mChanger->beginChange( todo, 0, TQString() ) ) { Todo *oldTodo = todo->clone(); todo->setPriority(mPriority[index]); mActiveItem->construct(); - mChanger->changeIncidence( oldTodo, todo, KOGlobals::PRIORITY_MODIFIED ); - mChanger->endChange( todo ); + mChanger->changeIncidence( oldTodo, todo, KOGlobals::PRIORITY_MODIFIED, this ); + mChanger->endChange( todo, 0, TQString() ); delete oldTodo; } } @@ -895,7 +904,8 @@ void KOTodoView::setNewPercentage( KOTodoViewItem *item, int percentage ) Todo *todo = item->todo(); if ( !todo ) return; - if ( !todo->isReadOnly () && mChanger->beginChange( todo ) ) { + if ( !todo->isReadOnly () && + mChanger->beginChange( todo, 0, TQString() ) ) { Todo *oldTodo = todo->clone(); /* Old code to make sub-items's percentage related to this one's: @@ -910,18 +920,20 @@ void KOTodoView::setNewPercentage( KOTodoViewItem *item, int percentage ) todo->setCompleted( TQDateTime::currentDateTime() ); // If the todo does recur, it doesn't get set as completed. However, the // item is still checked. Uncheck it again. - if ( !todo->isCompleted() ) item->setState( TQCheckListItem::Off ); - else todo->setPercentComplete( percentage ); + if ( !todo->isCompleted() ) { + item->setState( TQCheckListItem::Off ); + } } else { - todo->setCompleted( false ); todo->setPercentComplete( percentage ); } item->construct(); if ( todo->doesRecur() && percentage == 100 ) - mChanger->changeIncidence( oldTodo, todo, KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ); + mChanger->changeIncidence( oldTodo, todo, + KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE, this ); else - mChanger->changeIncidence( oldTodo, todo, KOGlobals::COMPLETION_MODIFIED ); - mChanger->endChange( todo ); + mChanger->changeIncidence( oldTodo, todo, + KOGlobals::COMPLETION_MODIFIED, this ); + mChanger->endChange( todo, 0, TQString() ); delete oldTodo; } else { item->construct(); @@ -940,24 +952,22 @@ void KOTodoView::setNewDate( TQDate date ) Todo *todo = mActiveItem->todo(); if ( !todo ) return; - if ( !todo->isReadOnly() && mChanger->beginChange( todo ) ) { + if ( !todo->isReadOnly() && mChanger->beginChange( todo, 0, TQString() ) ) { Todo *oldTodo = todo->clone(); TQDateTime dt; dt.setDate( date ); - if ( !todo->doesFloat() ) + if ( !todo->doesFloat() ) { dt.setTime( todo->dtDue().time() ); + } - if ( date.isNull() ) - todo->setHasDueDate( false ); - else if ( !todo->hasDueDate() ) - todo->setHasDueDate( true ); + todo->setHasDueDate( !date.isNull() ); todo->setDtDue( dt ); mActiveItem->construct(); - mChanger->changeIncidence( oldTodo, todo, KOGlobals::COMPLETION_MODIFIED ); - mChanger->endChange( todo ); + mChanger->changeIncidence( oldTodo, todo, KOGlobals::COMPLETION_MODIFIED, this ); + mChanger->endChange( todo, 0, TQString() ); delete oldTodo; } else { kdDebug(5850) << "No active item, active item is read-only, or locking failed" << endl; @@ -969,19 +979,24 @@ void KOTodoView::copyTodoToDate( TQDate date ) TQDateTime dt( date ); if ( mActiveItem && mChanger ) { - Todo *newTodo = mActiveItem->todo()->clone(); + Todo *oldTodo = mActiveItem->todo(); + Todo *newTodo = oldTodo->clone(); newTodo->recreate(); - newTodo->setHasDueDate( !date.isNull() ); - newTodo->setDtDue( dt ); - newTodo->setPercentComplete( 0 ); + newTodo->setHasDueDate( !date.isNull() ); + + if ( oldTodo->hasDueDate() && !oldTodo->doesFloat() ) { + dt.setTime( oldTodo->dtDue().time() ); + } + + newTodo->setDtDue( dt ); + newTodo->setPercentComplete( 0 ); - // avoid forking - if ( newTodo->doesRecur() ) - newTodo->recurrence()->unsetRecurs(); + QPair<ResourceCalendar *, TQString>p = + CalHelper::incSubResourceCalendar( calendar(), mActiveItem->todo() ); - mChanger->addIncidence( newTodo, this ); - } + mChanger->addIncidence( newTodo, p.first, p.second, this ); + } } TQPopupMenu *KOTodoView::getCategoryPopupMenu( KOTodoViewItem *todoItem ) @@ -1011,7 +1026,7 @@ void KOTodoView::changedCategories(int index) Todo *todo = mActiveItem->todo(); if ( !todo ) return; - if ( !todo->isReadOnly() && mChanger->beginChange( todo ) ) { + if ( !todo->isReadOnly() && mChanger->beginChange( todo, 0, TQString() ) ) { Todo *oldTodo = todo->clone(); TQStringList categories = todo->categories (); @@ -1022,8 +1037,8 @@ void KOTodoView::changedCategories(int index) categories.sort(); todo->setCategories( categories ); mActiveItem->construct(); - mChanger->changeIncidence( oldTodo, todo, KOGlobals::CATEGORY_MODIFIED ); - mChanger->endChange( todo ); + mChanger->changeIncidence( oldTodo, todo, KOGlobals::CATEGORY_MODIFIED, this ); + mChanger->endChange( todo, 0, TQString() ); delete oldTodo; } else { kdDebug(5850) << "No active item, active item is read-only, or locking failed" << endl; @@ -1082,9 +1097,13 @@ void KOTodoView::processSelectionChange() static_cast<KOTodoViewItem *>( mTodoListView->selectedItem() ); if ( !item ) { - emit incidenceSelected( 0 ); + emit incidenceSelected( 0, TQDate() ); } else { - emit incidenceSelected( item->todo() ); + if ( selectedIncidenceDates().isEmpty() ) { + emit incidenceSelected( item->todo(), TQDate() ); + } else { + emit incidenceSelected( item->todo(), selectedIncidenceDates().first() ); + } } } @@ -1105,8 +1124,7 @@ void KOTodoView::addQuickTodo() todo->setSummary( mQuickAdd->text() ); todo->setOrganizer( Person( KOPrefs::instance()->fullName(), KOPrefs::instance()->email() ) ); - if ( !mChanger->addIncidence( todo, this ) ) { - KODialogManager::errorSaveIncidence( this, todo ); + if ( !mChanger->addIncidence( todo, 0, TQString(), this ) ) { delete todo; return; } diff --git a/korganizer/kotodoview.h b/korganizer/kotodoview.h index 7deaafded..bc7302d34 100644 --- a/korganizer/kotodoview.h +++ b/korganizer/kotodoview.h @@ -58,12 +58,13 @@ using namespace KOrg; class KOTodoListViewToolTip : public QToolTip { public: - KOTodoListViewToolTip( TQWidget *parent, KOTodoListView *lv ); + KOTodoListViewToolTip( TQWidget *parent, Calendar *calendar, KOTodoListView *lv ); protected: void maybeTip( const TQPoint &pos ); private: + Calendar *mCalendar; KOTodoListView *todolist; }; @@ -99,7 +100,6 @@ class KOTodoListView : public KListView TQPoint mPressPos; bool mMousePressed; TQListViewItem *mOldCurrent; - KOTodoListViewToolTip *tooltip; }; @@ -121,7 +121,7 @@ class KOTodoView : public KOrg::BaseView Incidence::List selectedIncidences(); Todo::List selectedTodos(); - DateList selectedDates() { return DateList(); } + DateList selectedIncidenceDates() { return DateList(); } /** Return number of shown dates. TodoView does not show dates, */ int currentDateCount() { return 0; } @@ -143,7 +143,7 @@ class KOTodoView : public KOrg::BaseView void changeIncidenceDisplay( Incidence *, int ); void showDates( const TQDate &start, const TQDate &end ); - void showIncidences( const Incidence::List &incidenceList ); + void showIncidences( const Incidence::List &incidenceList, const TQDate &date ); void clearSelection(); @@ -177,8 +177,8 @@ class KOTodoView : public KOrg::BaseView signals: void unSubTodoSignal(); void unAllSubTodoSignal(); - void purgeCompletedSignal(); + void configChanged(); protected slots: void processSelectionChange(); @@ -232,7 +232,7 @@ class KOTodoView : public KOrg::BaseView ePercentColumn = 3, eDueDateColumn = 4, eCategoriesColumn = 5, - eDescriptionColumn = 6 + eFolderColumn = 6 }; enum { ePopupEdit = 1300, diff --git a/korganizer/kotodoviewitem.cpp b/korganizer/kotodoviewitem.cpp index 7e5541fa3..f5b0adced 100644 --- a/korganizer/kotodoviewitem.cpp +++ b/korganizer/kotodoviewitem.cpp @@ -24,17 +24,19 @@ without including the source code for Qt in the source distribution. */ -#include <tqpainter.h> +#include "kotodoviewitem.h" +#include "kotodoview.h" +#include "koprefs.h" +#include "koglobals.h" + +#include <libkcal/incidenceformatter.h> #include <klocale.h> #include <kdebug.h> #include <tqpainter.h> #include <tqpixmap.h> -#include "kotodoviewitem.h" -#include "kotodoview.h" -#include "koprefs.h" -#include "koglobals.h" +#include <tqpainter.h> KOTodoViewItem::KOTodoViewItem( TQListView *parent, Todo *todo, KOTodoView *kotodo) : TQCheckListItem( parent , "", CheckBox ), mTodo( todo ), mTodoView( kotodo ) @@ -50,7 +52,7 @@ KOTodoViewItem::KOTodoViewItem( KOTodoViewItem *parent, Todo *todo, KOTodoView * inline int KOTodoViewItem::compareDueDates( const KOTodoViewItem *b ) const { - if ( mEffectiveDueDate.isValid() && + if ( mEffectiveDueDate.isValid() && !b->mEffectiveDueDate.isValid() ) return -1; else if ( !mEffectiveDueDate.isValid() && @@ -63,41 +65,57 @@ inline int KOTodoViewItem::compareDueDates( const KOTodoViewItem *b ) const int KOTodoViewItem::compare( TQListViewItem *it, int col, bool ascending ) const { KOTodoViewItem *i = dynamic_cast<KOTodoViewItem *>( it ); - if ( !i ) + if ( !i ) { return TQListViewItem::compare( it, col, ascending ); - + } + // throw completed todos to the bottom - if ( mTodo->isCompleted() && !i->todo()->isCompleted() ) + if ( mTodo->isCompleted() && !i->todo()->isCompleted() ) { return ascending ? 1 : -1; - else if ( !mTodo->isCompleted() && i->todo()->isCompleted() ) + } else if ( !mTodo->isCompleted() && i->todo()->isCompleted() ) { return ascending ? -1 : 1; - + } + int c; switch ( col ) { - case ( KOTodoView::eSummaryColumn ): - return mTodo->summary().localeAwareCompare( i->todo()->summary() ); - case ( KOTodoView::eRecurColumn ): - return ( mTodo->doesRecur() ? 1 : 0 ) - (i->todo()->doesRecur() ? 1 : 0 ); - case ( KOTodoView::ePriorityColumn ): - c = mTodo->priority() - i->todo()->priority(); - if ( c ) - return c; + case KOTodoView::eSummaryColumn: + return mTodo->summary().localeAwareCompare( i->todo()->summary() ); + + case KOTodoView::eRecurColumn: + return ( mTodo->doesRecur() ? 1 : 0 ) - ( i->todo()->doesRecur() ? 1 : 0 ); + + case KOTodoView::ePriorityColumn: + c = mTodo->priority() - i->todo()->priority(); + if ( c ) { + return c; + } else { return compareDueDates( i ); - case ( KOTodoView::ePercentColumn ): - return mTodo->percentComplete() - i->todo()->percentComplete(); - case ( KOTodoView::eDueDateColumn ): - c = compareDueDates( i ); - if ( c ) - return c; + } + + case KOTodoView::ePercentColumn: + return mTodo->percentComplete() - i->todo()->percentComplete(); + + case KOTodoView::eDueDateColumn: + c = compareDueDates( i ); + if ( c ) { + return c; + } else { return mTodo->priority() - i->todo()->priority(); - case ( KOTodoView::eCategoriesColumn ): - return mTodo->categoriesStr().localeAwareCompare( - i->todo()->categoriesStr() ); - case ( KOTodoView::eDescriptionColumn ): - return mTodo->description().localeAwareCompare( i->todo()->description() ); - default: - Q_ASSERT( false && "unknown column to compare" ); - return TQListViewItem::compare( it, col, ascending ); + } + case KOTodoView::eCategoriesColumn: + return mTodo->categoriesStr().localeAwareCompare( i->todo()->categoriesStr() ); + + case KOTodoView::eFolderColumn: + return TQListViewItem::compare( it, col, ascending ); + +#if 0 + case KOTodoView::eDescriptionColumn: + return mTodo->description().localeAwareCompare( i->todo()->description() ); +#endif + + default: + Q_ASSERT( false && "unknown column to compare" ); + return TQListViewItem::compare( it, col, ascending ); } } @@ -120,14 +138,14 @@ void KOTodoViewItem::construct() static const TQPixmap recurPxmp = KOGlobals::self()->smallIcon("recur"); if ( mTodo->doesRecur() ) setPixmap( KOTodoView::eRecurColumn, recurPxmp ); - + if ( mTodo->priority()==0 ) { setText( KOTodoView::ePriorityColumn, i18n("--") ); } else { setText( KOTodoView::ePriorityColumn, TQString::number(mTodo->priority()) ); } setText( KOTodoView::ePercentColumn, TQString::number(mTodo->percentComplete()) ); - + if (mTodo->hasDueDate()) { TQString dtStr = mTodo->dtDueDateStr(); if (!mTodo->doesFloat()) { @@ -143,9 +161,12 @@ void KOTodoViewItem::construct() } } else setText( KOTodoView::eDueDateColumn, "" ); - + setText( KOTodoView::eCategoriesColumn, mTodo->categoriesStr() ); + setText( KOTodoView::eFolderColumn, + IncidenceFormatter::resourceString( mTodoView->calendar(), mTodo ) ); + #if 0 // Find sort id in description. It's the text behind the last '#' character // found in the description. White spaces are removed from beginning and end @@ -173,7 +194,7 @@ void KOTodoViewItem::stateChange( bool state ) setOn( mTodo->isCompleted() ); return; } - + kdDebug(5850) << "State changed, modified " << state << endl; mTodoView->setNewPercentageDelayed( this, state ? 100 : 0 ); } diff --git a/korganizer/koviewmanager.cpp b/korganizer/koviewmanager.cpp index f086e1924..1906a07ee 100644 --- a/korganizer/koviewmanager.cpp +++ b/korganizer/koviewmanager.cpp @@ -26,9 +26,12 @@ #include <tqwidgetstack.h> #include <tqtabwidget.h> +#include <libkcal/calendarresources.h> +#include <kactioncollection.h> #include <kconfig.h> #include <kglobal.h> +#include "actionmanager.h" #include "calendarview.h" #include "datenavigator.h" #include "kotodoview.h" @@ -42,6 +45,7 @@ #include "koglobals.h" #include "navigatorbar.h" #include "multiagendaview.h" +#include <korganizer/mainwindow.h> #include "koviewmanager.h" #include "koviewmanager.moc" @@ -62,6 +66,8 @@ KOViewManager::KOViewManager( CalendarView *mainView ) : mJournalView = 0; mTimelineView = 0; mAgendaViewTabs = 0; + mAgendaViewTabIndex = 0; + mAgendaMode = AGENDA_NONE; } KOViewManager::~KOViewManager() @@ -85,7 +91,29 @@ void KOViewManager::readSettings(KConfig *config) else if (view == "Journal") showJournalView(); else if (view == "Todo") showTodoView(); else if (view == "Timeline") showTimelineView(); - else showAgendaView(); + else { + mAgendaMode = AgendaMode( config->readNumEntry( "Agenda Mode", AGENDA_OTHER ) ); + + switch ( mAgendaMode ) { + case AGENDA_WORK_WEEK: + showWorkWeekView(); + break; + case AGENDA_WEEK: + showWeekView(); + break; + case AGENDA_NEXTX: + showNextXView(); + break; + case AGENDA_DAY: + showDayView(); + break; + case AGENDA_NONE: + // Someone has been playing with the config file. + default: + mAgendaMode = AGENDA_OTHER; + showAgendaView(); + } + } } void KOViewManager::writeSettings(KConfig *config) @@ -99,7 +127,10 @@ void KOViewManager::writeSettings(KConfig *config) else if (mCurrentView == mJournalView) view = "Journal"; else if (mCurrentView == mTodoView) view = "Todo"; else if (mCurrentView == mTimelineView) view = "Timeline"; - else view = "Agenda"; + else { + view = "Agenda"; + config->writeEntry( "Agenda Mode", mAgendaMode ); + } config->writeEntry("Current View",view); @@ -127,13 +158,37 @@ void KOViewManager::showView(KOrg::BaseView *view) if ( mAgendaView ) mAgendaView->deleteSelectedDateTime(); raiseCurrentView(); - mMainView->processIncidenceSelection( 0 ); + + mMainView->processIncidenceSelection( 0, TQDate() ); mMainView->updateView(); mMainView->adaptNavigationUnits(); } +void KOViewManager::goMenu( bool enable ) +{ + KOrg::MainWindow *w = ActionManager::findInstance( KURL() ); + if ( w ) { + KActionCollection *ac = w->getActionCollection(); + if ( ac ) { + KAction *action; + action = ac->action( "go_today" ); + if ( action ) { + action->setEnabled( enable ); + } + action = ac->action( "go_previous" ); + if ( action ) { + action->setEnabled( enable ); + } + action = ac->action( "go_next" ); + if ( action ) { + action->setEnabled( enable ); + } + } + } +} + void KOViewManager::raiseCurrentView() { if ((mMonthView && KOPrefs::instance()->mFullViewMonth && mCurrentView == mMonthView) || @@ -170,44 +225,46 @@ void KOViewManager::connectView(KOrg::BaseView *view) if (!view) return; // selecting an incidence - connect( view, TQT_SIGNAL( incidenceSelected( Incidence * ) ), - mMainView, TQT_SLOT( processMainViewSelection( Incidence * ) ) ); + connect( view, TQT_SIGNAL( incidenceSelected( Incidence *,const TQDate & ) ), + mMainView, TQT_SLOT( processMainViewSelection( Incidence *,const TQDate & ) ) ); // showing/editing/deleting an incidence. The calendar view takes care of the action. - connect(view, TQT_SIGNAL(showIncidenceSignal(Incidence *)), - mMainView, TQT_SLOT(showIncidence(Incidence *))); - connect(view, TQT_SIGNAL(editIncidenceSignal(Incidence *)), - mMainView, TQT_SLOT(editIncidence(Incidence *))); - connect(view, TQT_SIGNAL(deleteIncidenceSignal(Incidence *)), - mMainView, TQT_SLOT(deleteIncidence(Incidence *))); - connect(view, TQT_SIGNAL(copyIncidenceSignal(Incidence *)), - mMainView, TQT_SLOT(copyIncidence(Incidence *))); - connect(view, TQT_SIGNAL(cutIncidenceSignal(Incidence *)), - mMainView, TQT_SLOT(cutIncidence(Incidence *))); - connect(view, TQT_SIGNAL(pasteIncidenceSignal()), - mMainView, TQT_SLOT(pasteIncidence())); - connect(view, TQT_SIGNAL(toggleAlarmSignal(Incidence *)), - mMainView, TQT_SLOT(toggleAlarm(Incidence *))); - connect(view,TQT_SIGNAL(dissociateOccurrenceSignal( Incidence *, const TQDate & )), - mMainView, TQT_SLOT(dissociateOccurrence( Incidence *, const TQDate & ))); - connect(view,TQT_SIGNAL(dissociateFutureOccurrenceSignal( Incidence *, const TQDate & )), - mMainView, TQT_SLOT(dissociateFutureOccurrence( Incidence *, const TQDate & ))); + connect( view, TQT_SIGNAL(showIncidenceSignal(Incidence *,const TQDate &)), + mMainView, TQT_SLOT(showIncidence(Incidence *,const TQDate &)) ); + connect( view, TQT_SIGNAL(editIncidenceSignal(Incidence *,const TQDate &)), + mMainView, TQT_SLOT(editIncidence(Incidence *,const TQDate &)) ); + connect( view, TQT_SIGNAL(deleteIncidenceSignal(Incidence *)), + mMainView, TQT_SLOT(deleteIncidence(Incidence *)) ); + connect( view, TQT_SIGNAL(copyIncidenceSignal(Incidence *)), + mMainView, TQT_SLOT(copyIncidence(Incidence *)) ); + connect( view, TQT_SIGNAL(cutIncidenceSignal(Incidence *)), + mMainView, TQT_SLOT(cutIncidence(Incidence *)) ); + connect( view, TQT_SIGNAL(pasteIncidenceSignal()), + mMainView, TQT_SLOT(pasteIncidence())); + connect( view, TQT_SIGNAL(toggleAlarmSignal(Incidence *)), + mMainView, TQT_SLOT(toggleAlarm(Incidence *)) ); + connect( view,TQT_SIGNAL(dissociateOccurrenceSignal(Incidence *,const TQDate &)), + mMainView, TQT_SLOT(dissociateOccurrence(Incidence *,const TQDate &)) ); + connect( view,TQT_SIGNAL(dissociateFutureOccurrenceSignal(Incidence *,const TQDate &)), + mMainView, TQT_SLOT(dissociateFutureOccurrence(Incidence *,const TQDate &)) ); // signals to create new incidences - connect( view, TQT_SIGNAL( newEventSignal() ), - mMainView, TQT_SLOT( newEvent() ) ); - connect( view, TQT_SIGNAL( newEventSignal( const TQDateTime & ) ), - mMainView, TQT_SLOT( newEvent( const TQDateTime & ) ) ); - connect( view, TQT_SIGNAL( newEventSignal( const TQDateTime &, const TQDateTime & ) ), - mMainView, TQT_SLOT( newEvent( const TQDateTime &, const TQDateTime & ) ) ); - connect( view, TQT_SIGNAL( newEventSignal( const TQDate & ) ), - mMainView, TQT_SLOT( newEvent( const TQDate & ) ) ); - connect( view, TQT_SIGNAL( newTodoSignal( const TQDate & ) ), - mMainView, TQT_SLOT( newTodo( const TQDate & ) ) ); - connect( view, TQT_SIGNAL( newSubTodoSignal( Todo * ) ), - mMainView, TQT_SLOT( newSubTodo( Todo *) ) ); - connect( view, TQT_SIGNAL( newJournalSignal( const TQDate & ) ), - mMainView, TQT_SLOT( newJournal( const TQDate & ) ) ); + connect( view, TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &)), + mMainView, TQT_SLOT(newEvent(ResourceCalendar *,const TQString &)) ); + connect( view, TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &,const TQDate &)), + mMainView, TQT_SLOT(newEvent(ResourceCalendar *,const TQString &,const TQDate &)) ); + connect( view, TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &,const TQDateTime &)), + mMainView, TQT_SLOT(newEvent(ResourceCalendar *,const TQString &,const TQDateTime &)) ); + connect( view, TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &,const TQDateTime &,const TQDateTime &)), + mMainView, TQT_SLOT(newEvent(ResourceCalendar *,const TQString &,const TQDateTime &,const TQDateTime &)) ); + + connect( view, TQT_SIGNAL(newTodoSignal(ResourceCalendar *,const TQString &,const TQDate &)), + mMainView, TQT_SLOT(newTodo(ResourceCalendar *,const TQString &,const TQDate &)) ); + connect( view, TQT_SIGNAL(newSubTodoSignal(Todo *)), + mMainView, TQT_SLOT(newSubTodo(Todo *)) ); + + connect( view, TQT_SIGNAL(newJournalSignal(ResourceCalendar *,const TQString &,const TQDate &)), + mMainView, TQT_SLOT(newJournal(ResourceCalendar *,const TQString &,const TQDate &)) ); // reload settings connect(mMainView, TQT_SIGNAL(configChanged()), view, TQT_SLOT(updateConfig())); @@ -235,7 +292,7 @@ void KOViewManager::connectTodoView( KOTodoView* todoView ) connect( todoView, TQT_SIGNAL( unSubTodoSignal() ), mMainView, TQT_SLOT( todo_unsub() ) ); connect( todoView, TQT_SIGNAL( unAllSubTodoSignal() ), - mMainView, TQT_SLOT( makeSubTodosIndependents() ) ); + mMainView, TQT_SLOT( makeSubTodosIndependent() ) ); } void KOViewManager::zoomInHorizontally() @@ -272,6 +329,7 @@ void KOViewManager::showWhatsNextView() "KOViewManager::WhatsNextView"); addView(mWhatsNextView); } + goMenu( true ); showView(mWhatsNextView); } @@ -281,14 +339,24 @@ void KOViewManager::showListView() mListView = new KOListView(mMainView->calendar(), mMainView->viewStack(), "KOViewManager::ListView"); addView(mListView); } + goMenu( true ); showView(mListView); } void KOViewManager::showAgendaView() { - const bool showBoth = KOPrefs::instance()->agendaViewCalendarDisplay() == KOPrefs::AllCalendarViews; - const bool showMerged = showBoth || KOPrefs::instance()->agendaViewCalendarDisplay() == KOPrefs::CalendarsMerged; - const bool showSideBySide = showBoth || KOPrefs::instance()->agendaViewCalendarDisplay() == KOPrefs::CalendarsSideBySide; + // If the user opens a local file, through menu->open ( for example ), then + // it doesn't make sense to use multiagenda. + CalendarResources *calres = dynamic_cast<CalendarResources*>( mMainView->calendar() ); + bool isLocalFile = !calres; + + int mode = KOPrefs::instance()->agendaViewCalendarDisplay(); + + const bool showBoth = ( mode == KOPrefs::AllCalendarViews && !isLocalFile ); + + const bool showMerged = showBoth || mode == KOPrefs::CalendarsMerged || isLocalFile; + + const bool showSideBySide = !isLocalFile && ( showBoth || mode == KOPrefs::CalendarsSideBySide ); TQWidget *parent = mMainView->viewStack(); if ( !mAgendaViewTabs && showBoth ) { @@ -296,10 +364,17 @@ void KOViewManager::showAgendaView() connect( mAgendaViewTabs, TQT_SIGNAL( currentChanged( TQWidget* ) ), this, TQT_SLOT( currentAgendaViewTabChanged( TQWidget* ) ) ); parent = mAgendaViewTabs; + + KConfig *config = KOGlobals::self()->config(); + config->setGroup( "Views" ); + mAgendaViewTabIndex = config->readNumEntry( "Agenda View Tab Index", 0 ); } if ( !mAgendaView && showMerged ) { - mAgendaView = new KOAgendaView(mMainView->calendar(), parent, "KOViewManager::AgendaView"); + mAgendaView = new KOAgendaView( mMainView->calendar(), + mMainView, + parent, + "KOViewManager::AgendaView" ); addView(mAgendaView); @@ -315,7 +390,7 @@ void KOViewManager::showAgendaView() if ( !mAgendaSideBySideView && showSideBySide ) { mAgendaSideBySideView = - new MultiAgendaView( mMainView->calendar(), parent, + new MultiAgendaView( mMainView->calendar(), mMainView, parent, "KOViewManager::AgendaSideBySideView" ); addView(mAgendaSideBySideView); @@ -332,8 +407,9 @@ void KOViewManager::showAgendaView() if ( showBoth && mAgendaViewTabs ) { if ( mAgendaView && mAgendaViewTabs->indexOf( mAgendaView ) < 0 ) mAgendaViewTabs->addTab( mAgendaView, i18n("Merged calendar") ); - if ( mAgendaSideBySideView && mAgendaViewTabs->indexOf( mAgendaSideBySideView ) < 0 ) + if ( mAgendaSideBySideView && mAgendaViewTabs->indexOf( mAgendaSideBySideView ) < 0 ) mAgendaViewTabs->addTab( mAgendaSideBySideView, i18n("Calendars Side by Side") ); + mAgendaViewTabs->setCurrentPage( mAgendaViewTabIndex ); } else { if ( mAgendaView && mMainView->viewStack()->id( mAgendaView ) < 0 ) mMainView->viewStack()->addWidget( mAgendaView ); @@ -341,6 +417,7 @@ void KOViewManager::showAgendaView() mMainView->viewStack()->addWidget( mAgendaSideBySideView ); } + goMenu( true ); if ( mAgendaViewTabs && showBoth ) showView( static_cast<KOrg::BaseView*>( mAgendaViewTabs->currentPage() ) ); else if ( mAgendaView && showMerged ) @@ -351,24 +428,28 @@ void KOViewManager::showAgendaView() void KOViewManager::showDayView() { + mAgendaMode = AGENDA_DAY; showAgendaView(); mMainView->dateNavigator()->selectDates( 1 ); } void KOViewManager::showWorkWeekView() { + mAgendaMode = AGENDA_WORK_WEEK; showAgendaView(); mMainView->dateNavigator()->selectWorkWeek(); } void KOViewManager::showWeekView() { + mAgendaMode = AGENDA_WEEK; showAgendaView(); mMainView->dateNavigator()->selectWeek(); } void KOViewManager::showNextXView() { + mAgendaMode = AGENDA_NEXTX; showAgendaView(); mMainView->dateNavigator()->selectDates( TQDate::currentDate(), KOPrefs::instance()->mNextXDays ); @@ -381,6 +462,7 @@ void KOViewManager::showMonthView() addView(mMonthView); } + goMenu( true ); showView(mMonthView); } @@ -397,6 +479,7 @@ void KOViewManager::showTodoView() mTodoView->restoreLayout( config, "Todo View" ); } + goMenu( false ); showView( mTodoView ); } @@ -408,6 +491,7 @@ void KOViewManager::showJournalView() addView(mJournalView); } + goMenu( true ); showView(mJournalView); } @@ -419,13 +503,18 @@ void KOViewManager::showTimelineView() "KOViewManager::TimelineView"); addView(mTimelineView); } + goMenu( true ); showView(mTimelineView); } void KOViewManager::showEventView() { - if ( mLastEventView ) showView( mLastEventView ); - else showWeekView(); + if ( mLastEventView ) { + goMenu( true ); + showView( mLastEventView ); + } else { + showWeekView(); + } } Incidence *KOViewManager::currentSelection() @@ -441,7 +530,7 @@ TQDate KOViewManager::currentSelectionDate() { TQDate qd; if (mCurrentView) { - DateList qvl = mCurrentView->selectedDates(); + DateList qvl = mCurrentView->selectedIncidenceDates(); if (!qvl.isEmpty()) qd = qvl.first(); } return qd; @@ -465,6 +554,11 @@ TQWidget* KOViewManager::widgetForView( KOrg::BaseView* view ) const void KOViewManager::currentAgendaViewTabChanged( TQWidget* widget ) { + KConfig *config = KOGlobals::self()->config(); + config->setGroup( "Views" ); + config->writeEntry( "Agenda View Tab Index", mAgendaViewTabs->currentPageIndex() ); + + goMenu( true ); showView( static_cast<KOrg::BaseView*>( widget ) ); } @@ -475,3 +569,19 @@ void KOViewManager::resourcesChanged() if ( mAgendaSideBySideView ) mAgendaSideBySideView->resourcesChanged(); } + +void KOViewManager::updateMultiCalendarDisplay() +{ + if ( agendaIsSelected() ) { + showAgendaView(); + } else { + updateView(); + } +} + +bool KOViewManager::agendaIsSelected() const +{ + return mCurrentView == mAgendaView || + mCurrentView == mAgendaSideBySideView || + ( mAgendaViewTabs && mCurrentView == mAgendaViewTabs->currentPage() ); +} diff --git a/korganizer/koviewmanager.h b/korganizer/koviewmanager.h index 32c55c3d4..9fe521e4f 100644 --- a/korganizer/koviewmanager.h +++ b/korganizer/koviewmanager.h @@ -53,6 +53,16 @@ class KOViewManager : public QObject { Q_OBJECT public: + + enum AgendaMode { + AGENDA_NONE, + AGENDA_DAY, + AGENDA_WORK_WEEK, + AGENDA_WEEK, + AGENDA_NEXTX, + AGENDA_OTHER // for example, showing 8 days + }; + KOViewManager( CalendarView * ); virtual ~KOViewManager(); @@ -74,6 +84,7 @@ class KOViewManager : public QObject void updateView(); void updateView( const TQDate &start, const TQDate &end ); + void goMenu( bool enable ); void raiseCurrentView(); void connectView( KOrg::BaseView * ); @@ -84,7 +95,25 @@ class KOViewManager : public QObject KOAgendaView *agendaView() const { return mAgendaView; } KOrg::MultiAgendaView *multiAgendaView() const { return mAgendaSideBySideView; } - KOTodoView *todoView() const { return mTodoView; } + KOTodoView *todoView() const { return mTodoView; } + KOMonthView *monthView() const { return mMonthView; } + + void updateMultiCalendarDisplay(); + + /* + * Returns true if the agenda is the current view. + * + * Never use the pointer returned by agendaView() + * to know if agenda is selected, because agenda has other modes + * (tabbed, side by side). Use this function instead. + */ + bool agendaIsSelected() const; + + /** + If the agenda view is selected it returns the current range mode: + week, work week, day or nextX days + */ + AgendaMode agendaMode() const { return mAgendaMode; } public slots: void showWhatsNextView(); @@ -129,6 +158,10 @@ class KOViewManager : public QObject KOrg::BaseView *mLastEventView; TQTabWidget *mAgendaViewTabs; + int mAgendaViewTabIndex; + + AgendaMode mAgendaMode; + }; #endif diff --git a/korganizer/kowhatsnextview.cpp b/korganizer/kowhatsnextview.cpp index 351972199..884b70b22 100644 --- a/korganizer/kowhatsnextview.cpp +++ b/korganizer/kowhatsnextview.cpp @@ -35,6 +35,7 @@ #include <kmessagebox.h> #include <libkcal/calendar.h> +#include <libkcal/incidenceformatter.h> #include "koglobals.h" #include "koprefs.h" @@ -244,7 +245,7 @@ void KOWhatsNextView::showDates( const TQDate &start, const TQDate &end ) updateView(); } -void KOWhatsNextView::showIncidences( const Incidence::List & ) +void KOWhatsNextView::showIncidences( const Incidence::List &, const TQDate & ) { } @@ -312,8 +313,8 @@ void KOWhatsNextView::appendTodo( Incidence *ev ) if ( ev->type()=="Todo" ) { Todo *todo = static_cast<Todo*>(ev); if ( todo->hasDueDate() ) { - mText += i18n(" (Due: %1)") - .arg( (todo->doesFloat())?(todo->dtDueDateStr()):(todo->dtDueStr()) ); + mText += i18n( " (Due: %1)" ). + arg( IncidenceFormatter::dateTimeToString( todo->dtDue(), todo->doesFloat() ) ); } } mText += "</li>\n"; @@ -329,7 +330,9 @@ void KOWhatsNextView::showIncidence( const TQString &uid ) } else if ( uid.startsWith( "todo://" ) ) { incidence = calendar()->incidence( uid.mid( 7 ) ); } - if ( incidence ) emit showIncidenceSignal( incidence ); + if ( incidence ) { + emit showIncidenceSignal( incidence, TQDate() ); + } } #include "kowhatsnextview.moc" diff --git a/korganizer/kowhatsnextview.h b/korganizer/kowhatsnextview.h index 6f49ab2b1..69c6a62eb 100644 --- a/korganizer/kowhatsnextview.h +++ b/korganizer/kowhatsnextview.h @@ -57,17 +57,19 @@ class KOWhatsNextView : public KOrg::BaseView virtual int currentDateCount(); virtual Incidence::List selectedIncidences() { return Incidence::List(); } - DateList selectedDates() { return DateList(); } + DateList selectedIncidenceDates() { return DateList(); } + + bool supportsDateNavigation() const { return true; } public slots: virtual void updateView(); virtual void showDates(const TQDate &start, const TQDate &end); - virtual void showIncidences( const Incidence::List &incidenceList ); + virtual void showIncidences( const Incidence::List &incidenceList, const TQDate &date ); void changeIncidenceDisplay(Incidence *, int); protected: - void appendEvent( Incidence *, const TQDateTime &start = TQDateTime(), + void appendEvent( Incidence *, const TQDateTime &start = TQDateTime(), const TQDateTime &end = TQDateTime() ); void appendTodo( Incidence * ); diff --git a/korganizer/multiagendaview.cpp b/korganizer/multiagendaview.cpp index fb5cd6255..a6aa51665 100644 --- a/korganizer/multiagendaview.cpp +++ b/korganizer/multiagendaview.cpp @@ -30,6 +30,7 @@ #include <tqlayout.h> #include <tqvbox.h> #include <tqobjectlist.h> +#include <tqheader.h> #define FOREACH_VIEW(av) \ for(TQValueList<KOAgendaView*>::ConstIterator it = mAgendaViews.constBegin(); \ @@ -39,20 +40,23 @@ for(TQValueList<KOAgendaView*>::ConstIterator it = mAgendaViews.constBegin(); \ using namespace KOrg; -MultiAgendaView::MultiAgendaView(Calendar * cal, TQWidget * parent, const char *name ) : +MultiAgendaView::MultiAgendaView( Calendar * cal, CalendarView *calendarView, + TQWidget * parent, const char *name ) : AgendaView( cal, parent, name ), + mSelectedAgendaView( 0 ), mLastMovedSplitter( 0 ), mUpdateOnShow( false ), - mPendingChanges( true ) + mPendingChanges( true ), + mCalendarView( calendarView ) { TQBoxLayout *topLevelLayout = new TQHBoxLayout( this ); TQFontMetrics fm( font() ); - int topLabelHeight = 2 * fm.height(); + int topLabelHeight = 2 * fm.height() + fm.lineSpacing(); TQVBox *topSideBox = new TQVBox( this ); - TQWidget *topSideSpacer = new TQWidget( topSideBox ); - topSideSpacer->setFixedHeight( topLabelHeight ); + mLeftTopSpacer = new TQWidget( topSideBox ); + mLeftTopSpacer->setFixedHeight( topLabelHeight ); mLeftSplitter = new TQSplitter( Qt::Vertical, topSideBox ); mLeftSplitter->setOpaqueResize( KGlobalSettings::opaqueResize() ); TQLabel *label = new TQLabel( i18n("All Day"), mLeftSplitter ); @@ -75,8 +79,8 @@ MultiAgendaView::MultiAgendaView(Calendar * cal, TQWidget * parent, const char * mScrollView->addChild( mTopBox ); topSideBox = new TQVBox( this ); - topSideSpacer = new TQWidget( topSideBox ); - topSideSpacer->setFixedHeight( topLabelHeight ); + mRightTopSpacer = new TQWidget( topSideBox ); + mRightTopSpacer->setFixedHeight( topLabelHeight ); mRightSplitter = new TQSplitter( Qt::Vertical, topSideBox ); mRightSplitter->setOpaqueResize( KGlobalSettings::opaqueResize() ); new TQWidget( mRightSplitter ); @@ -96,8 +100,10 @@ MultiAgendaView::MultiAgendaView(Calendar * cal, TQWidget * parent, const char * void MultiAgendaView::recreateViews() { - if ( !mPendingChanges ) + if ( !mPendingChanges ) { return; + } + mPendingChanges = false; deleteViews(); @@ -105,9 +111,10 @@ void MultiAgendaView::recreateViews() CalendarResources *calres = dynamic_cast<CalendarResources*>( calendar() ); if ( !calres ) { // fallback to single-agenda - KOAgendaView* av = new KOAgendaView( calendar(), mTopBox ); + KOAgendaView* av = new KOAgendaView( calendar(), mCalendarView, mTopBox ); mAgendaViews.append( av ); mAgendaWidgets.append( av ); + mSelectedAgendaView = av; av->show(); } else { CalendarResourceManager *manager = calres->resourceManager(); @@ -116,8 +123,11 @@ void MultiAgendaView::recreateViews() TQStringList subResources = (*it)->subresources(); for ( TQStringList::ConstIterator subit = subResources.constBegin(); subit != subResources.constEnd(); ++subit ) { TQString type = (*it)->subresourceType( *subit ); - if ( !(*it)->subresourceActive( *subit ) || (!type.isEmpty() && type != "event") ) + + if ( !(*it)->subresourceActive( *subit ) || (!type.isEmpty() && type != "event") ) { continue; + } + addView( (*it)->labelForSubresource( *subit ), *it, *subit ); } } else { @@ -127,19 +137,14 @@ void MultiAgendaView::recreateViews() } // no resources activated, so stop here to avoid crashing somewhere down the line, TODO: show a nice message instead - if ( mAgendaViews.isEmpty() ) + if ( mAgendaViews.isEmpty() ) { return; + } setupViews(); TQTimer::singleShot( 0, this, TQT_SLOT(slotResizeScrollView()) ); mTimeLabels->updateConfig(); - TQScrollBar *scrollBar = mAgendaViews.first()->agenda()->verticalScrollBar(); - mScrollBar->setMinValue( scrollBar->minValue() ); - mScrollBar->setMaxValue( scrollBar->maxValue() ); - mScrollBar->setLineStep( scrollBar->lineStep() ); - mScrollBar->setPageStep( scrollBar->pageStep() ); - mScrollBar->setValue( scrollBar->value() ); connect( mTimeLabels->verticalScrollBar(), TQT_SIGNAL(valueChanged(int)), mScrollBar, TQT_SLOT(setValue(int)) ); connect( mScrollBar, TQT_SIGNAL(valueChanged(int)), @@ -147,7 +152,20 @@ void MultiAgendaView::recreateViews() installSplitterEventFilter( mLeftSplitter ); installSplitterEventFilter( mRightSplitter ); - resizeSplitters(); + + TQValueList<int> sizes = KOGlobals::self()->config()->readIntListEntry( "Separator AgendaView" ); + if ( sizes.count() != 2 ) { + sizes = mLeftSplitter->sizes(); + } + FOREACH_VIEW( agenda ) { + agenda->splitter()->setSizes( sizes ); + } + mLeftSplitter->setSizes( sizes ); + mRightSplitter->setSizes( sizes ); + + TQTimer::singleShot( 0, this, TQT_SLOT(setupScrollBar()) ); + + mTimeLabels->positionChanged(); } void MultiAgendaView::deleteViews() @@ -159,60 +177,88 @@ void MultiAgendaView::deleteViews() mAgendaViews.clear(); mAgendaWidgets.clear(); mLastMovedSplitter = 0; + mSelectedAgendaView = 0; } void MultiAgendaView::setupViews() { FOREACH_VIEW( agenda ) { - connect( agenda, TQT_SIGNAL( newEventSignal() ), - TQT_SIGNAL( newEventSignal() ) ); - connect( agenda, TQT_SIGNAL( editIncidenceSignal( Incidence * ) ), - TQT_SIGNAL( editIncidenceSignal( Incidence * ) ) ); - connect( agenda, TQT_SIGNAL( showIncidenceSignal( Incidence * ) ), - TQT_SIGNAL( showIncidenceSignal( Incidence * ) ) ); - connect( agenda, TQT_SIGNAL( deleteIncidenceSignal( Incidence * ) ), - TQT_SIGNAL( deleteIncidenceSignal( Incidence * ) ) ); - connect( agenda, TQT_SIGNAL( startMultiModify( const TQString & ) ), - TQT_SIGNAL( startMultiModify( const TQString & ) ) ); - connect( agenda, TQT_SIGNAL( endMultiModify() ), - TQT_SIGNAL( endMultiModify() ) ); - - connect( agenda, TQT_SIGNAL( incidenceSelected( Incidence * ) ), - TQT_SIGNAL( incidenceSelected( Incidence * ) ) ); - - connect( agenda, TQT_SIGNAL(cutIncidenceSignal(Incidence*)), - TQT_SIGNAL(cutIncidenceSignal(Incidence*)) ); - connect( agenda, TQT_SIGNAL(copyIncidenceSignal(Incidence*)), + if ( !agenda->readOnly() ) { + connect( agenda, + TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &)), + TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &)) ); + connect( agenda, + TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &,const TQDate &)), + TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &,const TQDate &)) ); + connect( agenda, + TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &,const TQDateTime &)), + TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &,const TQDateTime &)) ); + connect( agenda, + TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &,const TQDateTime &,const TQDateTime &)), + TQT_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &,const TQDateTime &,const TQDateTime&)) ); + + connect( agenda, + TQT_SIGNAL(newTodoSignal(ResourceCalendar *,const TQString &,const TQDate &)), + TQT_SIGNAL(newTodoSignal(ResourceCalendar *,const TQString &,const TQDate &)) ); + + connect( agenda, + TQT_SIGNAL(editIncidenceSignal(Incidence *,const TQDate &)), + TQT_SIGNAL(editIncidenceSignal(Incidence *,const TQDate &)) ); + connect( agenda, + TQT_SIGNAL(deleteIncidenceSignal(Incidence *)), + TQT_SIGNAL(deleteIncidenceSignal(Incidence *)) ); + connect( agenda, + TQT_SIGNAL(startMultiModify(const TQString &)), + TQT_SIGNAL(startMultiModify(const TQString &)) ); + connect( agenda, + TQT_SIGNAL(endMultiModify()), + TQT_SIGNAL(endMultiModify()) ); + + connect( agenda, + TQT_SIGNAL(cutIncidenceSignal(Incidence*)), + TQT_SIGNAL(cutIncidenceSignal(Incidence*)) ); + connect( agenda, + TQT_SIGNAL(pasteIncidenceSignal()), + TQT_SIGNAL(pasteIncidenceSignal()) ); + connect( agenda, + TQT_SIGNAL(toggleAlarmSignal(Incidence*)), + TQT_SIGNAL(toggleAlarmSignal(Incidence*)) ); + connect( agenda, + TQT_SIGNAL(dissociateOccurrenceSignal(Incidence*, const TQDate&)), + TQT_SIGNAL(dissociateOccurrenceSignal(Incidence*, const TQDate&)) ); + connect( agenda, + TQT_SIGNAL(dissociateFutureOccurrenceSignal(Incidence*, const TQDate&)), + TQT_SIGNAL(dissociateFutureOccurrenceSignal(Incidence*, const TQDate&)) ); + } + + connect( agenda, + TQT_SIGNAL(copyIncidenceSignal(Incidence*)), TQT_SIGNAL(copyIncidenceSignal(Incidence*)) ); - connect( agenda, TQT_SIGNAL(pasteIncidenceSignal()), - TQT_SIGNAL(pasteIncidenceSignal()) ); - connect( agenda, TQT_SIGNAL(toggleAlarmSignal(Incidence*)), - TQT_SIGNAL(toggleAlarmSignal(Incidence*)) ); - connect( agenda, TQT_SIGNAL(dissociateOccurrenceSignal(Incidence*, const TQDate&)), - TQT_SIGNAL(dissociateOccurrenceSignal(Incidence*, const TQDate&)) ); - connect( agenda, TQT_SIGNAL(dissociateFutureOccurrenceSignal(Incidence*, const TQDate&)), - TQT_SIGNAL(dissociateFutureOccurrenceSignal(Incidence*, const TQDate&)) ); - - connect( agenda, TQT_SIGNAL(newEventSignal(const TQDate&)), - TQT_SIGNAL(newEventSignal(const TQDate&)) ); - connect( agenda, TQT_SIGNAL(newEventSignal(const TQDateTime&)), - TQT_SIGNAL(newEventSignal(const TQDateTime&)) ); - connect( agenda, TQT_SIGNAL(newEventSignal(const TQDateTime&, const TQDateTime&)), - TQT_SIGNAL(newEventSignal(const TQDateTime&, const TQDateTime&)) ); - connect( agenda, TQT_SIGNAL(newTodoSignal(const TQDate&)), - TQT_SIGNAL(newTodoSignal(const TQDate&)) ); - - connect( agenda, TQT_SIGNAL(incidenceSelected(Incidence*)), + connect( agenda, + TQT_SIGNAL(showIncidenceSignal(Incidence *,const TQDate &)), + TQT_SIGNAL(showIncidenceSignal(Incidence *,const TQDate &)) ); + connect( agenda, + TQT_SIGNAL(incidenceSelected(Incidence *,const TQDate &)), + TQT_SIGNAL(incidenceSelected(Incidence *,const TQDate &)) ); + connect( agenda, + TQT_SIGNAL(incidenceSelected(Incidence*,const TQDate &)), TQT_SLOT(slotSelectionChanged()) ); - connect( agenda, TQT_SIGNAL(timeSpanSelectionChanged()), + connect( agenda, + TQT_SIGNAL(timeSpanSelectionChanged()), TQT_SLOT(slotClearTimeSpanSelection()) ); - disconnect( agenda->agenda(), TQT_SIGNAL(zoomView(const int,const TQPoint&,const Qt::Orientation)), agenda, 0 ); - connect( agenda->agenda(), TQT_SIGNAL(zoomView(const int,const TQPoint&,const Qt::Orientation)), + disconnect( agenda->agenda(), + TQT_SIGNAL(zoomView(const int,const TQPoint&,const Qt::Orientation)), + agenda, 0 ); + connect( agenda->agenda(), + TQT_SIGNAL(zoomView(const int,const TQPoint&,const Qt::Orientation)), TQT_SLOT(zoomView(const int,const TQPoint&,const Qt::Orientation)) ); } + KOAgenda *anAgenda = mAgendaViews.first()->agenda(); + connect( anAgenda, TQT_SIGNAL(lowerYChanged(int) ), TQT_SLOT(resizeSpacers(int)) ); + FOREACH_VIEW( agenda ) { agenda->readSettings(); } @@ -237,11 +283,11 @@ Incidence::List MultiAgendaView::selectedIncidences() return list; } -DateList MultiAgendaView::selectedDates() +DateList MultiAgendaView::selectedIncidenceDates() { DateList list; FOREACH_VIEW(agendaView) { - list += agendaView->selectedDates(); + list += agendaView->selectedIncidenceDates(); } return list; } @@ -262,10 +308,10 @@ void MultiAgendaView::showDates(const TQDate & start, const TQDate & end) agendaView->showDates( start, end ); } -void MultiAgendaView::showIncidences(const Incidence::List & incidenceList) +void MultiAgendaView::showIncidences(const Incidence::List & incidenceList, const TQDate &date) { FOREACH_VIEW( agendaView ) - agendaView->showIncidences( incidenceList ); + agendaView->showIncidences( incidenceList, date ); } void MultiAgendaView::updateView() @@ -326,12 +372,35 @@ void MultiAgendaView::finishTypeAhead() agenda->finishTypeAhead(); } -void MultiAgendaView::addView( const TQString &label, KCal::ResourceCalendar * res, const TQString & subRes ) +void MultiAgendaView::addView( const TQString &label, ResourceCalendar *res, const TQString &subRes ) { + bool readOnlyView = false; + TQVBox *box = new TQVBox( mTopBox ); - TQLabel *l = new TQLabel( label, box ); - l->setAlignment( AlignVCenter | AlignHCenter ); - KOAgendaView* av = new KOAgendaView( calendar(), box, 0, true ); + + // First, the calendar folder title + TQHeader *title = new TQHeader( 1, box ); + title->setClickEnabled( false ); + title->setStretchEnabled( true ); + if ( res->readOnly() || !res->subresourceWritable( subRes ) ) { + readOnlyView = true; + title->setLabel( 0, TQIconSet( KOGlobals::self()->smallIcon( "readonlyevent" ) ), label ); + } else { + TQColor resColor; + if ( subRes.isEmpty() ) { + resColor = *KOPrefs::instance()->resourceColor( res->identifier() ); + } else { + resColor = *KOPrefs::instance()->resourceColor( subRes ); + } + TQFontMetrics fm = fontMetrics(); + TQPixmap px( fm.height(), fm.height() ); + px.fill( resColor ); + title->setLabel( 0, TQIconSet( px, TQIconSet::Small ), label ); + } + + // Now, the sub agenda view + KOAgendaView* av = new KOAgendaView( calendar(), mCalendarView, box, 0, true ); + av->setReadOnly( readOnlyView ); av->setResource( res, subRes ); av->setIncidenceChanger( mChanger ); av->agenda()->setVScrollBarMode( TQScrollView::AlwaysOff ); @@ -345,6 +414,7 @@ void MultiAgendaView::addView( const TQString &label, KCal::ResourceCalendar * r connect( mTimeLabels->verticalScrollBar(), TQT_SIGNAL(valueChanged(int)), av, TQT_SLOT(setContentsPos(int)) ); + av->installEventFilter( this ); installSplitterEventFilter( av->splitter() ); } @@ -387,10 +457,10 @@ void MultiAgendaView::updateConfig() agenda->updateConfig(); } -// KDE4: not needed anymore, TQSplitter has a moved signal there bool MultiAgendaView::eventFilter(TQObject * obj, TQEvent * event) { if ( obj->className() == TQCString("QSplitterHandle") ) { + // KDE4: not needed anymore, TQSplitter has a moved signal there if ( (event->type() == TQEvent::MouseMove && KGlobalSettings::opaqueResize()) || event->type() == TQEvent::MouseButtonRelease ) { FOREACH_VIEW( agenda ) { @@ -404,9 +474,22 @@ bool MultiAgendaView::eventFilter(TQObject * obj, TQEvent * event) TQTimer::singleShot( 0, this, TQT_SLOT(resizeSplitters()) ); } } + + if ( obj->className() == TQCString( "KOAgendaView" ) ) { + if ( event->type() == TQEvent::MouseButtonRelease || + event->type() == TQEvent::MouseButtonPress ) { + mSelectedAgendaView = (KOAgendaView *)obj; + } + } + return AgendaView::eventFilter( obj, event ); } +KOAgendaView *MultiAgendaView::selectedAgendaView() +{ + return mSelectedAgendaView; +} + void MultiAgendaView::resizeSplitters() { if ( !mLastMovedSplitter ) @@ -422,6 +505,21 @@ void MultiAgendaView::resizeSplitters() mRightSplitter->setSizes( mLastMovedSplitter->sizes() ); } +void MultiAgendaView::resizeSpacers( int newY ) +{ + // this slot is needed because the Agenda view's day labels frame height + // can change depending if holidays are shown. When this happens, all + // the widgets move down except the timelabels, so we need to change + // the top spacer height accordingly to move the timelabels up/down. + // kolab/issue2656 + Q_UNUSED( newY ); + TQFontMetrics fm( font() ); + int topLabelHeight = mAgendaViews.first()->dayLabels()->height() + + fm.height() + mLeftSplitter->handleWidth(); + mLeftTopSpacer->setFixedHeight( topLabelHeight ); + mRightTopSpacer->setFixedHeight( topLabelHeight ); +} + void MultiAgendaView::zoomView( const int delta, const TQPoint & pos, const Qt::Orientation ori ) { if ( ori == Qt::Vertical ) { @@ -477,8 +575,45 @@ void MultiAgendaView::show() void MultiAgendaView::resourcesChanged() { mPendingChanges = true; + + kdDebug() << "mAgendaViews.size is " << mAgendaViews.size() + << "; mAgendaWidgets.size is " << mAgendaWidgets.size() + << "; mSelectedAgendaView is " << mSelectedAgendaView + << endl; + + if ( mSelectedAgendaView ) { + ResourceCalendar *res = mSelectedAgendaView->resourceCalendar(); + if ( res ) { + if ( res->canHaveSubresources() ) { + TQString subRes = mSelectedAgendaView->subResourceCalendar(); + if ( !res->subresourceWritable( subRes ) || + !res->subresourceActive( subRes ) ) { + mSelectedAgendaView = 0; + } + } else { + if ( res->readOnly() || !res->isActive() ) { + mSelectedAgendaView = 0; + } + } + } else { + mSelectedAgendaView = 0; + } + } + FOREACH_VIEW( agenda ) agenda->resourcesChanged(); } +void MultiAgendaView::setupScrollBar() +{ + if ( !mAgendaViews.isEmpty() && mAgendaViews.first()->agenda() ) { + TQScrollBar *scrollBar = mAgendaViews.first()->agenda()->verticalScrollBar(); + mScrollBar->setMinValue( scrollBar->minValue() ); + mScrollBar->setMaxValue( scrollBar->maxValue() ); + mScrollBar->setLineStep( scrollBar->lineStep() ); + mScrollBar->setPageStep( scrollBar->pageStep() ); + mScrollBar->setValue( scrollBar->value() ); + } +} + #include "multiagendaview.moc" diff --git a/korganizer/multiagendaview.h b/korganizer/multiagendaview.h index d7316698d..ebdfc9005 100644 --- a/korganizer/multiagendaview.h +++ b/korganizer/multiagendaview.h @@ -20,6 +20,7 @@ #define KORG_MULTIAGENDAVIEW_H_H #include "agendaview.h" +#include "calendarview.h" class TQScrollView; class TQHBox; @@ -41,11 +42,14 @@ class MultiAgendaView : public AgendaView { Q_OBJECT public: - explicit MultiAgendaView( Calendar* cal, TQWidget *parent = 0, const char *name = 0 ); + explicit MultiAgendaView( Calendar* cal, CalendarView *calendarView, + TQWidget *parent = 0, const char *name = 0 ); ~MultiAgendaView(); + KOAgendaView *selectedAgendaView(); + void deSelectAgendaView() { mSelectedAgendaView = 0; } Incidence::List selectedIncidences(); - DateList selectedDates(); + DateList selectedIncidenceDates(); int currentDateCount(); int maxDatesHint(); @@ -55,7 +59,7 @@ class MultiAgendaView : public AgendaView public slots: void showDates( const TQDate &start, const TQDate &end ); - void showIncidences( const Incidence::List &incidenceList ); + void showIncidences( const Incidence::List &incidenceList, const TQDate &date ); void updateView(); void changeIncidenceDisplay( Incidence *incidence, int mode ); void updateConfig(); @@ -84,10 +88,13 @@ class MultiAgendaView : public AgendaView void slotSelectionChanged(); void slotClearTimeSpanSelection(); void resizeSplitters(); + void resizeSpacers( int ); + void setupScrollBar(); void zoomView( const int delta, const TQPoint &pos, const Qt::Orientation ori ); void slotResizeScrollView(); private: + KOAgendaView *mSelectedAgendaView; TQValueList<KOAgendaView*> mAgendaViews; TQValueList<TQWidget*> mAgendaWidgets; TQHBox *mTopBox; @@ -96,10 +103,12 @@ class MultiAgendaView : public AgendaView TQSplitter *mLeftSplitter, *mRightSplitter; TQSplitter *mLastMovedSplitter; TQScrollBar *mScrollBar; + TQWidget *mLeftTopSpacer, *mRightTopSpacer; TQWidget *mLeftBottomSpacer, *mRightBottomSpacer; TQDate mStartDate, mEndDate; bool mUpdateOnShow; bool mPendingChanges; + CalendarView *mCalendarView; }; } diff --git a/korganizer/navigatorbar.cpp b/korganizer/navigatorbar.cpp index 0ece74c57..f663af815 100644 --- a/korganizer/navigatorbar.cpp +++ b/korganizer/navigatorbar.cpp @@ -60,55 +60,70 @@ NavigatorBar::NavigatorBar( TQWidget *parent, const char *name ) tfont.setPointSize( 10 ); tfont.setBold( false ); + // Create a horizontal spacers + TQSpacerItem *frontSpacer = new TQSpacerItem( 50, 1, TQSizePolicy::Expanding ); + TQSpacerItem *endSpacer = new TQSpacerItem( 50, 1, TQSizePolicy::Expanding ); + bool isRTL = KOGlobals::self()->reverseLayout(); TQPixmap pix; // Create backward navigation buttons - mPrevYear = new TQPushButton( this ); pix = KOGlobals::self()->smallIcon( isRTL ? "2rightarrow" : "2leftarrow" ); + mPrevYear = new TQPushButton( this ); mPrevYear->setPixmap( pix ); mPrevYear->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ); - TQToolTip::add( mPrevYear, i18n("Previous year") ); + TQToolTip::add( mPrevYear, i18n( "Previous year" ) ); pix = KOGlobals::self()->smallIcon( isRTL ? "1rightarrow" : "1leftarrow"); mPrevMonth = new TQPushButton( this ); mPrevMonth->setPixmap( pix ); mPrevMonth->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ); - TQToolTip::add( mPrevMonth, i18n("Previous month") ); + TQToolTip::add( mPrevMonth, i18n( "Previous month" ) ); // Create forward navigation buttons pix = KOGlobals::self()->smallIcon( isRTL ? "1leftarrow" : "1rightarrow"); mNextMonth = new TQPushButton( this ); mNextMonth->setPixmap( pix ); mNextMonth->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ); - TQToolTip::add( mNextMonth, i18n("Next month") ); + TQToolTip::add( mNextMonth, i18n( "Next month" ) ); pix = KOGlobals::self()->smallIcon( isRTL ? "2leftarrow" : "2rightarrow"); mNextYear = new TQPushButton( this ); mNextYear->setPixmap( pix ); mNextYear->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ); - TQToolTip::add( mNextYear, i18n("Next year") ); + TQToolTip::add( mNextYear, i18n( "Next year" ) ); // Create month name button mMonth = new ActiveLabel( this ); mMonth->setFont( tfont ); mMonth->setAlignment( AlignCenter ); mMonth->setMinimumHeight( mPrevYear->sizeHint().height() ); - TQToolTip::add( mMonth, i18n("Select a month") ); + TQToolTip::add( mMonth, i18n( "Select a month" ) ); + + // Create year button + mYear = new ActiveLabel( this ); + mYear->setFont( tfont ); + mYear->setAlignment( AlignCenter ); + mYear->setMinimumHeight( mPrevYear->sizeHint().height() ); + TQToolTip::add( mYear, i18n( "Select a year" ) ); // set up control frame layout - TQBoxLayout *ctrlLayout = new TQHBoxLayout( this, 0, 4 ); - ctrlLayout->addWidget( mPrevYear, 3 ); - ctrlLayout->addWidget( mPrevMonth, 3 ); - ctrlLayout->addWidget( mMonth, 3 ); - ctrlLayout->addWidget( mNextMonth, 3 ); - ctrlLayout->addWidget( mNextYear, 3 ); - - connect( mPrevYear, TQT_SIGNAL( clicked() ), TQT_SIGNAL( goPrevYear() ) ); - connect( mPrevMonth, TQT_SIGNAL( clicked() ), TQT_SIGNAL( goPrevMonth() ) ); - connect( mNextMonth, TQT_SIGNAL( clicked() ), TQT_SIGNAL( goNextMonth() ) ); - connect( mNextYear, TQT_SIGNAL( clicked() ), TQT_SIGNAL( goNextYear() ) ); - connect( mMonth, TQT_SIGNAL( clicked() ), TQT_SLOT( selectMonth() ) ); + TQHBoxLayout *ctrlLayout = new TQHBoxLayout( this ); + ctrlLayout->addWidget( mPrevYear ); + ctrlLayout->addWidget( mPrevMonth ); + ctrlLayout->addItem( frontSpacer ); + ctrlLayout->addWidget( mMonth ); + ctrlLayout->addWidget( mYear ); + ctrlLayout->addItem( endSpacer ); + ctrlLayout->addWidget( mNextMonth ); + ctrlLayout->addWidget( mNextYear ); + + connect( mPrevYear, TQT_SIGNAL( clicked() ), TQT_SIGNAL( prevYearClicked() ) ); + connect( mPrevMonth, TQT_SIGNAL( clicked() ), TQT_SIGNAL( prevMonthClicked() ) ); + connect( mNextMonth, TQT_SIGNAL( clicked() ), TQT_SIGNAL( nextMonthClicked() ) ); + connect( mNextYear, TQT_SIGNAL( clicked() ), TQT_SIGNAL( nextYearClicked() ) ); + connect( mMonth, TQT_SIGNAL( clicked() ), TQT_SLOT( selectMonthFromMenu() ) ); + connect( mYear, TQT_SIGNAL( clicked() ), TQT_SLOT( selectYearFromMenu() ) ); } NavigatorBar::~NavigatorBar() @@ -142,29 +157,29 @@ void NavigatorBar::selectDates( const KCal::DateList &dateList ) const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); - if ( !mHasMinWidth ) { - // Set minimum width to width of widest month name label - int i; - int maxwidth = 0; + // Set minimum width to width of widest month name label + int i; + int maxwidth = 0; - for( i = 1; i <= calSys->monthsInYear( mDate ); ++i ) { - int w = TQFontMetrics( mMonth->font() ).width( TQString("%1 8888") - .arg( calSys->monthName( i, calSys->year( mDate ) ) ) ); - if ( w > maxwidth ) maxwidth = w; + for( i = 1; i <= calSys->monthsInYear( mDate ); ++i ) { + int w = TQFontMetrics( mMonth->font() ). + width( TQString( "%1" ). + arg( calSys->monthName( i, calSys->year( mDate ) ) ) ); + if ( w > maxwidth ) { + maxwidth = w; } - mMonth->setMinimumWidth( maxwidth ); - - mHasMinWidth = true; } + mMonth->setMinimumWidth( maxwidth ); + + mHasMinWidth = true; - // compute the label at the top of the navigator - mMonth->setText( i18n( "monthname year", "%1 %2" ) - .arg( calSys->monthName( mDate ) ) - .arg( calSys->year( mDate ) ) ); + // set the label text at the top of the navigator + mMonth->setText( i18n( "monthname", "%1" ).arg( calSys->monthName( mDate ) ) ); + mYear->setText( i18n( "4 digit year", "%1" ).arg( calSys->yearString( mDate, false ) ) ); } } -void NavigatorBar::selectMonth() +void NavigatorBar::selectMonthFromMenu() { // every year can have different month names (in some calendar systems) const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); @@ -185,7 +200,36 @@ void NavigatorBar::selectMonth() return; // canceled } - emit goMonth( month ); + emit monthSelected( month ); + + delete popup; +} + +void NavigatorBar::selectYearFromMenu() +{ + const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); + + int year = calSys->year( mDate ); + int years = 11; // odd number (show a few years ago -> a few years from now) + int minYear = year - ( years / 3 ); + + TQPopupMenu *popup = new TQPopupMenu( mYear ); + + TQString yearStr; + int y = minYear; + for ( int i=0; i < years; i++ ) { + popup->insertItem( yearStr.setNum( y ), i ); + y++; + } + popup->setActiveItem( year - minYear ); + + if ( ( year = popup->exec( mYear->mapToGlobal( TQPoint( 0, 0 ) ), + year - minYear ) ) == -1 ) { + delete popup; + return; // canceled + } + + emit yearSelected( year + minYear ); delete popup; } diff --git a/korganizer/navigatorbar.h b/korganizer/navigatorbar.h index c6bc41768..05d624a58 100644 --- a/korganizer/navigatorbar.h +++ b/korganizer/navigatorbar.h @@ -58,14 +58,16 @@ class NavigatorBar: public QWidget void selectDates( const KCal::DateList & ); signals: - void goNextMonth(); - void goPrevMonth(); - void goNextYear(); - void goPrevYear(); - void goMonth(int month); + void nextMonthClicked(); + void prevMonthClicked(); + void nextYearClicked(); + void prevYearClicked(); + void monthSelected( int month ); + void yearSelected( int year ); private slots: - void selectMonth(); + void selectMonthFromMenu(); + void selectYearFromMenu(); private: bool mHasMinWidth; @@ -75,6 +77,7 @@ class NavigatorBar: public QWidget TQPushButton *mPrevYear; TQPushButton *mPrevMonth; ActiveLabel *mMonth; + ActiveLabel *mYear; TQPushButton *mNextMonth; TQPushButton *mNextYear; }; diff --git a/korganizer/plugins/datenums/datenums.desktop b/korganizer/plugins/datenums/datenums.desktop index b5010edc9..b93e3d1de 100644 --- a/korganizer/plugins/datenums/datenums.desktop +++ b/korganizer/plugins/datenums/datenums.desktop @@ -24,7 +24,6 @@ Name[hu]=DátumkezelÅ‘ bÅ‘vÃtÅ‘modul naptárakhoz Name[is]=Ãforrit fyrir númer dags á dagatali Name[it]=Plugin delle date per i calendari Name[ja]=日数表示カレンダープラグイン -Name[ka]=თáƒáƒ იღის რიცხვების მáƒáƒ“ული კáƒáƒšáƒ”ნდრებისáƒáƒ—ვის Name[kk]=Күнтізбедегі күн нөмірінің модулі Name[km]=កម្មវិធី​ជំនួយ​លáŸážâ€‹áž€áž¶áž›áž”រិច្ឆáŸáž‘​សម្រាប់​ប្រážáž·áž‘áž·áž“ Name[lt]=Datų numerių priedas kalendoriams @@ -69,7 +68,6 @@ Comment[hu]=MegjelenÃti az év elejétÅ‘l eltelt napok számát az áttekintÅ‘ Comment[is]=Þetta Ãforrit sýnir efst à fundarskránni númer hvers dags à árinu. T.d. er 1. febrúar 32. dagurinn à árinu. Comment[it]=Per ciascun giorno, questo plugin mostra la data giuliana (numero progressivo a partire dal primo gennaio dell'anno corrente). Per esempio al primo di febbraio corrisponde il numero 32. Comment[ja]=ã“ã®ãƒ—ラグインã¯äºˆå®šè¡¨ãƒ“ューã®ä¸Šã«ã€ãã‚Œãžã‚Œã®æ—¥ãŒãã®å¹´ã®ä½•æ—¥ç›®ã§ã‚ã‚‹ã‹ã‚’表示ã—ã¾ã™ã€‚例ãˆã°ã€2 月 1 æ—¥ã¯ãã®å¹´ã® 32 日目ã§ã™ã€‚ -Comment[ka]= გეგმის ზედრხედში ეს მáƒáƒ“ული თვითეული დღისáƒáƒ—ვის áƒáƒ©áƒ•áƒ”ნებს მის დღის ნáƒáƒ›áƒ”რს áƒáƒ› წლისáƒáƒ—ვის . მáƒáƒ’áƒáƒšáƒ˜áƒ—áƒáƒ“,1 თებერვáƒáƒšáƒ˜ წლის 32-ე დღეáƒ. Comment[kk]=Бұл модуль күн тәртібі бетінің жоғарында жыл баÑынан өткен күндер Ñанын көрÑетеді. МыÑалы, 1-ақпан жылдың 32-күні. Comment[km]=សម្រាប់​ážáŸ’ងៃ​នីមួយៗ កម្មវិធី​ជំនួយ​នáŸáŸ‡â€‹áž“ឹង​បង្ហាញ​លáŸážâ€‹ážáŸ’ងៃ​នៃ​ឆ្នាំ នៅ​ផ្នែក​ážáž¶áž„​លើ​នៃ​ទិដ្ឋភាព​របៀបវារៈ ។ ឧទាហរណ០ážáŸ’ងៃ​ទី ១ ážáŸ‚ កុម្ភៈ នឹង​ážáŸ’រូវ​ជា​ážáŸ’ងៃ​ទី ៣២ នៃ​ឆ្នាំ ។ Comment[lt]=Kiekvienai dienai Å¡is priedas rodo metų dienos numerį tvarkyklÄ—s virÅ¡uje. Pvz., Vasario 1 yra32 metų diena. diff --git a/korganizer/plugins/exchange/exchange.desktop b/korganizer/plugins/exchange/exchange.desktop index 121bf9863..95484e3b4 100644 --- a/korganizer/plugins/exchange/exchange.desktop +++ b/korganizer/plugins/exchange/exchange.desktop @@ -24,7 +24,6 @@ Name[hu]=Microsoft Exchange 2000-bÅ‘vÃtÅ‘modul a KOrganizerhez Name[is]=Microsoft Exchange 2000 Ãforrit fyrir KOrganizer Name[it]=Plugin Microsoft Exchange 2000 per KOrganizer Name[ja]=KOrganizer ã® Microsoft Exchange 2000 プラグイン -Name[ka]=Microsoft Exchange 2000-ის მáƒáƒ“ული KOrganizer-სთვის Name[kk]=KOrganizer-дің Microsoft Exchange 2000 модулі Name[km]=កម្មវិធី​ជំនួយ​ម៉ៃក្រូសូហ្វ Exchange ២០០០សម្រាប់ KOrganizer Name[lt]=Microsoft Exchange 2000 priedas, skirtas KOrganizer @@ -70,7 +69,6 @@ Comment[hu]=Ez a modul lehetÅ‘vé teszi KOrganizer-felhasználóknak Microsoft E Comment[is]=Þetta Ãforrit gerir KOrganizer kleyft að vinna með Microsoft Exchange 2000 hópvinnuþjónum. Comment[it]=Questo plugin permette agli utenti di korganizer di lavorare con i server groupware Microsoft Exchange 2000. Comment[ja]=ã“ã®ãƒ—ラグインã«ã‚ˆã‚Šã€korganizer ã®ãƒ¦ãƒ¼ã‚¶ãŒ Microsoft Exchange 2000 グループウェアサーãƒã¨åŒæœŸã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚ -Comment[ka]=ეს მáƒáƒ“ული korganizer-ის მáƒáƒ›áƒ®áƒ›áƒáƒ ებლებს სáƒáƒ¨áƒ£áƒáƒšáƒ”ბáƒáƒ¡ áƒáƒ«áƒšáƒ”ვს იმუშáƒáƒáƒœ Microsoft Exchange 2000 ჯგუფურსერვერებთáƒáƒœ. Comment[kk]=Бұл модуль korganizer-мен MS Exchange 2000 біріккен Ð¶Ò±Ð¼Ñ‹Ñ Ñервермен Ñ–Ñтеуге мүмкіндік береді. Comment[km]=កម្មវិធី​ជំនួយ​នáŸáŸ‡â€‹áž¢áž“ុញ្ញាážâ€‹áž²áŸ’យ​អ្នក​ប្រើ​របស់ korganizer ធ្វើការ​ជាមួយ​ម៉ាស៊ីន​បម្រើ​កម្មវិធី​ពហុ​អ្នកប្រើ​របស់​ម៉ៃក្រូសូហ្វ Exchange ២០០០ ។ Comment[lt]=Å is priedas leidžia korganizer dirbti su Microsoft Exchange 2000 groupware serveriais. diff --git a/korganizer/plugins/hebrew/hebrew.cpp b/korganizer/plugins/hebrew/hebrew.cpp index 9fb0f2fbf..8a9f37bd4 100644 --- a/korganizer/plugins/hebrew/hebrew.cpp +++ b/korganizer/plugins/hebrew/hebrew.cpp @@ -55,7 +55,7 @@ TQString Hebrew::shortText(const TQDate & date) Holiday::ParshaP = config.readBoolEntry("Parsha", true); Holiday::CholP = config.readBoolEntry("Chol_HaMoed", true); Holiday::OmerP = config.readBoolEntry("Omer", true); - TQString *label_text = new TQString(); + TQString label_text; int day = date.day(); int month = date.month(); @@ -81,7 +81,7 @@ TQString Hebrew::shortText(const TQDate & date) hebrew_day_number, hebrew_year); KCalendarSystem *cal = KCalendarSystemFactory::create("hebrew"); - *label_text = TQString("%1 %2").arg(cal->dayString(date, false)) + label_text = TQString("%1 %2").arg(cal->dayString(date, false)) .arg(cal->monthName(date)); if (holidays.count()) @@ -90,11 +90,11 @@ TQString Hebrew::shortText(const TQDate & date) for (int h = 0; h <= count; ++h) { - *label_text += "\n" + holidays[h]; + label_text += "\n" + holidays[h]; } } - return *label_text; + return label_text; } TQString Hebrew::info() diff --git a/korganizer/plugins/hebrew/hebrew.desktop b/korganizer/plugins/hebrew/hebrew.desktop index 86c88328d..dc67c2eba 100644 --- a/korganizer/plugins/hebrew/hebrew.desktop +++ b/korganizer/plugins/hebrew/hebrew.desktop @@ -23,7 +23,6 @@ Name[hu]=BÅ‘vÃtÅ‘modul a zsidó naptár kezeléséhez Name[is]=Gyðinga dagatalsÃforrit Name[it]=Plugin calendario ebraico Name[ja]=ユダヤæ´ã‚«ãƒ¬ãƒ³ãƒ€ãƒ¼ãƒ—ラグイン -Name[ka]=ებრáƒáƒ£áƒšáƒ˜ კáƒáƒšáƒ”ნდრის მáƒáƒ“ული Name[kk]=Яһуди күнтізбеÑінің модулі Name[km]=កម្មវិធី​ជំនួយ​ប្រážáž·áž‘áž·áž“ Jewish Name[lt]=Žydų kalendoriaus priedas @@ -70,7 +69,6 @@ Comment[hu]=A KOrganizer dátumait kiÃrja a hagyományos zsidó naptár szerint Comment[is]=Sýna alla dagsetningar à KOrganizer sem eru einnig à dagatali gyðinga. Comment[it]=Mostra tutte le date in korganizer secondo il calendario ebraico. Comment[ja]=korganizer ã®ã™ã¹ã¦ã®æ—¥ä»˜ã‚’ユダヤ暦ã§ã‚‚表示ã—ã¾ã™ã€‚ -Comment[ka]=ყველრთáƒáƒ იღს ებრáƒáƒ£áƒšáƒ˜ კáƒáƒšáƒ”ნდრის მიხედვითáƒáƒª áƒáƒ©áƒ•áƒ”ნებს Comment[kk]=Яһуди күнтізбе күндерін korganizer-де көрÑететін модулі. Comment[km]=បង្ហាញ​កាលបរិច្ឆáŸáž‘​ទាំងអស់​ក្នុង korganizer នៅ​ក្នុង​ប្រពáŸáž“្ធ​ប្រážáž·áž‘áž·áž“ Jewish ។ Comment[lt]=Rodo visas dienas kalendoriuje taip pat ir žydų kalendoriaus sistema. diff --git a/korganizer/plugins/printing/journal/journalprint.cpp b/korganizer/plugins/printing/journal/journalprint.cpp index 551f23a9d..93bc51eff 100644 --- a/korganizer/plugins/printing/journal/journalprint.cpp +++ b/korganizer/plugins/printing/journal/journalprint.cpp @@ -123,13 +123,19 @@ void CalPrintJournal::print( TQPainter &p, int width, int height ) } } - drawHeader( p, i18n("Journal entries"), TQDate(), TQDate(), TQRect( 0, 0, width, headerHeight() ) ); + TQRect headerBox( 0, 0, width, headerHeight() ); + TQRect footerBox( 0, height - footerHeight(), width, footerHeight() ); + height -= footerHeight(); + + drawHeader( p, i18n("Journal entries"), TQDate(), TQDate(), headerBox ); y = headerHeight() + 15; Journal::List::Iterator it = journals.begin(); for ( ; it != journals.end(); ++it ) { drawJournal( *it, p, x, y, width, height ); } + + drawFooter( p, footerBox ); } #endif diff --git a/korganizer/plugins/printing/journal/journalprint.desktop b/korganizer/plugins/printing/journal/journalprint.desktop index 081f73d6d..6d811fcec 100644 --- a/korganizer/plugins/printing/journal/journalprint.desktop +++ b/korganizer/plugins/printing/journal/journalprint.desktop @@ -21,7 +21,6 @@ Name[hu]=Naplónyomtatási stÃlus Name[is]=DagbókarprentstÃll Name[it]=Stile di stampa a diario Name[ja]=ジャーナルå°åˆ·ã‚¹ã‚¿ã‚¤ãƒ« -Name[ka]=ჟურნáƒáƒšáƒ˜áƒ¡ ბეáƒáƒ“ვის სტილი Name[kk]=Күнделікті баÑу Ñтилі Name[km]=រចនាបáŸáž‘្ម​បោះពុម្ព​ទិនានុប្បវážáŸ’ážáž· Name[lt]=Dienyno spausdinimo stilius @@ -65,7 +64,6 @@ Comment[hu]=Ez a modul naplóbejegyzések kinyomtatását teszi lehetÅ‘vé. Comment[is]=Þetta Ãforrit gerir þér kleyft að prenta út dagbókarfærslur. Comment[it]=Questo plugin ti permette di stampare le registrazioni del diario. Comment[ja]=ã“ã®ãƒ—ラグインã«ã‚ˆã‚Šã€ã‚¸ãƒ£ãƒ¼ãƒŠãƒ« (日誌) ã®ã‚¨ãƒ³ãƒˆãƒªã‚’å°åˆ·ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚ -Comment[ka]=ეს მáƒáƒ“ული სáƒáƒ¨áƒ£áƒáƒšáƒ”ბáƒáƒ¡ გáƒáƒ«áƒšáƒ”ვთ áƒáƒ›áƒáƒ‘ეáƒáƒ“áƒáƒ— ჟურნáƒáƒšáƒ˜áƒ¡ შემáƒáƒ“გენლáƒáƒ‘რ(დღიურის ელემენტები) Comment[kk]=Бұл күнделіктің жазуларын баÑып шығаратын модулі. Comment[km]=កម្មវិធី​ជំនួយ​នáŸáŸ‡â€‹áž¢áž“ុញ្ញាážâ€‹áž²áŸ’យ​អ្នក​បោះពុម្ព​ធាážáž»â€‹áž‘ិនានុប្បវážáŸ’ážáž· (ធាážáž»â€‹áž€áŸ†ážŽážáŸ‹áž áŸážáž»â€‹áž”្រចាំ​ážáŸ’ងៃ) ។ Comment[lt]=Å is priedas leidžia spausdinti dienyno įraÅ¡us. diff --git a/korganizer/plugins/printing/list/listprint.desktop b/korganizer/plugins/printing/list/listprint.desktop index 7688a2c52..6be822b85 100644 --- a/korganizer/plugins/printing/list/listprint.desktop +++ b/korganizer/plugins/printing/list/listprint.desktop @@ -21,7 +21,6 @@ Name[hu]=Eseménylista kinyomtatása Name[is]=ListaprentstÃll Name[it]=Stile di stampa ad elenco Name[ja]=リストå°åˆ·ã‚¹ã‚¿ã‚¤ãƒ« -Name[ka]=ბეáƒáƒ“ვის სტილის სირName[kk]=Тізімді баÑу Ñтилі Name[km]=រចនាបáŸáž‘្ម​បោះពុម្ព​បញ្ជី Name[lt]=SÄ…raÅ¡o spausdinimo stilius @@ -65,7 +64,6 @@ Comment[hu]=Ezzel a modullal listaként kinyomtathatók a feladatok és esemény Comment[is]=Þetta Ãforrit gerir þér kleyft að prenta út lista með atburðum og verkþáttum. Comment[it]=Questo plugin ti permette di stampare eventi e cose da fare in modalità elenco. Comment[ja]=ã“ã®ãƒ—ラグインã«ã‚ˆã‚Šã€ãƒªã‚¹ãƒˆãƒ•ã‚©ãƒ¼ãƒ 内ã®ã‚¤ãƒ™ãƒ³ãƒˆã‚„ To-Do ã‚’å°åˆ·ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚ -Comment[ka]=ეს მáƒáƒ“ული სáƒáƒ¨áƒ£áƒáƒšáƒ”ბáƒáƒ¡ გáƒáƒ«áƒšáƒ”ვთ სიის ფáƒáƒ მით áƒáƒ›áƒáƒ‘ეáƒáƒ“áƒáƒ— მáƒáƒ•áƒšáƒ”ნები დრდáƒáƒ•áƒáƒšáƒ”ბები. Comment[kk]=Бұл оқиғалар мен жоÑпарларды тізім түрінде баÑатын модулі. Comment[km]=កម្មវិធី​ជំនួយ​នáŸáŸ‡â€‹áž¢áž“ុញ្ញាážâ€‹áž²áŸ’យ​អ្នក​បោះពុម្ព​ព្រឹážáŸ’ážáž·áž€áž¶ážšážŽáŸ និង​ការងារ​ážáŸ’រូវ​ធ្វើក្នុង​ទម្រង់​ជា​បញ្ជី ។ Comment[lt]=Å is priedas leidžia spausdinti įvykius ir darbus sÄ…raÅ¡o forma. diff --git a/korganizer/plugins/printing/whatsnext/whatsnextprint.desktop b/korganizer/plugins/printing/whatsnext/whatsnextprint.desktop index 50131734e..59ed74c21 100644 --- a/korganizer/plugins/printing/whatsnext/whatsnextprint.desktop +++ b/korganizer/plugins/printing/whatsnext/whatsnextprint.desktop @@ -21,7 +21,6 @@ Name[hu]=A közeljövÅ‘ eseményeinek kinyomtatása Name[is]=Hvað er næst prentstÃll Name[it]=Stile di stampa "cosa viene dopo" Name[ja]=次ã¯ä½•ï¼Ÿ å°åˆ·ã‚¹ã‚¿ã‚¤ãƒ« -Name[ka]=ბეáƒáƒ“ვის სტილი "შემდეგი რრáƒáƒ ის?" Name[kk]="Ðе Ñ–Ñтеу?" бетін баÑу Ñтилі Name[km]=រចនាបáŸáž‘្ម​បោះពុម្ព​ការងារ​បន្ážáž”ន្ទាប់ Name[lt]=AteinanÄių įvykių spausdinimo stilius @@ -34,7 +33,7 @@ Name[nn]=Utskriftsstil for «Kva no» Name[pl]=Styl drukowania "Do dalej" Name[pt]=Estilo de Impressão "O Que Se Segue" Name[pt_BR]=Estilo de impressão "A Seguir" -Name[ru]=ПредÑтоÑщие задачи +Name[ru]=ДаджеÑÑ‚ Name[sk]=Å týl tlaÄe ÄŒo nasleduje Name[sl]=Slog tiskanja v obliki »Kaj je naslednje« Name[sr]=Стил штампе „Шта је Ñледеће“ @@ -65,7 +64,6 @@ Comment[hu]=Ezzel a modullal kinyomtathatók a rövidesen aktuálissá váló fe Comment[is]=Þetta Ãforrit gerir þér kleyft að prenta út lista yfir alla væntanlega atburði og verkþætti. Comment[it]=Questo plugin vi permette di stampare una lista dei prossimi eventi e cose da fare. Comment[ja]=ã“ã®ãƒ—ラグインã«ã‚ˆã‚Šã€å°†æ¥ã®ã™ã¹ã¦ã®ã‚¤ãƒ™ãƒ³ãƒˆã‚„ To-Do ã®ãƒªã‚¹ãƒˆã‚’å°åˆ·ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚ -Comment[ka]=ეს მáƒáƒ“ული სáƒáƒ¨áƒ£áƒáƒšáƒ”ბáƒáƒ¡ გáƒáƒ«áƒšáƒ”ვთ áƒáƒ›áƒáƒ‘ეáƒáƒ“áƒáƒ— მáƒáƒ›áƒáƒ•áƒáƒšáƒ˜ მáƒáƒ•áƒšáƒ”ნები დრდáƒáƒ•áƒáƒšáƒ”ბები. Comment[kk]=Бұл келер оқиғалар мен жоÑпарлар тізімін баÑып шығаратын модулі. Comment[km]=កម្មវិធី​ជំនួយ​នáŸáŸ‡â€‹áž¢áž“ុញ្ញាážâ€‹áž²áŸ’យ​អ្នក​បោះពុម្ព​បញ្ជី​នៃ​ព្រឹážáŸ’ážáž·áž€áž¶ážšážŽáŸ និង​ការងារ​ážáŸ’រូវ​ធ្វើ​បន្ážáž”ន្ទាប់ Comment[lt]=Å is priedas leidžia spausdinti sÄ…raÅ¡Ä… visų artÄ—janÄių įvykių ir darbų. diff --git a/korganizer/plugins/printing/year/yearprint.cpp b/korganizer/plugins/printing/year/yearprint.cpp index 5f3a9dc68..59a43db75 100644 --- a/korganizer/plugins/printing/year/yearprint.cpp +++ b/korganizer/plugins/printing/year/yearprint.cpp @@ -137,13 +137,14 @@ void CalPrintYear::setDateRange( const TQDate& from, const TQDate& to ) void CalPrintYear::print( TQPainter &p, int width, int height ) { -kdDebug()<<"CalPrintYear::print, width: "<<width<<", height: "<<height<<endl; - TQRect headerBox( 0, 0, width, headerHeight() ); -kdDebug()<<"headerBox: "<<headerBox<<endl; const KCalendarSystem *calsys = calendarSystem(); KLocale *locale = KGlobal::locale(); if ( !calsys || !locale ) return; + TQRect headerBox( 0, 0, width, headerHeight() ); + TQRect footerBox( 0, height - footerHeight(), width, footerHeight() ); + height -= footerHeight(); + TQDate start; calsys->setYMD( start, mYear, 1, 1 ); @@ -197,6 +198,8 @@ kdDebug()<<"headerBox: "<<headerBox<<endl; temp = calsys->addMonths( temp, 1 ); } + + drawFooter( p, footerBox ); start = calsys->addMonths( start, monthsPerPage ); } } diff --git a/korganizer/plugins/printing/year/yearprint.desktop b/korganizer/plugins/printing/year/yearprint.desktop index 5edafedc2..40f1de60b 100644 --- a/korganizer/plugins/printing/year/yearprint.desktop +++ b/korganizer/plugins/printing/year/yearprint.desktop @@ -16,7 +16,6 @@ Name[fr]=Impression annuelle Name[fy]=Printstyl foar jierkalinder Name[gl]=Estilo de impresión anual Name[hu]=Éves naptár nyomtatási stÃlus -Name[is]=ÃrsyfirlitsprentstÃll Name[it]=Stile di stampa annuale Name[ja]=年毎å°åˆ·ã‚¹ã‚¿ã‚¤ãƒ« Name[kk]=Жылдық баÑу Ñтилі @@ -54,7 +53,6 @@ Comment[fr]=Ce module vous permet d'imprimer l'ensemble de l'année Comment[fy]=Dizze plugin makket it mooglik om in jierkalinder út te printsjen. Comment[gl]=Este engadido permÃtelle imprimir un calendario anual. Comment[hu]=Ez a modul egy egész éves naptár kinyomtatását teszi lehetÅ‘vé. -Comment[is]=Þetta Ãforrit gerir þér kleyft að prenta út dagbókarfærslur fyrir allt árið. Comment[it]=Questo plugin ti permette di stampare un calendario annuale. Comment[ja]=ã“ã®ãƒ—ラグインã«ã‚ˆã‚Šã€å¹´æ¯Žã®ã‚«ãƒ¬ãƒ³ãƒ€ãƒ¼ã‚’å°åˆ·ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚ Comment[kk]=Бұл жылдық күнтізбені баÑып шығаратын модулі. diff --git a/korganizer/plugins/timespanview/timespanview.desktop b/korganizer/plugins/timespanview/timespanview.desktop index 13654b46a..72e403bb0 100644 --- a/korganizer/plugins/timespanview/timespanview.desktop +++ b/korganizer/plugins/timespanview/timespanview.desktop @@ -21,7 +21,6 @@ Name[hu]=IdÅ‘szakáttekintÅ‘ bÅ‘vÃtÅ‘modul a KOrganizerhez Name[is]=TÃmabilsskoðunar Ãforrit fyrir KOrganizer Name[it]=Plugin vista intervalli temporali per KOrganizer Name[ja]=KOrganizer タイムスパンビュー プラグイン -Name[ka]=დრáƒáƒ˜áƒ¡ დიáƒáƒ’რáƒáƒ›áƒ˜áƒáƒœáƒ˜ ხედის მáƒáƒ“ული KOrganizer-სთვის Name[kk]=KOrganizer-дің уақыт аралығы ÐºÓ©Ñ€Ñ–Ð½Ñ–Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ– Name[km]=កម្មវិធី​ជំនួយ​ទិដ្ឋភាព​រយៈពáŸáž›â€‹ážŸáž˜áŸ’រាប់ KOrganizer Name[lt]=Laiko tarpsnio vaizdo KOrganizer priedas @@ -65,7 +64,6 @@ Comment[hu]=Ezzel modullal egy idÅ‘szakot lehet áttekinteni a KOrganizerben (pà Comment[is]=Þetta Ãforrit veitir tÃmabilssýn fyrir KOrganizer (svipað og verkþátta eða mánaðarsýn). Ef þú virkjar þetta Ãforrit getur þú skipt yfir à tÃmabilssýn og skoðað atburðina þÃna eins og á Gantt skýringarmynd. Comment[it]=Questo plugin fornisce una vista a intervalli temporali. Se abiliti questo plugin, potrai passare alla vista a intervalli temporali e vedere i tuoi eventi come in un diagramma di Gantt. Comment[ja]=ã“ã®ãƒ—ラグイン㯠KOrganizer ã«ã‚¿ã‚¤ãƒ スパンビューをæä¾›ã—ã¾ã™ (To-Do ビューや月ビューãªã©)。ã“ã®ãƒ—ラグインを有効ã«ã™ã‚‹ã¨ã€ã‚¿ã‚¤ãƒ スパンビューã«åˆ‡ã‚Šæ›¿ãˆã¦ã€ã‚¬ãƒ³ãƒˆãƒãƒ£ãƒ¼ãƒˆã®ã‚ˆã†ã«ã‚¤ãƒ™ãƒ³ãƒˆã‚’見るã“ã¨ãŒã§ãã¾ã™ã€‚ -Comment[ka]=ეს მáƒáƒ“ული უზრუნველჰყáƒáƒ¤áƒ¡ korganizer-ს დრáƒáƒ˜áƒ¡ დიáƒáƒ’რáƒáƒ›áƒ˜áƒáƒœáƒ˜ ხედით (მáƒáƒ’.:დáƒáƒ•áƒáƒšáƒ”ბები áƒáƒœ თვიური მიმáƒáƒ®áƒ˜áƒšáƒ•áƒ). თუ áƒáƒ› მáƒáƒ“ულს გáƒáƒáƒáƒ¥áƒ¢áƒ˜áƒ£áƒ ებთ,თქვენ შეგიძლიáƒáƒ— გáƒáƒ“áƒáƒ თáƒáƒ— დრáƒáƒ˜áƒ¡ დიáƒáƒ’რáƒáƒ›áƒ˜áƒáƒœ ხედზე დრიხილáƒáƒ— მáƒáƒ•áƒšáƒ”ნები გáƒáƒœáƒ¢áƒ˜áƒ¡ დიáƒáƒ’რáƒáƒ›áƒ˜áƒ¡ სáƒáƒ®áƒ˜áƒ—. Comment[kk]=Бұл KOrganizer-нің уақыт аралығы көрініÑінің модулі. Модулін орнатÑаңыз, оÑÑ‹ көрініÑке ауыÑып оқиғаларыңызды Гант диаграмма түріне келтре алаÑыз. Comment[km]=កម្មវិធី​ជំនួយ​នáŸáŸ‡â€‹áž•áŸ’ដល់​នូវ​ទិដ្ឋភាព​រយៈពáŸáž›â€‹ážŸáž˜áŸ’រាប់ korganizer (ដូចជា ទិដ្ឋភាព​ការងារ​ážáŸ’រូវ​ធ្វើ ឬ ទិដ្ឋភាព​ážáŸ‚​ជាដើម) ។ បើ​អ្នក​ធ្វើ​ឲ្យ​កម្មវិធី​ជំនួយ​នáŸáŸ‡â€‹áž”្រើ​បាន អ្នក​នឹង​អាច​ប្ដូរ​ទិដ្ឋភាព​រយៈពáŸáž› ហើយ​មើល​ព្រឹážáŸ’ážáž·áž€áž¶ážšážŽáŸâ€‹ážšáž”ស់​អ្នក​ដូចជា​នៅ​ក្នុងដ្យាក្រាម Gantt អញ្ចឹង​ដែរ ។ Comment[lt]=Å is priedas korganizer programoje sudaro galimybÄ™ apžvelgti laiko tarpÄ… (pvz., darbų arba mÄ—nesio peržiÅ«ra). Ä®galinus šį priedÄ… galÄ—site persijungti į laiko tarpo peržiÅ«rÄ… ir žiÅ«rÄ—ti įvykius tarsi Gantt diagramoje. diff --git a/korganizer/previewdialog.cpp b/korganizer/previewdialog.cpp new file mode 100644 index 000000000..23671bd92 --- /dev/null +++ b/korganizer/previewdialog.cpp @@ -0,0 +1,163 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 2003,2004 Cornelius Schumacher <schumacher@kde.org> + Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net> + Author: Sergio Martins, <sergio.martins@kdab.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of TQt, and distribute the resulting executable, + without including the source code for TQt in the source distribution. +*/ + +#include "previewdialog.h" + +#include "kolistview.h" +#include "koprefs.h" +#include "stdcalendar.h" + +#include <klocale.h> + +#include <libkcal/calendarlocal.h> + +#include <kstandarddirs.h> +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <kio/netaccess.h> + +#include <tqlabel.h> +#include <tqlayout.h> +#include <tqradiobutton.h> +#include <tqpushbutton.h> +#include <tqdialog.h> + +using namespace KCal; + +PreviewDialog::PreviewDialog( const KURL &url, TQWidget *parent ) + : KDialogBase( Plain, i18n("Import Calendar/Event"), User1 | User2 | Cancel, User1, parent, + 0, true, true, KGuiItem( i18n("&Merge into existing calendar"), "merge" ) ), + mOriginalUrl( url ) +{ + TQFrame *topFrame = plainPage(); + TQVBoxLayout *topLayout = new TQVBoxLayout( topFrame, 0, spacingHint() ); + + mCalendar = new CalendarLocal( KOPrefs::instance()->mTimeZoneId ); + mListView = new KOListView( mCalendar, topFrame, "PreviewDialog::ListView", true ); + topLayout->addWidget( mListView ); + + topLayout->setSpacing( spacingHint() ); + topLayout->setMargin( marginHint() ); + + connect( this, TQT_SIGNAL(user1Clicked()), TQT_SLOT(slotMerge()) ); + connect( this, TQT_SIGNAL(user2Clicked()), TQT_SLOT(slotAdd()) ); + + // when someone edits a kmail attachment he's editing a tmp file, check for that + // and if it's a tmp file then open a save dialog + if ( isTempFile() ) { + setButtonGuiItem( User2, KGuiItem( i18n("&Add as new calendar..."), "add" ) ); + } else { + setButtonGuiItem( User2, KGuiItem( i18n("&Add as new calendar"), "add" ) ); + } + + mLocalUrl = 0; +} + +PreviewDialog::~PreviewDialog() +{ + if ( mLocalUrl && !mOriginalUrl.isLocalFile() ) { + KIO::NetAccess::removeTempFile( mLocalUrl->path() ); + delete mLocalUrl; + } + + delete mCalendar; +} + +bool PreviewDialog::loadCalendar() +{ + // If it's a remote file, download it so we can give it to CalendarLocal + if ( !mOriginalUrl.isLocalFile() ) { + if ( mLocalUrl ) { + // loadCalendar already called.. remove old one. + KIO::NetAccess::removeTempFile( mLocalUrl->path() ); + delete mLocalUrl; + } + + TQString tmpFile; + if ( KIO::NetAccess::download( mOriginalUrl, tmpFile, 0 ) ) { + mLocalUrl = new KURL( tmpFile ); + } else { + mLocalUrl = 0; + } + } else { + mLocalUrl = &mOriginalUrl; + } + + if ( mLocalUrl ) { + const bool success = mCalendar->load( mLocalUrl->path() ); + + if ( !success && !mOriginalUrl.isLocalFile() ) { + KIO::NetAccess::removeTempFile( mLocalUrl->path() ); + } else { + mListView->showAll(); + } + return success; + } else { + return false; + } +} + +void PreviewDialog::slotMerge() +{ + if ( mLocalUrl ) { + emit openURL( *mLocalUrl, true ); + emit dialogFinished( this ); + accept(); + } +} + +void PreviewDialog::slotAdd() +{ + KURL finalUrl = mOriginalUrl; + if ( isTempFile() ) { + const TQString fileName = + KFileDialog::getSaveFileName( locateLocal( "data","korganizer/" ), + i18n( "*.vcs *.ics|Calendar Files" ), + this, i18n( "Select path for new calendar" ) ); + + finalUrl = KURL( fileName ); + + if ( !KIO::NetAccess::copy( mOriginalUrl, finalUrl, this ) && KIO::NetAccess::lastError() ) { + KMessageBox::error( this, KIO::NetAccess::lastErrorString() ); + return; + } + } + + if ( finalUrl.isValid() ) { + emit addResource( finalUrl ); + emit dialogFinished( this ); + accept(); + } +} + +bool PreviewDialog::isTempFile() const +{ + return mOriginalUrl.path().startsWith( locateLocal( "tmp", "" ) ); +} + +#include "previewdialog.moc" diff --git a/korganizer/previewdialog.h b/korganizer/previewdialog.h new file mode 100644 index 000000000..ed32c5f50 --- /dev/null +++ b/korganizer/previewdialog.h @@ -0,0 +1,69 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 2003,2004 Cornelius Schumacher <schumacher@kde.org> + Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> + + Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net> + Author: Sergio Martins, <sergio.martins@kdab.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of TQt, and distribute the resulting executable, + without including the source code for TQt in the source distribution. +*/ + +#ifndef PREVIEWDIALOG_H +#define PREVIEWDIALOG_H + +#include <kdialogbase.h> +#include <kurl.h> + +class KOListView; + +namespace KCal { + class CalendarLocal; +} + +class PreviewDialog : public KDialogBase +{ + Q_OBJECT + public: + PreviewDialog( const KURL &url, TQWidget *parent ); + ~PreviewDialog(); + bool loadCalendar(); + + public slots: + void slotAdd(); + void slotMerge(); + + signals: + void dialogFinished( PreviewDialog * ); + void openURL( const KURL &, bool ); + void addResource( const KURL & ); + + private: + // Checks if mOriginalUrl is a temp file, if it is we ask the user a place to + // keep the calendar file + bool isTempFile() const; + private: + KURL mOriginalUrl; + KURL *mLocalUrl; + KOListView *mListView; + KCal::CalendarLocal *mCalendar; +}; + +#endif diff --git a/korganizer/printing/calprintdefaultplugins.cpp b/korganizer/printing/calprintdefaultplugins.cpp index bc4c62496..38d9b4b72 100644 --- a/korganizer/printing/calprintdefaultplugins.cpp +++ b/korganizer/printing/calprintdefaultplugins.cpp @@ -4,6 +4,7 @@ Copyright (c) 1998 Preston Brown <pbrown@kde.org> Copyright (c) 2003 Reinhold Kainhofer <reinhold@kainhofer.com> Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + Copyright (c) 2008 Ron Goodheart <ron.goodheart@gmail.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,6 +39,8 @@ #include <knuminput.h> #include <kcombobox.h> +#include <libkcal/incidenceformatter.h> + #include "calprintdefaultplugins.h" #include "calprintincidenceconfig_base.h" @@ -46,7 +49,6 @@ #include "calprintmonthconfig_base.h" #include "calprinttodoconfig_base.h" - /************************************************************** * Print Incidence **************************************************************/ @@ -131,18 +133,18 @@ class TimePrintStringsVisitor : public IncidenceBase::Visitor protected: bool visit( Event *event ) { if ( event->dtStart().isValid() ) { - mStartCaption = i18n("Start date: "); - // Show date/time or only date, depending on whether it's an all-day event -// TODO: Add shortfmt param to dtStartStr, dtEndStr and dtDueStr!!! - mStartString = (event->doesFloat()) ? (event->dtStartDateStr(false)) : (event->dtStartStr()); + mStartCaption = i18n( "Start date: " ); + mStartString = IncidenceFormatter::dateTimeToString( + event->dtStart(), event->doesFloat(), false ); } else { - mStartCaption = i18n("No start date"); + mStartCaption = i18n( "No start date" ); mStartString = TQString::null; } - + if ( event->hasEndDate() ) { - mEndCaption = i18n("End date: "); - mEndString = (event->doesFloat()) ? (event->dtEndDateStr(false)) : (event->dtEndStr()); + mEndCaption = i18n( "End date: " ); + mEndString = IncidenceFormatter::dateTimeToString( + event->dtEnd(), event->doesFloat(), false ); } else if ( event->hasDuration() ) { mEndCaption = i18n("Duration: "); int mins = event->duration() / 60; @@ -160,18 +162,18 @@ class TimePrintStringsVisitor : public IncidenceBase::Visitor } bool visit( Todo *todo ) { if ( todo->hasStartDate() ) { - mStartCaption = i18n("Start date: "); - // Show date/time or only date, depending on whether it's an all-day event -// TODO: Add shortfmt param to dtStartStr, dtEndStr and dtDueStr!!! - mStartString = (todo->doesFloat()) ? (todo->dtStartDateStr(false)) : (todo->dtStartStr()); + mStartCaption = i18n( "Start date: " ); + mStartString = IncidenceFormatter::dateTimeToString( + todo->dtStart(), todo->doesFloat(), false ); } else { - mStartCaption = i18n("No start date"); + mStartCaption = i18n( "No start date" ); mStartString = TQString::null; } - + if ( todo->hasDueDate() ) { - mEndCaption = i18n("Due date: "); - mEndString = (todo->doesFloat()) ? (todo->dtDueDateStr(false)) : (todo->dtDueStr()); + mEndCaption = i18n( "Due date: " ); + mEndString = IncidenceFormatter::dateTimeToString( + todo->dtDue(), todo->doesFloat(), false ); } else { mEndCaption = i18n("No due date"); mEndString = TQString::null; @@ -179,9 +181,9 @@ class TimePrintStringsVisitor : public IncidenceBase::Visitor return true; } bool visit( Journal *journal ) { - mStartCaption = i18n("Start date: "); -// TODO: Add shortfmt param to dtStartStr, dtEndStr and dtDueStr!!! - mStartString = (journal->doesFloat()) ? (journal->dtStartDateStr(false)) : (journal->dtStartStr()); + mStartCaption = i18n( "Start date: " ); + mStartString = IncidenceFormatter::dateTimeToString( + journal->dtStart(), journal->doesFloat(), false ); mEndCaption = TQString::null; mEndString = TQString::null; return true; @@ -210,8 +212,6 @@ int CalPrintIncidence::printCaptionAndText( TQPainter &p, const TQRect &box, con #include <tqfontdatabase.h> void CalPrintIncidence::print( TQPainter &p, int width, int height ) { - KLocale *local = KGlobal::locale(); - TQFont oldFont(p.font()); TQFont textFont( "sans-serif", 11, TQFont::Normal ); TQFont captionFont( "sans-serif", 11, TQFont::Bold ); @@ -267,7 +267,7 @@ void CalPrintIncidence::print( TQPainter &p, int width, int height ) TQRect timesBox( titleBox ); timesBox.setTop( titleBox.bottom() + padding() ); timesBox.setHeight( height / 8 ); - + TimePrintStringsVisitor stringVis; int h = timesBox.top(); if ( stringVis.act(*it) ) { @@ -279,28 +279,41 @@ void CalPrintIncidence::print( TQPainter &p, int width, int height ) textRect.setRight( timesBox.right() - padding() ); h = QMAX( printCaptionAndText( p, textRect, stringVis.mEndCaption, stringVis.mEndString, captionFont, textFont ), h ); } - - + + // Convert recurrence to a string if ( (*it)->doesRecur() ) { TQRect recurBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight ); - // TODO: Convert the recurrence to a string and print it out! - TQString recurString( "TODO: Convert Repeat to String!" ); - h = QMAX( printCaptionAndText( p, recurBox, i18n("Repeats: "), recurString, captionFont, textFont ), h ); + KCal::Recurrence *recurs = (*it)->recurrence(); + + TQString displayString = IncidenceFormatter::recurrenceString((*it)); + // exception dates + TQString exceptString; + if ( !recurs->exDates().isEmpty() ) { + exceptString = i18n("except for listed dates", " except"); + for ( uint i = 0; i < recurs->exDates().size(); i++ ) { + exceptString.append(" "); + exceptString.append( KGlobal::locale()->formatDate(recurs->exDates()[i], + true) ); + } + } + displayString.append(exceptString); + h = QMAX( printCaptionAndText( p, recurBox, i18n( "Repeats: "), displayString, captionFont, textFont ), h ); } - + + // Alarms Printing TQRect alarmBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight ); Alarm::List alarms = (*it)->alarms(); if ( alarms.count() == 0 ) { cap = i18n("No reminders"); - txt = TQString::null; + txt = TQString(); } else { cap = i18n("Reminder: ", "%n reminders: ", alarms.count() ); - + TQStringList alarmStrings; KCal::Alarm::List::ConstIterator it; for ( it = alarms.begin(); it != alarms.end(); ++it ) { Alarm *alarm = *it; - + // Alarm offset, copied from koeditoralarms.cpp: TQString offsetstr; int offset = 0; @@ -345,7 +358,7 @@ void CalPrintIncidence::print( TQPainter &p, int width, int height ) TQRect organizerBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight ); h = QMAX( printCaptionAndText( p, organizerBox, i18n("Organizer: "), (*it)->organizer().fullName(), captionFont, textFont ), h ); - + // Finally, draw the frame around the time information... timesBox.setBottom( QMAX( timesBox.bottom(), h+padding() ) ); drawBox( p, BOX_BORDER_WIDTH, timesBox ); @@ -360,43 +373,67 @@ void CalPrintIncidence::print( TQPainter &p, int width, int height ) // Now start constructing the boxes from the bottom: - TQRect categoriesBox( locationBox ); - categoriesBox.setBottom( box.bottom() ); - categoriesBox.setTop( categoriesBox.bottom() - lineHeight - 2*padding() ); + TQRect footerBox( locationBox ); + footerBox.setBottom( box.bottom() ); + footerBox.setTop( footerBox.bottom() - lineHeight - 2*padding() ); + TQRect categoriesBox( footerBox ); + categoriesBox.setBottom( footerBox.top() ); + categoriesBox.setTop( categoriesBox.bottom() - lineHeight - 2*padding() ); TQRect attendeesBox( box.left(), categoriesBox.top()-padding()-box.height()/9, box.width(), box.height()/9 ); - if ( !mShowAttendees ) { - attendeesBox.setTop( categoriesBox.top() ); - } + TQRect attachmentsBox( box.left(), attendeesBox.top()-padding()-box.height()/9, box.width()*3/4 - padding(), box.height()/9 ); TQRect optionsBox( attachmentsBox.right() + padding(), attachmentsBox.top(), 0, 0 ); optionsBox.setRight( box.right() ); optionsBox.setBottom( attachmentsBox.bottom() ); TQRect notesBox( optionsBox.left(), locationBox.bottom() + padding(), optionsBox.width(), 0 ); notesBox.setBottom( optionsBox.top() - padding() ); - - // TODO: Adjust boxes depending on the show options... -// if ( !mShowOptions ) { -// optionsBox.left() -// bool mShowOptions; -// // bool mShowSubitemsNotes; -// bool mShowAttendees; -// bool mShowAttachments; - TQRect descriptionBox( notesBox ); descriptionBox.setLeft( box.left() ); - descriptionBox.setRight( mShowOptions?(attachmentsBox.right()):(box.right()) ); + descriptionBox.setRight( attachmentsBox.right() ); + // Adjust boxes depending on the show options... + if (!mShowSubitemsNotes) { + descriptionBox.setRight( box.right() ); + } + if (!mShowAttachments || !mShowAttendees) { + descriptionBox.setBottom( attachmentsBox.bottom() ); + optionsBox.setTop( attendeesBox.top() ); + optionsBox.setBottom( attendeesBox.bottom() ); + notesBox.setBottom( attachmentsBox.bottom() ); + if (mShowOptions) { + attendeesBox.setRight( attachmentsBox.right() ); + } + if (!mShowAttachments && !mShowAttendees) { + if (mShowSubitemsNotes) { + descriptionBox.setBottom( attendeesBox.bottom() ); + } + if (!mShowOptions) { + descriptionBox.setBottom( attendeesBox.bottom() ); + notesBox.setBottom( attendeesBox.bottom() ); + } + } + } + if (mShowAttachments) { + if (!mShowOptions) { + attachmentsBox.setRight( box.right() ); + attachmentsBox.setRight( box.right() ); + } + if (!mShowAttendees) { + attachmentsBox.setTop( attendeesBox.top() ); + attachmentsBox.setBottom( attendeesBox.bottom() ); + } + } - drawBoxWithCaption( p, descriptionBox, i18n("Description:"), - (*it)->description(), /*sameLine=*/false, + drawBoxWithCaption( p, descriptionBox, i18n("Description:"), + (*it)->description(), /*sameLine=*/false, /*expand=*/false, captionFont, textFont ); - + if ( mShowSubitemsNotes ) { if ( (*it)->relations().isEmpty() || (*it)->type() != "Todo" ) { - int notesPosition = drawBoxWithCaption( p, notesBox, i18n("Notes:"), - TQString::null, /*sameLine=*/false, /*expand=*/false, + int notesPosition = drawBoxWithCaption( p, notesBox, i18n("Notes:"), + TQString::null, /*sameLine=*/false, /*expand=*/false, captionFont, textFont ); TQPen oldPen( p.pen() ); p.setPen( Qt::DotLine ); @@ -405,18 +442,104 @@ void CalPrintIncidence::print( TQPainter &p, int width, int height ) } p.setPen( oldPen ); } else { - int subitemsStart = drawBoxWithCaption( p, notesBox, i18n("Subitems:"), - (*it)->description(), /*sameLine=*/false, + Incidence::List relations = (*it)->relations(); + TQString subitemCaption; + if ( relations.count() == 0 ) { + subitemCaption = i18n( "No Subitems" ); + txt == ""; + } else { + subitemCaption = i18n( "1 Subitem:", + "%1 Subitems:", + relations.count() ); + } + Incidence::List::ConstIterator rit; + TQString subitemString; + TQString statusString; + TQString datesString; + int count = 0; + for ( rit = relations.begin(); rit != relations.end(); ++rit ) { + ++count; + if ( !(*rit) ) { // defensive, skip any zero pointers + continue; + } + // format the status + statusString = (*rit)->statusStr(); + if ( statusString.isEmpty() ) { + if ( (*rit)->status() == Incidence::StatusNone ) { + statusString = i18n( "no status", "none" ); + } else { + statusString = i18n( "unknown status", "unknown" ); + } + } + // format the dates if provided + datesString = ""; + if ( (*rit)->dtStart().isValid() ) { + datesString += i18n( + "Start Date: %1\n").arg( + KGlobal::locale()->formatDate( (*rit)->dtStart().date(), + true ) ); + if ( !(*rit)->doesFloat() ) { + datesString += i18n( + "Start Time: %1\n").arg( + KGlobal::locale()->formatTime((*rit)->dtStart().time(), + false, false) ); + } + } + if ( (*rit)->dtEnd().isValid() ) { + subitemString += i18n( + "Due Date: %1\n").arg( + KGlobal::locale()->formatDate( (*rit)->dtEnd().date(), + true ) ); + if ( !(*rit)->doesFloat() ) { + subitemString += i18n( + "subitem due time", "Due Time: %1\n").arg( + KGlobal::locale()->formatTime((*rit)->dtEnd().time(), + false, false) ); + } + } + subitemString += i18n("subitem counter", "%1: ", count); + subitemString += (*rit)->summary(); + subitemString += "\n"; + if ( !datesString.isEmpty() ) { + subitemString += datesString; + subitemString += "\n"; + } + subitemString += i18n( "subitem Status: statusString", + "Status: %1\n").arg( statusString ); + subitemString += IncidenceFormatter::recurrenceString((*rit)) + "\n"; + subitemString += i18n( "subitem Priority: N", + "Priority: %1\n").arg( (*rit)->priority() ); + subitemString += i18n( "subitem Secrecy: secrecyString", + "Secrecy: %1\n").arg( (*rit)->secrecyStr() ); + subitemString += "\n"; + } + drawBoxWithCaption( p, notesBox, i18n("Subitems:"), + (*it)->description(), /*sameLine=*/false, /*expand=*/false, captionFont, textFont ); - // TODO: Draw subitems } } if ( mShowAttachments ) { - int attachStart = drawBoxWithCaption( p, attachmentsBox, - i18n("Attachments:"), TQString::null, /*sameLine=*/false, - /*expand=*/false, captionFont, textFont ); - // TODO: Print out the attachments somehow + Attachment::List attachments = (*it)->attachments(); + TQString attachmentCaption; + if ( attachments.count() == 0 ) { + attachmentCaption = i18n( "No Attachments" ); + txt = TQString(); + } else { + attachmentCaption = i18n( "1 Attachment:", "%1 Attachments:", attachments.count() ); + } + TQString attachmentString; + Attachment::List::ConstIterator ait = attachments.begin(); + for ( ; ait != attachments.end(); ++ait ) { + if (!attachmentString.isEmpty()) { + attachmentString += i18n( "Spacer for list of attachments", " " ); + } + attachmentString.append((*ait)->label()); + } + drawBoxWithCaption( p, attachmentsBox, + attachmentCaption, attachmentString, + /*sameLine=*/false, /*expand=*/false, + captionFont, textFont ); } if ( mShowAttendees ) { @@ -436,7 +559,7 @@ void CalPrintIncidence::print( TQPainter &p, int width, int height ) .arg( (*ait)->fullName() ) .arg( (*ait)->roleStr() ).arg( (*ait)->statusStr() ); } - drawBoxWithCaption( p, attendeesBox, i18n("Attendees:"), attendeeString, + drawBoxWithCaption( p, attendeesBox, i18n("Attendees:"), attendeeString, /*sameLine=*/false, /*expand=*/false, captionFont, textFont ); } @@ -470,10 +593,12 @@ void CalPrintIncidence::print( TQPainter &p, int width, int height ) drawBoxWithCaption( p, optionsBox, i18n("Settings: "), optionsString, /*sameLine=*/false, /*expand=*/false, captionFont, textFont ); } - + drawBoxWithCaption( p, categoriesBox, i18n("Categories: "), (*it)->categories().join( i18n("Spacer for the joined list of categories", ", ") ), /*sameLine=*/true, /*expand=*/false, captionFont, textFont ); + + drawFooter( p, footerBox ); } p.setFont( oldFont ); } @@ -570,6 +695,12 @@ void CalPrintDay::print( TQPainter &p, int width, int height ) { TQDate curDay( mFromDate ); + TQRect headerBox( 0, 0, width, headerHeight() ); + TQRect footerBox( 0, height - footerHeight(), width, footerHeight() ); + height -= footerHeight(); + + KLocale *local = KGlobal::locale(); + do { TQTime curStartTime( mStartTime ); TQTime curEndTime( mEndTime ); @@ -581,35 +712,89 @@ void CalPrintDay::print( TQPainter &p, int width, int height ) curEndTime = curStartTime.addSecs( 3600 ); } - KLocale *local = KGlobal::locale(); - TQRect headerBox( 0, 0, width, headerHeight() ); drawHeader( p, local->formatDate( curDay ), curDay, TQDate(), headerBox ); - - Event::List eventList = mCalendar->events( curDay, EventSortStartDate, SortDirectionAscending ); - p.setFont( TQFont( "sans-serif", 12 ) ); + // split out the all day events as they will be printed in a separate box + Event::List alldayEvents, timedEvents; + Event::List::ConstIterator it; + for ( it = eventList.begin(); it != eventList.end(); ++it ) { + if ( (*it)->doesFloat() ) { + alldayEvents.append( *it ); + } else { + timedEvents.append( *it ); + } + } + + int fontSize = 11; + TQFont textFont( "sans-serif", fontSize, TQFont::Normal ); + p.setFont( textFont ); + uint lineSpacing = p.fontMetrics().lineSpacing(); - // TODO: Find a good way to determine the height of the all-day box + uint maxAllDayEvents = 8; // the max we allow to be printed, sorry. + uint allDayHeight = QMIN( alldayEvents.count(), maxAllDayEvents ) * lineSpacing; + allDayHeight = QMAX( allDayHeight, ( 5 * lineSpacing ) ) + ( 2 * padding() ); TQRect allDayBox( TIMELINE_WIDTH + padding(), headerBox.bottom() + padding(), - 0, height / 20 ); - allDayBox.setRight( width ); - int allDayHeight = drawAllDayBox( p, eventList, curDay, true, allDayBox ); + width - TIMELINE_WIDTH - padding(), allDayHeight ); + if ( alldayEvents.count() > 0 ) { + // draw the side bar for all-day events + TQFont oldFont( p.font() ); + p.setFont( TQFont( "sans-serif", 9, TQFont::Normal ) ); + drawVerticalBox( p, + BOX_BORDER_WIDTH, + TQRect( 0, headerBox.bottom() + padding(), TIMELINE_WIDTH, allDayHeight ), + i18n( "Today's Events" ), + TQt::AlignHCenter | TQt::AlignVCenter | TQt::WordBreak ); + p.setFont( oldFont ); + + // now draw at most maxAllDayEvents in the all-day box + drawBox( p, BOX_BORDER_WIDTH, allDayBox ); + + Event::List::ConstIterator it; + TQRect eventBox( allDayBox ); + eventBox.setLeft( TIMELINE_WIDTH + ( 2 * padding() ) ); + eventBox.setTop( eventBox.top() + padding() ); + eventBox.setBottom( eventBox.top() + lineSpacing ); + uint count = 0; + for ( it = alldayEvents.begin(); it != alldayEvents.end(); ++it ) { + if ( count == maxAllDayEvents ) { + break; + } + count++; + TQString str; + if ( (*it)->location().isEmpty() ) { + str = cleanStr( (*it)->summary() ); + } else { + str = i18n( "summary, location", "%1, %2" ). + arg( cleanStr( (*it)->summary() ), cleanStr( (*it)->location() ) ); + } + printEventString( p, eventBox, str ); + eventBox.setTop( eventBox.bottom() ); + eventBox.setBottom( eventBox.top() + lineSpacing ); + } + } else { + allDayBox.setBottom( headerBox.bottom() ); + } TQRect dayBox( allDayBox ); - dayBox.setTop( allDayHeight /*allDayBox.bottom()*/ ); + dayBox.setTop( allDayBox.bottom() + padding() ); dayBox.setBottom( height ); - drawAgendaDayBox( p, eventList, curDay, mIncludeAllEvents, + drawAgendaDayBox( p, timedEvents, curDay, mIncludeAllEvents, curStartTime, curEndTime, dayBox ); TQRect tlBox( dayBox ); tlBox.setLeft( 0 ); tlBox.setWidth( TIMELINE_WIDTH ); drawTimeLine( p, curStartTime, curEndTime, tlBox ); + + drawFooter( p, footerBox ); + curDay = curDay.addDays( 1 ); - if ( curDay <= mToDate ) mPrinter->newPage(); + if ( curDay <= mToDate ) { + mPrinter->newPage(); + } } while ( curDay <= mToDate ); } @@ -728,6 +913,9 @@ void CalPrintWeek::print( TQPainter &p, int width, int height ) TQString line1, line2, title; TQRect headerBox( 0, 0, width, headerHeight() ); + TQRect footerBox( 0, height - footerHeight(), width, footerHeight() ); + height -= footerHeight(); + TQRect weekBox( headerBox ); weekBox.setTop( headerBox.bottom() + padding() ); weekBox.setBottom( height ); @@ -744,7 +932,11 @@ void CalPrintWeek::print( TQPainter &p, int width, int height ) } title = title.arg( line1 ).arg( line2 ); drawHeader( p, title, curWeek.addDays( -6 ), TQDate(), headerBox ); + drawWeek( p, curWeek, weekBox ); + + drawFooter( p, footerBox ); + curWeek = curWeek.addDays( 7 ); if ( curWeek <= toWeek ) mPrinter->newPage(); @@ -763,11 +955,14 @@ void CalPrintWeek::print( TQPainter &p, int width, int height ) } title = title.arg( line1 ).arg( line2 ).arg( curWeek.weekNumber() ); drawHeader( p, title, curWeek, TQDate(), headerBox ); + TQRect weekBox( headerBox ); weekBox.setTop( headerBox.bottom() + padding() ); weekBox.setBottom( height ); - drawTimeTable( p, fromWeek, curWeek, mStartTime, mEndTime, weekBox ); + + drawFooter( p, footerBox ); + fromWeek = fromWeek.addDays( 7 ); curWeek = fromWeek.addDays( 6 ); if ( curWeek <= toWeek ) @@ -792,6 +987,8 @@ void CalPrintWeek::print( TQPainter &p, int width, int height ) drawTimeTable( p, endLeft.addDays( 1 ), curWeek, mStartTime, mEndTime, weekBox1 ); + drawFooter( p, footerBox ); + fromWeek = fromWeek.addDays( 7 ); curWeek = fromWeek.addDays( 6 ); if ( curWeek <= toWeek ) @@ -910,6 +1107,9 @@ void CalPrintMonth::print( TQPainter &p, int width, int height ) if ( !calSys ) return; TQRect headerBox( 0, 0, width, headerHeight() ); + TQRect footerBox( 0, height - footerHeight(), width, footerHeight() ); + height -= footerHeight(); + TQRect monthBox( 0, 0, width, height ); monthBox.setTop( headerBox.bottom() + padding() ); @@ -924,6 +1124,9 @@ void CalPrintMonth::print( TQPainter &p, int width, int height ) drawHeader( p, title, curMonth.addMonths( -1 ), curMonth.addMonths( 1 ), headerBox ); drawMonthTable( p, curMonth, mWeekNumbers, mRecurDaily, mRecurWeekly, monthBox ); + + drawFooter( p, footerBox ); + curMonth = curMonth.addDays( curMonth.daysInMonth() ); if ( curMonth <= toMonth ) mPrinter->newPage(); } while ( curMonth <= toMonth ); @@ -1054,30 +1257,32 @@ void CalPrintTodos::saveConfig() void CalPrintTodos::print( TQPainter &p, int width, int height ) { // TODO: Find a good way to guarantee a nicely designed output - int pospriority = 10; - int possummary = 60; + int pospriority = 0; + int possummary = 100; int posdue = width - 65; int poscomplete = posdue - 70; //Complete column is to right of the Due column int lineSpacing = 15; int fontHeight = 10; + TQRect headerBox( 0, 0, width, headerHeight() ); + TQRect footerBox( 0, height - footerHeight(), width, footerHeight() ); + height -= footerHeight(); + // Draw the First Page Header - drawHeader( p, mPageTitle, mFromDate, TQDate(), - TQRect( 0, 0, width, headerHeight() ) ); + drawHeader( p, mPageTitle, mFromDate, TQDate(), headerBox ); // Draw the Column Headers int mCurrentLinePos = headerHeight() + 5; TQString outStr; TQFont oldFont( p.font() ); - p.setFont( TQFont( "sans-serif", 10, TQFont::Bold ) ); + p.setFont( TQFont( "sans-serif", 9, TQFont::Bold ) ); lineSpacing = p.fontMetrics().lineSpacing(); mCurrentLinePos += lineSpacing; if ( mIncludePriority ) { outStr += i18n( "Priority" ); p.drawText( pospriority, mCurrentLinePos - 2, outStr ); } else { - possummary = 10; pospriority = -1; } @@ -1179,8 +1384,9 @@ void CalPrintTodos::print( TQPainter &p, int width, int height ) 0, 0, mCurrentLinePos, width, height, todoList ); } } + + drawFooter( p, footerBox ); p.setFont( oldFont ); } - #endif diff --git a/korganizer/printing/calprintdefaultplugins.h b/korganizer/printing/calprintdefaultplugins.h index 79a909a87..a16526433 100644 --- a/korganizer/printing/calprintdefaultplugins.h +++ b/korganizer/printing/calprintdefaultplugins.h @@ -42,10 +42,20 @@ class CalPrintIncidence : public CalPrintPluginBase public: CalPrintIncidence(); virtual ~CalPrintIncidence(); - virtual TQString description() { return i18n("Print &incidence"); } - virtual TQString info() { return i18n("Prints an incidence on one page"); } - virtual int sortID() { return CalPrinterBase::Incidence; } - // Enable the Print Incidence option only if there are selected incidences. + virtual TQString description() + { + return i18n( "Print &incidence" ); + } + virtual TQString info() + { + return i18n( "Prints an incidence on one page" ); + } + virtual int sortID() + { + return CalPrinterBase::Incidence; + } + + // Enable the Print Incidence option only if there are selected incidences. virtual bool enabled() { if ( mSelectedIncidences.count() > 0 ) { @@ -54,9 +64,11 @@ class CalPrintIncidence : public CalPrintPluginBase return false; } } - virtual TQWidget *createConfigWidget(TQWidget*); + virtual TQWidget *createConfigWidget( TQWidget * ); virtual KPrinter::Orientation defaultOrientation() - { return KPrinter::Portrait; } + { + return KPrinter::Portrait; + } public: void print( TQPainter &p, int width, int height ); @@ -66,7 +78,7 @@ class CalPrintIncidence : public CalPrintPluginBase virtual void saveConfig(); protected: int printCaptionAndText( TQPainter &p, const TQRect &box, const TQString &caption, - const TQString &text, TQFont captionFont, TQFont textFont ); + const TQString &text, TQFont captionFont, TQFont textFont ); protected: @@ -82,10 +94,22 @@ class CalPrintDay : public CalPrintPluginBase public: CalPrintDay(); virtual ~CalPrintDay(); - virtual TQString description() { return i18n("Print da&y"); } - virtual TQString info() { return i18n("Prints all events of a single day on one page"); } - virtual int sortID() { return CalPrinterBase::Day; } - virtual bool enabled() { return true; } + virtual TQString description() + { + return i18n( "Print da&y" ); + } + virtual TQString info() + { + return i18n( "Prints all events of a single day on one page" ); + } + virtual int sortID() + { + return CalPrinterBase::Day; + } + virtual bool enabled() + { + return true; + } virtual TQWidget *createConfigWidget( TQWidget* ); public: @@ -107,11 +131,24 @@ class CalPrintWeek : public CalPrintPluginBase public: CalPrintWeek(); virtual ~CalPrintWeek(); - virtual TQString description() { return i18n("Print &week"); } - virtual TQString info() { return i18n("Prints all events of one week on one page"); } - virtual int sortID() { return CalPrinterBase::Week; } - virtual bool enabled() { return true; } - virtual TQWidget *createConfigWidget(TQWidget*); + virtual TQString description() + { + return i18n( "Print &week" ); + } + virtual TQString info() + { + return i18n( "Prints all events of one week on one page" ); + } + virtual int sortID() + { + return CalPrinterBase::Week; + } + virtual bool enabled() + { + return true; + } + virtual TQWidget *createConfigWidget( TQWidget * ); + /** Returns the default orientation for the eWeekPrintType. */ @@ -136,12 +173,28 @@ class CalPrintMonth : public CalPrintPluginBase public: CalPrintMonth(); virtual ~CalPrintMonth(); - virtual TQString description() { return i18n("Print mont&h"); } - virtual TQString info() { return i18n("Prints all events of one month on one page"); } - virtual int sortID() { return CalPrinterBase::Month; } - virtual bool enabled() { return true; } - virtual TQWidget *createConfigWidget(TQWidget*); - virtual KPrinter::Orientation defaultOrientation() { return KPrinter::Landscape; } + virtual TQString description() + { + return i18n( "Print mont&h" ); + } + virtual TQString info() + { + return i18n( "Prints all events of one month on one page" ); + } + virtual int sortID() + { + return CalPrinterBase::Month; + } + virtual bool enabled() + { + return true; + } + virtual TQWidget *createConfigWidget( TQWidget * ); + virtual KPrinter::Orientation defaultOrientation() + { + return KPrinter::Landscape; + } + public: void print(TQPainter &p, int width, int height); @@ -163,11 +216,23 @@ class CalPrintTodos : public CalPrintPluginBase public: CalPrintTodos(); virtual ~CalPrintTodos(); - virtual TQString description() { return i18n("Print to-&dos"); } - virtual TQString info() { return i18n("Prints all to-dos in a (tree-like) list"); } - virtual int sortID() { return CalPrinterBase::Todolist; } - virtual bool enabled() { return true; } - virtual TQWidget *createConfigWidget(TQWidget*); + virtual TQString description() + { + return i18n( "Print to-&dos" ); + } + virtual TQString info() + { + return i18n( "Prints all to-dos in a (tree-like) list" ); + } + virtual int sortID() + { + return CalPrinterBase::Todolist; + } + virtual bool enabled() + { + return true; + } + virtual TQWidget *createConfigWidget( TQWidget * ); public: void print( TQPainter &p, int width, int height ); @@ -180,18 +245,23 @@ class CalPrintTodos : public CalPrintPluginBase TQString mPageTitle; enum eTodoPrintType { - TodosAll = 0, TodosUnfinished, TodosDueRange + TodosAll = 0, + TodosUnfinished, + TodosDueRange } mTodoPrintType; enum eTodoSortField { - TodoFieldSummary=0, - TodoFieldStartDate, TodoFieldDueDate, - TodoFieldPriority, TodoFieldPercentComplete, + TodoFieldSummary = 0, + TodoFieldStartDate, + TodoFieldDueDate, + TodoFieldPriority, + TodoFieldPercentComplete, TodoFieldUnset } mTodoSortField; enum eTodoSortDirection { - TodoDirectionAscending=0, TodoDirectionDescending, + TodoDirectionAscending = 0, + TodoDirectionDescending, TodoDirectionUnset } mTodoSortDirection; @@ -205,5 +275,7 @@ class CalPrintTodos : public CalPrintPluginBase bool mSortDirection; }; + #endif + #endif diff --git a/korganizer/printing/calprintpluginbase.cpp b/korganizer/printing/calprintpluginbase.cpp index 6f6762032..e16e72c6b 100644 --- a/korganizer/printing/calprintpluginbase.cpp +++ b/korganizer/printing/calprintpluginbase.cpp @@ -39,9 +39,16 @@ #ifndef KORG_NOPRINTER inline int round(const double x) - { - return int(x > 0.0 ? x + 0.5 : x - 0.5); - } +{ + return int(x > 0.0 ? x + 0.5 : x - 0.5); +} + +static TQString cleanStr( const TQString &instr ) +{ + TQString ret = instr; + return ret.replace( '\n', ' ' ); +} + /****************************************************************** ** The Todo positioning structure ** ******************************************************************/ @@ -108,8 +115,8 @@ class PrintCellItem : public KOrg::CellItem CalPrintPluginBase::CalPrintPluginBase() : PrintPlugin(), mUseColors( true ), - mHeaderHeight(-1), mSubHeaderHeight( SUBHEADER_HEIGHT ), - mMargin( MARGIN_SIZE ), mPadding( PADDING_SIZE), mCalSys( 0 ) + mHeaderHeight( -1 ), mSubHeaderHeight( SUBHEADER_HEIGHT ), mFooterHeight( -1 ), + mMargin( MARGIN_SIZE ), mPadding( PADDING_SIZE), mCalSys( 0 ) { } CalPrintPluginBase::~CalPrintPluginBase() @@ -245,9 +252,9 @@ void CalPrintPluginBase::setCategoryColors( TQPainter &p, Incidence *incidence ) TQColor CalPrintPluginBase::categoryBgColor( Incidence *incidence ) { - if (mCoreHelper && incidence) + if (mCoreHelper && incidence) return mCoreHelper->categoryColor( incidence->categories() ); - else + else return TQColor(); } @@ -314,6 +321,20 @@ void CalPrintPluginBase::setSubHeaderHeight( const int height ) mSubHeaderHeight = height; } +int CalPrintPluginBase::footerHeight() const +{ + if ( mFooterHeight >= 0 ) + return mFooterHeight; + else if ( orientation() == KPrinter::Portrait ) + return PORTRAIT_FOOTER_HEIGHT; + else + return LANDSCAPE_FOOTER_HEIGHT; +} +void CalPrintPluginBase::setFooterHeight( const int height ) +{ + mFooterHeight = height; +} + int CalPrintPluginBase::margin() const { return mMargin; @@ -370,7 +391,8 @@ void CalPrintPluginBase::printEventString( TQPainter &p, const TQRect &box, cons } -void CalPrintPluginBase::showEventBox( TQPainter &p, const TQRect &box, Incidence *incidence, const TQString &str, int flags ) +void CalPrintPluginBase::showEventBox( TQPainter &p, int linewidth, const TQRect &box, + Incidence *incidence, const TQString &str, int flags ) { TQPen oldpen( p.pen() ); TQBrush oldbrush( p.brush() ); @@ -380,7 +402,7 @@ void CalPrintPluginBase::showEventBox( TQPainter &p, const TQRect &box, Incidenc } else { p.setBrush( TQColor( 232, 232, 232 ) ); } - drawBox( p, EVENT_BORDER_WIDTH, box ); + drawBox( p, ( linewidth > 0 ) ? linewidth : EVENT_BORDER_WIDTH, box ); if ( mUseColors && bgColor.isValid() ) { p.setPen( textColor( bgColor ) ); @@ -391,8 +413,7 @@ void CalPrintPluginBase::showEventBox( TQPainter &p, const TQRect &box, Incidenc } -void CalPrintPluginBase::drawSubHeaderBox(TQPainter &p, const TQString &str, - const TQRect &box ) +void CalPrintPluginBase::drawSubHeaderBox(TQPainter &p, const TQString &str, const TQRect &box ) { drawShadedBox( p, BOX_BORDER_WIDTH, TQColor( 232, 232, 232 ), box ); TQFont oldfont( p.font() ); @@ -401,12 +422,14 @@ void CalPrintPluginBase::drawSubHeaderBox(TQPainter &p, const TQString &str, p.setFont( oldfont ); } -void CalPrintPluginBase::drawVerticalBox( TQPainter &p, const TQRect &box, const TQString &str ) +void CalPrintPluginBase::drawVerticalBox( TQPainter &p, int linewidth, const TQRect &box, + const TQString &str, int flags ) { p.save(); p.rotate( -90 ); TQRect rotatedBox( -box.top()-box.height(), box.left(), box.height(), box.width() ); - showEventBox( p, rotatedBox, 0, str, Qt::AlignLeft | Qt::AlignVCenter | Qt::SingleLine ); + showEventBox( p, linewidth, rotatedBox, 0, str, + ( flags == -1 ) ? Qt::AlignLeft | Qt::AlignVCenter | Qt::SingleLine : flags ); p.restore(); } @@ -414,10 +437,10 @@ void CalPrintPluginBase::drawVerticalBox( TQPainter &p, const TQRect &box, const /////////////////////////////////////////////////////////////////////////////// -// Return value: If expand, bottom of the printed box, otherwise vertical end +// Return value: If expand, bottom of the printed box, otherwise vertical end // of the printed contents inside the box. -int CalPrintPluginBase::drawBoxWithCaption( TQPainter &p, const TQRect &allbox, +int CalPrintPluginBase::drawBoxWithCaption( TQPainter &p, const TQRect &allbox, const TQString &caption, const TQString &contents, bool sameLine, bool expand, const TQFont &captionFont, const TQFont &textFont ) { TQFont oldFont( p.font() ); @@ -428,17 +451,17 @@ int CalPrintPluginBase::drawBoxWithCaption( TQPainter &p, const TQRect &allbox, TQRect box( allbox ); - + // Bounding rectangle for caption, single-line, clip on the right TQRect captionBox( box.left() + padding(), box.top() + padding(), 0, 0 ); p.setFont( captionFont ); captionBox = p.boundingRect( captionBox, Qt::AlignLeft | Qt::AlignTop | Qt::SingleLine, caption ); p.setFont( oldFont ); - if ( captionBox.right() > box.right() ) + if ( captionBox.right() > box.right() ) captionBox.setRight( box.right() ); - if ( expand && captionBox.bottom() + padding() > box.bottom() ) + if ( expand && captionBox.bottom() + padding() > box.bottom() ) box.setBottom( captionBox.bottom() + padding() ); - + // Bounding rectangle for the contents (if any), word break, clip on the bottom TQRect textBox( captionBox ); if ( !contents.isEmpty() ) { @@ -460,7 +483,7 @@ int CalPrintPluginBase::drawBoxWithCaption( TQPainter &p, const TQRect &allbox, } } } - + drawBox( p, BOX_BORDER_WIDTH, box ); p.setFont( captionFont ); p.drawText( captionBox, Qt::AlignLeft | Qt::AlignTop | Qt::SingleLine, caption ); @@ -469,7 +492,7 @@ int CalPrintPluginBase::drawBoxWithCaption( TQPainter &p, const TQRect &allbox, p.drawText( textBox, Qt::WordBreak | Qt::AlignTop | Qt::AlignLeft, contents ); } p.setFont( oldFont ); - + if ( expand ) { return box.bottom(); } else { @@ -494,8 +517,8 @@ int CalPrintPluginBase::drawHeader( TQPainter &p, TQString title, TQRect textRect( allbox ); textRect.addCoords( 5, 0, 0, 0 ); textRect.setRight( right ); - - + + TQFont oldFont( p.font() ); TQFont newFont("sans-serif", (textRect.height()<60)?16:18, TQFont::Bold); if ( expand ) { @@ -525,11 +548,24 @@ int CalPrintPluginBase::drawHeader( TQPainter &p, TQString title, p.setFont( newFont ); p.drawText( textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::WordBreak, title ); p.setFont( oldFont ); - + return textRect.bottom(); } +int CalPrintPluginBase::drawFooter( TQPainter &p, TQRect &footbox ) +{ + TQFont oldfont( p.font() ); + p.setFont( TQFont( "sans-serif", 6 ) ); + TQFontMetrics fm( p.font() ); + TQString dateStr = KGlobal::locale()->formatDateTime( TQDateTime::currentDateTime(), false ); + p.drawText( footbox, TQt::AlignCenter | TQt::AlignVCenter | TQt::SingleLine, + i18n( "print date: formatted-datetime", "printed: %1" ).arg( dateStr ) ); + p.setFont( oldfont ); + + return footbox.bottom(); +} + void CalPrintPluginBase::drawSmallMonth(TQPainter &p, const TQDate &qd, const TQRect &box ) { @@ -623,79 +659,78 @@ void CalPrintPluginBase::drawDaysOfWeekBox(TQPainter &p, const TQDate &qd, } -void CalPrintPluginBase::drawTimeLine(TQPainter &p, - const TQTime &fromTime, const TQTime &toTime, - const TQRect &box) +void CalPrintPluginBase::drawTimeLine( TQPainter &p, const TQTime &fromTime, + const TQTime &toTime, const TQRect &box ) { drawBox( p, BOX_BORDER_WIDTH, box ); - int totalsecs=fromTime.secsTo(toTime); - float minlen=(float)box.height()*60./(float)totalsecs; - float cellHeight=(60.*(float)minlen); - float currY=box.top(); + int totalsecs = fromTime.secsTo( toTime ); + float minlen = (float)box.height() * 60. / (float)totalsecs; + float cellHeight = ( 60. * (float)minlen ); + float currY = box.top(); // TODO: Don't use half of the width, but less, for the minutes! - int xcenter = box.left()+box.width()/2; + int xcenter = box.left() + box.width() / 2; TQTime curTime( fromTime ); TQTime endTime( toTime ); - if ( fromTime.minute() > 30 ) + if ( fromTime.minute() > 30 ) { curTime = TQTime( fromTime.hour()+1, 0, 0 ); - else if ( fromTime.minute() > 0 ) { + } else if ( fromTime.minute() > 0 ) { curTime = TQTime( fromTime.hour(), 30, 0 ); - float yy = currY + minlen*(float)fromTime.secsTo( curTime )/60.; + float yy = currY + minlen * (float)fromTime.secsTo( curTime ) / 60.; p.drawLine( xcenter, (int)yy, box.right(), (int)yy ); - curTime = TQTime( fromTime.hour()+1, 0, 0 ); + curTime = TQTime( fromTime.hour() + 1, 0, 0 ); } - currY += ( float( fromTime.secsTo(curTime)*minlen ) / 60. ); + currY += ( float( fromTime.secsTo( curTime ) * minlen ) / 60. ); while ( curTime < endTime ) { p.drawLine( box.left(), (int)currY, box.right(), (int)currY ); - int newY=(int)(currY+cellHeight/2.); + int newY = (int)( currY + cellHeight / 2. ); TQString numStr; if ( newY < box.bottom() ) { TQFont oldFont( p.font() ); // draw the time: if ( !KGlobal::locale()->use12Clock() ) { - p.drawLine( xcenter, (int)newY, box.right(), (int)newY); - numStr.setNum(curTime.hour()); - if (cellHeight > 30) { - p.setFont(TQFont("sans-serif", 16, TQFont::Bold)); + p.drawLine( xcenter, (int)newY, box.right(), (int)newY ); + numStr.setNum( curTime.hour() ); + if ( cellHeight > 30 ) { + p.setFont( TQFont( "sans-serif", 14, TQFont::Bold ) ); } else { - p.setFont(TQFont("sans-serif", 12, TQFont::Bold)); + p.setFont( TQFont( "sans-serif", 12, TQFont::Bold ) ); } - p.drawText( box.left()+2, (int)currY+2, box.width()/2-2, (int)cellHeight, - Qt::AlignTop | Qt::AlignRight, numStr); - p.setFont(TQFont("sans-serif", 10, TQFont::Normal)); - p.drawText( xcenter, (int)currY+2, box.width()/2+2, (int)(cellHeight/2)-3, - Qt::AlignTop | Qt::AlignLeft, "00"); + p.drawText( box.left() + 4, (int)currY + 2, box.width() / 2 - 2, (int)cellHeight, + Qt::AlignTop | Qt::AlignRight, numStr ); + p.setFont( TQFont ( "helvetica", 10, TQFont::Normal ) ); + p.drawText( xcenter + 4, (int)currY + 2, box.width() / 2 + 2, (int)(cellHeight / 2 ) - 3, + Qt::AlignTop | Qt::AlignLeft, "00" ); } else { - p.drawLine( box.left(), (int)newY, box.right(), (int)newY); + p.drawLine( box.left(), (int)newY, box.right(), (int)newY ); TQTime time( curTime.hour(), 0 ); numStr = KGlobal::locale()->formatTime( time ); if ( box.width() < 60 ) { - p.setFont(TQFont("sans-serif", 8, TQFont::Bold)); // for weekprint + p.setFont( TQFont( "sans-serif", 7, TQFont::Bold ) ); // for weekprint } else { - p.setFont(TQFont("sans-serif", 12, TQFont::Bold)); // for dayprint + p.setFont( TQFont( "sans-serif", 12, TQFont::Bold ) ); // for dayprint } - p.drawText(box.left()+2, (int)currY+2, box.width()-4, (int)cellHeight/2-3, - Qt::AlignTop|Qt::AlignLeft, numStr); + p.drawText( box.left() + 2, (int)currY + 2, box.width() - 4, (int)cellHeight / 2 - 3, + Qt::AlignTop|Qt::AlignLeft, numStr ); } - currY+=cellHeight; + currY += cellHeight; p.setFont( oldFont ); } // enough space for half-hour line and time - if (curTime.secsTo(endTime)>3600) - curTime=curTime.addSecs(3600); - else curTime=endTime; + if ( curTime.secsTo( endTime ) > 3600 ) { + curTime = curTime.addSecs( 3600 ); + } else { + curTime = endTime; + } } // currTime<endTime } - -/////////////////////////////////////////////////////////////////////////////// - -/** prints the all-day box for the agenda print view. if expandable is set, - height is the cell height of a single cell, and the returned height will - be the total height used for the all-day events. If !expandable, only one - cell will be used, and multiple events are concatenated using ", ". +/** + prints the all-day box for the agenda print view. if expandable is set, + height is the cell height of a single cell, and the returned height will + be the total height used for the all-day events. If !expandable, only one + cell will be used, and multiple events are concatenated using ", ". */ int CalPrintPluginBase::drawAllDayBox(TQPainter &p, Event::List &eventList, const TQDate &qd, bool expandable, const TQRect &box ) @@ -721,7 +756,7 @@ int CalPrintPluginBase::drawAllDayBox(TQPainter &p, Event::List &eventList, if ( expandable ) { TQRect eventBox( box ); eventBox.setTop( offset ); - showEventBox( p, eventBox, currEvent, currEvent->summary() ); + showEventBox( p, EVENT_BORDER_WIDTH, eventBox, currEvent, currEvent->summary() ); offset += box.height(); } else { if ( !multiDayStr.isEmpty() ) multiDayStr += ", "; @@ -867,7 +902,22 @@ void CalPrintPluginBase::drawAgendaItem( PrintCellItem *item, TQPainter &p, int currentHeight = int( box.top() + startPrintDate.secsTo( endTime ) * minlen / 60. ) - currentYPos; TQRect eventBox( currentX, currentYPos, currentWidth, currentHeight ); - showEventBox( p, eventBox, event, event->summary() ); + TQString str; + if ( event->location().isEmpty() ) { + str = i18n( "starttime - endtime summary", + "%1-%2 %3" ). + arg( KGlobal::locale()->formatTime( startTime.time() ) ). + arg( KGlobal::locale()->formatTime( endTime.time() ) ). + arg( cleanStr( event->summary() ) ); + } else { + str = i18n( "starttime - endtime summary, location", + "%1-%2 %3, %4" ). + arg( KGlobal::locale()->formatTime( startTime.time() ) ). + arg( KGlobal::locale()->formatTime( endTime.time() ) ). + arg( cleanStr( event->summary() ) ). + arg( cleanStr( event->location() ) ); + } + showEventBox( p, EVENT_BORDER_WIDTH, eventBox, event, str ); } } @@ -877,10 +927,8 @@ void CalPrintPluginBase::drawDayBox( TQPainter &p, const TQDate &qd, bool fullDate, bool printRecurDaily, bool printRecurWeekly ) { TQString dayNumStr; - TQString ampm; const KLocale*local = KGlobal::locale(); - // This has to be localized if ( fullDate && mCalSys ) { @@ -915,7 +963,7 @@ void CalPrintPluginBase::drawDayBox( TQPainter &p, const TQDate &qd, Event::List eventList = mCalendar->events( qd, EventSortStartDate, SortDirectionAscending ); - TQString text; + TQString timeText; p.setFont( TQFont( "sans-serif", 8 ) ); int textY=mSubHeaderHeight+3; // gives the relative y-coord of the next printed entry @@ -925,28 +973,60 @@ void CalPrintPluginBase::drawDayBox( TQPainter &p, const TQDate &qd, Event *currEvent = *it; if ( ( !printRecurDaily && currEvent->recurrenceType() == Recurrence::rDaily ) || ( !printRecurWeekly && currEvent->recurrenceType() == Recurrence::rWeekly ) ) { - continue; } - if ( currEvent->doesFloat() || currEvent->isMultiDay() ) - text = ""; - else - text = local->formatTime( currEvent->dtStart().time() ); + continue; + } + if ( currEvent->doesFloat() || currEvent->isMultiDay() ) { + timeText = ""; + } else { + timeText = local->formatTime( currEvent->dtStart().time() ); + } - drawIncidence( p, box, text, currEvent->summary(), textY ); + TQString str; + if ( !currEvent->location().isEmpty() ) { + str = i18n( "summary, location", "%1, %2" ). + arg( currEvent->summary() ).arg( currEvent->location() ); + } else { + str = currEvent->summary(); + } + drawIncidence( p, box, timeText, str, textY ); } - if ( textY<box.height() ) { + if ( textY < box.height() ) { Todo::List todos = mCalendar->todos( qd ); Todo::List::ConstIterator it2; - for( it2 = todos.begin(); it2 != todos.end() && textY<box.height(); ++it2 ) { + for ( it2 = todos.begin(); it2 != todos.end() && textY <box.height(); ++it2 ) { Todo *todo = *it2; if ( ( !printRecurDaily && todo->recurrenceType() == Recurrence::rDaily ) || - ( !printRecurWeekly && todo->recurrenceType() == Recurrence::rWeekly ) ) + ( !printRecurWeekly && todo->recurrenceType() == Recurrence::rWeekly ) ) { continue; - if ( todo->hasDueDate() && !todo->doesFloat() ) - text += KGlobal::locale()->formatTime(todo->dtDue().time()) + " "; - else - text = ""; - drawIncidence( p, box, text, i18n("To-do: %1").arg(todo->summary()), textY ); + } + if ( todo->hasStartDate() && !todo->doesFloat() ) { + timeText = KGlobal::locale()->formatTime( todo->dtStart().time() ) + " "; + } else { + timeText = ""; + } + TQString summaryStr; + if ( !todo->location().isEmpty() ) { + summaryStr = i18n( "summary, location", "%1, %2" ). + arg( todo->summary() ).arg( todo->location() ); + } else { + summaryStr = todo->summary(); + } + TQString str; + if ( todo->hasDueDate() ) { + if ( !todo->doesFloat() ) { + str = i18n( "%1 (Due: %2)" ). + arg( summaryStr ). + arg( KGlobal::locale()->formatDateTime( todo->dtDue() ) ); + } else { + str = i18n( "%1 (Due: %2)" ). + arg( summaryStr ). + arg( KGlobal::locale()->formatDate( todo->dtDue().date(), true ) ); + } + } else { + str = summaryStr; + } + drawIncidence( p, box, timeText, i18n("To-do: %1").arg( str ), textY ); } } @@ -1088,14 +1168,14 @@ void CalPrintPluginBase::drawMonth( TQPainter &p, const TQDate &dt, const TQRect int daysinmonth = calsys->daysInMonth( dt ); if ( maxdays <= 0 ) maxdays = daysinmonth; - + int d; float dayheight = float(daysBox.height()) / float( maxdays ); - + TQColor holidayColor( 240, 240, 240 ); TQColor workdayColor( 255, 255, 255 ); int dayNrWidth = p.fontMetrics().width( "99" ); - + // Fill the remaining space (if a month has less days than others) with a crossed-out pattern if ( daysinmonth<maxdays ) { TQRect dayBox( box.left(), daysBox.top() + round(dayheight*daysinmonth), box.width(), 0 ); @@ -1110,12 +1190,12 @@ void CalPrintPluginBase::drawMonth( TQPainter &p, const TQDate &dt, const TQRect TQRect dayBox( daysBox.left()/*+rand()%50*/, daysBox.top() + round(dayheight*d), daysBox.width()/*-rand()%50*/, 0 ); // FIXME: When using a border width of 0 for event boxes, don't let the rectangles overlap, i.e. subtract 1 from the top or bottom! dayBox.setBottom( daysBox.top()+round(dayheight*(d+1)) - 1 ); - + p.setBrush( isWorkingDay( day )?workdayColor:holidayColor ); p.drawRect( dayBox ); TQRect dateBox( dayBox ); dateBox.setWidth( dayNrWidth+3 ); - p.drawText( dateBox, Qt::AlignRight | Qt::AlignVCenter | Qt::SingleLine, + p.drawText( dateBox, Qt::AlignRight | Qt::AlignVCenter | Qt::SingleLine, TQString::number(d+1) ); } p.setBrush( oldbrush ); @@ -1154,16 +1234,16 @@ void CalPrintPluginBase::drawMonth( TQPainter &p, const TQDate &dt, const TQRect } } } - + TQValueList<MonthEventStruct> monthentries; - for ( Event::List::ConstIterator evit = events.begin(); + for ( Event::List::ConstIterator evit = events.begin(); evit != events.end(); ++evit ) { Event *e = (*evit); if (!e) continue; if ( e->doesRecur() ) { if ( e->recursOn( start ) ) { - // This occurrence has possibly started before the beginning of the + // This occurrence has possibly started before the beginning of the // month, so obtain the start date before the beginning of the month TQValueList<TQDateTime> starttimes = e->startDateTimesForDate( start ); TQValueList<TQDateTime>::ConstIterator it = starttimes.begin(); @@ -1171,8 +1251,8 @@ void CalPrintPluginBase::drawMonth( TQPainter &p, const TQDate &dt, const TQRect monthentries.append( MonthEventStruct( *it, e->endDateForStart( *it ), e ) ); } } - // Loop through all remaining days of the month and check if the event - // begins on that day (don't use Event::recursOn, as that will + // Loop through all remaining days of the month and check if the event + // begins on that day (don't use Event::recursOn, as that will // also return events that have started earlier. These start dates // however, have already been treated! Recurrence *recur = e->recurrence(); @@ -1216,7 +1296,7 @@ void CalPrintPluginBase::drawMonth( TQPainter &p, const TQDate &dt, const TQRect timeboxItems.append( new PrintCellItem( (*mit).event, thisstart, thisend ) ); } } - + // For Multi-day events, line them up nicely so that the boxes don't overlap TQPtrListIterator<KOrg::CellItem> it1( timeboxItems ); for( it1.toFirst(); it1.current(); ++it1 ) { @@ -1225,7 +1305,7 @@ void CalPrintPluginBase::drawMonth( TQPainter &p, const TQDate &dt, const TQRect } TQDateTime starttime( start, TQTime( 0, 0, 0 ) ); int newxstartcont = xstartcont; - + TQFont oldfont( p.font() ); p.setFont( TQFont( "sans-serif", 7 ) ); for( it1.toFirst(); it1.current(); ++it1 ) { @@ -1233,11 +1313,11 @@ void CalPrintPluginBase::drawMonth( TQPainter &p, const TQDate &dt, const TQRect int minsToStart = starttime.secsTo( placeItem->start() )/60; int minsToEnd = starttime.secsTo( placeItem->end() )/60; - TQRect eventBox( xstartcont + placeItem->subCell()*17, - daysBox.top() + round( double( minsToStart*daysBox.height()) / double(maxdays*24*60) ), + TQRect eventBox( xstartcont + placeItem->subCell()*17, + daysBox.top() + round( double( minsToStart*daysBox.height()) / double(maxdays*24*60) ), 14, 0 ); eventBox.setBottom( daysBox.top() + round( double( minsToEnd*daysBox.height()) / double(maxdays*24*60) ) ); - drawVerticalBox( p, eventBox, placeItem->event()->summary() ); + drawVerticalBox( p, 0, eventBox, placeItem->event()->summary() ); newxstartcont = QMAX( newxstartcont, eventBox.right() ); } xstartcont = newxstartcont; diff --git a/korganizer/printing/calprintpluginbase.h b/korganizer/printing/calprintpluginbase.h index 16a3374d2..b845b379e 100644 --- a/korganizer/printing/calprintpluginbase.h +++ b/korganizer/printing/calprintpluginbase.h @@ -48,6 +48,8 @@ using namespace KCal; #define PORTRAIT_HEADER_HEIGHT 72 // header height, for portrait orientation #define LANDSCAPE_HEADER_HEIGHT 54 // header height, for landscape orientation #define SUBHEADER_HEIGHT 20 // subheader height, for all orientations +#define PORTRAIT_FOOTER_HEIGHT 16 // footer height, for portrait orientation +#define LANDSCAPE_FOOTER_HEIGHT 14 // footer height, for landscape orientation #define MARGIN_SIZE 36 // margins, for all orientations #define PADDING_SIZE 7 // padding between the various top-level boxes #define BOX_BORDER_WIDTH 2 // width of the border of all top-level boxes @@ -115,7 +117,7 @@ class KDE_EXPORT CalPrintPluginBase : public KOrg::PrintPlugin void setKOrgCoreHelper( KOrg::CoreHelper*helper ); bool useColors() const; void setUseColors( bool useColors ); - + /** Helper functions to hide the KOrg::CoreHelper */ TQColor categoryBgColor( Incidence *incidence ); TQColor textColor( const TQColor &color ); @@ -123,7 +125,7 @@ class KDE_EXPORT CalPrintPluginBase : public KOrg::PrintPlugin bool isWorkingDay( const TQDate &dt ); TQString holidayString( const TQDate &dt ); Event *holiday( const TQDate &dt ); - + /** Determines the column of the given weekday ( 1=Monday, 7=Sunday ), taking the start of the week setting into account as given in kcontrol. @@ -135,7 +137,7 @@ class KDE_EXPORT CalPrintPluginBase : public KOrg::PrintPlugin KPrinter::Orientation orientation() const; /** Returns the height of the page header. If the height was explicitly - set using setHeaderHeight, that value is returned, otherwise a + set using setHeaderHeight, that value is returned, otherwise a default value based on the printer orientation. \return height of the page header of the printout */ @@ -145,12 +147,20 @@ class KDE_EXPORT CalPrintPluginBase : public KOrg::PrintPlugin int subHeaderHeight() const; void setSubHeaderHeight( const int height ); + /** Returns the height of the page footer. If the height was explicitly + set using setFooterHeight, that value is returned, otherwise a + default value based on the printer orientation. + \return height of the page footer of the printout + */ + int footerHeight() const; + void setFooterHeight( const int height ); + int margin() const; void setMargin( const int margin ); - + int padding() const; void setPadding( const int margin ); - + int borderWidth() const; void setBorderWidth( const int border ); @@ -161,7 +171,7 @@ class KDE_EXPORT CalPrintPluginBase : public KOrg::PrintPlugin /***************************************************************** ** PRINTING HELPER FUNCTIONS ** *****************************************************************/ - public: + public: /** Draw a box with given width at the given coordinates. \param p The printer to be used @@ -177,44 +187,51 @@ class KDE_EXPORT CalPrintPluginBase : public KOrg::PrintPlugin \param rect The rectangle of the box */ static void drawShadedBox( TQPainter &p, int linewidth, const TQBrush &brush, const TQRect &rect ); - + /** Print the given string (event summary) in the given rectangle. Margins and justification (centered or not) are automatically adjusted. \param p TQPainter of the printout \param box Coordinates of the surrounding event box \param str The text to be printed in the box + \param flags is a bitwise OR of TQt::AlignmentFlags and TQt::TextFlags values. */ void printEventString( TQPainter &p, const TQRect &box, const TQString &str, int flags = -1 ); /** Print the box for the given event with the given string. \param p QPainer of the printout + \param linewidth is the width of the line used to draw the box, ignored if less than 1. \param box Coordinates of the event's box \param incidence The incidence (if available), from which the category color will be deduced, if applicable. \param str The string to print inside the box + \param flags is a bitwise OR of TQt::AlignmentFlags and TQt::TextFlags values. */ - void showEventBox( TQPainter &p, const TQRect &box, Incidence *incidence, const TQString &str, int flags = -1 ); - - /** + void showEventBox( TQPainter &p, int linewidth, const TQRect &box, Incidence *incidence, + const TQString &str, int flags = -1 ); + + /** Draw a subheader box with a shaded background and the given string \param p TQPainter of the printout \param str Text to be printed inside the box \param box Coordinates of the box */ void drawSubHeaderBox(TQPainter &p, const TQString &str, const TQRect &box ); - + /** Draw an event box with vertical text. \param p TQPainter of the printout + \param linewidth is the width of the line used to draw the box, ignored if less than 1. \param box Coordinates of the box \param str ext to be printed inside the box + \param flags is a bitwise OR of TQt::AlignmentFlags and TQt::TextFlags values. */ - void drawVerticalBox( TQPainter &p, const TQRect &box, const TQString &str ); - + void drawVerticalBox( TQPainter &p, int linewidth, const TQRect &box, const TQString &str, + int flags=-1 ); + /** - Draw a component box with a heading (printed in bold). + Draw a component box with a heading (printed in bold). \param p TQPainter of the printout \param box Coordinates of the box \param caption Caption string to be printed inside the box @@ -222,7 +239,7 @@ class KDE_EXPORT CalPrintPluginBase : public KOrg::PrintPlugin then no text will be printed, only the caption. \param sameLine Whether the contents should start on the same line as the caption (the space below the caption text will be - used as indentation in the subsequent lines) or on the + used as indentation in the subsequent lines) or on the next line (no indentation of the contents) \param expand Whether to expand the box vertically to fit the whole text in it. @@ -234,7 +251,7 @@ class KDE_EXPORT CalPrintPluginBase : public KOrg::PrintPlugin custom contents in that case. */ int drawBoxWithCaption( TQPainter &p, const TQRect &box, const TQString &caption, - const TQString &contents, + const TQString &contents, bool sameLine, bool expand, const TQFont &captionFont, const TQFont &textFont ); /** @@ -260,13 +277,23 @@ class KDE_EXPORT CalPrintPluginBase : public KOrg::PrintPlugin \param box coordinates of the title bar \param expand Whether to expand the box vertically to fit the whole title in it. - \return The bottom of the printed box. If expand==false, this + \return The bottom of the printed box. If expand==false, this is box.bottom, otherwise it is larger than box.bottom and matches the y-coordinate of the surrounding rectangle. */ int drawHeader( TQPainter &p, TQString title, const TQDate &month1, const TQDate &month2, const TQRect &box, bool expand = false ); + + /** + Draw a page footer containing the printing date and possibly + other things, like a page number. + \param p TQPainter of the printout + \param box coordinates of the footer + \return The bottom of the printed box. + */ + int drawFooter( TQPainter &p, TQRect &box ); + /** Draw a small calendar with the days of a month into the given area. Used for example in the title bar of the sheet. @@ -309,7 +336,7 @@ class KDE_EXPORT CalPrintPluginBase : public KOrg::PrintPlugin void drawTimeLine( TQPainter &p, const TQTime &fromTime, const TQTime &toTime, const TQRect &box ); - + /** Draw the all-day box for the agenda print view (the box on top which doesn't have a time on the time scale associated). If expandable is set, @@ -359,7 +386,7 @@ class KDE_EXPORT CalPrintPluginBase : public KOrg::PrintPlugin const TQDateTime &startPrintDate, const TQDateTime &endPrintDate, float minlen, const TQRect &box ); - + /** Draw the box containing a list of all events of the given day (with their times, of course). Used in the Filofax and the month print style. @@ -429,8 +456,8 @@ class KDE_EXPORT CalPrintPluginBase : public KOrg::PrintPlugin \param dt Arbitrary date within the month to be printed \param box coordinates of the box reserved for the month \param maxdays Days to print. If a value of -1 is given, the number of days - is deduced from the month. If maxdays is larger than the - number of days in the month, the remaining boxes are + is deduced from the month. If maxdays is larger than the + number of days in the month, the remaining boxes are shaded to indicate they are not days of the month. \param subDailyFlags Bitfield consisting of DisplayFlags flags to determine how events that do not cross midnight should be printed. @@ -501,6 +528,7 @@ class KDE_EXPORT CalPrintPluginBase : public KOrg::PrintPlugin bool mUseColors; int mHeaderHeight; int mSubHeaderHeight; + int mFooterHeight; int mMargin; int mPadding; int mBorder; diff --git a/korganizer/publishdialog.cpp b/korganizer/publishdialog.cpp index ac684069f..68d5c6307 100644 --- a/korganizer/publishdialog.cpp +++ b/korganizer/publishdialog.cpp @@ -160,9 +160,8 @@ void PublishDialog::updateInput() if (!item) return; mWidget->mNameLineEdit->setEnabled( true ); mWidget->mEmailLineEdit->setEnabled( true ); - TQString mail = item->text( 1 ); mWidget->mNameLineEdit->setText( item->text( 0 ) ); - mWidget->mEmailLineEdit->setText( mail ); + mWidget->mEmailLineEdit->setText( item->text( 1 ) ); } #include "publishdialog.moc" diff --git a/korganizer/resourceview.cpp b/korganizer/resourceview.cpp index d4a76f73e..150aa0143 100644 --- a/korganizer/resourceview.cpp +++ b/korganizer/resourceview.cpp @@ -24,7 +24,10 @@ */ #include "resourceview.h" +#include "koviewmanager.h" +#include "multiagendaview.h" +#include <dcopref.h> #include <kcolordialog.h> #include <kdialog.h> #include <klistview.h> @@ -37,6 +40,7 @@ #include <kresources/resource.h> #include <kresources/configdialog.h> #include <libkcal/calendarresources.h> +#include <kconfig.h> #include <tqhbox.h> #include <tqheader.h> @@ -45,6 +49,7 @@ #include <tqpainter.h> #include <tqpushbutton.h> #include <tqpopupmenu.h> +#include <tqregexp.h> #include <tqtooltip.h> #include <tqwhatsthis.h> @@ -52,20 +57,53 @@ using namespace KCal; -ResourceViewFactory::ResourceViewFactory( KCal::CalendarResources *calendar, - CalendarView *view ) - : mCalendar( calendar ), mView( view ), mResourceView( 0 ) +static TQString labelFromSubResName( ResourceCalendar *resource, const TQString &subRes ) +{ + + DCOPRef ref( "kmail", "KMailICalIface" ); + DCOPReply reply = ref.call( "dimapAccounts" ); + if ( !reply.isValid() ) { + kdDebug() << "DCOP Call dimapAccounts() failed " << endl; + return TQString(); + } + + TQString label; + if ( (int)reply > 1 ) { + if( resource && !resource->resourceName().isEmpty() ) { + label = i18n( "My %1 (%2)" ).arg( subRes, resource->resourceName() ); + } else { + label = i18n( "My %1" ).arg( subRes ); + } + } else { + label = i18n( "My %1" ).arg( subRes ); + } + return label; +} + +static TQString labelFromIdentifier( ResourceCalendar *resource, const TQString &identifier ) +{ + TQString subResLabel; + if ( identifier.contains( "/.INBOX.directory/" ) ) { // my subresource + TQString subResName = identifier; + subResName.remove( TQRegExp( "^.*/\\.INBOX\\.directory/" ) ); + subResLabel = labelFromSubResName( resource, subResName ); + } + return subResLabel; +} + +ResourceViewFactory::ResourceViewFactory( CalendarResources *calendar, CalendarView *view ) + : mCalendar( calendar ), mCalendarView( view ), mResourceView( 0 ) { } CalendarViewExtension *ResourceViewFactory::create( TQWidget *parent ) { - mResourceView = new ResourceView( mCalendar, parent ); + mResourceView = new ResourceView( mCalendar, mCalendarView, parent ); TQObject::connect( mResourceView, TQT_SIGNAL( resourcesChanged() ), - mView, TQT_SLOT( resourcesChanged() ) ); + mCalendarView, TQT_SLOT( resourcesChanged() ) ); TQObject::connect( mResourceView, TQT_SIGNAL( resourcesChanged() ), - mView, TQT_SLOT( updateCategories() ) ); + mCalendarView, TQT_SLOT( updateCategories() ) ); TQObject::connect( mCalendar, TQT_SIGNAL( signalResourceAdded( ResourceCalendar * ) ), @@ -76,9 +114,9 @@ CalendarViewExtension *ResourceViewFactory::create( TQWidget *parent ) mResourceView, TQT_SLOT( updateResourceItem( ResourceCalendar * ) ) ); TQObject::connect( mCalendar, TQT_SIGNAL( signalResourceAdded( ResourceCalendar * ) ), - mView, TQT_SLOT( updateCategories() ) ); + mCalendarView, TQT_SLOT( updateCategories() ) ); TQObject::connect( mCalendar, TQT_SIGNAL( signalResourceModified( ResourceCalendar * ) ), - mView, TQT_SLOT( updateCategories() ) ); + mCalendarView, TQT_SLOT( updateCategories() ) ); return mResourceView; } @@ -91,7 +129,7 @@ ResourceView *ResourceViewFactory::resourceView() const ResourceItem::ResourceItem( ResourceCalendar *resource, ResourceView *view, KListView *parent ) : TQCheckListItem( parent, resource->resourceName(), CheckBox ), - mResource( resource ), mView( view ), mBlockStateChange( false ), + mResource( resource ), mResourceView( view ), mBlockStateChange( false ), mIsSubresource( false ), mResourceIdentifier( TQString::null ), mSubItemsCreated( false ), mIsStandardResource( false ) { @@ -112,8 +150,11 @@ void ResourceItem::createSubresourceItems() // This resource has subresources TQStringList::ConstIterator it; for ( it=subresources.begin(); it!=subresources.end(); ++it ) { - ResourceItem *item = new ResourceItem( mResource, *it, mResource->labelForSubresource( *it ), - mView, this ); + TQString text = labelFromIdentifier( mResource, *it ); + if ( text.isEmpty() ) { + text = mResource->labelForSubresource( *it ); + } + ResourceItem *item = new ResourceItem( mResource, *it, text, mResourceView, this ); TQColor resourceColor = *KOPrefs::instance()->resourceColor( *it ); item->setResourceColor( resourceColor ); item->update(); @@ -122,16 +163,14 @@ void ResourceItem::createSubresourceItems() mSubItemsCreated = true; } -ResourceItem::ResourceItem( KCal::ResourceCalendar *resource, - const TQString& sub, const TQString& label, - ResourceView *view, ResourceItem* parent ) - +ResourceItem::ResourceItem( ResourceCalendar *resource, const TQString &identifier, + const TQString &label, ResourceView *view, ResourceItem *parent ) : TQCheckListItem( parent, label, CheckBox ), mResource( resource ), - mView( view ), mBlockStateChange( false ), mIsSubresource( true ), + mResourceView( view ), mBlockStateChange( false ), mIsSubresource( true ), mSubItemsCreated( false ), mIsStandardResource( false ) { mResourceColor = TQColor(); - mResourceIdentifier = sub; + mResourceIdentifier = identifier; setGuiState(); } @@ -159,10 +198,12 @@ void ResourceItem::stateChange( bool active ) createSubresourceItems(); } } else { - // mView->requestClose must be called before mResource->save() because + // mResourceView->requestClose must be called before mResource->save() because // save causes closeResource do be called. - mView->requestClose( mResource ); - if ( mResource->save() ) mResource->setActive( false ); + mResourceView->requestClose( mResource ); + if ( mResource->save() ) { + mResource->setActive( false ); + } } setOpen( mResource->isActive() && childCount() > 0 ); @@ -170,7 +211,7 @@ void ResourceItem::stateChange( bool active ) setGuiState(); } - mView->emitResourcesChanged(); + mResourceView->emitResourcesChanged(); } void ResourceItem::update() @@ -216,9 +257,9 @@ void ResourceItem::paintCell(TQPainter *p, const TQColorGroup &cg, } -ResourceView::ResourceView( KCal::CalendarResources *calendar, - TQWidget *parent, const char *name ) - : CalendarViewExtension( parent, name ), mCalendar( calendar ) +ResourceView::ResourceView( CalendarResources *calendar, + CalendarView *view, TQWidget *parent, const char *name ) + : CalendarViewExtension( parent, name ), mCalendar( calendar ), mCalendarView( view ) { TQBoxLayout *topLayout = new TQVBoxLayout( this, 0, KDialog::spacingHint() ); @@ -305,9 +346,9 @@ void ResourceView::updateView() { mListView->clear(); - KCal::CalendarResourceManager *manager = mCalendar->resourceManager(); + CalendarResourceManager *manager = mCalendar->resourceManager(); - KCal::CalendarResourceManager::Iterator it; + CalendarResourceManager::Iterator it; for( it = manager->begin(); it != manager->end(); ++it ) { addResourceItem( *it ); } @@ -322,44 +363,47 @@ void ResourceView::emitResourcesChanged() void ResourceView::addResource() { bool ok = false; - KCal::CalendarResourceManager *manager = mCalendar->resourceManager(); - ResourceItem *i = static_cast<ResourceItem*>( mListView->selectedItem() ); - if ( i && ( i->isSubresource() || i->resource()->canHaveSubresources() ) ) { - const TQString folderName = KInputDialog::getText( i18n( "Add Subresource" ), - i18n( "Please enter a name for the new subresource" ), TQString::null, - &ok, this ); + CalendarResourceManager *manager = mCalendar->resourceManager(); + ResourceItem *item = static_cast<ResourceItem*>( mListView->selectedItem() ); + if ( item && ( item->isSubresource() || item->resource()->canHaveSubresources() ) ) { + const TQString folderName = + KInputDialog::getText( i18n( "Add Subresource" ), + i18n( "Please enter a name for the new subresource" ), TQString::null, + &ok, this ); if ( !ok ) return; - const TQString parentId = i->isSubresource() ? i->resourceIdentifier() : TQString:: null; - if ( !i->resource()->addSubresource( folderName, parentId ) ) { - KMessageBox::error( this, i18n("<qt>Unable to create subresource <b>%1</b>.</qt>") - .arg( folderName ) ); + const TQString parentId = item->isSubresource() ? item->resourceIdentifier() : TQString:: null; + if ( !item->resource()->addSubresource( folderName, parentId ) ) { + KMessageBox::error( + this, + i18n( "<qt>Unable to create subresource <b>%1</b>.</qt>" ).arg( folderName ) ); } return; } TQStringList types = manager->resourceTypeNames(); TQStringList descs = manager->resourceTypeDescriptions(); - TQString desc = KInputDialog::getItem( i18n( "Resource Configuration" ), - i18n( "Please select type of the new resource:" ), descs, 0, false, &ok, - this ); - if ( !ok ) + TQString desc = + KInputDialog::getItem( i18n( "Resource Configuration" ), + i18n( "Please select type of the new resource:" ), + descs, 0, false, &ok, this ); + if ( !ok ) { return; + } TQString type = types[ descs.findIndex( desc ) ]; // Create new resource ResourceCalendar *resource = manager->createResource( type ); if( !resource ) { - KMessageBox::error( this, i18n("<qt>Unable to create resource of type <b>%1</b>.</qt>") - .arg( type ) ); + KMessageBox::error( + this, + i18n( "<qt>Unable to create resource of type <b>%1</b>.</qt>" ).arg( type ) ); return; } - resource->setResourceName( i18n("%1 resource").arg( type ) ); - - KRES::ConfigDialog *dlg = new KRES::ConfigDialog( this, TQString("calendar"), resource, - "KRES::ConfigDialog" ); + KRES::ConfigDialog *dlg = + new KRES::ConfigDialog( this, TQString( "calendar" ), resource, "KRES::ConfigDialog" ); bool success = true; if ( !dlg || !dlg->exec() ) @@ -370,8 +414,7 @@ void ResourceView::addResource() if ( resource->isActive() && ( !resource->open() || !resource->load() ) ) { // ### There is a resourceLoadError() signal declared in ResourceCalendar // but no subclass seems to make use of it. We could do better. - KMessageBox::error( this, i18n("Unable to create the resource.") - .arg( type ) ); + KMessageBox::error( this, i18n("Unable to create the resource.").arg( type ) ); success = false; } } @@ -396,7 +439,7 @@ void ResourceView::addResource() void ResourceView::addResourceItem( ResourceCalendar *resource ) { - ResourceItem *item=new ResourceItem( resource, this, mListView ); + ResourceItem *item = new ResourceItem( resource, this, mListView ); // assign a color, but only if this is a resource that actually // hold items at top level @@ -427,38 +470,47 @@ void ResourceView::addResourceItem( ResourceCalendar *resource ) } // Add a new entry -void ResourceView::slotSubresourceAdded( ResourceCalendar *calendar, - const TQString& /*type*/, - const TQString& resource, - const TQString& label) +void ResourceView::slotSubresourceAdded( ResourceCalendar *resource, + const TQString &type, + const TQString &identifier, + const TQString &label ) { - TQListViewItem *i = mListView->findItem( calendar->resourceName(), 0 ); - if ( !i ) + Q_UNUSED( type ); + + TQListViewItem *lvitem = mListView->findItem( resource->resourceName(), 0 ); + if ( !lvitem ) // Not found return; - if ( findItemByIdentifier( resource ) ) return; + if ( findItemByIdentifier( identifier ) ) return; - ResourceItem *item = static_cast<ResourceItem *>( i ); - ResourceItem *newItem = new ResourceItem( calendar, resource, label, this, item ); - TQColor resourceColor = *KOPrefs::instance()->resourceColor( resource ); + TQString text = labelFromIdentifier( resource, identifier ); + if ( text.isEmpty() ) { + text = label; + } + ResourceItem *item = static_cast<ResourceItem *>( lvitem ); + ResourceItem *newItem = new ResourceItem( resource, identifier, text, this, item ); + TQColor resourceColor = *KOPrefs::instance()->resourceColor( identifier ); newItem->setResourceColor( resourceColor ); } // Remove an entry -void ResourceView::slotSubresourceRemoved( ResourceCalendar * /*calendar*/, - const TQString &/*type*/, - const TQString &resource ) +void ResourceView::slotSubresourceRemoved( ResourceCalendar *resource, + const TQString &type, + const TQString &identifier ) { - delete findItemByIdentifier( resource ); + Q_UNUSED( resource ); + Q_UNUSED( type ); + + delete findItemByIdentifier( identifier ); emit resourcesChanged(); } -void ResourceView::closeResource( ResourceCalendar *r ) +void ResourceView::closeResource( ResourceCalendar *resource ) { - if ( mResourcesToClose.find( r ) >= 0 ) { - r->close(); - mResourcesToClose.remove( r ); + if ( mResourcesToClose.find( resource ) >= 0 ) { + resource->close(); + mResourcesToClose.remove( resource ); } } @@ -482,31 +534,46 @@ void ResourceView::removeResource() ResourceItem *item = currentItem(); if ( !item ) return; - const TQString warningMsg = item->isSubresource() ? - i18n("<qt>Do you really want to remove the subresource <b>%1</b>? " - "Note that its contents will be completely deleted. This " - "operation cannot be undone. </qt>").arg( item->text( 0 ) ) : - i18n("<qt>Do you really want to remove the resource <b>%1</b>?</qt>").arg( item->text( 0 ) ); - - int km = KMessageBox::warningContinueCancel( this, warningMsg, "", - KGuiItem( i18n("&Remove" ), "editdelete") ); - if ( km == KMessageBox::Cancel ) return; - -// Don't be so restricitve -#if 0 - if ( item->resource() == mCalendar->resourceManager()->standardResource() ) { - KMessageBox::sorry( this, - i18n( "You cannot delete your standard resource." ) ); + // Do not allow a non-subresource folder to be removed if it is the standard resource. + if ( !item->isSubresource() ) { + if ( item->resource() == mCalendar->resourceManager()->standardResource() ) { + KMessageBox::sorry( + this, + i18n( "<qt>You may not delete your standard calendar resource.<p>" + "You can change the standard calendar resource in the " + "KDE Control Center using the KDE Resource settings under the " + "KDE Components area.</qt>" ) ); + return; + } + } + + TQString moreInfo; + if ( item->resource()->type() == "imap" || item->resource()->type() == "scalix" ) { + moreInfo = i18n( "This is a groupware folder so you can always re-subscribe to the folder " + "later as you desire." ); + } else { + moreInfo = i18n( "The contents will not be removed so you can always re-add this calendar " + "later as you desire." ); + } + + int km = + KMessageBox::warningContinueCancel( + this, + i18n( "<qt>Do you really want to remove the calendar <b>%1</b>?<p><b>Note:</b> %2</qt>" ). + arg( item->text( 0 ), moreInfo ), + "", KGuiItem( i18n( "&Remove" ) ) ); + if ( km == KMessageBox::Cancel ) { return; } -#endif + if ( item->isSubresource() ) { if ( !item->resource()->removeSubresource( item->resourceIdentifier() ) ) - KMessageBox::sorry( this, - i18n ("<qt>Failed to remove the subresource <b>%1</b>. The " - "reason could be that it is a built-in one which cannot " - "be removed, or that the removal of the underlying storage " - "folder failed.</qt>").arg( item->resource()->name() ) ); + KMessageBox::sorry( + this, + i18n ("<qt>Failed to remove the subresource <b>%1</b>. The " + "reason could be that it is a built-in one which cannot " + "be removed, or that the removal of the underlying storage " + "folder failed.</qt>").arg( item->resource()->name() ) ); return; } else { mCalendar->resourceManager()->remove( item->resource() ); @@ -520,62 +587,103 @@ void ResourceView::removeResource() void ResourceView::editResource() { + bool ok = false; ResourceItem *item = currentItem(); if (!item) return; ResourceCalendar *resource = item->resource(); - KRES::ConfigDialog dlg( this, TQString("calendar"), resource, - "KRES::ConfigDialog" ); + if ( item->isSubresource() ) { + if ( resource->type() == "imap" || resource->type() == "scalix" ) { + TQString identifier = item->resourceIdentifier(); + if ( !identifier.contains( "/.INBOX.directory/" ) ) { + KMessageBox::sorry( + this, + i18n( "Cannot rename someone else's calendar folder." ) ); + return; + } + + TQString oldSubResourceName = identifier; + oldSubResourceName.remove( TQRegExp( "^.*/\\.INBOX\\.directory/" ) ); + TQString newSubResourceName = + KInputDialog::getText( + i18n( "Rename Subresource" ), + i18n( "<qt>Enter a new name for the subresource<p>" + "<b>Note:</b> the new name will take affect after the next sync.</qt>" ), + oldSubResourceName, &ok, this ); + if ( !ok ) { + return; + } - if ( dlg.exec() ) { - item->setText( 0, resource->resourceName() ); + DCOPRef ref( "kmail", "KMailICalIface" ); + DCOPReply reply = ref.call( "changeResourceUIName", identifier, newSubResourceName ); + if ( !reply.isValid() ) { + KMessageBox::sorry( + this, + i18n( "Communication with KMail failed when attempting to change the folder name." ) ); + return; + } + + item->setText( 0, labelFromSubResName( resource, newSubResourceName ) ); + + KOrg::BaseView *cV = mCalendarView->viewManager()->currentView(); + if ( cV && cV == mCalendarView->viewManager()->multiAgendaView() ) { + mCalendarView->viewManager()->multiAgendaView()->deSelectAgendaView(); + } + } else { + KMessageBox::sorry( + this, + i18n ("<qt>Cannot edit the subresource <b>%1</b>.</qt>").arg( item->resource()->name() ) ); + } + } else { + KRES::ConfigDialog dlg( this, TQString("calendar"), resource, "KRES::ConfigDialog" ); - mCalendar->resourceManager()->change( resource ); + if ( dlg.exec() ) { + item->setText( 0, resource->resourceName() ); + mCalendar->resourceManager()->change( resource ); + } } emitResourcesChanged(); } -void ResourceView::currentChanged( TQListViewItem *item ) +void ResourceView::currentChanged( TQListViewItem *lvitem ) { - ResourceItem *i = currentItem(); - if ( !item || i->isSubresource() ) { - mDeleteButton->setEnabled( false ); - mEditButton->setEnabled( false ); - } else { - mDeleteButton->setEnabled( true ); - mEditButton->setEnabled( true ); - } + ResourceItem *item = currentItem(); + if ( !lvitem || item->isSubresource() ) { + mDeleteButton->setEnabled( false ); + mEditButton->setEnabled( false ); + } else { + mDeleteButton->setEnabled( true ); + mEditButton->setEnabled( true ); + } } -ResourceItem *ResourceView::findItem( ResourceCalendar *r ) +ResourceItem *ResourceView::findItem( ResourceCalendar *resource ) { - TQListViewItem *item; - ResourceItem *i = 0; - for( item = mListView->firstChild(); item; item = item->nextSibling() ) { - i = static_cast<ResourceItem *>( item ); - if ( i->resource() == r ) break; + TQListViewItem *lvitem; + ResourceItem *item = 0; + for( lvitem = mListView->firstChild(); lvitem; lvitem = lvitem->nextSibling() ) { + item = static_cast<ResourceItem *>( lvitem ); + if ( item->resource() == resource ) break; } - return i; + return item; } -ResourceItem *ResourceView::findItemByIdentifier( const TQString& id ) +ResourceItem *ResourceView::findItemByIdentifier( const TQString &identifier ) { - TQListViewItem *item; - ResourceItem *i = 0; - for( item = mListView->firstChild(); item; item = item->itemBelow() ) { - i = static_cast<ResourceItem *>( item ); - if ( i->resourceIdentifier() == id ) - return i; + TQListViewItem *lvitem; + ResourceItem *item = 0; + for ( lvitem = mListView->firstChild(); lvitem; lvitem = lvitem->itemBelow() ) { + item = static_cast<ResourceItem *>( lvitem ); + if ( item->resourceIdentifier() == identifier ) + return item; } return 0; } - -void ResourceView::contextMenuRequested ( TQListViewItem *i, - const TQPoint &pos, int ) +void ResourceView::contextMenuRequested ( TQListViewItem *lvitem, const TQPoint &pos, int ) { - KCal::CalendarResourceManager *manager = mCalendar->resourceManager(); - ResourceItem *item = static_cast<ResourceItem *>( i ); + CalendarResourceManager *manager = mCalendar->resourceManager(); + ResourceItem *item = static_cast<ResourceItem *>( lvitem ); TQPopupMenu *menu = new TQPopupMenu( this ); connect( menu, TQT_SIGNAL( aboutToHide() ), menu, TQT_SLOT( deleteLater() ) ); @@ -598,7 +706,14 @@ void ResourceView::contextMenuRequested ( TQListViewItem *i, menu->insertItem( i18n( "Resources Colors" ), assignMenu ); } - menu->insertItem( i18n("&Edit..."), this, TQT_SLOT( editResource() ) ); + if ( item->isSubresource() && + ( item->resource()->type() == "imap" || item->resource()->type() == "scalix" ) ) { + if ( item->resourceIdentifier().contains( "/.INBOX.directory/" ) ) { + menu->insertItem( i18n("&Rename..."), this, TQT_SLOT( editResource() ) ); + } + } else { + menu->insertItem( i18n("&Edit..."), this, TQT_SLOT( editResource() ) ); + } menu->insertItem( i18n("&Remove"), this, TQT_SLOT( removeResource() ) ); if ( item->resource() != manager->standardResource() ) { menu->insertSeparator(); @@ -620,7 +735,7 @@ void ResourceView::assignColor() return; // A color without initialized is a color invalid TQColor myColor; - KCal::ResourceCalendar *cal = item->resource(); + ResourceCalendar *cal = item->resource(); TQString identifier = cal->identifier(); if ( item->isSubresource() ) @@ -641,13 +756,16 @@ void ResourceView::assignColor() void ResourceView::disableColor() { ResourceItem *item = currentItem(); - if ( !item ) + if ( !item ) { return; + } + TQColor colorInvalid; - KCal::ResourceCalendar *cal = item->resource(); + ResourceCalendar *cal = item->resource(); TQString identifier = cal->identifier(); - if ( item->isSubresource() ) + if ( item->isSubresource() ) { identifier = item->resourceIdentifier(); + } KOPrefs::instance()->setResourceColor( identifier, colorInvalid ); item->setResourceColor( colorInvalid ); item->update(); @@ -658,7 +776,12 @@ void ResourceView::showInfo() ResourceItem *item = currentItem(); if ( !item ) return; - TQString txt = "<qt>" + item->resource()->infoText() + "</qt>"; + TQString identifier; + if ( item->isSubresource() ) { + identifier = "<p>" + item->resourceIdentifier(); + } + + TQString txt = "<qt>" + item->resource()->infoText() + identifier + "</qt>"; KMessageBox::information( this, txt ); } @@ -667,8 +790,8 @@ void ResourceView::reloadResource() ResourceItem *item = currentItem(); if ( !item ) return; - ResourceCalendar *r = item->resource(); - r->load(); + ResourceCalendar *resource = item->resource(); + resource->load(); } void ResourceView::saveResource() @@ -676,8 +799,8 @@ void ResourceView::saveResource() ResourceItem *item = currentItem(); if ( !item ) return; - ResourceCalendar *r = item->resource(); - r->save(); + ResourceCalendar *resource = item->resource(); + resource->save(); } void ResourceView::setStandard() @@ -685,9 +808,9 @@ void ResourceView::setStandard() ResourceItem *item = currentItem(); if ( !item ) return; - ResourceCalendar *r = item->resource(); - KCal::CalendarResourceManager *manager = mCalendar->resourceManager(); - manager->setStandardResource( r ); + ResourceCalendar *resource = item->resource(); + CalendarResourceManager *manager = mCalendar->resourceManager(); + manager->setStandardResource( resource ); updateResourceList(); } diff --git a/korganizer/resourceview.h b/korganizer/resourceview.h index f34d0cf22..ee4060272 100644 --- a/korganizer/resourceview.h +++ b/korganizer/resourceview.h @@ -27,11 +27,11 @@ #include "calendarview.h" -#include <libkcal/resourcecalendar.h> #include <tqlistview.h> namespace KCal { -class CalendarResources; + class CalendarResources; + class ResourceCalendar; } using namespace KCal; class KListView; @@ -41,16 +41,15 @@ class TQPushButton; class ResourceViewFactory : public CalendarViewExtension::Factory { public: - ResourceViewFactory( KCal::CalendarResources *calendar, - CalendarView *view ); + ResourceViewFactory( CalendarResources *calendar, CalendarView *view ); CalendarViewExtension *create( TQWidget * ); ResourceView *resourceView() const; private: - KCal::CalendarResources *mCalendar; - CalendarView *mView; + CalendarResources *mCalendar; + CalendarView *mCalendarView; ResourceView *mResourceView; }; @@ -58,18 +57,15 @@ class ResourceViewFactory : public CalendarViewExtension::Factory class ResourceItem : public QCheckListItem { public: - ResourceItem( KCal::ResourceCalendar *resource, ResourceView *view, - KListView *parent ); - ResourceItem( KCal::ResourceCalendar *resource, const TQString& sub, - const TQString& label, ResourceView *view, - ResourceItem* parent ); + ResourceItem( ResourceCalendar *resource, ResourceView *view, KListView *parent ); + ResourceItem( ResourceCalendar *resource, const TQString &identifier, + const TQString &label, ResourceView *view, ResourceItem *parent ); - KCal::ResourceCalendar *resource() { return mResource; } + ResourceCalendar *resource() { return mResource; } const TQString& resourceIdentifier() { return mResourceIdentifier; } bool isSubresource() const { return mIsSubresource; } void createSubresourceItems(); void setStandardResource( bool std ); - void update(); virtual void paintCell(TQPainter *p, const TQColorGroup &cg, @@ -77,15 +73,15 @@ class ResourceItem : public QCheckListItem void setResourceColor(TQColor& color); TQColor &resourceColor() {return mResourceColor;} + protected: void stateChange( bool active ); - void setGuiState(); TQColor mResourceColor; private: - KCal::ResourceCalendar *mResource; - ResourceView *mView; + ResourceCalendar *mResource; + ResourceView *mResourceView; bool mBlockStateChange; bool mIsSubresource; TQString mResourceIdentifier; @@ -100,45 +96,45 @@ class ResourceView : public CalendarViewExtension { Q_OBJECT public: - ResourceView( KCal::CalendarResources *calendar, TQWidget *parent = 0, - const char *name = 0 ); + ResourceView( CalendarResources *calendar, CalendarView *view, + TQWidget *parent = 0, const char *name = 0 ); ~ResourceView(); - KCal::CalendarResources *calendar() const { return mCalendar; } + CalendarResources *calendar() const { return mCalendar; } void updateView(); void emitResourcesChanged(); - void requestClose( ResourceCalendar * ); + void requestClose( ResourceCalendar *resource ); void showButtons( bool visible ); public slots: - void addResourceItem( ResourceCalendar * ); - void updateResourceItem( ResourceCalendar * ); + void addResourceItem( ResourceCalendar *resource ); + void updateResourceItem( ResourceCalendar *resource ); signals: void resourcesChanged(); protected: - ResourceItem *findItem( ResourceCalendar * ); - ResourceItem *findItemByIdentifier( const TQString& id ); + ResourceItem *findItem( ResourceCalendar *resource ); + ResourceItem *findItemByIdentifier( const TQString &identifier ); ResourceItem *currentItem(); protected slots: void addResource(); void removeResource(); void editResource(); - void currentChanged( TQListViewItem* ); - void slotSubresourceAdded( ResourceCalendar *, const TQString &, - const TQString &resource,const TQString& label ); + void currentChanged( TQListViewItem *lvitem ); + void slotSubresourceAdded( ResourceCalendar *resource, const TQString &type, + const TQString &identifier, const TQString &label ); - void slotSubresourceRemoved( ResourceCalendar *, const TQString &, - const TQString & ); - void closeResource( ResourceCalendar * ); + void slotSubresourceRemoved( ResourceCalendar *resource, const TQString &type, + const TQString &identifier ); + void closeResource( ResourceCalendar *resource ); - void contextMenuRequested ( TQListViewItem *i, const TQPoint &pos, int ); + void contextMenuRequested ( TQListViewItem *lvitem, const TQPoint &pos, int ); void assignColor(); void disableColor(); @@ -152,7 +148,8 @@ class ResourceView : public CalendarViewExtension private: KListView *mListView; - KCal::CalendarResources *mCalendar; + CalendarResources *mCalendar; + CalendarView *mCalendarView; TQPushButton *mAddButton; TQPushButton *mDeleteButton; TQPushButton *mEditButton; diff --git a/korganizer/searchdialog.cpp b/korganizer/searchdialog.cpp index 487296a6d..2cc4bb442 100644 --- a/korganizer/searchdialog.cpp +++ b/korganizer/searchdialog.cpp @@ -120,12 +120,12 @@ SearchDialog::SearchDialog(Calendar *calendar,TQWidget *parent) connect( this,TQT_SIGNAL(user1Clicked()),TQT_SLOT(doSearch())); // Propagate edit and delete event signals from event list view - connect( listView, TQT_SIGNAL( showIncidenceSignal( Incidence * ) ), - TQT_SIGNAL( showIncidenceSignal( Incidence *) ) ); - connect( listView, TQT_SIGNAL( editIncidenceSignal( Incidence * ) ), - TQT_SIGNAL( editIncidenceSignal( Incidence * ) ) ); - connect( listView, TQT_SIGNAL( deleteIncidenceSignal( Incidence * ) ), - TQT_SIGNAL( deleteIncidenceSignal( Incidence * ) ) ); + connect( listView, TQT_SIGNAL(showIncidenceSignal(Incidence *,const TQDate &)), + TQT_SIGNAL(showIncidenceSignal(Incidence *,const TQDate &)) ); + connect( listView, TQT_SIGNAL(editIncidenceSignal(Incidence *,const TQDate &)), + TQT_SIGNAL(editIncidenceSignal(Incidence *,const TQDate &)) ); + connect( listView, TQT_SIGNAL(deleteIncidenceSignal(Incidence *)), + TQT_SIGNAL(deleteIncidenceSignal(Incidence *)) ); } SearchDialog::~SearchDialog() @@ -155,7 +155,7 @@ void SearchDialog::doSearch() search( re ); - listView->showIncidences( mMatchedEvents ); + listView->showIncidences( mMatchedEvents, TQDate() ); if ( mMatchedEvents.count() == 0 ) { KMessageBox::information( this, @@ -176,7 +176,7 @@ void SearchDialog::updateView() mMatchedEvents.clear(); } - listView->showIncidences( mMatchedEvents ); + listView->showIncidences( mMatchedEvents, TQDate() ); } void SearchDialog::search( const TQRegExp &re ) diff --git a/korganizer/searchdialog.h b/korganizer/searchdialog.h index cd535bd10..53195bc13 100644 --- a/korganizer/searchdialog.h +++ b/korganizer/searchdialog.h @@ -60,9 +60,9 @@ class SearchDialog : public KDialogBase void searchTextChanged( const TQString &_text ); signals: - void showIncidenceSignal(Incidence *); - void editIncidenceSignal(Incidence *); - void deleteIncidenceSignal(Incidence *); + void showIncidenceSignal( Incidence *, const TQDate & ); + void editIncidenceSignal( Incidence *, const TQDate & ); + void deleteIncidenceSignal( Incidence * ); private: void search(const TQRegExp &); diff --git a/korganizer/timelabels.cpp b/korganizer/timelabels.cpp index 0c4956bd4..81b53c1f6 100644 --- a/korganizer/timelabels.cpp +++ b/korganizer/timelabels.cpp @@ -47,6 +47,7 @@ TimeLabels::TimeLabels(int rows,TQWidget *parent,const char *name,WFlags f) : { mRows = rows; mMiniWidth = 0; + mAgenda = 0; mCellHeight = KOPrefs::instance()->mHourSize*4; @@ -204,16 +205,19 @@ void TimeLabels::updateConfig() // If the agenda is zoomed out so that more then 24 would be shown, // the agenda only shows 24 hours, so we need to take the cell height // from the agenda, which is larger than the configured one! - if ( mCellHeight < 4*mAgenda->gridSpacingY() ) + if ( mAgenda && mCellHeight < 4*mAgenda->gridSpacingY() ) { mCellHeight = 4*mAgenda->gridSpacingY(); + } resizeContents( mMiniWidth, int(mRows * mCellHeight+1) ); } /** update time label positions */ void TimeLabels::positionChanged() { - int adjustment = mAgenda->contentsY(); - setContentsPos(0, adjustment); + if ( mAgenda ) { + int adjustment = mAgenda->contentsY(); + setContentsPos( 0, adjustment ); + } } void TimeLabels::positionChanged( int pos ) @@ -222,7 +226,7 @@ void TimeLabels::positionChanged( int pos ) } /** */ -void TimeLabels::setAgenda(KOAgenda* agenda) +void TimeLabels::setAgenda( KOAgenda* agenda ) { mAgenda = agenda; diff --git a/korganizer/timelineitem.cpp b/korganizer/timelineitem.cpp index 7240e06d0..6ebff843f 100644 --- a/korganizer/timelineitem.cpp +++ b/korganizer/timelineitem.cpp @@ -31,8 +31,8 @@ using namespace KOrg; using namespace KCal; -TimelineItem::TimelineItem( const TQString &label, KDGanttView * parent) : - KDGanttViewTaskItem( parent ) +TimelineItem::TimelineItem( const TQString &label, KCal::Calendar *calendar, KDGanttView * parent) : + KDGanttViewTaskItem( parent ), mCalendar( calendar ) { setListViewText( 0, label ); setDisplaySubitemsAsGroup( true ); @@ -56,7 +56,7 @@ void TimelineItem::insertIncidence(KCal::Incidence * incidence, const TQDateTime if ( (*it)->startTime() == start && (*it)->endTime() == end ) return; - TimelineSubItem * item = new TimelineSubItem( incidence, this ); + TimelineSubItem * item = new TimelineSubItem( mCalendar, incidence, this ); TQColor c1, c2, c3; colors( c1, c2, c3 ); item->setColors( c1, c2, c3 ); @@ -91,14 +91,16 @@ void TimelineItem::moveItems(KCal::Incidence * incidence, int delta, int duratio } -TimelineSubItem::TimelineSubItem(KCal::Incidence * incidence, TimelineItem * parent) : +TimelineSubItem::TimelineSubItem( KCal::Calendar *calendar, + KCal::Incidence *incidence, TimelineItem *parent) : KDGanttViewTaskItem( parent ), mIncidence( incidence ), mLeft( 0 ), mRight( 0 ), mMarkerWidth( 0 ) { - setTooltipText( IncidenceFormatter::toolTipString( incidence ) ); + setTooltipText( IncidenceFormatter::toolTipStr( calendar, incidence, + originalStart().date(), true ) ); if ( !incidence->isReadOnly() ) { setMoveable( true ); setResizeable( true ); diff --git a/korganizer/timelineitem.h b/korganizer/timelineitem.h index 2ff3b2e06..a3406f115 100644 --- a/korganizer/timelineitem.h +++ b/korganizer/timelineitem.h @@ -42,7 +42,7 @@ class TimelineSubItem; class TimelineItem : public KDGanttViewTaskItem { public: - TimelineItem( const TQString &label, KDGanttView* parent ); + TimelineItem( const TQString &label, KCal::Calendar *calendar, KDGanttView* parent ); void insertIncidence( KCal::Incidence *incidence, const TQDateTime &start = TQDateTime(), @@ -52,13 +52,14 @@ class TimelineItem : public KDGanttViewTaskItem void moveItems( KCal::Incidence* incidence, int delta, int duration ); private: + KCal::Calendar *mCalendar; TQMap<KCal::Incidence*, TQValueList<TimelineSubItem*> > mItemMap; }; class TimelineSubItem : public KDGanttViewTaskItem { public: - TimelineSubItem( KCal::Incidence *incidence, TimelineItem *parent ); + TimelineSubItem( KCal::Calendar *calendar, KCal::Incidence *incidence, TimelineItem *parent ); ~TimelineSubItem(); KCal::Incidence* incidence() const { return mIncidence; } diff --git a/korganizer/tips b/korganizer/tips index 50430aadc..31bf9fcb0 100644 --- a/korganizer/tips +++ b/korganizer/tips @@ -43,7 +43,7 @@ <tip category="KOrganizer|General"> <html> -<p>...that you can import birthdays from your address book? There is a resource available which connects the birthdays to your calendar; it is even possible to set a reminder for each event. +<p>...that your calender can display birthdays from your address book? It is even possible to set up reminders for them. To activate this, add the corresponding 'birthdays' resource to your calender. </p> </html> </tip> diff --git a/korganizer/urihandler.cpp b/korganizer/urihandler.cpp index 4b7c7bdff..0c406318e 100644 --- a/korganizer/urihandler.cpp +++ b/korganizer/urihandler.cpp @@ -24,23 +24,58 @@ #include "urihandler.h" +#include <libkcal/attachment.h> +#include <libkcal/attachmenthandler.h> +#include <libkcal/calendarresources.h> +#include <libkcal/incidence.h> +using namespace KCal; + #ifndef KORG_NODCOP #include <dcopclient.h> #include "kmailIface_stub.h" #endif -#include <kiconloader.h> -#include <krun.h> #include <kapplication.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <kmimetype.h> #include <kprocess.h> +#include <krun.h> +#include <ktempfile.h> #include <kdebug.h> +#include <kio/netaccess.h> + +#include <tqfile.h> + +TQString UriHandler::attachmentNameFromUri( const TQString &uri ) +{ + TQString tmp; + if ( uri.startsWith( "ATTACH:" ) ) { + tmp = uri.mid( 9 ).section( ':', -1, -1 ); + } + return tmp; +} + +TQString UriHandler::uidFromUri( const TQString &uri ) +{ + TQString tmp; + if ( uri.startsWith( "ATTACH:" ) ) { + tmp = uri.mid( 9 ).section( ':', 0, 0 ); + } else if ( uri.startsWith( "uid:" ) ) { + tmp = uri.mid( 6 ); + } + return tmp; +} -bool UriHandler::process( const TQString &uri ) +bool UriHandler::process( TQWidget *parent, const TQString &uri ) { kdDebug(5850) << "UriHandler::process(): " << uri << endl; #ifndef KORG_NODCOP if ( uri.startsWith( "kmail:" ) ) { + // make sure kmail is running or the part is shown kapp->startServiceByDesktopPath("kmail"); @@ -53,10 +88,15 @@ bool UriHandler::process( const TQString &uri ) KMailIface_stub kmailIface( "kmail", "KMailIface" ); kmailIface.showMail( serialNumberStr.toUInt(), TQString() ); return true; + } else if ( uri.startsWith( "mailto:" ) ) { + KApplication::kApplication()->invokeMailer( uri.mid(7), TQString::null ); return true; + } else if ( uri.startsWith( "uid:" ) ) { + + TQString uid = uidFromUri( uri ); DCOPClient *client = KApplication::kApplication()->dcopClient(); const TQByteArray noParamData; const TQByteArray paramData; @@ -66,27 +106,31 @@ bool UriHandler::process( const TQString &uri ) "interfaces()", noParamData, replyTypeStr, replyData ); if ( foundAbbrowser ) { - //KAddressbook is already running, so just DCOP to it to bring up the contact editor + // KAddressbook is already running, so just DCOP to it to bring up the contact editor #if KDE_IS_VERSION( 3, 2, 90 ) kapp->updateRemoteUserTimestamp("kaddressbook"); #endif DCOPRef kaddressbook( "kaddressbook", "KAddressBookIface" ); - kaddressbook.send( "showContactEditor", uri.mid( 6 ) ); + kaddressbook.send( "showContactEditor", uid ); return true; } else { - /* - KaddressBook is not already running. Pass it the UID of the contact via the command line while starting it - its neater. - We start it without its main interface - */ + // KaddressBook is not already running. + // Pass it the UID of the contact via the command line while starting it - its neater. + // We start it without its main interface TQString iconPath = KGlobal::iconLoader()->iconPath( "go", KIcon::Small ); TQString tmpStr = "kaddressbook --editor-only --uid "; - tmpStr += KProcess::quote( uri.mid( 6 ) ); + tmpStr += KProcess::quote( uid ); KRun::runCommand( tmpStr, "KAddressBook", iconPath ); return true; } - } - else { // no special URI, let KDE handle it - new KRun(KURL( uri )); + + } else if ( uri.startsWith( "ATTACH:" ) ) { + + // a calendar incidence attachment + return AttachmentHandler::view( parent, attachmentNameFromUri( uri ), uidFromUri( uri ) ); + + } else { // no special URI, let KDE handle it + new KRun( KURL( uri ) ); } #endif diff --git a/korganizer/urihandler.h b/korganizer/urihandler.h index 915b28578..1dc9264ca 100644 --- a/korganizer/urihandler.h +++ b/korganizer/urihandler.h @@ -24,16 +24,21 @@ #ifndef URIHANDLER_H #define URIHANDLER_H -#include <tqstring.h> #include <kdepimmacros.h> +class TQString; +class TQWidget; + class KDE_EXPORT UriHandler { public: /** Process URI. Return true if handler handled the URI, otherwise false. */ - static bool process( const TQString &uri ); + static bool process( TQWidget *parent, const TQString &uri ); + + static TQString attachmentNameFromUri( const TQString &uri ); + static TQString uidFromUri( const TQString &uri ); }; #endif diff --git a/korganizer/version.h b/korganizer/version.h index 63a1b3a59..a25f926f2 100644 --- a/korganizer/version.h +++ b/korganizer/version.h @@ -53,6 +53,6 @@ 3.2 alpha1 */ -static const char korgVersion[] = "3.5.9"; +static const char korgVersion[] = "3.5.9 (enterprise35 0.20100827.1168748)"; #endif |