Commit 3e29bf91 authored by Jeannie Backer's avatar Jeannie Backer
Browse files

PROG: Merge TargetBodyDisplayProperties from ipce into trunk.

git-svn-id: http://subversion.wr.usgs.gov/repos/prog/isis3/trunk@6836 41f8697f-d340-4b68-9986-7bafba869bb8
parent 90f6629d
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
ifeq ($(ISISROOT), $(BLANK))
.SILENT:
error:
	echo "Please set ISISROOT";
else
	include $(ISISROOT)/make/isismake.objs
endif
 No newline at end of file
+334 −0
Original line number Diff line number Diff line
#include "TargetBodyDisplayProperties.h"

#include <QAction>
#include <QBitArray>
#include <QBuffer>
#include <QColorDialog>
#include <QDebug>
#include <QInputDialog>
#include <QMap>
#include <QVariant>
#include <QXmlStreamWriter>

#include "FileName.h"
#include "Pvl.h"
#include "XmlStackedHandlerReader.h"

namespace Isis {
  /**
   * @brief TargetBodyDisplayProperties constructor. This sets default values and
   * constructs the object *.
   * @param displayName The filename (fully expanded) of the object.
   * @param parent Qt parent object (this is destroyed when parent is destroyed)
   */
  TargetBodyDisplayProperties::TargetBodyDisplayProperties(QString displayName, QObject *parent) :
      DisplayProperties(displayName, parent) {

    m_propertiesUsed = None;
    m_propertyValues = new QMap<int, QVariant>;

    // set all of the defaults to prevent unwanted change signals from
    //   being emitted later.
    setShowLabel(false);
    setSelected(false);

    setValue(Color, QVariant::fromValue(randomColor()));
  }

  /**
   * @brief TargetBodyDisplayProperties constructor
   * @param xmlReader The XML reader parsing the XML file containing the display properties.
   * @param parent The Qt parent object (this is destroyed when the parent is destroyed).
   */
  TargetBodyDisplayProperties::TargetBodyDisplayProperties(XmlStackedHandlerReader *xmlReader,
      QObject *parent) : DisplayProperties("", parent) {
    m_propertiesUsed = None;
    m_propertyValues = new QMap<int, QVariant>;

    xmlReader->pushContentHandler(new XmlHandler(this));
  }


  /**
   * @brief The destructor.
   */
  TargetBodyDisplayProperties::~TargetBodyDisplayProperties() {
  }


//  void TargetBodyDisplayProperties::fromPvl(const PvlObject &pvl) {
//    m_displayName = ((IString)pvl["DisplayName"][0]).ToQt();

//    QByteArray hexValues(pvl["Values"][0].c_str());
//    QDataStream valuesStream(QByteArray::fromHex(hexValues));
//    valuesStream >> *m_propertyValues;
//  }


//  /**
//   * Convert to Pvl for project files. This stores all of the data associated
//   *   with all of the properties (but not what is supported). This also s  tores
//   *   the target filename.
//   */
//  PvlObject TargetBodyDisplayProperties::toPvl() const {
//    PvlObject output("DisplayProperties");
//    output += PvlKeyword("DisplayName", m_displayName);

//    QBuffer dataBuffer;
//    dataBuffer.open(QIODevice::ReadWrite);

//    QDataStream propsStream(&dataBuffer);
//    propsStream << *m_propertyValues;
//    dataBuffer.seek(0);

//    output += PvlKeyword("Values", QString(dataBuffer.data().toHex()));

//    return output;
//  }


  /**
   * @brief Call this with every property you support, otherwise they will not
   *  communicate properly between widgets.
   * @param prop The property you are adding support for
   */
  void TargetBodyDisplayProperties::addSupport(Property prop) {
    if (!supports(prop)) {
      m_propertiesUsed = (Property)(m_propertiesUsed | prop);
      emit supportAdded(prop);
    }
  }


  /**
   * @brief Support for this may come later. Please make sure you are connected to the
   *  supportAdded signal.
   * @return @b bool True if the property has support, false otherwise.
   */
  bool TargetBodyDisplayProperties::supports(Property prop) {
    return (m_propertiesUsed & prop) == prop;
  }


  /**
   * @brief Get a property's associated data.
   *
   * @param prop The property
   * @return @b QVariant The data associated with the property.
   */
  QVariant TargetBodyDisplayProperties::getValue(Property prop) const {
    return (*m_propertyValues)[prop];
  }


  /**
   * @brief Creates and returns a random color for the initial color of
   * the footprint polygon.
   * @return @b QColor The color for the initial footprint polygon.
   */
  QColor TargetBodyDisplayProperties::randomColor() {
    // Gives a random number between 0 and 255
    int red = 0;
    int green = 0;
    int blue = 0;

    // Generate dark
    while (red + green + blue < 300) {
      red   = rand() % 256;
      green = rand() % 256;
      blue  = rand() % 256;
    }

    return QColor(red, green, blue, 60);
  }

  /**
   * @brief Saves this object to an XML file.
   * @param stream  The XML stream writer write to.
   * @param project The project this object is attached to (not used).
   * @param newProjectRoot FileName of the project?  (not used).
   */
  void TargetBodyDisplayProperties::save(QXmlStreamWriter &stream, const Project *project,
                                      FileName newProjectRoot) const {
    stream.writeStartElement("displayProperties");

    stream.writeAttribute("displayName", displayName());

    // Get hex-encoded data
    QBuffer dataBuffer;
    dataBuffer.open(QIODevice::ReadWrite);
    QDataStream propsStream(&dataBuffer);
    propsStream << *m_propertyValues;
    dataBuffer.seek(0);

    stream.writeCharacters(dataBuffer.data().toHex());

    stream.writeEndElement();
  }


  /**
   * @brief Change the color associated with this target.
   * @param newColor  The new color associated with this target.
   */
  void TargetBodyDisplayProperties::setColor(QColor newColor) {
    setValue(Color, QVariant::fromValue(newColor));
  }


  /**
   * @brief Change the selected state associated with this target.
   * @param The new state associated with this target.
   */
  void TargetBodyDisplayProperties::setSelected(bool newValue) {
    setValue(Selected, newValue);
  }


  /**
   * @brief Change the visibility of the display name associated with this target.
   * @param newValue The visibiliy of the display name for this target.
   */
  void TargetBodyDisplayProperties::setShowLabel(bool newValue) {
    setValue(ShowLabel, newValue);
  }


  /**
   * @description. Change the visibility of the display name. This should only be connected to
   * by an action with a list of displays as its data. This synchronizes all
   * of the values where at least one is guaranteed to be toggled.
   */
  void TargetBodyDisplayProperties::toggleShowLabel() {
    QList<TargetBodyDisplayProperties *> displays = senderToData(sender());

    bool value = getValue(ShowLabel).toBool();
    value = !value;

    TargetBodyDisplayProperties *display;
    foreach (display, displays) {
      display->setShowLabel(value);
    }
  }


  /**
   * @description Constructor for the XmlHandler class.  This is a child class of XmlStackedHandler,
   * which is used by XmlStackedHandlerReader to parse an XML file.
   * @param displayProperties Pointer to a TargetBodyDisplayProperties object.
   */
  TargetBodyDisplayProperties::XmlHandler::XmlHandler(TargetBodyDisplayProperties *displayProperties) {
    m_displayProperties = displayProperties;
  }


  /**
   * @brief This overrides the parent startElement function in XmlStackedHandler so the parser can
   * handle an XML file containing TargetBodyDisplayProperties information.
   * @param namespaceURI The Uniform Resource Identifier of the element's namespace
   * @param localName The local name string
   * @param qName The XML qualified string (or empty, if QNames are not available).
   * @param atts The XML attributes attached to each element
   * @return @b bool  Returns True signalling to the reader the start of a valid XML element.  If
   * False is returned, something bad happened.
   */
  bool TargetBodyDisplayProperties::XmlHandler::startElement(const QString &namespaceURI,
      const QString &localName, const QString &qName, const QXmlAttributes &atts) {
    if (XmlStackedHandler::startElement(namespaceURI, localName, qName, atts)) {
      if (localName == "displayProperties") {
        QString displayName = atts.value("displayName");

        if (!displayName.isEmpty()) {
          m_displayProperties->setDisplayName(displayName);
        }
      }
    }

    return true;
  }


  /**
   * @description This implementation of a virtual function calls
   * QXmlDefaultHandler::characters(QString &ch)
   * which in turn calls QXmlContentHandler::characters(QString &ch) which
   * is called when the XML processor has parsed a chunk of character data.
   * @see XmlStackedHandler, QXmlDefaultHandler,QXmlContentHandler
   * @param ch The character data.
   * @return @b bool Returns True if there were no problems with the character processing.
   * It returns False if there was a problem, and the XML reader stops.
   */
  bool TargetBodyDisplayProperties::XmlHandler::characters(const QString &ch) {
    m_hexData += ch;

    return XmlStackedHandler::characters(ch);
  }



  /**
   * @brief The XML reader invokes this method at the end of every element in the
   *        XML document.
   * @param namespaceURI  The Uniform Resource Identifier of the namespace (eg. "xmlns")
   * @param localName The local name string (eg. "xhtml")
   * @param qName The XML qualified string (eg.  "xmlns:xhtml"). This can be empty if
   *        QNames are not available.
   * @return @b bool If this function returns True, then a signal is sent to the reader indicating
   * the end of the element.  If this function returns False, something bad
   * happened and processing stops.
   */
  bool TargetBodyDisplayProperties::XmlHandler::endElement(const QString &namespaceURI,
      const QString &localName, const QString &qName) {
    if (localName == "displayProperties") {
      QByteArray hexValues(m_hexData.toLatin1());
      QDataStream valuesStream(QByteArray::fromHex(hexValues));
      valuesStream >> *m_displayProperties->m_propertyValues;
    }

    return XmlStackedHandler::endElement(namespaceURI, localName, qName);
  }



  /**
   * @description This is the generic mutator for properties. Given a value, this will
   * change it and emit propertyChanged if its different and supported.
   * @param prop The key into the m_propertyValues QMap <int, QVariant>
   * @param value The value we want to change to.
   */
  void TargetBodyDisplayProperties::setValue(Property prop, QVariant value) {
    if ((*m_propertyValues)[prop] != value) {
      (*m_propertyValues)[prop] = value;

      if (supports(prop)) {
        emit propertyChanged(this);
      }
    }
  }


  /**
   * @description This is for the slots that have a list of display properties as associated
   * data. This gets that list out of the data.
   * @param The object requesting the data.
   * @return @b QList<TargetBodyDisplayProperties *> A list of pointers to
   * TargetBodyDisplayProperties objects.
   */
  QList<TargetBodyDisplayProperties *> TargetBodyDisplayProperties::senderToData(
      QObject *senderObj) {
    QList<TargetBodyDisplayProperties *> data;

    if (senderObj) {
      QAction *caller = (QAction *)senderObj;
      QVariant callerData = caller->data();

      if (callerData.canConvert< QList<TargetBodyDisplayProperties *> >() ) {
        data = callerData.value< QList<TargetBodyDisplayProperties *> >();
      }
    }

    return data;
  }


}
+176 −0
Original line number Diff line number Diff line
#ifndef TargetBodyDisplayProperties_H
#define TargetBodyDisplayProperties_H
/**
 * @file
 * $Revision: 1.9 $
 * $Date: 2012/06/12 06:30:00 $
 *
 *   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 &amp; 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 <QColor> // This is required since QColor is in a slot
#include <QMetaType> // required since we're adding to QVariant
#include <QObject>

#include "DisplayProperties.h"
#include "XmlStackedHandler.h"

class QAction;
class QXmlStreamWriter;

namespace Isis {
  class FileName;
  class Project;
  class Pvl;
  class PvlObject;
  class XmlStackedHandlerReader;

  /**
   * @brief This is the GUI communication mechanism for target body objects.
   *
   * This class is the connector between various GUI interfaces for target body objects.
   *   We use this to communicate shared properties that various widgets need
   *   to know/should react to in a generic way.
   *
   * This is how this class is supposed to "connect" widgets:
   *
   *  widgetA         widgetB           widgetC
   *     |               |                 |
   *     ------DisplayProperties -------
   *
   * When a user selects a target in widgetA, widgetB and widgetC now have a
   *   chance to also select the same target. This applies to all shared
   *   properties. Some of the properties are actions - such as ?????. This
   *   also allows a widget with no ??? (such as a list) to have an option
   *   to ???? (if any of the widgets support it*) and have that option work.
   *   There is no state associated with ????? - it's an action connected
   *   to a signal.
   *
   * The proper way to detect a target going away is to connect to the
   *   destroyed signal (from the parent QObject). Once that is emitted you
   *   cannot call any methods on this object.
   *
   * @author 2015-05-27 Ken Edmundson
   *
   * @internal
   *   @history 2015-05-27 Ken Edmundson - Creation.
   *   @hsitory 21016-06-14 Tyler Wilson - Added documentation to member functions/variables
   *                           and corrected some formatting to bring the the code in line
   *                           with ISIS3 coding standards.  Fixes #3997.
   *
   */
  class TargetBodyDisplayProperties : public DisplayProperties {
      Q_OBJECT
    public:
        /**
         * @brief This is a list of properties and actions that are possible.
         */
        enum Property {
          //! Null display property for bit-flag purposes
          None             = 0,
          //! The color of the control net, default randomized (QColor)
          Color            = 1,
          //! The selection state of this control net (bool)
          Selected         = 2,
          //! True if the control net should show its display name (bool)
          ShowLabel        = 16,
        };


      TargetBodyDisplayProperties(QString displayName, QObject *parent = NULL);
      TargetBodyDisplayProperties(XmlStackedHandlerReader *xmlReader, QObject *parent = NULL);
      virtual ~TargetBodyDisplayProperties();

//      void fromPvl(const PvlObject &pvl);
//      PvlObject toPvl() const;

      void addSupport(Property prop);
      bool supports(Property prop);

      QVariant getValue(Property prop) const;

      static QColor randomColor();

      void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const;

    signals:
      void propertyChanged(TargetBodyDisplayProperties *);
      void supportAdded(Property);

    public slots:
      void setColor(QColor newColor);
      void setShowLabel(bool);
      void setSelected(bool);

    private slots:
      void toggleShowLabel();

    private:
      /**
       * @description This class is used for processing an XML file containing information
       * about a WorkOrder.
       *
       * @author 2012-??-?? Steven Lambright
       *
       * @internal
       */
      class XmlHandler : public XmlStackedHandler {
        public:
          XmlHandler(TargetBodyDisplayProperties *displayProperties);

          virtual bool startElement(const QString &namespaceURI, const QString &localName,
                                    const QString &qName, const QXmlAttributes &atts);

          virtual bool characters(const QString &ch);

          virtual bool endElement(const QString &namespaceURI, const QString &localName,
                                  const QString &qName);

        private:
          Q_DISABLE_COPY(XmlHandler);

          TargetBodyDisplayProperties *m_displayProperties;
          QString m_hexData;
      };

    private:
      TargetBodyDisplayProperties(const TargetBodyDisplayProperties &);
      TargetBodyDisplayProperties &operator=(const TargetBodyDisplayProperties &);

      void setValue(Property prop, QVariant value);
      static QList<TargetBodyDisplayProperties *> senderToData(QObject *sender);

      /**
       * This indicated whether any widgets with this DisplayProperties
       *   is using a particular property. This helps others who can set
       *   but not display know whether they should give the option to set.
       */
      Property m_propertiesUsed;

      /**
       * This is a map from Property to value -- the reason I use an int is
       *   so Qt knows how to serialize this QMap into binary data
       */
      QMap<int, QVariant> *m_propertyValues;
  };
}

Q_DECLARE_METATYPE(QList<Isis::TargetBodyDisplayProperties *>);

#endif