Home || Architecture || Video Search || Visual Search || Scripts || Applications || Important Messages || OGL || Src

TableDataSource.h

Go to the documentation of this file.
00001 #ifndef VideoExcel_TableDataSource_h
00002 #define VideoExcel_TableDataSource_h
00003 
00004 #include "TableUpdateListener.h"
00005 #include "Core/Array/Arrays.h"
00006 #include "TableFilter.h"
00007 #include "TableSourceColumnDescription.h"
00008 
00009 namespace Impala {
00010 namespace Application {
00011 namespace VideoExcel {
00012 
00013 
00014 // comparison, not case sensitive.
00015 bool compare_string_nocase (std::pair<String, int> a, std::pair<String, int> b)
00016 {
00017     unsigned int i=0;
00018     String first = a.first;
00019     String second = b.first;
00020     while ( (i<first.length()) && (i<second.length()) )
00021     {
00022         if (tolower(first[i])<tolower(second[i])) return true;
00023         else if (tolower(first[i])>tolower(second[i])) return false;
00024         ++i;
00025     }
00026     if (first.length()<second.length()) return true;
00027     else return false;
00028 };
00029 
00030 // comparison, double.
00031 bool compare_double (std::pair<double, int> a, std::pair<double, int> b)
00032 {
00033     if (a.first < b.first)
00034         return true;
00035     return false;
00036 };
00037 
00038 // comparison, int.
00039 bool compare_int (std::pair<int, int> a, std::pair<int, int> b)
00040 {
00041     if (a.first < b.first)
00042         return true;
00043     return false;
00044 };
00045 
00046 class TableDataSource : public TableFilterUpdateListener
00047 {
00048 public:
00049     typedef Impala::Core::Array::Array2dVec3UInt8 Array2dVec3UInt8;
00050 
00051     static const int TYPE_TEXT            = 1;
00052     static const int TYPE_NORMALIZEDVALUE = 2;
00053     static const int TYPE_IMAGE           = 3;
00054     static const int TYPE_INT             = 4;
00055     static const int TYPE_DOUBLE          = 5;
00056 
00057     TableDataSource()
00058     {
00059         mDisplayRows            = 50;
00060         mTotalRows              = 1000;
00061         mFilteredRows           = 1000;
00062         mStartRow               = 0;
00063         mDefaultRowHeight       = 20;
00064         mDefaultRowZoomHeight   = 80;
00065         mSortType               = 1;
00066         mZoomRow                = -1;
00067         mSortColumn             = "";
00068         mSortAscending          = true;
00069         mFiltersWorking         = false;
00070         mFiltersActive          = false;
00071     }
00072 
00073     int GetTotalRows()
00074     {
00075         return mTotalRows;
00076     }
00077 
00078     int GetFilteredRows()
00079     {
00080         return mFilteredRows;
00081     }
00082 
00083     void SetStartRow(int startrow)
00084     {
00085         if (startrow >= 0 && startrow < GetTotalRows() && startrow!=mStartRow)
00086         {
00087             mStartRow = startrow;
00088             DoUpdateRowsEvent();
00089         }
00090     }
00091 
00092     void SetNumberOfRows(int number)
00093     {
00094         if (number > 0 && number != mDisplayRows)
00095         {
00096             ILOG_DEBUG("SetNumberOfRows(" << number << ")");
00097             mDisplayRows = number;
00098             DoUpdateRowsEvent();
00099         }
00100     }
00101 
00102     void SetNumberOfRowsInPixels(int pixels)
00103     {
00104         if (pixels <= 0)
00105             return;
00106 
00107         int yoff = 0;
00108         int rows = 0;
00109         for (int i=GetStartRow(); i<GetTotalRows(); i++)
00110         {
00111             if ((yoff += GetRowHeight(i)) > pixels)
00112                 break;
00113             rows++;
00114         }
00115         if (rows != mDisplayRows)
00116         {
00117             ILOG_DEBUG("SetNumberOfRowsInPixels: " << pixels << " yields " <<
00118                        rows << " rows.");
00119             SetNumberOfRows(rows);
00120         }
00121     }
00122 
00123     /* mark/unmark support **************************************/
00124 
00125     int GetMark(int sortedrow)
00126     {   
00127         int row = mSortSequence[sortedrow];
00128         if(mMarkedRows.find(row) != mMarkedRows.end())
00129             return mMarkedRows[row];
00130         return 0;
00131     }
00132 
00133     /* returns a <ID, mark> map for all rows in the database */
00134     std::map<int, int>
00135     GetMarkedRowsMap()
00136     {
00137         return mMarkedRows;
00138     }
00139 
00140     void
00141     MarkRow(int sortedrow, int markstate, bool mark=true, bool toggle=false)
00142     {
00143         int row = mSortSequence[sortedrow];
00144         if (row < 0 || row > GetTotalRows())
00145             return;
00146         if (mark)
00147         {
00148             if(mMarkedRows.find(row) == mMarkedRows.end())
00149                 mMarkedRows[row] = markstate;
00150             else if (toggle)
00151                 mMarkedRows[row] = mMarkedRows[row] ^ markstate;
00152             else
00153                 mMarkedRows[row] = mMarkedRows[row] | markstate;
00154         }
00155         else if(mMarkedRows.find(row) != mMarkedRows.end())
00156             mMarkedRows[row] = mMarkedRows[row] & ~markstate;
00157 
00158         //ILOG_DEBUG("Markrow: " << row << " state=" << markstate << " mark=" <<
00159         //           mark<<" toggle=" << toggle << " RES=" << mMarkedRows[row]);
00160     }
00161 
00162     void MarkVisibleRows(int markstate, bool mark=true)
00163     {
00164         MarkRange(GetStartRow(), GetEndRow(), markstate, mark);
00165     }
00166 
00167     void MarkAllRows(int markstate, bool mark=true)
00168     {
00169         MarkRange(0, GetTotalRows(), markstate, mark);
00170     }
00171 
00172     void MarkRange(int start, int stop, int markstate, bool mark=true)
00173     {
00174         if (stop <= start)
00175         {
00176             int t = stop;
00177             stop  = start;
00178             start = t;
00179         }
00180         if (start < 0) start = 0;
00181         if (stop >= GetEndRow()) stop = GetEndRow()-1;
00182 
00183         for (int i=start; i<=stop; i++)
00184             MarkRow(i, markstate, mark);
00185     }
00186 
00187     void TransformMarkedTo(int sourcemask, int targetmask)
00188     {
00189         for (int i=0; i<GetTotalRows(); i++)
00190         {
00191             if(mMarkedRows.find(i) != mMarkedRows.end())
00192             {
00193                 if (mMarkedRows[i] & sourcemask)
00194                 {
00195                     mMarkedRows[i] = mMarkedRows[i] & ~sourcemask;
00196                     mMarkedRows[i] = mMarkedRows[i] | targetmask;
00197                 }
00198             }
00199         }
00200     }
00201 
00202     /* individual row zooming support ****/
00203     void SetZoomRow(int row)
00204     {
00205         if (row == mZoomRow)
00206             return;
00207         if (OutOfBounds(row))
00208             return;
00209         if (mZoomRow == -1)
00210             DoUpdateNumberOfRowsEvent();
00211         mZoomRow = row;
00212         DoUpdateRowsEvent();
00213     }
00214 
00215     void UnsetZoom()
00216     {
00217         if (mZoomRow == -1)
00218             return;
00219         mZoomRow = -1;
00220         DoUpdateNumberOfRowsEvent();
00221         DoUpdateRowsEvent();
00222     }
00223 
00224     void SetDefaultRowSizes(int unzoom, int zoom)
00225     {
00226         mDefaultRowHeight = unzoom;
00227         mDefaultRowZoomHeight = zoom;
00228         DoUpdateNumberOfRowsEvent();
00229         DoUpdateRowsEvent();
00230     }
00231 
00232     /* return row indices of currently displayed data window ****/
00233     int GetStartRow()
00234     {
00235         return mStartRow;
00236     }
00237 
00238     int GetEndRow()
00239     {
00240         return GetStartRow() + GetNumberOfRows();
00241     }
00242 
00243     int GetNumberOfRows()
00244     {
00245         if (mDisplayRows > mFilteredRows - GetStartRow())
00246             return mFilteredRows - GetStartRow();
00247         return mDisplayRows;
00248     }
00249 
00250     bool OutOfBounds(int row)
00251     {
00252         if (row < GetStartRow() || row > GetStartRow() + GetNumberOfRows())
00253             return true;
00254         return false;
00255     }
00256 
00257     bool OutOfBoundsByID(int id)
00258     {
00259         return OutOfBounds(GetRowForID(id));
00260     }
00261 
00262     /* column sorting ********************************************/
00263 
00264     String GetSortColumn()
00265     {
00266         return mSortColumn;
00267     }
00268 
00269     bool GetSortAscending()
00270     {
00271         return mSortAscending;
00272     }
00273 
00274     /* returns a <ID, bool isvisible> map for all rows in the database
00275        todo: name clash: visible here means "not filtered"
00276     */
00277     std::map<int, bool>
00278     GetVisibleRowsMap()
00279     {
00280         return mVisibleRows;
00281     }
00282 
00283     void SortAndFilter()
00284     {
00285         ILOG_DEBUG("re-sorting to " << mSortColumn << "/" << mSortAscending);
00286         mVisibleRows.clear();
00287         if (mSortType == TYPE_TEXT)
00288         {
00289             std::list < std::pair <String, int> > sortthis;
00290             for (int i=0; i<GetTotalRows();i++)
00291             {
00292                 if (!IsFiltered(i))
00293                 {
00294                     String txt = GetTextDataByID(mSortColumn, i);
00295                     sortthis.push_back( std::make_pair(txt, i) );
00296                     mVisibleRows[i] = true;
00297                 }
00298                 else
00299                     mVisibleRows[i] = false;
00300             }
00301             mFilteredRows = sortthis.size();
00302             sortthis.sort(compare_string_nocase);
00303             ILOG_DEBUG("filtered # of rows: " << mFilteredRows);
00304 
00305             if (!mSortAscending)
00306                 sortthis.reverse();
00307             mSortSequence.clear();
00308 
00309             std::list<std::pair <String, int> >::iterator it;
00310             for (it=sortthis.begin(); it!=sortthis.end(); ++it)
00311                 mSortSequence.push_back(it->second);
00312         }
00313         if (mSortType == TYPE_NORMALIZEDVALUE || mSortType == TYPE_DOUBLE)
00314         {
00315             std::list < std::pair <double, int> > sortthis;
00316             for (int i=0; i<GetTotalRows();i++)
00317             {
00318                 if (!IsFiltered(i))
00319                 {
00320                         double dVal;
00321                     if (mSortType == TYPE_NORMALIZEDVALUE)
00322                         dVal = GetNormalizedDataByID(mSortColumn, i);
00323                     else
00324                         dVal = GetDoubleDataByID(mSortColumn, i);
00325                     sortthis.push_back( std::make_pair(dVal, i) );
00326                     mVisibleRows[i] = true;
00327                 }
00328                 else
00329                     mVisibleRows[i] = false;
00330             }
00331             mFilteredRows = sortthis.size();
00332             sortthis.sort(compare_double);
00333             ILOG_DEBUG("filtered # of rows: " << mFilteredRows);
00334 
00335             if (mSortAscending)
00336                 sortthis.reverse();
00337             mSortSequence.clear();
00338 
00339             std::list<std::pair <double, int> >::iterator it;
00340             for (it=sortthis.begin(); it!=sortthis.end(); ++it)
00341                 mSortSequence.push_back(it->second);
00342         }
00343         if (mSortType == TYPE_INT)
00344         {
00345             std::list < std::pair <int, int> > sortthis;
00346             for (int i=0; i<GetTotalRows();i++)
00347             {
00348                 if (!IsFiltered(i))
00349                 {
00350                     int iVal = GetIntDataByID(mSortColumn, i);
00351                     sortthis.push_back( std::make_pair(iVal, i) );
00352                     mVisibleRows[i] = true;
00353                 }
00354                 else
00355                     mVisibleRows[i] = false;
00356             }
00357             mFilteredRows = sortthis.size();
00358             sortthis.sort(compare_int);
00359             ILOG_DEBUG("filtered # of rows: " << mFilteredRows);
00360 
00361             if (mSortAscending)
00362                 sortthis.reverse();
00363             mSortSequence.clear();
00364 
00365             std::list<std::pair <int, int> >::iterator it;
00366             for (it=sortthis.begin(); it!=sortthis.end(); ++it)
00367                 mSortSequence.push_back(it->second);
00368         }
00369         ILOG_DEBUG("sorting completed.");
00370         DoUpdateSortEvent();
00371         DoUpdateSelectionEvent();
00372         DoUpdateRowsEvent();
00373     }
00374 
00375     void SetSortColumn(String column, int type, bool ascending=true)
00376     {
00377         if (mSortColumn != column || mSortAscending != ascending)
00378         {
00379             mSortColumn = column;
00380             mSortAscending = ascending;
00381             mSortType = type;
00382             SortAndFilter();
00383         }
00384     }
00385 
00386     /* table listeners ******************************/
00387     void AddTableUpdateListener(TableUpdateListener* l)
00388     {
00389         mTableListeners.push_back(l);
00390     }
00391 
00392     void DoUpdateRowsEvent()
00393     {
00394         for (int i=0; i< mTableListeners.size(); i++)
00395             if (mTableListeners[i]->GetListenTableUpdates())
00396                 mTableListeners[i]->UpdateRowsEvent();
00397     }
00398 
00399     void DoUpdateNumberOfRowsEvent()
00400     {
00401         for (int i=0; i< mTableListeners.size(); i++)
00402             if (mTableListeners[i]->GetListenTableUpdates())
00403                 mTableListeners[i]->UpdateNumberOfRowsEvent();
00404     }
00405 
00406     void DoUpdateSelectionEvent()
00407     {
00408         for (int i=0; i< mTableListeners.size(); i++)
00409             if (mTableListeners[i]->GetListenTableUpdates())
00410                 mTableListeners[i]->UpdateSelectionEvent();
00411     }
00412 
00413 
00414     void DoUpdateSortEvent()
00415     {
00416         for (int i=0; i< mTableListeners.size(); i++)
00417             if (mTableListeners[i]->GetListenTableUpdates())
00418                 mTableListeners[i]->UpdateSortEvent(mSortColumn, mSortAscending);
00419     }
00420 
00421     void DoUpdateScrollFromSourceEvent()
00422     {
00423         for (int i=0; i< mTableListeners.size(); i++)
00424             if (mTableListeners[i]->GetListenTableUpdates())
00425                 mTableListeners[i]->UpdateScrollFromSourceEvent();
00426     }
00427 
00428     /* get individual row characteristics ************************/
00429 
00430     inline String
00431     GetSortedTextData(String column, int row)
00432     {
00433         if (column=="rank")
00434         {
00435             std::ostringstream s;
00436             s << row;
00437             return s.str();
00438         }
00439         return GetTextDataByID(column, mSortSequence[row]);
00440     }
00441 
00442     inline double
00443     GetSortedNormalizedData(String column, int row)
00444     {
00445         return GetNormalizedDataByID(column, mSortSequence[row]);
00446     }
00447 
00448     inline Array2dVec3UInt8*
00449     GetSortedImageData(String column, int row)
00450     {
00451         return GetImageDataByID(column, mSortSequence[row]);
00452     }
00453 
00454     inline Array2dVec3UInt8*
00455     GetSortedVideoData(String column, int row)
00456     {
00457         return GetVideoDataByID(column, mSortSequence[row]);
00458     }
00459 
00460     inline int
00461     GetSortedIntData(String column, int row)
00462     {
00463         return GetIntDataByID(column, mSortSequence[row]);
00464     }
00465 
00466     inline double
00467     GetSortedDoubleData(String column, int row)
00468     {
00469         return GetDoubleDataByID(column, mSortSequence[row]);
00470     }
00471 
00472 
00473     virtual int GetRowHeight(int row)
00474     {
00475         if (mZoomRow > -1)
00476         {
00477             int dist = abs((row) - mZoomRow);
00478             if (dist > 5) return mDefaultRowHeight;
00479             double div;
00480             if (dist == 0) div = 1.0;
00481             if (dist == 1) div = 0.45;
00482             if (dist == 2) div = 0.25;
00483             if (dist == 3) div = 0.15;
00484             if (dist == 4) div = 0.1;
00485             if (dist == 5) div = 0.05;
00486             return (int)(mDefaultRowZoomHeight*div+mDefaultRowHeight*(1.0-div));
00487         }
00488         return mDefaultRowHeight;
00489     }
00490 
00491     int GetID(int row)
00492     {
00493         if (row >= 0 && row < mTotalRows && row < mSortSequence.size())
00494             return mSortSequence[row];
00495         else
00496             return -1;
00497     }
00498 
00499     int GetRowForID(int id)
00500     {
00501         int size = mSortSequence.size();
00502         for (int i=0; i<mTotalRows && i<size; i++)
00503             if (mSortSequence[i] == id)
00504                 return i;
00505         return -1;
00506     }
00507 
00508     virtual String
00509     GetTextDataByID(String column, int row)
00510     {
00511         if (OutOfBounds(row))
00512             return "";
00513         std::ostringstream os;
00514         os << column << ":" << row;
00515         return os.str();
00516     }
00517 
00518     virtual Array2dVec3UInt8*
00519     GetImageDataByID(String column, int row)
00520     {
00521         return 0;
00522     }
00523 
00524     virtual Array2dVec3UInt8*
00525     GetVideoDataByID(String column, int row)
00526     {
00527         return 0;
00528     }
00529 
00530     virtual double
00531     GetNormalizedDataByID(String column, int row)
00532     {
00533         return row / (double)mTotalRows;
00534     }
00535 
00536     virtual int
00537     GetIntDataByID(String column, int row)
00538     {
00539         return 0;
00540     }
00541 
00542     virtual double
00543     GetDoubleDataByID(String column, int row)
00544     {
00545         return 0;
00546     }
00547 
00548 public:
00549     // RvB: Not used yet, but contains a BUG
00550     void RemoveFilter(String column)
00551     {
00552         std::list<TableFilter*>::iterator it;
00553         for (it=mFilters.begin(); it!=mFilters.end(); it++)
00554         {
00555             if ((*it)->GetColumn() == column)
00556                 mFilters.erase(it); //delete *it;
00557 
00558             if (mFilters.size() == 0)
00559                 mFiltersActive = false;
00560 
00561             // RvB: Below is a BUG!!! Not used yet but needs to be solved
00562             if (!mFiltersWorking)
00563                 ApplyFilters();
00564                 break;
00565         }
00566     }
00567 
00568     void RegisterFilter(TableFilter *t)
00569     {
00570         mFiltersWorking = true;
00571         RemoveFilter(t->GetColumn());
00572         mFiltersWorking = false;
00573         mFilters.push_back(t);
00574         mFiltersActive = true;
00575         //ApplyFilters();
00576     }
00577 
00578     void EnableFilterByMark(int mark)
00579     {
00580         ILOG_DEBUG("Enable filter by mark for mark=" << mark);
00581         mFilterByMark = mark;
00582         ApplyFilters();
00583     }
00584 
00585     int GetMarkFilter()
00586     {
00587         return mFilterByMark;
00588     }
00589 
00590     int GetMarkFilterForEverything()
00591     {
00592         return 4|8|16|32|64|128;
00593     }
00594 
00595     void DisableFilterByMark()
00596     {
00597         ILOG_DEBUG("Filter by mark disabled");
00598         mFilterByMark = -1;
00599         ApplyFilters();
00600     }
00601 
00602     std::vector<TableSourceColumnDescription>
00603     GetColumns()
00604     {
00605         return mColumnNames;
00606     }
00607 
00608     std::vector<TableSourceColumnDescription>
00609     GetExtraColumns()
00610     {
00611         return mExtraColumnNames;
00612     }
00613 
00614     virtual void ApplyFilters()
00615     {
00616         SortAndFilter();
00617     }
00618 
00619 
00620 protected:
00621 
00622     void AddStaticColumn(String name, int coltype, int width=120, int param=0)
00623     {
00624         TableSourceColumnDescription p(name, coltype, width, param);
00625         mColumnNames.push_back(p);
00626     }
00627 
00628     void AddColumn(String name, int coltype, int width=120, int param=0)
00629     {
00630         TableSourceColumnDescription p(name, coltype, width, param);
00631         mExtraColumnNames.push_back(p);
00632     }
00633 
00634 private:
00635 
00636     bool IsFiltered(int id)
00637     {
00638         // filter by marked state:
00639         if (mFilterByMark > -1)
00640         {
00641             if (mMarkedRows.find(id) != mMarkedRows.end())
00642             {
00643                 if (!(mMarkedRows[id] & mFilterByMark))
00644                     return true;
00645             }
00646             else if (mFilterByMark != 0)
00647                 return true;
00648         }
00649 
00650         // filter by columns:
00651         if (!mFiltersActive)
00652             return false;
00653 
00654         std::list<TableFilter*>::iterator it;
00655         for (it=mFilters.begin(); it!=mFilters.end(); it++)
00656         {
00657             if ((*it)->GetType() == TYPE_TEXT)
00658             {
00659                 String txt = GetTextDataByID((*it)->GetColumn(), id);
00660                 if ((*it)->IsFilteredByText(txt))
00661                     return true;
00662             }
00663             if ((*it)->GetType() == TYPE_NORMALIZEDVALUE)
00664             {
00665                 double dVal = GetNormalizedDataByID((*it)->GetColumn(),id);
00666                 if ((*it)->IsFilteredByValue(dVal))
00667                     return true;
00668             }
00669             if ((*it)->GetType() == TYPE_DOUBLE)
00670             {
00671                 double dVal = GetDoubleDataByID((*it)->GetColumn(),id);
00672                 if ((*it)->IsFilteredByValue(dVal))
00673                     return true;
00674             }
00675             if ((*it)->GetType() == TYPE_INT)
00676             {
00677                 int iVal = GetIntDataByID((*it)->GetColumn(),id);
00678                 // DO: Converts to double automatically? Is this right?
00679                 if ((*it)->IsFilteredByValue(iVal))
00680                     return true;
00681             }
00682         }
00683         return false;
00684     }
00685 
00686 protected:
00687     int             mTotalRows;
00688     int             mFilteredRows;
00689 
00690     int             mDefaultRowHeight;
00691     int             mDefaultRowZoomHeight;
00692     int             mZoomRow;
00693 
00694 private:
00695     bool            mFiltersActive;
00696     bool            mFiltersWorking;
00697     bool            mSortAscending;
00698 
00699     int             mStartRow;
00700     int             mDisplayRows;
00701     int             mSortType; // Needs to be removed and nicified
00702     int             mFilterByMark;
00703 
00704     String          mSortColumn;
00705 
00706     std::vector<TableUpdateListener*>           mTableListeners;
00707     std::list<TableFilter*>                     mFilters;
00708     std::vector<int>                            mSortSequence;
00709     std::map<int, int>                          mMarkedRows;
00710     std::map<int, bool>                         mVisibleRows;
00711 
00712     // self description of data columns:
00713     std::vector<TableSourceColumnDescription>   mColumnNames;
00714     std::vector<TableSourceColumnDescription>   mExtraColumnNames;
00715 
00716     ILOG_VAR_DEC;
00717 };
00718 
00719 ILOG_VAR_INIT(TableDataSource, Application.VideoExcel);
00720 
00721 } // namespace VideoExcel
00722 } // namespace Application
00723 } // namespace Impala
00724 
00725 #endif // TableDataSource_h

Generated on Fri Mar 19 09:30:34 2010 for ImpalaSrc by  doxygen 1.5.1