lib/UpgradeMessage.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 "UpgradeMessage.h"
00023 #include "Config.h"
00024 #include "DbPlugin.h"
00025 #include "Traverse.h"
00026 #include <qlayout.h>
00027 #include <qwidget.h>
00028 #include <qstring.h>
00029 #include <qtextedit.h>
00030 #include <qlabel.h>
00031 #include <qmessagebox.h>
00032 #include <qfileinfo.h>
00033 #include <qdir.h>
00034 #include <qfile.h>
00035 #include <qpushbutton.h>
00036 #include <db.h>
00037 
00038 UpgradeMessage::UpgradeMessage (int type) : QTabDialog (0, "UpgradeMessage", TRUE)
00039 {
00040   switch (type)
00041   {
00042     case V031:
00043       createPage031();
00044       break;
00045     case V034:
00046       createPage034();
00047       break;
00048     default:
00049       break;
00050   }
00051 }
00052 
00053 UpgradeMessage::~UpgradeMessage ()
00054 {
00055 }
00056 
00057 void UpgradeMessage::createPage031 ()
00058 {
00059   QWidget *w = new QWidget(this);
00060   
00061   QVBoxLayout *vbox = new QVBoxLayout(w);
00062   vbox->setMargin(5);
00063   vbox->setSpacing(5);
00064 
00065   QString s = tr("This version of Qtstalker uses a new data format.");
00066   s.append(tr(" It can not read data files from previous versions."));
00067   s.append(tr(" This means that you will start with an empty workspace."));
00068   s.append(tr(" Your old data files have been preserved in $HOME/Qtstalker"));
00069   s.append(tr(" and can still be accessed by older Qtstalker versions."));
00070   s.append(tr(" If you don't intend to downgrade to a previous Qtstalker"));
00071   s.append(tr(" version, then you can remove that directory."));
00072 
00073   QTextEdit *message = new QTextEdit(w);
00074   message->setReadOnly(TRUE);
00075   message->setText(s);
00076   vbox->addWidget(message);
00077 
00078   check = new QCheckBox(tr("Do not show this message again."), w);
00079   vbox->addWidget(check);
00080 
00081   addTab(w, tr("Warning"));
00082   
00083   setOkButton(tr("&OK"));
00084   setCancelButton(tr("&Cancel"));
00085 }
00086 
00087 bool UpgradeMessage::getStatus ()
00088 {
00089   return check->isChecked();
00090 }
00091 
00092 void UpgradeMessage::createPage034 ()
00093 {
00094   QWidget *w = new QWidget(this);
00095   
00096   QVBoxLayout *vbox = new QVBoxLayout(w);
00097   vbox->setMargin(5);
00098   vbox->setSpacing(5);
00099 
00100   QString s = tr("Your workspace will be converted into the ~/.qtstalker/data1/ directory.");
00101   s.append(tr(" It could take a long time if there are many data items."));
00102   s.append(tr(" When satisfied, the old workspace can be manually removed from ~/.qtstalker/data0/\n"));
00103   s.append(tr("\n"));
00104   s.append(tr(" If you choose Cancel, then Quit immediately and see the cleanup notes in docs/install.html"));
00105   QTextEdit *message = new QTextEdit(w);
00106   message->setReadOnly(TRUE);
00107   message->setText(s);
00108   vbox->addWidget(message);
00109 
00110   QHBoxLayout *hbox = new QHBoxLayout(vbox);
00111   hbox->setSpacing(2);
00112 
00113   QLabel *label = new QLabel(tr("Progress"), w);
00114   hbox->addWidget(label);
00115 
00116   progBar = new QProgressBar(w);
00117   hbox->addWidget(progBar);
00118 
00119   addTab(w, tr("Chart Conversion"));
00120 
00121   QPushButton *button = new QPushButton(tr("Perform Conversion"), w);
00122   QObject::connect(button, SIGNAL(clicked()), this, SLOT(convert034()));
00123   vbox->addWidget(button);
00124 
00125   vbox->addStretch(1);
00126   
00127   setOkButton(QString::null);  
00128 
00129   setCancelButton(tr("&Cancel"));
00130 
00131   resize(500, 300);
00132 }
00133 
00134 void UpgradeMessage::convert034 ()
00135 {
00136   // get all chart paths
00137   QStringList symbolList;
00138   Config config;
00139   QString dataPath;
00140   config.getData(Config::DataPath, dataPath);
00141   int t = dataPath.find("/data1/", 0, TRUE);
00142   dataPath.replace(t + 5, 1, "0");
00143   Traverse trav(Traverse::File);
00144   trav.traverse(dataPath);
00145   trav.getList(symbolList);
00146 
00147   QString s;
00148   config.getData(Config::IndexPath, s);
00149   index.open(s);
00150   
00151   int loop;
00152   for (loop = 0; loop < (int) symbolList.count(); loop++)
00153   {
00154     progBar->setProgress(loop, (int) symbolList.count());
00155 
00156     if (createDir(symbolList[loop]))
00157       continue;
00158 
00159     qDebug("Converting %s", symbolList[loop].latin1());
00160     if (createChart(symbolList[loop]))
00161       continue;
00162   }
00163 
00164   index.close();
00165 
00166   copyFiles();
00167 
00168   progBar->setProgress((int) symbolList.count(), (int) symbolList.count());
00169 
00170   qDebug("Conversion complete");
00171 }
00172 
00173 bool UpgradeMessage::createChart (QString &path)
00174 {
00175   DB *olddb = 0;
00176   int rc = db_create(&olddb, NULL, 0);
00177   if (rc)
00178   {
00179    qDebug("UpgradeMessage::createChart: %s", db_strerror(rc));
00180     return TRUE;
00181   }
00182   
00183   rc = olddb->open(olddb, NULL, (char *) path.latin1(), NULL, DB_BTREE, DB_RDONLY, 0664);
00184   if (rc)
00185   {
00186     qDebug("UpgradeMessage::createChart: %s", db_strerror(rc));
00187     return TRUE;
00188   }
00189 
00190   QString newPath = path;
00191   int t = newPath.find("/data0/", 0, TRUE);
00192   newPath.replace(t + 5, 1, "1");
00193   DbPlugin db;
00194   if (db.open(newPath, &index))
00195   {
00196     olddb->close(olddb, 0);
00197     return TRUE;
00198   }
00199 
00200   QFileInfo fi(newPath);
00201   QString fn = fi.fileName();
00202 
00203   DBIndexItem item;
00204 
00205   DBT key, data;
00206   DBC *cur;
00207   memset(&key, 0, sizeof(DBT));
00208   memset(&data, 0, sizeof(DBT));
00209   olddb->cursor(olddb, NULL, &cur, 0);
00210   while (! cur->c_get(cur, &key, &data, DB_NEXT))
00211   {
00212     QString k = (char *) key.data;
00213     QString d = (char *) data.data;
00214     if (key.size != 15)
00215     {
00216       saveHeaderData(db, k, d, fn, item);
00217       continue;
00218     }
00219 
00220     Bar bar;
00221     if (bar.setDate(k))
00222       continue;
00223   
00224     QStringList l = QStringList::split(",", d, FALSE);
00225     bar.setOpen(l[0].toDouble());
00226     bar.setHigh(l[1].toDouble());
00227     bar.setLow(l[2].toDouble());
00228     bar.setClose(l[3].toDouble());
00229     bar.setVolume(l[4].toDouble());
00230     if (l.count() == 6)
00231       bar.setOI(l[5].toInt());
00232     db.setBar(bar);
00233   }
00234   cur->c_close(cur);
00235 
00236   olddb->close(olddb, 0);
00237   db.close();
00238 
00239   index.setIndexItem(fn, item);
00240 
00241   return FALSE;
00242 }
00243 
00244 void UpgradeMessage::saveHeaderData (DbPlugin &db, QString &k, QString &d, QString &sym, DBIndexItem &item)
00245 {
00246   // is this a co key?
00247   bool ok = FALSE;
00248   double t = k.toDouble(&ok);
00249   if (ok)
00250   {
00251     if (t < 10000)
00252     {
00253       // its a chart object
00254       Setting t;
00255       t.parse(d);
00256       QString s = "Plugin";
00257       QString s2;
00258       t.getData(s,s2);
00259       if (s2.length())
00260       {
00261         t.remove(s);
00262         s = "Type";
00263         t.setData(s, s2);
00264       }
00265 
00266       s = "Plot";
00267       t.getData(s, s2);
00268       if (! s2.compare("Main Plot"))
00269       {
00270         s2 = "Bars";
00271         t.setData(s, s2);
00272       }
00273       else
00274         return;
00275 
00276       index.setChartObject(sym, k, t);
00277       return;
00278     }
00279   }
00280 
00281   if (! k.compare("Type"))
00282   {
00283     item.setType(d);
00284     return;
00285   }
00286 
00287   if (! k.compare("FuturesType"))
00288   {
00289     item.setFuturesType(d);
00290     return;
00291   }
00292 
00293   if (! k.compare("FuturesMonth"))
00294   {
00295     item.setFuturesMonth(d);
00296     return;
00297   }
00298 
00299   if (! k.compare("BarType"))
00300   {
00301     item.setBarType(d);
00302     return;
00303   }
00304 
00305   if (! k.compare("Fundamentals"))
00306   {
00307     index.setFundamentals(sym, d);
00308     return;
00309   }
00310 
00311   if (! k.compare("LocalIndicators"))
00312   {
00313     index.addIndicator(sym, d);
00314     return;
00315   }
00316 
00317   if (! k.compare("QuotePlugin"))
00318   {
00319     item.setQuotePlugin(d);
00320     return;
00321   }
00322 
00323   if (! k.compare("Symbol"))
00324   {
00325     item.setSymbol(d);
00326     return;
00327   }
00328 
00329   if (! k.compare("Title"))
00330   {
00331     item.setTitle(d);
00332     return;
00333   }
00334 
00335   if (! k.compare("Path"))
00336   {
00337     item.setPath(d);
00338     return;
00339   }
00340 
00341   if (! k.compare("SpreadFirstSymbol"))
00342   {
00343     int t = d.find("/data0/", 0, TRUE);
00344     d.replace(t + 5, 1, "1");
00345     QString ts = "FirstSymbol";
00346     db.setData(ts, d);
00347     return;
00348   }
00349 
00350   if (! k.compare("SpreadSecondSymbol"))
00351   {
00352     int t = d.find("/data0/", 0, TRUE);
00353     d.replace(t + 5, 1, "1");
00354     QString ts = "SecondSymbol";
00355     db.setData(ts, d);
00356     return;
00357   }
00358 
00359   if (! k.compare("IndexList"))
00360   {
00361     while (1)
00362     {
00363       int t = d.find("/data0/", 0, TRUE);
00364       if (t == -1)
00365         break;
00366       else
00367         d.replace(t + 5, 1, "1");
00368     }
00369     QString ts = "List";
00370     db.setData(ts, d);
00371     return;
00372   }
00373 
00374   if (! k.compare("CCAdjustment"))
00375   {
00376     QString ts = "Adjustment";
00377     db.setData(ts, d);
00378     return;
00379   }
00380 }
00381 
00382 bool UpgradeMessage::createDir (QString &p)
00383 {
00384   QString path = p;
00385   int t = path.find("/data0/", 0, TRUE);
00386   path.replace(t + 5, 1, "1");
00387   
00388   QStringList l = QStringList::split("/", path, FALSE);
00389   int loop = l.findIndex(".qtstalker");
00390   loop = loop + 2;
00391   for (; loop < (int) l.count() - 1; loop++)
00392   {
00393     QString s;
00394     int loop2;
00395     for (loop2 = 0; loop2 <= loop; loop2++)
00396       s.append("/" + l[loop2]);
00397 
00398     QDir dir(s);
00399     if (! dir.exists(s, TRUE))
00400     {
00401       if (! dir.mkdir(s, TRUE))
00402       {
00403         qDebug("UpgradeMessage::createDir: error %s", s.latin1());
00404         return TRUE;
00405       }
00406     }
00407   }
00408 
00409   return FALSE;
00410 }
00411 
00412 void UpgradeMessage::copyFiles ()
00413 {
00414   QString oldPath, newPath;
00415   Config config;
00416   config.getData(Config::Home, oldPath);
00417   newPath = oldPath;
00418   oldPath.truncate(oldPath.length() - 1);
00419   oldPath.append("0");
00420   Traverse trav(Traverse::File);
00421 
00422   // copy group files
00423   qDebug("Converting group files...");
00424 
00425   QStringList l;
00426   QString s = oldPath + "/group";
00427   trav.traverse(s);
00428   trav.getList(l);
00429 
00430   int loop;
00431   for (loop = 0; loop < (int) l.count(); loop++)
00432   {
00433     QFileInfo fi(l[loop]);
00434     s = fi.readLink();
00435     int t = s.find("/data0/", 0, TRUE);
00436     s.replace(t + 5, 1, "1");
00437 
00438     if (createDir(l[loop]))
00439       continue;
00440 
00441     QString s2 = l[loop];
00442     t = s2.find("/data0/", 0, TRUE);
00443     s2.replace(t + 5, 1, "1");
00444 
00445     s = "ln -s " + s + " " + s2;
00446 
00447     if (system(s.latin1()))
00448       qDebug("UpgradeMessage::copyFiles: error creating symlink for group file");
00449   }
00450 
00451   // copy indicator files
00452   qDebug("Converting indicator files...");
00453   s = "cp -R " + oldPath + "/indicator " + newPath;
00454   if (system(s.latin1()))
00455     qDebug("UpgradeMessage::copyFiles: error copying indicator files");
00456   l.clear();
00457   s = newPath + "/indicator";
00458   trav.clear();
00459   trav.traverse(s);
00460   trav.getList(l);
00461   correctPathFiles(l);
00462 
00463   // copy plugin files
00464   qDebug("Converting plugin files...");
00465   s = "cp -R " + oldPath + "/plugin " + newPath;
00466   if (system(s.latin1()))
00467     qDebug("UpgradeMessage::copyFiles: error copying indicator files");
00468 
00469   // copy portfolio files
00470   qDebug("Converting portfolio files...");
00471   s = "cp -R " + oldPath + "/portfolio " + newPath;
00472   if (system(s.latin1()))
00473     qDebug("UpgradeMessage::copyFiles: error copying portfolio files");
00474   l.clear();
00475   s = newPath + "/portfolio";
00476   trav.clear();
00477   trav.traverse(s);
00478   trav.getList(l);
00479   correctPathFiles(l);
00480 
00481   // copy scanner files
00482   qDebug("Converting scanner files...");
00483   s = "cp -R " + oldPath + "/scanner " + newPath;
00484   if (system(s.latin1()))
00485     qDebug("UpgradeMessage::copyFiles: error copying scanner files");
00486   l.clear();
00487   s = newPath + "/scanner";
00488   trav.clear();
00489   trav.traverse(s);
00490   trav.getList(l);
00491   correctPathFiles(l);
00492 
00493   // copy test files
00494   qDebug("Converting test files...");
00495   s = "cp -R " + oldPath + "/test " + newPath;
00496   if (system(s.latin1()))
00497     qDebug("UpgradeMessage::copyFiles: error copying test files");
00498   l.clear();
00499   s = newPath + "/test";
00500   trav.clear();
00501   trav.traverse(s);
00502   trav.getList(l);
00503   correctPathFiles(l);
00504 }
00505 
00506 void UpgradeMessage::correctPathFiles (QStringList &list)
00507 {
00508   int loop;
00509   for (loop = 0; loop < (int) list.count(); loop++)
00510   {
00511     QFile inFile(list[loop]);
00512     if (! inFile.open(IO_ReadOnly))
00513     {
00514       qDebug("UpgradeMessage::correctPathFiles: error opening input file");
00515       continue;
00516     }
00517     QTextStream inStream(&inFile);
00518   
00519     QStringList l;
00520     while(inStream.atEnd() == 0)
00521     {
00522       QString s = inStream.readLine();
00523       s = s.stripWhiteSpace();
00524       if (! s.length())
00525         continue;
00526       l.append(s);
00527     }
00528     inFile.close();
00529 
00530     QFile outFile(list[loop]);
00531     if (! outFile.open(IO_WriteOnly))
00532     {
00533       qDebug("UpgradeMessage::correctPathFiles: error opening output file");
00534       continue;
00535     }
00536     QTextStream outStream(&outFile);
00537 
00538     int loop2;
00539     for (loop2 = 0; loop2 < (int) l.count(); loop2++)
00540     {
00541       int t = l[loop2].find("/data0/", 0, TRUE);
00542       if (t != -1)
00543         l[loop2].replace(t + 5, 1, "1");
00544       outStream << l[loop2] << "\n";
00545     }
00546 
00547     outFile.close();
00548   }
00549 }