/**************************************************************************** Copyright (C) 2010-2012 the Office National des Forêts (ONF), France and the Association de Recherche Technologie et Sciences (ARTS), Ecole Nationale Suprieure d'Arts et Métiers (ENSAM), Cluny, France. All rights reserved. Contact : alexandre.piboule@onf.fr Developers : Michaël KREBS (ARTS/ENSAM) This file is part of Computree version 2.0. Computree is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Computree is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Computree. If not, see . *****************************************************************************/ #include "gstepmanager.h" #include "dm_guimanager.h" #include "cdm_configfile.h" #include "gstepmanageroptions.h" #include "ct_result/abstract/ct_abstractresult.h" #include "ct_step/abstract/ct_abstractsteploadfile.h" #include "ct_abstractstepplugin.h" #include "gaboutstepdialog.h" #include #include #include #include #include #include #include #include GStepManager::GStepManager(CDM_StepManager &stepManager, QWidget *parent) : QWidget(parent) { _stepManager = &stepManager; _delegate = new MyTreeDelegate(&m_treeView); m_proxy = new DM_StepManagerTreeViewProxy(this); m_proxy->setSourceModel(&_model); m_treeView.setModel(m_proxy); m_treeView.setItemDelegate(_delegate); m_treeView.setIndentation(12); QStringList header; header << tr("Nom"); header << tr("Debug"); header << tr("Temps"); _model.setHorizontalHeaderLabels(header); m_rootItem = new MyQStandardItem(NULL, NULL, MyQStandardItem::Text, tr("Flux d'étapes")); m_rootItem->setEditable(false); _model.invisibleRootItem()->appendRow(m_rootItem); #if QT_VERSION < QT_VERSION_CHECK(5,0,0) m_treeView.header()->setResizeMode(0, QHeaderView::ResizeToContents); #else m_treeView.header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); #endif m_treeView.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);" "}")); delete layout(); setLayout(new QVBoxLayout()); layout()->addWidget(&m_treeView); _contextMenuStep = new GTreeStepContextMenu(*_stepManager, this); m_treeView.setContextMenuPolicy(Qt::CustomContextMenu); //m_treeView.setExpandsOnDoubleClick(true); connect(_contextMenuStep, SIGNAL(executeSelectedStep(CT_VirtualAbstractStep*)), this, SLOT(executeStep(CT_VirtualAbstractStep*)), Qt::QueuedConnection); connect(_contextMenuStep, SIGNAL(executeModifySelectedStep(CT_VirtualAbstractStep*)), this, SLOT(executeModifyStep(CT_VirtualAbstractStep*)), Qt::QueuedConnection); connect(_contextMenuStep, SIGNAL(configureInputResultOfSelectedStep(CT_VirtualAbstractStep*)), this, SLOT(configureInputResultOfStep(CT_VirtualAbstractStep*)), Qt::QueuedConnection); connect(_contextMenuStep, SIGNAL(configureSelectedStep(CT_VirtualAbstractStep*)), this, SLOT(configureStep(CT_VirtualAbstractStep*)), Qt::QueuedConnection); connect(_contextMenuStep, SIGNAL(deleteSelectedStep(CT_VirtualAbstractStep*)), this, SLOT(removeStep(CT_VirtualAbstractStep*)), Qt::QueuedConnection); connect(_contextMenuStep, SIGNAL(loadResultOfSelectedStep(CT_AbstractStepSerializable*)), this, SLOT(loadResultStep(CT_AbstractStepSerializable*)), Qt::QueuedConnection); connect(_contextMenuStep, SIGNAL(expand()), this, SLOT(expandSelected())); connect(_contextMenuStep, SIGNAL(expandAll()), this, SLOT(expandAllTypeOfSelected())); connect(_contextMenuStep, SIGNAL(collapse()), this, SLOT(collapseSelected())); connect(_contextMenuStep, SIGNAL(collapseAll()), this, SLOT(collapseAllTypeOfSelected())); connect(_contextMenuStep, SIGNAL(locateSelectedStepInMenu(CT_VirtualAbstractStep*)), this, SIGNAL(locateStepInMenu(CT_VirtualAbstractStep*))); connect(_stepManager, SIGNAL(stepAdded(CT_VirtualAbstractStep*)), this, SLOT(stepAdded(CT_VirtualAbstractStep*)), Qt::DirectConnection); connect(_stepManager, SIGNAL(stepInserted(int,CT_VirtualAbstractStep*)), this, SLOT(stepInserted(int,CT_VirtualAbstractStep*)), Qt::DirectConnection); connect(_stepManager, SIGNAL(stepToBeRemoved(CT_VirtualAbstractStep*)), this, SLOT(stepToBeRemoved(CT_VirtualAbstractStep*)), Qt::DirectConnection); connect(_stepManager, SIGNAL(resultToBeSerialized(const CT_AbstractResult*)), this, SLOT(resultToBeSerialized(const CT_AbstractResult*)), Qt::DirectConnection); connect(&m_treeView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showViewContextMenu(QPoint)), Qt::QueuedConnection); connect(&m_treeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(indexDoubleClicked(QModelIndex)), Qt::QueuedConnection); connect(m_treeView.selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged(QItemSelection,QItemSelection))); connect(this, SIGNAL(addResult(QStandardItem*,CT_AbstractResult*)), this, SLOT(resultToAdd(QStandardItem*,CT_AbstractResult*)), Qt::QueuedConnection); connect(this, SIGNAL(removeResult(QStandardItem*,MyQStandardItem*)), this, SLOT(resultToRemove(QStandardItem*,MyQStandardItem*)), Qt::QueuedConnection); connect(this, SIGNAL(removeItem(QStandardItem*)), this, SLOT(itemToRemove(QStandardItem*)), Qt::QueuedConnection); m_treeView.expand(m_proxy->mapFromSource(_model.indexFromItem(getRootItem()))); } GStepManager::~GStepManager() { } CDM_StepManager* GStepManager::getStepManager() const { return _stepManager; } ////////////////// PRIVATE ///////////////// QList GStepManager::createItemsForStep(CT_VirtualAbstractStep &step) { QList list; // nom de l'tape MyQStandardItem *item = new MyQStandardItem(&step, NULL, MyQStandardItem::StepName, QString()); item->setToolTip(step.getToolTip()); item->setEditable(false); connect(item, SIGNAL(dataChanged(QStandardItem*)), this, SLOT(itemDataChanged(QStandardItem*))); connect(&step, SIGNAL(inProgress(int)), item, SLOT(setIntDataInvisible(int)), Qt::QueuedConnection); list.append(item); // debug item = new MyQStandardItem(&step, NULL, MyQStandardItem::StepDebug, QString("")); item->setEditable(false); item->setCheckable(true); item->setBoolData(step.isDebugModeOn()); connect(item, SIGNAL(dataChanged(QStandardItem*)), this, SLOT(itemDataChanged(QStandardItem*))); list.append(item); // temps coul item = new MyQStandardItem(&step, NULL, MyQStandardItem::StepElapsedTime, step.getExecuteTime()); item->setEditable(false); connect(&step, SIGNAL(elapsed(int)), item, SLOT(setIntData(int)), Qt::QueuedConnection); list.append(item); setStepItemBackgroundColor(step, list); return list; } QList GStepManager::createItemsForResult(CT_AbstractResult &res) { QList list; // nom du rsultat MyQStandardItem *item = new MyQStandardItem(NULL, &res, MyQStandardItem::ResultVisibility, res.getName()); item->setCheckable(true); item->setEditable(false); item->setEnabled(!res.isBusy()); connect(&res, SIGNAL(busyStateChanged(bool)), item, SLOT(slotSetDisabled(bool))); connect(item, SIGNAL(dataChanged(QStandardItem*)), this, SLOT(itemDataChanged(QStandardItem*))); item->setToolTip(QString("%1 (%2)").arg(res.getName()).arg(res.getToolTip())); list.append(item); item = new MyQStandardItem(NULL, &res, MyQStandardItem::ResultEmpty, QString("")); item->setEditable(false); list.append(item); item = new MyQStandardItem(NULL, &res, MyQStandardItem::ResultEmpty, QString("")); item->setEditable(false); list.append(item); setResultItemBackgroundColor(ResultInfo(res.getClearFromMemoryProgress() < 100, false), list); return list; } void GStepManager::setStepItemBackgroundColor(CT_VirtualAbstractStep &step, QList &list) { Q_UNUSED(step) QListIterator it(list); while(it.hasNext()) { QStandardItem *item = it.next(); item->setData(step.isManual() ? QColor(183, 225, 170) : QColor(170, 186, 225), Qt::BackgroundColorRole); } } void GStepManager::setResultItemBackgroundColor(ResultInfo info, QList &list) { QListIterator it(list); while(it.hasNext()) { QStandardItem *item = it.next(); if(info._isClearedFromMemory) { item->setData(QColor(236, 208, 209), Qt::BackgroundColorRole); } else if(info._isSerialized) { item->setData(QColor(206, 238, 211), Qt::BackgroundColorRole); } else { item->setData(QColor(220, 220, 220), Qt::BackgroundColorRole); } } } MyQStandardItem* GStepManager::findItem(CT_VirtualAbstractStep *step) { MyQStandardItem *item = getSelectedItem(); if((item != NULL) && (item->step() == step)) { return item; } return recursiveFindItem(step); } MyQStandardItem* GStepManager::findItem(CT_AbstractResult *res) { MyQStandardItem *item = getSelectedItem(); if((item != NULL) && (item->result() == res)) { return item; } return recursiveFindItem(res); } MyQStandardItem* GStepManager::getSelectedItem() { QModelIndexList list = m_treeView.selectionModel()->selectedRows(); if(!list.isEmpty()) return dynamic_cast(_model.itemFromIndex(m_proxy->mapToSource(list.first()))); return NULL; } MyQStandardItem* GStepManager::recursiveFindItem(CT_VirtualAbstractStep *step) { CT_VirtualAbstractStep* parent = step->parentStep(); QStandardItem *parentItem = NULL; if(parent != NULL) { // on recherche le parent parentItem = recursiveFindItem(parent); } // on est arriver au dbut de l'arbre else { // on recherche l'tape dans les enfants // de l'item root parentItem = getRootItem(); } if(parentItem != NULL) { int n = parentItem->rowCount(); for(int i=0; ichild(i); if(item->step() == step) { return item; } } } return NULL; } MyQStandardItem* GStepManager::recursiveFindItem(CT_AbstractResult *res) { CT_VirtualAbstractStep* parent = res->parentStep(); MyQStandardItem *stepItem = recursiveFindItem(parent); if(stepItem != NULL) { return getItemForResult(stepItem, res); } return NULL; } MyQStandardItem* GStepManager::getItemForResult(QStandardItem *stepItem, CT_AbstractResult *res) { int n = stepItem->rowCount(); for(int i=0; ichild(i); if(item->result() == res) { return item; } } return NULL; } QList GStepManager::getItemsForResult(QStandardItem *stepItem, CT_AbstractResult *res) { QList list; int n = stepItem->rowCount(); for(int i=0; ichild(i); if(item->result() == res) { int nc = _model.columnCount(); for(int j=0; jchild(i, j); list.append(item); } return list; } } return list; } MyQStandardItem *GStepManager::recursiveFindItemThatRepresentAStepForChild(MyQStandardItem *child) const { if(child->step() != NULL) return child; MyQStandardItem *parent = dynamic_cast(child->parentItem()); if(parent == NULL) return NULL; return recursiveFindItemThatRepresentAStepForChild(parent); } QStandardItem *GStepManager::getRootItem() const { return m_rootItem; } void GStepManager::stepDataChanged(MyQStandardItem *item) { CT_VirtualAbstractStep *step = item->step(); if(step != NULL) { switch(item->columnType()) { case MyQStandardItem::StepDebug : { bool debugOn = (item->checkState() == Qt::Checked); if(debugOn && !step->isDebuggable()) { item->setData(false, Qt::CheckStateRole); showMessageStepNotDebuggable(); } else if(step->isDebugModeOn() != debugOn) { getStepManager()->setStepDebugModeOn(step, debugOn); } break; } } } } void GStepManager::resultDataChanged(MyQStandardItem *item) { _mutexItemRes.lock(); CT_AbstractResult *res = item->result(); _mutexItemRes.unlock(); if(res != NULL) { switch(item->columnType()) { case MyQStandardItem::ResultVisibility : if(item->checkState() == Qt::Checked) { editItemDrawableModelOfResult(item->result()); } else { removeEditItemDrawableModelOfResult(item->result()); removeItemDrawableOfResult(item->result()); } break; } } } QString GStepManager::staticGetStepName(CT_VirtualAbstractStep &step) { CT_AbstractStepLoadFile *stepLF = dynamic_cast(&step); if(stepLF != NULL) { QString filePath = stepLF->getFilePath(); QFileInfo info(filePath); return QString("%1%2").arg(step.isSettingsModified() ? "*" : "").arg(((step.getStepCustomName() == step.getStepExtendedDisplayableName()) && !info.fileName().isEmpty()) ? info.fileName() : step.getStepCustomName()); } return QString("%1%2").arg(step.isSettingsModified() ? "*" : "").arg(step.getStepCustomName() == step.getStepExtendedDisplayableName() ? step.getStepExtendedDisplayableName() : step.getStepCustomName()); } void GStepManager::showMessageStepNotDebuggable() { QMessageBox::warning(this, tr("Debug"), tr("L'étape ne semble pas être débogable.")); } bool GStepManager::checkExecuteStepAndShowWarningMessage(CT_VirtualAbstractStep *step, bool debugMode) { bool continueExecution = true; if(_stepManager->getOptions().isAutoSaveEnable() && (step != NULL) && _stepManager->checkAutoSaveDisabledIfExecuteFromStep(*step)) { continueExecution = false; QMessageBox msg(QMessageBox::Warning, tr("Attention"), tr("La srialisation semble tre active, si vous executez" " l'opration partir de cette tape elle sera dsactive."), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, this); msg.setInformativeText(tr("Voulez-vous quand même continuer ?")); if(msg.clickedButton() == msg.button(QMessageBox::Yes)) { continueExecution = true; } } if(continueExecution) { bool oneStepInDebugMode = _stepManager->checkOneStepIsInDebugModeFromStep(step); if(oneStepInDebugMode && !debugMode) { continueExecution = false; QMessageBox msg(QMessageBox::Warning, tr("Attention"), tr("Une ou plusieurs étapes sont en mode debug or vous allez lancer" " les traitements en mode normal."), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, this); msg.setInformativeText(tr("Voulez-vous quand même continuer ?")); msg.exec(); if(msg.clickedButton() == msg.button(QMessageBox::Yes)) { continueExecution = true; } } else if(!oneStepInDebugMode && debugMode) { continueExecution = false; QMessageBox msg(QMessageBox::Warning, tr("Attention"), tr("Aucune étape n'est en mode debug or vous allez lancer" " les traitements dans ce mode."), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, this); msg.setInformativeText(tr("Voulez-vous quand même continuer ?")); msg.exec(); if(msg.clickedButton() == msg.button(QMessageBox::Yes)) { continueExecution = true; } } } return continueExecution; } bool GStepManager::configureStepAndAdd(CT_VirtualAbstractStep *stepToCopy, CT_VirtualAbstractStep *parentStep) { if((stepToCopy != NULL) && (stepToCopy->getPlugin() != NULL)) { if(!stepToCopy->acceptAddAfterThisStep(parentStep)) { QString error = tr("Impossible d'ajouter l'étape %1").arg(staticGetStepName(*stepToCopy)); if(parentStep != NULL) error += tr(" après l'étape %2 car elles ne sont pas compatible !").arg(staticGetStepName(*parentStep)); else error += tr(" à la racine !"); GUI_LOG->addErrorMessage(LogInterface::gui, error); } else { CT_VirtualAbstractStep *stepCopied = stepToCopy->getPlugin()->createNewInstanceOfStep(*stepToCopy, parentStep); if(stepCopied->showPreConfigurationDialog()) { if(stepCopied->initInResultModelList()) { if(stepCopied->showInputResultConfigurationDialog()) { if(stepCopied->showPostConfigurationDialog()) { if(stepCopied->initAfterConfiguration()) { _stepManager->addStep(stepCopied, parentStep); selectStep(stepCopied); return true; } } } } } delete stepCopied; } } return false; } void GStepManager::recursiveExpandCollapseItemOfStep(MyQStandardItem *item, bool expand) { if(item->step() != NULL) { if(expand) m_treeView.expand(m_proxy->mapFromSource(_model.indexFromItem(item))); else m_treeView.collapse(m_proxy->mapFromSource(_model.indexFromItem(item))); } int size = item->rowCount(); for(int i=0; ichild(i), expand); } void GStepManager::recursiveExpandCollapseItemOfResultsGroup(MyQStandardItem *item, bool expand) { if((item->step() == NULL) && (item->result() == NULL)) { if(expand) m_treeView.expand(m_proxy->mapFromSource(_model.indexFromItem(item))); else m_treeView.collapse(m_proxy->mapFromSource(_model.indexFromItem(item))); } int size = item->rowCount(); for(int i=0; ichild(i), expand); } void GStepManager::selectStep(CT_VirtualAbstractStep *step) { MyQStandardItem *item = findItem(step); if(item != NULL) m_treeView.selectionModel()->select(m_proxy->mapFromSource(_model.indexFromItem(item)), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); } void GStepManager::addStepToSelectedStepOrToRootAndConfigure(CT_VirtualAbstractStep *stepToCopy) { MyQStandardItem *item = getSelectedItem(); configureStepAndAdd(stepToCopy, (item == NULL) ? NULL : item->step()); } ////////////// PUBLIC SLOTS ////////////// void GStepManager::addOpenFileStep(QString filePath) { CDM_PluginManager *pluginManager = getStepManager()->getScriptManager()->getPluginManager(); if(pluginManager->isAPluginLoaded()) { QList stepLfList; CT_AbstractStepLoadFile *stepToCopy = NULL; 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 = NULL; 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(GStepManager::staticGetStepName(*stepLf) + " (" + pluginManager->getPluginName(stepLf->getPlugin()) + ")"); } if(dialog.exec() == 1) { stepToCopy = stepLfList.at(cb->currentIndex()); } } if(stepToCopy != NULL) { stepLfList.removeOne(stepToCopy); CT_VirtualAbstractStep *newStep = stepToCopy->getPlugin()->createNewInstanceOfStep(*stepToCopy, NULL); CT_AbstractStepLoadFile *newStepLF = dynamic_cast(newStep); if(newStepLF != NULL) { if(newStepLF->setFilePath(filePath)) { if(newStepLF->showPreConfigurationDialog()) { if(newStepLF->initInResultModelList()) { if(newStepLF->showInputResultConfigurationDialog()) { if(newStepLF->initAfterConfiguration()) { _stepManager->addStep(newStepLF); selectStep(newStepLF); return; } } } } } } delete newStep; } } } bool GStepManager::executeStep(CT_VirtualAbstractStep *step) { if(!_stepManager->isRunning()) { if(checkExecuteStepAndShowWarningMessage(step, false)) return _stepManager->executeStep(step); else return false; } return _stepManager->executeStep(step); } bool GStepManager::executeModifyStep(CT_VirtualAbstractStep *step) { if(!_stepManager->isRunning()) return _stepManager->executeModifyStep(step); return _stepManager->executeModifyStep(step); } bool GStepManager::executeOrForwardStepInDebugMode(CT_VirtualAbstractStep *step) { if(!_stepManager->isRunning()) { if(checkExecuteStepAndShowWarningMessage(step, true)) return _stepManager->executeOrForwardStepInDebugMode(step); else return false; } return _stepManager->executeOrForwardStepInDebugMode(step); } bool GStepManager::executeOrForwardStepFastInDebugMode(CT_VirtualAbstractStep *step) { if(!_stepManager->isRunning()) { if(checkExecuteStepAndShowWarningMessage(step, true)) return _stepManager->executeOrForwardStepFastInDebugMode(step); else return false; } return _stepManager->executeOrForwardStepFastInDebugMode(step); } bool GStepManager::executeOrForwardStepAutoInDebugMode(CT_VirtualAbstractStep *step) { if(!_stepManager->isRunning()) { if(checkExecuteStepAndShowWarningMessage(step, true)) return _stepManager->executeOrForwardStepAutoInDebugMode(step); else return false; } return _stepManager->executeOrForwardStepAutoInDebugMode(step); } bool GStepManager::configureInputResultOfStep(CT_VirtualAbstractStep *step) { if((step != NULL) && (!_stepManager->isRunning())) { if(step->showInputResultConfigurationDialog()) { return step->initAfterConfiguration(); } } return false; } bool GStepManager::configureStep(CT_VirtualAbstractStep *step) { if((step != NULL) && (!_stepManager->isRunning())) { if(step->showPostConfigurationDialog()) { return step->initAfterConfiguration(); } } return false; } bool GStepManager::removeStep(CT_VirtualAbstractStep *step) { if(step != NULL) { return GUI_MANAGER->asyncRemoveStep(*step, NULL); } return false; } bool GStepManager::loadResultStep(CT_AbstractStepSerializable *step) { if(step != NULL) { return GUI_MANAGER->asyncLoadResultStep(*step, NULL); } return false; } bool GStepManager::editItemDrawableModelOfResult(CT_AbstractResult *res) { if(res != NULL) { return GUI_MANAGER->editItemDrawableModelOfResult(*res); } return false; } bool GStepManager::removeEditItemDrawableModelOfResult(CT_AbstractResult *res) { if(res != NULL) { return GUI_MANAGER->removeEditItemDrawableModelOfResult(*res); } return false; } bool GStepManager::removeItemDrawableOfResult(CT_AbstractResult *res) { if(res != NULL) { return GUI_MANAGER->asyncRemoveAllItemDrawableOfResultFromView(*res, NULL); } return false; } void GStepManager::showStepManagerOptions() { QDialog dialog(this); dialog.setWindowTitle(tr("Configuration")); QVBoxLayout *layout = new QVBoxLayout(); GStepManagerOptions *widget = new GStepManagerOptions(&dialog); widget->setOptions(_stepManager->getOptions()); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); layout->addWidget(widget); layout->addWidget(buttonBox); delete dialog.layout(); dialog.setLayout(layout); connect(buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject())); if(dialog.exec()) { _stepManager->setOptions(widget->getOptions()); } } void GStepManager::setStepNameConfiguration(GStepViewDefault::DisplayNameConfigs config) { m_proxy->setStepNameConfig(config); } ////////////// PRIVATE SLOTS ////////////// void GStepManager::stepAdded(CT_VirtualAbstractStep *step) { CT_VirtualAbstractStep *parentStep = step->parentStep(); QStandardItem *item = NULL; if(parentStep == NULL) { item = getRootItem(); } else { item = findItem(parentStep); } if(item != NULL) { connect(step, SIGNAL(resultAdded(const CT_AbstractResult*)), this, SLOT(resultAdded(const CT_AbstractResult*)), Qt::DirectConnection); connect(step, SIGNAL(resultToBeClearedFromMemory(const CT_AbstractResult*)), this, SLOT(resultToBeClearedFromMemory(const CT_AbstractResult*)), Qt::DirectConnection); connect(step, SIGNAL(resultToBeRemoved(const CT_AbstractResult*)), this, SLOT(resultToBeRemoved(const CT_AbstractResult*)), Qt::DirectConnection); connect(step, SIGNAL(settingsModified()), this, SLOT(stepSettingsModified()), Qt::QueuedConnection); QList newItems = createItemsForStep(*step); item->appendRow(newItems); QModelIndex index = m_proxy->mapFromSource(_model.indexFromItem(newItems.first())); m_treeView.expand(index); m_treeView.selectionModel()->select(index, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect); } } void GStepManager::stepInserted(int row, CT_VirtualAbstractStep *step) { CT_VirtualAbstractStep *parentStep = step->parentStep(); QStandardItem *item = NULL; if(parentStep == NULL) { item = getRootItem(); } else { item = findItem(parentStep); } if(item != NULL) { connect(step, SIGNAL(resultAdded(CT_AbstractResult*)), this, SLOT(resultAdded(CT_AbstractResult*)), Qt::DirectConnection); connect(step, SIGNAL(resultToBeClearedFromMemory(CT_AbstractResult*)), this, SLOT(resultToBeClearedFromMemory(CT_AbstractResult*)), Qt::DirectConnection); connect(step, SIGNAL(resultToBeRemoved(CT_AbstractResult*)), this, SLOT(resultToBeRemoved(CT_AbstractResult*)), Qt::DirectConnection); connect(step, SIGNAL(settingsModified()), this, SLOT(stepSettingsModified()), Qt::QueuedConnection); QList list = createItemsForStep(*step); if(row > 0) { item->insertRow(row, list); } else { QStandardItem *newItem = list.first(); int nResult = ((MyQStandardItem*)item)->step()->nResult(); while(item->rowCount() > nResult) { QList tmpList = item->takeRow(item->rowCount()-1); newItem->insertRow(0, tmpList); } item->insertRow(item->rowCount(), list); } m_treeView.expandAll(); } } void GStepManager::stepToBeRemoved(CT_VirtualAbstractStep *step) { QStandardItem *item = findItem(step); if(item != NULL) { // on emet un signal pour qu'on supprime // l'item dans une boucle d'vnement. Que se passerai-t-il // si on ne faisait pas a : lorsqu'un thread supprime une tape // du step manager et qu'on reoit directement le signal, // on n'est pas dans la boucle d'vnement donc la vue est peut tre // en train d'tre mis jour, donc si on supprime l'item pendant la // mise jour du qteeview il peut y avoir un plantage. emit removeItem(item); } } void GStepManager::stepSettingsModified() { CT_VirtualAbstractStep *step = dynamic_cast(sender()); if(step != NULL) { MyQStandardItem *item = findItem(step); if(item != NULL) { item->setDataWithoutSignal(GStepManager::staticGetStepName(*step), Qt::DisplayRole); item->setToolTip(step->getToolTip()); } } } void GStepManager::resultAdded(const CT_AbstractResult *res) { QStandardItem *item = findItem(res->parentStep()); if(item != NULL) { _mutexResList.lock(); _resToBeAddedList.append((CT_AbstractResult*)res); _mutexResList.unlock(); // on emet un signal pour les mmes raisons que // lors de la suppression d'tape emit addResult(item, (CT_AbstractResult*)res); } } void GStepManager::resultToBeClearedFromMemory(const CT_AbstractResult *res) { QStandardItem *item = findItem((CT_AbstractResult*)res); if(item != NULL) { QStandardItem *parent = item->parent(); int row = item->row(); int col = parent->columnCount(); QList list; for(int i=0; ichild(row, i)); } setResultItemBackgroundColor(ResultInfo(true, false), list); } } void GStepManager::resultToBeRemoved(const CT_AbstractResult *res) { // Dans un cas bien particulier il peut y avoir une // erreur d'accs au rsultat, ce cas est le suivant : // // Si on a reu un signal qu'on doit ajouter un rsultat, // on emet un signal d'ajout du rsultat. Si juste aprs on reoit // un signal qu'un rsultat va tre supprim on emet un signal pour // supprimer le rsultat. SI avant de recevoir NOTRE signal d'ajout // du rsultat le rsultat est supprimer alors on aura une erreur // d'accs mmoire si on essaye de crer des items pour ce rsultat. // // C'est pourquoi j'ai cr cette liste qui permet de vrifier si on // a reu aussi un signal de suppression du rsultat aprs le signal d'ajout // comme a on ne cre pas le rsultat. // // // Je rapelle qu'on reoit un signal de l'tape quelle va ajouter un rsultat // en Qt::DirectConnection et qu'on met un signal en Qt::QueuedConnection // pour ce remettre dans l'event loop de Qt et ne pas avoir d'erreur si la vue // est en train de ce mettre jour. _mutexResList.lock(); _resToBeAddedList.removeOne((CT_AbstractResult*)res); _mutexResList.unlock(); QStandardItem *item = findItem(res->parentStep()); MyQStandardItem *itemRes = NULL; QList itemResList = getItemsForResult(item, (CT_AbstractResult*)res); QListIterator it(itemResList); if(it.hasNext()) { itemRes = it.next(); it.toFront(); while(it.hasNext()) { _mutexItemRes.lock(); it.next()->removeResult(); _mutexItemRes.unlock(); } } if((item != NULL) && (itemRes != NULL)) { // on emet un signal pour les mmes raisons que // lors de la suppression d'tape emit removeResult(item, itemRes); } } void GStepManager::resultToBeSerialized(const CT_AbstractResult *res) { QStandardItem *item = findItem((CT_AbstractResult*)res); if(item != NULL) { QStandardItem *parent = item->parent(); int row = item->row(); int col = parent->columnCount(); QList list; for(int i=0; ichild(row, i)); } setResultItemBackgroundColor(ResultInfo(false, true), list); } } void GStepManager::itemDataChanged(QStandardItem *item) { MyQStandardItem *myItem = (MyQStandardItem*)item; if(myItem->step() != NULL) { stepDataChanged(myItem); } else if(myItem->result() != NULL) { resultDataChanged(myItem); } } void GStepManager::indexDoubleClicked(QModelIndex index) { MyQStandardItem *myItem = dynamic_cast(_model.itemFromIndex(m_proxy->mapToSource(index))); if((myItem != NULL) && (myItem->result() != NULL)) { QStandardItem *it = ((QStandardItem*)myItem)->parent()->child(myItem->row(), MyQStandardItem::ResultVisibility-MyQStandardItem::BeginIndexForResult); if(it->isEnabled()) it->setCheckState(it->checkState() == Qt::Checked ? Qt::Unchecked : Qt::Checked); } else if((myItem != NULL) && (myItem->step() != NULL) && (myItem->columnType() != MyQStandardItem::StepName)) { GAboutStepDialog dialog(myItem->step()); dialog.exec(); } } void GStepManager::resultToAdd(QStandardItem *parentItem, CT_AbstractResult *res) { _mutexResList.lock(); int index; // si le rsultat est toujours dans la liste. if((index = _resToBeAddedList.indexOf(res)) >= 0) { QList newItems = createItemsForResult(*res); parentItem->insertRow(0, newItems); _resToBeAddedList.removeAt(index); m_treeView.expand(m_proxy->mapFromSource(_model.indexFromItem(newItems.first()))); } _mutexResList.unlock(); } void GStepManager::resultToRemove(QStandardItem *parentItem, MyQStandardItem *resItem) { if(resItem != NULL) { parentItem->removeRow(resItem->row()); } } void GStepManager::itemToRemove(QStandardItem *item) { if(item->parent() != NULL) { item->parent()->removeRow(item->row()); } else { getRootItem()->removeRow(item->row()); } } void GStepManager::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { MyQStandardItem *item = getSelectedItem(); // if the item represent a step if((item != NULL) && (item->step() != NULL)) emit stepSelected(item->step()); else if(item != NULL){ // if not we get the first parent that represent a step and select it if we find it MyQStandardItem *itemOfAStep = recursiveFindItemThatRepresentAStepForChild(item); if(itemOfAStep == NULL) emit stepSelected(NULL); else selectStep(itemOfAStep->step()); } else { emit stepSelected(NULL); } } void GStepManager::expandSelected() { QModelIndexList list = m_treeView.selectionModel()->selectedRows(); if(!list.isEmpty()) m_treeView.expand(list.first()); } void GStepManager::expandAllTypeOfSelected() { MyQStandardItem *item = getSelectedItem(); if(item != NULL) { if(item->step() != NULL) { QStandardItem *root = getRootItem(); int size = root->rowCount(); for(int i=0; ichild(i), true); } else if(item->result() == NULL) { QStandardItem *root = getRootItem(); int size = root->rowCount(); for(int i=0; ichild(i), true); } } } void GStepManager::collapseSelected() { QModelIndexList list = m_treeView.selectionModel()->selectedRows(); if(!list.isEmpty()) m_treeView.collapse(list.first()); } void GStepManager::collapseAllTypeOfSelected() { MyQStandardItem *item = getSelectedItem(); if(item != NULL) { if(item->step() != NULL) { QStandardItem *root = getRootItem(); int size = root->rowCount(); for(int i=0; ichild(i), false); } else if(item->result() == NULL) { QStandardItem *root = getRootItem(); int size = root->rowCount(); for(int i=0; ichild(i), false); } } } void GStepManager::removeAllStepFromRoot() { GUI_MANAGER->asyncRemoveAllStep(NULL); } void GStepManager::showViewContextMenu(const QPoint &point) { MyQStandardItem *item = getSelectedItem(); if(item != NULL) { if(item->step() != NULL) { _contextMenuStep->setSelectedStep(item->step()); _contextMenuStep->exec(m_treeView.viewport()->mapToGlobal(point)); } else if(item->result() == NULL) { QMenu menu(this); menu.addAction(QIcon(":/Icones/Icones/delete.png"), tr("Supprimer toutes les étapes"), this, SLOT(removeAllStepFromRoot())); menu.addAction(QIcon(":/Icones/Icones/expand.png"), tr("Déplier"), this, SLOT(expandSelected())); menu.addAction(QIcon(":/Icones/Icones/collapse.png"), tr("Replier"), this, SLOT(collapseSelected())); menu.exec(m_treeView.viewport()->mapToGlobal(point)); } } }