3 #include "AbstractTreeModel.h"
8 #include <QFutureWatcher>
10 #include <QModelIndex>
15 #include <QtConcurrentFilter>
17 #include <QtConcurrentMap>
23 #include "BusyLeafItem.h"
30 #include "AbstractTreeItem.h"
31 #include "FilterWidget.h"
37 AbstractTreeModel::AbstractTreeModel(ControlNet *controlNet, TreeView *v,
38 QObject *parent) :
QObject(parent), m_view(v), m_cNet(controlNet) {
41 m_filterWatcher = NULL;
42 m_rebuildWatcher = NULL;
45 m_expandedState = NULL;
46 m_selectedState = NULL;
47 m_guisFilterWidget = NULL;
48 m_localFilterWidgetCopy = NULL;
51 m_busyItem =
new BusyLeafItem(NULL);
52 rootItem =
new RootItem;
60 connect(m_filterWatcher, SIGNAL(finished()),
this, SLOT(applyFilterDone()));
61 connect(m_rebuildWatcher, SIGNAL(finished()),
this, SLOT(rebuildItemsDone()));
63 connect(m_filterWatcher, SIGNAL(progressValueChanged(
int)),
64 this, SIGNAL(filterProgressChanged(
int)));
65 connect(m_filterWatcher, SIGNAL(progressRangeChanged(
int,
int)),
66 this, SIGNAL(filterProgressRangeChanged(
int,
int)));
67 connect(m_rebuildWatcher, SIGNAL(progressValueChanged(
int)),
68 this, SIGNAL(rebuildProgressChanged(
int)));
69 connect(m_rebuildWatcher, SIGNAL(progressRangeChanged(
int,
int)),
70 this, SIGNAL(rebuildProgressRangeChanged(
int,
int)));
73 m_filterAgain =
false;
74 m_filterRunning =
false;
75 m_rebuildRunning =
false;
77 m_rebuildPending =
false;
81 AbstractTreeModel::~AbstractTreeModel() {
82 delete m_filterWatcher;
83 m_filterWatcher = NULL;
85 delete m_rebuildWatcher;
86 m_rebuildWatcher = NULL;
94 delete m_expandedState;
95 m_expandedState = NULL;
97 delete m_selectedState;
98 m_selectedState = NULL;
103 delete m_localFilterWidgetCopy;
104 m_localFilterWidgetCopy = NULL;
106 m_guisFilterWidget = NULL;
115 InterestingItemsFlag flags,
bool ignoreExpansion) {
117 int rowCount = end - start;
118 const AbstractTreeItem *lastVisibleFilteredItem =
119 rootItem->getLastVisibleFilteredItem();
121 bool grabToEnd = (start >= 0 && end < 0);
123 if (lastVisibleFilteredItem && (rowCount > 0 || grabToEnd) &&
124 rootItem->childCount()) {
126 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
128 if (currentItem && !itemIsInteresting(currentItem, flags)) {
129 currentItem = nextItem(currentItem, flags, ignoreExpansion);
132 bool listStillValid =
true;
134 while (row < start && listStillValid && currentItem) {
136 listStillValid = (currentItem != lastVisibleFilteredItem ||
137 currentItem == currentItem->parent()->getLastVisibleChild());
140 currentItem = nextItem(currentItem, flags, ignoreExpansion);
143 while ((row < end || grabToEnd) && listStillValid && currentItem) {
145 foundItems.append(currentItem);
146 listStillValid = (currentItem != lastVisibleFilteredItem ||
147 currentItem == currentItem->parent()->getLastVisibleChild());
151 currentItem = nextItem(currentItem, flags, ignoreExpansion);
157 while (!grabToEnd && isFiltering() && foundItems.size() < rowCount) {
158 foundItems.append(m_busyItem);
167 AbstractTreeItem *item1, AbstractTreeItem *item2,
168 InterestingItemsFlag flags,
bool ignoreExpansion) {
171 if (rootItem->childCount()) {
172 AbstractTreeItem *start = NULL;
174 AbstractTreeItem *curItem = rootItem->getFirstVisibleChild();
176 while (!start && curItem) {
177 if (curItem == item1)
179 else if (curItem == item2)
183 curItem = nextItem(curItem, flags, ignoreExpansion);
187 QString msg =
"The first item passed to getItems(AbstractTreeItem*, "
188 "AbstractTreeItem*) is not visible in this model's tree";
192 AbstractTreeItem *end = item2;
199 AbstractTreeItem *
const &);
202 if (start == item2) {
207 while (curItem && curItem != end) {
208 (foundItems.*someKindaPend)(curItem);
209 curItem = nextItem(curItem, flags, ignoreExpansion);
213 QString msg =
"The second item passed to getItems(AbstractTreeItem*, "
214 "AbstractTreeItem*) is not visible in this model's tree";
218 (foundItems.*someKindaPend)(end);
226 InterestingItemsFlag flags,
bool ignoreExpansion) {
231 if (!isFiltering()) {
232 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
234 if (currentItem && !itemIsInteresting(currentItem, flags))
235 currentItem = nextItem(currentItem, flags, ignoreExpansion);
237 while (currentItem) {
238 if (currentItem->isSelected())
239 selectedItems.append(currentItem);
241 currentItem = nextItem(currentItem, flags, ignoreExpansion);
245 return selectedItems;
249 QMutex *AbstractTreeModel::getMutex()
const {
254 int AbstractTreeModel::getItemCount(InterestingItemsFlag flags)
const {
255 return getItemCount(rootItem, flags);
259 int AbstractTreeModel::getTopLevelItemCount()
const {
260 return rootItem->childCount();
263 int AbstractTreeModel::getVisibleItemCount(InterestingItemsFlag flags,
264 bool ignoreExpansion)
const {
265 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
268 if (!isFiltering()) {
271 while (currentItem) {
272 if (itemIsInteresting(currentItem, flags)) {
276 currentItem = nextItem(currentItem, flags, ignoreExpansion);
284 int AbstractTreeModel::getVisibleTopLevelItemCount()
const {
285 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
288 if (!isFiltering()) {
291 while (currentItem) {
293 currentItem = currentItem->getNextVisiblePeer();
301 int AbstractTreeModel::indexOfVisibleItem(AbstractTreeItem
const *item,
302 InterestingItemsFlag flags,
bool ignoreExpansion)
const {
303 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
306 if (!isFiltering()) {
307 while (currentItem && currentItem != item) {
308 if (itemIsInteresting(currentItem, flags))
311 currentItem = nextItem(currentItem, flags, ignoreExpansion);
324 void AbstractTreeModel::setFrozen(
bool newFrozenState) {
325 m_frozen = newFrozenState;
327 if (m_rebuildPending) {
329 m_rebuildPending =
false;
338 bool AbstractTreeModel::isFrozen()
const {
343 void AbstractTreeModel::queueRebuild() {
344 m_rebuildPending =
true;
348 bool AbstractTreeModel::isFiltering()
const {
349 return m_filterRunning;
353 bool AbstractTreeModel::isRebuilding()
const {
354 return m_rebuildRunning;
358 void AbstractTreeModel::setFilter(FilterWidget *fw) {
359 m_guisFilterWidget = fw;
361 connect(m_guisFilterWidget, SIGNAL(filterChanged()),
362 this, SLOT(applyFilter()));
368 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();
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 &&
502 flags.testFlag(PointItems)) ||
503 (pointerType == AbstractTreeItem::Measure &&
504 flags.testFlag(MeasureItems)) ||
505 (pointerType == AbstractTreeItem::CubeGraphNode &&
506 flags.testFlag(SerialItems))) {
515 int AbstractTreeModel::getItemCount(AbstractTreeItem *item,
516 InterestingItemsFlag flags)
const {
519 if (item && itemIsInteresting(item, flags)) {
523 if (item->childCount()) {
524 foreach (AbstractTreeItem * childItem, item->getChildren()) {
525 count += getItemCount(childItem, flags);
533 AbstractTreeItem *AbstractTreeModel::nextItem(AbstractTreeItem *current,
534 InterestingItemsFlag flags,
bool ignoreExpansion)
const {
537 if ((ignoreExpansion || current->isExpanded()) &&
538 current->getFirstVisibleChild())
539 current = current->getFirstVisibleChild();
540 else if (current->getNextVisiblePeer())
541 current = current->getNextVisiblePeer();
542 else if (current->parent())
543 current = current->parent()->getNextVisiblePeer();
547 while (current && !itemIsInteresting(current, flags));
554 void AbstractTreeModel::applyFilterDone() {
555 m_filterRunning =
false;
558 m_filterAgain =
false;
562 emit modelModified();
564 getTopLevelItemCount());
569 void AbstractTreeModel::rebuildItemsDone() {
573 RootItem *newRoot = newRootPtr.loadAcquire();
575 if (newRoot && newRoot->childCount()) {
589 setRebuilding(
false);
590 emit modelModified();
594 AbstractTreeModel::FilterFunctor::FilterFunctor(
595 FilterWidget *fw) : m_filter(fw) {
599 AbstractTreeModel::FilterFunctor::FilterFunctor(FilterFunctor
const &other) {
600 m_filter = other.m_filter;
604 AbstractTreeModel::FilterFunctor::~FilterFunctor() {
608 bool AbstractTreeModel::FilterFunctor::operator()(
609 AbstractTreeItem *
const &item)
const {
615 AbstractTreeModel::FilterFunctor &
616 AbstractTreeModel::FilterFunctor::operator=(FilterFunctor
const &other) {
618 m_filter = other.m_filter;
624 void AbstractTreeModel::FilterFunctor::filterWorker(
625 AbstractTreeItem *item)
const {
626 switch (item->getPointerType()) {
628 case AbstractTreeItem::Point:
629 item->setVisible((!m_filter || m_filter->evaluate(
630 (ControlPoint *) item->getPointer())) ?
true :
false);
633 case AbstractTreeItem::Measure:
634 item->setVisible((!m_filter || m_filter->evaluate(
635 (ControlMeasure *) item->getPointer())) ?
true :
false);
638 case AbstractTreeItem::CubeGraphNode:
639 item->setVisible((!m_filter || m_filter->evaluate(
640 (ControlCubeGraphNode *) item->getPointer())) ?
true :
false);
643 case AbstractTreeItem::None:
644 item->setVisible(
true);
649 if (item->getFirstVisibleChild())
650 item->setFirstVisibleChild(NULL);
652 if (item->getLastVisibleChild())
653 item->setLastVisibleChild(NULL);
655 item->setNextVisiblePeer(NULL);
659 if (item->childCount()) {
660 for (
int i = 0; i < item->childCount(); i++) {
661 AbstractTreeItem *child = item->childAt(i);
664 if (child->isVisible()) {
665 if (!item->getFirstVisibleChild()) {
666 item->setFirstVisibleChild(child);
667 item->setLastVisibleChild(child);
670 item->getLastVisibleChild()->setNextVisiblePeer(child);
671 item->setLastVisibleChild(child);
679 void AbstractTreeModel::FilterFunctor::updateTopLevelLinks(
681 AbstractTreeItem *
const &item) {
683 if ( root.testAndSetOrdered(NULL, item->parent()) ) {
684 AbstractTreeItem *loadedRoot = root.loadAcquire();
685 loadedRoot->setFirstVisibleChild(NULL);
686 loadedRoot->setLastVisibleChild(NULL);
687 loadedRoot->setLastVisibleFilteredItem(NULL);
691 AbstractTreeItem *loadedRoot = root.loadAcquire();
692 if (item->isVisible()) {
693 if (!loadedRoot->getFirstVisibleChild()) {
694 loadedRoot->setFirstVisibleChild(item);
695 loadedRoot->setLastVisibleChild(item);
698 loadedRoot->getLastVisibleChild()->setNextVisiblePeer(item);
699 loadedRoot->setLastVisibleChild(item);
702 loadedRoot->setLastVisibleFilteredItem(item);
This error is for when a programmer made an API call that was illegal.
Base class for an item in the tree.
#define _FILEINFO_
Macro for the filename and line number.
void filterCountsChanged(int visibleTopLevelItemCount, int topLevelItemCount)
This signal is emitted after filtering to provide the number of visible top-level items remaining aft...
QSize getVisibleSize(int indentation) const
indentation is in pixels