TinkerCell Core 1.0
TinkerCell's Core library providing all basic functionalities
DataTable.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003 Copyright (c) 2008 Deepak Chandran
00004 Contact: Deepak Chandran (dchandran1@gmail.com)
00005 See COPYRIGHT.TXT
00006 
00007 This file defines the DataTable class. 
00008 The DataTable is a template class that contains a 2D vector (values) and two vectors
00009 of QStrings (row names and column names). It provides various functions for manipulating
00010 the table. 
00011 
00012 ****************************************************************************/
00013 
00014 #ifndef TINKERCELL_DATATABLE_H
00015 #define TINKERCELL_DATATABLE_H
00016 
00017 #include <QList>
00018 #include <QHash>
00019 #include <QVector>
00020 #include <QString>
00021 #include <QStringList>
00022 #include <QUndoCommand>
00023 #include <QDebug>
00024 
00025 #ifndef TINKERCELLCOREEXPORT
00026 #ifdef Q_WS_WIN
00027 #   if defined(TC_EXPORTS) || defined(TinkerCellCore_EXPORTS)
00028 #       define TINKERCELLCOREEXPORT __declspec(dllexport)
00029 #   else
00030 #       define TINKERCELLCOREEXPORT __declspec(dllimport)
00031 #   endif
00032 #else
00033 #    define TINKERCELLCOREEXPORT
00034 #endif
00035 #endif
00036 
00037 namespace Tinkercell
00038 {
00042         template <typename T>
00043         class TINKERCELLCOREEXPORT DataTable 
00044         {
00045         protected:
00047                 QVector<T> dataMatrix;
00049                 QVector<QString> colHeaders, rowHeaders;
00051                 QHash<QString,int> colHash, rowHash;
00053                 QString desc;
00054 
00055         public:
00056         
00058                 virtual ~DataTable();
00059 
00061                 DataTable();
00062 
00064                 DataTable(int rows,int columns);
00065                 
00067                 virtual QString description() const;
00068                 
00070                 virtual QString& description();
00071                 
00075                 virtual QStringList columnNames() const;
00080                 virtual bool hasRow(const QString&) const;
00085                 virtual bool hasColumn(const QString&) const;
00089                 virtual QStringList rowNames() const;
00090                 
00095                 virtual QString rowName(int i) const;
00096                 
00101                 virtual QString columnName(int i) const;
00102                 
00108                 virtual bool setRowName(int i, const QString& name);
00109                 
00115                 virtual bool setColumnName(int i, const QString& name);
00116                 
00121                 virtual void setColumnNames(const QStringList& names);
00122                 
00127                 virtual void setRowNames(const QStringList& names);
00128                 
00132                 virtual int rows() const;
00133                 
00137                 virtual int columns() const;
00138                 
00144                 virtual T& value (int i, int j=0) ;
00145                 
00151                 virtual T& operator() (int i, int j=0) ;
00152                 
00158                 virtual T operator() (int i, int j=0)  const;
00159                 
00165                 virtual T& value (const QString& r, const QString& c);
00166                 
00172                 virtual T& operator() (const QString& r, const QString& c);
00173                 
00179                 virtual T operator() (const QString& r, const QString& c) const;
00180                 
00186                 virtual T& value (const QString& r, int j=0);
00187                 
00193                 virtual T& operator() (const QString& r, int j=0);
00194                 
00200                 virtual T operator() (const QString& r, int j=0) const;
00201                 
00207                 virtual T& value (int i, const QString& c);
00208                 
00214                 virtual T& operator() (int i, const QString& c);
00215                 
00221                 virtual T operator() (int i, const QString& c) const;
00222                 
00227                 virtual bool operator == (const DataTable<T>& D);
00228                 
00233                 virtual bool operator != (const DataTable<T>& D);
00234                 
00240                 virtual T at (int i, int j=0) const;
00241                 
00247                 virtual T at (const QString& r, const QString& c) const;
00248                 
00254                 virtual T at (const QString& r, int j=0) const;
00255                 
00261                 virtual T at (int i, const QString& c) const;
00262                 
00268                 virtual void resize(int m, int n=1);
00269                 
00276                 virtual bool insertRow(int k, const QString& row);
00277                 
00284                 virtual bool insertColumn(int k, const QString& col);
00285                 
00290                 virtual bool removeRow(int k);
00291                 
00296                 virtual bool removeRow(const QString& name);
00297                 
00302                 virtual bool removeColumn(int k);
00303                 
00308                 virtual bool removeColumn(const QString& name);
00309                 
00315                 virtual void swapRows(int i1, int i2);
00316                 
00322                 virtual void swapColumns(int j1, int j2);
00323                 
00329                 virtual void swapRows(const QString& s1, const QString& s2);
00330                 
00336                 virtual void swapColumns(const QString& s1, const QString& s2);
00337                 
00341                 virtual DataTable<T> transpose() const;
00342                 
00343         };
00344 
00345 
00350         template <typename T>
00351         class TINKERCELLCOREEXPORT ChangeDataCommand : public QUndoCommand
00352         {
00353         public:
00359                 ChangeDataCommand(const QString& name, DataTable<T>* oldDataTable, const DataTable<T>* newDataTable);
00365                 ChangeDataCommand(const QString& name,const QList< DataTable<T>* >& oldDataTable,const QList< DataTable<T>* >& newDataTable);
00367                 void redo();
00369                 void undo();
00371                 QList< DataTable<T>* > targetDataTable;
00373                 QList< DataTable<T> > newDataTable;
00375                 QList< DataTable<T> > oldDataTable;
00376         };
00377 
00381         template <typename T1, typename T2>
00382         class TINKERCELLCOREEXPORT Change2DataCommand : public QUndoCommand
00383         {
00384         public:
00392                 Change2DataCommand(const QString& name, DataTable<T1>* oldDataTable1, const DataTable<T1>* newDataTable1, DataTable<T2>* oldDataTable2, const DataTable<T2>* newDataTable2);
00400                 Change2DataCommand(const QString& name,const QList< DataTable<T1>* >& oldDataTable1,const QList< DataTable<T1>* >& newDataTable1,const QList< DataTable<T2>* >& oldDataTable2,const QList< DataTable<T2>* >& newDataTable2);
00402                 void redo();
00404                 void undo();
00406                 QList< DataTable<T1>* > targetDataTable1;
00408                 QList< DataTable<T1> > newDataTable1;
00410                 QList< DataTable<T1> > oldDataTable1;
00412                 QList< DataTable<T2>* > targetDataTable2;
00414                 QList< DataTable<T2> > newDataTable2;
00416                 QList< DataTable<T2> > oldDataTable2;
00417         };
00418         
00419 #if defined(TC_EXPORTS) || defined(TinkerCellCore_EXPORTS)
00420 
00422         template <typename T> 
00423         DataTable<T>::~DataTable()
00424         {
00425         }
00426 
00428         template <typename T> 
00429         DataTable<T>::DataTable()
00430         {
00431         }
00432 
00434         template <typename T> 
00435         DataTable<T>::DataTable(int r,int c)
00436         {
00437                 resize(r,c);
00438         }
00439         
00440         template <typename T> QString DataTable<T>::description() const { return desc; }
00441                 
00443         template <typename T>  QString& DataTable<T>::description() { return desc; }
00444         
00448         template <typename T>  QStringList DataTable<T>::columnNames() const { return QStringList(colHeaders.toList()); }
00452         template <typename T>  QStringList DataTable<T>::rowNames() const { return QStringList(rowHeaders.toList()); }
00457         template <typename T> bool DataTable<T>::hasRow(const QString& s) const { return rowHash.contains(s); }
00462         template <typename T> bool DataTable<T>::hasColumn(const QString& s) const { return colHash.contains(s); }
00468         template <typename T>  bool DataTable<T>::setColumnName(int i, const QString& name) 
00469         { 
00470                 if (colHash.contains(name))
00471                 {
00472                         /*if (colHash[name] != i)
00473                         {
00474                                 int k = colHash[name];
00475                                 removeColumn(i);
00476                                 if (k > i)
00477                                         --i;
00478                         }
00479                         else*/
00480                                 return false;
00481                 }
00482                 
00483                 if (i < 0)
00484                         i = 0;
00485                         
00486                 if (i >= colHeaders.size())
00487                         resize(rowHeaders.size(), i+1);
00488                 colHash.remove(colHeaders[i]);
00489                 colHeaders[i]= name;
00490                 colHash[name] = i;
00491                 return true;
00492         }               
00497         template <typename T>  QString DataTable<T>::rowName(int i) const
00498         { 
00499                 if (i < 0 || i >= rowHeaders.size())
00500                 {
00501                         return QString();
00502                 }
00503                 return rowHeaders.at(i);
00504         }
00509         template <typename T>  QString DataTable<T>::columnName(int i) const
00510         { 
00511                 if (i < 0 || i >= colHeaders.size())
00512                         return QString();
00513                 return colHeaders.at(i);
00514         }
00519         template <typename T>  bool DataTable<T>::setRowName(int i, const QString& name) 
00520         { 
00521                 if (rowHash.contains(name))
00522                 {
00523                         /*if (rowHash[name] != i)
00524                         {
00525                                 int k = rowHash[name];
00526                                 removeRow(i);
00527                                 if (k > i)
00528                                         --i;
00529                         }
00530                         else*/
00531                         return false;
00532                 }
00533                 
00534                 if (i < 0)
00535                         i = 0;
00536                 
00537                 if (i >= rowHeaders.size())
00538                         resize(i+1, colHeaders.size());
00539                 rowHash.remove(rowHeaders[i]);
00540                 rowHeaders[i] = name;
00541                 rowHash[name] = i;
00542                 return true;
00543         }
00548         template <typename T>  void DataTable<T>::setColumnNames(const QStringList& lst)
00549         {
00550                 QStringList names;
00551                 for (int i=0; i < lst.size(); ++i)
00552                         if (!names.contains(lst[i]))
00553                                 names << lst[i];
00554                 if (names.size() != colHeaders.size())
00555                         resize(rowHeaders.size(),names.size());
00556                 colHeaders = QVector<QString>::fromList(names);
00557                 colHash.clear();
00558                 for (int i=0; i < names.size(); ++i)
00559                         colHash[ names[i] ] = i;
00560         }
00565         template <typename T>  void DataTable<T>::setRowNames(const QStringList& lst)
00566         {
00567                 QStringList names;
00568                 for (int i=0; i < lst.size(); ++i)
00569                         if (!names.contains(lst[i]))
00570                                 names << lst[i];
00571                 if (names.size() != colHeaders.size())
00572                         resize(names.size(),colHeaders.size());
00573                 rowHeaders = QVector<QString>::fromList(names);
00574                 
00575                 rowHash.clear();
00576                 for (int i=0; i < names.size(); ++i)
00577                         rowHash[ names[i] ] = i;
00578         }
00582         template <typename T>  int DataTable<T>::rows() const
00583         {
00584                 return rowHeaders.size();
00585         }
00589         template <typename T>  int DataTable<T>::columns() const
00590         {
00591                 return colHeaders.size();
00592         }
00598         template <typename T>  T& DataTable<T>::value (int i, int j)
00599         {
00600                 if (i < 0) i = 0;
00601                 if (j < 0) j = 0;
00602 
00603                 int k = i*colHeaders.size()+j;
00604                 if (k >= dataMatrix.size() || j >= colHeaders.size() || i >= rowHeaders.size()) 
00605                 {
00606                         int m = rowHeaders.size(), n = colHeaders.size();
00607                         if (i >= rowHeaders.size()) m = i + 1;
00608                         if (j >= colHeaders.size()) n = j + 1;
00609                         while (k >= m*n) ++m;
00610                         resize(m,n);
00611                 }
00612 
00613                 return dataMatrix[k];
00614         }
00621         template <typename T>  T& DataTable<T>::value (const QString& r, const QString& c)
00622         {
00623                 int m = rowHeaders.size(), n = colHeaders.size();
00624                 if (!rowHash.contains(r))
00625                         ++m;
00626                 if (!colHash.contains(c))
00627                         ++n;
00628                 if (m != rowHeaders.size() || n != colHeaders.size())
00629                 {
00630                         resize(m,n);
00631                         if (!rowHash.contains(r))
00632                         {
00633                                 rowHeaders[ rowHeaders.size()-1 ] = r;
00634                                 rowHash[ r ] = rowHeaders.size()-1;
00635                         }
00636                         if (!colHeaders.contains(c))
00637                         {
00638                                 colHeaders[ colHeaders.size()-1 ] = c;
00639                                 colHash[ c ] = colHeaders.size()-1;
00640                         }
00641                 }
00642                 int i = rowHash[r],     j = colHash[c];
00643                 return value(i,j);
00644         }
00651         template <typename T>  T& DataTable<T>::value (const QString& r, int j)
00652         {
00653                 int m = rowHeaders.size(), n = colHeaders.size();
00654                 if (!rowHash.contains(r))
00655                         ++m;
00656                 if (j >= n)
00657                         n = j + 1;
00658                 if (m != rowHeaders.size() || n != colHeaders.size())
00659                 {
00660                         resize(m,n);
00661                         if (!rowHash.contains(r))
00662                         {
00663                                 rowHeaders[ rowHeaders.size()-1 ] = r;
00664                                 rowHash[ r ] = rowHeaders.size()-1;
00665                         }
00666                 }
00667                 int i = rowHash[r];
00668                 return value(i,j);
00669         }
00676         template <typename T>  T& DataTable<T>::value (int i, const QString& c)
00677         {
00678                 int m = rowHeaders.size(), n = colHeaders.size();
00679                 if (!colHash.contains(c))
00680                         ++n;
00681                 if (i >= m)
00682                         m = i + 1;
00683                 if (m != rowHeaders.size() || n != colHeaders.size())
00684                 {
00685                         resize(m,n);
00686                         if (!colHash.contains(c))
00687                         {
00688                                 colHeaders[ colHeaders.size()-1 ] = c;
00689                                 colHash[ c ] = colHeaders.size()-1;
00690                         }
00691                 }
00692                 int j = colHash[c];
00693                 return value(i,j);      
00694         }
00699         template <typename T>  bool DataTable<T>::operator == (const DataTable<T>& D)
00700         {
00701                 return dataMatrix == D.dataMatrix && colHeaders == D.colHeaders && rowHeaders == D.rowHeaders;
00702         }
00707         template <typename T>  bool DataTable<T>::operator != (const DataTable<T>& D)
00708         {
00709                 return !( operator==(D) );
00710         }
00716         template <typename T>  T DataTable<T>::at (int i, int j) const
00717         {
00718                 if (i < 0) i = 0;
00719                 if (j < 0) j = 0;
00720 
00721                 int k = i*colHeaders.size()+j;
00722                 if (k >= dataMatrix.size() || j >= colHeaders.size() || i >= rowHeaders.size()) 
00723                 {
00724                         return T();
00725                 }
00726 
00727                 return dataMatrix.at(k);
00728         }
00734         template <typename T>  T DataTable<T>::at (const QString& r, const QString& c) const
00735         {
00736                 if (!rowHash.contains(r) || !colHash.contains(c))
00737                         return T();
00738 
00739                 int i = rowHash[r], j = colHash[c];
00740                 return at(i,j);
00741         }
00747         template <typename T>  T DataTable<T>::at (const QString& r, int j) const
00748         {
00749                 if (!rowHash.contains(r))
00750                         return T();
00751 
00752                 int i = rowHash[r];
00753                 return at(i,j);
00754         }
00760         template <typename T>  T DataTable<T>::at (int i, const QString& c) const
00761         {
00762                 if (!colHash.contains(c))
00763                         return T();
00764 
00765                 int j = colHash[c];
00766                 return at(i,j);
00767         }
00773         template <typename T>  void DataTable<T>::resize(int m, int n)
00774         {
00775                 if (m < 0 || n < 0) return;
00776 
00777                 int m0 = rowHeaders.size(), n0 = colHeaders.size();
00778                 QVector<T> oldMatrix(dataMatrix);
00779                 
00780                 if (m < m0)
00781                         for (int i=m; i < m0; ++i)
00782                                 rowHash.remove( rowHeaders[i] );
00783                 
00784                 if (n < n0)
00785                         for (int i=n; i < n0; ++i)
00786                                 colHash.remove( colHeaders[i] );
00787 
00788                 dataMatrix.clear();
00789                 dataMatrix.resize(m*n);
00790                 rowHeaders.resize(m);
00791                 colHeaders.resize(n);
00792 
00793                 int k0=0, k1=0; 
00794                 for (int i=0; i < m0 && i < m; ++i)
00795                         for (int j=0; j < n0 && j < n; ++j)
00796                         {
00797                                 k0 = i*n0 + j;
00798                                 k1 = i*n + j;
00799                                 dataMatrix[k1] = oldMatrix[k0];
00800                         }
00801         }
00808         template <typename T>  bool DataTable<T>::insertRow(int k, const QString& row)
00809         {
00810                 if (rowHash.contains(row)) return false;
00811                 int m = rowHeaders.size();
00812                 resize( m+1, colHeaders.size() );
00813                 rowHeaders[ m ] = row;
00814                 rowHash[ row ] = m;
00815                 return true;
00816         }
00823         template <typename T>  bool DataTable<T>::insertColumn(int k, const QString& col)
00824         {
00825                 if (colHash.contains(col)) return false;
00826                 int n = colHeaders.size();
00827                 resize( rowHeaders.size() , n + 1 );
00828                 colHeaders[ n ] = col;
00829                 colHash[ col ] = n;
00830                 return true;
00831         }
00836         template <typename T>  bool DataTable<T>::removeRow(int k)
00837         {
00838                 if (k < 0 || k >= rowHeaders.size()) return false;
00839                 int n = rowHeaders.size()-1;
00840                 
00841                 QVector<T> dataMatrix2( n * colHeaders.size() );
00842 
00843                 for (int i=0; i < rowHeaders.size(); ++i)
00844                         for (int j=0; j < colHeaders.size(); ++j)
00845                         {
00846                                 if (i < k)
00847                                         dataMatrix2[ i*colHeaders.size()+j ] = dataMatrix[ i*colHeaders.size()+j ];
00848                                 else
00849                                         if (i > k)
00850                                                 dataMatrix2[ (i-1)*colHeaders.size()+j ] = dataMatrix[ i*colHeaders.size()+j ];
00851                         }
00852 
00853                 dataMatrix = dataMatrix2;
00854                 rowHash.clear();
00855                 rowHeaders.remove(k);
00856                 
00857                 for (int i=0; i < rowHeaders.size(); ++i)
00858                         rowHash[ rowHeaders[i] ] = i;
00859 
00860                 return true;
00861         }
00866         template <typename T>  bool DataTable<T>::removeRow(const QString& name)
00867         {
00868                 if (rowHash.contains(name))
00869                         return removeRow(rowHash[name]);
00870                 return false;
00871         }
00876         template <typename T>  bool DataTable<T>::removeColumn(int k)
00877         {
00878                 if (k < 0 || k >= colHeaders.size()) return false;
00879 
00880                 int n = colHeaders.size()-1;
00881 
00882                 QVector<T> dataMatrix2( n * rowHeaders.size() );
00883 
00884                 for (int i=0; i < rowHeaders.size(); ++i)
00885                         for (int j=0; j < colHeaders.size(); ++j)
00886                         {
00887                                 if (j < k)
00888                                         dataMatrix2[ i*n+j ] = dataMatrix[ i*colHeaders.size()+j ];
00889                                 else
00890                                         if (j > k)
00891                                                 dataMatrix2[ i*n+j-1 ] = dataMatrix[ i*colHeaders.size()+j ];
00892                         }
00893 
00894                 dataMatrix = dataMatrix2;
00895                 colHash.clear();
00896                 colHeaders.remove(k);
00897                 
00898                 for (int i=0; i < colHeaders.size(); ++i)
00899                         colHash[ colHeaders[i] ] = i;
00900 
00901                 return true;
00902         }
00907         template <typename T>  bool DataTable<T>::removeColumn(const QString& name)
00908         {
00909                 if (colHash.contains(name))
00910                         return removeColumn(colHash[name]);
00911                 return false;
00912         }
00918         template <typename T>  void DataTable<T>::swapRows(int i1, int i2)
00919         {
00920                 if (i1 < 0 || i2 < 0 || i1 >= rowHeaders.size() || i2 >= rowHeaders.size()) return;
00921 
00922                 QString str = rowHeaders[i1];
00923                 rowHeaders[i1] = rowHeaders[i2];
00924                 rowHeaders[i2] = str;
00925 
00926                 rowHash[ rowHeaders[i1] ] = i1;
00927                 rowHash[ rowHeaders[i2] ] = i2;
00928 
00929                 int n = colHeaders.size();
00930                 int k1,k2;
00931                 T temp;
00932                 for (int j=0; j < n; ++j)
00933                 {
00934                         k1 = i1*n + j;
00935                         k2 = i2*n + j;
00936                         temp = dataMatrix[k1];
00937                         dataMatrix[k1] = dataMatrix[k2];
00938                         dataMatrix[k2] = temp;
00939                 }
00940         }
00946         template <typename T>  void DataTable<T>::swapColumns(int j1, int j2)
00947         {
00948                 if (j1 < 0 || j2 < 0 || j1 >= colHeaders.size() || j2 >= colHeaders.size()) return;
00949 
00950                 QString str = colHeaders[j1];
00951                 colHeaders[j1] = colHeaders[j2];
00952                 colHeaders[j2] = str;
00953                 
00954                 colHash[ colHeaders[j1] ] = j1;
00955                 colHash[ colHeaders[j2] ] = j2;
00956 
00957                 int n = colHeaders.size(), m = rowHeaders.size();
00958                 int k1,k2;
00959                 T temp;
00960                 for (int i=0; i < m; ++i)
00961                 {
00962                         k1 = i*n + j1;
00963                         k2 = i*n + j2;
00964                         temp = dataMatrix[k1];
00965                         dataMatrix[k1] = dataMatrix[k2];
00966                         dataMatrix[k2] = temp;
00967                 }
00968         }
00974         template <typename T>  void DataTable<T>::swapRows(const QString& s1, const QString& s2)
00975         {
00976                 if (rowHash.contains(s1) && rowHash.contains(s2))
00977                         swapRows( rowHash[s1], rowHash[s2] );
00978         }
00984         template <typename T>  void DataTable<T>::swapColumns(const QString& s1, const QString& s2)
00985         {
00986                 if (colHash.contains(s1) && colHash.contains(s2))
00987                         swapColumns( colHash[s1], colHash[s2] );
00988         }
00992         template <typename T>  DataTable<T> DataTable<T>::transpose() const
00993         {
00994                 DataTable<T> newTable;
00995                 newTable.resize( colHeaders.size(), rowHeaders.size() );
00996 
00997                 newTable.colHeaders = rowHeaders;
00998                 newTable.rowHeaders = colHeaders;
00999                 newTable.rowHash = rowHash;
01000                 newTable.colHash = colHash;
01001 
01002                 for (int i=0; i < rows(); ++i)
01003                         for (int j=0; j < columns(); ++j)
01004                                 newTable.value(j,i) = at(i,j);
01005 
01006                 return newTable;
01007         }
01008 /*      
01009         template <typename T> void DataTable<T>::appendRows(DataTable<T>* other)
01010         {
01011                 QList< DataTable<T> * > list;
01012                 list << this << other;
01013                 DataTable<T> A = appendRows(list);
01014                 dataMatrix = A.dataMatrix;
01015                 rowHeaders = A.rowHeaders;
01016                 colHeaders = A.colHeaders;
01017                 colHash = A.colHash;
01018                 rowHash = A.rowHash;
01019         }
01020         
01021         template <typename T>  DataTable<T> DataTable<T>::appendRows(const QList< DataTable<T>* >& list)
01022         {
01023                 DataTable<T> newTable;
01024                 QHash<QString,int> colHash, rowHash;
01025                 QStringList colHeaders, rowHeaders;
01026                 
01027                 QString s;
01028                 
01029                 int rows = 0, cols = 0, p;
01030                 
01031                 for (int i=0; i < list.size(); ++i)
01032                         if (list[i])
01033                         {
01034                                 for (int j=0; j < list[i]->rows(); ++j) //get all rows with unique names
01035                                 {
01036                                         s = list[i]->rowName(j);
01037                                         p = rows;
01038                                         if (s.isEmpty() || !rowHash.contains(s))
01039                                         {
01040                                                 rowHeaders << s;
01041                                                 if (!s.isEmpty())
01042                                                         rowHash[s] = rows;
01043                                                 ++rows;
01044                                         }
01045                                 }
01046 
01047                                 for (int j=0; j < list[i]->columns(); ++j) //get all rows with unique names
01048                                 {
01049                                         s = list[i]->columnName(j);
01050                                         if (s.isEmpty() || !colHash.contains(s))
01051                                         {
01052                                                 colHeaders << s;
01053                                                 if (!s.isEmpty())
01054                                                         colHash[s] = rows;
01055                                                 ++cols;
01056                                         }
01057                                 }
01058                         }
01059 
01060                 newTable.resize(rows,cols);
01061                 for (int i=0; i < colHeaders.size(); ++i)
01062                         newTable.colHeaders[i] = colHeaders[i];
01063                 newTable.colHash = colHash;
01064                 for (int i=0; i < rowHeaders.size(); ++i)
01065                         newTable.rowHeaders[i] = rowHeaders[i];
01066                 newTable.rowHash = rowHash;
01067                 
01068                 rows = 0;
01069                 for (int i=0; i < list.size(); ++i)
01070                         if (list[i])
01071                         {
01072                                 for (int j=0; j < list[i]->columns(); ++j) //get all rows with unique names
01073                                 {
01074                                         if (colHash.contains(list[i]->columnName(j)))
01075                                                 cols = colHash[ list[i]->columnName(j) ];
01076                                         else
01077                                                 cols = j;
01078                                         for (int k=0; k < list[i]->rows(); ++k)
01079                                         {
01080                                                 newTable.value(rows, cols) = list[i]->value(k, j);
01081                                                 ++rows;
01082                                         }
01083                                 }
01084                         }
01085                 
01086                 return newTable;
01087         }
01088         
01089         template <typename T> void DataTable<T>::appendColumns(DataTable<T>* other)
01090         {
01091                 QList< DataTable<T> * > list;
01092                 list << this << other;
01093                 DataTable<T> A = appendColumns(list);
01094                 dataMatrix = A.dataMatrix;
01095                 rowHeaders = A.rowHeaders;
01096                 colHeaders = A.colHeaders;
01097                 colHash = A.colHash;
01098                 rowHash = A.rowHash;
01099         }
01100         
01101         template <typename T>  DataTable<T> DataTable<T>::appendColumns(const QList< DataTable<T>* >& list)
01102         {
01103                 DataTable<T> newTable;
01104                 QHash<QString,int> colHash, rowHash;
01105                 QStringList colHeaders, rowHeaders;
01106                 
01107                 QString s;
01108                 
01109                 int rows = 0, cols = 0, p;
01110                 
01111                 for (int i=0; i < list.size(); ++i)
01112                         if (list[i])
01113                         {
01114                                 for (int j=0; j < list[i]->rows(); ++j) //get all rows with unique names
01115                                 {
01116                                         s = list[i]->rowName(j);
01117                                         if (s.isEmpty() ||!rowHash.contains(s))
01118                                         {
01119                                                 rowHeaders << s;
01120                                                 if (!s.isEmpty())
01121                                                         rowHash[s] = rows;
01122                                                 ++rows;
01123                                         }
01124                                 }
01125 
01126                                 for (int j=0; j < list[i]->columns(); ++j) //get all rows with unique names
01127                                 {
01128                                         s = list[i]->columnName(j);
01129                                         p = cols;
01130                                         if (s.isEmpty() || !colHash.contains(s))
01131                                         {
01132                                                 colHeaders << s;
01133                                                 if (!s.isEmpty())
01134                                                         colHash[s] = cols;
01135                                                 ++cols;
01136                                         }
01137                                 }
01138                         }
01139 
01140                 newTable.resize(rows,cols);
01141                 for (int i=0; i < colHeaders.size(); ++i)
01142                         newTable.colHeaders[i] = colHeaders[i];
01143                 newTable.colHash = colHash;
01144                 for (int i=0; i < rowHeaders.size(); ++i)
01145                         newTable.rowHeaders[i] = rowHeaders[i];
01146                 newTable.rowHash = rowHash;
01147                 
01148                 cols = 0;
01149                 for (int i=0; i < list.size(); ++i)
01150                         if (list[i])
01151                         {
01152                                 for (int j=0; j < list[i]->rows(); ++j) //get all rows with unique names
01153                                 {
01154                                         if (rowHash.contains(list[i]->rowName(j)))
01155                                                 rows = rowHash[ list[i]->rowName(j) ];
01156                                         else
01157                                                 rows = j;
01158                                         for (int k=0; k < list[i]->columns(); ++k)
01159                                         {
01160                                                 newTable.value(rows, cols) = list[i]->value(j, k);
01161                                                 ++cols;
01162                                         }
01163                                 }
01164                         }
01165                 
01166                 return newTable;
01167         }
01168 */
01169 
01170         template <typename T> T& DataTable<T>::operator() (int r, int c)
01171         {
01172                 return this->value(r,c);
01173         }
01174         
01175         template <typename T> T DataTable<T>::operator() (int r, int c) const
01176         {
01177                 return this->at(r,c);
01178         }
01179         
01180         template <typename T> T& DataTable<T>::operator() (const QString& r, const QString& c)
01181         {
01182                 return this->value(r,c);
01183         }
01184 
01185         template <typename T> T DataTable<T>::operator() (const QString& r, const QString& c) const
01186         {
01187                 return this->at(r,c);
01188         }
01189         
01190         template <typename T> T& DataTable<T>::operator() (const QString& r, int c)
01191         {
01192                 return this->value(r,c);
01193         }
01194 
01195         template <typename T> T DataTable<T>::operator() (const QString& r, int c) const
01196         {
01197                 return this->at(r,c);
01198         }
01199         
01200         template <typename T> T& DataTable<T>::operator() (int r, const QString& c)
01201         {
01202                 return this->value(r,c);
01203         }
01204 
01205         template <typename T> T DataTable<T>::operator() (int r, const QString& c) const
01206         {
01207                 return this->at(r,c);
01208         }
01209 
01210         template <typename T>
01211         ChangeDataCommand<T>::ChangeDataCommand(const QString& name, DataTable<T>* oldDataTable, const DataTable<T>* newDataTable)
01212                 : QUndoCommand(name)
01213         {
01214                 if (newDataTable && oldDataTable)
01215                 {
01216                         this->newDataTable += *newDataTable;
01217                         this->oldDataTable += *oldDataTable;
01218                         this->targetDataTable += oldDataTable;
01219                 }
01220         }
01221         
01222         template <typename T>
01223         ChangeDataCommand<T>::ChangeDataCommand(const QString& name,const QList< DataTable<T>* >& oldDataTable,const QList< DataTable<T>* >& newDataTable)
01224                 : QUndoCommand(name)
01225         {
01226                 for (int i=0; i < oldDataTable.size() && i < newDataTable.size(); ++i)
01227                         if (newDataTable[i] && oldDataTable[i])
01228                         {
01229                                 this->newDataTable += *(newDataTable[i]);
01230                                 this->oldDataTable += *(oldDataTable[i]);
01231                                 this->targetDataTable += (oldDataTable[i]);
01232                         }
01233         }
01234         
01235         template <typename T>
01236         void ChangeDataCommand<T>::redo()
01237         {
01238                 for (int i=0; i < targetDataTable.size() && i < newDataTable.size(); ++i)
01239                         if (targetDataTable[i])
01240                                 (*(targetDataTable[i])) = newDataTable[i];
01241         }
01242         
01243         template <typename T>
01244         void ChangeDataCommand<T>::undo()
01245         {
01246                 for (int i=0; i < targetDataTable.size() && i < oldDataTable.size(); ++i)
01247                         if (targetDataTable[i])
01248                                 (*(targetDataTable[i])) = oldDataTable[i];
01249         }
01250 
01251         template <typename T1, typename T2>
01252         Change2DataCommand<T1,T2>::Change2DataCommand(const QString& name, DataTable<T1>* oldDataTable1, const DataTable<T1>* newDataTable1, DataTable<T2>* oldDataTable2, const DataTable<T2>* newDataTable2)
01253                 : QUndoCommand(name)
01254         {
01255                 if (newDataTable1 && oldDataTable1)
01256                 {
01257                         DataTable<T1> dat1n(*(newDataTable1));
01258                         DataTable<T1> dat1o(*(oldDataTable1));
01259 
01260                         this->newDataTable1 += dat1n;
01261                         this->oldDataTable1 += dat1o;
01262                         this->targetDataTable1 += oldDataTable1;
01263                 }
01264 
01265                 if (newDataTable2 && oldDataTable2)
01266                 {
01267                         DataTable<T2> dat2n(*(newDataTable2));
01268                         DataTable<T2> dat2o(*(oldDataTable2));
01269 
01270                         this->newDataTable2 += dat2n;
01271                         this->oldDataTable2 += dat2o;
01272                         this->targetDataTable2 += oldDataTable2;
01273                 }
01274         }
01275 
01276         template <typename T1, typename T2>
01277         Change2DataCommand<T1,T2>::Change2DataCommand(const QString& name,const QList< DataTable<T1>* >& oldDataTable1,const QList< DataTable<T1>* >& newDataTable1,const QList< DataTable<T2>* >& oldDataTable2,const QList< DataTable<T2>* >& newDataTable2)
01278                 : QUndoCommand(name)
01279         {
01280                 for (int i=0; i < newDataTable1.size() && i < oldDataTable1.size(); ++i)
01281                         if (newDataTable1[i] && oldDataTable1[i])
01282                         {
01283                                 DataTable<T1> dat1n(*(newDataTable1[i]));
01284                                 DataTable<T1> dat1o(*(oldDataTable1[i]));
01285 
01286                                 this->newDataTable1 += dat1n;
01287                                 this->oldDataTable1 += dat1o;
01288                                 this->targetDataTable1 += (oldDataTable1.at(i));
01289                         }
01290 
01291                         for (int i=0; i < newDataTable2.size() && i < oldDataTable2.size(); ++i)
01292                                 if (newDataTable2[i] && oldDataTable2[i])
01293                                 {
01294                                         DataTable<T2> dat2n(*(newDataTable2[i]));
01295                                         DataTable<T2> dat2o(*(oldDataTable2[i]));
01296 
01297                                         this->newDataTable2 += dat2n;
01298                                         this->oldDataTable2 += dat2o;
01299                                         this->targetDataTable2 += (oldDataTable2[i]);
01300                                 }
01301         }
01302         
01303         template <typename T1, typename T2>
01304         void Change2DataCommand<T1,T2>::redo()
01305         {
01306                 for (int i=0; i < targetDataTable1.size() && i < newDataTable1.size(); ++i)
01307                         if (targetDataTable1[i])
01308                                 (*(targetDataTable1[i])) = newDataTable1[i];
01309 
01310                 for (int i=0; i < targetDataTable2.size() && i < newDataTable2.size(); ++i)
01311                         if (targetDataTable2[i])
01312                                 (*(targetDataTable2[i])) = newDataTable2[i];
01313         }
01314         
01315         template <typename T1, typename T2>
01316         void Change2DataCommand<T1,T2>::undo()
01317         {
01318                 for (int i=0; i < targetDataTable1.size() && i < oldDataTable1.size(); ++i)
01319                         if (targetDataTable1[i])
01320                                 (*(targetDataTable1[i])) = oldDataTable1[i];
01321 
01322                 for (int i=0; i < targetDataTable2.size() && i < oldDataTable2.size(); ++i)
01323                         if (targetDataTable2[i])
01324                                 (*(targetDataTable2[i])) = oldDataTable2[i];
01325         }
01326 
01327 #endif
01328 
01332         typedef DataTable<QString> TextDataTable;
01333         
01337         typedef DataTable<qreal> NumericalDataTable;
01338         
01342         typedef ChangeDataCommand<QString> ChangeTextDataCommand;
01343         
01347         typedef ChangeDataCommand<qreal> ChangeNumericalDataCommand;
01348 
01349 }
01350 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines