plugins/quote/CSV/CSV.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 "CSV.h"
00023 #include "Bar.h"
00024 #include "../../../pics/newchart.xpm"
00025 #include "../../../pics/edit.xpm"
00026 #include "../../../pics/delete.xpm"
00027 #include "HelpWindow.h"
00028 #include "SymbolDialog.h"
00029 #include "CSVRuleDialog.h"
00030 #include "DBIndexItem.h"
00031 #include <qfile.h>
00032 #include <qtextstream.h>
00033 #include <qdir.h>
00034 #include <qsettings.h>
00035 #include <qmessagebox.h>
00036 #include <qlayout.h>
00037 #include <qlabel.h>
00038 #include <qtooltip.h>
00039 #include <qinputdialog.h>
00040 
00041 CSV::CSV ()
00042 {
00043   pluginName = "CSV";
00044   delim = ",";
00045   helpFile = "csv.html";
00046   cancelFlag = FALSE;
00047 
00048   reloadTimer = new QTimer(this);
00049   connect(reloadTimer, SIGNAL(timeout()), SLOT(parse()));
00050   
00051   config.getData(Config::QuotePluginStorage, ruleDir);
00052   ruleDir.append("/CSV");
00053   QDir dir;
00054   if (! dir.exists(ruleDir))
00055   {
00056     if (! dir.mkdir(ruleDir, TRUE))
00057       qDebug("CSVDialog::could not create storage directory %s", ruleDir.latin1());
00058   }
00059   
00060   createMainPage();
00061   setOkButton();
00062   setCancelButton();
00063   setHelpButton();
00064   QObject::connect(this, SIGNAL(helpButtonPressed()), this, SLOT(help()));
00065 
00066   loadSettings();
00067 
00068   updateRules();
00069   
00070   resize(400, 400);
00071 }
00072 
00073 CSV::~CSV ()
00074 {
00075   saveSettings();
00076 }
00077 
00078 void CSV::update ()
00079 {
00080   if (minutes->value() > 0)
00081     reloadTimer->start(60000 * minutes->value(), FALSE);
00082   parse();
00083 }
00084 
00085 void CSV::parse ()
00086 {
00087   Setting rule;
00088   getRule(rule);
00089   
00090   if (! rule.count())
00091   {
00092     QString s(tr("Empty rule"));
00093     printStatusLogMessage(s);
00094     downloadComplete();
00095     return;
00096   }
00097 
00098   QString ts = "Rule";
00099   QString ts2, s;
00100   rule.getData(ts, ts2);
00101   if (! ts2.contains("Date:"))
00102   {
00103     QString ss(tr("Rule missing Date field"));
00104     printStatusLogMessage(ss);
00105     downloadComplete();
00106     return;
00107   }
00108 
00109   ts = "Delimiter";
00110   rule.getData(ts, s);
00111   if (! s.length())
00112   {
00113     QString ss(tr("Delimiter not found"));
00114     printStatusLogMessage(ss);
00115     downloadComplete();
00116     return;
00117   }
00118   setDelimiter(s);
00119 
00120   if (dateRange->isChecked())
00121   {
00122     if (sdate->date() >= edate->date() || edate->date() <= sdate->date())
00123     {
00124       QString ss = stringDone + " " + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
00125       printStatusLogMessage(ss);
00126       downloadComplete();
00127       return;
00128     }
00129   }
00130 
00131   QString type;
00132   ts = "Type";
00133   rule.getData(ts, type);
00134   if (! type.length())
00135   {
00136     QString ss(tr("Type not found"));
00137     printStatusLogMessage(ss);
00138     downloadComplete();
00139     return;
00140   }
00141   
00142   ts = "Rule";
00143   rule.getData(ts, ts2);
00144   QStringList fieldList = QStringList::split(",", ts2, FALSE);
00145   if (! fieldList.count())
00146   {
00147     QString ss(tr("No rule found"));
00148     printStatusLogMessage(ss);
00149     downloadComplete();
00150     return;
00151   }
00152 
00153   // get the directory path offset
00154   ts = "Directory";
00155   QString directory;
00156   rule.getData(ts, directory);
00157   if (! directory.length())
00158   {
00159     QString ss(tr("Directory not found"));
00160     printStatusLogMessage(ss);
00161     downloadComplete();
00162     return;
00163   }
00164 
00165   // get the symbol filter
00166   ts = "SymbolFilter";
00167   rule.getData(ts, ts2);
00168   QStringList symbolFilter = QStringList::split(",", ts2, FALSE);
00169   
00170   // check for time field and set the tickflag  
00171   bool tickFlag = FALSE;
00172   ts = "Rule";
00173   rule.getData(ts, ts2);
00174   if (ts2.contains("Time"))
00175     tickFlag = TRUE;
00176   else
00177   {
00178     if (ts2.contains("HHMMSS"))
00179       tickFlag = TRUE;
00180   }
00181 
00182   QStringList list;
00183   file->getFile(list);
00184 
00185   int loop;
00186   for (loop = 0; loop < (int) list.count(); loop++)
00187   {
00188     if (cancelFlag)
00189       break;
00190       
00191     QFile f(list[loop]);
00192     if (! f.open(IO_ReadOnly))
00193       continue;
00194     QTextStream stream(&f);
00195 
00196     QString symbol = symbolOveride;
00197     if (! symbol.length() && fieldList.findIndex("Symbol") == -1)
00198     {
00199       QStringList l = QStringList::split("/", list[loop], FALSE);
00200       symbol = l[l.count() - 1];
00201 
00202       if (symbol.right(4).contains(".txt"))
00203         symbol.truncate(symbol.length() - 4);
00204 
00205       if (symbol.right(4).contains(".TXT"))
00206         symbol.truncate(symbol.length() - 4);
00207       
00208       while (symbol.contains("_"))
00209         symbol = symbol.remove(symbol.find("_", 0, TRUE), 1);
00210     }
00211 
00212     QString path;
00213     if (! type.compare("Stocks"))
00214     {
00215       QString tmp = "Stocks/" + directory;
00216       createDirectory(tmp, path);
00217       if (! path.length())
00218       {
00219         QString ss(tr("Unable to create directory"));
00220         printStatusLogMessage(ss);
00221         downloadComplete();
00222         f.close();
00223         return;
00224       }
00225     }
00226     else
00227     {
00228       if (! type.compare("Futures"))
00229       {
00230         QString tmp = "Futures/" + directory;
00231         createDirectory(tmp, path);
00232         if (! path.length())
00233         {
00234           QString ss(tr("Unable to create directory"));
00235           printStatusLogMessage(ss);
00236           downloadComplete();
00237           f.close();
00238           return;
00239         }
00240       }
00241     }
00242 
00243     path.append("/");
00244 
00245     if (symbol.length())
00246     {
00247       QString s = path;
00248       s.append(symbol);
00249       if (openDb(s, symbol, type, tickFlag))
00250         continue;
00251 //      QString ss = tr("Updating") + " " + symbol;
00252 //      printStatusLogMessage(ss);
00253         progressBar->setProgress(loop, (int) list.count());
00254     }
00255 
00256     int lineCount = 0;
00257     QFileInfo fi(f);
00258     QString fName = fi.fileName();
00259     while(stream.atEnd() == 0)
00260     {
00261       QString ts = stream.readLine();
00262       QString s;
00263       stripJunk(ts, s);
00264 
00265       QStringList l = QStringList::split(delim, s, FALSE);
00266       lineCount++;
00267       if (l.count() != fieldList.count())
00268       {
00269         QString ss = QString().sprintf(
00270           "%s - %s - %s: %s Number of fields in file (%i) != rule format (%i)",
00271           fName.latin1(), symbol.latin1(), tr("Line").latin1(),
00272           QString::number(lineCount).latin1(),  l.count(), fieldList.count()
00273           );
00274         printStatusLogMessage(ss);
00275         continue;
00276       }
00277       
00278       int fieldLoop;
00279       bool flag = FALSE;
00280       Setting r;
00281       for (fieldLoop = 0; fieldLoop < (int) fieldList.count(); fieldLoop++)
00282       {
00283         if (fieldList[fieldLoop].contains("Date:"))
00284         {
00285           QDate dt;
00286           getDate(fieldList[fieldLoop], l[fieldLoop], r, dt);
00287           if (! dt.isValid())
00288           {
00289             QString ss = QString().sprintf("%s - %s - %s: %s %s: %s",
00290               fName.latin1(), symbol.latin1(), tr("Line").latin1(), QString::number(lineCount).latin1(),
00291               tr("Bad date").latin1(), l[fieldLoop].latin1()
00292               );
00293             printStatusLogMessage(ss);
00294             flag = TRUE;
00295             break;
00296           }
00297           
00298           if (dateRange->isChecked())
00299           {
00300             if (dt < sdate->date() || dt > edate->date())
00301             {
00302               flag = TRUE;
00303               break;
00304             }
00305           }
00306           ts = "Date";
00307           ts2 = dt.toString("yyyyMMdd");
00308           r.setData(ts, ts2);
00309           continue;
00310         }
00311 
00312         if (! fieldList[fieldLoop].compare("Time"))
00313         {
00314           getTime(l[fieldLoop], s);
00315           if (! s.length())
00316           {
00317             QString ss = QString().sprintf("%s - %s - %s: %s %s: %s",
00318               fName.latin1(), symbol.latin1(), tr("Line").latin1(), QString::number(lineCount).latin1(),
00319               tr("Bad time").latin1(), l[fieldLoop].latin1()
00320               );
00321             printStatusLogMessage(ss);
00322             flag = TRUE;
00323             break;
00324           }
00325           ts = "Time";
00326           r.setData(ts, s);
00327           continue;
00328         }
00329         
00330         if (! fieldList[fieldLoop].compare("Symbol"))
00331         {
00332           if (symbolFilter.count())
00333           {
00334             if (symbolFilter.findIndex(l[fieldLoop]) == -1)
00335             {
00336               flag = TRUE;
00337               break;
00338             }
00339           }
00340           
00341           ts = "Symbol";
00342           r.setData(ts, l[fieldLoop]);
00343           continue;
00344         }
00345         
00346         if (! fieldList[fieldLoop].compare("Name"))
00347         {
00348           ts = "Name";
00349           r.setData(ts, l[fieldLoop]);
00350           continue;
00351         }
00352         
00353         if (! fieldList[fieldLoop].compare("Open") ||
00354             ! fieldList[fieldLoop].compare("High") ||
00355             ! fieldList[fieldLoop].compare("Low") ||
00356             ! fieldList[fieldLoop].compare("Close"))
00357         {
00358           if (setTFloat(l[fieldLoop], TRUE))
00359           {
00360             QString ss = QString().sprintf("%s - %s - %s: %i %s: %s",
00361               fName.latin1(), symbol.latin1(), tr("Line").latin1(), lineCount,
00362               tr("Bad value").latin1(), tr(fieldList[fieldLoop]).latin1()
00363               );
00364             printStatusLogMessage(ss);
00365             flag = TRUE;
00366             break;
00367           }
00368           ts = QString::number(tfloat);
00369           r.setData(fieldList[fieldLoop], ts);
00370           continue;
00371         }
00372         
00373         if (! fieldList[fieldLoop].compare("Volume") ||
00374             ! fieldList[fieldLoop].compare("OI"))
00375         {
00376           if (setTFloat(l[fieldLoop], FALSE))
00377           {
00378             QString ss = QString().sprintf("%s - %s - %s: %s %s: %s",
00379               fName.latin1(), symbol.latin1(), tr("Line").latin1(), QString::number(lineCount).latin1(),
00380               tr("Bad value").latin1(), tr(fieldList[fieldLoop]).latin1()
00381               );
00382             printStatusLogMessage(ss);
00383             flag = TRUE;
00384             break;
00385           }
00386           ts = QString::number(tfloat);
00387           r.setData(fieldList[fieldLoop], ts);
00388           continue;
00389         }
00390       }
00391       
00392       if (flag)
00393         continue;
00394 
00395       ts = "Date";
00396       r.getData(ts, s);
00397       if (! s.length())
00398         continue;
00399       
00400       ts = "Time";
00401       r.getData(ts, ts2);
00402       if (ts2.length())
00403         s.append(ts2);
00404       else
00405         s.append("000000");
00406         
00407       Bar bar;
00408       if (bar.setDate(s))
00409       {
00410         ts = "Date";
00411         r.getData(ts, ts2);
00412         QString ss = tr("Bad date") + " " + ts2;
00413         printStatusLogMessage(ss);
00414         continue;
00415       }
00416       bar.setTickFlag(tickFlag);
00417       ts = "Open";
00418       bar.setOpen(r.getDouble(ts));
00419       ts = "High";
00420       bar.setHigh(r.getDouble(ts));
00421       ts = "Low";
00422       bar.setLow(r.getDouble(ts));
00423       ts = "Close";
00424       bar.setClose(r.getDouble(ts));
00425       ts = "Volume";
00426       bar.setVolume(r.getDouble(ts));
00427       ts = "OI";
00428       bar.setOI(r.getInt(ts));
00429 
00430       DBIndexItem item;
00431 
00432       if (! symbol.length())
00433       {
00434         ts = "Symbol";
00435         QString t;
00436         r.getData(ts, t);
00437         s = path;
00438         s.append(t);
00439         if (openDb(s, t, type, tickFlag))
00440           continue;
00441         
00442         ts = "Name";
00443         r.getData(ts, s);
00444         if (s.length())
00445         {
00446           chartIndex->getIndexItem(t, item);
00447           item.setTitle(s);
00448           chartIndex->setIndexItem(t, item);
00449         }
00450 
00451         db.setBar(bar);
00452         
00453         ts = "Symbol";
00454         r.getData(ts, ts2);
00455 //        QString ss = tr("Updating") + " " + ts2;
00456 //        printStatusLogMessage(ss);
00457         config.closePlugin(type);
00458 
00459         db.close();
00460 
00461         emit signalWakeup();
00462       }
00463       else
00464       {
00465         ts = "Name";
00466         r.getData(ts, s);
00467         if (s.length())
00468         {
00469           chartIndex->getIndexItem(symbol, item);
00470           item.setTitle(s);
00471           chartIndex->setIndexItem(symbol, item);
00472         }
00473         db.setBar(bar);
00474 
00475         emit signalWakeup();
00476       }
00477     }
00478 
00479     db.close();
00480     f.close();
00481   }
00482 
00483   progressBar->setProgress((int) list.count(), (int) list.count());
00484   downloadComplete();
00485   if (cancelFlag)
00486   {
00487     cancelFlag = FALSE;
00488     printStatusLogMessage(stringCanceled);
00489   }
00490   else {
00491     QString ss = stringDone + " " + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
00492     printStatusLogMessage(ss);
00493   }
00494   progressBar->reset();
00495 }
00496 
00497 void CSV::setDelimiter (QString &d)
00498 {
00499   if (! d.compare("Comma"))
00500   {
00501     delim = ",";
00502     return;
00503   }
00504 
00505   if (! d.compare("Tab"))
00506   {
00507     delim = "   ";
00508     return;
00509   }
00510 
00511   if (! d.compare("Space"))
00512   {
00513     delim = " ";
00514     return;
00515   }
00516 
00517   if (! d.compare("Semicolon"))
00518   {
00519     delim = ";";
00520     return;
00521   }
00522 }
00523 
00524 void CSV::getTime (QString &d, QString &time)
00525 {
00526   time.truncate(0);
00527   
00528   if (! d.contains(":"))
00529   {
00530     if (d.length() == 6)
00531     {
00532       time = d;
00533       time.insert(4, ":");
00534       time.insert(2, ":");
00535       return;
00536     }
00537     else
00538       return;
00539   }
00540     
00541   QStringList l = QStringList::split(":", d, FALSE);
00542   if (l.count() != 3)
00543     return;
00544     
00545   time = l[0] + l[1];
00546    
00547   if (l[2].toInt() < 10)
00548     time.append("0");
00549   time.append(QString::number(l[2].toInt()));
00550 }
00551 
00552 void CSV::getDate (QString &k, QString &d, Setting &r, QDate &date)
00553 {
00554   QStringList l;
00555   QString dateString = d;
00556   QString timeString;
00557   
00558   if (d.contains(" "))
00559   {
00560     QStringList l2 = QStringList::split(" ", d, FALSE);
00561     dateString = l2[0];
00562     timeString = l2[1];
00563   }
00564 
00565   while (1)
00566   {
00567     if (dateString.contains("/"))
00568     {
00569       l = QStringList::split("/", dateString, FALSE);
00570       if (l.count() != 3)
00571         return;
00572       else
00573         dateString = l.join(QString::null);
00574       break;
00575     }
00576 
00577     if (dateString.contains("-"))
00578     {
00579       l = QStringList::split("-", dateString, FALSE);
00580       if (l.count() != 3)
00581         return;
00582       else
00583         dateString = l.join(QString::null);
00584       break;
00585     }
00586 
00587     if (dateString.contains("."))
00588     {
00589       l = QStringList::split(".", dateString, FALSE);
00590       if (l.count() != 3)
00591         return;
00592       else
00593         dateString = l.join(QString::null);
00594       break;
00595     }
00596 
00597     break;
00598   }
00599 
00600   while (1)
00601   {
00602     if (! k.compare("Date:YYYYMMDD"))
00603     {
00604       if (l.count())
00605         date.setYMD(l[0].toInt(), l[1].toInt(), l[2].toInt());
00606       else
00607       {
00608         if (dateString.length() == 8)
00609           date.setYMD(dateString.left(4).toInt(), dateString.mid(4, 2).toInt(),
00610           dateString.right(2).toInt());
00611       }
00612       break;
00613     }
00614 
00615     if (! k.compare("Date:YYMMDD"))
00616     {
00617       if (l.count())
00618         date.setYMD(l[0].toInt(), l[1].toInt(), l[2].toInt());
00619       else
00620       {
00621         if (dateString.length() == 6)
00622           date.setYMD(dateString.left(2).toInt(), dateString.mid(2, 2).toInt(),
00623           dateString.right(2).toInt());
00624       }
00625       break;
00626     }
00627 
00628     if (! k.compare("Date:MMDDYYYY"))
00629     {
00630       if (l.count())
00631         date.setYMD(l[2].toInt(), l[0].toInt(), l[1].toInt());
00632       else
00633       {
00634         if (dateString.length() == 8)
00635           date.setYMD(dateString.right(4).toInt(), dateString.left(2).toInt(),
00636           dateString.mid(2, 2).toInt());
00637       }
00638       break;
00639     }
00640 
00641     if (! k.compare("Date:MMDDYY"))
00642     {
00643       if (l.count())
00644         date.setYMD(l[2].toInt(), l[0].toInt(), l[1].toInt());
00645       else
00646       {
00647         if (dateString.length() == 6)
00648           date.setYMD(dateString.right(2).toInt(), dateString.left(2).toInt(),
00649           dateString.mid(2, 2).toInt());
00650       }
00651       break;
00652     }
00653 
00654     if (! k.compare("Date:DDMMYYYY"))
00655     {
00656       if (l.count())
00657         date.setYMD(l[2].toInt(), l[1].toInt(), l[0].toInt());
00658       else
00659       {
00660         if (dateString.length() == 8)
00661           date.setYMD(dateString.right(4).toInt(), dateString.mid(2, 2).toInt(),
00662           dateString.left(2).toInt());
00663       }
00664       break;
00665     }
00666 
00667     if (! k.compare("Date:MMDDYYYYHHMMSS"))
00668     {
00669       QString s;
00670       getTime(timeString, s);
00671       if (s.length())
00672       {
00673         QString ts = "Time";
00674         r.setData(ts, s);
00675       }
00676       else
00677         break;
00678       
00679       if (l.count())
00680         date.setYMD(l[2].toInt(), l[0].toInt(), l[1].toInt());
00681       else
00682       {
00683         if (dateString.length() == 8)
00684           date.setYMD(dateString.right(4).toInt(), dateString.left(2).toInt(),
00685           dateString.mid(2, 2).toInt());
00686       }
00687       
00688       break;
00689     }
00690     
00691     if (! k.compare("Date:YYYYMMDDHHMMSS"))
00692     {
00693       timeString = d.right(6);
00694       dateString = d.left(8);
00695       QString s;
00696       getTime(timeString, s);
00697       if (s.length())
00698       {
00699         QString ts = "Time";
00700         r.setData(ts, s);
00701       }
00702       else
00703         break;
00704       
00705       if (l.count())
00706         date.setYMD(l[0].toInt(), l[1].toInt(), l[2].toInt());
00707       else
00708       {
00709         if (dateString.length() == 8)
00710           date.setYMD(dateString.left(4).toInt(), dateString.mid(4, 2).toInt(),
00711           dateString.right(2).toInt());
00712       }
00713       
00714       break;
00715     }
00716     
00717     break;
00718   }
00719 }
00720 
00721 bool CSV::openDb (QString &path, QString &symbol, QString &type, bool tickFlag)
00722 {
00723   if (db.open(path, chartIndex))
00724   {
00725     qDebug("CSV::openDb:can't open chart");
00726     QString ss("CSV::OpenDb:Could not open db.");
00727     printStatusLogMessage(ss);
00728     db.close();
00729     return TRUE;
00730   }
00731   
00732   QString s;
00733   DBIndexItem item;
00734   chartIndex->getIndexItem(symbol, item);
00735   item.getSymbol(s);
00736   if (! s.length())
00737   {
00738     if (! type.compare("Futures"))
00739     {
00740       db.setType(DbPlugin::Futures1);
00741       if (db.createNewFutures())
00742       {
00743         db.close();
00744         return TRUE;
00745       }
00746     }
00747     else
00748     {
00749       if(db.createNewStock())
00750       {
00751         db.close();
00752         return TRUE;
00753       }
00754     }
00755 
00756     item.setSymbol(symbol);    
00757     item.setBarType(tickFlag);
00758     chartIndex->setIndexItem(symbol, item);
00759   }
00760 
00761   // verify if this chart can be updated by this plugin
00762   item.getQuotePlugin(s);
00763   if (! s.length())
00764   {
00765     item.setQuotePlugin(pluginName);
00766     chartIndex->setIndexItem(symbol, item);
00767   }
00768   else
00769   {
00770     if (s.compare(pluginName))
00771     {
00772       s = symbol + " - skipping update. Source does not match destination.";
00773       printStatusLogMessage(s);
00774       db.close();
00775       return TRUE;
00776     }
00777   }
00778 
00779   return FALSE;
00780 }
00781 
00782 void CSV::loadSettings ()
00783 {
00784   QSettings settings;
00785   settings.beginGroup("/Qtstalker/CSV plugin");
00786 
00787   QString s = settings.readEntry("/RuleName");
00788   ruleCombo->setCurrentText(s);
00789 
00790   s = settings.readEntry("/DateRange", "0");
00791   dateRange->setChecked(s.toInt());
00792   dateRangeChanged(s.toInt());
00793   
00794   lastPath = settings.readEntry("/lastPath", QDir::homeDirPath());
00795   QStringList l;
00796   l.append(lastPath);
00797   file->setFile(l);
00798 
00799   s = settings.readEntry("/ReloadInterval", "0");
00800   minutes->setValue(s.toInt());
00801 
00802   settings.endGroup();
00803 }
00804 
00805 void CSV::saveSettings ()
00806 {
00807   QSettings settings;
00808   settings.beginGroup("/Qtstalker/CSV plugin");
00809 
00810   settings.writeEntry("/RuleName", ruleCombo->currentText());
00811   settings.writeEntry("/DateRange", QString::number(dateRange->isChecked()));
00812   settings.writeEntry("/ReloadInterval", minutes->text());
00813 
00814   QStringList l;
00815   file->getFile(l);
00816   if (l.count())
00817     lastPath = l[0];
00818   settings.writeEntry("/lastPath", lastPath);
00819   
00820   settings.endGroup();
00821 }
00822 
00823 void CSV::getRule (Setting &set)
00824 {
00825   QString s = ruleDir +"/" + ruleCombo->currentText();
00826   QFile f(s);
00827   if (! f.open(IO_ReadOnly))
00828   {
00829     qDebug("CSV::getRule:cannot read file.");
00830     return;
00831   }
00832   QTextStream stream(&f);
00833 
00834   while(stream.atEnd() == 0)
00835   {
00836     s = stream.readLine();
00837     s = s.stripWhiteSpace();
00838     if (! s.length())
00839       continue;
00840       
00841     QStringList l = QStringList::split("=", s, FALSE);
00842     if (l.count() != 2)
00843       continue;
00844       
00845     set.setData(l[0], l[1]);
00846   }
00847   
00848   f.close();
00849 }
00850 
00851 void CSV::cancelUpdate ()
00852 {
00853   cancelFlag = TRUE;
00854 }
00855 
00856 void CSV::createMainPage ()
00857 {
00858   setCaption(tr("CSV Quotes"));
00859 
00860   QString s = "new";
00861   QString s2 = tr("New Rule");
00862   toolbar->addButton(s, newchart, s2);
00863   QObject::connect(toolbar->getButton(s), SIGNAL(clicked()), this, SLOT(newRule()));
00864   
00865   s = "edit";
00866   s2 = tr("Edit Rule");
00867   toolbar->addButton(s, edit, s2);
00868   QObject::connect(toolbar->getButton(s), SIGNAL(clicked()), this, SLOT(editRule()));
00869   
00870   s = "delete";
00871   s2 = tr("Delete Rule");
00872   toolbar->addButton(s, deleteitem, s2);
00873   QObject::connect(toolbar->getButton(s), SIGNAL(clicked()), this, SLOT(deleteRule()));
00874   
00875   QLabel *label = new QLabel(tr("Rule"), baseWidget);
00876   grid->addWidget(label, 0, 0);
00877 
00878   ruleCombo = new QComboBox(baseWidget);
00879   updateRules();
00880   grid->addWidget(ruleCombo, 0, 1);
00881   
00882   label = new QLabel(tr("Input"), baseWidget);
00883   grid->addWidget(label, 1, 0);
00884   
00885   QStringList l;
00886   file = new FileButton(baseWidget, l, lastPath);
00887   grid->addWidget(file, 1, 1);
00888 
00889   label = new QLabel(tr("Symbol"), baseWidget);
00890   grid->addWidget(label, 2, 0);
00891   
00892   symbol = new QLineEdit(baseWidget);
00893   grid->addWidget(symbol, 2, 1);
00894   
00895   label = new QLabel(tr("Auto Reload"), baseWidget);
00896   grid->addWidget(label, 3, 0);
00897   
00898   minutes = new QSpinBox(baseWidget);
00899   minutes->setMinValue(0);
00900   minutes->setMaxValue(99);
00901   minutes->setLineStep(1);
00902   QObject::connect(minutes, SIGNAL(valueChanged(int)), this, SLOT(reloadTimerChanged(int)));
00903   grid->addWidget(minutes, 3, 1);
00904   
00905   dateRange = new QCheckBox(tr("Select Date Range"), baseWidget);
00906   QObject::connect(dateRange, SIGNAL(toggled(bool)), this, SLOT(dateRangeChanged(bool)));
00907   grid->addWidget(dateRange, 5, 0);
00908   
00909   label = new QLabel(tr("Date Start"), baseWidget);
00910   grid->addWidget(label, 6, 0);
00911   
00912   sdate = new QDateEdit(QDate::currentDate(), baseWidget);
00913   sdate->setAutoAdvance(TRUE);
00914   sdate->setOrder(QDateEdit::YMD);
00915   grid->addWidget(sdate, 6, 1);
00916   
00917   label = new QLabel(tr("Date End"), baseWidget);
00918   grid->addWidget(label, 7, 0);
00919   
00920   edate = new QDateEdit(QDate::currentDate(), baseWidget);
00921   edate->setAutoAdvance(TRUE);
00922   edate->setOrder(QDateEdit::YMD);
00923   grid->addWidget(edate, 7, 1);
00924 
00925   // set the default end date
00926   QDate dt = QDate::currentDate();
00927   if (dt.dayOfWeek() == 6)
00928     dt = dt.addDays(-1);
00929   else
00930   {
00931     if (dt.dayOfWeek() == 7)
00932       dt = dt.addDays(-2);
00933   }
00934   edate->setDate(dt);
00935   sdate->setDate(dt);
00936 }
00937 
00938 void CSV::newRule ()
00939 {
00940   bool ok = FALSE;
00941   QString s = QInputDialog::getText(tr("New Rule"),
00942                                     tr("Enter new rule name."),
00943                                     QLineEdit::Normal,
00944                                     tr("NewRule"),
00945                                     &ok,
00946                                     this);
00947   if ((! ok) || (s.isNull()))
00948     return;
00949     
00950   // remove any bad chars
00951   int loop;
00952   QString name;
00953   for (loop = 0; loop < (int) s.length(); loop++)
00954   {
00955     QChar c = s.at(loop);
00956     if (c.isLetterOrNumber())
00957       name.append(c);
00958   }
00959     
00960   QDir dir;
00961   s = ruleDir + "/" + name;
00962   if (dir.exists(s))
00963   {
00964     QMessageBox::information(this, tr("Warning"), tr("This rule already exists."));
00965     return;
00966   }
00967     
00968   CSVRuleDialog *dialog = new CSVRuleDialog(this, s);
00969           
00970   int rc = dialog->exec();
00971   
00972   if (rc == QDialog::Accepted)
00973   {
00974     updateRules();
00975   }
00976   
00977   delete dialog;
00978 }
00979 
00980 void CSV::editRule ()
00981 {
00982   QString s("*");
00983   SymbolDialog *dialog = new SymbolDialog(this,
00984                                           ruleDir,
00985                                           ruleDir,
00986                                           s,
00987                                           QFileDialog::ExistingFiles);
00988   dialog->setCaption(tr("Select Rule To Edit"));
00989 
00990   int rc = dialog->exec();
00991 
00992   if (rc == QDialog::Rejected)
00993   {
00994     delete dialog;
00995     return;
00996   }
00997 
00998   QStringList l = dialog->selectedFiles();
00999   delete dialog;
01000   if (! l.count())
01001     return;
01002 
01003   CSVRuleDialog *rdialog = new CSVRuleDialog(this, l[0]);
01004           
01005   rc = rdialog->exec();
01006   
01007   delete rdialog;
01008 }
01009 
01010 void CSV::deleteRule ()
01011 {
01012   QString s("*");
01013   SymbolDialog *dialog = new SymbolDialog(this,
01014                                           ruleDir,
01015                                           ruleDir,
01016                                           s,
01017                                           QFileDialog::ExistingFiles);
01018   dialog->setCaption(tr("Select Rules To Delete"));
01019 
01020   int rc = dialog->exec();
01021 
01022   if (rc == QDialog::Accepted)
01023   {
01024     rc = QMessageBox::warning(this,
01025                               tr("Qtstalker: Warning"),
01026                               tr("Are you sure you want to delete this rule?"),
01027                               QMessageBox::Yes,
01028                               QMessageBox::No,
01029                               QMessageBox::NoButton);
01030 
01031     if (rc == QMessageBox::No)
01032     {
01033       delete dialog;
01034       return;
01035     }
01036 
01037     QStringList l = dialog->selectedFiles();
01038     delete dialog;
01039     if (! l.count())
01040       return;
01041     
01042     int loop;
01043     QDir dir;
01044     for (loop = 0; loop < (int) l.count(); loop++)
01045       dir.remove(l[loop]);
01046     
01047     updateRules();
01048   }
01049   else
01050     delete dialog;
01051 }
01052 
01053 void CSV::reloadTimerChanged (int t)
01054 {
01055   if (t == 0)
01056   {
01057     QString ss = "Reload timer is off";
01058     printStatusLogMessage(ss);
01059     reloadTimer->stop();
01060   }
01061   else
01062   {
01063     QString sm = t>1 ? " minutes" : " minute";
01064     QString ss = "Reload timer is restarted (interval=" + QString::number(t) + sm + ")";
01065     printStatusLogMessage(ss);
01066     reloadTimer->start(60000 * t, FALSE);
01067   }
01068 }
01069 
01070 void CSV::dateRangeChanged (bool d)
01071 {
01072   sdate->setEnabled(d);
01073   edate->setEnabled(d);
01074 }
01075 
01076 void CSV::updateRules ()
01077 {
01078   QString current = ruleCombo->currentText();
01079   
01080   ruleCombo->clear();
01081   
01082   QStringList l;
01083   QDir dir(ruleDir);
01084   int loop;
01085   for (loop = 2; loop < (int) dir.count(); loop++)
01086   {
01087     QString s = dir.absPath() + "/" + dir[loop];
01088     QFileInfo fi(s);
01089     if (! fi.isDir())
01090       l.append(dir[loop]);
01091   }
01092   ruleCombo->insertStringList(l, -1);
01093 
01094   if (current.length())
01095     ruleCombo->setCurrentItem(l.findIndex(current));
01096 }
01097 
01098 void CSV::help ()
01099 {
01100   HelpWindow *hw = new HelpWindow(this, helpFile);
01101   hw->show();
01102 }
01103 
01104 //**********************************************************
01105 //**********************************************************
01106 //**********************************************************
01107 
01108 QuotePlugin * createQuotePlugin ()
01109 {
01110   CSV *o = new CSV;
01111   return ((QuotePlugin *) o);
01112 }
01113 
01114