New element panel can display the thumbnail of elements used in a project

git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@4293 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
blacksun
2015-12-30 09:39:22 +00:00
parent 72c65f80ad
commit 313e4b9793
20 changed files with 462 additions and 126 deletions

View File

@@ -19,6 +19,9 @@
#include "qetapp.h"
#include "qetproject.h"
#include "elementscollectioncache.h"
#include "xmlelementcollection.h"
#include "elementfactory.h"
#include "element.h"
/**
* @brief ElementLocation::ElementLocation
@@ -34,6 +37,7 @@ ElementLocation::ElementLocation(QString path):
/**
* @brief ElementLocation::ElementLocation
* @param path : path of item embedded in @project
* The path must be in form : embed://dir/subdir/myElement.elmt
* @param project : project
*/
ElementLocation::ElementLocation(QString path, QETProject *project) :
@@ -58,116 +62,148 @@ bool ElementLocation::setPath(QString path)
{
QString tmp_path = path;
//The path is in file system
if (!m_project)
//There is a project, the path is for an embedded coolection.
if (m_project)
{
//The given path is relative to common or custom collection
if (path.startsWith("common://") || path.startsWith("custom://"))
if (path.startsWith("embed://"))
{
QString p;
if (path.startsWith("common://"))
{
tmp_path.remove("common://");
p = QETApp::commonElementsDir() + tmp_path;
}
else
{
tmp_path.remove("custom://");
p = QETApp::customElementsDir() + tmp_path;
}
m_collection_path = path;
return true;
}
else
return false;
}
//This is an element
if (path.endsWith(".elmt"))
//The path start with project, we get the project and the path from the string
else if (tmp_path.startsWith("project"))
{
QRegExp rx("^project([0-9]+)\\+(embed:\\/\\/.*)$", Qt::CaseInsensitive);
if (rx.exactMatch(tmp_path))
{
bool conv_ok;
uint project_id = rx.capturedTexts().at(1).toUInt(&conv_ok);
if (conv_ok)
{
QFile file(p);
if (file.exists())
QETProject *project = QETApp::project(project_id);
if (project)
{
m_file_system_path = p;
m_collection_path = path;
m_collection_path = rx.capturedTexts().at(2);
m_project = project;
return true;
}
return false;
}
//They must be a directory
else
{
QDir dir(p);
if(dir.exists())
{
m_file_system_path = p;
m_collection_path = path;
return true;
}
return false;
}
}
//In this case, the path is supposed to be relative to the file system.
return false;
}
//The path is in file system, the given path is relative to common or custom collection
else if (path.startsWith("common://") || path.startsWith("custom://"))
{
QString p;
if (path.startsWith("common://"))
{
tmp_path.remove("common://");
p = QETApp::commonElementsDir() + tmp_path;
}
else
{
if(path.endsWith(".elmt"))
tmp_path.remove("custom://");
p = QETApp::customElementsDir() + tmp_path;
}
//This is an element
if (path.endsWith(".elmt"))
{
QFile file(p);
if (file.exists())
{
QFile file(path);
if (file.exists())
{
m_file_system_path = path;
if (path.startsWith(QETApp::commonElementsDir()))
{
path.remove(QETApp::commonElementsDir());
path.prepend("common://");
m_collection_path = path;
}
else if (path.startsWith(QETApp::customElementsDir()))
{
path.remove(QETApp::customElementsDir());
path.prepend("custom://");
m_collection_path = path;
}
return true;
}
return false;
m_file_system_path = p;
m_collection_path = path;
return true;
}
else
return false;
}
//They must be a directory
else
{
QDir dir(p);
if(dir.exists())
{
QDir dir(path);
if (dir.exists())
{
m_file_system_path = path;
if (path.startsWith(QETApp::commonElementsDir()))
{
path.remove(QETApp::commonElementsDir());
path.prepend("common://");
m_collection_path = path;
}
else if (path.startsWith(QETApp::customElementsDir()))
{
path.remove(QETApp::customElementsDir());
path.prepend("custom://");
m_collection_path = path;
}
return true;
}
return false;
m_file_system_path = p;
m_collection_path = path;
return true;
}
return false;
}
}
//In this case, the path is supposed to be relative to the file system.
else
{
if(path.endsWith(".elmt"))
{
QFile file(path);
if (file.exists())
{
m_file_system_path = path;
if (path.startsWith(QETApp::commonElementsDir()))
{
path.remove(QETApp::commonElementsDir());
path.prepend("common://");
m_collection_path = path;
}
else if (path.startsWith(QETApp::customElementsDir()))
{
path.remove(QETApp::customElementsDir());
path.prepend("custom://");
m_collection_path = path;
}
return true;
}
return false;
}
else
{
QDir dir(path);
if (dir.exists())
{
m_file_system_path = path;
if (path.startsWith(QETApp::commonElementsDir()))
{
path.remove(QETApp::commonElementsDir());
path.prepend("common://");
m_collection_path = path;
}
else if (path.startsWith(QETApp::customElementsDir()))
{
path.remove(QETApp::customElementsDir());
path.prepend("custom://");
m_collection_path = path;
}
return true;
}
return false;
}
}
return false;
}
/**
* @brief ElementLocation::isNull
* @return True represent nothing
*/
bool ElementLocation::isNull() const
{
if (m_file_system_path.isEmpty())
return true;
else
return false;
if (!m_file_system_path.isEmpty()) return false;
else if (!m_collection_path.isEmpty()) return false;
else return true;
}
/**
* @brief ElementLocation::setProject
* @param project : set the project of this location to @project.
*/
void ElementLocation::setProject(QETProject *project)
{
void ElementLocation::setProject(QETProject *project) {
m_project = project;
}
@@ -233,6 +269,20 @@ QDomElement ElementLocation::xml()
if (docu.setContent(&file))
m_xml = docu.documentElement().cloneNode().toElement();
}
else
{
QString str = m_collection_path;
if (isElement())
{
QDomElement element = m_project->embeddedElementCollection()->element(str.remove("embed://"));
m_xml = element.firstChildElement("definition");
}
else
{
QDomElement element = m_project->embeddedElementCollection()->directory(str.remove("embed://"));
m_xml = element;
}
}
return m_xml;
}
@@ -254,22 +304,65 @@ QUuid ElementLocation::uuid()
return m_uuid;
}
/**
* @brief ElementLocation::icon
* @return The icon of the represented element.
* If icon can't be set, return a null QIcon
*/
QIcon ElementLocation::icon()
{
if (!m_icon.isNull()) return m_icon;
ElementsCollectionCache *cache = QETApp::collectionCache();
if (cache->fetchElement(*this))
m_icon = QIcon(cache->pixmap());
if (!m_project)
{
ElementsCollectionCache *cache = QETApp::collectionCache();
if (cache->fetchElement(*this))
m_icon = QIcon(cache->pixmap());
}
else
{
ElementFactory *factory = ElementFactory::Instance();
int state;
Element *elmt = factory->createElement(*this, 0, &state);
if (state == 0)
m_icon = QIcon(elmt->pixmap());
}
return m_icon;
}
/**
* @brief ElementLocation::name
* @return The name of the represented element in the current local
*/
QString ElementLocation::name()
{
ElementsCollectionCache *cache = QETApp::collectionCache();
if (cache->fetchElement(*this))
return cache->name();
if (!m_project)
{
ElementsCollectionCache *cache = QETApp::collectionCache();
if (cache->fetchElement(*this))
return cache->name();
else
return QString();
}
else
return QString();
{
NamesList nl;
nl.fromXml(xml());
return nl.name(fileName());
}
}
/**
* @brief ElementLocation::fileName
* @return Return the file name of this element whatever the storage system (file system, xml collection)
*/
QString ElementLocation::fileName() const
{
if (m_collection_path.isEmpty()) return QString();
QStringList qsl = m_collection_path.split("/");
if (qsl.isEmpty()) return QString();
else return qsl.last();
}

View File

@@ -49,10 +49,11 @@ class ElementLocation
QETProject *project() const;
QDomElement xml();
QDomElement xml();
QUuid uuid();
QIcon icon();
QString name();
QString fileName() const;
private:
QString m_collection_path;

View File

@@ -16,12 +16,17 @@
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "xmlelementcollection.h"
#include "qdebug.h"
#include "nameslist.h"
/**
* @brief XmlElementCollection::XmlElementCollection
* Build an empty collection
* Build an empty collection.
* The collection start by :
* <collection>
* <category name="import>
* </category>
* </collection>
* All elements and category are stored as child of <category name="import>
* @param parent
*/
XmlElementCollection::XmlElementCollection(QObject *parent) :
@@ -130,3 +135,75 @@ QList<QDomElement> XmlElementCollection::elements(const QDomElement &parent_elem
return element_list;
}
/**
* @brief XmlElementCollection::element
* @param path : path of element : the path must start by "import/",
* because import is the first directory of an xml collection
* @return the QDomElement that represent the element at path @path
* or a null QDomElement if not found or doesn't represent an element
*/
QDomElement XmlElementCollection::element(const QString &path)
{
if (!path.endsWith(".elmt")) return QDomElement();
QStringList path_list = path.split("/");
QString element_name = path_list.last();
path_list.removeLast();
QDomElement dom_element = directory(path_list.join("/"));
if (dom_element.isNull()) return QDomElement();
QDomNodeList node_list = dom_element.elementsByTagName("element");
if (node_list.isEmpty()) return QDomElement();
for (int i=0 ; i <node_list.size() ; i++)
{
QDomNode node = node_list.at(i);
if (node.isElement())
{
QDomElement qde = node.toElement();
if (qde.attribute("name") == element_name)
return qde;
}
}
return QDomElement();
}
/**
* @brief XmlElementCollection::directory
* @param path : path of directory : the path must start by "import/",
* because import is the first directory of an xml collection
* @return the QDomElement that represent the directory at path @path
* or a null QDomElement if not found.
*/
QDomElement XmlElementCollection::directory(const QString &path)
{
QStringList path_list = path.split("/");
QDomElement dom_element = m_dom_document.documentElement();
for (int i=0 ; i<path_list.size() ; i++)
{
QDomNodeList node_list = dom_element.elementsByTagName("category");
if (node_list.isEmpty()) return QDomElement();
for (int j=0 ; j <node_list.size() ; j++)
{
QDomNode node = node_list.at(j);
if (node.isElement())
{
QDomElement qde = node.toElement();
if (qde.attribute("name") == path_list.at(i))
{
dom_element = node.toElement();
j = node_list.size(); //Use to go out of the for loop
}
else if (j == node_list.size()-1)
return QDomElement();
}
}
}
return dom_element;
}

View File

@@ -23,6 +23,10 @@
class QDomElement;
/**
* @brief The XmlElementCollection class
* This class represent a collection of elements stored to xml
*/
class XmlElementCollection : public QObject
{
Q_OBJECT
@@ -33,6 +37,8 @@ class XmlElementCollection : public QObject
QDomNodeList childs(const QDomElement &parent_element);
QList<QDomElement> directory(const QDomElement &parent_element);
QList<QDomElement> elements(const QDomElement &parent_element);
QDomElement element(const QString &path);
QDomElement directory(const QString &path);
signals:

View File

@@ -21,6 +21,7 @@
#include "xmlelementcollection.h"
#include "nameslist.h"
#include "qetapp.h"
#include "elementlocation.h"
#include <algorithm>
/**
@@ -81,7 +82,14 @@ QVariant XmlProjectElementCollectionItem::data(int column, int role)
else if (isDir())
return QET::Icons::Folder;
else
return QET::Icons::Element;
{
if (m_icon.isNull())
{
ElementLocation loc(embeddedPath(), m_project);
m_icon = loc.icon();
}
return m_icon;
}
break;
case Qt::ToolTipRole:
if (isCollectionRoot())
@@ -151,23 +159,8 @@ QString XmlProjectElementCollectionItem::name()
}
else
{
NamesList nl;
if (isDir())
{
nl.fromXml(m_dom_element);
if (nl.name().isEmpty())
m_name = m_dom_element.attribute("name");
else
m_name = nl.name();
}
else
{
nl.fromXml(m_dom_element.firstChildElement("definition"));
if (nl.name().isEmpty())
m_name = m_dom_element.attribute("name");
else
m_name = nl.name();
}
ElementLocation location (embeddedPath(), m_project);
m_name = location.name();
return m_name;
}
}
@@ -210,7 +203,8 @@ bool XmlProjectElementCollectionItem::isElement() const
/**
* @brief XmlProjectElementCollectionItem::collectionPath
* @return The collection path of this item
* @return The collection path of this item.
* The path is in form : project0+embed://dir/subdir/myElement.elmt
*/
QString XmlProjectElementCollectionItem::collectionPath() const
{
@@ -230,6 +224,28 @@ QString XmlProjectElementCollectionItem::collectionPath() const
}
}
/**
* @brief XmlProjectElementCollectionItem::embeddedPath
* @return The embedde path of this item
* The path is in form : embed://dir/subdir/myElement.elmt
*/
QString XmlProjectElementCollectionItem::embeddedPath() const
{
if (isCollectionRoot())
{
return "embed://";
}
else
{
XmlProjectElementCollectionItem *parent = static_cast<XmlProjectElementCollectionItem *>(m_parent_item);
if (parent->isCollectionRoot())
return parent->embeddedPath() + m_dom_element.attribute("name");
else
return parent->embeddedPath() + "/" + m_dom_element.attribute("name");
}
}
/**
* @brief XmlProjectElementCollectionItem::populate
* Populate this item

View File

@@ -21,6 +21,7 @@
#include "elementcollectionitem.h"
#include <QDomElement>
#include <QIcon>
class QETProject;
@@ -51,6 +52,7 @@ class XmlProjectElementCollectionItem : public ElementCollectionItem
virtual bool isDir() const;
virtual bool isElement() const;
QString collectionPath() const;
QString embeddedPath() const;
private:
void populate();
@@ -58,6 +60,7 @@ class XmlProjectElementCollectionItem : public ElementCollectionItem
private:
QETProject *m_project;
QDomElement m_dom_element;
QIcon m_icon;
};
#endif // XMLPROJECTELEMENTCOLLECTIONITEM_H

View File

@@ -59,3 +59,31 @@ Element * ElementFactory::createElement(const ElementsLocation &location, QGraph
//default if nothing match for link_type
return (new SimpleElement(location, qgi, state));
}
/**
* @brief ElementFactory::createElement
* @param location : The location of the element
* @param parent : parent item for the new element
* @param state : state of the creation
* @return : the element or nullptr if the creation failed
*/
Element *ElementFactory::createElement(ElementLocation &location, QGraphicsItem *parent, int *state)
{
if (!location.isElement() || location.isNull())
{
if (state) *state = 1;
return nullptr;
}
if (location.xml().hasAttribute("link_type"))
{
QString link_type = location.xml().attribute("link_type");
if (link_type == "next_report" || link_type == "previous_report") return (new ReportElement(location, link_type, parent, state));
if (link_type == "master") return (new MasterElement (location, parent, state));
if (link_type == "slave") return (new SlaveElement (location, parent, state));
if (link_type == "terminal") return (new TerminalElement (location, parent, state));
}
//default if nothing match for link_type
return (new SimpleElement(location, parent, state));
}

View File

@@ -70,7 +70,8 @@ class ElementFactory
~ElementFactory() {}
public:
Element * createElement (const ElementsLocation &, QGraphicsItem * = 0, int * = 0);
Element *createElement (const ElementsLocation &, QGraphicsItem * = 0, int * = 0);
Element *createElement(ElementLocation &location, QGraphicsItem *parent = nullptr, int *state = nullptr);
};
//ElementFactory ElementFactory::factory_ = 0;
#endif // ELEMENTFACTORY_H

View File

@@ -90,6 +90,50 @@ CustomElement::CustomElement(const ElementsLocation &location, QGraphicsItem *qg
elmt_state = 0;
}
/**
* @brief CustomElement::CustomElement
* Constructor build an element from the location @location
* @param location : location of the element
* @param parent : parent of element
* @param state : pointeur used to know the encountered error at creation...
- 0 : No error
- 1 : The location don't represent an element
- 2 : The location can't be readable
- 3 : The location isn't valid / exploitable / usable
- 4 : The xml document wasn't an element "definition"
- 5 : The attributes of the defintion aren't present and/or valid
- 6 : The defintion is empty
- 7 : The analyze of an xml element that describe a part of the drawing was failed
- 8 : No part of the drawing can be loaded
*/
CustomElement::CustomElement(ElementLocation &location, QGraphicsItem *parent, int *state) :
FixedElement(parent),
elmt_state(-1),
m_location(location),
forbid_antialiasing(false)
{
if (!location.isElement())
{
if (state) *state = 1;
elmt_state = 1;
}
//Start from empty lists.
list_lines_.clear();
list_rectangles_.clear();
list_circles_.clear();
list_polygons_.clear();
list_arcs_.clear();
buildFromXml(location.xml(), &elmt_state);
if (state) *state = elmt_state;
if (elmt_state) return;
if (state) *state = 0;
elmt_state = 0;
}
/**
Construit l'element personnalise a partir d'un element XML representant sa
definition.

View File

@@ -20,6 +20,7 @@
#include "fixedelement.h"
#include "nameslist.h"
#include "elementslocation.h"
#include "elementlocation.h"
#include <QPicture>
class ElementTextItem;
@@ -30,28 +31,32 @@ class Terminal;
element, the difference being that the CustomElement reads its description
(names, drawing, behavior) from an XML document.
*/
class CustomElement : public FixedElement {
class CustomElement : public FixedElement
{
Q_OBJECT
// constructors, destructor
// constructors, destructor
public:
CustomElement(const ElementsLocation &, QGraphicsItem * = 0, int * = 0);
CustomElement (const ElementsLocation &, QGraphicsItem * = 0, int * = 0);
CustomElement (ElementLocation &location, QGraphicsItem *parent = nullptr, int *state = nullptr);
virtual ~CustomElement();
private:
CustomElement(const CustomElement &);
CustomElement(const CustomElement &);
// attributes
// attributes
protected:
int elmt_state; // hold the error code in case the instanciation fails, or 0 if everything went well
NamesList names;
ElementsLocation location_;
QPicture drawing;
QPicture low_zoom_drawing;
QList<Terminal *> list_terminals;
QList<ElementTextItem *> list_texts_;
bool forbid_antialiasing;
int elmt_state; // hold the error code in case the instanciation fails, or 0 if everything went well
NamesList names;
ElementsLocation location_;
ElementLocation m_location;
QPicture drawing;
QPicture low_zoom_drawing;
QList<Terminal *> list_terminals;
QList<ElementTextItem *> list_texts_;
bool forbid_antialiasing;
QList<QLineF *> list_lines_;
QList<QRectF *> list_rectangles_;

View File

@@ -35,6 +35,14 @@ MasterElement::MasterElement(const ElementsLocation &location, QGraphicsItem *qg
connect(this, SIGNAL(elementInfoChange(DiagramContext, DiagramContext)), this, SLOT(updateLabel(DiagramContext, DiagramContext)));
}
MasterElement::MasterElement(ElementLocation &location, QGraphicsItem *parent, int *state) :
CustomElement(location, parent, state),
cri_ (nullptr)
{
link_type_ = Master;
connect(this, SIGNAL(elementInfoChange(DiagramContext, DiagramContext)), this, SLOT(updateLabel(DiagramContext, DiagramContext)));
}
/**
* @brief MasterElement::~MasterElement
* default destructor

View File

@@ -34,6 +34,7 @@ class MasterElement : public CustomElement
public:
explicit MasterElement(const ElementsLocation &, QGraphicsItem * = 0, int * = 0);
explicit MasterElement(ElementLocation &location, QGraphicsItem *parent = nullptr, int *state = nullptr);
~MasterElement();
virtual void linkToElement (Element *elmt);

View File

@@ -51,6 +51,34 @@ ReportElement::ReportElement(const ElementsLocation &location, QString link_type
}
}
ReportElement::ReportElement(ElementLocation &location, QString link_type, QGraphicsItem *parent, int *state) :
CustomElement(location, parent, state),
m_text_field (nullptr),
m_watched_conductor (nullptr)
{
/*
* Get text tagged label. This is work for report
* create after the revision 3559.
* for report create before, we take the first text field
* because report haven't got a text field tagged label
*/
m_text_field = taggedText("label");
if (!m_text_field && !texts().isEmpty())
m_text_field = texts().first();
if (m_text_field)
m_text_field -> setNoEditable();
link_type == "next_report"? link_type_=NextReport : link_type_=PreviousReport;
link_type == "next_report"? inverse_report=PreviousReport : inverse_report=NextReport;
//We make these connections, to be always aware about the conductor properties
if (terminals().size())
{
connect (terminals().first(), &Terminal::conductorWasAdded, this, &ReportElement::conductorWasAdded);
connect (terminals().first(), &Terminal::conductorWasRemoved, this, &ReportElement::conductorWasRemoved);
}
}
/**
* @brief ReportElement::~ReportElement
* Destructor

View File

@@ -33,6 +33,7 @@ class ReportElement : public CustomElement
public :
explicit ReportElement(const ElementsLocation &,QString link_type, QGraphicsItem * = 0, int * = 0);
explicit ReportElement(ElementLocation &location, QString link_type, QGraphicsItem *parent = nullptr, int *state = nullptr);
~ReportElement();
virtual void linkToElement(Element *);
virtual void unlinkAllElements();

View File

@@ -33,6 +33,14 @@ SimpleElement::SimpleElement(const ElementsLocation &location, QGraphicsItem *qg
connect(this, SIGNAL(elementInfoChange(DiagramContext, DiagramContext)), this, SLOT(updateLabel(DiagramContext, DiagramContext)));
}
SimpleElement::SimpleElement(ElementLocation &location, QGraphicsItem *parent, int *state) :
CustomElement(location, parent, state),
m_comment_item (nullptr)
{
link_type_ = Simple;
connect(this, SIGNAL(elementInfoChange(DiagramContext, DiagramContext)), this, SLOT(updateLabel(DiagramContext, DiagramContext)));
}
/**
* @brief SimpleElement::~SimpleElement
*/

View File

@@ -33,6 +33,7 @@ class SimpleElement : public CustomElement {
public :
explicit SimpleElement(const ElementsLocation &, QGraphicsItem * = 0, int * = 0);
explicit SimpleElement(ElementLocation &location, QGraphicsItem *parent = nullptr, int *state = nullptr);
~SimpleElement();
virtual void initLink(QETProject *project);

View File

@@ -32,7 +32,14 @@
SlaveElement::SlaveElement(const ElementsLocation &location, QGraphicsItem *qgi, int *state) :
CustomElement(location, qgi, state)
{
Xref_item = NULL;
Xref_item = nullptr;
link_type_ = Slave;
}
SlaveElement::SlaveElement(ElementLocation &location, QGraphicsItem *parent, int *state) :
CustomElement(location, parent, state)
{
Xref_item = nullptr;
link_type_ = Slave;
}

View File

@@ -25,6 +25,7 @@ class SlaveElement : public CustomElement
Q_OBJECT
public:
explicit SlaveElement (const ElementsLocation &, QGraphicsItem * = 0, int * = 0);
explicit SlaveElement(ElementLocation &location, QGraphicsItem *parent = nullptr, int *state = nullptr);
~SlaveElement();
virtual void linkToElement(Element *elmt);
virtual void unlinkAllElements();

View File

@@ -31,4 +31,10 @@ TerminalElement::TerminalElement(const ElementsLocation &location, QGraphicsItem
link_type_ = Terminale;
}
TerminalElement::TerminalElement(ElementLocation &location, QGraphicsItem *parent, int *state) :
CustomElement(location, parent, state)
{
link_type_ = Terminale;
}
TerminalElement::~TerminalElement() {}

View File

@@ -25,6 +25,7 @@ class TerminalElement : public CustomElement
Q_OBJECT
public:
TerminalElement(const ElementsLocation &, QGraphicsItem * = 0, int * = 0);
TerminalElement (ElementLocation &location, QGraphicsItem *parent = nullptr, int *state = nullptr);
~TerminalElement();
};