Save to image fix (ticket:96)
[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   copySelectedTracksAsFasta(buffer);
105
106   // get reference to clipboard
107   QClipboard *clipboard = QApplication::clipboard();
108   clipboard->setText(buffer.c_str());
109 }
110
111
112 void SequenceBrowser::clear()
113 {
114   GlSeqBrowser::clear();
115   emit tracksChanged();
116 }
117
118 void SequenceBrowser::displayContextMenu(const QPoint& point)
119 {
120   popupMenu->popup(point);
121 }
122
123 void SequenceBrowser::push_sequence(boost::shared_ptr<Sequence> s)
124 {
125   GlSeqBrowser::push_sequence(s);
126   emit tracksChanged();
127 }
128
129 void SequenceBrowser::push_sequence(boost::shared_ptr<GlSequence> gs)
130 {
131   GlSeqBrowser::push_sequence(gs);
132   emit tracksChanged();
133 }
134
135 ////////////////////
136 // Rendering code
137 void SequenceBrowser::initializeGL()
138 {
139   GlSeqBrowser::initializeGL();
140 }
141
142 void SequenceBrowser::resizeGL(int width, int height)
143 {
144   GlSeqBrowser::resizeGL(width, height);
145   emit viewportChanged();
146 }
147
148 void SequenceBrowser::paintGL()
149 {
150   GlSeqBrowser::paintGL();
151 }
152
153 void SequenceBrowser::mousePressEvent( QMouseEvent *e)
154 {
155   switch(e->button()) {
156     case Qt::LeftButton:
157       startSelecting(e);
158       break;
159    case Qt::RightButton:
160       break;
161    default:
162       break;
163   }
164 }
165
166 void SequenceBrowser::mouseMoveEvent( QMouseEvent *e )
167 {
168   if (rubberBand and rubberBand->isVisible()) {
169     rubberBand->setGeometry(QRect(bandOrigin, e->pos()).normalized());
170   }
171 }
172
173 void SequenceBrowser::mouseReleaseEvent( QMouseEvent *e)
174 {
175   switch(e->button()) {
176     case Qt::LeftButton:
177       stopSelecting(e);
178       break;
179    case Qt::RightButton:
180       // ok so selectedMode and drawing mode should probably be combinded
181       // into a single state variable.
182       if (rubberBand and 
183           not rubberBand->isVisible() and
184           selectedCanvasRegion.contains(e->pos())) {
185         displayContextMenu(e->globalPos());
186       }
187       break;
188    default:
189       break;
190   }
191
192 }
193
194 void SequenceBrowser::startSelecting(QMouseEvent *e)
195 {
196   if (!rubberBand)
197     rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
198
199   if (not rubberBand->isVisible()) {
200     bandOrigin = e->pos();
201     rubberBand->setGeometry(QRect(bandOrigin, QSize()));
202     rubberBand->show();
203   }
204 }
205
206 void SequenceBrowser::stopSelecting(QMouseEvent *e)
207 {
208   if (rubberBand and rubberBand->isVisible()) {
209     rubberBand->hide();
210     selectedMode = false;
211     QRect r = QRect(bandOrigin, e->pos()).normalized();
212     bandOrigin = r.topLeft();
213   
214     selectRegion(r.top(), r.left(), r.bottom(), r.right());
215     selectedCanvasRegion = r;
216   }
217 }