diff --git a/.gitignore b/.gitignore index 77c2ea2d819fa17b120547f321769e3dc4d66a25..d5ae5ef4afb7aa8732b13aa4afa633cd2675a50a 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ print.prt */tsts/*/input/* */tsts/*/truth/* */tsts/*/output/* +data/ diff --git a/isis/make/config.darwin-MacOSX10_11 b/isis/make/config.darwin-MacOSX10_11 index 2b600ac626ea5eac65da848fbe326f8212c42dcc..4a842ac98b3e35f18dc7845f0fdf47be3690d095 100644 --- a/isis/make/config.darwin-MacOSX10_11 +++ b/isis/make/config.darwin-MacOSX10_11 @@ -39,6 +39,7 @@ endif ISISCPPFLAGS += -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE ISISCPPFLAGS += -fPIC ISISCPPFLAGS += -DGMM_USES_SUPERLU +ISISCPPFLAGS += -std=c++11 #ifeq ($(findstring DEBUG, $(MODE)),DEBUG) ISISCPPFLAGS += -g @@ -380,7 +381,7 @@ NNLIB = -lnn BULLETLIB = -lBullet3OpenCL_clew -lBullet3Common -lBullet3Geometry \ -lBulletSoftBody -lBulletDynamics -lBullet3Dynamics \ -lBulletInverseDynamics -lBulletCollision -lBullet3Collision \ - -lLinearMath + -lLinearMath BULLETINCDIR = -I$(ISIS3LOCAL)/include/bullet BULLETLIBDIR = -L$(ISIS3LOCAL)/lib @@ -394,7 +395,7 @@ ifeq (,$(findstring $(PCLPYFRAMES)/Python.framework,$(wildcard $(PCLPYFRAMES)/Py endif #--------------------------------------------------------------------------- -# Set up for PCL libraries +# Set up for PCL libraries #--------------------------------------------------------------------------- PCLINCDIR = -I$(ISIS3LOCAL)/include/pcl-1.8 PCLLIBDIR = -L$(ISIS3LOCAL)/lib @@ -404,7 +405,7 @@ VTKLIB = -lvtksys-7.0.1 EMBREELIB = -lembree #--------------------------------------------------------------------------- -# Set up for Eigen (link to include files only, no library) +# Set up for Eigen (link to include files only, no library) #--------------------------------------------------------------------------- EIGENINCDIR = -I$(ISIS3OPT)/include/eigen3 diff --git a/isis/make/config.linux-x86_32 b/isis/make/config.linux-x86_32 index 4546d52eff783cc76614d8d21c7e98292d22d88b..9f6edeb255ac067eb738af73c36a2d3b037235ca 100644 --- a/isis/make/config.linux-x86_32 +++ b/isis/make/config.linux-x86_32 @@ -77,6 +77,7 @@ endif #--------------------------------------------------------------------------- QTINCDIR = -I$(ISIS3LOCAL)/include/qt/qt4.6.2 QTINCDIR += -I$(ISIS3LOCAL)/include/qt/qt4.6.2/Qt +QTINCDIR += -I$(ISIS3LOCAL)/include/qt/qt4.6.2/QtChrats QTINCDIR += -I$(ISIS3LOCAL)/include/qt/qt4.6.2/QtCore QTINCDIR += -I$(ISIS3LOCAL)/include/qt/qt4.6.2/QtAssistant QTINCDIR += -I$(ISIS3LOCAL)/include/qt/qt4.6.2/QtGui diff --git a/isis/make/config.linux-x86_64 b/isis/make/config.linux-x86_64 index 3a9a9f92f7d1878043cd084c05a025b5daddf2ee..f9d039a5236c59684e61524ccbcb988b429b251e 100644 --- a/isis/make/config.linux-x86_64 +++ b/isis/make/config.linux-x86_64 @@ -115,7 +115,6 @@ QTINCDIR += -I$(ISIS3LOCAL)/include/qt/qt5.7.1/QtXml QTINCDIR += -I$(ISIS3LOCAL)/include/qt/qt5.7.1/QtXmlPatterns QTLIBDIR = -L$(ISIS3LOCAL)/lib QTLIB = -lQt5Core -lQt5Concurrent -lQt5XmlPatterns -lQt5Xml -lQt5Network -lQt5Sql -lQt5Gui -lQt5PrintSupport -lQt5Positioning -lQt5Qml -lQt5Quick -lQt5Sensors -lQt5Svg -lQt5Test -lQt5OpenGL -lQt5Widgets -lQt5Multimedia -lQt5MultimediaWidgets -lQt5WebChannel -lQt5WebEngine -lQt5WebEngineWidgets -lQt5DBus - UIC = $(ISIS3LOCAL)/bin/uic MOC = $(ISIS3LOCAL)/bin/moc RCC = $(ISIS3LOCAL)/bin/rcc @@ -300,14 +299,14 @@ FLANNINCDIR = -I$(ISIS3LOCAL)/include/flann QHULLINCDIR = -I$(ISIS3LOCAL)/include/qhull #--------------------------------------------------------------------------- -# Set up for Embree libraries +# Set up for Embree libraries #--------------------------------------------------------------------------- EMBREEINCDIR = -I$(ISIS3LOCAL)/include/embree2 EMBREELIBDIR = -L$(ISIS3LOCAL)/lib EMBREELIB = -lembree #--------------------------------------------------------------------------- -# Set up for OpenCV libraries +# Set up for OpenCV libraries # # Add the following line to your app's Makefile (see the NN notes) # ALLLIBS += $(OPENCVLIBS) @@ -344,11 +343,11 @@ NNLIB = -lnn #BULLETLIB = -lBullet3Collision -lBullet3Common \ # -lBullet3Dynamics -lBullet3Geometry -lBullet3OpenCL_clew \ # -lBulletCollision -lBulletDynamics -lBulletInverseDynamics \ -# -lBulletSoftBody -lLinearMath +# -lBulletSoftBody -lLinearMath BULLETLIB = -lBullet3OpenCL_clew -lBullet3Common -lBullet3Geometry \ -lBulletSoftBody -lBulletDynamics -lBullet3Dynamics \ -lBulletInverseDynamics -lBulletCollision -lBullet3Collision \ - -lLinearMath + -lLinearMath BULLETINCDIR = -I$(ISIS3LOCAL)/include/bullet BULLETLIBDIR = -L$(ISIS3LOCAL)/lib diff --git a/isis/make/config.linux-x86_64_Debian8 b/isis/make/config.linux-x86_64_Debian8 index ba893d58d02c7a8505f4c28e290e9685178dc912..376ef9c0cdcdcd7b74186c6bf456f6b51490e9d9 100644 --- a/isis/make/config.linux-x86_64_Debian8 +++ b/isis/make/config.linux-x86_64_Debian8 @@ -115,7 +115,6 @@ QTINCDIR += -I$(ISIS3LOCAL)/include/qt/qt5.7.1/QtXml QTINCDIR += -I$(ISIS3LOCAL)/include/qt/qt5.7.1/QtXmlPatterns QTLIBDIR = -L$(ISIS3LOCAL)/lib QTLIB = -lQt5Core -lQt5Concurrent -lQt5XmlPatterns -lQt5Xml -lQt5Network -lQt5Sql -lQt5Gui -lQt5PrintSupport -lQt5Positioning -lQt5Qml -lQt5Quick -lQt5Sensors -lQt5Svg -lQt5Test -lQt5OpenGL -lQt5Widgets -lQt5Multimedia -lQt5MultimediaWidgets -lQt5WebChannel -lQt5WebEngine -lQt5WebEngineWidgets -lQt5DBus - UIC = $(ISIS3LOCAL)/bin/uic MOC = $(ISIS3LOCAL)/bin/moc RCC = $(ISIS3LOCAL)/bin/rcc @@ -298,7 +297,7 @@ FLANNINCDIR = -I$(ISIS3LOCAL)/include/flann QHULLINCDIR = -I$(ISIS3LOCAL)/include/qhull #--------------------------------------------------------------------------- -# Set up for Embree libraries +# Set up for Embree libraries #--------------------------------------------------------------------------- EMBREEINCDIR = -I$(ISIS3LOCAL)/include/embree2 EMBREELIBDIR = -L$(ISIS3LOCAL)/lib @@ -346,7 +345,7 @@ NNLIB = -lnn BULLETLIB = -lBullet3OpenCL_clew -lBullet3Common -lBullet3Geometry \ -lBulletSoftBody -lBulletDynamics -lBullet3Dynamics \ -lBulletInverseDynamics -lBulletCollision -lBullet3Collision \ - -lLinearMath + -lLinearMath BULLETINCDIR = -I$(ISIS3LOCAL)/include/bullet #--------------------------------------------------------------------------- @@ -359,6 +358,7 @@ DEFAULTINCDIR = -I$(ISIS3LOCAL)/include #--------------------------------------------------------------------------- # Qt Libraries + THIRDPARTYLIBS += "$(ISIS3LOCAL)/lib/libQt5Concurrent.so" THIRDPARTYLIBS += "$(ISIS3LOCAL)/lib/libQt5Concurrent.so.5" THIRDPARTYLIBS += "$(ISIS3LOCAL)/lib/libQt5Concurrent.so.5.7.*[^g]" diff --git a/isis/make/config.linux-x86_64_Fedora21 b/isis/make/config.linux-x86_64_Fedora21 index 558089c7f155485a6b3d993916735fd6e9131f96..b2bbbcf5091bd424abf577facead3b517465f977 100644 --- a/isis/make/config.linux-x86_64_Fedora21 +++ b/isis/make/config.linux-x86_64_Fedora21 @@ -301,14 +301,14 @@ FLANNINCDIR = -I$(ISIS3LOCAL)/include/flann #QHULLINCDIR = -I$(ISIS3LOCAL)/include/qhull #--------------------------------------------------------------------------- -# Set up for Embree libraries +# Set up for Embree libraries #--------------------------------------------------------------------------- EMBREEINCDIR = -I$(ISIS3LOCAL)/include/embree2 EMBREELIBDIR = -L$(ISIS3LOCAL)/lib EMBREELIB = -lembree #--------------------------------------------------------------------------- -# Set up for OpenCV libraries +# Set up for OpenCV libraries # # Add the following line to your app's Makefile (see the NN notes) # ALLLIBS += $(OPENCVLIBS) @@ -345,11 +345,11 @@ NNLIB = -lnn BULLETLIB = -lBullet3Collision -lBullet3Common \ -lBullet3Dynamics -lBullet3Geometry -lBullet3OpenCL_clew \ -lBulletCollision -lBulletDynamics -lBulletInverseDynamics \ - -lBulletSoftBody -lLinearMath + -lBulletSoftBody -lLinearMath #BULLETLIB = -lBullet3OpenCL_clew -lBullet3Common -lBullet3Geometry \ # -lBulletSoftBody -lBulletDynamics -lBullet3Dynamics \ # -lBulletInverseDynamics -lBulletCollision -lBullet3Collision \ -# -lLinearMath +# -lLinearMath BULLETINCDIR = -I$(ISIS3LOCAL)/include/bullet BULLETLIBDIR = -L$(ISIS3LOCAL)/lib @@ -368,6 +368,7 @@ DEFAULTINCDIR = -I$(ISIS3LOCAL)/include #--------------------------------------------------------------------------- # Qt Libraries + THIRDPARTYLIBS += "$(ISIS3LOCAL)/lib/libQt5Concurrent.so" THIRDPARTYLIBS += "$(ISIS3LOCAL)/lib/libQt5Concurrent.so.5" THIRDPARTYLIBS += "$(ISIS3LOCAL)/lib/libQt5Concurrent.so.5.7.*[^g]" diff --git a/isis/make/config.linux-x86_64_Fedora25 b/isis/make/config.linux-x86_64_Fedora25 index 4cb724c0772f5ce734bf9f91b631788bf5017be9..54e80fe6c089d46b35d4481d991342bfc388116d 100644 --- a/isis/make/config.linux-x86_64_Fedora25 +++ b/isis/make/config.linux-x86_64_Fedora25 @@ -301,14 +301,14 @@ FLANNINCDIR = -I$(ISIS3LOCAL)/include/flann #QHULLINCDIR = -I$(ISIS3LOCAL)/include/qhull #--------------------------------------------------------------------------- -# Set up for Embree libraries +# Set up for Embree libraries #--------------------------------------------------------------------------- EMBREEINCDIR = -I$(ISIS3LOCAL)/include/embree2 EMBREELIBDIR = -L$(ISIS3LOCAL)/lib EMBREELIB = -lembree #--------------------------------------------------------------------------- -# Set up for OpenCV libraries +# Set up for OpenCV libraries # # Add the following line to your app's Makefile (see the NN notes) # ALLLIBS += $(OPENCVLIBS) @@ -345,11 +345,11 @@ NNLIB = -lnn BULLETLIB = -lBullet3Collision -lBullet3Common \ -lBullet3Dynamics -lBullet3Geometry -lBullet3OpenCL_clew \ -lBulletCollision -lBulletDynamics -lBulletInverseDynamics \ - -lBulletSoftBody -lLinearMath + -lBulletSoftBody -lLinearMath #BULLETLIB = -lBullet3OpenCL_clew -lBullet3Common -lBullet3Geometry \ # -lBulletSoftBody -lBulletDynamics -lBullet3Dynamics \ # -lBulletInverseDynamics -lBulletCollision -lBullet3Collision \ -# -lLinearMath +# -lLinearMath BULLETINCDIR = -I$(ISIS3LOCAL)/include/bullet BULLETLIBDIR = -L$(ISIS3LOCAL)/lib @@ -368,6 +368,7 @@ DEFAULTINCDIR = -I$(ISIS3LOCAL)/include #--------------------------------------------------------------------------- # Qt Libraries + THIRDPARTYLIBS += "$(ISIS3LOCAL)/lib/libQt5Concurrent.so" THIRDPARTYLIBS += "$(ISIS3LOCAL)/lib/libQt5Concurrent.so.5" THIRDPARTYLIBS += "$(ISIS3LOCAL)/lib/libQt5Concurrent.so.5.7.*[^g]" diff --git a/isis/make/config.linux-x86_64_Ubuntu14_04 b/isis/make/config.linux-x86_64_Ubuntu14_04 index c2a0d1e46d1f9d976977c0a6e0b5f061f3ed0c64..5cd34f75518182576ffdc29d81e9943d564d6b8f 100644 --- a/isis/make/config.linux-x86_64_Ubuntu14_04 +++ b/isis/make/config.linux-x86_64_Ubuntu14_04 @@ -298,7 +298,7 @@ FLANNINCDIR = -I$(ISIS3LOCAL)/include/flann QHULLINCDIR = -I$(ISIS3LOCAL)/include/qhull #--------------------------------------------------------------------------- -# Set up for Embree libraries +# Set up for Embree libraries #--------------------------------------------------------------------------- EMBREEINCDIR = -I$(ISIS3LOCAL)/include/embree2 EMBREELIBDIR = -L$(ISIS3LOCAL)/lib @@ -355,6 +355,7 @@ DEFAULTINCDIR = -I$(ISIS3LOCAL)/include #--------------------------------------------------------------------------- # Qt Libraries + THIRDPARTYLIBS += "$(ISIS3LOCAL)/lib/libQt5Concurrent.so" THIRDPARTYLIBS += "$(ISIS3LOCAL)/lib/libQt5Concurrent.so.5" THIRDPARTYLIBS += "$(ISIS3LOCAL)/lib/libQt5Concurrent.so.5.7.*[^g]" diff --git a/isis/src/base/apps/ddd2isis/ddd2isis.cpp b/isis/src/base/apps/ddd2isis/ddd2isis.cpp index 2db7e354feeb2e57923dccac114418755af89893..efae0dc7aa3568117bdb73a438859d6330fb2681 100644 --- a/isis/src/base/apps/ddd2isis/ddd2isis.cpp +++ b/isis/src/base/apps/ddd2isis/ddd2isis.cpp @@ -4,26 +4,19 @@ #include "SpecialPixel.h" #include "FileName.h" #include "Pvl.h" +#include <QMap> using namespace std; using namespace Isis; void IsisMain() { + UserInterface &ui = Application::GetUserInterface(); - ProcessImport p; IString from = ui.GetFileName("FROM"); - EndianSwapper swp("MSB"); - int nsamples = 0, nlines = 0, nbands = 1, noffset = 0, bittype = 0, nbytes = 0; - - union { - char readChars[4]; - long readLong; - float readFloat; - } readBytes; - ifstream fin; + fin.open(from.c_str(), ios::in | ios::binary); - if(!fin.is_open()) { + if( !fin.is_open() ) { string msg = "Cannot open input file [" + from + "]"; throw IException(IException::Io, msg, _FILEINFO_); } @@ -41,86 +34,146 @@ void IsisMain() { * */ - // Verify the magic number + // ifstream read() needs a char* to read values into, so the union + // is used to store read values + union { + char readChars[4]; + long readLong; + float readFloat; + } readBytes; + + // ddd files are LSB + EndianSwapper swp("MSB"); + + // Verify that the file is a ddd by reading in the first 4 bytes and + // comparing the magic numbers. The magic number for a ddd file is 1659. readBytes.readLong = 0; fin.seekg(0); fin.read(readBytes.readChars, 4); + if( fin.fail() || fin.eof() ) { + string msg = "Could not read the magic number in the input file [" + from + "]"; + throw IException(IException::Io, msg, _FILEINFO_); + } readBytes.readFloat = swp.Float(readBytes.readChars); - if(readBytes.readLong != 0x67B) { + if(readBytes.readLong != 1659) { string msg = "Input file [" + from + "] does not appear to be in ddd format"; throw IException(IException::Io, msg, _FILEINFO_); } + // Read bytes 4-7 to get number of lines fin.read(readBytes.readChars, 4); + if( fin.fail() || fin.eof() ) { + string msg = "Could not read the number of lines in the input file [" + from + "]"; + throw IException(IException::Io, msg, _FILEINFO_); + } readBytes.readFloat = swp.Float(readBytes.readChars); - nlines = (int)readBytes.readLong; + int nLines = (int) readBytes.readLong; + // Read bytes 8-11 to get number of bytes fin.read(readBytes.readChars, 4); + if( fin.fail() || fin.eof() ) { + string msg = "Could not read the number of bytes in the input file [" + from + "]"; + throw IException(IException::Io, msg, _FILEINFO_); + } readBytes.readFloat = swp.Float(readBytes.readChars); - nbytes = (int)readBytes.readLong; + int nBytes = (int) readBytes.readLong; + // Read bytes 12-15 to get the total number of bits out of all the bands fin.read(readBytes.readChars, 4); - readBytes.readFloat = swp.Float(readBytes.readChars); - - if(fin.fail() || fin.eof()) { - string msg = "An error ocurred when reading the input file [" + from + "]"; + if( fin.fail() || fin.eof() ) { + string msg = "Could not read the number of bits in the input file [" + from + "]"; throw IException(IException::Io, msg, _FILEINFO_); } - - bittype = readBytes.readLong; - - fin.read(readBytes.readChars, 4); readBytes.readFloat = swp.Float(readBytes.readChars); - + int totalBandBits = readBytes.readLong; + + // Maps the bit type of the file to the number of bytes of that type + // Taken directly from a given python program that reads in ddd data + QMap<int, int> dataTypes; + dataTypes.insert(1450901768, 1); + dataTypes.insert(1450902032, 2); + dataTypes.insert(1450902288, 2); + dataTypes.insert(1450902560, 4); + dataTypes.insert(1450902816, 4); + dataTypes.insert(1450903072, 4); + dataTypes.insert(1450903360, 8); + dataTypes.insert(8, 1); + dataTypes.insert(16, 2); + dataTypes.insert(48, 2); + + // Read bytes 16-19 to get the bit type + // Map the bit type to the number of bytes of that data type fin.read(readBytes.readChars, 4); readBytes.readFloat = swp.Float(readBytes.readChars); - noffset = (int)readBytes.readLong; - if (noffset < 1024) { - noffset = 1024; + int bitType = (int) readBytes.readLong; + + int dataTypeBytes; + int nOffset; + // Check for new header format. Taken from the python program. + if ( (bitType & 0xfffff000) == 0x567b0000 ) { + dataTypeBytes = dataTypes.value(bitType); + + // Read bytes 20-23 to get offset + // New header format may have different offsets + fin.read(readBytes.readChars, 4); + readBytes.readFloat = swp.Float(readBytes.readChars); + nOffset = (int) readBytes.readLong; + if (nOffset < 1024) { + nOffset = 1024; + } + } + else { + // Old header format does not have a bit type + // Old header format's offset is always 1024. + dataTypeBytes = dataTypes.value(totalBandBits); + nOffset = 1024; } + fin.close(); + PvlGroup results("FileInfo"); - results += PvlKeyword("NumberOfLines", toString(nlines)); - results += PvlKeyword("NumberOfBytesPerLine", toString(nbytes)); - results += PvlKeyword("BitType", toString(bittype)); - nsamples = nbytes / (bittype / 8); - results += PvlKeyword("NumberOfSamples", toString(nsamples)); - nbands = nbytes / nsamples; - results += PvlKeyword("NumberOfBands", toString(nbands)); - results += PvlKeyword("LabelBytes", toString(noffset)); + results += PvlKeyword( "NumberOfLines", toString(nLines) ); + results += PvlKeyword( "NumberOfBytesPerLine", toString(nBytes) ); + results += PvlKeyword( "BitType", toString(bitType) ); + int nSamples = nBytes / (totalBandBits / 8); + results += PvlKeyword( "NumberOfSamples", toString(nSamples) ); + int nBands = (totalBandBits / 8) / dataTypeBytes; + results += PvlKeyword( "NumberOfBands", toString(nBands) ); + results += PvlKeyword( "LabelBytes", toString(nOffset) ); Application::Log(results); - fin.close(); - - if (ui.WasEntered("TO")) { - switch(bittype) { - case 8: - p.SetPixelType(Isis::UnsignedByte); - break; - case 16: - p.SetPixelType(Isis::UnsignedWord); - break; - case 32: - p.SetPixelType(Isis::Real); - break; - default: - IString msg = "Unsupported bit per pixel count [" + IString(bittype) + "]. "; - msg += "(Use the raw2isis and crop programs to import the file in case it is "; - msg += "line or sample interleaved.)"; - throw IException(IException::Io, msg, _FILEINFO_); - } + ProcessImport p; - p.SetDimensions(nsamples, nlines, nbands); - p.SetFileHeaderBytes(noffset); - p.SetByteOrder(Isis::Msb); - p.SetInputFile(ui.GetFileName("FROM")); - p.SetOutputCube("TO"); + int bitsPerBand = totalBandBits / nBands; + switch(bitsPerBand) { + case 8: + p.SetPixelType(Isis::UnsignedByte); + break; + case 16: + p.SetPixelType(Isis::UnsignedWord); + break; + case 32: + p.SetPixelType(Isis::Real); + break; + default: + IString msg = "Unsupported bit per pixel count [" + IString(bitsPerBand) + "] "; + msg += "from [" + from + "]"; + throw IException(IException::Io, msg, _FILEINFO_); + } - p.StartProcess(); - p.EndProcess(); + // ddd files with more than one band are pixel interleaved + // Having one band is similar to BIP, but this is here for clarification + if (nBands > 1) { + p.SetOrganization(ProcessImport::BIP); } - return; -} + p.SetDimensions(nSamples, nLines, nBands); + p.SetFileHeaderBytes(nOffset); + p.SetByteOrder(Isis::Msb); + p.SetInputFile( ui.GetFileName("FROM") ); + p.SetOutputCube("TO"); + p.StartProcess(); + p.EndProcess(); +} diff --git a/isis/src/base/apps/ddd2isis/ddd2isis.xml b/isis/src/base/apps/ddd2isis/ddd2isis.xml index e35ea4decf63a2909a8f699198bd113543c33d30..19548a0aff53048f4a06974e0accc43b0cb2c968 100644 --- a/isis/src/base/apps/ddd2isis/ddd2isis.xml +++ b/isis/src/base/apps/ddd2isis/ddd2isis.xml @@ -7,7 +7,8 @@ </brief> <description> - This program will import a ddd image into an Isis cube. The ddd format files are created by Malin Space Science Systems. + This program will import a ddd image into an Isis cube. The ddd format files + are created by Malin Space Science Systems. </description> <history> @@ -30,6 +31,16 @@ will need to be read in using a combination of the raw2isis and crop programs. Fixes #1713. </change> + <change name="Kaitlyn Lee" date="2018-03-01"> + We were given a python program that reads in data from a ddd file + to use as an example. In the python program, the formula they used to + calculate the number of bands is different from the one we previously used. + The old formula did the number of total band bits / 8; the formula is now + (the number of total band bits / 8) / the number of bytes of the data type + of the file's bit type. Added the ability to process files with multiple + bands. Removed the internal default of the output parameter set to None so + that an output file is now requried. Fixes #703. + </change> </history> <category> @@ -55,7 +66,6 @@ <parameter name="TO"> <type>cube</type> <fileMode>output</fileMode> - <internalDefault>None</internalDefault> <brief> Output Isis cube </brief> diff --git a/isis/src/base/apps/ddd2isis/tsts/default/Makefile b/isis/src/base/apps/ddd2isis/tsts/default/Makefile index a1ac8f27297b69f98b7d719b691b7fe4275918df..1272a0aca97f291f6610d723012c9419628a2a33 100644 --- a/isis/src/base/apps/ddd2isis/tsts/default/Makefile +++ b/isis/src/base/apps/ddd2isis/tsts/default/Makefile @@ -4,3 +4,5 @@ include $(ISISROOT)/make/isismake.tsts commands: $(APPNAME) FROM=$(INPUT)/vis1flat.ddd TO=$(OUTPUT)/vis1flat.cub > /dev/null; + $(APPNAME) FROM=$(INPUT)/0023MD0000140000101507C00_DXXX_16b.ddd \ + TO=$(OUTPUT)/0023MD0000140000101507C00_DXXX_16b.cub > /dev/null; diff --git a/isis/src/base/apps/ddd2isis/tsts/errors/Makefile b/isis/src/base/apps/ddd2isis/tsts/errors/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4aa6202f90433c5ba1d0021e8d55518ffd45e6ab --- /dev/null +++ b/isis/src/base/apps/ddd2isis/tsts/errors/Makefile @@ -0,0 +1,24 @@ +APPNAME = ddd2isis + +include $(ISISROOT)/make/isismake.tsts + +commands: + # TEST: Throws an error when trying to open the file + if [ `$(APPNAME) \ + FROM=$(INPUT)/vis1flat.ddd \ + TO=$(OUTPUT)/vis1flat.cub \ + 2> $(OUTPUT)/temp.txt > /dev/null` ]; \ + then true; \ + fi; + + # TEST: Throws an error when trying to read from a cub instead of ddd + if [ `$(APPNAME) \ + FROM=$(INPUT)/vis1flat.cub \ + TO=$(OUTPUT)/vis1flat.cub \ + 2>> $(OUTPUT)/temp.txt > /dev/null` ]; \ + then true; \ + fi; + + # Removes input file path up until input + $(SED) 's+\[.*/input+[input+' $(OUTPUT)/temp.txt > $(OUTPUT)/errorTruth.txt; + $(RM) $(OUTPUT)/temp.txt diff --git a/isis/src/base/apps/dsk2isis/dsk2isis.xml b/isis/src/base/apps/dsk2isis/dsk2isis.xml index 3378468635f2b3bca5bcfc85aaa26f7a94ed8bc3..003b304c6fcc6c8dcc88af620f922b7670027ff9 100755 --- a/isis/src/base/apps/dsk2isis/dsk2isis.xml +++ b/isis/src/base/apps/dsk2isis/dsk2isis.xml @@ -7,9 +7,9 @@ </brief> <description> - This application will convert a NAIF DSK plate model to an ISIS cube. - Users must provide a valid map file to use for allocation of the ISIS - cube. The scale and type of projection determine the size of the output + This application will convert a NAIF DSK plate model to an ISIS cube. + Users must provide a valid map file to use for allocation of the ISIS + cube. The scale and type of projection determine the size of the output cube. </description> @@ -24,10 +24,13 @@ Process data tiles instead of a pixel at a time; Test for valid output map coordinate at every map pixel. References #2035 </change> + <change name="Kaitlyn Lee" date="2018-03-10"> + Changed the category to Import and Export. Fixes #5188. + </change> </history> <category> - <categoryItem>Map Projection</categoryItem> + <categoryItem>Import and Export</categoryItem> </category> <groups> @@ -37,9 +40,9 @@ <fileMode>input</fileMode> <brief>Name of NAIF DSK DEM file</brief> <description> - This parameter provides the name of the NAIF DSK file to convert to - ISIS format. It is assumed to be in body fixed coordinates from which - intersections for each output map grid point will be computed using + This parameter provides the name of the NAIF DSK file to convert to + ISIS format. It is assumed to be in body fixed coordinates from which + intersections for each output map grid point will be computed using NAIF's DSK toolkit. </description> <filter> @@ -52,8 +55,8 @@ <fileMode>input</fileMode> <brief>Name of file containing map description</brief> <description> - This paramter provides the name of a file containing a valid map - projection defintion. One can use the ISIS maptemplate application + This paramter provides the name of a file containing a valid map + projection defintion. One can use the ISIS maptemplate application to create a map template. </description> <filter> @@ -69,8 +72,8 @@ Output cube </brief> <description> - Name of the output ISIS file created by this application containing - the rendering of the DSK DEM into and ISIS compatible DEM for use in + Name of the output ISIS file created by this application containing + the rendering of the DSK DEM into and ISIS compatible DEM for use in the ISIS system. </description> </parameter> @@ -82,8 +85,8 @@ </brief> <description> <p> - This parameter provides two different methods to compute the - output radius value for a given latitude, longitude map grid + This parameter provides two different methods to compute the + output radius value for a given latitude, longitude map grid point. </p> </description> @@ -91,27 +94,27 @@ <list> <option value="RAY"> <brief> - Ray intersection from image pixel location to DEM + Ray intersection from image pixel location to DEM </brief> <description> - Calculates an intercept location on the (irregularly - shaped) body from the observer point (i.e., image pixel - location) and look (or ray) direction + Calculates an intercept location on the (irregularly + shaped) body from the observer point (i.e., image pixel + location) and look (or ray) direction </description> </option> <option value="GRID"> <brief> - Calculate using surface point latitude, longitude grid - point + Calculate using surface point latitude, longitude grid + point </brief> <description> - The radius value of the DEM is determined at the - intercept point of the triaxial ellipsoid from the - center of the body. This method extends the surface (x, - y, z) body fixed coordinate of the ellisoid by - extending the vector by a factor of 1.5. This creates - the obsever point. The direction vector is then the - negation of the observer point. From this, a DEM + The radius value of the DEM is determined at the + intercept point of the triaxial ellipsoid from the + center of the body. This method extends the surface (x, + y, z) body fixed coordinate of the ellisoid by + extending the vector by a factor of 1.5. This creates + the obsever point. The direction vector is then the + negation of the observer point. From this, a DEM surface intercept point is determined. </description> </option> diff --git a/isis/src/control/apps/cnetwinnow/cnetwinnow.cpp b/isis/src/control/apps/cnetwinnow/cnetwinnow.cpp index 6510a966bc67d6d98b3122672f10a1ca0722c725..b7194969f145a5d23c407b578066eaea0c687432 100644 --- a/isis/src/control/apps/cnetwinnow/cnetwinnow.cpp +++ b/isis/src/control/apps/cnetwinnow/cnetwinnow.cpp @@ -311,7 +311,6 @@ void IsisMain() { measFlag[j] = true; //test passed } - //for now it is necessary to set measures to ignor before testing to see if they would split the network //this will change when the expected ControlNet::isCriticalMeasure(...) method is written for (int j=0; j<measGroup.size(); j++) { @@ -319,25 +318,12 @@ void IsisMain() { } //if the number of islands has increased the network has split - if (net.GetSerialConnections().size() > numInitialIslands) islandFlag = false; //test failed - else islandFlag = true; //test passed - - //Check to see if the network has split - //this simplifies to making sure that all cubes observing the ControlPoint that had some or - //all of it's measures ignored are still connected - /* //Travis Addair informed me that this method only checks 1 step conections - // thus it was effectively only enforcing that the last tie between pairs - // of images not be ingorned - QList<ControlMeasure *> ptMeas = suspectMeasures[i]->Parent()->getMeasures(); - const ControlCubeGraphNode *node0 = net.getGraphNode(ptMeas[0]->GetCubeSerialNumber()); - islandFlag = true; //assuming the best, and then verify - for (int j=1; j<ptMeas.size(); j++) { - //check each subsequent node for conection to the first - if ( !node0->isConnected(net.getGraphNode(ptMeas[j]->GetCubeSerialNumber()))) { - islandFlag = false; //test failed - break; - } - }*/ + if (net.GetSerialConnections().size() > numInitialIslands) { + islandFlag = false; //test failed + } + else { + islandFlag = true; //test passed + } //again we will temporarily be setting the measure back to unignored //this will change when the expected ControlNet::isCriticalMeasure(...) method is written @@ -393,7 +379,6 @@ void IsisMain() { fclose(guiltyFile); fclose(ignoredReport); - //save out the winnowed ControlNet net.Write(ui.GetFileName("ONET")); } diff --git a/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp b/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp index 2e3ef8cd5d06f392f5fc275da5cabe24b6af7c52..894a12d9f8d28ebec13a1206cb41b51bab7ab747 100644 --- a/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp +++ b/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp @@ -275,9 +275,8 @@ namespace Isis { m_bundleSettings = bundleSettings; m_abort = false; - Progress progress; try { - m_controlNet = ControlNetQsp( new ControlNet(control.fileName(), &progress) ); + m_controlNet = ControlNetQsp( new ControlNet(control.fileName()) ); } catch (IException &e) { throw; @@ -360,7 +359,7 @@ namespace Isis { * @todo answer comments with questions, TODO, ???, and !!! */ void BundleAdjust::init(Progress *progress) { - + emit(statusUpdate("Initialization")); m_previousNumberImagePartials = 0; // initialize @@ -551,8 +550,9 @@ namespace Isis { * printed to stdout. References #4313. */ bool BundleAdjust::validateNetwork() { + outputBundleStatus("\nValidating network..."); - + int imagesWithInsufficientMeasures = 0; QString msg = "Images with one or less measures:\n"; int numObservations = m_bundleObservations.size(); @@ -576,8 +576,8 @@ namespace Isis { throw IException(IException::User, msg, _FILEINFO_); } - outputBundleStatus("Validation complete!..."); - + outputBundleStatus("\nValidation complete!...\n"); + return true; } @@ -710,6 +710,7 @@ namespace Isis { * mode. Fixes #4483. */ bool BundleAdjust::solveCholesky() { + emit(statusBarUpdate("Solving")); try { // throw error if a frame camera is included AND @@ -766,7 +767,7 @@ namespace Isis { for (;;) { - emit iterationUpdate(m_iteration, m_bundleResults.sigma0()); + emit iterationUpdate(m_iteration); // testing if (m_abort) { @@ -803,7 +804,7 @@ namespace Isis { // solve the system if (!solveSystem()) { - printf("solve failed!\n"); + outputBundleStatus("\nsolve failed!"); m_bundleResults.setConverged(false); break; } @@ -855,22 +856,22 @@ namespace Isis { char format = 'f'; int precision = 10; - emit statusUpdate(QString("Iteration: %1") + emit statusUpdate(QString("Iteration: %1 \n") .arg(m_iteration)); - emit statusUpdate(QString("Sigma0: %1") + emit statusUpdate(QString("Sigma0: %1 \n") .arg(m_bundleResults.sigma0(), fieldWidth, format, precision)); - emit statusUpdate(QString("Observations: %1") + emit statusUpdate(QString("Observations: %1 \n") .arg(m_bundleResults.numberObservations())); - emit statusUpdate(QString("Constrained Parameters:%1") + emit statusUpdate(QString("Constrained Parameters:%1 \n") .arg(m_bundleResults.numberConstrainedPointParameters())); - emit statusUpdate(QString("Unknowns: %1") + emit statusUpdate(QString("Unknowns: %1 \n") .arg(m_bundleResults.numberUnknownParameters())); - emit statusUpdate(QString("Degrees of Freedom: %1") + emit statusUpdate(QString("Degrees of Freedom: %1 \n") .arg(m_bundleResults.degreesOfFreedom())); - emit iterationUpdate(m_iteration, m_bundleResults.sigma0()); + emit iterationUpdate(m_iteration); // check for convergence if (m_bundleSettings->convergenceCriteria() == BundleSettings::Sigma0) { @@ -896,6 +897,7 @@ namespace Isis { else { // otherwise iterations are complete m_bundleResults.setConverged(true); emit statusUpdate("Bundle has converged\n"); + emit statusBarUpdate("Converged"); break; } } @@ -914,7 +916,8 @@ namespace Isis { if ( numConvergedParams == numImgParams ) { m_bundleResults.setConverged(true); - emit statusUpdate("Bundle has converged"); + emit statusUpdate("Bundle has converged\n"); + emit statusBarUpdate("Converged"); break; } } @@ -923,14 +926,15 @@ namespace Isis { clock_t iterationStopClock = clock(); double iterationTime = (iterationStopClock - iterationStartClock) / (double)CLOCKS_PER_SEC; - emit statusUpdate( QString("End of Iteration %1").arg(m_iteration) ); - emit statusUpdate( QString("Elapsed Time: %1").arg(iterationTime, + emit statusUpdate( QString("End of Iteration %1 \n").arg(m_iteration) ); + emit statusUpdate( QString("Elapsed Time: %1 \n").arg(iterationTime, fieldWidth, format, precision) ); // check for maximum iterations if (m_iteration >= m_bundleSettings->convergenceCriteriaMaximumIterations()) { + emit(statusBarUpdate("Max Iterations Reached")); break; } @@ -958,9 +962,11 @@ namespace Isis { if (m_bundleResults.converged() && m_bundleSettings->errorPropagation()) { clock_t errorPropStartClock = clock(); - printf("Starting Error Propagation"); + + outputBundleStatus("\nStarting Error Propagation"); + errorPropagation(); - emit statusUpdate("\n\nError Propagation Complete"); + emit statusUpdate("\n\nError Propagation Complete\n"); clock_t errorPropStopClock = clock(); m_bundleResults.setElapsedTimeErrorProp((errorPropStopClock - errorPropStartClock) / (double)CLOCKS_PER_SEC); @@ -978,13 +984,14 @@ namespace Isis { emit resultsReady(bundleSolveInformation()); - emit statusUpdate("\nBundle Complete"); + emit statusUpdate("\nBundle Complete\n"); iterationSummary(); } catch (IException &e) { m_bundleResults.setConverged(false); emit statusUpdate("\n aborting..."); + emit statusBarUpdate("Failed to Converge"); emit finished(); QString msg = "Could not solve bundle adjust."; throw IException(e, e.errorType(), msg, _FILEINFO_); @@ -1025,6 +1032,7 @@ namespace Isis { * @see BundleAdjust::formWeightedNormals */ bool BundleAdjust::formNormalEquations() { + emit(statusBarUpdate("Forming Normal Equations")); bool status = false; m_bundleResults.setNumberObservations(0);// ??? @@ -1067,10 +1075,10 @@ namespace Isis { int pointIndex = 0; int num3DPoints = m_bundleControlPoints.size(); - printf("\n"); - + outputBundleStatus("\n\n"); + for (int i = 0; i < num3DPoints; i++) { - + emit(pointUpdate(i+1)); BundleControlPointQsp point = m_bundleControlPoints.at(i); if (point->isRejected()) { @@ -1652,7 +1660,7 @@ namespace Isis { -1, CHOLMOD_REAL, &m_cholmodCommon); if ( !m_cholmodTriplet ) { - printf("Triplet allocation failure"); + outputBundleStatus("\nTriplet allocation failure\n"); return false; } @@ -1673,7 +1681,9 @@ namespace Isis { SparseBlockColumnMatrix *normalsColumn = m_sparseNormals[columnIndex]; if ( !normalsColumn ) { - printf("SparseBlockColumnMatrix retrieval failure at column %d", columnIndex); + QString status = "\nSparseBlockColumnMatrix retrieval failure at column " + + QString::number(columnIndex); + outputBundleStatus(status); return false; } @@ -1692,9 +1702,15 @@ namespace Isis { LinearAlgebra::Matrix *normalsBlock = it.value(); if ( !normalsBlock ) { - printf("matrix block retrieval failure at column %d, row %d", columnIndex, rowIndex); - printf("Total # of block columns: %d", numBlockcolumns); - printf("Total # of blocks: %d", m_sparseNormals.numberOfBlocks()); + QString status = "\nmatrix block retrieval failure at column "; + status.append(columnIndex); + status.append(", row "); + status.append(rowIndex); + outputBundleStatus(status); + status = "Total # of block columns: " + QString::number(numBlockcolumns); + outputBundleStatus(status); + status = "Total # of blocks: " + QString::number(m_sparseNormals.numberOfBlocks()); + outputBundleStatus(status); return false; } @@ -2127,7 +2143,7 @@ namespace Isis { * apply parameter corrections for solution. */ void BundleAdjust::applyParameterCorrections() { - + emit(statusBarUpdate("Updating Parameters")); int t = 0; // TODO - update target body parameters if in solution @@ -2262,6 +2278,7 @@ namespace Isis { * image sample and line residuals. */ double BundleAdjust::computeResiduals() { + emit(statusBarUpdate("Computing Residuals")); double vtpv = 0.0; double vtpvControl = 0.0; double vtpvImage = 0.0; @@ -2465,17 +2482,26 @@ namespace Isis { medianDev = residuals[midpointIndex]; } - std::cout << "median deviation: " << medianDev << std::endl; - + QString status = "\nmedian deviation: "; + status.append(QString("%1").arg(medianDev)); + status.append("\n"); + outputBundleStatus(status); + mad = 1.4826 * medianDev; - std::cout << "mad: " << mad << "\n"; - + status = "\nmad: "; + status.append(QString("%1").arg(mad)); + status.append("\n"); + outputBundleStatus(status); + m_bundleResults.setRejectionLimit(median + m_bundleSettings->outlierRejectionMultiplier() * mad); - std::cout << "Rejection Limit: " << m_bundleResults.rejectionLimit() << std::endl; - + status = "\nRejection Limit: "; + status.append(QString("%1").arg(m_bundleResults.rejectionLimit())); + status.append("\n"); + outputBundleStatus(status); + return true; } @@ -2502,6 +2528,8 @@ namespace Isis { int numComingBack = 0; int numObjectPoints = m_bundleControlPoints.size(); + + outputBundleStatus("\n"); for (int i = 0; i < numObjectPoints; i++) { BundleControlPointQsp point = m_bundleControlPoints.at(i); @@ -2526,7 +2554,10 @@ namespace Isis { // was it previously rejected? if ( measure->isRejected() ) { - printf("Coming back in: %s\r",point->id().toLatin1().data()); + QString status = "Coming back in: "; + status.append(QString("%1").arg(point->id().toLatin1().data())); + status.append("\r"); + outputBundleStatus(status); numComingBack++; m_controlNet->DecrementNumberOfRejectedMeasuresInImage(measure->cubeSerialNumber()); } @@ -2575,7 +2606,10 @@ namespace Isis { // do we still have sufficient remaining observations for this 3D point? if ( ( numMeasures-numRejected ) < 2 ) { point->setRejected(true); - printf("Rejecting Entire Point: %s\r",point->id().toLatin1().data()); + QString status = "Rejecting Entire Point: "; + status.append(QString("%1").arg(point->id().toLatin1().data())); + status.append("\r"); + outputBundleStatus(status); } else point->setRejected(false); @@ -2584,12 +2618,20 @@ namespace Isis { int numberRejectedObservations = 2*totalNumRejected; - printf("\nRejected Observations:%10d (Rejection Limit:%12.5lf)\n", - numberRejectedObservations, usedRejectionLimit); + QString status = "\nRejected Observations:"; + status.append(QString("%1").arg(numberRejectedObservations)); + status.append(" (Rejection Limit:"); + status.append(QString("%1").arg(usedRejectionLimit)); + status.append(")\n"); + outputBundleStatus(status); + m_bundleResults.setNumberRejectedObservations(numberRejectedObservations); - std::cout << "Measures that came back: " << numComingBack << "\n" << std::endl; - + status = "\nMeasures that came back: "; + status.append(QString("%1").arg(numComingBack)); + status.append("\n"); + outputBundleStatus(status); + return true; } @@ -2645,7 +2687,7 @@ namespace Isis { * Blocking and Filling point covariance messages. References #4463. */ bool BundleAdjust::errorPropagation() { - + emit(statusBarUpdate("Error Propagation")); // free unneeded memory cholmod_free_triplet(&m_cholmodTriplet, &m_cholmodCommon); cholmod_free_sparse(&m_cholmodNormal, &m_cholmodCommon); @@ -2659,8 +2701,12 @@ namespace Isis { int numObjectPoints = m_bundleControlPoints.size(); std::string currentTime = iTime::CurrentLocalTime().toLatin1().data(); - printf(" Time: %s\n\n", currentTime.c_str()); - + + QString status = " Time: "; + status.append(currentTime.c_str()); + status.append("\n\n"); + outputBundleStatus(status); + // create and initialize array of 3x3 matrices for all object points std::vector< symmetric_matrix<double> > pointCovariances(numObjectPoints, symmetric_matrix<double>(3)); @@ -2791,7 +2837,7 @@ namespace Isis { // now loop over all object points to sum contributions into 3x3 point covariance matrix int pointIndex = 0; for (j = 0; j < numObjectPoints; j++) { - + emit(pointUpdate(j+1)); BundleControlPointQsp point = m_bundleControlPoints.at(pointIndex); if ( point->isRejected() ) { continue; @@ -2799,10 +2845,15 @@ namespace Isis { // only update point every 100 points if (j%100 == 0) { - printf("\rError Propagation: Inverse Block %8d of %8d; Point %8d of %8d", i+1, - numBlockColumns, j+1, numObjectPoints); - - emit iterationUpdate(i+1, j+1); + QString status = "\rError Propagation: Inverse Block "; + status.append(QString::number(i+1)); + status.append(" of "); + status.append(QString::number(numBlockColumns)); + status.append("; Point "); + status.append(QString::number(j+1)); + status.append(" of "); + status.append(QString::number(numObjectPoints)); + outputBundleStatus(status); } // get corresponding Q matrix @@ -2858,7 +2909,7 @@ namespace Isis { } catch (std::exception &e) { - printf("\n\n"); + outputBundleStatus("\n\n"); QString msg = "Input data and settings are not sufficiently stable " "for error propagation."; throw IException(IException::User, msg, _FILEINFO_); @@ -2881,10 +2932,14 @@ namespace Isis { // free b (right-hand side vector cholmod_free_dense(&b,&m_cholmodCommon); - printf("\n\n"); + outputBundleStatus("\n\n"); + currentTime = Isis::iTime::CurrentLocalTime().toLatin1().data(); - printf("\rFilling point covariance matrices: Time %s", currentTime.c_str()); - printf("\n\n"); + + status = "\rFilling point covariance matrices: Time "; + status.append(currentTime.c_str()); + outputBundleStatus(status); + outputBundleStatus("\n\n"); // now loop over points again and set final covariance stuff int pointIndex = 0; @@ -2897,8 +2952,12 @@ namespace Isis { } if (j%100 == 0) { - printf("\rError Propagation: Filling point covariance matrices %8d of %8d\r",j+1, - numObjectPoints); + status = "\rError Propagation: Filling point covariance matrices "; + status.append(QString("%1").arg(j+1)); + status.append(" of "); + status.append(QString("%1").arg(numObjectPoints)); + status.append("\r"); + outputBundleStatus(status); } // get corresponding point covariance matrix @@ -3091,6 +3150,16 @@ namespace Isis { } + /** + * Returns if the BundleAdjust has been aborted. + * + * @return @b bool If the BundleAdjust was aborted. + */ + bool BundleAdjust::isAborted() { + return m_abort; + } + + /** * Returns the iteration summary string. * @@ -3113,8 +3182,9 @@ namespace Isis { * -Wformat-security warning during the build. */ void BundleAdjust::outputBundleStatus(QString status) { - status += "\n"; - printf("%s", status.toStdString().c_str()); + if (QCoreApplication::applicationName() != "ipce") { + printf("%s", status.toStdString().c_str()); + } } diff --git a/isis/src/control/objs/BundleAdjust/BundleAdjust.h b/isis/src/control/objs/BundleAdjust/BundleAdjust.h index 428973b9b2a337af237e5ff3eeda156866b7022f..715c62037706d16c201922f8ad8acd567e58d168 100644 --- a/isis/src/control/objs/BundleAdjust/BundleAdjust.h +++ b/isis/src/control/objs/BundleAdjust/BundleAdjust.h @@ -292,6 +292,10 @@ namespace Isis { * constructor in the BundleSolutionInfo class because it is derived * from QObject. Note that we ultimately want to return a QSharedPointer * instead of a raw pointer. + * @history 2018-06-14 Christopher Combs - Added getter method to tell if a bundle adjust was + * aborted. Added emits for status updates to the run widget. + * @history 2018-06-18 Makayla Shepherd - Stopped command line output for ipce BundleAdjust. + * Fixes #4171. */ class BundleAdjust : public QObject { Q_OBJECT @@ -324,6 +328,7 @@ namespace Isis { BundleSolutionInfo* solveCholeskyBR(); QList<ImageList *> imageLists(); + bool isAborted(); public slots: bool solveCholesky(); @@ -345,7 +350,9 @@ namespace Isis { signals: void statusUpdate(QString); void error(QString); - void iterationUpdate(int, double); + void iterationUpdate(int); + void pointUpdate(int); + void statusBarUpdate(QString); void resultsReady(BundleSolutionInfo *bundleSolveInformation); void finished(); diff --git a/isis/src/control/objs/BundleSettings/BundleSettings.cpp b/isis/src/control/objs/BundleSettings/BundleSettings.cpp index b2e9d2ab97f9b97a847b3f8771e00be9cab765ea..305aead1d942e6a2470ae396f1947e3b3c7bdb25 100644 --- a/isis/src/control/objs/BundleSettings/BundleSettings.cpp +++ b/isis/src/control/objs/BundleSettings/BundleSettings.cpp @@ -51,7 +51,7 @@ namespace Isis { m_createInverseMatrix = false; m_outlierRejection = false; - m_outlierRejectionMultiplier = 1.0; + m_outlierRejectionMultiplier = 3.0; // Parameter Uncertainties (Weighting) m_globalLatitudeAprioriSigma = Isis::Null; @@ -271,7 +271,7 @@ namespace Isis { m_outlierRejectionMultiplier = multiplier; } else { - m_outlierRejectionMultiplier = 1.0; + m_outlierRejectionMultiplier = 3.0; } } @@ -435,29 +435,30 @@ namespace Isis { /** - * Retrieves solve settings for the observation corresponding to the given - * observation number. + * Retrieves solve settings for the observation corresponding to the given observation number. + * If no corresponding settings object exists, return a new solve settings with no related + * observation numbers. * * @param observationNumber The observation number associated with the * BundleObservationSolveSettings object to be accessed. * * @return @b BundleObservationSolveSettings The observation settings object that contains * the observation number passed. - * - * @throw IException::Unknown "Unable to find BundleObservationSolveSettings - * for given observation number" */ BundleObservationSolveSettings BundleSettings::observationSolveSettings(QString observationNumber) const { + BundleObservationSolveSettings defaultSolveSettings; + for (int i = 0; i < numberSolveSettings(); i++) { if (m_observationSolveSettings[i].observationNumbers().contains(observationNumber)) { return m_observationSolveSettings[i]; } } - QString msg = "Unable to find BundleObservationSolveSettings for observation number [" - + observationNumber + "]."; - throw IException(IException::Unknown, msg, _FILEINFO_); + return defaultSolveSettings; + //QString msg = "Unable to find BundleObservationSolveSettings for observation number [" + // + observationNumber + "]."; + // throw IException(IException::Unknown, msg, _FILEINFO_); } @@ -484,6 +485,17 @@ namespace Isis { } + /** + * Retrieves solve settings for the observation corresponding to the given index. + * + * @return QList<BundleObservationSolveSettings> The QList of BundleObservationSolveSettings + * objects + */ + QList<BundleObservationSolveSettings> BundleSettings::observationSolveSettings() const { + return m_observationSolveSettings; + } + + // =============================================================================================// // ======================== Convergence Criteria ===============================================// // =============================================================================================// @@ -1154,7 +1166,7 @@ namespace Isis { = toDouble(outlierRejectionMultiplierStr); } else { - m_xmlHandlerBundleSettings->m_outlierRejectionMultiplier = 1.0; + m_xmlHandlerBundleSettings->m_outlierRejectionMultiplier = 3.0; } } } diff --git a/isis/src/control/objs/BundleSettings/BundleSettings.h b/isis/src/control/objs/BundleSettings/BundleSettings.h index 88db2ff4c71f2a978f9e1e8129ae2b717b7345d9..323195bf76aa752b8aaa334d5d2fab6a4d87ec47 100644 --- a/isis/src/control/objs/BundleSettings/BundleSettings.h +++ b/isis/src/control/objs/BundleSettings/BundleSettings.h @@ -106,6 +106,8 @@ namespace Isis { * is for creating and displaying the correlation matrix, which is * currently not working. * 2) commented out hdf5 header includes in cpp + * @history 2018-06-28 Christopher Combs - Added observationSolveSettings() method to retrieve + * m_observationSolveSettings. Fixes #497. * * @todo Determine which XmlStackedHandlerReader constructor is preferred * @todo Determine which XmlStackedHandler needs a Project pointer (see constructors) @@ -175,6 +177,7 @@ namespace Isis { int numberSolveSettings() const; BundleObservationSolveSettings observationSolveSettings(QString instrumentId) const; BundleObservationSolveSettings observationSolveSettings(int n) const; + QList<BundleObservationSolveSettings> observationSolveSettings() const; //=====================================================================// diff --git a/isis/src/control/objs/BundleSettings/BundleSettings.truth b/isis/src/control/objs/BundleSettings/BundleSettings.truth index 853a4c351862bae73b2d739f7dac4dcd08c98de0..1426a8bf77628a193162c58703ec50e93564ee2e 100644 --- a/isis/src/control/objs/BundleSettings/BundleSettings.truth +++ b/isis/src/control/objs/BundleSettings/BundleSettings.truth @@ -434,7 +434,6 @@ Testing XML: Object deserialized as (should match object above): Testing error throws... -**ERROR** Unable to find BundleObservationSolveSettings for observation number [UnassociatedObservationNumber]. **ERROR** Unable to find BundleObservationSolveSettings with index = [32]. **ERROR** Unable to find BundleObservationSolveSettings with index = [-1]. **PROGRAMMER ERROR** Unknown bundle convergence criteria [Pickles]. diff --git a/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp b/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp index b6f9a017bfd27af609c506bcc0efb91ea18fee38..547fa6b5b95e5cbc8c83c998851a6ddea1c3df80 100755 --- a/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp +++ b/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp @@ -129,7 +129,7 @@ int main(int argc, char *argv[]) { bundleControlPointVector.append(fixedBundleControlPoint); Camera *camera = NULL; BundleImage bundleImage(camera, - "TestImageSerialNumber", + "Ignored", "TestImageFileName"); BundleObservationVector observationVector; QObject *parent = NULL; diff --git a/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.cpp b/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.cpp index 6fecb8fd7244297e8232239e1812cc21c702cd2c..7a70a70e63b2d7708b401f699bf6ca30ba91a030 100644 --- a/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.cpp +++ b/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.cpp @@ -259,6 +259,19 @@ namespace Isis { } + /** + * Removes an observation number from this solve settings. The observation is no longer + * associated with this solve settings. + * + * @param QString observationNumber The observation number to remove from this solve settings. + * @return bool Returns true if the observation number passed was actually removed; otherwise + * returns false. + */ + bool BundleObservationSolveSettings::removeObservationNumber(QString observationNumber) { + return m_observationNumbers.remove(observationNumber); + } + + /** * Returns a list of observation numbers associated with these solve settings. * @@ -368,7 +381,7 @@ namespace Isis { bool solvePolynomialOverExisting, double anglesAprioriSigma, double angularVelocityAprioriSigma, - double angularAccelerationAprioriSigma) { + double angularAccelerationAprioriSigma,QList<double> * additionalPointingSigmas) { // automatically set the solve option and ck degree to the user entered values m_instrumentPointingSolveOption = option; @@ -421,6 +434,16 @@ namespace Isis { } } + if (additionalPointingSigmas) { + for (int i=0;i < additionalPointingSigmas->count();i++) { + m_anglesAprioriSigma.append(additionalPointingSigmas->value(i)); + } + } + + + + + m_solveTwist = solveTwist; // dependent on solve option??? // Set the SpiceRotation interpolation type enum appropriately @@ -609,14 +632,14 @@ namespace Isis { * @param velocityAprioriSigma A priori velocity sigma * @param accelerationAprioriSigma A priori acceleration sigma */ - void BundleObservationSolveSettings::setInstrumentPositionSettings( - InstrumentPositionSolveOption option, + void BundleObservationSolveSettings::setInstrumentPositionSettings(InstrumentPositionSolveOption option, int spkDegree, int spkSolveDegree, bool positionOverHermite, double positionAprioriSigma, double velocityAprioriSigma, - double accelerationAprioriSigma) { + double accelerationAprioriSigma, + QList<double> *additionalPositionSigmas) { // automatically set the solve option and spk degree to the user entered values m_instrumentPositionSolveOption = option; @@ -667,6 +690,12 @@ namespace Isis { } } + if (additionalPositionSigmas) { + for (int i=0;i < additionalPositionSigmas->count();i++) { + m_positionAprioriSigma.append(additionalPositionSigmas->value(i)); + } + } + // Set the SpicePosition interpolation type enum appropriately m_solvePositionOverHermiteSpline = positionOverHermite; if (m_solvePositionOverHermiteSpline) { diff --git a/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.h b/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.h index fd570fee7c28eea9e0724afe066b11fb7575e26c..0598712498bea5cbc86bc3f6382738719ec0bbed 100644 --- a/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.h +++ b/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.h @@ -75,7 +75,13 @@ namespace Isis { * with these settings. Removed the setFromPvl() method. When re- * implemented, it should be put in jigsaw. References #4293. * @history 2017-04-24 Ian Humphrey - Removed pvlObject(). Fixes #4797. - * + * @history 2018-06-21 Ian Humphrey - Added removeObservationNumber() to be able to remove an + * observation number from a BundleObservationSolveSettings. + * References #497. + * @history 2018-06-26 Tyler Wilson - Added support for adding an arbitrary number of + * additional apriori sigma values in setInstrumentPositionSettings/ + * setInstrumentPointingSettings beyond position/velocity/acceleration. + * References #497. * * @todo Figure out why solve degree and num coefficients does not match solve option. * @todo Determine whether xml stuff needs a Project pointer. @@ -99,6 +105,7 @@ class BundleObservationSolveSettings { void setInstrumentId(QString instrumentId); QString instrumentId() const; void addObservationNumber(QString observationNumber); + bool removeObservationNumber(QString observationNumber); QSet<QString> observationNumbers() const; @@ -124,7 +131,8 @@ class BundleObservationSolveSettings { bool solvePolynomialOverExisting = false, double anglesAprioriSigma = -1.0, double angularVelocityAprioriSigma = -1.0, - double angularAccelerationAprioriSigma = -1.0); + double angularAccelerationAprioriSigma = -1.0, + QList<double> * additionalPointingSigmas=nullptr); InstrumentPointingSolveOption instrumentPointingSolveOption() const; bool solveTwist() const; int ckDegree() const; @@ -155,7 +163,8 @@ class BundleObservationSolveSettings { bool positionOverHermite = false, double positionAprioriSigma = -1.0, double velocityAprioriSigma = -1.0, - double accelerationAprioriSigma = -1.0); + double accelerationAprioriSigma = -1.0, + QList<double> * additionalPositionSigmas=nullptr); InstrumentPositionSolveOption instrumentPositionSolveOption() const; int spkDegree() const; int spkSolveDegree() const; diff --git a/isis/src/control/objs/ControlCubeGraphNode/ControlCubeGraphNode.cpp b/isis/src/control/objs/ControlCubeGraphNode/ControlCubeGraphNode.cpp deleted file mode 100644 index 2c9915c81b9f2d8ffb6f2ef8a8d18e6df346c9e0..0000000000000000000000000000000000000000 --- a/isis/src/control/objs/ControlCubeGraphNode/ControlCubeGraphNode.cpp +++ /dev/null @@ -1,269 +0,0 @@ -#include "IsisDebug.h" - -#include "ControlCubeGraphNode.h" - -#include <iostream> - -#include <QHash> -#include <QString> - -#include "ControlMeasure.h" -#include "ControlPoint.h" -#include "IException.h" -#include "IString.h" - - -namespace Isis { - /** - * Create an empty SerialNumber object. - */ - ControlCubeGraphNode::ControlCubeGraphNode(QString sn) { - nullify(); - - serialNumber = new QString(sn); - measures = new QHash<ControlPoint *, ControlMeasure *>; - connections = new QHash < ControlCubeGraphNode *, QList< ControlPoint * > >; - } - - - ControlCubeGraphNode::ControlCubeGraphNode(const ControlCubeGraphNode &other) { - nullify(); - - serialNumber = new QString(*other.serialNumber); - measures = new QHash<ControlPoint *, ControlMeasure *>; - connections = new QHash < ControlCubeGraphNode *, QList< ControlPoint * > >; - - *measures = *other.measures; - } - - - void ControlCubeGraphNode::nullify() { - serialNumber = NULL; - measures = NULL; - connections = NULL; - } - - - /** - * Destroy a SerialNumber object. - */ - ControlCubeGraphNode::~ControlCubeGraphNode() { - if (serialNumber) { - delete serialNumber; - serialNumber = NULL; - } - - if (measures) { - delete measures; - measures = NULL; - } - - if (connections) { - delete connections; - connections = NULL; - } - } - - - /** - * @param point The ControlPoint to check for - * - * @returns true if the point is contained, false otherwise - */ - bool ControlCubeGraphNode::contains(ControlPoint *point) const { - return measures->contains(point); - } - - - /** - * Adds a measure - * - * @param measure The ControlMeasure to add - */ - void ControlCubeGraphNode::addMeasure(ControlMeasure *measure) { - ASSERT(measure); - - if (measure->GetCubeSerialNumber() != *serialNumber) { - QString msg = "Attempted to add Control Measure with Cube Serial Number "; - msg += "[" + measure->GetCubeSerialNumber() + "] does not match Serial "; - msg += "Number [" + *serialNumber + "]"; - throw IException(IException::User, msg, _FILEINFO_); - } - - measure->associatedCSN = this; - ASSERT(!measures->contains(measure->Parent())); - (*measures)[measure->Parent()] = measure; - } - - - void ControlCubeGraphNode::removeMeasure(ControlMeasure *measure) { - - if (measures->remove(measure->Parent()) != 1) { - ASSERT(0); - } - - measure->associatedCSN = NULL; - } - - - void ControlCubeGraphNode::addConnection(ControlCubeGraphNode *node, - ControlPoint *point) { - ASSERT(node); - ASSERT(point); - - if (connections->contains(node)) { - if (!(*connections)[node].contains(point)) - (*connections)[node].append(point); - } - else { - QList< ControlPoint * > newConnectionList; - newConnectionList.append(point); - (*connections)[node] = newConnectionList; - } - } - - - void ControlCubeGraphNode::removeConnection(ControlCubeGraphNode *node, - ControlPoint *point) { - ASSERT(node); - ASSERT(point); - ASSERT(connections); - - if (connections->contains(node)) { - if ((*connections)[node].contains(point)) { - (*connections)[node].removeOne(point); - if (!(*connections)[node].size()) - connections->remove(node); - } - } - } - - - int ControlCubeGraphNode::getMeasureCount() const { - return measures->size(); - } - - - QString ControlCubeGraphNode::getSerialNumber() const { - return *serialNumber; - } - - - QList< ControlMeasure * > ControlCubeGraphNode::getMeasures() const { - return measures->values(); - } - - - QList< ControlMeasure * > ControlCubeGraphNode::getValidMeasures() const { - QList< ControlMeasure * > validMeasures; - - QList< ControlMeasure * > measureList = measures->values(); - foreach(ControlMeasure * measure, measureList) { - if (!measure->IsIgnored()) - validMeasures.append(measure); - } - - return validMeasures; - } - - - QList< ControlCubeGraphNode * > ControlCubeGraphNode::getAdjacentNodes() const { - return connections->keys(); - } - - - bool ControlCubeGraphNode::isConnected(ControlCubeGraphNode *other) const { - return connections->contains(other); - } - - - ControlMeasure *ControlCubeGraphNode::getMeasure(ControlPoint *point) { - if (!measures->contains(point)) { - QString msg = "point ["; - msg += (QString) point->GetId(); - msg += "] not found in the ControlCubeGraphNode"; - throw IException(IException::Programmer, msg, _FILEINFO_); - } - - return (*measures)[point]; - } - - - const ControlMeasure *ControlCubeGraphNode::getMeasure( - ControlPoint *point) const { - if (!measures->contains(point)) { - QString msg = "point ["; - msg += (QString) point->GetId(); - msg += "] not found in the ControlCubeGraphNode"; - throw IException(IException::Programmer, msg, _FILEINFO_); - } - - return measures->value(point); - } - - - ControlMeasure *ControlCubeGraphNode::operator[](ControlPoint *point) { - return getMeasure(point); - } - - - const ControlMeasure *ControlCubeGraphNode::operator[]( - ControlPoint *point) const { - return getMeasure(point); - } - - - const ControlCubeGraphNode &ControlCubeGraphNode::operator=( - ControlCubeGraphNode other) { - if (this == &other) - return *this; - - if (serialNumber) { - delete serialNumber; - serialNumber = NULL; - } - - if (measures) { - delete measures; - measures = NULL; - } - - if (connections) { - delete connections; - connections = NULL; - } - - serialNumber = new QString; - measures = new QHash< ControlPoint *, ControlMeasure *>; - connections = new QHash< ControlCubeGraphNode *, QList< ControlPoint * > >; - - *serialNumber = *other.serialNumber; - *measures = *other.measures; - *connections = *other.connections; - - return *this; - } - - - QString ControlCubeGraphNode::connectionsToString() const { - QHashIterator< ControlCubeGraphNode *, QList< ControlPoint * > > i( - *connections); - - QStringList serials; - while (i.hasNext()) { - i.next(); - QString line = " " + (QString) i.key()->getSerialNumber(); - line += " : "; - for (int j = 0; j < i.value().size(); j++) { - line += (QString) i.value()[j]->GetId(); - if (j != i.value().size() - 1) - line += ", "; - } - serials << line; - } - qSort(serials); - - return serials.join("\n"); - } - -} diff --git a/isis/src/control/objs/ControlCubeGraphNode/ControlCubeGraphNode.h b/isis/src/control/objs/ControlCubeGraphNode/ControlCubeGraphNode.h deleted file mode 100644 index 0a8d349696219da91c9889757d7176411bd5d346..0000000000000000000000000000000000000000 --- a/isis/src/control/objs/ControlCubeGraphNode/ControlCubeGraphNode.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef ControlCubeGraphNode_h -#define ControlCubeGraphNode_h - -/** - * @file - * $Revision: 1.8 $ - * $Date: 2008/06/18 18:54:11 $ - * - * Unless noted otherwise, the portions of Isis written by the USGS are public - * domain. See individual third-party library and package descriptions for - * intellectual property information,user agreements, and related information. - * - * Although Isis has been used by the USGS, no warranty, expressed or implied, - * is made by the USGS as to the accuracy and functioning of such software - * and related material nor shall the fact of distribution constitute any such - * warranty, and no responsibility is assumed by the USGS in connection - * therewith. - * - * For additional information, launch - * $ISISROOT/doc//documents/Disclaimers/Disclaimers.html in a browser or see - * the Privacy & Disclaimers page on the Isis website, - * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on - * http://www.usgs.gov/privacy.html. - */ - -#include <QObject> - -template< typename A, typename B > class QHash; -template< typename T > class QList; - -class QString; - -namespace Isis { - class ControlMeasure; - class ControlPoint; - - /** - * @brief Serial Number with added functionality for Control Networks - * - * This class is extends the Serial Number class in order to directly point - * between its associated measures in a Control Network and back. - * - * @ingroup ControlNetwork - * - * @author 2011-01-14 Travis Addair and Christopher Austin - * - * @see ControlPoint ControlMeasure - * - * @internal - * @history 2011-01-14 Travis Addair and Christopher Austin - original - * version - * @history 2011-02-18 Eric Hyer - This class now also acts as a vertex - * class for a graph where edges are the connections between - * images. This means that connections are stored to other - * ControlCubeGraphNode objects who have measures which have - * the same parent (point) as measures here. - * @history 2011-02-22 Eric Hyer - Added isConnected() and - * getAdjacentNodes methods - * @history 2011-03-15 Eric Hyer - Connections handled more simply - fixed - * connection related bugs - * @history 2011-06-22 James Alexander Crough and Eric Hyer- Added - * getValidMeasures method. - * @history 2011-07-29 Jai Rideout, Steven Lambright, and Eric Hyer - Made - * this inherit from QObject to get destroyed() - * signal - */ - class ControlCubeGraphNode : public QObject { - - Q_OBJECT - - public: - explicit ControlCubeGraphNode(QString sn); - ControlCubeGraphNode(const ControlCubeGraphNode &other); - virtual ~ControlCubeGraphNode(); - - void addMeasure(ControlMeasure *measure); - void removeMeasure(ControlMeasure *measure); - void addConnection(ControlCubeGraphNode *, ControlPoint *); - void removeConnection(ControlCubeGraphNode *, ControlPoint *); - - bool contains(ControlPoint *point) const; - QString getSerialNumber() const; - int getMeasureCount() const; - QList< ControlMeasure * > getMeasures() const; - QList< ControlMeasure * > getValidMeasures() const; - QList< ControlCubeGraphNode * > getAdjacentNodes() const; - bool isConnected(ControlCubeGraphNode *other) const; - - ControlMeasure *getMeasure(ControlPoint *point); - const ControlMeasure *getMeasure(ControlPoint *point) const; - ControlMeasure *operator[](ControlPoint *point); - const ControlMeasure *operator[](ControlPoint *point) const; - - const ControlCubeGraphNode &operator=(ControlCubeGraphNode); - - QString connectionsToString() const; - - - private: - void nullify(); - - - private: - QString *serialNumber; - - //! ControlMeasures hashed by ControlPoint - QHash< ControlPoint *, ControlMeasure * > * measures; - - /** - * Stores a list of ControlPoints which establish a conection to the - * ControlCubeGraphNode that the list is hashed by - */ - QHash< ControlCubeGraphNode *, QList< ControlPoint * > > * connections; - - }; -} - -#endif diff --git a/isis/src/control/objs/ControlCubeGraphNode/ControlCubeGraphNode.truth b/isis/src/control/objs/ControlCubeGraphNode/ControlCubeGraphNode.truth deleted file mode 100644 index 6c39428d06e80bf27e9e9a88ab81d100c0534612..0000000000000000000000000000000000000000 --- a/isis/src/control/objs/ControlCubeGraphNode/ControlCubeGraphNode.truth +++ /dev/null @@ -1,26 +0,0 @@ -Test adding first measure ... -Key = Point1 -Value = measure with cube serial number Image1 -Successfully added measure - -Test adding second measure ... -Key = Point1 -Value = measure with cube serial number Image2 -**USER ERROR** Attempted to add Control Measure with Cube Serial Number [Image2] does not match Serial Number [Image1]. - -Test adding third measure ... -Key = Point2 -Value = measure with cube serial number Image1 -Successfully added measure - -Test adding fourth measure ... -Key = Point2 -Value = measure with cube serial number Image2 -**USER ERROR** Attempted to add Control Measure with Cube Serial Number [Image2] does not match Serial Number [Image1]. - -Testing getMeasures method... - (Image1) - (Image1) - -Testing getValidMeasures method... - (Image1) diff --git a/isis/src/control/objs/ControlCubeGraphNode/unitTest.cpp b/isis/src/control/objs/ControlCubeGraphNode/unitTest.cpp deleted file mode 100644 index aec5a5baef32527113c8c7d9023e67bc4a09f978..0000000000000000000000000000000000000000 --- a/isis/src/control/objs/ControlCubeGraphNode/unitTest.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include <iostream> -#include <float.h> - -#include <QList> -#include <QString> -#include <QStringList> - -#include "ControlMeasure.h" -#include "ControlPoint.h" -#include "ControlCubeGraphNode.h" - -#include "ControlMeasureLogData.h" -#include "IException.h" -#include "Preference.h" - -using namespace std; -using namespace Isis; - - -int main() { - Preference::Preferences(true); - - ControlCubeGraphNode graphNode("Image1"); - - ControlPoint point1("Point1"); - - ControlMeasure *measure1 = new ControlMeasure(); - measure1->SetCubeSerialNumber("Image1"); - measure1->SetCoordinate(1,2); - ControlMeasure *measure2 = new ControlMeasure(); - measure2->SetCubeSerialNumber("Image2"); - - point1.Add(measure1); - point1.Add(measure2); - - cout << "Test adding first measure ..." << endl; - cout << "Key = " << measure1->GetPointId().toStdString() << endl; - cout << "Value = measure with cube serial number " << - measure1->GetCubeSerialNumber() << endl; - try { - graphNode.addMeasure(measure1); - cout << "Successfully added measure" << endl; - } - catch (IException &e) { - e.print(); - } - cout << endl; - - cout << "Test adding second measure ..." << endl; - cout << "Key = " << measure2->GetPointId().toStdString() << endl; - cout << "Value = measure with cube serial number " << - measure2->GetCubeSerialNumber() << endl; - try { - graphNode.addMeasure(measure2); - cout << "Successfully added measure" << endl; - } - catch (IException &e) { - e.print(); - } - cout << endl; - - ControlPoint point2("Point2"); - - ControlMeasure *measure3 = new ControlMeasure(); - measure3->SetCubeSerialNumber("Image1"); - measure3->SetCoordinate(3,4); - ControlMeasure *measure4 = new ControlMeasure(); - measure4->SetCubeSerialNumber("Image2"); - - point2.Add(measure3); - point2.Add(measure4); - - cout << "Test adding third measure ..." << endl; - cout << "Key = " << measure3->GetPointId().toStdString() << endl; - cout << "Value = measure with cube serial number " << - measure3->GetCubeSerialNumber() << endl; - try { - graphNode.addMeasure(measure3); - cout << "Successfully added measure" << endl; - } - catch (IException &e) { - e.print(); - } - cout << endl; - - cout << "Test adding fourth measure ..." << endl; - cout << "Key = " << measure4->GetPointId().toStdString() << endl; - cout << "Value = measure with cube serial number " << - measure4->GetCubeSerialNumber() << endl; - try { - graphNode.addMeasure(measure4); - cout << "Successfully added measure" << endl; - } - catch (IException &e) { - e.print(); - } - cout << endl; - - cout << "Testing getMeasures method...\n"; - QList< ControlMeasure * > measures = graphNode.getMeasures(); - foreach (ControlMeasure * measure, measures) { - cout << " (" << measure->GetCubeSerialNumber() << ")\n"; - } - - cout << "\nTesting getValidMeasures method...\n"; - measures[0]->SetIgnored(true); - measures = graphNode.getValidMeasures(); - foreach (ControlMeasure * measure, measures) { - cout << " (" << measure->GetCubeSerialNumber() << ")\n"; - } - - return 0; -} - diff --git a/isis/src/control/objs/ControlMeasure/ControlMeasure.cpp b/isis/src/control/objs/ControlMeasure/ControlMeasure.cpp index 6b87dcdc9e1c3956c76208cc763e02d4a4cd53f8..aac404555bede0537ac0872579a088f294342f0f 100644 --- a/isis/src/control/objs/ControlMeasure/ControlMeasure.cpp +++ b/isis/src/control/objs/ControlMeasure/ControlMeasure.cpp @@ -30,7 +30,6 @@ #include "ControlMeasureLogData.h" #include "ControlNet.h" #include "ControlPoint.h" -#include "ControlCubeGraphNode.h" #include "IString.h" #include "iTime.h" #include "SpecialPixel.h" @@ -84,13 +83,11 @@ namespace Isis { p_sampleResidual = other.p_sampleResidual; p_lineResidual = other.p_lineResidual; p_camera = other.p_camera; - associatedCSN = other.associatedCSN; } //! initialize pointers and other data to NULL void ControlMeasure::InitializeToNull() { - // Previously these were initialized to 0.0 in the constructor. p_sample = Null; p_line = Null; @@ -117,7 +114,6 @@ namespace Isis { p_measuredEphemerisTime = Null; parentPoint = NULL; - associatedCSN = NULL; } @@ -145,7 +141,6 @@ namespace Isis { p_loggedData = NULL; } - associatedCSN = NULL; } @@ -153,6 +148,7 @@ namespace Isis { if (IsEditLocked()) return MeasureLocked; MeasureModified(); + p_aprioriLine = aprioriLine; return Success; } @@ -163,6 +159,7 @@ namespace Isis { if (IsEditLocked()) return MeasureLocked; MeasureModified(); + p_aprioriSample = aprioriSample; return Success; } @@ -250,8 +247,10 @@ namespace Isis { if (IsEditLocked()) return MeasureLocked; MeasureModified(); + p_sample = sample; p_line = line; + SetType(type); return Success; } @@ -365,9 +364,14 @@ namespace Isis { if (IsEditLocked()) return MeasureLocked; + bool oldStatus = p_ignore; p_ignore = newIgnoreStatus; + if (Parent()) { + Parent()->emitMeasureModified(this, IgnoredModified, oldStatus, p_ignore); + } + // only update if there was a change in status if (oldStatus != p_ignore) { MeasureModified(); @@ -378,6 +382,7 @@ namespace Isis { } } + return Success; } @@ -406,8 +411,9 @@ namespace Isis { */ ControlMeasure::Status ControlMeasure::SetResidual(double sampResidual, double lineResidual) { - + MeasureModified(); + p_sampleResidual = sampResidual; p_lineResidual = lineResidual; return Success; @@ -428,6 +434,7 @@ namespace Isis { if (IsEditLocked()) return MeasureLocked; MeasureModified(); + p_measureType = type; return Success; } @@ -1030,32 +1037,31 @@ namespace Isis { p_dateTime = new QString; p_loggedData = new QVector<ControlMeasureLogData>(); - *p_serialNumber = *other.p_serialNumber; - *p_chooserName = *other.p_chooserName; - *p_dateTime = *other.p_dateTime; + bool oldLock = p_editLock; + p_editLock = false; + + p_sample = other.p_sample; + p_line = other.p_line; *p_loggedData = *other.p_loggedData; - p_measureType = other.p_measureType; + SetCubeSerialNumber(*other.p_serialNumber); + SetChooserName(*other.p_chooserName); + SetDateTime(*other.p_dateTime); + SetType(other.p_measureType); // Call SetIgnored to update the ControlGraphNode. However, SetIgnored // will return if EditLock is true, so set to false temporarily. - p_editLock = false; SetIgnored(other.p_ignore); - p_editLock = other.p_editLock; - p_sample = other.p_sample; - p_line = other.p_line; - p_diameter = other.p_diameter; - p_aprioriSample = other.p_aprioriSample; - p_aprioriLine = other.p_aprioriLine; - p_sampleSigma = other.p_sampleSigma; - p_lineSigma = other.p_lineSigma; - p_sampleResidual = other.p_sampleResidual; - p_lineResidual = other.p_lineResidual; - p_camera = other.p_camera; - p_focalPlaneMeasuredX = other.p_focalPlaneMeasuredX; - p_focalPlaneMeasuredY = other.p_focalPlaneMeasuredY; - p_focalPlaneComputedX = other.p_focalPlaneComputedX; - p_focalPlaneComputedY = other.p_focalPlaneComputedY; - associatedCSN = other.associatedCSN; + SetDiameter(other.p_diameter); + SetAprioriSample(other.p_aprioriSample); + SetAprioriLine(other.p_aprioriLine); + SetSampleSigma(other.p_sampleSigma); + SetLineSigma(other.p_lineSigma); + SetResidual(other.p_sampleResidual, other.p_lineResidual); + SetCamera(other.p_camera); + SetFocalPlaneMeasured(other.p_focalPlaneMeasuredX, other.p_focalPlaneMeasuredY); + SetFocalPlaneComputed(other.p_focalPlaneComputedX, other.p_focalPlaneComputedY); + p_editLock = oldLock; + SetEditLock(other.p_editLock); return *this; } diff --git a/isis/src/control/objs/ControlMeasure/ControlMeasure.h b/isis/src/control/objs/ControlMeasure/ControlMeasure.h index 60959b396f1249d605d2e3844cbb4910d723315d..6c6b26a324685f6b1f276350acdb331c97c3304e 100644 --- a/isis/src/control/objs/ControlMeasure/ControlMeasure.h +++ b/isis/src/control/objs/ControlMeasure/ControlMeasure.h @@ -36,7 +36,6 @@ namespace Isis { class Camera; class ControlMeasureLogData; class ControlPoint; - class ControlCubeGraphNode; class PvlGroup; class PvlKeyword; @@ -175,13 +174,23 @@ namespace Isis { * @history 2018-01-05 Adam Goins - Added HasDateTime() and HasChooserName() methods to allow * to allow the value of these variables to be read without being * overriden if they're empty. (Getters override if they're empty). + * @history 2018-01-26 Kristin Berry - Removed code related to now-unused ControlCubeGraphNode, + * as part of the switch to using the boost graph library. + * References #5434 + * @history 2018-06-15 Adam Goins & Jesse Mapel - Added the ModType enum, as well as a series + * of calls to parentNetwork()->emitPointModified() whenever a change + * is made to a Control Point or any of it's measures. This is done + * to allow for communication between the ControlNetVitals class + * and changes made to the Control Network that it is observing. + * Fixes #5435. + * @history 2018-06-29 Adam Goins - Modified operator= to use setters when setting values + * so that the proper signals/slots are called. Fixes #5435. */ class ControlMeasure : public QObject { Q_OBJECT friend class ControlPoint; - friend class ControlCubeGraphNode; public: /** * @brief Control network measurement types @@ -224,6 +233,20 @@ namespace Isis { MeasureLocked }; + + /** + * @brief Control Measure Modification Types + * + * This enum is designed to represent the different types of modifications that can be + * made to a ControlMeasure. + * + * IgnoredModified means that the Control Measure had it's IGNORED flag changed. + * + */ + enum ModType { + IgnoredModified + }; + enum DataField { AprioriLine = 1, AprioriSample = 2, @@ -249,7 +272,6 @@ namespace Isis { ~ControlMeasure(); ControlPoint *Parent() { return parentPoint; } - ControlCubeGraphNode *ControlSN() { return associatedCSN; } Status SetAprioriLine(double aprioriLine); Status SetAprioriSample(double aprioriSample); @@ -333,7 +355,6 @@ namespace Isis { private: // data ControlPoint *parentPoint; //!< Pointer to parent ControlPoint, may be null - ControlCubeGraphNode *associatedCSN; //!< Pointer to the Serial Number // structure connecting measures in an image QString *p_serialNumber; diff --git a/isis/src/control/objs/ControlNet/ControlNet.cpp b/isis/src/control/objs/ControlNet/ControlNet.cpp index 9c3a06ebe3c344225ac88ac12f089b671b6e3587..f3988cfde4ea86caaa4af1908af1558d88de142b 100644 --- a/isis/src/control/objs/ControlNet/ControlNet.cpp +++ b/isis/src/control/objs/ControlNet/ControlNet.cpp @@ -6,15 +6,15 @@ #include <cmath> #include <sstream> -#include <QtAlgorithms> #include <QDebug> #include <QMutex> #include <QMutexLocker> #include <QPair> -#include <QQueue> #include <QScopedPointer> #include <QSet> +#include <QStringList> #include <QTime> +#include <QVariant> #include <QVector> #include <boost/numeric/ublas/symmetric.hpp> @@ -25,7 +25,6 @@ #include "ControlMeasure.h" #include "ControlNetVersioner.h" #include "ControlPoint.h" -#include "ControlCubeGraphNode.h" #include "Distance.h" #include "FileName.h" #include "IException.h" @@ -45,18 +44,16 @@ namespace Isis { void ControlNet::nullify() { points = NULL; - cubeGraphNodes = NULL; pointIds = NULL; m_mutex = NULL; } - //!Creates an empty ControlNet object + //! Creates an empty ControlNet object ControlNet::ControlNet() { nullify(); points = new QHash< QString, ControlPoint * >; - cubeGraphNodes = new QHash< QString, ControlCubeGraphNode * >; pointIds = new QStringList; m_ownPoints = true; @@ -70,7 +67,6 @@ namespace Isis { nullify(); points = new QHash< QString, ControlPoint * >; - cubeGraphNodes = new QHash< QString, ControlCubeGraphNode * >; pointIds = new QStringList; for (int cpIndex = 0; cpIndex < other.GetNumPoints(); cpIndex++) { @@ -103,7 +99,6 @@ namespace Isis { nullify(); points = new QHash< QString, ControlPoint * >; - cubeGraphNodes = new QHash< QString, ControlCubeGraphNode * >; pointIds = new QStringList; m_ownPoints = true; @@ -128,13 +123,40 @@ namespace Isis { clear(); delete points; - delete cubeGraphNodes; delete pointIds; nullify(); } + /** + * This method is a wrapper to emit the measureModified() signal and is called whenever a change + * is made to a Control Measure. + * + * @param measure The ControlMeasure* that was modified. + * @param type The ControlMeasure::ModType indicating which modification occured. + * @param oldValue The oldValue before the change. + * @param newValue The new value that the change incorporated. + */ + void ControlNet::emitMeasureModified(ControlMeasure *measure, ControlMeasure::ModType type, QVariant oldValue, QVariant newValue) { + emit measureModified(measure, type, oldValue, newValue); + } + + + /** + * This method is a wrapper to emit the pointModified() signal and is called whenever a change + * is made to a Control Point. + * + * @param point The ControlPoint* that was modified. + * @param type The ControlPoint::ModType indicating which modification occured. + * @param oldValue The oldValue before the change. + * @param newValue The new value that the change incorporated. + */ + void ControlNet::emitPointModified(ControlPoint *point, ControlPoint::ModType type, QVariant oldValue, QVariant newValue) { + emit pointModified(point, type, oldValue, newValue); + } + + /** * @brief Clear the contents of this object * @@ -160,15 +182,8 @@ namespace Isis { points->clear(); } - if (cubeGraphNodes) { - QHashIterator< QString, ControlCubeGraphNode * > i(*cubeGraphNodes); - while (i.hasNext()) { - i.next(); - delete(*cubeGraphNodes)[i.key()]; - (*cubeGraphNodes)[i.key()] = NULL; - } - cubeGraphNodes->clear(); - } + m_vertexMap.clear(); + m_controlGraph.clear(); if (pointIds) { pointIds->clear(); @@ -358,15 +373,15 @@ namespace Isis { /** * Adds a whole point to the control net graph. * - * @throws IException::Programmer "NULL measure passed to ControlNet::AddControlCubeGraphNode!" + * @throws IException::Programmer "NULL measure passed to ControlNet::pointAdded!" * @throws IException::Programmer "Control measure with NULL parent passed to - * ControlNet::AddControlCubeGraphNode!" + * ControlNet::pointAdded" * @throws IException::Programmer "ControlNet does not contain the point." */ void ControlNet::pointAdded(ControlPoint *point) { if (!point) { IString msg = "NULL point passed to " - "ControlNet::AddControlCubeGraphNode!"; + "ControlNet::pointAdded!"; throw IException(IException::Programmer, msg, _FILEINFO_); } @@ -376,64 +391,201 @@ namespace Isis { throw IException(IException::Programmer, msg, _FILEINFO_); } - // make sure there is a node for every measure + // Make sure there is a node for every measure for (int i = 0; i < point->GetNumMeasures(); i++) { QString sn = point->GetMeasure(i)->GetCubeSerialNumber(); - if (!cubeGraphNodes->contains(sn)) { - cubeGraphNodes->insert(sn, new ControlCubeGraphNode(sn)); + + // If the graph doesn't have the sn, add a node for it + if (!m_vertexMap.contains(sn)) { + Image newImage; + newImage.serial = sn; + ImageVertex newVertex = boost::add_vertex(newImage, m_controlGraph); + m_vertexMap.insert(sn, newVertex); + emit networkModified(GraphModified); } } - foreach(ControlMeasure* measure, point->getMeasures()) { - // add the measure to the corresponding node + QList< ControlMeasure * > measures = point->getMeasures(); + for(int i = 0; i < measures.size(); i++) { + ControlMeasure* measure = measures[i]; + // Add the measure to the corresponding node QString serial = measure->GetCubeSerialNumber(); - ControlCubeGraphNode *node = (*cubeGraphNodes)[serial]; - node->addMeasure(measure); + m_controlGraph[m_vertexMap[serial]].measures[measure->Parent()] = measure; - // in this measure's node add connections to the other nodes reachable from + // In this measure's node add connections to the other nodes reachable from // its point if (!point->IsIgnored() && !measure->IsIgnored()) { - for (int i = 0; i < point->GetNumMeasures(); i++) { - ControlMeasure *cm = point->GetMeasure(i); + for (int j = i + 1; j < measures.size(); j++) { + ControlMeasure *cm = measures[j]; if (!cm->IsIgnored()) { QString sn = cm->GetCubeSerialNumber(); - ControlCubeGraphNode *neighborNode = (*cubeGraphNodes)[sn]; - - if (neighborNode != node) { - node->addConnection(neighborNode, point); - neighborNode->addConnection(node, point); - } + addEdge(serial, sn); } } } } + emit newPoint(point); + } + + + /** + * In the ControlNet graph: adds an edge between the verticies associated with the two serial + * numbers provided. Or, if the edge already exists, increments the strength of the edge. + * + * @param sourceSerial The first serial to be connected by the edge + * @param targetSerial The second serial number to be connected by the edge + * + * @return bool true if a new edge was added, false otherwise. + */ + bool ControlNet::addEdge(QString sourceSerial, QString targetSerial) { + // If the edge doesn't already exist, this adds and returns the edge. + // If the edge already exists, this just returns it. (The use of a set + // forces the edges to be unique.) + ImageConnection connection; + bool edgeAdded; + + boost::tie(connection, edgeAdded) = boost::add_edge(m_vertexMap[sourceSerial], + m_vertexMap[targetSerial], + m_controlGraph); + m_controlGraph[connection].strength++; + if (edgeAdded) { + emit networkModified(GraphModified); + } + return edgeAdded; + } + + + /** + * In the ControlNet graph, decrements the strength on the edge between the two serial numbers. + * This is called when the ControlMeasures that connect these images are deleted or ignored. + * If it is the last measure connecting two verticies (serial numbers) the edge is removed. + * + * @param sourceSerial The first serial number defining the end of the edge to have its strength + * decremented or be removed. + * @param targetSerial The second serial number defining the other end of the edge to have its + * strength decremented or be removed. + * @return bool true if the edge is removed, otherwise false + */ + bool ControlNet::removeEdge(QString sourceSerial, QString targetSerial) { + ImageConnection connection; + bool edgeExists; + boost::tie(connection, edgeExists) = boost::edge(m_vertexMap[sourceSerial], + m_vertexMap[targetSerial], + m_controlGraph); + if (edgeExists) { + m_controlGraph[connection].strength--; + if (m_controlGraph[connection].strength <= 0) { + boost::remove_edge(m_vertexMap[sourceSerial], + m_vertexMap[targetSerial], + m_controlGraph); + emit networkModified(GraphModified); + + return true; + } + } + return false; } /** - * Updates the ControlCubeGraphNode for the measure's serial number to - * reflect the addition. If there is currently no ControlCubeGraphNode for - * this measure's serial, then a new ControlCubeGraphNode is created with + * Used for verifying graph intergrity + * + * @returns A string representation of the ControlNet graph + */ + QString ControlNet::GraphToString() const { + QString graphString; + + QStringList images = GetCubeSerials(); + images.sort(); + + QHash<QString, QStringList> imagePointIds; + + foreach(QString imageSerial, images) { + QList<ControlPoint *> imagePoints = m_controlGraph[m_vertexMap[imageSerial]].measures.keys(); + QStringList pointIds; + foreach(ControlPoint *point, imagePoints) { + if (!point->IsIgnored()) { + pointIds.append(point->GetId()); + } + } + pointIds.sort(); + imagePointIds.insert(imageSerial, pointIds); + } + + foreach(QString imageSerial, images) { + QStringList adjacentImages = getAdjacentImages(imageSerial); + adjacentImages.sort(); + foreach(QString adjacentSerial, adjacentImages) { + if (QString::compare(adjacentSerial, imageSerial) < 0) { + continue; + } + + QStringList commonPoints; + QList<QString>::const_iterator imageIt = imagePointIds[imageSerial].cbegin(); + QList<QString>::const_iterator adjacentIt = imagePointIds[adjacentSerial].cbegin(); + while (imageIt != imagePointIds[imageSerial].cend() && + adjacentIt != imagePointIds[adjacentSerial].cend()) { + int stringDiff = QString::compare(*imageIt, *adjacentIt); + if (stringDiff < 0) { + imageIt++; + } + else if(stringDiff == 0) { + commonPoints.append(*imageIt); + imageIt++; + adjacentIt++; + } + else { + adjacentIt++; + } + } + + std::pair<ImageConnection, bool> result = boost::edge(m_vertexMap[imageSerial], + m_vertexMap[adjacentSerial], + m_controlGraph); + QString edgeStrength = "UNKNOWN"; + if (result.second) { + edgeStrength = toString(m_controlGraph[result.first].strength); + } + + graphString.append(imageSerial); + graphString.append(" ----("); + graphString.append(edgeStrength); + graphString.append(") ["); + graphString.append(commonPoints.join(",")); + graphString.append("]---- "); + graphString.append(adjacentSerial); + graphString.append("\n"); + } + } + + return graphString; + } + + + /** + * Updates the ControlNet graph for the measure's serial number to + * reflect the addition. If there is currently no node for + * this measure's serial, then a new node is created with * this measure as its first. * * @param measure The measure added to the network. * - * @throws IException::Programmer "NULL measure passed to ControlNet::AddControlCubeGraphNode!" + * @throws IException::Programmer "NULL measure passed to ControlNet::measureAdded!" * @throws IException::Programmer "Control measure with NULL parent passed to - * ControlNet::AddControlCubeGraphNode!" + * ControlNet::measureAdded!" * @throws IException::Programmer "ControlNet does not contain the point." */ void ControlNet::measureAdded(ControlMeasure *measure) { if (!measure) { IString msg = "NULL measure passed to " - "ControlNet::AddControlCubeGraphNode!"; + "ControlNet::measureAdded!"; throw IException(IException::Programmer, msg, _FILEINFO_); } ControlPoint *point = measure->Parent(); if (!point) { IString msg = "Control measure with NULL parent passed to " - "ControlNet::AddControlCubeGraphNode!"; + "ControlNet::measureAdded!"; throw IException(IException::Programmer, msg, _FILEINFO_); } @@ -442,19 +594,19 @@ namespace Isis { msg += point->GetId() + "]"; throw IException(IException::Programmer, msg, _FILEINFO_); } + // Add the measure to the corresponding node + QString serial = measure->GetCubeSerialNumber(); - // make sure there is a node for every measure in this measure's parent - for (int i = 0; i < point->GetNumMeasures(); i++) { - QString sn = point->GetMeasure(i)->GetCubeSerialNumber(); - if (!cubeGraphNodes->contains(sn)) { - cubeGraphNodes->insert(sn, new ControlCubeGraphNode(sn)); - } + // If the graph doesn't have the sn, add a node for it + if (!m_vertexMap.contains(serial)) { + Image newImage; + newImage.serial = serial; + ImageVertex newVertex = boost::add_vertex(newImage, m_controlGraph); + m_vertexMap.insert(serial, newVertex); + emit networkModified(GraphModified); } - // add the measure to the corresponding node - QString serial = measure->GetCubeSerialNumber(); - ControlCubeGraphNode *node = (*cubeGraphNodes)[serial]; - node->addMeasure(measure); + m_controlGraph[m_vertexMap[serial]].measures[measure->Parent()] = measure; // in this measure's node add connections to the other nodes reachable from // its point @@ -463,41 +615,80 @@ namespace Isis { ControlMeasure *cm = point->GetMeasure(i); if (!cm->IsIgnored()) { QString sn = cm->GetCubeSerialNumber(); - ControlCubeGraphNode *neighborNode = (*cubeGraphNodes)[sn]; - if (neighborNode != node) { - node->addConnection(neighborNode, point); - neighborNode->addConnection(node, point); + + if (QString::compare(sn, serial) != 0) { + addEdge(serial, sn); } } } } + emit newMeasure(measure); + } + + + /** + * Update the ControlNet's internal structure when a ControlPoint is un-ignored. + * + * @param point A pointer to the un-ignored point. + */ + void ControlNet::pointUnIgnored(ControlPoint *point) { + if (!point) { + IString msg = "NULL point passed to " + "ControlNet::pointUnIgnored!"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + QList< ControlMeasure * > validMeasures = point->getMeasures(true); + + for (int i = 0; i < validMeasures.size(); i++) { + ControlMeasure *sourceMeasure = validMeasures[i]; + QString sourceSerial = sourceMeasure->GetCubeSerialNumber(); + + if (!ValidateSerialNumber(sourceSerial)) { + QString msg = "Node does not exist for ["; + msg += sourceSerial + "]"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + for(int j = i+1; j < validMeasures.size(); j++) { + ControlMeasure *targetMeasure = validMeasures[j]; + QString targetSerial = targetMeasure->GetCubeSerialNumber(); + + if (!ValidateSerialNumber(targetSerial)) { + QString msg = "Node does not exist for ["; + msg += targetSerial + "]"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + addEdge(sourceSerial, targetSerial); + } + } } /** - * Updates the connections for the ControlCubeGraphNode associated with the + * Updates the connections for the ControlNet graph associated with the * measure's serial number to reflect the unignoration. * * @param measure The measure unignored from the network. * - * @throws IException::Programmer "NULL measure passed to ControlNet::AddControlCubeGraphNode!" + * @throws IException::Programmer "NULL measure passed to ControlNet::measureUnIgnored!" * @throws IException::Programmer "Control measure with NULL parent passed to - * ControlNet::AddControlCubeGraphNode!" + * ControlNet::measureUnIgnored!" * @throws IException::Programmer "ControlNet does not contain the point." * @throws IException::Programmer "Node does not exist for the cube serial number." */ void ControlNet::measureUnIgnored(ControlMeasure *measure) { if (!measure) { IString msg = "NULL measure passed to " - "ControlNet::AddControlCubeGraphNode!"; + "ControlNet::measureUnIgnored!"; throw IException(IException::Programmer, msg, _FILEINFO_); } ControlPoint *point = measure->Parent(); if (!point) { IString msg = "Control measure with NULL parent passed to " - "ControlNet::AddControlCubeGraphNode!"; + "ControlNet::measureUnIgnored!"; throw IException(IException::Programmer, msg, _FILEINFO_); } @@ -507,10 +698,11 @@ namespace Isis { throw IException(IException::Programmer, msg, _FILEINFO_); } - // make sure there is a node for every measure in this measure's parent + // Make sure there is a node for every measure in this measure's parent for (int i = 0; i < point->GetNumMeasures(); i++) { - QString sn = point->GetMeasure(i)->GetCubeSerialNumber(); - if (!cubeGraphNodes->contains(sn)) { + ControlMeasure *adjacentMeasure = point->GetMeasure(i); + QString sn = adjacentMeasure->GetCubeSerialNumber(); + if (!adjacentMeasure->IsIgnored() && !m_vertexMap.contains(sn)) { QString msg = "Node does not exist for ["; msg += measure->GetCubeSerialNumber() + "]"; throw IException(IException::Programmer, msg, _FILEINFO_); @@ -519,18 +711,16 @@ namespace Isis { if (!point->IsIgnored()) { QString serial = measure->GetCubeSerialNumber(); - ControlCubeGraphNode *node = (*cubeGraphNodes)[serial]; - // in this measure's node add connections to the other nodes reachable + // In this measure's node add connections to the other nodes reachable // from its point for (int i = 0; i < point->GetNumMeasures(); i++) { ControlMeasure *cm = point->GetMeasure(i); if (!cm->IsIgnored()) { QString sn = cm->GetCubeSerialNumber(); - ControlCubeGraphNode *neighborNode = (*cubeGraphNodes)[sn]; - if (neighborNode != node) { - node->addConnection(neighborNode, point); - neighborNode->addConnection(node, point); + + if (QString::compare(sn, serial) != 0) { + addEdge(serial, sn); } } } @@ -554,182 +744,119 @@ namespace Isis { /** - * Updates the ControlCubeGraphNode for this measure's serial number to - * reflect the deletion. If this is the only measure left in the containing - * ControlCubeGraphNode, then the ControlCubeGraphNode is deleted as well. + * Updates the node for this measure's serial number to + * reflect the deletion. * * @param measure The measure removed from the network. */ void ControlNet::measureDeleted(ControlMeasure *measure) { ASSERT(measure); - QString serial = measure->GetCubeSerialNumber(); - ASSERT(cubeGraphNodes->contains(serial)); - ControlCubeGraphNode *node = (*cubeGraphNodes)[serial]; + ASSERT(m_vertexMap.contains(serial)); + + emit measureRemoved(measure); - // remove connections to and from this node + // Remove connections to and from this node if (!measure->IsIgnored() && !measure->Parent()->IsIgnored()) { // Break connections measureIgnored(measure); } - // Remove the measure from the node. If this caused the node to be empty, - // then delete the node. - node->removeMeasure(measure); - if (!node->getMeasureCount()) { - delete node; - node = NULL; - cubeGraphNodes->remove(serial); + // Remove the measure from the associated node. + // Conceptually, I think this belongs in measureIgnored, but it isn't done + // for the old graph. + m_controlGraph[m_vertexMap[serial]].measures.remove(measure->Parent()); + + } + + + /** + * Update the ControlNet's internal structure when a ControlPoint is ignored. + * + * @param point A pointer to the ignored point. + */ + void ControlNet::pointIgnored(ControlPoint *point) { + if (!point) { + IString msg = "NULL point passed to " + "ControlNet::pointIgnored!"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + QList< ControlMeasure * > validMeasures = point->getMeasures(true); + + for (int i = 0; i < validMeasures.size(); i++) { + ControlMeasure *sourceMeasure = validMeasures[i]; + QString sourceSerial = sourceMeasure->GetCubeSerialNumber(); + + if (!ValidateSerialNumber(sourceSerial)) { + QString msg = "Node does not exist for ["; + msg += sourceSerial + "]"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + for(int j = i+1; j < validMeasures.size(); j++) { + ControlMeasure *targetMeasure = validMeasures[j]; + QString targetSerial = targetMeasure->GetCubeSerialNumber(); + + if (!ValidateSerialNumber(targetSerial)) { + QString msg = "Node does not exist for ["; + msg += targetSerial + "]"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + removeEdge(sourceSerial, targetSerial); + } } } + + /** + * Updates the edges in the ControlNet graph to reflect the ignored + * measure. If this was the last measure connecting one node to another, + * then the edge is deleted as well. + * + * @param measure The measure set to ignored from the network. + */ void ControlNet::measureIgnored(ControlMeasure *measure) { if (!measure) { IString msg = "NULL measure passed to " - "ControlNet::AddControlCubeGraphNode!"; + "ControlNet::measureIgnored!"; throw IException(IException::Programmer, msg, _FILEINFO_); } ControlPoint *point = measure->Parent(); if (!point) { IString msg = "Control measure with NULL parent passed to " - "ControlNet::AddControlCubeGraphNode!"; + "ControlNet::measureIgnored!"; throw IException(IException::Programmer, msg, _FILEINFO_); } QString serial = measure->GetCubeSerialNumber(); - if (!cubeGraphNodes->contains(serial)) { + if (!ValidateSerialNumber(serial)) { QString msg = "Node does not exist for ["; msg += serial + "]"; throw IException(IException::Programmer, msg, _FILEINFO_); } - ControlCubeGraphNode *node = (*cubeGraphNodes)[serial]; - - // remove connections to and from this node + // Decrement the edge strength for edges from this node + // Remove edge if the strength becomes 0. for (int i = 0; i < point->GetNumMeasures(); i++) { - QString sn = point->GetMeasure(i)->GetCubeSerialNumber(); - if (cubeGraphNodes->contains(sn)) { - ControlCubeGraphNode *neighborNode = (*cubeGraphNodes)[sn]; - if (node != neighborNode) { - neighborNode->removeConnection(node, point); - node->removeConnection(neighborNode, point); + ControlMeasure *adjacentMeasure = point->GetMeasure(i); + QString sn = adjacentMeasure->GetCubeSerialNumber(); + if (!adjacentMeasure->IsIgnored() && m_vertexMap.contains(sn)) { + if (QString::compare(serial, sn) !=0) { + removeEdge(serial, sn); } } } } - void ControlNet::emitNetworkStructureModified() { - emit networkStructureModified(); - } - - /** - * Random breadth-first search. This meathod starts at a random serial, and - * returns a list with the start serial as well as any serial which is - * directly or indirectly connected to it. The list returned will contain - * all the serials in the network if and only if the network is completely - * connected. Otherwise, the list returned will be the entire island on - * which a random image resides. - * - * @returns A List of connected graph nodes + * This method is a wrapper to emit the networkStructureModified() signal. */ - QList< ControlCubeGraphNode * > ControlNet::RandomBFS( - QList< ControlCubeGraphNode * > nodes) const { - qsrand(42); - Shuffle(nodes); - - // for keeping track of visited nodes - QMap< ControlCubeGraphNode *, bool > searchList; - for (int i = 0; i < nodes.size(); i++) - searchList.insert(nodes[i], false); - - // for storing nodes as they are found - QSet< ControlCubeGraphNode * > results; - - QQueue< ControlCubeGraphNode * > q; - q.enqueue(nodes[0]); - while (q.size()) { - ControlCubeGraphNode *curNode = q.dequeue(); - if (!results.contains(curNode)) { - // add to results - results.insert(curNode); - searchList[curNode] = true; - - // add all the neighbors to the queue - QList< ControlCubeGraphNode * > neighbors = curNode->getAdjacentNodes(); - Shuffle(neighbors); - for (int i = 0; i < neighbors.size(); i++) - q.enqueue(neighbors[i]); - } - } // end of breadth-first search - - return results.values(); - } - - - /** - * Shuffles the QStrings in a QList< QString > - * - * @param list The list to be shuffled - */ - void ControlNet::Shuffle(QList< ControlCubeGraphNode * > & list) const { - for (int i = list.size() - 1; i > 0; i--) { - // standard form is qrand() / (RAND_MAX + 1.0) * (max + 1 - min) + min - // min is always zero here so it is simplified to... - int j = (int)(qrand() / (RAND_MAX + 1.0) * (i + 1)); - qSwap(list[j], list[i]); - } - } - - - /** - * Calculate the band width and critical edges needed by the adjacency matrix - * that could store cube connectivity if that matrix used the same ordering - * as is in the provided list. Note that no adjacency matrices are ever used - * in this class! - * - * Critical edges are edges that contribute to band width. - * - * @param serials A list of cube serial numbers. - * - * @returns A QPair such that the first element is the needed bandwidth for - * the serials how they are currently ordered in the list, and the - * second element is the number of critical edges. - */ - QPair< int, int > ControlNet::CalcBWAndCE(QList< QString > serials) const { - - for (int i = 0; i < serials.size(); i++) - ASSERT(cubeGraphNodes->contains(serials[i])); - - int bw = 0; - QList< int > colWidths; - - for (int i = 0; i < serials.size(); i++) { - int colWidth = 0; - ControlCubeGraphNode *node1 = (*cubeGraphNodes)[serials[i]]; - for (int j = 0; j < serials.size(); j++) { - if (i != j) { - ControlCubeGraphNode *node2 = (*cubeGraphNodes)[serials[j]]; - int colDiff = abs(i - j); - if (node1->isConnected(node2) && colDiff > colWidth) - colWidth = colDiff; - } - } - colWidths.append(colWidth); - if (colWidth > bw) - bw = colWidth; - } - - int criticalEdges = 0; - foreach(int width, colWidths) { - if (width == bw) - criticalEdges++; - } - - return qMakePair(bw, criticalEdges); + void ControlNet::emitNetworkStructureModified() { + emit networkStructureModified(); } @@ -773,9 +900,11 @@ namespace Isis { // notify CubeSerialNumbers of the loss of this point foreach(ControlMeasure * measure, point->getMeasures()) { - measureDeleted(measure); + point->Delete(measure); } + emit pointDeleted(point); + // delete point points->remove(pointId); pointIds->removeAt(pointIds->indexOf(pointId)); @@ -784,7 +913,6 @@ namespace Isis { if (!wasIgnored) emit networkStructureModified(); - return ControlPoint::Success; } @@ -826,208 +954,35 @@ namespace Isis { * @returns A list of cube islands as serial numbers */ QList< QList< QString > > ControlNet::GetSerialConnections() const { - QList< QList< QString > > islandStrings; - QList< QList< ControlCubeGraphNode * > > islands = GetNodeConnections(); - for (int i = 0; i < islands.size(); i++) { - QList< QString > newIsland; - islandStrings.append(newIsland); - for (int j = 0; j < islands[i].size(); j++) - islandStrings[i].append(islands[i][j]->getSerialNumber()); - } - return islandStrings; - } + VertexIndexMap indexMap; + VertexIndexMapAdaptor indexMapAdaptor(indexMap); - /** - * This method searches through all the cube serial numbers in the network. - * Serials which are connected to other serials through points are grouped - * together in the same lists. The list containing the lists of strings is - * nothing more than a list of islands such that each island is a list of - * serials which are connected to each other. If the control network is - * completely connected, then this list will only have one element (a list - * of all the serials in the network). - * - * @returns A list of cube islands as graph nodes - */ - QList< QList< ControlCubeGraphNode * > > ControlNet::GetNodeConnections() const { - QList< ControlCubeGraphNode * > notYetFound = cubeGraphNodes->values(); - QList< QList< ControlCubeGraphNode * > > islands; - - do { - // extract an island from the nodes which are not yet found - QList< ControlCubeGraphNode * > island = RandomBFS(notYetFound); - - // remove newly found nodes from notYetFound - for (int i = 0; i < island.size(); i++) - notYetFound.removeOne(island[i]); - - // Add island to list of islands - islands.append(island); - } - while (notYetFound.size()); - - return islands; - } - - - /** - * This method uses Kruskal's Algorithm to construct a minimum spanning tree - * of the given island, with control measures acting as the edges between - * graph nodes. Because measures do not directly connect graph nodes, but - * rather connect graph nodes to control points, points are considered - * "intermediate vertices". When building the tree, we treat points like - * normal graph node vertices, but after the tree is built, we prune away any - * measures that, in conjunction with a point, form an "incomplete edge". - * Such an edge goes from a graph node to a point, but does not have another - * edge going from that point to another node. Since the primary purpose of - * this tree is to evaluate image connectivity, such edges are unnecessary. - * A "complete edge" consists of two measures and a point, and connects two - * graph nodes, or images. - * - * The cost of each edge is determined by the provided less-than comparison - * function. If a Control Measure is less-than another, it is said to have a - * lower cost, and is thus more likely to appear in the minimum spanning tree. - * - * Minimum spanning trees are constructed on islands, not networks, so it is - * important that the caller first retrieve the list of islands in the network - * from the GetNodeConnections() method before invoking this method. Creating - * a minimum spanning tree for an entire network with multiple islands would - * be impractical, as this method does not account for the possibility that - * some nodes are disconnected in the input. - * - * A common usage of the minimum spanning tree is to measure the importance of - * a given measure or point to the overall connectivity of a network. If a - * measurement is not in the MST, we do not need to worry about creating - * additional islands by removing it. - * - * It is important that the user choose their less-than function carefully. - * If a poor less-than function is used, then "bad" measures could end up in - * the MST while "good" measures are excluded, thus giving the user the false - * impression that a good measure can be safely deleted, while a bad measure - * must be preserved. The application "cnetwinnow", for example, tries to - * remove as many measures with high residuals as possible without increasing - * the island count of the network, so its less-than function compares the - * residual magnitude of the two input measures. - * - * @param island The list of graph nodes forming the island to be minimized - * @param lessThan A comparison function telling us if one measure is better - * than another - * - * @return The set of all measures (edges) in the minimum spanning tree - */ - QSet< ControlMeasure * > ControlNet::MinimumSpanningTree( - QList< ControlCubeGraphNode *> &island, - bool lessThan(const ControlMeasure *, const ControlMeasure *)) const { - - // Kruskal's Algorithm - QSet< ControlMeasure * > minimumTree; - - // We start with a map containing all the unconnected vertices (nodes and - // points), each its own single-element tree. Our goal is join them all - // together into one tree connecting every vertex. We map into the forest - // with point ID and serial number so the two types of vertices can share a - // common, nearly constant-time lookup interface. - QMap< QString, ControlVertex * > forest; - - // Get a list of all the candidate edges on the island, and a set of their - // associated Control Points (to avoid duplication, as measures share common - // points). Keep a count of how many measures in the MST are connected to - // each point, as we'll want to prune off points with only one such - // conenction. - QList< ControlMeasure * > edges; - QMap< ControlPoint *, int > uniquePoints; - for (int i = 0; i < island.size(); i++) { - // Add each graph node as a tree in the forest - ControlCubeGraphNode *node = island[i]; - forest.insert(node->getSerialNumber(), new ControlVertex(node)); - - // Every graph node has a list of measures: these are our edges - QList< ControlMeasure * > measures = node->getMeasures(); - for (int j = 0; j < measures.size(); j++) { - edges.append(measures[j]); - - // Every measure has a point: these act as intermediate vertices. We - // keep a count of how many edges in the MST come off this point. - // Points with less than 2 edges are considered incomplete, as they do - // not form a connection from one graph node to another, or a "complete - // edge" - uniquePoints.insert(measures[j]->Parent(), 0); - } + // Needed to use connected_componenets + QList< QString> serials = m_vertexMap.keys(); + for (int i = 0; i < serials.size(); i++) { + boost::put(indexMapAdaptor, m_vertexMap[serials[i]], i); } - // Sort the edges in increasing cost with the provided less-than function - qSort(edges.begin(), edges.end(), lessThan); - - // Add every unique point on the island as a tree in the forest - QList< ControlPoint * > pointList = uniquePoints.keys(); - for (int i = 0; i < pointList.size(); i++) { - ControlPoint *point = pointList[i]; - forest.insert(point->GetId(), new ControlVertex(point)); - } - - // Every time we join two trees together, we reduce the total number of - // trees by one, but our forest data structure is unchanged, so keep a - // record of the actual forest size to decrement manually as we go along - int trees = forest.size(); - - // Keep trying to join trees until there is only one tree remaining or we're - // out of edges to try - while (trees > 1 && edges.size() > 0) { - // Try to add our lowest-cost edge to the minimum spanning tree - ControlMeasure *leastEdge = edges.takeFirst(); - - // Each edge connects two vertices: a point and a graph node. So grab the - // trees for each node and check that they're disjoint, and thus able to - // be joined. - QString pointId = leastEdge->Parent()->GetId(); - ControlVertex *pointVertex = forest[pointId]; - - QString serialNum = leastEdge->ControlSN()->getSerialNumber(); - ControlVertex *nodeVertex = forest[serialNum]; - - // When the edge joins two different trees (i.e., they have different - // roots), then add the edge to the minimum spanning tree and join the - // trees into one. Otherwise, we have formed a cycle and should thus - // discard the edge. - if (pointVertex->getRoot() != nodeVertex->getRoot()) { - ControlVertex::join(pointVertex, nodeVertex); - trees--; - minimumTree.insert(leastEdge); - uniquePoints[pointVertex->getPoint()]++; - } - } + VertexIndexMap componentMap; + VertexIndexMapAdaptor componentAdaptor(componentMap); + int numComponents = boost::connected_components(m_controlGraph, componentAdaptor, + boost::vertex_index_map(indexMapAdaptor)); - // Prune edges that go from a graph node to a point, but not from that - // point to another graph node. We care about image (graph node) - // connectivity, not point connectivity. A complete edge consists of two - // measures and a point, so remove any incomplete edges. - QList< ControlMeasure * > unprunedEdges = minimumTree.values(); - for (int i = 0; i < unprunedEdges.size(); i++) { - if (uniquePoints[unprunedEdges[i]->Parent()] < 2) - // The point this edge is connected to does not go on to another node, - // so prune it - minimumTree.remove(unprunedEdges[i]); - } - - // Clean up our vertices. This will not delete any of the points, measures, - // or graph nodes. All of that is owned by the network. - QList< ControlVertex * > vertexList = forest.values(); - for (int i = 0; i < vertexList.size(); i++) delete vertexList[i]; - - // Sanity check: an island with n > 1 nodes must, by definition, have an MST - // of e edges such that n <= e <= 2n - int n = island.size(); - int e = minimumTree.size(); - if (n > 1) { - if (e < n || e > 2 * n) { - IString msg = "An island of n = [" + IString(n) + - "] > 1 nodes must have a minimum spanning tree of e edges such that " - " n <= e <= 2n, but e = [" + IString(e) + "]"; - throw IException(IException::Programmer, msg, _FILEINFO_); - } + QList< QList< QString > > islandStrings; + for (int i = 0; i < numComponents; i++) { + QList<QString> tempList; + islandStrings.append(tempList); + } + std::map<ImageVertex, size_t>::iterator it = componentMap.begin(); + while(it != componentMap.end()) + { + QString serial = m_controlGraph[it->first].serial; + int group = (int) it->second; + islandStrings[group].append(serial); + ++it; } - - return minimumTree; + return islandStrings; } @@ -1035,36 +990,7 @@ namespace Isis { * @returns The total number of edges in the bi-directional graph for images */ int ControlNet::getEdgeCount() const { - int total = 0; - foreach (ControlCubeGraphNode * node, *cubeGraphNodes) { - total += node->getAdjacentNodes().size(); - } - - return total; - } - - - /** - * Used for verifying graph intergrity - * - * @returns A string representation of the cube graph - */ - QString ControlNet::CubeGraphToString() const { - QStringList serials; - QHashIterator < QString, ControlCubeGraphNode * > i(*cubeGraphNodes); - while (i.hasNext()) { - i.next(); - serials << i.value()->getSerialNumber(); - } - qSort(serials); - - QString str; - for (int i = 0; i < serials.size(); i++) { - str += " " + serials[i] + "\n" - + (*cubeGraphNodes)[serials[i]]->connectionsToString() + "\n"; - } - - return str; + return boost::num_edges(m_controlGraph); } @@ -1077,30 +1003,46 @@ namespace Isis { * @returns A list of the Cube Serial Numbers in the ControlNet. */ QList< QString > ControlNet::GetCubeSerials() const { - return cubeGraphNodes->keys(); + return m_vertexMap.keys(); } /** - * @returns A list of all the cube graph nodes in the network + * Does a check to ensure that the given serial number is contained within + * the network. + * + * @param serialNumber the cube serial number to validate + * + * @return @b bool If the serial number is contained in the network. */ - QList< ControlCubeGraphNode * > ControlNet::GetCubeGraphNodes() { - return cubeGraphNodes->values(); + bool ControlNet::ValidateSerialNumber(QString serialNumber) const { + return m_vertexMap.contains(serialNumber); } /** - * Does a check to ensure that the given serial number is contained within - * the network. If it is not, then an exception is thrown + * Get all images connected to a given image by common control points. * - * @param serialNumber the cube serial number to validate + * @param serialNumber the serial number of the image to find images adjacent to. + * + * @returns @b QList<QString> The serial numbers of all adjacent images. */ - void ControlNet::ValidateSerialNumber(QString serialNumber) const { - if (!cubeGraphNodes->contains(serialNumber)) { - IString msg = "Cube Serial Number [" + serialNumber + "] not found in " + QList< QString > ControlNet::getAdjacentImages(QString serialNumber) const { + if (!ValidateSerialNumber(serialNumber)) { + QString msg = "Cube Serial Number [" + serialNumber + "] not found in " "the network"; throw IException(IException::Programmer, msg, _FILEINFO_); } + + QList< QString > adjacentSerials; + + AdjacencyIterator adjIt, adjEnd; + boost::tie(adjIt, adjEnd) = boost::adjacent_vertices(m_vertexMap[serialNumber], m_controlGraph); + for( ; adjIt != adjEnd; adjIt++) { + adjacentSerials.append(m_controlGraph[*adjIt].serial); + } + + return adjacentSerials; } @@ -1110,8 +1052,13 @@ namespace Isis { * @returns A list of all measures which are in a given cube */ QList< ControlMeasure * > ControlNet::GetMeasuresInCube(QString serialNumber) { - ValidateSerialNumber(serialNumber); - return (*cubeGraphNodes)[serialNumber]->getMeasures(); + if( !ValidateSerialNumber(serialNumber) ) { + IString msg = "Cube Serial Number [" + serialNumber + "] not found in " + "the network"; + throw IException(IException::Programmer, msg, _FILEINFO_); + + } + return m_controlGraph[m_vertexMap[serialNumber]].measures.values(); } @@ -1121,8 +1068,17 @@ namespace Isis { * @returns A list of all valid measures which are in a given cube */ QList< ControlMeasure * > ControlNet::GetValidMeasuresInCube(QString serialNumber) { - ValidateSerialNumber(serialNumber); - return (*cubeGraphNodes)[serialNumber]->getValidMeasures(); + QList< ControlMeasure * > validMeasures; + + // Get measures in cube will validate this for us, so we don't need to re-check + QList< ControlMeasure * > measureList = GetMeasuresInCube(serialNumber); + + foreach(ControlMeasure * measure, measureList) { + if (!measure->IsIgnored()) + validMeasures.append(measure); + } + + return validMeasures; } @@ -1175,7 +1131,7 @@ namespace Isis { ControlPoint *point = this->GetPoint(i); if (point->IsIgnored()) continue; //if the point is ignored then continue - //get the number of measures + // Get the number of measures int nObs = point->GetNumMeasures(); for (int j=0;j<nObs;j++) { //for every measure ControlMeasure *measure = point->GetMeasure(j); @@ -1186,7 +1142,7 @@ namespace Isis { } } - //sort the measures + // Sort the measures ControlMeasureLessThanFunctor lessThan(statFunc); qSort(measures.begin(),measures.end(),lessThan); @@ -1194,22 +1150,6 @@ namespace Isis { } - /** - * Essentially removes a cube from the networkid - * - * @param serialNumber The cube serial number to be removed from the network - */ - void ControlNet::DeleteMeasuresWithId(QString serialNumber) { - ValidateSerialNumber(serialNumber); - - ControlCubeGraphNode *csn = (*cubeGraphNodes)[serialNumber]; - QList< ControlMeasure * > measures = csn->getMeasures(); - foreach(ControlMeasure * measure, measures) { - measure->Parent()->Delete(measure); - } - } - - /** * Compute error for each point in the network * @@ -1319,7 +1259,8 @@ namespace Isis { */ ControlPoint *ControlNet::FindClosest(QString serialNumber, double sample, double line) { - if (!cubeGraphNodes->contains(serialNumber)) { + + if (!ValidateSerialNumber(serialNumber)) { QString msg = "serialNumber ["; msg += serialNumber; msg += "] not found in ControlNet"; @@ -1330,12 +1271,12 @@ namespace Isis { double minDist = SEARCH_DISTANCE; ControlPoint *closestPoint = NULL; - ControlCubeGraphNode *csn = (*cubeGraphNodes)[serialNumber]; - QList< ControlMeasure * > measures = csn->getMeasures(); + QList < ControlMeasure * > measures = m_controlGraph[m_vertexMap[serialNumber]].measures.values(); + for (int i = 0; i < measures.size(); i++) { ControlMeasure *measureToCheck = measures[i]; - //Find closest line sample & return that controlpoint + // Find closest line sample & return that controlpoint double dx = fabs(sample - measureToCheck->GetSample()); double dy = fabs(line - measureToCheck->GetLine()); @@ -1445,7 +1386,11 @@ namespace Isis { * returning a count of only valid measures (Ignore=False). */ int ControlNet::GetNumberOfValidMeasuresInImage(const QString &serialNumber) { - return p_cameraValidMeasuresMap[serialNumber]; + // If SetImage was called, use the map that has been populated with valid measures + if (p_cameraList.size() > 0) { + return p_cameraValidMeasuresMap[serialNumber]; + } + return GetValidMeasuresInCube(serialNumber).size(); } @@ -1874,7 +1819,6 @@ namespace Isis { */ void ControlNet::swap(ControlNet &other) { std::swap(points, other.points); - std::swap(cubeGraphNodes, other.cubeGraphNodes); std::swap(pointIds, other.pointIds); std::swap(m_mutex, other.m_mutex); std::swap(p_targetName, other.p_targetName); @@ -1899,6 +1843,9 @@ namespace Isis { while (i2.hasNext()) { i2.next().value()->parentNetwork = &other; } + + emit networkModified(ControlNet::Swapped); + } @@ -1963,29 +1910,6 @@ namespace Isis { } - const ControlCubeGraphNode *ControlNet::getGraphNode( - QString serialNumber) const { - if (!cubeGraphNodes->contains(serialNumber)) { - IString msg = "Serial Number [" + serialNumber + "] does not exist in" - " the network."; - throw IException(IException::Programmer, msg, _FILEINFO_); - } - - return cubeGraphNodes->value(serialNumber); - } - - ControlCubeGraphNode *ControlNet::getGraphNode( - QString serialNumber) { - if (!cubeGraphNodes->contains(serialNumber)) { - IString msg = "Serial Number [" + serialNumber + "] does not exist in" - " the network."; - throw IException(IException::Programmer, msg, _FILEINFO_); - } - - return cubeGraphNodes->value(serialNumber); - } - - /** * Get the target radii * diff --git a/isis/src/control/objs/ControlNet/ControlNet.h b/isis/src/control/objs/ControlNet/ControlNet.h index 5ae923fbb948664c0e450fae647fd12c126e3486..e6d6b3121746116b79d709ab1e302c3315240efc 100644 --- a/isis/src/control/objs/ControlNet/ControlNet.h +++ b/isis/src/control/objs/ControlNet/ControlNet.h @@ -20,7 +20,7 @@ * $ISISROOT/doc//documents/Disclaimers/Disclaimers.html * in a browser or see the Privacy & Disclaimers page on the Isis website, * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on - * http://www.usgs.gov/privacy.html. + * http://www.usgs.gov/privacy.html */ // This is needed for the QVariant macro @@ -29,12 +29,24 @@ #include <QSharedPointer> #include <QString> #include <QMap> +#include <QVariant> #include <QVector> +#include <QVariant> + + +// Boost includes +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/connected_components.hpp> + +#include "ControlMeasure.h" +#include "ControlPoint.h" template< typename A, typename B > class QHash; template< typename T > class QList; template< typename A, typename B > struct QPair; template< typename T > class QSet; + class QMutex; class QString; @@ -42,7 +54,6 @@ namespace Isis { class Camera; class ControlMeasure; class ControlPoint; - class ControlCubeGraphNode; class Distance; class Progress; class Pvl; @@ -213,10 +224,39 @@ namespace Isis { * image. Previously, this had to be done throug the graph. * @history 2018-01-26 Kristin Berry - Added pointAdded() function to eliminate redundant measure * adds to the control network. + * @history 2018-06-10 Kristin Berry - Removed unused methods and associated code: + * MinimumSpanningTree(), GetNodeConnections(), RandomBFS(), Shuffle(), + * CalcBWAndCE(), CubeGraphToString(), getGraphNode(). References #5434 + * @history 2018-06-10 Kristin Berry - Updated to use the boost graph library instead of our + * custom graph structure ControlCubeGraphNode. * @history 2018-04-05 Adam Goins - Added a check to the versionedReader targetRadii * group to set radii values to those ingested from the versioner * if they exist. Otherwise, we call SetTarget with the targetname. * Fixes #5361. + * @history 2018-06-06 Jesse Mapel - Added a method to get all adjacent images to ControlNet. + * Previously this functionality was only available through the + * ControlCubeGraphNode class. References #5434. + * @history 2018-06-06 Jesse Mapel - Added a point ignored and un-ignored methods. This will + * prevent edge strengths getting incremented or decremented twice. + * References #5434. + * @history 2018-06-15 Adam Goins & Jesse Mapel - Added the ModType enum, as well as a series + * of signals that are emitted whenever a change is made to a + * Control Point or any of it's measures, or to the network itself. + * These signals exist for the purpose of communication between the + * ControlNetVitals class, and the network that it is observing. + * Fixes #5435. + * @history 2018-06-25 Kristin Berry - Updated GetNumberOfValidMeasuresInImage() to use + * GetValidMeasuresInCube() if SetImage has not yet been called to populate + * the p_cameraValidMeasuresMap. + * @history 2018-06-25 Jesse Mapel - Fixed the incorrect signal being called when adding and + * removing measures. References #5435. + * @history 2018-06-29 Kristin Berry - Added addEdge() and removeEdge() functions to make + * code cleaner. + * @history 2018-06-25 Jesse Mapel - Fixed ignoring measures with ignored adjacent measures + * incorrectly modifying the edge between the two image vertices. + * @history 2018-07-06 Jesse Mapel - Modified addEdge and removeEdge to always emit a graph + * modified signal if an edge is added or removed. Added graph + * modified signal when a vertex is added. */ class ControlNet : public QObject { Q_OBJECT @@ -225,6 +265,21 @@ namespace Isis { friend class ControlPoint; public: + + /** + * @brief Control Point Modification Types + * + * This enum is designed to represent the different types of modifications that can be + * made to a ControlNet. + * + * Swapped means the network was swapped with another network (ControlNet::Swap(ControlNet &other)). + * GraphModified means that a vertice or edge was added/removed from the graph.. + */ + enum ModType { + Swapped, + GraphModified + }; + ControlNet(); ControlNet(const ControlNet &other); ControlNet(const QString &filename, Progress *progress = 0); @@ -244,19 +299,14 @@ namespace Isis { bool ContainsPoint(QString pointId) const; QList< QString > GetCubeSerials() const; - QList< ControlCubeGraphNode * > GetCubeGraphNodes(); + QString GraphToString() const; QList< QList< QString > > GetSerialConnections() const; - QList< QList< ControlCubeGraphNode * > > GetNodeConnections() const; - QSet< ControlMeasure * > MinimumSpanningTree( - QList< ControlCubeGraphNode *> &island, - bool lessThan(const ControlMeasure *, const ControlMeasure *)) const; int getEdgeCount() const; - QString CubeGraphToString() const; + QList< QString > getAdjacentImages(QString serialNumber) const; QList< ControlMeasure * > GetMeasuresInCube(QString serialNumber); QList< ControlMeasure * > GetValidMeasuresInCube(QString serialNumber); QList< ControlMeasure * > sortedMeasureList(double(ControlMeasure::*statFunc)() const, double min,double max); - void DeleteMeasuresWithId(QString serialNumber); void ComputeResiduals(); void ComputeApriori(); @@ -266,9 +316,6 @@ namespace Isis { const ControlPoint *GetPoint(int index) const; ControlPoint *GetPoint(int index); - const ControlCubeGraphNode *getGraphNode(QString serialNumber) const; - ControlCubeGraphNode *getGraphNode(QString serialNumber); - double AverageResidual(); Isis::Camera *Camera(int index); QString CreatedDate() const; @@ -297,6 +344,7 @@ namespace Isis { QList< QString > GetPointIds() const; std::vector<Distance> GetTargetRadii(); + void SetCreatedDate(const QString &date); void SetDescription(const QString &newDescription); void SetImages(const QString &imageListFile); @@ -323,25 +371,34 @@ namespace Isis { signals: void networkStructureModified(); + void networkModified(ControlNet::ModType type); + void pointModified(ControlPoint *point, ControlPoint::ModType type, QVariant oldValue, QVariant newValue); + void measureModified(ControlMeasure *measure, ControlMeasure::ModType type, QVariant oldValue, QVariant newValue); + void pointDeleted(ControlPoint *point); + void newPoint(ControlPoint *); + void newMeasure(ControlMeasure *); + void measureRemoved(ControlMeasure *); + + private: void nullify(); - void ValidateSerialNumber(QString serialNumber) const; + bool ValidateSerialNumber(QString serialNumber) const; void measureAdded(ControlMeasure *measure); - void pointAdded(ControlPoint *point); void measureDeleted(ControlMeasure *measure); void measureIgnored(ControlMeasure *measure); void measureUnIgnored(ControlMeasure *measure); + void pointIgnored(ControlPoint *point); + void pointUnIgnored(ControlPoint *point); void UpdatePointReference(ControlPoint *point, QString oldId); void emitNetworkStructureModified(); - + void emitMeasureModified(ControlMeasure *measure, ControlMeasure::ModType type, QVariant oldValue, QVariant newValue); + void emitPointModified(ControlPoint *point, ControlPoint::ModType type, QVariant oldValue, QVariant newValue); + void pointAdded(ControlPoint *point); + bool addEdge(QString sourceSerial, QString targetSerial); + bool removeEdge(QString sourceSerial, QString targetSerial); private: // graphing functions - QList< ControlCubeGraphNode * > RandomBFS(QList < - ControlCubeGraphNode * > list) const; - void Shuffle(QList< ControlCubeGraphNode * > & list) const; - QPair< int, int > CalcBWAndCE(QList< QString > serials) const; - /** * @author 2012-04-13 Orrin Thomas * @@ -366,79 +423,46 @@ namespace Isis { double(ControlMeasure::*m_accessor)() const; }; + private: // data + //! hash ControlPoints by ControlPoint Id + QHash< QString, ControlPoint * > * points; - /** - * Encapsulation of a vertex in a minimum spanning tree. Can be either a - * Control Point or a Graph Node. Each vertex is connected to another by - * a measure. A vertex without a parent vertex is considered a root node, - * or the base of its own tree. - * - * @author ????-??-?? Unknown - * - * @internal - */ - class ControlVertex { - public: - //! Construct a vertex from a Graph Node - ControlVertex(ControlCubeGraphNode *node) { - m_node = node; - m_point = NULL; - m_parent = NULL; - } - - //! Construct a vertex from a Control Point - ControlVertex(ControlPoint *point) { - m_point = point; - m_node = NULL; - m_parent = NULL; - } - - //! Does not own any of its private data - ~ControlVertex() {} - - //! Set the parent vertex, removing the root node status. - void setParent(ControlVertex *v) { m_parent = v; } - - //! Get the root node, or greatest ancestor - ControlVertex * getRoot() { - ControlVertex *current = this; - while (current->getParent() != NULL) - current = current->getParent(); - return current; - } - - //! Get the parent node. A root node has no parent. - ControlVertex * getParent() { return m_parent; } - - //! Get the node representation of this vertex - ControlCubeGraphNode * getNode() { return m_node; } - - //! Get the point representation of this vertex - ControlPoint * getPoint() { return m_point; } + //! Used to define the verticies of the graph + struct Image { + QString serial; //! The serial number associated with the image + //! The measures on the image, hashed by pointers to their parent ControlPoints + QHash< ControlPoint *, ControlMeasure * > measures; + }; - //! Join two nodes by setting one root to be the other's parent - static void join(ControlVertex *v1, ControlVertex *v2) { - v1->getRoot()->setParent(v2->getRoot()); - } + //! Used to define the edges of the graph. + struct Connection { + int strength; + Connection() : strength(0) {} + }; - private: - //! The possibly non-existant graph node - ControlCubeGraphNode *m_node; + //! Defines the graph type as an undirected graph that uses Images for verticies, + //! and Connections for edges. It is defined as an adjacency list with the edge list + //! represented by a set, the and vertex list represented by a list. + typedef boost::adjacency_list<boost::setS, + boost::listS, + boost::undirectedS, + Image, + Connection> Network; - //! The possibly non-existant control point - ControlPoint *m_point; + typedef Network::vertex_descriptor ImageVertex; //! Reprents the verticies of the graph + typedef Network::edge_descriptor ImageConnection; //! Represents the edges of the graph - //! The possibly non-existant parent vertex - ControlVertex *m_parent; - }; + //! A map between an ImageVertex and its index + typedef std::map<ImageVertex, size_t> VertexIndexMap; + //! Converts VertexIndexMap into the appropriate form to be used by boost + typedef boost::associative_property_map<VertexIndexMap> VertexIndexMapAdaptor; - private: // data - //! hash ControlPoints by ControlPoint Id - QHash< QString, ControlPoint * > * points; + //! Iterates over adjacent verticies + typedef boost::graph_traits<Network>::adjacency_iterator AdjacencyIterator; - //! hash ControlCubeGraphNodes by CubeSerialNumber - QHash< QString, ControlCubeGraphNode * > * cubeGraphNodes; + QHash<QString, ImageVertex> m_vertexMap; //! The serial number -> vertex hash used by the graph + Network m_controlGraph; //! The ControlNet graph QStringList *pointIds; QMutex *m_mutex; diff --git a/isis/src/control/objs/ControlNet/ControlNet.truth b/isis/src/control/objs/ControlNet/ControlNet.truth index caa915ff646a406d8487be8b9ef4db5a01aeefe1..7bfd60953e8d3b416473315452e5ad684b3a833d 100644 --- a/isis/src/control/objs/ControlNet/ControlNet.truth +++ b/isis/src/control/objs/ControlNet/ControlNet.truth @@ -1,85 +1,65 @@ UnitTest for ControlNet .... ******* test cube connection graph ************ - ALPHA - BRAVO : p0 - BRAVO - ALPHA : p0 +testing ignoring measures.............................. +starting graph +ALPHA ----(1) [p0]---- BRAVO - ALPHA +ignore a measure - BRAVO +un-ignore a measure +ALPHA ----(1) [p0]---- BRAVO +testing measure addition to point already in network... +add point with only 1 measure +ALPHA ----(1) [p0]---- BRAVO - ALPHA - BRAVO : p0 - BRAVO - ALPHA : p0 +add a measure +ALPHA ----(2) [p0,p1]---- BRAVO -testing measure addition to point already in network... - ALPHA - BRAVO : p0, p1 - CHARLIE : p1 - BRAVO - ALPHA : p0, p1 - CHARLIE : p1 - CHARLIE - ALPHA : p1 - BRAVO : p1 +add another measure +ALPHA ----(2) [p0,p1]---- BRAVO +ALPHA ----(1) [p1]---- CHARLIE +BRAVO ----(1) [p1]---- CHARLIE testing setting point to ignored....................... - ALPHA - BRAVO : p0 - BRAVO - ALPHA : p0 - CHARLIE +ignore p1 +ALPHA ----(1) [p0]---- BRAVO - - ALPHA - BRAVO : p0, p1 - CHARLIE : p1 - BRAVO - ALPHA : p0, p1 - CHARLIE : p1 - CHARLIE - ALPHA : p1 - BRAVO : p1 +un-ignore p1 +ALPHA ----(2) [p0,p1]---- BRAVO +ALPHA ----(1) [p1]---- CHARLIE +BRAVO ----(1) [p1]---- CHARLIE testing measure deletion & addition.................... - ALPHA - BRAVO : p1 - CHARLIE : p1 - BRAVO - ALPHA : p1 - CHARLIE : p1 - CHARLIE - ALPHA : p1 - BRAVO : p1 +ALPHA ----(1) [p1]---- BRAVO +ALPHA ----(1) [p1]---- CHARLIE +BRAVO ----(1) [p1]---- CHARLIE - ALPHA - BRAVO : p1 - CHARLIE : p1 - DELTA : p0 +ALPHA ----(1) [p1]---- BRAVO +ALPHA ----(1) [p1]---- CHARLIE +ALPHA ----(1) [p0]---- DELTA +BRAVO ----(1) [p1]---- CHARLIE + +testing FindClosest.................... +Closest Point ID: p1 + +testing getAdjacentImages.................... +Adjacent Images: BRAVO - ALPHA : p1 - CHARLIE : p1 CHARLIE - ALPHA : p1 - BRAVO : p1 DELTA - ALPHA : p0 testing point deletion................................. - ALPHA - DELTA : p0 - DELTA - ALPHA : p0 +ALPHA ----(1) [p0]---- DELTA ******* Done testing cube graph *************** testing GetCubeSerials... (NOTE: unittest sorts the results) ALPHA + BRAVO + CHARLIE DELTA testing set target................................. @@ -365,45 +345,23 @@ Writing ControlNet to temp2.bin in binary format Reading ControlNet from temp2.bin Diffing temp.bin and temp2.bin Read/Write of binary files OK. -Testing GetCubeGraphNodes ALPHA + BRAVO + CHARLIE DELTA +ALPHA ----(1) [p0]---- DELTA -Testing getGraphNode: ALPHA -Testing getEdgeCount: 2 +Testing getEdgeCount: 1 +Getting measures in cube with SN: ALPHA: +Serial Number: ALPHA +Testing GetSerialConnections -Testing GetNodeConnections() +Testing GetSerialConnections() Island Count = 2 -Testing MinimumSpanningTree() - Tree Count = 2 - Graph Node Count = 5 - Measure Count = 9 - Island Count == 2 == MST Count - - Minimum Spanning Tree 0 - Nodes = 4 - Included Measures = 5 - m1 (ALPHA -> p1, residual = 1.41421) - m2 (BETA -> p1, residual = 2.82843) - m3 (GAMMA -> p1, residual = 4.24264) - m6 (DELTA -> p3, residual = 4.24264) - m7 (ALPHA -> p3, residual = 5.65685) - Excluded Measures = 3 - m4 (GAMMA -> p2, residual = 1.41421) - m5 (DELTA -> p2, residual = 11.3137) - m8 (ALPHA -> p4, residual = 1.41421) - - Minimum Spanning Tree 1 - Nodes = 1 - Included Measures = 0 - Excluded Measures = 1 - m9 (EPSILON -> p5, residual = 1.41421) - Testing take() functionality to take owernship of the points in a ControlNet: Original control net number of points: 1 Number of points taken out: 1 Now there should be zero points in the original control net. There are: 0 And zero pointIDs in the original control net. There are: 0 -And zero cubeGraphNodes in the original control net. There are: 0 diff --git a/isis/src/control/objs/ControlNet/unitTest.cpp b/isis/src/control/objs/ControlNet/unitTest.cpp index b172f0d36c8b09659a75ff6d929aa17fc317993e..0e687157efc6e21e0e426add70ac5f0ed7e46a08 100644 --- a/isis/src/control/objs/ControlNet/unitTest.cpp +++ b/isis/src/control/objs/ControlNet/unitTest.cpp @@ -5,12 +5,13 @@ #include <sstream> #include <ctime> +#include <QHash> #include <QList> #include <QSet> #include <QString> +#include <QStringList> #include <QVector> -#include "ControlCubeGraphNode.h" #include "ControlMeasure.h" #include "ControlMeasureLogData.h" #include "ControlNet.h" @@ -26,11 +27,13 @@ using namespace std; using namespace Isis; /** - * Unit test for ControlNet class - * + * Unit test for ControlNet class + * * @author ????-??-?? Unknown * @internal * @history 2016-05-11 Jeannie Backer - Added tests for setTarget methods. + * @history 2018-05-29 Kristin Berry - Removed code related to unused, removed methods. Ref #5434. + * Added tests for untested methods. */ bool lessThan(const ControlMeasure *m1, const ControlMeasure *m2) { return m1->GetResidualMagnitude() < m2->GetResidualMagnitude(); @@ -143,72 +146,16 @@ void testConnectivity() { net.AddPoint(p4); net.AddPoint(p5); - cout << "\nTesting GetNodeConnections()\n"; - QList< QList< ControlCubeGraphNode * > > islands = net.GetNodeConnections(); - if (islands[0].contains(m9->ControlSN())) islands.swap(0, 1); - cout << " " << "Island Count = " << islands.size() << endl; - - cout << "\nTesting MinimumSpanningTree()\n"; - QList< QSet< ControlMeasure * > > spanningTrees; - int nodeCount = 0; - for (int i = 0; i < islands.size(); i++) { - spanningTrees.append(net.MinimumSpanningTree(islands[i], lessThan)); - nodeCount += islands[i].size(); - } - - cout << " " << "Tree Count = " << spanningTrees.size() << endl; - cout << " " << "Graph Node Count = " << nodeCount << endl; - - QList< QMap< QString, ControlMeasure * > > includedMaps; - QList< QMap< QString, ControlMeasure * > > excludedMaps; - for (int i = 0; i < spanningTrees.size(); i++) { - includedMaps.append(QMap< QString, ControlMeasure * >()); - excludedMaps.append(QMap< QString, ControlMeasure * >()); - } - - int measureCount = 0; - for (int p = 0; p < net.GetNumPoints(); p++) { - ControlPoint *point = net.GetPoint(p); - for (int m = 0; m < point->GetNumMeasures(); m++) { - ControlMeasure *measure = point->GetMeasure(m); - measureCount++; - for (int i = 0; i < spanningTrees.size(); i++) { - if (islands[i].contains(measure->ControlSN())) { - if (spanningTrees[i].contains(measure)) - includedMaps[i].insert(measureNames[measure], measure); - else - excludedMaps[i].insert(measureNames[measure], measure); - } - } - } - } - cout << " " << "Measure Count = " << measureCount << endl; - - int includedMeasures = 0; - for (int i = 0; i < spanningTrees.size(); i++) { - QSet< ControlMeasure * > measures = spanningTrees[i]; - includedMeasures += measures.size(); - } - - if (islands.size() != spanningTrees.size()) { - cout << " " << "Island Count == " << islands.size() << " != " << - spanningTrees.size() << " == MST Count" << endl; - } - else { - cout << " " << "Island Count == " << islands.size() << - " == MST Count" << endl; - - for (int i = 0; i < spanningTrees.size(); i++) { - cout << "\n " << "Minimum Spanning Tree " << i << endl; + std::cout << "Getting measures in cube with SN: ALPHA: " << std::endl; + QList< ControlMeasure *> measures = net.GetMeasuresInCube("ALPHA"); + std::cout << "Serial Number: " << measures[0]->GetCubeSerialNumber() << std::endl; - cout << " " << "Nodes = " << islands[i].size() << endl; - cout << " " << "Included Measures = " << includedMaps[i].size() << endl; - printMeasures(includedMaps[i].values(), measureNames); + std::cout << "Testing GetSerialConnections" << std::endl; + net.GetSerialConnections(); - cout << " " << "Excluded Measures = " << excludedMaps[i].size() << endl; - printMeasures(excludedMaps[i].values(), measureNames); - } - } +cout << "\nTesting GetSerialConnections()\n"; +QList< QList< QString > > islands = net.GetSerialConnections(); +cout << " " << "Island Count = " << islands.size() << endl; } @@ -231,11 +178,15 @@ int main() { net.AddPoint(p0); // test ignoring of measures - cout << net.CubeGraphToString() << "\n"; + cout << "testing ignoring measures..............................\n"; + cout << "starting graph\n"; + cout << net.GraphToString() << "\n"; + cout << "ignore a measure\n"; p0m1->SetIgnored(true); - cout << net.CubeGraphToString() << "\n"; + cout << net.GraphToString() << "\n"; + cout << "un-ignore a measure\n"; p0m1->SetIgnored(false); - cout << net.CubeGraphToString() << "\n"; + cout << net.GraphToString() << "\n"; // add another point - testing case where measures are added to points which // are already added to a net. @@ -249,39 +200,66 @@ int main() { p1m1->SetCubeSerialNumber("BRAVO"); ControlMeasure *p1m2 = new ControlMeasure; p1m2->SetCubeSerialNumber("CHARLIE"); + cout << "add point with only 1 measure\n"; + cout << net.GraphToString() << "\n"; + cout << "add a measure\n"; p1->Add(p1m1); + cout << net.GraphToString() << "\n"; + cout << "add another measure\n"; p1->Add(p1m2); - cout << net.CubeGraphToString() << "\n"; + cout << net.GraphToString() << "\n"; // test ignoring of point cout << "testing setting point to ignored.......................\n"; + cout << "ignore p1\n"; p1->SetIgnored(true); - cout << net.CubeGraphToString() << "\n"; + cout << net.GraphToString() << "\n"; + cout << "un-ignore p1\n"; p1->SetIgnored(false); - cout << net.CubeGraphToString() << "\n"; + cout << net.GraphToString() << "\n"; // test measure deletion cout << "testing measure deletion & addition....................\n"; p0->Delete(p0m1); p0m1 = NULL; - cout << net.CubeGraphToString() << "\n"; + cout << net.GraphToString() << "\n"; p0m0 = new ControlMeasure; p0m0->SetCubeSerialNumber("DELTA"); p0->Add(p0m0); - cout << net.CubeGraphToString() << "\n"; + cout << net.GraphToString() << "\n"; + + // test FindClosest() + cout << "testing FindClosest....................\n"; + p1m0->SetCoordinate(1.0, 1.0); + p0m0->SetCoordinate(1.0, 2.0); + + ControlPoint *closestPoint = net.FindClosest("ALPHA", 1.0,1.0); + cout << "Closest Point ID: " << closestPoint->GetId() << endl << endl; + + // test getAdjacentImages() + cout << "testing getAdjacentImages....................\n"; + + QStringList adjacentSerials = net.getAdjacentImages("ALPHA"); + // We cannot gaurantee order on this list, so sort it for testing purposes + adjacentSerials.sort(); + cout << "Adjacent Images: " << endl; + foreach(QString serial, adjacentSerials) { + cout << " " << serial << endl; + } + cout << endl; // test point deletion cout << "testing point deletion.................................\n"; net.DeletePoint(p1); p1 = NULL; - cout << net.CubeGraphToString() << "\n"; + cout << net.GraphToString() << "\n"; cout << "******* Done testing cube graph ***************\n\n\n"; cout << "testing GetCubeSerials... (NOTE: unittest sorts the results)\n"; QList< QString > serials = net.GetCubeSerials(); - - // Let's sort the data since GetCubeSerials relies on a QHash + + // Let's sort the data since GetCubeSerials relies on a QHash QStringList sortedSerials(serials); sortedSerials.sort(); @@ -310,7 +288,7 @@ int main() { cn1.SetTarget("SomethingStrange", targetRadii); vector<Distance> targRad = cn1.GetTargetRadii(); cout << " TargetName = " << cn1.GetTarget() << endl; - cout << " TargetRadii = (" << targRad[0].meters() << ", " + cout << " TargetRadii = (" << targRad[0].meters() << ", " << targRad[1].meters() << ", " << targRad[2].meters() << ")" << endl; cout << endl; @@ -321,7 +299,7 @@ int main() { cn1.SetTarget(label); targRad = cn1.GetTargetRadii(); cout << " TargetName = " << cn1.GetTarget() << endl; - cout << " TargetRadii = (" << targRad[0].meters() << ", " + cout << " TargetRadii = (" << targRad[0].meters() << ", " << targRad[1].meters() << ", " << targRad[2].meters() << ")" << endl; cout << endl; @@ -334,7 +312,7 @@ int main() { cn1.SetTarget(label); targRad = cn1.GetTargetRadii(); cout << " TargetName = " << cn1.GetTarget() << endl; - cout << " TargetRadii = (" << targRad[0].meters() << ", " + cout << " TargetRadii = (" << targRad[0].meters() << ", " << targRad[1].meters() << ", " << targRad[2].meters() << ")" << endl; cout << endl; @@ -345,7 +323,7 @@ int main() { cn1.SetTarget(label); targRad = cn1.GetTargetRadii(); cout << " TargetName = " << cn1.GetTarget() << endl; - cout << " TargetRadii = (" << targRad[0].meters() << ", " + cout << " TargetRadii = (" << targRad[0].meters() << ", " << targRad[1].meters() << ", " << targRad[2].meters() << ")" << endl; cout << endl; @@ -353,7 +331,7 @@ int main() { cn1.SetTarget(""); targRad = cn1.GetTargetRadii(); cout << " TargetName = " << cn1.GetTarget() << endl; - cout << " TargetRadii = (" << targRad[0].meters() << ", " + cout << " TargetRadii = (" << targRad[0].meters() << ", " << targRad[1].meters() << ", " << targRad[2].meters() << ")" << endl; cout << endl; @@ -361,7 +339,7 @@ int main() { cn1.SetTarget("Mars"); targRad = cn1.GetTargetRadii(); cout << " TargetName = " << cn1.GetTarget() << endl; - cout << " TargetRadii = (" << targRad[0].meters() << ", " + cout << " TargetRadii = (" << targRad[0].meters() << ", " << targRad[1].meters() << ", " << targRad[2].meters() << ")" << endl; cout << endl; @@ -531,108 +509,98 @@ int main() { remove("temp.bin"); remove("temp2.bin"); - cout << "Testing GetCubeGraphNodes\n"; - - QList< ControlCubeGraphNode * > graphnodes = net.GetCubeGraphNodes(); + QList< QString > graphSNs = net.GetCubeSerials(); // Use this to sort the output - QList<QString> sortedSNs; - foreach ( ControlCubeGraphNode * node, graphnodes ) { - sortedSNs.append(node->getSerialNumber()); - } - sort(sortedSNs.begin(), sortedSNs.end()); - foreach ( QString sn, sortedSNs ) { + sort(graphSNs.begin(), graphSNs.end()); + foreach ( QString sn, graphSNs ) { cout << " " << sn << "\n"; } - - cout << "\nTesting getGraphNode: " - << net.getGraphNode("ALPHA")->getSerialNumber() << "\n"; - + + + cout << net.GraphToString() << endl; cout << "\nTesting getEdgeCount: " << net.getEdgeCount() << "\n"; testConnectivity(); cout << "\nTesting take() functionality to take owernship of the points in a ControlNet:" << endl; - cout << "Original control net number of points: " << QString::number(net.GetNumPoints()) << endl; + cout << "Original control net number of points: " << QString::number(net.GetNumPoints()) << endl; + + QList<ControlPoint*> points = net.take(); - QList<ControlPoint*> points = net.take(); - - cout << "Number of points taken out: " << QString::number(points.length()) << endl; - - cout << "Now there should be zero points in the original control net. There are: " - << QString::number(net.GetNumPoints()) << endl; + cout << "Number of points taken out: " << QString::number(points.length()) << endl; - cout << "And zero pointIDs in the original control net. There are: " - << QString::number(net.GetPointIds().length()) << endl; + cout << "Now there should be zero points in the original control net. There are: " + << QString::number(net.GetNumPoints()) << endl; - cout << "And zero cubeGraphNodes in the original control net. There are: " - << QString::number(net.GetCubeGraphNodes().length()) << endl; + cout << "And zero pointIDs in the original control net. There are: " + << QString::number(net.GetPointIds().length()) << endl; - //system("cat unitTest.output | grep -v DateTime > temp.output; mv temp.output unitTest.output"); + //system("cat unitTest.output | grep -v DateTime > temp.output; mv temp.output unitTest.output"); //system("cat unitTest.output | sed -r s/`date +%Y-%m-%dT`\\[0-9:\\]\\{8\\}/2010-08-27T17:10:06/g > temp.output; mv temp.output unitTest.output"); return 0; -#if 0 - - // ------------------------------------------------------------------------- - // Testing the google protocol buffer methods added to the ControlNet class - // SLA 6/30/09 - // ------------------------------------------------------------------------- - - cout << "Enter input cnet: "; - string inNet; - cin >> inNet; - string outFile; - cout << "Enter output file (directory & prefix, no extension): "; - cin >> outFile; - - ControlNet *cn1 = new ControlNet; - cout << "Speed Test for ControlNet ...." << endl << endl; - cout << "\nReading from the ascii file.... " << inNet << endl; - std::clock_t start = std::clock(); -// cn1.ReadControl("/work1/tsucharski/protobuf/isis/nets/cnet.net"); -// cn1->ReadControl("/work1/tsucharski/protobuf/isis/nets/pntreg2.net"); -// cn1->ReadControl("/work1/tsucharski/protobuf/isis/nets/pntreg_combinedparts.net"); - cn1->ReadControl(inNet); - std::cout << ((std::clock() - start) / (double)CLOCKS_PER_SEC) << " seconds \n"; - - cout << "\nWriting to the binary file...." << endl; - start = std::clock(); -// cn1.WritePB("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/cnet.bin"); -// cn1->WritePB("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/pntreg2.bin"); -// cn1->WritePB("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/pntreg_combinedparts.bin"); - cn1->WritePB(outFile + ".bin"); - std::cout << ((std::clock() - start) / (double)CLOCKS_PER_SEC) << " seconds \n"; - delete cn1; - -// ControlNet cn2; - ControlNet *cn2 = new ControlNet; - - cout << "\nReading from the binary file...." << endl; - std::clock_t start2 = std::clock(); -// cn2.ReadPBControl("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/cnet.bin"); -// cn2->ReadPBControl("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/pntreg2.bin"); -// cn2->ReadPBControl("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/pntreg_combinedparts.bin"); - cn2->ReadPBControl(outFile + ".bin"); - std::cout << ((std::clock() - start2) / (double)CLOCKS_PER_SEC) << " seconds \n"; - -// apLat = (*cn2)[2].AprioriLatitude(); -// cout<<"binaryNet AprioriLatitude = "<<apLat<<endl; - -//cout << "\nConverting the binary to Pvl...." << endl; -//std::clock_t start2 = std::clock(); -//cn1.ConvertBinToPvl(); -//std::cout<< ( ( std::clock() - start2 ) / (double)CLOCKS_PER_SEC ) <<" seconds \n"; - - - - cout << "\nWriting to the Pvl file...." << endl; - std::clock_t start3 = std::clock(); -// cn2.Write("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/cnet.pvl"); -// cn2->Write("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/pntreg2.pvl"); -// cn2->Write("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/pntreg_combinedparts.pvl"); - cn2->Write(outFile + ".pvl"); - std::cout << ((std::clock() - start3) / (double)CLOCKS_PER_SEC) << " seconds \n"; - -#endif + #if 0 + + // ------------------------------------------------------------------------- + // Testing the google protocol buffer methods added to the ControlNet class + // SLA 6/30/09 + // ------------------------------------------------------------------------- + + cout << "Enter input cnet: "; + string inNet; + cin >> inNet; + string outFile; + cout << "Enter output file (directory & prefix, no extension): "; + cin >> outFile; + + ControlNet *cn1 = new ControlNet; + cout << "Speed Test for ControlNet ...." << endl << endl; + cout << "\nReading from the ascii file.... " << inNet << endl; + std::clock_t start = std::clock(); + // cn1.ReadControl("/work1/tsucharski/protobuf/isis/nets/cnet.net"); + // cn1->ReadControl("/work1/tsucharski/protobuf/isis/nets/pntreg2.net"); + // cn1->ReadControl("/work1/tsucharski/protobuf/isis/nets/pntreg_combinedparts.net"); + cn1->ReadControl(inNet); + std::cout << ((std::clock() - start) / (double)CLOCKS_PER_SEC) << " seconds \n"; + + cout << "\nWriting to the binary file...." << endl; + start = std::clock(); + // cn1.WritePB("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/cnet.bin"); + // cn1->WritePB("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/pntreg2.bin"); + // cn1->WritePB("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/pntreg_combinedparts.bin"); + cn1->WritePB(outFile + ".bin"); + std::cout << ((std::clock() - start) / (double)CLOCKS_PER_SEC) << " seconds \n"; + delete cn1; + + // ControlNet cn2; + ControlNet *cn2 = new ControlNet; + + cout << "\nReading from the binary file...." << endl; + std::clock_t start2 = std::clock(); + // cn2.ReadPBControl("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/cnet.bin"); + // cn2->ReadPBControl("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/pntreg2.bin"); + // cn2->ReadPBControl("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/pntreg_combinedparts.bin"); + cn2->ReadPBControl(outFile + ".bin"); + std::cout << ((std::clock() - start2) / (double)CLOCKS_PER_SEC) << " seconds \n"; + + // apLat = (*cn2)[2].AprioriLatitude(); + // cout<<"binaryNet AprioriLatitude = "<<apLat<<endl; + + //cout << "\nConverting the binary to Pvl...." << endl; + //std::clock_t start2 = std::clock(); + //cn1.ConvertBinToPvl(); + //std::cout<< ( ( std::clock() - start2 ) / (double)CLOCKS_PER_SEC ) <<" seconds \n"; + + + + cout << "\nWriting to the Pvl file...." << endl; + std::clock_t start3 = std::clock(); + // cn2.Write("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/cnet.pvl"); + // cn2->Write("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/pntreg2.pvl"); + // cn2->Write("/work1/tsucharski/protobuf/isis/nets/testMultiMsgs/pntreg_combinedparts.pvl"); + cn2->Write(outFile + ".pvl"); + std::cout << ((std::clock() - start3) / (double)CLOCKS_PER_SEC) << " seconds \n"; + + #endif } diff --git a/isis/src/control/objs/ControlNetVitals/ControlNetVitals.cpp b/isis/src/control/objs/ControlNetVitals/ControlNetVitals.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f6b66f80ca202be898aa77b750cd0d01aba3427 --- /dev/null +++ b/isis/src/control/objs/ControlNetVitals/ControlNetVitals.cpp @@ -0,0 +1,909 @@ +#include "ControlNetVitals.h" + +#include <QDateTime> +#include <QList> +#include <QPair> +#include <QVariant> + +#include "IException.h" +#include "IString.h" +#include "ControlNet.h" +#include "ControlPoint.h" +#include "ControlMeasure.h" + +namespace Isis { + + + /** + * Constructs a ControlNetVitals object from a ControlNet. + * once complete, it calls the validate() method to evaluate the current status + * of the newly ingested Control Network. + * + * @param cnet The Control Network that we will be tracking vitals for. + */ + ControlNetVitals::ControlNetVitals(ControlNet *cnet) { + m_controlNet = cnet; + + initializeVitals(); + + connect(cnet, SIGNAL(networkModified(ControlNet::ModType)), + this, SLOT(validateNetwork(ControlNet::ModType))); + + connect(cnet, SIGNAL(newPoint(ControlPoint*)), + this, SLOT(addPoint(ControlPoint*))); + connect(cnet, SIGNAL(pointModified(ControlPoint *, ControlPoint::ModType, QVariant, QVariant)), + this, SLOT(pointModified(ControlPoint *, ControlPoint::ModType, QVariant, QVariant))); + connect(cnet, SIGNAL(pointDeleted(ControlPoint*)), + this, SLOT(deletePoint(ControlPoint*))); + + connect(cnet, SIGNAL(newMeasure(ControlMeasure*)), + this, SLOT(addMeasure(ControlMeasure*))); + connect(cnet, SIGNAL(measureModified(ControlMeasure *, ControlMeasure::ModType, QVariant, QVariant)), + this, SLOT(measureModified(ControlMeasure *, ControlMeasure::ModType, QVariant, QVariant))); + connect(cnet, SIGNAL(measureRemoved(ControlMeasure*)), + this, SLOT(deleteMeasure(ControlMeasure*))); + + validate(); + } + + + /** + * This will initialize all necessary values and set up the point measure and + * image measure QMaps appropriately. + * + */ + void ControlNetVitals::initializeVitals() { + + m_islandList = m_controlNet->GetSerialConnections(); + + m_numPoints = 0; + m_numPointsIgnored = 0; + m_numPointsLocked = 0; + m_numMeasures = m_controlNet->GetNumMeasures(); + + m_pointMeasureCounts.clear(); + m_imageMeasureCounts.clear(); + m_pointTypeCounts.clear(); + + m_pointTypeCounts.insert(ControlPoint::Free, 0); + m_pointTypeCounts.insert(ControlPoint::Constrained, 0); + m_pointTypeCounts.insert(ControlPoint::Fixed, 0); + + foreach(ControlPoint* point, m_controlNet->GetPoints()) { + addPoint(point); + } + + foreach(QString serial, m_controlNet->GetCubeSerials()) { + int numValidMeasures = m_controlNet->GetNumberOfValidMeasuresInImage(serial); + if ( !m_imageMeasureCounts.contains(numValidMeasures) ) { + m_imageMeasureCounts.insert(numValidMeasures, 1); + } + else { + m_imageMeasureCounts[numValidMeasures]++; + } + } + } + + + /** + * This method is designed to be called whenever a modification is made to the network, + * or any of it's control points or measures. It receives all of the components that + * make up the history entry (the comment, the ID of what was modified, oldValue, newValue) + * and emits them along with a timestamp of when the modification was made. + * + * The historyEntry() will pass these values on to the listening SLOT in the health monitor + * widget so that it can be displayed in the history table. + * + * @param entry The history comment that includes what modification was made. + * @param id The ID of the object modified. This can be a point id, measure serial, or net id. + * @param oldValue The oldValue the object had before the modification. + * @param newValue The newValue the object had after its modification. + */ + void ControlNetVitals::emitHistoryEntry(QString entry, QString id, QVariant oldValue, QVariant newValue) { + emit historyEntry(entry, id, oldValue, newValue, QDateTime::currentDateTime().toString()); + } + + + /** + * This SLOT is designed to intercept the newPoint() signal emitted from a ControlNetwork + * whenever a new point has been added. It observes the Control Point and increments the + * appropriate internal counters to reflect the addition of this new point. + * + * Once complete, we then call the validate() method to re-validate the status and + * details of the Control Network. + * + * Unlike deletePoint(), this method does modify counters based on measures + * because the ControlNet does not emit separate measureAdded signals for + * efficiency reasons. + * + * @param point The ControlPoint being added to the network. + */ + void ControlNetVitals::addPoint(ControlPoint *point) { + + emitHistoryEntry("Control Point Added", point->GetId(), "", ""); + m_numPoints++; + + if (point->IsIgnored()) { + m_numPointsIgnored++; + return; + } + + if (point->IsEditLocked()) { + m_numPointsLocked++; + } + + m_pointTypeCounts[point->GetType()]++; + + int numValidMeasures = point->GetNumValidMeasures(); + if ( !m_pointMeasureCounts.contains(numValidMeasures) ) { + m_pointMeasureCounts.insert(numValidMeasures, 1); + } + + else { + m_pointMeasureCounts[numValidMeasures]++; + } + + m_numMeasures = m_controlNet->GetNumMeasures(); + validate(); + } + + + /** + * This SLOT is designed to receive a signal emitted from the Control Network + * whenever a modification is made to a Control Point. This SLOT receives the + * ControlPoint that was modified, as well with the ControlPoint::ModType enum + * indicating what type of modification was made to the Control Point. + * + * We then increment or decrement the appropriate internal counters based on which type + * of modification was made to the Control Point. + * + * Once complete, we then call the validate() method to re-validate the status and + * details of the Control Network. + * + * @param point The Control Point that was modified in the observed Control Network. + * @param type The type of modification that was made to the Control Point. + * @param oldValue The old value (if any) of whatever modification was made to the Control Point. + * @param newValue The new value (if any) of whatever modification was made to the Control Point. + */ + void ControlNetVitals::pointModified(ControlPoint *point, ControlPoint::ModType type, + QVariant oldValue, QVariant newValue) { + + QString historyEntry; + + switch(type) { + case ControlPoint::EditLockModified: + + historyEntry = "Point Edit Lock Modified"; + + if (oldValue.toBool()) { + m_numPointsLocked--; + } + + if (newValue.toBool()) { + m_numPointsLocked++; + } + + emitHistoryEntry( historyEntry, point->GetId(), + oldValue, newValue ); + + break; + + case ControlPoint::IgnoredModified: + + historyEntry = "Point Ignored Modified"; + + if (oldValue.toBool()) { + m_numPointsIgnored--; + if (point->IsEditLocked()) { + m_numPointsLocked++; + } + m_pointTypeCounts[point->GetType()]++; + int numValidMeasures = point->GetNumValidMeasures(); + if ( !m_pointMeasureCounts.contains(numValidMeasures) ) { + m_pointMeasureCounts.insert(numValidMeasures, 1); + } + else { + m_pointMeasureCounts[numValidMeasures]++; + } + } + + if (newValue.toBool()) { + m_numPointsIgnored++; + if (point->IsEditLocked()) { + m_numPointsLocked--; + } + m_pointTypeCounts[point->GetType()]--; + int numValidMeasures = point->GetNumValidMeasures(); + if ( --m_pointMeasureCounts[numValidMeasures] < 1 ) { + m_pointMeasureCounts.remove(numValidMeasures); + } + } + + emitHistoryEntry( historyEntry, point->GetId(), + oldValue, newValue ); + + break; + + case ControlPoint::TypeModified: + + historyEntry = "Point Type Modified"; + + m_pointTypeCounts[ControlPoint::PointType(oldValue.toInt())]--; + m_pointTypeCounts[ControlPoint::PointType(newValue.toInt())]++; + + emitHistoryEntry( historyEntry, point->GetId(), + ControlPoint::PointTypeToString(ControlPoint::PointType(oldValue.toInt())), + ControlPoint::PointTypeToString(ControlPoint::PointType(newValue.toInt())) ); + + break; + + default: + // no operation + break; + } + + validate(); + + } + + + /** + * This method is designed to return the Control Point with the associated point id + * from the Control Network. + * + * @param id The Point ID of the control point to be fetched. + * @return The Control Point with the associated point id. + */ + ControlPoint* ControlNetVitals::getPoint(QString id) { + return m_controlNet->GetPoint(id); + } + + + /** + * This SLOT is designed to intercept the removePoint() signal emitted by a Control Network + * whenever a point is deleted. It observes the to-be deleted point and decrements the + * appropriate internal counters to reflect the removal of this point. + * + * This does not modify any counters based on the measures in the point + * because separate measureDeleted signals will be emitted by the ControlNet. + * addPoint does add modify counters based on measures because ControlNet does + * not emit separate measureAdded signals for efficiency reasons. + * + * Once complete, we then call the validate() method to re-validate the status and + * details of the Control Network. + * + * @param point The Control Point being deleted from the Control Network. + */ + void ControlNetVitals::deletePoint(ControlPoint *point) { + + emitHistoryEntry("Control Point Deleted", point->GetId(), "", ""); + m_numPoints--; + + if (point->IsIgnored()) { + m_numPointsIgnored--; + validate(); + return; + } + if (point->IsEditLocked()) { + m_numPointsLocked--; + } + + m_pointTypeCounts[point->GetType()]--; + + int numValidMeasures= point->GetNumValidMeasures(); + if ( --m_pointMeasureCounts[numValidMeasures] < 1 ) { + m_pointMeasureCounts.remove(numValidMeasures); + } + + validate(); + } + + + /** + * This SLOT is designed to intercept the newMeasure() signal emitted by a Control Network + * whenever a measure is added to one of it's Control Points. + * It grabs the parent Control Point of the Measure and decrements the pointMeasureCount QMap + * at the old measure count for the Control Point and increments the pointMeasureCount at the + * new measure count for the Control Point to reflect the addition of this measure. + * + * This does not modify any counters based on the measures in the point + * because separate measureDeleted signals will be emitted by the ControlNet. + * addPoint does add modify counters based on measures because ControlNet does + * not emit separate measureAdded signals for efficiency reasons. + * + * Once complete, we then call the validate() method to re-validate the status and + * details of the Control Network. + * + * @param measure The Control Measure being added to a Control Point in the network. + */ + void ControlNetVitals::addMeasure(ControlMeasure *measure) { + emitHistoryEntry("Control Measure Added", measure->GetCubeSerialNumber(), "", ""); + + m_numMeasures++; + + addMeasureToCounts(measure); + + validate(); + } + + + /** + * This SLOT is designed to intercept the measureModified() signal emitted by a Control Network + * whenever a measure is modified in one of it's Control Points. This SLOT receives the + * ControlMeasure that was modified, as well with the ControlMeasure::ModType enum + * indicating what type of modification was made to the Control Measure. The appropriate methods + * are called depending on which modification was made. + * + * Once complete, we then call the validate() method to re-validate the status and + * details of the Control Network. + * + * @param point The Control Measure that was modified in the observed Control Network. + * @param type The type of modification that was made to the Control Measure. + * @param oldValue The old value (if any) of whatever modification was made to the Control Measure. + * @param newValue The new value (if any) of whatever modification was made to the Control Measure. + */ + void ControlNetVitals::measureModified(ControlMeasure *measure, ControlMeasure::ModType type, QVariant oldValue, QVariant newValue) { + + QString historyEntry; + + switch (type) { + case ControlMeasure::IgnoredModified: + + historyEntry = "Measure Ignored Modified"; + + if ( !oldValue.toBool() && newValue.toBool() ) { + return removeMeasureFromCounts(measure); + } + else if ( oldValue.toBool() && !newValue.toBool() ) { + return addMeasureToCounts(measure); + } + break; + + default: + // No operation. + break; + } + + ControlNetVitals::emitHistoryEntry(historyEntry, measure->GetCubeSerialNumber(), "", ""); + validate(); + } + + + /** + * This SLOT is designed to intercept the measureRemoved() signal emitted by a Control Network + * whenever a Control Measure is deleted. It observes the to-be deleted point and decrements the + * appropriate internal counters to reflect the removal of this Control Measure. + * + * Once complete, we then call the validate() method to re-validate the status and + * details of the Control Network. + * + * @param point The Control Measure being deleted from a Control Point in the Control Network. + */ + void ControlNetVitals::deleteMeasure(ControlMeasure *measure) { + + emitHistoryEntry("Control Measure Deleted", measure->GetCubeSerialNumber(), "", ""); + + m_numMeasures--; + + removeMeasureFromCounts(measure); + + validate(); + } + + + /** + * Add a measure to the internal counters + * + * @param measure The measure to add + */ + void ControlNetVitals::addMeasureToCounts(ControlMeasure *measure) { + ControlPoint *point = measure->Parent(); + if (point) { + // By this time, the measure has been added to its parent point, so the + // old count is the current count minus one. + int numValidMeasures = point->GetNumValidMeasures(); + if ( --m_pointMeasureCounts[numValidMeasures] < 1 ) { + m_pointMeasureCounts.remove(numValidMeasures); + } + if ( !m_pointMeasureCounts.contains(numValidMeasures + 1) ) { + m_pointMeasureCounts.insert(numValidMeasures + 1, 1); + } + else { + m_pointMeasureCounts[numValidMeasures + 1]++; + } + } + + QString serial = measure->GetCubeSerialNumber(); + int numValidMeasures = m_controlNet->GetNumberOfValidMeasuresInImage(serial); + if ( --m_imageMeasureCounts[numValidMeasures - 1] < 1 ) { + m_imageMeasureCounts.remove(numValidMeasures); + } + if ( !m_imageMeasureCounts.contains(numValidMeasures) ) { + m_imageMeasureCounts.insert(numValidMeasures, 1); + } + else { + m_imageMeasureCounts[numValidMeasures]++; + } + } + + + /** + * Remove a measure from the internal counters + * + * @param measure The measure to remove + */ + void ControlNetVitals::removeMeasureFromCounts(ControlMeasure *measure) { + ControlPoint *point = measure->Parent(); + if (point) { + // By this time, the measure is still a valid measure in the parent control point. + int numValidMeasures = point->GetNumValidMeasures(); + + if ( --m_pointMeasureCounts[numValidMeasures] < 1 ) { + m_pointMeasureCounts.remove(numValidMeasures); + } + if ( !m_pointMeasureCounts.contains(numValidMeasures - 1) ) { + m_pointMeasureCounts.insert(numValidMeasures - 1, 1); + } + else { + m_pointMeasureCounts[numValidMeasures - 1]++; + } + } + + QString serial = measure->GetCubeSerialNumber(); + int numValidMeasures = m_controlNet->GetNumberOfValidMeasuresInImage(serial); + + if ( --m_imageMeasureCounts[numValidMeasures] < 1 ) { + m_imageMeasureCounts.remove(numValidMeasures); + } + + if ( !m_imageMeasureCounts.contains(numValidMeasures - 1) ) { + m_imageMeasureCounts.insert(numValidMeasures - 1, 1); + } + else { + m_imageMeasureCounts[numValidMeasures - 1]++; + } + } + + + /** + * This SLOT is designed to intercept the networkModified() signal emitted by a Control Network + * whenever a modification is made to the network. This SLOT receives the ControlNet::ModType + * enum indicating what type of modication was made to the Control Network. It then acts + * based on what type of change was made. + * + * Once complete, we then call the validate() method to re-validate the status and + * details of the Control Network. + * + * @param point The type of modification that was made to the observed Control Network. + */ + void ControlNetVitals::validateNetwork(ControlNet::ModType type) { + + QString historyEntry; + + switch (type) { + case ControlNet::Swapped: + emitHistoryEntry("Control Net Swapped", m_controlNet->GetNetworkId(), "", ""); + initializeVitals(); + break; + case ControlNet::GraphModified: + emitHistoryEntry("Control Net Graph Modified", m_controlNet->GetNetworkId(), "", ""); + m_islandList = m_controlNet->GetSerialConnections(); + break; + default: + // No operation. + break; + } + validate(); + } + + + /** + * De-constructor + */ + ControlNetVitals::~ControlNetVitals() { + } + + + /** + * This method is designed to return true if islands exist in the ControlNet Graph + * and False otherwise. + * + * @return True if islands exist, False otherwise. + */ + bool ControlNetVitals::hasIslands() { + return numIslands() > 1; + } + + + /** + * This method is designed to return the number of islands that exist in the + * ControlNet Graph. + * + * @return The number of islands present in the ControlNet Graph. + */ + int ControlNetVitals::numIslands() { + return m_islandList.size(); + } + + + /** + * This method is designed to return a QList containing each island present in the ControlNet. + * + * Each island is composed of another QList containing the cube serials for all cubes in that island. + * + * @return A QList containing a QList of cube serials for each island present in the Control Net. + */ + const QList< QList<QString> > &ControlNetVitals::getIslands() { + return m_islandList; + } + + + /** + * This method is designed to return the number of points in the Control Network. + * + * @return The number of points in the Control Network. + */ + int ControlNetVitals::numPoints() { + return m_numPoints; + } + + + /** + * This method is designed to return the number of ignored points in the Control Network. + * + * @return The number of ignored points in the Control Network. + */ + int ControlNetVitals::numIgnoredPoints() { + return m_numPointsIgnored; + } + + + /** + * This method is designed to return the number of edit locked points in the Control Network. + * + * @return The number of edit locked points in the Control Network. + */ + int ControlNetVitals::numLockedPoints() { + return m_numPointsLocked; + } + + + /** + * This method is designed to return the number of fixed points in the Control Network. + * + * @return The number of fixed points in the Control Network. + */ + int ControlNetVitals::numFixedPoints() { + return m_pointTypeCounts[ControlPoint::Fixed]; + } + + + /** + * This method is designed to return the number of constrained points in the Control Network. + * + * @return The number of constrained points in the Control Network. + */ + int ControlNetVitals::numConstrainedPoints() { + return m_pointTypeCounts[ControlPoint::Constrained]; + } + + + /** + * This method is designed to return the number of free points in the Control Network. + * + * @return The number of free points in the Control Network. + */ + int ControlNetVitals::numFreePoints() { + return m_pointTypeCounts[ControlPoint::Free]; + } + + + /** + * This method is designed to return the number of points that fall below a measure threshold. + * + * For instance, a measure threshold of 3 would return all points with less than 3 measures. + * + * @param num The number of measures a point needs to have to meet the threshold. + * @return The number of points with number of measures less than the threshold. + */ + int ControlNetVitals::numPointsBelowMeasureThreshold(int num) { + int count = 0; + + QMap<int, int>::const_iterator i = m_pointMeasureCounts.constBegin(); + while (i != m_pointMeasureCounts.constEnd()) { + if (i.key() >= num ) { + break; + } + count += i.value(); + ++i; + } + + return count; + } + + + /** + * This method is designed to return the number of images in the Control Network. + * + * @return The number of images in the Control Network. + */ + int ControlNetVitals::numImages() { + return m_controlNet->GetCubeSerials().size(); + } + + + /** + * This method is designed to return the number of measures in the Control Network. + * + * @return The number of measures in the Control Network. + */ + int ControlNetVitals::numMeasures() { + return m_numMeasures; + } + + + /** + * This method is designed to return the number of images that fall below a measure threshold. + * + * For instance, a measure threshold of 3 would return all images with less than 3 measures. + * + * @param num The number of measures an image needs to have to meet the threshold. + * @return The number of images with number of measures less than the threshold. + */ + int ControlNetVitals::numImagesBelowMeasureThreshold(int num) { + int count = 0; + + QMap<int, int>::const_iterator i = m_imageMeasureCounts.constBegin(); + while (i != m_imageMeasureCounts.constEnd()) { + if (i.key() >= num ) { + break; + } + count += i.value(); + ++i; + } + return count; + } + + + // REFACTOR + /** + * This method is designed to return the number of images that fall below a hull tolerance. + * + * For instance, a tolerance of .75 would return all images with a hull tolerance of < 75%. + * + * @param num The number of measures an image needs to have to meet the threshold. + * @return The number of images with number of measures less than the threshold. + */ + int ControlNetVitals::numImagesBelowHullTolerance(int tolerance) { + return 0; + } + + + /** + * This method is designed to return all cube serials present in the Control Network. + * + * @return A QList<QString> containing all cube serials in the Control Network. + */ + QList<QString> ControlNetVitals::getCubeSerials() { + return m_controlNet->GetCubeSerials(); + } + + + /** + * This method is designed to return all points in the Control Network. + * + * @return A QList<ControlPoint*> containing all points in the Control Network. + */ + QList<ControlPoint*> ControlNetVitals::getAllPoints() { + return m_controlNet->GetPoints(); + } + + + /** + * This method is designed to return all ignored points in the Control Network. + * + * @return A QList<ControlPoint*> containing all ignored points in the Control Network. + */ + QList<ControlPoint*> ControlNetVitals::getIgnoredPoints() { + QList<ControlPoint*> ignoredPoints; + foreach(ControlPoint* point, m_controlNet->GetPoints()) { + if (point->IsIgnored()) ignoredPoints.append(point); + } + return ignoredPoints; + } + + + /** + * This method is designed to return all edit locked points in the Control Network. + * + * @return A QList<ControlPoint*> containing all edit locked points in the Control Network. + */ + QList<ControlPoint*> ControlNetVitals::getLockedPoints() { + QList<ControlPoint*> lockedPoints; + foreach(ControlPoint* point, m_controlNet->GetPoints()) { + if (!point->IsIgnored() && point->IsEditLocked()) lockedPoints.append(point); + } + return lockedPoints; + } + + + /** + * This method is designed to return all fixed points in the Control Network. + * + * @return A QList<ControlPoint*> containing all fixed points in the Control Network. + */ + QList<ControlPoint*> ControlNetVitals::getFixedPoints() { + QList<ControlPoint*> fixedPoints; + foreach(ControlPoint* point, m_controlNet->GetPoints()) { + if (!point->IsIgnored() && point->GetType() == ControlPoint::Fixed) fixedPoints.append(point); + } + return fixedPoints; + } + + + /** + * This method is designed to return all constrained points in the Control Network. + * + * @return A QList<ControlPoint*> containing all constrained points in the Control Network. + */ + QList<ControlPoint*> ControlNetVitals::getConstrainedPoints() { + QList<ControlPoint*> constrainedPoints; + foreach(ControlPoint* point, m_controlNet->GetPoints()) { + if (!point->IsIgnored() && point->GetType() == ControlPoint::Constrained) constrainedPoints.append(point); + } + return constrainedPoints; + } + + + /** + * This method is designed to return all free points in the Control Network. + * + * @return A QList<ControlPoint*> containing all free points in the Control Network. + */ + QList<ControlPoint*> ControlNetVitals::getFreePoints() { + QList<ControlPoint*> freePoints; + foreach(ControlPoint* point, m_controlNet->GetPoints()) { + if (!point->IsIgnored() && point->GetType() == ControlPoint::Free) freePoints.append(point); + } + return freePoints; + } + + + /** + * This method is designed to return all points that fall below a measure threshold. + * + * For instance, a measure threshold of 3 would return all points with less than 3 measures. + * + * @param num The number of measures a point needs to have to meet the threshold. + * @return All of points with number of measures less than the threshold. + */ + QList<ControlPoint*> ControlNetVitals::getPointsBelowMeasureThreshold(int num) { + QList<ControlPoint*> belowThreshold; + foreach(ControlPoint* point, m_controlNet->GetPoints()) { + if (!point->IsIgnored() && point->GetNumMeasures() < num) belowThreshold.append(point); + } + return belowThreshold; + } + + + /** + * This method is designed to return a QList containing cube serials for all images + * that fall below a measure threshold. + * + * For instance, a measure threshold of 3 would return all images with less than 3 measures. + * + * @param num The number of measures an image needs to have to meet the threshold. + * @return A QList<QString> containing all images with number of measures less than the threshold. + */ + QList<QString> ControlNetVitals::getImagesBelowMeasureThreshold(int num) { + QList<QString> imagesBelowThreshold; + foreach(QString serial, m_controlNet->GetCubeSerials()) { + if (m_controlNet->GetValidMeasuresInCube(serial).size() < num) { + imagesBelowThreshold.append(serial); + } + } + return imagesBelowThreshold; + } + + + /** + * This method is designed to return a QList containing cube serials for all images + * that fall below a convex hull tolerance threshold. + * + * For instance, a tolerance of .75 would return all images with a hull tolerance less than 75%. + * + * @param num The hull tolerance (decimal percent) an image needs to meet the threshold. + * @return A QList<QString> containing all images with a hull tolerance below the threshold. + */ + QList<QString> ControlNetVitals::getImagesBelowHullTolerance(int num) { + QList<QString> list; + return list; + } + + + /** + * This method is designed to return the current status of the network. + * + * The possible values are "Healthy!", "Weak!", "Broken!" + * + * @return A QString indicating the status of the Control Network. + */ + QString ControlNetVitals::getStatus() { + return m_status; + } + + + /** + * This method is designed to return details for the status of the network. + * + * This QString could contain several details if the status is weak, if more than one + * factor contribute to the weakness of the network. Details are separated by newline '\n' + * in the QString. + * + * @return A QString containing details for the status of the Control Network. + */ + QString ControlNetVitals::getStatusDetails() { + return m_statusDetails; + } + + + /** + * This method is designed to return networkId of the observed Control Network. + * + * It is a wrapper for the ControlNet::GetNetworkId() call of the observed Control Network. + * + * @return A QString containing the NetworkId of the Control Network. + */ + QString ControlNetVitals::getNetworkId() { + return m_controlNet->GetNetworkId(); + } + + + /** + * This method is designed to evaluate the current vitals of the network to determine + * if any weaknesses are present and update the status of the network. + * + * The network status is split into 3 states: Healthy, Weak, and Broken. + * + * Healthy - A network is healthy if there are no weaknesses found and it is not broken. + * Weak - A network is weak if it has points that fall below the measure threshold, + * A network is weak if it has images that fall below the measure threshold, + * A network is weak if it has images that fall below a Convex Hull tolerance. + * Broken - A network is broken if it has more than 1 island. + */ + void ControlNetVitals::validate() { + + QString status = ""; + QString details = ""; + if (hasIslands()) { + status = "Broken!"; + details = "This network has " + toString(numIslands()) + " islands."; + } + else { + + if (numPointsBelowMeasureThreshold() > 0) { + status = "Weak!"; + details += "This network has " + toString(numPointsBelowMeasureThreshold()) + " point(s) with less than 3 measures\n"; + } + + if (numImagesBelowMeasureThreshold() > 0) { + status = "Weak!"; + details += "This network has " + toString(numImagesBelowMeasureThreshold()) + " image(s) with less than 3 measures\n"; + } + + if (numImagesBelowHullTolerance() > 0) { + status = "Weak!"; + details += "This network has " + toString(numImagesBelowHullTolerance()) + " image(s) below the Convex Hull Tolerance of 75%\n"; + } + + if (status.isEmpty()) { + status = "Healthy!"; + details = "This network is healthy."; + } + } + m_status = status; + m_statusDetails = details; + emit networkChanged(); + } + +} diff --git a/isis/src/control/objs/ControlNetVitals/ControlNetVitals.h b/isis/src/control/objs/ControlNetVitals/ControlNetVitals.h new file mode 100644 index 0000000000000000000000000000000000000000..b0528c100e887df9bbf218d8c02ce85448760dc5 --- /dev/null +++ b/isis/src/control/objs/ControlNetVitals/ControlNetVitals.h @@ -0,0 +1,167 @@ +#ifndef ControlNetVitals_h +#define ControlNetVitals_h +/** + * @file + * $Revision: 1.2 $ + * $Date: 2010/06/28 17:15:01 $ + * + * Unless noted otherwise, the portions of Isis written by the USGS are + * public domain. See individual third-party library and package descriptions + * for intellectual property information, user agreements, and related + * information. + * + * Although Isis has been used by the USGS, no warranty, expressed or + * implied, is made by the USGS as to the accuracy and functioning of such + * software and related material nor shall the fact of distribution + * constitute any such warranty, and no responsibility is assumed by the + * USGS in connection therewith. + * + * For additional information, launch + * $ISISROOT/doc/documents/Disclaimers/Disclaimers.html + * in a browser or see the Privacy & Disclaimers page on the Isis website, + * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on + * http://www.usgs.gov/privacy.html. + */ + +#include <QStringList> + +#include "ControlMeasure.h" +#include "ControlNet.h" +#include "ControlPoint.h" + +namespace Isis { + class ControlNet; + + + /** + * + * @brief ControlNetVitals + * + * This class is designed to represent the health of a control network. + * It utilizes signals and slots to listen for changes in an observed Control Network and + * re-evaluates the health of a network whenever a change is made. + * It tracks several statistics, and is intended to be the back-end for the ControlHealthMonitorWidget + * that is located in IPCE. + * + * The ControlNetVitals class keeps track of several member variables that are a running counter + * for network statistics in regard to the health of the observed network. It creates these + * variables upon intialization and references these internal variables when returning certain + * statistics about a Control Network that can't be accessed by wrapper methods for the network itself. + * It then listens for specific signals to be emitted whenever a change is made to the network + * to update it's internal counters with respect to that change. + * + * @author 2018-05-28 Adam Goins + * + * @internal + * @history 2018-05-28 Adam Goins - Initial Creation. + * @history 2018-06-14 Adam Goins & Jesse Maple - Refactored method calls and Signal/Slot usage. + * @history 2018-06-15 Adam Goins - Added documentation. + * @history 2018-06-25 Kristin Berry - Fixed problem with getImagesBelowMeasureThreshold().size() + * not matching numImagesBelowMeasureThreshold(). Fixed a similar + * problem with numPointsBelowMeasureThreshold(). + * @history 2018-07-03 Jesse Mapel - Fixed deleting control points not properly updating the + * point counters. + */ + class ControlNetVitals : public QObject { + Q_OBJECT + + public: + ControlNetVitals(ControlNet *net); + virtual ~ControlNetVitals(); + + void initializeVitals(); + + bool hasIslands(); + int numIslands(); + const QList< QList<QString> > &getIslands(); + + ControlPoint *getPoint(QString id); + + int numPoints(); + int numIgnoredPoints(); + int numLockedPoints(); + int numFixedPoints(); + int numConstrainedPoints(); + int numFreePoints(); + int numPointsBelowMeasureThreshold(int num=3); + + int numImages(); + int numMeasures(); + int numImagesBelowMeasureThreshold(int num=3); + int numImagesBelowHullTolerance(int tolerance=75); + + QList<QString> getCubeSerials(); + QList<ControlPoint*> getAllPoints(); + QList<ControlPoint*> getIgnoredPoints(); + QList<ControlPoint*> getLockedPoints(); + QList<ControlPoint*> getFixedPoints(); + QList<ControlPoint*> getConstrainedPoints(); + QList<ControlPoint*> getFreePoints(); + QList<ControlPoint*> getPointsBelowMeasureThreshold(int num=3); + + QList<QString> getImagesBelowMeasureThreshold(int num=3); + QList<QString> getImagesBelowHullTolerance(int num=75); + + QString getNetworkId(); + QString getStatus(); + QString getStatusDetails(); + + void emitHistoryEntry(QString entry, QString id, QVariant oldValue, QVariant newValue); + + signals: + void networkChanged(); + void historyEntry(QString, QString, QVariant, QVariant, QString); + + public slots: + void validate(); + void validateNetwork(ControlNet::ModType); + void addPoint(ControlPoint *); + void pointModified(ControlPoint *, ControlPoint::ModType, QVariant, QVariant); + void deletePoint(ControlPoint *); + void addMeasure(ControlMeasure *); + void measureModified(ControlMeasure *, ControlMeasure::ModType, QVariant, QVariant); + void deleteMeasure(ControlMeasure *); + + + private: + void addMeasureToCounts(ControlMeasure *measure); + void removeMeasureFromCounts(ControlMeasure *measure); + + //! The Control Network that the vitals class is observing. + ControlNet *m_controlNet; + + //! The string representing the status of the net. Healthy, Weak, or Broken. + QString m_status; + //! The string providing details into the status of the network. + QString m_statusDetails; + + //! A QList containing every island in the net. Each island consists of a QList containing + //! All cube serials for that island. + QList< QList< QString > > m_islandList; + + //! The measureCount maps track how many points/images have how many measures. + //! For instance, if I wanted to know how many points have 3 measures I would query + //! the m_pointMeasureCounts with a key of 3 and it would return how many points + //! have 3 measures. + QMap<int, int> m_pointMeasureCounts; + //! The same is true for imageMeasureCounts, except for images. + QMap<int, int> m_imageMeasureCounts; + + //! The pointTypeCounts operates in the same fashion as the above two, except + //! that the key would be the ControlPoint::PointType you're searching for. + //! For instance, if I wanted to know how many points were fixed I would query + //! This map at key ControlPoint::Fixed and it would return how many fixed points there are. + QMap<ControlPoint::PointType, int> m_pointTypeCounts; + + //! The number of points in the network. + int m_numPoints; + //! The number of ignored points in the network. + int m_numPointsIgnored; + //! The number of edit locked points in the network. + int m_numPointsLocked; + //! The number of measures in the network. + int m_numMeasures; + }; +}; + +#endif diff --git a/isis/src/control/objs/ControlNetVitals/ControlNetVitals.truth b/isis/src/control/objs/ControlNetVitals/ControlNetVitals.truth new file mode 100644 index 0000000000000000000000000000000000000000..622e95ba5ae334564e92bdacdd5e1a2eff00579e --- /dev/null +++ b/isis/src/control/objs/ControlNetVitals/ControlNetVitals.truth @@ -0,0 +1,86 @@ +Testing Control Net Vitals + +Loading Network +Calculating Network Vitals +Network ID: "LROC_NAC_LRPAIR_AUTO" +Network Status: "Weak!" +Status Details: "This network has 4 image(s) with less than 3 measures\n" +Network has additional islands? no +Number of islands in network: 1 +Serials in island 0 + "LRO/1/274847978:28626/NACL" + "LRO/1/274847978:28626/NACR" + "LRO/1/274868345:16174/NACR" + "LRO/1/274888710:05688/NACR" + "LRO/1/274909074:43699/NACR" + "LRO/1/277164494:04377/NACR" + "LRO/1/277184863:36490/NACR" + "LRO/1/277205233:08310/NACR" + "LRO/1/277225597:08310/NACL" + "LRO/1/277245961:32558/NACL" + "LRO/1/277266323:25349/NACL" + "LRO/1/285452254:35179/NACL" + "LRO/1/290182186:06999/NACL" + "LRO/1/290182186:06999/NACR" + "LRO/1/292537538:63360/NACR" + "LRO/1/300686942:48419/NACL" + "LRO/1/300700514:53662/NACL" + "LRO/1/300700514:53662/NACR" + "LRO/1/300714095:63575/NACL" + "LRO/1/300714095:63575/NACR" + "LRO/1/300727653:10001/NACL" + "LRO/1/300727653:10001/NACR" + "LRO/1/300741228:63823/NACR" + "LRO/1/305389100:01888/NACL" + "LRO/1/305409449:44487/NACL" + "LRO/1/305409449:44487/NACR" + "LRO/1/305423011:64885/NACL" + "LRO/1/305423011:64885/NACR" + "LRO/1/305443365:16554/NACL" + "LRO/1/305443365:16554/NACR" + "LRO/1/305450184:05413/NACL" + "LRO/1/305450184:05413/NACR" + "LRO/1/305456931:43507/NACR" + "LRO/1/305463753:22535/NACL" + "LRO/1/305463753:22535/NACR" +Number of images in network: 35 +Number of points in network: 75 +Number of measures in network: 651 +Number of ignored points in network: 0 +Number of editlocked points in network: 0 +Number of fixed points in network: 0 +Number of constrained points in network: 0 +Number of free points in network: 75 +Number of points without measures: 0 +Number of points with less than 3 measures: 0 +Number of images without measures: 0 +Number of images with less than 2 measures: 1 +Number of images with less 75 percent hull coverage: 0 +Testing getters... + +Testing signal/slots... +Setting type to Free... +Free points incremented correctly +Setting type to Constrained... +Constrained points incremented correctly +Setting type to Fixed... +Fixed points incremented correctly +Locking the point... +Locking the point works appropriately. +Ignoring Point... +Number of Ignored Points increments correctly. +Ignored point no longer contributes to it's point type statistic correctly. +Unignoring Point... +Adding a measure... +Measure added correctly. +Setting ignored... +Measure ignored correctly. +Deleting Measure... +Measure deleted correctly. +Deleting point... +Point deleted correctly. +Adding dummy point... +Deleting dummy point... +Point deleted correctly +Swapping Control Net... +Net swapped correctly. diff --git a/isis/src/control/objs/ControlCubeGraphNode/Makefile b/isis/src/control/objs/ControlNetVitals/Makefile similarity index 100% rename from isis/src/control/objs/ControlCubeGraphNode/Makefile rename to isis/src/control/objs/ControlNetVitals/Makefile diff --git a/isis/src/control/objs/ControlNetVitals/unitTest.cpp b/isis/src/control/objs/ControlNetVitals/unitTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..18f5967e8f5c6b63ac88caf24b0505bf143b02f8 --- /dev/null +++ b/isis/src/control/objs/ControlNetVitals/unitTest.cpp @@ -0,0 +1,196 @@ +#include <string> +#include <iostream> + +#include <QDebug> +#include <QString> +#include <QStringList> + +#include "ControlNetVitals.h" +#include "FileName.h" +#include "IException.h" +#include "Preference.h" + +using namespace Isis; +using namespace std; + +/** + * Unit test for ControlNetVitals class + * + * @author 2018-06-18 Adam Goins + * @internal + * @history 2018-06-22 Kristin Berry - Upated after fix to numImagesBelowMeasureThreshold() + */ +int main() { + try { + Preference::Preferences(true); + + qDebug() << "Testing Control Net Vitals" << endl; + + qDebug() << "Loading Network"; + + QString testNetFile("$control/testData/unitTest_ControlNetVersioner_ProtoNetwork2_ProtoV0002.net"); + ControlNet *testNet = new ControlNet(testNetFile); + + qDebug() << "Calculating Network Vitals"; + + ControlNetVitals netVitals(testNet); + + qDebug() << "Network ID:" << netVitals.getNetworkId(); + qDebug() << "Network Status:" << netVitals.getStatus(); + qDebug() << "Status Details:" << netVitals.getStatusDetails(); + + qDebug() << "Network has additional islands?" << (netVitals.hasIslands() ? "yes" : "no"); + qDebug() << "Number of islands in network:" << netVitals.numIslands(); + QList< QList<QString> > islandLists = netVitals.getIslands(); + for (int islandIndex = 0; islandIndex < islandLists.size(); islandIndex++) { + QStringList islandSerials(islandLists[islandIndex]); + islandSerials.sort(); + qDebug() << "Serials in island " << islandIndex; + foreach(QString serial, islandSerials) { + qDebug() << " " << serial; + } + } + + int numImages = netVitals.numImages(); + int numPoints = netVitals.numPoints(); + int numMeasures = netVitals.numMeasures(); + int numIgnored = netVitals.numIgnoredPoints(); + int numFixed = netVitals.numFixedPoints(); + int numFree = netVitals.numFreePoints(); + int numLockedPoints = netVitals.numLockedPoints(); + int numConstrained = netVitals.numConstrainedPoints(); + int pointsWithoutMeasures = netVitals.numPointsBelowMeasureThreshold(1); + int pointsBelowMeasures = netVitals.numPointsBelowMeasureThreshold(3); + int imagesWithoutMeasures = netVitals.numImagesBelowMeasureThreshold(1); + int imagesBelowMeasures = netVitals.numImagesBelowMeasureThreshold(2); + int numImagesBelowHull = netVitals.numImagesBelowHullTolerance(); + + + qDebug() << "Number of images in network:" << numImages; + qDebug() << "Number of points in network:" << numPoints; + qDebug() << "Number of measures in network:" << numMeasures; + qDebug() << "Number of ignored points in network:" << numIgnored; + qDebug() << "Number of editlocked points in network:" << numLockedPoints; + qDebug() << "Number of fixed points in network:" << numFixed; + qDebug() << "Number of constrained points in network:" << numConstrained; + qDebug() << "Number of free points in network:" << numFree; + qDebug() << "Number of points without measures:" << pointsWithoutMeasures; + qDebug() << "Number of points with less than 3 measures:" << pointsBelowMeasures; + qDebug() << "Number of images without measures:" << imagesWithoutMeasures; + qDebug() << "Number of images with less than 2 measures:" << imagesBelowMeasures; + qDebug() << "Number of images with less 75 percent hull coverage:" << numImagesBelowHull; + + qDebug() << "Testing getters..."; + assert(numImages == netVitals.getCubeSerials().size()); + assert(numPoints == netVitals.getAllPoints().size()); + assert(numIgnored == netVitals.getIgnoredPoints().size()); + assert(numLockedPoints == netVitals.getLockedPoints().size()); + assert(numFixed == netVitals.getFixedPoints().size()); + assert(numConstrained == netVitals.getConstrainedPoints().size()); + assert(numFree == netVitals.getFreePoints().size()); + assert(pointsWithoutMeasures == netVitals.getPointsBelowMeasureThreshold(1).size()); + assert(pointsBelowMeasures == netVitals.getPointsBelowMeasureThreshold(3).size()); + assert(imagesWithoutMeasures == netVitals.getImagesBelowMeasureThreshold(1).size()); + assert(imagesBelowMeasures == netVitals.getImagesBelowMeasureThreshold(2).size()); + assert(numImagesBelowHull == netVitals.getImagesBelowHullTolerance().size()); + + qDebug() << "\nTesting signal/slots..."; + ControlPoint *testPoint = new ControlPoint; + testPoint->SetEditLock(true); + testNet->AddPoint(testPoint); + numPoints++; + assert( netVitals.numPoints() == testNet->GetNumPoints() ); + testPoint->SetEditLock(false); + + qDebug() << "Setting type to Free..."; + testPoint->SetType(ControlPoint::Free); + assert(netVitals.numFreePoints() == numFree + 1); + qDebug() << "Free points incremented correctly"; + + qDebug() << "Setting type to Constrained..."; + testPoint->SetType(ControlPoint::Constrained); + assert(netVitals.numConstrainedPoints() == numConstrained + 1); + qDebug() << "Constrained points incremented correctly"; + + qDebug() << "Setting type to Fixed..."; + testPoint->SetType(ControlPoint::Fixed); + assert(netVitals.numFixedPoints() == numFixed + 1); + qDebug() << "Fixed points incremented correctly"; + + qDebug() << "Locking the point..."; + testPoint->SetEditLock(true); + assert(netVitals.numLockedPoints() == numLockedPoints + 1); + testPoint->SetEditLock(true); + assert(netVitals.numLockedPoints() == numLockedPoints + 1); + testPoint->SetEditLock(false); + assert(netVitals.numLockedPoints() == numLockedPoints); + testPoint->SetEditLock(false); + assert(netVitals.numLockedPoints() == numLockedPoints); + qDebug() << "Locking the point works appropriately."; + + qDebug() << "Ignoring Point..."; + testPoint->SetIgnored(true); + + assert(netVitals.numIgnoredPoints() == numIgnored + 1); + qDebug() << "Number of Ignored Points increments correctly."; + + assert(netVitals.numFixedPoints() == numFixed); + qDebug() << "Ignored point no longer contributes to it's point type statistic correctly."; + + qDebug() << "Unignoring Point..."; + testPoint->SetIgnored(false); + + qDebug() << "Adding a measure..."; + ControlMeasure *newMeasure = new ControlMeasure(); + newMeasure->SetCubeSerialNumber("Hey.test"); + testPoint->Add(newMeasure); + assert(netVitals.numMeasures() == numMeasures + 1); + qDebug() << "Measure added correctly."; + qDebug() << "Setting ignored..."; + + newMeasure->SetIgnored(true); + newMeasure->SetIgnored(true); + assert(testNet->GetNumValidMeasures() == numMeasures); + qDebug() << "Measure ignored correctly."; + newMeasure->SetIgnored(false); + newMeasure->SetIgnored(false); + + + qDebug() << "Deleting Measure..."; + testPoint->Delete(newMeasure); + assert(netVitals.numMeasures() == numMeasures); + qDebug() << "Measure deleted correctly."; + + qDebug() << "Deleting point..."; + testPoint->SetEditLock(false); + testNet->DeletePoint(testPoint); + assert(netVitals.numPoints() == --numPoints); + qDebug() << "Point deleted correctly."; + + qDebug() << "Adding dummy point..."; + ControlPoint *newPoint = new ControlPoint; + testNet->AddPoint(newPoint); + assert(netVitals.numPoints() == ++numPoints); + + qDebug() << "Deleting dummy point..."; + newPoint->SetIgnored(true); + testNet->DeletePoint(newPoint); + assert(netVitals.numPoints() == --numPoints); + qDebug() << "Point deleted correctly"; + + qDebug() << "Swapping Control Net..."; + ControlNet net; + testNet->swap(net); + + assert(netVitals.numPoints() == 0); + qDebug() << "Net swapped correctly."; + + delete testNet; + testNet = NULL; + + } + catch(IException &e) { + qDebug() << "ControlNetVitals unit test failed!" << endl; + e.print(); + } +} diff --git a/isis/src/control/objs/ControlPoint/ControlPoint.cpp b/isis/src/control/objs/ControlPoint/ControlPoint.cpp index 04df89eae32ecb2cad8503fd845a05d73809ae92..db66f7e4d71bc84b9c767cef89cf63cf39bbc957 100644 --- a/isis/src/control/objs/ControlPoint/ControlPoint.cpp +++ b/isis/src/control/objs/ControlPoint/ControlPoint.cpp @@ -285,6 +285,15 @@ namespace Isis { ValidateMeasure(serialNumber); ControlMeasure *cm = (*measures)[serialNumber]; + // notify parent network of the change + if (parentNetwork) { + parentNetwork->measureDeleted(cm); + + if (!IsIgnored() && !cm->IsIgnored()) { + parentNetwork->emitNetworkStructureModified(); + } + } + if (cm->IsEditLocked()) { return ControlMeasure::MeasureLocked; } @@ -304,15 +313,6 @@ namespace Isis { referenceMeasure = NULL; } - // notify parent network of the change - if (parentNetwork) { - parentNetwork->measureDeleted(cm); - - if (!IsIgnored() && !cm->IsIgnored()) { - parentNetwork->emitNetworkStructureModified(); - } - } - delete cm; cm = NULL; @@ -322,6 +322,22 @@ namespace Isis { } + /** + * This method is a wrapper to emit the measureModified() signal in the parent network + * is called whenever a change is made to a Control Measure. + * + * @param measure The ControlMeasure* that was modified. + * @param type The ControlMeasure::ModType indicating which modification occured. + * @param oldValue The oldValue before the change. + * @param newValue The new value that the change incorporated. + */ + void ControlPoint::emitMeasureModified(ControlMeasure *measure, ControlMeasure::ModType modType, QVariant oldValue, QVariant newValue) { + if (parentNetwork) { + parentNetwork->emitMeasureModified(measure, modType, oldValue, newValue); + } + } + + /** * Remove a measurement from the control point, deleting reference measure * is allowed. @@ -497,6 +513,9 @@ namespace Isis { * point to be modified. */ ControlPoint::Status ControlPoint::SetEditLock(bool lock) { + if (parentNetwork) { + parentNetwork->emitPointModified(this, ControlPoint::EditLockModified, editLock, lock); + } editLock = lock; return Success; } @@ -636,17 +655,13 @@ namespace Isis { if (oldStatus != ignore) { PointModified(); if (parentNetwork) { - foreach(ControlMeasure * cm, measures->values()) { - if (!cm->IsIgnored()) { - if (ignore) { - parentNetwork->measureIgnored(cm); - } - else { - parentNetwork->measureUnIgnored(cm); - } - } + if (ignore) { + parentNetwork->pointIgnored(this); } - parentNetwork->emitNetworkStructureModified(); + else { + parentNetwork->pointUnIgnored(this); + } + parentNetwork->emitPointModified(this, ControlPoint::IgnoredModified, oldStatus, ignore); } } @@ -693,6 +708,10 @@ namespace Isis { if (editLock) { return PointLocked; } + if (parentNetwork) { + parentNetwork->emitPointModified(this, ControlPoint::TypeModified, type, newType); + } + PointModified(); type = newType; return Success; @@ -1917,6 +1936,7 @@ namespace Isis { const ControlPoint &ControlPoint::operator=(const ControlPoint &other) { if (this != &other) { + bool oldLock = editLock; editLock = false; for (int i = cubeSerials->size() - 1; i >= 0; i--) { (*measures)[cubeSerials->at(i)]->SetEditLock(false); @@ -1936,23 +1956,27 @@ namespace Isis { } } - id = other.id; - chooserName = other.chooserName; - dateTime = other.dateTime; - type = other.type; - invalid = other.invalid; - editLock = other.editLock; - jigsawRejected = other.jigsawRejected; - referenceExplicitlySet = other.referenceExplicitlySet; - ignore = other.ignore; - aprioriSurfacePointSource = other.aprioriSurfacePointSource; - aprioriSurfacePointSourceFile = other.aprioriSurfacePointSourceFile; - aprioriRadiusSource = other.aprioriRadiusSource; - aprioriRadiusSourceFile = other.aprioriRadiusSourceFile; - aprioriSurfacePoint = other.aprioriSurfacePoint; - adjustedSurfacePoint = other.adjustedSurfacePoint; + invalid = other.invalid; + referenceExplicitlySet = other.referenceExplicitlySet; numberOfRejectedMeasures = other.numberOfRejectedMeasures; - constraintStatus = other.constraintStatus; + constraintStatus = other.constraintStatus; + + SetId(other.id); + SetChooserName(other.chooserName); + SetDateTime(other.dateTime); + SetType(other.type); + SetRejected(other.jigsawRejected); + SetIgnored(other.ignore); + SetAprioriSurfacePointSource(other.aprioriSurfacePointSource); + SetAprioriSurfacePointSourceFile(other.aprioriSurfacePointSourceFile); + SetAprioriRadiusSource(other.aprioriRadiusSource); + SetAprioriRadiusSourceFile(other.aprioriRadiusSourceFile); + SetAprioriSurfacePoint(other.aprioriSurfacePoint); + SetAdjustedSurfacePoint(other.adjustedSurfacePoint); + + // Set edit lock last so the it doesn't interfere with copying the other fields over. + editLock = oldLock; + SetEditLock(other.editLock); } return *this; diff --git a/isis/src/control/objs/ControlPoint/ControlPoint.h b/isis/src/control/objs/ControlPoint/ControlPoint.h index f2c00adb101cb1a14eece562084ed2a76e87dc1a..3506ac8d56e526a515157e4ce98ad4d32f1e7e85 100644 --- a/isis/src/control/objs/ControlPoint/ControlPoint.h +++ b/isis/src/control/objs/ControlPoint/ControlPoint.h @@ -29,6 +29,7 @@ #include <QObject> #include <QString> +#include "ControlMeasure.h" #include "SurfacePoint.h" template< typename A, typename B > class QHash; @@ -36,7 +37,6 @@ template< typename A, typename B > class QHash; class QStringList; namespace Isis { - class ControlMeasure; class ControlNet; class ControlPointFileEntryV0002; class Latitude; @@ -343,6 +343,17 @@ namespace Isis { * @history 2018-01-05 Adam Goins - Added HasDateTime() and HasChooserName() methods to allow * to allow the value of these variables to be read without being * overriden if they're empty. (Getters override if they're empty). + * @history 2018-06-06 Jesse Mapel - Modified setIgnored to use new pointIgnored and + * pointUnIgnored methods. References #5434. + * @history 2018-06-15 Adam Goins & Jesse Mapel - Added the ModType enum, as well as a series + * of calls to parentNetwork()->emitPointModified() whenever a change + * is made to a Control Point or any of it's measures. This is done + * to allow for communication between the ControlNetVitals class + * and changes made to the Control Network that it is observing. + * Fixes #5435. + * @history 2018-06-29 Adam Goins - Modified to operator= method to use setters when copying + * one Control Point to another so that the proper signals get called. + * Fixes #5435. */ class ControlPoint : public QObject { @@ -420,6 +431,22 @@ namespace Isis { // ZConstrained = 5; }; + /** + * @brief Control Point Modification Types + * + * This enum is designed to represent the different types of modifications that can be + * made to a ControlPoint. + * + * EditLockModified means that the Control Point had it's edit lock flag changed. + * IgnoredModified means that the Control Measure had it's ignored flag changed. + * TypeModified means that the ControlPoint::PointType for this control point was modified. + */ + enum ModType { + EditLockModified, + IgnoredModified, + TypeModified + }; + // This stuff input to jigsaw // How did apriori source get computed?? struct SurfacePointSource { @@ -546,6 +573,9 @@ namespace Isis { int IndexOfRefMeasure() const; bool IsReferenceExplicit() const; QString GetReferenceSN() const; + void emitMeasureModified(ControlMeasure *measure, ControlMeasure::ModType modType, QVariant oldValue, QVariant newValue); + + Statistics GetStatistic(double(ControlMeasure::*statFunc)() const) const; Statistics GetStatistic(long dataType) const; diff --git a/isis/src/control/objs/MaximumLikelihoodWFunctions/MaximumLikelihoodWFunctions.cpp b/isis/src/control/objs/MaximumLikelihoodWFunctions/MaximumLikelihoodWFunctions.cpp index ef797f1c4f30299670192995b4b71d834cc9ad8f..0a49bdfce535b598ca38c03afc16f302fde224c5 100644 --- a/isis/src/control/objs/MaximumLikelihoodWFunctions/MaximumLikelihoodWFunctions.cpp +++ b/isis/src/control/objs/MaximumLikelihoodWFunctions/MaximumLikelihoodWFunctions.cpp @@ -6,10 +6,10 @@ #include <math.h> #include <stdio.h> -#include "IException.h" -#include "IString.h" +#include "IException.h" +#include "IString.h" -namespace Isis { +namespace Isis { /** * Sets up a maximumlikelihood estimation function with Huber model and default tweaking * constant @@ -49,7 +49,7 @@ namespace Isis { double tweakingConstant) { // choose Model and define the tweaking constant setModel(modelSelection, tweakingConstant); - } + } MaximumLikelihoodWFunctions::MaximumLikelihoodWFunctions( const MaximumLikelihoodWFunctions &other) @@ -57,7 +57,7 @@ namespace Isis { m_tweakingConstant(other.m_tweakingConstant) { } - + MaximumLikelihoodWFunctions::~MaximumLikelihoodWFunctions() { } // empty destructor @@ -131,8 +131,8 @@ namespace Isis { void MaximumLikelihoodWFunctions::setModel(Model modelSelection, double tweakingConstant) { // choose Model and define the tweaking constant m_model = modelSelection; - setTweakingConstant(tweakingConstant); - } + setTweakingConstant(tweakingConstant); + } @@ -147,32 +147,32 @@ namespace Isis { */ void MaximumLikelihoodWFunctions::setTweakingConstant(double tweakingConstant) { // leave model type unaltered and change tweaking constant - if (tweakingConstant <= 0.0) { - IString msg = "Maximum likelihood estimation tweaking constants must be > 0.0"; - throw IException(IException::Programmer, msg, _FILEINFO_); + if (tweakingConstant <= 0.0) { + IString msg = "Maximum likelihood estimation tweaking constants must be > 0.0"; + throw IException(IException::Programmer, msg, _FILEINFO_); } m_tweakingConstant = tweakingConstant; - } + } + - - /** + /** * Returns the current tweaking constant - */ - double MaximumLikelihoodWFunctions::tweakingConstant() const { - return m_tweakingConstant; - } - - - - /** + */ + double MaximumLikelihoodWFunctions::tweakingConstant() const { + return m_tweakingConstant; + } + + + + /** * This provides the scalar for the weight (not the scaler for the square * root of the weight, which is generally more useful) - * - * @param[in] double residualZScore, this the residual of a particulare measure in a particular + * + * @param[in] double residualZScore, this the residual of a particulare measure in a particular * iteration divided by the standard deviation (sigma) of that * measure - * @return double the scaler adjustment to the weight for the measure + * @return double the scaler adjustment to the weight for the measure * nominal weight = 1 /sigma/sigma and weight' = scaler/sigma/sigma */ double MaximumLikelihoodWFunctions::weightScaler(double residualZScore) { @@ -192,18 +192,18 @@ namespace Isis { return 1.0; // default to prevent nonsense from being returned, // but the program should never reach this line } - } + } - - /** + + /** * This provides the scaler to the sqrt of the weight, which is very useful for building normal * equations. - * - * @param[in] double residualZScore, this the residual of a particulare measure in a particular + * + * @param[in] double residualZScore, this the residual of a particulare measure in a particular * iteration divided by the standard deviation (sigma) of that * measure - * @return double the scaler adjustment to the sqrt of the weight for the measure + * @return double the scaler adjustment to the sqrt of the weight for the measure * nominal sqrt(weight) = 1 /sigma and sqrt(weight') = scaler/sigma */ double MaximumLikelihoodWFunctions::sqrtWeightScaler(double residualZScore) { @@ -215,18 +215,18 @@ namespace Isis { // (thus this saves some time) } return sqrt(scaler); - } + } - - /** + + /** * Huber maximum likelihood estimation function evaluation. For details, see documentation of the * enum, MaximumLikelihoodWFunctions::Model - * - * @param[in] double residualZScore, this the residual of a particulare measure in a particular + * + * @param[in] double residualZScore, this the residual of a particulare measure in a particular * iteration divided by the standard deviation (sigma) of that * measure - * @return double the scaler adjustment to the weight for the measure + * @return double the scaler adjustment to the weight for the measure * nominal weight = 1 /sigma/sigma and weight' = scaler/sigma/sigma */ double MaximumLikelihoodWFunctions::huber(double residualZScore) { @@ -237,18 +237,18 @@ namespace Isis { else { return m_tweakingConstant/fabs(residualZScore); } - } + } - - /** + + /** * Modified Huber maximum likelihood estimation function evaluation. For * details see documentation of enum Model - * - * @param[in] double residualZScore, this the residual of a particulare measure in a particular + * + * @param[in] double residualZScore, this the residual of a particulare measure in a particular * iteration divided by the standard deviation (sigma) of that * measure - * @return double the scaler adjustment to the weight for the measure + * @return double the scaler adjustment to the weight for the measure * nominal weight = 1 /sigma/sigma and weight' = scaler/sigma/sigma */ double MaximumLikelihoodWFunctions::huberModified(double residualZScore) { @@ -277,10 +277,10 @@ namespace Isis { // welsch weight function double weightFactor = residualZScore / m_tweakingConstant; return exp(-(weightFactor)*(weightFactor)); - } - + } + + - /** * Modified Huber maximum likelihood estimation function evaluation. * For details, see documentation of enum Model. @@ -303,17 +303,17 @@ namespace Isis { return 0.0; } } - - /** + + /** * Suggest a quantile of the probility distribution of the residuals to use as the tweaking * constants based on the maximum likelihood estimation model being used. - * + * * @return double quantile [0,1] the value pretaining to this quantile (in the probility * distribution of the residuals) should be used as the tweaking constant. */ - double MaximumLikelihoodWFunctions::tweakingConstantQuantile() { + double MaximumLikelihoodWFunctions::tweakingConstantQuantile() { // returns which quantile of the sqaured residuals is recommended to use as the tweaking // constants, this varies as a function of the model being employed desired quantiles for // various models, these parameters are estimated based on inspection of the fucntions and @@ -343,7 +343,7 @@ namespace Isis { * * @param model Enumerated value for a MaximumLikelihoodWFunctions model. * @return QString label for the enumeration. - */ + */ QString MaximumLikelihoodWFunctions::modelToString(MaximumLikelihoodWFunctions::Model model) { if (model == MaximumLikelihoodWFunctions::Huber) return "Huber"; else if (model == MaximumLikelihoodWFunctions::HuberModified) return "HuberModified"; @@ -360,10 +360,9 @@ namespace Isis { if (modelName.compare("HUBER", Qt::CaseInsensitive) == 0) { return Huber; } - else if (modelName.compare("HUBER_MODIFIED", Qt::CaseInsensitive) == 0) { - return HuberModified; - } - else if (modelName.compare("HUBERMODIFIED", Qt::CaseInsensitive) == 0) { + else if (modelName.compare("HUBER_MODIFIED", Qt::CaseInsensitive) == 0 || + modelName.compare("HUBERMODIFIED", Qt::CaseInsensitive) == 0 || + modelName.compare("HUBER MODIFIED", Qt::CaseInsensitive) == 0) { return HuberModified; } else if (modelName.compare("WELSCH", Qt::CaseInsensitive) == 0) { @@ -451,5 +450,5 @@ namespace Isis { modelEnum = (MaximumLikelihoodWFunctions::Model)modelInteger; return stream; } - -}// end namespace Isis + +}// end namespace Isis diff --git a/isis/src/control/objs/MaximumLikelihoodWFunctions/MaximumLikelihoodWFunctions.h b/isis/src/control/objs/MaximumLikelihoodWFunctions/MaximumLikelihoodWFunctions.h index 6be0bc535955b5a5a08bbb0ad9703b94febc10cd..f31ee3a0eb2885dc8d473780ac2f453026519a76 100644 --- a/isis/src/control/objs/MaximumLikelihoodWFunctions/MaximumLikelihoodWFunctions.h +++ b/isis/src/control/objs/MaximumLikelihoodWFunctions/MaximumLikelihoodWFunctions.h @@ -58,6 +58,8 @@ namespace Isis { * methods. * @history 2014-09-19 Jeannie Backer - Removed bugs. Added documentation. Cleaned * duplicate code. + * @history 2018-06-29 Christopher Combs - Added extra HuberModified case to stringToModel(). + * Fixes #5446. */ class MaximumLikelihoodWFunctions { public: diff --git a/isis/src/lro/apps/lronacpho/lronacpho.xml b/isis/src/lro/apps/lronacpho/lronacpho.xml index a3bd28c4af51a4ded4bdeaf49c5475386aa7a712..4f1b951b2343e64c9db6b657bbdb1da9485be969 100644 --- a/isis/src/lro/apps/lronacpho/lronacpho.xml +++ b/isis/src/lro/apps/lronacpho/lronacpho.xml @@ -104,6 +104,7 @@ incidence angle greater than 90 degrees is set to the ISIS special Null pixel value. And, of course, any ISIS special pixel encountered on input is propagated to the output TO file without modification. + <b>Function is only valid for phase angles between 15 and 65 degrees.</b> </p> </description> diff --git a/isis/src/qisis/apps/ipce/IpceMainWindow.cpp b/isis/src/qisis/apps/ipce/IpceMainWindow.cpp index b16393e6c57490f3ba0ac1a3f3434069d34e1002..62963c3622568c167955f0d992cb4ec2732e26c3 100644 --- a/isis/src/qisis/apps/ipce/IpceMainWindow.cpp +++ b/isis/src/qisis/apps/ipce/IpceMainWindow.cpp @@ -40,12 +40,15 @@ #include <QDateTime> #include <QTreeView> #include <QVariant> +#include <QTabWidget> + #include "AbstractProjectItemView.h" #include "Directory.h" #include "FileName.h" #include "IException.h" #include "IString.h" +#include "JigsawRunWidget.h" #include "MosaicSceneWidget.h" #include "ProgressWidget.h" #include "Project.h" @@ -76,26 +79,26 @@ namespace Isis { QMainWindow(parent) { m_maxThreadCount = -1; - QMdiArea *centralWidget = new QMdiArea; - centralWidget->setActivationOrder(QMdiArea::StackingOrder); - - connect(centralWidget, SIGNAL( subWindowActivated(QMdiSubWindow *) ), - this, SLOT( onSubWindowActivated(QMdiSubWindow *) ) ); - + QWidget *centralWidget = new QWidget; setCentralWidget(centralWidget); + setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::North); + //setDockOptions(GroupedDragging | AllowTabbedDocks); + //centralWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + //centralWidget->hide(); setDockNestingEnabled(true); - m_activeView = NULL; - try { m_directory = new Directory(this); connect(m_directory, SIGNAL( newWidgetAvailable(QWidget *) ), this, SLOT( addView(QWidget *) ) ); - connect(m_directory, SIGNAL(viewClosed(QWidget *)), this, SLOT(removeView(QWidget *))); + connect(m_directory, SIGNAL(viewClosed(QWidget *)), + this, SLOT(removeView(QWidget *))); connect(m_directory, SIGNAL( directoryCleaned() ), this, SLOT( removeAllViews() ) ); connect(m_directory->project(), SIGNAL(projectLoaded(Project *)), this, SLOT(readSettings(Project *))); + connect(m_directory->project(), SIGNAL(projectSaved(Project *)), + this, SLOT(writeSettings(Project *))); connect(m_directory, SIGNAL( newWarning() ), this, SLOT( raiseWarningTab() ) ); } @@ -115,6 +118,7 @@ namespace Isis { projectTreeView->treeView()->expandAll(); projectTreeView->installEventFilter(this); m_projectDock->setWidget(projectTreeView); + m_projectDock->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); addDockWidget(Qt::LeftDockWidgetArea, m_projectDock, Qt::Horizontal); @@ -140,20 +144,10 @@ namespace Isis { m_directory->setHistoryContainer(historyDock); tabifyDockWidget(m_warningsDock, historyDock); -// QDockWidget *progressDock = new QDockWidget("Progress", this, Qt::SubWindow); -// progressDock->setObjectName("progressDock"); -// progressDock->setFeatures(QDockWidget::DockWidgetClosable | -// QDockWidget::DockWidgetMovable | -// QDockWidget::DockWidgetFloatable); -// progressDock->setAllowedAreas(Qt::BottomDockWidgetArea); -// //m_directory->setProgressContainer(progressDock); -// addDockWidget(Qt::BottomDockWidgetArea, progressDock); -// tabifyDockWidget(historyDock, progressDock); - historyDock->raise(); - setTabPosition(Qt::TopDockWidgetArea, QTabWidget::North); + setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); setCorner(Qt::BottomLeftCorner, Qt::BottomDockWidgetArea); @@ -166,101 +160,80 @@ namespace Isis { statusBar()->addWidget(progressBar); } - createMenus(); - initializeActions(); - updateMenuActions(); - - m_permToolBar = new QToolBar(this); - m_activeToolBar = new QToolBar(this); - m_toolPad = new QToolBar(this); - - QSize iconSize(25, 45); - - m_permToolBar->setIconSize(iconSize); - m_activeToolBar->setIconSize(iconSize); - m_toolPad->setIconSize(iconSize); - - m_permToolBar->setObjectName("PermanentToolBar"); - m_activeToolBar->setObjectName("ActiveToolBar"); - m_toolPad->setObjectName("ToolPad"); - - addToolBar(m_permToolBar); - addToolBar(m_activeToolBar); - addToolBar(m_toolPad); - updateToolBarActions(); + // Read default app settings. NOTE: This must be completed before initializing actions in order + // to read the recent projects from the config file. + readSettings(m_directory->project() ); - setTabbedViewMode(); - centralWidget->setTabsMovable(true); - centralWidget->setTabsClosable(true); + initializeActions(); + createMenus(); + createToolBars(); + QCoreApplication::setApplicationName("ipce"); QStringList args = QCoreApplication::arguments(); if (args.count() == 2) { OpenProjectWorkOrder *workorder = new OpenProjectWorkOrder(m_directory->project()); workorder->execute(); } - - // ken testing If this is used, we will not need to call updateMenuActions() or updateToolBar() - // above. They are both called from setActiveView. - // setActiveView(projectTreeView); - // ken testing } /** - * This is connected from Directory's newWidgetAvailable signal and called when re-attaching a - * view which was detached from the MDI main window. + * This is connected from Directory's newWidgetAvailable signal * * @param[in] newWidget (QWidget *) */ - void IpceMainWindow::addView(QWidget *newWidget) { + void IpceMainWindow::addView(QWidget *newWidget, Qt::DockWidgetArea area, + Qt::Orientation orientation) { + // JigsawRunWidget is already a QDockWidget, and no modifications need to be made to it + if (qobject_cast<JigsawRunWidget *>(newWidget)) { + splitDockWidget(m_projectDock, (QDockWidget*)newWidget, Qt::Vertical); + return; + } + + QDockWidget *dock = new QDockWidget(newWidget->windowTitle(), this); + dock->setWidget(newWidget); + dock->setObjectName(newWidget->windowTitle()); + dock->setAttribute(Qt::WA_DeleteOnClose); + dock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable | + QDockWidget::DockWidgetFloatable); + if ( qobject_cast<SensorInfoWidget *>(newWidget) || qobject_cast<TargetInfoWidget *>(newWidget) || qobject_cast<TemplateEditorWidget *>(newWidget)) { - QDockWidget *dock = new QDockWidget( newWidget->windowTitle() ); - dock->setAttribute(Qt::WA_DeleteOnClose, true); - dock->setWidget(newWidget); - dock->setObjectName(newWidget->windowTitle()); splitDockWidget(m_projectDock, dock, Qt::Vertical); } else { - if ( QMdiArea *mdiArea = qobject_cast<QMdiArea *>( centralWidget() ) ) { - mdiArea->addSubWindow(newWidget); - newWidget->show(); - mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(newWidget)); - setActiveView(qobject_cast<AbstractProjectItemView *>(newWidget)); - } + addDockWidget(area, dock, orientation); + } + + // When dock widget is destroyed, make sure the view it holds is also destroyed + connect(dock, SIGNAL(destroyed(QObject *)), newWidget, SLOT(deleteLater())); + // The list of dock widgets needs cleanup as each view is destroyed + connect(dock, SIGNAL(destroyed(QObject *)), this, SLOT(cleanupViewDockList(QObject *))); + + // Save view docks for cleanup during a project close + m_viewDocks.append(dock); + } + + + void IpceMainWindow::cleanupViewDockList(QObject *obj) { + QDockWidget *dock = static_cast<QDockWidget *>(obj); + if (dock) { + m_viewDocks.removeAll(dock); } } /** - * @description This slot is connected from Directory::viewClosed(QWidget *) signal. It will - * close the given QMdiSubWindow from the QMdiArea. This will also delete the widget contained - * within the subwindow which is an AbstractProjectItemView. - * - * @param view QWidget* + * This slot is connected from Directory::viewClosed(QWidget *) signal. It will + * close the given view and delete the view. This was written to handle * + * @param view QWidget* The view to close. */ void IpceMainWindow::removeView(QWidget *view) { - - QMdiArea *mdiArea = qobject_cast<QMdiArea *>( centralWidget() ); - if (mdiArea){ - // Get all QMdiSubWindows, then find subwindow that hold widget - QList<QMdiSubWindow *> subWindowList = mdiArea->subWindowList(); - foreach (QMdiSubWindow *sub, subWindowList) { - if (sub->widget() == view) { - sub->close(); - break; - } - } -// QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(view); -// qDebug()<<"IpceMainWindow::removeView activewindow = "<<window; -// mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(view)); -// qDebug()<<"IpceMainWindow::removeView"; -// mdiArea->closeActiveSubWindow(); - delete view; - } + view->close(); + delete view; } @@ -269,29 +242,14 @@ namespace Isis { */ void IpceMainWindow::removeAllViews() { setWindowTitle("ipce"); - QMdiArea *mdiArea = qobject_cast<QMdiArea *>( centralWidget() ); - if (mdiArea){ -// QMdiSubWindow* window = new QMdiSubWindow(); -// window->show(); -// window->activateWindow(); -// mdiArea->addSubWindow(window); - mdiArea->closeAllSubWindows(); -// delete window; - } - if (!m_detachedViews.isEmpty()) { - foreach ( QMainWindow* view, m_detachedViews ) { - view->close(); - } - } - - QList<QDockWidget *> docks = tabifiedDockWidgets(m_projectDock); - if(docks.count() > 1) { - foreach ( QDockWidget* widget, docks ) { - if(widget != m_projectDock) { - delete widget; - } + foreach (QDockWidget *dock, m_viewDocks) { + if (dock) { + removeDockWidget(dock); + m_viewDocks.removeAll(dock); + delete dock; } } + m_viewDocks.clear(); } @@ -304,173 +262,17 @@ namespace Isis { /** - * Sets the active view and updates the toolbars and menus. + * This is needed so that the project clean flag is not set to false when move and resize events + * are emitted from ipce.cpp when IpceMainWindow::show() is called. + * The non-spontaneous or internal QShowEvent is only emitted once from ipce.cpp, so the project + * clean flag can be reset. + * + * @param event QShowEvent* * - * @param[in] view (AbstractProjectItemView *) The active view. - */ - void IpceMainWindow::setActiveView(AbstractProjectItemView *view) { - m_activeView = view; - updateMenuActions(); - updateToolBarActions(); - } - - - /** - * Clears all the menus, then populates the menus with QActions from - * several sources. The QActions come from an internal list of - * QActions, the Directory, and the active view. - */ - void IpceMainWindow::updateMenuActions() { - - m_fileMenu->clear(); - // Get Directory FileMenu actions - foreach ( QAction *action, m_directory->fileMenuActions() ) { - m_fileMenu->addAction(action); - } - m_fileMenu->addSeparator(); - // Get FileMenu actions for the active view (eg. CubeDnView, Footprint2DView) - if (m_activeView) { - foreach ( QAction *action, m_activeView->fileMenuActions() ) { - m_fileMenu->addAction(action); - } - } - m_fileMenu->addSeparator(); - // Get FileMenu actions from the ipceMainWindow, Exit is the only action - foreach ( QAction *action, m_fileMenuActions ) { - m_fileMenu->addAction(action); - } - - m_projectMenu->clear(); - // Get Project menu actions from Directory - foreach ( QAction *action, m_directory->projectMenuActions() ) { - m_projectMenu->addAction(action); - } - m_projectMenu->addSeparator(); - // Get Project menu actions from the active view - if (m_activeView) { - foreach ( QAction *action, m_activeView->projectMenuActions() ) { - m_projectMenu->addAction(action); - } - } - m_projectMenu->addSeparator(); - // Get Project menu actions from IpceMainWindow - foreach ( QAction *action, m_projectMenuActions ) { - m_projectMenu->addAction(action); - } - - m_editMenu->clear(); - // Get Edit menu actions from Directory - foreach ( QAction *action, m_directory->editMenuActions() ) { - m_editMenu->addAction(action); - } - m_editMenu->addSeparator(); - // Get Edit menu actions from active view - if (m_activeView) { - foreach ( QAction *action, m_activeView->editMenuActions() ) { - m_editMenu->addAction(action); - } - } - m_editMenu->addSeparator(); - // Get Edit menu actions from IpceMainWindow - foreach ( QAction *action, m_editMenuActions ) { - m_editMenu->addAction(action); - } - - m_viewMenu->clear(); - // Get View menu actions from Directory - foreach ( QAction *action, m_directory->viewMenuActions() ) { - m_viewMenu->addAction(action); - } - m_viewMenu->addSeparator(); - // Get View menu actions from IpceMainWindow - foreach ( QAction *action, m_viewMenuActions ) { - m_viewMenu->addAction(action); - } - m_viewMenu->addSeparator(); - // Get View menu actions from active view - if (m_activeView) { - foreach ( QAction *action, m_activeView->viewMenuActions() ) { - m_viewMenu->addAction(action); - } - } - - m_settingsMenu->clear(); - // Get Settings menu actions from Directory - foreach ( QAction *action, m_directory->settingsMenuActions() ) { - m_settingsMenu->addAction(action); - } - m_settingsMenu->addSeparator(); - // Get Settings menu actions from active view - if (m_activeView) { - foreach ( QAction *action, m_activeView->settingsMenuActions() ) { - m_settingsMenu->addAction(action); - } - } - m_settingsMenu->addSeparator(); - // Get Settings menu actions from IpceMainWindow - foreach ( QAction *action, m_settingsMenuActions ) { - m_settingsMenu->addAction(action); - } - - m_helpMenu->clear(); - // Get Help menu actions from Directory - foreach ( QAction *action, m_directory->helpMenuActions() ) { - m_helpMenu->addAction(action); - } - m_helpMenu->addSeparator(); - // Get Help menu actions from active view - if (m_activeView) { - foreach ( QAction *action, m_activeView->helpMenuActions() ) { - m_helpMenu->addAction(action); - } - } - m_helpMenu->addSeparator(); - // Get Help menu actions from IpceMainWindow - foreach ( QAction *action, m_helpMenuActions ) { - m_helpMenu->addAction(action); - } - } - - - /** - * Clears the tool bars and repopulates them with QActions from - * several sources. Actions are taken from an internal list of - * QActions, the Directory, and the active view. */ - void IpceMainWindow::updateToolBarActions() { - - m_permToolBar->clear(); - foreach ( QAction *action, m_directory->permToolBarActions() ) { - m_permToolBar->addAction(action); - } - foreach (QAction *action, m_permToolBarActions) { - if (action->text() == "&Save Active Control Network") { - m_permToolBar->addSeparator(); - } - m_permToolBar->addAction(action); - if (action->text() == "&Save Active Control Network") { - m_permToolBar->addSeparator(); - } - } - m_permToolBar->addSeparator(); - if (m_activeView) { - foreach ( QAction *action, m_activeView->permToolBarActions() ) { - m_permToolBar->addAction(action); - } - } - - m_activeToolBar->clear(); - if (m_activeView) { - foreach ( QAction *action, m_activeView->activeToolBarActions() ) { - m_activeToolBar->addAction(action); - } - } - - m_toolPad->clear(); - if (m_activeView) { - foreach ( QAction *action, m_activeView->toolPadActions() ) { - m_toolPad->addAction(action); - } + void IpceMainWindow::showEvent(QShowEvent *event) { + if (!event->spontaneous()) { + m_directory->project()->setClean(true); } } @@ -554,29 +356,9 @@ namespace Isis { m_fileMenuActions.append(exitAction); m_permToolBarActions.append(exitAction); - QAction *saveNet = new QAction("&Save Active Control Network", this); - saveNet->setIcon( QIcon::fromTheme("document-save") ); - saveNet->setShortcut(Qt::CTRL + Qt::Key_S); - saveNet->setToolTip("Save current active control network"); - saveNet->setStatusTip("Save current active control network"); - QString whatsThis = "<b>Function:</b> Saves the current active<i>" - "control network</i>"; - saveNet->setWhatsThis(whatsThis); - connect(saveNet, SIGNAL(triggered()), m_directory, SLOT(saveActiveControl())); - m_permToolBarActions.append(saveNet); - -// m_saveAsNet = new QAction(QPixmap(toolIconDir() + "/mActionFileSaveAs.png"), -// "Save Control Network &As...", -// m_matchTool); -// m_saveAsNet->setToolTip("Save current control network to chosen file"); -// m_saveAsNet->setStatusTip("Save current control network to chosen file"); -// whatsThis = "<b>Function:</b> Saves the current <i>" -// "control network</i> under chosen filename"; -// m_saveAsNet->setWhatsThis(whatsThis); -// connect(m_saveAsNet, SIGNAL(triggered()), this, SLOT(saveAsNet())); - - - + QAction *tabViewsAction = new QAction("Tab Views", this); + connect( tabViewsAction, SIGNAL(triggered()), this, SLOT(tabViews()) ); + m_viewMenuActions.append(tabViewsAction); QAction *undoAction = m_directory->undoAction(); undoAction->setShortcut(Qt::Key_Z | Qt::CTRL); @@ -587,27 +369,6 @@ namespace Isis { m_editMenuActions.append(undoAction); m_editMenuActions.append(redoAction); - - QAction *viewModeAction = new QAction("Toggle View Mode", this); - connect(viewModeAction, SIGNAL( triggered() ), - this, SLOT( toggleViewMode() ) ); - m_viewMenuActions.append(viewModeAction); - - m_cascadeViewsAction = new QAction("Cascade Views", this); - connect(m_cascadeViewsAction, SIGNAL( triggered() ), - centralWidget(), SLOT( cascadeSubWindows() ) ); - m_viewMenuActions.append(m_cascadeViewsAction); - - m_tileViewsAction = new QAction("Tile Views", this); - connect(m_tileViewsAction, SIGNAL( triggered() ), - centralWidget(), SLOT( tileSubWindows() ) ); - m_viewMenuActions.append(m_tileViewsAction); - - QAction *detachActiveViewAction = new QAction("Detach Active View", this); - connect(detachActiveViewAction, SIGNAL( triggered() ), - this, SLOT( detachActiveView() ) ); - m_viewMenuActions.append(detachActiveViewAction); - QAction *threadLimitAction = new QAction("Set Thread &Limit", this); connect(threadLimitAction, SIGNAL(triggered()), this, SLOT(configureThreadLimit())); @@ -624,21 +385,32 @@ namespace Isis { connect(activateWhatsThisAct, SIGNAL(triggered()), this, SLOT(enterWhatsThisMode())); m_helpMenuActions.append(activateWhatsThisAct); - - readSettings(m_directory->project() ); } /** - * Creates the main menus of the menu bar. + * Creates and fills the application menus of the menu bar. */ void IpceMainWindow::createMenus() { + m_fileMenu = menuBar()->addMenu(tr("&File")); m_fileMenu->setObjectName("fileMenu"); + // Get Directory FileMenu actions + foreach ( QAction *action, m_directory->fileMenuActions() ) { + m_fileMenu->addAction(action); + } + m_fileMenu->addSeparator(); + // Get FileMenu actions from the ipceMainWindow, Exit is the only action + foreach ( QAction *action, m_fileMenuActions ) { + m_fileMenu->addAction(action); + } m_projectMenu = menuBar()->addMenu(tr("&Project")); m_projectMenu->setObjectName("projectMenu"); - + // Get Project menu actions from Directory + foreach ( QAction *action, m_directory->projectMenuActions() ) { + m_projectMenu->addAction(action); + } // Allow tool tips to be displayed for the project menu's actions (e.g. "Bundle Adjustment") // This is a work around for Qt's what this text not working on disabled actions // (even though the Qt documentation says it should work on disabled QAction's). @@ -646,62 +418,88 @@ namespace Isis { m_editMenu = menuBar()->addMenu(tr("&Edit")); m_editMenu->setObjectName("editMenu"); + m_editMenu->addSeparator(); + // Get Edit menu actions from Directory + foreach ( QAction *action, m_directory->editMenuActions() ) { + m_editMenu->addAction(action); + } + // Get Edit menu actions from IpceMainWindow + foreach ( QAction *action, m_editMenuActions ) { + m_editMenu->addAction(action); + } m_viewMenu = menuBar()->addMenu("&View"); m_viewMenu->setObjectName("viewMenu"); + // Get View menu actions from Directory + foreach ( QAction *action, m_directory->viewMenuActions() ) { + m_viewMenu->addAction(action); + } + m_viewMenu->addSeparator(); + // Get View menu actions from IpceMainWindow + foreach ( QAction *action, m_viewMenuActions ) { + m_viewMenu->addAction(action); + } m_settingsMenu = menuBar()->addMenu("&Settings"); m_settingsMenu->setObjectName("settingsMenu"); + // Get Settings menu actions from Directory + foreach ( QAction *action, m_directory->settingsMenuActions() ) { + m_settingsMenu->addAction(action); + } + m_settingsMenu->addSeparator(); + // Get Settings menu actions from IpceMainWindow + foreach ( QAction *action, m_settingsMenuActions ) { + m_settingsMenu->addAction(action); + } m_helpMenu = menuBar()->addMenu("&Help"); m_helpMenu->setObjectName("helpMenu"); + // Get Help menu actions from Directory + foreach ( QAction *action, m_directory->helpMenuActions() ) { + m_helpMenu->addAction(action); + } + m_helpMenu->addSeparator(); + // Get Help menu actions from IpceMainWindow + foreach ( QAction *action, m_helpMenuActions ) { + m_helpMenu->addAction(action); + } } /** - * Write the window positioning and state information out to a - * config file. This allows us to restore the settings when we - * create another main window (the next time this program is run). - * - * The state will be saved according to the currently loaded project and its name. - * - * When no project is loaded (i.e. the default "Project" is open), the config file used is - * $HOME/.Isis/$APPNAME/$APPNAME_Project.config. - * When a project, ProjectName, is loaded, the config file used is - * $HOME/.Isis/$APPNAME/$APPNAME_ProjectName.config. - * - * @param[in] project Pointer to the project that is currently loaded (default is "Project") - * - * @internal - * @history 2016-11-09 Ian Humphrey - Settings are now written according to the loaded project. - * References #4358. - * @history 2017-10-17 Tyler Wilson Added a [recent projects] group for the saving and - * restoring of recently opened projects. References #4492. + * Create the tool bars and populates them with QActions from several sources. Actions are taken + * from an internal list of QActions and the Directory. */ - void IpceMainWindow::writeSettings(const Project *project) const { + void IpceMainWindow::createToolBars() { + m_permToolBar = new QToolBar(this); + QSize iconSize(25, 45); + m_permToolBar->setIconSize(iconSize); + m_permToolBar->setObjectName("PermanentToolBar"); + addToolBar(m_permToolBar); - // Ensure that we are not using a NULL pointer - if (!project) { - QString msg = "Cannot write settings with a NULL Project pointer."; - throw IException(IException::Programmer, msg, _FILEINFO_); + foreach ( QAction *action, m_directory->permToolBarActions() ) { + m_permToolBar->addAction(action); + } + + foreach (QAction *action, m_permToolBarActions) { + m_permToolBar->addAction(action); } + } + + + /** + * Writes the global settings like recent projects and thread count. + */ + void IpceMainWindow::writeGlobalSettings(Project *project) { + QString appName = QApplication::applicationName(); - QSettings projectSettings( - FileName("$HOME/.Isis/" + appName + "/" + appName + "_" + project->name() + ".config") - .expanded(), - QSettings::NativeFormat); - QSettings globalSettings( - FileName("$HOME/.Isis/" + appName + "/" + appName + "_" + "Project.config") - .expanded(), + QSettings globalSettings(FileName("$HOME/.Isis/" + appName + "/ipce.config").expanded(), QSettings::NativeFormat); - projectSettings.setValue("geometry", saveGeometry()); - projectSettings.setValue("windowState", saveState()); - projectSettings.setValue("size", size()); - projectSettings.setValue("pos", pos()); - - projectSettings.setValue("maxThreadCount", m_maxThreadCount); + if (project->isTemporaryProject()) { + globalSettings.setValue("geometry", QVariant(geometry())); + } globalSettings.setValue("maxThreadCount", m_maxThreadCount); globalSettings.setValue("maxRecentProjects",m_maxRecentProjects); @@ -763,12 +561,49 @@ namespace Isis { QString projName = project->name(); QString t0String=QString::number(t0); - if (!project->projectRoot().contains("tmpProject") && + if (!project->isTemporaryProject() && !projectPaths.contains( project->projectRoot())) { globalSettings.setValue(t0String+"%%%%%"+projName,project->projectRoot()); } } globalSettings.endGroup(); + globalSettings.sync(); + } + + + /** + * Write the window positioning and state information out to a + * config file. This allows us to restore the settings when we + * create another main window (the next time this program is run). + * + * The state will be saved according to the currently loaded project and its name. + * + * When no project is loaded (i.e. the default "Project" is open), the config file used is + * $HOME/.Isis/$APPNAME/ipce.config. + * When a project, ProjectName, is loaded, the config file used is + * project->projectRoot()/ipce.config. + * + * @param[in] project Pointer to the project that is currently loaded (default is "Project") + * + * @internal + * @history 2016-11-09 Ian Humphrey - Settings are now written according to the loaded project. + * References #4358. + * @history 2017-10-17 Tyler Wilson Added a [recent projects] group for the saving and + * restoring of recently opened projects. References #4492. + */ + void IpceMainWindow::writeSettings(Project *project) { + + // Ensure that we are not using a NULL pointer + if (!project) { + QString msg = "Cannot write settings with a NULL Project pointer."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + QSettings projectSettings(FileName(project->newProjectRoot() + "/ipce.config").expanded(), + QSettings::NativeFormat); + + projectSettings.setValue("geometry", QVariant(geometry())); + projectSettings.setValue("windowState", saveState()); + projectSettings.sync(); } @@ -776,9 +611,9 @@ namespace Isis { * Read the window positioning and state information from the config file. * * When running ipce without opening a project, the config file read is - * $HOME/.Isis/$APPNAME/$APPNAME_Project.config - * Otherwise, when running ipce and opening a project (ProjectName), the config file read is - * $HOME/.Isis/$APPNAME/$APPNAME_ProjectName.config + * $HOME/.Isis/$APPNAME/ipce.config + * When running ipce and opening a project (ProjectName), the config file read is + * project->projectRoot()/ipce.config * * @param[in] project (Project *) The project that was loaded. * @@ -786,8 +621,10 @@ namespace Isis { * @history Ian Humphrey - Settings are now read on a project name basis. References #4358. * @history Tyler Wilson 2017-11-02 - Settings now read recent projects. References #4492. * @history Tyler Wilson 2017-11-13 - Commented out a resize call near the end because it - * was messing with the positions of widgets after a - * project was loaded. Fixes #5075. + * was messing with the positions of widgets after a project was loaded. + * Fixes #5075. + * @history Makayla Shepherd 2018-06-10 - Settings are read from the project root ipce.config. + * If that does not exist then we read from .Isis/ipce/ipce.config. */ void IpceMainWindow::readSettings(Project *project) { // Ensure that the Project pointer is not NULL @@ -795,72 +632,92 @@ namespace Isis { QString msg = "Cannot read settings with a NULL Project pointer."; throw IException(IException::Programmer, msg, _FILEINFO_); } + + // Set the path of the settings file + // The default is to assume that the project has an ipce.config in it + // If the file does not exist then we read settings from .Isis/ipce/ipce.config + QString appName = QApplication::applicationName(); + QString filePath = project->projectRoot() + "/ipce.config"; + bool isFullScreen = false; + if (!FileName(filePath).fileExists()) { + filePath = "$HOME/.Isis/" + appName + "/ipce.config"; + // If the $HOME/.Isis/ipce/ipce.config does not exist then we want ipce to show up in + // in full screen. In other words the default geometry is full screen + if (!FileName(filePath).fileExists()) { + isFullScreen = true; + } + } + if (project->name() == "Project") { setWindowTitle("ipce"); } else { setWindowTitle( project->name() ); - QString projName = project->name(); - setWindowTitle(projName ); } - QString appName = QApplication::applicationName(); - - QSettings settings( - FileName("$HOME/.Isis/" + appName + "/" + appName + "_" + project->name() + ".config") - .expanded(), QSettings::NativeFormat); - restoreGeometry(settings.value("geometry").toByteArray()); - restoreState(settings.value("windowState").toByteArray()); + QSettings projectSettings(FileName(filePath).expanded(), QSettings::NativeFormat); - QStringList projectNameList; - QStringList projectPathList; - settings.beginGroup("recent_projects"); - QStringList keys = settings.allKeys(); - - QRegExp underscore("%%%%%"); - - foreach (QString key, keys) { - QString childKey = "recent_projects/"+key; - QString projectPath = settings.value(key).toString(); - QString projectName = projectPath.split("/").last(); - projectPathList.append(projectPath) ; - projectNameList.append(projectName); + if (!isFullScreen) { + setGeometry(projectSettings.value("geometry").value<QRect>()); + if (!project->isTemporaryProject()) { + restoreState(projectSettings.value("windowState").toByteArray()); + } + } + else { + this->showMaximized(); } - settings.endGroup(); - - QStringList projectPathReverseList; + if (project->name() == "Project") { + QSettings globalSettings(FileName("$HOME/.Isis/" + appName + "/ipce.config").expanded(), + QSettings::NativeFormat); - for (int i = projectPathList.count()-1;i>=0;i--) { - projectPathReverseList.append(projectPathList[i]); - } + QStringList projectNameList; + QStringList projectPathList; + globalSettings.beginGroup("recent_projects"); + QStringList keys = globalSettings.allKeys(); + QRegExp underscore("%%%%%"); - QStringList projectPathListTruncated; + foreach (QString key, keys) { + QString childKey = "recent_projects/"+key; + QString projectPath = globalSettings.value(key).toString(); + QString projectName = projectPath.split("/").last(); + projectPathList.append(projectPath) ; + projectNameList.append(projectName); + } - int i =0; + globalSettings.endGroup(); - foreach (QString proj,projectPathReverseList) { - if (i <= m_maxRecentProjects) { - projectPathListTruncated.append(proj); - i++; + QStringList projectPathReverseList; + for (int i = projectPathList.count() - 1; i >= 0; i--) { + projectPathReverseList.append(projectPathList[i]); } - else - break; - } + QStringList projectPathListTruncated; - m_directory->setRecentProjectsList(projectPathListTruncated); - m_directory->updateRecentProjects(); + int i =0; + + foreach (QString proj,projectPathReverseList) { + if (i <= m_maxRecentProjects) { + projectPathListTruncated.append(proj); + i++; + } + else + break; + } + + m_directory->setRecentProjectsList(projectPathListTruncated); + m_directory->updateRecentProjects(); + m_maxThreadCount = globalSettings.value("maxThreadCount", m_maxThreadCount).toInt(); + applyMaxThreadCount(); + } // The geom/state isn't enough for main windows to correctly remember // their position and size, so let's restore those on top of // the geom and state. - if (!settings.value("pos").toPoint().isNull()) - move(settings.value("pos").toPoint()); - - m_maxThreadCount = settings.value("maxThreadCount", m_maxThreadCount).toInt(); - applyMaxThreadCount(); - + if (!projectSettings.value("pos").toPoint().isNull()) { + move(projectSettings.value("pos").toPoint()); + } +// m_directory->project()->setClean(true); } @@ -890,7 +747,8 @@ namespace Isis { m_directory->project()->save(); } } - writeSettings(m_directory->project()); + // Write global settings, for now this is for the project "Project" + writeGlobalSettings(m_directory->project()); m_directory->project()->clear(); QMainWindow::closeEvent(event); @@ -942,220 +800,23 @@ namespace Isis { /** - * Slot to connect to the subWindowActivated signal from the central - * QMdiArea. Updates the active view to the active sub window, or - * sets it to null if the active window is not an AbstractProjectItemView. - * - * @param[in] window (QMdiSubWindow *) The active sub window. + * Tabs all open attached/detached views */ - void IpceMainWindow::onSubWindowActivated(QMdiSubWindow * window) { - if (window) { - setActiveView( qobject_cast<AbstractProjectItemView *>( window->widget() ) ); - } - else { - setActiveView(0); - } - } - - - /** - * Toggles the view mode of the central QMdiArea between tabbed and - * sub window mode. - */ - void IpceMainWindow::toggleViewMode() { - QMdiArea *mdiArea = qobject_cast<QMdiArea *>( centralWidget() ); - if (mdiArea->viewMode() == QMdiArea::SubWindowView) { - setTabbedViewMode(); - } - else { - setSubWindowViewMode(); - } - } - - - /** - * Sets the QMdiArea in the central widget to the tabbed view mode - * and updates the appropriate actions. - */ - void IpceMainWindow::setTabbedViewMode() { - QMdiArea *mdiArea = qobject_cast<QMdiArea *>( centralWidget() ); - mdiArea->setViewMode(QMdiArea::TabbedView); - m_cascadeViewsAction->setEnabled(false); - m_tileViewsAction->setEnabled(false); - } - - - /** - * Sets the QMdiArea in the central widget to the sub window view - * mode and updates the appropriate actions. - */ - void IpceMainWindow::setSubWindowViewMode() { - QMdiArea *mdiArea = qobject_cast<QMdiArea *>( centralWidget() ); - mdiArea->setViewMode(QMdiArea::SubWindowView); - m_cascadeViewsAction->setEnabled(true); - m_tileViewsAction->setEnabled(true); - } - - /** - * Closes the detached window and removes it from the m_detachedViews list - */ - void IpceMainWindow::closeDetachedView() { - - ViewSubWindow *viewWindow = qobject_cast<ViewSubWindow *>( sender() ); - - if (!viewWindow) { - return; - } - - m_detachedViews.removeAt(m_detachedViews.indexOf(viewWindow)); - viewWindow->close(); - } - - - /** - * Moves the active view from the mdi area to its own independent - * window. The view, its toolbars, and menu actions, are removed - * from the main window and placed in an independent - * QMainWindow. The new window contains the view as well as its - * toolbars and menu actions. A detached view will not be set as the - * active view when it is activated. - */ - void IpceMainWindow::detachActiveView() { - AbstractProjectItemView *view = m_activeView; - - if (!m_activeView) { - return; - } + void IpceMainWindow::tabViews() { + // tabifyDockWidget() takes two widgets and tabs them, so an easy way to do + // this is to grab the first view and tab the rest with the first. + QDockWidget *firstView = m_viewDocks.first(); - QMdiArea *mdiArea = qobject_cast<QMdiArea *>( centralWidget() ); - if (mdiArea) { - mdiArea->removeSubWindow(view); - mdiArea->closeActiveSubWindow(); - } - - ViewSubWindow *newWindow = new ViewSubWindow(this, Qt::Window); - - connect( newWindow, SIGNAL( closeWindow() ), - this, SLOT( closeDetachedView() ) ); - - connect( newWindow, SIGNAL( closeWindow() ), - view, SLOT( deleteLater() ) ); + foreach (QDockWidget *currentView, m_viewDocks) { + // We have to reattach a view before it can be tabbed. If it is attached, + // this will have no affect. + currentView->setFloating(false); - m_detachedViews.append(newWindow); - newWindow->setCentralWidget(view); - newWindow->setWindowTitle( view->windowTitle() ); - - if ( !view->permToolBarActions().isEmpty() ) { - QToolBar *permToolBar = new QToolBar(newWindow); - foreach ( QAction *action, view->permToolBarActions() ) { - permToolBar->addAction(action); + if (currentView == firstView) { + continue; } - newWindow->addToolBar(permToolBar); + tabifyDockWidget(firstView, currentView); } - - if ( !view->activeToolBarActions().isEmpty() ) { - QToolBar *activeToolBar = new QToolBar(newWindow); - foreach ( QAction *action, view->activeToolBarActions() ) { - activeToolBar->addAction(action); - } - newWindow->addToolBar(activeToolBar); - } - - if ( !view->toolPadActions().isEmpty() ) { - QToolBar *toolPad = new QToolBar(newWindow); - foreach ( QAction *action, view->toolPadActions() ) { - toolPad->addAction(action); - } - newWindow->addToolBar(Qt::RightToolBarArea, toolPad); - } - - QMenuBar *menuBar = new QMenuBar(newWindow); - newWindow->setMenuBar(menuBar); - - if ( !view->fileMenuActions().isEmpty() ) { - QMenu *fileMenu = new QMenu("&File", newWindow); - foreach ( QAction *action, view->fileMenuActions() ) { - fileMenu->addAction(action); - } - menuBar->addMenu(fileMenu); - } - - if ( !view->projectMenuActions().isEmpty() ) { - QMenu *projectMenu = new QMenu("&Project", newWindow); - foreach ( QAction *action, view->projectMenuActions() ) { - projectMenu->addAction(action); - } - menuBar->addMenu(projectMenu); - } - - if ( !view->editMenuActions().isEmpty() ) { - QMenu *editMenu = new QMenu("&Edit", newWindow); - foreach ( QAction *action, view->editMenuActions() ) { - editMenu->addAction(action); - } - menuBar->addMenu(editMenu); - } - - QAction *reattachAction = new QAction("Reattach View", newWindow); - connect( reattachAction, SIGNAL( triggered() ), - this, SLOT( reattachView() ) ); - - QMenu *viewMenu = new QMenu("&View", newWindow); - - viewMenu->addAction(reattachAction); - - if ( !view->viewMenuActions().isEmpty() ) { - foreach ( QAction *action, view->viewMenuActions() ) { - viewMenu->addAction(action); - } - } - menuBar->addMenu(viewMenu); - - if ( !view->settingsMenuActions().isEmpty() ) { - QMenu *settingsMenu = new QMenu("S&ettings", newWindow); - foreach ( QAction *action, view->settingsMenuActions() ) { - settingsMenu->addAction(action); - } - menuBar->addMenu(settingsMenu); - } - - if ( !view->helpMenuActions().isEmpty() ) { - QMenu *helpMenu = new QMenu("&Help", newWindow); - foreach ( QAction *action, view->helpMenuActions() ) { - helpMenu->addAction(action); - } - menuBar->addMenu(helpMenu); - } - newWindow->show(); - } - - - /** - * Reattaches a detached view. This slot can only be called by a QAction - * from a QMainWindow that contains the view. The view is added to - * the main window and the window that previously contained it is - * deleted. - */ - void IpceMainWindow::reattachView() { - QAction *reattachAction = qobject_cast<QAction *>( sender() ); - if (!reattachAction) { - return; - } - - QMainWindow *viewWindow = qobject_cast<QMainWindow *>( reattachAction->parent() ); - if (!viewWindow) { - return; - } - - AbstractProjectItemView *view = qobject_cast<AbstractProjectItemView *>( viewWindow->centralWidget() ); - if (!view) { - return; - } - - view->setParent(this); - viewWindow->deleteLater(); - - addView(view); } @@ -1165,5 +826,4 @@ namespace Isis { void IpceMainWindow::raiseWarningTab() { m_warningsDock->raise(); } - } diff --git a/isis/src/qisis/apps/ipce/IpceMainWindow.h b/isis/src/qisis/apps/ipce/IpceMainWindow.h index b56d732babaae7b345f0f0f71351546a769e7e3b..710149b8fc76271b4d9d17522a84eaeadcc94b61 100644 --- a/isis/src/qisis/apps/ipce/IpceMainWindow.h +++ b/isis/src/qisis/apps/ipce/IpceMainWindow.h @@ -24,6 +24,8 @@ */ #include "ViewSubWindow.h" +#include <QEvent> +#include <QMainWindow> #include <QPointer> #include <QProgressBar> #include <QMdiSubWindow> @@ -111,7 +113,7 @@ namespace Isis { * detached views from the m_detachedViews list appropriately. * This fixes an issue where a detached view would appear to be * open even after it has been closed. Fixes #5109. - * @history 2017-11-12 Tyler Wilson - Removed a resize call in readSettings because it + * @history 2017-11-12 Tyler Wilson - Removed a resize call in readSettings because it * was screwing up the display of widgets when a project is loaded. * Also switched the order in which a project is saved. A project is * cleared after it is saved, and not before (which had been the previous @@ -129,7 +131,40 @@ namespace Isis { * test to determine whether project needs saving. * @history 2018-05-01 Tracie Sucharski - Code accidently left commented from previous checking. * Fixes #5412. - * + * @history 2018-05-31 Christopher Combs - Added support for JigsawRunWidget to be created as a + * dockable widget in addView(). Fixes #5428. + * @history 2018-05-30 Tracie Sucharski - Fix to handle the re-factored docked views. + * Changed from MDI to SDI, changing the centralWidget to a dumy, unused + * widget. Remove all methods having to do with MDI sub-windows, + * detached views. The dock widgets holding the views are saved off + * for cleanup because there is no way to get the dock from the view. + * Cleanup connections are made for the views and the docks to ensure + * that cleanup happens for both. Fixes #5433. + * @history 2018-06-13 Tracie Sucharski - Fixed cleanup of views and QDockWidgets. + * @history 2018-06-13 Kaitlyn Lee - Since views now inherit from QMainWindow, each individual + * view has its own toolbar, so having an active toolbar and tool pad is + * not needed. Removed code adding the save active control net button and + * the toolpad, since control nets can be saved with the project save button. + * @history 2018-06-14 Christopher Combs - Changed addView method to take in JigsawRunWidget as + * a QDockWidget object instead of wrapping it in one. + * @history 2018-06-15 Tracie Sucharski - Fixed break to recent projects. The readSettings + * must be called before initializeActions to get the recent projects + * from the config file. + * @history 2018-06-18 Makayla Shepherd - Set the QApplication name so that BundleAdjust does + * not output text to the command line for ipce. Fixes #4171. + * @history 2018-06-19 Kaitlyn Lee - Added tabViews() and the menu option under the View menu to + * tab the views. Currently, this can tab all attached/detached views. I + * left the line setting dock options to allow grouped dragging, but tabbing + * views does not always work with this enabled. With this option enabled, the + * type of a view will randomly change and setting its type has no effect. + * Use windowType() to get the type. Also added the toolbar title in the + * permanent toolbar constructor. + * @history 2018-06-22 Tracie Sucharski - Cleanup destruction of dock widgets and the views they + * hold. Extra destroy slots were causing double deletion of memory. + * @history 2018-06-22 Tracie Sucharski - Added a showEvent handler so that the project clean + * state can be reset after the IpceMainWindow::show() causes resize and + * move events which in turn cause the project clean flag to be false + * even though the project has just opened. */ class IpceMainWindow : public QMainWindow { Q_OBJECT @@ -138,41 +173,37 @@ namespace Isis { ~IpceMainWindow(); public slots: - void addView(QWidget *newWidget); + void addView(QWidget *newWidget, Qt::DockWidgetArea area = Qt::LeftDockWidgetArea, + Qt::Orientation orientation = Qt::Horizontal); void removeView(QWidget *view); void removeAllViews(); - void setActiveView(AbstractProjectItemView *view); - void updateMenuActions(); - void updateToolBarActions(); void readSettings(Project *); + void writeSettings(Project *project); + void writeGlobalSettings(Project *project); protected: + void showEvent(QShowEvent *event); void closeEvent(QCloseEvent *event); bool eventFilter(QObject *watched, QEvent *event); private slots: void configureThreadLimit(); void enterWhatsThisMode(); - void onSubWindowActivated(QMdiSubWindow *); - void toggleViewMode(); - void setTabbedViewMode(); - void setSubWindowViewMode(); - - void closeDetachedView(); - void detachActiveView(); - void reattachView(); + void tabViews(); void raiseWarningTab(); + void cleanupViewDockList(QObject *obj); + private: Q_DISABLE_COPY(IpceMainWindow); void applyMaxThreadCount(); - void createMenus(); - void writeSettings(const Project *project) const; void initializeActions(); + void createMenus(); + void createToolBars(); private: /** @@ -182,8 +213,10 @@ namespace Isis { QPointer<Directory> m_directory; QDockWidget *m_projectDock; - QList<ViewSubWindow *> m_detachedViews; //!< List to keep track of any detached main windows QDockWidget *m_warningsDock; + + QList<QDockWidget *> m_viewDocks; //!< QDockWidgets holding the views + /** * This is the "goal" or "estimated" maximum number of active threads running in this program * at once. For now, the GUI consumes 1 thread and QtConcurrent @@ -194,8 +227,6 @@ namespace Isis { static const int m_maxRecentProjects = 5; QToolBar *m_permToolBar; //!< The toolbar for actions that rarely need to be changed. - QToolBar *m_activeToolBar; //<! The toolbar for the actions of the current tool. - QToolBar *m_toolPad; //<! The toolbar for the actions that activate tools. QMenu *m_fileMenu; //!< Menu for the file actions QMenu *m_projectMenu; //!< Menu for the project actions @@ -212,13 +243,9 @@ namespace Isis { QList<QAction *> m_helpMenuActions;//!< Internal list of help actions QList<QAction *> m_permToolBarActions;//!< Internal list of permanent toolbar actions - QList<QAction *> m_activeToolBarActions;//!< Internal list of active toolbar actions - QList<QAction *> m_toolPadActions;//!< Internal list of toolpad actions QAction *m_cascadeViewsAction; //!< Action that cascades the mdi area QAction *m_tileViewsAction; //!< Action that tiles the mdi area - - AbstractProjectItemView *m_activeView; //!< The active view }; } diff --git a/isis/src/qisis/objs/AbstractProjectItemView/AbstractProjectItemView.cpp b/isis/src/qisis/objs/AbstractProjectItemView/AbstractProjectItemView.cpp index 3d4d699b000fb0166e8c64b841a1f4a0466b4156..94143389e3e65aefc42c3e59b5e0dab6607b76f1 100644 --- a/isis/src/qisis/objs/AbstractProjectItemView/AbstractProjectItemView.cpp +++ b/isis/src/qisis/objs/AbstractProjectItemView/AbstractProjectItemView.cpp @@ -28,6 +28,7 @@ #include <QDragMoveEvent> #include <QDropEvent> #include <QList> +#include <QMainWindow> #include <QWidget> #include "ProjectItem.h" @@ -39,9 +40,11 @@ namespace Isis { /** * Constructs the AbstractProjectItemView. * - * @param[in] parent (QWidget *) The parent widget + * @param[in] parent (QMainWindow *) The parent widget */ - AbstractProjectItemView::AbstractProjectItemView(QWidget *parent) : QWidget(parent) { + AbstractProjectItemView::AbstractProjectItemView(QWidget *parent) : QMainWindow(parent) { + + setWindowFlags(Qt::Widget); m_internalModel = new ProjectItemProxyModel(this); setAcceptDrops(true); } @@ -54,7 +57,7 @@ namespace Isis { * @param[in] model (ProjectItemModel *) The new model */ void AbstractProjectItemView::setModel(ProjectItemModel *model) { - if (ProjectItemProxyModel *proxyModel = + if (ProjectItemProxyModel *proxyModel = qobject_cast<ProjectItemProxyModel *>( internalModel() ) ) { proxyModel->setSourceModel(model); } @@ -68,7 +71,7 @@ namespace Isis { * @return @b ProjectItemModel * The model. */ ProjectItemModel *AbstractProjectItemView::model() { - if (ProjectItemProxyModel *proxyModel = + if (ProjectItemProxyModel *proxyModel = qobject_cast<ProjectItemProxyModel *>( internalModel() ) ) { return proxyModel->sourceModel(); } @@ -126,7 +129,7 @@ namespace Isis { } } - + /** * Drops the data into the internal model if it can accept the data. * @@ -142,110 +145,74 @@ namespace Isis { } } - - /** - * Returns a list of actions appropriate for the permanent tool bar. - * - * @return @b QList<QAction *> The actions - */ - QList<QAction *> AbstractProjectItemView::permToolBarActions() { - return QList<QAction *>(); - } + void AbstractProjectItemView::moveEvent(QMoveEvent *event) { + QMainWindow::moveEvent(event); - /** - * Returns a list of actions appropriate for the active tool bar. - * - * @return @b QList<QAction *> The actions - */ - QList<QAction *> AbstractProjectItemView::activeToolBarActions() { - return QList<QAction *>(); + emit windowChangeEvent(false); } - /** - * Returns a list of actions appropriate for the tool pad. - * - * @return @b QList<QAction *> The actions - */ - QList<QAction *> AbstractProjectItemView::toolPadActions() { - return QList<QAction *>(); - } - + void AbstractProjectItemView::resizeEvent(QResizeEvent *event) { + QMainWindow::resizeEvent(event); - /** - * Returns a list of actions appropriate for a context menu. - * - * @return @b QList<QAction *> The actions - */ - QList<QAction *> AbstractProjectItemView::contextMenuActions() { - return QList<QAction *>(); + emit windowChangeEvent(false); } /** - * Returns a list of actions appropriate for a file menu. + * Enables actions when cursor enters the view * - * @return @b QList<QAction *> The actions + * @param event The enter event */ - QList<QAction *> AbstractProjectItemView::fileMenuActions() { - return QList<QAction *>(); + void AbstractProjectItemView::enterEvent(QEvent *event) { + enableActions(); } /** - * Returns a list of actions appropriate for a project menu. + * Disables actions when cursor leaves the view. * - * @return @b QList<QAction *> The actions + * @param event The leave event */ - QList<QAction *> AbstractProjectItemView::projectMenuActions() { - return QList<QAction *>(); + void AbstractProjectItemView::leaveEvent(QEvent *event) { + disableActions(); } /** - * Returns a list of actions appropriate for an edit menu. - * - * @return @b QList<QAction *> The actions + * Disables toolbars and toolpad actions */ - QList<QAction *> AbstractProjectItemView::editMenuActions() { - return QList<QAction *>(); + void AbstractProjectItemView::disableActions() { + foreach (QAction *action, actions()) { + action->setDisabled(true); + } } /** - * Returns a list of actions appropriate for a view menu. - * - * @return @b QList<QAction *> The actions + * Enables toolbars and toolpad actions */ - QList<QAction *> AbstractProjectItemView::viewMenuActions() { - return QList<QAction *>(); - } - - - /** - * Returns a list of actions appropriate for a settings menu. - * - * @return @b QList<QAction *> The actions - */ - QList<QAction *> AbstractProjectItemView::settingsMenuActions() { - return QList<QAction *>(); + void AbstractProjectItemView::enableActions() { + foreach (QAction *action, actions()) { + action->setEnabled(true); + } } /** - * Returns a list of actions appropriate for a help menu. + * Returns a list of actions appropriate for a context menu. * * @return @b QList<QAction *> The actions */ - QList<QAction *> AbstractProjectItemView::helpMenuActions() { + QList<QAction *> AbstractProjectItemView::contextMenuActions() { return QList<QAction *>(); } - + /** * Returns the current item of the model. - * + * * @return @b ProjectItem * The item */ ProjectItem *AbstractProjectItemView::currentItem() { @@ -262,7 +229,7 @@ namespace Isis { return model()->selectedItems(); } - + /** * Adds an item to the view. The item must be part of the view's * model. This method can be overriden in a subclass to filter out @@ -299,7 +266,7 @@ namespace Isis { * @param[in] item (ProjectItem *) The item to remove. */ void AbstractProjectItemView::removeItem(ProjectItem *item) { - if (ProjectItemProxyModel *proxyModel = + if (ProjectItemProxyModel *proxyModel = qobject_cast<ProjectItemProxyModel *>( internalModel() ) ) { proxyModel->removeItem(item); } diff --git a/isis/src/qisis/objs/AbstractProjectItemView/AbstractProjectItemView.h b/isis/src/qisis/objs/AbstractProjectItemView/AbstractProjectItemView.h index 1ca80d5b3172fe37e8ff8107602d74be3308a5c3..6147b77c54bb3f42e8b9c9e503b1ee5f3bd3b528 100644 --- a/isis/src/qisis/objs/AbstractProjectItemView/AbstractProjectItemView.h +++ b/isis/src/qisis/objs/AbstractProjectItemView/AbstractProjectItemView.h @@ -23,16 +23,18 @@ * http://www.usgs.gov/privacy.html. */ -#include <QWidget> +#include <QMainWindow> class QAction; class QDragEnterEvent; +class QWidget; template <typename T> class QList; namespace Isis { class ProjectItem; class ProjectItemModel; + /** * AbstractProjectItemView is a base class for views of a * ProjectItemModel in Qt's model-view @@ -42,11 +44,6 @@ namespace Isis { * ProjectItemProxyModel that represents the items appropriately for * the view. * - * An AbstractProjectItemView may provide QActions for manipulating - * the view. These actions can be accessed in different contexts - * through toolBarActions(), menuActions(), and - * contextMenuActions(). - * * When mime data is dropped on a view the view adds the selected * items from the source model to the view. * @@ -55,13 +52,30 @@ namespace Isis { * @author 2015-10-21 Jeffrey Covington * @internal * @history 2015-10-21 Jeffrey Covington - Original version. - * @history 2016-06-27 Ian Humphrey - Minor updates to documentation and coding standards. + * @history 2016-06-27 Ian Humphrey - Minor updates to documentation and coding standards. * Fixes #4004. * @history 2016-07-28 Tracie Sucharski - Implemented removeItem and removeItems methods. * @history 2016-08-25 Adam Paquette - Minor updates to documentation. * Fixes #4299. + * @history 2018-05-29 Tracie Sucharski & Summer Stapleton - updated to inherit from QMainWindow + * instead of QWidget. This updates all views in the ipce main window + * to be main windows themselves, changing from an mdi interface to an + * sdi interface. + * @history 2018-05-30 Tracie Sucharski - Added the WindowFlag to set this as a Widget. + * @history 2018-06-15 Kaitlyn Lee - Removed methods returing toolbar and menu actions because each + * individual has its own toolbar. These methods are not needed anymore. + * @History 2018-06-18 Summer Stapleton - Overloaded moveEvent and resizeEvent and added a + * windowChangeEvent signal to allow project to recognize a new save + * state. Fixes #5114 + * @history 2018-06-25 Kaitlyn Lee - When multiple views are open, there is a possibility of getting + * ambiguous shortcut errors. To counter this, we need a way to focus on one + * widget. Giving the views focus did not work completely. Instead, + * enabling/disabling actions was the best option. Added enableActions(), + * disableActions(), enterEvent(), and leaveEvent(). On default, a view's + * actions are disabled. To enable the actions, move the cursor over the view. + * When a user moves the cursor outside of the view, the actions are disabled. */ - class AbstractProjectItemView : public QWidget { + class AbstractProjectItemView : public QMainWindow { Q_OBJECT @@ -70,30 +84,29 @@ namespace Isis { virtual void setModel(ProjectItemModel *model); virtual ProjectItemModel *model(); - + virtual void dragEnterEvent(QDragEnterEvent *event); virtual void dragMoveEvent(QDragMoveEvent *event); virtual void dropEvent(QDropEvent *event); - virtual QList<QAction *> permToolBarActions(); - virtual QList<QAction *> activeToolBarActions(); - virtual QList<QAction *> toolPadActions(); - + virtual void moveEvent(QMoveEvent *event); + virtual void resizeEvent(QResizeEvent *event); + + virtual void enterEvent(QEvent *event); + virtual void leaveEvent(QEvent *event); + virtual void enableActions(); + virtual QList<QAction *> contextMenuActions(); - virtual QList<QAction *> fileMenuActions(); - virtual QList<QAction *> projectMenuActions(); - virtual QList<QAction *> editMenuActions(); - virtual QList<QAction *> viewMenuActions(); - virtual QList<QAction *> settingsMenuActions(); - virtual QList<QAction *> helpMenuActions(); - virtual ProjectItem *currentItem(); virtual QList<ProjectItem *> selectedItems(); virtual ProjectItemModel *internalModel(); virtual void setInternalModel(ProjectItemModel *model); + signals: + void windowChangeEvent(bool event); + public slots: virtual void addItem(ProjectItem *item); virtual void addItems(QList<ProjectItem *> items); @@ -101,10 +114,11 @@ namespace Isis { virtual void removeItem(ProjectItem *item); virtual void removeItems(QList<ProjectItem *> items); + virtual void disableActions(); + private: ProjectItemModel *m_internalModel; //!< The internal model used by the view }; - } #endif diff --git a/isis/src/qisis/objs/AbstractProjectItemView/ProjectItemViewMenu.cpp b/isis/src/qisis/objs/AbstractProjectItemView/ProjectItemViewMenu.cpp new file mode 100644 index 0000000000000000000000000000000000000000..73e7d5bcd8080d51a9f12a569f8eead6e526a9da --- /dev/null +++ b/isis/src/qisis/objs/AbstractProjectItemView/ProjectItemViewMenu.cpp @@ -0,0 +1,37 @@ +/** + * @file + * $Date$ + * $Revision$ + * + * Unless noted otherwise, the portions of Isis written by the USGS are + * public domain. See individual third-party library and package descriptions + * for intellectual property information, user agreements, and related + * information. + * + * Although Isis has been used by the USGS, no warranty, expressed or + * implied, is made by the USGS as to the accuracy and functioning of such + * software and related material nor shall the fact of distribution + * constitute any such warranty, and no responsibility is assumed by the + * USGS in connection therewith. + * + * For additional information, launch + * $ISISROOT/doc//documents/Disclaimers/Disclaimers.html + * in a browser or see the Privacy & Disclaimers page on the Isis website, + * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on + * http://www.usgs.gov/privacy.html. + */ +#include "ProjectItemViewMenu.h" + +namespace Isis { + + + /** + * Overrides the closeEvent to emit the signal menuClosed(). + * menuClosed() is connected to the slot disableActions() in a view. + * + * @param event The close event + */ + void ProjectItemViewMenu::closeEvent(QCloseEvent *event) { + emit menuClosed(); + } +} diff --git a/isis/src/qisis/objs/AbstractProjectItemView/ProjectItemViewMenu.h b/isis/src/qisis/objs/AbstractProjectItemView/ProjectItemViewMenu.h new file mode 100644 index 0000000000000000000000000000000000000000..50b7979b8f57e015160455b9953bfe4cb2cf3df4 --- /dev/null +++ b/isis/src/qisis/objs/AbstractProjectItemView/ProjectItemViewMenu.h @@ -0,0 +1,54 @@ +#ifndef ProjectItemViewMenu_h +#define ProjectItemViewMenu_h +/** + * @file + * $Date$ + * $Revision$ + * + * Unless noted otherwise, the portions of Isis written by the USGS are + * public domain. See individual third-party library and package descriptions + * for intellectual property information, user agreements, and related + * information. + * + * Although Isis has been used by the USGS, no warranty, expressed or + * implied, is made by the USGS as to the accuracy and functioning of such + * software and related material nor shall the fact of distribution + * constitute any such warranty, and no responsibility is assumed by the + * USGS in connection therewith. + * + * For additional information, launch + * $ISISROOT/doc//documents/Disclaimers/Disclaimers.html + * in a browser or see the Privacy & Disclaimers page on the Isis website, + * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on + * http://www.usgs.gov/privacy.html. + */ + +#include <QMenu> + +namespace Isis { + + /** + * QMenu subclass that overrides the closeEvent. Used in views to disable + * actions when a menu is visible and a user clicks outside of a view. + * + * @author 2018-06-27 Kaitlyn Lee + * + * @internal + * @history 2018-06-27 Kaitlyn Lee - Original version. + */ + + class ProjectItemViewMenu : public QMenu { + Q_OBJECT + + public: + ProjectItemViewMenu(const QString &title, QWidget *parent = 0) : QMenu(title, parent){}; + + signals: + void menuClosed(); + + private: + void closeEvent(QCloseEvent *event); + }; +} + +#endif diff --git a/isis/src/qisis/objs/BundleObservationView/BundleObservationView.cpp b/isis/src/qisis/objs/BundleObservationView/BundleObservationView.cpp index 7b29484de477f96218e5f28bda24b5dbd3091b58..ebbd350b2377d8c377f0e5e11f57c9da3c819f52 100755 --- a/isis/src/qisis/objs/BundleObservationView/BundleObservationView.cpp +++ b/isis/src/qisis/objs/BundleObservationView/BundleObservationView.cpp @@ -38,9 +38,9 @@ namespace Isis { - /** + /** * Creates a view showing the CSV or text files from BundleSolutionInfo. - * + * * @param FileItemQsp fileItem QSharedPointer to the fileItem from the ProjectItemModel */ BundleObservationView::BundleObservationView(FileItemQsp fileItem, QWidget *parent): @@ -156,9 +156,7 @@ namespace Isis { // NOTE: QHeaderView::ResizeToContents does not allow user to resize by dragging column divider qtable->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); - QVBoxLayout *layout = new QVBoxLayout; - setLayout(layout); - layout->addWidget(qtable); + setCentralWidget(qtable); QSizePolicy policy = sizePolicy(); policy.setHorizontalPolicy(QSizePolicy::Expanding); @@ -198,10 +196,7 @@ namespace Isis { file.close(); - QVBoxLayout *layout = new QVBoxLayout; - setLayout(layout); - layout->addWidget(qText); - + setCentralWidget(qText); qText->moveCursor(QTextCursor::Start); QSizePolicy policy = sizePolicy(); @@ -217,6 +212,3 @@ namespace Isis { BundleObservationView::~BundleObservationView() { } } - - - diff --git a/isis/src/qisis/objs/BundleObservationView/BundleObservationView.h b/isis/src/qisis/objs/BundleObservationView/BundleObservationView.h index 6921c422ac902a4d41bd08703598d1ff8bc9c2ae..30cf4fd63e9699484714910980a58ccfe8e3db2f 100755 --- a/isis/src/qisis/objs/BundleObservationView/BundleObservationView.h +++ b/isis/src/qisis/objs/BundleObservationView/BundleObservationView.h @@ -47,6 +47,9 @@ namespace Isis{ * @history 2018-04-16 Ken Edmundson - Modified display of residuals.csv to properly show the * rejected column if there are rejected measures. Also displays * rejected measure row in red. + * @history 2018-06-06 Kaitlyn Lee - Set a central widget and removed layout (it is not needed + * after setting a central widget) because AbstractProjectItemView was + * updated to inherit from QMainWindow. */ class BundleObservationView : public AbstractProjectItemView diff --git a/isis/src/qisis/objs/CnetEditorView/CnetEditorView.cpp b/isis/src/qisis/objs/CnetEditorView/CnetEditorView.cpp index eca23209c60b0dfd915fd4dfaec8dc7e3d71a19e..4c88121f902d0bc7dc5fd06dd9536b13ac90f257 100644 --- a/isis/src/qisis/objs/CnetEditorView/CnetEditorView.cpp +++ b/isis/src/qisis/objs/CnetEditorView/CnetEditorView.cpp @@ -37,8 +37,6 @@ #include <QTabWidget> #include <QToolBar> #include <QtXml> -#include <QVBoxLayout> -#include <QWidgetAction> #include "Control.h" #include "ControlNet.h" @@ -46,9 +44,8 @@ #include "Directory.h" #include "FileName.h" #include "Project.h" -#include "ToolPad.h" #include "XmlStackedHandlerReader.h" - +#include "ProjectItemViewMenu.h" namespace Isis { /** @@ -60,123 +57,114 @@ namespace Isis { // TODO: This layout should be inside of the cnet editor widget, but I put it here to not // conflict with current work in the cnet editor widget code. //QWidget *result = new QWidget; - QGridLayout *resultLayout = new QGridLayout; - setLayout(resultLayout); - - int row = 0; - QMenuBar *menuBar = new QMenuBar; - resultLayout->addWidget(menuBar, row, 0, 1, 2); - row++; + QWidget *centralWidget = new QWidget; + setCentralWidget(centralWidget); + QGridLayout *resultLayout = new QGridLayout; + centralWidget->setLayout(resultLayout); m_cnetEditorWidget = new CnetEditorWidget(control, configFile.expanded()); m_control = control; - resultLayout->addWidget(m_cnetEditorWidget, row, 0, 1, 2); - row++; - - // Populate the menu... - QMap< QAction *, QList< QString > > actionMap = m_cnetEditorWidget->menuActions(); - QMapIterator< QAction *, QList< QString > > actionMapIterator(actionMap); - - QMap<QString, QMenu *> topLevelMenus; - - while ( actionMapIterator.hasNext() ) { - actionMapIterator.next(); - QAction *actionToAdd = actionMapIterator.key(); - QList< QString > location = actionMapIterator.value(); - - QMenu *menuToPutActionInto = NULL; - - if ( location.count() ) { - QString topLevelMenuTitle = location.takeFirst(); - if (!topLevelMenus[topLevelMenuTitle]) { - topLevelMenus[topLevelMenuTitle] = menuBar->addMenu(topLevelMenuTitle); - } - - menuToPutActionInto = topLevelMenus[topLevelMenuTitle]; - } - - foreach (QString menuName, location) { - bool foundSubMenu = false; - foreach ( QAction *possibleSubMenu, menuToPutActionInto->actions() ) { - if (!foundSubMenu && - possibleSubMenu->menu() && possibleSubMenu->menu()->title() == menuName) { - foundSubMenu = true; - menuToPutActionInto = possibleSubMenu->menu(); - } - } - - if (!foundSubMenu) { - menuToPutActionInto = menuToPutActionInto->addMenu(menuName); - } - } - - menuToPutActionInto->addAction(actionToAdd); - } + resultLayout->addWidget(m_cnetEditorWidget, 0, 0, 1, 2); QTabWidget *treeViews = new QTabWidget; treeViews->addTab( m_cnetEditorWidget->pointTreeView(), tr("Point View") ); treeViews->addTab( m_cnetEditorWidget->serialTreeView(), tr("Serial View") ); treeViews->addTab( m_cnetEditorWidget->connectionTreeView(), tr("Connection View") ); - resultLayout->addWidget(treeViews, row, 0, 1, 1); + resultLayout->addWidget(treeViews, 1, 0, 1, 1); QTabWidget *filterViews = new QTabWidget; filterViews->addTab( m_cnetEditorWidget->pointFilterWidget(), tr("Filter Points and Measures") ); filterViews->addTab( m_cnetEditorWidget->serialFilterWidget(), tr("Filter Images and Points") ); filterViews->addTab( m_cnetEditorWidget->connectionFilterWidget(), tr("Filter Connections") ); - resultLayout->addWidget(filterViews, row, 1, 1, 1); - row++; + resultLayout->addWidget(filterViews, 1, 1, 1, 1); + createMenus(); + createToolBars(); + // Store the actions for easy enable/disable. + foreach (QAction *action, m_permToolBar->actions()) { + addAction(action); + } + // On default, actions are disabled until the cursor enters the view. + disableActions(); + } + /** + * Destructor + */ + CnetEditorView::~CnetEditorView() { + delete m_cnetEditorWidget; + delete m_permToolBar; + delete m_tablesMenu; - m_permToolBar = new QToolBar("Standard Tools", 0); - m_permToolBar->setObjectName("permToolBar"); - m_permToolBar->setIconSize(QSize(22, 22)); - //toolBarLayout->addWidget(m_permToolBar); + m_tablesMenu = 0; + m_permToolBar = 0; + } - m_activeToolBar = new QToolBar("Active Tool", 0); - m_activeToolBar->setObjectName("activeToolBar"); - m_activeToolBar->setIconSize(QSize(22, 22)); - //toolBarLayout->addWidget(m_activeToolBar); + /** + * Uses the actions created by CnetEditorWidget, creates the tables menu, + * and puts the actions into the tables menu. + */ + void CnetEditorView::createMenus() { + QMap< QAction *, QList< QString > > actionMap = m_cnetEditorWidget->menuActions(); + QMapIterator< QAction *, QList< QString > > actionMapIter(actionMap); - m_toolPad = new ToolPad("Tool Pad", 0); - m_toolPad->setObjectName("toolPad"); - //toolBarLayout->addWidget(m_toolPad); + m_tablesMenu = new ProjectItemViewMenu("&Tables"); + connect(m_tablesMenu, SIGNAL(menuClosed()), this, SLOT(disableActions())); + menuBar()->addMenu(m_tablesMenu); + while ( actionMapIter.hasNext() ) { + actionMapIter.next(); + QAction *actionToAdd = actionMapIter.key(); -// m_cnetEditorWidget->addToPermanent(m_permToolBar); -// m_cnetEditorWidget->addTo(m_activeToolBar); -// m_cnetEditorWidget->addTo(m_toolPad); + // Skip the "What's This?" action because it is in the main help menu of IPCE + if (actionToAdd->text() == "What's This?") { + continue; + } + m_tablesMenu->addAction(actionToAdd); + } + } - m_activeToolBarAction = new QWidgetAction(this); - m_activeToolBarAction->setDefaultWidget(m_activeToolBar); - setAcceptDrops(true); + /** + * Uses and adds the actions created by CnetEditorWidget to the view's toolbars + * Right now, all actions created in CnetEditorWidget are added to the toolpad. + * This was copied from CnetEditorWindow + */ + void CnetEditorView::createToolBars() { + m_permToolBar = addToolBar("Standard Tools"); + m_permToolBar->setObjectName("permToolBar"); + m_permToolBar->setIconSize(QSize(22, 22)); - QSizePolicy policy = sizePolicy(); - policy.setHorizontalPolicy(QSizePolicy::Expanding); - policy.setVerticalPolicy(QSizePolicy::Expanding); - setSizePolicy(policy); + QMap< QString, QList< QAction * > > actionMap; + actionMap = m_cnetEditorWidget->toolBarActions(); + QMapIterator< QString, QList< QAction * > > actionIter(actionMap); + while (actionIter.hasNext()) { + actionIter.next(); + QString objName = actionIter.key(); + QList< QAction * > actionList = actionIter.value(); + foreach (QAction *action, actionList) { + m_permToolBar->addAction(action); + } + } } /** - * Destructor + * Disables actions when cursor leaves the view. Overriden method + * If a menu is visible, i.e. clicked on, this causes a leave event. We want the + * actions to still be enabled when a menu is visible. + * + * @param event The leave event */ - CnetEditorView::~CnetEditorView() { - - delete m_cnetEditorWidget; - delete m_permToolBar; - delete m_activeToolBar; - delete m_toolPad; - - m_permToolBar = 0; - m_activeToolBar = 0; - m_toolPad = 0; + void CnetEditorView::leaveEvent(QEvent *event) { + if (!m_tablesMenu->isVisible()) { + disableActions(); + } } @@ -192,9 +180,9 @@ namespace Isis { /** - * @description Returns the Control displayed in the CnetEditorWidget - * - * @return (Control *) The Control displayed in the CnetEditorWidget + * @description Returns the Control displayed in the CnetEditorWidget + * + * @return (Control *) The Control displayed in the CnetEditorWidget */ Control *CnetEditorView::control() { return m_control; @@ -210,41 +198,6 @@ namespace Isis { return QSize(800, 600); } - - /** - * Returns a list of actions for the permanent tool bar. - * - * @return (QList<QAction *>) The actions - */ - QList<QAction *> CnetEditorView::permToolBarActions() { - return m_permToolBar->actions(); - } - - - /** - * Returns a list of actions for the active tool bar. - * - * @return (QList<QAction *>) The actions - */ - QList<QAction *> CnetEditorView::activeToolBarActions() { - QList<QAction *> actions; - actions.append(m_activeToolBarAction); - return actions; - } - - - /** - * Returns a list of actions for the tool pad. - * - * @return (QList<QAction *>) The actions - */ - QList<QAction *> CnetEditorView::toolPadActions() { - return m_toolPad->actions(); - } - - - - /** * This method pushes a new XmlHandler into the parser stack. * @@ -325,4 +278,3 @@ namespace Isis { return result; } } - diff --git a/isis/src/qisis/objs/CnetEditorView/CnetEditorView.h b/isis/src/qisis/objs/CnetEditorView/CnetEditorView.h index 21e98d307d8b70e01d33be604cbad736408612e6..fbcd13523ca200b3749cc981fa801f28b7211ed4 100644 --- a/isis/src/qisis/objs/CnetEditorView/CnetEditorView.h +++ b/isis/src/qisis/objs/CnetEditorView/CnetEditorView.h @@ -44,13 +44,30 @@ namespace Isis { class Project; class ToolPad; class XmlStackedHandlerReader; + class ProjectItemViewMenu; /** * Ipce view containing the CnetEditorWidget * * @author 2018-04-04 Tracie Sucharski - * - * @internal + * + * @internal + * @history 2018-06-01 Kaitlyn Lee - Because AbstractProjectItemView now inherits from QMainWindow, + * I added a dummy central widget and set its layout to the grid layout. + * We used to set the whole CnetEditorView widget's layout, now we only + * set the central widget's layout. + * @history 2018-06-05 Kaitlyn Lee - Added createMenus() and createToolBars(). The body of createMenus() + * was moved from the constructor. createToolBars() was copied and edited + * from CnetEditorWindow. Fixes #5416 + * @history 2018-06-13 Kaitlyn Lee - Since views now inherit from QMainWindow, each individual + * view has its own toolbar, so having getters that return toolbar + * actions to fill the toolbar of the IpceMainWindow are unnecessary. + * Removed methods that returned menu and toolbar actions. + * @history 2018-06-25 Kaitlyn Lee - When multiple views are open, there is a possibility of getting + * ambiguous shortcut errors. To counter this, we enable/disable actions. Overrode + * leaveEvent() to handle open menus causing a leave event. On default, a view's + * actions are disabled. To enable the actions, move the cursor over the view. + * When a user moves the cursor outside of the view, the actions are disabled. */ class CnetEditorView : public AbstractProjectItemView { @@ -58,14 +75,10 @@ class CnetEditorView : public AbstractProjectItemView { Q_OBJECT public: - CnetEditorView(Directory *directory, Control *control, FileName configFile, + CnetEditorView(Directory *directory, Control *control, FileName configFile, QWidget *parent = 0); ~CnetEditorView(); - virtual QList<QAction *> permToolBarActions(); - virtual QList<QAction *> activeToolBarActions(); - virtual QList<QAction *> toolPadActions(); - CnetEditorWidget *cnetEditorWidget(); Control *control(); @@ -74,8 +87,12 @@ class CnetEditorView : public AbstractProjectItemView { void load(XmlStackedHandlerReader *xmlReader); void save(QXmlStreamWriter &stream, Project *project, FileName newProjectRoot) const; + private: + void createToolBars(); + void createMenus(); + void leaveEvent(QEvent *event); + - private: /** * @author 2012-09-?? Steven Lambright * @@ -103,10 +120,8 @@ class CnetEditorView : public AbstractProjectItemView { QPointer<Control> m_control; QToolBar *m_permToolBar; //!< The permanent tool bar - QToolBar *m_activeToolBar; //!< The active tool bar - ToolPad *m_toolPad; //!< The tool pad + ProjectItemViewMenu *m_tablesMenu; //!< View menu for storing actions - QWidgetAction *m_activeToolBarAction; //!< Stores the active tool bar }; } diff --git a/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeFilter.cpp index 3393a4e4aef3c5a7b0ccdbac39fcdc4d777e1964..fc6e6099323f3e059bd54e2a88b7b7d7d4826328 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeFilter.cpp @@ -2,19 +2,24 @@ #include "APrioriLatitudeFilter.h" +#include <QPair> +#include <QString> + +#include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" #include "Latitude.h" namespace Isis { APrioriLatitudeFilter::APrioriLatitudeFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } - APrioriLatitudeFilter::APrioriLatitudeFilter( - const APrioriLatitudeFilter &other) : AbstractNumberFilter(other) { + APrioriLatitudeFilter::APrioriLatitudeFilter(const APrioriLatitudeFilter &other) + : AbstractNumberFilter(other) { } @@ -22,20 +27,18 @@ namespace Isis { } - bool APrioriLatitudeFilter::evaluate( - const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + bool APrioriLatitudeFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } bool APrioriLatitudeFilter::evaluate(const ControlPoint *point) const { return AbstractNumberFilter::evaluate( - point->GetAprioriSurfacePoint().GetLatitude().degrees()); + point->GetAprioriSurfacePoint().GetLatitude().degrees()); } - bool APrioriLatitudeFilter::evaluate( - const ControlMeasure *measure) const { + bool APrioriLatitudeFilter::evaluate(const ControlMeasure *measure) const { return true; } @@ -64,4 +67,3 @@ namespace Isis { descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeFilter.h b/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeFilter.h index 7d04b57d0c789fefd06c6d215a97b27b8d20f53b..6783d93d54854baf231e8395a7084e3944d317c8 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -23,19 +21,21 @@ namespace Isis { * * @author 2012-04-25 Jai Rideout * - * @internal + * @internal * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class APrioriLatitudeFilter : public AbstractNumberFilter { Q_OBJECT public: APrioriLatitudeFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); APrioriLatitudeFilter(const APrioriLatitudeFilter &other); virtual ~APrioriLatitudeFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -47,4 +47,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeSigmaFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeSigmaFilter.cpp index 764a53eafe18bcfd9f1b0865703bab69070e4e7d..c11b94ddf649c03c6323eb977bc3e7899e6405a3 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeSigmaFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeSigmaFilter.cpp @@ -2,19 +2,24 @@ #include "APrioriLatitudeSigmaFilter.h" +#include <QPair> +#include <QString> + +#include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" #include "Latitude.h" namespace Isis { APrioriLatitudeSigmaFilter::APrioriLatitudeSigmaFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } - APrioriLatitudeSigmaFilter::APrioriLatitudeSigmaFilter( - const APrioriLatitudeSigmaFilter &other) : AbstractNumberFilter(other) { + APrioriLatitudeSigmaFilter::APrioriLatitudeSigmaFilter(const APrioriLatitudeSigmaFilter &other) + : AbstractNumberFilter(other) { } @@ -23,19 +28,18 @@ namespace Isis { bool APrioriLatitudeSigmaFilter::evaluate( - const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } bool APrioriLatitudeSigmaFilter::evaluate(const ControlPoint *point) const { return AbstractNumberFilter::evaluate( - point->GetAprioriSurfacePoint().GetLatSigmaDistance().meters()); + point->GetAprioriSurfacePoint().GetLatSigmaDistance().meters()); } - bool APrioriLatitudeSigmaFilter::evaluate( - const ControlMeasure *measure) const { + bool APrioriLatitudeSigmaFilter::evaluate(const ControlMeasure *measure) const { return true; } @@ -61,7 +65,6 @@ namespace Isis { QString APrioriLatitudeSigmaFilter::getPointDescription() const { return "have <i>a priori</i> surface point latitude sigmas which are " + - descriptionSuffix(); + descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeSigmaFilter.h b/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeSigmaFilter.h index 75553bef8fee19cc7761da2b922a785a61bb0df1..3ce9f4923d8897d666dd87bdc13fda1a2897b7a7 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeSigmaFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/APrioriLatitudeSigmaFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class ControlCubeGraphNode; - class AbstractFilterSelector; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -23,19 +21,21 @@ namespace Isis { * * @author 2012-04-25 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class APrioriLatitudeSigmaFilter : public AbstractNumberFilter { Q_OBJECT public: APrioriLatitudeSigmaFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); APrioriLatitudeSigmaFilter(const APrioriLatitudeSigmaFilter &other); virtual ~APrioriLatitudeSigmaFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -47,4 +47,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeFilter.cpp index 02af6c252776f605ffab3fb5b4e93567409e3ea2..e72c25104aacc9f82d7f668f40e10ebf6c08ef1f 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeFilter.cpp @@ -2,19 +2,24 @@ #include "APrioriLongitudeFilter.h" +#include <QPair> +#include <QString> + +#include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" #include "Longitude.h" namespace Isis { APrioriLongitudeFilter::APrioriLongitudeFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } - APrioriLongitudeFilter::APrioriLongitudeFilter( - const APrioriLongitudeFilter &other) : AbstractNumberFilter(other) { + APrioriLongitudeFilter::APrioriLongitudeFilter(const APrioriLongitudeFilter &other) + : AbstractNumberFilter(other) { } @@ -23,19 +28,18 @@ namespace Isis { bool APrioriLongitudeFilter::evaluate( - const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } bool APrioriLongitudeFilter::evaluate(const ControlPoint *point) const { return AbstractNumberFilter::evaluate( - point->GetAprioriSurfacePoint().GetLongitude().degrees()); + point->GetAprioriSurfacePoint().GetLongitude().degrees()); } - bool APrioriLongitudeFilter::evaluate( - const ControlMeasure *measure) const { + bool APrioriLongitudeFilter::evaluate(const ControlMeasure *measure) const { return true; } @@ -64,4 +68,3 @@ namespace Isis { descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeFilter.h b/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeFilter.h index e7aadf1180468fd177ddefd9c175db3e403e2ea8..851dbf3a2accb0c81a15f60b22949038d27a560e 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -23,19 +21,21 @@ namespace Isis { * * @author 2012-04-25 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class APrioriLongitudeFilter : public AbstractNumberFilter { Q_OBJECT public: APrioriLongitudeFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); APrioriLongitudeFilter(const APrioriLongitudeFilter &other); virtual ~APrioriLongitudeFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -47,4 +47,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeSigmaFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeSigmaFilter.cpp index 65346d9ec4ef2c41ce4821a1dd99ca31f6385b1b..d692e0991650d82e3fa5e1748a7269397356f2de 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeSigmaFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeSigmaFilter.cpp @@ -2,19 +2,24 @@ #include "APrioriLongitudeSigmaFilter.h" +#include <QPair> +#include <QString> + +#include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" #include "Longitude.h" namespace Isis { APrioriLongitudeSigmaFilter::APrioriLongitudeSigmaFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } APrioriLongitudeSigmaFilter::APrioriLongitudeSigmaFilter( - const APrioriLongitudeSigmaFilter &other) : AbstractNumberFilter(other) { + const APrioriLongitudeSigmaFilter &other) : AbstractNumberFilter(other) { } @@ -23,20 +28,18 @@ namespace Isis { bool APrioriLongitudeSigmaFilter::evaluate( - const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } - bool APrioriLongitudeSigmaFilter::evaluate( - const ControlPoint *point) const { + bool APrioriLongitudeSigmaFilter::evaluate(const ControlPoint *point) const { return AbstractNumberFilter::evaluate( - point->GetAprioriSurfacePoint().GetLonSigmaDistance().meters()); + point->GetAprioriSurfacePoint().GetLonSigmaDistance().meters()); } - bool APrioriLongitudeSigmaFilter::evaluate( - const ControlMeasure *measure) const { + bool APrioriLongitudeSigmaFilter::evaluate(const ControlMeasure *measure) const { return true; } @@ -65,4 +68,3 @@ namespace Isis { descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeSigmaFilter.h b/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeSigmaFilter.h index d4dec40ebd52fc08492f6468b176a4a294b83c81..caf0a9004894c33baf5e608672d73a791b84fd37 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeSigmaFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/APrioriLongitudeSigmaFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class ControlCubeGraphNode; - class AbstractFilterSelector; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -23,19 +21,21 @@ namespace Isis { * * @author 2012-04-25 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class APrioriLongitudeSigmaFilter : public AbstractNumberFilter { Q_OBJECT public: APrioriLongitudeSigmaFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); APrioriLongitudeSigmaFilter(const APrioriLongitudeSigmaFilter &other); virtual ~APrioriLongitudeSigmaFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -47,4 +47,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusFilter.cpp index 9a0def576672a39c3c2689661f6a043f572ef4b2..c98beea0b0305728a5202758231db2d852610bf7 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusFilter.cpp @@ -2,19 +2,23 @@ #include "APrioriRadiusFilter.h" +#include <QPair> +#include <QString> + +#include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" -#include "Longitude.h" namespace Isis { APrioriRadiusFilter::APrioriRadiusFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } - APrioriRadiusFilter::APrioriRadiusFilter( - const APrioriRadiusFilter &other) : AbstractNumberFilter(other) { + APrioriRadiusFilter::APrioriRadiusFilter(const APrioriRadiusFilter &other) + : AbstractNumberFilter(other) { } @@ -22,20 +26,18 @@ namespace Isis { } - bool APrioriRadiusFilter::evaluate( - const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + bool APrioriRadiusFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } bool APrioriRadiusFilter::evaluate(const ControlPoint *point) const { return AbstractNumberFilter::evaluate( - point->GetAprioriSurfacePoint().GetLocalRadius().meters()); + point->GetAprioriSurfacePoint().GetLocalRadius().meters()); } - bool APrioriRadiusFilter::evaluate( - const ControlMeasure *measure) const { + bool APrioriRadiusFilter::evaluate(const ControlMeasure *measure) const { return true; } @@ -64,4 +66,3 @@ namespace Isis { descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusFilter.h b/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusFilter.h index affaf9da9ced0aa869c7ea8939dc87be97fac01f..9080812a0251a8c67566089bcc4e659e32c43471 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -23,19 +21,21 @@ namespace Isis { * * @author 2012-04-25 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class APrioriRadiusFilter : public AbstractNumberFilter { Q_OBJECT public: APrioriRadiusFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); APrioriRadiusFilter(const APrioriRadiusFilter &other); virtual ~APrioriRadiusFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -47,4 +47,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusSigmaFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusSigmaFilter.cpp index 7670f4e9779d256e011b1cd2fe6bac3fb7ffc507..802c953f3bc128705e7544772191f0d6c78735dc 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusSigmaFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusSigmaFilter.cpp @@ -2,19 +2,23 @@ #include "APrioriRadiusSigmaFilter.h" +#include <QPair> +#include <QString> + +#include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" -#include "Longitude.h" namespace Isis { APrioriRadiusSigmaFilter::APrioriRadiusSigmaFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } - APrioriRadiusSigmaFilter::APrioriRadiusSigmaFilter( - const APrioriRadiusSigmaFilter &other) : AbstractNumberFilter(other) { + APrioriRadiusSigmaFilter::APrioriRadiusSigmaFilter(const APrioriRadiusSigmaFilter &other) + : AbstractNumberFilter(other) { } @@ -23,19 +27,18 @@ namespace Isis { bool APrioriRadiusSigmaFilter::evaluate( - const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } bool APrioriRadiusSigmaFilter::evaluate(const ControlPoint *point) const { return AbstractNumberFilter::evaluate( - point->GetAprioriSurfacePoint().GetLocalRadiusSigma().meters()); + point->GetAprioriSurfacePoint().GetLocalRadiusSigma().meters()); } - bool APrioriRadiusSigmaFilter::evaluate( - const ControlMeasure *measure) const { + bool APrioriRadiusSigmaFilter::evaluate(const ControlMeasure *measure) const { return true; } @@ -64,4 +67,3 @@ namespace Isis { descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusSigmaFilter.h b/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusSigmaFilter.h index 0b177603b80a6d7052dec3a140704ab10e1295d3..bef494f5a82583926b37d5080b22ae764f5642ee 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusSigmaFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/APrioriRadiusSigmaFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -23,19 +21,21 @@ namespace Isis { * * @author 2012-04-25 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class APrioriRadiusSigmaFilter : public AbstractNumberFilter { Q_OBJECT public: APrioriRadiusSigmaFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); APrioriRadiusSigmaFilter(const APrioriRadiusSigmaFilter &other); virtual ~APrioriRadiusSigmaFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -47,4 +47,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/AbstractFilter.cpp index 5e8973a01b04bccc6e4dd7d108539a2dc7d2a6bf..79d3f44aecbc2b76e1de431bc1f3413117c504dd 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractFilter.cpp @@ -15,14 +15,15 @@ #include <QMargins> #include <QMenu> #include <QMenuBar> +#include <QPair> #include <QRadioButton> #include <QSpinBox> #include <QString> #include <QVBoxLayout> #include <QWriteLocker> -#include "ControlCubeGraphNode.h" #include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" #include "AbstractFilterSelector.h" @@ -30,7 +31,7 @@ namespace Isis { AbstractFilter::AbstractFilter(FilterEffectivenessFlag effectiveness, - int minimumForSuccess) { + int minimumForSuccess) { nullify(); m_minForSuccess = minimumForSuccess; @@ -284,26 +285,26 @@ namespace Isis { bool AbstractFilter::evaluateImageFromPointFilter( - const ControlCubeGraphNode *node) const { - ASSERT(node); - + const QPair<QString, ControlNet *> *imageAndNet) const { bool evaluation = true; - if (canFilterImages()) - evaluation = evaluateFromCount(node->getMeasures(), true); + if (canFilterImages()) { + evaluation = evaluateFromCount(imageAndNet->second->GetMeasuresInCube(imageAndNet->first), + true); + } return evaluation; } bool AbstractFilter::evaluateImageFromMeasureFilter( - const ControlCubeGraphNode *node) const { - ASSERT(node); - + const QPair<QString, ControlNet *> *imageAndNet) const { bool evaluation = true; - if (canFilterImages()) - evaluation = evaluateFromCount(node->getMeasures(), false); + if (canFilterImages()) { + evaluation = evaluateFromCount(imageAndNet->second->GetMeasuresInCube(imageAndNet->first), + false); + } return evaluation; } diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractFilter.h b/isis/src/qisis/objs/CnetEditorWidget/AbstractFilter.h index d8c8d84cc84af89c46b62d039f8a094e4163b149..bb0ffb8d2e11d9b806d04fb87728debf9f1668d9 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractFilter.h @@ -3,10 +3,11 @@ #include <QWidget> - class QBoxLayout; class QButtonGroup; class QCheckBox; +template< typename U, typename V > class QPair; +class QString; template< typename T > class QFlags; @@ -14,7 +15,7 @@ namespace Isis { class AbstractFilterSelector; class ControlPoint; class ControlMeasure; - class ControlCubeGraphNode; + class ControlNet; /** * @brief Base class for control net filters @@ -29,6 +30,8 @@ namespace Isis { * @internal * @history 2012-09-28 Kimberly Oyama - Changed member variables to be prefixed with "m_". * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class AbstractFilter : public QWidget { Q_OBJECT @@ -51,7 +54,7 @@ namespace Isis { virtual bool canFilterPoints() const; virtual bool canFilterMeasures() const; - virtual bool evaluate(const ControlCubeGraphNode *) const = 0; + virtual bool evaluate(const QPair<QString, ControlNet *> *) const = 0; virtual bool evaluate(const ControlPoint *) const = 0; virtual bool evaluate(const ControlMeasure *) const = 0; @@ -75,8 +78,8 @@ namespace Isis { QBoxLayout *getMainLayout() const; QBoxLayout *getInclusiveExclusiveLayout() const; - bool evaluateImageFromPointFilter(const ControlCubeGraphNode *) const; - bool evaluateImageFromMeasureFilter(const ControlCubeGraphNode *) const; + bool evaluateImageFromPointFilter(const QPair<QString, ControlNet *> *) const; + bool evaluateImageFromMeasureFilter(const QPair<QString, ControlNet *> *) const; bool evaluatePointFromMeasureFilter(const ControlPoint *) const; virtual bool evaluate(const ControlPoint *, diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractFilterSelector.cpp b/isis/src/qisis/objs/CnetEditorWidget/AbstractFilterSelector.cpp index 31b0ed6e67c110cd337af59e65350705073fc452..c0b0cf85ef18111fd26e775ad39946dd24eff3e8 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractFilterSelector.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractFilterSelector.cpp @@ -36,27 +36,26 @@ namespace Isis { } - bool AbstractFilterSelector::hasFilter( - bool (AbstractFilter::*meth)() const) const { + bool AbstractFilterSelector::hasFilter(bool (AbstractFilter::*meth)() const) const { return m_filter && (m_filter->*meth)(); } - QString AbstractFilterSelector::getDescription( - QString(AbstractFilter::*meth)() const) const { + QString AbstractFilterSelector::getDescription(QString(AbstractFilter::*meth)() const) const { QString description; - if (m_filter) + if (m_filter) { description = (m_filter->*meth)(); + } return description; } - AbstractFilterSelector &AbstractFilterSelector::operator=( - const AbstractFilterSelector &other) { + AbstractFilterSelector &AbstractFilterSelector::operator=(const AbstractFilterSelector &other) { getSelector()->setCurrentIndex(other.getSelector()->currentIndex()); - if (m_filter && other.m_filter) + if (m_filter && other.m_filter) { setFilter(other.m_filter->clone()); + } return *this; } @@ -79,7 +78,7 @@ namespace Isis { m_selector->addItem("---- select ----"); m_selector->insertSeparator(m_selector->count()); connect(m_selector, SIGNAL(currentIndexChanged(int)), - this, SLOT(changeFilter(int))); + this, SLOT(changeFilter(int))); m_mainLayout = new QHBoxLayout; m_mainLayout->setContentsMargins(0, 0, 0, 0); @@ -117,15 +116,13 @@ namespace Isis { m_filter = someFilter; connect(getFilter(), SIGNAL(filterChanged()), - this, SIGNAL(filterChanged())); + this, SIGNAL(filterChanged())); getMainLayout()->insertWidget(2, getFilter()); } void AbstractFilterSelector::deleteFilter() { if (m_filter) { - // QWidget * widget = m_mainLayout->takeAt(2)->widget(); - // ASSERT(widget && widget == m_filter); delete m_filter; m_filter = NULL; } diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractFilterSelector.h b/isis/src/qisis/objs/CnetEditorWidget/AbstractFilterSelector.h index afc00ad683224631594934da1e885135f9d198bf..9f7d468cd3dfbe10a38bba03b0e99572f71e0033 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractFilterSelector.h +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractFilterSelector.h @@ -15,8 +15,7 @@ class QPushButton; class QReadWriteLock; namespace Isis { - class AbstractFilter; - class ControlCubeGraphNode; + class ControlNet; class ControlMeasure; class ControlPoint; @@ -33,6 +32,8 @@ namespace Isis { * @history 2012-09-28 Kimberly Oyama - Changed member variables to be prefixed with "m_". * @history 2015-11-16 Ian Humphrey - Removed embedded close button icon. References #1041. * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class AbstractFilterSelector : public QWidget { Q_OBJECT diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractImageItem.cpp b/isis/src/qisis/objs/CnetEditorWidget/AbstractImageItem.cpp index 2430bcd97941121aea8d44d05acd6a290dc345c2..2e12f4b25b4c0eb7ab626e684c970ac6964d6e0d 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractImageItem.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractImageItem.cpp @@ -4,35 +4,35 @@ #include <iostream> +#include <QPair> #include <QString> #include <QVariant> -#include "ControlCubeGraphNode.h" #include "ControlNet.h" namespace Isis { - AbstractImageItem::AbstractImageItem(ControlCubeGraphNode *cubeGraphNode, - int avgCharWidth, AbstractTreeItem *parent) - : AbstractTreeItem(parent) { - ASSERT(cubeGraphNode); - m_ccgn = cubeGraphNode; + AbstractImageItem::AbstractImageItem(QString imageSerial, ControlNet *net, + int avgCharWidth, AbstractTreeItem *parent) + : AbstractTreeItem(parent) { + m_imageAndNet = new QPair<QString, ControlNet *>(imageSerial, net); calcDataWidth(avgCharWidth); - - connect(m_ccgn, SIGNAL(destroyed(QObject *)), this, SLOT(sourceDeleted())); } AbstractImageItem::~AbstractImageItem() { - m_ccgn = NULL; + if (m_imageAndNet) { + delete m_imageAndNet; + } + m_imageAndNet = NULL; } QVariant AbstractImageItem::getData() const { - if (m_ccgn) - return QVariant((QString)m_ccgn->getSerialNumber()); - else - return QVariant(); + if (m_imageAndNet) { + return QVariant(m_imageAndNet->first); + } + return QVariant(); } @@ -51,28 +51,31 @@ namespace Isis { } - void AbstractImageItem::deleteSource() { - // Shouldn't be deleting ControlCubeGraphNode's! - ASSERT(0); - } + void AbstractImageItem::deleteSource() { } AbstractTreeItem::InternalPointerType AbstractImageItem::getPointerType() const { - return AbstractTreeItem::CubeGraphNode; + return AbstractTreeItem::ImageAndNet; } void *AbstractImageItem::getPointer() const { - return m_ccgn; + return m_imageAndNet; } - bool AbstractImageItem::hasNode(ControlCubeGraphNode *node) const { - return m_ccgn == node || AbstractTreeItem::hasNode(node); + bool AbstractImageItem::hasImage(QString imageSerial) const { + if(!m_imageAndNet) { + return false; + } + return (QString::compare(m_imageAndNet->first, imageSerial) == 0) || + AbstractTreeItem::hasImage(imageSerial); } - void AbstractImageItem::sourceDeleted() { - m_ccgn = NULL; - } + /** + * This method is required to be implemented by the parent AbstractTreeItem class, + * but for this it's a NOP. + */ + void AbstractImageItem::sourceDeleted() { } } diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractImageItem.h b/isis/src/qisis/objs/CnetEditorWidget/AbstractImageItem.h index 8c17319ec6ac0e167c85f88b3dfac76c3c1c215f..d14fe1ecd54ea88c0ddcfcd40451f8189171195e 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractImageItem.h +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractImageItem.h @@ -4,13 +4,11 @@ #include "AbstractTreeItem.h" - class QString; class QVariant; - namespace Isis { - class ControlCubeGraphNode; + class ControlNet; /** * @brief Base class for an image item in the tree @@ -23,11 +21,13 @@ namespace Isis { * @internal * @history 2012-09-28 Kimberly Oyama - Changed member variables to be prefixed with "m_". * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class AbstractImageItem : public virtual AbstractTreeItem { public: - AbstractImageItem(ControlCubeGraphNode *cubeGraphNode, - int avgCharWidth, AbstractTreeItem *parent = 0); + AbstractImageItem(QString imageSerial, ControlNet *net, + int avgCharWidth, AbstractTreeItem *parent = 0); virtual ~AbstractImageItem(); QVariant getData() const; @@ -37,7 +37,7 @@ namespace Isis { void deleteSource(); InternalPointerType getPointerType() const; void *getPointer() const; - bool hasNode(ControlCubeGraphNode *) const; + bool hasImage(QString imageSerial) const; protected: @@ -49,7 +49,7 @@ namespace Isis { private: - ControlCubeGraphNode *m_ccgn; + QPair<QString, ControlNet *> *m_imageAndNet; }; } diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractMultipleChoiceFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/AbstractMultipleChoiceFilter.cpp index 46da59e2dff6f35280b13154cca05bb83c68c2b0..2c14883dd533335f7ac161694b2889f3e168c666 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractMultipleChoiceFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractMultipleChoiceFilter.cpp @@ -13,15 +13,14 @@ namespace Isis { AbstractMultipleChoiceFilter::AbstractMultipleChoiceFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { nullify(); m_curChoice = new QString; } AbstractMultipleChoiceFilter::AbstractMultipleChoiceFilter( - AbstractMultipleChoiceFilter const &other) - : AbstractFilter(other) { + AbstractMultipleChoiceFilter const &other) : AbstractFilter(other) { nullify(); m_curChoice = new QString; diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractMultipleChoiceFilter.h b/isis/src/qisis/objs/CnetEditorWidget/AbstractMultipleChoiceFilter.h index 674ee79a8aeaaa4b5ca5c2fbb8226ade9bd4c700..c5103cafcd19dca0ddede3d12431c6f34e271b7e 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractMultipleChoiceFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractMultipleChoiceFilter.h @@ -23,13 +23,15 @@ namespace Isis { * @internal * @history 2012-09-28 Kimberly Oyama - Changed member variables to be prefixed with "m_". * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class AbstractMultipleChoiceFilter : public AbstractFilter { Q_OBJECT public: AbstractMultipleChoiceFilter(AbstractFilter::FilterEffectivenessFlag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); AbstractMultipleChoiceFilter(const AbstractMultipleChoiceFilter &other); virtual ~AbstractMultipleChoiceFilter(); diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractNumberFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/AbstractNumberFilter.cpp index e177be1bb4bb75ee101e1d17d4eec6e243f65292..c542028d2fc33b594862f901998a5b166a6396bb 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractNumberFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractNumberFilter.cpp @@ -12,22 +12,21 @@ #include <QMargins> #include <QRadioButton> -#include "ControlCubeGraphNode.h" #include "ControlMeasure.h" #include "ControlPoint.h" namespace Isis { AbstractNumberFilter::AbstractNumberFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { nullify(); createWidget(); } AbstractNumberFilter::AbstractNumberFilter(const AbstractNumberFilter &other) - : AbstractFilter(other) { + : AbstractFilter(other) { nullify(); createWidget(); @@ -141,4 +140,3 @@ namespace Isis { *m_lineEditText = newText; } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractNumberFilter.h b/isis/src/qisis/objs/CnetEditorWidget/AbstractNumberFilter.h index d8d9a0e2cc0737e22be45942aa123bf4172e71d7..0b86eba5ed33753c225355c9292d7a480c30ceab 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractNumberFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractNumberFilter.h @@ -25,13 +25,15 @@ namespace Isis { * @internal * @history 2012-09-28 Kimberly Oyama - Changed member variables to be prefixed with "m_". * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class AbstractNumberFilter : public AbstractFilter { Q_OBJECT public: AbstractNumberFilter(AbstractFilter::FilterEffectivenessFlag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); AbstractNumberFilter(const AbstractNumberFilter &other); virtual ~AbstractNumberFilter(); diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractStringFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/AbstractStringFilter.cpp index 6c4cfc33806ffd0fa02c60603e80050a5d7d6874..bd11a847bd15b3b03d3d9ed73cd1044a152790ed 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractStringFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractStringFilter.cpp @@ -7,21 +7,20 @@ #include <QHBoxLayout> #include <QLineEdit> -#include "ControlCubeGraphNode.h" #include "ControlMeasure.h" #include "ControlPoint.h" namespace Isis { AbstractStringFilter::AbstractStringFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { nullify(); createWidget(); } AbstractStringFilter::AbstractStringFilter( - const AbstractStringFilter &other) : AbstractFilter(other) { + const AbstractStringFilter &other) : AbstractFilter(other) { nullify(); createWidget(); diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractStringFilter.h b/isis/src/qisis/objs/CnetEditorWidget/AbstractStringFilter.h index bb410d1c3655d446950b0675acc65f19adb844f4..e7f2f12c26b69c38256a7cba3c89a91429403dd5 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractStringFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractStringFilter.h @@ -1,11 +1,8 @@ #ifndef AbstractStringFilter_H #define AbstractStringFilter_H - -// parent #include "AbstractFilter.h" - class QLineEdit; class QString; @@ -25,13 +22,15 @@ namespace Isis { * @internal * @history 2012-09-28 Kimberly Oyama - Changed member variables to be prefixed with "m_". * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class AbstractStringFilter : public AbstractFilter { Q_OBJECT public: AbstractStringFilter(AbstractFilter::FilterEffectivenessFlag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); AbstractStringFilter(const AbstractStringFilter &other); virtual ~AbstractStringFilter(); diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeItem.cpp b/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeItem.cpp index da1467357bd0762889104e0e3ced6e5c49d05373..02b48829c47e4ac203c492a27de8aa072115c844 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeItem.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeItem.cpp @@ -95,11 +95,12 @@ namespace Isis { } - bool AbstractTreeItem::hasNode(ControlCubeGraphNode *cube) const { + bool AbstractTreeItem::hasImage(QString imageSerial) const { bool found = false; - for (int i = 0; !found && i < childCount(); i++) - found = childAt(i)->hasNode(cube); + for (int i = 0; !found && i < childCount(); i++) { + found = childAt(i)->hasImage(imageSerial); + } return found; } @@ -222,4 +223,3 @@ namespace Isis { return d; } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeItem.h b/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeItem.h index 9b80a8d4666cb4f6cdc226abf5591148d57fbc0f..0bf13463a5a0ea24dbeaf6145fd143bef47f1bc9 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeItem.h +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeItem.h @@ -10,7 +10,6 @@ class QVariant; namespace Isis { - class ControlCubeGraphNode; class ControlPoint; class ControlMeasure; @@ -26,6 +25,8 @@ namespace Isis { * @internal * @history 2012-09-28 Kimberly Oyama - Changed member variables to be prefixed with "m_". * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode usages to + * image serial number. References #5434. */ class AbstractTreeItem : public QObject { @@ -36,7 +37,7 @@ namespace Isis { None, Point, Measure, - CubeGraphNode, + ImageAndNet, }; @@ -78,7 +79,7 @@ namespace Isis { virtual QString getFormattedData(QString columnTitle) const; virtual bool hasMeasure(ControlMeasure *) const; - virtual bool hasNode(ControlCubeGraphNode *) const; + virtual bool hasImage(QString imageSerial) const; virtual bool hasPoint(ControlPoint *) const; virtual AbstractTreeItem *getNextVisiblePeer() const; diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeModel.cpp b/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeModel.cpp index ea404f398ecefb1f9f46a0dd9700a866beb683f9..a199891bf347d88e44c87cbbb567c7de4bfbf918 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeModel.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeModel.cpp @@ -497,12 +497,9 @@ namespace Isis { AbstractTreeItem::InternalPointerType pointerType = item->getPointerType(); - if ((pointerType == AbstractTreeItem::Point && - flags.testFlag(PointItems)) || - (pointerType == AbstractTreeItem::Measure && - flags.testFlag(MeasureItems)) || - (pointerType == AbstractTreeItem::CubeGraphNode && - flags.testFlag(SerialItems))) { + if ((pointerType == AbstractTreeItem::Point && flags.testFlag(PointItems)) || + (pointerType == AbstractTreeItem::Measure && flags.testFlag(MeasureItems)) || + (pointerType == AbstractTreeItem::ImageAndNet && flags.testFlag(ImageItems))) { return true; } else { @@ -634,9 +631,9 @@ namespace Isis { (ControlMeasure *) item->getPointer())) ? true : false); break; - case AbstractTreeItem::CubeGraphNode: + case AbstractTreeItem::ImageAndNet: item->setVisible((!m_filter || m_filter->evaluate( - (ControlCubeGraphNode *) item->getPointer())) ? true : false); + (QPair<QString, ControlNet *> *) item->getPointer())) ? true : false); break; case AbstractTreeItem::None: @@ -702,4 +699,3 @@ namespace Isis { } } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeModel.h b/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeModel.h index d10c08266af2da9d939c7d8aa46953b8184fe47f..ffaed462909cc4b76822405a5b8774f598fbc07d 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeModel.h +++ b/isis/src/qisis/objs/CnetEditorWidget/AbstractTreeModel.h @@ -43,8 +43,8 @@ namespace Isis { enum InterestingItems { PointItems = 1, MeasureItems = 2, - SerialItems = 4, - AllItems = PointItems | MeasureItems | SerialItems + ImageItems = 4, + AllItems = PointItems | MeasureItems | ImageItems }; Q_DECLARE_FLAGS(InterestingItemsFlag, InterestingItems) diff --git a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeFilter.cpp index 3f044d5fee6fa3afacc1a9c74f8cf41f56f37329..79b2bcaec03aa5eb7990a2b4d036f696c307a8de 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeFilter.cpp @@ -2,19 +2,23 @@ #include "AdjustedLatitudeFilter.h" +#include <QPair> +#include <QString> + #include "ControlPoint.h" +#include "ControlNet.h" #include "Latitude.h" namespace Isis { AdjustedLatitudeFilter::AdjustedLatitudeFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } AdjustedLatitudeFilter::AdjustedLatitudeFilter( - const AdjustedLatitudeFilter &other) : AbstractNumberFilter(other) { + const AdjustedLatitudeFilter &other) : AbstractNumberFilter(other) { } @@ -22,20 +26,18 @@ namespace Isis { } - bool AdjustedLatitudeFilter::evaluate( - const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + bool AdjustedLatitudeFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } bool AdjustedLatitudeFilter::evaluate(const ControlPoint *point) const { return AbstractNumberFilter::evaluate( - point->GetAdjustedSurfacePoint().GetLatitude().degrees()); + point->GetAdjustedSurfacePoint().GetLatitude().degrees()); } - bool AdjustedLatitudeFilter::evaluate( - const ControlMeasure *measure) const { + bool AdjustedLatitudeFilter::evaluate(const ControlMeasure *measure) const { return true; } @@ -64,4 +66,3 @@ namespace Isis { descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeFilter.h b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeFilter.h index 90cf8e6e9ab1877de558e6380a079baab5508871..c67522d7c7d61eb359b79a1c846bda2b0c4ad50f 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeFilter.h @@ -3,13 +3,11 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; class ControlPoint; @@ -23,19 +21,21 @@ namespace Isis { * * @author 2012-04-23 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class AdjustedLatitudeFilter : public AbstractNumberFilter { Q_OBJECT public: AdjustedLatitudeFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); AdjustedLatitudeFilter(const AdjustedLatitudeFilter &other); virtual ~AdjustedLatitudeFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -47,4 +47,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeSigmaFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeSigmaFilter.cpp index 27e69145794f60e0510590510424e147dbde33bc..5d43155d3e2a7db6c42e903182bf404531257ad6 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeSigmaFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeSigmaFilter.cpp @@ -2,19 +2,24 @@ #include "AdjustedLatitudeSigmaFilter.h" +#include <QPair> +#include <QString> + #include "ControlPoint.h" +#include "ControlMeasure.h" +#include "ControlNet.h" #include "Latitude.h" namespace Isis { AdjustedLatitudeSigmaFilter::AdjustedLatitudeSigmaFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } AdjustedLatitudeSigmaFilter::AdjustedLatitudeSigmaFilter( - const AdjustedLatitudeSigmaFilter &other) : AbstractNumberFilter(other) { + const AdjustedLatitudeSigmaFilter &other) : AbstractNumberFilter(other) { } @@ -23,20 +28,18 @@ namespace Isis { bool AdjustedLatitudeSigmaFilter::evaluate( - const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } - bool AdjustedLatitudeSigmaFilter::evaluate( - const ControlPoint *point) const { + bool AdjustedLatitudeSigmaFilter::evaluate(const ControlPoint *point) const { return AbstractNumberFilter::evaluate( - point->GetAdjustedSurfacePoint().GetLatSigmaDistance().meters()); + point->GetAdjustedSurfacePoint().GetLatSigmaDistance().meters()); } - bool AdjustedLatitudeSigmaFilter::evaluate( - const ControlMeasure *measure) const { + bool AdjustedLatitudeSigmaFilter::evaluate(const ControlMeasure *measure) const { return true; } @@ -65,4 +68,3 @@ namespace Isis { descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeSigmaFilter.h b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeSigmaFilter.h index 7defcc6e9be6257efdd6f3fa00b719add4cc7924..2e4848871ac7f2c34e56d99fbbed38415740685c 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeSigmaFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLatitudeSigmaFilter.h @@ -3,14 +3,13 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -23,19 +22,21 @@ namespace Isis { * * @author 2012-04-25 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class AdjustedLatitudeSigmaFilter : public AbstractNumberFilter { Q_OBJECT public: AdjustedLatitudeSigmaFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); AdjustedLatitudeSigmaFilter(const AdjustedLatitudeSigmaFilter &other); virtual ~AdjustedLatitudeSigmaFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -47,4 +48,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeFilter.cpp index 386bc51699544121c21928bc4483236804887e6a..0f330ac0b2cde80781064dab0cff79d9bc8b4295 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeFilter.cpp @@ -2,19 +2,25 @@ #include "AdjustedLongitudeFilter.h" +#include <QPair> +#include <QString> + #include "ControlPoint.h" +#include "ControlMeasure.h" +#include "ControlNet.h" #include "Longitude.h" namespace Isis { AdjustedLongitudeFilter::AdjustedLongitudeFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) + : AbstractNumberFilter(flag, minimumForSuccess) { } - AdjustedLongitudeFilter::AdjustedLongitudeFilter( - const AdjustedLongitudeFilter &other) : AbstractNumberFilter(other) { + AdjustedLongitudeFilter::AdjustedLongitudeFilter(const AdjustedLongitudeFilter &other) + : AbstractNumberFilter(other) { } @@ -22,20 +28,18 @@ namespace Isis { } - bool AdjustedLongitudeFilter::evaluate( - const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + bool AdjustedLongitudeFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } bool AdjustedLongitudeFilter::evaluate(const ControlPoint *point) const { return AbstractNumberFilter::evaluate( - point->GetAdjustedSurfacePoint().GetLongitude().degrees()); + point->GetAdjustedSurfacePoint().GetLongitude().degrees()); } - bool AdjustedLongitudeFilter::evaluate( - const ControlMeasure *measure) const { + bool AdjustedLongitudeFilter::evaluate(const ControlMeasure *measure) const { return true; } @@ -64,4 +68,3 @@ namespace Isis { descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeFilter.h b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeFilter.h index aa72b985335c231b6f46abe02be0fb93d521bb13..7df0d6a881279150d434cd05c2a0f6c30cdaed80 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeFilter.h @@ -3,15 +3,14 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; class ControlPoint; + class ControlNet; /** * @brief Allows filtering by adjusted surface point longitude @@ -23,19 +22,21 @@ namespace Isis { * * @author 2012-04-25 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class AdjustedLongitudeFilter : public AbstractNumberFilter { Q_OBJECT public: AdjustedLongitudeFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); AdjustedLongitudeFilter(const AdjustedLongitudeFilter &other); virtual ~AdjustedLongitudeFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -47,4 +48,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeSigmaFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeSigmaFilter.cpp index 7a0141ec6192600daa30e8f4fc8d35299f9309f5..b8657441a500cc825aecc08ac8874f12772fc954 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeSigmaFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeSigmaFilter.cpp @@ -2,20 +2,25 @@ #include "AdjustedLongitudeSigmaFilter.h" +#include <QPair> +#include <QString> + +#include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" #include "Longitude.h" namespace Isis { AdjustedLongitudeSigmaFilter::AdjustedLongitudeSigmaFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } AdjustedLongitudeSigmaFilter::AdjustedLongitudeSigmaFilter( - const AdjustedLongitudeSigmaFilter &other) : - AbstractNumberFilter(other) { + const AdjustedLongitudeSigmaFilter &other) : + AbstractNumberFilter(other) { } @@ -24,20 +29,18 @@ namespace Isis { bool AdjustedLongitudeSigmaFilter::evaluate( - const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } - bool AdjustedLongitudeSigmaFilter::evaluate( - const ControlPoint *point) const { + bool AdjustedLongitudeSigmaFilter::evaluate(const ControlPoint *point) const { return AbstractNumberFilter::evaluate( - point->GetAdjustedSurfacePoint().GetLonSigmaDistance().meters()); + point->GetAdjustedSurfacePoint().GetLonSigmaDistance().meters()); } - bool AdjustedLongitudeSigmaFilter::evaluate( - const ControlMeasure *measure) const { + bool AdjustedLongitudeSigmaFilter::evaluate(const ControlMeasure *measure) const { return true; } @@ -66,4 +69,3 @@ namespace Isis { descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeSigmaFilter.h b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeSigmaFilter.h index ace520c7e593fa51e203b52b82955bb9d0746222..e302af1b5768b5399dde167aa7195d7527625d5a 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeSigmaFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/AdjustedLongitudeSigmaFilter.h @@ -3,14 +3,13 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -23,19 +22,21 @@ namespace Isis { * * @author 2012-04-25 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class AdjustedLongitudeSigmaFilter : public AbstractNumberFilter { Q_OBJECT public: AdjustedLongitudeSigmaFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); AdjustedLongitudeSigmaFilter(const AdjustedLongitudeSigmaFilter &other); virtual ~AdjustedLongitudeSigmaFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -47,4 +48,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusFilter.cpp index 6df8a5f60768b627fcf840454a15f9ebe64573c4..b6c9d9c5bc2364bb4dd6bfe46480a76cfb9e7b7b 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusFilter.cpp @@ -2,19 +2,23 @@ #include "AdjustedRadiusFilter.h" +#include <QPair> +#include <QString> + +#include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" -#include "Longitude.h" namespace Isis { AdjustedRadiusFilter::AdjustedRadiusFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } - AdjustedRadiusFilter::AdjustedRadiusFilter( - const AdjustedRadiusFilter &other) : AbstractNumberFilter(other) { + AdjustedRadiusFilter::AdjustedRadiusFilter(const AdjustedRadiusFilter &other) + : AbstractNumberFilter(other) { } @@ -22,20 +26,18 @@ namespace Isis { } - bool AdjustedRadiusFilter::evaluate( - const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + bool AdjustedRadiusFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } bool AdjustedRadiusFilter::evaluate(const ControlPoint *point) const { return AbstractNumberFilter::evaluate( - point->GetAdjustedSurfacePoint().GetLocalRadius().meters()); + point->GetAdjustedSurfacePoint().GetLocalRadius().meters()); } - bool AdjustedRadiusFilter::evaluate( - const ControlMeasure *measure) const { + bool AdjustedRadiusFilter::evaluate(const ControlMeasure *measure) const { return true; } @@ -64,4 +66,3 @@ namespace Isis { descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusFilter.h b/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusFilter.h index 46956b58d23dba2f0f6556ac930af72a5ab155a1..46792f158cb5be0057b8aa63886c716aadc7aa5f 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusFilter.h @@ -3,14 +3,13 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -23,19 +22,21 @@ namespace Isis { * * @author 2012-04-25 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class AdjustedRadiusFilter : public AbstractNumberFilter { Q_OBJECT public: AdjustedRadiusFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); AdjustedRadiusFilter(const AdjustedRadiusFilter &other); virtual ~AdjustedRadiusFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -47,4 +48,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusSigmaFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusSigmaFilter.cpp index 6fbed39cab42afca74f9fe420210d2ffcf0d7d39..034991a40445083f6e3b86052b594b5f4b7ae0f0 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusSigmaFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusSigmaFilter.cpp @@ -2,19 +2,23 @@ #include "AdjustedRadiusSigmaFilter.h" +#include <QPair> +#include <QString> + +#include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" namespace Isis { AdjustedRadiusSigmaFilter::AdjustedRadiusSigmaFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } - AdjustedRadiusSigmaFilter::AdjustedRadiusSigmaFilter( - const AdjustedRadiusSigmaFilter &other) : - AbstractNumberFilter(other) { + AdjustedRadiusSigmaFilter::AdjustedRadiusSigmaFilter(const AdjustedRadiusSigmaFilter &other) + : AbstractNumberFilter(other) { } @@ -23,20 +27,18 @@ namespace Isis { bool AdjustedRadiusSigmaFilter::evaluate( - const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } - bool AdjustedRadiusSigmaFilter::evaluate( - const ControlPoint *point) const { + bool AdjustedRadiusSigmaFilter::evaluate(const ControlPoint *point) const { return AbstractNumberFilter::evaluate( - point->GetAdjustedSurfacePoint().GetLocalRadiusSigma().meters()); + point->GetAdjustedSurfacePoint().GetLocalRadiusSigma().meters()); } - bool AdjustedRadiusSigmaFilter::evaluate( - const ControlMeasure *measure) const { + bool AdjustedRadiusSigmaFilter::evaluate(const ControlMeasure *measure) const { return true; } @@ -65,4 +67,3 @@ namespace Isis { descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusSigmaFilter.h b/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusSigmaFilter.h index 840f8d7cf765b130b616dd18a30d8f0ca498e8b1..d67e9cca3fb91af5e37c5461028c9d05646f9cd8 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusSigmaFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/AdjustedRadiusSigmaFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -23,19 +21,21 @@ namespace Isis { * * @author 2012-04-25 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class AdjustedRadiusSigmaFilter : public AbstractNumberFilter { Q_OBJECT public: AdjustedRadiusSigmaFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); AdjustedRadiusSigmaFilter(const AdjustedRadiusSigmaFilter &other); virtual ~AdjustedRadiusSigmaFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -47,4 +47,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/ChooserNameFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/ChooserNameFilter.cpp index 89d51ebffcbdaef3e8292044d2b2ac65154b74bd..bd1b2b56e2c7c113b2b08ebd48400aeda11ebed5 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ChooserNameFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/ChooserNameFilter.cpp @@ -2,23 +2,24 @@ #include "ChooserNameFilter.h" +#include <QPair> #include <QString> -#include "ControlCubeGraphNode.h" #include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" #include "IString.h" namespace Isis { ChooserNameFilter::ChooserNameFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractStringFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractStringFilter(flag, minimumForSuccess) { } ChooserNameFilter::ChooserNameFilter(const ChooserNameFilter &other) - : AbstractStringFilter(other) { + : AbstractStringFilter(other) { } @@ -26,8 +27,8 @@ namespace Isis { } - bool ChooserNameFilter::evaluate(const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + bool ChooserNameFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } diff --git a/isis/src/qisis/objs/CnetEditorWidget/ChooserNameFilter.h b/isis/src/qisis/objs/CnetEditorWidget/ChooserNameFilter.h index 9980de0f8d70cbf21fa7af3ec2fabf74d2f61e3b..7fc1b2a981e064cd114c49999a615fb130ef6cf2 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ChooserNameFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/ChooserNameFilter.h @@ -3,14 +3,13 @@ #include "AbstractStringFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlPoint; class ControlMeasure; + class ControlNet; + class ControlPoint; /** * @brief Allows filtering by the chooser name @@ -21,19 +20,21 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class ChooserNameFilter : public AbstractStringFilter { Q_OBJECT public: ChooserNameFilter(AbstractFilter::FilterEffectivenessFlag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); ChooserNameFilter(const ChooserNameFilter &other); virtual ~ChooserNameFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; diff --git a/isis/src/qisis/objs/CnetEditorWidget/CnetEditorSortConfigDialog.cpp b/isis/src/qisis/objs/CnetEditorWidget/CnetEditorSortConfigDialog.cpp index 324560dde985b82d9d6b85f21c6406c8bbfb0e67..b328810050d329bda03f513f83675f9399630509 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/CnetEditorSortConfigDialog.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/CnetEditorSortConfigDialog.cpp @@ -23,6 +23,8 @@ namespace Isis { CnetEditorWidget *cnetWidget) : QDialog(cnetWidget) { m_cnetWidget = cnetWidget; + setWindowTitle("Table Sorting"); + QGridLayout *mainLayout = new QGridLayout; mainLayout->setColumnMinimumWidth(0, 20); setLayout(mainLayout); @@ -200,4 +202,3 @@ namespace Isis { m_measureSortingCheckBox->isChecked()); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/CnetEditorSortConfigDialog.h b/isis/src/qisis/objs/CnetEditorWidget/CnetEditorSortConfigDialog.h index 8ccbf915bc03542d65c588fc6abbae8f12259eb5..3223a6054d5961def496a94c8b0de402cbd5813b 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/CnetEditorSortConfigDialog.h +++ b/isis/src/qisis/objs/CnetEditorWidget/CnetEditorSortConfigDialog.h @@ -23,6 +23,8 @@ namespace Isis { * * @internal * @history 2012-09-28 Kimberly Oyama - Changed member variables to be prefixed with "m_". + * @history 2018-06-12 Kaitlyn Lee - Set the window title to "Table Sorting" + * with setWindowTitle(). */ class CnetEditorSortConfigDialog : public QDialog { Q_OBJECT @@ -64,4 +66,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.cpp b/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.cpp index 30dbba1a8c973bf8963801b298563b15286d0ab6..f5f77b888872c0f0a8bc2e20d16a4452e78e0aa0 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.cpp @@ -75,6 +75,8 @@ namespace Isis { m_updatingSelection = false; + m_sortDialog = NULL; + m_control = control; connect(CnetDisplayProperties::getInstance(), SIGNAL(compositionFinished()), this, SLOT(rebuildModels())); @@ -151,6 +153,9 @@ namespace Isis { delete m_connectionModel; m_connectionModel = NULL; + + delete m_sortDialog; + m_sortDialog = NULL; } @@ -189,6 +194,8 @@ namespace Isis { m_control = NULL; m_settingsPath = NULL; m_workingVersion = NULL; + + m_sortDialog = NULL; } @@ -1015,12 +1022,14 @@ namespace Isis { /** - * Configures the sorting dialog + * Configures the sorting dialog. + * If one does not already exist, create it, then show the dialog */ void CnetEditorWidget::configSorting() { - CnetEditorSortConfigDialog *dialog = new CnetEditorSortConfigDialog(this); - dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->show(); + if (!m_sortDialog) { + m_sortDialog = new CnetEditorSortConfigDialog(this); + } + m_sortDialog->show(); } diff --git a/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.h b/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.h index e66c559403d103365c789babd46b6e2cb814e7ec..c048436790b58193f5d3c70d966b6022a3df236e 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.h +++ b/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.h @@ -44,6 +44,7 @@ namespace Isis { class PointTableModel; class TableView; class TreeView; + class CnetEditorSortConfigDialog; /** * This widget provides full editing, filtering and viewing capabilities for @@ -73,6 +74,8 @@ namespace Isis { * Fixes #4989. * @history 2018-04-11 Tracie Sucharski - Moved the Xml serialization to the newly created * CnetEditorView class for ipce. + * @history 2018-06-12 Kaitlyn Lee - Added m_sortDialog to keep track if a dialog exists + * so only one instance can be open at a time. */ class CnetEditorWidget : public QWidget { Q_OBJECT @@ -190,6 +193,9 @@ namespace Isis { QMap< QString, QList< QAction * > > * m_toolBarActions; //!< QMap of tool bar actions QString *m_settingsPath; //!< Path to read/write settings + + CnetEditorSortConfigDialog *m_sortDialog; //!< Sorting dialog + }; } diff --git a/isis/src/qisis/objs/CnetEditorWidget/ConnectionParentItem.cpp b/isis/src/qisis/objs/CnetEditorWidget/ConnectionParentItem.cpp index d0d3014f9ab08d400197e9cb0ad96d65e759069b..2824c1ede76c8978163f05f261619ebd3732c992 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ConnectionParentItem.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/ConnectionParentItem.cpp @@ -6,9 +6,9 @@ namespace Isis { - ConnectionParentItem::ConnectionParentItem(ControlCubeGraphNode *node, - int avgCharWidth, AbstractTreeItem *parent) - : AbstractTreeItem(parent), AbstractImageItem(node, avgCharWidth) { + ConnectionParentItem::ConnectionParentItem(QString imageSerial, ControlNet *net, + int avgCharWidth, AbstractTreeItem *parent) + : AbstractTreeItem(parent), AbstractImageItem(imageSerial, net, avgCharWidth) { } diff --git a/isis/src/qisis/objs/CnetEditorWidget/ConnectionParentItem.h b/isis/src/qisis/objs/CnetEditorWidget/ConnectionParentItem.h index fd38dd2caa3f502acc96cf07db70bfe65b496db1..5f09abd8c805534105d8db9728de89586cc5c2ec 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ConnectionParentItem.h +++ b/isis/src/qisis/objs/CnetEditorWidget/ConnectionParentItem.h @@ -5,9 +5,10 @@ #include "AbstractImageItem.h" #include "AbstractParentItem.h" +class QString; namespace Isis { - class ControlCubeGraphNode; + class ControlNet; /** * @brief Tree item that is a parent and represents an image @@ -17,14 +18,16 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class ConnectionParentItem : public AbstractImageItem, public AbstractParentItem { public: - ConnectionParentItem(ControlCubeGraphNode *node, - int avgCharWidth, AbstractTreeItem *parent = 0); + ConnectionParentItem(QString imageSerial, ControlNet *net, + int avgCharWidth, AbstractTreeItem *parent = 0); virtual ~ConnectionParentItem(); void addChild(AbstractTreeItem *child); diff --git a/isis/src/qisis/objs/CnetEditorWidget/FilterWidget.cpp b/isis/src/qisis/objs/CnetEditorWidget/FilterWidget.cpp index e05a3a6edaea62946697565d352f1d23ae2c4c77..a7bcb433681c0cfbedc37bed8421f82a12e194f9 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/FilterWidget.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/FilterWidget.cpp @@ -8,6 +8,7 @@ #include <QHBoxLayout> #include <QIcon> #include <QLabel> +#include <QPair> #include <QPushButton> #include <QRadioButton> #include <QString> @@ -71,8 +72,8 @@ namespace Isis { } - bool FilterWidget::evaluate(const ControlCubeGraphNode *node) const { - return evaluate(node, &AbstractFilter::canFilterImages); + bool FilterWidget::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluate(imageAndNet, &AbstractFilter::canFilterImages); } diff --git a/isis/src/qisis/objs/CnetEditorWidget/FilterWidget.h b/isis/src/qisis/objs/CnetEditorWidget/FilterWidget.h index a71955f929141521a38d901d40eeea4a3d09975c..ea10c8a561ceb5f1d35e829ab2e15f63cd573680 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/FilterWidget.h +++ b/isis/src/qisis/objs/CnetEditorWidget/FilterWidget.h @@ -11,6 +11,7 @@ class QLabel; template< class T > class QList; +template< typename U, typename V > class QPair; class QPushButton; class QString; class QTextEdit; @@ -18,7 +19,7 @@ class QVBoxLayout; namespace Isis { - class ControlCubeGraphNode; + class ControlNet; class ControlMeasure; class ControlPoint; class FilterGroup; @@ -42,6 +43,8 @@ namespace Isis { * @history 2012-09-28 Kimberly Oyama - Changed member variables to be prefixed with "m_". * @history 2015-11-16 Ian Humphrey - Removed embedded icons. References #1041. * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class FilterWidget : public QWidget { Q_OBJECT @@ -63,7 +66,7 @@ namespace Isis { for (int i = 0; looking && i < m_filterGroups->size(); i++) { if (m_filterGroups->at(i)->hasFilter(meth)) looking = !(m_filterGroups->at(i)->evaluate(t, meth) ^ - m_andGroupsTogether); + m_andGroupsTogether); } // It is good that we are still looking for failures if we were @@ -73,7 +76,7 @@ namespace Isis { return !(looking ^ m_andGroupsTogether) || !hasFilter(meth); } - bool evaluate(const ControlCubeGraphNode *node) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *point) const; bool evaluate(const ControlMeasure *measure) const; diff --git a/isis/src/qisis/objs/CnetEditorWidget/GoodnessOfFitFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/GoodnessOfFitFilter.cpp index 696804bc88776f56f928b0d4167503db0fd6ef39..7dd671821d36688df9f61bfb53599abddc2bca29 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/GoodnessOfFitFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/GoodnessOfFitFilter.cpp @@ -2,21 +2,25 @@ #include "GoodnessOfFitFilter.h" -#include "ControlCubeGraphNode.h" +#include <QPair> +#include <QString> + #include "ControlMeasure.h" #include "ControlMeasureLogData.h" +#include "ControlNet.h" +#include "ControlPoint.h" #include "SpecialPixel.h" namespace Isis { GoodnessOfFitFilter::GoodnessOfFitFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } - GoodnessOfFitFilter::GoodnessOfFitFilter( - const GoodnessOfFitFilter &other) : AbstractNumberFilter(other) { + GoodnessOfFitFilter::GoodnessOfFitFilter(const GoodnessOfFitFilter &other) + : AbstractNumberFilter(other) { } @@ -24,8 +28,8 @@ namespace Isis { } - bool GoodnessOfFitFilter::evaluate(const ControlCubeGraphNode *node) const { - return evaluateImageFromMeasureFilter(node); + bool GoodnessOfFitFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromMeasureFilter(imageAndNet); } @@ -36,9 +40,9 @@ namespace Isis { bool GoodnessOfFitFilter::evaluate(const ControlMeasure *measure) const { double goodness = Null; + if (measure->HasLogData(ControlMeasureLogData::GoodnessOfFit)) { - goodness = measure->GetLogData( - ControlMeasureLogData::GoodnessOfFit).GetNumericalValue(); + goodness = measure->GetLogData(ControlMeasureLogData::GoodnessOfFit).GetNumericalValue(); } return AbstractNumberFilter::evaluate(goodness); diff --git a/isis/src/qisis/objs/CnetEditorWidget/GoodnessOfFitFilter.h b/isis/src/qisis/objs/CnetEditorWidget/GoodnessOfFitFilter.h index 22103bfccf55b7850094d79cb2f404d2d7143de8..d5e397169bd7f061f433f7e11f2785836ff9d37e 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/GoodnessOfFitFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/GoodnessOfFitFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -22,20 +20,21 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. - * + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class GoodnessOfFitFilter : public AbstractNumberFilter { Q_OBJECT public: GoodnessOfFitFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); GoodnessOfFitFilter(const GoodnessOfFitFilter &other); virtual ~GoodnessOfFitFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; diff --git a/isis/src/qisis/objs/CnetEditorWidget/ImageIdFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/ImageIdFilter.cpp index 9f0227d444e82037ed542d5d6ca4826cfa292062..8f041b5b929c72ef14b35afd463d7d486d969686 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ImageIdFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/ImageIdFilter.cpp @@ -2,24 +2,24 @@ #include "ImageIdFilter.h" +#include <QPair> #include <QString> #include "CnetDisplayProperties.h" -#include "ControlCubeGraphNode.h" #include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" #include "IString.h" namespace Isis { ImageIdFilter::ImageIdFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractStringFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractStringFilter(flag, minimumForSuccess) { } - ImageIdFilter::ImageIdFilter( - const ImageIdFilter &other): AbstractStringFilter(other) { + ImageIdFilter::ImageIdFilter(const ImageIdFilter &other): AbstractStringFilter(other) { } @@ -27,11 +27,9 @@ namespace Isis { } - bool ImageIdFilter::evaluate( - const ControlCubeGraphNode *node) const { + bool ImageIdFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { return AbstractStringFilter::evaluate( - CnetDisplayProperties::getInstance()->getImageName( - (QString) node->getSerialNumber())); + CnetDisplayProperties::getInstance()->getImageName(imageAndNet->first)); } @@ -42,8 +40,8 @@ namespace Isis { bool ImageIdFilter::evaluate(const ControlMeasure *measure) const { return AbstractStringFilter::evaluate( - CnetDisplayProperties::getInstance()->getImageName( - (QString) measure->GetCubeSerialNumber())); + CnetDisplayProperties::getInstance()->getImageName( + (QString) measure->GetCubeSerialNumber())); } diff --git a/isis/src/qisis/objs/CnetEditorWidget/ImageIdFilter.h b/isis/src/qisis/objs/CnetEditorWidget/ImageIdFilter.h index 82f3c1d7d59c6ad3dbf140c397407abf38dadbfc..0eca7f262676e4b8b6cab578d4f7fc7b5b9e3caf 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ImageIdFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/ImageIdFilter.h @@ -3,14 +3,12 @@ #include "AbstractStringFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -24,19 +22,21 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class ImageIdFilter : public AbstractStringFilter { Q_OBJECT public: ImageIdFilter(AbstractFilter::FilterEffectivenessFlag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); ImageIdFilter(const ImageIdFilter &other); virtual ~ImageIdFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; diff --git a/isis/src/qisis/objs/CnetEditorWidget/ImageImageTreeModel.cpp b/isis/src/qisis/objs/CnetEditorWidget/ImageImageTreeModel.cpp index d79dba245ac1e9f72c90b2fa72cdeab6552ad4e4..50ad80710854f2d289cb77d03d3f231caa181e18 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ImageImageTreeModel.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/ImageImageTreeModel.cpp @@ -10,7 +10,6 @@ #include <QString> #include <QtConcurrentMap> -#include "ControlCubeGraphNode.h" #include "ControlMeasure.h" #include "ControlNet.h" @@ -39,8 +38,9 @@ namespace Isis { ImageImageTreeModel::CreateRootItemFunctor::CreateRootItemFunctor( - AbstractTreeModel *tm, QThread *tt) { + AbstractTreeModel *tm, ControlNet *net, QThread *tt) { m_treeModel = tm; + m_controlNet = net; m_targetThread = tt; m_avgCharWidth = QFontMetrics( m_treeModel->getView()->getContentFont()).averageCharWidth(); @@ -50,6 +50,7 @@ namespace Isis { ImageImageTreeModel::CreateRootItemFunctor::CreateRootItemFunctor( const CreateRootItemFunctor &other) { m_treeModel = other.m_treeModel; + m_controlNet = other.m_controlNet; m_targetThread = other.m_targetThread; m_avgCharWidth = other.m_avgCharWidth; } @@ -57,27 +58,28 @@ namespace Isis { ImageImageTreeModel::CreateRootItemFunctor::~CreateRootItemFunctor() { m_treeModel = NULL; + m_controlNet = NULL; m_targetThread = NULL; } ImageParentItem *ImageImageTreeModel::CreateRootItemFunctor::operator()( - ControlCubeGraphNode *const &node) const { + const QString imageSerial) const { + ImageParentItem *parentItem = - new ImageParentItem(node, m_avgCharWidth); + new ImageParentItem(imageSerial, m_controlNet, m_avgCharWidth); parentItem->setSelectable(false); parentItem->moveToThread(m_targetThread); - QList< ControlCubeGraphNode * > connectedNodes = node->getAdjacentNodes(); + QList< QString > connectedImages = m_controlNet->getAdjacentImages(imageSerial); - for (int j = 0; j < connectedNodes.size(); j++) { - ControlCubeGraphNode *connectedNode = connectedNodes[j]; - ImageLeafItem *serialItem = - new ImageLeafItem(connectedNode, m_avgCharWidth, parentItem); - serialItem->setSelectable(false); - serialItem->moveToThread(m_targetThread); + for (int j = 0; j < connectedImages.size(); j++) { + ImageLeafItem *childItem = + new ImageLeafItem(connectedImages[j], m_controlNet, m_avgCharWidth, parentItem); + childItem->setSelectable(false); + childItem->moveToThread(m_targetThread); - parentItem->addChild(serialItem); + parentItem->addChild(childItem); } return parentItem; @@ -126,8 +128,8 @@ namespace Isis { } futureRoot = QtConcurrent::mappedReduced( - getControlNetwork()->GetCubeGraphNodes(), - CreateRootItemFunctor(this, QThread::currentThread()), + getControlNetwork()->GetCubeSerials(), + CreateRootItemFunctor(this, getControlNetwork(), QThread::currentThread()), &CreateRootItemFunctor::addToRootItem, QtConcurrent::OrderedReduce | QtConcurrent::SequentialReduce); diff --git a/isis/src/qisis/objs/CnetEditorWidget/ImageImageTreeModel.h b/isis/src/qisis/objs/CnetEditorWidget/ImageImageTreeModel.h index 662c17bb5aab0db6b08fc9bf378eeb25253f1f65..e595a254518e22817609ab45216b62f7fddc5c1e 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ImageImageTreeModel.h +++ b/isis/src/qisis/objs/CnetEditorWidget/ImageImageTreeModel.h @@ -14,7 +14,6 @@ class QString; namespace Isis { - class ControlCubeGraphNode; class ControlNet; class ImageParentItem; class TreeView; @@ -36,6 +35,8 @@ namespace Isis { * @internal * @history 2012-09-28 Kimberly Oyama - Changed member variables to be prefixed with "m_". * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class ImageImageTreeModel : public AbstractTreeModel { Q_OBJECT @@ -60,12 +61,12 @@ namespace Isis { * @history 2012-09-28 Kimberly Oyama - Changed member variables to be prefixed with "m_". */ class CreateRootItemFunctor : public std::unary_function < - ControlCubeGraphNode *const &, ImageParentItem * > { + const QString, ImageParentItem * > { public: - CreateRootItemFunctor(AbstractTreeModel *tm, QThread *tt); + CreateRootItemFunctor(AbstractTreeModel *tm, ControlNet *net, QThread *tt); CreateRootItemFunctor(const CreateRootItemFunctor &); ~CreateRootItemFunctor(); - ImageParentItem *operator()(ControlCubeGraphNode *const &) + ImageParentItem *operator()(const QString imageSerial) const; CreateRootItemFunctor &operator=(const CreateRootItemFunctor &); @@ -76,6 +77,7 @@ namespace Isis { int m_avgCharWidth; AbstractTreeModel *m_treeModel; QThread *m_targetThread; + ControlNet *m_controlNet; }; }; } diff --git a/isis/src/qisis/objs/CnetEditorWidget/ImageLeafItem.cpp b/isis/src/qisis/objs/CnetEditorWidget/ImageLeafItem.cpp index c9513edb9acf320ebc6d82222126c10662f75e1b..bcdcac8f2dd98304acdc94131fca63867855881c 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ImageLeafItem.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/ImageLeafItem.cpp @@ -4,9 +4,9 @@ namespace Isis { - ImageLeafItem::ImageLeafItem(ControlCubeGraphNode *node, - int avgCharWidth, AbstractTreeItem *parent) - : AbstractTreeItem(parent), AbstractImageItem(node, avgCharWidth) { + ImageLeafItem::ImageLeafItem(QString imageSerial, ControlNet *net, + int avgCharWidth, AbstractTreeItem *parent) + : AbstractTreeItem(parent), AbstractImageItem(imageSerial, net, avgCharWidth) { } diff --git a/isis/src/qisis/objs/CnetEditorWidget/ImageLeafItem.h b/isis/src/qisis/objs/CnetEditorWidget/ImageLeafItem.h index 1776f6f9217b01aa6e3bb771f8459a94d692c8ce..c9cb9dd2a4adf361565da5d50a9da1bf52191d6e 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ImageLeafItem.h +++ b/isis/src/qisis/objs/CnetEditorWidget/ImageLeafItem.h @@ -1,13 +1,14 @@ #ifndef ImageLeafItem_H #define ImageLeafItem_H +#include <QString> #include "AbstractImageItem.h" #include "AbstractLeafItem.h" namespace Isis { - class ControlCubeGraphNode; + class ControlNet; /** * @brief Tree item that is a leaf and represents an image @@ -17,13 +18,15 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class ImageLeafItem : public AbstractImageItem, public AbstractLeafItem { public: - ImageLeafItem(ControlCubeGraphNode *node, - int avgCharWidth, AbstractTreeItem *parent = 0); + ImageLeafItem(QString imageSerial, ControlNet *net, + int avgCharWidth, AbstractTreeItem *parent = 0); virtual ~ImageLeafItem(); diff --git a/isis/src/qisis/objs/CnetEditorWidget/ImageParentItem.cpp b/isis/src/qisis/objs/CnetEditorWidget/ImageParentItem.cpp index 2a55b3938b51cccf566f7db85fa791d5f969f1ed..d99de2b36a559bce265e55c4d41fb971300ca244 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ImageParentItem.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/ImageParentItem.cpp @@ -2,11 +2,12 @@ #include "ImageParentItem.h" +#include "ControlNet.h" namespace Isis { - ImageParentItem::ImageParentItem(ControlCubeGraphNode *node, - int avgCharWidth, AbstractTreeItem *parent) - : AbstractTreeItem(parent), AbstractImageItem(node, avgCharWidth) { + ImageParentItem::ImageParentItem(QString imageSerial, ControlNet *net, + int avgCharWidth, AbstractTreeItem *parent) + : AbstractTreeItem(parent), AbstractImageItem(imageSerial, net, avgCharWidth) { } diff --git a/isis/src/qisis/objs/CnetEditorWidget/ImageParentItem.h b/isis/src/qisis/objs/CnetEditorWidget/ImageParentItem.h index dce3fa6865ef12a4d20771409223032d3f38719e..82777e57c9661a367bd4d52b020de06be6f9923e 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ImageParentItem.h +++ b/isis/src/qisis/objs/CnetEditorWidget/ImageParentItem.h @@ -1,13 +1,14 @@ #ifndef ImageParentItem_H #define ImageParentItem_H +#include <QString> #include "AbstractImageItem.h" #include "AbstractParentItem.h" namespace Isis { - class ControlCubeGraphNode; + class ControlNet; /** * @brief Tree item that is a parent and represents an image @@ -17,13 +18,15 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class ImageParentItem : public AbstractImageItem, public AbstractParentItem { public: - ImageParentItem(ControlCubeGraphNode *node, - int avgCharWidth, AbstractTreeItem *parent = 0); + ImageParentItem(QString imageSerial, ControlNet *net, + int avgCharWidth, AbstractTreeItem *parent = 0); virtual ~ImageParentItem(); diff --git a/isis/src/qisis/objs/CnetEditorWidget/ImagePointFilterSelector.cpp b/isis/src/qisis/objs/CnetEditorWidget/ImagePointFilterSelector.cpp index ae7eeef75cd04e1f4d8b8852e4ad747489a4ac36..dffafa341511fcaac4b992e0b623938052e04739 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ImagePointFilterSelector.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/ImagePointFilterSelector.cpp @@ -50,12 +50,12 @@ namespace Isis { } - ImagePointFilterSelector::ImagePointFilterSelector( - const ImagePointFilterSelector &other) { + ImagePointFilterSelector::ImagePointFilterSelector(const ImagePointFilterSelector &other) { createSelector(); getSelector()->setCurrentIndex(other.getSelector()->currentIndex()); - if (other.getFilter()) + if (other.getFilter()) { setFilter(other.getFilter()->clone()); + } } @@ -64,7 +64,7 @@ namespace Isis { ImagePointFilterSelector &ImagePointFilterSelector::operator=( - const ImagePointFilterSelector &other) { + const ImagePointFilterSelector &other) { *((AbstractFilterSelector *) this) = other; return *this; } @@ -229,4 +229,3 @@ namespace Isis { emit filterChanged(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/ImagePointFilterSelector.h b/isis/src/qisis/objs/CnetEditorWidget/ImagePointFilterSelector.h index 7979b1eec245b3ba1590980a4632914793d3a6c0..a18ddb8302543c78bbb50af0178f44a9524bc6c6 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ImagePointFilterSelector.h +++ b/isis/src/qisis/objs/CnetEditorWidget/ImagePointFilterSelector.h @@ -6,7 +6,6 @@ namespace Isis { - class AbstractFilter; /** * @brief Allows users to choose filters for filtering images and points @@ -16,8 +15,8 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. */ class ImagePointFilterSelector : public AbstractFilterSelector { Q_OBJECT @@ -26,8 +25,7 @@ namespace Isis { ImagePointFilterSelector(); ImagePointFilterSelector(const ImagePointFilterSelector &other); virtual ~ImagePointFilterSelector(); - ImagePointFilterSelector &operator=( - const ImagePointFilterSelector &other); + ImagePointFilterSelector &operator=(const ImagePointFilterSelector &other); protected: @@ -40,4 +38,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/ImagePointTreeModel.cpp b/isis/src/qisis/objs/CnetEditorWidget/ImagePointTreeModel.cpp index c79efea2e9e576c6661563546218d49260ab3ec1..c22981e1ce6a5ecaec42646778ab6601ca15d433 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ImagePointTreeModel.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/ImagePointTreeModel.cpp @@ -11,7 +11,6 @@ #include <QString> #include <QtConcurrentMap> -#include "ControlCubeGraphNode.h" #include "ControlMeasure.h" #include "ControlNet.h" #include "ControlPoint.h" @@ -41,8 +40,9 @@ namespace Isis { ImagePointTreeModel::CreateRootItemFunctor::CreateRootItemFunctor( - AbstractTreeModel *tm, QThread *tt) { + AbstractTreeModel *tm, ControlNet *net, QThread *tt) { m_treeModel = tm; + m_controlNet = net; m_targetThread = tt; m_avgCharWidth = QFontMetrics( m_treeModel->getView()->getContentFont()).averageCharWidth(); @@ -52,6 +52,7 @@ namespace Isis { ImagePointTreeModel::CreateRootItemFunctor::CreateRootItemFunctor( const CreateRootItemFunctor &other) { m_treeModel = other.m_treeModel; + m_controlNet = other.m_controlNet; m_targetThread = other.m_targetThread; m_avgCharWidth = other.m_avgCharWidth; } @@ -59,18 +60,21 @@ namespace Isis { ImagePointTreeModel::CreateRootItemFunctor::~CreateRootItemFunctor() { m_targetThread = NULL; + m_controlNet = NULL; m_treeModel = NULL; } ImageParentItem *ImagePointTreeModel::CreateRootItemFunctor::operator()( - ControlCubeGraphNode *const &node) const { + QString imageSerial) const { ImageParentItem *imageItem = NULL; - imageItem = new ImageParentItem(node, m_avgCharWidth); + // TODO connect parent item destroy to image removed from network + + imageItem = new ImageParentItem(imageSerial, m_controlNet, m_avgCharWidth); imageItem->setSelectable(false); imageItem->moveToThread(m_targetThread); - QList< ControlMeasure * > measures = node->getMeasures(); + QList< ControlMeasure * > measures = m_controlNet->GetMeasuresInCube(imageSerial); for (int j = 0; j < measures.size(); j++) { ASSERT(measures[j]); ControlPoint *point = measures[j]->Parent(); @@ -129,8 +133,8 @@ namespace Isis { } futureRoot = QtConcurrent::mappedReduced( - getControlNetwork()->GetCubeGraphNodes(), - CreateRootItemFunctor(this, QThread::currentThread()), + getControlNetwork()->GetCubeSerials(), + CreateRootItemFunctor(this, getControlNetwork(), QThread::currentThread()), &CreateRootItemFunctor::addToRootItem, QtConcurrent::OrderedReduce | QtConcurrent::SequentialReduce); diff --git a/isis/src/qisis/objs/CnetEditorWidget/ImagePointTreeModel.h b/isis/src/qisis/objs/CnetEditorWidget/ImagePointTreeModel.h index 3835cff8be60f97d0a392c904026bf6765678322..02347d9c34c8bd8736d63bf049c5f1ca132efb37 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ImagePointTreeModel.h +++ b/isis/src/qisis/objs/CnetEditorWidget/ImagePointTreeModel.h @@ -13,7 +13,6 @@ class QString; namespace Isis { - class ControlCubeGraphNode; class ControlNet; class ImageParentItem; class TreeView; @@ -35,6 +34,8 @@ namespace Isis { * @internal * @history 2012-09-28 Kimberly Oyama - Changed member variables to be prefixed with "m_". * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class ImagePointTreeModel : public AbstractTreeModel { Q_OBJECT @@ -58,12 +59,12 @@ namespace Isis { * @internal */ class CreateRootItemFunctor : public std::unary_function < - ControlCubeGraphNode *const &, ImageParentItem * > { + const QString, ImageParentItem * > { public: - CreateRootItemFunctor(AbstractTreeModel *tm, QThread *tt); + CreateRootItemFunctor(AbstractTreeModel *tm, ControlNet *net, QThread *tt); CreateRootItemFunctor(const CreateRootItemFunctor &); ~CreateRootItemFunctor(); - ImageParentItem *operator()(ControlCubeGraphNode *const &) const; + ImageParentItem *operator()(const QString imageSerial) const; CreateRootItemFunctor &operator=(const CreateRootItemFunctor &); static void addToRootItem(QAtomicPointer< RootItem > &, @@ -73,6 +74,7 @@ namespace Isis { int m_avgCharWidth; AbstractTreeModel *m_treeModel; QThread *m_targetThread; + ControlNet *m_controlNet; }; }; } diff --git a/isis/src/qisis/objs/CnetEditorWidget/LineFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/LineFilter.cpp index 10e1305bfe4fe9d50ffae0539b763762d2d3c176..3a51b82c4b84f00de4dedf10f52f0ecb5b8bf105 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/LineFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/LineFilter.cpp @@ -2,19 +2,22 @@ #include "LineFilter.h" -#include "ControlCubeGraphNode.h" +#include <QPair> +#include <QString> + #include "ControlMeasure.h" +#include "ControlNet.h" +#include "ControlPoint.h" namespace Isis { LineFilter::LineFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } - LineFilter::LineFilter(const LineFilter &other) - : AbstractNumberFilter(other) { + LineFilter::LineFilter(const LineFilter &other) : AbstractNumberFilter(other) { } @@ -22,8 +25,8 @@ namespace Isis { } - bool LineFilter::evaluate(const ControlCubeGraphNode *node) const { - return evaluateImageFromMeasureFilter(node); + bool LineFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromMeasureFilter(imageAndNet); } @@ -44,10 +47,12 @@ namespace Isis { QString LineFilter::getImageDescription() const { QString description = AbstractFilter::getImageDescription(); - if (getMinForSuccess() == 1) + if (getMinForSuccess() == 1) { description += "measure that has a line which is "; - else + } + else { description += "measures that have lines which are "; + } description += descriptionSuffix(); return description; diff --git a/isis/src/qisis/objs/CnetEditorWidget/LineFilter.h b/isis/src/qisis/objs/CnetEditorWidget/LineFilter.h index 15e6cfb3814bc236e18f7ea3b5996225e29c66fc..5d0ed194d40428682d170303d2fc611216b4e104 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/LineFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/LineFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -23,20 +21,21 @@ namespace Isis { * * @author 2012-01-05 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. - * + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class LineFilter : public AbstractNumberFilter { Q_OBJECT public: LineFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); LineFilter(const LineFilter &other); virtual ~LineFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -49,4 +48,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/LineResidualFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/LineResidualFilter.cpp index 74752fcf10930c64e9398c98ff0e2388752dc9bf..0091e3be206b493570453389aa97facf10e0b16b 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/LineResidualFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/LineResidualFilter.cpp @@ -2,19 +2,23 @@ #include "LineResidualFilter.h" -#include "ControlCubeGraphNode.h" +#include <QPair> +#include <QString> + #include "ControlMeasure.h" +#include "ControlNet.h" +#include "ControlPoint.h" namespace Isis { LineResidualFilter::LineResidualFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } LineResidualFilter::LineResidualFilter(const LineResidualFilter &other) - : AbstractNumberFilter(other) { + : AbstractNumberFilter(other) { } @@ -22,8 +26,8 @@ namespace Isis { } - bool LineResidualFilter::evaluate(const ControlCubeGraphNode *node) const { - return evaluateImageFromMeasureFilter(node); + bool LineResidualFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromMeasureFilter(imageAndNet); } @@ -44,10 +48,13 @@ namespace Isis { QString LineResidualFilter::getImageDescription() const { QString description = AbstractFilter::getImageDescription(); - if (getMinForSuccess() == 1) + + if (getMinForSuccess() == 1) { description += "measure that has a line residual which is "; - else + } + else { description += "measures that have line residuals which are "; + } description += descriptionSuffix(); return description; @@ -63,4 +70,3 @@ namespace Isis { return "have line residuals which are " + descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/LineResidualFilter.h b/isis/src/qisis/objs/CnetEditorWidget/LineResidualFilter.h index 949c0edfb820abd812cf602a494d7c322345cf3a..5ea78c9172af0c1aeff4f8b8785160ff3c432887 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/LineResidualFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/LineResidualFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -22,19 +20,21 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class LineResidualFilter : public AbstractNumberFilter { Q_OBJECT public: LineResidualFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); LineResidualFilter(const LineResidualFilter &other); virtual ~LineResidualFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; diff --git a/isis/src/qisis/objs/CnetEditorWidget/LineShiftFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/LineShiftFilter.cpp index 8f60cd2bb2b2ba968d4d6517d06a1a028aa06891..a4742086e078324de11342d0916301e93482d4d8 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/LineShiftFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/LineShiftFilter.cpp @@ -2,19 +2,22 @@ #include "LineShiftFilter.h" -#include "ControlCubeGraphNode.h" +#include <QPair> +#include <QString> + #include "ControlMeasure.h" +#include "ControlNet.h" +#include "ControlPoint.h" namespace Isis { LineShiftFilter::LineShiftFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } - LineShiftFilter::LineShiftFilter(const LineShiftFilter &other) - : AbstractNumberFilter(other) { + LineShiftFilter::LineShiftFilter(const LineShiftFilter &other) : AbstractNumberFilter(other) { } @@ -22,8 +25,8 @@ namespace Isis { } - bool LineShiftFilter::evaluate(const ControlCubeGraphNode *node) const { - return evaluateImageFromMeasureFilter(node); + bool LineShiftFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromMeasureFilter(imageAndNet); } @@ -63,4 +66,3 @@ namespace Isis { return "have line shifts which are " + descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/LineShiftFilter.h b/isis/src/qisis/objs/CnetEditorWidget/LineShiftFilter.h index c22b9021ac3d3cd8faccfc7b70ef0a16a1ff604d..480cb01ecb7d8fc92b15d5d502c53d86d92a10db 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/LineShiftFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/LineShiftFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -24,19 +22,21 @@ namespace Isis { * * @author 2012-04-18 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class LineShiftFilter : public AbstractNumberFilter { Q_OBJECT public: LineShiftFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); LineShiftFilter(const LineShiftFilter &other); virtual ~LineShiftFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -49,4 +49,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/MeasureCountFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/MeasureCountFilter.cpp index 136a1289eb82adcb46f7b260e899918bc9555824..8a78023184e1e3e545fcaa2442afb74f592bdaf2 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/MeasureCountFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/MeasureCountFilter.cpp @@ -10,25 +10,26 @@ #include <QLabel> #include <QLineEdit> #include <QMargins> +#include <QPair> #include <QRadioButton> #include <QSpinBox> +#include <QString> -#include "ControlCubeGraphNode.h" #include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" namespace Isis { MeasureCountFilter::MeasureCountFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { init(); createWidget(); } - MeasureCountFilter::MeasureCountFilter(const MeasureCountFilter &other) - : AbstractFilter(other) { + MeasureCountFilter::MeasureCountFilter(const MeasureCountFilter &other) : AbstractFilter(other) { init(); createWidget(); @@ -84,14 +85,14 @@ namespace Isis { } - bool MeasureCountFilter::evaluate(const ControlCubeGraphNode *node) const { - return AbstractFilter::evaluateImageFromPointFilter(node); + bool MeasureCountFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return AbstractFilter::evaluateImageFromPointFilter(imageAndNet); } bool MeasureCountFilter::evaluate(const ControlPoint *point) const { return (point->getMeasures().size() >= m_count && m_minimum) || - (point->getMeasures().size() <= m_count && !m_minimum); + (point->getMeasures().size() <= m_count && !m_minimum); } diff --git a/isis/src/qisis/objs/CnetEditorWidget/MeasureCountFilter.h b/isis/src/qisis/objs/CnetEditorWidget/MeasureCountFilter.h index 0a985fc21a26584d055e1b6742c47e6057dcb9c7..d51e3697df7d78f07e7493577812bf1a559c0c00 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/MeasureCountFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/MeasureCountFilter.h @@ -2,20 +2,19 @@ #define MeasureCountFilter_H -// parent #include "AbstractFilter.h" - class QButtonGroup; class QLineEdit; +template< typename U, typename V > class QPair; class QSpinBox; class QString; namespace Isis { - class AbstractFilterSelector; - class ControlPoint; class ControlMeasure; + class ControlNet; + class ControlPoint; /** * @brief Allows filtering by the number of measures in a control point @@ -29,17 +28,19 @@ namespace Isis { * @internal * @history 2012-09-28 Kimberly Oyama - Changed member variables to be prefixed with "m_". * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class MeasureCountFilter : public AbstractFilter { Q_OBJECT public: MeasureCountFilter(AbstractFilter::FilterEffectivenessFlag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); MeasureCountFilter(const MeasureCountFilter &other); virtual ~MeasureCountFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; diff --git a/isis/src/qisis/objs/CnetEditorWidget/MeasureIgnoredFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/MeasureIgnoredFilter.cpp index 39f451a15bbfc350563f762e1074331df002ce2b..db1bc8fa7f8228f3fe6ce667d88d3f7e971d5758 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/MeasureIgnoredFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/MeasureIgnoredFilter.cpp @@ -2,18 +2,18 @@ #include "MeasureIgnoredFilter.h" -#include <iostream> +#include <QPair> +#include <QString> -#include <QHBoxLayout> - -#include "ControlCubeGraphNode.h" #include "ControlMeasure.h" +#include "ControlNet.h" +#include "ControlPoint.h" namespace Isis { MeasureIgnoredFilter::MeasureIgnoredFilter( - AbstractFilter::FilterEffectivenessFlag flag, int minimumForSuccess) : - AbstractFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { } @@ -21,8 +21,8 @@ namespace Isis { } - bool MeasureIgnoredFilter::evaluate(const ControlCubeGraphNode *node) const { - return AbstractFilter::evaluateImageFromMeasureFilter(node); + bool MeasureIgnoredFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return AbstractFilter::evaluateImageFromMeasureFilter(imageAndNet); } @@ -43,15 +43,19 @@ namespace Isis { QString MeasureIgnoredFilter::getImageDescription() const { QString description = AbstractFilter::getImageDescription(); - if (getMinForSuccess() == 1) + if (getMinForSuccess() == 1) { description += "measure that is "; - else + } + else { description += "measures that are "; + } - if (inclusive()) + if (inclusive()) { description += "ignored"; - else + } + else { description += "not ignored"; + } return description; } @@ -65,10 +69,12 @@ namespace Isis { QString MeasureIgnoredFilter::getMeasureDescription() const { QString description = "are "; - if (inclusive()) + if (inclusive()) { description += "ignored"; - else + } + else { description += "not ignored"; + } return description; } diff --git a/isis/src/qisis/objs/CnetEditorWidget/MeasureIgnoredFilter.h b/isis/src/qisis/objs/CnetEditorWidget/MeasureIgnoredFilter.h index d608cc61bd1d4c3d565521bdea3746a783d8c319..cd5bde932a63199c5b03b10581c144f927896406 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/MeasureIgnoredFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/MeasureIgnoredFilter.h @@ -3,11 +3,13 @@ #include "AbstractFilter.h" +template< typename U, typename V > class QPair; +class QString; namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; + class ControlPoint; /** * @brief Allows filtering by a control measure's ignored status @@ -18,18 +20,20 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal + * @internal * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class MeasureIgnoredFilter : public AbstractFilter { Q_OBJECT public: MeasureIgnoredFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); virtual ~MeasureIgnoredFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; diff --git a/isis/src/qisis/objs/CnetEditorWidget/MeasureJigsawRejectedFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/MeasureJigsawRejectedFilter.cpp index 034feb5ea9e2c16b9c958b049eef18fb811e9026..01a034cb661670ef83502430d9fcd7ae868ed12d 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/MeasureJigsawRejectedFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/MeasureJigsawRejectedFilter.cpp @@ -2,21 +2,20 @@ #include "MeasureJigsawRejectedFilter.h" -#include <iostream> +#include <QPair> +#include <QString> -#include <QHBoxLayout> - -#include "ControlCubeGraphNode.h" #include "ControlMeasure.h" - +#include "ControlNet.h" +#include "ControlPoint.h" using std::cerr; namespace Isis { MeasureJigsawRejectedFilter::MeasureJigsawRejectedFilter( - AbstractFilter::FilterEffectivenessFlag flag, int minimumForSuccess) : - AbstractFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, int minimumForSuccess) : + AbstractFilter(flag, minimumForSuccess) { } @@ -24,8 +23,9 @@ namespace Isis { } - bool MeasureJigsawRejectedFilter::evaluate(const ControlCubeGraphNode *node) const { - return AbstractFilter::evaluateImageFromMeasureFilter(node); + bool MeasureJigsawRejectedFilter::evaluate( + const QPair<QString, ControlNet *> *imageAndNet) const { + return AbstractFilter::evaluateImageFromMeasureFilter(imageAndNet); } @@ -46,15 +46,19 @@ namespace Isis { QString MeasureJigsawRejectedFilter::getImageDescription() const { QString description = AbstractFilter::getImageDescription(); - if (getMinForSuccess() == 1) + if (getMinForSuccess() == 1) { description += "measure that is "; - else + } + else { description += "measures that are "; + } - if (inclusive()) + if (inclusive()) { description += "jigsaw rejected"; - else + } + else { description += "not jigsaw rejected"; + } return description; } @@ -68,12 +72,13 @@ namespace Isis { QString MeasureJigsawRejectedFilter::getMeasureDescription() const { QString description = "are "; - if (inclusive()) + if (inclusive()) { description += "jigsaw rejected"; - else + } + else { description += "not jigsaw rejected"; + } return description; } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/MeasureJigsawRejectedFilter.h b/isis/src/qisis/objs/CnetEditorWidget/MeasureJigsawRejectedFilter.h index efa38b6207b7f4307ced02dfe1eaa44642be856f..4c59aeb70480cf24c16a7b6d337c81dd0578a6ec 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/MeasureJigsawRejectedFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/MeasureJigsawRejectedFilter.h @@ -3,11 +3,13 @@ #include "AbstractFilter.h" +template< typename U, typename V > class QPair; +class QString; namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; + class ControlPoint; /** * @brief Allows filtering by a control measure's jigsaw rejected status @@ -18,18 +20,20 @@ namespace Isis { * * @author 2012-04-18 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class MeasureJigsawRejectedFilter : public AbstractFilter { Q_OBJECT public: MeasureJigsawRejectedFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); virtual ~MeasureJigsawRejectedFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -42,4 +46,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/MeasureTypeFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/MeasureTypeFilter.cpp index bccb60a2dff806eeab632bb39b5e2ab22a638bde..4b2b9daaae5fc637c8b8fba5c637ecee7bc05605 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/MeasureTypeFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/MeasureTypeFilter.cpp @@ -2,18 +2,20 @@ #include "MeasureTypeFilter.h" +#include <QPair> #include <QString> #include <QStringList> -#include "ControlCubeGraphNode.h" #include "ControlMeasure.h" +#include "ControlNet.h" +#include "ControlPoint.h" #include "IString.h" namespace Isis { MeasureTypeFilter::MeasureTypeFilter( - AbstractFilter::FilterEffectivenessFlag flag, int minimumForSuccess) : - AbstractMultipleChoiceFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, int minimumForSuccess) : + AbstractMultipleChoiceFilter(flag, minimumForSuccess) { QStringList options; options << "Candidate" << "Manual" << "RegisteredPixel" << "RegisteredSubPixel"; @@ -22,7 +24,7 @@ namespace Isis { MeasureTypeFilter::MeasureTypeFilter(const MeasureTypeFilter &other) - : AbstractMultipleChoiceFilter(other) { + : AbstractMultipleChoiceFilter(other) { } @@ -30,8 +32,8 @@ namespace Isis { } - bool MeasureTypeFilter::evaluate(const ControlCubeGraphNode *node) const { - return evaluateImageFromMeasureFilter(node); + bool MeasureTypeFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromMeasureFilter(imageAndNet); } @@ -42,7 +44,7 @@ namespace Isis { bool MeasureTypeFilter::evaluate(const ControlMeasure *measure) const { return ((QString) measure->GetMeasureTypeString() == getCurrentChoice()) ^ - !inclusive(); + !inclusive(); } @@ -54,20 +56,25 @@ namespace Isis { QString MeasureTypeFilter::getImageDescription() const { QString description = AbstractFilter::getImageDescription() + "measure"; - if (getMinForSuccess() != 1) + if (getMinForSuccess() != 1) { description += "s "; - else + } + else { description += " "; + } description += "that "; - if (getMinForSuccess() == 1) + if (getMinForSuccess() == 1) { description += "is "; - else + } + else { description += "are "; + } - if (!inclusive()) + if (!inclusive()) { description += "not "; + } description += " of type " + getCurrentChoice(); @@ -78,8 +85,9 @@ namespace Isis { QString MeasureTypeFilter::getMeasureDescription() const { QString description = "are "; - if (!inclusive()) + if (!inclusive()) { description += "not "; + } description += "of type " + getCurrentChoice(); @@ -91,4 +99,3 @@ namespace Isis { return getImageDescription(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/MeasureTypeFilter.h b/isis/src/qisis/objs/CnetEditorWidget/MeasureTypeFilter.h index 06b767923a1bd70032c60b2dca1d86937bb51b6e..c387a9002696b741ef2a4419a6e49806fe4acbb8 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/MeasureTypeFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/MeasureTypeFilter.h @@ -3,14 +3,13 @@ #include "AbstractMultipleChoiceFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlPoint; class ControlMeasure; + class ControlNet; + class ControlPoint; /** * @brief Filters by measure type @@ -22,19 +21,21 @@ namespace Isis { * * @author 2012-01-05 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class MeasureTypeFilter : public AbstractMultipleChoiceFilter { Q_OBJECT public: MeasureTypeFilter(AbstractFilter::FilterEffectivenessFlag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); MeasureTypeFilter(const MeasureTypeFilter &other); virtual ~MeasureTypeFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -47,4 +48,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/PointEditLockedFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/PointEditLockedFilter.cpp index e0d683d3e1771aad6fe95760751a12a323298e2a..c351b97ff3380298ee09c9f35e7c4af03927402e 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/PointEditLockedFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/PointEditLockedFilter.cpp @@ -2,23 +2,23 @@ #include "PointEditLockedFilter.h" -#include <iostream> - -#include <QHBoxLayout> +#include <QPair> +#include <QString> #include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" namespace Isis { PointEditLockedFilter::PointEditLockedFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { } PointEditLockedFilter::PointEditLockedFilter(const AbstractFilter &other) - : AbstractFilter(other) { + : AbstractFilter(other) { } @@ -26,9 +26,8 @@ namespace Isis { } - bool PointEditLockedFilter::evaluate( - const ControlCubeGraphNode *node) const { - return AbstractFilter::evaluateImageFromPointFilter(node); + bool PointEditLockedFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return AbstractFilter::evaluateImageFromPointFilter(imageAndNet); } @@ -50,15 +49,19 @@ namespace Isis { QString PointEditLockedFilter::getImageDescription() const { QString description = AbstractFilter::getImageDescription(); - if (getMinForSuccess() == 1) + if (getMinForSuccess() == 1) { description += "point that is "; - else + } + else { description += "points that are "; + } - if (inclusive()) + if (inclusive()) { description += "edit locked"; - else + } + else { description += "not edit locked"; + } return description; } @@ -67,10 +70,12 @@ namespace Isis { QString PointEditLockedFilter::getPointDescription() const { QString description = "are "; - if (inclusive()) + if (inclusive()) { description += "edit locked"; - else + } + else { description += "not edit locked"; + } return description; } diff --git a/isis/src/qisis/objs/CnetEditorWidget/PointEditLockedFilter.h b/isis/src/qisis/objs/CnetEditorWidget/PointEditLockedFilter.h index f64dc441a9c33960e09bb726896299759dc57a02..831f53465ccef342efe070cf36f7a48ef24af21d 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/PointEditLockedFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/PointEditLockedFilter.h @@ -3,11 +3,13 @@ #include "AbstractFilter.h" +template< typename U, typename V > class QPair; +class QString; namespace Isis { - class ControlCubeGraphNode; - class ControlPoint; class ControlMeasure; + class ControlNet; + class ControlPoint; /** * @brief Allows filtering by a control point's edit lock status @@ -18,19 +20,21 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class PointEditLockedFilter : public AbstractFilter { Q_OBJECT public: PointEditLockedFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); PointEditLockedFilter(const AbstractFilter &other); virtual ~PointEditLockedFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; diff --git a/isis/src/qisis/objs/CnetEditorWidget/PointIdFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/PointIdFilter.cpp index 4d29826e14cf01084637b4d62afbb3cebc665fd5..43e6810f106f8cce19163ded09c19f83c6ef55a1 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/PointIdFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/PointIdFilter.cpp @@ -2,21 +2,23 @@ #include "PointIdFilter.h" +#include <QPair> #include <QString> -#include "ControlCubeGraphNode.h" +#include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" #include "IString.h" namespace Isis { - PointIdFilter::PointIdFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractStringFilter(flag, minimumForSuccess) { + PointIdFilter::PointIdFilter( + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractStringFilter(flag, minimumForSuccess) { } - PointIdFilter::PointIdFilter(const PointIdFilter &other) - : AbstractStringFilter(other) { + PointIdFilter::PointIdFilter(const PointIdFilter &other) : AbstractStringFilter(other) { } @@ -24,8 +26,8 @@ namespace Isis { } - bool PointIdFilter::evaluate(const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + bool PointIdFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } @@ -47,10 +49,12 @@ namespace Isis { QString PointIdFilter::getImageDescription() const { QString description = AbstractFilter::getImageDescription(); - if (getMinForSuccess() == 1) + if (getMinForSuccess() == 1) { description += "point with it's ID "; - else + } + else { description += "points with IDs "; + } description += descriptionSuffix(); return description; diff --git a/isis/src/qisis/objs/CnetEditorWidget/PointIdFilter.h b/isis/src/qisis/objs/CnetEditorWidget/PointIdFilter.h index 79336271a2baaf4c15644a2d12771228661df9f1..37a0f2f14459525628c5076e202fa7ea38a1f7f8 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/PointIdFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/PointIdFilter.h @@ -3,14 +3,13 @@ #include "AbstractStringFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlPoint; class ControlMeasure; + class ControlNet; + class ControlPoint; /** * @brief Filter by control point id string @@ -21,19 +20,21 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class PointIdFilter : public AbstractStringFilter { Q_OBJECT public: PointIdFilter(AbstractFilter::FilterEffectivenessFlag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); PointIdFilter(const PointIdFilter &other); virtual ~PointIdFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; diff --git a/isis/src/qisis/objs/CnetEditorWidget/PointIgnoredFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/PointIgnoredFilter.cpp index 56f27d64468eb7d869cb1c907d7ba71b2f22de0a..440fddb93b734444682333472ced150b27102e7d 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/PointIgnoredFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/PointIgnoredFilter.cpp @@ -2,23 +2,22 @@ #include "PointIgnoredFilter.h" -#include <iostream> +#include <QPair> +#include <QString> -#include <QHBoxLayout> - -#include "ControlCubeGraphNode.h" +#include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" namespace Isis { PointIgnoredFilter::PointIgnoredFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { } - PointIgnoredFilter::PointIgnoredFilter(const AbstractFilter &other) - : AbstractFilter(other) { + PointIgnoredFilter::PointIgnoredFilter(const AbstractFilter &other) : AbstractFilter(other) { } @@ -26,8 +25,8 @@ namespace Isis { } - bool PointIgnoredFilter::evaluate(const ControlCubeGraphNode *node) const { - return AbstractFilter::evaluateImageFromPointFilter(node); + bool PointIgnoredFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return AbstractFilter::evaluateImageFromPointFilter(imageAndNet); } @@ -49,15 +48,19 @@ namespace Isis { QString PointIgnoredFilter::getImageDescription() const { QString description = AbstractFilter::getImageDescription(); - if (getMinForSuccess() == 1) + if (getMinForSuccess() == 1) { description += "point that is "; - else + } + else { description += "points that are "; + } - if (inclusive()) + if (inclusive()) { description += "ignored"; - else + } + else { description += "not ignored"; + } return description; } @@ -66,10 +69,12 @@ namespace Isis { QString PointIgnoredFilter::getPointDescription() const { QString description = "are "; - if (inclusive()) + if (inclusive()) { description += "ignored"; - else + } + else { description += "not ignored"; + } return description; } diff --git a/isis/src/qisis/objs/CnetEditorWidget/PointIgnoredFilter.h b/isis/src/qisis/objs/CnetEditorWidget/PointIgnoredFilter.h index 7661e36377778546c5f346a9ca07556a4cb15da6..242b994d84bda4360116229e85d52beb33c9137c 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/PointIgnoredFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/PointIgnoredFilter.h @@ -3,11 +3,12 @@ #include "AbstractFilter.h" +template< typename U, typename V > class QPair; +class QString; namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -19,19 +20,21 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class PointIgnoredFilter : public AbstractFilter { Q_OBJECT public: PointIgnoredFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); PointIgnoredFilter(const AbstractFilter &other); virtual ~PointIgnoredFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; diff --git a/isis/src/qisis/objs/CnetEditorWidget/PointJigsawRejectedFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/PointJigsawRejectedFilter.cpp index f082306cc7581e562330be5af5ecbba4b88271ae..0d628de472bd23fc534e548e6b7a26fac78fa003 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/PointJigsawRejectedFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/PointJigsawRejectedFilter.cpp @@ -2,11 +2,11 @@ #include "PointJigsawRejectedFilter.h" -#include <iostream> - -#include <QHBoxLayout> +#include <QPair> +#include <QString> #include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" @@ -15,13 +15,13 @@ using std::cerr; namespace Isis { PointJigsawRejectedFilter::PointJigsawRejectedFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractFilter(flag, minimumForSuccess) { } - PointJigsawRejectedFilter::PointJigsawRejectedFilter( - const AbstractFilter &other) : AbstractFilter(other) { + PointJigsawRejectedFilter::PointJigsawRejectedFilter(const AbstractFilter &other) + : AbstractFilter(other) { } @@ -30,8 +30,8 @@ namespace Isis { bool PointJigsawRejectedFilter::evaluate( - const ControlCubeGraphNode *node) const { - return AbstractFilter::evaluateImageFromPointFilter(node); + const QPair<QString, ControlNet *> *imageAndNet) const { + return AbstractFilter::evaluateImageFromPointFilter(imageAndNet); } @@ -53,15 +53,19 @@ namespace Isis { QString PointJigsawRejectedFilter::getImageDescription() const { QString description = AbstractFilter::getImageDescription(); - if (getMinForSuccess() == 1) + if (getMinForSuccess() == 1) { description += "point that is "; - else + } + else { description += "points that are "; + } - if (inclusive()) + if (inclusive()) { description += "jigsaw rejected"; - else + } + else { description += "not jigsaw rejected"; + } return description; } @@ -70,12 +74,13 @@ namespace Isis { QString PointJigsawRejectedFilter::getPointDescription() const { QString description = "are "; - if (inclusive()) + if (inclusive()) { description += "jigsaw rejected"; - else + } + else { description += "not jigsaw rejected"; + } return description; } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/PointJigsawRejectedFilter.h b/isis/src/qisis/objs/CnetEditorWidget/PointJigsawRejectedFilter.h index ca83c7f7f23e8fbb616003521a083b32f2e7b2d3..fed5e8973d80b8d4d578bc731e63a65e28e894bc 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/PointJigsawRejectedFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/PointJigsawRejectedFilter.h @@ -3,11 +3,13 @@ #include "AbstractFilter.h" +template< typename U, typename V > class QPair; +class QString; namespace Isis { - class ControlCubeGraphNode; - class ControlPoint; class ControlMeasure; + class ControlNet; + class ControlPoint; /** * @brief Allows filtering by a control point's jigsaw rejected status @@ -18,19 +20,21 @@ namespace Isis { * * @author 2012-04-18 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class PointJigsawRejectedFilter : public AbstractFilter { Q_OBJECT public: PointJigsawRejectedFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); PointJigsawRejectedFilter(const AbstractFilter &other); virtual ~PointJigsawRejectedFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -42,4 +46,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/PointTypeFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/PointTypeFilter.cpp index d7370f0ec2828e4eb8620ab4cbf862ce25f79494..dddae5720179f83bde691b7327eac00a2eef828d 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/PointTypeFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/PointTypeFilter.cpp @@ -2,18 +2,20 @@ #include "PointTypeFilter.h" +#include <QPair> #include <QString> #include <QStringList> -#include "ControlCubeGraphNode.h" +#include "ControlMeasure.h" +#include "ControlNet.h" #include "ControlPoint.h" #include "IString.h" namespace Isis { - PointTypeFilter::PointTypeFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : - AbstractMultipleChoiceFilter(flag, minimumForSuccess) { + PointTypeFilter::PointTypeFilter( + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractMultipleChoiceFilter(flag, minimumForSuccess) { QStringList options; options << "Fixed" << "Constrained" << "Free"; createWidget(options); @@ -21,7 +23,7 @@ namespace Isis { PointTypeFilter::PointTypeFilter(const PointTypeFilter &other) - : AbstractMultipleChoiceFilter(other) { + : AbstractMultipleChoiceFilter(other) { } @@ -29,14 +31,14 @@ namespace Isis { } - bool PointTypeFilter::evaluate(const ControlCubeGraphNode *node) const { - return evaluateImageFromPointFilter(node); + bool PointTypeFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromPointFilter(imageAndNet); } bool PointTypeFilter::evaluate(const ControlPoint *point) const { return ((QString) point->GetPointTypeString() == getCurrentChoice()) ^ - !inclusive(); + !inclusive(); } @@ -53,20 +55,25 @@ namespace Isis { QString PointTypeFilter::getImageDescription() const { QString description = AbstractFilter::getImageDescription() + "point"; - if (getMinForSuccess() != 1) + if (getMinForSuccess() != 1) { description += "s "; - else + } + else { description += " "; + } description += "that "; - if (getMinForSuccess() == 1) + if (getMinForSuccess() == 1) { description += "is "; - else + } + else { description += "are "; + } - if (!inclusive()) + if (!inclusive()) { description += "not "; + } description += " of type " + getCurrentChoice(); @@ -77,8 +84,9 @@ namespace Isis { QString PointTypeFilter::getPointDescription() const { QString description = "are "; - if (!inclusive()) + if (!inclusive()) { description += "not "; + } description += "of type " + getCurrentChoice(); diff --git a/isis/src/qisis/objs/CnetEditorWidget/PointTypeFilter.h b/isis/src/qisis/objs/CnetEditorWidget/PointTypeFilter.h index 47a260bfb6afb0a94954140dd0049312aaca16af..3abf14e15c85bd1060229f8e505ebc184314d2e8 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/PointTypeFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/PointTypeFilter.h @@ -3,14 +3,13 @@ #include "AbstractMultipleChoiceFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlPoint; class ControlMeasure; + class ControlNet; + class ControlPoint; /** * @brief Filters by point type @@ -20,19 +19,21 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal + * @internal * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class PointTypeFilter : public AbstractMultipleChoiceFilter { Q_OBJECT public: PointTypeFilter(AbstractFilter::FilterEffectivenessFlag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); PointTypeFilter(const PointTypeFilter &other); virtual ~PointTypeFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; diff --git a/isis/src/qisis/objs/CnetEditorWidget/ResidualMagnitudeFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/ResidualMagnitudeFilter.cpp index bc7ea32f0405583538847f7a0eef3d7bb8a36f89..ac650360d5662bb5e8b848ee340b4051e72eba30 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ResidualMagnitudeFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/ResidualMagnitudeFilter.cpp @@ -2,19 +2,23 @@ #include "ResidualMagnitudeFilter.h" -#include "ControlCubeGraphNode.h" +#include <QPair> +#include <QString> + #include "ControlMeasure.h" +#include "ControlNet.h" +#include "ControlPoint.h" namespace Isis { ResidualMagnitudeFilter::ResidualMagnitudeFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } - ResidualMagnitudeFilter::ResidualMagnitudeFilter( - const ResidualMagnitudeFilter &other) : AbstractNumberFilter(other) { + ResidualMagnitudeFilter::ResidualMagnitudeFilter(const ResidualMagnitudeFilter &other) + : AbstractNumberFilter(other) { } @@ -23,8 +27,8 @@ namespace Isis { bool ResidualMagnitudeFilter::evaluate( - const ControlCubeGraphNode *node) const { - return evaluateImageFromMeasureFilter(node); + const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromMeasureFilter(imageAndNet); } @@ -45,10 +49,12 @@ namespace Isis { QString ResidualMagnitudeFilter::getImageDescription() const { QString description = AbstractFilter::getImageDescription(); - if (getMinForSuccess() == 1) + if (getMinForSuccess() == 1) { description += "measure that has a residual magnitude which is "; - else + } + else { description += "measures that have residual magnitudes which are "; + } description += descriptionSuffix(); return description; diff --git a/isis/src/qisis/objs/CnetEditorWidget/ResidualMagnitudeFilter.h b/isis/src/qisis/objs/CnetEditorWidget/ResidualMagnitudeFilter.h index f1625ef31e970814bb7819b84798f8d10ba29253..90a77ca88dcb8b41d03155715f2fcea0d556e322 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/ResidualMagnitudeFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/ResidualMagnitudeFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -20,19 +18,21 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class ResidualMagnitudeFilter : public AbstractNumberFilter { Q_OBJECT public: ResidualMagnitudeFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); ResidualMagnitudeFilter(const ResidualMagnitudeFilter &other); virtual ~ResidualMagnitudeFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; diff --git a/isis/src/qisis/objs/CnetEditorWidget/SampleFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/SampleFilter.cpp index 46862a4319212d3a7736470ee8aa4b4b9248ff9c..69cb67e8c31356478bb44f4a77ddac2f9f30b810 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/SampleFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/SampleFilter.cpp @@ -2,20 +2,22 @@ #include "SampleFilter.h" -#include "ControlCubeGraphNode.h" +#include <QPair> +#include <QString> + #include "ControlMeasure.h" +#include "ControlNet.h" +#include "ControlPoint.h" namespace Isis { SampleFilter::SampleFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : - AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } - SampleFilter::SampleFilter( - const SampleFilter &other) : AbstractNumberFilter(other) { + SampleFilter::SampleFilter(const SampleFilter &other) : AbstractNumberFilter(other) { } @@ -23,8 +25,8 @@ namespace Isis { } - bool SampleFilter::evaluate(const ControlCubeGraphNode *node) const { - return evaluateImageFromMeasureFilter(node); + bool SampleFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromMeasureFilter(imageAndNet); } @@ -45,10 +47,12 @@ namespace Isis { QString SampleFilter::getImageDescription() const { QString description = AbstractFilter::getImageDescription(); - if (getMinForSuccess() == 1) + if (getMinForSuccess() == 1) { description += "measure that has a sample which is "; - else + } + else { description += "measures that have samples which are "; + } description += descriptionSuffix(); return description; @@ -64,4 +68,3 @@ namespace Isis { return "have samples which are " + descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/SampleFilter.h b/isis/src/qisis/objs/CnetEditorWidget/SampleFilter.h index 0ed226602b6773a50ad5fa2e7ef41ebd6b9c30d9..7ec333567ad242184ead522c857612dcb775af6e 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/SampleFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/SampleFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -23,19 +21,21 @@ namespace Isis { * * @author 2012-01-05 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class SampleFilter : public AbstractNumberFilter { Q_OBJECT public: SampleFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); SampleFilter(const SampleFilter &other); virtual ~SampleFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -48,4 +48,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/CnetEditorWidget/SampleResidualFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/SampleResidualFilter.cpp index 3015b8a0ec91d25468f4be1f5367e8500a03cfd1..ddffe0302af70df08ab579a6adbf02b897230eac 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/SampleResidualFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/SampleResidualFilter.cpp @@ -2,20 +2,23 @@ #include "SampleResidualFilter.h" -#include "ControlCubeGraphNode.h" +#include <QPair> +#include <QString> + #include "ControlMeasure.h" +#include "ControlNet.h" +#include "ControlPoint.h" namespace Isis { SampleResidualFilter::SampleResidualFilter( - AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : - AbstractNumberFilter(flag, minimumForSuccess) { + AbstractFilter::FilterEffectivenessFlag flag, + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } - SampleResidualFilter::SampleResidualFilter( - const SampleResidualFilter &other) : AbstractNumberFilter(other) { + SampleResidualFilter::SampleResidualFilter(const SampleResidualFilter &other) + : AbstractNumberFilter(other) { } @@ -23,8 +26,8 @@ namespace Isis { } - bool SampleResidualFilter::evaluate(const ControlCubeGraphNode *node) const { - return evaluateImageFromMeasureFilter(node); + bool SampleResidualFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromMeasureFilter(imageAndNet); } @@ -45,10 +48,12 @@ namespace Isis { QString SampleResidualFilter::getImageDescription() const { QString description = AbstractFilter::getImageDescription(); - if (getMinForSuccess() == 1) + if (getMinForSuccess() == 1) { description += "measure that has a sample residual which is "; - else + } + else { description += "measures that have sample residuals which are "; + } description += descriptionSuffix(); return description; diff --git a/isis/src/qisis/objs/CnetEditorWidget/SampleResidualFilter.h b/isis/src/qisis/objs/CnetEditorWidget/SampleResidualFilter.h index c5944c48a3246604bdeb14a47f199ae208fedfdb..4d8bb7547005a013cab61288ea6436c998387dc1 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/SampleResidualFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/SampleResidualFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -22,19 +20,21 @@ namespace Isis { * * @author ????-??-?? Eric Hyer * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class SampleResidualFilter : public AbstractNumberFilter { Q_OBJECT public: SampleResidualFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); SampleResidualFilter(const SampleResidualFilter &other); virtual ~SampleResidualFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; diff --git a/isis/src/qisis/objs/CnetEditorWidget/SampleShiftFilter.cpp b/isis/src/qisis/objs/CnetEditorWidget/SampleShiftFilter.cpp index 5166d30272c81ce304f32214d4f48e85b7efd0d3..985303632d14c5f93d5ad4d0cd1f7cce8c21c4c7 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/SampleShiftFilter.cpp +++ b/isis/src/qisis/objs/CnetEditorWidget/SampleShiftFilter.cpp @@ -2,20 +2,23 @@ #include "SampleShiftFilter.h" -#include "ControlCubeGraphNode.h" +#include <QPair> +#include <QString> + #include "ControlMeasure.h" +#include "ControlNet.h" +#include "ControlPoint.h" namespace Isis { SampleShiftFilter::SampleShiftFilter( AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess) : - AbstractNumberFilter(flag, minimumForSuccess) { + int minimumForSuccess) : AbstractNumberFilter(flag, minimumForSuccess) { } - SampleShiftFilter::SampleShiftFilter( - const SampleShiftFilter &other) : AbstractNumberFilter(other) { + SampleShiftFilter::SampleShiftFilter(const SampleShiftFilter &other) + : AbstractNumberFilter(other) { } @@ -23,8 +26,8 @@ namespace Isis { } - bool SampleShiftFilter::evaluate(const ControlCubeGraphNode *node) const { - return evaluateImageFromMeasureFilter(node); + bool SampleShiftFilter::evaluate(const QPair<QString, ControlNet *> *imageAndNet) const { + return evaluateImageFromMeasureFilter(imageAndNet); } @@ -45,10 +48,12 @@ namespace Isis { QString SampleShiftFilter::getImageDescription() const { QString description = AbstractFilter::getImageDescription(); - if (getMinForSuccess() == 1) + if (getMinForSuccess() == 1) { description += "measure that has a sample shift which is "; - else + } + else { description += "measures that have sample shifts which are "; + } description += descriptionSuffix(); return description; @@ -64,4 +69,3 @@ namespace Isis { return "have sample shifts which are " + descriptionSuffix(); } } - diff --git a/isis/src/qisis/objs/CnetEditorWidget/SampleShiftFilter.h b/isis/src/qisis/objs/CnetEditorWidget/SampleShiftFilter.h index 48d8e3bdce9152bce164969f420794148b1d46fe..2cba630ff4f3ffbbee002f86a78e16aadc07210d 100644 --- a/isis/src/qisis/objs/CnetEditorWidget/SampleShiftFilter.h +++ b/isis/src/qisis/objs/CnetEditorWidget/SampleShiftFilter.h @@ -3,14 +3,12 @@ #include "AbstractNumberFilter.h" - +template< typename U, typename V > class QPair; class QString; - namespace Isis { - class AbstractFilterSelector; - class ControlCubeGraphNode; class ControlMeasure; + class ControlNet; class ControlPoint; /** @@ -24,19 +22,21 @@ namespace Isis { * * @author 2012-04-18 Jai Rideout * - * @internal - * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @internal + * @history 2017-07-25 Summer Stapleton - Removed the CnetViz namespace. Fixes #5054. + * @history 2018-06-01 Jesse Mapel - Changed ControlCubeGraphNode to image serial number. + * References #5434. */ class SampleShiftFilter : public AbstractNumberFilter { Q_OBJECT public: SampleShiftFilter(AbstractFilter::FilterEffectivenessFlag flag, - int minimumForSuccess = -1); + int minimumForSuccess = -1); SampleShiftFilter(const SampleShiftFilter &other); virtual ~SampleShiftFilter(); - bool evaluate(const ControlCubeGraphNode *) const; + bool evaluate(const QPair<QString, ControlNet *> *) const; bool evaluate(const ControlPoint *) const; bool evaluate(const ControlMeasure *) const; @@ -49,4 +49,3 @@ namespace Isis { } #endif - diff --git a/isis/src/qisis/objs/ControlHealthMonitorView/ControlHealthMonitorView.cpp b/isis/src/qisis/objs/ControlHealthMonitorView/ControlHealthMonitorView.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4ef1e044a7ec24c62d096256b3c9a20904f79a2 --- /dev/null +++ b/isis/src/qisis/objs/ControlHealthMonitorView/ControlHealthMonitorView.cpp @@ -0,0 +1,211 @@ +/** + * @file + * $Date$ + * $Revision$ + * + * Unless noted otherwise, the portions of Isis written by the USGS are + * public domain. See individual third-party library and package descriptions + * for intellectual property information, user agreements, and related + * information. + * + * Although Isis has been used by the USGS, no warranty, expressed or + * implied, is made by the USGS as to the accuracy and functioning of such + * software and related material nor shall the fact of distribution + * constitute any such warranty, and no responsibility is assumed by the + * USGS in connection therewith. + * + * For additional information, launch + * $ISISROOT/doc//documents/Disclaimers/Disclaimers.html + * in a browser or see the Privacy & Disclaimers page on the Isis website, + * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on + * http://www.usgs.gov/privacy.html. + */ +#include "IsisDebug.h" + +#include "ControlHealthMonitorView.h" + +#include <QAction> +#include <QList> +#include <QSize> +#include <QSizePolicy> +#include <QToolBar> +#include <QVBoxLayout> +#include <QWidgetAction> + +#include "ControlHealthMonitorWidget.h" +#include "ControlPointEditView.h" +#include "ControlPointEditWidget.h" +#include "CnetEditorView.h" +#include "CubeDnView.h" + +#include "ControlNet.h" +#include "ControlPoint.h" +#include "Directory.h" +#include "ProjectItem.h" +#include "ProjectItemModel.h" + +#include "ToolPad.h" + + +namespace Isis { + + /** + * Constructor. + */ + ControlHealthMonitorView::ControlHealthMonitorView(Directory *directory, QWidget *parent) : + AbstractProjectItemView(parent) { + m_directory = directory; + ControlNet *net = m_directory->project()->activeControl()->controlNet(); + + ControlNetVitals *vitals = new ControlNetVitals(net); + m_controlHealthMonitorWidget = new ControlHealthMonitorWidget(vitals, parent); + + connect(m_controlHealthMonitorWidget, SIGNAL(openPointEditor(ControlPoint *)), + this, SLOT(openPointEditor(ControlPoint *))); + + connect(m_controlHealthMonitorWidget, SIGNAL(openImageEditor(QList<QString>)), + this, SLOT(openImageEditor(QList<QString>))); + + setCentralWidget(m_controlHealthMonitorWidget); + + m_permToolBar = new QToolBar("Standard Tools", 0); + m_permToolBar->setObjectName("permToolBar"); + m_permToolBar->setIconSize(QSize(22, 22)); + + m_activeToolBar = new QToolBar("Active Tool", 0); + m_activeToolBar->setObjectName("activeToolBar"); + m_activeToolBar->setIconSize(QSize(22, 22)); + + m_toolPad = new ToolPad("Tool Pad", 0); + m_toolPad->setObjectName("toolPad"); + + +// m_ControlHealthMonitorWidget->addToPermanent(m_permToolBar); +// m_ControlHealthMonitorWidget->addTo(m_activeToolBar); +// m_ControlHealthMonitorWidget->addTo(m_toolPad); + + m_activeToolBarAction = new QWidgetAction(this); + m_activeToolBarAction->setDefaultWidget(m_activeToolBar); + + setAcceptDrops(true); + + QSizePolicy policy = sizePolicy(); + policy.setHorizontalPolicy(QSizePolicy::Expanding); + policy.setVerticalPolicy(QSizePolicy::Expanding); + setSizePolicy(policy); + + } + + /** + * This SLOT is designed to intercept the openPointEditor() signal that's emitted + * Whenever a point is double clicked on inside of the ControlHealthMonitorWidget. + * + * It is designed to open the ControlPointEditWidget and edit the point that was + * selected in the health monitor. + * + * @param point The Control Point to be editted. + */ + void ControlHealthMonitorView::openPointEditor(ControlPoint *point) { + ControlPointEditWidget* widget = m_directory->addControlPointEditView()->controlPointEditWidget(); + + if (point && point != widget->editPoint()) { + widget->setEditPoint(point); + } + + // m_directory->addCnetEditorView(m_directory->project()->activeControl()); + } + + + /** + * This SLOT is designed to intercept the openImageEditor() signal that's emitted + * Whenever an image is double clicked on inside of the ControlHealthMonitorWidget. + * + * It is designed to open the CubeDnView and populate it with the selected cubes. + */ + void ControlHealthMonitorView::openImageEditor(QList<QString> serials) { + CubeDnView *cubeView = m_directory->addCubeDnView(); + foreach (QString serial, serials) { + QList<ImageList*> imageLists = m_directory->project()->images(); + foreach(ImageList *list, imageLists) { + foreach(Image *image, *list) { + QString imageSerial = image->serialNumber(); + if (imageSerial == serial) { + ProjectItem *item = m_directory->model()->findItemData(QVariant::fromValue(image)); + if (item) { + cubeView->addItem(item); + } + } + } + } + } + } + + + /** + * Destructor + */ + ControlHealthMonitorView::~ControlHealthMonitorView() { + delete m_controlHealthMonitorWidget; + delete m_permToolBar; + delete m_activeToolBar; + delete m_toolPad; + + m_permToolBar = 0; + m_activeToolBar = 0; + m_toolPad = 0; + } + + + /** + * Returns the ControlHealthMonitorWidget. + * + * @return (ControlHealthMonitorWidget *) The currently active ControlHealthMonitorWidget. + */ + ControlHealthMonitorWidget *ControlHealthMonitorView::controlHealthMonitorWidget() { + return m_controlHealthMonitorWidget; + } + + + /** + * Returns the suggested size for the widget. + * + * @return (QSize) The size + */ + QSize ControlHealthMonitorView::sizeHint() const { + return QSize(800, 600); + } + + + /** + * Returns a list of actions for the permanent tool bar. + * + * @return (QList<QAction *>) The actions + */ + QList<QAction *> ControlHealthMonitorView::permToolBarActions() { + return m_permToolBar->actions(); + } + + + /** + * Returns a list of actions for the active tool bar. + * + * @return (QList<QAction *>) The actions + */ + QList<QAction *> ControlHealthMonitorView::activeToolBarActions() { + QList<QAction *> actions; + actions.append(m_activeToolBarAction); + return actions; + } + + + /** + * Returns a list of actions for the tool pad. + * + * @return (QList<QAction *>) The actions + */ + QList<QAction *> ControlHealthMonitorView::toolPadActions() { + return m_toolPad->actions(); + } + + +} diff --git a/isis/src/qisis/objs/ControlHealthMonitorView/ControlHealthMonitorView.h b/isis/src/qisis/objs/ControlHealthMonitorView/ControlHealthMonitorView.h new file mode 100644 index 0000000000000000000000000000000000000000..bd8534a241a53416cf90cb0265305b78a7137c50 --- /dev/null +++ b/isis/src/qisis/objs/ControlHealthMonitorView/ControlHealthMonitorView.h @@ -0,0 +1,86 @@ +#ifndef ControlHealthMonitorView_h +#define ControlHealthMonitorView_h +/** + * @file + * $Date$ + * $Revision$ + * + * Unless noted otherwise, the portions of Isis written by the USGS are + * public domain. See individual third-party library and package descriptions + * for intellectual property information, user agreements, and related + * information. + * + * Although Isis has been used by the USGS, no warranty, expressed or + * implied, is made by the USGS as to the accuracy and functioning of such + * software and related material nor shall the fact of distribution + * constitute any such warranty, and no responsibility is assumed by the + * USGS in connection therewith. + * + * For additional information, launch + * $ISISROOT/doc//documents/Disclaimers/Disclaimers.html + * in a browser or see the Privacy & Disclaimers page on the Isis website, + * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on + * http://www.usgs.gov/privacy.html. + */ +#include <QMap> +#include <QPointer> +#include <QToolBar> +#include <QWidgetAction> + +#include "AbstractProjectItemView.h" + +namespace Isis { + class Control; + class Directory; + class ProjectItem; + class ControlHealthMonitorWidget; + class ControlNet; + class ControlPoint; + class ToolPad; + + /** + * View for the Control Net Health Monitor + * + * @author 2018-06-07 Adam Goins + * + * @internal + * @history 2018-06-07 Adam Goins - Initial Version. + * @history 2018-06-26 Adam Goins - Made the view dockable with setCentralWidget(). + */ + +class ControlHealthMonitorView : public AbstractProjectItemView { + + Q_OBJECT + + public: + ControlHealthMonitorView(Directory *directory, QWidget *parent = 0); + ~ControlHealthMonitorView(); + + virtual QList<QAction *> permToolBarActions(); + virtual QList<QAction *> activeToolBarActions(); + virtual QList<QAction *> toolPadActions(); + + ControlHealthMonitorWidget *controlHealthMonitorWidget(); + + QSize sizeHint() const; + + public slots: + + private slots: + void openPointEditor(ControlPoint *point); + void openImageEditor(QList<QString> serials); + + private: + Directory *m_directory; + + QPointer<ControlHealthMonitorWidget> m_controlHealthMonitorWidget; + + ToolPad *m_toolPad; //!< The tool pad + QToolBar *m_permToolBar; //!< The permanent tool bar + QToolBar *m_activeToolBar; //!< The active tool bar + + QWidgetAction *m_activeToolBarAction; //!< Stores the active tool bar + }; +} + +#endif // ControlHealthMonitorVIEW_H diff --git a/isis/src/qisis/objs/JigsawDialog/Makefile b/isis/src/qisis/objs/ControlHealthMonitorView/Makefile similarity index 100% rename from isis/src/qisis/objs/JigsawDialog/Makefile rename to isis/src/qisis/objs/ControlHealthMonitorView/Makefile diff --git a/isis/src/qisis/objs/ControlHealthMonitorWidget/ControlHealthMonitorWidget.cpp b/isis/src/qisis/objs/ControlHealthMonitorWidget/ControlHealthMonitorWidget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4bed4c132bb99bb1968b8d1151560b202c3baa1b --- /dev/null +++ b/isis/src/qisis/objs/ControlHealthMonitorWidget/ControlHealthMonitorWidget.cpp @@ -0,0 +1,903 @@ +/** + * @file + * $Date$ + * $Revision$ + * + * Unless noted otherwise, the portions of Isis written by the USGS are + * public domain. See individual third-party library and package descriptions + * for intellectual property information, user agreements, and related + * information. + * + * Although Isis has been used by the USGS, no warranty, expressed or + * implied, is made by the USGS as to the accuracy and functioning of such + * software and related material nor shall the fact of distribution + * constitute any such warranty, and no responsibility is assumed by the + * USGS in connection therewith. + * + * For additional information, launch + * $ISISROOT/doc//documents/Disclaimers/Disclaimers.html + * in a browser or see the Privacy & Disclaimers page on the Isis website, + * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on + * http://www.usgs.gov/privacy.html. + */ +#include "ControlHealthMonitorWidget.h" + + +#include "ControlNet.h" +#include "IString.h" +#include "Progress.h" +#include <QCheckBox> +#include <QToolBar> +#include <iostream> + +#include <QApplication> +#include <QtCore> +#include <QLabel> +#include <QtGui> +#include <QPushButton> +#include <QProgressBar> +#include <QTabWidget> +#include <QPointer> +#include <QTableWidgetItem> +#include <QIcon> +#include <QLineEdit> +#include <QHeaderView> +#include <QDesktopWidget> +#include <QGridLayout> +#include <QWidgetAction> +#include <QMenu> +#include <ControlNet.h> +#include <ControlNetVitals.h> +#include <ControlPoint.h> + + +namespace Isis { + + /** + * This class is the front end representation of a ControlNetVitals object. + * It will accept a ControlNetVitals object upon initialization and reflects the current + * real-time status of the embedded ControlNet in the ControlNetVitals object. + * + * @param vitals (ControlNetVitals *) The ControlNetVitals object that contains the ControlNet. + * @param parent (QWidget *) Pointer to parent widget + */ + ControlHealthMonitorWidget::ControlHealthMonitorWidget(ControlNetVitals *vitals, QWidget *parent) : QWidget(parent) { + createGui(); + m_vitals = vitals; + + connect (m_vitals, SIGNAL(networkChanged()), + this, SLOT(update())); + + connect (m_vitals, SIGNAL(historyEntry(QString, QString, QVariant, QVariant, QString)), + this, SLOT (historyEntry(QString, QString, QVariant, QVariant, QString))); + update(); + } + + + /** + * This SLOT is called whenever the is a change made to the network embedded in the + * Global m_vitals object. Changes are detected via the networkChanged() signal which + * is emitted from the ControlNetVitals object which is triggered whenever + * networkStructureModified() is emitted from the embedded ControlNet. + * + */ + void ControlHealthMonitorWidget::update() { + m_numImagesLabel->setText("Images: " + toString(m_vitals->numImages())); + m_numPointsLabel->setText("Points " + toString(m_vitals->numPoints())); + m_numMeasuresLabel->setText("Measures: " + toString(m_vitals->numMeasures())); + m_netLabel->setText("Control Network: " + m_vitals->getNetworkId()); + m_statusLabel->setText(m_vitals->getStatus()); + m_statusDetails->setText(m_vitals->getStatusDetails()); + m_imagesMeasuresValue->setText(toString(m_vitals->numImagesBelowMeasureThreshold())); + m_imagesHullValue->setText(toString(m_vitals->numImagesBelowHullTolerance())); + m_pointsIgnoredLabel->setText(toString(m_vitals->numIgnoredPoints())); + m_pointsFreeLabel->setText(toString(m_vitals->numFreePoints())); + m_pointsFixedLabel->setText(toString(m_vitals->numFixedPoints())); + m_pointsConstrainedLabel->setText(toString(m_vitals->numConstrainedPoints())); + m_pointsEditLockedLabel->setText(toString(m_vitals->numLockedPoints())); + m_pointsFewMeasuresLabel->setText(toString(m_vitals->numPointsBelowMeasureThreshold())); + + double freePercent = ( (double) m_vitals->numFreePoints() ) / ( (double) m_vitals->numPoints() ) * 100; + freePercent = ( (int) (freePercent * 100) ) / 100.0; + QString freeFormat = toString(m_vitals->numFreePoints()) + " (" + toString(freePercent) + ")%"; + m_pointsFreeProgressbar->setValue(freePercent); + m_pointsFreeProgressbar->setFormat(freeFormat); + + double constrainedPercent = ( (double) m_vitals->numConstrainedPoints() ) / + ( (double) m_vitals->numPoints() ) * 100; + constrainedPercent = ( (int) (constrainedPercent * 100) ) / 100.0; + QString constrainedFormat = toString(m_vitals->numConstrainedPoints()) + " (" + toString(constrainedPercent) + ")%"; + m_pointsConstrainedProgressbar->setValue(constrainedPercent); + m_pointsConstrainedProgressbar->setFormat(constrainedFormat); + + double fixedPercent = ( (double) m_vitals->numFixedPoints() ) / ( (double) m_vitals->numPoints() ) * 100; + fixedPercent = ( (int) (fixedPercent * 100) ) / 100.0; + QString fixedFormat = toString(m_vitals->numFixedPoints()) + " (" + toString(fixedPercent) + ")%"; + m_pointsFixedProgressbar->setValue(fixedPercent); + m_pointsFixedProgressbar->setFormat(fixedFormat); + + + // We should enumerate the network state and do a comparison on enums here, not strings. + if (m_vitals->getStatus() == "Broken!") updateStatus(0); + else if (m_vitals->getStatus() == "Weak!") updateStatus(1); + else if (m_vitals->getStatus() == "Healthy!") updateStatus(2); + + // QPieSeries series; + // series.append("Free", m_vitals->numFreePoints()); + // series.append("Constrained", m_vitals->numConstrainedPoints()); + // series.append("Fixed", m_vitals->numFixedPoints()); + // + // foreach (QPieSlice *slice, series->slices()) { + // + // // Get the percent and round it to two decimal places. + // double percent = slice->percentage() * 100; + // percent = ( (int) (percent * 100) ) / 100.0; + // + // QString label = slice->label() + " " + toString(percent) + "%"; + // + // if (percent > 0.0) { + // slice->setLabelVisible(); + // } + // slice->setLabel(label); + // } + // // + // m_pointChartView->chart()->removeAllSeries(); + // m_pointChartView->chart()->addSeries(series); + + viewImageAll(); + viewPointAll(); + } + + + /* + * This SLOT is designed to update the values in the gui to properly represent + * The current state of the Control Network. This SLOT is triggered whenever the + * projectStructureModified() signal is emitted from the Control Network, which triggers + * the "Update()" signal in the ControlNetVitals class in which this slot is connected. + * + * The status bar will display the proper color with respect to the health of the network, + * And will display details related to that health as well. + * + * @param code The status code. Should be an ENUM eventually for the 3 network states. + */ + void ControlHealthMonitorWidget::updateStatus(int code) { + QPalette p = m_statusBar->palette(); + switch(code) { + case 0: + p.setColor(QPalette::Highlight, Qt::red); + p.setColor(QPalette::Text, Qt::black); + break; + case 1: + p.setColor(QPalette::Highlight, Qt::yellow); + p.setColor(QPalette::Text, Qt::black); + break; + case 2: + p.setColor(QPalette::Highlight, Qt::green); + p.setColor(QPalette::Text, Qt::white); + break; + } + m_statusBar->setPalette(p); + } + + + /** + * This method is responsible for creating all of the components that comprise the GUI. + */ + void ControlHealthMonitorWidget::createGui() { + + initializeEverything(); + setWindowTitle("Control Net Health Monitor"); + resize(725, 1100); + + QFont fontBig("Arial", 18, QFont::Bold); + QFont fontNormal("Arial", 14); + QFont searchFont("Seqoe UI Symbol", 12); + + // Parent layout for this entire widget. + QVBoxLayout *gridLayout = new QVBoxLayout; + gridLayout->setAlignment(Qt::AlignTop); + gridLayout->setSpacing(5); + setLayout(gridLayout); + + // Title and net + QLabel *titleLabel = new QLabel("Control Net Health Monitor"); + titleLabel->setFont(fontBig); + titleLabel->setAlignment(Qt::AlignTop); + + QWidget *netWidget = new QWidget; + QHBoxLayout *netLayout = new QHBoxLayout; + netLayout->setAlignment(Qt::AlignLeft); + + m_netLabel = new QLabel("Control Network:"); + m_netLabel->setFont(fontNormal); + m_netLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft); + gridLayout->addWidget(titleLabel); + + netLayout->addWidget(m_netLabel); + netWidget->setLayout(netLayout); + + gridLayout->addWidget(netWidget); + + // 4 net details, size, images, points, measures. + QWidget *stats = new QWidget; + QHBoxLayout *netStatsLayout = new QHBoxLayout; + netStatsLayout->setAlignment(Qt::AlignLeft); + netStatsLayout->setSpacing(25); + m_numImagesLabel = new QLabel("Images:"); + m_numPointsLabel = new QLabel("Points:"); + m_numMeasuresLabel = new QLabel("Measures:"); + + netStatsLayout->addWidget(m_numImagesLabel); + netStatsLayout->addWidget(m_numPointsLabel); + netStatsLayout->addWidget(m_numMeasuresLabel); + + stats->setLayout(netStatsLayout); + gridLayout->addWidget(stats); + + // Status Bar + m_statusBar = new QProgressBar(); + QPalette p = m_statusBar->palette(); + p.setColor(QPalette::Highlight, Qt::green); + p.setColor(QPalette::Text, Qt::red); + m_statusBar->setPalette(p); + m_statusBar->setRange(0, 0); + + m_statusBar->setFormat("Loading..."); + gridLayout->addWidget(m_statusBar); + + m_lastModLabel = new QLabel("Last Modification:"); + gridLayout->addWidget(m_lastModLabel); + + QFrame* line = new QFrame(); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + gridLayout->addSpacing(15); + + gridLayout->addWidget(line); + gridLayout->addSpacing(15); + + // Tabs + QTabWidget *tabs = new QTabWidget(); + + QWidget *overviewTab = createOverviewTab(); + QWidget *imagesTab = createImagesTab(); + QWidget *pointsTab = createPointsTab(); + // QWidget *graphTab = createGraphTab(); + + tabs->insertTab(0, overviewTab, "Overview"); + tabs->insertTab(1, imagesTab, "Images"); + tabs->insertTab(2, pointsTab, "Points"); + // tabs->insertTab(3, graphTab, "Graph"); + + gridLayout->addWidget(tabs); + } + + + /** + * Initializes all member variables to NULL. + * + */ + void ControlHealthMonitorWidget::initializeEverything() { + m_historyTable = NULL; + m_imagesHullValue = NULL; + m_imagesMeasuresValue = NULL; + m_imagesShowingLabel = NULL; + m_imagesTable = NULL; + m_lastModLabel = NULL; + m_numImagesLabel = NULL; + m_numMeasuresLabel = NULL; + m_numPointsLabel = NULL; + // m_pointChartView = NULL; + m_pointsEditLockedLabel = NULL; + m_pointsFewMeasuresLabel = NULL; + m_pointsIgnoredLabel = NULL; + m_pointsShowingLabel = NULL; + m_pointsTable = NULL; + m_statusBar = NULL; + m_statusDetails = NULL; + m_statusLabel = NULL; + m_vitals = NULL; + } + + + /* + * This method creates the Overview tab. + * + */ + QWidget* ControlHealthMonitorWidget::createOverviewTab() { + + // Parent container for the overview tab. + QWidget *overview = new QWidget(); + QVBoxLayout *overviewLayout = new QVBoxLayout; + overviewLayout->setAlignment(Qt::AlignTop); + overviewLayout->setSpacing(5); + + QFont fontBig("Arial", 16, QFont::Bold); + QFont fontNormal("Arial", 14); + QFont fontSmall("Arial", 12); + + m_statusLabel = new QLabel("Healthy!"); + m_statusLabel->setFont(fontBig); + m_statusLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft); + + m_statusDetails = new QLabel("Your network is healthy."); + m_statusDetails->setFont(fontNormal); + m_statusDetails->setAlignment(Qt::AlignTop | Qt::AlignLeft); + + m_statusDetails->setFont(fontNormal); + m_statusDetails->setAlignment(Qt::AlignTop | Qt::AlignLeft); + + overviewLayout->addWidget(m_statusLabel); + overviewLayout->addWidget(m_statusDetails); + overviewLayout->addSpacing(50); + + QLabel *modLabel = new QLabel("Modification History"); + modLabel->setFont(fontSmall); + overviewLayout->addWidget(modLabel); + + QStringList headers; + headers.append("Action"); + headers.append("Id"); + headers.append("Old Value"); + headers.append("New Value"); + headers.append("Timestamp"); + + m_historyTable = new QTableWidget(); + m_historyTable->setColumnCount(5); + m_historyTable->setHorizontalHeaderLabels(headers); + m_historyTable->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + m_historyTable->horizontalHeader()->setStretchLastSection(true); + m_historyTable->verticalHeader()->setVisible(false); + m_historyTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_historyTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_historyTable->setSelectionMode(QAbstractItemView::SingleSelection); + m_historyTable->setGeometry(QApplication::desktop()->screenGeometry()); + + overviewLayout->addWidget(m_historyTable); + overview->setLayout(overviewLayout); + + return overview; + } + + + /* + * This method creates the Images tab. + * + */ + QWidget* ControlHealthMonitorWidget::createImagesTab() { + QFont fontSmall("Arial", 12); + QFont fontMedium("Arial", 14); + + // This is the parent QWidget for the images tab. + QWidget *imagesTab = new QWidget(); + QVBoxLayout *imagesLayout = new QVBoxLayout; + imagesLayout->setAlignment(Qt::AlignTop); + imagesLayout->setSpacing(15); + imagesLayout->addSpacing(10); + + QWidget *temp = new QWidget; + QGridLayout *tempLayout = new QGridLayout; + + // Create the labels + QLabel *threeMeasure = new QLabel("Less than 3 valid Measures:"); + m_imagesMeasuresValue = new QLabel(""); + + QLabel *withoutMeasures = new QLabel("Exceeding convex hull tolerance:"); + m_imagesHullValue = new QLabel(""); + + // Set the fonts + m_imagesMeasuresValue->setFont(fontSmall); + threeMeasure->setFont(fontSmall); + withoutMeasures->setFont(fontSmall); + m_imagesHullValue->setFont(fontSmall); + + // Create the view buttons + QPushButton *button = new QPushButton("View"); + QPushButton *button2 = new QPushButton("View"); + + connect(button, SIGNAL(clicked()), this, SLOT(viewImageFewMeasures())); + connect(button2, SIGNAL(clicked()), this, SLOT(viewImageHullTolerance())); + + // Add everything in the right spot. + tempLayout->addWidget(threeMeasure, 0, 0); + tempLayout->addWidget(m_imagesMeasuresValue, 0, 1); + tempLayout->addWidget(button, 0, 2); + + tempLayout->addWidget(withoutMeasures, 1, 0); + tempLayout->addWidget(m_imagesHullValue, 1, 1); + tempLayout->addWidget(button2, 1, 2); + + temp->setLayout(tempLayout); + imagesLayout->addWidget(temp); + + // Create the table. + m_imagesTable = new QTableWidget(); + + connect(m_imagesTable, SIGNAL(itemDoubleClicked(QTableWidgetItem *)), + this, SLOT(emitOpenImageEditor())); + + QStringList headers; + headers.append("#"); + headers.append("Cube Serial"); + + m_imagesTable->setColumnCount(2); + m_imagesTable->setHorizontalHeaderLabels(headers); + m_imagesTable->horizontalHeader()->setStretchLastSection(true); + m_imagesTable->verticalHeader()->setVisible(false); + m_imagesTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_imagesTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_imagesTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + + m_imagesTable->setShowGrid(true); + m_imagesTable->setGeometry(QApplication::desktop()->screenGeometry()); + m_imagesTable->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + + imagesLayout->addSpacing(30); + + m_imagesShowingLabel = new QLabel(""); + m_imagesShowingLabel->setFont(fontMedium); + + QPushButton *viewAllButton = new QPushButton("View All"); + connect(viewAllButton, SIGNAL(clicked()), + this, SLOT(viewImageAll())); + + QGridLayout *showingLayout = new QGridLayout; + QWidget *showingWidget = new QWidget; + + showingLayout->addWidget(m_imagesShowingLabel, 0, 0, 1, 2); + showingLayout->addWidget(viewAllButton, 0, 2); + showingWidget->setLayout(showingLayout); + + imagesLayout->addWidget(showingWidget); + imagesLayout->addWidget(m_imagesTable); + + imagesTab->setLayout(imagesLayout); + return imagesTab; + } + + + /* + * This method creates the Points tab. + * + */ + QWidget* ControlHealthMonitorWidget::createPointsTab() { + + QFont fontSmall("Arial", 12); + QFont fontMedium("Arial", 14); + QFont searchFont("Seqoe UI Symbol", 12); + + // This is the main parent widget for the points tab. + QWidget *pointsTab = new QWidget(); + QVBoxLayout *pointsLayout = new QVBoxLayout; + pointsLayout->setAlignment(Qt::AlignTop); + pointsLayout->setSpacing(15); + pointsLayout->addSpacing(10); + + QWidget *viewWidget = new QWidget; + QGridLayout *viewLayout = new QGridLayout; + + // Create the labels. + QLabel *pointsIgnored = new QLabel("Points Ignored:"); + m_pointsIgnoredLabel = new QLabel(""); + + QLabel *freePoints = new QLabel("Points Free:"); + m_pointsFreeLabel = new QLabel(""); + m_pointsFreeProgressbar = new QProgressBar(); + QPalette p = m_pointsFreeProgressbar->palette(); + p.setColor(QPalette::Highlight, Qt::blue); + p.setColor(QPalette::Text, Qt::black); + m_pointsFreeProgressbar->setPalette(p); + m_pointsFreeProgressbar->setRange(0, 100); + + QLabel *constrainedPoints = new QLabel("Points Constrained:"); + m_pointsConstrainedLabel = new QLabel(""); + m_pointsConstrainedProgressbar = new QProgressBar(); + m_pointsConstrainedProgressbar->setPalette(p); + m_pointsConstrainedProgressbar->setRange(0, 100); + + QLabel *fixedPoints = new QLabel("Points Fixed:"); + m_pointsFixedLabel = new QLabel(""); + m_pointsFixedProgressbar = new QProgressBar(); + m_pointsFixedProgressbar->setPalette(p); + m_pointsFixedProgressbar->setRange(0, 100); + + QLabel *pointsLocked = new QLabel("Points Edit Locked:"); + m_pointsEditLockedLabel = new QLabel(""); + + QLabel *pointsMeasure = new QLabel("Less than 3 valid Measures:"); + m_pointsFewMeasuresLabel = new QLabel(""); + + // Set the font for the labels. + pointsLocked->setFont(fontSmall); + m_pointsEditLockedLabel->setFont(fontSmall); + pointsMeasure->setFont(fontSmall); + m_pointsFewMeasuresLabel->setFont(fontSmall); + freePoints->setFont(fontSmall); + m_pointsFreeLabel->setFont(fontSmall); + fixedPoints->setFont(fontSmall); + constrainedPoints->setFont(fontSmall); + pointsIgnored->setFont(fontSmall); + m_pointsFixedLabel->setFont(fontSmall); + m_pointsConstrainedLabel->setFont(fontSmall); + m_pointsIgnoredLabel->setFont(fontSmall); + + // Create the view buttons. + QPushButton *viewIgnoredButton = new QPushButton("View"); + QPushButton *viewLockedButton = new QPushButton("View"); + QPushButton *viewMeasureButton = new QPushButton("View"); + QPushButton *viewFreePoints = new QPushButton("View"); + QPushButton *viewFixedPoints = new QPushButton("View"); + QPushButton *viewConstrainedPoints = new QPushButton("View"); + + // Connect the buttons. + connect(viewIgnoredButton, SIGNAL(clicked()), this, SLOT(viewPointIgnored())); + connect(viewLockedButton, SIGNAL(clicked()), this, SLOT(viewPointEditLocked())); + connect(viewMeasureButton, SIGNAL(clicked()), this, SLOT(viewPointFewMeasures())); + connect(viewFreePoints, SIGNAL(clicked()), this, SLOT(viewPointFree())); + connect(viewFixedPoints, SIGNAL(clicked()), this, SLOT(viewPointFixed())); + connect(viewConstrainedPoints, SIGNAL(clicked()), this, SLOT(viewPointConstrained())); + + // Add the widgets in the proper place. + viewLayout->addWidget(freePoints, 0, 0); + viewLayout->addWidget(m_pointsFreeProgressbar, 0, 1); + viewLayout->addWidget(viewFreePoints, 0, 2); + + viewLayout->addWidget(fixedPoints, 1, 0); + viewLayout->addWidget(m_pointsFixedProgressbar, 1, 1); + viewLayout->addWidget(viewFixedPoints, 1, 2); + + viewLayout->addWidget(constrainedPoints, 2, 0); + viewLayout->addWidget(m_pointsConstrainedProgressbar, 2, 1); + viewLayout->addWidget(viewConstrainedPoints, 2, 2); + + viewLayout->addWidget(pointsIgnored, 3, 0); + viewLayout->addWidget(m_pointsIgnoredLabel, 3, 1); + viewLayout->addWidget(viewIgnoredButton, 3, 2); + + viewLayout->addWidget(pointsLocked, 4, 0); + viewLayout->addWidget(m_pointsEditLockedLabel, 4, 1); + viewLayout->addWidget(viewLockedButton, 4, 2); + + viewLayout->addWidget(pointsMeasure, 5, 0); + viewLayout->addWidget(m_pointsFewMeasuresLabel, 5, 1); + viewLayout->addWidget(viewMeasureButton, 5, 2); + + viewWidget->setLayout(viewLayout); + pointsLayout->addWidget(viewWidget); + + // Create the table. + m_pointsTable = new QTableWidget(); + QStringList headers; + headers.append("#"); + headers.append("Point ID"); + headers.append("Type"); + headers.append("Ignored"); + headers.append("Rejected"); + headers.append("Edit Locked"); + + m_pointsTable->setColumnCount(6); + m_pointsTable->setHorizontalHeaderLabels(headers); + m_pointsTable->horizontalHeader()->setStretchLastSection(true); + m_pointsTable->verticalHeader()->setVisible(false); + m_pointsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_pointsTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_pointsTable->setSelectionMode(QAbstractItemView::SingleSelection); + m_pointsTable->setShowGrid(true); + m_pointsTable->setGeometry(QApplication::desktop()->screenGeometry()); + m_pointsTable->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + + connect(m_pointsTable, SIGNAL(itemDoubleClicked(QTableWidgetItem *)), + this, SLOT(emitOpenPointEditor())); + + m_pointsShowingLabel = new QLabel(""); + m_pointsShowingLabel->setFont(fontMedium); + QPushButton *showAllButton = new QPushButton("View All"); + + QGridLayout *showLayout = new QGridLayout; + QWidget *showWidget = new QWidget; + + connect(showAllButton, SIGNAL(clicked()), + this, SLOT(viewPointAll())); + + showLayout->addWidget(m_pointsShowingLabel, 0, 0, 1, 2); + showLayout->addWidget(showAllButton, 0, 2); + showWidget->setLayout(showLayout); + + pointsLayout->addSpacing(30); + pointsLayout->addWidget(showWidget); + pointsLayout->addWidget(m_pointsTable); + + pointsTab->setLayout(pointsLayout); + return pointsTab; + } + + + /** + * This method is designed to be called whenever a user double-clicks on an image + * in the image table of the images tab. It will grab the selected images and emit + * the openImageEditor() signal, emitting with it the images that were selected. + * + * The openImageEditor() signal is intercepted by the ControlHealthMonitorView + * and opens the CubeDnView with the images selected. + */ + void ControlHealthMonitorWidget::emitOpenImageEditor() { + QList<QString> serials; + QModelIndexList rows = m_imagesTable->selectionModel()->selectedRows(1); + foreach (QModelIndex index, rows) { + serials.append(index.data().toString()); + } + emit openImageEditor(serials); + } + + + /** + * This method is designed to be called whenever a user double-clicks on a point + * in the point table of the points tab. It will grab the selected point and emit + * the openPointEditor() signal, emitting with it the point that was selected. + * + * The openPointEditor() signal is intercepted by the ControlHealthMonitorView + * and opens the ControlPointEditWidget with that point selected. + */ + void ControlHealthMonitorWidget::emitOpenPointEditor() { + // Get the point + QModelIndex pointId = m_pointsTable->selectionModel()->selectedIndexes()[1]; + ControlPoint *point = m_vitals->getPoint(pointId.data().toString()); + emit openPointEditor(point); + } + + + /** + * This SLOT is designed to intercept the historyEntry() signal emitted from the + * ControlNetVitals class whenever a modification is made to the network. The + * signal emits several details pertaining to the history entry. + * + * @param entry The history comment to be displayed. + * @param id The id of the Control Point, Measure, or Network that was modified. + * @param oldValue The old value before the modification was made. + * @param newValue The new value after the modification was made. + * @param timeStamp The timestamp of when the modification was made. + * + */ + void ControlHealthMonitorWidget::historyEntry(QString entry, QString id, + QVariant oldValue, QVariant newValue, + QString timeStamp) { + + m_lastModLabel->setText("Last Modification: " + timeStamp); + + m_historyTable->insertRow(0); + m_historyTable->setItem(0, 0, new QTableWidgetItem(entry)); + m_historyTable->setItem(0, 1, new QTableWidgetItem(id)); + m_historyTable->setItem(0, 2, new QTableWidgetItem(oldValue.toString())); + m_historyTable->setItem(0, 3, new QTableWidgetItem(newValue.toString())); + m_historyTable->setItem(0, 4, new QTableWidgetItem(timeStamp)); + } + + + /* + * This method creates the Graph tab. + * + */ + QWidget* ControlHealthMonitorWidget::createGraphTab() { + QWidget *graph = new QWidget(); + + QVBoxLayout *graphLayout = new QVBoxLayout; + graphLayout->setAlignment(Qt::AlignTop); + graphLayout->setSpacing(5); + // + // m_pointChartView = new QChartView; + // m_pointChartView->resize(200, 200); + // m_pointChartView->setRenderHint(QPainter::Antialiasing); + // + // QChart *chart = new QChart(); + // chart->setTitle("Point Breakdown"); + // chart->setTheme(QChart::ChartThemeBlueCerulean); + // chart->legend()->setAlignment(Qt::AlignRight); + // m_pointChartView->setChart(chart); + // graphLayout->addWidget(m_pointChartView); + + graph->setLayout(graphLayout); + return graph; + + } + + + /* + * This method loads a QList of cube serials into the images table. + * + */ + void ControlHealthMonitorWidget::updateImageTable(QList<QString> serials) { + m_imagesTable->setRowCount(0); + for (int i = 0; i < serials.size(); i++) { + m_imagesTable->insertRow(i); + m_imagesTable->setItem(i, 0, new QTableWidgetItem(toString(i + 1))); + m_imagesTable->setItem(i, 1, new QTableWidgetItem(serials.at(i))); + } + } + + + /* + * This method loads a QList of ControlPoint* into the points table. + * + */ + void ControlHealthMonitorWidget::updatePointTable(QList<ControlPoint*> points) { + m_pointsTable->setRowCount(0); + for (int i = 0; i < points.size(); i++) { + ControlPoint *point = points.at(i); + m_pointsTable->insertRow(i); + m_pointsTable->setItem(i, 0, new QTableWidgetItem(toString(i + 1))); + m_pointsTable->setItem(i, 1, new QTableWidgetItem(point->GetId())); + m_pointsTable->setItem(i, 2, new QTableWidgetItem(point->GetPointTypeString())); + m_pointsTable->setItem(i, 3, new QTableWidgetItem(toString(point->IsIgnored()))); + m_pointsTable->setItem(i, 4, new QTableWidgetItem(toString(point->IsRejected()))); + m_pointsTable->setItem(i, 5, new QTableWidgetItem(toString(point->IsEditLocked()))); + } + } + + + /* + * This SLOT is designed to view all points in the Control Network. + * + */ + void ControlHealthMonitorWidget::viewPointAll() { + updatePointTable(m_vitals->getAllPoints()); + m_pointsShowingLabel->setText("Showing: All Points <sup>" + + toString(m_vitals->numPoints()) + + " / " + toString(m_vitals->numPoints()) + "</sup>"); + } + + + /* + * This SLOT is designed to view ignored points in the Control Network. + * + */ + void ControlHealthMonitorWidget::viewPointIgnored() { + updatePointTable(m_vitals->getIgnoredPoints()); + m_pointsShowingLabel->setText("Showing: Ignored Points <sup>" + + toString(m_vitals->numIgnoredPoints()) + + " / " + toString(m_vitals->numPoints()) + "</sup>"); + } + + + /* + * This SLOT is designed to view free points in the Control Network. + * + */ + void ControlHealthMonitorWidget::viewPointFree() { + updatePointTable(m_vitals->getFreePoints()); + m_pointsShowingLabel->setText("Showing: Free Points <sup>" + + toString(m_vitals->numFreePoints()) + + " / " + toString(m_vitals->numPoints()) + "</sup>"); + } + + + /* + * This SLOT is designed to view fixed points in the Control Network. + * + */ + void ControlHealthMonitorWidget::viewPointFixed() { + updatePointTable(m_vitals->getFixedPoints()); + m_pointsShowingLabel->setText("Showing: Fixed Points <sup>" + + toString(m_vitals->numFixedPoints()) + + " / " + toString(m_vitals->numPoints()) + "</sup>"); + } + + + /* + * This SLOT is designed to view constrained points in the Control Network. + * + */ + void ControlHealthMonitorWidget::viewPointConstrained() { + updatePointTable(m_vitals->getConstrainedPoints()); + m_pointsShowingLabel->setText("Showing: Constrained Points <sup>" + + toString(m_vitals->numConstrainedPoints()) + + " / " + toString(m_vitals->numPoints()) + "</sup>"); + } + + + /* + * This SLOT is designed to view locked points in the Control Network. + * + */ + void ControlHealthMonitorWidget::viewPointEditLocked() { + updatePointTable(m_vitals->getLockedPoints()); + m_pointsShowingLabel->setText("Showing: Locked Points <sup>" + + toString(m_vitals->numLockedPoints()) + + " / " + toString(m_vitals->numPoints()) + "</sup>"); + + } + + + /* + * This SLOT is designed to view points with less than 3 valid measures in the Control Network. + * + */ + void ControlHealthMonitorWidget::viewPointFewMeasures() { + updatePointTable(m_vitals->getPointsBelowMeasureThreshold()); + m_pointsShowingLabel->setText("Showing: Points with less than 3 Measures <sup>" + + toString(m_vitals->numPointsBelowMeasureThreshold()) + + " / " + toString(m_vitals->numPoints()) + "</sup>"); + } + + + /* + * This SLOT is designed to view all images in the Control Network. + * + */ + void ControlHealthMonitorWidget::viewImageAll() { + updateImageTable(m_vitals->getCubeSerials()); + m_imagesShowingLabel->setText("Showing: All Images <sup>" + + toString(m_vitals->numImages()) + + " / " + toString(m_vitals->numImages()) + "</sup>"); + } + + + /* + * This SLOT is designed to view images with less than 3 valid measures in the Control Network. + * + */ + void ControlHealthMonitorWidget::viewImageFewMeasures() { + updateImageTable(m_vitals->getImagesBelowMeasureThreshold()); + m_imagesShowingLabel->setText("Showing: Images with less than 3 Measures <sup>" + + toString(m_vitals->numImagesBelowMeasureThreshold()) + + " / " + toString(m_vitals->numImages()) + "</sup>"); + } + + + /* + * This SLOT is designed to view images below the Convex Hull Tolerance in the Control Network. + * + */ + void ControlHealthMonitorWidget::viewImageHullTolerance() { + updateImageTable(m_vitals->getImagesBelowHullTolerance()); + m_imagesShowingLabel->setText("Showing: Images below a hull tolerance of 75% <sup>" + + toString(m_vitals->numImagesBelowHullTolerance()) + + " / " + toString(m_vitals->numImages()) + "</sup>"); + } + + + /** + * Destructor + */ + ControlHealthMonitorWidget::~ControlHealthMonitorWidget() { + + delete m_historyTable; + delete m_imagesHullValue; + delete m_imagesMeasuresValue; + delete m_imagesShowingLabel; + delete m_imagesTable; + delete m_lastModLabel; + delete m_numImagesLabel; + delete m_numMeasuresLabel; + delete m_numPointsLabel; + // delete m_pointChartView; + delete m_pointsEditLockedLabel; + delete m_pointsFewMeasuresLabel; + delete m_pointsIgnoredLabel; + delete m_pointsShowingLabel; + delete m_pointsTable; + delete m_statusBar; + delete m_statusDetails; + delete m_statusLabel; + delete m_vitals; + + m_historyTable = NULL; + m_imagesHullValue = NULL; + m_imagesMeasuresValue = NULL; + m_imagesShowingLabel = NULL; + m_imagesTable = NULL; + m_lastModLabel = NULL; + m_numImagesLabel = NULL; + m_numMeasuresLabel = NULL; + m_numPointsLabel = NULL; + // m_pointChartView = NULL; + m_pointsEditLockedLabel = NULL; + m_pointsFewMeasuresLabel = NULL; + m_pointsIgnoredLabel = NULL; + m_pointsShowingLabel = NULL; + m_pointsTable = NULL; + m_statusBar = NULL; + m_statusDetails = NULL; + m_statusLabel = NULL; + m_vitals = NULL; + } +} diff --git a/isis/src/qisis/objs/ControlHealthMonitorWidget/ControlHealthMonitorWidget.h b/isis/src/qisis/objs/ControlHealthMonitorWidget/ControlHealthMonitorWidget.h new file mode 100644 index 0000000000000000000000000000000000000000..cf0afd10919d762a574839f56c8ef8629c12ab36 --- /dev/null +++ b/isis/src/qisis/objs/ControlHealthMonitorWidget/ControlHealthMonitorWidget.h @@ -0,0 +1,123 @@ +#ifndef ControlHealthMonitorWidget_h +#define ControlHealthMonitorWidget_h +/** + * @file + * $Date$ + * $Revision$ + * + * Unless noted otherwise, the portions of Isis written by the USGS are + * public domain. See individual third-party library and package descriptions + * for intellectual property information, user agreements, and related + * information. + * + * Although Isis has been used by the USGS, no warranty, expressed or + * implied, is made by the USGS as to the accuracy and functioning of such + * software and related material nor shall the fact of distribution + * constitute any such warranty, and no responsibility is assumed by the + * USGS in connection therewith. + * + * For additional information, launch + * $ISISROOT/doc//documents/Disclaimers/Disclaimers.html + * in a browser or see the Privacy & Disclaimers page on the Isis website, + * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on + * http://www.usgs.gov/privacy.html. + */ + +#include <QLabel> +#include <QTableWidget> +#include <QProgressBar> +#include <QPointer> +#include <ControlNetVitals.h> + + + +namespace Isis { + /** + * Interface that allows real-time evaluation of the state of a Control Network. + * + * @author 2018-05-28 Adam Goins + * + * @internal + * @history 2018-05-28 Adam Goins - Initial Creation. + */ + class ControlHealthMonitorWidget : public QWidget { + + + Q_OBJECT + + public: + ControlHealthMonitorWidget(ControlNetVitals *vitals, QWidget *parent=0); + ~ControlHealthMonitorWidget(); + void createGui(); + QWidget* createImagesTab(); + QWidget* createPointsTab(); + QWidget* createOverviewTab(); + QWidget* createGraphTab(); + void setVitals(ControlNetVitals *vitals); + void initializeEverything(); + + public slots: + void emitOpenImageEditor(); + void emitOpenPointEditor(); + + void historyEntry(QString, QString, QVariant, QVariant, QString); + + void viewPointAll(); + void viewPointFree(); + + void viewPointFixed(); + void viewPointConstrained(); + + void viewPointIgnored(); + void viewPointEditLocked(); + void viewPointFewMeasures(); + + void viewImageAll(); + void viewImageFewMeasures(); + void viewImageHullTolerance(); + + void update(); + + signals: + void openPointEditor(ControlPoint *point); + void openImageEditor(QList<QString> serials); + + private: + void updateStatus(int code); + void updateImageTable(QList<QString> serials); + void updatePointTable(QList<ControlPoint*> points); + + // QChartView *m_pointChartView; + ControlNetVitals *m_vitals; + QProgressBar *m_statusBar; + QProgressBar *m_pointsFreeProgressbar; + QProgressBar *m_pointsConstrainedProgressbar; + QProgressBar *m_pointsFixedProgressbar; + + + QTableWidget *m_historyTable; + QTableWidget *m_imagesTable; + QTableWidget *m_pointsTable; + + QLabel *m_imagesHullValue; + QLabel *m_imagesMeasuresValue; + QLabel *m_imagesShowingLabel; + QLabel *m_lastModLabel; + QLabel *m_netLabel; + QLabel *m_numImagesLabel; + QLabel *m_numMeasuresLabel; + QLabel *m_numPointsLabel; + QLabel *m_pointsConstrainedLabel; + QLabel *m_pointsEditLockedLabel; + QLabel *m_pointsFewMeasuresLabel; + QLabel *m_pointsFixedLabel; + QLabel *m_pointsFreeLabel; + QLabel *m_pointsIgnoredLabel; + QLabel *m_pointsShowingLabel; + QLabel *m_statusDetails; + QLabel *m_statusLabel; + + }; +} + +#endif diff --git a/isis/src/qisis/objs/ControlHealthMonitorWidget/Makefile b/isis/src/qisis/objs/ControlHealthMonitorWidget/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f122bc88227c5c7ebd108dea5d339d1d2e074d82 --- /dev/null +++ b/isis/src/qisis/objs/ControlHealthMonitorWidget/Makefile @@ -0,0 +1,7 @@ +ifeq ($(ISISROOT), $(BLANK)) +.SILENT: +error: + echo "Please set ISISROOT"; +else + include $(ISISROOT)/make/isismake.objs +endif \ No newline at end of file diff --git a/isis/src/qisis/objs/ControlMeasureEditWidget/ControlMeasureEditWidget.cpp b/isis/src/qisis/objs/ControlMeasureEditWidget/ControlMeasureEditWidget.cpp index 140d2b5fab036de064b6f5c8c1678b165c2d502e..31c65f3cb7a8d5f2a9b20768af3ae134d6621a87 100644 --- a/isis/src/qisis/objs/ControlMeasureEditWidget/ControlMeasureEditWidget.cpp +++ b/isis/src/qisis/objs/ControlMeasureEditWidget/ControlMeasureEditWidget.cpp @@ -142,21 +142,18 @@ namespace Isis { leftZoomIn->setIconSize(isize); leftZoomIn->setToolTip("Zoom In 2x"); leftZoomIn->setWhatsThis("Zoom In 2x on left measure."); - leftZoomIn->setShortcut(Qt::Key_Plus); QToolButton *leftZoomOut = new QToolButton(); leftZoomOut->setIcon(QPixmap(toolIconDir + "/viewmag-.png")); leftZoomOut->setIconSize(isize); leftZoomOut->setToolTip("Zoom Out 2x"); leftZoomOut->setWhatsThis("Zoom Out 2x on left measure."); - leftZoomOut->setShortcut(Qt::Key_Minus); QToolButton *leftZoom1 = new QToolButton(); leftZoom1->setIcon(QPixmap(toolIconDir + "/viewmag1.png")); leftZoom1->setIconSize(isize); leftZoom1->setToolTip("Zoom 1:1"); leftZoom1->setWhatsThis("Show left measure at full resolution."); - leftZoom1->setShortcut(Qt::Key_Slash); QHBoxLayout *leftZoomPan = new QHBoxLayout; leftZoomPan->addWidget(leftZoomIn); @@ -216,7 +213,6 @@ namespace Isis { m_rightZoomIn->setIconSize(isize); m_rightZoomIn->setToolTip("Zoom In 2x"); m_rightZoomIn->setWhatsThis("Zoom In 2x on right measure."); - m_rightZoomIn->setShortcut(Qt::Key_Plus); m_rightZoomOut = new QToolButton(); m_rightZoomOut->setIcon(QIcon(FileName("$base/icons/viewmag-.png"). @@ -224,14 +220,12 @@ namespace Isis { m_rightZoomOut->setIconSize(isize); m_rightZoomOut->setToolTip("Zoom Out 2x"); m_rightZoomOut->setWhatsThis("Zoom Out 2x on right measure."); - m_rightZoomOut->setShortcut(Qt::Key_Minus); m_rightZoom1 = new QToolButton(); m_rightZoom1->setIcon(QPixmap(toolIconDir + "/viewmag1.png")); m_rightZoom1->setIconSize(isize); m_rightZoom1->setToolTip("Zoom 1:1"); m_rightZoom1->setWhatsThis("Show right measure at full resolution."); - m_rightZoom1->setShortcut(Qt::Key_Slash); QHBoxLayout *rightZoomPan = new QHBoxLayout; rightZoomPan->addWidget(m_rightZoomIn); @@ -607,7 +601,6 @@ namespace Isis { m_autoReg->setShortcut(Qt::Key_R); m_autoReg->setToolTip("Sub-pixel register the right measure to the left. " "<strong>Shortcut: R</strong>"); - m_autoReg->setToolTip("Sub-pixel register the right measure to the left"); m_autoReg->setWhatsThis("Sub-pixel register the right measure to the left " "and move the result under the crosshair. After " "viewing the results, the option exists to move the " @@ -812,6 +805,8 @@ namespace Isis { m_autoRegExtension->hide(); m_autoReg->setText("Register"); m_autoReg->setShortcut(Qt::Key_R); + m_autoReg->setToolTip("Sub-pixel register the right measure to the left. " + "<strong>Shortcut: R</strong>"); } m_autoRegAttempted = false; @@ -1026,6 +1021,9 @@ namespace Isis { m_autoRegShown = false; m_autoRegExtension->hide(); m_autoReg->setText("Register"); + m_autoReg->setShortcut(Qt::Key_R); + m_autoReg->setToolTip("Sub-pixel register the right measure to the left. " + "<strong>Shortcut: R</strong>"); // Reload chip with original measure emit updateRightView(m_rightMeasure->GetSample(), diff --git a/isis/src/qisis/objs/ControlMeasureEditWidget/ControlMeasureEditWidget.h b/isis/src/qisis/objs/ControlMeasureEditWidget/ControlMeasureEditWidget.h index 7a03032e8e36306260b3bcb58e1eb2db58ff6c6f..964a3e088594a715ac9bd96f7d8eb5f59a2608b9 100644 --- a/isis/src/qisis/objs/ControlMeasureEditWidget/ControlMeasureEditWidget.h +++ b/isis/src/qisis/objs/ControlMeasureEditWidget/ControlMeasureEditWidget.h @@ -144,7 +144,10 @@ namespace Isis { * @history 2017-08-11 Tracie Sucharski - Created a new ControlMeasure when editing points so * that the edit ControlPoint is no changed until user selects * "Save Measures", and colorize save buttons. Fixes #4984. - * + * @history 2018-06-28 Kaitlyn Lee - Removed shortcuts from zoom buttons because of ambiguous + * shortcut errors. Set the shortcut and tooltip of m_autoReg inside of + * registerPoint() to allow the user to use the shortcut after an + * undo-registration ocurs. * @todo Re-think design of the change made on 2012-07-26. The linking was put into * ::updateLeftPositionLabel because it was the fastest solution, but * should this be put somewhere else. diff --git a/isis/src/qisis/objs/ControlPointEditView/ControlPointEditView.cpp b/isis/src/qisis/objs/ControlPointEditView/ControlPointEditView.cpp index 77b7889cf77106efafd6217a6edc37e4352c5c03..dd50838e460b131d28214f0e16dea5ef9aeca2dd 100644 --- a/isis/src/qisis/objs/ControlPointEditView/ControlPointEditView.cpp +++ b/isis/src/qisis/objs/ControlPointEditView/ControlPointEditView.cpp @@ -29,7 +29,6 @@ #include <QSize> #include <QSizePolicy> #include <QToolBar> -#include <QVBoxLayout> #include <QWidgetAction> #include "ControlNet.h" @@ -53,41 +52,20 @@ namespace Isis { // net, while the editors might be using a different net. Will Directory keep track? // + setCentralWidget(m_controlPointEditWidget); - QVBoxLayout *layout = new QVBoxLayout; - setLayout(layout); - - layout->addWidget(m_controlPointEditWidget); - - m_permToolBar = new QToolBar("Standard Tools", 0); - m_permToolBar->setObjectName("permToolBar"); - m_permToolBar->setIconSize(QSize(22, 22)); - //toolBarLayout->addWidget(m_permToolBar); - - m_activeToolBar = new QToolBar("Active Tool", 0); - m_activeToolBar->setObjectName("activeToolBar"); - m_activeToolBar->setIconSize(QSize(22, 22)); - //toolBarLayout->addWidget(m_activeToolBar); - - m_toolPad = new ToolPad("Tool Pad", 0); - m_toolPad->setObjectName("toolPad"); - //toolBarLayout->addWidget(m_toolPad); - - -// m_controlPointEditWidget->addToPermanent(m_permToolBar); -// m_controlPointEditWidget->addTo(m_activeToolBar); -// m_controlPointEditWidget->addTo(m_toolPad); + setAcceptDrops(true); - m_activeToolBarAction = new QWidgetAction(this); - m_activeToolBarAction->setDefaultWidget(m_activeToolBar); + // Store the buttons (actions) for easy enable/disable. + m_buttons = m_controlPointEditWidget->findChildren<QPushButton *>(); - setAcceptDrops(true); + // On default, actions are disabled until the cursor enters the view. + disableActions(); QSizePolicy policy = sizePolicy(); policy.setHorizontalPolicy(QSizePolicy::Expanding); policy.setVerticalPolicy(QSizePolicy::Expanding); setSizePolicy(policy); - } @@ -96,13 +74,6 @@ namespace Isis { */ ControlPointEditView::~ControlPointEditView() { delete m_controlPointEditWidget; - delete m_permToolBar; - delete m_activeToolBar; - delete m_toolPad; - - m_permToolBar = 0; - m_activeToolBar = 0; - m_toolPad = 0; } @@ -128,36 +99,21 @@ namespace Isis { /** - * Returns a list of actions for the permanent tool bar. - * - * @return (QList<QAction *>) The actions + * Disables buttons/actions. Overriden method. */ - QList<QAction *> ControlPointEditView::permToolBarActions() { - return m_permToolBar->actions(); + void ControlPointEditView::disableActions() { + foreach (QPushButton *button, m_buttons) { + button->setDisabled(true); + } } /** - * Returns a list of actions for the active tool bar. - * - * @return (QList<QAction *>) The actions - */ - QList<QAction *> ControlPointEditView::activeToolBarActions() { - QList<QAction *> actions; - actions.append(m_activeToolBarAction); - return actions; - } - - - /** - * Returns a list of actions for the tool pad. - * - * @return (QList<QAction *>) The actions + * Enables buttons/actions. Overriden method. */ - QList<QAction *> ControlPointEditView::toolPadActions() { - return m_toolPad->actions(); + void ControlPointEditView::enableActions() { + foreach (QPushButton *button, m_buttons) { + button->setEnabled(true); + } } - - } - diff --git a/isis/src/qisis/objs/ControlPointEditView/ControlPointEditView.h b/isis/src/qisis/objs/ControlPointEditView/ControlPointEditView.h index 18304a19efbdae94a4d126ab560826b6f501e0a2..a260f9715fe4c818056a1c34e1fa1cbdf97f425b 100644 --- a/isis/src/qisis/objs/ControlPointEditView/ControlPointEditView.h +++ b/isis/src/qisis/objs/ControlPointEditView/ControlPointEditView.h @@ -26,6 +26,7 @@ #include <QPointer> #include <QToolBar> #include <QWidgetAction> +#include <QPushButton> #include "AbstractProjectItemView.h" @@ -40,10 +41,23 @@ namespace Isis { * View for editing a single ControlPoint * * @author 2016-04-06 Tracie Sucharski - * - * @internal + * + * @internal * @history 2016-09-30 Tracie Sucharski - Pass in directory to constructor, so that we can - * query for shapes and other data from the project. + * query for shapes and other data from the project. + * @history 2018-05-28 Kaitlyn Lee - Since AbstractProjectItemView now inherits + * from QMainWindow, I added a dummy central widget + * and set its layout to QVBoxLayout. We used to set + * the whole CnetEditorView widget's layout, now we only + * set the central widget's layout. + * @history 2018-06-28 Kaitlyn Lee - Removed toolbars. When multiple views are open, + * there is a possibility of getting ambiguous shortcut errors. + * To counter this, we enable/disable actions. On default, a + * view's actions are disabled. To enable the actions, move the + * cursor over the view. When a user moves the cursor outside of + * the view, the actions are disabled. Because this view uses + * buttons instead of actions, overrode enableActions() and + * disableActions() and added m_buttons to enable/disable buttons. */ class ControlPointEditView : public AbstractProjectItemView { @@ -54,30 +68,20 @@ class ControlPointEditView : public AbstractProjectItemView { ControlPointEditView(Directory *directory, QWidget *parent = 0); ~ControlPointEditView(); - virtual QList<QAction *> permToolBarActions(); - virtual QList<QAction *> activeToolBarActions(); - virtual QList<QAction *> toolPadActions(); - ControlPointEditWidget *controlPointEditWidget(); // setEditPoint(ControlPoint *editPoint); // createNewPoint(QString serialNumber, Latitude lat, Longitude lon); - QSize sizeHint() const; - - public slots: - - private slots: + QSize sizeHint() const; private: + void disableActions(); + void enableActions(); + QPointer<ControlPointEditWidget> m_controlPointEditWidget; QMap<Control *, ProjectItem *> m_controlItemMap; //!<Maps control net to project item - - QToolBar *m_permToolBar; //!< The permanent tool bar - QToolBar *m_activeToolBar; //!< The active tool bar - ToolPad *m_toolPad; //!< The tool pad - - QWidgetAction *m_activeToolBarAction; //!< Stores the active tool bar + QList<QPushButton *> m_buttons; }; } diff --git a/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.cpp b/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.cpp index 7e657d0df4cd2ed6c15f04f06afa22d7771a4012..3954e53f4c23c0ed6527552fbea4b6eeb54c74e5 100644 --- a/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.cpp +++ b/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.cpp @@ -178,11 +178,9 @@ namespace Isis { } m_reloadPoint = new QPushButton("Reload Point"); - m_reloadPoint->setShortcut(Qt::Key_R); m_reloadPoint->setToolTip("Reload the control point."); m_reloadPoint->setWhatsThis("Reload the measures for the control point" - " in the Chip Viewports to its saved values. " - "<strong>Shortcut: R</strong>"); + " in the Chip Viewports to its saved values. "); connect(m_reloadPoint, SIGNAL(clicked()), this, SLOT(reloadPoint())); m_savePoint = new QPushButton ("Save Point"); @@ -219,8 +217,6 @@ namespace Isis { saveMeasureLayout->insertStretch(-1); m_cnetFileNameLabel = new QLabel("Control Network: " + m_cnetFileName); - m_cnetFileNameLabel->setToolTip("Name of opened control network file."); - m_cnetFileNameLabel->setWhatsThis("Name of opened control network file."); m_templateFileNameLabel = new QLabel("Template File: " + m_measureEditor->templateFileName()); @@ -580,7 +576,7 @@ namespace Isis { * New control network being edited * * @param cnet (Control *) The control network to edit - * + * * @internal */ void ControlPointEditWidget::setControl(Control *control) { @@ -589,7 +585,11 @@ namespace Isis { m_controlNet = control->controlNet(); m_cnetFileName = control->fileName(); - m_cnetFileNameLabel->setText("Control Network: " + m_cnetFileName); + QStringList cnetDirs = m_cnetFileName.split('/'); + QString strippedCnetFilename = cnetDirs.value(cnetDirs.length() -1); + m_cnetFileNameLabel->setText("Control Network: " + strippedCnetFilename); + m_cnetFileNameLabel->setToolTip(m_cnetFileName); + m_cnetFileNameLabel->setWhatsThis(m_cnetFileName); setWindowTitle("Control Point Editor- Control Network File: " + m_cnetFileName); emit newControlNetwork(m_controlNet); @@ -597,10 +597,10 @@ namespace Isis { /** - * New active control was set from ipce - * - * TODO: This will need to be redesigned with the ::setControl method to better handle editing - * points from different cnets. + * New active control was set from ipce + * + * TODO: This will need to be redesigned with the ::setControl method to better handle editing + * points from different cnets. */ void ControlPointEditWidget::setControlFromActive() { @@ -612,7 +612,7 @@ namespace Isis { m_cnetFileNameLabel->setText("Control Network: " + m_cnetFileName); setWindowTitle("Control Point Editor- Control Network File: " + m_cnetFileName); - emit newControlNetwork(m_controlNet); + emit newControlNetwork(m_controlNet); } } @@ -703,9 +703,9 @@ namespace Isis { * Find the ground source location from ControlPoint parameter, AprioriXYZSourceFile. If file * does not exist, give option to look in another location and change location in the ControlNet * for either this point and/or all points in net. - * + * * @return FileName The filename including full path of the ground source - * + * */ FileName ControlPointEditWidget::findGroundFile() { @@ -787,9 +787,9 @@ namespace Isis { /** * Slot called by Directory to set the control point for editing * - * @param controlPoint (ControlPoint *) ControlPoint that will be loaded into editor - * @param serialNumber (QString) Optional parameter indicating the serial number of the cube that - * the point was chosen from + * @param controlPoint (ControlPoint *) ControlPoint that will be loaded into editor + * @param serialNumber (QString) Optional parameter indicating the serial number of the cube that + * the point was chosen from */ void ControlPointEditWidget::setEditPoint(ControlPoint *controlPoint, QString serialNumber) { @@ -810,11 +810,10 @@ namespace Isis { else { m_editPoint = new ControlPoint; *m_editPoint = *controlPoint; - // New point loaded, make sure all save button's text is default black color colorizeAllSaveButtons("black"); - } + } loadPoint(serialNumber); loadTemplateFile(m_measureEditor->templateFileName()); } @@ -829,7 +828,7 @@ namespace Isis { m_saveNet->setPalette(m_saveDefaultPalette); } else if (color == "red") { - m_measureEditor->colorizeSaveButton(); + m_measureEditor->colorizeSaveButton(); colorizeSavePointButton(); colorizeSaveNetButton(); } @@ -838,9 +837,9 @@ namespace Isis { /** * Load point into ControlPointEditWidget. - * + * * @param serialNumber (QString) The serial number of cube point was chosen from. This will - * + * * @internal * @history 2008-11-26 Jeannie Walldren - Added "Number of Measures" to * ControlPointEditWidget point information. @@ -860,6 +859,7 @@ namespace Isis { // Write pointId QString CPId = m_editPoint->GetId(); + QString ptId("Point ID: "); ptId += (QString) CPId; m_ptIdValue->setText(ptId); @@ -901,6 +901,7 @@ namespace Isis { else { rad = "Apriori Radius: " + QString::number(surfPoint.GetLocalRadius().meters(), 'f', 2); } + m_aprioriRadius->setText(rad); // Set EditLock box correctly @@ -1019,12 +1020,13 @@ namespace Isis { rightIndex = 0; } } - // Handle pts with a single measure, for now simply put measure on left/right // Evenutally put on left with black on right?? if (rightIndex > m_editPoint->GetNumMeasures()-1) rightIndex = 0; + m_rightCombo->setCurrentIndex(rightIndex); m_leftCombo->setCurrentIndex(leftIndex); + // Initialize pointEditor with measures selectLeftMeasure(leftIndex); selectRightMeasure(rightIndex); @@ -1968,7 +1970,6 @@ namespace Isis { void ControlPointEditWidget::selectLeftMeasure(int index) { QString file = m_pointFiles[index]; - QString serial; try { serial = m_serialNumberList->serialNumber(file); @@ -1991,8 +1992,8 @@ namespace Isis { delete m_leftMeasure; m_leftMeasure = NULL; } - m_leftMeasure = new ControlMeasure(); - // Find measure for each file + m_leftMeasure = new ControlMeasure; + *m_leftMeasure = *((*m_editPoint)[serial]); // If m_leftCube is not null, delete before creating new one @@ -2001,7 +2002,6 @@ namespace Isis { // Update left measure of pointEditor m_measureEditor->setLeftMeasure (m_leftMeasure, m_leftCube.data(), m_editPoint->GetId()); updateLeftMeasureInfo (); - } @@ -2041,9 +2041,8 @@ namespace Isis { delete m_rightMeasure; m_rightMeasure = NULL; } - m_rightMeasure = new ControlMeasure(); + m_rightMeasure = new ControlMeasure; - // Find measure for each file *m_rightMeasure = *((*m_editPoint)[serial]); // If m_rightCube is not null, delete before creating new one @@ -2546,8 +2545,8 @@ namespace Isis { } - /** - * This was used when ipce used docked widgets. + /** + * This was used when ipce used docked widgets. * This method is called from the constructor so that when the * Main window is created, it know's it's size and location. * diff --git a/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.h b/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.h index 29e62dae70160a281975101be1f8090a28cf4048..a75abc3b982f0aba25e0cd12c2b4d7f2695abcad 100644 --- a/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.h +++ b/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.h @@ -89,7 +89,13 @@ namespace Isis { * or FootprintView if a ground source exists in the serial number list. * Fixes #5399. * @history 2018-05-02 Tracie Sucharski - Colorize save buttons properly when creating new - * control point and loading a different control point. + * control point and loading a different control point. + * @history 2018-06-11 Summer Stapleton - Stripped path from displayed filename of Control + * Network and set the tooltip to the full path for easier access. + * control point and loading a different control point. + * @history 2018-06-19 Adam Goins - Fixed updating references in selectLeftMeasure and + * selectRightMeasure to fix a segfault that was occuring. #Fixes #5435 + * @history 2018-06-28 Kaitlyn Lee - Removed shortcut from reload point button. */ class ControlPointEditWidget : public QWidget { Q_OBJECT diff --git a/isis/src/qisis/objs/CubeDnView/CubeDnView.cpp b/isis/src/qisis/objs/CubeDnView/CubeDnView.cpp index e662a195a5f82eb90801885434c38b9e64241b12..c667a250d06a8ddde30787301736a084aec8e835 100644 --- a/isis/src/qisis/objs/CubeDnView/CubeDnView.cpp +++ b/isis/src/qisis/objs/CubeDnView/CubeDnView.cpp @@ -25,15 +25,18 @@ #include <QAction> #include <QDebug> #include <QHBoxLayout> +#include <QKeySequence> #include <QMap> #include <QMdiArea> #include <QMdiSubWindow> #include <QMenu> +#include <QMenuBar> #include <QModelIndex> #include <QSize> #include <QSizePolicy> #include <QStatusBar> #include <QToolBar> +#include <QToolButton> #include <QVBoxLayout> #include <QWidgetAction> #include <QXmlStreamWriter> @@ -49,7 +52,6 @@ #include "FileName.h" #include "FileTool.h" #include "FindTool.h" -#include "HelpTool.h" #include "HistogramTool.h" #include "Image.h" #include "ImageList.h" @@ -76,12 +78,15 @@ #include "TrackTool.h" #include "ToolList.h" #include "ToolPad.h" + #include "ViewportMdiSubWindow.h" #include "Workspace.h" #include "WindowTool.h" #include "XmlStackedHandlerReader.h" #include "ZoomTool.h" +#include "ProjectItemViewMenu.h" + namespace Isis { /** * Constructs the view, initializing the tools. @@ -102,59 +107,49 @@ namespace Isis { m_workspace = new Workspace(false, this); m_workspace->mdiArea()->setActivationOrder(QMdiArea::StackingOrder); + // Since this is a QMainWindow, set the workspace as the central widget. + setCentralWidget(m_workspace); + + createActions(directory); + connect(m_workspace, SIGNAL( cubeViewportActivated(MdiCubeViewport *) ), this, SLOT( onCubeViewportActivated(MdiCubeViewport *) ) ); connect(m_workspace, SIGNAL( cubeViewportAdded(MdiCubeViewport *) ), this, SLOT( onCubeViewportAdded(MdiCubeViewport *) ) ); - Project *activeProject = directory->project(); - // These connect signals listen to the active project, and if a control network - // or list of control networks is added, then the enableControlNetTool() function is called. - connect(activeProject, SIGNAL(controlListAdded(ControlList *)), this, SLOT(enableControlNetTool())); - connect(activeProject, SIGNAL(controlAdded(Control *)), this, SLOT(enableControlNetTool())); - - - QVBoxLayout *layout = new QVBoxLayout; - setLayout(layout); - - //m_toolBar = new QWidget(this); + QSizePolicy policy = sizePolicy(); + policy.setHorizontalPolicy(QSizePolicy::Expanding); + policy.setVerticalPolicy(QSizePolicy::Expanding); + setSizePolicy(policy); + } - //QHBoxLayout *toolBarLayout = new QHBoxLayout; + void CubeDnView::createActions(Directory *directory) { - m_permToolBar = new QToolBar("Standard Tools", 0); + m_permToolBar = new QToolBar("Standard Tools", this); m_permToolBar->setObjectName("permToolBar"); m_permToolBar->setIconSize(QSize(22, 22)); - //toolBarLayout->addWidget(m_permToolBar); + addToolBar(m_permToolBar); - m_activeToolBar = new QToolBar("Active Tool", 0); + m_activeToolBar = new QToolBar("Active Tool", this); m_activeToolBar->setObjectName("activeToolBar"); m_activeToolBar->setIconSize(QSize(22, 22)); - //toolBarLayout->addWidget(m_activeToolBar); + addToolBar(m_activeToolBar); - m_toolPad = new ToolPad("Tool Pad", 0); + m_toolPad = new ToolPad("Tool Pad", this); m_toolPad->setObjectName("toolPad"); - //toolBarLayout->addWidget(m_toolPad); - - //m_toolBar->setLayout(toolBarLayout); - - //layout->addWidget(m_toolBar); - layout->addWidget(m_workspace); + addToolBar(Qt::RightToolBarArea, m_toolPad); // Create tools ToolList *tools = new ToolList; - Tool *defaultActiveTool = NULL; - tools->append(new RubberBandTool(this)); -// QnetTool *qnetTool = new QnetTool(m_workspace); - //tools->append(new FileTool(this)); - //tools->append(new QnetFileTool(qnetTool, this)); - tools->append(NULL); + + // 2018-07-02 Kaitlyn Lee - Commented this out; not sure why it was here + //tools->append(NULL); ControlNetTool *controlNetTool = new ControlNetTool(directory, this); - defaultActiveTool = controlNetTool; - tools->append(defaultActiveTool); + tools->append(controlNetTool); if (directory->project()->activeControl()) { controlNetTool->setControlNet(directory->project()->activeControl()->controlNet()); @@ -179,7 +174,8 @@ namespace Isis { connect(this, SIGNAL(redrawMeasures()), controlNetTool, SLOT(paintAllViewports())); tools->append(new BandTool(this)); - tools->append(new ZoomTool(this)); + ZoomTool *zoomTool = new ZoomTool(this); + tools->append(zoomTool); tools->append(new PanTool(this)); tools->append(new StretchTool(this)); tools->append(new FindTool(this)); @@ -197,20 +193,22 @@ namespace Isis { tools->append(new HistogramTool(this)); tools->append(new StatisticsTool(this)); tools->append(new StereoTool(this)); - tools->append(new HelpTool(this)); - - QStatusBar *statusBar = new QStatusBar(this); - layout->addWidget(statusBar); - tools->append(new TrackTool(statusBar)); + tools->append(new TrackTool(statusBar())); m_separatorAction = new QAction(this); m_separatorAction->setSeparator(true); - m_fileMenu = new QMenu; - m_viewMenu = new QMenu; - m_optionsMenu = new QMenu; - m_windowMenu = new QMenu; - m_helpMenu = new QMenu; + m_viewMenu = new ProjectItemViewMenu("&View"); + connect(m_viewMenu, SIGNAL(menuClosed()), this, SLOT(disableActions())); + menuBar()->addMenu(m_viewMenu); + + m_optionsMenu = new ProjectItemViewMenu("&Options"); + connect(m_optionsMenu, SIGNAL(menuClosed()), this, SLOT(disableActions())); + menuBar()->addMenu(m_optionsMenu); + + m_windowMenu = new ProjectItemViewMenu("&Window"); + connect(m_windowMenu, SIGNAL(menuClosed()), this, SLOT(disableActions())); + menuBar()->addMenu(m_windowMenu); for (int i = 0; i < tools->count(); i++) { Tool *tool = (*tools)[i]; @@ -224,10 +222,7 @@ namespace Isis { if (!tool->menuName().isEmpty()) { QString menuName = tool->menuName(); - if (menuName == "&File") { - tool->addTo(m_fileMenu); - } - else if (menuName == "&View") { + if (menuName == "&View") { tool->addTo(m_viewMenu); } else if (menuName == "&Options") { @@ -236,9 +231,6 @@ namespace Isis { else if (menuName == "&Window") { tool->addTo(m_windowMenu); } - else if (menuName == "&Help") { - tool->addTo(m_helpMenu); - } } } else { @@ -246,37 +238,107 @@ namespace Isis { } } - m_permToolBarActions.append( m_permToolBar->actions() ); + // Store the actions and widgets for easy enable/disable. + foreach (QAction *action, findChildren<QAction *>()) { + // Remove the edit tool's save button shortcut because the ipce main window + // already has one and this causes an ambiquous shortcut error. + if (action->toolTip() == "Save") { + action->setShortcut(QKeySequence()); + } + // The active toolbar's actions are inside of a container that is a QWidgetAction. + // We want to skip adding this because we want to disable the active toolbar's + // actions separately to skip the combo boxes. + if (QString(action->metaObject()->className()) == "QWidgetAction") { + continue; + } + addAction(action); + } - m_activeToolBarAction = new QWidgetAction(this); - m_activeToolBarAction->setDefaultWidget(m_activeToolBar); + // There was a problem with disabling/enabling the combo boxes. The only way to + // get this to work was to skip disabling the combo boxes. We also skip QWidgets + // because the combo boxes are contained inside of a QWidget. + foreach (QWidget *child, m_activeToolBar->findChildren<QWidget *>()) { + if (QString(child->metaObject()->className()).contains("ComboBox") || + QString(child->metaObject()->className()).contains("Widget")) { + continue; + } + m_childWidgets.append(child); + } - m_toolPadActions.append( m_toolPad->actions() ); + // On default, actions are disabled until the cursor enters the view. + disableActions(); - QSizePolicy policy = sizePolicy(); - policy.setHorizontalPolicy(QSizePolicy::Expanding); - policy.setVerticalPolicy(QSizePolicy::Expanding); - setSizePolicy(policy); + zoomTool->activate(true); + } + + + /** + * Disables actions when the cursor leaves the view. Overriden method + * If a project item view menu or toolpad action menu is visible, i.e. clicked on, + * this causes a leave event. We want the actions to still be enabled when a + * menu is visible. + * + * @param event The leave event + */ + void CubeDnView::leaveEvent(QEvent *event) { + if (m_optionsMenu->isVisible() || m_viewMenu->isVisible() || m_windowMenu->isVisible()) { + return; + } + // Find the toolpad actions (buttons) with menus and check if they are visible + foreach (QToolButton *button, findChildren<QToolButton *>()) { + if (button->menu() && button->menu()->isVisible()) { + return; + } + } + disableActions(); + } + + + /** + * Disables toolbars and toolpad actions/widgets. Overriden method. + */ + void CubeDnView::disableActions() { + foreach (QAction *action, actions()) { + action->setDisabled(true); + } + foreach (QWidget *widget, m_childWidgets) { + widget->setDisabled(true); + } } /** - * @description enableControlNetTool: This is a slot function which - * is called when the active project emits a signal to the CubeDnView - * object after a control network (or a list of control networks) - * has been added. It enables the control network editor tool if it - * has been disabled. + * Enables toolbars and toolpad actions/widgets. Overriden method. */ - void CubeDnView::enableControlNetTool() { + void CubeDnView::enableActions() { + foreach (QAction *action, actions()) { + action->setEnabled(true); + } + foreach (QWidget *widget, m_childWidgets) { + widget->setEnabled(true); + } + } - foreach (QAction * action, m_toolPadActions) { + + /** + * A slot function that is called when directory emits a signal that an active + * control network is set. It enables the control network editor tool in the + * toolpad and loads the network. + * + * @param value The boolean that holds if a control network has been set. + */ + void CubeDnView::enableControlNetTool(bool value) { + foreach (QAction *action, m_toolPad->actions()) { if (action->objectName() == "ControlNetTool") { - action->setDisabled(false); + action->setEnabled(value); + if (value) { + ControlNetTool *cnetTool = static_cast<ControlNetTool *>(action->parent()); + cnetTool->loadNetwork(); + } } } } - /** * Destructor */ @@ -284,10 +346,17 @@ namespace Isis { delete m_permToolBar; delete m_activeToolBar; delete m_toolPad; + delete m_viewMenu; + delete m_optionsMenu; + delete m_windowMenu; + m_permToolBar = 0; m_activeToolBar = 0; m_toolPad = 0; + m_viewMenu = 0; + m_optionsMenu = 0; + m_windowMenu = 0; } @@ -305,7 +374,6 @@ namespace Isis { AbstractProjectItemView::addItem(item); } - /** * Returns the suggested size * @@ -327,102 +395,6 @@ namespace Isis { return item->isShape(); } - - /** - * Returns a list of actions appropriate for a file menu. - * - * @return @b QList<QAction*> The actions - */ - QList<QAction *> CubeDnView::fileMenuActions() { - return m_fileMenu->actions(); - } - - - /** - * Returns a list of actions appropriate for a project menu. - * - * @return @b QList<QAction*> The actions - */ - QList<QAction *> CubeDnView::projectMenuActions() { - return QList<QAction *>(); - } - - /** - * Returns a list of actions appropriate for an edit menu. - * - * @return @b QList<QAction*> The actions - */ - QList<QAction *> CubeDnView::editMenuActions() { - return QList<QAction *>(); - } - - - /** - * Returns a list of actions appropriate for a view menu. - * - * @return @b QList<QAction*> The actions - */ - QList<QAction *> CubeDnView::viewMenuActions() { - QList<QAction *> result; - result.append( m_viewMenu->actions() ); - result.append(m_separatorAction); - result.append( m_windowMenu->actions() ); - return result; - } - - - /** - * Returns a list of actions appropriate for a settings menu. - * - * @return @b QList<QAction*> The actions - */ - QList<QAction *> CubeDnView::settingsMenuActions() { - return m_optionsMenu->actions(); - } - - - /** - * Returns a list of actions appropriate for a help menu. - * - * @return @b QList<QAction*> The actions - */ - QList<QAction *> CubeDnView::helpMenuActions() { - return m_helpMenu->actions(); - } - - - /** - * Returns a list of actions for the permanent tool bar. - * - * @return @b QList<QAction*> The actions - */ - QList<QAction *> CubeDnView::permToolBarActions() { - return m_permToolBar->actions(); - } - - - /** - * Returns a list of actions for the active tool bar. - * - * @return @b QList<QAction*> The actions - */ - QList<QAction *> CubeDnView::activeToolBarActions() { - QList<QAction *> actions; - actions.append(m_activeToolBarAction); - return actions; - } - - - /** - * Returns a list of actions for the tool pad. - * - * @return @b QList<QAction*> The actions - */ - QList<QAction *> CubeDnView::toolPadActions() { - return m_toolPad->actions(); - } - - /** * Slot to connect to the currentChanged() signal from a selection * model. If the new current item is an image the corresponding diff --git a/isis/src/qisis/objs/CubeDnView/CubeDnView.h b/isis/src/qisis/objs/CubeDnView/CubeDnView.h index 4ffe267a2a47013654446c9c2e366dbeb0c425dd..c185f4c19774f111b437ceaae1f703e184ce319d 100644 --- a/isis/src/qisis/objs/CubeDnView/CubeDnView.h +++ b/isis/src/qisis/objs/CubeDnView/CubeDnView.h @@ -36,6 +36,7 @@ class QMenu; class QModelIndex; class QToolBar; class QXmlStreamWriter; +class QWidget; namespace Isis { @@ -49,6 +50,7 @@ namespace Isis { class ToolPad; class Workspace; class XmlStackedHandlerReader; + class ProjectItemViewMenu; /** * View that displays cubes in a QView-like way. @@ -79,7 +81,27 @@ namespace Isis { * ipce tool to redraw control measures on cube viewports. Fixes #5007, * #5008. * @history 2017-08-03 Cole Neubauer - Changed all references from IpceTool to ControlNetTool - * Fixes #5090 + * Fixes #5090. + * @history 2018-05-30 Tracie Sucharski - Refactored for new docked interface. Views are now + * responsible for creating their menus and toolbars. + * AbstractProjectItemView now inherits from QMainWindow, so the + * Workspace of this view is the centralWidget. This needs further work + * to cleanup and fit in with the new docked view interface.git + * @history 2018-06-12 Kaitlyn Lee - Removed help menu and the "What's This?" action because the + * ipce help menu has this action. + * @history 2018-06-13 Kaitlyn Lee - Since views now inherit from QMainWindow, each individual + * view has its own toolbar, so having getters that return toolbar + * actions to fill the toolbar of the IpceMainWindow are unnecessary. + * Removed methods that returned menu and toolbar actions. + * Removed connections that connected the project and CubeDnView and called + * enableControlNetTool() because Directory now does this. + * @history 2018-06-25 Kaitlyn Lee - When multiple views are open, there is a possibility of getting + * ambiguous shortcut errors. To counter this, we enable/disable actions. + * Overrode leaveEvent() to handle open menus causing a leave event. Overrode + * enable/disableActions() because we need to disable the active toolbar's widgets. + * On default, a view's actions are disabled. To enable the actions, move the + * cursor over the view. When a user moves the cursor outside of the view, the + * actions are disabled. */ class CubeDnView : public AbstractProjectItemView { @@ -89,17 +111,6 @@ namespace Isis { CubeDnView(Directory *directory, QWidget *parent=0); ~CubeDnView(); - virtual QList<QAction *> fileMenuActions(); - virtual QList<QAction *> projectMenuActions(); - virtual QList<QAction *> editMenuActions(); - virtual QList<QAction *> viewMenuActions(); - virtual QList<QAction *> settingsMenuActions(); - virtual QList<QAction *> helpMenuActions(); - - virtual QList<QAction *> permToolBarActions(); - virtual QList<QAction *> activeToolBarActions(); - virtual QList<QAction *> toolPadActions(); - QSize sizeHint() const; bool viewportContainsShape(MdiCubeViewport *viewport); @@ -107,8 +118,6 @@ namespace Isis { void load(XmlStackedHandlerReader *xmlReader, Project *project); void save(QXmlStreamWriter &stream, Project *project, FileName newProjectRoot) const; - - signals: void modifyControlPoint(ControlPoint *controlPoint, QString serialNumber); void deleteControlPoint(ControlPoint *controlPoint); @@ -120,18 +129,23 @@ namespace Isis { public slots: void addItem(ProjectItem *item); - void enableControlNetTool(); + void enableControlNetTool(bool value); private slots: + void createActions(Directory *directory); + void onCurrentChanged(const QModelIndex ¤t); void onCubeViewportActivated(MdiCubeViewport *); void onItemAdded(ProjectItem *item); void onCubeViewportAdded(MdiCubeViewport *viewport); void onCubeViewportDeleted(QObject *obj); + void disableActions(); private: Cube *workspaceActiveCube(); void setWorkspaceActiveCube(Image *image); + void leaveEvent(QEvent *event); + void enableActions(); private: /** @@ -161,21 +175,16 @@ namespace Isis { QMap<Cube *, ProjectItem *> m_cubeItemMap; //!< Maps cubes to their items Workspace *m_workspace; //!< The workspace - QMenu *m_fileMenu; //!< File menu for storing actions - QMenu *m_viewMenu; //!< View menu for storing actions - QMenu *m_optionsMenu; //!< Options menu for storing actions - QMenu *m_windowMenu; //!< Window menu for storing actions - QMenu *m_helpMenu; //!< Help menu for storing actions + ProjectItemViewMenu *m_viewMenu; //!< View menu for storing actions + ProjectItemViewMenu *m_optionsMenu; //!< Options menu for storing actions + ProjectItemViewMenu *m_windowMenu; //!< Window menu for storing actions QAction *m_separatorAction; //!< A separator action that is reused QToolBar *m_permToolBar; //!< A tool bar for storing actions QToolBar *m_activeToolBar; //!< A tool bar for storing actions ToolPad *m_toolPad; //!< A tool bar for storing actions - - QList<QAction *> m_permToolBarActions; //!< The permanent tool bar actions - QWidgetAction *m_activeToolBarAction; //!< Widget of the active tool - QList<QAction *> m_toolPadActions; //!< The tool pad actions + QList<QWidget *> m_childWidgets; //!< Child widgets of the active toolbar }; } diff --git a/isis/src/qisis/objs/Directory/ControlHealthMonitorWorkOrder.cpp b/isis/src/qisis/objs/Directory/ControlHealthMonitorWorkOrder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..18f384a13b07b3953eab1539d020796611404325 --- /dev/null +++ b/isis/src/qisis/objs/Directory/ControlHealthMonitorWorkOrder.cpp @@ -0,0 +1,128 @@ +/** + * @file + * + * Unless noted otherwise, the portions of Isis written by the USGS are + * public domain. See individual third-party library and package descriptions + * for intellectual property information, user agreements, and related + * information. + * + * Although Isis has been used by the USGS, no warranty, expressed or + * implied, is made by the USGS as to the accuracy and functioning of such + * software and related material nor shall the fact of distribution + * constitute any such warranty, and no responsibility is assumed by the + * USGS in connection therewith. + * + * For additional information, launch + * $ISISROOT/doc//documents/Disclaimers/Disclaimers.html + * in a browser or see the Privacy & Disclaimers page on the Isis website, + * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on + * http://www.usgs.gov/privacy.html. + */ +#include "ControlHealthMonitorWorkOrder.h" + +#include <QMessageBox> +#include <QtDebug> + +#include "Control.h" +#include "Directory.h" +#include "IException.h" +#include "Project.h" +#include "ProjectItem.h" +#include "ProjectItemModel.h" + +namespace Isis { + +/** + * @brief Creates a WorkOrder that will display the Control Net Health Monitor interface. + * @param project The Project that this work order should be interacting with. + */ + ControlHealthMonitorWorkOrder::ControlHealthMonitorWorkOrder(Project *project) : + WorkOrder(project) { + + // This workorder is not undoable + m_isUndoable = false; + + QAction::setText(tr("View Control Net Health Monitor") ); + QUndoCommand::setText(tr("View Control Net Health Monitor")); + } + + + /** + * @brief Copies the 'other' WorkOrder instance into this new instance. + * @param other The WorkOrder being copied. + */ + ControlHealthMonitorWorkOrder::ControlHealthMonitorWorkOrder(const ControlHealthMonitorWorkOrder &other) : + WorkOrder(other) { + } + + + /** + * @brief The Destructor. + */ + ControlHealthMonitorWorkOrder::~ControlHealthMonitorWorkOrder() { + } + + + /** + * @brief Returns a copy of this ControlHealthMonitorWorkOrder instance. + * @return @b (ControlHealthMonitorWorkOrder *) A pointer to a copy of this WorkOrder. + */ + ControlHealthMonitorWorkOrder *ControlHealthMonitorWorkOrder::clone() const { + return new ControlHealthMonitorWorkOrder(*this); + } + + + /** + * @brief Determines if we can execute the health monitor. + * We can execute if there's an active control. + * + * @param controls (ControlList *) The ControlList chosen from the project tree. + * @return @b bool True if we can set as active, False otherwise. + */ + bool ControlHealthMonitorWorkOrder::isExecutable(ControlList *controls) { + return !!controls; + } + + /** + * @brief Make sure an active ImageList has been chosen. + * + * @return @b bool True if project has an active Control Network, False otherwise. + */ + bool ControlHealthMonitorWorkOrder::setupExecution() { + + bool success = WorkOrder::setupExecution(); + if (success) { + if (!isExecutable(controlList())) { + + QMessageBox::critical(NULL, tr("Unable to load Control Net Health Monitor."), + tr("You must first set an active control in order to view the health monitor.")); + success = false; + } + // So far, so good, set the command text + else { + QUndoCommand::setText(tr("Set Active Control Network to [%1]").arg( + controlList()->at(0)->displayProperties()->displayName())); + } + } + + return success; + } + + + /** + * @brief Set the active control net for the project. This allows any views to operate on + * the same control net. The active image list must be set before the active + * control net is chosen. If not, a critical message dialog is displayed and we + * return false. + * + */ + void ControlHealthMonitorWorkOrder::execute() { + try { + project()->directory()->addControlHealthMonitorView(); + } + catch (IException e) { + m_status = WorkOrderFinished; + QMessageBox::critical(NULL, tr("Error"), tr(e.what())); + } + } +} diff --git a/isis/src/qisis/objs/Directory/ControlHealthMonitorWorkOrder.h b/isis/src/qisis/objs/Directory/ControlHealthMonitorWorkOrder.h new file mode 100644 index 0000000000000000000000000000000000000000..92cc63b4f852bb18311ac61fcaade592e94c8b4a --- /dev/null +++ b/isis/src/qisis/objs/Directory/ControlHealthMonitorWorkOrder.h @@ -0,0 +1,57 @@ +#ifndef ControlHealthMonitorWorkOrder_H +#define ControlHealthMonitorWorkOrder_H +/** + * @file + * + * Unless noted otherwise, the portions of Isis written by the USGS are + * public domain. See individual third-party library and package descriptions + * for intellectual property information, user agreements, and related + * information. + * + * Although Isis has been used by the USGS, no warranty, expressed or + * implied, is made by the USGS as to the accuracy and functioning of such + * software and related material nor shall the fact of distribution + * constitute any such warranty, and no responsibility is assumed by the + * USGS in connection therewith. + * + * For additional information, launch + * $ISISROOT/doc//documents/Disclaimers/Disclaimers.html + * in a browser or see the Privacy & Disclaimers page on the Isis website, + * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on + * http://www.usgs.gov/privacy.html. + */ +#include "WorkOrder.h" + +namespace Isis { + class Control; + + /** + * @brief This is a child of class WorkOrder which is used for anything that performs + * an action in a Project. This work order allows the user to view the ControlHealthMonitor + * for the project's active Control Network. + * + * @author 2016-06-22 Adam Goins + * + * @internal + * @history 2018-06-07 Adam Goins - Initial Version. + */ + + class ControlHealthMonitorWorkOrder : public WorkOrder { + Q_OBJECT + public: + ControlHealthMonitorWorkOrder(Project *project); + ControlHealthMonitorWorkOrder(const ControlHealthMonitorWorkOrder &other); + ~ControlHealthMonitorWorkOrder(); + + virtual ControlHealthMonitorWorkOrder *clone() const; + + virtual bool isExecutable(ControlList *controls); + + bool setupExecution(); + void execute(); + + private: + ControlHealthMonitorWorkOrder &operator=(const ControlHealthMonitorWorkOrder &rhs); + }; +} +#endif diff --git a/isis/src/qisis/objs/Directory/Directory.cpp b/isis/src/qisis/objs/Directory/Directory.cpp index ea9f9194872e92d948262d1d9f63bd5e047cc047..18466b7ac0bb9beec05d84aaad460e980c12f238 100644 --- a/isis/src/qisis/objs/Directory/Directory.cpp +++ b/isis/src/qisis/objs/Directory/Directory.cpp @@ -27,6 +27,7 @@ #include <QApplication> #include <QDockWidget> #include <QGridLayout> +#include <QMainWindow> #include <QMenu> #include <QMenuBar> #include <QMessageBox> @@ -47,6 +48,8 @@ #include "CloseProjectWorkOrder.h" #include "CnetEditorView.h" #include "CnetEditorViewWorkOrder.h" +#include "ControlHealthMonitorView.h" +#include "ControlHealthMonitorWorkOrder.h" #include "CnetEditorWidget.h" #include "Control.h" #include "ControlDisplayProperties.h" @@ -72,6 +75,7 @@ #include "ImportImagesWorkOrder.h" #include "ImportShapesWorkOrder.h" #include "ImportTemplateWorkOrder.h" +#include "JigsawRunWidget.h" #include "JigsawWorkOrder.h" #include "MatrixSceneWidget.h" #include "MatrixViewWorkOrder.h" @@ -158,6 +162,7 @@ namespace Isis { createWorkOrder<TargetGetInfoWorkOrder>(); createWorkOrder<BundleObservationViewWorkOrder>(); createWorkOrder<TemplateEditViewWorkOrder>(); + createWorkOrder<ControlHealthMonitorWorkOrder>(); // Main menu actions m_exportControlNetWorkOrder = createWorkOrder<ExportControlNetWorkOrder>(); @@ -287,6 +292,8 @@ namespace Isis { * to allow for a new project to be opened in IPCE. */ void Directory::clean() { + emit directoryCleaned(); + m_historyTreeWidget->clear(); m_warningTreeWidget->clear(); m_bundleObservationViews.clear(); @@ -299,9 +306,9 @@ namespace Isis { m_sensorInfoWidgets.clear(); m_targetInfoWidgets.clear(); m_templateEditorWidgets.clear(); + m_jigsawRunWidget.clear(); m_projectItemModel->clean(); - emit directoryCleaned(); } @@ -313,7 +320,7 @@ namespace Isis { * @history Adam Goins 2017-11-27 - Updated this function to add the most recent * project to the recent projects menu. References #5216. */ - void Directory::updateRecentProjects(){ + void Directory::updateRecentProjects() { if (m_recentProjectsLoaded) { QMenu *recentProjectsMenu = new QMenu("&Recent Projects"); @@ -391,6 +398,7 @@ namespace Isis { } } + /** * @brief Initializes the actions that the Directory can provide to a main window. * @@ -533,12 +541,12 @@ namespace Isis { /** - * @description This slot was created specifically for the CnetEditorWidgets when user chooses a - * new active control and wants to discard any edits in the old active control. The only view - * which will not be updated with the new control are any CnetEditorViews showing the old active - * control. CnetEditorWidget classes do not have the ability to reload a control net, so the + * @description This slot was created specifically for the CnetEditorWidgets when user chooses a + * new active control and wants to discard any edits in the old active control. The only view + * which will not be updated with the new control are any CnetEditorViews showing the old active + * control. CnetEditorWidget classes do not have the ability to reload a control net, so the * CnetEditor view displaying the old control is removed, then recreated. - * + * */ void Directory::reloadActiveControlInCnetEditorView() { @@ -595,6 +603,9 @@ namespace Isis { connect( result, SIGNAL( destroyed(QObject *) ), this, SLOT( cleanupBundleObservationViews(QObject *) ) ); + + connect(result, SIGNAL(windowChangeEvent(bool)), + m_project, SLOT(setClean(bool))); m_bundleObservationViews.append(result); @@ -656,6 +667,9 @@ namespace Isis { // connect destroyed signal to cleanupCnetEditorViewWidgets slot connect(result, SIGNAL( destroyed(QObject *) ), this, SLOT( cleanupCnetEditorViewWidgets(QObject *) ) ); + + connect(result, SIGNAL(windowChangeEvent(bool)), + m_project, SLOT(setClean(bool))); // Connections for control point editing between views connect(result->cnetEditorWidget(), SIGNAL(editControlPoint(ControlPoint *, QString)), @@ -694,6 +708,9 @@ namespace Isis { m_cubeDnViewWidgets.append(result); connect( result, SIGNAL( destroyed(QObject *) ), this, SLOT( cleanupCubeDnViewWidgets(QObject *) ) ); + + connect(result, SIGNAL(windowChangeEvent(bool)), + m_project, SLOT(setClean(bool))); result->setWindowTitle("Cube DN View"); result->setWindowTitle( tr("Cube DN View %1").arg(m_cubeDnViewWidgets.count() ) ); @@ -716,25 +733,12 @@ namespace Isis { connect(this, SIGNAL(redrawMeasures()), result, SIGNAL(redrawMeasures())); connect(this, SIGNAL(cnetModified()), result, SIGNAL(redrawMeasures())); - // Note: This assumes the Control Net tool is the 1st in the toolpad. - QList<QAction *> toolbar = result->toolPadActions(); - QAction* cnetAction = toolbar[0]; - ControlNetTool *cnetTool = static_cast<ControlNetTool *>(cnetAction->parent()); - - connect (project(), SIGNAL(activeControlSet(bool)), - cnetAction, SLOT(setEnabled(bool))); connect (project(), SIGNAL(activeControlSet(bool)), - cnetTool, SLOT(loadNetwork())); - - // If an active control has not been set, make the control net tool inactive - if (!project()->activeControl()) { - cnetAction->setEnabled(false); - } + result, SLOT(enableControlNetTool(bool))); return result; } - /** * @brief Add the qmos view widget to the window. * @return @b (Footprint2DView*) A pointer to the Footprint2DView to display. @@ -749,7 +753,10 @@ namespace Isis { connect(result, SIGNAL(destroyed(QObject *)), this, SLOT(cleanupFootprint2DViewWidgets(QObject *))); - + + connect(result, SIGNAL(windowChangeEvent(bool)), + m_project, SLOT(setClean(bool))); + emit newWidgetAvailable(result); // Connections between mouse button events from footprint2DView and control point editing @@ -772,24 +779,38 @@ namespace Isis { // to be drawn with different color/shape. connect(this, SIGNAL(redrawMeasures()), result, SIGNAL(redrawMeasures())); - // Note: This assumes the Control Net tool is the 4th in the toolpad. - QList<QAction *> toolbar = result->toolPadActions(); - QAction* cnetAction = toolbar[3]; - MosaicControlNetTool *cnetTool = static_cast<MosaicControlNetTool *>(cnetAction->parent()); - - connect (project(), SIGNAL(activeControlSet(bool)), - cnetAction, SLOT(setEnabled(bool))); connect (project(), SIGNAL(activeControlSet(bool)), - cnetTool, SLOT(loadNetwork())); - - // Control Net tool will only be active if the project has an active Control. - if (!project()->activeControl()) { - cnetAction->setEnabled(false); - } + result, SLOT(enableControlNetTool(bool))); return result; } + ControlHealthMonitorView *Directory::controlHealthMonitorView() { + return m_controlHealthMonitorView; + } + + + ControlHealthMonitorView *Directory::addControlHealthMonitorView() { + + if (!controlHealthMonitorView()) { + + Control *activeControl = project()->activeControl(); + if (activeControl == NULL) { + QString message = "No active control network chosen. Choose active control network on " + "project tree.\n"; + QMessageBox::critical(qobject_cast<QWidget *>(parent()), "Error", message); + return NULL; + } + + ControlHealthMonitorView *result = new ControlHealthMonitorView(this); + result->setWindowTitle(tr("Control NetHealth Monitor")); + result->setObjectName(result->windowTitle()); + + m_controlHealthMonitorView = result; + emit newWidgetAvailable(result); + } + return controlHealthMonitorView(); + } ControlPointEditView *Directory::addControlPointEditView() { @@ -847,7 +868,10 @@ namespace Isis { connect(result->controlPointEditWidget(), SIGNAL(saveControlNet()), this, SLOT(makeBackupActiveControl())); connect (project(), SIGNAL(activeControlSet(bool)), - result->controlPointEditWidget(), SLOT(setControlFromActive())); + result->controlPointEditWidget(), SLOT(setControlFromActive())); + + connect(result, SIGNAL(windowChangeEvent(bool)), + m_project, SLOT(setClean(bool))); } return controlPointEditView(); @@ -880,6 +904,9 @@ namespace Isis { connect( result, SIGNAL( destroyed(QObject *) ), this, SLOT( cleanupMatrixViewWidgets(QObject *) ) ); + + connect(result, SIGNAL(windowChangeEvent(bool)), + m_project, SLOT(setClean(bool))); m_matrixViewWidgets.append(result); @@ -901,6 +928,9 @@ namespace Isis { connect( result, SIGNAL( destroyed(QObject *) ), this, SLOT( cleanupTargetInfoWidgets(QObject *) ) ); + + connect(result, SIGNAL(windowChangeEvent(bool)), + m_project, SLOT(setClean(bool))); m_targetInfoWidgets.append(result); @@ -922,6 +952,9 @@ namespace Isis { connect( result, SIGNAL( destroyed(QObject *) ), this, SLOT( cleanupTemplateEditorWidgets(QObject *) ) ); + + connect(result, SIGNAL(windowChangeEvent(bool)), + m_project, SLOT(setClean(bool))); m_templateEditorWidgets.append(result); @@ -933,6 +966,23 @@ namespace Isis { return result; } + JigsawRunWidget *Directory::addJigsawRunWidget() { + if (jigsawRunWidget()) { + return m_jigsawRunWidget; + } + JigsawRunWidget *result = new JigsawRunWidget(m_project); + + connect( result, SIGNAL( destroyed(QObject *) ), + this, SLOT( cleanupJigsawRunWidget(QObject *) ) ); + m_jigsawRunWidget = result; + + result->setAttribute(Qt::WA_DeleteOnClose); + result->show(); + + emit newWidgetAvailable(result); + return result; + } + /** * @brief Add sensor data view widget to the window. @@ -944,6 +994,9 @@ namespace Isis { connect( result, SIGNAL( destroyed(QObject *) ), this, SLOT( cleanupSensorInfoWidgets(QObject *) ) ); + connect(result, SIGNAL(windowChangeEvent(bool)), + m_project, SLOT(setClean(bool))); + m_sensorInfoWidgets.append(result); result->setWindowTitle( tr("%1").arg(camera->displayProperties()->displayName() ) ); @@ -965,6 +1018,9 @@ namespace Isis { connect( result, SIGNAL( destroyed(QObject *) ), this, SLOT( cleanupFileListWidgets(QObject *) ) ); + + connect(result, SIGNAL(windowChangeEvent(bool)), + m_project, SLOT(setClean(bool))); m_fileListWidgets.append(result); @@ -987,6 +1043,9 @@ namespace Isis { // node located on the ProjectTreeView. connect(m_projectItemModel, SIGNAL(projectNameEdited(QString)), this, SLOT(initiateRenameProjectWorkOrder(QString))); + + connect(result, SIGNAL(windowChangeEvent(bool)), + m_project, SLOT(setClean(bool))); return result; } @@ -1039,12 +1098,25 @@ namespace Isis { m_project->setClean(false); } + // /** + // * @brief Removes pointers to deleted Control Health Monitor objects. + // */ + // void Directory::cleanupControlHealthMonitorView(QObject *obj) { + // + // ControlHealthMonitorView *healthMonitorView = static_cast<ControlHealthMonitorView *>(obj); + // if (!healthMonitorView) { + // return; + // } + // + // m_project->setClean(false); + // } + /** * @brief Removes pointers to deleted CnetEditorWidget objects. */ void Directory::cleanupCnetEditorViewWidgets(QObject *obj) { - + CnetEditorView *cnetEditorView = static_cast<CnetEditorView *>(obj); if (!cnetEditorView) { return; @@ -1053,7 +1125,7 @@ namespace Isis { Control *control = m_controlMap.key(cnetEditorView); m_controlMap.remove(control, cnetEditorView); - if ( m_controlMap.count(control) == 0 && project()->activeControl() != control) { + if ( m_controlMap.count(control) == 0 && project()->activeControl() != control) { control->closeControlNet(); } @@ -1063,11 +1135,11 @@ namespace Isis { /** - * @description Return true if control is not currently being viewed in a CnetEditorWidget - * - * @param Control * Control used to search current CnetEditorWidgets - * - * @return @b (bool) Returns true if control is currently being viewed in CnetEditorWidget + * @description Return true if control is not currently being viewed in a CnetEditorWidget + * + * @param Control * Control used to search current CnetEditorWidgets + * + * @return @b (bool) Returns true if control is currently being viewed in CnetEditorWidget */ bool Directory::controlUsedInCnetEditorWidget(Control *control) { @@ -1195,6 +1267,15 @@ namespace Isis { } + void Directory::cleanupJigsawRunWidget(QObject *obj) { + JigsawRunWidget *jigsawRunWidget = static_cast<JigsawRunWidget *>(obj); + if (!jigsawRunWidget) { + return; + } + m_jigsawRunWidget = NULL; + } + + /** * @brief Adds a new Project object to the list of recent projects if it has not * already been added. @@ -1342,6 +1423,13 @@ namespace Isis { return m_controlPointEditViewWidget; } + + JigsawRunWidget *Directory::jigsawRunWidget() { + + return m_jigsawRunWidget; + } + + /* ChipViewportsWidget *Directory::controlPointChipViewports() { @@ -1791,22 +1879,6 @@ namespace Isis { } - /** - * Save the current active control. - * - */ - void Directory::saveActiveControl() { - - if (project()->activeControl()) { - project()->activeControl()->write(); - // add to HistoryTreeWidget - QString saveCnetHistoryEntry = project()->activeControl()->fileName() + - "has been saved."; - m_historyTreeWidget->addToHistory(saveCnetHistoryEntry); - } - } - - /** * Autosave for control net. The control net is auto saved to the same directory as the input * net. It is saved to controlNetFilename.net.bak. diff --git a/isis/src/qisis/objs/Directory/Directory.h b/isis/src/qisis/objs/Directory/Directory.h index 938ff71c6aa8ff46d41c6db254857392b2c8abe6..be73754fceed08c645a305980da55609b641311f 100644 --- a/isis/src/qisis/objs/Directory/Directory.h +++ b/isis/src/qisis/objs/Directory/Directory.h @@ -23,6 +23,7 @@ * http://www.usgs.gov/privacy.html. */ +#include <QMainWindow> #include <QMultiMap> #include <QObject> #include <QPointer> @@ -39,6 +40,7 @@ class QAction; class QDockWidget; +class QMainWindow; class QMenuBar; class QProgressBar; class QSplitter; @@ -54,11 +56,13 @@ namespace Isis { class Control; class ControlNet; class ControlPointEditView; + class ControlHealthMonitorView; class CubeDnView; class FileItem; class Footprint2DView; class HistoryTreeWidget; class ImageFileListWidget; + class JigsawRunWidget; class MatrixSceneWidget; class MosaicSceneWidget; class Project; @@ -200,10 +204,10 @@ namespace Isis { * @history 2017-11-13 Makayla Shepherd - Modifying the name of an ImageList, ShapeList or * BundeSolutionInfo on the ProjectTree now sets the project to * not clean. Fixes #5174. - * @history 2017-12-01 Summer Stapleton - Commented-out RemoveImagesWorkOrder being created. + * @history 2017-12-01 Summer Stapleton - Commented-out RemoveImagesWorkOrder being created. * Fixes #5224 * @history 2017-12-01 Adam Goins Modified updateRecentProjects() to update the recent projects - * menu it display a chronologically ordered list of recently loaded + * menu it display a chronologically ordered list of recently loaded * projects. Fixes #5216. * @history 2017-12-05 Christopher Combs - Added support for TemplateEditorWidget and * TemplateEditViewWorkOrder. Fixes #5168. @@ -236,6 +240,22 @@ namespace Isis { * @history 2018-05-14 Tracie Sucharski - Serialize Footprint2DView rather than * MosaicSceneWidget. This will allow all parts of Footprint2DView to be * saved/restored including the ImageFileListWidget. Fixes #5422. + * @history 2018-05-25 Christopher Combs - Made changes to reflect updates to JigsawRunWidget. + * Added addJigsawView method and m_jigsawRunWidget member variable. + * Fixes #5428. + * @history 2018-06-13 Kaitlyn Lee - The signal activeControlSet() in addCubeDnView() and + * addFootprint2DView() now connects to enableControlNetTool() in + * CubeDnView and Footprint2DView, instead of enabling the tool directly. + * Removed saveActiveControl() since users can save the control + * network with the project save button. + * @history 2018-06-18 Summer Stapleton - Added connection to each view on creation to + * catch a windowChangeEvent on moveEvent or resizeEvent of these views + * to allow for saving of the project at these times. Fixes #5114. + * @history 2018-06-07 Adam Goins - Added the addControlHealthMonitorView() method to directory. + * Fixes #5435. + * @history 2018-06-19 Adam Goins - Gave the ControlHealthMonitorView() a reference to the + * directory instance rather than the activeControl. Fixes #5435. + * */ class Directory : public QObject { Q_OBJECT @@ -250,9 +270,11 @@ namespace Isis { QStringList recentProjectsList(); BundleObservationView *addBundleObservationView(FileItemQsp fileItem); + ControlHealthMonitorView *addControlHealthMonitorView(); CnetEditorView *addCnetEditorView(Control *control); CubeDnView *addCubeDnView(); Footprint2DView *addFootprint2DView(); + JigsawRunWidget *addJigsawRunWidget(); MatrixSceneWidget *addMatrixView(); TargetInfoWidget *addTargetInfoView(TargetBodyQsp target); TemplateEditorWidget *addTemplateEditorView(Template *currentTemplate); @@ -288,7 +310,9 @@ namespace Isis { QList<TemplateEditorWidget *> templateEditorViews(); QList<ImageFileListWidget *> imageFileListViews(); QList<QProgressBar *> progressBars(); + ControlHealthMonitorView *controlHealthMonitorView(); ControlPointEditView *controlPointEditView(); + JigsawRunWidget *jigsawRunWidget(); // ChipViewportsWidget *controlPointChipViewports(); bool controlUsedInCnetEditorWidget(Control *control); @@ -354,6 +378,7 @@ namespace Isis { signals: void directoryCleaned(); void newWarning(); + void newDockAvailable(QMainWindow *newWidget); void newWidgetAvailable(QWidget *newWidget); void viewClosed(QWidget *widget); @@ -374,10 +399,10 @@ namespace Isis { void cleanupSensorInfoWidgets(QObject *); void cleanupTargetInfoWidgets(QObject *); void cleanupTemplateEditorWidgets(QObject *); + void cleanupJigsawRunWidget(QObject *); //void imagesAddedToProject(ImageList *images); void updateControlNetEditConnections(); - void saveActiveControl(); // TODO temporary slot until autosave is implemented void makeBackupActiveControl(); @@ -448,6 +473,8 @@ namespace Isis { QPointer<HistoryTreeWidget> m_historyTreeWidget; //!< Pointer to the HistoryTreeWidget. QPointer<Project> m_project; //!< Pointer to the Project. QPointer<WarningTreeWidget> m_warningTreeWidget; //!< Pointer to the WarningTreeWidget. + QPointer<JigsawRunWidget> m_jigsawRunWidget; //!< Pointer to the JigsawRunWidget. + //!< List of BundleObservationView QList< QPointer<BundleObservationView> > m_bundleObservationViews; @@ -455,6 +482,8 @@ namespace Isis { QList< QPointer<CubeDnView> > m_cubeDnViewWidgets; //!< List of CubeDnCiew obs QList< QPointer<ImageFileListWidget> > m_fileListWidgets; //!< List of ImageFileListWidgets QList< QPointer<Footprint2DView> > m_footprint2DViewWidgets; //!< List of Footprint2DView objs + + QPointer<ControlHealthMonitorView> m_controlHealthMonitorView; QPointer <ControlPointEditView> m_controlPointEditViewWidget; //QPointer <ChipViewportsWidget> m_chipViewports; QList< QPointer<MatrixSceneWidget> > m_matrixViewWidgets; //!< List of MatrixSceneWidgets diff --git a/isis/src/qisis/objs/Directory/ImportControlNetWorkOrder.cpp b/isis/src/qisis/objs/Directory/ImportControlNetWorkOrder.cpp index dca33080cd0492562491ae6e0df35450a08abf92..3bba87b87eeb7262dec79efc0059770e5af87103 100644 --- a/isis/src/qisis/objs/Directory/ImportControlNetWorkOrder.cpp +++ b/isis/src/qisis/objs/Directory/ImportControlNetWorkOrder.cpp @@ -51,6 +51,7 @@ namespace Isis { m_isSynchronous = false; m_list = NULL; m_watcher = NULL; + m_isUndoable = false; QAction::setText(tr("Import &Control Networks...")); @@ -206,32 +207,13 @@ namespace Isis { } m_status = WorkOrderFinished; m_readProgresses.clear(); - } - - /** - * @brief Deletes the control network - * - * This method deletes the control network from the project. This method is was - * renamed from undoSyncRedo() to undoExecution(). - */ - void ImportControlNetWorkOrder::undoExecution() { - if (m_list && project()->controls().size() > 0 && m_watcher->isFinished()) { - // Remove the controls from disk. - m_list->deleteFromDisk( project() ); - // Remove the controls from the model, which updates the tree view. - ProjectItem *currentItem = - project()->directory()->model()->findItemData( QVariant::fromValue(m_list) ); - project()->directory()->model()->removeItem(currentItem); - - foreach (Control *control, *m_list) { - delete control; - } - delete m_list; - } + // If one control network was imported, no active control has been set, and no + // other control networks exist in the project, then activeControl() will set + // the active control to the newly imported control network. + project()->activeControl(); } - /** * CreateControlsFunctor constructor * diff --git a/isis/src/qisis/objs/Directory/ImportControlNetWorkOrder.h b/isis/src/qisis/objs/Directory/ImportControlNetWorkOrder.h index 2ea3a37bd8b3549f4f8f3bfa918ac4ebf76723aa..eb4d75eb3a43bff85b1281f88c16abddd98ce249 100644 --- a/isis/src/qisis/objs/Directory/ImportControlNetWorkOrder.h +++ b/isis/src/qisis/objs/Directory/ImportControlNetWorkOrder.h @@ -65,6 +65,9 @@ namespace Isis { * Control is created Fixes #5026 * @histroy 2017-10-24 Adam Goins - Removed the undoStack() call that occurred when a * Failed cnet is imported. Fixes #5186 + * @histroy 2018-06-13 Kaitlyn Lee - Removed undoExecution() because we should not want to undo + * an import. In postExecution(), added the ability to set an active + * control network when one control network is imported. Fixes #5440 #5389. */ class ImportControlNetWorkOrder : public WorkOrder { Q_OBJECT @@ -80,7 +83,6 @@ namespace Isis { void execute(); protected: - void undoExecution(); void postExecution(); private slots: diff --git a/isis/src/qisis/objs/Directory/JigsawWorkOrder.cpp b/isis/src/qisis/objs/Directory/JigsawWorkOrder.cpp index f08ae306d9ede9efb0c013b05038bc9d8e8617de..f7b909adf4bfa89bd039a456fbddbbb05b1af265 100644 --- a/isis/src/qisis/objs/Directory/JigsawWorkOrder.cpp +++ b/isis/src/qisis/objs/Directory/JigsawWorkOrder.cpp @@ -33,7 +33,7 @@ #include "BundleSolutionInfo.h" #include "Control.h" #include "Directory.h" -#include "JigsawDialog.h" +#include "JigsawRunWidget.h" #include "JigsawSetupDialog.h" #include "Project.h" @@ -43,11 +43,11 @@ namespace Isis { * @brief Constructs a JigsawWorkOrder. * * This creates a work order to run bundle adjustments. Note that right now, - * the design implemented means that this work order finishes after a JigsawDialog + * the design implemented means that this work order finishes after a JigsawRunWidget * is shown. This work order is synchronous and not undoable. Note is is synchronous * in that it simply displays a dialog. The actual bundle adjust is threaded. * - * @see JigsawDialog + * @see JigsawRunWidget * * @param project The Project that we are going to Bundle Adjust * @@ -92,6 +92,20 @@ namespace Isis { } +/** + * This method is no longer necessary and will remain commented out until it needs to be implemented + * + * If WorkOrder:setupExecution() returns true, this creates a setup dialog. + * + * When the setup is successful (i.e. the user does not cancel the dialog), this work order + * will be read to execute. + * + * @return bool Returns True if setup dialog for the bundle adjustment is successful. + */ +// bool JigsawWorkOrder::setupExecution() { +// } + + /** * This check is used by Directory::supportedActions(DataType data). * @@ -99,55 +113,10 @@ namespace Isis { * is greater than 0. */ bool JigsawWorkOrder::isExecutable() { - return (project()->controls().size() > 0 && project()->images().size() > 0); - } - - - /** - * If WorkOrder:setupExecution() returns true, this creates a setup dialog. - * - * When the setup is successful (i.e. the user does not cancel the dialog), this work order - * will be read to execute. - * - * @return bool Returns True if setup dialog for the bundle adjustment is successful. - */ - bool JigsawWorkOrder::setupExecution() { - bool success = WorkOrder::setupExecution(); - - if (success) { - - QStringList internalData; - - // Create a blocking setup dialog initially and check to make sure we get valid info - JigsawSetupDialog setup(project()); - if (setup.exec() == QDialog::Accepted) { - m_bundleSettings = setup.bundleSettings(); - if (setup.selectedControl()) { - internalData.append(QStringList(setup.selectedControl()->id())); - } - // This else should not happen, the work order should be disabled if there are no controls. - else { - QString msg = "Cannot run a bundle adjustment without a selected control network."; - QMessageBox::critical(qobject_cast<QWidget *>(parent()), "Error", msg); - success = false; - } - // set output control network file name - if (!setup.outputControlName().isEmpty()) { - internalData.append(setup.outputControlName()); - } - else { - QString msg = "You must set an output control network filename."; - QMessageBox::critical(qobject_cast<QWidget *>(parent()), "Error", msg); - success = false; - } - } - else { - success = false; - } - setInternalData(internalData); - } - - return success; + // Is this code ever run? + return (project()->controls().size() > 0 && + project()->images().size() > 0 && + !project()->directory()->jigsawRunWidget()); } @@ -172,17 +141,10 @@ namespace Isis { * @see WorkOrder::execute() */ void JigsawWorkOrder::execute() { - - Project *proj = project(); - - // Get the selected control and bundle settings and give them to the JigsawDialog for now. - Control *selectedControl = proj->control(internalData().first()); - - QString outputControlFileName = internalData().at(1); - - JigsawDialog *runDialog = new JigsawDialog(project(), m_bundleSettings, selectedControl, - outputControlFileName); - runDialog->setAttribute(Qt::WA_DeleteOnClose); - runDialog->show(); + JigsawRunWidget *runWidget = project()->directory()->addJigsawRunWidget(); + if (!runWidget) { + QString msg = "Unable to open Jigsaw Run Widget"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } } } diff --git a/isis/src/qisis/objs/Directory/JigsawWorkOrder.h b/isis/src/qisis/objs/Directory/JigsawWorkOrder.h index 49f3d81f72ea6a554cda91310569c848638c07e0..84e8845b44fba2b91b0d8025499ba0f230cebbaf 100644 --- a/isis/src/qisis/objs/Directory/JigsawWorkOrder.h +++ b/isis/src/qisis/objs/Directory/JigsawWorkOrder.h @@ -47,7 +47,7 @@ namespace Isis { * active cnet and image list have been set. Fixes #4749. * @history 2017-04-25 Ian Humphrey - Modified tool tip text. Fixes #4819. * @history 2017-07-25 Cole Neubauer - Added project()->setClean call #4969 - * @history 2017-07-25 Cole Neubauer - Moved project()->setClean call to JigsawDialog because + * @history 2017-07-25 Cole Neubauer - Moved project()->setClean call to JigsawRunWidget because * the workorder does not actually execute the bundle adjustment #4960 * @history 2018-03-22 Ken Edmundson - Modified setupExecution method to append output control * network filename to internalData. Modified execute method to look for @@ -56,6 +56,8 @@ namespace Isis { * @history 2018-03-23 Ken Edmundson - In execute method, removed search for input control * network in BundleSolutionInfos. No longer needed as control is now * properly saved in projects m_idToControlMap. + * @history 2018-05-31 Christopher Combs - Updated to reflect change from JigsawDialog to + * JigsawRunWidget. Removed setupExecution() method. Fixes #5428. */ class JigsawWorkOrder : public WorkOrder { Q_OBJECT @@ -67,7 +69,6 @@ namespace Isis { virtual JigsawWorkOrder *clone() const; virtual bool isExecutable(); - virtual bool setupExecution(); virtual void execute(); protected: diff --git a/isis/src/qisis/objs/Directory/OpenProjectWorkOrder.cpp b/isis/src/qisis/objs/Directory/OpenProjectWorkOrder.cpp index 57998628800d44ccae175e8be6413d2d37a37165..15e3d15ffb2ca1da73cdde289ea140c598b908c5 100644 --- a/isis/src/qisis/objs/Directory/OpenProjectWorkOrder.cpp +++ b/isis/src/qisis/objs/Directory/OpenProjectWorkOrder.cpp @@ -152,20 +152,17 @@ namespace Isis { if (!m_projectPath.isEmpty()) { QUndoCommand::setText(tr("Open Project [%1]").arg(m_projectPath)); } - } else { - - m_projectPath =toolTip(); - - //We are dealing with a recent project - - } - + success = false; + } } else { - success = false; + m_projectPath = toolTip(); } - + } + else { + success = false; + } return success; } diff --git a/isis/src/qisis/objs/Directory/OpenProjectWorkOrder.h b/isis/src/qisis/objs/Directory/OpenProjectWorkOrder.h index e187552551f399008455e0ddb260accc46173506..4f3739a61f4e9966367e9ee64deafba8282462cb 100644 --- a/isis/src/qisis/objs/Directory/OpenProjectWorkOrder.h +++ b/isis/src/qisis/objs/Directory/OpenProjectWorkOrder.h @@ -50,6 +50,8 @@ namespace Isis { * @history 2017-11-09 Tyler Wilson - Made changes to isExecutable() to import functionality * needed in OpenRecentProjectWorkOrder into OpenProjectWorkOrder * since OpenRecentProjectWorker is being deleted. Fixes #5220. + * @history 2018-06-14 Makayla Shepherd - Added an else so that when someone cancels the dialog + * it will cancel properly. */ class OpenProjectWorkOrder : public WorkOrder { Q_OBJECT diff --git a/isis/src/qisis/objs/Footprint2DView/Footprint2DView.cpp b/isis/src/qisis/objs/Footprint2DView/Footprint2DView.cpp index 6fda9c72a21f20347adc7c66ece8b6205dfd6834..f0ebacae8bf9910fe5ef256fbda59190516eb50c 100644 --- a/isis/src/qisis/objs/Footprint2DView/Footprint2DView.cpp +++ b/isis/src/qisis/objs/Footprint2DView/Footprint2DView.cpp @@ -43,6 +43,7 @@ #include <QWidgetAction> #include <QXmlStreamWriter> +#include "ControlNetTool.h" #include "ControlPoint.h" #include "Cube.h" #include "Directory.h" @@ -50,6 +51,7 @@ #include "ImageFileListWidget.h" #include "MosaicGraphicsView.h" #include "MosaicSceneWidget.h" +#include "MosaicControlNetTool.h" #include "Project.h" #include "ProjectItem.h" #include "ProjectItemModel.h" @@ -61,7 +63,7 @@ namespace Isis { /** * Constructor. * - * @param parent Pointer to parent QWidget + * @param parent (QMainWindow *) Pointer to parent QMainWindow */ Footprint2DView::Footprint2DView(Directory *directory, QWidget *parent) : AbstractProjectItemView(parent) { @@ -92,18 +94,15 @@ namespace Isis { connect(m_sceneWidget, SIGNAL(createControlPoint(double, double)), this, SIGNAL(createControlPoint(double, double))); - - connect(m_sceneWidget, SIGNAL(mosCubeClosed(Image *)), + + connect(m_sceneWidget, SIGNAL(mosCubeClosed(Image *)), this, SLOT(onMosItemRemoved(Image *))); // Pass on redrawMeasure signal from Directory, so the control measures are redrawn on all // the footprints. connect(this, SIGNAL(redrawMeasures()), m_sceneWidget->getScene(), SLOT(update())); - QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom); - QHBoxLayout *viewlayout = new QHBoxLayout(); - - layout->addWidget(statusBar); + setStatusBar(statusBar); m_fileListWidget = new ImageFileListWidget(directory); @@ -119,51 +118,51 @@ namespace Isis { imageFileListdock->setWidget(m_fileListWidget); - m_window = new QMainWindow(); - m_window->addDockWidget(Qt::LeftDockWidgetArea, imageFileListdock, Qt::Vertical); - m_window->setCentralWidget(m_sceneWidget); - viewlayout->addWidget(m_window); - layout->addLayout(viewlayout); + addDockWidget(Qt::LeftDockWidgetArea, imageFileListdock, Qt::Vertical); + setCentralWidget(m_sceneWidget); - setLayout(layout); - - m_permToolBar = new QToolBar("Standard Tools", 0); + m_permToolBar = addToolBar("Standard Tools"); m_permToolBar->setObjectName("permToolBar"); m_permToolBar->setIconSize(QSize(22, 22)); - //toolBarLayout->addWidget(m_permToolBar); - m_activeToolBar = new QToolBar("Active Tool", 0); + m_activeToolBar = addToolBar("Active Tool"); m_activeToolBar->setObjectName("activeToolBar"); m_activeToolBar->setIconSize(QSize(22, 22)); - //toolBarLayout->addWidget(m_activeToolBar); m_toolPad = new ToolPad("Tool Pad", 0); m_toolPad->setObjectName("toolPad"); - //toolBarLayout->addWidget(m_toolPad); - + addToolBar(Qt::RightToolBarArea, m_toolPad); m_sceneWidget->addToPermanent(m_permToolBar); m_sceneWidget->addTo(m_activeToolBar); m_sceneWidget->addTo(m_toolPad); - m_activeToolBarAction = new QWidgetAction(this); - m_activeToolBarAction->setDefaultWidget(m_activeToolBar); + // Store the actions for easy enable/disable. + foreach (QAction *action, findChildren<QAction *>()) { + addAction(action); + } + // On default, actions are disabled until the cursor enters the view. + disableActions(); + + // MosaicSceneWidget's default is to have the Control Net Tool enabled. + // In ipce, we want it to be disabled if an active control is not set. + foreach (QAction *action, m_toolPad->actions()) { + if (action->toolTip() == "Control Net (c)") { + m_controlNetTool = action; + } + } + if (!directory->project()->activeControl()) { + m_controlNetTool->setEnabled(false); + } setAcceptDrops(true); - - QSizePolicy policy = sizePolicy(); - policy.setHorizontalPolicy(QSizePolicy::Expanding); - policy.setVerticalPolicy(QSizePolicy::Expanding); - setSizePolicy(policy); } - /** * Destructor */ Footprint2DView::~Footprint2DView() { delete m_fileListWidget; - delete m_window; delete m_permToolBar; delete m_activeToolBar; delete m_toolPad; @@ -249,11 +248,11 @@ namespace Isis { } } - + /** - * Slot at removes the mosaic item and corresponding image file list item when a cube is closed + * Slot at removes the mosaic item and corresponding image file list item when a cube is closed * using the Close Cube context menu. - * + * * @param image The image that was closed and needs to be removed */ void Footprint2DView::onMosItemRemoved(Image *image) { @@ -269,7 +268,7 @@ namespace Isis { } } } - + /** * Slot to connect to the itemRemoved signal from the model. If the item is an image it removes it @@ -326,34 +325,17 @@ namespace Isis { /** - * Returns a list of actions for the permanent tool bar. + * A slot function that is called when directory emits a siganl that an active + * control network is set. It enables the control network editor tool in the + * toolpad. + * We do not load the network here because the network does not open until + * the tool is beng used. This is done in MosaicControlNetTool::updateTool() and + * is connected in MosaicTool. * - * @return @b QList<QAction*> The actions + * @param value The boolean that holds if a control network has been set. */ - QList<QAction *> Footprint2DView::permToolBarActions() { - return m_permToolBar->actions(); - } - - - /** - * Returns a list of actions for the active tool bar. - * - * @return @b QList<QAction*> The actions - */ - QList<QAction *> Footprint2DView::activeToolBarActions() { - QList<QAction *> actions; - actions.append(m_activeToolBarAction); - return actions; - } - - - /** - * Returns a list of actions for the tool pad. - * - * @return @b QList<QAction*> The actions - */ - QList<QAction *> Footprint2DView::toolPadActions() { - return m_toolPad->actions(); + void Footprint2DView::enableControlNetTool(bool value) { + m_controlNetTool->setEnabled(value); } @@ -367,7 +349,7 @@ namespace Isis { /** - * @brief Save the footprint view widgets (ImageFileListWidget and MosaicSceneWidget to an XML + * @brief Save the footprint view widgets (ImageFileListWidget and MosaicSceneWidget to an XML * file. * @param stream The XML stream writer * @param newProjectRoot The FileName of the project this Directory is attached to. @@ -443,4 +425,3 @@ namespace Isis { return result; } } - diff --git a/isis/src/qisis/objs/Footprint2DView/Footprint2DView.h b/isis/src/qisis/objs/Footprint2DView/Footprint2DView.h index 821fe9ae7049e1ad641c86c1f64838b79e124ba4..3523c3a43bd25cc38c58fde68184dd8a7ef39496 100644 --- a/isis/src/qisis/objs/Footprint2DView/Footprint2DView.h +++ b/isis/src/qisis/objs/Footprint2DView/Footprint2DView.h @@ -72,6 +72,24 @@ namespace Isis { * @history 2018-05-14 Tracie Sucharski - Serialize Footprint2DView rather than * MosaicSceneWidget. This will allow all parts of Footprint2DView to be * saved/restored including the ImageFileListWidget. Fixes #5422. + * @history 2018-05-30 Summer Stapleton - updated the view to remove QMainWindow constructor, + * include a central widget and to remove layout capacity. This change + * was made to adjust to parent class now inheriting from QMainWindow + * instead of QWidget. References #5433. + * @history 2018-06-08 Tracie Sucharski - Remove deletion of m_window from destructor. This + * member variable no longer exists. + * @history 2018-06-13 Kaitlyn Lee - Since views now inherit from QMainWindow, each individual + * view has its own toolbar, so having getters that return toolbar + * actions to fill the toolbar of the IpceMainWindow are unnecessary. + * Removed methods that returned menu and toolbar actions. + * Made it so that on default and if there is no active control net, + * the Control Net Tool will be disabled. + * Added enableControlNetTool(bool) so when an active control net is set, + * the tool becomes enabled. + * @history 2018-06-25 Kaitlyn Lee - When multiple views are open, there is a possibility of getting + * ambiguous shortcut errors. To counter this, we enable/disable actions. + * On default, actions are disabled until a user moves the cursor over the view. + * When a user moves the cursor outside of the view, the actions are disabled. */ class Footprint2DView : public AbstractProjectItemView { @@ -82,9 +100,6 @@ namespace Isis { ~Footprint2DView(); MosaicSceneWidget *mosaicSceneWidget(); - virtual QList<QAction *> permToolBarActions(); - virtual QList<QAction *> activeToolBarActions(); - virtual QList<QAction *> toolPadActions(); QSize sizeHint() const; @@ -99,6 +114,9 @@ namespace Isis { void redrawMeasures(); void controlPointAdded(QString newPointId); + public slots: + void enableControlNetTool(bool value); + protected: bool eventFilter(QObject *watched, QEvent *event); @@ -140,7 +158,7 @@ namespace Isis { QToolBar *m_activeToolBar; //!< The active tool bar ToolPad *m_toolPad; //!< The tool pad - QWidgetAction *m_activeToolBarAction; //!< Stores the active tool bar + QAction *m_controlNetTool; //!< The Control Point Editor Tool }; } diff --git a/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.cpp b/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.cpp index eeb4b0cb8fce81c4daa0d2f5b61c95f33288c9dd..ff79f6581ec09ed923ee7c84a67874d90d69ec55 100644 --- a/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.cpp +++ b/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.cpp @@ -136,7 +136,6 @@ namespace Isis { newItem->setForeground(1, Qt::gray); this->insertTopLevelItem(0, newItem); -// invisibleRootItem()->addChild(newItem); connect(workOrder, SIGNAL(statusChanged(WorkOrder *)), this, SLOT(updateStatus(WorkOrder *))); @@ -151,8 +150,7 @@ namespace Isis { //include those that do not need it. if(workOrder->progressBar() ) { - setItemWidget(newItem, 1, new ProgressBar); -// this->setItemWidget(newItem, 1, workOrder->progressBar() ); + this->setItemWidget(newItem, 1, workOrder->progressBar() ); } scrollToItem(newItem); refit(); diff --git a/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.h b/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.h index b32eaf7c56cf73dd1599cbfd9aaa41cced41dd55..2d8d8f9f2972ceaac3475ce4cd7df65185a144c1 100644 --- a/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.h +++ b/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.h @@ -45,7 +45,7 @@ namespace Isis { * saving a control is turned into a WorkOrder. This was done for the * alpha release simply to notify the user that the control was saved. * However, this history entry is not saved/restored to a project. - * + * @history 2018-06-28 Makayla Shepherd - Restored the ProgressBar. Fixes #5228. */ class HistoryTreeWidget : public QTreeWidget { Q_OBJECT diff --git a/isis/src/qisis/objs/Image/Image.cpp b/isis/src/qisis/objs/Image/Image.cpp index 036c5097e02afcd69058364beebb42719b02ee78..245ba8b06917f1dda4b0308cf38a5915577f22e7 100644 --- a/isis/src/qisis/objs/Image/Image.cpp +++ b/isis/src/qisis/objs/Image/Image.cpp @@ -24,6 +24,7 @@ #include "ImageDisplayProperties.h" #include "ImagePolygon.h" #include "IString.h" +#include "ObservationNumber.h" #include "PolygonTools.h" #include "Project.h" #include "SerialNumber.h" @@ -311,12 +312,27 @@ namespace Isis { } + /** + * @brief Returns the observation number of the Cube + * @return QString A string representation of the observation number of the cube. + */ + QString Image::observationNumber() { + if (m_observationNumber.isEmpty()) { + m_observationNumber = ObservationNumber::Compose(*(cube())); + } + return m_observationNumber; + } + + /** * @brief Returns the serial number of the Cube * @return @b QString A string representation of the serial number of the cube. */ QString Image::serialNumber() { - return SerialNumber::Compose(*(cube())); + if (m_serialNumber.isEmpty()) { + m_serialNumber = SerialNumber::Compose(*(cube())); + } + return m_serialNumber; } diff --git a/isis/src/qisis/objs/Image/Image.h b/isis/src/qisis/objs/Image/Image.h index c79ca8d34241a1e40b9ac202df58a36f07401dc3..add975271e98f3265af875a1871c44f121965dd1 100644 --- a/isis/src/qisis/objs/Image/Image.h +++ b/isis/src/qisis/objs/Image/Image.h @@ -91,6 +91,14 @@ namespace Isis { * located outside of the import image directories such as the updated * Images from a bundle run. To improve efficiency, return from method * if the project root has not changed. Fixes #4849. + * @history 2018-06-30 Ian Humphrey - Added observationNumber() method so anything that grabs + * an Image ProjectItem can easily get both the serial number and + * observation number now. References #497. + * @history 2018-07-02 Ian Humphrey - Changed serialNumber() implementation to follow how + * observationNumber() is implemented. This ensures that any calls + * after the first call to these methods are O(1) and are not + * bottlenecekd by any file I/O that occurs in the Compose() + * methods. References #497. */ class Image : public QObject { @@ -110,6 +118,7 @@ namespace Isis { ImageDisplayProperties *displayProperties(); const ImageDisplayProperties *displayProperties() const; QString fileName() const; + QString observationNumber(); QString serialNumber(); geos::geom::MultiPolygon *footprint(); const geos::geom::MultiPolygon *footprint() const; @@ -206,6 +215,16 @@ namespace Isis { */ QString m_instrumentId; + /** + * The observation number for this image. + */ + QString m_observationNumber; + + /** + * The serial number for this image. + */ + QString m_serialNumber; + /** * Spacecraft name associated with this Image. */ diff --git a/isis/src/qisis/objs/JigsawDialog/JigsawDialog.ui b/isis/src/qisis/objs/JigsawDialog/JigsawDialog.ui deleted file mode 100644 index 8bc268bc758bf10dcf6b7e50748836f3f603bed0..0000000000000000000000000000000000000000 --- a/isis/src/qisis/objs/JigsawDialog/JigsawDialog.ui +++ /dev/null @@ -1,201 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>JigsawDialog</class> - <widget class="QDialog" name="JigsawDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>540</width> - <height>300</height> - </rect> - </property> - <property name="windowTitle"> - <string>Jigsaw</string> - </property> - <property name="windowIcon"> - <iconset> - <normaloff>icons/jigsaw.png</normaloff>icons/jigsaw.png</iconset> - </property> - <property name="modal"> - <bool>false</bool> - </property> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="geometry"> - <rect> - <x>170</x> - <y>260</y> - <width>341</width> - <height>32</height> - </rect> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - <widget class="QWidget" name="jigsawButtonsLayoutWidget"> - <property name="geometry"> - <rect> - <x>320</x> - <y>10</y> - <width>208</width> - <height>94</height> - </rect> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QPushButton" name="JigsawSetupButton"> - <property name="text"> - <string>&Setup</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QPushButton" name="JigsawRunButton"> - <property name="text"> - <string>&Run</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QCheckBox" name="useLastSettings"> - <property name="text"> - <string>Use Last Accepted Settings</string> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="gridLayoutWidget"> - <property name="geometry"> - <rect> - <x>10</x> - <y>10</y> - <width>301</width> - <height>241</height> - </rect> - </property> - <layout class="QGridLayout" name="statusUpdatesLayout"> - <item row="0" column="0"> - <widget class="QScrollArea" name="statusUpdateScrollArea"> - <property name="widgetResizable"> - <bool>true</bool> - </property> - <widget class="QLabel" name="statusUpdatesLabel"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>297</width> - <height>237</height> - </rect> - </property> - <property name="text"> - <string>Welcome to Jigsaw</string> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - </widget> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="iterationLayoutWidget"> - <property name="geometry"> - <rect> - <x>321</x> - <y>110</y> - <width>188</width> - <height>59</height> - </rect> - </property> - <layout class="QGridLayout" name="iterationSigma0Layout"> - <item row="0" column="0"> - <widget class="QLabel" name="iterationLabel"> - <property name="text"> - <string>Iteration</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLabel" name="sigma0Label"> - <property name="text"> - <string>sigma0</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLCDNumber" name="iterationLcdNumber"> - <property name="minimumSize"> - <size> - <width>90</width> - <height>35</height> - </size> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLCDNumber" name="sigma0LcdNumber"> - <property name="minimumSize"> - <size> - <width>90</width> - <height>35</height> - </size> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - </widget> - </item> - </layout> - </widget> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>JigsawDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>JigsawDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/isis/src/qisis/objs/JigsawDialog/JigsawDialog.cpp b/isis/src/qisis/objs/JigsawRunWidget/JigsawRunWidget.cpp similarity index 62% rename from isis/src/qisis/objs/JigsawDialog/JigsawDialog.cpp rename to isis/src/qisis/objs/JigsawRunWidget/JigsawRunWidget.cpp index 1494b1f4a75d3b2b3920fd09c506f5771a8226d0..2dfb18bc7a68e9791445c2b31d534b67d0928814 100644 --- a/isis/src/qisis/objs/JigsawDialog/JigsawDialog.cpp +++ b/isis/src/qisis/objs/JigsawRunWidget/JigsawRunWidget.cpp @@ -1,6 +1,7 @@ -#include "JigsawDialog.h" +#include "JigsawRunWidget.h" #include <QtConcurrent> +#include <QCloseEvent> #include <QDebug> #include <QDir> #include <QFuture> @@ -22,22 +23,22 @@ #include "iTime.h" #include "Process.h" #include "Project.h" -#include "ui_JigsawDialog.h" +#include "ui_JigsawRunWidget.h" namespace Isis { /** * @brief Constructor. * - * Creates a dialog for running a jigsaw (bundle adjustment) and changing the solve settings. + * Creates a widget for running a jigsaw (bundle adjustment) and changing the solve settings. * - * @param Project *project Pointer to the project this dialog belongs to. + * @param Project *project Pointer to the project this widget belongs to. * @param QWidget *parent Pointer to parent widget. */ - JigsawDialog::JigsawDialog(Project *project, QWidget *parent) : - QDialog(parent), m_ui(new Ui::JigsawDialog) { + JigsawRunWidget::JigsawRunWidget(Project *project, QWidget *parent) : m_ui(new Ui::JigsawRunWidget) { m_project = project; m_selectedControl = NULL; + m_bundleThread = NULL; init(); } @@ -45,24 +46,26 @@ namespace Isis { /** * @brief Constructor that takes bundle settings and a selected control. * - * Creates a dialog after the jigsaw solve settings have been set up and a control has been + * Creates a widget after the jigsaw solve settings have been set up and a control has been * selected. * - * @param Project *project Pointer to the project this dialog belongs to. - * @param BundleSettingsQsp bundleSettings Settings to give to this dialog to use for a jigsaw. + * @param Project *project Pointer to the project this widget belongs to. + * @param BundleSettingsQsp bundleSettings Settings to give to this widget to use for a jigsaw. * @param Control *selectedControl Pointer to the selected control to adjust. * @param QWidget *parent Pointer to the parent widget. */ - JigsawDialog::JigsawDialog(Project *project, + JigsawRunWidget::JigsawRunWidget(Project *project, BundleSettingsQsp bundleSettings, Control *selectedControl, QString outputControlFileName, - QWidget *parent) : QDialog(parent), m_ui(new Ui::JigsawDialog) { + QWidget *parent) : m_ui(new Ui::JigsawRunWidget) { + m_project = project; m_bundleSettings = bundleSettings; m_selectedControl = selectedControl; m_selectedControlName = FileName(selectedControl->fileName()).name(); m_outputControlName = outputControlFileName; + m_bundleThread = NULL; init(); } @@ -72,41 +75,15 @@ namespace Isis { * * Delegate method that helps the constructors. This is used to reduce repeated code. */ - void JigsawDialog::init() { + void JigsawRunWidget::init() { m_ui->setupUi(this); - // Note: The buttons are added to the UI setup from the JigsawDialog.ui file. + // Note: The buttons are added to the UI setup from the JigsawRunWidget.ui file. // These could have been added to the UI file itself (as XML). - // Three buttons: Accept, Reject, Close. Initially only close is enabled. - // Close is only disabled when a bundle is running. - // After a bundle is successfully run, reject and accept are enabled. - // If aborting a bundle, only close will be enabled. - m_accept = new QPushButton(tr("&Accept")); - m_reject = new QPushButton(tr("&Reject")); - m_close = new QPushButton(tr("&Close")); - m_accept->setEnabled(false); - m_reject->setEnabled(false); - m_close->setEnabled(true); - - // Add tool tips to the buttons - m_accept->setToolTip(tr("Accept the bundle results and save them to the project.")); - m_reject->setToolTip(tr("Reject and discard the bundle results. This resets the dialog.")); - m_close->setToolTip(tr("Close this dialog.")); - - // Add the buttons to the QDialogButtonBox defined in the UI file. - // Note that according to the Qt doc'n for QDialogButtonBox, addButton() causes the - // dialog box to take ownership of the QPushButton's, so we don't manually manage their memory. - m_ui->buttonBox->addButton(m_accept, QDialogButtonBox::ActionRole); - m_ui->buttonBox->addButton(m_reject, QDialogButtonBox::ActionRole); - m_ui->buttonBox->addButton(m_close, QDialogButtonBox::AcceptRole); - - // Accept will handle saving the results. - connect(m_accept, SIGNAL(clicked(bool)), - this, SLOT(acceptBundleResults())); - // Reject will handle discarding the results. - connect(m_reject, SIGNAL(clicked(bool)), - this, SLOT(rejectBundleResults())); + + // After a bundle is successfully run, accept is enabled. + m_ui->JigsawRunButton->setEnabled(false); m_bundleAdjust = NULL; // m_bundleSolutionInfo = NULL; @@ -118,11 +95,6 @@ namespace Isis { m_ui->useLastSettings->setEnabled(false); } - m_ui->iterationLcdNumber->setDigitCount(3); - - m_ui->sigma0LcdNumber->setMode(QLCDNumber::Dec); - m_ui->sigma0LcdNumber->setDigitCount(5); - QString lastSettingsToolTip("Use the settings from the most recently accepted bundle adjust."); QString lastSettingsWhat("When checked, the settings from the most recently accepted bundle " "adjust (i.e. the most recent bundle results in the project) will be " @@ -130,30 +102,36 @@ namespace Isis { m_ui->useLastSettings->setToolTip(lastSettingsToolTip); m_ui->useLastSettings->setWhatsThis(lastSettingsWhat); - setWindowFlags(Qt::WindowStaysOnTopHint); + // setWindowFlags(Qt::WindowStaysOnTopHint); + } /** * Destructor. */ - JigsawDialog::~JigsawDialog() { + JigsawRunWidget::~JigsawRunWidget() { // if (m_bundleSolutionInfo) { // delete m_bundleSolutionInfo; +// m_bundleSolutionInfo = NULL; // } if (m_bundleAdjust) { - delete m_bundleAdjust; - m_bundleAdjust = NULL; + m_bundleAdjust->deleteLater(); + m_bundleAdjust = NULL; + } + if (m_bundleThread) { + m_bundleThread->quit(); + m_bundleThread->deleteLater(); + m_bundleThread = NULL; } if (m_ui) { delete m_ui; + m_ui = NULL; } -// m_bundleSolutionInfo = NULL; - m_ui = NULL; } - void JigsawDialog::on_JigsawSetupButton_pressed() { + void JigsawRunWidget::on_JigsawSetupButton_clicked() { // Each time the SetUp button is pressed, create JigsawSetupDialog object with // project, @@ -168,7 +146,14 @@ namespace Isis { // We want to use the current settings if not use the most recently accepted bundle settings. // This allows user to click "Setup", make changes, "OK", then click "Setup", and those changes // are present in the setup dialog. - if (m_bundleSettings && !m_ui->useLastSettings->isChecked()) { + if (m_ui->useLastSettings->isChecked() && m_project->bundleSolutionInfo().size() > 0) { + QList<BundleSolutionInfo *> bundleSolutionInfo = m_project->bundleSolutionInfo(); + BundleSettingsQsp lastBundleSettings = (bundleSolutionInfo.last())->bundleSettings(); + setupdlg.loadSettings(lastBundleSettings); + // We also tell the setup dialog what the last selected control is. + setupdlg.selectControl(m_selectedControlName); + } + else if (m_bundleSettings) { setupdlg.loadSettings(m_bundleSettings); // We also tell the setup dialog what the last selected control is. setupdlg.selectControl(m_selectedControlName); @@ -181,14 +166,15 @@ namespace Isis { m_bundleSettings = setupdlg.bundleSettings(); // The settings have been modified, might be misleading to keep this check after setup. m_ui->useLastSettings->setChecked(false); + m_ui->JigsawRunButton->setEnabled(true); } } - void JigsawDialog::on_JigsawRunButton_clicked() { + void JigsawRunWidget::on_JigsawRunButton_clicked() { // Once a bundle is run, the previous results cannot be accepted or rejected. - m_accept->setEnabled(false); - m_reject->setEnabled(false); + m_ui->JigsawAcceptButton->setEnabled(false); + m_ui->statusOutputLabel->setText("Initialization"); if (!m_bRunning) { // ??? warning dialogs ??? @@ -218,7 +204,7 @@ namespace Isis { // Clear the dialog displays. clearDialog(); - QThread *bundleThread = new QThread; + m_bundleThread = new QThread; // Make sure to clean up any previously run bundle adjusts. if (m_bundleAdjust) { @@ -229,7 +215,7 @@ namespace Isis { m_bundleAdjust = new BundleAdjust(m_bundleSettings, *m_selectedControl, m_project->images(), false); - m_bundleAdjust->moveToThread(bundleThread); + m_bundleAdjust->moveToThread(m_bundleThread); // Track the status updates bundle adjust gives and update the dialog. connect( m_bundleAdjust, SIGNAL( statusUpdate(QString) ), @@ -240,11 +226,17 @@ namespace Isis { this, SLOT( errorString(QString) ) ); // Update the iteration dialog element when the bundle updates its iteration count. - connect( m_bundleAdjust, SIGNAL( iterationUpdate(int, double) ), - this, SLOT( updateIterationSigma0(int, double) ) ); + connect( m_bundleAdjust, SIGNAL( iterationUpdate(int) ), + this, SLOT( updateIteration(int) ) ); + + connect( m_bundleAdjust, SIGNAL( pointUpdate(int) ), + this, SLOT( updatePoint(int) ) ); + + connect( m_bundleAdjust, SIGNAL( statusBarUpdate(QString) ), + this, SLOT( updateStatus(QString) ) ); // When we start the bundle thread, run the bundle adjustment. - connect( bundleThread, SIGNAL( started() ), + connect( m_bundleThread, SIGNAL( started() ), m_bundleAdjust, SLOT( solveCholesky() ) ); // When the bundle adjust says results are ready, we can allow the dialog to update the @@ -252,42 +244,163 @@ namespace Isis { connect( m_bundleAdjust, SIGNAL( resultsReady(BundleSolutionInfo *) ), this, SLOT( bundleFinished(BundleSolutionInfo *) ) ); - // Schedule the bundle thread for deletion when it finishes. - connect( bundleThread, SIGNAL( finished() ), - bundleThread, SLOT( deleteLater() ) ); - // ken testing // Notify the dialog that the bundle thread is finished, and update the gui elements. - connect( bundleThread, SIGNAL( finished() ), + connect( m_bundleThread, SIGNAL( finished() ), this, SLOT( notifyThreadFinished() ) ); // Tell the thread to quit (stop) when the bundle adjust finishes (successfully or not) connect( m_bundleAdjust, SIGNAL( finished() ), - bundleThread, SLOT( quit() ) ); + m_bundleThread, SLOT( quit() ) ); + + m_ui->imagesLcdNumber->display(m_bundleAdjust->numberOfImages()); + m_ui->pointsLcdNumber->display(m_bundleAdjust->controlNet()->GetNumPoints()); + m_ui->measuresLcdNumber->display(m_bundleAdjust->controlNet()->GetNumMeasures()); - bundleThread->start(); + m_bundleThread->start(); // change "Run" button text to "Abort" (or maybe pause) m_bRunning = true; - m_close->setEnabled(false); m_ui->JigsawRunButton->setText("&Abort"); update(); } else { // Make sure to abort the bundle if it is currently running. - m_bundleAdjust->abortBundle(); - m_bRunning = false; m_ui->JigsawRunButton->setText("&Aborting..."); + m_ui->statusOutputLabel->setText("Aborting..."); + m_bundleAdjust->abortBundle(); update(); } } + /** + * Accepts the bundle results and saves them to the project. The "Accept" button will be disabled. + */ + void JigsawRunWidget::on_JigsawAcceptButton_clicked() { + m_ui->JigsawAcceptButton->setEnabled(false); + + // create bundle results folder + QString runTime = m_bundleSolutionInfo->runTime(); + QDir bundleDir = m_project->addBundleSolutionInfoFolder(runTime); //??? + // save solution information to a file + + m_bundleSolutionInfo->bundleSettings()->setOutputFilePrefix(bundleDir.absolutePath() + "/"); + + // Write csv files + m_bundleSolutionInfo->outputResiduals(); + m_bundleSolutionInfo->outputImagesCSV(); + m_bundleSolutionInfo->outputPointsCSV(); + + // Write text summary file + m_bundleSolutionInfo->outputText(); + + // create output control net file name + FileName outputControlName; + if (!m_outputControlName.isEmpty()) { + outputControlName + = FileName(m_project->bundleSolutionInfoRoot() + "/" + runTime + "/" + + m_outputControlName); + } + else { + outputControlName + = FileName(m_project->bundleSolutionInfoRoot() + "/" + runTime + "/Out-" + runTime + "-" + + FileName(m_bundleSolutionInfo->inputControlNetFileName()).name()); + } + + // Write output control net with correct path to results folder + runtime + m_bundleSolutionInfo->bundleResults().outputControlNet()->Write(outputControlName.toString()); + + // create Control with output control net and add to m_bundleSolutionInfo + m_bundleSolutionInfo->setOutputControl(new Control(m_project, outputControlName.expanded())); + + if (m_ui->detachedLabelsCheckBox->isChecked()) { + // Iterate through all of the image lists (the "imports" in the project). + QList<ImageList *> imageLists = m_bundleSolutionInfo->imageList(); + foreach (ImageList *imageList, imageLists) { + // Keep track of the file names of the images that were used in the bundle. + QStringList imagesToCopy; + + // Now, we iterate through each image in the current image list ("import"), and we determine + // the location of the image and where to copy it to (as an ecub). + foreach (Image *image, *imageList) { + FileName original(image->fileName()); + // Update our list of tracked file names for the images we are going to copy. + imagesToCopy.append(original.expanded()); + } + // Concurrently copy the bundled images as ecub's to the bundle solution info results. + CopyImageToResultsFunctor copyImage(m_project->bundleSolutionInfoRoot() + "/" + + m_bundleSolutionInfo->runTime() + "/images/" + + imageList->name()); + QFuture<Cube *> copiedCubes = QtConcurrent::mapped(imagesToCopy, copyImage); + + // Prepare for our adjusted images (ecubs) + ImageList *adjustedImages = new ImageList(imageList->name(), imageList->path()); + + // Update the adjusted images' labels + for (int i = 0; i < imagesToCopy.size(); i++) { + Cube *ecub = copiedCubes.resultAt(i); + if (ecub) { + Process propagateHistory; + propagateHistory.SetInputCube(ecub); + + // check for existing polygon, if exists delete it + if (ecub->label()->hasObject("Polygon")) { + ecub->label()->deleteObject("Polygon"); + } + + // check for CameraStatistics Table, if exists, delete + for (int iobj = 0; iobj < ecub->label()->objects(); iobj++) { + PvlObject obj = ecub->label()->object(iobj); + if (obj.name() != "Table") continue; + if (obj["Name"][0] != QString("CameraStatistics")) continue; + ecub->label()->deleteObject(iobj); + break; + } + + // Timestamp and propagate the instrument pointing table and instrument position table + QString bundleTimestamp = "Jigged = " + m_bundleSolutionInfo->runTime(); + Table cMatrix = m_bundleAdjust->cMatrix(i); + Table spVector = m_bundleAdjust->spVector(i); + cMatrix.Label().addComment(bundleTimestamp); + spVector.Label().addComment(bundleTimestamp); + ecub->write(cMatrix); + ecub->write(spVector); + // The ecub is now adjusted, add this to our list of adjusted images + Image *newImage = new Image(ecub); + adjustedImages->append(newImage); + newImage->closeCube(); + } + } + // Tell the BundleSolutionInfo what the adjusted images are + m_bundleSolutionInfo->addAdjustedImages(adjustedImages); + } + + } + + // Tell the project about the BundleSolutionInfo + // m_project->addBundleSolutionInfo( new BundleSolutionInfo(*m_bundleSolutionInfo) ); + m_project->addBundleSolutionInfo(m_bundleSolutionInfo); + + // Make sure that when we add our results, we let the use last settings box be checkable. + m_ui->useLastSettings->setEnabled(true); + + // m_ui->convergenceStatusLabel->setText("Bundle converged, camera pointing updated"); + //This bundle was bad so we should delete all remenants. + + //TODO: delete correlation matrix cov file... + //TODO: delete bundle results object + +// m_ui->convergenceStatusLabel->setText("Bundle did not converge, camera pointing NOT updated"); + m_project->setClean(false); + } + + /** * Constructs a image copier functor for copying images used in the bundle adjustment to the * bundle solution info results (when the bundle is accepted). */ - JigsawDialog::CopyImageToResultsFunctor::CopyImageToResultsFunctor(const QDir &destination) { + JigsawRunWidget::CopyImageToResultsFunctor::CopyImageToResultsFunctor(const QDir &destination) { m_destinationFolder = destination; } @@ -295,7 +408,7 @@ namespace Isis { /** * Destructor. */ - JigsawDialog::CopyImageToResultsFunctor::~CopyImageToResultsFunctor() { + JigsawRunWidget::CopyImageToResultsFunctor::~CopyImageToResultsFunctor() { m_destinationFolder = QDir(); } @@ -311,7 +424,7 @@ namespace Isis { * @return Cube* Returns a pointer to the external cube copy. Returns NULL if an error * occurs. */ - Cube *JigsawDialog::CopyImageToResultsFunctor::operator()(const FileName &image) { + Cube *JigsawRunWidget::CopyImageToResultsFunctor::operator()(const FileName &image) { try { Cube *result = NULL; @@ -359,163 +472,25 @@ namespace Isis { } - /** - * Accepts the bundle results and saves them to the project. The "Accept" and "Reject" buttons - * will be disabled. - */ - void JigsawDialog::acceptBundleResults() { - m_accept->setEnabled(false); - m_reject->setEnabled(false); - - // create bundle results folder - QString runTime = m_bundleSolutionInfo->runTime(); - QDir bundleDir = m_project->addBundleSolutionInfoFolder(runTime); //??? - // save solution information to a file - - m_bundleSolutionInfo->bundleSettings()->setOutputFilePrefix(bundleDir.absolutePath() + "/"); - - // Write csv files - m_bundleSolutionInfo->outputResiduals(); - m_bundleSolutionInfo->outputImagesCSV(); - m_bundleSolutionInfo->outputPointsCSV(); - - // Write text summary file - m_bundleSolutionInfo->outputText(); - - // create output control net file name - FileName outputControlName; - if (!m_outputControlName.isEmpty()) { - outputControlName - = FileName(m_project->bundleSolutionInfoRoot() + "/" + runTime + "/" + - m_outputControlName); - } - else { - outputControlName - = FileName(m_project->bundleSolutionInfoRoot() + "/" + runTime + "/Out-" + runTime + "-" + - FileName(m_bundleSolutionInfo->inputControlNetFileName()).name()); - } - - // Write output control net with correct path to results folder + runtime - m_bundleSolutionInfo->bundleResults().outputControlNet()->Write(outputControlName.toString()); - - // create Control with output control net and add to m_bundleSolutionInfo - m_bundleSolutionInfo->setOutputControl(new Control(m_project, outputControlName.expanded())); - - // Iterate through all of the image lists (the "imports" in the project). - QList<ImageList *> imageLists = m_bundleSolutionInfo->imageList(); - foreach (ImageList *imageList, imageLists) { - // Keep track of the file names of the images that were used in the bundle. - QStringList imagesToCopy; - - // Now, we iterate through each image in the current image list ("import"), and we determine - // the location of the image and where to copy it to (as an ecub). - foreach (Image *image, *imageList) { - FileName original(image->fileName()); - // Update our list of tracked file names for the images we are going to copy. - imagesToCopy.append(original.expanded()); - } - // Concurrently copy the bundled images as ecub's to the bundle solution info results. - CopyImageToResultsFunctor copyImage(m_project->bundleSolutionInfoRoot() + "/" + - m_bundleSolutionInfo->runTime() + "/images/" + - imageList->name()); - QFuture<Cube *> copiedCubes = QtConcurrent::mapped(imagesToCopy, copyImage); - - // Prepare for our adjusted images (ecubs) - ImageList *adjustedImages = new ImageList(imageList->name(), imageList->path()); - - // Update the adjusted images' labels - for (int i = 0; i < imagesToCopy.size(); i++) { - Cube *ecub = copiedCubes.resultAt(i); - if (ecub) { - Process propagateHistory; - propagateHistory.SetInputCube(ecub); - - // check for existing polygon, if exists delete it - if (ecub->label()->hasObject("Polygon")) { - ecub->label()->deleteObject("Polygon"); - } - - // check for CameraStatistics Table, if exists, delete - for (int iobj = 0; iobj < ecub->label()->objects(); iobj++) { - PvlObject obj = ecub->label()->object(iobj); - if (obj.name() != "Table") continue; - if (obj["Name"][0] != QString("CameraStatistics")) continue; - ecub->label()->deleteObject(iobj); - break; - } - - // Timestamp and propagate the instrument pointing table and instrument position table - QString bundleTimestamp = "Jigged = " + m_bundleSolutionInfo->runTime(); - Table cMatrix = m_bundleAdjust->cMatrix(i); - Table spVector = m_bundleAdjust->spVector(i); - cMatrix.Label().addComment(bundleTimestamp); - spVector.Label().addComment(bundleTimestamp); - ecub->write(cMatrix); - ecub->write(spVector); - // The ecub is now adjusted, add this to our list of adjusted images - Image *newImage = new Image(ecub); - adjustedImages->append(newImage); - newImage->closeCube(); - } - } - // Tell the BundleSolutionInfo what the adjusted images are - m_bundleSolutionInfo->addAdjustedImages(adjustedImages); - } - - // Tell the project about the BundleSolutionInfo -// m_project->addBundleSolutionInfo( new BundleSolutionInfo(*m_bundleSolutionInfo) ); - m_project->addBundleSolutionInfo(m_bundleSolutionInfo); - - // Make sure that when we add our results, we let the use last settings box be checkable. - m_ui->useLastSettings->setEnabled(true); - // Once the bundle has been accepted, re-enable the close button - m_close->setEnabled(true); - - // m_ui->convergenceStatusLabel->setText("Bundle converged, camera pointing updated"); - //This bundle was bad so we should delete all remenants. - - //TODO: delete correlation matrix cov file... - //TODO: delete bundle results object - -// m_ui->convergenceStatusLabel->setText("Bundle did not converge, camera pointing NOT updated"); - m_project->setClean(false); - } - - - /** - * Rejects the bundle results and discards them. The "Accept" and "Reject" buttons will be - * disabled. - */ - void JigsawDialog::rejectBundleResults() { - // TODO should there be a prompt to user (are you sure?) -- Annoying? - // TODO Add tooltip/what'sthis for the buttons!!!! (CTR) - // Disable the "Accept" and "Reject" buttons, enable the "Close" button - m_accept->setEnabled(false); - m_reject->setEnabled(false); - m_close->setEnabled(true); - - // Clear the dialog so the lcd's are 0 and the status text is cleared. - clearDialog(); - QString statusText("Bundle Rejected.\n\n"); - m_ui->statusUpdatesLabel->setText(statusText); - - // Cleanup the results (bundle solution info) - // How does this affect m_bundleSettings or m_bundleAdjustment? - // How does this affect using the last (most recent) settings for the run? -// delete m_bundleSolutionInfo; -// m_bundleSolutionInfo = NULL; - } - - /** * Resets the dialog's status widgets to their default state. This will clear the status text, * reset the lcd displays to 0, and update the scroll on the scroll bar. This does NOT affect * the state of the buttons. */ - void JigsawDialog::clearDialog() { - m_ui->iterationLcdNumber->display(0); - m_ui->sigma0LcdNumber->display(0); + void JigsawRunWidget::clearDialog() { m_ui->statusUpdatesLabel->clear(); + m_ui->iterationLcdNumber->display(0); + m_ui->pointLcdNumber->display(0); + + m_ui->imagesLcdNumber->display(0); + m_ui->pointsLcdNumber->display(0); + m_ui->measuresLcdNumber->display(0); + + m_ui->rmsAdjustedPointSigmasGroupBox->setEnabled(false); + m_ui->latitudeLcdNumber->display(0); + m_ui->longitudeLcdNumber->display(0); + m_ui->radiusLcdNumber->display(0); + updateScrollBar(); } @@ -523,7 +498,7 @@ namespace Isis { /** * Updates the scroll bar to position to its maximum setting (the bottom). */ - void JigsawDialog::updateScrollBar() { + void JigsawRunWidget::updateScrollBar() { m_ui->statusUpdateScrollArea->verticalScrollBar()->setSliderPosition( m_ui->statusUpdateScrollArea->verticalScrollBar()->maximum()); } @@ -535,7 +510,7 @@ namespace Isis { * * @param status Current status of bundle. */ - void JigsawDialog::outputBundleStatus(QString status) { + void JigsawRunWidget::outputBundleStatus(QString status) { QString updateStr = "\n" + status; m_ui->statusUpdatesLabel->setText( m_ui->statusUpdatesLabel->text().append(updateStr) ); @@ -551,16 +526,13 @@ namespace Isis { * * @param error Error status of bundle. */ - void JigsawDialog::errorString(QString error) { + void JigsawRunWidget::errorString(QString error) { QString errorStr = "\n" + error; m_ui->statusUpdatesLabel->setText( m_ui->statusUpdatesLabel->text().append(errorStr) ); updateScrollBar(); update(); - - // Re-enable the close button - m_close->setEnabled(true); } @@ -569,7 +541,7 @@ namespace Isis { * * @param error Error status of bundle. */ - void JigsawDialog::reportException(QString exception) { + void JigsawRunWidget::reportException(QString exception) { QString exceptionStr = "\n" + exception; m_ui->statusUpdatesLabel->setText( m_ui->statusUpdatesLabel->text().append(exceptionStr) ); @@ -584,31 +556,78 @@ namespace Isis { * * @param error Error status of bundle. */ - void JigsawDialog::updateIterationSigma0(int iteration, double sigma0) { + void JigsawRunWidget::updateIteration(int iteration) { m_ui->iterationLcdNumber->display(iteration); - m_ui->sigma0LcdNumber->display(sigma0); + update(); + } + + /** + * Update the label or text edit area with the error message by appending to list and refreshing. + * + * @param error Error status of bundle. + */ + void JigsawRunWidget::updatePoint(int point) { + m_ui->pointLcdNumber->display(point); + update(); + } + + + /** + * Update the label or text edit area with the error message by appending to list and refreshing. + * + * @param error Error status of bundle. + */ + void JigsawRunWidget::updateStatus(QString status) { + m_ui->statusOutputLabel->setText(status); update(); } /** - * @brief Notifies the dialog that the bundle thread has finished. + * @brief Notifies the widget that the bundle thread has finished. * - * This slot is used to notify the dialog that the bundle has finished. The bundle thread + * This slot is used to notify the widget that the bundle has finished. The bundle thread * finishes when the bundle adjust finishes (either successfully or unsuccessfully, or if the * user aborts the run). */ - void JigsawDialog::notifyThreadFinished() { + void JigsawRunWidget::notifyThreadFinished() { //QString str = "\nThread Finished signal received"; //m_ui->statusUpdatesLabel->setText( m_ui->statusUpdatesLabel->text().append(str) ); // set Run button text back to "Run" m_ui->JigsawRunButton->setText("&Run"); + + if (m_bundleAdjust->isAborted()) { + m_ui->statusOutputLabel->setText("Aborted"); + } + + if (m_bundleSettings->errorPropagation()) { + m_ui->rmsAdjustedPointSigmasGroupBox->setEnabled(true); + m_ui->latitudeLcdNumber->display( + m_bundleSolutionInfo->bundleResults().sigmaLatitudeStatisticsRms()); + m_ui->longitudeLcdNumber->display( + m_bundleSolutionInfo->bundleResults().sigmaLongitudeStatisticsRms()); + + if (m_bundleSettings->solveRadius()) { + m_ui->radiusLcdNumber->display( + m_bundleSolutionInfo->bundleResults().sigmaRadiusStatisticsRms()); + m_ui->radiusLcdNumber->setEnabled(true); + m_ui->radiusLcdLabel->setEnabled(true); + } + else { + m_ui->radiusLcdNumber->setEnabled(false); + m_ui->radiusLcdLabel->setEnabled(false); + } + + } + else { + m_ui->rmsAdjustedPointSigmasGroupBox->setEnabled(false); + } + // Since this slot is invoked when the thread finishes, the bundle adjustment is no longer // running. m_bRunning = false; - updateScrollBar(); update(); @@ -624,14 +643,43 @@ namespace Isis { * * @param bundleSolutionInfo The results of the bundle run. */ - void JigsawDialog::bundleFinished(BundleSolutionInfo *bundleSolutionInfo) { + void JigsawRunWidget::bundleFinished(BundleSolutionInfo *bundleSolutionInfo) { bundleSolutionInfo->setRunTime( Isis::iTime::CurrentLocalTime().toLatin1().data() ); m_bundleSolutionInfo = bundleSolutionInfo; // Since results are available, the user can accept (save) or reject(discard) the results. - m_accept->setEnabled(true); - m_reject->setEnabled(true); + m_ui->JigsawAcceptButton->setEnabled(true); + } + + + /** + * This method is called whenever the widget recieves a close request. If a bundle is running, the + * user will be asked if they want to abort the bundle. In this case, the bundle thread must be + * scheduled to delete when it has finished aborting. Otherwise, the event will accept. + * + * @param event The close event being handled. + */ + void JigsawRunWidget::closeEvent(QCloseEvent *event) { + if( m_bRunning ) { + QMessageBox::StandardButton resBtn = + QMessageBox::question(this, + "WARNING", + tr("You are about to abort the bundle adjustment. Are you sure?\n"), + QMessageBox::No | QMessageBox::Yes); + if (resBtn != QMessageBox::Yes) { + event->ignore(); + return; + } + else if (m_bRunning) { // check m_bRunning again just in case the bundle has finished + // We need to wait for the bundle adjust thread to finish before deleting the + // JigsawRunWidget so that we dont close the widget before the thread is finished + connect(m_bundleThread, SIGNAL(finished()), this, SLOT(deleteLater())); + m_bundleAdjust->abortBundle(); + return; + } + } + event->accept(); } } @@ -641,7 +689,7 @@ namespace Isis { * 2015-08-24 Notes added: Ken Edmundson * * If a bundle is NOT currently running, we ... - * 1) create a QThread object (bundleThread) + * 1) create a QThread object (m_bundleThread) * 2) create a new pointer to a BundleAdjust object (m_bundleAdjust) * 3) move the BundleAdjust object to the QThread * 4) connect signals & slots to ... diff --git a/isis/src/qisis/objs/JigsawDialog/JigsawDialog.h b/isis/src/qisis/objs/JigsawRunWidget/JigsawRunWidget.h similarity index 80% rename from isis/src/qisis/objs/JigsawDialog/JigsawDialog.h rename to isis/src/qisis/objs/JigsawRunWidget/JigsawRunWidget.h index 01fb118dadf009a124951bafa176fdb2e4c7b0b4..dbfd879f6a5104a00c6c57fa47248c65355fa11e 100644 --- a/isis/src/qisis/objs/JigsawDialog/JigsawDialog.h +++ b/isis/src/qisis/objs/JigsawRunWidget/JigsawRunWidget.h @@ -1,8 +1,11 @@ -#ifndef JigsawDialog_h -#define JigsawDialog_h +#ifndef JigsawRunWidget_h +#define JigsawRunWidget_h #include <QDialog> #include <QDir> +#include <QDockWidget> +#include <QFrame> +#include <QMessageBox> #include <QPointer> #include <QWidget> @@ -10,10 +13,11 @@ #include "IException.h" namespace Ui { - class JigsawDialog; + class JigsawRunWidget; } class QString; +class QThread; namespace Isis { class BundleAdjust; @@ -88,25 +92,39 @@ namespace Isis { * not delete m_BundleSolutionInfo or set it to NULL. Note this is NOT * ideal, m_BundleSolutionInfo should be a QSharedPointer, not a raw * pointer. + * @history 2018-05-31 Christopher Combs - Name changed from JigsawDialog to JigsawRunWidget. + * Now inherits from QFrame instead of QDialog. Added support for new + * workflow in which JigsawSetupDialog is only ever called from a + * button on this widget. Fixes #5428. + * @history 2018-06-14 Christopher Combs - Made changes according to new design mockup. Added + * status bar, control net info, and rms adj point sigmas sections. + * Removed buttons for close and reject. Now inherits from QDockWidget + * instead of QFrame, and handles close event if a bundle is running. + * @history 2018-06-15 Christopher Combs - Implemented "Write detached labels" checkbox. + * made changes to on_JigsawAcceptButton_clicked to reflect this. */ - class JigsawDialog : public QDialog { + class JigsawRunWidget : public QDockWidget { Q_OBJECT public: - explicit JigsawDialog(Project *project, QWidget *parent = 0); - explicit JigsawDialog(Project *project, + explicit JigsawRunWidget(Project *project, QWidget *parent = 0); + explicit JigsawRunWidget(Project *project, BundleSettingsQsp bundleSettings, Control *selectedControl, QString outputControlFileName, QWidget *parent = 0); - ~JigsawDialog(); + ~JigsawRunWidget(); + void closeEvent(QCloseEvent *event); + public slots: void outputBundleStatus(QString status); void errorString(QString error); void reportException(QString exception); - void updateIterationSigma0(int iteration, double sigma0); + void updateIteration(int iteration); + void updatePoint(int point); + void updateStatus(QString status); void bundleFinished(BundleSolutionInfo *bundleSolutionInfo); void notifyThreadFinished(); @@ -121,9 +139,7 @@ namespace Isis { private: bool m_bRunning; /**< Indicates whether or not the bundle adjust is running. */ - QPushButton *m_accept; /**< Dialog's accept button that is used to save the bundle results. */ - QPushButton *m_close; /**< Dialog's close button that is used to close the dialog. */ - QPushButton *m_reject; /**< Dialog's reject button that is used to discard the results. */ + QThread *m_bundleThread; /**< separate thread for running bundle adjust calculations in. */ /** * Functor used to copy images to a specified destination directory. This is used by @@ -145,18 +161,17 @@ namespace Isis { }; private slots: - void on_JigsawSetupButton_pressed(); + void on_JigsawSetupButton_clicked(); void on_JigsawRunButton_clicked(); - void acceptBundleResults(); - void rejectBundleResults(); + void on_JigsawAcceptButton_clicked(); void clearDialog(); void updateScrollBar(); private: - /** Captures the most recent results of a bundle. JigsawDialog owns this pointer. */ + /** Captures the most recent results of a bundle. JigsawRunWidget owns this pointer. */ BundleSolutionInfo *m_bundleSolutionInfo; /** Reference to self's UI generated with QtDesigner. */ - Ui::JigsawDialog *m_ui; + Ui::JigsawRunWidget *m_ui; }; }; #endif diff --git a/isis/src/qisis/objs/JigsawRunWidget/JigsawRunWidget.ui b/isis/src/qisis/objs/JigsawRunWidget/JigsawRunWidget.ui new file mode 100644 index 0000000000000000000000000000000000000000..3694fe0657d10bda92069b3e0e2ad428680fc294 --- /dev/null +++ b/isis/src/qisis/objs/JigsawRunWidget/JigsawRunWidget.ui @@ -0,0 +1,603 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>JigsawRunWidget</class> + <widget class="QDockWidget" name="JigsawRunWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>544</width> + <height>434</height> + </rect> + </property> + <property name="windowTitle"> + <string>&Jigsaw</string> + </property> + <widget class="QWidget" name="dockWidgetContents"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="minimumSize"> + <size> + <width>540</width> + <height>400</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>800</width> + <height>400</height> + </size> + </property> + <property name="windowTitle"> + <string>Jigsaw</string> + </property> + <property name="windowIcon"> + <iconset> + <normaloff>icons/jigsaw.png</normaloff>icons/jigsaw.png</iconset> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="QFrame" name="frame"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QScrollArea" name="statusUpdateScrollArea"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>200</width> + <height>0</height> + </size> + </property> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <widget class="QLabel" name="statusUpdatesLabel"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>196</width> + <height>368</height> + </rect> + </property> + <property name="text"> + <string>Welcome to Jigsaw</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="statusLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>Status</string> + </property> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_3"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string/> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="statusOutputLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Setup</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <widget class="QLabel" name="iterationLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>40</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>Iteration</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="pointLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>40</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>Point</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLCDNumber" name="iterationLcdNumber"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="autoFillBackground"> + <bool>true</bool> + </property> + <property name="segmentStyle"> + <enum>QLCDNumber::Flat</enum> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QLCDNumber" name="pointLcdNumber"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="autoFillBackground"> + <bool>true</bool> + </property> + <property name="segmentStyle"> + <enum>QLCDNumber::Flat</enum> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="3" column="1"> + <widget class="QGroupBox" name="rmsAdjustedPointSigmasGroupBox"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="autoFillBackground"> + <bool>true</bool> + </property> + <property name="title"> + <string>RMS Adj Point Sigmas</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="2" column="0" alignment="Qt::AlignRight"> + <widget class="QLabel" name="radiusLcdLabel"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Radius</string> + </property> + </widget> + </item> + <item row="0" column="0" alignment="Qt::AlignRight"> + <widget class="QLabel" name="label_4"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Latitude</string> + </property> + </widget> + </item> + <item row="1" column="0" alignment="Qt::AlignRight"> + <widget class="QLabel" name="label_7"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Longitude</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLCDNumber" name="latitudeLcdNumber"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="smallDecimalPoint"> + <bool>false</bool> + </property> + <property name="segmentStyle"> + <enum>QLCDNumber::Flat</enum> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLCDNumber" name="longitudeLcdNumber"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="segmentStyle"> + <enum>QLCDNumber::Flat</enum> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLCDNumber" name="radiusLcdNumber"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="segmentStyle"> + <enum>QLCDNumber::Flat</enum> + </property> + </widget> + </item> + </layout> + <zorder>label_4</zorder> + <zorder>label_7</zorder> + <zorder>radiusLcdLabel</zorder> + <zorder>latitudeLcdNumber</zorder> + <zorder>longitudeLcdNumber</zorder> + <zorder>radiusLcdNumber</zorder> + </widget> + </item> + <item row="3" column="0"> + <widget class="QGroupBox" name="groupBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string> Control Network </string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="2" column="1"> + <widget class="QLCDNumber" name="measuresLcdNumber"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="autoFillBackground"> + <bool>true</bool> + </property> + <property name="segmentStyle"> + <enum>QLCDNumber::Flat</enum> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLCDNumber" name="pointsLcdNumber"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="autoFillBackground"> + <bool>true</bool> + </property> + <property name="segmentStyle"> + <enum>QLCDNumber::Flat</enum> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLCDNumber" name="imagesLcdNumber"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="autoFillBackground"> + <bool>true</bool> + </property> + <property name="segmentStyle"> + <enum>QLCDNumber::Flat</enum> + </property> + </widget> + </item> + <item row="0" column="0" alignment="Qt::AlignRight"> + <widget class="QLabel" name="label_3"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Images</string> + </property> + </widget> + </item> + <item row="2" column="0" alignment="Qt::AlignRight"> + <widget class="QLabel" name="label_6"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Measures</string> + </property> + </widget> + </item> + <item row="1" column="0" alignment="Qt::AlignRight"> + <widget class="QLabel" name="label_5"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Points</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QCheckBox" name="detachedLabelsCheckBox"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Write Detached Image Labels on Accept</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="tristate"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="useLastSettings"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Use Last Accepted Settings</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_8"> + <item> + <widget class="QPushButton" name="JigsawSetupButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Setup</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="JigsawRunButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Run</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="JigsawAcceptButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Accept</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </widget> + <resources/> + <connections/> +</ui> diff --git a/isis/src/qisis/objs/JigsawRunWidget/Makefile b/isis/src/qisis/objs/JigsawRunWidget/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f122bc88227c5c7ebd108dea5d339d1d2e074d82 --- /dev/null +++ b/isis/src/qisis/objs/JigsawRunWidget/Makefile @@ -0,0 +1,7 @@ +ifeq ($(ISISROOT), $(BLANK)) +.SILENT: +error: + echo "Please set ISISROOT"; +else + include $(ISISROOT)/make/isismake.objs +endif \ No newline at end of file diff --git a/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.cpp b/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.cpp index 97cbd74ea632085f80aa1cc9950c24ff732bba91..92ab258c1c75e9a0c9f5597b29268a6912111f3e 100644 --- a/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.cpp +++ b/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.cpp @@ -3,18 +3,28 @@ #include <vector> #include <QDebug> +#include <QIdentityProxyModel> #include <QMessageBox> #include <QPushButton> +#include <QSortFilterProxyModel> #include <QStandardItemModel> +#include <QItemSelection> +#include "BundleObservationSolveSettings.h" #include "BundleSolutionInfo.h" #include "BundleSettings.h" #include "BundleTargetBody.h" +#include "Camera.h" #include "Control.h" +#include "Cube.h" +#include "Image.h" #include "IString.h" #include "MaximumLikelihoodWFunctions.h" #include "Project.h" +#include "ProjectItem.h" +#include "ProjectItemProxyModel.h" #include "SpecialPixel.h" +#include "SortFilterProxyModel.h" #include "ui_JigsawSetupDialog.h" namespace Isis { @@ -28,7 +38,7 @@ namespace Isis { // care of in the ui setup. // For example: - // radiusCheckBox is connected to pointRadiusSigmaLabel and pointRadiusSigmaLineEdit + // pointRadiusSigmaCheckBox is connected to pointRadiusSigmaLineEdit // outlierRejectionCheckBox is connected // to outlierRejectionMultiplierLabel and outlierRejectionMultiplierLineEdit // @@ -47,6 +57,11 @@ namespace Isis { makeReadOnly(); } + m_bundleSettings = BundleSettingsQsp(new BundleSettings()); + + //connect( m_project->directory()->model(), SIGNAL(selectionChanged(QList<ProjectItem *> &)), + // this, SLOT(on_projectItemSelectionChanged(const QList<ProjectItem *> &) ) ); + // initializations for general tab // fill control net combo box from project @@ -57,7 +72,7 @@ namespace Isis { QVariant v = qVariantFromValue((void*)control); - m_ui->controlNetworkComboBox->addItem(control->displayProperties()->displayName(), v); + m_ui->inputControlNetCombo->addItem(control->displayProperties()->displayName(), v); } } // add control nets from bundle solutions, if any @@ -67,37 +82,113 @@ namespace Isis { QVariant v = qVariantFromValue((void*)bundleControl); - m_ui->controlNetworkComboBox->addItem(bundleControl->displayProperties()->displayName(), v); + m_ui->inputControlNetCombo->addItem(bundleControl->displayProperties()->displayName(), v); } // initialize default output control network filename - FileName fname = m_ui->controlNetworkComboBox->currentText(); - m_ui->outputControlNet->setText(fname.baseName() + "-out.net"); + FileName fname = m_ui->inputControlNetCombo->currentText(); + m_ui->outputControlNetLineEdit->setText(fname.baseName() + "-out.net"); + + // initializations for observation solve settings tab + createObservationSolveSettingsTreeView(); - QList<BundleSolutionInfo *> bundleSolutionInfo = m_project->bundleSolutionInfo(); - if (useLastSettings && bundleSolutionInfo.size() > 0) { - BundleSettingsQsp lastBundleSettings = (bundleSolutionInfo.last())->bundleSettings(); - // Retrieve the control net name used in the last bundle adjustment. - // Note that this returns a fully specified path and filename, while the cnet combo box - // only stores file names. - selectControl(bundleSolutionInfo.last()->inputControlNetFileName()); - fillFromSettings(lastBundleSettings); + + // Create default settings for all of the observations + QList<Image *> imagesToAdd; + // If we have selected any project items, find the images and add them to imagesToAdd + if (!m_project->directory()->model()->selectedItems().isEmpty()) { + foreach (ProjectItem * projItem, m_project->directory()->model()->selectedItems()) { + if (projItem->isImage()) { + imagesToAdd.append(projItem->image()); + } + else if (projItem->isImageList()) { + for (int i = 0; i < projItem->rowCount(); i++) { + imagesToAdd.append(projItem->child(i)->image()); + } + } + } + } + // if we didnt have any images selected in the previous case, or no proj items were selected, + // take all images from the project tree + if (imagesToAdd.isEmpty()) { + ProjectItem *imgRoot = m_project->directory()->model()->findItemData(QVariant("Images"),0); + if (imgRoot) { + for (int i = 0; i < imgRoot->rowCount(); i++) { + ProjectItem * imglistItem = imgRoot->child(i); + for (int j = 0; j < imglistItem->rowCount(); j++) { + ProjectItem * imgItem = imglistItem->child(j); + if (imgItem->isImage()) { + imagesToAdd.append(imgItem->image()); + } + } + } + } } + + // create default solve settings for supported camera types + BundleObservationSolveSettings defaultFramingSettings; + BundleObservationSolveSettings defaultLineScanSettings; + defaultLineScanSettings.setInstrumentPointingSettings( + BundleObservationSolveSettings::AnglesVelocityAcceleration, true, 2, 2, true); - // Update setup dialog with settings from any active (current) settings in jigsaw dialog. - // initializations for observation solve settings tab - m_ui->spkSolveDegreeSpinBox_2->setValue(-1); + // sort each chosen image into its camera type + foreach (Image * image, imagesToAdd) { + int cameraType = image->cube()->camera()->GetCameraType(); + if (cameraType == Camera::LineScan) { + defaultLineScanSettings.addObservationNumber(image->observationNumber()); + } + else { // assume cameraType == Camera::Framing + defaultFramingSettings.addObservationNumber(image->observationNumber()); + } + } + + // only add defaults that have been applied + QList<BundleObservationSolveSettings> solveSettingsList; + if (defaultFramingSettings.observationNumbers().count()) + solveSettingsList.append(defaultFramingSettings); + if (defaultLineScanSettings.observationNumbers().count()) + solveSettingsList.append(defaultLineScanSettings); + + m_bundleSettings->setObservationSolveOptions(solveSettingsList); + + // Populate the solve option comboboxes + const QStringList positionOptions{"NONE", "POSITION", "VELOCITY", "ACCELERATION", "ALL"}; + m_ui->positionComboBox->insertItems(0, positionOptions); + m_ui->positionComboBox->setCurrentIndex(0); + + const QStringList pointingOptions{"NONE", "ANGLES", "VELOCITY", "ACCELERATION", "ALL"}; + m_ui->pointingComboBox->insertItems(0, pointingOptions); + m_ui->pointingComboBox->setCurrentIndex(1); + + // The degree solve options' minimums are -1 (set in ui file), make the -1's display as N/A + m_ui->spkSolveDegreeSpinBox->setSpecialValueText("N/A"); + m_ui->ckSolveDegreeSpinBox->setSpecialValueText("N/A"); + QStringList tableHeaders; - tableHeaders << "coefficients" << "a priori sigma" << "units"; + tableHeaders << "coefficients" << "description" << "units" << "a priori sigma"; m_ui->positionAprioriSigmaTable->setHorizontalHeaderLabels(tableHeaders); + m_ui->pointingAprioriSigmaTable->setHorizontalHeaderLabels(tableHeaders); - m_ui->positionAprioriSigmaTable->setColumnWidth(0, fontMetrics().width(tableHeaders.at(0))); - m_ui->positionAprioriSigmaTable->setColumnWidth(1, fontMetrics().width(tableHeaders.at(1))); - m_ui->positionAprioriSigmaTable->setColumnWidth(2, fontMetrics().width(tableHeaders.at(2))); + // Set the default size of the columns + m_ui->positionAprioriSigmaTable->setColumnWidth(0, fontMetrics().width(tableHeaders.at(0)) + 10); + m_ui->positionAprioriSigmaTable->setColumnWidth(1, fontMetrics().width(tableHeaders.at(1)) + 10); + m_ui->positionAprioriSigmaTable->setColumnWidth(2, fontMetrics().width(tableHeaders.at(2)) + 10); + m_ui->positionAprioriSigmaTable->setColumnWidth(3, fontMetrics().width(tableHeaders.at(3)) + 10); + + m_ui->pointingAprioriSigmaTable->setColumnWidth(0, fontMetrics().width(tableHeaders.at(0)) + 10); + m_ui->pointingAprioriSigmaTable->setColumnWidth(1, fontMetrics().width(tableHeaders.at(1)) + 10); + m_ui->pointingAprioriSigmaTable->setColumnWidth(2, fontMetrics().width(tableHeaders.at(2)) + 10); + m_ui->pointingAprioriSigmaTable->setColumnWidth(3, fontMetrics().width(tableHeaders.at(3)) + 10); - m_ui->pointingAprioriSigmaTable->setHorizontalHeaderLabels(tableHeaders); + + // Add validators to the tables in the observation solve settings tab to validate the a priori + // sigma items + connect(m_ui->positionAprioriSigmaTable, SIGNAL(itemChanged(QTableWidgetItem *)), + this, SLOT(validateSigmaValue(QTableWidgetItem *))); + connect(m_ui->pointingAprioriSigmaTable, SIGNAL(itemChanged(QTableWidgetItem *)), + this, SLOT(validateSigmaValue(QTableWidgetItem *))); // initializations for target body tab @@ -132,7 +223,7 @@ namespace Isis { m_ui->noneRadiiRadioButton->setChecked(true); // validators for target body entries... - QDoubleValidator *sigmaValidator = new QDoubleValidator(0.0, 1.0e+10, 8, this); + QDoubleValidator *sigmaValidator = new QDoubleValidator(0.0, 1.0e+4, 8, this); sigmaValidator->setNotation(QDoubleValidator::ScientificNotation); // right ascension valid range is from 0 to 360 degrees @@ -179,6 +270,30 @@ namespace Isis { m_ui->meanRadiusLineEdit)); m_ui->meanRadiusSigmaLineEdit->setValidator(sigmaValidator); + + + // jigsaw run setup general tab validation + // global apriori point sigmas + m_ui->pointLatitudeSigmaLineEdit->setValidator(new QDoubleValidator(1.0e-10, 1.0e+10, 8, this)); + m_ui->pointLongitudeSigmaLineEdit->setValidator(new QDoubleValidator(1.0e-10, 1.0e+10, 8,this)); + m_ui->pointRadiusSigmaLineEdit->setValidator(new QDoubleValidator(1.0e-10, 1.0e+10, 8, this)); + + // outlier rejection + m_ui->outlierRejectionMultiplierLineEdit->setValidator( + new QDoubleValidator(1.0e-10, 1.0e+10, 8, this)); + m_ui->maximumLikelihoodModel1QuantileLineEdit->setValidator( + new QDoubleValidator(1.0e-10, 1.0, 8, this)); + m_ui->maximumLikelihoodModel2QuantileLineEdit->setValidator( + new QDoubleValidator(1.0e-10, 1.0, 8, this)); + m_ui->maximumLikelihoodModel3QuantileLineEdit->setValidator( + new QDoubleValidator(1.0e-10, 1.0, 8, this)); + + // convergence criteria + m_ui->sigma0ThresholdLineEdit->setValidator(new QDoubleValidator(1.0e-20, 1.0e+10, 8, this)); + m_ui->maximumIterationsLineEdit->setValidator(new QIntValidator(1, 10000, this)); + + + // signals for target body tab // connect(m_ui->radiiButtonGroup, SIGNAL(buttonClicked(int)), // this, SLOT(on_radiiGroupClicked(int))); @@ -191,6 +306,7 @@ namespace Isis { } + JigsawSetupDialog::~JigsawSetupDialog() { // delete/null m_ui since we did "new" this pointers in the constructor if (m_ui) { @@ -201,158 +317,159 @@ namespace Isis { } - void JigsawSetupDialog::on_radiusCheckBox_toggled(bool checked) { - m_ui->pointRadiusSigmaLabel->setEnabled(checked); + void JigsawSetupDialog::on_pointRadiusSigmaCheckBox_toggled(bool checked) { m_ui->pointRadiusSigmaLineEdit->setEnabled(checked); - m_ui->pointRadiusSigmaUnitsLabel->setEnabled(checked); } +// m_ui->positionComboBox has been removed from the general tab, it is planned to be moved to +// the obs solve settings tab. This function will be commented out until it is added back. +// void JigsawSetupDialog::on_positionComboBox_currentIndexChanged(int index) { +// // indices: +// // 0 = none, 1 = position, 2 = velocity, 3 = acceleration, 4 = all +// bool solvePosition = (bool) (index > 0); +// bool solveVelocity = (bool) (index > 1); +// bool solveAcceleration = (bool) (index > 2); +// // bool solveAllPolynomialCoefficients = (bool) (index > 3); -// void JigsawSetupDialog::on_outlierRejectionCheckBox_toggled(bool checked) { -// m_ui->outlierRejectionMultiplierLabel->setEnabled(checked); -// m_ui->outlierRejectionMultiplierLineEdit->setEnabled(checked); -// } +// m_ui->hermiteSplineCheckBox->setEnabled(solvePosition); +// m_ui->positionSigmaLabel->setEnabled(solvePosition); +// m_ui->positionSigmaLineEdit->setEnabled(solvePosition); +// m_ui->positionSigmaUnitsLabel->setEnabled(solvePosition); +// m_ui->velocitySigmaLabel->setEnabled(solveVelocity); +// m_ui->velocitySigmaLineEdit->setEnabled(solveVelocity); +// m_ui->velocitySigmaUnitsLabel->setEnabled(solveVelocity); - void JigsawSetupDialog::on_positionComboBox_currentIndexChanged(int index) { +// m_ui->accelerationSigmaLabel->setEnabled(solveAcceleration); +// m_ui->accelerationSigmaLineEdit->setEnabled(solveAcceleration); +// m_ui->accelerationSigmaUnitsLabel->setEnabled(solveAcceleration); - // indices: - // 0 = none, 1 = position, 2 = velocity, 3 = acceleration, 4 = all - bool solvePosition = (bool) (index > 0); - bool solveVelocity = (bool) (index > 1); - bool solveAcceleration = (bool) (index > 2); -// bool solveAllPolynomialCoefficients = (bool) (index > 3); +// // m_ui->spkDegreeLabel->setEnabled(solveAllPolynomialCoefficients); +// // m_ui->spkDegreeSpinBox->setEnabled(solveAllPolynomialCoefficients); +// // m_ui->spkSolveDegreeLabel->setEnabled(solveAllPolynomialCoefficients); +// // m_ui->spkSolveDegreeSpinBox->setEnabled(solveAllPolynomialCoefficients); - m_ui->hermiteSplineCheckBox->setEnabled(solvePosition); - m_ui->positionSigmaLabel->setEnabled(solvePosition); - m_ui->positionSigmaLineEdit->setEnabled(solvePosition); - m_ui->positionSigmaUnitsLabel->setEnabled(solvePosition); +// } - m_ui->velocitySigmaLabel->setEnabled(solveVelocity); - m_ui->velocitySigmaLineEdit->setEnabled(solveVelocity); - m_ui->velocitySigmaUnitsLabel->setEnabled(solveVelocity); +// m_ui->pointingComboBox has been removed from the general tab, it is planned to be moved to +// the obs solve settings tab. This function will be commented out until it is added back. +// void JigsawSetupDialog::on_pointingComboBox_currentIndexChanged(int index) { - m_ui->accelerationSigmaLabel->setEnabled(solveAcceleration); - m_ui->accelerationSigmaLineEdit->setEnabled(solveAcceleration); - m_ui->accelerationSigmaUnitsLabel->setEnabled(solveAcceleration); +// // indices: +// // 0 = angles, 1 = none, 2 = velocity, 3 = acceleration, 4 = all +// bool solveAngles = (bool) (index == 0 || index > 1); +// bool solveAngularVelocity = (bool) (index > 1); +// bool solveAngularAcceleration = (bool) (index > 2); +// // bool solveAllPolynomialCoefficients = (bool) (index > 3); -// m_ui->spkDegreeLabel->setEnabled(solveAllPolynomialCoefficients); -// m_ui->spkDegreeSpinBox->setEnabled(solveAllPolynomialCoefficients); -// m_ui->spkSolveDegreeLabel->setEnabled(solveAllPolynomialCoefficients); -// m_ui->spkSolveDegreeSpinBox->setEnabled(solveAllPolynomialCoefficients); +// m_ui->twistCheckBox->setEnabled(solveAngles); +// m_ui->fitOverPointingCheckBox->setEnabled(solveAngles); - } - - - void JigsawSetupDialog::on_pointingComboBox_currentIndexChanged(int index) { +// // m_ui->ckDegreeLabel->setEnabled(solveAllPolynomialCoefficients); +// // m_ui->ckDegreeSpinBox->setEnabled(solveAllPolynomialCoefficients); +// // m_ui->ckSolveDegreeSpinBox->setEnabled(solveAllPolynomialCoefficients); +// // m_ui->ckSolveDegreeLabel->setEnabled(solveAllPolynomialCoefficients); - // indices: - // 0 = angles, 1 = none, 2 = velocity, 3 = acceleration, 4 = all - bool solveAngles = (bool) (index == 0 || index > 1); - bool solveAngularVelocity = (bool) (index > 1); - bool solveAngularAcceleration = (bool) (index > 2); -// bool solveAllPolynomialCoefficients = (bool) (index > 3); +// m_ui->pointingAnglesSigmaLabel->setEnabled(solveAngles); +// m_ui->pointingAnglesSigmaLineEdit->setEnabled(solveAngles); +// m_ui->pointingAnglesSigmaUnitsLabel->setEnabled(solveAngles); - m_ui->twistCheckBox->setEnabled(solveAngles); - m_ui->fitOverPointingCheckBox->setEnabled(solveAngles); +// m_ui->pointingAngularVelocitySigmaLabel->setEnabled(solveAngularVelocity); +// m_ui->pointingAngularVelocitySigmaLineEdit->setEnabled(solveAngularVelocity); +// m_ui->pointingAngularVelocitySigmaUnitsLabel->setEnabled(solveAngularVelocity); -// m_ui->ckDegreeLabel->setEnabled(solveAllPolynomialCoefficients); -// m_ui->ckDegreeSpinBox->setEnabled(solveAllPolynomialCoefficients); -// m_ui->ckSolveDegreeSpinBox->setEnabled(solveAllPolynomialCoefficients); -// m_ui->ckSolveDegreeLabel->setEnabled(solveAllPolynomialCoefficients); +// m_ui->pointingAngularAccelerationSigmaLabel->setEnabled(solveAngularAcceleration); +// m_ui->pointingAngularAccelerationSigmaLineEdit->setEnabled(solveAngularAcceleration); +// m_ui->pointingAngularAccelerationSigmaUnitsLabel->setEnabled(solveAngularAcceleration); - m_ui->pointingAnglesSigmaLabel->setEnabled(solveAngles); - m_ui->pointingAnglesSigmaLineEdit->setEnabled(solveAngles); - m_ui->pointingAnglesSigmaUnitsLabel->setEnabled(solveAngles); - - m_ui->pointingAngularVelocitySigmaLabel->setEnabled(solveAngularVelocity); - m_ui->pointingAngularVelocitySigmaLineEdit->setEnabled(solveAngularVelocity); - m_ui->pointingAngularVelocitySigmaUnitsLabel->setEnabled(solveAngularVelocity); - - m_ui->pointingAngularAccelerationSigmaLabel->setEnabled(solveAngularAcceleration); - m_ui->pointingAngularAccelerationSigmaLineEdit->setEnabled(solveAngularAcceleration); - m_ui->pointingAngularAccelerationSigmaUnitsLabel->setEnabled(solveAngularAcceleration); - - } +// } void JigsawSetupDialog::on_maximumLikelihoodModel1ComboBox_currentIndexChanged(int index) { bool model1Selected = (bool) (index > 0); - m_ui->maximumLikelihoodModel1QuantileLabel->setEnabled(model1Selected); + + // lock/unlock current tier's quantile and next tier's model m_ui->maximumLikelihoodModel1QuantileLineEdit->setEnabled(model1Selected); m_ui->maximumLikelihoodModel2Label->setEnabled(model1Selected); m_ui->maximumLikelihoodModel2ComboBox->setEnabled(model1Selected); + m_ui->maximumLikelihoodModel2QuantileLineEdit->setEnabled( + m_ui->maximumLikelihoodModel2ComboBox->currentIndex()); + + // when setting "NONE", set remaining max likelihood options to false + if (!model1Selected) { + m_ui->maximumLikelihoodModel2QuantileLineEdit->setEnabled(false); + m_ui->maximumLikelihoodModel3QuantileLineEdit->setEnabled(false); + m_ui->maximumLikelihoodModel3Label->setEnabled(false); + m_ui->maximumLikelihoodModel3ComboBox->setEnabled(false); + } + + on_maximumLikelihoodModel1QuantileLineEdit_textChanged(""); + on_maximumLikelihoodModel2QuantileLineEdit_textChanged(""); + on_maximumLikelihoodModel3QuantileLineEdit_textChanged(""); + // sigma and max likelihood options are exclusive + m_ui->outlierRejectionCheckBox->setEnabled(!model1Selected); } void JigsawSetupDialog::on_maximumLikelihoodModel2ComboBox_currentIndexChanged(int index) { bool model2Selected = (bool)(index > 0); - m_ui->maximumLikelihoodModel2QuantileLabel->setEnabled(model2Selected); + + // lock/unlock current tier's quantile and next tier's model m_ui->maximumLikelihoodModel2QuantileLineEdit->setEnabled(model2Selected); m_ui->maximumLikelihoodModel3Label->setEnabled(model2Selected); m_ui->maximumLikelihoodModel3ComboBox->setEnabled(model2Selected); + m_ui->maximumLikelihoodModel3QuantileLineEdit->setEnabled( + m_ui->maximumLikelihoodModel3ComboBox->currentIndex()); + // when setting "NONE", set remaining max likelihood options to false + if (!model2Selected) { + m_ui->maximumLikelihoodModel3QuantileLineEdit->setEnabled(false); + } + + on_maximumLikelihoodModel2QuantileLineEdit_textChanged(""); + on_maximumLikelihoodModel3QuantileLineEdit_textChanged(""); } void JigsawSetupDialog::on_maximumLikelihoodModel3ComboBox_currentIndexChanged(int index) { bool model3Selected = (bool)(index > 0); - m_ui->maximumLikelihoodModel3QuantileLabel->setEnabled(model3Selected); + m_ui->maximumLikelihoodModel3QuantileLineEdit->setEnabled(model3Selected); + on_maximumLikelihoodModel3QuantileLineEdit_textChanged(""); } - void JigsawSetupDialog::fillFromSettings(const BundleSettingsQsp settings) { + void JigsawSetupDialog::on_outlierRejectionCheckBox_stateChanged(int arg1) { + + on_outlierRejectionMultiplierLineEdit_textChanged(""); + m_ui->outlierRejectionMultiplierLineEdit->setEnabled(arg1); - BundleObservationSolveSettings observationSolveSettings = settings->observationSolveSettings(0); + // sigma and maxlikelihood options are exclusive + m_ui->CQuantileLabel->setEnabled(!arg1); + m_ui->maxLikelihoodEstimationLabel->setEnabled(!arg1); + m_ui->maximumLikelihoodModel1ComboBox->setEnabled(!arg1); + m_ui->maximumLikelihoodModel1Label->setEnabled(!arg1); + } + + + void JigsawSetupDialog::fillFromSettings(const BundleSettingsQsp settings) { // general tab m_ui->observationModeCheckBox->setChecked(settings->solveObservationMode()); - m_ui->radiusCheckBox->setChecked(settings->solveRadius()); - m_ui->updateCubeLabelCheckBox->setChecked(settings->updateCubeLabel()); + m_ui->pointRadiusSigmaCheckBox->setChecked(settings->solveRadius()); + // m_ui->updateCubeLabelCheckBox->setChecked(settings->updateCubeLabel()); m_ui->errorPropagationCheckBox->setChecked(settings->errorPropagation()); m_ui->outlierRejectionCheckBox->setChecked(settings->outlierRejection()); m_ui->outlierRejectionMultiplierLineEdit->setText(toString(settings->outlierRejectionMultiplier())); m_ui->sigma0ThresholdLineEdit->setText(toString(settings->convergenceCriteriaThreshold())); m_ui->maximumIterationsLineEdit->setText(toString(settings->convergenceCriteriaMaximumIterations())); - - m_ui->positionComboBox->setCurrentIndex(observationSolveSettings.instrumentPositionSolveOption()); - m_ui->hermiteSplineCheckBox->setChecked(observationSolveSettings.solvePositionOverHermite()); - m_ui->spkDegreeSpinBox->setValue(observationSolveSettings.spkDegree()); - m_ui->spkSolveDegreeSpinBox->setValue(observationSolveSettings.spkSolveDegree()); - - - int pointingOption = observationSolveSettings.instrumentPointingSolveOption(); - if (pointingOption == 0) { - pointingOption = 1; - } - if (pointingOption == 1) { - pointingOption = 0; - } - - if ( pointingOption > 0 ) { - m_ui->twistCheckBox->setEnabled(true); - } - else { - m_ui->twistCheckBox->setEnabled(true); - } - - m_ui->pointingComboBox->setCurrentIndex(pointingOption); -// m_ui->pointingComboBox->setCurrentIndex(observationSolveSettings.instrumentPointingSolveOption()); - - - m_ui->twistCheckBox->setChecked(observationSolveSettings.solveTwist()); - m_ui->fitOverPointingCheckBox->setChecked(observationSolveSettings.solvePolyOverPointing()); - m_ui->ckDegreeSpinBox->setValue(observationSolveSettings.ckDegree()); - m_ui->ckSolveDegreeSpinBox->setValue(observationSolveSettings.ckSolveDegree()); - // weighting tab if ( !IsNullPixel(settings->globalLatitudeAprioriSigma()) ) { m_ui->pointLatitudeSigmaLineEdit->setText(toString(settings->globalLatitudeAprioriSigma())); @@ -368,46 +485,27 @@ namespace Isis { } - QList<double> aprioriPositionSigmas = observationSolveSettings.aprioriPositionSigmas(); - - if ( aprioriPositionSigmas.size() > 0 && !IsNullPixel(aprioriPositionSigmas[0]) ) { - m_ui->positionSigmaLineEdit->setText(toString(aprioriPositionSigmas[0])); - m_ui->positionSigmaLineEdit->setModified(true); - } - - if ( aprioriPositionSigmas.size() > 1 && !IsNullPixel(aprioriPositionSigmas[1]) ) { - m_ui->velocitySigmaLineEdit->setText(toString(aprioriPositionSigmas[1])); - m_ui->velocitySigmaLineEdit->setModified(true); - } - - if ( aprioriPositionSigmas.size() > 2 && !IsNullPixel(aprioriPositionSigmas[2]) ) { - m_ui->accelerationSigmaLineEdit->setText(toString(aprioriPositionSigmas[2])); - m_ui->accelerationSigmaLineEdit->setModified(true); - } - - QList<double> aprioriPointingSigmas = observationSolveSettings.aprioriPointingSigmas(); - - if ( aprioriPointingSigmas.size() > 0 && !IsNullPixel(aprioriPointingSigmas[0]) ) { - m_ui->pointingAnglesSigmaLineEdit->setText(toString(aprioriPointingSigmas[0])); - m_ui->pointingAnglesSigmaLineEdit->setModified(true); - } - - if ( aprioriPointingSigmas.size() > 1 && !IsNullPixel(aprioriPointingSigmas[1]) ) { - m_ui->pointingAngularVelocitySigmaLineEdit->setText(toString(aprioriPointingSigmas[1])); - m_ui->pointingAngularVelocitySigmaLineEdit->setModified(true); - } + // If we click setup after changing image selection in the project tree, not all images will + // have solve settings. Here we add those images and their default settings to the list + QList<BundleObservationSolveSettings> defaultSettings = m_bundleSettings->observationSolveSettings(); + QList<BundleObservationSolveSettings> fillSettings = settings->observationSolveSettings(); - if ( aprioriPointingSigmas.size() > 2 && !IsNullPixel(aprioriPointingSigmas[2]) ) { - m_ui->pointingAngularAccelerationSigmaLineEdit->setText(toString(aprioriPointingSigmas[2])); - m_ui->pointingAngularAccelerationSigmaLineEdit->setModified(true); + for (auto &solveSettings : defaultSettings) { + // Remove any images from defaultSettings that exist in fillSettings + foreach (QString observationNumber, solveSettings.observationNumbers()) { + // The method will return a default with no obs numbers if none are found + if (settings->observationSolveSettings(observationNumber).observationNumbers().isEmpty()) { + solveSettings.removeObservationNumber(observationNumber); + } + } + // Append leftover defaultSettings + if (!solveSettings.observationNumbers().isEmpty()) { + fillSettings.append(solveSettings); + } } - // maximum liklihood tab - - // self-calibration tab - - // target body tab - + m_bundleSettings->setObservationSolveOptions(fillSettings); + update(); } @@ -415,7 +513,7 @@ namespace Isis { BundleSettingsQsp JigsawSetupDialog::bundleSettings() { - BundleSettingsQsp settings = BundleSettingsQsp(new BundleSettings); + BundleSettingsQsp settings = m_bundleSettings; settings->setValidateNetwork(true); // solve options @@ -432,65 +530,16 @@ namespace Isis { radiusSigma = m_ui->pointRadiusSigmaLineEdit->text().toDouble(); } settings->setSolveOptions(m_ui->observationModeCheckBox->isChecked(), - m_ui->updateCubeLabelCheckBox->isChecked(), + false, + // m_ui->updateCubeLabelCheckBox->isChecked(), m_ui->errorPropagationCheckBox->isChecked(), - m_ui->radiusCheckBox->isChecked(), + m_ui->pointRadiusSigmaCheckBox->isChecked(), latitudeSigma, longitudeSigma, radiusSigma); settings->setOutlierRejection(m_ui->outlierRejectionCheckBox->isChecked(), m_ui->outlierRejectionMultiplierLineEdit->text().toDouble()); - - - - QList<BundleObservationSolveSettings> observationSolveSettingsList; - BundleObservationSolveSettings observationSolveSettings; - - // pointing settings - double anglesSigma = -1.0; - double angularVelocitySigma = -1.0; - double angularAccelerationSigma = -1.0; - - if (m_ui->pointingAnglesSigmaLineEdit->isModified()) { - anglesSigma = m_ui->pointingAnglesSigmaLineEdit->text().toDouble(); - } - if (m_ui->pointingAngularVelocitySigmaLineEdit->isModified()) { - angularVelocitySigma = m_ui->pointingAngularVelocitySigmaLineEdit->text().toDouble(); - } - if (m_ui->pointingAngularAccelerationSigmaLineEdit->isModified()) { - angularAccelerationSigma = m_ui->pointingAngularAccelerationSigmaLineEdit->text().toDouble(); - } - observationSolveSettings.setInstrumentPointingSettings( - BundleObservationSolveSettings::stringToInstrumentPointingSolveOption(m_ui->pointingComboBox->currentText()), - m_ui->twistCheckBox->isChecked(), - m_ui->ckDegreeSpinBox->text().toInt(), - m_ui->ckSolveDegreeSpinBox->text().toInt(), - m_ui->fitOverPointingCheckBox->isChecked(), - anglesSigma, angularVelocitySigma, angularAccelerationSigma); - - // position option - double positionSigma = -1.0; - double velocitySigma = -1.0; - double accelerationSigma = -1.0; - if (m_ui->positionSigmaLineEdit->isModified()) { - positionSigma = m_ui->positionSigmaLineEdit->text().toDouble(); - } - if (m_ui->velocitySigmaLineEdit->isModified()) { - velocitySigma = m_ui->velocitySigmaLineEdit->text().toDouble(); - } - if (m_ui->accelerationSigmaLineEdit->isModified()) { - accelerationSigma = m_ui->accelerationSigmaLineEdit->text().toDouble(); - } - observationSolveSettings.setInstrumentPositionSettings( - BundleObservationSolveSettings::stringToInstrumentPositionSolveOption(m_ui->positionComboBox->currentText()), - m_ui->spkDegreeSpinBox->text().toInt(), - m_ui->spkSolveDegreeSpinBox->text().toInt(), - m_ui->hermiteSplineCheckBox->isChecked(), - positionSigma, velocitySigma, accelerationSigma); - - observationSolveSettingsList.append(observationSolveSettings); - settings->setObservationSolveOptions(observationSolveSettingsList); // convergence criteria settings->setConvergenceCriteria(BundleSettings::Sigma0, m_ui->sigma0ThresholdLineEdit->text().toDouble(), @@ -520,7 +569,6 @@ namespace Isis { } } } - // target body // ensure user entered something to adjust if (m_ui->poleRaCheckBox->isChecked() || @@ -627,10 +675,6 @@ namespace Isis { settings->setBundleTargetBody(bundleTargetBody); } - - // output options -//??? settings->setOutputFilePrefix(""); - return settings; } @@ -656,7 +700,7 @@ namespace Isis { * @param const QString &controlName The name of the control to try to find in the combo box. */ void JigsawSetupDialog::selectControl(const QString &controlName) { - QComboBox &cnetBox = *(m_ui->controlNetworkComboBox); + QComboBox &cnetBox = *(m_ui->inputControlNetCombo); int foundControlIndex = cnetBox.findText(FileName(controlName).name()); // We did not find it, so we need to see if the combo box is empty or not. if (foundControlIndex == -1) { @@ -677,58 +721,209 @@ namespace Isis { Control *JigsawSetupDialog::selectedControl() { - int nIndex = m_ui->controlNetworkComboBox->currentIndex(); + int nIndex = m_ui->inputControlNetCombo->currentIndex(); Control *selectedControl - = (Control *)(m_ui->controlNetworkComboBox->itemData(nIndex).value< void * >()); + = (Control *)(m_ui->inputControlNetCombo->itemData(nIndex).value< void * >()); return selectedControl; } QString JigsawSetupDialog::selectedControlName() { - return QString(m_ui->controlNetworkComboBox->currentText()); + return QString(m_ui->inputControlNetCombo->currentText()); } + + + /** + * @brief updateBundleObservationSolveSettings: This function sets the parameters of + * a BundleObservationSolveSettings object by reading user settings from the BOSS + * tab, as well as reading in the selected images on the BOSS QTreeView these + * BOSS settings are to be applied to. + * @param BundleObservationSolveSettings &boss The object which stores user-specified + * settings from the BOSS tab. + */ + void JigsawSetupDialog::updateBundleObservationSolveSettings(BundleObservationSolveSettings &boss) + { + + int ckSolveDegree = m_ui->ckSolveDegreeSpinBox->value(); + int spkSolveDegree = m_ui->spkSolveDegreeSpinBox->value(); + int ckDegree = m_ui->ckDegreeSpinBox->value(); + int spkDegree = m_ui->spkDegreeSpinBox->value(); + int instrumentPointingSolveOption=m_ui->pointingComboBox->currentIndex(); + int instrumentPositionSolveOption=m_ui->positionComboBox->currentIndex(); + + BundleObservationSolveSettings::InstrumentPointingSolveOption pointSolvingOption; + BundleObservationSolveSettings::InstrumentPositionSolveOption positionSolvingOption; + + double anglesAprioriSigma(-1.0); + double angularVelocityAprioriSigma(-1.0); + double angularAccelerationAprioriSigma(-1.0); + QList<double> additionalAngularCoefficients; + + double positionAprioriSigma(-1.0); + double velocityAprioriSigma(-1.0); + double accelerationAprioriSigma(-1.0); + QList<double> additionalPositionCoefficients; + + bool solveTwist(false); + bool solvePolynomialOverExisting(false); + bool positionOverHermite(false); + + if (m_ui->pointingAprioriSigmaTable->item(0,3)) + anglesAprioriSigma = m_ui->pointingAprioriSigmaTable->item(0,3)->data(0).toDouble(); + + if (m_ui->pointingAprioriSigmaTable->item(1,3)) + angularVelocityAprioriSigma = m_ui->pointingAprioriSigmaTable->item(1,3)->data(0).toDouble(); + + if (m_ui->pointingAprioriSigmaTable->item(2,3) ) + angularAccelerationAprioriSigma = m_ui->pointingAprioriSigmaTable->item(2,3)->data(0).toDouble(); + + if (m_ui->positionAprioriSigmaTable->item(0,3)) + positionAprioriSigma = m_ui->positionAprioriSigmaTable->item(0,3)->data(0).toDouble(); + + if (m_ui->positionAprioriSigmaTable->item(1,3)) + velocityAprioriSigma = m_ui->positionAprioriSigmaTable->item(1,3)->data(0).toDouble(); + + if (m_ui->positionAprioriSigmaTable->item(2,3) ) + accelerationAprioriSigma = m_ui->positionAprioriSigmaTable->item(2,3)->data(0).toDouble(); + + //Saving additionalPositional/Angular coefficients (deg >=3) in case they are needed + //later. + if (spkSolveDegree >2) { + for (int i = 3;i <= spkSolveDegree;i++ ) { + if (m_ui->positionAprioriSigmaTable->item(i,3)) + additionalPositionCoefficients.append(m_ui->positionAprioriSigmaTable->item(i,3)->data(0).toDouble() ); + } + } + + if (ckSolveDegree > 2) { + for (int i = 3;i <= ckSolveDegree;i++ ) { + if (m_ui->pointingAprioriSigmaTable->item(i,3)) + additionalAngularCoefficients.append(m_ui->pointingAprioriSigmaTable->item(i,3)->data(0).toDouble() ); + } + + } + + + if (m_ui->twistCheckBox->checkState() == Qt::Checked) + solveTwist = true; + if (m_ui->fitOverPointingCheckBox->checkState() == Qt::Checked) + solvePolynomialOverExisting = true; + if (m_ui->hermiteSplineCheckBox->checkState() == Qt::Checked) + positionOverHermite = true; + + switch(instrumentPointingSolveOption) { + + case 0: pointSolvingOption = BundleObservationSolveSettings::InstrumentPointingSolveOption::NoPointingFactors; + break; + case 1:pointSolvingOption = BundleObservationSolveSettings::InstrumentPointingSolveOption::AnglesOnly; + break; + case 2:pointSolvingOption = BundleObservationSolveSettings::InstrumentPointingSolveOption::AnglesVelocity; + break; + case 3:pointSolvingOption = BundleObservationSolveSettings::InstrumentPointingSolveOption::AnglesVelocityAcceleration; + break; + + case 4:pointSolvingOption = BundleObservationSolveSettings::InstrumentPointingSolveOption::AllPointingCoefficients; + break; + default: pointSolvingOption = BundleObservationSolveSettings::InstrumentPointingSolveOption::NoPointingFactors; + break; + + } + + switch(instrumentPositionSolveOption) { + + case 0: positionSolvingOption = BundleObservationSolveSettings::InstrumentPositionSolveOption::NoPositionFactors; + break; + case 1:positionSolvingOption = BundleObservationSolveSettings::InstrumentPositionSolveOption::PositionOnly; + break; + case 2:positionSolvingOption = BundleObservationSolveSettings::InstrumentPositionSolveOption::PositionVelocity; + break; + case 3:positionSolvingOption = BundleObservationSolveSettings::InstrumentPositionSolveOption::PositionVelocityAcceleration; + break; + + case 4:positionSolvingOption = BundleObservationSolveSettings::InstrumentPositionSolveOption::AllPositionCoefficients; + break; + default: positionSolvingOption = BundleObservationSolveSettings::InstrumentPositionSolveOption::NoPositionFactors; + break; + + } + + + boss.setInstrumentPositionSettings(positionSolvingOption,spkDegree,spkSolveDegree,positionOverHermite, + positionAprioriSigma,velocityAprioriSigma,accelerationAprioriSigma, + &additionalPositionCoefficients); + + boss.setInstrumentPointingSettings(pointSolvingOption,solveTwist,ckDegree,ckSolveDegree,solvePolynomialOverExisting, + anglesAprioriSigma,angularVelocityAprioriSigma,angularAccelerationAprioriSigma, + &additionalAngularCoefficients); + + //What if multiple instrument IDs are represented? + boss.setInstrumentId(""); + + + SortFilterProxyModel* proxyModel = (SortFilterProxyModel *)m_ui->treeView->model(); + ProjectItemModel* sourceModel = (ProjectItemModel *)proxyModel->sourceModel(); + QModelIndexList selectedIndexes = m_ui->treeView->selectionModel()->selectedIndexes(); + + foreach (QModelIndex index, selectedIndexes) { + + QModelIndex sourceix = proxyModel->mapToSource(index); + ProjectItem * projItem = sourceModel->itemFromIndex(sourceix); + + if (projItem) { + + if (projItem->isImage() ) { + Image * img = projItem->data().value<Image *>(); + boss.addObservationNumber(img->observationNumber() ); + + } + } + + } + + } + QString JigsawSetupDialog::outputControlName() { - return QString(m_ui->outputControlNet->text()); + return QString(m_ui->outputControlNetLineEdit->text()); } void JigsawSetupDialog::makeReadOnly() { - m_ui->controlNetworkComboBox->setEnabled(false); + m_ui->inputControlNetCombo->setEnabled(false); m_ui->observationModeCheckBox->setEnabled(false); - m_ui->radiusCheckBox->setEnabled(false); - m_ui->updateCubeLabelCheckBox->setEnabled(false); + m_ui->pointRadiusSigmaCheckBox->setEnabled(false); + // m_ui->updateCubeLabelCheckBox->setEnabled(false); m_ui->errorPropagationCheckBox->setEnabled(false); m_ui->outlierRejectionCheckBox->setEnabled(false); m_ui->outlierRejectionMultiplierLineEdit->setEnabled(false); m_ui->sigma0ThresholdLineEdit->setEnabled(false); m_ui->maximumIterationsLineEdit->setEnabled(false); - m_ui->positionComboBox->setEnabled(false); + // m_ui->positionComboBox->setEnabled(false); m_ui->hermiteSplineCheckBox->setEnabled(false); m_ui->spkDegreeSpinBox->setEnabled(false); m_ui->spkSolveDegreeSpinBox->setEnabled(false); m_ui->twistCheckBox->setEnabled(false); - m_ui->pointingComboBox->setEnabled(false); + // m_ui->pointingComboBox->setEnabled(false); m_ui->fitOverPointingCheckBox->setEnabled(false); m_ui->ckDegreeSpinBox->setEnabled(false); m_ui->ckSolveDegreeSpinBox->setEnabled(false); - // weighting tab - m_ui->pointLatitudeSigmaLineEdit->setEnabled(false); - m_ui->pointLongitudeSigmaLineEdit->setEnabled(false); - m_ui->pointRadiusSigmaLineEdit->setEnabled(false); - m_ui->positionSigmaLineEdit->setEnabled(false); - m_ui->velocitySigmaLineEdit->setEnabled(false); - m_ui->accelerationSigmaLineEdit->setEnabled(false); - m_ui->pointingAnglesSigmaLineEdit->setEnabled(false); - m_ui->pointingAngularVelocitySigmaLineEdit->setEnabled(false); - m_ui->pointingAngularAccelerationSigmaLineEdit->setEnabled(false); - - // maximum liklihood tab - - // self-calibration tab + // observation solve settings tab + m_ui->treeView->setEnabled(false); + m_ui->positionComboBox->setEnabled(false); + m_ui->spkSolveDegreeSpinBox->setEnabled(false); + m_ui->spkDegreeSpinBox->setEnabled(false); + m_ui->hermiteSplineCheckBox->setEnabled(false); + m_ui->positionAprioriSigmaTable->setEnabled(false); + m_ui->pointingComboBox->setEnabled(false); + m_ui->ckSolveDegreeSpinBox->setEnabled(false); + m_ui->ckDegreeSpinBox->setEnabled(false); + m_ui->twistCheckBox->setEnabled(false); + m_ui->fitOverPointingCheckBox->setEnabled(false); + m_ui->pointingAprioriSigmaTable->setEnabled(false); + m_ui->applySettingsPushButton->setEnabled(false); // target body tab m_ui->targetBodyComboBox->setEnabled(false); @@ -863,7 +1058,7 @@ namespace Isis { // if we're not solving for target body triaxial radii or mean radius, we CAN solve for point // radii so we ensure the point radius checkbox under the general settings tab is enabled - m_ui->radiusCheckBox->setEnabled(true); + m_ui->pointRadiusSigmaCheckBox->setEnabled(true); } else if (arg1 == 1) { m_ui->aRadiusLabel->setEnabled(true); @@ -881,8 +1076,8 @@ namespace Isis { // if we're solving for target body mean radius, we can't solve for point radii // so we uncheck and disable the point radius checkbox under the general settings tab // and remind the user - m_ui->radiusCheckBox->setChecked(false); - m_ui->radiusCheckBox->setEnabled(false); + m_ui->pointRadiusSigmaCheckBox->setChecked(false); + m_ui->pointRadiusSigmaCheckBox->setEnabled(false); QMessageBox *msgBox = new QMessageBox(QMessageBox::Information, "Triaxial Radii Reminder!", "Individual point radii and target body triaxial radii can't be solved for" @@ -906,8 +1101,8 @@ namespace Isis { // if we're solving for target body triaxial radii, we can't solve for point radii // so we uncheck and disable the point radius checkbox under the general settings tab // and remind the user - m_ui->radiusCheckBox->setChecked(false); - m_ui->radiusCheckBox->setEnabled(false); + m_ui->pointRadiusSigmaCheckBox->setChecked(false); + m_ui->pointRadiusSigmaCheckBox->setEnabled(false); QMessageBox *msgBox = new QMessageBox(QMessageBox::Information, "Mean Radius Reminder!", "Individual point radii and target body mean radius can't be solved for" @@ -990,47 +1185,6 @@ namespace Isis { } - void Isis::JigsawSetupDialog::on_spkSolveDegreeSpinBox_2_valueChanged(int arg1) { - if (arg1 == -1) { - m_ui->spkSolveDegreeSpinBox_2->setSuffix("(NONE)"); - m_ui->positionAprioriSigmaTable->setRowCount(0); - } - m_ui->positionAprioriSigmaTable->setRowCount(arg1+1); - m_ui->positionAprioriSigmaTable->resizeColumnsToContents(); - - if (arg1 == 0) { - QTableWidgetItem *twItem = new QTableWidgetItem(); - twItem->setText("POSITION"); - m_ui->positionAprioriSigmaTable->setItem(arg1,0, twItem); - QTableWidgetItem *twItemunits = new QTableWidgetItem(); - twItemunits->setText("meters"); - //m_ui->positionAprioriSigmaTable->item(arg1,2)->setText("meters"); - } - else if (arg1 == 1) { - m_ui->positionAprioriSigmaTable->item(arg1,0)->setText("VELOCITY"); - m_ui->positionAprioriSigmaTable->item(arg1,2)->setText("m/sec"); - } - else if (arg1 == 2) { - m_ui->positionAprioriSigmaTable->item(arg1,0)->setText("ACCELERATION"); - m_ui->positionAprioriSigmaTable->item(arg1,2)->setText("m/s^2"); - } - /* - else if (arg1 == 0) { - m_ui->spkSolveDegreeSpinBox_2->setSuffix("(POSITION)"); - int nRows = m_ui->positionAprioriSigmaTable->rowCount(); - - m_ui->positionAprioriSigmaTable->insertRow(nRows); - } - else if (arg1 == 1) - m_ui->spkSolveDegreeSpinBox_2->setSuffix("(VELOCITY)"); - else if (arg1 == 2) - m_ui->spkSolveDegreeSpinBox_2->setSuffix("(ACCELERATION)"); - else - m_ui->spkSolveDegreeSpinBox_2->setSuffix(""); - */ - } - - void Isis::JigsawSetupDialog::on_rightAscensionLineEdit_textChanged(const QString &arg1) { if (!m_ui->rightAscensionLineEdit->hasAcceptableInput()) { m_ui->rightAscensionLineEdit->setStyleSheet("QLineEdit { background-color: red }"); @@ -1108,6 +1262,129 @@ namespace Isis { update(); } + // general tab text validation + // global apriori point sigmas + void Isis::JigsawSetupDialog::on_pointLatitudeSigmaLineEdit_textChanged(const QString &arg1) { + if (arg1 == "" || m_ui->pointLatitudeSigmaLineEdit->hasAcceptableInput()) { + m_ui->pointLatitudeSigmaLineEdit->setStyleSheet("QLineEdit { background-color: white }"); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + } + else { + m_ui->pointLatitudeSigmaLineEdit->setStyleSheet("QLineEdit { background-color: red }"); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } + update(); + } + + void Isis::JigsawSetupDialog::on_pointLongitudeSigmaLineEdit_textChanged(const QString &arg1) { + if (arg1 == "" || m_ui->pointLongitudeSigmaLineEdit->hasAcceptableInput()) { + m_ui->pointLongitudeSigmaLineEdit->setStyleSheet("QLineEdit { background-color: white }"); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + } + else { + m_ui->pointLongitudeSigmaLineEdit->setStyleSheet("QLineEdit { background-color: red }"); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } + update(); + } + + + void Isis::JigsawSetupDialog::on_pointRadiusSigmaLineEdit_textChanged(const QString &arg1) { + if (arg1 == "" || m_ui->pointRadiusSigmaLineEdit->hasAcceptableInput()) { + m_ui->pointRadiusSigmaLineEdit->setStyleSheet("QLineEdit { background-color: white }"); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + } + else { + m_ui->pointRadiusSigmaLineEdit->setStyleSheet("QLineEdit { background-color: red }"); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } + update(); + } + + // outlier rejection + void Isis::JigsawSetupDialog::on_maximumLikelihoodModel1QuantileLineEdit_textChanged(const QString &arg1) { + if (!m_ui->maximumLikelihoodModel1QuantileLineEdit->isEnabled() || + m_ui->maximumLikelihoodModel1QuantileLineEdit->hasAcceptableInput()) { + m_ui->maximumLikelihoodModel1QuantileLineEdit->setStyleSheet(""); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + } + else { + m_ui->maximumLikelihoodModel1QuantileLineEdit->setStyleSheet("QLineEdit { background-color: red }"); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } + update(); + } + + + void Isis::JigsawSetupDialog::on_maximumLikelihoodModel2QuantileLineEdit_textChanged(const QString &arg1) { + if (!m_ui->maximumLikelihoodModel2QuantileLineEdit->isEnabled() || + m_ui->maximumLikelihoodModel2QuantileLineEdit->hasAcceptableInput()) { + m_ui->maximumLikelihoodModel2QuantileLineEdit->setStyleSheet(""); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + } + else { + m_ui->maximumLikelihoodModel2QuantileLineEdit->setStyleSheet("QLineEdit { background-color: red }"); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } + update(); + } + + + void Isis::JigsawSetupDialog::on_maximumLikelihoodModel3QuantileLineEdit_textChanged(const QString &arg1) { + if (!m_ui->maximumLikelihoodModel3QuantileLineEdit->isEnabled() || + m_ui->maximumLikelihoodModel3QuantileLineEdit->hasAcceptableInput()) { + m_ui->maximumLikelihoodModel3QuantileLineEdit->setStyleSheet(""); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + } + else { + m_ui->maximumLikelihoodModel3QuantileLineEdit->setStyleSheet("QLineEdit { background-color: red }"); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } + update(); + } + + + // convergence criteria + void Isis::JigsawSetupDialog::on_outlierRejectionMultiplierLineEdit_textChanged(const QString &arg1) { + if (!m_ui->outlierRejectionCheckBox->isChecked() || + m_ui->outlierRejectionMultiplierLineEdit->hasAcceptableInput()) { + m_ui->outlierRejectionMultiplierLineEdit->setStyleSheet(""); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + } + else { + m_ui->outlierRejectionMultiplierLineEdit->setStyleSheet("QLineEdit { background-color: red }"); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } + update(); + } + + + void Isis::JigsawSetupDialog::on_sigma0ThresholdLineEdit_textChanged(const QString &arg1) { + if (m_ui->sigma0ThresholdLineEdit->hasAcceptableInput()) { + m_ui->sigma0ThresholdLineEdit->setStyleSheet("QLineEdit { background-color: white }"); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + } + else { + m_ui->sigma0ThresholdLineEdit->setStyleSheet("QLineEdit { background-color: red }"); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } + update(); + } + + + void Isis::JigsawSetupDialog::on_maximumIterationsLineEdit_textChanged(const QString &arg1) { + if (m_ui->maximumIterationsLineEdit->hasAcceptableInput()) { + m_ui->maximumIterationsLineEdit->setStyleSheet("QLineEdit { background-color: white }"); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + } + else { + m_ui->maximumIterationsLineEdit->setStyleSheet("QLineEdit { background-color: red }"); + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } + update(); + } + + void JigsawSetupDialog::showTargetParametersGroupBox() { m_ui->targetParametersGroupBox->setEnabled(true); } @@ -1117,8 +1394,492 @@ namespace Isis { m_ui->targetParametersGroupBox->setEnabled(false); } - void Isis::JigsawSetupDialog::on_controlNetworkComboBox_currentTextChanged(const QString &arg1) { + void Isis::JigsawSetupDialog::on_inputControlNetCombo_currentTextChanged(const QString &arg1) { FileName fname = arg1; - m_ui->outputControlNet->setText(fname.baseName() + "-out.net"); + m_ui->outputControlNetLineEdit->setText(fname.baseName() + "-out.net"); } + + + /** + * Validates the a priori sigma values for a given QTableWidgetItem. + * + * This will only validate items in the a priori sigma column. Valid a priori sigma values are + * "FREE" or any positive double. Items that are invalid will be marked with a red background + * color. + * + * @param QTableWidgetItem* Pointer to the QTableWidgetItem to be validated. + */ + void JigsawSetupDialog::validateSigmaValue(QTableWidgetItem *item) { + // Only validate the "a priori sigma" column + if (item->column() != 3) { + return; + } + // FREE is a valid value for the a priori sigma column + int free = item->text().simplified().compare("FREE", Qt::CaseInsensitive); + + // Positive doubles are valid values for the a priori sigma column + bool convertSuccess = false; + double sigma = item->text().toDouble(&convertSuccess); + if ((convertSuccess && sigma >= 0.0) || free == 0) { + const QTableWidget *table = item->tableWidget(); + item->setData(Qt::UserRole, QVariant(true)); + // Set background color depending on if the table has alternating row colors and row is odd + if (table->alternatingRowColors() && item->row() % 2 != 0) { + item->setBackground(table->palette().color(QPalette::AlternateBase)); + } + else { + item->setBackground(table->palette().color(QPalette::Base)); + } + + if (sigma == 0.0) { + item->setText("FREE"); + } + } + else { + item->setData(Qt::UserRole, QVariant(false)); + item->setBackground(Qt::red); + } + + validateSigmaTables(); + } + + + /** + * Validates the tables in the observation solve settings tab and enables/disables the OK + * button appropriately. + * + * This method validates both the position and pointing a priori sigma tables in the observation + * solve settings tab. If any of the sigma values are invalid, the JigsawSetupDialog's OK button + * is disabled. If all of the sigma values are valid, the JigsawSetupDialog's OK button is + * (re)enabled. + */ + void JigsawSetupDialog::validateSigmaTables() { + bool tablesAreValid = true; + + // Evaluate both tables; if any value is invalid, the table is invalid + QList<const QTableWidget *> tables{m_ui->positionAprioriSigmaTable, + m_ui->pointingAprioriSigmaTable}; + + for (const auto &table : tables) { + for (int i = 0; i < table->rowCount(); i++) { + // a priori sigma column is column 3 + const QTableWidgetItem *item = table->item(i,3); + if (item) { + if (item->data(Qt::UserRole).toBool() == false) { + tablesAreValid = false; + break; + } + } + } + } + + m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(tablesAreValid); + if (!m_ui->treeView->selectionModel()->selectedRows().isEmpty()) { + m_ui->applySettingsPushButton->setEnabled(tablesAreValid); + } + } + + + /** + * Slot that listens for changes to the SPK Solve Degree spin box. + * + * This slot populates the Instrument Position Solve Options table according to the value of the + * SPK Solve Degree. Rows are added depending on the degree set, where number of rows added is + * equal to the SPK Solve Degree + 1. Note that this relies on the updateSolveSettingsSigmaTables + * slot, which uses the SPK Solve Degree if the ALL position option is selected. + * + * @param int Value the SPK Solve Degree spin box was changed to. + */ + void JigsawSetupDialog::on_spkSolveDegreeSpinBox_valueChanged(int i) { + // Update the position apriori sigma table and use the position combo box solve option + updateSolveSettingsSigmaTables(m_ui->positionComboBox, m_ui->positionAprioriSigmaTable); + } + + + /** + * Slot that listens for changes to the CK Solve Degree spin box. + * + * This slot populates the Instrument Pointing Solve Options table according to the value of the + * CK Solve Degree. Rows are added depending on the degree set, where number of rows added is + * equal to the CK Solve Degree + 1. Note that this relies on the updateSolveSettingsSigmaTables + * slot, which uses the CK Solve Degree if the ALL pointing option is selected. + * + * @param int Value the CK Solve Degree spin box was changed to. + */ + void JigsawSetupDialog::on_ckSolveDegreeSpinBox_valueChanged(int i) { + // Update the pointing apriori sigma table and use the pointing combo box solve option + updateSolveSettingsSigmaTables(m_ui->pointingComboBox, m_ui->pointingAprioriSigmaTable); + } + + + /** + * Slot that updates the sigma tables based on the current solve option selection. + * + * This will add/remove rows based on the solve option selected, and if ALL, the current + * solve degree value. + * + * @param const QComboBox * The solve option combo box to read the solve option from + * @param QTableWidget * The a priori sigma table we are going to update rows for + */ + void JigsawSetupDialog::updateSolveSettingsSigmaTables(const QComboBox *solveOptionComboBox, + QTableWidget *table) { + int rowCount = solveOptionComboBox->currentIndex(); + + // Position: { NONE, POSITION, VELOCITY, ACCELERATION, ALL } + // Pointing: { NONE, ANGLES, ANGULAR VELOCITY, ANGULAR ACCELERATION, ALL } + // Need to add to the solve degree value since number of rows == number of solve coefficients, + // and for our polynomials the number of solve coefficients == solve degree + 1 + // When solve option is ALL (index 4), use the spk/ck solve degree value + 1 for number of rows + if (rowCount == 4) { + if (solveOptionComboBox == m_ui->positionComboBox) { + rowCount = m_ui->spkSolveDegreeSpinBox->value() + 1; + } + else { // if (solveOptionComboBox == m_ui->pointingComboBox) + rowCount = m_ui->ckSolveDegreeSpinBox->value() + 1; + } + } + + // number of rows == position solve option == SolveDegree value + 1 (i+1) + const int oldRowCount = table->rowCount(); + // if solving ALL, don't add extra row + table->setRowCount(rowCount); + const int newRowCount = table->rowCount(); + + // Need to check if table is valid in case a row is removed (a row is removed implicitly when + // the setRowCount() is called when newRowCount < oldRowCount + validateSigmaTables(); + + // Determine the units for either position or pointing + QStringList solveOptions; + QString longUnits("N/A"); + QString shortUnits("N/A"); + if (solveOptionComboBox == m_ui->positionComboBox) { + longUnits = "meters"; + shortUnits = "m"; + solveOptions += {"POSITION", "VELOCITY", "ACCELERATION"}; + } + else { // if (solveOptionComboBox == m_ui->pointingComboBox) { + longUnits = "degrees"; + shortUnits = "deg"; + solveOptions += {"ANGLES", "ANGULAR VELOCITY", "ANGULAR ACCELERATION"}; + } + + // Rows need to be added + if (newRowCount > oldRowCount) { + for (int row = oldRowCount; row < newRowCount; row++) { + // Headers : coefficient, description, units, a priori sigma + QTableWidgetItem *coefficient = new QTableWidgetItem(); + coefficient->setFlags(Qt::ItemIsEnabled); + coefficient->setText(QString::number(row + 1)); + table->setItem(row, 0, coefficient); + + QTableWidgetItem *description = new QTableWidgetItem(); + description->setFlags(Qt::ItemIsEnabled); + description->setText("N/A"); + table->setItem(row, 1, description); + + QTableWidgetItem *units = new QTableWidgetItem(); + units->setFlags(Qt::ItemIsEnabled); + units->setText(shortUnits + "/s^" + QString::number(row)); + table->setItem(row, 2, units); + + QTableWidgetItem *sigma = new QTableWidgetItem(); + sigma->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); + sigma->setText("0.0"); + sigma->setData(Qt::UserRole, QVariant(true)); + table->setItem(row, 3, sigma); + + // Solve option: spk degree { NONE: -1, POSITION: 0, VELOCITY: 1, ACCELERATION: 2, ALL: 2 } + // POSITION + if (row == 0) { + QTableWidgetItem *description = table->item(0, 1); + description->setText(solveOptions.at(row)); + + QTableWidgetItem *units = table->item(0, 2); + units->setText(longUnits); + } + + // VELOCITY + else if (row == 1) { + QTableWidgetItem *description = table->item(1, 1); + description->setText(solveOptions.at(row)); + + QTableWidgetItem *units = table->item(1, 2); + units->setText(shortUnits + "/s"); + } + + // ACCELERATION + else if (row == 2) { + QTableWidgetItem *description = table->item(2, 1); + description->setText(solveOptions.at(row)); + + QTableWidgetItem *units = table->item(2, 2); + units->setText(shortUnits + "/s^2"); + } + } + } + + table->resizeColumnToContents(1); + table->resizeColumnToContents(2); + } + + + /** + * Slot that listens for when the Instrument Position Solve Option combobox changes. + * + * This slot updates the value of the SPK Solve Degree spin box according to which solve position + * option is selected. This slot also disables the SPK spin boxes whenever a solve + * position that is not ALL is selected. + * + * @param const QString & Reference to the value that the position option combobox was changed to. + */ + void JigsawSetupDialog::on_positionComboBox_currentIndexChanged(const QString &arg1) { + int solveIndex = m_ui->positionComboBox->currentIndex(); + QList<QSpinBox *> spinBoxes{m_ui->spkSolveDegreeSpinBox, m_ui->spkDegreeSpinBox}; + for (auto &spinBox : spinBoxes) { + // ALL enables the solve degree spin box, but does not increase the degree + // Below shows the corresponding degree for each of the solve options: + // NONE = -1; ANGLES = 0; VELOCITY = 1; ACCELERATION = 2; ALL = 2 + if (arg1 == "ALL") { + spinBox->setValue(solveIndex - 2); + spinBox->setEnabled(true); + } + else { + // The default value for the spk solve degree and spk degree spinboxes is 2. This is + // emulating jigsaw's defaults for position solve options that are not ALL. + spinBox->setValue(2); + spinBox->setEnabled(false); + } + } + + updateSolveSettingsSigmaTables(m_ui->positionComboBox, m_ui->positionAprioriSigmaTable); + } + + + /** + * Slot that listens for when the Instrument Pointing Solve Option combobox changes. + * + * This slot updates the value of the CK Solve Degree spin box according to which solve pointing + * option is selected. This slot also disables the CK spin boxes whenever a solve + * pointing that is not ALL is selected. + * + * @param const QString & Reference to the value that the pointing option combobox was changed to. + */ + void JigsawSetupDialog::on_pointingComboBox_currentIndexChanged(const QString &arg1) { + int solveIndex = m_ui->pointingComboBox->currentIndex(); + QList<QSpinBox *> spinBoxes{m_ui->ckSolveDegreeSpinBox, m_ui->ckDegreeSpinBox}; + for (auto &spinBox : spinBoxes) { + // ALL enables the solve degree spin box, but does not increase the degree + // Below shows the corresponding degree for each of the solve options: + // NONE = -1; ANGLES = 0; ANGULAR VELOCITY = 1; ANGULAR ACCELERATION = 2; ALL = 2 + if (arg1 == "ALL") { + spinBox->setValue(solveIndex - 2); + spinBox->setEnabled(true); + } + else { + // The default value for the ck solve degree and spk degree spinboxes is 2. This is + // emulating jigsaw's defaults for pointing solve options that are not ALL. + spinBox->setValue(2); + spinBox->setEnabled(false); + } + } + + updateSolveSettingsSigmaTables(m_ui->pointingComboBox, m_ui->pointingAprioriSigmaTable); + } + + + + void JigsawSetupDialog::createObservationSolveSettingsTreeView() { + + QList<ProjectItem *> selectedBOSSItems = m_project->directory()->model()->selectedBOSSImages(); + + ProjectItemModel *model = m_project->directory()->model(); + + SortFilterProxyModel *osspm = new SortFilterProxyModel; + osspm->setSourceModel(model); + + //osspm->setDynamicSortFilter(true); + osspm->setSelectedItems(selectedBOSSItems ); + m_ui->treeView->setModel(osspm); + + + + + ProjectItem *imgRoot = model->findItemData(QVariant("Images"),0); + if (imgRoot) { + + m_ui->treeView->setRootIndex(osspm->mapFromSource(imgRoot->index())); + } + else { + m_ui->treeView->setRootIndex(QModelIndex()); + } + + connect(m_ui->treeView->selectionModel(), + SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), + this, + SLOT(treeViewSelectionChanged(const QItemSelection&,const QItemSelection&))); + + + // Try to loop through the view here to add the "groups" so they aren't part of the model + + // Add apply button to the tab view + // set the text to bold? + + + } + + + void JigsawSetupDialog::treeViewSelectionChanged(const QItemSelection &selected, + const QItemSelection &deselected) { + QModelIndexList indexList = m_ui->treeView->selectionModel()->selectedRows(); + + // qDebug() << "\n\nselected: " << selected.indexes(); + // qDebug() << "deselected: " << deselected.indexes(); + // qDebug() << "selectedRows: " << m_ui->treeView->selectionModel()->selectedRows(); + + + if (!indexList.isEmpty()) { + QModelIndex displayIndex = indexList[0]; + + SortFilterProxyModel * proxyModel = (SortFilterProxyModel *) m_ui->treeView->model(); + ProjectItemModel *sourceModel = (ProjectItemModel *) proxyModel->sourceModel(); + + QModelIndex sourceIndex = proxyModel->mapToSource(displayIndex); + ProjectItem * projItem = sourceModel->itemFromIndex(sourceIndex); + + if (projItem->isImageList()) { + projItem = projItem->child(0); + } + BundleObservationSolveSettings settings = m_bundleSettings->observationSolveSettings( + projItem->image()->observationNumber()); + + // Populate RHS of Observation Solve Settings tab with selected image's BOSS + // Instrument Position Solve Options + m_ui->positionComboBox->setCurrentIndex(settings.instrumentPositionSolveOption()); + m_ui->spkSolveDegreeSpinBox->setValue(settings.spkSolveDegree()); + m_ui->spkDegreeSpinBox->setValue(settings.spkDegree()); + m_ui->hermiteSplineCheckBox->setChecked(settings.solvePositionOverHermite()); + + for (int row = 0; row < settings.aprioriPositionSigmas().count(); row++) { + QTableWidgetItem * sigmaItem = m_ui->positionAprioriSigmaTable->item(row, 3); + double sigma = settings.aprioriPositionSigmas()[row]; + if (sigma == Isis::Null) { + sigmaItem->setText("FREE"); + } + else { + sigmaItem->setText(QString::number(sigma)); + } + } + + // Instrument Pointing Solve Options + m_ui->pointingComboBox->setCurrentIndex(settings.instrumentPointingSolveOption()); + m_ui->ckSolveDegreeSpinBox->setValue(settings.ckSolveDegree()); + m_ui->ckDegreeSpinBox->setValue(settings.ckDegree()); + m_ui->twistCheckBox->setChecked(settings.solveTwist()); + m_ui->fitOverPointingCheckBox->setChecked(settings.solvePolyOverPointing()); + + for (int row = 0; row < settings.aprioriPointingSigmas().count(); row++) { + QTableWidgetItem * sigmaItem = m_ui->pointingAprioriSigmaTable->item(row, 3); + double sigma = settings.aprioriPointingSigmas()[row]; + if (sigma == Isis::Null) { + sigmaItem->setText("FREE"); + } + else { + sigmaItem->setText(QString::number(sigma)); + } + } + + } + + m_ui->applySettingsPushButton->setEnabled(!selected.isEmpty()); + } + + + + /** + * Slot for handling the Observation Solve Settings tab's Apply button. Retrieve's the selected + * ProjectItems and adds their images' serial numbers to a new BundleObservationSolveSettings + * object. Serial numbers will be removed from all other BOSS objects, and empty BOSS objects will + * be removed. + */ + void JigsawSetupDialog::on_applySettingsPushButton_clicked() { + + // Get the current selected images and the item models + SortFilterProxyModel * proxyModel = (SortFilterProxyModel *) m_ui->treeView->model(); + ProjectItemModel *sourceModel = (ProjectItemModel *) proxyModel->sourceModel(); + + QModelIndexList selectedIndexes = m_ui->treeView->selectionModel()->selectedIndexes(); + QStringList selectedObservationNumbers; + + // Append selected images' serial numbers to selectedObservationNumbers + foreach (QModelIndex index, selectedIndexes) { + QModelIndex sourceIndex = proxyModel->mapToSource(index); + ProjectItem * projItem = sourceModel->itemFromIndex(sourceIndex); + + if (projItem) { + // Tree traversal is top down so we dont need to do this check for imagelists? + if (projItem->isImage()) { + // Grab the observation up front so we don't need to re-compose the observation number + // more than once (@todo: this should not be necessary when 5026 is integrated) + const QString observationNumber = projItem->image()->observationNumber(); + if (!selectedObservationNumbers.contains(observationNumber)) { + selectedObservationNumbers.append(observationNumber); + } + } + else if (projItem->isImageList()) { + // Use the proxymodel's children as it might not include all of the sourcemodel's children + for (int i = 0; i < proxyModel->rowCount(index); i++) { + QModelIndex childProxyIndex = proxyModel->index(i, 0, index); + QModelIndex childSourceIndex = proxyModel->mapToSource(childProxyIndex); + ProjectItem * childItem = sourceModel->itemFromIndex(childSourceIndex); + selectedObservationNumbers.append(childItem->image()->observationNumber()); + } + } + } + } + + QList<BundleObservationSolveSettings> solveSettingsList = m_bundleSettings->observationSolveSettings(); + + //find the bundle observation solve settings for each of the selected observations and remove + // the observation number from them + for (auto &solveSettings : solveSettingsList) { + foreach (QString observationNumber, selectedObservationNumbers) { + solveSettings.removeObservationNumber(observationNumber); + } + } + + + // Remove any existing solve settings that no longer have any observation numbers + int iter = 0; + while (iter < solveSettingsList.count()) { + if (solveSettingsList[iter].observationNumbers().isEmpty() ) { + solveSettingsList.removeAt(iter); + } + else { + iter++; // This list shrinks as we remove, so we dont need to iterate every time + } + } + + // Create a new bundle observation solve settings + BundleObservationSolveSettings solveSettings; + foreach (QString observationNumber, selectedObservationNumbers) { + solveSettings.addObservationNumber(observationNumber); + } + + // Grab the data from the right hand side of the observation solve settings tab to set + // up the new bundle observation solve settings + updateBundleObservationSolveSettings(solveSettings); + + // Add the new solve settings to the solve settings list + solveSettingsList.append(solveSettings); + + // Update bundle settings with the new list of bundle observation solve settings + m_bundleSettings->setObservationSolveOptions(solveSettingsList); + + // qDebug()<<"Current BOSS list --------"; + // for (int i = 0; i < solveSettingsList.count(); i++) { + // qDebug() << "solveSettingsList["<<i<<"]: " << solveSettingsList[i].observationNumbers(); + // } + } + } diff --git a/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.h b/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.h index 7cc6e2e5409562845c158a5c02d9f8db11660af9..0676933761c42cdf360c49b50caf01b3fc223897 100644 --- a/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.h +++ b/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.h @@ -9,8 +9,15 @@ namespace Ui { class JigsawSetupDialog; } +class QComboBox; +class QItemSelection; +class QTableWidget; +class QTableWidgetItem; + namespace Isis { + class BundleObservationSolveSettings; class Project; + class ProjectItem; class Control; /** @@ -36,9 +43,9 @@ namespace Isis { * @history 2016-08-18 Jeannie Backer - Removed all references to deprecated solve methods * SpeckialK and OldSparse. References #4162. * @history 2016-08-25 Adam Paquette - Updated documentation. Fixes #4299. - * @history 2017-04-25 Ian Humphrey - Added public loadSettings() to allow JigsawDialog to + * @history 2017-04-25 Ian Humphrey - Added public loadSettings() to allow JigsawRunWidget to * load its current settings into the setup dialog. Fixes #4817. - * @history 2017-04-27 Ian Humphrey - Added selectControl() to allow JigsawDialog to + * @history 2017-04-27 Ian Humphrey - Added selectControl() to allow JigsawRunWidget to * properly tell the setup dialog which control to select in its * combo box. References #4817. * @history 2017-05-16 Tracie Sucharski - Comment qDebug statements. @@ -57,8 +64,36 @@ namespace Isis { * fred.net, the output filename QLineEdit is automatically changed to * fred-out.net. The user can always manually change the output control * net name to anything they choose. + * @history 2018-06-01 Christopher Combs - Added support for ui changes, exclusive options and + * input validators. + * @history 2018-06-21 Ian Humphrey - Added on_applySettingsPushButtonClicked() to listen for when + * the apply button is clicked on the observation solve settings tab. + * References #497. + * @history 2018-06-21 Tyler Wilson - Added support in the Bundle Observations Solve Settings + * (BOSS) tab for displaying user-selected images from the main Project + * treeview. All changes were made in the + * createObservationSolveSettingsTreeView() function. References #497. + * @history 2018-06-25 Ian Humphrey - Implemented the position and pointing a priori sigma + * tables in the observation solve settings tab. References #497. + * @history 2018-06-26 Tyler Wilson - Added the function + * updateBundleObservationSolveSettings(BundleObservationSolveSettings &) + * which grabs BOSS settings from the JSD BOSS tab for selected images + * in the BOSS QTreeView and saves them in a BOSS object. + * @history 2018-06-26 Tyler Wilson - Added support in + * updateBundleObservationSolveSettings(BundleObservationSolveSettings &) + * for the user to set an arbitrary number of position/pointing Apriori + * Sigma values beyond position/velocity/acceleration. References #497. + * @history 2018-06-27 Ian Humphrey - Added validateSigmaTables() that checks if there are any + * invalid a priori sigma values whenever an a priori sigma values changes. + * If any value is invalid, the OK and Apply Settings buttons are disabled + * until all the a priori sigma values are valid again. References #497. + * @history 2018-06-28 Christopher Combs - Implemented pseudocode in on_applySettings... method. + * Added selected images to default BOSS object. References #497. + * @history 2018-07-01 Ian Humphrey - Added updateSolveSettingsSigmaTables() to try to + * generalize how the sigma tables are updated. Solve options have + * their respective solve degree and degree combo boxes set to 2 unless + * the solve option is ALL. References #497. */ - class JigsawSetupDialog : public QDialog { Q_OBJECT @@ -80,18 +115,33 @@ namespace Isis { private slots: - void on_radiusCheckBox_toggled(bool checked); + void on_pointRadiusSigmaCheckBox_toggled(bool checked); + //void on_projectItemSelectionChanged(const QList<ProjectItem *> selectedItems); //void on_outlierRejectionCheckBox_toggled(bool checked); // general tab - void on_positionComboBox_currentIndexChanged(int index); - void on_pointingComboBox_currentIndexChanged(int index); - void on_controlNetworkComboBox_currentTextChanged(const QString &arg1); + // void on_positionComboBox_currentIndexChanged(int index); + // void on_pointingComboBox_currentIndexChanged(int index); + void on_inputControlNetCombo_currentTextChanged(const QString &arg1); + + // general tab - line edit validators + void on_pointLatitudeSigmaLineEdit_textChanged(const QString &arg1); + void on_pointLongitudeSigmaLineEdit_textChanged(const QString &arg1); + void on_pointRadiusSigmaLineEdit_textChanged(const QString &arg1); + + void on_outlierRejectionMultiplierLineEdit_textChanged(const QString &arg1); + void on_maximumLikelihoodModel1QuantileLineEdit_textChanged(const QString &arg1); + void on_maximumLikelihoodModel2QuantileLineEdit_textChanged(const QString &arg1); + void on_maximumLikelihoodModel3QuantileLineEdit_textChanged(const QString &arg1); + + void on_sigma0ThresholdLineEdit_textChanged(const QString &arg1); + void on_maximumIterationsLineEdit_textChanged(const QString &arg1); - // maximum liklihood tab + // general tab - outlier rejection exclusivity lock/unlocks void on_maximumLikelihoodModel1ComboBox_currentIndexChanged(int index); void on_maximumLikelihoodModel2ComboBox_currentIndexChanged(int index); void on_maximumLikelihoodModel3ComboBox_currentIndexChanged(int index); + void on_outlierRejectionCheckBox_stateChanged(int arg1); // target body tab void on_poleRaCheckBox_stateChanged(int arg1); @@ -103,28 +153,46 @@ namespace Isis { void on_radiiButtonGroupClicked(int arg1); void on_aRadiusLineEdit_textChanged(const QString &arg1); void on_targetBodyComboBox_currentIndexChanged(int index); - void on_spkSolveDegreeSpinBox_2_valueChanged(int arg1); + void on_spkSolveDegreeSpinBox_valueChanged(int arg1); + void on_ckSolveDegreeSpinBox_valueChanged(int arg1); void on_rightAscensionLineEdit_textChanged(const QString &arg1); void on_declinationLineEdit_textChanged(const QString &arg1); void on_rightAscensionVelocityLineEdit_textChanged(const QString &arg1); void on_declinationVelocityLineEdit_textChanged(const QString &arg1); void on_spinRateLineEdit_textChanged(const QString &arg1); void on_primeMeridianOffsetLineEdit_textChanged(const QString &arg1); + + void on_applySettingsPushButton_clicked(); + + void on_positionComboBox_currentIndexChanged(const QString &arg1); + void on_pointingComboBox_currentIndexChanged(const QString &arg1); + + void updateSolveSettingsSigmaTables(const QComboBox *solveOptionComboBox, + QTableWidget *table); + void validateSigmaValue(QTableWidgetItem *); + void validateSigmaTables(); + public slots: void slotTextChanged(const QString &text); void checkIsValid(); + void treeViewSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); + private: - void makeReadOnly() ; + void makeReadOnly(); void fillFromSettings(const BundleSettingsQsp settings); void showTargetParametersGroupBox(); void hideTargetParametersGroupBox(); + void updateBundleObservationSolveSettings(BundleObservationSolveSettings &boss); + + void createObservationSolveSettingsTreeView(); private: Ui::JigsawSetupDialog *m_ui; Project *m_project; + BundleSettingsQsp m_bundleSettings; /**< The BundleSettings Object created by this dialog */ }; }; #endif // JigsawSetupDialog_h diff --git a/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.ui b/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.ui index 3fb99daa8bc32f6e9c8254a52c1872de1ae86963..da59e250036bfff562158ccd40aef2c0e777c587 100644 --- a/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.ui +++ b/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>977</width> - <height>678</height> + <width>1000</width> + <height>700</height> </rect> </property> <property name="sizePolicy"> @@ -43,7 +43,7 @@ </sizepolicy> </property> <property name="currentIndex"> - <number>3</number> + <number>1</number> </property> <widget class="QWidget" name="generalSettingsTab"> <attribute name="title"> @@ -51,600 +51,1144 @@ </attribute> <layout class="QGridLayout" name="gridLayout_2"> <item row="0" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <property name="sizeConstraint"> - <enum>QLayout::SetFixedSize</enum> - </property> + <layout class="QHBoxLayout" name="horizontalLayout_7"> <item> - <layout class="QGridLayout" name="solveOptionsAndConvergencCriteriaGridLayout"> - <item row="4" column="0" colspan="2"> - <widget class="QCheckBox" name="updateCubeLabelCheckBox"> + <layout class="QVBoxLayout" name="verticalLayout_6"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_8"> + <item> + <widget class="QLabel" name="label"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>15</height> + </size> + </property> + <property name="text"> + <string><html><head/><body><p align="center"><span style=" font-weight:600;">Data</span></p></body></html></string> + </property> + <property name="scaledContents"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_6"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="title"> + <string/> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <layout class="QGridLayout" name="gridLayout_11"> + <item row="1" column="1"> + <widget class="QLineEdit" name="outputControlNetLineEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="outputControlNetLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>150</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string><html><head/><body><p align="right">Output Control Net</p></body></html></string> + </property> + <property name="textFormat"> + <enum>Qt::RichText</enum> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="inputControlNetLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>150</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string><html><head/><body><p align="right">Input Control Net</p></body></html></string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="inputControlNetCombo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToContents</enum> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer_5"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>50</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>15</height> + </size> + </property> + <property name="text"> + <string><html><head/><body><p align="center"><span style=" font-weight:600;">Outlier Rejection Options</span></p></body></html></string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QGroupBox" name="groupBox_8"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="text"> - <string>Update Cube Label</string> + <property name="title"> + <string/> </property> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="1" column="3"> + <spacer name="horizontalSpacer_7"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="2"> + <widget class="QLineEdit" name="outlierRejectionMultiplierLineEdit"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string><html><head/><body><p>Outlier Rejection Multiplier</p></body></html></string> + </property> + <property name="text"> + <string>3.0</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="placeholderText"> + <string/> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QCheckBox" name="outlierRejectionCheckBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>1000</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Image measures are flagged as rejected if their residuals are greater +than the multiplier times the current standard deviation (sigma). + +Must be positive.</string> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="text"> + <string>Sigma Multiplier</string> + </property> + </widget> + </item> + </layout> </widget> </item> - <item row="7" column="0"> - <widget class="QCheckBox" name="outlierRejectionCheckBox"> + <item> + <widget class="QGroupBox" name="groupBox_7"> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> - <width>74</width> + <width>0</width> <height>0</height> </size> </property> - <property name="text"> - <string>Outlier Rejection</string> - </property> - </widget> - </item> - <item row="6" column="1" colspan="2"> - <widget class="QLabel" name="outlierRejectionMultiplierLabel"> - <property name="enabled"> + <property name="autoFillBackground"> <bool>false</bool> </property> - <property name="font"> - <font> - <italic>false</italic> - </font> - </property> - <property name="text"> - <string>&Multiplier</string> + <property name="title"> + <string/> </property> <property name="alignment"> <set>Qt::AlignCenter</set> </property> - <property name="buddy"> - <cstring>outlierRejectionMultiplierLineEdit</cstring> - </property> - </widget> - </item> - <item row="3" column="0" colspan="2"> - <widget class="QCheckBox" name="radiusCheckBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> + <property name="flat"> + <bool>false</bool> </property> - <property name="text"> - <string>Radius</string> + <property name="checkable"> + <bool>false</bool> </property> + <layout class="QGridLayout" name="gridLayout_14"> + <item row="6" column="1" colspan="2"> + <widget class="QComboBox" name="maximumLikelihoodModel1ComboBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <item> + <property name="text"> + <string>NONE</string> + </property> + </item> + <item> + <property name="text"> + <string>HUBER</string> + </property> + </item> + <item> + <property name="text"> + <string>HUBER MODIFIED</string> + </property> + </item> + </widget> + </item> + <item row="8" column="3"> + <widget class="QLineEdit" name="maximumLikelihoodModel3QuantileLineEdit"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>0.5</string> + </property> + </widget> + </item> + <item row="7" column="3"> + <widget class="QLineEdit" name="maximumLikelihoodModel2QuantileLineEdit"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>0.5</string> + </property> + </widget> + </item> + <item row="6" column="3"> + <widget class="QLineEdit" name="maximumLikelihoodModel1QuantileLineEdit"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>0.5</string> + </property> + </widget> + </item> + <item row="7" column="1" colspan="2"> + <widget class="QComboBox" name="maximumLikelihoodModel2ComboBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <item> + <property name="text"> + <string>NONE</string> + </property> + </item> + <item> + <property name="text"> + <string>HUBER</string> + </property> + </item> + <item> + <property name="text"> + <string>HUBER MODIFIED</string> + </property> + </item> + <item> + <property name="text"> + <string>WELSCH</string> + </property> + </item> + <item> + <property name="text"> + <string>CHEN</string> + </property> + </item> + </widget> + </item> + <item row="7" column="0" alignment="Qt::AlignRight"> + <widget class="QLabel" name="maximumLikelihoodModel2Label"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Valid Range: 1.0e-10 to 1.0</string> + </property> + <property name="text"> + <string><html><head/><body><p align="center">Model 2</p></body></html></string> + </property> + <property name="buddy"> + <cstring>maximumLikelihoodModel2ComboBox</cstring> + </property> + </widget> + </item> + <item row="8" column="1" colspan="2"> + <widget class="QComboBox" name="maximumLikelihoodModel3ComboBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <item> + <property name="text"> + <string>NONE</string> + </property> + </item> + <item> + <property name="text"> + <string>HUBER</string> + </property> + </item> + <item> + <property name="text"> + <string>HUBER MODIFIED</string> + </property> + </item> + <item> + <property name="text"> + <string>WELSCH</string> + </property> + </item> + <item> + <property name="text"> + <string>CHEN</string> + </property> + </item> + </widget> + </item> + <item row="6" column="0" alignment="Qt::AlignRight"> + <widget class="QLabel" name="maximumLikelihoodModel1Label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Valid Range: 1.0e-10 to 1.0</string> + </property> + <property name="text"> + <string><html><head/><body><p align="center">Model 1</p></body></html></string> + </property> + <property name="buddy"> + <cstring>maximumLikelihoodModel1ComboBox</cstring> + </property> + </widget> + </item> + <item row="8" column="0" alignment="Qt::AlignRight"> + <widget class="QLabel" name="maximumLikelihoodModel3Label"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>Valid Range: 1.0e-10 to 1.0</string> + </property> + <property name="text"> + <string><html><head/><body><p align="center">Model 3</p></body></html></string> + </property> + <property name="buddy"> + <cstring>maximumLikelihoodModel3ComboBox</cstring> + </property> + </widget> + </item> + <item row="4" column="0" colspan="4"> + <widget class="QLabel" name="maxLikelihoodEstimationLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Maximum Likelihood Estimation and Sigma Multiplier are exclusive options. +Set Model 1 to "NONE" before checking Sigma Multiplier.</string> + </property> + <property name="text"> + <string><html><head/><body><p align="center">Maximum Likelihood Estimation</p></body></html></string> + </property> + </widget> + </item> + <item row="5" column="3" alignment="Qt::AlignHCenter"> + <widget class="QLabel" name="CQuantileLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>C Quantile</string> + </property> + </widget> + </item> + </layout> </widget> </item> - <item row="11" column="1"> - <widget class="QLineEdit" name="sigma0ThresholdLineEdit"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> + </layout> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>50</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_7"> + <item> + <widget class="QLabel" name="label_3"> <property name="minimumSize"> <size> - <width>78</width> - <height>0</height> + <width>0</width> + <height>20</height> </size> </property> <property name="text"> - <string>1.0e-10</string> - </property> - </widget> - </item> - <item row="2" column="0" colspan="2"> - <widget class="QCheckBox" name="observationModeCheckBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Observation Mode</string> + <string><html><head/><body><p align="center"><span style=" font-weight:600;">Convergence Criteria</span></p></body></html></string> </property> </widget> </item> - <item row="5" column="0" colspan="2"> - <widget class="QCheckBox" name="errorPropagationCheckBox"> + <item> + <widget class="QGroupBox" name="groupBox_3"> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <sizepolicy hsizetype="Minimum" vsizetype="Expanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> - <width>74</width> - <height>0</height> + <width>0</width> + <height>150</height> </size> </property> - <property name="text"> - <string>Error Propagation</string> - </property> - </widget> - </item> - <item row="11" column="0"> - <widget class="QLabel" name="sigma0ThresholdLabel"> - <property name="text"> - <string>Sigma&0 Threshold</string> - </property> - <property name="buddy"> - <cstring>sigma0ThresholdLineEdit</cstring> - </property> - </widget> - </item> - <item row="12" column="0"> - <widget class="QLabel" name="maximumIterationsLabel"> - <property name="text"> - <string>Ma&ximum Iterations</string> - </property> - <property name="buddy"> - <cstring>maximumIterationsLineEdit</cstring> - </property> - </widget> - </item> - <item row="7" column="1" colspan="2"> - <widget class="QLineEdit" name="outlierRejectionMultiplierLineEdit"> - <property name="enabled"> + <property name="autoFillBackground"> <bool>false</bool> </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="toolTip"> - <string><html><head/><body><p>Outlier Rejection Multiplier</p></body></html></string> - </property> - <property name="text"> - <string>3.0</string> - </property> - <property name="placeholderText"> + <property name="title"> <string/> </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <layout class="QGridLayout" name="gridLayout_17"> + <item row="0" column="2" alignment="Qt::AlignRight"> + <widget class="QLineEdit" name="sigma0ThresholdLineEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>78</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>100</height> + </size> + </property> + <property name="text"> + <string>1.0e-10</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1" alignment="Qt::AlignRight"> + <widget class="QLabel" name="sigma0ThresholdLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>150</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Valid Range: 1.0e-10 to 1.0e+10</string> + </property> + <property name="text"> + <string><html><head/><body><p align="right">Sigma&amp;0 Threshold</p></body></html></string> + </property> + <property name="buddy"> + <cstring>sigma0ThresholdLineEdit</cstring> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QLineEdit" name="maximumIterationsLineEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>100</height> + </size> + </property> + <property name="text"> + <string>50</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="3" rowspan="2"> + <spacer name="horizontalSpacer_6"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>10</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="1" alignment="Qt::AlignHCenter"> + <widget class="QLabel" name="maximumIterationsLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>150</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Valid Range: 1 to 10,000</string> + </property> + <property name="text"> + <string><html><head/><body><p align="right">Ma&amp;ximum Iterations</p></body></html></string> + </property> + <property name="buddy"> + <cstring>maximumIterationsLineEdit</cstring> + </property> + </widget> + </item> + <item row="0" column="0" rowspan="2"> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>10</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> </widget> </item> - <item row="8" column="0" colspan="2"> - <spacer name="solveOptionsToConvergenceCriteriaVerticalSpacer"> + <item> + <spacer name="verticalSpacer_3"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> <property name="sizeType"> - <enum>QSizePolicy::Preferred</enum> + <enum>QSizePolicy::Expanding</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> - <height>40</height> + <height>50</height> </size> </property> </spacer> </item> - <item row="9" column="0" colspan="2"> - <widget class="QLabel" name="convergenceCriteriaLabel"> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Convergence Criteria</span></p></body></html></string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="0" column="0" colspan="2"> - <widget class="QLabel" name="solveMethodLabel"> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Solve Method and Options</span></p></body></html></string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="12" column="1"> - <widget class="QLineEdit" name="maximumIterationsLineEdit"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>50</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QGridLayout" name="controlNetPositionAndPointingOptionsGridLayout"> - <item row="10" column="0"> - <widget class="QLabel" name="spkSolveDegreeLabel"> - <property name="enabled"> - <bool>true</bool> + <item> + <widget class="QLabel" name="label_4"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>20</height> + </size> </property> <property name="text"> - <string>SPKSolveDegree</string> - </property> - <property name="buddy"> - <cstring>spkSolveDegreeSpinBox</cstring> + <string><html><head/><body><p align="center"><span style=" font-weight:600;">Global Apriori Point Sigmas (meters)</span></p></body></html></string> </property> </widget> </item> - <item row="9" column="1"> - <widget class="QSpinBox" name="spkDegreeSpinBox"> - <property name="enabled"> - <bool>true</bool> - </property> + <item> + <widget class="QGroupBox" name="groupBox_4"> <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <sizepolicy hsizetype="Minimum" vsizetype="Expanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="value"> - <number>2</number> + <property name="minimumSize"> + <size> + <width>0</width> + <height>200</height> + </size> </property> - </widget> - </item> - <item row="8" column="0" colspan="2"> - <widget class="QCheckBox" name="hermiteSplineCheckBox"> - <property name="enabled"> + <property name="autoFillBackground"> <bool>false</bool> </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> + <property name="title"> + <string/> </property> - <property name="text"> - <string>Solve over Hermite Spline</string> + <property name="alignment"> + <set>Qt::AlignCenter</set> </property> + <layout class="QGridLayout" name="gridLayout_13"> + <item row="1" column="0"> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>10</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="2"> + <widget class="QLineEdit" name="pointLongitudeSigmaLineEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>100</height> + </size> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="3"> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>10</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="1" alignment="Qt::AlignRight"> + <widget class="QLabel" name="pointLongitudeSigmaLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Valid Range: 1.0e-10 to 1.0e+10</string> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="text"> + <string><html><head/><body><p align="center">Longitude</p></body></html></string> + </property> + <property name="textFormat"> + <enum>Qt::RichText</enum> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLineEdit" name="pointLatitudeSigmaLineEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>100</height> + </size> + </property> + <property name="inputMask"> + <string/> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QLineEdit" name="pointRadiusSigmaLineEdit"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>100</height> + </size> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="1" alignment="Qt::AlignRight"> + <widget class="QCheckBox" name="pointRadiusSigmaCheckBox"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Solve for local point radii. + +Valid Range: 1.0e-10 to 1.0e+10</string> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="text"> + <string>Radius</string> + </property> + <property name="tristate"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="0" column="1" alignment="Qt::AlignRight"> + <widget class="QLabel" name="pointLatitudeSigmaLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Valid Range: 1.0e-10 to 1.0e+10</string> + </property> + <property name="text"> + <string><html><head/><body><p align="center">Latitude</p></body></html></string> + </property> + <property name="textFormat"> + <enum>Qt::RichText</enum> + </property> + </widget> + </item> + </layout> </widget> </item> - <item row="5" column="0" colspan="2"> - <spacer name="controlNetworkToSpkOptionsVerticalSpacer"> + <item> + <spacer name="verticalSpacer_4"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> <property name="sizeType"> - <enum>QSizePolicy::Preferred</enum> + <enum>QSizePolicy::Expanding</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> - <height>40</height> + <height>50</height> </size> </property> </spacer> </item> - <item row="15" column="0" colspan="2"> - <widget class="QCheckBox" name="fitOverPointingCheckBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> + <item> + <widget class="QLabel" name="label_5"> <property name="minimumSize"> <size> - <width>269</width> - <height>0</height> + <width>0</width> + <height>20</height> </size> </property> <property name="text"> - <string>Fit Polynomial over Existing Pointing</string> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="outputControlNet_2"> - <property name="text"> - <string>Output</string> - </property> - </widget> - </item> - <item row="13" column="0" colspan="2"> - <widget class="QComboBox" name="pointingComboBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="toolTip"> - <string><html><head/><body><p>Instrument Pointing Options</p></body></html></string> - </property> - <property name="currentIndex"> - <number>0</number> - </property> - <property name="frame"> - <bool>true</bool> - </property> - <item> - <property name="text"> - <string>ANGLES</string> - </property> - </item> - <item> - <property name="text"> - <string>NONE</string> - </property> - </item> - <item> - <property name="text"> - <string>VELOCITIES</string> - </property> - </item> - <item> - <property name="text"> - <string>ACCELERATIONS</string> - </property> - </item> - <item> - <property name="text"> - <string>ALL</string> - </property> - </item> - </widget> - </item> - <item row="9" column="0"> - <widget class="QLabel" name="spkDegreeLabel"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>SPKDegree</string> - </property> - <property name="buddy"> - <cstring>spkDegreeSpinBox</cstring> + <string><html><head/><body><p align="center"><span style=" font-weight:600;">Other</span></p></body></html></string> </property> </widget> </item> - <item row="3" column="1"> - <widget class="QLineEdit" name="outputControlNet"> + <item> + <widget class="QGroupBox" name="groupBox_5"> <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <sizepolicy hsizetype="Minimum" vsizetype="Expanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="inputControlNet"> - <property name="text"> - <string>Input</string> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="6" column="0" colspan="2"> - <widget class="QLabel" name="positionSolveOptionsLabel"> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Instrument Solve Options</span></p></body></html></string> + <property name="minimumSize"> + <size> + <width>0</width> + <height>100</height> + </size> </property> - <property name="scaledContents"> + <property name="autoFillBackground"> <bool>false</bool> </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="7" column="0" colspan="2"> - <widget class="QComboBox" name="positionComboBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="toolTip"> - <string><html><head/><body><p>Instrument Solve Options</p></body></html></string> - </property> - <item> - <property name="text"> - <string>NONE</string> - </property> - </item> - <item> - <property name="text"> - <string>POSITIONS</string> - </property> - </item> - <item> - <property name="text"> - <string>VELOCITIES</string> - </property> - </item> - <item> - <property name="text"> - <string>ACCELERATIONS</string> - </property> - </item> - <item> - <property name="text"> - <string>ALL</string> - </property> - </item> - </widget> - </item> - <item row="0" column="0" colspan="2"> - <widget class="QLabel" name="controlNetworkHeader"> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Control Networks</span></p></body></html></string> + <property name="title"> + <string/> </property> <property name="alignment"> <set>Qt::AlignCenter</set> </property> - </widget> - </item> - <item row="11" column="0" colspan="2"> - <spacer name="spkToCkOptionsverticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Preferred</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item row="17" column="0"> - <widget class="QLabel" name="ckSolveDegreeLabel"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>C&KSolveDegree</string> - </property> - <property name="buddy"> - <cstring>ckSolveDegreeSpinBox</cstring> - </property> - </widget> - </item> - <item row="16" column="0"> - <widget class="QLabel" name="ckDegreeLabel"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>CKDegree</string> - </property> - <property name="buddy"> - <cstring>ckDegreeSpinBox</cstring> - </property> - </widget> - </item> - <item row="14" column="0" colspan="2"> - <widget class="QCheckBox" name="twistCheckBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Twist</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="12" column="0" colspan="2"> - <widget class="QLabel" name="pointingSolveOptionsLabel"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>269</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Instrument Pointing Solve Options</span></p></body></html></string> - </property> - <property name="scaledContents"> - <bool>false</bool> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="16" column="1"> - <widget class="QSpinBox" name="ckDegreeSpinBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="value"> - <number>2</number> - </property> - </widget> - </item> - <item row="10" column="1"> - <widget class="QSpinBox" name="spkSolveDegreeSpinBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="value"> - <number>2</number> - </property> - </widget> - </item> - <item row="17" column="1"> - <widget class="QSpinBox" name="ckSolveDegreeSpinBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="value"> - <number>2</number> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QComboBox" name="controlNetworkComboBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="observationModeCheckBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>40</height> + </size> + </property> + <property name="toolTip"> + <string>Constrain position and pointing for images within an observation to be identical</string> + </property> + <property name="text"> + <string>Observation Mode</string> + </property> + </widget> + </item> + <item alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="errorPropagationCheckBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>74</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>40</height> + </size> + </property> + <property name="toolTip"> + <string>Compute adjusted parameter uncertainties</string> + </property> + <property name="text"> + <string>Error Propagation</string> + </property> + </widget> + </item> + </layout> </widget> </item> </layout> @@ -661,7 +1205,7 @@ <item row="0" column="1"> <widget class="QGroupBox" name="groupBox"> <property name="title"> - <string>Position</string> + <string>Instrument Position Solve Options</string> </property> <property name="flat"> <bool>false</bool> @@ -670,46 +1214,11 @@ <bool>false</bool> </property> <layout class="QGridLayout" name="gridLayout_9"> - <item row="0" column="0"> - <widget class="QLabel" name="spkDegreeLabel_2"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>SPK Initiali&zation Polynomial Degree</string> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - <property name="buddy"> - <cstring>spkDegreeSpinBox</cstring> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QSpinBox" name="spkDegreeSpinBox_2"> + <item row="2" column="2"> + <widget class="QCheckBox" name="hermiteSplineCheckBox"> <property name="enabled"> <bool>true</bool> </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="value"> - <number>2</number> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QCheckBox" name="hermiteSplineCheckBox_2"> - <property name="enabled"> - <bool>false</bool> - </property> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> @@ -721,42 +1230,7 @@ </property> </widget> </item> - <item row="1" column="0"> - <widget class="QLabel" name="spkSolveDegreeLabel_2"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>SPK Solve Polynomial Degree</string> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - <property name="buddy"> - <cstring>spkSolveDegreeSpinBox</cstring> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QSpinBox" name="spkSolveDegreeSpinBox_2"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimum"> - <number>-1</number> - </property> - <property name="value"> - <number>0</number> - </property> - </widget> - </item> - <item row="2" column="0" colspan="3"> + <item row="4" column="0" colspan="3"> <widget class="QTableWidget" name="positionAprioriSigmaTable"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -766,7 +1240,7 @@ </property> <property name="maximumSize"> <size> - <width>390</width> + <width>16777215</width> <height>16777215</height> </size> </property> @@ -774,13 +1248,19 @@ <enum>Qt::ScrollBarAsNeeded</enum> </property> <property name="horizontalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOff</enum> + <enum>Qt::ScrollBarAsNeeded</enum> + </property> + <property name="autoScroll"> + <bool>true</bool> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> </property> <property name="showGrid"> <bool>true</bool> </property> <property name="columnCount"> - <number>3</number> + <number>4</number> </property> <attribute name="horizontalHeaderCascadingSectionResizes"> <bool>false</bool> @@ -791,6 +1271,9 @@ <attribute name="horizontalHeaderMinimumSectionSize"> <number>130</number> </attribute> + <attribute name="horizontalHeaderShowSortIndicator" stdset="0"> + <bool>false</bool> + </attribute> <attribute name="horizontalHeaderStretchLastSection"> <bool>true</bool> </attribute> @@ -800,35 +1283,24 @@ <column/> <column/> <column/> + <column/> </widget> </item> - </layout> - </widget> - </item> - <item row="1" column="1"> - <widget class="QGroupBox" name="groupBox_2"> - <property name="title"> - <string>Pointing</string> - </property> - <layout class="QGridLayout" name="gridLayout_10"> - <item row="0" column="0"> - <widget class="QLabel" name="ckDegreeLabel_2"> + <item row="1" column="0"> + <widget class="QLabel" name="spkSolveDegreeLabel"> <property name="enabled"> <bool>true</bool> </property> <property name="text"> - <string>C&K Initialization Polynomial Degree</string> + <string>SPK Solve Degree</string> </property> <property name="wordWrap"> <bool>true</bool> </property> - <property name="buddy"> - <cstring>ckDegreeSpinBox</cstring> - </property> </widget> </item> - <item row="0" column="1"> - <widget class="QSpinBox" name="ckDegreeSpinBox_2"> + <item row="2" column="1"> + <widget class="QSpinBox" name="spkDegreeSpinBox"> <property name="enabled"> <bool>true</bool> </property> @@ -839,50 +1311,124 @@ </sizepolicy> </property> <property name="minimum"> - <number>1</number> + <number>0</number> </property> <property name="value"> <number>2</number> </property> </widget> </item> - <item row="0" column="2"> - <widget class="QCheckBox" name="fitOverPointingCheckBox_2"> + <item row="1" column="1"> + <widget class="QSpinBox" name="spkSolveDegreeSpinBox"> + <property name="enabled"> + <bool>true</bool> + </property> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> + <property name="minimum"> + <number>-1</number> + </property> + <property name="value"> + <number>1</number> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="spkDegreeLabel"> + <property name="enabled"> + <bool>true</bool> </property> <property name="text"> - <string>over Existing Pointing</string> + <string>SPK Degree</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="0" colspan="2"> + <widget class="QComboBox" name="positionComboBox"/> + </item> + </layout> + </widget> + </item> + <item row="3" column="1"> + <widget class="QPushButton" name="applySettingsPushButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Apply Settings to Selected Images</string> + </property> + </widget> + </item> + <item row="0" column="0" rowspan="4"> + <widget class="QTreeView" name="treeView"> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + <property name="headerHidden"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Instrument Pointing Solve Options</string> + </property> + <layout class="QGridLayout" name="gridLayout_10"> + <item row="1" column="2"> + <widget class="QCheckBox" name="twistCheckBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Twist</string> + </property> + <property name="checked"> + <bool>true</bool> </property> </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="ckSolveDegreeLabel_2"> + <widget class="QLabel" name="ckSolveDegreeLabel"> <property name="enabled"> <bool>true</bool> </property> <property name="text"> - <string>CK Solve Polyno&mial Degree</string> + <string>CK Solve Degree</string> </property> <property name="wordWrap"> <bool>true</bool> </property> - <property name="buddy"> - <cstring>ckSolveDegreeSpinBox</cstring> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="ckDegreeLabel"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>CK Degree</string> + </property> + <property name="wordWrap"> + <bool>true</bool> </property> </widget> </item> - <item row="1" column="1"> - <widget class="QSpinBox" name="ckSolveDegreeSpinBox_2"> + <item row="2" column="1"> + <widget class="QSpinBox" name="ckDegreeSpinBox"> <property name="enabled"> <bool>true</bool> </property> @@ -893,856 +1439,114 @@ </sizepolicy> </property> <property name="minimum"> - <number>1</number> + <number>0</number> </property> <property name="value"> <number>2</number> </property> </widget> </item> - <item row="1" column="2"> - <widget class="QCheckBox" name="twistCheckBox_2"> + <item row="2" column="2"> + <widget class="QCheckBox" name="fitOverPointingCheckBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="text"> - <string>Twist</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="2" column="0" colspan="3"> - <widget class="QTableWidget" name="pointingAprioriSigmaTable"> - <property name="maximumSize"> + <property name="minimumSize"> <size> - <width>390</width> - <height>16777215</height> + <width>0</width> + <height>0</height> </size> </property> - <property name="verticalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOn</enum> - </property> - <property name="horizontalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOff</enum> - </property> - <property name="columnCount"> - <number>3</number> - </property> - <attribute name="horizontalHeaderDefaultSectionSize"> - <number>125</number> - </attribute> - <attribute name="horizontalHeaderMinimumSectionSize"> - <number>130</number> - </attribute> - <column/> - <column/> - <column/> - </widget> - </item> - </layout> - <zorder>pointingAprioriSigmaTable</zorder> - <zorder>ckSolveDegreeSpinBox_2</zorder> - <zorder>ckDegreeLabel_2</zorder> - <zorder>ckDegreeSpinBox_2</zorder> - <zorder>ckSolveDegreeLabel_2</zorder> - <zorder>fitOverPointingCheckBox_2</zorder> - <zorder>twistCheckBox_2</zorder> - </widget> - </item> - <item row="0" column="0"> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - <widget class="QWidget" name="weightingTab"> - <attribute name="title"> - <string>Weighting</string> - </attribute> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="0" column="0"> - <layout class="QGridLayout" name="globalParameterUncertaintiesGridLayout"> - <item row="1" column="2"> - <widget class="QLabel" name="pointLatitudeSigmaUnitsLabel"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximumSize"> - <size> - <width>58</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>&meters</string> - </property> - <property name="buddy"> - <cstring>pointLatitudeSigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QLabel" name="pointLongitudeSigmaUnitsLabel"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximumSize"> - <size> - <width>58</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>meters</string> - </property> - <property name="buddy"> - <cstring>pointLongitudeSigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="9" column="1"> - <widget class="QLineEdit" name="pointingAngularAccelerationSigmaLineEdit"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="4" column="1"> - <widget class="QLineEdit" name="positionSigmaLineEdit"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="8" column="0"> - <widget class="QLabel" name="pointingAngularVelocitySigmaLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Instrument Pointing Angular Velocity Sigma</string> - </property> - <property name="buddy"> - <cstring>pointingAngularVelocitySigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="positionSigmaLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Instrument Position Sigma</string> - </property> - <property name="buddy"> - <cstring>positionSigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="6" column="1"> - <widget class="QLineEdit" name="accelerationSigmaLineEdit"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="pointLatitudeSigmaLineEdit"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="7" column="1"> - <widget class="QLineEdit" name="pointingAnglesSigmaLineEdit"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="9" column="0"> - <widget class="QLabel" name="pointingAngularAccelerationSigmaLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>326</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string>Instrument Pointing Angular Acceleration Sigma</string> - </property> - <property name="buddy"> - <cstring>pointingAngularAccelerationSigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="9" column="2"> - <widget class="QLabel" name="pointingAngularAccelerationSigmaUnitsLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximumSize"> - <size> - <width>202</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>degrees per second squared</string> - </property> - <property name="buddy"> - <cstring>pointingAngularAccelerationSigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="8" column="2"> - <widget class="QLabel" name="pointingAngularVelocitySigmaUnitsLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximumSize"> - <size> - <width>141</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>degrees per second</string> - </property> - <property name="buddy"> - <cstring>pointingAngularVelocitySigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="8" column="1"> - <widget class="QLineEdit" name="pointingAngularVelocitySigmaLineEdit"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="pointLongitudeSigmaLabel"> - <property name="text"> - <string>Point Longitude Sigma</string> - </property> - <property name="buddy"> - <cstring>pointLongitudeSigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="5" column="1"> - <widget class="QLineEdit" name="velocitySigmaLineEdit"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QLabel" name="velocitySigmaLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Instrument Velocity Sigma</string> - </property> - <property name="buddy"> - <cstring>velocitySigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QLineEdit" name="pointLongitudeSigmaLineEdit"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="7" column="2"> - <widget class="QLabel" name="pointingAnglesSigmaUnitsLabel"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximumSize"> - <size> - <width>58</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>degrees</string> - </property> - <property name="buddy"> - <cstring>pointingAnglesSigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="7" column="0"> - <widget class="QLabel" name="pointingAnglesSigmaLabel"> - <property name="text"> - <string>Instrument Pointing Angles Sigma</string> - </property> - <property name="buddy"> - <cstring>pointingAnglesSigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="0" column="0" colspan="3"> - <widget class="QLabel" name="globalParameterUncertaintiesLabel"> - <property name="text"> - <string>Global Parameter Uncertainties</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="pointLatitudeSigmaLabel"> - <property name="text"> - <string>Point Latitude Sigma</string> - </property> - <property name="buddy"> - <cstring>pointLatitudeSigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="3" column="2"> - <widget class="QLabel" name="pointRadiusSigmaUnitsLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximumSize"> - <size> - <width>49</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>meters</string> - </property> - <property name="buddy"> - <cstring>pointRadiusSigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="4" column="2"> - <widget class="QLabel" name="positionSigmaUnitsLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximumSize"> - <size> - <width>49</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>meters</string> - </property> - <property name="buddy"> - <cstring>positionSigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="5" column="2"> - <widget class="QLabel" name="velocitySigmaUnitsLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximumSize"> - <size> - <width>132</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>meters per second</string> - </property> - <property name="buddy"> - <cstring>velocitySigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="6" column="0"> - <widget class="QLabel" name="accelerationSigmaLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Instrument Acceleration Sigma</string> - </property> - <property name="buddy"> - <cstring>accelerationSigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="6" column="2"> - <widget class="QLabel" name="accelerationSigmaUnitsLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximumSize"> - <size> - <width>193</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>meters per second s&quared</string> - </property> - <property name="buddy"> - <cstring>accelerationSigmaLineEdit</cstring> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QLineEdit" name="pointRadiusSigmaLineEdit"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="pointRadiusSigmaLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Point Radius Sigma</string> - </property> - <property name="buddy"> - <cstring>pointRadiusSigmaLineEdit</cstring> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <widget class="QWidget" name="maximumLikelihoodTab"> - <attribute name="title"> - <string>Maximum Likelihood</string> - </attribute> - <layout class="QGridLayout" name="gridLayout_4"> - <item row="0" column="0"> - <layout class="QGridLayout" name="maximumLikelihoodGridLayout"> - <item row="2" column="0" colspan="2"> - <spacer name="maximumLikelihoodModel1ToModel2VerticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Preferred</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item row="5" column="0" colspan="2"> - <spacer name="maximumLikelihoodModel2ToModel3VerticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Preferred</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="maximumLikelihoodModel1Label"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>279</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string>&Maximum Likelihood Estimator Model 1</string> - </property> - <property name="buddy"> - <cstring>maximumLikelihoodModel1ComboBox</cstring> - </property> - </widget> - </item> - <item row="6" column="0"> - <widget class="QLabel" name="maximumLikelihoodModel3Label"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>279</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string>Ma&ximum Likelihood Estimator Model 3</string> - </property> - <property name="buddy"> - <cstring>maximumLikelihoodModel3ComboBox</cstring> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QComboBox" name="maximumLikelihoodModel1ComboBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <item> - <property name="text"> - <string>NONE</string> - </property> - </item> - <item> - <property name="text"> - <string>HUBER</string> - </property> - </item> - <item> - <property name="text"> - <string>HUBER MODIFIED</string> - </property> - </item> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="maximumLikelihoodModel2Label"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>279</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string>Maximum &Likelihood Estimator Model 2</string> - </property> - <property name="buddy"> - <cstring>maximumLikelihoodModel2ComboBox</cstring> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="maximumLikelihoodModel1QuantileLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Model &1 C Quantile</string> - </property> - <property name="buddy"> - <cstring>maximumLikelihoodModel1QuantileLineEdit</cstring> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="maximumLikelihoodModel1QuantileLineEdit"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>0.5</string> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="maximumLikelihoodModel2QuantileLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Model &2 C Quantile</string> - </property> - <property name="buddy"> - <cstring>maximumLikelihoodModel2QuantileLineEdit</cstring> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QComboBox" name="maximumLikelihoodModel2ComboBox"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <item> - <property name="text"> - <string>NONE</string> - </property> - </item> - <item> - <property name="text"> - <string>HUBER</string> - </property> - </item> - <item> <property name="text"> - <string>HUBER MODIFIED</string> + <string>over Existing Pointing</string> </property> - </item> - <item> - <property name="text"> - <string>WELSCH</string> + </widget> + </item> + <item row="4" column="0" colspan="3"> + <widget class="QTableWidget" name="pointingAprioriSigmaTable"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> - </item> - <item> - <property name="text"> - <string>CHEN</string> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> </property> - </item> - </widget> - </item> - <item row="4" column="1"> - <widget class="QLineEdit" name="maximumLikelihoodModel2QuantileLineEdit"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>0.5</string> - </property> - </widget> - </item> - <item row="6" column="1"> - <widget class="QComboBox" name="maximumLikelihoodModel3ComboBox"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <item> - <property name="text"> - <string>NONE</string> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAsNeeded</enum> </property> - </item> - <item> - <property name="text"> - <string>HUBER</string> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAsNeeded</enum> </property> - </item> - <item> - <property name="text"> - <string>HUBER MODIFIED</string> + <property name="alternatingRowColors"> + <bool>true</bool> </property> - </item> - <item> - <property name="text"> - <string>WELSCH</string> + <property name="showGrid"> + <bool>true</bool> </property> - </item> - <item> - <property name="text"> - <string>CHEN</string> + <property name="columnCount"> + <number>4</number> </property> - </item> - </widget> - </item> - <item row="7" column="0"> - <widget class="QLabel" name="maximumLikelihoodModel3QuantileLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Model &3 C Quantile</string> - </property> - <property name="buddy"> - <cstring>maximumLikelihoodModel3QuantileLineEdit</cstring> - </property> - </widget> - </item> - <item row="7" column="1"> - <widget class="QLineEdit" name="maximumLikelihoodModel3QuantileLineEdit"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>0.5</string> - </property> - </widget> - </item> - </layout> + <attribute name="horizontalHeaderDefaultSectionSize"> + <number>125</number> + </attribute> + <attribute name="horizontalHeaderMinimumSectionSize"> + <number>130</number> + </attribute> + <attribute name="horizontalHeaderStretchLastSection"> + <bool>true</bool> + </attribute> + <attribute name="verticalHeaderVisible"> + <bool>false</bool> + </attribute> + <column/> + <column/> + <column/> + <column/> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="ckSolveDegreeSpinBox"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimum"> + <number>-1</number> + </property> + <property name="value"> + <number>2</number> + </property> + </widget> + </item> + <item row="0" column="0" colspan="2"> + <widget class="QComboBox" name="pointingComboBox"/> + </item> + </layout> + <zorder>pointingAprioriSigmaTable</zorder> + <zorder>ckDegreeLabel</zorder> + <zorder>ckDegreeSpinBox</zorder> + <zorder>fitOverPointingCheckBox</zorder> + <zorder>ckSolveDegreeSpinBox</zorder> + <zorder>ckSolveDegreeLabel</zorder> + <zorder>twistCheckBox</zorder> + <zorder>pointingComboBox</zorder> + </widget> </item> </layout> </widget> - <widget class="QWidget" name="selfCalibrationTab"> - <attribute name="title"> - <string>Self-Calibration</string> - </attribute> - <layout class="QGridLayout" name="gridLayout_7"/> - </widget> <widget class="QWidget" name="targetBodyTab"> <attribute name="title"> <string>Target Body</string> @@ -1802,6 +1606,40 @@ <string>Target Parameters</string> </property> <layout class="QGridLayout" name="gridLayout_12"> + <item row="5" column="1"> + <widget class="QLineEdit" name="primeMeridianOffsetLineEdit"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>22</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>22</height> + </size> + </property> + <property name="toolTip"> + <string><html><head/><body><p>a priori prime meridian offset</p></body></html></string> + </property> + <property name="text"> + <string/> + </property> + <property name="placeholderText"> + <string/> + </property> + </widget> + </item> <item row="6" column="2"> <widget class="QLineEdit" name="spinRateSigmaLineEdit"> <property name="enabled"> @@ -1906,28 +1744,6 @@ </property> </widget> </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="rightAscensionLineEdit"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="toolTip"> - <string><html><head/><body><p>a priori pole right ascension</p></body></html></string> - </property> - <property name="text"> - <string/> - </property> - <property name="placeholderText"> - <string/> - </property> - </widget> - </item> <item row="3" column="1"> <widget class="QLineEdit" name="declinationLineEdit"> <property name="enabled"> @@ -2160,40 +1976,6 @@ </property> </widget> </item> - <item row="5" column="1"> - <widget class="QLineEdit" name="primeMeridianOffsetLineEdit"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>22</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>22</height> - </size> - </property> - <property name="toolTip"> - <string><html><head/><body><p>a priori prime meridian offset</p></body></html></string> - </property> - <property name="text"> - <string/> - </property> - <property name="placeholderText"> - <string/> - </property> - </widget> - </item> <item row="5" column="2"> <widget class="QLineEdit" name="primeMeridianOffsetSigmaLineEdit"> <property name="enabled"> @@ -2281,6 +2063,28 @@ </property> </widget> </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="rightAscensionLineEdit"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string><html><head/><body><p>a priori pole right ascension</p></body></html></string> + </property> + <property name="text"> + <string/> + </property> + <property name="placeholderText"> + <string/> + </property> + </widget> + </item> </layout> </widget> </item> @@ -2828,38 +2632,6 @@ </widget> </widget> <tabstops> - <tabstop>observationModeCheckBox</tabstop> - <tabstop>radiusCheckBox</tabstop> - <tabstop>updateCubeLabelCheckBox</tabstop> - <tabstop>errorPropagationCheckBox</tabstop> - <tabstop>outlierRejectionCheckBox</tabstop> - <tabstop>outlierRejectionMultiplierLineEdit</tabstop> - <tabstop>sigma0ThresholdLineEdit</tabstop> - <tabstop>controlNetworkComboBox</tabstop> - <tabstop>positionComboBox</tabstop> - <tabstop>hermiteSplineCheckBox</tabstop> - <tabstop>spkDegreeSpinBox</tabstop> - <tabstop>spkSolveDegreeSpinBox</tabstop> - <tabstop>pointingComboBox</tabstop> - <tabstop>twistCheckBox</tabstop> - <tabstop>fitOverPointingCheckBox</tabstop> - <tabstop>ckDegreeSpinBox</tabstop> - <tabstop>ckSolveDegreeSpinBox</tabstop> - <tabstop>pointLatitudeSigmaLineEdit</tabstop> - <tabstop>pointLongitudeSigmaLineEdit</tabstop> - <tabstop>pointRadiusSigmaLineEdit</tabstop> - <tabstop>positionSigmaLineEdit</tabstop> - <tabstop>velocitySigmaLineEdit</tabstop> - <tabstop>accelerationSigmaLineEdit</tabstop> - <tabstop>pointingAnglesSigmaLineEdit</tabstop> - <tabstop>pointingAngularVelocitySigmaLineEdit</tabstop> - <tabstop>pointingAngularAccelerationSigmaLineEdit</tabstop> - <tabstop>maximumLikelihoodModel1ComboBox</tabstop> - <tabstop>maximumLikelihoodModel1QuantileLineEdit</tabstop> - <tabstop>maximumLikelihoodModel2ComboBox</tabstop> - <tabstop>maximumLikelihoodModel2QuantileLineEdit</tabstop> - <tabstop>maximumLikelihoodModel3ComboBox</tabstop> - <tabstop>maximumLikelihoodModel3QuantileLineEdit</tabstop> <tabstop>poleRaCheckBox</tabstop> <tabstop>rightAscensionLineEdit</tabstop> <tabstop>rightAscensionSigmaLineEdit</tabstop> @@ -2913,38 +2685,6 @@ </hint> </hints> </connection> - <connection> - <sender>outlierRejectionCheckBox</sender> - <signal>toggled(bool)</signal> - <receiver>outlierRejectionMultiplierLineEdit</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>100</x> - <y>251</y> - </hint> - <hint type="destinationlabel"> - <x>292</x> - <y>251</y> - </hint> - </hints> - </connection> - <connection> - <sender>outlierRejectionCheckBox</sender> - <signal>toggled(bool)</signal> - <receiver>outlierRejectionMultiplierLabel</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>100</x> - <y>251</y> - </hint> - <hint type="destinationlabel"> - <x>292</x> - <y>223</y> - </hint> - </hints> - </connection> </connections> <buttongroups> <buttongroup name="radiiButtonGroup"/> diff --git a/isis/src/qisis/objs/MosaicSceneWidget/MosaicControlNetTool.h b/isis/src/qisis/objs/MosaicSceneWidget/MosaicControlNetTool.h index c844a21e4af52090831fa92840cf653860b43fa8..2ca6c4f029fbdc43964b50e096f852f100aba80c 100644 --- a/isis/src/qisis/objs/MosaicSceneWidget/MosaicControlNetTool.h +++ b/isis/src/qisis/objs/MosaicSceneWidget/MosaicControlNetTool.h @@ -17,7 +17,7 @@ namespace Isis { /** * //TODO: Remove debug printout & comment - * // 2016-08-25 Tracie Sucharski - Checking Directory pointer for IPCE code not ideal. + * // 2016-08-25 Tracie Sucharski - Checking Directory pointer for IPCE code not ideal. * Is there a better design? This might go away if we emit signals, * which only IPCE classes would connect to. * @brief Handles Control Net displays @@ -169,4 +169,3 @@ namespace Isis { }; #endif - diff --git a/isis/src/qisis/objs/MosaicSceneWidget/MosaicZoomTool.cpp b/isis/src/qisis/objs/MosaicSceneWidget/MosaicZoomTool.cpp index 3240c70668616ee31cc86089a85d3847cf32199c..65f776940ae9f25906397d99d6d2c868c7fb6744 100644 --- a/isis/src/qisis/objs/MosaicSceneWidget/MosaicZoomTool.cpp +++ b/isis/src/qisis/objs/MosaicSceneWidget/MosaicZoomTool.cpp @@ -413,4 +413,3 @@ namespace Isis { } } - diff --git a/isis/src/qisis/objs/ProgressBar/ProgressBar.h b/isis/src/qisis/objs/ProgressBar/ProgressBar.h index 6854e7eb93f547a7c4c76529d3de2d1f1d989cc6..81d3314638c8e691c1ba394c06e86f69f8d26d3f 100644 --- a/isis/src/qisis/objs/ProgressBar/ProgressBar.h +++ b/isis/src/qisis/objs/ProgressBar/ProgressBar.h @@ -4,10 +4,11 @@ #include <QProgressBar> namespace Isis { - /** - * @brief QProgressBar with customizable text + /** * * @author ????-??-?? Steven Lambright + * @internal ????-??-?? Steven Lambright - QProgressBar with customizable text + * * */ diff --git a/isis/src/qisis/objs/Project/Project.cpp b/isis/src/qisis/objs/Project/Project.cpp index b3f45a0882a13498fdfdb212e7ff6d75df8f58bb..07c4f36abf0a5137d1a382812710ff873de6a687 100644 --- a/isis/src/qisis/objs/Project/Project.cpp +++ b/isis/src/qisis/objs/Project/Project.cpp @@ -540,7 +540,7 @@ namespace Isis { tempDir.removeRecursively(); } } - + projectXml.close(); } @@ -569,7 +569,7 @@ namespace Isis { m_guiCameras->clear(); m_bundleSolutionInfo->clear(); m_workOrderHistory->clear(); - + directory()->clean(); setClean(true); } @@ -948,7 +948,7 @@ namespace Isis { void Project::addImages(ImageList newImages) { imagesReady(newImages); - // The each + // The each emit guiCamerasAdded(m_guiCameras); emit targetsAdded(m_targets); } @@ -1386,7 +1386,8 @@ namespace Isis { } } m_isOpen = true; - writeSettings(); + + setClean(true); emit projectLoaded(this); } @@ -1564,8 +1565,8 @@ namespace Isis { /** - * Get the top-level folder of the new project. This is where the project is opened from/saved to. - * This is set when a Save As operation is in progress. + * Get the top-level folder of the new project. This is where the project is opened from/saved to. + * This is set when a Save As operation is in progress. */ QString Project::newProjectRoot() const { return m_newProjectRoot; @@ -1708,7 +1709,7 @@ namespace Isis { * */ void Project::setActiveControl(QString displayName) { - Control *previousControl = m_activeControl; + Control *previousControl = m_activeControl; if (m_activeControl) { // If the current active control has been modified, ask user if they want to save or discard @@ -1776,10 +1777,10 @@ namespace Isis { * * @description Returns the active control (control network) for views which need to operate on * the same control, ie. Footprint2dView, CubeDnView, ControlPointEditView. - * IMPORTANT: Returns NULL if no active Control. - * + * IMPORTANT: Returns NULL if no active Control. + * * @return @b Control * Returns the active Control if set, otherwise returns NULL - * + * * @internal * @history 2016-06-23 Tracie Sucharski - Original version. * @history 2017-05-17 Tracie Sucharski - If no active control set & there is only one control @@ -1803,8 +1804,8 @@ namespace Isis { void Project::activeControlModified() { - m_activeControl->setModified(true); + setClean(false); } @@ -1870,9 +1871,9 @@ namespace Isis { * @brief Returns the active ImageList * * Returns the active ImageList for views which need to operate on the - * same list of images, ie. Footprint2dView, CubeDnView, ControlPointEditView. - * IMPORTANT: Returns NULL if active ImageList is not set and a default cannot be set if there - * are multiple image lists in the project. + * same list of images, ie. Footprint2dView, CubeDnView, ControlPointEditView. + * IMPORTANT: Returns NULL if active ImageList is not set and a default cannot be set if there + * are multiple image lists in the project. * * @internal * @history 2016-06-23 Tracie Sucharski - Original version. @@ -1883,7 +1884,7 @@ namespace Isis { if (!m_activeImageList && m_images->count() == 1) { QString imageList = m_images->at(0)->name(); - + setActiveImageList(imageList); } return m_activeImageList; @@ -2189,13 +2190,13 @@ namespace Isis { QString(".")); if ( !newDestination.isEmpty() ) { + m_isTemporaryProject = false; save( QFileInfo(newDestination + "/").absolutePath() ); - + // delete the temporary project deleteAllProjectFiles(); relocateProjectRoot(newDestination); - m_isTemporaryProject = false; - + // 2014-03-14 kle This is a lame kludge because we think that relocateProjectRoot is not // working properly. For example, when we save a new project and try to view a control net // the it thinks it's still in the /tmp area @@ -2208,13 +2209,14 @@ namespace Isis { } } else { - // Save current active control if it has been modified + // Save current active control if it has been modified. If "Save As" is being processed, + // the active control is written in the Control::copyToNewProjectRoot so the control in + // current project is not modified. if (activeControl() && activeControl()->isModified()) { activeControl()->write(); } save(m_projectRoot->absolutePath(), false); - // if (newDestination != ) } return saveDialogCompleted; @@ -2348,7 +2350,7 @@ namespace Isis { // For now set the member variable rather than calling setName which emits signal and updates // ProjectItemModel & the project name on the tree. This will be updated when the new project - // is opened. + // is opened. m_name = newPath.name(); QFile projectSettingsFile(newPath.toString() + "/project.xml"); @@ -2426,6 +2428,9 @@ namespace Isis { directoryStateWriter.writeEndDocument(); m_isOpen = true; + + emit projectSaved(this); + } @@ -2619,12 +2624,12 @@ namespace Isis { /** - * Add images to the id map which are not under the projects main data area, the Images node on - * the project tree, such as the images under bundle results. This is an interim solution since - * the Project and model/view does not seem to be properly handling data which is not on the main - * data part of the project tree. - * - * @param ImagesList of images + * Add images to the id map which are not under the projects main data area, the Images node on + * the project tree, such as the images under bundle results. This is an interim solution since + * the Project and model/view does not seem to be properly handling data which is not on the main + * data part of the project tree. + * + * @param ImagesList of images */ void Project::addImagesToIdMap(ImageList images) { diff --git a/isis/src/qisis/objs/Project/Project.h b/isis/src/qisis/objs/Project/Project.h index 848fc6101296af47f31b18def7dc1b008135eced..8f193daf730ac1117aea8d2147d8a78e588502c0 100644 --- a/isis/src/qisis/objs/Project/Project.h +++ b/isis/src/qisis/objs/Project/Project.h @@ -253,6 +253,19 @@ namespace Isis { * @history 2018-04-25 Tracie Sucharski - Fixed typo in XmlHandler::startElement reading * imported shapes from a project which caused the shapes to be put in * the wrong place on the project tree. Fixes #5274. + * @history 2018-06-06 Kaitlyn Lee - activeControlModified() calls setClean(false) to enable the save + * button when the active control net is modified, i.e. a point is modified. + * + * !!!!!!!!!!!!! Delete following history entry when project save/restore geometry/state + * implemented + * !!!!!!!!!!!!!!! + * @history 2018-06-08 Tracie Sucharski - Quick fix for the project save/restore prototype: The + * changes made to readSettings, writeSettings cause following problem: + * save project with view, close view and exit, the project + * geometry/state is saved on closeEvent instead of project save. Quickly + * added signal when project is saved, so the writeSettings can happen + * for project. This will be cleaned up when save/restore is fully + * implemented. * */ class Project : public QObject { @@ -475,9 +488,9 @@ namespace Isis { /** * Emitted when project is saved. - * + * receivers: IpceMainWindow */ - void projectSave(FileName projectName); + void projectSaved(Project *); /** * Emitted when project location moved diff --git a/isis/src/qisis/objs/ProjectItem/ProjectItem.cpp b/isis/src/qisis/objs/ProjectItem/ProjectItem.cpp index acca2e2ac78a44ea474c1820b3d6658a51e83673..ef679f445bc3d0e224bd95e5229c46f6a1dc3c21 100644 --- a/isis/src/qisis/objs/ProjectItem/ProjectItem.cpp +++ b/isis/src/qisis/objs/ProjectItem/ProjectItem.cpp @@ -144,7 +144,9 @@ namespace Isis { appendRow( new ProjectItem( bundleSolutionInfo->bundleSettings() ) ); appendRow( new ProjectItem(bundleSolutionInfo->control()) ); appendRow( new ProjectItem( bundleSolutionInfo->bundleResults() ) ); - appendRow( new ProjectItem( bundleSolutionInfo->adjustedImages() ) ); + if (!bundleSolutionInfo->adjustedImages().isEmpty()) { + appendRow( new ProjectItem( bundleSolutionInfo->adjustedImages() ) ); + } } diff --git a/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.cpp b/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.cpp index 091c7508c96c57b487dd6b7b787f67c7979549b4..a49a293addd2f9c009221d1b0325a6d9668898a0 100644 --- a/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.cpp +++ b/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.cpp @@ -171,12 +171,122 @@ namespace Isis { QItemSelection selection = selectionModel()->selection(); QList<ProjectItem *> items; + foreach ( QModelIndex index, selection.indexes() ) { items.append( itemFromIndex(index) ); } return items; } + /** + * @brief ProjectItemModel::selectedBOSSImages + * @return This is a refinement of the selectedItems function which + * was needed to display a subset of Images/ImageLists in the + * Bundle Observation Solve Settings (BOSS) tab of the JigsawSetupDialog widget. + * The primary consumer of the selected images is going to be the SortFilterProxyModel + * class. + */ + QList<ProjectItem *> ProjectItemModel::selectedBOSSImages() { + + QItemSelection selection = selectionModel()->selection(); + QList<ProjectItem *> items; + QModelIndexList indices = selection.indexes(); + + // If nothing is selected, fill items with all image lists and images. + if (indices.size() == 0) { + ProjectItem *imageRoot = findItemData(QVariant("Images"), 0); + items.append(imageRoot); + for (int i = 0; i < imageRoot->rowCount(); i++) { + ProjectItem *imglistItem = imageRoot->child(i); + items.append(imglistItem); + for (int j = 0; j < imglistItem->rowCount(); j++) { + ProjectItem *imgItem = imglistItem->child(j); + if (imgItem->isImage()) { + items.append(imgItem); + } + } + } + return items; + } + + //Query the selected items to see if they have children + foreach ( QModelIndex ix, indices ) { + + ProjectItem *item = this->itemFromIndex(ix); + + //Anything that is not an image or an image list does + //not make sense to display in the BOSS treeview tab, + //so we need to exclude these items. + if (item->isImageList() || item->isImage() ) { + items.append( item ); + } + else { + return items; + } + + //If the selected ImageList has children, we have to handle + //the case where some of the children are selected, or + //the possibility that the user wants all of the children selected. + if (this->hasChildren(ix)) { + + //If the node has children, loop through all of them + //and add them to selected items. + bool childrenSelected(false); + int numChildren = this->rowCount(ix); + + //First loop through the children to see if any of them are also selected + for (int i = 0; i < numChildren;i++) { + QModelIndex ixchild = this->index(i,0,ix); + if (indices.contains(ixchild) ){ + childrenSelected=true; + break; + } + } + //If they are, then add them to selected items + if (childrenSelected) { + for (int i =0;i < numChildren;i++) { + QModelIndex ixchild = this->index(i,0,ix); + if (indices.contains(ixchild)) + items.append(this->itemFromIndex(ixchild )); + } + } + //No children selected, so we are assuming that the user + //wanted to select all of the children under the parent. + else { + for (int i =0;i < numChildren;i++) { + QModelIndex ixchild = this->index(i,0,ix); + items.append(this->itemFromIndex(ixchild )); + } + + } + + }//end if + + //Append the parent of any selected child. This is so + //the children aren't hanging on the tree without + //a collapsible parent node. + if( item->parent() ->hasChildren()) { + ProjectItem * parent = item->parent(); + if (!items.contains(parent)){ + items.append(parent); + }// end inner if + }//end outer if + //Also include the grandparent. This handles the event + //that we may have multiple image lists selected to the treeview + //and we need a grandparent node attached to group them under. + if (this->itemFromIndex(ix)->parent()->parent() ){ + ProjectItem *grandparent = this->itemFromIndex(ix)->parent()->parent(); + if (!items.contains(grandparent)) { + items.append(grandparent); + } //end inner if + + } //end outer if + + }// end foreach + + return items; + + } /** @@ -697,6 +807,7 @@ namespace Isis { item->image()->displayProperties()->setSelected(false); } } + } diff --git a/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.h b/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.h index 820c7643b88ef48a08442d782c55ff78b96480b2..0bcf772b71a0759d19b664311707f070c14c9035 100644 --- a/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.h +++ b/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.h @@ -121,8 +121,8 @@ namespace Isis { * in the project tree if there is no valid currentIndex. This would * happen if the user was interacting with a cubeDN or footprint view * and then tried right clicking on the project tree. Fixes #5111. - * @history 2017-11-13 Makayla Shepherd - Modifying the name of an ImageList, ShapeList or - * BundeSolutionInfo on the ProjectTree now sets the project to + * @history 2017-11-13 Makayla Shepherd - Modifying the name of an ImageList, ShapeList or + * BundeSolutionInfo on the ProjectTree now sets the project to * not clean. Fixes #5174. * @history 2017-11-03 Christopher Combs - Added support for new Template and TemplateList * classes. Fixes #5117. @@ -130,6 +130,18 @@ namespace Isis { * bundleoutput.txt (Summary) file to the BundleSolution Statistics * node. Also changed the name of the Images node under Statistics to * Image to prevent Import Images to appear on it's context menu. + * @history 2018-06-21 Tyler Wilson - Added the function selectedBOSSImages(). This is a + * refinement of selectedItems and is used by the JigsawSetupDialog + * Bundle Observation Solve Settings (BOSS) tab when displaying a + * subset of user-selected images. References #497 + * @history 2018-06-24 Tyler Wilson - Fixed an edge-case scenario in the selection criteria for + * selectedBOSSImages(). If a user selected an image list and some + * (but not all) of the images within that list, the function returned + * all of the images in the list and not just the selected ones. + * References #497. + * @history 2018-07-10 Kaitlyn Lee - If a user does not select any images in the project tree, + * all image lists and images will be returned in selectedBOSSImages(). + * References #497. */ class ProjectItemModel : public QStandardItemModel { @@ -155,6 +167,8 @@ namespace Isis { ProjectItem *currentItem(); QList<ProjectItem *> selectedItems(); + QList<ProjectItem *> selectedBOSSImages(); + void appendRow(ProjectItem *item); void clean(); @@ -179,7 +193,7 @@ namespace Isis { * This signal is emitted when a ProjectItem is removed to the model. */ void itemRemoved(ProjectItem *); - + /** * This signal is emitted whrn a ProjectItem's name is changed. */ diff --git a/isis/src/qisis/objs/ProjectItemTreeView/ProjectItemTreeView.cpp b/isis/src/qisis/objs/ProjectItemTreeView/ProjectItemTreeView.cpp index 8635a3d542c879bcbec993598d0c9ed7161d7c7d..382bf8902cc4c878df93eca1e18c66b840d55686 100644 --- a/isis/src/qisis/objs/ProjectItemTreeView/ProjectItemTreeView.cpp +++ b/isis/src/qisis/objs/ProjectItemTreeView/ProjectItemTreeView.cpp @@ -49,17 +49,20 @@ namespace Isis { m_treeView->setDragEnabled(false); m_treeView->setAcceptDrops(false); m_treeView->setHeaderHidden(true); + + setCentralWidget(m_treeView); // Currently set all items on view to un-editable //m_treeView->setEditTriggers(QAbstractItemView::NoEditTriggers); // setAcceptDrops(true); - QBoxLayout *layout = new QVBoxLayout; - layout->addWidget(m_treeView); - layout->setContentsMargins(0, 0, 0, 0); - - setLayout(layout); + // TODO Commented-out by Summer for new inheritence for parent class. Will clean up when confirmed that not needed. + // QBoxLayout *layout = new QVBoxLayout; + // layout->addWidget(m_treeView); + // layout->setContentsMargins(0, 0, 0, 0); + // + // setLayout(layout); } diff --git a/isis/src/qisis/objs/ProjectItemTreeView/ProjectItemTreeView.h b/isis/src/qisis/objs/ProjectItemTreeView/ProjectItemTreeView.h index 1ddf11fde344ec4b044b911f1ff14bbdebe62e0e..e54f98c58f1ba0e00675309542c4738083d3d491 100644 --- a/isis/src/qisis/objs/ProjectItemTreeView/ProjectItemTreeView.h +++ b/isis/src/qisis/objs/ProjectItemTreeView/ProjectItemTreeView.h @@ -55,6 +55,9 @@ namespace Isis { * Resolves [-Wheader-guard] warnings for prog17 (clang). * @history 2017-04-12 Tracie Sucharski - Turn off dragging on the treeView for now since it is * does not work and is causing errors. + * @history 2018-05-29 Summer Stapleton - updated the view to include a central widget and to + * remove layout capacity. This change was made to adjust to parent + * class now inheriting from QMainWindow instead of QWidget. */ class ProjectItemTreeView : public AbstractProjectItemView { diff --git a/isis/src/qisis/objs/QIsisApplication/QIsisApplication.cpp b/isis/src/qisis/objs/QIsisApplication/QIsisApplication.cpp index 94598f1c237c0ee940e68e6c93394493c871440d..d8b81a7bd64ab67de7b3a3cc0a52ee5fe446081b 100644 --- a/isis/src/qisis/objs/QIsisApplication/QIsisApplication.cpp +++ b/isis/src/qisis/objs/QIsisApplication/QIsisApplication.cpp @@ -24,24 +24,24 @@ namespace Isis { * * @param argc Pass this in from main(argc, argv) * @param argv Pass this in from main(argc, argv) - * + * * @internal - * @history 2017-10-06 Adam Goins - QIsisApplication now checks for a "-pref" flag - * in the command-line arguments and loads the following + * @history 2017-10-06 Adam Goins - QIsisApplication now checks for a "-pref" flag + * in the command-line arguments and loads the following * preference file if it exists. Fixes # 814 */ QIsisApplication::QIsisApplication(int &argc, char *argv[]) : QApplication(argc, argv) { // try to use US locale for numbers so we don't end up printing "," instead // of "." where it might count. - + for (int i = 1; i < argc; i++) { QString arg(argv[i]); if (arg.startsWith("-pref")) { - + // So that we can grab the file located after the current '-pref' flag. int nextIndex = i + 1; - + if (nextIndex < argc) { FileName preferenceFile(argv[nextIndex]); QString filePath = preferenceFile.expanded(); @@ -52,7 +52,7 @@ namespace Isis { QMessageBox::warning(NULL, "Warning", "Preference flag set but no preference file given."); } } - } + } setlocale(LC_NUMERIC, "en_US"); QDesktopServices::setUrlHandler("http", this, "openUrl"); diff --git a/isis/src/qisis/objs/SortFilterProxyModel/Makefile b/isis/src/qisis/objs/SortFilterProxyModel/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f122bc88227c5c7ebd108dea5d339d1d2e074d82 --- /dev/null +++ b/isis/src/qisis/objs/SortFilterProxyModel/Makefile @@ -0,0 +1,7 @@ +ifeq ($(ISISROOT), $(BLANK)) +.SILENT: +error: + echo "Please set ISISROOT"; +else + include $(ISISROOT)/make/isismake.objs +endif \ No newline at end of file diff --git a/isis/src/qisis/objs/SortFilterProxyModel/SortFilterProxyModel.cpp b/isis/src/qisis/objs/SortFilterProxyModel/SortFilterProxyModel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7272ef3902d8cc5f568c513de8a221f65c392eb1 --- /dev/null +++ b/isis/src/qisis/objs/SortFilterProxyModel/SortFilterProxyModel.cpp @@ -0,0 +1,97 @@ +#include "SortFilterProxyModel.h" + +#include <QAbstractItemModel> +#include <QIdentityProxyModel> +#include <QModelIndex> +#include <QObject> +#include <QPersistentModelIndex> +#include <QSortFilterProxyModel> +#include <QStandardItem> +#include <QVariant> + +#include "ProjectItem.h" +#include "ProjectItemModel.h" + +namespace Isis { + + SortFilterProxyModel::SortFilterProxyModel(QObject *parent) : + QSortFilterProxyModel(parent) { + } + + + void SortFilterProxyModel::setSelectedItems(QList<ProjectItem *> selected){ + + QList<QModelIndex> selIx; + foreach(ProjectItem * item,selected) { + selIx.append(item->index() ); + + } + + foreach(QModelIndex ix,selIx) { + selectedIndexRows.append(ix.row() ); + } + + selectedIndices=selIx; + + } + + void SortFilterProxyModel::setSourceModel(ProjectItemModel *newSourceModel) { + + QPersistentModelIndex persistentIndex(newSourceModel->index(0,0,QModelIndex())); + + + + if (persistentIndex.isValid()) { + //qDebug() << "persistent index is valid: " << persistentIndex; + m_root = persistentIndex; + } + else { + //qDebug() << "persistent index NOT valid."; + m_root = QPersistentModelIndex(QModelIndex()); + } + + baseModel = newSourceModel; + QSortFilterProxyModel::setSourceModel(newSourceModel); + } + + + bool SortFilterProxyModel::setRoot(const QStandardItem *item) { + + m_root = QPersistentModelIndex(item->index()); + return true; + + + } + + + bool SortFilterProxyModel::filterAcceptsRow(int sourceRow, + const QModelIndex &sourceParent) const { + bool accept(false); + + if (selectedIndices.count() == 0) { + accept = true; + } + + if (this->sourceModel()!=nullptr) { + QModelIndex ix = this->sourceModel()->index( sourceRow, 0, sourceParent ); + if (ix.isValid() ) { + ProjectItem * item = baseModel->itemFromIndex(ix); + if (selectedIndices.contains(ix) ) { + accept = true; + } + if (item->text() == "Images" ) { + accept = true; + } + }//end if (ix.isValid() ) + + } + return accept; + + } + + + + +}//end namespace + + diff --git a/isis/src/qisis/objs/SortFilterProxyModel/SortFilterProxyModel.h b/isis/src/qisis/objs/SortFilterProxyModel/SortFilterProxyModel.h new file mode 100644 index 0000000000000000000000000000000000000000..9a697014f2cd96054d4590fc4e1183e9d3e77395 --- /dev/null +++ b/isis/src/qisis/objs/SortFilterProxyModel/SortFilterProxyModel.h @@ -0,0 +1,83 @@ + +#ifndef SortFilterProxyModel_h +#define SortFilterProxyModel_h + +/** + * @file + * $Date: 2018/06/88 16:40:33 $ $Revision: 1.0 $ + * + * Unless noted otherwise, the portions of Isis written by the USGS are public domain. See + * individual third-party library and package descriptions for intellectual property information, + * user agreements, and related information. + * + * Although Isis has been used by the USGS, no warranty, expressed or implied, is made by the + * USGS as to the accuracy and functioning of such software and related material nor shall the + * fact of distribution constitute any such warranty, and no responsibility is assumed by the + * USGS in connection therewith. + * + * For additional information, launch $ISISROOT/doc//documents/Disclaimers/Disclaimers.html + * in a browser or see the Privacy & Disclaimers page on the Isis website, + * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on + * http://www.usgs.gov/privacy.html. + */ + +#include <QList> +#include <QIdentityProxyModel> +#include <QModelIndex> +#include <QPersistentModelIndex> +#include <QSortFilterProxyModel> + +class QAbstractProxyModel; +class QObject; +class QStandardItem; + +class QVariant; + +namespace Isis { + +class ProjectItem; +class ProjectItemModel; + + /** + * + * @author 2018-06-18 Tyler Wilson + * + * @internal + * @history 2018-06-18 Tyler Wilson - Original version. A proxy class for filtering data + * within the JigsawSetupDialog Bundle Observation Solve Settings (BOSS) tab. + */ + + class SortFilterProxyModel : public QSortFilterProxyModel { + Q_OBJECT + + public: + explicit SortFilterProxyModel(QObject *parent = 0); + + //QModelIndex mapFromSource(const QModelIndex &sourceIndex) const Q_DECL_OVERRIDE; + //QModelIndex mapToSource(const QModelIndex &proxyIndex) const Q_DECL_OVERRIDE; + + //void setSourceModel(ProjectItemModel *newSourceModel) Q_DECL_OVERRIDE; + void setSourceModel(ProjectItemModel *newSourceModel); + + bool setRoot(const QStandardItem *item); + + void setSelectedItems(QList<ProjectItem*> selected); + + + protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + + private: + ProjectItemModel * baseModel; + QList<QModelIndex> selectedIndices; + QList<int> selectedIndexRows; + QPersistentModelIndex m_root; + QModelIndex root; + + + }; + +}; + + +#endif diff --git a/isis/src/qisis/objs/SubTreeProxyModel/Makefile b/isis/src/qisis/objs/SubTreeProxyModel/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f122bc88227c5c7ebd108dea5d339d1d2e074d82 --- /dev/null +++ b/isis/src/qisis/objs/SubTreeProxyModel/Makefile @@ -0,0 +1,7 @@ +ifeq ($(ISISROOT), $(BLANK)) +.SILENT: +error: + echo "Please set ISISROOT"; +else + include $(ISISROOT)/make/isismake.objs +endif \ No newline at end of file diff --git a/isis/src/qisis/objs/SubTreeProxyModel/SubTreeProxyModel.cpp b/isis/src/qisis/objs/SubTreeProxyModel/SubTreeProxyModel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f13dd42d5eaeea7dacd302ff53d1f5c331a23df --- /dev/null +++ b/isis/src/qisis/objs/SubTreeProxyModel/SubTreeProxyModel.cpp @@ -0,0 +1,97 @@ +#include "SubTreeProxyModel.h" + +#include <QAbstractItemModel> +#include <QIdentityProxyModel> +#include <QModelIndex> +#include <QObject> +#include <QPersistentModelIndex> +#include <QSortFilterProxyModel> +#include <QStandardItem> +#include <QVariant> + +#include "ProjectItem.h" + +namespace Isis { + + + /** + * @brief Constructs a SubTreeProxyModel. + * + * Constructs a SubTreeProxyModel that can be used to operate on a sub-section of the source + * model. By default, the sub tree will be identical to the source model. The setRoot() method + * can be used to specify where the subtree starts. An example of usage can be found in + * JigsawDialog::createObservationSolveSettingsTreeView(). + * + * @param QObject *parent The parent of this SubTreeProxyModel. + * + * @see JigsawDialog::createObservationSolveSettingsTreeView() + * @see SubTreeProxyModel::setRoot() + */ + SubTreeProxyModel::SubTreeProxyModel(QObject *parent) : QIdentityProxyModel(parent) { + } + + + // Returns the model index in the proxy model corresponding to the sourceIndex from the + // source model + QModelIndex SubTreeProxyModel::mapFromSource(const QModelIndex &sourceIndex) const { + // check if the model index corresponds to the invisible root item in source model + if (sourceIndex == + static_cast<QStandardItemModel *>(sourceModel())->invisibleRootItem()->index()) { + qDebug() << "creating index for invisible root item " + << static_cast<QStandardItemModel *>(sourceModel())->invisibleRootItem()->index(); + return createIndex(sourceIndex.row(), 0, sourceIndex.internalId()); + } + + // First check to see if the source index is the proxy root + if (sourceIndex == m_root) { + return createIndex(sourceIndex.row(), 0, sourceIndex.internalId()); + } + + // If the source index is a child of the proxy root, one if its ancestors IS proxy root + QModelIndex ancestorIndex = sourceIndex.parent(); + while (ancestorIndex.isValid() && ancestorIndex != m_root) { + ancestorIndex = ancestorIndex.parent(); + } + if (ancestorIndex.isValid()) { + return createIndex(sourceIndex.row(), 0, sourceIndex.internalId()); + } + else { + return QModelIndex(); + } + } + + + //Returns the model index in the source that corresponds to the proxy index + //in the proxy model + QModelIndex SubTreeProxyModel::mapToSource(const QModelIndex &proxyIndex) const { + return QIdentityProxyModel::mapToSource(proxyIndex); + } + + + void SubTreeProxyModel::setSourceModel(QAbstractItemModel *newSourceModel) { + QPersistentModelIndex persistentIndex(newSourceModel->index(0,0,QModelIndex())); + + if (persistentIndex.isValid()) { + m_root = persistentIndex; + } + else { + m_root = QPersistentModelIndex(QModelIndex()); + } + + QIdentityProxyModel::setSourceModel(newSourceModel); + } + + + bool SubTreeProxyModel::setRoot(const QStandardItem *item) { + QAbstractItemModel::removeRows(1,2,item->index()); + + if (m_root.isValid()) { + return true; + } + else { + return false; + } + } + + +} diff --git a/isis/src/qisis/objs/SubTreeProxyModel/SubTreeProxyModel.h b/isis/src/qisis/objs/SubTreeProxyModel/SubTreeProxyModel.h new file mode 100644 index 0000000000000000000000000000000000000000..96fe3aa60b5b799095c05c1815d60eaf3d6cae9c --- /dev/null +++ b/isis/src/qisis/objs/SubTreeProxyModel/SubTreeProxyModel.h @@ -0,0 +1,57 @@ + +#ifndef SubTreeProxyModel_h +#define SubTreeProxyModel_h + +#include <QIdentityProxyModel> +#include <QPersistentModelIndex> +#include <QSortFilterProxyModel> + +class QAbstractProxyModel; +class QObject; +class QStandardItem; +class QVariant; + +namespace Isis { + +/** + * + * @author ????-??-?? Ian Humphrey + * @internal ????-??-?? Ian Humphrey + * + * + */ + + class SubTreeProxyModel : public QIdentityProxyModel { + Q_OBJECT + + public: + explicit SubTreeProxyModel(QObject *parent = 0); + + QModelIndex mapFromSource(const QModelIndex &sourceIndex) const Q_DECL_OVERRIDE; + QModelIndex mapToSource(const QModelIndex &proxyIndex) const Q_DECL_OVERRIDE; + + void setSourceModel(QAbstractItemModel *newSourceModel) Q_DECL_OVERRIDE; + + bool setRoot(const QStandardItem *item); + + + // Allow reading of the model + //QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + //Qt::ItemFlags flags(const QModelIndex &index) const override; + + // Allow re-sizing the model + //bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; + + // Use the method below to change how filtering chooses to accept the row + // protected: + // bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + + private: + QPersistentModelIndex m_root; + + }; + +}; + + +#endif diff --git a/isis/src/qisis/objs/TableMainWindow/TableMainWindow.cpp b/isis/src/qisis/objs/TableMainWindow/TableMainWindow.cpp index f13312e3d06c9660c5ccc679229aaea0b6a9ed64..12e6b3a02f75b272340eec0d33d5cb420af9f16c 100644 --- a/isis/src/qisis/objs/TableMainWindow/TableMainWindow.cpp +++ b/isis/src/qisis/objs/TableMainWindow/TableMainWindow.cpp @@ -140,6 +140,7 @@ namespace Isis { QAction *clear = new QAction(this); clear->setText("Clear table"); + clear->setShortcut(Qt::CTRL + Qt::Key_Delete); connect(clear, SIGNAL(triggered()), this, SLOT(clearTable())); QAction *close = new QAction(this); diff --git a/isis/src/qisis/objs/TableMainWindow/TableMainWindow.h b/isis/src/qisis/objs/TableMainWindow/TableMainWindow.h index e7f849b2c74574bcacff517385d386074ab1637e..815af0f8411315cd5cf9112f87b1a8a44514ed66 100644 --- a/isis/src/qisis/objs/TableMainWindow/TableMainWindow.h +++ b/isis/src/qisis/objs/TableMainWindow/TableMainWindow.h @@ -51,6 +51,8 @@ namespace Isis { * Added resizeColumn() slot and readColumnSettings(). * modified writeSettings() to write updated settings on destroy. * Fixes #5142. + * @history 2018-04-20 Adam Goins - Added the ctrl+del keyboard shortcut to the TableMainWindow's + * "Clear Table" menu option. Fixes #4912. */ class TableMainWindow : public MainWindow { Q_OBJECT diff --git a/isis/src/qisis/objs/Template/Template.h b/isis/src/qisis/objs/Template/Template.h index fa2bd9c733006f27210395a1b35f0c4322ea427b..30953d8eca30b854cfe6d8f99bed180347723c80 100755 --- a/isis/src/qisis/objs/Template/Template.h +++ b/isis/src/qisis/objs/Template/Template.h @@ -34,11 +34,12 @@ class FileName; class Project; - /** - * This represents an ISIS template in a project-based GUI interface. - * This encapsulates ideas about a template such as it's filename and import name. - * + /** * @author 2017-11-01 Christopher Combs + * @internal + * @history - 2017-11-01 Christopher Combs - This represents an ISIS template in a + * project-based GUI interface. This encapsulates ideas about a + * template such as it's filename and import name. */ class Template : public QObject { Q_OBJECT @@ -59,13 +60,13 @@ void updateFileName(Project * project); private: - /** - * Nested class used to write the Template object information to an XML file for the - * purpose of saving and restoring the state of the project. - * - * @author 2012-??-?? Steven Lambright + /** + * @author ????-??-?? Steven Lambright * * @internal + * @history ????-??-?? Steven Lambright - Nested class used to write the Template object + * information to an XML file for the purpose of saving and + * restoring the state of the project. */ class XmlHandler : public XmlStackedHandler { public: diff --git a/isis/src/qisis/objs/TemplateList/TemplateList.h b/isis/src/qisis/objs/TemplateList/TemplateList.h index 03e7f793185442010a6ff89e2d83f317b77439ad..3524204d0b3e47f14e33e7a746e63d2b281ca165 100755 --- a/isis/src/qisis/objs/TemplateList/TemplateList.h +++ b/isis/src/qisis/objs/TemplateList/TemplateList.h @@ -34,11 +34,13 @@ namespace Isis { - /** - * Maintains a list of Templates so that templates can easily be copied from one Project to - * another, saved to disk, or deleted from disk. Adapted from ControlList. + /** * * @author 2017-11-01 Christopher Combs + * @internal + * @history 2017-11-01 Christopher Combs - Maintains a list of Templates so that templates + * can easily be copied from one Project to another, saved to disk, or deleted from disk. + * Adapted from ControlList. */ class TemplateList : public QObject, public QList<Template *> { Q_OBJECT @@ -67,6 +69,14 @@ QString m_type; class XmlHandler : public XmlStackedHandler { + /** + * + * @author 2017-11-01 Christopher Combs + * @internal + * @history 2017-11-01 Christopher Combs - Maintains a list of Templates so that templates + * can easily be copied from one Project to another, saved to disk, or deleted from disk. + * Adapted from ControlList. + */ public: XmlHandler(TemplateList *templateList, Project *project); diff --git a/isis/src/qisis/objs/WorkOrder/WorkOrder.cpp b/isis/src/qisis/objs/WorkOrder/WorkOrder.cpp index 18197b995cb61ffde06fd3bf3b84a298c208f068..8050613fc84a98ffcb88b233c41c4aea35e91a9e 100644 --- a/isis/src/qisis/objs/WorkOrder/WorkOrder.cpp +++ b/isis/src/qisis/objs/WorkOrder/WorkOrder.cpp @@ -173,7 +173,6 @@ namespace Isis { delete m_imageList; delete m_shapeList; delete m_futureWatcher; - delete m_progressBar; delete m_progressBarDeletionTimer; delete m_progressBarUpdateTimer; delete m_transparentConstMutex; @@ -1576,8 +1575,6 @@ namespace Isis { delete m_progressBarDeletionTimer; m_progressBarDeletionTimer = new QTimer; m_progressBarDeletionTimer->setSingleShot(true); - connect(m_progressBarDeletionTimer, SIGNAL(timeout()), - this, SLOT(deleteProgress())); m_progressBarDeletionTimer->start(5 * 1000); // 5 seconds @@ -1650,20 +1647,6 @@ namespace Isis { } - /** - * @brief Deletes the progress bar. - */ - void WorkOrder::deleteProgress() { - ProgressBar *progress = m_progressBar; - - if (m_progressBar) { - m_progressBar = NULL; - emit deletingProgress(this); - delete progress; - } - } - - /** * @brief Updates the progress bar. */ diff --git a/isis/src/qisis/objs/WorkOrder/WorkOrder.h b/isis/src/qisis/objs/WorkOrder/WorkOrder.h index eb7f482fa564ed9f3b37df0480d193a83db795ff..1e391fa658d2b7bf36cd02d93cb5b524bc082de1 100644 --- a/isis/src/qisis/objs/WorkOrder/WorkOrder.h +++ b/isis/src/qisis/objs/WorkOrder/WorkOrder.h @@ -314,6 +314,10 @@ namespace Isis { * a private QString object called m_data. References #4492. * @history 2017-12-05 Christopher Combs - Added support for TemplateEditorWidget and * TemplateEditViewWorkOrder. Fixes #5168. + * @history 2018-06-28 Makayla Shepherd - Removed the ProgressBar cleanup because it was + * causing a seg fault when the ProgressBar was added to the + * HistoryTreeWidget. The HistoryTreeWidget will now clean up the + * ProgressBar. Fixes #5228. */ class WorkOrder : public QAction, public QUndoCommand { Q_OBJECT @@ -480,7 +484,6 @@ namespace Isis { void executionFinished(); void clearImageList(); void clearShapeList(); - void deleteProgress(); void updateProgress(); void startRedo(); diff --git a/isis/src/qisis/objs/WorkOrder/WorkOrderFactory.cpp b/isis/src/qisis/objs/WorkOrder/WorkOrderFactory.cpp index 369ff1bee0e702677d514e1ca0c34924f8318459..5ce3cfce88a9fe4d8cf76a527150d74945bf9317 100644 --- a/isis/src/qisis/objs/WorkOrder/WorkOrderFactory.cpp +++ b/isis/src/qisis/objs/WorkOrder/WorkOrderFactory.cpp @@ -2,6 +2,7 @@ #include "BundleObservationViewWorkOrder.h" #include "CnetEditorViewWorkOrder.h" +#include "ControlHealthMonitorWorkOrder.h" #include "CubeDnViewWorkOrder.h" #include "ExportControlNetWorkOrder.h" #include "ExportImagesWorkOrder.h" @@ -50,6 +51,7 @@ namespace Isis { tryType<BundleObservationViewWorkOrder>(type, project, result); tryType<CnetEditorViewWorkOrder>(type, project, result); + tryType<ControlHealthMonitorWorkOrder>(type, project, result); tryType<CubeDnViewWorkOrder>(type, project, result); tryType<ExportImagesWorkOrder>(type, project, result); tryType<ExportControlNetWorkOrder>(type, project, result); diff --git a/isis/src/qisis/objs/WorkOrder/WorkOrderFactory.h b/isis/src/qisis/objs/WorkOrder/WorkOrderFactory.h index f9747d71eacd4ff87923e8c1126f9352fe94763f..f9a317fb3278b407078c4516d3b150c58af92e4f 100644 --- a/isis/src/qisis/objs/WorkOrder/WorkOrderFactory.h +++ b/isis/src/qisis/objs/WorkOrder/WorkOrderFactory.h @@ -53,10 +53,12 @@ namespace Isis { * @history 2017-05-04 Tracie Sucharski - Added BundleObservationViewWorkOrder. Fixes #4840. * @history 2017-08-11 Christopher Combs - Added ImportTemplateWorkOrder. Fixes #5086. * @history 2017-11-02 Tyler Wilson - Added the OpenRecentProjectsWorkOrder. Fixes #4492. - * @history 2017-11-09 Tyler Wilson - Merged the functionality of OpenRecentProjectsWorkOrder + * @history 2017-11-09 Tyler Wilson - Merged the functionality of OpenRecentProjectsWorkOrder * into OpenProjectWorkOrder to reduce unnecessary code duplication, * and removed references to OpenRecentProjectWorkOrder in this * class. Fixes #5220. + * @history 2018-06-18 Adam Goins - Added ControlHealthMonitorWorkOrder to WorkOrderFactory. + * Fixes #5435. */ class WorkOrderFactory { public: