上一章我们了解了如何自定义只读模型。顾名思义,只读模型只能够用于展示只读数据,用户不能对其进行修改。如果允许用户修改数据,则应该提供可编辑的模型。可编辑模型与只读模型非常相似,至少在展示数据方面几乎是完全一样的,所不同的是可编辑模型需要提供用户编辑数据后,应当如何将数据保存到实际存储值中。
我们还是利用上一章的CurrencyModel
,在此基础上进行修改。相同的代码这里不再赘述,我们只列出增加以及修改的代码。相比只读模型,可编辑模型需要增加以下两个函数的实现:
|
Qt
::
ItemFlags
flags
(
const
QModelIndex
&
index
)
const
;
bool
setData
(
const
QModelIndex
&
index
,
const
QVariant
&
value
,
int
role
=
Qt
::
EditRole
)
;
|
还记得之前我们曾经介绍过,在 Qt 的 model/view 模型中,我们使用委托 delegate 来实现数据的编辑。在实际创建编辑器之前,委托需要检测这个数据项是不是允许编辑。模型必须让委托知道这一点,这是通过返回模型中每个数据项的标记 flag 来实现的,也就是这个 flags() 函数。这本例中,只有行和列的索引不一致的时候,我们才允许修改(因为对角线上面的值恒为 1.0000,不应该对其进行修改):
|
Qt
::
ItemFlags
CurrencyModel
::
flags
(
const
QModelIndex
&
index
)
const
{
Qt
::
ItemFlags
flags
=
QAbstractItemModel
::
flags
(
index
)
;
if
(
index
.
row
(
)
!=
index
.
column
(
)
)
{
flags
|=
Qt
::
ItemIsEditable
;
}
return
flags
;
}
|
注意,我们并不是在判断了index.row() != index.column()
之后直接返回Qt::ItemIsEditable
,而是返回QAbstractItemModel::flags(index) | Qt::ItemIsEditable
。这是因为我们不希望丢弃原来已经存在的那些标记。
我们不需要知道在实际编辑的过程中,委托究竟做了什么,只需要提供一种方式,告诉 Qt 如何将委托获得的用户输入的新的数据保存到模型中。这一步骤是通过setData()
函数实现的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
bool
CurrencyModel
::
setData
(
const
QModelIndex
&
index
,
const
QVariant
&
value
,
int
role
)
{
if
(
index
.
isValid
(
)
&&
index
.
row
(
)
!=
index
.
column
(
)
&&
role
==
Qt
::
EditRole
)
{
QString
columnCurrency
=
headerData
(
index
.
column
(
)
,
Qt
::
Horizontal
,
Qt
::
DisplayRole
)
.
toString
(
)
;
QString
rowCurrency
=
headerData
(
index
.
row
(
)
,
Qt
::
Vertical
,
Qt
::
DisplayRole
)
.
toString
(
)
;
currencyMap
.
insert
(
columnCurrency
,
value
.
toDouble
(
)
*
currencyMap
.
value
(
rowCurrency
)
)
;
emit
dataChanged
(
index
,
index
)
;
return
true
;
}
return
false
;
}
|
回忆一下我们的业务逻辑:我们的底层数据结构中保存的是各个币种相对美元的汇率,显示的时候,我们使用列与行的比值获取两两之间的汇率。