diff --git a/app/RevisionFile.cpp b/app/RevisionFile.cpp index e8b767ee..c94c3321 100644 --- a/app/RevisionFile.cpp +++ b/app/RevisionFile.cpp @@ -2,7 +2,7 @@ bool RevisionFile::statusCmp(int idx, RevisionFile::StatusFlag sf) const { - return (onlyModified ? MODIFIED : status.at(static_cast(idx))) & sf; + return (mOnlyModified ? MODIFIED : status.at(static_cast(idx))) & sf; } const QString RevisionFile::extendedStatus(int idx) const @@ -21,23 +21,45 @@ void RevisionFile::setStatus(const QString &rowSt) { case 'M': case 'T': + status.append(RevisionFile::MODIFIED); + break; case 'U': status.append(RevisionFile::MODIFIED); + status[status.count() - 1] |= RevisionFile::CONFLICT; + mOnlyModified = false; break; case 'D': status.append(RevisionFile::DELETED); - onlyModified = false; + mOnlyModified = false; break; case 'A': status.append(RevisionFile::NEW); - onlyModified = false; + mOnlyModified = false; break; case '?': status.append(RevisionFile::UNKNOWN); - onlyModified = false; + mOnlyModified = false; break; default: status.append(RevisionFile::MODIFIED); break; } } + +void RevisionFile::setStatus(RevisionFile::StatusFlag flag) +{ + status.append(flag); + + if (flag == RevisionFile::DELETED || flag == RevisionFile::NEW || flag == RevisionFile::UNKNOWN) + mOnlyModified = false; +} + +void RevisionFile::setStatus(int pos, RevisionFile::StatusFlag flag) +{ + status[pos] = flag; +} + +void RevisionFile::appendStatus(int pos, RevisionFile::StatusFlag flag) +{ + status[pos] |= flag; +} diff --git a/app/RevisionFile.h b/app/RevisionFile.h index 9d2018dc..ca917905 100644 --- a/app/RevisionFile.h +++ b/app/RevisionFile.h @@ -5,22 +5,6 @@ class RevisionFile { - friend class Git; - - // Status information is splitted in a flags vector and in a string - // vector in 'status' are stored flags according to the info returned - // by 'git diff-tree' without -C option. - // In case of a working directory file an IN_INDEX flag is or-ed togheter in - // case file is present in git index. - // If file is renamed or copied an entry in 'extStatus' stores the - // value returned by 'git diff-tree -C' plus source and destination - // files info. - // When status of all the files is 'modified' then onlyModified is - // set, this let us to do some optimization in this common case - bool onlyModified = true; - QVector status; - QVector extStatus; - public: enum StatusFlag { @@ -31,7 +15,7 @@ class RevisionFile COPIED = 16, UNKNOWN = 32, IN_INDEX = 64, - ANY = 127 + CONFLICT = 128 }; RevisionFile() = default; @@ -55,4 +39,28 @@ class RevisionFile bool statusCmp(int idx, StatusFlag sf) const; const QString extendedStatus(int idx) const; void setStatus(const QString &rowSt); + void setStatus(RevisionFile::StatusFlag flag); + void setStatus(int pos, RevisionFile::StatusFlag flag); + void appendStatus(int pos, RevisionFile::StatusFlag flag); + int getStatus(int pos) const { return status.at(pos); } + void setOnlyModified(bool onlyModified) { mOnlyModified = onlyModified; } + int getFilesCount() const { return status.size(); } + void appendExtStatus(const QString &file) { extStatus.append(file); } + +private: + // friend class Git; + + // Status information is splitted in a flags vector and in a string + // vector in 'status' are stored flags according to the info returned + // by 'git diff-tree' without -C option. + // In case of a working directory file an IN_INDEX flag is or-ed togheter in + // case file is present in git index. + // If file is renamed or copied an entry in 'extStatus' stores the + // value returned by 'git diff-tree -C' plus source and destination + // files info. + // When status of all the files is 'modified' then onlyModified is + // set, this let us to do some optimization in this common case + bool mOnlyModified = true; + QVector status; + QVector extStatus; }; diff --git a/app/WorkInProgressWidget.cpp b/app/WorkInProgressWidget.cpp index b813cd0b..7fc91f77 100644 --- a/app/WorkInProgressWidget.cpp +++ b/app/WorkInProgressWidget.cpp @@ -154,27 +154,16 @@ void WorkInProgressWidget::insertFilesInList(const RevisionFile &files, QListWid { for (auto i = 0; i < files.count(); ++i) { - QColor myColor; - - const auto isUnknown = files.statusCmp(i, RevisionFile::UNKNOWN); - const auto isInIndex = files.statusCmp(i, RevisionFile::IN_INDEX); - const auto untrackedFile = !isInIndex && isUnknown; - const auto staged = isInIndex && !isUnknown; - const auto isDeleted = files.statusCmp(i, RevisionFile::DELETED); - - if ((files.statusCmp(i, RevisionFile::NEW) || isUnknown || isInIndex) && !untrackedFile && !isDeleted) - myColor = GitQlientStyles::getGreen(); - else if (isDeleted) - myColor = GitQlientStyles::getRed(); - else if (untrackedFile) - myColor = GitQlientStyles::getOrange(); - else - myColor = GitQlientStyles::getTextColor(); - - const auto fileName = mGit->filePath(files, i); + auto fileName = mGit->filePath(files, i); if (!mCurrentFilesCache.contains(fileName)) { + const auto isUnknown = files.statusCmp(i, RevisionFile::UNKNOWN); + const auto isInIndex = files.statusCmp(i, RevisionFile::IN_INDEX); + const auto isConflict = files.statusCmp(i, RevisionFile::CONFLICT); + const auto untrackedFile = !isInIndex && isUnknown; + const auto staged = isInIndex && !isUnknown && !isConflict; + QListWidgetItem *item = nullptr; if (untrackedFile) @@ -193,6 +182,24 @@ void WorkInProgressWidget::insertFilesInList(const RevisionFile &files, QListWid item->setData(Qt::UserRole, QVariant::fromValue(fileList)); } + QColor myColor; + const auto isDeleted = files.statusCmp(i, RevisionFile::DELETED); + + if ((files.statusCmp(i, RevisionFile::NEW) || isUnknown || isInIndex) && !untrackedFile && !isDeleted + && !isConflict) + myColor = GitQlientStyles::getGreen(); + else if (isConflict) + { + myColor = GitQlientStyles::getBlue(); + item->setData(Qt::UserRole + 1, true); + } + else if (isDeleted) + myColor = GitQlientStyles::getRed(); + else if (untrackedFile) + myColor = GitQlientStyles::getOrange(); + else + myColor = GitQlientStyles::getTextColor(); + item->setText(fileName); item->setToolTip(fileName); item->setForeground(myColor); @@ -201,6 +208,9 @@ void WorkInProgressWidget::insertFilesInList(const RevisionFile &files, QListWid item->setFlags(item->flags() & (~Qt::ItemIsSelectable & ~Qt::ItemIsEnabled)); mCurrentFilesCache.insert(fileName, qMakePair(true, item)); + + if (item->data(Qt::UserRole + 1).toBool()) + item->setText(item->text().append(" (conflicts)")); } else mCurrentFilesCache[fileName].first = true; @@ -235,6 +245,9 @@ void WorkInProgressWidget::addAllFilesToCommitList() { auto item = ui->unstagedFilesList->takeItem(i); ui->stagedFilesList->addItem(item); + + if (item->data(Qt::UserRole + 1).toBool()) + item->setText(item->text().remove("(conflicts)").trimmed()); } ui->lUnstagedCount->setText(QString("(%1)").arg(ui->unstagedFilesList->count())); @@ -248,6 +261,10 @@ void WorkInProgressWidget::addFileToCommitList(QListWidgetItem *item) const auto row = fileList->row(item); fileList->takeItem(row); ui->stagedFilesList->addItem(item); + + if (item->data(Qt::UserRole + 1).toBool()) + item->setText(item->text().remove("(conflicts)").trimmed()); + ui->lUntrackedCount->setText(QString("(%1)").arg(ui->untrackedFilesList->count())); ui->lUnstagedCount->setText(QString("(%1)").arg(ui->unstagedFilesList->count())); ui->lStagedCount->setText(QString("(%1)").arg(ui->stagedFilesList->count())); @@ -274,6 +291,9 @@ void WorkInProgressWidget::removeFileFromCommitList(QListWidgetItem *item) const auto itemOriginalList = qvariant_cast(item->data(Qt::UserRole)); const auto row = ui->stagedFilesList->row(item); + if (item->data(Qt::UserRole + 1).toBool()) + item->setText(item->text().append(" (conflicts)")); + ui->stagedFilesList->takeItem(row); itemOriginalList->addItem(item); ui->lUnstagedCount->setText(QString("(%1)").arg(ui->unstagedFilesList->count())); diff --git a/app/git.cpp b/app/git.cpp index e779df52..1fe24c70 100644 --- a/app/git.cpp +++ b/app/git.cpp @@ -882,12 +882,12 @@ RevisionFile Git::fakeWorkDirRevFile(const WorkingDirInfo &wd) FileNamesLoader fl; RevisionFile rf; parseDiffFormat(rf, wd.diffIndex, fl); - rf.onlyModified = false; + rf.setOnlyModified(false); for (auto it : wd.otherFiles) { appendFileName(rf, it, fl); - rf.status.append(RevisionFile::UNKNOWN); + rf.setStatus(RevisionFile::UNKNOWN); rf.mergeParent.append(1); } @@ -896,8 +896,15 @@ RevisionFile Git::fakeWorkDirRevFile(const WorkingDirInfo &wd) flushFileNames(fl); for (auto i = 0; i < rf.count(); i++) + { if (findFileIndex(cachedFiles, filePath(rf, i)) != -1) - rf.status[i] |= RevisionFile::IN_INDEX; + { + if (cachedFiles.statusCmp(i, RevisionFile::CONFLICT)) + rf.appendStatus(i, RevisionFile::CONFLICT); + + rf.appendStatus(i, RevisionFile::IN_INDEX); + } + } return rf; } @@ -1003,20 +1010,18 @@ void Git::setExtStatus(RevisionFile &rf, const QString &rowSt, int parNum, FileN // simulate new file appendFileName(rf, dest, fl); rf.mergeParent.append(parNum); - rf.status.append(RevisionFile::NEW); - rf.extStatus.resize(rf.status.size()); - rf.extStatus[rf.status.size() - 1] = extStatusInfo; + rf.setStatus(RevisionFile::NEW); + rf.appendExtStatus(extStatusInfo); // simulate deleted orig file only in case of rename if (type.at(0) == 'R') { // renamed file appendFileName(rf, orig, fl); rf.mergeParent.append(parNum); - rf.status.append(RevisionFile::DELETED); - rf.extStatus.resize(rf.status.size()); - rf.extStatus[rf.status.size() - 1] = extStatusInfo; + rf.setStatus(RevisionFile::DELETED); + rf.appendExtStatus(extStatusInfo); } - rf.onlyModified = false; + rf.setOnlyModified(false); } // CT TODO utility function; can go elsewhere