Browse Source

Created basic git graph

Alexey Edelev 8 years ago
parent
commit
90a6eaeb7f
9 changed files with 211 additions and 57 deletions
  1. 6 2
      NiceGit.pro
  2. 96 0
      commitgraph.cpp
  3. 29 0
      commitgraph.h
  4. 6 0
      commitviewmodel.cpp
  5. 39 0
      commitviewmodel.h
  6. 9 27
      gitcommit.cpp
  7. 3 1
      gitcommit.h
  8. 10 16
      githandler.cpp
  9. 13 11
      qml/MainView.qml

+ 6 - 2
NiceGit.pro

@@ -15,7 +15,9 @@ SOURCES += \
     gitoid.cpp \
     gitcommit.cpp \
     commitmodel.cpp \
-    universallistmodel.cpp
+    universallistmodel.cpp \
+    commitgraph.cpp \
+    commitviewmodel.cpp
 
 HEADERS += \
     githandler.h \
@@ -27,7 +29,9 @@ HEADERS += \
     gitoid.h \
     gitcommit.h \
     commitmodel.h \
-    universallistmodel.h
+    universallistmodel.h \
+    commitgraph.h \
+    commitviewmodel.h
 
 RESOURCES += \
     resources.qrc

+ 96 - 0
commitgraph.cpp

@@ -0,0 +1,96 @@
+#include "commitgraph.h"
+
+#include <git2/revwalk.h>
+#include <git2/commit.h>
+
+#include <gitcommit.h>
+#include <QDateTime>
+
+CommitGraph::CommitGraph() : QObject()
+{
+    qsrand(QDateTime::currentMSecsSinceEpoch());
+}
+
+void CommitGraph::addHead(const GitOid &oid)
+{
+    int red = qrand()%205 + 50;
+    int green = qrand()%205 + 50;
+    int blue = qrand()%205 + 50;
+
+    m_color = QString::number(red, 16) + QString::number(green, 16) + QString::number(blue, 16);
+    qDebug() << m_color;
+
+    git_revwalk* walk;
+    git_revwalk_new(&walk, oid.repository()->raw());
+
+    git_revwalk_push(walk, oid.raw());
+    git_revwalk_sorting(walk, GIT_SORT_TOPOLOGICAL);
+
+    git_oid newOid;
+    while(git_revwalk_next(&newOid, walk) == 0) {
+        qDebug() << "Next commit parents";
+        GitOid commitOid(&newOid, oid.repository());
+        GitCommit *commit = GitCommit::fromOid(commitOid);
+        findParents(commit);
+    }
+
+
+    git_revwalk_free(walk);
+}
+
+void CommitGraph::findParents(GitCommit* commit)
+{
+    QList<GitOid> reverseList;
+
+    git_commit* commitRaw = commit->raw();
+    while(commitRaw != nullptr)
+    {
+        GitOid parentOid(git_commit_id(commitRaw), commit->repository());
+        commit = GitCommit::fromOid(parentOid);
+        reverseList.push_front(parentOid);
+        qDebug() << "Add commit to reverselist" << parentOid.toString();
+        commitRaw = nullptr;
+        git_commit_parent(&commitRaw, commit->raw(), 0);
+    }
+
+    if(reverseList.isEmpty()) {
+        return;
+    }
+    addCommits(reverseList);
+}
+
+void CommitGraph::addCommits(QList<GitOid>& reversList)
+{
+    GitCommit* parent;
+    GitCommit* commit;
+
+    for(int i = 0; i < (reversList.count() - 1); i++) {
+        parent = m_commits.value(reversList[i], nullptr);
+        if(parent == nullptr) {
+            //Ony in case if i==0
+            parent = GitCommit::fromOid(reversList[i]);
+            m_commits.insert(parent->oid(), parent);
+            parent->m_color = m_color;
+            m_fullList.push_back(parent);
+        }
+
+        commit = m_commits.value(reversList[i+1], nullptr);
+        if(commit == nullptr) {
+            commit = GitCommit::fromOid(reversList[i+1]);
+            commit->m_x = parent->m_childrenCounter++;
+            commit->m_childrenCounter = commit->m_x;
+            m_commits.insert(commit->oid(), commit);
+            commit->m_color = m_color;
+            if(commit->m_x == parent->m_x) { //TODO: Too dirty hack seems will not work with amount of commits more than 1
+                parent->m_color = commit->m_color;
+            }
+
+            int parentPosition = m_fullList.indexOf(parent);
+            if(parentPosition >= 0) {
+                m_fullList.insert(parentPosition + 1, commit);
+            }
+            qDebug() << "New commit: " << commit->sha1() << commit->x() << commit->y();
+            qDebug() << "Parent commit: " << parent->sha1() << parent->x() << parent->y();
+        }
+    }
+}

+ 29 - 0
commitgraph.h

@@ -0,0 +1,29 @@
+#ifndef COMMITGRAPH_H
+#define COMMITGRAPH_H
+
+#include <QObject>
+
+#include <QString>
+#include <QHash>
+#include <gitoid.h>
+
+class GitCommit;
+
+class CommitGraph : public QObject
+{
+public:
+    CommitGraph();
+    void addHead(const GitOid& oid);
+
+    QHash<GitOid, GitCommit*> m_commits;
+    QList<GitCommit*> m_fullList;
+
+private:
+    void findParents(GitCommit *commit);
+
+    void addCommits(QList<GitOid> &reversList);
+
+    QString m_color;
+};
+
+#endif // COMMITGRAPH_H

+ 6 - 0
commitviewmodel.cpp

@@ -0,0 +1,6 @@
+#include "commitviewmodel.h"
+
+CommitViewModel::CommitViewModel(CommitGraph *graph)
+{
+
+}

+ 39 - 0
commitviewmodel.h

@@ -0,0 +1,39 @@
+#ifndef COMMITVIEWMODEL_H
+#define COMMITVIEWMODEL_H
+
+#include <QObject>
+
+class CommitGraph;
+
+class CommitViewModel : public QObject
+{
+    Q_OBJECT
+    Q_PROPERTY(int x READ x CONSTANT)
+    Q_PROPERTY(int y READ y CONSTANT)
+    Q_PROPERTY(QString color READ color CONSTANT)
+
+public:
+    CommitViewModel(CommitGraph* graph);
+
+    int x() const
+    {
+        return m_x;
+    }
+
+    int y() const
+    {
+        return m_y;
+    }
+
+    QString color() const
+    {
+        return m_color;
+    }
+
+private:
+    int m_x;
+    int m_y;
+    QString m_color;
+};
+
+#endif // COMMITVIEWMODEL_H

+ 9 - 27
gitcommit.cpp

@@ -6,8 +6,6 @@
 
 #include <git2/commit.h>
 
-QHash<GitOid, GitCommit*> GitCommit::m_commitPool;
-
 GitCommit::GitCommit(git_commit* raw, GitRepository* parent) : GitBase(raw, parent)
   ,m_x(0)
   ,m_y(0)
@@ -22,32 +20,16 @@ GitCommit::GitCommit() : GitBase(nullptr, nullptr)
 
 GitCommit* GitCommit::fromOid(const GitOid& oid)
 {
-    if(!m_commitPool.contains(oid)) {
-        if(!oid.isValid()) {
-            return nullptr;
-        }
-
-        git_commit *commit;
-        if(git_commit_lookup(&commit, oid.repository()->raw(), oid.raw()) != 0) {
-            return nullptr;
-        }
-        m_commitPool.insert(oid, new GitCommit(commit, oid.repository()));
-        qDebug() << "Uniq commit:" << QByteArray((const char*)(oid.raw()->id),GIT_OID_RAWSZ).toHex();
-
-        git_commit* parent = nullptr;
-        git_commit_parent(&parent, commit, 0);
-        if(parent != nullptr)
-        {
-            GitOid parentOid(git_commit_id(parent),oid.repository());
-            GitCommit* parentCommit = fromOid(parentOid);
-            m_commitPool[oid]->m_x = parentCommit->m_childrenCounter++;
-            m_commitPool[oid]->m_y = parentCommit->m_y + 1;
-            m_commitPool[oid]->m_childrenCounter = m_commitPool[oid]->m_x;
-        }
-    } else {
-//        qDebug() << "Return duplicate that in pool" << QByteArray((const char*)(oid.raw()->id),GIT_OID_RAWSZ).toHex();
+    if(!oid.isValid()) {
+        return nullptr;
+    }
+
+    git_commit *commit;
+    if(git_commit_lookup(&commit, oid.repository()->raw(), oid.raw()) != 0) {
+        return nullptr;
     }
-    return m_commitPool.value(oid, nullptr);
+
+    return new GitCommit(commit, oid.repository());
 }
 
 GitCommit::~GitCommit()

+ 3 - 1
gitcommit.h

@@ -20,6 +20,7 @@ class GitCommit : public GitBase<git_commit>
     Q_PROPERTY(bool isMerge READ isMerge NOTIFY commitChanged)
     Q_PROPERTY(int x READ x NOTIFY commitChanged)
     Q_PROPERTY(int y READ y NOTIFY commitChanged)
+    Q_PROPERTY(QString color READ color)
 
 public:
     GitCommit(git_commit* raw, GitRepository* parent);
@@ -36,6 +37,7 @@ public:
     bool isMerge() const;
     int x() const { return m_x; }
     int y() const { return m_y; }
+    QString color() const { return m_color; }
 
 public slots:
     void setAuthor(QString author);
@@ -55,10 +57,10 @@ private:
     QString m_email;
 
 public:
-    static QHash<GitOid, GitCommit*> m_commitPool;
     int m_x;
     int m_y;
     int m_childrenCounter;
+    QString m_color;
 };
 
 #endif // GITCOMMIT_H

+ 10 - 16
githandler.cpp

@@ -9,6 +9,8 @@
 #include <commitmodel.h>
 #include <git2.h>
 
+#include <commitgraph.h>
+
 GitHandler::GitHandler() : QObject()
   ,m_repositories(new RepositoryModel(this))
 {
@@ -43,28 +45,20 @@ void GitHandler::open(const QString &path)
 
     BranchContainer &branches = repo->branches();
 
-    QMap<GitOid, GitBranch*> branchesSorted;
-    CommitModel* model = nullptr;
-//    CommitModel* model = CommitModel::fromBranch(branches.value("master"));
-//    m_commits.insert(model->head(), model);
+    CommitGraph* graph = new CommitGraph();
+    graph->addHead(branches.value("master").data()->oid());
     foreach(GitBranch* branch, branches) {
-        branchesSorted.insert(branch->oid(), branch);
-//        if(m_commits.contains(branch->name())) {
-//            continue;
-//        }
-
-//        model = CommitModel::fromBranch(branch);
-//        m_commits.insert(model->head(), model);
+        qDebug() << "Next head " << branch->name();
+        graph->addHead(branch->oid());
     }
 
-    foreach(GitBranch* branch, branchesSorted) {
-        model = CommitModel::fromBranch(branch);
-        m_commits.insert(model->head(), model);
+    foreach (GitCommit* commit, graph->m_fullList) {
+        qDebug() << commit->sha1();
+        commit->m_y = graph->m_fullList.indexOf(commit);
     }
 
-
     CommitModel* main = new CommitModel("main");
-    foreach (GitCommit* commitPtr, GitCommit::m_commitPool) {
+    foreach (GitCommit* commitPtr, graph->m_commits) {
         main->add(commitPtr);
     }
     m_commits.insert("main", main);

+ 13 - 11
qml/MainView.qml

@@ -39,20 +39,22 @@ Item {
             y: model.y*(height+10)
             width: 100
             height: 30
-            color: {
-                var red = ((model.x+10)*5).toString()
-                var green = (128 + (model.x + 10)*5).toString()
-                var blue = (128 + (model.x + 10)*5).toString()
-
-                red = red.length < 2 ? "0" + red : red
-                blue = blue.length < 2 ? "0" + blue : blue
-                green = green.length < 2 ? "0" + green : green
-
-                return "#"+red+green+blue
-            }
+            color: "#"+model.color;
             Text {
+                id: sha1Lable
+                maximumLineCount: 8
                 text: model.shortSha1
             }
+            MouseArea {
+                hoverEnabled: true
+                anchors.fill: parent
+                onEntered: {
+                    parent.state = "full"
+                }
+                onExited: {
+                    parent.state = "short"
+                }
+            }
         }
     }
 }