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"
28 AbstractTableModel::AbstractTableModel(AbstractTreeModel *model,
29 AbstractTableDelegate *someDelegate) {
33 connect(model, SIGNAL(cancelSort()),
this, SLOT(cancelSort()));
35 m_delegate = someDelegate;
37 m_sortingEnabled =
false;
42 m_busyItem =
new BusyLeafItem;
43 m_sortStatusPoller =
new QTimer;
46 connect(m_sortingWatcher, SIGNAL(finished()),
this, SLOT(sortFinished()));
48 connect(m_sortStatusPoller, SIGNAL(timeout()),
49 this, SLOT(sortStatusUpdated()));
52 connect(model, SIGNAL(modelModified()), SLOT(rebuildSort()));
54 connect(model, SIGNAL(filterProgressChanged(
int)),
55 this, SIGNAL(filterProgressChanged(
int)));
57 connect(model, SIGNAL(rebuildProgressChanged(
int)),
58 this, SIGNAL(rebuildProgressChanged(
int)));
60 connect(model, SIGNAL(filterProgressRangeChanged(
int,
int)),
61 this, SIGNAL(filterProgressRangeChanged(
int,
int)));
63 connect(model, SIGNAL(rebuildProgressRangeChanged(
int,
int)),
64 this, SIGNAL(rebuildProgressRangeChanged(
int,
int)));
68 connect(model, SIGNAL(filterCountsChanged(
int,
int)),
69 this, SIGNAL(filterCountsChanged(
int,
int)));
73 AbstractTableModel::~AbstractTableModel() {
87 delete m_sortStatusPoller;
88 m_sortStatusPoller = NULL;
90 delete m_lessThanFunctor;
91 m_lessThanFunctor = NULL;
94 for (
int i = 0; i < m_columns->size(); i++)
95 delete(*m_columns)[i];
101 delete m_sortingWatcher;
102 m_sortingWatcher = NULL;
106 bool AbstractTableModel::isSorting()
const {
111 bool AbstractTableModel::isFiltering()
const {
112 return m_dataModel && m_dataModel->isFiltering();
116 bool AbstractTableModel::sortingIsEnabled()
const {
117 return m_sortingEnabled;
121 void AbstractTableModel::setSortingEnabled(
bool enabled) {
122 if (m_sortingEnabled != enabled) {
123 m_sortingEnabled = enabled;
129 int AbstractTableModel::sortLimit()
const {
134 void AbstractTableModel::setSortLimit(
int limit) {
135 if (m_sortLimit != limit) {
142 bool AbstractTableModel::sortingOn()
const {
143 return (sortingIsEnabled() && (getVisibleRowCount() <= sortLimit()));
147 TableColumnList *AbstractTableModel::getColumns() {
149 m_columns = createColumns();
150 connect(m_columns, SIGNAL(sortOutDated()),
this, SLOT(sort()));
157 const AbstractTableDelegate *AbstractTableModel::getDelegate()
const {
162 void AbstractTableModel::applyFilter() {
163 getDataModel()->applyFilter();
167 void AbstractTableModel::sort() {
168 if (sortingOn() && m_sortedItems->size() && !m_dataModel->isFiltering() &&
169 !m_dataModel->isRebuilding()) {
173 else if (!m_lessThanFunctor) {
177 m_lessThanFunctor =
new LessThanFunctor(
178 m_columns->getSortingOrder().first());
181 QFuture< QList< AbstractTreeItem * > > future =
182 QtConcurrent::run(
this, &AbstractTableModel::doSort,
184 m_sortingWatcher->setFuture(future);
186 emit modelModified();
192 void AbstractTableModel::reverseOrder(TableColumn *column) {
196 void AbstractTableModel::updateSort() {
200 AbstractTreeModel *AbstractTableModel::getDataModel() {
206 const AbstractTreeModel *AbstractTableModel::getDataModel()
const {
213 int start,
int end, AbstractTreeModel::InterestingItems flags) {
217 while (start <= end) {
218 if (start < m_sortedItems->size())
219 sortedSubsetOfItems.append(m_sortedItems->at(start));
220 else if (isFiltering())
221 sortedSubsetOfItems.append(m_busyItem);
227 sortedSubsetOfItems = getDataModel()->getItems(start, end, flags,
true);
230 return sortedSubsetOfItems;
235 AbstractTreeItem *item1, AbstractTreeItem *item2,
236 AbstractTreeModel::InterestingItems flags) {
240 sortedSubsetOfItems = getDataModel()->getItems(item1, item2, flags,
true);
243 AbstractTreeItem *start = NULL;
245 int currentIndex = 0;
247 while (!start && currentIndex < m_sortedItems->size()) {
248 AbstractTreeItem *current = m_sortedItems->at(currentIndex);
249 if (current == item1)
251 else if (current == item2)
259 IString msg =
"Could not find the first item";
263 AbstractTreeItem *end = item2;
270 AbstractTreeItem *
const &);
273 if (start == item2) {
278 while (currentIndex < m_sortedItems->size() &&
279 m_sortedItems->at(currentIndex) != end) {
280 (sortedSubsetOfItems.*someKindaPend)(m_sortedItems->at(currentIndex));
284 if (currentIndex >= m_sortedItems->size()) {
285 IString msg =
"Could not find the second item";
289 (sortedSubsetOfItems.*someKindaPend)(end);
292 return sortedSubsetOfItems;
296 void AbstractTableModel::handleTreeSelectionChanged(
298 AbstractTreeItem::InternalPointerType pointerType) {
300 foreach (AbstractTreeItem * item, newlySelectedItems) {
301 if (item->getPointerType() == pointerType)
302 interestingSelectedItems.append(item);
305 if (interestingSelectedItems.size()) {
306 emit treeSelectionChanged(interestingSelectedItems);
311 void AbstractTableModel::sortStatusUpdated() {
312 if (m_lessThanFunctor)
313 emit sortProgressChanged(m_lessThanFunctor->getCompareCount());
317 void AbstractTableModel::sortFinished() {
318 bool interrupted = m_lessThanFunctor->interrupted();
319 delete m_lessThanFunctor;
320 m_lessThanFunctor = NULL;
325 if (!m_dataModel->isFiltering() && !m_dataModel->isRebuilding()) {
326 *m_sortedItems = newSortedItems;
327 emit modelModified();
336 void AbstractTableModel::cancelSort() {
337 if (m_lessThanFunctor) {
338 m_lessThanFunctor->interrupt();
339 m_sortingWatcher->waitForFinished();
344 void AbstractTableModel::itemsLost() {
346 m_sortedItems->clear();
352 ASSERT(!isSorting());
360 m_sortStatusPoller->start(SORT_UPDATE_FREQUENCY);
364 int numItems = itemsToSort.size();
367 emit sortProgressRangeChanged(0,
368 (
int)((a * numItems) * (log2(b * numItems))));
371 qStableSort(itemsToSort.begin(), itemsToSort.end(),
374 catch (SortingCanceledException &e) {
375 m_sortStatusPoller->stop();
376 emit sortProgressRangeChanged(0, 0);
377 emit sortProgressChanged(0);
378 emit modelModified();
387 m_sortStatusPoller->stop();
388 emit sortProgressRangeChanged(0, 0);
389 emit sortProgressChanged(0);
390 emit modelModified();
400 void AbstractTableModel::nullify() {
403 m_sortedItems = NULL;
405 m_sortStatusPoller = NULL;
406 m_lessThanFunctor = NULL;
408 m_sortingWatcher = NULL;
412 void AbstractTableModel::setSorting(
bool isSorting) {
413 m_sorting = isSorting;
417 void AbstractTableModel::rebuildSort() {
419 ASSERT(m_sortedItems);
420 m_sortedItems->clear();
424 m_sortingEnabled =
false;
425 *m_sortedItems = getItems(0, -1);
427 foreach (AbstractTreeItem * item, *m_sortedItems) {
428 connect(item, SIGNAL(destroyed(
QObject *)),
this, SLOT(itemsLost()));
431 m_sortingEnabled =
true;
434 emit userWarning(None);
438 emit modelModified();
440 if (!m_sortingEnabled)
441 emit userWarning(SortingDisabled);
443 emit userWarning(SortingTableSizeLimitReached);
451 AbstractTableModel::LessThanFunctor::LessThanFunctor(
452 TableColumn
const *someColumn) : m_column(someColumn) {
453 m_sharedData =
new LessThanFunctorData;
457 AbstractTableModel::LessThanFunctor::LessThanFunctor(
458 LessThanFunctor
const &other) : m_sharedData(other.m_sharedData) {
459 m_column = other.m_column;
463 AbstractTableModel::LessThanFunctor::~LessThanFunctor() {
468 int AbstractTableModel::LessThanFunctor::getCompareCount()
const {
469 return m_sharedData->getCompareCount();
473 void AbstractTableModel::LessThanFunctor::interrupt() {
474 m_sharedData->setInterrupted(
true);
478 bool AbstractTableModel::LessThanFunctor::interrupted() {
479 return m_sharedData->interrupted();
483 void AbstractTableModel::LessThanFunctor::reset() {
484 m_sharedData->setInterrupted(
false);
488 bool AbstractTableModel::LessThanFunctor::operator()(
489 AbstractTreeItem *
const &left, AbstractTreeItem *
const &right) {
490 if (left->getPointerType() != right->getPointerType()) {
491 IString msg =
"Tried to compare apples to oranges";
495 if (m_sharedData->interrupted()) {
496 throw SortingCanceledException();
499 m_sharedData->incrementCompareCount();
501 QVariant leftData = left->getData(m_column->getTitle());
502 QVariant rightData = right->getData(m_column->getTitle());
503 QString busy = BusyLeafItem().getData().toString();
506 if (leftData.type() == QVariant::String &&
507 rightData.type() == QVariant::String) {
508 lessThan = leftData.toString() < rightData.toString();
510 else if (leftData.type() == QVariant::Double &&
511 rightData.type() == QVariant::Double) {
512 lessThan = (leftData.toDouble() < rightData.toDouble());
514 else if (leftData.type() == QVariant::Double ||
515 rightData.type() == QVariant::Double) {
518 lessThan = (leftData.toString() == busy);
521 lessThan = leftData.toString() < rightData.toString();
524 return lessThan ^ m_column->sortAscending();
528 AbstractTableModel::LessThanFunctor &
529 AbstractTableModel::LessThanFunctor::operator=(
530 LessThanFunctor
const &other) {
531 if (
this != &other) {
532 m_column = other.m_column;
533 m_sharedData = other.m_sharedData;
543 AbstractTableModel::LessThanFunctorData::LessThanFunctorData() {
544 m_compareCount.fetchAndStoreRelaxed(0);
545 m_interruptFlag.fetchAndStoreRelaxed(0);
549 AbstractTableModel::LessThanFunctorData::LessThanFunctorData(
550 LessThanFunctorData
const &other) :
QSharedData(other),
551 m_compareCount(other.m_compareCount), m_interruptFlag(other.m_interruptFlag) {
555 AbstractTableModel::LessThanFunctorData::~LessThanFunctorData() {
559 int AbstractTableModel::LessThanFunctorData::getCompareCount()
const {
560 return m_compareCount;
564 void AbstractTableModel::LessThanFunctorData::incrementCompareCount() {
565 m_compareCount.fetchAndAddRelaxed(1);
569 void AbstractTableModel::LessThanFunctorData::setInterrupted(
bool newStatus) {
570 newStatus ? m_interruptFlag.fetchAndStoreRelaxed(1) :
571 m_interruptFlag.fetchAndStoreRelaxed(0);
575 bool AbstractTableModel::LessThanFunctorData::interrupted() {
576 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.