Logo Search packages:      
Sourcecode: kboincspy version File versions  Download package

kbscreditcalendar.cpp

/***************************************************************************
 *   Copyright (C) 2004 by Roberto Virga                                   *
 *   rvirga@users.sf.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  *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <qpainter.h>

#include <kcalendarsystem.h>
#include <kglobal.h>
#include <klocale.h>
#include <kbslogmanager.h>
#include <kbsprojectmonitor.h>

#include <kbslogmanager.h>

#include "kbscreditcalendar.h"

const unsigned KBSCreditCalendar::s_border = 1;

KBSCreditCalendar::KBSCreditCalendar(QWidget *parent, const char *name)
                 : QWidget(parent, name), m_initial(0.0), m_increment(0.0)
{
  // set reasonable settings for the slot variables
  m_start = QDate::currentDate();
  m_current = firstOfMonth(m_start);
  
  // clear the cache
  setupCache();
  
  // set minimum size; can grow, but not shrink, from that
  {
    QFontMetrics metrics = this->fontMetrics();
    const int lineHeight = this->fontMetrics().lineSpacing();
    const int cellWidth = metrics.width("___________");

    setMinimumSize(QSize(2 * lineHeight + 7 * (cellWidth + 4 * s_border),
                         3 * lineHeight + 6 * (3 * lineHeight + 4 * s_border)));
  }
  setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
  
  // optimize redrawing
  setBackgroundMode(NoBackground);
  
  KBSLogManager *log = KBSLogManager::self();
  connect(log, SIGNAL(logChanged()), this, SLOT(updateLog()));
  connect(log, SIGNAL(workunitsUpdated()), this, SLOT(updateLog()));
}

QString KBSCreditCalendar::projectName() const
{
  return m_projectName;
}

void KBSCreditCalendar::setProjectName(const QString &projectName)
{
  if(projectName == m_projectName) return;
  
  m_projectName = projectName;
  
  setupCache();
  
  repaint();
}

double KBSCreditCalendar::initial() const
{
  return(m_initial);
}

double KBSCreditCalendar::increment() const
{
  return(m_increment);
}

QDate KBSCreditCalendar::currentDate() const
{
  return(m_current);
}

QPixmap KBSCreditCalendar::pixmap()
{
  return QPixmap::grabWidget(this);
}

void KBSCreditCalendar::addMonths(int months)
{
  if(0 == months) return;

  const int epoch = m_current.year() * 12 + (m_current.month() - 1) + months;
  m_current = QDate(epoch / 12, epoch % 12 + 1, 1);
  
  setupCache();

  repaint();
}

void KBSCreditCalendar::setInitial(double initial)
{
  if(initial == m_initial) return;
  
  m_initial = initial;
  // setting the WU's updates the start date
  m_start = QDate::currentDate();

  repaint();
}

void KBSCreditCalendar::setIncrement(double increment)
{
  if(increment == m_increment) return;

  m_increment = increment;

  repaint();
}

void KBSCreditCalendar::paintEvent(QPaintEvent *)
{
  QPixmap buffer(this->size());
  buffer.fill(black);
  
  QPainter painter(&buffer);
  KLocale *locale = KGlobal::locale();
  
  QFontMetrics metrics = painter.fontMetrics();
  const int lineHeight = metrics.lineSpacing();
  
  // drawing area limits
  QPoint topLeft(lineHeight, lineHeight);
  QPoint bottomRight(width() - lineHeight, height() - lineHeight);
  
  // draw on screen the name of the month and the year
  const QString month = locale->calendar()->monthName(m_current, false);
  QRect header(topLeft, QSize(width() - 2 * lineHeight, lineHeight));

  painter.setPen(yellow);
  painter.drawText(header, AlignLeft | AlignTop, i18n("%1, %2").arg(month).arg(m_current.year()));

  // as many columns as days of the week, and 6 rows are enough to acommodate all months
  const unsigned rows = 6;
  const unsigned columns = 7;

  // day grid rectangle
  QRect grid(QPoint(lineHeight, 2 * lineHeight), bottomRight);
  // text area inside a day grid cell
  QRect textArea(2 * s_border, s_border,
                 grid.width() / columns - 4 * s_border, grid.height() / rows - 2 * s_border);

  // offset is the column offset for the first day of the month
  const int offset =  (m_current.dayOfWeek() + 7 - locale->weekStartDay()) % 7;
    
  // draw the day grid rectangle and its contents
  painter.setPen(white);
  painter.drawRect(grid);
  for(uint i = 0; i < rows; i++)
    for(uint j = 0; j < columns; j++)
    {
      painter.save();

      painter.translate(lineHeight + double(grid.width() * j) / columns,
                        2 * lineHeight + double(grid.height() * i) / rows);

      painter.setPen(white);
      if(i > 0 && j == 0)
        painter.drawLine(0, 0, grid.width()-1, 0);
      if(i == 0 && j > 0)
        painter.drawLine(0, 0, 0, grid.height()-1);

      // draw the cell interior for meaningful days
      const int day = i * 7 + j - offset + 1;
      if(day > 0 && day <= m_current.daysInMonth())
      {
        const QDate date = m_current.addDays(day-1);

        if(date > m_start)
        {
          // draw the number of future wu's in blue, provided it is meaningful (i.e. nonnegative)
          const double credits = m_initial + m_start.daysTo(date) * m_increment;

          if(m_initial >= 0.0 && credits > 0.0)
          {
            QString text = locale->formatNumber(credits, 2);
            text.remove(locale->thousandsSeparator());
            
            painter.setPen(QColor(0, 231, 231));
            painter.drawText(textArea, AlignRight | AlignBottom, text);
          }
        }
        else
        {
          // draw the number of wu's in the log, if it is greater than zero
          const double credits = m_cache[day-1];
          
          if(credits > 0.0)
          {
            // compute the rect of this cell
            const int w = int(double(grid.width() * (j+1)) / columns) - int(double(grid.width() * j) / columns);
            const int h = int(double(grid.height() * (i+1))/rows) - int(double(grid.height() * i)/rows);  
            const QRect cell(QPoint(1, 1), QSize(w - 2, h - 2));

            painter.fillRect(cell, darkRed);

            QString text = locale->formatNumber(credits, 2);
            text.remove(locale->thousandsSeparator());
            
            painter.setPen(yellow);
            painter.drawText(textArea, AlignRight | AlignBottom, text);
          }
        }
        
        painter.setPen(white);
        painter.drawText(textArea, AlignLeft | AlignTop, QString::number(day));
      }
    
      painter.restore();
    }
    
  painter.end();
  
  painter.begin(this);
  painter.drawPixmap(0, 0, buffer);
}

void KBSCreditCalendar::updateLog()
{
  setupCache();
  
  // updating the log data updates also the start date
  m_start = QDate::currentDate();
  
  repaint();
}

void KBSCreditCalendar::setupCache()
{
  if(m_current > firstOfMonth(m_start)) return;

  for(unsigned i = 0; i < 31; ++i)
    m_cache[i] = 0.0;

  KBSLogData log = KBSLogManager::self()->workunits();
  for(KBSLogData::const_iterator it = log.begin(); it != log.end(); ++it)
  {
    const QDate date = (*it)["date"].toDateTime().date();
    const QString projectName = (*it)["project_name"].toString();
    
    if(firstOfMonth(date) == m_current && projectName == m_projectName)
    {
      const double fpops = (*it)["p_fpops"].toDouble();
      const double iops = (*it)["p_iops"].toDouble();
      const double cpu = (*it)["cpu"].toDouble();
      
      m_cache[date.day()-1] += cpu * BOINCHostInfo::credit_per_cpu_sec(fpops, iops);
    }
  }
}

QDate KBSCreditCalendar::firstOfMonth(const QDate& date)
{
  return(QDate(date.year(), date.month(), 1));
}

#include "kbscreditcalendar.moc"

Generated by  Doxygen 1.6.0   Back to index