0927cfd137ea144c5082370e84922b5c09466022
[mussa.git] / qui / seqbrowser / SequenceBrowser.cpp
1 #include <QApplication>
2 #include <QClipboard>
3 #include <QDir>
4 #include <QFileDialog>
5 #include <QMessageBox>
6 #include <QMouseEvent>
7 #include <QRubberBand>
8 #include <QRect>
9 #include <QString>
10 #include <iostream>
11 #include <set>
12
13 #include <math.h>
14
15 #include "qui/seqbrowser/SequenceBrowser.hpp"
16 #include "mussa_exceptions.hpp"
17
18 using namespace std;
19
20 SequenceBrowser::SequenceBrowser(QWidget *parent)
21   : QGLWidget(parent),
22     rubberBand(0),
23     popupMenu(0),
24     copySelectedSequenceAsFastaAction(0),
25     copySelectedSequenceAsStringAction(0),
26     editSequencePropertiesAction(0)
27
28   popupMenu = new QMenu(this);
29   copySelectedSequenceAsFastaAction = new QAction(tr("&Copy as Fasta"), this);
30   copySelectedSequenceAsStringAction = new QAction(tr("&Copy Sequence"), this);
31   editSequencePropertiesAction = new QAction(tr("Sequence &Properties"), this);
32   
33   connect(copySelectedSequenceAsFastaAction, SIGNAL(triggered()), 
34           this, SLOT(copySelectedSequenceAsFasta()));
35   popupMenu->addAction(copySelectedSequenceAsFastaAction);
36   copySelectedSequenceAsStringAction->setShortcut(Qt::CTRL | Qt::Key_C);
37   connect(copySelectedSequenceAsStringAction, SIGNAL(triggered()), 
38           this, SLOT(copySelectedSequenceAsString()));
39   popupMenu->addAction(copySelectedSequenceAsStringAction);
40   // connect edit properties action
41   connect(editSequencePropertiesAction, SIGNAL(triggered()), 
42           this, SLOT(editSequenceProperties()));
43 }
44
45 SequenceBrowser::SequenceBrowser(const SequenceBrowser& sb, QWidget *parent)
46   : QGLWidget(parent),
47     GlSeqBrowser(sb),
48     rubberBand(sb.rubberBand),
49     popupMenu(sb.popupMenu),
50     copySelectedSequenceAsFastaAction(sb.copySelectedSequenceAsFastaAction)
51 {
52   resize(sb.width(), sb.height());
53   setZoom(sb.zoom());
54   paintGL();
55 }
56
57 QMenu *SequenceBrowser::getPopupMenu()
58 {
59   return popupMenu;
60 }
61
62 QAction *SequenceBrowser::getCopySelectedSequenceAsFastaAction()
63 {
64   return copySelectedSequenceAsFastaAction;
65 }
66
67 QAction *SequenceBrowser::getCopySelectedSequenceAsStringAction()
68 {
69   return copySelectedSequenceAsStringAction;
70 }
71
72 QAction *SequenceBrowser::getEditSequencePropertiesAction()
73 {
74   return editSequencePropertiesAction;
75 }
76
77 QSize SequenceBrowser::sizeHint() const
78 {
79   return QSize(viewportPixelWidth(), viewportPixelHeight());
80 }
81
82 void SequenceBrowser::setViewportCenter(float x)
83 {
84   const float epsilon = 1e-10;
85   float center = GlSeqBrowser::viewportCenter();
86   float difference = fabsf(x - center);
87   float abs_x = fabsf(x);
88   center = fabsf(center);
89
90   // the difference < epsilon * val is one of the recommended tests
91   // for float equality.
92   // of course since we're looking for not equals, we need to toss a
93   // not at the beginning
94   if (not (difference < epsilon * abs_x or difference < epsilon * center))
95   {
96     GlSeqBrowser::setViewportCenter(x);
97     emit viewportChanged();
98     update();
99   }
100 }
101
102 void SequenceBrowser::setZoom(double new_zoom)
103 {
104   if (new_zoom != GlSeqBrowser::zoom()) {
105     GlSeqBrowser::setZoom(new_zoom);
106     emit viewportChanged();
107     update();
108   }
109 }
110
111 void SequenceBrowser::setClipPlane(int )
112 {
113 /*
114   if (clipZ != (double) newZ){
115     clipZ = (double) newZ;
116     update();
117   }
118 */
119 }
120
121 void SequenceBrowser::copySelectedSequenceAsFasta()
122 {
123   // get fasta data
124   std::string buffer;
125   size_t base_pairs_copied = copySelectedTracksAsFasta(buffer);
126
127   // get reference to clipboard
128   QClipboard *clipboard = QApplication::clipboard();
129   clipboard->setText(buffer.c_str());
130   emit basepairsCopied(base_pairs_copied);
131 }
132
133 void SequenceBrowser::copySelectedSequenceAsString()
134 {
135   // get fasta data
136   std::string buffer;
137   size_t base_pairs_copied = copySelectedTracksAsString(buffer);
138
139   // get reference to clipboard
140   QClipboard *clipboard = QApplication::clipboard();
141   clipboard->setText(buffer.c_str());
142   emit basepairsCopied(base_pairs_copied);
143 }
144
145 void SequenceBrowser::clear()
146 {
147   GlSeqBrowser::clear();
148   emit tracksChanged();
149 }
150
151 void SequenceBrowser::displayContextMenu(const QPoint& point)
152 {
153   popupMenu->popup(point);
154 }
155
156 void SequenceBrowser::editSequenceProperties()
157 {
158   // if there's a previous window, disconnect its signal
159   if (properties) {
160     disconnect(properties.get(), SIGNAL(propertiesChanged()),
161                this, SLOT(updateGL()));
162   }
163   PropertiesWindowRef new_properties(new PropertiesWindow(track_container));
164   properties = new_properties;
165   connect(properties.get(), SIGNAL(propertiesChanged()),
166           this, SLOT(updateGL()));
167   properties->show();
168 }
169
170 void SequenceBrowser::push_sequence(boost::shared_ptr<Sequence> s)
171 {
172   GlSeqBrowser::push_sequence(s);
173   emit tracksChanged();
174 }
175
176 void SequenceBrowser::push_sequence(boost::shared_ptr<GlSequence> gs)
177 {
178   GlSeqBrowser::push_sequence(gs);
179   emit tracksChanged();
180 }
181
182 ////////////////////
183 // Rendering code
184 void SequenceBrowser::initializeGL()
185 {
186   GlSeqBrowser::initializeGL();
187 }
188
189 void SequenceBrowser::resizeGL(int width, int height)
190 {
191   GlSeqBrowser::resizeGL(width, height);
192   emit viewportChanged();
193 }
194
195 void SequenceBrowser::paintGL()
196 {
197   GlSeqBrowser::paintGL();
198 }
199
200 void SequenceBrowser::mousePressEvent( QMouseEvent *e)
201 {
202   switch(e->button()) {
203     case Qt::LeftButton:
204       startSelecting(e);
205       break;
206    case Qt::RightButton:
207       break;
208    default:
209       break;
210   }
211 }
212
213 void SequenceBrowser::mouseMoveEvent( QMouseEvent *e )
214 {
215   if (rubberBand and rubberBand->isVisible()) {
216     rubberBand->setGeometry(QRect(bandOrigin, e->pos()).normalized());
217   }
218 }
219
220 void SequenceBrowser::mouseReleaseEvent( QMouseEvent *e)
221 {
222   switch(e->button()) {
223     case Qt::LeftButton:
224       stopSelecting(e);
225       break;
226    case Qt::RightButton:
227       // ok so selectedMode and drawing mode should probably be combinded
228       // into a single state variable.
229       if (rubberBand and 
230           not rubberBand->isVisible() and
231           selectedCanvasRegion.contains(e->pos())) {
232         displayContextMenu(e->globalPos());
233       }
234       break;
235    default:
236       break;
237   }
238
239 }
240
241 void SequenceBrowser::startSelecting(QMouseEvent *e)
242 {
243   if (!rubberBand)
244     rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
245
246   if (not rubberBand->isVisible()) {
247     bandOrigin = e->pos();
248     rubberBand->setGeometry(QRect(bandOrigin, QSize()));
249     rubberBand->show();
250   }
251 }
252
253 void SequenceBrowser::stopSelecting(QMouseEvent *e)
254 {
255   if (rubberBand and rubberBand->isVisible()) {
256     rubberBand->hide();
257     selectedMode = false;
258     QRect r = QRect(bandOrigin, e->pos()).normalized();
259     bandOrigin = r.topLeft();
260   
261     selectRegion(r.top(), r.left(), r.bottom(), r.right());
262     selectedCanvasRegion = r;
263   }
264 }