Browse Source

Created basic git graph

Alexey Edelev 8 years ago
parent
commit
46a07056fd
8 changed files with 202 additions and 68 deletions
  1. 4 1
      commitmodel.cpp
  2. 34 9
      gitcommit.cpp
  3. 13 0
      gitcommit.h
  4. 23 6
      githandler.cpp
  5. 6 2
      gitoid.cpp
  6. 6 0
      gitoid.h
  7. 2 2
      gitrepository.h
  8. 114 48
      qml/MainView.qml

+ 4 - 1
commitmodel.cpp

@@ -10,12 +10,13 @@ CommitModel::CommitModel(const QString &head, QObject* parent) : UniversalListMo
 
 CommitModel* CommitModel::fromBranch(GitBranch* branch)
 {
+    qDebug() << branch->name();
     CommitModel* tmpModel = new CommitModel(branch->name(), branch);
     git_revwalk* walk;
     git_revwalk_new(&walk, branch->repository()->raw());
 
     git_revwalk_push(walk, branch->oid().raw());
-    git_revwalk_sorting(walk, GIT_SORT_TIME);
+    git_revwalk_sorting(walk, GIT_SORT_TOPOLOGICAL);
 
     git_oid newOid;
     while(git_revwalk_next(&newOid, walk) == 0) {
@@ -23,6 +24,8 @@ CommitModel* CommitModel::fromBranch(GitBranch* branch)
         GitCommit *commit = GitCommit::fromOid(commitOid);
         if(commit != nullptr) {
             tmpModel->add(commit);
+        } else {
+            qDebug() << "Commit is null";
         }
     }
 

+ 34 - 9
gitcommit.cpp

@@ -6,8 +6,12 @@
 
 #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)
+  ,m_childrenCounter(0)
 {
     m_oid = GitOid(git_commit_id(m_raw), m_repository);
 }
@@ -18,16 +22,32 @@ GitCommit::GitCommit() : GitBase(nullptr, nullptr)
 
 GitCommit* GitCommit::fromOid(const GitOid& oid)
 {
-    if(!oid.isValid()) {
-        return nullptr;
+    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();
     }
-
-    git_commit *commit;
-    if(git_commit_lookup(&commit, oid.repository()->raw(), oid.raw()) != 0) {
-        return nullptr;
-    }
-
-    return new GitCommit(commit, oid.repository());
+    return m_commitPool.value(oid, nullptr);
 }
 
 GitCommit::~GitCommit()
@@ -65,6 +85,11 @@ QString GitCommit::shortSha1() const
     return oid().toShorten();
 }
 
+bool GitCommit::isMerge() const
+{
+    return git_commit_parentcount(m_raw) > 1;
+}
+
 void GitCommit::setAuthor(QString author)
 {
     Q_UNUSED(author)

+ 13 - 0
gitcommit.h

@@ -17,6 +17,9 @@ class GitCommit : public GitBase<git_commit>
     Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY commitChanged)
     Q_PROPERTY(QString sha1 READ sha1 NOTIFY commitChanged)
     Q_PROPERTY(QString shortSha1 READ shortSha1 NOTIFY commitChanged)
+    Q_PROPERTY(bool isMerge READ isMerge NOTIFY commitChanged)
+    Q_PROPERTY(int x READ x NOTIFY commitChanged)
+    Q_PROPERTY(int y READ y NOTIFY commitChanged)
 
 public:
     GitCommit(git_commit* raw, GitRepository* parent);
@@ -30,6 +33,9 @@ public:
     QString email() const;
     QString sha1() const;
     QString shortSha1() const;
+    bool isMerge() const;
+    int x() const { return m_x; }
+    int y() const { return m_y; }
 
 public slots:
     void setAuthor(QString author);
@@ -42,10 +48,17 @@ signals:
 
 private:
     GitCommit();
+
     QString m_author;
     QDateTime m_time;
     QString m_message;
     QString m_email;
+
+public:
+    static QHash<GitOid, GitCommit*> m_commitPool;
+    int m_x;
+    int m_y;
+    int m_childrenCounter;
 };
 
 #endif // GITCOMMIT_H

+ 23 - 6
githandler.cpp

@@ -43,14 +43,31 @@ void GitHandler::open(const QString &path)
 
     BranchContainer &branches = repo->branches();
 
-//    foreach(GitBranch* branch, branches) {
-//        qDebug() << "Branch: " << branch->name();
-//        CommitModel* model = CommitModel::fromBranch(branch);
+    QMap<GitOid, GitBranch*> branchesSorted;
+    CommitModel* model = nullptr;
+//    CommitModel* model = CommitModel::fromBranch(branches.value("master"));
+//    m_commits.insert(model->head(), model);
+    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);
-//    }
+    }
+
+    foreach(GitBranch* branch, branchesSorted) {
+        model = CommitModel::fromBranch(branch);
+        m_commits.insert(model->head(), model);
+    }
+
 
-    CommitModel* model = CommitModel::fromBranch(branches.value("master"));
-    m_commits.insert(model->head(), model);
+    CommitModel* main = new CommitModel("main");
+    foreach (GitCommit* commitPtr, GitCommit::m_commitPool) {
+        main->add(commitPtr);
+    }
+    m_commits.insert("main", main);
     m_repositories->add(repo);
 }
 

+ 6 - 2
gitoid.cpp

@@ -25,13 +25,17 @@ QString GitOid::toShorten() const
     return m_string.mid(0,9);
 }
 
-
 bool GitOid::operator ==(const GitOid& other) const
 {
-    return git_oid_equal(&m_oid, &(other.m_oid)) == 0
+    return git_oid_equal(&m_oid, &(other.m_oid)) == true
             && m_repository == other.m_repository;
 }
 
+bool GitOid::operator <(const GitOid& other) const
+{
+    return git_oid_cmp(raw(), other.raw()) < 0;
+}
+
 GitOid& GitOid::operator=(const GitOid& other)
 {
     updateOid(&(other.m_oid));

+ 6 - 0
gitoid.h

@@ -4,6 +4,7 @@
 #include <QObject>
 #include <QString>
 #include <git2/oid.h>
+#include <QDebug>
 
 class GitRepository;
 
@@ -16,6 +17,7 @@ public:
 
 
     bool operator ==(const GitOid& other) const;
+    bool operator <(const GitOid& other) const;
     GitOid& operator=(const GitOid& other);
 
     const git_oid* raw() const {
@@ -39,4 +41,8 @@ private:
     GitRepository *m_repository;
 };
 
+inline uint qHash(const GitOid& oid) {
+    return qHash(QByteArray((const char*)(oid.raw()->id), GIT_OID_RAWSZ));
+}
+
 #endif // GITOID_H

+ 2 - 2
gitrepository.h

@@ -3,13 +3,13 @@
 
 #include <QObject>
 #include <QString>
-#include <QHash>
+#include <QMap>
 #include <QPointer>
 
 struct git_repository;
 
 class GitBranch;
-typedef QHash<QString, QPointer<GitBranch>> BranchContainer;
+typedef QMap<QString, QPointer<GitBranch> > BranchContainer;
 
 class GitRepository : public QObject
 {

+ 114 - 48
qml/MainView.qml

@@ -4,6 +4,7 @@ import QtQuick.Dialogs 1.2
 import org.semlanik.nicegit 1.0
 
 Item {
+    id: root
     Row {
         id: selector
         Text {
@@ -26,62 +27,127 @@ Item {
         }
     }
 
+    Item {
+    width:  childrenRect.width
+    height: childrenRect.height
+    anchors.right: parent.right
+    Repeater {
+        model: _handler.modelByHead("main")
+        Rectangle {
+            radius: 10
+            x: model.x*(width+20)
+            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()
 
-    ListView {
-        anchors.top: parent.top
-        anchors.bottom: parent.bottom
-        width: 200
-        anchors.right: parent.right
-        model: _handler.modelByHead("master")
-        delegate: Rectangle {
-            id: idRect
-            width: parent.width
-            height: 80
-            color: "#cccccc"
-            states: [
-                State {
-                    name:"full"
-                    PropertyChanges {
-                        target: sha1Lable
-                        text: model.sha1
-                    }
-                    PropertyChanges {
-                        target: idRect
-                        color: "#dddddd"
-                    }
-                },
-                State {
-                    name:"short"
-                    PropertyChanges {
-                        target: sha1Lable
-                        text: model.shortSha1
-                    }
-                    PropertyChanges {
-                        target: idRect
-                        color: "#cccccc"
-                    }
-                }]
-
-            state: "short"
+                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
+            }
             Text {
-                id: sha1Lable
-                maximumLineCount: 8
                 text: model.shortSha1
             }
-            MouseArea {
-                hoverEnabled: true
-                anchors.fill: parent
-                onEntered: {
-                    parent.state = "full"
-                }
-                onExited: {
-                    parent.state = "short"
-                }
-            }
         }
     }
+}
+//    Row {
+//        anchors.right: parent.right
+//        anchors.top: parent.top
+//        anchors.bottom: parent.bottom
+//        Repeater {
+//            model: ListModel {
+//                ListElement {
+//                    branch: "b3"
+//                }
+//                ListElement {
+//                    branch: "master"
+//                }
+//                ListElement {
+//                    branch: "b1"
+//                }
+//                ListElement {
+//                    branch: "b2"
+//                }
+//                ListElement {
+//                    branch: "b4"
+//                }
+//            }
+
+//            Column {
+//                width: 200
+//                Text {
+//                    id: branchName
+//                    text: "Branch:" + branch
+//                }
+//                ListView {
+//                    id: branchList
+//                    height: root.height
+//                    width: 200
+//                    model: _handler.modelByHead(branch)
+//                    delegate: Rectangle {
+//                        id: idRect
+//                        width: parent.width
+//                        height: 80
+//                        color: "#cccccc"
+//                        states: [
+//                            State {
+//                                name:"full"
+//                                PropertyChanges {
+//                                    target: sha1Lable
+//                                    text: model.sha1
+//                                }
+//                                PropertyChanges {
+//                                    target: idRect
+//                                    color: !model.isMerge ? "#dddddd" : "#aa6666"
+//                                }
+//                            },
+//                            State {
+//                                name:"short"
+//                                PropertyChanges {
+//                                    target: sha1Lable
+//                                    text: model.shortSha1
+//                                }
+//                                PropertyChanges {
+//                                    target: idRect
+//                                    color: "#cccccc"
+//                                }
+//                            }]
+
+//                        state: "short"
 
+//                        Column {
+//                            width: branchList.width
+//                            Text {
+//                                id: sha1Lable
+//                                width: branchList.width
+//                                maximumLineCount: 8
+//                                text: model.shortSha1
+//                            }
+//                            Text {
+//                                text: model.message
+//                            }
+//                        }
+//                        MouseArea {
+//                            hoverEnabled: true
+//                            anchors.fill: parent
+//                            onEntered: {
+//                                parent.state = "full"
+//                            }
+//                            onExited: {
+//                                parent.state = "short"
+//                            }
+//                        }
+//                    }
+//                }
+//            }
+//        }
+//    }
     FileDialog {
         id: repoOpenDialog
         folder: "."