Finish off setting sequence offset user interface
[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   : QScrollArea(parent),
26     default_dir(default_dir_),
27     left_sidebar(new SequenceBrowserSidebar),
28     scrollable_browser(new ScrollableSequenceBrowser),
29     right_sidebar(new SequenceBrowserSidebar),
30     layout(new QHBoxLayout),
31     layout_container(new QWidget(this))
32 {
33   layout->addWidget(left_sidebar, 0);
34   layout->addWidget(scrollable_browser, 1);
35   layout->addWidget(right_sidebar, 0);
36   
37   layout_container->setLayout(layout);
38   setWidget(layout_container);
39   setWidgetResizable(true);
40   
41   // update position values when something in the SequenceBrowser changes
42   connect(&(scrollable_browser->browser()), SIGNAL(viewportChanged()),
43           this, SLOT(updatePosition()));
44   connect(&(scrollable_browser->browser()), SIGNAL(basepairsCopied(size_t)),
45           this, SIGNAL(basepairsCopied(size_t)));
46 }
47
48 QSize SequenceBrowserWidget::sizeHint() const
49 {
50   // don't trust the layouts size computation
51   // use some heavy handed brute force to compute
52   // the correct size so our stupid scrollable_browser
53   // will show the full viewport.
54   QSize left = left_sidebar->sizeHint();
55   QSize center = scrollable_browser->sizeHint();
56   QSize right = right_sidebar->sizeHint();
57   
58   int width = left.width()+center.width()+right.width();
59   width += 2 * layout->margin();
60   if (layout->spacing() > 0) {
61     width += layout->spacing() * 3;
62   }
63   return QSize(width, center.height());
64 }
65
66
67 void SequenceBrowserWidget::clear()
68 {
69   converted_sequences.clear();
70   scrollable_browser->browser().clear();
71
72   SequenceBrowserSidebar::collection left = left_sidebar->descriptions;
73   SequenceBrowserSidebar::collection right = right_sidebar->descriptions;
74   for(size_t i = 0; i != left_sidebar->size(); ++i)
75   {
76     disconnect(left[i], SIGNAL(nameChanged(const QString &)),
77                right[i], SLOT(setName(const QString &)));
78     disconnect(right[i], SIGNAL(nameChanged(const QString &)),
79                left[i], SLOT(setName(const QString &)));
80   }
81   left_sidebar->clear();
82   right_sidebar->clear();
83 }
84
85 QMenu *SequenceBrowserWidget::getPopupMenu()
86 {
87   return scrollable_browser->browser().getPopupMenu();
88 }
89
90 QAction *SequenceBrowserWidget::getCopySelectedSequenceAsStringAction()
91 {
92   return scrollable_browser->browser().getCopySelectedSequenceAsStringAction();
93 }
94
95 QAction *SequenceBrowserWidget::getCopySelectedSequenceAsFastaAction()
96 {
97   return scrollable_browser->browser().getCopySelectedSequenceAsFastaAction();
98 }
99
100 QAction *SequenceBrowserWidget::getEditSequencePropertiesAction()
101 {
102   return scrollable_browser->browser().getEditSequencePropertiesAction();
103 }
104
105 void SequenceBrowserWidget::copySelectedSequenceAsFasta()
106 {
107   scrollable_browser->browser().copySelectedSequenceAsFasta();
108 }
109
110 void SequenceBrowserWidget::copySelectedTracksAsSeqLocation(
111     std::list<SequenceLocation>& locations
112 )
113 {
114   scrollable_browser->browser().copySelectedTracksAsSeqLocation(locations);
115 }
116
117 void SequenceBrowserWidget::setSequences(
118     const std::vector<boost::shared_ptr<Sequence> >& sequences,
119     boost::shared_ptr<AnnotationColors> cm)
120 {
121   SequenceBrowser& browser = scrollable_browser->browser();
122   clear();
123   for(Mussa::vector_sequence_type::const_iterator seq_i = sequences.begin();
124       seq_i != sequences.end();
125       ++seq_i)
126   {
127     boost::shared_ptr<GlSequence> gs(new GlSequence(*seq_i, cm));
128     converted_sequences.push_back(gs);
129     browser.push_sequence(gs);
130   }
131   left_sidebar->setSequences(converted_sequences);
132   right_sidebar->setSequences(converted_sequences);
133
134   // connect the text change signals to each other
135   SequenceBrowserSidebar::collection left = left_sidebar->descriptions;
136   SequenceBrowserSidebar::collection right = right_sidebar->descriptions;
137   for(size_t i = 0; i != sequences.size() and i != right.size(); ++i)
138   {
139     connect(left[i], SIGNAL(nameChanged(const QString &)),
140             right[i], SLOT(setName(const QString &)));
141     connect(right[i], SIGNAL(nameChanged(const QString &)),
142             left[i], SLOT(setName(const QString &)));
143   }
144
145   updatePosition();
146 }
147
148 void SequenceBrowserWidget::setSequences(
149   std::vector<boost::shared_ptr<GlSequence> >& sequences
150 )
151 {
152   SequenceBrowser& browser = scrollable_browser->browser();
153   clear();
154   for(vector<boost::shared_ptr<GlSequence> >::iterator seq_i = sequences.begin();
155       seq_i != sequences.end();
156       ++seq_i)
157   {
158     browser.push_sequence(*seq_i);
159   }
160   left_sidebar->setSequences(sequences);
161   right_sidebar->setSequences(sequences);
162   updatePosition();
163 }
164
165 const vector<boost::shared_ptr<GlSequence> >& SequenceBrowserWidget::sequences() const
166 {
167   return scrollable_browser->browser().sequences();
168 }
169
170 void SequenceBrowserWidget::clear_links()
171 {
172   scrollable_browser->browser().clear_links();
173 }
174
175 void SequenceBrowserWidget::link(const std::vector<int>& path, 
176                                  const std::vector<bool>& isRC, 
177                                  int length)
178 {
179   scrollable_browser->browser().link(path, isRC, length);
180   scrollable_browser->browser().update();
181 }
182
183 const std::set<int> SequenceBrowserWidget::selectedPaths() const
184 {
185   return scrollable_browser->browser().selectedPaths();
186 }
187
188 void SequenceBrowserWidget::centerOnPath(const vector<int>& paths)
189 {
190   scrollable_browser->browser().centerOnPath(paths);
191   updatePosition();
192 }
193
194 /* This could theoretically be pushed down to some set 
195  * of signals and slots connecting SequenceDescriptions and 
196  * some signal emitted by the browser's viewportChanged code
197  * but evertime I tried to figure it out, I got confused about 
198  * how the descriptions in one of the sidebars was supposed to know
199  * if it was mapping the rightbase or the leftbase.
200  * And so though this could be better the typical use cases 
201  * can just talk to the SequenceBrowserWidget for rendering
202  * or mussa output
203  */
204 void SequenceBrowserWidget::updatePosition()
205 {
206   const SequenceBrowser& browser = scrollable_browser->browser();
207   const vector<boost::shared_ptr<GlSequence> > &sequences = browser.sequences();
208   SequenceBrowserSidebar::collection left = left_sidebar->descriptions;
209   SequenceBrowserSidebar::collection right = right_sidebar->descriptions;
210   for(size_t i = 0; i != sequences.size() and i != right.size(); ++i)
211   {
212     left[i]->setPosition(sequences[i]->leftbase(browser.viewportLeft()));
213     right[i]->setPosition(sequences[i]->rightbase(browser.viewportRight()));
214   }
215   scrollable_browser->browser().update();
216   scrollable_browser->updateScrollBar();
217 }
218
219 void SequenceBrowserWidget::promptSaveBrowserPixmap()
220 {
221   QSize size;
222   size = scrollable_browser->browser().size();
223   //Image Save Dialog
224   ImageSaveDialog imageSaveDialog(default_dir, scrollable_browser, this);
225   imageSaveDialog.setSize(size.width(), size.height());
226   imageSaveDialog.exec();
227 }
228
229 double SequenceBrowserWidget::zoom()
230 {
231   return scrollable_browser->browser().zoom();
232 }
233
234 double SequenceBrowserWidget::zoomOut()
235 {
236   double zoom_level = scrollable_browser->browser().zoomOut();
237   scrollable_browser->updateScrollBar();
238   return zoom_level;
239 }
240
241 double SequenceBrowserWidget::zoomToSequence()
242 {
243   double zoom_level = scrollable_browser->browser().zoomToSequence();
244   scrollable_browser->updateScrollBar();
245   return zoom_level;
246 }
247
248 void SequenceBrowserWidget::setZoom(double z)
249 {
250   scrollable_browser->browser().setZoom(z);
251 }
252
253 void SequenceBrowserWidget::update()
254 {
255   QWidget::update();
256   scrollable_browser->browser().update();
257 }