mirror of
https://gitlab.gnome.org/GNOME/gitg
synced 2024-06-30 23:29:33 +00:00
Compare commits
11 Commits
929b128ac1
...
93cfb99e92
Author | SHA1 | Date | |
---|---|---|---|
|
93cfb99e92 | ||
|
afa7724628 | ||
|
e8186875a8 | ||
|
4aaf3fd368 | ||
|
715f8080e7 | ||
|
673316ebc4 | ||
|
9fc4079e08 | ||
|
5c172cce71 | ||
|
5dc465d8c4 | ||
|
2b3137767b | ||
|
5caf471654 |
41
gitg/compare/gitg-compare-branch-view.vala
Normal file
41
gitg/compare/gitg-compare-branch-view.vala
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* This file is part of gitg
|
||||
*
|
||||
* Copyright (C) 2020 - Mahmoud Ahmed Khalil
|
||||
*
|
||||
* gitg 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* gitg 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with gitg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace GitgCompare
|
||||
{
|
||||
[GtkTemplate (ui = "/org/gnome/gitg/ui/gitg-compare-branch-view.ui")]
|
||||
public class BranchView : Gtk.Paned
|
||||
{
|
||||
[GtkChild]
|
||||
private Gitg.CommitListView d_commit_list_view;
|
||||
|
||||
[GtkChild]
|
||||
private Gitg.DiffView d_diff_view;
|
||||
|
||||
public Gitg.CommitListView commit_list_view
|
||||
{
|
||||
get { return d_commit_list_view; }
|
||||
}
|
||||
|
||||
public Gitg.DiffView diff_view
|
||||
{
|
||||
get { return d_diff_view; }
|
||||
}
|
||||
}
|
||||
}
|
49
gitg/compare/gitg-compare-commits-view.vala
Normal file
49
gitg/compare/gitg-compare-commits-view.vala
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* This file is part of gitg
|
||||
*
|
||||
* Copyright (C) 2020 - Mahmoud Ahmed Khalil
|
||||
*
|
||||
* gitg 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* gitg 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with gitg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace GitgCompare
|
||||
{
|
||||
[GtkTemplate (ui = "/org/gnome/gitg/ui/gitg-compare-commits-view.ui")]
|
||||
public class CommitsView : Gtk.Box
|
||||
{
|
||||
[GtkChild]
|
||||
private Gitg.CommitListView d_source_commit_list_view;
|
||||
|
||||
[GtkChild]
|
||||
private Gitg.CommitListView d_target_commit_list_view;
|
||||
|
||||
[GtkChild]
|
||||
private Gitg.DiffView d_diff_view;
|
||||
|
||||
public Gitg.CommitListView source_commit_list_view
|
||||
{
|
||||
get { return d_source_commit_list_view; }
|
||||
}
|
||||
|
||||
public Gitg.CommitListView target_commit_list_view
|
||||
{
|
||||
get { return d_target_commit_list_view; }
|
||||
}
|
||||
|
||||
public Gitg.DiffView diff_view
|
||||
{
|
||||
get { return d_diff_view; }
|
||||
}
|
||||
}
|
||||
}
|
135
gitg/compare/gitg-compare-main-view.vala
Normal file
135
gitg/compare/gitg-compare-main-view.vala
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* This file is part of gitg
|
||||
*
|
||||
* Copyright (C) 2020 - Mahmoud Ahmed Khalil
|
||||
*
|
||||
* gitg 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* gitg 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with gitg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace GitgCompare
|
||||
{
|
||||
[GtkTemplate (ui = "/org/gnome/gitg/ui/gitg-compare-main-view.ui")]
|
||||
public class MainView : Gtk.Grid
|
||||
{
|
||||
[GtkChild]
|
||||
private Gtk.MenuButton d_first_branch;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.Label d_first_branch_label;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.MenuButton d_second_branch;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.Label d_second_branch_label;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.Button d_compare_branches;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.Button d_compare_commits;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.Label d_indicator_label;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.Label d_compare_label;
|
||||
|
||||
private Gitg.BranchesPopover d_first_branch_popover;
|
||||
private Gitg.BranchesPopover d_second_branch_popover;
|
||||
|
||||
public Gtk.MenuButton first_branch
|
||||
{
|
||||
get
|
||||
{
|
||||
return d_first_branch;
|
||||
}
|
||||
}
|
||||
|
||||
public Gtk.MenuButton second_branch
|
||||
{
|
||||
get
|
||||
{
|
||||
return d_second_branch;
|
||||
}
|
||||
}
|
||||
|
||||
public Gtk.Label first_branch_label
|
||||
{
|
||||
get
|
||||
{
|
||||
return d_first_branch_label;
|
||||
}
|
||||
}
|
||||
|
||||
public Gtk.Label second_branch_label
|
||||
{
|
||||
get
|
||||
{
|
||||
return d_second_branch_label;
|
||||
}
|
||||
}
|
||||
|
||||
public Gtk.Button compare_branches
|
||||
{
|
||||
get { return d_compare_branches; }
|
||||
}
|
||||
|
||||
public Gtk.Button compare_commits
|
||||
{
|
||||
get { return d_compare_commits; }
|
||||
}
|
||||
|
||||
public Gitg.BranchesPopover first_branch_popover
|
||||
{
|
||||
get
|
||||
{
|
||||
return d_first_branch_popover;
|
||||
}
|
||||
}
|
||||
|
||||
public Gitg.BranchesPopover second_branch_popover
|
||||
{
|
||||
get
|
||||
{
|
||||
return d_second_branch_popover;
|
||||
}
|
||||
}
|
||||
|
||||
public Gtk.Label indicator_label
|
||||
{
|
||||
get
|
||||
{
|
||||
return d_indicator_label;
|
||||
}
|
||||
}
|
||||
|
||||
public Gtk.Label compare_label
|
||||
{
|
||||
get
|
||||
{
|
||||
return d_compare_label;
|
||||
}
|
||||
}
|
||||
|
||||
construct
|
||||
{
|
||||
d_first_branch_popover = new Gitg.BranchesPopover();
|
||||
d_second_branch_popover = new Gitg.BranchesPopover();
|
||||
|
||||
d_first_branch.popover = d_first_branch_popover;
|
||||
d_second_branch.popover = d_second_branch_popover;
|
||||
}
|
||||
}
|
||||
}
|
49
gitg/compare/gitg-compare-stack.vala
Normal file
49
gitg/compare/gitg-compare-stack.vala
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* This file is part of gitg
|
||||
*
|
||||
* Copyright (C) 2020 - Mahmoud Ahmed Khalil
|
||||
*
|
||||
* gitg 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* gitg 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with gitg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace GitgCompare
|
||||
{
|
||||
[GtkTemplate (ui = "/org/gnome/gitg/ui/gitg-compare-stack.ui")]
|
||||
public class Stack : Gtk.Stack
|
||||
{
|
||||
[GtkChild]
|
||||
private MainView d_main_view;
|
||||
|
||||
[GtkChild]
|
||||
private BranchView d_branch_view;
|
||||
|
||||
[GtkChild]
|
||||
private CommitsView d_commits_view;
|
||||
|
||||
public MainView main_view
|
||||
{
|
||||
get { return d_main_view; }
|
||||
}
|
||||
|
||||
public BranchView branch_view
|
||||
{
|
||||
get { return d_branch_view; }
|
||||
}
|
||||
|
||||
public CommitsView commits_view
|
||||
{
|
||||
get { return d_commits_view; }
|
||||
}
|
||||
}
|
||||
}
|
753
gitg/compare/gitg-compare.vala
Normal file
753
gitg/compare/gitg-compare.vala
Normal file
|
@ -0,0 +1,753 @@
|
|||
/*
|
||||
* This file is part of gitg
|
||||
*
|
||||
* Copyright (C) 2020 - Mahmoud Ahmed Khalil
|
||||
*
|
||||
* gitg 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* gitg 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with gitg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace GitgCompare
|
||||
{
|
||||
public enum CurrentView
|
||||
{
|
||||
MAIN,
|
||||
BRANCH,
|
||||
COMMIT
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare View, this view can be used to compare any two different branches/commits
|
||||
*/
|
||||
public class Activity : Object, GitgExt.UIElement, GitgExt.Activity
|
||||
{
|
||||
// Do this to pull in config.h before glib.h (for gettext...)
|
||||
private const string version = Gitg.Config.VERSION;
|
||||
|
||||
private int d_current_view;
|
||||
private Stack? d_main;
|
||||
|
||||
private string[] d_mainline;
|
||||
private Gitg.Ref[] d_branches; // used to load current branches(local and upstream)
|
||||
|
||||
private Gitg.Ref d_source_ref;
|
||||
private Gitg.Ref d_target_ref;
|
||||
|
||||
public Gitg.Ref source_ref
|
||||
{
|
||||
get
|
||||
{
|
||||
return d_source_ref;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if(value != null)
|
||||
{
|
||||
d_source_ref = value;
|
||||
|
||||
reload_main_view();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Gitg.Ref target_ref
|
||||
{
|
||||
get
|
||||
{
|
||||
return d_target_ref;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if(value != null)
|
||||
{
|
||||
d_target_ref = value;
|
||||
|
||||
reload_main_view();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Ggit.RevisionWalker? d_walker;
|
||||
private Gitg.CommitModel d_commits_view_source_model;
|
||||
private Gitg.CommitModel d_commits_view_target_model;
|
||||
private Gitg.CommitModel d_branch_view_model;
|
||||
|
||||
private ulong d_externally_changed_id;
|
||||
private ulong d_commits_changed_id;
|
||||
private uint d_walker_update_idle_id;
|
||||
|
||||
private Gitg.WhenMapped d_reload_when_mapped;
|
||||
|
||||
public GitgExt.Application? application { owned get; construct set; }
|
||||
|
||||
public Activity(GitgExt.Application application)
|
||||
{
|
||||
Object(application: application);
|
||||
}
|
||||
|
||||
public int current_view
|
||||
{
|
||||
get { return d_current_view; }
|
||||
|
||||
set
|
||||
{
|
||||
if(value < 3)
|
||||
{
|
||||
d_current_view = value;
|
||||
reload_ui();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
construct
|
||||
{
|
||||
application.bind_property("repository", this,
|
||||
"repository", BindingFlags.DEFAULT);
|
||||
|
||||
d_externally_changed_id = application.repository_changed_externally.connect(repository_changed_externally);
|
||||
d_commits_changed_id = application.repository_commits_changed.connect(repository_commits_changed);
|
||||
|
||||
d_commits_view_source_model = new Gitg.CommitModel(null);
|
||||
d_commits_view_target_model = new Gitg.CommitModel(null);
|
||||
d_branch_view_model = new Gitg.CommitModel(null);
|
||||
|
||||
d_commits_view_source_model.finished.connect(on_commits_view_source_model_finished);
|
||||
d_commits_view_source_model.begin_clear.connect(on_commits_view_source_model_begin_clear);
|
||||
|
||||
d_commits_view_target_model.finished.connect(on_commits_view_target_model_finished);
|
||||
d_commits_view_target_model.begin_clear.connect(on_commits_view_target_model_begin_clear);
|
||||
|
||||
d_branch_view_model.finished.connect(on_branch_view_model_finished);
|
||||
d_branch_view_model.begin_clear.connect(on_branch_view_model_begin_clear);
|
||||
}
|
||||
|
||||
private void update_commits_view_diff()
|
||||
{
|
||||
Gitg.Commit? source_commit = null;
|
||||
Gitg.Commit? target_commit = null;
|
||||
|
||||
d_main.commits_view.diff_view.diff = null;
|
||||
|
||||
d_main.commits_view.source_commit_list_view.get_selection().selected_foreach((model, path, iter) => {
|
||||
source_commit = d_commits_view_source_model.commit_from_iter(iter);
|
||||
});
|
||||
|
||||
d_main.commits_view.target_commit_list_view.get_selection().selected_foreach((model, path, iter) => {
|
||||
target_commit = d_commits_view_target_model.commit_from_iter(iter);
|
||||
});
|
||||
|
||||
if(source_commit != null && target_commit != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
d_main.commits_view.diff_view.diff = new Ggit.Diff.tree_to_tree(application.repository,
|
||||
target_commit.get_tree(),
|
||||
source_commit.get_tree(),
|
||||
null);
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
else if(source_commit != null)
|
||||
{
|
||||
d_main.commits_view.diff_view.diff = source_commit.get_diff(null, 0);
|
||||
}
|
||||
else if(target_commit != null)
|
||||
{
|
||||
d_main.commits_view.diff_view.diff = target_commit.get_diff(null, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void on_commits_view_source_model_begin_clear()
|
||||
{
|
||||
d_main.commits_view.source_commit_list_view.model = null;
|
||||
}
|
||||
|
||||
private void on_commits_view_source_model_finished()
|
||||
{
|
||||
d_main.commits_view.source_commit_list_view.model = d_commits_view_source_model;
|
||||
|
||||
var path = path_for_ref(d_source_ref, d_commits_view_source_model);
|
||||
|
||||
if(path == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
d_main.commits_view.source_commit_list_view.get_selection().select_path(path);
|
||||
|
||||
if(d_source_ref.get_name() == d_target_ref.get_name())
|
||||
{
|
||||
d_main.commits_view.target_commit_list_view.model = null;
|
||||
|
||||
d_commits_view_target_model = d_commits_view_source_model;
|
||||
d_main.commits_view.target_commit_list_view.model = d_commits_view_target_model;
|
||||
}
|
||||
else
|
||||
{
|
||||
update_walker_idle(d_commits_view_target_model, d_target_ref, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void on_commits_view_target_model_begin_clear()
|
||||
{
|
||||
d_main.commits_view.target_commit_list_view.model = null;
|
||||
}
|
||||
|
||||
private void on_commits_view_target_model_finished()
|
||||
{
|
||||
d_main.commits_view.target_commit_list_view.model = d_commits_view_target_model;
|
||||
|
||||
var path = path_for_ref(d_target_ref, d_commits_view_target_model);
|
||||
|
||||
if(path == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
d_main.commits_view.target_commit_list_view.get_selection().select_path(path);
|
||||
}
|
||||
|
||||
private void on_branch_view_selection_changed(Gtk.TreeSelection sel)
|
||||
{
|
||||
if(d_branch_view_model == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// using selected_foreach() to only get the first selected commit (if there is any)
|
||||
sel.selected_foreach((model, path, iter) => {
|
||||
var selected_commit = d_branch_view_model.commit_from_iter(iter);
|
||||
|
||||
if(selected_commit == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
d_main.branch_view.diff_view.diff = selected_commit.get_diff(null, 0);
|
||||
});
|
||||
}
|
||||
|
||||
private void on_branch_view_model_begin_clear()
|
||||
{
|
||||
d_main.branch_view.commit_list_view.model = null;
|
||||
}
|
||||
|
||||
private void on_branch_view_model_finished()
|
||||
{
|
||||
d_main.branch_view.commit_list_view.model = d_branch_view_model;
|
||||
|
||||
var path = path_for_ref(d_source_ref, d_branch_view_model);
|
||||
|
||||
if(path == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
d_main.branch_view.commit_list_view.get_selection().select_path(path);
|
||||
}
|
||||
|
||||
private void repository_changed_externally(GitgExt.ExternalChangeHint hint)
|
||||
{
|
||||
var repository = application.repository;
|
||||
if(repository == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(d_main != null && (hint & GitgExt.ExternalChangeHint.REFS) != 0)
|
||||
{
|
||||
reload_when_mapped();
|
||||
}
|
||||
}
|
||||
|
||||
private void repository_commits_changed()
|
||||
{
|
||||
if (d_main != null)
|
||||
{
|
||||
reload_when_mapped();
|
||||
}
|
||||
}
|
||||
|
||||
private void reload_when_mapped()
|
||||
{
|
||||
if(d_main == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
d_reload_when_mapped = new Gitg.WhenMapped(d_main);
|
||||
|
||||
d_reload_when_mapped.update(() => {
|
||||
reload();
|
||||
}, this);
|
||||
}
|
||||
|
||||
private void reload()
|
||||
{
|
||||
d_reload_when_mapped = null;
|
||||
|
||||
d_source_ref = null;
|
||||
d_target_ref = null;
|
||||
|
||||
var repository = application.repository;
|
||||
if(repository == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(d_walker_update_idle_id != 0)
|
||||
{
|
||||
Source.remove(d_walker_update_idle_id);
|
||||
d_walker_update_idle_id = 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
d_walker = new Ggit.RevisionWalker(repository);
|
||||
}
|
||||
catch(Error err)
|
||||
{
|
||||
stderr.printf("Couldn't load walker: %s\n", err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// mainline is already reloaded, configured, and saved in the history activity
|
||||
// that's why I'm assuming we should only read it here
|
||||
try
|
||||
{
|
||||
d_mainline = repository.get_config().snapshot().get_string("gitg.mainline").split(",");
|
||||
}
|
||||
catch(Error err)
|
||||
{
|
||||
stderr.printf("Could reload mainlin: %s\n", err.message);
|
||||
d_mainline = new string[] {"refs/heads/master"};
|
||||
}
|
||||
|
||||
// reload branches
|
||||
d_branches = new Gitg.Ref[0];
|
||||
|
||||
try
|
||||
{
|
||||
var uniq_id = new Gee.HashSet<Ggit.OId>((Gee.HashDataFunc)Ggit.OId.hash,
|
||||
(Gee.EqualDataFunc)Ggit.OId.equal);
|
||||
|
||||
repository.references_foreach((reference) => {
|
||||
if(reference.is_branch() || reference.is_remote())
|
||||
{
|
||||
try
|
||||
{
|
||||
reference = reference.resolve();
|
||||
var id = reference.get_target();
|
||||
|
||||
if(id != null && uniq_id.add(id))
|
||||
{
|
||||
var r = reference as Gitg.Ref;
|
||||
d_branches += r;
|
||||
|
||||
// setting the source/target refs to master
|
||||
if(source_ref == null && target_ref == null)
|
||||
{
|
||||
d_source_ref = r;
|
||||
d_target_ref = r;
|
||||
debug("source/target are set");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Error err)
|
||||
{
|
||||
stderr.printf("Error while resolving reference: %s\n", err.message);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
catch(Error err)
|
||||
{
|
||||
stderr.printf("Error while looking up references: %s\n", err.message);
|
||||
}
|
||||
|
||||
// resetting all models, we only need to keep track of the models used in the selected view(branch/commits)
|
||||
// so this should be called whenever we change the views or reload the repositories
|
||||
reset_models();
|
||||
|
||||
// reloading ui elements
|
||||
reload_ui();
|
||||
}
|
||||
|
||||
private void reset_models()
|
||||
{
|
||||
d_commits_view_source_model.repository = null;
|
||||
d_commits_view_source_model.walker = null;
|
||||
|
||||
d_commits_view_target_model.repository = null;
|
||||
d_commits_view_target_model.walker = null;
|
||||
|
||||
d_branch_view_model.repository = null;
|
||||
d_branch_view_model.walker = null;
|
||||
}
|
||||
|
||||
private void reload_ui()
|
||||
{
|
||||
if(d_main == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var commits_view = d_main.commits_view;
|
||||
var branch_view = d_main.branch_view;
|
||||
|
||||
commits_view.diff_view.diff = null;
|
||||
commits_view.source_commit_list_view.model = null;
|
||||
commits_view.target_commit_list_view.model = null;
|
||||
|
||||
branch_view.diff_view.diff = null;
|
||||
branch_view.commit_list_view.model = null;
|
||||
|
||||
switch(d_current_view)
|
||||
{
|
||||
case CurrentView.MAIN:
|
||||
d_main.set_visible_child(d_main.main_view);
|
||||
reload_main_view();
|
||||
break;
|
||||
case CurrentView.BRANCH:
|
||||
d_main.set_visible_child(d_main.branch_view);
|
||||
reload_branch_view();
|
||||
break;
|
||||
case CurrentView.COMMIT:
|
||||
reload_commits_view();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void reload_main_view()
|
||||
{
|
||||
if(d_main == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
d_main.main_view.first_branch_popover.set_branches(d_branches);
|
||||
d_main.main_view.second_branch_popover.set_branches(d_branches);
|
||||
|
||||
// if the d_source_ref and d_target_ref are not set, that means that this
|
||||
// is a bare repository and no branches created yet
|
||||
if(d_source_ref == null && d_target_ref == null)
|
||||
{
|
||||
d_main.main_view.first_branch.visible = false;
|
||||
d_main.main_view.second_branch.visible = false;
|
||||
d_main.main_view.compare_branches.visible = false;
|
||||
d_main.main_view.compare_commits.visible = false;
|
||||
d_main.main_view.compare_label.visible = false;
|
||||
|
||||
d_main.main_view.indicator_label.visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_main.main_view.first_branch.visible = true;
|
||||
d_main.main_view.second_branch.visible = true;
|
||||
d_main.main_view.compare_branches.visible = true;
|
||||
d_main.main_view.compare_commits.visible = true;
|
||||
d_main.main_view.compare_label.visible = true;
|
||||
|
||||
d_main.main_view.indicator_label.visible = false;
|
||||
|
||||
d_main.main_view.first_branch_label.label = d_source_ref.parsed_name.shortname;
|
||||
d_main.main_view.second_branch_label.label = d_target_ref.parsed_name.shortname;
|
||||
}
|
||||
}
|
||||
|
||||
private void reload_commits_view()
|
||||
{
|
||||
d_commits_view_source_model.repository = application.repository;
|
||||
d_commits_view_source_model.walker = d_walker;
|
||||
d_commits_view_source_model.limit = 1000;
|
||||
|
||||
d_commits_view_target_model.repository = application.repository;
|
||||
d_commits_view_target_model.walker = d_walker;
|
||||
d_commits_view_target_model.limit = 1000;
|
||||
|
||||
update_walker_idle(d_commits_view_source_model, d_source_ref, null);
|
||||
}
|
||||
|
||||
private void reload_branch_view()
|
||||
{
|
||||
d_branch_view_model.repository = application.repository;
|
||||
d_branch_view_model.walker = d_walker;
|
||||
|
||||
update_walker_idle(d_branch_view_model, d_source_ref, d_target_ref);
|
||||
}
|
||||
|
||||
private void build_ui()
|
||||
{
|
||||
d_main = new Stack();
|
||||
|
||||
d_main.main_view.compare_commits.clicked.connect(on_compare_commits);
|
||||
d_main.main_view.compare_branches.clicked.connect(on_compare_branches);
|
||||
|
||||
d_main.main_view.first_branch_popover.on_selected.connect((reference) => {
|
||||
d_main.main_view.first_branch_label.label = reference.parsed_name.shortname;
|
||||
d_source_ref = reference;
|
||||
});
|
||||
|
||||
d_main.main_view.second_branch_popover.on_selected.connect((reference) => {
|
||||
d_main.main_view.second_branch_label.label = reference.parsed_name.shortname;
|
||||
d_target_ref = reference;
|
||||
});
|
||||
|
||||
d_main.branch_view.commit_list_view.get_selection().set_mode(Gtk.SelectionMode.SINGLE);
|
||||
d_main.branch_view.commit_list_view.get_selection().changed.connect(on_branch_view_selection_changed);
|
||||
|
||||
d_main.commits_view.source_commit_list_view.get_selection().set_mode(Gtk.SelectionMode.SINGLE);
|
||||
d_main.commits_view.source_commit_list_view.get_selection().changed.connect(update_commits_view_diff);
|
||||
d_main.commits_view.target_commit_list_view.get_selection().set_mode(Gtk.SelectionMode.SINGLE);
|
||||
d_main.commits_view.target_commit_list_view.get_selection().changed.connect(update_commits_view_diff);
|
||||
|
||||
application.bind_property("repository", d_main.commits_view.diff_view, "repository", BindingFlags.SYNC_CREATE);
|
||||
application.bind_property("repository", d_main.branch_view.diff_view, "repository", BindingFlags.SYNC_CREATE);
|
||||
|
||||
d_current_view = CurrentView.MAIN;
|
||||
|
||||
reload_main_view();
|
||||
}
|
||||
|
||||
private void on_compare_commits()
|
||||
{
|
||||
reset_models();
|
||||
|
||||
d_current_view = CurrentView.COMMIT;
|
||||
|
||||
reload_commits_view();
|
||||
d_main.set_visible_child(d_main.commits_view);
|
||||
}
|
||||
|
||||
private void on_compare_branches()
|
||||
{
|
||||
reset_models();
|
||||
|
||||
d_current_view = CurrentView.BRANCH;
|
||||
|
||||
reload_branch_view();
|
||||
d_main.set_visible_child(d_main.branch_view);
|
||||
}
|
||||
|
||||
private Gtk.TreePath? path_for_ref(Ggit.Ref r, Gitg.CommitModel model)
|
||||
{
|
||||
Gtk.TreePath? path = null;
|
||||
|
||||
if(model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var selected_commit_oid = id_for_ref(r);
|
||||
|
||||
try
|
||||
{
|
||||
var selected_commit = application.repository.lookup_commit(selected_commit_oid) as Gitg.Commit;
|
||||
var selected_commit_path = model.path_from_commit(selected_commit);
|
||||
path = selected_commit_path;
|
||||
}
|
||||
catch(Error err)
|
||||
{
|
||||
stderr.printf("Error while retrieving path for ref: %s\n", err.message);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
private Ggit.OId? id_for_ref(Ggit.Ref r)
|
||||
{
|
||||
Ggit.OId? id = null;
|
||||
|
||||
try
|
||||
{
|
||||
var resolved = r.resolve();
|
||||
|
||||
if (resolved.is_tag())
|
||||
{
|
||||
var t = application.repository.lookup<Ggit.Tag>(resolved.get_target());
|
||||
|
||||
id = t.get_target_id();
|
||||
}
|
||||
else
|
||||
{
|
||||
id = resolved.get_target();
|
||||
}
|
||||
}
|
||||
catch {}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
private void update_walker(Gitg.CommitModel model, Gitg.Ref src, Gitg.Ref? target)
|
||||
{
|
||||
if(application.repository == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(model == null || src == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var include = new Gee.HashSet<Ggit.OId>((Gee.HashDataFunc)Ggit.OId.hash,
|
||||
(Gee.EqualDataFunc)Ggit.OId.equal);
|
||||
|
||||
var exclude = new Gee.HashSet<Ggit.OId>((Gee.HashDataFunc)Ggit.OId.hash,
|
||||
(Gee.EqualDataFunc)Ggit.OId.equal);
|
||||
|
||||
var perm_uniq = new Gee.HashSet<Ggit.OId>((Gee.HashDataFunc)Ggit.OId.hash,
|
||||
(Gee.EqualDataFunc)Ggit.OId.equal);
|
||||
|
||||
var permanent = new Ggit.OId[0];
|
||||
|
||||
foreach (var ml in d_mainline)
|
||||
{
|
||||
Ggit.OId id;
|
||||
|
||||
try
|
||||
{
|
||||
id = id_for_ref(application.repository.lookup_reference(ml));
|
||||
} catch { continue; }
|
||||
|
||||
if (id != null && perm_uniq.add(id))
|
||||
{
|
||||
permanent += id;
|
||||
}
|
||||
}
|
||||
|
||||
var id = id_for_ref(src);
|
||||
|
||||
if (id != null)
|
||||
{
|
||||
include.add(id);
|
||||
}
|
||||
|
||||
if(target != null)
|
||||
{
|
||||
id = id_for_ref(target);
|
||||
|
||||
if(id != null)
|
||||
{
|
||||
exclude.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
model.set_permanent_lanes(permanent);
|
||||
model.set_include(include.to_array());
|
||||
model.set_exclude(exclude.to_array());
|
||||
model.reload();
|
||||
}
|
||||
|
||||
private void update_walker_idle(Gitg.CommitModel model, Gitg.Ref src, Gitg.Ref? target)
|
||||
{
|
||||
if (application.repository == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (d_walker_update_idle_id == 0)
|
||||
{
|
||||
d_walker_update_idle_id = Idle.add(() => {
|
||||
d_walker_update_idle_id = 0;
|
||||
update_walker(model, src, target);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public Gitg.Repository repository
|
||||
{
|
||||
set
|
||||
{
|
||||
d_current_view = CurrentView.MAIN;
|
||||
reload();
|
||||
}
|
||||
}
|
||||
|
||||
public override void dispose()
|
||||
{
|
||||
if (d_externally_changed_id != 0)
|
||||
{
|
||||
application.disconnect(d_externally_changed_id);
|
||||
d_externally_changed_id = 0;
|
||||
}
|
||||
|
||||
if(d_walker_update_idle_id != 0)
|
||||
{
|
||||
Source.remove(d_walker_update_idle_id);
|
||||
d_walker_update_idle_id = 0;
|
||||
}
|
||||
|
||||
if (d_commits_changed_id != 0)
|
||||
{
|
||||
application.disconnect(d_commits_changed_id);
|
||||
d_commits_changed_id = 0;
|
||||
}
|
||||
|
||||
d_mainline = null;
|
||||
d_branches = null;
|
||||
|
||||
reset_models();
|
||||
|
||||
base.dispose();
|
||||
}
|
||||
|
||||
public string id
|
||||
{
|
||||
owned get { return "/org/gnome/gitg/Activities/Compare"; }
|
||||
}
|
||||
|
||||
public string display_name
|
||||
{
|
||||
owned get { return C_("Activity", "Compare"); }
|
||||
}
|
||||
|
||||
public string description
|
||||
{
|
||||
owned get { return null; }
|
||||
}
|
||||
|
||||
public string? icon
|
||||
{
|
||||
owned get { return null; }
|
||||
}
|
||||
|
||||
public Gtk.Widget? widget
|
||||
{
|
||||
owned get
|
||||
{
|
||||
if (d_main == null)
|
||||
{
|
||||
build_ui();
|
||||
}
|
||||
|
||||
return d_main;
|
||||
}
|
||||
}
|
||||
|
||||
public bool available
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public bool enabled
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
77
gitg/gitg-ref-action-compare.vala
Normal file
77
gitg/gitg-ref-action-compare.vala
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* This file is part of gitg
|
||||
*
|
||||
* Copyright (C) 2020 - Mahmoud Ahmed Khalil
|
||||
*
|
||||
* gitg 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* gitg 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with gitg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Gitg
|
||||
{
|
||||
|
||||
class RefActionCompare : GitgExt.UIElement, GitgExt.Action, GitgExt.RefAction, Object
|
||||
{
|
||||
// Do this to pull in config.h before glib.h (for gettext...)
|
||||
private const string version = Gitg.Config.VERSION;
|
||||
|
||||
public GitgExt.Application? application { owned get; construct set; }
|
||||
public GitgExt.RefActionInterface action_interface { get; construct set; }
|
||||
public Gitg.Ref reference { get; construct set; }
|
||||
|
||||
public RefActionCompare(GitgExt.Application application,
|
||||
GitgExt.RefActionInterface action_interface,
|
||||
Gitg.Ref reference)
|
||||
{
|
||||
Object(application: application,
|
||||
action_interface: action_interface,
|
||||
reference: reference);
|
||||
}
|
||||
|
||||
public string id
|
||||
{
|
||||
owned get { return "/org/gnome/gitg/ref-actions/compare"; }
|
||||
}
|
||||
|
||||
public string display_name
|
||||
{
|
||||
owned get { return _("Compare branches/commits"); }
|
||||
}
|
||||
|
||||
public string description
|
||||
{
|
||||
owned get { return _("Compare the selected branch with other repository branches"); }
|
||||
}
|
||||
|
||||
public bool enabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return reference.is_branch() || reference.is_remote();
|
||||
}
|
||||
}
|
||||
|
||||
public void activate()
|
||||
{
|
||||
var compare_id = "/org/gnome/gitg/Activities/Compare";
|
||||
|
||||
var activity = application.get_activity_by_id(compare_id) as GitgCompare.Activity;
|
||||
activity.source_ref = reference;
|
||||
|
||||
application.set_activity_by_id(compare_id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ex:set ts=4 noet
|
|
@ -180,6 +180,20 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable
|
|||
[GtkCallback]
|
||||
private void dash_button_clicked(Gtk.Button dash)
|
||||
{
|
||||
var elems = d_activities.get_available_elements();
|
||||
|
||||
if(d_activities.current == elems[2])
|
||||
{
|
||||
var compare_activity = d_activities.current as GitgCompare.Activity;
|
||||
|
||||
if(compare_activity.current_view != GitgCompare.CurrentView.MAIN)
|
||||
{
|
||||
compare_activity.current_view = GitgCompare.CurrentView.MAIN;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
repository = null;
|
||||
}
|
||||
|
||||
|
@ -966,7 +980,8 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable
|
|||
|
||||
var builtins = new GitgExt.Activity[] {
|
||||
new GitgHistory.Activity(this),
|
||||
new GitgCommit.Activity(this)
|
||||
new GitgCommit.Activity(this),
|
||||
new GitgCompare.Activity(this)
|
||||
};
|
||||
|
||||
var extset = new Peas.ExtensionSet(engine,
|
||||
|
|
|
@ -884,6 +884,7 @@ namespace GitgHistory
|
|||
add_ref_action(actions, new Gitg.RefActionRename(application, af, reference));
|
||||
add_ref_action(actions, new Gitg.RefActionDelete(application, af, reference));
|
||||
add_ref_action(actions, new Gitg.RefActionCopyName(application, af, reference));
|
||||
add_ref_action(actions, new Gitg.RefActionCompare(application, af, reference));
|
||||
|
||||
var fetch = new Gitg.RefActionFetch(application, af, reference);
|
||||
|
||||
|
|
|
@ -13,6 +13,11 @@ sources = gitg_sources + files(
|
|||
'commit/gitg-commit-submodule-history-view.vala',
|
||||
'commit/gitg-commit-submodule-info.vala',
|
||||
'commit/gitg-commit.vala',
|
||||
'compare/gitg-compare.vala',
|
||||
'compare/gitg-compare-branch-view.vala',
|
||||
'compare/gitg-compare-commits-view.vala',
|
||||
'compare/gitg-compare-main-view.vala',
|
||||
'compare/gitg-compare-stack.vala',
|
||||
'history/gitg-history-action-interface.vala',
|
||||
'history/gitg-history-command-line.vala',
|
||||
'history/gitg-history-paned.vala',
|
||||
|
@ -43,6 +48,7 @@ sources = gitg_sources + files(
|
|||
'gitg-popup-menu.vala',
|
||||
'gitg-recursive-monitor.vala',
|
||||
'gitg-recursive-scanner.vala',
|
||||
'gitg-ref-action-compare.vala',
|
||||
'gitg-ref-action-copy-name.vala',
|
||||
'gitg-ref-action-create-branch.vala',
|
||||
'gitg-ref-action-create-patch.vala',
|
||||
|
@ -106,6 +112,10 @@ resource_data = files(
|
|||
'resources/ui/gitg-commit-submodule-diff-view.ui',
|
||||
'resources/ui/gitg-commit-submodule-history-view.ui',
|
||||
'resources/ui/gitg-commit-submodule-info.ui',
|
||||
'resources/ui/gitg-compare-branch-view.ui',
|
||||
'resources/ui/gitg-compare-commits-view.ui',
|
||||
'resources/ui/gitg-compare-main-view.ui',
|
||||
'resources/ui/gitg-compare-stack.ui',
|
||||
'resources/ui/gitg-create-branch-dialog.ui',
|
||||
'resources/ui/gitg-create-tag-dialog.ui',
|
||||
'resources/ui/gitg-dash-view.ui',
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-commit-submodule-diff-view.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-commit-submodule-info.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-commit-dialog.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-compare-main-view.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-compare-branch-view.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-compare-commits-view.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-compare-stack.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-create-branch-dialog.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-create-tag-dialog.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-dash-view.ui</file>
|
||||
|
|
79
gitg/resources/ui/gitg-compare-branch-view.ui
Normal file
79
gitg/resources/ui/gitg-compare-branch-view.ui
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 3.3 -->
|
||||
<!-- interface-requires gitg 0.0 -->
|
||||
<!-- interface-requires gd 1.0 -->
|
||||
<template class="GitgCompareBranchView" parent="GtkPaned">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="d_scrolled_window_commit_list">
|
||||
<property name="visible">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="shadow-type">none</property>
|
||||
<child>
|
||||
<object class="GitgCommitListView" id="d_commit_list_view">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="has_focus">True</property>
|
||||
<property name="fixed-height-mode">True</property>
|
||||
<property name="headers-visible">False</property>
|
||||
<property name="enable-search">False</property>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="column_commit_list_subject">
|
||||
<property name="title" translatable="yes">Subject</property>
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="resizable">True</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fixed-width">400</property>
|
||||
<child>
|
||||
<object class="GitgCellRendererLanes" id="renderer_commit_list_subject">
|
||||
<property name="ellipsize">end</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="column_commit_list_author_date">
|
||||
<property name="title" translatable="yes">Date</property>
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="resizable">True</property>
|
||||
<property name="fixed-width">150</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="renderer_commit_list_author_date">
|
||||
<property name="ellipsize">end</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">6</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">True</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GitgDiffView" id="d_diff_view">
|
||||
<property name="visible">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="handle_selection">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
114
gitg/resources/ui/gitg-compare-commits-view.ui
Normal file
114
gitg/resources/ui/gitg-compare-commits-view.ui
Normal file
|
@ -0,0 +1,114 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 3.3 -->
|
||||
<!-- interface-requires gitg 0.0 -->
|
||||
<!-- interface-requires gd 1.0 -->
|
||||
<template class="GitgCompareCommitsView" parent="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkPaned">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="d_commit_lists_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="can-focus">True</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<object class="GitgCommitListView" id="d_source_commit_list_view">
|
||||
<property name="can-focus">True</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="fixed-height-mode">True</property>
|
||||
<property name="headers-visible">False</property>
|
||||
<property name="enable-search">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Subject</property>
|
||||
<property name="resizable">True</property>
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fixed-width">400</property>
|
||||
<child>
|
||||
<object class="GitgCellRendererLanes">
|
||||
<property name="ellipsize">none</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<object class="GitgCommitListView" id="d_target_commit_list_view">
|
||||
<property name="can-focus">True</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="fixed-height-mode">True</property>
|
||||
<property name="headers-visible">False</property>
|
||||
<property name="enable-search">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Subject</property>
|
||||
<property name="resizable">True</property>
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fixed-width">400</property>
|
||||
<child>
|
||||
<object class="GitgCellRendererLanes">
|
||||
<property name="ellipsize">none</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">True</property>
|
||||
<property name="shrink">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GitgDiffView" id="d_diff_view">
|
||||
<property name="visible">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="handle_selection">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">True</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
163
gitg/resources/ui/gitg-compare-main-view.ui
Normal file
163
gitg/resources/ui/gitg-compare-main-view.ui
Normal file
|
@ -0,0 +1,163 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 3.3 -->
|
||||
<!-- interface-requires gitg 0.0 -->
|
||||
<!-- interface-requires gd 1.0 -->
|
||||
<template class="GitgCompareMainView" parent="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="row_homogeneous">True</property>
|
||||
<property name="column_homogeneous">True</property>
|
||||
<property name="width_request">450</property>
|
||||
<property name="halign">center</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="pixel_size">256</property>
|
||||
<property name="icon_name">org.gnome.gitg-symbolic</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="d_compare_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Choose two branches to compare</property>
|
||||
<property name="justify">center</property>
|
||||
<attributes>
|
||||
<attribute name="font-desc" value="Cantarell Bold 12"/>
|
||||
<attribute name="weight" value="bold"/>
|
||||
<attribute name="foreground" value="#88888a8a8585"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="d_indicator_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Bare repository, nothing yet to compare</property>
|
||||
<property name="justify">center</property>
|
||||
<attributes>
|
||||
<attribute name="font-desc" value="Cantarell Bold 16"/>
|
||||
<attribute name="weight" value="bold"/>
|
||||
<attribute name="foreground" value="#88888a8a8585"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="d_first_branch">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="d_first_branch_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="max-width-chars">50</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_END</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="icon-name">go-down-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="d_second_branch">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="d_second_branch_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="max-width-chars">50</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_END</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="icon-name">go-down-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="d_compare_branches">
|
||||
<property name="label" translatable="yes">Compare Branches</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="d_compare_commits">
|
||||
<property name="label" translatable="yes">Compare Commits</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
41
gitg/resources/ui/gitg-compare-stack.ui
Normal file
41
gitg/resources/ui/gitg-compare-stack.ui
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 3.3 -->
|
||||
<!-- interface-requires gitg 0.0 -->
|
||||
<!-- interface-requires gd 1.0 -->
|
||||
<template class="GitgCompareStack" parent="GtkStack">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GitgCompareMainView" id="d_main_view">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="receives_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">Compare Main View</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GitgCompareBranchView" id="d_branch_view">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">Compare Branch View</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GitgCompareCommitsView" id="d_commits_view">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">Compare Commits View</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
|
@ -263,6 +263,7 @@
|
|||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="d_search_up_button">
|
||||
<property name="tooltip-text" translatable="yes">Previous result</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<signal name="clicked" handler="search_up_clicked" swapped="no"/>
|
||||
|
@ -278,6 +279,7 @@
|
|||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="d_search_down_button">
|
||||
<property name="tooltip-text" translatable="yes">Next result</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<signal name="clicked" handler="search_down_clicked" swapped="no"/>
|
||||
|
|
194
libgitg/gitg-branches-popover.vala
Normal file
194
libgitg/gitg-branches-popover.vala
Normal file
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* This file is part of gitg
|
||||
*
|
||||
* Copyright (C) 2020 - Mahmoud Ahmed Khalil
|
||||
*
|
||||
* gitg 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* gitg 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with gitg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Gitg
|
||||
{
|
||||
[GtkTemplate (ui = "/org/gnome/gitg/ui/gitg-branches-popover.ui")]
|
||||
public class BranchesPopover : Gtk.Popover
|
||||
{
|
||||
public signal void on_selected(Gitg.Ref r);
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.SearchEntry d_search_entry;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.ListBox d_listbox;
|
||||
|
||||
private Gitg.Ref[] d_branches;
|
||||
private GLib.ListStore d_model;
|
||||
|
||||
public void set_branches(Gitg.Ref[] branches)
|
||||
{
|
||||
if(branches == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
d_branches = branches;
|
||||
purge_model.begin();
|
||||
}
|
||||
|
||||
construct
|
||||
{
|
||||
d_model = new GLib.ListStore(typeof(Gitg.Ref));
|
||||
}
|
||||
|
||||
private async void purge_model()
|
||||
{
|
||||
d_model.remove_all();
|
||||
|
||||
foreach(var branch in d_branches)
|
||||
{
|
||||
d_model.append(branch);
|
||||
}
|
||||
|
||||
d_listbox.bind_model(d_model, (item) => {
|
||||
var branch = item as Gitg.Ref;
|
||||
|
||||
var entry = new ListEntry();
|
||||
entry.reference = branch;
|
||||
|
||||
return entry;
|
||||
});
|
||||
}
|
||||
|
||||
[GtkCallback]
|
||||
private async void on_search_entry_changed()
|
||||
{
|
||||
var text = d_search_entry.get_text ();
|
||||
if (text.length == 0) {
|
||||
yield purge_model ();
|
||||
|
||||
return;
|
||||
} else {
|
||||
d_model.remove_all ();
|
||||
}
|
||||
|
||||
d_listbox.select_row (null);
|
||||
|
||||
var query = canonicalize_for_search (text);
|
||||
var nresults = 6;
|
||||
foreach (var branch in d_branches) {
|
||||
if (nresults == 0)
|
||||
return;
|
||||
|
||||
var name = canonicalize_for_search (branch.parsed_name.shortname);
|
||||
if (query in name) {
|
||||
d_model.append (branch);
|
||||
|
||||
nresults -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[GtkCallback]
|
||||
private void on_listbox_row_activated()
|
||||
{
|
||||
var row = d_listbox.get_selected_row();
|
||||
|
||||
if(row == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var entry = row.get_child() as ListEntry;
|
||||
if(entry == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
on_selected(entry.reference);
|
||||
|
||||
d_listbox.unselect_row(row);
|
||||
this.popdown();
|
||||
}
|
||||
|
||||
private string canonicalize_for_search (string str)
|
||||
{
|
||||
unowned string s;
|
||||
var buf = new unichar[18];
|
||||
var res = new StringBuilder();
|
||||
|
||||
for (s = str; s[0] != 0; s = s.next_char()) {
|
||||
var c = strip_char (s.get_char());
|
||||
if (c != 0) {
|
||||
var size = c.fully_decompose(false, buf);
|
||||
if (size > 0)
|
||||
res.append_unichar(buf[0]);
|
||||
}
|
||||
}
|
||||
return res.str;
|
||||
}
|
||||
|
||||
private unichar strip_char(unichar ch)
|
||||
{
|
||||
switch (ch.type ())
|
||||
{
|
||||
case UnicodeType.CONTROL:
|
||||
case UnicodeType.FORMAT:
|
||||
case UnicodeType.UNASSIGNED:
|
||||
case UnicodeType.NON_SPACING_MARK:
|
||||
case UnicodeType.COMBINING_MARK:
|
||||
case UnicodeType.ENCLOSING_MARK:
|
||||
/* Ignore those */
|
||||
return 0;
|
||||
default:
|
||||
return ch.tolower ();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class ListEntry : Gtk.Box
|
||||
{
|
||||
private Gitg.Ref d_reference;
|
||||
|
||||
public Gitg.Ref reference
|
||||
{
|
||||
get
|
||||
{
|
||||
return d_reference;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if(value != null)
|
||||
{
|
||||
d_reference = value;
|
||||
update_entry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Gtk.Label d_label;
|
||||
|
||||
private void update_entry()
|
||||
{
|
||||
d_label.label = d_reference.parsed_name.shortname;
|
||||
d_label.visible = true;
|
||||
add(d_label);
|
||||
}
|
||||
|
||||
construct
|
||||
{
|
||||
d_label = new Gtk.Label(null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -83,6 +83,17 @@ namespace Gitg
|
|||
|
||||
public uint limit { get; set; }
|
||||
|
||||
public Ggit.RevisionWalker walker
|
||||
{
|
||||
set
|
||||
{
|
||||
if(value != null)
|
||||
{
|
||||
d_walker = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Ggit.SortMode sort_mode
|
||||
{
|
||||
get { return d_sortmode; }
|
||||
|
|
|
@ -57,6 +57,8 @@ public class Gitg.DiffView : Gtk.Grid
|
|||
private uint d_reveal_options_timeout;
|
||||
private uint d_unreveal_options_timeout;
|
||||
|
||||
private uint d_update_diff_id;
|
||||
|
||||
private static Gee.HashSet<string> s_image_mime_types;
|
||||
|
||||
public Ggit.DiffOptions options
|
||||
|
@ -231,6 +233,12 @@ public class Gitg.DiffView : Gtk.Grid
|
|||
d_cancellable.cancel();
|
||||
}
|
||||
|
||||
if(d_update_diff_id != 0)
|
||||
{
|
||||
Source.remove(d_update_diff_id);
|
||||
d_update_diff_id = 0;
|
||||
}
|
||||
|
||||
base.dispose();
|
||||
}
|
||||
|
||||
|
@ -590,7 +598,22 @@ public class Gitg.DiffView : Gtk.Grid
|
|||
|
||||
if (d_diff != null)
|
||||
{
|
||||
update_diff(d_diff, preserve_expanded, d_cancellable);
|
||||
if(d_update_diff_id != 0)
|
||||
{
|
||||
Source.remove(d_update_diff_id);
|
||||
d_update_diff_id = 0;
|
||||
}
|
||||
|
||||
d_update_diff_id = Idle.add(() => {
|
||||
update_diff.begin(d_diff,
|
||||
preserve_expanded,
|
||||
d_cancellable,
|
||||
(obj, res) => {
|
||||
d_update_diff_id = 0;
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -693,7 +716,7 @@ public class Gitg.DiffView : Gtk.Grid
|
|||
return "";
|
||||
}
|
||||
|
||||
private void update_diff(Ggit.Diff diff, bool preserve_expanded, Cancellable? cancellable)
|
||||
private async void update_diff(Ggit.Diff diff, bool preserve_expanded, Cancellable? cancellable)
|
||||
{
|
||||
var nqueries = 0;
|
||||
var finished = false;
|
||||
|
|
|
@ -24,6 +24,7 @@ sources = files(
|
|||
'gitg-avatar-cache.vala',
|
||||
'gitg-branch-base.vala',
|
||||
'gitg-branch.vala',
|
||||
'gitg-branches-popover.vala',
|
||||
'gitg-cell-renderer-lanes.vala',
|
||||
'gitg-color.vala',
|
||||
'gitg-commit-list-view.vala',
|
||||
|
@ -77,6 +78,7 @@ sources = files(
|
|||
|
||||
resource_data = files(
|
||||
'resources/ui/gitg-authentication-dialog.ui',
|
||||
'resources/ui/gitg-branches-popover.ui',
|
||||
'resources/ui/gitg-diff-view-commit-details.ui',
|
||||
'resources/ui/gitg-diff-view-file-renderer-binary.ui',
|
||||
'resources/ui/gitg-diff-view-file-renderer-image.ui',
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<gresources>
|
||||
<gresource prefix="/org/gnome/gitg">
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-repository-list-box-row.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-branches-popover.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-authentication-dialog.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-diff-view.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-diff-view-file.ui</file>
|
||||
|
|
46
libgitg/resources/ui/gitg-branches-popover.ui
Normal file
46
libgitg/resources/ui/gitg-branches-popover.ui
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GitgBranchesPopover" parent="GtkPopover">
|
||||
<property name="modal">True</property>
|
||||
<property name="position">bottom</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="width-request">450</property>
|
||||
<property name="height-request">300</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="border-width">5</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="d_search_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="placeholder-text" translatable="yes">Search for branch...</property>
|
||||
<signal name="search-changed" handler="on_search_entry_changed" />
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="d_scrolled_window">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="d_listbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="selection-mode">single</property>
|
||||
<signal name="row-activated" handler="on_listbox_row_activated"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</template>
|
||||
</interface>
|
||||
|
Loading…
Reference in New Issue
Block a user