You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kipi-plugins/kipi-plugins/calendar/calpainter.cpp

626 lines
17 KiB

/* ============================================================
* File : calpainter.cpp
* Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
* Date : 2003-11-02
* Description :
*
* Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
* 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, 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.
*
* ============================================================ */
// TQt includes.
#include <tqpainter.h>
#include <tqrect.h>
#include <tqpaintdevice.h>
#include <tqdatetime.h>
#include <tqpaintdevicemetrics.h>
#include <tqstring.h>
#include <tqimage.h>
#include <tqtimer.h>
#include <tqwmatrix.h>
// KDE includes.
#include <kglobal.h>
#include <klocale.h>
#include <tdeversion.h>
#include <kcalendarsystem.h>
#include <kdebug.h>
// Local includes.
#include "calpainter.h"
#include "calsettings.h"
#include "calformatter.h"
namespace KIPICalendarPlugin
{
CalPainter::CalPainter(TQPaintDevice *pd)
{
pd_ = pd;
}
CalPainter::~CalPainter()
{
}
void CalPainter::setYearMonth(int year, int month)
{
year_ = year;
month_ = month;
}
void CalPainter::paint(bool useDeviceMetrics)
{
if (!pd_) return;
TQPainter *painter = new TQPainter();
painter->begin(pd_);
int width = 0;
int height = 0;
CalParams& params = CalSettings::instance()->calParams;
if (!useDeviceMetrics) {
width = params.width;
height = params.height;
}
else {
TQPaintDeviceMetrics metrics( painter->device());
width = metrics.width();
height = metrics.height();
}
// --------------------------------------------------
int days[42];
int startDayOffset = KGlobal::locale()->weekStartDay();
for (int i=0; i<42; i++)
days[i] = -1;
TQDate d;
KGlobal::locale()->calendar()->setYMD(d, year_, month_, 1);
int s = d.dayOfWeek();
if (s+7-startDayOffset >= 7)
s=s-7;
for (int i=s; i<(s+KGlobal::locale()->calendar()->daysInMonth(d)); i++) {
days[i + (7-startDayOffset)] = i-s+1;
}
// -----------------------------------------------
TQRect rCal, rImage, rCalHeader;
int cellSizeX;
int cellSizeY;
switch (params.imgPos) {
case(CalParams::Top): {
rImage = TQRect(0,0,0,0);
rImage.setWidth(width);
rImage.setHeight((int)(height *
(params.ratio)/(params.ratio + 100)));
int remainingHeight = height - rImage.height();
cellSizeX = (width - 20)/7;
cellSizeY = remainingHeight/8;
rCal = TQRect(0,0,0,0);
rCal.setWidth(cellSizeX*7);
rCal.setHeight((int)(cellSizeY*7));
rCalHeader = TQRect(0,0,0,0);
rCalHeader.setWidth(rCal.width());
rCalHeader.setHeight((int)(cellSizeY));
rCalHeader.moveTop(rImage.bottom());
rCalHeader.moveLeft(width/2 - rCalHeader.width()/2);
rCal.moveTopLeft(rCalHeader.bottomLeft());
break;
}
case(CalParams::Left): {
rImage = TQRect(0,0,0,0);
rImage.setHeight(height);
rImage.setWidth((int)(width *
(params.ratio)/(params.ratio + 100)));
int remainingWidth = width - rImage.width();
cellSizeX = remainingWidth/8;
cellSizeY = (height - 20)/7;
rCal = TQRect(0,0,0,0);
rCal.setWidth(cellSizeX*7);
rCal.setHeight(cellSizeY*7);
rCalHeader = TQRect(0,0,0,0);
rCalHeader.setWidth(rCal.width());
rCalHeader.setHeight(cellSizeY);
rCalHeader.moveLeft(rImage.right() + cellSizeX);
rCalHeader.moveTop(height/2 -
(rCalHeader.height()+rCal.height()/2));
rCal.moveTopLeft(rCalHeader.bottomLeft());
break;
}
case(CalParams::Right): {
rImage = TQRect(0,0,0,0);
rImage.setHeight(height);
rImage.setWidth((int)(width *
(params.ratio)/(params.ratio + 100)));
int remainingWidth = width - rImage.width();
cellSizeX = remainingWidth/8;
cellSizeY = (height - 20)/7;
rCal = TQRect(0,0,0,0);
rCal.setWidth(cellSizeX*7);
rCal.setHeight(cellSizeY*7);
rCalHeader = TQRect(0,0,0,0);
rCalHeader.setWidth(rCal.width());
rCalHeader.setHeight(cellSizeY);
rCalHeader.moveTop(height/2 -
(rCalHeader.height()+rCal.height()/2));
rCal.moveTop(rCalHeader.bottom());
rImage.moveLeft(width - rImage.width());
break;
}
default:
return;
}
int fontPixels = (int)((float)cellSizeX/3.0);
params.baseFont.setPixelSize(fontPixels);
// ---------------------------------------------------------------
painter->fillRect(0,0,width, height, TQt::white);
painter->fillRect(rImage, TQt::black);
painter->setFont(params.baseFont);
// ---------------------------------------------------------------
painter->save();
TQFont f(params.baseFont);
f.setBold(true);
f.setPixelSize(f.pixelSize() + 5);
painter->setFont(f);
painter->drawText(rCalHeader, TQt::AlignLeft|TQt::AlignVCenter,
TQString::number(year_));
#if KDE_IS_VERSION(3,2,0)
painter->drawText(rCalHeader, TQt::AlignRight|TQt::AlignVCenter,
KGlobal::locale()->calendar()->monthName(month_, year_));
#else
painter->drawText(rCalHeader, TQt::AlignRight|TQt::AlignVCenter,
KGlobal::locale()->monthName(month_));
#endif
painter->restore();
// ---------------------------------------------------------------
int sx, sy;
TQRect r, rsmall;
r.setWidth(cellSizeX);
r.setHeight(cellSizeY);
int index = 0;
painter->save();
painter->setPen(TQt::red);
sy = rCal.top();
for (int i=0; i<7; i++)
{
int dayname = i + startDayOffset;
if (dayname > 7)
dayname = dayname-7;
sx = cellSizeX * i + rCal.left();
r.moveTopLeft(TQPoint(sx,sy));
rsmall = r;
rsmall.setWidth(r.width() - 2);
rsmall.setHeight(r.height() - 2);
#if KDE_IS_VERSION(3,2,0)
painter->drawText(rsmall, TQt::AlignRight|TQt::AlignBottom,
KGlobal::locale()->calendar()->weekDayName(dayname, true));
#else
painter->drawText(rsmall, TQt::AlignRight|TQt::AlignBottom,
KGlobal::locale()->weekDayName(dayname, true));
#endif
}
painter->restore();
for (int j=0; j<6; j++) {
sy = cellSizeY * (j + 1) + rCal.top();
for (int i=0; i<7; i++) {
sx = cellSizeX * i + rCal.left();
r.moveTopLeft(TQPoint(sx,sy));
rsmall = r;
rsmall.setWidth(r.width() - 2);
rsmall.setHeight(r.height() - 2);
if (days[index] != -1)
painter->drawText(rsmall, TQt::AlignRight|TQt::AlignBottom,
TQString::number(days[index]));
index++;
}
}
// ---------------------------------------------------------------
if (params.drawLines) {
sx = rCal.left();
for (int j=0; j<8; j++) {
sy = cellSizeY * j + rCal.top();
painter->drawLine(sx,sy,rCal.right(),sy);
}
sy = rCal.top();
for (int i=0; i<8; i++) {
sx = cellSizeX * i + rCal.left();
painter->drawLine(sx,sy,sx,rCal.bottom());
}
}
painter->end();
delete painter;
}
CalBlockPainter::CalBlockPainter(TQObject *parent, int year, int month,
const KURL& imagePath, int angle, CalFormatter *formatter, TQPainter *painter)
: TQObject(parent), painter_(painter)
{
int width = 0;
int height = 0;
CalParams& params = CalSettings::instance()->calParams;
TQPaintDeviceMetrics metrics( painter->device());
width = metrics.width();
height = metrics.height();
// --------------------------------------------------
int days[42];
int startDayOffset = KGlobal::locale()->weekStartDay();
for (int i=0; i<42; i++)
days[i] = -1;
TQDate d;
KGlobal::locale()->calendar()->setYMD(d, year, month, 1);
int s = d.dayOfWeek();
if (s+7-startDayOffset >= 7)
s=s-7;
for (int i=s; i<(s+KGlobal::locale()->calendar()->daysInMonth(d)); i++) {
days[i+(7-startDayOffset)] = i-s+1;
}
// -----------------------------------------------
TQRect rCal, rImage, rCalHeader;
int cellSizeX;
int cellSizeY;
switch (params.imgPos) {
case(CalParams::Top): {
rImage = TQRect(0,0,0,0);
rImage.setWidth(width);
rImage.setHeight((int)(height *
(params.ratio)/(params.ratio + 100)));
int remainingHeight = height - rImage.height();
cellSizeX = (width - 20)/7;
cellSizeY = remainingHeight/8;
rCal = TQRect(0,0,0,0);
rCal.setWidth(cellSizeX*7);
rCal.setHeight((int)(cellSizeY*7));
rCalHeader = TQRect(0,0,0,0);
rCalHeader.setWidth(rCal.width());
rCalHeader.setHeight((int)(cellSizeY));
rCalHeader.moveTop(rImage.bottom());
rCalHeader.moveLeft(width/2 - rCalHeader.width()/2);
rCal.moveTopLeft(rCalHeader.bottomLeft());
break;
}
case(CalParams::Left): {
rImage = TQRect(0,0,0,0);
rImage.setHeight(height);
rImage.setWidth((int)(width *
(params.ratio)/(params.ratio + 100)));
int remainingWidth = width - rImage.width();
cellSizeX = remainingWidth/8;
cellSizeY = (height - 20)/7;
rCal = TQRect(0,0,0,0);
rCal.setWidth(cellSizeX*7);
rCal.setHeight(cellSizeY*7);
rCalHeader = TQRect(0,0,0,0);
rCalHeader.setWidth(rCal.width());
rCalHeader.setHeight(cellSizeY);
rCalHeader.moveLeft(rImage.right() + cellSizeX);
rCalHeader.moveTop(height/2 -
(rCalHeader.height()+rCal.height()/2));
rCal.moveTopLeft(rCalHeader.bottomLeft());
break;
}
case(CalParams::Right): {
rImage = TQRect(0,0,0,0);
rImage.setHeight(height);
rImage.setWidth((int)(width *
(params.ratio)/(params.ratio + 100)));
int remainingWidth = width - rImage.width();
cellSizeX = remainingWidth/8;
cellSizeY = (height - 20)/7;
rCal = TQRect(0,0,0,0);
rCal.setWidth(cellSizeX*7);
rCal.setHeight(cellSizeY*7);
rCalHeader = TQRect(0,0,0,0);
rCalHeader.setWidth(rCal.width());
rCalHeader.setHeight(cellSizeY);
rCalHeader.moveTop(height/2 -
(rCalHeader.height()+rCal.height()/2));
rCal.moveTop(rCalHeader.bottom());
rImage.moveLeft(width - rImage.width());
break;
}
default:
return;
}
int fontPixels = (int)((float)cellSizeX/3.0);
params.baseFont.setPixelSize(fontPixels);
// ---------------------------------------------------------------
painter->fillRect(0,0,width, height, TQt::white);
painter->setFont(params.baseFont);
// ---------------------------------------------------------------
painter->save();
TQFont f(params.baseFont);
f.setBold(true);
f.setPixelSize(f.pixelSize() + 5);
painter->setFont(f);
painter->drawText(rCalHeader, TQt::AlignLeft|TQt::AlignVCenter,
TQString::number(year));
#if KDE_IS_VERSION(3,2,0)
painter->drawText(rCalHeader, TQt::AlignRight|TQt::AlignVCenter,
KGlobal::locale()->calendar()->monthName(month, year));
#else
painter->drawText(rCalHeader, TQt::AlignRight|TQt::AlignVCenter,
KGlobal::locale()->monthName(month));
#endif
painter->restore();
// ---------------------------------------------------------------
int sx, sy;
TQRect r, rsmall, rSpecial;
r.setWidth(cellSizeX);
r.setHeight(cellSizeY);
int index = 0;
painter->save();
painter->setPen(TQt::red);
sy = rCal.top();
for (int i=0; i<7; i++) {
int dayname = i + startDayOffset;
if (dayname > 7)
dayname = dayname-7;
sx = cellSizeX * i + rCal.left();
r.moveTopLeft(TQPoint(sx,sy));
rsmall = r;
rsmall.setWidth(r.width() - 2);
rsmall.setHeight(r.height() - 2);
#if KDE_IS_VERSION(3,2,0)
painter->drawText(rsmall, TQt::AlignRight|TQt::AlignBottom,
KGlobal::locale()->calendar()->weekDayName(dayname, true));
#else
painter->drawText(rsmall, TQt::AlignRight|TQt::AlignBottom,
KGlobal::locale()->weekDayName(dayname, true));
#endif
}
painter->restore();
for (int j=0; j<6; j++) {
sy = cellSizeY * (j + 1) + rCal.top();
for (int i=0; i<7; i++) {
sx = cellSizeX * i + rCal.left();
r.moveTopLeft(TQPoint(sx,sy));
rsmall = r;
rsmall.setWidth(r.width() - 2);
rsmall.setHeight(r.height() - 2);
if (days[index] != -1) {
if (formatter->isSpecial(month, days[index])) {
painter->save();
painter->setPen( formatter->getDayColor(month, days[index]) );
painter->drawText(rsmall, TQt::AlignRight|TQt::AlignBottom,
TQString::number(days[index]));
TQString descr = formatter->getDayDescr(month, days[index]);
kdDebug(51000) << "Painting special info: '" << descr << "' for date " << days[index] << "/" << month << endl;
rSpecial = rsmall;
rSpecial.moveBy(2,0);
TQFont f(params.baseFont);
f.setPixelSize(f.pixelSize() / 3);
painter->setFont(f);
painter->drawText(rSpecial, TQt::AlignLeft|TQt::AlignTop, descr);
painter->restore();
}
else
{
painter->drawText(rsmall, TQt::AlignRight|TQt::AlignBottom,
TQString::number(days[index]));
}
}
index++;
}
}
// ---------------------------------------------------------------
if (params.drawLines) {
sx = rCal.left();
for (int j=0; j<8; j++) {
sy = cellSizeY * j + rCal.top();
painter->drawLine(sx,sy,rCal.right(),sy);
}
sy = rCal.top();
for (int i=0; i<8; i++) {
sx = cellSizeX * i + rCal.left();
painter->drawLine(sx,sy,sx,rCal.bottom());
}
}
// ---------------------------------------------------------------
TQImage img = TQImage(imagePath.path()); // PENDING(blackie) handle general URLS.
if (!img.isNull()) {
if ( angle != 0 ) {
TQWMatrix matrix;
matrix.rotate( angle );
img = img.xForm( matrix );
}
image_ = new TQImage(img.smoothScale(rImage.width(), rImage.height(),
TQ_ScaleMin));
// Center the image
int x = rImage.x() + rImage.width()/2 - image_->width()/2;
int y = rImage.y() + rImage.height()/2 - image_->height()/2;
// Print in 10 pixel strips
int blockSize = 10;
numBlocks_ = image_->height()/blockSize;
blocks_ = new struct Block[numBlocks_];
struct Block* pb = blocks_;
struct Block* pbNext;
pb->x = x;
pb->y = y;
pb->sx = 0;
pb->sy = 0;
pb->w = image_->width();
pb->h = blockSize;
for (int j=1; j<numBlocks_; j++) {
pbNext = pb + 1;
pbNext->x = x;
pbNext->y = pb->y + blockSize;
pbNext->sx = 0;
pbNext->sy = pb->sy + blockSize;
pbNext->w = pb->w;
pbNext->h = blockSize;
pb = pbNext;
}
pb->h = image_->height() - pb->y;
currBlock_ = 0;
TQTimer::singleShot(10, this, TQT_SLOT(slotPaintNextBlock()));
}
else {
image_ = 0;
blocks_ = 0;
painter->fillRect(rImage, TQt::blue);
}
}
CalBlockPainter::~CalBlockPainter()
{
if (blocks_) delete [] blocks_;
if (image_) delete image_;
}
void CalBlockPainter::slotPaintNextBlock()
{
struct Block& b = blocks_[currBlock_];
painter_->drawImage(b.x, b.y, *image_, b.sx, b.sy,
b.w, b.h);
currBlock_++;
if (currBlock_ < numBlocks_) {
TQTimer::singleShot(10, this, TQT_SLOT(slotPaintNextBlock()));
emit signalProgress(currBlock_+1, numBlocks_);
}
else {
emit signalCompleted();
delete this;
}
}
} // NameSpace KIPICalendarPlugin
#include "calpainter.moc"