14 #include <QCoreApplication>
17 #include <QFutureWatcher>
19 #include <QtConcurrentRun>
22 #include "IException.h"
25 #include "AbstractTableDelegate.h"
26 #include "AbstractTableModel.h"
27 #include "BusyLeafItem.h"
28 #include "TableColumn.h"
29 #include "TableColumnList.h"
30 #include "TableView.h"
31 #include "AbstractTreeModel.h"
35 AbstractTableModel::AbstractTableModel(AbstractTreeModel *model,
36 AbstractTableDelegate *someDelegate) {
40 connect(model, SIGNAL(cancelSort()),
this, SLOT(cancelSort()));
42 m_delegate = someDelegate;
44 m_sortingEnabled =
false;
49 m_busyItem =
new BusyLeafItem;
50 m_sortStatusPoller =
new QTimer;
53 connect(m_sortingWatcher, SIGNAL(finished()),
this, SLOT(sortFinished()));
55 connect(m_sortStatusPoller, SIGNAL(timeout()),
56 this, SLOT(sortStatusUpdated()));
59 connect(model, SIGNAL(modelModified()), SLOT(rebuildSort()));
61 connect(model, SIGNAL(filterProgressChanged(
int)),
62 this, SIGNAL(filterProgressChanged(
int)));
64 connect(model, SIGNAL(rebuildProgressChanged(
int)),
65 this, SIGNAL(rebuildProgressChanged(
int)));
67 connect(model, SIGNAL(filterProgressRangeChanged(
int,
int)),
68 this, SIGNAL(filterProgressRangeChanged(
int,
int)));
70 connect(model, SIGNAL(rebuildProgressRangeChanged(
int,
int)),
71 this, SIGNAL(rebuildProgressRangeChanged(
int,
int)));
75 connect(model, SIGNAL(filterCountsChanged(
int,
int)),
76 this, SIGNAL(filterCountsChanged(
int,
int)));
80 AbstractTableModel::~AbstractTableModel() {
94 delete m_sortStatusPoller;
95 m_sortStatusPoller = NULL;
97 delete m_lessThanFunctor;
98 m_lessThanFunctor = NULL;
101 for (
int i = 0; i < m_columns->size(); i++)
102 delete(*m_columns)[i];
108 delete m_sortingWatcher;
109 m_sortingWatcher = NULL;
113 bool AbstractTableModel::isSorting()
const {
118 bool AbstractTableModel::isFiltering()
const {
119 return m_dataModel && m_dataModel->isFiltering();
123 bool AbstractTableModel::sortingIsEnabled()
const {
124 return m_sortingEnabled;
128 void AbstractTableModel::setSortingEnabled(
bool enabled) {
129 if (m_sortingEnabled != enabled) {
130 m_sortingEnabled = enabled;
136 int AbstractTableModel::sortLimit()
const {
141 void AbstractTableModel::setSortLimit(
int limit) {
142 if (m_sortLimit != limit) {
149 bool AbstractTableModel::sortingOn()
const {
150 return (sortingIsEnabled() && (getVisibleRowCount() <= sortLimit()));
154 TableColumnList *AbstractTableModel::getColumns() {
156 m_columns = createColumns();
157 connect(m_columns, SIGNAL(sortOutDated()),
this, SLOT(sort()));
164 const AbstractTableDelegate *AbstractTableModel::getDelegate()
const {
169 void AbstractTableModel::applyFilter() {
170 getDataModel()->applyFilter();
174 void AbstractTableModel::sort() {
175 if (sortingOn() && m_sortedItems->size() && !m_dataModel->isFiltering() &&
176 !m_dataModel->isRebuilding()) {
180 else if (!m_lessThanFunctor) {
184 m_lessThanFunctor =
new LessThanFunctor(
185 m_columns->getSortingOrder().first());
188 QFuture< QList< AbstractTreeItem * > > future =
189 QtConcurrent::run(
this, &AbstractTableModel::doSort,
191 m_sortingWatcher->setFuture(future);
193 emit modelModified();
199 void AbstractTableModel::reverseOrder(TableColumn *column) {
203 void AbstractTableModel::updateSort() {
207 AbstractTreeModel *AbstractTableModel::getDataModel() {
213 const AbstractTreeModel *AbstractTableModel::getDataModel()
const {
220 int start,
int end, AbstractTreeModel::InterestingItems flags) {
224 while (start <= end) {
225 if (start < m_sortedItems->size())
226 sortedSubsetOfItems.append(m_sortedItems->at(start));
227 else if (isFiltering())
228 sortedSubsetOfItems.append(m_busyItem);
234 sortedSubsetOfItems = getDataModel()->getItems(start, end, flags,
true);
237 return sortedSubsetOfItems;
242 AbstractTreeItem *item1, AbstractTreeItem *item2,
243 AbstractTreeModel::InterestingItems flags) {
247 sortedSubsetOfItems = getDataModel()->getItems(item1, item2, flags,
true);
250 AbstractTreeItem *start = NULL;
252 int currentIndex = 0;
254 while (!start && currentIndex < m_sortedItems->size()) {
255 AbstractTreeItem *current = m_sortedItems->at(currentIndex);
256 if (current == item1)
258 else if (current == item2)
266 IString msg =
"Could not find the first item";
270 AbstractTreeItem *end = item2;
277 AbstractTreeItem *
const &);
280 if (start == item2) {
285 while (currentIndex < m_sortedItems->size() &&
286 m_sortedItems->at(currentIndex) != end) {
287 (sortedSubsetOfItems.*someKindaPend)(m_sortedItems->at(currentIndex));
291 if (currentIndex >= m_sortedItems->size()) {
292 IString msg =
"Could not find the second item";
296 (sortedSubsetOfItems.*someKindaPend)(end);
299 return sortedSubsetOfItems;
303 void AbstractTableModel::handleTreeSelectionChanged(
305 AbstractTreeItem::InternalPointerType pointerType) {
307 foreach (AbstractTreeItem * item, newlySelectedItems) {
308 if (item->getPointerType() == pointerType)
309 interestingSelectedItems.append(item);
312 if (interestingSelectedItems.size()) {
313 emit treeSelectionChanged(interestingSelectedItems);
318 void AbstractTableModel::sortStatusUpdated() {
319 if (m_lessThanFunctor)
320 emit sortProgressChanged(m_lessThanFunctor->getCompareCount());
324 void AbstractTableModel::sortFinished() {
325 bool interrupted = m_lessThanFunctor->interrupted();
326 delete m_lessThanFunctor;
327 m_lessThanFunctor = NULL;
332 if (!m_dataModel->isFiltering() && !m_dataModel->isRebuilding()) {
333 *m_sortedItems = newSortedItems;
334 emit modelModified();
343 void AbstractTableModel::cancelSort() {
344 if (m_lessThanFunctor) {
345 m_lessThanFunctor->interrupt();
346 m_sortingWatcher->waitForFinished();
351 void AbstractTableModel::itemsLost() {
353 m_sortedItems->clear();
359 ASSERT(!isSorting());
367 m_sortStatusPoller->start(SORT_UPDATE_FREQUENCY);
371 int numItems = itemsToSort.size();
374 emit sortProgressRangeChanged(0,
375 (
int)((a * numItems) * (log2(b * numItems))));
378 qStableSort(itemsToSort.begin(), itemsToSort.end(),
381 catch (SortingCanceledException &e) {
382 m_sortStatusPoller->stop();
383 emit sortProgressRangeChanged(0, 0);
384 emit sortProgressChanged(0);
385 emit modelModified();
394 m_sortStatusPoller->stop();
395 emit sortProgressRangeChanged(0, 0);
396 emit sortProgressChanged(0);
397 emit modelModified();
407 void AbstractTableModel::nullify() {
410 m_sortedItems = NULL;
412 m_sortStatusPoller = NULL;
413 m_lessThanFunctor = NULL;
415 m_sortingWatcher = NULL;
419 void AbstractTableModel::setSorting(
bool isSorting) {
420 m_sorting = isSorting;
424 void AbstractTableModel::rebuildSort() {
426 ASSERT(m_sortedItems);
427 m_sortedItems->clear();
431 m_sortingEnabled =
false;
432 *m_sortedItems = getItems(0, -1);
434 foreach (AbstractTreeItem * item, *m_sortedItems) {
435 connect(item, SIGNAL(destroyed(
QObject *)),
this, SLOT(itemsLost()));
438 m_sortingEnabled =
true;
441 emit userWarning(None);
445 emit modelModified();
447 if (!m_sortingEnabled)
448 emit userWarning(SortingDisabled);
450 emit userWarning(SortingTableSizeLimitReached);
458 AbstractTableModel::LessThanFunctor::LessThanFunctor(
459 TableColumn
const *someColumn) : m_column(someColumn) {
460 m_sharedData =
new LessThanFunctorData;
464 AbstractTableModel::LessThanFunctor::LessThanFunctor(
465 LessThanFunctor
const &other) : m_sharedData(other.m_sharedData) {
466 m_column = other.m_column;
470 AbstractTableModel::LessThanFunctor::~LessThanFunctor() {
475 int AbstractTableModel::LessThanFunctor::getCompareCount()
const {
476 return m_sharedData->getCompareCount();
480 void AbstractTableModel::LessThanFunctor::interrupt() {
481 m_sharedData->setInterrupted(
true);
485 bool AbstractTableModel::LessThanFunctor::interrupted() {
486 return m_sharedData->interrupted();
490 void AbstractTableModel::LessThanFunctor::reset() {
491 m_sharedData->setInterrupted(
false);
495 bool AbstractTableModel::LessThanFunctor::operator()(
496 AbstractTreeItem *
const &left, AbstractTreeItem *
const &right) {
497 if (left->getPointerType() != right->getPointerType()) {
498 IString msg =
"Tried to compare apples to oranges";
502 if (m_sharedData->interrupted()) {
503 throw SortingCanceledException();
506 m_sharedData->incrementCompareCount();
508 QVariant leftData = left->getData(m_column->getTitle());
509 QVariant rightData = right->getData(m_column->getTitle());
510 QString busy = BusyLeafItem().getData().toString();
513 if (leftData.type() == QVariant::String &&
514 rightData.type() == QVariant::String) {
515 lessThan = leftData.toString() < rightData.toString();
517 else if (leftData.type() == QVariant::Double &&
518 rightData.type() == QVariant::Double) {
519 lessThan = (leftData.toDouble() < rightData.toDouble());
521 else if (leftData.type() == QVariant::Double ||
522 rightData.type() == QVariant::Double) {
525 lessThan = (leftData.toString() == busy);
528 lessThan = leftData.toString() < rightData.toString();
531 return lessThan ^ m_column->sortAscending();
535 AbstractTableModel::LessThanFunctor &
536 AbstractTableModel::LessThanFunctor::operator=(
537 LessThanFunctor
const &other) {
538 if (
this != &other) {
539 m_column = other.m_column;
540 m_sharedData = other.m_sharedData;
550 AbstractTableModel::LessThanFunctorData::LessThanFunctorData() {
551 m_compareCount.fetchAndStoreRelaxed(0);
552 m_interruptFlag.fetchAndStoreRelaxed(0);
556 AbstractTableModel::LessThanFunctorData::LessThanFunctorData(
557 LessThanFunctorData
const &other) :
QSharedData(other),
558 m_compareCount(other.m_compareCount), m_interruptFlag(other.m_interruptFlag) {
562 AbstractTableModel::LessThanFunctorData::~LessThanFunctorData() {
566 int AbstractTableModel::LessThanFunctorData::getCompareCount()
const {
567 return m_compareCount;
571 void AbstractTableModel::LessThanFunctorData::incrementCompareCount() {
572 m_compareCount.fetchAndAddRelaxed(1);
576 void AbstractTableModel::LessThanFunctorData::setInterrupted(
bool newStatus) {
577 newStatus ? m_interruptFlag.fetchAndStoreRelaxed(1) :
578 m_interruptFlag.fetchAndStoreRelaxed(0);
582 bool AbstractTableModel::LessThanFunctorData::interrupted() {
583 return m_interruptFlag != 0;