From ba26165951a034fec35c81719544d5bef562af05 Mon Sep 17 00:00:00 2001 From: stefan <stefan@5a81b35b-ba03-0410-adc8-b2c5c5119f08> Date: Mon, 3 May 2010 10:53:10 +0000 Subject: [PATCH] New sequence viewer, added secondary structure rendering git-svn-id: https://dng.biozentrum.unibas.ch/svn/openstructure/trunk@2163 5a81b35b-ba03-0410-adc8-b2c5c5119f08 --- modules/gui/src/CMakeLists.txt | 3 + .../gui/src/sequence/seq_secstr_painter.cc | 99 +++++++++++++++++++ .../gui/src/sequence/seq_secstr_painter.hh | 43 ++++++++ modules/gui/src/sequence/seq_text_painter.cc | 4 +- modules/gui/src/sequence/sequence_model.cc | 12 +++ modules/gui/src/sequence/sequence_model.hh | 3 + modules/gui/src/sequence/sequence_viewer.cc | 16 +-- modules/gui/src/sequence/view_object.cc | 76 +++++++++++--- modules/gui/src/sequence/view_object.hh | 30 +++++- 9 files changed, 257 insertions(+), 29 deletions(-) create mode 100644 modules/gui/src/sequence/seq_secstr_painter.cc create mode 100644 modules/gui/src/sequence/seq_secstr_painter.hh diff --git a/modules/gui/src/CMakeLists.txt b/modules/gui/src/CMakeLists.txt index 01ed36015..4bba75bb2 100644 --- a/modules/gui/src/CMakeLists.txt +++ b/modules/gui/src/CMakeLists.txt @@ -23,6 +23,7 @@ sequence_search_bar.hh set(OST_GUI_SEQUENCE_VIEW_HEADERS painter.hh row.hh +seq_secstr_painter.hh seq_selection_painter.hh seq_text_painter.hh sequence_delegate.hh @@ -206,6 +207,7 @@ sequence_viewer/sequence_viewer.cc sequence_viewer/sequence_scene.cc sequence_viewer/sequence_search_bar.cc sequence/row.cc +sequence/seq_secstr_painter.cc sequence/seq_selection_painter.cc sequence/seq_text_painter.cc sequence/sequence_delegate.cc @@ -331,6 +333,7 @@ sequence_viewer/sequence_scene.hh sequence_viewer/sequence_search_bar.hh sequence/painter.hh sequence/row.hh +sequence/seq_secstr_painter.hh sequence/seq_selection_painter.hh sequence/seq_text_painter.hh sequence/sequence_delegate.hh diff --git a/modules/gui/src/sequence/seq_secstr_painter.cc b/modules/gui/src/sequence/seq_secstr_painter.cc new file mode 100644 index 000000000..095841b25 --- /dev/null +++ b/modules/gui/src/sequence/seq_secstr_painter.cc @@ -0,0 +1,99 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +/* + Author: Stefan Scheuber + */ + + +#include <QtGui> + +#include "seq_secstr_painter.hh" +#include "view_object.hh" + +namespace ost { namespace gui { + +SeqSecStrPainter::SeqSecStrPainter(QObject* parent) + : Painter(parent) +{} + +void SeqSecStrPainter::Paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index){ + QVariant var = index.data(Qt::UserRole); + painter->save(); + painter->setPen(QPen(Qt::lightGray)); + ListEntry entry = index.data(Qt::UserRole).value<ListEntry>(); + if(entry.secstr.size()>0){ + QSize size = index.data(Qt::UserRole+1).toSize(); + QVarLengthArray<mol::SecStructure>& sec_str = entry.secstr; + int column = index.column()-1; + if(column < sec_str.size()){ + mol::SecStructure sec_element = sec_str[column]; + + int std_diff = (size.height()/2); + int diff = size.height()/1.25; + int center = option.rect.top()+(option.rect.height()/2); + + if (sec_element.IsCoil()) { + int pos = center - std_diff; + painter->drawLine(option.rect.left(),pos,option.rect.right(),pos); + pos = center + std_diff; + painter->drawLine(option.rect.left(),pos,option.rect.right(),pos); + //stack.push_back(QPointF(s.first*advance_, -.6*height_)); + //stack.push_back(QPointF((s.last+1)*advance_, -.6*height_)); + } else if (sec_element.IsHelical()) { + int pos = center - diff; + painter->drawLine(option.rect.left(),pos,option.rect.right(),pos); + pos = center + diff; + painter->drawLine(option.rect.left(),pos,option.rect.right(),pos); + if(column - 1 > 0 && !sec_str[column-1].IsHelical()){ + painter->drawLine(option.rect.left(),center+std_diff,option.rect.left(),center+diff); + painter->drawLine(option.rect.left(),center-std_diff,option.rect.left(),center-diff); + } + if(column + 1 < sec_str.size() && !sec_str[column+1].IsHelical()){ + painter->drawLine(option.rect.right(),center+std_diff,option.rect.right(),center+diff); + painter->drawLine(option.rect.right(),center-std_diff,option.rect.right(),center-diff); + } + } else if (sec_element.IsExtended()) { + int pos = center - diff; + if(column - 1 > 0 && !sec_str[column-1].IsExtended()){ + painter->drawLine(option.rect.left(),center+std_diff,option.rect.left(),center+diff); + painter->drawLine(option.rect.left(),center-std_diff,option.rect.left(),center-diff); + } + if(column + 1 < sec_str.size() && !sec_str[column+1].IsExtended()){ + int max_diff = size.height(); + painter->drawLine(option.rect.left(),center+diff,option.rect.left(),center+max_diff); + painter->drawLine(option.rect.left(),center-diff,option.rect.left(),center-max_diff); + painter->drawLine(option.rect.left(),center+max_diff,option.rect.right(),center+std_diff); + painter->drawLine(option.rect.left(),center-max_diff,option.rect.right(),center-std_diff); + } + else{ + painter->drawLine(option.rect.left(),pos,option.rect.right(),pos); + pos = center + diff; + painter->drawLine(option.rect.left(),pos,option.rect.right(),pos); + } + } + if(!(column+1 < sec_str.size())){ + painter->drawLine(option.rect.right(),center+std_diff,option.rect.right(),center-std_diff); + } + } + } + painter->restore(); +} + +}} diff --git a/modules/gui/src/sequence/seq_secstr_painter.hh b/modules/gui/src/sequence/seq_secstr_painter.hh new file mode 100644 index 000000000..7255a5f3e --- /dev/null +++ b/modules/gui/src/sequence/seq_secstr_painter.hh @@ -0,0 +1,43 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_SEQUENCE_VIEWER_SEQ_SECSTR_PAINTER +#define OST_SEQUENCE_VIEWER_SEQ_SECSTR_PAINTER + +/* + Author: Stefan Scheuber + */ + +#include <QObject> + +#include "painter.hh" + +namespace ost { namespace gui { + +class SeqSecStrPainter : public Painter +{ + Q_OBJECT +public: + SeqSecStrPainter(QObject* parent = 0); + void Paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index); +}; + +}} + +#endif diff --git a/modules/gui/src/sequence/seq_text_painter.cc b/modules/gui/src/sequence/seq_text_painter.cc index 9ac48a688..30c1e1623 100644 --- a/modules/gui/src/sequence/seq_text_painter.cc +++ b/modules/gui/src/sequence/seq_text_painter.cc @@ -38,8 +38,8 @@ void SeqTextPainter::Paint(QPainter* painter, const QStyleOptionViewItem& option QVariant value = index.data(Qt::DisplayRole); if (value.isValid()){ QString text = value.toString(); - painter->setFont(QFont("Courier",10)); - painter->drawText(option.rect, Qt::AlignLeft|Qt::AlignVCenter, text); + painter->setFont(index.data(Qt::FontRole).value<QFont>()); + painter->drawText(option.rect, Qt::AlignCenter, text); } painter->restore(); } diff --git a/modules/gui/src/sequence/sequence_model.cc b/modules/gui/src/sequence/sequence_model.cc index 06199fbf4..f52ddfd60 100644 --- a/modules/gui/src/sequence/sequence_model.cc +++ b/modules/gui/src/sequence/sequence_model.cc @@ -45,6 +45,18 @@ void SequenceModel::InsertSequence(QString& name, seq::SequenceHandle& seq){ this->endInsertRows(); } +void SequenceModel::InsertChain(QString& name, mol::ChainView& view){ + int cols = this->columnCount(); + int new_cols = view.GetResidueCount(); + this->beginInsertRows(QModelIndex(),this->rowCount(),this->rowCount()); + objects_.append(new ViewObject(view, name, this)); + if(new_cols > cols){ + this->beginInsertColumns(QModelIndex(), cols, new_cols); + this->endInsertColumns(); + } + this->endInsertRows(); +} + void SequenceModel::InsertSequences(QString& name, seq::SequenceList& list){ this->beginInsertRows(this->index(this->rowCount(),0),this->rowCount(),this->rowCount()+list.GetCount()); objects_.append(new ViewObject(list, name, this)); diff --git a/modules/gui/src/sequence/sequence_model.hh b/modules/gui/src/sequence/sequence_model.hh index 234cebc7b..2b7bc481b 100644 --- a/modules/gui/src/sequence/sequence_model.hh +++ b/modules/gui/src/sequence/sequence_model.hh @@ -25,6 +25,8 @@ #include <QAbstractTableModel> +#include <ost/mol/chain_view.hh> + #include <ost/seq/sequence_list.hh> #include "sequence_model.hh" @@ -39,6 +41,7 @@ class SequenceModel : public QAbstractTableModel public: SequenceModel(QObject *parent = 0); + void InsertChain(QString& name, mol::ChainView& view); void InsertSequence(QString& name, seq::SequenceHandle& seq); void InsertSequences(QString& name, seq::SequenceList& list); diff --git a/modules/gui/src/sequence/sequence_viewer.cc b/modules/gui/src/sequence/sequence_viewer.cc index 4fa20eac3..25fbcfee1 100644 --- a/modules/gui/src/sequence/sequence_viewer.cc +++ b/modules/gui/src/sequence/sequence_viewer.cc @@ -67,25 +67,11 @@ void SequenceViewerV2::NodeAdded(const gfx::GfxNodeP& n) for (mol::ChainViewList::const_iterator c=v.GetChainList().begin(), e1=v.GetChainList().end(); c!=e1; ++c) { mol::ChainView chain=*c; - String seq_str; - seq_str.reserve(chain.GetResidueCount()); - for (mol::ResidueViewList::const_iterator r=chain.GetResidueList().begin(), - e2=chain.GetResidueList().end(); r!=e2; ++r) { - mol::ResidueView res=*r; - seq_str.append(1, res.GetOneLetterCode()); - } - if (seq_str.empty()) { - continue; - } QString name = QString(o->GetName().c_str()); if (chain.GetName()!="" && chain.GetName()!=" ") { name= name + " ("+chain.GetName().c_str()+")"; } - seq::SequenceHandle sequence=seq::CreateSequence(name.toStdString(), seq_str); - mol::EntityView v_one_chain=v.GetHandle().CreateEmptyView(); - v_one_chain.AddChain(chain, mol::ViewAddFlag::INCLUDE_ALL); - sequence.AttachView(v_one_chain); - model_->InsertSequence(name,sequence); + model_->InsertChain(name,chain); } seq_table_view_->resizeColumnsToContents(); seq_table_view_->resizeRowsToContents(); diff --git a/modules/gui/src/sequence/view_object.cc b/modules/gui/src/sequence/view_object.cc index 43d6601e0..ce504fd8f 100644 --- a/modules/gui/src/sequence/view_object.cc +++ b/modules/gui/src/sequence/view_object.cc @@ -24,9 +24,12 @@ #include <QtGui> +#include <ost/mol/mol.hh> + #include "painter.hh" -#include "seq_text_painter.hh" +#include "seq_secstr_painter.hh" #include "seq_selection_painter.hh" +#include "seq_text_painter.hh" #include "view_object.hh" @@ -47,19 +50,25 @@ ViewObject::ViewObject(seq::SequenceHandle& sequence, const QString& name, QObje this->Init(); } +ViewObject::ViewObject(mol::ChainView& chain, const QString& name, QObject *parent): QObject(parent), name_(name) +{ + this->AddChain(chain); + this->Init(); +} + void ViewObject::Init() { font_ = QFont("Courier",10); QFontMetrics metrics = QFontMetrics(font_); - default_size_ = QSize(metrics.width(QString("_"))+2,metrics.height()+2); + default_size_=QSize(metrics.boundingRect('W').width(),metrics.boundingRect('|').height()); + default_cell_size_ = QSize(metrics.boundingRect('W').width()+2,metrics.boundingRect('|').height()+2); } void ViewObject::InsertRow(int pos, Row* row) { if(pos >= 0 && pos <= rows_.size()){ - seq::SequenceHandle sequence = seq::SequenceHandle(); - QPair<Row*, seq::SequenceHandle> pair(row,sequence); - rows_.insert(pos,pair); + ListEntry entry(row); + rows_.insert(pos,entry); } } @@ -67,7 +76,7 @@ void ViewObject::RemoveRow(Row* row) { QList<int> rows_to_delete; for (int i = 0; i < rows_.size(); ++i){ - if(rows_[i].first == row){ + if(rows_[i].row == row){ rows_to_delete.append(i); } } @@ -79,7 +88,7 @@ void ViewObject::RemoveRow(Row* row) Row* ViewObject::GetRow(int pos) { if(pos >= 0 && pos < rows_.size()){ - return rows_[pos].first; + return rows_[pos].row; } return NULL; } @@ -97,7 +106,44 @@ void ViewObject::AddSequence(seq::SequenceHandle& sequence) p = new SeqTextPainter(this); new_row->InsertPainter(p); QPair<Row*, seq::SequenceHandle> pair(new_row,sequence); - rows_.append(pair); + //rows_.append(pair); +} + +void ViewObject::AddChain(mol::ChainView& chain) +{ + String seq_str; + seq_str.reserve(chain.GetResidueCount()); + for (mol::ResidueViewList::const_iterator r=chain.GetResidueList().begin(), + e2=chain.GetResidueList().end(); r!=e2; ++r) { + mol::ResidueView res=*r; + seq_str.append(1, res.GetOneLetterCode()); + } + if (!seq_str.empty()) { + seq::SequenceHandle sequence=seq::CreateSequence(this->GetName().toStdString(), seq_str); + mol::EntityView v_one_chain=chain.GetEntity().GetHandle().CreateEmptyView(); + v_one_chain.AddChain(chain, mol::ViewAddFlag::INCLUDE_ALL); + sequence.AttachView(v_one_chain); + + Row* new_row = new Row(this); + Painter* p = new SeqSelectionPainter(this); + new_row->InsertPainter(p); + p = new SeqSecStrPainter(this); + new_row->InsertPainter(p); + p = new SeqTextPainter(this); + new_row->InsertPainter(p); + QPair<Row*, seq::SequenceHandle> pair(new_row,sequence); + mol::alg::SecStructureSegments sec = mol::alg::ExtractSecStructureSegments(chain); + QVarLengthArray<mol::SecStructure> sec_str(chain.GetResidueCount()); + for (mol::alg::SecStructureSegments::iterator i=sec.begin(), + e=sec.end(); i!=e; ++i) { + mol::alg::SecStructureSegment s=*i; + for(int i = s.first; i <= s.last ;i++){ + sec_str[i] = s.ss_type; + } + } + ListEntry entry(new_row, sequence, sec_str); + rows_.append(entry); + } } QVariant ViewObject::GetData(int row, int column, int role) @@ -113,12 +159,20 @@ QVariant ViewObject::GetData(int row, int column, int role) } else if(column > 0) { if (role==Qt::DisplayRole) { - return QVariant(QString(rows_[row].second.GetOneLetterCode(column - 1))); + return QVariant(QString(rows_[row].seq.GetOneLetterCode(column - 1))); } if (role==Qt::FontRole){ return QVariant(font_); } if (role==Qt::SizeHintRole){ + return QVariant(default_cell_size_); + } + if (role==Qt::UserRole){ + QVariant variant; + variant.setValue(rows_[row]); + return variant; + } + if (role==Qt::UserRole+1){ return QVariant(default_size_); } } @@ -129,9 +183,9 @@ int ViewObject::GetMaxColumnCount() const { int columns = 0; for(int i = 0; i < rows_.size(); i++){ - int col_length = rows_[i].second.GetLength(); + int col_length = rows_[i].seq.GetLength(); if(columns < col_length){ - columns = rows_[i].second.GetLength() + 1; + columns = rows_[i].seq.GetLength() + 1; } } return columns; diff --git a/modules/gui/src/sequence/view_object.hh b/modules/gui/src/sequence/view_object.hh index d8ae32802..795d996cd 100644 --- a/modules/gui/src/sequence/view_object.hh +++ b/modules/gui/src/sequence/view_object.hh @@ -26,9 +26,13 @@ #include <QObject> #include <QPair> #include <QList> +#include <QVarLengthArray> #include <QFont> #include <QSize> +#include <ost/mol/alg/sec_structure_segments.hh> +#include <ost/mol/entity_handle.hh> + #include <ost/seq/sequence_list.hh> #include "row.hh" @@ -36,13 +40,33 @@ namespace ost { namespace gui { +struct ListEntry { + Row* row; + seq::SequenceHandle seq; + QVarLengthArray<mol::SecStructure> secstr; + ListEntry(): row(NULL) + {} + ListEntry(Row* r): row(r) + {} + ListEntry(Row* r, + seq::SequenceHandle& sequence): row(r), seq(sequence) + {} + ListEntry(Row* r, + seq::SequenceHandle& sequence, + QVarLengthArray<mol::SecStructure>& sec): row(r), seq(sequence), secstr(sec) + {} +}; + + class ViewObject : public QObject { Q_OBJECT + public: ViewObject(seq::SequenceList& sequences, const QString& name, QObject* parent = 0); ViewObject(seq::SequenceHandle& sequence, const QString& name, QObject* parent = 0); + ViewObject(mol::ChainView& chain, const QString& name, QObject* parent = 0); void InsertRow(int pos, Row* row); void RemoveRow(Row* row); @@ -55,6 +79,7 @@ public: int GetMaxColumnCount() const; void AddSequence(seq::SequenceHandle& sequence); + void AddChain(mol::ChainView& chain); QVariant GetData(int row, int column, int role); @@ -66,12 +91,15 @@ public: private: void Init(); QString name_; - QList<QPair<Row*, seq::SequenceHandle> > rows_; + QList<ListEntry> rows_; QFont font_; QSize default_size_; + QSize default_cell_size_; }; }} +Q_DECLARE_METATYPE(ost::gui::ListEntry) + #endif -- GitLab