Skip to content

Commit

Permalink
Add filtering commit log by author
Browse files Browse the repository at this point in the history
  • Loading branch information
ArekPiekarz committed May 21, 2022
1 parent 947af96 commit 5d74afb
Show file tree
Hide file tree
Showing 12 changed files with 453 additions and 100 deletions.
2 changes: 1 addition & 1 deletion src/application_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl ApplicationWindow

pub fn show(&self)
{
self.window.show_all();
self.window.show();
}

pub fn setOpacity(&self, value: f64)
Expand Down
13 changes: 13 additions & 0 deletions src/commit_log_author_filter_entry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use crate::event::{Event, Sender, Source};
use crate::gui_element_provider::GuiElementProvider;

use gtk::traits::EntryExt;


pub fn setupCommitLogAuthorFilterEntry(guiElementProvider: &GuiElementProvider, sender: Sender)
{
let widget = guiElementProvider.get::<gtk::Entry>("Commit log author filter entry");
widget.connect_activate(move |widget| {
sender.send((Source::CommitLogAuthorFilterEntry, Event::TextEntered(widget.text().into()))).unwrap();
});
}
9 changes: 9 additions & 0 deletions src/commit_log_column.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ impl CommitLogColumn
}
}

#[allow(clippy::as_conversions)]
impl From<CommitLogColumn> for i32
{
fn from(value: CommitLogColumn) -> Self
{
value as Self
}
}

#[allow(clippy::as_conversions)]
impl From<CommitLogColumn> for u32
{
Expand Down
35 changes: 35 additions & 0 deletions src/commit_log_filters_view.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::event::{Event, handleUnknown, IEventHandler, Source};
use crate::gui_element_provider::GuiElementProvider;

use gtk::traits::WidgetExt;


pub(crate) struct CommitLogFiltersView
{
widget: gtk::Grid
}

impl IEventHandler for CommitLogFiltersView
{
fn handle(&mut self, source: Source, event: &Event)
{
match event {
Event::Toggled => self.onToggled(),
_ => handleUnknown(source, event)
}
}
}

impl CommitLogFiltersView
{
pub(crate) fn new(guiElementProvider: &GuiElementProvider) -> Self
{
let widget = guiElementProvider.get::<gtk::Grid>("Commit log filters grid");
Self{widget}
}

fn onToggled(&self)
{
self.widget.set_visible(!self.widget.is_visible());
}
}
78 changes: 78 additions & 0 deletions src/commit_log_model_filter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use crate::commit_log_column::{CommitLogColumn};
use crate::event::{Event, handleUnknown, IEventHandler, Source};
use crate::gui_element_provider::GuiElementProvider;

use gtk::glib;
use gtk::traits::TreeModelExt;
use gtk::traits::TreeModelFilterExt;
use std::cell::RefCell;
use std::rc::Rc;


pub struct CommitLogModelFilter
{
modelFilter: gtk::TreeModelFilter,
authorFilter: AuthorFilter,
}

type AuthorFilter = Rc<RefCell<String>>;

impl IEventHandler for CommitLogModelFilter
{
fn handle(&mut self, source: Source, event: &Event)
{
match event {
Event::TextEntered(filter) => self.onCommitAuthorFilterChanged(filter),
_ => handleUnknown(source, event)
}
}
}

impl CommitLogModelFilter
{
pub fn new(guiElementProvider: &GuiElementProvider)
-> Self
{
let modelFilter = guiElementProvider.get::<gtk::TreeModelFilter>("Commit log store filter");
let authorFilter = Rc::new(RefCell::new(String::new()));
setupFilterFunction(&modelFilter, Rc::clone(&authorFilter));
Self{modelFilter, authorFilter}
}


// private

fn onCommitAuthorFilterChanged(&self, filter: &str)
{
*self.authorFilter.borrow_mut() = filter.into();
self.modelFilter.refilter();
}
}

fn setupFilterFunction(modelFilter: &gtk::TreeModelFilter, authorFilter: AuthorFilter)
{
modelFilter.set_visible_func(move |model, iter| {
if isRowEmpty(model, iter) {
return false;
}

let authorFilter = &*authorFilter.borrow();
if authorFilter.is_empty() {
return true;
}
let author = model.value(iter, CommitLogColumn::Author.into());
let author = author.get::<&str>().unwrap();
author == *authorFilter
});
}

fn isRowEmpty(model: &gtk::TreeModel, iter: &gtk::TreeIter) -> bool
{
match model.value(iter, CommitLogColumn::Date.into()).get::<&str>() {
Ok(text) => text.is_empty(),
Err(error) => match error {
glib::value::ValueTypeMismatchOrNoneError::WrongValueType(e) => panic!("Wrong value type: {}", e),
glib::value::ValueTypeMismatchOrNoneError::UnexpectedNone => true
}
}
}
9 changes: 9 additions & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ pub enum Event

// tree selection
SelectionChanged(gtk::TreeSelection),

// stack
StackChildChanged(String),

// text entry
TextEntered(String)
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
Expand All @@ -64,12 +70,15 @@ pub enum Source
CommitAmendCheckbox,
CommitButton,
CommitDiffViewWidget,
CommitLogAuthorFilterEntry,
CommitLogView,
CommitLogViewWidget,
CommitMessageView,
DiffView,
MainStack,
RefreshButton,
Repository,
ShowCommitLogFiltersButton,
StagedChangesStore,
StagedChangesView,
UnstagedChangesStore,
Expand Down
120 changes: 73 additions & 47 deletions src/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use crate::application_window::ApplicationWindow;
use crate::commit_button::CommitButton;
use crate::commit_diff_view::CommitDiffView;
use crate::commit_log::CommitLog;
use crate::commit_log_author_filter_entry::setupCommitLogAuthorFilterEntry;
use crate::commit_log_filters_view::CommitLogFiltersView;
use crate::commit_log_model::CommitLogModel;
use crate::commit_log_model_filter::CommitLogModelFilter;
use crate::commit_log_view::CommitLogView;
use crate::commit_message_reader::CommitMessageReader;
use crate::commit_message_view::CommitMessageView;
Expand All @@ -14,11 +17,14 @@ use crate::file_changes_paned::setupFileChangesPaned;
use crate::gui_element_provider::GuiElementProvider;
use crate::main_context::attach;
use crate::main_paned::setupMainPaned;
use crate::main_stack::setupMainStack;
use crate::refresh_button::RefreshButton;
use crate::repository::Repository;
use crate::settings::Settings;
use crate::show_commit_log_filters_button::setupShowCommitLogFiltersButton;
use crate::staged_changes_store::StagedChangesStore;
use crate::staged_changes_view::{makeStagedChangesView, StagedChangesView};
use crate::tool_bar_stack::ToolBarStack;
use crate::unstaged_changes_store::UnstagedChangesStore;
use crate::unstaged_changes_view::{makeUnstagedChangesView, UnstagedChangesView};

Expand All @@ -34,6 +40,7 @@ pub struct Gui

struct GuiObjects
{
toolBarStack: ToolBarStack,
unstagedChangesView: UnstagedChangesView,
stagedChangesView: StagedChangesView,
diffView: DiffView,
Expand All @@ -43,8 +50,10 @@ struct GuiObjects
commitAmendCheckbox: CommitAmendCheckbox,
unstagedChangesStore: Rc<RefCell<UnstagedChangesStore>>,
stagedChangesStore: Rc<RefCell<StagedChangesStore>>,
commitLogFiltersView: CommitLogFiltersView,
commitLogModelFilter: CommitLogModelFilter,
commitLogView: CommitLogView,
commitDiffView: CommitDiffView
commitDiffView: CommitDiffView,
}

impl Gui
Expand Down Expand Up @@ -72,10 +81,18 @@ impl Gui
let commitButton = CommitButton::new(
&guiElementProvider, commitMessageReader, Rc::clone(&repository), sender.clone());

let commitLogFiltersView = CommitLogFiltersView::new(&guiElementProvider);
let commitLogModelFilter = CommitLogModelFilter::new(&guiElementProvider);
let commitLog = CommitLog::new(&repository.borrow());
let _commitLogModel = CommitLogModel::new(&commitLog, &guiElementProvider);
let commitLogView = CommitLogView::new(commitLog, &guiElementProvider, sender.clone());
let commitDiffView = CommitDiffView::new(Rc::clone(&repository), &guiElementProvider, sender);
let commitDiffView = CommitDiffView::new(Rc::clone(&repository), &guiElementProvider, sender.clone());

setupMainStack(&guiElementProvider, sender.clone());
let toolBarStack = ToolBarStack::new(&guiElementProvider);

setupShowCommitLogFiltersButton(&guiElementProvider, sender.clone());
setupCommitLogAuthorFilterEntry(&guiElementProvider, sender);

let mut settings = Settings::new();
setupPanes(&guiElementProvider, &mut settings);
Expand All @@ -93,8 +110,11 @@ impl Gui
commitAmendCheckbox,
unstagedChangesStore,
stagedChangesStore,
commitLogFiltersView,
commitLogModelFilter,
commitLogView,
commitDiffView
commitDiffView,
toolBarStack
};
setupDispatching(guiObjects, repository, receiver);
newSelf
Expand All @@ -115,6 +135,7 @@ impl Gui
#[allow(clippy::match_same_arms)]
fn setupDispatching(gui: GuiObjects, mut repository: Rc<RefCell<Repository>>, receiver: Receiver)
{
let mut toolBarStack = gui.toolBarStack;
let mut unstagedChangesView = gui.unstagedChangesView;
let mut stagedChangesView = gui.stagedChangesView;
let mut diffView = gui.diffView;
Expand All @@ -124,56 +145,61 @@ fn setupDispatching(gui: GuiObjects, mut repository: Rc<RefCell<Repository>>, re
let mut commitAmendCheckbox = gui.commitAmendCheckbox;
let mut unstagedChangesStore = Rc::clone(&gui.unstagedChangesStore);
let mut stagedChangesStore = Rc::clone(&gui.stagedChangesStore);
let mut commitLogFiltersView = gui.commitLogFiltersView;
let mut commitLogModelFilter = gui.commitLogModelFilter;
let mut commitLogView = gui.commitLogView;
let mut commitDiffView = gui.commitDiffView;

use Source as S;
use Event as E;
attach(receiver, move |(source, event)| { match (source, &event) {
(S::CommitAmendCheckbox, E::CommitAmendDisabled) => (&repository, &mut commitMessageView, &mut commitButton, &mut diffView).handle(source, &event),
(S::CommitAmendCheckbox, E::CommitAmendEnabled) => (&repository, &mut commitMessageView, &mut commitButton, &mut diffView).handle(source, &event),
(S::CommitAmendCheckbox, E::Toggled) => commitAmendCheckbox.handle(source, &event),
(S::CommitButton, E::AmendCommitRequested(_)) => repository.handle(source, &event),
(S::CommitButton, E::Clicked) => commitButton.handle(source, &event),
(S::CommitButton, E::CommitRequested(_)) => repository.handle(source, &event),
(S::CommitDiffViewWidget, E::ZoomRequested(_)) => commitDiffView.handle(source, &event),
(S::CommitLogView, E::CommitSelected(_)) => commitDiffView.handle(source, &event),
(S::CommitLogView, E::CommitUnselected) => commitDiffView.handle(source, &event),
(S::CommitLogViewWidget, E::RightClicked(_)) => (),
(S::CommitLogViewWidget, E::RowActivated(_)) => (),
(S::CommitLogViewWidget, E::SelectionChanged(_)) => commitLogView.handle(source, &event),
(S::CommitMessageView, E::BufferChanged) => commitMessageView.handle(source, &event),
(S::CommitMessageView, E::Emptied) => commitButton.handle(source, &event),
(S::CommitMessageView, E::Filled) => commitButton.handle(source, &event),
(S::CommitMessageView, E::ZoomRequested(_)) => commitMessageView.handle(source, &event),
(S::DiffView, E::ZoomRequested(_)) => diffView.handle(source, &event),
(S::RefreshButton, E::Clicked) => refreshButton.handle(source, &event),
(S::RefreshButton, E::RefreshRequested) => repository.handle(source, &event),
(S::Repository, E::AddedToStaged(_)) => (&stagedChangesStore, &mut commitButton).handle(source, &event),
(S::Repository, E::AddedToUnstaged(_)) => unstagedChangesStore.handle(source, &event),
(S::Repository, E::AmendedCommit) => (&stagedChangesStore, &mut commitAmendCheckbox).handle(source, &event),
(S::Repository, E::Committed) => (&stagedChangesStore, &mut commitMessageView, &mut commitAmendCheckbox).handle(source, &event),
(S::Repository, E::RemovedFromStaged(_)) => (&stagedChangesStore, &mut commitButton).handle(source, &event),
(S::Repository, E::RemovedFromUnstaged(_)) => unstagedChangesStore.handle(source, &event),
(S::Repository, E::Refreshed) => (&unstagedChangesStore, &stagedChangesStore).handle(source, &event),
(S::Repository, E::UpdatedInStaged(_)) => stagedChangesStore.handle(source, &event),
(S::Repository, E::UpdatedInUnstaged(_)) => unstagedChangesStore.handle(source, &event),
(S::StagedChangesStore, E::Refreshed) => stagedChangesView.handle(source, &event),
(S::StagedChangesView, E::FileChangeRefreshed(_)) => diffView.handle(source, &event),
(S::StagedChangesView, E::FileChangeSelected(_)) => (&mut diffView, &mut unstagedChangesView).handle(source, &event),
(S::StagedChangesView, E::FileChangeUnselected) => diffView.handle(source, &event),
(S::StagedChangesView, E::RightClicked(_)) => stagedChangesView.handle(source, &event),
(S::StagedChangesView, E::RowActivated(_)) => stagedChangesView.handle(source, &event),
(S::StagedChangesView, E::SelectionChanged(_)) => stagedChangesView.handle(source, &event),
(S::StagedChangesView, E::UnstageRequested(_)) => repository.handle(source, &event),
(S::UnstagedChangesStore, E::Refreshed) => unstagedChangesView.handle(source, &event),
(S::UnstagedChangesView, E::FileChangeRefreshed(_)) => diffView.handle(source, &event),
(S::UnstagedChangesView, E::FileChangeSelected(_)) => (&mut diffView, &mut stagedChangesView).handle(source, &event),
(S::UnstagedChangesView, E::FileChangeUnselected) => diffView.handle(source, &event),
(S::UnstagedChangesView, E::RightClicked(_)) => unstagedChangesView.handle(source, &event),
(S::UnstagedChangesView, E::RowActivated(_)) => unstagedChangesView.handle(source, &event),
(S::UnstagedChangesView, E::SelectionChanged(_)) => unstagedChangesView.handle(source, &event),
(S::UnstagedChangesView, E::StageRequested(_)) => repository.handle(source, &event),
(S::CommitAmendCheckbox, E::CommitAmendDisabled) => (&repository, &mut commitMessageView, &mut commitButton, &mut diffView).handle(source, &event),
(S::CommitAmendCheckbox, E::CommitAmendEnabled) => (&repository, &mut commitMessageView, &mut commitButton, &mut diffView).handle(source, &event),
(S::CommitAmendCheckbox, E::Toggled) => commitAmendCheckbox.handle(source, &event),
(S::CommitButton, E::AmendCommitRequested(_)) => repository.handle(source, &event),
(S::CommitButton, E::Clicked) => commitButton.handle(source, &event),
(S::CommitButton, E::CommitRequested(_)) => repository.handle(source, &event),
(S::CommitDiffViewWidget, E::ZoomRequested(_)) => commitDiffView.handle(source, &event),
(S::CommitLogAuthorFilterEntry, E::TextEntered(_)) => commitLogModelFilter.handle(source, &event),
(S::CommitLogView, E::CommitSelected(_)) => commitDiffView.handle(source, &event),
(S::CommitLogView, E::CommitUnselected) => commitDiffView.handle(source, &event),
(S::CommitLogViewWidget, E::RightClicked(_)) => (),
(S::CommitLogViewWidget, E::RowActivated(_)) => (),
(S::CommitLogViewWidget, E::SelectionChanged(_)) => commitLogView.handle(source, &event),
(S::CommitMessageView, E::BufferChanged) => commitMessageView.handle(source, &event),
(S::CommitMessageView, E::Emptied) => commitButton.handle(source, &event),
(S::CommitMessageView, E::Filled) => commitButton.handle(source, &event),
(S::CommitMessageView, E::ZoomRequested(_)) => commitMessageView.handle(source, &event),
(S::DiffView, E::ZoomRequested(_)) => diffView.handle(source, &event),
(S::MainStack, E::StackChildChanged(_)) => toolBarStack.handle(source, &event),
(S::RefreshButton, E::Clicked) => refreshButton.handle(source, &event),
(S::RefreshButton, E::RefreshRequested) => repository.handle(source, &event),
(S::Repository, E::AddedToStaged(_)) => (&stagedChangesStore, &mut commitButton).handle(source, &event),
(S::Repository, E::AddedToUnstaged(_)) => unstagedChangesStore.handle(source, &event),
(S::Repository, E::AmendedCommit) => (&stagedChangesStore, &mut commitAmendCheckbox).handle(source, &event),
(S::Repository, E::Committed) => (&stagedChangesStore, &mut commitMessageView, &mut commitAmendCheckbox).handle(source, &event),
(S::Repository, E::RemovedFromStaged(_)) => (&stagedChangesStore, &mut commitButton).handle(source, &event),
(S::Repository, E::RemovedFromUnstaged(_)) => unstagedChangesStore.handle(source, &event),
(S::Repository, E::Refreshed) => (&unstagedChangesStore, &stagedChangesStore).handle(source, &event),
(S::Repository, E::UpdatedInStaged(_)) => stagedChangesStore.handle(source, &event),
(S::Repository, E::UpdatedInUnstaged(_)) => unstagedChangesStore.handle(source, &event),
(S::ShowCommitLogFiltersButton, E::Toggled) => commitLogFiltersView.handle(source, &event),
(S::StagedChangesStore, E::Refreshed) => stagedChangesView.handle(source, &event),
(S::StagedChangesView, E::FileChangeRefreshed(_)) => diffView.handle(source, &event),
(S::StagedChangesView, E::FileChangeSelected(_)) => (&mut diffView, &mut unstagedChangesView).handle(source, &event),
(S::StagedChangesView, E::FileChangeUnselected) => diffView.handle(source, &event),
(S::StagedChangesView, E::RightClicked(_)) => stagedChangesView.handle(source, &event),
(S::StagedChangesView, E::RowActivated(_)) => stagedChangesView.handle(source, &event),
(S::StagedChangesView, E::SelectionChanged(_)) => stagedChangesView.handle(source, &event),
(S::StagedChangesView, E::UnstageRequested(_)) => repository.handle(source, &event),
(S::UnstagedChangesStore, E::Refreshed) => unstagedChangesView.handle(source, &event),
(S::UnstagedChangesView, E::FileChangeRefreshed(_)) => diffView.handle(source, &event),
(S::UnstagedChangesView, E::FileChangeSelected(_)) => (&mut diffView, &mut stagedChangesView).handle(source, &event),
(S::UnstagedChangesView, E::FileChangeUnselected) => diffView.handle(source, &event),
(S::UnstagedChangesView, E::RightClicked(_)) => unstagedChangesView.handle(source, &event),
(S::UnstagedChangesView, E::RowActivated(_)) => unstagedChangesView.handle(source, &event),
(S::UnstagedChangesView, E::SelectionChanged(_)) => unstagedChangesView.handle(source, &event),
(S::UnstagedChangesView, E::StageRequested(_)) => repository.handle(source, &event),
(source, event) => handleUnknown(source, event) }

glib::Continue(true)
Expand Down
Loading

0 comments on commit 5d74afb

Please sign in to comment.