ImagingTools Core SDK
TTaskCollectionEditorCompBase.h
1// SPDX-License-Identifier: LGPL-2.1-or-later OR GPL-2.0-or-later OR GPL-3.0-or-later OR LicenseRef-ImtCore-Commercial
2#pragma once
3
4
5// Qt includes
6#include <QtCore/QItemSelection>
7#include <QtGui/QStandardItemModel>
8#include <QtWidgets/QMenu>
9#include <QtWidgets/QMessageBox>
10#include <QtWidgets/QInputDialog>
11#include <QtWidgets/QLineEdit>
12
13// ACF includes
14#include <imod/CMultiModelDispatcherBase.h>
15#include <iimg/CBitmap.h>
16#include <ibase/ICommandsProvider.h>
17#include <iqtgui/TDesignerGuiObserverCompBase.h>
18#include <iqtgui/CHierarchicalCommand.h>
19#include <iqtgui/CGuiComponentDialog.h>
20#include <iqtgui/TMakeStateIconWrapper.h>
21#include <imod/IModel.h>
22#include <iprm/IOptionsList.h>
23#include <istd/CChangeGroup.h>
24#include <istd/CChangeNotifier.h>
25
26// ImtCore
27#include <imtbase/TModelUpdateBinder.h>
28
29// Acula includes
30#include <imthype/ITaskCollection.h>
31#include <imthype/ITaskResultCollection.h>
32#include <imthype/ITaskSettings.h>
33#include <imthypegui/CTaskItemDelegate.h>
34#include <imthypegui/CTaskSettingsDialog.h>
35#include <imthypegui/CTaskSettingsGuiComp.h>
36
37
38namespace imthypegui
39{
40
41
42template <class UI>
43class TTaskCollectionEditorCompBase:
44 public iqtgui::StateIconWrapper<
45 iqtgui::TDesignerGuiObserverCompBase<
46 UI,
47 imthype::ITaskCollection> >,
48 protected imod::CMultiModelDispatcherBase,
49 virtual public ibase::ICommandsProvider
50{
51 Q_DECLARE_TR_FUNCTIONS(TTaskCollectionEditorCompBase)
52
53public:
54 typedef iqtgui::StateIconWrapper< iqtgui::TDesignerGuiObserverCompBase<UI, imthype::ITaskCollection> > BaseClass;
55 typedef imod::CMultiModelDispatcherBase BaseClass2;
56
57 I_BEGIN_BASE_COMPONENT(TTaskCollectionEditorCompBase);
58 I_REGISTER_SUBELEMENT(Commands);
59 I_REGISTER_SUBELEMENT_INTERFACE(Commands, ibase::ICommandsProvider, ExtractCommands);
60 I_REGISTER_SUBELEMENT_INTERFACE(Commands, istd::IChangeable, ExtractCommands);
61 I_REGISTER_SUBELEMENT_INTERFACE(Commands, imod::IModel, ExtractCommands);
62 I_REGISTER_SUBELEMENT(TaskSettings);
63 I_REGISTER_SUBELEMENT_INTERFACE(TaskSettings, imthype::ITaskSettings, ExtractTaskSettings);
64 I_REGISTER_SUBELEMENT_INTERFACE(TaskSettings, istd::IChangeable, ExtractTaskSettings);
65 I_REGISTER_SUBELEMENT_INTERFACE(TaskSettings, imod::IModel, ExtractTaskSettings);
66 I_ASSIGN(m_previewArtifactIdAttrPtr, "PreviewArtifactId", "ID of the artifact used for task tumbnail", true, "Preview");
67 I_ASSIGN(m_allowAddTasksAttrPtr, "AllowAddTasks", "If enabled, adding the new task by user will be possible", true, true);
68 I_ASSIGN(m_taskInputManagerGuiCompPtr, "TaskInputEditor", "Editor of task inputs", false, "TaskInputEditor");
69 I_ASSIGN_TO(m_taskInputManagerObserverCompPtr, m_taskInputManagerGuiCompPtr, true);
70 I_ASSIGN(m_taskSettingsGuiCompPtr, "TaskSettingsEditor", "Editor of task settings", false, "TaskSettingsGui");
71 I_ASSIGN_TO(m_taskSettingsObserverCompPtr, m_taskSettingsGuiCompPtr, true);
72 I_END_COMPONENT;
73
74 TTaskCollectionEditorCompBase();
75 ~TTaskCollectionEditorCompBase();
76
77protected:
78 void TestAll();
79 void AddTask(const QByteArray& typeId = QByteArray(), bool initUserId = false);
80 void DeleteTask();
81 void DuplicateTask();
82 void OnTaskSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
83 void EditTask(const QModelIndex& index);
84 void ToggleTask();
85 void RenameTask(bool autoRename = true);
86 void ShowInputsManager();
87
88 int GetLastNumberedUserId();
89
90protected:
91 virtual QItemSelectionModel* GetTaskSelectionModel() const = 0;
92
93 virtual void UpdateCommands();
94 void UpdateTaskItemState(const QModelIndex& index);
95 imod::IModel* GetTaskModelFromSelection(const QItemSelection& itemSelection) const;
96 imod::IObserver* GetTaskModelObserverFromSelection(const QItemSelection& itemSelection) const;
97
98 void InfoToTaskSettings();
99 void InfoFromTaskSettings();
100 void OnTaskSettingsChanged(const istd::IChangeable::ChangeSet& /*changeset*/, const imthype::ITaskSettings* taskSettingsPtr);
101
102 // reimplemented (iqtgui::TGuiObserverWrap)
103 virtual void OnGuiModelAttached() override;
104 virtual void OnGuiModelDetached() override;
105 virtual void UpdateGui(const istd::IChangeable::ChangeSet& changeSet) override;
106
107 // reimplemented (imod::CMultiModelDispatcherBase)
108 virtual void OnModelChanged(int modelId, const istd::IChangeable::ChangeSet& changeSet) override;
109
110private:
111 class TaskSettings: virtual public imthype::ITaskSettings
112 {
113 public:
114 TaskSettings();
115
116 void SetParent(TTaskCollectionEditorCompBase* parentPtr);
117
118 // reimplemented (imthype::ITaskSettings)
119 virtual QString GetTaskName() const override;
120 virtual void SetTaskName(const QString& taskName) override;
121 virtual QString GetTaskDescription() const override;
122 virtual void SetTaskDescription(const QString& taskDescription) override;
123 virtual bool GetTaskEnabled() const override;
124 virtual void SetTaskEnabled(bool isEnabled) override;
125 virtual QByteArray GetUserTaskId() const override;
126 virtual void SetUserTaskId(const QByteArray& userTaskId) override;
127 virtual QByteArray GetTaskInputId() const override;
128 virtual void SetTaskInputId(const QByteArray& inputId) override;
129 virtual const imtbase::IObjectCollection* GetTaskInputs() const override;
130
131 private:
132 TTaskCollectionEditorCompBase* m_parentPtr = nullptr;
133
134 QString m_taskName;
135 QString m_taskDescription;
136 bool m_isEnabled = false;
137 QByteArray m_userTaskId;
138 QByteArray m_inputId;
139 };
140
141 template <typename InterfaceType>
142 static InterfaceType* ExtractTaskSettings(TTaskCollectionEditorCompBase& component)
143 {
144 return &component.m_taskSettings;
145 }
146
147
148 class Commands: virtual public ibase::ICommandsProvider
149 {
150 public:
151 Commands();
152
153 void SetParent(TTaskCollectionEditorCompBase* parentPtr);
154
155 protected:
156 // reimplemented (ibase::ICommandsProvider)
157 virtual const ibase::IHierarchicalCommand* GetCommands() const override;
158
159 private:
160 TTaskCollectionEditorCompBase* m_parentPtr = nullptr;
161 };
162
163 template <typename InterfaceType>
164 static InterfaceType* ExtractCommands(TTaskCollectionEditorCompBase& component)
165 {
166 return &component.m_commandsProvider;
167 }
168
169protected:
170 QStandardItemModel m_itemModel;
171
172 typedef QMap<QByteArray, imod::IObserver*> ObserversMap;
173 ObserversMap m_observersMap;
174
175 typedef QMap<QByteArray, iqtgui::IGuiObjectSharedPtr> EditorsMap;
176 EditorsMap m_editorsMap;
177
178 typedef QMap<QByteArray, qsizetype> TypeToIndexMap;
179 TypeToIndexMap m_typeToStackIndexMap;
180
181 QMenu m_startVariableMenus;
182
183 int m_currentSelectedIndex = -1;
184
185 iqtgui::CHierarchicalCommand m_rootCommands;
186 iqtgui::CHierarchicalCommand m_commands;
187 iqtgui::CHierarchicalCommand m_showTaskListCommand;
188 iqtgui::CHierarchicalCommand m_executeAllTasksCommand;
189 iqtgui::CHierarchicalCommand m_addCommand;
190 iqtgui::CHierarchicalCommand m_deleteCommand;
191 iqtgui::CHierarchicalCommand m_duplicateCommand;
192 iqtgui::CHierarchicalCommand m_showInputsManagerCommand;
193
194 imod::TModelWrap<Commands> m_commandsProvider;
195
196 imod::TModelWrap<TaskSettings> m_taskSettings;
197 bool m_isTaskSettingsUpdating = false;
198 QByteArray m_selectedTaskId;
199
201
202 I_ATTR(QByteArray, m_previewArtifactIdAttrPtr);
203 I_ATTR(bool, m_allowAddTasksAttrPtr);
204 I_REF(iqtgui::IGuiObject, m_taskInputManagerGuiCompPtr);
205 I_REF(imod::IObserver, m_taskInputManagerObserverCompPtr);
206 I_REF(iqtgui::IGuiObject, m_taskSettingsGuiCompPtr);
207 I_REF(imod::IObserver, m_taskSettingsObserverCompPtr);
208};
209
210
211
212template <class UI>
213TTaskCollectionEditorCompBase<UI>::TTaskCollectionEditorCompBase()
214 :m_currentSelectedIndex(0),
215 m_showTaskListCommand("Show Task List", 100, ibase::ICommand::CF_GLOBAL_MENU | ibase::ICommand::CF_ONOFF, 1977),
216 m_executeAllTasksCommand("Execute", 100, ibase::ICommand::CF_GLOBAL_MENU, 1978),
217 m_addCommand("Add Task", 100, ibase::ICommand::CF_GLOBAL_MENU, 1979),
218 m_deleteCommand("Remove Task", 100, ibase::ICommand::CF_GLOBAL_MENU, 1979),
219 m_duplicateCommand("Duplicate Task", 100, ibase::ICommand::CF_GLOBAL_MENU, 1979),
220 m_showInputsManagerCommand("Edit Inputs", 100, ibase::ICommand::CF_GLOBAL_MENU, 1980),
221 m_isTaskSettingsUpdating(false),
222 m_taskSettingsObserver(*this)
223{
224 m_rootCommands.InsertChild(&m_commands, false);
225
226 m_commands.InsertChild(&m_showTaskListCommand);
227 m_commands.InsertChild(&m_executeAllTasksCommand);
228 m_commands.InsertChild(&m_addCommand);
229 m_commands.InsertChild(&m_deleteCommand);
230 m_commands.InsertChild(&m_duplicateCommand);
231 m_commands.InsertChild(&m_showInputsManagerCommand);
232
233 m_commandsProvider.SetParent(this);
234
235 m_taskSettings.SetParent(this);
236 m_taskSettingsObserver.RegisterObject(&m_taskSettings, &TTaskCollectionEditorCompBase<UI>::OnTaskSettingsChanged);
237}
238
239
240template <class UI>
241TTaskCollectionEditorCompBase<UI>::~TTaskCollectionEditorCompBase()
242{
243 m_taskSettingsObserver.UnregisterAllObjects();
244}
245
246
247template <class UI>
248void TTaskCollectionEditorCompBase<UI>::TestAll()
249{
250 imthype::ITaskCollection* objectPtr = BaseClass::BaseClass::GetObjectPtr();
251 if (objectPtr != nullptr){
252 imtbase::ICollectionInfo::Ids taskIds = objectPtr->GetElementIds();
253 for (const QByteArray& taskId : taskIds){
254 iinsp::ISupplier* taskPtr = const_cast<iinsp::ISupplier*>(objectPtr->GetTask(taskId));
255 bool isTaskEnabled = objectPtr->GetElementInfo(taskId, imtbase::ICollectionInfo::EIT_ENABLED).toBool();
256
257 if ((taskPtr != nullptr) && isTaskEnabled){
258 taskPtr->InvalidateSupplier();
259
260 taskPtr->EnsureWorkInitialized();
261 }
262 }
263
264 for (const QByteArray& taskId : taskIds){
265 iinsp::ISupplier* taskPtr = const_cast<iinsp::ISupplier*>(objectPtr->GetTask(taskId));
266 bool isTaskEnabled = objectPtr->GetElementInfo(taskId, imtbase::ICollectionInfo::EIT_ENABLED).toBool();
267
268 if ((taskPtr != nullptr) && isTaskEnabled){
269 taskPtr->EnsureWorkFinished();
270 }
271 }
272 }
273}
274
275
276template <class UI>
277void TTaskCollectionEditorCompBase<UI>::AddTask(const QByteArray& typeId, bool initUserId)
278{
279 imthype::ITaskCollection* objectPtr = BaseClass::GetObjectPtr();
280 if (objectPtr == nullptr){
281 return;
282 }
283
284 const iprm::IOptionsList* taskTypesPtr = objectPtr->GetObjectTypesInfo();
285 if (taskTypesPtr == nullptr || taskTypesPtr->GetOptionsCount() < 1){
286 return;
287 }
288
289 QByteArray workingTypeId = typeId;
290 if (workingTypeId.isEmpty()){
291 workingTypeId = taskTypesPtr->GetOptionId(0);
292 }
293
294 istd::CChangeGroup changeGroup(objectPtr);
295 Q_UNUSED(changeGroup);
296
297 QByteArray taskId = objectPtr->InsertNewObject(workingTypeId, QString(), QString());
298
299 if (taskId.isEmpty()){
300 QMessageBox::critical(BaseClass::GetWidget(), QObject::tr("Task Manager"), QObject::tr("Task could not be created!"));
301 return;
302 }
303
304 if (initUserId){
305 int lastUserId = GetLastNumberedUserId();
306
307 if (lastUserId >= 0){
308 objectPtr->SetUserTaskId(taskId, QByteArray(QString::number(lastUserId + 1).toUtf8()));
309 }
310 }
311
312 // select the recent task
313 QItemSelectionModel* selectionModelPtr = GetTaskSelectionModel();
314 int lastRow = selectionModelPtr->model()->rowCount() - 1;
315 m_currentSelectedIndex = lastRow;
316 selectionModelPtr->setCurrentIndex(selectionModelPtr->model()->index(lastRow, 0), QItemSelectionModel::SelectCurrent);
317}
318
319
320template <class UI>
321void TTaskCollectionEditorCompBase<UI>::DeleteTask()
322{
323 imthype::ITaskCollection* objectPtr = BaseClass::GetObjectPtr();
324 if (objectPtr == nullptr){
325 return;
326 }
327
328 QItemSelectionModel* selectionModelPtr = GetTaskSelectionModel();
329 if (selectionModelPtr == nullptr){
330 return;
331 }
332
333 const QItemSelection currentSelection = selectionModelPtr->selection();
334 const QModelIndexList indexes = currentSelection.indexes();
335 if (indexes.isEmpty()){
336 return;
337 }
338
339 int selectionIndex = m_currentSelectedIndex;
340 selectionModelPtr->select(currentSelection, QItemSelectionModel::Deselect);
341
342 imtbase::ICollectionInfo::Ids taskIds = objectPtr->GetElementIds();
343
344 if (taskIds.count() > 1){
345 m_currentSelectedIndex = selectionIndex > 0 ? selectionIndex - 1 : 0;
346 }
347
348 const QModelIndex index = indexes[0];
349
350 QByteArray taskId = index.data(CTaskItemDelegate::DR_TASK_UUID).toByteArray();
351
352 imtbase::ICollectionInfo::Ids elementIds;
353 elementIds << taskId;
354
355 objectPtr->RemoveElements(elementIds);
356}
357
358
359template <class UI>
360void TTaskCollectionEditorCompBase<UI>::DuplicateTask()
361{
362 imthype::ITaskCollection* objectPtr = BaseClass::GetObjectPtr();
363 if (objectPtr == nullptr){
364 return;
365 }
366
367 QItemSelectionModel* selectionModelPtr = GetTaskSelectionModel();
368 if (selectionModelPtr == nullptr){
369 return;
370 }
371
372 const QItemSelection currentSelection = selectionModelPtr->selection();
373 const QModelIndexList selectedIndexes = currentSelection.indexes();
374
375 if (!selectedIndexes.isEmpty()){
376 const QModelIndex index = selectedIndexes[0];
377
378 QByteArray taskId = index.data(CTaskItemDelegate::DR_TASK_UUID).toByteArray();
379 QByteArray taskTypeId = index.data(CTaskItemDelegate::DR_TYPE_ID).toByteArray();
380 QString sourceTaskName = index.data(CTaskItemDelegate::DR_TASK_NAME).toString();
381
382 istd::CChangeGroup changeGroup(objectPtr);
383 Q_UNUSED(changeGroup);
384
385 QByteArray newTaskId = objectPtr->InsertNewObject(taskTypeId, QString("Copy of %1").arg(sourceTaskName), "", objectPtr->GetObjectPtr(taskId));
386 if (newTaskId.isEmpty()){
387 QMessageBox::critical(BaseClass::GetWidget(), QObject::tr("Task Error"), QObject::tr("Task could not be duplicated!"));
388 return;
389 }
390
391 if (!objectPtr->GetUserTaskId(taskId).isEmpty()){
392 int lastUserId = GetLastNumberedUserId();
393 if (lastUserId >= 0){
394 objectPtr->SetUserTaskId(newTaskId, QByteArray(QString::number(lastUserId + 1).toUtf8()));
395 }
396 }
397 }
398
399 // select the recent task
400 int lastRow = selectionModelPtr->model()->rowCount() - 1;
401 m_currentSelectedIndex = lastRow;
402 selectionModelPtr->setCurrentIndex(selectionModelPtr->model()->index(lastRow, 0), QItemSelectionModel::SelectCurrent);
403}
404
405
406template <class UI>
407void TTaskCollectionEditorCompBase<UI>::OnTaskSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected)
408{
409 int pageIndex = 0;
410 m_currentSelectedIndex = 0;
411 QString taskName;
412
413 m_selectedTaskId.clear();
414
415 imthype::ITaskCollection* objectPtr = BaseClass::GetObjectPtr();
416 if (objectPtr != nullptr){
417 imod::IModel* taskModelPtr = GetTaskModelFromSelection(deselected);
418 imod::IObserver* observerPtr = GetTaskModelObserverFromSelection(deselected);
419 if (taskModelPtr != nullptr && observerPtr != nullptr){
420 taskModelPtr->DetachObserver(observerPtr);
421 }
422
423 const QModelIndexList selectedIndexes = selected.indexes();
424 if (!selectedIndexes.isEmpty()){
425 const QModelIndex index = selectedIndexes[0];
426
427 QStandardItem* itemPtr = m_itemModel.itemFromIndex(index);
428 if (itemPtr != nullptr){
429 m_currentSelectedIndex = itemPtr->row();
430
431 QByteArray typeId = itemPtr->data(CTaskItemDelegate::DR_TYPE_ID).toByteArray();
432 pageIndex = m_typeToStackIndexMap[typeId];
433 taskName = itemPtr->data(CTaskItemDelegate::DR_TASK_NAME).toString();
434 m_selectedTaskId = itemPtr->data(CTaskItemDelegate::DR_TASK_UUID).toByteArray();
435
436 const iinsp::ISupplier* supplierPtr = objectPtr->GetTask(m_selectedTaskId);
437 imod::IModel* selectedTaskModelPtr = dynamic_cast<imod::IModel*>(const_cast<iinsp::ISupplier*>(supplierPtr));
438 imod::IObserver* selectedObserverPtr = m_observersMap[typeId];
439
440 if (selectedTaskModelPtr && selectedObserverPtr && !selectedTaskModelPtr->IsAttached(selectedObserverPtr)){
441 selectedTaskModelPtr->AttachObserver(selectedObserverPtr);
442 }
443 }
444 }
445 }
446
447 BaseClass::TaskEditorStack->setCurrentIndex(pageIndex);
448
449 BaseClass::SetStatusText(taskName);
450
451 UpdateCommands();
452
453 InfoToTaskSettings();
454}
455
456
457template <class UI>
458void TTaskCollectionEditorCompBase<UI>::EditTask(const QModelIndex& /*index*/)
459{
460 imthype::ITaskCollection* objectPtr = BaseClass::GetObservedObject();
461 if (objectPtr != nullptr && m_taskSettingsGuiCompPtr.IsValid() && m_taskSettingsObserverCompPtr.IsValid()){
462 iqtgui::CGuiComponentDialog dialog(m_taskSettingsGuiCompPtr.GetPtr(), QDialogButtonBox::Ok);
463 dialog.SetDialogGeometry(0.15);
464
465 dialog.exec();
466 }
467}
468
469
470template <class UI>
471void TTaskCollectionEditorCompBase<UI>::ToggleTask()
472{
473 QItemSelectionModel* selectionModelPtr = GetTaskSelectionModel();
474 if (selectionModelPtr == nullptr){
475 return;
476 }
477
478 imthype::ITaskCollection* objectPtr = BaseClass::GetObjectPtr();
479 if (objectPtr != nullptr){
480 const QItemSelection currentSelection = selectionModelPtr->selection();
481 const QModelIndexList selectedIndexes = currentSelection.indexes();
482
483 if (!selectedIndexes.isEmpty()){
484 const QModelIndex index = selectedIndexes[0];
485
486 QByteArray taskId = index.data(CTaskItemDelegate::DR_TASK_UUID).toByteArray();
487 bool isEnabled = index.data(CTaskItemDelegate::DR_TASK_ENABLED).toBool();
488
489 objectPtr->SetElementEnabled(taskId, !isEnabled);
490 }
491 }
492}
493
494
495template <class UI>
496void TTaskCollectionEditorCompBase<UI>::RenameTask(bool autoRename)
497{
498 QItemSelectionModel* selectionModelPtr = GetTaskSelectionModel();
499 if (selectionModelPtr == nullptr){
500 return;
501 }
502
503 imthype::ITaskCollection* objectPtr = BaseClass::GetObjectPtr();
504 if (objectPtr != nullptr){
505 const QItemSelection currentSelection = selectionModelPtr->selection();
506 const QModelIndexList selectedIndexes = currentSelection.indexes();
507
508 if (!selectedIndexes.isEmpty()){
509 const QModelIndex index = selectedIndexes[0];
510
511 QString currentTaskName = index.data(CTaskItemDelegate::DR_TASK_NAME).toString();
512
513 bool renamingFinished = false;
514
515 while (!renamingFinished){
516 bool isGetNameOk = false;
517 const QString newName = QInputDialog::getText(BaseClass::GetWidget(), QObject::tr("Enter new task name"), QObject::tr("Name"), QLineEdit::Normal, currentTaskName, &isGetNameOk).trimmed();
518
519 if (isGetNameOk){
520 if (!newName.isEmpty()){
521#if QT_VERSION > 0x060000
522 QRegularExpressionValidator inputValidator(QRegularExpression("^[^\\\\/:\\*\\?\"\\<\\>\\|\\+]+$"));
523#else
524 QRegExpValidator inputValidator(QRegExp("^[^\\\\/:\\*\\?\"\\<\\>\\|\\+]+$"));
525#endif
526 int pos;
527 QString name = newName;
528 if (inputValidator.validate(name, pos) != QValidator::Acceptable){
529 QMessageBox::critical(nullptr, tr("Error"), tr("The task name contains some not allowed characters"));
530
531 return;
532 }
533
534 QByteArray taskId = index.data(CTaskItemDelegate::DR_TASK_UUID).toByteArray();
535
536 bool isNewNameExists = false;
537
538 if (!autoRename){
539 imtbase::IObjectCollection::Ids ids = objectPtr->GetElementIds();
540 for (const imtbase::IObjectCollection::Id& id : ids){
541 QString taskName = objectPtr->GetElementInfo(id, imtbase::ICollectionInfo::EIT_NAME).toString();
542
543 if (newName == taskName){
544 isNewNameExists = true;
545 break;
546 }
547 }
548 }
549
550 if (!isNewNameExists){
551 objectPtr->SetElementName(taskId, newName);
552 renamingFinished = true;
553 }
554 else {
555 QMessageBox::warning(
556 BaseClass::GetQtWidget(),
557 QObject::tr("Warning"),
558 QObject::tr("Task name already exist"));
559 }
560 }
561 else{
562 QMessageBox::warning(BaseClass::GetWidget(), QObject::tr("Wrong task name"), QObject::tr("Empty task name cannot be used"));
563 }
564 }
565 else{
566 renamingFinished = true;
567 }
568 }
569 }
570 }
571}
572
573
574template<class UI>
575void TTaskCollectionEditorCompBase<UI>::ShowInputsManager()
576{
577 if (m_taskInputManagerGuiCompPtr.IsValid() && m_taskInputManagerObserverCompPtr.IsValid()){
578 imthype::ITaskCollection* objectPtr = BaseClass::GetObjectPtr();
579 if (objectPtr != nullptr){
580 const imtbase::IObjectCollection* taskInputsPtr = objectPtr->GetTaskInputs();
581 if (taskInputsPtr != nullptr){
582 const imod::IModel* taskInputsModelPtr = dynamic_cast<const imod::IModel*>(taskInputsPtr);
583 if (taskInputsModelPtr != nullptr){
584 if ((const_cast<imod::IModel*>(taskInputsModelPtr))->AttachObserver(m_taskInputManagerObserverCompPtr.GetPtr())){
585 iqtgui::CGuiComponentDialog dialog(m_taskInputManagerGuiCompPtr.GetPtr(), QDialogButtonBox::Close, false, BaseClass::GetWidget());
586 dialog.SetDialogGeometry(0.5);
587 dialog.setWindowTitle(tr("Task Input Manager"));
588
589 dialog.exec();
590
591 (const_cast<imod::IModel*>(taskInputsModelPtr))->DetachObserver(m_taskInputManagerObserverCompPtr.GetPtr());
592 }
593 }
594 }
595 }
596 }
597}
598
599
600template <class UI>
601int TTaskCollectionEditorCompBase<UI>::GetLastNumberedUserId()
602{
603 imthype::ITaskCollection* objectPtr = BaseClass::GetObjectPtr();
604 if (objectPtr == nullptr){
605 return -1;
606 }
607
608 int lastUserId = 0;
609
610 imtbase::IObjectCollection::Ids ids = objectPtr->GetElementIds();
611 for (const imtbase::IObjectCollection::Id& id : ids){
612 QByteArray userId = objectPtr->GetUserTaskId(id);
613
614 bool isOk = false;
615 int convertedUserId = userId.toInt(&isOk);
616
617 if (isOk){
618 if (convertedUserId > lastUserId){
619 lastUserId = convertedUserId;
620 }
621 }
622 }
623
624 return lastUserId;
625}
626
627
628template <class UI>
629void TTaskCollectionEditorCompBase<UI>::UpdateCommands()
630{
631 m_addCommand.setEnabled(false);
632 m_deleteCommand.setEnabled(false);
633 m_duplicateCommand.setEnabled(false);
634 m_showInputsManagerCommand.setEnabled(false);
635
636 imthype::ITaskCollection* objectPtr = BaseClass::GetObjectPtr();
637 if (objectPtr != nullptr){
638 m_addCommand.setEnabled(true);
639
640 m_addCommand.setVisible(*m_allowAddTasksAttrPtr && (objectPtr->GetOperationFlags() & imthype::ITaskCollection::OF_SUPPORT_INSERT));
641 m_duplicateCommand.setVisible(*m_allowAddTasksAttrPtr && (objectPtr->GetOperationFlags() & imthype::ITaskCollection::OF_SUPPORT_INSERT));
642
643 const QModelIndexList selection = BaseClass::TaskList->selectionModel()->selectedIndexes();
644 if (!selection.isEmpty()){
645 const QModelIndex index = selection[0];
646
647 QByteArray taskId = index.data(CTaskItemDelegate::DR_TASK_UUID).toByteArray();
648 int flags = objectPtr->GetOperationFlags(taskId);
649
650 m_deleteCommand.setVisible(*m_allowAddTasksAttrPtr);
651 m_deleteCommand.setEnabled(*m_allowAddTasksAttrPtr && (flags & imthype::ITaskCollection::OF_SUPPORT_DELETE));
652
653 m_duplicateCommand.setEnabled(*m_allowAddTasksAttrPtr);
654 }
655
656 m_showInputsManagerCommand.setEnabled(objectPtr->GetTaskInputs() != nullptr);
657 }
658}
659
660
661template <class UI>
662void TTaskCollectionEditorCompBase<UI>::InfoToTaskSettings()
663{
664 m_isTaskSettingsUpdating = true;
665
666 QString name;
667 QString description;
668 bool isEnabled = false;
669 QByteArray userTaskId;
670 QByteArray inputId;
671
672 imthype::ITaskCollection* objectPtr = BaseClass::GetObservedObject();
673 if (objectPtr != nullptr && objectPtr->GetElementIds().contains(m_selectedTaskId)){
674 name = objectPtr->GetElementInfo(m_selectedTaskId, imtbase::ICollectionInfo::EIT_NAME).toString();
675 description = objectPtr->GetElementInfo(m_selectedTaskId, imtbase::ICollectionInfo::EIT_DESCRIPTION).toString();
676 isEnabled = objectPtr->GetElementInfo(m_selectedTaskId, imtbase::ICollectionInfo::EIT_ENABLED).toBool();
677 userTaskId = objectPtr->GetUserTaskId(m_selectedTaskId);
678 inputId = objectPtr->GetTaskInputId(m_selectedTaskId);
679 }
680
681 {
682 istd::CChangeGroup group(&m_taskSettings);
683
684 m_taskSettings.SetTaskName(name);
685 m_taskSettings.SetTaskDescription(description);
686 m_taskSettings.SetTaskEnabled(isEnabled);
687 m_taskSettings.SetUserTaskId(userTaskId);
688 m_taskSettings.SetTaskInputId(inputId);
689 }
690
691 m_isTaskSettingsUpdating = false;
692}
693
694
695template <class UI>
696void TTaskCollectionEditorCompBase<UI>::InfoFromTaskSettings()
697{
698 if (!m_isTaskSettingsUpdating){
699 QString name = m_taskSettings.GetTaskName();
700 QString description = m_taskSettings.GetTaskDescription();
701 bool isEnabled = m_taskSettings.GetTaskEnabled();
702 QByteArray userTaskId = m_taskSettings.GetUserTaskId();
703 QByteArray inputId = m_taskSettings.GetTaskInputId();
704
705 imthype::ITaskCollection* taskCollectionPtr = BaseClass::GetObservedObject();
706 if (taskCollectionPtr != nullptr && taskCollectionPtr->GetElementIds().contains(m_selectedTaskId)){
707 istd::CChangeGroup group(taskCollectionPtr);
708
709 taskCollectionPtr->SetElementName(m_selectedTaskId, name);
710 taskCollectionPtr->SetElementDescription(m_selectedTaskId, description);
711 taskCollectionPtr->SetElementEnabled(m_selectedTaskId, isEnabled);
712 taskCollectionPtr->SetTaskInputId(m_selectedTaskId, inputId);
713 if (!taskCollectionPtr->SetUserTaskId(m_selectedTaskId, userTaskId)){
714 QByteArray userId = taskCollectionPtr->GetUserTaskId(m_selectedTaskId);
715 m_taskSettings.SetUserTaskId(userId);
716 //taskCollectionPtr->SetUserTaskId(m_selectedTaskId, userId);
717 }
718 }
719 }
720}
721
722
723template <class UI>
724void TTaskCollectionEditorCompBase<UI>::UpdateTaskItemState(const QModelIndex& index)
725{
726 istd::IInformationProvider::InformationCategory taskState = istd::IInformationProvider::IC_NONE;
727
728 imthype::ITaskCollection* objectPtr = BaseClass::GetObjectPtr();
729 if (objectPtr == nullptr){
730 return;
731 }
732
733 QByteArray taskId = index.data(CTaskItemDelegate::DR_TASK_UUID).toByteArray();
734
735 const iinsp::ISupplier* taskPtr = objectPtr->GetTask(taskId);
736 if (taskPtr == nullptr){
737 m_itemModel.setData(index, taskState, CTaskItemDelegate::DR_TASK_PROCESSING_STATE);
738 m_itemModel.setData(index, this->GetCategoryPixmap(taskState), CTaskItemDelegate::DR_TASK_PROCESSING_STATE_ICON);
739 return;
740 }
741
742 const istd::IInformationProvider* infoProviderPtr = dynamic_cast<const istd::IInformationProvider*>(taskPtr);
743 if (infoProviderPtr != nullptr){
744 taskState = infoProviderPtr->GetInformationCategory();
745 }
746
747 const imthype::ITaskResultCollection* taskResultsProviderPtr = CompCastPtr<const imthype::ITaskResultCollection>(taskPtr);
748 if (taskResultsProviderPtr != nullptr){
749 // \todo Call the rendering processor for preview generation at this place. Input is the artifact object, output is a bitmap!
750 const iimg::IBitmap* inputBitmapPtr = dynamic_cast<const iimg::IBitmap*>(taskResultsProviderPtr->GetObjectPtr(*m_previewArtifactIdAttrPtr));
751 if (inputBitmapPtr != nullptr){
752 // check if this is already QImage, to avoid extra copying
753 if (const iimg::CBitmap* imagePtr = dynamic_cast<const iimg::CBitmap*>(inputBitmapPtr)) {
754 m_itemModel.setData(index, imagePtr->GetQImage(), CTaskItemDelegate::DR_TASK_PREVIEW_OBJECT);
755 }
756 else { // na ja, then copy it to QImage
757 iimg::CBitmap previewBitmap;
758 previewBitmap.CopyFrom(*inputBitmapPtr, istd::IChangeable::CM_CONVERT);
759
760 m_itemModel.setData(index, previewBitmap.GetQImage(), CTaskItemDelegate::DR_TASK_PREVIEW_OBJECT);
761 }
762 }
763 }
764
765 m_itemModel.setData(index, taskState, CTaskItemDelegate::DR_TASK_PROCESSING_STATE);
766 m_itemModel.setData(index, this->GetCategoryPixmap(taskState), CTaskItemDelegate::DR_TASK_PROCESSING_STATE_ICON);
767}
768
769
770template <class UI>
771imod::IModel* TTaskCollectionEditorCompBase<UI>::GetTaskModelFromSelection(const QItemSelection& itemSelection) const
772{
773 imthype::ITaskCollection* objectPtr = BaseClass::GetObjectPtr();
774 if (objectPtr == nullptr){
775 return nullptr;
776 }
777
778 const QModelIndexList indexes = itemSelection.indexes();
779 if (indexes.isEmpty()){
780 return nullptr;
781 }
782
783 const QModelIndex index = indexes[0];
784
785 QByteArray taskId = index.data(CTaskItemDelegate::DR_TASK_UUID).toByteArray();
786
787 const iinsp::ISupplier* supplierPtr = objectPtr->GetTask(taskId);
788
789 return dynamic_cast<imod::IModel*>(const_cast<iinsp::ISupplier*>(supplierPtr));
790}
791
792
793template <class UI>
794imod::IObserver* TTaskCollectionEditorCompBase<UI>::GetTaskModelObserverFromSelection(const QItemSelection& itemSelection) const
795{
796 imthype::ITaskCollection* objectPtr = BaseClass::GetObjectPtr();
797 if (objectPtr == nullptr){
798 return nullptr;
799 }
800
801 const QModelIndexList indexes = itemSelection.indexes();
802 if (indexes.isEmpty()){
803 return nullptr;
804 }
805
806 const QModelIndex index = indexes[0];
807
808 const QStandardItem* itemPtr = m_itemModel.itemFromIndex(index);
809 Q_ASSERT(itemPtr != nullptr);
810
811 QByteArray typeId = itemPtr->data(CTaskItemDelegate::DR_TYPE_ID).toByteArray();
812
813 return m_observersMap[typeId];
814}
815
816
817template <class UI>
818void TTaskCollectionEditorCompBase<UI>::OnTaskSettingsChanged(
819 const istd::IChangeable::ChangeSet& /*changeset*/,
820 const imthype::ITaskSettings* /*taskSettingsPtr*/)
821{
822 InfoFromTaskSettings();
823}
824
825
826// reimplemented (iqtgui::TGuiObserverWrap)
827
828template <class UI>
829void TTaskCollectionEditorCompBase<UI>::OnGuiModelAttached()
830{
831 BaseClass::OnGuiModelAttached();
832
833 imthype::ITaskCollection* objectPtr = BaseClass::GetObjectPtr();
834 if (objectPtr != nullptr){
835 const iprm::IOptionsList* taskTypesPtr = objectPtr->GetObjectTypesInfo();
836 if (taskTypesPtr != nullptr){
837 int taskTypesCount = taskTypesPtr->GetOptionsCount();
838 for (int i = 0; i < taskTypesCount; ++i){
839 if (taskTypesPtr->IsOptionEnabled(i)){
840 const QString typeName = taskTypesPtr->GetOptionName(i);
841
842 QAction* action = m_startVariableMenus.addAction(typeName);
843 action->setData(taskTypesPtr->GetOptionId(i));
844 }
845 }
846
847 m_addCommand.setMenu(&m_startVariableMenus);
848
849 QObject::connect(&m_startVariableMenus, SIGNAL(triggered(QAction*)), this, SLOT(OnAddMenuOptionClicked(QAction*)));
850 }
851 }
852}
853
854
855template <class UI>
856void TTaskCollectionEditorCompBase<UI>::OnGuiModelDetached()
857{
858 BaseClass::OnGuiModelDetached();
859}
860
861
862template <class UI>
863void TTaskCollectionEditorCompBase<UI>::UpdateGui(const istd::IChangeable::ChangeSet& changeSet)
864{
865 Q_ASSERT(BaseClass::IsGuiCreated());
866 int currentSelectedIndex = m_currentSelectedIndex;
867
868 if (changeSet.ContainsExplicit(istd::IChangeable::CF_DELEGATED, true)){
869 return;
870 }
871
872 const QItemSelection currentSelection = BaseClass::TaskList->selectionModel()->selection();
873 const QModelIndexList indexes = currentSelection.indexes();
874 if (!indexes.isEmpty()){
875 BaseClass::TaskList->selectionModel()->select(currentSelection, QItemSelectionModel::Deselect);
876 }
877
878 BaseClass::TaskList->selectionModel()->clear();
879 m_itemModel.clear();
880 m_itemModel.setColumnCount(1);
881
882 BaseClass2::UnregisterAllModels();
883
884 const imthype::ITaskCollection* objectPtr = BaseClass::GetObjectPtr();
885 if (objectPtr == nullptr){
886 UpdateCommands();
887 return;
888 }
889
890 int modelId = 0;
891
892 const iprm::IOptionsList* typesInfoPtr = objectPtr->GetObjectTypesInfo();
893
894 imtbase::ICollectionInfo::Ids taskIds = objectPtr->GetElementIds();
895 for (const QByteArray& taskId : taskIds){
896 QByteArray taskTypeId = objectPtr->GetObjectTypeId(taskId);
897 QString taskTypeName = taskTypeId;
898 if (typesInfoPtr != nullptr){
899 for (int i = 0; i < typesInfoPtr->GetOptionsCount(); ++i){
900 if (typesInfoPtr->GetOptionId(i) == taskTypeId){
901 taskTypeName = typesInfoPtr->GetOptionName(i);
902 break;
903 }
904 }
905 }
906
907 QStandardItem* taskItemPtr = new QStandardItem();
908 taskItemPtr->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
909 taskItemPtr->setData(taskId, CTaskItemDelegate::DR_TASK_UUID);
910 taskItemPtr->setData(taskTypeId, CTaskItemDelegate::DR_TYPE_ID);
911 taskItemPtr->setData(taskTypeName, CTaskItemDelegate::DR_TYPE_NAME);
912 QString taskName = objectPtr->GetElementInfo(taskId, imtbase::ICollectionInfo::EIT_NAME).toString();
913 taskItemPtr->setData(taskName, CTaskItemDelegate::DR_TASK_NAME);
914 taskItemPtr->setData(objectPtr->GetElementInfo(taskId, imtbase::ICollectionInfo::EIT_ENABLED), CTaskItemDelegate::DR_TASK_ENABLED);
915 taskItemPtr->setData(objectPtr->GetUserTaskId(taskId), CTaskItemDelegate::DR_TASK_USERID);
916 taskItemPtr->setData(objectPtr->GetTaskInputId(taskId), CTaskItemDelegate::DR_TASK_INPUTID);
917
918 taskItemPtr->setToolTip(
919 tr("Task name: ") + taskName
920 + tr("\nUser-ID: ") + objectPtr->GetUserTaskId(taskId)
921 + tr("\nInput-ID: ") + objectPtr->GetTaskInputId(taskId));
922
923 m_itemModel.appendRow(taskItemPtr);
924
925 const iinsp::ISupplier* taskPtr = objectPtr->GetTask(taskId);
926 imod::IModel* taskModelPtr = const_cast<imod::IModel*>(dynamic_cast<const imod::IModel*>(taskPtr));
927 if (taskModelPtr != nullptr){
928 BaseClass2::RegisterModel(taskModelPtr, modelId++);
929 }
930 }
931
932 int rowCount = m_itemModel.rowCount();
933
934 if (currentSelectedIndex > rowCount - 1){
935 currentSelectedIndex = rowCount - 1;
936 }
937
938 for (int i = 0; i < rowCount; ++i){
939 const QModelIndex index = m_itemModel.index(i, 0);
940 if (i == currentSelectedIndex){
941 BaseClass::TaskList->selectionModel()->select(index, QItemSelectionModel::Select);
942 }
943
944 UpdateTaskItemState(index);
945 }
946
947 UpdateCommands();
948}
949
950
951// reimplemented (imod::CMultiModelDispatcherBase)
952
953template <class UI>
954void TTaskCollectionEditorCompBase<UI>::OnModelChanged(int modelId, const istd::IChangeable::ChangeSet& /*changeSet*/)
955{
956 const QModelIndex index = m_itemModel.index(modelId, 0);
957
958 UpdateTaskItemState(index);
959}
960
961
962// public methods of the embedded class Commands
963
964template <class UI>
965TTaskCollectionEditorCompBase<UI>::Commands::Commands()
966 :m_parentPtr(nullptr)
967{
968}
969
970
971template <class UI>
972void TTaskCollectionEditorCompBase<UI>::Commands::SetParent(TTaskCollectionEditorCompBase<UI>* parentPtr)
973{
974 Q_ASSERT(parentPtr != nullptr);
975
976 m_parentPtr = parentPtr;
977}
978
979
980// reimplemented (ibase::ICommandsProvider)
981
982template <class UI>
983const ibase::IHierarchicalCommand* TTaskCollectionEditorCompBase<UI>::Commands::GetCommands() const
984{
985 Q_ASSERT(m_parentPtr != nullptr);
986
987 return &m_parentPtr->m_rootCommands;
988}
989
990
991// public methods of the embedded class TaskSettings
992
993template <class UI>
994TTaskCollectionEditorCompBase<UI>::TaskSettings::TaskSettings()
995 :m_parentPtr(nullptr),
996 m_isEnabled(false)
997{
998}
999
1000
1001template <class UI>
1002void TTaskCollectionEditorCompBase<UI>::TaskSettings::SetParent(TTaskCollectionEditorCompBase* parentPtr)
1003{
1004 Q_ASSERT(parentPtr != nullptr);
1005
1006 m_parentPtr = parentPtr;
1007}
1008
1009
1010// reimplemented (imthype::ITaskSettings)
1011
1012template <class UI>
1013QString TTaskCollectionEditorCompBase<UI>::TaskSettings::GetTaskName() const
1014{
1015 return m_taskName;
1016}
1017
1018
1019template <class UI>
1020void TTaskCollectionEditorCompBase<UI>::TaskSettings::SetTaskName(const QString& taskName)
1021{
1022 if (m_taskName != taskName){
1023 istd::CChangeNotifier notifier(this);
1024
1025 m_taskName = taskName;
1026 }
1027}
1028
1029
1030template <class UI>
1031QString TTaskCollectionEditorCompBase<UI>::TaskSettings::GetTaskDescription() const
1032{
1033 return m_taskDescription;
1034}
1035
1036
1037template <class UI>
1038void TTaskCollectionEditorCompBase<UI>::TaskSettings::SetTaskDescription(const QString& taskDescription)
1039{
1040 if (m_taskDescription != taskDescription){
1041 istd::CChangeNotifier notifier(this);
1042
1043 m_taskDescription = taskDescription;
1044 }
1045}
1046
1047
1048template <class UI>
1049bool TTaskCollectionEditorCompBase<UI>::TaskSettings::GetTaskEnabled() const
1050{
1051 return m_isEnabled;
1052}
1053
1054
1055template <class UI>
1056void TTaskCollectionEditorCompBase<UI>::TaskSettings::SetTaskEnabled(bool isEnabled)
1057{
1058 if (m_isEnabled!= isEnabled){
1059 istd::CChangeNotifier notifier(this);
1060
1061 m_isEnabled = isEnabled;
1062 }
1063}
1064
1065
1066template <class UI>
1067QByteArray TTaskCollectionEditorCompBase<UI>::TaskSettings::GetUserTaskId() const
1068{
1069 return m_userTaskId;
1070}
1071
1072
1073template <class UI>
1074void TTaskCollectionEditorCompBase<UI>::TaskSettings::SetUserTaskId(const QByteArray& userTaskId)
1075{
1076 if (m_userTaskId != userTaskId){
1077 istd::CChangeNotifier notifier(this);
1078
1079 m_userTaskId = userTaskId;
1080 }
1081}
1082
1083
1084template <class UI>
1085QByteArray TTaskCollectionEditorCompBase<UI>::TaskSettings::GetTaskInputId() const
1086{
1087 return m_inputId;
1088}
1089
1090
1091template <class UI>
1092void TTaskCollectionEditorCompBase<UI>::TaskSettings::SetTaskInputId(const QByteArray& inputId)
1093{
1094 if (m_inputId != inputId){
1095 istd::CChangeNotifier notifier(this);
1096
1097 m_inputId = inputId;
1098 }
1099}
1100
1101
1102template <class UI>
1103const imtbase::IObjectCollection* TTaskCollectionEditorCompBase<UI>::TaskSettings::GetTaskInputs() const
1104{
1105 Q_ASSERT(m_parentPtr != nullptr);
1106
1107 imthype::ITaskCollection* taskCollectionPtr = m_parentPtr->GetObservedObject();
1108 if (taskCollectionPtr != nullptr){
1109 return taskCollectionPtr->GetTaskInputs();
1110 }
1111
1112 return nullptr;
1113}
1114
1115
1116} // namespace imthypegui
1117
1118
virtual bool SetElementName(const Id &elementId, const QString &name, ilog::IMessageConsumer *logPtr=nullptr)=0
virtual QVariant GetElementInfo(const Id &elementId, int infoType, ilog::IMessageConsumer *logPtr=nullptr) const =0
virtual Ids GetElementIds(int offset=0, int count=-1, const iprm::IParamsSet *selectionParamsPtr=nullptr, ilog::IMessageConsumer *logPtr=nullptr) const =0
virtual bool SetElementEnabled(const Id &elementId, bool isEnabled=true, ilog::IMessageConsumer *logPtr=nullptr)=0
virtual bool SetElementDescription(const Id &elementId, const QString &description, ilog::IMessageConsumer *logPtr=nullptr)=0
virtual const istd::IChangeable * GetObjectPtr(const Id &objectId) const =0
virtual bool RemoveElements(const Ids &elementIds, const IOperationContext *operationContextPtr=nullptr)=0
virtual int GetOperationFlags(const Id &elementId=Id()) const =0
virtual Id InsertNewObject(const QByteArray &typeId, const QString &name, const QString &description, const istd::IChangeable *defaultValuePtr=nullptr, const Id &proposedElementId=Id(), const idoc::IDocumentMetaInfo *dataMetaInfoPtr=nullptr, const idoc::IDocumentMetaInfo *elementMetaInfoPtr=nullptr, const IOperationContext *operationContextPtr=nullptr)=0
virtual const iprm::IOptionsList * GetObjectTypesInfo() const =0
virtual Id GetObjectTypeId(const Id &objectId) const =0
virtual const imtbase::IObjectCollection * GetTaskInputs() const =0
virtual QByteArray GetUserTaskId(const QByteArray &taskUuid) const =0
virtual bool SetUserTaskId(const QByteArray &taskUuid, const QByteArray &userTaskId)=0
virtual const iinsp::ISupplier * GetTask(const QByteArray &taskId) const =0
virtual bool SetTaskInputId(const QByteArray &taskUuid, const QByteArray &inputId)=0
virtual QByteArray GetTaskInputId(const QByteArray &taskUuid) const =0