From cb3bbfb7e609b069b6a048e384458d1ae38e69c4 Mon Sep 17 00:00:00 2001 From: Jiri Novak Date: Wed, 21 Feb 2018 15:18:58 +0100 Subject: [PATCH] release 1.0.1216 --- CycloBranch.sln | 1 - CycloBranch/CycloBranch-Linux.pro | 91 +++++ CycloBranch/CycloBranch-MacOSX.pro | 99 +++++ CycloBranch/CycloBranch.vcxproj | 58 ++- CycloBranch/CycloBranch.vcxproj.filters | 24 ++ CycloBranch/core/cBricksDatabase.cpp | 29 +- CycloBranch/core/cBricksDatabase.h | 6 +- CycloBranch/core/cCandidate.cpp | 24 +- CycloBranch/core/cCandidate.h | 16 +- CycloBranch/core/cDeNovoGraph.cpp | 47 ++- CycloBranch/core/cDeNovoGraph.h | 3 +- CycloBranch/core/cFragmentIons.cpp | 75 +++- CycloBranch/core/cFragmentIons.h | 73 ++++ CycloBranch/core/cParameters.cpp | 46 ++- CycloBranch/core/cParameters.h | 6 + CycloBranch/core/cSequence.cpp | 15 +- CycloBranch/core/cSequence.h | 2 +- CycloBranch/core/cSequenceDatabase.cpp | 2 +- CycloBranch/core/cSummaryFormula.cpp | 22 +- CycloBranch/core/cSummaryFormula.h | 30 +- CycloBranch/core/cTheoreticalSpectrum.cpp | 73 +++- CycloBranch/core/utilities.cpp | 15 +- CycloBranch/core/utilities.h | 16 +- CycloBranch/gui/cAboutWidget.cpp | 4 +- CycloBranch/gui/cBranchedWidget.cpp | 2 +- CycloBranch/gui/cBricksDatabaseWidget.cpp | 190 ++++++++- CycloBranch/gui/cBricksDatabaseWidget.h | 24 +- CycloBranch/gui/cCyclicWidget.cpp | 2 +- CycloBranch/gui/cDrawPeptideWidget.cpp | 8 +- CycloBranch/gui/cExportDialog.cpp | 52 +++ CycloBranch/gui/cExportDialog.h | 59 +++ CycloBranch/gui/cFindDialog.cpp | 58 +++ CycloBranch/gui/cFindDialog.h | 62 +++ CycloBranch/gui/cGraphWidget.cpp | 2 +- CycloBranch/gui/cLassoWidget.cpp | 2 +- CycloBranch/gui/cLinearWidget.cpp | 2 +- CycloBranch/gui/cMainThread.cpp | 6 +- CycloBranch/gui/cMainWindow.cpp | 417 +++++++++++++++----- CycloBranch/gui/cMainWindow.h | 28 +- CycloBranch/gui/cModificationsWidget.cpp | 211 ++++++++-- CycloBranch/gui/cModificationsWidget.h | 26 +- CycloBranch/gui/cParametersWidget.cpp | 46 ++- CycloBranch/gui/cParametersWidget.h | 4 + CycloBranch/gui/cSequenceDatabaseWidget.cpp | 197 ++++++++- CycloBranch/gui/cSequenceDatabaseWidget.h | 27 +- CycloBranch/gui/cSpectrumDetailWidget.cpp | 306 ++++++++++---- CycloBranch/gui/cSpectrumDetailWidget.h | 35 +- CycloBranch/gui/cSpectrumSceneWidget.cpp | 6 +- CycloBranch/images.qrc | 5 +- CycloBranch/images/cb.icns | Bin 0 -> 35090 bytes CycloBranch/images/icons/56.png | Bin 0 -> 645 bytes CycloBranch/images/icons/65.png | Bin 0 -> 986 bytes CycloBranch/images/icons/66.png | Bin 0 -> 1187 bytes CycloBranch/images/icons/95.png | Bin 0 -> 1068 bytes CycloBranch/main.cpp | 4 +- CycloBranch/parallel/cGraphReaderThread.cpp | 10 + CycloBranch/readme-macosx-compile.txt | 18 + 57 files changed, 2229 insertions(+), 357 deletions(-) create mode 100644 CycloBranch/CycloBranch-Linux.pro create mode 100644 CycloBranch/CycloBranch-MacOSX.pro create mode 100644 CycloBranch/gui/cExportDialog.cpp create mode 100644 CycloBranch/gui/cExportDialog.h create mode 100644 CycloBranch/gui/cFindDialog.cpp create mode 100644 CycloBranch/gui/cFindDialog.h create mode 100644 CycloBranch/images/cb.icns create mode 100644 CycloBranch/images/icons/56.png create mode 100644 CycloBranch/images/icons/65.png create mode 100644 CycloBranch/images/icons/66.png create mode 100644 CycloBranch/images/icons/95.png create mode 100644 CycloBranch/readme-macosx-compile.txt diff --git a/CycloBranch.sln b/CycloBranch.sln index cae5bf9..a6fcc20 100644 --- a/CycloBranch.sln +++ b/CycloBranch.sln @@ -1,4 +1,3 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CycloBranch", "CycloBranch\CycloBranch.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}" diff --git a/CycloBranch/CycloBranch-Linux.pro b/CycloBranch/CycloBranch-Linux.pro new file mode 100644 index 0000000..996dcea --- /dev/null +++ b/CycloBranch/CycloBranch-Linux.pro @@ -0,0 +1,91 @@ +###################################################################### +# Automatically generated by qmake (3.0) Fri Dec 5 03:02:26 2014 +###################################################################### + +TEMPLATE = app +TARGET = CycloBranch +QT += core gui widgets printsupport svg +INCLUDEPATH += . core gui parallel +QMAKE_CXXFLAGS += -std=c++0x -DLINUX -m64 +QMAKE_LIBS += -lboost_regex +OBJECTS_DIR = build/ +MOC_DIR = moc/ + +# Input +RESOURCES = images.qrc +HEADERS += core/cAllocator.h \ + core/cBrick.h \ + core/cBricksDatabase.h \ + core/cCandidate.h \ + core/cCandidateSet.h \ + core/cDeNovoGraph.h \ + core/cDeNovoGraphNode.h \ + core/cFragmentIons.h \ + core/cParameters.h \ + core/cPeak.h \ + core/cPeaksList.h \ + core/cSequence.h \ + core/cSequenceDatabase.h \ + core/cSummaryFormula.h \ + core/cTheoreticalSpectrum.h \ + core/cTheoreticalSpectrumList.h \ + core/utilities.h \ + gui/cAboutWidget.h \ + gui/cBranchedWidget.h \ + gui/cBricksDatabaseWidget.h \ + gui/cCyclicWidget.h \ + gui/cDrawPeptideWidget.h \ + gui/cEventFilter.h \ + gui/cExportDialog.h \ + gui/cFindDialog.h \ + gui/cFragmentIonsListWidget.h \ + gui/cGraphWidget.h \ + gui/cLassoWidget.h \ + gui/cLinearWidget.h \ + gui/cMainThread.h \ + gui/cMainWindow.h \ + gui/cModificationsWidget.h \ + gui/cParametersWidget.h \ + gui/cSequenceDatabaseWidget.h \ + gui/cSpectrumDetailWidget.h \ + gui/cSpectrumSceneWidget.h \ + parallel/cGraphReaderThread.h \ + parallel/cSpectrumComparatorThread.h +SOURCES += core/cBrick.cpp \ + core/cBricksDatabase.cpp \ + core/cCandidate.cpp \ + core/cCandidateSet.cpp \ + core/cDeNovoGraph.cpp \ + core/cDeNovoGraphNode.cpp \ + core/cFragmentIons.cpp \ + core/cParameters.cpp \ + core/cPeak.cpp \ + core/cPeaksList.cpp \ + core/cSequence.cpp \ + core/cSequenceDatabase.cpp \ + core/cSummaryFormula.cpp \ + core/cTheoreticalSpectrum.cpp \ + core/cTheoreticalSpectrumList.cpp \ + core/utilities.cpp \ + gui/cAboutWidget.cpp \ + gui/cBranchedWidget.cpp \ + gui/cBricksDatabaseWidget.cpp \ + gui/cCyclicWidget.cpp \ + gui/cDrawPeptideWidget.cpp \ + gui/cEventFilter.cpp \ + gui/cExportDialog.cpp \ + gui/cFindDialog.cpp \ + gui/cFragmentIonsListWidget.cpp \ + gui/cGraphWidget.cpp \ + gui/cLassoWidget.cpp \ + gui/cLinearWidget.cpp \ + gui/cMainThread.cpp \ + gui/cMainWindow.cpp \ + gui/cModificationsWidget.cpp \ + gui/cParametersWidget.cpp \ + gui/cSequenceDatabaseWidget.cpp \ + gui/cSpectrumDetailWidget.cpp \ + gui/cSpectrumSceneWidget.cpp \ + parallel/cGraphReaderThread.cpp \ + parallel/cSpectrumComparatorThread.cpp \ + main.cpp diff --git a/CycloBranch/CycloBranch-MacOSX.pro b/CycloBranch/CycloBranch-MacOSX.pro new file mode 100644 index 0000000..822b6d9 --- /dev/null +++ b/CycloBranch/CycloBranch-MacOSX.pro @@ -0,0 +1,99 @@ +###################################################################### +# Automatically generated by qmake (3.0) Fri Dec 5 03:02:26 2014 +###################################################################### + +TEMPLATE = app +TARGET = CycloBranch +QT += core gui widgets printsupport svg +INCLUDEPATH += . core gui parallel /usr/local/Cellar/boost/1.57.0/include +QMAKE_CXXFLAGS += -std=c++0x -DMACOSX -m64 +QMAKE_LIBS += -lboost_regex +QMAKE_LIBDIR = /usr/local/Cellar/boost/1.57.0/lib +OBJECTS_DIR = build/ +MOC_DIR = moc/ +ICON = images/cb.icns + +# The following variables must be manually fixed in the 'Makefile' generated by qmake. +# The variables QMAKE_CC, QMAKE_CXX and QMAKE_LINK are ignored by qmake. +#CC = /usr/local/Cellar/gcc/4.9.2_1/bin/gcc-4.9 +#CXX = /usr/local/Cellar/gcc/4.9.2_1/bin/g++-4.9 +#LINK = /usr/local/Cellar/gcc/4.9.2_1/bin/g++-4.9 + +# Input +RESOURCES = images.qrc +HEADERS += core/cAllocator.h \ + core/cBrick.h \ + core/cBricksDatabase.h \ + core/cCandidate.h \ + core/cCandidateSet.h \ + core/cDeNovoGraph.h \ + core/cDeNovoGraphNode.h \ + core/cFragmentIons.h \ + core/cParameters.h \ + core/cPeak.h \ + core/cPeaksList.h \ + core/cSequence.h \ + core/cSequenceDatabase.h \ + core/cSummaryFormula.h \ + core/cTheoreticalSpectrum.h \ + core/cTheoreticalSpectrumList.h \ + core/utilities.h \ + gui/cAboutWidget.h \ + gui/cBranchedWidget.h \ + gui/cBricksDatabaseWidget.h \ + gui/cCyclicWidget.h \ + gui/cDrawPeptideWidget.h \ + gui/cEventFilter.h \ + gui/cExportDialog.h \ + gui/cFindDialog.h \ + gui/cFragmentIonsListWidget.h \ + gui/cGraphWidget.h \ + gui/cLassoWidget.h \ + gui/cLinearWidget.h \ + gui/cMainThread.h \ + gui/cMainWindow.h \ + gui/cModificationsWidget.h \ + gui/cParametersWidget.h \ + gui/cSequenceDatabaseWidget.h \ + gui/cSpectrumDetailWidget.h \ + gui/cSpectrumSceneWidget.h \ + parallel/cGraphReaderThread.h \ + parallel/cSpectrumComparatorThread.h +SOURCES += core/cBrick.cpp \ + core/cBricksDatabase.cpp \ + core/cCandidate.cpp \ + core/cCandidateSet.cpp \ + core/cDeNovoGraph.cpp \ + core/cDeNovoGraphNode.cpp \ + core/cFragmentIons.cpp \ + core/cParameters.cpp \ + core/cPeak.cpp \ + core/cPeaksList.cpp \ + core/cSequence.cpp \ + core/cSequenceDatabase.cpp \ + core/cSummaryFormula.cpp \ + core/cTheoreticalSpectrum.cpp \ + core/cTheoreticalSpectrumList.cpp \ + core/utilities.cpp \ + gui/cAboutWidget.cpp \ + gui/cBranchedWidget.cpp \ + gui/cBricksDatabaseWidget.cpp \ + gui/cCyclicWidget.cpp \ + gui/cDrawPeptideWidget.cpp \ + gui/cEventFilter.cpp \ + gui/cExportDialog.cpp \ + gui/cFindDialog.cpp \ + gui/cFragmentIonsListWidget.cpp \ + gui/cGraphWidget.cpp \ + gui/cLassoWidget.cpp \ + gui/cLinearWidget.cpp \ + gui/cMainThread.cpp \ + gui/cMainWindow.cpp \ + gui/cModificationsWidget.cpp \ + gui/cParametersWidget.cpp \ + gui/cSequenceDatabaseWidget.cpp \ + gui/cSpectrumDetailWidget.cpp \ + gui/cSpectrumSceneWidget.cpp \ + parallel/cGraphReaderThread.cpp \ + parallel/cSpectrumComparatorThread.cpp \ + main.cpp diff --git a/CycloBranch/CycloBranch.vcxproj b/CycloBranch/CycloBranch.vcxproj index 12d8bf3..3431970 100644 --- a/CycloBranch/CycloBranch.vcxproj +++ b/CycloBranch/CycloBranch.vcxproj @@ -139,8 +139,8 @@ Windows $(OutDir)\$(ProjectName).exe $(QTDIR)\lib;C:\boost_1_57_0\lib64-msvc-11.0;%(AdditionalLibraryDirectories) - true - qtmain.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Svgd.lib;Qt5PrintSupport.lib;libboost_regex-vc110-mt-1_57.lib;%(AdditionalDependencies) + false + qtmain.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Svg.lib;Qt5PrintSupport.lib;libboost_regex-vc110-mt-1_57.lib;%(AdditionalDependencies) true true UseLinkTimeCodeGeneration @@ -187,6 +187,14 @@ true true + + true + true + + + true + true + true true @@ -273,6 +281,14 @@ true true + + true + true + + + true + true + true true @@ -331,6 +347,8 @@ + + @@ -362,6 +380,42 @@ + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cExportDialog.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 cExportDialog.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 cExportDialog.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 cExportDialog.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:\boost_1_57_0\boost" + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cFindDialog.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 cFindDialog.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 cFindDialog.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 cFindDialog.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:\boost_1_57_0\boost" + $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cSpectrumSceneWidget.h... diff --git a/CycloBranch/CycloBranch.vcxproj.filters b/CycloBranch/CycloBranch.vcxproj.filters index f42329c..aa5e87e 100644 --- a/CycloBranch/CycloBranch.vcxproj.filters +++ b/CycloBranch/CycloBranch.vcxproj.filters @@ -272,6 +272,24 @@ Generated Files\Release + + Generated Files\Debug + + + Generated Files\Release + + + Source Files\gui + + + Generated Files\Debug + + + Generated Files\Release + + + Source Files\gui + @@ -340,6 +358,12 @@ Header Files\gui + + Header Files\gui + + + Header Files\gui + diff --git a/CycloBranch/core/cBricksDatabase.cpp b/CycloBranch/core/cBricksDatabase.cpp index 810fde9..e1693b7 100644 --- a/CycloBranch/core/cBricksDatabase.cpp +++ b/CycloBranch/core/cBricksDatabase.cpp @@ -57,14 +57,19 @@ void generateBricksPermutations(vector& bricks, vector& currentp } -bool cBricksDatabase::nextCombination(vector& combarray, int numberofbasicbricks, int maximumbricksincombination, double maximumcumulativemass) { +bool cBricksDatabase::nextCombination(vector& combarray, int numberofbasicbricks, int maximumbricksincombination, double maximumcumulativemass, double neutralprecursormass) { int pointer = 0; int cyFlag = 0; + double mass; + do { + combarray[pointer]++; // set combarray[pointer] to the maximum value when outside of the mass range - if ((cyFlag == 0) && (combarray[pointer] <= numberofbasicbricks) && (maximumcumulativemass > 0) && (getMassOfComposition(combarray, maximumbricksincombination) > maximumcumulativemass)) { + mass = getMassOfComposition(combarray); + + if ((cyFlag == 0) && (combarray[pointer] <= numberofbasicbricks) && (((maximumcumulativemass > 0) && (mass > maximumcumulativemass)) || (mass > neutralprecursormass))) { combarray[pointer] = numberofbasicbricks + 1; } @@ -77,27 +82,35 @@ bool cBricksDatabase::nextCombination(vector& combarray, int numberofbasicb } // skip combinations outside of the mass range - while ((combarray[pointer] <= numberofbasicbricks) && (pointer < maximumbricksincombination - 1) && (maximumcumulativemass > 0) && (getMassOfComposition(combarray, maximumbricksincombination) > maximumcumulativemass)) { + mass = getMassOfComposition(combarray); + + while ((combarray[pointer] <= numberofbasicbricks) && (pointer < maximumbricksincombination - 1) && (((maximumcumulativemass > 0) && (mass > maximumcumulativemass)) || (mass > neutralprecursormass))) { pointer++; combarray[pointer]++; for (int i = pointer - 1; i >= 0; i--) { combarray[i] = combarray[pointer]; } + + mass = getMassOfComposition(combarray); } - if ((combarray[pointer] > numberofbasicbricks) || ((maximumcumulativemass > 0) && (getMassOfComposition(combarray, maximumbricksincombination) > maximumcumulativemass))) { + if ((combarray[pointer] > numberofbasicbricks) || ((maximumcumulativemass > 0) && (mass > maximumcumulativemass)) || (mass > neutralprecursormass)) { return false; } } return true; + } else { + cyFlag = 1; pointer++; + } + } while (pointer < maximumbricksincombination); return false; @@ -178,7 +191,7 @@ int cBricksDatabase::loadFromPlainTextStream(ifstream &stream, string& errormess } // load references - #if OS_TYPE == UNX + #if OS_TYPE != WIN if ((s.size() > 0) && (s.back() == '\r')) { s = s.substr(0, s.size() - 1); } @@ -252,12 +265,14 @@ cBrick& cBricksDatabase::operator[](int position) { } -double cBricksDatabase::getMassOfComposition(vector& combarray, int maximumbricksincombination) { +double cBricksDatabase::getMassOfComposition(vector& combarray) { double mass = 0; - for (int i = 0; i < maximumbricksincombination; i++) { + int i = 0; + while (i < (int)combarray.size()) { if (combarray[i] > 0) { mass += bricks[combarray[i] - 1].getMass(); } + i++; } return mass; } diff --git a/CycloBranch/core/cBricksDatabase.h b/CycloBranch/core/cBricksDatabase.h index c2a50de..ff62d24 100644 --- a/CycloBranch/core/cBricksDatabase.h +++ b/CycloBranch/core/cBricksDatabase.h @@ -75,9 +75,10 @@ class cBricksDatabase { \param numberofbasicbricks initial number of bricks in a database \param maximumbricksincombination maximum number of combined bricks \param maximumcumulativemass maximum cummulative mass of combined bricks + \param neutralprecursormass neutral precursor mass \retval bool true when a valid vector is stored in combarray, false when all valid vectors were already generated */ - bool nextCombination(vector& combarray, int numberofbasicbricks, int maximumbricksincombination, double maximumcumulativemass); + bool nextCombination(vector& combarray, int numberofbasicbricks, int maximumbricksincombination, double maximumcumulativemass, double neutralprecursormass); /** @@ -133,10 +134,9 @@ class cBricksDatabase { /** \brief Get the mass of a composition of bricks. \param combarray reference to an input integer vector of ids - \param maximumbricksincombination maximum number of bricks in a combination \retval double cumulative mass of the bricks in the \a combarray */ - double getMassOfComposition(vector& combarray, int maximumbricksincombination); + double getMassOfComposition(vector& combarray); /** diff --git a/CycloBranch/core/cCandidate.cpp b/CycloBranch/core/cCandidate.cpp index b7cdb27..c784205 100644 --- a/CycloBranch/core/cCandidate.cpp +++ b/CycloBranch/core/cCandidate.cpp @@ -867,7 +867,7 @@ bool cCandidate::compare(cCandidate& candidate) { } -vector& cCandidate::getPath() { +vector cCandidate::getPath() { return path; } @@ -896,7 +896,7 @@ bool cCandidate::hasOnlyArtificialBricks(cBricksDatabase& brickdatabasewithcombi if (numberofinternalbricks <= 2) { cBrick b; vector intcomposition; - b.setComposition(internalcomposition,false); + b.setComposition(internalcomposition, false); b.explodeToIntComposition(intcomposition); for (int i = 0; i < (int)intcomposition.size(); i++) { if (!brickdatabasewithcombinations[intcomposition[i] - 1].isArtificial()) { @@ -909,6 +909,18 @@ bool cCandidate::hasOnlyArtificialBricks(cBricksDatabase& brickdatabasewithcombi } +bool cCandidate::hasLastBrickArtificial(cBricksDatabase& brickdatabasewithcombinations) { + cBrick b; + vector intcomposition; + b.setComposition(internalcomposition, false); + b.explodeToIntComposition(intcomposition); + if ((intcomposition.size() > 0) && brickdatabasewithcombinations[intcomposition.back() - 1].isArtificial()) { + return true; + } + return false; +} + + void cCandidate::getRotations(vector& rotations, bool includerevertedrotations) { rotations.clear(); //rotations.push_back(composition); @@ -932,7 +944,7 @@ void cCandidate::getLassoRotations(vector& lassorotations, bool incl } -string cCandidate::getSummaryFormula(cParameters& parameters, peptideType peptidetype) { +cSummaryFormula cCandidate::getSummaryFormula(cParameters& parameters, peptideType peptidetype) { cBrick b; vector bricks; b.setComposition(internalcomposition, false); @@ -977,8 +989,10 @@ string cCandidate::getSummaryFormula(cParameters& parameters, peptideType peptid partial = true; } } - - return partial?formula.getFormula() + " (partial)":formula.getFormula(); + + formula.setPartial(partial); + + return formula; } diff --git a/CycloBranch/core/cCandidate.h b/CycloBranch/core/cCandidate.h index 145b90b..6204bf1 100644 --- a/CycloBranch/core/cCandidate.h +++ b/CycloBranch/core/cCandidate.h @@ -383,9 +383,9 @@ class cCandidate { /** \brief Get a path in the de novo graph corresponding to the peptide sequence candidate. - \retval vector reference to a vector of pairs node and edge + \retval vector vector of pairs node and edge */ - vector& getPath(); + vector getPath(); /** @@ -404,6 +404,14 @@ class cCandidate { bool hasOnlyArtificialBricks(cBricksDatabase& brickdatabasewithcombinations); + /** + \brief Check if the last brick is artificial. + \param brickdatabasewithcombinations reference to an input database of bricks with combinations of bricks + \retval bool true if the last brick is artificial, false otherwise + */ + bool hasLastBrickArtificial(cBricksDatabase& brickdatabasewithcombinations); + + /** \brief Get rotations of a cyclic peptide sequence. \param rotations reference to an output vector containing rotations of a sequence @@ -424,9 +432,9 @@ class cCandidate { \brief Get 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 string the summary formula + \retval cSummaryFormula the summary formula */ - string getSummaryFormula(cParameters& parameters, peptideType peptidetype); + cSummaryFormula getSummaryFormula(cParameters& parameters, peptideType peptidetype); /** diff --git a/CycloBranch/core/cDeNovoGraph.cpp b/CycloBranch/core/cDeNovoGraph.cpp index 9c9c1e8..4ae488b 100644 --- a/CycloBranch/core/cDeNovoGraph.cpp +++ b/CycloBranch/core/cDeNovoGraph.cpp @@ -22,7 +22,12 @@ cDeNovoGraph::cDeNovoGraph() { } -bool cDeNovoGraph::findPath(int sourcenodeid, int edgeid, int targetnodeid, string& composition, string brickspath, int maximumbricksincombination, vector& path) { +bool cDeNovoGraph::findPath(int sourcenodeid, int edgeid, int targetnodeid, string& composition, string brickspath, int maximumbricksincombination, vector& path, bool& terminatecomputation) { + + if (terminatecomputation) { + return false; + } + string localbrickpath; bool found; bool badpath; @@ -70,7 +75,7 @@ bool cDeNovoGraph::findPath(int sourcenodeid, int edgeid, int targetnodeid, stri ne.edgeid = i; path.push_back(ne); - found = findPath(graph[sourcenodeid][i].targetnode, i, targetnodeid, composition, localbrickpath, maximumbricksincombination, path); + found = findPath(graph[sourcenodeid][i].targetnode, i, targetnodeid, composition, localbrickpath, maximumbricksincombination, path, terminatecomputation); path.pop_back(); @@ -78,6 +83,10 @@ bool cDeNovoGraph::findPath(int sourcenodeid, int edgeid, int targetnodeid, stri //*os << graph[sourcenodeid].getMZRatio() << " "; return true; } + + if (terminatecomputation) { + return false; + } } } @@ -380,7 +389,7 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { combarray.push_back(0); } - while (bricksdatabasewithcombinations.nextCombination(combarray, numberofbasicbricks, parameters->maximumbricksincombination, parameters->maximumcumulativemass)) { + while (bricksdatabasewithcombinations.nextCombination(combarray, numberofbasicbricks, parameters->maximumbricksincombination, parameters->maximumcumulativemass, uncharge(parameters->precursormass, parameters->precursorcharge))) { if (terminatecomputation) { return -1; } @@ -400,7 +409,7 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { *os << "Generating combinations of bricks and generating edges... " << endl; int j = 0; - while (bricksdatabasewithcombinations.nextCombination(combarray, numberofbasicbricks, parameters->maximumbricksincombination, parameters->maximumcumulativemass)) { + while (bricksdatabasewithcombinations.nextCombination(combarray, numberofbasicbricks, parameters->maximumbricksincombination, parameters->maximumcumulativemass, uncharge(parameters->precursormass, parameters->precursorcharge))) { if (terminatecomputation) { return -1; @@ -424,7 +433,7 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { } else { b.clear(); - b.setMass(bricksdatabasewithcombinations.getMassOfComposition(combarray, parameters->maximumbricksincombination)); + b.setMass(bricksdatabasewithcombinations.getMassOfComposition(combarray)); b.setComposition(compositionname, true); bricksdatabasewithcombinations.push_back(b); } @@ -773,6 +782,7 @@ int cDeNovoGraph::connectEdgesFormingPathsNotFinishingInPrecursor(bool& terminat graph[i].insertEdge(e); edgescreated++; + // normal brick cBrick b; b.setName(to_string(e.massdifference)); b.setAcronyms(to_string(e.massdifference)); @@ -783,6 +793,16 @@ int cDeNovoGraph::connectEdgesFormingPathsNotFinishingInPrecursor(bool& terminat b.setComposition(to_string(e.brickid), false); b.setArtificial(true); bricksdatabasewithcombinations.push_back(b); + + // water loss brick + b.setName(to_string(e.massdifference - H2O)); + b.setAcronyms(to_string(e.massdifference - H2O)); + b.setReferences(s); + b.setSummary(s); + b.setMass(e.massdifference - H2O); + b.setComposition(to_string((int)bricksdatabasewithcombinations.size() + 1), false); + b.setArtificial(true); + bricksdatabasewithcombinations.push_back(b); //} } @@ -879,7 +899,7 @@ int cDeNovoGraph::removePathsWhichCanBeSubstitutedByLongerPath(bool& terminateco cBrick b; b.setComposition(graph[i][j].composition, true); path.clear(); - if (findPath(i, j, graph[i][j].targetnode, b.getComposition(), "", parameters->maximumbricksincombination, path)) { + if (findPath(i, j, graph[i][j].targetnode, b.getComposition(), "", parameters->maximumbricksincombination, path, terminatecomputation)) { //*os << "removing edge: " << graph[i].getMZRatio() << "->" << graph[graph[i][j].targetnode].getMZRatio() << " " << bricksdatabasewithcombinations.getTagName(b.getComposition()) << endl; graph[i].removeEdge(j); edgesremoved++; @@ -887,6 +907,11 @@ int cDeNovoGraph::removePathsWhichCanBeSubstitutedByLongerPath(bool& terminateco else { j++; } + + if (terminatecomputation) { + return -1; + } + } } *os << "ok" << endl; @@ -960,6 +985,7 @@ void cDeNovoGraph::printPaths(cMainThread* os, cDeNovoGraphNode& node, vector 0) { - g += "The node " + s + " with relative intensity " + to_string(graph[i].getIntensity()) + " has " + to_string(graph[i].size()) + " outgoing edge(s).
"; + g += "The node " + s + " with relative intensity " + to_string(graph[i].getIntensity()) + " has " + to_string(graph[i].size()) + " outgoing edge(s):
"; } else { g += "The node " + s + " with relative intensity " + to_string(graph[i].getIntensity()) + " does not have any outgoing edge.
"; @@ -978,7 +1004,8 @@ string cDeNovoGraph::printGraph() { //g += graph[i].printAnnotations(); //g += "\n"; - for (int j = 0; j < (int)graph[i].size(); j++) { + for (int j = 0; j < min((int)graph[i].size(), edgesmaxreport); j++) { + s2 = to_string(graph[graph[i][j].targetnode].getMZRatio()); g += s + "->" + s2 + " using brick(s): "; if (graph[i][j].composition.compare("0") == 0) { @@ -1007,6 +1034,10 @@ string cDeNovoGraph::printGraph() { g += ")
"; } + if ((int)graph[i].size() > edgesmaxreport) { + g += "... and " + to_string((int)graph[i].size() - edgesmaxreport) + " other edge(s).
"; + } + g += "
"; } diff --git a/CycloBranch/core/cDeNovoGraph.h b/CycloBranch/core/cDeNovoGraph.h index c5b49ed..045fecf 100644 --- a/CycloBranch/core/cDeNovoGraph.h +++ b/CycloBranch/core/cDeNovoGraph.h @@ -55,7 +55,7 @@ class cDeNovoGraph { cGraphReaderThread* graphreaderthread; - bool findPath(int sourcenodeid, int edgeid, int targetnodeid, string& composition, string brickspath, int maximumbricksincombination, vector& path); + bool findPath(int sourcenodeid, int edgeid, int targetnodeid, string& composition, string brickspath, int maximumbricksincombination, vector& path, bool& terminatecomputation); // create vectors of edges from temporary unordered_sets void createVectorsOfEdges(); @@ -63,6 +63,7 @@ class cDeNovoGraph { // check whether a path leads to the precursor bool finishInPrecursor(int currentnode, double cummass); + public: /** diff --git a/CycloBranch/core/cFragmentIons.cpp b/CycloBranch/core/cFragmentIons.cpp index c10b320..9d38635 100644 --- a/CycloBranch/core/cFragmentIons.cpp +++ b/CycloBranch/core/cFragmentIons.cpp @@ -12,6 +12,7 @@ cPeriodicTableMap::cPeriodicTableMap() { table["N"] = N; table["O"] = O; table["F"] = F; + table["Ne"] = Ne; table["Na"] = Na; table["Mg"] = Mg; table["Al"] = Al; @@ -19,6 +20,7 @@ cPeriodicTableMap::cPeriodicTableMap() { table["P"] = P; table["S"] = S; table["Cl"] = Cl; + table["Ar"] = Ar; table["K"] = K; table["Ca"] = Ca; table["Sc"] = Sc; @@ -31,10 +33,81 @@ cPeriodicTableMap::cPeriodicTableMap() { table["Ni"] = Ni; table["Cu"] = Cu; table["Zn"] = Zn; + table["Ga"] = Ga; + table["Ge"] = Ge; + table["As"] = As; table["Se"] = Se; table["Br"] = Br; + table["Kr"] = Kr; + table["Rb"] = Rb; + table["Sr"] = Sr; + table["Y"] = Y; + table["Zr"] = Zr; + table["Nb"] = Nb; table["Mo"] = Mo; + table["Tc"] = Tc; + table["Ru"] = Ru; + table["Rh"] = Rh; + table["Pd"] = Pd; + table["Ag"] = Ag; + table["Cd"] = Cd; + table["In"] = In; + table["Sn"] = Sn; + table["Sb"] = Sb; + table["Te"] = Te; table["I"] = I; + table["Xe"] = Xe; + table["Cs"] = Cs; + table["Ba"] = Ba; + table["La"] = La; + table["Ce"] = Ce; + table["Pr"] = Pr; + table["Nd"] = Nd; + table["Pm"] = Pm; + table["Sm"] = Sm; + table["Eu"] = Eu; + table["Gd"] = Gd; + table["Tb"] = Tb; + table["Dy"] = Dy; + table["Ho"] = Ho; + table["Er"] = Er; + table["Tm"] = Tm; + table["Yb"] = Yb; + table["Lu"] = Lu; + table["Hf"] = Hf; + table["Ta"] = Ta; + table["W"] = W; + table["Re"] = Re; + table["Os"] = Os; + table["Ir"] = Ir; + table["Pt"] = Pt; + table["Au"] = Au; + table["Hg"] = Hg; + table["Tl"] = Tl; + table["Pb"] = Pb; + table["Bi"] = Bi; + table["Po"] = Po; + table["At"] = At; + table["Rn"] = Rn; + table["Fr"] = Fr; + table["Ra"] = Ra; + table["Ac"] = Ac; + table["Th"] = Th; + table["Pa"] = Pa; + table["U"] = U; + table["Np"] = Np; + table["Pu"] = Pu; + table["Am"] = Am; + table["Cm"] = Cm; + table["Bk"] = Bk; + table["Cf"] = Cf; + table["Es"] = Es; + table["Fm"] = Fm; + table["Md"] = Md; + table["No"] = No; + table["Lr"] = Lr; + table["R"] = R; + table["X"] = X; } @@ -717,7 +790,7 @@ int loadModificationsFromPlainTextStream(ifstream &stream, vector 0) && (s.back() == '\r')) { s = s.substr(0, s.size() - 1); } diff --git a/CycloBranch/core/cFragmentIons.h b/CycloBranch/core/cFragmentIons.h index aab7545..728e596 100644 --- a/CycloBranch/core/cFragmentIons.h +++ b/CycloBranch/core/cFragmentIons.h @@ -33,6 +33,7 @@ const double C = 12.0; const double N = 14.0030740052; const double O = 15.9949146221; const double F = 18.998404; +const double Ne = 19.992439; const double Na = 22.989771; const double Mg = 23.985043; const double Al = 26.981539; @@ -40,6 +41,7 @@ const double Si = 27.976927; const double P = 30.97376151; const double S = 31.97207069; const double Cl = 34.968853; +const double Ar = 39.962383; const double K = 38.963707; const double Ca = 39.962589; const double Sc = 44.95591; @@ -52,10 +54,81 @@ const double Co = 58.933201; const double Ni = 57.935349; const double Cu = 62.9296; const double Zn = 63.929146; +const double Ga = 68.925583; +const double Ge = 73.921181; +const double As = 74.921600; const double Se = 79.916519; const double Br = 78.918327; +const double Kr = 83.911507; +const double Rb = 84.911789; +const double Sr = 87.905617; +const double Y = 88.905846; +const double Zr = 89.904701; +const double Nb = 92.906403; const double Mo = 97.905411; +const double Tc = 97.907219; +const double Ru = 101.904388; +const double Rh = 102.905502; +const double Pd = 105.903481; +const double Ag = 106.905090; +const double Cd = 113.903358; +const double In = 114.903877; +const double Sn = 119.902199; +const double Sb = 120.903824; +const double Te = 129.906219; const double I = 126.904457; +const double Xe = 131.904160; +const double Cs = 132.905441; +const double Ba = 137.905243; +const double La = 138.906342; +const double Ce = 139.905441; +const double Pr = 140.907593; +const double Nd = 141.907700; +const double Pm = 144.912750; +const double Sm = 151.919693; +const double Eu = 152.921204; +const double Gd = 157.924103; +const double Tb = 158.925293; +const double Dy = 163.929199; +const double Ho = 164.930298; +const double Er = 165.930298; +const double Tm = 168.934204; +const double Yb = 173.938904; +const double Lu = 174.940796; +const double Hf = 179.946503; +const double Ta = 180.947998; +const double W = 183.950897; +const double Re = 186.955597; +const double Os = 191.961502; +const double Ir = 192.962906; +const double Pt = 194.964798; +const double Au = 196.966507; +const double Hg = 201.970596; +const double Tl = 204.974396; +const double Pb = 207.976593; +const double Bi = 208.980392; +const double Po = 208.982422; +const double At = 209.987137; +const double Rn = 222.017563; +const double Fr = 209.996399; +const double Ra = 226.025406; +const double Ac = 227.027740; +const double Th = 232.038055; +const double Pa = 231.035904; +const double U = 238.050781; +const double Np = 237.048172; +const double Pu = 242.058746; +const double Am = 243.061371; +const double Cm = 247.070343; +const double Bk = 247.070297; +const double Cf = 251.079575; +const double Es = 252.082977; +const double Fm = 257.095093; +const double Md = 258.098419; +const double No = 259.101044; +const double Lr = 262.109802; +const double R = 0; +const double X = 0; const double e = H - Hplus; diff --git a/CycloBranch/core/cParameters.cpp b/CycloBranch/core/cParameters.cpp index 40c8b26..c0eb7db 100644 --- a/CycloBranch/core/cParameters.cpp +++ b/CycloBranch/core/cParameters.cpp @@ -40,6 +40,7 @@ void cParameters::clear() { cyclicnterminus = false; cycliccterminus = false; enablescrambling = false; + similaritysearch = false; hitsreported = 1000; sequencetag = ""; originalsequencetag = ""; @@ -130,27 +131,40 @@ int cParameters::checkAndPrepare() { *os << "Converting the file " + peaklistfilename + " to mgf ... "; #if OS_TYPE == UNX - s = linuxinstalldir.toStdString() + "External/linux/any2mgf.sh " + peaklistfilename; + s = installdir.toStdString() + "External/linux/any2mgf.sh " + peaklistfilename; if (system(s.c_str()) != 0) { error = true; 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 (sudo apt-get install topp) ?\n"; - errormessage += "Do you have 'any2mgf.sh' file located in '" + linuxinstalldir.toStdString() + "External/linux' folder ?\n"; - errormessage += "Is the file 'any2mgf.sh' executable (sudo chmod +x " + linuxinstalldir.toStdString() + "External/linux/any2mgf.sh) ? \n"; + errormessage += "Do you have 'any2mgf.sh' file located in '" + installdir.toStdString() + "External/linux' folder ?\n"; + errormessage += "Is the file 'any2mgf.sh' executable (sudo chmod +x " + installdir.toStdString() + "External/linux/any2mgf.sh) ? \n"; } #else - s = "External\\windows\\any2mgf.bat \"" + peaklistfilename + "\""; - if (system(s.c_str()) != 0) { - error = true; - 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 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"; - } + #if OS_TYPE == OSX + s = installdir.toStdString() + "External/macosx/any2mgf.sh " + peaklistfilename; + if (system(s.c_str()) != 0) { + error = true; + 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 'any2mgf.sh' file located in '" + installdir.toStdString() + "External/macosx' folder ?\n"; + errormessage += "Is the file 'any2mgf.sh' executable ? \n"; + } + #else + s = "External\\windows\\any2mgf.bat \"" + peaklistfilename + "\""; + if (system(s.c_str()) != 0) { + error = true; + 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 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"; + } + #endif #endif if (!error) { @@ -475,6 +489,10 @@ string cParameters::printToString() { s += enablescrambling ? "on" : "off"; s += "\n"; + s += "Similarity Search: "; + s += similaritysearch ? "on" : "off"; + s += "\n"; + s += "Mode: "; switch ((modeType)mode) { case denovoengine: @@ -617,6 +635,7 @@ void cParameters::store(ofstream& os) { os.write((char *)&cyclicnterminus, sizeof(bool)); os.write((char *)&cycliccterminus, sizeof(bool)); os.write((char *)&enablescrambling, sizeof(bool)); + os.write((char *)&similaritysearch, sizeof(bool)); os.write((char *)&hitsreported, sizeof(int)); storeString(sequencetag, os); @@ -694,6 +713,7 @@ void cParameters::load(ifstream& is) { is.read((char *)&cyclicnterminus, sizeof(bool)); is.read((char *)&cycliccterminus, sizeof(bool)); is.read((char *)&enablescrambling, sizeof(bool)); + is.read((char *)&similaritysearch, sizeof(bool)); is.read((char *)&hitsreported, sizeof(int)); loadString(sequencetag, is); diff --git a/CycloBranch/core/cParameters.h b/CycloBranch/core/cParameters.h index 923b1d1..9bafc84 100644 --- a/CycloBranch/core/cParameters.h +++ b/CycloBranch/core/cParameters.h @@ -221,6 +221,12 @@ class cParameters { bool enablescrambling; + /** + \brief True when the similarity search is enabled. + */ + bool similaritysearch; + + /** \brief Maximum number of reported hits. */ diff --git a/CycloBranch/core/cSequence.cpp b/CycloBranch/core/cSequence.cpp index 26dcbbb..c777eea 100644 --- a/CycloBranch/core/cSequence.cpp +++ b/CycloBranch/core/cSequence.cpp @@ -164,6 +164,17 @@ string cSequence::getNameWithReferenceAsHTMLString() { } } + // KEGG Compounds (undocumented) + if (!correctreference) { + rx = "^C[0-9]{5}$"; + if (regex_search(reference, rx)) { + s += ""; + s += name; + s += ""; + correctreference = true; + } + } + } catch (regex_error& /*e*/) { // nothing to do @@ -182,7 +193,7 @@ void cSequence::setSummaryFormula(const string& formula) { } -string& cSequence::getSummaryFormula() { - return summary.getFormula(); +string cSequence::getSummaryFormula() { + return summary.getSummary(); } diff --git a/CycloBranch/core/cSequence.h b/CycloBranch/core/cSequence.h index bd2d2df..c84c94d 100644 --- a/CycloBranch/core/cSequence.h +++ b/CycloBranch/core/cSequence.h @@ -179,7 +179,7 @@ class cSequence { \brief Get the summary formula. \retval string summary formula */ - string& getSummaryFormula(); + string getSummaryFormula(); }; diff --git a/CycloBranch/core/cSequenceDatabase.cpp b/CycloBranch/core/cSequenceDatabase.cpp index 00a0748..91ad447 100644 --- a/CycloBranch/core/cSequenceDatabase.cpp +++ b/CycloBranch/core/cSequenceDatabase.cpp @@ -124,7 +124,7 @@ void cSequenceDatabase::loadFromPlainTextStream(ifstream &stream) { } // load reference - #if OS_TYPE == UNX + #if OS_TYPE != WIN if ((s.size() > 0) && (s.back() == '\r')) { s = s.substr(0, s.size() - 1); } diff --git a/CycloBranch/core/cSummaryFormula.cpp b/CycloBranch/core/cSummaryFormula.cpp index 352643e..86337c8 100644 --- a/CycloBranch/core/cSummaryFormula.cpp +++ b/CycloBranch/core/cSummaryFormula.cpp @@ -84,26 +84,38 @@ cSummaryFormula::cSummaryFormula() { } -cSummaryFormula::cSummaryFormula(string& formula) { - this->formula = formula; +cSummaryFormula::cSummaryFormula(string& formula, bool partial) { + setFormula(formula, partial); } void cSummaryFormula::clear() { formula = ""; + partial = false; } -void cSummaryFormula::setFormula(const string& formula) { +void cSummaryFormula::setFormula(const string& formula, bool partial) { this->formula = formula; + this->partial = partial; } -string& cSummaryFormula::getFormula() { +string cSummaryFormula::getSummary() { return formula; } +bool cSummaryFormula::isPartial() { + return partial; +} + + +void cSummaryFormula::setPartial(bool partial) { + this->partial = partial; +} + + void cSummaryFormula::addFormula(string& formula) { if ((int)formula.size() == 0) { return; @@ -247,10 +259,12 @@ double cSummaryFormula::getMass() { void cSummaryFormula::store(ofstream& os) { storeString(formula, os); + os.write((char *)&partial, sizeof(bool)); } void cSummaryFormula::load(ifstream& is) { loadString(formula, is); + is.read((char *)&partial, sizeof(bool)); } diff --git a/CycloBranch/core/cSummaryFormula.h b/CycloBranch/core/cSummaryFormula.h index f6dc553..eb36771 100644 --- a/CycloBranch/core/cSummaryFormula.h +++ b/CycloBranch/core/cSummaryFormula.h @@ -21,6 +21,8 @@ using namespace boost; */ class cSummaryFormula { + bool partial; + string formula; void explodeSummary(map& atoms, string& summary); @@ -36,9 +38,10 @@ class cSummaryFormula { /** \brief The constructor. - \brief formula a chemical formula + \param formula a chemical formula + \param partial true when the formula is incomplete */ - cSummaryFormula(string& formula); + cSummaryFormula(string& formula, bool partial = false); /** @@ -50,15 +53,30 @@ class cSummaryFormula { /** \brief Set the formula. \param formula a chemical formula + \param partial true when the formula is incomplete + */ + void setFormula(const string& formula, bool partial = false); + + + /** + \brief Get the summary formula as a string. + \retval string formula as a string + */ + string getSummary(); + + + /** + \brief Check if the formula is incomplete or not. + \retval bool true when the formula is incomplete, false when the formula is complete */ - void setFormula(const string& formula); + bool isPartial(); /** - \brief Get the formula. - \retval string reference to the formula + \brief Set the formula as partial. + \param partial true if the formula is incomplete */ - string& getFormula(); + void setPartial(bool partial); /** diff --git a/CycloBranch/core/cTheoreticalSpectrum.cpp b/CycloBranch/core/cTheoreticalSpectrum.cpp index 7a53ba6..d72487f 100644 --- a/CycloBranch/core/cTheoreticalSpectrum.cpp +++ b/CycloBranch/core/cTheoreticalSpectrum.cpp @@ -156,13 +156,67 @@ void cTheoreticalSpectrum::generatePrecursorIon(vector& intcomposition, cBr peak.iontype = (fragmentIonType)i; if (writedescription) { + string str; + if (parameters->precursorcharge > 0) { - peak.description = to_string(j) + "+ " + parameters->fragmentdefinitions[(fragmentIonType)i].name + ":"; + peak.description = parameters->fragmentdefinitions[(fragmentIonType)i].name + ":"; + + if (!parameters->precursoradduct.empty()) { + str = "+" + parameters->precursoradduct; + if (j > 1) { + str += "+"; + if (j > 2) { + str += to_string(j - 1); + } + str += "H"; + } + peak.description.replace(peak.description.find("+zH"), 3, str); + } + else { + str = "+"; + if (j > 1) { + str += to_string(j); + } + str += "H"; + peak.description.replace(peak.description.find("+zH"), 3, str); + } + + str = "]"; + if (j > 1) { + str += to_string(j); + } + str += "+"; + peak.description.replace(peak.description.find("]+"), 2, str); } else { - peak.description = to_string(j) + "- " + parameters->fragmentdefinitions[(fragmentIonType)i].name + ":"; - peak.description.replace(peak.description.find("+z"), 2, "-z"); - peak.description.replace(peak.description.find("]+"), 2, "]-"); + peak.description = parameters->fragmentdefinitions[(fragmentIonType)i].name + ":"; + + if (!parameters->precursoradduct.empty()) { + str = "-" + parameters->precursoradduct; + if (j > 1) { + str += "-"; + if (j > 2) { + str += to_string(j - 1); + } + str += "H"; + } + peak.description.replace(peak.description.find("+zH"), 3, str); + } + else { + str = "-"; + if (j > 1) { + str += to_string(j); + } + str += "H"; + peak.description.replace(peak.description.find("+zH"), 3, str); + } + + str = "]"; + if (j > 1) { + str += to_string(j); + } + str += "-"; + peak.description.replace(peak.description.find("]+"), 2, str); } } @@ -703,7 +757,7 @@ int cTheoreticalSpectrum::compareLinear(cPeaksList& sortedpeaklist, cBricksDatab clearFalseHits(series, parameters->fragmentionsfortheoreticalspectra); for (int i = 0; i < theoreticalpeaksrealsize; i++) { - if ((theoreticalpeaks[i].matched > 0) && ((series.count(parameters->fragmentdefinitions[theoreticalpeaks[i].iontype].parent) == 0) || (series[parameters->fragmentdefinitions[theoreticalpeaks[i].iontype].parent][theoreticalpeaks[i].seriesid] == 0))) { + if ((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--; @@ -1101,7 +1155,6 @@ int cTheoreticalSpectrum::compareLasso(cPeaksList& sortedpeaklist, cBricksDataba int theoreticalpeaksrealsize = 0; vector lassorotations; - // normalize the candidate candidate.getLassoRotations(lassorotations, false); int numberofbricks = getNumberOfBricks(candidate.getComposition()); @@ -1109,12 +1162,14 @@ int cTheoreticalSpectrum::compareLasso(cPeaksList& sortedpeaklist, cBricksDataba if (lassorotations[i].getBranchEnd() == numberofbricks - 1) { vector v; v.push_back(lassorotations[i].getComposition()); - candidate.setCandidate(v, candidate.getPath(), candidate.getStartModifID(), candidate.getEndModifID(), candidate.getMiddleModifID(), lassorotations[i].getBranchStart(), lassorotations[i].getBranchEnd()); + string name = candidate.getName(); + vector cpath = candidate.getPath(); + candidate.setCandidate(v, cpath, candidate.getStartModifID(), candidate.getEndModifID(), candidate.getMiddleModifID(), lassorotations[i].getBranchStart(), lassorotations[i].getBranchEnd()); + candidate.setName(name); break; } } - // get branch-cyclic rotations candidate.getLassoRotations(lassorotations, true); @@ -1421,7 +1476,7 @@ int cTheoreticalSpectrum::compareLinearPolysaccharide(cPeaksList& sortedpeaklist clearFalseHits(series, parameters->fragmentionsfortheoreticalspectra); for (int i = 0; i < theoreticalpeaksrealsize; i++) { - if ((theoreticalpeaks[i].matched > 0) && ((series.count(parameters->fragmentdefinitions[theoreticalpeaks[i].iontype].parent) == 0) || (series[parameters->fragmentdefinitions[theoreticalpeaks[i].iontype].parent][theoreticalpeaks[i].seriesid] == 0))) { + if ((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--; diff --git a/CycloBranch/core/utilities.cpp b/CycloBranch/core/utilities.cpp index f8868c3..73d9619 100644 --- a/CycloBranch/core/utilities.cpp +++ b/CycloBranch/core/utilities.cpp @@ -4,8 +4,15 @@ QString appname = "CycloBranch"; -QString appversion = "v. 1.0.1106 (64-bit)"; -QString linuxinstalldir = "/usr/share/cyclobranch/"; +QString appversion = "v. 1.0.1216 (64-bit)"; + +#if OS_TYPE == UNX + QString installdir = "/usr/share/cyclobranch/"; +#endif + +#if OS_TYPE == OSX + QString installdir = ""; +#endif void storeString(string& s, ofstream& os) { @@ -120,7 +127,7 @@ void parseBranch(peptideType peptidetype, string& composition, vector& v if (s[i] == '(') { if (i > 0) { b.clear(); - b.setComposition(s.substr(0, i - 1), false); + b.setComposition(s.substr(0, i), false); branchstart = getNumberOfBricks(b.getComposition()); s[i] = '-'; } @@ -135,7 +142,7 @@ void parseBranch(peptideType peptidetype, string& composition, vector& v for (int i = 0; i < (int)s.size(); i++) { if (s[i] == ')') { b.clear(); - b.setComposition(s.substr(0, i - 1), false); + b.setComposition(s.substr(0, i), false); branchend = getNumberOfBricks(b.getComposition()) - 1; if (i < (int)s.size() - 1) { s[i] = '-'; diff --git a/CycloBranch/core/utilities.h b/CycloBranch/core/utilities.h index bdff4c4..daf0cdc 100644 --- a/CycloBranch/core/utilities.h +++ b/CycloBranch/core/utilities.h @@ -18,13 +18,21 @@ class cBrick; #define WIN 0 // Windows #define UNX 1 // Linux/UNIX +#define OSX 2 // Mac OS X -#ifdef UNIX + +#ifdef LINUX #define OS_TYPE UNX #define sscanf_s sscanf #define sprintf_s sprintf #else - #define OS_TYPE WIN + #ifdef MACOSX + #define OS_TYPE OSX + #define sscanf_s sscanf + #define sprintf_s sprintf + #else + #define OS_TYPE WIN + #endif #endif @@ -58,9 +66,9 @@ extern QString appversion; /** - \brief A directory where the application is installed in Linux. + \brief A directory where the application is installed under Linux or OSX. */ -extern QString linuxinstalldir; +extern QString installdir; /** diff --git a/CycloBranch/gui/cAboutWidget.cpp b/CycloBranch/gui/cAboutWidget.cpp index 0fc521d..3f354a6 100644 --- a/CycloBranch/gui/cAboutWidget.cpp +++ b/CycloBranch/gui/cAboutWidget.cpp @@ -32,7 +32,7 @@ cAboutWidget::cAboutWidget(QWidget* parent) { message->setReadOnly(true); message->setAcceptRichText(true); message->setOpenExternalLinks(true); - message->setHtml("
" + splash + "" + appname + " " + appversion + "

" + title + developers /*+ licence*/ + acknowledgement); + message->setHtml("
" + splash + "" + appname + " " + appversion + "

" + title + developers + licence + acknowledgement); buttonbox = new QDialogButtonBox(QDialogButtonBox::Ok); //buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); @@ -62,7 +62,7 @@ void cAboutWidget::closeEvent(QCloseEvent *event) { void cAboutWidget::keyPressEvent(QKeyEvent *event) { - if(event->key() == Qt::Key_Escape) { + if (event->key() == Qt::Key_Escape) { hide(); } } diff --git a/CycloBranch/gui/cBranchedWidget.cpp b/CycloBranch/gui/cBranchedWidget.cpp index ea01478..f551660 100644 --- a/CycloBranch/gui/cBranchedWidget.cpp +++ b/CycloBranch/gui/cBranchedWidget.cpp @@ -41,7 +41,6 @@ void cBranchedWidget::exportToPDF(QString filename, bool postscript) { QString errstr = "The file cannot be created."; #if OS_TYPE == UNX errstr += "\nDo you have a properly configured print server (sudo apt-get install cups-pdf) ?"; - errstr += "\nIf you cannot create a ps file, you can create a pdf file and then use pdf2ps tool."; #endif msgBox.setText(errstr); msgBox.exec(); @@ -89,6 +88,7 @@ void cBranchedWidget::exportToSVG(QString filename) { return; } + painter.fillRect(QRect(0, 0, width(), height()), Qt::white); paint(painter); painter.end(); } diff --git a/CycloBranch/gui/cBricksDatabaseWidget.cpp b/CycloBranch/gui/cBricksDatabaseWidget.cpp index 81dec94..ed58bfa 100644 --- a/CycloBranch/gui/cBricksDatabaseWidget.cpp +++ b/CycloBranch/gui/cBricksDatabaseWidget.cpp @@ -15,6 +15,7 @@ #include #include #include +#include int numberOfOccurrences(const string& s, char c) { @@ -43,17 +44,44 @@ cBricksDatabaseWidget::cBricksDatabaseWidget(QWidget* parent) { close->setToolTip("Close the window."); load = new QPushButton(tr("Load")); load->setToolTip("Load the database of building blocks."); - save = new QPushButton(QString("Save")); + 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."); saveas = new QPushButton(tr("Save As...")); saveas->setToolTip("Save the database of building blocks into a file."); + rowsfilterline = new QLineEdit(); + rowsfilterline->setMinimumWidth(250); + rowsfilterline->setToolTip("Text to Find"); + rowsfiltercasesensitive = new QCheckBox(); + rowsfiltercasesensitive->setToolTip("Case Sensitive"); + rowsfilterbutton = new QPushButton("Filter"); + rowsfilterbutton->setToolTip("Filter Search Results"); + rowsfilterbutton->setMinimumWidth(50); + rowsfilterclearbutton = new QPushButton("Clear"); + rowsfilterclearbutton->setToolTip("Clear Form and Reset Search Results"); + rowsfilterclearbutton->setMinimumWidth(50); + + rowsfilterhbox = new QHBoxLayout(); + rowsfilterhbox->addWidget(rowsfilterline); + rowsfilterhbox->addStretch(); + rowsfilterhbox->addWidget(rowsfiltercasesensitive); + rowsfilterhbox->addStretch(); + rowsfilterhbox->addWidget(rowsfilterbutton); + rowsfilterhbox->addStretch(); + rowsfilterhbox->addWidget(rowsfilterclearbutton); + + rowsfilterwidget = new QWidget(); + rowsfilterwidget->setLayout(rowsfilterhbox); + rowsfilterwidget->setMaximumWidth(420); + buttons = new QHBoxLayout(); buttons->addWidget(close); - buttons->addStretch(1); + buttons->addStretch(); buttons->addWidget(insertrow); buttons->addWidget(removechecked); - buttons->addStretch(10); + buttons->addStretch(); + buttons->addWidget(rowsfilterwidget); + buttons->addStretch(); buttons->addWidget(load); buttons->addWidget(save); buttons->addWidget(saveas); @@ -91,11 +119,13 @@ cBricksDatabaseWidget::cBricksDatabaseWidget(QWidget* parent) { 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(removeEmptyRows())); + 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())); + connect(rowsfilterbutton, SIGNAL(released()), this, SLOT(filterRows())); + connect(rowsfilterclearbutton, SIGNAL(released()), this, SLOT(resetFilter())); setLayout(mainlayout); @@ -106,10 +136,12 @@ cBricksDatabaseWidget::cBricksDatabaseWidget(QWidget* parent) { #if OS_TYPE == WIN lastdir = "./BrickDatabases/"; #else - lastdir = linuxinstalldir + "BrickDatabases/"; + lastdir = installdir + "BrickDatabases/"; #endif bricks.clear(); + + setDataModified(false); } @@ -128,6 +160,14 @@ cBricksDatabaseWidget::~cBricksDatabaseWidget() { delete load; delete save; delete saveas; + + delete rowsfilterline; + delete rowsfiltercasesensitive; + delete rowsfilterbutton; + delete rowsfilterclearbutton; + delete rowsfilterhbox; + delete rowsfilterwidget; + delete database; delete buttons; delete mainlayout; @@ -230,20 +270,55 @@ bool cBricksDatabaseWidget::checkFormula(int row, const string& summary) { return false; } if (database->item(row, 4)) { - database->item(row, 4)->setData(Qt::DisplayRole, formula.getMass()); + database->item(row, 4)->setData(Qt::DisplayRole, to_string(formula.getMass()).c_str()); } return true; } +void cBricksDatabaseWidget::setDataModified(bool datamodified) { + if (datamodified == this->datamodified) { + return; + } + + this->datamodified = datamodified; + + if (datamodified) { + save->setText("*" + save->text()); + } + else { + if ((save->text().size() > 0) && (save->text().at(0) == '*')) { + save->setText(save->text().toStdString().substr(1).c_str()); + } + } +} + + void cBricksDatabaseWidget::keyPressEvent(QKeyEvent *event) { - if(event->key() == Qt::Key_Escape) { - hide(); + if (event->key() == Qt::Key_Escape) { + closeWindow(); + } + + if ((event->key() == Qt::Key_Enter) || (event->key() == Qt::Key_Return)) { + if (rowsfilterline->hasFocus()) { + filterRows(); + } } } void cBricksDatabaseWidget::closeWindow() { + if (datamodified) { + QMessageBox::StandardButton reply; + reply = QMessageBox::question(this, appname, "Save changes ?", QMessageBox::Yes|QMessageBox::No); + + if (reply == QMessageBox::Yes) { + if (!saveDatabase()) { + return; + } + } + } + hide(); } @@ -256,7 +331,7 @@ void cBricksDatabaseWidget::loadDatabase() { string errormessage; databasefile = filename; - save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); + save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); inputstream.open(filename.toStdString().c_str()); @@ -293,7 +368,7 @@ void cBricksDatabaseWidget::loadDatabase() { database->item(i, 3)->setText(bricks[i].getSummary().c_str()); database->setItem(i, 4, widgetitemallocator.getNewItem()); - database->item(i, 4)->setData(Qt::DisplayRole, bricks[i].getMass()); + database->item(i, 4)->setData(Qt::DisplayRole, to_string(bricks[i].getMass()).c_str()); database->setItem(i, 5, widgetitemallocator.getNewItem()); database->item(i, 5)->setText(bricks[i].getReferencesAsString().c_str()); @@ -315,6 +390,8 @@ void cBricksDatabaseWidget::loadDatabase() { progress.setValue(bricks.size()); + setDataModified(false); + } inputstream.close(); @@ -323,15 +400,15 @@ void cBricksDatabaseWidget::loadDatabase() { } -void cBricksDatabaseWidget::saveDatabase() { +bool cBricksDatabaseWidget::saveDatabase() { + bool saved = false; if (!checkTable()) { - return; + return saved; } if (databasefile.compare("") == 0) { - saveDatabaseAs(); - return; + return saveDatabaseAs(); } outputstream.open(databasefile.toStdString().c_str()); @@ -352,9 +429,15 @@ void cBricksDatabaseWidget::saveDatabase() { bricks.clear(); string s; - removeEmptyRows(); + removeCheckedRows(); for (int i = 0; i < database->rowCount(); i++) { + + if (database->isRowHidden(i)) { + progress.setValue(i); + continue; + } + b.clear(); for (int j = 0; j < database->columnCount(); j++) { switch (j) @@ -397,15 +480,20 @@ void cBricksDatabaseWidget::saveDatabase() { progress.setValue(progress.maximum()); + setDataModified(false); + + saved = true; + } outputstream.close(); -} + return saved; +} -void cBricksDatabaseWidget::saveDatabaseAs() { +bool cBricksDatabaseWidget::saveDatabaseAs() { if (!checkTable()) { - return; + return false; } QString filename = QFileDialog::getSaveFileName(this, tr("Save the Database of Building Blocks As..."), lastdir, tr("Database of Building Blocks (*.txt)")); @@ -414,9 +502,11 @@ void cBricksDatabaseWidget::saveDatabaseAs() { lastdir = filename; databasefile = filename; - save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); - saveDatabase(); + save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); + return saveDatabase(); } + + return false; } @@ -440,11 +530,12 @@ void cBricksDatabaseWidget::addRow() { } -void cBricksDatabaseWidget::removeEmptyRows() { +void cBricksDatabaseWidget::removeCheckedRows() { int i = 0; while (i < database->rowCount()) { if (((QCheckBox *)(database->cellWidget(i, 0)))->isChecked()) { removeRow(i); + setDataModified(true); } else { i++; @@ -466,10 +557,14 @@ void cBricksDatabaseWidget::itemChanged(QTableWidgetItem* item) { b.setReferences(database->item(item->row(), 5)->text().toStdString()); ((QLabel *)database->cellWidget(item->row(), 6))->setText(b.getAcronymsWithReferencesAsHTMLString().c_str()); } + + setDataModified(true); } void cBricksDatabaseWidget::headerItemDoubleClicked(int index) { + setDataModified(true); + if (headersort[index] == -1) { database->sortByColumn(index, Qt::AscendingOrder); headersort[index] = 1; @@ -486,3 +581,56 @@ void cBricksDatabaseWidget::headerItemDoubleClicked(int index) { } } + +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, 0, rowcount, this); + 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; + } + + if (database->item(i, j)->text().contains(str, casesensitive)) { + match = true; + break; + } + } + database->setRowHidden(i, !match); + progress.setValue(i); + } + + progress.setValue(rowcount); +} + + +void cBricksDatabaseWidget::resetFilter() { + rowsfilterline->setText(""); + int rowcount = database->rowCount(); + + QProgressDialog progress("Updating...", /*"Cancel"*/0, 0, rowcount, this); + 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); + } + + progress.setValue(rowcount); +} + diff --git a/CycloBranch/gui/cBricksDatabaseWidget.h b/CycloBranch/gui/cBricksDatabaseWidget.h index 673abe1..5b5b03b 100644 --- a/CycloBranch/gui/cBricksDatabaseWidget.h +++ b/CycloBranch/gui/cBricksDatabaseWidget.h @@ -22,6 +22,8 @@ class QVBoxLayout; class QTableWidget; class QTableWidgetItem; class QPushButton; +class QCheckBox; +class QLineEdit; /** @@ -64,6 +66,7 @@ class cBricksDatabaseWidget : public QWidget private: + QWidget* parent; QPushButton* insertrow; QPushButton* removechecked; @@ -71,6 +74,14 @@ class cBricksDatabaseWidget : public QWidget QPushButton* load; QPushButton* save; QPushButton* saveas; + + QWidget* rowsfilterwidget; + QHBoxLayout* rowsfilterhbox; + QLineEdit* rowsfilterline; + QCheckBox* rowsfiltercasesensitive; + QPushButton* rowsfilterbutton; + QPushButton* rowsfilterclearbutton; + QTableWidget* database; QHBoxLayout* buttons; QVBoxLayout* mainlayout; @@ -85,6 +96,8 @@ class cBricksDatabaseWidget : public QWidget cAllocator widgetitemallocator; + bool datamodified; + void deleteTable(bool enableprogress); void removeRow(int row); @@ -93,6 +106,7 @@ class cBricksDatabaseWidget : public QWidget bool checkFormula(int row, const string& summary); + void setDataModified(bool datamodified); protected: @@ -110,18 +124,22 @@ private slots: void loadDatabase(); - void saveDatabase(); + bool saveDatabase(); - void saveDatabaseAs(); + bool saveDatabaseAs(); void addRow(); - void removeEmptyRows(); + void removeCheckedRows(); void itemChanged(QTableWidgetItem* item); void headerItemDoubleClicked(int index); + void filterRows(); + + void resetFilter(); + }; #endif diff --git a/CycloBranch/gui/cCyclicWidget.cpp b/CycloBranch/gui/cCyclicWidget.cpp index 491397e..bffbf38 100644 --- a/CycloBranch/gui/cCyclicWidget.cpp +++ b/CycloBranch/gui/cCyclicWidget.cpp @@ -317,7 +317,6 @@ void cCyclicWidget::exportToPDF(QString filename, bool postscript) { QString errstr = "The file cannot be created."; #if OS_TYPE == UNX errstr += "\nDo you have a properly configured print server (sudo apt-get install cups-pdf) ?"; - errstr += "\nIf you cannot create a ps file, you can create a pdf file and then use pdf2ps tool."; #endif msgBox.setText(errstr); msgBox.exec(); @@ -365,6 +364,7 @@ void cCyclicWidget::exportToSVG(QString filename) { return; } + painter.fillRect(QRect(0, 0, width(), height()), Qt::white); paint(painter); painter.end(); } diff --git a/CycloBranch/gui/cDrawPeptideWidget.cpp b/CycloBranch/gui/cDrawPeptideWidget.cpp index 9744319..2c659de 100644 --- a/CycloBranch/gui/cDrawPeptideWidget.cpp +++ b/CycloBranch/gui/cDrawPeptideWidget.cpp @@ -239,7 +239,7 @@ void cDrawPeptideWidget::setSequence(int peptidetypeindex, QString sequence) { void cDrawPeptideWidget::keyPressEvent(QKeyEvent *event) { - if(event->key() == Qt::Key_Escape) { + if (event->key() == Qt::Key_Escape) { hide(); } } @@ -574,6 +574,9 @@ void cDrawPeptideWidget::sequenceChanged() { } if ((peptidetype == branched) || (peptidetype == lasso)) { + branchstart = theoreticalspectrum.getCandidate().getBranchStart(); + branchend = theoreticalspectrum.getCandidate().getBranchEnd(); + numberofblocksbackbone->setValue((int)v.size() - branchend + branchstart); numberofblocksbranch->setValue(branchend - branchstart); branchposition->setValue(branchstart + 1); @@ -644,7 +647,8 @@ void cDrawPeptideWidget::drawPeptide(vector& composition, cBricksDatabas if (lassorotations[i].getBranchEnd() == numberofbricks - 1) { vector v; v.push_back(lassorotations[i].getComposition()); - theoreticalspectrum.getCandidate().setCandidate(v, theoreticalspectrum.getCandidate().getPath(), theoreticalspectrum.getCandidate().getStartModifID(), theoreticalspectrum.getCandidate().getEndModifID(), theoreticalspectrum.getCandidate().getMiddleModifID(), lassorotations[i].getBranchStart(), lassorotations[i].getBranchEnd()); + vector cpath = theoreticalspectrum.getCandidate().getPath(); + theoreticalspectrum.getCandidate().setCandidate(v, cpath, theoreticalspectrum.getCandidate().getStartModifID(), theoreticalspectrum.getCandidate().getEndModifID(), theoreticalspectrum.getCandidate().getMiddleModifID(), lassorotations[i].getBranchStart(), lassorotations[i].getBranchEnd()); break; } } diff --git a/CycloBranch/gui/cExportDialog.cpp b/CycloBranch/gui/cExportDialog.cpp new file mode 100644 index 0000000..6eb0bd9 --- /dev/null +++ b/CycloBranch/gui/cExportDialog.cpp @@ -0,0 +1,52 @@ +#include "gui/cExportDialog.h" + +#include "gui/cSpectrumDetailWidget.h" + + +cExportDialog::cExportDialog(QWidget* parent) { + this->parent = parent; + + exportspectrum = new QRadioButton(); + exportspectrum->setChecked(true); + exportpeptide = new QRadioButton(); + exportbutton = new QPushButton("Export"); + connect(exportbutton, SIGNAL(released()), this, SLOT(processExport())); + + exportbox = new QHBoxLayout(); + exportbox->addWidget(exportspectrum); + exportbox->addWidget(exportbutton); + + formlayout = new QFormLayout(); + formlayout->addRow("Export spectrum: ", exportbox); + formlayout->addRow("Export peptide: ", exportpeptide); + + setLayout(formlayout); + setWindowTitle("Export Image"); + setMinimumSize(300, 50); +} + + +cExportDialog::~cExportDialog() { + delete exportspectrum; + delete exportbutton; + delete exportbox; + + delete exportpeptide; + + delete formlayout; +} + + +void cExportDialog::processExport() { + close(); + + QTextDocument::FindFlags flags = 0; + + if (exportspectrum->isChecked()) { + ((cSpectrumDetailWidget *)parent)->exportImage(true); + } + else if (exportpeptide->isChecked()) { + ((cSpectrumDetailWidget *)parent)->exportImage(false); + } +} + diff --git a/CycloBranch/gui/cExportDialog.h b/CycloBranch/gui/cExportDialog.h new file mode 100644 index 0000000..132cec4 --- /dev/null +++ b/CycloBranch/gui/cExportDialog.h @@ -0,0 +1,59 @@ +/** + \file cExportDialog.h + \brief The implementation of a dialog to export spectrum/peptide image. +*/ + + +#ifndef _CEXPORTDIALOG_H +#define _CEXPORTDIALOG_H + +#include +#include +#include +#include +#include +#include + + +/** + \brief The implementation of a dialog to export spectrum/peptide image. +*/ +class cExportDialog : public QDialog +{ + Q_OBJECT + +private: + + QWidget* parent; + + QHBoxLayout* exportbox; + + QFormLayout* formlayout; + QPushButton* exportbutton; + QRadioButton* exportspectrum; + QRadioButton* exportpeptide; + +public: + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cExportDialog(QWidget* parent = (QWidget *)0); + + + /** + \brief The destructor. + */ + ~cExportDialog(); + + +private slots: + + + void processExport(); + +}; + +#endif \ No newline at end of file diff --git a/CycloBranch/gui/cFindDialog.cpp b/CycloBranch/gui/cFindDialog.cpp new file mode 100644 index 0000000..0b9cc42 --- /dev/null +++ b/CycloBranch/gui/cFindDialog.cpp @@ -0,0 +1,58 @@ +#include "gui/cFindDialog.h" + +#include "gui/cSpectrumDetailWidget.h" + + +cFindDialog::cFindDialog(QWidget* parent) { + this->parent = parent; + + searchline = new QLineEdit(); + searchbutton = new QPushButton("Find"); + connect(searchbutton, SIGNAL(released()), this, SLOT(findAll())); + + matchcase = new QCheckBox(); + matchwholeword = new QCheckBox(); + + searchbox = new QHBoxLayout(); + searchbox->addWidget(searchline); + searchbox->addWidget(searchbutton); + + formlayout = new QFormLayout(); + formlayout->addRow("Find what: ", searchbox); + formlayout->addRow("Match case: ", matchcase); + formlayout->addRow("Match whole word: ", matchwholeword); + + setLayout(formlayout); + setWindowTitle("Find Text"); + setMinimumSize(400, 50); +} + + +cFindDialog::~cFindDialog() { + delete searchline; + delete searchbutton; + delete searchbox; + + delete matchcase; + delete matchwholeword; + + delete formlayout; +} + + +void cFindDialog::findAll() { + close(); + + QTextDocument::FindFlags flags = 0; + + if (matchcase->isChecked()) { + flags |= QTextDocument::FindCaseSensitively; + } + + if (matchwholeword->isChecked()) { + flags |= QTextDocument::FindWholeWords; + } + + ((cSpectrumDetailWidget *)parent)->findAll(searchline->text(), flags); +} + diff --git a/CycloBranch/gui/cFindDialog.h b/CycloBranch/gui/cFindDialog.h new file mode 100644 index 0000000..6ec2407 --- /dev/null +++ b/CycloBranch/gui/cFindDialog.h @@ -0,0 +1,62 @@ +/** + \file cFindDialog.h + \brief The implementation of a find dialog. +*/ + + +#ifndef _CFINDDIALOG_H +#define _CFINDDIALOG_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + \brief The implementation of a find dialog. +*/ +class cFindDialog : public QDialog +{ + Q_OBJECT + +private: + + QWidget* parent; + + QHBoxLayout* searchbox; + + QFormLayout* formlayout; + QLineEdit* searchline; + QPushButton* searchbutton; + QCheckBox* matchcase; + QCheckBox* matchwholeword; + +public: + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cFindDialog(QWidget* parent = (QWidget *)0); + + + /** + \brief The destructor. + */ + ~cFindDialog(); + + +private slots: + + + void findAll(); + +}; + +#endif \ No newline at end of file diff --git a/CycloBranch/gui/cGraphWidget.cpp b/CycloBranch/gui/cGraphWidget.cpp index dde3d75..201f2fc 100644 --- a/CycloBranch/gui/cGraphWidget.cpp +++ b/CycloBranch/gui/cGraphWidget.cpp @@ -64,7 +64,7 @@ void cGraphWidget::load(ifstream& is) { void cGraphWidget::keyPressEvent(QKeyEvent *event) { - if(event->key() == Qt::Key_Escape) { + if (event->key() == Qt::Key_Escape) { hide(); } } diff --git a/CycloBranch/gui/cLassoWidget.cpp b/CycloBranch/gui/cLassoWidget.cpp index 3806b29..c742d1e 100644 --- a/CycloBranch/gui/cLassoWidget.cpp +++ b/CycloBranch/gui/cLassoWidget.cpp @@ -86,7 +86,6 @@ void cLassoWidget::exportToPDF(QString filename, bool postscript) { QString errstr = "The file cannot be created."; #if OS_TYPE == UNX errstr += "\nDo you have a properly configured print server (sudo apt-get install cups-pdf) ?"; - errstr += "\nIf you cannot create a ps file, you can create a pdf file and then use pdf2ps tool."; #endif msgBox.setText(errstr); msgBox.exec(); @@ -134,6 +133,7 @@ void cLassoWidget::exportToSVG(QString filename) { return; } + painter.fillRect(QRect(0, 0, width(), height()), Qt::white); paint(painter); painter.end(); } diff --git a/CycloBranch/gui/cLinearWidget.cpp b/CycloBranch/gui/cLinearWidget.cpp index cdda0a9..b1d7c30 100644 --- a/CycloBranch/gui/cLinearWidget.cpp +++ b/CycloBranch/gui/cLinearWidget.cpp @@ -62,7 +62,6 @@ void cLinearWidget::exportToPDF(QString filename, bool postscript) { QString errstr = "The file cannot be created."; #if OS_TYPE == UNX errstr += "\nDo you have a properly configured print server (sudo apt-get install cups-pdf) ?"; - errstr += "\nIf you cannot create a ps file, you can create a pdf file and then use pdf2ps tool."; #endif msgBox.setText(errstr); msgBox.exec(); @@ -110,6 +109,7 @@ void cLinearWidget::exportToSVG(QString filename) { return; } + painter.fillRect(QRect(0, 0, width(), height()), Qt::white); paint(painter); painter.end(); } diff --git a/CycloBranch/gui/cMainThread.cpp b/CycloBranch/gui/cMainThread.cpp index d5da33b..3204a2b 100644 --- a/CycloBranch/gui/cMainThread.cpp +++ b/CycloBranch/gui/cMainThread.cpp @@ -357,7 +357,7 @@ void cMainThread::run() { // set candidate and check precursor mass error c.setCandidate(v, netmp, startmodifid, endmodifid, middlemodifid, branchstart, branchend); - if (!calculatesummaries && !isInPpmMassErrorTolerance(charge(uncharge(parameters.precursormass, parameters.precursorcharge), (parameters.precursorcharge > 0)?1:-1), c.getPrecursorMass(parameters.bricksdatabase, ¶meters), parameters.precursormasserrortolerance)) { + if (!calculatesummaries && !parameters.similaritysearch && !isInPpmMassErrorTolerance(charge(uncharge(parameters.precursormass, parameters.precursorcharge), (parameters.precursorcharge > 0)?1:-1), c.getPrecursorMass(parameters.bricksdatabase, ¶meters), parameters.precursormasserrortolerance)) { continue; } @@ -365,7 +365,7 @@ void cMainThread::run() { candidates.getSet().insert(c); if (calculatesummaries) { - *os << c.getSummaryFormula(parameters, parameters.sequencedatabase[i].getPeptideType()) << endl; + *os << c.getSummaryFormula(parameters, parameters.sequencedatabase[i].getPeptideType()).getSummary() << endl; } } @@ -375,7 +375,7 @@ void cMainThread::run() { return; } - *os << "Number of candidates in the precursor mass error tolerance found: " << candidates.size() << endl; + *os << "Number of candidates found: " << candidates.size() << endl; graphreaderisworking = false; diff --git a/CycloBranch/gui/cMainWindow.cpp b/CycloBranch/gui/cMainWindow.cpp index c8bd9e3..217ddcf 100644 --- a/CycloBranch/gui/cMainWindow.cpp +++ b/CycloBranch/gui/cMainWindow.cpp @@ -77,11 +77,17 @@ cMainWindow::cMainWindow() { actionDrawPeptide->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_P)); + actionShowIsomers = new QAction(QIcon(":/images/icons/95.png"), tr("Show &Isomers"), this); + actionShowIsomers->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_I)); + actionShowIsomers->setCheckable(true); + actionGraph = new QAction(QIcon(":/images/icons/32.png"), tr("De Novo &Graph"), this); actionGraph->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_G)); actionLog = new QAction(QIcon(":/images/icons/2.png"), tr("&Log Window"), this); actionLog->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); + actionLog->setCheckable(true); + actionLog->setChecked(true); actionHTMLDocumentation = new QAction(QIcon(":/images/icons/3.png"), tr("&HTML Documentation"), this); @@ -113,6 +119,7 @@ cMainWindow::cMainWindow() { toolbarTools->addAction(actionDrawPeptide); toolbarView = addToolBar(tr("View")); + toolbarView->addAction(actionShowIsomers); toolbarView->addAction(actionGraph); toolbarView->addAction(actionLog); @@ -121,6 +128,34 @@ cMainWindow::cMainWindow() { toolbarHelp->addAction(actionPDFManual); toolbarHelp->addAction(actionAbout); + rowsfilterline = new QLineEdit(); + rowsfilterline->setMinimumWidth(250); + rowsfilterline->setToolTip("Text to Find"); + rowsfiltercasesensitive = new QCheckBox(); + rowsfiltercasesensitive->setToolTip("Case Sensitive"); + rowsfilterbutton = new QPushButton("Filter"); + rowsfilterbutton->setToolTip("Filter Search Results"); + rowsfilterbutton->setMinimumWidth(50); + rowsfilterclearbutton = new QPushButton("Clear"); + rowsfilterclearbutton->setToolTip("Clear Form and Reset Search Results"); + rowsfilterclearbutton->setMinimumWidth(50); + + rowsfilterhbox = new QHBoxLayout(); + rowsfilterhbox->addWidget(rowsfilterline); + rowsfilterhbox->addStretch(); + rowsfilterhbox->addWidget(rowsfiltercasesensitive); + rowsfilterhbox->addStretch(); + rowsfilterhbox->addWidget(rowsfilterbutton); + rowsfilterhbox->addStretch(); + rowsfilterhbox->addWidget(rowsfilterclearbutton); + + rowsfilterwidget = new QWidget(); + rowsfilterwidget->setLayout(rowsfilterhbox); + rowsfilterwidget->setMaximumWidth(420); + + toolbarFilter = addToolBar(tr("Filter")); + toolbarFilter->addWidget(rowsfilterwidget); + // widgets results = new QTableWidget(0, 0, this); @@ -153,12 +188,16 @@ cMainWindow::cMainWindow() { connect(actionSequenceDatabase, SIGNAL(triggered()), this, SLOT(showSequenceDatabase())); connect(actionModifications, SIGNAL(triggered()), this, SLOT(showModifications())); connect(actionDrawPeptide, SIGNAL(triggered()), this, SLOT(showDrawPeptideWidget())); + connect(actionShowIsomers, SIGNAL(triggered()), this, SLOT(updateSpectra())); connect(actionGraph, SIGNAL(triggered()), this, SLOT(showGraph())); connect(actionLog, SIGNAL(triggered()), this, SLOT(showHideLog())); connect(actionHTMLDocumentation, SIGNAL(triggered()), this, SLOT(showHTMLDocumentation())); connect(actionPDFManual, SIGNAL(triggered()), this, SLOT(showPDFManual())); connect(actionAbout, SIGNAL(triggered()), this, SLOT(showAbout())); + connect(rowsfilterbutton, SIGNAL(released()), this, SLOT(filterResults())); + connect(rowsfilterclearbutton, SIGNAL(released()), this, SLOT(resetFilter())); + // add subitems to the items in main menu // menuFile->addAction(actionOpen); menuFile->addAction(actionOpenResults); @@ -177,8 +216,9 @@ cMainWindow::cMainWindow() { menuTools->addAction(actionModifications); menuTools->addSeparator(); menuTools->addAction(actionDrawPeptide); - menuView->addAction(actionGraph); + menuView->addAction(actionShowIsomers); menuView->addSeparator(); + menuView->addAction(actionGraph); menuView->addAction(actionLog); menuHelp->addAction(actionHTMLDocumentation); menuHelp->addAction(actionPDFManual); @@ -222,7 +262,7 @@ cMainWindow::cMainWindow() { // set the size of main window resize(1280, 700); - resultsbasecolumncount = 8; + resultsbasecolumncount = 9; resultsspecificcolumncount = 0; dbsearchspecificcolumncount = 0; @@ -238,13 +278,108 @@ cMainWindow::cMainWindow() { } +cMainWindow::~cMainWindow() { + deleteResults(); + + delete rowsfilterline; + delete rowsfiltercasesensitive; + delete rowsfilterbutton; + delete rowsfilterclearbutton; + delete rowsfilterhbox; + delete rowsfilterwidget; + + delete results; + delete logWindow; + delete splitter; + + delete about; + delete graph; + delete bricksdatabasewidget; + delete sequencedatabasewidget; + delete modificationswidget; + delete drawpeptidewidget; + delete parameterswidget; + + delete actionOpenResults; + delete actionSaveResults; + delete actionExportToCsv; + delete actionExportToHTML; + delete actionQuit; + delete actionProperties; + delete actionRun; + delete actionBricksDatabase; + delete actionSequenceDatabase; + delete actionModifications; + delete actionDrawPeptide; + delete actionShowIsomers; + delete actionGraph; + delete actionLog; + delete actionHTMLDocumentation; + delete actionPDFManual; + delete actionAbout; + + delete menuFile; + delete menuSearch; + delete menuTools; + delete menuView; + delete menuHelp; + + delete menuBar; +} + + +void cMainWindow::keyPressEvent(QKeyEvent *event) { + if ((event->key() == Qt::Key_Enter) || (event->key() == Qt::Key_Return)) { + if (rowsfilterline->hasFocus()) { + filterResults(); + } + else { + if ((results->currentRow() >= 0) && !results->isRowHidden(results->currentRow())) { + resultsCellClicked(results->currentRow(), 0); + } + } + } +} + + void cMainWindow::closeEvent(QCloseEvent *event) { quitApplication(); event->ignore(); } -void cMainWindow::reportSpectrum(int id, cTheoreticalSpectrum& theoreticalspectrum) { +void cMainWindow::preparePeptideSequence(int row, string& peptidesequence, bool reportisomers) { + int spectrumindex = results->item(row, 1)->data(Qt::DisplayRole).toInt() - 1; + string tmpsequence; + bool copy; + + if (!reportisomers) { + tmpsequence = stripHTML(theoreticalspectrumlist[spectrumindex].getCandidate().getAcronymPeptideNameWithHTMLReferences()); + peptidesequence = ""; + copy = true; + for (int j = 0; j < (int)tmpsequence.size(); j++) { + if (tmpsequence[j] == '/') { + copy = false; + } + if (tmpsequence[j] == ']') { + copy = true; + } + if (copy) { + peptidesequence += tmpsequence[j]; + } + } + } + else { + peptidesequence = stripHTML(theoreticalspectrumlist[spectrumindex].getCandidate().getAcronymPeptideNameWithHTMLReferences()); + } + +} + + +void cMainWindow::reportSpectrum(int id, cTheoreticalSpectrum& theoreticalspectrum, bool reportisomers) { + string peptidesequence; + cSummaryFormula formula; + int row = results->rowCount(); results->insertRow(row); @@ -261,57 +396,63 @@ void cMainWindow::reportSpectrum(int id, cTheoreticalSpectrum& theoreticalspectr } results->setItem(row, 2 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 2 + dbsearchspecificcolumncount)->setText(stripHTML(theoreticalspectrum.getCandidate().getAcronymPeptideNameWithHTMLReferences()).c_str()); + preparePeptideSequence(row, peptidesequence, reportisomers); + results->item(row, 2 + dbsearchspecificcolumncount)->setText(peptidesequence.c_str()); + + formula = theoreticalspectrum.getCandidate().getSummaryFormula(parameters, parameters.peptidetype); results->setItem(row, 3 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 3 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getCandidate().getSummaryFormula(parameters, parameters.peptidetype).c_str()); + results->item(row, 3 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, 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, getNumberOfBricks(theoreticalspectrum.getCandidate().getComposition())); + results->item(row, 4 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, to_string(formula.getMass()).c_str()); + + results->setItem(row, 5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 5 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, getNumberOfBricks(theoreticalspectrum.getCandidate().getComposition())); switch (parameters.peptidetype) { case linear: - results->setItem(row, 5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 5 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getStartModifID()].name.c_str()); results->setItem(row, 6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 6 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getEndModifID()].name.c_str()); + 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()); break; case branched: - results->setItem(row, 5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 5 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getStartModifID()].name.c_str()); results->setItem(row, 6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 6 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getMiddleModifID()].name.c_str()); + 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()); + 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()); break; case cyclic: - results->setItem(row, 5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 5 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedBricks()); + results->setItem(row, 6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 6 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedBricks()); break; case lasso: - results->setItem(row, 5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 5 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getMiddleModifID()].name.c_str()); + results->setItem(row, 6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 6 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getMiddleModifID()].name.c_str()); break; case linearpolysaccharide: - results->setItem(row, 5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 5 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getStartModifID()].name.c_str()); results->setItem(row, 6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 6 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getEndModifID()].name.c_str()); + 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()); break; case other: default: break; } - results->setItem(row, 5 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 5 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedPeaks()); - results->setItem(row, 6 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 6 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getRatioOfMatchedPeaks()*100); + results->item(row, 6 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedPeaks()); results->setItem(row, 7 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); - results->item(row, 7 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getWeightedIntensityScore()); + results->item(row, 7 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, to_string(theoreticalspectrum.getRatioOfMatchedPeaks()*100).c_str()); + + results->setItem(row, 8 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 8 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, to_string(theoreticalspectrum.getWeightedIntensityScore()).c_str()); for (int i = 0; i < (int)parameters.fragmentionsfortheoreticalspectra.size(); i++) { results->setItem(row, resultsbasecolumncount + dbsearchspecificcolumncount + resultsspecificcolumncount + i, widgetitemallocator.getNewItem()); @@ -338,10 +479,10 @@ void cMainWindow::reportSpectrum(int id, cTheoreticalSpectrum& theoreticalspectr results->item(row, 2)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedPeaks()); results->setItem(row, 3, widgetitemallocator.getNewItem()); - results->item(row, 3)->setData(Qt::DisplayRole, theoreticalspectrum.getRatioOfMatchedPeaks()*100); + results->item(row, 3)->setData(Qt::DisplayRole, to_string(theoreticalspectrum.getRatioOfMatchedPeaks()*100).c_str()); results->setItem(row, 4, widgetitemallocator.getNewItem()); - results->item(row, 4)->setData(Qt::DisplayRole, theoreticalspectrum.getWeightedIntensityScore()); + results->item(row, 4)->setData(Qt::DisplayRole, to_string(theoreticalspectrum.getWeightedIntensityScore()).c_str()); } @@ -474,6 +615,15 @@ void cMainWindow::enableButtonsHandlingResults(bool enable) { actionSaveResults->setEnabled(enable); actionExportToCsv->setEnabled(enable); actionExportToHTML->setEnabled(enable); + + if (parameters.mode == dereplication) { + actionShowIsomers->setEnabled(false); + rowsfilterwidget->setEnabled(false); + } + else { + actionShowIsomers->setEnabled(enable); + rowsfilterwidget->setEnabled(enable); + } } @@ -537,56 +687,62 @@ void cMainWindow::reportSpectra() { results->setHorizontalHeaderItem(2, widgetitemallocator.getNewItem()); results->horizontalHeaderItem(2)->setText("Name"); } + results->setHorizontalHeaderItem(2 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); results->horizontalHeaderItem(2 + dbsearchspecificcolumncount)->setText("Peptide Sequence"); + results->setHorizontalHeaderItem(3 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); results->horizontalHeaderItem(3 + dbsearchspecificcolumncount)->setText("Summary Formula"); + results->setHorizontalHeaderItem(4 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(4 + dbsearchspecificcolumncount)->setText("Number of Bricks"); + results->horizontalHeaderItem(4 + dbsearchspecificcolumncount)->setText("Monoisotopic Mass"); + + results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(5 + dbsearchspecificcolumncount)->setText("Number of Bricks"); switch (parameters.peptidetype) { case linear: - results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(5 + dbsearchspecificcolumncount)->setText("N-terminal Modification"); results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("C-terminal Modification"); + results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("N-terminal Modification"); + results->setHorizontalHeaderItem(7 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(7 + dbsearchspecificcolumncount)->setText("C-terminal Modification"); break; case branched: - results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(5 + dbsearchspecificcolumncount)->setText("N-terminal Modification"); results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("Branch Modification"); + results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("N-terminal Modification"); results->setHorizontalHeaderItem(7 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(7 + dbsearchspecificcolumncount)->setText("C-terminal Modification"); + results->horizontalHeaderItem(7 + dbsearchspecificcolumncount)->setText("Branch Modification"); + results->setHorizontalHeaderItem(8 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(8 + dbsearchspecificcolumncount)->setText("C-terminal Modification"); break; case cyclic: - results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(5 + dbsearchspecificcolumncount)->setText("Matched Bricks"); + results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("Matched Bricks"); break; case lasso: - results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(5 + dbsearchspecificcolumncount)->setText("Branch Modification"); + results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("Branch Modification"); break; case linearpolysaccharide: - results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(5 + dbsearchspecificcolumncount)->setText("N-terminal Modification"); results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("C-terminal Modification"); + results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("N-terminal Modification"); + results->setHorizontalHeaderItem(7 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(7 + dbsearchspecificcolumncount)->setText("C-terminal Modification"); break; case other: default: break; } - results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(5 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setText("Matched Peaks"); - results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(6 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setText("Ratio of Matched Peaks [%]"); - + results->horizontalHeaderItem(6 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setText("Matched Peaks"); + results->setHorizontalHeaderItem(7 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); - results->horizontalHeaderItem(7 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setText("Sum of Relative Intensities"); + results->horizontalHeaderItem(7 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setText("Ratio of Matched Peaks [%]"); + + results->setHorizontalHeaderItem(8 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(8 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setText("Sum of Relative Intensities"); for (int i = 0; i < (int)parameters.fragmentionsfortheoreticalspectra.size(); i++) { results->setHorizontalHeaderItem(resultsbasecolumncount + dbsearchspecificcolumncount + resultsspecificcolumncount + i, widgetitemallocator.getNewItem()); @@ -623,7 +779,6 @@ void cMainWindow::reportSpectra() { resultsheadersort[i] = -1; } - QProgressDialog progress("Preparing the report...", /*"Cancel"*/0, 0, theoreticalspectrumlist.size(), this); cEventFilter filter; progress.installEventFilter(&filter); @@ -632,8 +787,9 @@ void cMainWindow::reportSpectra() { spectradetails.clear(); spectradetails.resize(theoreticalspectrumlist.size()); + bool reportisomers = actionShowIsomers->isChecked(); for (int i = 0; i < theoreticalspectrumlist.size(); i++) { - reportSpectrum(i, theoreticalspectrumlist[i]); + reportSpectrum(i, theoreticalspectrumlist[i], reportisomers); progress.setValue(i); //if (progress.wasCanceled()) { // break; @@ -649,6 +805,40 @@ void cMainWindow::reportSpectra() { } +void cMainWindow::updateSpectra() { + + if ((parameters.mode == denovoengine) || (parameters.mode == singlecomparison) || (parameters.mode == databasesearch)) { + + bool reportisomers = actionShowIsomers->isChecked(); + string peptidesequence; + + QProgressDialog progress("Updating the report...", /*"Cancel"*/0, 0, theoreticalspectrumlist.size(), this); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); + + for (int i = 0; i < results->rowCount(); i++) { + preparePeptideSequence(i, peptidesequence, reportisomers); + results->item(i, 2 + dbsearchspecificcolumncount)->setText(peptidesequence.c_str()); + + progress.setValue(i); + //if (progress.wasCanceled()) { + // break; + //} + } + + for (int i = 0; i < results->columnCount(); i++) { + results->resizeColumnToContents(i); + } + + progress.setValue(theoreticalspectrumlist.size()); + + } + +} + + void cMainWindow::deleteResults() { widgetitemallocator.reset(); results->setColumnCount(0); @@ -714,6 +904,11 @@ void cMainWindow::exportToCsv() { out << endl; for (int i = 0; i < results->rowCount(); i++) { + + if (results->isRowHidden(i)) { + continue; + } + for (int j = 0; j < results->columnCount(); j++) { out << "\"" << results->item(i, j)->data(Qt::DisplayRole).toString() << "\""; if (j < results->columnCount() - 1) { @@ -785,7 +980,15 @@ void cMainWindow::exportToHTML() { } out << "\n"; + int spectrumindex; for (int i = 0; i < results->rowCount(); i++) { + + if (results->isRowHidden(i)) { + continue; + } + + spectrumindex = results->item(i, 1)->data(Qt::DisplayRole).toInt() - 1; + out << "\n"; @@ -811,8 +1014,8 @@ void cMainWindow::exportToHTML() { out << results->columnCount(); out << "\">\n"; - out << "

" << spectradetails[i].getTheoreticalSpectrum().getCoverageBySeries().c_str(); - out << "
" << spectradetails[i].getDetailsAsHTMLString().c_str() << "

\n"; + out << "

" << spectradetails[spectrumindex].getTheoreticalSpectrum().getCoverageBySeries().c_str(); + out << "
" << spectradetails[spectrumindex].getDetailsAsHTMLString().c_str() << "

\n"; out << "\n"; @@ -853,7 +1056,7 @@ void cMainWindow::showHTMLDocumentation() { #if OS_TYPE == WIN QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/userguide.html").absoluteFilePath())); #else - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(linuxinstalldir + "docs/html/userguide.html").absoluteFilePath())); + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/html/userguide.html").absoluteFilePath())); #endif } @@ -862,7 +1065,7 @@ void cMainWindow::showPDFManual() { #if OS_TYPE == WIN QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/refman.pdf").absoluteFilePath())); #else - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(linuxinstalldir + "docs/refman.pdf").absoluteFilePath())); + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(installdir + "docs/refman.pdf").absoluteFilePath())); #endif } @@ -989,6 +1192,15 @@ void cMainWindow::openResultsFile() { parameters.load(infile); parameterswidget->setAndRestoreParameters(parameters); + if (parameters.mode == dereplication) { + actionShowIsomers->setEnabled(false); + rowsfilterwidget->setEnabled(false); + } + else { + actionShowIsomers->setEnabled(true); + rowsfilterwidget->setEnabled(true); + } + // load theoretical spectra infile.read((char *)&size, sizeof(int)); @@ -1039,6 +1251,13 @@ void cMainWindow::insertSequence(int peptidetypeindex, QString sequence) { void cMainWindow::quitApplication() { + QMessageBox::StandardButton reply; + reply = QMessageBox::question(this, appname, "Quit ?", QMessageBox::Yes|QMessageBox::No); + + if (reply != QMessageBox::Yes) { + return; + } + emit stopComputation(); quitapp = true; @@ -1048,6 +1267,54 @@ void cMainWindow::quitApplication() { } +void cMainWindow::filterResults() { + 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, 0, rowcount, this); + 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); + } + + progress.setValue(rowcount); +} + + +void cMainWindow::resetFilter() { + rowsfilterline->setText(""); + int rowcount = results->rowCount(); + + QProgressDialog progress("Updating the report...", /*"Cancel"*/0, 0, rowcount, this); + 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); + } + + progress.setValue(rowcount); +} + + /* void cMainWindow::showContextMenu(const QPoint &pt) { QMenu *menu = logWindow->createStandardContextMenu(); @@ -1057,45 +1324,3 @@ void cMainWindow::showContextMenu(const QPoint &pt) { } */ - -cMainWindow::~cMainWindow() { - deleteResults(); - - delete menuBar; - - delete menuFile; - delete menuSearch; - delete menuTools; - delete menuView; - delete menuHelp; - - delete actionOpenResults; - delete actionSaveResults; - delete actionExportToCsv; - delete actionExportToHTML; - delete actionQuit; - delete actionProperties; - delete actionRun; - delete actionBricksDatabase; - delete actionSequenceDatabase; - delete actionModifications; - delete actionDrawPeptide; - delete actionGraph; - delete actionLog; - delete actionHTMLDocumentation; - delete actionPDFManual; - delete actionAbout; - - delete results; - delete logWindow; - delete splitter; - - delete about; - delete graph; - delete bricksdatabasewidget; - delete sequencedatabasewidget; - delete modificationswidget; - delete drawpeptidewidget; - delete parameterswidget; -} - diff --git a/CycloBranch/gui/cMainWindow.h b/CycloBranch/gui/cMainWindow.h index d95dcd3..259d309 100644 --- a/CycloBranch/gui/cMainWindow.h +++ b/CycloBranch/gui/cMainWindow.h @@ -53,6 +53,15 @@ class cMainWindow : public QMainWindow ~cMainWindow(); +protected: + + /** + \brief Handle a key press event. + \param event pointer to QKeyEvent + */ + void keyPressEvent(QKeyEvent *event); + + private: // main menu @@ -71,6 +80,7 @@ class cMainWindow : public QMainWindow QToolBar* toolbarTools; QToolBar* toolbarView; QToolBar* toolbarHelp; + QToolBar* toolbarFilter; // subitems in the menu QAction* actionOpenResults; @@ -85,12 +95,20 @@ class cMainWindow : public QMainWindow QAction* actionSequenceDatabase; QAction* actionModifications; QAction *actionDrawPeptide; + QAction* actionShowIsomers; QAction* actionGraph; QAction* actionLog; QAction* actionHTMLDocumentation; QAction* actionPDFManual; QAction* actionAbout; + QWidget* rowsfilterwidget; + QHBoxLayout* rowsfilterhbox; + QLineEdit* rowsfilterline; + QCheckBox* rowsfiltercasesensitive; + QPushButton* rowsfilterbutton; + QPushButton* rowsfilterclearbutton; + QTableWidget* results; cTheoreticalSpectrumList theoreticalspectrumlist; vector spectradetails; @@ -125,7 +143,9 @@ class cMainWindow : public QMainWindow void closeEvent(QCloseEvent *event); - void reportSpectrum(int id, cTheoreticalSpectrum& theoreticalspectrum); + void preparePeptideSequence(int row, string& peptidesequence, bool reportisomers); + + void reportSpectrum(int id, cTheoreticalSpectrum& theoreticalspectrum, bool reportisomers); void deleteResults(); @@ -166,6 +186,8 @@ private slots: void reportSpectra(); + void updateSpectra(); + void resultsCellClicked(int row, int column); void setGraph(string s); @@ -192,6 +214,10 @@ private slots: void quitApplication(); + void filterResults(); + + void resetFilter(); + //void showContextMenu(const QPoint &pt); signals: diff --git a/CycloBranch/gui/cModificationsWidget.cpp b/CycloBranch/gui/cModificationsWidget.cpp index cc175be..2b3b1f2 100644 --- a/CycloBranch/gui/cModificationsWidget.cpp +++ b/CycloBranch/gui/cModificationsWidget.cpp @@ -14,6 +14,7 @@ #include #include #include +#include cModificationsWidget::cModificationsWidget(QWidget* parent) { @@ -31,17 +32,44 @@ cModificationsWidget::cModificationsWidget(QWidget* parent) { close->setToolTip("Close the window."); load = new QPushButton(tr("Load")); load->setToolTip("Load modifications."); - save = new QPushButton(QString("Save")); + 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."); saveas = new QPushButton(tr("Save As...")); saveas->setToolTip("Save modifications into a file."); + rowsfilterline = new QLineEdit(); + rowsfilterline->setMinimumWidth(250); + rowsfilterline->setToolTip("Text to Find"); + rowsfiltercasesensitive = new QCheckBox(); + rowsfiltercasesensitive->setToolTip("Case Sensitive"); + rowsfilterbutton = new QPushButton("Filter"); + rowsfilterbutton->setToolTip("Filter Search Results"); + rowsfilterbutton->setMinimumWidth(50); + rowsfilterclearbutton = new QPushButton("Clear"); + rowsfilterclearbutton->setToolTip("Clear Form and Reset Search Results"); + rowsfilterclearbutton->setMinimumWidth(50); + + rowsfilterhbox = new QHBoxLayout(); + rowsfilterhbox->addWidget(rowsfilterline); + rowsfilterhbox->addStretch(); + rowsfilterhbox->addWidget(rowsfiltercasesensitive); + rowsfilterhbox->addStretch(); + rowsfilterhbox->addWidget(rowsfilterbutton); + rowsfilterhbox->addStretch(); + rowsfilterhbox->addWidget(rowsfilterclearbutton); + + rowsfilterwidget = new QWidget(); + rowsfilterwidget->setLayout(rowsfilterhbox); + rowsfilterwidget->setMaximumWidth(420); + buttons = new QHBoxLayout(); buttons->addWidget(close); - buttons->addStretch(1); + buttons->addStretch(); buttons->addWidget(insertrow); buttons->addWidget(removechecked); - buttons->addStretch(10); + buttons->addStretch(); + buttons->addWidget(rowsfilterwidget); + buttons->addStretch(); buttons->addWidget(load); buttons->addWidget(save); buttons->addWidget(saveas); @@ -71,11 +99,13 @@ cModificationsWidget::cModificationsWidget(QWidget* parent) { 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(removeEmptyRows())); + 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())); + connect(rowsfilterbutton, SIGNAL(released()), this, SLOT(filterRows())); + connect(rowsfilterclearbutton, SIGNAL(released()), this, SLOT(resetFilter())); setLayout(mainlayout); @@ -86,10 +116,12 @@ cModificationsWidget::cModificationsWidget(QWidget* parent) { #if OS_TYPE == WIN lastdir = "./Modifications/"; #else - lastdir = linuxinstalldir + "Modifications/"; + lastdir = installdir + "Modifications/"; #endif modifications.clear(); + + setDataModified(false); } @@ -108,6 +140,14 @@ cModificationsWidget::~cModificationsWidget() { delete load; delete save; delete saveas; + + delete rowsfilterline; + delete rowsfiltercasesensitive; + delete rowsfilterbutton; + delete rowsfilterclearbutton; + delete rowsfilterhbox; + delete rowsfilterwidget; + delete database; delete buttons; delete mainlayout; @@ -195,20 +235,55 @@ bool cModificationsWidget::checkFormula(int row, const string& summary) { return false; } if (database->item(row, 3)) { - database->item(row, 3)->setData(Qt::DisplayRole, formula.getMass()); + database->item(row, 3)->setData(Qt::DisplayRole, to_string(formula.getMass()).c_str()); } return true; } +void cModificationsWidget::setDataModified(bool datamodified) { + if (datamodified == this->datamodified) { + return; + } + + this->datamodified = datamodified; + + if (datamodified) { + save->setText("*" + save->text()); + } + else { + if ((save->text().size() > 0) && (save->text().at(0) == '*')) { + save->setText(save->text().toStdString().substr(1).c_str()); + } + } +} + + void cModificationsWidget::keyPressEvent(QKeyEvent *event) { - if(event->key() == Qt::Key_Escape) { - hide(); + if (event->key() == Qt::Key_Escape) { + closeWindow(); + } + + if ((event->key() == Qt::Key_Enter) || (event->key() == Qt::Key_Return)) { + if (rowsfilterline->hasFocus()) { + filterRows(); + } } } void cModificationsWidget::closeWindow() { + if (datamodified) { + QMessageBox::StandardButton reply; + reply = QMessageBox::question(this, appname, "Save changes ?", QMessageBox::Yes|QMessageBox::No); + + if (reply == QMessageBox::Yes) { + if (!saveDatabase()) { + return; + } + } + } + hide(); } @@ -221,7 +296,7 @@ void cModificationsWidget::loadDatabase() { string errormessage; databasefile = filename; - save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); + save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); inputstream.open(filename.toStdString().c_str()); @@ -255,15 +330,17 @@ void cModificationsWidget::loadDatabase() { database->item(i, 2)->setText(modifications[i].summary.c_str()); database->setItem(i, 3, widgetitemallocator.getNewItem()); - database->item(i, 3)->setData(Qt::DisplayRole, modifications[i].massdifference); + database->item(i, 3)->setData(Qt::DisplayRole, to_string(modifications[i].massdifference).c_str()); checkbox = new QCheckBox(); + connect(checkbox, SIGNAL(stateChanged(int)), this, SLOT(checkBoxModified(int))); if (modifications[i].nterminal) { checkbox->setChecked(true); } database->setCellWidget(i, 4, checkbox); checkbox = new QCheckBox(); + connect(checkbox, SIGNAL(stateChanged(int)), this, SLOT(checkBoxModified(int))); if (modifications[i].cterminal) { checkbox->setChecked(true); } @@ -281,6 +358,8 @@ void cModificationsWidget::loadDatabase() { progress.setValue((int)modifications.size()); + setDataModified(false); + } inputstream.close(); @@ -289,15 +368,15 @@ void cModificationsWidget::loadDatabase() { } -void cModificationsWidget::saveDatabase() { +bool cModificationsWidget::saveDatabase() { + bool saved = false; if (!checkTable()) { - return; + return saved; } if (databasefile.compare("") == 0) { - saveDatabaseAs(); - return; + return saveDatabaseAs(); } outputstream.open(databasefile.toStdString().c_str()); @@ -317,9 +396,15 @@ void cModificationsWidget::saveDatabase() { fragmentDescription modification; modifications.clear(); - removeEmptyRows(); + removeCheckedRows(); for (int i = 0; i < database->rowCount(); i++) { + + if (database->isRowHidden(i)) { + progress.setValue(i); + continue; + } + modification.clear(); for (int j = 0; j < database->columnCount(); j++) { switch (j) @@ -358,15 +443,20 @@ void cModificationsWidget::saveDatabase() { progress.setValue(progress.maximum()); + setDataModified(false); + + saved = true; + } outputstream.close(); -} + return saved; +} -void cModificationsWidget::saveDatabaseAs() { +bool cModificationsWidget::saveDatabaseAs() { if (!checkTable()) { - return; + return false; } QString filename = QFileDialog::getSaveFileName(this, tr("Save Modifications As..."), lastdir, tr("Modifications (*.txt)")); @@ -375,9 +465,11 @@ void cModificationsWidget::saveDatabaseAs() { lastdir = filename; databasefile = filename; - save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); - saveDatabase(); + save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); + return saveDatabase(); } + + return false; } @@ -389,16 +481,27 @@ void cModificationsWidget::addRow() { database->setItem(row, 1, widgetitemallocator.getNewItem()); database->setItem(row, 2, widgetitemallocator.getNewItem()); database->setItem(row, 3, widgetitemallocator.getNewItem()); - database->setCellWidget(row, 4, new QCheckBox()); - database->setCellWidget(row, 5, new QCheckBox()); + + 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); + + setDataModified(true); } -void cModificationsWidget::removeEmptyRows() { +void cModificationsWidget::removeCheckedRows() { int i = 0; while (i < database->rowCount()) { if (((QCheckBox *)(database->cellWidget(i, 0)))->isChecked()) { removeRow(i); + setDataModified(true); } else { i++; @@ -412,10 +515,14 @@ void cModificationsWidget::itemChanged(QTableWidgetItem* item) { if (item->column() == 2) { checkFormula(item->row(), item->text().toStdString()); } + + setDataModified(true); } void cModificationsWidget::headerItemDoubleClicked(int index) { + setDataModified(true); + if (headersort[index] == -1) { database->sortByColumn(index, Qt::AscendingOrder); headersort[index] = 1; @@ -432,3 +539,61 @@ void cModificationsWidget::headerItemDoubleClicked(int index) { } } + +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, 0, rowcount, this); + 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; + } + + if (database->item(i, j)->text().contains(str, casesensitive)) { + match = true; + break; + } + } + database->setRowHidden(i, !match); + progress.setValue(i); + } + + progress.setValue(rowcount); +} + + +void cModificationsWidget::resetFilter() { + rowsfilterline->setText(""); + int rowcount = database->rowCount(); + + QProgressDialog progress("Updating...", /*"Cancel"*/0, 0, rowcount, this); + 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); + } + + progress.setValue(rowcount); +} + + +void cModificationsWidget::checkBoxModified(int state) { + setDataModified(true); +} + diff --git a/CycloBranch/gui/cModificationsWidget.h b/CycloBranch/gui/cModificationsWidget.h index 3deb65f..ff9fd69 100644 --- a/CycloBranch/gui/cModificationsWidget.h +++ b/CycloBranch/gui/cModificationsWidget.h @@ -23,6 +23,8 @@ class QVBoxLayout; class QTableWidget; class QTableWidgetItem; class QPushButton; +class QLineEdit; +class QCheckBox; /** @@ -56,6 +58,7 @@ class cModificationsWidget : public QWidget private: + QWidget* parent; QPushButton* insertrow; QPushButton* removechecked; @@ -63,6 +66,14 @@ class cModificationsWidget : public QWidget QPushButton* load; QPushButton* save; QPushButton* saveas; + + QWidget* rowsfilterwidget; + QHBoxLayout* rowsfilterhbox; + QLineEdit* rowsfilterline; + QCheckBox* rowsfiltercasesensitive; + QPushButton* rowsfilterbutton; + QPushButton* rowsfilterclearbutton; + QTableWidget* database; QHBoxLayout* buttons; QVBoxLayout* mainlayout; @@ -77,6 +88,8 @@ class cModificationsWidget : public QWidget cAllocator widgetitemallocator; + bool datamodified; + void deleteTable(bool enableprogress); void removeRow(int row); @@ -85,6 +98,7 @@ class cModificationsWidget : public QWidget bool checkFormula(int row, const string& summary); + void setDataModified(bool datamodified); protected: @@ -102,18 +116,24 @@ private slots: void loadDatabase(); - void saveDatabase(); + bool saveDatabase(); - void saveDatabaseAs(); + bool saveDatabaseAs(); void addRow(); - void removeEmptyRows(); + void removeCheckedRows(); void itemChanged(QTableWidgetItem* item); void headerItemDoubleClicked(int index); + void filterRows(); + + void resetFilter(); + + void checkBoxModified(int state); + }; #endif diff --git a/CycloBranch/gui/cParametersWidget.cpp b/CycloBranch/gui/cParametersWidget.cpp index bd2a3f3..dff9ca3 100644 --- a/CycloBranch/gui/cParametersWidget.cpp +++ b/CycloBranch/gui/cParametersWidget.cpp @@ -19,6 +19,7 @@ #include #include #include +#include cParametersWidget::cParametersWidget(QWidget* parent) { @@ -63,7 +64,7 @@ cParametersWidget::cParametersWidget(QWidget* parent) { peaklistline = new QLineEdit(); peaklistbutton = new QPushButton("Select"); - #if OS_TYPE == UNX + #if OS_TYPE != WIN peaklistline->setToolTip("Select the peaklist. Following formats are supported: txt, mgf, mzML, mzXML."); peaklistbutton->setToolTip("Select the peaklist. Following formats are supported: txt, mgf, mzML, mzXML."); #else @@ -208,6 +209,10 @@ cParametersWidget::cParametersWidget(QWidget* parent) { enablescrambling->setToolTip("When checked, scrambled fragment ions of cyclic peptides are generated 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."); + miscformlayout->addRow(tr("Enable Similarity Search: "), similaritysearch); + miscgroupbox = new QGroupBox("Miscellaneous"); miscgroupbox->setLayout(miscformlayout); @@ -312,13 +317,21 @@ cParametersWidget::cParametersWidget(QWidget* parent) { hlayout = new QHBoxLayout(); + hlayout->setContentsMargins(0, 0, 0, 0); hlayout->addLayout(vlayout1); hlayout->addLayout(vlayout2); + hlayoutwidget = new QWidget(); + hlayoutwidget->setLayout(hlayout); + + hlayoutscroll = new QScrollArea(); + hlayoutscroll->setWidgetResizable(true); + hlayoutscroll->setFrameShape(QFrame::NoFrame); + hlayoutscroll->setWidget(hlayoutwidget); + vlayout = new QVBoxLayout(); - vlayout->addLayout(hlayout); - vlayout->addStretch(1); + vlayout->addWidget(hlayoutscroll); vlayout->addLayout(buttons); setLayout(vlayout); @@ -355,12 +368,12 @@ cParametersWidget::cParametersWidget(QWidget* parent) { lastdirselectmodifications = "./Modifications/"; lastdirselectsequencedatabase = "./SequenceDatabases/"; #else - lastdirloadsettings = linuxinstalldir + "Settings/"; - lastdirsavesettings = linuxinstalldir + "Settings/"; - lastdirselectpeaklist = linuxinstalldir + "PeakLists/"; - lastdirselectbricksdatabase = linuxinstalldir + "BrickDatabases/"; - lastdirselectmodifications = linuxinstalldir + "Modifications/"; - lastdirselectsequencedatabase = linuxinstalldir + "SequenceDatabases/"; + lastdirloadsettings = installdir + "Settings/"; + lastdirsavesettings = installdir + "Settings/"; + lastdirselectpeaklist = installdir + "PeakLists/"; + lastdirselectbricksdatabase = installdir + "BrickDatabases/"; + lastdirselectmodifications = installdir + "Modifications/"; + lastdirselectsequencedatabase = installdir + "SequenceDatabases/"; #endif } @@ -407,6 +420,7 @@ cParametersWidget::~cParametersWidget() { delete cyclicnterminus; delete cycliccterminus; delete enablescrambling; + delete similaritysearch; delete miscformlayout; delete miscgroupbox; @@ -435,6 +449,8 @@ cParametersWidget::~cParametersWidget() { delete vlayout1; delete vlayout2; delete hlayout; + delete hlayoutwidget; + delete hlayoutscroll; delete vlayout; } @@ -477,7 +493,7 @@ void cParametersWidget::setTag(int peptidetypeindex, QString tag) { void cParametersWidget::keyPressEvent(QKeyEvent *event) { - if(event->key() == Qt::Key_Escape) { + if (event->key() == Qt::Key_Escape) { restoreParameters(); } } @@ -518,6 +534,7 @@ void cParametersWidget::loadSettings() { settings.value("cyclicnterminus", 0).toInt() == 0 ? cyclicnterminus->setChecked(false) : cyclicnterminus->setChecked(true); 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); mode->setCurrentIndex(settings.value("mode", 0).toInt()); sequencedatabaseline->setText(settings.value("sequencedatabase", "").toString()); @@ -578,6 +595,7 @@ void cParametersWidget::saveSettings() { cyclicnterminus->isChecked() ? settings.setValue("cyclicnterminus", 1) : settings.setValue("cyclicnterminus", 0); 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); settings.setValue("mode", mode->currentIndex()); settings.setValue("sequencedatabase", sequencedatabaseline->text()); @@ -615,7 +633,7 @@ void cParametersWidget::saveSettingsAs() { void cParametersWidget::peaklistButtonReleased() { - #if OS_TYPE == UNX + #if OS_TYPE != WIN QString filename = QFileDialog::getOpenFileName(this, tr("Select Peaklist..."), lastdirselectpeaklist, tr("Peak Lists (*.txt *.mgf *.mzML *.mzXML)")); #else QString filename = QFileDialog::getOpenFileName(this, tr("Select Peaklist..."), lastdirselectpeaklist, tr("Peak Lists (*.txt *.mgf *.mzML *.mzXML *.baf)")); @@ -723,6 +741,7 @@ bool cParametersWidget::updateParameters() { parameters.cyclicnterminus = cyclicnterminus->isChecked(); parameters.cycliccterminus = cycliccterminus->isChecked(); parameters.enablescrambling = enablescrambling->isChecked(); + parameters.similaritysearch = similaritysearch->isChecked(); parameters.mode = (modeType)mode->currentIndex(); parameters.sequencedatabasefilename = sequencedatabaseline->text().toStdString(); @@ -813,6 +832,7 @@ void cParametersWidget::restoreParameters() { cyclicnterminus->setChecked(parameters.cyclicnterminus); cycliccterminus->setChecked(parameters.cycliccterminus); enablescrambling->setChecked(parameters.enablescrambling); + similaritysearch->setChecked(parameters.similaritysearch); mode->setCurrentIndex(parameters.mode); sequencedatabaseline->setText(parameters.sequencedatabasefilename.c_str()); @@ -955,6 +975,7 @@ void cParametersWidget::updateSettingsWhenModeChanged(int index) { sequencedatabaseline->setDisabled(true); sequencedatabasebutton->setDisabled(true); blindedges->setDisabled(false); + similaritysearch->setDisabled(true); maximumnumberofthreads->setDisabled(false); scoretype->setDisabled(false); hitsreported->setDisabled(false); @@ -984,6 +1005,7 @@ void cParametersWidget::updateSettingsWhenModeChanged(int index) { sequencedatabaseline->setDisabled(true); sequencedatabasebutton->setDisabled(true); blindedges->setDisabled(true); + similaritysearch->setDisabled(true); maximumnumberofthreads->setDisabled(true); scoretype->setDisabled(true); hitsreported->setDisabled(true); @@ -1011,6 +1033,7 @@ void cParametersWidget::updateSettingsWhenModeChanged(int index) { modificationsline->setDisabled(false); modificationsbutton->setDisabled(false); blindedges->setDisabled(true); + similaritysearch->setDisabled(false); sequencedatabaseline->setDisabled(false); sequencedatabasebutton->setDisabled(false); maximumnumberofthreads->setDisabled(false); @@ -1040,6 +1063,7 @@ void cParametersWidget::updateSettingsWhenModeChanged(int index) { modificationsline->setDisabled(true); modificationsbutton->setDisabled(true); blindedges->setDisabled(true); + similaritysearch->setDisabled(true); sequencedatabaseline->setDisabled(false); sequencedatabasebutton->setDisabled(false); maximumnumberofthreads->setDisabled(true); diff --git a/CycloBranch/gui/cParametersWidget.h b/CycloBranch/gui/cParametersWidget.h index a3bf011..46bff4d 100644 --- a/CycloBranch/gui/cParametersWidget.h +++ b/CycloBranch/gui/cParametersWidget.h @@ -37,6 +37,7 @@ class QCheckBox; class QTableWidget; class QListWidget; class QMessageBox; +class QScrollArea; /** @@ -109,6 +110,8 @@ class cParametersWidget : public QWidget QVBoxLayout* vlayout2; QVBoxLayout* vlayout; QHBoxLayout* hlayout; + QWidget* hlayoutwidget; + QScrollArea* hlayoutscroll; QString settingsfile; QString oldsettingsfile; @@ -154,6 +157,7 @@ class cParametersWidget : public QWidget QCheckBox* cyclicnterminus; QCheckBox* cycliccterminus; QCheckBox* enablescrambling; + QCheckBox* similaritysearch; QFormLayout* applicationformlayout; QGroupBox* applicationgroupbox; diff --git a/CycloBranch/gui/cSequenceDatabaseWidget.cpp b/CycloBranch/gui/cSequenceDatabaseWidget.cpp index 7d70122..963bf63 100644 --- a/CycloBranch/gui/cSequenceDatabaseWidget.cpp +++ b/CycloBranch/gui/cSequenceDatabaseWidget.cpp @@ -16,6 +16,7 @@ #include #include #include +#include cSequenceDatabaseWidget::cSequenceDatabaseWidget(QWidget* parent) { @@ -33,17 +34,44 @@ cSequenceDatabaseWidget::cSequenceDatabaseWidget(QWidget* parent) { close->setToolTip("Close the window."); load = new QPushButton(tr("Load")); load->setToolTip("Load the database of sequences."); - save = new QPushButton(QString("Save")); + 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."); saveas = new QPushButton(tr("Save As...")); saveas->setToolTip("Save the database of sequences into a file."); + rowsfilterline = new QLineEdit(); + rowsfilterline->setMinimumWidth(250); + rowsfilterline->setToolTip("Text to Find"); + rowsfiltercasesensitive = new QCheckBox(); + rowsfiltercasesensitive->setToolTip("Case Sensitive"); + rowsfilterbutton = new QPushButton("Filter"); + rowsfilterbutton->setToolTip("Filter Search Results"); + rowsfilterbutton->setMinimumWidth(50); + rowsfilterclearbutton = new QPushButton("Clear"); + rowsfilterclearbutton->setToolTip("Clear Form and Reset Search Results"); + rowsfilterclearbutton->setMinimumWidth(50); + + rowsfilterhbox = new QHBoxLayout(); + rowsfilterhbox->addWidget(rowsfilterline); + rowsfilterhbox->addStretch(); + rowsfilterhbox->addWidget(rowsfiltercasesensitive); + rowsfilterhbox->addStretch(); + rowsfilterhbox->addWidget(rowsfilterbutton); + rowsfilterhbox->addStretch(); + rowsfilterhbox->addWidget(rowsfilterclearbutton); + + rowsfilterwidget = new QWidget(); + rowsfilterwidget->setLayout(rowsfilterhbox); + rowsfilterwidget->setMaximumWidth(420); + buttons = new QHBoxLayout(); buttons->addWidget(close); - buttons->addStretch(1); + buttons->addStretch(); buttons->addWidget(insertrow); buttons->addWidget(removechecked); - buttons->addStretch(10); + buttons->addStretch(); + buttons->addWidget(rowsfilterwidget); + buttons->addStretch(); buttons->addWidget(load); buttons->addWidget(save); buttons->addWidget(saveas); @@ -78,11 +106,13 @@ cSequenceDatabaseWidget::cSequenceDatabaseWidget(QWidget* parent) { 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(removeEmptyRows())); + 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())); + connect(rowsfilterbutton, SIGNAL(released()), this, SLOT(filterRows())); + connect(rowsfilterclearbutton, SIGNAL(released()), this, SLOT(resetFilter())); setLayout(mainlayout); @@ -93,10 +123,12 @@ cSequenceDatabaseWidget::cSequenceDatabaseWidget(QWidget* parent) { #if OS_TYPE == WIN lastdir = "./SequenceDatabases/"; #else - lastdir = linuxinstalldir + "SequenceDatabases/"; + lastdir = installdir + "SequenceDatabases/"; #endif sequences.clear(); + + setDataModified(false); } @@ -115,6 +147,14 @@ cSequenceDatabaseWidget::~cSequenceDatabaseWidget() { delete load; delete save; delete saveas; + + delete rowsfilterline; + delete rowsfiltercasesensitive; + delete rowsfilterbutton; + delete rowsfilterclearbutton; + delete rowsfilterhbox; + delete rowsfilterwidget; + delete database; delete buttons; delete mainlayout; @@ -222,7 +262,7 @@ bool cSequenceDatabaseWidget::checkFormula(int row, const string& summary) { return false; } if (database->item(row, 4)) { - database->item(row, 4)->setData(Qt::DisplayRole, formula.getMass()); + database->item(row, 4)->setData(Qt::DisplayRole, to_string(formula.getMass()).c_str()); } return true; } @@ -290,14 +330,49 @@ bool cSequenceDatabaseWidget::checkSequence(int row) { } +void cSequenceDatabaseWidget::setDataModified(bool datamodified) { + if (datamodified == this->datamodified) { + return; + } + + this->datamodified = datamodified; + + if (datamodified) { + save->setText("*" + save->text()); + } + else { + if ((save->text().size() > 0) && (save->text().at(0) == '*')) { + save->setText(save->text().toStdString().substr(1).c_str()); + } + } +} + + void cSequenceDatabaseWidget::keyPressEvent(QKeyEvent *event) { - if(event->key() == Qt::Key_Escape) { - hide(); + if (event->key() == Qt::Key_Escape) { + closeWindow(); + } + + if ((event->key() == Qt::Key_Enter) || (event->key() == Qt::Key_Return)) { + if (rowsfilterline->hasFocus()) { + filterRows(); + } } } void cSequenceDatabaseWidget::closeWindow() { + if (datamodified) { + QMessageBox::StandardButton reply; + reply = QMessageBox::question(this, appname, "Save changes ?", QMessageBox::Yes|QMessageBox::No); + + if (reply == QMessageBox::Yes) { + if (!saveDatabase()) { + return; + } + } + } + hide(); } @@ -309,7 +384,7 @@ void cSequenceDatabaseWidget::loadDatabase() { lastdir = filename; databasefile = filename; - save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); + save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); inputstream.open(filename.toStdString().c_str()); @@ -342,6 +417,7 @@ void cSequenceDatabaseWidget::loadDatabase() { combo->addItem(QString(getStringFromPeptideType((peptideType)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()); @@ -352,7 +428,7 @@ void cSequenceDatabaseWidget::loadDatabase() { formula.setFormula(sequences[i].getSummaryFormula()); database->setItem(i, 4, widgetitemallocator.getNewItem()); - database->item(i, 4)->setData(Qt::DisplayRole, formula.getMass()); + database->item(i, 4)->setData(Qt::DisplayRole, to_string(formula.getMass()).c_str()); database->setItem(i, 5, widgetitemallocator.getNewItem()); database->item(i, 5)->setText(sequences[i].getSequence().c_str()); @@ -385,6 +461,8 @@ void cSequenceDatabaseWidget::loadDatabase() { } progress.setValue(sequences.size()); + + setDataModified(false); } @@ -394,15 +472,15 @@ void cSequenceDatabaseWidget::loadDatabase() { } -void cSequenceDatabaseWidget::saveDatabase() { +bool cSequenceDatabaseWidget::saveDatabase() { + bool saved = false; if (!checkTable()) { - return; + return saved; } if (databasefile.compare("") == 0) { - saveDatabaseAs(); - return; + return saveDatabaseAs(); } outputstream.open(databasefile.toStdString().c_str()); @@ -423,9 +501,15 @@ void cSequenceDatabaseWidget::saveDatabase() { sequences.clear(); string s; - removeEmptyRows(); + removeCheckedRows(); for (int i = 0; i < database->rowCount(); i++) { + + if (database->isRowHidden(i)) { + progress.setValue(i); + continue; + } + seq.clear(); for (int j = 0; j < database->columnCount(); j++) { switch (j) @@ -483,15 +567,20 @@ void cSequenceDatabaseWidget::saveDatabase() { progress.setValue(progress.maximum()); + setDataModified(false); + + saved = true; + } outputstream.close(); -} + return saved; +} -void cSequenceDatabaseWidget::saveDatabaseAs() { +bool cSequenceDatabaseWidget::saveDatabaseAs() { if (!checkTable()) { - return; + return false; } QString filename = QFileDialog::getSaveFileName(this, tr("Save the Database of Sequences As..."), lastdir, tr("Database of Sequences (*.txt)")); @@ -500,9 +589,11 @@ void cSequenceDatabaseWidget::saveDatabaseAs() { lastdir = filename; databasefile = filename; - save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); - saveDatabase(); + save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); + return saveDatabase(); } + + return false; } @@ -518,6 +609,7 @@ void cSequenceDatabaseWidget::addRow() { combo->addItem(QString(getStringFromPeptideType((peptideType)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()); @@ -536,11 +628,12 @@ void cSequenceDatabaseWidget::addRow() { } -void cSequenceDatabaseWidget::removeEmptyRows() { +void cSequenceDatabaseWidget::removeCheckedRows() { int i = 0; while (i < database->rowCount()) { if (((QCheckBox *)(database->cellWidget(i, 0)))->isChecked()) { removeRow(i); + setDataModified(true); } else { i++; @@ -567,10 +660,14 @@ void cSequenceDatabaseWidget::itemChanged(QTableWidgetItem* item) { seq.setReference(database->item(item->row(), 9)->text().toStdString()); ((QLabel *)database->cellWidget(item->row(), 10))->setText(seq.getNameWithReferenceAsHTMLString().c_str()); } + + setDataModified(true); } void cSequenceDatabaseWidget::headerItemDoubleClicked(int index) { + setDataModified(true); + if (headersort[index] == -1) { database->sortByColumn(index, Qt::AscendingOrder); headersort[index] = 1; @@ -587,3 +684,61 @@ void cSequenceDatabaseWidget::headerItemDoubleClicked(int index) { } } + +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, 0, rowcount, this); + 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; + } + + if (database->item(i, j)->text().contains(str, casesensitive)) { + match = true; + break; + } + } + database->setRowHidden(i, !match); + progress.setValue(i); + } + + progress.setValue(rowcount); +} + + +void cSequenceDatabaseWidget::resetFilter() { + rowsfilterline->setText(""); + int rowcount = database->rowCount(); + + QProgressDialog progress("Updating...", /*"Cancel"*/0, 0, rowcount, this); + 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); + } + + progress.setValue(rowcount); +} + + +void cSequenceDatabaseWidget::comboBoxModified(int index) { + setDataModified(true); +} + diff --git a/CycloBranch/gui/cSequenceDatabaseWidget.h b/CycloBranch/gui/cSequenceDatabaseWidget.h index 204c984..e206bcb 100644 --- a/CycloBranch/gui/cSequenceDatabaseWidget.h +++ b/CycloBranch/gui/cSequenceDatabaseWidget.h @@ -23,6 +23,8 @@ class QVBoxLayout; class QTableWidget; class QTableWidgetItem; class QPushButton; +class QLineEdit; +class QCheckBox; /** @@ -64,6 +66,7 @@ class cSequenceDatabaseWidget : public QWidget private: + QWidget* parent; QPushButton* insertrow; QPushButton* removechecked; @@ -71,6 +74,14 @@ class cSequenceDatabaseWidget : public QWidget QPushButton* load; QPushButton* save; QPushButton* saveas; + + QWidget* rowsfilterwidget; + QHBoxLayout* rowsfilterhbox; + QLineEdit* rowsfilterline; + QCheckBox* rowsfiltercasesensitive; + QPushButton* rowsfilterbutton; + QPushButton* rowsfilterclearbutton; + QTableWidget* database; QHBoxLayout* buttons; QVBoxLayout* mainlayout; @@ -85,6 +96,8 @@ class cSequenceDatabaseWidget : public QWidget cAllocator widgetitemallocator; + bool datamodified; + void deleteTable(bool enableprogress); void removeRow(int row); @@ -95,6 +108,8 @@ class cSequenceDatabaseWidget : public QWidget bool checkSequence(int row); + void setDataModified(bool datamodified); + protected: @@ -112,18 +127,24 @@ private slots: void loadDatabase(); - void saveDatabase(); + bool saveDatabase(); - void saveDatabaseAs(); + bool saveDatabaseAs(); void addRow(); - void removeEmptyRows(); + void removeCheckedRows(); void itemChanged(QTableWidgetItem* item); void headerItemDoubleClicked(int index); + void filterRows(); + + void resetFilter(); + + void comboBoxModified(int index); + }; #endif diff --git a/CycloBranch/gui/cSpectrumDetailWidget.cpp b/CycloBranch/gui/cSpectrumDetailWidget.cpp index 6327cd4..875e075 100644 --- a/CycloBranch/gui/cSpectrumDetailWidget.cpp +++ b/CycloBranch/gui/cSpectrumDetailWidget.cpp @@ -148,8 +148,6 @@ cSpectrumDetailWidget::~cSpectrumDetailWidget() { break; } - delete actionExportPeptide; - } delete hsplitter1; @@ -158,6 +156,9 @@ cSpectrumDetailWidget::~cSpectrumDetailWidget() { delete vsplitter; delete actionExportSpectrum; + delete actionFind; + delete actionPrevious; + delete actionNext; delete actionZoomIn; delete actionZoomOut; delete actionZoomReset; @@ -166,6 +167,9 @@ cSpectrumDetailWidget::~cSpectrumDetailWidget() { delete actionHideScrambled; delete actionMouseMzSelection; + delete finddialog; + delete exportdialog; + } } @@ -219,19 +223,37 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { toolbarExport->setMovable(false); toolbarExport->setFloatable(false); - actionExportSpectrum = new QAction(QIcon(":/images/icons/54.png"), tr("Export Spectrum"), this); + actionExportSpectrum = new QAction(QIcon(":/images/icons/66.png"), tr("Export Image"), this); actionExportSpectrum->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E)); - actionExportSpectrum->setToolTip("Export Spectrum (Ctrl + E)"); + actionExportSpectrum->setToolTip("Export Image (Ctrl + E)"); toolbarExport->addAction(actionExportSpectrum); - connect(actionExportSpectrum, SIGNAL(triggered()), this, SLOT(exportSpectrum())); + connect(actionExportSpectrum, SIGNAL(triggered()), this, SLOT(openExportDialog())); + + + toolbarFind = addToolBar(tr("Find")); + toolbarFind->setMovable(false); + toolbarFind->setFloatable(false); + + actionFind = new QAction(QIcon(":/images/icons/65.png"), tr("Find Text"), this); + actionFind->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_F)); + actionFind->setToolTip("Find Text (Ctrl + F)"); + toolbarFind->addAction(actionFind); + connect(actionFind, SIGNAL(triggered()), this, SLOT(openFindDialog())); + + actionPrevious = new QAction(QIcon(":/images/icons/56.png"), tr("Find Previous"), this); + actionPrevious->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_1)); + actionPrevious->setToolTip("Find Previous (Ctrl + 1)"); + toolbarFind->addAction(actionPrevious); + connect(actionPrevious, SIGNAL(triggered()), this, SLOT(movePrevious())); + actionPrevious->setDisabled(true); + + actionNext = new QAction(QIcon(":/images/icons/57.png"), tr("Find Next"), this); + actionNext->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_2)); + actionNext->setToolTip("Find Next (Ctrl + 2)"); + toolbarFind->addAction(actionNext); + connect(actionNext, SIGNAL(triggered()), this, SLOT(moveNext())); + actionNext->setDisabled(true); - if (parameters && ((parameters->mode == denovoengine) || (parameters->mode == singlecomparison) || (parameters->mode == databasesearch))) { - actionExportPeptide = new QAction(QIcon(":/images/icons/57.png"), tr("Export Peptide"), this); - actionExportPeptide->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_P)); - actionExportPeptide->setToolTip("Export Peptide (Ctrl + P)"); - toolbarExport->addAction(actionExportPeptide); - connect(actionExportPeptide, SIGNAL(triggered()), this, SLOT(exportPeptide())); - } toolbarZoom = addToolBar(tr("Zoom")); toolbarZoom->setMovable(false); @@ -521,6 +543,9 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { setCentralWidget(vsplitter); centralWidget()->setContentsMargins(10, 10, 10, 10); + finddialog = new cFindDialog(this); + exportdialog = new cExportDialog(this); + resize(1280, 700); if (parameters && theoreticalspectrum) { @@ -555,6 +580,7 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { spectrumscene->initialize(parameters, theoreticalspectrum); textbrowser->setHtml(getDetailsAsHTMLString().c_str()); + } preparedToShow = true; @@ -563,12 +589,88 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { } +void cSpectrumDetailWidget::findAll(const QString& str, QTextDocument::FindFlags opt) { + + currentfinditem = 0; + + // textbrowser + QList extraSelections; + textbrowser->moveCursor(QTextCursor::Start); + QColor color = QColor(Qt::yellow); + + while (textbrowser->find(str, opt)) { + QTextEdit::ExtraSelection extra; + extra.format.setBackground(color); + + extra.cursor = textbrowser->textCursor(); + extraSelections.append(extra); + } + + textbrowser->setExtraSelections(extraSelections); + + + // textedit + extraSelections.clear(); + textedit->moveCursor(QTextCursor::Start); + + while (textedit->find(str, opt)) { + QTextEdit::ExtraSelection extra; + extra.format.setBackground(color); + + extra.cursor = textedit->textCursor(); + extraSelections.append(extra); + } + + textedit->setExtraSelections(extraSelections); + + + if (textbrowser->extraSelections().size() + textedit->extraSelections().size() == 0) { + actionPrevious->setDisabled(true); + actionNext->setDisabled(true); + + QMessageBox msgBox; + QString errstr = "No results were found."; + msgBox.setWindowTitle("Find Text"); + msgBox.setText(errstr); + msgBox.exec(); + } + else { + actionPrevious->setDisabled(false); + actionNext->setDisabled(false); + } + + + // order changed because of setFocus() + if (textedit->extraSelections().size() > 0) { + textedit->setTextCursor(textedit->extraSelections().at(0).cursor); + textedit->setFocus(); + } + + + if (textbrowser->extraSelections().size() > 0) { + textbrowser->setTextCursor(textbrowser->extraSelections().at(0).cursor); + textbrowser->setFocus(); + } + +} + + +void cSpectrumDetailWidget::exportImage(bool exportspectrum) { + if (exportspectrum) { + exportSpectrum(); + } + else { + exportPeptide(); + } +} + + void cSpectrumDetailWidget::keyPressEvent(QKeyEvent *event) { - if(event->key() == Qt::Key_Escape) { + if (event->key() == Qt::Key_Escape) { hide(); } - if(event->key() == Qt::Key_Enter) { + if ((event->key() == Qt::Key_Enter) || (event->key() == Qt::Key_Return)) { setMZInterval(); } } @@ -586,10 +688,10 @@ void cSpectrumDetailWidget::setMZInterval() { void cSpectrumDetailWidget::exportSpectrum() { - #if OS_TYPE == UNX + #if OS_TYPE == WIN QString filename = QFileDialog::getSaveFileName(this, tr("Export Spectrum..."), "./", "PDF Files (*.pdf);; PS Files (*.ps);; PNG Files (*.png);; SVG Files (*.svg)"); #else - QString filename = QFileDialog::getSaveFileName(this, tr("Export Spectrum..."), "./", "PDF Files (*.pdf);; PS Files (*.ps);; PNG Files (*.png)"); + QString filename = QFileDialog::getSaveFileName(this, tr("Export Spectrum..."), "./", "PDF Files (*.pdf);; PNG Files (*.png);; SVG Files (*.svg)"); #endif if (!filename.isEmpty()) { regex rx; @@ -601,11 +703,13 @@ void cSpectrumDetailWidget::exportSpectrum() { selected = true; } - rx = ".+\\.ps$"; - if (!selected && (regex_search(filename.toStdString(), rx))) { - spectrumscene->exportToPDF(filename, true); - selected = true; - } + #if OS_TYPE == WIN + rx = ".+\\.ps$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + spectrumscene->exportToPDF(filename, true); + selected = true; + } + #endif rx = ".+\\.png$"; if (!selected && (regex_search(filename.toStdString(), rx))) { @@ -613,13 +717,11 @@ void cSpectrumDetailWidget::exportSpectrum() { selected = true; } - #if OS_TYPE == UNX - rx = ".+\\.svg$"; - if (!selected && (regex_search(filename.toStdString(), rx))) { - spectrumscene->exportToSVG(filename); - selected = true; - } - #endif + rx = ".+\\.svg$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + spectrumscene->exportToSVG(filename); + selected = true; + } if (!selected) { QMessageBox msgBox; @@ -632,10 +734,10 @@ void cSpectrumDetailWidget::exportSpectrum() { void cSpectrumDetailWidget::exportPeptide() { - #if OS_TYPE == UNX + #if OS_TYPE == WIN QString filename = QFileDialog::getSaveFileName(this, tr("Export Peptide..."), "./", "PDF Files (*.pdf);; PS Files (*.ps);; PNG Files (*.png);; SVG Files (*.svg)"); #else - QString filename = QFileDialog::getSaveFileName(this, tr("Export Peptide..."), "./", "PDF Files (*.pdf);; PS Files (*.ps);; PNG Files (*.png)"); + QString filename = QFileDialog::getSaveFileName(this, tr("Export Peptide..."), "./", "PDF Files (*.pdf);; PNG Files (*.png);; SVG Files (*.svg)"); #endif if (!filename.isEmpty() && parameters) { regex rx; @@ -649,11 +751,13 @@ void cSpectrumDetailWidget::exportPeptide() { selected = true; } - rx = ".+\\.ps$"; - if (!selected && (regex_search(filename.toStdString(), rx))) { - linearwidget->exportToPDF(filename, true); - selected = true; - } + #if OS_TYPE == WIN + rx = ".+\\.ps$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + linearwidget->exportToPDF(filename, true); + selected = true; + } + #endif rx = ".+\\.png$"; if (!selected && (regex_search(filename.toStdString(), rx))) { @@ -661,13 +765,11 @@ void cSpectrumDetailWidget::exportPeptide() { selected = true; } - #if OS_TYPE == UNX - rx = ".+\\.svg$"; - if (!selected && (regex_search(filename.toStdString(), rx))) { - linearwidget->exportToSVG(filename); - selected = true; - } - #endif + rx = ".+\\.svg$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + linearwidget->exportToSVG(filename); + selected = true; + } break; case cyclic: rx = ".+\\.pdf$"; @@ -676,26 +778,25 @@ void cSpectrumDetailWidget::exportPeptide() { selected = true; } - rx = ".+\\.ps$"; + #if OS_TYPE == WIN + rx = ".+\\.ps$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + cyclicwidget->exportToPDF(filename, true); + selected = true; + } + #endif + + rx = ".+\\.png$"; if (!selected && (regex_search(filename.toStdString(), rx))) { - cyclicwidget->exportToPDF(filename, true); + cyclicwidget->exportToPNG(filename); selected = true; } - - rx = ".+\\.png$"; + rx = ".+\\.svg$"; if (!selected && (regex_search(filename.toStdString(), rx))) { - cyclicwidget->exportToPNG(filename); + cyclicwidget->exportToSVG(filename); selected = true; } - - #if OS_TYPE == UNX - rx = ".+\\.svg$"; - if (!selected && (regex_search(filename.toStdString(), rx))) { - cyclicwidget->exportToSVG(filename); - selected = true; - } - #endif break; case branched: rx = ".+\\.pdf$"; @@ -704,12 +805,13 @@ void cSpectrumDetailWidget::exportPeptide() { selected = true; } - rx = ".+\\.ps$"; - if (!selected && (regex_search(filename.toStdString(), rx))) { - branchedwidget->exportToPDF(filename, true); - selected = true; - } - + #if OS_TYPE == WIN + rx = ".+\\.ps$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + branchedwidget->exportToPDF(filename, true); + selected = true; + } + #endif rx = ".+\\.png$"; if (!selected && (regex_search(filename.toStdString(), rx))) { @@ -717,13 +819,11 @@ void cSpectrumDetailWidget::exportPeptide() { selected = true; } - #if OS_TYPE == UNX - rx = ".+\\.svg$"; - if (!selected && (regex_search(filename.toStdString(), rx))) { - branchedwidget->exportToSVG(filename); - selected = true; - } - #endif + rx = ".+\\.svg$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + branchedwidget->exportToSVG(filename); + selected = true; + } break; case lasso: rx = ".+\\.pdf$"; @@ -732,26 +832,25 @@ void cSpectrumDetailWidget::exportPeptide() { selected = true; } - rx = ".+\\.ps$"; + #if OS_TYPE == WIN + rx = ".+\\.ps$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + lassowidget->exportToPDF(filename, true); + selected = true; + } + #endif + + rx = ".+\\.png$"; if (!selected && (regex_search(filename.toStdString(), rx))) { - lassowidget->exportToPDF(filename, true); + lassowidget->exportToPNG(filename); selected = true; } - - rx = ".+\\.png$"; + rx = ".+\\.svg$"; if (!selected && (regex_search(filename.toStdString(), rx))) { - lassowidget->exportToPNG(filename); + lassowidget->exportToSVG(filename); selected = true; } - - #if OS_TYPE == UNX - rx = ".+\\.svg$"; - if (!selected && (regex_search(filename.toStdString(), rx))) { - lassowidget->exportToSVG(filename); - selected = true; - } - #endif break; case linearpolysaccharide: break; @@ -770,3 +869,48 @@ void cSpectrumDetailWidget::exportPeptide() { } } + +void cSpectrumDetailWidget::openFindDialog() { + finddialog->exec(); +} + + +void cSpectrumDetailWidget::openExportDialog() { + if (parameters && ((parameters->mode == denovoengine) || (parameters->mode == singlecomparison) || (parameters->mode == databasesearch))) { + exportdialog->exec(); + } + else { + exportSpectrum(); + } +} + + +void cSpectrumDetailWidget::movePrevious() { + int count = textbrowser->extraSelections().size() + textedit->extraSelections().size(); + currentfinditem = (currentfinditem + count - 1)%count; + + if (currentfinditem < textbrowser->extraSelections().size()) { + textbrowser->setFocus(); + textbrowser->setTextCursor(textbrowser->extraSelections().at(currentfinditem).cursor); + } + else { + textedit->setFocus(); + textedit->setTextCursor(textedit->extraSelections().at(currentfinditem - textbrowser->extraSelections().size()).cursor); + } +} + + +void cSpectrumDetailWidget::moveNext() { + int count = textbrowser->extraSelections().size() + textedit->extraSelections().size(); + currentfinditem = (currentfinditem + 1)%count; + + if (currentfinditem < textbrowser->extraSelections().size()) { + textbrowser->setFocus(); + textbrowser->setTextCursor(textbrowser->extraSelections().at(currentfinditem).cursor); + } + else { + textedit->setFocus(); + textedit->setTextCursor(textedit->extraSelections().at(currentfinditem - textbrowser->extraSelections().size()).cursor); + } +} + diff --git a/CycloBranch/gui/cSpectrumDetailWidget.h b/CycloBranch/gui/cSpectrumDetailWidget.h index 6c0063c..2595315 100644 --- a/CycloBranch/gui/cSpectrumDetailWidget.h +++ b/CycloBranch/gui/cSpectrumDetailWidget.h @@ -9,12 +9,15 @@ #include #include +#include #include "core/cTheoreticalSpectrum.h" #include "gui/cLinearWidget.h" #include "gui/cCyclicWidget.h" #include "gui/cBranchedWidget.h" #include "gui/cLassoWidget.h" #include "gui/cSpectrumSceneWidget.h" +#include "gui/cFindDialog.h" +#include "gui/cExportDialog.h" // forward declaration @@ -103,6 +106,21 @@ class cSpectrumDetailWidget : public QMainWindow \param peptidetype a type of peptide */ void prepareToShow(peptideType peptidetype); + + + /** + \brief Find all occurrences of \a str and highlight them. + \param str search string + \param opt search options + */ + void findAll(const QString& str, QTextDocument::FindFlags opt = 0); + + + /** + \brief Export spectrum/peptide image. + \param exportspectrum if true, a spectrum image is exported; if false, a peptide image is exported + */ + void exportImage(bool exportspectrum); protected: @@ -117,6 +135,7 @@ class cSpectrumDetailWidget : public QMainWindow private: QToolBar* toolbarExport; + QToolBar* toolbarFind; QToolBar* toolbarZoom; QToolBar* toolbarHide; QToolBar* toolbarMz; @@ -124,7 +143,9 @@ class cSpectrumDetailWidget : public QMainWindow QToolBar* toolbarTrotation; QAction* actionExportSpectrum; - QAction* actionExportPeptide; + QAction* actionFind; + QAction* actionPrevious; + QAction* actionNext; QAction* actionZoomIn; QAction* actionZoomOut; QAction* actionZoomReset; @@ -169,6 +190,10 @@ class cSpectrumDetailWidget : public QMainWindow bool preparedToShow; cParameters* parameters; + cFindDialog* finddialog; + cExportDialog* exportdialog; + int currentfinditem; + signals: @@ -190,6 +215,14 @@ private slots: void exportPeptide(); + void openFindDialog(); + + void openExportDialog(); + + void movePrevious(); + + void moveNext(); + }; #endif \ No newline at end of file diff --git a/CycloBranch/gui/cSpectrumSceneWidget.cpp b/CycloBranch/gui/cSpectrumSceneWidget.cpp index eaa1420..fe11e10 100644 --- a/CycloBranch/gui/cSpectrumSceneWidget.cpp +++ b/CycloBranch/gui/cSpectrumSceneWidget.cpp @@ -100,7 +100,6 @@ void cSpectrumSceneWidget::exportToPDF(QString filename, bool postscript) { QString errstr = "The file cannot be created."; #if OS_TYPE == UNX errstr += "\nDo you have a properly configured print server (sudo apt-get install cups-pdf) ?"; - errstr += "\nIf you cannot create a ps file, you can create a pdf file and then use pdf2ps tool."; #endif msgBox.setText(errstr); msgBox.exec(); @@ -128,6 +127,7 @@ void cSpectrumSceneWidget::exportToSVG(QString filename) { return; } + painter.fillRect(QRect(0, 0, scene->width(), scene->height()), Qt::white); scene->render(&painter); painter.end(); } @@ -437,9 +437,11 @@ void cSpectrumSceneWidget::redrawScene() { sprintf_s(tmpbuf,"%.3f\0",visiblepeaks[i].mzratio); s = tmpbuf; hits.push_back(s); + QGraphicsLineItem* line; if (hits.size() > 1) { - scene->addLine(x, h - bottommargin - 2, x, h - bottommargin - std::max((int)y, 5), QPen(Qt::red, 2, Qt::SolidLine)); + line = scene->addLine(x, h - bottommargin - 2, x, h - bottommargin - std::max((int)y, 5), QPen(Qt::red, 2, Qt::SolidLine)); + line->setZValue(1); hiddenitems.clear(); sumh = 0; diff --git a/CycloBranch/images.qrc b/CycloBranch/images.qrc index 74aa3b2..1361d37 100644 --- a/CycloBranch/images.qrc +++ b/CycloBranch/images.qrc @@ -26,7 +26,10 @@ images/icons/84.png images/icons/80.png images/icons/57.png - images/icons/54.png images/icons/64.png + images/icons/95.png + images/icons/65.png + images/icons/56.png + images/icons/66.png diff --git a/CycloBranch/images/cb.icns b/CycloBranch/images/cb.icns new file mode 100644 index 0000000000000000000000000000000000000000..46626aae7370726f179ee59bf867a45376bb952d GIT binary patch literal 35090 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 IM6N<$g6e+WQ2+n{ literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/66.png b/CycloBranch/images/icons/66.png new file mode 100644 index 0000000000000000000000000000000000000000..67c373a3f87219f195c6a1247f475a8acdbc3538 GIT binary patch literal 1187 zcmV;U1YG-xP)F7{~ty?rm>h?rr5A%1f;k9D}*ZnA0%W0w$YcNH()ACPs`|mSu5^d-*W^uy5e9 zEpC1>b8~8(iOxZ0!lpzdBHL6L!d6iWrRbmn1uW$PExn~@r?_o2&{3mr0BWQliMwL$tL2WTSj$*2i}>mmjP4% z3#@gVXA!rvH|>(>OO-e;zi!Q|uo@SCibA)Zd$2$Vv3b4hd5{IT5C!_PC0;tc&9b7{ zrEM}4!OskQxqlk&iBKd$F~XqLQK08gSz1PZk^o9#;wW7%a;YIgVzOy;Bsz}}9P1oM zW4}DBMCcWkT8IBwrBxz`(H3BI{>NAci3Nxd-9xbNCS8`d<&|Vj z0f_|FQ~}}nL5_{_;jENZfftK&#Ee88`o@E(>-G*4y!9L93<`8Q0VYWglUal$8KBc^ zG2$75;u}Lzwh2XRl98KkR&hN;esuJC@oUd0ynZrQT(COsaeD$eb8B#n;Eh(wNf8DR zAejs>n~W-O%I||Q=)=oT=U`KAD*n&K_1+QG-Mo)K`U7FRJv+W%2~7~}Zl+vvJoGv( z0~wh@BeXnAy3dQiV8|I^4MZCpfb;h8?G^Y)8c}AKv5#e<{-h& zM#`lN&@+o71DeeSkkAauEE?=7v*W^@37ot>2>Ib4=4PfDNp zU8uV;6dn(7GQleil(UKq7_)3*7n%0q!*VO0%vy!L-}l1R^8in!YEhP#r21}gj-qR1 z7Pj0ReEaHJbPf1$=wdJJy)zjisH~@4UZPqAlWN%jZD0&XUt14J$D{Pi4$R4Zl(RW0 zqDEEdl|yK9j)NCXxcY7pRT zH9A-%4Rm~*3JfT7@JuQQ&j!(cphN|}Q+F4w_4j57N>5R)*sA6*THR<-(zOcSD@jK| zsu5eixQ1aWg3}7o^&MNHtm1Q_Akyd*8umYj?qM09HV@EW&O6w`e)c#6ri0_+q2YOG zv>a?{ChTH;I|`F<{HhC|UvYy^&ID&Ls9Pl*kfC@V;{Ec~*!#R4KRCv4;*u+L`=ihWCq=lHywRBIyEJduU0 zyfh?b#`f~~ke_=0dNk$f9cgp6->-q|gXRV8e*;Z*vePDpLL>kH002ovPDHLkV1kG! BEtLQO literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/95.png b/CycloBranch/images/icons/95.png new file mode 100644 index 0000000000000000000000000000000000000000..ab9248a091bc0624dd8b2d2df7a2c77ac70d9c7f GIT binary patch literal 1068 zcmV+{1k?M8P)SIF8YdbdI!kma(T*#NZQ1{T4vTdg(Nmlu$|O=y0ZDb_ zmJV>;o)B>i(fbpkoE;sCeuw0bwo&hT=KGL^TrlDSoH{GNhyNaN8PseF){z@^08u^?0wTR(4Y7M z-&{BeGso?i?qHGEu#1A<sj1>)#Q^her3)y)g%jIS0=gS)525#oRvz=KeM=vWf#p zm)`02%N_~!D;v?bc>p&vTEB0?=*%$8yoH&O`3$S*Kswam@ylL@Rqk?p+jQxs03R5* z9aGu_9oNFtk8>GT9>Zv$#)z08m`B+i>&-b^r}I*HN3^S3>#G8DhxxSO0b~o7S6S#gzWBrs>Qq{~!7("cParameters"); qRegisterMetaType >("vector"); diff --git a/CycloBranch/parallel/cGraphReaderThread.cpp b/CycloBranch/parallel/cGraphReaderThread.cpp index 8c9e5da..fb488f2 100644 --- a/CycloBranch/parallel/cGraphReaderThread.cpp +++ b/CycloBranch/parallel/cGraphReaderThread.cpp @@ -74,6 +74,16 @@ int cGraphReaderThread::getCandidatesIter(bool cterminalstartingnode, cCandidate } else { cCandidate candidate(composition, perspectivepath, startmodifID, endmodifID, middlemodifID, middlepos); + + if (!cterminalstartingnode && (((parameters->peptidetype == linear) && !parameters->cyclicnterminus && !parameters->cycliccterminus) || (parameters->peptidetype == branched) || (parameters->peptidetype == linearpolysaccharide))) { + if ((candidate.hasLastBrickArtificial(*bricksdatabasewithcombinations)) && (composition.size() > 0)) { + int bid = atoi(composition.back().c_str()) + 1; + 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))) { if (isInPpmMassErrorTolerance(precursormass, candidate.getPrecursorMass(*bricksdatabasewithcombinations, parameters), parameters->precursormasserrortolerance)) { diff --git a/CycloBranch/readme-macosx-compile.txt b/CycloBranch/readme-macosx-compile.txt new file mode 100644 index 0000000..5a71b33 --- /dev/null +++ b/CycloBranch/readme-macosx-compile.txt @@ -0,0 +1,18 @@ +Tested on OS X Mountain Lion: + +1) Prerequisities: +- download and install Xcode 4.6.2 (release date 15.4.2013) +- download and install Command Line Tools for Xcode 4.6.2 (OS X Mountain Lion) +- download and install Qt 5.2.1 +- download and install brew and type "brew doctor" +- install boost 1.57.0 using "brew install boost" +- install gcc using "brew install gcc" + +2) Execute the following commands in the directory where CycloBranch is unpacked: +- type "/opt/local/share/Qt5.2.1/5.2.1/clang_64/bin/qmake" +- open "Makefile" using a text editor and correct the following lines: +CC = /usr/local/Cellar/gcc/4.9.2_1/bin/gcc-4.9 +CXX = /usr/local/Cellar/gcc/4.9.2_1/bin/g++-4.9 +LINK = /usr/local/Cellar/gcc/4.9.2_1/bin/g++-4.9 +- type "make" +