.
This commit is contained in:
+32
-9
@@ -19,6 +19,7 @@ use oxigraph::io::RdfFormat;
|
||||
use oxigraph::model::vocab::{rdf, rdfs};
|
||||
use oxigraph::model::{BaseDirection, BlankNode, Dataset, NamedNode, NamedNodeRef, NamedOrBlankNode, Quad, Term, Triple};
|
||||
use tracing::{debug, debug_span, error, info, trace};
|
||||
use crate::app::Message::URLInputSubmitted;
|
||||
use crate::rdf::language;
|
||||
use crate::rdf::vocab::rda;
|
||||
use crate::widget::iri_input::iri_input;
|
||||
@@ -57,6 +58,8 @@ pub(crate) enum Message {
|
||||
HideOverwriteConfirmationModal,
|
||||
ConfirmOverwrite,
|
||||
NewDocument(NamedNode),
|
||||
NavigateToPredicate(QuadKey),
|
||||
NavigateToObject(QuadKey),
|
||||
ResetState,
|
||||
}
|
||||
|
||||
@@ -332,15 +335,19 @@ impl Publisher {
|
||||
SearchResultClickAction::URLInput => None,
|
||||
};
|
||||
|
||||
let (id, window_task) = window::open(Settings::default());
|
||||
self.search_state = Some(SearchState {
|
||||
window_id: id,
|
||||
action,
|
||||
entity_selection: None,
|
||||
query: String::new(),
|
||||
results: Vec::new(),
|
||||
});
|
||||
task = window_task.map(|_| Message::None);
|
||||
if let Some(search_state) = &mut self.search_state {
|
||||
search_state.action = action;
|
||||
} else {
|
||||
let (id, window_task) = window::open(Settings::default());
|
||||
self.search_state = Some(SearchState {
|
||||
window_id: id,
|
||||
action,
|
||||
entity_selection: None,
|
||||
query: String::new(),
|
||||
results: Vec::new(),
|
||||
});
|
||||
task = window_task.map(|_| Message::None);
|
||||
}
|
||||
|
||||
if let Some(selected_entity_class) = selected_entity_class {
|
||||
let selection = self.ontology.info(&selected_entity_class.into_owned(), &*language::ENGLISH_OR_UNTAGGED);
|
||||
@@ -525,6 +532,20 @@ impl Publisher {
|
||||
self.show_new_document_buttons = false;
|
||||
self.show_overwrite_confirmation = false;
|
||||
}
|
||||
Message::NavigateToPredicate(key) => {
|
||||
if let Some(quad) = self.document.dataset_mut().quads.get_mut(key) {
|
||||
self.url_input = quad.predicate.as_str().to_string();
|
||||
task = Task::done(URLInputSubmitted);
|
||||
}
|
||||
}
|
||||
Message::NavigateToObject(key) => {
|
||||
if let Some(quad) = self.document.dataset_mut().quads.get_mut(key) {
|
||||
if let Term::NamedNode(node) = &quad.object {
|
||||
self.url_input = node.as_str().to_string();
|
||||
task = Task::done(URLInputSubmitted);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
task
|
||||
@@ -563,6 +584,7 @@ impl Publisher {
|
||||
} else {
|
||||
predicate_input_base.on_input(move |value| Message::PredicateUpdated(key, value))
|
||||
.on_control_click(Message::OpenQueryWindow(SearchResultClickAction::Predicate(key)))
|
||||
.on_shift_click(Message::NavigateToPredicate(key))
|
||||
};
|
||||
|
||||
let term = TermHelper::new(&triple.object);
|
||||
@@ -592,6 +614,7 @@ impl Publisher {
|
||||
object_input_base.align_x(value_alignment)
|
||||
.on_input(move |value| Message::ObjectUpdated(key, value))
|
||||
.on_control_click(Message::OpenQueryWindow(SearchResultClickAction::Object(key)))
|
||||
.on_shift_click(Message::NavigateToObject(key))
|
||||
};
|
||||
|
||||
let selected_datatype = term.datatype().map(|node| self.ontology.abbreviate(node));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::error;
|
||||
use crate::rdf::vocab::gl;
|
||||
use oxigraph::model::vocab::{rdf, rdfs, xsd};
|
||||
use oxigraph::model::{Dataset, LiteralRef, NamedNode, NamedNodeRef, NamedOrBlankNode, NamedOrBlankNodeRef, Term, TermRef, Triple, TripleRef};
|
||||
use oxigraph::model::{Dataset, Graph, LiteralRef, NamedNode, NamedNodeRef, NamedOrBlankNode, NamedOrBlankNodeRef, Term, TermRef, Triple, TripleRef};
|
||||
use oxigraph::sparql::{QueryResults, SparqlEvaluator};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||
use std::fmt::Display;
|
||||
@@ -327,12 +327,17 @@ WHERE {{
|
||||
|
||||
pub fn exclude_read_only(&self) -> impl Fn(TripleRef<'_>) -> bool + 'static {
|
||||
let true_term = TermRef::Literal(LiteralRef::new_typed_literal("true", xsd::BOOLEAN));
|
||||
let dataset = self.store
|
||||
let read_only_graph = self.store
|
||||
.quads_for_pattern(None, Some(gl::READ_ONLY), Some(true_term), None)
|
||||
.filter_map(Result::ok)
|
||||
.collect::<Dataset>();
|
||||
.map(Triple::from)
|
||||
.collect::<Graph>();
|
||||
move |triple| {
|
||||
dataset.quads_for_subject(triple.subject).count() == 0
|
||||
if triple.predicate == rdf::TYPE && let TermRef::NamedNode(class) = triple.object {
|
||||
read_only_graph.triples_for_subject(class).count() == 0
|
||||
} else {
|
||||
read_only_graph.triples_for_subject(triple.predicate).count() == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ use iced::widget::text_input::Catalog;
|
||||
|
||||
pub struct State {
|
||||
control: bool,
|
||||
shift: bool,
|
||||
}
|
||||
|
||||
pub struct IriInput<'a, Message, Theme, Renderer>
|
||||
@@ -19,6 +20,7 @@ where
|
||||
{
|
||||
prefixes: &'a BTreeMap<String, String>,
|
||||
on_control_click: Option<Message>,
|
||||
on_shift_click: Option<Message>,
|
||||
text_input: widget::TextInput<'a, Message, Theme, Renderer>,
|
||||
}
|
||||
|
||||
@@ -50,6 +52,7 @@ where
|
||||
Self {
|
||||
prefixes,
|
||||
on_control_click: None,
|
||||
on_shift_click: None,
|
||||
text_input,
|
||||
}
|
||||
}
|
||||
@@ -64,6 +67,11 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_shift_click(mut self, on_shift_click: Message) -> Self {
|
||||
self.on_shift_click = Some(on_shift_click);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_input(mut self, on_input: impl Fn(String) -> Message + 'a) -> Self {
|
||||
let wrapped = move |value: String| {
|
||||
let expanded_value = expand(self.prefixes, &value);
|
||||
@@ -126,6 +134,7 @@ where
|
||||
fn state(&self) -> tree::State {
|
||||
tree::State::new(State {
|
||||
control: false,
|
||||
shift: false,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -139,11 +148,19 @@ where
|
||||
match event {
|
||||
Event::Keyboard(keyboard::Event::ModifiersChanged(modifiers)) => {
|
||||
state.control = modifiers.control();
|
||||
state.shift = modifiers.shift();
|
||||
}
|
||||
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
|
||||
if cursor.is_over(layout.bounds()) && state.control && let Some(on_control_click) = &self.on_control_click {
|
||||
shell.publish(on_control_click.clone());
|
||||
shell.capture_event();
|
||||
if cursor.is_over(layout.bounds()) {
|
||||
if state.control && let Some(on_control_click) = &self.on_control_click {
|
||||
shell.publish(on_control_click.clone());
|
||||
shell.capture_event();
|
||||
}
|
||||
|
||||
if state.shift && let Some(on_shift_click) = &self.on_shift_click {
|
||||
shell.publish(on_shift_click.clone());
|
||||
shell.capture_event();
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@@ -154,10 +171,13 @@ where
|
||||
|
||||
fn mouse_interaction(&self, tree: &Tree, layout: Layout<'_>, cursor: Cursor, viewport: &Rectangle, renderer: &Renderer) -> Interaction {
|
||||
let state = tree.state.downcast_ref::<State>();
|
||||
if cursor.is_over(layout.bounds()) && state.control {
|
||||
Interaction::Pointer
|
||||
} else {
|
||||
Widget::mouse_interaction(&self.text_input, tree, layout, cursor, viewport, renderer)
|
||||
}
|
||||
let interaction = if cursor.is_over(layout.bounds()) {
|
||||
if (state.control && self.on_control_click.is_some()) ||
|
||||
(state.shift && self.on_shift_click.is_some()) {
|
||||
Some(Interaction::Pointer)
|
||||
} else { None }
|
||||
} else { None };
|
||||
|
||||
interaction.unwrap_or_else(|| Widget::mouse_interaction(&self.text_input, tree, layout, cursor, viewport, renderer))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user