mirror of
https://gitlab.gnome.org/GNOME/gitg
synced 2024-09-29 20:53:40 +00:00
Allow to add new remotes
This commit is contained in:
parent
14661a4baa
commit
be22b5370c
90
gitg/gitg-add-remote-action-dialog.vala
Normal file
90
gitg/gitg-add-remote-action-dialog.vala
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* This file is part of gitg
|
||||
*
|
||||
* Copyright (C) 2022 - Adwait Rawat
|
||||
*
|
||||
* 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-add-remote-action-dialog.ui")]
|
||||
class AddRemoteActionDialog : Gtk.Dialog
|
||||
{
|
||||
[GtkChild]
|
||||
private Gtk.Button d_button_create;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.Entry d_entry_remote_name;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.Entry d_entry_remote_url;
|
||||
|
||||
construct
|
||||
{
|
||||
d_entry_remote_name.changed.connect(() => {
|
||||
var is_name_valid = (d_entry_remote_name.text != "");
|
||||
|
||||
d_entry_remote_url.changed.connect((e) => {
|
||||
var is_url_valid = (d_entry_remote_url.text != "");
|
||||
|
||||
set_response_sensitive(Gtk.ResponseType.OK, is_name_valid && is_url_valid);
|
||||
});
|
||||
});
|
||||
|
||||
set_default(d_button_create);
|
||||
set_default_response(Gtk.ResponseType.OK);
|
||||
}
|
||||
|
||||
public AddRemoteActionDialog(Gtk.Window? parent)
|
||||
{
|
||||
Object(use_header_bar : 1);
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
set_transient_for(parent);
|
||||
}
|
||||
}
|
||||
|
||||
public string remote_name
|
||||
{
|
||||
owned get
|
||||
{
|
||||
return d_entry_remote_name.text.strip();
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
d_entry_remote_name.text = value.strip();
|
||||
}
|
||||
}
|
||||
|
||||
public string remote_url
|
||||
{
|
||||
owned get
|
||||
{
|
||||
return d_entry_remote_url.text.strip();
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
d_entry_remote_url.text = value.strip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ex: ts=4 noet
|
158
gitg/gitg-add-remote-action.vala
Normal file
158
gitg/gitg-add-remote-action.vala
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* This file is part of gitg
|
||||
*
|
||||
* Copyright (C) 2022 - Adwait Rawat
|
||||
*
|
||||
* 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 AddRemoteAction : GitgExt.UIElement, GitgExt.Action, 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; }
|
||||
private Gitg.Remote? d_remote;
|
||||
private Gitg.Repository? repo;
|
||||
private string? remote_name;
|
||||
private string? remote_url;
|
||||
|
||||
public AddRemoteAction(GitgExt.Application application)
|
||||
{
|
||||
Object(application: application);
|
||||
}
|
||||
|
||||
public string id
|
||||
{
|
||||
owned get { return "/org/gnome/gitg/ref-actions/add-remote"; }
|
||||
}
|
||||
|
||||
public string display_name
|
||||
{
|
||||
owned get { return _("Add Remote"); }
|
||||
}
|
||||
|
||||
public string description
|
||||
{
|
||||
owned get { return _("Adds remote to the remotes list"); }
|
||||
}
|
||||
|
||||
public async bool fetch()
|
||||
{
|
||||
var notification = new RemoteNotification(d_remote);
|
||||
application.notifications.add(notification);
|
||||
|
||||
notification.text = _("Fetching from %s").printf(d_remote.get_url());
|
||||
|
||||
var updates = new Gee.ArrayList<string>();
|
||||
|
||||
var tip_updated_id = d_remote.tip_updated.connect((d_remote, name, a, b) => {
|
||||
/* Translators: new refers to a new remote reference having been fetched, */
|
||||
updates.add(@"%s (%s)".printf(name, _("new")));
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
yield d_remote.fetch(null, null);
|
||||
}
|
||||
catch (Error e)
|
||||
{
|
||||
try {
|
||||
notification.error(_("Failed to fetch from %s: %s").printf(d_remote.get_url(), e.message));
|
||||
}
|
||||
catch {}
|
||||
application.show_infobar(_("Failed to fetch added remote"),
|
||||
e.message,
|
||||
Gtk.MessageType.ERROR);
|
||||
}
|
||||
finally
|
||||
{
|
||||
((Object)d_remote).disconnect(tip_updated_id);
|
||||
}
|
||||
|
||||
((Gtk.ApplicationWindow)application).activate_action("reload", null);
|
||||
if (updates.size != 0)
|
||||
{
|
||||
notification.success(_("Fetched from %s: %s").printf(d_remote.get_url(), string.joinv(", ", updates.to_array())));
|
||||
}
|
||||
else
|
||||
{
|
||||
add_remote(remote_name, remote_url);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void add_remote(owned string? name = "", owned string? url = "")
|
||||
{
|
||||
var dlg = new AddRemoteActionDialog((Gtk.Window)application);
|
||||
|
||||
remote_name = name;
|
||||
remote_url = url;
|
||||
dlg.remote_name = remote_name;
|
||||
dlg.remote_url = remote_url;
|
||||
|
||||
dlg.response.connect((d, resp) => {
|
||||
if (resp == Gtk.ResponseType.OK)
|
||||
{
|
||||
Ggit.Remote? remote = null;
|
||||
d_remote = null;
|
||||
|
||||
repo = application.repository;
|
||||
remote_name = dlg.remote_name;
|
||||
remote_url = dlg.remote_url;
|
||||
|
||||
try
|
||||
{
|
||||
remote = repo.create_remote(remote_name,
|
||||
remote_url);
|
||||
}
|
||||
catch (Error e)
|
||||
{
|
||||
add_remote(remote_name, remote_url);
|
||||
application.show_infobar(_("Failed to add remote"),
|
||||
e.message,
|
||||
Gtk.MessageType.ERROR);
|
||||
}
|
||||
|
||||
d_remote = application.remote_lookup.lookup(remote_name);
|
||||
|
||||
if (remote != null)
|
||||
{
|
||||
fetch.begin((obj,res) => {
|
||||
fetch.end(res);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
dlg.destroy();
|
||||
});
|
||||
|
||||
dlg.show();
|
||||
}
|
||||
|
||||
public void activate()
|
||||
{
|
||||
add_remote();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ex:set ts=4 noet
|
|
@ -43,7 +43,7 @@ private enum RefAnimation
|
|||
ANIMATE
|
||||
}
|
||||
|
||||
private interface RefTyped : Object
|
||||
public interface RefTyped : Object
|
||||
{
|
||||
public abstract Gitg.RefType ref_type { get; }
|
||||
}
|
||||
|
@ -402,11 +402,12 @@ private class RefRow : RefTyped, Gtk.ListBoxRow
|
|||
}
|
||||
|
||||
[GtkTemplate (ui = "/org/gnome/gitg/ui/gitg-history-ref-header.ui")]
|
||||
private class RefHeader : RefTyped, Gtk.ListBoxRow
|
||||
public class RefHeader : RefTyped, Gtk.ListBoxRow
|
||||
{
|
||||
private Gitg.RefType d_rtype;
|
||||
private bool d_is_sub_header_remote;
|
||||
private string d_name;
|
||||
public Gee.LinkedList<GitgExt.Action> actions { get; set; }
|
||||
|
||||
public Gitg.RemoteState remote_state
|
||||
{
|
||||
|
@ -536,6 +537,15 @@ public class RefsList : Gtk.ListBox
|
|||
private RefHeader? d_all_tags;
|
||||
private RefRow.SortOrder d_ref_sort_order;
|
||||
private HeaderState[] d_expanded;
|
||||
public RefHeader? branches_header { get { return d_all_branches; } }
|
||||
public RefHeader? remotes_header { get { return d_all_remotes; } }
|
||||
public RefHeader? tags_header { get { return d_all_tags; } }
|
||||
private Gee.LinkedList<GitgExt.Action> d_branches_actions = null;
|
||||
private Gee.LinkedList<GitgExt.Action> d_remotes_actions = null;
|
||||
private Gee.LinkedList<GitgExt.Action> d_tags_actions = null;
|
||||
public Gee.LinkedList<GitgExt.Action> branches_actions { get {return d_branches_actions;} set { d_branches_actions = value; refresh();} }
|
||||
public Gee.LinkedList<GitgExt.Action> remotes_actions { get {return d_remotes_actions;} set { d_remotes_actions = value; refresh();} }
|
||||
public Gee.LinkedList<GitgExt.Action> tags_actions { get {return d_tags_actions;} set { d_tags_actions = value; refresh();} }
|
||||
|
||||
public signal void changed();
|
||||
|
||||
|
@ -869,10 +879,11 @@ public class RefsList : Gtk.ListBox
|
|||
}
|
||||
}
|
||||
|
||||
private RefHeader add_header(Gitg.RefType ref_type, string name)
|
||||
private RefHeader add_header(Gitg.RefType ref_type, string name, Gee.LinkedList<GitgExt.Action>? actions)
|
||||
{
|
||||
var header = new RefHeader(ref_type, name);
|
||||
init_header(header);
|
||||
header.actions = actions;
|
||||
|
||||
add(header);
|
||||
return header;
|
||||
|
@ -1176,9 +1187,9 @@ public class RefsList : Gtk.ListBox
|
|||
}
|
||||
|
||||
d_all_commits = add_ref_row(null);
|
||||
d_all_branches = add_header(Gitg.RefType.BRANCH, _("Branches"));
|
||||
d_all_remotes = add_header(Gitg.RefType.REMOTE, _("Remotes"));
|
||||
d_all_tags = add_header(Gitg.RefType.TAG, _("Tags"));
|
||||
d_all_branches = add_header(Gitg.RefType.BRANCH, _("Branches"), branches_actions);
|
||||
d_all_remotes = add_header(Gitg.RefType.REMOTE, _("Remotes"), remotes_actions);
|
||||
d_all_tags = add_header(Gitg.RefType.TAG, _("Tags"), tags_actions);
|
||||
|
||||
RefRow? head = null;
|
||||
|
||||
|
@ -1412,7 +1423,7 @@ public class RefsList : Gtk.ListBox
|
|||
row.begin_editing((owned)done);
|
||||
}
|
||||
|
||||
private int y_in_window(int y, Gdk.Window origin)
|
||||
public int y_in_window(int y, Gdk.Window origin)
|
||||
{
|
||||
while (origin != get_window())
|
||||
{
|
||||
|
|
|
@ -627,6 +627,10 @@ namespace GitgHistory
|
|||
|
||||
d_commit_list_model.begin_clear.connect(on_commit_model_begin_clear);
|
||||
d_commit_list_model.end_clear.connect(on_commit_model_end_clear);
|
||||
|
||||
var actions = new Gee.LinkedList<GitgExt.Action>();
|
||||
actions.add(new Gitg.AddRemoteAction(application));
|
||||
d_main.refs_list.remotes_actions = actions;
|
||||
}
|
||||
|
||||
private void update_walker_idle()
|
||||
|
@ -988,9 +992,12 @@ namespace GitgHistory
|
|||
|
||||
private Gtk.Menu? on_refs_list_populate_menu(Gdk.EventButton? event)
|
||||
{
|
||||
Gtk.ListBoxRow selection = null;
|
||||
if (event != null)
|
||||
{
|
||||
var row = d_main.refs_list.get_row_at_y((int)event.y);
|
||||
var y = d_main.refs_list.y_in_window((int)event.y, event.window);
|
||||
var row = d_main.refs_list.get_row_at_y(y);
|
||||
selection = row;
|
||||
d_main.refs_list.select_row(row);
|
||||
}
|
||||
|
||||
|
@ -998,7 +1005,30 @@ namespace GitgHistory
|
|||
|
||||
if (references.is_empty || references.first() != references.last())
|
||||
{
|
||||
return null;
|
||||
Gee.LinkedList<GitgExt.Action> actions = null;
|
||||
if (selection != null && selection.get_type () == typeof(RefHeader)
|
||||
&& (actions = ((RefHeader)selection).actions) != null && actions.size > 0) {
|
||||
var menu = new Gtk.Menu();
|
||||
|
||||
foreach (var ac in actions)
|
||||
{
|
||||
if (ac != null)
|
||||
{
|
||||
ac.populate_menu(menu);
|
||||
}
|
||||
else
|
||||
{
|
||||
var sep = new Gtk.SeparatorMenuItem();
|
||||
sep.show();
|
||||
menu.append(sep);
|
||||
}
|
||||
}
|
||||
|
||||
menu.set_data("gitg-ext-actions", actions);
|
||||
return menu;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return popup_menu_for_ref(references.first());
|
||||
|
|
|
@ -46,6 +46,8 @@ sources = gitg_sources + files(
|
|||
'gitg-ref-action-fetch.vala',
|
||||
'gitg-ref-action-push.vala',
|
||||
'gitg-ref-action-rename.vala',
|
||||
'gitg-add-remote-action-dialog.vala',
|
||||
'gitg-add-remote-action.vala',
|
||||
'gitg-remote-manager.vala',
|
||||
'gitg-remote-notification.vala',
|
||||
'gitg-simple-notification.vala',
|
||||
|
@ -106,6 +108,7 @@ resource_data = files(
|
|||
'resources/ui/gitg-preferences-history.ui',
|
||||
'resources/ui/gitg-preferences-interface.ui',
|
||||
'resources/ui/gitg-preferences.ui',
|
||||
'resources/ui/gitg-add-remote-action-dialog.ui',
|
||||
'resources/ui/gitg-remote-notification.ui',
|
||||
'resources/ui/gitg-shortcuts.ui',
|
||||
'resources/ui/gitg-simple-notification.ui',
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-preferences-commit.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-preferences-interface.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-preferences.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-add-remote-action-dialog.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-clone-dialog.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-author-details-dialog.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/gitg-history-paned.ui</file>
|
||||
|
|
139
gitg/resources/ui/gitg-add-remote-action-dialog.ui
Normal file
139
gitg/resources/ui/gitg-add-remote-action-dialog.ui
Normal file
|
@ -0,0 +1,139 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 3.0 -->
|
||||
<template class="GitgAddRemoteActionDialog" parent="GtkDialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">12</property>
|
||||
<property name="title" translatable="yes">Create Remote</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child internal-child="headerbar">
|
||||
<object class="GtkHeaderBar" id="dialog-header_bar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="show_close_button">False</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="button_cancel">
|
||||
<property name="label" translatable="yes">_Cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="valign">center</property>
|
||||
<style>
|
||||
<class name="text-button"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">start</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="d_button_create">
|
||||
<property name="label" translatable="yes">_Add</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<style>
|
||||
<class name="text-button"/>
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">end</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox" id="dialog-vbox1">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Remote _name:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">d_entry_remote_name</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="d_entry_remote_name">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="activates_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Remote _URL:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">d_entry_remote_url</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="d_entry_remote_url">
|
||||
<property name="width_request">350</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="activates_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="cancel">button_cancel</action-widget>
|
||||
<action-widget response="ok">d_button_create</action-widget>
|
||||
</action-widgets>
|
||||
</template>
|
||||
</interface>
|
|
@ -46,6 +46,10 @@ public interface Action : UIElement
|
|||
item.show();
|
||||
menu.append(item);
|
||||
}
|
||||
|
||||
public virtual async bool fetch(){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue