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