6 #include <QCoreApplication> 9 #include <QFutureWatcher> 11 #include <QtConcurrentRun> 17 #include "AbstractTableDelegate.h" 18 #include "AbstractTableModel.h" 19 #include "BusyLeafItem.h" 20 #include "TableColumn.h" 21 #include "TableColumnList.h" 22 #include "TableView.h" 23 #include "AbstractTreeModel.h" 27 AbstractTableModel::AbstractTableModel(AbstractTreeModel *model,
28 AbstractTableDelegate *someDelegate) {
32 connect(model, SIGNAL(cancelSort()),
this, SLOT(cancelSort()));
34 m_delegate = someDelegate;
36 m_sortingEnabled =
false;
41 m_busyItem =
new BusyLeafItem;
42 m_sortStatusPoller =
new QTimer;
45 connect(m_sortingWatcher, SIGNAL(finished()),
this, SLOT(sortFinished()));
47 connect(m_sortStatusPoller, SIGNAL(timeout()),
48 this, SLOT(sortStatusUpdated()));
51 connect(model, SIGNAL(modelModified()), SLOT(rebuildSort()));
53 connect(model, SIGNAL(filterProgressChanged(
int)),
54 this, SIGNAL(filterProgressChanged(
int)));
56 connect(model, SIGNAL(rebuildProgressChanged(
int)),
57 this, SIGNAL(rebuildProgressChanged(
int)));
59 connect(model, SIGNAL(filterProgressRangeChanged(
int,
int)),
60 this, SIGNAL(filterProgressRangeChanged(
int,
int)));
62 connect(model, SIGNAL(rebuildProgressRangeChanged(
int,
int)),
63 this, SIGNAL(rebuildProgressRangeChanged(
int,
int)));
67 connect(model, SIGNAL(filterCountsChanged(
int,
int)),
68 this, SIGNAL(filterCountsChanged(
int,
int)));
72 AbstractTableModel::~AbstractTableModel() {
86 delete m_sortStatusPoller;
87 m_sortStatusPoller = NULL;
89 delete m_lessThanFunctor;
90 m_lessThanFunctor = NULL;
93 for (
int i = 0; i < m_columns->size(); i++)
94 delete(*m_columns)[i];
100 delete m_sortingWatcher;
101 m_sortingWatcher = NULL;
105 bool AbstractTableModel::isSorting()
const {
110 bool AbstractTableModel::isFiltering()
const {
111 return m_dataModel && m_dataModel->isFiltering();
115 bool AbstractTableModel::sortingIsEnabled()
const {
116 return m_sortingEnabled;
120 void AbstractTableModel::setSortingEnabled(
bool enabled) {
121 if (m_sortingEnabled != enabled) {
122 m_sortingEnabled = enabled;
128 int AbstractTableModel::sortLimit()
const {
133 void AbstractTableModel::setSortLimit(
int limit) {
134 if (m_sortLimit != limit) {
141 bool AbstractTableModel::sortingOn()
const {
142 return (sortingIsEnabled() && (getVisibleRowCount() <= sortLimit()));
146 TableColumnList *AbstractTableModel::getColumns() {
148 m_columns = createColumns();
149 connect(m_columns, SIGNAL(sortOutDated()),
this, SLOT(sort()));
156 const AbstractTableDelegate *AbstractTableModel::getDelegate()
const {
161 void AbstractTableModel::applyFilter() {
162 getDataModel()->applyFilter();
166 void AbstractTableModel::sort() {
167 if (sortingOn() && m_sortedItems->size() && !m_dataModel->isFiltering() &&
168 !m_dataModel->isRebuilding()) {
172 else if (!m_lessThanFunctor) {
176 m_lessThanFunctor =
new LessThanFunctor(
177 m_columns->getSortingOrder().first());
180 QFuture< QList< AbstractTreeItem * > > future =
181 QtConcurrent::run(
this, &AbstractTableModel::doSort,
183 m_sortingWatcher->setFuture(future);
185 emit modelModified();
191 void AbstractTableModel::reverseOrder(TableColumn *column) {
195 void AbstractTableModel::updateSort() {
199 AbstractTreeModel *AbstractTableModel::getDataModel() {
205 const AbstractTreeModel *AbstractTableModel::getDataModel()
const {
212 int start,
int end, AbstractTreeModel::InterestingItems flags) {
216 while (start <= end) {
217 if (start < m_sortedItems->size())
218 sortedSubsetOfItems.append(m_sortedItems->at(start));
219 else if (isFiltering())
220 sortedSubsetOfItems.append(m_busyItem);
226 sortedSubsetOfItems = getDataModel()->getItems(start, end, flags,
true);
229 return sortedSubsetOfItems;
234 AbstractTreeItem *item1, AbstractTreeItem *item2,
235 AbstractTreeModel::InterestingItems flags) {
239 sortedSubsetOfItems = getDataModel()->getItems(item1, item2, flags,
true);
242 AbstractTreeItem *start = NULL;
244 int currentIndex = 0;
246 while (!start && currentIndex < m_sortedItems->size()) {
247 AbstractTreeItem *current = m_sortedItems->at(currentIndex);
248 if (current == item1)
250 else if (current == item2)
258 IString msg =
"Could not find the first item";
262 AbstractTreeItem *end = item2;
269 AbstractTreeItem *
const &);
272 if (start == item2) {
277 while (currentIndex < m_sortedItems->size() &&
278 m_sortedItems->at(currentIndex) != end) {
279 (sortedSubsetOfItems.*someKindaPend)(m_sortedItems->at(currentIndex));
283 if (currentIndex >= m_sortedItems->size()) {
284 IString msg =
"Could not find the second item";
288 (sortedSubsetOfItems.*someKindaPend)(end);
291 return sortedSubsetOfItems;
295 void AbstractTableModel::handleTreeSelectionChanged(
297 AbstractTreeItem::InternalPointerType pointerType) {
299 foreach (AbstractTreeItem * item, newlySelectedItems) {
300 if (item->getPointerType() == pointerType)
301 interestingSelectedItems.append(item);
304 if (interestingSelectedItems.size()) {
305 emit treeSelectionChanged(interestingSelectedItems);
310 void AbstractTableModel::sortStatusUpdated() {
311 if (m_lessThanFunctor)
312 emit sortProgressChanged(m_lessThanFunctor->getCompareCount());
316 void AbstractTableModel::sortFinished() {
317 bool interrupted = m_lessThanFunctor->interrupted();
318 delete m_lessThanFunctor;
319 m_lessThanFunctor = NULL;
324 if (!m_dataModel->isFiltering() && !m_dataModel->isRebuilding()) {
325 *m_sortedItems = newSortedItems;
326 emit modelModified();
335 void AbstractTableModel::cancelSort() {
336 if (m_lessThanFunctor) {
337 m_lessThanFunctor->interrupt();
338 m_sortingWatcher->waitForFinished();
343 void AbstractTableModel::itemsLost() {
345 m_sortedItems->clear();
351 ASSERT(!isSorting());
359 m_sortStatusPoller->start(SORT_UPDATE_FREQUENCY);
363 int numItems = itemsToSort.size();
366 emit sortProgressRangeChanged(0,
367 (
int)((a * numItems) * (log2(b * numItems))));
370 qStableSort(itemsToSort.begin(), itemsToSort.end(),
373 catch (SortingCanceledException &e) {
374 m_sortStatusPoller->stop();
375 emit sortProgressRangeChanged(0, 0);
376 emit sortProgressChanged(0);
377 emit modelModified();
386 m_sortStatusPoller->stop();
387 emit sortProgressRangeChanged(0, 0);
388 emit sortProgressChanged(0);
389 emit modelModified();
399 void AbstractTableModel::nullify() {
402 m_sortedItems = NULL;
404 m_sortStatusPoller = NULL;
405 m_lessThanFunctor = NULL;
407 m_sortingWatcher = NULL;
411 void AbstractTableModel::setSorting(
bool isSorting) {
412 m_sorting = isSorting;
416 void AbstractTableModel::rebuildSort() {
418 ASSERT(m_sortedItems);
419 m_sortedItems->clear();
423 m_sortingEnabled =
false;
424 *m_sortedItems = getItems(0, -1);
426 foreach (AbstractTreeItem * item, *m_sortedItems) {
427 connect(item, SIGNAL(destroyed(
QObject *)),
this, SLOT(itemsLost()));
430 m_sortingEnabled =
true;
433 emit userWarning(None);
437 emit modelModified();
439 if (!m_sortingEnabled)
440 emit userWarning(SortingDisabled);
442 emit userWarning(SortingTableSizeLimitReached);
450 AbstractTableModel::LessThanFunctor::LessThanFunctor(
451 TableColumn
const *someColumn) : m_column(someColumn) {
452 m_sharedData =
new LessThanFunctorData;
456 AbstractTableModel::LessThanFunctor::LessThanFunctor(
457 LessThanFunctor
const &other) : m_sharedData(other.m_sharedData) {
458 m_column = other.m_column;
462 AbstractTableModel::LessThanFunctor::~LessThanFunctor() {
467 int AbstractTableModel::LessThanFunctor::getCompareCount()
const {
468 return m_sharedData->getCompareCount();
472 void AbstractTableModel::LessThanFunctor::interrupt() {
473 m_sharedData->setInterrupted(
true);
477 bool AbstractTableModel::LessThanFunctor::interrupted() {
478 return m_sharedData->interrupted();
482 void AbstractTableModel::LessThanFunctor::reset() {
483 m_sharedData->setInterrupted(
false);
487 bool AbstractTableModel::LessThanFunctor::operator()(
488 AbstractTreeItem *
const &left, AbstractTreeItem *
const &right) {
489 if (left->getPointerType() != right->getPointerType()) {
490 IString msg =
"Tried to compare apples to oranges";
494 if (m_sharedData->interrupted()) {
495 throw SortingCanceledException();
498 m_sharedData->incrementCompareCount();
500 QVariant leftData = left->getData(m_column->getTitle());
501 QVariant rightData = right->getData(m_column->getTitle());
502 QString busy = BusyLeafItem().getData().toString();
505 if (leftData.type() == QVariant::String &&
506 rightData.type() == QVariant::String) {
507 lessThan = leftData.toString() < rightData.toString();
509 else if (leftData.type() == QVariant::Double &&
510 rightData.type() == QVariant::Double) {
511 lessThan = (leftData.toDouble() < rightData.toDouble());
513 else if (leftData.type() == QVariant::Double ||
514 rightData.type() == QVariant::Double) {
517 lessThan = (leftData.toString() == busy);
520 lessThan = leftData.toString() < rightData.toString();
523 return lessThan ^ m_column->sortAscending();
527 AbstractTableModel::LessThanFunctor &
528 AbstractTableModel::LessThanFunctor::operator=(
529 LessThanFunctor
const &other) {
530 if (
this != &other) {
531 m_column = other.m_column;
532 m_sharedData = other.m_sharedData;
542 AbstractTableModel::LessThanFunctorData::LessThanFunctorData() {
543 m_compareCount.fetchAndStoreRelaxed(0);
544 m_interruptFlag.fetchAndStoreRelaxed(0);
548 AbstractTableModel::LessThanFunctorData::LessThanFunctorData(
549 LessThanFunctorData
const &other) :
QSharedData(other),
550 m_compareCount(other.m_compareCount), m_interruptFlag(other.m_interruptFlag) {
554 AbstractTableModel::LessThanFunctorData::~LessThanFunctorData() {
558 int AbstractTableModel::LessThanFunctorData::getCompareCount()
const {
559 return m_compareCount;
563 void AbstractTableModel::LessThanFunctorData::incrementCompareCount() {
564 m_compareCount.fetchAndAddRelaxed(1);
568 void AbstractTableModel::LessThanFunctorData::setInterrupted(
bool newStatus) {
569 newStatus ? m_interruptFlag.fetchAndStoreRelaxed(1) :
570 m_interruptFlag.fetchAndStoreRelaxed(0);
574 bool AbstractTableModel::LessThanFunctorData::interrupted() {
575 return m_interruptFlag != 0;
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.