A table with system processes and a qml chart
parent
8043efe34e
commit
2cc3d2ccf9
|
@ -22,6 +22,17 @@ add_custom_command(
|
|||
DEPENDS rust_qt_binding_generator tree.json
|
||||
)
|
||||
|
||||
# generate c++ and rust code from processes.json
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/rust/src/processes_interface.rs"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/rust/src/processes_types.rs"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/Processes.h"
|
||||
# if the cpp file is marked GENERATED, CMake will not check it for moc
|
||||
# "${CMAKE_CURRENT_SOURCE_DIR}/src/Processes.cpp"
|
||||
COMMAND ${CMAKE_BINARY_DIR}/src/rust_qt_binding_generator "${CMAKE_CURRENT_SOURCE_DIR}/processes.json"
|
||||
DEPENDS rust_qt_binding_generator processes.json
|
||||
)
|
||||
|
||||
# generate c++ and rust code from time_series.json
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/rust/src/time_series_interface.rs"
|
||||
|
@ -47,6 +58,9 @@ add_custom_command(
|
|||
rust/src/time_series_interface.rs
|
||||
rust/src/time_series_implementation.rs
|
||||
rust/src/time_series_types.rs
|
||||
rust/src/processes_interface.rs
|
||||
rust/src/processes_implementation.rs
|
||||
rust/src/processes_types.rs
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/rust"
|
||||
)
|
||||
add_custom_target(rust_target DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/rust/${RUST_TARGET_DIR}/librust.a")
|
||||
|
@ -65,7 +79,7 @@ if (Qt5Charts_FOUND)
|
|||
endif()
|
||||
|
||||
set(Demo_SRCS src/main.cpp src/Fibonacci.cpp src/Tree.cpp src/TimeSeries.cpp
|
||||
resource_file.qrc)
|
||||
src/Processes.cpp resource_file.qrc)
|
||||
|
||||
add_executable(Demo ${Demo_SRCS})
|
||||
add_dependencies(Demo rust_target)
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
import QtQuick 2.6
|
||||
import QtCharts 2.2
|
||||
|
||||
Item {
|
||||
ChartView {
|
||||
id: chart
|
||||
anchors.fill: parent
|
||||
legend.alignment: Qt.AlignBottom
|
||||
antialiasing: true
|
||||
|
||||
DateTimeAxis {
|
||||
id: axisX
|
||||
titleText: "Date"
|
||||
format: "MMM yyyy"
|
||||
tickCount: 10
|
||||
//alignment: Qt.AlignBottom
|
||||
}
|
||||
|
||||
ValueAxis {
|
||||
id: axisY
|
||||
titleText: "Sunspots count"
|
||||
}
|
||||
|
||||
LineSeries {
|
||||
id: cpu
|
||||
name: "CPU"
|
||||
axisX: axisX
|
||||
axisY: axisY
|
||||
}
|
||||
|
||||
VXYModelMapper {
|
||||
model: timeSeries
|
||||
xColumn: 0
|
||||
yColumn: 1
|
||||
series: cpu
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,22 +12,35 @@ ApplicationWindow {
|
|||
visible: true
|
||||
ItemSelectionModel {
|
||||
id: selectionModel
|
||||
model: fsModel
|
||||
model: sortedFileSystem
|
||||
}
|
||||
TabView {
|
||||
id: tabView
|
||||
anchors.fill: parent
|
||||
onCountChanged: {
|
||||
for (var i = 0; i < tabView.count; ++i) {
|
||||
if (tabView.getTab(i).title == initialTab) {
|
||||
tabView.currentIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
Tab {
|
||||
title: "style"
|
||||
ComboBox {
|
||||
currentIndex: qtquickIndex
|
||||
model: styles
|
||||
textRole: "display"
|
||||
onCurrentIndexChanged: {
|
||||
if (currentIndex != qtquickIndex) {
|
||||
widgets.currentIndex = currentIndex;
|
||||
application.close();
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 5
|
||||
ComboBox {
|
||||
currentIndex: qtquickIndex
|
||||
model: styles
|
||||
textRole: "display"
|
||||
onCurrentIndexChanged: {
|
||||
if (currentIndex != qtquickIndex) {
|
||||
widgets.currentIndex = currentIndex;
|
||||
application.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {}
|
||||
}
|
||||
}
|
||||
Tab {
|
||||
|
@ -61,7 +74,9 @@ ApplicationWindow {
|
|||
title: "tree"
|
||||
TreeView {
|
||||
id: treeView
|
||||
model: sortedFsModel
|
||||
model: sortedFileSystem
|
||||
sortIndicatorVisible: true
|
||||
alternatingRowColors: true
|
||||
selection: selectionModel
|
||||
TableViewColumn {
|
||||
title: "Name"
|
||||
|
@ -78,5 +93,65 @@ ApplicationWindow {
|
|||
}
|
||||
}
|
||||
}
|
||||
Tab {
|
||||
title: "processes"
|
||||
TreeView {
|
||||
id: processView
|
||||
model: processes
|
||||
sortIndicatorVisible: true
|
||||
alternatingRowColors: true
|
||||
TableViewColumn {
|
||||
title: "pid"
|
||||
role: "pid"
|
||||
}
|
||||
TableViewColumn {
|
||||
title: "name"
|
||||
role: "name"
|
||||
}
|
||||
TableViewColumn {
|
||||
title: "cpu"
|
||||
role: "cpu"
|
||||
}
|
||||
onSortIndicatorColumnChanged: {
|
||||
switch (processView.sortIndicatorColumn) {
|
||||
case 0: model.sortRole = Qt.DisplayRole; break;
|
||||
}
|
||||
console.log(model.sortRole);
|
||||
}
|
||||
onSortIndicatorOrderChanged: {
|
||||
console.log(model.sort);
|
||||
model.sort(Qt.DisplayRole, processView.sortIndicatorOrderChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
Tab {
|
||||
id: chartTab
|
||||
title: "chart"
|
||||
// Row {
|
||||
// anchors.fill: parent
|
||||
Text {
|
||||
text: "YAYAYA"
|
||||
anchors.left: parent.left
|
||||
anchors.right: i.left
|
||||
}
|
||||
Item {
|
||||
id: i
|
||||
anchors.right: parent.right
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "QtChart is not available.";
|
||||
visible: chartLoader.status !== Loader.Ready
|
||||
}
|
||||
Loader {
|
||||
width: 100
|
||||
|
||||
id: chartLoader
|
||||
// anchors.fill: parent
|
||||
source: "chart.qml"
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"cppFile": "src/Processes.cpp",
|
||||
"rust": {
|
||||
"dir": "rust",
|
||||
"interfaceModule": "processes_interface",
|
||||
"implementationModule": "processes_implementation",
|
||||
"typesModule": "processes_types"
|
||||
},
|
||||
"objects": {
|
||||
"Processes": {
|
||||
"type": "UniformTree",
|
||||
"properties": {
|
||||
},
|
||||
"itemProperties": {
|
||||
"pid": {
|
||||
"type": "quint32",
|
||||
"roles": [ ["display"] ]
|
||||
},
|
||||
"name": {
|
||||
"type": "QString",
|
||||
"roles": [ [], ["display"] ]
|
||||
},
|
||||
"cpuUsage": {
|
||||
"type": "float",
|
||||
"roles": [ [], [], ["display"] ]
|
||||
},
|
||||
"memory": {
|
||||
"type": "quint64",
|
||||
"roles": [ [], [], [], ["display"] ]
|
||||
},
|
||||
"uid": {
|
||||
"type": "quint32"
|
||||
},
|
||||
"cpuPercentage": {
|
||||
"type": "quint8"
|
||||
},
|
||||
"cmd": {
|
||||
"type": "QString"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>demo.qml</file>
|
||||
<file>chart.qml</file>
|
||||
<file>demo-qtquick2.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -4,6 +4,7 @@ version = "0.1.0"
|
|||
|
||||
[dependencies]
|
||||
libc = "*"
|
||||
sysinfo = "0.3"
|
||||
|
||||
[lib]
|
||||
name = "rust"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
extern crate libc;
|
||||
extern crate sysinfo;
|
||||
|
||||
mod fibonacci_types;
|
||||
mod fibonacci_implementation;
|
||||
|
@ -11,3 +12,7 @@ pub mod interface;
|
|||
mod time_series_types;
|
||||
mod time_series_implementation;
|
||||
pub mod time_series_interface;
|
||||
|
||||
mod processes_types;
|
||||
mod processes_implementation;
|
||||
pub mod processes_interface;
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
use types::*;
|
||||
use processes_interface::*;
|
||||
use sysinfo::*;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::collections::HashMap;
|
||||
use libc::pid_t;
|
||||
use std::{thread, time};
|
||||
|
||||
struct ProcessItem {
|
||||
parent: Option<usize>,
|
||||
row: usize,
|
||||
tasks: Vec<usize>,
|
||||
process: Process
|
||||
}
|
||||
|
||||
#[derive (Default)]
|
||||
struct ProcessTree {
|
||||
top: Vec<usize>,
|
||||
processes: Vec<ProcessItem>,
|
||||
cpusum: f32
|
||||
}
|
||||
|
||||
pub struct Processes {
|
||||
emit: ProcessesEmitter,
|
||||
model: ProcessesUniformTree,
|
||||
p: ProcessTree,
|
||||
incoming: Arc<Mutex<Option<ProcessTree>>>
|
||||
}
|
||||
|
||||
fn handle_tasks(tasks: &HashMap<pid_t,Process>,
|
||||
mut processes: &mut Vec<ProcessItem>,
|
||||
parentPos: Option<usize>) -> (Vec<usize>, f32) {
|
||||
let mut t = Vec::new();
|
||||
let mut i = 0;
|
||||
let mut cpusum = 0.0;
|
||||
for process in tasks.values() {
|
||||
let pos = processes.len();
|
||||
t.push(pos);
|
||||
processes.push(ProcessItem {
|
||||
parent: parentPos,
|
||||
row: i,
|
||||
tasks: Vec::new(),
|
||||
process: process.clone()
|
||||
});
|
||||
let (t, s) = handle_tasks(&process.tasks, &mut processes, Some(pos));
|
||||
processes[pos].tasks = t;
|
||||
cpusum += process.cpu_usage + s;
|
||||
i += 1;
|
||||
}
|
||||
(t, cpusum)
|
||||
}
|
||||
|
||||
fn update() -> ProcessTree {
|
||||
let mut p = ProcessTree::default();
|
||||
let mut sysinfo = System::new();
|
||||
sysinfo.refresh_processes();
|
||||
let (top, cpusum) = handle_tasks(sysinfo.get_process_list(),
|
||||
&mut p.processes, None);
|
||||
p.top = top;
|
||||
p.cpusum = cpusum;
|
||||
p
|
||||
}
|
||||
|
||||
fn update_thread(emit: ProcessesEmitter, incoming: Arc<Mutex<Option<ProcessTree>>>) {
|
||||
thread::spawn(move || {
|
||||
let second = time::Duration::new(1, 0);
|
||||
while true {
|
||||
*incoming.lock().unwrap() = Some(update());
|
||||
emit.new_data_ready(None);
|
||||
thread::sleep(second);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
impl ProcessesTrait for Processes {
|
||||
fn create(emit: ProcessesEmitter, model: ProcessesUniformTree) -> Processes {
|
||||
let mut p = Processes {
|
||||
emit: emit.clone(),
|
||||
model: model,
|
||||
p: ProcessTree::default(),
|
||||
incoming: Arc::new(Mutex::new(None))
|
||||
};
|
||||
update_thread(emit, p.incoming.clone());
|
||||
p
|
||||
}
|
||||
fn emit(&self) -> &ProcessesEmitter {
|
||||
&self.emit
|
||||
}
|
||||
fn row_count(&self, item: Option<usize>) -> usize {
|
||||
if let Some(item) = item {
|
||||
self.p.processes[item].tasks.len()
|
||||
} else {
|
||||
self.p.top.len()
|
||||
}
|
||||
}
|
||||
fn index(&self, item: Option<usize>, row: usize) -> usize {
|
||||
if let Some(item) = item {
|
||||
self.p.processes[item].tasks[row]
|
||||
} else {
|
||||
self.p.top[row]
|
||||
}
|
||||
}
|
||||
fn parent(&self, item: usize) -> Option<usize> {
|
||||
self.p.processes[item].parent
|
||||
}
|
||||
fn can_fetch_more(&self, item: Option<usize>) -> bool {
|
||||
if let Ok(ref incoming) = self.incoming.try_lock() {
|
||||
incoming.is_some()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
fn fetch_more(&mut self, item: Option<usize>) {
|
||||
if let Ok(ref mut incoming) = self.incoming.try_lock() {
|
||||
if let Some(more) = incoming.take() {
|
||||
self.model.begin_reset_model();
|
||||
self.p = more;
|
||||
self.model.end_reset_model();
|
||||
}
|
||||
}
|
||||
}
|
||||
fn row(&self, item: usize) -> usize {
|
||||
self.p.processes[item].row
|
||||
}
|
||||
fn pid(&self, item: usize) -> u32 {
|
||||
self.p.processes[item].process.pid as u32
|
||||
}
|
||||
fn uid(&self, item: usize) -> u32 {
|
||||
self.p.processes[item].process.uid as u32
|
||||
}
|
||||
fn cpu_usage(&self, item: usize) -> f32 {
|
||||
self.p.processes[item].process.cpu_usage
|
||||
}
|
||||
fn cpu_percentage(&self, item: usize) -> u8 {
|
||||
let cpu = self.p.processes[item].process.cpu_usage / self.p.cpusum;
|
||||
(cpu * 100.0) as u8
|
||||
}
|
||||
fn memory(&self, item: usize) -> u64 {
|
||||
self.p.processes[item].process.memory
|
||||
}
|
||||
fn name(&self, item: usize) -> String {
|
||||
self.p.processes[item].process.name.clone()
|
||||
}
|
||||
fn cmd(&self, item: usize) -> String {
|
||||
self.p.processes[item].process.cmd.join(" ")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
/* generated by rust_qt_binding_generator */
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(mutex_atomic, needless_pass_by_value)]
|
||||
#![allow(unused_imports)]
|
||||
use libc::{c_int, c_void};
|
||||
use types::*;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::ptr::null;
|
||||
|
||||
use processes_implementation::*;
|
||||
|
||||
pub struct ProcessesQObject {}
|
||||
|
||||
#[derive (Clone)]
|
||||
pub struct ProcessesEmitter {
|
||||
qobject: Arc<Mutex<*const ProcessesQObject>>,
|
||||
new_data_ready: fn(*const ProcessesQObject, item: usize, valid: bool),
|
||||
}
|
||||
|
||||
unsafe impl Send for ProcessesEmitter {}
|
||||
|
||||
impl ProcessesEmitter {
|
||||
fn clear(&self) {
|
||||
*self.qobject.lock().unwrap() = null();
|
||||
}
|
||||
pub fn new_data_ready(&self, item: Option<usize>) {
|
||||
let ptr = *self.qobject.lock().unwrap();
|
||||
if !ptr.is_null() {
|
||||
(self.new_data_ready)(ptr, item.unwrap_or(13), item.is_some());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ProcessesUniformTree {
|
||||
qobject: *const ProcessesQObject,
|
||||
begin_reset_model: fn(*const ProcessesQObject),
|
||||
end_reset_model: fn(*const ProcessesQObject),
|
||||
begin_insert_rows: fn(*const ProcessesQObject, item: usize, valid: bool, usize, usize),
|
||||
end_insert_rows: fn(*const ProcessesQObject),
|
||||
begin_remove_rows: fn(*const ProcessesQObject, item: usize, valid: bool, usize, usize),
|
||||
end_remove_rows: fn(*const ProcessesQObject),
|
||||
}
|
||||
|
||||
impl ProcessesUniformTree {
|
||||
pub fn begin_reset_model(&self) {
|
||||
(self.begin_reset_model)(self.qobject);
|
||||
}
|
||||
pub fn end_reset_model(&self) {
|
||||
(self.end_reset_model)(self.qobject);
|
||||
}
|
||||
pub fn begin_insert_rows(&self, item: Option<usize>, first: usize, last: usize) {
|
||||
(self.begin_insert_rows)(self.qobject, item.unwrap_or(13), item.is_some(), first, last);
|
||||
}
|
||||
pub fn end_insert_rows(&self) {
|
||||
(self.end_insert_rows)(self.qobject);
|
||||
}
|
||||
pub fn begin_remove_rows(&self, item: Option<usize>, first: usize, last: usize) {
|
||||
(self.begin_remove_rows)(self.qobject, item.unwrap_or(13), item.is_some(), first, last);
|
||||
}
|
||||
pub fn end_remove_rows(&self) {
|
||||
(self.end_remove_rows)(self.qobject);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ProcessesTrait {
|
||||
fn create(emit: ProcessesEmitter, model: ProcessesUniformTree) -> Self;
|
||||
fn emit(&self) -> &ProcessesEmitter;
|
||||
fn row_count(&self, Option<usize>) -> usize;
|
||||
fn can_fetch_more(&self, Option<usize>) -> bool { false }
|
||||
fn fetch_more(&mut self, Option<usize>) {}
|
||||
fn sort(&mut self, u8, SortOrder) {}
|
||||
fn index(&self, item: Option<usize>, row: usize) -> usize;
|
||||
fn parent(&self, item: usize) -> Option<usize>;
|
||||
fn row(&self, item: usize) -> usize;
|
||||
fn cmd(&self, item: usize) -> String;
|
||||
fn cpu_percentage(&self, item: usize) -> u8;
|
||||
fn cpu_usage(&self, item: usize) -> f32;
|
||||
fn memory(&self, item: usize) -> u64;
|
||||
fn name(&self, item: usize) -> String;
|
||||
fn pid(&self, item: usize) -> u32;
|
||||
fn uid(&self, item: usize) -> u32;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn processes_new(qobject: *const ProcessesQObject,
|
||||
new_data_ready: fn(*const ProcessesQObject, item: usize, valid: bool),
|
||||
begin_reset_model: fn(*const ProcessesQObject),
|
||||
end_reset_model: fn(*const ProcessesQObject),
|
||||
begin_insert_rows: fn(*const ProcessesQObject, item: usize, valid: bool,
|
||||
usize,
|
||||
usize),
|
||||
end_insert_rows: fn(*const ProcessesQObject),
|
||||
begin_remove_rows: fn(*const ProcessesQObject, item: usize, valid: bool,
|
||||
usize,
|
||||
usize),
|
||||
end_remove_rows: fn(*const ProcessesQObject))
|
||||
-> *mut Processes {
|
||||
let emit = ProcessesEmitter {
|
||||
qobject: Arc::new(Mutex::new(qobject)),
|
||||
new_data_ready: new_data_ready,
|
||||
};
|
||||
let model = ProcessesUniformTree {
|
||||
qobject: qobject,
|
||||
begin_reset_model: begin_reset_model,
|
||||
end_reset_model: end_reset_model,
|
||||
begin_insert_rows: begin_insert_rows,
|
||||
end_insert_rows: end_insert_rows,
|
||||
begin_remove_rows: begin_remove_rows,
|
||||
end_remove_rows: end_remove_rows,
|
||||
};
|
||||
let d = Processes::create(emit, model);
|
||||
Box::into_raw(Box::new(d))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_free(ptr: *mut Processes) {
|
||||
Box::from_raw(ptr).emit().clear();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_row_count(ptr: *const Processes, item: usize, valid: bool) -> c_int {
|
||||
if valid {
|
||||
(&*ptr).row_count(Some(item)) as c_int
|
||||
} else {
|
||||
(&*ptr).row_count(None) as c_int
|
||||
}
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_can_fetch_more(ptr: *const Processes, item: usize, valid: bool) -> bool {
|
||||
if valid {
|
||||
(&*ptr).can_fetch_more(Some(item))
|
||||
} else {
|
||||
(&*ptr).can_fetch_more(None)
|
||||
}
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_fetch_more(ptr: *mut Processes, item: usize, valid: bool) {
|
||||
if valid {
|
||||
(&mut *ptr).fetch_more(Some(item))
|
||||
} else {
|
||||
(&mut *ptr).fetch_more(None)
|
||||
}
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_sort(ptr: *mut Processes, column: u8, order: SortOrder) {
|
||||
(&mut *ptr).sort(column, order)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_index(ptr: *const Processes, item: usize, valid: bool, row: c_int) -> usize {
|
||||
if !valid {
|
||||
(&*ptr).index(None, row as usize)
|
||||
} else {
|
||||
(&*ptr).index(Some(item), row as usize)
|
||||
}
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_parent(ptr: *const Processes, index: usize) -> QModelIndex {
|
||||
if let Some(parent) = (&*ptr).parent(index) {
|
||||
QModelIndex::create((&*ptr).row(parent) as c_int, parent)
|
||||
} else {
|
||||
QModelIndex::invalid()
|
||||
}
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_row(ptr: *const Processes, item: usize) -> c_int {
|
||||
(&*ptr).row(item) as c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_data_cmd(ptr: *const Processes, item: usize,
|
||||
d: *mut c_void,
|
||||
set: fn(*mut c_void, QString)) {
|
||||
let data = (&*ptr).cmd(item);
|
||||
set(d, QString::from(&data));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_data_cpu_percentage(ptr: *const Processes, item: usize) -> u8 {
|
||||
(&*ptr).cpu_percentage(item).into()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_data_cpu_usage(ptr: *const Processes, item: usize) -> f32 {
|
||||
(&*ptr).cpu_usage(item).into()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_data_memory(ptr: *const Processes, item: usize) -> u64 {
|
||||
(&*ptr).memory(item).into()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_data_name(ptr: *const Processes, item: usize,
|
||||
d: *mut c_void,
|
||||
set: fn(*mut c_void, QString)) {
|
||||
let data = (&*ptr).name(item);
|
||||
set(d, QString::from(&data));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_data_pid(ptr: *const Processes, item: usize) -> u32 {
|
||||
(&*ptr).pid(item).into()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn processes_data_uid(ptr: *const Processes, item: usize) -> u32 {
|
||||
(&*ptr).uid(item).into()
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/* generated by rust_qt_binding_generator */
|
||||
#![allow(dead_code)]
|
||||
use std::slice;
|
||||
use libc::{c_int, uint8_t, uint16_t};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct COption<T> {
|
||||
data: T,
|
||||
some: bool,
|
||||
}
|
||||
|
||||
impl<T> From<Option<T>> for COption<T> where T: Default {
|
||||
fn from(t: Option<T>) -> COption <T> {
|
||||
if let Some(v) = t {
|
||||
COption {
|
||||
data: v,
|
||||
some: true
|
||||
}
|
||||
} else {
|
||||
COption {
|
||||
data: T::default(),
|
||||
some: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct QString {
|
||||
data: *const uint8_t,
|
||||
len: c_int,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct QStringIn {
|
||||
data: *const uint16_t,
|
||||
len: c_int,
|
||||
}
|
||||
|
||||
impl QStringIn {
|
||||
pub fn convert(&self) -> String {
|
||||
let data = unsafe { slice::from_raw_parts(self.data, self.len as usize) };
|
||||
String::from_utf16_lossy(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a String> for QString {
|
||||
fn from(string: &'a String) -> QString {
|
||||
QString {
|
||||
len: string.len() as c_int,
|
||||
data: string.as_ptr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct QByteArray {
|
||||
data: *const uint8_t,
|
||||
len: c_int,
|
||||
}
|
||||
|
||||
impl QByteArray {
|
||||
pub fn convert(&self) -> Vec<u8> {
|
||||
let data = unsafe { slice::from_raw_parts(self.data, self.len as usize) };
|
||||
Vec::from(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Vec<u8>> for QByteArray {
|
||||
fn from(value: &'a Vec<u8>) -> QByteArray {
|
||||
QByteArray {
|
||||
len: value.len() as c_int,
|
||||
data: value.as_ptr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct QModelIndex {
|
||||
row: c_int,
|
||||
internal_id: usize,
|
||||
}
|
||||
|
||||
impl QModelIndex {
|
||||
pub fn invalid() -> QModelIndex {
|
||||
QModelIndex {
|
||||
row: -1,
|
||||
internal_id: 0,
|
||||
}
|
||||
}
|
||||
pub fn create(row: c_int, id: usize) -> QModelIndex {
|
||||
QModelIndex {
|
||||
row: row,
|
||||
internal_id: id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum SortOrder {
|
||||
Ascending = 0,
|
||||
Descending = 1
|
||||
}
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
/* generated by rust_qt_binding_generator */
|
||||
#include "Processes.h"
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
struct option {
|
||||
public:
|
||||
T value;
|
||||
bool some;
|
||||
operator QVariant() const {
|
||||
if (some) {
|
||||
return QVariant(value);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
};
|
||||
struct qbytearray_t {
|
||||
private:
|
||||
const char* data;
|
||||
int len;
|
||||
public:
|
||||
qbytearray_t(const QByteArray& v):
|
||||
data(v.data()),
|
||||
len(v.size()) {
|
||||
}
|
||||
operator QByteArray() const {
|
||||
return QByteArray(data, len);
|
||||
}
|
||||
};
|
||||
struct qstring_t {
|
||||
private:
|
||||
const void* data;
|
||||
int len;
|
||||
public:
|
||||
qstring_t(const QString& v):
|
||||
data(static_cast<const void*>(v.utf16())),
|
||||
len(v.size()) {
|
||||
}
|
||||
operator QString() const {
|
||||
return QString::fromUtf8(static_cast<const char*>(data), len);
|
||||
}
|
||||
};
|
||||
struct qmodelindex_t {
|
||||
int row;
|
||||
quintptr id;
|
||||
};
|
||||
}
|
||||
typedef void (*qstring_set)(QString*, qstring_t*);
|
||||
void set_qstring(QString* v, qstring_t* val) {
|
||||
*v = *val;
|
||||
}
|
||||
typedef void (*qbytearray_set)(QByteArray*, qbytearray_t*);
|
||||
void set_qbytearray(QByteArray* v, qbytearray_t* val) {
|
||||
*v = *val;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void processes_data_cmd(const Processes::Private*, quintptr, QString*, qstring_set);
|
||||
quint8 processes_data_cpu_percentage(const Processes::Private*, quintptr);
|
||||
float processes_data_cpu_usage(const Processes::Private*, quintptr);
|
||||
quint64 processes_data_memory(const Processes::Private*, quintptr);
|
||||
void processes_data_name(const Processes::Private*, quintptr, QString*, qstring_set);
|
||||
uint processes_data_pid(const Processes::Private*, quintptr);
|
||||
uint processes_data_uid(const Processes::Private*, quintptr);
|
||||
void processes_sort(Processes::Private*, unsigned char column, Qt::SortOrder order = Qt::AscendingOrder);
|
||||
|
||||
int processes_row_count(const Processes::Private*, quintptr, bool);
|
||||
bool processes_can_fetch_more(const Processes::Private*, quintptr, bool);
|
||||
void processes_fetch_more(Processes::Private*, quintptr, bool);
|
||||
quintptr processes_index(const Processes::Private*, quintptr, bool, int);
|
||||
qmodelindex_t processes_parent(const Processes::Private*, quintptr);
|
||||
int processes_row(const Processes::Private*, quintptr);
|
||||
}
|
||||
int Processes::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
bool Processes::hasChildren(const QModelIndex &parent) const
|
||||
{
|
||||
return rowCount(parent) > 0;
|
||||
}
|
||||
|
||||
int Processes::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid() && parent.column() != 0) {
|
||||
return 0;
|
||||
}
|
||||
return processes_row_count(d, parent.internalId(), parent.isValid());
|
||||
}
|
||||
|
||||
QModelIndex Processes::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (row < 0 || column < 0 || column >= 4) {
|
||||
return QModelIndex();
|
||||
}
|
||||
if (parent.isValid() && parent.column() != 0) {
|
||||
return QModelIndex();
|
||||
}
|
||||
if (row >= rowCount(parent)) {
|
||||
return QModelIndex();
|
||||
}
|
||||
const quintptr id = processes_index(d, parent.internalId(), parent.isValid(), row);
|
||||
return createIndex(row, column, id);
|
||||
}
|
||||
|
||||
QModelIndex Processes::parent(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return QModelIndex();
|
||||
}
|
||||
const qmodelindex_t parent = processes_parent(d, index.internalId());
|
||||
return parent.row >= 0 ?createIndex(parent.row, 0, parent.id) :QModelIndex();
|
||||
}
|
||||
|
||||
bool Processes::canFetchMore(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid() && parent.column() != 0) {
|
||||
return false;
|
||||
}
|
||||
return processes_can_fetch_more(d, parent.internalId(), parent.isValid());
|
||||
}
|
||||
|
||||
void Processes::fetchMore(const QModelIndex &parent)
|
||||
{
|
||||
processes_fetch_more(d, parent.internalId(), parent.isValid());
|
||||
}
|
||||
|
||||
void Processes::sort(int column, Qt::SortOrder order)
|
||||
{
|
||||
processes_sort(d, column, order);
|
||||
}
|
||||
Qt::ItemFlags Processes::flags(const QModelIndex &i) const
|
||||
{
|
||||
auto flags = QAbstractItemModel::flags(i);
|
||||
return flags;
|
||||
}
|
||||
QVariant Processes::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
QVariant v;
|
||||
QString s;
|
||||
QByteArray b;
|
||||
switch (index.column()) {
|
||||
case 0:
|
||||
switch (role) {
|
||||
case Qt::UserRole + 0:
|
||||
processes_data_cmd(d, index.internalId(), &s, set_qstring);
|
||||
if (!s.isNull()) v.setValue<QString>(s);
|
||||
break;
|
||||
case Qt::UserRole + 1:
|
||||
v = processes_data_cpu_percentage(d, index.internalId());
|
||||
break;
|
||||
case Qt::UserRole + 2:
|
||||
v = processes_data_cpu_usage(d, index.internalId());
|
||||
break;
|
||||
case Qt::UserRole + 3:
|
||||
v = processes_data_memory(d, index.internalId());
|
||||
break;
|
||||
case Qt::UserRole + 4:
|
||||
processes_data_name(d, index.internalId(), &s, set_qstring);
|
||||
if (!s.isNull()) v.setValue<QString>(s);
|
||||
break;
|
||||
case Qt::DisplayRole:
|
||||
case Qt::UserRole + 5:
|
||||
v = processes_data_pid(d, index.internalId());
|
||||
break;
|
||||
case Qt::UserRole + 6:
|
||||
v = processes_data_uid(d, index.internalId());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case Qt::UserRole + 4:
|
||||
processes_data_name(d, index.internalId(), &s, set_qstring);
|
||||
if (!s.isNull()) v.setValue<QString>(s);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case Qt::UserRole + 2:
|
||||
v = processes_data_cpu_usage(d, index.internalId());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case Qt::UserRole + 3:
|
||||
v = processes_data_memory(d, index.internalId());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
QHash<int, QByteArray> Processes::roleNames() const {
|
||||
QHash<int, QByteArray> names = QAbstractItemModel::roleNames();
|
||||
names.insert(Qt::UserRole + 0, "cmd");
|
||||
names.insert(Qt::UserRole + 1, "cpuPercentage");
|
||||
names.insert(Qt::UserRole + 2, "cpuUsage");
|
||||
names.insert(Qt::UserRole + 3, "memory");
|
||||
names.insert(Qt::UserRole + 4, "name");
|
||||
names.insert(Qt::UserRole + 5, "pid");
|
||||
names.insert(Qt::UserRole + 6, "uid");
|
||||
return names;
|
||||
}
|
||||
bool Processes::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
bool set = false;
|
||||
if (set) {
|
||||
emit dataChanged(index, index, QVector<int>() << role);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
extern "C" {
|
||||
Processes::Private* processes_new(Processes*,
|
||||
void (*)(const Processes*, quintptr, bool),
|
||||
void (*)(Processes*),
|
||||
void (*)(Processes*),
|
||||
void (*)(Processes*, option<quintptr>, int, int),
|
||||
void (*)(Processes*),
|
||||
void (*)(Processes*, option<quintptr>, int, int),
|
||||
void (*)(Processes*));
|
||||
void processes_free(Processes::Private*);
|
||||
};
|
||||
Processes::Processes(QObject *parent):
|
||||
QAbstractItemModel(parent),
|
||||
d(processes_new(this,
|
||||
[](const Processes* o, quintptr id, bool valid) {
|
||||
if (valid) {
|
||||
int row = processes_row(o->d, id);
|
||||
emit o->newDataReady(o->createIndex(row, 0, id));
|
||||
} else {
|
||||
emit o->newDataReady(QModelIndex());
|
||||
}
|
||||
},
|
||||
[](Processes* o) {
|
||||
o->beginResetModel();
|
||||
},
|
||||
[](Processes* o) {
|
||||
o->endResetModel();
|
||||
},
|
||||
[](Processes* o, option<quintptr> id, int first, int last) {
|
||||
if (id.some) {
|
||||
int row = processes_row(o->d, id.value);
|
||||
o->beginInsertRows(o->createIndex(row, 0, id.value), first, last);
|
||||
} else {
|
||||
o->beginInsertRows(QModelIndex(), first, last);
|
||||
}
|
||||
},
|
||||
[](Processes* o) {
|
||||
o->endInsertRows();
|
||||
},
|
||||
[](Processes* o, option<quintptr> id, int first, int last) {
|
||||
if (id.some) {
|
||||
int row = processes_row(o->d, id.value);
|
||||
o->beginRemoveRows(o->createIndex(row, 0, id.value), first, last);
|
||||
} else {
|
||||
o->beginRemoveRows(QModelIndex(), first, last);
|
||||
}
|
||||
},
|
||||
[](Processes* o) {
|
||||
o->endRemoveRows();
|
||||
}
|
||||
)) {
|
||||
connect(this, &Processes::newDataReady, this, [this](const QModelIndex& i) {
|
||||
fetchMore(i);
|
||||
}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
|
||||
Processes::~Processes() {
|
||||
processes_free(d);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* generated by rust_qt_binding_generator */
|
||||
#ifndef PROCESSES_H
|
||||
#define PROCESSES_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
class Processes : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
class Private;
|
||||
private:
|
||||
Private * const d;
|
||||
public:
|
||||
explicit Processes(QObject *parent = nullptr);
|
||||
~Processes();
|
||||
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex &index) const override;
|
||||
bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
bool canFetchMore(const QModelIndex &parent) const override;
|
||||
void fetchMore(const QModelIndex &parent) override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
signals:
|
||||
// new data is ready to be made available to the model with fetchMore()
|
||||
void newDataReady(const QModelIndex &parent) const;
|
||||
signals:
|
||||
private:
|
||||
};
|
||||
#endif // PROCESSES_H
|
|
@ -1,6 +1,7 @@
|
|||
#include "Tree.h"
|
||||
#include "Fibonacci.h"
|
||||
#include "TimeSeries.h"
|
||||
#include "Processes.h"
|
||||
|
||||
#ifdef QT_CHARTS_LIB
|
||||
#include <QtCharts>
|
||||
|
@ -39,8 +40,10 @@ struct Models {
|
|||
QStringListModel styles;
|
||||
Fibonacci fibonacci;
|
||||
FibonacciList fibonacciList;
|
||||
Tree tree;
|
||||
QSortFilterProxyModel sortedTree;
|
||||
Tree fileSystem;
|
||||
QSortFilterProxyModel sortedFileSystem;
|
||||
Processes processes;
|
||||
QSortFilterProxyModel sortedProcesses;
|
||||
TimeSeries timeSeries;
|
||||
};
|
||||
|
||||
|
@ -74,17 +77,21 @@ void copyWindowGeometry(QWidget* w, QQmlContext* c) {
|
|||
}
|
||||
}
|
||||
|
||||
void createQtQuick(const QString& name, const QString& qml, Models* models, QWidget* widgets) {
|
||||
void createQtQuick(const QString& name, const QString& qml, Models* models,
|
||||
QWidget* widgets, const QString& initialTab) {
|
||||
QQmlApplicationEngine* engine = new QQmlApplicationEngine();
|
||||
QQmlContext* c = engine->rootContext();
|
||||
c->setContextProperty("fsModel", &models->tree);
|
||||
c->setContextProperty("sortedFsModel", &models->sortedTree);
|
||||
c->setContextProperty("styles", &models->styles);
|
||||
c->setContextProperty("fibonacci", &models->fibonacci);
|
||||
c->setContextProperty("fibonacciList", &models->fibonacciList);
|
||||
c->setContextProperty("styles", &models->styles);
|
||||
c->setContextProperty("sortedFileSystem", &models->sortedFileSystem);
|
||||
c->setContextProperty("processes", &models->sortedProcesses);
|
||||
c->setContextProperty("timeSeries", &models->timeSeries);
|
||||
|
||||
c->setContextProperty("widgets", widgets);
|
||||
c->setContextProperty("qtquickIndex",
|
||||
QVariant(models->styles.stringList().indexOf(name)));
|
||||
c->setContextProperty("initialTab", initialTab);
|
||||
copyWindowGeometry(widgets, engine->rootContext());
|
||||
engine->load(QUrl(qml));
|
||||
}
|
||||
|
@ -111,10 +118,10 @@ QComboBox* createStyleComboBox(Models* models) {
|
|||
return box;
|
||||
}
|
||||
|
||||
QWidget* createStyleTab(Models* models, QWidget* tabs) {
|
||||
QComboBox* box = createStyleComboBox(models);
|
||||
QWidget* createStyleTab(Models* models, QWidget* tabs, QComboBox* box,
|
||||
const QString& initialTab) {
|
||||
QRect windowRect;
|
||||
box->connect(box, &QComboBox::currentTextChanged, box, [windowRect, box, tabs, models](const QString &text) mutable {
|
||||
auto f = [windowRect, box, tabs, models, initialTab](const QString &text) mutable {
|
||||
QWindow* window = getWindow(tabs);
|
||||
bool visible = tabs->isVisible();
|
||||
if (text.startsWith("QWidgets ")) {
|
||||
|
@ -138,13 +145,16 @@ QWidget* createStyleTab(Models* models, QWidget* tabs) {
|
|||
#ifdef QTQUICKCONTROLS2
|
||||
if (text == "QtQuick Controls 2") {
|
||||
createQtQuick("QtQuick Controls 2", "qrc:///demo-qtquick2.qml",
|
||||
models, box);
|
||||
models, box, initialTab);
|
||||
} else
|
||||
#endif
|
||||
createQtQuick("QtQuick", "qrc:///demo.qml", models, box);
|
||||
createQtQuick("QtQuick", "qrc:///demo.qml", models, box, initialTab);
|
||||
#endif
|
||||
}
|
||||
});
|
||||
};
|
||||
box->connect(box, &QComboBox::currentTextChanged, box, f);
|
||||
// box->setCurrentText(style);
|
||||
// f(style);
|
||||
return box;
|
||||
}
|
||||
|
||||
|
@ -188,14 +198,25 @@ QWidget* createTreeTab(Models* models) {
|
|||
QTreeView* view = new QTreeView();
|
||||
view->setUniformRowHeights(true);
|
||||
view->setSortingEnabled(true);
|
||||
view->setModel(&models->sortedTree);
|
||||
auto root = models->sortedTree.index(0, 0);
|
||||
view->setModel(&models->sortedFileSystem);
|
||||
auto root = models->sortedFileSystem.index(0, 0);
|
||||
view->expand(root);
|
||||
view->sortByColumn(0, Qt::AscendingOrder);
|
||||
view->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
return view;
|
||||
}
|
||||
|
||||
QWidget* createProcessesTab(Models* models) {
|
||||
QTreeView* view = new QTreeView();
|
||||
view->setUniformRowHeights(true);
|
||||
view->setSortingEnabled(true);
|
||||
view->setModel(&models->sortedProcesses);
|
||||
auto root = models->sortedFileSystem.index(0, 0);
|
||||
view->expand(root);
|
||||
view->sortByColumn(0, Qt::AscendingOrder);
|
||||
return view;
|
||||
}
|
||||
|
||||
#ifdef QT_CHARTS_LIB
|
||||
|
||||
using namespace QtCharts;
|
||||
|
@ -237,18 +258,27 @@ QWidget* createChartTab(Models* models) {
|
|||
}
|
||||
#endif
|
||||
|
||||
void createWidgets(Models* models) {
|
||||
void createWidgets(Models* models, const QString& initialStyle,
|
||||
const QString& initialTab) {
|
||||
QTabWidget* tabs = new QTabWidget();
|
||||
|
||||
tabs->addTab(createStyleTab(models, tabs), "style");
|
||||
QComboBox* box = createStyleComboBox(models);
|
||||
tabs->addTab(createStyleTab(models, tabs, box, initialTab), "style");
|
||||
tabs->addTab(createObjectTab(models), "object");
|
||||
tabs->addTab(createListTab(models), "list");
|
||||
tabs->addTab(createTreeTab(models), "tree");
|
||||
tabs->addTab(createProcessesTab(models), "processes");
|
||||
#ifdef QT_CHARTS_LIB
|
||||
tabs->addTab(createChartTab(models), "chart");
|
||||
#endif
|
||||
tabs->setMinimumSize(QSize(500, 500));
|
||||
tabs->show();
|
||||
box->setCurrentText(initialStyle);
|
||||
for (int i = 0; i < tabs->count(); ++i) {
|
||||
if (tabs->tabText(i) == initialTab) {
|
||||
tabs->setCurrentIndex(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
|
@ -256,20 +286,38 @@ int main (int argc, char *argv[])
|
|||
QApplication app(argc, argv);
|
||||
|
||||
#ifdef QT_QUICK_LIB
|
||||
|
||||
qmlRegisterType<QSortFilterProxyModel>("org.qtproject.example", 1, 0, "SortFilterProxyModel");
|
||||
qmlRegisterType<Fibonacci>("rust", 1, 0, "Fibonacci");
|
||||
qmlRegisterType<FibonacciList>("rust", 1, 0, "FibonacciList");
|
||||
|
||||
#endif
|
||||
|
||||
Models models;
|
||||
Tree& model = models.tree;
|
||||
QSortFilterProxyModel& sortedModel = models.sortedTree;
|
||||
model.setPath("/");
|
||||
sortedModel.setSourceModel(&model);
|
||||
sortedModel.setDynamicSortFilter(true);
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("Demo application for Qt and RUst");
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
// --initial-style
|
||||
QCommandLineOption initialStyleOption(QStringList()
|
||||
<< "initial-style",
|
||||
QCoreApplication::translate("main", "Initial widget style."),
|
||||
QCoreApplication::translate("main", "style"));
|
||||
parser.addOption(initialStyleOption);
|
||||
// --initial-tab
|
||||
QCommandLineOption initialTabOption(QStringList()
|
||||
<< "initial-tab",
|
||||
QCoreApplication::translate("main", "Initial tab."),
|
||||
QCoreApplication::translate("main", "tab"));
|
||||
parser.addOption(initialTabOption);
|
||||
parser.process(app);
|
||||
|
||||
Models models;
|
||||
models.fileSystem.setPath("/");
|
||||
models.sortedFileSystem.setSourceModel(&models.fileSystem);
|
||||
models.sortedFileSystem.setDynamicSortFilter(true);
|
||||
models.sortedProcesses.setSourceModel(&models.processes);
|
||||
models.sortedProcesses.setDynamicSortFilter(true);
|
||||
|
||||
createWidgets(&models, parser.value(initialStyleOption),
|
||||
parser.value(initialTabOption));
|
||||
|
||||
createWidgets(&models);
|
||||
return app.exec();
|
||||
}
|
||||
|
|
2
dev
2
dev
|
@ -14,4 +14,4 @@ else
|
|||
charts="qt5.qtcharts libsForQt5.kirigami_2"
|
||||
fi
|
||||
|
||||
nix-shell -p qtcreator kmail cmake ninja gcc rustc cargo qt5.full extra-cmake-modules kdeFrameworks.kwidgetsaddons kdeFrameworks.kcoreaddons kdeFrameworks.ki18n appstream cmakeCurses kdeFrameworks.ktexteditor qt5.qtquickcontrols2 $charts
|
||||
nix-shell -p kdevelop qtcreator qt5.qtsensors qt5.qtdoc cmake ninja gcc rustc cargo qt5.full extra-cmake-modules kdeFrameworks.kwidgetsaddons kdeFrameworks.kcoreaddons kdeFrameworks.ki18n appstream cmakeCurses kdeFrameworks.ktexteditor qt5.qtquickcontrols2 $charts
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
static QTextStream err;
|
||||
|
||||
inline QString snakeCase(const QString& name) {
|
||||
return name.left(1).toLower() + name.mid(1)
|
||||
.replace(QRegExp("([A-Z])"), "_\\1").toLower();
|
||||
|
@ -36,6 +34,7 @@ public:
|
|||
void write() const {
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
QTextStream err(stderr);
|
||||
err << QCoreApplication::translate("main",
|
||||
"Cannot write %1.\n").arg(file.fileName());
|
||||
err.flush();
|
||||
|
|
|
@ -27,6 +27,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
const QStringList args = parser.positionalArguments();
|
||||
if (args.isEmpty()) {
|
||||
QTextStream err(stderr);
|
||||
err << QCoreApplication::translate("main",
|
||||
"Configuration file is missing.\n");
|
||||
return 1;
|
||||
|
|
|
@ -20,6 +20,13 @@ const QMap<BindingType, BindingTypeProperties>& bindingTypeProperties() {
|
|||
if (p.empty()) {
|
||||
QMap<BindingType, BindingTypeProperties> f;
|
||||
f.insert(BindingType::Bool, simpleType("bool", "true"));
|
||||
f.insert(BindingType::UChar, {
|
||||
.name = "quint8",
|
||||
.cppSetType = "quint8",
|
||||
.cSetType = "quint8",
|
||||
.rustType = "u8",
|
||||
.rustTypeInit = "0",
|
||||
});
|
||||
f.insert(BindingType::Int, {
|
||||
.name = "qint32",
|
||||
.cppSetType = "qint32",
|
||||
|
@ -41,6 +48,13 @@ const QMap<BindingType, BindingTypeProperties>& bindingTypeProperties() {
|
|||
.rustType = "u64",
|
||||
.rustTypeInit = "0"
|
||||
});
|
||||
f.insert(BindingType::Float, {
|
||||
.name = "float",
|
||||
.cppSetType = "float",
|
||||
.cSetType = "float",
|
||||
.rustType = "f32",
|
||||
.rustTypeInit = "0.0"
|
||||
});
|
||||
f.insert(BindingType::QString, {
|
||||
.name = "QString",
|
||||
.cppSetType = "const QString&",
|
||||
|
@ -68,6 +82,7 @@ BindingTypeProperties parseBindingType(const QString& value) {
|
|||
return i.value();
|
||||
}
|
||||
}
|
||||
QTextStream err(stderr);
|
||||
err << QCoreApplication::translate("main",
|
||||
"'%1' is not a supported type. Try one of\n").arg(value);
|
||||
for (auto i: bindingTypeProperties()) {
|
||||
|
@ -94,6 +109,7 @@ Qt::ItemDataRole parseItemDataRole(const QString& s) {
|
|||
if (v >= 0) {
|
||||
return (Qt::ItemDataRole)v;
|
||||
}
|
||||
QTextStream err(stderr);
|
||||
err << QCoreApplication::translate("main",
|
||||
"%1 is not a valid role name.\n").arg(s);
|
||||
err.flush();
|
||||
|
@ -134,6 +150,7 @@ parseObject(const QString& name, const QJsonObject& json) {
|
|||
for (const QString& key: properties.keys()) {
|
||||
o.properties.append(parseProperty(key, properties[key].toObject()));
|
||||
}
|
||||
QTextStream err(stderr);
|
||||
const QJsonObject& itemProperties = json.value("itemProperties").toObject();
|
||||
if (o.type != ObjectType::Object && itemProperties.size() == 0) {
|
||||
err << QCoreApplication::translate("main",
|
||||
|
@ -159,6 +176,7 @@ Configuration
|
|||
parseConfiguration(const QString& path) {
|
||||
QFile configurationFile(path);
|
||||
const QDir base = QFileInfo(configurationFile).dir();
|
||||
QTextStream err(stderr);
|
||||
if (!configurationFile.open(QIODevice::ReadOnly)) {
|
||||
err << QCoreApplication::translate("main",
|
||||
"Cannot read %1.\n").arg(configurationFile.fileName());
|
||||
|
|
|
@ -12,9 +12,11 @@ enum class ObjectType {
|
|||
|
||||
enum class BindingType {
|
||||
Bool,
|
||||
UChar,
|
||||
Int,
|
||||
UInt,
|
||||
ULongLong,
|
||||
Float,
|
||||
QString,
|
||||
QByteArray
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue