X-Git-Url: http://woldlab.caltech.edu/gitweb/?a=blobdiff_plain;f=qui%2FMussaWindow.cpp;h=5d934fa36d637536fa33b03ccac033cdaa5c8f72;hb=a55b0297c987f8885a255527a0599f813e3bb8dc;hp=a97f40ec804da19725efcdad1bd0acd215763bc0;hpb=1fe75ad7f632bc1ed73c4e69ccbadec222e48a14;p=mussa.git diff --git a/qui/MussaWindow.cpp b/qui/MussaWindow.cpp index a97f40e..5d934fa 100644 --- a/qui/MussaWindow.cpp +++ b/qui/MussaWindow.cpp @@ -1,11 +1,12 @@ -#include "py/python.hpp" #include "qui/MussaWindow.hpp" #include "mussa_exceptions.hpp" +#include "version.hpp" #include #include #include #include +#include #include #include #include @@ -16,6 +17,7 @@ #include #include #include +#include #include #include @@ -24,21 +26,29 @@ #include #include +#include namespace fs = boost::filesystem; #include 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_), - default_dir(QDir::home().absolutePath().toStdString(), fs::native), motif_editor(0), - setup_analysis_dialog(this), - browser(this), - mussaViewTB("Path Views"), - zoom(), - threshold(), + setup_analysis_dialog(0), + browser(0), + mussaViewTB(0), + zoom(0), + threshold(0), progress_dialog(0), aboutAction(0), closeAction(0), @@ -58,51 +68,53 @@ MussaWindow::MussaWindow(Mussa *analysis_, QWidget *parent) : viewMussaAlignmentAction(0), manualAssistant(0) { + init_resources(); + setupWidgets(); setupActions(); - setupMainMenu(); setupAssistant(); + setupMainMenu(); + + setWindowIcon(QIcon(":/icons/mussa.png")); + default_dir.reset(new QDir(QDir::home().absolutePath())); - //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 - - //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)), + 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); + + // 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); - connect(analysis, SIGNAL(progress(const std::string&, int, int)), - this, SLOT(updateProgress(const std::string&, int, int))); + + // 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 clear(); - delete analysis; - analysis = new_analysis; - setWindowTitle(analysis->get_name().c_str()); + analysis.swap(new_analysis); + updateTitle(); updateAnalysis(); } } @@ -123,10 +135,11 @@ void MussaWindow::setupActions() connect(closeAction, SIGNAL(triggered()), this, SLOT(close())); closeAction->setIcon(QIcon(":/icons/exit.png")); - createNewAnalysisAction = new QAction(tr("Create 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("Add to Subanalysis"), this); connect(createSubAnalysisAction, SIGNAL(triggered()), @@ -136,6 +149,7 @@ void MussaWindow::setupActions() 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()), @@ -145,7 +159,7 @@ void MussaWindow::setupActions() 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")); @@ -155,15 +169,16 @@ void MussaWindow::setupActions() this, SLOT(loadMupa())); loadMupaAction->setIcon(QIcon(":/icons/fileopen.png")); - loadSavedAnalysisAction = new QAction(tr("Load Existing &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())); + this, SLOT(showManual())); newMussaWindowAction = new QAction(tr("&New Mussa Window"), this); newMussaWindowAction->setStatusTip("open another mussa window to allow comparing results"); @@ -193,9 +208,11 @@ void MussaWindow::setupActions() //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 sequence alignment"), this); connect(viewMussaAlignmentAction, SIGNAL(triggered()), @@ -242,8 +259,10 @@ void MussaWindow::setupMainMenu() newMenu = menuBar()->addMenu(tr("&Edit")); newMenu->addAction(editMotifsAction); - newMenu->addAction(&browser.getCopySelectedSequenceAsFastaAction()); + 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); @@ -256,14 +275,28 @@ void MussaWindow::setupMainMenu() newMenu->addAction(aboutAction); // add some extra features to the context menu - QMenu& popupMenu = browser.getPopupMenu(); - popupMenu.addAction(viewMussaAlignmentAction); - popupMenu.addAction(createSubAnalysisAction); + 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_ASSISTANT_FOUND) +#if defined(QT_QTASSISTANT_FOUND) QStringList manualAssistantArgs; manualAssistantArgs = QStringList(); manualAssistantArgs << "-profile" << "./doc/manual/mussagl_manual.adp"; @@ -276,20 +309,28 @@ void MussaWindow::setupAssistant() 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 += "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 += "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(); + browser->clear(); } void MussaWindow::createNewAnalysis() @@ -299,10 +340,8 @@ void MussaWindow::createNewAnalysis() // but this should work for the moment. if (not isClearingAnalysisSafe()) return; - if (setup_analysis_dialog.exec()) { - Mussa *m = 0; - m = setup_analysis_dialog.getMussa(); - setAnalysis(m); + if (setup_analysis_dialog->exec()) { + setAnalysis(setup_analysis_dialog->getMussa()); } } catch(mussa_error e) { QString msg(e.what()); @@ -313,8 +352,8 @@ void MussaWindow::createNewAnalysis() void MussaWindow::createSubAnalysis() { list result; - SequenceLocationModel& model = subanalysis_window.getModel(); - browser.copySelectedTracksAsSeqLocation(result); + SequenceLocationModel& model = subanalysis_window->getModel(); + browser->copySelectedTracksAsSeqLocation(result); for(list::iterator result_itor = result.begin(); result_itor != result.end(); ++result_itor) @@ -322,8 +361,8 @@ void MussaWindow::createSubAnalysis() model.push_back(*result_itor); } - if (not subanalysis_window.isVisible()) { - subanalysis_window.show(); + if (not subanalysis_window->isVisible()) { + subanalysis_window->show(); } } @@ -339,7 +378,15 @@ void MussaWindow::saveAnalysis() // this doesn't work when a sequence changes something (like its // name) //else if (analysis->is_dirty()) - analysis->save(); + try { + analysis->save(); + } catch (std::exception e) { + QMessageBox::critical(this, + tr("Mussa Save Error"), + tr(e.what()), + QMessageBox::Ok, 0, 0); + } + } } } @@ -349,7 +396,7 @@ void MussaWindow::saveAnalysisAs() std::auto_ptr dialog(new QFileDialog(this)); dialog->setAcceptMode(QFileDialog::AcceptSave); dialog->setFileMode(QFileDialog::AnyFile); - dialog->setDirectory(QDir(default_dir.native_directory_string().c_str())); + dialog->setDirectory(*default_dir); QStringList fileNames; if (not dialog->exec()) { @@ -360,23 +407,30 @@ void MussaWindow::saveAnalysisAs() if (fileNames.size() != 1) { return; } - - 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; + 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); } - analysis->save(save_path); - default_dir = (save_path / "..").normalize(); } bool MussaWindow::isClearingAnalysisSafe() @@ -410,24 +464,21 @@ bool MussaWindow::isClearingAnalysisSafe() 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)"); - QDir default_qdir(default_dir.native_directory_string().c_str()); QString path = QFileDialog::getOpenFileName(this, caption, - default_qdir.absolutePath(), + default_dir->absolutePath(), filter); // user hit cancel? if (path.isNull()) @@ -436,32 +487,55 @@ void MussaWindow::loadMotifList() try { fs::path converted_path(path.toStdString(), fs::native); analysis->load_motifs(converted_path); - default_dir = converted_path.branch_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)"); - QDir default_qdir(QDir(default_dir.native_directory_string().c_str())); - QString mupa_path = QFileDialog::getOpenFileName( this, caption, - default_qdir.absolutePath(), + default_dir->absolutePath(), filter ); // user hit cancel? @@ -473,16 +547,16 @@ void MussaWindow::loadMupa() // but this should work for the moment. if (not isClearingAnalysisSafe()) return; - Mussa *m = new Mussa; + MussaRef m = Mussa::init(); fs::path converted_path(mupa_path.toStdString(), fs::native); - connect(m, SIGNAL(progress(const std::string&, int, int)), - this, SLOT(updateProgress(const std::string&, int, int))); + connect(m.get(), SIGNAL(progress(const QString&, int, int)), + this, SLOT(updateProgress(const QString&, int, int))); m->load_mupa_file(converted_path); m->analyze(); setAnalysis(m); - setWindowTitle(converted_path.native_file_string().c_str()); + updateTitle(); // grab the path ignoring the mupa file portion - default_dir = converted_path.branch_path(); + 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; @@ -495,12 +569,11 @@ void MussaWindow::loadMupa() void MussaWindow::loadSavedAnalysis() { - QDir default_qdir(QDir(default_dir.native_directory_string().c_str())); QString caption("Load a previously run analysis"); QString muway_dir = QFileDialog::getExistingDirectory( this, caption, - default_qdir.absolutePath() + default_dir->absolutePath() ); // user hit cancel? if (muway_dir.isNull()) @@ -511,23 +584,29 @@ void MussaWindow::loadSavedAnalysis() // but this should work for the moment. if (not isClearingAnalysisSafe()) return; - Mussa *m = new Mussa; + MussaRef m = Mussa::init(); fs::path converted_path(muway_dir.toStdString(), fs::native); - connect(m, SIGNAL(progress(const std::string&, int, int)), - this, SLOT(updateProgress(const std::string&, int, int))); + 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 if (analysis->empty()) { // our current window is empty so load and replace. setAnalysis(m); - setWindowTitle(converted_path.native_file_string().c_str()); - default_dir = converted_path.branch_path(); + updateTitle(); + default_dir->setPath(converted_path.branch_path().native_directory_string().c_str()); } else { MussaWindow *win = new MussaWindow(m); - win->setWindowTitle(converted_path.native_file_string().c_str()); - win->default_dir = converted_path.branch_path(); + 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; @@ -540,30 +619,41 @@ void MussaWindow::loadSavedAnalysis() 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_threshold() != threshold) { - analysis->set_soft_threshold(threshold); + if (analysis->get_soft_threshold() != value) { + threshold->setEnabled( false ); + analysis->set_soft_threshold(value); analysis->nway(); updateLinks(); update(); + threshold->setEnabled( true ); } } 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(); @@ -571,14 +661,26 @@ void MussaWindow::toggleMotifs() void MussaWindow::showManual() { -#if QT_QTASSISTANT_FOUND - manualAssistant->openAssistant(); +#if defined(QT_QTASSISTANT_FOUND) + if (manualAssistant) { + manualAssistant->openAssistant(); + } else { + QMessageBox::warning(this, + tr("Mussa Help Error"), + tr("QtAssistant not setup correctly"), + QMessageBox::Ok, + QMessageBox::NoButton, + QMessageBox::NoButton); + } #else - try { - boost::python::object webopen = get_py()["webbrowser.open"]; - webopen("http://woldlab.caltech.edu/~king/mussagl_manual/"); - } catch( boost::python::error_already_set ) { - PyErr_Print(); + 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 } @@ -598,15 +700,15 @@ void MussaWindow::NotImplementedBox() void MussaWindow::viewMussaAlignment() { - const set& selected_paths = browser.selectedPaths(); + const set& 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 { - boost::shared_ptr ma_win( - new MussaAlignedWindow(*analysis, selected_paths) + MussaAlignedWindowRef ma_win( + new MussaAlignedWindow(analysis, default_dir, selected_paths, subanalysis_window) ); aligned_windows.push_back(ma_win); @@ -618,13 +720,17 @@ void MussaWindow::viewMussaAlignment() void MussaWindow::updateAnalysis() { - threshold.setRange(analysis->get_threshold(),analysis->get_window()); - const Mussa::vector_sequence_type& seqs = analysis->sequences(); - browser.setSequences(seqs, analysis->colorMapper()); + 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()); updateLinks(); - browser.zoomOut(); - zoom.setValue(browser.zoom()); + browser->zoomOut(); + zoom->setValue(browser->zoom()); } void MussaWindow::updateAnnotations() @@ -632,12 +738,17 @@ 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(); @@ -675,13 +786,13 @@ void MussaWindow::updateLinks() 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(); + browser->update(); } void -MussaWindow::updateProgress(const string& description, int current, int max) +MussaWindow::updateProgress(const QString& description, int current, int max) { // if we're done if (current == max) { @@ -693,9 +804,8 @@ MussaWindow::updateProgress(const string& description, int current, int max) } else { // if we're starting, create the dialog if (progress_dialog == 0) { - QString desc(description.c_str()); QString cancel("Cancel"); - progress_dialog = new QProgressDialog(desc, cancel, current, max, this); + progress_dialog = new QProgressDialog(description, cancel, current, max, this); progress_dialog->show(); } else { // just update the dialog @@ -704,3 +814,17 @@ MussaWindow::updateProgress(const string& description, int current, int max) } 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); + } +}