Isis 3 Programmer Reference
ShapeList.cpp
1 
7 /* SPDX-License-Identifier: CC0-1.0 */
8 
9 #include "ShapeList.h"
10 
11 #include <QDebug>
12 #include <QDir>
13 #include <QFile>
14 #include <QFuture>
15 #include <QInputDialog>
16 #include <QLabel>
17 #include <QProgressDialog>
18 #include <QtConcurrentMap>
19 #include <QXmlStreamWriter>
20 
21 #include "FileName.h"
22 #include "IException.h"
23 #include "IString.h"
24 #include "Project.h"
25 #include "XmlStackedHandlerReader.h"
26 
27 namespace Isis {
35  ShapeList::ShapeList(QString name, QString path, QObject *parent) : QObject(parent) {
36  m_name = name;
37  m_path = path;
38  }
39 
40 
46  ShapeList::ShapeList(QObject *parent) : QObject(parent) {
47  }
48 
49 
56  ShapeList::ShapeList(QList<Shape *> shapes, QObject *parent) : QObject(parent) {
57  append(shapes);
58  }
59 
60 
69  QObject(parent) {
70  xmlReader->pushContentHandler(new XmlHandler(this, project));
71  }
72 
73 
80  QList<Shape *>(other) {
81  m_name = other.m_name;
82  m_path = other.m_path;
83  }
84 
85 
92  foreach (QString fileName, fileNames) {
93  try {
94  Shape *shape = new Shape(fileName);
95  append(shape);
96  }
97  catch (IException &) {
98  }
99  }
100  }
101 
102 
107  }
108 
109 
116 
117  SerialNumberList result;
118 
119  for (int i = 0; i < count(); i++) {
120  result.add((*this)[i]->fileName());
121  }
122  return result;
123  }
124 
125 
133  void ShapeList::append(Shape * const &value) {
134  QList<Shape *>::append(value);
135  emit countChanged(count());
136  }
137 
138 
146  void ShapeList::append(const QList<Shape *> &value) {
147  QList<Shape *>::append(value);
148  emit countChanged(count());
149  }
150 
151 
158  bool countChanging = count();
160  if (countChanging) {
161  emit countChanged(count());
162  }
163  }
164 
165 
176  iterator result = QList<Shape *>::erase(pos);
177  emit countChanged(count());
178  return result;
179  }
180 
181 
194  QList<Shape *>::iterator ShapeList::erase(iterator begin, iterator end) {
195  iterator result = QList<Shape *>::erase(begin, end);
196  emit countChanged(count());
197  return result;
198  }
199 
200 
209  void ShapeList::insert(int i, Shape * const &value) {
210  QList<Shape *>::insert(i, value);
211 
212  emit countChanged(count());
213  }
214 
215 
226  QList<Shape *>::iterator ShapeList::insert(iterator before, Shape * const &value) {
227  iterator result = QList<Shape *>::insert(before, value);
228  emit countChanged(count());
229  return result;
230  }
231 
232 
240  void ShapeList::prepend(Shape * const &value) {
242  emit countChanged(count());
243  }
244 
245 
254  void ShapeList::push_back(Shape * const &value) {
256  emit countChanged(count());
257  }
258 
259 
268  void ShapeList::push_front(Shape * const &value) {
270  emit countChanged(count());
271  }
272 
273 
283  int ShapeList::removeAll(Shape * const &value) {
284  int result = QList<Shape *>::removeAll(value);
285 
286  if (result != 0) {
287  emit countChanged(count());
288  }
289 
290  return result;
291  }
292 
293 
301  void ShapeList::removeAt(int i) {
303  emit countChanged(count());
304  }
305 
306 
314  emit countChanged(count());
315  }
316 
317 
325  emit countChanged(count());
326  }
327 
328 
338  bool ShapeList::removeOne(Shape * const &value) {
339  bool result = QList<Shape *>::removeOne(value);
340 
341  if (result) {
342  emit countChanged(count());
343  }
344 
345  return result;
346  }
347 
348 
357  QList<Shape *>::swap(other);
358 
359  if (count() != other.count()) {
360  emit countChanged(count());
361  }
362  }
363 
364 
375  Shape * result = QList<Shape *>::takeAt(i);
376  emit countChanged(count());
377  return result;
378  }
379 
380 
389  Shape *result = QList<Shape *>::takeFirst();
390  emit countChanged(count());
391  return result;
392  }
393 
394 
403  Shape *result = QList<Shape *>::takeLast();
404  emit countChanged(count());
405  return result;
406  }
407 
408 
421 
422  if (other.count()) {
423  emit countChanged(count());
424  }
425 
426  return *this;
427  }
428 
429 
442  emit countChanged(count());
443  return *this;
444  }
445 
446 
459 
460  if (other.count()) {
461  emit countChanged(count());
462  }
463 
464  return *this;
465  }
466 
467 
480  emit countChanged(count());
481  return *this;
482  }
483 
484 
495  bool countChanging = (rhs.count() != count());
497 
498  if (countChanging) {
499  emit countChanged(count());
500  }
501 
502  return *this;
503  }
504 
505 
514  bool countChanging = (rhs.count() != count());
516 
517  m_name = rhs.m_name;
518  m_path = rhs.m_path;
519 
520  if (countChanging) {
521  emit countChanged(count());
522  }
523 
524  return *this;
525  }
526 
527 
534  void ShapeList::setName(QString newName) {
535  m_name = newName;
536  }
537 
538 
545  void ShapeList::setPath(QString newPath) {
546  m_path = newPath;
547  }
548 
549 
555  QString ShapeList::name() const {
556  return m_name;
557  }
558 
559 
566  QString ShapeList::path() const {
567  return m_path;
568  }
569 
570 
579  foreach (Shape *shape, *this) {
580  shape->deleteFromDisk();
581  }
582 
583  if (!m_path.isEmpty()) {
584  QFile::remove(project->shapeDataRoot() + "/" + m_path + "/shapes.xml");
585 
586  QDir dir;
587  dir.rmdir(project->shapeDataRoot() + "/" + m_path);
588  }
589  }
590 
591 
615  void ShapeList::save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot)
616  const {
617  stream.writeStartElement("shapeList");
618  stream.writeAttribute("name", m_name);
619  stream.writeAttribute("path", m_path);
620 
621  FileName settingsFileName(
622  Project::shapeDataRoot(newProjectRoot.toString()) + "/" + m_path + "/shapes.xml");
623 
624  if (!settingsFileName.dir().mkpath(settingsFileName.path())) {
626  QString("Failed to create directory [%1]")
627  .arg(settingsFileName.path()),
628  _FILEINFO_);
629  }
630 
631  QFile shapeListContentsFile(settingsFileName.toString());
632 
633  if (!shapeListContentsFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
635  QString("Unable to save shape information for [%1] because [%2] could not be opened for "
636  "writing")
637  .arg(m_name).arg(settingsFileName.original()),
638  _FILEINFO_);
639  }
640 
641  QXmlStreamWriter shapeDetailsWriter(&shapeListContentsFile);
642  shapeDetailsWriter.setAutoFormatting(true);
643  shapeDetailsWriter.writeStartDocument();
644 
645  int countWidth = QString("%1L").arg(count()).size() - 1;
646  QChar paddingChar('0');
647 
648  QLabel *progressLabel = new QLabel;
649 
650  QProgressDialog progressDialog;
651  progressDialog.setLabel(progressLabel);
652  progressDialog.setRange(-1, count());
653  progressDialog.setValue(-1);
654 
655  shapeDetailsWriter.writeStartElement("shapes");
656  // Mapped is way faster than hundreds/thousands of run() calls... so use mapped for performance
657  QFuture<void *> future = QtConcurrent::mapped(*this,
658  CopyShapeDataFunctor(project, newProjectRoot));
659 
660  for (int i = 0; i < count(); i++) {
661  int newProgressValue = progressDialog.value() + 1;
662  progressLabel->setText(
663  tr("Saving Shape Information for [%1] - %L2/%L3 done")
664  .arg(m_name)
665  .arg(newProgressValue, countWidth, 10, paddingChar)
666  .arg(count()));
667  progressDialog.setValue(newProgressValue);
668  future.resultAt(i);
669  }
670 
671  progressLabel->setText(tr("Finalizing..."));
672  progressDialog.setRange(0, 0);
673  progressDialog.setValue(0);
674 
675  foreach (Shape *shape, *this) {
676  shape->save(shapeDetailsWriter, project, newProjectRoot);
677  }
678 
679  shapeDetailsWriter.writeEndElement();
680 
681  shapeDetailsWriter.writeEndDocument();
682 
683  stream.writeEndElement();
684  }
685 
686 
694  FileName newProjectRoot) {
695  m_project = project;
696  m_newProjectRoot = newProjectRoot;
697  }
698 
699 
706  m_project = other.m_project;
707  m_newProjectRoot = other.m_newProjectRoot;
708  }
709 
710 
715  }
716 
717 
727  shapeToCopy->copyToNewProjectRoot(m_project, m_newProjectRoot);
728  return NULL;
729  }
730 
731 
740  const CopyShapeDataFunctor &rhs) {
741  m_project = rhs.m_project;
742  m_newProjectRoot = rhs.m_newProjectRoot;
743  return *this;
744  }
745 
746 
756  m_shapeList = shapeList;
757  m_project = project;
758  }
759 
760 
767  bool ShapeList::XmlHandler::startElement(const QString &namespaceURI, const QString &localName,
768  const QString &qName, const QXmlAttributes &atts) {
769  if (XmlStackedHandler::startElement(namespaceURI, localName, qName, atts)) {
770  if (localName == "shapeList") {
771  QString name = atts.value("name");
772  QString path = atts.value("path");
773 
774  if (!name.isEmpty()) {
775  m_shapeList->setName(name);
776  }
777 
778  if (!path.isEmpty()) {
779  m_shapeList->setPath(path);
780  }
781  }
782  else if (localName == "shape") {
783  m_shapeList->append(new Shape(m_project->shapeDataRoot() + "/" + m_shapeList->path(),
784  reader()));
785  }
786  }
787 
788  return true;
789  }
790 
791 
801  bool ShapeList::XmlHandler::endElement(const QString &namespaceURI, const QString &localName,
802  const QString &qName) {
803  if (localName == "shapeList") {
804  XmlHandler handler(m_shapeList, m_project);
805 
807  reader.pushContentHandler(&handler);
808  reader.setErrorHandler(&handler);
809 
810  QString shapeListXmlPath = m_project->shapeDataRoot() + "/" + m_shapeList->path() +
811  "/shapes.xml";
812  QFile file(shapeListXmlPath);
813 
814  if (!file.open(QFile::ReadOnly)) {
816  QString("Unable to open [%1] with read access")
817  .arg(shapeListXmlPath),
818  _FILEINFO_);
819  }
820 
821  QXmlInputSource xmlInputSource(&file);
822  if (!reader.parse(xmlInputSource))
824  tr("Failed to open shape list XML [%1]").arg(shapeListXmlPath),
825  _FILEINFO_);
826  }
827 
828  return XmlStackedHandler::endElement(namespaceURI, localName, qName);
829  }
830 }
Isis::IException::Io
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition: IException.h:155
Isis::ShapeList::insert
void insert(int i, Shape *const &value)
Inserts an shape into the shape list at an index.
Definition: ShapeList.cpp:209
Isis::Shape::deleteFromDisk
void deleteFromDisk()
Delete the shape data from disk.
Definition: Shape.cpp:591
Isis::ShapeList::takeLast
Shape * takeLast()
Removes and returns the last shape.
Definition: ShapeList.cpp:402
QList< Shape * >
Project.h
Isis::ShapeList::operator<<
ShapeList & operator<<(const QList< Shape * > &other)
Appends a list of shapes to the end of the shape list.
Definition: ShapeList.cpp:457
Isis::FileName
File name manipulation and expansion.
Definition: FileName.h:100
Isis::ShapeList::CopyShapeDataFunctor::CopyShapeDataFunctor
CopyShapeDataFunctor(const Project *project, FileName newProjectRoot)
Constructor for CopyShapeDataFunctor.
Definition: ShapeList.cpp:693
Isis::XmlStackedHandlerReader::pushContentHandler
virtual void pushContentHandler(XmlStackedHandler *newHandler)
Push a contentHandler and maybe continue parsing...
Definition: XmlStackedHandlerReader.cpp:55
Isis::ShapeList::CopyShapeDataFunctor::~CopyShapeDataFunctor
~CopyShapeDataFunctor()
Destructor for CopyShapeDataFunctor.
Definition: ShapeList.cpp:714
Isis::ShapeList::takeFirst
Shape * takeFirst()
Removes and returns the first shape.
Definition: ShapeList.cpp:388
Isis::ShapeList::setName
void setName(QString newName)
Set the human-readable name of this shape list.
Definition: ShapeList.cpp:534
Isis::ShapeList::CopyShapeDataFunctor::operator()
void * operator()(Shape *const &shapeToCopy)
Copies the cub/ecub files for an shape into m_project.
Definition: ShapeList.cpp:726
Isis::ShapeList::~ShapeList
~ShapeList()
Destructor.
Definition: ShapeList.cpp:106
Isis::ShapeList::clear
void clear()
Clears the shape list.
Definition: ShapeList.cpp:157
Isis::Project::shapeDataRoot
static QString shapeDataRoot(QString projectRoot)
Appends the root directory name 'shapes' to the project .
Definition: Project.cpp:2087
Isis::ShapeList::push_front
void push_front(Shape *const &value)
Prepends an shape to the beginning of the shape list.
Definition: ShapeList.cpp:268
Isis::ShapeList::operator+=
ShapeList & operator+=(const QList< Shape * > &other)
Appends a list of shapes to the end of the shape list.
Definition: ShapeList.cpp:419
Isis::ShapeList::erase
iterator erase(iterator pos)
Erases a single shape from the shape list.
Definition: ShapeList.cpp:175
QStringList
Isis::ShapeList::XmlHandler
This class is used to read an shapes.xml file into an shape list.
Definition: ShapeList.h:105
Isis::ShapeList::CopyShapeDataFunctor::m_newProjectRoot
FileName m_newProjectRoot
This stores the path to the root of the project that is going to be copied to.
Definition: ShapeList.h:155
Isis::SerialNumberList
Serial Number list generator.
Definition: SerialNumberList.h:64
Isis::XmlStackedHandlerReader
Manage a stack of content handlers for reading XML files.
Definition: XmlStackedHandlerReader.h:30
Isis::Shape::copyToNewProjectRoot
void copyToNewProjectRoot(const Project *project, FileName newProjectRoot)
Copy the cub/ecub files associated with this shape into the new project.
Definition: Shape.cpp:555
Isis::ShapeList::operator=
ShapeList & operator=(const QList< Shape * > &rhs)
Assigns another list of shapes to the shape list.
Definition: ShapeList.cpp:494
Isis::ShapeList::setPath
void setPath(QString newPath)
Set the relative path (from the project root) to this shape list's folder.
Definition: ShapeList.cpp:545
Isis::ShapeList::takeAt
Shape * takeAt(int i)
Removes the shape at an index and returns it.
Definition: ShapeList.cpp:374
Isis::ShapeList::deleteFromDisk
void deleteFromDisk(Project *project)
Delete all of the contained Shapes from disk.
Definition: ShapeList.cpp:578
Isis::Project
The main project for ipce.
Definition: Project.h:289
Isis::ShapeList::m_path
QString m_path
This stores the directory name that contains the shapes in this shape list.
Definition: ShapeList.h:176
Isis::ShapeList::CopyShapeDataFunctor::operator=
CopyShapeDataFunctor & operator=(const CopyShapeDataFunctor &rhs)
Assignment operator for CopyShapeDataFunctor.
Definition: ShapeList.cpp:739
Isis::ShapeList::removeOne
bool removeOne(Shape *const &value)
Removes the first occurance of an shape.
Definition: ShapeList.cpp:338
Isis::ShapeList::serialNumberList
SerialNumberList serialNumberList()
Creates a SerialNumberList from the shape list.
Definition: ShapeList.cpp:115
Isis::FileName::dir
QDir dir() const
Returns the path of the file's parent directory as a QDir object.
Definition: FileName.cpp:465
Isis::ShapeList::removeFirst
void removeFirst()
Removes the shape at the front of the shape list.
Definition: ShapeList.cpp:312
Isis::Project::shapeDataRoot
QString shapeDataRoot() const
Accessor for the root directory of the shape model data.
Definition: Project.cpp:2097
Isis::ShapeList::XmlHandler::XmlHandler
XmlHandler(ShapeList *shapeList, Project *project)
Create an XML Handler (reader) that can populate the Shape list class data.
Definition: ShapeList.cpp:755
Isis::SerialNumberList::add
void add(const QString &filename, bool def2filename=false)
Adds a new filename / serial number pair to the SerialNumberList.
Definition: SerialNumberList.cpp:121
Isis::Shape
This represents a shape in a project-based GUI interface.
Definition: Shape.h:68
Isis::ShapeList::swap
void swap(QList< Shape * > &other)
Swaps the shape list with another list of shapes.
Definition: ShapeList.cpp:356
Isis::ShapeList::push_back
void push_back(Shape *const &value)
Appends an shape to the end of the shape list.
Definition: ShapeList.cpp:254
Isis::ShapeList
Internalizes a list of shapes and allows for operations on the entire list.
Definition: ShapeList.h:33
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::ShapeList::removeAt
void removeAt(int i)
Removes the shape at an index.
Definition: ShapeList.cpp:301
Isis::ShapeList::prepend
void prepend(Shape *const &value)
Inserts an shape at the beginning of the shape list.
Definition: ShapeList.cpp:240
Isis::FileName::toString
QString toString() const
Returns a QString of the full file name including the file path, excluding the attributes with any Is...
Definition: FileName.cpp:515
Isis::ShapeList::save
void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const
Convert this shape list into XML format for saving/restoring capabilities.
Definition: ShapeList.cpp:615
Isis::ShapeList::CopyShapeDataFunctor
This functor is used for copying the shapes between two projects quickly.
Definition: ShapeList.h:137
Isis::ShapeList::name
QString name() const
Get the human-readable name of this shape list.
Definition: ShapeList.cpp:555
Isis::ShapeList::XmlHandler::startElement
virtual bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts)
Handle an XML start element.
Definition: ShapeList.cpp:767
Isis::ShapeList::ShapeList
ShapeList(QString name, QString path, QObject *parent=NULL)
Creates an shape list from an shape list name and path (does not read Shapes).
Definition: ShapeList.cpp:35
Isis::ShapeList::append
void append(Shape *const &value)
Appends an shape to the shape list.
Definition: ShapeList.cpp:133
Isis::Shape::save
void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const
Output format:
Definition: Shape.cpp:844
Isis::ShapeList::m_name
QString m_name
This stores the shape list's name.
Definition: ShapeList.h:164
Isis::ShapeList::XmlHandler::endElement
virtual bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName)
Handle an XML end element.
Definition: ShapeList.cpp:801
QObject
Isis::FileName::original
QString original() const
Returns the full file name including the file path.
Definition: FileName.cpp:212
Isis::ShapeList::removeAll
int removeAll(Shape *const &value)
Removes all occurances of an shape.
Definition: ShapeList.cpp:283
Isis::ShapeList::CopyShapeDataFunctor::m_project
const Project * m_project
This stores the name of the project that is going to be copied to.
Definition: ShapeList.h:151
Isis::ShapeList::removeLast
void removeLast()
Removes the shape at the end of the shape list.
Definition: ShapeList.cpp:323
Isis::FileName::path
QString path() const
Returns the path of the file name.
Definition: FileName.cpp:103
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::ShapeList::path
QString path() const
Get the path to the shapes in the shape list (relative to project root).
Definition: ShapeList.cpp:566