Compare commits

...

11 Commits

Author SHA1 Message Date
Mahmoud Khalil
93cfb99e92 Merge branch 'wip/mahmoudkhalil11/adds-compare-activity-to-compare-branches-or-commits' into 'master'
WIP: Creates A New Compare Activity That Handles Comparing Between Two Different Branches/Commits

See merge request GNOME/gitg!156
2024-06-19 14:35:11 +00:00
Sabri Ünal
afa7724628 ui: Add tooltips to search buttons
- Add tooltips to the previous result and next result buttons.
2024-06-19 10:40:33 +00:00
Mahmoud Khalil
e8186875a8 Make updating diff asynchronously and be called on Idle
Before this commit, huge changes will affect the performance of the application
A lot due to fetching the changes and showing them on the screen.

This commit helps in reducing the lag a bit, by moving the updating and buffering
The changes to Idle.
2020-08-30 09:38:44 +02:00
Mahmoud Khalil
4aaf3fd368 Adds Commits View to compare any two commits from any two branches
This adds a new view to the Compare Activity to support comparing any two
non-consecutive commits
2020-08-30 09:38:44 +02:00
Mahmoud Khalil
715f8080e7 Users shouldn't be allowed to interact with the Compare Activity if the current repository is a bare one
This commit restrict user interaction with the activity if this is a bare repository
Users shouldn't be allowed to select anything since there isn't any pushed commits or
any branches found yet
2020-08-30 09:38:44 +02:00
Mahmoud Khalil
673316ebc4 Only reload Compare Activity when it's mapped 2020-08-30 09:38:44 +02:00
Mahmoud Khalil
9fc4079e08 Implements Branch View of the Compare Activity
This commit implements the Branch View which compares the two selected branches
by the user upon his/her request from the main view.

This commit, we implement the walker of the Activity which will be shared across
the different models used in the activity. It also implements reading from the
branch view model and loading the difference of commits between the two branches

We might need to introduce the Diff/Files plugins in the activity later.
2020-08-30 09:38:44 +02:00
Mahmoud Khalil
5c172cce71 Allow setting Model Revision Walker
This allows setting Model Revision Walker which will help in sharing multiple
walkers across different models
2020-08-30 09:38:44 +02:00
Mahmoud Khalil
5dc465d8c4 Use GtkPopover instead of the very long list from GtkComboBoxText
This commit replaces the GtkComboBoxText with GtkPopover, to provide a better
User experience and enable the user to search for a specific branch

Before this commit, I used GtkComboBoxText, which produced a long list of the branches
taking space up to the whole vertical length of the screen.
2020-08-30 09:20:57 +02:00
Mahmoud Khalil
2b3137767b Transitioning to the Compare Activity is only allowed from the History Activity
Before this commit, we used a third button in the stack switcher, which might
Be complicated in terms of user flow.

In this commit, we only allow transitioning to the Compare Activity using an
Entry from a context menu in the History Activity.
2020-08-11 20:23:59 +02:00
Mahmoud Khalil
5caf471654 Creates A New Compare Activity That Handles Comparing Between Two Different Branches/Commits
This commit creates a new compare activity that will contain two different
views for comparing branches, or commits.
2020-07-30 06:03:12 +02:00
21 changed files with 1813 additions and 3 deletions

View 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; }
}
}
}

View 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; }
}
}
}

View 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;
}
}
}

View 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; }
}
}
}

View 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; }
}
}
}

View 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

View File

@ -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,

View File

@ -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);

View File

@ -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',

View File

@ -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>

View 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>

View 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>

View 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>

View 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>

View File

@ -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"/>

View 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);
}
}
}

View File

@ -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; }

View File

@ -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;

View File

@ -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',

View File

@ -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>

View 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>