QMatchData QSortedModelEngine::filter(const QString& part, const QModelIndex& parent, int) { const QAbstractItemModel *model = c->proxy->sourceModel(); QMatchData hint; if (lookupCache(part, parent, &hint)) return hint; QIndexMapper indices; Qt::SortOrder order = sortOrder(parent); if (matchHint(part, parent, &hint)) { if (!hint.isValid()) return QMatchData(); indices = hint.indices; } else { indices = indexHint(part, parent, order); } // binary search the model within 'indices' for 'part' under 'parent' int high = indices.to() + 1; int low = indices.from() - 1; int probe; QModelIndex probeIndex; QString probeData; while (high - low > 1) { probe = (high + low) / 2; probeIndex = model->index(probe, c->column, parent); probeData = model->data(probeIndex, c->role).toString(); const int cmp = QString::compare(probeData, part, c->cs); if ((order == Qt::AscendingOrder && cmp >= 0) || (order == Qt::DescendingOrder && cmp < 0)) { high = probe; } else { low = probe; } } if ((order == Qt::AscendingOrder && low == indices.to()) || (order == Qt::DescendingOrder && high == indices.from())) { // not found saveInCache(part, parent, QMatchData()); return QMatchData(); } probeIndex = model->index(order == Qt::AscendingOrder ? low+1 : high-1, c->column, parent); probeData = model->data(probeIndex, c->role).toString(); if (!probeData.startsWith(part, c->cs)) { saveInCache(part, parent, QMatchData()); return QMatchData(); } const bool exactMatch = QString::compare(probeData, part, c->cs) == 0; int emi = exactMatch ? (order == Qt::AscendingOrder ? low+1 : high-1) : -1; int from = 0; int to = 0; if (order == Qt::AscendingOrder) { from = low + 1; high = indices.to() + 1; low = from; } else { to = high - 1; low = indices.from() - 1; high = to; } while (high - low > 1) { probe = (high + low) / 2; probeIndex = model->index(probe, c->column, parent); probeData = model->data(probeIndex, c->role).toString(); const bool startsWith = probeData.startsWith(part, c->cs); if ((order == Qt::AscendingOrder && startsWith) || (order == Qt::DescendingOrder && !startsWith)) { low = probe; } else { high = probe; } } QMatchData m(order == Qt::AscendingOrder ? QIndexMapper(from, high - 1) : QIndexMapper(low+1, to), emi, false); saveInCache(part, parent, m); return m; }
// Boilerplate program options code from http://www.radmangames.com/programming/how-to-use-boost-program_options int main(int argc, char** argv) { bool enable_sorting = true; double seed = 0; double power_mean = 300.0; // Watts double power_stdev = power_mean/10.0; double power_estimate_error_stdev = power_stdev/10.0; double arrival_rate = 1000.0; // Jobs per second double completion_time_mean = 0.9*NUM_SERVERS/arrival_rate; // Seconds double completion_time_stdev = completion_time_mean/10.0; double sorting_time_min = completion_time_mean/1000.0; double sorting_time_max = sorting_time_min*2.0; double routing_time_min = sorting_time_min; double routing_time_max = sorting_time_max; try { /** Define and parse the program options */ namespace po = boost::program_options; po::options_description desc("Options"); desc.add_options() ("help", "Print help messages") ("seed", po::value<double>(&seed), "Seed for random number generator") ("power_estimate_error_stdev", po::value<double>(&power_estimate_error_stdev), "Power estimate standard deviation") ("completion_time_stdev", po::value<double>(&completion_time_stdev), "Completion time standard deviation") ("enable_sorting", po::value<bool>(&enable_sorting), "Enable sorting") ; po::variables_map vm; try { po::store(po::parse_command_line(argc, argv, desc), vm); // can throw /** --help option */ if ( vm.count("help") ) { std::cout << "Basic Command Line Parameter App" << std::endl << desc << std::endl; return SUCCESS; } po::notify(vm); // throws on error, so do after help in case // there are any problems } catch(po::error& e) { std::cerr << "ERROR: " << e.what() << std::endl << std::endl; std::cerr << desc << std::endl; return ERROR_IN_COMMAND_LINE; } // BEGIN APPLICATION CODE // DataCenterRandomPtr rand(new DataCenterRandom( seed, power_mean, power_stdev, arrival_rate, completion_time_mean, completion_time_stdev, sorting_time_min, sorting_time_max, routing_time_min, routing_time_max, power_estimate_error_stdev)); PriorityTypePtr sortOrder(new JobEvent::PriorityType(JobEvent::TIME)); PriorityQueueEventListPtr eventList(new PriorityQueueEventList( EVENT_LIST_LEN, sortOrder)); PriorityQueueWorkingServers::SortingDomain sortingDomain; if(enable_sorting){ sortingDomain = PriorityQueueWorkingServers::POWER_AWARE; } else{ sortingDomain = PriorityQueueWorkingServers::RANDOM; } std::ostringstream s; s << seed; AccumulatorStatistics statistics(s.str()); PriorityQueueWorkingServersPtr workingServersQueue(new PriorityQueueWorkingServers( NUM_SERVERS, rand, eventList, statistics.getAccumulator(AccumulatorStatistics::LATENCY), statistics.getAccumulator(AccumulatorStatistics::TOTAL_ENERGY), sortOrder, s.str() + "server_currents.csv", sortingDomain)); PriorityQueueJobSorterPtr sortedJobQueue(new PriorityQueueJobSorter( SORTED_JOBS_LIST_LEN, rand, workingServersQueue, eventList, sortOrder, enable_sorting)); QueueJobBufferPtr unsortedJobQueue(new QueueJobBuffer( UNSORTED_JOBS_LIST_LEN, statistics.getAccumulator(AccumulatorStatistics::TIME_BETWEEN_REJECTED_JOBS), sortedJobQueue)); #ifndef UNITTEST double time = 0; JobEventPtr arrival(new JobEvent(0, Event::JOB_ARRIVAL, sortOrder)); _NOTEL(0,"Welcome to the data center stacked server simulator."); _LOGL(1,"Initialization parameters: "); _LOGL(1,"Sorting enabled: " << enable_sorting); _LOGL(1,"Simulation time: " << MAX_TIME); _LOGL(1,"Event list length: " << EVENT_LIST_LEN); _LOGL(1,"Unsorted jobs list length: " << UNSORTED_JOBS_LIST_LEN); _LOGL(1,"Sorted jobs list length: " << SORTED_JOBS_LIST_LEN); _LOGL(1,"Number of servers: " << NUM_SERVERS); _LOGL(1, *rand); // Queue up initial arrival. _NOTEL(2,"Creating initial arrival event."); eventList->enqueue(arrival); while(time < MAX_TIME){ EventPtr e = eventList->dequeue(); time = e->time; _NOTEL(2, time); if(e->type == Event::JOB_ARRIVAL || e->type == Event::JOB_FINISHED){ JobEventPtr job = boost::static_pointer_cast<JobEvent>(e); if(job->type == Event::JOB_ARRIVAL){ double t = time + rand->sample_arrivalTime(); _NOTEL(2,"Processing job arrival event. Scheduling next job arrival for time " << t); JobEventPtr nextJob(new JobEvent(t, Event::JOB_ARRIVAL, sortOrder)); eventList->enqueue(nextJob); if(!unsortedJobQueue->enqueue(job)){ if(!sortedJobQueue->enqueue(job,time)){ workingServersQueue->enqueue(job,time); } } } else{ // if(job->type == Event::JOB_FINISHED){ _NOTEL(2,"Processing job removal event."); workingServersQueue->remove(job,time); if(enable_sorting){ if(!sortedJobQueue->is_busy() && !sortedJobQueue->is_empty()){ JobEventPtr job = sortedJobQueue->dequeueJob(); workingServersQueue->enqueue(job,time); } } else{ if(!unsortedJobQueue->is_empty()){ JobEventPtr job = unsortedJobQueue->dequeue(); workingServersQueue->enqueue(job,time); } } } } else if(e->type == Event::SORTED_QUEUE_READY){ if(enable_sorting){ _NOTEL(2,"Processing sorted queue ready event."); sortedJobQueue->reset_busy(); if(!sortedJobQueue->is_empty() && !workingServersQueue->is_busy() && !workingServersQueue->is_full()){ JobEventPtr job = sortedJobQueue->dequeueJob(); workingServersQueue->enqueue(job,time); } if(!unsortedJobQueue->is_empty()){ JobEventPtr job = unsortedJobQueue->dequeue(); if(!sortedJobQueue->enqueue(job,time)){ workingServersQueue->enqueue(job,time); } } else{ _NOTEL(2,"Nothing for sorted queue to do."); } } else{ _NOTEL(0,"PROBLEM!!!"); } } else{ // if(e->type == Event::WORKING_SERVERS_QUEUE_READY){ _NOTEL(2,"Processing working servers queue ready event."); workingServersQueue->reset_busy(); if(enable_sorting){ if(!sortedJobQueue->is_busy() && !sortedJobQueue->is_empty()){ JobEventPtr job = sortedJobQueue->dequeueJob(); workingServersQueue->enqueue(job,time); } } else{ if(!unsortedJobQueue->is_empty()){ JobEventPtr job = unsortedJobQueue->dequeue(); workingServersQueue->enqueue(job,time); } } } //_NOTE(3, (*eventList) << std::endl); } _NOTEL(1,"Finished simulation of " << time << " virtual seconds."); _LOGL(0,"Simulation results: " << std::endl << statistics); AccumulatorPtr latency = statistics.getAccumulator(AccumulatorStatistics::LATENCY); AccumulatorPtr total_energy = statistics.getAccumulator(AccumulatorStatistics::TOTAL_ENERGY); _LOGL(0, latency->getMean() << "$\\pm$" << latency->getCI(0.95) << " & " << total_energy->getMean() << "$\\pm$" << total_energy->getCI(0.95)); return 0; // Run the Unit tests #else _NOTEL(0,"Welcome to the unit tests."); test_accumulator(rand,statistics); test_working_servers(workingServersQueue,sortOrder,statistics); return 0; #endif // END APPLICATION CODE // } catch(std::exception& e) { std::cerr << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << std::endl; return ERROR_UNHANDLED_EXCEPTION; } return SUCCESS; } // main
bool RKObjectListViewSettings::lessThan (const QModelIndex& left, const QModelIndex& right) const { // don't trace this. Used in sorting if (!(left.isValid () && right.isValid ())) return false; RObject* left_object = static_cast<RObject*> (left.internalPointer ()); RObject* right_object = static_cast<RObject*> (right.internalPointer ()); // for top-level environments, always use the search order if (left_object->isType (RObject::ToplevelEnv) && right_object->isType (RObject::ToplevelEnv)) { RObject* left_parent = left_object->parentObject (); RObject* right_parent = right_object->parentObject (); if (!(left_parent && right_parent)) return false; return (left_parent->getObjectModelIndexOf (left_object) < right_parent->getObjectModelIndexOf (right_object)); } else if (left_object->isPseudoObject ()) return false; else if (right_object->isPseudoObject ()) return true; else if (!left.parent ().isValid ()) { // For the two root items, _always_ sort .GlobalEnv on top, irrespective of sort order return ((static_cast<RObject*> (left.internalPointer ()) == RObjectList::getGlobalEnv ()) == (sortOrder () == Qt::AscendingOrder)); } return (QSortFilterProxyModel::lessThan (left, right)); }
bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { switch (sortColumn()) { case TransferListModel::TR_CATEGORY: case TransferListModel::TR_TAGS: case TransferListModel::TR_NAME: { const QVariant vL = left.data(); const QVariant vR = right.data(); if (!vL.isValid() || !vR.isValid() || (vL == vR)) return lowerPositionThan(left, right); const int result = Utils::String::naturalCompare(vL.toString(), vR.toString(), Qt::CaseInsensitive); return (result < 0); } case TransferListModel::TR_STATUS: { // QSortFilterProxyModel::lessThan() uses the < operator only for specific QVariant types // so our custom type is outside that list. // In this case QSortFilterProxyModel::lessThan() converts other types to QString and // sorts them. // Thus we can't use the code in the default label. const auto leftValue = left.data().value<BitTorrent::TorrentState>(); const auto rightValue = right.data().value<BitTorrent::TorrentState>(); if (leftValue != rightValue) return leftValue < rightValue; return lowerPositionThan(left, right); } case TransferListModel::TR_ADD_DATE: case TransferListModel::TR_SEED_DATE: case TransferListModel::TR_SEEN_COMPLETE_DATE: { return dateLessThan(sortColumn(), left, right, true); } case TransferListModel::TR_PRIORITY: { return lowerPositionThan(left, right); } case TransferListModel::TR_SEEDS: case TransferListModel::TR_PEERS: { const int leftActive = left.data().toInt(); const int leftTotal = left.data(Qt::UserRole).toInt(); const int rightActive = right.data().toInt(); const int rightTotal = right.data(Qt::UserRole).toInt(); // Active peers/seeds take precedence over total peers/seeds. if (leftActive != rightActive) return (leftActive < rightActive); if (leftTotal != rightTotal) return (leftTotal < rightTotal); return lowerPositionThan(left, right); } case TransferListModel::TR_ETA: { const TransferListModel *model = qobject_cast<TransferListModel *>(sourceModel()); // Sorting rules prioritized. // 1. Active torrents at the top // 2. Seeding torrents at the bottom // 3. Torrents with invalid ETAs at the bottom const bool isActiveL = TorrentFilter::ActiveTorrent.match(model->torrentHandle(model->index(left.row()))); const bool isActiveR = TorrentFilter::ActiveTorrent.match(model->torrentHandle(model->index(right.row()))); if (isActiveL != isActiveR) return isActiveL; const int prioL = model->data(model->index(left.row(), TransferListModel::TR_PRIORITY)).toInt(); const int prioR = model->data(model->index(right.row(), TransferListModel::TR_PRIORITY)).toInt(); const bool isSeedingL = (prioL < 0); const bool isSeedingR = (prioR < 0); if (isSeedingL != isSeedingR) { const bool isAscendingOrder = (sortOrder() == Qt::AscendingOrder); if (isSeedingL) return !isAscendingOrder; return isAscendingOrder; } const qlonglong etaL = left.data().toLongLong(); const qlonglong etaR = right.data().toLongLong(); const bool isInvalidL = ((etaL < 0) || (etaL >= MAX_ETA)); const bool isInvalidR = ((etaR < 0) || (etaR >= MAX_ETA)); if (isInvalidL && isInvalidR) { if (isSeedingL) // Both seeding return dateLessThan(TransferListModel::TR_SEED_DATE, left, right, true); return (prioL < prioR); } if (!isInvalidL && !isInvalidR) { return (etaL < etaR); } return !isInvalidL; } case TransferListModel::TR_LAST_ACTIVITY: { const int vL = left.data().toInt(); const int vR = right.data().toInt(); if (vL < 0) return false; if (vR < 0) return true; return (vL < vR); } case TransferListModel::TR_RATIO_LIMIT: { const qreal vL = left.data().toReal(); const qreal vR = right.data().toReal(); if (vL < 0) return false; if (vR < 0) return true; return (vL < vR); } default: { if (left.data() != right.data()) return QSortFilterProxyModel::lessThan(left, right); return lowerPositionThan(left, right); } } }
bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { const int column = sortColumn(); if (column == TorrentModel::TR_NAME) { QVariant vL = left.data(); QVariant vR = right.data(); if (!vL.isValid() || !vR.isValid() || (vL == vR)) return lowerPositionThan(left, right); bool res = false; if (Utils::String::naturalSort(vL.toString(), vR.toString(), res)) return res; return QSortFilterProxyModel::lessThan(left, right); } else if (column == TorrentModel::TR_ADD_DATE || column == TorrentModel::TR_SEED_DATE || column == TorrentModel::TR_SEEN_COMPLETE_DATE) { QDateTime vL = left.data().toDateTime(); QDateTime vR = right.data().toDateTime(); //not valid dates should be sorted at the bottom. if (!vL.isValid()) return false; if (!vR.isValid()) return true; return vL < vR; } else if (column == TorrentModel::TR_PRIORITY) { return lowerPositionThan(left, right); } else if (column == TorrentModel::TR_PEERS || column == TorrentModel::TR_SEEDS) { int left_active = left.data().toInt(); int left_total = left.data(Qt::UserRole).toInt(); int right_active = right.data().toInt(); int right_total = right.data(Qt::UserRole).toInt(); // Active peers/seeds take precedence over total peers/seeds. if (left_active == right_active) { if (left_total == right_total) return lowerPositionThan(left, right); return (left_total < right_total); } else { return (left_active < right_active); } } else if (column == TorrentModel::TR_ETA) { TorrentModel *model = qobject_cast<TorrentModel *>(sourceModel()); const int prioL = model->data(model->index(left.row(), TorrentModel::TR_PRIORITY)).toInt(); const int prioR = model->data(model->index(right.row(), TorrentModel::TR_PRIORITY)).toInt(); const qlonglong etaL = left.data().toLongLong(); const qlonglong etaR = right.data().toLongLong(); const bool ascend = (sortOrder() == Qt::AscendingOrder); const bool invalidL = (etaL < 0 || etaL >= MAX_ETA); const bool invalidR = (etaR < 0 || etaR >= MAX_ETA); const bool seedingL = (prioL < 0); const bool seedingR = (prioR < 0); bool activeR = TorrentFilter::ActiveTorrent.match(model->torrentHandle(model->index(right.row()))); bool activeL = TorrentFilter::ActiveTorrent.match(model->torrentHandle(model->index(right.row()))); // Sorting rules prioritized. // 1. Active torrents at the top // 2. Seeding torrents at the bottom // 3. Torrents with invalid ETAs at the bottom if (activeL != activeR) return activeL; if (seedingL != seedingR) { if (seedingL) return !ascend; else return ascend; } if (invalidL && invalidR) { if (seedingL) { //Both seeding QDateTime dateL = model->data(model->index(left.row(), TorrentModel::TR_SEED_DATE)).toDateTime(); QDateTime dateR = model->data(model->index(right.row(), TorrentModel::TR_SEED_DATE)).toDateTime(); //not valid dates should be sorted at the bottom. if (!dateL.isValid()) return false; if (!dateR.isValid()) return true; return dateL < dateR; } else { return prioL < prioR; } } else if (!invalidL && !invalidR) { return lowerPositionThan(left, right); } else { return !invalidL; } } else if (column == TorrentModel::TR_LAST_ACTIVITY) { const qlonglong vL = left.data().toLongLong(); const qlonglong vR = right.data().toLongLong(); if (vL == -1) return false; if (vR == -1) return true; return vL < vR; } else if (column == TorrentModel::TR_RATIO_LIMIT) { const qreal vL = left.data().toDouble(); const qreal vR = right.data().toDouble(); if (vL == -1) return false; if (vR == -1) return true; return vL < vR; } if (left.data() == right.data()) return lowerPositionThan(left, right); return QSortFilterProxyModel::lessThan(left, right); }
void TffdshowPageDec::onResetOrder(void) { if (SUCCEEDED(deciD->resetOrder())) { sortOrder(); } }
void SortFilterModel::manualSort() { sort(0, sortOrder()); }
void QDeclarativeContactSortOrder::componentComplete() { setSortOrder(sortOrder()); }