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