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" 36 AbstractTreeModel::AbstractTreeModel(ControlNet *controlNet, TreeView *v,
37 QObject *parent) :
QObject(parent), m_view(v), m_cNet(controlNet) {
40 m_filterWatcher = NULL;
41 m_rebuildWatcher = NULL;
44 m_expandedState = NULL;
45 m_selectedState = NULL;
46 m_guisFilterWidget = NULL;
47 m_localFilterWidgetCopy = NULL;
50 m_busyItem =
new BusyLeafItem(NULL);
51 rootItem =
new RootItem;
59 connect(m_filterWatcher, SIGNAL(finished()),
this, SLOT(applyFilterDone()));
60 connect(m_rebuildWatcher, SIGNAL(finished()),
this, SLOT(rebuildItemsDone()));
62 connect(m_filterWatcher, SIGNAL(progressValueChanged(
int)),
63 this, SIGNAL(filterProgressChanged(
int)));
64 connect(m_filterWatcher, SIGNAL(progressRangeChanged(
int,
int)),
65 this, SIGNAL(filterProgressRangeChanged(
int,
int)));
66 connect(m_rebuildWatcher, SIGNAL(progressValueChanged(
int)),
67 this, SIGNAL(rebuildProgressChanged(
int)));
68 connect(m_rebuildWatcher, SIGNAL(progressRangeChanged(
int,
int)),
69 this, SIGNAL(rebuildProgressRangeChanged(
int,
int)));
72 m_filterAgain =
false;
73 m_filterRunning =
false;
74 m_rebuildRunning =
false;
76 m_rebuildPending =
false;
80 AbstractTreeModel::~AbstractTreeModel() {
81 delete m_filterWatcher;
82 m_filterWatcher = NULL;
84 delete m_rebuildWatcher;
85 m_rebuildWatcher = NULL;
93 delete m_expandedState;
94 m_expandedState = NULL;
96 delete m_selectedState;
97 m_selectedState = NULL;
102 delete m_localFilterWidgetCopy;
103 m_localFilterWidgetCopy = NULL;
105 m_guisFilterWidget = NULL;
114 InterestingItemsFlag flags,
bool ignoreExpansion) {
116 int rowCount = end - start;
117 const AbstractTreeItem *lastVisibleFilteredItem =
118 rootItem->getLastVisibleFilteredItem();
120 bool grabToEnd = (start >= 0 && end < 0);
122 if (lastVisibleFilteredItem && (rowCount > 0 || grabToEnd) &&
123 rootItem->childCount()) {
125 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
127 if (currentItem && !itemIsInteresting(currentItem, flags)) {
128 currentItem = nextItem(currentItem, flags, ignoreExpansion);
131 bool listStillValid =
true;
133 while (row < start && listStillValid && currentItem) {
135 listStillValid = (currentItem != lastVisibleFilteredItem ||
136 currentItem == currentItem->parent()->getLastVisibleChild());
139 currentItem = nextItem(currentItem, flags, ignoreExpansion);
142 while ((row < end || grabToEnd) && listStillValid && currentItem) {
144 foundItems.append(currentItem);
145 listStillValid = (currentItem != lastVisibleFilteredItem ||
146 currentItem == currentItem->parent()->getLastVisibleChild());
150 currentItem = nextItem(currentItem, flags, ignoreExpansion);
156 while (!grabToEnd && isFiltering() && foundItems.size() < rowCount) {
157 foundItems.append(m_busyItem);
166 AbstractTreeItem *item1, AbstractTreeItem *item2,
167 InterestingItemsFlag flags,
bool ignoreExpansion) {
170 if (rootItem->childCount()) {
171 AbstractTreeItem *start = NULL;
173 AbstractTreeItem *curItem = rootItem->getFirstVisibleChild();
175 while (!start && curItem) {
176 if (curItem == item1)
178 else if (curItem == item2)
182 curItem = nextItem(curItem, flags, ignoreExpansion);
186 QString msg =
"The first item passed to getItems(AbstractTreeItem*, " 187 "AbstractTreeItem*) is not visible in this model's tree";
191 AbstractTreeItem *end = item2;
198 AbstractTreeItem *
const &);
201 if (start == item2) {
206 while (curItem && curItem != end) {
207 (foundItems.*someKindaPend)(curItem);
208 curItem = nextItem(curItem, flags, ignoreExpansion);
212 QString msg =
"The second item passed to getItems(AbstractTreeItem*, " 213 "AbstractTreeItem*) is not visible in this model's tree";
217 (foundItems.*someKindaPend)(end);
225 InterestingItemsFlag flags,
bool ignoreExpansion) {
230 if (!isFiltering()) {
231 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
233 if (currentItem && !itemIsInteresting(currentItem, flags))
234 currentItem = nextItem(currentItem, flags, ignoreExpansion);
236 while (currentItem) {
237 if (currentItem->isSelected())
238 selectedItems.append(currentItem);
240 currentItem = nextItem(currentItem, flags, ignoreExpansion);
244 return selectedItems;
248 QMutex *AbstractTreeModel::getMutex()
const {
253 int AbstractTreeModel::getItemCount(InterestingItemsFlag flags)
const {
254 return getItemCount(rootItem, flags);
258 int AbstractTreeModel::getTopLevelItemCount()
const {
259 return rootItem->childCount();
262 int AbstractTreeModel::getVisibleItemCount(InterestingItemsFlag flags,
263 bool ignoreExpansion)
const {
264 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
267 if (!isFiltering()) {
270 while (currentItem) {
271 if (itemIsInteresting(currentItem, flags)) {
275 currentItem = nextItem(currentItem, flags, ignoreExpansion);
283 int AbstractTreeModel::getVisibleTopLevelItemCount()
const {
284 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
287 if (!isFiltering()) {
290 while (currentItem) {
292 currentItem = currentItem->getNextVisiblePeer();
300 int AbstractTreeModel::indexOfVisibleItem(AbstractTreeItem
const *item,
301 InterestingItemsFlag flags,
bool ignoreExpansion)
const {
302 AbstractTreeItem *currentItem = rootItem->getFirstVisibleChild();
305 if (!isFiltering()) {
306 while (currentItem && currentItem != item) {
307 if (itemIsInteresting(currentItem, flags))
310 currentItem = nextItem(currentItem, flags, ignoreExpansion);
323 void AbstractTreeModel::setFrozen(
bool newFrozenState) {
324 m_frozen = newFrozenState;
326 if (m_rebuildPending) {
328 m_rebuildPending =
false;
337 bool AbstractTreeModel::isFrozen()
const {
342 void AbstractTreeModel::queueRebuild() {
343 m_rebuildPending =
true;
347 bool AbstractTreeModel::isFiltering()
const {
348 return m_filterRunning;
352 bool AbstractTreeModel::isRebuilding()
const {
353 return m_rebuildRunning;
357 void AbstractTreeModel::setFilter(FilterWidget *fw) {
358 m_guisFilterWidget = fw;
360 connect(m_guisFilterWidget, SIGNAL(filterChanged()),
361 this, SLOT(applyFilter()));
367 void AbstractTreeModel::clear() {
372 rootItem =
new RootItem;
376 ControlNet *AbstractTreeModel::getControlNetwork()
const {
382 AbstractTreeModel::getRebuildWatcher()
const {
383 return m_rebuildWatcher;
387 RootItem *AbstractTreeModel::getRootItem()
const {
392 TreeView *AbstractTreeModel::getView()
const {
397 void AbstractTreeModel::stopWorking() {
398 m_filterWatcher->cancel();
399 m_filterWatcher->waitForFinished();
400 m_rebuildWatcher->cancel();
401 m_rebuildWatcher->waitForFinished();
409 if (!isFiltering()) {
410 int visibleRowCount = 0;
413 if (rootItem && rootItem->getFirstVisibleChild()) {
416 while (current != NULL) {
417 int depth = current->getDepth();
420 maxWidth = qMax(maxWidth,
421 current->getDataWidth() + indentation * depth);
422 current = nextItem(current, AllItems,
false);
426 size = QSize(maxWidth, visibleRowCount);
433 void AbstractTreeModel::applyFilter() {
436 if (!m_frozen && !m_filterAgain && m_guisFilterWidget &&
437 m_rebuildWatcher->isFinished()) {
439 QFuture< QAtomicPointer< AbstractTreeItem> > futureRoot;
441 if (m_filterRunning) {
442 m_filterAgain =
true;
443 futureRoot = m_filterWatcher->future();
452 if (m_localFilterWidgetCopy) {
453 delete m_localFilterWidgetCopy;
454 m_localFilterWidgetCopy = NULL;
457 m_localFilterWidgetCopy =
new FilterWidget(*m_guisFilterWidget);
462 m_filterRunning =
true;
463 rootItem->setLastVisibleFilteredItem(NULL);
464 futureRoot = QtConcurrent::filteredReduced(rootItem->getChildren(),
465 FilterFunctor(m_localFilterWidgetCopy),
466 &FilterFunctor::updateTopLevelLinks,
467 QtConcurrent::OrderedReduce | QtConcurrent::SequentialReduce);
469 m_filterWatcher->setFuture(futureRoot);
475 void AbstractTreeModel::setGlobalSelection(
bool selected,
476 InterestingItemsFlag flags) {
477 selectItems(rootItem, selected, flags);
481 void AbstractTreeModel::selectItems(
482 AbstractTreeItem *item,
bool selected, InterestingItemsFlag flags) {
483 if (item && itemIsInteresting(item, flags)) {
484 item->setSelected(selected);
487 if (item->childCount()) {
488 foreach (AbstractTreeItem * childItem, item->getChildren()) {
489 selectItems(childItem, selected, flags);
495 bool AbstractTreeModel::itemIsInteresting(AbstractTreeItem *item,
496 InterestingItemsFlag flags) {
497 AbstractTreeItem::InternalPointerType pointerType =
498 item->getPointerType();
500 if ((pointerType == AbstractTreeItem::Point && flags.testFlag(PointItems)) ||
501 (pointerType == AbstractTreeItem::Measure && flags.testFlag(MeasureItems)) ||
502 (pointerType == AbstractTreeItem::ImageAndNet && flags.testFlag(ImageItems))) {
511 int AbstractTreeModel::getItemCount(AbstractTreeItem *item,
512 InterestingItemsFlag flags)
const {
515 if (item && itemIsInteresting(item, flags)) {
519 if (item->childCount()) {
520 foreach (AbstractTreeItem * childItem, item->getChildren()) {
521 count += getItemCount(childItem, flags);
529 AbstractTreeItem *AbstractTreeModel::nextItem(AbstractTreeItem *current,
530 InterestingItemsFlag flags,
bool ignoreExpansion)
const {
533 if ((ignoreExpansion || current->isExpanded()) &&
534 current->getFirstVisibleChild())
535 current = current->getFirstVisibleChild();
536 else if (current->getNextVisiblePeer())
537 current = current->getNextVisiblePeer();
538 else if (current->parent())
539 current = current->parent()->getNextVisiblePeer();
543 while (current && !itemIsInteresting(current, flags));
550 void AbstractTreeModel::applyFilterDone() {
551 m_filterRunning =
false;
554 m_filterAgain =
false;
558 emit modelModified();
560 getTopLevelItemCount());
565 void AbstractTreeModel::rebuildItemsDone() {
569 RootItem *newRoot = newRootPtr.loadAcquire();
571 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(
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(
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);
QSize getVisibleSize(int indentation) const
indentation is in pixels
void filterCountsChanged(int visibleTopLevelItemCount, int topLevelItemCount)
This signal is emitted after filtering to provide the number of visible top-level items remaining aft...
This error is for when a programmer made an API call that was illegal.
#define _FILEINFO_
Macro for the filename and line number.
Namespace for ISIS/Bullet specific routines.
Base class for an item in the tree.