这是我想要实现的目标的简化版本。对于添加的每个商店,可以添加一个或多个部门。对于添加的每个部门,可以添加一名或多名员工。选择列表中的一行将更新其右侧的列表。例如,选择芝麻街将更新部门列表以显示属于该商店的所有部门。选择服装将更新员工列表以显示属于该部门的所有员工。
这种关系也在下面进行了演示(请注意,这些实际上是类,并且能够在其数据在内部更改时(例如,从外部源更改)时发出信号):
struct Employee {
std::string id;
std::string name;
double hourly_rate;
};
struct Department {
std::string id;
std::string name;
int personCount;
bool status;
Employee* onShift;
std::vector<Employee> employees;
};
struct Store {
std::string id;
std::string name;
std::string address;
std::vector<Department> departments;
};
在另一个选项卡上,我们有跨商店所有部门的汇总列表,显示实时数据,并带有一个下拉列表,可从属于该部门的员工池中选择轮班领导者。
就 Qt 模型而言,我想有几种方法可以解决这个问题。我更喜欢将 Qt 模型视为视图和数据之间的接口,而不是它们本身对所述数据负责或拥有所述数据的所有权。
我建议将数据的所有权交给 Manager 类,该类还包含我们创建的任何子类模型。对于配置页面,我们有商店、部门和员工的三个 QAbstractListModel 子类。对于部门和员工模型,我们可以传递列表指针并根据需要调用 begin/endResetModel 以在选择项目时更新列表。
对于“所有部门”页面,我们有一个聚合部门模型,它也是 QAbstractListModel 的子类。这将包含商店中所有部门的指针列表。 On Shift Leader 下拉列表有点棘手,因为我们不能使用单一模型。我想知道在这种情况下,部门拥有自己的员工列表实例是否更有意义,可以将其返回给 QML 委托...
如您所见,我们现在有许多用于相当基本的数据层次结构的模型。模型之间的同步可能会成为一个问题,因此只能通过 Manager 类修改底层数据,然后 Manager 类可以协调模型的更新。
我是否描述了解决问题的有价值的方法,或者是否造成了混乱?我实在想不出更好的办法了
如果我设计数据结构,我会进行以下更改:
id
,因为这可能会与 QML 的 id 混淆(使用 storeId、departmentId、employeeId 代替)如果我在 RDBMS 中表示这一点,我的 DDL 将如下所示:
CREATE TABLE Store
(
storeId int primary key,
name string ,
address string
);
CREATE TABLE Department
(
departmentId int primary key,
storeId int foreign key REFERENCES Store(storeId),
name string,
personCount int,
status boolean
);
CREATE TABLE Employee
(
employeeId int primary key,
departmentId int foreign key REFERENCES Department(departmentId),
name string,
hourlyRate real,
shiftLeader boolean
);
如果我需要持久性并存储超过 100 条记录,我会考虑使用 SQLite 之类的东西。如果我的应用程序位于内存中并且很小,我会使用 Qt6.4
list<var>
类型,因为:
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
property list<var> stores: ([
{"storeId": 1, "name": "Cherry Tree Lane"},
{"storeId": 2, "name": "Sesame Street"},
{"storeId": 3, "name": "Diagon Alley"}
])
property int currentStoreId: 2
property list<var> departments: ([
{"departmentId": 1, "storeId": 2, "name": "Clothing"},
{"departmentId": 2, "storeId": 2, "name": "Kitchen"},
{"departmentId": 3, "storeId": 3, "name": "Olivanders"},
{"departmentId": 4, "storeId": 3, "name": "Borgen and Burkes"}
])
property int currentDepartmentId: 1
property list<var> employees: ([
{"employeeId": 1, "departmentId": 1, "name": "Alex"},
{"employeeId": 2, "departmentId": 1, "name": "John"},
{"employeeId": 3, "departmentId": 1, "name": "Alice"},
{"employeeId": 4, "departmentId": 1, "name": "Emma"},
{"employeeId": 5, "departmentId": 4, "name": "Garrick"}
])
property int currentEmployeeId: 1
RowLayout {
anchors.fill: parent
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
model: stores
delegate: ItemDelegate {
text: modelData.name
background: Rectangle {
color: modelData.storeId === currentStoreId ? "skyblue" : "white"
}
onClicked: {
currentStoreId = modelData.storeId;
currentDepartmentId = -1;
currentEmployeeId = -1;
}
}
}
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
model: departments.filter(d => d.storeId === currentStoreId)
delegate: ItemDelegate {
text: modelData.name
background: Rectangle {
color: modelData.departmentId === currentDepartmentId ? "skyblue" : "white"
}
onClicked: {
currentDepartmentId = modelData.departmentId;
currentEmployeeId = -1;
}
}
}
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
model: employees.filter(e => e.departmentId === currentDepartmentId)
delegate: ItemDelegate {
text: modelData.name
background: Rectangle {
color: modelData.employeeId === currentEmployeeId ? "skyblue" : "white"
}
onClicked: currentEmployeeId = modelData.employeeId
}
}
}
}
您可以在线尝试以上方法!