Work on editability of models.
parent
b94d65a217
commit
a5f22ad04b
|
@ -14,6 +14,7 @@ use std::collections::HashMap;
|
|||
pub struct DirEntry {
|
||||
name: OsString,
|
||||
metadata: Option<Metadata>,
|
||||
path: Option<PathBuf>
|
||||
}
|
||||
|
||||
type Incoming<T> = Arc<Mutex<HashMap<usize, Vec<T>>>>;
|
||||
|
@ -23,6 +24,7 @@ impl Item for DirEntry {
|
|||
DirEntry {
|
||||
name: OsString::from(name),
|
||||
metadata: metadata(name).ok(),
|
||||
path: None
|
||||
}
|
||||
}
|
||||
fn can_fetch_more(&self) -> bool {
|
||||
|
@ -31,6 +33,17 @@ impl Item for DirEntry {
|
|||
fn file_name(&self) -> String {
|
||||
self.name.to_string_lossy().to_string()
|
||||
}
|
||||
fn file_path(&self) -> Option<String> {
|
||||
self.path.as_ref().map(|p| p.to_string_lossy().into())
|
||||
}
|
||||
fn set_file_name(&mut self, file_name: String) -> bool {
|
||||
self.name = file_name.into();
|
||||
true
|
||||
}
|
||||
fn set_file_path(&mut self, file_path: Option<String>) -> bool {
|
||||
self.path = file_path.map(|f| f.into());
|
||||
true
|
||||
}
|
||||
fn file_permissions(&self) -> c_int {
|
||||
42
|
||||
}
|
||||
|
@ -46,11 +59,12 @@ impl Item for DirEntry {
|
|||
let mut v = Vec::new();
|
||||
let path: PathBuf = parents.into_iter().map(|e| &e.name).collect();
|
||||
thread::spawn(move || {
|
||||
if let Ok(it) = read_dir(path) {
|
||||
if let Ok(it) = read_dir(&path) {
|
||||
for i in it.filter_map(|v| v.ok()) {
|
||||
let de = DirEntry {
|
||||
name: i.file_name(),
|
||||
metadata: i.metadata().ok()
|
||||
metadata: i.metadata().ok(),
|
||||
path: Some(i.path())
|
||||
};
|
||||
v.push(de);
|
||||
}
|
||||
|
@ -70,6 +84,7 @@ impl Default for DirEntry {
|
|||
DirEntry {
|
||||
name: OsString::new(),
|
||||
metadata: None,
|
||||
path: None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,9 +94,12 @@ pub trait Item: Default {
|
|||
fn can_fetch_more(&self) -> bool;
|
||||
fn retrieve(id: usize, parents: Vec<&Self>, q: Incoming<Self>, emit: TreeEmitter);
|
||||
fn file_name(&self) -> String;
|
||||
fn file_path(&self) -> Option<String>;
|
||||
fn set_file_name(&mut self, file_name: String) -> bool;
|
||||
fn file_permissions(&self) -> c_int;
|
||||
fn file_type(&self) -> c_int;
|
||||
fn file_size(&self) -> Option<u64>;
|
||||
fn set_file_path(&mut self, file_path: Option<String>) -> bool;
|
||||
}
|
||||
|
||||
pub type Tree = RGeneralItemModel<DirEntry>;
|
||||
|
@ -145,6 +163,10 @@ impl<T: Item> RGeneralItemModel<T> where T: Sync + Send {
|
|||
self.get_index(row, parent)
|
||||
.map(|i| &self.entries[i])
|
||||
}
|
||||
fn get_mut(&mut self, row: c_int, parent: usize) -> Option<&mut Entry<T>> {
|
||||
self.get_index(row, parent)
|
||||
.map(move |i| &mut self.entries[i])
|
||||
}
|
||||
fn retrieve(&mut self, row: c_int, parent: usize) {
|
||||
let id = self.get_index(row, parent).unwrap();
|
||||
let parents = self.get_parents(id);
|
||||
|
@ -258,6 +280,11 @@ impl<T: Item> TreeTrait for RGeneralItemModel<T> where T: Sync + Send {
|
|||
.map(|entry| entry.data.file_name())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
fn set_file_name(&mut self, row: c_int, parent: usize, v: String) -> bool {
|
||||
self.get_mut(row, parent)
|
||||
.map(|mut entry| entry.data.set_file_name(v))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
fn file_permissions(&self, row: c_int, parent: usize) -> c_int {
|
||||
self.get(row, parent)
|
||||
.map(|entry| entry.data.file_permissions())
|
||||
|
@ -267,7 +294,9 @@ impl<T: Item> TreeTrait for RGeneralItemModel<T> where T: Sync + Send {
|
|||
Vec::new()
|
||||
}
|
||||
fn file_path(&self, row: c_int, parent: usize) -> Option<String> {
|
||||
None
|
||||
self.get(row, parent)
|
||||
.map(|entry| entry.data.file_path())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
fn file_type(&self, row: c_int, parent: usize) -> c_int {
|
||||
self.get(row, parent)
|
||||
|
@ -279,4 +308,9 @@ impl<T: Item> TreeTrait for RGeneralItemModel<T> where T: Sync + Send {
|
|||
.map(|entry| entry.data.file_size())
|
||||
.unwrap_or(None)
|
||||
}
|
||||
fn set_file_path(&mut self, row: c_int, parent: usize, v: Option<String>) -> bool {
|
||||
self.get_mut(row, parent)
|
||||
.map(|mut entry| entry.data.set_file_path(v))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,8 +79,10 @@ pub trait TreeTrait {
|
|||
fn fetch_more(&mut self, c_int, usize) {}
|
||||
fn sort(&mut self, c_int, SortOrder) {}
|
||||
fn file_name(&self, row: c_int, parent: usize) -> String;
|
||||
fn set_file_name(&mut self, row: c_int, parent: usize, String) -> bool;
|
||||
fn file_icon(&self, row: c_int, parent: usize) -> Vec<u8>;
|
||||
fn file_path(&self, row: c_int, parent: usize) -> Option<String>;
|
||||
fn set_file_path(&mut self, row: c_int, parent: usize, Option<String>) -> bool;
|
||||
fn file_permissions(&self, row: c_int, parent: usize) -> i32;
|
||||
fn file_type(&self, row: c_int, parent: usize) -> i32;
|
||||
fn file_size(&self, row: c_int, parent: usize) -> Option<u64>;
|
||||
|
@ -191,6 +193,11 @@ pub unsafe extern "C" fn tree_data_file_path(ptr: *const Tree,
|
|||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn tree_set_data_file_path_none(ptr: *mut Tree, row: c_int, parent: usize) -> bool {
|
||||
(&mut *ptr).set_file_path(row, parent, None)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn tree_data_file_permissions(ptr: *const Tree, row: c_int, parent: usize) -> i32 {
|
||||
(&*ptr).file_permissions(row, parent).into()
|
||||
|
|
|
@ -179,7 +179,8 @@ void FibonacciList::sort(int column, Qt::SortOrder order)
|
|||
}
|
||||
Qt::ItemFlags FibonacciList::flags(const QModelIndex &i) const
|
||||
{
|
||||
return QAbstractItemModel::flags(i);
|
||||
auto flags = QAbstractItemModel::flags(i);
|
||||
return flags;
|
||||
}
|
||||
QVariant FibonacciList::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
|
|
|
@ -121,6 +121,7 @@ extern "C" {
|
|||
void tree_data_file_name(const Tree::Private*, int, quintptr, QString*, qstring_set);
|
||||
void tree_data_file_icon(const Tree::Private*, int, quintptr, QByteArray*, qbytearray_set);
|
||||
void tree_data_file_path(const Tree::Private*, int, quintptr, QString*, qstring_set);
|
||||
bool tree_set_data_file_path_none(Tree::Private*, int, quintptr);
|
||||
qint32 tree_data_file_permissions(const Tree::Private*, int, quintptr);
|
||||
qint32 tree_data_file_type(const Tree::Private*, int, quintptr);
|
||||
option<quint64> tree_data_file_size(const Tree::Private*, int, quintptr);
|
||||
|
@ -190,7 +191,14 @@ void Tree::sort(int column, Qt::SortOrder order)
|
|||
}
|
||||
Qt::ItemFlags Tree::flags(const QModelIndex &i) const
|
||||
{
|
||||
return QAbstractItemModel::flags(i);
|
||||
auto flags = QAbstractItemModel::flags(i);
|
||||
if (i.column() == 0) {
|
||||
flags |= Qt::ItemIsEditable;
|
||||
}
|
||||
if (i.column() == 1) {
|
||||
flags |= Qt::ItemIsEditable;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
QVariant Tree::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
|
@ -204,6 +212,10 @@ QVariant Tree::data(const QModelIndex &index, int role) const
|
|||
tree_data_file_name(d, index.row(), index.internalId(), &s, set_qstring);
|
||||
if (!s.isNull()) v.setValue<QString>(s);
|
||||
break;
|
||||
case Qt::EditRole:
|
||||
tree_data_file_name(d, index.row(), index.internalId(), &s, set_qstring);
|
||||
if (!s.isNull()) v.setValue<QString>(s);
|
||||
break;
|
||||
case Qt::DecorationRole:
|
||||
tree_data_file_icon(d, index.row(), index.internalId(), &b, set_qbytearray);
|
||||
if (!b.isNull()) v.setValue<QByteArray>(b);
|
||||
|
@ -233,6 +245,10 @@ QVariant Tree::data(const QModelIndex &index, int role) const
|
|||
tree_data_file_path(d, index.row(), index.internalId(), &s, set_qstring);
|
||||
if (!s.isNull()) v.setValue<QString>(s);
|
||||
break;
|
||||
case Qt::EditRole:
|
||||
tree_data_file_path(d, index.row(), index.internalId(), &s, set_qstring);
|
||||
if (!s.isNull()) v.setValue<QString>(s);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
|
@ -271,5 +287,33 @@ QHash<int, QByteArray> Tree::roleNames() const {
|
|||
}
|
||||
bool Tree::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (index.column() == 0) {
|
||||
if (role == (Qt::DisplayRole)) {
|
||||
return true;
|
||||
}
|
||||
if (role == (Qt::EditRole)) {
|
||||
return true;
|
||||
}
|
||||
if (role == (Qt::UserRole + 1)) {
|
||||
if (!value.isValid() || value.isNull()) {
|
||||
return tree_set_data_file_path_none(d, index.row(), index.internalId());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (index.column() == 1) {
|
||||
if (role == (Qt::DisplayRole)) {
|
||||
if (!value.isValid() || value.isNull()) {
|
||||
return tree_set_data_file_path_none(d, index.row(), index.internalId());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (role == (Qt::EditRole)) {
|
||||
if (!value.isValid() || value.isNull()) {
|
||||
return tree_set_data_file_path_none(d, index.row(), index.internalId());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ int main (int argc, char *argv[])
|
|||
auto root = sortedModel.index(0, 0);
|
||||
view.expand(root);
|
||||
view.sortByColumn(0, Qt::AscendingOrder);
|
||||
// view.show();
|
||||
view.show();
|
||||
view.header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
|
|
|
@ -19,7 +19,13 @@
|
|||
[{
|
||||
"name": "fileName",
|
||||
"value": "Qt::DisplayRole",
|
||||
"type": "QString"
|
||||
"type": "QString",
|
||||
"write": true
|
||||
}, {
|
||||
"name": "fileName",
|
||||
"value": "Qt::EditRole",
|
||||
"type": "QString",
|
||||
"write": true
|
||||
}, {
|
||||
"name": "fileIcon",
|
||||
"value": "Qt::DecorationRole",
|
||||
|
@ -28,6 +34,7 @@
|
|||
"name": "filePath",
|
||||
"value": "Qt::UserRole + 1",
|
||||
"type": "QString",
|
||||
"write": true,
|
||||
"optional": true
|
||||
}, {
|
||||
"name": "fileName",
|
||||
|
@ -51,6 +58,13 @@
|
|||
"name": "filePath",
|
||||
"value": "Qt::DisplayRole",
|
||||
"type": "QString",
|
||||
"write": true,
|
||||
"optional": true
|
||||
}, {
|
||||
"name": "filePath",
|
||||
"value": "Qt::EditRole",
|
||||
"type": "QString",
|
||||
"write": true,
|
||||
"optional": true
|
||||
}],
|
||||
[{
|
||||
|
|
|
@ -335,6 +335,14 @@ signals:
|
|||
)");
|
||||
}
|
||||
|
||||
bool isWrite(const QList<Role>& roles) {
|
||||
bool write = false;
|
||||
for (auto role: roles) {
|
||||
write = write | role.write;
|
||||
}
|
||||
return write;
|
||||
}
|
||||
|
||||
void writeCppModel(QTextStream& cpp, const Object& o) {
|
||||
const QString lcname(snakeCase(o.name));
|
||||
QString indexDecl = ", int";
|
||||
|
@ -353,6 +361,14 @@ void writeCppModel(QTextStream& cpp, const Object& o) {
|
|||
cpp << QString(" %4 %2_data_%3(const %1::Private*%5);\n")
|
||||
.arg(o.name, lcname, snakeCase(role.name), cppSetType(role), indexDecl);
|
||||
}
|
||||
if (role.write) {
|
||||
// cpp << QString(" void %2_data_%3_set(%1::Private*, %3);")
|
||||
// .arg(o.name, base, p.type.cSetType) << endl;
|
||||
if (role.optional) {
|
||||
cpp << QString(" bool %2_set_data_%3_none(%1::Private*%4);")
|
||||
.arg(o.name, lcname, snakeCase(role.name), indexDecl) << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
cpp << QString(" void %2_sort(%1::Private*, int column, Qt::SortOrder order = Qt::AscendingOrder);\n").arg(o.name, lcname);
|
||||
if (o.type == ObjectType::List) {
|
||||
|
@ -470,7 +486,15 @@ void %1::sort(int column, Qt::SortOrder order)
|
|||
}
|
||||
Qt::ItemFlags %1::flags(const QModelIndex &i) const
|
||||
{
|
||||
return QAbstractItemModel::flags(i);
|
||||
auto flags = QAbstractItemModel::flags(i);
|
||||
)").arg(o.name, lcname);
|
||||
for (int col = 0; col < o.columnRoles.size(); ++col) {
|
||||
if (isWrite(o.columnRoles[col])) {
|
||||
cpp << " if (i.column() == " << col << ") {\n";
|
||||
cpp << " flags |= Qt::ItemIsEditable;\n }\n";
|
||||
}
|
||||
}
|
||||
cpp << QString(R"( return flags;
|
||||
}
|
||||
QVariant %1::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
|
@ -478,7 +502,7 @@ QVariant %1::data(const QModelIndex &index, int role) const
|
|||
QString s;
|
||||
QByteArray b;
|
||||
switch (index.column()) {
|
||||
)").arg(o.name, lcname);
|
||||
)").arg(o.name);
|
||||
|
||||
for (int col = 0; col < o.columnRoles.size(); ++col) {
|
||||
auto roles = o.columnRoles[col];
|
||||
|
@ -513,9 +537,36 @@ QVariant %1::data(const QModelIndex &index, int role) const
|
|||
cpp << QString(R"(}
|
||||
bool %1::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
)").arg(o.name);
|
||||
for (int col = 0; col < o.columnRoles.size(); ++col) {
|
||||
if (!isWrite(o.columnRoles[col])) {
|
||||
continue;
|
||||
}
|
||||
cpp << " if (index.column() == " << col << ") {\n";
|
||||
auto roles = o.columnRoles[col];
|
||||
for (auto role: roles) {
|
||||
if (!role.write) {
|
||||
continue;
|
||||
}
|
||||
cpp << " if (role == (" << role.value << ")) {\n";
|
||||
if (role.optional) {
|
||||
QString test = "!value.isValid()";
|
||||
if (role.type.isComplex()) {
|
||||
test += " || value.isNull()";
|
||||
}
|
||||
cpp << " if (" << test << ") {\n";
|
||||
cpp << QString(" return %1_set_data_%2_none(d%3);")
|
||||
.arg(lcname, snakeCase(role.name), index) << endl;
|
||||
cpp << " }\n";
|
||||
}
|
||||
cpp << " return true;\n";
|
||||
cpp << " }\n";
|
||||
}
|
||||
cpp << " }\n";
|
||||
}
|
||||
cpp << R"( return false;
|
||||
}
|
||||
)";
|
||||
}
|
||||
|
||||
void writeHeaderObject(QTextStream& h, const Object& o) {
|
||||
|
@ -977,6 +1028,10 @@ pub trait %1Trait {
|
|||
for (auto role: o.allRoles) {
|
||||
r << QString(" fn %1(&self%3) -> %2;\n")
|
||||
.arg(snakeCase(role.name), rustType(role), index);
|
||||
if (role.write) {
|
||||
r << QString(" fn set_%1(&mut self%3, %2) -> bool;\n")
|
||||
.arg(snakeCase(role.name), rustType(role), index);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o.type == ObjectType::UniformTree) {
|
||||
|
@ -1178,6 +1233,14 @@ pub unsafe extern "C" fn %2_data_%3(ptr: *const %1, row: c_int%5) -> %4 {
|
|||
}
|
||||
)").arg(o.name, lcname, snakeCase(role.name), rustCType(role), indexDecl, index);
|
||||
}
|
||||
if (role.write && role.optional) {
|
||||
r << QString(R"(
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn %2_set_data_%3_none(ptr: *mut %1, row: c_int%4) -> bool {
|
||||
(&mut *ptr).set_%3(row%5, None)
|
||||
}
|
||||
)").arg(o.name, lcname, snakeCase(role.name), indexDecl, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o.type == ObjectType::UniformTree) {
|
||||
|
|
Loading…
Reference in New Issue