/* Copyright 2006-2015 The QElectroTech Team This file is part of QElectroTech. QElectroTech 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 2 of the License, or (at your option) any later version. QElectroTech 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 QElectroTech. If not, see . */ #include "genericpanel.h" #include #include "qetproject.h" #include "diagram.h" #include "elementscollection.h" #include "elementscategory.h" #include "elementdefinition.h" #include "titleblock/templatescollection.h" #include "titleblock/templatelocation.h" #include "elementslocation.h" #include "qeticons.h" #include "elementscollectioncache.h" #include "qetapp.h" /** Constructor @param parent Parent QWidget */ GenericPanel::GenericPanel(QWidget *parent) : QTreeWidget(parent), cache_(0), first_activation_(true) { header() -> hide(); setIconSize(QSize(50, 50)); } /** Destructor */ GenericPanel::~GenericPanel() { } /** @return the elements cache currently used, or 0 if none has been set. */ ElementsCollectionCache *GenericPanel::elementsCache() { return(cache_); } /** @return the elements cache to be used to render elements collection. If no cache has been explicitly set using setElementsCache(), this method builds a basic cache named "genericpanel.sqlite" in the current working directory. */ ElementsCollectionCache *GenericPanel::getElementsCache() { if (!cache_) { // build a default cache QString cache_path = "./genericpanel.sqlite"; cache_ = new ElementsCollectionCache(cache_path, this); cache_->setLocale(QETApp::langFromSetting()); } return(cache_); } /** @return the type of the current item */ int GenericPanel::currentItemType() { QTreeWidgetItem *current_qtwi = currentItem(); if (!current_qtwi) return(0); return(current_qtwi -> type()); } QETProject *GenericPanel::projectForItem(QTreeWidgetItem *item) const { if (item && item -> type() == QET::Project) { return(valueForItem(item)); } return(0); } /** */ Diagram *GenericPanel::diagramForItem(QTreeWidgetItem *item) const { if (item && item -> type() == QET::Diagram) { return(valueForItem(item)); } return(0); } /** */ TitleBlockTemplateLocation GenericPanel::templateLocationForItem(QTreeWidgetItem *item) const { if (item && item -> type() & QET::TitleBlockTemplatesCollectionItem) { return(valueForItem(item)); } return(TitleBlockTemplateLocation()); } /** */ ElementsLocation GenericPanel::elementLocationForItem(QTreeWidgetItem *item) const { if (item && item -> type() & QET::ElementsCollectionItem) { return(valueForItem(item)); } return(ElementsLocation()); } /** */ QETProject *GenericPanel::selectedProject() const { return(projectForItem(currentItem())); } /** */ Diagram *GenericPanel::selectedDiagram() const { return(diagramForItem(currentItem())); } /** */ TitleBlockTemplateLocation GenericPanel::selectedTemplateLocation() const { return(templateLocationForItem(currentItem())); } /** */ ElementsLocation GenericPanel::selectedElementLocation() const { return(elementLocationForItem(currentItem())); } /** @param cache New cache to be used to render elements. @param previous if non-zero, this pointer will be set to the previously used cache @return true if the cache was changed, false otherwise (it may happen if the provided cache is already the one being used). */ bool GenericPanel::setElementsCache(ElementsCollectionCache *cache, ElementsCollectionCache **previous) { if (cache == cache_) return(false); if (previous) { *previous = cache_; } cache_ = cache; return(true); } /** */ QTreeWidgetItem *GenericPanel::addProject(QETProject *project, QTreeWidgetItem *parent_item, PanelOptions options) { if (!project) return(0); bool creation_required; QTreeWidgetItem *project_qtwi = getItemForProject(project, &creation_required); updateProjectItem(project_qtwi, project, options, creation_required); reparent(project_qtwi, parent_item); fillProjectItem(project_qtwi, project, options, creation_required); return(project_qtwi); } /** @param project A standard project. @return the tree item representing the provided project or 0 if this project does not appear within this panel. */ QTreeWidgetItem *GenericPanel::itemForProject(QETProject *project) { if (!project) return(0); return(projects_.value(project, 0)); } /** @param project A standard project. @param created if provided with a pointer to a boolean, this method will update it to reflect whether the returned item has been freshly created or not. @return the tree item representing the provided project. If it does not appear within this panel, it is created. */ QTreeWidgetItem *GenericPanel::getItemForProject(QETProject *project, bool *created) { if (!project) return(0); QTreeWidgetItem *project_qtwi = projects_.value(project, 0); if (project_qtwi) { if (created) *created = false; return(project_qtwi); } project_qtwi = makeItem(QET::Project); if (created) *created = true; return(project_qtwi); } /** */ QTreeWidgetItem *GenericPanel::updateProjectItem(QTreeWidgetItem *project_qtwi, QETProject *project, PanelOptions options, bool freshly_created) { Q_UNUSED(options) if (!project_qtwi || !project) return(0); if (freshly_created) { project_qtwi -> setData(0, GenericPanel::Item, qVariantFromValue(project)); projects_.insert(project, project_qtwi); connect( project, SIGNAL(projectInformationsChanged(QETProject *)), this, SLOT (projectInformationsChanged(QETProject *)) ); connect( project, SIGNAL(readOnlyChanged(QETProject *, bool)), this, SLOT (projectInformationsChanged(QETProject *)) ); } // text project_qtwi -> setText(0, project -> pathNameTitle()); // tooltip QString final_tooltip = QDir::toNativeSeparators(project -> filePath()); if (final_tooltip.isEmpty()) { final_tooltip = tr( "Pas de fichier", "tooltip for a file-less project in the element panel" ); } project_qtwi -> setToolTip(0, final_tooltip); QString project_whatsthis = tr("Ceci est un projet QElectroTech, c'est-à-dire un fichier d'extension .qet regroupant plusieurs folios. Il embarque également les éléments et modèles de cartouches utilisés dans ces folios.", "\"What's this\" tip"); project_qtwi -> setWhatsThis(0, project_whatsthis); return(updateItem(project_qtwi, options, freshly_created)); } /** */ QTreeWidgetItem *GenericPanel::fillProjectItem(QTreeWidgetItem *project_qtwi, QETProject *project, PanelOptions options, bool freshly_created) { if (!project_qtwi || !project) return(0); if (options & AddChildDiagrams) { if (freshly_created) { connect( project, SIGNAL(diagramAdded(QETProject *, Diagram *)), this, SLOT (diagramAdded(QETProject *, Diagram *)) ); connect( project, SIGNAL(diagramRemoved(QETProject *, Diagram *)), this, SLOT (diagramRemoved(QETProject *, Diagram *)) ); connect( project, SIGNAL(projectDiagramsOrderChanged(QETProject *, int, int)), this, SLOT (projectDiagramsOrderChanged(QETProject *, int, int)) ); connect( project, SIGNAL(elementIntegrated(QETProject *, const ElementsLocation &)), this, SLOT(elementIntegrated(QETProject *, const ElementsLocation &)) ); } else { // remove diagrams unknown to the project (presumably removed) removeObsoleteItems(project -> diagrams(), project_qtwi, QET::Diagram, false); } int index = 0; foreach (Diagram *diagram, project -> diagrams()) { QTreeWidgetItem *diagram_qtwi = addDiagram(diagram, 0, options); project_qtwi -> insertChild(index, diagram_qtwi); ++ index; } } if (options & AddChildTemplatesCollection) { if (freshly_created) { connect( project, SIGNAL(diagramUsedTemplate(TitleBlockTemplatesCollection *, const QString &)), this, SLOT (diagramUsedTemplate(TitleBlockTemplatesCollection *, const QString &)) ); } addTemplatesCollection( project -> embeddedTitleBlockTemplatesCollection(), project_qtwi, options ); } if (options & AddChildElementsCollections) { QTreeWidgetItem *collection_qtwi = addElementsCollection( project -> embeddedCollection(), project_qtwi, options ); QString collection_whatsthis = tr("Ceci est une collection embarquée dans un fichier projet. Elle permet de stocker et gérer les éléments utilisés dans les schémas du projet parent.", "\"What's this\" tip"); collection_qtwi -> setWhatsThis(0, collection_whatsthis); // special instructions for the integration category if (QTreeWidgetItem *integration_qtwi = itemForElementsCategory(project -> integrationCategory())) { QString integration_whats_this = tr("Cette catégorie d'éléments est utilisée pour intégrer automatiquement dans le projet tout élément utilisé sur un des schémas de ce projet.", "\"What's this\" tip"); integration_qtwi -> setWhatsThis(0, integration_whats_this); } } return(fillItem(project_qtwi, options, freshly_created)); } /** */ QTreeWidgetItem *GenericPanel::addDiagram(Diagram *diagram, QTreeWidgetItem *parent_item, PanelOptions options) { Q_UNUSED(options) if (!diagram) return(0); bool creation_required; QTreeWidgetItem *diagram_qtwi = getItemForDiagram(diagram, &creation_required); updateDiagramItem(diagram_qtwi, diagram, options, creation_required); reparent(diagram_qtwi, parent_item); fillDiagramItem(diagram_qtwi, diagram, options, creation_required); return(diagram_qtwi); } /** */ QTreeWidgetItem *GenericPanel::itemForDiagram(Diagram *diagram) { if (!diagram) return(0); return(diagrams_.value(diagram, 0)); } /** */ QTreeWidgetItem *GenericPanel::getItemForDiagram(Diagram *diagram, bool *created) { if (!diagram) return(0); QTreeWidgetItem *diagram_qtwi = diagrams_.value(diagram, 0); if (diagram_qtwi) { if (created) *created = false; return(diagram_qtwi); } diagram_qtwi = makeItem(QET::Diagram); if (created) *created = true; return(diagram_qtwi); } /** */ QTreeWidgetItem *GenericPanel::updateDiagramItem(QTreeWidgetItem *diagram_qtwi, Diagram *diagram, PanelOptions options, bool freshly_created) { Q_UNUSED(options) if (!diagram || !diagram_qtwi) return(0); QString displayed_title = diagram -> title(); if (displayed_title.isEmpty()) { displayed_title = tr("Folio sans titre", "Fallback label when a diagram has no title"); } QString displayed_label; int diagram_folio_idx = diagram -> folioIndex(); if (diagram_folio_idx != -1) { displayed_label = QString( tr( "%1 - %2", "label displayed for a diagram in the panel ; %1 is the folio index, %2 is the diagram title" ) ).arg(diagram_folio_idx + 1).arg(displayed_title); } else { displayed_label = displayed_title; } diagram_qtwi -> setText(0, displayed_label); if (freshly_created) { diagram_qtwi -> setData(0, GenericPanel::Item, qVariantFromValue(diagram)); diagrams_.insert(diagram, diagram_qtwi); connect( diagram, SIGNAL(diagramTitleChanged(Diagram *, const QString &)), this, SLOT (diagramTitleChanged(Diagram *, const QString &)) ); } return(updateItem(diagram_qtwi, options, freshly_created)); } /** */ QTreeWidgetItem *GenericPanel::fillDiagramItem(QTreeWidgetItem *diagram_qtwi, Diagram *diagram, PanelOptions options, bool freshly_created) { Q_UNUSED(diagram) Q_UNUSED(options) Q_UNUSED(freshly_created) return(fillItem(diagram_qtwi, options, freshly_created)); } /** */ QTreeWidgetItem *GenericPanel::addTemplatesCollection(TitleBlockTemplatesCollection *tbt_collection, QTreeWidgetItem *parent_item, PanelOptions options) { if (!tbt_collection) return(0); bool creation_required; QTreeWidgetItem *tbt_collection_qtwi = getItemForTemplatesCollection(tbt_collection, &creation_required); updateTemplatesCollectionItem(tbt_collection_qtwi, tbt_collection, options, creation_required); reparent(tbt_collection_qtwi, parent_item); fillTemplatesCollectionItem(tbt_collection_qtwi, tbt_collection, options, creation_required); return(tbt_collection_qtwi); } /** */ QTreeWidgetItem *GenericPanel::itemForTemplatesCollection(TitleBlockTemplatesCollection *tbt_collection) { if (!tbt_collection) return(0); return(tb_templates_.value(tbt_collection -> location(), 0)); } /** */ QTreeWidgetItem *GenericPanel::getItemForTemplatesCollection(TitleBlockTemplatesCollection *tbt_collection, bool *created) { if (!tbt_collection) return(0); QTreeWidgetItem *tbt_collection_item = tb_templates_.value(tbt_collection -> location(), 0); if (tbt_collection_item) { if (created) *created = false; return(tbt_collection_item); } tbt_collection_item = makeItem(QET::TitleBlockTemplatesCollection); if (created) *created = true; return(tbt_collection_item); } /** */ QTreeWidgetItem *GenericPanel::updateTemplatesCollectionItem(QTreeWidgetItem *tbt_collection_qtwi, TitleBlockTemplatesCollection *tbt_collection, PanelOptions options, bool freshly_created) { Q_UNUSED(options) QString label = tbt_collection -> title(); if (label.isEmpty()) label = tr("Modèles de cartouche"); tbt_collection_qtwi -> setText(0, label); tbt_collection_qtwi -> setToolTip(0, tbt_collection -> location().toString()); if (freshly_created) { tbt_collection_qtwi -> setData(0, GenericPanel::Item, qVariantFromValue(tbt_collection -> location())); tb_templates_.insert(tbt_collection -> location(), tbt_collection_qtwi); } return(updateItem(tbt_collection_qtwi, options, freshly_created)); } /** */ QTreeWidgetItem *GenericPanel::fillTemplatesCollectionItem(QTreeWidgetItem *tbt_collection_qtwi, TitleBlockTemplatesCollection *tbt_collection, PanelOptions options, bool freshly_created) { if (!tbt_collection_qtwi || !tbt_collection) return(tbt_collection_qtwi); if (options & AddChildTemplates) { if (freshly_created) { connect( tbt_collection, SIGNAL(changed(TitleBlockTemplatesCollection*,QString)), this, SLOT(templatesCollectionChanged(TitleBlockTemplatesCollection*, const QString &)) ); if (QETProject *project = tbt_collection -> parentProject()) { connect( project, SIGNAL(diagramUsedTemplate(TitleBlockTemplatesCollection *, const QString &)), this, SLOT (templatesCollectionChanged(TitleBlockTemplatesCollection *, const QString &)) ); } } else { // remove templates unknown to the collection (presumably removed) removeObsoleteItems(tbt_collection -> templatesLocations(), tbt_collection_qtwi, QET::TitleBlockTemplate, false); } int index = 0; foreach (QString template_name, tbt_collection -> templates()) { QTreeWidgetItem *template_item = addTemplate(tbt_collection -> location(template_name), 0, options); tbt_collection_qtwi -> insertChild(index ++, template_item); } } return(fillItem(tbt_collection_qtwi, options, freshly_created)); } /** */ QTreeWidgetItem *GenericPanel::addTemplate(const TitleBlockTemplateLocation &tb_template, QTreeWidgetItem *parent_item, PanelOptions options) { if (!tb_template.isValid()) return(0); bool creation_required; QTreeWidgetItem *tb_template_qtwi = getItemForTemplate(tb_template, &creation_required); updateTemplateItem(tb_template_qtwi, tb_template, options, creation_required); reparent(tb_template_qtwi, parent_item); fillTemplateItem(tb_template_qtwi, tb_template, options, creation_required); return(tb_template_qtwi); } /** */ QTreeWidgetItem *GenericPanel::itemForTemplate(const TitleBlockTemplateLocation &tb_template) { return(tb_templates_.value(tb_template, 0)); } /** */ QTreeWidgetItem *GenericPanel::getItemForTemplate(const TitleBlockTemplateLocation &tb_template, bool *created) { if (!tb_template.isValid()) return(0); QTreeWidgetItem *tb_template_qtwi = tb_templates_.value(tb_template, 0); if (tb_template_qtwi) { if (created) *created = false; return(tb_template_qtwi); } tb_template_qtwi = makeItem(QET::TitleBlockTemplate); if (created) *created = true; return(tb_template_qtwi); } /** */ QTreeWidgetItem *GenericPanel::updateTemplateItem(QTreeWidgetItem *tb_template_qtwi, const TitleBlockTemplateLocation &tb_template, PanelOptions options, bool freshly_created) { Q_UNUSED(options) tb_template_qtwi -> setText(0, tr("Modèle \"%1\"", "used to display a title block template").arg(tb_template.name())); QString tbt_whatsthis = tr( "Ceci est un modèle de cartouche, qui peut être appliqué à un folio.", "\"What's this\" tip" ); tb_template_qtwi -> setWhatsThis(0, tbt_whatsthis); // note the following lines are technically marking the template as used tb_template_qtwi -> setToolTip(0, tb_template.toString()); tb_template_qtwi -> setBackground(0, QBrush()); // special action for templates that belong to a project if (QETProject *tbt_project = tb_template.parentProject()) { // display unused templates using a red background if (!tbt_project -> usesTitleBlockTemplate(tb_template)) { markItemAsUnused(tb_template_qtwi); } } if (freshly_created) { tb_template_qtwi -> setData(0, GenericPanel::Item, qVariantFromValue(tb_template)); tb_templates_.insert(tb_template, tb_template_qtwi); } return(updateItem(tb_template_qtwi, options, freshly_created)); } /** */ QTreeWidgetItem *GenericPanel::fillTemplateItem(QTreeWidgetItem *tb_template_qtwi, const TitleBlockTemplateLocation &tb_template, PanelOptions options, bool freshly_created) { Q_UNUSED(tb_template) Q_UNUSED(options) Q_UNUSED(freshly_created) return(fillItem(tb_template_qtwi, options, freshly_created)); } /** Add an elements category to the panel. @param parent_item Parent for the created QTreeWidgetItem @param collection Collection to be added to the panel @param options Control the creation of child items @return the created QTreeWidgetItem */ QTreeWidgetItem *GenericPanel::addElementsCollection(ElementsCollection *collection, QTreeWidgetItem *parent_item, PanelOptions options) { if (!collection) return(0); bool creation_required; QTreeWidgetItem *collection_qtwi = getItemForElementsCollection(collection, &creation_required); updateElementsCollectionItem(collection_qtwi, collection, options, creation_required); reparent(collection_qtwi, parent_item); fillElementsCollectionItem(collection_qtwi, collection, options, creation_required); return(collection_qtwi); } /** */ QTreeWidgetItem *GenericPanel::itemForElementsCollection(ElementsCollection *collection) { if (!collection) return(0); return(elements_.value(collection -> rootCategory() -> location(), 0)); } /** */ QTreeWidgetItem *GenericPanel::getItemForElementsCollection(ElementsCollection *collection, bool *created) { if (!collection) return(0); QTreeWidgetItem *collection_item = elements_.value(collection -> rootCategory() -> location(), 0); if (collection_item) { if (created) *created = false; return(collection_item); } collection_item = makeItem(QET::ElementsCollection); if (created) *created = true; return(collection_item); } /** */ QTreeWidgetItem *GenericPanel::updateElementsCollectionItem(QTreeWidgetItem *collection_qtwi, ElementsCollection *collection, PanelOptions options, bool freshly_created) { Q_UNUSED(options) if (!collection) return(0); QString collection_title = collection -> title(); QIcon collection_icon = collection -> icon(); if (!collection_title.isEmpty()) collection_qtwi -> setText(0, collection_title); if (!collection_icon.isNull()) collection_qtwi -> setIcon(0, collection_icon); if (freshly_created) { collection_qtwi -> setData(0, GenericPanel::Item, qVariantFromValue(collection -> rootCategory() -> location())); elements_.insert(collection -> rootCategory() -> location(), collection_qtwi); connect( collection, SIGNAL(elementsCollectionChanged(ElementsCollection*)), this, SLOT(elementsCollectionChanged(ElementsCollection*)) ); } return(updateItem(collection_qtwi, options, freshly_created)); } /** */ QTreeWidgetItem *GenericPanel::fillElementsCollectionItem(QTreeWidgetItem *collection_qtwi, ElementsCollection *collection, PanelOptions options, bool freshly_created) { // use the cache from the provided collection, if any bool restore_previous_cache = false; ElementsCollectionCache *previous_cache = 0; ElementsCollectionCache *collection_cache = collection -> cache(); if (collection_cache) { restore_previous_cache = setElementsCache(collection_cache, &previous_cache); } ElementsCollectionCache *cache = getElementsCache(); cache -> beginCollection(collection); fillElementsCategoryItem(collection_qtwi, collection -> rootCategory(), options, freshly_created); cache -> endCollection(collection); // restore the former cache if (restore_previous_cache) { setElementsCache(previous_cache); } return(fillItem(collection_qtwi, options, freshly_created)); } /** */ QTreeWidgetItem *GenericPanel::itemForElementsLocation(const ElementsLocation &location) { return(elements_.value(location, 0)); } /** Add an elements category to the panel. @param category Category to be added to the panel @param parent_item Parent for the created QTreeWidgetItem @param options Control the creation of child items @return the created QTreeWidgetItem */ QTreeWidgetItem *GenericPanel::addElementsCategory(ElementsCategory *category, QTreeWidgetItem *parent_item, PanelOptions options) { if (!category) return(0); bool creation_required; QTreeWidgetItem *category_qtwi = getItemForElementsCategory(category, &creation_required); updateElementsCategoryItem(category_qtwi, category, options, creation_required); reparent(category_qtwi, parent_item); fillElementsCategoryItem(category_qtwi, category, options, creation_required); return(category_qtwi); } /** */ QTreeWidgetItem *GenericPanel::itemForElementsCategory(ElementsCategory *category) { if (!category) return(0); return(elements_.value(category -> location())); } /** */ QTreeWidgetItem *GenericPanel::getItemForElementsCategory(ElementsCategory *category, bool *created) { if (!category) return(0); QTreeWidgetItem *category_item = elements_.value(category -> location(), 0); if (category_item) { if (created) *created = false; return(category_item); } category_item = makeItem(QET::ElementsCategory); if (created) *created = true; return(category_item); } /** */ QTreeWidgetItem *GenericPanel::updateElementsCategoryItem(QTreeWidgetItem *category_qtwi, ElementsCategory *category, PanelOptions options, bool freshly_created) { Q_UNUSED(options) if (!category || !category_qtwi) return(0); QString category_whatsthis = tr( "Ceci est une catégorie d'éléments, un simple container permettant d'organiser les collections d'éléments", "\"What's this\" tip" ); category_qtwi -> setWhatsThis(0, category_whatsthis); QString category_tooltip = category -> location().toString(); category_qtwi -> setToolTip(0, category_tooltip); category_qtwi -> setText(0, category -> name()); markItemAsContainer(category_qtwi); if (freshly_created) { category_qtwi -> setData(0, GenericPanel::Item, qVariantFromValue(category -> location())); elements_.insert(category -> location(), category_qtwi); } return(updateItem(category_qtwi, options, freshly_created)); } /** */ QTreeWidgetItem *GenericPanel::fillElementsCategoryItem(QTreeWidgetItem *category_qtwi, ElementsCategory *category, PanelOptions options, bool freshly_created) { if (!category || !category_qtwi) return(0); int index = 0; category_qtwi -> setData(0, GenericPanel::PanelFlags, (int)options); if (options & AddChildElementsCategories) { if (!freshly_created) { QList sub_categories; foreach(ElementsCategory *sub_category, category -> categories()) { sub_categories << sub_category -> location(); } removeObsoleteItems(sub_categories, category_qtwi, QET::ElementsCategory, false); } foreach (ElementsCategory *sub_category, category -> categories()) { QTreeWidgetItem *sub_category_qtwi = addElementsCategory(sub_category, 0, options); category_qtwi -> insertChild(index ++, sub_category_qtwi); } } if (options & AddChildElements) { if (!freshly_created) { QList sub_elements; foreach(ElementDefinition *sub_element, category -> elements()) { sub_elements << sub_element -> location(); } removeObsoleteItems(sub_elements, category_qtwi, QET::Element, false); } foreach (ElementDefinition *sub_element, category -> elements()) { QTreeWidgetItem *sub_element_qtwi = addElement(sub_element, 0, options); category_qtwi -> insertChild(index ++, sub_element_qtwi); } } return(fillItem(category_qtwi, options, freshly_created)); } /** Refresh elements category at \a location. @return the refreshed tree item */ QTreeWidgetItem *GenericPanel::refreshElementsCategory(const ElementsLocation &location) { QTreeWidgetItem *item = itemForElementsLocation(location); if (!item) return(0); if (item -> type() != QET::ElementsCategory && item -> type() != QET::ElementsCollection) return(0); QTreeWidgetItem *result = fillElementsCategoryItem( item, QETApp::collectionItem(location) -> toCategory(), PanelOptions(QFlag(item -> data(0, GenericPanel::PanelFlags).toInt())), false ); return(result); } /** Refresh element at \a location. @return the refreshed tree item */ QTreeWidgetItem *GenericPanel::refreshElement(const ElementsLocation &location) { QTreeWidgetItem *item = itemForElementsLocation(location); if (!item) return(0); if (item -> type() != QET::Element) return(0); QTreeWidgetItem *parent = item -> parent(); if (!parent) return(0); QTreeWidgetItem *result = updateElementItem( item, QETApp::collectionItem(location) -> toElement(), PanelOptions(QFlag(parent -> data(0, GenericPanel::PanelFlags).toInt())), false ); return(result); } /** */ QTreeWidgetItem *GenericPanel::addElement(ElementDefinition *element, QTreeWidgetItem *parent_item, PanelOptions options) { if (!element) return(0); bool creation_required; QTreeWidgetItem *element_qtwi = getItemForElement(element, &creation_required); updateElementItem(element_qtwi, element, options, creation_required); reparent(element_qtwi, parent_item); fillElementItem(element_qtwi, element, options, creation_required); return(element_qtwi); } /** */ QTreeWidgetItem *GenericPanel::itemForElement(ElementDefinition *element) { if (!element) return(0); return(elements_.value(element -> location(), 0)); } /** */ QTreeWidgetItem *GenericPanel::getItemForElement(ElementDefinition *element, bool *created) { if (!element) return(0); QTreeWidgetItem *element_qtwi = elements_.value(element -> location(), 0); if (element_qtwi) { if (created) *created = false; return(element_qtwi); } element_qtwi = makeItem(QET::Element); if (created) *created = true; return(element_qtwi); } /** */ QTreeWidgetItem *GenericPanel::updateElementItem(QTreeWidgetItem *element_qtwi, ElementDefinition *element, PanelOptions options, bool freshly_created) { Q_UNUSED(options) Q_UNUSED(freshly_created) if (!element_qtwi || !element) { return(updateItem(element_qtwi, options, freshly_created)); } ElementsCollectionCache *cache = getElementsCache(); if (!cache -> fetchElement(element)) { return(updateItem(element_qtwi, options, freshly_created)); } ElementsLocation element_location = element -> location(); element_qtwi -> setText(0, cache -> name()); QString element_whatsthis = tr("Ceci est un élément que vous pouvez insérer dans un schéma.", "\"What's this\" tip"); element_qtwi -> setWhatsThis(0, element_whatsthis); if (options & DisplayElementsPreview) { element_qtwi -> setIcon(0, QIcon(cache -> pixmap())); } // note the following lines are technically marking the element as used element_qtwi -> setToolTip(0, element_location.toString()); element_qtwi -> setBackground(0, QBrush()); // actions speciales pour les elements appartenant a un projet if (QETProject *element_project = element_location.project()) { // affiche en rouge les elements inutilises dans un projet if (!element_project -> usesElement(element -> location())) { markItemAsUnused(element_qtwi); } } if (freshly_created) { element_qtwi -> setData(0, GenericPanel::Item, qVariantFromValue(element_location)); elements_.insert(element_location, element_qtwi); } return(updateItem(element_qtwi, options, freshly_created)); } /** */ QTreeWidgetItem *GenericPanel::fillElementItem (QTreeWidgetItem *element_qtwi, ElementDefinition *element, PanelOptions options, bool freshly_created) { Q_UNUSED(element_qtwi) Q_UNUSED(element) Q_UNUSED(options) Q_UNUSED(freshly_created) return(fillItem(element_qtwi, options, freshly_created)); } /** This generic method is called at the end of each update*Item method. Its only purpose is being reimplemented in a subclass. The default implementation does nothing. */ QTreeWidgetItem *GenericPanel::updateItem(QTreeWidgetItem *qtwi, PanelOptions options, bool freshly_created) { Q_UNUSED(qtwi); Q_UNUSED(options); Q_UNUSED(freshly_created); QApplication::processEvents(); return(qtwi); } /** This generic method is called at the end of each fill*Item method. Its only purpose is being reimplemented in a subclass. The default implementation does nothing. */ QTreeWidgetItem *GenericPanel::fillItem(QTreeWidgetItem *qtwi, PanelOptions options, bool freshly_created) { Q_UNUSED(qtwi); Q_UNUSED(options); Q_UNUSED(freshly_created); return(qtwi); } /** */ void GenericPanel::projectInformationsChanged(QETProject *project) { addProject(project, 0, 0); emit(panelContentChanged()); } /** */ void GenericPanel::diagramAdded(QETProject *project, Diagram *diagram) { Q_UNUSED(diagram) addProject(project, 0, GenericPanel::AddChildDiagrams); emit(panelContentChanged()); } /** */ void GenericPanel::diagramRemoved(QETProject *project, Diagram *diagram) { Q_UNUSED(diagram) addProject(project, 0, GenericPanel::AddChildDiagrams); emit(panelContentChanged()); } /** * @brief GenericPanel::projectDiagramsOrderChanged * @param project project where diagram moved * @param from Index of diagram before move * @param to Index of diagram after move */ void GenericPanel::projectDiagramsOrderChanged(QETProject *project, int from, int to) { // get the item representing the provided project QTreeWidgetItem *qtwi_project = itemForProject(project); if (!qtwi_project) return; // get the item representing the moved diagram QTreeWidgetItem *moved_qtwi_diagram = qtwi_project -> child(from); if (!moved_qtwi_diagram) return; // remove the QTWI then insert it back at the adequate location bool was_selected = moved_qtwi_diagram -> isSelected(); qtwi_project -> removeChild (moved_qtwi_diagram); qtwi_project -> insertChild (to, moved_qtwi_diagram); // update the QTWI labels because they may display the folio index for (int i = qMin(from, to); i < qMax(from, to) + 1; i++) { QTreeWidgetItem *qtwi_diagram = qtwi_project -> child(i); if (!qtwi_diagram) continue; Diagram *diagram = valueForItem(qtwi_diagram); if (diagram) updateDiagramItem(qtwi_diagram, diagram); } if (was_selected) setCurrentItem(moved_qtwi_diagram); emit(panelContentChanged()); } /** Inform this panel the project \a project has integrated the element at \a location */ QList GenericPanel::elementIntegrated(QETProject *project, const ElementsLocation &location) { Q_UNUSED(project) QList added_locations; int i = 0; ElementsLocation loc = location; // starting from the provided location, goes up into the tree until a displayed location is reached while (i < 100 && !(itemForElementsLocation(loc))) { added_locations << loc; loc = loc.parent(); ++ i; } if (added_locations.count()) { refreshElementsCategory(loc); } else { if (refreshElement(location)) { added_locations << location; } } // Since we have refreshed the panel before the element is actually used by // the diagram, it will appear as unused; we force it as used. // FIXME a better solution would be to get warned when an element gets used // or unused. if (QTreeWidgetItem *integrated_element_qtwi = itemForElementsLocation(location)) { integrated_element_qtwi -> setToolTip(0, location.toString()); integrated_element_qtwi -> setBackground(0, QBrush()); } return(added_locations); } /** Inform this panel the diagram \a diagram has changed its title to \a title. */ void GenericPanel::diagramTitleChanged(Diagram *diagram, const QString &title) { Q_UNUSED(title) GenericPanel::addDiagram(diagram); emit(panelContentChanged()); } /** @param collection Title block templates collection that changed and should be updated @param template_name Name of the changed template (unused) */ void GenericPanel::templatesCollectionChanged(TitleBlockTemplatesCollection*collection, const QString &template_name) { Q_UNUSED(template_name) addTemplatesCollection(collection); emit(panelContentChanged()); } /** */ void GenericPanel::diagramUsedTemplate(TitleBlockTemplatesCollection *collection, const QString &name) { Q_UNUSED(collection) Q_UNUSED(name) addTemplatesCollection(collection); emit(panelContentChanged()); } /** */ void GenericPanel::elementsCollectionChanged(ElementsCollection *collection) { addElementsCollection(collection, 0, 0); emit(panelContentChanged()); } /** */ QString GenericPanel::defaultText(QET::ItemType type) { switch(type) { case QET::ElementsCollectionItem: case QET::Element: return("element"); case QET::ElementsContainer: case QET::ElementsCategory: return("elements category"); case QET::ElementsCollection: return("elements collection"); case QET::TitleBlockTemplatesCollectionItem: case QET::TitleBlockTemplate: return("title block template"); case QET::TitleBlockTemplatesCollection: return("title block templates collection"); case QET::Diagram: return("diagram"); case QET::Project: return("project"); default: return(QString()); } return(QString()); } /** @param type Item type we want the default icon for @return the default icon for \a type */ QIcon GenericPanel::defaultIcon(QET::ItemType type) { if (type & QET::ElementsContainer) { return(QET::Icons::Folder); } else if (type & QET::TitleBlockTemplatesCollectionItem) { return(QIcon(QET::Icons::TitleBlock.pixmap(QSize(16, 16)))); } else if (type == QET::Diagram) { return(QET::Icons::Diagram); } else if (type == QET::Project) { return(QIcon(QET::Icons::ProjectFileGP.pixmap(QSize(16, 16)))); } return(QIcon()); } /** Create a QTreeWidgetItem @param parent Parent for the created item @param type Item type (e.g QET::Diagram, QET::Project, ...) @param label Label for the created item @param icon Icon for the created item @return the create QTreeWidgetItem */ QTreeWidgetItem *GenericPanel::makeItem(QET::ItemType type, QTreeWidgetItem *parent, const QString &label, const QIcon &icon) { QTreeWidgetItem *qtwi = new QTreeWidgetItem(parent, type); qtwi -> setText(0, label.isEmpty() ? defaultText(type) : label); qtwi -> setIcon(0, icon.isNull() ? defaultIcon(type) : icon); return(qtwi); } /** Delete and item and its children. @param item item to delete @param deleted_on_cascade true if the item is not being directly deleted but is undergoing the deletion of its parent. */ void GenericPanel::deleteItem(QTreeWidgetItem *item, bool deleted_on_cascade) { Q_UNUSED(deleted_on_cascade) // recursively delete child items first for (int i = item -> childCount() - 1 ; i >= 0 ; -- i) { deleteItem(item -> child(i), true); } // delete the item itself unregisterItem(item); delete item; } /** Mark an item as being a container (collection, category, ...) */ void GenericPanel::markItemAsContainer(QTreeWidgetItem *qtwi) { if (!qtwi) return; QLinearGradient t(0, 0, 200, 0); t.setColorAt(0, QColor("#e8e8e8")); t.setColorAt(1, QColor("#ffffff")); qtwi -> setBackground(0, QBrush(t)); } /** Mark the provided QTreeWidgetItem as unused in its parent project. @param qtwi A QTreeWidgetItem */ void GenericPanel::markItemAsUnused(QTreeWidgetItem *qtwi) { QLinearGradient t(0, 0, 200, 0); t.setColorAt(0, QColor("#ffc0c0")); t.setColorAt(1, QColor("#ffffff")); qtwi -> setBackground(0, QBrush(t)); qtwi -> setToolTip(0, QString(tr("%1 [non utilisé dans le projet]")).arg(qtwi -> toolTip(0))); } /** */ void GenericPanel::reparent(QTreeWidgetItem *item, QTreeWidgetItem *parent) { if (parent && item -> parent() != parent) { parent -> addChild(item); } } /** @return the child items of \a item of type \a type @param item Parent item that will be searched. @param type Type of items to look for. @param recursive Whether to search recursively. */ QList GenericPanel::childItems(QTreeWidgetItem *item, QET::ItemType type, bool recursive) const { QList items; if (!item) return(items); for (int i = 0 ; i < item -> childCount() ; ++ i) { QTreeWidgetItem *current_item = item -> child(i); if (!current_item) continue; if (current_item -> type() == type) { items << current_item; } if (recursive) { items << childItems(current_item, type, true); } } return(items); } /** This variant of childItems() removes any child considered obsolete, i.e. not found in \a expected_items. @param expected_items A list of non-obsolete values @param item Parent item that will be searched. @param type Type of items to look for. @param recursive Whether to search recursively. @see GenericPanel::childItems() */ template void GenericPanel::removeObsoleteItems(const QList &expected_items, QTreeWidgetItem *item, QET::ItemType type, bool recursive) { // remove items not found in expected_items foreach (QTreeWidgetItem *child_item, childItems(item, type, recursive)) { T child_value = valueForItem(child_item); if (!expected_items.contains(child_value)) { deleteItem(child_item); } } } /** @return the value stored in \a item */ template T GenericPanel::valueForItem(QTreeWidgetItem *item) const { return item -> data(0, GenericPanel::Item).value(); } template TitleBlockTemplateLocation GenericPanel::valueForItem(QTreeWidgetItem *item) const; template ElementsLocation GenericPanel::valueForItem(QTreeWidgetItem*) const; template QETProject* GenericPanel::valueForItem(QTreeWidgetItem*) const; template Diagram* GenericPanel::valueForItem(QTreeWidgetItem*) const; /** */ void GenericPanel::unregisterItem(QTreeWidgetItem *item) { if (!item) return; int type = item ->type(); if (type & QET::ElementsCollectionItem) { elements_.remove(valueForItem(item)); } else if (type & QET::TitleBlockTemplatesCollectionItem) { tb_templates_.remove(valueForItem(item)); } else if (type == QET::Diagram) { diagrams_.remove(valueForItem(item)); } else if (type == QET::Project) { projects_.remove(valueForItem(item)); } } /** */ void GenericPanel::clearPanel() { clear(); projects_.clear(); diagrams_.clear(); tb_templates_.clear(); elements_.clear(); } /** Handle various events; reimplemented here to emit the signal firstActivated(). */ bool GenericPanel::event(QEvent *event) { if (first_activation_) { if (event -> type() == QEvent::WindowActivate || event -> type() == QEvent::Show) { QTimer::singleShot(250, this, SLOT(emitFirstActivated())); first_activation_ = false; } } return(QTreeWidget::event(event)); } /** Emit the signal firstActivated(). */ void GenericPanel::emitFirstActivated() { emit(firstActivated()); }