add copy sequence as string option
[mussa.git] / qui / seqbrowser / SequenceBrowserWidget.cpp
1 #include <iostream>
2
3 #include <QLabel>
4 #include <QScrollBar>
5 #include <QSpacerItem>
6 #include <QSplitter>
7 #include <QVBoxLayout>
8 #include <QWidget>
9
10 #include "qui/seqbrowser/SequenceBrowserWidget.hpp"
11 #include "qui/seqbrowser/SequenceBrowser.hpp"
12 #include "qui/seqbrowser/ScrollableSequenceBrowser.hpp"
13 #include "qui/seqbrowser/SequenceDescription.hpp"
14 #include "qui/ImageSaveDialog.hpp"
15
16 #include "alg/glsequence.hpp"
17
18 #include <math.h>
19 using namespace std;
20
21 SequenceBrowserWidget::SequenceBrowserWidget(
22     boost::shared_ptr<QDir> default_dir_,
23     QWidget *parent
24 )
25   : QWidget(parent),
26     default_dir(default_dir_),
27     scrollable_browser(this)
28 {
29   QHBoxLayout *hlayout = new QHBoxLayout;
30   hlayout->addWidget(&left_sidebar, 0);
31   hlayout->addWidget(&scrollable_browser, 1);
32   hlayout->addWidget(&right_sidebar, 0);
33   setLayout(hlayout);
34
35   // update position values when something in the SequenceBrowser changes
36   connect(&scrollable_browser.browser(), SIGNAL(viewportChanged()),
37           this, SLOT(updatePosition()));
38   connect(&scrollable_browser.browser(), SIGNAL(basepairsCopied(size_t)),
39           this, SIGNAL(basepairsCopied(size_t)));
40 }
41
42 void SequenceBrowserWidget::clear()
43 {
44   converted_sequences.clear();
45   scrollable_browser.browser().clear();
46
47   SequenceBrowserSidebar::collection left = left_sidebar.descriptions;
48   SequenceBrowserSidebar::collection right = right_sidebar.descriptions;
49   for(size_t i = 0; i != left_sidebar.size(); ++i)
50   {
51     disconnect(left[i], SIGNAL(nameChanged(const QString &)),
52                right[i], SLOT(setName(const QString &)));
53     disconnect(right[i], SIGNAL(nameChanged(const QString &)),
54                left[i], SLOT(setName(const QString &)));
55   }
56   left_sidebar.clear();
57   right_sidebar.clear();
58 }
59
60 QMenu *SequenceBrowserWidget::getPopupMenu()
61 {
62   return scrollable_browser.browser().getPopupMenu();
63 }
64
65 QAction *SequenceBrowserWidget::getCopySelectedSequenceAsStringAction()
66 {
67   return scrollable_browser.browser().getCopySelectedSequenceAsStringAction();
68 }
69
70 QAction *SequenceBrowserWidget::getCopySelectedSequenceAsFastaAction()
71 {
72   return scrollable_browser.browser().getCopySelectedSequenceAsFastaAction();
73 }
74
75 void SequenceBrowserWidget::copySelectedSequenceAsFasta()
76 {
77   scrollable_browser.browser().copySelectedSequenceAsFasta();
78 }
79
80 void SequenceBrowserWidget::copySelectedTracksAsSeqLocation(
81     std::list<SequenceLocation>& locations
82 )
83 {
84   scrollable_browser.browser().copySelectedTracksAsSeqLocation(locations);
85 }
86
87 void SequenceBrowserWidget::setSequences(
88     const std::vector<boost::shared_ptr<Sequence> >& sequences,
89     boost::shared_ptr<AnnotationColors> cm)
90 {
91   SequenceBrowser& browser = scrollable_browser.browser();
92   clear();
93   for(Mussa::vector_sequence_type::const_iterator seq_i = sequences.begin();
94       seq_i != sequences.end();
95       ++seq_i)
96   {
97     boost::shared_ptr<GlSequence> gs(new GlSequence(*seq_i, cm));
98     converted_sequences.push_back(gs);
99     browser.push_sequence(gs);
100   }
101   left_sidebar.setSequences(converted_sequences);
102   right_sidebar.setSequences(converted_sequences);
103
104   // connect the text change signals to each other
105   SequenceBrowserSidebar::collection left = left_sidebar.descriptions;
106   SequenceBrowserSidebar::collection right = right_sidebar.descriptions;
107   for(size_t i = 0; i != sequences.size() and i != right.size(); ++i)
108   {
109     connect(left[i], SIGNAL(nameChanged(const QString &)),
110             right[i], SLOT(setName(const QString &)));
111     connect(right[i], SIGNAL(nameChanged(const QString &)),
112             left[i], SLOT(setName(const QString &)));
113   }
114
115   updatePosition();
116 }
117
118 void SequenceBrowserWidget::setSequences(
119   std::vector<boost::shared_ptr<GlSequence> >& sequences
120 )
121 {
122   SequenceBrowser& browser = scrollable_browser.browser();
123   clear();
124   for(vector<boost::shared_ptr<GlSequence> >::iterator seq_i = sequences.begin();
125       seq_i != sequences.end();
126       ++seq_i)
127   {
128     browser.push_sequence(*seq_i);
129   }
130   left_sidebar.setSequences(sequences);
131   right_sidebar.setSequences(sequences);
132   updatePosition();
133 }
134
135 const vector<boost::shared_ptr<GlSequence> >& SequenceBrowserWidget::sequences() const
136 {
137   return scrollable_browser.browser().sequences();
138 }
139
140 void SequenceBrowserWidget::clear_links()
141 {
142   scrollable_browser.browser().clear_links();
143 }
144
145 void SequenceBrowserWidget::link(const std::vector<int>& path, 
146                                  const std::vector<bool>& isRC, 
147                                  int length)
148 {
149   scrollable_browser.browser().link(path, isRC, length);
150   scrollable_browser.browser().update();
151 }
152
153 const std::set<int> SequenceBrowserWidget::selectedPaths() const
154 {
155   return scrollable_browser.browser().selectedPaths();
156 }
157
158 void SequenceBrowserWidget::centerOnPath(const vector<int>& paths)
159 {
160   scrollable_browser.browser().centerOnPath(paths);
161   updatePosition();
162 }
163
164 /* This could theoretically be pushed down to some set 
165  * of signals and slots connecting SequenceDescriptions and 
166  * some signal emitted by the browser's viewportChanged code
167  * but evertime I tried to figure it out, I got confused about 
168  * how the descriptions in one of the sidebars was supposed to know
169  * if it was mapping the rightbase or the leftbase.
170  * And so though this could be better the typical use cases 
171  * can just talk to the SequenceBrowserWidget for rendering
172  * or mussa output
173  */
174 void SequenceBrowserWidget::updatePosition()
175 {
176   const SequenceBrowser& browser = scrollable_browser.browser();
177   const vector<boost::shared_ptr<GlSequence> > &sequences = browser.sequences();
178   SequenceBrowserSidebar::collection left = left_sidebar.descriptions;
179   SequenceBrowserSidebar::collection right = right_sidebar.descriptions;
180   for(size_t i = 0; i != sequences.size() and i != right.size(); ++i)
181   {
182     left[i]->setPosition(sequences[i]->leftbase(browser.viewportLeft()));
183     right[i]->setPosition(sequences[i]->rightbase(browser.viewportRight()));
184   }
185   scrollable_browser.browser().update();
186   scrollable_browser.updateScrollBar();
187 }
188
189 void SequenceBrowserWidget::promptSaveBrowserPixmap()
190 {
191   QSize size;
192   size = scrollable_browser.browser().size();
193   //Image Save Dialog
194   ImageSaveDialog imageSaveDialog(default_dir, &scrollable_browser, this);
195   imageSaveDialog.setSize(size.width(), size.height());
196   imageSaveDialog.exec();
197 }
198
199 double SequenceBrowserWidget::zoom()
200 {
201   return scrollable_browser.browser().zoom();
202 }
203
204 double SequenceBrowserWidget::zoomOut()
205 {
206   double zoom_level = scrollable_browser.browser().zoomOut();
207   scrollable_browser.updateScrollBar();
208   return zoom_level;
209 }
210
211 double SequenceBrowserWidget::zoomToSequence()
212 {
213   double zoom_level = scrollable_browser.browser().zoomToSequence();
214   scrollable_browser.updateScrollBar();
215   return zoom_level;
216 }
217
218 void SequenceBrowserWidget::setZoom(double z)
219 {
220   scrollable_browser.browser().setZoom(z);
221 }
222
223 void SequenceBrowserWidget::update()
224 {
225   QWidget::update();
226   scrollable_browser.browser().update();
227 }