📄 dayview.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.************************************************************************/#include "dayview.h"#include "dayviewheaderimpl.h"#include "layoutmanager.h"#include "datebookdb.h"#ifdef Q_WS_QWS#include <qtopia/ir.h>#endif#include <qtopia/resource.h>#include <qtopia/qpeapplication.h>#include <qtopia/timestring.h>#include <qtopia/qpedebug.h>#include <qheader.h>#include <qdatetime.h>#include <qpainter.h>#include <qsimplerichtext.h>#include <qpopupmenu.h>#include <qtextcodec.h>#include <qpalette.h>#include <qabstractlayout.h>#include <qlayout.h>#include <qregexp.h>#include <qstyle.h>#include <qtimer.h>#include <qlist.h>#include <qtl.h>static const int short_time_height = 20;static int day_height = 18;static const int day_time_margin = 2;inline QRect expandRect(QRect r){ QRect nr(r.x() - 1, r.y() - 1, r.width() + 1, r.height() + 1); return nr;}// ====================================================================class DayItem : public LayoutItem{ friend class DayViewContents;public: DayItem(const QDate &referenceDate, const Occurrence &ev); ~DayItem(); void setFocus(bool b); void drawItem( QPainter *p, int x, int y, const QColorGroup &cg ); void setCompressed();private: void loadPMs(); QPixmap pm_repeat, pm_alarmbell, pm_repeatE; QString strDesc; QString headingText; QString noteTZ; QDateTime noteStart; QDateTime noteEnd; bool noteShowStartDate; bool noteShowEndDate; QString noteStr; bool hasFocus; bool compressed;};// ====================================================================class DayViewLayout : public LayoutManager{public: DayViewLayout(int w, int h); void clear(); DayItem *focusedItem() const; void setFocusedItem(DayItem *i); virtual DayItem *firstItem(); virtual DayItem *nextItem(); virtual DayItem *previousItem(); virtual DayItem *lastItem(); void addOccurrence(Occurrence &e, const QDate &cDate ); virtual void setTimeHeight( int th );protected: DayItem *fItem; int time_height;};// ====================================================================class AllDayLayout : public DayViewLayout{public: AllDayLayout(int w, int h); void layoutItems(bool = FALSE);};// ====================================================================class CompressedDayLayout : public DayViewLayout{public: CompressedDayLayout( int w, int h, const int &sod ); void clear(); void eventsChanged(); int timeToHeight( const QTime &time ) const; void setSize( int w, int h ); void setTimeHeight( int th ); TimeList times; private: const int &start_of_day;};// ====================================================================DayItem::DayItem(const QDate &referenceDate, const Occurrence &ev) : LayoutItem(ev) , hasFocus(FALSE), compressed( FALSE ){ // why would someone use "<"? Oh well, fix it up... // I wonder what other things may be messed up... strDesc = ev.event().description(); int where = strDesc.find( "<" ); while ( where != -1 ) { strDesc.remove( where, 1 ); strDesc.insert( where, "<" ); where = strDesc.find( "<", where ); } QString strCat; // ### Fix later... // QString strCat = ev.category(); // where = strCat.find( "<" ); // while ( where != -1 ) { // strCat.remove( where, 1 ); // strCat.insert( where, "<" ); // where = strCat.find( "<", where ); // } QString strNote = ev.event().notes(); where = strNote.find( "<" ); while ( where != -1 ) { strNote.remove( where, 1 ); strNote.insert( where, "<" ); where = strNote.find( "<", where ); } headingText = "<b>" + strDesc + "</b><br>"; if (ev.event().timeZone().isValid()) { noteTZ=ev.event().timeZone().id(); // ########### translate with new TZ class, not this mess int i = noteTZ.find('/'); noteTZ = noteTZ.mid( i + 1 ); noteTZ = noteTZ.replace(QRegExp("_"), " "); } noteStart = ev.event().start(); noteEnd = ev.event().end(); noteShowStartDate = referenceDate != ev.date(); noteShowEndDate = referenceDate != ev.endDate(); noteStr = strNote; //setBackgroundMode( PaletteBase );}DayItem::~DayItem(){}void DayItem::setFocus(bool b){ hasFocus = b;}void DayItem::drawItem( QPainter *p, int x, int y, const QColorGroup &cg ){ p->save(); QRect r = expandRect(geometry()); x += r.x(); y += r.y(); int w = r.width(); int h = r.height(); p->setBrush(event().color().light(175)); if (hasFocus) { p->setPen( QPen(QColor(0,0,0)) ); p->drawRect( x, y, w, h ); p->drawRect( x + 1, y + 1, w - 2, h - 2 ); } else { p->setPen( QColor(100, 100, 100) ); p->drawRect( x, y, w, h ); } // now for the inner rect; x += 4; w -= 8; y += 2; h -= 4; int d = 0; loadPMs(); if ( event().hasAlarm() ) { p->drawPixmap( x + w - 13, y, pm_alarmbell ); d += 17; } if ( event().hasRepeat() ) { p->drawPixmap( x + w - 13 - d, y, pm_repeat ); d += 17; } else if ( event().isException() ) { p->drawPixmap( x + w - 13 - d, y, pm_repeatE ); d += 17; } if ( compressed ) { headingText = strDesc; QSimpleRichText rt( headingText, p->font() ); // modified clip region for rt. // better to clip than to draw over our icons. QRect rect(x, y, w - d, h); rt.setWidth( w - d ); p->setClipRect(p->xForm(QRect(x,y,w,h))); p->setClipRect(p->xForm(rect)); rt.draw( p, x, y, QRegion(rect), cg ); p->restore(); } else { QSimpleRichText rt( headingText, p->font() ); QString noteText; if (!noteTZ.isEmpty()) noteText = "<b>"+DayViewContents::tr("Time zone:")+"</b> " + noteTZ + "<br>"; noteText += "<b>" + DayViewContents::tr("Start") + "</b>: "; if ( noteShowStartDate ) { // multi-day event. Show start date noteText += TimeString::localYMD( noteStart.date(), TimeString::Long ); } else { // Show start time. noteText += TimeString::localHM( noteStart.time() ); } noteText += "<br><b>" + DayViewContents::tr("End") + "</b>: "; if ( noteShowEndDate ) { // multi-day event. Show end date noteText += TimeString::localYMD( noteEnd.date(), TimeString::Long ); } else { // Show end time. noteText += TimeString::localHM( noteEnd.time() ); } noteText += "<br><br>" + noteStr; QSimpleRichText rtNotes( noteText, p->font() ); // modified clip region for rt. // better to clip than to draw over our icons. QRect rect(x, y, w - d, h); rt.setWidth( w - d ); rtNotes.setWidth( w ); p->setClipRect(p->xForm(QRect(x,y,w,h))); rtNotes.draw( p, x, y + rt.height(), QRegion(x, y, w, h), cg ); p->setClipRect(p->xForm(rect)); rt.draw( p, x, y, QRegion(rect), cg ); p->restore(); }}void DayItem::setCompressed(){ compressed = TRUE;}void DayItem::loadPMs(){ if ( pm_repeat.isNull() ) { pm_repeat = Resource::loadIconSet("repeat").pixmap(QIconSet::Small, TRUE); pm_repeatE = Resource::loadIconSet("repeatException").pixmap(QIconSet::Small, TRUE); pm_alarmbell = Resource::loadIconSet("smallalarm").pixmap(QIconSet::Small, TRUE); }}// ====================================================================DayViewLayout::DayViewLayout(int w, int h) : LayoutManager(w,h), fItem(0){}void DayViewLayout::clear(){ fItem = 0; LayoutManager::clear();}DayItem *DayViewLayout::focusedItem() const{ return fItem;}void DayViewLayout::setFocusedItem(DayItem *i){ if (fItem) fItem->setFocus(FALSE); fItem = 0; if (i && items().containsRef(i)) { i->setFocus(TRUE); fItem = i; }}DayItem *DayViewLayout::firstItem(){ if (fItem) fItem->setFocus(FALSE); if (items().size() > 0) { // really should be 'top' item, most to left. fItem = (DayItem *)items().at(0); fItem->setFocus(TRUE); } else fItem = 0; return fItem;}DayItem *DayViewLayout::nextItem(){ if (fItem) fItem->setFocus(FALSE); else return 0; int pos = items().findRef(fItem); pos++; if (pos >= (int)items().count()) { fItem = 0; } else { fItem = (DayItem *)items().at(pos); fItem->setFocus(TRUE); } return fItem;}DayItem *DayViewLayout::previousItem(){ if (fItem) fItem->setFocus(FALSE); else return 0; int pos = items().findRef(fItem); pos--; if (pos < 0 || items().count() < 1) { fItem = 0; } else { fItem = (DayItem *)items().at(pos); fItem->setFocus(TRUE); } return fItem;}DayItem *DayViewLayout::lastItem(){ if (fItem) fItem->setFocus(FALSE); if (items().size() > 0) { // really should be 'top' item, most to left. fItem = (DayItem *)items().at(items().size()-1); fItem->setFocus(TRUE); } else fItem = 0; return fItem;}void DayViewLayout::addOccurrence(Occurrence &e, const QDate &cDate ){ DayItem *di = new DayItem(cDate, e); addItem(di); eventsChanged(); initializeGeometry(di);}void DayViewLayout::setTimeHeight( int th ){ time_height = th;}// ====================================================================AllDayLayout::AllDayLayout(int w, int h) : DayViewLayout(w,h){}void AllDayLayout::layoutItems(bool){ for ( int i = 0; i < count(); i++) { LayoutItem *w = items().at(i); // one under the other, full width. QRect geom = w->geometry(); geom.setX( i % 2 ? size().width() / 2 : 0 ); geom.setY( day_height * (i / 2) ); int width = size().width() - (size().width() % 2); // round down to even. int day_width = i % 2 == 0 && i == count() - 1 ? size().width() : width / 2; if ( i % 2 ) day_width += size().width() % 2; // round up the second item. geom.setWidth( day_width ); geom.setHeight( day_height ); w->setGeometry(geom); }}// ====================================================================TimeList::TimeList() : list(), height24( 0 ), infoModified( FALSE ), time_height(short_time_height){ clear();}void TimeList::clear(){ for ( int i = 0; i <= 24; i++ ) { hourInfo[i].empty = TRUE; hourInfo[i].stretch = FALSE; hourInfo[i].hits = 0; } list.clear();}void TimeList::add( const QDate &referenceDate, LayoutItem *item ){ const QTime &t1 = item->occurrence().startInCurrentTZ().time(); const QTime &t2 = item->occurrence().endInCurrentTZ().time(); bool need1 = referenceDate <= item->occurrence().startInCurrentTZ().date(); bool need2 = referenceDate >= item->occurrence().startInCurrentTZ().date().addDays( item->occurrence().startInCurrentTZ().date().daysTo( item->occurrence().endInCurrentTZ().date() ) ); if ( need1 ) add( t1 ); else add( QTime(0,0,0) ); if ( need2 ) add( t2 ); int start = need1 ? t1.hour() - 1 : 0; int end = need2 ? t2.hour() - 1 : 23; for ( int i = (start >= 0) ? start : 0; i < end; i++ ) hourInfo[i].empty = FALSE;}void TimeList::add( const QTime &val ){ if ( list.contains( val ) == 0 ) list.append( val );}void TimeList::addDone(){ qHeapSort( list ); for ( TimeVals::ConstIterator it = list.begin(); it != list.end(); it++ ) { const QTime &t = *it; hit( t.hour() ); } height24 = height(25); infoModified = FALSE;}void TimeList::hit( int index ){ for ( int i = index; i <= 24; i++ ) hourInfo[i].hits++;}int TimeList::height( const QTime &time ) const{ int h1 = (time.hour() > 0) ? hourInfo[time.hour() - 1].hits : 0; if ( time.hour() < 24 ) { int h2 = hourInfo[time.hour()].hits; if ( h2 - h1 > 1 ) { // There are multiple appointments that start at this hour // so we count the ones before us and add an "hour" for each // of them. This is because of the longer hours. TimeVals::ConstIterator it = list.find( time ); if ( it != list.end() ) { while ( it != list.begin() ) { --it; const QTime &t = *it; if ( t.hour() != time.hour() ) break; h1++; } } } } return h1;}int TimeList::height( const int hour ) const{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -