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