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