diff --git a/core/libs/database/models/itemsortsettings.cpp b/core/libs/database/models/itemsortsettings.cpp index ec26afb7df..3e5f6d1a7f 100644 --- a/core/libs/database/models/itemsortsettings.cpp +++ b/core/libs/database/models/itemsortsettings.cpp @@ -1,425 +1,425 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2009-03-05 * Description : Filter values for use with ItemFilterModel * * Copyright (C) 2009 by Marcel Wiesweg * Copyright (C) 2014 by Mohamed_Anwer * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "itemsortsettings.h" // Qt includes #include #include // Local includes #include "coredbfields.h" #include "iteminfo.h" namespace Digikam { ItemSortSettings::ItemSortSettings() { categorizationMode = NoCategories; categorizationSortOrder = DefaultOrder; categorizationCaseSensitivity = Qt::CaseSensitive; sortRole = SortByFileName; sortOrder = DefaultOrder; strTypeNatural = true; sortCaseSensitivity = Qt::CaseSensitive; currentCategorizationSortOrder = Qt::AscendingOrder; currentSortOrder = Qt::AscendingOrder; } bool ItemSortSettings::operator==(const ItemSortSettings& other) const { return categorizationMode == other.categorizationMode && categorizationSortOrder == other.categorizationSortOrder && categorizationCaseSensitivity == other.categorizationCaseSensitivity && sortRole == other.sortRole && sortOrder == other.sortOrder && sortCaseSensitivity == other.sortCaseSensitivity; } void ItemSortSettings::setCategorizationMode(CategorizationMode mode) { categorizationMode = mode; if (categorizationSortOrder == DefaultOrder) { currentCategorizationSortOrder = defaultSortOrderForCategorizationMode(categorizationMode); } } void ItemSortSettings::setCategorizationSortOrder(SortOrder order) { categorizationSortOrder = order; if (categorizationSortOrder == DefaultOrder) { currentCategorizationSortOrder = defaultSortOrderForCategorizationMode(categorizationMode); } else { currentCategorizationSortOrder = (Qt::SortOrder)categorizationSortOrder; } } void ItemSortSettings::setSortRole(SortRole role) { sortRole = role; if (sortOrder == DefaultOrder) { currentSortOrder = defaultSortOrderForSortRole(sortRole); } } void ItemSortSettings::setSortOrder(SortOrder order) { sortOrder = order; if (sortOrder == DefaultOrder) { currentSortOrder = defaultSortOrderForSortRole(sortRole); } else { currentSortOrder = (Qt::SortOrder)order; } } void ItemSortSettings::setStringTypeNatural(bool natural) { strTypeNatural = natural; } Qt::SortOrder ItemSortSettings::defaultSortOrderForCategorizationMode(CategorizationMode mode) { switch (mode) { case OneCategory: case NoCategories: case CategoryByAlbum: case CategoryByMonth: case CategoryByFormat: default: return Qt::AscendingOrder; } } Qt::SortOrder ItemSortSettings::defaultSortOrderForSortRole(SortRole role) { switch (role) { case SortByFilePath: case SortByFileName: case SortByManualOrder: case SortByCreationDate: case SortByModificationDate: return Qt::AscendingOrder; case SortByRating: case SortByFileSize: case SortByImageSize: case SortBySimilarity: case SortByAspectRatio: return Qt::DescendingOrder; default: return Qt::AscendingOrder; } } int ItemSortSettings::compareCategories(const ItemInfo& left, const ItemInfo& right) const { switch (categorizationMode) { case NoCategories: case OneCategory: return 0; case CategoryByAlbum: { int leftAlbum = left.albumId(); int rightAlbum = right.albumId(); // return comparison result if (leftAlbum == rightAlbum) { return 0; } else if (lessThanByOrder(leftAlbum, rightAlbum, currentCategorizationSortOrder)) { return -1; } else { return 1; } } case CategoryByFormat: { return naturalCompare(left.format(), right.format(), currentCategorizationSortOrder, categorizationCaseSensitivity, strTypeNatural); } case CategoryByMonth: { return compareByOrder(left.dateTime().date(), right.dateTime().date(), currentCategorizationSortOrder); } default: return 0; } } bool ItemSortSettings::lessThan(const ItemInfo& left, const ItemInfo& right) const { int result = compare(left, right, sortRole); if (result != 0) { return result < 0; } // are they identical? if (left == right) { return false; } // If left and right equal for first sort order, use a hierarchy of all sort orders if ( (result = compare(left, right, SortByFileName)) != 0) { return result < 0; } if ( (result = compare(left, right, SortByCreationDate)) != 0) { return result < 0; } if ( (result = compare(left, right, SortByModificationDate)) != 0) { return result < 0; } if ( (result = compare(left, right, SortByFilePath)) != 0) { return result < 0; } if ( (result = compare(left, right, SortByFileSize)) != 0) { return result < 0; } if ( (result = compare(left, right, SortBySimilarity)) != 0) { return result < 0; } if ( (result = compare(left, right, SortByManualOrder)) != 0) { return result < 0; } return false; } int ItemSortSettings::compare(const ItemInfo& left, const ItemInfo& right) const { return compare(left, right, sortRole); } int ItemSortSettings::compare(const ItemInfo& left, const ItemInfo& right, SortRole role) const { switch (role) { case SortByFileName: { - bool versioning = (left.name().contains(QLatin1String("_v"), Qt::CaseInsensitive) || - right.name().contains(QLatin1String("_v"), Qt::CaseInsensitive)); - return naturalCompare(left.name(), right.name(), currentSortOrder, sortCaseSensitivity, strTypeNatural, versioning); + return naturalCompare(left.name(), right.name(), + currentSortOrder, sortCaseSensitivity, strTypeNatural); } case SortByFilePath: - return naturalCompare(left.filePath(), right.filePath(), currentSortOrder, sortCaseSensitivity, strTypeNatural); + return naturalCompare(left.filePath(), right.filePath(), + currentSortOrder, sortCaseSensitivity, strTypeNatural); case SortByFileSize: return compareByOrder(left.fileSize(), right.fileSize(), currentSortOrder); case SortByModificationDate: return compareByOrder(left.modDateTime(), right.modDateTime(), currentSortOrder); case SortByCreationDate: return compareByOrder(left.dateTime(), right.dateTime(), currentSortOrder); case SortByRating: // I have the feeling that inverting the sort order for rating is the natural order return - compareByOrder(left.rating(), right.rating(), currentSortOrder); case SortByImageSize: { QSize leftSize = left.dimensions(); QSize rightSize = right.dimensions(); int leftPixels = leftSize.width() * leftSize.height(); int rightPixels = rightSize.width() * rightSize.height(); return compareByOrder(leftPixels, rightPixels, currentSortOrder); } case SortByAspectRatio: { QSize leftSize = left.dimensions(); QSize rightSize = right.dimensions(); int leftAR = (double(leftSize.width()) / double(leftSize.height())) * 1000000; int rightAR = (double(rightSize.width()) / double(rightSize.height())) * 1000000; return compareByOrder(leftAR, rightAR, currentSortOrder); } case SortBySimilarity: { qlonglong leftReferenceImageId = left.currentReferenceImage(); qlonglong rightReferenceImageId = right.currentReferenceImage(); // make sure that the original image has always the highest similarity. double leftSimilarity = left.id() == leftReferenceImageId ? 1.1 : left.currentSimilarity(); double rightSimilarity = right.id() == rightReferenceImageId ? 1.1 : right.currentSimilarity(); return compareByOrder(leftSimilarity, rightSimilarity, currentSortOrder); } case SortByManualOrder: return compareByOrder(left.manualOrder(), right.manualOrder(), currentSortOrder); default: return 1; } } bool ItemSortSettings::lessThan(const QVariant& left, const QVariant& right) const { if (left.type() != right.type()) { return false; } switch (left.type()) { case QVariant::Int: return compareByOrder(left.toInt(), right.toInt(), currentSortOrder); case QVariant::UInt: return compareByOrder(left.toUInt(), right.toUInt(), currentSortOrder); case QVariant::LongLong: return compareByOrder(left.toLongLong(), right.toLongLong(), currentSortOrder); case QVariant::ULongLong: return compareByOrder(left.toULongLong(), right.toULongLong(), currentSortOrder); case QVariant::Double: return compareByOrder(left.toDouble(), right.toDouble(), currentSortOrder); case QVariant::Date: return compareByOrder(left.toDate(), right.toDate(), currentSortOrder); case QVariant::DateTime: return compareByOrder(left.toDateTime(), right.toDateTime(), currentSortOrder); case QVariant::Time: return compareByOrder(left.toTime(), right.toTime(), currentSortOrder); case QVariant::Rect: case QVariant::RectF: { QRectF rectLeft = left.toRectF(); QRectF rectRight = right.toRectF(); int result; if ((result = compareByOrder(rectLeft.top(), rectRight.top(), currentSortOrder)) != 0) { return result < 0; } if ((result = compareByOrder(rectLeft.left(), rectRight.left(), currentSortOrder)) != 0) { return result < 0; } QSizeF sizeLeft = rectLeft.size(); QSizeF sizeRight = rectRight.size(); if ((result = compareByOrder(sizeLeft.width()*sizeLeft.height(), sizeRight.width()*sizeRight.height(), currentSortOrder)) != 0) { return result < 0; } #if __GNUC__ >= 7 // krazy:exclude=cpp [[fallthrough]]; #endif } default: { return naturalCompare(left.toString(), right.toString(), currentSortOrder, sortCaseSensitivity, strTypeNatural); } } } DatabaseFields::Set ItemSortSettings::watchFlags() const { DatabaseFields::Set set; switch (sortRole) { case SortByFileName: set |= DatabaseFields::Name; break; case SortByFilePath: set |= DatabaseFields::Name; break; case SortByFileSize: set |= DatabaseFields::FileSize; break; case SortByModificationDate: set |= DatabaseFields::ModificationDate; break; case SortByCreationDate: set |= DatabaseFields::CreationDate; break; case SortByRating: set |= DatabaseFields::Rating; break; case SortByImageSize: set |= DatabaseFields::Width | DatabaseFields::Height; break; case SortByAspectRatio: set |= DatabaseFields::Width | DatabaseFields::Height; break; case SortBySimilarity: // TODO: Not sure what to do here.... set |= DatabaseFields::Name; break; case SortByManualOrder: set |= DatabaseFields::ManualOrder; break; } switch (categorizationMode) { case OneCategory: case NoCategories: case CategoryByAlbum: break; case CategoryByFormat: set |= DatabaseFields::Format; break; case CategoryByMonth: set |= DatabaseFields::CreationDate; break; } return set; } } // namespace Digikam diff --git a/core/libs/database/models/itemsortsettings.h b/core/libs/database/models/itemsortsettings.h index 1e9e2350ed..33e8cf0848 100644 --- a/core/libs/database/models/itemsortsettings.h +++ b/core/libs/database/models/itemsortsettings.h @@ -1,227 +1,232 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2009-05-31 * Description : Sort settings for use with ItemFilterModel * * Copyright (C) 2009 by Marcel Wiesweg * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_ITEM_SORT_SETTINGS_H #define DIGIKAM_ITEM_SORT_SETTINGS_H // Qt includes #include #include #include #include #include // Local includes #include "digikam_export.h" namespace Digikam { class ItemInfo; namespace DatabaseFields { class Set; } class DIGIKAM_DATABASE_EXPORT ItemSortSettings { public: explicit ItemSortSettings(); bool operator==(const ItemSortSettings& other) const; /** Compares the categories of left and right. * Return -1 if left is less than right, 0 if both fall in the same category, * and 1 if left is greater than right. * Adheres to set categorization mode and current category sort order. */ int compareCategories(const ItemInfo& left, const ItemInfo& right) const; /** Returns true if left is less than right. * Adheres to current sort role and sort order. */ bool lessThan(const ItemInfo& left, const ItemInfo& right) const; /** Compares the ItemInfos left and right. * Return -1 if left is less than right, 1 if left is greater than right, * and 0 if left equals right comparing the current sort role's value. * Adheres to set sort role and sort order. */ int compare(const ItemInfo& left, const ItemInfo& right) const; /** Returns true if left QVariant is less than right. * Adheres to current sort role and sort order. * Use for extraValue, if necessary. */ bool lessThan(const QVariant& left, const QVariant& right) const; enum SortOrder { AscendingOrder = Qt::AscendingOrder, DescendingOrder = Qt::DescendingOrder, DefaultOrder /// sort order depends on the chosen sort role }; /// --- Categories --- enum CategorizationMode { NoCategories, /// categorization switched off OneCategory, /// all items in one global category CategoryByAlbum, CategoryByFormat, CategoryByMonth }; CategorizationMode categorizationMode; SortOrder categorizationSortOrder; void setCategorizationMode(CategorizationMode mode); void setCategorizationSortOrder(SortOrder order); /// Only Ascending or Descending, never DefaultOrder Qt::SortOrder currentCategorizationSortOrder; Qt::CaseSensitivity categorizationCaseSensitivity; bool isCategorized() const { return categorizationMode >= CategoryByAlbum; } /// --- Image Sorting --- enum SortRole { // Note: For legacy reasons, the order of the first five entries must remain unchanged SortByFileName, SortByFilePath, SortByCreationDate, SortByFileSize, SortByRating, SortByImageSize, // pixel number SortByAspectRatio, // width / height * 100000 SortBySimilarity, SortByManualOrder, SortByModificationDate // currently not used in the icon view }; SortRole sortRole; SortOrder sortOrder; bool strTypeNatural; void setSortRole(SortRole role); void setSortOrder(SortOrder order); void setStringTypeNatural(bool natural); Qt::SortOrder currentSortOrder; Qt::CaseSensitivity sortCaseSensitivity; int compare(const ItemInfo& left, const ItemInfo& right, SortRole sortRole) const; // --- --- static Qt::SortOrder defaultSortOrderForCategorizationMode(CategorizationMode mode); static Qt::SortOrder defaultSortOrderForSortRole(SortRole role); /// --- Change notification --- /** Returns database fields a change in which would affect the current sorting. */ DatabaseFields::Set watchFlags() const; /// --- Utilities --- /** Returns a < b if sortOrder is Ascending, or b < a if order is descending. */ template static inline bool lessThanByOrder(const T& a, const T& b, Qt::SortOrder sortOrder) { if (sortOrder == Qt::AscendingOrder) { return a < b; } - else - { - return b < a; - } + + return b < a; } /** Returns the usual compare result of -1, 0, or 1 for lessThan, equals and greaterThan. */ template static inline int compareValue(const T& a, const T& b) { if (a == b) { return 0; } - if (a < b) - { - return -1; - } - else + if (a > b) { return 1; } + + return -1; } /** Takes a typical result from a compare method (0 is equal, -1 is less than, 1 is greater than) * and applies the given sort order to it. */ static inline int compareByOrder(int compareResult, Qt::SortOrder sortOrder) { if (sortOrder == Qt::AscendingOrder) { return compareResult; } - else - { - return - compareResult; - } + + return - compareResult; } template static inline int compareByOrder(const T& a, const T& b, Qt::SortOrder sortOrder) { return compareByOrder(compareValue(a, b), sortOrder); } /** Compares the two string by natural comparison and adheres to given sort order */ static inline int naturalCompare(const QString& a, const QString& b, Qt::SortOrder sortOrder, Qt::CaseSensitivity caseSensitive = Qt::CaseSensitive, - bool natural = true, bool versioning = false) + bool natural = true) { QCollator collator; collator.setNumericMode(natural); - collator.setIgnorePunctuation(versioning); + collator.setIgnorePunctuation(false); collator.setCaseSensitivity(caseSensitive); - return (compareByOrder(collator.compare(a, b), sortOrder)); + + if (a.contains(QLatin1String("_v"), Qt::CaseInsensitive)) + { + collator.setIgnorePunctuation(true); + } + + if (sortOrder == Qt::AscendingOrder) + { + return collator.compare(a, b); + } + + return - collator.compare(a, b); } }; } // namespace Digikam #endif // DIGIKAM_ITEM_SORT_SETTINGS_H diff --git a/core/libs/models/itemalbumfiltermodel.cpp b/core/libs/models/itemalbumfiltermodel.cpp index 1bb39c7558..ac2c8eab0c 100644 --- a/core/libs/models/itemalbumfiltermodel.cpp +++ b/core/libs/models/itemalbumfiltermodel.cpp @@ -1,244 +1,244 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2009-03-11 * Description : Qt item model for database entries, using AlbumManager * * Copyright (C) 2009-2011 by Marcel Wiesweg * Copyright (C) 2015 by Mohamed_Anwer * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "itemalbumfiltermodel.h" // Qt includes #include // Local includes #include "itemfiltermodel_p.h" #include "album.h" #include "albummanager.h" #include "coredbaccess.h" #include "coredbchangesets.h" #include "coredbwatch.h" #include "itemalbummodel.h" namespace Digikam { class Q_DECL_HIDDEN ItemAlbumFilterModelPrivate : public ItemFilterModel::ItemFilterModelPrivate { public: ItemAlbumFilterModelPrivate() { delayedAlbumNamesTimer = 0; delayedTagNamesTimer = 0; } QHash tagNamesHash; QHash albumNamesHash; QTimer* delayedAlbumNamesTimer; QTimer* delayedTagNamesTimer; }; ItemAlbumFilterModel::ItemAlbumFilterModel(QObject* const parent) : ItemFilterModel(*new ItemAlbumFilterModelPrivate, parent) { Q_D(ItemAlbumFilterModel); connect(AlbumManager::instance(), SIGNAL(signalAlbumAdded(Album*)), this, SLOT(slotAlbumAdded(Album*))); connect(AlbumManager::instance(), SIGNAL(signalAlbumAboutToBeDeleted(Album*)), this, SLOT(slotAlbumAboutToBeDeleted(Album*))); connect(AlbumManager::instance(), SIGNAL(signalAlbumsCleared()), this, SLOT(slotAlbumsCleared())); connect(AlbumManager::instance(), SIGNAL(signalAlbumRenamed(Album*)), this, SLOT(slotAlbumRenamed(Album*))); d->delayedAlbumNamesTimer = new QTimer(this); d->delayedAlbumNamesTimer->setInterval(250); d->delayedAlbumNamesTimer->setSingleShot(true); d->delayedTagNamesTimer = new QTimer(this); d->delayedTagNamesTimer->setInterval(250); d->delayedTagNamesTimer->setSingleShot(true); connect(d->delayedAlbumNamesTimer, SIGNAL(timeout()), this, SLOT(slotDelayedAlbumNamesTimer())); connect(d->delayedTagNamesTimer, SIGNAL(timeout()), this, SLOT(slotDelayedTagNamesTimer())); foreach (Album* const a, AlbumManager::instance()->allPAlbums()) { albumChange(a); } foreach (Album* const a, AlbumManager::instance()->allTAlbums()) { albumChange(a); } } ItemAlbumFilterModel::~ItemAlbumFilterModel() { } void ItemAlbumFilterModel::setSourceItemModel(ItemAlbumModel* model) { ItemFilterModel::setSourceItemModel(model); } ItemAlbumModel* ItemAlbumFilterModel::sourceModel() const { Q_D(const ItemAlbumFilterModel); return static_cast(d->imageModel); } void ItemAlbumFilterModel::prepareThumbnails(const QList& indexesToPrepare) { sourceModel()->prepareThumbnails(mapListToSource(indexesToPrepare)); } void ItemAlbumFilterModel::setItemFilterSettings(const ItemFilterSettings& s) { Q_D(ItemAlbumFilterModel); ItemFilterSettings settings(s); settings.setAlbumNames(d->albumNamesHash); settings.setTagNames(d->tagNamesHash); ItemFilterModel::setItemFilterSettings(settings); } int ItemAlbumFilterModel::compareInfosCategories(const ItemInfo& left, const ItemInfo& right) const { Q_D(const ItemAlbumFilterModel); switch (d->sorter.categorizationMode) { case ItemSortSettings::CategoryByAlbum: { int leftAlbumId = left.albumId(); int rightAlbumId = right.albumId(); PAlbum* const leftAlbum = AlbumManager::instance()->findPAlbum(leftAlbumId); PAlbum* const rightAlbum = AlbumManager::instance()->findPAlbum(rightAlbumId); if (!leftAlbum || !rightAlbum) { return -1; } if (leftAlbum == rightAlbum) { return 0; } if (d->sorter.sortRole == ItemSortSettings::SortByCreationDate || d->sorter.sortRole == ItemSortSettings::SortByModificationDate) { // Here we want to sort the _categories_ by _album_ date if images are sorted by date // We must still make sure that categorization is unique! QDate leftDate = leftAlbum->date(); QDate rightDate = rightAlbum->date(); if (leftDate != rightDate) { return ItemSortSettings::compareByOrder(leftDate > rightDate ? 1 : -1, - d->sorter.currentCategorizationSortOrder); + d->sorter.currentCategorizationSortOrder); } } return ItemSortSettings::naturalCompare(leftAlbum->albumPath(), rightAlbum->albumPath(), - d->sorter.currentCategorizationSortOrder, - d->sorter.categorizationCaseSensitivity, - d->sorter.strTypeNatural, true); + d->sorter.currentCategorizationSortOrder, + d->sorter.categorizationCaseSensitivity, + d->sorter.strTypeNatural); } default: { return ItemFilterModel::compareInfosCategories(left, right); } } } void ItemAlbumFilterModel::albumChange(Album* album) { Q_D(const ItemAlbumFilterModel); if (album->type() == Album::PHYSICAL) { d->delayedAlbumNamesTimer->start(); } else if (album->type() == Album::TAG) { d->delayedTagNamesTimer->start(); } } void ItemAlbumFilterModel::slotAlbumRenamed(Album* album) { albumChange(album); } void ItemAlbumFilterModel::slotAlbumAdded(Album* album) { albumChange(album); } void ItemAlbumFilterModel::slotAlbumAboutToBeDeleted(Album* album) { albumChange(album); } void ItemAlbumFilterModel::slotAlbumsCleared() { Q_D(ItemAlbumFilterModel); d->albumNamesHash.clear(); d->tagNamesHash.clear(); } void ItemAlbumFilterModel::slotDelayedAlbumNamesTimer() { Q_D(ItemAlbumFilterModel); d->albumNamesHash = AlbumManager::instance()->albumTitles(); if (d->filter.isFilteringByText()) { setItemFilterSettings(d->filter); } } void ItemAlbumFilterModel::slotDelayedTagNamesTimer() { Q_D(ItemAlbumFilterModel); d->tagNamesHash = AlbumManager::instance()->tagNames(); if (d->filter.isFilteringByText() || d->filter.isFilteringByTags()) { setItemFilterSettings(d->filter); } } } // namespace Digikam diff --git a/core/utilities/import/models/camitemsortsettings.cpp b/core/utilities/import/models/camitemsortsettings.cpp index 057115f7c4..6741e7774c 100644 --- a/core/utilities/import/models/camitemsortsettings.cpp +++ b/core/utilities/import/models/camitemsortsettings.cpp @@ -1,299 +1,299 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2012-23-06 * Description : Sort settings for camera item infos * * Copyright (C) 2012 by Islam Wazery * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "camitemsortsettings.h" // Qt includes #include namespace Digikam { CamItemSortSettings::CamItemSortSettings() { categorizationMode = NoCategories; categorizationSortOrder = DefaultOrder; categorizationCaseSensitivity = Qt::CaseSensitive; sortRole = SortByFileName; sortOrder = DefaultOrder; strTypeNatural = true; sortCaseSensitivity = Qt::CaseSensitive; currentCategorizationSortOrder = Qt::AscendingOrder; currentSortOrder = Qt::AscendingOrder; } CamItemSortSettings::~CamItemSortSettings() { } bool CamItemSortSettings::operator ==(const CamItemSortSettings& other) const { return (categorizationMode == other.categorizationMode && categorizationSortOrder == other.categorizationSortOrder && categorizationCaseSensitivity == other.categorizationCaseSensitivity && sortRole == other.sortRole && sortOrder == other.sortOrder && sortCaseSensitivity == other.sortCaseSensitivity); } void CamItemSortSettings::setCategorizationMode(CategorizationMode mode) { categorizationMode = mode; if (categorizationSortOrder == DefaultOrder) { currentCategorizationSortOrder = defaultSortOrderForCategorizationMode(categorizationMode); } } void CamItemSortSettings::setCategorizationSortOrder(SortOrder order) { categorizationSortOrder = order; if (categorizationSortOrder == DefaultOrder) { currentCategorizationSortOrder = defaultSortOrderForCategorizationMode(categorizationMode); } else { currentCategorizationSortOrder = (Qt::SortOrder)categorizationSortOrder; } } void CamItemSortSettings::setSortRole(SortRole role) { sortRole = role; if (sortOrder == DefaultOrder) { currentSortOrder = defaultSortOrderForSortRole(sortRole); } } void CamItemSortSettings::setSortOrder(SortOrder order) { sortOrder = order; if (sortOrder == DefaultOrder) { currentSortOrder = defaultSortOrderForSortRole(sortRole); } else { currentSortOrder = (Qt::SortOrder)order; } } void CamItemSortSettings::setStringTypeNatural(bool natural) { strTypeNatural = natural; } Qt::SortOrder CamItemSortSettings::defaultSortOrderForCategorizationMode(CategorizationMode mode) { switch (mode) { case NoCategories: case CategoryByFolder: case CategoryByFormat: case CategoryByDate: default: return Qt::AscendingOrder; } } Qt::SortOrder CamItemSortSettings::defaultSortOrderForSortRole(SortRole role) { switch (role) { case SortByFileName: case SortByFilePath: return Qt::AscendingOrder; case SortByFileSize: return Qt::DescendingOrder; case SortByCreationDate: return Qt::AscendingOrder; case SortByDownloadState: return Qt::AscendingOrder; case SortByRating: return Qt::DescendingOrder; default: return Qt::AscendingOrder; } } int CamItemSortSettings::compareCategories(const CamItemInfo& left, const CamItemInfo& right) const { switch (categorizationMode) { case NoCategories: case CategoryByFolder: return naturalCompare(left.folder, right.folder, currentCategorizationSortOrder, categorizationCaseSensitivity, strTypeNatural); case CategoryByFormat: return naturalCompare(left.mime, right.mime, currentCategorizationSortOrder, categorizationCaseSensitivity, strTypeNatural); case CategoryByDate: return compareByOrder(left.ctime.date(), right.ctime.date(), currentCategorizationSortOrder); default: return 0; } } bool CamItemSortSettings::lessThan(const CamItemInfo& left, const CamItemInfo& right) const { int result = compare(left, right, sortRole); if (result != 0) { return result < 0; } if (left == right) { return false; } if ((result = compare(left, right, SortByFileName)) != 0) { return result < 0; } if ((result = compare(left, right, SortByCreationDate)) != 0) { return result < 0; } if ( (result = compare(left, right, SortByFilePath)) != 0) { return result < 0; } if ( (result = compare(left, right, SortByFileSize)) != 0) { return result < 0; } if ( (result = compare(left, right, SortByRating)) != 0) { return result < 0; } if ( (result = compare(left, right, SortByDownloadState)) != 0) { return result < 0; } return false; } int CamItemSortSettings::compare(const CamItemInfo& left, const CamItemInfo& right) const { return compare(left, right, sortRole); } int CamItemSortSettings::compare(const CamItemInfo& left, const CamItemInfo& right, SortRole role) const { switch (role) { case SortByFileName: { - bool versioning = (left.name.contains(QLatin1String("_v"), Qt::CaseInsensitive) || - right.name.contains(QLatin1String("_v"), Qt::CaseInsensitive)); - return naturalCompare(left.name, right.name, currentSortOrder, sortCaseSensitivity, strTypeNatural, versioning); + return naturalCompare(left.name, right.name, + currentSortOrder, sortCaseSensitivity, strTypeNatural); } case SortByFilePath: - return naturalCompare(left.url().toLocalFile(), right.url().toLocalFile(), currentSortOrder, sortCaseSensitivity, strTypeNatural); + return naturalCompare(left.url().toLocalFile(), right.url().toLocalFile(), + currentSortOrder, sortCaseSensitivity, strTypeNatural); case SortByFileSize: return compareByOrder(left.size, right.size, currentSortOrder); //FIXME: Change it to creation date instead of modification date. case SortByCreationDate: return compareByOrder(left.ctime, right.ctime, currentSortOrder); case SortByRating: return compareByOrder(left.rating, right.rating, currentSortOrder); case SortByDownloadState: return compareByOrder(left.downloaded, right.downloaded, currentSortOrder); default: return 1; } } bool CamItemSortSettings::lessThan(const QVariant& left, const QVariant& right) const { if (left.type() != right.type()) { return false; } switch (left.type()) { case QVariant::Int: return compareByOrder(left.toInt(), right.toInt(), currentSortOrder); case QVariant::UInt: return compareByOrder(left.toUInt(), right.toUInt(), currentSortOrder); case QVariant::LongLong: return compareByOrder(left.toLongLong(), right.toLongLong(), currentSortOrder); case QVariant::ULongLong: return compareByOrder(left.toULongLong(), right.toULongLong(), currentSortOrder); case QVariant::Double: return compareByOrder(left.toDouble(), right.toDouble(), currentSortOrder); case QVariant::Date: return compareByOrder(left.toDate(), right.toDate(), currentSortOrder); case QVariant::DateTime: return compareByOrder(left.toDateTime(), right.toDateTime(), currentSortOrder); case QVariant::Time: return compareByOrder(left.toTime(), right.toTime(), currentSortOrder); case QVariant::Rect: case QVariant::RectF: { QRectF rectLeft = left.toRectF(); QRectF rectRight = right.toRectF(); int result; if ((result = compareByOrder(rectLeft.top(), rectRight.top(), currentSortOrder)) != 0) { return result < 0; } if ((result = compareByOrder(rectLeft.left(), rectRight.left(), currentSortOrder)) != 0) { return result < 0; } QSizeF sizeLeft = rectLeft.size(); QSizeF sizeRight = rectRight.size(); if ((result = compareByOrder(sizeLeft.width()*sizeLeft.height(), sizeRight.width()*sizeRight.height(), currentSortOrder)) != 0) { return result < 0; } #if __GNUC__ >= 7 // krazy:exclude=cpp [[fallthrough]]; #endif } default: return naturalCompare(left.toString(), right.toString(), currentSortOrder, sortCaseSensitivity, strTypeNatural); } } } // namespace Digikam diff --git a/core/utilities/import/models/camitemsortsettings.h b/core/utilities/import/models/camitemsortsettings.h index 2db09bfc05..65994c801c 100644 --- a/core/utilities/import/models/camitemsortsettings.h +++ b/core/utilities/import/models/camitemsortsettings.h @@ -1,187 +1,206 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2012-23-06 * Description : Sort settings for camera item infos * * Copyright (C) 2012 by Islam Wazery * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_CAMITEM_SORT_SETTINGS_H #define DIGIKAM_CAMITEM_SORT_SETTINGS_H // Qt includes #include // Local includes #include "camiteminfo.h" namespace Digikam { class CamItemSortSettings { public: CamItemSortSettings(); ~CamItemSortSettings(); bool operator==(const CamItemSortSettings& other) const; /** Compares the categories of left and right camItemInfos. * It returns -1 if the left camItemInfo is less than right, and 0 if both fall * in the same category, and 1 if the left camItemInfo is greater than right. * Adheres to set categorization mode and current category sort order. */ int compareCategories(const CamItemInfo& left, const CamItemInfo& right) const; /** Returns true if left is less than right. * Adheres to current sort role and sort order. */ bool lessThan(const CamItemInfo& left, const CamItemInfo& right) const; /** Returns true if left QVariant is less than right. * Adheres to current sort role and sort order. */ bool lessThan(const QVariant& left, const QVariant& right) const; /** Compares the camItemInfos left and right. * Return -1 if left is less than right, 1 if left is greater than right, * and 0 if left equals right comparing the current sort role's value. * Adheres to set sort role and sort order. */ int compare(const CamItemInfo& left, const CamItemInfo& right) const; enum SortOrder { AscendingOrder = Qt::AscendingOrder, DescendingOrder = Qt::DescendingOrder, DefaultOrder /// sort order depends on the chosen sort role }; /// --- Categories --------------- enum CategorizationMode { NoCategories, CategoryByFolder, CategoryByFormat, CategoryByDate }; CategorizationMode categorizationMode; SortOrder categorizationSortOrder; void setCategorizationMode(CategorizationMode mode); void setCategorizationSortOrder(SortOrder order); /// Only Ascending or Descending, never be DefaultOrder Qt::SortOrder currentCategorizationSortOrder; Qt::CaseSensitivity categorizationCaseSensitivity; bool isCategorized() const { return categorizationMode >= CategoryByFolder; } /// --- Camera Items Sorting --------------- enum SortRole { SortByFileName, SortByFilePath, SortByCreationDate, SortByFileSize, SortByDownloadState, SortByRating }; SortOrder sortOrder; SortRole sortRole; bool strTypeNatural; void setSortRole(SortRole role); void setSortOrder(SortOrder order); void setStringTypeNatural(bool natural); Qt::SortOrder currentSortOrder; Qt::CaseSensitivity sortCaseSensitivity; int compare(const CamItemInfo& left, const CamItemInfo& right, SortRole sortRole) const; static Qt::SortOrder defaultSortOrderForCategorizationMode(CategorizationMode mode); static Qt::SortOrder defaultSortOrderForSortRole(SortRole role); /** Returns a < b if sortOrder is Ascending, or b < a if order is descending */ template static inline bool lessThanByOrder(const T& a, const T& b, Qt::SortOrder sortOrder) { if (sortOrder == Qt::AscendingOrder) + { return a < b; - else - return b < a; + } + + return b < a; } /** Returns the usual compare result of -1, 0, or 1 for lessThan, equals and greaterThan. */ template static inline int compareValue(const T& a, const T &b) { if (a == b) + { return 0; + } - if (a < b) - return -1; - else + if (a > b) + { return 1; + } + + return -1; } /** Takes a typical result from a compare method (0 is equal, -1 is less than, 1 is greater than) * and applies the given sort order to it. */ static inline int compareByOrder(int compareResult, Qt::SortOrder sortOrder) { if (sortOrder == Qt::AscendingOrder) + { return compareResult; - else - return - compareResult; + } + + return - compareResult; } template static inline int compareByOrder(const T& a, const T& b, Qt::SortOrder sortOrder) { return compareByOrder(compareValue(a, b), sortOrder); } /** Compares the two string by natural comparison and adheres to given sort order */ static inline int naturalCompare(const QString& a, const QString& b, Qt::SortOrder sortOrder, Qt::CaseSensitivity caseSensitive = Qt::CaseSensitive, - bool natural = true, bool versioning = false) + bool natural = true) { QCollator collator; collator.setNumericMode(natural); - collator.setIgnorePunctuation(versioning); + collator.setIgnorePunctuation(false); collator.setCaseSensitivity(caseSensitive); - return (compareByOrder(collator.compare(a, b), sortOrder)); + + if (a.contains(QLatin1String("_v"), Qt::CaseInsensitive)) + { + collator.setIgnorePunctuation(true); + } + + if (sortOrder == Qt::AscendingOrder) + { + return collator.compare(a, b); + } + + return - collator.compare(a, b); } }; } // namespace Digikam #endif // DIGIKAM_CAMITEM_SORT_SETTINGS_H