added all files
[ffqwlibrary] / libffqw-n810-1.0 / sources / ffchartscene.cpp
diff --git a/libffqw-n810-1.0/sources/ffchartscene.cpp b/libffqw-n810-1.0/sources/ffchartscene.cpp
new file mode 100644 (file)
index 0000000..292951e
--- /dev/null
@@ -0,0 +1,903 @@
+/*
+         GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+http://www.gnu.org/licenses/gpl-3.0.txt
+*/
+/**
+ * @file ffchartscene.cpp
+ * @brief Implementation of the FFChartScene class.
+ *
+ * @author ComArch S.A.
+ * @date 2009.09.01
+ * @version 1.1
+ */
+
+#include "ffchartscene.h"
+
+// ############################################################ CONSTRUCTORS
+
+/**
+ * Constructs a FFChartScene with a parent.
+ */
+FFChartScene::FFChartScene(QObject* parent) :
+       QGraphicsScene(parent)
+{
+       init();
+}
+
+/**
+ * A virtual destructor.
+ */
+FFChartScene::~FFChartScene()
+{
+
+}
+
+/**
+ * Initiates an object of FFChartScene. Sets all needed fields connections.
+ * It is called by all constructors.
+ */
+void FFChartScene::init()
+{
+       //sets default configuration
+       moveModeSw = false;
+       zoomModeSw = false;
+       kineticCount = 0;
+
+       accumulatedZoomFactor_ = QSize(1, 1);
+       QBrush zoomRectBrush(QColor(60, 80, 60));
+
+       QPen zoomRectPen;
+       zoomRectPen.setBrush(zoomRectBrush);
+       zoomRectPen.setColor(QColor(80, 180, 80));
+       zoomRectPen.setWidth(3);
+
+       zoomRect = new QGraphicsRectItem;
+       zoomRect->setPen(zoomRectPen);
+       zoomRect->setBrush(zoomRectBrush);
+       setBackgroundBrush(QBrush(QColor(30, 30, 30)));
+
+       timer = new QTimer(this);
+       connect(timer, SIGNAL(timeout()), this, SLOT(kineticScroll()));
+
+       zoomInButton.moveBy(10,10);
+       zoomOutButton.moveBy(10,90);
+       legendButton.moveBy(10, sceneRect().height() - 70);
+
+       subaxesSpacing_ = 40;
+       subaxesPen_.setColor(QColor(80,80,80));
+       subaxesPen_.setStyle(Qt::DashLine);
+       subaxesPen_.setCosmetic(true);
+
+       axesValuesPen_.setColor(QColor(240, 240, 240));
+
+       //adds button to chart
+       addItem(&zoomInButton);
+       addItem(&zoomOutButton);
+       addItem(&legendButton);
+
+
+
+       //connects
+       connect(&zoomInButton, SIGNAL(mouseRelease()), this, SLOT(zoomIn()));
+       connect(&zoomOutButton, SIGNAL(mouseRelease()), this, SLOT(zoomOut()));
+       connect(&legendButton, SIGNAL(mouseRelease()), parent(), SLOT(showLegend()));
+
+       //sets chart's buttons
+       zoomInButton.setImage(":/standard/chart_zoomin");
+       zoomOutButton.setImage(":/standard/chart_zoomout");
+       legendButton.setImage(":/standard/chart_legendON",":/standard/chart_legendOFF");
+
+       zoomInButton.setZoomRatio(1.4);
+       zoomOutButton.setZoomRatio(0.6);
+       legendButton.setZoomRatio(1.4);
+
+       zoomInButton.setSize(QSize(60, 60));
+       zoomOutButton.setSize(QSize(60, 60));
+       legendButton.setSize(QSize(60, 60));
+
+}
+
+// ################################################################## PUBLIC
+
+/**
+ * Moves given point of chart to the scene's top left corner.
+ */
+void FFChartScene::moveTo(QPoint point)
+{
+       translateFactor_ = point;
+       update();
+}
+
+/**
+ * Moves given point of chart to the scene's top left corner.
+ */
+void FFChartScene::moveTo(float x, float y)
+{
+       translateFactor_ = QPointF(x, y);
+       update();
+}
+
+/**
+ * Moves the chart by a given vector.
+ */
+void FFChartScene::moveBy(QPoint destPoint)
+{
+       translateFactor_ += destPoint;
+       update();
+}
+
+/**
+ * Moves the chart by a given vector.
+ */
+void FFChartScene::moveBy(float x, float y)
+{
+       translateFactor_ += QPointF(x, y);
+       update();
+}
+
+/**
+ * Adds set of points to chart.
+ */
+void FFChartScene::addSeries(FFChartSeries* series)
+{
+       this->series.append(series);
+       itemsBoundingRect_ = itemsBoundingRect(&itemsBoundingValues_);
+
+       update();
+
+       emit seriesChanged(this->series);
+}
+
+/**
+ * Sets a list of series.
+ */
+void FFChartScene::setSeries(QList<FFChartSeries*> series)
+{
+       this->series = series;
+       itemsBoundingRect_ = itemsBoundingRect(&itemsBoundingValues_);
+
+       update();
+
+       emit seriesChanged(&series);
+}
+
+/**
+ * Overridden method from QGraphicsScene.
+ */
+void FFChartScene::setSceneRect(const QRectF& rect)
+{
+       QGraphicsScene::setSceneRect(rect);
+       legendButton.setPos(10, rect.height() - 70);
+
+       translateFactor_.setX(rect.width() * 0.5);
+       translateFactor_.setY(rect.height() * 0.5);
+
+       sceneRec = rect;
+}
+
+/**
+ * Sets a distance in pixels between subaxes.
+ */
+void FFChartScene::setSubaxesSpacing(const float& subaxesSpacing)
+{
+       subaxesSpacing_ = subaxesSpacing;
+}
+
+/**
+ * Returns a distance in pixels between subaxes.
+ */
+float FFChartScene::subaxesSpacing() const
+{
+       return subaxesSpacing_;
+}
+
+/**
+ * Sets a pen that will be used to draw subaxes.
+ */
+void FFChartScene::setSubaxesPen(const QPen& subaxesPen)
+{
+       subaxesPen_ = subaxesPen;
+}
+
+/**
+ * Returns a pen that is used to draw subaxes.
+ */
+QPen FFChartScene::subaxesPen() const
+{
+       return subaxesPen_;
+}
+
+/**
+ * Sets a pen that will be used to draw values next to subaxes.
+ */
+void FFChartScene::setAxesValuesPen(const QPen& axesValuesPen)
+{
+       axesValuesPen_ = axesValuesPen;
+}
+
+/**
+ * Returns a pen that is used to draw values next to subaxes.
+ */
+QPen FFChartScene::axesValuesPen() const
+{
+       return axesValuesPen_;
+}
+
+// ############################################################ PUBLIC SLOTS
+
+/**
+ * Zooms the chart into the given rectangle.
+ */
+void FFChartScene::zoom(QRectF zoomRect)
+{
+       // Normalizing zoom rectangle (width and height must are greater than 0)
+       QRectF zoomRectNormalized(zoomRect);
+       if(zoomRect.width() < 0)
+       {
+               zoomRectNormalized.setX(zoomRect.x() + zoomRect.width());
+               zoomRectNormalized.setWidth(qAbs(zoomRect.width()));
+       }
+       if(zoomRect.height() < 0)
+       {
+               zoomRectNormalized.setY(zoomRect.y() + zoomRect.height());
+               zoomRectNormalized.setHeight(qAbs(zoomRect.height()));
+       }
+
+       // Calculating zoom factor for scale() function ( >1 zoomin, <1 zoomout )
+       QSizeF zoomFactor(sceneRec.width() / zoomRectNormalized.width(),
+                         sceneRec.height() / zoomRectNormalized.height());
+
+       accumulatedZoomFactor_.setWidth(zoomFactor.width()
+                       * accumulatedZoomFactor_.width());
+       accumulatedZoomFactor_.setHeight(zoomFactor.height()
+                       * accumulatedZoomFactor_.height());
+       //checking if factor of zooming is not to high
+       if(accumulatedZoomFactor_.width() > 20 || accumulatedZoomFactor_.height() > 20)
+       {
+               accumulatedZoomFactor_.setWidth(20);
+               accumulatedZoomFactor_.setHeight(20);
+               return;
+       }
+
+
+
+       translateFactor_ = QPointF((translateFactor_.x()
+                                                  - zoomRectNormalized.x())
+                                                  * zoomFactor.width(),
+                                  (translateFactor_.y()
+                                                  - zoomRectNormalized.y())
+                                                  * zoomFactor.height());
+
+       update();
+}
+
+/**
+ * Slot that changes series' set.
+ */
+void FFChartScene::seriesChanged(QList<FFChartSeries*> series)
+{
+       setSeries(series);
+}
+
+/**
+ * Slot that zooms in the current chart into a rectangle which is smaller by
+ * a given ratio.
+ */
+void FFChartScene::zoomIn(qreal ratio)
+{
+       qreal dx, dy;
+
+       if(accumulatedZoomFactor_.width() > 15)
+       {
+               dx = 0;
+       }
+       else
+       {
+               dx = ratio * sceneRec.width();
+       }
+
+       if(accumulatedZoomFactor_.height() > 15)
+       {
+               dy = 0;
+       }
+       else
+       {
+               dy = ratio * sceneRec.height();
+       }
+
+       zoom(QRectF(dx, dy, sceneRec.width() - 2 * dx, sceneRec.height() - 2
+                       * dy));
+}
+
+/**
+ * Slot that zooms out the current chart into a rectangle which is larger by
+ * a given ratio.
+ */
+void FFChartScene::zoomOut(qreal ratio)
+{
+       qreal dx, dy;
+
+       if(accumulatedZoomFactor_.width() < 0.1)
+       {
+               dx = 0;
+       }
+       else
+       {
+               dx = ratio * sceneRec.width();
+       }
+
+       if(accumulatedZoomFactor_.height() < 0.1)
+       {
+               dy = 0;
+       }
+       else
+       {
+               dy = ratio * sceneRec.height();
+       }
+
+       zoom(QRectF(-dx, -dy, sceneRec.width() + 2 * dx, sceneRec.height() + 2
+                       * dy));
+}
+
+// ############################################################### PROTECTED
+
+/**
+ * Overridden method from QGraphicsScene. Draws all items that should be seen
+ * on the chart.
+ */
+void FFChartScene::drawItems(QPainter* painter,
+                             int numItems,
+                             QGraphicsItem* items[],
+                             const QStyleOptionGraphicsItem options[],
+                             QWidget* widget)
+{
+       Q_UNUSED(items)
+       Q_UNUSED(numItems)
+       Q_UNUSED(options)
+
+       // Drawing zoom rectangle
+       if(zoomModeSw)
+       {
+               zoomRect->paint(painter, new QStyleOptionGraphicsItem, widget);
+       }
+
+       painter->scale(1, 1);
+
+
+       // Drawing subaxes
+       drawSubAxes(painter, widget);
+
+       // Drawing axes
+       drawAxes(painter, widget);
+
+       // Drawing series
+       drawSeries(painter, widget);
+
+       // Drawing axes values
+       drawValues(painter, widget);
+
+       // Drawing static items
+       drawStaticItems(painter, widget);
+}
+
+/**
+ * Overridden virtual method from QGraphicsScene. It is responsible for
+ * handling a mouse press event.
+ * @param event Contains all informations about event.
+ */
+void FFChartScene::mousePressEvent(QGraphicsSceneMouseEvent* event)
+{
+       QGraphicsScene::mousePressEvent(event);
+
+       kinetic = false;
+       timer->stop();
+       kineticCount = 0;
+
+       if(itemAt(event->scenePos()))
+       {
+               return;
+       }
+
+       pressPos = event->scenePos();
+       moveModeSw = true;
+       zoomModeSw = false;
+
+       if(timer->isActive() == false)
+       {
+               timer->start(80);
+       }
+
+       update();
+}
+
+/**
+ * Overridden virtual method from QGraphicsScene. It is responsible for
+ * handling a mouse double click event.
+ * @param event Contains all informations about event.
+ */
+void FFChartScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
+{
+       if(itemAt(event->scenePos()))
+       {
+               return;
+       }
+
+       zoomModeSw = true;
+       moveModeSw = false;
+       kinetic = false;
+       kineticCount = 0;
+
+       zoomRect->setRect(event->scenePos().x(), event->scenePos().y(), 1, 1);
+       update();
+}
+
+/**
+ * Overridden virtual method from QGraphicsScene. It is responsible for
+ * handling a mouse release event.
+ * @param event Contains all informations about event.
+ */
+void FFChartScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
+{
+       QGraphicsScene::mouseReleaseEvent(event);
+
+       if(zoomModeSw) // zooming
+       {
+               zoomModeSw = false;
+
+               if(qAbs(zoomRect->rect().width()) <= 15
+                               || qAbs(zoomRect->rect().height()) <= 15)
+               {
+                       update();
+                       return;
+               }
+
+               zoom(zoomRect->rect());
+               update();
+       }
+       else if(moveModeSw) //moving
+       {
+               moveModeSw = false;
+
+               if(oldKineticVec != kineticVec && kineticCount > 2 && zoomModeSw == false)
+               {
+                       kinetic = true;
+                       kineticVec *= kineticRatio;
+               }
+               else
+               {
+                       kinetic = false;
+                       timer->stop();
+               }
+       }
+}
+
+/**
+ * Overridden virtual method from QGraphicsScene. It is responsible for
+ * handling a mouse move event.
+ * @param event Contains all informations about event.
+ */
+void FFChartScene::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
+{
+
+       //if button's type is not left button return
+       if(event->buttons() != Qt::LeftButton)
+       {
+               return;
+       }
+
+       kineticCount++;
+
+       //updates parameters
+       //zooming mode
+       if(zoomModeSw)
+       {
+               zoomRect->setRect(pressPos.x(),
+                                 pressPos.y(),
+                                 event->scenePos().x() - pressPos.x(),
+                                 event->scenePos().y() - pressPos.y());
+       }
+       //moving mode
+       else if(moveModeSw)
+       {
+               QPointF scrollRatio(event->scenePos().x() - pressPos.x(),
+                                  event->scenePos().y() - pressPos.y());
+
+               oldPressPos = pressPos;
+               pressPos = event->scenePos();
+               translateFactor_ += scrollRatio;
+       }
+       update();
+}
+
+// ################################################################ PPRIVATE
+
+/**
+ * Returns a rectangle around all points in series
+ * @param boundaryValues vector of boundary values
+ * @return bounding rectangle QRectF
+ */
+QRectF FFChartScene::itemsBoundingRect(QVector<float>* boundaryValues)
+{
+       //if any series are available returns zero rectangle
+       if(series.isEmpty())
+       {
+               return QRectF(0, 0, 0, 0);
+       }
+       //if only one series is available returns rectangle for points from one
+       //series
+       if(series.size() == 1 && series.at(0)->size() == 1)
+       {
+               return QRectF(series.at(0)->at(0)->x(),
+                             series.at(0)->at(0)->y(),
+                             0,
+                             0);
+       }
+       //looks for maximum points in all series
+       float minX = series.at(0)->at(0)->x();
+       float maxX = series.at(0)->at(0)->x();
+       float minY = series.at(0)->at(0)->y();
+       float maxY = series.at(0)->at(0)->y();
+
+       for(int i = 0; i < series.size(); ++i)
+       {
+               for(int j = 0; j < series.at(i)->size(); ++j)
+               {
+                       if(series.at(i)->at(j)->x() < minX)
+                       {
+                               minX = series.at(i)->at(j)->x();
+                       }
+
+                       if(series.at(i)->at(j)->y() < minY)
+                       {
+                               minY = series.at(i)->at(j)->y();
+                       }
+
+                       if(series.at(i)->at(j)->x() > maxX)
+                       {
+                               maxX = series.at(i)->at(j)->x();
+                       }
+
+                       if(series.at(i)->at(j)->y() > maxY)
+                       {
+                               maxY = series.at(i)->at(j)->y();
+                       }
+               }
+       }
+
+       if(boundaryValues)
+       {
+               boundaryValues->clear();
+               boundaryValues->append(minX);
+               boundaryValues->append(minY);
+               boundaryValues->append(maxX);
+               boundaryValues->append(maxY);
+       }
+
+       return QRectF(minX, maxY, maxX - minX, maxY - minY);
+}
+
+/**
+ * Slot that zooms in by default value.
+ */
+void FFChartScene::zoomIn()
+{
+       zoomIn(defaultZoomInRatio);
+}
+
+/**
+ * Slot that zooms out by default value.
+ */
+void FFChartScene::zoomOut()
+{
+       zoomOut(defaultZoomOutRatio);
+}
+
+/**
+ * Draws main axes.
+ * @param painter a tool to drawing elements
+ * @param widget points to the widget where elements will be drew
+ */
+void FFChartScene::drawAxes(QPainter* painter, QWidget* widget)
+{
+    Q_UNUSED(widget)
+
+    painter->save();
+
+    painter->setPen(QColor(255, 255, 250));
+
+    // horizontal
+    painter->drawLine(QPointF(0,
+                      translateFactor_.y()),
+                      QPointF(sceneRec.width(),
+                      translateFactor_.y()));
+
+    // vertical
+    painter->drawLine(QPointF(translateFactor_.x(),
+                      0),
+                      QPointF(translateFactor_.x(),
+                      sceneRec.height()));
+
+    painter->restore();
+}
+
+/**
+ * Draws subaxes.
+ * @param painter a tool to drawing elements
+ * @param widget points to the widget where elements will be drew
+ */
+void FFChartScene::drawSubAxes(QPainter* painter, QWidget* widget)
+{
+       Q_UNUSED(widget);
+
+       painter->save();
+
+       //draws horizontal lines
+       int subaxesNumber = (int)(sceneRec.height() / subaxesSpacing_);
+       qreal offset = translateFactor_.y() - (qFloor(translateFactor_.y() / subaxesSpacing_)) * subaxesSpacing_;
+
+       painter->setPen(subaxesPen_);
+
+       int i;
+       for(i = 0; i <= subaxesNumber; i++)
+       {
+               painter->drawLine(QPointF(0,
+                                 offset + i * subaxesSpacing_),
+                                 QPointF(sceneRec.width(),
+                                 offset + i * subaxesSpacing_));
+       }
+
+       //draws vertical lines
+       subaxesNumber = (int)(sceneRec.width() / subaxesSpacing_);
+       offset = translateFactor_.x() - (qFloor(translateFactor_.x() / subaxesSpacing_)) * subaxesSpacing_;
+
+       for(i = 0; i <= subaxesNumber; i++)
+       {
+               painter->drawLine(QPointF(offset + i * subaxesSpacing_,
+                                 0),
+                                 QPointF(offset + i * subaxesSpacing_,
+                                 sceneRec.height()));
+       }
+       painter->restore();
+
+}
+
+/**
+ * Draws all series on the chart.
+ * @param painter a tool to drawing elements
+ * @param widget points to the widget where elements will be drew
+ */
+void FFChartScene::drawSeries(QPainter* painter, QWidget* widget)
+{
+       Q_UNUSED(widget)
+
+       //saves old painter
+       painter->save();
+       //sets painter's configuration
+       painter->translate(translateFactor_);
+       painter->scale(accumulatedZoomFactor_.width(),
+                      accumulatedZoomFactor_.height());
+
+       transform = painter->transform();
+       transform.rotate(180, Qt::XAxis);
+       painter->setTransform(transform, false);
+
+       //draws series
+       for(int i = 0; i < series.size(); ++i)
+       {
+               if(!series.at(i)->isVisible())
+               {
+                       continue;
+               }
+
+               painter->setPen(*series.at(i)->pen());
+               painter->drawPolyline(series.at(i)->data(), series.at(i)->size());
+       }
+       //restores paitner
+       painter->restore();
+}
+
+/**
+ * Draws static items (they are not moving and being scaled) on the chart,
+ * e.g. zoom buttons.
+ * @param painter a tool to drawing elements
+ * @param widget points to the widget where elements will be drew
+ */
+void FFChartScene::drawStaticItems(QPainter* painter, QWidget* widget)
+{
+       //draws zoomInButton
+       painter->save();
+       painter->setMatrix(zoomInButton.sceneMatrix(), true);
+       zoomInButton.paint(painter, new QStyleOptionGraphicsItem, widget);
+       painter->restore();
+
+       //draws zoomOutButton
+       painter->save();
+       painter->setMatrix(zoomOutButton.sceneMatrix(), true);
+       zoomOutButton.paint(painter, new QStyleOptionGraphicsItem, widget);
+       painter->restore();
+
+       //draws legendButton
+       painter->save();
+       painter->setMatrix(legendButton.sceneMatrix(), true);
+       legendButton.paint(painter, new QStyleOptionGraphicsItem, widget);
+       painter->restore();
+}
+
+/*
+ * Draws values next to subaxes.
+ * @param painter a tool to drawing elements
+ * @param widget points to the widget where elements will be drew
+ */
+void FFChartScene::drawValues(QPainter* painter, QWidget* widget)
+{
+       Q_UNUSED(widget)
+       //saves painter
+       painter->save();
+
+       //sets painter
+       painter->setPen(axesValuesPen_);
+       painter->setFont(QFont(FONT_TITLE_DEF, 10));
+
+       //sets needed values
+       subaxesSpacing_ *= 2;
+
+       //drawing values of axes
+       int subaxesNumber = (int)(sceneRec.height() / subaxesSpacing_);
+       qreal offset = translateFactor_.y() - (qFloor(translateFactor_.y() / subaxesSpacing_)) * subaxesSpacing_;
+
+       int i;
+
+
+       if(translateFactor_.x() < 0)
+       {
+               for(i = -1; i <= subaxesNumber; i++)
+               {
+                       painter->drawText(QPointF(1, offset + i * subaxesSpacing_ + 11), QString::number((-translateFactor_.y() + offset + i * subaxesSpacing_) / -accumulatedZoomFactor_.height(), 'f', 1));
+               }
+       }
+       else if(translateFactor_.x() > sceneRec.width())
+       {
+               for(i = -1; i <= subaxesNumber; i++)
+               {
+                       painter->drawText(QRectF(sceneRec.width() - 305, offset + i * subaxesSpacing_ + 11, 300, 11), Qt::AlignRight | Qt::AlignVCenter, QString::number((-translateFactor_.y() + offset + i * subaxesSpacing_) / -accumulatedZoomFactor_.height(), 'f', 1));
+               }
+       }
+       else
+       {
+               for(i = -1; i <= subaxesNumber; i++)
+               {
+                       painter->drawText(QPointF(translateFactor_.x() + 1, offset + i * subaxesSpacing_ + 11), QString::number((-translateFactor_.y() + offset + i * subaxesSpacing_) / -accumulatedZoomFactor_.height(), 'f', 1));
+               }
+       }
+
+       subaxesNumber = (int)(sceneRec.width() / subaxesSpacing_);
+       offset = translateFactor_.x() - (qFloor(translateFactor_.x() / subaxesSpacing_)) * subaxesSpacing_;
+
+       if(translateFactor_.y() < 0)
+       {
+               for(i = -1; i <= subaxesNumber; i++)
+               {
+                       painter->drawText(QPointF(offset + i * subaxesSpacing_ + 1, 11), QString::number((-translateFactor_.x() + offset + i * subaxesSpacing_) / accumulatedZoomFactor_.width(), 'f', 1));
+               }
+       }
+       else if(translateFactor_.y() > sceneRec.height())
+       {
+               for(i = -1; i <= subaxesNumber; i++)
+               {
+                       painter->drawText(QPointF(offset + i * subaxesSpacing_ + 1, sceneRec.height() - 5), QString::number((-translateFactor_.x() + offset + i * subaxesSpacing_) / accumulatedZoomFactor_.width(), 'f', 1));
+               }
+       }
+       else
+       {
+               for(i = -1; i <= subaxesNumber; i++)
+               {
+                       painter->drawText(QPointF(offset + i * subaxesSpacing_ + 1, translateFactor_.y() + 11), QString::number((-translateFactor_.x() + offset + i * subaxesSpacing_) / accumulatedZoomFactor_.width(), 'f', 1));
+               }
+       }
+
+       subaxesSpacing_ /= 2;
+
+       painter->restore();
+}
+
+/**
+ * This method is responsible for kinetic scrolling.
+ */
+void FFChartScene::kineticScroll()
+{
+       //check if kinetic mode is active
+       if(kinetic)
+       {
+               translateFactor_ += kineticVec;
+
+               if(qAbs((kineticVec *= 0.8).x()) < 0.5 && qAbs((kineticVec
+                               *= 0.8).y()) < 0.5)
+               {
+                       timer->stop();
+                       kinetic = false;
+               }
+
+               update();
+       }
+       //otherwise updates kinetic's vectors
+       else
+       {
+               oldKineticVec = kineticVec;
+               kineticVec =  pressPos - oldPressPos;
+       }
+}
+
+/*!
+ * \fn void FFChartScene::seriesChanged(QList<FFChartSeries*>*);
+ *
+ * Signal that is emitted when the set of series has changed.
+ */