9#include "AbstractTreeModel.h"
14#include <QFutureWatcher>
21#include <QtConcurrentFilter>
23#include <QtConcurrentMap>
29#include "BusyLeafItem.h"
31#include "ControlMeasure.h"
32#include "ControlNet.h"
33#include "ControlPoint.h"
34#include "IException.h"
36#include "AbstractTreeItem.h"
37#include "FilterWidget.h"
43 QObject *parent) : QObject(parent), m_view(v), m_cNet(controlNet) {
45 m_filterWatcher = NULL;
46 m_rebuildWatcher = NULL;
49 m_expandedState = NULL;
50 m_selectedState = NULL;
51 m_guisFilterWidget = NULL;
52 m_localFilterWidgetCopy = NULL;
55 m_busyItem =
new BusyLeafItem(NULL);
56 rootItem =
new RootItem;
64 connect(m_filterWatcher, SIGNAL(finished()),
this, SLOT(applyFilterDone()));
65 connect(m_rebuildWatcher, SIGNAL(finished()),
this, SLOT(rebuildItemsDone()));
67 connect(m_filterWatcher, SIGNAL(progressValueChanged(
int)),
68 this, SIGNAL(filterProgressChanged(
int)));
69 connect(m_filterWatcher, SIGNAL(progressRangeChanged(
int,
int)),
70 this, SIGNAL(filterProgressRangeChanged(
int,
int)));
71 connect(m_rebuildWatcher, SIGNAL(progressValueChanged(
int)),
72 this, SIGNAL(rebuildProgressChanged(
int)));
73 connect(m_rebuildWatcher, SIGNAL(progressRangeChanged(
int,
int)),
74 this, SIGNAL(rebuildProgressRangeChanged(
int,
int)));
77 m_filterAgain =
false;
78 m_filterRunning =
false;
79 m_rebuildRunning =
false;
81 m_rebuildPending =
false;
85 AbstractTreeModel::~AbstractTreeModel() {
86 delete m_filterWatcher;
87 m_filterWatcher = NULL;
89 delete m_rebuildWatcher;
90 m_rebuildWatcher = NULL;
98 delete m_expandedState;
99 m_expandedState = NULL;
101 delete m_selectedState;
102 m_selectedState = NULL;
107 delete m_localFilterWidgetCopy;
108 m_localFilterWidgetCopy = NULL;
110 m_guisFilterWidget = NULL;
119 InterestingItemsFlag flags,
bool ignoreExpansion) {
121 int rowCount = end - start;
122 const AbstractTreeItem *lastVisibleFilteredItem =
123 rootItem->getLastVisibleFilteredItem();
125 bool grabToEnd = (start >= 0 && end < 0);
127 if (lastVisibleFilteredItem && (rowCount > 0 || grabToEnd) &&
128 rootItem->childCount()) {
130 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
132 if (currentItem && !itemIsInteresting(currentItem, flags)) {
133 currentItem = nextItem(currentItem, flags, ignoreExpansion);
136 bool listStillValid =
true;
138 while (row < start && listStillValid && currentItem) {
140 listStillValid = (currentItem != lastVisibleFilteredItem ||
141 currentItem == currentItem->parent()->getLastVisibleChild());
144 currentItem = nextItem(currentItem, flags, ignoreExpansion);
147 while ((row < end || grabToEnd) && listStillValid && currentItem) {
148 foundItems.append(currentItem);
149 listStillValid = (currentItem != lastVisibleFilteredItem ||
150 currentItem == currentItem->parent()->getLastVisibleChild());
154 currentItem = nextItem(currentItem, flags, ignoreExpansion);
160 while (!grabToEnd && isFiltering() && foundItems.size() < rowCount) {
161 foundItems.append(m_busyItem);
170 AbstractTreeItem *item1, AbstractTreeItem *item2,
171 InterestingItemsFlag flags,
bool ignoreExpansion) {
174 if (rootItem->childCount()) {
175 AbstractTreeItem *start = NULL;
177 AbstractTreeItem *curItem = rootItem->getFirstVisibleChild();
179 while (!start && curItem) {
180 if (curItem == item1)
182 else if (curItem == item2)
186 curItem = nextItem(curItem, flags, ignoreExpansion);
190 QString msg =
"The first item passed to getItems(AbstractTreeItem*, "
191 "AbstractTreeItem*) is not visible in this model's tree";
192 throw IException(IException::Programmer, msg, _FILEINFO_);
195 AbstractTreeItem *end = item2;
202 AbstractTreeItem *
const &);
205 if (start == item2) {
210 while (curItem && curItem != end) {
211 (foundItems.*someKindaPend)(curItem);
212 curItem = nextItem(curItem, flags, ignoreExpansion);
216 QString msg =
"The second item passed to getItems(AbstractTreeItem*, "
217 "AbstractTreeItem*) is not visible in this model's tree";
218 throw IException(IException::Programmer, msg, _FILEINFO_);
221 (foundItems.*someKindaPend)(end);
229 InterestingItemsFlag flags,
bool ignoreExpansion) {
232 if (!isFiltering()) {
233 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
235 if (currentItem && !itemIsInteresting(currentItem, flags))
236 currentItem = nextItem(currentItem, flags, ignoreExpansion);
238 while (currentItem) {
239 if (currentItem->isSelected())
240 selectedItems.append(currentItem);
242 currentItem = nextItem(currentItem, flags, ignoreExpansion);
246 return selectedItems;
250 QMutex *AbstractTreeModel::getMutex()
const {
255 int AbstractTreeModel::getItemCount(InterestingItemsFlag flags)
const {
256 return getItemCount(rootItem, flags);
260 int AbstractTreeModel::getTopLevelItemCount()
const {
261 return rootItem->childCount();
264 int AbstractTreeModel::getVisibleItemCount(InterestingItemsFlag flags,
265 bool ignoreExpansion)
const {
266 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
269 if (!isFiltering()) {
272 while (currentItem) {
273 if (itemIsInteresting(currentItem, flags)) {
277 currentItem = nextItem(currentItem, flags, ignoreExpansion);
285 int AbstractTreeModel::getVisibleTopLevelItemCount()
const {
286 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
289 if (!isFiltering()) {
292 while (currentItem) {
294 currentItem = currentItem->getNextVisiblePeer();
302 int AbstractTreeModel::indexOfVisibleItem(AbstractTreeItem
const *item,
303 InterestingItemsFlag flags,
bool ignoreExpansion)
const {
304 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
307 if (!isFiltering()) {
308 while (currentItem && currentItem != item) {
309 if (itemIsInteresting(currentItem, flags))
312 currentItem = nextItem(currentItem, flags, ignoreExpansion);
325 void AbstractTreeModel::setFrozen(
bool newFrozenState) {
326 m_frozen = newFrozenState;
328 if (m_rebuildPending) {
330 m_rebuildPending =
false;
339 bool AbstractTreeModel::isFrozen()
const {
344 void AbstractTreeModel::queueRebuild() {
345 m_rebuildPending =
true;
349 bool AbstractTreeModel::isFiltering()
const {
350 return m_filterRunning;
354 bool AbstractTreeModel::isRebuilding()
const {
355 return m_rebuildRunning;
359 void AbstractTreeModel::setFilter(FilterWidget *fw) {
360 m_guisFilterWidget = fw;
362 connect(m_guisFilterWidget, SIGNAL(filterChanged()),
363 this, SLOT(applyFilter()));
369 void AbstractTreeModel::clear() {
373 rootItem =
new RootItem;
377 ControlNet *AbstractTreeModel::getControlNetwork()
const {
383 AbstractTreeModel::getRebuildWatcher()
const {
384 return m_rebuildWatcher;
388 RootItem *AbstractTreeModel::getRootItem()
const {
393 TreeView *AbstractTreeModel::getView()
const {
398 void AbstractTreeModel::stopWorking() {
399 m_filterWatcher->cancel();
400 m_filterWatcher->waitForFinished();
401 m_rebuildWatcher->cancel();
402 m_rebuildWatcher->waitForFinished();
410 if (!isFiltering()) {
411 int visibleRowCount = 0;
414 if (rootItem && rootItem->getFirstVisibleChild()) {
417 while (current != NULL) {
418 int depth = current->getDepth();
421 maxWidth = qMax(maxWidth,
422 current->getDataWidth() + indentation * depth);
423 current = nextItem(current, AllItems,
false);
427 size = QSize(maxWidth, visibleRowCount);
434 void AbstractTreeModel::applyFilter() {
437 if (!m_frozen && !m_filterAgain && m_guisFilterWidget &&
438 m_rebuildWatcher->isFinished()) {
440 QFuture< QAtomicPointer< AbstractTreeItem> > futureRoot;
442 if (m_filterRunning) {
443 m_filterAgain =
true;
444 futureRoot = m_filterWatcher->future();
450 emit filterCountsChanged(-1, getTopLevelItemCount());
453 if (m_localFilterWidgetCopy) {
454 delete m_localFilterWidgetCopy;
455 m_localFilterWidgetCopy = NULL;
458 m_localFilterWidgetCopy =
new FilterWidget(*m_guisFilterWidget);
463 m_filterRunning =
true;
464 rootItem->setLastVisibleFilteredItem(NULL);
465 futureRoot = QtConcurrent::filteredReduced(rootItem->getChildren(),
466 FilterFunctor(m_localFilterWidgetCopy),
467 &FilterFunctor::updateTopLevelLinks,
468 QtConcurrent::OrderedReduce | QtConcurrent::SequentialReduce);
470 m_filterWatcher->setFuture(futureRoot);
476 void AbstractTreeModel::setGlobalSelection(
bool selected,
477 InterestingItemsFlag flags) {
478 selectItems(rootItem, selected, flags);
482 void AbstractTreeModel::selectItems(
483 AbstractTreeItem *item,
bool selected, InterestingItemsFlag flags) {
484 if (item && itemIsInteresting(item, flags)) {
485 item->setSelected(selected);
488 if (item->childCount()) {
489 foreach (AbstractTreeItem * childItem, item->getChildren()) {
490 selectItems(childItem, selected, flags);
496 bool AbstractTreeModel::itemIsInteresting(AbstractTreeItem *item,
497 InterestingItemsFlag flags) {
498 AbstractTreeItem::InternalPointerType pointerType =
499 item->getPointerType();
501 if ((pointerType == AbstractTreeItem::Point && flags.testFlag(PointItems)) ||
502 (pointerType == AbstractTreeItem::Measure && flags.testFlag(MeasureItems)) ||
503 (pointerType == AbstractTreeItem::ImageAndNet && flags.testFlag(ImageItems))) {
512 int AbstractTreeModel::getItemCount(AbstractTreeItem *item,
513 InterestingItemsFlag flags)
const {
516 if (item && itemIsInteresting(item, flags)) {
520 if (item->childCount()) {
521 foreach (AbstractTreeItem * childItem, item->getChildren()) {
522 count += getItemCount(childItem, flags);
530 AbstractTreeItem *AbstractTreeModel::nextItem(AbstractTreeItem *current,
531 InterestingItemsFlag flags,
bool ignoreExpansion)
const {
534 if ((ignoreExpansion || current->isExpanded()) &&
535 current->getFirstVisibleChild())
536 current = current->getFirstVisibleChild();
537 else if (current->getNextVisiblePeer())
538 current = current->getNextVisiblePeer();
539 else if (current->parent())
540 current = current->parent()->getNextVisiblePeer();
544 while (current && !itemIsInteresting(current, flags));
551 void AbstractTreeModel::applyFilterDone() {
552 m_filterRunning =
false;
555 m_filterAgain =
false;
559 emit modelModified();
560 emit filterCountsChanged(getVisibleTopLevelItemCount(),
561 getTopLevelItemCount());
566 void AbstractTreeModel::rebuildItemsDone() {
570 RootItem *newRoot = newRootPtr.loadAcquire();
572 if (newRoot && newRoot->childCount()) {
585 setRebuilding(
false);
586 emit modelModified();
590 AbstractTreeModel::FilterFunctor::FilterFunctor(
591 FilterWidget *fw) : m_filter(fw) {
595 AbstractTreeModel::FilterFunctor::FilterFunctor(FilterFunctor
const &other) {
596 m_filter = other.m_filter;
600 AbstractTreeModel::FilterFunctor::~FilterFunctor() {
604 bool AbstractTreeModel::FilterFunctor::operator()(
605 AbstractTreeItem *
const &item)
const {
611 AbstractTreeModel::FilterFunctor &
612 AbstractTreeModel::FilterFunctor::operator=(
FilterFunctor const &other) {
614 m_filter = other.m_filter;
620 void AbstractTreeModel::FilterFunctor::filterWorker(
621 AbstractTreeItem *item)
const {
622 switch (item->getPointerType()) {
624 case AbstractTreeItem::Point:
625 item->setVisible((!m_filter || m_filter->evaluate(
626 (ControlPoint *) item->getPointer())) ?
true :
false);
629 case AbstractTreeItem::Measure:
630 item->setVisible((!m_filter || m_filter->evaluate(
631 (ControlMeasure *) item->getPointer())) ?
true :
false);
634 case AbstractTreeItem::ImageAndNet:
635 item->setVisible((!m_filter || m_filter->evaluate(
636 (QPair<QString, ControlNet *> *) item->getPointer())) ?
true :
false);
639 case AbstractTreeItem::None:
640 item->setVisible(
true);
645 if (item->getFirstVisibleChild())
646 item->setFirstVisibleChild(NULL);
648 if (item->getLastVisibleChild())
649 item->setLastVisibleChild(NULL);
651 item->setNextVisiblePeer(NULL);
655 if (item->childCount()) {
656 for (
int i = 0; i < item->childCount(); i++) {
657 AbstractTreeItem *child = item->childAt(i);
660 if (child->isVisible()) {
661 if (!item->getFirstVisibleChild()) {
662 item->setFirstVisibleChild(child);
663 item->setLastVisibleChild(child);
666 item->getLastVisibleChild()->setNextVisiblePeer(child);
667 item->setLastVisibleChild(child);
675 void AbstractTreeModel::FilterFunctor::updateTopLevelLinks(
676 QAtomicPointer< AbstractTreeItem > & root,
677 AbstractTreeItem *
const &item) {
679 if ( root.testAndSetOrdered(NULL, item->parent()) ) {
680 AbstractTreeItem *loadedRoot = root.loadAcquire();
681 loadedRoot->setFirstVisibleChild(NULL);
682 loadedRoot->setLastVisibleChild(NULL);
683 loadedRoot->setLastVisibleFilteredItem(NULL);
687 AbstractTreeItem *loadedRoot = root.loadAcquire();
688 if (item->isVisible()) {
689 if (!loadedRoot->getFirstVisibleChild()) {
690 loadedRoot->setFirstVisibleChild(item);
691 loadedRoot->setLastVisibleChild(item);
694 loadedRoot->getLastVisibleChild()->setNextVisiblePeer(item);
695 loadedRoot->setLastVisibleChild(item);
698 loadedRoot->setLastVisibleFilteredItem(item);
Base class for an item in the tree.
QSize getVisibleSize(int indentation) const
indentation is in pixels
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.