Isis 3 Programmer Reference
WorkOrder.cpp
1
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include "WorkOrder.h"
10
11#include <QDebug>
12#include <QFutureWatcher>
13#include <QMutex>
14#include <QMutexLocker>
15#include <QtConcurrentRun>
16#include <QTimer>
17#include <QXmlStreamWriter>
18
19#include "ControlList.h"
20#include "IException.h"
21#include "ImageList.h"
22#include "IString.h"
23#include "ProgressBar.h"
24#include "Project.h"
25#include "ProjectItem.h"
26#include "ShapeList.h"
27#include "Template.h"
28#include "XmlStackedHandlerReader.h"
29
30
31namespace Isis {
39 WorkOrder::WorkOrder(Project *project) : QAction(project) {
41
42 m_context = NoContext;
43 m_data = "";
44 m_imageList = new ImageList;
45 m_shapeList = new ShapeList;
46 m_controlList = NULL;
47 m_correlationMatrix = CorrelationMatrix();
50 m_template = NULL;
52
53 m_isUndoable = true;
54 m_isSavedToHistory = true;
55 m_isSynchronous = true;
56
57 m_createsCleanState = false;
58 m_modifiesDiskState = false;
59 m_status = WorkOrderNotStarted;
60 m_queuedAction = NoQueuedAction;
62 m_elapsedTimer = NULL;
63
64 m_futureWatcher = new QFutureWatcher<void>;
65 m_transparentConstMutex = new QMutex;
66
70
71 m_secondsElapsed = 0.0;
72
73 if (!m_project) {
75 tr("Work orders cannot be created without a project."), _FILEINFO_);
76 }
77
78 connect(this, SIGNAL(triggered()),
79 this, SLOT(addCloneToProject()));
80 connect(m_futureWatcher, SIGNAL(finished()),
81 this, SLOT(executionFinished()));
82 }
83
84
92 QAction(other.icon(), ((QAction &)other).text(), other.parentWidget()),
93 QUndoCommand(((QUndoCommand &)other).text()) {
94 // Copy the action's what's this and tool tip (hover text).
95 QAction::setWhatsThis(other.whatsThis());
96 QAction::setToolTip(other.toolTip());
97
99 m_elapsedTimer = NULL;
100 m_project = other.project();
101 m_context = other.m_context;
102 m_imageIds = other.m_imageIds;
103 m_imageList = new ImageList(*other.m_imageList);
104 m_shapeIds = other.m_shapeIds;
105 m_shapeList = new ShapeList(*other.m_shapeList);
106 m_correlationMatrix = other.m_correlationMatrix;
107 m_controlList = other.m_controlList;
108 m_guiCamera = other.m_guiCamera;
109 m_targetBody = other.m_targetBody;
110 m_fileItem = other.m_fileItem;
111 m_internalData = other.m_internalData;
112 m_template = other.m_template;
113
114 m_isUndoable = other.m_isUndoable;
115 m_isSavedToHistory = other.m_isSavedToHistory;
116 m_isSynchronous = other.m_isSynchronous;
117
118 m_createsCleanState = other.m_createsCleanState;
119 m_modifiesDiskState = other.m_modifiesDiskState;
120
121 m_executionTime = other.m_executionTime;
122
123 m_status = other.m_status;
124 m_queuedAction = other.m_queuedAction;
125
126 m_secondsElapsed = other.m_secondsElapsed;
127
128 m_progressRangeMinValue = other.m_progressRangeMinValue;
129 m_progressRangeMaxValue = other.m_progressRangeMaxValue;
130 m_progressValue = other.m_progressValue;
131
132 m_futureWatcher = new QFutureWatcher<void>;
133 m_transparentConstMutex = new QMutex;
134
135 if (!other.isInStableState()) {
137 tr("Can not copy work order [%1] because it is currently running")
138 .arg(((QUndoCommand &)other).text()),
139 _FILEINFO_);
140 }
141
142 connect(this, SIGNAL(triggered()),
143 this, SLOT(addCloneToProject()));
144 connect(m_futureWatcher, SIGNAL(finished()),
145 this, SLOT(executionFinished()));
146
149 }
150
151
156
157 delete m_imageList;
158 delete m_shapeList;
159 delete m_futureWatcher;
163
164 m_nextWorkOrder = NULL;
165 m_previousWorkOrder = NULL;
166 m_project = NULL;
168 }
169
170
181 return false;
182 }
183
184
195 return false;
196 }
197
198
209 return false;
210 }
211
212
220//bool WorkOrder::isExecutable(Control *control) {
221// return false;
222//}
223
224
233 return false;
234 }
235
236
237 bool WorkOrder::isExecutable(CorrelationMatrix correlationMatrix) {
238 return false;
239 }
240
241
247 m_context = context;
248 }
249
250 void WorkOrder::setData(QString data) {
251 m_data = data;
252 }
253
254
260 m_imageIds.clear();
261 delete m_imageList;
262
263 m_imageList = new ImageList(*images);
265 }
266
267
273 m_shapeIds.clear();
274 delete m_shapeList;
275
276 m_shapeList = new ShapeList(*shapes);
278 }
279
280
285//void WorkOrder::setData(Control *control) {
286// m_control = control;
287//}
288
289
296 m_controlList = controls;
297 }
298
299
304 void WorkOrder::setData(CorrelationMatrix correlationMatrix) {
305 m_correlationMatrix = correlationMatrix;
306 }
307
308
309
310
318
319
324 void WorkOrder::setData(Template *currentTemplate) {
325 m_template = currentTemplate;
326 }
327
328
335 }
336
337
344 }
345
346
352 if ( item->isProject() ) {
353 setData( ProjectContext );
354 }
355 else if ( item->isImageList() ) {
356 setData( item->imageList() );
357 }
358 else if ( item->isImage() ) {
359 ImageList *imageList = new ImageList(this);
360 imageList->append( item->image() );
362 }
363 else if ( item->isShapeList() ) {
364 setData( item->shapeList() );
365 }
366 else if ( item->isShape() ) {
367 ShapeList *shapeList = new ShapeList(this);
368 shapeList->append( item->shape() );
370 }
371 else if (item->isControlList()) {
372 setData( item->controlList() );
373 }
374 else if ( item->isControl() ) {
376 controlList->append( item->control() );
378// //setData(*controlList);
379 }
380 else if ( item->isCorrelationMatrix() ) {
381 setData( item->correlationMatrix() );
382 }
383 else if ( item->isTargetBody() ) {
384 setData( item->targetBody() );
385 }
386 else if ( item->isGuiCamera() ) {
387 setData( item->guiCamera() );
388 }
389 else if ( item->isFileItem() ) {
390 setData( item->fileItem() );
391 }
392 else if ( item->isTemplate() ) {
393 setData( item->getTemplate() );
394 }
395 }
396
397
398
399
400
409 return false;
410 }
411
412
420 bool WorkOrder::isExecutable(Template *currentTemplate) {
421 return false;
422 }
423
424
433 return false;
434 }
435
436
445 return false;
446 }
447
448
457 if ( !item ) {
458 return false;
459 }
460 else if ( item->isProject() ) {
461 return isExecutable( ProjectContext );
462 }
463 else if ( item->isImageList() ) {
464 return isExecutable( item->imageList() );
465 }
466 else if ( item->isImage() ) {
468 imageList->append( item->image() );
469 bool ret = isExecutable(imageList);
470 imageList->deleteLater();
471 return ret;
472 }
473 else if ( item->isShapeList() ) {
474 return isExecutable( item->shapeList() );
475 }
476 else if ( item->isShape() ) {
478 shapeList->append( item->shape() );
479 bool ret = isExecutable(shapeList);
480 shapeList->deleteLater();
481 return ret;
482 }
483 else if ( item->isControlList() ) {
484 return isExecutable (item -> controlList() );
485 }
486 else if ( item->isControl() ) {
488 controlList->append( item->control() );
489 bool ret = isExecutable(controlList);
490 controlList->deleteLater();
491 return ret;
492 }
493 else if ( item->isCorrelationMatrix() ) {
494 return isExecutable( item->correlationMatrix() );
495 }
496 else if ( item->isTargetBody() ) {
497 //return isExecutable( item->targetBody() ) || isExecutable( item->targetBody().data() );
498 return isExecutable(item->targetBody());
499 }
500 else if ( item->isGuiCamera() ) {
501 //return isExecutable( item->guiCamera() ) || isExecutable( item->guiCamera().data() );
502 return isExecutable( item->guiCamera() );
503 }
504 else if ( item->isFileItem() ) {
505 return isExecutable( item->fileItem() );
506 }
507 else if ( item->isTemplate() ) {
508 return isExecutable( item->getTemplate() );
509 }
510
511 return false;
512 }
513
514
519 xmlReader->pushContentHandler(new XmlHandler(this));
520 }
521
522
542 void WorkOrder::save(QXmlStreamWriter &stream) const {
543 if (!isInStableState()) {
545 tr("Can not store an unstable work order. The work order [%1] is currently "
546 "working").arg(bestText()),
547 _FILEINFO_);
548 }
549
550 stream.writeStartElement("workOrder");
551
552 stream.writeAttribute("actionText", QAction::text());
553 stream.writeAttribute("undoText", QUndoCommand::text());
554 stream.writeAttribute("executionTime", m_executionTime.toString());
555 stream.writeAttribute("type", metaObject()->className());
556 stream.writeAttribute("status", toString(m_status));
557
558 if (m_imageIds.count()) {
559 stream.writeStartElement("images");
560
561 foreach (QString imageId, m_imageIds) {
562 stream.writeStartElement("image");
563 stream.writeAttribute("id", imageId);
564 stream.writeEndElement();
565 }
566
567 stream.writeEndElement();
568 }
569
570 if (m_shapeIds.count()) {
571 stream.writeStartElement("shapes");
572
573 foreach (QString shapeId, m_shapeIds) {
574 stream.writeStartElement("shape");
575 stream.writeAttribute("id", shapeId);
576 stream.writeEndElement();
577 }
578
579 stream.writeEndElement();
580 }
581
582 if (m_internalData.count()) {
583 stream.writeStartElement("internalDataValues");
584
585 foreach (QString str, m_internalData) {
586 stream.writeStartElement("dataValue");
587 stream.writeAttribute("value", str);
588 stream.writeEndElement();
589 }
590
591 stream.writeEndElement();
592 }
593
594 if (m_context != NoContext) {
595 stream.writeStartElement("context");
596
597 QString contextStr = "ProjectContext";
598 stream.writeAttribute("value", contextStr);
599
600 stream.writeEndElement();
601 }
602
603 stream.writeEndElement();
604 }
605
606
611 void WorkOrder::setNext(WorkOrder *nextWorkOrder) {
612 m_nextWorkOrder = nextWorkOrder;
613 }
614
615
620 void WorkOrder::setPrevious(WorkOrder *previousWorkOrder) {
621 m_previousWorkOrder = previousWorkOrder;
622 }
623
624
630 QMutexLocker locker(project()->workOrderMutex());
631 if (!m_imageList) {
632 bool anyImagesAreNull = false;
633
634 m_imageList = new ImageList;
635
636 foreach (QString id, m_imageIds) {
637 Image *image = project()->image(id);
638 m_imageList->append(image);
639
640 if (!image) {
641 anyImagesAreNull = true;
642 }
643 }
644
645 if (anyImagesAreNull) {
646 delete m_imageList;
647 }
648 else {
650 }
651 }
652
653 return m_imageList;
654 }
655
656
662 QMutexLocker locker(project()->workOrderMutex());
663 if (!m_shapeList) {
664 bool anyShapesAreNull = false;
665
666 m_shapeList = new ShapeList;
667
668 foreach (QString id, m_shapeIds) {
669 Shape *shape = project()->shape(id);
670 m_shapeList->append(shape);
671
672 if (!shape) {
673 anyShapesAreNull = true;
674 }
675 }
676
677 if (anyShapesAreNull) {
678 delete m_shapeList;
679 }
680 else {
682 }
683 }
684
685 return
686 m_shapeList;
687 }
688
689
695 QMutexLocker locker(project()->workOrderMutex());
696 return m_correlationMatrix;
697 }
698
699
704 QPointer<ControlList> WorkOrder::controlList() {
705 QMutexLocker locker(project()->workOrderMutex());
706 return m_controlList;
707 }
708
709
715 QMutexLocker lock(m_transparentConstMutex);
716 return const_cast<WorkOrder *>(this)->imageList();
717 }
718
719
725 QMutexLocker lock(m_transparentConstMutex);
726 return const_cast<WorkOrder *>(this)->shapeList();
727 }
728
729
735 QMutexLocker locker(project()->workOrderMutex());
736 return m_template;
737 }
738
739
745 QMutexLocker locker(project()->workOrderMutex());
746 return m_targetBody;
747 }
748
749
755 QMutexLocker locker(project()->workOrderMutex());
756 return m_guiCamera;
757 }
758
759
765 QMutexLocker locker(project()->workOrderMutex());
766 return m_fileItem;
767 }
768
769
780 return true;
781 }
782
783
793 QString WorkOrder::bestText() const {
794 QString result = QUndoCommand::text().remove("&").remove("...");
795
796 // if the QUndoCommand has no text, create a warning
797 if (result.isEmpty()) {
798 // get the name of the work order
799 result = QString(metaObject()->className()).remove("Isis::").remove("WorkOrder")
800 .replace(QRegExp("([a-z0-9])([A-Z])"), "\\1 \\2");
801 qWarning() << QString("WorkOrder::bestText(): Work order [%1] has no QUndoCommand text")
802 .arg(result);
803 }
804
805 return result;
806 }
807
808
818 QMutexLocker locker(project()->workOrderMutex());
819 return m_isUndoable;
820 }
821
822
829 QMutexLocker locker(project()->workOrderMutex());
830 return m_isSavedToHistory;
831 }
832
833
840 QMutexLocker locker(project()->workOrderMutex());
841 return m_isSynchronous;
842 }
843
844
853 QMutexLocker locker(project()->workOrderMutex());
854 return m_createsCleanState;
855 }
856
857
862 QDateTime WorkOrder::executionTime() const {
863 QMutexLocker locker(project()->workOrderMutex());
864 return m_executionTime;
865 }
866
867
873 return m_status == WorkOrderFinished;
874 }
875
876
881 bool WorkOrder::isRedoing() const {
882 QMutexLocker locker(project()->workOrderMutex());
883 return m_status == WorkOrderRedoing;
884 }
885
886
891 bool WorkOrder::isRedone() const {
892 QMutexLocker locker(project()->workOrderMutex());
893 return m_status == WorkOrderRedone;
894 }
895
896
901 bool WorkOrder::isUndoing() const {
902 QMutexLocker locker(project()->workOrderMutex());
903 return m_status == WorkOrderUndoing;
904 }
905
906
911 bool WorkOrder::isUndone() const {
912 QMutexLocker locker(project()->workOrderMutex());
913 return m_status == WorkOrderUndone;
914 }
915
916
923 QMutexLocker locker(project()->workOrderMutex());
924 return m_modifiesDiskState;
925 }
926
927
933 QMutexLocker locker(project()->workOrderMutex());
934 return m_nextWorkOrder;
935 }
936
937
943 QMutexLocker locker(project()->workOrderMutex());
944 return m_previousWorkOrder;
945 }
946
947
952 QString WorkOrder::statusText() const {
953 QMutexLocker locker(project()->workOrderMutex());
954 QString result = toString(m_status);
955
956 if (m_secondsElapsed) {
957 // QTime can't format in the way that I want (0-n minutes, 00-59 seconds, no hours
958 // displayed)... so do it manually.
959 // Expected output format examples: 0:01, 0:55, 1:30, 55:55, 90:00, 100:12
960 int seconds = qRound(m_secondsElapsed) % 60;
961 int minutes = qRound(m_secondsElapsed) / 60;
962 result += tr(" (elapsed: %1:%2)").arg(minutes).arg(seconds, 2, 10, QChar('0'));
963 }
964
965 return result;
966 }
967
968
974 QMutexLocker locker(project()->workOrderMutex());
975 return m_progressBar;
976 }
977
978
987 statusString = statusString.toUpper();
988 WorkOrderStatus result = WorkOrderUnknownStatus;
989
990 for (WorkOrderStatus possibleResult = WorkOrderUnknownStatus;
991 possibleResult <= WorkOrderLastStatus;
992 possibleResult = (WorkOrderStatus)(possibleResult + 1)) {
993 if (statusString == toString(possibleResult).toUpper()) {
994 result = possibleResult;
995 }
996 }
997
998 return result;
999 }
1000
1001
1008 QString result;
1009
1010 switch (status) {
1011 case WorkOrderUnknownStatus:
1012 result = tr("Unknown");
1013 break;
1014 case WorkOrderNotStarted:
1015 result = tr("Not Started");
1016 break;
1017 case WorkOrderRedoing:
1018 result = tr("In Progress");
1019 break;
1020 case WorkOrderRedone:
1021 result = tr("Completed");
1022 break;
1023 case WorkOrderUndoing:
1024 result = tr("Undoing");
1025 break;
1026 case WorkOrderUndone:
1027 result = tr("Undone");
1028 break;
1029 case WorkOrderFinished:
1030 result = tr("Finished");
1031 break;
1032 }
1033
1034 return result;
1035 }
1036
1037
1042 if (!isInStableState()) {
1043 m_queuedAction = RedoQueuedAction;
1044 }
1045
1046 if (!isRedone()) {
1047 bool mustQueueThisRedo = false;
1048
1049 WorkOrder *dependency = NULL;
1050 WorkOrder *current = this;
1051 while (current->previous() && !dependency) {
1052 if (!current->previous()->isRedone() && !current->previous()->isFinished()) {
1053 WorkOrder *possibleDependency = current->previous();
1054
1055 if (dependsOn(possibleDependency)) {
1056 connect(possibleDependency, SIGNAL(finished(WorkOrder *)),
1057 this, SLOT(attemptQueuedAction()));
1058 dependency = possibleDependency;
1059 mustQueueThisRedo = true;
1060 }
1061 }
1062
1063 current = current->previous();
1064 }
1065
1066 if (!imageList()) {
1067 connect(project(), SIGNAL(imagesAdded(ImageList *)),
1068 this, SLOT(attemptQueuedAction()));
1069 mustQueueThisRedo = true;
1070 }
1071
1072 if (!shapeList()) {
1073 connect(project(), SIGNAL(shapesAdded(ShapeList *)),
1074 this, SLOT(attemptQueuedAction()));
1075 mustQueueThisRedo = true;
1076 }
1077
1078 if (mustQueueThisRedo && !isUndoing() && !isRedoing()) {
1079
1080 m_queuedAction = RedoQueuedAction;
1081
1082 QString queueStatusText;
1083
1084 if (dependency) {
1085 QString dependencyText = dependency->bestText();
1086
1087 if (dependencyText.count() > 5) {
1088 dependencyText = dependencyText.mid(0, 5) + "...";
1089 }
1090
1091 queueStatusText = tr("Wait for [%1]").arg(dependencyText);
1092 }
1093 else if (!imageList()) {
1094 queueStatusText = tr("Wait for images");
1095 }
1096 else if (!shapeList()) {
1097 queueStatusText = tr("Wait for shapes");
1098 }
1099
1101 m_progressBar->setValue(m_progressBar->minimum());
1102 m_progressBar->setText(queueStatusText);
1103 m_progressBar->update();
1104 }
1105
1106 if (m_queuedAction == NoQueuedAction) {
1107 m_status = WorkOrderRedoing;
1108 emit statusChanged(this);
1109
1111 m_progressBar->setText("Starting...");
1112 m_progressBar->update();
1113
1114 delete m_elapsedTimer;
1115 m_elapsedTimer = new QTime;
1116 m_elapsedTimer->start();
1117
1118 if (isSynchronous()) {
1119 execute();
1121 }
1122 else {
1123 m_progressBar->setText("Running...");
1124 m_progressBar->update();
1125 // queue the workorder for asynchronous execution
1126 QFuture<void> future = QtConcurrent::run(this, &WorkOrder::execute);
1127 // executionFinished() is called via the finished signal. The
1128 // connection is setup in the constructor.
1129 m_futureWatcher->setFuture(future);
1130 }
1131 }
1132 }
1133 else {
1135 }
1136 }
1137
1138
1145 if (!isInStableState()) {
1146 m_queuedAction = UndoQueuedAction;
1147 }
1148
1149 if (!isUndone() && m_status != WorkOrderNotStarted) {
1150 WorkOrder *dependency = NULL;
1151 WorkOrder *current = this;
1152 while (current->next() && !dependency) {
1153 if (!current->next()->isUndone() && !current->next()->isFinished() &&
1154 current->next()->m_status != WorkOrderNotStarted) {
1155 connect(current->next(), SIGNAL(finished(WorkOrder *)),
1156 this, SLOT(attemptQueuedAction()));
1157 m_queuedAction = UndoQueuedAction;
1158 dependency = current->next();
1159 }
1160
1161 current = current->next();
1162 }
1163
1164 if (dependency && !isUndoing() && !isRedoing()) {
1165 QString prevText = dependency->bestText();
1166
1167 if (prevText.count() > 5) {
1168 prevText = prevText.mid(0, 5) + "...";
1169 }
1170
1172 m_progressBar->setValue(m_progressBar->minimum());
1173 m_progressBar->setText(tr("Undo after [%1]").arg(prevText));
1174 m_progressBar->update();
1175 }
1176
1177 if (m_queuedAction == NoQueuedAction) {
1178 m_status = WorkOrderUndoing;
1179 emit statusChanged(this);
1180
1182 m_progressBar->setText("Starting Undo...");
1183 m_progressBar->update();
1184
1185 delete m_elapsedTimer;
1186 m_elapsedTimer = new QTime;
1187 m_elapsedTimer->start();
1188
1189 if (isSynchronous()) {
1190 undoExecution();
1192 }
1193 else {
1194 m_progressBar->setText("Undoing...");
1195 m_progressBar->update();
1196 // queue the workorder for asynchronous execution
1197 QFuture<void> future = QtConcurrent::run(this, &WorkOrder::undoExecution);
1198 // executionFinished() is called via the finished signal. The
1199 // connection is setup in the constructor.
1200 m_futureWatcher->setFuture(future);
1201 }
1202 }
1203 }
1204 else {
1206 }
1207 }
1208
1217 setEnabled(true);
1218 }
1219
1220
1229 setEnabled(false);
1230 }
1231
1232
1260 // We're finished at this point if we save/open a project, we're not finished if we need to do
1261 // redo()
1262 if (createsCleanState() || !isUndoable()) {
1263 m_status = WorkOrderFinished;
1264
1265 emit statusChanged(this);
1266 }
1267
1268 m_executionTime = QDateTime::currentDateTime();
1269
1271
1272 if (createsCleanState() || !isUndoable()) {
1274 }
1275 else {
1276 m_progressBar->setText("Initializing...");
1277 }
1278
1279 return true;
1280 }
1281
1282
1289 return project()->directory();
1290 }
1291
1292
1299 if (!m_project) {
1301 "This work order no longer has a project.", _FILEINFO_);
1302 }
1303
1304 return m_project;
1305 }
1306
1307
1319
1320
1326 QMutexLocker locker(project()->workOrderMutex());
1328 }
1329
1330
1336 QMutexLocker locker(project()->workOrderMutex());
1338 }
1339
1340
1346 QMutexLocker locker(project()->workOrderMutex());
1347 return m_progressValue;
1348 }
1349
1350
1356 void WorkOrder::setProgressRange(int minValue, int maxValue) {
1357 m_progressRangeMinValue = minValue;
1358 m_progressRangeMaxValue = maxValue;
1359 }
1360
1361
1367 m_progressValue = value;
1368 }
1369
1370
1376 QMutexLocker locker(project()->workOrderMutex());
1377 return m_internalData;
1378 }
1379
1380
1402 }
1403
1404
1414
1415
1434
1435
1445
1446
1451 if (project()) {
1452 project()->addToProject(clone());
1453 }
1454 }
1455
1456
1462 bool result = true;
1463
1464 if (isRedoing() || isUndoing() || m_queuedAction != NoQueuedAction) {
1465 result = false;
1466 }
1467
1468 return result;
1469 }
1470
1471
1478 m_imageIds.clear();
1479 foreach (Image *image, *m_imageList) {
1480 if (image) {
1481 m_imageIds.append(image->id());
1482
1483 // If we lose any images, destroy the entire list. This will let us know that we need to
1484 // rebuild it, if needed, when requested.
1485 connect(image, SIGNAL(destroyed(QObject *)),
1486 this, SLOT(clearImageList()));
1487 }
1488 }
1489 }
1490
1491
1501 m_shapeIds.clear();
1502 foreach (Shape *shape, *m_shapeList) {
1503 if (shape) {
1504 m_shapeIds.append(shape->id());
1505
1506 // If we lose any shapes, destroy the entire list. This will let us know that we need to
1507 // rebuild it, if needed, when requested.
1508 connect(shape, SIGNAL(destroyed(QObject *)),
1509 this, SLOT(clearShapeList()));
1510 }
1511 }
1512 }
1513
1514
1520
1521 if (!m_progressBar) {
1523 emit creatingProgress(this);
1524 }
1525
1527 m_progressBarUpdateTimer = new QTimer;
1528 connect(m_progressBarUpdateTimer, SIGNAL(timeout()),
1529 this, SLOT(updateProgress()));
1530 m_progressBarUpdateTimer->start(100);
1531 }
1532
1535 m_progressValue = 0;
1536 }
1537
1538
1543 if (m_progressBar) {
1544 if (isRedone()) {
1545 m_progressBar->setText(tr("Finished"));
1546 }
1547 else if (isUndone() || m_status == WorkOrderNotStarted) {
1548 m_progressBar->setText(tr("Undone"));
1549 }
1550
1551 if (m_progressBar->minimum() != 0 || m_progressBar->maximum() != 0) {
1552 m_progressBar->setValue(m_progressBar->maximum());
1553 }
1554 else {
1555 m_progressBar->setRange(0, 100);
1556 m_progressBar->setValue(100);
1557 }
1558
1560 m_progressBarDeletionTimer = new QTimer;
1561 m_progressBarDeletionTimer->setSingleShot(true);
1562
1563 m_progressBarDeletionTimer->start(5 * 1000); // 5 seconds
1564
1565 m_progressBar->update();
1566 }
1567 }
1568
1569
1574 QueuedWorkOrderAction queued = m_queuedAction;
1575 m_queuedAction = NoQueuedAction;
1576
1577 if (queued == RedoQueuedAction && m_status != WorkOrderRedone) {
1578 redo();
1579 }
1580 else if (queued == UndoQueuedAction && m_status != WorkOrderUndone) {
1581 undo();
1582 }
1583 }
1584
1585
1592
1593 WorkOrderStatus finishedStatus = WorkOrderRedone;
1594 void (WorkOrder::*postMethod)() = &WorkOrder::postExecution;
1595
1596 if (isUndoing()) {
1597 finishedStatus = WorkOrderUndone;
1598 postMethod = &WorkOrder::postUndoExecution;
1599 }
1600
1601 (this->*postMethod)();
1602
1603 m_status = finishedStatus;
1604
1605 m_secondsElapsed = m_elapsedTimer->elapsed() / 1000.0;
1606
1607 delete m_elapsedTimer;
1608 m_elapsedTimer = NULL;
1609
1610 emit statusChanged(this);
1612 emit finished(this);
1613
1615 }
1616
1617
1622 delete m_imageList;
1623 }
1624
1625
1630 delete m_shapeList;
1631 }
1632
1633
1643
1644
1649 }
1650
1651
1661 void WorkOrder::setCreatesCleanState(bool createsCleanState) {
1663 }
1664
1665
1672 void WorkOrder::setModifiesDiskState(bool changesProjectOnDisk) {
1673 m_modifiesDiskState = changesProjectOnDisk;
1674 }
1675
1676
1682 m_workOrder = workOrder;
1683 }
1684
1685
1700 bool WorkOrder::XmlHandler::startElement(const QString &namespaceURI, const QString &localName,
1701 const QString &qName, const QXmlAttributes &atts) {
1702 if (XmlStackedHandler::startElement(namespaceURI, localName, qName, atts)) {
1703 if (localName == "workOrder") {
1704 QString actionText = atts.value("actionText");
1705 QString undoText = atts.value("undoText");
1706 QString executionTime = atts.value("executionTime");
1707 QString statusStr = atts.value("status");
1708
1709 if (!actionText.isEmpty()) {
1710 ((QAction *)m_workOrder)->setText(actionText);
1711 }
1712
1713 if (!undoText.isEmpty()) {
1714 ((QUndoCommand *)m_workOrder)->setText(undoText);
1715 }
1716
1717 if (!executionTime.isEmpty()) {
1718 m_workOrder->m_executionTime = QDateTime::fromString(executionTime);
1719 }
1720
1721 if (!statusStr.isEmpty()) {
1722 m_workOrder->m_status = fromStatusString(statusStr);
1723 }
1724 else {
1725 if (m_workOrder->createsCleanState()) {
1726 m_workOrder->m_status = WorkOrderFinished;
1727 }
1728 else {
1729 m_workOrder->m_status = WorkOrderRedone;
1730 }
1731 }
1732 }
1733 else if (localName == "dataValue") {
1734 m_workOrder->m_internalData.append(atts.value("value"));
1735 }
1736 else if (localName == "context") {
1737 if (atts.value("value") == "ProjectContext") {
1738 m_workOrder->m_context = ProjectContext;
1739 }
1740 }
1741 }
1742
1743 return true;
1744 }
1745}
Maintains a list of Controls so that control nets can easily be copied from one Project to another,...
Definition ControlList.h:44
This is a container for the correlation matrix that comes from a bundle adjust.
Isis exception class.
Definition IException.h:91
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
This represents a cube in a project-based GUI interface.
Definition Image.h:107
QString id() const
Get a unique, identifying string associated with this image.
Definition Image.cpp:445
Internalizes a list of images and allows for operations on the entire list.
Definition ImageList.h:55
void append(Image *const &value)
Appends an image to the image list.
The main project for ipce.
Definition Project.h:289
Shape * shape(QString id)
Return a shape given its id.
Definition Project.cpp:1538
void addToProject(WorkOrder *)
This executes the WorkOrder and stores it in the project.
Definition Project.cpp:2597
Directory * directory() const
Returns the directory associated with this Project.
Definition Project.cpp:1228
Image * image(QString id)
Return an image given its id.
Definition Project.cpp:1508
Represents an item of a ProjectItemModel in Qt's model-view framework.
TargetBodyQsp targetBody() const
Returns the TargetBodyQsp stored in the data of the item.
bool isShape() const
Returns true if an Shape is stored in the data of the item.
Template * getTemplate() const
Returns the Template stored in the data of the item.
bool isProject() const
Returns true if a Project is stored in the data of the item.
FileItemQsp fileItem() const
Returns the FileItemQsp stored in the data of the item.
ShapeList * shapeList() const
Returns the ShapeList stored in the data of the item.
bool isControl() const
Returns true if a Control is stored in the data of the item.
bool isControlList() const
Returns true if a ControlList is stored in the data of the item.
bool isShapeList() const
Returns true if an ShapeList is stored in the data of the item.
CorrelationMatrix correlationMatrix() const
Returns the CorrelationMatrix stored the item.
Shape * shape() const
Returns the Shape stored in the data of the item.
bool isImageList() const
Returns true if an ImageList is stored in the data of the item.
ImageList * imageList() const
Returns the ImageList stored in the data of the item.
bool isFileItem() const
Returns true if a FileItemQsp is stored in the data of the item.
Control * control() const
Returns the Control stored in the data of the item.
Image * image() const
Returns the Image stored in the data of the item.
ControlList * controlList() const
Returns the ControlList stored in the data of the item.
bool isImage() const
Returns true if an Image is stored in the data of the item.
GuiCameraQsp guiCamera() const
Returns the GuiCameraQsp stored in the data of the item.
bool isGuiCamera() const
Returns true if a GuiCameraQsp is stored in the data of the item.
bool isCorrelationMatrix() const
Returns true if a CorrelationMatrix is stored in the data of the item.
bool isTargetBody() const
Returns true if a TargetBodyQsp is stored in the data of the item.
This represents a shape in a project-based GUI interface.
Definition Shape.h:68
QString id() const
Get a unique, identifying string associated with this shape.
Definition Shape.cpp:459
Internalizes a list of shapes and allows for operations on the entire list.
Definition ShapeList.h:33
void append(Shape *const &value)
Appends an shape to the shape list.
This class is used for processing an XML file containing information about a WorkOrder.
Definition WorkOrder.h:497
virtual bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts)
The XML reader invokes this method at the start of every element in the XML document.
XmlHandler(WorkOrder *workOrder)
Passes a pointer to a WorkOrder to the WorkOrder::XmlHandler class.
WorkOrder * m_workOrder
This is a pointer to the WorkOrder the XmlHandler is filling with information it parses from an XML f...
Definition WorkOrder.h:511
Provide Undo/redo abilities, serialization, and history for an operation.
Definition WorkOrder.h:311
QTime * m_elapsedTimer
A QTime object holding the excecution time of the WorkOrder.
Definition WorkOrder.h:677
void enableWorkOrder()
Enables the work order.
QPointer< QTimer > m_progressBarUpdateTimer
A pointer to the QTimer which updates the ProgressBar.
Definition WorkOrder.h:666
QStringList m_imageIds
A QStringList of unique image identifiers for all of the images this WorkOrder is dealing with.
Definition WorkOrder.h:610
void setNext(WorkOrder *nextWorkOrder)
Sets the next WorkOrder in the sequence.
void updateProgress()
Updates the progress bar.
ShapeList * shapeList()
@briefReturns a pointer to the ShapeList for this WorkOrder.
bool m_isSavedToHistory
Set the work order to be shown in the HistoryTreeWidget.
Definition WorkOrder.h:537
QueuedWorkOrderAction
This enum describes the current state of a Queued WorkOrder.
Definition WorkOrder.h:483
void setProgressRange(int, int)
Sets the progress range of the WorkOrder.
int progressMax() const
Gets the maximum value of the progress range of the WorkOrder.
QStringList m_shapeIds
A QStringList of unique shape identifiers for all of the shapes this WorkOrder is dealing with.
Definition WorkOrder.h:616
virtual void setData(Context)
Sets the context data for this WorkOrder.
WorkOrder * next() const
Gets the next WorkOrder.
bool modifiesDiskState() const
Returns the modified disk state.
void read(XmlStackedHandlerReader *xmlReader)
Read this work order's data from disk.
bool m_isSynchronous
This is defaulted to true.
Definition WorkOrder.h:530
bool isUndoing() const
Returns the WorkOrderUndoing state.
void attemptQueuedAction()
Attempts to execute an action on the action queue.
virtual void undoExecution()
Execute the steps necessary to undo this workorder.
virtual void postUndoExecution()
Perform any steps necessary after an undo of a workorder.
Template * getTemplate()
WorkOrder::getTemplate.
Template * m_template
A QSharedPointer to the Template (A Template object but encapsulated within a Gui framework.
Definition WorkOrder.h:590
void save(QXmlStreamWriter &stream) const
: Saves a WorkOrder to a data stream.
void clearShapeList()
Clears the list of shapes.
bool isRedone() const
Returns the WorkOrder redone status.
void executionFinished()
Signals the Project that the WorkOrder is finished, deletes the update time for the Progress bar,...
virtual void redo()
Starts (or enqueues) a redo.
WorkOrderStatus
This enumeration is used by other functions to set and retrieve the current state of the WorkOrder.
Definition WorkOrder.h:321
@ WorkOrderFinished
This is used for work orders that will not undo or redo (See createsCleanState())
Definition WorkOrder.h:331
virtual void undo()
Starts (or enqueues) an undo.
int progressMin() const
Gets the minimum value of the progress range of the WorkOrder.
bool isUndoable() const
Returns true if this work order is undoable, otherwise false.
WorkOrder * previous() const
Gets the previous WorkOrder.
bool m_isUndoable
Set the workorder to be undoable/redoable This is defaulted to true - his will allow the workorder to...
Definition WorkOrder.h:523
void setProgressValue(int)
Sets the current progress value for the WorkOrder.
static QString toString(WorkOrderStatus)
Gets the current status of the WorkOrder.
bool isUndone() const
Returns the WorkOrder undo status.
virtual bool setupExecution()
This sets up the state for the work order.
void setProgressToFinalText()
Sets the ProgressBar to display the final status of the operation.
QDateTime m_executionTime
This is the date/time that setupExecution() was called.
Definition WorkOrder.h:647
bool m_createsCleanState
This is defaulted to false.
Definition WorkOrder.h:549
bool isSavedToHistory() const
Returns true if this work order is to be shown in History, otherwise false.
bool isInStableState() const
Determines if the WorkOrder is in a stable state, or if it's busy doing something.
GuiCameraQsp m_guiCamera
A QSharedPointer to the GuiCamera (the Camera object but encapsulated within a Gui framework.
Definition WorkOrder.h:583
QPointer< WorkOrder > m_previousWorkOrder
A pointer to the previous WorkOrder in the queue.
Definition WorkOrder.h:631
static WorkOrderStatus fromStatusString(QString)
Attempts to query the current status of the WorkOrder.
bool isRedoing() const
Returns the redoing status of this WorkOrder.
int m_progressRangeMaxValue
The maximum value of the Progess Bar.
Definition WorkOrder.h:567
QStringList internalData() const
Gets the internal data for this WorkOrder.
QPointer< ControlList > controlList()
Returns the Control List for this WorkOrder (a list of control networks).
Directory * directory() const
return the workorder project directory Returns the Directory object of the Project this WorkOrder is ...
int m_progressValue
The current value of the Progress Bar.
Definition WorkOrder.h:571
GuiCameraQsp guiCamera()
WorkOrder::guiCamera.
void setCreatesCleanState(bool createsCleanState)
Declare that this work order is saving the project.
QString statusText() const
WorkOrder::statusText.
QDateTime executionTime() const
Gets the execution time of this WorkOrder.
virtual void execute()
Execute the workorder.
void setModifiesDiskState(bool changesProjectOnDisk)
QPointer< ProgressBar > m_progressBar
A pointer to the ProgressBar.
Definition WorkOrder.h:661
void setPrevious(WorkOrder *previousWorkOrder)
Sets the previous WorkOrder in the sequence.
void listenForShapeDestruction()
Checks to see if we have lost any shapes in the ShapeList.
virtual bool isExecutable(Context)
Re-implement this method if your work order utilizes controls for data in order to operate.
void disableWorkOrder()
Disables the work order.
bool createsCleanState() const
Returns the CleanState status (whether the Project has been saved to disk or not).
TargetBodyQsp targetBody()
WorkOrder::targetBody.
double m_secondsElapsed
The seconds that have elapsed since the WorkOrder started executing.
Definition WorkOrder.h:682
void setInternalData(QStringList data)
Sets the internal data for this WorkOrder.
int m_progressRangeMinValue
The miniumum value of the Progess Bar.
Definition WorkOrder.h:563
virtual bool dependsOn(WorkOrder *other) const
Indicate workorder dependency This is a virtual function whose role in child classes is to determine ...
Project * project() const
Returns the Project this WorkOrder is attached to.
void clearImageList()
Clears the list of images.
QPointer< Project > m_project
A pointer to the Project this WorkOrder is attached to.
Definition WorkOrder.h:636
virtual ~WorkOrder()
The Destructor.
ProgressBar * progressBar()
Returns the ProgressBar.
QStringList m_internalData
A QStringList of internal properties for this WorkOrder.
Definition WorkOrder.h:621
bool m_modifiesDiskState
This is defaulted to false.
Definition WorkOrder.h:556
QMutex * m_transparentConstMutex
This is used to protect the integrity of data the WorkOrder is working on so that only one thread at ...
Definition WorkOrder.h:642
QPointer< WorkOrder > m_nextWorkOrder
A pointer to the next WorkOrder in the queue.
Definition WorkOrder.h:626
void addCloneToProject()
Runs a copy of the current WorkOrder and stores it in the project.
void startRedo()
WorkOrder::startRedo This function is currently empty.
void resetProgressBar()
Resets the ProgressBar.
FileItemQsp m_fileItem
A QSharedPointer to the FileItem.
Definition WorkOrder.h:603
ImageList * imageList()
Returns a pointer to the ImageList for this WorkOrder.
bool isSynchronous() const
Returns true if this work order is run synchronously, otherwise false.
Context
This enumeration is for recording the context of the current Workorder (whether it is part of a proje...
Definition WorkOrder.h:339
QString bestText() const
Generate unique action names We don't use action text anymore because Directory likes to rename our a...
int progressValue() const
Gets the current progress value of the WorkOrder.
bool isFinished() const
Returns the finished state of this WorkOrder.
virtual void postExecution()
Perform any necessary actions after execution of a workorder.
QPointer< QFutureWatcher< void > > m_futureWatcher
A pointer to a QFutureWatcher object which monitors a QFuture object using signals and slots.
Definition WorkOrder.h:654
CorrelationMatrix correlationMatrix()
Returns the CorrleationMatrix for this WorkOrder.
QPointer< QTimer > m_progressBarDeletionTimer
A pointer to the ProgressBar deletion timer.
Definition WorkOrder.h:671
void listenForImageDestruction()
Checks to see if we have lost any images in the ImageList.
FileItemQsp fileItem()
WorkOrder::fileItem.
WorkOrder(Project *project)
Create a work order that will work with the given project.
Definition WorkOrder.cpp:39
TargetBodyQsp m_targetBody
A QSharedPointer to the TargetBody (A Target object but encapsulated within a Gui framework.
Definition WorkOrder.h:597
Manage a stack of content handlers for reading XML files.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QSharedPointer< GuiCamera > GuiCameraQsp
GuiCameraQsp Represents a smart pointer to a GuiCamera object.
Definition GuiCamera.h:186
QSharedPointer< TargetBody > TargetBodyQsp
Defines A smart pointer to a TargetBody obj.
Definition TargetBody.h:216
QSharedPointer< FileItem > FileItemQsp
A FileItem smart pointer.
Definition FileItem.h:36