+#include "qui/MussaWindow.hpp"
+#include "mussa_exceptions.hpp"
+#include "version.hpp"
+
#include <QAction>
+#include <QApplication>
+#include <QAssistantClient>
+#include <QCloseEvent>
+#include <QDesktopServices>
#include <QDir>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QIcon>
+#include <QLibraryInfo>
#include <QMenuBar>
#include <QMessageBox>
+#include <QProcess>
#include <QScrollBar>
#include <QStatusBar>
#include <QString>
+#include <QStringList>
+#include <QTextStream>
+#include <QUrl>
#include <QWhatsThis>
-#include "qui/MussaWindow.hpp"
-#include "mussa_exceptions.hpp"
-
+#include <memory>
+#include <iterator>
#include <iostream>
#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/convenience.hpp>
namespace fs = boost::filesystem;
+#include <boost/bind.hpp>
using namespace std;
-MussaWindow::MussaWindow(Mussa *analysis_, QWidget *parent) :
+static void init_resources() {
+ static bool resources_loaded = false;
+ if (not resources_loaded) {
+ Q_INIT_RESOURCE(icons);
+ resources_loaded = true;
+ }
+}
+
+MussaWindow::MussaWindow(MussaRef analysis_, QWidget *parent) :
QMainWindow(parent),
analysis(analysis_),
motif_editor(0),
- browser(this),
- mussaViewTB("Path Views"),
- zoom(),
- threshold(),
- closeAction(0) // initialize one of the pointers to null as a saftey flag
+ setup_analysis_dialog(0),
+ browser(0),
+ mussaViewTB(0),
+ zoom(0),
+ threshold(0),
+ progress_dialog(0),
+ aboutAction(0),
+ closeAction(0),
+ createNewAnalysisAction(0),
+ createSubAnalysisAction(0),
+ editMotifsAction(0),
+ loadMotifListAction(0),
+ loadMupaAction(0),
+ loadSavedAnalysisAction(0),
+ mussaManualAssistantAction(0),
+ newMussaWindowAction(0),
+ saveMotifListAction(0),
+ showMussaViewToolbarAction(0),
+ toggleMotifsAction(0),
+ saveBrowserPixmapAction(0),
+ whatsThisAction(0),
+ viewMussaAlignmentAction(0),
+ assistantProcess(0)
{
+ init_resources();
+
+ default_dir.reset(new QDir(QDir::home().absolutePath()));
+
+ setupWidgets();
setupActions();
+ setupAssistant();
setupMainMenu();
+
+ setWindowIcon(QIcon(":/icons/mussa.png"));
- //This next setWhatsThis function prevents
- // a segfault when using WhatsThis feature with
- // opengl widget.
- //scene->setWhatsThis(tr("Mussa in OpenGL!"));
- setCentralWidget(&browser);
+ setCentralWidget(browser);
// well updatePosition isn't quite right as we really just need
// to call update()
- connect(this, SIGNAL(changedAnnotations()), &browser, SLOT(update()));
-
- mussaViewTB.addAction(toggleMotifsAction);
- mussaViewTB.addWidget(&zoom);
-
- connect(&zoom, SIGNAL(valueChanged(double)),
- &browser, SLOT(setZoom(double)));
-
- // threshold range is set in updateAnalysis
+ connect(this, SIGNAL(changedAnnotations()), browser, SLOT(update()));
+ connect(this, SIGNAL(changedMotifs()), this, SLOT(updateAnnotations()));
+ connect(browser, SIGNAL(basepairsCopied(size_t)),
+ this, SLOT(showBasePairsCopied(size_t)));
+ connect(zoom, SIGNAL(valueChanged(double)),
+ browser, SLOT(setZoom(double)));
+ mussaViewTB->addWidget(zoom);
- //scene->setClipPlane(20);
- // FIXME: for when we get the paths drawn at the appropriate depth
- //connect(&threshold, SIGNAL(thresholdChanged(int)),
- // this, SLOT(setClipPlane(int)));
- connect(&threshold, SIGNAL(thresholdChanged(int)),
+ // Mouse Wheel triggered zooming
+ connect(browser, SIGNAL(mouseWheelZoom(double)),
+ zoom, SLOT(setValue(double)));
+
+ // threshold range is set in updateAnalysis
+ connect(threshold, SIGNAL(thresholdChanged(int)),
this, SLOT(setSoftThreshold(int)));
- mussaViewTB.addWidget(&threshold);
+ mussaViewTB->addWidget(threshold);
- addToolBar(&mussaViewTB);
+ addToolBar(mussaViewTB);
statusBar()->showMessage("Welcome to mussa", 2000);
- updateAnalysis();
-}
-
-MussaWindow::~MussaWindow()
-{
- if (analysis != 0) delete analysis;
- aligned_windows.clear();
- if (motif_editor != 0) delete motif_editor;
- if (aboutAction != 0) delete aboutAction;
- if (closeAction != 0) delete closeAction;
- if (createNewAnalysisAction != 0) delete createNewAnalysisAction;
- if (createSubAnalysisAction != 0) delete createSubAnalysisAction;
- if (editMotifsAction != 0) delete editMotifsAction;
- if (loadMotifListAction != 0) delete loadMotifListAction;
- if (loadMupaAction != 0) delete loadMupaAction;
- if (loadSavedAnalysisAction != 0) delete loadSavedAnalysisAction;
- if (newMussaWindowAction != 0) delete newMussaWindowAction;
- if (saveMotifListAction != 0) delete saveMotifListAction;
- if (showMussaViewToolbarAction != 0) delete showMussaViewToolbarAction;
- if (toggleMotifsAction != 0) delete toggleMotifsAction;
- if (saveBrowserPixmapAction != 0) delete saveBrowserPixmapAction;
+ // FIXME: we should start refactoring the connect call to updateAnalysis or something
+ if (analysis) {
+ connect(analysis.get(), SIGNAL(progress(const QString&, int, int)),
+ this, SLOT(updateProgress(const QString&, int, int)));
+ connect(analysis.get(), SIGNAL(isModified(bool)),
+ this, SLOT(updateAnalysisModified(bool)));
+ }
+ updateTitle();
+ updateAnalysis();
}
-void MussaWindow::setAnalysis(Mussa *new_analysis)
+void MussaWindow::setAnalysis(MussaRef new_analysis)
{
if (new_analysis != 0) {
// only switch mussas if we loaded without error
- delete analysis;
- analysis = new_analysis;
- setWindowTitle(analysis->get_name().c_str());
+ clear();
+ //std::cout << "analysis soft: " << analysis->get_soft_threshold()
+ // << " new analysis soft: " << new_analysis->get_soft_threshold()
+ // << "\n";
+ analysis.swap(new_analysis);
+ //std::cout << "after swap soft thres: " << analysis->get_soft_threshold()
+ // << "\n";
+ threshold->disconnect(this);
+ threshold->reset(analysis->get_threshold(),
+ analysis->get_window(),
+ analysis->get_soft_threshold());
+ connect(threshold, SIGNAL(thresholdChanged(int)),
+ this, SLOT(setSoftThreshold(int)));
+ updateTitle();
updateAnalysis();
}
}
connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
closeAction->setIcon(QIcon(":/icons/exit.png"));
- createNewAnalysisAction = new QAction(tr("Define Analysis"), this);
+ createNewAnalysisAction = new QAction(tr("Create &New Analysis"), this);
connect(createNewAnalysisAction, SIGNAL(triggered()),
this, SLOT(createNewAnalysis()));
createNewAnalysisAction->setIcon(QIcon(":/icons/filenew.png"));
+ createNewAnalysisAction->setShortcut(Qt::CTRL | Qt::Key_N);
- createSubAnalysisAction = new QAction(tr("Define SubAnalysis"), this);
+ createSubAnalysisAction = new QAction(tr("Add to Subanalysis"), this);
connect(createSubAnalysisAction, SIGNAL(triggered()),
this, SLOT(createSubAnalysis()));
+ saveAnalysisAction = new QAction(tr("&Save Analysis"), this);
+ connect(saveAnalysisAction, SIGNAL(triggered()),
+ this, SLOT(saveAnalysis()));
+ saveAnalysisAction->setIcon(QIcon(":/icons/filesave.png"));
+ saveAnalysisAction->setShortcut(Qt::CTRL | Qt::Key_S);
+
+ saveAnalysisAsAction = new QAction(tr("Save Analysis &As"), this);
+ connect(saveAnalysisAsAction, SIGNAL(triggered()),
+ this, SLOT(saveAnalysisAs()));
+ saveAnalysisAsAction->setIcon(QIcon(":/icons/filesave.png"));
+
editMotifsAction = new QAction(tr("Edit Motifs"), this);;
connect(editMotifsAction, SIGNAL(triggered()), this, SLOT(editMotifs()));
- loadMotifListAction = new QAction(tr("Load Motif List"), this);
+ loadMotifListAction = new QAction(tr("Open Motif List"), this);
connect(loadMotifListAction, SIGNAL(triggered()),
this, SLOT(loadMotifList()));
loadMotifListAction->setIcon(QIcon(":/icons/fileopen.png"));
- loadMupaAction = new QAction(tr("Load Mussa Parameters"), this);
+ loadMupaAction = new QAction(tr("Create Analysis from File"), this);
connect(loadMupaAction, SIGNAL(triggered()),
this, SLOT(loadMupa()));
loadMupaAction->setIcon(QIcon(":/icons/fileopen.png"));
- loadSavedAnalysisAction = new QAction(tr("Load &Analysis"), this);
+ loadSavedAnalysisAction = new QAction(tr("&Open Existing &Analysis"), this);
connect(loadSavedAnalysisAction, SIGNAL(triggered()),
this, SLOT(loadSavedAnalysis()));
loadSavedAnalysisAction->setIcon(QIcon(":/icons/fileopen.png"));
+ loadSavedAnalysisAction->setShortcut(Qt::CTRL | Qt::Key_O);
+
+ mussaManualAssistantAction = new QAction(tr("Mussagl Manual..."), this);
+ mussaManualAssistantAction->setIcon(QIcon(":/icons/contents.png"));
+ connect(mussaManualAssistantAction, SIGNAL(triggered()),
+ this, SLOT(showManual()));
newMussaWindowAction = new QAction(tr("&New Mussa Window"), this);
newMussaWindowAction->setStatusTip("open another mussa window to allow comparing results");
//Save pixel map action
saveBrowserPixmapAction = new QAction(tr("Save to image..."), this);
- connect(saveBrowserPixmapAction, (SIGNAL(triggered())),
- &browser, SLOT(promptSaveBrowserPixmap()));
- saveBrowserPixmapAction->setIcon(QIcon(":/icons/image2.png"));
+ if (browser) {
+ connect(saveBrowserPixmapAction, (SIGNAL(triggered())),
+ browser, SLOT(promptSaveBrowserPixmap()));
+ saveBrowserPixmapAction->setIcon(QIcon(":/icons/image2.png"));
+ }
- viewMussaAlignmentAction = new QAction(tr("View mussa alignment"), this);
+ viewMussaAlignmentAction = new QAction(tr("View sequence alignment"), this);
connect(viewMussaAlignmentAction, SIGNAL(triggered()),
this, SLOT(viewMussaAlignment() ));
viewMussaAlignmentAction->setWhatsThis(tr("Create a zoomed in window "
whatsThisAction = QWhatsThis::createAction(this);
whatsThisAction->setIcon(QIcon(":/icons/help.png"));
+
+}
+
+void MussaWindow::closeEvent(QCloseEvent *event)
+{
+ if(isClearingAnalysisSafe()) {
+ event->accept();
+ } else {
+ event->ignore();
+ }
}
void MussaWindow::setupMainMenu()
{
// we need to run setupActions first
assert (closeAction != 0);
+
+ QMenu *newMenu = menuBar()->addMenu(tr("&File"));
- QMenu *newMenu;
- newMenu = menuBar()->addMenu(tr("&File"));
newMenu->addAction(newMussaWindowAction);
newMenu->addAction(createNewAnalysisAction);
newMenu->addAction(loadMupaAction);
newMenu->addAction(loadSavedAnalysisAction);
- //newMenu->addAction(createSubAnalysisAction);
+ newMenu->addAction(saveAnalysisAction);
+ newMenu->addAction(saveAnalysisAsAction);
newMenu->addSeparator();
newMenu->addAction(loadMotifListAction);
newMenu->addAction(saveMotifListAction);
newMenu->addSeparator();
newMenu->addAction(closeAction);
- newMenu = menuBar()->addMenu(tr("&View"));
+ newMenu = menuBar()->addMenu(tr("&Edit"));
newMenu->addAction(editMotifsAction);
+ if (browser) newMenu->addAction(browser->getCopySelectedSequenceAsStringAction());
+ if (browser) newMenu->addAction(browser->getCopySelectedSequenceAsFastaAction());
+ newMenu->addAction(createSubAnalysisAction);
+ if (browser) newMenu->addAction(browser->getEditSequencePropertiesAction());
+
+ newMenu = menuBar()->addMenu(tr("&View"));
newMenu->addAction(viewMussaAlignmentAction);
newMenu->addAction(showMussaViewToolbarAction);
newMenu = menuBar()->addMenu(tr("&Help"));
+ newMenu->addAction(mussaManualAssistantAction);
newMenu->addAction(whatsThisAction);
newMenu->addSeparator();
newMenu->addAction(aboutAction);
+
+ // add some extra features to the context menu
+ if (browser) {
+ QMenu *popupMenu = browser->getPopupMenu();
+ if (popupMenu) {
+ popupMenu->addAction(viewMussaAlignmentAction);
+ popupMenu->addAction(createSubAnalysisAction);
+ }
+ }
+}
+
+void MussaWindow::setupWidgets()
+{
+ setup_analysis_dialog = new MussaSetupDialog;
+ subanalysis_window.reset(new SubanalysisWindow(analysis));
+ browser = new SequenceBrowserWidget(default_dir);
+ mussaViewTB = new QToolBar("Path Views", this);
+ zoom = new ZoomWidget(mussaViewTB);
+ threshold = new ThresholdWidget(mussaViewTB);
+}
+
+void MussaWindow::setupAssistant()
+{
+#if defined(QT_QTASSISTANT_FOUND)
+ /*
+ QStringList manualAssistantArgs;
+ manualAssistantArgs = QStringList();
+ manualAssistantArgs << "-profile" << "./doc/manual/mussagl_manual.adp";
+ manualAssistant = new QAssistantClient("assistant", this);
+ manualAssistant->setArguments(manualAssistantArgs);
+ connect(manualAssistant, SIGNAL(error(QString)),
+ this, SLOT(assistantError(QString)));
+ */
+#endif
}
void MussaWindow::about()
{
- QString msg("Welcome to Multiple Species Sequence Analysis\n"
- "(c) 2005-2006 California Institute of Technology\n"
- "Tristan De Buysscher, Diane Trout\n");
- msg += "\n\r";
- msg += "Path: ";
- msg += QDir::currentPath();
- msg += "\n";
- msg += "OpenGL: ";
- msg += (char *)glGetString(GL_VERSION);
- msg += "\n";
- QMessageBox::about(this, tr("About mussa"), msg);
+ QString msg;
+ msg += "Welcome to Multiple Species Sequence Analysis\n";
+ msg += "(c) 2005-2006 California Institute of Technology\n";
+ msg += "Diane Trout, Tristan De Buysscher, Brandon King\n";
+ msg += "Version: ";
+ msg += mussa_version;
+ msg += "\n";
+ msg += "Qt: ";
+ msg += qVersion();
+ msg += "\n";
+ msg += "OpenGL: ";
+ msg += (char *)glGetString(GL_VERSION);
+ msg += "\n";
+ QMessageBox::about(this, tr("About mussa"), msg);
+}
+
+void MussaWindow::clear()
+{
+ if (motif_editor != 0) {
+ motif_editor->hide();
+ delete motif_editor;
+ }
+
+ aligned_windows.clear();
+ browser->clear();
}
void MussaWindow::createNewAnalysis()
{
try {
- if (setup_analysis_dialog.exec()) {
- Mussa *m = 0;
- m = setup_analysis_dialog.getMussa();
- setAnalysis(m);
- } else {
- std::cout << "New mussa exp. aborted!\n";
+ // ideally we should open a new window if there's an analysis
+ // but this should work for the moment.
+ if (not isClearingAnalysisSafe()) return;
+
+ if (setup_analysis_dialog->exec()) {
+ setAnalysis(setup_analysis_dialog->getMussa());
}
} catch(mussa_error e) {
QString msg(e.what());
void MussaWindow::createSubAnalysis()
{
- NotImplementedBox();
+ list<SequenceLocation> result;
+ SequenceLocationModel& model = subanalysis_window->getModel();
+ browser->copySelectedTracksAsSeqLocation(result);
+ for(list<SequenceLocation>::iterator result_itor = result.begin();
+ result_itor != result.end();
+ ++result_itor)
+ {
+ model.push_back(*result_itor);
+ }
+
+ if (not subanalysis_window->isVisible()) {
+ subanalysis_window->show();
+ }
+}
+
+void MussaWindow::saveAnalysis()
+{
+ // if we've got an analysis
+ if (analysis and not analysis->empty()) {
+ // if it doesn't have a name we need to pick one
+ if (analysis->get_analysis_path().empty()) {
+ saveAnalysisAs();
+ } else {
+ // if we've got a name, has it changed any?
+ // this doesn't work when a sequence changes something (like its
+ // name)
+ //else if (analysis->is_dirty())
+ try {
+ analysis->save();
+ } catch (std::exception e) {
+ QMessageBox::critical(this,
+ tr("Mussa Save Error"),
+ tr(e.what()),
+ QMessageBox::Ok, 0, 0);
+ }
+
+ }
+ }
+}
+
+void MussaWindow::saveAnalysisAs()
+{
+ std::auto_ptr<QFileDialog> dialog(new QFileDialog(this));
+ dialog->setAcceptMode(QFileDialog::AcceptSave);
+ dialog->setFileMode(QFileDialog::AnyFile);
+ dialog->setDirectory(*default_dir);
+
+ QStringList fileNames;
+ if (not dialog->exec()) {
+ return;
+ }
+ fileNames = dialog->selectedFiles();
+
+ if (fileNames.size() != 1) {
+ return;
+ }
+ try {
+ fs::path save_path(fileNames[0].toStdString(), fs::native);
+ // do you want to overwrite?
+ if (fs::exists(save_path) and
+ QMessageBox::question(
+ this,
+ tr("Overwrite File? -- Mussa"),
+ tr("A file called %1 already exists"
+ "do you want to overwrite it?")
+ .arg(fileNames[0]),
+ tr("&Yes"), tr("&No"),
+ QString(), 0, 1)
+ ) {
+ return;
+ }
+ analysis->save(save_path);
+ fs::path normalized_path = (save_path / "..").normalize();
+ default_dir->setPath(normalized_path.native_directory_string().c_str());
+ } catch (std::exception e) {
+ QMessageBox::critical(this,
+ tr("Mussa Save Error"),
+ tr(e.what()),
+ QMessageBox::Ok, 0, 0);
+ }
+}
+
+bool MussaWindow::isClearingAnalysisSafe()
+{
+ if (analysis and not analysis->empty() and analysis->is_dirty()) {
+ switch (QMessageBox::question(
+ this,
+ tr("Save Unsaved Changes -- Mussa"),
+ tr("There are unsaved changes,\ndo you want to save?"),
+ tr("&Yes"), tr("&No"), tr("&Cancel"),
+ 0, 2)) {
+ case 0:
+ // save
+ saveAnalysis();
+ break;
+ case 1:
+ // don't save
+ break;
+ case 2:
+ // don't replace
+ return false;
+ break;
+ default:
+ // error
+ throw runtime_error("isClearingAnalysis QMesageBox failure");
+ }
+ }
+ // if we're here we've been saved and can replace
+ return true;
}
void MussaWindow::editMotifs()
{
- if (motif_editor != 0) {
- motif_editor->hide();
- delete motif_editor;
+ if (not motif_editor) {
+ motif_editor = new MotifEditor(analysis);
+ connect(motif_editor, SIGNAL(changedMotifs()),
+ this, SLOT(updateAnnotations()));
}
- motif_editor = new MotifEditor(analysis);
- connect(motif_editor, SIGNAL(changedMotifs()),
- this, SLOT(updateAnnotations()));
motif_editor->show();
}
void MussaWindow::loadMotifList()
{
- QString caption("Load a motif list");
+ QString caption("Mussa Load Motifs");
QString filter("Motif list(*.txt *.mtl)");
QString path = QFileDialog::getOpenFileName(this,
- caption,
- QDir::currentPath(),
- filter);
+ caption,
+ default_dir->absolutePath(),
+ filter);
// user hit cancel?
if (path.isNull())
return;
try {
fs::path converted_path(path.toStdString(), fs::native);
analysis->load_motifs(converted_path);
- } catch (runtime_error e) {
+ default_dir->setPath(converted_path.branch_path().native_directory_string().c_str());
+ emit changedMotifs();
+ } catch (std::exception e) {
QString msg("Unable to load ");
msg += path;
msg += "\n";
msg += e.what();
- QMessageBox::warning(this, "Load Motifs", msg);
+ QMessageBox::warning(this, caption, msg);
}
- assert (analysis != 0);
}
void MussaWindow::saveMotifList()
{
- NotImplementedBox();
-}
+ QString caption("Mussa Save Motifs");
+ QString filter("Motif list(*.txt *.mtl)");
+ QString path = QFileDialog::getSaveFileName(this,
+ caption,
+ default_dir->absolutePath(),
+ filter);
+ // user hit cancel?
+ if (path.isNull())
+ return;
+ // try to load safely
+ try {
+ fs::path converted_path(path.toStdString(), fs::native);
+ if (fs::extension(converted_path).size() == 0) {
+ // no extension, so add one
+ fs::path base_path = converted_path.branch_path();
+ fs::path filename(converted_path.leaf() + ".mtl", fs::native);
+ converted_path = base_path / filename;
+ }
+ analysis->save_motifs(converted_path);
+ default_dir->setPath(converted_path.branch_path().native_directory_string().c_str());
+ } catch (std::exception e) {
+ QString msg("Unable to save ");
+ msg += path;
+ msg += "\n";
+ msg += e.what();
+ QMessageBox::warning(this, caption, msg);
+ }}
void MussaWindow::loadMupa()
{
QString caption("Load a mussa parameter file");
QString filter("Mussa Parameters (*.mupa)");
- QString mupa_path = QFileDialog::getOpenFileName(this,
- caption,
- QDir::currentPath(),
- filter);
+ QString mupa_path = QFileDialog::getOpenFileName(
+ this,
+ caption,
+ default_dir->absolutePath(),
+ filter
+ );
// user hit cancel?
if (mupa_path.isNull())
return;
// try to load safely
try {
- Mussa *m = new Mussa;
+ // ideally we should open a new window if there's an analysis
+ // but this should work for the moment.
+ if (not isClearingAnalysisSafe()) return;
+
+ MussaRef m = Mussa::init();
fs::path converted_path(mupa_path.toStdString(), fs::native);
+ connect(m.get(), SIGNAL(progress(const QString&, int, int)),
+ this, SLOT(updateProgress(const QString&, int, int)));
m->load_mupa_file(converted_path);
- m->analyze(0, 0, Mussa::TransitiveNway, 0.0);
+ m->analyze();
setAnalysis(m);
- setWindowTitle(converted_path.native_file_string().c_str());
+ updateTitle();
+ // grab the path ignoring the mupa file portion
+ default_dir->setPath(converted_path.branch_path().native_directory_string().c_str());
} catch (mussa_load_error e) {
QString msg("Unable to load ");
msg += mupa_path;
void MussaWindow::loadSavedAnalysis()
{
QString caption("Load a previously run analysis");
- QString muway_dir = QFileDialog::getExistingDirectory(this,
- caption,
- QDir::currentPath());
+ QString muway_dir = QFileDialog::getExistingDirectory(
+ this,
+ caption,
+ default_dir->absolutePath()
+ );
// user hit cancel?
if (muway_dir.isNull())
return;
// try to safely load
try {
- Mussa *m = new Mussa;
+ // ideally we should open a new window if there's an analysis
+ // but this should work for the moment.
+ if (not isClearingAnalysisSafe()) return;
+
+ MussaRef m = Mussa::init();
fs::path converted_path(muway_dir.toStdString(), fs::native);
+ connect(m.get(), SIGNAL(progress(const QString&, int, int)),
+ this, SLOT(updateProgress(const QString&, int, int)));
m->load(converted_path);
// only switch mussas if we loaded without error
- setAnalysis(m);
- setWindowTitle(converted_path.native_file_string().c_str());
+ if (analysis->empty()) {
+ // our current window is empty so load and replace.
+ setAnalysis(m);
+ updateTitle();
+ default_dir->setPath(converted_path.branch_path().native_directory_string().c_str());
+ } else {
+ MussaWindow *win = new MussaWindow(m);
+ updateTitle();
+ win->default_dir->setPath(converted_path.branch_path().native_directory_string().c_str());
+ win->show();
+ }
+ } catch (boost::filesystem::filesystem_error e) {
+ QString msg("Unable to load ");
+ msg += muway_dir;
+ msg += "\n";
+ msg += e.what();
+ QMessageBox::warning(this, "Load Parameter", msg);
} catch (mussa_load_error e) {
QString msg("Unable to load ");
msg += muway_dir;
void MussaWindow::newMussaWindow()
{
- Mussa *a = new Mussa();
- MussaWindow *win = new MussaWindow(a);
+ MussaWindow *win = new MussaWindow(Mussa::init());
+ win->default_dir = default_dir;
win->show();
}
-void MussaWindow::setSoftThreshold(int threshold)
+void MussaWindow::setSoftThreshold(int value)
{
- if (analysis->get_soft_thres() != threshold) {
- analysis->set_soft_thres(threshold);
+ //std::cout << "Soft: " << analysis->get_soft_threshold()
+ // << " Value: " << value << "\n";
+ if (analysis->get_soft_threshold() != value) {
+ threshold->setEnabled( false );
+ //std::cout << "Updating!!!!\n";
+ analysis->set_soft_threshold(value);
analysis->nway();
updateLinks();
update();
+ threshold->setEnabled( true );
}
+ //else
+ //{
+ // std::cout << "NOT Updating!!!!\n";
+ //}
}
void MussaWindow::showMussaToolbar()
{
- if (mussaViewTB.isVisible())
- mussaViewTB.hide();
+ if (mussaViewTB->isVisible())
+ mussaViewTB->hide();
else
- mussaViewTB.show();
+ mussaViewTB->show();
+}
+
+void MussaWindow::showBasePairsCopied(size_t bp_copied)
+{
+ QString msg("Copied ");
+ QString num;
+ num.setNum(bp_copied);
+ msg += num + " base pairs";
+ statusBar()->showMessage(msg, 5000);
}
+
void MussaWindow::toggleMotifs()
{
NotImplementedBox();
}
+void MussaWindow::showManual()
+{
+#if defined(QT_QTASSISTANT_FOUND)
+
+ // Only define the process once.
+ if (!assistantProcess)
+ assistantProcess = new QProcess(this);
+
+ // No need to fire up the process again if it is already running.
+ if (assistantProcess->state() == QProcess::Running)
+ return;
+
+ QString app = QLibraryInfo::location(QLibraryInfo::BinariesPath)
+ + QLatin1String("/assistant");
+
+ assistantProcess->start(app, QStringList() << QLatin1String("-enableRemoteControl")
+ << QLatin1String("-collectionFile") << QLatin1String("mussagl_manual.qhc"));
+ if (!assistantProcess->waitForStarted()) {
+ QMessageBox::critical(this, tr("Remote Control"),
+ tr("Could not start Qt Assistant from %1.").arg(app));
+ return;
+ }
+
+ // show index page
+ QTextStream str(assistantProcess);
+ str << QLatin1String("SetSource qthelp://edu.caltech.woldlab.mussagl.1_0_0/doc/mussagl_manual.html")
+ << QLatin1Char('\0') << endl;
+
+#else
+ QUrl manual_url("http://woldlab.caltech.edu/~king/mussagl_manual/");
+ if (not QDesktopServices::openUrl(manual_url)) {
+ QMessageBox::warning(this,
+ tr("Mussa Help Error"),
+ tr("Unable to launch webbrowser"),
+ QMessageBox::Ok,
+ QMessageBox::NoButton,
+ QMessageBox::NoButton);
+#endif //QT_QTASSISTANT_FOUND
+}
+
+void MussaWindow::assistantError(QString message)
+{
+ //std::cout << "QAssistantError: " << message.toStdString() << "\n";
+ QMessageBox::warning ( this, "Warning: Mussagl Manual", message,
+ QMessageBox::Ok,
+ QMessageBox::NoButton);
+}
+
void MussaWindow::NotImplementedBox()
{
QMessageBox::warning(this, QObject::tr("mussa"), QObject::tr("Not implemented yet"));
void MussaWindow::viewMussaAlignment()
{
- const set<int>& selected_paths = browser.selectedPaths();
+ const set<int>& selected_paths = browser->selectedPaths();
if (selected_paths.size() == 0 ) {
QMessageBox::warning(this,
QObject::tr("mussa"),
QObject::tr("you should probably select some paths "
"first"));
} else {
- MussaAlignedWindow *ma_win = new MussaAlignedWindow(*analysis,
- selected_paths);
- connect(this, SIGNAL(changedAnnotations()),
- ma_win, SLOT(update()));
+ MussaAlignedWindowRef ma_win(
+ new MussaAlignedWindow(analysis, default_dir, selected_paths, subanalysis_window)
+ );
+
aligned_windows.push_back(ma_win);
- ma_win->show();
+ connect(this, SIGNAL(changedAnnotations()),
+ aligned_windows.back().get(), SLOT(update()));
+ aligned_windows.back()->show();
}
}
void MussaWindow::updateAnalysis()
{
- threshold.setRange(analysis->get_threshold(),analysis->get_window());
- for (list<MussaAlignedWindow *>::iterator maw_i = aligned_windows.begin();
- maw_i != aligned_windows.end();
- ++maw_i)
- {
- (*maw_i)->hide();
- delete *maw_i;
- }
-
- browser.clear();
- const vector<Sequence>& seqs = analysis->sequences();
- browser.setSequences(seqs, analysis->colorMapper());
+ const Mussa::vector_sequence_type& seqs = analysis->sequences();
+ browser->setSequences(seqs, analysis->colorMapper());
+ assert(browser->sequences().size() == analysis->size());
+
+ // setRange eventually emits something that causes updateLinks to be called
+ // but it's possible for us to not have had a chance to set out sequences
+ // yet.
+ threshold->setRange(analysis->get_threshold(),analysis->get_window());
+ threshold->setBasepairThreshold(analysis->get_soft_threshold());
updateLinks();
- browser.zoomOut();
- zoom.setValue(browser.zoom());
+ browser->zoomOut();
+ zoom->setValue(browser->zoom());
}
void MussaWindow::updateAnnotations()
// motifs were changed in the sequences by
// Mussa::update_sequences_motifs
emit changedAnnotations();
- browser.update();
+ browser->update();
}
void MussaWindow::updateLinks()
{
- browser.clear_links();
+ if(browser->sequences().size() == 0) {
+ // we don't have any sequences load so we have no business setting links
+ return;
+ }
+
+ browser->clear_links();
bool reversed = false;
const NwayPaths& nway = analysis->paths();
- typedef list<ExtendedConservedPath> conserved_paths;
+ typedef list<ConservedPath> conserved_paths;
typedef conserved_paths::const_iterator const_conserved_paths_itor;
for(const_conserved_paths_itor path_itor = nway.refined_pathz.begin();
path_itor != nway.refined_pathz.end();
normalized_path.push_back(x);
rc_flags.push_back(reversed);
}
- browser.link(normalized_path, rc_flags, path_itor->window_size);
+ browser->link(normalized_path, rc_flags, path_itor->window_size);
+ }
+ browser->update();
+}
+
+void
+MussaWindow::updateProgress(const QString& description, int current, int max)
+{
+ // if we're done
+ if (current == max) {
+ if (progress_dialog != 0) {
+ progress_dialog->hide();
+ delete progress_dialog;
+ progress_dialog = 0;
+ }
+ } else {
+ // if we're starting, create the dialog
+ if (progress_dialog == 0) {
+ QString cancel("Cancel");
+ progress_dialog = new QProgressDialog(description, cancel, current, max, this);
+ progress_dialog->show();
+ } else {
+ // just update the dialog
+ progress_dialog->setValue(current);
+ }
}
- browser.update();
+ qApp->processEvents();
}
+void MussaWindow::updateAnalysisModified(bool is_modified)
+{
+ setWindowModified(is_modified);
+}
+
+void MussaWindow::updateTitle()
+{
+ if (analysis) {
+ QString title(analysis->get_title().c_str());
+ title += "[*]";
+ setWindowTitle(title);
+ }
+}