lib/TrendLine.cpp

Go to the documentation of this file.
00001 /*
00002  *  Qtstalker stock charter
00003  *
00004  *  Copyright (C) 2001-2007 Stefan S. Stratigakos
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00019  *  USA.
00020  */
00021 
00022 #include "TrendLine.h"
00023 #include "PrefDialog.h"
00024 #include "Config.h"
00025 #include <qpainter.h>
00026 
00027 TrendLine::TrendLine ()
00028 {
00029   defaultColor.setNamedColor("red");
00030   usebar = FALSE;
00031   extend = TRUE;
00032   bar = "Close";
00033   helpFile = "trendline.html";
00034   date2 = date;
00035   type = "TrendLine";
00036 
00037   sdateLabel = "Start Date";
00038   edateLabel = "End Date";
00039   svalueLabel = "Start Value";
00040   evalueLabel = "End Value";
00041   fieldLabel = "Bar Field";
00042   usebarLabel = "Use Bar";
00043   extendLabel = "Extend Line";
00044   
00045   loadDefaults();
00046 }
00047 
00048 TrendLine::~TrendLine ()
00049 {
00050 }
00051 
00052 void TrendLine::draw (QPixmap &buffer, Scaler &scaler, int startIndex, int pixelspace, int startX)
00053 {
00054   QPainter painter;
00055   painter.begin(&buffer);
00056   
00057   int x2 = data->getX(date);
00058   if (x2 == -1)
00059     return;
00060 
00061   int x = startX + (x2 * pixelspace) - (startIndex * pixelspace);
00062   if (x == -1)
00063     return;
00064         
00065   x2 = data->getX(date2);
00066   if (x2 == -1)
00067     return;
00068 
00069   x2 = startX + (x2 * pixelspace) - (startIndex * pixelspace);
00070   if (x2 == -1)
00071     return;
00072     
00073   int y;
00074   int y2;
00075   if (getUseBar())
00076   {
00077     int i = data->getX(date);
00078     int i2 = data->getX(date2);
00079 
00080     while (1)
00081     {
00082       if (! bar.compare(tr("Open")))
00083       {
00084         y = scaler.convertToY(data->getOpen(i));
00085         y2 = scaler.convertToY(data->getOpen(i2));
00086         break;
00087       }
00088 
00089       if (! bar.compare(tr("High")))
00090       {
00091         y = scaler.convertToY(data->getHigh(i));
00092         y2 = scaler.convertToY(data->getHigh(i2));
00093         break;
00094       }
00095 
00096       if (! bar.compare(tr("Low")))
00097       {
00098         y = scaler.convertToY(data->getLow(i));
00099         y2 = scaler.convertToY(data->getLow(i2));
00100         break;
00101       }
00102 
00103       if (! bar.compare(tr("Close")))
00104       {
00105         y = scaler.convertToY(data->getClose(i));
00106         y2 = scaler.convertToY(data->getClose(i2));
00107         break;
00108       }
00109 
00110       return;
00111     }
00112   }
00113   else
00114   {
00115     y = scaler.convertToY(getValue());
00116     y2 = scaler.convertToY(getValue2());
00117   }
00118 
00119   painter.setPen(getColor());
00120   painter.drawLine (x, y, x2, y2);
00121 
00122   // save old values;
00123   int tx2 = x2;
00124   int ty2 = y2;
00125   int tx = x;
00126   int ty = y;
00127 
00128   if (getExtend())
00129   {  
00130     int ydiff = y - y2;
00131     int xdiff = x2 - x;
00132     while (x2 < buffer.width())
00133     {
00134       x = x2;
00135       y = y2;
00136       x2 = x2 + xdiff;
00137       y2 = y2 - ydiff;
00138       painter.drawLine (x, y, x2, y2);
00139     }
00140   }
00141 
00142   // store the selectable area the line occupies
00143   clearSelectionArea();
00144   QPointArray array;
00145   array.putPoints(0, 4, tx, ty - 4, tx, ty + 4, x2, y2 + 4, x2, y2 - 4);
00146   setSelectionArea(new QRegion(array));
00147     
00148   if (getStatus() == COBase::Selected)
00149   {
00150     clearGrabHandles();
00151     
00152     setGrabHandle(new QRegion(tx,
00153                   ty - (HANDLE_WIDTH / 2),
00154                   HANDLE_WIDTH,
00155                   HANDLE_WIDTH,
00156                   QRegion::Rectangle));
00157     painter.fillRect(tx, ty - (HANDLE_WIDTH / 2), HANDLE_WIDTH, HANDLE_WIDTH, getColor());
00158       
00159     setGrabHandle(new QRegion(tx2,
00160                   ty2 - (HANDLE_WIDTH / 2),
00161                   HANDLE_WIDTH,
00162                   HANDLE_WIDTH,
00163                   QRegion::Rectangle));
00164     painter.fillRect(tx2, ty2 - (HANDLE_WIDTH / 2), HANDLE_WIDTH, HANDLE_WIDTH, getColor());
00165   }
00166 
00167   painter.end();
00168 }
00169 
00170 void TrendLine::prefDialog ()
00171 {
00172   QStringList l;
00173   l.append(tr("Open"));
00174   l.append(tr("High"));
00175   l.append(tr("Low"));
00176   l.append(tr("Close"));
00177 
00178   QString pl = tr("Details");
00179   QString cl = tr("Color");
00180   QString sd = tr("Set Default");
00181   QString ub = tr("Use Bar");
00182   QString el = tr("Extend Line");
00183   QString bf = tr("Bar Field");
00184   QString sl = tr("Start Value");
00185   QString dl = tr("End Value");
00186   
00187   PrefDialog *dialog = new PrefDialog();
00188   dialog->setCaption(tr("Edit TrendLine"));
00189   dialog->createPage (pl);
00190   dialog->setHelpFile (helpFile);
00191   dialog->addColorPrefItem(cl, pl, color);
00192   dialog->addComboItem(bf, pl, l, bar);
00193   dialog->addCheckItem(ub, pl, usebar);
00194   dialog->addCheckItem(el, pl, extend);
00195   dialog->addDoubleItem(sl, pl, getValue());
00196   dialog->addDoubleItem(dl, pl, getValue2());
00197   dialog->addCheckItem(sd, pl, FALSE);
00198   
00199   int rc = dialog->exec();
00200   
00201   if (rc == QDialog::Accepted)
00202   {
00203     dialog->getColor(cl, color);
00204     dialog->getCombo(bf, bar);
00205     usebar = dialog->getCheck(ub);
00206     extend = dialog->getCheck(el);
00207     setValue(dialog->getDouble(sl));
00208     setValue2(dialog->getDouble(dl));
00209     
00210     setSaveFlag(TRUE);
00211     
00212     bool f = dialog->getCheck(sd);
00213     if (f)
00214     {
00215       dialog->getColor(cl, defaultColor);
00216       dialog->getCombo(bf, bar);
00217       usebar = dialog->getCheck(ub);
00218       extend = dialog->getCheck(el);
00219       
00220       saveDefaults();
00221     }
00222     
00223     emit signalDraw();
00224   }
00225   
00226   delete dialog;
00227 }
00228 
00229 void TrendLine::newObject (QString &ind, QString &n)
00230 {
00231   indicator = ind;
00232   plot = ind;
00233   name = n;
00234   mpx2 = -1;
00235   mpy2 = -1;
00236   status = ClickWait;
00237   emit message(tr("Select TrendLine starting point..."));
00238 }
00239 
00240 COBase::Status TrendLine::pointerClick (QPoint &point, QDateTime &x, double y)
00241 {
00242   switch (status)
00243   {
00244     case None:
00245       if (isSelected(point))
00246       {
00247         status = Selected;
00248         emit signalDraw();
00249       }
00250       break;
00251     case Selected:
00252       moveFlag = isGrabSelected(point);
00253       if (moveFlag)
00254         status = Moving;
00255       else
00256       {
00257         if (! isSelected(point))
00258         {
00259           status = None;
00260           emit signalDraw();
00261         }
00262       }
00263       break;
00264     case Moving:
00265       status = Selected;
00266       break;
00267     case ClickWait:
00268       tx = x;
00269       ty = y;
00270       mpx = point.x();
00271       mpy = point.y();
00272       status = ClickWait2;
00273       emit message(tr("Select TrendLine ending point..."));
00274       break;
00275     case ClickWait2:
00276       if (x <= tx)
00277         break;
00278   
00279       setDate(tx);
00280       setDate2(x);
00281       setValue(ty);
00282       setValue2(y);
00283 
00284       setSaveFlag(TRUE);
00285       setColor(defaultColor);
00286       emit signalDraw();
00287       status = None;
00288       emit message("");
00289       emit signalSave(name);
00290       break;
00291     default:
00292       break;
00293   }
00294 
00295   return status;    
00296 }
00297 
00298 void TrendLine::pointerMoving (QPixmap &buffer, QPoint &point, QDateTime &x, double y)
00299 {
00300   if (status == ClickWait2)
00301   {
00302     drawMovingPointer(buffer, point);
00303     return;
00304   }
00305   
00306   if (! moveFlag || status != Moving)
00307     return;
00308     
00309   if (moveFlag == 1)
00310   {
00311     if (x >= date2)
00312       return;
00313     
00314     setDate(x);
00315     setValue(y);
00316     setSaveFlag(TRUE);
00317     emit signalDraw();
00318     QString s = x.toString("yyyy-MM-dd hh:mm:ss") + " " + QString::number(y);
00319     emit message(s);
00320   }
00321   else
00322   {
00323     if (x <= date)
00324       return;
00325     
00326     setDate2(x);
00327     setValue2(y);
00328     setSaveFlag(TRUE);
00329     emit signalDraw();
00330     
00331     QString s = x.toString("yyyy-MM-dd hh:mm:ss") + " " + QString::number(y);
00332     emit message(s);
00333   }
00334 }
00335 
00336 void TrendLine::drawMovingPointer (QPixmap &buffer, QPoint &point)
00337 {
00338   if (point.x() < mpx)
00339     return;
00340 
00341   QPainter painter;
00342   painter.begin(&buffer);
00343   painter.setRasterOp(Qt::XorROP);
00344   painter.setPen(defaultColor);
00345       
00346   // erase the previous line drawn
00347   if (mpx2 != -1 && mpy2 != -1)
00348     painter.drawLine (mpx, mpy, mpx2, mpy2);
00349       
00350   // draw the new line
00351   painter.drawLine (mpx, mpy, point.x(), point.y());
00352       
00353   mpx2 = point.x();
00354   mpy2 = point.y();
00355   
00356   painter.end();
00357   
00358   emit signalRefresh();
00359 }
00360 
00361 void TrendLine::loadDefaults ()
00362 {
00363   Config settings;
00364   QString s2 = "DefaultTrendLineColor";
00365   QString s;
00366   settings.getData(s2, s);
00367   if (s.length())
00368     defaultColor.setNamedColor(s);
00369 
00370   s2 = "DefaultTrendLineBar";
00371   settings.getData(s2, s);
00372   if (s.length())
00373     bar = s;
00374 
00375   s2 = "DefaultTrendLineExtend";
00376   settings.getData(s2, s);
00377   if (s.length())
00378     extend = s.toInt();
00379 
00380   s2 = "DefaultTrendLineUseBar";
00381   settings.getData(s2, s);
00382   if (s.length())
00383     usebar = s.toInt();
00384 }
00385 
00386 void TrendLine::saveDefaults ()
00387 {
00388   Config config;
00389   
00390   QString s = "DefaultTrendLineColor";
00391   QString s2 = defaultColor.name();
00392   config.setData(s, s2);
00393 
00394   s = "DefaultTrendLineBar";
00395   config.setData(s, bar);
00396 
00397   s = "DefaultTrendLineExtend";
00398   s2 = QString::number(extend);
00399   config.setData(s, s2);
00400 
00401   s = "DefaultTrendLineUseBar";
00402   s2 = QString::number(usebar);
00403   config.setData(s, s2);
00404 }
00405 
00406 double TrendLine::getHigh ()
00407 {
00408   double high = -99999999.0;
00409 
00410   if (getValue() > high)
00411       high = getValue();
00412   if (getValue2() > high)
00413       high = getValue2();
00414   
00415   return high;
00416 }
00417 
00418 double TrendLine::getLow ()
00419 {
00420   double low = 99999999.0;
00421   
00422   if (getValue() < low)
00423     low = getValue();
00424   if (getValue2() < low)
00425     low = getValue2();
00426 
00427   return low;
00428 }
00429 
00430 void TrendLine::setDate2 (QDateTime &d)
00431 {
00432   date2 = d;
00433 }
00434 
00435 void TrendLine::getDate2 (QDateTime &d)
00436 {
00437   d = date2;
00438 }
00439 
00440 void TrendLine::setValue2 (double d)
00441 {
00442   value2 = d;
00443 }
00444 
00445 double TrendLine::getValue2 ()
00446 {
00447   return value2;
00448 }
00449 
00450 int TrendLine::isGrabSelected (QPoint point)
00451 {
00452   int loop;
00453   for (loop = 0; loop < (int) grabHandles.count(); loop++)
00454   {
00455     QRegion *r = grabHandles.at(loop);
00456     if (r->contains(point))
00457       return loop + 1;
00458   }
00459   
00460   return 0;
00461 }
00462 
00463 void TrendLine::getSettings (Setting &set)
00464 {
00465   QString s = date.toString(dateFormat);
00466   set.setData(sdateLabel, s);
00467   s = date2.toString(dateFormat);
00468   set.setData(edateLabel, s);
00469   s = QString::number(value);
00470   set.setData(svalueLabel, s);
00471   s = QString::number(value2);
00472   set.setData(evalueLabel, s);
00473   set.setData(fieldLabel, bar);
00474   s = QString::number(usebar);
00475   set.setData(usebarLabel, s);
00476   s = QString::number(extend);
00477   set.setData(extendLabel, s);
00478   s = color.name();
00479   set.setData(colorLabel, s);
00480   set.setData(plotLabel, plot);
00481   set.setData(nameLabel, name);
00482   set.setData(typeLabel, type);
00483 }
00484 
00485 void TrendLine::setSettings (Setting &set)
00486 {
00487   QString s;
00488   set.getData(colorLabel, s);
00489   color.setNamedColor(s);
00490   set.getData(sdateLabel, s);
00491   Bar b;
00492   b.setDate(s);
00493   b.getDate(date);
00494   set.getData(edateLabel, s);
00495   b.setDate(s);
00496   b.getDate(date2);
00497   value = set.getDouble(svalueLabel);
00498   value2 = set.getDouble(evalueLabel);
00499   set.getData(fieldLabel, bar);
00500   usebar = set.getInt(usebarLabel);
00501   extend = set.getInt(extendLabel);
00502   set.getData(plotLabel, plot);
00503   set.getData(nameLabel, name);
00504 }
00505 
00506 bool TrendLine::getUseBar ()
00507 {
00508   return usebar;
00509 }
00510 
00511 void TrendLine::getBar (QString &d)
00512 {
00513   d = bar;
00514 }
00515 
00516 bool TrendLine::getExtend ()
00517 {
00518   return extend;
00519 }
00520 
00521 void TrendLine::adjustForSplit (QDateTime &dt, double d)
00522 {
00523   if (date < dt)
00524     value = value * d;
00525   if (date2 < dt)
00526     value2 = value2 * d;
00527 }
00528 
00529