trapperview.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002  *                                                                             *
00003  *   Copyright (C) 2003  Erik Sjolund,  (<html>Erik Sj&ouml;lund</html>)       *
00004  *                       Center for Genomics and Bioinformatics,               *
00005  *                       Karolinska Institutet,                                *
00006  *                       Stockholm,                                            *
00007  *                       Sweden                                                *
00008  *                                                                             *
00009  *  Author: Erik Sjolund                                                       *
00010  *  Email: erik.sjolund@adivo.se                                               *
00011  *                                                                             *
00012  *******************************************************************************
00013  */
00014 
00015 // include files for Qt
00016 #include <qprinter.h>
00017 #include <qinputdialog.h>
00018 #include <qlineedit.h>
00019 #include <qstring.h>
00020 #include <qcstring.h>
00021 #include <qvaluelist.h>
00022 #include <qwidget.h>
00023 #include <qdragobject.h>
00024 #include <qclipboard.h>
00025 #include <qapplication.h>
00026 
00027 #include <qpopupmenu.h>
00028 #include <qlabel.h>
00029 #include "trapperconf.h"
00030 #include <qcursor.h>
00031 // application specific includes
00032 #include "trapperview.h"
00033 #include "trapperdoc.h"
00034 
00035 #include "generalmaker.h"
00036 
00037 #include "featuregui.h"
00038 #include "readdata.h"
00039 
00040 #include "viewmode.h"
00041 #include <string>
00042 #include <iostream>
00043 
00044 #include "algomaker.h"
00045 #include "algo.h"
00046 
00047 #include <algorithm>
00048 #include <cstdlib>
00049 #include <vector>
00050 #include "readsinrect.h"
00051 #include <sstream>
00052 #include "destroyer.h"
00053 #include "infopopup.h"
00054 
00055 
00056 using namespace std;
00057 
00058 
00059 /** \brief drag object representing selected reads. Is created when a drag in TrapperView is initiated. */
00060 
00061 class ReadDrag : public QStoredDrag
00062 {
00063 public:
00064   ReadDrag( QPixmap & pixmap, QPoint & hotspot, QWidget * w ) : QStoredDrag("min_mime_type", w) {
00065     setPixmap( pixmap, hotspot );
00066 
00067   } 
00068   ReadDrag( QWidget* w ) : QStoredDrag("min_mime_type", w) { } 
00069   ~ReadDrag(){}
00070   
00071 };
00072 
00073 TrapperView::TrapperView(TrapperDoc* pDoc, QWidget *parent, const char* name, QString _viewMode )
00074   : QScrollView(parent, name,/** wflags**/ WResizeNoErase|WStaticContents|WDestructiveClose/*|WNoAutoErase*/), doc( pDoc )
00075 {
00076 //   cerr << "in TrapperView::TrapperView" << endl;
00077 //   cerr<<"doc: "<<doc<<endl;
00078   viewport()->setAcceptDrops( true );
00079   setDragAutoScroll( true );
00080   allow_dragging = true;
00081   dragging = false;
00082   moving = false;
00083   rubber_band = 0;
00084   last_click_selected_read = false;
00085   last_click_changed_selection = false;
00086   time_course = false;
00087   tc_normalize = false;
00088 
00089   setFocusPolicy(StrongFocus);
00090   
00091   if ( _viewMode.isNull() )
00092     {
00093       _viewMode = "closeup";
00094     }
00095 
00096   viewModes = new ViewModes( _viewMode, doc );
00097   
00098   //Ugly business here...
00099   list<string> type_list = GeneralMaker::listRegistered();
00100   for( list<string>::iterator it = type_list.begin(); it != type_list.end(); ++it ) {
00101     zoom_cutoff[ *it ] = 0;
00102   }
00103   zoom_cutoff["DnaStrData"] = 4;
00104   zoom_cutoff["QualityData"] = 4;
00105   zoom_cutoff["ChromatData"] = 8;
00106   zoom_cutoff["DnpData"] = 1;
00107 //   min_cutoff = 1;
00108   min_cutoff = 0.0009765625;
00109 
00110 
00111 //   globalRows = 1000;
00112 //   globalBases = 50000;
00113   globalRows = 50;
00114   globalBases = 2000;
00115 //   rowheight = 20;
00116 //   basewidth = 10;
00117   rowheight = 5;
00118   basewidth = 1;
00119   magnifyX = 8;
00120   magnifyY = 4;
00121   zoomfactor = 2;
00122   spaceBetweenRows = 0;
00123   center_point = 0;
00124 
00125   read_cluster_min_num = 10;
00126   read_cluster_window = 100;
00127 
00128 
00129   fitContentsizeToData();
00130   
00131 
00132   viewport()->setPaletteBackgroundColor(white);
00133   viewport()->setBackgroundMode( Qt::FixedColor );
00134   setCaption( "yes" );
00135   viewport()->setMouseTracking(TRUE);
00136 }
00137 
00138 
00139 TrapperView::~TrapperView()
00140 {
00141  
00142   if ( viewModes ) {
00143     delete viewModes;
00144     viewModes = NULL;
00145   }
00146 }
00147 
00148 void TrapperView::fitContentsizeToData()
00149 {
00150   Database::SecondaryIterator<ReadData>* end_it = new Database::SecondaryIterator<ReadData>( "end", doc, "ReadData" );
00151   int ret_end = end_it->last();
00152   Database::SecondaryIterator<ReadData>* row_it = new Database::SecondaryIterator<ReadData>( "pos", doc, "ReadData" );
00153   int ret_row = row_it->last();
00154   ReadData* r_end = (ret_end != DB_NOTFOUND) ? end_it->answer() : 0;
00155   ReadData* r_row = (ret_row != DB_NOTFOUND) ? row_it->answer() : 0;
00156   if ( r_end ) {
00157     
00158     globalBases = r_end->endPos() + 50;    
00159   }
00160   if ( r_row ) {
00161     
00162     globalRows = r_row->row() + 500;
00163   }
00164   
00165   delete end_it;
00166   delete row_it;
00167   
00168   resizeContents(static_cast<int>(globalBases * magnifyX * basewidth), globalRows * rowheight * magnifyY);
00169  
00170 }
00171 
00172 QString TrapperView::mode()
00173 {
00174     return viewModes->currentViewMode()->name();
00175 }
00176 
00177 TrapperDoc *TrapperView::getDocument() const
00178 {
00179     return doc;
00180 }
00181 
00182 void TrapperView::update(TrapperView* pSender)
00183 {
00184     if(pSender != this)
00185         repaint();
00186 }
00187 
00188 void TrapperView::print(QPrinter *pPrinter)
00189 {
00190     if (pPrinter->setup(this))
00191     {
00192         QPainter p;
00193         p.begin(pPrinter);
00194 
00195         ///////////////////////////////
00196         // TODO: add your printing code here
00197         ///////////////////////////////
00198 
00199         p.end();
00200     }
00201 }
00202 
00203 void TrapperView::closeEvent(QCloseEvent*)
00204 {
00205     // LEAVE THIS EMPTY: THE EVENT FILTER IN THE TrapperApp CLASS TAKES CARE FOR CLOSING
00206     // QWidget closeEvent must be prevented.
00207 }
00208 
00209 void TrapperView::convertToDnaCoordinates( TR_DNA & x_dna, TR_DNA & y_dna, const TR_PIX cx, const TR_PIX cy )
00210 {
00211     x_dna = pixelCoordToDna_X(cx);
00212     y_dna = pixelCoordToDna_Y(cy);
00213     return;
00214 }
00215 
00216 TR_DNA TrapperView::pixelCoordToDna_X( TR_PIX cx )
00217 {
00218 //   if ( basewidth * magnifyX < 1 ) {
00219 //     cerr<<"basewidth: "<<basewidth<<endl;
00220 //     cerr<<"basewidth * magnifyX: "<<basewidth * magnifyX<<endl;
00221 //   }
00222   
00223 
00224   return static_cast<TR_DNA>(cx / ( basewidth * magnifyX ));
00225 }
00226 
00227 TR_DNA TrapperView::pixelCoordToDna_Y( TR_PIX cy )
00228 {
00229   return cy / ( rowheight * magnifyY );
00230 }
00231 
00232 void TrapperView::convertToPixelCoordinates( TR_PIX & x_pix, TR_PIX & y_pix, TR_DNA x_dna, TR_DNA y_dna )
00233 {
00234     x_pix = dnaCoordToPixel_X(x_dna);
00235     y_pix = dnaCoordToPixel_Y(y_dna);
00236     return;
00237 }
00238 
00239 TR_PIX TrapperView::dnaCoordToPixel_X( TR_DNA x_dna )
00240 {
00241 //   if ( x_dna * basewidth * magnifyX < 1 ) {
00242 //     cerr<<"x_dna: "<<x_dna<<endl;
00243 //     cerr<<"basewidth: "<<basewidth<<endl;
00244 //     cerr<<"x_dna * basewidth * magnifyX: "<<x_dna * basewidth * magnifyX<<endl;
00245 //   }
00246   
00247 
00248   return static_cast<TR_PIX>(x_dna * basewidth * magnifyX);
00249 }
00250 
00251 TR_PIX TrapperView::dnaCoordToPixel_Y( TR_DNA y_dna )
00252 {
00253   return y_dna * rowheight * magnifyY;
00254 }
00255 
00256 void TrapperView::paintFeatures( QPainter* p, QPainter * bitmapPainter, db_recno_t readRecno, 
00257                                  TR_PIX x_pix, TR_PIX y_pix, 
00258                                  TR_DNA x_dna_relative, TR_DNA dna_len , 
00259                                  /*TR_PIX*/double width, TR_PIX height, bool selected, int center_relative, 
00260                                  bool overlap, TR_DNA bg, TR_DNA eg )
00261 {
00262 
00263   int pix_len = static_cast<int>(dna_len*width);
00264   if ( pix_len < 1 ) {
00265     pix_len = 1;
00266   }
00267   
00268   
00269   Layer * layer;
00270   
00271   p->setPen( Qt::black );
00272   
00273   /* clear away old painted stuff, by painting white in the read rectangle */
00274   QBrush brush;
00275   brush.setStyle( Qt::SolidPattern );
00276   brush.setColor( Qt::white );
00277   p->fillRect( x_pix  , y_pix ,  pix_len , height ,brush) ;
00278   
00279   brush.setColor( Qt::color1 );
00280   
00281   if ( bitmapPainter && selected )
00282     bitmapPainter->fillRect( x_pix  , y_pix , pix_len , height ,brush) ;
00283   
00284   /*  finished clearing */
00285   
00286   
00287   
00288   
00289   
00290   // we use two pixels in the height to draw the paintReadBorder
00291   y_pix += 1;
00292   height -= 2;
00293   
00294   
00295   
00296   /* starting painting features */
00297   
00298   if ( !time_course  ) {
00299   
00300     TR_PIX heightLayerSum = 0; /* each feature knows how many percent of the total height
00301                                   it may use when painting itself. The variable heightLayerSum stores how much of the
00302                                   total height has already been painted to by other feature layers */
00303     for (layer = viewModes->currentViewMode()->layerList.first(); layer; layer =  viewModes->currentViewMode()->layerList.next() ) {
00304       TR_PIX heightLayer = layer->heightInPix( height );
00305       Database::SecondaryIterator<SpatialFeatureData> * it;
00306       for (it  = layer->featureList.first(); it; it = layer->featureList.next() ) {
00307 
00308         if ( magnifyX < min_cutoff || magnifyY < min_cutoff ) continue;
00309         int cutoff = zoom_cutoff[ it->name() ];
00310         if ( magnifyX < cutoff || magnifyY < cutoff ) continue;
00311         
00312         it->key()->setReadRecno( readRecno );
00313         if ( it->set() == 0 ) {
00314           int ret;
00315           do {
00316             
00317             
00318             it->answer()->gui()->paint( p, x_pix, y_pix + heightLayerSum , x_dna_relative, x_dna_relative + dna_len -1 , width, heightLayer, center_relative );
00319             
00320           } while ( (ret = it->nextdup())  == 0);
00321           
00322           
00323         }
00324         it->closeCursor();
00325       }
00326       heightLayerSum += heightLayer;
00327     }
00328   }
00329   else  {
00330     
00331     //TIME COURSE
00332     Database::SecondaryIterator<ReadMetaData> read_meta_it( "readRecno", doc, "ReadMetaData" );
00333     //   assert( read_it.setFromRecno(readRecno) == 0 );
00334     read_meta_it.key()->setReadRecno( readRecno );
00335     assert(read_meta_it.set() == 0 );
00336     if ( read_meta_it.answer()->tc_vec.stlVector().size() != 0 ) {
00337     
00338 
00339       Database::PrimaryIterator<ReadData> read_it( doc, "ReadData" );
00340       assert( read_it.setFromRecno(readRecno) == 0 );
00341       
00342       //     int tc_len = dnaCoordToPixel_X( read_it.answer()->tc_vec.stlVector().size() );
00343       int tc_len = dnaCoordToPixel_X( read_it.answer()->endPos() - read_it.answer()->startPos() + 1 );
00344       int start_tc_pix = dnaCoordToPixel_X( read_it.answer()->startPos() ) + 1;
00345       int stop_tc_pix = start_tc_pix + tc_len;
00346       //     if ( r_end && cx + cw > start_tc_pix && cx < stop_tc_pix ) {
00347       //Part of time course needs to be drawn
00348       
00349       //Paint new TC
00350       int numpoints = read_meta_it.answer()->tc_vec.stlVector().size();
00351       if ( numpoints > 0 ) {
00352         
00353         
00354         int pix_per_point = tc_len/numpoints;
00355         
00356         //       int start_paint_index = max(0, (cx - start_tc_pix)/numpoints - 10);
00357         //       int stop_paint_index = min(numpoints, (cx + cw)/numpoints);
00358         int start_paint_index = 0;
00359         int stop_paint_index = numpoints;
00360         
00361         
00362         
00363         //Need to find the max tc value for each read for normalization
00364         double max_tc(0.000001);
00365         if ( tc_normalize ) {
00366           bool foundmax(false);
00367           for( size_t i = 0; i < read_meta_it.answer()->tc_vec.stlVector().size(); i++ ) {
00368             if ( read_meta_it.answer()->tc_vec.stlVector()[i] > max_tc ) {
00369               max_tc = read_meta_it.answer()->tc_vec.stlVector()[i];
00370               foundmax = true;
00371             }
00372           }
00373           if ( !foundmax ) {
00374             max_tc = 1;
00375           }
00376         }
00377         
00378         QBrush brush;
00379         for( int i = start_paint_index; i < stop_paint_index && i < numpoints; i++ ) {
00380           brush.setStyle( Qt::SolidPattern );
00381           QColor tc_color;
00382           double tc_val = read_meta_it.answer()->tc_vec.stlVector()[i];
00383           if ( ( tc_normalize && tc_val/max_tc < 0.125 ) || ( !tc_normalize && tc_val < 1) ) {
00384             tc_color.setNamedColor("#0000FF");
00385           }
00386           else if ( ( tc_normalize && tc_val/max_tc < 0.250 ) || ( !tc_normalize && tc_val < 2 ) ) {
00387             tc_color.setNamedColor("#00BFFF");
00388           }
00389           else if ( ( tc_normalize && tc_val/max_tc < 0.375 ) || ( !tc_normalize && tc_val < 5 ) ) {
00390             tc_color.setNamedColor("#20B2AA");
00391           }
00392           else if ( ( tc_normalize && tc_val/max_tc < 0.500 ) || ( !tc_normalize && tc_val < 10 ) ) {
00393             tc_color.setNamedColor("#32CD32");
00394           }
00395           else if ( ( tc_normalize && tc_val/max_tc < 0.625 ) || ( !tc_normalize && tc_val < 100 ) ) {
00396             tc_color.setNamedColor("#FFD700");
00397           }
00398           else if ( ( tc_normalize && tc_val/max_tc < 0.750 ) || ( !tc_normalize && tc_val < 500 ) ) {
00399             tc_color.setNamedColor("#FFA500");
00400           }
00401           else if ( ( tc_normalize && tc_val/max_tc < 0.875 ) || ( !tc_normalize && tc_val < 1000 ) ) {
00402             tc_color.setNamedColor("#FF4500");
00403           }
00404           else {
00405             tc_color.setNamedColor("#FF0000");
00406           }
00407           
00408           brush.setColor( tc_color );
00409           p->fillRect( start_tc_pix + i* pix_per_point, read_it.answer()->row()*rowheight*magnifyY + 2, pix_per_point, rowheight*magnifyY - spaceBetweenRows - 2,brush) ;
00410           
00411         }
00412         
00413       }
00414     }
00415     
00416   }
00417   
00418   //     }
00419   
00420   //END TIME COURSE
00421   
00422   
00423   
00424   
00425 
00426   /* finished painting features */
00427   
00428   
00429   /* paint readBorder, start */
00430   
00431   /* the horisontal border is painted just outside the features,
00432      but the vertical border is painted on the features side, so the 
00433      features lose one pixel of width on the left and right sides */
00434   
00435   QPen oldpen( p->pen() ), newpen( p->pen() );
00436   
00437   if ( selected ) {
00438     newpen.setColor( Qt::red );
00439     if ( moving )
00440       newpen.setStyle( Qt::DashLine);
00441   }
00442   if ( overlap ) {
00443     newpen.setColor(Qt::green);
00444   }
00445   p->setPen(newpen);
00446   
00447   
00448   p->drawRect( x_pix  , y_pix,  pix_len, height ) ;
00449 
00450   //Quality trimming
00451   brush.setStyle( Qt::Dense4Pattern );
00452   brush.setColor( Qt::white );
00453   if ( x_dna_relative < bg ) {
00454     p->fillRect( x_pix  , y_pix,  static_cast<int>((bg - x_dna_relative)*width), height, brush ) ;
00455   }
00456   if ( x_dna_relative + dna_len > eg ) {
00457     int goodlen = eg - x_dna_relative + 1;
00458     if ( goodlen < 0 ) goodlen = 0;
00459     p->fillRect( static_cast<int>(x_pix + goodlen*width), y_pix, static_cast<int>((dna_len - goodlen )*width), height, brush ) ;
00460   }
00461   
00462   p->setPen( oldpen );
00463 
00464 
00465   
00466   /* finished painting readBorder */
00467 }
00468 
00469 // void TrapperView::drawContents(QPainter* p, int cx, int cy, int cw, int ch)
00470 void TrapperView::drawContents(QPainter* p, TR_PIX cx, TR_PIX cy, TR_PIX cw, TR_PIX ch)
00471 {
00472 //   QPoint qp = viewportToContents(viewport()->rect().topLeft());
00473 //   cerr<<"qp.x(): "<<qp.x()<<endl;
00474 //   cerr<<"qp.y(): "<<qp.y()<<endl;
00475 
00476   drawContents_helper(p, NULL, cx, cy, cw, ch, 0, 0);
00477   paintGrid( p, cx, cy, cw, ch);
00478 }
00479 
00480 void TrapperView::drawContents_helper(QPainter* p,QPainter* bitmapPainter, int cx, int cy, int cw, int ch, int dx, int dy)
00481 {
00482   /* We have the window to paint in pixel coordinates, but the biological data ( the reads ) are stored
00483      in dna coordinates. The pixel coordinates are on a smaler scale than the dna coordinates, so therefore
00484      the pixel coordinates might lay a fraction of a dna coordinate. Thus we seak the minimal overlapping window 
00485      in dna coordinates. */
00486 
00487 
00488   if ( moving ) {
00489     assert( bitmapPainter == 0 );
00490     //MOVINGTEST
00491 //     p->setRasterOp(NotROP);
00492     p->setRasterOp(NotXorROP);
00493 //      p->setRasterOp(XorROP);
00494     if ( moveOn ) {
00495       p->drawPixmap(oldMovePoint, dragPixmap);
00496     }
00497     else {
00498       oldMovePoint = contentsToViewport(mousePressedPoint - dragWindowPoint);
00499       p->setRasterOp(NotXorROP);
00500       p->drawPixmap(oldMovePoint, dragPixmap);
00501       
00502     }
00503     
00504 
00505     oldMovePoint = contentsToViewport(mousePressedPoint - dragWindowPoint + QPoint(0, dnaCoordToPixel_Y(pixelCoordToDna_Y(y_delta)) ));
00506     //END MOVINGTEST
00507 //     oldMovePoint = mousePressedPoint - dragWindowPoint + QPoint(0, dnaCoordToPixel_Y(pixelCoordToDna_Y(y_delta)) );
00508     p->drawPixmap(oldMovePoint, dragPixmap);
00509     //MOVINGTEST
00510     moveOn = true;
00511     return;
00512     //END MOVINGTEST
00513   }
00514   
00515   
00516   TR_DNA x_dna, y_dna; /* the dna coordinate of upperleft corner of the overlapping dna window */
00517   TR_DNA x2_dna, y2_dna;
00518   TR_DNA h_dna, w_dna; /* representing the width and height of the overlapping dna window */
00519   
00520   convertToDnaCoordinates( x_dna, y_dna, cx, cy );
00521   convertToDnaCoordinates( x2_dna, y2_dna, cx + cw - 1, cy + ch - 1 );
00522 
00523   /* to be on the safe side that we paint on a rectangle big enough we add some on the edges.
00524      The reason comes from the fact that vertical read border is drawn up on the uttermost pixels
00525      of the feature area. */
00526    x_dna -= 10;
00527    x2_dna += 10;
00528   
00529   w_dna = x2_dna - x_dna + 1;
00530   h_dna = y2_dna - y_dna + 1;
00531   
00532   
00533   
00534   TR_PIX x_pix, y_pix; /* the pixel coordinate of upperleft corner of the overlapping dna window */
00535   convertToPixelCoordinates( x_pix, y_pix, x_dna, y_dna );
00536   
00537   TR_PIX cx_paint = x_pix + dx;
00538   TR_PIX cy_paint = y_pix + dy;
00539 
00540 
00541 
00542   
00543   readsInRect = new ReadsInRect( doc );
00544 
00545 
00546   readsInRect->setWindowCoord( x_dna, y_dna,  w_dna,h_dna );
00547 //   cerr<<"rowheight*magnifyY - spaceBetweenRows: "<<rowheight*magnifyY - spaceBetweenRows<<endl;
00548   int previous_row(-1), previous_end(-1);
00549   for ( ReadData * r = readsInRect->first(); r; r = readsInRect->next() ) {
00550 //     cerr<<r->name()<<'\t'<<r->getRecno()<<endl;
00551     
00552     bool overlap(false);
00553     if ( r->row() == previous_row && (r->startPos() <= previous_end ) ) {
00554       overlap = true;
00555     }
00556     previous_row = r->row();
00557     previous_end = r->endPos();
00558     
00559     bool selected = isSelected( r->getRecno() );
00560     
00561     /* we just have to paint the part of the read that is visible in the current window.
00562        Therefore we seak max and min values 
00563     */
00564     
00565     TR_DNA x1_dna_paint = max( r->startPos(), x_dna    ) ;
00566     TR_DNA x2_dna_paint = min( r->endPos(), x_dna + w_dna - 1  ) ;
00567     
00568     TR_PIX x_pix_adjust, y_pix_adjust;
00569     convertToPixelCoordinates( x_pix_adjust, y_pix_adjust, x1_dna_paint - x_dna, r->row() - y_dna );
00570     
00571     // x_pix += cx;
00572     //      y_pix += cy;
00573     
00574     TR_DNA len = x2_dna_paint - x1_dna_paint +1 ;
00575     
00576     paintFeatures( p, bitmapPainter, r->getRecno(), 
00577                    x_pix_adjust + cx_paint, y_pix_adjust + cy_paint,  
00578                    x1_dna_paint - r->startPos(), len, 
00579                    basewidth*magnifyX, rowheight*magnifyY - spaceBetweenRows , selected, center_point - r->startPos(), 
00580                    overlap, 0, r->endPos() - r->startPos() );
00581 //                    overlap, r->beginGood(), r->endGood() );
00582     
00583   }
00584   
00585   
00586   delete readsInRect;
00587 
00588 
00589 
00590 
00591   if ( rubber_band ) {
00592     QPen oldpen( p->pen() );
00593     QPen newpen( Qt::black, 0, Qt::DotLine );
00594     
00595     p->setPen( newpen );
00596     p->drawRect( *rubber_band );
00597     p->setPen( oldpen );    
00598     
00599   }
00600 
00601   return;
00602   
00603   
00604 }
00605 
00606 void TrapperView::paintGrid(QPainter* p, TR_PIX cx, TR_PIX cy, TR_PIX cw, TR_PIX ch)
00607 {
00608   p->setPen( Qt::black );
00609 
00610   int local_rowheight = 100;
00611   int toprow=cy/local_rowheight;
00612   int bottomrow=(cy+ch+local_rowheight-1)/local_rowheight;
00613   int colwidth=100;
00614   int leftcol=cx/colwidth;
00615   int rightcol=(cx+cw+colwidth-1)/colwidth;
00616 
00617   //Coordinates
00618   QFont f;
00619   f.setPointSize(10);
00620   p->setFont(f);
00621   int viewport_toprow=contentsY()/local_rowheight - 2;
00622   if (viewport_toprow <0 ) viewport_toprow = 0;
00623   
00624   int viewport_bottomrow=(cy+ch+local_rowheight-1)/local_rowheight + 1;
00625   for( int i = leftcol; i <= rightcol; i++ ) {
00626     p->drawText( i*colwidth + dnaCoordToPixel_X(1)/2, 10, QString().setNum(pixelCoordToDna_X( i*colwidth )) );
00627   }
00628   for( int i = viewport_toprow; i < viewport_bottomrow; i++ ) {
00629     p->drawText( 0, i*local_rowheight, QString().setNum(pixelCoordToDna_Y( i*local_rowheight )) );    
00630   }
00631 
00632   return;
00633   
00634 
00635   //Grid
00636   for (int r=toprow; r<=bottomrow; r++) {
00637     int py=r*local_rowheight - dnaCoordToPixel_Y(1)/2;
00638     for (int c=leftcol; c<=rightcol; c++) {
00639       int px=c*colwidth + dnaCoordToPixel_X(1)/2;
00640       p->drawLine(px, py, px+2, py);
00641       
00642     }
00643   }
00644   
00645 
00646   //Chromat line
00647   bottomrow=(cy+ch+rowheight-1)/rowheight;
00648   int center_x = dnaCoordToPixel_X(center_point) + dnaCoordToPixel_X(1)/2;
00649   p->drawLine(center_x, 0, center_x, bottomrow*rowheight );
00650 
00651 }
00652 
00653 void TrapperView::moveData(TR_PIX dx, TR_PIX dy)
00654 {
00655 //     cerr<<"PLEASE NOTE: ALGO PARAMS SHOULD BE FIXED!!!"<<endl;
00656   TR_DNA col_delta, row_delta;
00657   row_delta = pixelCoordToDna_Y( dy );
00658   col_delta = pixelCoordToDna_X( dx);
00659 
00660   AlgoMoveParam param( col_delta, row_delta );
00661   
00662   runAlgo( "Move Reads", getSelectedReads(), &param );
00663 
00664   last_move_x = param.get_x_delta();
00665   last_move_y = param.get_y_delta();
00666   
00667   
00668 }
00669 
00670 void TrapperView::clearLastMove()
00671 {
00672   last_move_x = last_move_y = 0;
00673 }
00674 
00675 
00676 void TrapperView::contentsMousePressEvent(QMouseEvent* e)
00677 {
00678   setFocus();
00679 
00680   QString msg = "Row: " + QString().setNum(pixelCoordToDna_Y(e->y())) + ", col: " + QString().setNum(pixelCoordToDna_X(e->x()));
00681   sendMsg( msg );
00682 
00683   y_delta = 0;
00684   y_delta_previous = 0;
00685   
00686   bool ctrlclick = Qt::ControlButton & e->state();
00687   bool leftbutton = Qt::LeftButton & e->stateAfter();
00688 
00689   if ( ctrlclick ) {
00690     ctrl = true;
00691   }
00692   else {
00693     ctrl = false;
00694   }
00695   
00696   
00697 
00698   
00699   
00700   mousePressedPoint.setX( e->x() );
00701   mousePressedPoint.setY( e->y() );
00702 
00703   
00704   //RUBBERTEST
00705   RubberStart=contentsToViewport(e->pos());
00706   RubberEnd = RubberStart;
00707   RubberOn=FALSE;
00708   //END RUBBERTEST
00709 
00710   //MOVINGTEST
00711   moveOn = false;
00712   //END MOVINGTEST
00713 
00714   TR_DNA x_dna, y_dna;
00715   convertToDnaCoordinates( x_dna, y_dna, e->x(), e->y() );
00716   
00717   readsInRect = new ReadsInRect( doc );
00718 //   readsInRect->setWindowCoord( x_dna, y_dna, 1, 1 );  /* a rectangle with dimension 1x1 */
00719   readsInRect->setWindowCoord( x_dna, y_dna, 3, 3 );  /* a rectangle with dimension 3x3 */
00720   ReadData * r = readsInRect->first(); 
00721   if ( r ) {//hit read
00722     if ( ctrlclick ) {
00723       if ( isSelected( r->getRecno() ) ) {
00724         select( r->getRecno(), false );
00725         last_click_selected_read = false;
00726         last_click_changed_selection = true;
00727       }
00728       else {
00729         select( r->getRecno(), true);
00730         last_click_selected_read = true;
00731         last_selected_recno = r->getRecno();
00732         last_click_changed_selection = true;
00733       }
00734     }//end ctrlclick
00735     else {//no ctrlclick
00736       if ( isSelected( r->getRecno() ) ) {
00737         last_click_selected_read = true;
00738         last_selected_recno = r->getRecno();
00739         last_click_changed_selection = false;
00740       }
00741       else {
00742         clearSelected();
00743         select( r->getRecno(), true);       
00744         last_click_selected_read = true;        
00745         last_selected_recno = r->getRecno();
00746         last_click_changed_selection = true;
00747       }
00748       
00749     }//end no ctrlclick
00750     if ( last_click_selected_read )
00751       dragging = TRUE; 
00752   }// end hit read
00753   else {//didn't hit read
00754 //     if ( rubber_band != 0 ) {
00755 //       delete rubber_band;
00756 //     }
00757 //     rubber_band = new QRect( mousePressedPoint, mousePressedPoint );
00758     if ( ctrlclick ) {
00759       last_click_selected_read = false;
00760       last_click_changed_selection = false;
00761     }//end ctrlclick
00762     else {//no ctrlclick
00763       last_click_selected_read = false;
00764       if ( selectedReads.size() > 0 )
00765         last_click_changed_selection = true;
00766         
00767       clearSelected();
00768 
00769       //"Rubber band"
00770 //       if ( rubber_band != 0 ) {
00771 //         delete rubber_band;
00772 //       }
00773 //       if ( leftbutton )
00774 //         rubber_band = new QRect( mousePressedPoint, mousePressedPoint );
00775       
00776       
00777     }//end no ctrlclick
00778     if ( rubber_band != 0 ) {
00779       delete rubber_band;
00780     }
00781     if (leftbutton && !last_click_selected_read) {
00782       moving = false;
00783       rubber_band = new QRect( mousePressedPoint, mousePressedPoint );
00784     }
00785     
00786   }//end didn't hit read
00787 
00788 //   updateContents();//Removed this because of visual bug...
00789   delete readsInRect;
00790   
00791   // From here on: about Start a drag and painting
00792   if ( last_click_selected_read )//"if" added 071203
00793   {
00794     cerr<<"filling pixmap..."<<endl;
00795     dragWindowPoint.setX( size().width() );
00796     dragWindowPoint.setY( size().height() );
00797     QRect re( mousePressedPoint - dragWindowPoint, mousePressedPoint + dragWindowPoint );
00798     
00799     
00800     dragPixmap.resize( re.size() );
00801     QPainter p2;
00802     p2.begin(&dragPixmap, this);
00803     dragBitmap.resize( re.size()  );
00804     p3.begin(&dragBitmap, this);
00805     QBrush brush;
00806     brush.setStyle( Qt::SolidPattern );
00807     brush.setColor( Qt::white );
00808     p2.fillRect( 0  , 0 , re.width() , re.height() ,brush) ;
00809     brush.setColor( Qt::color0 );
00810     
00811     p3.fillRect( 0  , 0 , re.width() , re.height() ,brush) ;
00812     
00813     QPoint tl = re.topLeft() ;
00814     QPoint br = re.bottomRight() ;
00815     
00816     drawContents_helper(&p2, &p3, tl.x(), tl.y(), br.x() - tl.x() + 1, br.y() - tl.y() + 1, 
00817                         - ( mousePressedPoint.x() - dragWindowPoint.x() ),  - ( mousePressedPoint.y() - dragWindowPoint.y() ));
00818     
00819     dragPixmap.setMask(dragBitmap);
00820 
00821     p2.end();
00822     p3.end();
00823   }
00824 }
00825 
00826 
00827 void TrapperView::contentsMouseMoveEvent(QMouseEvent* e)
00828 {
00829   QString msg = "Row: " + QString().setNum(pixelCoordToDna_Y(e->y())) + ", col: " + QString().setNum(pixelCoordToDna_X(e->x()));
00830   sendMsg( msg );
00831 
00832   bool nobutton = Qt::NoButton & e->state();
00833 
00834   if ( nobutton ) {
00835     moving = false;
00836     return;
00837   }
00838 
00839 
00840 
00841   if ( allow_dragging && dragging ) {
00842 //     if ( dragging ) 
00843 //       cerr<<"Dragging..."<<endl;
00844 
00845 
00846     ReadDrag *d = new ReadDrag( dragPixmap, dragWindowPoint, this );
00847 //     QCString ar("hej");
00848     QByteArray ar;
00849     QDataStream data_stream(ar, IO_WriteOnly);
00850     writeSelected(data_stream);
00851 
00852     d->setEncodedData(ar);
00853     d->dragCopy(); // do NOT delete d.
00854     dragging = FALSE;
00855     moving = false;
00856     last_click_selected_read = false;
00857 //     cerr<<"Stopped dragging"<<endl;
00858   }
00859   else if ( last_click_selected_read ) {
00860 //   else if ( !selectedReads.empty() ) {
00861     //"Normal" moving
00862     moving = true;
00863     
00864     curr_mouse_pos = e->pos();//Don't really need this??
00865 //     y_delta = pixelCoordToDna_Y( (curr_mouse_pos - mousePressedPoint).y() );
00866     y_delta = (curr_mouse_pos - mousePressedPoint).y();
00867 
00868     if ( pixelCoordToDna_Y( y_delta) == pixelCoordToDna_Y( y_delta_previous ) ) {
00869 //       moving = false;
00870       return;
00871     }
00872     
00873     y_delta_previous = y_delta;
00874 
00875     //MOVINGTEST
00876 
00877     QPainter p(viewport());
00878     drawContents_helper(&p, 0,0,0,0,0,0,0);
00879     return;
00880     //END MOVINGTEST
00881     
00882     updateContents();
00883   }
00884   else if ( rubber_band != 0 ) {
00885 
00886     //RUBBERTEST
00887     QPainter p(viewport());
00888     p.setPen(QColor(255,255,255));
00889     p.setRasterOp(NotROP);
00890     if(RubberOn) drawRubber(&p);
00891     RubberEnd= contentsToViewport(e->pos());
00892     drawRubber(&p);
00893     RubberOn=TRUE;
00894     return;
00895     //END RUBBERTEST
00896     
00897     curr_mouse_pos = e->pos();
00898     
00899     QRect oldband = rubber_band->normalize();
00900 
00901     rubber_band->setSize( QSize( curr_mouse_pos.x() - mousePressedPoint.x(),
00902                                  curr_mouse_pos.y() - mousePressedPoint.y() ) );
00903     
00904 //     updateContents();
00905     QPoint margin( 1, 1 );
00906     QRect norm = rubber_band->normalize();
00907     
00908     updateContents( QRect( norm.topLeft() - margin, norm.bottomRight() + margin ).unite( QRect(oldband.topLeft() - margin, oldband.bottomRight() + margin ) ) );
00909   }
00910   
00911 }
00912 
00913 void TrapperView::contentsMouseReleaseEvent(QMouseEvent* e)
00914 {
00915   dragging = false;
00916   //Maybe dragging code here? NO!
00917   
00918   if ( moving ) {
00919     //Moving stuff...
00920     moveData(0, y_delta);
00921 
00922     
00923 
00924     //MOVINGTEST
00925     if(moveOn) 
00926       {
00927         updateContents();
00928         moveOn=FALSE;
00929       }    
00930     //END MOVINGTEST
00931 
00932     moving = false;
00933   }
00934   else { //not moving
00935     
00936     bool ctrlclick = Qt::ControlButton & e->state();
00937 
00938     if ( !ctrlclick && last_click_selected_read ) {
00939       clearSelected();
00940       select( last_selected_recno, true );
00941       last_click_changed_selection = true;
00942 
00943     }
00944 //     if ( last_click_changed_selection ) {
00945 //       updateContents();
00946 //     }
00947     
00948 
00949     if ( rubber_band != 0 ) {
00950       
00951       readsInRect = new ReadsInRect( doc );
00952       
00953       TR_DNA x_dna, y_dna, w_dna, h_dna, x2_dna, y2_dna;
00954       TR_PIX x_pix, y_pix, w_pix, h_pix;
00955       
00956       QRect norm = rubber_band->normalize();
00957       //RUBBERTEST
00958       RubberStart = viewportToContents( RubberStart );
00959       RubberEnd = viewportToContents( RubberEnd );
00960       
00961       norm = QRect(
00962                 RubberStart.x(),
00963                 RubberStart.y(),
00964                 RubberEnd.x()-RubberStart.x(),
00965                 RubberEnd.y()-RubberStart.y()
00966                 ).normalize();
00967       //END RUBBERTEST
00968 
00969       rubber_band->setTopLeft( norm.topLeft() );      
00970       rubber_band->setBottomRight( norm.bottomRight() );      
00971 
00972       rubber_band->rect( &x_pix, &y_pix, &w_pix, &h_pix);
00973       convertToDnaCoordinates( x_dna, y_dna, x_pix, y_pix );
00974       convertToDnaCoordinates( x2_dna, y2_dna, x_pix + w_pix, y_pix + h_pix);
00975       
00976       w_dna = x2_dna - x_dna;
00977       h_dna = y2_dna - y_dna;
00978 
00979 
00980       readsInRect->setWindowCoord( x_dna, y_dna,  w_dna,h_dna );
00981       if ( !ctrlclick) 
00982         clearSelected();
00983       
00984       for ( ReadData * r = readsInRect->first(); r; r = readsInRect->next() ) {
00985         last_click_changed_selection = true;//new 071203
00986         select( r->getRecno(), true);
00987       }
00988       //RUBBERTEST
00989       QPainter p(viewport());
00990       p.setPen(QColor(255,255,255));
00991       p.setRasterOp(NotROP);
00992       if(RubberOn) 
00993         {
00994           drawRubber(&p);
00995           RubberOn=FALSE;
00996         }
00997       else
00998         {
00999           RubberEnd=RubberStart;
01000         }
01001       //END RUBBERTEST
01002       
01003       delete rubber_band;
01004       rubber_band = 0;
01005       delete readsInRect;
01006 //       updateContents();
01007     }
01008 
01009   }
01010   if ( last_click_changed_selection ) {
01011     updateContents();
01012   }
01013 
01014   moving = false;
01015   dragging = false;
01016   last_click_changed_selection = false;
01017   last_click_selected_read = false;
01018   
01019 }
01020 
01021 void TrapperView::contentsContextMenuEvent( QContextMenuEvent * e )
01022 {
01023   if ( last_click_changed_selection ) {
01024     updateContents();
01025   }
01026   moving = false;
01027   dragging = false;
01028   last_click_selected_read = false;
01029   last_click_changed_selection = false;
01030   
01031   QPopupMenu* contextMenu = new QPopupMenu( this );
01032   Q_CHECK_PTR( contextMenu );
01033 //   QLabel *caption = new QLabel( "<font color=darkblue><u><b>"
01034 //                                 "Context Menu</b></u></font>", this );
01035 //   caption->setAlignment( Qt::AlignCenter );
01036 //   contextMenu->insertItem( caption );
01037   
01038 
01039   
01040 
01041   //Algo stuff
01042   algoMenu = new QPopupMenu( this );
01043   Q_CHECK_PTR( algoMenu );
01044   list<string> algos = AlgoMaker::algosRegistered();
01045   list<string>::iterator stIt;
01046   
01047   for (stIt = algos.begin() ; stIt != algos.end(); ++stIt )
01048     {
01049       algoMenu->insertItem (  stIt->c_str()  );
01050     }
01051   connect( algoMenu, SIGNAL( activated( int ) ),
01052            this, SLOT( slotStartAlgo( int ) ) );
01053   contextMenu->insertItem( "&Operations", algoMenu );
01054   
01055 
01056 
01057   //Info stuff
01058   infoMenu = new QPopupMenu(this);
01059 
01060   vector<list<string> > infos = getInfo( e->pos() );
01061   QPtrList<QPopupMenu> infolist;
01062   infolist.setAutoDelete( true );
01063   
01064   for( size_t i = 0; i < infos.size(); i++ ) {
01065     stIt = infos[i].begin();
01066     if ( stIt == infos[i].end() ) continue;
01067     infolist.append(new InfoPopup(this));
01068     ++stIt;
01069 
01070     for ( ; stIt != infos[i].end(); ++stIt ) {
01071 //       infoMenu->insertItem (  stIt->c_str()  );
01072 
01073       infolist.last()->insertItem (  stIt->c_str()  );
01074     }
01075 
01076     
01077     infoMenu->insertItem(infos[i].begin()->c_str(), infolist.last());
01078   }
01079 
01080   //Info is copied to clipboard through InfoPopup class
01081 
01082   contextMenu->insertItem( "&Info", infoMenu );
01083 
01084 
01085   //Viewmode stuff
01086   switchViewMenu = new QPopupMenu( this );
01087   Q_CHECK_PTR( switchViewMenu );
01088   TrapperConf * conf = TrapperConf::instance();
01089   QStringList names = conf->viewModeNames();
01090   
01091   QStringList::Iterator it = names.begin();
01092   for ( ; it != names.end(); ++it )
01093     {
01094       switchViewMenu->insertItem ( *it );
01095     }
01096   connect( switchViewMenu, SIGNAL( activated( int ) ),
01097            this, SLOT( slotSwitchToMode( int ) ) );
01098   contextMenu->insertItem( "&Switch to viewmode", switchViewMenu );
01099 
01100 
01101   contextMenu->insertSeparator();
01102   contextSelectMenu = new QPopupMenu( this );
01103   Q_CHECK_PTR( contextSelectMenu );
01104   
01105   contextSelectMenu->insertItem("above");
01106   contextSelectMenu->insertItem("below");
01107   contextSelectMenu->insertItem("left");
01108   contextSelectMenu->insertItem("right");
01109   connect( contextSelectMenu, SIGNAL( activated( int ) ),
01110            this, SLOT( slotContextSelect( int ) ) );
01111   contextMenu->insertItem( "&Select all", contextSelectMenu );
01112   
01113 
01114 //   contextMenu->insertSeparator();
01115 //   contextMenu->insertItem("Set chromat center", this, SLOT(slotSetCenter()));
01116 //   contextMenu->insertItem("Clear chromat center", this, SLOT(slotClearCenter()));
01117 
01118   contextMenu->insertSeparator();
01119   contextMenu->insertItem("Scroll Here", this, SLOT(slotScrollToMouse()) );
01120   contextMenu->insertItem("Scroll to pos", this, SLOT(slotScrollToPos()) );
01121 
01122   contextMenu->exec( QCursor::pos() );
01123   delete contextMenu;
01124   delete switchViewMenu;//Previous memory leak??
01125   delete algoMenu;
01126   delete infoMenu;
01127   delete contextSelectMenu;
01128 }
01129 
01130 void TrapperView::slotSwitchToMode( int i )
01131 {
01132     QString viewMode =  switchViewMenu->text(i);
01133     viewModes->setMode( viewMode );
01134     doc->changedViewList();
01135     updateContents();
01136 }
01137 
01138 void TrapperView::slotStartAlgo( int i )
01139 {
01140   QString algoStr =  algoMenu->text(i);
01141   
01142   /* Right now the Algo constructor takes a list of db_recno_t.
01143      We create such a list from the keys in the map, selectedReads.
01144      
01145      Todo: To make the code prettier: is it be possible to
01146      pass the map iterators to the constructor of the list?
01147      Instead of our manual forloop.
01148   */
01149   
01150   
01151   //     std::list< db_recno_t > alist = getSelectedReads();
01152   //     Algo * algo = AlgoMaker::newAlgo( algoStr.ascii(), doc , alist );
01153   //     doc->addAlgorithm( algo );
01154   //     algo->start();
01155   //     doc->removeAlgorithm( algo );//POSSIBLE MEMORY LEAK!!!!!!!!!
01156   //     updateContents();
01157   
01158   ViewParam param(this);
01159 
01160   updateContents();
01161   runAlgo( algoStr.ascii(), getSelectedReads(), &param );
01162   //To be on the safe side...
01163   clearLastMove();
01164 }
01165 
01166 
01167 void TrapperView::slotScrollToMouse()
01168 {
01169   scrollTo(mousePressedPoint.x(), mousePressedPoint.y());
01170 
01171 }
01172 
01173 void TrapperView::slotScrollToPos()
01174 {
01175   bool ok;
01176   int res = QInputDialog::getInteger(
01177                                      "Scroll to position", "Enter row:", 0, 0, numeric_limits<int>::max(), 1,
01178                                      &ok, 0 );
01179   
01180   if ( ok ) {
01181     // user entered something and pressed OK
01182   } else {
01183     // user pressed Cancel
01184     return;
01185   }
01186   TR_PIX y = dnaCoordToPixel_Y(res);
01187 
01188   res = QInputDialog::getInteger(
01189                                  "Scroll to position", "Enter column:", 0, 0, numeric_limits<int>::max(), 1,
01190                                  &ok, 0 );
01191   
01192   if ( ok ) {
01193     // user entered something and pressed OK
01194   } else {
01195     // user pressed Cancel
01196     return;
01197   }
01198 
01199   TR_PIX x = dnaCoordToPixel_X(res);
01200   
01201   scrollTo(x, y);
01202 
01203 }
01204 
01205 void TrapperView::slotSetCenter()
01206 {
01207   center_point = mousePressedCol();
01208 //   cerr<<center_point<<endl;
01209   updateContents();
01210 }
01211 
01212 void TrapperView::slotClearCenter()
01213 {
01214   center_point = 0;
01215   updateContents();
01216 }
01217 
01218 void TrapperView::slotContextSelect(int i)
01219 {
01220   QString direction =  contextSelectMenu->text(i);
01221   int start, stop;
01222 
01223   if ( direction == "above" || direction == "below") {
01224     if ( direction == "above" ){
01225       start = 0;
01226       stop = mousePressedRow();
01227     }
01228     else {
01229       start = mousePressedRow();
01230       stop = globalRows;
01231     }
01232     selectRows(start, stop);
01233   }
01234   else {
01235     assert(direction == "left" || direction == "right");
01236     if ( direction == "left" ){
01237       start = 0;
01238       stop = mousePressedCol();
01239     }
01240     else {
01241       start = mousePressedCol();
01242       stop = globalBases;
01243     }
01244     selectCols(start, stop);
01245   }
01246   
01247 
01248 }
01249 
01250 void TrapperView::findRead()
01251 {
01252   bool ok;
01253   QString res = QInputDialog::getText ( "Find read", "Enter read name:", QLineEdit::Normal, QString::null, &ok );
01254   
01255 
01256   if ( ok ) {
01257     // user entered something and pressed OK
01258   } else {
01259     // user pressed Cancel
01260     return;
01261   }
01262 
01263   Database::SecondaryIterator<ReadMetaData> name_it( "name", doc, "ReadMetaData" );
01264   name_it.key()->setName( res );
01265   if ( name_it.setRange() != 0 ) {
01266     cerr<<"Error, couldn't find "<<res<<" in db"<<endl;
01267     return;
01268   }
01269   clearSelected();
01270 
01271   do {
01272     select(name_it.answer()->readRecno(), true);
01273   } while ( name_it.next() == 0 && name_it.answer()->name().find(res.ascii()) < name_it.answer()->name().size() );
01274 //   } while ( name_it.next() == 0 && name_it.answer()->name() == res );
01275   
01276   updateContents();
01277   
01278 
01279 //   TR_PIX y = dnaCoordToPixel_Y(name_it.answer()->row());
01280 //   TR_PIX x = dnaCoordToPixel_X(name_it.answer()->startPos());
01281 //   scrollTo(x, y);
01282 
01283 }
01284 
01285 void TrapperView::findTag()
01286 {
01287   bool ok;
01288   QString res = QInputDialog::getText ( "Find tag", "Enter tag name:", QLineEdit::Normal, QString::null, &ok );
01289   
01290 
01291   if ( ok ) {
01292     // user entered something and pressed OK
01293   } else {
01294     // user pressed Cancel
01295     return;
01296   }
01297 
01298   Database::SecondaryIterator<TagData> info_it( "info", doc, "TagData" );
01299   info_it.key()->setInfo( res );
01300   if ( info_it.setRange() != 0 ) {
01301     cerr<<"Error, couldn't find "<<res<<" in db"<<endl;
01302     return;
01303   }
01304   clearSelected();
01305 
01306   do {
01307     select(info_it.answer()->readRecno(), true);
01308   } while ( info_it.next() == 0 && info_it.answer()->getInfo().find(res.ascii()) < info_it.answer()->getInfo().size() );
01309 //   } while ( name_it.next() == 0 && name_it.answer()->name() == res );
01310   
01311   updateContents();
01312   
01313 
01314 //   TR_PIX y = dnaCoordToPixel_Y(name_it.answer()->row());
01315 //   TR_PIX x = dnaCoordToPixel_X(name_it.answer()->startPos());
01316 //   scrollTo(x, y);
01317 
01318 }
01319 
01320 
01321 std::set<db_recno_t>& TrapperView::getSelectedReads()
01322 {
01323   return selectedReads;
01324 }
01325 
01326 void TrapperView::select( db_recno_t recno, bool status )
01327 {
01328   RecnoMap::iterator pos;
01329   if ( status == true && !isSelected(recno) ) {
01330     selectedReads.insert( recno );
01331     clearLastMove();
01332   }
01333   else if ( ( pos = selectedReads.find( recno )) != selectedReads.end() ) {
01334     selectedReads.erase( pos );
01335     clearLastMove();
01336   }
01337   
01338 }
01339 
01340 bool TrapperView::isSelected( db_recno_t recno )
01341 {
01342   return selectedReads.find( recno ) != selectedReads.end();
01343 }
01344 
01345 void TrapperView::clearSelected()
01346 {
01347   selectedReads.clear();
01348   clearLastMove();
01349 }
01350 
01351 std::vector<std::list<std::string > > TrapperView::getInfo( const QPoint& pos )
01352 {
01353   vector<list<string> > result;
01354   list<string> readResult;
01355   list<string> featResult;
01356   list<string> generalResult;
01357   
01358   //Recalc pos
01359   TR_DNA row = pixelCoordToDna_Y( pos.y() );
01360   TR_DNA col = pixelCoordToDna_X( pos.x() );
01361 
01362   readsInRect = new ReadsInRect( doc );
01363   readsInRect->setWindowCoord( col, row, 1, 1 );  /* a rectangle with dimension 1x1 */
01364 //   readsInRect->setWindowCoord( col, row, 3, 3 );  /* a rectangle with dimension 3x3 */
01365   ReadData * r = readsInRect->first();
01366 
01367   ostringstream os;
01368   if ( r ) {
01369     Database::SecondaryIterator<ReadMetaData> read_m_it( "readRecno", doc, "ReadMetaData" );
01370     
01371     read_m_it.key()->setReadRecno( r->getRecno() );
01372     
01373     assert(read_m_it.set() == 0);
01374 
01375 
01376     list<string> types = GeneralMaker::listRegistered();
01377     readResult.push_back( "Read info" );
01378     readResult.push_back( read_m_it.answer()->name() );
01379     
01380     os<<"TC:";
01381     for( size_t i = 0; i < read_m_it.answer()->tc_vec.stlVector().size(); i++ ) {
01382       os<<' '<<read_m_it.answer()->tc_vec.stlVector()[i];
01383     }
01384     readResult.push_back( os.str() );
01385 
01386     os.str("");
01387     os<<"Strand: "<<read_m_it.answer()->strand();
01388     readResult.push_back( os.str() );
01389     os.str("");
01390     os<<"Mate: "<<read_m_it.answer()->mate() << ' ' << read_m_it.answer()->mateLength();
01391     readResult.push_back( os.str() );
01392     os.str("");
01393     os<<"Begin good: "<<read_m_it.answer()->beginGood();
01394     readResult.push_back( os.str() );
01395     os.str("");
01396     os<<"End good: "<<read_m_it.answer()->endGood();
01397     readResult.push_back( os.str() );
01398     os.str("");
01399     os<<"Read index: "<<col - r->startPos();
01400     readResult.push_back( os.str() );
01401     
01402 
01403     featResult.push_back( "Feature info" );
01404     
01405     //Feature stuff
01406     for( list<string>::iterator it = types.begin(); it != types.end(); ++it ) {
01407       GeneralData * data = GeneralMaker::newData( *it );
01408       SpatialFeatureData * fdata = dynamic_cast<SpatialFeatureData *>( data );
01409       // fdata is just used to see that the registered string is corresponding to
01410       // a feature
01411       if ( fdata ) {
01412         Database::SecondaryIterator<SpatialFeatureData> featIt( "readRecno", doc, it->c_str() );
01413 
01414         featIt.key()->setReadRecno( r->getRecno() );
01415         
01416         string featInfo;
01417         
01418         if ( featIt.set() == 0 ) {
01419 
01420           int ret;
01421           do {
01422             
01423             featInfo = featIt.answer()->info()->getPosInfo( col - r->startPos() );
01424             if ( !featInfo.empty() ) {
01425               featResult.push_back( featInfo );
01426             }
01427             featInfo = featIt.answer()->info()->getRangeInfo( 0, r->endPos() - r->startPos() );
01428             if ( !featInfo.empty() ) {
01429               readResult.push_back( featInfo );
01430             }
01431             
01432             
01433           } while ( (ret = featIt.nextdup())  == 0);
01434         }
01435       }
01436       
01437       delete data;
01438       
01439     }
01440 
01441 
01442     
01443   }
01444   generalResult.push_back("General info");
01445   os.str("");
01446   os<<"Row: "<<row<<", Col: "<<col;
01447   generalResult.push_back( os.str() );
01448   
01449   result.push_back(readResult);
01450   result.push_back(featResult);
01451   result.push_back(generalResult);
01452   
01453   delete readsInRect;
01454   return result;
01455 }
01456 
01457 void TrapperView::runAlgo( const std::string& AlgoType, std::set< db_recno_t >& recnoList, AlgoParam* param )
01458 {
01459   
01460   if (selectedReads.size() > 0 ) {
01461     
01462     Algo * algo = AlgoMaker::newAlgo( AlgoType, doc , recnoList, param );
01463     doc->addAlgorithm( algo );
01464     algo->start();
01465     doc->removeAlgorithm( algo );//POSSIBLE MEMORY LEAK!!!!!!!!!
01466     delete algo;//To avoid memory leak...
01467     
01468     updateContents();
01469     fitContentsizeToData();
01470   }
01471   
01472 }
01473 
01474 void TrapperView::zoomIn()
01475 {
01476   zoomInX();
01477   zoomInY();
01478 }
01479 
01480 void TrapperView::zoomInX()
01481 {
01482   if ( magnifyX >= 128 ) {
01483     return;
01484   }
01485   
01486   
01487   magnifyX *= zoomfactor;
01488   if ( static_cast<int>(globalBases * magnifyX * basewidth) < 0 ) {
01489     magnifyX /= zoomfactor;
01490     return;
01491   }
01492   
01493 
01494   
01495 //   QPoint p = viewportToContents(viewport()->rect().topLeft());
01496   QPoint p = viewportToContents(viewport()->rect().topLeft()) + QPoint(visibleWidth()/2, 0);
01497 
01498   resizeContents(static_cast<int>(globalBases * magnifyX * basewidth), globalRows * rowheight * magnifyY);
01499 //   setContentsPos(p.x()*zoomfactor, p.y());
01500   setContentsPos(p.x()*zoomfactor - visibleWidth()/2, p.y());
01501 
01502 //   updateContents();
01503 
01504 }
01505 
01506 void TrapperView::zoomInY()
01507 {
01508   if ( magnifyY >= 8 )
01509     return;
01510   magnifyY *= zoomfactor;
01511 //   doZoom();
01512 
01513   QPoint p = viewportToContents(viewport()->rect().topLeft());
01514   
01515   resizeContents(static_cast<int>(globalBases * magnifyX * basewidth), globalRows * rowheight * magnifyY);
01516   setContentsPos(p.x(), p.y()*zoomfactor);
01517 
01518   updateContents();
01519 }
01520 
01521 void TrapperView::zoomOut()
01522 {
01523   zoomOutX();
01524   zoomOutY();
01525 }
01526 
01527 void TrapperView::zoomOutX()
01528 {
01529 
01530 //   if ( magnifyX <= 0.25 ) {
01531 //   if ( magnifyX <= 0.0625 ) {
01532 //   if ( magnifyX <= 0.015625 ) {
01533 //   if ( magnifyX <= 0.0078125 ) {
01534 //   if ( magnifyX <= 0.00390625 ) {
01535 //   if ( magnifyX <= 0.0009765625 ) {
01536 //   if ( magnifyX <= 0.000244140625 ) {
01537 //   if ( magnifyX <= 6.103515625e-05 ) {
01538 //   if ( magnifyX <= 1.52587890625e-05 ) {
01539   if ( magnifyX <= 7.62939453125e-06 ) {
01540     return;
01541   }
01542   magnifyX /= zoomfactor;
01543 
01544 
01545   QPoint p = viewportToContents(viewport()->rect().topLeft()) + QPoint(visibleWidth()/2, 0);
01546 
01547 //   if ( globalBases * magnifyX * basewidth < 1 ) {
01548 //     cerr<<"globalBases: "<<globalBases<<endl;
01549 //     cerr<<"globalBases * magnifyX * basewidth: "<<globalBases * magnifyX * basewidth<<endl;
01550 //   }
01551   resizeContents(static_cast<int>(globalBases * magnifyX * basewidth), globalRows * rowheight * magnifyY);
01552   setContentsPos(p.x()/zoomfactor - visibleWidth()/2, p.y());
01553 
01554   updateContents();
01555 }
01556 
01557 void TrapperView::zoomOutY()
01558 {
01559   if ( magnifyY <= 1 )
01560     {
01561       return;
01562     }
01563   magnifyY /= zoomfactor;
01564 //   doZoom();
01565 
01566   QPoint p = viewportToContents(viewport()->rect().topLeft());
01567   resizeContents(static_cast<int>(globalBases * magnifyX * basewidth), globalRows * rowheight * magnifyY);
01568   setContentsPos(p.x(), p.y()/zoomfactor);
01569 
01570   updateContents();
01571 }
01572 
01573 void TrapperView::doZoom()
01574 {
01575 //   QPoint p = viewportToContents(viewport()->rect().topLeft());
01576 
01577 //   if ( globalBases * magnifyX * basewidth < 1 ) {
01578 //     cerr<<"globalBases: "<<globalBases<<endl;
01579 //     cerr<<"globalBases * magnifyX * basewidth: "<<globalBases * magnifyX * basewidth<<endl;
01580 //   }
01581   resizeContents(static_cast<int>(globalBases * magnifyX * basewidth), globalRows * rowheight * magnifyY);
01582   //     QPoint p = viewportToContents(viewport()->rect().center());
01583   //     center( p.x()* factor , p.y()*factor );
01584 //   setContentsPos(p.x()*zoomfactor, p.y()*zoomfactor);
01585 //   setContentsPos(p.x(), p.y());
01586   updateContents();
01587   
01588 }
01589 
01590 void TrapperView::scrollTo(TR_PIX x, TR_PIX y)
01591 {
01592   setContentsPos( x, y );
01593 //   updateContents();
01594   
01595 }
01596 
01597 
01598 void TrapperView::enlarge()
01599 {
01600   globalRows *= 2;
01601   globalBases = static_cast<int32_t>(globalBases * 1.25);
01602   resizeContents(static_cast<int>(globalBases * magnifyX * basewidth), globalRows * rowheight * magnifyY);
01603   updateContents();
01604 }
01605 
01606 void TrapperView::shrink()
01607 {
01608   globalRows = static_cast<int32_t>(globalRows * 0.5);
01609   globalBases = static_cast<int32_t>(globalBases * 0.8);
01610   resizeContents(static_cast<int>(globalBases * magnifyX * basewidth), globalRows * rowheight * magnifyY);
01611   updateContents();
01612 }
01613 
01614 
01615 void TrapperView::selectAll()
01616 {
01617   clearSelected();
01618   Database::PrimaryIterator<ReadData> iter( doc, "ReadData" );
01619   
01620   if ( iter.first() == 0 ) {
01621   
01622     do {
01623       select( iter.answer()->getRecno(), true );
01624       
01625     } while ( iter.next() == 0 );
01626     
01627   }
01628   updateContents();
01629 
01630 }
01631 
01632 void TrapperView::selectBetween()
01633 {
01634   bool ok;
01635   TR_DNA start, stop;
01636   int res = QInputDialog::getInteger("Select between rows", "Enter start row for selected reads:", 0, 1, numeric_limits<int>::max(), 1,
01637                                      &ok, 0 );
01638   if ( ok ) {
01639     start = res;
01640   }
01641   else {
01642     return;
01643   }
01644   
01645   res = QInputDialog::getInteger("Select between rows", 
01646                                  "Enter stop row for selected reads:", 
01647                                  0, 1, numeric_limits<int>::max(), 1,
01648                                  &ok, 0 );
01649   if ( ok ) {
01650     stop = res;
01651     if ( start > stop ) {
01652       TR_DNA tmp = start;
01653       start = stop;
01654       stop = tmp;
01655     }
01656   }
01657   else {
01658     return;
01659   }
01660   selectRows(start, stop);
01661 
01662 }
01663 
01664 void TrapperView::selectRows(int start, int stop)
01665 {
01666   if ( !ctrl )
01667     clearSelected();
01668 
01669   Database::SecondaryIterator<ReadData> row_it( "pos", doc, "ReadData" );
01670   row_it.key()->setRow(start);
01671   row_it.key()->setStartPos(0);
01672   
01673   if ( row_it.setRange() != 0 ) {
01674 
01675     return;
01676   }
01677   
01678   do {
01679     select( row_it.answer()->getRecno(), true );
01680   }while( row_it.next() == 0 && row_it.answer()->row() <= stop );
01681 
01682   updateContents();
01683   
01684 }
01685 
01686 
01687 void TrapperView::selectBetweenCols()
01688 {
01689   bool ok;
01690   TR_DNA start, stop;
01691   int res = QInputDialog::getInteger("Select between cols", "Enter start col for selected reads:", 0, 1, numeric_limits<int>::max(), 1,
01692                                      &ok, 0 );
01693   if ( ok ) {
01694     start = res;
01695   }
01696   else {
01697     return;
01698   }
01699   
01700   res = QInputDialog::getInteger("Select between cols", 
01701                                  "Enter stop col for selected reads:", 
01702                                  0, 1, numeric_limits<int>::max(), 1,
01703                                  &ok, 0 );
01704   if ( ok ) {
01705     stop = res;
01706     if ( start > stop ) {
01707       TR_DNA tmp = start;
01708       start = stop;
01709       stop = tmp;
01710     }
01711   }
01712   else {
01713     return;
01714   }
01715 
01716   selectCols(start, stop);
01717 }
01718 
01719 void TrapperView::selectCols(int start, int stop)
01720 {
01721   if ( !ctrl )
01722     clearSelected();
01723 
01724   Database::SecondaryIterator<ReadData> row_it( "end", doc, "ReadData" );
01725   row_it.key()->setRow(0);
01726   row_it.key()->setEndPos(start);
01727   
01728   if ( row_it.setRange() != 0 ) {
01729 
01730     return;
01731   }
01732   
01733   do {
01734     if ( row_it.answer()->startPos() >= start ) {
01735       select( row_it.answer()->getRecno(), true );
01736     }
01737   }while( row_it.next() == 0 && row_it.answer()->endPos() <= stop );
01738 
01739   updateContents();
01740   
01741 }
01742 
01743 /* todo: check this: maybe unused */
01744 void TrapperView::contentsDragEnterEvent(QDragEnterEvent* event)
01745 {
01746   event->accept( TRUE );
01747 }
01748 
01749 void TrapperView::contentsDragMoveEvent ( QDragMoveEvent* e )
01750 {
01751   
01752 //   e->setPoint( QPoint( mousePressedPoint.x(), e->pos().y() ) );
01753 
01754 //   cerr << "in TrapperView::dragMoveEvent" << endl;  
01755 //   cerr<<"x(): "<<e->pos().x()<<endl;
01756 //   cerr<<"y(): "<<e->pos().y()<<endl;
01757  
01758 }
01759 
01760 void TrapperView::contentsDropEvent(QDropEvent* event)
01761 {
01762 //   cerr << "in TrapperView::dropEvent" << endl;
01763 
01764  QPoint deltaMovement = event->pos() - mousePressedPoint;
01765  TR_DNA x_dna_movDelta;
01766  TR_DNA y_dna_movDelta;
01767 
01768  convertToDnaCoordinates( x_dna_movDelta, y_dna_movDelta, deltaMovement.x(), deltaMovement.y() );
01769 //  cerr << "dropped happened with delta x=" << x_dna_movDelta << " y=" << y_dna_movDelta << endl; 
01770  
01771  TrapperView* w = dynamic_cast<TrapperView*>( event->source() );
01772 
01773  if ( !w) {
01774    //Drop from another app...
01775    return;
01776  }
01777  
01778 
01779  assert(w);
01780  
01781  if ( w->getDocument() == this->getDocument() ) {
01782 
01783    moveData( deltaMovement.x(), deltaMovement.y() );
01784  }
01785  else {
01786    QByteArray ar( event->encodedData("min_mime_type") );
01787    QDataStream data_stream(ar, IO_ReadOnly);
01788    
01789    readSelected(data_stream);
01790    updateContents();
01791  }
01792  
01793 
01794 }
01795 
01796 void TrapperView::writeSelected(QDataStream& data_stream)
01797 {
01798   //Write to stream
01799 
01800   
01801   //Get registered types
01802   
01803   list<string> type_list = GeneralMaker::listRegistered();
01804   
01805   
01806   //Loop over selected reads
01807   for( set<db_recno_t>::iterator recno_it = selectedReads.begin(); recno_it != selectedReads.end(); ++recno_it ) {
01808     //Get recno
01809     db_recno_t recno(*recno_it);
01810     
01811     //Create primary iterator for ReadData with new
01812     Database::PrimaryIterator<ReadData>* read_it = new Database::PrimaryIterator<ReadData>(doc, "ReadData");
01813     
01814     //Set iterator from recno
01815     read_it->setFromRecno(recno);
01816     
01817     //Write dataname to stream - null terminated, right?? Must check size stuff...
01818     data_stream<<"ReadData";
01819     
01820     //write ReadData to stream using writeStream
01821     read_it->answer()->writeStream(data_stream);
01822     
01823     //Delete primary readiterator
01824     delete read_it;
01825     
01826     //Loop over types
01827     for( list<string>::iterator type_it = type_list.begin(); type_it != type_list.end(); ++type_it ) {
01828       
01829       GeneralData * data = GeneralMaker::newData( *type_it );
01830       FeatureData * fdata = dynamic_cast<FeatureData *>( data );
01831       // fdata is just used to see that the registered string is corresponding to
01832       // a feature
01833       if ( fdata ) {/* Can cast type to feature */
01834         //Create secondary feature iterator
01835         Database::SecondaryIterator<FeatureData> featIt( "readRecno", doc, type_it->c_str() );
01836         
01837         //Set iterator key read recno
01838         featIt.key()->setReadRecno( recno );
01839         
01840         if ( featIt.set() == 0 ) {//Read has such feature
01841           int ret;
01842           do {
01843             
01844             //write feat name to stream
01845             data_stream<<type_it->c_str();
01846             
01847             //write FeatureData to stream using writeStream
01848             featIt.answer()->writeStream(data_stream);
01849             
01850           } while ((ret = featIt.nextdup())== 0);
01851           
01852         }
01853         
01854       }
01855       
01856       delete data;
01857       
01858     }
01859     
01860   }
01861   
01862 }
01863 
01864 void TrapperView::readSelected(QDataStream& data_stream)
01865 {
01866   //Read from stream
01867   clearSelected();
01868   
01869   db_recno_t recno(0);
01870 
01871   //Keep track of lowest row and start pos, and transpose the pasted reads there
01872 
01873   TR_DNA rowmin(numeric_limits<TR_DNA>::max());
01874   TR_DNA colmin(numeric_limits<TR_DNA>::max());
01875 
01876   while ( !data_stream.atEnd() ) {
01877     
01878     //Read data type
01879     char* data_type;
01880     
01881     data_stream>>data_type;//must delete this myself according to Qt docs
01882     
01883     string type(data_type);
01884     
01885     //Create Creator for general data with Data type name to constructor
01886     Database::Creator<GeneralData> a_creator(doc, type);
01887     
01888     //Read stream using readStream on Creators data() pointer
01889     a_creator.data()->readStream(data_stream);
01890     
01891     if ( ReadData* data = dynamic_cast<ReadData*>(a_creator.data())) {/* type is ReadData*/
01892       
01893       //Creator::create(false) and save read recno
01894       recno = a_creator.create(false);
01895       select(recno, true);
01896       if ( data->row() < rowmin ) {
01897         rowmin = data->row();
01898       }
01899       if ( data->startPos() < colmin ) {
01900         colmin = data->startPos();
01901       }
01902       
01903     }
01904     else {
01905       //Type is feature, but let's do a sanity check
01906       FeatureData* data = dynamic_cast<FeatureData*>(a_creator.data());
01907       assert( data  );
01908       assert( recno != 0 );
01909       
01910       //Set feature's read recno to saved recno
01911       data->setReadRecno(recno);
01912       
01913       //Creator::create()
01914       a_creator.create(false);
01915     }
01916     
01917     delete data_type;
01918   }
01919   fitContentsizeToData();
01920   moveData( -dnaCoordToPixel_X(colmin - 1), -dnaCoordToPixel_Y(rowmin - 1) );
01921   clearLastMove();
01922 }
01923 
01924 void TrapperView::setDragMode(bool status)
01925 {
01926   allow_dragging = status;
01927 }
01928 
01929 void TrapperView::copy()
01930 {
01931   QByteArray ar;
01932   QDataStream str(ar, IO_WriteOnly);
01933   
01934   writeSelected(str);
01935   QClipboard* cb = QApplication::clipboard();
01936   ReadDrag* r = new ReadDrag(this);
01937   r->setEncodedData(ar);
01938   cb->setData(r, QClipboard::Clipboard);
01939   
01940 }
01941 
01942 void TrapperView::paste()
01943 {
01944   
01945   QClipboard* cb = QApplication::clipboard();
01946   QMimeSource* r = cb->data(QClipboard::Clipboard);
01947 
01948   QByteArray ar(r->encodedData("min_mime_type"));
01949   QDataStream str(ar, IO_ReadOnly);
01950   
01951   readSelected(str);
01952   updateContents();
01953 }
01954 
01955 void TrapperView::cut()
01956 {
01957   copy();
01958   Destroyer d(doc);
01959   for( set<db_recno_t>::iterator it = selectedReads.begin(); it != selectedReads.end(); ++it ) {
01960     d.destroy(*it);
01961   }
01962   clearSelected();
01963   updateContents();
01964   
01965 }
01966 
01967 void TrapperView::undo()
01968 {
01969   moveData( -dnaCoordToPixel_X(last_move_x), -dnaCoordToPixel_Y(last_move_y) );
01970 }
01971 
01972 TR_DNA TrapperView::mousePressedRow()
01973 {
01974   return pixelCoordToDna_Y( mousePressedPoint.y() );
01975   
01976   
01977 }
01978 
01979 TR_DNA TrapperView::mousePressedCol()
01980 {
01981   return pixelCoordToDna_X( mousePressedPoint.x() );
01982   
01983 }
01984 
01985 void TrapperView::sendMsg( const QString& msg)
01986 {
01987   emit message(msg);
01988 }
01989 
01990 void TrapperView::setViewTimeCourse(bool toggle)
01991 {
01992   if ( time_course != toggle) {
01993     updateContents();
01994   }
01995   time_course = toggle;
01996 }
01997 
01998 void TrapperView::setNormalizeTimeCourse(bool toggle)
01999 {
02000   if ( tc_normalize != toggle) {
02001     updateContents();
02002   }
02003   tc_normalize = toggle;
02004 }
02005 
02006 void TrapperView::scrollToNextCluster(bool forward)
02007 {
02008 
02009 
02010   Database::SecondaryIterator<ReadData> start_it( "start", doc, "ReadData" );
02011 
02012   TR_DNA start;
02013   if ( forward ) {
02014     start = pixelCoordToDna_X( contentsX() + visibleWidth()*3/5 ) + 1;
02015   }
02016   else {
02017     start = pixelCoordToDna_X( contentsX() + visibleWidth()*2/5 );
02018   }
02019 
02020   while( true ) {
02021     
02022     start_it.key()->setStartPos( start );
02023     
02024 
02025     if ( forward ) {
02026       if ( start_it.setRange() != 0 ){
02027         
02028         return;
02029       }
02030       
02031     }
02032     else {
02033       if (start_it.setRange() == 0) {
02034         if ( start_it.prev() != 0 ) {
02035           return;
02036         }
02037       }
02038       else {
02039         if (start_it.last() != 0){
02040           
02041         }
02042       }
02043     }
02044     
02045     
02046     start = start_it.answer()->startPos();
02047     TR_DNA stop;
02048     if ( forward ) {
02049       stop = start + read_cluster_window;
02050     }
02051     else {
02052       stop = start - read_cluster_window;
02053     }
02054     
02055   
02056     size_t num_in_win(0);
02057     
02058     do {
02059       num_in_win++;
02060 
02061     }while( ( (forward && start_it.next() == 0) || (!forward && start_it.prev() == 0) ) && 
02062             ( (forward && start_it.answer()->startPos() < stop) || (!forward && start_it.answer()->startPos() > stop) ) && 
02063             num_in_win < read_cluster_min_num );
02064     
02065     if ( num_in_win == read_cluster_min_num ) {
02066       //Found a cluster
02067       scrollTo( dnaCoordToPixel_X(start) - visibleWidth()/2, contentsY() );
02068       
02069       return;
02070     }
02071     else if ( forward && start_it.answer()->startPos() >= stop ) {
02072       start++;
02073     }
02074     else if ( !forward && start_it.answer()->startPos() <= stop ) {
02075       start--;
02076     }
02077     else {
02078       return;
02079     }
02080     
02081     
02082   }
02083   
02084   
02085 
02086 }
02087 
02088 void TrapperView::setClusterWindow(int window_size)
02089 {
02090   read_cluster_window = window_size;
02091 }
02092 
02093 
02094 void TrapperView::setClusterMinNum(int num)
02095 {
02096   read_cluster_min_num = num;
02097 }

Generated on Fri Jul 17 20:19:29 2009 for ngsview by  doxygen 1.5.1