#include "gstepmanager2.h" #include "ui_gstepmanager2.h" #include "batchdialog.h" #include "cdm_stepmanager.h" #include "cdm_pluginmanager.h" #include "cdm_scriptmanagerabstract.h" #include "ct_step/abstract/ct_abstractsteploadfile.h" #include "ct_result/abstract/ct_abstractresult.h" #include "ct_abstractstepplugin.h" #include #include #include #include #include #include #include #include #include GStepManager2::GStepManager2(QWidget *parent) : m_stepManager(*static_cast(parent)->getBatchCore().getStepManager()), QWidget(parent), ui(new Ui::GStepManager2) { ui->setupUi(this); setStepNameConfiguration(DNC_StepShortDescription); m_protectTreeMutex = new QMutex(QMutex::Recursive); m_updateTreeTimer.setInterval(33); m_updateTreeTimer.setSingleShot(false); ui->treeWidget->topLevelItem(0)->setData(0, Qt::UserRole, DT_Others); #if QT_VERSION < QT_VERSION_CHECK(5,0,0) ui->treeWidget->header()->setResizeMode(0, QHeaderView::ResizeToContents); #else ui->treeWidget->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); #endif ui->treeWidget->setStyleSheet(QString("QTreeView::item:selected{" "color: rgb(255, 255, 255);" "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #F3C870, stop: 1 #BDA757);" "}")); connect(&m_updateTreeTimer, SIGNAL(timeout()), this, SLOT(updateTree()), Qt::QueuedConnection); connect(ui->treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), Qt::DirectConnection); connect(&m_stepManager, SIGNAL(stepAdded(CT_VirtualAbstractStep*)), this, SLOT(stepAdded(CT_VirtualAbstractStep*)), Qt::QueuedConnection); connect(&m_stepManager, SIGNAL(stepInserted(int,CT_VirtualAbstractStep*)), this, SLOT(stepInserted(int,CT_VirtualAbstractStep*)), Qt::QueuedConnection); connect(&m_stepManager, SIGNAL(stepToBeRemoved(CT_VirtualAbstractStep*)), this, SLOT(stepToBeRemoved(CT_VirtualAbstractStep*)), Qt::DirectConnection); m_updateTreeTimer.start(); } GStepManager2::~GStepManager2() { delete ui; delete m_protectTreeMutex; } QString GStepManager2::staticGetStepNameFromConfiguration(CT_VirtualAbstractStep *step, const DisplayNameConfigs &config, bool showStepID) { QString name = ""; QString shortDescription = " " + step->description() + " "; QString key = " " + step->pluginStaticCastT<>()->getKeyForStep(*step) + " "; QString displayableName = " " + step->displayableCustomName()+ " "; if(config.testFlag(DNC_StepShortDescription) ) name += shortDescription; if(config.testFlag(DNC_StepKey) && !name.contains(key)) { if(!name.isEmpty()) name += "/"; name += key; } if(config.testFlag(DNC_StepDisplayableName) && !name.contains(displayableName)) { if(!name.isEmpty()) name += "/"; name += displayableName; } if (showStepID) name = QString(" %1 -").arg(step->uniqueID()) + name; return name; } void GStepManager2::setStepNameConfiguration(DisplayNameConfigs config) { m_stepNameConfig = config; } void GStepManager2::addOpenFileStep(QString filePath) { QMutexLocker locker(m_protectTreeMutex); CDM_PluginManager *pluginManager = m_stepManager.getScriptManager()->getPluginManager(); if(pluginManager->isAPluginLoaded()) { QList stepLfList; CT_AbstractStepLoadFile *stepToCopy = nullptr; int count = pluginManager->countPluginLoaded(); for(int i =0; i steps = pluginManager->getPlugin(i)->getOpenFileStep(filePath); if(!steps.isEmpty()) { stepToCopy = steps.first(); stepLfList.append(steps); } } if(stepLfList.size() > 1) { stepToCopy = nullptr; QDialog dialog(this); dialog.setLayout(new QVBoxLayout()); QComboBox *cb = new QComboBox(&dialog); QDialogButtonBox *dbb = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); connect(dbb, SIGNAL(accepted()), &dialog, SLOT(accept())); connect(dbb, SIGNAL(rejected()), &dialog, SLOT(reject())); dialog.layout()->addWidget(cb); dialog.layout()->addWidget(dbb); QListIterator itLf(stepLfList); while(itLf.hasNext()) { CT_AbstractStepLoadFile *stepLf = itLf.next(); cb->addItem(staticGetStepNameFromConfiguration(stepLf, m_stepNameConfig, true) + " (" + pluginManager->getPluginName(stepLf->pluginStaticCastT<>()) + ")"); } if(dialog.exec() == 1) { stepToCopy = stepLfList.at(cb->currentIndex()); } } if(stepToCopy != nullptr) { stepLfList.removeOne(stepToCopy); CT_VirtualAbstractStep *newStep = stepToCopy->pluginStaticCastT<>()->createNewInstanceOfStep(*stepToCopy, nullptr); CT_AbstractStepLoadFile *newStepLF = dynamic_cast(newStep); if(newStepLF != nullptr) { if(newStepLF->setFilePath(filePath)) { if(newStepLF->showPreInputConfigurationDialog()) { if(newStepLF->showInputResultConfigurationDialog()) { if(newStepLF->showInputResultConfigurationDialog()) { if(newStepLF->finalizeConfiguration()) { m_stepManager.addStep(newStepLF); return; } } } } } } delete newStep; } } } void GStepManager2::executeStep(CT_VirtualAbstractStep* step) { QMutexLocker locker(m_protectTreeMutex); if(!m_stepManager.isRunning()) { m_stepManager.executeStep(step); return; } m_stepManager.executeStep(step); } void GStepManager2::executeOrForwardStepInDebugMode(CT_VirtualAbstractStep *step) { QMutexLocker locker(m_protectTreeMutex); if(!m_stepManager.isRunning()) { m_stepManager.executeOrForwardStepInDebugMode(step); return; } m_stepManager.executeOrForwardStepInDebugMode(step); } void GStepManager2::executeOrForwardStepFastInDebugMode(CT_VirtualAbstractStep *step) { QMutexLocker locker(m_protectTreeMutex); if(!m_stepManager.isRunning()) { m_stepManager.executeOrForwardStepFastInDebugMode(step); return; } m_stepManager.executeOrForwardStepFastInDebugMode(step); } void GStepManager2::executeOrForwardStepAutoInDebugMode(CT_VirtualAbstractStep *step) { QMutexLocker locker(m_protectTreeMutex); if(!m_stepManager.isRunning()) { m_stepManager.executeOrForwardStepAutoInDebugMode(step); return; } m_stepManager.executeOrForwardStepAutoInDebugMode(step); } void GStepManager2::addStepToCurrentStepOrToRootAndConfigure(CT_VirtualAbstractStep* stepToCopy) { QMutexLocker locker(m_protectTreeMutex); if((stepToCopy != nullptr) && (stepToCopy->plugin() != nullptr)) { CT_VirtualAbstractStep* parentStep = extractStepFromItem(ui->treeWidget->currentItem()); if(!stepToCopy->acceptAddAfterThisStep(parentStep)) { QString error = tr("Impossible d'ajouter l'étape %1").arg(staticGetStepNameFromConfiguration(stepToCopy, m_stepNameConfig, true)); if(parentStep != nullptr) error += tr(" après l'étape %2 car elles ne sont pas compatible !").arg(staticGetStepNameFromConfiguration(parentStep, m_stepNameConfig, true)); else error += tr(" à la racine !"); qDebug().noquote() << error; } else { CT_VirtualAbstractStep *stepCopied = stepToCopy->pluginStaticCastT()->createNewInstanceOfStep(*stepToCopy, parentStep); if(stepCopied->showPreInputConfigurationDialog()) { if(stepCopied->showInputResultConfigurationDialog()) { if(stepCopied->showInputResultConfigurationDialog()) { if(stepCopied->showPostConfigurationDialog()) { if(stepCopied->finalizeConfiguration()) { m_stepManager.addStep(stepCopied, parentStep); return; } } } } } delete stepCopied; } } } CT_VirtualAbstractStep* GStepManager2::extractStepFromItem(QTreeWidgetItem *item) { if(item == nullptr) return nullptr; if(item->data(0, Qt::UserRole).toInt() == DT_Step) return static_cast(item->data(0, Qt::UserRole+1).value()); return nullptr; } CT_AbstractResult* GStepManager2::extractResultFromItem(QTreeWidgetItem *item) { if(item == nullptr) return nullptr; if(item->data(0, Qt::UserRole).toInt() == DT_Result) return static_cast(item->data(0, Qt::UserRole+1).value()); return nullptr; } void GStepManager2::setStepToItem(CT_VirtualAbstractStep *step, QTreeWidgetItem *item) { item->setData(0, Qt::UserRole, DT_Step); item->setData(0, Qt::UserRole+1, QVariant::fromValue((void*)step)); } void GStepManager2::setResultToItem(CT_AbstractResult *result, QTreeWidgetItem *item) { item->setData(0, Qt::UserRole, DT_Result); item->setData(0, Qt::UserRole+1, QVariant::fromValue((void*)result)); } void GStepManager2::recursiveUpdateTree(QTreeWidgetItem *parent) { for(int i=0; ichildCount(); ++i) { QTreeWidgetItem* child = parent->child(i); const int type = child->data(0, Qt::UserRole).toInt(); bool updated = false; if(type == DT_Step) updated = updateStepInTree(child); else if(type == DT_Result) updated = updateResultInTree(child); if(updated) recursiveUpdateTree(child); else --i; } } void GStepManager2::addResultsThatMustBe() { QMutexLocker locker(m_protectTreeMutex); QMutableHashIterator > it(m_resultsToAdd); while(it.hasNext()) { it.next(); const QPair pair = it.value(); QTreeWidgetItem* parentItem = m_steps.value(pair.first); if(parentItem != nullptr) { parentItem->insertChild(0, pair.second); m_results.insert(it.key(), pair.second); ui->treeWidget->expandItem(parentItem); } else { delete pair.second; } it.remove(); } } QTreeWidgetItem* GStepManager2::createAndAddItemForStep(CT_VirtualAbstractStep *step, QTreeWidgetItem *parent, int insertRow) { QTreeWidgetItem* item = new QTreeWidgetItem(); setStepToItem(step, item); if(insertRow < 0) parent->addChild(item); else parent->insertChild(insertRow, item); ui->treeWidget->setItemWidget(item, 1, new QLabel("")); ui->treeWidget->expandItem(parent); ui->treeWidget->setCurrentItem(item); updateStepInTree(item); connect(step, SIGNAL(resultAdded(const CT_AbstractResult*)), this, SLOT(resultAdded(const CT_AbstractResult*)), Qt::DirectConnection); connect(step, SIGNAL(resultToBeRemoved(const CT_AbstractResult*)), this, SLOT(resultToBeRemoved(const CT_AbstractResult*)), Qt::DirectConnection); return item; } QTreeWidgetItem *GStepManager2::createItemForResult(const CT_AbstractResult* result) { QTreeWidgetItem* item = new QTreeWidgetItem(); item->setCheckState(0, Qt::Unchecked); setResultToItem((CT_AbstractResult*)result, item); updateResultInTree(item); return item; } void GStepManager2::currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) { Q_UNUSED(previous) emit currentStepChanged(extractStepFromItem(current)); } void GStepManager2::expandCurrentItem() { QTreeWidgetItem* item = ui->treeWidget->currentItem(); if(item != nullptr) ui->treeWidget->expandItem(item); } void GStepManager2::collapseCurrentItem() { QTreeWidgetItem* item = ui->treeWidget->currentItem(); if(item != nullptr) ui->treeWidget->collapseItem(item); } void GStepManager2::expandAllTypeSameAsCurrentItem() { expandOrCollapseAllTypeSameAsCurrentItem(true); } void GStepManager2::collapseAllTypeSameAsCurrentItem() { expandOrCollapseAllTypeSameAsCurrentItem(false); } void GStepManager2::stepAdded(CT_VirtualAbstractStep *step) { // GUI thread QMutexLocker locker(m_protectTreeMutex); QTreeWidgetItem* parentItem = ui->treeWidget->topLevelItem(0); if(step->parentStep() != nullptr) parentItem = m_steps.value(step->parentStep()); if(parentItem != nullptr) { QTreeWidgetItem* child = createAndAddItemForStep(step, parentItem); m_steps.insert(step, child); } } void GStepManager2::stepInserted(int row, CT_VirtualAbstractStep *step) { // GUI thread QMutexLocker locker(m_protectTreeMutex); QTreeWidgetItem* parentItem = m_steps.value(step, nullptr); if(parentItem != nullptr) { QTreeWidgetItem* child = createAndAddItemForStep(step, parentItem, row); m_steps.insert(step, child); } } void GStepManager2::stepToBeRemoved(CT_VirtualAbstractStep* step) { // NOT GUI thread ! QMutexLocker locker(m_protectTreeMutex); setStepToItem(nullptr, m_steps.take(step)); } void GStepManager2::resultAdded(const CT_AbstractResult* result) { // NOT GUI thread ! QMutexLocker locker(m_protectTreeMutex); QTreeWidgetItem* parentItem = m_steps.value(static_cast(result->parentStep())); if(parentItem != nullptr) { QTreeWidgetItem* child = createItemForResult(result); m_resultsToAdd.insert((CT_AbstractResult*)result, qMakePair(static_cast(result->parentStep()), child)); } } void GStepManager2::resultToBeRemoved(const CT_AbstractResult *result) { // NOT GUI thread ! QMutexLocker locker(m_protectTreeMutex); QTreeWidgetItem* item = m_results.take((CT_AbstractResult*)result); if(item == nullptr) delete m_resultsToAdd.take((CT_AbstractResult*)result).second; else setResultToItem(nullptr, item); } void GStepManager2::updateTree() { // GUI thread QTreeWidgetItem* workflowRoot = ui->treeWidget->topLevelItem(0); recursiveUpdateTree(workflowRoot); addResultsThatMustBe(); } bool GStepManager2::updateResultInTree(QTreeWidgetItem* child) { QString name; bool isClearedFromMemory; bool isBusy; if(extractResultInformationFromTree(child, name, isClearedFromMemory, isBusy)) { child->setDisabled(isBusy); child->setText(0, name); for(int i=0; itreeWidget->columnCount(); ++i) { if(isClearedFromMemory) child->setBackground(i, QColor(236, 208, 209)); else child->setBackground(i, QColor(220, 220, 220)); } return true; } if(child->parent() != nullptr) child->parent()->removeChild(child); delete child; return false; } bool GStepManager2::extractResultInformationFromTree(QTreeWidgetItem *child, QString &name, bool& isClearedFromMemory, bool &isBusy) { QMutexLocker locker(m_protectTreeMutex); CT_AbstractResult* result = extractResultFromItem(child); if(result != nullptr) { name = result->displayableName(); isClearedFromMemory = result->isClearedFromMemory(); isBusy = result->isBusy(); } return (result != nullptr); } bool GStepManager2::updateStepInTree(QTreeWidgetItem* child) { QString name; QString filepath; int progress; bool isSettingsModified; bool debugModeOn; int executeTime; bool isManual; if(extractStepInformationFromTree(child, name, filepath, progress, isSettingsModified, debugModeOn, isManual, executeTime)) { updateStepNameInTree(child, name, isSettingsModified, progress, filepath); updateStepDebugInTree(child, debugModeOn); updateStepExecuteTimeInTree(child, executeTime); updateStepColorsInTree(child, isManual); return true; } if(child->parent() != nullptr) child->parent()->removeChild(child); delete child; return false; } bool GStepManager2::extractStepInformationFromTree(QTreeWidgetItem* child, QString& name, QString& filepath, int& progress, bool& isSettingsModified, bool& debugModeOn, bool& isManual, int& executeTime) { QMutexLocker locker(m_protectTreeMutex); CT_VirtualAbstractStep* step = extractStepFromItem(child); if(step != nullptr) { filepath = ""; name = staticGetStepNameFromConfiguration(step, m_stepNameConfig, true); debugModeOn = step->isDebugModeOn(); progress = step->progressValue(); isSettingsModified = step->isSettingsModified(); executeTime = step->executeTime(); isManual = step->isManual(); CT_AbstractStepLoadFile *stepLF = dynamic_cast(step); if(stepLF != nullptr) filepath = stepLF->filePath(); } return (step != nullptr); } void GStepManager2::updateStepNameInTree(QTreeWidgetItem* child, QString name, const bool& isSettingsModified, const int& progress, const QString& filepath) { if(progress != 100) name = "(" + QString().setNum(progress) + "%)" + name; if(!filepath.isEmpty()) { QFileInfo info(filepath); if(!info.fileName().isEmpty()) name += tr("( %1 )").arg(info.fileName()); } child->setText(0, name); if(isSettingsModified && ((progress == 0) || (progress == 100))) child->setIcon(0, QIcon(":/Icones/Icones/view-refresh.png")); else if(progress == 100) child->setIcon(0, QIcon(":/Icones/Icones/valid.png")); else child->setIcon(0, QIcon(":/Icones/Icones/in_progress.png")); } void GStepManager2::updateStepDebugInTree(QTreeWidgetItem* child, bool debugModeOn) { QLabel* debugLabel = static_cast(ui->treeWidget->itemWidget(child, 1)); if(debugModeOn) debugLabel->setPixmap(QPixmap(":/Icones/Icones/debug_on.png")); else debugLabel->setPixmap(QPixmap(":/Icones/Icones/debug_off.png")); } void GStepManager2::updateStepExecuteTimeInTree(QTreeWidgetItem* child, int executeTime) { const int hour = executeTime/3600000; executeTime -= hour*3600000; const int min = executeTime/60000; executeTime -= min*60000; const int sec = executeTime/1000; executeTime -= sec*1000; const int ms = executeTime; child->setText(2, QString("%1h:%2m:%3s:%4ms").arg(hour).arg(min).arg(sec).arg(ms)); } void GStepManager2::updateStepColorsInTree(QTreeWidgetItem* child, bool isManual) { for(int i=0; itreeWidget->columnCount(); ++i) { child->setBackground(i, isManual ? QColor(183, 225, 170) : QColor(170, 186, 225)); } } void GStepManager2::expandOrCollapseAllTypeSameAsCurrentItem(bool expand) { QQueue items; QTreeWidgetItem* item = ui->treeWidget->currentItem(); if(item != nullptr) { const int type = item->data(0, Qt::UserRole).toInt(); items.enqueue(item); while(!items.isEmpty()) { item = items.dequeue(); if(expand) ui->treeWidget->expandItem(item); else ui->treeWidget->collapseItem(item); const int size = item->childCount(); for(int i=0; ichild(i); if(child->data(0, Qt::UserRole).toInt() == type) items.enqueue(child); } } } }