dsadas
This commit is contained in:
parent
fc953316bf
commit
7f6fab0870
@ -13,6 +13,7 @@ gtk-sys = "^0.4.0"
|
||||
libpijul = "^0.7.3"
|
||||
log = "^0.3.8"
|
||||
base64 = "^0.6.0"
|
||||
chrono = "^0.4.0"
|
||||
|
||||
[dependencies.gdk]
|
||||
features = [
|
||||
|
@ -60,14 +60,89 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<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="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</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>
|
||||
</child>
|
||||
</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 libpijul;
|
||||
extern crate base64;
|
||||
extern crate chrono;
|
||||
|
||||
extern crate flexi_logger;
|
||||
#[macro_use]
|
||||
@ -17,9 +18,12 @@ extern crate log;
|
||||
#[macro_use]
|
||||
extern crate error_chain;
|
||||
|
||||
mod ui;
|
||||
mod appstate;
|
||||
mod errors;
|
||||
mod pijul_glue;
|
||||
mod ui;
|
||||
|
||||
use appstate::*;
|
||||
use ui::entry::*;
|
||||
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 gtk::prelude::*;
|
||||
use std::rc::Rc;
|
||||
use appstate::*;
|
||||
use gtk::WidgetExt;
|
||||
use libpijul;
|
||||
use libpijul::fs_representation::*;
|
||||
use std::path::Path;
|
||||
use errors::*;
|
||||
use gtk::prelude::*;
|
||||
use gtk;
|
||||
use pijul_glue::branches::*;
|
||||
use pijul_glue::patches::*;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
||||
pub struct AppS {
|
||||
_cant_construct: (),
|
||||
pub gui: Gui,
|
||||
}
|
||||
const HASH_COLUMN: i32 = 3;
|
||||
|
||||
|
||||
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>) {
|
||||
{
|
||||
@ -56,61 +22,74 @@ pub fn init(appstate: Rc<AppS>) {
|
||||
}
|
||||
|
||||
{
|
||||
let ls = gtk::ListStore::new(&[gtk::Type::String]);
|
||||
let patches = get_patches("/home/hasufell/git/pijul",
|
||||
let mut columns: Vec<gtk::TreeViewColumn> = Vec::new();
|
||||
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");
|
||||
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_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();
|
||||
}
|
||||
|
||||
|
||||
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 mut vec = Vec::new();
|
||||
let id = v.len() as i32;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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),
|
||||
}
|
||||
let renderer = gtk::CellRendererText::new();
|
||||
let col = gtk::TreeViewColumn::new();
|
||||
col.set_title(title);
|
||||
col.set_resizable(true);
|
||||
col.set_sort_column_id(id);
|
||||
if let Some(max_width) = max_width {
|
||||
col.set_max_width(max_width);
|
||||
col.set_expand(true);
|
||||
}
|
||||
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.
|
||||
|
||||
pub mod entry;
|
||||
pub mod gui;
|
||||
|
Loading…
Reference in New Issue
Block a user