11 #include "AbstractTreeModel.h"
16 #include <QFutureWatcher>
18 #include <QModelIndex>
23 #include <QtConcurrentFilter>
25 #include <QtConcurrentMap>
31 #include "BusyLeafItem.h"
33 #include "ControlMeasure.h"
34 #include "ControlNet.h"
35 #include "ControlPoint.h"
36 #include "IException.h"
38 #include "AbstractTreeItem.h"
39 #include "FilterWidget.h"
44 AbstractTreeModel::AbstractTreeModel(ControlNet *controlNet, TreeView *v,
45 QObject *parent) :
QObject(parent), m_view(v), m_cNet(controlNet) {
48 m_filterWatcher = NULL;
49 m_rebuildWatcher = NULL;
52 m_expandedState = NULL;
53 m_selectedState = NULL;
54 m_guisFilterWidget = NULL;
55 m_localFilterWidgetCopy = NULL;
58 m_busyItem =
new BusyLeafItem(NULL);
59 rootItem =
new RootItem;
67 connect(m_filterWatcher, SIGNAL(finished()),
this, SLOT(applyFilterDone()));
68 connect(m_rebuildWatcher, SIGNAL(finished()),
this, SLOT(rebuildItemsDone()));
70 connect(m_filterWatcher, SIGNAL(progressValueChanged(
int)),
71 this, SIGNAL(filterProgressChanged(
int)));
72 connect(m_filterWatcher, SIGNAL(progressRangeChanged(
int,
int)),
73 this, SIGNAL(filterProgressRangeChanged(
int,
int)));
74 connect(m_rebuildWatcher, SIGNAL(progressValueChanged(
int)),
75 this, SIGNAL(rebuildProgressChanged(
int)));
76 connect(m_rebuildWatcher, SIGNAL(progressRangeChanged(
int,
int)),
77 this, SIGNAL(rebuildProgressRangeChanged(
int,
int)));
80 m_filterAgain =
false;
81 m_filterRunning =
false;
82 m_rebuildRunning =
false;
84 m_rebuildPending =
false;
88 AbstractTreeModel::~AbstractTreeModel() {
89 delete m_filterWatcher;
90 m_filterWatcher = NULL;
92 delete m_rebuildWatcher;
93 m_rebuildWatcher = NULL;
101 delete m_expandedState;
102 m_expandedState = NULL;
104 delete m_selectedState;
105 m_selectedState = NULL;
110 delete m_localFilterWidgetCopy;
111 m_localFilterWidgetCopy = NULL;
113 m_guisFilterWidget = NULL;
122 InterestingItemsFlag flags,
bool ignoreExpansion) {
124 int rowCount = end - start;
125 const AbstractTreeItem *lastVisibleFilteredItem =
126 rootItem->getLastVisibleFilteredItem();
128 bool grabToEnd = (start >= 0 && end < 0);
130 if (lastVisibleFilteredItem && (rowCount > 0 || grabToEnd) &&
131 rootItem->childCount()) {
133 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
135 if (currentItem && !itemIsInteresting(currentItem, flags)) {
136 currentItem = nextItem(currentItem, flags, ignoreExpansion);
139 bool listStillValid =
true;
141 while (row < start && listStillValid && currentItem) {
143 listStillValid = (currentItem != lastVisibleFilteredItem ||
144 currentItem == currentItem->parent()->getLastVisibleChild());
147 currentItem = nextItem(currentItem, flags, ignoreExpansion);
150 while ((row < end || grabToEnd) && listStillValid && currentItem) {
152 foundItems.append(currentItem);
153 listStillValid = (currentItem != lastVisibleFilteredItem ||
154 currentItem == currentItem->parent()->getLastVisibleChild());
158 currentItem = nextItem(currentItem, flags, ignoreExpansion);
164 while (!grabToEnd && isFiltering() && foundItems.size() < rowCount) {
165 foundItems.append(m_busyItem);
174 AbstractTreeItem *item1, AbstractTreeItem *item2,
175 InterestingItemsFlag flags,
bool ignoreExpansion) {
178 if (rootItem->childCount()) {
179 AbstractTreeItem *start = NULL;
181 AbstractTreeItem *curItem = rootItem->getFirstVisibleChild();
183 while (!start && curItem) {
184 if (curItem == item1)
186 else if (curItem == item2)
190 curItem = nextItem(curItem, flags, ignoreExpansion);
194 QString msg =
"The first item passed to getItems(AbstractTreeItem*, "
195 "AbstractTreeItem*) is not visible in this model's tree";
199 AbstractTreeItem *end = item2;
206 AbstractTreeItem *
const &);
209 if (start == item2) {
214 while (curItem && curItem != end) {
215 (foundItems.*someKindaPend)(curItem);
216 curItem = nextItem(curItem, flags, ignoreExpansion);
220 QString msg =
"The second item passed to getItems(AbstractTreeItem*, "
221 "AbstractTreeItem*) is not visible in this model's tree";
225 (foundItems.*someKindaPend)(end);
233 InterestingItemsFlag flags,
bool ignoreExpansion) {
238 if (!isFiltering()) {
239 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
241 if (currentItem && !itemIsInteresting(currentItem, flags))
242 currentItem = nextItem(currentItem, flags, ignoreExpansion);
244 while (currentItem) {
245 if (currentItem->isSelected())
246 selectedItems.append(currentItem);
248 currentItem = nextItem(currentItem, flags, ignoreExpansion);
252 return selectedItems;
256 QMutex *AbstractTreeModel::getMutex()
const {
261 int AbstractTreeModel::getItemCount(InterestingItemsFlag flags)
const {
262 return getItemCount(rootItem, flags);
266 int AbstractTreeModel::getTopLevelItemCount()
const {
267 return rootItem->childCount();
270 int AbstractTreeModel::getVisibleItemCount(InterestingItemsFlag flags,
271 bool ignoreExpansion)
const {
272 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
275 if (!isFiltering()) {
278 while (currentItem) {
279 if (itemIsInteresting(currentItem, flags)) {
283 currentItem = nextItem(currentItem, flags, ignoreExpansion);
291 int AbstractTreeModel::getVisibleTopLevelItemCount()
const {
292 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
295 if (!isFiltering()) {
298 while (currentItem) {
300 currentItem = currentItem->getNextVisiblePeer();
308 int AbstractTreeModel::indexOfVisibleItem(AbstractTreeItem
const *item,
309 InterestingItemsFlag flags,
bool ignoreExpansion)
const {
310 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
313 if (!isFiltering()) {
314 while (currentItem && currentItem != item) {
315 if (itemIsInteresting(currentItem, flags))
318 currentItem = nextItem(currentItem, flags, ignoreExpansion);
331 void AbstractTreeModel::setFrozen(
bool newFrozenState) {
332 m_frozen = newFrozenState;
334 if (m_rebuildPending) {
336 m_rebuildPending =
false;
345 bool AbstractTreeModel::isFrozen()
const {
350 void AbstractTreeModel::queueRebuild() {
351 m_rebuildPending =
true;
355 bool AbstractTreeModel::isFiltering()
const {
356 return m_filterRunning;
360 bool AbstractTreeModel::isRebuilding()
const {
361 return m_rebuildRunning;
365 void AbstractTreeModel::setFilter(FilterWidget *fw) {
366 m_guisFilterWidget = fw;
368 connect(m_guisFilterWidget, SIGNAL(filterChanged()),
369 this, SLOT(applyFilter()));
375 void AbstractTreeModel::clear() {
380 rootItem =
new RootItem;
384 ControlNet *AbstractTreeModel::getControlNetwork()
const {
390 AbstractTreeModel::getRebuildWatcher()
const {
391 return m_rebuildWatcher;
395 RootItem *AbstractTreeModel::getRootItem()
const {
400 TreeView *AbstractTreeModel::getView()
const {
405 void AbstractTreeModel::stopWorking() {
406 m_filterWatcher->cancel();
407 m_filterWatcher->waitForFinished();
408 m_rebuildWatcher->cancel();
409 m_rebuildWatcher->waitForFinished();
417 if (!isFiltering()) {
418 int visibleRowCount = 0;
421 if (rootItem && rootItem->getFirstVisibleChild()) {
424 while (current != NULL) {
425 int depth = current->getDepth();
428 maxWidth = qMax(maxWidth,
429 current->getDataWidth() + indentation * depth);
430 current = nextItem(current, AllItems,
false);
434 size = QSize(maxWidth, visibleRowCount);
441 void AbstractTreeModel::applyFilter() {
444 if (!m_frozen && !m_filterAgain && m_guisFilterWidget &&
445 m_rebuildWatcher->isFinished()) {
447 QFuture< QAtomicPointer< AbstractTreeItem> > futureRoot;
449 if (m_filterRunning) {
450 m_filterAgain =
true;
451 futureRoot = m_filterWatcher->future();
460 if (m_localFilterWidgetCopy) {
461 delete m_localFilterWidgetCopy;
462 m_localFilterWidgetCopy = NULL;
465 m_localFilterWidgetCopy =
new FilterWidget(*m_guisFilterWidget);
470 m_filterRunning =
true;
471 rootItem->setLastVisibleFilteredItem(NULL);
472 futureRoot = QtConcurrent::filteredReduced(rootItem->getChildren(),
473 FilterFunctor(m_localFilterWidgetCopy),
474 &FilterFunctor::updateTopLevelLinks,
475 QtConcurrent::OrderedReduce | QtConcurrent::SequentialReduce);
477 m_filterWatcher->setFuture(futureRoot);
483 void AbstractTreeModel::setGlobalSelection(
bool selected,
484 InterestingItemsFlag flags) {
485 selectItems(rootItem, selected, flags);
489 void AbstractTreeModel::selectItems(
490 AbstractTreeItem *item,
bool selected, InterestingItemsFlag flags) {
491 if (item && itemIsInteresting(item, flags)) {
492 item->setSelected(selected);
495 if (item->childCount()) {
496 foreach (AbstractTreeItem * childItem, item->getChildren()) {
497 selectItems(childItem, selected, flags);
503 bool AbstractTreeModel::itemIsInteresting(AbstractTreeItem *item,
504 InterestingItemsFlag flags) {
505 AbstractTreeItem::InternalPointerType pointerType =
506 item->getPointerType();
508 if ((pointerType == AbstractTreeItem::Point && flags.testFlag(PointItems)) ||
509 (pointerType == AbstractTreeItem::Measure && flags.testFlag(MeasureItems)) ||
510 (pointerType == AbstractTreeItem::ImageAndNet && flags.testFlag(ImageItems))) {
519 int AbstractTreeModel::getItemCount(AbstractTreeItem *item,
520 InterestingItemsFlag flags)
const {
523 if (item && itemIsInteresting(item, flags)) {
527 if (item->childCount()) {
528 foreach (AbstractTreeItem * childItem, item->getChildren()) {
529 count += getItemCount(childItem, flags);
537 AbstractTreeItem *AbstractTreeModel::nextItem(AbstractTreeItem *current,
538 InterestingItemsFlag flags,
bool ignoreExpansion)
const {
541 if ((ignoreExpansion || current->isExpanded()) &&
542 current->getFirstVisibleChild())
543 current = current->getFirstVisibleChild();
544 else if (current->getNextVisiblePeer())
545 current = current->getNextVisiblePeer();
546 else if (current->parent())
547 current = current->parent()->getNextVisiblePeer();
551 while (current && !itemIsInteresting(current, flags));
558 void AbstractTreeModel::applyFilterDone() {
559 m_filterRunning =
false;
562 m_filterAgain =
false;
566 emit modelModified();
568 getTopLevelItemCount());
573 void AbstractTreeModel::rebuildItemsDone() {
577 RootItem *newRoot = newRootPtr.loadAcquire();
579 if (newRoot && newRoot->childCount()) {
593 setRebuilding(
false);
594 emit modelModified();
598 AbstractTreeModel::FilterFunctor::FilterFunctor(
599 FilterWidget *fw) : m_filter(fw) {
603 AbstractTreeModel::FilterFunctor::FilterFunctor(FilterFunctor
const &other) {
604 m_filter = other.m_filter;
608 AbstractTreeModel::FilterFunctor::~FilterFunctor() {
612 bool AbstractTreeModel::FilterFunctor::operator()(
613 AbstractTreeItem *
const &item)
const {
619 AbstractTreeModel::FilterFunctor &
620 AbstractTreeModel::FilterFunctor::operator=(FilterFunctor
const &other) {
622 m_filter = other.m_filter;
628 void AbstractTreeModel::FilterFunctor::filterWorker(
629 AbstractTreeItem *item)
const {
630 switch (item->getPointerType()) {
632 case AbstractTreeItem::Point:
633 item->setVisible((!m_filter || m_filter->evaluate(
634 (ControlPoint *) item->getPointer())) ?
true :
false);
637 case AbstractTreeItem::Measure:
638 item->setVisible((!m_filter || m_filter->evaluate(
639 (ControlMeasure *) item->getPointer())) ?
true :
false);
642 case AbstractTreeItem::ImageAndNet:
643 item->setVisible((!m_filter || m_filter->evaluate(
647 case AbstractTreeItem::None:
648 item->setVisible(
true);
653 if (item->getFirstVisibleChild())
654 item->setFirstVisibleChild(NULL);
656 if (item->getLastVisibleChild())
657 item->setLastVisibleChild(NULL);
659 item->setNextVisiblePeer(NULL);
663 if (item->childCount()) {
664 for (
int i = 0; i < item->childCount(); i++) {
665 AbstractTreeItem *child = item->childAt(i);
668 if (child->isVisible()) {
669 if (!item->getFirstVisibleChild()) {
670 item->setFirstVisibleChild(child);
671 item->setLastVisibleChild(child);
674 item->getLastVisibleChild()->setNextVisiblePeer(child);
675 item->setLastVisibleChild(child);
683 void AbstractTreeModel::FilterFunctor::updateTopLevelLinks(
685 AbstractTreeItem *
const &item) {
687 if ( root.testAndSetOrdered(NULL, item->parent()) ) {
688 AbstractTreeItem *loadedRoot = root.loadAcquire();
689 loadedRoot->setFirstVisibleChild(NULL);
690 loadedRoot->setLastVisibleChild(NULL);
691 loadedRoot->setLastVisibleFilteredItem(NULL);
695 AbstractTreeItem *loadedRoot = root.loadAcquire();
696 if (item->isVisible()) {
697 if (!loadedRoot->getFirstVisibleChild()) {
698 loadedRoot->setFirstVisibleChild(item);
699 loadedRoot->setLastVisibleChild(item);
702 loadedRoot->getLastVisibleChild()->setNextVisiblePeer(item);
703 loadedRoot->setLastVisibleChild(item);
706 loadedRoot->setLastVisibleFilteredItem(item);