From: Diane Trout Date: Thu, 16 Mar 2006 08:14:36 +0000 (+0000) Subject: track labels X-Git-Url: http://woldlab.caltech.edu/gitweb/?p=mussa.git;a=commitdiff_plain;h=9ae0266a8661ea217421b89108cfd8aafdde4f95 track labels ticket:3 This adds two side bars to the PathWidget that show the current position (and the total length of the sequence, and should show the name). Scrolling the viewport around makes the position number change too. (Which revealed a bug that glsequence.leftbase would return values larger than the sequence). I also fixed the default size hint. However all is not completely well, I really need to specialize the right and left sidebars. And there were way too many classes created for trying to handle all the user interface widgets. And I'm the locations of the various signals and updating code could certainly be better thought out. --- diff --git a/alg/glsequence.cpp b/alg/glsequence.cpp index d802d62..aaedf18 100644 --- a/alg/glsequence.cpp +++ b/alg/glsequence.cpp @@ -86,6 +86,8 @@ Sequence::size_type GlSequence::leftbase(GLfloat left) const left = ceil(left); if (left < seq_x) return 0; + else if (left > seq.size() ) + return seq.size(); else return (Sequence::size_type)left; } diff --git a/alg/mussa.cpp b/alg/mussa.cpp index fa54eb2..ea3fb23 100644 --- a/alg/mussa.cpp +++ b/alg/mussa.cpp @@ -107,6 +107,11 @@ Mussa::set_soft_thres(int sft_thres) soft_thres = sft_thres; } +int Mussa::get_soft_thres() const +{ + return soft_thres; +} + void Mussa::set_analysis_mode(enum analysis_modes new_ana_mode) { diff --git a/alg/mussa.hpp b/alg/mussa.hpp index ded2a8b..8cf8ffa 100644 --- a/alg/mussa.hpp +++ b/alg/mussa.hpp @@ -68,7 +68,8 @@ class Mussa //! get number of bases that must match for a window to be saved int get_threshold() const; void set_soft_thres(int sft_thres); - + int get_soft_thres() const; + void set_analysis_mode(enum analysis_modes new_ana_mode); enum analysis_modes get_analysis_mode() const; //! return a string name for an analysis mode diff --git a/alg/test/module.mk b/alg/test/module.mk index 81c8cce..63bf408 100644 --- a/alg/test/module.mk +++ b/alg/test/module.mk @@ -5,7 +5,7 @@ SOURCES.cpp := test_annotation_color.cpp \ test_flp.cpp \ test_glsequence.cpp \ test_gltracks.cpp \ - test_color.cpp \ + test_color.cpp \ test_main.cpp \ test_mussa.cpp \ test_nway.cpp \ diff --git a/alg/test/test_glsequence.cpp b/alg/test/test_glsequence.cpp index 563af53..81443a5 100644 --- a/alg/test/test_glsequence.cpp +++ b/alg/test/test_glsequence.cpp @@ -106,6 +106,7 @@ BOOST_AUTO_TEST_CASE( glsequence_leftright_base ) BOOST_CHECK_EQUAL( glseq.leftbase( -50.0 ), 0 ); BOOST_CHECK_EQUAL( glseq.leftbase( 0.5 ), 1 ); + BOOST_CHECK_EQUAL( glseq.leftbase( 500.0 ), seq_string.size() ); BOOST_CHECK_EQUAL( glseq.rightbase( 1000.0 ), seq_string.size() ); BOOST_CHECK_EQUAL( glseq.rightbase( seq_string.size()-0.5), seq_string.size()-1); diff --git a/mussagl.pro b/mussagl.pro index 639ee43..69b1378 100644 --- a/mussagl.pro +++ b/mussagl.pro @@ -15,6 +15,9 @@ HEADERS += mussa_exceptions.hpp \ qui/PathWidget.hpp \ qui/PathWindow.hpp \ qui/PathScene.hpp \ + qui/PathSidebar.hpp \ + qui/ScrollableScene.hpp \ + qui/SequenceDescription.hpp \ qui/ThresholdWidget.hpp \ qui/ImageScaler.hpp \ qui/ImageSaveDialog.hpp \ @@ -32,6 +35,9 @@ SOURCES += mussagl.cpp \ qui/PathWidget.cpp \ qui/PathWindow.cpp \ qui/PathScene.cpp \ + qui/PathSidebar.cpp \ + qui/ScrollableScene.cpp \ + qui/SequenceDescription.cpp \ qui/ThresholdWidget.cpp \ qui/ImageScaler.cpp \ qui/ImageSaveDialog.cpp \ @@ -47,13 +53,7 @@ SOURCES += mussagl.cpp \ alg/nway_other.cpp \ alg/nway_paths.cpp \ alg/parse_options.cpp \ -# alg/nway_refine.cpp \ alg/sequence.cpp -# test/test_flp.cpp \ -# test/test_main.cpp \ -# test/test_mussa.cpp \ -# test/test_nway.cpp \ -# test/test_sequence.cpp LIBS += -lm QT += opengl diff --git a/qui/PathScene.cpp b/qui/PathScene.cpp index ccbd7e0..4a48882 100644 --- a/qui/PathScene.cpp +++ b/qui/PathScene.cpp @@ -26,7 +26,8 @@ PathScene::PathScene(QWidget *parent) QSize PathScene::sizeHint() const { - return QSize((int)GlTracks::viewportHeight(), (int)GlTracks::viewportWidth()); + //return QSize((int)GlTracks::viewportHeight(), (int)GlTracks::viewportWidth()); + return QSize(600, 400); } void PathScene::setViewportCenter(float x) @@ -68,6 +69,24 @@ void PathScene::setClipPlane(int ) */ } +void PathScene::clear() +{ + GlTracks::clear(); + emit tracksChanged(); +} + +void PathScene::push_sequence(const Sequence &s) +{ + GlTracks::push_sequence(s); + emit tracksChanged(); +} + +void PathScene::push_sequence(GlSequence &gs) +{ + GlTracks::push_sequence(gs); + emit tracksChanged(); +} + //////////////////// // Rendering code void PathScene::initializeGL() diff --git a/qui/PathScene.hpp b/qui/PathScene.hpp index 7433907..ef4a357 100644 --- a/qui/PathScene.hpp +++ b/qui/PathScene.hpp @@ -24,7 +24,11 @@ public: PathScene(QWidget *parent=0); QSize sizeHint() const; - + + void clear(); + void push_sequence(const Sequence &s); + void push_sequence(GlSequence &); + public slots: void setClipPlane(int z); //! set the center of the current viewport @@ -33,8 +37,8 @@ public slots: void setZoom(int); signals: - //! emitted when our analysis has changed - void analysisUpdated(); + //! emited when someone adds to our list of tracks + void tracksChanged(); void viewportChanged(); private: diff --git a/qui/PathSidebar.cpp b/qui/PathSidebar.cpp new file mode 100644 index 0000000..50bf9cc --- /dev/null +++ b/qui/PathSidebar.cpp @@ -0,0 +1,35 @@ +#include "qui/PathSidebar.hpp" +#include "alg/glsequence.hpp" + +using namespace std; + +PathSidebar::PathSidebar(QWidget* parent) + : QWidget(parent) +{ + setLayout(&layout); +} + +void PathSidebar::updateSidebar(PathScene& scene) +{ + for (vector::iterator desc_i = descriptions.begin(); + desc_i != descriptions.end(); + ++desc_i) + { + layout.removeWidget(*desc_i); + } + descriptions.clear(); + cout << "sidebar " << scene.tracks().size() << endl; + for (vector::const_iterator track_i = scene.tracks().begin(); + track_i != scene.tracks().end(); + ++track_i) + { + cout << " " << track_i->sequence().length() << endl; + SequenceDescription *desc = new SequenceDescription(this); + //disc->setName(track_i->sequence().name()); + desc->setLength(track_i->sequence().length()); + //desc->setPosition(track_i->sequence().length()); + descriptions.push_back(desc); + layout.addWidget(desc); + } + setLayout(&layout); +} diff --git a/qui/PathSidebar.hpp b/qui/PathSidebar.hpp new file mode 100644 index 0000000..852f1c9 --- /dev/null +++ b/qui/PathSidebar.hpp @@ -0,0 +1,21 @@ +#ifndef _PATH_SIDEBAR_H +#define _PATH_SIDEBAR_H + +#include + +#include +#include +#include "qui/PathScene.hpp" +#include "qui/SequenceDescription.hpp" + +//! store a collection of sequence descriptions for the PathWidget +class PathSidebar : public QWidget +{ +public: + PathSidebar(QWidget *parent = 0); + + void updateSidebar(PathScene& scene); + QVBoxLayout layout; + std::vector descriptions; +}; +#endif diff --git a/qui/PathWidget.cpp b/qui/PathWidget.cpp index 88f886f..1b4cd52 100644 --- a/qui/PathWidget.cpp +++ b/qui/PathWidget.cpp @@ -1,54 +1,51 @@ #include +#include +#include +#include +#include #include #include #include "qui/PathScene.hpp" #include "qui/PathWidget.hpp" +#include "qui/ScrollableScene.hpp" +#include "qui/SequenceDescription.hpp" +#include "alg/glsequence.hpp" #include using namespace std; -// whats the maximum reasonable range for a scrollbar -const float max_scrollbar_range = 100000; - -PathWidget::PathWidget(QWidget *parent) : - QWidget(parent), - viewportBar(Qt::Horizontal) +PathWidget::PathWidget(QWidget *parent) + : QSplitter(parent), + scrollable_scene(parent) { - QVBoxLayout *layout = new QVBoxLayout; - - layout->addWidget(&scene); - layout->addWidget(&viewportBar); + setOrientation(Qt::Horizontal); - connect(&viewportBar, SIGNAL(valueChanged(int)), - this, SLOT(setViewportCenter(int))); - connect(&scene, SIGNAL(viewportChanged()), - this, SLOT(updateScrollBar())); - setLayout(layout); + addWidget(&left_sidebar); + addWidget(&scrollable_scene); + addWidget(&right_sidebar); - // sets range & scale - updateScrollBar(); + connect(&scrollable_scene.scene(), SIGNAL(viewportChanged()), + this, SLOT(updatePosition())); } -void PathWidget::updateScrollBar() +void PathWidget::updateTracks() { - float max_right = scene.right(); - float max_left = scene.left(); - float max_range = max_right - max_left; - float cur_left = scene.viewportLeft(); - float cur_right = scene.viewportRight(); - float cur_center = ((cur_right-cur_left)/2)+cur_left; - // set range to min - thumb = (int)cur_center; - viewportBar.setRange((int)max_left, (int)max_right); - viewportBar.setValue(thumb); + left_sidebar.updateSidebar(scrollable_scene.scene()); + right_sidebar.updateSidebar(scrollable_scene.scene()); + updatePosition(); } -void PathWidget::setViewportCenter(int x) +void PathWidget::updatePosition() { - if (x != thumb) { - thumb = x; - scene.setViewportCenter(thumb); + const PathScene& scene = scrollable_scene.scene(); + const vector &tracks = scene.tracks(); + vector left = left_sidebar.descriptions; + vector right = right_sidebar.descriptions; + for(size_t i = 0; i != tracks.size() and i != right.size(); ++i) + { + left[i]->setPosition(tracks[i].leftbase(scene.viewportLeft())); + right[i]->setPosition(tracks[i].rightbase(scene.viewportRight())); } } diff --git a/qui/PathWidget.hpp b/qui/PathWidget.hpp index 08c46bb..7c47f42 100644 --- a/qui/PathWidget.hpp +++ b/qui/PathWidget.hpp @@ -1,31 +1,28 @@ #ifndef _PATH_WIDGET_H_ #define _PATH_WIDGET_H_ -#include -#include +#include -#include "qui/PathScene.hpp" +#include "qui/ScrollableScene.hpp" +#include "qui/PathSidebar.hpp" -class PathWidget : public QWidget +class PathWidget : public QSplitter { Q_OBJECT public: PathWidget(QWidget *parent=0); - PathScene scene; + PathScene& scene() { return scrollable_scene.scene(); } + public slots: - //! update the scrollbar with current viewport information - void updateScrollBar(); - //! update scene with the properly scalled scrollbar offset - void setViewportCenter(int x); + //! when a scene changes its tracks lets update some of our meta info + void updateTracks(); + void updatePosition(); private: - QScrollBar viewportBar; - int thumb; - - float range; - float scale; + ScrollableScene scrollable_scene; + PathSidebar left_sidebar; + PathSidebar right_sidebar; }; - #endif diff --git a/qui/PathWindow.cpp b/qui/PathWindow.cpp index 7ffbadc..5a1dc53 100644 --- a/qui/PathWindow.cpp +++ b/qui/PathWindow.cpp @@ -43,16 +43,16 @@ PathWindow::PathWindow(Mussa *analysis_, QWidget *parent) : zoomBox.setRange(2,1000); mussaViewTB.addWidget(&zoomBox); connect(&zoomBox, SIGNAL(valueChanged(int)), - &path_view.scene, SLOT(setZoom(int))); + &path_view.scene(), SLOT(setZoom(int))); threshold.setRange(19, 30); threshold.setThreshold(19); //scene->setClipPlane(20); // FIXME: for when we get the paths drawn at the appropriate depth - //connect(threshold, SIGNAL(thresholdChanged(int)), - // scene, SLOT(setClipPlane(int))); //connect(&threshold, SIGNAL(thresholdChanged(int)), - // &scene, SLOT(setSoftThreshold(int))); + // this, SLOT(setClipPlane(int))); + connect(&threshold, SIGNAL(thresholdChanged(int)), + this, SLOT(setSoftThreshold(int))); mussaViewTB.addWidget(&threshold); addToolBar(&mussaViewTB); @@ -264,7 +264,7 @@ void PathWindow::loadSavedAnalysis() void PathWindow::setSoftThreshold(int threshold) { - if (analysis->get_threshold() != threshold) { + if (analysis->get_soft_thres() != threshold) { analysis->set_soft_thres(threshold); analysis->nway(); updateLinks(); @@ -293,9 +293,9 @@ void PathWindow::NotImplementedBox() void PathWindow::promptSaveOpenGlPixmap() { QSize size; - size = path_view.scene.size(); + size = path_view.scene().size(); //Image Save Dialog - ImageSaveDialog imageSaveDialog(&path_view.scene, this); + ImageSaveDialog imageSaveDialog(&path_view.scene(), this); imageSaveDialog.setSize(size.width(), size.height()); int result = imageSaveDialog.exec(); cout << "Result: " << result << "\n"; @@ -304,20 +304,21 @@ void PathWindow::promptSaveOpenGlPixmap() void PathWindow::updateAnalysis() { cout << "analysis updated" << endl; - path_view.scene.clear(); + path_view.scene().clear(); const vector& seqs = analysis->sequences(); for(vector::const_iterator seq_i = seqs.begin(); seq_i != seqs.end(); ++seq_i) { - path_view.scene.push_sequence(*seq_i); + path_view.scene().push_sequence(*seq_i); } updateLinks(); + path_view.updateTracks(); } void PathWindow::updateLinks() { - path_view.scene.clear_links(); + path_view.scene().clear_links(); bool reversed = false; const NwayPaths& nway = analysis->paths(); @@ -354,7 +355,8 @@ void PathWindow::updateLinks() normalized_path.push_back(x); rc_flags.push_back(reversed); } - path_view.scene.link(normalized_path, rc_flags, path_itor->window_size); + path_view.scene().link(normalized_path, rc_flags, path_itor->window_size); } + path_view.scene().update(); } diff --git a/qui/ScrollableScene.cpp b/qui/ScrollableScene.cpp new file mode 100644 index 0000000..0c3de45 --- /dev/null +++ b/qui/ScrollableScene.cpp @@ -0,0 +1,48 @@ + +#include + +#include "qui/ScrollableScene.hpp" + +ScrollableScene::ScrollableScene(QWidget *parent) : + QWidget(parent), + viewportBar(Qt::Horizontal) +{ + // construct central opengl widget + QVBoxLayout *layout = new QVBoxLayout; + + layout->addWidget(&path_scene); + layout->addWidget(&viewportBar); + + connect(&viewportBar, SIGNAL(valueChanged(int)), + this, SLOT(setViewportCenter(int))); + connect(&path_scene, SIGNAL(viewportChanged()), + this, SLOT(updateScrollBar())); + + setLayout(layout); + + // sets range & scale + updateScrollBar(); +} + +void ScrollableScene::updateScrollBar() +{ + float max_right = path_scene.right(); + float max_left = path_scene.left(); + float max_range = max_right - max_left; + float cur_left = path_scene.viewportLeft(); + float cur_right = path_scene.viewportRight(); + float cur_center = ((cur_right-cur_left)/2)+cur_left; + // set range to min + thumb = (int)cur_center; + viewportBar.setRange((int)max_left, (int)max_right); + viewportBar.setValue(thumb); +} + +void ScrollableScene::setViewportCenter(int x) +{ + if (x != thumb) { + thumb = x; + path_scene.setViewportCenter(thumb); + } +} + diff --git a/qui/ScrollableScene.hpp b/qui/ScrollableScene.hpp new file mode 100644 index 0000000..4b90e53 --- /dev/null +++ b/qui/ScrollableScene.hpp @@ -0,0 +1,31 @@ +#ifndef _SCROLLABLE_SCENE_H_ +#define _SCROLLABLE_SCENE_H_ + +#include +#include +#include "qui/PathScene.hpp" + +class ScrollableScene : public QWidget +{ + Q_OBJECT + +public: + ScrollableScene(QWidget *parent=0); + PathScene path_scene; + + PathScene& scene() { return path_scene; } +public slots: + //! update the scrollbar with current viewport information + void updateScrollBar(); + //! update scene with the properly scalled scrollbar offset + void setViewportCenter(int x); + +private: + QScrollBar viewportBar; + int thumb; + + float range; + float scale; +}; + +#endif diff --git a/qui/SequenceDescription.cpp b/qui/SequenceDescription.cpp new file mode 100644 index 0000000..130483b --- /dev/null +++ b/qui/SequenceDescription.cpp @@ -0,0 +1,45 @@ +#include "qui/SequenceDescription.hpp" + +#include + +using namespace std; + +SequenceDescription::SequenceDescription(QWidget *parent) + : QWidget(parent) +{ + createWidget(); +} + +SequenceDescription::SequenceDescription(string& name, float length, + QWidget *parent) + : QWidget(parent) +{ + setName(name); + setLength(length); + createWidget(); +} + +void SequenceDescription::createWidget() +{ + QLayout *layout = new QVBoxLayout; + layout->setSpacing(2); + layout->addWidget(&name_label); + layout->addWidget(&length_label); + layout->addWidget(&position_label); + setLayout(layout); +} + +void SequenceDescription::setLength(float length) +{ + QString s; + if (length > 1000) { + length /= 1000; + s.setNum(length, 'f', 2); + s += "kb"; + } else { + s.setNum(length); + s += "b"; + } + length_label.setText(s); +} + diff --git a/qui/SequenceDescription.hpp b/qui/SequenceDescription.hpp new file mode 100644 index 0000000..88e01ef --- /dev/null +++ b/qui/SequenceDescription.hpp @@ -0,0 +1,29 @@ +#ifndef _SEQUENCE_DESCRIPTION_H +#define _SEQUENCE_DESCRIPTION_H + +#include + +#include +#include +#include + +class SequenceDescription : public QWidget +{ + Q_OBJECT + +public: + SequenceDescription(QWidget *parent=0); + SequenceDescription(std::string& name, float length, QWidget *parent=0); + + void setName(std::string& name) { name_label.setText(name.c_str()); } + void setLength(float length); + void setPosition(int pos) { QString s; position_label.setText(s.setNum(pos));} + +private: + QLabel name_label; + QLabel length_label; + QLabel position_label; + + void createWidget(); +}; +#endif