I want to use GtkSourceView in my Rust app.
I've created the UI file using Glade. I had to install the component and link it.
This is my Rust code:
use gtk::prelude::*;
fn main() {
if gtk::init().is_err() {
println!("Failed to initialize GTK.");
return;
}
let glade_src = include_str!("user_interface.glade");
let builder = gtk::Builder::new_from_string(glade_src);
let window: gtk::Window = builder.get_object("main_window").unwrap();
window.show_all();
gtk::main();
}
...and the error I'm getting when I try cargo run:
alex#smartalex-bed:~/.repos/codelib/rust/venom$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.05s
Running `target/debug/venom`
(venom:10028): Gtk-ERROR **: 04:25:30.689: failed to add UI: .:17:1 Invalid object type 'GtkSourceView'
Trace/breakpoint trap (core dumped)
I found this and tried to include it in my Cargo.toml, however the error persists.
How can I use GtkSourceView in my Rust app?
This is user_interface.glade:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<requires lib="gtksourceview" version="4.0"/>
<object class="GtkWindow" id="main_window">
<property name="can_focus">False</property>
<child type="titlebar">
<placeholder/>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkSourceView">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="left_margin">2</property>
<property name="right_margin">2</property>
<property name="monospace">True</property>
<property name="show_line_numbers">True</property>
<property name="show_line_marks">True</property>
<property name="tab_width">4</property>
<property name="auto_indent">True</property>
<property name="insert_spaces_instead_of_tabs">True</property>
<property name="show_right_margin">True</property>
<property name="highlight_current_line">True</property>
<property name="smart_backspace">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</interface>
I was able to run the program by adding following line:
sourceview::View::static_type();
The full example code:
use gtk::prelude::*;
fn main() {
if gtk::init().is_err() {
println!("Failed to initialize GTK.");
return;
}
sourceview::View::static_type();
let glade_src = include_str!("user_interface.glade");
let builder = gtk::Builder::new_from_string(glade_src);
let window: gtk::Window = builder.get_object("main_window").unwrap();
window.show_all();
gtk::main();
}
Further, Cargo.toml contains following dependencies:
[dependencies]
gtk = { version = "*", features = ["v3_22"] }
sourceview = "*"
Related
I'm trying to develop an application using GNOME Builder and Glade, but it will not render.
Here's the .ui code.
https:// pastebin.com/JbfqC6Mt
The window is supposed to render 3 buttons in a row.
i'm not sure if it's my version of something or what. I need this to work as i am one of the main programmers of this project.
`<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
<requires lib="gtk" version="4.0"/>
<requires lib="gtk+" version="3.10"/>
<template class="EmucratelauncherWindow" parent="GtkApplicationWindow">
<property name="can-focus">False</property>
<property name="default-width">600</property>
<property name="default-height">300</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="spacing">100</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkHeaderBar" id="header_bar">
<property name="can-focus">False</property>
<child type="end">
<object class="GtkMenuButton">
<property name="can-focus">False</property>
<property name="receives-default">False</property>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>`
I created a simple GUI with a window,entry box ,label and a button using glade and saved as example.glade in my src directory of my rust project.
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow">
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkFixed" id="windows1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">button</property>
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="x">182</property>
<property name="y">146</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="box1">
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="x">68</property>
<property name="y">45</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="x">321</property>
<property name="y">44</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
My aim is to create a simple rust application which changes label name when a value is entered in the entry box and submitted by a button click.
I tried to write a rust backend using this example with gtk-rs v0.9.2 . This is my code
use gtk::glib;
use gtk::prelude::*;
use gtk::{ApplicationWindow, Builder, Button, MessageDialog};
use std::env::args;
fn build_ui(application: >k::Application) {
let glade_src = include_str!("example.glade");
let builder = Builder::from_string(glade_src);
let window: ApplicationWindow = builder.get_object("window1").expect("Couldn't get window1");
window.show_all();
}
fn main() {
let application = gtk::Application::new(
Some("com.github.gtk-rs.examples.builder_basics"),
Default::default(),
)
.expect("Initialization failed...");
application.connect_activate(build_ui);
application.run(&args().collect::<Vec<_>>());
}
When I run this I get below errors
error: extern crate `glib` is private, and cannot be re-exported (error E0365), consider declaring with `pub`
--> src/main.rs:1:5
|
1 | use gtk::glib;
error[E0599]: no method named `connect_activate` found for struct `Application` in the current scope
--> src/main.rs:23:17
|
23 | application.connect_activate(build_ui);
| ^^^^^^^^^^^^^^^^ method not found in `Application`
error[E0599]: no method named `run` found for struct `Application` in the current scope
--> src/main.rs:25:17
|
25 | application.run(&args().collect::<Vec<_>>());
| ^^^ method not found in `Application`
How do we build GUI with glade, gtk-rs in rust?
#Cargo.toml
[dependencies]
gtk = "0.9.2"
I can't say this is the clever/correct way to do this but looking at your errors.
glib is its own dependancy so in your cargo.toml add it.
The minimum i think you need is:
[dependancies]
gio = {version = "*", features =["v2_44"]}
glib = "*"
gtk = {version = "*", features =["v3_16"]}
gdk = "*"
where some of the features i required specifically for my program.
I have my use statements as this:
// imports for GTK UI windows
use gio::prelude::*;
use gtk::prelude::*;
use glib;
use gtk::{Button} // as an example widget
the preludes should help with the missing functions for connecting and running ect.
my main for running is this, similar but not the same as yours:
// gtk UI setup an run
let application =
gtk::Application::new(Some("Program name"), Default::default())
.expect("Initialization failed...");
application.connect_activate(|app| {
build_ui(app);
});
application.run(&args().collect::<Vec<_>>());
Its real hard to program in rust with its lack of good documents, tutorials or help. I had to comb through many sites and copy-past-edit many example codes to get this thing working. First of all we have to specify a version in cargo.toml file and the version has to be our installed gtk3, gio version. Now my dependencies look some thing like this.
[dependencies]
glib = "0.10.3"
[dependencies.gtk]
version = "0.9.2"
features = ["v3_XX"] // XX our gtk3 sub version
[dependencies.gio]
version = "0.9.1"
features = ["v2_XX"] // XX our gio sub version
Then I edited my glade file to set a signal event with handler _on_clicked
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkFixed">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">button</property>
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="_on_clicked" swapped="no"/>
</object>
<packing>
<property name="x">182</property>
<property name="y">146</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="box1">
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="x">68</property>
<property name="y">45</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="x">321</property>
<property name="y">44</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
This is my corresponding logic in rust
extern crate gtk;
extern crate gio;
use gtk::prelude::*;
use gio::prelude::*;
use gtk::{Builder,Window, Button};
use std::env::args;
// the handler
fn on_clicked(param: &[glib::Value]) -> Option<glib::Value> {
println!("on_start_clicked fired!");
None
}
fn build_ui(application: >k::Application) {
let glade_src = include_str!("example.glade");
let builder = Builder::from_string(glade_src);
let window: Window = builder.get_object("window1").expect("Couldn't get window");
window.set_application(Some(application));
window.set_title("Test");
window.connect_delete_event(|_, _| {
gtk::main_quit();
Inhibit(true)
});
// directly calling the button1 without implementing signal
//let btn: Button = builder.get_object("button1").expect("Cant get button");
//btn.connect_clicked(|_| {
//println!("Activated");
//});
builder.connect_signals(|builder, handler_name| {
match handler_name {
// handler_name as defined in the glade file => handler function as defined above
"_on_clicked" => Box::new(on_clicked),
_ => Box::new(|_| {None})
}
});
window.show_all();
}
fn main() {
let application = gtk::Application::new(
Some("com.test.app"),
Default::default(),
)
.expect("Initialization failed...");
application.connect_activate(|app| {
build_ui(app);
});
application.run(&args().collect::<Vec<_>>());
}
I'd like to write a program that has one main window and if I click on a button it changes the content of the window (or something similar) and the user can go back after that to the "home page".
I'm using python3, gtk3 and glade on Ubuntu 19.04.
Here's the example.glade XML file
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkApplicationWindow" id="main">
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkButton" id="button">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
</child>
</object>
</interface>
And here's the Python3 file
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import gi
import os
os.chdir('/home/sources')
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class app:
def __init__(self):
self.gladefile = 'example.glade'
self.builder = Gtk.Builder()
self.builder.add_from_file(self.gladefile)
self.builder.connect_signals(self)
self.window = self.builder.get_object('main')
elf.window = self.builder.get_object('button')
self.window.show()
if __name__ == '__main__':
main = app()
Gtk.main()
I'd like to change the window (but in the same window) to this when the button is pressed
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkApplicationWindow" id="main">
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkNotebook" id="notebook">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkButton" id="but1">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
</child>
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">page 1</property>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkButton" id="but2">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">page 2</property>
</object>
<packing>
<property name="position">1</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkButton" id="but3">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">page 3</property>
</object>
<packing>
<property name="position">2</property>
<property name="tab_fill">False</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
Here is a possible solution using Gtk.Stack
The glade file:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-go-back</property>
</object>
<object class="GtkWindow" id="window">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">window</property>
<property name="window_position">center</property>
<property name="default_width">500</property>
<property name="default_height">400</property>
<signal name="destroy" handler="on_window_destroy" swapped="no"/>
<child>
<placeholder/>
</child>
<child>
<object class="GtkStack" id="stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="home_button">
<property name="label" translatable="yes">Notebook page</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="button_clicked" swapped="no"/>
</object>
<packing>
<property name="name">page0</property>
<property name="title" translatable="yes">page0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="notebook_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Home</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">image1</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="home_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkNotebook" id="notebook">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkButton" id="but1">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
</child>
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">page 1</property>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkButton" id="but2">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">page 2</property>
</object>
<packing>
<property name="position">1</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkButton" id="but3">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">page 3</property>
</object>
<packing>
<property name="position">2</property>
<property name="tab_fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="name">page1</property>
<property name="title" translatable="yes">page1</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
The python file:
#!/usr/bin/env python
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
UI_FILE = "file.glade"
class GUI:
def __init__(self):
self.builder = Gtk.Builder()
self.builder.add_from_file(UI_FILE)
self.builder.connect_signals(self)
window = self.builder.get_object('window')
window.show_all()
def on_window_destroy(self, window):
Gtk.main_quit()
def home_clicked (self, button):
stack = self.builder.get_object('stack')
home_button = self.builder.get_object('home_button')
stack.set_visible_child(home_button)
def button_clicked (self, button):
stack = self.builder.get_object('stack')
notebook_box = self.builder.get_object('notebook_box')
stack.set_visible_child(notebook_box)
app = GUI()
Gtk.main()
I am trying to build a GUI in Rust using GTK, Cairo and Glade. I want to draw a playing field using gtk::DrawingArea but I do not know how to use it. I have this:
extern crate cairo;
extern crate gtk;
use gtk::*;
fn main() {
gtk::init().unwrap(); //init gtk before using it
let glade_src = include_str!("Glade_gui.glade"); //build the glade gui
let builder = gtk::Builder::new_from_string(glade_src);
//get widgets from the gui
let draw_area: gtk::DrawingArea = builder.get_object("zeichenbrett").unwrap();
let window: gtk::Window = builder.get_object("fenster").unwrap();
let size = (600, 600); //define the size for the image
let style_context: gtk::StyleContext = draw_area.get_style_context().unwrap(); //get the style context from the drawing area
let surface: cairo::ImageSurface =
cairo::ImageSurface::create(cairo::Format::ARgb32, size.0, size.1).unwrap(); //build a new ImageSurface to draw on
let context: cairo::Context = cairo::Context::new(&surface); //build a new cairo context from that ImageSurface to draw on
//just a blue area
context.set_source_rgb(0.0, 0.0, 1.0);
context.paint();
context.stroke();
gtk::functions::render_background(
&style_context,
&context,
0.0,
0.0,
size.0 as f64,
size.1 as f64,
); //here I thought that I drew the context cairo::Context to the drawingArea but it seems to do nothing.
window.show_all();
gtk::main();
}
It compiles and runs, but no playing field is shown on the window.
I think I am not using the render_background function correctly, but I do not know how to do it right.
Here is the Glade_gui.glade file:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="fenster">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Reise nach Jerusalem</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">5</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkButton" id="links">
<property name="label" translatable="yes">Left</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="rechts">
<property name="label" translatable="yes">Right</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="quit">
<property name="label" translatable="yes">Quit</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</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="GtkDrawingArea" id="zeichenbrett">
<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>
</object>
</child>
</object>
</interface>
As a note, I have no experience in Rust, so I'll use mainly C examples.
You are attempting to render your GUI before starting gtk::main. The proper way to implement a GTK+ GUI is to add your widgets, connect their draw signal (and any other necessary signals) to your own draw callback function, then run gtk::main.
As an example, take the documentation's simple GtkDrawingArea example found here. In this example, g_signal_connect is used to connect the draw signal to the draw_callback callback function. This way, when the widget is actually created by gtk::main, it will draw your desired image on it.
Your draw_callback function will get a Cairo context as a parameter. You will do all your drawing on that context, so there is no need to create your own. This is also demonstrated in the docs by the use of the pointer cr in the parameters of draw_callback.
All your drawing needs to be done in the draw callback function. It will get called anytime an update is necessary (including creation of the GtkDrawingArea widget), or you can force an update by emitting the queue_draw signal.
The C docs can be a great help even when using a different language, especially if your chosen language doesn't have comprehensive documentation.
Also, the recommended modern way to create a GTK+ application is to use GtkApplication. You may want to look into that.
I created a scheduler as in the example on the Alfresco wiki page but it does not work.
In final form it should delete documents older than 30 days and this cron and lucene query is only for test (it remove in every second all documents from folder test).
I create it in simple amp module and I install it as in tutorial.
My beans:
<bean id="templateActionModelFactory" class="org.alfresco.repo.action.scheduled.FreeMarkerWithLuceneExtensionsModelFactory">
<property name="serviceRegistry">
<ref bean="ServiceRegistry" />
</property>
</bean>
<!-- Action -->
<bean id="deleteNodesActionBean"
class="pl.consdata.eximee.spike.deletescheduler.DeleteNodeActionExecuter"
parent="action-executer">
<property name="nodeService">
<ref bean="nodeService" />
</property>
<property name="transactionService">
<ref bean="TransactionService" />
</property>
</bean>
<!-- Action Definition -->
<bean id="deletefilesActionDefinition"
class="org.alfresco.repo.action.scheduled.SimpleTemplateActionDefinition">
<property name="actionName">
<value>deleteNodesActionBean</value>
</property>
<!-- Required services and the FreeMarker template model -->
<property name="templateActionModelFactory">
<ref bean="templateActionModelFactory" />
</property>
<property name="dictionaryService">
<ref bean="DictionaryService" />
</property>
<property name="actionService">
<ref bean="ActionService" />
</property>
<property name="templateService">
<ref bean="TemplateService" />
</property>
</bean>
<!-- Scheduler -->
<bean id="addClassifiableAspectEveryTenMinutes"
class="org.alfresco.repo.action.scheduled.CronScheduledQueryBasedTemplateActionDefinition">
<property name="transactionMode">
<value>ISOLATED_TRANSACTIONS</value>
</property>
<property name="compensatingActionMode">
<value>IGNORE</value>
</property>
<property name="searchService">
<ref bean="SearchService" />
</property>
<property name="templateService">
<ref bean="TemplateService" />
</property>
<property name="queryLanguage">
<value>lucene</value>
</property>
<property name="stores">
<list>
<value>workspace://SpacesStore</value>
</list>
</property>
<!-- QUERY -->
<property name="queryTemplate">
<value>PATH:"/app:company_home/cm:test/*"</value>
</property>
<property name="cronExpression">
<value>0/1 * * * * ?</value>
</property>
<property name="jobName">
<value>jobA</value>
</property>
<property name="jobGroup">
<value>jobGroup</value>
</property>
<property name="triggerName">
<value>triggerA</value>
</property>
<property name="triggerGroup">
<value>triggerGroup</value>
</property>
<!-- Inject the scheduler - the trigger will be registered with this scheduler -->
<property name="scheduler">
<ref bean="schedulerFactory" />
</property>
<property name="actionService">
<ref bean="ActionService" />
</property>
<property name="templateActionModelFactory">
<ref bean="templateActionModelFactory" />
</property>
<property name="templateActionDefinition">
<ref bean="deletefilesActionDefinition" />
</property>
<property name="transactionService">
<ref bean="TransactionService" />
</property>
<property name="runAsUser">
<value>System</value>
</property>
</bean>
And my action code:
public class DeleteNodeActionExecuter extends ActionExecuterAbstractBase {
public static final String NAME = "deleteNodesActionBean";
private static final Logger LOGGER = LoggerFactory
.getLogger(DeleteNodeActionExecuter.class);
private NodeService nodeService;
private TransactionService transactionService;
public void setNodeService(final NodeService nodeService) {
this.nodeService = nodeService;
}
public void setTransactionService(TransactionService transactionService) {
this.transactionService = transactionService;
}
#Override
protected void executeImpl(Action action, final NodeRef actionedUponNodeRef) {
if (!nodeService.exists(actionedUponNodeRef)) {
LOGGER.warn("< node does not exist!", action, actionedUponNodeRef);
return;
}
transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<Void>() {
public Void execute() throws Throwable {
if (!nodeService.exists(actionedUponNodeRef)) {
// Node has gone away, skip
LOGGER.debug("Node has gone away, skip: "+ actionedUponNodeRef.getId());
return null;
}
LOGGER.debug("deleting node: "
+ actionedUponNodeRef.getId());
nodeService.deleteNode(actionedUponNodeRef);
LOGGER.debug("node deleted");
return null;
}
});
}
#Override
protected void addParameterDefinitions(List<ParameterDefinition> paramList) {
}
}