00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "IndicatorPlot.h"
00023 #include "DbPlugin.h"
00024 #include "PrefDialog.h"
00025 #include "HelpWindow.h"
00026 #include "RcFile.h"
00027 #include <qpainter.h>
00028 #include <qpen.h>
00029 #include <qpoint.h>
00030 #include <qpointarray.h>
00031 #include <qcursor.h>
00032 #include <math.h>
00033 #include <qprinter.h>
00034 #include <qpaintdevicemetrics.h>
00035 #include <qimage.h>
00036 #include <qmessagebox.h>
00037 #include <qinputdialog.h>
00038 #include <qdir.h>
00039
00040
00041 #include <math.h>
00042
00043 #include "../pics/indicator.xpm"
00044 #include "../pics/edit.xpm"
00045 #include "../pics/delete.xpm"
00046 #include "../pics/co.xpm"
00047 #include "../pics/print.xpm"
00048 #include "../pics/loggrid.xpm"
00049 #include "../pics/date.xpm"
00050 #include "../pics/buyarrow.xpm"
00051 #include "../pics/arc.xpm"
00052 #include "../pics/fib.xpm"
00053 #include "../pics/horizontal.xpm"
00054 #include "../pics/sellarrow.xpm"
00055 #include "../pics/text.xpm"
00056 #include "../pics/trend.xpm"
00057 #include "../pics/vertical.xpm"
00058 #include "../pics/help.xpm"
00059
00060 IndicatorPlot::IndicatorPlot (QWidget *w, DBIndex *i) : QWidget(w)
00061 {
00062 chartIndex = i;
00063 setBackgroundMode(NoBackground);
00064 startX = 2;
00065 backgroundColor.setNamedColor("black");
00066 borderColor.setNamedColor("white");
00067 gridColor.setNamedColor("#626262");
00068 pixelspace = 0;
00069 gridFlag = TRUE;
00070 interval = BarData::DailyBar;
00071 scaleToScreen = FALSE;
00072 logScale = FALSE;
00073 startIndex = 0;
00074 mouseFlag = None;
00075 crossHairFlag = FALSE;
00076 chartMenu = 0;
00077 drawMode = FALSE;
00078 crosshairs = TRUE;
00079 infoFlag = TRUE;
00080 coSelected = 0;
00081 dateFlag = TRUE;
00082 menuFlag = TRUE;
00083
00084 plotFont.setFamily("Helvetica");
00085 plotFont.setPointSize(12);
00086 plotFont.setWeight(50);
00087 plotFontMetrics = new QFontMetrics(plotFont);
00088
00089 indy = 0;
00090 data = 0;
00091
00092 chartMenu = new QPopupMenu();
00093
00094 setMouseTracking(TRUE);
00095
00096 setFocusPolicy(QWidget::ClickFocus);
00097
00098 coList.setAutoDelete(TRUE);
00099 }
00100
00101 IndicatorPlot::~IndicatorPlot ()
00102 {
00103 delete chartMenu;
00104 config.closePlugins();
00105 }
00106
00107 void IndicatorPlot::clear ()
00108 {
00109 saveChartObjects();
00110
00111 if (indy)
00112 {
00113 delete indy;
00114 indy = 0;
00115 }
00116
00117 data = 0;
00118 mouseFlag = None;
00119 crossHairFlag = FALSE;
00120
00121 coList.clear();
00122 }
00123
00124 void IndicatorPlot::setData (BarData *l)
00125 {
00126 if (! l->count())
00127 return;
00128
00129 data = l;
00130 }
00131
00132 void IndicatorPlot::setScaleToScreen (bool d)
00133 {
00134 scaleToScreen = d;
00135 }
00136
00137 void IndicatorPlot::setLogScale (bool d)
00138 {
00139 logScale = d;
00140 }
00141
00142 void IndicatorPlot::setDateFlag (bool d)
00143 {
00144 dateFlag = d;
00145 }
00146
00147 void IndicatorPlot::setChartPath (QString &d)
00148 {
00149 chartPath = d;
00150 }
00151
00152 void IndicatorPlot::setDrawMode (bool d)
00153 {
00154 drawMode = d;
00155
00156 if (drawMode)
00157 setCursor(QCursor(ArrowCursor));
00158 else
00159 setCursor(QCursor(CrossCursor));
00160
00161 if (! drawMode && mouseFlag == COSelected && coSelected)
00162 {
00163 QPoint p(-1, -1);
00164 coSelected->pointerClick(p, x1, y1);
00165 mouseFlag = None;
00166 }
00167 }
00168
00169 void IndicatorPlot::setInfoFlag (bool d)
00170 {
00171 infoFlag = d;
00172 }
00173
00174 void IndicatorPlot::setInterval (BarData::BarLength d)
00175 {
00176 interval = d;
00177 }
00178
00179 void IndicatorPlot::draw ()
00180 {
00181 buffer.fill(backgroundColor);
00182
00183 if (data)
00184 {
00185 if (! indy)
00186 {
00187 paintEvent(0);
00188 return;
00189 }
00190
00191 setScale();
00192 drawXGrid();
00193 drawYGrid();
00194 drawInfo();
00195 drawLines();
00196 drawObjects();
00197 drawCrossHair();
00198
00199 }
00200
00201 paintEvent(0);
00202
00203 emit signalDraw();
00204 }
00205
00206 void IndicatorPlot::drawRefresh ()
00207 {
00208 paintEvent(0);
00209 }
00210
00211 void IndicatorPlot::drawLines ()
00212 {
00213 if (! indy->getEnable())
00214 return;
00215
00216 int loop;
00217 for (loop = 0; loop < indy->getLines(); loop++)
00218 {
00219 currentLine = indy->getLine(loop);
00220
00221 if (! currentLine->getSize())
00222 continue;
00223
00224 switch (currentLine->getType())
00225 {
00226 case PlotLine::Histogram:
00227 drawHistogram();
00228 break;
00229 case PlotLine::HistogramBar:
00230 drawHistogramBar();
00231 break;
00232 case PlotLine::Dot:
00233 drawDot();
00234 break;
00235 case PlotLine::Line:
00236 case PlotLine::Dash:
00237 drawLine();
00238 break;
00239 case PlotLine::Horizontal:
00240 drawHorizontalLine();
00241 break;
00242 case PlotLine::Bar:
00243 drawBar();
00244 break;
00245 case PlotLine::Candle:
00246 drawCandle();
00247 break;
00248 case PlotLine::PF:
00249 drawPF();
00250 break;
00251 default:
00252 break;
00253 }
00254 }
00255 }
00256
00257 void IndicatorPlot::paintEvent (QPaintEvent *)
00258 {
00259 bitBlt(this, 0, 0, &buffer);
00260 }
00261
00262 void IndicatorPlot::resizeEvent (QResizeEvent *event)
00263 {
00264 buffer.resize(event->size());
00265 draw();
00266 }
00267
00268 void IndicatorPlot::mousePressEvent (QMouseEvent *event)
00269 {
00270 if (! indy || ! data)
00271 return;
00272
00273 if (! drawMode)
00274 {
00275 if (event->button() == LeftButton)
00276 {
00277 if (crosshairs)
00278 {
00279 crossHair(event->x(), event->y(), TRUE);
00280 updateStatusBar(event->x(), event->y());
00281 emit leftMouseButton(event->x(), event->y(), 0);
00282 }
00283 else
00284 updateStatusBar(event->x(), event->y());
00285 return;
00286 }
00287 }
00288
00289 if (event->button() == LeftButton)
00290 {
00291 getXY(event->x(), event->y());
00292
00293 if (mouseFlag == None)
00294 {
00295 QDictIterator<COBase> it(coList);
00296 for (; it.current(); ++it)
00297 {
00298 coSelected = it.current();
00299 QPoint p(event->x(), event->y());
00300 COBase::Status rc = coSelected->pointerClick(p, x1, y1);
00301 if (rc != COBase::None)
00302 {
00303 mouseFlag = COSelected;
00304 return;
00305 }
00306 }
00307 }
00308
00309 if (mouseFlag == COSelected)
00310 {
00311 QPoint p(event->x(), event->y());
00312 COBase::Status rc = coSelected->pointerClick(p, x1, y1);
00313 if (rc == COBase::Moving)
00314 {
00315 mouseFlag = Moving;
00316 return;
00317 }
00318
00319 if (rc == COBase::None)
00320 {
00321 mouseFlag = None;
00322 return;
00323 }
00324 }
00325
00326 if (mouseFlag == Moving)
00327 {
00328 QPoint p(event->x(), event->y());
00329 coSelected->pointerClick(p, x1, y1);
00330 mouseFlag = COSelected;
00331 return;
00332 }
00333
00334 if (mouseFlag == ClickWait)
00335 {
00336 QPoint p(event->x(), event->y());
00337 COBase::Status rc = coSelected->pointerClick(p, x1, y1);
00338 if (rc == COBase::None)
00339 {
00340 mouseFlag = None;
00341 emit statusMessage("");
00342 setCursor(QCursor(Qt::ArrowCursor));
00343 return;
00344 }
00345 }
00346 }
00347 }
00348
00349 void IndicatorPlot::contextMenuEvent (QContextMenuEvent *)
00350 {
00351 if (drawMode && mouseFlag == COSelected && coSelected)
00352 coSelected->showMenu();
00353 else
00354 {
00355 if (menuFlag)
00356 showPopupMenu();
00357 }
00358 }
00359
00360 void IndicatorPlot::mouseMoveEvent (QMouseEvent *event)
00361 {
00362 if (! indy || ! data)
00363 return;
00364
00365
00366 if (event->y() <= 0)
00367 return;
00368
00369
00370 if (drawMode)
00371 {
00372 if (mouseFlag == Moving || mouseFlag == ClickWait)
00373 {
00374 getXY(event->x(), event->y());
00375 QPoint p(event->x(), event->y());
00376 coSelected->pointerMoving(buffer, p, x1, y1);
00377 return;
00378 }
00379 }
00380
00381 if (! infoFlag)
00382 return;
00383 else
00384 getInfo(event->x());
00385 }
00386
00387 void IndicatorPlot::getInfo (int x)
00388 {
00389 int i = convertXToDataIndex(x);
00390
00391 Setting tr;
00392 QString s, k;
00393 Bar bar;
00394 data->getBar(i, bar);
00395 bar.getDateString(TRUE, s);
00396 k = "D";
00397 tr.setData(k, s);
00398 bar.getTimeString(TRUE, s);
00399 k = "T";
00400 tr.setData(k, s);
00401
00402
00403 if (coList.count() > 0)
00404 {
00405 QDateTime d;
00406 bar.getDate(d);
00407 QDateTime coDate;
00408 int c = 0;
00409 Setting set;
00410 QDictIterator<COBase> it(coList);
00411 for (; it.current(); ++it)
00412 {
00413 it.current()->getDate(coDate);
00414 if (coDate == d)
00415 {
00416 it.current()->getSettings(set);
00417 k = "Type";
00418 set.getData(k, s);
00419 if (s == "BuyArrow" || s == "SellArrow")
00420 {
00421 c++;
00422 QString label = "Trade";
00423 label += "-" + QString::number(c);
00424 QString text = s.replace("Arrow", "");
00425 k = "Identifier";
00426 set.getData(k, s);
00427 if (s != "") text += " " + s;
00428 k = "Price";
00429 set.getData(k, s);
00430 if (s != "") text += " " + s;
00431 tr.setData(label, text);
00432 }
00433 }
00434 }
00435 }
00436
00437 if (indy && indy->getEnable())
00438 {
00439 int loop;
00440 for (loop = 0; loop < (int) indy->getLines(); loop++)
00441 {
00442 PlotLine *line = indy->getLine(loop);
00443 int li = line->getSize() - data->count() + i;
00444 if (li > -1 && li < line->getSize())
00445 line->getInfo(li, tr);
00446 }
00447 }
00448
00449 if (tr.count())
00450 {
00451 Setting *r = new Setting;
00452 tr.copy(r);
00453 emit infoMessage(r);
00454 }
00455 }
00456
00457 void IndicatorPlot::mouseDoubleClickEvent (QMouseEvent *)
00458 {
00459 if (! indy || ! data)
00460 return;
00461
00462 if (mouseFlag != COSelected)
00463 return;
00464
00465 coSelected->prefDialog();
00466 }
00467
00468 void IndicatorPlot::keyPressEvent (QKeyEvent *key)
00469 {
00470
00471 if (mouseFlag == COSelected)
00472 {
00473 coSelected->keyEvent(key);
00474 return;
00475 }
00476
00477
00478 switch (key->key())
00479 {
00480 case Qt::Key_Left:
00481 case Qt::Key_Right:
00482 case Qt::Key_Home:
00483 case Qt::Key_End:
00484 case Qt::Key_Plus:
00485 case Qt::Key_Minus:
00486 case Qt::Key_Prior:
00487 case Qt::Key_Next:
00488 case Qt::Key_Up:
00489 case Qt::Key_Down:
00490 emit keyPressed(key);
00491 break;
00492 default:
00493 key->ignore();
00494 break;
00495 }
00496 }
00497
00498 void IndicatorPlot::setBackgroundColor (QColor &d)
00499 {
00500 backgroundColor = d;
00501 }
00502
00503 void IndicatorPlot::setBorderColor (QColor &d)
00504 {
00505 borderColor = d;
00506 }
00507
00508 void IndicatorPlot::setGridColor (QColor &d)
00509 {
00510 gridColor = d;
00511 }
00512
00513 void IndicatorPlot::setPlotFont (QFont &d)
00514 {
00515 plotFont = d;
00516 delete plotFontMetrics;
00517 plotFontMetrics = new QFontMetrics(plotFont);
00518 }
00519
00520 void IndicatorPlot::setGridFlag (bool d)
00521 {
00522 gridFlag = d;
00523 }
00524
00525 void IndicatorPlot::setMenuFlag (bool d)
00526 {
00527 menuFlag = d;
00528 }
00529
00530 void IndicatorPlot::setPixelspace (int d)
00531 {
00532 pixelspace = d;
00533 }
00534
00535 void IndicatorPlot::setIndex (int d)
00536 {
00537 startIndex = d;
00538 }
00539
00540 void IndicatorPlot::setXGrid (QMemArray<int> &d)
00541 {
00542 xGrid = d;
00543 }
00544
00545 void IndicatorPlot::drawXGrid ()
00546 {
00547 if (gridFlag == FALSE)
00548 return;
00549
00550 QPainter painter;
00551 painter.begin(&buffer);
00552 painter.setPen(QPen(gridColor, 1, QPen::DotLine));
00553
00554 int loop;
00555 for (loop = 0; loop < (int) xGrid.size(); loop++)
00556 {
00557 if (xGrid[loop] >= startIndex)
00558 {
00559 int x = startX + (xGrid[loop] * pixelspace) - (startIndex * pixelspace);
00560 painter.drawLine (x, 0, x, buffer.height());
00561 }
00562 }
00563
00564 painter.end();
00565 }
00566
00567 void IndicatorPlot::addIndicator (Indicator *i)
00568 {
00569 indy = i;
00570 }
00571
00572 Indicator * IndicatorPlot::getIndicator ()
00573 {
00574 return indy;
00575 }
00576
00577 bool IndicatorPlot::deleteIndicator ()
00578 {
00579 if (indy)
00580 {
00581 delete indy;
00582 indy = 0;
00583 }
00584
00585 return FALSE;
00586 }
00587
00588 void IndicatorPlot::drawYGrid ()
00589 {
00590 if (! gridFlag)
00591 return;
00592
00593 QPainter painter;
00594 painter.begin(&buffer);
00595 painter.setPen(QPen(gridColor, 1, QPen::DotLine));
00596
00597 QMemArray<double> scaleArray;
00598 scaler.getScaleArray(scaleArray);
00599
00600 int loop;
00601 for (loop = 0; loop < (int) scaleArray.size(); loop++)
00602 {
00603 int y = scaler.convertToY(scaleArray[loop]);
00604 painter.drawLine (startX, y, buffer.width(), y);
00605 }
00606
00607 painter.end();
00608 }
00609
00610 void IndicatorPlot::drawInfo ()
00611
00612 {
00613 QPainter painter;
00614 painter.begin(&buffer);
00615 painter.setPen(borderColor);
00616 painter.setFont(plotFont);
00617 painter.setBackgroundMode(OpaqueMode);
00618 painter.setBackgroundColor(backgroundColor);
00619
00620
00621 int pos = startX;
00622
00623 QString s;
00624 Bar bar;
00625 data->getBar(data->count() - 1, bar);
00626 bar.getDateString(TRUE, s);
00627 s.append(" ");
00628 painter.drawText(pos, 10, s, -1);
00629 pos = pos + plotFontMetrics->width(s);
00630
00631 if (indy && indy->getEnable())
00632 {
00633 int loop;
00634 for (loop = 0; loop < (int) indy->getLines(); loop++)
00635 {
00636 PlotLine *line = indy->getLine(loop);
00637 if (line->getSize() > 1)
00638 {
00639 if (line->getType() == PlotLine::Bar || line->getType() == PlotLine::Candle)
00640 {
00641 if (data->count())
00642 {
00643 double ch = 0;
00644 double per = 0;
00645 if (data->count() > 1)
00646 {
00647 ch = data->getClose(data->count() - 1) - data->getClose(data->count() - 2);
00648 per = (ch / data->getClose(data->count() - 2)) * 100;
00649 }
00650 s = "CH=";
00651 QString str;
00652 strip(ch, 4, str);
00653 s.append(str);
00654 s.append(" (");
00655 strip(per, 2, str);
00656 s.append(str);
00657 s.append("%) ");
00658 if (ch < 0)
00659 painter.setPen(QColor("red"));
00660 else
00661 {
00662 if (ch > 0)
00663 painter.setPen(QColor("green"));
00664 else
00665 painter.setPen(QColor("blue"));
00666 }
00667 painter.drawText(pos, 10, s, -1);
00668 pos = pos + plotFontMetrics->width(s);
00669
00670 painter.setPen(borderColor);
00671
00672 s = "O=";
00673 strip(data->getOpen(data->count() - 1), 4, str);
00674 s.append(str);
00675 s.append(" H=");
00676 strip(data->getHigh(data->count() - 1), 4, str);
00677 s.append(str);
00678 s.append(" L=");
00679 strip(data->getLow(data->count() - 1), 4, str);
00680 s.append(str);
00681 s.append(" C=");
00682 strip(data->getClose(data->count() - 1), 4, str);
00683 s.append(str);
00684 s.append(" ");
00685 painter.drawText(pos, 10, s, -1);
00686 pos = pos + plotFontMetrics->width(s);
00687 }
00688 }
00689
00690 else if (line->getType() == PlotLine::Horizontal)
00691 {
00692
00693
00694 continue;
00695 }
00696 else
00697 {
00698 line->getLabel(s);
00699 s.append("=");
00700 QString str;
00701 strip(line->getData(line->getSize() - 1), 4, str);
00702 s.append(str);
00703 s.append(" ");
00704
00705 QColor c;
00706 line->getColor(c);
00707 painter.setPen(c);
00708 painter.drawText(pos, 10, s, -1);
00709 pos = pos + plotFontMetrics->width(s);
00710 }
00711 }
00712 }
00713 }
00714
00715 painter.end();
00716 }
00717
00718 void IndicatorPlot::crossHair (int x, int y, bool f)
00719 {
00720 crossHairFlag = TRUE;
00721 getXY(x, y);
00722 crossHairY = y1;
00723 crossHairX = x1;
00724 if (f)
00725 draw();
00726 }
00727
00728 void IndicatorPlot::drawCrossHair ()
00729 {
00730 if (! crosshairs)
00731 return;
00732
00733 if (! crossHairFlag)
00734 return;
00735
00736 int y = scaler.convertToY(crossHairY);
00737 int x = startX + (data->getX(crossHairX) * pixelspace) - (startIndex * pixelspace);
00738
00739 QPainter painter;
00740 painter.begin(&buffer);
00741 painter.setPen(QPen(borderColor, 1, QPen::DotLine));
00742 painter.drawLine (0, y, buffer.width(), y);
00743 painter.drawLine (x, 0, x, buffer.height());
00744 painter.end();
00745 }
00746
00747 void IndicatorPlot::getXY (int x, int y)
00748 {
00749 int i = convertXToDataIndex(x);
00750 data->getDate(i, x1);
00751 y1 = scaler.convertToVal(y);
00752 }
00753
00754 int IndicatorPlot::convertXToDataIndex (int x)
00755 {
00756 int i = (x / pixelspace) + startIndex;
00757 if (i >= (int) data->count())
00758 i = data->count() - 1;
00759 if (i < startIndex)
00760 i = startIndex;
00761
00762 return i;
00763 }
00764
00765 void IndicatorPlot::updateStatusBar (int x, int y)
00766 {
00767 int i = convertXToDataIndex(x);
00768 QString s;
00769 Bar bar;
00770 data->getBar(i, bar);
00771 bar.getDateTimeString(TRUE, s);
00772 s.append(" ");
00773 QString str;
00774 strip(scaler.convertToVal(y), 4, str);
00775 s.append(str);
00776 emit statusMessage(s);
00777 }
00778
00779 void IndicatorPlot::setScale ()
00780 {
00781 double scaleHigh = -99999999;
00782 double scaleLow = 99999999;
00783 bool pfFlag = FALSE;
00784
00785 if (indy && indy->getEnable())
00786 {
00787 int loop;
00788 for (loop = 0; loop < indy->getLines(); loop++)
00789 {
00790 PlotLine *line = indy->getLine(loop);
00791 if (line->getType() == PlotLine::Invisible)
00792 continue;
00793
00794 if (line->getScaleFlag())
00795 continue;
00796
00797 if (line->getType() == PlotLine::PF)
00798 pfFlag = TRUE;
00799
00800 if (! scaleToScreen)
00801 {
00802 if (line->getHigh() > scaleHigh)
00803 scaleHigh = line->getHigh();
00804
00805 if (line->getLow() < scaleLow)
00806 scaleLow = line->getLow();
00807 }
00808 else
00809 {
00810 int loop2 = line->getSize() - data->count() + startIndex;
00811 int end = (buffer.width() / pixelspace) + loop2;
00812 if (loop2 < 0)
00813 loop2 = 0;
00814 if (end > line->getSize())
00815 end = line->getSize();
00816
00817 double h, l;
00818 line->getHighLowRange(loop2, end - 1, h, l);
00819 if (h > scaleHigh)
00820 scaleHigh = h;
00821 if (l < scaleLow)
00822 scaleLow = l;
00823 }
00824 }
00825 }
00826
00827 if (! scaleToScreen)
00828 {
00829 QDictIterator<COBase> it(coList);
00830 for (; it.current(); ++it)
00831 {
00832 COBase *plug = it.current();
00833
00834 if (plug->getHigh() > scaleHigh)
00835 scaleHigh = plug->getHigh();
00836
00837 if (plug->getLow() < scaleLow)
00838 scaleLow = plug->getLow();
00839 }
00840 }
00841
00842
00843
00844 if (pfFlag)
00845 scaleHigh = scaleHigh * 1.02;
00846
00847
00848
00849 double logScaleHigh = 1;
00850 double logRange = 0;
00851 if (logScale)
00852 {
00853 logScaleHigh = scaleHigh > 0.0 ? log(scaleHigh) : 1;
00854 double logScaleLow = scaleLow > 0.0 ? log(scaleLow) : 0;
00855 logRange = logScaleHigh - logScaleLow;
00856 }
00857
00858 scaler.set(buffer.height(), scaleHigh, scaleLow, logScaleHigh, logRange, logScale);
00859 }
00860
00861 int IndicatorPlot::getXFromDate (QDateTime &d)
00862 {
00863 int x2 = data->getX(d);
00864 if (x2 == -1)
00865 return -1;
00866
00867 int x = startX + (x2 * pixelspace) - (startIndex * pixelspace);
00868
00869 return x;
00870 }
00871
00872 void IndicatorPlot::strip (double d, int p, QString &s)
00873 {
00874 if (fabs(d) < 1)
00875 s = QString::number(d, 'f', p);
00876 else
00877 {
00878 if (fabs(d) > 1000)
00879 s = QString::number(d, 'f', 0);
00880 else
00881 s = QString::number(d, 'f', 2);
00882 }
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903 }
00904
00905 void IndicatorPlot::printChart ()
00906 {
00907 QPrinter printer;
00908 printer.setPageSize(QPrinter::Letter);
00909
00910 if (printer.setup())
00911 {
00912 emit statusMessage(tr("Creating chart snapshot..."));
00913
00914 printer.setFullPage(true);
00915 QSize margins = printer.margins();
00916 int leftMargin = margins.width();
00917 int topMargin = margins.height();
00918
00919 QPaintDeviceMetrics prm(&printer);
00920
00921 int prmw = prm.width() - leftMargin;
00922 int prmh = prm.height() - topMargin;
00923
00924 if ((buffer.width() > prmw) || (buffer.height() > prmh))
00925 {
00926 QImage image = buffer.convertToImage();
00927 image = image.smoothScale(prmw, prmh, QImage::ScaleMin);
00928 buffer.convertFromImage(image);
00929 }
00930
00931 emit statusMessage(tr("Printing..."));
00932
00933 QPainter painter;
00934 painter.begin(&printer);
00935 painter.drawPixmap(leftMargin/2, topMargin/2, buffer);
00936 painter.end();
00937 emit statusMessage(tr("Printing complete."));
00938 }
00939 }
00940
00941 void IndicatorPlot::showPopupMenu ()
00942 {
00943 chartMenu->clear();
00944
00945 chartMenu->insertItem(QPixmap(indicator), tr("New &Indicator"), this,
00946 SLOT(slotNewIndicator()), CTRL+Key_I);
00947 chartMenu->insertItem(QPixmap(edit), tr("&Edit Indicator"), this, SLOT(slotEditIndicator()), CTRL+Key_E);
00948 chartMenu->insertItem(QPixmap(help), tr("Indicator &Help"), this, SLOT(slotIndicatorHelp()), CTRL+Key_H);
00949 chartMenu->insertSeparator ();
00950 chartMenu->insertItem(QPixmap(edit), tr("Edit &Chart"), this, SLOT(slotEditChart()), CTRL+Key_C);
00951 chartMenu->insertSeparator ();
00952
00953 chartObjectMenu = new QPopupMenu();
00954 int id = chartObjectMenu->insertItem(QPixmap(buyarrow), "BuyArrow", this, SLOT(slotNewChartObject(int)));
00955 chartObjectMenu->setItemParameter(id, id);
00956 id = chartObjectMenu->insertItem(QPixmap(arc), "Cycle", this, SLOT(slotNewChartObject(int)));
00957 chartObjectMenu->setItemParameter(id, id);
00958 id = chartObjectMenu->insertItem(QPixmap(fib), "FiboLine", this, SLOT(slotNewChartObject(int)));
00959 chartObjectMenu->setItemParameter(id, id);
00960 id = chartObjectMenu->insertItem(QPixmap(horizontal), "HorizontalLine", this,
00961 SLOT(slotNewChartObject(int)));
00962 chartObjectMenu->setItemParameter(id, id);
00963 id = chartObjectMenu->insertItem(QPixmap(sellarrow), "SellArrow", this, SLOT(slotNewChartObject(int)));
00964 chartObjectMenu->setItemParameter(id, id);
00965 id = chartObjectMenu->insertItem(QPixmap(text), "Text", this, SLOT(slotNewChartObject(int)));
00966 chartObjectMenu->setItemParameter(id, id);
00967 id = chartObjectMenu->insertItem(QPixmap(trend), "TrendLine", this, SLOT(slotNewChartObject(int)));
00968 chartObjectMenu->setItemParameter(id, id);
00969 id = chartObjectMenu->insertItem(QPixmap(vertical), "VerticalLine", this, SLOT(slotNewChartObject(int)));
00970 chartObjectMenu->setItemParameter(id, id);
00971
00972 id = chartMenu->insertItem (QPixmap(co), tr("New Chart Object"), chartObjectMenu);
00973
00974 if (! drawMode || ! data)
00975 chartObjectMenu->setEnabled(FALSE);
00976 else
00977 chartObjectMenu->setEnabled(TRUE);
00978
00979 chartMenu->insertItem(QPixmap(deleteitem), tr("Delete &All Chart Objects"), this,
00980 SLOT(slotDeleteAllChartObjects()), CTRL+Key_A);
00981
00982 chartMenu->insertSeparator ();
00983 chartMenu->insertItem(QPixmap(print), tr("&Print Chart"), this, SLOT(printChart()), CTRL+Key_P);
00984
00985 id = chartMenu->insertItem(QPixmap(date), tr("Date"), this, SLOT(toggleDate()), CTRL+Key_D);
00986 chartMenu->setItemChecked(id, dateFlag);
00987
00988 id = chartMenu->insertItem(QPixmap(loggridicon), tr("Log Scaling"), this, SLOT(toggleLog()), CTRL+Key_L);
00989 chartMenu->setItemChecked(id, logScale);
00990
00991 chartMenu->exec(QCursor::pos());
00992 }
00993
00994 void IndicatorPlot::toggleDate ()
00995 {
00996 if (dateFlag == FALSE)
00997 dateFlag = TRUE;
00998 else
00999 dateFlag = FALSE;
01000
01001 if (indy)
01002 {
01003 Setting set;
01004 QString s;
01005 indy->getFile(s);
01006 config.getIndicator(s, set);
01007 QString k = "dateFlag";
01008 QString d = QString::number(dateFlag);
01009 set.setData(k, d);
01010 config.setIndicator(s, set);
01011 }
01012
01013 emit signalDateFlag(dateFlag);
01014 }
01015
01016 void IndicatorPlot::toggleLog ()
01017 {
01018 if (logScale == FALSE)
01019 logScale = TRUE;
01020 else
01021 logScale = FALSE;
01022
01023 if (indy)
01024 {
01025 Setting set;
01026 QString s;
01027 indy->getFile(s);
01028 config.getIndicator(s, set);
01029 QString k = "logScale";
01030 QString d = QString::number(logScale);
01031 set.setData(k, d);
01032 config.setIndicator(s, set);
01033 }
01034
01035 emit signalLogFlag(logScale);
01036 }
01037
01038 void IndicatorPlot::setCrosshairsStatus (bool status)
01039 {
01040 crosshairs = status;
01041 crossHairFlag = FALSE;
01042 draw();
01043 }
01044
01045 void IndicatorPlot::slotEditIndicator ()
01046 {
01047 if (indy)
01048 {
01049 QString s;
01050 indy->getName(s);
01051 emit signalEditIndicator(s);
01052 }
01053 }
01054
01055 void IndicatorPlot::slotNewIndicator ()
01056 {
01057 emit signalNewIndicator();
01058 }
01059
01060 void IndicatorPlot::slotMessage (QString d)
01061 {
01062 emit statusMessage(d);
01063 }
01064
01065 void IndicatorPlot::slotSliderChanged (int v)
01066 {
01067 setIndex(v);
01068 draw();
01069 }
01070
01071 void IndicatorPlot::slotGridChanged (bool d)
01072 {
01073 setGridFlag(d);
01074 draw();
01075 }
01076
01077 void IndicatorPlot::slotScaleToScreenChanged (bool d)
01078 {
01079 setScaleToScreen(d);
01080 draw();
01081 }
01082
01083 void IndicatorPlot::slotDrawModeChanged (bool d)
01084 {
01085 setDrawMode(d);
01086 }
01087
01088 void IndicatorPlot::slotLogScaleChanged (bool d)
01089 {
01090 setLogScale(d);
01091 draw();
01092 }
01093
01094 int IndicatorPlot::getWidth ()
01095 {
01096 return buffer.width();
01097 }
01098
01099 void IndicatorPlot::slotEditChart ()
01100 {
01101 emit signalEditChart(chartPath);
01102 }
01103
01104 void IndicatorPlot::slotIndicatorHelp ()
01105 {
01106 QString s, f;
01107 QString h = "indicator/intro.html";
01108 indy->getName(s);
01109 s.append(".html");
01110
01111
01112 s.lower();
01113 RcFile rcfile;
01114 rcfile.loadData(RcFile::UserDocsPath, userDocsPath);
01115 userDocsPath.append("/");
01116 rcfile.loadData(RcFile::HelpFilePath, helpFilePath);
01117 helpFilePath.append("/");
01118 QDir dir;
01119
01120
01121
01122 f = userDocsPath + "indicator/" + s;
01123 if (dir.exists(f))
01124 h = f;
01125 else
01126 {
01127 f = helpFilePath + "indicator/" + s;
01128 if (dir.exists(f))
01129 h = "indicator/" + s;
01130 else
01131 {
01132
01133 f = helpFilePath + s;
01134 if (dir.exists(f))
01135 h = s;
01136 }
01137 }
01138 HelpWindow *hw = new HelpWindow(this, h);
01139 hw->show();
01140 }
01141
01142
01143
01144
01145
01146 void IndicatorPlot::drawLine ()
01147 {
01148 QPainter painter;
01149 painter.begin(&buffer);
01150
01151 QPen pen;
01152 QColor c;
01153 currentLine->getColor(c);
01154 pen.setColor(c);
01155
01156 if (currentLine->getType() == PlotLine::Dash)
01157 pen.setStyle(Qt::DotLine);
01158 else
01159 pen.setStyle(Qt::SolidLine);
01160 painter.setPen(pen);
01161
01162 int x = -1;
01163 int x2 = startX;
01164 int y = -1;
01165 int y2 = -1;
01166 int loop = currentLine->getSize() - data->count() + startIndex;
01167
01168 Scaler scale;
01169 if (currentLine->getScaleFlag())
01170 {
01171 scale.set(scaler.getHeight(),
01172 currentLine->getHigh(),
01173 currentLine->getLow(),
01174 scaler.getLogScaleHigh(),
01175 scaler.getLogRange(),
01176 scaler.getLogFlag());
01177 }
01178
01179 while ((x2 < buffer.width()) && (loop < (int) currentLine->getSize()))
01180 {
01181 if (loop > -1)
01182 {
01183 if (currentLine->getScaleFlag())
01184 y2 = scale.convertToY(currentLine->getData(loop));
01185 else
01186 y2 = scaler.convertToY(currentLine->getData(loop));
01187
01188 if (y != -1)
01189 painter.drawLine (x, y, x2, y2);
01190 x = x2;
01191 y = y2;
01192 }
01193
01194 x2 = x2 + pixelspace;
01195 loop++;
01196 }
01197
01198 painter.end();
01199 }
01200
01201 void IndicatorPlot::drawHorizontalLine ()
01202 {
01203 QPainter painter;
01204 painter.begin(&buffer);
01205
01206 QPen pen;
01207 QColor c;
01208 currentLine->getColor(c);
01209 pen.setColor(c);
01210 painter.setPen(pen);
01211
01212 int y = scaler.convertToY(currentLine->getData(currentLine->getSize() - 1));
01213
01214 painter.drawLine (0, y, buffer.width(), y);
01215
01216 QString s, s2;
01217 strip(currentLine->getData(currentLine->getSize() - 1), 4, s);
01218 currentLine->getLabel(s2);
01219 s = s2 + "=" + s;
01220
01221 painter.setBackgroundMode(OpaqueMode);
01222 painter.setBackgroundColor(backgroundColor);
01223 painter.setFont(plotFont);
01224
01225 QRect rc = painter.boundingRect(startX, y - (plotFontMetrics->height()/2) , 1, 1, AlignAuto, s, -1, 0);
01226 painter.drawText(rc, AlignAuto, s);
01227 painter.drawRect(rc);
01228 painter.end();
01229 }
01230
01231 void IndicatorPlot::drawDot ()
01232 {
01233 QPainter painter;
01234 painter.begin(&buffer);
01235
01236 QPen pen;
01237 QColor c;
01238 currentLine->getColor(c);
01239 pen.setColor(c);
01240 painter.setPen(pen);
01241
01242 int x = startX;
01243 int loop = currentLine->getSize() - data->count() + startIndex;
01244
01245 Scaler scale;
01246 if (currentLine->getScaleFlag())
01247 {
01248 scale.set(scaler.getHeight(),
01249 currentLine->getHigh(),
01250 currentLine->getLow(),
01251 scaler.getLogScaleHigh(),
01252 scaler.getLogRange(),
01253 scaler.getLogFlag());
01254 }
01255
01256 while ((x < buffer.width()) && (loop < (int) currentLine->getSize()))
01257 {
01258 if (loop > -1)
01259 {
01260 int y;
01261 if (currentLine->getScaleFlag())
01262 y = scale.convertToY(currentLine->getData(loop));
01263 else
01264 y = scaler.convertToY(currentLine->getData(loop));
01265
01266 painter.drawPoint(x, y);
01267 }
01268
01269 x = x + pixelspace;
01270 loop++;
01271 }
01272
01273 painter.end();
01274 }
01275
01276 void IndicatorPlot::drawHistogram ()
01277 {
01278 QPainter painter;
01279 painter.begin(&buffer);
01280 QColor c;
01281 currentLine->getColor(c);
01282 painter.setPen(c);
01283 painter.setBrush(c);
01284
01285 int loop = currentLine->getSize() - data->count() + startIndex;
01286
01287 QPointArray pa(4);
01288
01289 int zero = 0;
01290 Scaler scale;
01291 if (currentLine->getScaleFlag())
01292 {
01293 scale.set(scaler.getHeight(),
01294 currentLine->getHigh(),
01295 currentLine->getLow(),
01296 scaler.getLogScaleHigh(),
01297 scaler.getLogRange(),
01298 scaler.getLogFlag());
01299 zero = scale.convertToY(0);
01300 }
01301 else
01302 zero = scaler.convertToY(0);
01303
01304 int x = -1;
01305 int x2 = startX;
01306 int y = -1;
01307 int y2 = -1;
01308
01309 while ((x < buffer.width()) && (loop < (int) currentLine->getSize()))
01310 {
01311 if (loop > -1)
01312 {
01313 if (currentLine->getScaleFlag())
01314 y2 = scale.convertToY(currentLine->getData(loop));
01315 else
01316 y2 = scaler.convertToY(currentLine->getData(loop));
01317 pa.setPoint(0, x, zero);
01318 pa.setPoint(1, x, y);
01319 pa.setPoint(2, x2, y2);
01320 pa.setPoint(3, x2, zero);
01321
01322 if (y != -1)
01323 painter.drawPolygon(pa, TRUE, 0, -1);
01324
01325 x = x2;
01326 y = y2;
01327 }
01328
01329 x2 = x2 + pixelspace;
01330 loop++;
01331 }
01332
01333 painter.end();
01334 }
01335
01336 void IndicatorPlot::drawHistogramBar ()
01337 {
01338 QPainter painter;
01339 painter.begin(&buffer);
01340
01341 QColor color;
01342 currentLine->getColor(color);
01343
01344 int x = startX;
01345 int zero = 0;
01346 Scaler scale;
01347 if (currentLine->getScaleFlag())
01348 {
01349 scale.set(scaler.getHeight(),
01350 currentLine->getHigh(),
01351 currentLine->getLow(),
01352 scaler.getLogScaleHigh(),
01353 scaler.getLogRange(),
01354 scaler.getLogFlag());
01355 zero = scale.convertToY(0);
01356 }
01357 else
01358 zero = scaler.convertToY(0);
01359
01360 int loop = currentLine->getSize() - data->count() + startIndex;
01361
01362 while ((x < buffer.width()) && (loop < (int) currentLine->getSize()))
01363 {
01364 if (loop > -1)
01365 {
01366 int y;
01367 if (currentLine->getScaleFlag())
01368 y = scale.convertToY(currentLine->getData(loop));
01369 else
01370 y = scaler.convertToY(currentLine->getData(loop));
01371
01372 if (currentLine->getColorFlag() == TRUE)
01373 currentLine->getColorBar(loop, color);
01374
01375 painter.fillRect(x, y, pixelspace - 1, zero - y, color);
01376 }
01377
01378 x = x + pixelspace;
01379 loop++;
01380 }
01381
01382 painter.end();
01383 }
01384
01385 void IndicatorPlot::drawBar ()
01386 {
01387 QPainter painter;
01388 painter.begin(&buffer);
01389
01390 int loop = currentLine->getSize() - data->count() + startIndex;
01391 int x = startX;
01392 double o = 0;
01393 double h = 0;
01394 double l = 0;
01395 double cl = 0;
01396 bool ff = FALSE;
01397 QColor c;
01398
01399 while ((x < buffer.width()) && (loop < (int) currentLine->getSize()))
01400 {
01401 if (loop > -1)
01402 {
01403 currentLine->getData(loop, c, o, h, l, cl, ff);
01404
01405 painter.setPen(c);
01406
01407 int y = scaler.convertToY(o);
01408 painter.drawLine (x - 2, y, x, y);
01409
01410 y = scaler.convertToY(cl);
01411 painter.drawLine (x + 2, y, x, y);
01412
01413 y = scaler.convertToY(h);
01414 int y2 = scaler.convertToY(l);
01415 painter.drawLine (x, y, x, y2);
01416 }
01417
01418 x = x + pixelspace;
01419 loop++;
01420 }
01421
01422 painter.end();
01423 }
01424
01425 void IndicatorPlot::drawCandle ()
01426 {
01427 QPainter painter;
01428 painter.begin(&buffer);
01429
01430 int loop = currentLine->getSize() - data->count() + startIndex;
01431 int x = startX;
01432 double o = 0;
01433 double h = 0;
01434 double l = 0;
01435 double cl = 0;
01436 QColor c;
01437 bool ff = FALSE;
01438
01439 while ((x < buffer.width()) && (loop < (int) currentLine->getSize()))
01440 {
01441 if (loop > -1)
01442 {
01443 currentLine->getData(loop, c, o, h, l, cl, ff);
01444
01445 painter.setPen(c);
01446
01447 int xh = scaler.convertToY(h);
01448 int xl = scaler.convertToY(l);
01449 int xc = scaler.convertToY(cl);
01450 int xo = scaler.convertToY(o);
01451
01452 if (! ff)
01453 {
01454 painter.drawLine (x, xh, x, xc);
01455 painter.drawLine (x, xo, x, xl);
01456
01457 if (xc == xo)
01458 painter.drawLine (x - 2, xo, x + 2, xo);
01459 else
01460 painter.drawRect(x - 2, xc, 5, xo - xc);
01461 }
01462 else
01463 {
01464 painter.drawLine (x, xh, x, xl);
01465
01466 if (xc == xo)
01467 painter.drawLine (x - 2, xo, x + 2, xo);
01468 else
01469 painter.fillRect(x - 2, xo, 5, xc - xo, c);
01470 }
01471 }
01472
01473 x = x + pixelspace;
01474 loop++;
01475 }
01476
01477 painter.end();
01478 }
01479
01480 void IndicatorPlot::drawPF ()
01481 {
01482 QPainter painter;
01483 painter.begin(&buffer);
01484
01485 painter.setFont(plotFont);
01486
01487
01488 double box = 0;
01489 double h = 0;
01490 double l = 0;
01491 double cl = 0;
01492 QColor c;
01493 bool ff = FALSE;
01494 int x = startX;
01495 int loop = currentLine->getSize() - data->count() + startIndex;
01496
01497 while ((x < buffer.width()) && (loop < (int) currentLine->getSize()))
01498 {
01499 if (loop > -1)
01500 {
01501 currentLine->getData(loop, c, box, h, l, cl, ff);
01502
01503 painter.setPen(c);
01504
01505 QString s = "O";
01506 if (ff)
01507 s = "X";
01508
01509
01510
01511
01512
01513
01514
01515 double d = l;
01516
01517 while (d <= h)
01518 {
01519 int y = scaler.convertToY(d);
01520 painter.drawText (x, y, s, -1);
01521 d = d + box;
01522
01523 }
01524 }
01525
01526 x = x + pixelspace;
01527 loop++;
01528 }
01529
01530 painter.end();
01531 }
01532
01533
01534
01535
01536
01537 void IndicatorPlot::slotNewChartObject (int id)
01538 {
01539 if (! chartPath.length())
01540 return;
01541
01542 QDir dir;
01543 if (! dir.exists(chartPath))
01544 return;
01545
01546 QString selection = chartObjectMenu->text(id);
01547
01548 COBase tco;
01549 coSelected = tco.getCO(selection);
01550 if (! coSelected)
01551 return;
01552
01553 coSelected->setData(data);
01554 QObject::connect(coSelected, SIGNAL(signalDraw()), this, SLOT(draw()));
01555 QObject::connect(coSelected, SIGNAL(signalRefresh()), this, SLOT(drawRefresh()));
01556 QObject::connect(coSelected, SIGNAL(message(QString)), this, SLOT(slotMessage(QString)));
01557 QObject::connect(coSelected, SIGNAL(signalObjectDeleted(QString)), this, SLOT(slotChartObjectDeleted(QString)));
01558 QObject::connect(coSelected, SIGNAL(signalSave(QString)), this, SLOT(saveChartObject(QString)));
01559
01560 QFileInfo fi(chartPath);
01561 QString symbol = fi.fileName();
01562 DBIndexItem item;
01563 chartIndex->getIndexItem(symbol, item);
01564 QString s, name;
01565 item.getSymbol(s);
01566 chartIndex->getNewChartObjectName(s, name);
01567
01568 coList.replace(name, coSelected);
01569
01570 indy->getName(s);
01571
01572 setCursor(QCursor(Qt::PointingHandCursor));
01573
01574 mouseFlag = ClickWait;
01575
01576 coSelected->newObject(s, name);
01577 }
01578
01579 void IndicatorPlot::addChartObject (Setting &set)
01580 {
01581 COBase tco;
01582 COBase *co = tco.getCO(set);
01583 if (! co)
01584 return;
01585
01586 co->setData(data);
01587 QObject::connect(co, SIGNAL(signalDraw()), this, SLOT(draw()));
01588 QObject::connect(co, SIGNAL(signalRefresh()), this, SLOT(drawRefresh()));
01589 QObject::connect(co, SIGNAL(message(QString)), this, SLOT(slotMessage(QString)));
01590 QObject::connect(co, SIGNAL(signalObjectDeleted(QString)), this, SLOT(slotChartObjectDeleted(QString)));
01591
01592 QString s;
01593 QString k = "Name";
01594 set.getData(k, s);
01595 coList.replace(s, co);
01596
01597 co->addObject(set);
01598 }
01599
01600 void IndicatorPlot::drawObjects ()
01601 {
01602 QDictIterator<COBase> it(coList);
01603 for (; it.current(); ++it)
01604 {
01605 COBase *co = it.current();
01606 co->draw(buffer, scaler, startIndex, pixelspace, startX);
01607 }
01608 }
01609
01610 void IndicatorPlot::slotDeleteAllChartObjects ()
01611 {
01612 if (! chartPath.length())
01613 return;
01614
01615 QDir dir;
01616 if (! dir.exists(chartPath))
01617 return;
01618
01619 if (! coList.count())
01620 {
01621 QMessageBox::information(this,
01622 tr("Qtstalker: Delete All Chart Objects"),
01623 tr("No chart objects to delete."));
01624 return;
01625 }
01626
01627 emit signalDeleteAllCO();
01628
01629 coList.clear();
01630
01631 mouseFlag = None;
01632 draw();
01633 }
01634
01635 void IndicatorPlot::setCrosshairsFlag (bool d)
01636 {
01637 crosshairs = d;
01638 }
01639
01640 void IndicatorPlot::setScaler (Scaler &d)
01641 {
01642 scaler = d;
01643 }
01644
01645 Scaler & IndicatorPlot::getScaler ()
01646 {
01647 return scaler;
01648 }
01649
01650 void IndicatorPlot::slotChartObjectDeleted (QString d)
01651 {
01652 if (! chartPath.length())
01653 return;
01654
01655 QDir dir;
01656 if (! dir.exists(chartPath))
01657 return;
01658
01659 if (! coList.count())
01660 return;
01661
01662 emit signalDeleteCO(d);
01663
01664 coList.remove(d);
01665
01666 mouseFlag = None;
01667
01668 draw();
01669 }
01670
01671 void IndicatorPlot::saveChartObjects ()
01672 {
01673 if (! chartPath.length())
01674 return;
01675
01676 QDictIterator<COBase> it(coList);
01677 for (; it.current(); ++it)
01678 {
01679 COBase *co = it.current();
01680 if (co->getSaveFlag())
01681 {
01682 Setting set;
01683 co->getSettings(set);
01684 emit signalSaveCO(set);
01685 }
01686 }
01687 }
01688
01689 void IndicatorPlot::saveChartObject (QString name)
01690 {
01691 COBase *co = coList[name];
01692 if (! co)
01693 return;
01694
01695 Setting set;
01696 co->getSettings(set);
01697 emit signalSaveCO(set);
01698 }
01699