dsadas
This commit is contained in:
parent
fc953316bf
commit
7f6fab0870
@ -13,6 +13,7 @@ gtk-sys = "^0.4.0"
|
|||||||
libpijul = "^0.7.3"
|
libpijul = "^0.7.3"
|
||||||
log = "^0.3.8"
|
log = "^0.3.8"
|
||||||
base64 = "^0.6.0"
|
base64 = "^0.6.0"
|
||||||
|
chrono = "^0.4.0"
|
||||||
|
|
||||||
[dependencies.gdk]
|
[dependencies.gdk]
|
||||||
features = [
|
features = [
|
||||||
|
@ -60,14 +60,89 @@
|
|||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkComboBoxText" id="branch_select">
|
<object class="GtkBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">Branch</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="padding">2</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkComboBoxText" id="branch_select">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="padding">2</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSeparator">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">0</property>
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_left">2</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">Hash</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="padding">2</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="hash_entry">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="editable">False</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="padding">2</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="padding">2</property>
|
||||||
|
<property name="position">2</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
20
src/appstate.rs
Normal file
20
src/appstate.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use gtk;
|
||||||
|
use ui::gui::*;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct AppS {
|
||||||
|
_cant_construct: (),
|
||||||
|
pub gui: Gui,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl AppS {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let builder = gtk::Builder::new_from_string(include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/data/ui/window.glade")));
|
||||||
|
|
||||||
|
return AppS {
|
||||||
|
_cant_construct: (),
|
||||||
|
gui: Gui::new(builder),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ extern crate gtk;
|
|||||||
extern crate gtk_sys;
|
extern crate gtk_sys;
|
||||||
extern crate libpijul;
|
extern crate libpijul;
|
||||||
extern crate base64;
|
extern crate base64;
|
||||||
|
extern crate chrono;
|
||||||
|
|
||||||
extern crate flexi_logger;
|
extern crate flexi_logger;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@ -17,9 +18,12 @@ extern crate log;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate error_chain;
|
extern crate error_chain;
|
||||||
|
|
||||||
mod ui;
|
mod appstate;
|
||||||
mod errors;
|
mod errors;
|
||||||
|
mod pijul_glue;
|
||||||
|
mod ui;
|
||||||
|
|
||||||
|
use appstate::*;
|
||||||
use ui::entry::*;
|
use ui::entry::*;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
18
src/pijul_glue/branches.rs
Normal file
18
src/pijul_glue/branches.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use libpijul;
|
||||||
|
use libpijul::fs_representation::*;
|
||||||
|
use errors::*;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn get_branches(path: &str) -> Result<Vec<String>> {
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
|
||||||
|
let repo = libpijul::Repository::open(pristine_dir(path), None).unwrap();
|
||||||
|
let txn = repo.txn_begin().unwrap();
|
||||||
|
|
||||||
|
let branches = txn.iter_branches(None).map(|x| String::from(x.name.as_str()));
|
||||||
|
|
||||||
|
vec.extend(branches);
|
||||||
|
return Ok(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
4
src/pijul_glue/mod.rs
Normal file
4
src/pijul_glue/mod.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
//! The pijul glue subsystem.
|
||||||
|
|
||||||
|
pub mod branches;
|
||||||
|
pub mod patches;
|
79
src/pijul_glue/patches.rs
Normal file
79
src/pijul_glue/patches.rs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
use libpijul;
|
||||||
|
use libpijul::patch;
|
||||||
|
use libpijul::fs_representation::*;
|
||||||
|
use std::path::Path;
|
||||||
|
use errors::*;
|
||||||
|
use base64;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Patch {
|
||||||
|
pub name: String,
|
||||||
|
pub authors: String,
|
||||||
|
pub created: String,
|
||||||
|
pub signed: bool,
|
||||||
|
hash: libpijul::Hash,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Patch {
|
||||||
|
pub fn from_patch(patch: patch::Patch, hash: libpijul::Hash) -> Self {
|
||||||
|
let p = Patch {
|
||||||
|
name: patch.header().name.clone(),
|
||||||
|
authors: patch.header().authors.join(", "),
|
||||||
|
created: format!("{}", patch.header().timestamp.format("%F %T")),
|
||||||
|
signed: patch_is_signed(patch),
|
||||||
|
hash: hash,
|
||||||
|
};
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hash_to_str(&self) -> String {
|
||||||
|
let config = base64::Config::new(base64::CharacterSet::Standard,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
base64::LineWrap::NoWrap);
|
||||||
|
let s = self.hash.to_base64(config);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn str_to_hash(s: String) -> Option<libpijul::Hash> {
|
||||||
|
return libpijul::Hash::from_base64(s.as_ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn get_patch_headers(path: &str, branch: &str) -> Result<Vec<Patch>> {
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
|
||||||
|
let repo = libpijul::Repository::open(pristine_dir(path), None)?;
|
||||||
|
let txn = repo.txn_begin().unwrap();
|
||||||
|
|
||||||
|
let branch = txn.get_branch(branch).unwrap();
|
||||||
|
|
||||||
|
let patches_ids = txn.iter_patches(&branch, None).map(|x| x.0);
|
||||||
|
for pid in patches_ids {
|
||||||
|
let hash_ref = txn.external_hash(pid);
|
||||||
|
let mp = libpijul::fs_representation::read_patch(Path::new(path),
|
||||||
|
hash_ref);
|
||||||
|
match mp {
|
||||||
|
Ok(p) => {
|
||||||
|
vec.push(Patch::from_patch(p, hash_ref.to_owned()));
|
||||||
|
},
|
||||||
|
Err(e) => warn!("Could not get patch for patch_id {:?}\nError: {:?}", pid, e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn patch_is_signed(patch: patch::Patch) -> bool {
|
||||||
|
match patch {
|
||||||
|
patch::Patch::Unsigned(_) => return false,
|
||||||
|
patch::Patch::Signed{patch: _, signature: _ } => return true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
147
src/ui/entry.rs
147
src/ui/entry.rs
@ -1,49 +1,15 @@
|
|||||||
use gtk;
|
use appstate::*;
|
||||||
use gtk::prelude::*;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use gtk::WidgetExt;
|
use gtk::WidgetExt;
|
||||||
use libpijul;
|
use gtk::prelude::*;
|
||||||
use libpijul::fs_representation::*;
|
use gtk;
|
||||||
use std::path::Path;
|
use pijul_glue::branches::*;
|
||||||
use errors::*;
|
use pijul_glue::patches::*;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
|
||||||
pub struct AppS {
|
const HASH_COLUMN: i32 = 3;
|
||||||
_cant_construct: (),
|
|
||||||
pub gui: Gui,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl AppS {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let builder = gtk::Builder::new_from_string(include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/data/ui/window.glade")));
|
|
||||||
|
|
||||||
return AppS {
|
|
||||||
_cant_construct: (),
|
|
||||||
gui: Gui::new(builder),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub struct Gui {
|
|
||||||
_cant_construct: (),
|
|
||||||
pub window: gtk::Window,
|
|
||||||
pub branch_select: gtk::ComboBoxText,
|
|
||||||
pub patch_tree: gtk::TreeView,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Gui {
|
|
||||||
pub fn new(builder: gtk::Builder) -> Self {
|
|
||||||
return Gui {
|
|
||||||
_cant_construct: (),
|
|
||||||
window: builder.get_object("main").unwrap(),
|
|
||||||
branch_select: builder.get_object("branch_select").unwrap(),
|
|
||||||
patch_tree: builder.get_object("patch_tree").unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn init(appstate: Rc<AppS>) {
|
pub fn init(appstate: Rc<AppS>) {
|
||||||
{
|
{
|
||||||
@ -56,61 +22,74 @@ pub fn init(appstate: Rc<AppS>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let ls = gtk::ListStore::new(&[gtk::Type::String]);
|
let mut columns: Vec<gtk::TreeViewColumn> = Vec::new();
|
||||||
let patches = get_patches("/home/hasufell/git/pijul",
|
append_column("Patch", &mut columns, &appstate.gui.patch_tree, Some(200));
|
||||||
|
append_column("Authors", &mut columns, &appstate.gui.patch_tree, None);
|
||||||
|
append_column("Date", &mut columns, &appstate.gui.patch_tree, None);
|
||||||
|
|
||||||
|
let ls = gtk::ListStore::new(&[
|
||||||
|
// visible
|
||||||
|
gtk::Type::String, // name
|
||||||
|
gtk::Type::String, // authors
|
||||||
|
gtk::Type::String, // creation date
|
||||||
|
// not visible
|
||||||
|
gtk::Type::String, // hash
|
||||||
|
]);
|
||||||
|
let patches = get_patch_headers("/home/hasufell/git/pijul",
|
||||||
"master");
|
"master");
|
||||||
for patch in patches.unwrap() {
|
for patch in patches.unwrap() {
|
||||||
ls.insert_with_values(None, &[0], &[&patch.as_str()]);
|
ls.insert_with_values(None, &[0, 1, 2, 3],
|
||||||
|
&[&patch.name.as_str(),
|
||||||
|
&patch.authors.as_str(),
|
||||||
|
&patch.created.as_str(),
|
||||||
|
&patch.hash_to_str(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let renderer = gtk::CellRendererText::new();
|
|
||||||
let col = gtk::TreeViewColumn::new();
|
|
||||||
col.set_title("Patch");
|
|
||||||
col.set_resizable(true);
|
|
||||||
col.pack_start(&renderer, true);
|
|
||||||
col.add_attribute(&renderer, "text", 0);
|
|
||||||
col.set_clickable(true);
|
|
||||||
col.set_sort_column_id(0);
|
|
||||||
|
|
||||||
appstate.gui.patch_tree.append_column(&col);
|
|
||||||
appstate.gui.patch_tree.set_model(Some(&ls));
|
appstate.gui.patch_tree.set_model(Some(&ls));
|
||||||
|
appstate.gui.patch_tree.set_headers_visible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
let selection = appstate.gui.patch_tree.get_selection();
|
||||||
|
selection.set_mode(gtk::SelectionMode::Single);
|
||||||
|
|
||||||
|
/* connect selection change */
|
||||||
|
{
|
||||||
|
let apps = appstate.clone();
|
||||||
|
selection.connect_changed(move |ts| {
|
||||||
|
if let Some((model, iter)) = ts.get_selected() {
|
||||||
|
let val = model.get_value(&iter, HASH_COLUMN);
|
||||||
|
let s: String = val.downcast().unwrap().get().unwrap();
|
||||||
|
apps.gui.hash_entry.set_text(s.as_ref());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
appstate.gui.window.show_all();
|
appstate.gui.window.show_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn append_column(title: &str,
|
||||||
|
v: &mut Vec<gtk::TreeViewColumn>,
|
||||||
|
tree: >k::TreeView,
|
||||||
|
max_width: Option<i32>) {
|
||||||
|
|
||||||
fn get_branches(path: &str) -> Result<Vec<String>> {
|
let id = v.len() as i32;
|
||||||
let mut vec = Vec::new();
|
|
||||||
|
|
||||||
let repo = libpijul::Repository::open(pristine_dir(path), None).unwrap();
|
let renderer = gtk::CellRendererText::new();
|
||||||
let txn = repo.txn_begin().unwrap();
|
let col = gtk::TreeViewColumn::new();
|
||||||
|
col.set_title(title);
|
||||||
let branches = txn.iter_branches(None).map(|x| String::from(x.name.as_str()));
|
col.set_resizable(true);
|
||||||
|
col.set_sort_column_id(id);
|
||||||
vec.extend(branches);
|
if let Some(max_width) = max_width {
|
||||||
return Ok(vec);
|
col.set_max_width(max_width);
|
||||||
}
|
col.set_expand(true);
|
||||||
|
|
||||||
|
|
||||||
fn get_patches(path: &str, branch: &str) -> Result<Vec<String>> {
|
|
||||||
let mut vec = Vec::new();
|
|
||||||
|
|
||||||
let repo = libpijul::Repository::open(pristine_dir(path), None)?;
|
|
||||||
let txn = repo.txn_begin().unwrap();
|
|
||||||
|
|
||||||
let branch = txn.get_branch(branch).unwrap();
|
|
||||||
|
|
||||||
let patches_ids = txn.iter_patches(&branch, None).map(|x| x.0);
|
|
||||||
for pid in patches_ids {
|
|
||||||
let mp = libpijul::fs_representation::read_patch(Path::new(path),
|
|
||||||
txn.external_hash(pid));
|
|
||||||
match mp {
|
|
||||||
Ok(p) => vec.push(p.header().name.clone()),
|
|
||||||
Err(e) => warn!("Could not get patch for patch_id {:?}\nError: {:?}", pid, e),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
col.pack_start(&renderer, true);
|
||||||
|
col.add_attribute(&renderer, "text", id);
|
||||||
|
col.set_clickable(true);
|
||||||
|
|
||||||
return Ok(vec);
|
tree.append_column(&col);
|
||||||
|
|
||||||
|
v.push(col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
src/ui/gui.rs
Normal file
22
src/ui/gui.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use gtk;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Gui {
|
||||||
|
_cant_construct: (),
|
||||||
|
pub window: gtk::Window,
|
||||||
|
pub branch_select: gtk::ComboBoxText,
|
||||||
|
pub patch_tree: gtk::TreeView,
|
||||||
|
pub hash_entry: gtk::Entry,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Gui {
|
||||||
|
pub fn new(builder: gtk::Builder) -> Self {
|
||||||
|
return Gui {
|
||||||
|
_cant_construct: (),
|
||||||
|
window: builder.get_object("main").unwrap(),
|
||||||
|
branch_select: builder.get_object("branch_select").unwrap(),
|
||||||
|
patch_tree: builder.get_object("patch_tree").unwrap(),
|
||||||
|
hash_entry: builder.get_object("hash_entry").unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
//! The UI subsystem.
|
//! The UI subsystem.
|
||||||
|
|
||||||
pub mod entry;
|
pub mod entry;
|
||||||
|
pub mod gui;
|
||||||
|
Loading…
Reference in New Issue
Block a user