lib/FiboLine.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 "FiboLine.h"
00023 #include "PrefDialog.h"
00024 #include "Config.h"
00025 #include <qpainter.h>
00026 #include <qsettings.h>
00027 
00028 FiboLine::FiboLine ()
00029 {
00030   defaultColor.setNamedColor("red");
00031   helpFile = "fiboline.html";
00032   extend = FALSE;
00033   line1 = 0.382;
00034   line2 = 0.5;
00035   line3 = 0.618;
00036   line4 = 0;
00037   line5 = 0;
00038   line6 = 0;
00039   startDate = QDateTime::currentDateTime();
00040   endDate = startDate;
00041   type = "FiboLine";
00042 
00043   highLabel = "High";
00044   lowLabel = "Low";
00045   sdateLabel = "Start Date";
00046   edateLabel = "End Date";
00047   l1Label = "Line 1";
00048   l2Label = "Line 2";
00049   l3Label = "Line 3";
00050   l4Label = "Line 4";
00051   l5Label = "Line 5";
00052   l6Label = "Line 6";
00053   extendLabel = "Extend";
00054 
00055   Config config;
00056   QString s;
00057   config.getData(Config::PlotFont, s);
00058   QStringList l = QStringList::split(",", s, FALSE);
00059   QFont f(l[0], l[1].toInt(), l[2].toInt());
00060   font = f;
00061     
00062   loadDefaults();
00063 }
00064 
00065 FiboLine::~FiboLine ()
00066 {
00067 }
00068 
00069 void FiboLine::draw (QPixmap &buffer, Scaler &scaler, int startIndex, int pixelspace, int startX)
00070 {
00071   QPainter painter;
00072   painter.begin(&buffer);
00073   painter.setFont(font);
00074   
00075   int x2 = data->getX(startDate);
00076   if (x2 == -1)
00077     return;
00078 
00079   int x = startX + (x2 * pixelspace) - (startIndex * pixelspace);
00080   if (x == -1)
00081     return;
00082         
00083   QDateTime dt = endDate;
00084   if (extend)
00085     data->getDate(data->count() - 1, dt);
00086     
00087   x2 = data->getX(dt);
00088   if (x2 == -1)
00089     return;
00090 
00091   x2 = startX + (x2 * pixelspace) - (startIndex * pixelspace);
00092   if (x2 == -1)
00093     return;
00094     
00095   painter.setPen(getColor());
00096   
00097   QPointArray array;
00098   clearSelectionArea();
00099     
00100   int loop;
00101   for (loop = 1; loop <= 6; loop++)
00102   {
00103     if (getLine(loop) != 0)
00104     {
00105       double r = getY(getLine(loop), getHigh(), getLow());
00106       int y = scaler.convertToY(r);
00107       painter.drawLine (x, y, x2, y);
00108       painter.drawText(x, y - 1, QString::number(getLine(loop) * 100) + "% - " + QString::number(r), -1);
00109         
00110       array.putPoints(0, 4, x, y - 4, x, y + 4, x2, y + 4, x2, y - 4);
00111       setSelectionArea(new QRegion(array));
00112     }
00113   }
00114   
00115   // draw the low line
00116   int y = scaler.convertToY(getLow());
00117   painter.drawLine (x, y, x2, y);
00118   // if (co->getStatus() == FiboLineObject::Selected)
00119   painter.drawText(x, y - 1, "0% - " + QString::number(getLow()), -1);
00120 
00121   // store the selectable area the low line occupies
00122   array.putPoints(0, 4, x, y - 4, x, y + 4, x2, y + 4, x2, y - 4);
00123   setSelectionArea(new QRegion(array));
00124     
00125   // draw the high line
00126   int y2 = scaler.convertToY(getHigh());
00127   painter.drawLine (x, y2, x2, y2);
00128   // if (co->getStatus() == FiboLineObject::Selected)
00129   painter.drawText(x, y2 - 1, "100% - " + QString::number(getHigh()), -1);
00130 
00131   // store the selectable area the high line occupies
00132   array.putPoints(0, 4, x, y2 - 4, x, y2 + 4, x2, y2 + 4, x2, y2 - 4);
00133   setSelectionArea(new QRegion(array));
00134     
00135   if (getStatus() == COBase::Selected)
00136   {
00137     clearGrabHandles();
00138     
00139     //bottom left corner
00140     y = scaler.convertToY(getLow());
00141     setGrabHandle(new QRegion(x,
00142                               y - (HANDLE_WIDTH / 2),
00143                               HANDLE_WIDTH,
00144                               HANDLE_WIDTH,
00145                               QRegion::Rectangle));
00146     painter.fillRect(x, y - (HANDLE_WIDTH / 2), HANDLE_WIDTH, HANDLE_WIDTH, getColor());
00147     
00148     //top right corner
00149     y2 = scaler.convertToY(getHigh());
00150     setGrabHandle(new QRegion(x2,
00151                               y2 - (HANDLE_WIDTH / 2),
00152                               HANDLE_WIDTH,
00153                               HANDLE_WIDTH,
00154                               QRegion::Rectangle));
00155     painter.fillRect(x2, y2 - (HANDLE_WIDTH / 2), HANDLE_WIDTH, HANDLE_WIDTH, getColor());
00156   }
00157 
00158   painter.end();
00159 }
00160 
00161 double FiboLine::getY (double v, double high, double low)
00162 {
00163   double range = high - low;
00164   double r = 0;
00165   if (v < 0)
00166     r = low + (range * v);
00167   else
00168   {
00169     if (v > 0)
00170       r = low + (range * v);
00171     else
00172     {
00173       if (v < 0)
00174         r = high;
00175       else
00176         r = low;
00177     }
00178   }
00179 
00180   return r;
00181 }
00182 
00183 void FiboLine::prefDialog ()
00184 {
00185   QString pl = tr("Details");
00186   QString cl = tr("Color");
00187   QString sd = tr("Set Default");
00188   QString l1 = tr("Line 1");
00189   QString l2 = tr("Line 2");
00190   QString l3 = tr("Line 3");
00191   QString l4 = tr("Line 4");
00192   QString l5 = tr("Line 5");
00193   QString l6 = tr("Line 6");
00194   QString hl = tr("High");
00195   QString ll = tr("Low");
00196   QString el = tr("Extend");
00197 
00198   PrefDialog *dialog = new PrefDialog();
00199   dialog->setCaption(tr("Edit FiboLine"));
00200   dialog->createPage (pl);
00201   dialog->setHelpFile (helpFile);
00202   dialog->addColorPrefItem(cl, pl, color);
00203   dialog->addDoubleItem(hl, pl, getHigh());
00204   dialog->addDoubleItem(ll, pl, getLow());
00205   dialog->addCheckItem(el, pl, extend);
00206   dialog->addCheckItem(sd, pl, FALSE);
00207 
00208   pl = tr("Levels");
00209   dialog->createPage (pl);
00210   dialog->addDoubleItem(l1, pl, getLine(1));
00211   dialog->addDoubleItem(l2, pl, getLine(2));
00212   dialog->addDoubleItem(l3, pl, getLine(3));
00213   dialog->addDoubleItem(l4, pl, getLine(4));
00214   dialog->addDoubleItem(l5, pl, getLine(5));
00215   dialog->addDoubleItem(l6, pl, getLine(6));
00216     
00217   int rc = dialog->exec();
00218   
00219   if (rc == QDialog::Accepted)
00220   {
00221     dialog->getColor(cl, color);
00222     line1 = dialog->getDouble(l1);
00223     line2 = dialog->getDouble(l2);
00224     line3 = dialog->getDouble(l3);
00225     line4 = dialog->getDouble(l4);
00226     line5 = dialog->getDouble(l5);
00227     line6 = dialog->getDouble(l6);
00228     high = dialog->getDouble(hl);
00229     low = dialog->getDouble(ll);
00230     extend = dialog->getCheck(el);
00231     
00232     setSaveFlag(TRUE);
00233     
00234     bool f = dialog->getCheck(sd);
00235     if (f)
00236     {
00237       dialog->getColor(cl, defaultColor);
00238       line1 = dialog->getDouble(l1);
00239       line2 = dialog->getDouble(l2);
00240       line3 = dialog->getDouble(l3);
00241       line4 = dialog->getDouble(l4);
00242       line5 = dialog->getDouble(l5);
00243       line6 = dialog->getDouble(l6);
00244       
00245       saveDefaults();
00246     }
00247     
00248     emit signalDraw();
00249   }
00250   
00251   delete dialog;
00252 }
00253 
00254 void FiboLine::newObject (QString &ind, QString &n)
00255 {
00256   indicator = ind;
00257   plot = ind;
00258   name = n;
00259   mpx2 = -1;
00260   mpy2 = -1;
00261   status = ClickWait;
00262   emit message(tr("Select FiboLine high point..."));
00263 }
00264 
00265 COBase::Status FiboLine::pointerClick (QPoint &point, QDateTime &x, double y)
00266 {
00267   switch (status)
00268   {
00269     case None:
00270       if (isSelected(point))
00271       {
00272         status = Selected;
00273         emit signalDraw();
00274       }
00275       break;
00276     case Selected:
00277       moveFlag = isGrabSelected(point);
00278       if (moveFlag)
00279         status = Moving;
00280       else
00281       {
00282         if (! isSelected(point))
00283         {
00284           status = None;
00285           emit signalDraw();
00286         }
00287       }
00288       break;
00289     case Moving:
00290       status = Selected;
00291       break;
00292     case ClickWait:
00293       tx = x;
00294       ty = y;
00295       mpx = point.x();
00296       mpy = point.y();
00297       status = ClickWait2;
00298       emit message(tr("Select FiboLine low point..."));
00299       break;
00300     case ClickWait2:
00301       if (x <= tx)
00302         break;
00303       if (y >= ty)
00304         break;
00305     
00306       startDate = tx;
00307       endDate = x;
00308       high = ty;
00309       low = y;
00310 
00311       setSaveFlag(TRUE);
00312       setColor(defaultColor);
00313       emit signalDraw();
00314       status = None;
00315       emit message("");
00316       emit signalSave(name);
00317       break;
00318     default:
00319       break;
00320   }
00321 
00322   return status;    
00323 }
00324 
00325 void FiboLine::pointerMoving (QPixmap &buffer, QPoint &point, QDateTime &x, double y)
00326 {
00327   if (status == ClickWait2)
00328   {
00329     drawMovingPointer(buffer, point);
00330     return;
00331   }
00332   
00333   if (! moveFlag || status != Moving)
00334     return;
00335     
00336   if (moveFlag == 1)
00337   {
00338     // bottom left corner
00339     if (x >= endDate)
00340       return;
00341     
00342     if (y >= getHigh())
00343       return;
00344 
00345     startDate = x;
00346     low = y;
00347     setSaveFlag(TRUE);
00348     
00349     emit signalDraw();
00350     
00351     QString s = x.toString("yyyy-MM-dd hh:mm:ss") + " " + QString::number(y);
00352     emit message(s);
00353   }
00354   else
00355   {
00356     //top right corner
00357     if (x <= startDate)
00358       return;
00359 
00360     if (y <= getLow())
00361       return;
00362 
00363     endDate = x;
00364     high = y;
00365     setSaveFlag(TRUE);
00366     
00367     emit signalDraw();
00368     
00369     QString s = x.toString("yyyy-MM-dd hh:mm:ss") + " " + QString::number(y);
00370     emit message(s);
00371   }
00372 }
00373 
00374 void FiboLine::drawMovingPointer (QPixmap &buffer, QPoint &point)
00375 {
00376   if (point.x() < mpx)
00377     return;
00378 
00379   if (point.y() < mpy)
00380     return;
00381   
00382   QPainter painter;
00383   painter.begin(&buffer);
00384   painter.setRasterOp(Qt::XorROP);
00385   painter.setPen(defaultColor);
00386       
00387   // erase the previous line drawn
00388   if (mpx2 != -1 && mpy2 != -1)
00389   {
00390     painter.drawLine (mpx, mpy, mpx2, mpy);
00391     painter.drawLine (mpx, mpy2, mpx2, mpy2);
00392   }
00393       
00394   // draw the new line
00395   painter.drawLine (mpx, mpy, point.x(), mpy);
00396   painter.drawLine (mpx, point.y(), point.x(), point.y());
00397         
00398   mpx2 = point.x();
00399   mpy2 = point.y();
00400   
00401   painter.end();
00402   
00403   emit signalRefresh();
00404 }
00405 
00406 void FiboLine::loadDefaults ()
00407 {
00408   QSettings settings;
00409   
00410   QString s = "/Qtstalker/DefaultFiboLineColor";
00411   s = settings.readEntry(s);
00412   if (s.length())
00413     defaultColor.setNamedColor(s);
00414 
00415   s = "/Qtstalker/DefaultFiboLine1";
00416   s = settings.readEntry(s);
00417   if (s.length())
00418     line1 = s.toFloat();
00419 
00420   s = "/Qtstalker/DefaultFiboLine2";
00421   s = settings.readEntry(s);
00422   if (s.length())
00423     line2 = s.toFloat();
00424 
00425   s = "/Qtstalker/DefaultFiboLine3";
00426   s = settings.readEntry(s);
00427   if (s.length())
00428     line3 = s.toFloat();
00429 
00430   s = "/Qtstalker/DefaultFiboLine4";
00431   s = settings.readEntry(s);
00432   if (s.length())
00433     line4 = s.toFloat();
00434 
00435   s = "/Qtstalker/DefaultFiboLine5";
00436   s = settings.readEntry(s);
00437   if (s.length())
00438     line5 = s.toFloat();
00439 
00440   s = "/Qtstalker/DefaultFiboLine6";
00441   s = settings.readEntry(s);
00442   if (s.length())
00443     line6 = s.toFloat();
00444 }
00445 
00446 void FiboLine::saveDefaults ()
00447 {
00448   QSettings settings;
00449   
00450   QString s = "/Qtstalker/DefaultFiboLineColor";
00451   settings.writeEntry(s, defaultColor.name());
00452 
00453   s = "/Qtstalker/DefaultFiboLine1";
00454   settings.writeEntry(s, QString::number(line1));
00455 
00456   s = "/Qtstalker/DefaultFiboLine2";
00457   settings.writeEntry(s, QString::number(line2));
00458 
00459   s = "/Qtstalker/DefaultFiboLine3";
00460   settings.writeEntry(s, QString::number(line3));
00461 
00462   s = "/Qtstalker/DefaultFiboLine4";
00463   settings.writeEntry(s, QString::number(line4));
00464 
00465   s = "/Qtstalker/DefaultFiboLine5";
00466   settings.writeEntry(s, QString::number(line5));
00467 
00468   s = "/Qtstalker/DefaultFiboLine6";
00469   settings.writeEntry(s, QString::number(line6));
00470 }
00471 
00472 double FiboLine::getHigh ()
00473 {
00474   return high;
00475 }
00476 
00477 double FiboLine::getLow ()
00478 {
00479   return low;
00480 }
00481 
00482 void FiboLine::getSettings (Setting &set)
00483 {
00484   QString s = color.name();
00485   set.setData(colorLabel, s);
00486   set.setData(plotLabel, plot);
00487   set.setData(nameLabel, name);
00488   s = QString::number(high);
00489   set.setData(highLabel, s);
00490   s = QString::number(low);
00491   set.setData(lowLabel, s);
00492   s = startDate.toString(dateFormat);
00493   set.setData(sdateLabel, s);
00494   s = endDate.toString(dateFormat);
00495   set.setData(edateLabel, s);
00496   s = QString::number(line1);
00497   set.setData(l1Label, s);
00498   s = QString::number(line2);
00499   set.setData(l2Label, s);
00500   s = QString::number(line3);
00501   set.setData(l3Label, s);
00502   s = QString::number(line4);
00503   set.setData(l4Label, s);
00504   s = QString::number(line5);
00505   set.setData(l5Label, s);
00506   s = QString::number(line6);
00507   set.setData(l6Label, s);
00508   s = QString::number(extend);
00509   set.setData(extendLabel, s);
00510   set.setData(typeLabel, type);
00511 }
00512 
00513 void FiboLine::setSettings (Setting &set)
00514 {
00515   QString s;
00516   set.getData(colorLabel, s);
00517   color.setNamedColor(s);
00518   set.getData(plotLabel, plot);
00519   set.getData(nameLabel, name);
00520   high = set.getDouble(highLabel);
00521   low = set.getDouble(lowLabel);
00522   set.getData(sdateLabel, s);
00523   Bar bar;
00524   bar.setDate(s);
00525   bar.getDate(startDate);
00526   set.getData(edateLabel, s);
00527   bar.setDate(s);
00528   bar.getDate(endDate);
00529   line1 = set.getDouble(l1Label);
00530   line2 = set.getDouble(l2Label);
00531   line3 = set.getDouble(l3Label);
00532   line4 = set.getDouble(l4Label);
00533   line5 = set.getDouble(l5Label);
00534   line6 = set.getDouble(l6Label);
00535   extend = set.getInt(extendLabel);
00536 }
00537 
00538 int FiboLine::isGrabSelected (QPoint point)
00539 {
00540   int loop;
00541   for (loop = 0; loop < (int) grabHandles.count(); loop++)
00542   {
00543     QRegion *r = grabHandles.at(loop);
00544     if (r->contains(point))
00545       return loop + 1;
00546   }
00547   
00548   return 0;
00549 }
00550 
00551 double FiboLine::getLine (int i)
00552 {
00553   double v = 0.0;
00554   
00555   switch (i)
00556   {
00557     case 1:
00558       v = line1;
00559       break;
00560     case 2:
00561       v = line2;
00562       break;
00563     case 3:
00564       v = line3;
00565       break;
00566     case 4:
00567       v = line4;
00568       break;
00569     case 5:
00570       v = line5;
00571       break;
00572     case 6:
00573       v = line6;
00574       break;
00575     default:
00576       break;
00577   }
00578   
00579   return v;
00580 }
00581 
00582 void FiboLine::adjustForSplit (QDateTime &dt, double d)
00583 {
00584   if (startDate < dt && endDate < dt)
00585   {
00586     high = high * d;
00587     low = low * d;
00588   }
00589 }
00590