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 /** finds a read */ 00154 void findRead(); 00155 /** enlarges view*/ 00156 void enlarge(); 00157 /** shrinks view*/ 00158 void shrink(); 00159 /** sets pointer mode*/ 00160 void setDragMode(bool status); 00161 /** copies selected data*/ 00162 void copy(); 00163 /** pastes selected data*/ 00164 void paste(); 00165 /** cuts selected data*/ 00166 void cut(); 00167 /** undoes last move*/ 00168 void undo(); 00169 /** gets row position of last mouse press*/ 00170 TR_DNA mousePressedRow(); 00171 /** gets col position of last mouse press*/ 00172 TR_DNA mousePressedCol(); 00173 /** Sends out a message*/ 00174 void sendMsg( const QString& msg); 00175 00176 public slots: 00177 void slotSwitchToMode( int i ); 00178 void slotStartAlgo( int i ); 00179 void slotScrollToMouse(); 00180 void slotScrollToPos(); 00181 void slotSetCenter(); 00182 void slotClearCenter(); 00183 00184 protected: 00185 void contentsDragEnterEvent(QDragEnterEvent* event); 00186 void contentsDropEvent(QDropEvent* event); 00187 void contentsMouseMoveEvent(QMouseEvent* e); 00188 void contentsMouseReleaseEvent(QMouseEvent* e); 00189 void contentsContextMenuEvent( QContextMenuEvent * e ); 00190 void contentsMousePressEvent(QMouseEvent* e); 00191 void contentsDragMoveEvent ( QDragMoveEvent * ); 00192 virtual void closeEvent(QCloseEvent*); 00193 void doZoom(); 00194 void scrollTo(TR_PIX x, TR_PIX y); 00195 00196 void drawContents(QPainter* p, TR_PIX cx, TR_PIX cy, TR_PIX cw, TR_PIX ch); 00197 00198 /** \brief paint a rectangle of the window 00199 * 00200 * @param p where to paint to 00201 * @param bmp where to paint a bitmask, we paint to the bitmask on the same places as we paint to p. 00202 * @param cx x coordinate of rectangle in "content" coordinate system 00203 * @param cy y coordinate of rectangle in "content" coordinate system 00204 * @param cw width of rectangle in "content" coordinate system 00205 * @param ch height of rectangle in "content" coordinate system 00206 * @param dx displace painting with this 00207 * @param dy displace painting with this 00208 */ 00209 00210 00211 void drawContents_helper(QPainter* p,QPainter* bitmapPainter, int cx, int cy, int cw, int ch, int dx, int dy); 00212 00213 00214 /** \brief paint border line around the read rectangle. Then divide the rectangle into layers 00215 * and paint features of the read into these layers. 00216 * 00217 * @param p where to paint 00218 * @param bmp where to paint a bitmask, we paint to the bitmask on the same places as we paint to p. 00219 * @param readRecno the index of the read in the underlying berkeley db. 00220 * @param x_pix x "content" coordinate of the upperleft corner of the paint area 00221 * @param y_pix y "content" coordinate of the upperleft corner of the paint area 00222 * @param x1_dna x dna coordinate of the left most position to paint seen relative the left side of the read 00223 * @param x2_dna x dna coordinate of the right most position to paint seen relative the left side of the read 00224 * @param width the pixel width of one x dna coordinate 00225 * @param height the pixel width of one x dna coordinate 00226 * @param highlight if true change the read border color 00227 */ 00228 00229 00230 void paintFeatures( QPainter* p, QPainter * bitmapPainter, db_recno_t readRecno, 00231 TR_PIX x_pix, TR_PIX y_pix, 00232 TR_DNA x_dna_relative, TR_DNA dna_len , 00233 /*TR_PIX*/double width, TR_PIX height, bool selected, int center_relative, 00234 bool overlap, TR_DNA bg, TR_DNA eg ); 00235 00236 /** \brief paint some extra dots in the background of the window. These will move along when the 00237 * user scrolls. Nice to have some visual feedback of movement when there are no reads in the window */ 00238 void paintGrid(QPainter* p, TR_PIX cx, TR_PIX cy, TR_PIX cw, TR_PIX ch); 00239 void convertToPixelCoordinates( TR_PIX & x_pix, TR_PIX & y_pix, TR_DNA x_dna, TR_DNA y_dna ); 00240 void convertToDnaCoordinates( TR_DNA & x_dna, TR_DNA & y_dna, const TR_PIX cx, const TR_PIX cy ); 00241 TR_PIX dnaCoordToPixel_X( TR_DNA cx ); 00242 TR_PIX dnaCoordToPixel_Y( TR_DNA cy ); 00243 TR_DNA pixelCoordToDna_X( TR_PIX x_dna ); 00244 TR_DNA pixelCoordToDna_Y( TR_PIX y_dna ); 00245 00246 std::set< db_recno_t >& getSelectedReads(); 00247 void select( db_recno_t recno, bool status ); 00248 bool isSelected( db_recno_t recno ); 00249 void clearSelected(); 00250 std::vector<std::list<std::string> > getInfo( const QPoint& pos ); 00251 00252 void runAlgo( const std::string& AlgoType, std::set< db_recno_t >& recnoList, AlgoParam* param = 0 ); 00253 void writeSelected(QDataStream& data_stream); 00254 void readSelected(QDataStream& data_stream); 00255 00256 void moveData(TR_PIX dx, TR_PIX dy); 00257 00258 void fitContentsizeToData(); 00259 00260 void clearLastMove(); 00261 00262 TR_PIX basewidth; 00263 TR_PIX spaceBetweenRows; 00264 TR_PIX rowheight; 00265 TR_DNA globalRows, globalBases; 00266 TR_DNA center_point; 00267 00268 TrapperDoc *doc; 00269 QLabel * lab; 00270 // u_int16_t magnifyX; 00271 double magnifyX; 00272 u_int16_t magnifyY; 00273 int zoomfactor; 00274 ViewModes * viewModes; 00275 QPopupMenu *switchViewMenu; 00276 QPopupMenu *algoMenu; 00277 QPopupMenu *infoMenu; 00278 00279 00280 typedef std::set<db_recno_t> RecnoMap; 00281 /** The index values ( of type db_recno_t ) of all selected reads. 00282 * 00283 * Just some thoughts about implemantion: 00284 * Right now they are stored as an STL map but 00285 * there are other alternatives of how to implement this: Maybe an 00286 * STL bitset or STL vector<bool> or maybe store it in a berkeley db. 00287 * If you want to select all possible reads, 4^32, then you would 00288 * lower your memory consumption if used a bitset. And going with 00289 * a berkeley db you would have even lower memory demands. 00290 * 00291 * 040315: Changed selectedReads into std::set --EA 00292 */ 00293 std::set<db_recno_t> selectedReads; 00294 std::map<std::string, int> zoom_cutoff; 00295 00296 ReadsInRect * readsInRect; 00297 bool dragging; 00298 bool allow_dragging; 00299 bool moving; 00300 bool last_click_selected_read; 00301 bool last_click_changed_selection; 00302 db_recno_t last_selected_recno; 00303 QPoint curr_mouse_pos; 00304 TR_PIX y_delta; 00305 TR_PIX y_delta_previous; 00306 00307 TR_DNA last_move_x; 00308 TR_DNA last_move_y; 00309 00310 private: 00311 QPixmap dragPixmap; 00312 QBitmap dragBitmap; 00313 QPainter p3; 00314 QPoint mousePressedPoint; 00315 QPoint dragWindowPoint; 00316 QRect* rubber_band; 00317 00318 //RUBBERTEST 00319 QPoint RubberStart,RubberEnd; 00320 bool RubberOn; 00321 QPoint oldMovePoint; 00322 bool moveOn; 00323 00324 void drawRubber(QPainter *p) 00325 { 00326 QPen ppen = p->pen(); 00327 ppen.setStyle(Qt::DotLine); 00328 p->setPen(ppen); 00329 p->drawRect( 00330 RubberStart.x(), 00331 RubberStart.y(), 00332 RubberEnd.x()-RubberStart.x(), 00333 RubberEnd.y()-RubberStart.y() 00334 ); 00335 } 00336 //END RUBBERTEST 00337 signals: 00338 void createView( QString ); 00339 void message( const QString& ); 00340 }; 00341 00342 #endif