00001 /******************************************************************************* 00002 * * 00003 * Copyright (C) 2003 Erik Sjolund, (<html>Erik Sjö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 00016 #ifndef TRAPPER2VIEW_H 00017 #define TRAPPER2VIEW_H 00018 00019 // include files for Qt 00020 #include <qpixmap.h> 00021 #include <qpainter.h> 00022 #include <qbitmap.h> 00023 #include <qwidget.h> 00024 #include <qscrollview.h> 00025 #include "trappertypes.h" 00026 #include <list> 00027 #include <db_cxx.h> 00028 #include "readdata.h" 00029 #include "algoparam.h"//NB, should maybe be removed 00030 #include "viewparam.h"//NB, should maybe be removed 00031 #include "readsinrect.h" 00032 #include <set> 00033 #include <map> 00034 #include <vector> 00035 00036 class QPopupMenu; 00037 class ViewModes; 00038 class TrapperDoc; 00039 class QLabel; 00040 class QString; 00041 #include "generaldata.h" 00042 //class GeneralData::SecondaryIterator; 00043 00044 #include <iostream> 00045 // using namespace std; 00046 00047 /** \brief This class gives an iterator interface to the reads that are visible inside a 00048 * specified window ( a rectangle ) in the dna coordinate system. 00049 * 00050 * The reads are indexed in a btree where the order of the records is: 00051 * higher row number is bigger, 00052 * and if the same row number: higher endPosition of the read is bigger. 00053 * 00054 * Sketch about the interior: 00055 * To find out the visible reads of a window this class starts the search 00056 * in the top left corner of the visible window and search for the next bigger 00057 * read. If the found read lies outside of the search window we do another search 00058 * from another row. We make use of the fact that berkeley db has a cursor 00059 * when we do the searching. So sometimes we just take the next bigger record 00060 * instead of doing a btree search. 00061 * 00062 * Important: This indexing and searching relies on the fact that the reads do not overlap. 00063 * Therefore you must be careful when adding a new read or moving an old read to see 00064 * that the space needed is not used by another read. 00065 */ 00066 00067 class ReadsInRect; 00068 00069 00070 /** @author Source Framework Automatically Generated by KDevelop, (c) The KDevelop Team. 00071 * @version KDevelop version 1.1 code generation 00072 */ 00073 00074 00075 /** \brief The view to graphically present the reads and their features. 00076 * The user will mainly interact with this window. 00077 * 00078 * Functionality given to the user: Scrolling, zooming, drag and drop of the reads to move them around, selecting 00079 * reads and start algorithms. 00080 * 00081 * This software is designed to have totally decoupled view and data classes. The view is stateless 00082 * ( it does not store any data ) and will for every update newly read in all data needed to paint up the view. 00083 * In other words, the view does not cash anything. 00084 * 00085 * This has some nice implications: 00086 * Data algorithm classes will work directly with the data classes and will 00087 * not be aware of any views. Any number of views can be opened up and they will be independent and will 00088 * not be aware of each other. 00089 * 00090 * For it to be possible to take this design approach the data classes must respond quickly to queries 00091 * because any delay here will make the views appear sluggish. Scrolling will here be the toughest test for 00092 * the speed of the data class queries. Because by scrolling, new data should be painted very fast to 00093 * the view. The user would not like big delays here. 00094 * 00095 * To make the data class queries very fast, the data is stored in the embedded database Berkeley Db. 00096 * 00097 * 00098 * About how the reads and features get shown in TrapperView: 00099 * TrapperView is inherited from QScrollView. QScrollView gives us the scroll bars and also gives convertion methods 00100 * between the coordinate system of the actual window ( the viewport ) and the coordinate system of the 00101 * content window ( the big window the user has to scroll to see all of it ). 00102 * QScrollView gives us the possibility to place out "static" widgets on the content window, and QScrollView would 00103 * then handle the scrolling automatically. But we would like a totally stateless view so we take another approach. 00104 * We reimplement the virtual method drawContents() that is called everytime some part of the window should be painted, 00105 * e.g. when the user has dragged the scrollbars. 00106 * The method drawContents() takes as arguments the "content" pixel coordinates of a rectangle to be painted. 00107 * Some background pixels are painted to enhance the "movement feeling" when scrolling. 00108 * Then drawContents_helper() is called ( which is also is reused when painting reads in a drag & drop ). 00109 * In drawContents_helper() we first convert to DNA coordinates, i.e. the x-axis unit is a nucleotid-base and the y-axis unit 00110 * is a row. We then use the class ReadsInRect that can tell us which reads are visible in our painting rectangle. 00111 * Now paintFeatures() is called for each read. In paintFeatures(), features for the read are painted in different layers inside the 00112 * read rectangle. 00113 */ 00114 00115 class TrapperView : public QScrollView 00116 { 00117 Q_OBJECT 00118 00119 friend class TrapperDoc; 00120 00121 public: 00122 /** Constructor for the view 00123 * @param pDoc your document instance that the view represents. Create a document before calling the constructor 00124 * or connect an already existing document to a new MDI child widget.*/ 00125 TrapperView(TrapperDoc* pDoc, QWidget* parent, const char *name, QString _viewMode = QString("everything") ); 00126 // TrapperView(TrapperDoc* pDoc, QWidget* parent, const char *name, QString _viewMode = QString("closeup") ); 00127 /** Destructor for the main view */ 00128 ~TrapperView(); 00129 /** returns a pointer to the document connected to the view*/ 00130 TrapperDoc *getDocument() const; 00131 /** gets called to redraw the document contents if it has been modified */ 00132 void update(TrapperView* pSender); 00133 /** contains the implementation for printing functionality and gets called by TrapperApp::slotFilePrint() */ 00134 void print(QPrinter *pPrinter); 00135 /** the name of the view mode that the TrapperView is using right now */ 00136 QString mode(); 00137 /** zooms in */ 00138 void zoomIn(); 00139 /** zooms in X-direction*/ 00140 void zoomInX(); 00141 /** zooms in Y-direction*/ 00142 void zoomInY(); 00143 /** zooms out */ 00144 void zoomOut(); 00145 /** zooms out X-dir*/ 00146 void zoomOutX(); 00147 /** zooms out Y-dir*/ 00148 void zoomOutY(); 00149 /** selects all */ 00150 void selectAll(); 00151 /** selects between rows */ 00152 void selectBetween(); 00153 /** selects between cols */ 00154 void selectBetweenCols(); 00155 /** selects between specified rows */ 00156 void selectRows(int start, int stop); 00157 /** selects between specified cols */ 00158 void selectCols(int start, int stop); 00159 /** finds a read */ 00160 void findRead(); 00161 /** finds a tag */ 00162 void findTag(); 00163 /** enlarges view*/ 00164 void enlarge(); 00165 /** shrinks view*/ 00166 void shrink(); 00167 /** sets pointer mode*/ 00168 void setDragMode(bool status); 00169 /** copies selected data*/ 00170 void copy(); 00171 /** pastes selected data*/ 00172 void paste(); 00173 /** cuts selected data*/ 00174 void cut(); 00175 /** undoes last move*/ 00176 void undo(); 00177 /** gets row position of last mouse press*/ 00178 TR_DNA mousePressedRow(); 00179 /** gets col position of last mouse press*/ 00180 TR_DNA mousePressedCol(); 00181 /** Sends out a message*/ 00182 void sendMsg( const QString& msg); 00183 /** sets visualization mode for time course data*/ 00184 void setViewTimeCourse(bool toggle); 00185 /** sets normalization mode for time course data*/ 00186 void setNormalizeTimeCourse(bool toggle); 00187 /** scrolls to next visible read cluster*/ 00188 void scrollToNextCluster(bool forward); 00189 /** sets cluster window size*/ 00190 void setClusterWindow(int window_size); 00191 /** sets cluster minimum read num size*/ 00192 void setClusterMinNum(int num); 00193 00194 public slots: 00195 void slotSwitchToMode( int i ); 00196 void slotStartAlgo( int i ); 00197 void slotScrollToMouse(); 00198 void slotScrollToPos(); 00199 void slotSetCenter(); 00200 void slotClearCenter(); 00201 void slotContextSelect(int i); 00202 00203 protected: 00204 void contentsDragEnterEvent(QDragEnterEvent* event); 00205 void contentsDropEvent(QDropEvent* event); 00206 void contentsMouseMoveEvent(QMouseEvent* e); 00207 void contentsMouseReleaseEvent(QMouseEvent* e); 00208 void contentsContextMenuEvent( QContextMenuEvent * e ); 00209 void contentsMousePressEvent(QMouseEvent* e); 00210 void contentsDragMoveEvent ( QDragMoveEvent * ); 00211 virtual void closeEvent(QCloseEvent*); 00212 void doZoom(); 00213 void scrollTo(TR_PIX x, TR_PIX y); 00214 00215 void drawContents(QPainter* p, TR_PIX cx, TR_PIX cy, TR_PIX cw, TR_PIX ch); 00216 00217 /** \brief paint a rectangle of the window 00218 * 00219 * @param p where to paint to 00220 * @param bmp where to paint a bitmask, we paint to the bitmask on the same places as we paint to p. 00221 * @param cx x coordinate of rectangle in "content" coordinate system 00222 * @param cy y coordinate of rectangle in "content" coordinate system 00223 * @param cw width of rectangle in "content" coordinate system 00224 * @param ch height of rectangle in "content" coordinate system 00225 * @param dx displace painting with this 00226 * @param dy displace painting with this 00227 */ 00228 00229 00230 void drawContents_helper(QPainter* p,QPainter* bitmapPainter, int cx, int cy, int cw, int ch, int dx, int dy); 00231 00232 00233 /** \brief paint border line around the read rectangle. Then divide the rectangle into layers 00234 * and paint features of the read into these layers. 00235 * 00236 * @param p where to paint 00237 * @param bmp where to paint a bitmask, we paint to the bitmask on the same places as we paint to p. 00238 * @param readRecno the index of the read in the underlying berkeley db. 00239 * @param x_pix x "content" coordinate of the upperleft corner of the paint area 00240 * @param y_pix y "content" coordinate of the upperleft corner of the paint area 00241 * @param x1_dna x dna coordinate of the left most position to paint seen relative the left side of the read 00242 * @param x2_dna x dna coordinate of the right most position to paint seen relative the left side of the read 00243 * @param width the pixel width of one x dna coordinate 00244 * @param height the pixel width of one x dna coordinate 00245 * @param highlight if true change the read border color 00246 */ 00247 00248 00249 void paintFeatures( QPainter* p, QPainter * bitmapPainter, db_recno_t readRecno, 00250 TR_PIX x_pix, TR_PIX y_pix, 00251 TR_DNA x_dna_relative, TR_DNA dna_len , 00252 /*TR_PIX*/double width, TR_PIX height, bool selected, int center_relative, 00253 bool overlap, TR_DNA bg, TR_DNA eg ); 00254 00255 /** \brief paint some extra dots in the background of the window. These will move along when the 00256 * user scrolls. Nice to have some visual feedback of movement when there are no reads in the window */ 00257 void paintGrid(QPainter* p, TR_PIX cx, TR_PIX cy, TR_PIX cw, TR_PIX ch); 00258 void convertToPixelCoordinates( TR_PIX & x_pix, TR_PIX & y_pix, TR_DNA x_dna, TR_DNA y_dna ); 00259 void convertToDnaCoordinates( TR_DNA & x_dna, TR_DNA & y_dna, const TR_PIX cx, const TR_PIX cy ); 00260 TR_PIX dnaCoordToPixel_X( TR_DNA cx ); 00261 TR_PIX dnaCoordToPixel_Y( TR_DNA cy ); 00262 TR_DNA pixelCoordToDna_X( TR_PIX x_dna ); 00263 TR_DNA pixelCoordToDna_Y( TR_PIX y_dna ); 00264 00265 std::set< db_recno_t >& getSelectedReads(); 00266 void select( db_recno_t recno, bool status ); 00267 bool isSelected( db_recno_t recno ); 00268 void clearSelected(); 00269 std::vector<std::list<std::string> > getInfo( const QPoint& pos ); 00270 00271 void runAlgo( const std::string& AlgoType, std::set< db_recno_t >& recnoList, AlgoParam* param = 0 ); 00272 void writeSelected(QDataStream& data_stream); 00273 void readSelected(QDataStream& data_stream); 00274 00275 void moveData(TR_PIX dx, TR_PIX dy); 00276 00277 void fitContentsizeToData(); 00278 00279 void clearLastMove(); 00280 00281 TR_PIX basewidth; 00282 TR_PIX spaceBetweenRows; 00283 TR_PIX rowheight; 00284 TR_DNA globalRows, globalBases; 00285 TR_DNA center_point; 00286 00287 TrapperDoc *doc; 00288 QLabel * lab; 00289 // u_int16_t magnifyX; 00290 double magnifyX; 00291 u_int16_t magnifyY; 00292 int zoomfactor; 00293 ViewModes * viewModes; 00294 QPopupMenu *switchViewMenu; 00295 QPopupMenu *algoMenu; 00296 QPopupMenu *infoMenu; 00297 QPopupMenu *contextSelectMenu; 00298 00299 00300 typedef std::set<db_recno_t> RecnoMap; 00301 /** The index values ( of type db_recno_t ) of all selected reads. 00302 * 00303 * Just some thoughts about implemantion: 00304 * Right now they are stored as an STL map but 00305 * there are other alternatives of how to implement this: Maybe an 00306 * STL bitset or STL vector<bool> or maybe store it in a berkeley db. 00307 * If you want to select all possible reads, 4^32, then you would 00308 * lower your memory consumption if used a bitset. And going with 00309 * a berkeley db you would have even lower memory demands. 00310 * 00311 * 040315: Changed selectedReads into std::set --EA 00312 */ 00313 std::set<db_recno_t> selectedReads; 00314 std::map<std::string, int> zoom_cutoff; 00315 int min_cutoff; 00316 00317 ReadsInRect * readsInRect; 00318 bool dragging; 00319 bool allow_dragging; 00320 bool moving; 00321 bool last_click_selected_read; 00322 bool last_click_changed_selection; 00323 db_recno_t last_selected_recno; 00324 QPoint curr_mouse_pos; 00325 TR_PIX y_delta; 00326 TR_PIX y_delta_previous; 00327 00328 TR_DNA last_move_x; 00329 TR_DNA last_move_y; 00330 00331 bool time_course; 00332 bool tc_normalize; 00333 00334 int read_cluster_min_num; 00335 TR_DNA read_cluster_window; 00336 00337 00338 private: 00339 QPixmap dragPixmap; 00340 QBitmap dragBitmap; 00341 QPainter p3; 00342 QPoint mousePressedPoint; 00343 QPoint dragWindowPoint; 00344 QRect* rubber_band; 00345 bool ctrl; 00346 00347 //RUBBERTEST 00348 QPoint RubberStart,RubberEnd; 00349 bool RubberOn; 00350 QPoint oldMovePoint; 00351 bool moveOn; 00352 00353 00354 00355 00356 void drawRubber(QPainter *p) 00357 { 00358 QPen ppen = p->pen(); 00359 ppen.setStyle(Qt::DotLine); 00360 p->setPen(ppen); 00361 p->drawRect( 00362 RubberStart.x(), 00363 RubberStart.y(), 00364 RubberEnd.x()-RubberStart.x(), 00365 RubberEnd.y()-RubberStart.y() 00366 ); 00367 } 00368 //END RUBBERTEST 00369 signals: 00370 void createView( QString ); 00371 void message( const QString& ); 00372 }; 00373 00374 #endif