QElectroTech  0.70
elementscollectionmodel.cpp
Go to the documentation of this file.
1 /*
2  Copyright 2006-2019 The QElectroTech Team
3  This file is part of QElectroTech.
4 
5  QElectroTech is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 2 of the License, or
8  (at your option) any later version.
9 
10  QElectroTech is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
17 */
19 #include "elementcollectionitem.h"
22 #include "qetapp.h"
23 #include "xmlelementcollection.h"
24 #include "qetproject.h"
26 
27 #include <QtConcurrent>
28 
35  QStandardItemModel(parent)
36 {
37 }
38 
46 QVariant ElementsCollectionModel::data(const QModelIndex &index, int role) const
47 {
48  if (role == Qt::DecorationRole) {
49  QStandardItem *item = itemFromIndex(index);
50 
51  if (item->type() == FileElementCollectionItem::Type)
52  static_cast<FileElementCollectionItem*>(item)->setUpIcon();
53  else if (item->type() == XmlProjectElementCollectionItem::Type)
54  static_cast<XmlProjectElementCollectionItem*>(item)->setUpIcon();
55  }
56 
57  return QStandardItemModel::data(index, role);
58 }
59 
66 QMimeData *ElementsCollectionModel::mimeData(const QModelIndexList &indexes) const
67 {
68  QModelIndex index = indexes.first();
69  if (index.isValid())
70  {
71  ElementCollectionItem *item = static_cast<ElementCollectionItem*>(itemFromIndex(index));
72 
73  QMimeData *mime_data = new QMimeData();
74  mime_data->setText(item->collectionPath());
75 
76  if (item->isElement())
77  mime_data->setData("application/x-qet-element-uri", item->collectionPath().toLatin1());
78  else
79  mime_data->setData("application/x-qet-category-uri", item->collectionPath().toLatin1());
80 
81  return mime_data;
82  }
83  else
84  return new QMimeData();
85 }
86 
93 {
94  QStringList mime_list = QAbstractItemModel::mimeTypes();
95  mime_list << "application/x-qet-element-uri" << "application/x-qet-category-uri";
96  return mime_list;
97 }
98 
109 bool ElementsCollectionModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const
110 {
111  if (!(QStandardItemModel::canDropMimeData(data, action, row, column, parent) && parent.isValid()))
112  return false;
113 
114  QStandardItem *qsi = itemFromIndex(parent.child(row, column));
115  if (!qsi)
116  qsi = itemFromIndex(parent);
117 
118  //Drop in the common collection is forbiden
119  if (qsi->type() == FileElementCollectionItem::Type)
120  if (static_cast<FileElementCollectionItem *>(qsi)->isCommonCollection())
121  return false;
122 
123  ElementCollectionItem *eci = static_cast<ElementCollectionItem *>(qsi);
124 
125  if (data->hasFormat("application/x-qet-element-uri") || data->hasFormat("application/x-qet-category-uri"))
126  {
127  //Return false if user try to drop a item from a folder to the same folder
128  ElementsLocation drop_location(data->text());
129  for (int i=0 ; i<eci->rowCount() ; i++)
130  if (static_cast<ElementCollectionItem *>(eci->child(i))->collectionPath() == drop_location.collectionPath())
131  return false;
132 
133  return true;
134  }
135  else
136  return false;
137 }
138 
149 bool ElementsCollectionModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
150 {
151  Q_UNUSED(action);
152 
153  QStandardItem *qsi = itemFromIndex(parent.child(row, column));
154  if (!qsi)
155  qsi = itemFromIndex(parent);
156 
157  if (qsi->type() == FileElementCollectionItem::Type)
158  {
159  FileElementCollectionItem *feci = static_cast<FileElementCollectionItem *>(qsi);
160 
161  if (feci->isCommonCollection())
162  return false;
163 
164  if (feci->isElement() && feci->parent() && feci->parent()->type() == FileElementCollectionItem::Type)
165  feci = static_cast<FileElementCollectionItem *>(feci->parent());
166 
168 
169  ElementsLocation source(data->text());
170  ElementsLocation destination(feci->fileSystemPath());
171  ElementsLocation location = ech.copy(source, destination);
172 
173  if (location.exist())
174  {
175  //If feci have a child with the same path of location,
176  //we remove the existing child befor insert new child
177  for (int i=0 ; i<feci->rowCount() ; i++) {
178  if (static_cast<FileElementCollectionItem *>(feci->child(i))->collectionPath() == location.collectionPath())
179  feci->removeRow(i);
180  }
181  feci->addChildAtPath(location.fileName());
182  return true;
183  }
184 
185  return false;
186  }
187  else if (qsi->type() == XmlProjectElementCollectionItem::Type) {
189 
190  if (xpeci->isElement() && xpeci->parent() && xpeci->parent()->type() == XmlProjectElementCollectionItem::Type)
191  xpeci = static_cast<XmlProjectElementCollectionItem *>(xpeci->parent());
192 
193  //before do the copy, we get all collection path of xpeci child,
194  //for remove it if the copied item have the same path of an existing child.
195  //We can't do this after the copy, because at the copy if the xml collection have a DomElement with the same path,
196  //he was removed before the new xml DomElement is inserted
197  //So the existing child of this will return a null QString when call collectionPath(), because the item
198  //doesn't exist anymore in the xml collection.
199  QList <QString> child_path_list;
200  for (int i=0 ; i<xpeci->rowCount() ; i++)
201  child_path_list.append(static_cast<XmlProjectElementCollectionItem *>(xpeci->child(i, 0))->collectionPath());
202 
204 
205  ElementsLocation source(data->text());
206  ElementsLocation destination(xpeci->collectionPath());
207  ElementsLocation location = ech.copy(source, destination);
208 
209  return location.exist();
210  }
211 
212  return false;
213 }
214 
226 void ElementsCollectionModel::loadCollections(bool common_collection, bool custom_collection, QList<QETProject *> projects)
227 {
228  QList <ElementCollectionItem *> list;
229 
230  if (common_collection)
231  addCommonCollection(false);
232  if (custom_collection)
233  addCustomCollection(false);
234 
235  if (common_collection || custom_collection)
236  list.append(items());
237 
238 
239  foreach (QETProject *project, projects) {
240  addProject(project, false);
241  list.append(projectItems(project));
242  }
243 
244  QFuture<void> futur = QtConcurrent::map(list, setUpData);
245  emit loadingMaxValue(futur.progressMaximum());
246  while (futur.isRunning()) {
247  emit loadingProgressValue(futur.progressValue());
248  }
249 }
250 
256 {
258  if (feci->setRootPath(QETApp::commonElementsDirN(), set_data, m_hide_element)) {
259  invisibleRootItem()->appendRow(feci);
260  if (set_data)
261  feci->setUpData();
262  }
263  else
264  delete feci;
265 }
266 
272 {
274  if (feci->setRootPath(QETApp::customElementsDirN(), set_data, m_hide_element)) {
275  invisibleRootItem()->appendRow(feci);
276  if (set_data)
277  feci->setUpData();
278  }
279  else
280  delete feci;
281 }
282 
290 {
291  QModelIndex index = indexFromLocation(location);
292  if (index.isValid())
293  return;
294 
295  ElementCollectionItem *last_item = nullptr;
296  QString collection_name;
297 
298  if (location.isProject()) {
299  QETProject *project = location.project();
300 
301  if (project) {
303 
304  last_item = xpeci->lastItemForPath(location.collectionPath(false), collection_name);
305  }
306  }
307  else if (location.isCustomCollection()) {
308  QList <ElementCollectionItem *> child_list;
309 
310  for (int i=0 ; i<rowCount() ; i++)
311  child_list.append(static_cast<ElementCollectionItem *>(item(i)));
312 
313  foreach(ElementCollectionItem *eci, child_list) {
314 
315  if (eci->type() == FileElementCollectionItem::Type) {
316  FileElementCollectionItem *feci = static_cast<FileElementCollectionItem *>(eci);
317 
318  if (feci->isCustomCollection()) {
319  last_item = feci->lastItemForPath(location.collectionPath(false), collection_name);
320  if(last_item)
321  break;
322  }
323  }
324  }
325  }
326 
327  if (last_item)
328  last_item->addChildAtPath(collection_name);
329 }
330 
337 void ElementsCollectionModel::addProject(QETProject *project, bool set_data)
338 {
339  if (m_project_list.contains(project))
340  return;
341 
342  m_project_list.append(project);
343  int row = m_project_list.indexOf(project);
345  m_project_hash.insert(project, xpeci);
346 
347  xpeci->setProject(project, set_data);
348  insertRow(row, xpeci);
349  if (set_data)
350  xpeci->setUpData();
352  connect(project->embeddedElementCollection(), &XmlElementCollection::elementChanged, this, &ElementsCollectionModel::updateItem);
355 }
356 
363 {
364  if (!m_project_list.contains(project))
365  return;
366 
367  int row = m_project_list.indexOf(project);
368  if (removeRows(row, 1, QModelIndex())) {
369  m_project_list.removeOne(project);
370  m_project_hash.remove(project);
372  disconnect(project->embeddedElementCollection(), &XmlElementCollection::elementChanged, this, &ElementsCollectionModel::updateItem);
375  }
376 }
377 
382 QList<QETProject *> ElementsCollectionModel::project() const
383 {
384  return m_project_list;
385 }
386 
393 {
394  QList <ElementsLocation> unused;
395 
396  foreach (QETProject *project, m_project_list)
397  unused.append(project->unusedElements());
398 
399  QBrush brush;
400  brush.setStyle(Qt::Dense4Pattern);
401  brush.setColor(Qt::red);
402 
403  foreach (ElementsLocation location, unused) {
404  QModelIndex index = indexFromLocation(location);
405  if (index.isValid()) {
406  QStandardItem *qsi = itemFromIndex(index);
407  if (qsi)
408  qsi->setBackground(brush);
409  }
410  }
411 }
412 
417 QList <ElementCollectionItem *> ElementsCollectionModel::items() const
418 {
419  QList <ElementCollectionItem *> list;
420 
421  for (int i=0 ; i<rowCount() ; i++) {
422  ElementCollectionItem *eci = static_cast<ElementCollectionItem *>(item(i));
423  list.append(eci);
424  list.append(eci->items());
425  }
426 
427  return list;
428 }
429 
435 QList<ElementCollectionItem *> ElementsCollectionModel::projectItems(QETProject *project) const
436 {
437  QList <ElementCollectionItem *> list;
438 
439  if (m_project_list.contains(project)) {
441  list.append(eci);
442  list.append(eci->items());
443  }
444 
445  return list;
446 }
447 
453 {
454  m_hide_element = true;
455  foreach(ElementCollectionItem *eci, items()) {
456  if (eci->isElement()) {
457  removeRow(eci->row(), indexFromItem(eci).parent());
458  }
459  }
460 }
461 
470 {
471  QList <ElementCollectionItem *> child_list;
472 
473  for (int i=0 ; i<rowCount() ; i++)
474  child_list.append(static_cast<ElementCollectionItem *>(item(i)));
475 
476  foreach(ElementCollectionItem *eci, child_list) {
477 
478  ElementCollectionItem *match_eci = nullptr;
479 
480  if (eci->type() == FileElementCollectionItem::Type) {
481  if (FileElementCollectionItem *feci = static_cast<FileElementCollectionItem *>(eci)) {
482  if ( (location.isCommonCollection() && feci->isCommonCollection()) ||
483  (location.isCustomCollection() && !feci->isCommonCollection()) ) {
484  match_eci = feci->itemAtPath(location.collectionPath(false));
485  }
486  }
487  }
488  else if (eci->type() == XmlProjectElementCollectionItem::Type) {
489  if (XmlProjectElementCollectionItem *xpeci = static_cast<XmlProjectElementCollectionItem *>(eci)) {
490  match_eci = xpeci->itemAtPath(location.collectionPath(false));
491  }
492  }
493 
494  if (match_eci)
495  return indexFromItem(match_eci);
496  }
497 
498  return QModelIndex();
499 }
500 
508 {
509  QObject *object = sender();
510  XmlElementCollection *collection = static_cast<XmlElementCollection *> (object);
511  if (!collection)
512  return;
513 
514  QETProject *project = nullptr;
515 
516  //Get the owner project of the collection
517  foreach (QETProject *prj, m_project_list) {
518  if (prj->embeddedElementCollection() == collection) {
519  project = prj;
520  }
521  }
522 
523  if (project) {
525 
526  QString collection_name;
527  ElementCollectionItem *eci = xpeci->lastItemForPath(path, collection_name);
528  if (!eci)
529  return;
530 
531  eci->addChildAtPath(collection_name);
532  }
533 }
534 
541 {
542  QObject *object = sender();
543  XmlElementCollection *collection = static_cast<XmlElementCollection *> (object);
544  if (!collection)
545  return;
546 
547  QETProject *project = nullptr;
548 
549  //Get the owner project of the collection
550  foreach (QETProject *prj, m_project_list) {
551  if (prj->embeddedElementCollection() == collection) {
552  project = prj;
553  }
554  }
555 
556  if (project) {
557  QModelIndex index = indexFromLocation(ElementsLocation(path, project));
558  if (index.isValid())
559  removeRow(index.row(), index.parent());
560  }
561 }
562 
568 void ElementsCollectionModel::updateItem(const QString& path)
569 {
570  QObject *object = sender();
571  XmlElementCollection *collection = static_cast<XmlElementCollection *> (object);
572  if (!collection)
573  return;
574 
575  QETProject *project = nullptr;
576 
577  //Get the owner project of the collection
578  foreach (QETProject *prj, m_project_list) {
579  if (prj->embeddedElementCollection() == collection) {
580  project = prj;
581  }
582  }
583 
584  if (project) {
585  ElementCollectionItem *eci = m_project_hash.value(project)->itemAtPath(path);
586  if (!eci)
587  return;
588 
589  eci->clearData();
590  eci->setUpData();
591  }
592 }
The ElementCollectionItem class This class represent a item (a directory or an element) in a element ...
virtual void clearData()
ElementCollectionItem::clearData Reset the data.
bool isProject() const
ElementsLocation::isProject.
virtual void addChildAtPath(const QString &collection_name)=0
void addCommonCollection(bool set_data=true)
ElementsCollectionModel::addCommonCollection Add the common elements collection to this model...
int type() const override
QVariant data(const QModelIndex &index, int role) const override
ElementsCollectionModel::data Reimplemented from QStandardItemModel.
ElementsLocation copy(ElementsLocation &source, ElementsLocation &destination)
ElementCollectionHandler::copy Copy the content of collection represented by source to the collection...
bool isCustomCollection() const
FileElementCollectionItem::isCustomCollection.
QString collectionPath() const override
XmlProjectElementCollectionItem::collectionPath.
QList< ElementCollectionItem * > projectItems(QETProject *project) const
ElementsCollectionModel::projectItems.
void highlightUnusedElement()
ElementsCollectionModel::highlightUnusedElement Highlight every unused element of managed project...
void setUpData() override
XmlProjectElementCollectionItem::setUpData SetUp the data of this item.
void elementAdded(QString collection_path)
elementAdded This signal is emited when a element is added to this collection
ElementsCollectionModel(QObject *parent=Q_NULLPTR)
ElementsCollectionModel::ElementsCollectionModel Constructor.
QList< ElementCollectionItem * > items() const
ElementCollectionItem::items.
void loadingProgressValue(int)
QHash< QETProject *, XmlProjectElementCollectionItem * > m_project_hash
QList< QETProject * > project() const
ElementsCollectionModel::project.
void setUpData(ElementCollectionItem *eci)
QStringList mimeTypes() const override
ElementsCollectionModel::mimeTypes Reimplemented from QStandardItemModel.
The XmlProjectElementCollectionItem class This class specialise ElementCollectionItem for manage an x...
XmlElementCollection * embeddedElementCollection() const
QETProject::embeddedCollection.
Definition: qetproject.cpp:229
void removeProject(QETProject *project)
ElementsCollectionModel::removeProject Remove project from this model.
ElementCollectionItem * itemAtPath(const QString &path)
ElementCollectionItem::itemAtPath.
void addChildAtPath(const QString &collection_name) override
FileElementCollectionItem::addChildAtPath Ask to this item item to add a child with collection name ...
void loadCollections(bool common_collection, bool custom_collection, QList< QETProject *> projects)
ElementsCollectionModel::loadCollections Load the several collections in this model. Prefer use this method instead of addCommonCollection, addCustomCollection and addProject, because it use multithreading to speed up the loading. This method emit loadingMaxValue(int) for know the maximum progress value This method emit loadingProgressValue(int) for know the current progress value.
ElementCollectionItem * lastItemForPath(const QString &path, QString &no_found_path)
ElementCollectionItem::lastItemForPath Return the last existing item in this ElementCollectionItem hi...
void elementChanged(QString collection_path)
elementChanged This signal is emited when the defintion of the element at path was changed ...
void elementIntegratedToCollection(const QString &path)
ElementsCollectionModel::elementIntegratedToCollection When an element is added to embedded collectio...
QList< ElementCollectionItem * > items() const
ElementsCollectionModel::items.
QETProject * project() const
QString collectionPath(bool protocol=true) const
bool isCommonCollection() const
FileElementCollectionItem::isCommonCollection.
void elementRemoved(QString collection_path)
elementRemoved This signal is emited when an element is removed to this collection ...
bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override
ElementsCollectionModel::canDropMimeData Reimplemented from QStandardItemModel.
void addLocation(const ElementsLocation &location)
ElementsCollectionModel::addLocation Add the element or directory to this model. If the location is a...
void hideElement()
ElementsCollectionModel::hideElement Hide element in this model, only directory is managed...
QList< QETProject * > m_project_list
void itemRemovedFromCollection(const QString &path)
ElementsCollectionModel::itemRemovedFromCollection This method must be called by a signal...
void updateItem(const QString &path)
ElementsCollectionModel::updateItem Update the item at path.
bool exist() const
ElementsLocation::exist.
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
ElementsCollectionModel::dropMimeData Reimplemented from QStandardItemModel.
void addProject(QETProject *project, bool set_data=true)
ElementsCollectionModel::addProject Add project to this model.
void setProject(QETProject *project, bool set_data=true, bool hide_element=false)
XmlProjectElementCollectionItem::setProject Set the project for this item. Use this method for set th...
QMimeData * mimeData(const QModelIndexList &indexes) const override
ElementsCollectionModel::mimeData Reimplemented from QStandardItemModel.
virtual bool isElement() const =0
void setUpData() override
FileElementCollectionItem::setUpData SetUp the data of this item.
The FileElementCollectionItem class This class specialise ElementCollectionItem for manage a collecti...
void addCustomCollection(bool set_data=true)
ElementsCollectionModel::addCustomCollection Add the custom elements collection to this model...
void directoryRemoved(QString collection_path)
directoryRemoved This signal is emited when a directory is removed to this collection ...
virtual QString collectionPath() const =0
bool setRootPath(const QString &path, bool set_data=true, bool hide_element=false)
FileElementCollectionItem::setRootPath Set path has root path for this file item. Use this function o...
static QString customElementsDirN()
QETApp::customElementsDirN like QString QETApp::customElementsDir but without "/" at the end...
Definition: qetapp.cpp:598
QString fileSystemPath() const
FileElementCollectionItem::fileSystemPath.
bool isCommonCollection() const
ElementsLocation::isCommonCollection.
bool isCustomCollection() const
ElementsLocation::isCustomCollection.
static QString commonElementsDirN()
QETApp::commonElementsDirN like QString QETApp::commonElementsDir but without "/" at the end...
Definition: qetapp.cpp:586
virtual void setUpData()=0
bool isElement() const override
FileElementCollectionItem::isElement.
bool isElement() const override
XmlProjectElementCollectionItem::isElement.
The XmlElementCollection class This class represent a collection of elements stored to xml...
The ElementCollectionHandler class Provide several method to copy element or directory from a collect...
QModelIndex indexFromLocation(const ElementsLocation &location)
ElementsCollectionModel::indexFromLocation Return the index who represent . Index can be non valid...