File indexing completed on 2025-01-19 05:11:29

0001 /*
0002 SPDX-FileCopyrightText: 2021 Hamed Masafi <hamed.masfi@gmail.com>
0003 
0004 SPDX-License-Identifier: GPL-3.0-or-later
0005 */
0006 
0007 #include "authorsmodel.h"
0008 #include <KLocalizedString>
0009 
0010 namespace Git
0011 {
0012 
0013 AuthorsModel::AuthorsModel(Manager *git, QObject *parent)
0014     : AbstractGitItemsModel{git, parent}
0015 {
0016 }
0017 
0018 int AuthorsModel::rowCount(const QModelIndex &parent) const
0019 {
0020     Q_UNUSED(parent)
0021     return mData.size();
0022 }
0023 
0024 int AuthorsModel::columnCount(const QModelIndex &parent) const
0025 {
0026     Q_UNUSED(parent)
0027     return static_cast<int>(AuthorsModelsRoles::LastColumn);
0028 }
0029 
0030 QVariant AuthorsModel::headerData(int section, Qt::Orientation orientation, int role) const
0031 {
0032     if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
0033         return {};
0034 
0035     switch (section) {
0036     case Name:
0037         return i18n("Name");
0038     case Email:
0039         return i18n("Email");
0040     case Commits:
0041         return i18n("Commits");
0042     case Autheds:
0043         return i18n("Autheds");
0044     case Tags:
0045         return i18n("Tags");
0046     }
0047     return {};
0048 }
0049 
0050 QVariant AuthorsModel::data(const QModelIndex &index, int role) const
0051 {
0052     if (role != Qt::DisplayRole || !index.isValid() || index.row() < 0 || index.row() >= mData.size())
0053         return {};
0054 
0055     switch (index.column()) {
0056     case Name:
0057         return mData.at(index.row())->name;
0058     case Email:
0059         return mData.at(index.row())->email;
0060     case Commits:
0061         return mData.at(index.row())->commits.count;
0062     case Autheds:
0063         return mData.at(index.row())->authoredCommits.count;
0064     case Tags:
0065         return mData.at(index.row())->tags.count;
0066     }
0067 
0068     return {};
0069 }
0070 
0071 Author *AuthorsModel::findOrCreate(const QString &name, const QString &email)
0072 {
0073     QMutexLocker locker(&mDataMutex);
0074 
0075     auto authorIterator = std::find_if(mData.begin(), mData.end(), [&name, &email](Author *a) {
0076         return a->email == email && a->name == name;
0077     });
0078 
0079     if (authorIterator != mData.end())
0080         return *authorIterator;
0081 
0082     auto author = new Author;
0083     author->name = name;
0084     author->email = email;
0085 
0086     authorIterator = std::upper_bound(mData.begin(), mData.end(), qMakePair(name, email), [](const QPair<QString, QString> &data, const Author *a) {
0087         auto c = QString::compare(data.first, a->name, Qt::CaseInsensitive);
0088         if (!c)
0089             return QString::compare(data.second, a->email, Qt::CaseInsensitive) < 0;
0090         return c < 0;
0091     });
0092 
0093     const int idx = authorIterator - mData.begin();
0094     beginInsertRows(QModelIndex(), idx, idx);
0095     mData.insert(authorIterator, author);
0096     endInsertRows();
0097     return author;
0098 }
0099 
0100 Author *AuthorsModel::findOrCreate(const QString &name, const QString &email, const QDateTime &time, AuthorCreateReason reason)
0101 {
0102     QMutexLocker locker(&mDataMutex);
0103 
0104     auto authorIterator = std::find_if(mData.begin(), mData.end(), [&name, &email](Author *a) {
0105         return a->email == email && a->name == name;
0106     });
0107 
0108     if (authorIterator != mData.end()) {
0109         switch (reason) {
0110         case Commit:
0111             (*authorIterator)->commits.increase(time);
0112             break;
0113         case AuthoredCommit:
0114             (*authorIterator)->authoredCommits.increase(time);
0115             break;
0116         case Tag:
0117             (*authorIterator)->tags.increase(time);
0118             break;
0119         }
0120         return *authorIterator;
0121     }
0122 
0123     auto author = new Author;
0124     author->name = name;
0125     author->email = email;
0126 
0127     switch (reason) {
0128     case Commit:
0129         author->commits.begin(time);
0130         break;
0131     case AuthoredCommit:
0132         author->authoredCommits.begin(time);
0133         break;
0134     case Tag:
0135         author->tags.begin(time);
0136         break;
0137     }
0138 
0139     authorIterator = std::upper_bound(mData.begin(), mData.end(), author, [](Author *author, const Author *a) {
0140         auto c = QString::compare(author->name, a->name, Qt::CaseInsensitive);
0141         if (!c)
0142             return QString::compare(author->email, a->email, Qt::CaseInsensitive) < 0;
0143         return c < 0;
0144     });
0145 
0146     int idx = authorIterator - mData.begin();
0147     beginInsertRows(QModelIndex(), idx, idx);
0148     mData.insert(authorIterator, author);
0149     endInsertRows();
0150     return author;
0151 }
0152 
0153 Author *AuthorsModel::findOrCreate(QSharedPointer<Signature> signature, AuthorCreateReason reason)
0154 {
0155     QMutexLocker locker(&mDataMutex);
0156 
0157     auto authorIterator = std::find_if(mData.begin(), mData.end(), [&signature](Author *a) {
0158         return a->email == signature->email() && a->name == signature->name();
0159     });
0160 
0161     if (authorIterator != mData.end()) {
0162         switch (reason) {
0163         case Commit:
0164             (*authorIterator)->commits.increase(signature->time());
0165             break;
0166         case AuthoredCommit:
0167             (*authorIterator)->authoredCommits.increase(signature->time());
0168             break;
0169         case Tag:
0170             (*authorIterator)->tags.increase(signature->time());
0171             break;
0172         }
0173         return *authorIterator;
0174     }
0175 
0176     auto author = new Author;
0177     author->name = signature->name();
0178     author->email = signature->email();
0179 
0180     switch (reason) {
0181     case Commit:
0182         author->commits.begin(signature->time());
0183         break;
0184     case AuthoredCommit:
0185         author->authoredCommits.begin(signature->time());
0186         break;
0187     case Tag:
0188         author->tags.begin(signature->time());
0189         break;
0190     }
0191 
0192     authorIterator = std::upper_bound(mData.begin(), mData.end(), author, [](Author *author, const Author *a) {
0193         auto c = QString::compare(author->name, a->name, Qt::CaseInsensitive);
0194         if (!c)
0195             return QString::compare(author->email, a->email, Qt::CaseInsensitive) < 0;
0196         return c < 0;
0197     });
0198 
0199     int idx = authorIterator - mData.begin();
0200     beginInsertRows(QModelIndex(), idx, idx);
0201     mData.insert(authorIterator, author);
0202     endInsertRows();
0203     return author;
0204 }
0205 
0206 void AuthorsModel::clear()
0207 {
0208     beginResetModel();
0209     qDeleteAll(mData);
0210     mData.clear();
0211     endResetModel();
0212 }
0213 
0214 void AuthorsModel::fill()
0215 {
0216 }
0217 
0218 void DatesRange::begin(const QDateTime &time)
0219 {
0220     count = 1;
0221     first = time;
0222 }
0223 
0224 void DatesRange::increase(const QDateTime &time)
0225 {
0226     last = time;
0227     count++;
0228 }
0229 
0230 } // namespace Git
0231 
0232 #include "moc_authorsmodel.cpp"