diff --git a/CycloBranch/CycloBranch-Linux.pro b/CycloBranch/CycloBranch-Linux.pro index d9aaa86..4712eb1 100644 --- a/CycloBranch/CycloBranch-Linux.pro +++ b/CycloBranch/CycloBranch-Linux.pro @@ -13,8 +13,7 @@ MOC_DIR = moc/ # Input RESOURCES = images.qrc -HEADERS += core/cAllocator.h \ - core/cBrick.h \ +HEADERS += core/cBrick.h \ core/cBricksDatabase.h \ core/cCandidate.h \ core/cCandidateSet.h \ @@ -35,9 +34,11 @@ HEADERS += core/cAllocator.h \ gui/cAboutWidget.h \ gui/cBranchCyclicWidget.h \ gui/cBranchedWidget.h \ + gui/cBricksDatabaseProxyModel.h \ gui/cBricksDatabaseWidget.h \ + gui/cCheckBoxDelegate.h \ + gui/cComboBoxDelegate.h \ gui/cCyclicWidget.h \ - gui/cDelegate.h \ gui/cDrawPeptideWidget.h \ gui/cEventFilter.h \ gui/cExportDialog.h \ @@ -50,12 +51,19 @@ HEADERS += core/cAllocator.h \ gui/cLinearWidget.h \ gui/cMainThread.h \ gui/cMainWindow.h \ + gui/cMainWindowProxyModel.h \ + gui/cModificationsProxyModel.h \ gui/cModificationsWidget.h \ + gui/cMultipleButtonDelegate.h \ gui/cParametersWidget.h \ + gui/cSequenceDatabaseProxyModel.h \ gui/cSequenceDatabaseWidget.h \ + gui/cSpectrumDetailProxyModel.h \ gui/cSpectrumDetailWidget.h \ gui/cSpectrumSceneWidget.h \ + gui/cSummaryPeaksTableProxyModel.h \ gui/cSummaryPeaksTableWidget.h \ + gui/cViewButtonDelegate.h \ parallel/cGraphReaderThread.h \ parallel/cSpectrumComparatorThread.h SOURCES += core/cBrick.cpp \ @@ -79,9 +87,11 @@ SOURCES += core/cBrick.cpp \ gui/cAboutWidget.cpp \ gui/cBranchCyclicWidget.cpp \ gui/cBranchedWidget.cpp \ + gui/cBricksDatabaseProxyModel.cpp \ gui/cBricksDatabaseWidget.cpp \ + gui/cCheckBoxDelegate.cpp \ + gui/cComboBoxDelegate.cpp \ gui/cCyclicWidget.cpp \ - gui/cDelegate.cpp \ gui/cDrawPeptideWidget.cpp \ gui/cEventFilter.cpp \ gui/cExportDialog.cpp \ @@ -94,12 +104,19 @@ SOURCES += core/cBrick.cpp \ gui/cLinearWidget.cpp \ gui/cMainThread.cpp \ gui/cMainWindow.cpp \ + gui/cMainWindowProxyModel.cpp \ + gui/cModificationsProxyModel.cpp \ gui/cModificationsWidget.cpp \ + gui/cMultipleButtonDelegate.cpp \ gui/cParametersWidget.cpp \ + gui/cSequenceDatabaseProxyModel.cpp \ gui/cSequenceDatabaseWidget.cpp \ + gui/cSpectrumDetailProxyModel.cpp \ gui/cSpectrumDetailWidget.cpp \ gui/cSpectrumSceneWidget.cpp \ + gui/cSummaryPeaksTableProxyModel.cpp \ gui/cSummaryPeaksTableWidget.cpp \ + gui/cViewButtonDelegate.cpp \ parallel/cGraphReaderThread.cpp \ parallel/cSpectrumComparatorThread.cpp \ main.cpp diff --git a/CycloBranch/CycloBranch-MacOSX.pro b/CycloBranch/CycloBranch-MacOSX.pro index a20edbc..7f07270 100644 --- a/CycloBranch/CycloBranch-MacOSX.pro +++ b/CycloBranch/CycloBranch-MacOSX.pro @@ -21,8 +21,7 @@ ICON = images/cb.icns # Input RESOURCES = images.qrc -HEADERS += core/cAllocator.h \ - core/cBrick.h \ +HEADERS += core/cBrick.h \ core/cBricksDatabase.h \ core/cCandidate.h \ core/cCandidateSet.h \ @@ -43,9 +42,11 @@ HEADERS += core/cAllocator.h \ gui/cAboutWidget.h \ gui/cBranchCyclicWidget.h \ gui/cBranchedWidget.h \ + gui/cBricksDatabaseProxyModel.h \ gui/cBricksDatabaseWidget.h \ + gui/cCheckBoxDelegate.h \ + gui/cComboBoxDelegate.h \ gui/cCyclicWidget.h \ - gui/cDelegate.h \ gui/cDrawPeptideWidget.h \ gui/cEventFilter.h \ gui/cExportDialog.h \ @@ -58,12 +59,19 @@ HEADERS += core/cAllocator.h \ gui/cLinearWidget.h \ gui/cMainThread.h \ gui/cMainWindow.h \ + gui/cMainWindowProxyModel.h \ + gui/cModificationsProxyModel.h \ gui/cModificationsWidget.h \ + gui/cMultipleButtonDelegate.h \ gui/cParametersWidget.h \ + gui/cSequenceDatabaseProxyModel.h \ gui/cSequenceDatabaseWidget.h \ + gui/cSpectrumDetailProxyModel.h \ gui/cSpectrumDetailWidget.h \ gui/cSpectrumSceneWidget.h \ + gui/cSummaryPeaksTableProxyModel.h \ gui/cSummaryPeaksTableWidget.h \ + gui/cViewButtonDelegate.h \ parallel/cGraphReaderThread.h \ parallel/cSpectrumComparatorThread.h SOURCES += core/cBrick.cpp \ @@ -87,9 +95,11 @@ SOURCES += core/cBrick.cpp \ gui/cAboutWidget.cpp \ gui/cBranchCyclicWidget.cpp \ gui/cBranchedWidget.cpp \ + gui/cBricksDatabaseProxyModel.cpp \ gui/cBricksDatabaseWidget.cpp \ + gui/cCheckBoxDelegate.cpp \ + gui/cComboBoxDelegate.cpp \ gui/cCyclicWidget.cpp \ - gui/cDelegate.cpp \ gui/cDrawPeptideWidget.cpp \ gui/cEventFilter.cpp \ gui/cExportDialog.cpp \ @@ -102,12 +112,19 @@ SOURCES += core/cBrick.cpp \ gui/cLinearWidget.cpp \ gui/cMainThread.cpp \ gui/cMainWindow.cpp \ + gui/cMainWindowProxyModel.cpp \ + gui/cModificationsProxyModel.cpp \ gui/cModificationsWidget.cpp \ + gui/cMultipleButtonDelegate.cpp \ gui/cParametersWidget.cpp \ + gui/cSequenceDatabaseProxyModel.cpp \ gui/cSequenceDatabaseWidget.cpp \ + gui/cSpectrumDetailProxyModel.cpp \ gui/cSpectrumDetailWidget.cpp \ gui/cSpectrumSceneWidget.cpp \ + gui/cSummaryPeaksTableProxyModel.cpp \ gui/cSummaryPeaksTableWidget.cpp \ + gui/cViewButtonDelegate.cpp\ parallel/cGraphReaderThread.cpp \ parallel/cSpectrumComparatorThread.cpp \ main.cpp diff --git a/CycloBranch/CycloBranch.vcxproj b/CycloBranch/CycloBranch.vcxproj index 279e2b5..a52f013 100644 --- a/CycloBranch/CycloBranch.vcxproj +++ b/CycloBranch/CycloBranch.vcxproj @@ -177,15 +177,23 @@ true true + + true + true + true true - + true true - + + true + true + + true true @@ -241,14 +249,30 @@ true true + + true + true + + + true + true + true true + + true + true + true true + + true + true + true true @@ -257,6 +281,10 @@ true true + + true + true + true true @@ -265,10 +293,18 @@ true true + + true + true + true true + + true + true + @@ -291,15 +327,23 @@ true true + + true + true + true true - + true true - + + true + true + + true true @@ -355,14 +399,30 @@ true true + + true + true + + + true + true + true true + + true + true + true true + + true + true + true true @@ -371,6 +431,10 @@ true true + + true + true + true true @@ -379,16 +443,26 @@ true true + + true + true + true true + + true + true + + + + - @@ -401,18 +475,24 @@ + + + + + + + - @@ -429,6 +509,186 @@ + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cBricksDatabaseProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cBricksDatabaseProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cBricksDatabaseProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cBricksDatabaseProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtSvg" "-I$(QTDIR)\include\QtPrintSupport" "-IC:\boost_1_57_0" "-IC:\xerces-c-3.1.1\include" + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cMultipleButtonDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cMultipleButtonDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cMultipleButtonDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cMultipleButtonDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtSvg" "-I$(QTDIR)\include\QtPrintSupport" "-IC:\boost_1_57_0" "-IC:\xerces-c-3.1.1\include" + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cModificationsProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cModificationsProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cModificationsProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cModificationsProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtSvg" "-I$(QTDIR)\include\QtPrintSupport" "-IC:\boost_1_57_0" "-IC:\xerces-c-3.1.1\include" + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cViewButtonDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cViewButtonDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cViewButtonDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cViewButtonDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtSvg" "-I$(QTDIR)\include\QtPrintSupport" "-IC:\boost_1_57_0" "-IC:\xerces-c-3.1.1\include" + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cComboBoxDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cComboBoxDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cComboBoxDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cComboBoxDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtSvg" "-I$(QTDIR)\include\QtPrintSupport" "-IC:\boost_1_57_0" "-IC:\xerces-c-3.1.1\include" + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cCheckBoxDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cCheckBoxDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cCheckBoxDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cCheckBoxDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtSvg" "-I$(QTDIR)\include\QtPrintSupport" "-IC:\boost_1_57_0" "-IC:\xerces-c-3.1.1\include" + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSequenceDatabaseProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSequenceDatabaseProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSequenceDatabaseProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSequenceDatabaseProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtSvg" "-I$(QTDIR)\include\QtPrintSupport" "-IC:\boost_1_57_0" "-IC:\xerces-c-3.1.1\include" + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cMainWindowProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cMainWindowProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cMainWindowProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cMainWindowProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtSvg" "-I$(QTDIR)\include\QtPrintSupport" "-IC:\boost_1_57_0" "-IC:\xerces-c-3.1.1\include" + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSpectrumDetailProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSpectrumDetailProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSpectrumDetailProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSpectrumDetailProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtSvg" "-I$(QTDIR)\include\QtPrintSupport" "-IC:\boost_1_57_0" "-IC:\xerces-c-3.1.1\include" + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSummaryPeaksTableProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSummaryPeaksTableProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSummaryPeaksTableProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSummaryPeaksTableProxyModel.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtSvg" "-I$(QTDIR)\include\QtPrintSupport" "-IC:\boost_1_57_0" "-IC:\xerces-c-3.1.1\include" + $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cImageWindowWidget.h... @@ -519,24 +779,6 @@ .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtSvg" "-I$(QTDIR)\include\QtPrintSupport" "-IC:\boost_1_57_0" "-IC:\xerces-c-3.1.1\include" - - $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing cDelegate.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" - $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing cDelegate.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" - $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing cDelegate.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" - $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing cDelegate.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtSvg" "-I$(QTDIR)\include\QtPrintSupport" "-IC:\boost_1_57_0" "-IC:\xerces-c-3.1.1\include" - $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cExportDialog.h... diff --git a/CycloBranch/CycloBranch.vcxproj.filters b/CycloBranch/CycloBranch.vcxproj.filters index 9be1365..b3a2ab5 100644 --- a/CycloBranch/CycloBranch.vcxproj.filters +++ b/CycloBranch/CycloBranch.vcxproj.filters @@ -281,15 +281,6 @@ Source Files\gui - - Generated Files\Debug - - - Generated Files\Release - - - Source Files\gui - Source Files\core @@ -341,6 +332,96 @@ Source Files\gui + + Source Files\gui + + + Generated Files\Debug + + + Generated Files\Release + + + Source Files\gui + + + Generated Files\Debug + + + Generated Files\Release + + + Source Files\gui + + + Generated Files\Debug + + + Generated Files\Release + + + Generated Files\Debug + + + Generated Files\Release + + + Source Files\gui + + + Generated Files\Debug + + + Generated Files\Release + + + Source Files\gui + + + Source Files\gui + + + Generated Files\Debug + + + Generated Files\Release + + + Source Files\gui + + + Generated Files\Debug + + + Generated Files\Release + + + Source Files\gui + + + Generated Files\Debug + + + Generated Files\Release + + + Source Files\gui + + + Generated Files\Debug + + + Generated Files\Release + + + Source Files\gui + + + Generated Files\Debug + + + Generated Files\Release + @@ -412,9 +493,6 @@ Header Files\gui - - Header Files\gui - Header Files\gui @@ -430,6 +508,36 @@ Header Files\gui + + Header Files\gui + + + Header Files\gui + + + Header Files\gui + + + Header Files\gui + + + Header Files\gui + + + Header Files\gui + + + Header Files\gui + + + Header Files\gui + + + Header Files\gui + + + Header Files\gui + @@ -474,9 +582,6 @@ Header Files\core - - Header Files\core - Header Files\core diff --git a/CycloBranch/core/cBrick.h b/CycloBranch/core/cBrick.h index 3a3ef83..1cb8ddc 100644 --- a/CycloBranch/core/cBrick.h +++ b/CycloBranch/core/cBrick.h @@ -26,16 +26,6 @@ enum eResidueLossType { }; -/** - \brief Precursor loss types. -*/ -enum eKetidePrecursorType { - ketide_precursor_h2o = 0, - ketide_precursor_h2, - ketide_precursor_h2o2 -}; - - /** \brief Get the number of bricks in a composition. \param composition string containing ids of bricks separated by '-' diff --git a/CycloBranch/core/cBricksDatabase.cpp b/CycloBranch/core/cBricksDatabase.cpp index c7cd9ae..d9eea9f 100644 --- a/CycloBranch/core/cBricksDatabase.cpp +++ b/CycloBranch/core/cBricksDatabase.cpp @@ -122,16 +122,14 @@ cBricksDatabase::cBricksDatabase() { } -int cBricksDatabase::loadFromPlainTextStream(ifstream &stream, string& errormessage, bool ignoreerrors) { +int cBricksDatabase::loadFromPlainTextStream(ifstream &stream, string& errormessage, bool ignoreerrors, bool skiph2blocks) { string s; cBrick b; size_t pos; double mass; -#if OLIGOKETIDES == 1 regex rx; string name; -#endif bool error = false; errormessage = ""; @@ -165,14 +163,12 @@ int cBricksDatabase::loadFromPlainTextStream(ifstream &stream, string& errormess break; } -#if OLIGOKETIDES == 1 name = b.getName(); rx = "^\\(-2H\\) "; if (regex_search(name, rx)) { b.setResidueLossType(h2_loss); } -#endif // load acronyms pos = s.find('\t'); @@ -213,7 +209,7 @@ int cBricksDatabase::loadFromPlainTextStream(ifstream &stream, string& errormess b.setReferences(s); // store brick - if (ignoreerrors || (!ignoreerrors && !b.empty())) { + if ((ignoreerrors || (!ignoreerrors && !b.empty())) && (!skiph2blocks || (skiph2blocks && (b.getResidueLossType() == h2o_loss)))) { // calculate mass from the summary formula.clear(); @@ -525,6 +521,19 @@ void cBricksDatabase::removeLastBrick() { } +string cBricksDatabase::calculateSummaryFromComposition(int brickid) { + cSummaryFormula formula; + vector items; + bricks[brickid].explodeToIntComposition(items); + + for (int i = 0; i < (int)items.size(); i++) { + formula.addFormula(bricks[items[i] - 1].getSummary()); + } + + return formula.getSummary(); +} + + void cBricksDatabase::store(ofstream& os) { int size; @@ -549,10 +558,7 @@ void cBricksDatabase::load(ifstream& is) { } -#if OLIGOKETIDES == 1 - - -bool cBricksDatabase::checkKetideBlocks(cBrick& brickseries) { +bool cBricksDatabase::checkKetideBlocks(cBrick& brickseries, bool regularblocksorder) { vector intcomposition; brickseries.explodeToIntComposition(intcomposition); @@ -560,6 +566,10 @@ bool cBricksDatabase::checkKetideBlocks(cBrick& brickseries) { return false; } + if (!regularblocksorder) { + return true; + } + int h2_blocks = 0; int h2o_blocks = 0; for (int i = 0; i < (int)intcomposition.size(); i++) { @@ -584,5 +594,3 @@ bool cBricksDatabase::checkKetideBlocks(cBrick& brickseries) { return false; } - -#endif \ No newline at end of file diff --git a/CycloBranch/core/cBricksDatabase.h b/CycloBranch/core/cBricksDatabase.h index 0cc5801..76dac2f 100644 --- a/CycloBranch/core/cBricksDatabase.h +++ b/CycloBranch/core/cBricksDatabase.h @@ -92,9 +92,10 @@ class cBricksDatabase { \param stream reference to an input file stream \param errormessage reference to a string where an error message might be stored \param ignoreerrors if true errors are ignored + \param skiph2blocks ignore ketide 2H loss blocks \retval int 0 when the database was successfully loaded, -1 when an error occurred (\a errormessage is filled up) */ - int loadFromPlainTextStream(ifstream &stream, string& errormessage, bool ignoreerrors); + int loadFromPlainTextStream(ifstream &stream, string& errormessage, bool ignoreerrors, bool skiph2blocks); /** @@ -210,6 +211,14 @@ class cBricksDatabase { void removeLastBrick(); + /** + \brief Calculate the summary formula of a composition. + \param brickid brick id + \retval string summary formula + */ + string calculateSummaryFromComposition(int brickid); + + /** \brief Store the structure into an output stream. \param os an output stream @@ -224,18 +233,13 @@ class cBricksDatabase { void load(ifstream& is); -#if OLIGOKETIDES == 1 - - /** \brief Check if the numbers of H2 loss and H2O loss blocks are correct. \param brickseries a tested combination of building blocks + \param regularblocksorder check regular order of ketide blocks \retval bool true when the numbers of blocks are correct */ - bool checkKetideBlocks(cBrick& brickseries); - - -#endif + bool checkKetideBlocks(cBrick& brickseries, bool regularblocksorder); }; diff --git a/CycloBranch/core/cCandidate.cpp b/CycloBranch/core/cCandidate.cpp index bd598ff..c783e19 100644 --- a/CycloBranch/core/cCandidate.cpp +++ b/CycloBranch/core/cCandidate.cpp @@ -41,7 +41,8 @@ void cCandidate::getPermutationsIter(cCandidateSet& permutations, vector } } else { - cCandidate c(currentcandidate, path, startmodifID, endmodifID, middlemodifID, branchstart, branchend); + cCandidate c(currentcandidate, path, startiontype, startmodifID, endmodifID, middlemodifID, branchstart, branchend); + c.setSummaryFormula(summary); permutations.getSet().insert(c); } } @@ -175,7 +176,7 @@ void cCandidate::getPartialBranchCyclicRotations(const string& composition, vect vector v; vector ne; v.push_back(s); - cCandidate c(v, ne, startmodifID, endmodifID, middlemodifID, (branchstart + count - i) % count, (branchend + count - i) % count); + cCandidate c(v, ne, startiontype, startmodifID, endmodifID, middlemodifID, (branchstart + count - i) % count, (branchend + count - i) % count); branchcyclicrotations.push_back(c); //cout << s << endl; } @@ -188,19 +189,19 @@ cCandidate::cCandidate() { } -cCandidate::cCandidate(vector& composition, vector& path, int startmodifID, int endmodifID, int middlemodifID, int middlepos) { +cCandidate::cCandidate(vector& composition, vector& path, eFragmentIonType startiontype, int startmodifID, int endmodifID, int middlemodifID, int middlepos) { clear(); - setCandidate(composition, path, startmodifID, endmodifID, middlemodifID, middlepos); + setCandidate(composition, path, startiontype, startmodifID, endmodifID, middlemodifID, middlepos); } -cCandidate::cCandidate(vector& composition, vector& path, int startmodifID, int endmodifID, int middlemodifID, int branchstart, int branchend) { +cCandidate::cCandidate(vector& composition, vector& path, eFragmentIonType startiontype, int startmodifID, int endmodifID, int middlemodifID, int branchstart, int branchend) { clear(); - setCandidate(composition, path, startmodifID, endmodifID, middlemodifID, branchstart, branchend); + setCandidate(composition, path, startiontype, startmodifID, endmodifID, middlemodifID, branchstart, branchend); } -void cCandidate::setCandidate(vector& composition, vector& path, int startmodifID, int endmodifID, int middlemodifID, int middlepos) { +void cCandidate::setCandidate(vector& composition, vector& path, eFragmentIonType startiontype, int startmodifID, int endmodifID, int middlemodifID, int middlepos) { clear(); this->composition = composition; @@ -210,6 +211,7 @@ void cCandidate::setCandidate(vector& composition, vector& pat this->endmodifID = endmodifID; this->middlemodifID = middlemodifID; this->path = path; + this->startiontype = startiontype; if (middlepos == -1) { middlemodifID = 0; @@ -226,7 +228,7 @@ void cCandidate::setCandidate(vector& composition, vector& pat } -void cCandidate::setCandidate(vector& composition, vector& path, int startmodifID, int endmodifID, int middlemodifID, int branchstart, int branchend) { +void cCandidate::setCandidate(vector& composition, vector& path, eFragmentIonType startiontype, int startmodifID, int endmodifID, int middlemodifID, int branchstart, int branchend) { clear(); this->composition = composition; @@ -238,6 +240,7 @@ void cCandidate::setCandidate(vector& composition, vector& pat this->branchstart = branchstart; this->branchend = branchend; this->path = path; + this->startiontype = startiontype; } @@ -251,7 +254,9 @@ void cCandidate::clear() { branchstart = -1; branchend = -1; path.clear(); + startiontype = fragmentIonTypeEnd; name = ""; + summary.clear(); realpeptidename = ""; acronympeptidename = ""; @@ -733,17 +738,20 @@ void cCandidate::getPermutationsOfBranches(vector& tpermutations) } -double cCandidate::getPrecursorMass(cBricksDatabase& brickdatabasewithcombinations, cParameters* parameters) { +double cCandidate::calculatePrecursorMass(cBricksDatabase& brickdatabasewithcombinations, cParameters* parameters) { cBrick b; vector bricks; b.setComposition(internalcomposition, false); b.explodeToIntComposition(bricks); + + if (parameters->peptidetype == linearpolyketide) { + return 0; + } double mass = 0; switch (parameters->peptidetype) { case linear: - case linearpolysaccharide: mass = parameters->fragmentdefinitions[precursor_ion].massdifference + parameters->searchedmodifications[startmodifID].massdifference + parameters->searchedmodifications[endmodifID].massdifference; break; case cyclic: @@ -755,29 +763,12 @@ double cCandidate::getPrecursorMass(cBricksDatabase& brickdatabasewithcombinatio case branchcyclic: mass = parameters->fragmentdefinitions[cyclic_precursor_ion].massdifference + parameters->searchedmodifications[middlemodifID].massdifference; break; -#if OLIGOKETIDES == 1 - case linearoligoketide: - switch (getKetidePrecursorType(brickdatabasewithcombinations)) - { - case ketide_precursor_h2o: - mass = parameters->fragmentdefinitions[linear_oligoketide_precursor_ion_h_oh].massdifference; - break; - case ketide_precursor_h2: - mass = parameters->fragmentdefinitions[linear_oligoketide_precursor_ion_h_h].massdifference; - break; - case ketide_precursor_h2o2: - mass = parameters->fragmentdefinitions[linear_oligoketide_precursor_ion_oh_oh].massdifference; - break; - default: - mass = 0; - break; - } - mass += parameters->searchedmodifications[startmodifID].massdifference + parameters->searchedmodifications[endmodifID].massdifference; + case linearpolyketide: + // not supported because of terminal ambiguities H- -OH, H- -H, OH- -OH break; - case cyclicoligoketide: - mass = parameters->fragmentdefinitions[cyclic_oligoketide_precursor_ion].massdifference; + case cyclicpolyketide: + mass = parameters->fragmentdefinitions[cyclic_polyketide_precursor_ion].massdifference; break; -#endif case other: break; default: @@ -794,11 +785,14 @@ double cCandidate::getPrecursorMass(cBricksDatabase& brickdatabasewithcombinatio bool cCandidate::isEqualTo(cCandidate& candidate) { if ((internalcomposition.compare(candidate.internalcomposition) == 0) + && (summary.getSummary().compare(candidate.summary.getSummary()) == 0) + && (summary.isPartial() == candidate.summary.isPartial()) && (startmodifID == candidate.startmodifID) && (endmodifID == candidate.endmodifID) && (middlemodifID == candidate.middlemodifID) && (branchstart == candidate.branchstart) - && (branchend == candidate.branchend)) { + && (branchend == candidate.branchend) + && (startiontype == candidate.startiontype)) { return true; } return false; @@ -992,7 +986,7 @@ void cCandidate::getBranchCyclicRotations(vector& branchcyclicrotati } -cSummaryFormula cCandidate::getSummaryFormula(cParameters& parameters, ePeptideType peptidetype) { +cSummaryFormula cCandidate::calculateSummaryFormula(cParameters& parameters, ePeptideType peptidetype, double precursormass) { cBrick b; vector bricks; b.setComposition(internalcomposition, false); @@ -1001,10 +995,13 @@ cSummaryFormula cCandidate::getSummaryFormula(cParameters& parameters, ePeptideT cSummaryFormula formula; string summary; + if ((peptidetype == linearpolyketide) && (precursormass == 0)) { + return formula; + } + switch (peptidetype) { case linear: - case linearpolysaccharide: summary = "H2O"; formula.addFormula(summary); formula.addFormula(parameters.searchedmodifications[startmodifID].summary); @@ -1022,40 +1019,33 @@ cSummaryFormula cCandidate::getSummaryFormula(cParameters& parameters, ePeptideT case branchcyclic: formula.addFormula(parameters.searchedmodifications[middlemodifID].summary); break; -#if OLIGOKETIDES == 1 - case linearoligoketide: - switch (getKetidePrecursorType(parameters.bricksdatabase)) - { - case ketide_precursor_h2o: - summary = "H2O"; - break; - case ketide_precursor_h2: - summary = "H2"; - break; - case ketide_precursor_h2o2: - summary = "H2O2"; - break; - default: - break; - } - - if (hasFirstBrickArtificial(parameters.bricksdatabase) || hasLastBrickArtificial(parameters.bricksdatabase)) { - summary = ""; - } - - formula.addFormula(summary); + case linearpolyketide: formula.addFormula(parameters.searchedmodifications[startmodifID].summary); formula.addFormula(parameters.searchedmodifications[endmodifID].summary); break; - case cyclicoligoketide: + case cyclicpolyketide: break; -#endif case other: break; default: break; } + summary = parameters.precursoradduct.empty()?"":"H-1"; + formula.addFormula(summary); + formula.addFormula(parameters.precursoradduct); + + if ((peptidetype == linear) || (peptidetype == linearpolyketide)) { + if (parameters.cyclicnterminus) { + summary = "H2O"; + formula.addFormula(summary, true); + } + if (parameters.cycliccterminus) { + summary = "H2O"; + formula.addFormula(summary, true); + } + } + bool partial = false; for (int i = 0; i < (int)bricks.size(); i++) { if (bricks[i] - 1 < (int)parameters.bricksdatabase.size()) { @@ -1068,10 +1058,72 @@ cSummaryFormula cCandidate::getSummaryFormula(cParameters& parameters, ePeptideT formula.setPartial(partial); + if (!partial && (peptidetype == linearpolyketide)) { + summary = "H2O2"; + formula.addFormula(summary); + + cSummaryFormula tempformula; + tempformula.setFormula(formula.getSummary()); + summary = "Hplus"; + tempformula.addFormula(summary); + summary = (parameters.precursorcharge > 0)?"":"Hplus-2"; + tempformula.addFormula(summary); + + precursormass = charge(uncharge(precursormass, parameters.precursorcharge), (parameters.precursorcharge > 0)?1:-1); + + double tempmass = tempformula.getMass(); + double bestmz = fabs(precursormass - tempmass); + int bestcase = 1; + + summary = "O-1"; + + tempformula.addFormula(summary); + tempmass = tempformula.getMass(); + if (fabs(precursormass - tempmass) < bestmz) { + bestmz = fabs(precursormass - tempmass); + bestcase = 2; + } + + tempformula.addFormula(summary); + tempmass = tempformula.getMass(); + if (fabs(precursormass - tempmass) < bestmz) { + bestmz = fabs(precursormass - tempmass); + bestcase = 3; + } + + if (bestcase == 1) { + return formula; + } + + if (bestcase == 2) { + summary = "O-1"; + formula.addFormula(summary); + return formula; + } + + if (bestcase == 3) { + summary = "O-2"; + formula.addFormula(summary); + return formula; + } + + } + return formula; } +cSummaryFormula& cCandidate::getSummaryFormula() { + return summary; +} + + + +void cCandidate::setSummaryFormula(cSummaryFormula& summary) { + this->summary = summary; +} + + void cCandidate::store(ofstream& os) { int size; @@ -1087,7 +1139,9 @@ void cCandidate::store(ofstream& os) { path[i].store(os); } + os.write((char *)&startiontype, sizeof(eFragmentIonType)); storeString(name, os); + summary.store(os); storeStringVector(composition, os); storeString(internalcomposition, os); @@ -1117,7 +1171,9 @@ void cCandidate::load(ifstream& is) { path[i].load(is); } + is.read((char *)&startiontype, sizeof(eFragmentIonType)); loadString(name, is); + summary.load(is); loadStringVector(composition, is); loadString(internalcomposition, is); @@ -1238,6 +1294,7 @@ void cCandidate::setPath(cDeNovoGraph& graph, cParameters* parameters) { if (currentedge->endmodifID > 0) { stringpath += ", terminal modification: " + parameters->searchedmodifications[currentedge->endmodifID].name; } + stringpath += ", summary: " + currentedge->summary; //path += currentedge->printSourceAnnotation(fragmentdefinitions); //path += "->"; //path += currentedge->printTargetAnnotation(fragmentdefinitions); @@ -1256,11 +1313,8 @@ void cCandidate::setRealPeptideName(cBricksDatabase& bricksdatabase, ePeptideTyp { case linear: case cyclic: -#if OLIGOKETIDES == 1 - case linearoligoketide: - case cyclicoligoketide: -#endif - case linearpolysaccharide: + case linearpolyketide: + case cyclicpolyketide: realpeptidename = bricksdatabase.getRealName(internalcomposition); break; case branched: @@ -1280,11 +1334,8 @@ void cCandidate::setAcronymPeptideNameWithHTMLReferences(cBricksDatabase& bricks { case linear: case cyclic: -#if OLIGOKETIDES == 1 - case linearoligoketide: - case cyclicoligoketide: -#endif - case linearpolysaccharide: + case linearpolyketide: + case cyclicpolyketide: acronympeptidename = bricksdatabase.getAcronymName(internalcomposition, true); break; case branched: @@ -1309,55 +1360,17 @@ string& cCandidate::getAcronymPeptideNameWithHTMLReferences() { } -eKetidePrecursorType cCandidate::getKetidePrecursorType(cBricksDatabase& bricksdatabase) { - cBrick b; - b.setComposition(internalcomposition, false); - vector intcomposition; - b.explodeToIntComposition(intcomposition); - - /* - if (intcomposition.size() == 0) { - return ketide_precursor_h2o; - } - - if ((bricksdatabase[intcomposition[0] - 1].getResidueLossType() == h2_loss) && (bricksdatabase[intcomposition.back() - 1].getResidueLossType() == h2_loss)) { - return ketide_precursor_h2; - } - - if ((bricksdatabase[intcomposition[0] - 1].getResidueLossType() == h2o_loss) && (bricksdatabase[intcomposition.back() - 1].getResidueLossType() == h2o_loss)) { - return ketide_precursor_h2o2; - } - - return ketide_precursor_h2o; - */ - - int h2_blocks = 0; - int h2o_blocks = 0; - for (int i = 0; i < (int)intcomposition.size(); i++) { - if (bricksdatabase[intcomposition[i] - 1].getResidueLossType() == h2_loss) { - h2_blocks++; - } - if (bricksdatabase[intcomposition[i] - 1].getResidueLossType() == h2o_loss) { - h2o_blocks++; - } - } - - if (h2_blocks == h2o_blocks) { - return ketide_precursor_h2o; - } - - if (h2_blocks > h2o_blocks) { - return ketide_precursor_h2; - } - - return ketide_precursor_h2o2; +void cCandidate::setStartIonType(eFragmentIonType iontype) { + startiontype = iontype; } -#if OLIGOKETIDES == 1 +eFragmentIonType cCandidate::getStartIonType() { + return startiontype; +} -bool cCandidate::checkKetideSequence(cBricksDatabase& bricksdatabase, ePeptideType peptidetype) { +bool cCandidate::checkKetideSequence(cBricksDatabase& bricksdatabase, ePeptideType peptidetype, bool regularblocksorder) { cBrick b; b.setComposition(internalcomposition, false); @@ -1384,8 +1397,17 @@ bool cCandidate::checkKetideSequence(cBricksDatabase& bricksdatabase, ePeptideTy bool hasfirstblockartificial = hasFirstBrickArtificial(bricksdatabase); bool haslastblockartificial = hasLastBrickArtificial(bricksdatabase); - // cyclic oligoketide has always an even number of blocks - if ((peptidetype == cyclicoligoketide) && !hasfirstblockartificial && !haslastblockartificial && ((int)intcomposition.size() % 2 == 1)) { + // linear polyketide has at least 2 building blocks + if ((peptidetype == linearpolyketide) && !hasfirstblockartificial && !haslastblockartificial && ((int)intcomposition.size() < 2)) { + return false; + } + + if (!regularblocksorder) { + return true; + } + + // cyclic polyketide has always an even number of blocks + if ((peptidetype == cyclicpolyketide) && !hasfirstblockartificial && !haslastblockartificial && ((int)intcomposition.size() % 2 == 1)) { return false; } @@ -1429,7 +1451,7 @@ eResidueLossType cCandidate::getRightResidueType(cBricksDatabase& bricksdatabase } -bool cCandidate::checkKetideBlocks(cBricksDatabase& bricksdatabase, ePeptideType peptidetype) { +bool cCandidate::checkKetideBlocks(cBricksDatabase& bricksdatabase, ePeptideType peptidetype, bool regularblocksorder) { cBrick b; b.setComposition(internalcomposition, false); vector intcomposition; @@ -1439,11 +1461,15 @@ bool cCandidate::checkKetideBlocks(cBricksDatabase& bricksdatabase, ePeptideType return false; } + if (!regularblocksorder) { + return true; + } + bool hasfirstblockartificial = hasFirstBrickArtificial(bricksdatabase); bool haslastblockartificial = hasLastBrickArtificial(bricksdatabase); - // cyclic oligoketide has always an even number of blocks - if ((peptidetype == cyclicoligoketide) && !hasfirstblockartificial && !haslastblockartificial && ((int)intcomposition.size() % 2 == 1)) { + // cyclic polyketide has always an even number of blocks + if ((peptidetype == cyclicpolyketide) && !hasfirstblockartificial && !haslastblockartificial && ((int)intcomposition.size() % 2 == 1)) { return false; } @@ -1462,19 +1488,10 @@ bool cCandidate::checkKetideBlocks(cBricksDatabase& bricksdatabase, ePeptideType return true; } - /* - if ((h2_blocks == 0) && (h2o_blocks == (int)intcomposition.size())) { - return true; - } - */ - return false; } -#endif - - bool operator == (cCandidate const& a, cCandidate const& b) { return ((cCandidate &)a).isEqualTo((cCandidate &)b); } diff --git a/CycloBranch/core/cCandidate.h b/CycloBranch/core/cCandidate.h index 75c36d5..ad978ef 100644 --- a/CycloBranch/core/cCandidate.h +++ b/CycloBranch/core/cCandidate.h @@ -136,7 +136,9 @@ class cCandidate { int branchstart; int branchend; vector path; + eFragmentIonType startiontype; string name; + cSummaryFormula summary; vector composition; string internalcomposition; @@ -173,50 +175,54 @@ class cCandidate { \brief The constructor. \param composition reference to a vector of strings where each string is a sequence of ids of bricks separated by '-' (each string corresponds to an edge in the de novo graph) \param path reference to a path in the de novo graph which corresponds to a peptide sequence candidate + \param startiontype start ion type in the de novo graph \param startmodifID id of a terminal modification (at the beginning of a spectrum) \param endmodifID id of a terminal modification (at the end of a spectrum) \param middlemodifID id of a terminal modification of a branched peptide (in the middle of a spectrum) \param middlepos position in \a composition corresponding to a branch of a branched peptide */ - cCandidate(vector& composition, vector& path, int startmodifID, int endmodifID, int middlemodifID, int middlepos); + cCandidate(vector& composition, vector& path, eFragmentIonType startiontype, int startmodifID, int endmodifID, int middlemodifID, int middlepos); /** \brief The constructor. \param composition reference to a vector of strings where each string is a sequence of ids of bricks separated by '-' (each string corresponds to an edge in the de novo graph) \param path reference to a path in the de novo graph which corresponds to a peptide sequence candidate + \param startiontype start ion type in the de novo graph \param startmodifID id of a terminal modification (at the beginning of a spectrum) \param endmodifID id of a terminal modification (at the end of a spectrum) \param middlemodifID id of a terminal modification of a branched peptide (in the middle of a spectrum) \param branchstart position of a brick where a branch of a branched peptide starts (it is assumed that all strings in \a composition are concatenated) \param branchend position of a brick where a branch of a branched peptide ends (it is assumed that all strings in \a composition are concatenated) */ - cCandidate(vector& composition, vector& path, int startmodifID, int endmodifID, int middlemodifID, int branchstart, int branchend); + cCandidate(vector& composition, vector& path, eFragmentIonType startiontype, int startmodifID, int endmodifID, int middlemodifID, int branchstart, int branchend); /** \brief Set a peptide sequence candidate. \param composition reference to a vector of strings where each string is a sequence of ids of bricks separated by '-' (each string corresponds to an edge in the de novo graph) \param path reference to a path in the de novo graph which corresponds to a peptide sequence candidate + \param startiontype start ion type in the de novo graph \param startmodifID id of a terminal modification (at the beginning of a spectrum) \param endmodifID id of a terminal modification (at the end of a spectrum) \param middlemodifID id of a terminal modification of a branched peptide (in the middle of a spectrum) \param middlepos position in \a composition corresponding to a branch of a branched peptide */ - void setCandidate(vector& composition, vector& path, int startmodifID, int endmodifID, int middlemodifID, int middlepos); + void setCandidate(vector& composition, vector& path, eFragmentIonType startiontype, int startmodifID, int endmodifID, int middlemodifID, int middlepos); /** \brief Set a peptide sequence candidate. \param composition reference to a vector of strings where each string is a sequence of ids of bricks separated by '-' (each string corresponds to an edge in the de novo graph) \param path reference to a path in the de novo graph which corresponds to a peptide sequence candidate + \param startiontype start ion type in the de novo graph \param startmodifID id of a terminal modification (at the beginning of a spectrum) \param endmodifID id of a terminal modification (at the end of a spectrum) \param middlemodifID id of a terminal modification of a branched peptide (in the middle of a spectrum) \param branchstart position of a brick where a branch of a branched peptide starts (it is assumed that all strings in \a composition are concatenated) \param branchend position of a brick where a branch of a branched peptide ends (it is assumed that all strings in \a composition are concatenated) */ - void setCandidate(vector& composition, vector& path, int startmodifID, int endmodifID, int middlemodifID, int branchstart, int branchend); + void setCandidate(vector& composition, vector& path, eFragmentIonType startiontype, int startmodifID, int endmodifID, int middlemodifID, int branchstart, int branchend); /** @@ -307,12 +313,12 @@ class cCandidate { /** - \brief Get the precursor mass of the peptide sequence candidate. + \brief Calculate the precursor mass of the peptide sequence candidate. \param brickdatabasewithcombinations reference to an input database of bricks with combinations of bricks \param parameters a pointer to the parameters of the application \retval double precursor mass of the candidate */ - double getPrecursorMass(cBricksDatabase& brickdatabasewithcombinations, cParameters* parameters); + double calculatePrecursorMass(cBricksDatabase& brickdatabasewithcombinations, cParameters* parameters); /** @@ -445,12 +451,27 @@ class cCandidate { /** - \brief Get the summary formula of the peptide sequence candidate. + \brief Calculate the summary formula of the peptide sequence candidate. \param parameters a reference to the parameters of the application \param peptidetype the type of peptide - \retval cSummaryFormula the summary formula + \param precursormass experimantal precursor mass + \retval string summary formula + */ + cSummaryFormula calculateSummaryFormula(cParameters& parameters, ePeptideType peptidetype, double precursormass = 0); + + + /** + \brief Get the summary formula of the peptide sequence candidate. + \retval cSummaryFormula summary formula + */ + cSummaryFormula& getSummaryFormula(); + + + /** + \brief Set the summary formula of the peptide sequence candidate. + \param summary summary formula */ - cSummaryFormula getSummaryFormula(cParameters& parameters, ePeptideType peptidetype); + void setSummaryFormula(cSummaryFormula& summary); /** @@ -569,22 +590,27 @@ class cCandidate { /** - \brief Get the precursor type. - \param bricksdatabase a database of building blocks - \retval eKetidePrecursorType the type of precursor ion + \brief Set start ion type used in the de novo graph. + \param iontype fragment ion type */ - eKetidePrecursorType getKetidePrecursorType(cBricksDatabase& bricksdatabase); + void setStartIonType(eFragmentIonType iontype); + + /** + \brief Get start ion type used in the de novo graph. + \retval eFragmentIonType fragment ion type + */ + eFragmentIonType getStartIonType(); -#if OLIGOKETIDES == 1 /** \brief Check if the order of blocks is correct. \param bricksdatabase a database of building blocks \param peptidetype the type of peptide + \param regularblocksorder check regular order of ketide blocks \retval bool true when the order of blocks is correct; false otherwise */ - bool checkKetideSequence(cBricksDatabase& bricksdatabase, ePeptideType peptidetype); + bool checkKetideSequence(cBricksDatabase& bricksdatabase, ePeptideType peptidetype, bool regularblocksorder); /** @@ -607,13 +633,12 @@ class cCandidate { \brief Check if the numbers of H2 loss and H2O loss blocks are correct. \param bricksdatabase a database of building blocks \param peptidetype the type of peptide + \param regularblocksorder check regular order of ketide blocks \retval bool true when the numbers of blocks are correct */ - bool checkKetideBlocks(cBricksDatabase& bricksdatabase, ePeptideType peptidetype); + bool checkKetideBlocks(cBricksDatabase& bricksdatabase, ePeptideType peptidetype, bool regularblocksorder); -#endif - }; diff --git a/CycloBranch/core/cDeNovoGraph.cpp b/CycloBranch/core/cDeNovoGraph.cpp index 4b248c2..c13b2f2 100644 --- a/CycloBranch/core/cDeNovoGraph.cpp +++ b/CycloBranch/core/cDeNovoGraph.cpp @@ -137,13 +137,14 @@ void cDeNovoGraph::initialize(cMainThread& os, cParameters& parameters) { int cDeNovoGraph::createGraph(bool& terminatecomputation) { cDeNovoGraphNode node; + cSummaryFormula formula; + cSummaryFormula tmpformula; double mass; double termmass; - int left, right, middle; - cEdge e, e1, e2; + int left, right, middle, targetnode, i; + cEdge e; double unchargedprecursormass = charge(uncharge(parameters->precursormass, parameters->precursorcharge), (parameters->precursorcharge > 0)?1:-1); double unchargedmz; - int i; sortedpeaklist = parameters->peaklistseries[0]; // insert the single charged precursor, if neccessary @@ -170,16 +171,37 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { *os << "Number of nodes when deamidated ions are removed: " << sortedpeaklist.size() << endl; double negativeshift = (parameters->precursorcharge > 0)?0:-2*Hplus; + string negativeshiftsummary = (parameters->precursorcharge > 0)?"":"Hplus-2"; // insert system nodes switch (parameters->peptidetype) { case cyclic: + node.clear(); + node.setMZRatio(0); + node.setIntensity(0); + node.addIonAnnotation(b_ion); + graph.push_back(node); + node.clear(); node.setMZRatio(parameters->fragmentdefinitions[b_ion].massdifference + negativeshift); node.setIntensity(0); node.addIonAnnotation(b_ion); graph.push_back(node); + + e.clear(); + e.composition = "0"; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[b_ion].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); + e.targetnode = 1; + e.targetion = b_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); + graph[0].insertTempEdge(e); + + lastsystemnode = (int)graph.size() - 1; + startnode = 1; break; case linear: case branched: @@ -204,43 +226,80 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { e.clear(); e.composition = "0"; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[b_ion].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); e.targetnode = 1; + e.targetion = b_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); graph[0].insertTempEdge(e); e.clear(); e.composition = "0"; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[y_ion].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); e.targetnode = 2; + e.targetion = y_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); graph[0].insertTempEdge(e); + targetnode = 2; + for (i = 1; i < (int)parameters->searchedmodifications.size(); i++) { - node.clear(); - e.clear(); - e.composition = "0"; - e.targetnode = i + 2; - if (parameters->searchedmodifications[i].nterminal) { + node.clear(); node.setMZRatio(parameters->fragmentdefinitions[b_ion].massdifference + parameters->searchedmodifications[i].massdifference + negativeshift); node.setIntensity(0); node.addIonAnnotation(b_ion); + graph.push_back(node); + + e.clear(); + e.composition = "0"; + e.startmodifID = i; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[b_ion].summary); + tmpformula.addFormula(parameters->searchedmodifications[i].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); + targetnode++; + e.targetnode = targetnode; + e.targetion = b_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); + + graph[0].insertTempEdge(e); } if (parameters->searchedmodifications[i].cterminal) { + node.clear(); node.setMZRatio(parameters->fragmentdefinitions[y_ion].massdifference + parameters->searchedmodifications[i].massdifference + negativeshift); node.setIntensity(0); node.addIonAnnotation(y_ion); + graph.push_back(node); + + e.clear(); + e.composition = "0"; + e.startmodifID = i; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[y_ion].summary); + tmpformula.addFormula(parameters->searchedmodifications[i].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); + targetnode++; + e.targetnode = targetnode; + e.targetion = y_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); + + graph[0].insertTempEdge(e); } - graph.push_back(node); - graph[0].insertTempEdge(e); } lastsystemnode = (int)graph.size() - 1; startnode = 1; - - // to do - problem with e.targetnode - //sort(graph.begin() + 1, graph.end(), compareNodes); - break; case branchcyclic: node.clear(); @@ -264,44 +323,85 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { e.clear(); e.composition = "0"; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[b_ion].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); e.targetnode = 1; + e.targetion = b_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); graph[0].insertTempEdge(e); //e.clear(); //e.composition = "0"; + //tmpformula.clear(); + //tmpformula.addFormula(parameters->fragmentdefinitions[y_ion].summary); + //tmpformula.addFormula(negativeshiftsummary); + //e.summary = tmpformula.getSummary(); //e.targetnode = 2; + //e.targetion = y_ion; + //e.massdifference = graph[e.targetnode].getMZRatio(); //graph[0].insertTempEdge(e); /* + + targetnode = 2; + for (i = 1; i < (int)parameters->searchedmodifications.size(); i++) { - node.clear(); - - e.clear(); - e.composition = "0"; - e.targetnode = i + 2; if (parameters->searchedmodifications[i].nterminal) { + node.clear(); node.setMZRatio(parameters->fragmentdefinitions[b_ion].massdifference + parameters->searchedmodifications[i].massdifference + negativeshift); node.setIntensity(0); node.addIonAnnotation(b_ion); + graph.push_back(node); + + e.clear(); + e.composition = "0"; + e.startmodifID = i; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[b_ion].summary); + tmpformula.addFormula(parameters->searchedmodifications[i].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); + targetnode++; + e.targetnode = targetnode; + e.targetion = b_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); + + graph[0].insertTempEdge(e); } if (parameters->searchedmodifications[i].cterminal) { + node.clear(); node.setMZRatio(parameters->fragmentdefinitions[y_ion].massdifference + parameters->searchedmodifications[i].massdifference + negativeshift); node.setIntensity(0); node.addIonAnnotation(y_ion); + graph.push_back(node); + + e.clear(); + e.composition = "0"; + e.startmodifID = i; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[y_ion].summary); + tmpformula.addFormula(parameters->searchedmodifications[i].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); + targetnode++; + e.targetnode = targetnode; + e.targetion = y_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); + + graph[0].insertTempEdge(e); } - graph.push_back(node); - graph[0].insertTempEdge(e); } */ lastsystemnode = (int)graph.size() - 1; startnode = 1; break; -#if OLIGOKETIDES == 1 - case linearoligoketide: + case linearpolyketide: node.clear(); node.setMZRatio(0); node.setIntensity(0); @@ -337,27 +437,49 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { e.clear(); e.composition = "0"; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[l1h_ion].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); e.targetnode = 1; + e.targetion = l1h_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); graph[0].insertTempEdge(e); e.clear(); e.composition = "0"; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[l2h_ion].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); e.targetnode = 2; + e.targetion = l2h_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); graph[0].insertTempEdge(e); e.clear(); e.composition = "0"; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[l1oh_ion].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); e.targetnode = 3; + e.targetion = l1oh_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); graph[0].insertTempEdge(e); e.clear(); e.composition = "0"; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[l2oh_ion].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); e.targetnode = 4; + e.targetion = l2oh_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); graph[0].insertTempEdge(e); - e.clear(); - e.composition = "0"; - e.targetnode = 4; + targetnode = 4; for (i = 1; i < (int)parameters->searchedmodifications.size(); i++) { @@ -367,7 +489,20 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { node.setIntensity(0); node.addIonAnnotation(l1h_ion); graph.push_back(node); - e.targetnode++; + + e.clear(); + e.composition = "0"; + e.startmodifID = i; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[l1h_ion].summary); + tmpformula.addFormula(parameters->searchedmodifications[i].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); + targetnode++; + e.targetnode = targetnode; + e.targetion = l1h_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); + graph[0].insertTempEdge(e); node.clear(); @@ -375,7 +510,20 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { node.setIntensity(0); node.addIonAnnotation(l2h_ion); graph.push_back(node); - e.targetnode++; + + e.clear(); + e.composition = "0"; + e.startmodifID = i; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[l2h_ion].summary); + tmpformula.addFormula(parameters->searchedmodifications[i].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); + targetnode++; + e.targetnode = targetnode; + e.targetion = l2h_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); + graph[0].insertTempEdge(e); } @@ -385,7 +533,20 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { node.setIntensity(0); node.addIonAnnotation(l1oh_ion); graph.push_back(node); - e.targetnode++; + + e.clear(); + e.composition = "0"; + e.startmodifID = i; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[l1oh_ion].summary); + tmpformula.addFormula(parameters->searchedmodifications[i].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); + targetnode++; + e.targetnode = targetnode; + e.targetion = l1oh_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); + graph[0].insertTempEdge(e); node.clear(); @@ -393,16 +554,29 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { node.setIntensity(0); node.addIonAnnotation(l2oh_ion); graph.push_back(node); - e.targetnode++; + + e.clear(); + e.composition = "0"; + e.startmodifID = i; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[l2oh_ion].summary); + tmpformula.addFormula(parameters->searchedmodifications[i].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); + targetnode++; + e.targetnode = targetnode; + e.targetion = l2oh_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); + graph[0].insertTempEdge(e); - } + } } lastsystemnode = (int)graph.size() - 1; startnode = 1; break; - case cyclicoligoketide: + case cyclicpolyketide: node.clear(); node.setMZRatio(0); node.setIntensity(0); @@ -431,75 +605,30 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { e.clear(); e.composition = "0"; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[l1h_ion].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); e.targetnode = 1; + e.targetion = l1h_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); graph[0].insertTempEdge(e); e.clear(); e.composition = "0"; + tmpformula.clear(); + tmpformula.addFormula(parameters->fragmentdefinitions[l2h_ion].summary); + tmpformula.addFormula(negativeshiftsummary); + e.summary = tmpformula.getSummary(); e.targetnode = 2; + e.targetion = l2h_ion; + e.massdifference = graph[e.targetnode].getMZRatio(); graph[0].insertTempEdge(e); - e.clear(); + /*e.clear(); e.composition = "0"; e.targetnode = 3; - graph[0].insertTempEdge(e); - - lastsystemnode = (int)graph.size() - 1; - startnode = 1; - break; -#endif - case linearpolysaccharide: - node.clear(); - node.setMZRatio(0); - node.setIntensity(0); - node.addIonAnnotation(ms_nterminal_ion_hplus); - //node.addIonAnnotation(ms_cterminal_ion_hplus); - graph.push_back(node); - - node.clear(); - node.setMZRatio(H2O + Hplus + negativeshift); - node.setIntensity(0); - node.addIonAnnotation(ms_nterminal_ion_hplus); - graph.push_back(node); - - //node.clear(); - //node.setMZRatio(H2O + Hplus + negativeshift); - //node.setIntensity(0); - //node.addIonAnnotation(ms_cterminal_ion_hplus); - //graph.push_back(node); - - e.clear(); - e.composition = "0"; - e.targetnode = 1; - graph[0].insertTempEdge(e); - - //e.clear(); - //e.composition = "0"; - //e.targetnode = 2; - //graph[0].insertTempEdge(e); - - for (i = 1; i < (int)parameters->searchedmodifications.size(); i++) { - node.clear(); - - e.clear(); - e.composition = "0"; - e.targetnode = i + 1;//2; - - //if (parameters->searchedmodifications[i].nterminal) { - node.setMZRatio(H2O + Hplus + parameters->searchedmodifications[i].massdifference + negativeshift); - node.setIntensity(0); - node.addIonAnnotation(ms_nterminal_ion_hplus); - //} - - //if (parameters->searchedmodifications[i].cterminal) { - // node.setMZRatio(H2O + Hplus + parameters->searchedmodifications[i].massdifference + negativeshift); - // node.setIntensity(0); - // node.addIonAnnotation(ms_cterminal_ion_hplus); - //} - - graph.push_back(node); - graph[0].insertTempEdge(e); - } + graph[0].insertTempEdge(e);*/ lastsystemnode = (int)graph.size() - 1; startnode = 1; @@ -512,6 +641,7 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { return -1; } + // sort(graph.begin() + startnode, graph.end(), compareNodes); // initialize nodes by mzratios from a sorted peak list for (i = 0; i < sortedpeaklist.size(); i++) { @@ -584,11 +714,9 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { b.setMass(bricksdatabasewithcombinations.getMassOfComposition(combarray, numberofbasicbricks)); b.setComposition(compositionname, true); -#if OLIGOKETIDES == 1 - if (((parameters->peptidetype == linearoligoketide) || (parameters->peptidetype == cyclicoligoketide)) && !bricksdatabasewithcombinations.checkKetideBlocks(b)) { + if (((parameters->peptidetype == linearpolyketide) || (parameters->peptidetype == cyclicpolyketide)) && !bricksdatabasewithcombinations.checkKetideBlocks(b, parameters->regularblocksorder)) { continue; } -#endif bricksdatabasewithcombinations.push_back(b); } @@ -623,10 +751,8 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { for (int k = 0; k < (int)parameters->fragmentionsfordenovograph.size(); k++) { if (/*!graph[i].ionannotation[parameters->fragmentionsfordenovograph[k]] ||*/ (parameters->fragmentionsfordenovograph[k] == precursor_ion) -#if OLIGOKETIDES == 1 - || (parameters->fragmentionsfordenovograph[k] == linear_oligoketide_precursor_ion_h_h) || (parameters->fragmentionsfordenovograph[k] == linear_oligoketide_precursor_ion_h_oh) - || (parameters->fragmentionsfordenovograph[k] == linear_oligoketide_precursor_ion_oh_oh) || (parameters->fragmentionsfordenovograph[k] == cyclic_oligoketide_precursor_ion) -#endif + || (parameters->fragmentionsfordenovograph[k] == linear_polyketide_precursor_ion_h_h) || (parameters->fragmentionsfordenovograph[k] == linear_polyketide_precursor_ion_h_oh) + || (parameters->fragmentionsfordenovograph[k] == linear_polyketide_precursor_ion_oh_oh) || (parameters->fragmentionsfordenovograph[k] == cyclic_polyketide_precursor_ion) ) { continue; } @@ -634,23 +760,14 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { for (int m = 0; m < (int)parameters->fragmentionsfordenovograph.size(); m++) { // test for incompatible ion series - if ( -#if OLIGOKETIDES == 1 - ( -#endif - !((parameters->fragmentdefinitions[parameters->fragmentionsfordenovograph[k]].nterminal == parameters->fragmentdefinitions[parameters->fragmentionsfordenovograph[m]].nterminal) && - (parameters->fragmentdefinitions[parameters->fragmentionsfordenovograph[k]].cterminal == parameters->fragmentdefinitions[parameters->fragmentionsfordenovograph[m]].cterminal)) -#if OLIGOKETIDES == 1 - || - (((parameters->peptidetype == linearoligoketide) || (parameters->peptidetype == cyclicoligoketide)) && + if ((!((parameters->fragmentdefinitions[parameters->fragmentionsfordenovograph[k]].nterminal == parameters->fragmentdefinitions[parameters->fragmentionsfordenovograph[m]].nterminal) && + (parameters->fragmentdefinitions[parameters->fragmentionsfordenovograph[k]].cterminal == parameters->fragmentdefinitions[parameters->fragmentionsfordenovograph[m]].cterminal)) || + (((parameters->peptidetype == linearpolyketide) || (parameters->peptidetype == cyclicpolyketide)) && !(/*((parameters->fragmentionsfordenovograph[k] == l0h_ion) && (parameters->fragmentionsfordenovograph[m] == l0h_ion)) ||*/ ((parameters->fragmentionsfordenovograph[k] == l1h_ion) && (parameters->fragmentionsfordenovograph[m] == l1h_ion)) || ((parameters->fragmentionsfordenovograph[k] == l2h_ion) && (parameters->fragmentionsfordenovograph[m] == l2h_ion)) - || ((parameters->fragmentionsfordenovograph[k] == l1oh_ion) && (parameters->fragmentionsfordenovograph[m] == l1oh_ion)) || ((parameters->fragmentionsfordenovograph[k] == l2oh_ion) && (parameters->fragmentionsfordenovograph[m] == l2oh_ion)))) - ) - && (parameters->fragmentionsfordenovograph[m] != linear_oligoketide_precursor_ion_h_h) && (parameters->fragmentionsfordenovograph[m] != linear_oligoketide_precursor_ion_h_oh) - && (parameters->fragmentionsfordenovograph[m] != linear_oligoketide_precursor_ion_oh_oh) && (parameters->fragmentionsfordenovograph[m] != cyclic_oligoketide_precursor_ion) -#endif - && (parameters->fragmentionsfordenovograph[m] != precursor_ion) - ) { + || ((parameters->fragmentionsfordenovograph[k] == l1oh_ion) && (parameters->fragmentionsfordenovograph[m] == l1oh_ion)) || ((parameters->fragmentionsfordenovograph[k] == l2oh_ion) && (parameters->fragmentionsfordenovograph[m] == l2oh_ion))))) + && (parameters->fragmentionsfordenovograph[m] != linear_polyketide_precursor_ion_h_h) && (parameters->fragmentionsfordenovograph[m] != linear_polyketide_precursor_ion_h_oh) + && (parameters->fragmentionsfordenovograph[m] != linear_polyketide_precursor_ion_oh_oh) && (parameters->fragmentionsfordenovograph[m] != cyclic_polyketide_precursor_ion) + && (parameters->fragmentionsfordenovograph[m] != precursor_ion)) { continue; } @@ -658,40 +775,26 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { for (int n = 0; n < (int)parameters->searchedmodifications.size(); n++) { if ((n > 0) && (parameters->fragmentionsfordenovograph[m] != precursor_ion) -#if OLIGOKETIDES == 1 - && (parameters->fragmentionsfordenovograph[m] != linear_oligoketide_precursor_ion_h_h) && (parameters->fragmentionsfordenovograph[m] != linear_oligoketide_precursor_ion_h_oh) - && (parameters->fragmentionsfordenovograph[m] != linear_oligoketide_precursor_ion_oh_oh) && (parameters->fragmentionsfordenovograph[m] != cyclic_oligoketide_precursor_ion) -#endif - ) { + && (parameters->fragmentionsfordenovograph[m] != linear_polyketide_precursor_ion_h_h) && (parameters->fragmentionsfordenovograph[m] != linear_polyketide_precursor_ion_h_oh) + && (parameters->fragmentionsfordenovograph[m] != linear_polyketide_precursor_ion_oh_oh) && (parameters->fragmentionsfordenovograph[m] != cyclic_polyketide_precursor_ion)) { continue; } // middle modifications for branched and branch-cyclic peptides for (int p = 0; p < (int)parameters->searchedmodifications.size(); p++) { - if ((p > 0) && ((parameters->peptidetype == linear) || (parameters->peptidetype == cyclic) || (parameters->peptidetype == linearpolysaccharide) -#if OLIGOKETIDES == 1 - || (parameters->peptidetype == linearoligoketide) || (parameters->peptidetype == cyclicoligoketide) -#endif - )) { + if ((p > 0) && ((parameters->peptidetype == linear) || (parameters->peptidetype == cyclic) + || (parameters->peptidetype == linearpolyketide) || (parameters->peptidetype == cyclicpolyketide))) { continue; } termmass = 0; -#if OLIGOKETIDES == 1 if ((parameters->fragmentionsfordenovograph[m] == precursor_ion) - || (parameters->fragmentionsfordenovograph[m] == linear_oligoketide_precursor_ion_h_h) || (parameters->fragmentionsfordenovograph[m] == linear_oligoketide_precursor_ion_h_oh) - || (parameters->fragmentionsfordenovograph[m] == linear_oligoketide_precursor_ion_oh_oh) || (parameters->fragmentionsfordenovograph[m] == cyclic_oligoketide_precursor_ion)) { -#else - if (parameters->fragmentionsfordenovograph[m] == precursor_ion) { -#endif - - if ((parameters->peptidetype == linear) || (parameters->peptidetype == linearpolysaccharide) -#if OLIGOKETIDES == 1 - || (parameters->peptidetype == linearoligoketide) -#endif - ) { + || (parameters->fragmentionsfordenovograph[m] == linear_polyketide_precursor_ion_h_h) || (parameters->fragmentionsfordenovograph[m] == linear_polyketide_precursor_ion_h_oh) + || (parameters->fragmentionsfordenovograph[m] == linear_polyketide_precursor_ion_oh_oh) || (parameters->fragmentionsfordenovograph[m] == cyclic_polyketide_precursor_ion)) { + + if ((parameters->peptidetype == linear) || (parameters->peptidetype == linearpolyketide)) { if ((n > 0) && ((parameters->fragmentdefinitions[parameters->fragmentionsfordenovograph[k]].nterminal && parameters->searchedmodifications[n].nterminal) || (parameters->fragmentdefinitions[parameters->fragmentionsfordenovograph[k]].cterminal && parameters->searchedmodifications[n].cterminal))) { continue; } @@ -709,6 +812,10 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { for (int z1 = 1; z1 <= abs(parameters->precursorcharge); z1++) { + if ((z1 > 1) && (i <= lastsystemnode)) { + break; + } + for (int z2 = 1; z2 <= abs(parameters->precursorcharge); z2++) { unchargedmz = charge(uncharge(graph[i].getMZRatio(), (parameters->precursorcharge > 0)?z1:-z1), (parameters->precursorcharge > 0)?1:-1); @@ -766,20 +873,30 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { } // irrelevant connection with precursor -#if OLIGOKETIDES == 1 if (((parameters->fragmentionsfordenovograph[m] == precursor_ion) - || (parameters->fragmentionsfordenovograph[m] == linear_oligoketide_precursor_ion_h_h) || (parameters->fragmentionsfordenovograph[m] == linear_oligoketide_precursor_ion_h_oh) - || (parameters->fragmentionsfordenovograph[m] == linear_oligoketide_precursor_ion_oh_oh) || (parameters->fragmentionsfordenovograph[m] == cyclic_oligoketide_precursor_ion)) + || (parameters->fragmentionsfordenovograph[m] == linear_polyketide_precursor_ion_h_h) || (parameters->fragmentionsfordenovograph[m] == linear_polyketide_precursor_ion_h_oh) + || (parameters->fragmentionsfordenovograph[m] == linear_polyketide_precursor_ion_oh_oh) || (parameters->fragmentionsfordenovograph[m] == cyclic_polyketide_precursor_ion)) && (middle != (int)graph.size() - 1) && (i != (int)graph.size() - 1)) { -#else - if ((parameters->fragmentionsfordenovograph[m] == precursor_ion) && (middle != (int)graph.size() - 1) && (i != (int)graph.size() - 1)) { -#endif middle++; continue; } // create an edge cEdge e; + + formula.clear(); + string sumstr = bricksdatabasewithcombinations.calculateSummaryFromComposition(j); + formula.addFormula(sumstr); + formula.addFormula(parameters->fragmentdefinitions[parameters->fragmentionsfordenovograph[k]].summary, true); + formula.addFormula(parameters->fragmentdefinitions[parameters->fragmentionsfordenovograph[m]].summary); + + if ((parameters->peptidetype == branched) || (parameters->peptidetype == branchcyclic)) { + formula.addFormula(parameters->searchedmodifications[p].summary); + } + + if (termmass != 0) { + formula.addFormula(parameters->searchedmodifications[n].summary); + } if (i == (int)graph.size() - 1) { e.targetnode = i; @@ -790,8 +907,11 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { e.targetcharge = (parameters->precursorcharge > 0)?z1:-z1; e.targetintensity = graph[i].getIntensity(); e.composition = bricksdatabasewithcombinations[j].getComposition(); + e.summary = formula.getSummary(); e.endmodifID = n; e.middlemodifID = p; + e.sourceion = parameters->fragmentionsfordenovograph[k]; + e.targetion = parameters->fragmentionsfordenovograph[m]; // insert the new edge and/or attach the annotation to the source node if the edge exists graph[middle].insertTempEdge(e); @@ -805,12 +925,12 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { e.targetcharge = (parameters->precursorcharge > 0)?z2:-z2; e.targetintensity = graph[middle].getIntensity(); e.composition = bricksdatabasewithcombinations[j].getComposition(); + e.summary = formula.getSummary(); e.endmodifID = n; e.middlemodifID = p; // insert the new edge and/or attach the annotation to the source node if the edge exists graph[i].insertTempEdge(e); - } usedbrick = true; @@ -865,7 +985,7 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { int cDeNovoGraph::removeEdgesFormingPathsNotFinishingInPrecursor(bool& terminatecomputation) { - *os << "Removing edges forming blind paths (not finishing in the precursor)... "; + *os << "Removing edges forming incomplete paths (not finishing in the precursor)... "; double neutralprecursormass = uncharge(parameters->precursormass, parameters->precursorcharge); bool removed = true; bool isprecursor; @@ -912,7 +1032,7 @@ int cDeNovoGraph::removeEdgesFormingPathsNotFinishingInPrecursor(bool& terminate int cDeNovoGraph::removeEdgesFormingPathsNotStartingFromFirstNode(bool& terminatecomputation) { - *os << "Removing edges forming blind paths (not starting from the first node)... "; + *os << "Removing edges forming incomplete paths (not starting from the first node)... "; bool removed = true; int edgesremoved = 0; bool match; @@ -957,7 +1077,7 @@ int cDeNovoGraph::removeEdgesFormingPathsNotStartingFromFirstNode(bool& terminat int cDeNovoGraph::connectEdgesFormingPathsNotFinishingInPrecursor(bool& terminatecomputation) { *os << "Connecting edges with the precursor's node to generate sequence tags... "; - //*os << "Connecting edges forming blind paths (not finishing in the precursor)... "; + //*os << "Connecting edges forming incomplete paths (not finishing in the precursor)... "; int edgescreated = 0; int precursorposition = (int)graph.size() - 1; @@ -996,6 +1116,7 @@ int cDeNovoGraph::connectEdgesFormingPathsNotFinishingInPrecursor(bool& terminat b.setArtificial(true); bricksdatabasewithcombinations.push_back(b); + // -H2O brick (1) b.setName(to_string(e.massdifference - H2O)); b.setAcronyms(to_string(e.massdifference - H2O)); @@ -1016,8 +1137,6 @@ int cDeNovoGraph::connectEdgesFormingPathsNotFinishingInPrecursor(bool& terminat b.setArtificial(true); bricksdatabasewithcombinations.push_back(b); -#if OLIGOKETIDES == 1 - // -H2 brick (3) b.setName(to_string(e.massdifference - 2*H)); b.setAcronyms(to_string(e.massdifference - 2*H)); @@ -1037,7 +1156,7 @@ int cDeNovoGraph::connectEdgesFormingPathsNotFinishingInPrecursor(bool& terminat b.setComposition(to_string((int)bricksdatabasewithcombinations.size() + 1), false); b.setArtificial(true); bricksdatabasewithcombinations.push_back(b); - +/* // +O brick (5) b.setName(to_string(e.massdifference + O)); b.setAcronyms(to_string(e.massdifference + O)); @@ -1077,8 +1196,8 @@ int cDeNovoGraph::connectEdgesFormingPathsNotFinishingInPrecursor(bool& terminat b.setComposition(to_string((int)bricksdatabasewithcombinations.size() + 1), false); b.setArtificial(true); bricksdatabasewithcombinations.push_back(b); +*/ -#endif //} } @@ -1093,7 +1212,7 @@ int cDeNovoGraph::connectEdgesFormingPathsNotFinishingInPrecursor(bool& terminat int cDeNovoGraph::connectEdgesFormingPathsNotStartingFromFirstNode(bool& terminatecomputation) { *os << "Connecting edges with the starting node to generate sequence tags... "; - //*os << "Connecting edges forming blind paths (not starting from the first node)... "; + //*os << "Connecting edges forming incomplete paths (not starting from the first node)... "; int edgescreated = 0; //bool match; @@ -1241,7 +1360,7 @@ void cDeNovoGraph::printPaths(cMainThread* os, cDeNovoGraphNode& node, vector tmp; - cCandidate candidate(composition, tmp, 0, 0, 0, -1); + cCandidate candidate(composition, tmp, fragmentIonTypeEnd, 0, 0, 0, -1); *os << "bricks: " << getNumberOfBricks(candidate.getComposition()) << " edges: " << composition.size() << " composition: "; *os << candidate.getComposition(); @@ -1261,7 +1380,7 @@ void cDeNovoGraph::printPaths(cMainThread* os, cDeNovoGraphNode& node, vector 0) { g += ", terminal modification: " + parameters->searchedmodifications[graph[i][j].endmodifID].name; } + g += ", summary: " + graph[i][j].summary; + //g += ", source annotation" + to_string(graph[i][j].sourceion); + //g += ", target annotation" + to_string(graph[i][j].targetion); //g += graph[i][j].printSourceAnnotation(fragmentdefinitions); //g += "->"; //g += graph[i][j].printTargetAnnotation(fragmentdefinitions); diff --git a/CycloBranch/core/cDeNovoGraphNode.cpp b/CycloBranch/core/cDeNovoGraphNode.cpp index b75dd92..b7dc72c 100644 --- a/CycloBranch/core/cDeNovoGraphNode.cpp +++ b/CycloBranch/core/cDeNovoGraphNode.cpp @@ -14,7 +14,7 @@ void nodeEdge::load(ifstream& is) { bool operator == (cEdge const& a, cEdge const& b) { - return (a.targetnode == b.targetnode) && (a.brickid == b.brickid); + return (a.targetnode == b.targetnode) && (a.brickid == b.brickid) && (a.sourceion == b.sourceion) && (a.targetion == b.targetion); } @@ -126,3 +126,4 @@ bool cDeNovoGraphNode::checkIonAnnotation(eFragmentIonType iontype) { return ionannotation[iontype]; } + diff --git a/CycloBranch/core/cDeNovoGraphNode.h b/CycloBranch/core/cDeNovoGraphNode.h index ffdf579..14a1ba8 100644 --- a/CycloBranch/core/cDeNovoGraphNode.h +++ b/CycloBranch/core/cDeNovoGraphNode.h @@ -104,9 +104,15 @@ struct cEdge { /** - \brief Id of a terminal modification (at the end of a spectrum). + \brief summary formula as a string */ - int endmodifID; + string summary; + + + /** + \brief Id of a terminal modification (at the beginning of a spectrum). + */ + int startmodifID; /** @@ -115,6 +121,24 @@ struct cEdge { int middlemodifID; + /** + \brief Id of a terminal modification (at the end of a spectrum). + */ + int endmodifID; + + + /** + \brief Source ion name. + */ + eFragmentIonType sourceion; + + + /** + \brief Target ion name. + */ + eFragmentIonType targetion; + + /** \brief The constructor. */ @@ -135,8 +159,12 @@ struct cEdge { targetcharge = 1; targetintensity = 0; composition = ""; - endmodifID = 0; + summary = ""; + startmodifID = 0; middlemodifID = 0; + endmodifID = 0; + sourceion = fragmentIonTypeEnd; + targetion = fragmentIonTypeEnd; } }; @@ -153,7 +181,7 @@ struct hash_cEdge { \retval size_t hashed edge */ size_t operator()(const cEdge& e) const { - return std::hash()(e.targetnode) ^ std::hash()(e.brickid); + return std::hash()(e.targetnode) ^ std::hash()(e.brickid) ^ std::hash()((int)(e.sourceion)) ^ std::hash()((int)(e.targetion)); } }; diff --git a/CycloBranch/core/cFragmentIons.cpp b/CycloBranch/core/cFragmentIons.cpp index 6cf0034..04dfc0e 100644 --- a/CycloBranch/core/cFragmentIons.cpp +++ b/CycloBranch/core/cFragmentIons.cpp @@ -4,7 +4,9 @@ cPeriodicTableMap::cPeriodicTableMap() { table["H"] = H; + table["Hplus"] = Hplus; table["D"] = D; + table["T"] = T; table["Li"] = Li; table["Be"] = Be; table["B"] = B; @@ -181,12 +183,17 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi double cterminusshift = cycliccterminus?-H2O:0; double adductshift = 0; + string nterminusshiftsummary = cyclicnterminus?"H-2O-1":""; + string cterminusshiftsummary = cycliccterminus?"H-2O-1":""; + string adductshiftsummary = ""; + if (precursoradduct.compare("") != 0) { cSummaryFormula formula; formula.setFormula(precursoradduct); adductshift = formula.getMass() - H; + adductshiftsummary = formula.getSummary() + "H-1"; } - + // initialize A-ion fragmentions[a_ion].nterminal = true; fragmentions[a_ion].cterminal = false; @@ -221,6 +228,7 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[b_ion].name = "B"; fragmentions[b_ion].massdifference = B_ION + nterminusshift + adductshift; fragmentions[b_ion].parent = b_ion; + fragmentions[b_ion].summary = "Hplus" + nterminusshiftsummary + adductshiftsummary; // initialize B-H2O ion fragmentions[b_ion_dehydrated].nterminal = true; @@ -305,6 +313,7 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[y_ion].name = "Y"; fragmentions[y_ion].massdifference = Y_ION + cterminusshift + adductshift; fragmentions[y_ion].parent = y_ion; + fragmentions[y_ion].summary = "H2OHplus" + cterminusshiftsummary + adductshiftsummary; // initialize Y-H2O ion fragmentions[y_ion_dehydrated].nterminal = false; @@ -361,6 +370,7 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[precursor_ion].name = "[M+zH]+"; fragmentions[precursor_ion].massdifference = PRECURSOR_ION + nterminusshift + cterminusshift + adductshift; fragmentions[precursor_ion].parent = precursor_ion; + fragmentions[precursor_ion].summary = "H2OHplus" + nterminusshiftsummary + cterminusshiftsummary + adductshiftsummary; // initialize precursor ion - H2O fragmentions[precursor_ion_dehydrated].nterminal = false; @@ -467,48 +477,6 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[cyclic_precursor_ion_co_loss_and_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_CYCLIC - CO - H2O - NH3 + adductshift; fragmentions[cyclic_precursor_ion_co_loss_and_dehydrated_and_deamidated].parent = cyclic_precursor_ion_co_loss; - // initialize MS N-terminal ion H+ - fragmentions[ms_nterminal_ion_hplus].nterminal = true; - fragmentions[ms_nterminal_ion_hplus].cterminal = false; - fragmentions[ms_nterminal_ion_hplus].name = "N_H+"; - fragmentions[ms_nterminal_ion_hplus].massdifference = H2O + Hplus; - fragmentions[ms_nterminal_ion_hplus].parent = ms_nterminal_ion_hplus; - - // initialize MS N-terminal ion Na+ - fragmentions[ms_nterminal_ion_naplus].nterminal = true; - fragmentions[ms_nterminal_ion_naplus].cterminal = false; - fragmentions[ms_nterminal_ion_naplus].name = "N_Na+"; - fragmentions[ms_nterminal_ion_naplus].massdifference = H2O + Naplus; - fragmentions[ms_nterminal_ion_naplus].parent = ms_nterminal_ion_naplus; - - // initialize MS N-terminal ion K+ - fragmentions[ms_nterminal_ion_kplus].nterminal = true; - fragmentions[ms_nterminal_ion_kplus].cterminal = false; - fragmentions[ms_nterminal_ion_kplus].name = "N_K+"; - fragmentions[ms_nterminal_ion_kplus].massdifference = H2O + Kplus; - fragmentions[ms_nterminal_ion_kplus].parent = ms_nterminal_ion_kplus; - - // initialize MS C-terminal ion H+ - fragmentions[ms_cterminal_ion_hplus].nterminal = false; - fragmentions[ms_cterminal_ion_hplus].cterminal = true; - fragmentions[ms_cterminal_ion_hplus].name = "C_H+"; - fragmentions[ms_cterminal_ion_hplus].massdifference = H2O + Hplus; - fragmentions[ms_cterminal_ion_hplus].parent = ms_cterminal_ion_hplus; - - // initialize MS C-terminal ion Na+ - fragmentions[ms_cterminal_ion_naplus].nterminal = false; - fragmentions[ms_cterminal_ion_naplus].cterminal = true; - fragmentions[ms_cterminal_ion_naplus].name = "C_Na+"; - fragmentions[ms_cterminal_ion_naplus].massdifference = H2O + Naplus; - fragmentions[ms_cterminal_ion_naplus].parent = ms_cterminal_ion_naplus; - - // initialize MS C-terminal ion K+ - fragmentions[ms_cterminal_ion_kplus].nterminal = false; - fragmentions[ms_cterminal_ion_kplus].cterminal = true; - fragmentions[ms_cterminal_ion_kplus].name = "C_K+"; - fragmentions[ms_cterminal_ion_kplus].massdifference = H2O + Kplus; - fragmentions[ms_cterminal_ion_kplus].parent = ms_cterminal_ion_kplus; - // initialize ion H+ fragmentions[ms_hplus].nterminal = true; fragmentions[ms_hplus].cterminal = true; @@ -747,7 +715,7 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[ms_MCaH].parent = ms_MCaH; fragmentions[ms_MCaH].positive = true; fragmentions[ms_MCaH].multiplier = 1; - fragmentions[ms_MCaH].numberofisotopes = 1; + fragmentions[ms_MCaH].numberofisotopes = 0; // initialize ion [M+Ca-2H+Na]+ fragmentions[ms_MCa2HNa].nterminal = true; @@ -757,7 +725,7 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[ms_MCa2HNa].parent = ms_MCa2HNa; fragmentions[ms_MCa2HNa].positive = true; fragmentions[ms_MCa2HNa].multiplier = 1; - fragmentions[ms_MCa2HNa].numberofisotopes = 1; + fragmentions[ms_MCa2HNa].numberofisotopes = 0; // initialize ion [M+Ca-3H]- fragmentions[ms_MCa3H].nterminal = true; @@ -767,7 +735,37 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[ms_MCa3H].parent = ms_MCa3H; fragmentions[ms_MCa3H].positive = false; fragmentions[ms_MCa3H].multiplier = 1; - fragmentions[ms_MCa3H].numberofisotopes = 1; + fragmentions[ms_MCa3H].numberofisotopes = 0; + + // initialize ion [M+Cr-2H]+ + fragmentions[ms_MCr2H].nterminal = true; + fragmentions[ms_MCr2H].cterminal = true; + fragmentions[ms_MCr2H].name = "[M+Cr-2H]+"; + fragmentions[ms_MCr2H].massdifference = Cr - 3*H + Hplus; + fragmentions[ms_MCr2H].parent = ms_MCr2H; + fragmentions[ms_MCr2H].positive = true; + fragmentions[ms_MCr2H].multiplier = 1; + fragmentions[ms_MCr2H].numberofisotopes = 2; + + // initialize ion [M+Cr-3H+Na]+ + fragmentions[ms_MCr3HNa].nterminal = true; + fragmentions[ms_MCr3HNa].cterminal = true; + fragmentions[ms_MCr3HNa].name = "[M+Cr-3H+Na]+"; + fragmentions[ms_MCr3HNa].massdifference = Cr - 3*H + Naplus; + fragmentions[ms_MCr3HNa].parent = ms_MCr3HNa; + fragmentions[ms_MCr3HNa].positive = true; + fragmentions[ms_MCr3HNa].multiplier = 1; + fragmentions[ms_MCr3HNa].numberofisotopes = 2; + + // initialize ion [M+Cr-4H]- + fragmentions[ms_MCr4H].nterminal = true; + fragmentions[ms_MCr4H].cterminal = true; + fragmentions[ms_MCr4H].name = "[M+Cr-4H]-"; + fragmentions[ms_MCr4H].massdifference = Cr - 3*H - Hplus; + fragmentions[ms_MCr4H].parent = ms_MCr4H; + fragmentions[ms_MCr4H].positive = false; + fragmentions[ms_MCr4H].multiplier = 1; + fragmentions[ms_MCr4H].numberofisotopes = 2; // initialize ion [M+Mn-H]+ fragmentions[ms_MMnH].nterminal = true; @@ -837,7 +835,7 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[ms_MNiH].parent = ms_MNiH; fragmentions[ms_MNiH].positive = true; fragmentions[ms_MNiH].multiplier = 1; - fragmentions[ms_MNiH].numberofisotopes = 3; + fragmentions[ms_MNiH].numberofisotopes = 2; // initialize ion [M+Ni-2H+Na]+ fragmentions[ms_MNi2HNa].nterminal = true; @@ -847,7 +845,7 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[ms_MNi2HNa].parent = ms_MNi2HNa; fragmentions[ms_MNi2HNa].positive = true; fragmentions[ms_MNi2HNa].multiplier = 1; - fragmentions[ms_MNi2HNa].numberofisotopes = 3; + fragmentions[ms_MNi2HNa].numberofisotopes = 2; // initialize ion [M+Ni-3H]- fragmentions[ms_MNi3H].nterminal = true; @@ -857,7 +855,7 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[ms_MNi3H].parent = ms_MNi3H; fragmentions[ms_MNi3H].positive = false; fragmentions[ms_MNi3H].multiplier = 1; - fragmentions[ms_MNi3H].numberofisotopes = 3; + fragmentions[ms_MNi3H].numberofisotopes = 2; // initialize ion [M+Cu-H]+ fragmentions[ms_MCuH].nterminal = true; @@ -949,8 +947,6 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[ms_MGa4H].multiplier = 1; fragmentions[ms_MGa4H].numberofisotopes = 1; -#if OLIGOKETIDES == 1 - // initialize l0h ion fragmentions[l0h_ion].nterminal = true; fragmentions[l0h_ion].cterminal = false; @@ -1013,6 +1009,7 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[l1h_ion].name = "LB"; fragmentions[l1h_ion].massdifference = L1H_ION + adductshift; fragmentions[l1h_ion].parent = l1h_ion; + fragmentions[l1h_ion].summary = "Hplus" + adductshiftsummary; // initialize l1h-H2O ion fragmentions[l1h_ion_dehydrated].nterminal = true; @@ -1069,6 +1066,7 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[l2h_ion].name = "LB+2H"; fragmentions[l2h_ion].massdifference = L2H_ION + adductshift; fragmentions[l2h_ion].parent = l2h_ion; + fragmentions[l2h_ion].summary = "H2Hplus" + adductshiftsummary; // initialize l2h-H2O ion fragmentions[l2h_ion_dehydrated].nterminal = true; @@ -1237,6 +1235,7 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[l1oh_ion].name = "LY-2H"; fragmentions[l1oh_ion].massdifference = L1OH_ION + adductshift; fragmentions[l1oh_ion].parent = l1oh_ion; + fragmentions[l1oh_ion].summary = "OHplus" + adductshiftsummary; // initialize l1oh-H2O ion fragmentions[l1oh_ion_dehydrated].nterminal = false; @@ -1293,6 +1292,7 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[l2oh_ion].name = "LY"; fragmentions[l2oh_ion].massdifference = L2OH_ION + adductshift; fragmentions[l2oh_ion].parent = l2oh_ion; + fragmentions[l2oh_ion].summary = "H2OHplus" + adductshiftsummary; // initialize l2oh-H2O ion fragmentions[l2oh_ion_dehydrated].nterminal = false; @@ -1455,230 +1455,233 @@ void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cyclicctermi fragmentions[r2oh_ion_co_loss_dehydrated_and_deamidated].massdifference = R2OH_ION - CO - H2O - NH3 + adductshift; fragmentions[r2oh_ion_co_loss_dehydrated_and_deamidated].parent = r2oh_ion; - // initialize linear oligoketide precursor ion (H-...-H) - fragmentions[linear_oligoketide_precursor_ion_h_h].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h].name = "[M+zH]+ (H-...-H)"; - fragmentions[linear_oligoketide_precursor_ion_h_h].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_H + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_h].parent = linear_oligoketide_precursor_ion_h_h; - - // initialize linear oligoketide precursor ion (H-...-H) - H2O - fragmentions[linear_oligoketide_precursor_ion_h_h_dehydrated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h_dehydrated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h_dehydrated].name = "[M+zH]+ * (H-...-H)"; - fragmentions[linear_oligoketide_precursor_ion_h_h_dehydrated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_H - H2O + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_h_dehydrated].parent = linear_oligoketide_precursor_ion_h_h; - - // initialize linear oligoketide precursor ion (H-...-H) - NH3 - fragmentions[linear_oligoketide_precursor_ion_h_h_deamidated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h_deamidated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h_deamidated].name = "[M+zH]+ x (H-...-H)"; - fragmentions[linear_oligoketide_precursor_ion_h_h_deamidated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_H - NH3 + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_h_deamidated].parent = linear_oligoketide_precursor_ion_h_h; - - // initialize linear oligoketide precursor ion (H-...-H) - H2O - NH3 - fragmentions[linear_oligoketide_precursor_ion_h_h_dehydrated_and_deamidated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h_dehydrated_and_deamidated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h_dehydrated_and_deamidated].name = "[M+zH]+ *x (H-...-H)"; - fragmentions[linear_oligoketide_precursor_ion_h_h_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_H - H2O - NH3 + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_h_dehydrated_and_deamidated].parent = linear_oligoketide_precursor_ion_h_h; - - // initialize linear oligoketide precursor ion (H-...-H) - CO - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss].name = "[M+zH]+ -CO (H-...-H)"; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_H - CO + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss].parent = linear_oligoketide_precursor_ion_h_h_co_loss; - - // initialize linear oligoketide precursor ion (H-...-H) - CO - H2O - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_dehydrated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_dehydrated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_dehydrated].name = "[M+zH]+ *-CO (H-...-H)"; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_dehydrated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_H - CO - H2O + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_dehydrated].parent = linear_oligoketide_precursor_ion_h_h_co_loss; - - // initialize linear oligoketide precursor ion (H-...-H) - CO - NH3 - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_deamidated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_deamidated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_deamidated].name = "[M+zH]+ x-CO (H-...-H)"; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_deamidated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_H - CO - NH3 + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_deamidated].parent = linear_oligoketide_precursor_ion_h_h_co_loss; - - // initialize linear oligoketide precursor ion (H-...-H) - CO - H2O - NH3 - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_dehydrated_and_deamidated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_dehydrated_and_deamidated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_dehydrated_and_deamidated].name = "[M+zH]+ *x-CO (H-...-H)"; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_H - CO - H2O - NH3 + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_h_co_loss_dehydrated_and_deamidated].parent = linear_oligoketide_precursor_ion_h_h_co_loss; - - // initialize linear oligoketide precursor ion (H-...-OH) - fragmentions[linear_oligoketide_precursor_ion_h_oh].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh].name = "[M+zH]+ (H-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_h_oh].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_OH + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_oh].parent = linear_oligoketide_precursor_ion_h_oh; - - // initialize linear oligoketide precursor ion (H-...-OH) - H2O - fragmentions[linear_oligoketide_precursor_ion_h_oh_dehydrated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh_dehydrated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh_dehydrated].name = "[M+zH]+ * (H-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_h_oh_dehydrated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_OH - H2O + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_oh_dehydrated].parent = linear_oligoketide_precursor_ion_h_oh; - - // initialize linear oligoketide precursor ion (H-...-OH) - NH3 - fragmentions[linear_oligoketide_precursor_ion_h_oh_deamidated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh_deamidated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh_deamidated].name = "[M+zH]+ x (H-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_h_oh_deamidated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_OH - NH3 + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_oh_deamidated].parent = linear_oligoketide_precursor_ion_h_oh; - - // initialize linear oligoketide precursor ion (H-...-OH) - H2O - NH3 - fragmentions[linear_oligoketide_precursor_ion_h_oh_dehydrated_and_deamidated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh_dehydrated_and_deamidated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh_dehydrated_and_deamidated].name = "[M+zH]+ *x (H-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_h_oh_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_OH - H2O - NH3 + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_oh_dehydrated_and_deamidated].parent = linear_oligoketide_precursor_ion_h_oh; - - // initialize linear oligoketide precursor ion (H-...-OH) - CO - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss].name = "[M+zH]+ -CO (H-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_OH - CO + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss].parent = linear_oligoketide_precursor_ion_h_oh_co_loss; - - // initialize linear oligoketide precursor ion (H-...-OH) - CO - H2O - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_dehydrated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_dehydrated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_dehydrated].name = "[M+zH]+ *-CO (H-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_dehydrated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_OH - CO - H2O + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_dehydrated].parent = linear_oligoketide_precursor_ion_h_oh_co_loss; - - // initialize linear oligoketide precursor ion (H-...-OH) - CO - NH3 - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_deamidated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_deamidated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_deamidated].name = "[M+zH]+ x-CO (H-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_deamidated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_OH - CO - NH3 + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_deamidated].parent = linear_oligoketide_precursor_ion_h_oh_co_loss; - - // initialize linear oligoketide precursor ion (H-...-OH) - CO - H2O - NH3 - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_dehydrated_and_deamidated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_dehydrated_and_deamidated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_dehydrated_and_deamidated].name = "[M+zH]+ *x-CO (H-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_OH - CO - H2O - NH3 + adductshift; - fragmentions[linear_oligoketide_precursor_ion_h_oh_co_loss_dehydrated_and_deamidated].parent = linear_oligoketide_precursor_ion_h_oh_co_loss; - - // initialize linear oligoketide precursor ion (HO-...-OH) - fragmentions[linear_oligoketide_precursor_ion_oh_oh].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh].name = "[M+zH]+ (HO-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_oh_oh].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_OH_OH + adductshift; - fragmentions[linear_oligoketide_precursor_ion_oh_oh].parent = linear_oligoketide_precursor_ion_oh_oh; - - // initialize linear oligoketide precursor ion (HO-...-OH) - H2O - fragmentions[linear_oligoketide_precursor_ion_oh_oh_dehydrated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_dehydrated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_dehydrated].name = "[M+zH]+ * (HO-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_dehydrated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_OH_OH - H2O + adductshift; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_dehydrated].parent = linear_oligoketide_precursor_ion_oh_oh; - - // initialize linear oligoketide precursor ion (HO-...-OH) - NH3 - fragmentions[linear_oligoketide_precursor_ion_oh_oh_deamidated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_deamidated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_deamidated].name = "[M+zH]+ x (HO-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_deamidated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_OH_OH - NH3 + adductshift; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_deamidated].parent = linear_oligoketide_precursor_ion_oh_oh; - - // initialize linear oligoketide precursor ion (HO-...-OH) - H2O - NH3 - fragmentions[linear_oligoketide_precursor_ion_oh_oh_dehydrated_and_deamidated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_dehydrated_and_deamidated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_dehydrated_and_deamidated].name = "[M+zH]+ *x (HO-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_OH_OH - H2O - NH3 + adductshift; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_dehydrated_and_deamidated].parent = linear_oligoketide_precursor_ion_oh_oh; - - // initialize linear oligoketide precursor ion (HO-...-OH) - CO - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss].name = "[M+zH]+ -CO (HO-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_OH_OH - CO + adductshift; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss].parent = linear_oligoketide_precursor_ion_oh_oh_co_loss; - - // initialize linear oligoketide precursor ion (HO-...-OH) - CO - H2O - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_dehydrated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_dehydrated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_dehydrated].name = "[M+zH]+ *-CO (HO-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_dehydrated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_OH_OH - CO - H2O + adductshift; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_dehydrated].parent = linear_oligoketide_precursor_ion_oh_oh_co_loss; - - // initialize linear oligoketide precursor ion (HO-...-OH) - CO - NH3 - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_deamidated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_deamidated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_deamidated].name = "[M+zH]+ x-CO (HO-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_deamidated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_OH_OH - CO - NH3 + adductshift; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_deamidated].parent = linear_oligoketide_precursor_ion_oh_oh_co_loss; - - // initialize linear oligoketide precursor ion (HO-...-OH) - CO - H2O - NH3 - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated].nterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated].cterminal = false; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated].name = "[M+zH]+ *x-CO (HO-...-OH)"; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_LINEAR_OLIGOKETIDE_OH_OH - CO - H2O - NH3 + adductshift; - fragmentions[linear_oligoketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated].parent = linear_oligoketide_precursor_ion_oh_oh_co_loss; - - // initialize cyclic oligoketide precursor ion - fragmentions[cyclic_oligoketide_precursor_ion].nterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion].cterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion].name = "[M+zH]+"; - fragmentions[cyclic_oligoketide_precursor_ion].massdifference = Hplus + adductshift; - fragmentions[cyclic_oligoketide_precursor_ion].parent = cyclic_oligoketide_precursor_ion; - - // initialize cyclic oligoketide precursor ion - H2O - fragmentions[cyclic_oligoketide_precursor_ion_dehydrated].nterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion_dehydrated].cterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion_dehydrated].name = "[M+zH]+ *"; - fragmentions[cyclic_oligoketide_precursor_ion_dehydrated].massdifference = Hplus - H2O + adductshift; - fragmentions[cyclic_oligoketide_precursor_ion_dehydrated].parent = cyclic_oligoketide_precursor_ion; - - // initialize cyclic oligoketide precursor ion - NH3 - fragmentions[cyclic_oligoketide_precursor_ion_deamidated].nterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion_deamidated].cterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion_deamidated].name = "[M+zH]+ x"; - fragmentions[cyclic_oligoketide_precursor_ion_deamidated].massdifference = Hplus - NH3 + adductshift; - fragmentions[cyclic_oligoketide_precursor_ion_deamidated].parent = cyclic_oligoketide_precursor_ion; - - // initialize cyclic oligoketide precursor ion - H2O - NH3 - fragmentions[cyclic_oligoketide_precursor_ion_dehydrated_and_deamidated].nterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion_dehydrated_and_deamidated].cterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion_dehydrated_and_deamidated].name = "[M+zH]+ *x"; - fragmentions[cyclic_oligoketide_precursor_ion_dehydrated_and_deamidated].massdifference = Hplus - H2O - NH3 + adductshift; - fragmentions[cyclic_oligoketide_precursor_ion_dehydrated_and_deamidated].parent = cyclic_oligoketide_precursor_ion; - - // initialize cyclic oligoketide precursor ion - CO - fragmentions[cyclic_oligoketide_precursor_ion_co_loss].nterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss].cterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss].name = "[M+zH]+ -CO"; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss].massdifference = Hplus - CO + adductshift; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss].parent = cyclic_oligoketide_precursor_ion_co_loss; - - // initialize cyclic oligoketide precursor ion - CO - H2O - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_dehydrated].nterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_dehydrated].cterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_dehydrated].name = "[M+zH]+ *-CO"; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_dehydrated].massdifference = Hplus - CO - H2O + adductshift; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_dehydrated].parent = cyclic_oligoketide_precursor_ion_co_loss; - - // initialize cyclic oligoketide precursor ion - CO - NH3 - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_deamidated].nterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_deamidated].cterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_deamidated].name = "[M+zH]+ x-CO"; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_deamidated].massdifference = Hplus - CO - NH3 + adductshift; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_deamidated].parent = cyclic_oligoketide_precursor_ion_co_loss; - - // initialize cyclic oligoketide precursor ion - CO - H2O - NH3 - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_dehydrated_and_deamidated].nterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_dehydrated_and_deamidated].cterminal = false; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_dehydrated_and_deamidated].name = "[M+zH]+ *x-CO"; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_dehydrated_and_deamidated].massdifference = Hplus - CO - H2O - NH3 + adductshift; - fragmentions[cyclic_oligoketide_precursor_ion_co_loss_dehydrated_and_deamidated].parent = cyclic_oligoketide_precursor_ion_co_loss; -#endif + // initialize linear polyketide precursor ion (H-...-H) + fragmentions[linear_polyketide_precursor_ion_h_h].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h].name = "[M+zH]+ (H-...-H)"; + fragmentions[linear_polyketide_precursor_ion_h_h].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_H + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_h].parent = linear_polyketide_precursor_ion_h_h; + fragmentions[linear_polyketide_precursor_ion_h_h].summary = "H2Hplus" + nterminusshiftsummary + cterminusshiftsummary + adductshiftsummary; + + // initialize linear polyketide precursor ion (H-...-H) - H2O + fragmentions[linear_polyketide_precursor_ion_h_h_dehydrated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h_dehydrated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h_dehydrated].name = "[M+zH]+ * (H-...-H)"; + fragmentions[linear_polyketide_precursor_ion_h_h_dehydrated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_H - H2O + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_h_dehydrated].parent = linear_polyketide_precursor_ion_h_h; + + // initialize linear polyketide precursor ion (H-...-H) - NH3 + fragmentions[linear_polyketide_precursor_ion_h_h_deamidated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h_deamidated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h_deamidated].name = "[M+zH]+ x (H-...-H)"; + fragmentions[linear_polyketide_precursor_ion_h_h_deamidated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_H - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_h_deamidated].parent = linear_polyketide_precursor_ion_h_h; + + // initialize linear polyketide precursor ion (H-...-H) - H2O - NH3 + fragmentions[linear_polyketide_precursor_ion_h_h_dehydrated_and_deamidated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h_dehydrated_and_deamidated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h_dehydrated_and_deamidated].name = "[M+zH]+ *x (H-...-H)"; + fragmentions[linear_polyketide_precursor_ion_h_h_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_H - H2O - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_h_dehydrated_and_deamidated].parent = linear_polyketide_precursor_ion_h_h; + + // initialize linear polyketide precursor ion (H-...-H) - CO + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss].name = "[M+zH]+ -CO (H-...-H)"; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_H - CO + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss].parent = linear_polyketide_precursor_ion_h_h_co_loss; + + // initialize linear polyketide precursor ion (H-...-H) - CO - H2O + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_dehydrated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_dehydrated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_dehydrated].name = "[M+zH]+ *-CO (H-...-H)"; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_dehydrated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_H - CO - H2O + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_dehydrated].parent = linear_polyketide_precursor_ion_h_h_co_loss; + + // initialize linear polyketide precursor ion (H-...-H) - CO - NH3 + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_deamidated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_deamidated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_deamidated].name = "[M+zH]+ x-CO (H-...-H)"; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_deamidated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_H - CO - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_deamidated].parent = linear_polyketide_precursor_ion_h_h_co_loss; + + // initialize linear polyketide precursor ion (H-...-H) - CO - H2O - NH3 + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_dehydrated_and_deamidated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_dehydrated_and_deamidated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_dehydrated_and_deamidated].name = "[M+zH]+ *x-CO (H-...-H)"; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_H - CO - H2O - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_h_co_loss_dehydrated_and_deamidated].parent = linear_polyketide_precursor_ion_h_h_co_loss; + + // initialize linear polyketide precursor ion (H-...-OH) + fragmentions[linear_polyketide_precursor_ion_h_oh].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh].name = "[M+zH]+ (H-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_h_oh].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_OH + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_oh].parent = linear_polyketide_precursor_ion_h_oh; + fragmentions[linear_polyketide_precursor_ion_h_oh].summary = "H2OHplus" + nterminusshiftsummary + cterminusshiftsummary + adductshiftsummary; + + // initialize linear polyketide precursor ion (H-...-OH) - H2O + fragmentions[linear_polyketide_precursor_ion_h_oh_dehydrated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh_dehydrated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh_dehydrated].name = "[M+zH]+ * (H-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_h_oh_dehydrated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_OH - H2O + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_oh_dehydrated].parent = linear_polyketide_precursor_ion_h_oh; + + // initialize linear polyketide precursor ion (H-...-OH) - NH3 + fragmentions[linear_polyketide_precursor_ion_h_oh_deamidated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh_deamidated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh_deamidated].name = "[M+zH]+ x (H-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_h_oh_deamidated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_OH - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_oh_deamidated].parent = linear_polyketide_precursor_ion_h_oh; + + // initialize linear polyketide precursor ion (H-...-OH) - H2O - NH3 + fragmentions[linear_polyketide_precursor_ion_h_oh_dehydrated_and_deamidated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh_dehydrated_and_deamidated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh_dehydrated_and_deamidated].name = "[M+zH]+ *x (H-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_h_oh_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_OH - H2O - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_oh_dehydrated_and_deamidated].parent = linear_polyketide_precursor_ion_h_oh; + + // initialize linear polyketide precursor ion (H-...-OH) - CO + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss].name = "[M+zH]+ -CO (H-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_OH - CO + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss].parent = linear_polyketide_precursor_ion_h_oh_co_loss; + + // initialize linear polyketide precursor ion (H-...-OH) - CO - H2O + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_dehydrated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_dehydrated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_dehydrated].name = "[M+zH]+ *-CO (H-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_dehydrated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_OH - CO - H2O + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_dehydrated].parent = linear_polyketide_precursor_ion_h_oh_co_loss; + + // initialize linear polyketide precursor ion (H-...-OH) - CO - NH3 + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_deamidated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_deamidated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_deamidated].name = "[M+zH]+ x-CO (H-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_deamidated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_OH - CO - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_deamidated].parent = linear_polyketide_precursor_ion_h_oh_co_loss; + + // initialize linear polyketide precursor ion (H-...-OH) - CO - H2O - NH3 + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_dehydrated_and_deamidated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_dehydrated_and_deamidated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_dehydrated_and_deamidated].name = "[M+zH]+ *x-CO (H-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_H_OH - CO - H2O - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_h_oh_co_loss_dehydrated_and_deamidated].parent = linear_polyketide_precursor_ion_h_oh_co_loss; + + // initialize linear polyketide precursor ion (HO-...-OH) + fragmentions[linear_polyketide_precursor_ion_oh_oh].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh].name = "[M+zH]+ (HO-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_oh_oh].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_OH_OH + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_oh_oh].parent = linear_polyketide_precursor_ion_oh_oh; + fragmentions[linear_polyketide_precursor_ion_oh_oh].summary = "H2O2Hplus" + nterminusshiftsummary + cterminusshiftsummary + adductshiftsummary; + + // initialize linear polyketide precursor ion (HO-...-OH) - H2O + fragmentions[linear_polyketide_precursor_ion_oh_oh_dehydrated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh_dehydrated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh_dehydrated].name = "[M+zH]+ * (HO-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_oh_oh_dehydrated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_OH_OH - H2O + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_oh_oh_dehydrated].parent = linear_polyketide_precursor_ion_oh_oh; + + // initialize linear polyketide precursor ion (HO-...-OH) - NH3 + fragmentions[linear_polyketide_precursor_ion_oh_oh_deamidated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh_deamidated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh_deamidated].name = "[M+zH]+ x (HO-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_oh_oh_deamidated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_OH_OH - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_oh_oh_deamidated].parent = linear_polyketide_precursor_ion_oh_oh; + + // initialize linear polyketide precursor ion (HO-...-OH) - H2O - NH3 + fragmentions[linear_polyketide_precursor_ion_oh_oh_dehydrated_and_deamidated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh_dehydrated_and_deamidated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh_dehydrated_and_deamidated].name = "[M+zH]+ *x (HO-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_oh_oh_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_OH_OH - H2O - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_oh_oh_dehydrated_and_deamidated].parent = linear_polyketide_precursor_ion_oh_oh; + + // initialize linear polyketide precursor ion (HO-...-OH) - CO + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss].name = "[M+zH]+ -CO (HO-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_OH_OH - CO + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss].parent = linear_polyketide_precursor_ion_oh_oh_co_loss; + + // initialize linear polyketide precursor ion (HO-...-OH) - CO - H2O + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_dehydrated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_dehydrated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_dehydrated].name = "[M+zH]+ *-CO (HO-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_dehydrated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_OH_OH - CO - H2O + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_dehydrated].parent = linear_polyketide_precursor_ion_oh_oh_co_loss; + + // initialize linear polyketide precursor ion (HO-...-OH) - CO - NH3 + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_deamidated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_deamidated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_deamidated].name = "[M+zH]+ x-CO (HO-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_deamidated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_OH_OH - CO - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_deamidated].parent = linear_polyketide_precursor_ion_oh_oh_co_loss; + + // initialize linear polyketide precursor ion (HO-...-OH) - CO - H2O - NH3 + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated].nterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated].cterminal = false; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated].name = "[M+zH]+ *x-CO (HO-...-OH)"; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_LINEAR_POLYKETIDE_OH_OH - CO - H2O - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[linear_polyketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated].parent = linear_polyketide_precursor_ion_oh_oh_co_loss; + + // initialize cyclic polyketide precursor ion + fragmentions[cyclic_polyketide_precursor_ion].nterminal = false; + fragmentions[cyclic_polyketide_precursor_ion].cterminal = false; + fragmentions[cyclic_polyketide_precursor_ion].name = "[M+zH]+"; + fragmentions[cyclic_polyketide_precursor_ion].massdifference = Hplus + adductshift; + fragmentions[cyclic_polyketide_precursor_ion].parent = cyclic_polyketide_precursor_ion; + fragmentions[cyclic_polyketide_precursor_ion].summary = "Hplus" + adductshiftsummary; + + // initialize cyclic polyketide precursor ion - H2O + fragmentions[cyclic_polyketide_precursor_ion_dehydrated].nterminal = false; + fragmentions[cyclic_polyketide_precursor_ion_dehydrated].cterminal = false; + fragmentions[cyclic_polyketide_precursor_ion_dehydrated].name = "[M+zH]+ *"; + fragmentions[cyclic_polyketide_precursor_ion_dehydrated].massdifference = Hplus - H2O + adductshift; + fragmentions[cyclic_polyketide_precursor_ion_dehydrated].parent = cyclic_polyketide_precursor_ion; + + // initialize cyclic polyketide precursor ion - NH3 + fragmentions[cyclic_polyketide_precursor_ion_deamidated].nterminal = false; + fragmentions[cyclic_polyketide_precursor_ion_deamidated].cterminal = false; + fragmentions[cyclic_polyketide_precursor_ion_deamidated].name = "[M+zH]+ x"; + fragmentions[cyclic_polyketide_precursor_ion_deamidated].massdifference = Hplus - NH3 + adductshift; + fragmentions[cyclic_polyketide_precursor_ion_deamidated].parent = cyclic_polyketide_precursor_ion; + + // initialize cyclic polyketide precursor ion - H2O - NH3 + fragmentions[cyclic_polyketide_precursor_ion_dehydrated_and_deamidated].nterminal = false; + fragmentions[cyclic_polyketide_precursor_ion_dehydrated_and_deamidated].cterminal = false; + fragmentions[cyclic_polyketide_precursor_ion_dehydrated_and_deamidated].name = "[M+zH]+ *x"; + fragmentions[cyclic_polyketide_precursor_ion_dehydrated_and_deamidated].massdifference = Hplus - H2O - NH3 + adductshift; + fragmentions[cyclic_polyketide_precursor_ion_dehydrated_and_deamidated].parent = cyclic_polyketide_precursor_ion; + + // initialize cyclic polyketide precursor ion - CO + fragmentions[cyclic_polyketide_precursor_ion_co_loss].nterminal = false; + fragmentions[cyclic_polyketide_precursor_ion_co_loss].cterminal = false; + fragmentions[cyclic_polyketide_precursor_ion_co_loss].name = "[M+zH]+ -CO"; + fragmentions[cyclic_polyketide_precursor_ion_co_loss].massdifference = Hplus - CO + adductshift; + fragmentions[cyclic_polyketide_precursor_ion_co_loss].parent = cyclic_polyketide_precursor_ion_co_loss; + + // initialize cyclic polyketide precursor ion - CO - H2O + fragmentions[cyclic_polyketide_precursor_ion_co_loss_dehydrated].nterminal = false; + fragmentions[cyclic_polyketide_precursor_ion_co_loss_dehydrated].cterminal = false; + fragmentions[cyclic_polyketide_precursor_ion_co_loss_dehydrated].name = "[M+zH]+ *-CO"; + fragmentions[cyclic_polyketide_precursor_ion_co_loss_dehydrated].massdifference = Hplus - CO - H2O + adductshift; + fragmentions[cyclic_polyketide_precursor_ion_co_loss_dehydrated].parent = cyclic_polyketide_precursor_ion_co_loss; + + // initialize cyclic polyketide precursor ion - CO - NH3 + fragmentions[cyclic_polyketide_precursor_ion_co_loss_deamidated].nterminal = false; + fragmentions[cyclic_polyketide_precursor_ion_co_loss_deamidated].cterminal = false; + fragmentions[cyclic_polyketide_precursor_ion_co_loss_deamidated].name = "[M+zH]+ x-CO"; + fragmentions[cyclic_polyketide_precursor_ion_co_loss_deamidated].massdifference = Hplus - CO - NH3 + adductshift; + fragmentions[cyclic_polyketide_precursor_ion_co_loss_deamidated].parent = cyclic_polyketide_precursor_ion_co_loss; + + // initialize cyclic polyketide precursor ion - CO - H2O - NH3 + fragmentions[cyclic_polyketide_precursor_ion_co_loss_dehydrated_and_deamidated].nterminal = false; + fragmentions[cyclic_polyketide_precursor_ion_co_loss_dehydrated_and_deamidated].cterminal = false; + fragmentions[cyclic_polyketide_precursor_ion_co_loss_dehydrated_and_deamidated].name = "[M+zH]+ *x-CO"; + fragmentions[cyclic_polyketide_precursor_ion_co_loss_dehydrated_and_deamidated].massdifference = Hplus - CO - H2O - NH3 + adductshift; + fragmentions[cyclic_polyketide_precursor_ion_co_loss_dehydrated_and_deamidated].parent = cyclic_polyketide_precursor_ion_co_loss; // initialize B-2H ion //fragmentions[b_ion_2H_loss].nterminal = true; @@ -1741,35 +1744,22 @@ void initializeFragmentIonsForDeNovoGraphOfBranchCyclicPeptides(vector& fragmentions) { +void initializeFragmentIonsForDeNovoGraphOfLinearPolyketide(vector& fragmentions) { fragmentions.push_back(l1h_ion); fragmentions.push_back(l2h_ion); fragmentions.push_back(l1oh_ion); fragmentions.push_back(l2oh_ion); - fragmentions.push_back(linear_oligoketide_precursor_ion_h_h); - fragmentions.push_back(linear_oligoketide_precursor_ion_h_oh); - fragmentions.push_back(linear_oligoketide_precursor_ion_oh_oh); + fragmentions.push_back(linear_polyketide_precursor_ion_h_h); + fragmentions.push_back(linear_polyketide_precursor_ion_h_oh); + fragmentions.push_back(linear_polyketide_precursor_ion_oh_oh); } -void initializeFragmentIonsForDeNovoGraphOfCyclicOligoketide(vector& fragmentions) { +void initializeFragmentIonsForDeNovoGraphOfCyclicPolyketide(vector& fragmentions) { //fragmentions.push_back(l0h_ion); fragmentions.push_back(l1h_ion); fragmentions.push_back(l2h_ion); - fragmentions.push_back(cyclic_oligoketide_precursor_ion); -} - - -#endif - - -void initializeFragmentIonsForDeNovoGraphOfLinearPolysaccharide(vector& fragmentions) { - fragmentions.push_back(ms_nterminal_ion_hplus); - //fragmentions.push_back(ms_cterminal_ion_hplus); - fragmentions.push_back(precursor_ion); + fragmentions.push_back(cyclic_polyketide_precursor_ion); } diff --git a/CycloBranch/core/cFragmentIons.h b/CycloBranch/core/cFragmentIons.h index 1578f4c..ea650be 100644 --- a/CycloBranch/core/cFragmentIons.h +++ b/CycloBranch/core/cFragmentIons.h @@ -27,6 +27,7 @@ const double Kplus = 38.963158; const double Liplus = 7.015455; const double H = 1.0078250321; const double D = 2.014102; +const double T = 3.016049; const double Li = 7.016004; const double Be = 9.012182; const double B = 11.009306; @@ -132,25 +133,22 @@ const double Lr = 262.109802; const double R = 0; const double X = 0; const double e = H - Hplus; -//const double neutron = D - H; - -const double Li6 = 6.015122; -const double Mg25 = 24.985837; -const double Mg26 = 25.982593; -const double K41 = 40.961825; -const double Ca44 = 43.95548; -const double Fe54 = 53.939612; -//const double Fe57 = 56.935396; -//const double Fe58 = 57.933278; -const double Ni60 = 59.930788; -const double Ni61 = 60.931061; -const double Ni62 = 61.928346; -//const double Ni64 = 63.927968; -const double Cu65 = 64.927793; -const double Zn66 = 65.926034; -const double Zn67 = 66.927129; -const double Zn68 = 67.924846; -const double Ga71 = 70.9247; + +// if isotopes are changed then fragmentions[xxx].numberofisotopes must be also fixed ! +const double Li6 = 6.015122; // 7.5% +const double Mg25 = 24.985837; // 10% +const double Mg26 = 25.982593; // 11.01% +const double K41 = 40.961825; // 6.73% +const double Cr50 = 49.946046; // 4.345% +const double Cr53 = 52.940651; // 9.501% +const double Fe54 = 53.939612; // 5.8% +const double Ni60 = 59.930788; // 26.223% +const double Ni62 = 61.928346; // 3.634% +const double Cu65 = 64.927793; // 30.85% +const double Zn66 = 65.926034; // 27.9% +const double Zn67 = 66.927129; // 4.1% +const double Zn68 = 67.924846; // 18.8% +const double Ga71 = 70.9247; // 39.89% /** @@ -201,21 +199,19 @@ const double Z_ION = Hplus + O - N - H; const double PRECURSOR_ION = Hplus + H2O; const double PRECURSOR_ION_CYCLIC = Hplus; -#if OLIGOKETIDES == 1 - const double L0H_ION = Hplus - 2 * H; - const double L1H_ION = Hplus; - const double L2H_ION = Hplus + 2 * H; - const double R1H_ION = Hplus; - const double R2H_ION = Hplus + 2 * H; - const double L1OH_ION = Hplus + O; - const double L2OH_ION = Hplus + H2O; - const double R1OH_ION = Hplus + O; - const double R2OH_ION = Hplus + H2O; - - const double PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_H = Hplus + 2 * H; - const double PRECURSOR_ION_LINEAR_OLIGOKETIDE_H_OH = Hplus + H2O; - const double PRECURSOR_ION_LINEAR_OLIGOKETIDE_OH_OH = Hplus + 2 * H + 2 * O; -#endif +const double L0H_ION = Hplus - 2 * H; +const double L1H_ION = Hplus; +const double L2H_ION = Hplus + 2 * H; +const double R1H_ION = Hplus; +const double R2H_ION = Hplus + 2 * H; +const double L1OH_ION = Hplus + O; +const double L2OH_ION = Hplus + H2O; +const double R1OH_ION = Hplus + O; +const double R2OH_ION = Hplus + H2O; + +const double PRECURSOR_ION_LINEAR_POLYKETIDE_H_H = Hplus + 2 * H; +const double PRECURSOR_ION_LINEAR_POLYKETIDE_H_OH = Hplus + H2O; +const double PRECURSOR_ION_LINEAR_POLYKETIDE_OH_OH = Hplus + 2 * H + 2 * O; /** @@ -286,12 +282,6 @@ enum eFragmentIonType { cyclic_precursor_ion_co_loss_and_dehydrated, cyclic_precursor_ion_co_loss_and_deamidated, cyclic_precursor_ion_co_loss_and_dehydrated_and_deamidated, - ms_nterminal_ion_hplus, - ms_nterminal_ion_naplus, - ms_nterminal_ion_kplus, - ms_cterminal_ion_hplus, - ms_cterminal_ion_naplus, - ms_cterminal_ion_kplus, ms_hplus, ms_naplus, ms_kplus, @@ -318,6 +308,9 @@ enum eFragmentIonType { ms_MCaH, ms_MCa2HNa, ms_MCa3H, + ms_MCr2H, + ms_MCr3HNa, + ms_MCr4H, ms_MMnH, ms_MMn2HNa, ms_MMn3H, @@ -336,7 +329,6 @@ enum eFragmentIonType { ms_MGa2H, ms_MGa3HNa, ms_MGa4H, -#if OLIGOKETIDES == 1 l0h_ion, l0h_ion_dehydrated, l0h_ion_deamidated, @@ -409,40 +401,38 @@ enum eFragmentIonType { r2oh_ion_co_loss_dehydrated, r2oh_ion_co_loss_deamidated, r2oh_ion_co_loss_dehydrated_and_deamidated, - linear_oligoketide_precursor_ion_h_h, - linear_oligoketide_precursor_ion_h_h_dehydrated, - linear_oligoketide_precursor_ion_h_h_deamidated, - linear_oligoketide_precursor_ion_h_h_dehydrated_and_deamidated, - linear_oligoketide_precursor_ion_h_h_co_loss, - linear_oligoketide_precursor_ion_h_h_co_loss_dehydrated, - linear_oligoketide_precursor_ion_h_h_co_loss_deamidated, - linear_oligoketide_precursor_ion_h_h_co_loss_dehydrated_and_deamidated, - linear_oligoketide_precursor_ion_h_oh, - linear_oligoketide_precursor_ion_h_oh_dehydrated, - linear_oligoketide_precursor_ion_h_oh_deamidated, - linear_oligoketide_precursor_ion_h_oh_dehydrated_and_deamidated, - linear_oligoketide_precursor_ion_h_oh_co_loss, - linear_oligoketide_precursor_ion_h_oh_co_loss_dehydrated, - linear_oligoketide_precursor_ion_h_oh_co_loss_deamidated, - linear_oligoketide_precursor_ion_h_oh_co_loss_dehydrated_and_deamidated, - linear_oligoketide_precursor_ion_oh_oh, - linear_oligoketide_precursor_ion_oh_oh_dehydrated, - linear_oligoketide_precursor_ion_oh_oh_deamidated, - linear_oligoketide_precursor_ion_oh_oh_dehydrated_and_deamidated, - linear_oligoketide_precursor_ion_oh_oh_co_loss, - linear_oligoketide_precursor_ion_oh_oh_co_loss_dehydrated, - linear_oligoketide_precursor_ion_oh_oh_co_loss_deamidated, - linear_oligoketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated, - cyclic_oligoketide_precursor_ion, - cyclic_oligoketide_precursor_ion_dehydrated, - cyclic_oligoketide_precursor_ion_deamidated, - cyclic_oligoketide_precursor_ion_dehydrated_and_deamidated, - cyclic_oligoketide_precursor_ion_co_loss, - cyclic_oligoketide_precursor_ion_co_loss_dehydrated, - cyclic_oligoketide_precursor_ion_co_loss_deamidated, - cyclic_oligoketide_precursor_ion_co_loss_dehydrated_and_deamidated, -#endif - //b_ion_2H_loss, + linear_polyketide_precursor_ion_h_h, + linear_polyketide_precursor_ion_h_h_dehydrated, + linear_polyketide_precursor_ion_h_h_deamidated, + linear_polyketide_precursor_ion_h_h_dehydrated_and_deamidated, + linear_polyketide_precursor_ion_h_h_co_loss, + linear_polyketide_precursor_ion_h_h_co_loss_dehydrated, + linear_polyketide_precursor_ion_h_h_co_loss_deamidated, + linear_polyketide_precursor_ion_h_h_co_loss_dehydrated_and_deamidated, + linear_polyketide_precursor_ion_h_oh, + linear_polyketide_precursor_ion_h_oh_dehydrated, + linear_polyketide_precursor_ion_h_oh_deamidated, + linear_polyketide_precursor_ion_h_oh_dehydrated_and_deamidated, + linear_polyketide_precursor_ion_h_oh_co_loss, + linear_polyketide_precursor_ion_h_oh_co_loss_dehydrated, + linear_polyketide_precursor_ion_h_oh_co_loss_deamidated, + linear_polyketide_precursor_ion_h_oh_co_loss_dehydrated_and_deamidated, + linear_polyketide_precursor_ion_oh_oh, + linear_polyketide_precursor_ion_oh_oh_dehydrated, + linear_polyketide_precursor_ion_oh_oh_deamidated, + linear_polyketide_precursor_ion_oh_oh_dehydrated_and_deamidated, + linear_polyketide_precursor_ion_oh_oh_co_loss, + linear_polyketide_precursor_ion_oh_oh_co_loss_dehydrated, + linear_polyketide_precursor_ion_oh_oh_co_loss_deamidated, + linear_polyketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated, + cyclic_polyketide_precursor_ion, + cyclic_polyketide_precursor_ion_dehydrated, + cyclic_polyketide_precursor_ion_deamidated, + cyclic_polyketide_precursor_ion_dehydrated_and_deamidated, + cyclic_polyketide_precursor_ion_co_loss, + cyclic_polyketide_precursor_ion_co_loss_dehydrated, + cyclic_polyketide_precursor_ion_co_loss_deamidated, + cyclic_polyketide_precursor_ion_co_loss_dehydrated_and_deamidated, fragmentIonTypeEnd }; @@ -675,31 +665,18 @@ void initializeFragmentIonsForDeNovoGraphOfTPeptides(vector& f void initializeFragmentIonsForDeNovoGraphOfBranchCyclicPeptides(vector& fragmentions); -#if OLIGOKETIDES == 1 - - -/** - \brief Initialize fragment ion types for the de novo graph of a linear oligoketide - \param fragmentions reference to a vector of fragment ion types -*/ -void initializeFragmentIonsForDeNovoGraphOfLinearOligoketide(vector& fragmentions); - - /** - \brief Initialize fragment ion types for the de novo graph of a cyclic oligoketide + \brief Initialize fragment ion types for the de novo graph of a linear polyketide \param fragmentions reference to a vector of fragment ion types */ -void initializeFragmentIonsForDeNovoGraphOfCyclicOligoketide(vector& fragmentions); - - -#endif +void initializeFragmentIonsForDeNovoGraphOfLinearPolyketide(vector& fragmentions); /** - \brief Initialize fragment ion types for the de novo graph of a linear polysaccharide + \brief Initialize fragment ion types for the de novo graph of a cyclic polyketide \param fragmentions reference to a vector of fragment ion types */ -void initializeFragmentIonsForDeNovoGraphOfLinearPolysaccharide(vector& fragmentions); +void initializeFragmentIonsForDeNovoGraphOfCyclicPolyketide(vector& fragmentions); /** diff --git a/CycloBranch/core/cImzML.cpp b/CycloBranch/core/cImzML.cpp index 29050f2..f8040e6 100644 --- a/CycloBranch/core/cImzML.cpp +++ b/CycloBranch/core/cImzML.cpp @@ -7,6 +7,8 @@ cImzML::cImzML() { XMLPlatformUtils::Initialize(); profilespectra = false; + use_64bit_precision = false; + continuous = false; parser = new XercesDOMParser(); document = 0; @@ -30,6 +32,8 @@ void cImzML::parse(string& filename) { } profilespectra = false; + use_64bit_precision = false; + continuous = false; // childrens of mzML for (XMLSize_t i = 0; i < root->getChildNodes()->getLength(); i++) { @@ -40,6 +44,59 @@ void cImzML::parse(string& filename) { DOMElement* currentElement1 = dynamic_cast(currentNode1); + if (XMLString::equals(currentElement1->getTagName(), XMLString::transcode("fileDescription"))) { + + + // childrens of fileDescription + for (XMLSize_t j = 0; j < currentNode1->getChildNodes()->getLength(); j++) { + + DOMNode* currentNode2 = currentNode1->getChildNodes()->item(j); + if (currentNode2->getNodeType() && currentNode2->getNodeType() == DOMNode::ELEMENT_NODE) { + + DOMElement* currentElement2 = dynamic_cast(currentNode2); + if (XMLString::equals(currentElement2->getTagName(), XMLString::transcode("fileContent"))) { + + + // childrens of fileContent + for (XMLSize_t k = 0; k < currentNode2->getChildNodes()->getLength(); k++) { + + DOMNode* currentNode3 = currentNode2->getChildNodes()->item(k); + if (currentNode3->getNodeType() && currentNode3->getNodeType() == DOMNode::ELEMENT_NODE) { + + DOMElement* currentElement3 = dynamic_cast(currentNode3); + if (XMLString::equals(currentElement3->getTagName(), XMLString::transcode("cvParam"))) { + + const XMLCh* xmlch_name = currentElement3->getAttribute(XMLString::transcode("name")); + string name = XMLString::transcode(xmlch_name); + + if (name.compare("continuous") == 0) { + + continuous = true; + + } + + if (name.compare("profile spectrum") == 0) { + + profilespectra = true; + + } + + } + + } + + } + + + } + + } + + } + + } + + if (XMLString::equals(currentElement1->getTagName(), XMLString::transcode("referenceableParamGroupList"))) { @@ -55,6 +112,35 @@ void cImzML::parse(string& filename) { const XMLCh* xmlch_id = currentElement2->getAttribute(XMLString::transcode("id")); string id = XMLString::transcode(xmlch_id); + if (id.compare("mzArray") == 0) { + + + // childrens of referenceableParamGroup + for (XMLSize_t k = 0; k < currentNode2->getChildNodes()->getLength(); k++) { + + DOMNode* currentNode3 = currentNode2->getChildNodes()->item(k); + if (currentNode3->getNodeType() && currentNode3->getNodeType() == DOMNode::ELEMENT_NODE) { + + DOMElement* currentElement3 = dynamic_cast(currentNode3); + if (XMLString::equals(currentElement3->getTagName(), XMLString::transcode("cvParam"))) { + + const XMLCh* xmlch_name = currentElement3->getAttribute(XMLString::transcode("name")); + string name = XMLString::transcode(xmlch_name); + if (name.compare("64-bit float") == 0) { + + use_64bit_precision = true; + + } + + } + + } + + } + + + } + if (id.compare("spectrum") == 0) { @@ -281,7 +367,6 @@ void cImzML::parse(string& filename) { } - } @@ -299,6 +384,11 @@ void cImzML::updateRawDataToPeakList(vector& peaklists) { unsigned long long offset = 16; int currentid = 0; + int size = 4; + if (use_64bit_precision) { + size = 8; + } + // childrens of mzML for (XMLSize_t i = 0; i < root->getChildNodes()->getLength(); i++) { @@ -308,6 +398,61 @@ void cImzML::updateRawDataToPeakList(vector& peaklists) { DOMElement* currentElement1 = dynamic_cast(currentNode1); + if (XMLString::equals(currentElement1->getTagName(), XMLString::transcode("fileDescription"))) { + + + // childrens of fileDescription + for (XMLSize_t j = 0; j < currentNode1->getChildNodes()->getLength(); j++) { + + DOMNode* currentNode2 = currentNode1->getChildNodes()->item(j); + if (currentNode2->getNodeType() && currentNode2->getNodeType() == DOMNode::ELEMENT_NODE) { + + DOMElement* currentElement2 = dynamic_cast(currentNode2); + if (XMLString::equals(currentElement2->getTagName(), XMLString::transcode("fileContent"))) { + + + // childrens of fileContent + for (XMLSize_t k = 0; k < currentNode2->getChildNodes()->getLength(); k++) { + + DOMNode* currentNode3 = currentNode2->getChildNodes()->item(k); + if (currentNode3->getNodeType() && currentNode3->getNodeType() == DOMNode::ELEMENT_NODE) { + + DOMElement* currentElement3 = dynamic_cast(currentNode3); + if (XMLString::equals(currentElement3->getTagName(), XMLString::transcode("cvParam"))) { + + const XMLCh* xmlch_name = currentElement3->getAttribute(XMLString::transcode("name")); + string name = XMLString::transcode(xmlch_name); + + if (name.compare("continuous") == 0) { + + currentElement3->setAttribute(XMLString::transcode("accession"), XMLString::transcode("IMS:1000031")); + currentElement3->setAttribute(XMLString::transcode("name"), XMLString::transcode("processed")); + + } + + if (name.compare("profile spectrum") == 0) { + + currentElement3->setAttribute(XMLString::transcode("accession"), XMLString::transcode("MS:1000127")); + currentElement3->setAttribute(XMLString::transcode("name"), XMLString::transcode("centroid spectrum")); + + } + + } + + } + + } + + + } + + } + + } + + } + + if (XMLString::equals(currentElement1->getTagName(), XMLString::transcode("referenceableParamGroupList"))) { @@ -339,6 +484,7 @@ void cImzML::updateRawDataToPeakList(vector& peaklists) { string name = XMLString::transcode(xmlch_name); if (name.compare("profile spectrum") == 0) { + currentElement3->setAttribute(XMLString::transcode("accession"), XMLString::transcode("MS:1000127")); currentElement3->setAttribute(XMLString::transcode("name"), XMLString::transcode("centroid spectrum")); } @@ -392,6 +538,21 @@ void cImzML::updateRawDataToPeakList(vector& peaklists) { if (currentNode4->getNodeType() && currentNode4->getNodeType() == DOMNode::ELEMENT_NODE) { DOMElement* currentElement4 = dynamic_cast(currentNode4); + if (XMLString::equals(currentElement4->getTagName(), XMLString::transcode("cvParam"))) { + + + const XMLCh* xmlch_name = currentElement4->getAttribute(XMLString::transcode("name")); + string name = XMLString::transcode(xmlch_name); + if (name.compare("profile spectrum") == 0) { + + currentElement4->setAttribute(XMLString::transcode("accession"), XMLString::transcode("MS:1000127")); + currentElement4->setAttribute(XMLString::transcode("name"), XMLString::transcode("centroid spectrum")); + + } + + + } + if (XMLString::equals(currentElement4->getTagName(), XMLString::transcode("binaryDataArrayList"))) { @@ -440,7 +601,7 @@ void cImzML::updateRawDataToPeakList(vector& peaklists) { if (name.compare("external encoded length") == 0) { stringstream ss; - ss << peaklists[currentid].size() * 8; + ss << peaklists[currentid].size() * size; currentElement6->setAttribute(XMLString::transcode("value"), XMLString::transcode(ss.str().c_str())); } @@ -453,13 +614,13 @@ void cImzML::updateRawDataToPeakList(vector& peaklists) { else { if (name.compare("external offset") == 0) { stringstream ss; - ss << offset + peaklists[currentid].size() * 8; + ss << offset + peaklists[currentid].size() * size; currentElement6->setAttribute(XMLString::transcode("value"), XMLString::transcode(ss.str().c_str())); } if (name.compare("external encoded length") == 0) { stringstream ss; - ss << peaklists[currentid].size() * 8; + ss << peaklists[currentid].size() * size; currentElement6->setAttribute(XMLString::transcode("value"), XMLString::transcode(ss.str().c_str())); } @@ -492,7 +653,7 @@ void cImzML::updateRawDataToPeakList(vector& peaklists) { } - offset += peaklists[currentid].size() * 8 * 2; + offset += peaklists[currentid].size() * size * 2; currentid++; @@ -530,6 +691,11 @@ bool cImzML::hasProfileSpectra() { } +bool cImzML::use64BitPrecision() { + return use_64bit_precision; +} + + void cImzML::write(string& filename) { if (document == 0) { return; diff --git a/CycloBranch/core/cImzML.h b/CycloBranch/core/cImzML.h index 73cc7a0..a59fe33 100644 --- a/CycloBranch/core/cImzML.h +++ b/CycloBranch/core/cImzML.h @@ -87,6 +87,8 @@ class cImzML { DOMDocument* document; bool profilespectra; + bool use_64bit_precision; + bool continuous; vector imzmlitems; public: @@ -132,6 +134,13 @@ class cImzML { bool hasProfileSpectra(); + /** + \brief Check the precision of data. + \retval bool if true, 64bit precision is used; if false, 32bit precision is used + */ + bool use64BitPrecision(); + + /** \brief Write an imzml file. \param filename an output imzml filename diff --git a/CycloBranch/core/cParameters.cpp b/CycloBranch/core/cParameters.cpp index ef30621..16368bd 100644 --- a/CycloBranch/core/cParameters.cpp +++ b/CycloBranch/core/cParameters.cpp @@ -25,6 +25,7 @@ void cParameters::clear() { precursorAdductHasK = false; precursorAdductHasCa = false; precursorAdductHasMn = false; + precursorAdductHasCr = false; precursorAdductHasFe = false; precursorAdductHasCo = false; precursorAdductHasNi = false; @@ -37,11 +38,12 @@ void cParameters::clear() { masserrortolerancefordeisotoping = 5; minimumrelativeintensitythreshold = 0; minimummz = 150; + fwhm = 0.1; bricksdatabasefilename = ""; bricksdatabase.clear(); - maximumbricksincombinationbegin = 3; - maximumbricksincombinationmiddle = 2; - maximumbricksincombinationend = 3; + maximumbricksincombinationbegin = 1; + maximumbricksincombinationmiddle = 1; + maximumbricksincombinationend = 1; maximumbricksincombination = max(max(maximumbricksincombinationbegin, maximumbricksincombinationmiddle), maximumbricksincombinationend); maximumcumulativemass = 0; generatebrickspermutations = true; @@ -55,6 +57,7 @@ void cParameters::clear() { cycliccterminus = false; enablescrambling = false; similaritysearch = false; + regularblocksorder = false; hitsreported = 1000; sequencetag = ""; originalsequencetag = ""; @@ -177,7 +180,7 @@ int cParameters::checkAndPrepare(bool& terminatecomputation) { errormessage = "The file cannot be converted.\n"; errormessage += "Does the file '" + peaklistfilename + "' exist ?\n"; errormessage += "Is the directory with the file '" + peaklistfilename + "' writable ?\n"; - errormessage += "Do you have FileConverter installed (OpenMS 1.11) ?\n"; + errormessage += "Do you have FileConverter installed (OpenMS must be installed) ?\n"; errormessage += "Do you have 'any2mgf.sh' file located in '" + installdir.toStdString() + "External/macosx' folder ?\n"; errormessage += "Is the file 'any2mgf.sh' executable ? \n"; } @@ -188,7 +191,7 @@ int cParameters::checkAndPrepare(bool& terminatecomputation) { errormessage = "The file cannot be converted.\n"; errormessage += "Does the file '" + peaklistfilename + "' exist ?\n"; errormessage += "Is the directory with the file '" + peaklistfilename + "' writable ?\n"; - errormessage += "Do you have FileConverter installed (OpenMS 1.11) ?\n"; + errormessage += "Do you have FileConverter installed (OpenMS must be installed) ?\n"; errormessage += "Do you have a path to FileConverter in your PATH variable (e.g., 'C:/Program Files/OpenMS-1.11/bin') ?\n"; errormessage += "Do you have 'any2mgf.bat' file located in the '" + appname.toStdString() + "/External/windows' folder ?\n"; } @@ -290,7 +293,7 @@ int cParameters::checkAndPrepare(bool& terminatecomputation) { #endif break; case imzML: - errtype = peaklistseries.loadFromIMZMLStream(peaklistfilename, peakliststream, minimumrelativeintensitythreshold, os, terminatecomputation); + errtype = peaklistseries.loadFromIMZMLStream(peaklistfilename, peakliststream, minimumrelativeintensitythreshold, fwhm, os, terminatecomputation); if (errtype == -1) { error = true; errormessage = "Aborted by user.\n"; @@ -302,7 +305,7 @@ int cParameters::checkAndPrepare(bool& terminatecomputation) { errormessage += "Does the file '" + peaklistfilename + "' exist ?\n"; errormessage += "Is the directory with the file '" + peaklistfilename + "' writable ?\n"; errormessage += "Do you have enough space on your hard drive ?\n"; - errormessage += "Do you have OpenMS 1.11 installed (sudo apt-get install topp) ?\n"; + errormessage += "Do you have OpenMS installed (sudo apt-get install topp) ?\n"; errormessage += "Do you have 'raw2peaks.sh' file located in '" + installdir.toStdString() + "External/linux' folder ?\n"; errormessage += "Is the file 'raw2peaks.sh' executable (sudo chmod +x " + installdir.toStdString() + "External/linux/raw2peaks.sh) ? \n"; #else @@ -311,7 +314,7 @@ int cParameters::checkAndPrepare(bool& terminatecomputation) { errormessage += "Does the file '" + peaklistfilename + "' exist ?\n"; errormessage += "Is the directory with the file '" + peaklistfilename + "' writable ?\n"; errormessage += "Do you have enough space on your hard drive ?\n"; - errormessage += "Do you have OpenMS 1.11 installed ?\n"; + errormessage += "Do you have OpenMS installed ?\n"; errormessage += "Do you have 'raw2peaks.sh' file located in '" + installdir.toStdString() + "External/macosx' folder ?\n"; errormessage += "Is the file 'raw2peaks.sh' executable (sudo chmod +x " + installdir.toStdString() + "External/macosx/raw2peaks.sh) ? \n"; #else @@ -319,7 +322,7 @@ int cParameters::checkAndPrepare(bool& terminatecomputation) { errormessage += "Does the file '" + peaklistfilename + "' exist ?\n"; errormessage += "Is the directory with the file '" + peaklistfilename + "' writable ?\n"; errormessage += "Do you have enough space on your hard drive ?\n"; - errormessage += "Do you have OpenMS 1.11 installed ?\n"; + errormessage += "Do you have OpenMS installed ?\n"; errormessage += "Do you have a path to OpenMS binaries folder in your PATH variable (e.g., 'C:/Program Files/OpenMS-1.11/bin') ?\n"; errormessage += "Do you have 'raw2peaks.bat' file located in the '" + appname.toStdString() + "/External/windows' folder ?\n"; #endif @@ -351,7 +354,8 @@ int cParameters::checkAndPrepare(bool& terminatecomputation) { if (os) { *os << "Loading the database of bricks... "; } - if (bricksdatabase.loadFromPlainTextStream(bricksdatabasestream, errormessage, false) == -1) { + bool skiph2blocks = !((peptidetype == linearpolyketide) || (peptidetype == cyclicpolyketide)); + if (bricksdatabase.loadFromPlainTextStream(bricksdatabasestream, errormessage, false, skiph2blocks) == -1) { error = true; } else { @@ -442,6 +446,7 @@ int cParameters::checkAndPrepare(bool& terminatecomputation) { precursorAdductHasK = false; precursorAdductHasCa = false; precursorAdductHasMn = false; + precursorAdductHasCr = false; precursorAdductHasFe = false; precursorAdductHasCo = false; precursorAdductHasNi = false; @@ -477,6 +482,10 @@ int cParameters::checkAndPrepare(bool& terminatecomputation) { if (regex_search(precursoradduct, rx)) { precursorAdductHasMn = true; } + rx = "Cr"; + if (regex_search(precursoradduct, rx)) { + precursorAdductHasCr = true; + } rx = "Fe"; if (regex_search(precursoradduct, rx)) { precursorAdductHasFe = true; @@ -543,16 +552,11 @@ int cParameters::checkAndPrepare(bool& terminatecomputation) { case branchcyclic: initializeFragmentIonsForDeNovoGraphOfBranchCyclicPeptides(fragmentionsfordenovograph); break; -#if OLIGOKETIDES == 1 - case linearoligoketide: - initializeFragmentIonsForDeNovoGraphOfLinearOligoketide(fragmentionsfordenovograph); - break; - case cyclicoligoketide: - initializeFragmentIonsForDeNovoGraphOfCyclicOligoketide(fragmentionsfordenovograph); + case linearpolyketide: + initializeFragmentIonsForDeNovoGraphOfLinearPolyketide(fragmentionsfordenovograph); break; -#endif - case linearpolysaccharide: - initializeFragmentIonsForDeNovoGraphOfLinearPolysaccharide(fragmentionsfordenovograph); + case cyclicpolyketide: + initializeFragmentIonsForDeNovoGraphOfCyclicPolyketide(fragmentionsfordenovograph); break; case other: error = true; @@ -612,16 +616,11 @@ string cParameters::printToString() { case branchcyclic: s += "Branch-cyclic\n"; break; -#if OLIGOKETIDES == 1 - case linearoligoketide: - s += "Linear oligoketide\n"; + case linearpolyketide: + s += "Linear polyketide\n"; break; - case cyclicoligoketide: - s += "Cyclic oligoketide\n"; - break; -#endif - case linearpolysaccharide: - s += "Linear polysaccharide (beta version)\n"; + case cyclicpolyketide: + s += "Cyclic polyketide\n"; break; case other: s += "Other\n"; @@ -638,6 +637,7 @@ string cParameters::printToString() { s += "Fragment Mass Error Tolerance for Deisotoping: " + to_string(masserrortolerancefordeisotoping) + "\n"; s += "Minimum Threshold of Relative Intensity: " + to_string(minimumrelativeintensitythreshold) + "\n"; s += "Minimum m/z Ratio: " + to_string(minimummz) + "\n"; + s += "FWHM: " + to_string(fwhm) + "\n"; s += "Brick Database File: " + bricksdatabasefilename + "\n"; s += "Maximum Number of Combined Blocks (start, middle, end): " + to_string(maximumbricksincombinationbegin) + ", " + to_string(maximumbricksincombinationmiddle) + ", " + to_string(maximumbricksincombinationend) + "\n"; s += "Maximum Cumulative Mass of Blocks: " + to_string(maximumcumulativemass) + "\n"; @@ -648,10 +648,10 @@ string cParameters::printToString() { s += "N-/C-terminal Modifications File: " + modificationsfilename + "\n"; - s += "Action with Blind Paths in De Novo Graph: "; + s += "Incomplete Paths in De Novo Graph: "; switch (blindedges) { case 0: - s += "none (you can see a complete de novo graph)"; + s += "keep (you can see a complete de novo graph)"; break; case 1: s += "remove (speed up the search)"; @@ -680,6 +680,10 @@ string cParameters::printToString() { s += similaritysearch ? "on" : "off"; s += "\n"; + s += "Regular Order of Ketide Blocks: "; + s += regularblocksorder ? "on" : "off"; + s += "\n"; + s += "Mode: "; switch ((eModeType)mode) { case denovoengine: @@ -692,7 +696,7 @@ string cParameters::printToString() { s += "Compare Peaklist with Database - MS/MS data"; break; case dereplication: - s += "Compare Peaklist with Database - MS data"; + s += "Compare Peaklist(s) with Database - MS or MSI data"; break; default: break; @@ -768,7 +772,7 @@ void cParameters::setOutputStream(cMainThread& os) { void cParameters::updateFragmentDefinitions() { - if (peptidetype == linear) { + if ((peptidetype == linear) || (peptidetype == linearpolyketide)) { fragmentdefinitions.recalculateFragments(cyclicnterminus, cycliccterminus, precursoradduct); } else { @@ -798,6 +802,7 @@ void cParameters::store(ofstream& os) { os.write((char *)&precursorAdductHasK, sizeof(bool)); os.write((char *)&precursorAdductHasCa, sizeof(bool)); os.write((char *)&precursorAdductHasMn, sizeof(bool)); + os.write((char *)&precursorAdductHasCr, sizeof(bool)); os.write((char *)&precursorAdductHasFe, sizeof(bool)); os.write((char *)&precursorAdductHasCo, sizeof(bool)); os.write((char *)&precursorAdductHasNi, sizeof(bool)); @@ -811,6 +816,7 @@ void cParameters::store(ofstream& os) { os.write((char *)&masserrortolerancefordeisotoping, sizeof(double)); os.write((char *)&minimumrelativeintensitythreshold, sizeof(double)); os.write((char *)&minimummz, sizeof(double)); + os.write((char *)&fwhm, sizeof(double)); storeString(bricksdatabasefilename, os); bricksdatabase.store(os); @@ -837,6 +843,7 @@ void cParameters::store(ofstream& os) { os.write((char *)&cycliccterminus, sizeof(bool)); os.write((char *)&enablescrambling, sizeof(bool)); os.write((char *)&similaritysearch, sizeof(bool)); + os.write((char *)®ularblocksorder, sizeof(bool)); os.write((char *)&hitsreported, sizeof(int)); storeString(sequencetag, os); @@ -890,6 +897,7 @@ void cParameters::load(ifstream& is) { is.read((char *)&precursorAdductHasK, sizeof(bool)); is.read((char *)&precursorAdductHasCa, sizeof(bool)); is.read((char *)&precursorAdductHasMn, sizeof(bool)); + is.read((char *)&precursorAdductHasCr, sizeof(bool)); is.read((char *)&precursorAdductHasFe, sizeof(bool)); is.read((char *)&precursorAdductHasCo, sizeof(bool)); is.read((char *)&precursorAdductHasNi, sizeof(bool)); @@ -903,6 +911,7 @@ void cParameters::load(ifstream& is) { is.read((char *)&masserrortolerancefordeisotoping, sizeof(double)); is.read((char *)&minimumrelativeintensitythreshold, sizeof(double)); is.read((char *)&minimummz, sizeof(double)); + is.read((char *)&fwhm, sizeof(double)); loadString(bricksdatabasefilename, is); bricksdatabase.load(is); @@ -929,6 +938,7 @@ void cParameters::load(ifstream& is) { is.read((char *)&cycliccterminus, sizeof(bool)); is.read((char *)&enablescrambling, sizeof(bool)); is.read((char *)&similaritysearch, sizeof(bool)); + is.read((char *)®ularblocksorder, sizeof(bool)); is.read((char *)&hitsreported, sizeof(int)); loadString(sequencetag, is); diff --git a/CycloBranch/core/cParameters.h b/CycloBranch/core/cParameters.h index 242b149..2a3a25f 100644 --- a/CycloBranch/core/cParameters.h +++ b/CycloBranch/core/cParameters.h @@ -141,6 +141,12 @@ class cParameters { bool precursorAdductHasMn; + /** + \brief True when the precursor adduct contains Cr. + */ + bool precursorAdductHasCr; + + /** \brief True when the precursor adduct contains Fe. */ @@ -213,6 +219,12 @@ class cParameters { double minimummz; + /** + \brief FWHM. + */ + double fwhm; + + /** \brief A file name of a bricks database. */ @@ -315,6 +327,12 @@ class cParameters { bool similaritysearch; + /** + \brief True when the order of polyketide blocks is regular. + */ + bool regularblocksorder; + + /** \brief Maximum number of reported hits. */ @@ -370,7 +388,7 @@ class cParameters { /** - \brief The identifier of an action with edges forming blind paths. + \brief The identifier of an action with edges forming incomplete paths. */ int blindedges; diff --git a/CycloBranch/core/cPeakListSeries.cpp b/CycloBranch/core/cPeakListSeries.cpp index 70e60bd..062705f 100644 --- a/CycloBranch/core/cPeakListSeries.cpp +++ b/CycloBranch/core/cPeakListSeries.cpp @@ -64,7 +64,7 @@ void cPeakListSeries::loadFromBAFStream(ifstream &stream) { } -int cPeakListSeries::loadFromIMZMLStream(string& imzmlfilename, ifstream &ibdstream, double minimumrelativeintensitythreshold, cMainThread* os, bool& terminatecomputation) { +int cPeakListSeries::loadFromIMZMLStream(string& imzmlfilename, ifstream &ibdstream, double minimumrelativeintensitythreshold, double fwhm, cMainThread* os, bool& terminatecomputation) { *os << endl << endl << "Parsing the imzML file..." << endl; cImzML imzml; @@ -75,8 +75,14 @@ int cPeakListSeries::loadFromIMZMLStream(string& imzmlfilename, ifstream &ibdstr string mgfname; string convertedimzmlfilename; string convertedibdfilename; + + char tempstring[1024]; + string peaksstring; + peaksstring.reserve(25000000); + int strip; bool rawdata = imzml.hasProfileSpectra(); + bool use_64bit_precision = imzml.use64BitPrecision(); if (rawdata) { mgfname = imzmlfilename.substr(0, (int)imzmlfilename.size() - 5); @@ -103,15 +109,18 @@ int cPeakListSeries::loadFromIMZMLStream(string& imzmlfilename, ifstream &ibdstr } cPeaksList peaklist; - peaklist.loadFromIBDStream(imzml.getItems()[i], ibdstream); + peaklist.loadFromIBDStream(imzml.getItems()[i], ibdstream, use_64bit_precision); if ((peaklist.size() > 0) && !rawdata) { peaklists.push_back(peaklist); } if (rawdata) { + peaksstring.clear(); for (int j = 0; j < peaklist.size(); j++) { - mgfofstream << peaklist[j].mzratio << " " << peaklist[j].intensity << endl; + sprintf_s(tempstring, "%f %f\n\0", peaklist[j].mzratio, peaklist[j].intensity); + peaksstring.append(tempstring); } + mgfofstream << peaksstring; mgfofstream << "END IONS" << endl << endl; if (((i + 1) % 100 == 0) && (i > 0)) { @@ -139,12 +148,12 @@ int cPeakListSeries::loadFromIMZMLStream(string& imzmlfilename, ifstream &ibdstr string s; #if OS_TYPE == UNX - s = installdir.toStdString() + "External/linux/raw2peaks.sh " + mgfname; + s = installdir.toStdString() + "External/linux/raw2peaks.sh " + mgfname + "," + to_string(fwhm); #else #if OS_TYPE == OSX - s = installdir.toStdString() + "External/macosx/raw2peaks.sh " + mgfname; + s = installdir.toStdString() + "External/macosx/raw2peaks.sh " + mgfname + "," + to_string(fwhm); #else - s = "External\\windows\\raw2peaks.bat \"" + mgfname + "\""; + s = "External\\windows\\raw2peaks.bat \"" + mgfname + "\" " + to_string(fwhm); #endif #endif @@ -160,12 +169,13 @@ int cPeakListSeries::loadFromIMZMLStream(string& imzmlfilename, ifstream &ibdstr peaklists.push_back(peaklist); } mgfifstream.close(); - QFile::remove(mgfname.c_str()); if (imzml.getItems().size() != peaklists.size()) { return -2; } + QFile::remove(mgfname.c_str()); + for (int i = 0; i < (int)imzml.getItems().size(); i++) { peaklists[i].setCoordinates(imzml.getItems()[i].x, imzml.getItems()[i].y); } @@ -173,8 +183,10 @@ int cPeakListSeries::loadFromIMZMLStream(string& imzmlfilename, ifstream &ibdstr imzml.updateRawDataToPeakList(peaklists); convertedimzmlfilename = imzmlfilename.substr(0, (int)imzmlfilename.size() - 6); - convertedibdfilename = convertedimzmlfilename + "_converted.ibd"; - convertedimzmlfilename += "_converted.imzML"; + convertedibdfilename = convertedimzmlfilename + "_converted_fwhm_" + to_string(fwhm) + ".ibd"; + convertedimzmlfilename += "_converted_fwhm_"; + convertedimzmlfilename += to_string(fwhm); + convertedimzmlfilename += ".imzML"; imzml.write(convertedimzmlfilename); ofstream ofibdstream; @@ -190,7 +202,7 @@ int cPeakListSeries::loadFromIMZMLStream(string& imzmlfilename, ifstream &ibdstr // write peaklists for (int i = 0; i < (int)peaklists.size(); i++) { - peaklists[i].storeToIBDStream(ofibdstream); + peaklists[i].storeToIBDStream(ofibdstream, use_64bit_precision); } ofibdstream.close(); diff --git a/CycloBranch/core/cPeakListSeries.h b/CycloBranch/core/cPeakListSeries.h index bb1c11b..ef46fea 100644 --- a/CycloBranch/core/cPeakListSeries.h +++ b/CycloBranch/core/cPeakListSeries.h @@ -85,11 +85,12 @@ class cPeakListSeries { \param imzmlfilename imzML filename \param ibdstream ibd binary file stream \param minimumrelativeintensitythreshold a minimum threshold of relative intensity + \param fwhm FWHM \param os pointer to the main thread of the application (output stream) \param terminatecomputation reference to a variable determining that the computation must be stopped \retval int 0 = success; -1 = aborted by user, -2 = error */ - int loadFromIMZMLStream(string& imzmlfilename, ifstream &ibdstream, double minimumrelativeintensitythreshold, cMainThread* os, bool& terminatecomputation); + int loadFromIMZMLStream(string& imzmlfilename, ifstream &ibdstream, double minimumrelativeintensitythreshold, double fwhm, cMainThread* os, bool& terminatecomputation); /** diff --git a/CycloBranch/core/cPeaksList.cpp b/CycloBranch/core/cPeaksList.cpp index 140dcf1..8591c5d 100644 --- a/CycloBranch/core/cPeaksList.cpp +++ b/CycloBranch/core/cPeaksList.cpp @@ -127,48 +127,97 @@ void cPeaksList::loadFromBAFStream(ifstream &stream) { } -void cPeaksList::loadFromIBDStream(cImzMLItem& imzmlitem, ifstream &ibdstream) { - unsigned long long start; - double value; +void cPeaksList::loadFromIBDStream(cImzMLItem& imzmlitem, ifstream &ibdstream, bool use_64bit_precision) { + if (use_64bit_precision) { + unsigned long long start; + double value; + + peaks.resize(imzmlitem.mzlength/8); + + start = imzmlitem.mzstart; + ibdstream.seekg(start, ibdstream.beg); + for (int i = 0; i < (int)imzmlitem.mzlength/8; i++) { + if (ibdstream.good()) { + ibdstream.read((char*)&value, 8); + peaks[i].mzratio = value; + } + } - peaks.resize(imzmlitem.mzlength/8); + if (imzmlitem.mzlength != imzmlitem.intensitylength) { + return; + } - start = imzmlitem.mzstart; - ibdstream.seekg(start, ibdstream.beg); - for (int i = 0; i < (int)imzmlitem.mzlength/8; i++) { - if (ibdstream.good()) { - ibdstream.read((char*)&value, 8); - peaks[i].mzratio = value; + start = imzmlitem.intensitystart; + ibdstream.seekg(start, ibdstream.beg); + for (int i = 0; i < (int)imzmlitem.intensitylength/8; i++) { + if (ibdstream.good()) { + ibdstream.read((char*)&value, 8); + peaks[i].intensity = value; + } } - } - if (imzmlitem.mzlength != imzmlitem.intensitylength) { - return; + x = imzmlitem.x; + y = imzmlitem.y; } + else { + unsigned start; + float value; - start = imzmlitem.intensitystart; - ibdstream.seekg(start, ibdstream.beg); - for (int i = 0; i < (int)imzmlitem.intensitylength/8; i++) { - if (ibdstream.good()) { - ibdstream.read((char*)&value, 8); - peaks[i].intensity = value; + peaks.resize(imzmlitem.mzlength/4); + + start = imzmlitem.mzstart; + ibdstream.seekg(start, ibdstream.beg); + for (int i = 0; i < (int)imzmlitem.mzlength/4; i++) { + if (ibdstream.good()) { + ibdstream.read((char*)&value, 4); + peaks[i].mzratio = value; + } + } + + if (imzmlitem.mzlength != imzmlitem.intensitylength) { + return; + } + + start = imzmlitem.intensitystart; + ibdstream.seekg(start, ibdstream.beg); + for (int i = 0; i < (int)imzmlitem.intensitylength/4; i++) { + if (ibdstream.good()) { + ibdstream.read((char*)&value, 4); + peaks[i].intensity = value; + } } - } - x = imzmlitem.x; - y = imzmlitem.y; + x = imzmlitem.x; + y = imzmlitem.y; + } } -void cPeaksList::storeToIBDStream(ofstream &ibdstream) { - // store m/z values - for (int i = 0; i < (int)peaks.size(); i++) { - ibdstream.write((char *)&(peaks[i].mzratio), 8); +void cPeaksList::storeToIBDStream(ofstream &ibdstream, bool use_64bit_precision) { + if (use_64bit_precision) { + // store m/z values + for (int i = 0; i < (int)peaks.size(); i++) { + ibdstream.write((char *)&(peaks[i].mzratio), 8); + } + + // store intensities + for (int i = 0; i < (int)peaks.size(); i++) { + ibdstream.write((char *)&(peaks[i].intensity), 8); + } } + else { + float value; + // store m/z values + for (int i = 0; i < (int)peaks.size(); i++) { + value = peaks[i].mzratio; + ibdstream.write((char *)&value, 4); + } - // store intensities - for (int i = 0; i < (int)peaks.size(); i++) { - ibdstream.write((char *)&(peaks[i].intensity), 8); + // store intensities + for (int i = 0; i < (int)peaks.size(); i++) { + value = peaks[i].intensity; + ibdstream.write((char *)&value, 4); + } } } diff --git a/CycloBranch/core/cPeaksList.h b/CycloBranch/core/cPeaksList.h index fd99dd7..20bd564 100644 --- a/CycloBranch/core/cPeaksList.h +++ b/CycloBranch/core/cPeaksList.h @@ -139,15 +139,17 @@ class cPeaksList { \brief Load the spectrum from .ibd file. \param imzmlitem cImzML containing the offset in the ibd file \param ibdstream an input binary file stream + \param use_64bit_precision if true, 64bit precision is used; if false, 32bit precision is used */ - void loadFromIBDStream(cImzMLItem& imzmlitem, ifstream &ibdstream); + void loadFromIBDStream(cImzMLItem& imzmlitem, ifstream &ibdstream, bool use_64bit_precision); /** \brief Store the spectrum into .ibd file. \param ibdstream an output binary file stream + \param use_64bit_precision if true, 64bit precision is used; if false, 32bit precision is used */ - void storeToIBDStream(ofstream &ibdstream); + void storeToIBDStream(ofstream &ibdstream, bool use_64bit_precision); /** diff --git a/CycloBranch/core/cSummaryFormula.cpp b/CycloBranch/core/cSummaryFormula.cpp index 86337c8..be45ac4 100644 --- a/CycloBranch/core/cSummaryFormula.cpp +++ b/CycloBranch/core/cSummaryFormula.cpp @@ -116,15 +116,21 @@ void cSummaryFormula::setPartial(bool partial) { } -void cSummaryFormula::addFormula(string& formula) { +void cSummaryFormula::addFormula(string& formula, bool remove) { if ((int)formula.size() == 0) { return; } map atoms; atoms.clear(); - explodeSummary(atoms, this->formula); + explodeSummary(atoms, formula); + if (remove) { + for (auto it = atoms.begin(); it != atoms.end(); ++it) { + it->second = -it->second; + } + } + explodeSummary(atoms, this->formula); this->formula = ""; for (auto it = atoms.begin(); it != atoms.end(); ++it) { diff --git a/CycloBranch/core/cSummaryFormula.h b/CycloBranch/core/cSummaryFormula.h index eb36771..52efa81 100644 --- a/CycloBranch/core/cSummaryFormula.h +++ b/CycloBranch/core/cSummaryFormula.h @@ -82,8 +82,9 @@ class cSummaryFormula { /** \brief Add a formula to the existing one. \param formula a chemical formula + \param remove if true then the formula is removed; if false then the formula is added */ - void addFormula(string& formula); + void addFormula(string& formula, bool remove = false); /** diff --git a/CycloBranch/core/cTheoreticalSpectrum.cpp b/CycloBranch/core/cTheoreticalSpectrum.cpp index d86d769..1e11bca 100644 --- a/CycloBranch/core/cTheoreticalSpectrum.cpp +++ b/CycloBranch/core/cTheoreticalSpectrum.cpp @@ -143,51 +143,17 @@ void cTheoreticalSpectrum::generatePrecursorIon(vector& intcomposition, cBr endtype = (int)cyclic_precursor_ion_co_loss_and_dehydrated_and_deamidated; usedmodifications.insert(candidate.getMiddleModifID()); break; -#if OLIGOKETIDES == 1 - case linearoligoketide: + case linearpolyketide: peak.mzratio = parameters->searchedmodifications[candidate.getStartModifID()].massdifference + parameters->searchedmodifications[candidate.getEndModifID()].massdifference; peak.seriesid = 0; - - switch (candidate.getKetidePrecursorType(bricksdatabasewithcombinations)) - { - case ketide_precursor_h2o: - starttype = (int)linear_oligoketide_precursor_ion_h_oh; - endtype = (int)linear_oligoketide_precursor_ion_h_oh_co_loss_dehydrated_and_deamidated; - break; - case ketide_precursor_h2: - starttype = (int)linear_oligoketide_precursor_ion_h_h; - endtype = (int)linear_oligoketide_precursor_ion_h_h_co_loss_dehydrated_and_deamidated; - break; - case ketide_precursor_h2o2: - starttype = (int)linear_oligoketide_precursor_ion_oh_oh; - endtype = (int)linear_oligoketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated; - break; - default: - break; - } - - if (candidate.hasFirstBrickArtificial(bricksdatabasewithcombinations) || candidate.hasLastBrickArtificial(bricksdatabasewithcombinations)) { - starttype = (int)linear_oligoketide_precursor_ion_h_h; - endtype = (int)linear_oligoketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated; - } - usedmodifications.insert(candidate.getStartModifID()); usedmodifications.insert(candidate.getEndModifID()); break; - case cyclicoligoketide: + case cyclicpolyketide: peak.mzratio = 0; peak.seriesid = (int)intcomposition.size() - 1; - starttype = (int)cyclic_oligoketide_precursor_ion; - endtype = (int)cyclic_oligoketide_precursor_ion_co_loss_dehydrated_and_deamidated; - break; -#endif - case linearpolysaccharide: - peak.mzratio = parameters->searchedmodifications[candidate.getStartModifID()].massdifference + parameters->searchedmodifications[candidate.getEndModifID()].massdifference; - peak.seriesid = 0; - starttype = (int)precursor_ion; - endtype = (int)precursor_ion_co_loss_and_dehydrated_and_deamidated; - usedmodifications.insert(candidate.getStartModifID()); - usedmodifications.insert(candidate.getEndModifID()); + starttype = (int)cyclic_polyketide_precursor_ion; + endtype = (int)cyclic_polyketide_precursor_ion_co_loss_dehydrated_and_deamidated; break; case other: break; @@ -198,6 +164,43 @@ void cTheoreticalSpectrum::generatePrecursorIon(vector& intcomposition, cBr for (int i = 0; i < (int)intcomposition.size(); i++) { peak.mzratio += bricksdatabasewithcombinations[intcomposition[i] - 1].getMass(); } + + if (parameters->peptidetype == linearpolyketide) { + double precursormass = charge(uncharge(parameters->precursormass, parameters->precursorcharge), (parameters->precursorcharge > 0)?1:-1); + double thprecursormass = peak.mzratio + parameters->fragmentdefinitions[linear_polyketide_precursor_ion_oh_oh].massdifference; + thprecursormass = (parameters->precursorcharge > 0)?thprecursormass:thprecursormass - 2*Hplus; + double bestmz = fabs(precursormass - thprecursormass); + int bestmatch = 1; + + thprecursormass = peak.mzratio + parameters->fragmentdefinitions[linear_polyketide_precursor_ion_h_oh].massdifference; + thprecursormass = (parameters->precursorcharge > 0)?thprecursormass:thprecursormass - 2*Hplus; + if (fabs(precursormass - thprecursormass) < bestmz) { + bestmz = fabs(precursormass - thprecursormass); + bestmatch = 2; + } + + thprecursormass = peak.mzratio + parameters->fragmentdefinitions[linear_polyketide_precursor_ion_h_h].massdifference; + thprecursormass = (parameters->precursorcharge > 0)?thprecursormass:thprecursormass - 2*Hplus; + if (fabs(precursormass - thprecursormass) < bestmz) { + bestmz = fabs(precursormass - thprecursormass); + bestmatch = 3; + } + + if (bestmatch == 1) { + starttype = (int)linear_polyketide_precursor_ion_oh_oh; + endtype = (int)linear_polyketide_precursor_ion_oh_oh_co_loss_dehydrated_and_deamidated; + } + + if (bestmatch == 2) { + starttype = (int)linear_polyketide_precursor_ion_h_oh; + endtype = (int)linear_polyketide_precursor_ion_h_oh_co_loss_dehydrated_and_deamidated; + } + + if (bestmatch == 3) { + starttype = (int)linear_polyketide_precursor_ion_h_h; + endtype = (int)linear_polyketide_precursor_ion_h_h_co_loss_dehydrated_and_deamidated; + } + } double tempratio = peak.mzratio; for (int i = starttype; i <= endtype; i++) { @@ -567,6 +570,10 @@ void cTheoreticalSpectrum::addAdductToDescription(string& description) { description += "_Mn"; } + if (parameters->precursorAdductHasCr) { + description += "_Cr"; + } + if (parameters->precursorAdductHasFe) { description += "_Fe"; } @@ -650,33 +657,45 @@ void cTheoreticalSpectrum::addMetalPeaks(cPeak& peak, int& peaklistrealsize, int if (parameters->precursorAdductHasCa) { cPeak tmppeak; - tmppeak = peak; + /*tmppeak = peak; tmppeak.isotope = true; tmppeak.mzratio += (Ca44 - Ca)/(double)charge; if (writedescription) { tmppeak.description.replace(tmppeak.description.find("Ca"), 2, "44Ca"); } - addPeakToList(tmppeak, peaklistrealsize); + addPeakToList(tmppeak, peaklistrealsize);*/ } - if (parameters->precursorAdductHasFe) { + if (parameters->precursorAdductHasCr) { cPeak tmppeak; tmppeak = peak; tmppeak.isotope = true; - tmppeak.mzratio -= (Fe - Fe54)/(double)charge; + tmppeak.mzratio -= (Cr - Cr50)/(double)charge; if (writedescription) { - tmppeak.description.replace(tmppeak.description.find("Fe"), 2, "54Fe"); + tmppeak.description.replace(tmppeak.description.find("Cr"), 2, "50Cr"); } addPeakToList(tmppeak, peaklistrealsize); - /*tmppeak = peak; + tmppeak = peak; tmppeak.isotope = true; - tmppeak.mzratio += (Fe57 - Fe)/(double)j; + tmppeak.mzratio += (Cr53 - Cr)/(double)charge; if (writedescription) { - tmppeak.description.replace(tmppeak.description.find(':') - 2, 2, "57Fe"); + tmppeak.description.replace(tmppeak.description.find("Cr"), 2, "53Cr"); } - addPeakToList(tmppeak, peaklistrealsize);*/ + addPeakToList(tmppeak, peaklistrealsize); + } + + if (parameters->precursorAdductHasFe) { + cPeak tmppeak; + + tmppeak = peak; + tmppeak.isotope = true; + tmppeak.mzratio -= (Fe - Fe54)/(double)charge; + if (writedescription) { + tmppeak.description.replace(tmppeak.description.find("Fe"), 2, "54Fe"); + } + addPeakToList(tmppeak, peaklistrealsize); } if (parameters->precursorAdductHasNi) { @@ -690,13 +709,13 @@ void cTheoreticalSpectrum::addMetalPeaks(cPeak& peak, int& peaklistrealsize, int } addPeakToList(tmppeak, peaklistrealsize); - tmppeak = peak; + /*tmppeak = peak; tmppeak.isotope = true; tmppeak.mzratio += (Ni61 - Ni)/(double)charge; if (writedescription) { tmppeak.description.replace(tmppeak.description.find("Ni"), 2, "61Ni"); } - addPeakToList(tmppeak, peaklistrealsize); + addPeakToList(tmppeak, peaklistrealsize);*/ tmppeak = peak; tmppeak.isotope = true; @@ -820,6 +839,7 @@ void cTheoreticalSpectrum::clear(bool clearpeaklist) { reversevalidposition = -1; seriescompleted = 1; + pathid = 0; } @@ -882,10 +902,10 @@ int cTheoreticalSpectrum::compareBranched(cPeaksList& sortedpeaklist, cBricksDat // j == 2, 4, 5 are invalid if ((j == 0) || ((j == 1) && (parameters->searchedmodifications[trotations[j].startmodifID].nterminal)) || ((j == 3) && (parameters->searchedmodifications[trotations[j].endmodifID].cterminal))) { if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal) { - generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, trotations[j].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, parameters->peptidetype, &trotations[j]); + generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, trotations[j].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, parameters->peptidetype, parameters->regularblocksorder, &trotations[j]); } if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal) { - generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, trotations[j].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, parameters->peptidetype, &trotations[j]); + generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, trotations[j].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, parameters->peptidetype, parameters->regularblocksorder, &trotations[j]); } } @@ -1025,10 +1045,10 @@ int cTheoreticalSpectrum::compareLinear(cPeaksList& sortedpeaklist, cBricksDatab for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal) { - generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, parameters->peptidetype); + generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, parameters->peptidetype, parameters->regularblocksorder); } if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal) { - generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, parameters->peptidetype); + generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, parameters->peptidetype, parameters->regularblocksorder); } } @@ -1224,13 +1244,11 @@ int cTheoreticalSpectrum::compareCyclic(cPeaksList& sortedpeaklist, cBricksDatab brick.setComposition(rotations[i], false); brick.explodeToIntComposition(intcomposition); -#if OLIGOKETIDES == 1 eResidueLossType leftresiduelosstype = bricksdatabasewithcombinations[intcomposition[0] - 1].getResidueLossType(); bool hasfirstblockartificial = bricksdatabasewithcombinations[intcomposition[0] - 1].isArtificial(); -#endif for (int j = 0; j < (int)parameters->fragmentionsfortheoreticalspectra.size(); j++) { - generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[j], bricksdatabasewithcombinations, writedescription, i, splittingsites, parameters->searchedmodifications, parameters->peptidetype, 0, leftresiduelosstype, hasfirstblockartificial); + generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[j], bricksdatabasewithcombinations, writedescription, i, splittingsites, parameters->searchedmodifications, parameters->peptidetype, parameters->regularblocksorder, 0, leftresiduelosstype, hasfirstblockartificial); } } @@ -1482,9 +1500,11 @@ int cTheoreticalSpectrum::compareBranchCyclic(cPeaksList& sortedpeaklist, cBrick vector v; v.push_back(branchcyclicrotations[i].getComposition()); string name = candidate.getName(); + cSummaryFormula summary = candidate.getSummaryFormula(); vector cpath = candidate.getPath(); - candidate.setCandidate(v, cpath, candidate.getStartModifID(), candidate.getEndModifID(), candidate.getMiddleModifID(), branchcyclicrotations[i].getBranchStart(), branchcyclicrotations[i].getBranchEnd()); + candidate.setCandidate(v, cpath, candidate.getStartIonType(), candidate.getStartModifID(), candidate.getEndModifID(), candidate.getMiddleModifID(), branchcyclicrotations[i].getBranchStart(), branchcyclicrotations[i].getBranchEnd()); candidate.setName(name); + candidate.setSummaryFormula(summary); break; } } @@ -1598,7 +1618,7 @@ int cTheoreticalSpectrum::compareBranchCyclic(cPeaksList& sortedpeaklist, cBrick if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal) { // if the start modification for k == 1 or k == 4 is nterminal, generate n-terminal ions (*) if (!(((k == 1) || (k == 4)) && (!parameters->searchedmodifications[trotationsofbranchcyclicrotations[j][k].startmodifID].nterminal))) { - generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, trotationsofbranchcyclicrotations[j][k].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, j, splittingsites, parameters->searchedmodifications, parameters->peptidetype, &trotationsofbranchcyclicrotations[j][k]); + generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, trotationsofbranchcyclicrotations[j][k].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, j, splittingsites, parameters->searchedmodifications, parameters->peptidetype, parameters->regularblocksorder, &trotationsofbranchcyclicrotations[j][k]); } } @@ -1606,7 +1626,7 @@ int cTheoreticalSpectrum::compareBranchCyclic(cPeaksList& sortedpeaklist, cBrick if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal && ((k == 3) || (k == 5) /*|| ((k == 0) && (trotationsofbranchcyclicrotations[j][k].endsWithBracket())) || ((k == 2) && (trotationsofbranchcyclicrotations[j][k].startsWithBracket()))*/)) { // if the end modification is cterminal, generate c-terminal ions (**) if (parameters->searchedmodifications[trotationsofbranchcyclicrotations[j][k].endmodifID].cterminal) { - generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, trotationsofbranchcyclicrotations[j][k].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, j, splittingsites, parameters->searchedmodifications, parameters->peptidetype, &trotationsofbranchcyclicrotations[j][k]); + generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, trotationsofbranchcyclicrotations[j][k].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, j, splittingsites, parameters->searchedmodifications, parameters->peptidetype, parameters->regularblocksorder, &trotationsofbranchcyclicrotations[j][k]); } } @@ -1735,12 +1755,9 @@ int cTheoreticalSpectrum::compareBranchCyclic(cPeaksList& sortedpeaklist, cBrick } -#if OLIGOKETIDES == 1 - - -int cTheoreticalSpectrum::compareLinearOligoketide(cPeaksList& sortedpeaklist, cBricksDatabase& bricksdatabasewithcombinations, bool writedescription, regex& sequencetag, regex& searchedsequence) { +int cTheoreticalSpectrum::compareLinearPolyketide(cPeaksList& sortedpeaklist, cBricksDatabase& bricksdatabasewithcombinations, bool writedescription, regex& sequencetag, regex& searchedsequence) { - if (!candidate.checkKetideSequence(bricksdatabasewithcombinations, parameters->peptidetype)) { + if (!candidate.checkKetideSequence(bricksdatabasewithcombinations, parameters->peptidetype, parameters->regularblocksorder)) { return -2; } @@ -1762,9 +1779,9 @@ int cTheoreticalSpectrum::compareLinearOligoketide(cPeaksList& sortedpeaklist, c if (!hasfirstblockartificial && !haslastblockartificial) { if (((leftresiduelosstype == h2_loss) && (candidate.getStartModifID() > 0) && parameters->searchedmodifications[candidate.getStartModifID()].cterminal) - || ((leftresiduelosstype == h2o_loss) && (candidate.getStartModifID() > 0) && parameters->searchedmodifications[candidate.getStartModifID()].nterminal) +/* || ((leftresiduelosstype == h2o_loss) && (candidate.getStartModifID() > 0) && parameters->searchedmodifications[candidate.getStartModifID()].nterminal)*/ || ((rightresiduelosstype == h2_loss) && (candidate.getEndModifID() > 0) && parameters->searchedmodifications[candidate.getEndModifID()].cterminal) - || ((rightresiduelosstype == h2o_loss) && (candidate.getEndModifID() > 0) && parameters->searchedmodifications[candidate.getEndModifID()].nterminal)) { +/* || ((rightresiduelosstype == h2o_loss) && (candidate.getEndModifID() > 0) && parameters->searchedmodifications[candidate.getEndModifID()].nterminal)*/) { return -2; } } @@ -1798,18 +1815,18 @@ int cTheoreticalSpectrum::compareLinearOligoketide(cPeaksList& sortedpeaklist, c for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { if ( - ((hasfirstblockartificial || (leftresiduelosstype == h2_loss)) && ((parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l1h_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l2h_ion))) + ((hasfirstblockartificial || !parameters->regularblocksorder || (leftresiduelosstype == h2_loss)) && ((parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l1h_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l2h_ion))) || - ((hasfirstblockartificial || (leftresiduelosstype == h2o_loss)) && ((parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l1oh_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l2oh_ion))) + ((hasfirstblockartificial || !parameters->regularblocksorder || (leftresiduelosstype == h2o_loss)) && ((parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l1oh_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l2oh_ion))) ) { - generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, parameters->peptidetype, 0, leftresiduelosstype, hasfirstblockartificial); + generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, parameters->peptidetype, parameters->regularblocksorder, 0, leftresiduelosstype, hasfirstblockartificial); } if ( - ((haslastblockartificial || (rightresiduelosstype == h2_loss)) && ((parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r1h_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r2h_ion))) + ((haslastblockartificial || !parameters->regularblocksorder || (rightresiduelosstype == h2_loss)) && ((parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r1h_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r2h_ion))) || - ((haslastblockartificial || (rightresiduelosstype == h2o_loss)) && ((parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r1oh_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r2oh_ion))) + ((haslastblockartificial || !parameters->regularblocksorder || (rightresiduelosstype == h2o_loss)) && ((parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r1oh_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r2oh_ion))) ) { - generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, parameters->peptidetype, 0, rightresiduelosstype, haslastblockartificial); + generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, parameters->peptidetype, parameters->regularblocksorder, 0, rightresiduelosstype, haslastblockartificial); } } @@ -1902,9 +1919,9 @@ int cTheoreticalSpectrum::compareLinearOligoketide(cPeaksList& sortedpeaklist, c } -int cTheoreticalSpectrum::compareCyclicOligoketide(cPeaksList& sortedpeaklist, cBricksDatabase& bricksdatabasewithcombinations, bool writedescription, regex& sequencetag, regex& searchedsequence) { +int cTheoreticalSpectrum::compareCyclicPolyketide(cPeaksList& sortedpeaklist, cBricksDatabase& bricksdatabasewithcombinations, bool writedescription, regex& sequencetag, regex& searchedsequence) { - if (!candidate.checkKetideSequence(bricksdatabasewithcombinations, parameters->peptidetype)) { + if (!candidate.checkKetideSequence(bricksdatabasewithcombinations, parameters->peptidetype, parameters->regularblocksorder)) { return -2; } @@ -1913,136 +1930,6 @@ int cTheoreticalSpectrum::compareCyclicOligoketide(cPeaksList& sortedpeaklist, c } -#endif - - -int cTheoreticalSpectrum::compareLinearPolysaccharide(cPeaksList& sortedpeaklist, cBricksDatabase& bricksdatabasewithcombinations, bool writedescription, regex& sequencetag, regex& searchedsequence) { - cBrick brick; - vector intcomposition; - vector splittingsites; - int theoreticalpeaksrealsize = 0; - - try { - if (!regex_search(candidate.getComposition(), sequencetag)) { - return -2; - } - - if (writedescription) { - valid = false; - if ((parameters->searchedsequence.size() > 0) && regex_search(candidate.getComposition(), searchedsequence) && - (parameters->searchedmodifications[candidate.getStartModifID()].name.compare(parameters->searchedsequenceNtermmodif) == 0) && - (parameters->searchedmodifications[candidate.getEndModifID()].name.compare(parameters->searchedsequenceCtermmodif) == 0)) { - valid = true; - } - } - } - catch (regex_error& /*e*/) { - return -2; - } - - intcomposition.clear(); - brick.clear(); - brick.setComposition(candidate.getComposition(), false); - brick.explodeToIntComposition(intcomposition); - - for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { - if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal) { - generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, parameters->peptidetype); - } - if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal) { - generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, parameters->peptidetype); - } - } - - generatePrecursorIon(intcomposition, bricksdatabasewithcombinations, theoreticalpeaksrealsize, writedescription); - - - // search the theoretical peaks in the experimental peak list - experimentalpeaks = sortedpeaklist; - vector > experimentalpeakmatches; - searchForPeakPairs(theoreticalpeaks, theoreticalpeaksrealsize, experimentalpeaks, experimentalpeakmatches, parameters->fragmentmasserrortolerance); - - - // coverage of series - map > series; - for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { - series[parameters->fragmentionsfortheoreticalspectra[i]].resize(intcomposition.size()); - } - - for (int i = 0; i < theoreticalpeaksrealsize; i++) { - if (!theoreticalpeaks[i].isotope && (theoreticalpeaks[i].matched > 0) && (series.count(theoreticalpeaks[i].iontype) == 1)) { - series[theoreticalpeaks[i].iontype][theoreticalpeaks[i].seriesid]++; - } - } - - - // peak hits without parents are removed - if (parameters->clearhitswithoutparent) { - clearFalseHits(series, parameters->fragmentionsfortheoreticalspectra); - - for (int i = 0; i < theoreticalpeaksrealsize; i++) { - if (!theoreticalpeaks[i].isotope && (theoreticalpeaks[i].matched > 0) && (theoreticalpeaks[i].rotationid != -1) && ((series.count(parameters->fragmentdefinitions[theoreticalpeaks[i].iontype].parent) == 0) || (series[parameters->fragmentdefinitions[theoreticalpeaks[i].iontype].parent][theoreticalpeaks[i].seriesid] == 0))) { - experimentalpeakmatches[theoreticalpeaks[i].matchedid].erase(experimentalpeakmatches[theoreticalpeaks[i].matchedid].find(i)); - experimentalpeaks[theoreticalpeaks[i].matchedid].matched--; - - theoreticalpeaks[i].matched--; - theoreticalpeaks[i].matchedid = -1; - } - } - } - - - removeUnmatchedMetalIsotopes(theoreticalpeaks, theoreticalpeaksrealsize, experimentalpeaks, experimentalpeakmatches); - - - // fill annotations of peaks - for (int i = 0; i < (int)experimentalpeaks.size(); i++) { - for (set::iterator it = experimentalpeakmatches[i].begin(); it != experimentalpeakmatches[i].end(); ++it) { - if (writedescription) { - if (experimentalpeaks[i].description.compare("") != 0) { - experimentalpeaks[i].description += ","; - } - experimentalpeaks[i].description += theoreticalpeaks[*it].description.substr(0,theoreticalpeaks[*it].description.find(':')); - theoreticalpeaks[*it].matchedmz = experimentalpeaks[i].mzratio; - theoreticalpeaks[*it].matchedintensity = experimentalpeaks[i].intensity; - theoreticalpeaks[*it].matchedppm = ppmError(experimentalpeaks[i].mzratio, theoreticalpeaks[*it].mzratio); - } - - // to do - if (experimentalpeaks[i].iontype != fragmentIonTypeEnd) { - if ((experimentalpeaks[i].iontype != y_ion) && (theoreticalpeaks[*it].iontype == y_ion)) { - experimentalpeaks[i].iontype = y_ion; - } - } - else { - experimentalpeaks[i].iontype = theoreticalpeaks[*it].iontype; - } - } - } - - - if (writedescription) { - - coveragebyseries = "Series of matched peaks:
\n"; - for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { - coveragebyseries += parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name + " "; - for (int j = 0; j < (int)series[parameters->fragmentionsfortheoreticalspectra[i]].size() - 1; j++) { - coveragebyseries += to_string(series[parameters->fragmentionsfortheoreticalspectra[i]][j]); - if (j < (int)series[parameters->fragmentionsfortheoreticalspectra[i]].size() - 2) { - coveragebyseries += " "; - } - } - coveragebyseries += "
\n"; - } - - } - - computeStatistics(writedescription); - - return theoreticalpeaksrealsize; -} - - void cTheoreticalSpectrum::generateMSSpectrum() { cPeak peak; cSummaryFormula formula; @@ -2067,6 +1954,7 @@ void cTheoreticalSpectrum::generateMSSpectrum() { parameters->precursorAdductHasMg = false; parameters->precursorAdductHasK = false; parameters->precursorAdductHasCa = false; + parameters->precursorAdductHasCr = false; parameters->precursorAdductHasFe = false; parameters->precursorAdductHasNi = false; parameters->precursorAdductHasCu = false; @@ -2092,6 +1980,10 @@ void cTheoreticalSpectrum::generateMSSpectrum() { if (regex_search(metalname, rx)) { parameters->precursorAdductHasCa = true; } + rx = "Cr"; + if (regex_search(metalname, rx)) { + parameters->precursorAdductHasCr = true; + } rx = "Fe"; if (regex_search(metalname, rx)) { parameters->precursorAdductHasFe = true; @@ -2215,17 +2107,13 @@ double cTheoreticalSpectrum::getRatioOfMatchedPeaks() { } -void cTheoreticalSpectrum::generateNTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& intcomposition, eFragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, ePeptideType peptidetype, TRotationInfo* trotation, eResidueLossType leftresiduelosstype, bool hasfirstblockartificial) { +void cTheoreticalSpectrum::generateNTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& intcomposition, eFragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, ePeptideType peptidetype, bool regularblocksorder, TRotationInfo* trotation, eResidueLossType leftresiduelosstype, bool hasfirstblockartificial) { cPeak peak; double tempratio; string tempdescription; peak.mzratio = parameters->fragmentdefinitions[fragmentiontype].massdifference; - if ((peptidetype == linear) || (peptidetype == linearpolysaccharide) -#if OLIGOKETIDES == 1 - || (peptidetype == linearoligoketide) -#endif - ) { + if ((peptidetype == linear) || (peptidetype == linearpolyketide)) { peak.mzratio += searchedmodifications[candidate.getStartModifID()].massdifference; } if ((peptidetype == branched) || (peptidetype == branchcyclic)) { @@ -2250,17 +2138,12 @@ void cTheoreticalSpectrum::generateNTerminalFragmentIons(int maxcharge, int& pea case branchcyclic: peak.rotationid = rotationid*6 + trotation->id; // to do - potential bug break; - case linearpolysaccharide: + case linearpolyketide: peak.rotationid = rotationid; break; -#if OLIGOKETIDES == 1 - case linearoligoketide: + case cyclicpolyketide: peak.rotationid = rotationid; break; - case cyclicoligoketide: - peak.rotationid = rotationid; - break; -#endif case other: break; default: @@ -2291,8 +2174,7 @@ void cTheoreticalSpectrum::generateNTerminalFragmentIons(int maxcharge, int& pea //} } -#if OLIGOKETIDES == 1 - if (peptidetype == linearoligoketide) { + if (regularblocksorder && (peptidetype == linearpolyketide)) { if (!hasfirstblockartificial && (leftresiduelosstype == h2_loss) && (parameters->fragmentdefinitions[fragmentiontype].parent == l1h_ion) && (i % 2 == 0)) { continue; } @@ -2309,8 +2191,22 @@ void cTheoreticalSpectrum::generateNTerminalFragmentIons(int maxcharge, int& pea continue; } } + + if (peptidetype == linearpolyketide) { + if (!hasfirstblockartificial && (leftresiduelosstype == h2_loss) && ((parameters->fragmentdefinitions[fragmentiontype].parent == l1oh_ion) || (parameters->fragmentdefinitions[fragmentiontype].parent == l2oh_ion))) { + continue; + } + + if (!hasfirstblockartificial && (candidate.getStartIonType() != fragmentIonTypeEnd) && parameters->fragmentdefinitions[candidate.getStartIonType()].nterminal && ((parameters->fragmentdefinitions[fragmentiontype].parent == l1oh_ion) || (parameters->fragmentdefinitions[fragmentiontype].parent == l2oh_ion))) { + continue; + } + + if (!hasfirstblockartificial && (candidate.getStartIonType() != fragmentIonTypeEnd) && parameters->fragmentdefinitions[candidate.getStartIonType()].cterminal && ((parameters->fragmentdefinitions[fragmentiontype].parent == l1h_ion) || (parameters->fragmentdefinitions[fragmentiontype].parent == l2h_ion))) { + continue; + } + } - if (peptidetype == cyclicoligoketide) { + if (regularblocksorder && (peptidetype == cyclicpolyketide)) { //if (!hasfirstblockartificial && (leftresiduelosstype == h2_loss) && (parameters->fragmentdefinitions[fragmentiontype].parent == l0h_ion)) { // b+2H ion is generated instead of b-2H // continue; @@ -2336,18 +2232,13 @@ void cTheoreticalSpectrum::generateNTerminalFragmentIons(int maxcharge, int& pea continue; } } -#endif peak.seriesid = i; if (writedescription) { peak.description = ""; -#if OLIGOKETIDES == 1 - if ((peptidetype == cyclic) || (peptidetype == cyclicoligoketide)) { -#else - if (peptidetype == cyclic) { -#endif + if ((peptidetype == cyclic) || (peptidetype == cyclicpolyketide)) { peak.description += to_string(splittingsites[rotationid].first + 1) + "-" + to_string(splittingsites[rotationid].second + 1) + "_"; } if (peptidetype == branched) { @@ -2358,22 +2249,18 @@ void cTheoreticalSpectrum::generateNTerminalFragmentIons(int maxcharge, int& pea peak.description += to_string(trotation->id + 1) + "_"; } -#if OLIGOKETIDES == 1 - if ((peptidetype == linearoligoketide) || (peptidetype == cyclicoligoketide)) { + if ((peptidetype == linearpolyketide) || (peptidetype == cyclicpolyketide)) { peak.description += parameters->fragmentdefinitions[fragmentiontype].name.substr(0, 2) + to_string(i + 1); if (parameters->fragmentdefinitions[fragmentiontype].name.size() > 2) { peak.description += parameters->fragmentdefinitions[fragmentiontype].name.substr(2, parameters->fragmentdefinitions[fragmentiontype].name.length() - 2); } } else { -#endif peak.description += parameters->fragmentdefinitions[fragmentiontype].name.substr(0, 1) + to_string(i + 1); if (parameters->fragmentdefinitions[fragmentiontype].name.size() > 1) { peak.description += parameters->fragmentdefinitions[fragmentiontype].name.substr(1, parameters->fragmentdefinitions[fragmentiontype].name.length() - 1); } -#if OLIGOKETIDES == 1 } -#endif addAdductToDescription(peak.description); peak.description += ": "; @@ -2421,17 +2308,13 @@ void cTheoreticalSpectrum::generateNTerminalFragmentIons(int maxcharge, int& pea } -void cTheoreticalSpectrum::generateCTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& intcomposition, eFragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, ePeptideType peptidetype, TRotationInfo* trotation, eResidueLossType rightresiduelosstype, bool haslastblockartificial) { +void cTheoreticalSpectrum::generateCTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& intcomposition, eFragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, ePeptideType peptidetype, bool regularblocksorder, TRotationInfo* trotation, eResidueLossType rightresiduelosstype, bool haslastblockartificial) { cPeak peak; double tempratio; string tempdescription; peak.mzratio = parameters->fragmentdefinitions[fragmentiontype].massdifference; - if ((peptidetype == linear) || (peptidetype == linearpolysaccharide) -#if OLIGOKETIDES == 1 - || (peptidetype == linearoligoketide) -#endif - ) { + if ((peptidetype == linear) || (peptidetype == linearpolyketide)) { peak.mzratio += searchedmodifications[candidate.getEndModifID()].massdifference; } if ((peptidetype == branched) || (peptidetype == branchcyclic)) { @@ -2456,15 +2339,10 @@ void cTheoreticalSpectrum::generateCTerminalFragmentIons(int maxcharge, int& pea case branchcyclic: peak.rotationid = rotationid*6 + trotation->id; // to do - potential bug break; -#if OLIGOKETIDES == 1 - case linearoligoketide: - peak.rotationid = rotationid; - break; - case cyclicoligoketide: + case linearpolyketide: peak.rotationid = rotationid; break; -#endif - case linearpolysaccharide: + case cyclicpolyketide: peak.rotationid = rotationid; break; case other: @@ -2498,8 +2376,7 @@ void cTheoreticalSpectrum::generateCTerminalFragmentIons(int maxcharge, int& pea //} } -#if OLIGOKETIDES == 1 - if (peptidetype == linearoligoketide) { + if (regularblocksorder && (peptidetype == linearpolyketide)) { if (!haslastblockartificial && (rightresiduelosstype == h2_loss) && (parameters->fragmentdefinitions[fragmentiontype].parent == r1h_ion) && (order % 2 == 0)) { continue; } @@ -2516,18 +2393,29 @@ void cTheoreticalSpectrum::generateCTerminalFragmentIons(int maxcharge, int& pea continue; } } -#endif + + if (peptidetype == linearpolyketide) { + if (!haslastblockartificial && (rightresiduelosstype == h2_loss) && ((parameters->fragmentdefinitions[fragmentiontype].parent == r1oh_ion) || (parameters->fragmentdefinitions[fragmentiontype].parent == r2oh_ion))) { + continue; + } + + //if (!haslastblockartificial && (candidate.getStartIonType() != fragmentIonTypeEnd) && parameters->fragmentdefinitions[candidate.getStartIonType()].nterminal && ((parameters->fragmentdefinitions[fragmentiontype].parent == r1oh_ion) || (parameters->fragmentdefinitions[fragmentiontype].parent == r2oh_ion))) { + // continue; + //} + + //if (!haslastblockartificial && (candidate.getStartIonType() != fragmentIonTypeEnd) && parameters->fragmentdefinitions[candidate.getStartIonType()].cterminal && ((parameters->fragmentdefinitions[fragmentiontype].parent == r1h_ion) || (parameters->fragmentdefinitions[fragmentiontype].parent == r2h_ion))) { + // continue; + //} + } peak.seriesid = (int)intcomposition.size() - i - 1; if (writedescription) { peak.description = ""; -#if OLIGOKETIDES == 1 - if (peptidetype == cyclicoligoketide) { + if (peptidetype == cyclicpolyketide) { peak.description += to_string(splittingsites[rotationid].first + 1) + "-" + to_string(splittingsites[rotationid].second + 1) + "_"; } -#endif //if (peptidetype == cyclic) { // peak.description += to_string(splittingsites[rotationid].first + 1) + "-" + to_string(splittingsites[rotationid].second + 1) + "_"; //} @@ -2539,22 +2427,18 @@ void cTheoreticalSpectrum::generateCTerminalFragmentIons(int maxcharge, int& pea peak.description += to_string(trotation->id + 1) + "_"; } -#if OLIGOKETIDES == 1 - if ((peptidetype == linearoligoketide) || (peptidetype == cyclicoligoketide)) { + if ((peptidetype == linearpolyketide) || (peptidetype == cyclicpolyketide)) { peak.description += parameters->fragmentdefinitions[fragmentiontype].name.substr(0, 2) + to_string((int)intcomposition.size() - i); if (parameters->fragmentdefinitions[fragmentiontype].name.size() > 2) { peak.description += parameters->fragmentdefinitions[fragmentiontype].name.substr(2, parameters->fragmentdefinitions[fragmentiontype].name.length() - 2); } } else { -#endif peak.description += parameters->fragmentdefinitions[fragmentiontype].name.substr(0, 1) + to_string((int)intcomposition.size() - i); if (parameters->fragmentdefinitions[fragmentiontype].name.size() > 1) { peak.description += parameters->fragmentdefinitions[fragmentiontype].name.substr(1, parameters->fragmentdefinitions[fragmentiontype].name.length() - 1); } -#if OLIGOKETIDES == 1 } -#endif addAdductToDescription(peak.description); peak.description += ": "; @@ -2612,11 +2496,6 @@ void cTheoreticalSpectrum::resizePeakList(int size) { } -double cTheoreticalSpectrum::getPrecursorMass(cBricksDatabase& brickdatabasewithcombinations) { - return candidate.getPrecursorMass(brickdatabasewithcombinations, parameters); -} - - double cTheoreticalSpectrum::getWeightedIntensityScore() const { return intensityweightedscore; } @@ -2682,6 +2561,16 @@ void cTheoreticalSpectrum::setNumberOfCompletedSeries(int numberofcompletedserie } +void cTheoreticalSpectrum::setPathId(int pathid) { + this->pathid = pathid; +} + + +int cTheoreticalSpectrum::getPathId() const { + return pathid; +} + + void cTheoreticalSpectrum::setParameters(cParameters* parameters) { this->parameters = parameters; } @@ -2723,6 +2612,7 @@ void cTheoreticalSpectrum::store(ofstream& os) { os.write((char *)&validposition, sizeof(int)); os.write((char *)&reversevalidposition, sizeof(int)); os.write((char *)&seriescompleted, sizeof(int)); + os.write((char *)&pathid, sizeof(int)); } @@ -2767,5 +2657,6 @@ void cTheoreticalSpectrum::load(ifstream& is) { is.read((char *)&validposition, sizeof(int)); is.read((char *)&reversevalidposition, sizeof(int)); is.read((char *)&seriescompleted, sizeof(int)); + is.read((char *)&pathid, sizeof(int)); } diff --git a/CycloBranch/core/cTheoreticalSpectrum.h b/CycloBranch/core/cTheoreticalSpectrum.h index d78f8d2..4c12cba 100644 --- a/CycloBranch/core/cTheoreticalSpectrum.h +++ b/CycloBranch/core/cTheoreticalSpectrum.h @@ -113,6 +113,7 @@ class cTheoreticalSpectrum { int validposition; int reversevalidposition; int seriescompleted; + int pathid; // remove false hits, i.e., b-H2O without existing b-ion void clearFalseHits(map >& series, vector& fragmentions); @@ -244,11 +245,8 @@ class cTheoreticalSpectrum { int compareBranchCyclic(cPeaksList& sortedpeaklist, cBricksDatabase& bricksdatabasewithcombinations, bool writedescription, regex& sequencetag, regex& searchedsequence); -#if OLIGOKETIDES == 1 - - /** - \brief Compare the theoretical spectrum of a linear oligoketide with an experimental spectrum. + \brief Compare the theoretical spectrum of a linear polyketide with an experimental spectrum. \param sortedpeaklist reference to an experimental peaklist \param bricksdatabasewithcombinations reference to a database of bricks with combinations of bricks \param writedescription if true then string descriptions of peaks are filled @@ -256,11 +254,11 @@ class cTheoreticalSpectrum { \param searchedsequence reference to a regex of a searched sequence \retval int number theoretical peaks generated; -2 when the sequence tag does not match the peptide sequence candidate */ - int compareLinearOligoketide(cPeaksList& sortedpeaklist, cBricksDatabase& bricksdatabasewithcombinations, bool writedescription, regex& sequencetag, regex& searchedsequence); + int compareLinearPolyketide(cPeaksList& sortedpeaklist, cBricksDatabase& bricksdatabasewithcombinations, bool writedescription, regex& sequencetag, regex& searchedsequence); /** - \brief Compare the theoretical spectrum of a cyclic oligoketide with an experimental spectrum. + \brief Compare the theoretical spectrum of a cyclic polyketide with an experimental spectrum. \param sortedpeaklist reference to an experimental peaklist \param bricksdatabasewithcombinations reference to a database of bricks with combinations of bricks \param writedescription if true then string descriptions of peaks are filled @@ -268,22 +266,7 @@ class cTheoreticalSpectrum { \param searchedsequence reference to a regex of a searched sequence \retval int number theoretical peaks generated; -2 when the sequence tag does not match the peptide sequence candidate */ - int compareCyclicOligoketide(cPeaksList& sortedpeaklist, cBricksDatabase& bricksdatabasewithcombinations, bool writedescription, regex& sequencetag, regex& searchedsequence); - - -#endif - - - /** - \brief Compare the theoretical spectrum of a linear polysaccharide with an experimental spectrum. - \param sortedpeaklist reference to an experimental peaklist - \param bricksdatabasewithcombinations reference to a database of bricks with combinations of bricks - \param writedescription if true then string descriptions of peaks are filled - \param sequencetag reference to a regex of a sequence tag - \param searchedsequence reference to a regex of a searched sequence - \retval int number theoretical peaks generated; -2 when the sequence tag does not match the peptide sequence candidate - */ - int compareLinearPolysaccharide(cPeaksList& sortedpeaklist, cBricksDatabase& bricksdatabasewithcombinations, bool writedescription, regex& sequencetag, regex& searchedsequence); + int compareCyclicPolyketide(cPeaksList& sortedpeaklist, cBricksDatabase& bricksdatabasewithcombinations, bool writedescription, regex& sequencetag, regex& searchedsequence); /** @@ -347,11 +330,12 @@ class cTheoreticalSpectrum { \param splittingsites reference to a vector of splitting sites of a cyclic peptide \param searchedmodifications reference to a vector of searched modifications \param peptidetype the type of searched peptide + \param regularblocksorder check regular order of ketide blocks \param trotation a pointer to a T-permutation of a branched peptide \param leftresiduelosstype a residue type of the leftmost building block \param hasfirstblockartificial true when the first block is artificial, false otherwise */ - void generateNTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& intcomposition, eFragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, ePeptideType peptidetype, TRotationInfo* trotation = 0, eResidueLossType leftresiduelosstype = h2o_loss, bool hasfirstblockartificial = false); + void generateNTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& intcomposition, eFragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, ePeptideType peptidetype, bool regularblocksorder, TRotationInfo* trotation = 0, eResidueLossType leftresiduelosstype = h2o_loss, bool hasfirstblockartificial = false); /** @@ -366,11 +350,12 @@ class cTheoreticalSpectrum { \param splittingsites reference to a vector of splitting sites of a cyclic peptide \param searchedmodifications reference to a vector of searched modifications \param peptidetype the type of searched peptide + \param regularblocksorder check regular order of ketide blocks \param trotation a pointer to a T-permutation of a branched peptide \param rightresiduelosstype a residue type of the rightmost building block \param haslastblockartificial true when the last block is artificial, false otherwise */ - void generateCTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& intcomposition, eFragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, ePeptideType peptidetype, TRotationInfo* trotation = 0, eResidueLossType rightresiduelosstype = h2o_loss, bool haslastblockartificial = false); + void generateCTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& intcomposition, eFragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, ePeptideType peptidetype, bool regularblocksorder, TRotationInfo* trotation = 0, eResidueLossType rightresiduelosstype = h2o_loss, bool haslastblockartificial = false); /** @@ -387,14 +372,6 @@ class cTheoreticalSpectrum { void resizePeakList(int size); - /** - \brief Get the precursor mass of the peptide sequence candidate. - \param brickdatabasewithcombinations reference to an input database of bricks with combinations of bricks - \retval double precursor mass of the candidate - */ - double getPrecursorMass(cBricksDatabase& brickdatabasewithcombinations); - - /** \brief Get the sum of relative intensities of matched peaks. \retval double sum of relative intensities of matched peaks @@ -487,6 +464,20 @@ class cTheoreticalSpectrum { void setNumberOfCompletedSeries(int numberofcompletedseries); + /** + \brief Set path id. + \param pathid id of a path + */ + void setPathId(int pathid); + + + /** + \brief Get path id. + \retval int id of a path + */ + int getPathId() const; + + /** \brief Set a pointer to the parameters of the application. \param parameters the pointer to the parameters of the application diff --git a/CycloBranch/core/cTheoreticalSpectrumList.cpp b/CycloBranch/core/cTheoreticalSpectrumList.cpp index 66a96a7..7ddbac5 100644 --- a/CycloBranch/core/cTheoreticalSpectrumList.cpp +++ b/CycloBranch/core/cTheoreticalSpectrumList.cpp @@ -256,16 +256,11 @@ int cTheoreticalSpectrumList::parallelCompareAndStore(cCandidateSet& candidates, case branchcyclic: theoreticalpeaksrealsize = tsp.compareBranchCyclic(peaklist, *bricksdb, true, rxsequencetag, rxsearchedsequence); break; -#if OLIGOKETIDES == 1 - case linearoligoketide: - theoreticalpeaksrealsize = tsp.compareLinearOligoketide(peaklist, *bricksdb, true, rxsequencetag, rxsearchedsequence); + case linearpolyketide: + theoreticalpeaksrealsize = tsp.compareLinearPolyketide(peaklist, *bricksdb, true, rxsequencetag, rxsearchedsequence); break; - case cyclicoligoketide: - theoreticalpeaksrealsize = tsp.compareCyclicOligoketide(peaklist, *bricksdb, true, rxsequencetag, rxsearchedsequence); - break; -#endif - case linearpolysaccharide: - theoreticalpeaksrealsize = tsp.compareLinearPolysaccharide(peaklist, *bricksdb, true, rxsequencetag, rxsearchedsequence); + case cyclicpolyketide: + theoreticalpeaksrealsize = tsp.compareCyclicPolyketide(peaklist, *bricksdb, true, rxsequencetag, rxsearchedsequence); break; case other: default: @@ -285,6 +280,8 @@ int cTheoreticalSpectrumList::parallelCompareAndStore(cCandidateSet& candidates, //computeNumbersOfCompletedSeries(); // sort peaks in theoretical spectra by mass and set real names of peptides + vector paths; + string tmps; for (int i = 0; i < (int)theoreticalspectra.size(); i++) { theoreticalspectra[i].sortByMass(); theoreticalspectra[i].getCandidate().setRealPeptideName(*bricksdb, parameters->peptidetype); @@ -296,10 +293,23 @@ int cTheoreticalSpectrumList::parallelCompareAndStore(cCandidateSet& candidates, } if (parameters->mode == denovoengine) { theoreticalspectra[i].getCandidate().setPath(*graph, parameters); + tmps = theoreticalspectra[i].getCandidate().getPathAsString(); + auto it = std::find(paths.begin(), paths.end(), tmps); + if (it == paths.end()) { + theoreticalspectra[i].setPathId((int)paths.size()); + paths.push_back(tmps); + } + else { + theoreticalspectra[i].setPathId(it - paths.begin()); + } } // parameters must not be used by viewer, they are not stored/loaded theoreticalspectra[i].setParameters(0); } + + if (parameters->mode == denovoengine) { + sortAndFitSize(); + } // -1 = partial results, aborted by user return terminatecomputation ? -1 : 0; diff --git a/CycloBranch/core/utilities.cpp b/CycloBranch/core/utilities.cpp index 7b72d2c..007087c 100644 --- a/CycloBranch/core/utilities.cpp +++ b/CycloBranch/core/utilities.cpp @@ -4,7 +4,7 @@ QString appname = "CycloBranch"; -QString appversion = "v. 1.1.170 (64-bit)"; +QString appversion = "v. 1.1.570 (64-bit)"; #if OS_TYPE == UNX @@ -74,16 +74,11 @@ bool checkRegex(ePeptideType peptidetype, string& sequence, string& errormessage switch (peptidetype) { case linear: - case linearpolysaccharide: -#if OLIGOKETIDES == 1 - case linearoligoketide: -#endif + case linearpolyketide: rx = "^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*$"; break; case cyclic: -#if OLIGOKETIDES == 1 - case cyclicoligoketide: -#endif + case cyclicpolyketide: rx = "^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])+$"; break; case branched: @@ -186,16 +181,11 @@ ePeptideType getPeptideTypeFromString(string& s) { if (s.compare("branch-cyclic") == 0) { return branchcyclic; } -#if OLIGOKETIDES == 1 - if (s.compare("linear-oligoketide") == 0) { - return linearoligoketide; + if (s.compare("linear-polyketide") == 0) { + return linearpolyketide; } - if (s.compare("cyclic-oligoketide") == 0) { - return cyclicoligoketide; - } -#endif - if (s.compare("linear-polysaccharide") == 0) { - return linearpolysaccharide; + if (s.compare("cyclic-polyketide") == 0) { + return cyclicpolyketide; } if (s.compare("other") == 0) { return other; @@ -220,16 +210,11 @@ string getStringFromPeptideType(ePeptideType peptidetype) { case branchcyclic: return "branch-cyclic"; break; -#if OLIGOKETIDES == 1 - case linearoligoketide: - return "linear-oligoketide"; + case linearpolyketide: + return "linear-polyketide"; break; - case cyclicoligoketide: - return "cyclic-oligoketide"; - break; -#endif - case linearpolysaccharide: - return "linear-polysaccharide"; + case cyclicpolyketide: + return "cyclic-polyketide"; break; case other: return "other"; @@ -250,3 +235,16 @@ double cropPrecisionToSixDecimals(double value) { return val; } + +QByteArray cropPrecisionToSixDecimalsByteArray(double value) { + char buffer[50]; + sprintf_s(buffer, "%.6f\0", value); + QByteArray bytearray = buffer; + return bytearray; +} + + +bool operator == (cCoordinates const& a, cCoordinates const& b) { + return ((a.x == b.x) && (a.y == b.y) && (a.id == b.id)); +} + diff --git a/CycloBranch/core/utilities.h b/CycloBranch/core/utilities.h index 33e3955..b8f92d9 100644 --- a/CycloBranch/core/utilities.h +++ b/CycloBranch/core/utilities.h @@ -8,9 +8,12 @@ #define _UTILITIES_H #include +#include #include #include #include +#include +#include #include class cBrick; @@ -36,9 +39,6 @@ class cBrick; #endif -#define OLIGOKETIDES 1 - - using namespace std; using namespace boost; @@ -51,15 +51,9 @@ enum ePeptideType { cyclic = 1, branched = 2, branchcyclic = 3, -#if OLIGOKETIDES == 1 - linearoligoketide = 4, - cyclicoligoketide = 5, - linearpolysaccharide = 6, - other = 7 -#else - linearpolysaccharide = 4, - other = 5 -#endif + linearpolyketide = 4, + cyclicpolyketide = 5, + other = 6 }; @@ -174,5 +168,139 @@ string getStringFromPeptideType(ePeptideType peptidetype); double cropPrecisionToSixDecimals(double value); +/** + \brief Crop a precision of a double to six decimal places. + \param value an input value + \retval QByteArray a value with the limited precision +*/ +QByteArray cropPrecisionToSixDecimalsByteArray(double value); + + +/** + \brief Store coordinates x and y. +*/ +struct cCoordinates { + + /** + \brief x coordinate + */ + int x; + + + /** + \brief y coordinate + */ + int y; + + + /** + \brief scan id + */ + int id; + + + /** + \brief m/z ratio + */ + double mzratio; + + + /** + \brief intensity + */ + double intensity; + + + /** + \brief name of compound + */ + string name; + + + /** + \brief The constructor. + */ + cCoordinates() { + x = 0; + y = 0; + id = 0; + mzratio = 0; + intensity = 0; + name = ""; + } + + + /** + \brief The constructor. + \param x coordinate x + \param y coordinate y + \param id scan id + \param mzratio m/z ratio + \param intensity intensity + \param name the name of item + */ + cCoordinates(int x, int y, int id, double mzratio, double intensity, string name = "") { + this->x = x; + this->y = y; + this->id = id; + this->mzratio = mzratio; + this->intensity = intensity; + this->name = name; + } + + + /** + \brief Set the coordinates. + \param x coordinate x + \param y coordinate y + \param id scan id + \param mzratio m/z ratio + \param intensity intensity + \param name the name of item + */ + void set(int x, int y, int id, double mzratio, double intensity, string name = "") { + this->x = x; + this->y = y; + this->id = id; + this->mzratio = mzratio; + this->intensity = intensity; + this->name = name; + } + +}; + + +/** + \brief Register vector by Qt. +*/ +Q_DECLARE_METATYPE(vector); + + +/** + \brief The structure defining a hash function of cCoordinates. +*/ +struct hash_cCoordinates { + + /** + \brief Hash cCoordinates. + \param coordinates cCoordinates + \retval size_t hashed cCoordinates + */ + size_t operator()(const cCoordinates& coordinates) const { + return std::hash()(coordinates.x) ^ std::hash()(coordinates.y) ^ std::hash()(coordinates.id); + } + +}; + + +/** + \brief Overloaded operator ==. + \param a first candidate + \param b second candidate + \retval bool true when cCoordinates are equal +*/ +bool operator == (cCoordinates const& a, cCoordinates const& b); + + #endif diff --git a/CycloBranch/gui/cAboutWidget.cpp b/CycloBranch/gui/cAboutWidget.cpp index ac06537..98c4a42 100644 --- a/CycloBranch/gui/cAboutWidget.cpp +++ b/CycloBranch/gui/cAboutWidget.cpp @@ -64,6 +64,7 @@ cAboutWidget::~cAboutWidget() { void cAboutWidget::closeEvent(QCloseEvent *event) { accept(); + event->accept(); } @@ -71,6 +72,7 @@ void cAboutWidget::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Escape) { hide(); } + event->accept(); } diff --git a/CycloBranch/gui/cBranchCyclicWidget.cpp b/CycloBranch/gui/cBranchCyclicWidget.cpp index 3214dc6..431394e 100644 --- a/CycloBranch/gui/cBranchCyclicWidget.cpp +++ b/CycloBranch/gui/cBranchCyclicWidget.cpp @@ -144,6 +144,7 @@ void cBranchCyclicWidget::paintEvent(QPaintEvent *event) { painter.begin(this); paint(painter); painter.end(); + event->accept(); } diff --git a/CycloBranch/gui/cBranchedWidget.cpp b/CycloBranch/gui/cBranchedWidget.cpp index f551660..70754d3 100644 --- a/CycloBranch/gui/cBranchedWidget.cpp +++ b/CycloBranch/gui/cBranchedWidget.cpp @@ -99,6 +99,7 @@ void cBranchedWidget::paintEvent(QPaintEvent *event) { painter.begin(this); paint(painter); painter.end(); + event->accept(); } diff --git a/CycloBranch/gui/cBricksDatabaseProxyModel.cpp b/CycloBranch/gui/cBricksDatabaseProxyModel.cpp new file mode 100644 index 0000000..7171448 --- /dev/null +++ b/CycloBranch/gui/cBricksDatabaseProxyModel.cpp @@ -0,0 +1,43 @@ +#include "gui/cBricksDatabaseProxyModel.h" + + +cBricksDatabaseProxyModel::cBricksDatabaseProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { +} + + +bool cBricksDatabaseProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { + int size = 6; + + for (int i = 1; i < size; i++) { + if (sourceModel()->data(sourceModel()->index(sourceRow, i, sourceParent)).toString().contains(filterRegExp())) { + return true; + } + } + + return false; +} + + +bool cBricksDatabaseProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { + if (left.column() == 6) { + return false; + } + + QVariant leftData = sourceModel()->data(left); + QVariant rightData = sourceModel()->data(right); + + if (left.column() == 0) { + return leftData.toInt() < rightData.toInt(); + } + + if (leftData.type() == QVariant::ByteArray) { + return leftData.toDouble() < rightData.toDouble(); + } + + if (leftData.type() == QVariant::String) { + return leftData.toString() < rightData.toString(); + } + + return QSortFilterProxyModel::lessThan(left, right); +} + diff --git a/CycloBranch/gui/cBricksDatabaseProxyModel.h b/CycloBranch/gui/cBricksDatabaseProxyModel.h new file mode 100644 index 0000000..1b87671 --- /dev/null +++ b/CycloBranch/gui/cBricksDatabaseProxyModel.h @@ -0,0 +1,58 @@ +/** + \file cBricksDatabaseProxyModel.h + \brief A proxy model for editor of database of building blocks. +*/ + + +#ifndef _CBRICKSDATABASEPROXYMODEL_H +#define _CBRICKSDATABASEPROXYMODEL_H + +#include +#include +#include +#include "core/cFragmentIons.h" + + +/** + \brief A proxy model for editor of database of building blocks. +*/ +class cBricksDatabaseProxyModel : public QSortFilterProxyModel { + + Q_OBJECT + +public: + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cBricksDatabaseProxyModel(QObject *parent = 0); + + +protected: + + + /** + \brief Reimplementation of filterAcceptsRow. + \param sourceRow int + \param sourceParent QModelIndex + \retval bool bool + */ + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE; + + + /** + \brief Reimplementation of lessThan. + \param left QModelIndex + \param right QModelIndex + \retval bool bool + */ + bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE; + + +}; + + +#endif + diff --git a/CycloBranch/gui/cBricksDatabaseWidget.cpp b/CycloBranch/gui/cBricksDatabaseWidget.cpp index d493e71..f75dccf 100644 --- a/CycloBranch/gui/cBricksDatabaseWidget.cpp +++ b/CycloBranch/gui/cBricksDatabaseWidget.cpp @@ -2,8 +2,6 @@ #include "gui/cMainThread.h" #include "gui/cEventFilter.h" -#include -#include #include #include #include @@ -12,10 +10,11 @@ #include #include #include -#include #include #include #include +#include +#include int numberOfOccurrences(const string& s, char c) { @@ -32,30 +31,16 @@ int numberOfOccurrences(const string& s, char c) { cBricksDatabaseWidget::cBricksDatabaseWidget(QWidget* parent) { this->parent = parent; - setWindowTitle("Building Blocks Editor"); - setWindowIcon(QIcon(":/images/icons/68.png")); - - insertrow = new QPushButton(tr("Add Row")); - insertrow->setToolTip("Add a new row."); - insertrow->setShortcut(QKeySequence(Qt::Key_Insert)); - - removechecked = new QPushButton(tr(" Remove Rows ")); - removechecked->setToolTip("Remove selected rows."); - removechecked->setShortcut(QKeySequence(Qt::Key_Delete)); - - close = new QPushButton(tr("Close")); - close->setToolTip("Close the window."); - - load = new QPushButton(tr("Load")); - load->setToolTip("Load the database of building blocks."); - load->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); + editorname = "Building Blocks Editor"; - save = new QPushButton(QString(" Save ")); - save->setToolTip("Save the database of building blocks in the current file. When a file has not been loaded yet, the \"Save As ...\" file dialog is opened."); + setWindowTitle(editorname); + setWindowIcon(QIcon(":/images/icons/68.png")); - saveas = new QPushButton(tr("Save As...")); - saveas->setToolTip("Save the database of building blocks into a file."); - saveas->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D)); + menuBar = new QMenuBar(this); + menuBar->setNativeMenuBar(false); + menuFile = new QMenu(tr("&File"), this); + menuEdit = new QMenu(tr("&Edit"), this); + menuHelp = new QMenu(tr("&Help"), this); rowsfilterline = new QLineEdit(); rowsfilterline->setMinimumWidth(250); @@ -86,63 +71,129 @@ cBricksDatabaseWidget::cBricksDatabaseWidget(QWidget* parent) { rowsfilterwidget->setLayout(rowsfilterhbox); rowsfilterwidget->setMaximumWidth(420); - buttons = new QHBoxLayout(); - buttons->addWidget(close); - buttons->addStretch(); - buttons->addWidget(insertrow); - buttons->addWidget(removechecked); - buttons->addStretch(); - buttons->addWidget(rowsfilterwidget); - buttons->addStretch(); - buttons->addWidget(load); - buttons->addWidget(save); - buttons->addWidget(saveas); - - database = new QTableWidget(0, 0, this); - database->setColumnCount(7); - database->setHorizontalHeaderItem(0, new QTableWidgetItem()); - database->setHorizontalHeaderItem(1, new QTableWidgetItem()); - database->horizontalHeaderItem(1)->setText("Name(s)"); - database->setHorizontalHeaderItem(2, new QTableWidgetItem()); - database->horizontalHeaderItem(2)->setText("Acronym(s)"); - database->setHorizontalHeaderItem(3, new QTableWidgetItem()); - database->horizontalHeaderItem(3)->setText("Residue Summary"); - database->setHorizontalHeaderItem(4, new QTableWidgetItem()); - database->horizontalHeaderItem(4)->setText("Monoisotopic Residue Mass"); - database->setItemDelegateForColumn(4, &columndelegate); - database->setHorizontalHeaderItem(5, new QTableWidgetItem()); - database->horizontalHeaderItem(5)->setText("Reference(s)"); - database->setHorizontalHeaderItem(6, new QTableWidgetItem()); - database->horizontalHeaderItem(6)->setText("Preview"); + database = new QTableView(this); + databasemodel = new QStandardItemModel(0, 0, this); + proxymodel = new cBricksDatabaseProxyModel(this); + proxymodel->setSourceModel(databasemodel); + proxymodel->setDynamicSortFilter(false); + database->setModel(proxymodel); + database->setSortingEnabled(true); - database->horizontalHeader()->setStretchLastSection(true); - for (int i = 0; i < database->columnCount(); i++) { - database->resizeColumnToContents(i); - } - - headersort.resize(database->columnCount()); - for (int i = 0; i < database->columnCount(); i++) { - headersort[i] = -1; - } + resetHeader(); mainlayout = new QVBoxLayout(); mainlayout->addWidget(database); - mainlayout->addLayout(buttons); - - connect(database->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(headerItemDoubleClicked(int))); - connect(database, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(itemChanged(QTableWidgetItem *))); - connect(insertrow, SIGNAL(released()), this, SLOT(addRow())); - connect(removechecked, SIGNAL(released()), this, SLOT(removeCheckedRows())); - connect(close, SIGNAL(released()), this, SLOT(closeWindow())); - connect(load, SIGNAL(released()), this, SLOT(loadDatabase())); - connect(save, SIGNAL(released()), this, SLOT(saveDatabase())); - connect(saveas, SIGNAL(released()), this, SLOT(saveDatabaseAs())); + + mainwidget = new QWidget(); + mainwidget->setLayout(mainlayout); + + toolbarFile = addToolBar(tr("File")); + + actionNewDatabase = new QAction(QIcon(":/images/icons/2.png"), tr("&New Database"), this); + actionNewDatabase->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N)); + actionNewDatabase->setToolTip("New Database (Ctrl + N)"); + toolbarFile->addAction(actionNewDatabase); + connect(actionNewDatabase, SIGNAL(triggered()), this, SLOT(createNewDatabase())); + + actionOpenDatabase = new QAction(QIcon(":/images/icons/52.png"), tr("&Open Database"), this); + actionOpenDatabase->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_O)); + actionOpenDatabase->setToolTip("Open Database (Ctrl + O)"); + toolbarFile->addAction(actionOpenDatabase); + connect(actionOpenDatabase, SIGNAL(triggered()), this, SLOT(openDatabase())); + + actionSaveDatabase = new QAction(QIcon(":/images/icons/22.png"), tr("&Save Database..."), this); + actionSaveDatabase->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); + actionSaveDatabase->setToolTip("Save Database... (Ctrl + S)"); + toolbarFile->addAction(actionSaveDatabase); + connect(actionSaveDatabase, SIGNAL(triggered()), this, SLOT(saveDatabase())); + + actionSaveDatabaseAs = new QAction(QIcon(":/images/icons/86.png"), tr("Save &Database As..."), this); + actionSaveDatabaseAs->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D)); + actionSaveDatabaseAs->setToolTip("Save Database As... (Ctrl + D)"); + toolbarFile->addAction(actionSaveDatabaseAs); + connect(actionSaveDatabaseAs, SIGNAL(triggered()), this, SLOT(saveDatabaseAs())); + + actionImportDatabase = new QAction(QIcon(":/images/icons/63.png"), tr("&Import Database"), this); + actionImportDatabase->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_I)); + actionImportDatabase->setToolTip("Import Database (Ctrl + I)"); + toolbarFile->addAction(actionImportDatabase); + connect(actionImportDatabase, SIGNAL(triggered()), this, SLOT(importDatabase())); + + actionCloseWindow = new QAction(QIcon(":/images/icons/33.png"), tr("&Close"), this); + actionCloseWindow->setShortcut(QKeySequence(Qt::Key_Escape)); + actionCloseWindow->setToolTip("Close (Esc)"); + toolbarFile->addAction(actionCloseWindow); + connect(actionCloseWindow, SIGNAL(triggered()), this, SLOT(closeWindow())); + + toolbarEdit = addToolBar(tr("Edit")); + + actionAddRow = new QAction(QIcon(":/images/icons/13.png"), tr("&Insert Row"), this); + actionAddRow->setShortcut(QKeySequence(Qt::Key_Insert)); + actionAddRow->setToolTip("Insert Row (Insert)"); + toolbarEdit->addAction(actionAddRow); + connect(actionAddRow, SIGNAL(triggered()), this, SLOT(addRow())); + + actionRemoveSelectedRows = new QAction(QIcon(":/images/icons/14.png"), tr("&Remove Selected Rows"), this); + actionRemoveSelectedRows->setShortcut(QKeySequence(Qt::Key_Delete)); + actionRemoveSelectedRows->setToolTip("Remove Selected Rows (Delete)"); + toolbarEdit->addAction(actionRemoveSelectedRows); + connect(actionRemoveSelectedRows, SIGNAL(triggered()), this, SLOT(removeSelectedRows())); + + actionSelectAll = new QAction(QIcon(":/images/icons/38.png"), tr("Select &All"), this); + actionSelectAll->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_A)); + actionSelectAll->setToolTip("Select all rows (Ctrl + A)"); + toolbarEdit->addAction(actionSelectAll); + connect(actionSelectAll, SIGNAL(triggered()), this, SLOT(selectAll())); + + actionUnselectAll = new QAction(QIcon(":/images/icons/38b.png"), tr("&Unselect All"), this); + actionUnselectAll->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U)); + actionUnselectAll->setToolTip("Unselect all rows (Ctrl + U)"); + toolbarEdit->addAction(actionUnselectAll); + connect(actionUnselectAll, SIGNAL(triggered()), this, SLOT(unselectAll())); + + toolbarHelp = addToolBar(tr("Help")); + + actionHTMLDocumentation = new QAction(QIcon(":/images/icons/3.png"), tr("&HTML Documentation"), this); + actionHTMLDocumentation->setShortcut(QKeySequence(Qt::Key_F1)); + actionHTMLDocumentation->setToolTip("Show HTML Documentation (F1)"); + toolbarHelp->addAction(actionHTMLDocumentation); + connect(actionHTMLDocumentation, SIGNAL(triggered()), this, SLOT(showHTMLDocumentation())); + + toolbarFilter = addToolBar(tr("Filter")); + toolbarFilter->addWidget(rowsfilterwidget); + + menuFile->addAction(actionNewDatabase); + menuFile->addAction(actionOpenDatabase); + menuFile->addSeparator(); + menuFile->addAction(actionSaveDatabase); + menuFile->addAction(actionSaveDatabaseAs); + menuFile->addSeparator(); + menuFile->addAction(actionImportDatabase); + menuFile->addSeparator(); + menuFile->addAction(actionCloseWindow); + + menuEdit->addAction(actionAddRow); + menuEdit->addAction(actionRemoveSelectedRows); + menuEdit->addSeparator(); + menuEdit->addAction(actionSelectAll); + menuEdit->addAction(actionUnselectAll); + + menuHelp->addAction(actionHTMLDocumentation); + + menuBar->addMenu(menuFile); + menuBar->addMenu(menuEdit); + menuBar->addMenu(menuHelp); + + setMenuBar(menuBar); + + connect(database->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(headerItemClicked(int))); + connect(databasemodel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(itemChanged(QStandardItem*))); connect(rowsfilterbutton, SIGNAL(released()), this, SLOT(filterRows())); connect(rowsfilterclearbutton, SIGNAL(released()), this, SLOT(resetFilter())); - setLayout(mainlayout); + setCentralWidget(mainwidget); - resize(1280, 700); + resize(1280, 750); databasefile = ""; @@ -159,20 +210,11 @@ cBricksDatabaseWidget::cBricksDatabaseWidget(QWidget* parent) { cBricksDatabaseWidget::~cBricksDatabaseWidget() { - deleteTable(false); + deleteTable(); - for (int i = 0; i < database->columnCount(); i++) { - delete database->horizontalHeaderItem(i); - } - - database->setColumnCount(0); - - delete insertrow; - delete removechecked; - delete close; - delete load; - delete save; - delete saveas; + delete databasemodel; + delete proxymodel; + delete database; delete rowsfilterline; delete rowsfiltercasesensitive; @@ -181,70 +223,76 @@ cBricksDatabaseWidget::~cBricksDatabaseWidget() { delete rowsfilterhbox; delete rowsfilterwidget; - delete database; - delete buttons; delete mainlayout; + delete mainwidget; + + delete actionNewDatabase; + delete actionOpenDatabase; + delete actionSaveDatabase; + delete actionSaveDatabaseAs; + delete actionImportDatabase; + delete actionCloseWindow; + delete actionAddRow; + delete actionRemoveSelectedRows; + delete actionSelectAll; + delete actionUnselectAll; + delete actionHTMLDocumentation; + + delete menuFile; + delete menuEdit; + delete menuHelp; + + delete menuBar; } void cBricksDatabaseWidget::closeEvent(QCloseEvent *event) { closeWindow(); + event->accept(); } -void cBricksDatabaseWidget::deleteTable(bool enableprogress) { - QProgressDialog* progress; - cEventFilter filter; - int rowcount = database->rowCount(); - - if (enableprogress) { - progress = new QProgressDialog("Clearing the table...", 0, 0, rowcount, this); - progress->setMinimumWidth(250); - progress->installEventFilter(&filter); - progress->setMinimumDuration(0); - progress->setWindowModality(Qt::WindowModal); - progress->setValue(0); +void cBricksDatabaseWidget::deleteTable() { + for (int i = 0; i < databasemodel->columnCount(); i++) { + if (database->itemDelegateForColumn(i)) { + delete database->itemDelegateForColumn(i); + } } - widgetitemallocator.reset(); + databasemodel->clear(); + databasemodel->setRowCount(0); +} - for (int i = 0; i < rowcount; i++) { - delete database->cellWidget(rowcount - i - 1, 0); - delete database->cellWidget(rowcount - i - 1, 6); - if (enableprogress) { - progress->setValue(i); - } - } - - database->setRowCount(0); - - if (enableprogress) { - progress->setValue(rowcount); - delete progress; - } -} +void cBricksDatabaseWidget::resetHeader() { + databasemodel->setColumnCount(7); + databasemodel->setHorizontalHeaderItem(0, new QStandardItem()); + database->setItemDelegateForColumn(0, new cCheckBoxDelegate()); + databasemodel->setHorizontalHeaderItem(1, new QStandardItem("Name(s)")); + databasemodel->setHorizontalHeaderItem(2, new QStandardItem("Acronym(s)")); + databasemodel->setHorizontalHeaderItem(3, new QStandardItem("Residue Summary")); + databasemodel->setHorizontalHeaderItem(4, new QStandardItem("Monoisotopic Residue Mass")); + databasemodel->setHorizontalHeaderItem(5, new QStandardItem("Reference(s)")); + databasemodel->setHorizontalHeaderItem(6, new QStandardItem("Preview")); + database->setItemDelegateForColumn(6, new cMultipleButtonDelegate()); -void cBricksDatabaseWidget::removeRow(int row) { - for (int i = 0; i < database->columnCount(); i++) { - if ((i == 0) || (i == 6)) { - delete database->cellWidget(row, i); - } - else { - database->takeItem(row, i); - } - } - database->removeRow(row); + database->horizontalHeader()->setStretchLastSection(true); + for (int i = 0; i < databasemodel->columnCount(); i++) { + database->resizeColumnToContents(i); + } + database->setColumnWidth(1, 400); + database->setColumnWidth(2, 400); + database->setColumnWidth(5, 400); } bool cBricksDatabaseWidget::checkTable() { // the fields name, acronym and reference must contain the same numbers of '/' int checkslash; - for (int i = 0; i < database->rowCount(); i++) { - checkslash = numberOfOccurrences(database->item(i, 1)->text().toStdString(),'/'); - if ((checkslash != numberOfOccurrences(database->item(i, 2)->text().toStdString(),'/')) || (checkslash != numberOfOccurrences(database->item(i, 5)->text().toStdString(),'/'))) { + for (int i = 0; i < databasemodel->rowCount(); i++) { + checkslash = numberOfOccurrences(databasemodel->item(i, 1)->text().toStdString(),'/'); + if ((checkslash != numberOfOccurrences(databasemodel->item(i, 2)->text().toStdString(),'/')) || (checkslash != numberOfOccurrences(databasemodel->item(i, 5)->text().toStdString(),'/'))) { QMessageBox msgBox; QString errstr = "Syntax error in the row no. "; errstr += to_string(i + 1).c_str(); @@ -256,8 +304,8 @@ bool cBricksDatabaseWidget::checkTable() { } // check summary formulas - for (int i = 0; i < database->rowCount(); i++) { - if (!checkFormula(i, database->item(i, 3)->text().toStdString())) { + for (int i = 0; i < databasemodel->rowCount(); i++) { + if (!checkFormula(i, databasemodel->item(i, 3)->text().toStdString())) { return false; } } @@ -280,8 +328,8 @@ bool cBricksDatabaseWidget::checkFormula(int row, const string& summary) { msgBox.exec(); return false; } - if (database->item(row, 4)) { - database->item(row, 4)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(formula.getMass())); + if (databasemodel->item(row, 4)) { + databasemodel->item(row, 4)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(formula.getMass())), Qt::DisplayRole); } return true; } @@ -295,46 +343,32 @@ void cBricksDatabaseWidget::setDataModified(bool datamodified) { this->datamodified = datamodified; if (datamodified) { - save->setText("*" + save->text()); + setWindowTitle("*" + windowTitle()); } else { - if ((save->text().size() > 0) && (save->text().at(0) == '*')) { - save->setText(save->text().toStdString().substr(1).c_str()); + if ((windowTitle().size() > 0) && (windowTitle().at(0) == '*')) { + setWindowTitle(windowTitle().toStdString().substr(1).c_str()); } } } void cBricksDatabaseWidget::keyPressEvent(QKeyEvent *event) { - if (event->key() == Qt::Key_Escape) { - closeWindow(); - } - if ((event->key() == Qt::Key_Enter) || (event->key() == Qt::Key_Return)) { if (rowsfilterline->hasFocus()) { filterRows(); } } - if (event->key() == Qt::Key_F1) { - #if OS_TYPE == WIN - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/blockseditor.html").absoluteFilePath())); - #else - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/blockseditor.html").absoluteFilePath())); - #endif - } - if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_F)) { rowsfilterline->setFocus(); } - if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_N)) { + if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_T)) { rowsfiltercasesensitive->setChecked(!rowsfiltercasesensitive->isChecked()); } - if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_S)) { - saveDatabase(); - } + event->accept(); } @@ -354,15 +388,15 @@ void cBricksDatabaseWidget::closeWindow() { } -void cBricksDatabaseWidget::loadDatabase() { - QString filename = QFileDialog::getOpenFileName(this, tr("Load the Database of Building Blocks"), lastdir, tr("Database of Building Blocks (*.txt)")); +void cBricksDatabaseWidget::openDatabase() { + QString filename = QFileDialog::getOpenFileName(this, tr("Open Database"), lastdir, tr("Database of Building Blocks (*.txt)")); if (!filename.isEmpty()) { lastdir = filename; string errormessage; databasefile = filename; - save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); + setWindowTitle(editorname + QString(" - ") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str())); inputstream.open(filename.toStdString().c_str()); @@ -373,10 +407,12 @@ void cBricksDatabaseWidget::loadDatabase() { } else { - bricks.clear(); - bricks.loadFromPlainTextStream(inputstream, errormessage, true); + deleteTable(); + resetHeader(); + resetFilter(); - deleteTable(true); + bricks.clear(); + bricks.loadFromPlainTextStream(inputstream, errormessage, true, false); QProgressDialog progress("Loading the Database of Building Blocks...", "Cancel", 0, bricks.size(), this); progress.setMinimumWidth(250); @@ -385,45 +421,57 @@ void cBricksDatabaseWidget::loadDatabase() { progress.setMinimumDuration(0); progress.setWindowModality(Qt::WindowModal); - database->setRowCount(bricks.size()); + database->setModel(0); + proxymodel->setSourceModel(0); + database->setSortingEnabled(false); + + databasemodel->setRowCount(bricks.size()); for (int i = 0; i < bricks.size(); i++) { - QCheckBox* checkbox = new QCheckBox(); - database->setCellWidget(i, 0, checkbox); - database->setItem(i, 1, widgetitemallocator.getNewItem()); - database->item(i, 1)->setText(bricks[i].getName().c_str()); + databasemodel->setItem(i, 0, new QStandardItem()); + databasemodel->item(i, 0)->setFlags(databasemodel->item(i, 0)->flags() & ~Qt::ItemIsEditable); + + databasemodel->setItem(i, 1, new QStandardItem()); + databasemodel->item(i, 1)->setText(bricks[i].getName().c_str()); - database->setItem(i, 2, widgetitemallocator.getNewItem()); - database->item(i, 2)->setText(bricks[i].getAcronymsAsString().c_str()); + databasemodel->setItem(i, 2, new QStandardItem()); + databasemodel->item(i, 2)->setText(bricks[i].getAcronymsAsString().c_str()); - database->setItem(i, 3, widgetitemallocator.getNewItem()); - database->item(i, 3)->setText(bricks[i].getSummary().c_str()); + databasemodel->setItem(i, 3, new QStandardItem()); + databasemodel->item(i, 3)->setText(bricks[i].getSummary().c_str()); - database->setItem(i, 4, widgetitemallocator.getNewItem()); - database->item(i, 4)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(bricks[i].getMass())); + databasemodel->setItem(i, 4, new QStandardItem()); + databasemodel->item(i, 4)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(bricks[i].getMass())), Qt::DisplayRole); - database->setItem(i, 5, widgetitemallocator.getNewItem()); - database->item(i, 5)->setText(bricks[i].getReferencesAsString().c_str()); + databasemodel->setItem(i, 5, new QStandardItem()); + databasemodel->item(i, 5)->setText(bricks[i].getReferencesAsString().c_str()); - database->setCellWidget(i, 6, new QLabel(bricks[i].getAcronymsWithReferencesAsHTMLString().c_str())); - ((QLabel *)database->cellWidget(i, 6))->setTextFormat(Qt::RichText); - ((QLabel *)database->cellWidget(i, 6))->setTextInteractionFlags(Qt::TextBrowserInteraction); - ((QLabel *)database->cellWidget(i, 6))->setOpenExternalLinks(true); + databasemodel->setItem(i, 6, new QStandardItem()); + databasemodel->item(i, 6)->setText(bricks[i].getAcronymsWithReferencesAsHTMLString().c_str()); progress.setValue(i); if (progress.wasCanceled()) { - deleteTable(true); + deleteTable(); + resetHeader(); bricks.clear(); databasefile = ""; - save->setText(" Save "); + setWindowTitle(editorname); break; } } - for (int i = 0; i < database->columnCount(); i++) { + proxymodel->setSourceModel(databasemodel); + database->setModel(proxymodel); + proxymodel->setSortRole(Qt::InitialSortOrderRole); + database->setSortingEnabled(true); + + for (int i = 0; i < databasemodel->columnCount(); i++) { database->resizeColumnToContents(i); } + database->setColumnWidth(1, 400); + database->setColumnWidth(2, 400); + database->setColumnWidth(5, 400); progress.setValue(bricks.size()); @@ -456,7 +504,7 @@ bool cBricksDatabaseWidget::saveDatabase() { } else { - QProgressDialog progress("Saving the Database of Building Blocks...", 0, 0, database->rowCount(), this); + QProgressDialog progress("Saving the Database of Building Blocks...", 0, 0, proxymodel->rowCount(), this); progress.setMinimumWidth(250); cEventFilter filter; progress.installEventFilter(&filter); @@ -467,39 +515,32 @@ bool cBricksDatabaseWidget::saveDatabase() { bricks.clear(); string s; - removeCheckedRows(); - - for (int i = 0; i < database->rowCount(); i++) { - - if (database->isRowHidden(i)) { - progress.setValue(i); - continue; - } + for (int i = 0; i < proxymodel->rowCount(); i++) { b.clear(); - for (int j = 0; j < database->columnCount(); j++) { + for (int j = 0; j < proxymodel->columnCount(); j++) { switch (j) { case 0: // nothing to do break; case 1: - s = database->item(i,j)->text().toStdString(); + s = proxymodel->index(i, j).data(Qt::DisplayRole).toString().toStdString(); b.setName(removeWhiteSpacesExceptSpaces(s)); break; case 2: - s = database->item(i,j)->text().toStdString(); + s = proxymodel->index(i, j).data(Qt::DisplayRole).toString().toStdString(); b.setAcronyms(removeWhiteSpacesExceptSpaces(s)); break; case 3: - s = database->item(i,j)->text().toStdString(); + s = proxymodel->index(i, j).data(Qt::DisplayRole).toString().toStdString(); b.setSummary(removeWhiteSpacesExceptSpaces(s)); break; case 4: - b.setMass(database->item(i,j)->data(Qt::DisplayRole).toDouble()); + b.setMass(proxymodel->index(i, j).data(Qt::DisplayRole).toDouble()); break; case 5: - s = database->item(i,j)->text().toStdString(); + s = proxymodel->index(i, j).data(Qt::DisplayRole).toString().toStdString(); b.setReferences(removeWhiteSpacesExceptSpaces(s)); break; default: @@ -531,13 +572,13 @@ bool cBricksDatabaseWidget::saveDatabaseAs() { return false; } - QString filename = QFileDialog::getSaveFileName(this, tr("Save the Database of Building Blocks As..."), lastdir, tr("Database of Building Blocks (*.txt)")); + QString filename = QFileDialog::getSaveFileName(this, tr("Save Database As..."), lastdir, tr("Database of Building Blocks (*.txt)")); if (!filename.isEmpty()) { lastdir = filename; databasefile = filename; - save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); + setWindowTitle(editorname + QString(" - ") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str())); return saveDatabase(); } @@ -546,30 +587,30 @@ bool cBricksDatabaseWidget::saveDatabaseAs() { void cBricksDatabaseWidget::addRow() { - int row = database->rowCount(); - database->insertRow(row); - - QCheckBox* checkbox = new QCheckBox(); - database->setCellWidget(row, 0, checkbox); - - database->setItem(row, 1, widgetitemallocator.getNewItem()); - database->setItem(row, 2, widgetitemallocator.getNewItem()); - database->setItem(row, 3, widgetitemallocator.getNewItem()); - database->setItem(row, 4, widgetitemallocator.getNewItem()); - database->setItem(row, 5, widgetitemallocator.getNewItem()); - - database->setCellWidget(row, 6, new QLabel()); - ((QLabel *)database->cellWidget(row, 6))->setTextFormat(Qt::RichText); - ((QLabel *)database->cellWidget(row, 6))->setTextInteractionFlags(Qt::TextBrowserInteraction); - ((QLabel *)database->cellWidget(row, 6))->setOpenExternalLinks(true); + resetFilter(); + + int row = databasemodel->rowCount(); + databasemodel->insertRow(row); + + databasemodel->setItem(row, 0, new QStandardItem()); + databasemodel->item(row, 0)->setFlags(databasemodel->item(row, 0)->flags() & ~Qt::ItemIsEditable); + + databasemodel->setItem(row, 1, new QStandardItem()); + databasemodel->setItem(row, 2, new QStandardItem()); + databasemodel->setItem(row, 3, new QStandardItem()); + databasemodel->setItem(row, 4, new QStandardItem()); + databasemodel->setItem(row, 5, new QStandardItem()); + databasemodel->setItem(row, 6, new QStandardItem()); + + database->scrollToBottom(); } -void cBricksDatabaseWidget::removeCheckedRows() { +void cBricksDatabaseWidget::removeSelectedRows() { int i = 0; - while (i < database->rowCount()) { - if (((QCheckBox *)(database->cellWidget(i, 0)))->isChecked()) { - removeRow(i); + while (i < proxymodel->rowCount()) { + if (proxymodel->index(i, 0).data(Qt::DisplayRole).toBool()) { + proxymodel->removeRow(i); setDataModified(true); } else { @@ -579,102 +620,196 @@ void cBricksDatabaseWidget::removeCheckedRows() { } -void cBricksDatabaseWidget::itemChanged(QTableWidgetItem* item) { +void cBricksDatabaseWidget::itemChanged(QStandardItem* item) { + if (!item) { + return; + } + // recalculate mass when formula is changed if (item->column() == 3) { checkFormula(item->row(), item->text().toStdString()); } // update references preview - if (((item->column() == 2) || (item->column() == 5)) && database->cellWidget(item->row(), 6)) { + if (((item->column() == 2) || (item->column() == 5)) && databasemodel->item(item->row(), 6)) { cBrick b; - b.setAcronyms(database->item(item->row(), 2)->text().toStdString()); - b.setReferences(database->item(item->row(), 5)->text().toStdString()); - ((QLabel *)database->cellWidget(item->row(), 6))->setText(b.getAcronymsWithReferencesAsHTMLString().c_str()); + + b.setAcronyms(databasemodel->item(item->row(), 2)->text().toStdString()); + b.setReferences(databasemodel->item(item->row(), 5)->text().toStdString()); + + databasemodel->item(item->row(), 6)->setText(b.getAcronymsWithReferencesAsHTMLString().c_str()); } - setDataModified(true); + if (item->column() > 0) { + setDataModified(true); + } } -void cBricksDatabaseWidget::headerItemDoubleClicked(int index) { +void cBricksDatabaseWidget::headerItemClicked(int index) { setDataModified(true); +} - if (headersort[index] == -1) { - database->sortByColumn(index, Qt::AscendingOrder); - headersort[index] = 1; - return; - } - if (headersort[index] == 0) { - database->sortByColumn(index, Qt::AscendingOrder); - headersort[index] = 1; - } - else { - database->sortByColumn(index, Qt::DescendingOrder); - headersort[index] = 0; - } +void cBricksDatabaseWidget::filterRows() { + proxymodel->setFilterKeyColumn(-1); + proxymodel->setFilterCaseSensitivity(rowsfiltercasesensitive->isChecked()?Qt::CaseSensitive:Qt::CaseInsensitive); + proxymodel->setFilterFixedString(rowsfilterline->text()); } -void cBricksDatabaseWidget::filterRows() { - Qt::CaseSensitivity casesensitive = rowsfiltercasesensitive->isChecked()?Qt::CaseSensitive:Qt::CaseInsensitive; - QString str = rowsfilterline->text(); - int rowcount = database->rowCount(); - bool match; - int i, j; - - QProgressDialog progress("Updating...", "Cancel", 0, rowcount, this); - progress.setMinimumWidth(250); - cEventFilter filter; - progress.installEventFilter(&filter); - progress.setMinimumDuration(0); - progress.setWindowModality(Qt::WindowModal); - - for (i = 0; i < rowcount; i++) { - - match = false; - for (j = 0; j < database->columnCount(); j++) { - // ignore non-text fields - if ((j == 0) || (j == 6)) { - continue; - } +void cBricksDatabaseWidget::resetFilter() { + rowsfilterline->setText(""); + + database->horizontalHeader()->setSortIndicator(-1, Qt::AscendingOrder); + proxymodel->sort(-1); - if (database->item(i, j)->text().contains(str, casesensitive)) { - match = true; - break; + proxymodel->setFilterKeyColumn(-1); + proxymodel->setFilterFixedString(""); +} + + +void cBricksDatabaseWidget::createNewDatabase() { + if (datamodified) { + QMessageBox::StandardButton reply; + reply = QMessageBox::question(this, appname, "Save changes ?", QMessageBox::Yes|QMessageBox::No); + + if (reply == QMessageBox::Yes) { + if (!saveDatabase()) { + return; } } - database->setRowHidden(i, !match); - progress.setValue(i); + } + + deleteTable(); + resetHeader(); + resetFilter(); + bricks.clear(); + databasefile = ""; + setWindowTitle(editorname); - if (progress.wasCanceled()) { + setDataModified(false); +} + + +void cBricksDatabaseWidget::importDatabase() { + QString filename = QFileDialog::getOpenFileName(this, tr("Import Database"), lastdir, tr("Database of Building Blocks (*.txt)")); + + if (!filename.isEmpty()) { + lastdir = filename; + string errormessage; + + inputstream.open(filename.toStdString().c_str()); + + if (!inputstream.good()) { + QMessageBox msgBox; + msgBox.setText("Cannot open the file '" + filename + "'."); + msgBox.exec(); + } + else { resetFilter(); - break; + + cBricksDatabase importedbricks; + importedbricks.loadFromPlainTextStream(inputstream, errormessage, true, false); + + QProgressDialog progress("Importing the Database of Building Blocks...", "Cancel", 0, importedbricks.size(), this); + progress.setMinimumWidth(250); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); + + database->setModel(0); + proxymodel->setSourceModel(0); + database->setSortingEnabled(false); + + int originalrowcount = databasemodel->rowCount(); + databasemodel->setRowCount(originalrowcount + importedbricks.size()); + for (int i = 0; i < importedbricks.size(); i++) { + + databasemodel->setItem(i + originalrowcount, 0, new QStandardItem()); + databasemodel->item(i + originalrowcount, 0)->setFlags(databasemodel->item(i + originalrowcount, 0)->flags() & ~Qt::ItemIsEditable); + + databasemodel->setItem(i + originalrowcount, 1, new QStandardItem()); + databasemodel->item(i + originalrowcount, 1)->setText(importedbricks[i].getName().c_str()); + + databasemodel->setItem(i + originalrowcount, 2, new QStandardItem()); + databasemodel->item(i + originalrowcount, 2)->setText(importedbricks[i].getAcronymsAsString().c_str()); + + databasemodel->setItem(i + originalrowcount, 3, new QStandardItem()); + databasemodel->item(i + originalrowcount, 3)->setText(importedbricks[i].getSummary().c_str()); + + databasemodel->setItem(i + originalrowcount, 4, new QStandardItem()); + databasemodel->item(i + originalrowcount, 4)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(importedbricks[i].getMass())), Qt::DisplayRole); + + databasemodel->setItem(i + originalrowcount, 5, new QStandardItem()); + databasemodel->item(i + originalrowcount, 5)->setText(importedbricks[i].getReferencesAsString().c_str()); + + databasemodel->setItem(i + originalrowcount, 6, new QStandardItem()); + databasemodel->item(i + originalrowcount, 6)->setText(importedbricks[i].getAcronymsWithReferencesAsHTMLString().c_str()); + + bricks.push_back(importedbricks[i]); + + progress.setValue(i); + if (progress.wasCanceled()) { + deleteTable(); + resetHeader(); + bricks.clear(); + databasefile = ""; + setWindowTitle(editorname); + break; + } + + } + + proxymodel->setSourceModel(databasemodel); + database->setModel(proxymodel); + proxymodel->setSortRole(Qt::InitialSortOrderRole); + database->setSortingEnabled(true); + + for (int i = 0; i < databasemodel->columnCount(); i++) { + database->resizeColumnToContents(i); + } + database->setColumnWidth(1, 400); + database->setColumnWidth(2, 400); + database->setColumnWidth(5, 400); + + if (progress.wasCanceled()) { + setDataModified(false); + } + else { + setDataModified(true); + } + + progress.setValue(importedbricks.size()); + } + inputstream.close(); + } +} - progress.setValue(rowcount); + +void cBricksDatabaseWidget::selectAll() { + for (int i = 0; i < proxymodel->rowCount(); i++) { + databasemodel->itemFromIndex(proxymodel->mapToSource(proxymodel->index(i, 0)))->setData(QVariant::fromValue(true), Qt::DisplayRole); + } } -void cBricksDatabaseWidget::resetFilter() { - rowsfilterline->setText(""); - int rowcount = database->rowCount(); - - QProgressDialog progress("Updating...", 0, 0, rowcount, this); - progress.setMinimumWidth(250); - cEventFilter filter; - progress.installEventFilter(&filter); - progress.setMinimumDuration(0); - progress.setWindowModality(Qt::WindowModal); - - for (int i = 0; i < rowcount; i++) { - database->setRowHidden(i, false); - progress.setValue(i); +void cBricksDatabaseWidget::unselectAll() { + for (int i = 0; i < proxymodel->rowCount(); i++) { + databasemodel->itemFromIndex(proxymodel->mapToSource(proxymodel->index(i, 0)))->setData(QVariant::fromValue(false), Qt::DisplayRole); } +} - progress.setValue(rowcount); + +void cBricksDatabaseWidget::showHTMLDocumentation() { + #if OS_TYPE == WIN + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/blockseditor.html").absoluteFilePath())); + #else + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/blockseditor.html").absoluteFilePath())); + #endif } diff --git a/CycloBranch/gui/cBricksDatabaseWidget.h b/CycloBranch/gui/cBricksDatabaseWidget.h index 5f595d3..d10b0c7 100644 --- a/CycloBranch/gui/cBricksDatabaseWidget.h +++ b/CycloBranch/gui/cBricksDatabaseWidget.h @@ -1,6 +1,6 @@ /** \file cBricksDatabaseWidget.h - \brief Visualization of the database of building blocks. + \brief An editor of building blocks database. */ @@ -11,23 +11,27 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include "core/utilities.h" #include "core/cBricksDatabase.h" -#include "core/cAllocator.h" -#include "gui/cDelegate.h" - -using namespace std; +#include "gui/cBricksDatabaseProxyModel.h" +#include "gui/cMultipleButtonDelegate.h" +#include "gui/cCheckBoxDelegate.h" // forward declaration class QHBoxLayout; class QVBoxLayout; -class QTableWidget; -class QTableWidgetItem; class QPushButton; -class QCheckBox; class QLineEdit; +class QMenuBar; +class QMenu; /** @@ -40,9 +44,9 @@ int numberOfOccurrences(const string& s, char c); /** - \brief Visualization of the database of building blocks. + \brief An editor of building blocks database. */ -class cBricksDatabaseWidget : public QWidget +class cBricksDatabaseWidget : public QMainWindow { Q_OBJECT @@ -71,14 +75,33 @@ class cBricksDatabaseWidget : public QWidget private: + QString editorname; + QWidget* parent; - QPushButton* insertrow; - QPushButton* removechecked; - QPushButton* close; - QPushButton* load; - QPushButton* save; - QPushButton* saveas; + QMenuBar* menuBar; + QMenu* menuFile; + QMenu* menuEdit; + QMenu* menuHelp; + + QToolBar* toolbarFile; + QAction* actionNewDatabase; + QAction* actionOpenDatabase; + QAction* actionSaveDatabase; + QAction* actionSaveDatabaseAs; + QAction* actionImportDatabase; + QAction* actionCloseWindow; + + QToolBar* toolbarEdit; + QAction* actionAddRow; + QAction* actionRemoveSelectedRows; + QAction* actionSelectAll; + QAction* actionUnselectAll; + + QToolBar* toolbarHelp; + QAction* actionHTMLDocumentation; + + QToolBar* toolbarFilter; QWidget* rowsfilterwidget; QHBoxLayout* rowsfilterhbox; QLineEdit* rowsfilterline; @@ -86,9 +109,11 @@ class cBricksDatabaseWidget : public QWidget QPushButton* rowsfilterbutton; QPushButton* rowsfilterclearbutton; - QTableWidget* database; - QHBoxLayout* buttons; + QTableView* database; + QStandardItemModel* databasemodel; + cBricksDatabaseProxyModel* proxymodel; QVBoxLayout* mainlayout; + QWidget* mainwidget; QString databasefile; QString lastdir; @@ -96,16 +121,11 @@ class cBricksDatabaseWidget : public QWidget ofstream outputstream; cBricksDatabase bricks; - vector headersort; - cDelegate columndelegate; - - cAllocator widgetitemallocator; - bool datamodified; - void deleteTable(bool enableprogress); + void deleteTable(); - void removeRow(int row); + void resetHeader(); bool checkTable(); @@ -127,7 +147,7 @@ private slots: void closeWindow(); - void loadDatabase(); + void openDatabase(); bool saveDatabase(); @@ -135,16 +155,27 @@ private slots: void addRow(); - void removeCheckedRows(); + void removeSelectedRows(); - void itemChanged(QTableWidgetItem* item); + void itemChanged(QStandardItem* item); - void headerItemDoubleClicked(int index); + void headerItemClicked(int index); void filterRows(); void resetFilter(); + void createNewDatabase(); + + void importDatabase(); + + void selectAll(); + + void unselectAll(); + + void showHTMLDocumentation(); + }; #endif + diff --git a/CycloBranch/gui/cCheckBoxDelegate.cpp b/CycloBranch/gui/cCheckBoxDelegate.cpp new file mode 100644 index 0000000..973459a --- /dev/null +++ b/CycloBranch/gui/cCheckBoxDelegate.cpp @@ -0,0 +1,32 @@ +#include "gui/cCheckBoxDelegate.h" + + +cCheckBoxDelegate::cCheckBoxDelegate(QObject* parent) : QStyledItemDelegate(parent) { +} + + +void cCheckBoxDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { + QStyleOptionButton button; + button.state = QStyle::State_Enabled; + + if (index.data(Qt::DisplayRole).toBool()) { + button.state |= QStyle::State_On; + } + else { + button.state |= QStyle::State_Off; + } + + button.direction = QApplication::layoutDirection(); + button.rect = option.rect; + QApplication::style()->drawControl(QStyle::CE_CheckBox, &button, painter); +} + + +bool cCheckBoxDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index) { + if (event->type() == QEvent::MouseButtonRelease) { + model->setData(model->index(index.row(), index.column()), QVariant::fromValue(!index.data(Qt::DisplayRole).toBool()), Qt::DisplayRole); + return true; + } + return false; +} + diff --git a/CycloBranch/gui/cCheckBoxDelegate.h b/CycloBranch/gui/cCheckBoxDelegate.h new file mode 100644 index 0000000..cdde244 --- /dev/null +++ b/CycloBranch/gui/cCheckBoxDelegate.h @@ -0,0 +1,65 @@ +/** + \file cCheckBoxDelegate.h + \brief A checkbox item delegate. +*/ + + +#ifndef _CCHECKBOXDELEGATE_H +#define _CCHECKBOXDELEGATE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + \brief A checkbox item delegate. +*/ +class cCheckBoxDelegate : public QStyledItemDelegate { + + Q_OBJECT + +public: + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cCheckBoxDelegate(QObject* parent = (QObject *)0); + + + /** + \brief Reimplementation of paint. + \param painter QPainter + \param option QStyleOptionViewItem + \param index QModelIndex + */ + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + + +protected: + + + /** + \brief Reimplementation of editorEvent. + \param event QEvent + \param model QAbstractItemModel + \param option QStyleOptionViewItem + \param index QModelIndex + */ + bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index); + + +}; + + +#endif + diff --git a/CycloBranch/gui/cComboBoxDelegate.cpp b/CycloBranch/gui/cComboBoxDelegate.cpp new file mode 100644 index 0000000..acbfabd --- /dev/null +++ b/CycloBranch/gui/cComboBoxDelegate.cpp @@ -0,0 +1,38 @@ +#include "gui/cComboBoxDelegate.h" + + +cComboBoxDelegate::cComboBoxDelegate(QObject* parent) : QStyledItemDelegate(parent) { +} + + +void cComboBoxDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { + QStyleOptionComboBox combobox; + combobox.state = QStyle::State_Enabled; + combobox.rect = option.rect; + combobox.currentText = QString(getStringFromPeptideType((ePeptideType)index.data(Qt::DisplayRole).toInt()).c_str()); + // visualization in Linux does not work well + // QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &combobox, painter, 0); + QApplication::style()->drawControl(QStyle::CE_ComboBoxLabel, &combobox, painter, 0); +} + + +void cComboBoxDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const { + QComboBox* combobox = static_cast(editor); + combobox->setCurrentIndex(index.data(Qt::DisplayRole).toInt()); +} + + +void cComboBoxDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { + QComboBox* combobox = qobject_cast(editor); + model->setData(index, combobox->currentIndex(), Qt::DisplayRole); +} + + +QWidget* cComboBoxDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { + QComboBox* combo = new QComboBox(parent); + for (int j = 0; j <= (int)other; j++) { + combo->addItem(QString(getStringFromPeptideType((ePeptideType)j).c_str())); + } + return combo; +} + diff --git a/CycloBranch/gui/cComboBoxDelegate.h b/CycloBranch/gui/cComboBoxDelegate.h new file mode 100644 index 0000000..1caa65e --- /dev/null +++ b/CycloBranch/gui/cComboBoxDelegate.h @@ -0,0 +1,80 @@ +/** + \file cComboBoxDelegate.h + \brief A combobox item delegate. +*/ + + +#ifndef _CCOMBOBOXDELEGATE_H +#define _CCOMBOBOXDELEGATE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "core/cFragmentIons.h" + +/** + \brief A combobox item delegate. +*/ +class cComboBoxDelegate : public QStyledItemDelegate { + + Q_OBJECT + +public: + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cComboBoxDelegate(QObject* parent = (QObject *)0); + + + /** + \brief Reimplementation of paint. + \param painter QPainter + \param option QStyleOptionViewItem + \param index QModelIndex + */ + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + + + /** + \brief Reimplementation of setEditorData. + \param editor QWidget + \param index QModelIndex + */ + void setEditorData(QWidget* editor, const QModelIndex& index) const; + + + /** + \brief Reimplementation of setModelData. + \param editor QWidget + \param model QAbstractItemModel + \param index QModelIndex + */ + void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; + + + /** + \brief Reimplementation of createEditor. + \param parent QWidget + \param option QStyleOptionViewItem + \param index QModelIndex + */ + QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const; + +}; + + +#endif + diff --git a/CycloBranch/gui/cCyclicWidget.cpp b/CycloBranch/gui/cCyclicWidget.cpp index 6b65c87..37ae860 100644 --- a/CycloBranch/gui/cCyclicWidget.cpp +++ b/CycloBranch/gui/cCyclicWidget.cpp @@ -210,31 +210,22 @@ void generateCyclicLabelsToRight(bool nterminal, int rotationid, int rotationsta string name; int m; if ((visiblerotationid == -1) || ((parameters->peptidetype == cyclic) && (visiblerotationid == rotationid)) -#if OLIGOKETIDES == 1 - || ((parameters->peptidetype == cyclicoligoketide) && (visiblerotationid == rotationid)) -#endif + || ((parameters->peptidetype == cyclicpolyketide) && (visiblerotationid == rotationid)) || ((parameters->peptidetype == branchcyclic) && (visiblerotationid == rotationid/6))) { for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { if ((nterminal && parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal) || (!nterminal && parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal) -#if OLIGOKETIDES == 1 - || (parameters->peptidetype == cyclicoligoketide) -#endif - ) { + || (parameters->peptidetype == cyclicpolyketide)) { m = 0; for (int j = fragmentstart; j < fragmentend; j++) { if ((branchstart == -1) || (branchend == -1) || ((branchstart >= 0) && (j < branchstart)) || ((branchend >= 0) && (j >= branchend))) { if (theoreticalspectrum->getVisualCoverage()[rotationid*parameters->fragmentionsfortheoreticalspectra.size() + i].series[j] > 0) { name = theoreticalspectrum->getVisualCoverage()[rotationid*parameters->fragmentionsfortheoreticalspectra.size() + i].name.substr(0, theoreticalspectrum->getVisualCoverage()[rotationid*parameters->fragmentionsfortheoreticalspectra.size() + i].name.rfind('_') + 1); -#if OLIGOKETIDES == 1 - if (parameters->peptidetype == cyclicoligoketide) { + if (parameters->peptidetype == cyclicpolyketide) { name += parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(0, 2) + to_string(j + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(2); } else { -#endif name += parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name[0] + to_string(j + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(1); -#if OLIGOKETIDES == 1 } -#endif cumulativeangle = angle*(double)((rotationstart + m + 1) % numberofringblocks) + angle/(double)2; if (cumulativeangle < pi/2) { @@ -268,31 +259,22 @@ void generateCyclicLabelsToLeft(bool nterminal, int rotationid, int rotationstar string name; int m; if ((visiblerotationid == -1) || ((parameters->peptidetype == cyclic) && (visiblerotationid == rotationid)) -#if OLIGOKETIDES == 1 - || ((parameters->peptidetype == cyclicoligoketide) && (visiblerotationid == rotationid)) -#endif + || ((parameters->peptidetype == cyclicpolyketide) && (visiblerotationid == rotationid)) || ((parameters->peptidetype == branchcyclic) && (visiblerotationid == rotationid/6))) { for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { if ((nterminal && parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal) || (!nterminal && parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal) -#if OLIGOKETIDES == 1 - || (parameters->peptidetype == cyclicoligoketide) -#endif - ) { + || (parameters->peptidetype == cyclicpolyketide)) { m = 0; for (int j = fragmentstart; j < fragmentend; j++) { if ((branchstart == -1) || (branchend == -1) || ((branchstart >= 0) && (j < branchstart)) || ((branchend >= 0) && (j >= branchend))) { if (theoreticalspectrum->getVisualCoverage()[rotationid*parameters->fragmentionsfortheoreticalspectra.size() + i].series[j] > 0) { name = theoreticalspectrum->getVisualCoverage()[rotationid*parameters->fragmentionsfortheoreticalspectra.size() + i].name.substr(0, theoreticalspectrum->getVisualCoverage()[rotationid*parameters->fragmentionsfortheoreticalspectra.size() + i].name.rfind('_') + 1); -#if OLIGOKETIDES == 1 - if (parameters->peptidetype == cyclicoligoketide) { + if (parameters->peptidetype == cyclicpolyketide) { name += parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(0, 2) + to_string(j + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(2); } else { -#endif name += parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name[0] + to_string(j + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(1); -#if OLIGOKETIDES == 1 } -#endif cumulativeangle = angle*(double)((2*numberofringblocks - rotationstart + numberofringblocks - m - 1) % numberofringblocks) + angle/(double)2; if (cumulativeangle < pi/2) { QPoint p4(centerx + sin(cumulativeangle)*(radius - linesize) + sin(pi/2 - cumulativeangle)*cornerlinesize, centery - sin(pi/2 - cumulativeangle)*(radius - linesize) + sin(cumulativeangle)*cornerlinesize); @@ -410,6 +392,7 @@ void cCyclicWidget::paintEvent(QPaintEvent *event) { painter.begin(this); paint(painter); painter.end(); + event->accept(); } diff --git a/CycloBranch/gui/cDrawPeptideWidget.cpp b/CycloBranch/gui/cDrawPeptideWidget.cpp index 83d29b1..5050501 100644 --- a/CycloBranch/gui/cDrawPeptideWidget.cpp +++ b/CycloBranch/gui/cDrawPeptideWidget.cpp @@ -42,11 +42,8 @@ cDrawPeptideWidget::cDrawPeptideWidget(QWidget* parent) { peptidetypecombobox->addItem(tr("Cyclic")); peptidetypecombobox->addItem(tr("Branched")); peptidetypecombobox->addItem(tr("Branch-cyclic")); -#if OLIGOKETIDES == 1 - peptidetypecombobox->addItem(tr("Linear oligoketide")); - peptidetypecombobox->addItem(tr("Cyclic oligoketide")); -#endif - //peptidetypecombobox->addItem(tr("Linear polysaccharide (beta version)")); + peptidetypecombobox->addItem(tr("Linear polyketide")); + peptidetypecombobox->addItem(tr("Cyclic polyketide")); //peptidetypecombobox->addItem(tr("Other")); drawpeptideformlayout->addRow(tr("Peptide Type: "), peptidetypecombobox); @@ -154,7 +151,7 @@ cDrawPeptideWidget::cDrawPeptideWidget(QWidget* parent) { mainbox->addLayout(vbox); setLayout(mainbox); - resize(1280, 700); + resize(1280, 750); connect(sequenceline, SIGNAL(textEdited(const QString&)), this, SLOT(sequenceChanged())); connect(sequenceactioncopy, SIGNAL(triggered()), this, SLOT(sequenceCopy())); @@ -230,6 +227,7 @@ cDrawPeptideWidget::~cDrawPeptideWidget() { void cDrawPeptideWidget::closeEvent(QCloseEvent *event) { hide(); + event->accept(); } @@ -254,6 +252,8 @@ void cDrawPeptideWidget::keyPressEvent(QKeyEvent *event) { QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/drawpeptide.html").absoluteFilePath())); #endif } + + event->accept(); } @@ -290,16 +290,12 @@ void cDrawPeptideWidget::separateBlocksChanged(int state) { void cDrawPeptideWidget::numberOfBackboneBlocksChanged(int numberofblocks) { switch ((ePeptideType)peptidetypecombobox->currentIndex()) { case linear: -#if OLIGOKETIDES == 1 - case linearoligoketide: -#endif + case linearpolyketide: numberofblocksbackbone->setRange(1, 100); branchposition->setRange(1, 1); break; case cyclic: -#if OLIGOKETIDES == 1 - case cyclicoligoketide: -#endif + case cyclicpolyketide: numberofblocksbackbone->setRange(2, 100); branchposition->setRange(1, 1); break; @@ -311,8 +307,6 @@ void cDrawPeptideWidget::numberOfBackboneBlocksChanged(int numberofblocks) { numberofblocksbackbone->setRange(2, 100); branchposition->setRange(1, numberofblocks); break; - case linearpolysaccharide: - break; case other: break; default: @@ -371,16 +365,12 @@ void cDrawPeptideWidget::peptideTypeChanged(int index) { switch ((ePeptideType)index) { case linear: -#if OLIGOKETIDES == 1 - case linearoligoketide: -#endif + case linearpolyketide: linearwidget->show(); numberOfBackboneBlocksChanged(max(backboneblocks->count(), 1)); break; case cyclic: -#if OLIGOKETIDES == 1 - case cyclicoligoketide: -#endif + case cyclicpolyketide: cyclicwidget->show(); numberOfBackboneBlocksChanged(max(backboneblocks->count(), 2)); break; @@ -392,8 +382,6 @@ void cDrawPeptideWidget::peptideTypeChanged(int index) { branchcyclicwidget->show(); numberOfBackboneBlocksChanged(max(backboneblocks->count(), 2)); break; - case linearpolysaccharide: - break; case other: break; default: @@ -447,11 +435,8 @@ void cDrawPeptideWidget::blocksChanged() { ePeptideType peptidetype = (ePeptideType)peptidetypecombobox->currentIndex(); - if ((peptidetype == linear) || (peptidetype == linearpolysaccharide) || ((backbonecount > 1) && (peptidetype == cyclic)) -#if OLIGOKETIDES == 1 - || (peptidetype == linearoligoketide) || ((backbonecount > 1) && (peptidetype == cyclicoligoketide)) -#endif - ) { + if ((peptidetype == linear) || ((backbonecount > 1) && (peptidetype == cyclic)) + || (peptidetype == linearpolyketide) || ((backbonecount > 1) && (peptidetype == cyclicpolyketide))) { for (int i = 0; i < backbonecount; i++) { if (i > 0) { s += "-"; @@ -588,11 +573,8 @@ void cDrawPeptideWidget::sequenceChanged() { b.setComposition(theoreticalspectrum.getCandidate().getComposition(), false); b.explodeToIntComposition(intcomposition); - if ((peptidetype == linear) || (peptidetype == linearpolysaccharide) || (peptidetype == cyclic) -#if OLIGOKETIDES == 1 - || (peptidetype == linearoligoketide) || (peptidetype == cyclicoligoketide) -#endif - ) { + if ((peptidetype == linear) || (peptidetype == cyclic) + || (peptidetype == linearpolyketide) || (peptidetype == cyclicpolyketide)) { numberofblocksbackbone->setValue((int)v.size()); for (int i = 0; i < backboneblocks->count(); i++) { if (i < (int)v.size()) { @@ -651,32 +633,28 @@ void cDrawPeptideWidget::drawPeptide(vector& composition, cBricksDatabas switch ((ePeptideType)peptidetypecombobox->currentIndex()) { case linear: -#if OLIGOKETIDES == 1 - case linearoligoketide: -#endif - theoreticalspectrum.getCandidate().setCandidate(composition, netmp, 0, 0, 0, -1, -1); + case linearpolyketide: + theoreticalspectrum.getCandidate().setCandidate(composition, netmp, fragmentIonTypeEnd, 0, 0, 0, -1, -1); theoreticalspectrum.getCandidate().setAcronyms(bricksdb); linearwidget->initialize(0, &theoreticalspectrum); linearwidget->repaint(); break; case cyclic: -#if OLIGOKETIDES == 1 - case cyclicoligoketide: -#endif - theoreticalspectrum.getCandidate().setCandidate(composition, netmp, 0, 0, 0, -1, -1); + case cyclicpolyketide: + theoreticalspectrum.getCandidate().setCandidate(composition, netmp, fragmentIonTypeEnd, 0, 0, 0, -1, -1); theoreticalspectrum.getCandidate().setAcronyms(bricksdb); cyclicwidget->initialize(0, &theoreticalspectrum); cyclicwidget->repaint(); break; case branched: - theoreticalspectrum.getCandidate().setCandidate(composition, netmp, 0, 0, 0, branchstart, branchend); + theoreticalspectrum.getCandidate().setCandidate(composition, netmp, fragmentIonTypeEnd, 0, 0, 0, branchstart, branchend); theoreticalspectrum.getCandidate().setBackboneAcronyms(bricksdb); theoreticalspectrum.getCandidate().setBranchAcronyms(bricksdb); branchedwidget->initialize(0, &theoreticalspectrum); branchedwidget->repaint(); break; case branchcyclic: - theoreticalspectrum.getCandidate().setCandidate(composition, netmp, 0, 0, 0, branchstart, branchend); + theoreticalspectrum.getCandidate().setCandidate(composition, netmp, fragmentIonTypeEnd, 0, 0, 0, branchstart, branchend); // normalize the candidate theoreticalspectrum.getCandidate().getBranchCyclicRotations(branchcyclicrotations, false); @@ -686,7 +664,7 @@ void cDrawPeptideWidget::drawPeptide(vector& composition, cBricksDatabas vector v; v.push_back(branchcyclicrotations[i].getComposition()); vector cpath = theoreticalspectrum.getCandidate().getPath(); - theoreticalspectrum.getCandidate().setCandidate(v, cpath, theoreticalspectrum.getCandidate().getStartModifID(), theoreticalspectrum.getCandidate().getEndModifID(), theoreticalspectrum.getCandidate().getMiddleModifID(), branchcyclicrotations[i].getBranchStart(), branchcyclicrotations[i].getBranchEnd()); + theoreticalspectrum.getCandidate().setCandidate(v, cpath, theoreticalspectrum.getCandidate().getStartIonType(), theoreticalspectrum.getCandidate().getStartModifID(), theoreticalspectrum.getCandidate().getEndModifID(), theoreticalspectrum.getCandidate().getMiddleModifID(), branchcyclicrotations[i].getBranchStart(), branchcyclicrotations[i].getBranchEnd()); break; } } @@ -696,8 +674,6 @@ void cDrawPeptideWidget::drawPeptide(vector& composition, cBricksDatabas branchcyclicwidget->initialize(0, &theoreticalspectrum); branchcyclicwidget->repaint(); break; - case linearpolysaccharide: - break; case other: break; default: diff --git a/CycloBranch/gui/cGraphWidget.cpp b/CycloBranch/gui/cGraphWidget.cpp index dd409e2..54d30c4 100644 --- a/CycloBranch/gui/cGraphWidget.cpp +++ b/CycloBranch/gui/cGraphWidget.cpp @@ -25,7 +25,7 @@ cGraphWidget::cGraphWidget() { setLayout(layout); - resize(1280, 700); + resize(1280, 750); } @@ -49,6 +49,7 @@ string cGraphWidget::getHTML() { void cGraphWidget::closeEvent(QCloseEvent *event) { hide(); + event->accept(); } @@ -70,10 +71,12 @@ void cGraphWidget::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_F1) { #if OS_TYPE == WIN - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/menubar.html").absoluteFilePath())); + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/mainwindow.html").absoluteFilePath())); #else - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/menubar.html").absoluteFilePath())); + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/mainwindow.html").absoluteFilePath())); #endif } + + event->accept(); } diff --git a/CycloBranch/gui/cImageWindow.cpp b/CycloBranch/gui/cImageWindow.cpp index 00e0c11..8a79abd 100644 --- a/CycloBranch/gui/cImageWindow.cpp +++ b/CycloBranch/gui/cImageWindow.cpp @@ -7,6 +7,9 @@ #include #include #include +#include +#include +#include cImageWindow::cImageWindow(QWidget* parent) { @@ -15,65 +18,272 @@ cImageWindow::cImageWindow(QWidget* parent) { setWindowTitle("Image Window"); setWindowIcon(QIcon(":/images/icons/23.png")); - close = new QPushButton(tr("Close")); - close->setToolTip("Close the window."); + menuBar = new QMenuBar(this); + menuBar->setNativeMenuBar(false); + menuFile = new QMenu(tr("&File"), this); + menuZoom = new QMenu(tr("&Zoom"), this); + menuHelp = new QMenu(tr("&Help"), this); - loadimagebutton = new QPushButton(tr("Load Image")); - loadimagebutton->setToolTip("Load an image file."); - loadimagebutton->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); + xfromlabel = new QLabel("X: "); + + xfrom = new QSpinBox(); + xfrom->setRange(0, 100000); + xfrom->setSingleStep(1); + xfrom->setValue(0); + + xtolabel = new QLabel("-"); + + xto = new QSpinBox(); + xto->setRange(0, 100000); + xto->setSingleStep(1); + xto->setValue(0); + + yfromlabel = new QLabel("Y: "); + + yfrom = new QSpinBox(); + yfrom->setRange(0, 100000); + yfrom->setSingleStep(1); + yfrom->setValue(0); + + ytolabel = new QLabel("-"); + + yto = new QSpinBox(); + yto->setRange(0, 100000); + yto->setSingleStep(1); + yto->setValue(0); + + setregionbutton = new QPushButton(" Select Region "); + setregionbutton->setToolTip("Select a region."); + + resetregionbutton = new QPushButton(" Reset Region "); + resetregionbutton->setToolTip("Clear the selection and view all points."); + resetregionbutton->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_A)); + + regionhbox = new QHBoxLayout(); + regionhbox->addWidget(xfromlabel); + regionhbox->addWidget(xfrom); + regionhbox->addWidget(xtolabel); + regionhbox->addWidget(xto); + regionhbox->addWidget(yfromlabel); + regionhbox->addWidget(yfrom); + regionhbox->addWidget(ytolabel); + regionhbox->addWidget(yto); + regionhbox->addWidget(setregionbutton); + regionhbox->addWidget(resetregionbutton); + + regionwidget = new QWidget(); + regionwidget->setLayout(regionhbox); + regionwidget->setMaximumWidth(640); + + maxxlabel = new QLabel("Max X: "); + + maxx = new QSpinBox(); + maxx->setRange(1, 100000); + maxx->setSingleStep(1); + maxx->setValue(500); + + maxylabel = new QLabel("Max Y: "); + + maxy = new QSpinBox(); + maxy->setRange(1, 100000); + maxy->setSingleStep(1); + maxy->setValue(500); + + leftmarginlabel = new QLabel("Left Crop: "); + + leftmargin = new QSpinBox(); + leftmargin->setRange(0, 100000); + leftmargin->setSingleStep(1); + leftmargin->setValue(0); + + topmarginlabel = new QLabel("Top Crop: "); + + topmargin = new QSpinBox(); + topmargin->setRange(0, 100000); + topmargin->setSingleStep(1); + topmargin->setValue(0); + + setmaxbutton = new QPushButton("Set"); + setmaxbutton->setToolTip("Set up the minimum and maximum coordinates corresponding to the bottom-right corner of the image, set up the left margin and the top margin."); + + maxcoordinateshbox = new QHBoxLayout(); + maxcoordinateshbox->addWidget(maxxlabel); + maxcoordinateshbox->addWidget(maxx); + maxcoordinateshbox->addWidget(maxylabel); + maxcoordinateshbox->addWidget(maxy); + //maxcoordinateshbox->addWidget(leftmarginlabel); + //maxcoordinateshbox->addWidget(leftmargin); + //maxcoordinateshbox->addWidget(topmarginlabel); + //maxcoordinateshbox->addWidget(topmargin); + maxcoordinateshbox->addWidget(setmaxbutton); + + maxcoordinateswidget = new QWidget(); + maxcoordinateswidget->setLayout(maxcoordinateshbox); + maxcoordinateswidget->setMaximumWidth(640); image = new QImage(); imagewindowwidget = new cImageWindowWidget(); - buttons = new QHBoxLayout(); - buttons->addWidget(close); - buttons->addStretch(); - buttons->addWidget(loadimagebutton); - mainlayout = new QVBoxLayout(); mainlayout->addWidget(imagewindowwidget); - mainlayout->addLayout(buttons); - connect(close, SIGNAL(released()), this, SLOT(closeWindow())); - connect(loadimagebutton, SIGNAL(released()), this, SLOT(loadImage())); + mainwidget = new QWidget(); + mainwidget->setLayout(mainlayout); + + connect(setmaxbutton, SIGNAL(released()), this, SLOT(setMaxButtonReleased())); + connect(setregionbutton, SIGNAL(released()), this, SLOT(setRegionButtonReleased())); + connect(resetregionbutton, SIGNAL(released()), this, SLOT(resetSelection())); + + toolbarFile = addToolBar(tr("File")); + + actionOpenImage = new QAction(QIcon(":/images/icons/52.png"), tr("&Open Image"), this); + actionOpenImage->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_O)); + actionOpenImage->setToolTip("Open Image (Ctrl + O)"); + toolbarFile->addAction(actionOpenImage); + connect(actionOpenImage, SIGNAL(triggered()), this, SLOT(openImage())); + + actionSaveImage = new QAction(QIcon(":/images/icons/22.png"), tr("&Save Image"), this); + actionSaveImage->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); + actionSaveImage->setToolTip("Save Image (Ctrl + S)"); + toolbarFile->addAction(actionSaveImage); + connect(actionSaveImage, SIGNAL(triggered()), this, SLOT(saveImage())); + + actionCloseWindow = new QAction(QIcon(":/images/icons/33.png"), tr("&Close"), this); + actionCloseWindow->setShortcut(QKeySequence(Qt::Key_Escape)); + actionCloseWindow->setToolTip("Close (Esc)"); + toolbarFile->addAction(actionCloseWindow); + connect(actionCloseWindow, SIGNAL(triggered()), this, SLOT(closeWindow())); + + toolbarZoom = addToolBar(tr("Zoom")); + + actionZoomIn = new QAction(QIcon(":/images/icons/83.png"), tr("Zoom &In"), this); + actionZoomIn->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Plus)); + actionZoomIn->setToolTip("Zoom In (Ctrl +)"); + toolbarZoom->addAction(actionZoomIn); + connect(actionZoomIn, SIGNAL(triggered()), imagewindowwidget, SLOT(zoomIn())); + + actionZoomOut = new QAction(QIcon(":/images/icons/82.png"), tr("Zoom &Out"), this); + actionZoomOut->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Minus)); + actionZoomOut->setToolTip("Zoom Out (Ctrl -)"); + toolbarZoom->addAction(actionZoomOut); + connect(actionZoomOut, SIGNAL(triggered()), imagewindowwidget, SLOT(zoomOut())); + + actionZoomReset = new QAction(QIcon(":/images/icons/84.png"), tr("&Reset Zoom"), this); + actionZoomReset->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R)); + actionZoomReset->setToolTip("Zoom Reset (Ctrl + R)"); + toolbarZoom->addAction(actionZoomReset); + connect(actionZoomReset, SIGNAL(triggered()), imagewindowwidget, SLOT(normalSize())); + + toolbarRegion = addToolBar(tr("Select Region")); + toolbarRegion->addWidget(regionwidget); + + toolbarMaxCoordinates = addToolBar(tr("Coordinates")); + toolbarMaxCoordinates->addWidget(maxcoordinateswidget); + + toolbarHelp = addToolBar(tr("Help")); + + actionHTMLDocumentation = new QAction(QIcon(":/images/icons/3.png"), tr("&HTML Documentation"), this); + actionHTMLDocumentation->setShortcut(QKeySequence(Qt::Key_F1)); + actionHTMLDocumentation->setToolTip("Show HTML Documentation (F1)"); + toolbarHelp->addAction(actionHTMLDocumentation); + connect(actionHTMLDocumentation, SIGNAL(triggered()), this, SLOT(showHTMLDocumentation())); + + menuFile->addAction(actionOpenImage); + menuFile->addAction(actionSaveImage); + menuFile->addSeparator(); + menuFile->addAction(actionCloseWindow); + + menuZoom->addAction(actionZoomIn); + menuZoom->addAction(actionZoomOut); + menuZoom->addAction(actionZoomReset); + //menuZoom->addSeparator(); + //menuZoom->addAction(actionViewAllPoints); - setLayout(mainlayout); + menuHelp->addAction(actionHTMLDocumentation); - resize(1280, 700); + menuBar->addMenu(menuFile); + menuBar->addMenu(menuZoom); + menuBar->addMenu(menuHelp); + + setMenuBar(menuBar); + + setCentralWidget(mainwidget); + centralWidget()->setContentsMargins(0, 0, 0, 0); + + connect(imagewindowwidget, SIGNAL(updateFilter(int, int, int, int)), this, SLOT(updateSelection(int, int, int, int))); + connect(imagewindowwidget, SIGNAL(updateFilter(int, int, int, int)), this->parent, SLOT(updateSummaryPeaksTableFilter(int, int, int, int))); + connect(this, SIGNAL(updateSummaryPeaksTableFilter(int, int, int, int)), this->parent, SLOT(updateSummaryPeaksTableFilter(int, int, int, int))); + + resize(1280, 750); lastimagedir = "./"; } cImageWindow::~cImageWindow() { - delete close; - delete loadimagebutton; + delete xfromlabel; + delete xfrom; + delete xtolabel; + delete xto; + delete yfromlabel; + delete yfrom; + delete ytolabel; + delete yto; + delete setregionbutton; + delete resetregionbutton; + delete regionhbox; + delete regionwidget; + + delete maxxlabel; + delete maxx; + delete maxylabel; + delete maxy; + delete leftmarginlabel; + delete leftmargin; + delete topmarginlabel; + delete topmargin; + delete setmaxbutton; + delete maxcoordinateshbox; + delete maxcoordinateswidget; delete image; delete imagewindowwidget; - delete buttons; delete mainlayout; + delete mainwidget; + + delete actionOpenImage; + delete actionSaveImage; + delete actionCloseWindow; + delete actionZoomIn; + delete actionZoomOut; + delete actionZoomReset; + delete actionHTMLDocumentation; + + delete menuFile; + delete menuZoom; + delete menuHelp; + + delete menuBar; } void cImageWindow::closeEvent(QCloseEvent *event) { closeWindow(); + event->accept(); } void cImageWindow::keyPressEvent(QKeyEvent *event) { - if (event->key() == Qt::Key_Escape) { - closeWindow(); + if ((event->key() == Qt::Key_Enter) || (event->key() == Qt::Key_Return)) { + if (xfrom->hasFocus() || xto->hasFocus() || yfrom->hasFocus() || yto->hasFocus()) { + setregionbutton->click(); + } + if (maxx->hasFocus() || maxy->hasFocus()) { + setmaxbutton->click(); + } } - - if (event->key() == Qt::Key_F1) { - #if OS_TYPE == WIN - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/imagewindow.html").absoluteFilePath())); - #else - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/imagewindow.html").absoluteFilePath())); - #endif - } + event->accept(); } @@ -82,8 +292,8 @@ void cImageWindow::closeWindow() { } -void cImageWindow::loadImage() { - QString filename = QFileDialog::getOpenFileName(this, tr("Open Image File..."), lastimagedir, tr("Image Files (*.jpg *.jpeg *.png *.tif *.tiff *.bmp *.gif)")); +void cImageWindow::openImage() { + QString filename = QFileDialog::getOpenFileName(this, tr("Open Image ..."), lastimagedir, tr("Image Files (*.jpg *.jpeg *.png *.tif *.tiff *.bmp *.gif)")); if (!filename.isEmpty()) { lastimagedir = filename; @@ -93,3 +303,56 @@ void cImageWindow::loadImage() { } } + +void cImageWindow::saveImage() { + QString filename = QFileDialog::getSaveFileName(this, tr("Save Image ..."), "./", "PNG Files (*.png)"); + + if (!filename.isEmpty()) { + lastimagedir = filename; + imagewindowwidget->getImage().save(filename, "PNG"); + } +} + + +void cImageWindow::setCoordinates(vector coordinates) { + imagewindowwidget->setCoordinates(coordinates); +} + + +void cImageWindow::setMaxButtonReleased() { + imagewindowwidget->setMaxXY(maxx->value(), maxy->value(), leftmargin->value(), topmargin->value()); + resetregionbutton->click(); +} + + +void cImageWindow::setRegionButtonReleased() { + emit updateSummaryPeaksTableFilter(xfrom->value(), xto->value(), yfrom->value(), yto->value()); +} + + +void cImageWindow::showHTMLDocumentation() { + #if OS_TYPE == WIN + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/imagewindow.html").absoluteFilePath())); + #else + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/imagewindow.html").absoluteFilePath())); + #endif +} + + +void cImageWindow::updateSelection(int xmin, int xmax, int ymin, int ymax) { + xfrom->setValue(xmin); + xto->setValue(xmax); + yfrom->setValue(ymin); + yto->setValue(ymax); +} + + +void cImageWindow::resetSelection() { + xfrom->setValue(0); + yfrom->setValue(0); + xto->setValue(maxx->value()); + yto->setValue(maxy->value()); + + emit updateSummaryPeaksTableFilter(xfrom->value(), xto->value(), yfrom->value(), yto->value()); +} + diff --git a/CycloBranch/gui/cImageWindow.h b/CycloBranch/gui/cImageWindow.h index 75ce8f1..8d40fa6 100644 --- a/CycloBranch/gui/cImageWindow.h +++ b/CycloBranch/gui/cImageWindow.h @@ -7,8 +7,10 @@ #ifndef _CIMAGEWINDOW_H #define _CIMAGEWINDOW_H -#include +#include #include +#include +#include #include "core/utilities.h" #include "gui/cImageWindowWidget.h" @@ -18,12 +20,18 @@ class QHBoxLayout; class QVBoxLayout; class QPushButton; class QImage; +class QLabel; +class QSpinBox; +class QAction; +class QToolBar; +class QMenuBar; +class QMenu; /** \brief Image window. */ -class cImageWindow : public QWidget +class cImageWindow : public QMainWindow { Q_OBJECT @@ -53,13 +61,57 @@ class cImageWindow : public QWidget private: QWidget* parent; - QPushButton* close; - QPushButton* loadimagebutton; + + QMenuBar* menuBar; + QMenu* menuFile; + QMenu* menuZoom; + QMenu* menuHelp; + + QToolBar* toolbarFile; + QAction* actionOpenImage; + QAction* actionSaveImage; + QAction* actionCloseWindow; + + QToolBar* toolbarZoom; + QAction* actionZoomIn; + QAction* actionZoomOut; + QAction* actionZoomReset; + //QAction* actionViewAllPoints; + + QToolBar* toolbarRegion; + QWidget* regionwidget; + QHBoxLayout* regionhbox; + QLabel* xfromlabel; + QSpinBox* xfrom; + QLabel* xtolabel; + QSpinBox* xto; + QLabel* yfromlabel; + QSpinBox* yfrom; + QLabel* ytolabel; + QSpinBox* yto; + QPushButton* setregionbutton; + QPushButton* resetregionbutton; + + QToolBar* toolbarMaxCoordinates; + QWidget* maxcoordinateswidget; + QHBoxLayout* maxcoordinateshbox; + QLabel* maxxlabel; + QSpinBox* maxx; + QLabel* maxylabel; + QSpinBox* maxy; + QLabel* leftmarginlabel; + QSpinBox* leftmargin; + QLabel* topmarginlabel; + QSpinBox* topmargin; + QPushButton* setmaxbutton; + + QToolBar* toolbarHelp; + QAction* actionHTMLDocumentation; QImage* image; cImageWindowWidget* imagewindowwidget; - QHBoxLayout* buttons; QVBoxLayout* mainlayout; + QWidget* mainwidget; QString lastimagedir; @@ -79,7 +131,42 @@ private slots: void closeWindow(); - void loadImage(); + + void openImage(); + + + void saveImage(); + + + void setCoordinates(vector coordinates); + + + void setMaxButtonReleased(); + + + void setRegionButtonReleased(); + + + void showHTMLDocumentation(); + + + void updateSelection(int xmin, int xmax, int ymin, int ymax); + + + void resetSelection(); + + +signals: + + + /** + \brief The signal is emitted when the region selection was changed. + \param xmin minimum x coordinate + \param xmax maximum x coordinate + \param ymin minimum y coordinate + \param ymax maximum y coordinate + */ + void updateSummaryPeaksTableFilter(int xmin, int xmax, int ymin, int ymax); }; diff --git a/CycloBranch/gui/cImageWindowWidget.cpp b/CycloBranch/gui/cImageWindowWidget.cpp index e399c7e..c16f21e 100644 --- a/CycloBranch/gui/cImageWindowWidget.cpp +++ b/CycloBranch/gui/cImageWindowWidget.cpp @@ -1,30 +1,424 @@ #include "gui/cImageWindowWidget.h" +#include +#include +#include + cImageWindowWidget::cImageWindowWidget(QWidget* parent) { + setAlignment(Qt::AlignLeft | Qt::AlignTop); pixmap = new QPixmap(); + scene = new QGraphicsScene(this); + setScene(scene); + coordinates.clear(); + maxx = 0; + maxy = 0; + leftmargin = 0; + topmargin = 0; + currentscale = 1; + factor = 0.1; + ispixmapdefined = false; + ismaxxydefined = false; + enablemouseselection = true; + + pressedx = -1; + pressedy = -1; + currentx = 0; + currenty = 0; + currentwidth = 1; + currentheight = 1; + + selectiongroup = new QGraphicsItemGroup(); + selectionrect = new QGraphicsRectItem(); + selectiongroup->addToGroup(selectionrect); + selectionsimpletextitem = new QGraphicsSimpleTextItem(); + selectiongroup->addToGroup(selectionsimpletextitem); + selectiongroup->setZValue(1); + scene->addItem(selectiongroup); } cImageWindowWidget::~cImageWindowWidget() { delete pixmap; + delete scene; } void cImageWindowWidget::setPixmap(QImage* image) { *pixmap = QPixmap::fromImage(*image); + currentscale = 1; + ispixmapdefined = true; + redrawScene(); } -void cImageWindowWidget::paint(QPainter& painter) { - painter.drawPixmap(0, 0, *pixmap); -} - +QImage cImageWindowWidget::getImage() { + QImage image(sceneRect().size().toSize(), QImage::Format_ARGB32); + image.fill(Qt::white); -void cImageWindowWidget::paintEvent(QPaintEvent *event) { QPainter painter; - painter.begin(this); - paint(painter); + if (!painter.begin(&image)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + msgBox.setText(errstr); + msgBox.exec(); + return image; + } + + scene->render(&painter, sceneRect(), sceneRect(), Qt::KeepAspectRatio); painter.end(); + + return image; +} + + +void cImageWindowWidget::setCoordinates(vector& coordinates) { + this->coordinates = coordinates; + redrawScene(); +} + + +void cImageWindowWidget::setMaxXY(int maxx, int maxy, int leftmargin, int topmargin) { + if (leftmargin >= maxx) { + leftmargin = 0; + } + if (topmargin >= maxy) { + topmargin = 0; + } + this->maxx = maxx - leftmargin; + this->maxy = maxy - topmargin; + this->leftmargin = leftmargin; + this->topmargin = topmargin; + ismaxxydefined = true; + redrawScene(); +} + + +void cImageWindowWidget::wheelEvent(QWheelEvent *event) { + if (event->delta() > 0) { + zoomIn(); + } + else { + zoomOut(); + } + + event->accept(); +} + + +void cImageWindowWidget::mousePressEvent(QMouseEvent *event) { + QGraphicsView::mousePressEvent(event); + + if (enablemouseselection && ispixmapdefined && ismaxxydefined) { + if (event->button() == Qt::LeftButton) { + QPointF p = mapToScene(event->x(), event->y()); + pressedx = (int)p.x(); + pressedy = (int)p.y(); + + currentx = pressedx; + currenty = pressedy; + + updateSelectionGroup(); + } + + if (event->button() == Qt::RightButton) { + pressedx = -1; + pressedy = -1; + + redrawScene(); + } + + if (event->button() == Qt::MiddleButton) { + pressedx = -1; + pressedy = -1; + + normalSize(); + + redrawScene(); + } + } + + event->accept(); +} + + +void cImageWindowWidget::mouseMoveEvent(QMouseEvent *event) { + QGraphicsView::mouseMoveEvent(event); + + if (enablemouseselection && ispixmapdefined && ismaxxydefined) { + QPointF p = mapToScene(event->x(), event->y()); + currentx = (int)p.x(); + currenty = (int)p.y(); + + updateSelectionGroup(); + } + + event->accept(); +} + + +void cImageWindowWidget::mouseReleaseEvent(QMouseEvent *event) { + QGraphicsView::mouseReleaseEvent(event); + + if (enablemouseselection && ispixmapdefined && ismaxxydefined) { + if (pressedx == currentx) { + pressedx = -1; + + redrawScene(); + } + + if ((event->button() == Qt::LeftButton) && (pressedx != -1) && (pressedy != -1)) { + if (pressedx < 0) { + pressedx = 0; + } + + if (pressedx > currentwidth) { + pressedx = currentwidth; + } + + if (currentx < 0) { + currentx = 0; + } + + if (currentx > currentwidth) { + currentx = currentwidth; + } + + if (pressedy < 0) { + pressedy = 0; + } + + if (pressedy > currentheight) { + pressedy = currentheight; + } + + if (currenty < 0) { + currenty = 0; + } + + if (currenty > currentheight) { + currenty = currentheight; + } + + int xmin, xmax, ymin, ymax; + xmin = max(0, (currentx < pressedx?currentx:pressedx)*(maxx + 1)/max(1, currentwidth)); + xmax = min(maxx, (currentx < pressedx?pressedx:currentx)*(maxx + 1)/max(1, currentwidth)); + ymin = max(0, (currenty < pressedy?currenty:pressedy)*(maxy + 1)/max(1, currentheight)); + ymax = min(maxy, (currenty < pressedy?pressedy:currenty)*(maxy + 1)/max(1, currentheight)); + + pressedx = -1; + pressedy = -1; + + redrawScene(); + + emit updateFilter(xmin, xmax, ymin, ymax); + } + } + + event->accept(); +} + + +void cImageWindowWidget::redrawScene() { + int xmin, xmax, ymin, ymax; + xmin = 0; + ymin = 0; + xmax = maxx; + ymax = maxy; + + scene->removeItem(selectiongroup); + scene->clear(); + selectiongroup->setVisible(false); + scene->addItem(selectiongroup); + + + if (!ispixmapdefined && !ismaxxydefined) { + scene->addText("Please, open an image and set up the maximum X (Max X) and Y (Max Y) coordinates of the image bottom-right corner."); + return; + } + + if (!ispixmapdefined) { + scene->addText("The maximum X (Max X) and Y (Max Y) coordinates have been set up. Please, open an image."); + return; + } + + if (!ismaxxydefined) { + scene->addText("The image has been successfully opened. Please, set up the maximum X and Y coordinates of the image bottom-right corner."); + return; + } + + QRect rect(pixmap->width()*leftmargin/(leftmargin + maxx), pixmap->height()*topmargin/(topmargin + maxy), pixmap->width()*maxx, pixmap->height()*maxy); + QPixmap croppedpixmap = pixmap->copy(rect); + + QPixmap scaledpixmap = croppedpixmap.scaledToHeight(croppedpixmap.height()*currentscale); + currentwidth = scaledpixmap.width(); + currentheight = scaledpixmap.height(); + scene->addPixmap(scaledpixmap); + + unordered_set reduced_coordinates; + for (int i = 0; i < (int)coordinates.size(); i++) { + if (reduced_coordinates.count(coordinates[i]) == 1) { + auto it = reduced_coordinates.find(coordinates[i]); + cCoordinates coord = *it; + coord.mzratio = 0; + coord.intensity += coordinates[i].intensity; + coord.name += "\n" + coordinates[i].name; + reduced_coordinates.erase(it); + reduced_coordinates.insert(coord); + + } + else { + reduced_coordinates.insert(coordinates[i]); + } + } + + double maximumintensity = 0; + for (auto it = reduced_coordinates.begin(); it != reduced_coordinates.end(); ++it) { + if (it->intensity > maximumintensity) { + maximumintensity = it->intensity; + } + } + + if (maximumintensity > 0) { + + for (auto it = reduced_coordinates.begin(); it != reduced_coordinates.end(); ++it) { + + QGraphicsRectItem* rectitem = new QGraphicsRectItem((it->x * currentwidth) / (maxx + 1), (it->y * currentheight) / (maxy + 1), currentwidth / (maxx + 1), currentheight / (maxy + 1)); + rectitem->setPen(Qt::NoPen); + QColor color; + color.setHslF(1 - it->intensity/maximumintensity, 0.5, 0.5, 0.75); + rectitem->setBrush(QBrush(color)); + string tooltip; + if (it->mzratio == 0) { + tooltip = it->name + "\nID: " + to_string(it->id) + "\nX: " + to_string(it->x) + "\nY: " + to_string(it->y); + } + else { + tooltip = it->name + "\nID: " + to_string(it->id) + "\nX: " + to_string(it->x) + "\nY: " + to_string(it->y) + "\nm/z: " + to_string(it->mzratio) + "\nintensity: " + to_string(it->intensity) + "%"; + } + rectitem->setToolTip(tooltip.c_str()); + scene->addItem(rectitem); + + if (it == reduced_coordinates.begin()) { + xmin = it->x; + xmax = it->x; + ymin = it->y; + ymax = it->y; + } + else { + if (it->x < xmin) { + xmin = it->x; + } + if (it->x > xmax) { + xmax = it->x; + } + if (it->y < ymin) { + ymin = it->y; + } + if (it->y > ymax) { + ymax = it->y; + } + } + } + + QString qstr = "Minimum Bounding Region\nX: " + QString::number(xmin) + "-" + QString::number(xmax) + "; Y: " + QString::number(ymin) + "-" + QString::number(ymax); + QGraphicsTextItem* text = scene->addText(qstr); + text->setPos(2, currentheight + 2); + + } + + setSceneRect(0, 0, currentwidth, currentheight + 50); + + updateSelectionGroup(); +} + + +void cImageWindowWidget::updateSelectionGroup() { + qreal rx1, rx2, ry1, ry2; + QFont myFont("Arial", 8); + int xmin, xmax, ymin, ymax; + QString qstr; + + if ((pressedx != -1) && (pressedy != -1)) { + + if (currentx < pressedx) { + rx1 = currentx; + rx2 = pressedx; + } + else { + rx1 = pressedx; + rx2 = currentx; + } + + if (currenty < pressedy) { + ry1 = currenty; + ry2 = pressedy; + } + else { + ry1 = pressedy; + ry2 = currenty; + } + + selectionrect->setPen(QPen(Qt::green, 1, Qt::DashLine)); + selectionrect->setRect(QRectF(QPointF(rx1, ry1), QPointF(rx2, ry2))); + + xmin = max(0, (currentx < pressedx?currentx:pressedx)*(maxx + 1)/max(1, currentwidth)); + xmax = min(maxx, (currentx < pressedx?pressedx:currentx)*(maxx + 1)/max(1, currentwidth)); + ymin = max(0, (currenty < pressedy?currenty:pressedy)*(maxy + 1)/max(1, currentheight)); + ymax = min(maxy, (currenty < pressedy?pressedy:currenty)*(maxy + 1)/max(1, currentheight)); + + qstr = "X: " + QString::number(xmin) + "-" + QString::number(xmax) + "; Y: " + QString::number(ymin) + "-" + QString::number(ymax); + + selectionsimpletextitem->setFont(myFont); + selectionsimpletextitem->setText(qstr); + selectionsimpletextitem->setBrush(QBrush(Qt::green)); + selectionsimpletextitem->setPos(QPointF(pressedx + 2, pressedy)); + + selectiongroup->setVisible(true); + selectionrect->setVisible(true); + selectionsimpletextitem->setVisible(true); + + } + else { + + xmin = currentx*(maxx + 1)/max(1, currentwidth); + ymin = currenty*(maxy + 1)/max(1, currentheight); + + if ((currentx > 0) && (currenty > 0) && (xmin <= maxx) && (ymin <= maxy)) { + qstr = "X: " + QString::number(xmin) + " Y: " + QString::number(ymin); + + selectionsimpletextitem->setFont(myFont); + selectionsimpletextitem->setText(qstr); + selectionsimpletextitem->setBrush(QBrush(Qt::green)); + selectionsimpletextitem->setPos(QPointF(currentx, currenty - 10)); + + selectiongroup->setVisible(true); + selectionrect->setVisible(false); + selectionsimpletextitem->setVisible(true); + } + else { + selectiongroup->setVisible(false); + } + + } +} + + +void cImageWindowWidget::zoomIn() { + currentscale += factor; + redrawScene(); +} + + +void cImageWindowWidget::zoomOut() { + if (currentscale > 2*factor) { + currentscale -= factor; + } + redrawScene(); +} + + +void cImageWindowWidget::normalSize() { + currentscale = 1; + redrawScene(); } diff --git a/CycloBranch/gui/cImageWindowWidget.h b/CycloBranch/gui/cImageWindowWidget.h index d9b5064..7a5af5f 100644 --- a/CycloBranch/gui/cImageWindowWidget.h +++ b/CycloBranch/gui/cImageWindowWidget.h @@ -8,16 +8,17 @@ #define _CIMAGEWINDOWWIDGET_H #include -#include -#include +#include #include #include +#include +#include "core/utilities.h" /** \brief Image window widget. */ -class cImageWindowWidget : public QWidget +class cImageWindowWidget : public QGraphicsView { Q_OBJECT @@ -44,22 +45,118 @@ class cImageWindowWidget : public QWidget void setPixmap(QImage* image); -private: + /** + \brief Get the image. + \retval QImage image + */ + QImage getImage(); - QPixmap* pixmap; + + /** + \brief Set points. + \param coordinates a vector of coordinates + */ + void setCoordinates(vector& coordinates); - void paint(QPainter& painter); + /** + \brief Set the maximum X and Y coordinates. + \param maxx maximum X coordinate + \param maxy maximum Y coordinate + \param leftmargin left margin + \param topmargin top margin + */ + void setMaxXY(int maxx, int maxy, int leftmargin, int topmargin); protected: /** - \brief Handle the paint event. - \param event pointer to QPaintEvent + \brief Handle the mouse wheel event. + \param event pointer to QWheelEvent + */ + void wheelEvent(QWheelEvent *event); + + + /** + \brief Handle the mouse press event. + \param event pointer to QMouseEvent + */ + void mousePressEvent(QMouseEvent *event); + + + /** + \brief Handle the mouse move event. + \param event pointer to QMouseEvent + */ + void mouseMoveEvent(QMouseEvent *event); + + + /** + \brief Handle the mouse release event. + \param event pointer to QMouseEvent */ - void paintEvent(QPaintEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + + +signals: + + + /** + \brief The signal is emitted when the selection of points has changed. + \param xmin minimum x coordinate + \param xmax maximum x coordinate + \param ymin minimum y coordinate + \param ymax maximum y coordinate + */ + void updateFilter(int xmin, int xmax, int ymin, int ymax); + + +private: + + + QGraphicsScene* scene; + QPixmap* pixmap; + vector coordinates; + + int maxx; + int maxy; + int leftmargin; + int topmargin; + qreal currentscale; + qreal factor; + bool ispixmapdefined; + bool ismaxxydefined; + bool enablemouseselection; + + int pressedx; + int pressedy; + int currentx; + int currenty; + int currentwidth; + int currentheight; + + QGraphicsItemGroup* selectiongroup; + QGraphicsRectItem* selectionrect; + QGraphicsSimpleTextItem* selectionsimpletextitem; + + void redrawScene(); + + void updateSelectionGroup(); + + +private slots: + + + void zoomIn(); + + + void zoomOut(); + + + void normalSize(); + }; diff --git a/CycloBranch/gui/cLinearWidget.cpp b/CycloBranch/gui/cLinearWidget.cpp index ac723ae..94af14f 100644 --- a/CycloBranch/gui/cLinearWidget.cpp +++ b/CycloBranch/gui/cLinearWidget.cpp @@ -120,6 +120,7 @@ void cLinearWidget::paintEvent(QPaintEvent *event) { painter.begin(this); paint(painter); painter.end(); + event->accept(); } @@ -176,50 +177,32 @@ void cLinearWidget::paint(QPainter& painter) { int len = (int)theoreticalspectrum->getVisualCoverage()[0].series.size(); for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { -#if OLIGOKETIDES == 1 if (((parameters->peptidetype == linear) && (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal)) || - ((parameters->peptidetype == linearoligoketide) && ((parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l1h_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l2h_ion) - || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l1oh_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l2oh_ion)))) - { -#else - if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal) { -#endif + ((parameters->peptidetype == linearpolyketide) && ((parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l1h_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l2h_ion) + || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l1oh_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == l2oh_ion)))) { for (int j = 0; j < len; j++) { if (theoreticalspectrum->getVisualCoverage()[i].series[j] > 0) { -#if OLIGOKETIDES == 1 - if (parameters->peptidetype == linearoligoketide) { + if (parameters->peptidetype == linearpolyketide) { name = parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(0, 2) + to_string(j + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(2); } else { -#endif name = parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name[0] + to_string(j + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(1); -#if OLIGOKETIDES == 1 } -#endif insertLabel(labels, leftmargin + horizontalstep/4 + horizontalstep/8 + horizontalstep*j + horizontalstep/2, topmargin - 35, name, false); } } } -#if OLIGOKETIDES == 1 if (((parameters->peptidetype == linear) && (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal)) || - ((parameters->peptidetype == linearoligoketide) && ((parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r1h_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r2h_ion) - || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r1oh_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r2oh_ion)))) - { -#else - if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal) { -#endif + ((parameters->peptidetype == linearpolyketide) && ((parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r1h_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r2h_ion) + || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r1oh_ion) || (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].parent == r2oh_ion)))) { for (int j = len - 1; j >= 0; j--) { if (theoreticalspectrum->getVisualCoverage()[i].series[len - j - 1] > 0) { -#if OLIGOKETIDES == 1 - if (parameters->peptidetype == linearoligoketide) { + if (parameters->peptidetype == linearpolyketide) { name = parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(0, 2) + to_string(len - j) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(2); } else { -#endif name = parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name[0] + to_string(len - j) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(1); -#if OLIGOKETIDES == 1 } -#endif insertLabel(labels, leftmargin + horizontalstep*(j + 1), topmargin + 35, name, false); } } diff --git a/CycloBranch/gui/cMainThread.cpp b/CycloBranch/gui/cMainThread.cpp index c1011c9..ddc4f5b 100644 --- a/CycloBranch/gui/cMainThread.cpp +++ b/CycloBranch/gui/cMainThread.cpp @@ -7,17 +7,9 @@ bool cMainThread::checkModifications(cParameters& parameters, cSequence& sequenc middlemodifid = 0; errormessage = ""; - if ((sequence.getPeptideType() == linear) || (sequence.getPeptideType() == branched) || (sequence.getPeptideType() == branchcyclic) || (sequence.getPeptideType() == linearpolysaccharide) -#if OLIGOKETIDES == 1 - || (sequence.getPeptideType() == linearoligoketide) -#endif - ) { - - if ((sequence.getPeptideType() == linear) || (sequence.getPeptideType() == branched) || (sequence.getPeptideType() == linearpolysaccharide) -#if OLIGOKETIDES == 1 - || (sequence.getPeptideType() == linearoligoketide) -#endif - ) { + if ((sequence.getPeptideType() == linear) || (sequence.getPeptideType() == branched) || (sequence.getPeptideType() == branchcyclic) || (sequence.getPeptideType() == linearpolyketide)) { + + if ((sequence.getPeptideType() == linear) || (sequence.getPeptideType() == branched) || (sequence.getPeptideType() == linearpolyketide)) { startmodifid = -1; endmodifid = -1; } @@ -28,11 +20,7 @@ bool cMainThread::checkModifications(cParameters& parameters, cSequence& sequenc for (int i = 0; i < (int)parameters.searchedmodifications.size(); i++) { - if ((sequence.getPeptideType() == linear) || (sequence.getPeptideType() == branched) || (sequence.getPeptideType() == linearpolysaccharide) -#if OLIGOKETIDES == 1 - || (sequence.getPeptideType() == linearoligoketide) -#endif - ) { + if ((sequence.getPeptideType() == linear) || (sequence.getPeptideType() == branched) || (sequence.getPeptideType() == linearpolyketide)) { if (parameters.searchedmodifications[i].name.compare(sequence.getNTterminalModification()) == 0) { startmodifid = i; } @@ -248,7 +236,10 @@ void cMainThread::run() { parseBranch(parameters.peptidetype, parameters.searchedsequence, v, branchstart, branchend); // startmodifid, endmodifid and middlemodifid were filled up by checkModifications - c.setCandidate(v, netmp, startmodifid, endmodifid, middlemodifid, branchstart, branchend); + c.setCandidate(v, netmp, fragmentIonTypeEnd, startmodifid, endmodifid, middlemodifid, branchstart, branchend); + cSummaryFormula formula = c.calculateSummaryFormula(parameters, parameters.peptidetype, parameters.precursormass); + c.setSummaryFormula(formula); + candidates.getSet().insert(c); graphreaderisworking = false; @@ -268,7 +259,7 @@ void cMainThread::run() { emit setGraph(graph.printGraph()); - // blind paths are removed + // incomplete paths are removed // note: paths finishing in precursor minus X are removed, however, precursor peak is always present thus any candidate should not be lost if (parameters.blindedges == 1) { if (graph.removeEdgesFormingPathsNotStartingFromFirstNode(terminatecomputation) == -1) { @@ -282,7 +273,7 @@ void cMainThread::run() { } } - // blind paths are connected + // incomplete paths are connected if (parameters.blindedges == 2) { if (graph.connectEdgesFormingPathsNotStartingFromFirstNode(terminatecomputation) == -1) { emitEndSignals(); @@ -339,9 +330,10 @@ void cMainThread::run() { // database search - MS/MS mode if (parameters.mode == databasesearch) { - string composition; + string composition, formstr; vector v; cCandidate c; + cSummaryFormula formula; vector netmp; int startmodifid, endmodifid, middlemodifid, branchstart, branchend; @@ -382,14 +374,12 @@ void cMainThread::run() { parseBranch(parameters.sequencedatabase[i].getPeptideType(), composition, v, branchstart, branchend); // set candidate - c.setCandidate(v, netmp, startmodifid, endmodifid, middlemodifid, branchstart, branchend); + c.setCandidate(v, netmp, fragmentIonTypeEnd, startmodifid, endmodifid, middlemodifid, branchstart, branchend); -#if OLIGOKETIDES == 1 + if (!calculatesummaries && ((parameters.sequencedatabase[i].getPeptideType() == linearpolyketide) || (parameters.sequencedatabase[i].getPeptideType() == cyclicpolyketide))) { - if (!calculatesummaries && ((parameters.sequencedatabase[i].getPeptideType() == linearoligoketide) || (parameters.sequencedatabase[i].getPeptideType() == cyclicoligoketide))) { - - if (!c.checkKetideSequence(parameters.bricksdatabase, parameters.sequencedatabase[i].getPeptideType())) { - if (parameters.sequencedatabase[i].getPeptideType() == linearoligoketide) { + if (!c.checkKetideSequence(parameters.bricksdatabase, parameters.sequencedatabase[i].getPeptideType(), parameters.regularblocksorder)) { + if (parameters.sequencedatabase[i].getPeptideType() == linearpolyketide) { *os << "Ignored sequence: " << parameters.sequencedatabase[i].getName() << " " << parameters.sequencedatabase[i].getSequence() << "; the order of building blocks is not correct." << endl; } else { @@ -401,28 +391,47 @@ void cMainThread::run() { eResidueLossType leftresiduelosstype = c.getLeftResidueType(parameters.bricksdatabase); eResidueLossType rightresiduelosstype = c.getRightResidueType(parameters.bricksdatabase); - if (((leftresiduelosstype == h2_loss) && (c.getStartModifID() > 0) && parameters.searchedmodifications[c.getStartModifID()].cterminal) - || ((leftresiduelosstype == h2o_loss) && (c.getStartModifID() > 0) && parameters.searchedmodifications[c.getStartModifID()].nterminal) - || ((rightresiduelosstype == h2_loss) && (c.getEndModifID() > 0) && parameters.searchedmodifications[c.getEndModifID()].cterminal) - || ((rightresiduelosstype == h2o_loss) && (c.getEndModifID() > 0) && parameters.searchedmodifications[c.getEndModifID()].nterminal)) { - *os << "Ignored sequence: " << parameters.sequencedatabase[i].getName() << " " << parameters.sequencedatabase[i].getSequence() << "; the N-terminal modification is attached to C-terminus or vice versa." << endl; - continue; + if (parameters.peptidetype == linearpolyketide) { + if (((leftresiduelosstype == h2_loss) && (c.getStartModifID() > 0) && parameters.searchedmodifications[c.getStartModifID()].cterminal) + || ((rightresiduelosstype == h2_loss) && (c.getEndModifID() > 0) && parameters.searchedmodifications[c.getEndModifID()].cterminal)) { + *os << "Ignored sequence: " << parameters.sequencedatabase[i].getName() << " " << parameters.sequencedatabase[i].getSequence() << "; the C-terminal modification is attached to the N-terminus." << endl; + continue; + } + } + else { + if (((leftresiduelosstype == h2_loss) && (c.getStartModifID() > 0) && parameters.searchedmodifications[c.getStartModifID()].cterminal) + || ((leftresiduelosstype == h2o_loss) && (c.getStartModifID() > 0) && parameters.searchedmodifications[c.getStartModifID()].nterminal) + || ((rightresiduelosstype == h2_loss) && (c.getEndModifID() > 0) && parameters.searchedmodifications[c.getEndModifID()].cterminal) + || ((rightresiduelosstype == h2o_loss) && (c.getEndModifID() > 0) && parameters.searchedmodifications[c.getEndModifID()].nterminal)) { + *os << "Ignored sequence: " << parameters.sequencedatabase[i].getName() << " " << parameters.sequencedatabase[i].getSequence() << "; the N-terminal modification is attached to the C-terminus or vice versa." << endl; + continue; + } } } -#endif - // check the precursor mass error - if (!calculatesummaries && !parameters.similaritysearch && !isInPpmMassErrorTolerance(charge(uncharge(parameters.precursormass, parameters.precursorcharge), (parameters.precursorcharge > 0)?1:-1), c.getPrecursorMass(parameters.bricksdatabase, ¶meters), parameters.precursormasserrortolerance)) { + formula.setFormula(parameters.sequencedatabase[i].getSummaryFormula()); + formstr = "Hplus"; + formula.addFormula(formstr); + formstr = (parameters.precursorcharge > 0)?"":"Hplus-2"; + formula.addFormula(formstr); + formstr = parameters.precursoradduct.empty()?"":"H-1"; + formula.addFormula(formstr); + formstr = parameters.precursoradduct; + formula.addFormula(formstr); + if (!calculatesummaries && !parameters.similaritysearch && !isInPpmMassErrorTolerance(charge(uncharge(parameters.precursormass, parameters.precursorcharge), (parameters.precursorcharge > 0)?1:-1), formula.getMass(), parameters.precursormasserrortolerance)) { continue; } c.setName(parameters.sequencedatabase[i].getName()); + formstr = (parameters.precursorcharge > 0)?"Hplus-1":"Hplus"; + formula.addFormula(formstr); + c.setSummaryFormula(formula); candidates.getSet().insert(c); if (calculatesummaries) { - *os << i + 1 << " " << c.getSummaryFormula(parameters, parameters.sequencedatabase[i].getPeptideType()).getSummary() << endl; + *os << i + 1 << " " << c.calculateSummaryFormula(parameters, parameters.sequencedatabase[i].getPeptideType()).getSummary() << endl; } } diff --git a/CycloBranch/gui/cMainWindow.cpp b/CycloBranch/gui/cMainWindow.cpp index 6fb5f36..41ee519 100644 --- a/CycloBranch/gui/cMainWindow.cpp +++ b/CycloBranch/gui/cMainWindow.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -77,10 +76,10 @@ cMainWindow::cMainWindow() { actionDrawPeptide->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_P)); actionNorine = new QAction(QIcon(":/images/icons/25.png"), tr("&Norine"), this); - actionNorine->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N)); + actionNorine->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_1)); actionSmilesToMonomers = new QAction(QIcon(":/images/icons/5.png"), tr("Smiles2Monome&rs"), this); - actionSmilesToMonomers->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_T)); + actionSmilesToMonomers->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_2)); actionShowIsomers = new QAction(QIcon(":/images/icons/95.png"), tr("Show &Isomers"), this); @@ -178,9 +177,10 @@ cMainWindow::cMainWindow() { toolbarFilter = addToolBar(tr("Filter")); toolbarFilter->addWidget(rowsfilterwidget); + results = new QTableView(this); + resultsmodel = new QStandardItemModel(0, 0, this); + resultsproxymodel = new cMainWindowProxyModel(this); - // widgets - results = new QTableWidget(0, 0, this); logWindow = new QTextEdit(this); splitter = new QSplitter(this); @@ -228,6 +228,7 @@ cMainWindow::cMainWindow() { connect(rowsfilterclearbutton, SIGNAL(released()), this, SLOT(resetFilter())); connect(summarytableofmatchedpeaks, SIGNAL(tableCancelled()), this, SLOT(summaryPeaksTableCancelled())); + connect(summarytableofmatchedpeaks, SIGNAL(sendCoordinates(vector)), imagewindow, SLOT(setCoordinates(vector))); // add subitems to the items in main menu // menuFile->addAction(actionOpen); @@ -272,11 +273,16 @@ cMainWindow::cMainWindow() { // enable the menu setMenuBar(menuBar); + resultsproxymodel->setSourceModel(resultsmodel); + resultsproxymodel->setDynamicSortFilter(false); + results->setModel(resultsproxymodel); + results->setSelectionBehavior(QAbstractItemView::SelectItems); + results->setSelectionMode(QAbstractItemView::SingleSelection); results->setEditTriggers(QAbstractItemView::NoEditTriggers); results->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); results->horizontalHeader()->setSectionsMovable(true); - connect(results->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(headerItemDoubleClicked(int))); - connect(results, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(resultsCellClicked(int, int))); + results->setSortingEnabled(true); + connect(results, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(rowDoubleClicked(const QModelIndex&))); logWindow->setReadOnly(true); @@ -299,11 +305,11 @@ cMainWindow::cMainWindow() { setCentralWidget(splitter); // set the size of main window - resize(1280, 700); + resize(1280, 750); resultsbasecolumncount = 9; resultsspecificcolumncount = 0; - dbsearchspecificcolumncount = 0; + searchspecificcolumncount = 0; theoreticalspectrumlist.clear(); spectradetails.clear(); @@ -329,8 +335,11 @@ cMainWindow::~cMainWindow() { delete rowsfilterhbox; delete rowsfilterwidget; + delete resultsmodel; + delete resultsproxymodel; delete results; - delete logWindow; + + delete logWindow; delete splitter; delete about; @@ -382,8 +391,8 @@ void cMainWindow::keyPressEvent(QKeyEvent *event) { filterResults(); } else { - if ((results->currentRow() >= 0) && !results->isRowHidden(results->currentRow())) { - resultsCellClicked(results->currentRow(), 0); + if ((results->selectionModel()->selectedRows().count() > 0) && (results->selectionModel()->selectedRows()[0].row() >= 0) && resultsproxymodel->mapFromSource(results->selectionModel()->selectedRows()[0]).isValid()) { + rowDoubleClicked(results->selectionModel()->selectedRows()[0]); } } } @@ -392,9 +401,11 @@ void cMainWindow::keyPressEvent(QKeyEvent *event) { rowsfilterline->setFocus(); } - if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_N)) { + if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_T)) { rowsfiltercasesensitive->setChecked(!rowsfiltercasesensitive->isChecked()); } + + event->accept(); } @@ -405,7 +416,7 @@ void cMainWindow::closeEvent(QCloseEvent *event) { void cMainWindow::preparePeptideSequence(int row, string& peptidesequence, bool reportisomers) { - int spectrumindex = results->item(row, 1)->data(Qt::DisplayRole).toInt() - 1; + int spectrumindex = resultsmodel->item(row, 1)->data(Qt::DisplayRole).toInt() - 1; string tmpsequence; bool copy; @@ -432,99 +443,97 @@ void cMainWindow::preparePeptideSequence(int row, string& peptidesequence, bool } -void cMainWindow::reportSpectrum(int id, cTheoreticalSpectrum& theoreticalspectrum, bool reportisomers) { +void cMainWindow::reportSpectrum(int row, cTheoreticalSpectrum& theoreticalspectrum, bool reportisomers) { string peptidesequence; cSummaryFormula formula; - int row = results->rowCount(); - results->insertRow(row); - - results->setItem(row, 0, widgetitemallocator.getNewItem()); + resultsmodel->setItem(row, 0, new QStandardItem()); + resultsmodel->item(row, 0)->setText(""); - results->setItem(row, 1, widgetitemallocator.getNewItem()); - results->item(row, 1)->setData(Qt::DisplayRole, results->rowCount()); + resultsmodel->setItem(row, 1, new QStandardItem()); + resultsmodel->item(row, 1)->setData(QVariant::fromValue(row + 1), Qt::DisplayRole); if ((parameters.mode == denovoengine) || (parameters.mode == singlecomparison) || (parameters.mode == databasesearch)) { + if (parameters.mode == denovoengine) { + resultsmodel->setItem(row, 2, new QStandardItem()); + resultsmodel->item(row, 2)->setData(QVariant::fromValue(theoreticalspectrum.getPathId() + 1), Qt::DisplayRole); + } + if (parameters.mode == databasesearch) { - results->setItem(row, 2, widgetitemallocator.getNewItem()); - results->item(row, 2)->setText(theoreticalspectrum.getCandidate().getName().c_str()); + resultsmodel->setItem(row, 2, new QStandardItem()); + resultsmodel->item(row, 2)->setText(theoreticalspectrum.getCandidate().getName().c_str()); } - results->setItem(row, 2 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + resultsmodel->setItem(row, 2 + searchspecificcolumncount, new QStandardItem()); preparePeptideSequence(row, peptidesequence, reportisomers); - results->item(row, 2 + dbsearchspecificcolumncount)->setText(peptidesequence.c_str()); + resultsmodel->item(row, 2 + searchspecificcolumncount)->setText(peptidesequence.c_str()); - formula = theoreticalspectrum.getCandidate().getSummaryFormula(parameters, parameters.peptidetype); + formula = theoreticalspectrum.getCandidate().getSummaryFormula(); - results->setItem(row, 3 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 3 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, formula.isPartial()?string(formula.getSummary() + " (partial)").c_str():formula.getSummary().c_str()); + resultsmodel->setItem(row, 3 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->item(row, 3 + searchspecificcolumncount)->setText(formula.isPartial()?string(formula.getSummary() + " (partial)").c_str():formula.getSummary().c_str()); - results->setItem(row, 4 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 4 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(formula.getMass())); + resultsmodel->setItem(row, 4 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->item(row, 4 + searchspecificcolumncount)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(formula.getMass())), Qt::DisplayRole); - results->setItem(row, 5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 5 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, getNumberOfBricks(theoreticalspectrum.getCandidate().getComposition())); + resultsmodel->setItem(row, 5 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->item(row, 5 + searchspecificcolumncount)->setData(QVariant::fromValue(getNumberOfBricks(theoreticalspectrum.getCandidate().getComposition())), Qt::DisplayRole); switch (parameters.peptidetype) { case linear: -#if OLIGOKETIDES == 1 - case linearoligoketide: -#endif - case linearpolysaccharide: - results->setItem(row, 6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 6 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getStartModifID()].name.c_str()); - results->setItem(row, 7 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 7 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getEndModifID()].name.c_str()); + case linearpolyketide: + resultsmodel->setItem(row, 6 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->item(row, 6 + searchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getStartModifID()].name.c_str()); + resultsmodel->setItem(row, 7 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->item(row, 7 + searchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getEndModifID()].name.c_str()); break; case branched: - results->setItem(row, 6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 6 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getStartModifID()].name.c_str()); - results->setItem(row, 7 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 7 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getMiddleModifID()].name.c_str()); - results->setItem(row, 8 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 8 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getEndModifID()].name.c_str()); + resultsmodel->setItem(row, 6 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->item(row, 6 + searchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getStartModifID()].name.c_str()); + resultsmodel->setItem(row, 7 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->item(row, 7 + searchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getMiddleModifID()].name.c_str()); + resultsmodel->setItem(row, 8 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->item(row, 8 + searchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getEndModifID()].name.c_str()); break; case cyclic: -#if OLIGOKETIDES == 1 - case cyclicoligoketide: -#endif - results->setItem(row, 6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 6 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedBricks()); + case cyclicpolyketide: + resultsmodel->setItem(row, 6 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->item(row, 6 + searchspecificcolumncount)->setData(QVariant::fromValue(theoreticalspectrum.getNumberOfMatchedBricks()), Qt::DisplayRole); break; case branchcyclic: - results->setItem(row, 6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 6 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getMiddleModifID()].name.c_str()); + resultsmodel->setItem(row, 6 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->item(row, 6 + searchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getMiddleModifID()].name.c_str()); break; case other: default: break; } - results->setItem(row, 6 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 6 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedPeaks()); + resultsmodel->setItem(row, 6 + searchspecificcolumncount + resultsspecificcolumncount, new QStandardItem()); + resultsmodel->item(row, 6 + searchspecificcolumncount + resultsspecificcolumncount)->setData(QVariant::fromValue(theoreticalspectrum.getNumberOfMatchedPeaks()), Qt::DisplayRole); - results->setItem(row, 7 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 7 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(theoreticalspectrum.getRatioOfMatchedPeaks()*100)); + resultsmodel->setItem(row, 7 + searchspecificcolumncount + resultsspecificcolumncount, new QStandardItem()); + resultsmodel->item(row, 7 + searchspecificcolumncount + resultsspecificcolumncount)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(theoreticalspectrum.getRatioOfMatchedPeaks()*100)), Qt::DisplayRole); - results->setItem(row, 8 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 8 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(theoreticalspectrum.getWeightedIntensityScore())); + resultsmodel->setItem(row, 8 + searchspecificcolumncount + resultsspecificcolumncount, new QStandardItem()); + resultsmodel->item(row, 8 + searchspecificcolumncount + resultsspecificcolumncount)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(theoreticalspectrum.getWeightedIntensityScore())), Qt::DisplayRole); for (int i = 0; i < (int)parameters.fragmentionsfortheoreticalspectra.size(); i++) { - results->setItem(row, resultsbasecolumncount + dbsearchspecificcolumncount + resultsspecificcolumncount + i, widgetitemallocator.getNewItem()); - results->item(row, resultsbasecolumncount + dbsearchspecificcolumncount + resultsspecificcolumncount + i)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedPeaks(parameters.fragmentionsfortheoreticalspectra[i])); + resultsmodel->setItem(row, resultsbasecolumncount + searchspecificcolumncount + resultsspecificcolumncount + i, new QStandardItem()); + resultsmodel->item(row, resultsbasecolumncount + searchspecificcolumncount + resultsspecificcolumncount + i)->setData(QVariant::fromValue(theoreticalspectrum.getNumberOfMatchedPeaks(parameters.fragmentionsfortheoreticalspectra[i])), Qt::DisplayRole); } if ((parameters.peptidetype == cyclic) && parameters.enablescrambling) { - results->setItem(row, results->columnCount() - 1, widgetitemallocator.getNewItem()); - results->item(row, results->columnCount() - 1)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfScrambledPeaks()); + resultsmodel->setItem(row, resultsmodel->columnCount() - 1, new QStandardItem()); + resultsmodel->item(row, resultsmodel->columnCount() - 1)->setData(QVariant::fromValue(theoreticalspectrum.getNumberOfScrambledPeaks()), Qt::DisplayRole); } if (theoreticalspectrum.isValid()) { - results->item(row, 0)->setData(Qt::DisplayRole, "*"); - for (int i = 0; i < results->columnCount(); i++) { - results->item(row, i)->setBackground(Qt::yellow); + resultsmodel->item(row, 0)->setText("*"); + for (int i = 0; i < resultsmodel->columnCount(); i++) { + resultsmodel->item(row, i)->setBackground(Qt::yellow); } } @@ -532,31 +541,31 @@ void cMainWindow::reportSpectrum(int id, cTheoreticalSpectrum& theoreticalspectr if (parameters.mode == dereplication) { - results->setItem(row, 2, widgetitemallocator.getNewItem()); - results->item(row, 2)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedPeaks()); + resultsmodel->setItem(row, 2, new QStandardItem()); + resultsmodel->item(row, 2)->setData(QVariant::fromValue(theoreticalspectrum.getNumberOfMatchedPeaks()), Qt::DisplayRole); - results->setItem(row, 3, widgetitemallocator.getNewItem()); - results->item(row, 3)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(theoreticalspectrum.getRatioOfMatchedPeaks()*100)); + resultsmodel->setItem(row, 3, new QStandardItem()); + resultsmodel->item(row, 3)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(theoreticalspectrum.getRatioOfMatchedPeaks()*100)), Qt::DisplayRole); - results->setItem(row, 4, widgetitemallocator.getNewItem()); - results->item(row, 4)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(theoreticalspectrum.getWeightedIntensityScore())); + resultsmodel->setItem(row, 4, new QStandardItem()); + resultsmodel->item(row, 4)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(theoreticalspectrum.getWeightedIntensityScore())), Qt::DisplayRole); if ((parameters.peaklistfileformat == mis) || (parameters.peaklistfileformat == imzML)) { - results->setItem(row, 5, widgetitemallocator.getNewItem()); - results->item(row, 5)->setData(Qt::DisplayRole, theoreticalspectrum.getExperimentalSpectrum().getCoordinateX()); + resultsmodel->setItem(row, 5, new QStandardItem()); + resultsmodel->item(row, 5)->setData(QVariant::fromValue(theoreticalspectrum.getExperimentalSpectrum().getCoordinateX()), Qt::DisplayRole); - results->setItem(row, 6, widgetitemallocator.getNewItem()); - results->item(row, 6)->setData(Qt::DisplayRole, theoreticalspectrum.getExperimentalSpectrum().getCoordinateY()); + resultsmodel->setItem(row, 6, new QStandardItem()); + resultsmodel->item(row, 6)->setData(QVariant::fromValue(theoreticalspectrum.getExperimentalSpectrum().getCoordinateY()), Qt::DisplayRole); } } - spectradetails[id].initialize(¶meters, theoreticalspectrum, this); + spectradetails[row].initialize(¶meters, theoreticalspectrum, this); if (parameters.mode == dereplication) { - spectradetails[id].setWindowTitle(("Experimental Spectrum No. " + to_string(row+1)).c_str()); + spectradetails[row].setWindowTitle(("Experimental Spectrum No. " + to_string(row + 1)).c_str()); } else { - spectradetails[id].setWindowTitle(("Theoretical Spectrum No. " + to_string(row+1)).c_str()); + spectradetails[row].setWindowTitle(("Theoretical Spectrum No. " + to_string(row + 1)).c_str()); } } @@ -609,21 +618,27 @@ void cMainWindow::setAndShowDrawPeptideWidget(int peptidetypeindex, QString sequ } -void cMainWindow::showSummaryTableOfMatchedPeaks() { - summarytableofmatchedpeaks->show(); - summarytableofmatchedpeaks->activateWindow(); +void cMainWindow::prepareSummaryTableOfMatchedPeaks() { if (!summarytableisprepared) { summarytableisprepared = true; rowsfilterwidget->setEnabled(false); - summarytableofmatchedpeaks->prepareToShow(results, ¶meters, &theoreticalspectrumlist); + summarytableofmatchedpeaks->prepareToShow(resultsmodel, resultsproxymodel, ¶meters, &theoreticalspectrumlist); rowsfilterwidget->setEnabled(true); } } +void cMainWindow::showSummaryTableOfMatchedPeaks() { + summarytableofmatchedpeaks->show(); + summarytableofmatchedpeaks->activateWindow(); + prepareSummaryTableOfMatchedPeaks(); +} + + void cMainWindow::showImageWindow() { imagewindow->show(); imagewindow->activateWindow(); + prepareSummaryTableOfMatchedPeaks(); } @@ -646,6 +661,8 @@ void cMainWindow::run() { logWindow->clear(); + resetFilter(); + deleteResults(); theoreticalspectrumlist.clear(); @@ -658,8 +675,12 @@ void cMainWindow::run() { if (regex_search(localparameters.peaklistfilename, rx)) { string convertedimzml = localparameters.peaklistfilename.substr(0, (int)localparameters.peaklistfilename.size() - 6); string convertedibd = convertedimzml; - convertedimzml += "_converted.imzML"; - convertedibd += "_converted.ibd"; + convertedimzml += "_converted_fwhm_"; + convertedimzml += to_string(localparameters.fwhm); + convertedimzml += ".imzML"; + convertedibd += "_converted_fwhm_"; + convertedibd += to_string(localparameters.fwhm); + convertedibd += ".ibd"; if (QFile::exists(convertedimzml.c_str()) && QFile::exists(convertedibd.c_str())) { QMessageBox::StandardButton reply; @@ -685,9 +706,10 @@ void cMainWindow::run() { connect(thread, SIGNAL(setGraph(string)), this, SLOT(setGraph(string))); connect(this, SIGNAL(stopComputation()), thread, SLOT(stopComputation())); - summarytableofmatchedpeaks->deleteTable(true); + summarytableofmatchedpeaks->deleteTable(); summarytableofmatchedpeaks->hide(); summarytableisprepared = false; + imagewindow->hide(); thread->start(); } @@ -736,6 +758,12 @@ void cMainWindow::enableButtonsHandlingResults(bool enable) { if (parameters.mode == dereplication) { actionShowIsomers->setEnabled(false); + if ((parameters.peaklistfileformat == mis) || (parameters.peaklistfileformat == imzML)) { + actionImageWindow->setEnabled(enable); + } + else { + actionImageWindow->setEnabled(false); + } } else { actionShowIsomers->setEnabled(enable); @@ -757,19 +785,14 @@ void cMainWindow::reportSpectra() { switch (parameters.peptidetype) { case linear: -#if OLIGOKETIDES == 1 - case linearoligoketide: -#endif - case linearpolysaccharide: + case linearpolyketide: resultsspecificcolumncount = 2; break; case branched: resultsspecificcolumncount = 3; break; case cyclic: -#if OLIGOKETIDES == 1 - case cyclicoligoketide: -#endif + case cyclicpolyketide: resultsspecificcolumncount = 1; break; case branchcyclic: @@ -781,106 +804,130 @@ void cMainWindow::reportSpectra() { } - if (parameters.mode == databasesearch) { - dbsearchspecificcolumncount = 1; + if ((parameters.mode == denovoengine) || (parameters.mode == databasesearch)) { + searchspecificcolumncount = 1; } else { - dbsearchspecificcolumncount = 0; + searchspecificcolumncount = 0; } if ((parameters.mode == denovoengine) || (parameters.mode == singlecomparison) || (parameters.mode == databasesearch)) { - results->setColumnCount(resultsbasecolumncount + dbsearchspecificcolumncount + resultsspecificcolumncount + (int)parameters.fragmentionsfortheoreticalspectra.size()); + resultsmodel->setColumnCount(resultsbasecolumncount + searchspecificcolumncount + resultsspecificcolumncount + (int)parameters.fragmentionsfortheoreticalspectra.size()); if ((parameters.peptidetype == cyclic) && parameters.enablescrambling) { - results->setColumnCount(results->columnCount() + 1); + resultsmodel->setColumnCount(resultsmodel->columnCount() + 1); } - results->setHorizontalHeaderItem(0, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(0)->setText("*"); + resultsmodel->setHorizontalHeaderItem(0, new QStandardItem()); + resultsmodel->horizontalHeaderItem(0)->setText("*"); + results->setItemDelegateForColumn(0, new QItemDelegate()); - results->setHorizontalHeaderItem(1, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(1)->setText("Result ID"); + resultsmodel->setHorizontalHeaderItem(1, new QStandardItem()); + resultsmodel->horizontalHeaderItem(1)->setText("Result ID"); + results->setItemDelegateForColumn(1, new QItemDelegate()); + if (parameters.mode == denovoengine) { + resultsmodel->setHorizontalHeaderItem(2, new QStandardItem()); + resultsmodel->horizontalHeaderItem(2)->setText("Group ID"); + results->setItemDelegateForColumn(2, new QItemDelegate()); + } + if (parameters.mode == databasesearch) { - results->setHorizontalHeaderItem(2, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(2)->setText("Name"); + resultsmodel->setHorizontalHeaderItem(2, new QStandardItem()); + resultsmodel->horizontalHeaderItem(2)->setText("Name"); + results->setItemDelegateForColumn(2, new QItemDelegate()); } - results->setHorizontalHeaderItem(2 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(2 + dbsearchspecificcolumncount)->setText("Peptide Sequence"); + resultsmodel->setHorizontalHeaderItem(2 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(2 + searchspecificcolumncount)->setText("Peptide Sequence"); + results->setItemDelegateForColumn(2 + searchspecificcolumncount, new QItemDelegate()); - results->setHorizontalHeaderItem(3 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(3 + dbsearchspecificcolumncount)->setText("Summary Formula"); + resultsmodel->setHorizontalHeaderItem(3 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(3 + searchspecificcolumncount)->setText("Summary Formula"); + results->setItemDelegateForColumn(3 + searchspecificcolumncount, new QItemDelegate()); - results->setHorizontalHeaderItem(4 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(4 + dbsearchspecificcolumncount)->setText("Monoisotopic Mass"); - results->setItemDelegateForColumn(4 + dbsearchspecificcolumncount, &columndelegate); + resultsmodel->setHorizontalHeaderItem(4 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(4 + searchspecificcolumncount)->setText("Monoisotopic Mass"); + results->setItemDelegateForColumn(4 + searchspecificcolumncount, new QItemDelegate()); - results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(5 + dbsearchspecificcolumncount)->setText("Number of Bricks"); + resultsmodel->setHorizontalHeaderItem(5 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(5 + searchspecificcolumncount)->setText("Number of Bricks"); + results->setItemDelegateForColumn(5 + searchspecificcolumncount, new QItemDelegate()); switch (parameters.peptidetype) { case linear: - case linearpolysaccharide: - results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("N-terminal Modification"); - results->setHorizontalHeaderItem(7 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(7 + dbsearchspecificcolumncount)->setText("C-terminal Modification"); + resultsmodel->setHorizontalHeaderItem(6 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(6 + searchspecificcolumncount)->setText("N-terminal Modification"); + results->setItemDelegateForColumn(6 + searchspecificcolumncount, new QItemDelegate()); + + resultsmodel->setHorizontalHeaderItem(7 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(7 + searchspecificcolumncount)->setText("C-terminal Modification"); + results->setItemDelegateForColumn(7 + searchspecificcolumncount, new QItemDelegate()); break; case branched: - results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("N-terminal Modification"); - results->setHorizontalHeaderItem(7 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(7 + dbsearchspecificcolumncount)->setText("Branch Modification"); - results->setHorizontalHeaderItem(8 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(8 + dbsearchspecificcolumncount)->setText("C-terminal Modification"); + resultsmodel->setHorizontalHeaderItem(6 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(6 + searchspecificcolumncount)->setText("N-terminal Modification"); + results->setItemDelegateForColumn(6 + searchspecificcolumncount, new QItemDelegate()); + + resultsmodel->setHorizontalHeaderItem(7 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(7 + searchspecificcolumncount)->setText("Branch Modification"); + results->setItemDelegateForColumn(7 + searchspecificcolumncount, new QItemDelegate()); + + resultsmodel->setHorizontalHeaderItem(8 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(8 + searchspecificcolumncount)->setText("C-terminal Modification"); + results->setItemDelegateForColumn(8 + searchspecificcolumncount, new QItemDelegate()); break; case cyclic: -#if OLIGOKETIDES == 1 - case cyclicoligoketide: -#endif - results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("Matched Bricks"); + case cyclicpolyketide: + resultsmodel->setHorizontalHeaderItem(6 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(6 + searchspecificcolumncount)->setText("Matched Bricks"); + results->setItemDelegateForColumn(6 + searchspecificcolumncount, new QItemDelegate()); break; case branchcyclic: - results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("Branch Modification"); + resultsmodel->setHorizontalHeaderItem(6 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(6 + searchspecificcolumncount)->setText("Branch Modification"); + results->setItemDelegateForColumn(6 + searchspecificcolumncount, new QItemDelegate()); break; -#if OLIGOKETIDES == 1 - case linearoligoketide: - results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("Left Terminal Modification"); - results->setHorizontalHeaderItem(7 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(7 + dbsearchspecificcolumncount)->setText("Right Terminal Modification"); + case linearpolyketide: + resultsmodel->setHorizontalHeaderItem(6 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(6 + searchspecificcolumncount)->setText("Left Terminal Modification"); + results->setItemDelegateForColumn(6 + searchspecificcolumncount, new QItemDelegate()); + + resultsmodel->setHorizontalHeaderItem(7 + searchspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(7 + searchspecificcolumncount)->setText("Right Terminal Modification"); + results->setItemDelegateForColumn(7 + searchspecificcolumncount, new QItemDelegate()); + break; -#endif case other: default: break; } - results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(6 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setText("Matched Peaks"); + resultsmodel->setHorizontalHeaderItem(6 + searchspecificcolumncount + resultsspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(6 + searchspecificcolumncount + resultsspecificcolumncount)->setText("Matched Peaks"); + results->setItemDelegateForColumn(6 + searchspecificcolumncount + resultsspecificcolumncount, new QItemDelegate()); - results->setHorizontalHeaderItem(7 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(7 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setText("Ratio of Matched Peaks [%]"); - results->setItemDelegateForColumn(7 + dbsearchspecificcolumncount + resultsspecificcolumncount, &columndelegate); + resultsmodel->setHorizontalHeaderItem(7 + searchspecificcolumncount + resultsspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(7 + searchspecificcolumncount + resultsspecificcolumncount)->setText("Ratio of Matched Peaks [%]"); + results->setItemDelegateForColumn(7 + searchspecificcolumncount + resultsspecificcolumncount, new QItemDelegate()); - results->setHorizontalHeaderItem(8 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(8 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setText("Sum of Relative Intensities"); - results->setItemDelegateForColumn(8 + dbsearchspecificcolumncount + resultsspecificcolumncount, &columndelegate); + resultsmodel->setHorizontalHeaderItem(8 + searchspecificcolumncount + resultsspecificcolumncount, new QStandardItem()); + resultsmodel->horizontalHeaderItem(8 + searchspecificcolumncount + resultsspecificcolumncount)->setText("Sum of Relative Intensities"); + results->setItemDelegateForColumn(8 + searchspecificcolumncount + resultsspecificcolumncount, new QItemDelegate()); for (int i = 0; i < (int)parameters.fragmentionsfortheoreticalspectra.size(); i++) { - results->setHorizontalHeaderItem(resultsbasecolumncount + dbsearchspecificcolumncount + resultsspecificcolumncount + i, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(resultsbasecolumncount + dbsearchspecificcolumncount + resultsspecificcolumncount + i)->setText(parameters.fragmentdefinitions[(eFragmentIonType)parameters.fragmentionsfortheoreticalspectra[i]].name.c_str()); + resultsmodel->setHorizontalHeaderItem(resultsbasecolumncount + searchspecificcolumncount + resultsspecificcolumncount + i, new QStandardItem()); + resultsmodel->horizontalHeaderItem(resultsbasecolumncount + searchspecificcolumncount + resultsspecificcolumncount + i)->setText(parameters.fragmentdefinitions[(eFragmentIonType)parameters.fragmentionsfortheoreticalspectra[i]].name.c_str()); + results->setItemDelegateForColumn(resultsbasecolumncount + searchspecificcolumncount + resultsspecificcolumncount + i, new QItemDelegate()); } if ((parameters.peptidetype == cyclic) && parameters.enablescrambling) { - results->setHorizontalHeaderItem(results->columnCount() - 1, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(results->columnCount() - 1)->setText("Scrambled Peaks"); + resultsmodel->setHorizontalHeaderItem(resultsmodel->columnCount() - 1, new QStandardItem()); + resultsmodel->horizontalHeaderItem(resultsmodel->columnCount() - 1)->setText("Scrambled Peaks"); + results->setItemDelegateForColumn(resultsmodel->columnCount() - 1, new QItemDelegate()); } } @@ -888,46 +935,46 @@ void cMainWindow::reportSpectra() { if (parameters.mode == dereplication) { if ((parameters.peaklistfileformat == mis) || (parameters.peaklistfileformat == imzML)) { - results->setColumnCount(7); + resultsmodel->setColumnCount(7); } else { - results->setColumnCount(5); + resultsmodel->setColumnCount(5); } - results->setHorizontalHeaderItem(0, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(0)->setText("*"); + resultsmodel->setHorizontalHeaderItem(0, new QStandardItem()); + resultsmodel->horizontalHeaderItem(0)->setText("*"); + results->setItemDelegateForColumn(0, new QItemDelegate()); - results->setHorizontalHeaderItem(1, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(1)->setText("Spectrum ID"); + resultsmodel->setHorizontalHeaderItem(1, new QStandardItem()); + resultsmodel->horizontalHeaderItem(1)->setText("Spectrum ID"); + results->setItemDelegateForColumn(1, new QItemDelegate()); - results->setHorizontalHeaderItem(2, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(2)->setText("Matched Peaks"); + resultsmodel->setHorizontalHeaderItem(2, new QStandardItem()); + resultsmodel->horizontalHeaderItem(2)->setText("Matched Peaks"); + results->setItemDelegateForColumn(2, new QItemDelegate()); - results->setHorizontalHeaderItem(3, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(3)->setText("Ratio of Matched Peaks [%]"); - results->setItemDelegateForColumn(3, &columndelegate); + resultsmodel->setHorizontalHeaderItem(3, new QStandardItem()); + resultsmodel->horizontalHeaderItem(3)->setText("Ratio of Matched Peaks [%]"); + results->setItemDelegateForColumn(3, new QItemDelegate()); - results->setHorizontalHeaderItem(4, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(4)->setText("Sum of Relative Intensities"); - results->setItemDelegateForColumn(4, &columndelegate); + resultsmodel->setHorizontalHeaderItem(4, new QStandardItem()); + resultsmodel->horizontalHeaderItem(4)->setText("Sum of Relative Intensities"); + results->setItemDelegateForColumn(4, new QItemDelegate()); if ((parameters.peaklistfileformat == mis) || (parameters.peaklistfileformat == imzML)) { - results->setHorizontalHeaderItem(5, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(5)->setText("Coordinate X"); + resultsmodel->setHorizontalHeaderItem(5, new QStandardItem()); + resultsmodel->horizontalHeaderItem(5)->setText("Coordinate X"); + results->setItemDelegateForColumn(5, new QItemDelegate()); - results->setHorizontalHeaderItem(6, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(6)->setText("Coordinate Y"); + resultsmodel->setHorizontalHeaderItem(6, new QStandardItem()); + resultsmodel->horizontalHeaderItem(6)->setText("Coordinate Y"); + results->setItemDelegateForColumn(6, new QItemDelegate()); } } results->resizeColumnsToContents(); - resultsheadersort.resize(results->columnCount()); - for (int i = 0; i < results->columnCount(); i++) { - resultsheadersort[i] = -1; - } - QProgressDialog progress("Preparing the report...", /*"Cancel"*/0, 0, theoreticalspectrumlist.size(), this); progress.setMinimumWidth(250); cEventFilter filter; @@ -935,8 +982,13 @@ void cMainWindow::reportSpectra() { progress.setMinimumDuration(0); progress.setWindowModality(Qt::WindowModal); + results->setModel(0); + resultsproxymodel->setSourceModel(0); + results->setSortingEnabled(false); + spectradetails.clear(); spectradetails.resize(theoreticalspectrumlist.size()); + resultsmodel->setRowCount(theoreticalspectrumlist.size()); bool reportisomers = actionShowIsomers->isChecked(); for (int i = 0; i < theoreticalspectrumlist.size(); i++) { reportSpectrum(i, theoreticalspectrumlist[i], reportisomers); @@ -946,7 +998,12 @@ void cMainWindow::reportSpectra() { //} } - for (int i = 0; i < results->columnCount(); i++) { + resultsproxymodel->setSourceModel(resultsmodel); + results->setModel(resultsproxymodel); + resultsproxymodel->setSortRole(Qt::InitialSortOrderRole); + results->setSortingEnabled(true); + + for (int i = 0; i < resultsmodel->columnCount(); i++) { results->resizeColumnToContents(i); } @@ -969,14 +1026,14 @@ void cMainWindow::updateSpectra() { progress.setMinimumDuration(0); progress.setWindowModality(Qt::WindowModal); - for (int i = 0; i < results->rowCount(); i++) { + for (int i = 0; i < resultsmodel->rowCount(); i++) { preparePeptideSequence(i, peptidesequence, reportisomers); - results->item(i, 2 + dbsearchspecificcolumncount)->setText(peptidesequence.c_str()); + resultsmodel->item(i, 2 + searchspecificcolumncount)->setText(peptidesequence.c_str()); progress.setValue(i); } - for (int i = 0; i < results->columnCount(); i++) { + for (int i = 0; i < resultsmodel->columnCount(); i++) { results->resizeColumnToContents(i); } @@ -988,16 +1045,22 @@ void cMainWindow::updateSpectra() { void cMainWindow::deleteResults() { - widgetitemallocator.reset(); - results->setColumnCount(0); - results->setRowCount(0); + for (int i = 0; i < resultsmodel->columnCount(); i++) { + if (results->itemDelegateForColumn(i)) { + delete results->itemDelegateForColumn(i); + } + } + resultsmodel->clear(); + resultsmodel->setColumnCount(0); + resultsmodel->setRowCount(0); } -void cMainWindow::resultsCellClicked(int row, int column) { - spectradetails[results->item(row, 1)->data(Qt::DisplayRole).toInt() - 1].prepareToShow(parameters.peptidetype); - spectradetails[results->item(row, 1)->data(Qt::DisplayRole).toInt() - 1].show(); - spectradetails[results->item(row, 1)->data(Qt::DisplayRole).toInt() - 1].activateWindow(); +void cMainWindow::rowDoubleClicked(const QModelIndex& item) { + int row = resultsproxymodel->mapToSource(item).row(); + spectradetails[resultsmodel->item(row, 1)->data(Qt::DisplayRole).toInt() - 1].prepareToShow(parameters.peptidetype); + spectradetails[resultsmodel->item(row, 1)->data(Qt::DisplayRole).toInt() - 1].show(); + spectradetails[resultsmodel->item(row, 1)->data(Qt::DisplayRole).toInt() - 1].activateWindow(); } @@ -1006,31 +1069,13 @@ void cMainWindow::setGraph(string s) { } -void cMainWindow::headerItemDoubleClicked(int index) { - if (resultsheadersort[index] == -1) { - results->sortByColumn(index, Qt::DescendingOrder); - resultsheadersort[index] = 0; - return; - } - - if (resultsheadersort[index] == 0) { - results->sortByColumn(index, Qt::AscendingOrder); - resultsheadersort[index] = 1; - } - else { - results->sortByColumn(index, Qt::DescendingOrder); - resultsheadersort[index] = 0; - } -} - - void cMainWindow::exportToCsv() { QString filename = QFileDialog::getSaveFileName(this, tr("Export to CSV"), lastdirexporttocsv, tr("Files (*.csv)")); if (!filename.isEmpty()) { lastdirexporttocsv = filename; - QProgressDialog progress("Exporting CSV file...", "Cancel", 0, results->rowCount(), this); + QProgressDialog progress("Exporting CSV file...", "Cancel", 0, resultsproxymodel->rowCount(), this); progress.setMinimumWidth(250); cEventFilter filter; progress.installEventFilter(&filter); @@ -1045,23 +1090,21 @@ void cMainWindow::exportToCsv() { QTextStream out(&file); - for (int i = 0; i < results->columnCount(); i++) { - out << "\"" << results->horizontalHeaderItem(i)->text() << "\""; - if (i < results->columnCount() - 1) { + for (int i = 0; i < resultsmodel->columnCount(); i++) { + out << "\"" << resultsmodel->horizontalHeaderItem(i)->text() << "\""; + if (i < resultsmodel->columnCount() - 1) { out << ","; } } out << endl; - for (int i = 0; i < results->rowCount(); i++) { - - if (results->isRowHidden(i)) { - continue; - } + QStandardItem* item; + for (int i = 0; i < resultsproxymodel->rowCount(); i++) { - for (int j = 0; j < results->columnCount(); j++) { - out << "\"" << results->item(i, j)->data(Qt::DisplayRole).toString() << "\""; - if (j < results->columnCount() - 1) { + for (int j = 0; j < resultsmodel->columnCount(); j++) { + item = resultsmodel->itemFromIndex(resultsproxymodel->mapToSource(resultsproxymodel->index(i, j))); + out << "\"" << item->data(Qt::DisplayRole).toString() << "\""; + if (j < resultsmodel->columnCount() - 1) { out << ","; } } @@ -1080,7 +1123,7 @@ void cMainWindow::exportToCsv() { file.remove(); } - progress.setValue(results->rowCount()); + progress.setValue(resultsproxymodel->rowCount()); } } @@ -1096,7 +1139,7 @@ void cMainWindow::exportToHTML() { if (!filename.isEmpty()) { lastdirexporttohtml = filename; - QProgressDialog progress("Exporting HTML report...", "Cancel", 0, results->rowCount(), this); + QProgressDialog progress("Exporting HTML report...", "Cancel", 0, resultsproxymodel->rowCount(), this); progress.setMinimumWidth(250); cEventFilter filter; progress.installEventFilter(&filter); @@ -1111,9 +1154,10 @@ void cMainWindow::exportToHTML() { QTextStream out(&file); - if (results->rowCount() > 0) { + if (resultsmodel->rowCount() > 0) { bool matchedrow; + QStandardItem* item; string title = appname.toStdString() + " " + appversion.toStdString() + " - Output Report"; out << "\n"; @@ -1152,30 +1196,27 @@ void cMainWindow::exportToHTML() { out << "

Output Report Table

\n"; out << "

\n\n"; - for (int i = 0; i < results->columnCount(); i++) { - out << "\n"; + for (int i = 0; i < resultsmodel->columnCount(); i++) { + out << "\n"; } out << "\n"; - for (int i = 0; i < results->rowCount(); i++) { - - if (results->isRowHidden(i)) { - continue; - } + for (int i = 0; i < resultsproxymodel->rowCount(); i++) { out << "\n"; matchedrow = false; - if (results->item(i, 0)->data(Qt::DisplayRole).toString().compare("*") == 0) { + if (resultsmodel->itemFromIndex(resultsproxymodel->mapToSource(resultsproxymodel->index(i, 0)))->data(Qt::DisplayRole).toString().compare("*") == 0) { matchedrow = true; } - for (int j = 0; j < results->columnCount(); j++) { + for (int j = 0; j < resultsmodel->columnCount(); j++) { + item = resultsmodel->itemFromIndex(resultsproxymodel->mapToSource(resultsproxymodel->index(i, j))); out << "" << results->item(i, j)->data(Qt::DisplayRole).toString() << "\n"; + out << ">" << item->data(Qt::DisplayRole).toString() << "\n"; } out << "\n"; @@ -1200,6 +1241,9 @@ void cMainWindow::exportToHTML() { columncount = 9; } } + else if (parameters.mode == denovoengine) { + columncount = 8; + } else { columncount = 7; } @@ -1215,7 +1259,12 @@ void cMainWindow::exportToHTML() { } out << ""; } - else { + + if (parameters.mode == denovoengine) { + out << ""; + } + + if (parameters.mode != dereplication) { out << ""; } @@ -1236,13 +1285,9 @@ void cMainWindow::exportToHTML() { out << ""; int spectrumindex; - for (int i = 0; i < results->rowCount(); i++) { + for (int i = 0; i < resultsproxymodel->rowCount(); i++) { - if (results->isRowHidden(i)) { - continue; - } - - spectrumindex = results->item(i, 1)->data(Qt::DisplayRole).toInt() - 1; + spectrumindex = resultsmodel->itemFromIndex(resultsproxymodel->mapToSource(resultsproxymodel->index(i, 1)))->data(Qt::DisplayRole).toInt() - 1; if (spectradetails[spectrumindex].getTheoreticalSpectrum().getNumberOfMatchedPeaks() == 0) { continue; @@ -1261,13 +1306,9 @@ void cMainWindow::exportToHTML() { out << "

Individual Rows in Output Report Table

\n"; int spectrumindex; - for (int i = 0; i < results->rowCount(); i++) { - - if (results->isRowHidden(i)) { - continue; - } + for (int i = 0; i < resultsproxymodel->rowCount(); i++) { - spectrumindex = results->item(i, 1)->data(Qt::DisplayRole).toInt() - 1; + spectrumindex = resultsmodel->itemFromIndex(resultsproxymodel->mapToSource(resultsproxymodel->index(i, 1)))->data(Qt::DisplayRole).toInt() - 1; if ((spectradetails[spectrumindex].getTheoreticalSpectrum().getNumberOfMatchedPeaks() == 0) && !htmlexportdialog->checkboxunmatchedtheoretical->isChecked() && !htmlexportdialog->checkboxunmatchedexperimental->isChecked()) { continue; @@ -1314,7 +1355,7 @@ void cMainWindow::exportToHTML() { file.remove(); } - progress.setValue(results->rowCount()); + progress.setValue(resultsproxymodel->rowCount()); } @@ -1438,9 +1479,9 @@ void cMainWindow::openResultsFile() { QString appinfo = appname + " " + appversion; if (appinfo.toStdString().compare(s) != 0) { QMessageBox msgBox; - QString errstr = "The results file cannot be read because it was created by different version "; + QString errstr = "The results file cannot be opened because it was created in the different version of " + appname + " ("; errstr += s.c_str(); - errstr += "."; + errstr += ")."; msgBox.setText(errstr); msgBox.exec(); @@ -1450,7 +1491,7 @@ void cMainWindow::openResultsFile() { deleteResults(); - summarytableofmatchedpeaks->deleteTable(true); + summarytableofmatchedpeaks->deleteTable(); summarytableofmatchedpeaks->hide(); summarytableisprepared = false; @@ -1474,6 +1515,12 @@ void cMainWindow::openResultsFile() { if (parameters.mode == dereplication) { actionShowIsomers->setEnabled(false); + if ((parameters.peaklistfileformat == mis) || (parameters.peaklistfileformat == imzML)) { + actionImageWindow->setEnabled(true); + } + else { + actionImageWindow->setEnabled(false); + } } else { actionShowIsomers->setEnabled(true); @@ -1522,7 +1569,7 @@ void cMainWindow::setTag(int peptidetypeindex, QString tag) { void cMainWindow::insertSequence(int peptidetypeindex, QString sequence) { showSequenceDatabase(); - sequencedatabasewidget->insertRow(peptidetypeindex, sequence); + sequencedatabasewidget->importSequence(peptidetypeindex, sequence); } @@ -1544,66 +1591,28 @@ void cMainWindow::quitApplication() { void cMainWindow::filterResults() { - summarytableofmatchedpeaks->deleteTable(true); + summarytableofmatchedpeaks->deleteTable(); summarytableofmatchedpeaks->hide(); summarytableisprepared = false; - Qt::CaseSensitivity casesensitive = rowsfiltercasesensitive->isChecked()?Qt::CaseSensitive:Qt::CaseInsensitive; - QString str = rowsfilterline->text(); - int rowcount = results->rowCount(); - bool match; - int i, j; - - QProgressDialog progress("Updating the report...", "Cancel", 0, rowcount, this); - progress.setMinimumWidth(250); - cEventFilter filter; - progress.installEventFilter(&filter); - progress.setMinimumDuration(0); - progress.setWindowModality(Qt::WindowModal); - - for (i = 0; i < rowcount; i++) { - match = false; - for (j = 0; j < results->columnCount(); j++) { - if (results->item(i, j)->text().contains(str, casesensitive)) { - match = true; - break; - } - } - results->setRowHidden(i, !match); - progress.setValue(i); - - if (progress.wasCanceled()) { - resetFilter(); - break; - } - - } - - progress.setValue(rowcount); + resultsproxymodel->setFilterKeyColumn(-1); + resultsproxymodel->setFilterCaseSensitivity(rowsfiltercasesensitive->isChecked()?Qt::CaseSensitive:Qt::CaseInsensitive); + resultsproxymodel->setFilterFixedString(rowsfilterline->text()); } void cMainWindow::resetFilter() { - summarytableofmatchedpeaks->deleteTable(true); + summarytableofmatchedpeaks->deleteTable(); summarytableofmatchedpeaks->hide(); summarytableisprepared = false; rowsfilterline->setText(""); - int rowcount = results->rowCount(); - - QProgressDialog progress("Updating the report...", 0, 0, rowcount, this); - progress.setMinimumWidth(250); - cEventFilter filter; - progress.installEventFilter(&filter); - progress.setMinimumDuration(0); - progress.setWindowModality(Qt::WindowModal); - for (int i = 0; i < rowcount; i++) { - results->setRowHidden(i, false); - progress.setValue(i); - } + results->horizontalHeader()->setSortIndicator(-1, Qt::AscendingOrder); + resultsproxymodel->sort(-1); - progress.setValue(rowcount); + resultsproxymodel->setFilterKeyColumn(-1); + resultsproxymodel->setFilterFixedString(""); } @@ -1621,6 +1630,12 @@ void cMainWindow::summaryPeaksTableCancelled() { summarytableisprepared = false; } + +void cMainWindow::updateSummaryPeaksTableFilter(int xmin, int xmax, int ymin, int ymax) { + summarytableofmatchedpeaks->updateFilterBySelectedRegion(xmin, xmax, ymin, ymax); +} + + /* void cMainWindow::showContextMenu(const QPoint &pt) { QMenu *menu = logWindow->createStandardContextMenu(); diff --git a/CycloBranch/gui/cMainWindow.h b/CycloBranch/gui/cMainWindow.h index 094afcd..baafb01 100644 --- a/CycloBranch/gui/cMainWindow.h +++ b/CycloBranch/gui/cMainWindow.h @@ -12,8 +12,11 @@ #include #include #include +#include +#include +#include +#include #include "core/utilities.h" -#include "core/cAllocator.h" #include "core/cTheoreticalSpectrum.h" #include "gui/cAboutWidget.h" #include "gui/cGraphWidget.h" @@ -25,9 +28,9 @@ #include "gui/cDrawPeptideWidget.h" #include "gui/cSummaryPeaksTableWidget.h" #include "gui/cMainThread.h" -#include "gui/cDelegate.h" #include "gui/cHTMLExportDialog.h" #include "gui/cImageWindow.h" +#include "gui/cMainWindowProxyModel.h" // forward declaration @@ -118,7 +121,9 @@ class cMainWindow : public QMainWindow QPushButton* rowsfilterbutton; QPushButton* rowsfilterclearbutton; - QTableWidget* results; + QTableView* results; + QStandardItemModel* resultsmodel; + cMainWindowProxyModel* resultsproxymodel; cTheoreticalSpectrumList theoreticalspectrumlist; vector spectradetails; @@ -140,10 +145,7 @@ class cMainWindow : public QMainWindow int resultsbasecolumncount; int resultsspecificcolumncount; - int dbsearchspecificcolumncount; - - vector resultsheadersort; - cDelegate columndelegate; + int searchspecificcolumncount; QString lastdirexporttocsv; QString lastdirexporttohtml; @@ -152,15 +154,13 @@ class cMainWindow : public QMainWindow bool summarytableisprepared; - cAllocator widgetitemallocator; - bool quitapp; void closeEvent(QCloseEvent *event); void preparePeptideSequence(int row, string& peptidesequence, bool reportisomers); - void reportSpectrum(int id, cTheoreticalSpectrum& theoreticalspectrum, bool reportisomers); + void reportSpectrum(int row, cTheoreticalSpectrum& theoreticalspectrum, bool reportisomers); void deleteResults(); @@ -181,6 +181,8 @@ private slots: void setAndShowDrawPeptideWidget(int peptidetypeindex, QString sequence); + void prepareSummaryTableOfMatchedPeaks(); + void showSummaryTableOfMatchedPeaks(); void showImageWindow(); @@ -207,12 +209,10 @@ private slots: void updateSpectra(); - void resultsCellClicked(int row, int column); + void rowDoubleClicked(const QModelIndex& item); void setGraph(string s); - void headerItemDoubleClicked(int); - void exportToCsv(); void exportToHTML(); @@ -243,6 +243,8 @@ private slots: void summaryPeaksTableCancelled(); + void updateSummaryPeaksTableFilter(int xmin, int xmax, int ymin, int ymax); + //void showContextMenu(const QPoint &pt); signals: diff --git a/CycloBranch/gui/cMainWindowProxyModel.cpp b/CycloBranch/gui/cMainWindowProxyModel.cpp new file mode 100644 index 0000000..5144453 --- /dev/null +++ b/CycloBranch/gui/cMainWindowProxyModel.cpp @@ -0,0 +1,36 @@ +#include "gui/cMainWindowProxyModel.h" + + +cMainWindowProxyModel::cMainWindowProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { +} + + +bool cMainWindowProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { + for (int i = 0; i < sourceModel()->columnCount(); i++) { + if (sourceModel()->data(sourceModel()->index(sourceRow, i, sourceParent)).toString().contains(filterRegExp())) { + return true; + } + } + return false; +} + + +bool cMainWindowProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { + QVariant leftData = sourceModel()->data(left); + QVariant rightData = sourceModel()->data(right); + + if (leftData.type() == QVariant::ByteArray) { + return leftData.toDouble() < rightData.toDouble(); + } + + if (leftData.type() == QVariant::String) { + return leftData.toString() < rightData.toString(); + } + + if (leftData.type() == QVariant::Int) { + return leftData.toInt() < rightData.toInt(); + } + + return QSortFilterProxyModel::lessThan(left, right); +} + diff --git a/CycloBranch/gui/cMainWindowProxyModel.h b/CycloBranch/gui/cMainWindowProxyModel.h new file mode 100644 index 0000000..d0e261d --- /dev/null +++ b/CycloBranch/gui/cMainWindowProxyModel.h @@ -0,0 +1,57 @@ +/** + \file cMainWindowProxyModel.h + \brief A table proxy model. +*/ + + +#ifndef _CMAINWINDOWPROXYMODEL_H +#define _CMAINWINDOWPROXYMODEL_H + +#include +#include +#include + + +/** + \brief A table proxy model. +*/ +class cMainWindowProxyModel : public QSortFilterProxyModel { + + Q_OBJECT + +public: + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cMainWindowProxyModel(QObject *parent = 0); + + +protected: + + + /** + \brief Reimplementation of filterAcceptsRow. + \param sourceRow int + \param sourceParent QModelIndex + \retval bool bool + */ + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE; + + + /** + \brief Reimplementation of lessThan. + \param left QModelIndex + \param right QModelIndex + \retval bool bool + */ + bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE; + + +}; + + +#endif + diff --git a/CycloBranch/gui/cModificationsProxyModel.cpp b/CycloBranch/gui/cModificationsProxyModel.cpp new file mode 100644 index 0000000..69f3a5d --- /dev/null +++ b/CycloBranch/gui/cModificationsProxyModel.cpp @@ -0,0 +1,39 @@ +#include "gui/cModificationsProxyModel.h" + + +cModificationsProxyModel::cModificationsProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { +} + + +bool cModificationsProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { + int size = 4; + + for (int i = 1; i < size; i++) { + if (sourceModel()->data(sourceModel()->index(sourceRow, i, sourceParent)).toString().contains(filterRegExp())) { + return true; + } + } + + return false; +} + + +bool cModificationsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { + QVariant leftData = sourceModel()->data(left); + QVariant rightData = sourceModel()->data(right); + + if ((left.column() == 0) || (left.column() == 4) || (left.column() == 5)) { + return leftData.toInt() < rightData.toInt(); + } + + if (leftData.type() == QVariant::ByteArray) { + return leftData.toDouble() < rightData.toDouble(); + } + + if (leftData.type() == QVariant::String) { + return leftData.toString() < rightData.toString(); + } + + return QSortFilterProxyModel::lessThan(left, right); +} + diff --git a/CycloBranch/gui/cModificationsProxyModel.h b/CycloBranch/gui/cModificationsProxyModel.h new file mode 100644 index 0000000..717fb19 --- /dev/null +++ b/CycloBranch/gui/cModificationsProxyModel.h @@ -0,0 +1,58 @@ +/** + \file cModificationsProxyModel.h + \brief A proxy model for editor of database of modifications. +*/ + + +#ifndef _CMODIFICATIONSPROXYMODEL_H +#define _CMODIFICATIONSPROXYMODEL_H + +#include +#include +#include +#include "core/cFragmentIons.h" + + +/** + \brief A proxy model for editor of database of modifications. +*/ +class cModificationsProxyModel : public QSortFilterProxyModel { + + Q_OBJECT + +public: + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cModificationsProxyModel(QObject *parent = 0); + + +protected: + + + /** + \brief Reimplementation of filterAcceptsRow. + \param sourceRow int + \param sourceParent QModelIndex + \retval bool bool + */ + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE; + + + /** + \brief Reimplementation of lessThan. + \param left QModelIndex + \param right QModelIndex + \retval bool bool + */ + bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE; + + +}; + + +#endif + diff --git a/CycloBranch/gui/cModificationsWidget.cpp b/CycloBranch/gui/cModificationsWidget.cpp index f3fcdbd..ff6f7d6 100644 --- a/CycloBranch/gui/cModificationsWidget.cpp +++ b/CycloBranch/gui/cModificationsWidget.cpp @@ -1,8 +1,6 @@ #include "gui/cModificationsWidget.h" #include "gui/cEventFilter.h" -#include -#include #include #include #include @@ -11,39 +9,26 @@ #include #include #include -#include #include #include #include +#include +#include cModificationsWidget::cModificationsWidget(QWidget* parent) { this->parent = parent; - setWindowTitle("Modifications Editor"); - setWindowIcon(QIcon(":/images/icons/61.png")); - - insertrow = new QPushButton(tr("Add Row")); - insertrow->setToolTip("Add a new row."); - insertrow->setShortcut(QKeySequence(Qt::Key_Insert)); - - removechecked = new QPushButton(tr(" Remove Rows ")); - removechecked->setToolTip("Remove selected rows."); - removechecked->setShortcut(QKeySequence(Qt::Key_Delete)); - - close = new QPushButton(tr("Close")); - close->setToolTip("Close the window."); - - load = new QPushButton(tr("Load")); - load->setToolTip("Load modifications."); - load->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); + editorname = "Modifications Editor"; - save = new QPushButton(QString(" Save ")); - save->setToolTip("Save modifications in the current file. When a file has not been loaded yet, the \"Save As ...\" file dialog is opened."); + setWindowTitle(editorname); + setWindowIcon(QIcon(":/images/icons/61.png")); - saveas = new QPushButton(tr("Save As...")); - saveas->setToolTip("Save modifications into a file."); - saveas->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D)); + menuBar = new QMenuBar(this); + menuBar->setNativeMenuBar(false); + menuFile = new QMenu(tr("&File"), this); + menuEdit = new QMenu(tr("&Edit"), this); + menuHelp = new QMenu(tr("&Help"), this); rowsfilterline = new QLineEdit(); rowsfilterline->setMinimumWidth(250); @@ -74,55 +59,129 @@ cModificationsWidget::cModificationsWidget(QWidget* parent) { rowsfilterwidget->setLayout(rowsfilterhbox); rowsfilterwidget->setMaximumWidth(420); - buttons = new QHBoxLayout(); - buttons->addWidget(close); - buttons->addStretch(); - buttons->addWidget(insertrow); - buttons->addWidget(removechecked); - buttons->addStretch(); - buttons->addWidget(rowsfilterwidget); - buttons->addStretch(); - buttons->addWidget(load); - buttons->addWidget(save); - buttons->addWidget(saveas); - - database = new QTableWidget(0, 0, this); - database->setColumnCount(6); - database->setHorizontalHeaderItem(0, new QTableWidgetItem("")); - database->setHorizontalHeaderItem(1, new QTableWidgetItem("Name")); - database->setHorizontalHeaderItem(2, new QTableWidgetItem("Summary Formula")); - database->setHorizontalHeaderItem(3, new QTableWidgetItem("Monoisotopic Mass")); - database->setItemDelegateForColumn(3, &columndelegate); - database->setHorizontalHeaderItem(4, new QTableWidgetItem("N-terminal")); - database->setHorizontalHeaderItem(5, new QTableWidgetItem("C-terminal")); - database->horizontalHeader()->setStretchLastSection(true); - for (int i = 0; i < database->columnCount(); i++) { - database->resizeColumnToContents(i); - } - - headersort.resize(database->columnCount()); - for (int i = 0; i < database->columnCount(); i++) { - headersort[i] = -1; - } + database = new QTableView(this); + databasemodel = new QStandardItemModel(0, 0, this); + proxymodel = new cModificationsProxyModel(this); + proxymodel->setSourceModel(databasemodel); + proxymodel->setDynamicSortFilter(false); + database->setModel(proxymodel); + database->setSortingEnabled(true); + resetHeader(); + mainlayout = new QVBoxLayout(); mainlayout->addWidget(database); - mainlayout->addLayout(buttons); - - connect(database->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(headerItemDoubleClicked(int))); - connect(database, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(itemChanged(QTableWidgetItem *))); - connect(insertrow, SIGNAL(released()), this, SLOT(addRow())); - connect(removechecked, SIGNAL(released()), this, SLOT(removeCheckedRows())); - connect(close, SIGNAL(released()), this, SLOT(closeWindow())); - connect(load, SIGNAL(released()), this, SLOT(loadDatabase())); - connect(save, SIGNAL(released()), this, SLOT(saveDatabase())); - connect(saveas, SIGNAL(released()), this, SLOT(saveDatabaseAs())); + + mainwidget = new QWidget(); + mainwidget->setLayout(mainlayout); + + toolbarFile = addToolBar(tr("File")); + + actionNewDatabase = new QAction(QIcon(":/images/icons/2.png"), tr("&New Database"), this); + actionNewDatabase->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N)); + actionNewDatabase->setToolTip("New Database (Ctrl + N)"); + toolbarFile->addAction(actionNewDatabase); + connect(actionNewDatabase, SIGNAL(triggered()), this, SLOT(createNewDatabase())); + + actionOpenDatabase = new QAction(QIcon(":/images/icons/52.png"), tr("&Open Database"), this); + actionOpenDatabase->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_O)); + actionOpenDatabase->setToolTip("Open Database (Ctrl + O)"); + toolbarFile->addAction(actionOpenDatabase); + connect(actionOpenDatabase, SIGNAL(triggered()), this, SLOT(openDatabase())); + + actionSaveDatabase = new QAction(QIcon(":/images/icons/22.png"), tr("&Save Database..."), this); + actionSaveDatabase->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); + actionSaveDatabase->setToolTip("Save Database... (Ctrl + S)"); + toolbarFile->addAction(actionSaveDatabase); + connect(actionSaveDatabase, SIGNAL(triggered()), this, SLOT(saveDatabase())); + + actionSaveDatabaseAs = new QAction(QIcon(":/images/icons/86.png"), tr("Save &Database As..."), this); + actionSaveDatabaseAs->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D)); + actionSaveDatabaseAs->setToolTip("Save Database As... (Ctrl + D)"); + toolbarFile->addAction(actionSaveDatabaseAs); + connect(actionSaveDatabaseAs, SIGNAL(triggered()), this, SLOT(saveDatabaseAs())); + + actionImportDatabase = new QAction(QIcon(":/images/icons/63.png"), tr("&Import Database"), this); + actionImportDatabase->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_I)); + actionImportDatabase->setToolTip("Import Database (Ctrl + I)"); + toolbarFile->addAction(actionImportDatabase); + connect(actionImportDatabase, SIGNAL(triggered()), this, SLOT(importDatabase())); + + actionCloseWindow = new QAction(QIcon(":/images/icons/33.png"), tr("&Close"), this); + actionCloseWindow->setShortcut(QKeySequence(Qt::Key_Escape)); + actionCloseWindow->setToolTip("Close (Esc)"); + toolbarFile->addAction(actionCloseWindow); + connect(actionCloseWindow, SIGNAL(triggered()), this, SLOT(closeWindow())); + + toolbarEdit = addToolBar(tr("Edit")); + + actionAddRow = new QAction(QIcon(":/images/icons/13.png"), tr("&Insert Row"), this); + actionAddRow->setShortcut(QKeySequence(Qt::Key_Insert)); + actionAddRow->setToolTip("Insert Row (Insert)"); + toolbarEdit->addAction(actionAddRow); + connect(actionAddRow, SIGNAL(triggered()), this, SLOT(addRow())); + + actionRemoveSelectedRows = new QAction(QIcon(":/images/icons/14.png"), tr("&Remove Selected Rows"), this); + actionRemoveSelectedRows->setShortcut(QKeySequence(Qt::Key_Delete)); + actionRemoveSelectedRows->setToolTip("Remove Selected Rows (Delete)"); + toolbarEdit->addAction(actionRemoveSelectedRows); + connect(actionRemoveSelectedRows, SIGNAL(triggered()), this, SLOT(removeSelectedRows())); + + actionSelectAll = new QAction(QIcon(":/images/icons/38.png"), tr("Select &All"), this); + actionSelectAll->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_A)); + actionSelectAll->setToolTip("Select all rows (Ctrl + A)"); + toolbarEdit->addAction(actionSelectAll); + connect(actionSelectAll, SIGNAL(triggered()), this, SLOT(selectAll())); + + actionUnselectAll = new QAction(QIcon(":/images/icons/38b.png"), tr("&Unselect All"), this); + actionUnselectAll->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U)); + actionUnselectAll->setToolTip("Unselect all rows (Ctrl + U)"); + toolbarEdit->addAction(actionUnselectAll); + connect(actionUnselectAll, SIGNAL(triggered()), this, SLOT(unselectAll())); + + toolbarHelp = addToolBar(tr("Help")); + + actionHTMLDocumentation = new QAction(QIcon(":/images/icons/3.png"), tr("&HTML Documentation"), this); + actionHTMLDocumentation->setShortcut(QKeySequence(Qt::Key_F1)); + actionHTMLDocumentation->setToolTip("Show HTML Documentation (F1)"); + toolbarHelp->addAction(actionHTMLDocumentation); + connect(actionHTMLDocumentation, SIGNAL(triggered()), this, SLOT(showHTMLDocumentation())); + + toolbarFilter = addToolBar(tr("Filter")); + toolbarFilter->addWidget(rowsfilterwidget); + + menuFile->addAction(actionNewDatabase); + menuFile->addAction(actionOpenDatabase); + menuFile->addSeparator(); + menuFile->addAction(actionSaveDatabase); + menuFile->addAction(actionSaveDatabaseAs); + menuFile->addSeparator(); + menuFile->addAction(actionImportDatabase); + menuFile->addSeparator(); + menuFile->addAction(actionCloseWindow); + + menuEdit->addAction(actionAddRow); + menuEdit->addAction(actionRemoveSelectedRows); + menuEdit->addSeparator(); + menuEdit->addAction(actionSelectAll); + menuEdit->addAction(actionUnselectAll); + + menuHelp->addAction(actionHTMLDocumentation); + + menuBar->addMenu(menuFile); + menuBar->addMenu(menuEdit); + menuBar->addMenu(menuHelp); + + setMenuBar(menuBar); + + connect(database->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(headerItemClicked(int))); + connect(databasemodel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(itemChanged(QStandardItem*))); connect(rowsfilterbutton, SIGNAL(released()), this, SLOT(filterRows())); connect(rowsfilterclearbutton, SIGNAL(released()), this, SLOT(resetFilter())); - setLayout(mainlayout); + setCentralWidget(mainwidget); - resize(1280, 700); + resize(1280, 750); databasefile = ""; @@ -139,20 +198,11 @@ cModificationsWidget::cModificationsWidget(QWidget* parent) { cModificationsWidget::~cModificationsWidget() { - deleteTable(false); + deleteTable(); - for (int i = 0; i < database->columnCount(); i++) { - delete database->horizontalHeaderItem(i); - } - - database->setColumnCount(0); - - delete insertrow; - delete removechecked; - delete close; - delete load; - delete save; - delete saveas; + delete databasemodel; + delete proxymodel; + delete database; delete rowsfilterline; delete rowsfiltercasesensitive; @@ -161,68 +211,74 @@ cModificationsWidget::~cModificationsWidget() { delete rowsfilterhbox; delete rowsfilterwidget; - delete database; - delete buttons; delete mainlayout; + delete mainwidget; + + delete actionNewDatabase; + delete actionOpenDatabase; + delete actionSaveDatabase; + delete actionSaveDatabaseAs; + delete actionImportDatabase; + delete actionCloseWindow; + delete actionAddRow; + delete actionRemoveSelectedRows; + delete actionSelectAll; + delete actionUnselectAll; + delete actionHTMLDocumentation; + + delete menuFile; + delete menuEdit; + delete menuHelp; + + delete menuBar; } void cModificationsWidget::closeEvent(QCloseEvent *event) { closeWindow(); + event->accept(); } -void cModificationsWidget::deleteTable(bool enableprogress) { - QProgressDialog* progress; - cEventFilter filter; - int rowcount = database->rowCount(); - - if (enableprogress) { - progress = new QProgressDialog("Clearing the table...", 0, 0, rowcount, this); - progress->setMinimumWidth(250); - progress->installEventFilter(&filter); - progress->setMinimumDuration(0); - progress->setWindowModality(Qt::WindowModal); - progress->setValue(0); - } - - widgetitemallocator.reset(); - - for (int i = 0; i < rowcount; i++) { - delete database->cellWidget(rowcount - i - 1, 4); - delete database->cellWidget(rowcount - i - 1, 5); - - if (enableprogress) { - progress->setValue(i); +void cModificationsWidget::deleteTable() { + for (int i = 0; i < databasemodel->columnCount(); i++) { + if (database->itemDelegateForColumn(i)) { + delete database->itemDelegateForColumn(i); } } - - database->setRowCount(0); - if (enableprogress) { - progress->setValue(rowcount); - delete progress; - } + databasemodel->clear(); + databasemodel->setRowCount(0); } -void cModificationsWidget::removeRow(int row) { - for (int i = 0; i < database->columnCount(); i++) { - if ((i == 4) || (i == 5)) { - delete database->cellWidget(row, i); - } - else { - database->takeItem(row, i); - } +void cModificationsWidget::resetHeader() { + databasemodel->setColumnCount(6); + + databasemodel->setHorizontalHeaderItem(0, new QStandardItem()); + database->setItemDelegateForColumn(0, new cCheckBoxDelegate()); + databasemodel->setHorizontalHeaderItem(1, new QStandardItem("Name")); + databasemodel->setHorizontalHeaderItem(2, new QStandardItem("Summary Formula")); + databasemodel->setHorizontalHeaderItem(3, new QStandardItem("Monoisotopic Mass")); + databasemodel->setHorizontalHeaderItem(4, new QStandardItem("N-terminal")); + database->setItemDelegateForColumn(4, new cCheckBoxDelegate()); + databasemodel->setHorizontalHeaderItem(5, new QStandardItem("C-terminal")); + database->setItemDelegateForColumn(5, new cCheckBoxDelegate()); + + database->horizontalHeader()->setStretchLastSection(true); + for (int i = 0; i < databasemodel->columnCount(); i++) { + database->resizeColumnToContents(i); } - database->removeRow(row); + database->setColumnWidth(1, 400); + database->setColumnWidth(2, 400); + database->setColumnWidth(4, (database->horizontalHeader()->sectionSize(4) + database->horizontalHeader()->sectionSize(5)) / 2); } bool cModificationsWidget::checkTable() { // check summary formulas - for (int i = 0; i < database->rowCount(); i++) { - if (!checkFormula(i, database->item(i, 2)->text().toStdString())) { + for (int i = 0; i < databasemodel->rowCount(); i++) { + if (!checkFormula(i, databasemodel->item(i, 2)->text().toStdString())) { return false; } } @@ -245,8 +301,8 @@ bool cModificationsWidget::checkFormula(int row, const string& summary) { msgBox.exec(); return false; } - if (database->item(row, 3)) { - database->item(row, 3)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(formula.getMass())); + if (databasemodel->item(row, 3)) { + databasemodel->item(row, 3)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(formula.getMass())), Qt::DisplayRole); } return true; } @@ -260,46 +316,32 @@ void cModificationsWidget::setDataModified(bool datamodified) { this->datamodified = datamodified; if (datamodified) { - save->setText("*" + save->text()); + setWindowTitle("*" + windowTitle()); } else { - if ((save->text().size() > 0) && (save->text().at(0) == '*')) { - save->setText(save->text().toStdString().substr(1).c_str()); + if ((windowTitle().size() > 0) && (windowTitle().at(0) == '*')) { + setWindowTitle(windowTitle().toStdString().substr(1).c_str()); } } } void cModificationsWidget::keyPressEvent(QKeyEvent *event) { - if (event->key() == Qt::Key_Escape) { - closeWindow(); - } - if ((event->key() == Qt::Key_Enter) || (event->key() == Qt::Key_Return)) { if (rowsfilterline->hasFocus()) { filterRows(); } } - if (event->key() == Qt::Key_F1) { - #if OS_TYPE == WIN - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/modificationseditor.html").absoluteFilePath())); - #else - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/modificationseditor.html").absoluteFilePath())); - #endif - } - if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_F)) { rowsfilterline->setFocus(); } - if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_N)) { + if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_T)) { rowsfiltercasesensitive->setChecked(!rowsfiltercasesensitive->isChecked()); } - if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_S)) { - saveDatabase(); - } + event->accept(); } @@ -319,15 +361,15 @@ void cModificationsWidget::closeWindow() { } -void cModificationsWidget::loadDatabase() { - QString filename = QFileDialog::getOpenFileName(this, tr("Load Modifications"), lastdir, tr("Modifications (*.txt)")); +void cModificationsWidget::openDatabase() { + QString filename = QFileDialog::getOpenFileName(this, tr("Open Database"), lastdir, tr("Database of Modifications (*.txt)")); if (!filename.isEmpty()) { lastdir = filename; string errormessage; databasefile = filename; - save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); + setWindowTitle(editorname + QString(" - ") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str())); inputstream.open(filename.toStdString().c_str()); @@ -338,11 +380,13 @@ void cModificationsWidget::loadDatabase() { } else { + deleteTable(); + resetHeader(); + resetFilter(); + modifications.clear(); loadModificationsFromPlainTextStream(inputstream, modifications, errormessage, true); - deleteTable(true); - QProgressDialog progress("Loading Modifications...", "Cancel", 0, (int)modifications.size(), this); progress.setMinimumWidth(250); cEventFilter filter; @@ -350,47 +394,59 @@ void cModificationsWidget::loadDatabase() { progress.setMinimumDuration(0); progress.setWindowModality(Qt::WindowModal); - database->setRowCount((int)modifications.size()); + database->setModel(0); + proxymodel->setSourceModel(0); + database->setSortingEnabled(false); + + databasemodel->setRowCount((int)modifications.size()); for (int i = 0; i < (int)modifications.size(); i++) { - QCheckBox* checkbox = new QCheckBox(); - database->setCellWidget(i, 0, checkbox); - database->setItem(i, 1, widgetitemallocator.getNewItem()); - database->item(i, 1)->setText(modifications[i].name.c_str()); + databasemodel->setItem(i, 0, new QStandardItem()); + databasemodel->item(i, 0)->setFlags(databasemodel->item(i, 0)->flags() & ~Qt::ItemIsEditable); + + databasemodel->setItem(i, 1, new QStandardItem()); + databasemodel->item(i, 1)->setText(modifications[i].name.c_str()); - database->setItem(i, 2, widgetitemallocator.getNewItem()); - database->item(i, 2)->setText(modifications[i].summary.c_str()); + databasemodel->setItem(i, 2, new QStandardItem()); + databasemodel->item(i, 2)->setText(modifications[i].summary.c_str()); - database->setItem(i, 3, widgetitemallocator.getNewItem()); - database->item(i, 3)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(modifications[i].massdifference)); + databasemodel->setItem(i, 3, new QStandardItem()); + databasemodel->item(i, 3)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(modifications[i].massdifference)), Qt::DisplayRole); - checkbox = new QCheckBox(); - connect(checkbox, SIGNAL(stateChanged(int)), this, SLOT(checkBoxModified(int))); + databasemodel->setItem(i, 4, new QStandardItem()); + databasemodel->item(i, 4)->setFlags(databasemodel->item(i, 4)->flags() & ~Qt::ItemIsEditable); if (modifications[i].nterminal) { - checkbox->setChecked(true); + databasemodel->item(i, 4)->setData(QVariant::fromValue(true), Qt::DisplayRole); } - database->setCellWidget(i, 4, checkbox); - checkbox = new QCheckBox(); - connect(checkbox, SIGNAL(stateChanged(int)), this, SLOT(checkBoxModified(int))); + databasemodel->setItem(i, 5, new QStandardItem()); + databasemodel->item(i, 5)->setFlags(databasemodel->item(i, 5)->flags() & ~Qt::ItemIsEditable); if (modifications[i].cterminal) { - checkbox->setChecked(true); + databasemodel->item(i, 5)->setData(QVariant::fromValue(true), Qt::DisplayRole); } - database->setCellWidget(i, 5, checkbox); progress.setValue(i); if (progress.wasCanceled()) { - deleteTable(true); + deleteTable(); + resetHeader(); modifications.clear(); databasefile = ""; - save->setText(" Save "); + setWindowTitle(editorname); break; } } - for (int i = 0; i < database->columnCount(); i++) { + proxymodel->setSourceModel(databasemodel); + database->setModel(proxymodel); + proxymodel->setSortRole(Qt::InitialSortOrderRole); + database->setSortingEnabled(true); + + for (int i = 0; i < databasemodel->columnCount(); i++) { database->resizeColumnToContents(i); } + database->setColumnWidth(1, 400); + database->setColumnWidth(2, 400); + database->setColumnWidth(4, (database->horizontalHeader()->sectionSize(4) + database->horizontalHeader()->sectionSize(5)) / 2); progress.setValue((int)modifications.size()); @@ -423,7 +479,7 @@ bool cModificationsWidget::saveDatabase() { } else { - QProgressDialog progress("Saving Modifications...", 0, 0, database->rowCount(), this); + QProgressDialog progress("Saving Modifications...", 0, 0, proxymodel->rowCount(), this); progress.setMinimumWidth(250); cEventFilter filter; progress.installEventFilter(&filter); @@ -433,36 +489,31 @@ bool cModificationsWidget::saveDatabase() { fragmentDescription modification; modifications.clear(); - removeCheckedRows(); - - for (int i = 0; i < database->rowCount(); i++) { - - if (database->isRowHidden(i)) { - progress.setValue(i); - continue; - } + for (int i = 0; i < proxymodel->rowCount(); i++) { modification.clear(); - for (int j = 0; j < database->columnCount(); j++) { + for (int j = 0; j < proxymodel->columnCount(); j++) { switch (j) { case 0: // nothing to do break; case 1: - modification.name = database->item(i,j)->text().toStdString(); + modification.name = proxymodel->index(i, j).data(Qt::DisplayRole).toString().toStdString(); + modification.name = removeWhiteSpacesExceptSpaces(modification.name); break; case 2: - modification.summary = database->item(i,j)->text().toStdString(); + modification.summary = proxymodel->index(i, j).data(Qt::DisplayRole).toString().toStdString(); + modification.summary = removeWhiteSpacesExceptSpaces(modification.summary); break; case 3: - modification.massdifference = database->item(i,j)->data(Qt::DisplayRole).toDouble(); + modification.massdifference = proxymodel->index(i, j).data(Qt::DisplayRole).toDouble(); break; case 4: - modification.nterminal = ((QCheckBox *)database->cellWidget(i, j))->isChecked(); + modification.nterminal = proxymodel->index(i, j).data(Qt::DisplayRole).toBool(); break; case 5: - modification.cterminal = ((QCheckBox *)database->cellWidget(i, j))->isChecked(); + modification.cterminal = proxymodel->index(i, j).data(Qt::DisplayRole).toBool(); break; default: break; @@ -493,13 +544,13 @@ bool cModificationsWidget::saveDatabaseAs() { return false; } - QString filename = QFileDialog::getSaveFileName(this, tr("Save Modifications As..."), lastdir, tr("Modifications (*.txt)")); + QString filename = QFileDialog::getSaveFileName(this, tr("Save Database As..."), lastdir, tr("Database of Modifications (*.txt)")); if (!filename.isEmpty()) { lastdir = filename; databasefile = filename; - save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); + setWindowTitle(editorname + QString(" - ") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str())); return saveDatabase(); } @@ -508,33 +559,33 @@ bool cModificationsWidget::saveDatabaseAs() { void cModificationsWidget::addRow() { - int row = database->rowCount(); - database->insertRow(row); + resetFilter(); - database->setCellWidget(row, 0, new QCheckBox()); - database->setItem(row, 1, widgetitemallocator.getNewItem()); - database->setItem(row, 2, widgetitemallocator.getNewItem()); - database->setItem(row, 3, widgetitemallocator.getNewItem()); - - QCheckBox* checkbox; - - checkbox = new QCheckBox(); - connect(checkbox, SIGNAL(stateChanged(int)), this, SLOT(checkBoxModified(int))); - database->setCellWidget(row, 4, checkbox); - - checkbox = new QCheckBox(); - connect(checkbox, SIGNAL(stateChanged(int)), this, SLOT(checkBoxModified(int))); - database->setCellWidget(row, 5, checkbox); + int row = databasemodel->rowCount(); + databasemodel->insertRow(row); - setDataModified(true); + databasemodel->setItem(row, 0, new QStandardItem()); + databasemodel->item(row, 0)->setFlags(databasemodel->item(row, 0)->flags() & ~Qt::ItemIsEditable); + + databasemodel->setItem(row, 1, new QStandardItem()); + databasemodel->setItem(row, 2, new QStandardItem()); + databasemodel->setItem(row, 3, new QStandardItem()); + + databasemodel->setItem(row, 4, new QStandardItem()); + databasemodel->item(row, 4)->setFlags(databasemodel->item(row, 4)->flags() & ~Qt::ItemIsEditable); + + databasemodel->setItem(row, 5, new QStandardItem()); + databasemodel->item(row, 5)->setFlags(databasemodel->item(row, 5)->flags() & ~Qt::ItemIsEditable); + + database->scrollToBottom(); } -void cModificationsWidget::removeCheckedRows() { +void cModificationsWidget::removeSelectedRows() { int i = 0; - while (i < database->rowCount()) { - if (((QCheckBox *)(database->cellWidget(i, 0)))->isChecked()) { - removeRow(i); + while (i < proxymodel->rowCount()) { + if (proxymodel->index(i, 0).data(Qt::DisplayRole).toBool()) { + proxymodel->removeRow(i); setDataModified(true); } else { @@ -544,99 +595,188 @@ void cModificationsWidget::removeCheckedRows() { } -void cModificationsWidget::itemChanged(QTableWidgetItem* item) { +void cModificationsWidget::itemChanged(QStandardItem* item) { + if (!item) { + return; + } + // recalculate mass when formula is changed if (item->column() == 2) { checkFormula(item->row(), item->text().toStdString()); } - setDataModified(true); + if (item->column() > 0) { + setDataModified(true); + } } -void cModificationsWidget::headerItemDoubleClicked(int index) { +void cModificationsWidget::headerItemClicked(int index) { setDataModified(true); +} - if (headersort[index] == -1) { - database->sortByColumn(index, Qt::AscendingOrder); - headersort[index] = 1; - return; - } - if (headersort[index] == 0) { - database->sortByColumn(index, Qt::AscendingOrder); - headersort[index] = 1; - } - else { - database->sortByColumn(index, Qt::DescendingOrder); - headersort[index] = 0; - } +void cModificationsWidget::filterRows() { + proxymodel->setFilterKeyColumn(-1); + proxymodel->setFilterCaseSensitivity(rowsfiltercasesensitive->isChecked()?Qt::CaseSensitive:Qt::CaseInsensitive); + proxymodel->setFilterFixedString(rowsfilterline->text()); } -void cModificationsWidget::filterRows() { - Qt::CaseSensitivity casesensitive = rowsfiltercasesensitive->isChecked()?Qt::CaseSensitive:Qt::CaseInsensitive; - QString str = rowsfilterline->text(); - int rowcount = database->rowCount(); - bool match; - int i, j; - - QProgressDialog progress("Updating...", "Cancel", 0, rowcount, this); - progress.setMinimumWidth(250); - cEventFilter filter; - progress.installEventFilter(&filter); - progress.setMinimumDuration(0); - progress.setWindowModality(Qt::WindowModal); - - for (i = 0; i < rowcount; i++) { - - match = false; - for (j = 0; j < database->columnCount(); j++) { - // ignore non-text fields - if ((j == 0) || (j == 4) || (j == 5)) { - continue; - } +void cModificationsWidget::resetFilter() { + rowsfilterline->setText(""); + + database->horizontalHeader()->setSortIndicator(-1, Qt::AscendingOrder); + proxymodel->sort(-1); + + proxymodel->setFilterKeyColumn(-1); + proxymodel->setFilterFixedString(""); +} - if (database->item(i, j)->text().contains(str, casesensitive)) { - match = true; - break; + +void cModificationsWidget::createNewDatabase() { + if (datamodified) { + QMessageBox::StandardButton reply; + reply = QMessageBox::question(this, appname, "Save changes ?", QMessageBox::Yes|QMessageBox::No); + + if (reply == QMessageBox::Yes) { + if (!saveDatabase()) { + return; } } - database->setRowHidden(i, !match); - progress.setValue(i); + } + + deleteTable(); + resetHeader(); + resetFilter(); + modifications.clear(); + databasefile = ""; + setWindowTitle(editorname); + + setDataModified(false); +} + + +void cModificationsWidget::importDatabase() { + QString filename = QFileDialog::getOpenFileName(this, tr("Import Database"), lastdir, tr("Database of Modifications (*.txt)")); + + if (!filename.isEmpty()) { + lastdir = filename; + string errormessage; + + inputstream.open(filename.toStdString().c_str()); - if (progress.wasCanceled()) { + if (!inputstream.good()) { + QMessageBox msgBox; + msgBox.setText("Cannot open the file '" + filename + "'."); + msgBox.exec(); + } + else { resetFilter(); - break; + + vector importedmodifications; + loadModificationsFromPlainTextStream(inputstream, importedmodifications, errormessage, true); + + QProgressDialog progress("Importing the Database of Modifications...", "Cancel", 0, (int)importedmodifications.size(), this); + progress.setMinimumWidth(250); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); + + database->setModel(0); + proxymodel->setSourceModel(0); + database->setSortingEnabled(false); + + int originalrowcount = databasemodel->rowCount(); + databasemodel->setRowCount(originalrowcount + (int)importedmodifications.size()); + for (int i = 0; i < (int)importedmodifications.size(); i++) { + + databasemodel->setItem(i + originalrowcount, 0, new QStandardItem()); + databasemodel->item(i + originalrowcount, 0)->setFlags(databasemodel->item(i + originalrowcount, 0)->flags() & ~Qt::ItemIsEditable); + + databasemodel->setItem(i + originalrowcount, 1, new QStandardItem()); + databasemodel->item(i + originalrowcount, 1)->setText(importedmodifications[i].name.c_str()); + + databasemodel->setItem(i + originalrowcount, 2, new QStandardItem()); + databasemodel->item(i + originalrowcount, 2)->setText(importedmodifications[i].summary.c_str()); + + databasemodel->setItem(i + originalrowcount, 3, new QStandardItem()); + databasemodel->item(i + originalrowcount, 3)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(importedmodifications[i].massdifference)), Qt::DisplayRole); + + databasemodel->setItem(i + originalrowcount, 4, new QStandardItem()); + databasemodel->item(i + originalrowcount, 4)->setFlags(databasemodel->item(i + originalrowcount, 4)->flags() & ~Qt::ItemIsEditable); + if (importedmodifications[i].nterminal) { + databasemodel->item(i + originalrowcount, 4)->setData(QVariant::fromValue(true), Qt::DisplayRole); + } + + databasemodel->setItem(i + originalrowcount, 5, new QStandardItem()); + databasemodel->item(i + originalrowcount, 5)->setFlags(databasemodel->item(i + originalrowcount, 5)->flags() & ~Qt::ItemIsEditable); + if (importedmodifications[i].cterminal) { + databasemodel->item(i + originalrowcount, 5)->setData(QVariant::fromValue(true), Qt::DisplayRole); + } + + modifications.push_back(importedmodifications[i]); + + progress.setValue(i); + if (progress.wasCanceled()) { + deleteTable(); + resetHeader(); + modifications.clear(); + databasefile = ""; + setWindowTitle(editorname); + break; + } + } + + proxymodel->setSourceModel(databasemodel); + database->setModel(proxymodel); + proxymodel->setSortRole(Qt::InitialSortOrderRole); + database->setSortingEnabled(true); + + for (int i = 0; i < databasemodel->columnCount(); i++) { + database->resizeColumnToContents(i); + } + database->setColumnWidth(1, 400); + database->setColumnWidth(2, 400); + database->setColumnWidth(4, (database->horizontalHeader()->sectionSize(4) + database->horizontalHeader()->sectionSize(5)) / 2); + + if (progress.wasCanceled()) { + setDataModified(false); + } + else { + setDataModified(true); + } + + progress.setValue((int)importedmodifications.size()); + } - } + inputstream.close(); - progress.setValue(rowcount); + } } -void cModificationsWidget::resetFilter() { - rowsfilterline->setText(""); - int rowcount = database->rowCount(); - - QProgressDialog progress("Updating...", 0, 0, rowcount, this); - progress.setMinimumWidth(250); - cEventFilter filter; - progress.installEventFilter(&filter); - progress.setMinimumDuration(0); - progress.setWindowModality(Qt::WindowModal); - - for (int i = 0; i < rowcount; i++) { - database->setRowHidden(i, false); - progress.setValue(i); +void cModificationsWidget::selectAll() { + for (int i = 0; i < proxymodel->rowCount(); i++) { + databasemodel->itemFromIndex(proxymodel->mapToSource(proxymodel->index(i, 0)))->setData(QVariant::fromValue(true), Qt::DisplayRole); } +} - progress.setValue(rowcount); + +void cModificationsWidget::unselectAll() { + for (int i = 0; i < proxymodel->rowCount(); i++) { + databasemodel->itemFromIndex(proxymodel->mapToSource(proxymodel->index(i, 0)))->setData(QVariant::fromValue(false), Qt::DisplayRole); + } } -void cModificationsWidget::checkBoxModified(int state) { - setDataModified(true); +void cModificationsWidget::showHTMLDocumentation() { + #if OS_TYPE == WIN + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/modificationseditor.html").absoluteFilePath())); + #else + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/modificationseditor.html").absoluteFilePath())); + #endif } diff --git a/CycloBranch/gui/cModificationsWidget.h b/CycloBranch/gui/cModificationsWidget.h index 39a4be5..1c73aa6 100644 --- a/CycloBranch/gui/cModificationsWidget.h +++ b/CycloBranch/gui/cModificationsWidget.h @@ -1,6 +1,6 @@ /** \file cModificationsWidget.h - \brief Editor of N-terminal and C-terminal modifications. + \brief An editor of N-/C-terminal modifications database. */ @@ -11,31 +11,33 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include "core/utilities.h" #include "core/cFragmentIons.h" #include "core/cSummaryFormula.h" -#include "core/cAllocator.h" -#include "gui/cDelegate.h" - - -using namespace std; +#include "gui/cModificationsProxyModel.h" +#include "gui/cCheckBoxDelegate.h" // forward declaration class QHBoxLayout; class QVBoxLayout; -class QTableWidget; -class QTableWidgetItem; class QPushButton; class QLineEdit; -class QCheckBox; +class QMenuBar; +class QMenu; /** - \brief Editor of N-terminal and C-terminal modifications. + \brief An editor of N-/C-terminal modifications database. */ -class cModificationsWidget : public QWidget +class cModificationsWidget : public QMainWindow { Q_OBJECT @@ -64,14 +66,33 @@ class cModificationsWidget : public QWidget private: + QString editorname; + QWidget* parent; - QPushButton* insertrow; - QPushButton* removechecked; - QPushButton* close; - QPushButton* load; - QPushButton* save; - QPushButton* saveas; + QMenuBar* menuBar; + QMenu* menuFile; + QMenu* menuEdit; + QMenu* menuHelp; + + QToolBar* toolbarFile; + QAction* actionNewDatabase; + QAction* actionOpenDatabase; + QAction* actionSaveDatabase; + QAction* actionSaveDatabaseAs; + QAction* actionImportDatabase; + QAction* actionCloseWindow; + + QToolBar* toolbarEdit; + QAction* actionAddRow; + QAction* actionRemoveSelectedRows; + QAction* actionSelectAll; + QAction* actionUnselectAll; + + QToolBar* toolbarHelp; + QAction* actionHTMLDocumentation; + + QToolBar* toolbarFilter; QWidget* rowsfilterwidget; QHBoxLayout* rowsfilterhbox; QLineEdit* rowsfilterline; @@ -79,9 +100,11 @@ class cModificationsWidget : public QWidget QPushButton* rowsfilterbutton; QPushButton* rowsfilterclearbutton; - QTableWidget* database; - QHBoxLayout* buttons; + QTableView* database; + QStandardItemModel* databasemodel; + cModificationsProxyModel* proxymodel; QVBoxLayout* mainlayout; + QWidget* mainwidget; QString databasefile; QString lastdir; @@ -89,16 +112,11 @@ class cModificationsWidget : public QWidget ofstream outputstream; vector modifications; - vector headersort; - cDelegate columndelegate; - - cAllocator widgetitemallocator; - bool datamodified; - void deleteTable(bool enableprogress); + void deleteTable(); - void removeRow(int row); + void resetHeader(); bool checkTable(); @@ -120,7 +138,7 @@ private slots: void closeWindow(); - void loadDatabase(); + void openDatabase(); bool saveDatabase(); @@ -128,17 +146,25 @@ private slots: void addRow(); - void removeCheckedRows(); + void removeSelectedRows(); - void itemChanged(QTableWidgetItem* item); + void itemChanged(QStandardItem* item); - void headerItemDoubleClicked(int index); + void headerItemClicked(int index); void filterRows(); void resetFilter(); - void checkBoxModified(int state); + void createNewDatabase(); + + void importDatabase(); + + void selectAll(); + + void unselectAll(); + + void showHTMLDocumentation(); }; diff --git a/CycloBranch/gui/cMultipleButtonDelegate.cpp b/CycloBranch/gui/cMultipleButtonDelegate.cpp new file mode 100644 index 0000000..d02c8c7 --- /dev/null +++ b/CycloBranch/gui/cMultipleButtonDelegate.cpp @@ -0,0 +1,68 @@ +#include "gui/cMultipleButtonDelegate.h" + +#include +#include +#include +#include +#include +#include + + +cMultipleButtonDelegate::cMultipleButtonDelegate(QObject* parent) : QStyledItemDelegate(parent) { +} + + +QString cMultipleButtonDelegate::displayText(const QVariant& value, const QLocale& locale) const { + return ""; +} + + +void cMultipleButtonDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { + QString acronyms = index.model()->index(index.row(), 2).data(Qt::DisplayRole).toString(); + + if (acronyms.isEmpty()) { + return; + } + + QStringList acronymslist = acronyms.split("/"); + int count = acronymslist.size(); + vector buttons; + buttons.resize(count); + for (int i = 0; i < count; i++) { + buttons[i].rect = option.rect; + buttons[i].rect.setX(buttons[i].rect.x() + i*(option.rect.width()/count)); + buttons[i].rect.setWidth(option.rect.width()/count); + buttons[i].text = acronymslist[i]; + buttons[i].state = QStyle::State_Enabled; + QApplication::style()->drawControl(QStyle::CE_PushButton, &(buttons[i]), painter); + } +} + + +bool cMultipleButtonDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index) { + if (event->type() == QEvent::MouseButtonRelease) { + QString acronyms = index.model()->index(index.row(), 2).data(Qt::DisplayRole).toString(); + QString references = index.model()->index(index.row(), 6).data(Qt::DisplayRole).toString(); + + if (acronyms.isEmpty() || references.isEmpty()) { + return false; + } + + QMouseEvent *mouseevent = static_cast(event); + QStringList acronymslist = acronyms.split("/"); + QStringList referenceslist = references.split("\""); + int count = acronymslist.size(); + + for (int i = 0; i < count; i++) { + if ((mouseevent->x() >= option.rect.x() + i*(option.rect.width()/count)) && (mouseevent->x() < option.rect.x() + (i + 1)*(option.rect.width()/count))) { + QString link = (2*i + 1 < referenceslist.size())?referenceslist[2*i + 1]:""; + QDesktopServices::openUrl(QUrl(link)); + break; + } + } + + return true; + } + return false; +} + diff --git a/CycloBranch/gui/cMultipleButtonDelegate.h b/CycloBranch/gui/cMultipleButtonDelegate.h new file mode 100644 index 0000000..4e578fa --- /dev/null +++ b/CycloBranch/gui/cMultipleButtonDelegate.h @@ -0,0 +1,71 @@ +/** + \file cMultipleButtonDelegate.h + \brief A delegate to create multiple buttons. +*/ + + +#ifndef _CMULTIPLEBUTTONDELEGATE_H +#define _CMULTIPLEBUTTONDELEGATE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "core/utilities.h" + +/** + \brief A delegate to create multiple buttons. +*/ +class cMultipleButtonDelegate : public QStyledItemDelegate { + + Q_OBJECT + +public: + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cMultipleButtonDelegate(QObject* parent = (QObject *)0); + + + /** + \brief Reimplementation of displayText. + \param value a value + \param locale a locale + \retval QString the value as a string + */ + QString displayText(const QVariant& value, const QLocale& locale) const; + + + /** + \brief Reimplementation of paint. + \param painter QPainter + \param option QStyleOptionViewItem + \param index QModelIndex + */ + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + + +protected: + + + /** + \brief Reimplementation of editorEvent. + \param event QEvent + \param model QAbstractItemModel + \param option QStyleOptionViewItem + \param index QModelIndex + */ + bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index); + +}; + + +#endif + diff --git a/CycloBranch/gui/cParametersWidget.cpp b/CycloBranch/gui/cParametersWidget.cpp index 3182e65..f0e6031 100644 --- a/CycloBranch/gui/cParametersWidget.cpp +++ b/CycloBranch/gui/cParametersWidget.cpp @@ -63,28 +63,25 @@ cParametersWidget::cParametersWidget(QWidget* parent) { peptidetype->addItem(tr("Cyclic")); peptidetype->addItem(tr("Branched")); peptidetype->addItem(tr("Branch-cyclic")); -#if OLIGOKETIDES == 1 - peptidetype->addItem(tr("Linear oligoketide")); - peptidetype->addItem(tr("Cyclic oligoketide")); -#endif - peptidetype->addItem(tr("Linear polysaccharide (beta version)")); + peptidetype->addItem(tr("Linear polyketide")); + peptidetype->addItem(tr("Cyclic polyketide")); //peptidetype->addItem(tr("Other")); peaklistformlayout->addRow(tr("Peptide Type: "), peptidetype); peaklistline = new QLineEdit(); peaklistbutton = new QPushButton("Select"); #if OS_TYPE != WIN - peaklistline->setToolTip("Select the peaklist. Following formats are supported: txt, mgf, mzML, mzXML, imzML."); - peaklistbutton->setToolTip("Select the peaklist. Following formats are supported: txt, mgf, mzML, mzXML, imzML."); + peaklistline->setToolTip("Select a file. Supported formats:\ntxt (peaklists),\nmgf (peaklists),\nmzML (peaklists),\nmzXML (peaklists),\nimzML (profile spectra or peaklists)."); + peaklistbutton->setToolTip("Select a file. Supported formats:\ntxt (peaklists),\nmgf (peaklists),\nmzML (peaklists),\nmzXML (peaklists),\nimzML (profile spectra or peaklists)."); #else - peaklistline->setToolTip("Select the peaklist. Following formats are supported: txt, mgf, mzML, mzXML, baf, mis, imzML."); - peaklistbutton->setToolTip("Select the peaklist. Following formats are supported: txt, mgf, mzML, mzXML, baf, mis, imzML."); + peaklistline->setToolTip("Select a file. Supported formats:\ntxt (peaklists),\nmgf (peaklists),\nmzML (peaklists),\nmzXML (peaklists),\nbaf (profile spectra),\nimzML (profile spectra or peaklists),\nmis (deprecated)."); + peaklistbutton->setToolTip("Select a file. Supported formats:\ntxt (peaklists),\nmgf (peaklists),\nmzML (peaklists),\nmzXML (peaklists),\nbaf (profile spectra),\nimzML (profile spectra or peaklists),\nmis (deprecated)."); #endif peaklistbutton->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_P)); peaklistlayout = new QHBoxLayout(); peaklistlayout->addWidget(peaklistline); peaklistlayout->addWidget(peaklistbutton); - peaklistformlayout->addRow(tr("Peaklist File: "), peaklistlayout); + peaklistformlayout->addRow(tr("File: "), peaklistlayout); precursormass = new QDoubleSpinBox(); precursormass->setToolTip("Enter the precursor mass-to-charge (m/z) ratio (a precursor m/z ratio in the peaklist file is ignored). The value will be automatically decharged."); @@ -98,7 +95,7 @@ cParametersWidget::cParametersWidget(QWidget* parent) { peaklistformlayout->addRow(tr("Precursor Ion Adduct: "), precursoradduct); precursorcharge = new QSpinBox(); - precursorcharge->setToolTip("Enter the precursor charge (a precursor charge in the peaklist file is ignored). Negative values are allowed.\nWhen mode is set up to \"Compare Peaklist with Database - MS data\", the value determines the maximum charge of generated peaks."); + precursorcharge->setToolTip("Enter the precursor charge (a precursor charge in the peaklist file is ignored). Negative values are allowed.\nWhen mode is set up to \"Compare Peaklist(s) with Database - MS or MSI data\", the value determines the maximum charge of generated peaks."); precursorcharge->setRange(-100, 100); precursorcharge->setSingleStep(1); peaklistformlayout->addRow(tr("Charge: "), precursorcharge); @@ -132,6 +129,7 @@ cParametersWidget::cParametersWidget(QWidget* parent) { minimumrelativeintensitythreshold->setDecimals(3); minimumrelativeintensitythreshold->setRange(0, 100); minimumrelativeintensitythreshold->setSingleStep(1); + minimumrelativeintensitythreshold->setSuffix(" %"); peaklistformlayout->addRow(tr("Minimum Threshold of Relative Intensity: "), minimumrelativeintensitythreshold); minimummz = new QDoubleSpinBox(); @@ -141,7 +139,14 @@ cParametersWidget::cParametersWidget(QWidget* parent) { minimummz->setSingleStep(1); peaklistformlayout->addRow(tr("Minimum m/z Ratio: "), minimummz); - peaklistgroupbox = new QGroupBox("Peaklist"); + fwhm = new QDoubleSpinBox(); + fwhm->setToolTip("Full width at half maximum. The value is used if the profile spectra are converted into peaklists (imzML)."); + fwhm->setDecimals(6); + fwhm->setRange(0, 1); + fwhm->setSingleStep(0.01); + peaklistformlayout->addRow(tr("FWHM: "), fwhm); + + peaklistgroupbox = new QGroupBox("Spectrum"); peaklistgroupbox->setLayout(peaklistformlayout); @@ -203,28 +208,32 @@ cParametersWidget::cParametersWidget(QWidget* parent) { miscformlayout = new QFormLayout(); blindedges = new QComboBox(); - blindedges->setToolTip("An operation which is performed with edges in the de novo graph forming exclusively blind paths:\nnone (edges are kept - useful when you would like to see the whole de novo graph in 'View -> Graph');\nremove (edges are removed - speeds up the search);\nconnect (edges are connected - useful when you are looking for sequence tags)."); - blindedges->addItem(tr("none (you can see a complete de novo graph)")); + blindedges->setToolTip("The operation to be performed with edges forming incomplete paths:\nkeep (edges are kept - useful when you would like to see the whole de novo graph in 'View -> Graph');\nremove (edges are removed - speeds up the search);\nconnect (edges are connected - useful when you are looking for sequence tags)."); + blindedges->addItem(tr("keep (you can see a complete de novo graph)")); blindedges->addItem(tr("remove (speed up the search)")); blindedges->addItem(tr("connect (allow detection of sequence tags)")); - miscformlayout->addRow(tr("Action with Blind Paths in De Novo Graph: "), blindedges); + miscformlayout->addRow(tr("Incomplete Paths in De Novo Graph: "), blindedges); cyclicnterminus = new QCheckBox(); - cyclicnterminus->setToolTip("N-terminal cyclization of a linear peptide is assumed when checked. H2O is subtracted from all theoretical N-terminal fragment ions and the theoretical precursor mass."); + cyclicnterminus->setToolTip("The water molecule is subtracted from all theoretical N-terminal fragment ions and the theoretical precursor mass.\nThis feature is useful when a linear peptide includes a small cycle close to the N-terminus.\nIf the linear polyketide is selected as the peptide type, the water molecule is subtracted only from the precursor ion."); miscformlayout->addRow(tr("Cyclic N-terminus: "), cyclicnterminus); cycliccterminus = new QCheckBox(); - cycliccterminus->setToolTip("C-terminal cyclization of a linear peptide is assumed when checked. H2O is subtracted from all theoretical C-terminal fragment ions and the theoretical precursor mass."); + cycliccterminus->setToolTip("The water molecule is subtracted from all theoretical C-terminal fragment ions and the theoretical precursor mass.\nThis feature is useful when a linear peptide includes a small cycle close to the C-terminus.\nIf the linear polyketide is selected as the peptide type, the water molecule is subtracted only from the precursor ion."); miscformlayout->addRow(tr("Cyclic C-terminus: "), cycliccterminus); enablescrambling = new QCheckBox(); - enablescrambling->setToolTip("When checked, scrambled fragment ions of cyclic peptides are generated in theoretical spectra."); + enablescrambling->setToolTip("Generate scrambled fragment ions of cyclic peptides in theoretical spectra."); miscformlayout->addRow(tr("Enable Scrambling: "), enablescrambling); similaritysearch = new QCheckBox(); - similaritysearch->setToolTip("It enables similarity search when a peaklist is searched against a database of sequences.\nThis feature disables filtering of peptide sequence candidates by precursor mass.\nIt may be useful to determine a peptide family when a similar peptide is contained in the database."); + similaritysearch->setToolTip("Enable the similarity search when a peaklist is searched against a database of sequences.\nThis feature disables filtering of peptide sequence candidates by precursor mass and can be useful to determine a peptide family when a similar peptide is included in a database of sequences."); miscformlayout->addRow(tr("Enable Similarity Search: "), similaritysearch); + regularblocksorder = new QCheckBox(); + regularblocksorder->setToolTip("Keep only polyketide sequence candidates whose ketide building blocks are in the regular order [water eliminating block]-[2H eliminating block]-[water eliminating block]-[2H eliminating block], etc."); + miscformlayout->addRow(tr("Regular Order of Ketide Blocks: "), regularblocksorder); + miscgroupbox = new QGroupBox("Miscellaneous"); miscgroupbox->setLayout(miscformlayout); @@ -232,12 +241,13 @@ cParametersWidget::cParametersWidget(QWidget* parent) { applicationformlayout = new QFormLayout(); mode = new QComboBox(); - mode->setToolTip("De Novo Search Engine (identification mode) - the default mode of the application.\nCompare Peaklist with Spectrum of Searched Sequence (annotation mode) - a theoretical spectrum is generated for an input \"Searched Peptide Sequence\" and it is compared with the peaklist.\nCompare Peaklist with Database - MS/MS data (identification mode) - a peaklist is compared with theoretical spectra generated from a database of sequences.\nCompare Peaklist with Database - MS data (identification mode) - a peaklist is compared with theoretical peaks generated from a database of compounds/sequences."); + mode->setToolTip("'De Novo Search Engine' - the default mode of the application.\n'Compare Peaklist with Spectrum of Searched Sequence' - a theoretical spectrum is generated for the input 'Searched Peptide Sequence' and is compared with the peaklist.\n'Compare Peaklist with Database - MS/MS data' - a peaklist is compared with theoretical spectra generated from a database of sequences.\n'Compare Peaklist(s) with Database - MS or MSI data' - dereplication; compounds search; the peaklists are compared with theoretical peaks generated from a database of compounds/sequences."); mode->addItem(tr("De Novo Search Engine")); mode->addItem(tr("Compare Peaklist with Spectrum of Searched Sequence")); mode->addItem(tr("Compare Peaklist with Database - MS/MS data")); - mode->addItem(tr("Compare Peaklist with Database - MS data")); + mode->addItem(tr("Compare Peaklist(s) with Database - MS or MSI data")); applicationformlayout->addRow(tr("Mode: "), mode); + oldmodetype = (eModeType)mode->currentIndex(); sequencedatabaseline = new QLineEdit(); sequencedatabaseline->setToolTip("Select the txt file containing a database of sequences."); @@ -350,7 +360,7 @@ cParametersWidget::cParametersWidget(QWidget* parent) { setLayout(vlayout); - resize(1280, 700); + resize(1280, 750); connect(load, SIGNAL(released()), this, SLOT(loadSettings())); connect(save, SIGNAL(released()), this, SLOT(saveSettings())); @@ -413,6 +423,7 @@ cParametersWidget::~cParametersWidget() { delete masserrortolerancefordeisotoping; delete minimumrelativeintensitythreshold; delete minimummz; + delete fwhm; delete peaklistformlayout; delete peaklistgroupbox; @@ -435,6 +446,7 @@ cParametersWidget::~cParametersWidget() { delete cycliccterminus; delete enablescrambling; delete similaritysearch; + delete regularblocksorder; delete miscformlayout; delete miscgroupbox; @@ -491,6 +503,7 @@ void cParametersWidget::setAndRestoreParameters(cParameters& parameters) { void cParametersWidget::closeEvent(QCloseEvent *event) { restoreParameters(); + event->accept(); } @@ -521,11 +534,13 @@ void cParametersWidget::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_F1) { #if OS_TYPE == WIN - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/basicconfiguration.html").absoluteFilePath())); + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/settings.html").absoluteFilePath())); #else - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/basicconfiguration.html").absoluteFilePath())); + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/settings.html").absoluteFilePath())); #endif } + + event->accept(); } @@ -551,11 +566,12 @@ void cParametersWidget::loadSettings() { masserrortolerancefordeisotoping->setValue(settings.value("masserrortolerancefordeisotoping", 5.0).toDouble()); minimumrelativeintensitythreshold->setValue(settings.value("minimumrelativeintensitythreshold", 0).toDouble()); minimummz->setValue(settings.value("minimummz", 150).toDouble()); + fwhm->setValue(settings.value("fwhm", 0.1).toDouble()); brickdatabaseline->setText(settings.value("brickdatabase", "").toString()); - maximumbricksincombinationbegin->setValue(settings.value("maximumbricksincombinationbegin", 3).toInt()); - maximumbricksincombinationmiddle->setValue(settings.value("maximumbricksincombinationmiddle", 2).toInt()); - maximumbricksincombinationend->setValue(settings.value("maximumbricksincombinationend", 3).toInt()); + maximumbricksincombinationbegin->setValue(settings.value("maximumbricksincombinationbegin", 1).toInt()); + maximumbricksincombinationmiddle->setValue(settings.value("maximumbricksincombinationmiddle", 1).toInt()); + maximumbricksincombinationend->setValue(settings.value("maximumbricksincombinationend", 1).toInt()); maximumcumulativemass->setValue(settings.value("maximumcumulativemass", 0).toDouble()); settings.value("generatebrickspermutations", 1).toInt() == 0 ? generatebrickspermutations->setChecked(false) : generatebrickspermutations->setChecked(true); modificationsline->setText(settings.value("modificationsfile", "").toString()); @@ -565,6 +581,7 @@ void cParametersWidget::loadSettings() { settings.value("cycliccterminus", 0).toInt() == 0 ? cycliccterminus->setChecked(false) : cycliccterminus->setChecked(true); settings.value("enablescrambling", 0).toInt() == 0 ? enablescrambling->setChecked(false) : enablescrambling->setChecked(true); settings.value("similaritysearch", 0).toInt() == 0 ? similaritysearch->setChecked(false) : similaritysearch->setChecked(true); + settings.value("regularblocksorder", 0).toInt() == 0 ? regularblocksorder->setChecked(false) : regularblocksorder->setChecked(true); mode->setCurrentIndex(settings.value("mode", 0).toInt()); sequencedatabaseline->setText(settings.value("sequencedatabase", "").toString()); @@ -612,6 +629,7 @@ void cParametersWidget::saveSettings() { settings.setValue("masserrortolerancefordeisotoping", masserrortolerancefordeisotoping->value()); settings.setValue("minimumrelativeintensitythreshold", minimumrelativeintensitythreshold->value()); settings.setValue("minimummz", minimummz->value()); + settings.setValue("fwhm", fwhm->value()); settings.setValue("brickdatabase", brickdatabaseline->text()); settings.setValue("maximumbricksincombinationbegin", maximumbricksincombinationbegin->value()); @@ -626,6 +644,7 @@ void cParametersWidget::saveSettings() { cycliccterminus->isChecked() ? settings.setValue("cycliccterminus", 1) : settings.setValue("cycliccterminus", 0); enablescrambling->isChecked() ? settings.setValue("enablescrambling", 1) : settings.setValue("enablescrambling", 0); similaritysearch->isChecked() ? settings.setValue("similaritysearch", 1) : settings.setValue("similaritysearch", 0); + regularblocksorder->isChecked() ? settings.setValue("regularblocksorder", 1) : settings.setValue("regularblocksorder", 0); settings.setValue("mode", mode->currentIndex()); settings.setValue("sequencedatabase", sequencedatabaseline->text()); @@ -731,6 +750,13 @@ bool cParametersWidget::updateParameters() { return false; } + if ((precursormass->value() == 0) && (((eModeType)mode->currentIndex() == denovoengine) || ((eModeType)mode->currentIndex() == singlecomparison) || ((eModeType)mode->currentIndex() == databasesearch))) { + errstr = "The precursor m/z ratio cannot be zero!"; + msgBox.setText(errstr); + msgBox.exec(); + return false; + } + if (precursorcharge->value() == 0) { errstr = "The charge cannot be zero!"; msgBox.setText(errstr); @@ -757,6 +783,7 @@ bool cParametersWidget::updateParameters() { parameters.masserrortolerancefordeisotoping = masserrortolerancefordeisotoping->value(); parameters.minimumrelativeintensitythreshold = minimumrelativeintensitythreshold->value(); parameters.minimummz = minimummz->value(); + parameters.fwhm = fwhm->value(); parameters.bricksdatabasefilename = brickdatabaseline->text().toStdString(); parameters.maximumbricksincombinationbegin = maximumbricksincombinationbegin->value(); @@ -772,6 +799,7 @@ bool cParametersWidget::updateParameters() { parameters.cycliccterminus = cycliccterminus->isChecked(); parameters.enablescrambling = enablescrambling->isChecked(); parameters.similaritysearch = similaritysearch->isChecked(); + parameters.regularblocksorder = regularblocksorder->isChecked(); parameters.mode = (eModeType)mode->currentIndex(); parameters.sequencedatabasefilename = sequencedatabaseline->text().toStdString(); @@ -796,17 +824,12 @@ bool cParametersWidget::updateParameters() { case branchcyclic: start = a_ion; break; -#if OLIGOKETIDES == 1 - case linearoligoketide: + case linearpolyketide: start = l1h_ion; break; - case cyclicoligoketide: + case cyclicpolyketide: start = l1h_ion; // l0h_ion; break; -#endif - case linearpolysaccharide: - start = ms_nterminal_ion_hplus; - break; case other: default: break; @@ -853,6 +876,7 @@ void cParametersWidget::restoreParameters() { masserrortolerancefordeisotoping->setValue(parameters.masserrortolerancefordeisotoping); minimumrelativeintensitythreshold->setValue(parameters.minimumrelativeintensitythreshold); minimummz->setValue(parameters.minimummz); + fwhm->setValue(parameters.fwhm); brickdatabaseline->setText(parameters.bricksdatabasefilename.c_str()); maximumbricksincombinationbegin->setValue(parameters.maximumbricksincombinationbegin); @@ -867,6 +891,7 @@ void cParametersWidget::restoreParameters() { cycliccterminus->setChecked(parameters.cycliccterminus); enablescrambling->setChecked(parameters.enablescrambling); similaritysearch->setChecked(parameters.similaritysearch); + regularblocksorder->setChecked(parameters.regularblocksorder); mode->setCurrentIndex(parameters.mode); sequencedatabaseline->setText(parameters.sequencedatabasefilename.c_str()); @@ -888,17 +913,12 @@ void cParametersWidget::restoreParameters() { case branchcyclic: start = a_ion; break; -#if OLIGOKETIDES == 1 - case linearoligoketide: + case linearpolyketide: start = l1h_ion; break; - case cyclicoligoketide: + case cyclicpolyketide: start = l1h_ion; // l0h_ion; break; -#endif - case linearpolysaccharide: - start = ms_nterminal_ion_hplus; - break; case other: default: break; @@ -930,7 +950,9 @@ void cParametersWidget::restoreParameters() { void cParametersWidget::updateSettingsWhenPeptideTypeChanged(int index) { - resetFragmentIonTypes(); + if (!(((eModeType)mode->currentIndex() != oldmodetype) && ((eModeType)mode->currentIndex() != dereplication) && (oldmodetype != dereplication))) { + resetFragmentIonTypes(); + } switch ((ePeptideType)index) { @@ -940,6 +962,7 @@ void cParametersWidget::updateSettingsWhenPeptideTypeChanged(int index) { cyclicnterminus->setDisabled(false); cycliccterminus->setDisabled(false); enablescrambling->setDisabled(true); + regularblocksorder->setDisabled(true); searchedsequenceNtermmodif->setDisabled(false); searchedsequenceCtermmodif->setDisabled(false); searchedsequenceTmodif->setDisabled(true); @@ -950,6 +973,7 @@ void cParametersWidget::updateSettingsWhenPeptideTypeChanged(int index) { cyclicnterminus->setDisabled(true); cycliccterminus->setDisabled(true); enablescrambling->setDisabled(false); + regularblocksorder->setDisabled(true); searchedsequenceNtermmodif->setDisabled(true); searchedsequenceCtermmodif->setDisabled(true); searchedsequenceTmodif->setDisabled(true); @@ -960,6 +984,7 @@ void cParametersWidget::updateSettingsWhenPeptideTypeChanged(int index) { cyclicnterminus->setDisabled(true); cycliccterminus->setDisabled(true); enablescrambling->setDisabled(true); + regularblocksorder->setDisabled(true); searchedsequenceNtermmodif->setDisabled(false); searchedsequenceCtermmodif->setDisabled(false); searchedsequenceTmodif->setDisabled(false); @@ -970,43 +995,35 @@ void cParametersWidget::updateSettingsWhenPeptideTypeChanged(int index) { cyclicnterminus->setDisabled(true); cycliccterminus->setDisabled(true); enablescrambling->setDisabled(true); + regularblocksorder->setDisabled(true); searchedsequenceNtermmodif->setDisabled(true); searchedsequenceCtermmodif->setDisabled(true); searchedsequenceTmodif->setDisabled(false); break; -#if OLIGOKETIDES == 1 - case linearoligoketide: + case linearpolyketide: modificationsline->setDisabled(false); modificationsbutton->setDisabled(false); - cyclicnterminus->setDisabled(true); - cycliccterminus->setDisabled(true); + cyclicnterminus->setDisabled(false); + cycliccterminus->setDisabled(false); enablescrambling->setDisabled(true); + regularblocksorder->setDisabled(false); searchedsequenceNtermmodif->setDisabled(false); searchedsequenceCtermmodif->setDisabled(false); searchedsequenceTmodif->setDisabled(true); break; - case cyclicoligoketide: + case cyclicpolyketide: modificationsline->setDisabled(true); modificationsbutton->setDisabled(true); cyclicnterminus->setDisabled(true); cycliccterminus->setDisabled(true); enablescrambling->setDisabled(true); + regularblocksorder->setDisabled(false); searchedsequenceNtermmodif->setDisabled(true); searchedsequenceCtermmodif->setDisabled(true); searchedsequenceTmodif->setDisabled(true); break; -#endif - case linearpolysaccharide: - modificationsline->setDisabled(false); - modificationsbutton->setDisabled(false); - cyclicnterminus->setDisabled(true); - cycliccterminus->setDisabled(true); - enablescrambling->setDisabled(true); - searchedsequenceNtermmodif->setDisabled(false); - searchedsequenceCtermmodif->setDisabled(false); - searchedsequenceTmodif->setDisabled(true); - break; case other: + break; default: break; } @@ -1023,6 +1040,7 @@ void cParametersWidget::updateSettingsWhenModeChanged(int index) { precursoradduct->setDisabled(false); precursorcharge->setDisabled(false); precursormasserrortolerance->setDisabled(false); + fwhm->setDisabled(true); brickdatabaseline->setDisabled(false); brickdatabasebutton->setDisabled(false); maximumbricksincombinationbegin->setDisabled(false); @@ -1053,6 +1071,7 @@ void cParametersWidget::updateSettingsWhenModeChanged(int index) { precursoradduct->setDisabled(false); precursorcharge->setDisabled(false); precursormasserrortolerance->setDisabled(false); + fwhm->setDisabled(true); brickdatabaseline->setDisabled(false); brickdatabasebutton->setDisabled(false); maximumbricksincombinationbegin->setDisabled(true); @@ -1083,6 +1102,7 @@ void cParametersWidget::updateSettingsWhenModeChanged(int index) { precursoradduct->setDisabled(false); precursorcharge->setDisabled(false); precursormasserrortolerance->setDisabled(false); + fwhm->setDisabled(true); brickdatabaseline->setDisabled(false); brickdatabasebutton->setDisabled(false); maximumbricksincombinationbegin->setDisabled(true); @@ -1113,6 +1133,7 @@ void cParametersWidget::updateSettingsWhenModeChanged(int index) { precursoradduct->setDisabled(true); precursorcharge->setDisabled(false); precursormasserrortolerance->setDisabled(true); + fwhm->setDisabled(false); brickdatabaseline->setDisabled(true); brickdatabasebutton->setDisabled(true); maximumbricksincombinationbegin->setDisabled(true); @@ -1150,6 +1171,7 @@ void cParametersWidget::updateSettingsWhenModeChanged(int index) { break; } + oldmodetype = (eModeType)mode->currentIndex(); } @@ -1176,21 +1198,16 @@ void cParametersWidget::resetFragmentIonTypes() { start = a_ion; end = z_ion_dehydrated_and_deamidated; break; -#if OLIGOKETIDES == 1 - case linearoligoketide: + case linearpolyketide: start = l1h_ion; end = r2oh_ion_co_loss_dehydrated_and_deamidated; break; - case cyclicoligoketide: + case cyclicpolyketide: start = l1h_ion; // l0h_ion; end = l2h_ion_co_loss_dehydrated_and_deamidated; break; -#endif - case linearpolysaccharide: - start = ms_nterminal_ion_hplus; - end = ms_cterminal_ion_kplus; - break; case other: + break; default: break; } @@ -1223,26 +1240,20 @@ void cParametersWidget::resetFragmentIonTypes() { fragmentiontypes->getList()->item(i-start)->setSelected(true); } break; -#if OLIGOKETIDES == 1 - case linearoligoketide: + case linearpolyketide: if (((eFragmentIonType)i == l1h_ion) || ((eFragmentIonType)i == l2h_ion) || ((eFragmentIonType)i == r1h_ion) || ((eFragmentIonType)i == r2h_ion) || ((eFragmentIonType)i == l1oh_ion) || ((eFragmentIonType)i == l2oh_ion) || ((eFragmentIonType)i == r1oh_ion) || ((eFragmentIonType)i == r2oh_ion) ) { fragmentiontypes->getList()->item(i-start)->setSelected(true); } break; - case cyclicoligoketide: + case cyclicpolyketide: if (/*((eFragmentIonType)i == l0h_ion) ||*/ ((eFragmentIonType)i == l1h_ion) || ((eFragmentIonType)i == l2h_ion)) { fragmentiontypes->getList()->item(i-start)->setSelected(true); } break; -#endif - case linearpolysaccharide: - if (((eFragmentIonType)i == ms_nterminal_ion_hplus) || ((eFragmentIonType)i == ms_cterminal_ion_hplus)) { - fragmentiontypes->getList()->item(i-start)->setSelected(true); - } - break; case other: + break; default: break; } diff --git a/CycloBranch/gui/cParametersWidget.h b/CycloBranch/gui/cParametersWidget.h index c4f15c5..66465b8 100644 --- a/CycloBranch/gui/cParametersWidget.h +++ b/CycloBranch/gui/cParametersWidget.h @@ -139,6 +139,7 @@ class cParametersWidget : public QWidget QDoubleSpinBox* masserrortolerancefordeisotoping; QDoubleSpinBox* minimumrelativeintensitythreshold; QDoubleSpinBox* minimummz; + QDoubleSpinBox* fwhm; QFormLayout* brickdatabaseformlayout; QGroupBox* brickdatabasegroupbox; @@ -161,10 +162,12 @@ class cParametersWidget : public QWidget QCheckBox* cycliccterminus; QCheckBox* enablescrambling; QCheckBox* similaritysearch; + QCheckBox* regularblocksorder; QFormLayout* applicationformlayout; QGroupBox* applicationgroupbox; QComboBox* mode; + eModeType oldmodetype; QLineEdit* sequencedatabaseline; QPushButton* sequencedatabasebutton; QHBoxLayout* sequencedatabaselayout; diff --git a/CycloBranch/gui/cSequenceDatabaseProxyModel.cpp b/CycloBranch/gui/cSequenceDatabaseProxyModel.cpp new file mode 100644 index 0000000..71952a0 --- /dev/null +++ b/CycloBranch/gui/cSequenceDatabaseProxyModel.cpp @@ -0,0 +1,43 @@ +#include "gui/cSequenceDatabaseProxyModel.h" + + +cSequenceDatabaseProxyModel::cSequenceDatabaseProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { +} + + +bool cSequenceDatabaseProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { + int size = 10; + + for (int i = 2; i < size; i++) { + if (sourceModel()->data(sourceModel()->index(sourceRow, i, sourceParent)).toString().contains(filterRegExp())) { + return true; + } + } + + return false; +} + + +bool cSequenceDatabaseProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { + QVariant leftData = sourceModel()->data(left); + QVariant rightData = sourceModel()->data(right); + + if (left.column() == 0) { + return leftData.toInt() < rightData.toInt(); + } + + if (left.column() == 1) { + return getStringFromPeptideType((ePeptideType)leftData.toInt()) < getStringFromPeptideType((ePeptideType)rightData.toInt()); + } + + if (leftData.type() == QVariant::ByteArray) { + return leftData.toDouble() < rightData.toDouble(); + } + + if (leftData.type() == QVariant::String) { + return leftData.toString() < rightData.toString(); + } + + return QSortFilterProxyModel::lessThan(left, right); +} + diff --git a/CycloBranch/gui/cSequenceDatabaseProxyModel.h b/CycloBranch/gui/cSequenceDatabaseProxyModel.h new file mode 100644 index 0000000..d2f8b62 --- /dev/null +++ b/CycloBranch/gui/cSequenceDatabaseProxyModel.h @@ -0,0 +1,58 @@ +/** + \file cSequenceDatabaseProxyModel.h + \brief A proxy model for editor of database of sequences. +*/ + + +#ifndef _CSEQUENCEDATABASEPROXYMODEL_H +#define _CSEQUENCEDATABASEPROXYMODEL_H + +#include +#include +#include +#include "core/cFragmentIons.h" + + +/** + \brief A proxy model for editor of database of sequences. +*/ +class cSequenceDatabaseProxyModel : public QSortFilterProxyModel { + + Q_OBJECT + +public: + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cSequenceDatabaseProxyModel(QObject *parent = 0); + + +protected: + + + /** + \brief Reimplementation of filterAcceptsRow. + \param sourceRow int + \param sourceParent QModelIndex + \retval bool bool + */ + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE; + + + /** + \brief Reimplementation of lessThan. + \param left QModelIndex + \param right QModelIndex + \retval bool bool + */ + bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE; + + +}; + + +#endif + diff --git a/CycloBranch/gui/cSequenceDatabaseWidget.cpp b/CycloBranch/gui/cSequenceDatabaseWidget.cpp index b6ce155..a285561 100644 --- a/CycloBranch/gui/cSequenceDatabaseWidget.cpp +++ b/CycloBranch/gui/cSequenceDatabaseWidget.cpp @@ -2,8 +2,6 @@ #include "gui/cMainThread.h" #include "gui/cEventFilter.h" -#include -#include #include #include #include @@ -13,39 +11,26 @@ #include #include #include -#include #include #include #include +#include +#include cSequenceDatabaseWidget::cSequenceDatabaseWidget(QWidget* parent) { this->parent = parent; - setWindowTitle("Sequence Database Editor"); - setWindowIcon(QIcon(":/images/icons/26.png")); - - insertrow = new QPushButton(tr("Add Row")); - insertrow->setToolTip("Add a new row."); - insertrow->setShortcut(QKeySequence(Qt::Key_Insert)); - - removechecked = new QPushButton(tr(" Remove Rows ")); - removechecked->setToolTip("Remove selected rows."); - removechecked->setShortcut(QKeySequence(Qt::Key_Delete)); - - close = new QPushButton(tr("Close")); - close->setToolTip("Close the window."); - - load = new QPushButton(tr("Load")); - load->setToolTip("Load the database of sequences."); - load->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); + editorname = "Sequence Database Editor"; - save = new QPushButton(QString(" Save ")); - save->setToolTip("Save the database of sequences in the current file. When a file has not been loaded yet, the \"Save As ...\" file dialog is opened."); + setWindowTitle(editorname); + setWindowIcon(QIcon(":/images/icons/26.png")); - saveas = new QPushButton(tr("Save As...")); - saveas->setToolTip("Save the database of sequences into a file."); - saveas->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D)); + menuBar = new QMenuBar(this); + menuBar->setNativeMenuBar(false); + menuFile = new QMenu(tr("&File"), this); + menuEdit = new QMenu(tr("&Edit"), this); + menuHelp = new QMenu(tr("&Help"), this); rowsfilterline = new QLineEdit(); rowsfilterline->setMinimumWidth(250); @@ -76,60 +61,132 @@ cSequenceDatabaseWidget::cSequenceDatabaseWidget(QWidget* parent) { rowsfilterwidget->setLayout(rowsfilterhbox); rowsfilterwidget->setMaximumWidth(420); - buttons = new QHBoxLayout(); - buttons->addWidget(close); - buttons->addStretch(); - buttons->addWidget(insertrow); - buttons->addWidget(removechecked); - buttons->addStretch(); - buttons->addWidget(rowsfilterwidget); - buttons->addStretch(); - buttons->addWidget(load); - buttons->addWidget(save); - buttons->addWidget(saveas); - - database = new QTableWidget(0, 0, this); - database->setColumnCount(11); - database->setHorizontalHeaderItem(0, new QTableWidgetItem("")); - database->setHorizontalHeaderItem(1, new QTableWidgetItem("Type")); - database->setHorizontalHeaderItem(2, new QTableWidgetItem("Name")); - database->setHorizontalHeaderItem(3, new QTableWidgetItem("Summary Formula")); - database->setHorizontalHeaderItem(4, new QTableWidgetItem("Monoisotopic Mass")); - database->setItemDelegateForColumn(4, &columndelegate); - database->setHorizontalHeaderItem(5, new QTableWidgetItem("Sequence")); - database->setHorizontalHeaderItem(6, new QTableWidgetItem("N-terminal Modification")); - database->setHorizontalHeaderItem(7, new QTableWidgetItem("C-terminal Modification")); - database->setHorizontalHeaderItem(8, new QTableWidgetItem("Branch Modification")); - database->setHorizontalHeaderItem(9, new QTableWidgetItem("Reference")); - database->setHorizontalHeaderItem(10, new QTableWidgetItem("Preview")); - database->horizontalHeader()->setStretchLastSection(true); - for (int i = 0; i < database->columnCount(); i++) { - database->resizeColumnToContents(i); - } + database = new QTableView(this); + databasemodel = new QStandardItemModel(0, 0, this); + proxymodel = new cSequenceDatabaseProxyModel(this); + proxymodel->setSourceModel(databasemodel); + proxymodel->setDynamicSortFilter(false); + database->setModel(proxymodel); + database->setSortingEnabled(true); - headersort.resize(database->columnCount()); - for (int i = 0; i < database->columnCount(); i++) { - headersort[i] = -1; - } + resetHeader(); mainlayout = new QVBoxLayout(); mainlayout->addWidget(database); - mainlayout->addLayout(buttons); - - connect(database->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(headerItemDoubleClicked(int))); - connect(database, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(itemChanged(QTableWidgetItem *))); - connect(insertrow, SIGNAL(released()), this, SLOT(addRow())); - connect(removechecked, SIGNAL(released()), this, SLOT(removeCheckedRows())); - connect(close, SIGNAL(released()), this, SLOT(closeWindow())); - connect(load, SIGNAL(released()), this, SLOT(loadDatabase())); - connect(save, SIGNAL(released()), this, SLOT(saveDatabase())); - connect(saveas, SIGNAL(released()), this, SLOT(saveDatabaseAs())); + + mainwidget = new QWidget(); + mainwidget->setLayout(mainlayout); + + toolbarFile = addToolBar(tr("File")); + + actionNewDatabase = new QAction(QIcon(":/images/icons/2.png"), tr("&New Database"), this); + actionNewDatabase->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N)); + actionNewDatabase->setToolTip("New Database (Ctrl + N)"); + toolbarFile->addAction(actionNewDatabase); + connect(actionNewDatabase, SIGNAL(triggered()), this, SLOT(createNewDatabase())); + + actionOpenDatabase = new QAction(QIcon(":/images/icons/52.png"), tr("&Open Database"), this); + actionOpenDatabase->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_O)); + actionOpenDatabase->setToolTip("Open Database (Ctrl + O)"); + toolbarFile->addAction(actionOpenDatabase); + connect(actionOpenDatabase, SIGNAL(triggered()), this, SLOT(openDatabase())); + + actionSaveDatabase = new QAction(QIcon(":/images/icons/22.png"), tr("&Save Database..."), this); + actionSaveDatabase->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); + actionSaveDatabase->setToolTip("Save Database... (Ctrl + S)"); + toolbarFile->addAction(actionSaveDatabase); + connect(actionSaveDatabase, SIGNAL(triggered()), this, SLOT(saveDatabase())); + + actionSaveDatabaseAs = new QAction(QIcon(":/images/icons/86.png"), tr("Save &Database As..."), this); + actionSaveDatabaseAs->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D)); + actionSaveDatabaseAs->setToolTip("Save Database As... (Ctrl + D)"); + toolbarFile->addAction(actionSaveDatabaseAs); + connect(actionSaveDatabaseAs, SIGNAL(triggered()), this, SLOT(saveDatabaseAs())); + + actionImportDatabase = new QAction(QIcon(":/images/icons/63.png"), tr("&Import Database"), this); + actionImportDatabase->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_I)); + actionImportDatabase->setToolTip("Import Database (Ctrl + I)"); + toolbarFile->addAction(actionImportDatabase); + connect(actionImportDatabase, SIGNAL(triggered()), this, SLOT(importDatabase())); + + actionCloseWindow = new QAction(QIcon(":/images/icons/33.png"), tr("&Close"), this); + actionCloseWindow->setShortcut(QKeySequence(Qt::Key_Escape)); + actionCloseWindow->setToolTip("Close (Esc)"); + toolbarFile->addAction(actionCloseWindow); + connect(actionCloseWindow, SIGNAL(triggered()), this, SLOT(closeWindow())); + + toolbarEdit = addToolBar(tr("Edit")); + + actionAddRow = new QAction(QIcon(":/images/icons/13.png"), tr("&Insert Row"), this); + actionAddRow->setShortcut(QKeySequence(Qt::Key_Insert)); + actionAddRow->setToolTip("Insert Row (Insert)"); + toolbarEdit->addAction(actionAddRow); + connect(actionAddRow, SIGNAL(triggered()), this, SLOT(addRow())); + + actionRemoveSelectedRows = new QAction(QIcon(":/images/icons/14.png"), tr("&Remove Selected Rows"), this); + actionRemoveSelectedRows->setShortcut(QKeySequence(Qt::Key_Delete)); + actionRemoveSelectedRows->setToolTip("Remove Selected Rows (Delete)"); + toolbarEdit->addAction(actionRemoveSelectedRows); + connect(actionRemoveSelectedRows, SIGNAL(triggered()), this, SLOT(removeSelectedRows())); + + actionSelectAll = new QAction(QIcon(":/images/icons/38.png"), tr("Select &All"), this); + actionSelectAll->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_A)); + actionSelectAll->setToolTip("Select all rows (Ctrl + A)"); + toolbarEdit->addAction(actionSelectAll); + connect(actionSelectAll, SIGNAL(triggered()), this, SLOT(selectAll())); + + actionUnselectAll = new QAction(QIcon(":/images/icons/38b.png"), tr("&Unselect All"), this); + actionUnselectAll->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U)); + actionUnselectAll->setToolTip("Unselect all rows (Ctrl + U)"); + toolbarEdit->addAction(actionUnselectAll); + connect(actionUnselectAll, SIGNAL(triggered()), this, SLOT(unselectAll())); + + toolbarHelp = addToolBar(tr("Help")); + + actionHTMLDocumentation = new QAction(QIcon(":/images/icons/3.png"), tr("&HTML Documentation"), this); + actionHTMLDocumentation->setShortcut(QKeySequence(Qt::Key_F1)); + actionHTMLDocumentation->setToolTip("Show HTML Documentation (F1)"); + toolbarHelp->addAction(actionHTMLDocumentation); + connect(actionHTMLDocumentation, SIGNAL(triggered()), this, SLOT(showHTMLDocumentation())); + + toolbarFilter = addToolBar(tr("Filter")); + toolbarFilter->addWidget(rowsfilterwidget); + + menuFile->addAction(actionNewDatabase); + menuFile->addAction(actionOpenDatabase); + menuFile->addSeparator(); + menuFile->addAction(actionSaveDatabase); + menuFile->addAction(actionSaveDatabaseAs); + menuFile->addSeparator(); + menuFile->addAction(actionImportDatabase); + menuFile->addSeparator(); + menuFile->addAction(actionCloseWindow); + + menuEdit->addAction(actionAddRow); + menuEdit->addAction(actionRemoveSelectedRows); + menuEdit->addSeparator(); + menuEdit->addAction(actionSelectAll); + menuEdit->addAction(actionUnselectAll); + + menuHelp->addAction(actionHTMLDocumentation); + + menuBar->addMenu(menuFile); + menuBar->addMenu(menuEdit); + menuBar->addMenu(menuHelp); + + setMenuBar(menuBar); + + database->setMouseTracking(true); + connect(database, SIGNAL(entered(const QModelIndex&)), this, SLOT(editItem(const QModelIndex&))); + + connect(database->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(headerItemClicked(int))); + connect(databasemodel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(itemChanged(QStandardItem*))); connect(rowsfilterbutton, SIGNAL(released()), this, SLOT(filterRows())); connect(rowsfilterclearbutton, SIGNAL(released()), this, SLOT(resetFilter())); - setLayout(mainlayout); + setCentralWidget(mainwidget); - resize(1280, 700); + resize(1280, 750); databasefile = ""; @@ -146,20 +203,11 @@ cSequenceDatabaseWidget::cSequenceDatabaseWidget(QWidget* parent) { cSequenceDatabaseWidget::~cSequenceDatabaseWidget() { - deleteTable(false); - - for (int i = 0; i < database->columnCount(); i++) { - delete database->horizontalHeaderItem(i); - } - - database->setColumnCount(0); + deleteTable(); - delete insertrow; - delete removechecked; - delete close; - delete load; - delete save; - delete saveas; + delete databasemodel; + delete proxymodel; + delete database; delete rowsfilterline; delete rowsfiltercasesensitive; @@ -168,87 +216,100 @@ cSequenceDatabaseWidget::~cSequenceDatabaseWidget() { delete rowsfilterhbox; delete rowsfilterwidget; - delete database; - delete buttons; delete mainlayout; + delete mainwidget; + + delete actionNewDatabase; + delete actionOpenDatabase; + delete actionSaveDatabase; + delete actionSaveDatabaseAs; + delete actionImportDatabase; + delete actionCloseWindow; + delete actionAddRow; + delete actionRemoveSelectedRows; + delete actionSelectAll; + delete actionUnselectAll; + delete actionHTMLDocumentation; + + delete menuFile; + delete menuEdit; + delete menuHelp; + + delete menuBar; } void cSequenceDatabaseWidget::closeEvent(QCloseEvent *event) { closeWindow(); + event->accept(); } -void cSequenceDatabaseWidget::insertRow(int peptidetypeindex, QString sequence) { +void cSequenceDatabaseWidget::importSequence(int peptidetypeindex, QString sequence) { addRow(); - ((QComboBox *)(database->cellWidget(database->rowCount() - 1, 1)))->setCurrentIndex(peptidetypeindex); - database->item(database->rowCount() - 1, 5)->setText(sequence); + databasemodel->item(databasemodel->rowCount() - 1, 1)->setData(QVariant::fromValue(peptidetypeindex), Qt::DisplayRole); + databasemodel->item(databasemodel->rowCount() - 1, 5)->setText(sequence); - for (int i = 0; i < database->columnCount(); i++) { + for (int i = 0; i < databasemodel->columnCount(); i++) { database->resizeColumnToContents(i); } + database->setColumnWidth(1, 150); + database->setColumnWidth(2, 400); + database->setColumnWidth(5, 400); } -void cSequenceDatabaseWidget::deleteTable(bool enableprogress) { - QProgressDialog* progress; - cEventFilter filter; - int rowcount = database->rowCount(); - - if (enableprogress) { - progress = new QProgressDialog("Clearing the table...", 0, 0, rowcount, this); - progress->setMinimumWidth(250); - progress->installEventFilter(&filter); - progress->setMinimumDuration(0); - progress->setWindowModality(Qt::WindowModal); - progress->setValue(0); - } - - widgetitemallocator.reset(); - - for (int i = 0; i < rowcount; i++) { - delete database->cellWidget(rowcount - i - 1, 0); - delete database->cellWidget(rowcount - i - 1, 1); - delete database->cellWidget(rowcount - i - 1, 10); - - if (enableprogress) { - progress->setValue(i); +void cSequenceDatabaseWidget::deleteTable() { + for (int i = 0; i < databasemodel->columnCount(); i++) { + if (database->itemDelegateForColumn(i)) { + delete database->itemDelegateForColumn(i); } } - database->setRowCount(0); - - if (enableprogress) { - progress->setValue(rowcount); - delete progress; - } + databasemodel->clear(); + databasemodel->setRowCount(0); } -void cSequenceDatabaseWidget::removeRow(int row) { - for (int i = 0; i < database->columnCount(); i++) { - if ((i == 0) || (i == 1) || (i == 10)) { - delete database->cellWidget(row, i); - } - else { - database->takeItem(row, i); - } +void cSequenceDatabaseWidget::resetHeader() { + databasemodel->setColumnCount(11); + + databasemodel->setHorizontalHeaderItem(0, new QStandardItem()); + database->setItemDelegateForColumn(0, new cCheckBoxDelegate()); + databasemodel->setHorizontalHeaderItem(1, new QStandardItem("Type")); + database->setItemDelegateForColumn(1, new cComboBoxDelegate()); + databasemodel->setHorizontalHeaderItem(2, new QStandardItem("Name")); + databasemodel->setHorizontalHeaderItem(3, new QStandardItem("Summary Formula")); + databasemodel->setHorizontalHeaderItem(4, new QStandardItem("Monoisotopic Mass")); + databasemodel->setHorizontalHeaderItem(5, new QStandardItem("Sequence")); + databasemodel->setHorizontalHeaderItem(6, new QStandardItem("N-terminal Modification")); + databasemodel->setHorizontalHeaderItem(7, new QStandardItem("C-terminal Modification")); + databasemodel->setHorizontalHeaderItem(8, new QStandardItem("Branch Modification")); + databasemodel->setHorizontalHeaderItem(9, new QStandardItem("Reference")); + databasemodel->setHorizontalHeaderItem(10, new QStandardItem("View")); + database->setItemDelegateForColumn(10, new cViewButtonDelegate()); + + database->horizontalHeader()->setStretchLastSection(true); + for (int i = 0; i < databasemodel->columnCount(); i++) { + database->resizeColumnToContents(i); } - database->removeRow(row); + database->setColumnWidth(1, 150); + database->setColumnWidth(2, 400); + database->setColumnWidth(5, 400); } bool cSequenceDatabaseWidget::checkTable() { // check summary formulas - for (int i = 0; i < database->rowCount(); i++) { - if (!checkFormula(i, database->item(i, 3)->text().toStdString())) { + for (int i = 0; i < databasemodel->rowCount(); i++) { + if (!checkFormula(i, databasemodel->item(i, 3)->text().toStdString())) { return false; } } // check sequences - for (int i = 0; i < database->rowCount(); i++) { + for (int i = 0; i < databasemodel->rowCount(); i++) { if (!checkSequence(i)) { return false; } @@ -272,8 +333,8 @@ bool cSequenceDatabaseWidget::checkFormula(int row, const string& summary) { msgBox.exec(); return false; } - if (database->item(row, 4)) { - database->item(row, 4)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(formula.getMass())); + if (databasemodel->item(row, 4)) { + databasemodel->item(row, 4)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(formula.getMass())), Qt::DisplayRole); } return true; } @@ -281,25 +342,20 @@ bool cSequenceDatabaseWidget::checkFormula(int row, const string& summary) { bool cSequenceDatabaseWidget::checkSequence(int row) { - if (database->item(row, 5)->text().toStdString().compare("") == 0) { + if (databasemodel->item(row, 5)->text().toStdString().compare("") == 0) { return true; } regex rx; // [^\\[\\]]+ is used instead of .+ to prevent from a too complex regex error - switch ((ePeptideType)((QComboBox *)database->cellWidget(row, 1))->currentIndex()) + switch ((ePeptideType)(databasemodel->item(row, 1)->data(Qt::DisplayRole).toInt())) { case linear: - case linearpolysaccharide: -#if OLIGOKETIDES == 1 - case linearoligoketide: -#endif + case linearpolyketide: rx = "^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*$"; break; case cyclic: -#if OLIGOKETIDES == 1 - case cyclicoligoketide: -#endif + case cyclicpolyketide: rx = "^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])+$"; break; case branched: @@ -315,14 +371,14 @@ bool cSequenceDatabaseWidget::checkSequence(int row) { } try { - if (!(regex_search(database->item(row, 5)->text().toStdString(), rx))) { + if (!(regex_search(databasemodel->item(row, 5)->text().toStdString(), rx))) { QMessageBox msgBox; QString errstr = "Row no. "; errstr += to_string(row + 1).c_str(); errstr += ". The format of sequence '"; - errstr += database->item(row, 5)->text().toStdString().c_str(); + errstr += databasemodel->item(row, 5)->text().toStdString().c_str(); errstr += "' does not correspond to the sequence type '"; - errstr += getStringFromPeptideType((ePeptideType)((QComboBox *)database->cellWidget(row, 1))->currentIndex()).c_str(); + errstr += getStringFromPeptideType((ePeptideType)(databasemodel->item(row, 1)->data(Qt::DisplayRole).toInt())).c_str(); errstr += "'."; msgBox.setText(errstr); msgBox.exec(); @@ -336,7 +392,7 @@ bool cSequenceDatabaseWidget::checkSequence(int row) { errstr += ". cSequenceDatabaseWidget::checkSequence: regex_search failed, error no. "; errstr += to_string(e.code()).c_str(); errstr += ". Please, check the sequence: '"; - errstr += database->item(row, 5)->text().toStdString().c_str(); + errstr += databasemodel->item(row, 5)->text().toStdString().c_str(); errstr += "'."; msgBox.setText(errstr); msgBox.exec(); @@ -355,46 +411,32 @@ void cSequenceDatabaseWidget::setDataModified(bool datamodified) { this->datamodified = datamodified; if (datamodified) { - save->setText("*" + save->text()); + setWindowTitle("*" + windowTitle()); } else { - if ((save->text().size() > 0) && (save->text().at(0) == '*')) { - save->setText(save->text().toStdString().substr(1).c_str()); + if ((windowTitle().size() > 0) && (windowTitle().at(0) == '*')) { + setWindowTitle(windowTitle().toStdString().substr(1).c_str()); } } } void cSequenceDatabaseWidget::keyPressEvent(QKeyEvent *event) { - if (event->key() == Qt::Key_Escape) { - closeWindow(); - } - if ((event->key() == Qt::Key_Enter) || (event->key() == Qt::Key_Return)) { if (rowsfilterline->hasFocus()) { filterRows(); } } - if (event->key() == Qt::Key_F1) { - #if OS_TYPE == WIN - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/sequenceeditor.html").absoluteFilePath())); - #else - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/sequenceeditor.html").absoluteFilePath())); - #endif - } - if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_F)) { rowsfilterline->setFocus(); } - if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_N)) { + if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_T)) { rowsfiltercasesensitive->setChecked(!rowsfiltercasesensitive->isChecked()); } - if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_S)) { - saveDatabase(); - } + event->accept(); } @@ -414,14 +456,14 @@ void cSequenceDatabaseWidget::closeWindow() { } -void cSequenceDatabaseWidget::loadDatabase() { - QString filename = QFileDialog::getOpenFileName(this, tr("Load the Database of Sequences"), lastdir, tr("Database of Sequences (*.txt)")); +void cSequenceDatabaseWidget::openDatabase() { + QString filename = QFileDialog::getOpenFileName(this, tr("Open Database"), lastdir, tr("Database of Sequences (*.txt)")); if (!filename.isEmpty()) { lastdir = filename; databasefile = filename; - save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); + setWindowTitle(editorname + QString(" - ") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str())); inputstream.open(filename.toStdString().c_str()); @@ -432,7 +474,12 @@ void cSequenceDatabaseWidget::loadDatabase() { } else { - deleteTable(true); + string stmp; + size_t pos; + + deleteTable(); + resetHeader(); + resetFilter(); sequences.clear(); sequences.loadFromPlainTextStream(inputstream); @@ -444,63 +491,80 @@ void cSequenceDatabaseWidget::loadDatabase() { progress.setMinimumDuration(0); progress.setWindowModality(Qt::WindowModal); + database->setModel(0); + proxymodel->setSourceModel(0); + database->setSortingEnabled(false); + cSummaryFormula formula; - database->setRowCount(sequences.size()); + databasemodel->setRowCount(sequences.size()); for (int i = 0; i < sequences.size(); i++) { - QCheckBox* checkbox = new QCheckBox(); - database->setCellWidget(i, 0, checkbox); - - QComboBox* combo = new QComboBox(); - for (int j = 0; j <= (int)other; j++) { - combo->addItem(QString(getStringFromPeptideType((ePeptideType)j).c_str())); - } - combo->setCurrentIndex((int)sequences[i].getPeptideType()); - connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(comboBoxModified(int))); - database->setCellWidget(i, 1, combo); - - database->setItem(i, 2, widgetitemallocator.getNewItem()); - database->item(i, 2)->setText(sequences[i].getName().c_str()); - database->setItem(i, 3, widgetitemallocator.getNewItem()); - database->item(i, 3)->setText(sequences[i].getSummaryFormula().c_str()); + databasemodel->setItem(i, 0, new QStandardItem()); + databasemodel->item(i, 0)->setFlags(databasemodel->item(i, 0)->flags() & ~Qt::ItemIsEditable); - formula.setFormula(sequences[i].getSummaryFormula()); - database->setItem(i, 4, widgetitemallocator.getNewItem()); - database->item(i, 4)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(formula.getMass())); - - database->setItem(i, 5, widgetitemallocator.getNewItem()); - database->item(i, 5)->setText(sequences[i].getSequence().c_str()); - - database->setItem(i, 6, widgetitemallocator.getNewItem()); - database->item(i, 6)->setText(sequences[i].getNTterminalModification().c_str()); + databasemodel->setItem(i, 1, new QStandardItem()); + databasemodel->item(i, 1)->setData(QVariant::fromValue((int)sequences[i].getPeptideType()), Qt::DisplayRole); - database->setItem(i, 7, widgetitemallocator.getNewItem()); - database->item(i, 7)->setText(sequences[i].getCTterminalModification().c_str()); + databasemodel->setItem(i, 2, new QStandardItem()); + databasemodel->item(i, 2)->setText(sequences[i].getName().c_str()); - database->setItem(i, 8, widgetitemallocator.getNewItem()); - database->item(i, 8)->setText(sequences[i].getBranchModification().c_str()); + databasemodel->setItem(i, 3, new QStandardItem()); + databasemodel->item(i, 3)->setText(sequences[i].getSummaryFormula().c_str()); - database->setItem(i, 9, widgetitemallocator.getNewItem()); - database->item(i, 9)->setText(sequences[i].getReference().c_str()); - - database->setCellWidget(i, 10, new QLabel(sequences[i].getNameWithReferenceAsHTMLString().c_str())); - ((QLabel *)database->cellWidget(i, 10))->setTextFormat(Qt::RichText); - ((QLabel *)database->cellWidget(i, 10))->setTextInteractionFlags(Qt::TextBrowserInteraction); - ((QLabel *)database->cellWidget(i, 10))->setOpenExternalLinks(true); + formula.setFormula(sequences[i].getSummaryFormula()); + databasemodel->setItem(i, 4, new QStandardItem()); + databasemodel->item(i, 4)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(formula.getMass())), Qt::DisplayRole); + + databasemodel->setItem(i, 5, new QStandardItem()); + databasemodel->item(i, 5)->setText(sequences[i].getSequence().c_str()); + + databasemodel->setItem(i, 6, new QStandardItem()); + databasemodel->item(i, 6)->setText(sequences[i].getNTterminalModification().c_str()); + + databasemodel->setItem(i, 7, new QStandardItem()); + databasemodel->item(i, 7)->setText(sequences[i].getCTterminalModification().c_str()); + + databasemodel->setItem(i, 8, new QStandardItem()); + databasemodel->item(i, 8)->setText(sequences[i].getBranchModification().c_str()); + + databasemodel->setItem(i, 9, new QStandardItem()); + databasemodel->item(i, 9)->setText(sequences[i].getReference().c_str()); + + databasemodel->setItem(i, 10, new QStandardItem()); + databasemodel->item(i, 10)->setText(""); + stmp = sequences[i].getNameWithReferenceAsHTMLString(); + pos = stmp.find('\"'); + if (pos + 1 != string::npos) { + stmp = stmp.substr(pos + 1); + pos = stmp.rfind('\"'); + if (pos != string::npos) { + stmp = stmp.substr(0, pos); + databasemodel->item(i, 10)->setText(stmp.c_str()); + } + } progress.setValue(i); if (progress.wasCanceled()) { - deleteTable(true); + deleteTable(); + resetHeader(); sequences.clear(); databasefile = ""; - save->setText(" Save "); + setWindowTitle(editorname); break; } } - for (int i = 0; i < database->columnCount(); i++) { + proxymodel->setSourceModel(databasemodel); + database->setModel(proxymodel); + proxymodel->setSortRole(Qt::InitialSortOrderRole); + database->setSortingEnabled(true); + + for (int i = 0; i < databasemodel->columnCount(); i++) { database->resizeColumnToContents(i); } + database->setColumnWidth(1, 150); + database->setColumnWidth(2, 400); + database->setColumnWidth(5, 400); progress.setValue(sequences.size()); @@ -533,65 +597,63 @@ bool cSequenceDatabaseWidget::saveDatabase() { } else { - QProgressDialog progress("Saving the Sequence Database...", 0, 0, database->rowCount(), this); + QProgressDialog progress("Saving the Sequence Database...", 0, 0, proxymodel->rowCount(), this); progress.setMinimumWidth(250); cEventFilter filter; progress.installEventFilter(&filter); progress.setMinimumDuration(0); progress.setWindowModality(Qt::WindowModal); + // close an editor of a combobox + database->setDisabled(true); + database->setDisabled(false); + database->setFocus(); + cSequence seq; sequences.clear(); string s; - removeCheckedRows(); - - for (int i = 0; i < database->rowCount(); i++) { - - if (database->isRowHidden(i)) { - progress.setValue(i); - continue; - } + for (int i = 0; i < proxymodel->rowCount(); i++) { seq.clear(); - for (int j = 0; j < database->columnCount(); j++) { + for (int j = 0; j < proxymodel->columnCount(); j++) { switch (j) { case 0: // nothing to do break; case 1: - seq.setPeptideType((ePeptideType)(((QComboBox *)database->cellWidget(i,j))->currentIndex())); + seq.setPeptideType((ePeptideType)(proxymodel->index(i, j).data(Qt::DisplayRole).toInt())); break; case 2: - s = database->item(i,j)->text().toStdString(); + s = proxymodel->index(i, j).data(Qt::DisplayRole).toString().toStdString(); seq.setName(removeWhiteSpacesExceptSpaces(s)); break; case 3: - s = database->item(i,j)->text().toStdString(); + s = proxymodel->index(i, j).data(Qt::DisplayRole).toString().toStdString(); seq.setSummaryFormula(removeWhiteSpacesExceptSpaces(s)); break; case 4: // nothing to do break; case 5: - s = database->item(i,j)->text().toStdString(); + s = proxymodel->index(i, j).data(Qt::DisplayRole).toString().toStdString(); seq.setSequence(removeWhiteSpacesExceptSpaces(s)); break; case 6: - s = database->item(i,j)->text().toStdString(); + s = proxymodel->index(i, j).data(Qt::DisplayRole).toString().toStdString(); seq.setNTterminalModification(removeWhiteSpacesExceptSpaces(s)); break; case 7: - s = database->item(i,j)->text().toStdString(); + s = proxymodel->index(i, j).data(Qt::DisplayRole).toString().toStdString(); seq.setCTterminalModification(removeWhiteSpacesExceptSpaces(s)); break; case 8: - s = database->item(i,j)->text().toStdString(); + s = proxymodel->index(i, j).data(Qt::DisplayRole).toString().toStdString(); seq.setBranchModification(removeWhiteSpacesExceptSpaces(s)); break; case 9: - s = database->item(i,j)->text().toStdString(); + s = proxymodel->index(i, j).data(Qt::DisplayRole).toString().toStdString(); seq.setReference(removeWhiteSpacesExceptSpaces(s)); break; default: @@ -623,13 +685,13 @@ bool cSequenceDatabaseWidget::saveDatabaseAs() { return false; } - QString filename = QFileDialog::getSaveFileName(this, tr("Save the Database of Sequences As..."), lastdir, tr("Database of Sequences (*.txt)")); + QString filename = QFileDialog::getSaveFileName(this, tr("Save Database As..."), lastdir, tr("Database of Sequences (*.txt)")); if (!filename.isEmpty()) { lastdir = filename; databasefile = filename; - save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); + setWindowTitle(editorname + QString(" - ") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str())); return saveDatabase(); } @@ -638,41 +700,34 @@ bool cSequenceDatabaseWidget::saveDatabaseAs() { void cSequenceDatabaseWidget::addRow() { - int row = database->rowCount(); - database->insertRow(row); - - QCheckBox* checkbox = new QCheckBox(); - database->setCellWidget(row, 0, checkbox); - - QComboBox* combo = new QComboBox(); - for (int i = 0; i <= (int)other; i++) { - combo->addItem(QString(getStringFromPeptideType((ePeptideType)i).c_str())); - } - combo->setCurrentIndex((int)other); - connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(comboBoxModified(int))); - database->setCellWidget(row, 1, combo); - - database->setItem(row, 2, widgetitemallocator.getNewItem()); - database->setItem(row, 3, widgetitemallocator.getNewItem()); - database->setItem(row, 4, widgetitemallocator.getNewItem()); - database->setItem(row, 5, widgetitemallocator.getNewItem()); - database->setItem(row, 6, widgetitemallocator.getNewItem()); - database->setItem(row, 7, widgetitemallocator.getNewItem()); - database->setItem(row, 8, widgetitemallocator.getNewItem()); - database->setItem(row, 9, widgetitemallocator.getNewItem()); - - database->setCellWidget(row, 10, new QLabel()); - ((QLabel *)database->cellWidget(row, 10))->setTextFormat(Qt::RichText); - ((QLabel *)database->cellWidget(row, 10))->setTextInteractionFlags(Qt::TextBrowserInteraction); - ((QLabel *)database->cellWidget(row, 10))->setOpenExternalLinks(true); + resetFilter(); + + int row = databasemodel->rowCount(); + databasemodel->insertRow(row); + + databasemodel->setItem(row, 0, new QStandardItem()); + databasemodel->item(row, 0)->setFlags(databasemodel->item(row, 0)->flags() & ~Qt::ItemIsEditable); + + databasemodel->setItem(row, 1, new QStandardItem()); + databasemodel->setItem(row, 2, new QStandardItem()); + databasemodel->setItem(row, 3, new QStandardItem()); + databasemodel->setItem(row, 4, new QStandardItem()); + databasemodel->setItem(row, 5, new QStandardItem()); + databasemodel->setItem(row, 6, new QStandardItem()); + databasemodel->setItem(row, 7, new QStandardItem()); + databasemodel->setItem(row, 8, new QStandardItem()); + databasemodel->setItem(row, 9, new QStandardItem()); + databasemodel->setItem(row, 10, new QStandardItem()); + + database->scrollToBottom(); } -void cSequenceDatabaseWidget::removeCheckedRows() { +void cSequenceDatabaseWidget::removeSelectedRows() { int i = 0; - while (i < database->rowCount()) { - if (((QCheckBox *)(database->cellWidget(i, 0)))->isChecked()) { - removeRow(i); + while (i < proxymodel->rowCount()) { + if (proxymodel->index(i, 0).data(Qt::DisplayRole).toBool()) { + proxymodel->removeRow(i); setDataModified(true); } else { @@ -682,10 +737,14 @@ void cSequenceDatabaseWidget::removeCheckedRows() { } -void cSequenceDatabaseWidget::itemChanged(QTableWidgetItem* item) { +void cSequenceDatabaseWidget::itemChanged(QStandardItem* item) { + if (!item) { + return; + } + // recalculate mass when formula is changed if (item->column() == 3) { - checkFormula(item->row(), item->text().toStdString()); + checkFormula(item->row(), item->data(Qt::DisplayRole).toString().toStdString()); } // check sequence @@ -694,100 +753,234 @@ void cSequenceDatabaseWidget::itemChanged(QTableWidgetItem* item) { } // update references preview - if (((item->column() == 2) || (item->column() == 9)) && database->cellWidget(item->row(), 10)) { + if (((item->column() == 2) || (item->column() == 9)) && databasemodel->item(item->row(), 10)) { cSequence seq; - seq.setName(database->item(item->row(), 2)->text().toStdString()); - seq.setReference(database->item(item->row(), 9)->text().toStdString()); - ((QLabel *)database->cellWidget(item->row(), 10))->setText(seq.getNameWithReferenceAsHTMLString().c_str()); + string stmp; + size_t pos; + + seq.setName(databasemodel->index(item->row(), 2).data(Qt::DisplayRole).toString().toStdString()); + seq.setReference(databasemodel->index(item->row(), 9).data(Qt::DisplayRole).toString().toStdString()); + + stmp = seq.getNameWithReferenceAsHTMLString(); + pos = stmp.find('\"'); + if (pos + 1 != string::npos) { + stmp = stmp.substr(pos + 1); + pos = stmp.rfind('\"'); + if (pos != string::npos) { + stmp = stmp.substr(0, pos); + databasemodel->item(item->row(), 10)->setText(stmp.c_str()); + } + } + } - setDataModified(true); + if (item->column() > 0) { + setDataModified(true); + } } -void cSequenceDatabaseWidget::headerItemDoubleClicked(int index) { +void cSequenceDatabaseWidget::headerItemClicked(int index) { setDataModified(true); +} - if (headersort[index] == -1) { - database->sortByColumn(index, Qt::AscendingOrder); - headersort[index] = 1; - return; - } - if (headersort[index] == 0) { - database->sortByColumn(index, Qt::AscendingOrder); - headersort[index] = 1; - } - else { - database->sortByColumn(index, Qt::DescendingOrder); - headersort[index] = 0; - } +void cSequenceDatabaseWidget::filterRows() { + proxymodel->setFilterKeyColumn(-1); + proxymodel->setFilterCaseSensitivity(rowsfiltercasesensitive->isChecked()?Qt::CaseSensitive:Qt::CaseInsensitive); + proxymodel->setFilterFixedString(rowsfilterline->text()); } -void cSequenceDatabaseWidget::filterRows() { - Qt::CaseSensitivity casesensitive = rowsfiltercasesensitive->isChecked()?Qt::CaseSensitive:Qt::CaseInsensitive; - QString str = rowsfilterline->text(); - int rowcount = database->rowCount(); - bool match; - int i, j; - - QProgressDialog progress("Updating...", "Cancel", 0, rowcount, this); - progress.setMinimumWidth(250); - cEventFilter filter; - progress.installEventFilter(&filter); - progress.setMinimumDuration(0); - progress.setWindowModality(Qt::WindowModal); - - for (i = 0; i < rowcount; i++) { - - match = false; - for (j = 0; j < database->columnCount(); j++) { - // ignore non-text fields - if ((j == 0) || (j == 1) || (j == 10)) { - continue; - } +void cSequenceDatabaseWidget::resetFilter() { + rowsfilterline->setText(""); + + database->horizontalHeader()->setSortIndicator(-1, Qt::AscendingOrder); + proxymodel->sort(-1); + + proxymodel->setFilterKeyColumn(-1); + proxymodel->setFilterFixedString(""); +} + - if (database->item(i, j)->text().contains(str, casesensitive)) { - match = true; - break; +void cSequenceDatabaseWidget::createNewDatabase() { + if (datamodified) { + QMessageBox::StandardButton reply; + reply = QMessageBox::question(this, appname, "Save changes ?", QMessageBox::Yes|QMessageBox::No); + + if (reply == QMessageBox::Yes) { + if (!saveDatabase()) { + return; } } - database->setRowHidden(i, !match); - progress.setValue(i); + } + + deleteTable(); + resetHeader(); + resetFilter(); + sequences.clear(); + databasefile = ""; + setWindowTitle(editorname); + + setDataModified(false); +} + + +void cSequenceDatabaseWidget::importDatabase() { + QString filename = QFileDialog::getOpenFileName(this, tr("Import Database"), lastdir, tr("Database of Sequences (*.txt)")); + + if (!filename.isEmpty()) { + lastdir = filename; + + inputstream.open(filename.toStdString().c_str()); - if (progress.wasCanceled()) { + if (!inputstream.good()) { + QMessageBox msgBox; + msgBox.setText("Cannot open the file '" + filename + "'."); + msgBox.exec(); + } + else { resetFilter(); - break; + + string stmp; + size_t pos; + + cSequenceDatabase importedsequences; + importedsequences.loadFromPlainTextStream(inputstream); + + QProgressDialog progress("Importing the Sequence Database...", "Cancel", 0, importedsequences.size(), this); + progress.setMinimumWidth(250); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); + + database->setModel(0); + proxymodel->setSourceModel(0); + database->setSortingEnabled(false); + + cSummaryFormula formula; + int originalrowcount = databasemodel->rowCount(); + databasemodel->setRowCount(originalrowcount + importedsequences.size()); + for (int i = 0; i < importedsequences.size(); i++) { + + databasemodel->setItem(i + originalrowcount, 0, new QStandardItem()); + databasemodel->item(i + originalrowcount, 0)->setFlags(databasemodel->item(i + originalrowcount, 0)->flags() & ~Qt::ItemIsEditable); + + databasemodel->setItem(i + originalrowcount, 1, new QStandardItem()); + databasemodel->item(i + originalrowcount, 1)->setData(QVariant::fromValue((int)importedsequences[i].getPeptideType()), Qt::DisplayRole); + + databasemodel->setItem(i + originalrowcount, 2, new QStandardItem()); + databasemodel->item(i + originalrowcount, 2)->setText(importedsequences[i].getName().c_str()); + + databasemodel->setItem(i + originalrowcount, 3, new QStandardItem()); + databasemodel->item(i + originalrowcount, 3)->setText(importedsequences[i].getSummaryFormula().c_str()); + + formula.setFormula(importedsequences[i].getSummaryFormula()); + databasemodel->setItem(i + originalrowcount, 4, new QStandardItem()); + databasemodel->item(i + originalrowcount, 4)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(formula.getMass())), Qt::DisplayRole); + + databasemodel->setItem(i + originalrowcount, 5, new QStandardItem()); + databasemodel->item(i + originalrowcount, 5)->setText(importedsequences[i].getSequence().c_str()); + + databasemodel->setItem(i + originalrowcount, 6, new QStandardItem()); + databasemodel->item(i + originalrowcount, 6)->setText(importedsequences[i].getNTterminalModification().c_str()); + + databasemodel->setItem(i + originalrowcount, 7, new QStandardItem()); + databasemodel->item(i + originalrowcount, 7)->setText(importedsequences[i].getCTterminalModification().c_str()); + + databasemodel->setItem(i + originalrowcount, 8, new QStandardItem()); + databasemodel->item(i + originalrowcount, 8)->setText(importedsequences[i].getBranchModification().c_str()); + + databasemodel->setItem(i + originalrowcount, 9, new QStandardItem()); + databasemodel->item(i + originalrowcount, 9)->setText(importedsequences[i].getReference().c_str()); + + databasemodel->setItem(i + originalrowcount, 10, new QStandardItem()); + databasemodel->item(i + originalrowcount, 10)->setText(""); + stmp = importedsequences[i].getNameWithReferenceAsHTMLString(); + pos = stmp.find('\"'); + if (pos + 1 != string::npos) { + stmp = stmp.substr(pos + 1); + pos = stmp.rfind('\"'); + if (pos != string::npos) { + stmp = stmp.substr(0, pos); + databasemodel->item(i + originalrowcount, 10)->setText(stmp.c_str()); + } + } + + sequences.push_back(importedsequences[i]); + + progress.setValue(i); + if (progress.wasCanceled()) { + deleteTable(); + resetHeader(); + sequences.clear(); + databasefile = ""; + setWindowTitle(editorname); + break; + } + } + + proxymodel->setSourceModel(databasemodel); + database->setModel(proxymodel); + proxymodel->setSortRole(Qt::InitialSortOrderRole); + database->setSortingEnabled(true); + + for (int i = 0; i < databasemodel->columnCount(); i++) { + database->resizeColumnToContents(i); + } + database->setColumnWidth(1, 150); + database->setColumnWidth(2, 400); + database->setColumnWidth(5, 400); + + if (progress.wasCanceled()) { + setDataModified(false); + } + else { + setDataModified(true); + } + + progress.setValue(importedsequences.size()); + } - } + inputstream.close(); - progress.setValue(rowcount); + } } -void cSequenceDatabaseWidget::resetFilter() { - rowsfilterline->setText(""); - int rowcount = database->rowCount(); +void cSequenceDatabaseWidget::selectAll() { + for (int i = 0; i < proxymodel->rowCount(); i++) { + databasemodel->itemFromIndex(proxymodel->mapToSource(proxymodel->index(i, 0)))->setData(QVariant::fromValue(true), Qt::DisplayRole); + } +} - QProgressDialog progress("Updating...", 0, 0, rowcount, this); - progress.setMinimumWidth(250); - cEventFilter filter; - progress.installEventFilter(&filter); - progress.setMinimumDuration(0); - progress.setWindowModality(Qt::WindowModal); - for (int i = 0; i < rowcount; i++) { - database->setRowHidden(i, false); - progress.setValue(i); +void cSequenceDatabaseWidget::unselectAll() { + for (int i = 0; i < proxymodel->rowCount(); i++) { + databasemodel->itemFromIndex(proxymodel->mapToSource(proxymodel->index(i, 0)))->setData(QVariant::fromValue(false), Qt::DisplayRole); } +} + - progress.setValue(rowcount); +void cSequenceDatabaseWidget::showHTMLDocumentation() { + #if OS_TYPE == WIN + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/sequenceeditor.html").absoluteFilePath())); + #else + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/sequenceeditor.html").absoluteFilePath())); + #endif } -void cSequenceDatabaseWidget::comboBoxModified(int index) { - setDataModified(true); +void cSequenceDatabaseWidget::editItem(const QModelIndex& index) { + if (isActiveWindow()) { + database->setDisabled(true); + database->setDisabled(false); + database->setFocus(); + if (index.column() == 1) { + database->edit(index); + } + } } diff --git a/CycloBranch/gui/cSequenceDatabaseWidget.h b/CycloBranch/gui/cSequenceDatabaseWidget.h index 01c2881..92ae214 100644 --- a/CycloBranch/gui/cSequenceDatabaseWidget.h +++ b/CycloBranch/gui/cSequenceDatabaseWidget.h @@ -1,6 +1,6 @@ /** \file cSequenceDatabaseWidget.h - \brief Visualization of the database of sequences. + \brief An editor of sequences database. */ @@ -11,31 +11,34 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include "core/utilities.h" #include "core/cSequenceDatabase.h" -#include "core/cAllocator.h" -#include "gui/cDelegate.h" - - -using namespace std; -using namespace boost; +#include "gui/cSequenceDatabaseProxyModel.h" +#include "gui/cViewButtonDelegate.h" +#include "gui/cCheckBoxDelegate.h" +#include "gui/cComboBoxDelegate.h" // forward declaration class QHBoxLayout; class QVBoxLayout; -class QTableWidget; -class QTableWidgetItem; class QPushButton; class QLineEdit; -class QCheckBox; +class QMenuBar; +class QMenu; /** - \brief Visualization of the database of sequences. + \brief An editor of sequences database. */ -class cSequenceDatabaseWidget : public QWidget +class cSequenceDatabaseWidget : public QMainWindow { Q_OBJECT @@ -63,23 +66,42 @@ class cSequenceDatabaseWidget : public QWidget /** - \brief Insert a new row, set its peptide type and sequence. + \brief Import a new sequence. \param peptidetypeindex an index of current peptide type \param sequence sequence */ - void insertRow(int peptidetypeindex, QString sequence); + void importSequence(int peptidetypeindex, QString sequence); private: + QString editorname; + QWidget* parent; - QPushButton* insertrow; - QPushButton* removechecked; - QPushButton* close; - QPushButton* load; - QPushButton* save; - QPushButton* saveas; + QMenuBar* menuBar; + QMenu* menuFile; + QMenu* menuEdit; + QMenu* menuHelp; + + QToolBar* toolbarFile; + QAction* actionNewDatabase; + QAction* actionOpenDatabase; + QAction* actionSaveDatabase; + QAction* actionSaveDatabaseAs; + QAction* actionImportDatabase; + QAction* actionCloseWindow; + + QToolBar* toolbarEdit; + QAction* actionAddRow; + QAction* actionRemoveSelectedRows; + QAction* actionSelectAll; + QAction* actionUnselectAll; + + QToolBar* toolbarHelp; + QAction* actionHTMLDocumentation; + + QToolBar* toolbarFilter; QWidget* rowsfilterwidget; QHBoxLayout* rowsfilterhbox; QLineEdit* rowsfilterline; @@ -87,9 +109,11 @@ class cSequenceDatabaseWidget : public QWidget QPushButton* rowsfilterbutton; QPushButton* rowsfilterclearbutton; - QTableWidget* database; - QHBoxLayout* buttons; + QTableView* database; + QStandardItemModel* databasemodel; + cSequenceDatabaseProxyModel* proxymodel; QVBoxLayout* mainlayout; + QWidget* mainwidget; QString databasefile; QString lastdir; @@ -97,16 +121,11 @@ class cSequenceDatabaseWidget : public QWidget ofstream outputstream; cSequenceDatabase sequences; - vector headersort; - cDelegate columndelegate; - - cAllocator widgetitemallocator; - bool datamodified; - void deleteTable(bool enableprogress); + void deleteTable(); - void removeRow(int row); + void resetHeader(); bool checkTable(); @@ -131,7 +150,7 @@ private slots: void closeWindow(); - void loadDatabase(); + void openDatabase(); bool saveDatabase(); @@ -139,17 +158,27 @@ private slots: void addRow(); - void removeCheckedRows(); + void removeSelectedRows(); - void itemChanged(QTableWidgetItem* item); + void itemChanged(QStandardItem* item); - void headerItemDoubleClicked(int index); + void headerItemClicked(int index); void filterRows(); void resetFilter(); - void comboBoxModified(int index); + void createNewDatabase(); + + void importDatabase(); + + void selectAll(); + + void unselectAll(); + + void showHTMLDocumentation(); + + void editItem(const QModelIndex& index); }; diff --git a/CycloBranch/gui/cSpectrumDetailProxyModel.cpp b/CycloBranch/gui/cSpectrumDetailProxyModel.cpp new file mode 100644 index 0000000..aa7a732 --- /dev/null +++ b/CycloBranch/gui/cSpectrumDetailProxyModel.cpp @@ -0,0 +1,61 @@ +#include "gui/cSpectrumDetailProxyModel.h" + + +cSpectrumDetailProxyModel::cSpectrumDetailProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { + hidematched = false; + hideunmatched = false; + hidescrambled = false; +} + + +void cSpectrumDetailProxyModel::setFlags(bool hidematched, bool hideunmatched, bool hidescrambled) { + this->hidematched = hidematched; + this->hideunmatched = hideunmatched; + this->hidescrambled = hidescrambled; +} + + +bool cSpectrumDetailProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { + bool show = true; + + if (hidematched + && ((QStandardItemModel *)sourceModel())->item(sourceRow, 1) + && ((QStandardItemModel *)sourceModel())->item(sourceRow, 2) + && !((QStandardItemModel *)sourceModel())->item(sourceRow, 1)->data(Qt::DisplayRole).toString().isEmpty() + && !((QStandardItemModel *)sourceModel())->item(sourceRow, 2)->data(Qt::DisplayRole).toString().isEmpty() + ) { + show = false; + } + + if (hideunmatched && ( + (((QStandardItemModel *)sourceModel())->item(sourceRow, 1) == 0) + || (((QStandardItemModel *)sourceModel())->item(sourceRow, 2) == 0) + || ((QStandardItemModel *)sourceModel())->item(sourceRow, 1)->data(Qt::DisplayRole).toString().isEmpty() + || ((QStandardItemModel *)sourceModel())->item(sourceRow, 2)->data(Qt::DisplayRole).toString().isEmpty() + )) { + show = false; + } + + if (hidescrambled && ((QStandardItemModel *)sourceModel())->item(sourceRow, 0) && (sourceModel()->data(sourceModel()->index(sourceRow, 0, sourceParent)).toString().contains(filterRegExp()))) { + show = false; + } + + return show; +} + + +bool cSpectrumDetailProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { + QVariant leftData = sourceModel()->data(left); + QVariant rightData = sourceModel()->data(right); + + if (leftData.type() == QVariant::ByteArray) { + return leftData.toDouble() < rightData.toDouble(); + } + + if (leftData.type() == QVariant::String) { + return leftData.toString() < rightData.toString(); + } + + return QSortFilterProxyModel::lessThan(left, right); +} + diff --git a/CycloBranch/gui/cSpectrumDetailProxyModel.h b/CycloBranch/gui/cSpectrumDetailProxyModel.h new file mode 100644 index 0000000..39e1a85 --- /dev/null +++ b/CycloBranch/gui/cSpectrumDetailProxyModel.h @@ -0,0 +1,70 @@ +/** + \file cSpectrumDetailProxyModel.h + \brief A table proxy model. +*/ + + +#ifndef _CSPECTRUMDETAILPROXYMODEL_H +#define _CSPECTRUMDETAILPROXYMODEL_H + +#include +#include +#include +#include + + +/** + \brief A table proxy model. +*/ +class cSpectrumDetailProxyModel : public QSortFilterProxyModel { + + Q_OBJECT + +private: + + bool hidematched, hideunmatched, hidescrambled; + +public: + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cSpectrumDetailProxyModel(QObject *parent = 0); + + + /** + \brief Set the flags for filtering. + \param hidematched hide matched peaks + \param hideunmatched hide unmatched peaks + \param hidescrambled hide scrambled peaks + */ + void setFlags(bool hidematched, bool hideunmatched, bool hidescrambled); + + +protected: + + + /** + \brief Reimplementation of filterAcceptsRow. + \param sourceRow int + \param sourceParent QModelIndex + \retval bool bool + */ + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE; + + + /** + \brief Reimplementation of lessThan. + \param left QModelIndex + \param right QModelIndex + \retval bool bool + */ + bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE; + +}; + + +#endif + diff --git a/CycloBranch/gui/cSpectrumDetailWidget.cpp b/CycloBranch/gui/cSpectrumDetailWidget.cpp index 8434d30..9aaba1f 100644 --- a/CycloBranch/gui/cSpectrumDetailWidget.cpp +++ b/CycloBranch/gui/cSpectrumDetailWidget.cpp @@ -121,21 +121,14 @@ string cSpectrumDetailWidget::getDetailsAsHTMLString() { s += "

"; s += "Branch Modification: " + bname + "
"; break; -#if OLIGOKETIDES == 1 - case linearoligoketide: + case linearpolyketide: s += "

"; s += "Left Modification: " + lname + "
"; s += "Right Modification: " + rname + "
"; break; - case cyclicoligoketide: + case cyclicpolyketide: s += "
"; break; -#endif - case linearpolysaccharide: - s += "

"; - s += "N-terminal Modification: " + lname + "
"; - s += "C-terminal Modification: " + rname + "
"; - break; case other: break; default: @@ -370,7 +363,12 @@ string cSpectrumDetailWidget::getPartialPeaksTableAsHTMLString(int id) { secondspace = (int)peak->description.find(' ', peak->description.find(' ') + 1); s += printHTMLTableCell(peak->description.substr(0, secondspace), isred); } - else { + + if (parameters->mode == denovoengine) { + s += printHTMLTableCell(to_string(theoreticalspectrum->getPathId() + 1), isred); + } + + if (parameters->mode != dereplication) { s += printHTMLTableCell(peak->description.substr(0, peak->description.find(':')), isred); } @@ -434,30 +432,15 @@ cSpectrumDetailWidget::~cSpectrumDetailWidget() { delete textbrowser; - //QProgressDialog progress("Clearing the peaklist...", /*"Cancel"*/0, 0, peakstable->rowCount(), this); - //progress.setMinimumWidth(250); - //cEventFilter filter; - //progress.installEventFilter(&filter); - //progress.setMinimumDuration(0); - //progress.setWindowModality(Qt::WindowModal); - - widgetitemallocator.reset(); - - if (parameters->mode == dereplication) { - for (int i = 0; i < peakstable->rowCount(); i++) { - if (peakstable->cellWidget(i, 7)) { - delete peakstable->cellWidget(i, 7); - } - - //progress.setValue(i); - //if (progress.wasCanceled()) { - // break; - //} + for (int i = 0; i < peakstablemodel->columnCount(); i++) { + if (peakstable->itemDelegateForColumn(i)) { + delete peakstable->itemDelegateForColumn(i); } } + peakstablemodel->clear(); - //progress.setValue(peakstable->rowCount()); - + delete peakstablemodel; + delete proxymodel; delete peakstable; delete labelmz; @@ -483,15 +466,11 @@ cSpectrumDetailWidget::~cSpectrumDetailWidget() { switch (parameters->peptidetype) { case linear: -#if OLIGOKETIDES == 1 - case linearoligoketide: -#endif + case linearpolyketide: delete linearwidget; break; case cyclic: -#if OLIGOKETIDES == 1 - case cyclicoligoketide: -#endif + case cyclicpolyketide: delete cyclicwidget; break; case branched: @@ -500,8 +479,6 @@ cSpectrumDetailWidget::~cSpectrumDetailWidget() { case branchcyclic: delete branchcyclicwidget; break; - case linearpolysaccharide: - break; case other: break; default: @@ -536,6 +513,7 @@ cSpectrumDetailWidget::~cSpectrumDetailWidget() { void cSpectrumDetailWidget::closeEvent(QCloseEvent *event) { hide(); + event->accept(); } @@ -557,15 +535,11 @@ void cSpectrumDetailWidget::prepareToShow(ePeptideType peptidetype) { switch (peptidetype) { case linear: -#if OLIGOKETIDES == 1 - case linearoligoketide: -#endif + case linearpolyketide: linearwidget = new cLinearWidget(); break; case cyclic: -#if OLIGOKETIDES == 1 - case cyclicoligoketide: -#endif + case cyclicpolyketide: cyclicwidget = new cCyclicWidget(); break; case branched: @@ -574,8 +548,6 @@ void cSpectrumDetailWidget::prepareToShow(ePeptideType peptidetype) { case branchcyclic: branchcyclicwidget = new cBranchCyclicWidget(); break; - case linearpolysaccharide: - break; case other: break; default: @@ -692,7 +664,13 @@ void cSpectrumDetailWidget::prepareToShow(ePeptideType peptidetype) { textbrowser->setAcceptRichText(true); textbrowser->setOpenExternalLinks(true); - peakstable = new QTableWidget(0, 0, this); + peakstable = new QTableView(this); + peakstablemodel = new QStandardItemModel(0, 0, this); + proxymodel = new cSpectrumDetailProxyModel(this); + proxymodel->setSourceModel(peakstablemodel); + proxymodel->setDynamicSortFilter(false); + peakstable->setModel(proxymodel); + peakstable->setSortingEnabled(true); labelmz = new QLabel(tr("View m/z (from - to): ")); @@ -779,11 +757,7 @@ void cSpectrumDetailWidget::prepareToShow(ePeptideType peptidetype) { if (parameters && ((parameters->mode == denovoengine) || (parameters->mode == singlecomparison) || (parameters->mode == databasesearch))) { // cyclic -#if OLIGOKETIDES == 1 - if (theoreticalspectrum && ((parameters->peptidetype == cyclic) || (parameters->peptidetype == cyclicoligoketide))) { -#else - if (theoreticalspectrum && (parameters->peptidetype == cyclic)) { -#endif + if (theoreticalspectrum && ((parameters->peptidetype == cyclic) || (parameters->peptidetype == cyclicpolyketide))) { int r = (int)theoreticalspectrum->getCandidate().getAcronyms().size(); int hint = (int)theoreticalspectrum->getVisualCoverage().size()/(2*r); @@ -881,15 +855,11 @@ void cSpectrumDetailWidget::prepareToShow(ePeptideType peptidetype) { switch (peptidetype) { case linear: -#if OLIGOKETIDES == 1 - case linearoligoketide: -#endif + case linearpolyketide: hsplitter1->addWidget(linearwidget); break; case cyclic: -#if OLIGOKETIDES == 1 - case cyclicoligoketide: -#endif + case cyclicpolyketide: hsplitter1->addWidget(cyclicwidget); break; case branched: @@ -898,8 +868,6 @@ void cSpectrumDetailWidget::prepareToShow(ePeptideType peptidetype) { case branchcyclic: hsplitter1->addWidget(branchcyclicwidget); break; - case linearpolysaccharide: - break; case other: break; default: @@ -924,7 +892,7 @@ void cSpectrumDetailWidget::prepareToShow(ePeptideType peptidetype) { finddialog = new cFindDialog(this); exportdialog = new cExportDialog(this); - resize(1280, 700); + resize(1280, 750); if (parameters && theoreticalspectrum) { @@ -933,15 +901,11 @@ void cSpectrumDetailWidget::prepareToShow(ePeptideType peptidetype) { switch (peptidetype) { case linear: -#if OLIGOKETIDES == 1 - case linearoligoketide: -#endif + case linearpolyketide: linearwidget->initialize(parameters, theoreticalspectrum); break; case cyclic: -#if OLIGOKETIDES == 1 - case cyclicoligoketide: -#endif + case cyclicpolyketide: cyclicwidget->initialize(parameters, theoreticalspectrum); break; case branched: @@ -950,8 +914,6 @@ void cSpectrumDetailWidget::prepareToShow(ePeptideType peptidetype) { case branchcyclic: branchcyclicwidget->initialize(parameters, theoreticalspectrum); break; - case linearpolysaccharide: - break; case other: break; default: @@ -999,39 +961,37 @@ void cSpectrumDetailWidget::findAll(const QString& str, QTextDocument::FindFlags textbrowser->setExtraSelections(extraSelections); - // table cTablePosition tpos; - for (int i = 0; i < peakstable->rowCount(); i++) { + QStandardItem* item; + for (int i = 0; i < proxymodel->rowCount(); i++) { - if (peakstable->isRowHidden(i)) { - continue; - } + for (int j = 0; j < ((parameters->mode == dereplication)?peakstablemodel->columnCount() - 1:peakstablemodel->columnCount()); j++) { + item = peakstablemodel->itemFromIndex(proxymodel->mapToSource(proxymodel->index(i, j))); - for (int j = 0; j < peakstable->columnCount(); j++) { - if (!peakstable->item(i, j)) { + if (!item) { continue; } - peakstable->item(i, j)->setBackgroundColor(Qt::white); + item->setBackground(QBrush(Qt::white)); if (str.isEmpty()) { continue; } if (opt & QTextDocument::FindWholeWords) { - if (peakstable->item(i, j)->text().compare(str, (opt & QTextDocument::FindCaseSensitively)?Qt::CaseSensitive:Qt::CaseInsensitive) == 0) { + if (item->text().compare(str, (opt & QTextDocument::FindCaseSensitively)?Qt::CaseSensitive:Qt::CaseInsensitive) == 0) { tpos.row = i; tpos.column = j; tablematches.push_back(tpos); - peakstable->item(i, j)->setBackgroundColor(color); + item->setBackground(QBrush(color)); } } else { - if (peakstable->item(i, j)->text().contains(str, (opt & QTextDocument::FindCaseSensitively)?Qt::CaseSensitive:Qt::CaseInsensitive)) { + if (item->text().contains(str, (opt & QTextDocument::FindCaseSensitively)?Qt::CaseSensitive:Qt::CaseInsensitive)) { tpos.row = i; tpos.column = j; tablematches.push_back(tpos); - peakstable->item(i, j)->setBackgroundColor(color); + item->setBackground(QBrush(color)); } } } @@ -1065,8 +1025,8 @@ void cSpectrumDetailWidget::findAll(const QString& str, QTextDocument::FindFlags if (tablematches.size() > 0) { peakstable->setFocus(); - peakstable->scrollToItem(peakstable->item(tablematches[0].row, tablematches[0].column)); - peakstable->item(tablematches[0].row, tablematches[0].column)->setSelected(true); + peakstable->scrollTo(proxymodel->index(tablematches[0].row, tablematches[0].column)); + peakstable->selectionModel()->select(proxymodel->index(tablematches[0].row, tablematches[0].column), QItemSelectionModel::Select); } } @@ -1090,6 +1050,72 @@ void cSpectrumDetailWidget::keyPressEvent(QKeyEvent *event) { if ((event->key() == Qt::Key_Enter) || (event->key() == Qt::Key_Return)) { setMZInterval(); } + + if ((event->key() == Qt::Key_F1) && parameters) { + #if OS_TYPE == WIN + if (parameters->mode == dereplication) { + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/dereplication.html").absoluteFilePath())); + } + else { + switch (parameters->peptidetype) { + case linear: + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/lineardetail.html").absoluteFilePath())); + break; + case cyclic: + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/cyclicdetail.html").absoluteFilePath())); + break; + case branched: + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/brancheddetail.html").absoluteFilePath())); + break; + case branchcyclic: + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/branchcyclicdetail.html").absoluteFilePath())); + break; + case linearpolyketide: + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/linearketidedetail.html").absoluteFilePath())); + break; + case cyclicpolyketide: + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/cyclicketidedetail.html").absoluteFilePath())); + break; + case other: + break; + default: + break; + } + } + #else + if (parameters->mode == dereplication) { + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/dereplication.html").absoluteFilePath())); + } + else { + switch (parameters->peptidetype) { + case linear: + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/lineardetail.html").absoluteFilePath())); + break; + case cyclic: + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/cyclicdetail.html").absoluteFilePath())); + break; + case branched: + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/brancheddetail.html").absoluteFilePath())); + break; + case branchcyclic: + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/branchcyclicdetail.html").absoluteFilePath())); + break; + case linearpolyketide: + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/linearketidedetail.html").absoluteFilePath())); + break; + case cyclicpolyketide: + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/cyclicketidedetail.html").absoluteFilePath())); + break; + case other: + break; + default: + break; + } + } + #endif + } + + event->accept(); } @@ -1098,48 +1124,44 @@ void cSpectrumDetailWidget::preparePeaksTable() { peakstable->setEditTriggers(QAbstractItemView::NoEditTriggers); peakstable->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); peakstable->horizontalHeader()->setSectionsMovable(true); - //peakstable->setSelectionMode(QAbstractItemView::SingleSelection); + peakstable->setSelectionMode(QAbstractItemView::SingleSelection); + peakstable->verticalHeader()->setDefaultSectionSize(25); if (parameters->mode == dereplication) { - peakstable->setColumnCount(8); + peakstablemodel->setColumnCount(8); } else { - peakstable->setColumnCount(6); + peakstablemodel->setColumnCount(6); } - for (int i = 0; i < peakstable->columnCount(); i++) { - peakstable->setHorizontalHeaderItem(i, widgetitemallocator.getNewItem()); + for (int i = 0; i < peakstablemodel->columnCount(); i++) { + peakstablemodel->setHorizontalHeaderItem(i, new QStandardItem()); } - peakstable->horizontalHeaderItem(1)->setText("Theoretical m/z"); - peakstable->setItemDelegateForColumn(1, &columndelegate); - - peakstable->horizontalHeaderItem(2)->setText("Experimental m/z"); - peakstable->setItemDelegateForColumn(2, &columndelegate); - - peakstable->horizontalHeaderItem(3)->setText("Intensity [%]"); - peakstable->setItemDelegateForColumn(3, &columndelegate); - - peakstable->horizontalHeaderItem(4)->setText("Error [ppm]"); - peakstable->setItemDelegateForColumn(4, &columndelegate); + peakstablemodel->horizontalHeaderItem(1)->setText("Theoretical m/z"); + peakstablemodel->horizontalHeaderItem(2)->setText("Experimental m/z"); + peakstablemodel->horizontalHeaderItem(3)->setText("Intensity [%]"); + peakstablemodel->horizontalHeaderItem(4)->setText("Error [ppm]"); if (parameters->mode == dereplication) { - peakstable->horizontalHeaderItem(0)->setText("Ion Type"); - peakstable->horizontalHeaderItem(5)->setText("Summary Formula"); - peakstable->horizontalHeaderItem(6)->setText("Name"); - peakstable->horizontalHeaderItem(7)->setText("Reference"); + peakstablemodel->horizontalHeaderItem(0)->setText("Ion Type"); + peakstablemodel->horizontalHeaderItem(5)->setText("Summary Formula"); + peakstablemodel->horizontalHeaderItem(6)->setText("Name"); + peakstablemodel->horizontalHeaderItem(7)->setText("Reference"); + peakstable->setItemDelegateForColumn(7, new cViewButtonDelegate()); } else { - peakstable->horizontalHeaderItem(0)->setText("Fragment Type"); - peakstable->horizontalHeaderItem(5)->setText("Sequence"); + peakstablemodel->horizontalHeaderItem(0)->setText("Fragment Type"); + peakstablemodel->horizontalHeaderItem(5)->setText("Sequence"); } - connect(peakstable->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(headerItemDoubleClicked(int))); + connect(peakstable->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(headerItemClicked(int))); cPeaksList* thpeaks; int thpeakscount; cPeak* peak; - int secondspace, langle, rangle, tmp1, tmp2; + int secondspace, langle, rangle, tmp; + string stmp; QBrush brush; if (parameters->mode == dereplication) { @@ -1157,7 +1179,7 @@ void cSpectrumDetailWidget::preparePeaksTable() { thpeakscount = theoreticalspectrum->getTheoreticalPeaks()->size(); } - peakstable->setRowCount(thpeakscount + theoreticalspectrum->getUnmatchedPeaks()->size()); + peakstablemodel->setRowCount(thpeakscount + theoreticalspectrum->getUnmatchedPeaks()->size()); QProgressDialog progress("Preparing the peaklist...", /*"Cancel"*/0, 0, thpeakscount + theoreticalspectrum->getUnmatchedPeaks()->size(), parent); progress.setMinimumWidth(250); @@ -1166,9 +1188,12 @@ void cSpectrumDetailWidget::preparePeaksTable() { progress.setMinimumDuration(0); progress.setWindowModality(Qt::WindowModal); + peakstable->setModel(0); + proxymodel->setSourceModel(0); + peakstable->setSortingEnabled(false); + // theoretical peaks for (int i = 0; i < thpeakscount; i++) { - peakstable->setRowHeight(i, 20); peak = &((*thpeaks)[i]); if (peak->matchedmz > 0) { @@ -1181,62 +1206,64 @@ void cSpectrumDetailWidget::preparePeaksTable() { if (parameters->mode == dereplication) { secondspace = (int)peak->description.find(' ', peak->description.find(' ') + 1); - peakstable->setItem(i, 0, widgetitemallocator.getNewItem()); - peakstable->item(i, 0)->setForeground(brush); - peakstable->item(i, 0)->setText(peak->description.substr(0, secondspace).c_str()); + peakstablemodel->setItem(i, 0, new QStandardItem()); + peakstablemodel->item(i, 0)->setForeground(brush); + peakstablemodel->item(i, 0)->setText(peak->description.substr(0, secondspace).c_str()); } else { - peakstable->setItem(i, 0, widgetitemallocator.getNewItem()); - peakstable->item(i, 0)->setForeground(brush); - peakstable->item(i, 0)->setText(peak->description.substr(0, peak->description.find(':')).c_str()); + peakstablemodel->setItem(i, 0, new QStandardItem()); + peakstablemodel->item(i, 0)->setForeground(brush); + peakstablemodel->item(i, 0)->setText(peak->description.substr(0, peak->description.find(':')).c_str()); } - peakstable->setItem(i, 1, widgetitemallocator.getNewItem()); - peakstable->item(i, 1)->setForeground(brush); - peakstable->item(i, 1)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(peak->mzratio)); + peakstablemodel->setItem(i, 1, new QStandardItem()); + peakstablemodel->item(i, 1)->setForeground(brush); + peakstablemodel->item(i, 1)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(peak->mzratio)), Qt::DisplayRole); if (peak->matchedmz > 0) { - peakstable->setItem(i, 2, widgetitemallocator.getNewItem()); - peakstable->item(i, 2)->setForeground(brush); - peakstable->item(i, 2)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(peak->matchedmz)); + peakstablemodel->setItem(i, 2, new QStandardItem()); + peakstablemodel->item(i, 2)->setForeground(brush); + peakstablemodel->item(i, 2)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(peak->matchedmz)), Qt::DisplayRole); - peakstable->setItem(i, 3, widgetitemallocator.getNewItem()); - peakstable->item(i, 3)->setForeground(brush); - peakstable->item(i, 3)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(peak->matchedintensity)); + peakstablemodel->setItem(i, 3, new QStandardItem()); + peakstablemodel->item(i, 3)->setForeground(brush); + peakstablemodel->item(i, 3)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(peak->matchedintensity)), Qt::DisplayRole); - peakstable->setItem(i, 4, widgetitemallocator.getNewItem()); - peakstable->item(i, 4)->setForeground(brush); - peakstable->item(i, 4)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(peak->matchedppm)); + peakstablemodel->setItem(i, 4, new QStandardItem()); + peakstablemodel->item(i, 4)->setForeground(brush); + peakstablemodel->item(i, 4)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(peak->matchedppm)), Qt::DisplayRole); } if (parameters->mode == dereplication) { - peakstable->setItem(i, 5, widgetitemallocator.getNewItem()); - peakstable->item(i, 5)->setForeground(brush); - peakstable->item(i, 5)->setText(peak->description.substr(peak->description.rfind('(') + 1, peak->description.rfind(')') - peak->description.rfind('(') - 1).c_str()); + peakstablemodel->setItem(i, 5, new QStandardItem()); + peakstablemodel->item(i, 5)->setForeground(brush); + peakstablemodel->item(i, 5)->setText(peak->description.substr(peak->description.rfind('(') + 1, peak->description.rfind(')') - peak->description.rfind('(') - 1).c_str()); - peakstable->setItem(i, 6, widgetitemallocator.getNewItem()); - peakstable->item(i, 6)->setForeground(brush); + peakstablemodel->setItem(i, 6, new QStandardItem()); + peakstablemodel->item(i, 6)->setForeground(brush); langle = (int)peak->description.rfind('<'); rangle = (int)peak->description.find('>'); if ((langle != string::npos) && (rangle != string::npos)) { - peakstable->item(i, 6)->setText(peak->description.substr(rangle + 1, langle - rangle - 1).c_str()); - - tmp1 = (int)peak->description.find('<'); - tmp2 = (int)peak->description.rfind('>'); - peakstable->setCellWidget(i, 7, new QLabel((peak->description.substr(tmp1, rangle - tmp1 + 1) + "view" + peak->description.substr(langle, tmp2 - langle + 1)).c_str())); - ((QLabel *)peakstable->cellWidget(i, 7))->setTextFormat(Qt::RichText); - ((QLabel *)peakstable->cellWidget(i, 7))->setTextInteractionFlags(Qt::TextBrowserInteraction); - ((QLabel *)peakstable->cellWidget(i, 7))->setOpenExternalLinks(true); + peakstablemodel->item(i, 6)->setText(peak->description.substr(rangle + 1, langle - rangle - 1).c_str()); + + tmp = (int)peak->description.find('<'); + stmp = peak->description.substr(tmp, rangle - tmp + 1); + stmp = stmp.substr(stmp.find('\"') + 1); + stmp = stmp.substr(0, stmp.rfind('\"')); + + peakstablemodel->setItem(i, 7, new QStandardItem()); + peakstablemodel->item(i, 7)->setForeground(brush); + peakstablemodel->item(i, 7)->setText(stmp.c_str()); } else { - peakstable->item(i, 6)->setText(peak->description.substr(secondspace + 1, peak->description.rfind('(') - secondspace - 2).c_str()); + peakstablemodel->item(i, 6)->setText(peak->description.substr(secondspace + 1, peak->description.rfind('(') - secondspace - 2).c_str()); } } else { if (peak->description.find(':') + 2 < peak->description.size()) { - peakstable->setItem(i, 5, widgetitemallocator.getNewItem()); - peakstable->item(i, 5)->setForeground(brush); - peakstable->item(i, 5)->setText(peak->description.substr(peak->description.find(':') + 2).c_str()); + peakstablemodel->setItem(i, 5, new QStandardItem()); + peakstablemodel->item(i, 5)->setForeground(brush); + peakstablemodel->item(i, 5)->setText(peak->description.substr(peak->description.find(':') + 2).c_str()); } } @@ -1248,14 +1275,13 @@ void cSpectrumDetailWidget::preparePeaksTable() { // unmatched experimental peaks for (int i = thpeakscount; i < thpeakscount + theoreticalspectrum->getUnmatchedPeaks()->size(); i++) { - peakstable->setRowHeight(i, 20); peak = &((*(theoreticalspectrum->getUnmatchedPeaks()))[i - thpeakscount]); - peakstable->setItem(i, 2, widgetitemallocator.getNewItem()); - peakstable->item(i, 2)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(peak->mzratio)); + peakstablemodel->setItem(i, 2, new QStandardItem()); + peakstablemodel->item(i, 2)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(peak->mzratio)), Qt::DisplayRole); - peakstable->setItem(i, 3, widgetitemallocator.getNewItem()); - peakstable->item(i, 3)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(peak->intensity)); + peakstablemodel->setItem(i, 3, new QStandardItem()); + peakstablemodel->item(i, 3)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(peak->intensity)), Qt::DisplayRole); progress.setValue(i); //if (progress.wasCanceled()) { @@ -1263,12 +1289,11 @@ void cSpectrumDetailWidget::preparePeaksTable() { //} } - peakstableheadersort.resize(peakstable->columnCount()); - for (int i = 0; i < peakstable->columnCount(); i++) { - peakstableheadersort[i] = -1; - } + proxymodel->setSourceModel(peakstablemodel); + peakstable->setModel(proxymodel); + peakstable->setSortingEnabled(true); - for (int i = 0; i < peakstable->columnCount(); i++) { + for (int i = 0; i < peakstablemodel->columnCount(); i++) { peakstable->resizeColumnToContents(i); } @@ -1373,9 +1398,7 @@ void cSpectrumDetailWidget::exportPeptide() { switch ((ePeptideType)parameters->peptidetype) { case linear: -#if OLIGOKETIDES == 1 - case linearoligoketide: -#endif + case linearpolyketide: rx = ".+\\.pdf$"; if (!selected && (regex_search(filename.toStdString(), rx))) { linearwidget->exportToPDF(filename, false); @@ -1403,9 +1426,7 @@ void cSpectrumDetailWidget::exportPeptide() { } break; case cyclic: -#if OLIGOKETIDES == 1 - case cyclicoligoketide: -#endif + case cyclicpolyketide: rx = ".+\\.pdf$"; if (!selected && (regex_search(filename.toStdString(), rx))) { cyclicwidget->exportToPDF(filename, false); @@ -1486,8 +1507,6 @@ void cSpectrumDetailWidget::exportPeptide() { selected = true; } break; - case linearpolysaccharide: - break; case other: break; default: @@ -1524,7 +1543,7 @@ void cSpectrumDetailWidget::exportTableToCSV() { if (!filename.isEmpty()) { - QProgressDialog progress("Exporting the CSV file...", "Cancel", 0, peakstable->rowCount(), this); + QProgressDialog progress("Exporting the CSV file...", "Cancel", 0, proxymodel->rowCount(), this); progress.setMinimumWidth(250); cEventFilter filter; progress.installEventFilter(&filter); @@ -1539,35 +1558,27 @@ void cSpectrumDetailWidget::exportTableToCSV() { QTextStream out(&file); - for (int i = 0; i < peakstable->columnCount(); i++) { - out << "\"" << peakstable->horizontalHeaderItem(i)->text() << "\""; - if (i < peakstable->columnCount() - 1) { + for (int i = 0; i < peakstablemodel->columnCount(); i++) { + out << "\"" << peakstablemodel->horizontalHeaderItem(i)->text() << "\""; + if (i < peakstablemodel->columnCount() - 1) { out << ","; } } out << endl; - for (int i = 0; i < peakstable->rowCount(); i++) { - - if (peakstable->isRowHidden(i)) { - continue; - } + QStandardItem* item; + for (int i = 0; i < proxymodel->rowCount(); i++) { - for (int j = 0; j < peakstable->columnCount(); j++) { - if (peakstable->item(i, j)) { - out << "\"" << peakstable->item(i, j)->data(Qt::DisplayRole).toString() << "\""; - if (j < peakstable->columnCount() - 1) { - out << ","; - } - } - else if (peakstable->cellWidget(i, j)) { - out << "\"" << ((QLabel *)(peakstable->cellWidget(i, j)))->text() << "\""; - if (j < peakstable->columnCount() - 1) { + for (int j = 0; j < peakstablemodel->columnCount(); j++) { + item = peakstablemodel->itemFromIndex(proxymodel->mapToSource(proxymodel->index(i, j))); + if (item) { + out << "\"" << item->data(Qt::DisplayRole).toString() << "\""; + if (j < peakstablemodel->columnCount() - 1) { out << ","; } } else { - if (j < peakstable->columnCount() - 1) { + if (j < peakstablemodel->columnCount() - 1) { out << ","; } } @@ -1587,7 +1598,7 @@ void cSpectrumDetailWidget::exportTableToCSV() { file.remove(); } - progress.setValue(peakstable->rowCount()); + progress.setValue(proxymodel->rowCount()); } } @@ -1603,8 +1614,8 @@ void cSpectrumDetailWidget::movePrevious() { if (currentfinditem < (int)tablematches.size()) { peakstable->setFocus(); - peakstable->scrollToItem(peakstable->item(tablematches[currentfinditem].row, tablematches[currentfinditem].column)); - peakstable->item(tablematches[currentfinditem].row, tablematches[currentfinditem].column)->setSelected(true); + peakstable->scrollTo(proxymodel->index(tablematches[currentfinditem].row, tablematches[currentfinditem].column)); + peakstable->selectionModel()->select(proxymodel->index(tablematches[currentfinditem].row, tablematches[currentfinditem].column), QItemSelectionModel::Select); } else { textbrowser->setFocus(); @@ -1623,8 +1634,8 @@ void cSpectrumDetailWidget::moveNext() { if (currentfinditem < (int)tablematches.size()) { peakstable->setFocus(); - peakstable->scrollToItem(peakstable->item(tablematches[currentfinditem].row, tablematches[currentfinditem].column)); - peakstable->item(tablematches[currentfinditem].row, tablematches[currentfinditem].column)->setSelected(true); + peakstable->scrollTo(proxymodel->index(tablematches[currentfinditem].row, tablematches[currentfinditem].column)); + peakstable->selectionModel()->select(proxymodel->index(tablematches[currentfinditem].row, tablematches[currentfinditem].column), QItemSelectionModel::Select); } else { textbrowser->setFocus(); @@ -1633,65 +1644,21 @@ void cSpectrumDetailWidget::moveNext() { } -void cSpectrumDetailWidget::headerItemDoubleClicked(int index) { +void cSpectrumDetailWidget::headerItemClicked(int index) { findAll("", 0, false); - - if (peakstableheadersort[index] == -1) { - peakstable->sortByColumn(index, Qt::DescendingOrder); - peakstableheadersort[index] = 0; - return; - } - - if (peakstableheadersort[index] == 0) { - peakstable->sortByColumn(index, Qt::AscendingOrder); - peakstableheadersort[index] = 1; - } - else { - peakstable->sortByColumn(index, Qt::DescendingOrder); - peakstableheadersort[index] = 0; - } } void cSpectrumDetailWidget::filterPeaksTable() { findAll("", 0, false); - int rowcount = peakstable->rowCount(); - int i; - bool hide; - cPeaksList* thpeaks = theoreticalspectrum->getTheoreticalPeaks(); - - QProgressDialog progress("Updating...", 0, 0, rowcount, this); - progress.setMinimumWidth(250); - cEventFilter filter; - progress.installEventFilter(&filter); - progress.setMinimumDuration(0); - progress.setWindowModality(Qt::WindowModal); - bool hm = actionHideMatched->isChecked(); bool hu = actionHideUnmatched->isChecked(); bool hs = actionHideScrambled->isChecked(); - for (i = 0; i < rowcount; i++) { - hide = false; - - if (hm && peakstable->item(i, 1) && peakstable->item(i, 2)) { - hide = true; - } - - if (hu && ((peakstable->item(i, 1) == 0) || (peakstable->item(i, 2) == 0))) { - hide = true; - } - - if (hs && peakstable->item(i, 0) && peakstable->item(i, 0)->text().contains("scrambled")) { - hide = true; - } - - peakstable->setRowHidden(i, hide); - progress.setValue(i); - } - - progress.setValue(rowcount); + proxymodel->setFlags(hm, hu, hs); + proxymodel->setFilterKeyColumn(-1); + proxymodel->setFilterFixedString("scrambled"); } diff --git a/CycloBranch/gui/cSpectrumDetailWidget.h b/CycloBranch/gui/cSpectrumDetailWidget.h index c093264..8799696 100644 --- a/CycloBranch/gui/cSpectrumDetailWidget.h +++ b/CycloBranch/gui/cSpectrumDetailWidget.h @@ -8,13 +8,17 @@ #define _CSPECTRUMDETAILWIDGET_H #include +#include +#include +#include #include #include -#include +#include +#include +#include #include #include #include -#include "core/cAllocator.h" #include "core/cTheoreticalSpectrum.h" #include "gui/cLinearWidget.h" #include "gui/cCyclicWidget.h" @@ -24,7 +28,8 @@ #include "gui/cFindDialog.h" #include "gui/cExportDialog.h" #include "gui/cEventFilter.h" -#include "gui/cDelegate.h" +#include "gui/cViewButtonDelegate.h" +#include "gui/cSpectrumDetailProxyModel.h" // forward declaration @@ -229,11 +234,11 @@ class cSpectrumDetailWidget : public QMainWindow QTextBrowser* textbrowser; - QTableWidget* peakstable; - vector peakstableheadersort; - cAllocator widgetitemallocator; + QTableView* peakstable; + QStandardItemModel* peakstablemodel; + cSpectrumDetailProxyModel* proxymodel; + vector tablematches; - cDelegate columndelegate; cLinearWidget* linearwidget; cCyclicWidget* cyclicwidget; @@ -287,7 +292,7 @@ private slots: void moveNext(); - void headerItemDoubleClicked(int); + void headerItemClicked(int); void filterPeaksTable(); diff --git a/CycloBranch/gui/cSpectrumSceneWidget.cpp b/CycloBranch/gui/cSpectrumSceneWidget.cpp index 22eb706..4b71c32 100644 --- a/CycloBranch/gui/cSpectrumSceneWidget.cpp +++ b/CycloBranch/gui/cSpectrumSceneWidget.cpp @@ -195,6 +195,8 @@ void cSpectrumSceneWidget::wheelEvent(QWheelEvent *event) { else { zoomOut(); } + + event->accept(); } @@ -208,6 +210,8 @@ void cSpectrumSceneWidget::mouseMoveEvent(QMouseEvent *event) { updateZoomGroup(); } + + event->accept(); } @@ -253,6 +257,8 @@ void cSpectrumSceneWidget::mouseReleaseEvent(QMouseEvent *event) { redrawScene(); } } + + event->accept(); } @@ -287,6 +293,8 @@ void cSpectrumSceneWidget::mousePressEvent(QMouseEvent *event) { redrawScene(); } } + + event->accept(); } @@ -295,6 +303,8 @@ void cSpectrumSceneWidget::showEvent(QShowEvent *event) { normalSize(); firstshow = false; } + + event->accept(); } diff --git a/CycloBranch/gui/cSummaryPeaksTableProxyModel.cpp b/CycloBranch/gui/cSummaryPeaksTableProxyModel.cpp new file mode 100644 index 0000000..1ca14ec --- /dev/null +++ b/CycloBranch/gui/cSummaryPeaksTableProxyModel.cpp @@ -0,0 +1,86 @@ +#include "gui/cSummaryPeaksTableProxyModel.h" + + +cSummaryPeaksTableProxyModel::cSummaryPeaksTableProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { + xmin = -1; + xmax = -1; + ymin = -1; + ymax = -1; +} + + +void cSummaryPeaksTableProxyModel::initialize(eModeType mode, ePeakListFileFormat peaklistfileformat) { + this->mode = mode; + this->peaklistfileformat = peaklistfileformat; +} + + +void cSummaryPeaksTableProxyModel::setRegion(int xmin, int xmax, int ymin, int ymax) { + this->xmin = xmin; + this->xmax = xmax; + this->ymin = ymin; + this->ymax = ymax; +} + + +bool cSummaryPeaksTableProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { + int size, x, y; + + if (mode == dereplication) { + if ((peaklistfileformat == mis) || (peaklistfileformat == imzML)) { + size = 10; + } + else { + size = 8; + } + } + else if (mode == denovoengine) { + size = 8; + } + else { + size = 7; + } + + if ((mode == dereplication) && ((peaklistfileformat == mis) || (peaklistfileformat == imzML))) { + x = sourceModel()->data(sourceModel()->index(sourceRow, 1)).toInt(); + y = sourceModel()->data(sourceModel()->index(sourceRow, 2)).toInt(); + + if (((xmin == -1) && (xmax == -1) && (ymin == -1) && (ymax == -1)) || ((x >= xmin) && (x <= xmax) && (y >= ymin) && (y <= ymax))) { + for (int i = 0; i < size; i++) { + if (sourceModel()->data(sourceModel()->index(sourceRow, i, sourceParent)).toString().contains(filterRegExp())) { + return true; + } + } + } + } + else { + for (int i = 0; i < size; i++) { + if (sourceModel()->data(sourceModel()->index(sourceRow, i, sourceParent)).toString().contains(filterRegExp())) { + return true; + } + } + } + + return false; +} + + +bool cSummaryPeaksTableProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { + QVariant leftData = sourceModel()->data(left); + QVariant rightData = sourceModel()->data(right); + + if (leftData.type() == QVariant::ByteArray) { + return leftData.toDouble() < rightData.toDouble(); + } + + if (leftData.type() == QVariant::String) { + return leftData.toString() < rightData.toString(); + } + + if (leftData.type() == QVariant::Int) { + return leftData.toInt() < rightData.toInt(); + } + + return QSortFilterProxyModel::lessThan(left, right); +} + diff --git a/CycloBranch/gui/cSummaryPeaksTableProxyModel.h b/CycloBranch/gui/cSummaryPeaksTableProxyModel.h new file mode 100644 index 0000000..d0fab37 --- /dev/null +++ b/CycloBranch/gui/cSummaryPeaksTableProxyModel.h @@ -0,0 +1,104 @@ +/** + \file cSummaryPeaksTableProxyModel.h + \brief A table proxy model. +*/ + + +#ifndef _CSUMMARYPEAKSTABLEPROXYMODEL_H +#define _CSUMMARYPEAKSTABLEPROXYMODEL_H + +#include +#include +#include +#include "core/cParameters.h" + + +/** + \brief A table proxy model. +*/ +class cSummaryPeaksTableProxyModel : public QSortFilterProxyModel { + + Q_OBJECT + +private: + + eModeType mode; + ePeakListFileFormat peaklistfileformat; + +public: + + /** + \brief The minimum X coordinate. + */ + int xmin; + + + /** + \brief The maximum X coordinate. + */ + int xmax; + + + /** + \brief The minimum Y coordinate. + */ + int ymin; + + + /** + \brief The maximum Y coordinate. + */ + int ymax; + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cSummaryPeaksTableProxyModel(QObject *parent = 0); + + + /** + \brief Initialize the model. + \param mode program mode + \param peaklistfileformat peaklist format + */ + void initialize(eModeType mode, ePeakListFileFormat peaklistfileformat); + + + /** + \brief Set the region for filtering. + \param xmin minimum x coordinate + \param xmax maximum x coordinate + \param ymin minimum y coordinate + \param ymax maximum y coordinate + */ + void setRegion(int xmin, int xmax, int ymin, int ymax); + + +protected: + + + /** + \brief Reimplementation of filterAcceptsRow. + \param sourceRow int + \param sourceParent QModelIndex + \retval bool bool + */ + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE; + + + /** + \brief Reimplementation of lessThan. + \param left QModelIndex + \param right QModelIndex + \retval bool bool + */ + bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE; + + +}; + + +#endif + diff --git a/CycloBranch/gui/cSummaryPeaksTableWidget.cpp b/CycloBranch/gui/cSummaryPeaksTableWidget.cpp index eb1ad4a..2227f06 100644 --- a/CycloBranch/gui/cSummaryPeaksTableWidget.cpp +++ b/CycloBranch/gui/cSummaryPeaksTableWidget.cpp @@ -3,8 +3,6 @@ #include "core/cTheoreticalSpectrumList.h" #include "gui/cEventFilter.h" -#include -#include #include #include #include @@ -18,6 +16,8 @@ #include #include #include +#include +#include cSummaryPeaksTableWidget::cSummaryPeaksTableWidget(QWidget* parent) { @@ -26,12 +26,10 @@ cSummaryPeaksTableWidget::cSummaryPeaksTableWidget(QWidget* parent) { setWindowTitle("Summary Table of Matched Peaks"); setWindowIcon(QIcon(":/images/icons/43.png")); - close = new QPushButton(tr("Close")); - close->setToolTip("Close the window."); - - exportcsv = new QPushButton(tr("Export")); - exportcsv->setToolTip("Export the table to CSV."); - exportcsv->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E)); + menuBar = new QMenuBar(this); + menuBar->setNativeMenuBar(false); + menuFile = new QMenu(tr("&File"), this); + menuHelp = new QMenu(tr("&Help"), this); rowsfilterline = new QLineEdit(); rowsfilterline->setMinimumWidth(250); @@ -62,48 +60,77 @@ cSummaryPeaksTableWidget::cSummaryPeaksTableWidget(QWidget* parent) { rowsfilterwidget->setLayout(rowsfilterhbox); rowsfilterwidget->setMaximumWidth(420); - buttons = new QHBoxLayout(); - buttons->addWidget(close); - buttons->addStretch(); - buttons->addWidget(rowsfilterwidget); - buttons->addStretch(); - buttons->addWidget(exportcsv); - - database = new QTableWidget(0, 0, this); + database = new QTableView(this); + databasemodel = new QStandardItemModel(0, 0, this); + proxymodel = new cSummaryPeaksTableProxyModel(this); + proxymodel->setSourceModel(databasemodel); + proxymodel->setDynamicSortFilter(false); + database->setModel(proxymodel); + database->setSortingEnabled(true); database->setEditTriggers(QAbstractItemView::NoEditTriggers); database->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); database->horizontalHeader()->setSectionsMovable(true); + database->verticalHeader()->setDefaultSectionSize(25); - mainlayout = new QVBoxLayout(); - mainlayout->addWidget(database); - mainlayout->addLayout(buttons); + toolbarFile = addToolBar(tr("File")); + + actionExportCSV = new QAction(QIcon(":/images/icons/62.png"), tr("&Export to CSV"), this); + actionExportCSV->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E)); + actionExportCSV->setToolTip("Export to CSV (Ctrl + E)"); + toolbarFile->addAction(actionExportCSV); + connect(actionExportCSV, SIGNAL(triggered()), this, SLOT(exportToCsv())); + + actionCloseWindow = new QAction(QIcon(":/images/icons/33.png"), tr("&Close"), this); + actionCloseWindow->setShortcut(QKeySequence(Qt::Key_Escape)); + actionCloseWindow->setToolTip("Close (Esc)"); + toolbarFile->addAction(actionCloseWindow); + connect(actionCloseWindow, SIGNAL(triggered()), this, SLOT(closeWindow())); + + toolbarHelp = addToolBar(tr("Help")); + + actionHTMLDocumentation = new QAction(QIcon(":/images/icons/3.png"), tr("&HTML Documentation"), this); + actionHTMLDocumentation->setShortcut(QKeySequence(Qt::Key_F1)); + actionHTMLDocumentation->setToolTip("Show HTML Documentation (F1)"); + toolbarHelp->addAction(actionHTMLDocumentation); + connect(actionHTMLDocumentation, SIGNAL(triggered()), this, SLOT(showHTMLDocumentation())); + + toolbarFilter = addToolBar(tr("Filter")); + toolbarFilter->addWidget(rowsfilterwidget); + + menuFile->addAction(actionExportCSV); + menuFile->addSeparator(); + menuFile->addAction(actionCloseWindow); + + menuHelp->addAction(actionHTMLDocumentation); + + menuBar->addMenu(menuFile); + menuBar->addMenu(menuHelp); + + setMenuBar(menuBar); - connect(database->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(headerItemDoubleClicked(int))); - connect(close, SIGNAL(released()), this, SLOT(closeWindow())); - connect(exportcsv, SIGNAL(released()), this, SLOT(exportToCsv())); connect(rowsfilterbutton, SIGNAL(released()), this, SLOT(filterRows())); connect(rowsfilterclearbutton, SIGNAL(released()), this, SLOT(resetFilter())); - setLayout(mainlayout); + mainlayout = new QVBoxLayout(); + mainlayout->addWidget(database); + + mainwidget = new QWidget(); + mainwidget->setLayout(mainlayout); + + setCentralWidget(mainwidget); - resize(1280, 700); + resize(1280, 750); lastdirexporttocsv = "./"; + + coordinates.clear(); + coordinates_orig.clear(); } cSummaryPeaksTableWidget::~cSummaryPeaksTableWidget() { - deleteTable(false); - - for (int i = 0; i < database->columnCount(); i++) { - delete database->horizontalHeaderItem(i); - } + deleteTable(); - database->setColumnCount(0); - - delete close; - delete exportcsv; - delete rowsfilterline; delete rowsfiltercasesensitive; delete rowsfilterbutton; @@ -111,135 +138,164 @@ cSummaryPeaksTableWidget::~cSummaryPeaksTableWidget() { delete rowsfilterhbox; delete rowsfilterwidget; + delete databasemodel; + delete proxymodel; delete database; - delete buttons; delete mainlayout; + delete mainwidget; + + delete actionExportCSV; + delete actionCloseWindow; + delete actionHTMLDocumentation; + + delete menuFile; + delete menuHelp; + + delete menuBar; } void cSummaryPeaksTableWidget::closeEvent(QCloseEvent *event) { closeWindow(); + event->accept(); } -void cSummaryPeaksTableWidget::prepareToShow(QTableWidget* tablewidget, cParameters* parameters, cTheoreticalSpectrumList* spectralist) { - if (!parameters || !spectralist || ((int)tablewidget->rowCount() != spectralist->size())) { +void cSummaryPeaksTableWidget::prepareToShow(QStandardItemModel* resultsstandardmodel, cMainWindowProxyModel* resultsproxymodel, cParameters* parameters, cTheoreticalSpectrumList* spectralist) { + if (!parameters || !spectralist || (resultsstandardmodel->rowCount() != spectralist->size())) { return; } this->parameters = parameters; + resetFilter(); + deleteTable(); + proxymodel->initialize(parameters->mode, parameters->peaklistfileformat); - // delete old data - deleteTable(true); - for (int i = 0; i < database->columnCount(); i++) { - database->setItemDelegateForColumn(i, 0); - delete database->horizontalHeaderItem(i); - } - database->setColumnCount(0); + coordinates.clear(); + coordinates_orig.clear(); // prepare the header if (parameters->mode == dereplication) { if ((parameters->peaklistfileformat == mis) || (parameters->peaklistfileformat == imzML)) { - database->setColumnCount(11); + databasemodel->setColumnCount(11); } else { - database->setColumnCount(9); + databasemodel->setColumnCount(9); } } + else if (parameters->mode == denovoengine) { + databasemodel->setColumnCount(8); + } else { - database->setColumnCount(7); + databasemodel->setColumnCount(7); } - database->setHorizontalHeaderItem(0, new QTableWidgetItem()); - database->horizontalHeaderItem(0)->setText("ID"); + databasemodel->setHorizontalHeaderItem(0, new QStandardItem()); + databasemodel->horizontalHeaderItem(0)->setText("ID"); + database->setItemDelegateForColumn(0, new QItemDelegate()); int currentcolumn = 1; if (parameters->mode == dereplication) { if ((parameters->peaklistfileformat == mis) || (parameters->peaklistfileformat == imzML)) { - database->setHorizontalHeaderItem(currentcolumn, new QTableWidgetItem()); - database->horizontalHeaderItem(currentcolumn)->setText("Coordinate X"); + databasemodel->setHorizontalHeaderItem(currentcolumn, new QStandardItem()); + databasemodel->horizontalHeaderItem(currentcolumn)->setText("Coordinate X"); + database->setItemDelegateForColumn(currentcolumn, new QItemDelegate()); currentcolumn++; - database->setHorizontalHeaderItem(currentcolumn, new QTableWidgetItem()); - database->horizontalHeaderItem(currentcolumn)->setText("Coordinate Y"); + + databasemodel->setHorizontalHeaderItem(currentcolumn, new QStandardItem()); + databasemodel->horizontalHeaderItem(currentcolumn)->setText("Coordinate Y"); + database->setItemDelegateForColumn(currentcolumn, new QItemDelegate()); currentcolumn++; } - database->setHorizontalHeaderItem(currentcolumn, new QTableWidgetItem()); - database->horizontalHeaderItem(currentcolumn)->setText("Ion Type"); + databasemodel->setHorizontalHeaderItem(currentcolumn, new QStandardItem()); + databasemodel->horizontalHeaderItem(currentcolumn)->setText("Ion Type"); + database->setItemDelegateForColumn(currentcolumn, new QItemDelegate()); currentcolumn++; } - else { - database->setHorizontalHeaderItem(currentcolumn, new QTableWidgetItem()); - database->horizontalHeaderItem(currentcolumn)->setText("Fragment Type"); + + if (parameters->mode == denovoengine) { + databasemodel->setHorizontalHeaderItem(currentcolumn, new QStandardItem()); + databasemodel->horizontalHeaderItem(currentcolumn)->setText("Group ID"); + database->setItemDelegateForColumn(currentcolumn, new QItemDelegate()); currentcolumn++; } - database->setHorizontalHeaderItem(currentcolumn, new QTableWidgetItem()); - database->horizontalHeaderItem(currentcolumn)->setText("Theoretical m/z"); - database->setItemDelegateForColumn(currentcolumn, &columndelegate); + if (parameters->mode != dereplication) { + databasemodel->setHorizontalHeaderItem(currentcolumn, new QStandardItem()); + databasemodel->horizontalHeaderItem(currentcolumn)->setText("Fragment Type"); + database->setItemDelegateForColumn(currentcolumn, new QItemDelegate()); + currentcolumn++; + } + + databasemodel->setHorizontalHeaderItem(currentcolumn, new QStandardItem()); + databasemodel->horizontalHeaderItem(currentcolumn)->setText("Theoretical m/z"); + database->setItemDelegateForColumn(currentcolumn, new QItemDelegate()); currentcolumn++; - database->setHorizontalHeaderItem(currentcolumn, new QTableWidgetItem()); - database->horizontalHeaderItem(currentcolumn)->setText("Experimental m/z"); - database->setItemDelegateForColumn(currentcolumn, &columndelegate); + databasemodel->setHorizontalHeaderItem(currentcolumn, new QStandardItem()); + databasemodel->horizontalHeaderItem(currentcolumn)->setText("Experimental m/z"); + database->setItemDelegateForColumn(currentcolumn, new QItemDelegate()); currentcolumn++; - database->setHorizontalHeaderItem(currentcolumn, new QTableWidgetItem()); - database->horizontalHeaderItem(currentcolumn)->setText("Intensity [%]"); - database->setItemDelegateForColumn(currentcolumn, &columndelegate); + databasemodel->setHorizontalHeaderItem(currentcolumn, new QStandardItem()); + databasemodel->horizontalHeaderItem(currentcolumn)->setText("Intensity [%]"); + database->setItemDelegateForColumn(currentcolumn, new QItemDelegate()); currentcolumn++; - database->setHorizontalHeaderItem(currentcolumn, new QTableWidgetItem()); - database->horizontalHeaderItem(currentcolumn)->setText("Error [ppm]"); - database->setItemDelegateForColumn(currentcolumn, &columndelegate); + databasemodel->setHorizontalHeaderItem(currentcolumn, new QStandardItem()); + databasemodel->horizontalHeaderItem(currentcolumn)->setText("Error [ppm]"); + database->setItemDelegateForColumn(currentcolumn, new QItemDelegate()); currentcolumn++; if (parameters->mode == dereplication) { - database->setHorizontalHeaderItem(currentcolumn, new QTableWidgetItem()); - database->horizontalHeaderItem(currentcolumn)->setText("Summary Formula"); + databasemodel->setHorizontalHeaderItem(currentcolumn, new QStandardItem()); + databasemodel->horizontalHeaderItem(currentcolumn)->setText("Summary Formula"); + database->setItemDelegateForColumn(currentcolumn, new QItemDelegate()); currentcolumn++; - database->setHorizontalHeaderItem(currentcolumn, new QTableWidgetItem()); - database->horizontalHeaderItem(currentcolumn)->setText("Name"); + databasemodel->setHorizontalHeaderItem(currentcolumn, new QStandardItem()); + databasemodel->horizontalHeaderItem(currentcolumn)->setText("Name"); + database->setItemDelegateForColumn(currentcolumn, new QItemDelegate()); currentcolumn++; - database->setHorizontalHeaderItem(currentcolumn, new QTableWidgetItem()); - database->horizontalHeaderItem(currentcolumn)->setText("Reference"); + databasemodel->setHorizontalHeaderItem(currentcolumn, new QStandardItem()); + databasemodel->horizontalHeaderItem(currentcolumn)->setText("Reference"); + database->setItemDelegateForColumn(currentcolumn, new cViewButtonDelegate()); currentcolumn++; } else { - database->setHorizontalHeaderItem(currentcolumn, new QTableWidgetItem()); - database->horizontalHeaderItem(currentcolumn)->setText("Sequence"); + databasemodel->setHorizontalHeaderItem(currentcolumn, new QStandardItem()); + databasemodel->horizontalHeaderItem(currentcolumn)->setText("Sequence"); + database->setItemDelegateForColumn(currentcolumn, new QItemDelegate()); currentcolumn++; } - database->horizontalHeader()->setStretchLastSection(true); - for (int i = 0; i < database->columnCount(); i++) { + for (int i = 0; i < databasemodel->columnCount(); i++) { database->resizeColumnToContents(i); } - headersort.resize(database->columnCount()); - for (int i = 0; i < database->columnCount(); i++) { - headersort[i] = -1; - } - // fill new data QProgressDialog* progress; cEventFilter filter; int spectracount = spectralist->size(); - progress = new QProgressDialog("Preparing the table...", "Cancel", 0, spectracount, this); + progress = new QProgressDialog("Preparing the data...", "Cancel", 0, spectracount, this); progress->setMinimumWidth(250); progress->installEventFilter(&filter); progress->setMinimumDuration(0); progress->setWindowModality(Qt::WindowModal); progress->setValue(0); + database->setModel(0); + proxymodel->setSourceModel(0); + database->setSortingEnabled(false); + int thpeakscount; - int secondspace, langle, rangle, tmp1, tmp2; + int secondspace, langle, rangle, tmp; cPeaksList* thpeaks; cPeak* peak; bool isred; @@ -252,12 +308,11 @@ void cSummaryPeaksTableWidget::prepareToShow(QTableWidget* tablewidget, cParamet for (int i = 0; i < spectracount; i++) { - if (tablewidget->isRowHidden(i)) { - progress->setValue(i); + if (!resultsproxymodel->mapFromSource(resultsstandardmodel->index(i, 0)).isValid()) { continue; } - spectrumindex = tablewidget->item(i, 1)->data(Qt::DisplayRole).toInt() - 1; + spectrumindex = resultsstandardmodel->item(i, 1)->data(Qt::DisplayRole).toInt() - 1; if ((*spectralist)[spectrumindex].getNumberOfMatchedPeaks() == 0) { progress->setValue(i); @@ -294,98 +349,131 @@ void cSummaryPeaksTableWidget::prepareToShow(QTableWidget* tablewidget, cParamet continue; } - currentrow = database->rowCount(); + currentrow = databasemodel->rowCount(); currentcolumn = 0; - database->insertRow(currentrow); - database->setRowHeight(currentrow, 20); + databasemodel->insertRow(currentrow); - database->setItem(currentrow, currentcolumn, widgetitemallocator.getNewItem()); - database->item(currentrow, currentcolumn)->setForeground(brush); - database->item(currentrow, currentcolumn)->setData(Qt::DisplayRole, spectrumindex + 1); + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setData(QVariant::fromValue(spectrumindex + 1), Qt::DisplayRole); currentcolumn++; if (parameters->mode == dereplication) { if ((parameters->peaklistfileformat == mis) || (parameters->peaklistfileformat == imzML)) { - database->setItem(currentrow, currentcolumn, widgetitemallocator.getNewItem()); - database->item(currentrow, currentcolumn)->setForeground(brush); - database->item(currentrow, currentcolumn)->setData(Qt::DisplayRole, (*spectralist)[spectrumindex].getExperimentalSpectrum().getCoordinateX()); + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setData(QVariant::fromValue((*spectralist)[spectrumindex].getExperimentalSpectrum().getCoordinateX()), Qt::DisplayRole); currentcolumn++; - database->setItem(currentrow, currentcolumn, widgetitemallocator.getNewItem()); - database->item(currentrow, currentcolumn)->setForeground(brush); - database->item(currentrow, currentcolumn)->setData(Qt::DisplayRole, (*spectralist)[spectrumindex].getExperimentalSpectrum().getCoordinateY()); - currentcolumn++; + + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setData(QVariant::fromValue((*spectralist)[spectrumindex].getExperimentalSpectrum().getCoordinateY()), Qt::DisplayRole); + currentcolumn++; + + coordinates.push_back(cCoordinates((*spectralist)[spectrumindex].getExperimentalSpectrum().getCoordinateX(), (*spectralist)[spectrumindex].getExperimentalSpectrum().getCoordinateY(), spectrumindex + 1, cropPrecisionToSixDecimalsByteArray(peak->matchedmz).toDouble(), cropPrecisionToSixDecimalsByteArray(peak->matchedintensity).toDouble())); } secondspace = (int)peak->description.find(' ', peak->description.find(' ') + 1); - database->setItem(currentrow, currentcolumn, widgetitemallocator.getNewItem()); - database->item(currentrow, currentcolumn)->setForeground(brush); - database->item(currentrow, currentcolumn)->setText(peak->description.substr(0, secondspace).c_str()); + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setText(peak->description.substr(0, secondspace).c_str()); currentcolumn++; } - else { - database->setItem(currentrow, currentcolumn, widgetitemallocator.getNewItem()); - database->item(currentrow, currentcolumn)->setForeground(brush); - database->item(currentrow, currentcolumn)->setText(peak->description.substr(0, peak->description.find(':')).c_str()); + + if (parameters->mode == denovoengine) { + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setData(QVariant::fromValue((*spectralist)[spectrumindex].getPathId() + 1), Qt::DisplayRole); + currentcolumn++; + } + + if (parameters->mode != dereplication) { + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setText(peak->description.substr(0, peak->description.find(':')).c_str()); currentcolumn++; } - database->setItem(currentrow, currentcolumn, widgetitemallocator.getNewItem()); - database->item(currentrow, currentcolumn)->setForeground(brush); - database->item(currentrow, currentcolumn)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(peak->mzratio)); + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(peak->mzratio)), Qt::DisplayRole); currentcolumn++; - database->setItem(currentrow, currentcolumn, widgetitemallocator.getNewItem()); - database->item(currentrow, currentcolumn)->setForeground(brush); - database->item(currentrow, currentcolumn)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(peak->matchedmz)); + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(peak->matchedmz)), Qt::DisplayRole); currentcolumn++; - database->setItem(currentrow, currentcolumn, widgetitemallocator.getNewItem()); - database->item(currentrow, currentcolumn)->setForeground(brush); - database->item(currentrow, currentcolumn)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(peak->matchedintensity)); + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(peak->matchedintensity)), Qt::DisplayRole); currentcolumn++; - database->setItem(currentrow, currentcolumn, widgetitemallocator.getNewItem()); - database->item(currentrow, currentcolumn)->setForeground(brush); - database->item(currentrow, currentcolumn)->setData(Qt::DisplayRole, cropPrecisionToSixDecimals(peak->matchedppm)); + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setData(QVariant::fromValue(cropPrecisionToSixDecimalsByteArray(peak->matchedppm)), Qt::DisplayRole); currentcolumn++; if (parameters->mode == dereplication) { - database->setItem(currentrow, currentcolumn, widgetitemallocator.getNewItem()); - database->item(currentrow, currentcolumn)->setForeground(brush); - database->item(currentrow, currentcolumn)->setText(peak->description.substr(peak->description.rfind('(') + 1, peak->description.rfind(')') - peak->description.rfind('(') - 1).c_str()); + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setText(peak->description.substr(peak->description.rfind('(') + 1, peak->description.rfind(')') - peak->description.rfind('(') - 1).c_str()); currentcolumn++; langle = (int)peak->description.rfind('<'); rangle = (int)peak->description.find('>'); if ((langle != string::npos) && (rangle != string::npos)) { - database->setItem(currentrow, currentcolumn, widgetitemallocator.getNewItem()); - database->item(currentrow, currentcolumn)->setForeground(brush); - database->item(currentrow, currentcolumn)->setText(peak->description.substr(rangle + 1, langle - rangle - 1).c_str()); + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setText(peak->description.substr(rangle + 1, langle - rangle - 1).c_str()); + if ((parameters->peaklistfileformat == mis) || (parameters->peaklistfileformat == imzML)) { + if (databasemodel->item(currentrow, currentcolumn)->text().length() > 40) { + coordinates.back().name = databasemodel->item(currentrow, currentcolumn)->text().toStdString().substr(0, 37) + "..."; + } + else { + coordinates.back().name = databasemodel->item(currentrow, currentcolumn)->text().toStdString(); + } + } currentcolumn++; - tmp1 = (int)peak->description.find('<'); - tmp2 = (int)peak->description.rfind('>'); - stmp = peak->description.substr(tmp1, rangle - tmp1 + 1) + "view" + peak->description.substr(langle, tmp2 - langle + 1); - database->setCellWidget(currentrow, currentcolumn, new QLabel(stmp.c_str())); - ((QLabel *)database->cellWidget(currentrow, currentcolumn))->setTextFormat(Qt::RichText); - ((QLabel *)database->cellWidget(currentrow, currentcolumn))->setTextInteractionFlags(Qt::TextBrowserInteraction); - ((QLabel *)database->cellWidget(currentrow, currentcolumn))->setOpenExternalLinks(true); + tmp = (int)peak->description.find('<'); + stmp = peak->description.substr(tmp, rangle - tmp + 1); + stmp = stmp.substr(stmp.find('\"') + 1); + stmp = stmp.substr(0, stmp.rfind('\"')); + + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setText(stmp.c_str()); currentcolumn++; } else { - database->setItem(currentrow, currentcolumn, widgetitemallocator.getNewItem()); - database->item(currentrow, currentcolumn)->setForeground(brush); - database->item(currentrow, currentcolumn)->setText(peak->description.substr(secondspace + 1, peak->description.rfind('(') - secondspace - 2).c_str()); + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setText(peak->description.substr(secondspace + 1, peak->description.rfind('(') - secondspace - 2).c_str()); + if ((parameters->peaklistfileformat == mis) || (parameters->peaklistfileformat == imzML)) { + if (databasemodel->item(currentrow, currentcolumn)->text().length() > 40) { + coordinates.back().name = databasemodel->item(currentrow, currentcolumn)->text().toStdString().substr(0, 37) + "..."; + } + else { + coordinates.back().name = databasemodel->item(currentrow, currentcolumn)->text().toStdString(); + } + } + currentcolumn++; + + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setText(""); currentcolumn++; } } else { + databasemodel->setItem(currentrow, currentcolumn, new QStandardItem()); + databasemodel->item(currentrow, currentcolumn)->setForeground(brush); + databasemodel->item(currentrow, currentcolumn)->setText(""); if (peak->description.find(':') + 2 < peak->description.size()) { - database->setItem(currentrow, currentcolumn, widgetitemallocator.getNewItem()); - database->item(currentrow, currentcolumn)->setForeground(brush); - database->item(currentrow, currentcolumn)->setText(peak->description.substr(peak->description.find(':') + 2).c_str()); - currentcolumn++; + databasemodel->item(currentrow, currentcolumn)->setText(peak->description.substr(peak->description.find(':') + 2).c_str()); } + currentcolumn++; } } @@ -396,15 +484,29 @@ void cSummaryPeaksTableWidget::prepareToShow(QTableWidget* tablewidget, cParamet progress->setValue(i); if (progress->wasCanceled()) { - deleteTable(true); + deleteTable(); emit tableCancelled(); break; } } - for (int i = 0; i < database->columnCount(); i++) { - database->resizeColumnToContents(i); + proxymodel->setSourceModel(databasemodel); + database->setModel(proxymodel); + proxymodel->setSortRole(Qt::InitialSortOrderRole); + database->setSortingEnabled(true); + + if (!progress->wasCanceled()) { + for (int i = 0; i < databasemodel->columnCount(); i++) { + database->resizeColumnToContents(i); + } + } + + if ((parameters->mode == dereplication) && !progress->wasCanceled()) { + if ((parameters->peaklistfileformat == mis) || (parameters->peaklistfileformat == imzML)) { + emit sendCoordinates(coordinates); + coordinates_orig = coordinates; + } } progress->setValue(spectracount); @@ -412,76 +514,38 @@ void cSummaryPeaksTableWidget::prepareToShow(QTableWidget* tablewidget, cParamet } -void cSummaryPeaksTableWidget::deleteTable(bool enableprogress) { - QProgressDialog* progress; - cEventFilter filter; - int rowcount = database->rowCount(); - - if (enableprogress) { - progress = new QProgressDialog("Clearing the table...", 0, 0, rowcount, this); - progress->setMinimumWidth(250); - progress->installEventFilter(&filter); - progress->setMinimumDuration(0); - progress->setWindowModality(Qt::WindowModal); - progress->setValue(0); - } - - widgetitemallocator.reset(); - - for (int i = 0; i < rowcount; i++) { - if (parameters->mode == dereplication) { - if ((parameters->peaklistfileformat == mis) || (parameters->peaklistfileformat == imzML)) { - delete database->cellWidget(rowcount - i - 1, 10); - } - else { - delete database->cellWidget(rowcount - i - 1, 8); - } +void cSummaryPeaksTableWidget::deleteTable() { + for (int i = 0; i < databasemodel->columnCount(); i++) { + if (database->itemDelegateForColumn(i)) { + delete database->itemDelegateForColumn(i); } + } + databasemodel->clear(); +} - if (enableprogress) { - progress->setValue(i); - } - } - - database->setRowCount(0); - if (enableprogress) { - progress->setValue(rowcount); - delete progress; - } +void cSummaryPeaksTableWidget::updateFilterBySelectedRegion(int xmin, int xmax, int ymin, int ymax) { + proxymodel->setRegion(xmin, xmax, ymin, ymax); + filterRows(); } void cSummaryPeaksTableWidget::keyPressEvent(QKeyEvent *event) { - if (event->key() == Qt::Key_Escape) { - closeWindow(); - } - if ((event->key() == Qt::Key_Enter) || (event->key() == Qt::Key_Return)) { if (rowsfilterline->hasFocus()) { filterRows(); } } - if (event->key() == Qt::Key_F1) { - #if OS_TYPE == WIN - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/summarypeakstable.html").absoluteFilePath())); - #else - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/summarypeakstable.html").absoluteFilePath())); - #endif - } - if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_F)) { rowsfilterline->setFocus(); } - if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_N)) { + if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_T)) { rowsfiltercasesensitive->setChecked(!rowsfiltercasesensitive->isChecked()); } - if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_E)) { - exportToCsv(); - } + event->accept(); } @@ -490,30 +554,12 @@ void cSummaryPeaksTableWidget::closeWindow() { } -void cSummaryPeaksTableWidget::headerItemDoubleClicked(int index) { - if (headersort[index] == -1) { - database->sortByColumn(index, Qt::AscendingOrder); - headersort[index] = 1; - return; - } - - if (headersort[index] == 0) { - database->sortByColumn(index, Qt::AscendingOrder); - headersort[index] = 1; - } - else { - database->sortByColumn(index, Qt::DescendingOrder); - headersort[index] = 0; - } -} - - void cSummaryPeaksTableWidget::filterRows() { Qt::CaseSensitivity casesensitive = rowsfiltercasesensitive->isChecked()?Qt::CaseSensitive:Qt::CaseInsensitive; QString str = rowsfilterline->text(); - int rowcount = database->rowCount(); + int rowcount = databasemodel->rowCount(); bool match; - int i, j; + int i, j, x, y; QProgressDialog progress("Updating...", "Cancel", 0, rowcount, this); progress.setMinimumWidth(250); @@ -522,10 +568,14 @@ void cSummaryPeaksTableWidget::filterRows() { progress.setMinimumDuration(0); progress.setWindowModality(Qt::WindowModal); + coordinates.clear(); + for (i = 0; i < rowcount; i++) { + x = databasemodel->item(i, 1)->data(Qt::DisplayRole).toInt(); + y = databasemodel->item(i, 2)->data(Qt::DisplayRole).toInt(); match = false; - for (j = 0; j < database->columnCount(); j++) { + for (j = 0; j < databasemodel->columnCount(); j++) { // ignore non-text fields if (parameters->mode == dereplication) { if ((parameters->peaklistfileformat == mis) || (parameters->peaklistfileformat == imzML)) { @@ -540,12 +590,25 @@ void cSummaryPeaksTableWidget::filterRows() { } } - if (database->item(i, j)->text().contains(str, casesensitive)) { + if (databasemodel->item(i, j) && databasemodel->item(i, j)->text().contains(str, casesensitive)) { + if (parameters->mode == dereplication) { + if ((parameters->peaklistfileformat == mis) || (parameters->peaklistfileformat == imzML)) { + if (((proxymodel->xmin == -1) && (proxymodel->xmax == -1) && (proxymodel->ymin == -1) && (proxymodel->ymax == -1)) || ((x >= proxymodel->xmin) && (x <= proxymodel->xmax) && (y >= proxymodel->ymin) && (y <= proxymodel->ymax))) { + coordinates.push_back(cCoordinates(databasemodel->item(i, 1)->text().toInt(), databasemodel->item(i, 2)->text().toInt(), databasemodel->item(i, 0)->text().toInt(), databasemodel->item(i, 5)->data(Qt::DisplayRole).toDouble(), databasemodel->item(i, 6)->data(Qt::DisplayRole).toDouble())); + if (databasemodel->item(i, 9)->text().length() > 40) { + coordinates.back().name = databasemodel->item(i, 9)->text().toStdString().substr(0, 37) + "..."; + } + else { + coordinates.back().name = databasemodel->item(i, 9)->text().toStdString(); + } + } + } + } + match = true; break; } } - database->setRowHidden(i, !match); progress.setValue(i); if (progress.wasCanceled()) { @@ -555,13 +618,25 @@ void cSummaryPeaksTableWidget::filterRows() { } + if ((parameters->mode == dereplication) && !progress.wasCanceled()) { + if ((parameters->peaklistfileformat == mis) || (parameters->peaklistfileformat == imzML)) { + emit sendCoordinates(coordinates); + } + } + + proxymodel->setFilterKeyColumn(-1); + proxymodel->setFilterCaseSensitivity(casesensitive); + proxymodel->setFilterFixedString(str); + progress.setValue(rowcount); } void cSummaryPeaksTableWidget::resetFilter() { rowsfilterline->setText(""); - int rowcount = database->rowCount(); + + int rowcount = databasemodel->rowCount(); + int i, x, y; QProgressDialog progress("Updating...", 0, 0, rowcount, this); progress.setMinimumWidth(250); @@ -570,11 +645,35 @@ void cSummaryPeaksTableWidget::resetFilter() { progress.setMinimumDuration(0); progress.setWindowModality(Qt::WindowModal); - for (int i = 0; i < rowcount; i++) { - database->setRowHidden(i, false); - progress.setValue(i); + if (parameters->mode == dereplication) { + if ((parameters->peaklistfileformat == mis) || (parameters->peaklistfileformat == imzML)) { + coordinates.clear(); + for (i = 0; i < rowcount; i++) { + x = databasemodel->item(i, 1)->data(Qt::DisplayRole).toInt(); + y = databasemodel->item(i, 2)->data(Qt::DisplayRole).toInt(); + + if (((proxymodel->xmin == -1) && (proxymodel->xmax == -1) && (proxymodel->ymin == -1) && (proxymodel->ymax == -1)) || ((x >= proxymodel->xmin) && (x <= proxymodel->xmax) && (y >= proxymodel->ymin) && (y <= proxymodel->ymax))) { + coordinates.push_back(cCoordinates(x, y, databasemodel->item(i, 0)->text().toInt(), databasemodel->item(i, 5)->data(Qt::DisplayRole).toDouble(), databasemodel->item(i, 6)->data(Qt::DisplayRole).toDouble())); + if (databasemodel->item(i, 9)->text().length() > 40) { + coordinates.back().name = databasemodel->item(i, 9)->text().toStdString().substr(0, 37) + "..."; + } + else { + coordinates.back().name = databasemodel->item(i, 9)->text().toStdString(); + } + } + + progress.setValue(i); + } + emit sendCoordinates(coordinates); + } } + database->horizontalHeader()->setSortIndicator(-1, Qt::AscendingOrder); + proxymodel->sort(-1); + + proxymodel->setFilterKeyColumn(-1); + proxymodel->setFilterFixedString(""); + progress.setValue(rowcount); } @@ -585,7 +684,7 @@ void cSummaryPeaksTableWidget::exportToCsv() { if (!filename.isEmpty()) { lastdirexporttocsv = filename; - QProgressDialog progress("Exporting CSV file...", "Cancel", 0, database->rowCount(), this); + QProgressDialog progress("Exporting CSV file...", "Cancel", 0, proxymodel->rowCount(), this); progress.setMinimumWidth(250); cEventFilter filter; progress.installEventFilter(&filter); @@ -600,35 +699,27 @@ void cSummaryPeaksTableWidget::exportToCsv() { QTextStream out(&file); - for (int i = 0; i < database->columnCount(); i++) { - out << "\"" << database->horizontalHeaderItem(i)->text() << "\""; - if (i < database->columnCount() - 1) { + for (int i = 0; i < databasemodel->columnCount(); i++) { + out << "\"" << databasemodel->horizontalHeaderItem(i)->text() << "\""; + if (i < databasemodel->columnCount() - 1) { out << ","; } } out << endl; - for (int i = 0; i < database->rowCount(); i++) { - - if (database->isRowHidden(i)) { - continue; - } + QStandardItem* item; + for (int i = 0; i < proxymodel->rowCount(); i++) { - for (int j = 0; j < database->columnCount(); j++) { - if (database->item(i, j)) { - out << "\"" << database->item(i, j)->data(Qt::DisplayRole).toString() << "\""; - if (j < database->columnCount() - 1) { - out << ","; - } - } - else if (database->cellWidget(i, j)) { - out << "\"" << ((QLabel *)(database->cellWidget(i, j)))->text() << "\""; - if (j < database->columnCount() - 1) { + for (int j = 0; j < databasemodel->columnCount(); j++) { + item = databasemodel->itemFromIndex(proxymodel->mapToSource(proxymodel->index(i, j))); + if (item) { + out << "\"" << item->data(Qt::DisplayRole).toString() << "\""; + if (j < databasemodel->columnCount() - 1) { out << ","; } } else { - if (j < database->columnCount() - 1) { + if (j < databasemodel->columnCount() - 1) { out << ","; } } @@ -640,6 +731,7 @@ void cSummaryPeaksTableWidget::exportToCsv() { removefile = true; break; } + } file.close(); @@ -648,7 +740,16 @@ void cSummaryPeaksTableWidget::exportToCsv() { file.remove(); } - progress.setValue(database->rowCount()); + progress.setValue(proxymodel->rowCount()); } } + +void cSummaryPeaksTableWidget::showHTMLDocumentation() { + #if OS_TYPE == WIN + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/summarypeakstable.html").absoluteFilePath())); + #else + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/summarypeakstable.html").absoluteFilePath())); + #endif +} + diff --git a/CycloBranch/gui/cSummaryPeaksTableWidget.h b/CycloBranch/gui/cSummaryPeaksTableWidget.h index 9b1642b..aa51a85 100644 --- a/CycloBranch/gui/cSummaryPeaksTableWidget.h +++ b/CycloBranch/gui/cSummaryPeaksTableWidget.h @@ -11,10 +11,17 @@ #include #include #include -//#include +#include +#include +#include +#include +#include +#include +#include #include "core/utilities.h" -#include "core/cAllocator.h" -#include "gui/cDelegate.h" +#include "gui/cViewButtonDelegate.h" +#include "gui/cSummaryPeaksTableProxyModel.h" +#include "gui/cMainWindowProxyModel.h" using namespace std; @@ -24,17 +31,17 @@ class cParameters; class cTheoreticalSpectrumList; class QHBoxLayout; class QVBoxLayout; -class QTableWidget; -class QTableWidgetItem; class QPushButton; class QCheckBox; class QLineEdit; +class QMenuBar; +class QMenu; /** \brief Summary table of matched peaks. */ -class cSummaryPeaksTableWidget : public QWidget +class cSummaryPeaksTableWidget : public QMainWindow { Q_OBJECT @@ -63,27 +70,47 @@ class cSummaryPeaksTableWidget : public QWidget /** \brief Prepare the widget to show. - \param tablewidget a pointer to the main window table widget with the results + \param resultsstandardmodel standard model of the tableview in the main application window + \param resultsproxymodel proxy model of the tableview in the main application window \param parameters parameters of the application \param spectralist list of spectra */ - void prepareToShow(QTableWidget* tablewidget, cParameters* parameters, cTheoreticalSpectrumList* spectralist); + void prepareToShow(QStandardItemModel* resultsstandardmodel, cMainWindowProxyModel* resultsproxymodel, cParameters* parameters, cTheoreticalSpectrumList* spectralist); /** \brief Delete the table content. - \param enableprogress if true, the progress dialog is shown; if false, the dialog is hidden */ - void deleteTable(bool enableprogress); + void deleteTable(); + + + /** + \brief Update the filter using an image region. + \param xmin minimum x coordinate + \param xmax maximum x coordinate + \param ymin minimum y coordinate + \param ymax maximum y coordinate + */ + void updateFilterBySelectedRegion(int xmin, int xmax, int ymin, int ymax); private: cParameters* parameters; QWidget* parent; - QPushButton* close; - QPushButton* exportcsv; + QMenuBar* menuBar; + QMenu* menuFile; + QMenu* menuHelp; + + QToolBar* toolbarFile; + QAction* actionExportCSV; + QAction* actionCloseWindow; + + QToolBar* toolbarHelp; + QAction* actionHTMLDocumentation; + + QToolBar* toolbarFilter; QWidget* rowsfilterwidget; QHBoxLayout* rowsfilterhbox; QLineEdit* rowsfilterline; @@ -91,16 +118,16 @@ class cSummaryPeaksTableWidget : public QWidget QPushButton* rowsfilterbutton; QPushButton* rowsfilterclearbutton; - QTableWidget* database; - QHBoxLayout* buttons; + QTableView* database; + QStandardItemModel* databasemodel; + cSummaryPeaksTableProxyModel* proxymodel; QVBoxLayout* mainlayout; - - vector headersort; - cDelegate columndelegate; + QWidget* mainwidget; QString lastdirexporttocsv; - cAllocator widgetitemallocator; + vector coordinates; + vector coordinates_orig; protected: @@ -118,9 +145,6 @@ private slots: void closeWindow(); - void headerItemDoubleClicked(int index); - - void filterRows(); @@ -130,6 +154,9 @@ private slots: void exportToCsv(); + void showHTMLDocumentation(); + + signals: @@ -138,6 +165,13 @@ private slots: */ void tableCancelled(); + + /** + \brief Send the vector of coordinates. + \param coordinates a vector of coordinates x and y + */ + void sendCoordinates(vector coordinates); + }; diff --git a/CycloBranch/gui/cViewButtonDelegate.cpp b/CycloBranch/gui/cViewButtonDelegate.cpp new file mode 100644 index 0000000..e64e107 --- /dev/null +++ b/CycloBranch/gui/cViewButtonDelegate.cpp @@ -0,0 +1,43 @@ +#include "gui/cViewButtonDelegate.h" + +#include +#include +#include +#include +#include + + +cViewButtonDelegate::cViewButtonDelegate(QObject* parent) : QStyledItemDelegate(parent) { +} + + +QString cViewButtonDelegate::displayText(const QVariant& value, const QLocale& locale) const { + return ""; +} + + +void cViewButtonDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { + if (index.data(Qt::DisplayRole).toString().isEmpty()) { + return; + } + + QStyleOptionButton button; + button.rect = option.rect; + button.text = "view"; + button.state = QStyle::State_Enabled; + + QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter); +} + + +bool cViewButtonDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index) { + if (event->type() == QEvent::MouseButtonRelease) { + if (index.data(Qt::DisplayRole).toString().isEmpty()) { + return false; + } + QDesktopServices::openUrl(QUrl(index.data(Qt::DisplayRole).toString())); + return true; + } + return false; +} + diff --git a/CycloBranch/gui/cViewButtonDelegate.h b/CycloBranch/gui/cViewButtonDelegate.h new file mode 100644 index 0000000..65ca4ba --- /dev/null +++ b/CycloBranch/gui/cViewButtonDelegate.h @@ -0,0 +1,71 @@ +/** + \file cViewButtonDelegate.h + \brief A delegate to create a reference view button. +*/ + + +#ifndef _CVIEWBUTTONDELEGATE_H +#define _CVIEWBUTTONDELEGATE_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + \brief A delegate to create a reference view button. +*/ +class cViewButtonDelegate : public QStyledItemDelegate { + + Q_OBJECT + +public: + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cViewButtonDelegate(QObject* parent = (QObject *)0); + + + /** + \brief Reimplementation of displayText. + \param value a value + \param locale a locale + \retval QString the value as a string + */ + QString displayText(const QVariant& value, const QLocale& locale) const; + + + /** + \brief Reimplementation of paint. + \param painter QPainter + \param option QStyleOptionViewItem + \param index QModelIndex + */ + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + + +protected: + + + /** + \brief Reimplementation of editorEvent. + \param event QEvent + \param model QAbstractItemModel + \param option QStyleOptionViewItem + \param index QModelIndex + */ + bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index); + +}; + + +#endif + diff --git a/CycloBranch/images.qrc b/CycloBranch/images.qrc index fcfad08..1ffa0c5 100644 --- a/CycloBranch/images.qrc +++ b/CycloBranch/images.qrc @@ -35,5 +35,12 @@ images/icons/25.png images/icons/43.png images/icons/23.png + images/icons/63.png + images/icons/13.png + images/icons/14.png + images/icons/38.png + images/icons/38b.png + images/icons/86.png + images/icons/42a.png diff --git a/CycloBranch/images/icons/13.png b/CycloBranch/images/icons/13.png new file mode 100644 index 0000000..230556b Binary files /dev/null and b/CycloBranch/images/icons/13.png differ diff --git a/CycloBranch/images/icons/14.png b/CycloBranch/images/icons/14.png new file mode 100644 index 0000000..24bb6ab Binary files /dev/null and b/CycloBranch/images/icons/14.png differ diff --git a/CycloBranch/images/icons/38.png b/CycloBranch/images/icons/38.png new file mode 100644 index 0000000..64fcab7 Binary files /dev/null and b/CycloBranch/images/icons/38.png differ diff --git a/CycloBranch/images/icons/38b.png b/CycloBranch/images/icons/38b.png new file mode 100644 index 0000000..cce8bea Binary files /dev/null and b/CycloBranch/images/icons/38b.png differ diff --git a/CycloBranch/images/icons/42a.png b/CycloBranch/images/icons/42a.png new file mode 100644 index 0000000..73ef5fc Binary files /dev/null and b/CycloBranch/images/icons/42a.png differ diff --git a/CycloBranch/images/icons/63.png b/CycloBranch/images/icons/63.png new file mode 100644 index 0000000..c795f31 Binary files /dev/null and b/CycloBranch/images/icons/63.png differ diff --git a/CycloBranch/images/icons/86.png b/CycloBranch/images/icons/86.png new file mode 100644 index 0000000..edba9ba Binary files /dev/null and b/CycloBranch/images/icons/86.png differ diff --git a/CycloBranch/main.cpp b/CycloBranch/main.cpp index 67a5703..894d2b2 100644 --- a/CycloBranch/main.cpp +++ b/CycloBranch/main.cpp @@ -30,6 +30,7 @@ int main(int argc, char** argv) { qRegisterMetaType >("vector"); qRegisterMetaType("string"); qRegisterMetaType("cFragmentIons"); + qRegisterMetaType >("vector"); QPixmap pixmap(":/images/splash.png"); QSplashScreen splash(pixmap); diff --git a/CycloBranch/parallel/cGraphReaderThread.cpp b/CycloBranch/parallel/cGraphReaderThread.cpp index 9b5b8fa..4eaa4a5 100644 --- a/CycloBranch/parallel/cGraphReaderThread.cpp +++ b/CycloBranch/parallel/cGraphReaderThread.cpp @@ -3,7 +3,7 @@ #include "gui/cMainThread.h" -int cGraphReaderThread::getCandidatesIter(bool cterminalstartingnode, cCandidateSet* candidates, int nodeid, vector& composition, double precursormass, int startmodifID, int endmodifID, int middlemodifID, int middlepos, vector& perspectivepath, double cummass, bool* terminatecomputation) { +int cGraphReaderThread::getCandidatesIter(eFragmentIonType startiontype, cCandidateSet* candidates, int nodeid, vector& composition, double precursormass, int startmodifID, int endmodifID, int middlemodifID, int middlepos, vector& perspectivepath, double cummass, string& startsummary, bool* terminatecomputation) { nodeEdge ne; int tmpmiddlemodifID = 0; int finish; @@ -62,7 +62,7 @@ int cGraphReaderThread::getCandidatesIter(bool cterminalstartingnode, cCandidate } composition.push_back((*graph)[nodeid][i].composition); - finish = getCandidatesIter(cterminalstartingnode, candidates, (*graph)[nodeid][i].targetnode, composition, precursormass, startmodifID, (*graph)[nodeid][i].endmodifID, tmpmiddlemodifID, middlepos, perspectivepath, cummass + (*graph)[nodeid][i].massdifference, terminatecomputation); + finish = getCandidatesIter(startiontype, candidates, (*graph)[nodeid][i].targetnode, composition, precursormass, startmodifID, (*graph)[nodeid][i].endmodifID, tmpmiddlemodifID, middlepos, perspectivepath, cummass + (*graph)[nodeid][i].massdifference, startsummary, terminatecomputation); composition.pop_back(); perspectivepath.pop_back(); @@ -74,14 +74,16 @@ int cGraphReaderThread::getCandidatesIter(bool cterminalstartingnode, cCandidate } } else { - cCandidate candidate(composition, perspectivepath, startmodifID, endmodifID, middlemodifID, middlepos); + cCandidate candidate(composition, perspectivepath, startiontype, startmodifID, endmodifID, middlemodifID, middlepos); - if (!cterminalstartingnode && (((parameters->peptidetype == linear) && !parameters->cyclicnterminus && !parameters->cycliccterminus) || (parameters->peptidetype == branched) || (parameters->peptidetype == linearpolysaccharide))) { + bool cterminalstartingnode = ((parameters->peptidetype == linear) || (parameters->peptidetype == branched) || (parameters->peptidetype == branchcyclic)) && (startiontype == y_ion); + + if (!cterminalstartingnode && (((parameters->peptidetype == linear) && !parameters->cyclicnterminus && !parameters->cycliccterminus) || (parameters->peptidetype == branched))) { if (candidate.hasLastBrickArtificial(*bricksdatabasewithcombinations) && (composition.size() > 0)) { bid = atoi(composition.back().c_str()) + 1; // offset of -H2O brick composition.pop_back(); composition.push_back(to_string(bid)); - candidate.setCandidate(composition, perspectivepath, startmodifID, endmodifID, middlemodifID, middlepos); + candidate.setCandidate(composition, perspectivepath, startiontype, startmodifID, endmodifID, middlemodifID, middlepos); } } @@ -94,108 +96,25 @@ int cGraphReaderThread::getCandidatesIter(bool cterminalstartingnode, cCandidate } composition.pop_back(); composition.push_back(to_string(bid)); - candidate.setCandidate(composition, perspectivepath, startmodifID, endmodifID, middlemodifID, middlepos); + candidate.setCandidate(composition, perspectivepath, startiontype, startmodifID, endmodifID, middlemodifID, middlepos); } -#if OLIGOKETIDES == 1 - if ((parameters->peptidetype == linearoligoketide) && candidate.hasLastBrickArtificial(*bricksdatabasewithcombinations) && (composition.size() > 0) && (perspectivepath.size() > 0)) { - - if ((*graph)[perspectivepath[0].nodeid].checkIonAnnotation(l1h_ion)) { - switch (candidate.getKetidePrecursorType(*bricksdatabasewithcombinations)) - { - case ketide_precursor_h2o: - bid = atoi(composition.back().c_str()) + 1; // offset of -H2O brick - break; - case ketide_precursor_h2: - bid = atoi(composition.back().c_str()) + 3; // offset of -H2 brick - break; - case ketide_precursor_h2o2: - bid = atoi(composition.back().c_str()) + 8; // offset of -H2O2 brick - break; - default: - bid = atoi(composition.back().c_str()); // nop - break; - } - composition.pop_back(); - composition.push_back(to_string(bid)); - candidate.setCandidate(composition, perspectivepath, startmodifID, endmodifID, middlemodifID, middlepos); - } - - if ((*graph)[perspectivepath[0].nodeid].checkIonAnnotation(l2h_ion)) { - switch (candidate.getKetidePrecursorType(*bricksdatabasewithcombinations)) - { - case ketide_precursor_h2o: - bid = atoi(composition.back().c_str()) + 4; // offset of -O brick - break; - case ketide_precursor_h2: - bid = atoi(composition.back().c_str()); // nop - break; - case ketide_precursor_h2o2: - bid = atoi(composition.back().c_str()) + 6; // offset of -O2 brick - break; - default: - bid = atoi(composition.back().c_str()); // nop - break; - } - composition.pop_back(); - composition.push_back(to_string(bid)); - candidate.setCandidate(composition, perspectivepath, startmodifID, endmodifID, middlemodifID, middlepos); - } - - if ((*graph)[perspectivepath[0].nodeid].checkIonAnnotation(l1oh_ion)) { - switch (candidate.getKetidePrecursorType(*bricksdatabasewithcombinations)) - { - case ketide_precursor_h2o: - bid = atoi(composition.back().c_str()) + 3; // offset of -H2 brick - break; - case ketide_precursor_h2: - bid = atoi(composition.back().c_str()) + 7; // offset of -H2+O brick - break; - case ketide_precursor_h2o2: - bid = atoi(composition.back().c_str()) + 1; // offset of -H2O brick - break; - default: - bid = atoi(composition.back().c_str()); // nop - break; - } - composition.pop_back(); - composition.push_back(to_string(bid)); - candidate.setCandidate(composition, perspectivepath, startmodifID, endmodifID, middlemodifID, middlepos); - } + if ((candidate.getComposition().compare("") != 0) && !candidate.hasOnlyArtificialBricks(*bricksdatabasewithcombinations) && !candidate.hasLastBrickInvalid(*bricksdatabasewithcombinations)) { - if ((*graph)[perspectivepath[0].nodeid].checkIonAnnotation(l2oh_ion)) { - switch (candidate.getKetidePrecursorType(*bricksdatabasewithcombinations)) - { - case ketide_precursor_h2o: - bid = atoi(composition.back().c_str()); // nop - break; - case ketide_precursor_h2: - bid = atoi(composition.back().c_str()) + 5; // offset of +O brick - break; - case ketide_precursor_h2o2: - bid = atoi(composition.back().c_str()) + 4; // offset of -O brick - break; - default: - bid = atoi(composition.back().c_str()); // nop - break; - } - composition.pop_back(); - composition.push_back(to_string(bid)); - candidate.setCandidate(composition, perspectivepath, startmodifID, endmodifID, middlemodifID, middlepos); + cEdge lastedge; + if (perspectivepath.size() > 0) { + lastedge = (*graph)[perspectivepath.back().nodeid][perspectivepath.back().edgeid]; } - - } -#endif - if ((candidate.getComposition().compare("") != 0) && !candidate.hasOnlyArtificialBricks(*bricksdatabasewithcombinations) && !candidate.hasLastBrickInvalid(*bricksdatabasewithcombinations)) { + if (isInPpmMassErrorTolerance(precursormass, getCandidatePrecursorMass(startsummary, perspectivepath), parameters->precursormasserrortolerance) + && (candidate.hasLastBrickArtificial(*bricksdatabasewithcombinations) || ((startiontype != fragmentIonTypeEnd) && (startiontype == lastedge.sourceion) + && ((lastedge.targetion == precursor_ion) || ((parameters->peptidetype != linear) && (parameters->peptidetype != branched))) + && ((lastedge.targetion == linear_polyketide_precursor_ion_h_h) || (lastedge.targetion == linear_polyketide_precursor_ion_h_oh) || (lastedge.targetion == linear_polyketide_precursor_ion_oh_oh) || (parameters->peptidetype != linearpolyketide)) + && ((lastedge.targetion == cyclic_polyketide_precursor_ion) || (parameters->peptidetype != cyclicpolyketide))))) { - if (isInPpmMassErrorTolerance(precursormass, candidate.getPrecursorMass(*bricksdatabasewithcombinations, parameters), parameters->precursormasserrortolerance) -#if OLIGOKETIDES == 1 - && (((parameters->peptidetype != linearoligoketide) && (parameters->peptidetype != cyclicoligoketide)) || candidate.checkKetideBlocks(*bricksdatabasewithcombinations, parameters->peptidetype)) -#endif - ) { - cCandidateSet result; + cSummaryFormula sumform = getCandidateSummaryFormula(startsummary, perspectivepath); + candidate.setSummaryFormula(sumform); if (cterminalstartingnode) { candidate.revertComposition(); @@ -218,6 +137,51 @@ int cGraphReaderThread::getCandidatesIter(bool cterminalstartingnode, cCandidate } } } + else if ((parameters->peptidetype == linearpolyketide) && candidate.hasLastBrickArtificial(*bricksdatabasewithcombinations) && (composition.size() > 0) && (perspectivepath.size() > 0)) { + + if (scanmode == 0) { + + candidates->lock(); + cSummaryFormula candidateformula = candidate.getSummaryFormula(); + + if ((*graph)[perspectivepath[0].nodeid].checkIonAnnotation(l1h_ion) || (*graph)[perspectivepath[0].nodeid].checkIonAnnotation(l1oh_ion)) { + bid = atoi(composition.back().c_str()) + 1; // offset of -H2O brick + composition.pop_back(); + composition.push_back(to_string(bid)); + candidate.setCandidate(composition, perspectivepath, startiontype, startmodifID, endmodifID, middlemodifID, middlepos); + candidate.setSummaryFormula(candidateformula); + candidates->getSet().insert(candidate); + + bid = atoi(composition.back().c_str()) + 3; // offset of -H2 brick + composition.pop_back(); + composition.push_back(to_string(bid)); + candidate.setCandidate(composition, perspectivepath, startiontype, startmodifID, endmodifID, middlemodifID, middlepos); + candidate.setSummaryFormula(candidateformula); + candidates->getSet().insert(candidate); + } + + if ((*graph)[perspectivepath[0].nodeid].checkIonAnnotation(l2h_ion) || (*graph)[perspectivepath[0].nodeid].checkIonAnnotation(l2oh_ion)) { + candidates->getSet().insert(candidate); // nop + + bid = atoi(composition.back().c_str()) + 4; // offset of -O brick + composition.pop_back(); + composition.push_back(to_string(bid)); + candidate.setCandidate(composition, perspectivepath, startiontype, startmodifID, endmodifID, middlemodifID, middlepos); + candidate.setSummaryFormula(candidateformula); + candidates->getSet().insert(candidate); + } + + candidates->unlock(); + + } + else { + *count += 2; + if (*count > maximumcandidates) { + return -1; + } + } + + } else { if (scanmode == 0) { candidates->lock(); @@ -258,6 +222,38 @@ int cGraphReaderThread::getCandidatesIter(bool cterminalstartingnode, cCandidate } +double cGraphReaderThread::getCandidatePrecursorMass(string& startsummary, vector& perspectivepath) { + double mass = 0; + cSummaryFormula formula; + formula.addFormula(startsummary); + for (int i = 0; i < (int)perspectivepath.size(); i++) { + if ((*graph)[perspectivepath[i].nodeid][perspectivepath[i].edgeid].summary.empty()) { + mass += (*graph)[perspectivepath[i].nodeid][perspectivepath[i].edgeid].massdifference; + } + else { + formula.addFormula((*graph)[perspectivepath[i].nodeid][perspectivepath[i].edgeid].summary); + } + } + return mass + formula.getMass(); +} + + +cSummaryFormula cGraphReaderThread::getCandidateSummaryFormula(string& startsummary, vector& perspectivepath) { + cSummaryFormula formula; + formula.setPartial(false); + formula.addFormula(startsummary); + for (int i = 0; i < (int)perspectivepath.size(); i++) { + formula.addFormula((*graph)[perspectivepath[i].nodeid][perspectivepath[i].edgeid].summary); + if ((*graph)[perspectivepath[i].nodeid][perspectivepath[i].edgeid].summary.empty()) { + formula.setPartial(true); + } + } + string s = "Hplus"; + formula.addFormula(s, true); + return formula; +} + + cGraphReaderThread::cGraphReaderThread() { graph = 0; bricksdatabasewithcombinations = 0; @@ -290,69 +286,50 @@ void cGraphReaderThread::initialize(vector& graph, cBricksData void cGraphReaderThread::run() { vector composition; vector perspectivepath; - int startmodifID = 0; + cEdge e; double unchargedprecursormass = charge(uncharge(parameters->precursormass, parameters->precursorcharge), (parameters->precursorcharge > 0)?1:-1); switch (parameters->peptidetype) { case cyclic: - if (getCandidatesIter(false, candidates, 0, composition, unchargedprecursormass, 0, 0, 0, -1, perspectivepath, (*graph)[0].getMZRatio(), terminatecomputation) == -1) { + e = (*graph)[0][0]; + if (getCandidatesIter(e.targetion, candidates, e.targetnode, composition, unchargedprecursormass, 0, 0, 0, -1, perspectivepath, (*graph)[e.targetnode].getMZRatio(), e.summary, terminatecomputation) == -1) { // terminated return; } break; case linear: case branched: - for (int i = 1; i <= lastsystemnode; i++) { - if (i - 2 > 0) { - startmodifID = i - 2; - } - if (getCandidatesIter((*graph)[i].checkIonAnnotation(y_ion), candidates, i, composition, unchargedprecursormass, startmodifID, 0, 0, -1, perspectivepath, (*graph)[i].getMZRatio(), terminatecomputation) == -1) { + for (int i = 0; i < (*graph)[0].size(); i++) { + e = (*graph)[0][i]; + if (getCandidatesIter(e.targetion, candidates, e.targetnode, composition, unchargedprecursormass, e.startmodifID, 0, 0, -1, perspectivepath, (*graph)[e.targetnode].getMZRatio(), e.summary, terminatecomputation) == -1) { // terminated return; } } break; case branchcyclic: - for (int i = 1; i <= lastsystemnode; i++) { - if (i - 1/*2*/ > 0) { - startmodifID = i - 1/*2*/; - } - if (parameters->searchedmodifications[startmodifID].nterminal) { - if (getCandidatesIter((*graph)[i].checkIonAnnotation(y_ion), candidates, i, composition, unchargedprecursormass, startmodifID, 0, 0, -1, perspectivepath, (*graph)[i].getMZRatio(), terminatecomputation) == -1) { - // terminated - return; - } - } - } - break; -#if OLIGOKETIDES == 1 - case linearoligoketide: - for (int i = 1; i <= lastsystemnode; i++) { - if (i - 4 > 0) { - startmodifID = i - 4; - } - if (getCandidatesIter(false, candidates, i, composition, unchargedprecursormass, startmodifID, 0, 0, -1, perspectivepath, (*graph)[i].getMZRatio(), terminatecomputation) == -1) { + for (int i = 0; i < (*graph)[0].size(); i++) { + e = (*graph)[0][i]; + if (getCandidatesIter(e.targetion, candidates, e.targetnode, composition, unchargedprecursormass, e.startmodifID, 0, 0, -1, perspectivepath, (*graph)[e.targetnode].getMZRatio(), e.summary, terminatecomputation) == -1) { // terminated return; } } break; - case cyclicoligoketide: - for (int i = 1; i <= lastsystemnode; i++) { - if (getCandidatesIter(false, candidates, i, composition, unchargedprecursormass, 0, 0, 0, -1, perspectivepath, (*graph)[i].getMZRatio(), terminatecomputation) == -1) { + case linearpolyketide: + for (int i = 0; i < (*graph)[0].size(); i++) { + e = (*graph)[0][i]; + if (getCandidatesIter(e.targetion, candidates, e.targetnode, composition, unchargedprecursormass, e.startmodifID, 0, 0, -1, perspectivepath, (*graph)[e.targetnode].getMZRatio(), e.summary, terminatecomputation) == -1) { // terminated return; } } break; -#endif - case linearpolysaccharide: - for (int i = 1; i <= lastsystemnode; i++) { - if (i - 1 > 0) { - startmodifID = i - 1; - } - if (getCandidatesIter((*graph)[i].checkIonAnnotation(y_ion), candidates, i, composition, unchargedprecursormass, startmodifID, 0, 0, -1, perspectivepath, (*graph)[i].getMZRatio(), terminatecomputation) == -1) { + case cyclicpolyketide: + for (int i = 0; i < (*graph)[0].size(); i++) { + e = (*graph)[0][i]; + if (getCandidatesIter(e.targetion, candidates, e.targetnode, composition, unchargedprecursormass, 0, 0, 0, -1, perspectivepath, (*graph)[e.targetnode].getMZRatio(), e.summary, terminatecomputation) == -1) { // terminated return; } diff --git a/CycloBranch/parallel/cGraphReaderThread.h b/CycloBranch/parallel/cGraphReaderThread.h index 81457e8..b90a318 100644 --- a/CycloBranch/parallel/cGraphReaderThread.h +++ b/CycloBranch/parallel/cGraphReaderThread.h @@ -44,7 +44,11 @@ class cGraphReaderThread : public QThread { int scanmode; bool* terminatecomputation; - int getCandidatesIter(bool cterminalstartingnode, cCandidateSet* candidates, int nodeid, vector& composition, double precursormass, int startmodifID, int endmodifID, int middlemodifID, int middlepos, vector& perspectivepath, double cummass, bool* terminatecomputation); + int getCandidatesIter(eFragmentIonType startiontype, cCandidateSet* candidates, int nodeid, vector& composition, double precursormass, int startmodifID, int endmodifID, int middlemodifID, int middlepos, vector& perspectivepath, double cummass, string& startsummary, bool* terminatecomputation); + + double getCandidatePrecursorMass(string& startsummary, vector& perspectivepath); + + cSummaryFormula getCandidateSummaryFormula(string& startsummary, vector& perspectivepath); public: diff --git a/CycloBranch/parallel/cSpectrumComparatorThread.cpp b/CycloBranch/parallel/cSpectrumComparatorThread.cpp index 83e9222..a6969a8 100644 --- a/CycloBranch/parallel/cSpectrumComparatorThread.cpp +++ b/CycloBranch/parallel/cSpectrumComparatorThread.cpp @@ -13,6 +13,12 @@ bool compareBandAllIonsDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpe if (a.getNumberOfMatchedPeaks() > b.getNumberOfMatchedPeaks()) { return true; } + if (a.getNumberOfMatchedPeaks() < b.getNumberOfMatchedPeaks()) { + return false; + } + if (a.getPathId() < b.getPathId()) { + return true; + } return false; } @@ -27,6 +33,12 @@ bool compareBBwaterLossAndAllIonsDesc(const cTheoreticalSpectrum& a, const cTheo if (a.getNumberOfMatchedPeaks() > b.getNumberOfMatchedPeaks()) { return true; } + if (a.getNumberOfMatchedPeaks() < b.getNumberOfMatchedPeaks()) { + return false; + } + if (a.getPathId() < b.getPathId()) { + return true; + } return false; } @@ -41,6 +53,12 @@ bool compareBBammoniaLossAndAllIonsDesc(const cTheoreticalSpectrum& a, const cTh if (a.getNumberOfMatchedPeaks() > b.getNumberOfMatchedPeaks()) { return true; } + if (a.getNumberOfMatchedPeaks() < b.getNumberOfMatchedPeaks()) { + return false; + } + if (a.getPathId() < b.getPathId()) { + return true; + } return false; } @@ -55,6 +73,12 @@ bool compareYBandAllIonsDesc(const cTheoreticalSpectrum& a, const cTheoreticalSp if (a.getNumberOfMatchedPeaks() > b.getNumberOfMatchedPeaks()) { return true; } + if (a.getNumberOfMatchedPeaks() < b.getNumberOfMatchedPeaks()) { + return false; + } + if (a.getPathId() < b.getPathId()) { + return true; + } return false; } @@ -69,22 +93,55 @@ bool compareYandAllIonsDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpe if (a.getNumberOfMatchedPeaks() > b.getNumberOfMatchedPeaks()) { return true; } + if (a.getNumberOfMatchedPeaks() < b.getNumberOfMatchedPeaks()) { + return false; + } + if (a.getPathId() < b.getPathId()) { + return true; + } return false; } bool compareWeightedIntensityDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b) { - return (a.getWeightedIntensityScore() > b.getWeightedIntensityScore()); + if (a.getWeightedIntensityScore() > b.getWeightedIntensityScore()) { + return true; + } + if (a.getWeightedIntensityScore() < b.getWeightedIntensityScore()) { + return false; + } + if (a.getPathId() < b.getPathId()) { + return true; + } + return false; } bool compareNumberOfMatchedPeaksDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b) { - return (a.getNumberOfMatchedPeaks() > b.getNumberOfMatchedPeaks()); + if (a.getNumberOfMatchedPeaks() > b.getNumberOfMatchedPeaks()) { + return true; + } + if (a.getNumberOfMatchedPeaks() < b.getNumberOfMatchedPeaks()) { + return false; + } + if (a.getPathId() < b.getPathId()) { + return true; + } + return false; } bool compareNumberOfMatchedBricksDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b) { - return (a.getNumberOfMatchedBricks() > b.getNumberOfMatchedBricks()); + if (a.getNumberOfMatchedBricks() > b.getNumberOfMatchedBricks()) { + return true; + } + if (a.getNumberOfMatchedBricks() < b.getNumberOfMatchedBricks()) { + return false; + } + if (a.getPathId() < b.getPathId()) { + return true; + } + return false; } @@ -117,6 +174,8 @@ void cSpectrumComparatorThread::run() { tsp.resizePeakList(5000); int theoreticalpeaksrealsize = 0; + double unchargedprecursormass = charge(uncharge(parameters->precursormass, parameters->precursorcharge), (parameters->precursorcharge > 0)?1:-1); + for (auto i = permutations.getSet().begin(); i != permutations.getSet().end(); ++i) { if (*terminatecomputation) { @@ -128,6 +187,12 @@ void cSpectrumComparatorThread::run() { tsp.setParameters(parameters); tsp.setCandidate((cCandidate&)*i); + if ((parameters->peptidetype == linearpolyketide) || (parameters->peptidetype == cyclicpolyketide)) { + if (!tsp.getCandidate().checkKetideBlocks(*bricksdatabasewithcombinations, parameters->peptidetype, parameters->regularblocksorder)) { + continue; + } + } + switch (parameters->peptidetype) { case linear: @@ -142,16 +207,11 @@ void cSpectrumComparatorThread::run() { case branchcyclic: theoreticalpeaksrealsize = tsp.compareBranchCyclic(peaklist, *bricksdatabasewithcombinations, false, *rxsequencetag, *rxsearchedsequence); break; -#if OLIGOKETIDES == 1 - case linearoligoketide: - theoreticalpeaksrealsize = tsp.compareLinearOligoketide(peaklist, *bricksdatabasewithcombinations, false, *rxsequencetag, *rxsearchedsequence); - break; - case cyclicoligoketide: - theoreticalpeaksrealsize = tsp.compareCyclicOligoketide(peaklist, *bricksdatabasewithcombinations, false, *rxsequencetag, *rxsearchedsequence); + case linearpolyketide: + theoreticalpeaksrealsize = tsp.compareLinearPolyketide(peaklist, *bricksdatabasewithcombinations, false, *rxsequencetag, *rxsearchedsequence); break; -#endif - case linearpolysaccharide: - theoreticalpeaksrealsize = tsp.compareLinearPolysaccharide(peaklist, *bricksdatabasewithcombinations, false, *rxsequencetag, *rxsearchedsequence); + case cyclicpolyketide: + theoreticalpeaksrealsize = tsp.compareCyclicPolyketide(peaklist, *bricksdatabasewithcombinations, false, *rxsequencetag, *rxsearchedsequence); break; case other: break;
" << results->horizontalHeaderItem(i)->text() << "" << resultsmodel->horizontalHeaderItem(i)->text() << "
Ion TypeGroup IDFragment Type