Browse Source

dsadas

master
Julian Ospald 6 years ago
parent
commit
7f6fab0870
10 changed files with 286 additions and 83 deletions
  1. +1
    -0
      Cargo.toml
  2. +76
    -1
      data/ui/window.glade
  3. +20
    -0
      src/appstate.rs
  4. +5
    -1
      src/main.rs
  5. +18
    -0
      src/pijul_glue/branches.rs
  6. +4
    -0
      src/pijul_glue/mod.rs
  7. +79
    -0
      src/pijul_glue/patches.rs
  8. +60
    -81
      src/ui/entry.rs
  9. +22
    -0
      src/ui/gui.rs
  10. +1
    -0
      src/ui/mod.rs

+ 1
- 0
Cargo.toml View File

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


+ 76
- 1
data/ui/window.glade View File

@@ -60,9 +60,34 @@
<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>
@@ -70,6 +95,56 @@
<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">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>
<packing>
<property name="expand">False</property>


+ 20
- 0
src/appstate.rs View 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),
}
}
}

+ 5
- 1
src/main.rs View File

@@ -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
- 0
src/pijul_glue/branches.rs View 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
- 0
src/pijul_glue/mod.rs View File

@@ -0,0 +1,4 @@
//! The pijul glue subsystem.

pub mod branches;
pub mod patches;

+ 79
- 0
src/pijul_glue/patches.rs View 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,
}
}


+ 60
- 81
src/ui/entry.rs View File

@@ -1,48 +1,14 @@
use gtk;
use appstate::*;
use gtk::WidgetExt;
use gtk::prelude::*;
use gtk;
use pijul_glue::branches::*;
use pijul_glue::patches::*;
use std::rc::Rc;
use gtk::WidgetExt;
use libpijul;
use libpijul::fs_representation::*;
use std::path::Path;
use errors::*;


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(),
]);
}
appstate.gui.patch_tree.set_model(Some(&ls));
appstate.gui.patch_tree.set_headers_visible(true);
}

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);
let selection = appstate.gui.patch_tree.get_selection();
selection.set_mode(gtk::SelectionMode::Single);

appstate.gui.patch_tree.append_column(&col);
appstate.gui.patch_tree.set_model(Some(&ls));
/* 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: &gtk::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 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);

let branches = txn.iter_branches(None).map(|x| String::from(x.name.as_str()));
tree.append_column(&col);

vec.extend(branches);
return Ok(vec);
v.push(col);
}


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),
}
}

return Ok(vec);
}

+ 22
- 0
src/ui/gui.rs View 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
- 0
src/ui/mod.rs View File

@@ -1,3 +1,4 @@
//! The UI subsystem.

pub mod entry;
pub mod gui;

Loading…
Cancel
Save