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