+#include "qui/subanalysis/SubanalysisWindow.hpp"
+#include "qui/MussaWindow.hpp"
+
+#include "mussa_exceptions.hpp"
+#include "alg/mussa.hpp"
+
+#include <QMessageBox>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QGridLayout>
+
+SubanalysisWindow::SubanalysisWindow(MussaRef m, QWidget *parent)
+ : QWidget(parent),
+ analysis(m),
+ window(0),
+ threshold(0),
+ table(0),
+ ok(0),
+ cancel(0)
+{
+ QGridLayout *parameterLayout = new QGridLayout;
+
+ QLabel *thresholdLabel = new QLabel(tr("threshold (bp)"));
+ parameterLayout->addWidget(thresholdLabel, 0, 0);
+ threshold = new QSpinBox(this);
+ threshold->setValue(8);
+ parameterLayout->addWidget(threshold, 1, 0);
+ QLabel *windowLabel = new QLabel(tr("window (bp)"));
+ parameterLayout->addWidget(windowLabel, 0, 1);
+ window = new QSpinBox(this);
+ window->setValue(10);
+ parameterLayout->addWidget(window, 1, 1);
+
+ ok = new QPushButton(tr("&OK"), this);
+ ok->setEnabled( false );
+ connect(ok, SIGNAL(clicked()), this, SLOT(run()));
+
+ cancel = new QPushButton(tr("Cancel"), this);
+ connect(cancel, SIGNAL(clicked()), this, SLOT(abort()));
+
+ table = new QTableView(this);
+ table->setModel(&model);
+
+ // layout buttons
+ QHBoxLayout *buttonLayout = new QHBoxLayout;
+ buttonLayout->addWidget(ok);
+ buttonLayout->addWidget(cancel);
+
+ // layout verticle space
+ QVBoxLayout *verticalLayout = new QVBoxLayout;
+ verticalLayout->addLayout(parameterLayout);
+ verticalLayout->addWidget(table);
+ verticalLayout->addLayout(buttonLayout);
+ setLayout(verticalLayout);
+
+ // now that we're all setup lets get notices when we're updated
+ connect(&model, SIGNAL(rowsInserted(const QModelIndex&, int, int)),
+ this, SLOT(modelUpdated(const QModelIndex&, int, int)));
+ connect(&model, SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
+ this, SLOT(modelUpdated(const QModelIndex&, int, int)));
+
+ updateTitle();
+}
+
+SequenceLocationModel& SubanalysisWindow::getModel()
+{
+ return model;
+}
+
+void SubanalysisWindow::abort()
+{
+ model.clear();
+ hide();
+}
+
+void SubanalysisWindow::run()
+{
+ if (window == 0 or threshold == 0) {
+ throw std::runtime_error("SubanalysisWindow misconstructed");
+ }
+
+ if (model.size() == 0) {
+ throw std::runtime_error("It shouldn't be possible to call run with an "
+ "empty model now.");
+ }
+
+ MussaRef new_m(new Mussa);
+
+ for(SequenceLocationModel::iterator itor = model.begin();
+ itor != model.end();
+ ++itor)
+ {
+ // append_sequence from a const Sequence & will make a copy
+ // for the shared pointer.
+ Sequence s = itor->getSelectedSequence();
+ s.clear_motifs();
+ new_m->append_sequence(s);
+ }
+
+ try {
+ new_m->set_window(window->value());
+ new_m->set_threshold(threshold->value());
+ new_m->analyze();
+ // FIXME: why isn't the nway_paths refined_pathz structure just initialized
+ // FIXME: with the contents of pathz?
+ new_m->set_soft_threshold(threshold->value());
+ // copy over motifs
+ std::vector<Sequence> motifs_copy;
+ std::vector<Color> color_copy;
+ const Mussa::motif_set motifs = analysis->motifs();
+ boost::shared_ptr<AnnotationColors> mapper = analysis->colorMapper();
+ for(Mussa::motif_set::const_iterator motif_i = motifs.begin();
+ motif_i != motifs.end();
+ ++motif_i)
+ {
+ motifs_copy.push_back(*motif_i);
+ color_copy.push_back(mapper->lookup("motif", motif_i->get_sequence()));
+ }
+ new_m->set_motifs(motifs_copy, color_copy);
+ MussaWindow *mw = new MussaWindow(new_m);
+ mw->show();
+ model.clear();
+ hide();
+ } catch(mussa_error e) {
+ QMessageBox::critical(this,
+ "Mussa Subanalysis Error",
+ QString(e.what()),
+ QMessageBox::Ok, 0, 0);
+ }
+}
+
+void SubanalysisWindow::modelUpdated(const QModelIndex&, int, int )
+{
+ // if the model is empty we shouldn't be able to click ok
+ if (ok) ok->setEnabled(not model.empty());
+}
+
+void SubanalysisWindow::updateTitle()
+{
+ std::string title("Subanalysis: ");
+ if (analysis) {
+ title += analysis->get_title();
+ }
+ setWindowTitle(title.c_str());
+}