📄 datebook.cpp
字号:
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS. All rights reserved.**** This file is part of the Qtopia Environment.** ** 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.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** 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.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#define QTOPIA_INTERNAL_FD#define QTOPIA_INTERNAL_FILEOPERATIONS#include "datebook.h"#include "dayview.h"#include "datebooksettings.h"#include "datebookweek.h"#include "entrydialog.h"#include "monthview.h"#include "finddialog.h"#include "exceptiondialog.h"#include "eventpicker.h"#include "alarmdialog.h"#include "eventview.h"#ifdef QTOPIA_DESKTOP#include <common/action.h>#endif#include <qtopia/vscrollview.h>#include <qtopia/qpeapplication.h>#include <qtopia/global.h>#include <qtopia/config.h>#include <qtopia/qpedebug.h>#include <qtopia/pim/event.h>#include <qtopia/stringutil.h>#ifdef Q_WS_QWS#include <qtopia/ir.h>#endif#include <qtopia/qpemenubar.h>#include <qtopia/qpemessagebox.h>#include <qtopia/resource.h>#include <qtopia/sound.h>#include <qtopia/timestring.h>#include <qtopia/qpetoolbar.h>#include <qtopia/tzselect.h>#include <qtopia/xmlreader.h>#include <qtopia/applnk.h>#include <qtopia/pim/private/eventio_p.h>#include <qtopia/pim/private/eventxmlio_p.h>#ifdef Q_WS_QWS#include <qtopia/qcopenvelope_qws.h>#endif#ifdef QTOPIA_DATA_LINKING#include <qtopia/qdl.h>#endif#ifdef QTOPIA_PHONE#include <qtopia/contextbar.h>#endif#ifdef QTOPIA_DESKTOP#include <qtopia/categoryselect.h>#endif#include <qtopia/datetimeedit.h>#include <qaction.h>#include <qtimer.h>#include <qdatetime.h>#include <qdialog.h>#include <qdir.h>#include <qfile.h>#include <qlabel.h>#include <qlayout.h>#include <qmessagebox.h>#include <qpopupmenu.h>#include <qpushbutton.h>#include <qtextcodec.h>#include <qtextstream.h>#include <qtl.h>#include <qwidgetstack.h>#include <qvbox.h>#include <qregexp.h>//#ifdef QWS////#include <qwindowsystem_qws.h>////#include <qcopchannel_qws.h>////#endif#include <qarray.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>#ifndef Q_OS_WIN32#include <unistd.h>#endif#include <stdlib.h>#define DAY 1#define WEEK 2#define MONTH 3#define EVENT 4#if !defined(QTOPIA_DESKTOP)DateBook::DateBook( QWidget *parent, const char *, WFlags f ) : DateBookGui( parent, "datebook", f ), aPreset( FALSE ), presetTime( -1 ), startTime( 8 ), // an acceptable default compressDay( TRUE ), syncing(FALSE), inSearch(FALSE), exceptionMb(0){ init();}#elseDateBook::DateBook() : DateBookGui(), aPreset( FALSE ), presetTime( -1 ), startTime( 8 ), // an acceptable default compressDay( TRUE ), syncing(FALSE), inSearch(FALSE), exceptionMb(0){}#endifvoid DateBook::init(){ int timingLoad, timingOther;#ifdef QTOPIA_DESKTOP Q_UNUSED(timingOther)#endif dayView = 0; weekView = 0; monthView = 0; eventView = 0;#ifdef Q_WS_QWS beamfile = Global::tempDir() + "obex"; QDir d; d.mkdir(beamfile); beamfile += "/event.vcs";#endif QTime t; t.start(); db = new DateBookTable(this); timingLoad = t.elapsed(); loadSettings(); DateBookGui::init();#if !defined(QTOPIA_DESKTOP) views = new QWidgetStack( parentWidget ); setCentralWidget( views ); timingOther = t.elapsed(); viewToday(); TimeString::connectChange(this, SLOT(changeClock()) ); connect( qApp, SIGNAL(weekChanged(bool)), this, SLOT(changeWeek(bool)) ); connect( qApp, SIGNAL( appMessage(const QCString&,const QByteArray&) ), this, SLOT( appMessage(const QCString&,const QByteArray&) ) ); connect( qApp, SIGNAL( timeChanged() ), this, SLOT( checkToday() ) ); connect( qApp, SIGNAL( timeChanged() ), this, SLOT( updateAlarms() ) ); connect( qApp, SIGNAL( flush() ), this, SLOT( flush() ) ); connect( qApp, SIGNAL( reload() ), this, SLOT( reload() ) ); // start Timer midnightTimer = new QTimer(this); connect(midnightTimer, SIGNAL(timeout()), this, SLOT(checkToday())); // 2 seconds after midnight midnightTimer->start( (QTime::currentTime().secsTo(QTime(23,59,59)) + 3) * 1000 );#endif // QTOPIA_DESKTOP}void DateBook::checkToday(){ if ( lastToday != QDate::currentDate() ) { if ( lastToday == currentDate() ) slotToday(); else lastToday = QDate::currentDate(); } else { refreshWidgets(); } midnightTimer->start( (QTime::currentTime().secsTo(QTime(23,59,59)) + 3) * 1000 );}void DateBook::updateAlarms(){ /* time may have gone backwards... but giving the same alarms again won't hurt (server will ignore) so send them all again, */ // no real way to tell if forward or backward, so need to do the lot. db->updateAlarms();}void DateBook::refreshWidgets(){ // update active view! if ( actionDay->isOn() ) dayView->redraw();#if !defined(QTOPIA_PHONE) else if ( actionWeek->isOn() ) weekView->redraw();#endif else if ( actionMonth->isOn() ) monthView->updateOccurrences();}DateBook::~DateBook(){}void DateBook::showSettings(){#if !defined(QTOPIA_DESKTOP) bool whichclock; Config config( "qpe" ); config.setGroup("Time"); whichclock = config.readBoolEntry("AMPM"); DateBookSettings frmSettings(whichclock, parentWidget, "settings"); frmSettings.setStartTime( startTime ); frmSettings.setAlarmPreset( aPreset, presetTime ); frmSettings.setCompressDay( compressDay ); if ( QPEApplication::execDialog(&frmSettings) ) { aPreset = frmSettings.alarmPreset(); presetTime = frmSettings.presetTime(); startTime = frmSettings.startTime(); compressDay = frmSettings.compressDay(); if ( dayView ) { dayView->setDayStarts( startTime ); dayView->setCompressDay( compressDay ); }#if !defined(QTOPIA_PHONE) if ( weekView ) weekView->setDayStarts( startTime );#endif saveSettings(); // make the change obvious if ( views->visibleWidget() ) { if ( views->visibleWidget() == dayView ) dayView->redraw();#if !defined(QTOPIA_PHONE) else if ( views->visibleWidget() == weekView ) weekView->redraw();#endif } }#endif}void DateBook::fileNew(){ newEvent("");}QString DateBook::checkEvent(const PimEvent &e){ /* check if overlaps with itself */ bool checkFailed = FALSE; /* check the next 12 repeats. should catch most problems */ QDate current_date = e.end().date(); int duration = e.start().date().daysTo(e.end().date()); PimEvent previous = e; for(int i = 0; i < 12; i++) { bool ok; QDateTime next; next = e.nextOccurrence(current_date.addDays(1), &ok); next.setTime(e.start().time()); if (!ok) break; // no more repeats if(next < previous.end()) { checkFailed = TRUE; break; } current_date = next.date().addDays(duration); } if(checkFailed) return tr("<qt>Event duration is potentially longer " "than interval between repeats.</qt>"); return QString::null;}QDate DateBook::currentDate(){ if ( dayView && views->visibleWidget() == dayView ) { return dayView->currentDate();#if !defined(QTOPIA_PHONE) } else if ( weekView && views->visibleWidget() == weekView ) { return weekView->currentDate();#endif } else if ( monthView && views->visibleWidget() == monthView ) { return monthView->selectedDate(); } else { return QDate(); // invalid; }}void DateBook::viewToday(){ lastToday = QDate::currentDate(); viewDay( lastToday );}void DateBook::viewDay(const QDate& dt){ initDay(); actionDay->setOn( TRUE ); dayView->selectDate( dt ); raiseWidget( dayView ); dayView->setFocus(); dayView->redraw(); updateIcons();}void DateBook::viewDay(){ viewDay( currentDate() );}void DateBook::viewWeek(){ viewWeek( currentDate() );}void DateBook::viewWeek( const QDate& dt ){ initWeek(); actionWeek->setOn( TRUE ); weekView->selectDate( dt ); raiseWidget( weekView ); weekView->redraw(); updateIcons();}void DateBook::viewMonth(){ viewMonth( currentDate() );}void DateBook::viewMonth( const QDate& dt){ initMonth(); actionMonth->setOn( TRUE ); monthView->setDate( dt ); raiseWidget( monthView ); monthView->updateOccurrences(); updateIcons();}void DateBook::updateIcons(){ bool view = (eventView && views->visibleWidget() == eventView);#ifdef QTOPIA_DESKTOP bool s = eventSelected(); actionDelete->setEnabled( s ); actionEdit->setEnabled( s );#else if ( view ) { if ( sub_bar ) sub_bar->hide(); if ( details_bar ) details_bar->show(); } else { if ( details_bar ) details_bar->hide(); if ( sub_bar ) sub_bar->show(); } actionNew->setEnabled( !view ); actionEdit->setEnabled( view ); actionDelete->setEnabled( view );#ifdef Q_WS_QWS if (Ir::supported()) actionBeam->setEnabled( view );#endif actionToday->setEnabled( !view ); actionDay->setEnabled( !view ); actionMonth->setEnabled( !view ); actionSettings->setEnabled( !view );#ifndef QTOPIA_PHONE actionBack->setEnabled( view ); actionWeek->setEnabled( !view );#endif#endif#ifdef QTOPIA_PHONE if ( eventSelected() ) // dayView definitely exists ContextBar::setLabel( dayView, Qt::Key_Select, ContextBar::View ); else if ( dayView ) // make sure it does in this case ContextBar::setLabel( dayView, Qt::Key_Select, ContextBar::NoLabel ); if ( !view ) { if ( views->visibleWidget() == monthView ) actionMonth->setEnabled( FALSE ); else actionMonth->setEnabled( TRUE ); }#endif}void DateBook::initExceptionMb() { exceptionMb = new ExceptionDialog( parentWidget, "exceptionDlg", TRUE );}// a bit to extreme.// should be possible to check each exception for if it still fits// on a valid date.bool affectsExceptions(const PimEvent &ne, const PimEvent &oe){ if (oe.hasExceptions()) { if (ne.start() != oe.start()) return TRUE; if (ne.frequency() != oe.frequency()) return TRUE; if (ne.repeatType() != oe.repeatType()) return TRUE; if ( ((PrEvent &)ne).p_weekMask() != ((PrEvent &)oe).p_weekMask()) return TRUE; } return FALSE;}bool DateBook::checkSyncing(){ if (syncing) { if ( QMessageBox::warning(parentWidget, tr("Calendar"), tr("<qt>Can not edit data, currently syncing</qt>"), QMessageBox::Ok, QMessageBox::Abort ) == QMessageBox::Abort ) { // Okay, if you say so (eg. Qtopia Desktop may have crashed).... syncing = FALSE; } else return TRUE; } return FALSE;}void DateBook::editOccurrence( const Occurrence &ev ){ editOccurrence( ev, FALSE );}void DateBook::editOccurrence( const Occurrence &ev, bool preview ){#if !defined(QTOPIA_DESKTOP) if ( checkSyncing() ) return;#endif // if this event is an exception, or has exceptions we may need to do somethign different. bool asException; PimEvent e; // stuff for "following" events bool following = FALSE; PimEvent orig; QValueList<QDate> pastExceptions; QValueList<QDate> futureExceptions; QValueList<QUuid> pastChildren; QValueList<QUuid> futureChildren; if (ev.event().hasRepeat()) { // ask if just this one or is series? if (!exceptionMb) initExceptionMb(); exceptionMb->setCaption( tr("Edit Event") ); switch (exceptionMb->exec()) { default: return; case ExceptionDialog::Current: e = ev.event(); // modify e to be an exceptional event. // with no uid (yet). e.setSeriesUid(ev.event().uid()); e.setRepeatType(PimEvent::NoRepeat); e.setStart(ev.start()); e.clearExceptions(); asException = TRUE; break; case ExceptionDialog::All: e = ev.event(); asException = FALSE; break; case ExceptionDialog::Following: // If we select Following but we're looking at the first instance, // just do the same as All. if ( ev.date() == e.start().date() ) { e = ev.event(); asException = FALSE; break; } e = ev.event(); orig = ev.event(); // modify e to be a new series with no uid (yet). e.setSeriesUid(QUuid()); e.setStart(ev.start()); asException = TRUE; following = TRUE; pastExceptions = ((PrEvent&)e).exceptions(); futureExceptions = ((PrEvent&)e).exceptions(); futureChildren = ((PrEvent&)e).childUids(); pastChildren = ((PrEvent&)e).childUids(); QValueList<QDate> processedDates; // we can only remove everything // put it back in while processing the lists e.clearExceptions(); QValueListIterator<QUuid> uiter; QValueListIterator<QDate> diter; // disassociate all children that are in the "past" for ( uiter = futureChildren.begin(); uiter != futureChildren.end(); ) { QUuid u = *uiter; PimEvent child = db->find( u ); QDate dateOfChild = child.start().date(); if ( dateOfChild < ev.date() ) { uiter = futureChildren.remove( uiter ); } else { uiter++; pastChildren.remove( u ); e.addException( dateOfChild, u ); processedDates.append( dateOfChild ); } } // remove all exceptions from the "past" for ( diter = futureExceptions.begin(); diter != futureExceptions.end(); ) { QDate d = *diter; if ( d < ev.date() ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -