1226 lines
37 KiB
C++
Raw Normal View History

#include "genericpanel.h"
#include <QTreeWidgetItem>
#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);
/// @todo we need a unique function to get the good language
cache_ -> setLocale(QLocale::system().name().left(2));
}
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<QETProject *>(item));
}
return(0);
}
/**
*/
Diagram *GenericPanel::diagramForItem(QTreeWidgetItem *item) const {
if (item && item -> type() == QET::Diagram) {
return(valueForItem<Diagram *>(item));
}
return(0);
}
/**
*/
TitleBlockTemplateLocation GenericPanel::templateLocationForItem(QTreeWidgetItem *item) const {
if (item && item -> type() & QET::TitleBlockTemplatesCollectionItem) {
return(valueForItem<TitleBlockTemplateLocation>(item));
}
return(TitleBlockTemplateLocation());
}
/**
*/
ElementsLocation GenericPanel::elementLocationForItem(QTreeWidgetItem *item) const {
if (item && item -> type() & QET::ElementsCollectionItem) {
return(valueForItem<ElementsLocation>(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-\340-dire un fichier d'extension .qet regroupant plusieurs sch\351mas/folios. Il embarque \351galement les \351l\351ments et mod\350les de cartouches utilis\351s dans ces sch\351mas/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\351e dans un fichier projet. Elle permet de stocker et g\351rer les \351l\351ments utilis\351s dans les sch\351mas 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\351gorie d'\351l\351ments est utilis\351e pour int\351grer automatiquement dans le projet tout \351l\351ment utilis\351 sur un des sch\351mas 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("Sch\351ma 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\350les 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\350le \"%1\"", "used to display a title block template").arg(tb_template.name()));
QString tbt_whatsthis = tr(
"Ceci est un mod\350le de cartouche, qui peut \352tre appliqu\351 \340 un sch\351ma.",
"\"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\351gorie d'\351l\351ments, un simple container permettant d'organiser les collections d'\351l\351ments",
"\"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<ElementsLocation> 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<ElementsLocation> 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);
}
/**
*/
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 \351l\351ment que vous pouvez ins\351rer dans un sch\351ma.", "\"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);
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());
}
/**
@param project Projet auquel appartiennent les schemas concernes
@param from Index de l'onglet avant le deplacement
@param to Index de l'onglet apres le deplacement
*/
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
foreach (int diagram_index, QList<int>() << from << to) {
QTreeWidgetItem *qtwi_diagram = qtwi_project -> child(diagram_index);
if (!qtwi_diagram) continue;
Diagram *diagram = valueForItem<Diagram *>(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<ElementsLocation> GenericPanel::elementIntegrated(QETProject *project, const ElementsLocation &location) {
Q_UNUSED(project)
QList<ElementsLocation> 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);
}
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::ProjectFile.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\351 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<QTreeWidgetItem *> GenericPanel::childItems(QTreeWidgetItem *item, QET::ItemType type, bool recursive) const {
QList<QTreeWidgetItem *> 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<typename T>
void GenericPanel::removeObsoleteItems(const QList<T> &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<T>(child_item);
if (!expected_items.contains(child_value)) {
deleteItem(child_item);
}
}
}
/**
@return the value stored in \a item
*/
template<typename T>
T GenericPanel::valueForItem(QTreeWidgetItem *item) const {
return(qVariantValue<T>(item -> data(0, GenericPanel::Item)));
}
/**
*/
void GenericPanel::unregisterItem(QTreeWidgetItem *item) {
if (!item) return;
int type = item ->type();
if (type & QET::ElementsCollectionItem) {
elements_.remove(valueForItem<ElementsLocation>(item));
} else if (type & QET::TitleBlockTemplatesCollectionItem) {
tb_templates_.remove(valueForItem<TitleBlockTemplateLocation>(item));
} else if (type == QET::Diagram) {
diagrams_.remove(valueForItem<Diagram *>(item));
} else if (type == QET::Project) {
projects_.remove(valueForItem<QETProject *>(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_ && event -> type() == QEvent::WindowActivate) {
QTimer::singleShot(250, this, SLOT(emitFirstActivated()));
first_activation_ = false;
}
return(QTreeWidget::event(event));
}
/**
Emit the signal firstActivated().
*/
void GenericPanel::emitFirstActivated() {
emit(firstActivated());
}