src/Scanner.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 <qlayout.h>
00023 #include <qinputdialog.h>
00024 #include <qmessagebox.h>
00025 #include <qdatetime.h>
00026 #include <qdir.h>
00027 #include <qhgroupbox.h>
00028 #include <qprogressdialog.h>
00029 #include <stdlib.h>
00030 #include <qlabel.h>
00031 #include "Scanner.h"
00032 #include "BarData.h"
00033 #include "SymbolDialog.h"
00034 #include "DbPlugin.h"
00035 #include "IndicatorPlugin.h"
00036 #include "HelpWindow.h"
00037 #include "Traverse.h"
00038 
00039 
00040 Scanner::Scanner (QString n, DBIndex *i) : QTabDialog (0, 0, FALSE)
00041 {
00042   chartIndex = i;
00043   scannerName = n;
00044   
00045   QString s = "Qtstalker Scanner";
00046   s.append(": ");
00047   s.append(scannerName);
00048   setCaption (s);
00049 
00050   QWidget *w = new QWidget(this);
00051   
00052   QVBoxLayout *vbox = new QVBoxLayout(w);
00053   vbox->setMargin(5);
00054   vbox->setSpacing(5);
00055   
00056   QHGroupBox *gbox = new QHGroupBox(tr("Symbol Selection"), w);  
00057   vbox->addWidget(gbox);
00058 
00059   allSymbols = new QCheckBox(tr("All symbols"), gbox);
00060   connect(allSymbols, SIGNAL(toggled(bool)), this, SLOT(allSymbolsToggled(bool)));
00061 
00062   fileButton = new QPushButton(tr("0 Symbols"), gbox);
00063   connect(fileButton, SIGNAL(clicked()), this, SLOT(getSymbols()));
00064 
00065   basePath = new QComboBox(gbox);
00066   basePath->insertItem(tr("Chart"), -1);
00067   basePath->insertItem(tr("Group"), -1);
00068 
00069   QGridLayout *grid = new QGridLayout(vbox, 1, 2);
00070   grid->setColStretch(1, 1);
00071 
00072   QLabel *label = new QLabel(tr("Bar Length"), w);
00073   grid->addWidget(label, 0, 0);
00074 
00075   BarData bd(scannerName);
00076   period = new QComboBox(w);
00077   bd.getBarLengthList(barLengthList);
00078   period->insertStringList(barLengthList, -1);
00079   period->setCurrentText("Daily");
00080   grid->addWidget(period, 0, 1);
00081 
00082   label = new QLabel(tr("Bars"), w);
00083   grid->addWidget(label, 1, 0);
00084 
00085   bars = new QSpinBox(1, 99999999, 1, w);
00086   bars->setValue(100);
00087   grid->addWidget(bars, 1, 1);
00088   
00089   list = new FormulaEdit(w, FormulaEdit::Logic);
00090   vbox->addWidget(list);
00091   
00092   setDefaultButton(tr("&Scan"));
00093   connect(this, SIGNAL(defaultButtonPressed()), this, SLOT(scan()));
00094   
00095   setApplyButton(tr("&Apply"));  
00096   connect(this, SIGNAL(applyButtonPressed()), this, SLOT(saveRule()));
00097   
00098   setCancelButton(tr("&Cancel"));  
00099   connect(this, SIGNAL(cancelButtonPressed()), this, SLOT(exitDialog()));
00100   
00101   setOkButton(QString::null);  
00102   
00103   setHelpButton();
00104   QObject::connect(this, SIGNAL(helpButtonPressed()), this, SLOT(slotHelp()));
00105   
00106   addTab(w, tr("Parms"));
00107 
00108   loadRule();
00109 }
00110 
00111 Scanner::~Scanner ()
00112 {
00113 }
00114 
00115 void Scanner::scan ()
00116 {
00117   if (! fileList.count() && ! allSymbols->isChecked())
00118   {
00119     QMessageBox::information(this,
00120                              tr("Qtstalker: Error"),
00121                              tr("No symbols selected."));
00122     return;
00123   }
00124 
00125   // open the CUS plugin
00126   QString iplugin("CUS");
00127   IndicatorPlugin *plug = config.getIndicatorPlugin(iplugin);
00128   if (! plug)
00129   {
00130     config.closePlugin(iplugin);
00131     return;
00132   }
00133 
00134   QString s;
00135   list->getText(s);
00136   QStringList l = QStringList::split("\n", s, FALSE);
00137   plug->setCustomFunction(l);
00138   
00139   this->setEnabled(FALSE);
00140   
00141   // clear dir for scan symbols
00142   QDir dir;
00143   config.getData(Config::GroupPath, s);
00144   s.append("/Scanner");
00145   if (! dir.exists(s, TRUE))
00146     dir.mkdir(s, TRUE);
00147   s.append("/" + scannerName);
00148   if (! dir.exists(s, TRUE))
00149     dir.mkdir(s, TRUE);
00150   else
00151   {
00152     int loop;
00153     dir.setPath(s);
00154     for (loop = 2; loop < (int) dir.count(); loop++)
00155     {
00156       QString s2 = dir.absPath() + "/" + dir[loop];
00157       if (! dir.remove(s2, TRUE))
00158         qDebug("%s not removed", s2.latin1());
00159     }
00160   }
00161   
00162   if (allSymbols->isChecked())
00163   {
00164     QString ts;
00165     if (! basePath->currentText().compare(tr("Chart")))
00166       config.getData(Config::DataPath, ts);
00167     else
00168       config.getData(Config::GroupPath, ts);
00169     Traverse trav(Traverse::File);
00170     trav.traverse(ts);
00171     trav.getList(fileList);
00172   }
00173   
00174   QProgressDialog prog(tr("Scanning..."),
00175                        tr("Cancel"),
00176                        fileList.count(),
00177                        this,
00178                        "progress",
00179                        TRUE);
00180   prog.show();
00181   
00182   int minBars = bars->value();
00183   
00184   emit message(QString("Scanning..."));
00185   
00186   int loop;
00187   for (loop = 0; loop < (int) fileList.count(); loop++)
00188   {
00189     prog.setProgress(loop);
00190     emit message(QString());
00191     if (prog.wasCancelled())
00192     {
00193       emit message(QString("Scan cancelled"));
00194       break;
00195     }
00196 
00197     QFileInfo fi(fileList[loop]);
00198     if (fi.isDir())
00199       continue;
00200 
00201     DbPlugin db;
00202     QDir dir;
00203     if (! dir.exists(fileList[loop]))
00204       continue;
00205     db.open(fileList[loop], chartIndex);
00206 
00207     db.setBarRange(minBars);
00208     db.setBarLength((BarData::BarLength) barLengthList.findIndex(period->currentText()));
00209 
00210     BarData *recordList = new BarData(fileList[loop]);
00211     QDateTime dt = QDateTime::currentDateTime();
00212     db.getHistory(recordList, dt);
00213     db.close();
00214     
00215     // load the CUS plugin and calculate
00216     plug->setIndicatorInput(recordList);
00217     Indicator *i = plug->calculate();
00218     if (! i->getLines())
00219     {
00220       delete recordList;
00221       delete i;
00222       continue;
00223     }
00224     
00225     PlotLine *line = i->getLine(0);
00226     if (line && line->getSize() > 0)
00227     {
00228       if (line->getData(line->getSize() - 1) > 0)
00229       {
00230         QString ts;
00231         config.getData(Config::GroupPath, ts);
00232         QString s = "ln -s \"" + fileList[loop] + "\" " + ts + "/Scanner/" + scannerName;
00233         system(s);
00234       }
00235     }
00236     
00237     delete recordList;
00238     delete i;
00239     
00240     emit message(QString());
00241   }
00242   
00243   if (! prog.wasCancelled())
00244     emit message(QString("Scan complete"));
00245   
00246   config.closePlugin(iplugin);
00247   
00248   this->setEnabled(TRUE);
00249 
00250   emit scanComplete();
00251 }
00252 
00253 void Scanner::saveRule ()
00254 {
00255   QString s;
00256   config.getData(Config::ScannerPath, s);
00257   s.append("/" + scannerName);
00258 
00259   QFile f(s);
00260   if (! f.open(IO_WriteOnly))
00261     return;
00262   QTextStream stream(&f);
00263   
00264   stream << "allSymbols=" << QString::number(allSymbols->isChecked()) << "\n";
00265   stream << "compression=" << period->currentText() << "\n";
00266   stream << "bars=" << bars->text() << "\n";
00267   stream << "basepath=" << basePath->currentText() << "\n";
00268   
00269   int loop;
00270   for (loop = 0; loop < (int) fileList.count(); loop++)
00271     stream << "symbol=" << fileList[loop] << "\n";
00272   
00273   list->getText(s);
00274   QStringList l = QStringList::split("\n", s, FALSE);
00275   stream << "script=" << l.join("|") << "\n";
00276   
00277   f.close();
00278 }
00279 
00280 void Scanner::loadRule ()
00281 {
00282   QString s;
00283   config.getData(Config::ScannerPath, s);
00284   s.append("/" + scannerName);
00285 
00286   QFile f(s);
00287   if (! f.open(IO_ReadOnly))
00288     return;
00289   QTextStream stream(&f);
00290 
00291   fileList.clear();
00292   
00293   while(stream.atEnd() == 0)
00294   {
00295     s = stream.readLine();
00296     s = s.stripWhiteSpace();
00297 
00298     if (! s.length())
00299       continue;
00300       
00301     QString key;
00302     QString dat;
00303     if (s.contains("="))
00304     {
00305       int t = s.find("=", 0, TRUE);
00306       key = s.left(t);
00307       dat = s.right(s.length() - t - 1);
00308     }
00309     else
00310       continue;
00311 
00312     if (! key.compare("allSymbols"))
00313     {
00314       allSymbols->setChecked(dat.toInt());
00315       continue;
00316     }
00317     
00318     if (! key.compare("compression"))
00319     {
00320       period->setCurrentText(dat);
00321       continue;
00322     }
00323     
00324     if (! key.compare("symbol"))
00325     {
00326       fileList.append(dat);
00327       continue;
00328     }
00329 
00330     if (! key.compare("bars"))
00331     {
00332       bars->setValue(dat.toInt());
00333       continue;
00334     }
00335 
00336     if (! key.compare("basepath"))
00337     {
00338       if (! dat.compare(tr("Chart")))
00339         basePath->setCurrentItem(0);
00340       else
00341         basePath->setCurrentItem(1);
00342       continue;
00343     }
00344     
00345     if (! key.compare("script"))
00346     {
00347       QStringList l2 = QStringList::split("|", dat, FALSE);
00348       int loop;
00349       for (loop = 0; loop < (int) l2.count(); loop++)
00350         list->setLine(l2[loop]);
00351     }
00352   }
00353 
00354   fileButton->setText(QString::number(fileList.count()) + " Symbols");
00355   
00356   f.close();
00357 }
00358 
00359 void Scanner::exitDialog ()
00360 {
00361   reject();
00362   emit exitScanner();
00363 }
00364 
00365 void Scanner::getSymbols ()
00366 {
00367   QString s;
00368   if (! basePath->currentText().compare(tr("Chart")))
00369     config.getData(Config::DataPath, s);
00370   else
00371     config.getData(Config::GroupPath, s);
00372   QString s2("*");
00373   SymbolDialog *dialog = new SymbolDialog(this,
00374                                           s,
00375                                           s,
00376                                           s2,
00377                                           QFileDialog::ExistingFiles);
00378   dialog->setCaption(tr("Select symbols to scan"));
00379   
00380   int rc = dialog->exec();
00381 
00382   if (rc == QDialog::Accepted)
00383     fileList = dialog->selectedFiles();
00384     
00385   fileButton->setText(QString::number(fileList.count()) + " Symbols");
00386     
00387   delete dialog;
00388 }
00389 
00390 void Scanner::allSymbolsToggled (bool d)
00391 {
00392   if (d)
00393     fileButton->setEnabled(FALSE);
00394   else
00395     fileButton->setEnabled(TRUE);
00396 }
00397 
00398 void Scanner::slotHelp ()
00399 {
00400   QString s = "workwithscanner.html";
00401   HelpWindow *hw = new HelpWindow(this, s);
00402   hw->show();
00403 }
00404