diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9d83c28381795063e2aaf2c1413a7bf8b640d8bf..150a5ff3cc0d897026c2f2ccb048ca245c3e04b0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -71,6 +71,7 @@ SET(CPP_FILES
   gui/peptide_detail_view/spectrum_widget/spectrumpainter.cpp
   input/xpipsaxhandler.cpp
   input/xtandemsaxhandler.cpp
+  output/masschroqml.cpp
   utils/identificationdatasourcestore.cpp
   utils/groupstore.cpp
   utils/msrunstore.cpp
diff --git a/src/core/msrun.cpp b/src/core/msrun.cpp
index f5685957b9625809884c9781f20e25d781a8f34f..38e7c45412eff029c20ef1eb67da290ffc4bfe20 100644
--- a/src/core/msrun.cpp
+++ b/src/core/msrun.cpp
@@ -61,3 +61,7 @@ const QString & MsRun::getXmlId() const {
 const QString & MsRun::getFilename() const {
     return _location;
 }
+
+MzFormat MsRun::getMzFormat() const {
+    return _mz_format;
+}
diff --git a/src/core/msrun.h b/src/core/msrun.h
index 5262b2bead094bfff276405ce12ac683491334eb..40604c926839d3297300452b3b05cabfee134014 100644
--- a/src/core/msrun.h
+++ b/src/core/msrun.h
@@ -34,6 +34,7 @@
 
 #include <memory>
 #include <QString>
+#include "../utils/types.h"
 
 class MsRun;
 typedef std::shared_ptr<MsRun> MsRunSp;
@@ -50,10 +51,13 @@ public:
     
     const QString & getFilename() const;
     const QString & getXmlId() const;
+    
+    MzFormat getMzFormat() const;
 private :
     QString _xml_id;
     QString _location;
     QString _name;
+    MzFormat _mz_format=MzFormat::mzXML;
 };
 
 #endif // MSRUN_H
diff --git a/src/core/project.cpp b/src/core/project.cpp
index 210b0e11c5c8f96a2bb61ee06ea109d0884c3276..0437c22e6ddcedb7006334894d7f776bccc7f511 100644
--- a/src/core/project.cpp
+++ b/src/core/project.cpp
@@ -122,12 +122,6 @@ void Project::readXpipFile(QFileInfo xpip_fileinfo) {
 
 }
 
-IdentificationGroup* Project::getCurrentIdentificationGroupP() const {
-
-    qDebug() << "Project::getCurrentIdentificationGroupP begin " << _p_current_identification_group;
-    return _p_current_identification_group;
-}
-
 
 void Project::startGrouping() {
     for (auto & p_id_group : _identification_goup_list) {
diff --git a/src/core/project.h b/src/core/project.h
index 3d04785b86604291452b4cc7f2594550feff9e7a..cbf721250a1cde53cc6ee525f730cebf96057a72 100644
--- a/src/core/project.h
+++ b/src/core/project.h
@@ -51,7 +51,6 @@ public:
     IdentificationDataSourceStore & getIdentificationDataSourceStore();
     void readXpipFile(QFileInfo xpip_source);
     IdentificationGroup* newIdentificationGroup();
-    IdentificationGroup* getCurrentIdentificationGroupP() const;
 
     /** @brief validate or invalidate peptides and proteins based automatic filters and manual checks
      * */
diff --git a/src/gui/main.ui b/src/gui/main.ui
index 8c36b0b947867c06150e1f9cff2893583573db34..4fd14c2e2d57770d32a465baba4cf79719a082c9 100644
--- a/src/gui/main.ui
+++ b/src/gui/main.ui
@@ -26,15 +26,25 @@
      <x>0</x>
      <y>0</y>
      <width>463</width>
-     <height>23</height>
+     <height>25</height>
     </rect>
    </property>
    <widget class="QMenu" name="menuFile">
     <property name="title">
      <string>F&amp;ile</string>
     </property>
+    <widget class="QMenu" name="menuExport_files">
+     <property name="title">
+      <string>Export files</string>
+     </property>
+     <addaction name="actionFasta"/>
+     <addaction name="actionMassChroQ"/>
+     <addaction name="actionSpreadsheet"/>
+    </widget>
     <addaction name="actionLoad_results"/>
     <addaction name="actionLoad"/>
+    <addaction name="separator"/>
+    <addaction name="menuExport_files"/>
    </widget>
    <addaction name="menuFile"/>
   </widget>
@@ -46,7 +56,22 @@
   </action>
   <action name="actionLoad_results">
    <property name="text">
-    <string>Load results</string>
+    <string>Load &amp;results</string>
+   </property>
+  </action>
+  <action name="actionFasta">
+   <property name="text">
+    <string>Fasta</string>
+   </property>
+  </action>
+  <action name="actionMassChroQ">
+   <property name="text">
+    <string>MassChroQ</string>
+   </property>
+  </action>
+  <action name="actionSpreadsheet">
+   <property name="text">
+    <string>Spreadsheet</string>
    </property>
   </action>
  </widget>
@@ -86,9 +111,26 @@
     </hint>
    </hints>
   </connection>
+  <connection>
+   <sender>actionMassChroQ</sender>
+   <signal>triggered()</signal>
+   <receiver>Main</receiver>
+   <slot>doActionMassChroQ()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>-1</x>
+     <y>-1</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>231</x>
+     <y>191</y>
+    </hint>
+   </hints>
+  </connection>
  </connections>
  <slots>
   <slot>selectXpipFile()</slot>
   <slot>loadResults()</slot>
+  <slot>doActionMassChroQ()</slot>
  </slots>
 </ui>
diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp
index 023c091235555831bfea48cd45cff6bb19741704..d4a10d9324fae909decbe0edafc4352563dc20d3 100644
--- a/src/gui/mainwindow.cpp
+++ b/src/gui/mainwindow.cpp
@@ -30,6 +30,7 @@
 
 #include "ui_main.h"
 #include <pappsomspp/pappsoexception.h>
+#include "../output/masschroqml.h"
 
 
 void XtpLoaderThread::doXpipFileLoad(QString filename) {
@@ -37,7 +38,7 @@ void XtpLoaderThread::doXpipFileLoad(QString filename) {
     try {
         QFileInfo new_xpip_file;
         new_xpip_file.setFile(filename);
-
+        emit loadingMessage(tr("loading XPIP file"));
 
         XpipFile xpip_file(new_xpip_file);
         ProjectSp project_sp = xpip_file.getProjectSp();
@@ -175,8 +176,10 @@ void MainWindow::doProjectReady(ProjectSp project_sp) {
 
     qDebug() << "MainWindow::doProjectReady begin";
     try {
+        _project_sp = project_sp;
         doDisplayLoadingMessage(tr("grouping proteins"));
         project_sp.get()->startGrouping();
+        doDisplayLoadingMessage(tr("grouping proteins finished"));
     }
     catch (pappso::PappsoException & error) {
         viewError(tr("Error while grouping :\n%1").arg(error.qwhat()));
@@ -219,3 +222,27 @@ void MainWindow::selectXpipFile() {
 
 }
 
+void MainWindow::doActionMassChroQ() {
+    qDebug() << "MainWindow::doActionMassChroQ begin";try {
+        QSettings settings;
+        QString default_location = settings.value("path/mcqfile", "").toString();
+
+        QString filename = QFileDialog::getSaveFileName(this, tr("Save MassChroqML file"),
+                           QString("%1/untitled.masschroqml").arg(default_location),
+                           tr("MassChroqML (*.masschroqml)"));
+
+        if (filename.isEmpty()) {
+            return;
+        }
+
+        settings.setValue("path/mcqfile", QFileInfo(filename).absolutePath());
+        MassChroQml output(filename);
+        output.write(_project_sp);
+        output.close();
+        //emit operateXpipFile(filename);
+    }
+    catch (pappso::PappsoException & error) {
+        viewError(tr("Error while writing MassChroqML file :\n%1").arg(error.qwhat()));
+    }
+    qDebug() << "MainWindow::doActionMassChroQ end";
+}
diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h
index 43946b49ae262f35426e49c8afff5cb425080b3e..02eb1617a3f571ce551a56ea1d0d426e3a88218e 100644
--- a/src/gui/mainwindow.h
+++ b/src/gui/mainwindow.h
@@ -78,6 +78,7 @@ public:
 public slots:
     void loadResults();
     void selectXpipFile();
+    void doActionMassChroQ();
     void doDisplayLoadingMessage(QString message);
     void doProjectReady(ProjectSp project_sp);
     void doProjectNotReady(QString error);
diff --git a/src/output/masschroqml.cpp b/src/output/masschroqml.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b4492759bbc8cd413e88dcd1fb86c8b4ef1647dc
--- /dev/null
+++ b/src/output/masschroqml.cpp
@@ -0,0 +1,188 @@
+/**
+ * \file output/masschroqml.cpp
+ * \date 7/4/2017
+ * \author Olivier Langella
+ * \brief MassChroQML writer
+ */
+
+/*******************************************************************************
+* Copyright (c) 2017 Olivier Langella <olivier.langella@u-psud.fr>.
+*
+* This file is part of XTPcpp.
+*
+*     XTPcpp is free software: you can redistribute it and/or modify
+*     it under the terms of the GNU General Public License as published by
+*     the Free Software Foundation, either version 3 of the License, or
+*     (at your option) any later version.
+*
+*     XTPcpp 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 General Public License for more details.
+*
+*     You should have received a copy of the GNU General Public License
+*     along with XTPcpp.  If not, see <http://www.gnu.org/licenses/>.
+*
+* Contributors:
+*     Olivier Langella <olivier.langella@u-psud.fr> - initial API and implementation
+******************************************************************************/
+
+#include "masschroqml.h"
+#include <pappsomspp/pappsoexception.h>
+#include <pappsomspp/utils.h>
+#include <pappsomspp/grouping/grpprotein.h>
+
+MassChroQml::MassChroQml(const QString & out_filename)
+{
+    //_p_digestion_pipeline = p_digestion_pipeline;
+
+    //_mzidentml = "http://psidev.info/psi/pi/mzIdentML/1.1";
+    QString complete_out_filename = out_filename;
+    _output_file = new QFile(complete_out_filename);
+
+    if (_output_file->open(QIODevice::WriteOnly))
+    {
+        _output_stream = new QXmlStreamWriter();
+        _output_stream->setDevice(_output_file);
+    } else
+    {
+        throw pappso::PappsoException(QObject::tr("error : cannot open the MassChroqML output file : %1\n").arg(out_filename));
+    }
+
+    _output_stream->setAutoFormatting(true);
+    _output_stream->writeStartDocument("1.0");
+
+
+}
+
+MassChroQml::~MassChroQml()
+{
+    delete _output_file;
+    delete _output_stream;
+}
+
+void MassChroQml::close() {
+    _output_stream->writeEndDocument();
+    _output_file->close();
+}
+
+void MassChroQml::write(ProjectSp sp_project) {
+
+    _sp_project = sp_project;
+    if (_sp_project.get() == nullptr) {
+        throw pappso::PappsoException(QObject::tr("Error writing MassChroqML file :\n project is empty"));
+    }
+    
+    //<masschroq>
+    _output_stream->writeStartElement("masschroq");
+    _output_stream->writeAttribute("type","input");
+    _output_stream->writeAttribute("version","2.2");
+    //_output_stream->writeAttribute("creationDate", QDateTime::currentDateTime().toString( Qt::ISODate));
+    _output_stream->writeNamespace("http://www.w3.org/2001/XMLSchema-instance","xsi");
+    //_output_stream->writeNamespace("http://www.w3.org/2001/XMLSchema-instance","xsi");
+    _output_stream->writeAttribute("xmlns","http://pappso.inra.fr/xsd/masschroqml/2.2");
+    //xsi:schemaLocation="http://psidev.info/psi/pi/mzIdentML/1.1 http://www.psidev.info/files/mzIdentML1.1.0.xsd"
+    _output_stream->writeAttribute("http://www.w3.org/2001/XMLSchema-instance","schemaLocation","http://pappso.inra.fr/xsd/masschroqml/2.2 http://pappso.inra.fr/xsd/masschroq-2.2.xsd");
+
+    // <rawdata><!-- time_values_dir="directory" to read retention time corrections-->
+    _output_stream->writeStartElement("rawdata");
+    _output_stream->writeComment("time_values_dir=\"directory\" to read retention time corrections");
+
+    std::vector<MsRunSp> msrun_list = _sp_project.get()->getMsRunStore().getMsRunList();
+    for (MsRunSp & msrun : msrun_list) {
+
+        //<data_file id="samp0" format="mzxml" path="bsa1.mzXML" type="centroid" />
+        _output_stream->writeStartElement("data_file");
+        _output_stream->writeAttribute("id",msrun.get()->getXmlId());
+        if(msrun.get()->getMzFormat() == MzFormat::mzXML) {
+            _output_stream->writeAttribute("format","mzxml");
+        }
+        _output_stream->writeAttribute("path",msrun.get()->getFilename());
+        _output_stream->writeAttribute("type","centroid");
+        // <data_file id="samp1" format="mzxml" path="bsa2.mzXML" type="profile" />
+        _output_stream->writeEndElement();
+    }
+    // <data_file id="samp2" format="mzml" path="/home/user/bsa3.mzml"      type="profile" />
+//<data_file id="samp3" format="mzml" path="/home/user/bsa4.mzml"             type="profile" />
+    // _output_stream.writeEndElement();
+    //             </rawdata>
+    _output_stream->writeEndElement();
+
+
+    writeGroups();
+    writeProteinList();
+    writePeptideList();
+}
+void MassChroQml::writePeptideList() {
+//<peptide_list>
+    _output_stream->writeStartElement("peptide_list");
+    /*
+		<peptide id="pep0" mh="1463.626" mods="114.08" prot_ids="P1.1"
+			seq="TCVADESHAGCEK">
+            <modifications><!-- this tag is optional but gives an exact mass computation -->
+                <psimod at="2" acc="MOD:00397"></psimod>
+                <psimod at="11" acc="MOD:00397"></psimod>
+            </modifications>
+			<observed_in data="samp0" scan="655" z="2" />
+			<observed_in data="samp1" scan="798" z="2" />
+		</peptide>
+		<peptide id="pep1" mh="1103.461" mods="57.04" prot_ids="P1.1"
+			seq="ADESHAGCEK">
+            <modifications><!-- this tag is optional but gives an exact mass computation -->
+                <psimod at="8" acc="MOD:00397"></psimod>
+            </modifications>
+			<observed_in data="samp3" scan="663" z="2" />
+		</peptide>*/
+	//</peptide_list>
+    _output_stream->writeEndElement();
+}
+	
+void MassChroQml::writeGroups() {
+//<groups>
+    _output_stream->writeStartElement("groups");
+    //<group data_ids="samp0 samp1" id="G1" />
+    _output_stream->writeStartElement("group");
+    _output_stream->writeAttribute("id",QString("fractiona1"));
+    std::vector<MsRunSp> msrun_list = _sp_project.get()->getMsRunStore().getMsRunList();
+    QStringList list;
+    for (MsRunSp & msrun : msrun_list) {
+        list << msrun.get()->getXmlId();
+    }
+    _output_stream->writeAttribute("data_ids",list.join(" "));
+    _output_stream->writeEndElement();
+    //<group data_ids="samp2 samp3" id="G2" />
+//	</groups>
+    _output_stream->writeEndElement();
+}
+
+void MassChroQml::writeProteinList() {
+//<protein_list>
+    _output_stream->writeStartElement("protein_list");
+    std::vector<IdentificationGroup *> identification_list = _sp_project.get()->getIdentificationGroupList();
+    if (identification_list.size() == 0) {
+        throw pappso::PappsoException(QObject::tr("Error writing MassChroqML file :\n no protein list"));
+    }
+    if (identification_list.size() > 1) {
+        throw pappso::PappsoException(QObject::tr("Error writing MassChroqML file :\n only available in combine mode"));
+    }
+    _p_identification_group = identification_list[0];
+    for (ProteinMatch * p_protein_match :_p_identification_group->getProteinMatchList()) {
+        if (!p_protein_match->isGrouped()) continue;
+		//<protein desc="conta|P02769|ALBU_BOVIN SERUM ALBUMIN PRECURSOR."
+		//	id="P1.1" />
+        pappso::GrpProteinSp grp_protein = p_protein_match->getGrpProteinSp();
+        if (grp_protein.get()->getRank() == 1) {
+        _output_stream->writeStartElement("protein");
+        _output_stream->writeAttribute("id",grp_protein.get()->getGroupingId());
+        QStringList list;
+        list << p_protein_match->getProteinXtpSp().get()->getAccession();
+        list << p_protein_match->getProteinXtpSp().get()->getDescription();
+        _output_stream->writeAttribute("desc",list.join(" "));
+		//<protein desc="conta|P02770|ALBU_RAT SERUM ALBUMIN PRECURSOR."
+		//	id="P1.2" />
+        _output_stream->writeEndElement();
+        }
+    }
+	//</protein_list>
+	_output_stream->writeEndElement();
+}
diff --git a/src/output/masschroqml.h b/src/output/masschroqml.h
new file mode 100644
index 0000000000000000000000000000000000000000..47559be08346f242c118f6b399bd9742599a297b
--- /dev/null
+++ b/src/output/masschroqml.h
@@ -0,0 +1,57 @@
+/**
+ * \file output/masschroqml.h
+ * \date 7/4/2017
+ * \author Olivier Langella
+ * \brief MassChroQML writer
+ */
+
+/*******************************************************************************
+* Copyright (c) 2017 Olivier Langella <olivier.langella@u-psud.fr>.
+*
+* This file is part of XTPcpp.
+*
+*     XTPcpp is free software: you can redistribute it and/or modify
+*     it under the terms of the GNU General Public License as published by
+*     the Free Software Foundation, either version 3 of the License, or
+*     (at your option) any later version.
+*
+*     XTPcpp 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 General Public License for more details.
+*
+*     You should have received a copy of the GNU General Public License
+*     along with XTPcpp.  If not, see <http://www.gnu.org/licenses/>.
+*
+* Contributors:
+*     Olivier Langella <olivier.langella@u-psud.fr> - initial API and implementation
+******************************************************************************/
+
+#ifndef MASSCHROQML_H
+#define MASSCHROQML_H
+
+#include <QXmlStreamWriter>
+#include <QFile>
+#include <QString>
+#include "../core/project.h"
+
+class MassChroQml
+{
+    public:
+    MassChroQml(const QString & out_filename);
+    ~MassChroQml();
+
+    void write(ProjectSp sp_project);
+    void close();
+private:
+    void writeGroups();
+    void writeProteinList();
+    void writePeptideList();
+private :
+    QFile * _output_file;
+    QXmlStreamWriter * _output_stream;
+    ProjectSp _sp_project;
+    IdentificationGroup * _p_identification_group;
+};
+
+#endif // MASSCHROQML_H
diff --git a/src/utils/msrunstore.cpp b/src/utils/msrunstore.cpp
index 1fee9ca9e8418400fe66135d1d8e8a0e353729f5..ee6c13061885896b559066d3e86a9f1f70321062 100644
--- a/src/utils/msrunstore.cpp
+++ b/src/utils/msrunstore.cpp
@@ -30,6 +30,7 @@
 
 #include "msrunstore.h"
 #include <pappsomspp/exception/exceptionnotfound.h>
+#include <pappsomspp/utils.h>
 
 MsRunStore::MsRunStore()
 {
@@ -49,9 +50,19 @@ MsRunSp MsRunStore::getInstance(const QString & location) {
     }
     else {
         MsRunSp p_xtfile = std::make_shared<MsRun>(location);
+        p_xtfile.get()->setXmlId(QString("samp%1").arg(pappso::Utils::getLexicalOrderedString(_map_msrun.size())));
         _map_msrun.insert(std::pair< QString, MsRunSp >(location, p_xtfile));
         return p_xtfile;
 
     }
     throw pappso::ExceptionNotFound(QObject::tr("Ms resource %1 not found").arg(location));
 }
+
+
+std::vector<MsRunSp> MsRunStore::getMsRunList() const {
+    std::vector<MsRunSp> msrun_list;
+    for (auto & msrun_pair :_map_msrun) {
+        msrun_list.push_back(msrun_pair.second);
+    }
+    return msrun_list;
+}
diff --git a/src/utils/msrunstore.h b/src/utils/msrunstore.h
index 27e6df6f26cc0bd37c3d5ecee7b294223af9f036..0741d45a7777a547b31f1de3683870b4247aa3c1 100644
--- a/src/utils/msrunstore.h
+++ b/src/utils/msrunstore.h
@@ -33,6 +33,7 @@
 
 #include <QString>
 #include <map>
+#include <vector>
 #include "../core/msrun.h"
 
 class MsRunStore
@@ -42,6 +43,8 @@ public:
     ~MsRunStore();
 
     MsRunSp getInstance(const QString & location);
+    
+    std::vector<MsRunSp> getMsRunList() const;
 private:
     std::map<QString, MsRunSp> _map_msrun;
 };
diff --git a/src/utils/types.h b/src/utils/types.h
index 3bf0931e26f444e13db4fe087d87c5e9ae4face8..7a5be71be3a1735e6984713699b0ef4356a741de 100644
--- a/src/utils/types.h
+++ b/src/utils/types.h
@@ -37,6 +37,15 @@ enum class GroupingType {
 };
 
 
+/** \def MzFormat mz data file format types
+ *
+ */
+
+enum class MzFormat {
+     mzML, ///< mzML
+     mzXML, ///< mzXML
+};
+
 /** \def ProteinListColumn list of available fields to display in protein list
  *
  */