void SortUtils::Sort(SortBy sortBy, SortOrder sortOrder, SortAttribute attributes, DatabaseResults& items, int limitEnd /* = -1 */, int limitStart /* = 0 */) { if (sortBy != SortByNone) { // get the matching SortPreparator SortPreparator preparator = getPreparator(sortBy); if (preparator != NULL) { Fields sortingFields = GetFieldsForSorting(sortBy); // Prepare the string used for sorting and store it under FieldSort for (DatabaseResults::iterator item = items.begin(); item != items.end(); ++item) { // add all fields to the item that are required for sorting if they are currently missing for (Fields::const_iterator field = sortingFields.begin(); field != sortingFields.end(); ++field) { if (item->find(*field) == item->end()) item->insert(std::pair<Field, CVariant>(*field, CVariant::ConstNullVariant)); } std::wstring sortLabel; g_charsetConverter.utf8ToW(preparator(attributes, *item), sortLabel, false); item->insert(std::pair<Field, CVariant>(FieldSort, CVariant(sortLabel))); } // Do the sorting std::stable_sort(items.begin(), items.end(), getSorter(sortOrder, attributes)); } } if (limitStart > 0 && (size_t)limitStart < items.size()) { items.erase(items.begin(), items.begin() + limitStart); limitEnd -= limitStart; } if (limitEnd > 0 && (size_t)limitEnd < items.size()) items.erase(items.begin() + limitEnd, items.end()); }
bool DatabaseUtils::GetDatabaseResults(const MediaType &mediaType, const FieldList &fields, const std::unique_ptr<dbiplus::Dataset> &dataset, DatabaseResults &results) { if (dataset->num_rows() == 0) return true; const dbiplus::result_set &resultSet = dataset->get_result_set(); unsigned int offset = results.size(); if (fields.empty()) { DatabaseResult result; for (unsigned int index = 0; index < resultSet.records.size(); index++) { result[FieldRow] = index + offset; results.push_back(result); } return true; } if (resultSet.record_header.size() < fields.size()) return false; std::vector<int> fieldIndexLookup; fieldIndexLookup.reserve(fields.size()); for (FieldList::const_iterator it = fields.begin(); it != fields.end(); ++it) fieldIndexLookup.push_back(GetFieldIndex(*it, mediaType)); results.reserve(resultSet.records.size() + offset); for (unsigned int index = 0; index < resultSet.records.size(); index++) { DatabaseResult result; result[FieldRow] = index + offset; unsigned int lookupIndex = 0; for (FieldList::const_iterator it = fields.begin(); it != fields.end(); ++it) { int fieldIndex = fieldIndexLookup[lookupIndex++]; if (fieldIndex < 0) return false; std::pair<Field, CVariant> value; value.first = *it; if (!GetFieldValue(resultSet.records[index]->at(fieldIndex), value.second)) CLog::Log(LOGWARNING, "GetDatabaseResults: unable to retrieve value of field %s", resultSet.record_header[fieldIndex].name.c_str()); if (value.first == FieldYear && (mediaType == MediaTypeTvShow || mediaType == MediaTypeEpisode)) { CDateTime dateTime; dateTime.SetFromDBDate(value.second.asString()); if (dateTime.IsValid()) { value.second.clear(); value.second = dateTime.GetYear(); } } result.insert(value); } result[FieldMediaType] = mediaType; if (mediaType == MediaTypeMovie || mediaType == MediaTypeVideoCollection || mediaType == MediaTypeTvShow || mediaType == MediaTypeMusicVideo) result[FieldLabel] = result.at(FieldTitle).asString(); else if (mediaType == MediaTypeEpisode) { std::ostringstream label; label << (int)(result.at(FieldSeason).asInteger() * 100 + result.at(FieldEpisodeNumber).asInteger()); label << ". "; label << result.at(FieldTitle).asString(); result[FieldLabel] = label.str(); } else if (mediaType == MediaTypeAlbum) result[FieldLabel] = result.at(FieldAlbum).asString(); else if (mediaType == MediaTypeSong) { std::ostringstream label; label << (int)result.at(FieldTrackNumber).asInteger(); label << ". "; label << result.at(FieldTitle).asString(); result[FieldLabel] = label.str(); } else if (mediaType == MediaTypeArtist) result[FieldLabel] = result.at(FieldArtist).asString(); results.push_back(result); } return true; }