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