From 0894979a0bf0b8c5aa51788bf9829517ef48fc5a Mon Sep 17 00:00:00 2001 From: Olivier Langella <olivier.langella@u-psud.fr> Date: Tue, 20 Feb 2018 23:08:01 +0100 Subject: [PATCH] new contaminant widget is available --- .../load_results_dialog/loadresultsdialog.cpp | 6 + .../load_results_dialog/loadresultsdialog.h | 2 + src/gui/mainwindow.cpp | 9 ++ src/gui/mainwindow.h | 1 + src/gui/project_view/project_view.ui | 125 +++++------------- src/gui/project_view/projectwindow.cpp | 45 +------ src/gui/project_view/projectwindow.h | 1 - .../contaminant_widget/contaminant_widget.ui | 120 ++++++++++++++++- .../contaminant_widget/contaminantwidget.cpp | 100 +++++++++++++- .../contaminant_widget/contaminantwidget.h | 13 +- src/gui/workerthread.cpp | 5 +- src/gui/workerthread.h | 1 + 12 files changed, 284 insertions(+), 144 deletions(-) diff --git a/src/gui/load_results_dialog/loadresultsdialog.cpp b/src/gui/load_results_dialog/loadresultsdialog.cpp index df97b21b4..556ffb6c4 100644 --- a/src/gui/load_results_dialog/loadresultsdialog.cpp +++ b/src/gui/load_results_dialog/loadresultsdialog.cpp @@ -104,3 +104,9 @@ void LoadResultsDialog::chooseFiles() { // tr("Error choosing identification result files : %1").arg(error.qwhat()), error); } } + + +void LoadResultsDialog::setProjectContaminants(Project * p_project) const { + ui->contaminant_widget->setProjectContaminants(p_project); +} + diff --git a/src/gui/load_results_dialog/loadresultsdialog.h b/src/gui/load_results_dialog/loadresultsdialog.h index 3d02ae179..c4b7c9440 100644 --- a/src/gui/load_results_dialog/loadresultsdialog.h +++ b/src/gui/load_results_dialog/loadresultsdialog.h @@ -27,6 +27,7 @@ #include <QDialog> #include <QStringListModel> #include "../widgets/automatic_filter_widget/automaticfilterwidget.h" +#include "../../core/project.h" namespace Ui { @@ -45,6 +46,7 @@ public: AutomaticFilterParameters getAutomaticFilterParameters() const; QStringList getFileList() const; bool isIndividual() const; + void setProjectContaminants(Project * p_project) const; public slots: void chooseFiles(); void clearFileList(); diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 53872b170..b41506ff3 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -226,6 +226,15 @@ void MainWindow::doGroupingFinished() { _project_window->setProjectSp(_project_sp); } +void MainWindow::doLoadingResultsReady(ProjectSp project_sp) { + qDebug() << "MainWindow::doLoadingResultsReady begin"; + if (_p_load_results_dialog != nullptr) { + _p_load_results_dialog->setProjectContaminants(project_sp.get()); + } + doProjectReady(project_sp); + qDebug() << "MainWindow::doLoadingResultsReady end"; +} + void MainWindow::doProjectReady(ProjectSp project_sp) { qDebug() << "MainWindow::doProjectReady begin"; diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index 629751d03..14581e7c1 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -82,6 +82,7 @@ public slots: void doWorkerAppendText(char *); void doWorkerSetText(QString); void doProjectReady(ProjectSp project_sp); + void doLoadingResultsReady(ProjectSp project_sp); void doProjectNotReady(QString error); void doAcceptedLoadResultDialog(); void doAcceptedTandemRunDialog(); diff --git a/src/gui/project_view/project_view.ui b/src/gui/project_view/project_view.ui index 24b203fb9..755536b84 100644 --- a/src/gui/project_view/project_view.ui +++ b/src/gui/project_view/project_view.ui @@ -51,59 +51,29 @@ <item row="0" column="0"> <layout class="QVBoxLayout" name="filter_parameter_tab_layout"> <item> - <widget class="AutomaticFilterWidget" name="filter_parameter_widget" native="true"/> + <widget class="AutomaticFilterWidget" name="filter_parameter_widget" native="true"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>10</height> + </size> + </property> + <property name="sizeIncrement"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + </widget> </item> <item> - <widget class="QGroupBox" name="contaminant_groupbox"> - <property name="title"> - <string>Contaminants</string> + <widget class="ContaminantWidget" name="contaminant_widget" native="true"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>10</height> + </size> </property> - <layout class="QVBoxLayout" name="verticalLayout_6"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <widget class="QRadioButton" name="contaminant_file_radiobutton"> - <property name="toolTip"> - <string>select contaminants from fasta files</string> - </property> - <property name="text"> - <string>contaminant file</string> - </property> - <attribute name="buttonGroup"> - <string notr="true">contaminant_source_buttongroup</string> - </attribute> - </widget> - </item> - <item> - <widget class="QRadioButton" name="contaminant_regexp_radiobutton"> - <property name="toolTip"> - <string>select contaminants using a regular expression</string> - </property> - <property name="text"> - <string>contaminant &regular expression</string> - </property> - <attribute name="buttonGroup"> - <string notr="true">contaminant_source_buttongroup</string> - </attribute> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QListView" name="contaminant_database_listview"/> - </item> - <item> - <layout class="QVBoxLayout" name="verticalLayout_8"> - <item> - <widget class="QLineEdit" name="contaminant_protein_regexp_line_edit"> - <property name="placeholderText"> - <string>^conta\\|</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> </widget> </item> </layout> @@ -409,6 +379,12 @@ <header>gui/widgets/automatic_filter_widget/automaticfilterwidget.h</header> <container>1</container> </customwidget> + <customwidget> + <class>ContaminantWidget</class> + <extends>QWidget</extends> + <header>gui/widgets/contaminant_widget/contaminantwidget.h</header> + <container>1</container> + </customwidget> </customwidgets> <resources/> <connections> @@ -419,8 +395,8 @@ <slot>doFdrChanged()</slot> <hints> <hint type="sourcelabel"> - <x>442</x> - <y>485</y> + <x>119</x> + <y>104</y> </hint> <hint type="destinationlabel"> <x>484</x> @@ -435,8 +411,8 @@ <slot>doMassPrecisionUnitChanged(QString)</slot> <hints> <hint type="sourcelabel"> - <x>253</x> - <y>113</y> + <x>119</x> + <y>104</y> </hint> <hint type="destinationlabel"> <x>489</x> @@ -467,8 +443,8 @@ <slot>doSelectDecoySource()</slot> <hints> <hint type="sourcelabel"> - <x>110</x> - <y>184</y> + <x>119</x> + <y>104</y> </hint> <hint type="destinationlabel"> <x>682</x> @@ -483,8 +459,8 @@ <slot>doSelectDecoySource()</slot> <hints> <hint type="sourcelabel"> - <x>326</x> - <y>192</y> + <x>119</x> + <y>104</y> </hint> <hint type="destinationlabel"> <x>693</x> @@ -492,38 +468,6 @@ </hint> </hints> </connection> - <connection> - <sender>contaminant_file_radiobutton</sender> - <signal>clicked()</signal> - <receiver>ProjectView</receiver> - <slot>doSelectContaminantSource()</slot> - <hints> - <hint type="sourcelabel"> - <x>159</x> - <y>127</y> - </hint> - <hint type="destinationlabel"> - <x>581</x> - <y>113</y> - </hint> - </hints> - </connection> - <connection> - <sender>contaminant_regexp_radiobutton</sender> - <signal>clicked()</signal> - <receiver>ProjectView</receiver> - <slot>doSelectContaminantSource()</slot> - <hints> - <hint type="sourcelabel"> - <x>408</x> - <y>129</y> - </hint> - <hint type="destinationlabel"> - <x>578</x> - <y>62</y> - </hint> - </hints> - </connection> </connections> <slots> <slot>doFdrChanged()</slot> @@ -533,7 +477,6 @@ <slot>doSelectContaminantSource()</slot> </slots> <buttongroups> - <buttongroup name="contaminant_source_buttongroup"/> <buttongroup name="decoy_source_buttongroup"/> </buttongroups> </ui> diff --git a/src/gui/project_view/projectwindow.cpp b/src/gui/project_view/projectwindow.cpp index 57c84718f..2a2fc3123 100644 --- a/src/gui/project_view/projectwindow.cpp +++ b/src/gui/project_view/projectwindow.cpp @@ -53,9 +53,6 @@ ProjectWindow::ProjectWindow(MainWindow *parent): _p_fasta_str_li = new QStandardItemModel(); ui->decoy_database_listview->setModel(_p_fasta_str_li); - ui->contaminant_database_listview->setModel(_p_fasta_str_li); - QItemSelectionModel * selection_model = ui->contaminant_database_listview->selectionModel(); - ui->contaminant_database_listview->setSelectionMode(QAbstractItemView::MultiSelection); ui->decoy_database_listview->setSelectionMode(QAbstractItemView::MultiSelection); @@ -387,24 +384,8 @@ void ProjectWindow::doAutomaticFilterParametersChanged(AutomaticFilterParameters showWaitingMessage(tr("Updating filters")); doDisplayLoadingMessage(tr("tagging contaminant proteins")); - if (ui->contaminant_file_radiobutton->isChecked()) { - QModelIndexList index_list = ui->contaminant_database_listview->selectionModel()->selectedIndexes(); - _project_sp.get()->getProteinStore().clearContaminants(); - if (index_list.size() > 0) { - for (QModelIndex index :index_list) { - if (index.data(Qt::UserRole).canConvert<FastaFile *>()) { - FastaFile * p_fasta_file = index.data(Qt::UserRole).value<FastaFile *>(); - p_fasta_file->setContaminants(_project_sp.get()->getProteinStore()); - } - else { - throw pappso::PappsoException(QObject::tr("can not convert to FastaFile index.data().canConvert<FastaFile *>()")); - } - } - } - } - else { - _project_sp.get()->getProteinStore().setRegexpContaminantPattern(ui->contaminant_protein_regexp_line_edit->text()); - } + + ui->contaminant_widget->setProjectContaminants(_project_sp.get()); doDisplayLoadingMessage(tr("updating filters")); _project_sp.get()->updateAutomaticFilters(parameters); @@ -594,13 +575,7 @@ void ProjectWindow::setProjectSp(ProjectSp project_sp) { ui->decoy_database_groupbox->setVisible(true); } - ui->contaminant_regexp_radiobutton->setChecked(true); - ui->contaminant_database_listview->setVisible(false); - if (_project_sp.get()->getProteinStore().getContaminantFastaFileList().size() > 0) { - ui->contaminant_file_radiobutton->setChecked(true); - ui->contaminant_protein_regexp_line_edit->setVisible(false); - ui->contaminant_database_listview->setVisible(true); - } + ui->contaminant_widget->getProjectContaminants(_project_sp.get()); qDebug() << "ProjectWindow::setProjectSp begin " << _project_sp.get()->getFastaFileStore().getFastaFileList().size() ; @@ -710,7 +685,6 @@ void ProjectWindow::setProjectSp(ProjectSp project_sp) { //_protein_list_window->show(); ui->decoy_protein_regexp_line_edit->setText(_project_sp.get()->getProteinStore().getRegexpDecoy().pattern()); - ui->contaminant_protein_regexp_line_edit->setText(_project_sp.get()->getProteinStore().getRegexpContaminant().pattern()); refresh(); this->setEnabled(true); @@ -811,16 +785,3 @@ void ProjectWindow::doSelectDecoySource() { } qDebug() << "ProjectWindow::doSelectDecoySource end"; } - -void ProjectWindow::doSelectContaminantSource() { - qDebug() << "ProjectWindow::doSelectContaminantSource begin"; - ui->contaminant_database_listview->setVisible(false); - ui->contaminant_protein_regexp_line_edit->setVisible(false); - if (ui->contaminant_file_radiobutton->isChecked()) { - ui->contaminant_database_listview->setVisible(true); - } - else { - ui->contaminant_protein_regexp_line_edit->setVisible(true); - } - qDebug() << "ProjectWindow::doSelectContaminantSource end"; -} diff --git a/src/gui/project_view/projectwindow.h b/src/gui/project_view/projectwindow.h index 119404289..8ea083902 100644 --- a/src/gui/project_view/projectwindow.h +++ b/src/gui/project_view/projectwindow.h @@ -70,7 +70,6 @@ public slots: void doAutomaticFilterParametersChanged(AutomaticFilterParameters parameters); void doFdrChanged(); void doSelectDecoySource(); - void doSelectContaminantSource(); void doMassPrecisionUnitChanged(QString combo_value); void doOperationFailed(QString); void doOperationFinished(); diff --git a/src/gui/widgets/contaminant_widget/contaminant_widget.ui b/src/gui/widgets/contaminant_widget/contaminant_widget.ui index 5255bcd78..f7e6a7a0e 100644 --- a/src/gui/widgets/contaminant_widget/contaminant_widget.ui +++ b/src/gui/widgets/contaminant_widget/contaminant_widget.ui @@ -30,6 +30,9 @@ <property name="text"> <string>contaminant file</string> </property> + <property name="checked"> + <bool>true</bool> + </property> <attribute name="buttonGroup"> <string notr="true">contaminant_source_buttongroup</string> </attribute> @@ -53,6 +56,51 @@ <item> <widget class="QListView" name="contaminant_database_listview"/> </item> + <item> + <widget class="QWidget" name="control_list_widget" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton"> + <property name="text"> + <string>clear list</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_2"> + <property name="text"> + <string>add files</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> <item> <layout class="QVBoxLayout" name="verticalLayout_8"> <item> @@ -70,7 +118,77 @@ </layout> </widget> <resources/> - <connections/> + <connections> + <connection> + <sender>contaminant_file_radiobutton</sender> + <signal>clicked()</signal> + <receiver>ContaminantWidget</receiver> + <slot>doSelectContaminantSource()</slot> + <hints> + <hint type="sourcelabel"> + <x>113</x> + <y>58</y> + </hint> + <hint type="destinationlabel"> + <x>735</x> + <y>64</y> + </hint> + </hints> + </connection> + <connection> + <sender>contaminant_regexp_radiobutton</sender> + <signal>clicked()</signal> + <receiver>ContaminantWidget</receiver> + <slot>doSelectContaminantSource()</slot> + <hints> + <hint type="sourcelabel"> + <x>226</x> + <y>52</y> + </hint> + <hint type="destinationlabel"> + <x>670</x> + <y>79</y> + </hint> + </hints> + </connection> + <connection> + <sender>pushButton_2</sender> + <signal>clicked()</signal> + <receiver>ContaminantWidget</receiver> + <slot>doSelectFastaFile()</slot> + <hints> + <hint type="sourcelabel"> + <x>333</x> + <y>229</y> + </hint> + <hint type="destinationlabel"> + <x>690</x> + <y>146</y> + </hint> + </hints> + </connection> + <connection> + <sender>pushButton</sender> + <signal>clicked()</signal> + <receiver>ContaminantWidget</receiver> + <slot>doClearList()</slot> + <hints> + <hint type="sourcelabel"> + <x>269</x> + <y>220</y> + </hint> + <hint type="destinationlabel"> + <x>508</x> + <y>201</y> + </hint> + </hints> + </connection> + </connections> + <slots> + <slot>doSelectContaminantSource()</slot> + <slot>doSelectFastaFile()</slot> + <slot>doClearList()</slot> + </slots> <buttongroups> <buttongroup name="contaminant_source_buttongroup"/> </buttongroups> diff --git a/src/gui/widgets/contaminant_widget/contaminantwidget.cpp b/src/gui/widgets/contaminant_widget/contaminantwidget.cpp index ab94e6497..ee3275cc5 100644 --- a/src/gui/widgets/contaminant_widget/contaminantwidget.cpp +++ b/src/gui/widgets/contaminant_widget/contaminantwidget.cpp @@ -32,7 +32,9 @@ #include "ui_contaminant_widget.h" #include <QDebug> - +#include <pappsomspp/pappsoexception.h> +#include <QSettings> +#include <QFileDialog> ContaminantWidget::ContaminantWidget(QWidget * parent): QWidget(parent), @@ -45,6 +47,8 @@ ContaminantWidget::ContaminantWidget(QWidget * parent): ui->contaminant_database_listview->setModel(_p_fasta_str_li); QItemSelectionModel * selection_model = ui->contaminant_database_listview->selectionModel(); ui->contaminant_database_listview->setSelectionMode(QAbstractItemView::MultiSelection); + + doSelectContaminantSource(); qDebug() << "ContaminantWidget::ContaminantWidget end"; } @@ -61,13 +65,10 @@ void ContaminantWidget::setRegexpContaminantPattern(const QString & pattern) { ui->contaminant_protein_regexp_line_edit->setText(pattern); } -const QString ContaminantWidget::getRegexpContaminant() const { - - return ui->contaminant_protein_regexp_line_edit->text(); -} void ContaminantWidget::setFastaFileList(std::vector<FastaFileSp> fasta_file_list) { + _fasta_file_list = fasta_file_list; _p_fasta_str_li->removeRows(0, _p_fasta_str_li->rowCount()); for (FastaFileSp fasta_file : fasta_file_list ) { @@ -80,3 +81,92 @@ void ContaminantWidget::setFastaFileList(std::vector<FastaFileSp> fasta_file_lis } } + +void ContaminantWidget::getProjectContaminants(const Project * p_project) { + ui->contaminant_regexp_radiobutton->setChecked(true); + ui->contaminant_database_listview->setVisible(false); + if (p_project->getProteinStore().getContaminantFastaFileList().size() > 0) { + ui->contaminant_file_radiobutton->setChecked(true); + ui->contaminant_protein_regexp_line_edit->setVisible(false); + ui->contaminant_database_listview->setVisible(true); + } + + ui->contaminant_protein_regexp_line_edit->setText(p_project->getProteinStore().getRegexpContaminant().pattern()); + + this->setFastaFileList( p_project->getFastaFileStore().getFastaFileList()); + + ui->control_list_widget->setVisible(false); + _no_project = false; +} + +void ContaminantWidget::setProjectContaminants(Project * p_project) { + qDebug() << "ContaminantWidget::setProjectContaminants begin"; + if (ui->contaminant_file_radiobutton->isChecked()) { + QModelIndexList index_list = ui->contaminant_database_listview->selectionModel()->selectedIndexes(); + p_project->getProteinStore().clearContaminants(); + if (index_list.size() > 0) { + for (QModelIndex index :index_list) { + if (index.data(Qt::UserRole).canConvert<FastaFile *>()) { + FastaFile * p_fasta_file = index.data(Qt::UserRole).value<FastaFile *>(); + p_fasta_file->setContaminants(p_project->getProteinStore()); + } + else { + throw pappso::PappsoException(QObject::tr("can not convert to FastaFile index.data().canConvert<FastaFile *>()")); + } + } + } + + if (_no_project) { + ui->control_list_widget->setVisible(true); + } + } + else { + p_project->getProteinStore().setRegexpContaminantPattern(ui->contaminant_protein_regexp_line_edit->text()); + ui->control_list_widget->setVisible(false); + } + qDebug() << "ContaminantWidget::setProjectContaminants end"; +} + + +void ContaminantWidget::doSelectContaminantSource() { + qDebug() << "ContaminantWidget::doSelectContaminantSource begin"; + ui->contaminant_database_listview->setVisible(false); + ui->contaminant_protein_regexp_line_edit->setVisible(false); + if (ui->contaminant_file_radiobutton->isChecked()) { + ui->contaminant_database_listview->setVisible(true); + } + else { + ui->contaminant_protein_regexp_line_edit->setVisible(true); + } + qDebug() << "ContaminantWidget::doSelectContaminantSource end"; +} + + +void ContaminantWidget::doSelectFastaFile() { + try { + QSettings settings; + QString default_fasta_location = settings.value("path/fastafiles_directory", "").toString(); + + QStringList filenames = QFileDialog::getOpenFileNames(this,tr("FASTA files"),default_fasta_location, + tr("FASTA files (*.fasta);;all files (*)") ); + + if (filenames.size() > 0) { + settings.setValue("path/fastafiles_directory", QFileInfo(filenames[0]).absolutePath()); + } + + std::vector<FastaFileSp> fasta_file_list; + for (QString filename :filenames) { + fasta_file_list.push_back(std::make_shared<FastaFile>(filename)); + } + + this->setFastaFileList(fasta_file_list); + + } + catch (pappso::PappsoException & error) { + //QMessageBox::warning(this, + // tr("Error choosing identification result files : %1").arg(error.qwhat()), error); + } +} +void ContaminantWidget::doClearList() { + _p_fasta_str_li->removeRows( 0, _p_fasta_str_li->rowCount() ); +} diff --git a/src/gui/widgets/contaminant_widget/contaminantwidget.h b/src/gui/widgets/contaminant_widget/contaminantwidget.h index 6971cd121..5ed5d73a3 100644 --- a/src/gui/widgets/contaminant_widget/contaminantwidget.h +++ b/src/gui/widgets/contaminant_widget/contaminantwidget.h @@ -34,6 +34,7 @@ #include <QWidget> #include <QStandardItemModel> #include "../../../files/fastafile.h" +#include "../../../core/project.h" namespace Ui { @@ -50,19 +51,27 @@ public: void setRegexpContaminantPattern(const QString & pattern); - - const QString getRegexpContaminant() const; void setFastaFileList(std::vector<FastaFileSp> fasta_file_list); + + void setProjectContaminants(Project * p_project); + void getProjectContaminants(const Project * p_project); public slots: + void doSelectContaminantSource(); + void doSelectFastaFile(); + void doClearList(); signals: private: Ui::ContaminantWidget *ui; + bool _no_project = true; + QStandardItemModel * _p_fasta_str_li; + + std::vector<FastaFileSp> _fasta_file_list; }; diff --git a/src/gui/workerthread.cpp b/src/gui/workerthread.cpp index 093159823..d7e6e460f 100644 --- a/src/gui/workerthread.cpp +++ b/src/gui/workerthread.cpp @@ -62,6 +62,7 @@ WorkerThread::WorkerThread(MainWindow * p_main_window) connect(p_main_window, &MainWindow::operateXpipFile, this,&WorkerThread::doXpipFileLoad); connect(p_main_window, &MainWindow::operateWritingXpipFile, this,&WorkerThread::doWritingXpipFile); connect(this, &WorkerThread::projectReady, p_main_window,&MainWindow::doProjectReady); + connect(this, &WorkerThread::loadingResultsFinished, p_main_window,&MainWindow::doLoadingResultsReady); connect(p_main_window, &MainWindow::operateLoadingResults, this,&WorkerThread::doLoadingResults); @@ -361,8 +362,8 @@ void WorkerThread::doLoadingResults(bool is_individual, AutomaticFilterParameter emit loadingMessage(tr("filtering proteins")); project_sp.get()->updateAutomaticFilters(param); - qDebug() << "WorkerThread::doLoadingResults emit projectReady(project_sp) "; - emit projectReady(project_sp); + qDebug() << "WorkerThread::doLoadingResults emit loadingResultsFinished(project_sp) "; + emit loadingResultsFinished(project_sp); } catch (pappso::PappsoException & error) { diff --git a/src/gui/workerthread.h b/src/gui/workerthread.h index 35ccd0e1d..8ecd9af72 100644 --- a/src/gui/workerthread.h +++ b/src/gui/workerthread.h @@ -72,6 +72,7 @@ public slots: signals: void loadingMessage(QString message); void projectReady(ProjectSp project_sp); + void loadingResultsFinished(ProjectSp project_sp); void projectNotReady(QString error); void groupingFinished(); void groupingOnIdentificationFinished(IdentificationGroup * p_identification_group); -- GitLab