2012-07-10 14:32:48 +00:00
|
|
|
/*
|
|
|
|
* This file is part of gitg
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 - Ignacio Casal Quinteiro
|
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
using Gitg;
|
|
|
|
using Gtk;
|
|
|
|
|
|
|
|
namespace GitgGtk
|
|
|
|
{
|
2012-10-22 07:01:10 +00:00
|
|
|
public class DashView : Grid
|
2012-07-10 14:32:48 +00:00
|
|
|
{
|
2013-03-14 10:48:18 +00:00
|
|
|
private static Gtk.IconSize d_icon_size;
|
2013-03-13 09:26:15 +00:00
|
|
|
private string? d_filter_text;
|
2013-06-22 11:09:05 +00:00
|
|
|
private ListBox d_listbox;
|
|
|
|
|
|
|
|
private class DashRow : ListBoxRow
|
2012-07-10 14:32:48 +00:00
|
|
|
{
|
2013-03-21 19:06:18 +00:00
|
|
|
public Repository? repository;
|
2013-03-13 14:14:14 +00:00
|
|
|
public DateTime time;
|
2013-03-27 14:55:46 +00:00
|
|
|
public ProgressBin bin;
|
2013-03-14 10:48:18 +00:00
|
|
|
public Image image;
|
2013-03-13 09:26:15 +00:00
|
|
|
public Label repository_label;
|
2012-07-10 14:32:48 +00:00
|
|
|
public Label branch_label;
|
2013-03-21 15:51:25 +00:00
|
|
|
public Arrow arrow;
|
2013-03-21 16:32:15 +00:00
|
|
|
public Spinner spinner;
|
2012-07-10 14:32:48 +00:00
|
|
|
}
|
|
|
|
|
2013-03-16 16:45:28 +00:00
|
|
|
public signal void repository_activated(Repository repository);
|
2012-07-10 14:32:48 +00:00
|
|
|
|
|
|
|
construct
|
|
|
|
{
|
2013-03-14 10:48:18 +00:00
|
|
|
d_icon_size = Gtk.icon_size_register ("gitg", 64, 64);
|
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
d_listbox = new ListBox();
|
2012-10-20 13:35:18 +00:00
|
|
|
var context = d_listbox.get_style_context();
|
|
|
|
context.add_class("view");
|
|
|
|
context.add_class("content-view");
|
2013-06-22 11:09:05 +00:00
|
|
|
d_listbox.set_header_func(update_header);
|
2013-03-13 09:26:15 +00:00
|
|
|
d_listbox.set_filter_func(null);
|
2013-03-13 14:14:14 +00:00
|
|
|
d_listbox.set_sort_func(compare_widgets);
|
2012-10-19 08:05:22 +00:00
|
|
|
d_listbox.show();
|
2012-10-03 07:00:20 +00:00
|
|
|
add(d_listbox);
|
|
|
|
|
2013-03-11 07:31:33 +00:00
|
|
|
d_listbox.set_selection_mode (Gtk.SelectionMode.NONE);
|
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
d_listbox.row_activated.connect((listbox, row) => {
|
|
|
|
var r = row as DashRow;
|
2012-10-03 07:00:20 +00:00
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
if (r.repository != null)
|
2012-10-03 07:00:20 +00:00
|
|
|
{
|
2013-06-22 11:09:05 +00:00
|
|
|
repository_activated(r.repository);
|
2012-10-03 07:00:20 +00:00
|
|
|
}
|
|
|
|
});
|
2012-07-10 14:32:48 +00:00
|
|
|
|
2013-03-13 14:38:08 +00:00
|
|
|
add_recent_info();
|
2012-07-10 14:32:48 +00:00
|
|
|
}
|
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
private void update_header(ListBoxRow row, ListBoxRow? before)
|
2012-10-20 13:35:18 +00:00
|
|
|
{
|
2013-06-22 11:09:05 +00:00
|
|
|
row.set_header(before != null ? new Separator(Orientation.HORIZONTAL) : null);
|
2012-10-20 13:35:18 +00:00
|
|
|
}
|
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
private bool filter(ListBoxRow row)
|
2013-03-13 09:26:15 +00:00
|
|
|
{
|
2013-06-22 11:09:05 +00:00
|
|
|
var text = (row as DashRow).repository_label.get_text();
|
2013-03-13 09:26:15 +00:00
|
|
|
return text.contains(d_filter_text);
|
|
|
|
}
|
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
private int compare_widgets(ListBoxRow a, ListBoxRow b)
|
2013-03-13 14:14:14 +00:00
|
|
|
{
|
2013-06-22 11:09:05 +00:00
|
|
|
return - (a as DashRow).time.compare((b as DashRow).time);
|
2013-03-13 14:14:14 +00:00
|
|
|
}
|
|
|
|
|
2013-03-13 14:38:08 +00:00
|
|
|
private void add_recent_info()
|
2012-07-10 14:32:48 +00:00
|
|
|
{
|
2013-03-13 14:38:08 +00:00
|
|
|
var recent_manager = RecentManager.get_default();
|
2013-03-13 15:13:34 +00:00
|
|
|
var reversed_items = recent_manager.get_items();
|
|
|
|
reversed_items.reverse();
|
2012-07-10 14:32:48 +00:00
|
|
|
|
2013-03-13 15:13:34 +00:00
|
|
|
foreach (var item in reversed_items)
|
2012-07-10 14:32:48 +00:00
|
|
|
{
|
2013-03-13 14:38:08 +00:00
|
|
|
if (item.has_group("gitg"))
|
|
|
|
{
|
|
|
|
File info_file = File.new_for_uri(item.get_uri());
|
|
|
|
File repo_file;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
repo_file = Ggit.Repository.discover(info_file);
|
|
|
|
}
|
|
|
|
catch
|
|
|
|
{
|
2013-03-13 14:42:25 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
recent_manager.remove_item(item.get_uri());
|
|
|
|
}
|
|
|
|
catch {}
|
2013-03-13 14:38:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Gitg.Repository repo;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
repo = new Gitg.Repository(repo_file, null);
|
|
|
|
}
|
|
|
|
catch
|
|
|
|
{
|
2013-03-13 14:42:25 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
recent_manager.remove_item(item.get_uri());
|
|
|
|
}
|
|
|
|
catch {}
|
2013-03-13 14:38:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
add_repository(repo);
|
|
|
|
}
|
2012-07-10 14:32:48 +00:00
|
|
|
}
|
2013-03-13 14:14:14 +00:00
|
|
|
}
|
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
private DashRow get_row_for_repository(Gitg.Repository repository)
|
2013-03-13 14:14:14 +00:00
|
|
|
{
|
2013-06-22 11:09:05 +00:00
|
|
|
DashRow? row = null;
|
2013-03-13 14:31:13 +00:00
|
|
|
|
|
|
|
foreach (var child in d_listbox.get_children())
|
2012-07-10 14:32:48 +00:00
|
|
|
{
|
2013-06-22 11:09:05 +00:00
|
|
|
var d = child as DashRow;
|
2013-03-13 15:13:34 +00:00
|
|
|
if (d.repository.get_location().equal(repository.get_location()))
|
2013-03-13 14:31:13 +00:00
|
|
|
{
|
2013-06-22 11:09:05 +00:00
|
|
|
row = d;
|
2013-03-13 14:31:13 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-07-10 14:32:48 +00:00
|
|
|
}
|
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
return row;
|
2013-03-21 15:51:25 +00:00
|
|
|
}
|
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
private DashRow create_repository_row(string name, string branch_name, bool spin, bool local)
|
2013-03-21 19:06:18 +00:00
|
|
|
{
|
2013-06-22 11:09:05 +00:00
|
|
|
var row = new DashRow();
|
|
|
|
row.repository = null;
|
|
|
|
row.time = new DateTime.now_local();
|
|
|
|
row.bin = new ProgressBin();
|
|
|
|
row.add(row.bin);
|
2013-03-27 14:55:46 +00:00
|
|
|
var grid = new Grid();
|
|
|
|
grid.margin = 12;
|
|
|
|
grid.column_spacing = 10;
|
2013-06-22 11:09:05 +00:00
|
|
|
row.bin.add(grid);
|
2013-03-21 19:06:18 +00:00
|
|
|
|
2013-06-15 08:38:48 +00:00
|
|
|
// FIXME: Change folder image for a repository uses github remote.
|
|
|
|
var folder_icon_name = local ? "folder" : "folder-remote";
|
2013-06-22 11:09:05 +00:00
|
|
|
row.image = new Image.from_icon_name(folder_icon_name, d_icon_size);
|
|
|
|
grid.attach(row.image, 0, 0, 1, 2);
|
|
|
|
|
|
|
|
row.repository_label = new Label(null);
|
|
|
|
row.repository_label.set_markup("<b>%s</b>".printf(name));
|
|
|
|
row.repository_label.ellipsize = Pango.EllipsizeMode.END;
|
|
|
|
row.repository_label.halign = Align.START;
|
|
|
|
row.repository_label.valign = Align.END;
|
|
|
|
row.repository_label.hexpand = true;
|
|
|
|
grid.attach(row.repository_label, 1, 0, 1, 1);
|
|
|
|
|
|
|
|
row.branch_label = new Label("");
|
|
|
|
row.branch_label.set_markup("<small>%s</small>".printf(branch_name));
|
|
|
|
row.branch_label.ellipsize = Pango.EllipsizeMode.END;
|
|
|
|
row.branch_label.valign = Align.START;
|
|
|
|
row.branch_label.halign = Align.START;
|
|
|
|
row.branch_label.get_style_context().add_class("dim-label");
|
|
|
|
grid.attach(row.branch_label, 1, 1, 1, 1);
|
|
|
|
|
|
|
|
row.arrow = new Arrow(ArrowType.RIGHT, ShadowType.NONE);
|
|
|
|
grid.attach(row.arrow, 2, 0, 1, 2);
|
|
|
|
|
|
|
|
row.show_all();
|
|
|
|
d_listbox.add(row);
|
2013-03-21 19:06:18 +00:00
|
|
|
|
|
|
|
if (spin)
|
|
|
|
{
|
2013-06-22 11:09:05 +00:00
|
|
|
row.arrow.hide();
|
|
|
|
row.spinner = new Spinner();
|
|
|
|
grid.attach(row.spinner, 3, 0, 1, 2);
|
|
|
|
row.spinner.show();
|
|
|
|
row.spinner.start();
|
2013-03-21 19:06:18 +00:00
|
|
|
}
|
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
return row;
|
2013-03-21 19:06:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void add_repository_to_recent_manager(string uri)
|
|
|
|
{
|
|
|
|
var recent_manager = RecentManager.get_default();
|
|
|
|
var item = RecentData();
|
|
|
|
item.app_name = Environment.get_application_name();
|
|
|
|
item.mime_type = "inode/directory";
|
|
|
|
item.app_exec = string.join(" ", Environment.get_prgname(), "%f");
|
|
|
|
item.groups = { "gitg", null };
|
|
|
|
recent_manager.add_full(uri, item);
|
|
|
|
}
|
|
|
|
|
2013-03-21 15:51:25 +00:00
|
|
|
public void add_repository(Gitg.Repository repository)
|
|
|
|
{
|
2013-06-22 11:09:05 +00:00
|
|
|
DashRow? row = get_row_for_repository(repository);
|
2013-03-21 15:51:25 +00:00
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
if (row == null)
|
2012-07-10 14:32:48 +00:00
|
|
|
{
|
2013-03-24 11:32:48 +00:00
|
|
|
string head_name = "";
|
2013-06-15 08:38:48 +00:00
|
|
|
bool local = false;
|
2013-03-21 19:06:18 +00:00
|
|
|
|
2012-07-10 14:32:48 +00:00
|
|
|
try
|
|
|
|
{
|
2013-03-24 11:32:48 +00:00
|
|
|
var head = repository.get_head();
|
|
|
|
head_name = head.parsed_name.shortname;
|
2013-06-15 08:38:48 +00:00
|
|
|
var remotes = repository.list_remotes();
|
|
|
|
if (remotes.length == 0)
|
|
|
|
{
|
|
|
|
local = true;
|
|
|
|
}
|
2013-03-13 14:31:13 +00:00
|
|
|
}
|
|
|
|
catch {}
|
2012-07-10 14:32:48 +00:00
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
row = create_repository_row(repository.name, head_name, false, local);
|
|
|
|
row.repository = repository;
|
2013-03-13 14:31:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// to get the item sorted to the beginning of the list
|
2013-06-22 11:09:05 +00:00
|
|
|
row.time = new DateTime.now_local();
|
|
|
|
d_listbox.invalidate_filter();
|
2013-03-13 14:31:13 +00:00
|
|
|
}
|
2013-03-13 14:42:25 +00:00
|
|
|
|
2013-03-24 11:32:48 +00:00
|
|
|
var f = repository.workdir != null ? repository.workdir : repository.location;
|
|
|
|
if (f != null)
|
|
|
|
{
|
|
|
|
add_repository_to_recent_manager(f.get_uri());
|
|
|
|
}
|
2012-07-10 14:32:48 +00:00
|
|
|
}
|
2013-03-13 09:26:15 +00:00
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
private async Gitg.Repository? clone(DashRow row, string url, File location, bool is_bare)
|
2013-03-21 16:32:15 +00:00
|
|
|
{
|
2013-03-21 19:36:06 +00:00
|
|
|
SourceFunc callback = clone.callback;
|
2013-03-21 16:32:15 +00:00
|
|
|
Gitg.Repository? repository = null;
|
|
|
|
|
2013-03-21 19:36:06 +00:00
|
|
|
ThreadFunc<void*> run = () => {
|
|
|
|
try
|
|
|
|
{
|
2013-03-26 12:03:54 +00:00
|
|
|
var options = new Ggit.CloneOptions();
|
|
|
|
options.set_is_bare(is_bare);
|
2013-03-27 14:55:46 +00:00
|
|
|
options.set_fetch_progress_callback((stats) => {
|
2013-06-22 11:09:05 +00:00
|
|
|
row.bin.fraction = (stats.get_received_objects() + stats.get_indexed_objects()) / (double)(2 * stats.get_total_objects());
|
2013-03-27 14:55:46 +00:00
|
|
|
return 0;
|
|
|
|
});
|
2013-03-26 12:03:54 +00:00
|
|
|
|
|
|
|
repository = Ggit.Repository.clone(url, location, options) as Gitg.Repository;
|
2013-03-21 19:36:06 +00:00
|
|
|
}
|
2013-03-21 19:52:13 +00:00
|
|
|
catch (Ggit.Error e)
|
|
|
|
{
|
|
|
|
warning("error cloning: %s", e.message);
|
|
|
|
}
|
|
|
|
catch (GLib.Error e)
|
|
|
|
{
|
|
|
|
warning("error cloning: %s", e.message);
|
|
|
|
}
|
2013-03-21 16:32:15 +00:00
|
|
|
|
2013-03-21 19:36:06 +00:00
|
|
|
Idle.add((owned) callback);
|
|
|
|
return null;
|
|
|
|
};
|
2013-03-21 16:32:15 +00:00
|
|
|
|
2013-03-21 19:36:06 +00:00
|
|
|
try
|
|
|
|
{
|
2013-06-10 17:20:08 +00:00
|
|
|
new Thread<void*>.try("gitg-clone-thread", (owned)run);
|
2013-03-21 19:36:06 +00:00
|
|
|
yield;
|
2013-03-21 16:32:15 +00:00
|
|
|
}
|
|
|
|
catch {}
|
2013-03-21 19:36:06 +00:00
|
|
|
|
|
|
|
return repository;
|
|
|
|
}
|
|
|
|
|
2013-03-26 12:03:54 +00:00
|
|
|
public void clone_repository(string url, File location, bool is_bare)
|
2013-03-21 19:36:06 +00:00
|
|
|
{
|
2013-03-26 11:48:56 +00:00
|
|
|
// create subfolder
|
|
|
|
var subfolder_name = url.substring(url.last_index_of_char('/') + 1);
|
2013-03-28 10:22:52 +00:00
|
|
|
if (subfolder_name.has_suffix(".git") && !is_bare)
|
2013-03-26 11:48:56 +00:00
|
|
|
{
|
2013-03-28 10:22:52 +00:00
|
|
|
subfolder_name = subfolder_name.slice(0, - ".git".length);
|
2013-03-26 12:03:54 +00:00
|
|
|
}
|
2013-03-28 10:22:52 +00:00
|
|
|
else if (is_bare)
|
2013-03-26 12:03:54 +00:00
|
|
|
{
|
|
|
|
subfolder_name += ".git";
|
2013-03-26 11:48:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var subfolder = location.resolve_relative_path(subfolder_name);
|
2013-03-21 19:36:06 +00:00
|
|
|
|
2013-03-26 11:48:56 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
subfolder.make_directory_with_parents(null);
|
|
|
|
}
|
|
|
|
catch (GLib.Error e)
|
|
|
|
{
|
|
|
|
warning("error creating subfolder: %s", e.message);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clone
|
2013-06-22 11:09:05 +00:00
|
|
|
DashRow? row = create_repository_row(subfolder_name, "Cloning...", true, false);
|
2013-03-26 11:48:56 +00:00
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
clone.begin(row, url, subfolder, is_bare, (obj, res) => {
|
2013-03-21 19:36:06 +00:00
|
|
|
Gitg.Repository? repository = clone.end(res);
|
|
|
|
string branch_name = "";
|
|
|
|
|
2013-03-21 19:52:13 +00:00
|
|
|
// FIXME: show an error
|
|
|
|
if (repository != null)
|
2013-03-21 19:36:06 +00:00
|
|
|
{
|
2013-03-21 20:06:59 +00:00
|
|
|
File? workdir = repository.get_workdir();
|
|
|
|
File? repo_file = repository.get_location();
|
|
|
|
var uri = (workdir != null) ? workdir.get_uri() : repo_file.get_uri();
|
|
|
|
add_repository_to_recent_manager(uri);
|
|
|
|
|
2013-03-21 19:52:13 +00:00
|
|
|
try
|
|
|
|
{
|
2013-03-26 11:48:56 +00:00
|
|
|
var head = repository.get_head();
|
2013-03-21 19:52:13 +00:00
|
|
|
branch_name = head.parsed_name.shortname;
|
|
|
|
}
|
|
|
|
catch {}
|
2013-03-21 19:36:06 +00:00
|
|
|
}
|
|
|
|
|
2013-06-22 11:09:05 +00:00
|
|
|
row.repository = repository;
|
|
|
|
row.branch_label.set_markup("<small>%s</small>".printf(branch_name));
|
|
|
|
row.spinner.stop();
|
|
|
|
row.spinner.hide();
|
|
|
|
row.arrow.show();
|
|
|
|
row.bin.fraction = 0;
|
2013-03-21 19:36:06 +00:00
|
|
|
});
|
2013-03-21 16:32:15 +00:00
|
|
|
}
|
|
|
|
|
2013-03-13 09:26:15 +00:00
|
|
|
public void filter_text(string? text)
|
|
|
|
{
|
|
|
|
d_filter_text = text;
|
|
|
|
|
|
|
|
if (text != null && text != "")
|
|
|
|
{
|
|
|
|
d_listbox.set_filter_func(filter);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d_listbox.set_filter_func(null);
|
|
|
|
}
|
|
|
|
}
|
2012-07-10 14:32:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ex:ts=4 noet
|