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
27namespace Isis {
35 ShapeList::ShapeList(QString name, QString path, QObject *parent) : QObject(parent) {
36 m_name = name;
37 m_path = path;
38 }
39
40
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
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) {
135 emit countChanged(count());
136 }
137
138
146 void ShapeList::append(const QList<Shape *> &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
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
356 void ShapeList::swap(QList<Shape *> &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
390 emit countChanged(count());
391 return result;
392 }
393
394
404 emit countChanged(count());
405 return result;
406 }
407
408
419 ShapeList &ShapeList::operator+=(const QList<Shape *> &other) {
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
457 ShapeList &ShapeList::operator<<(const QList<Shape *> &other) {
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
494 ShapeList &ShapeList::operator=(const QList<Shape *> &rhs) {
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
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}
File name manipulation and expansion.
Definition FileName.h:100
QString path() const
Returns the path of the file name.
Definition FileName.cpp:103
QDir dir() const
Returns the path of the file's parent directory as a QDir object.
Definition FileName.cpp:465
QString original() const
Returns the full file name including the file path.
Definition FileName.cpp:212
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 exception class.
Definition IException.h:91
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition IException.h:155
The main project for ipce.
Definition Project.h:289
static QString shapeDataRoot(QString projectRoot)
Appends the root directory name 'shapes' to the project .
Definition Project.cpp:2086
QString shapeDataRoot() const
Accessor for the root directory of the shape model data.
Definition Project.cpp:2096
Serial Number list generator.
void add(const QString &filename, bool def2filename=false)
Adds a new filename / serial number pair to the SerialNumberList.
This represents a shape in a project-based GUI interface.
Definition Shape.h:68
void deleteFromDisk()
Delete the shape data from disk.
Definition Shape.cpp:591
void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const
Output format:
Definition Shape.cpp:844
This functor is used for copying the shapes between two projects quickly.
Definition ShapeList.h:137
CopyShapeDataFunctor(const Project *project, FileName newProjectRoot)
Constructor for CopyShapeDataFunctor.
CopyShapeDataFunctor & operator=(const CopyShapeDataFunctor &rhs)
Assignment operator for CopyShapeDataFunctor.
FileName m_newProjectRoot
This stores the path to the root of the project that is going to be copied to.
Definition ShapeList.h:155
void * operator()(Shape *const &shapeToCopy)
Copies the cub/ecub files for an shape into m_project.
~CopyShapeDataFunctor()
Destructor for CopyShapeDataFunctor.
const Project * m_project
This stores the name of the project that is going to be copied to.
Definition ShapeList.h:151
This class is used to read an shapes.xml file into an shape list.
Definition ShapeList.h:105
virtual bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName)
Handle an XML end element.
virtual bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts)
Handle an XML start element.
XmlHandler(ShapeList *shapeList, Project *project)
Create an XML Handler (reader) that can populate the Shape list class data.
Internalizes a list of shapes and allows for operations on the entire list.
Definition ShapeList.h:33
void insert(int i, Shape *const &value)
Inserts an shape into the shape list at an index.
void append(Shape *const &value)
Appends an shape to the shape list.
void deleteFromDisk(Project *project)
Delete all of the contained Shapes from disk.
void removeAt(int i)
Removes the shape at an index.
void setName(QString newName)
Set the human-readable name of this shape list.
Shape * takeLast()
Removes and returns the last shape.
iterator erase(iterator pos)
Erases a single shape from the shape list.
SerialNumberList serialNumberList()
Creates a SerialNumberList from the shape list.
void swap(QList< Shape * > &other)
Swaps the shape list with another list of shapes.
QString m_name
This stores the shape list's name.
Definition ShapeList.h:164
void clear()
Clears the shape list.
QString m_path
This stores the directory name that contains the shapes in this shape list.
Definition ShapeList.h:176
void push_back(Shape *const &value)
Appends an shape to the end of the shape list.
void removeFirst()
Removes the shape at the front of the shape list.
void removeLast()
Removes the shape at the end of the shape list.
QString path() const
Get the path to the shapes in the shape list (relative to project root).
int removeAll(Shape *const &value)
Removes all occurances of an shape.
QString name() const
Get the human-readable name of this shape list.
void prepend(Shape *const &value)
Inserts an shape at the beginning of the shape list.
Shape * takeAt(int i)
Removes the shape at an index and returns it.
void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const
Convert this shape list into XML format for saving/restoring capabilities.
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
void push_front(Shape *const &value)
Prepends an shape to the beginning of the shape list.
ShapeList & operator<<(const QList< Shape * > &other)
Appends a list of shapes to the end of the shape list.
~ShapeList()
Destructor.
bool removeOne(Shape *const &value)
Removes the first occurance of an shape.
ShapeList & operator=(const QList< Shape * > &rhs)
Assigns another list of shapes to the shape list.
void setPath(QString newPath)
Set the relative path (from the project root) to this shape list's folder.
Shape * takeFirst()
Removes and returns the first shape.
ShapeList & operator+=(const QList< Shape * > &other)
Appends a list of shapes to the end of the shape list.
Manage a stack of content handlers for reading XML files.
virtual void pushContentHandler(XmlStackedHandler *newHandler)
Push a contentHandler and maybe continue parsing...
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16