mirror of
https://github.com/zhuzichu520/FluentUI.git
synced 2025-07-02 08:05:29 +08:00
Compare commits
28 Commits
1.7.5
...
18685b17ec
Author | SHA1 | Date | |
---|---|---|---|
18685b17ec | |||
0eb4d9f346 | |||
8015dcc2f1 | |||
0b1755e9eb | |||
e471d5a230 | |||
f922978338 | |||
91bda2a22c | |||
6638fe2e06 | |||
bf001d99d2 | |||
30531079b5 | |||
a746bc2684 | |||
96a6d0e7fa | |||
c733f3c60e | |||
effd9f3058 | |||
d93aac3518 | |||
5f6745b630 | |||
4f202831b8 | |||
29cee84edd | |||
2d4e61445e | |||
cc79854191 | |||
500efa6298 | |||
355332da96 | |||
a0d662a8a5 | |||
aecc3fe3b4 | |||
3554fb99cd | |||
24fdff7e35 | |||
d2fdd08604 | |||
1f5d6ce1aa |
@ -1292,6 +1292,7 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
|
||||
<message>
|
||||
<location filename="qml/page/T_GroupBox.qml" line="24"/>
|
||||
<source>RadioButton Group</source>
|
||||
<oldsource>RadioButton Group111111111111111111111111</oldsource>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
@ -1331,12 +1332,7 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Icons.qml" line="20"/>
|
||||
<source>Search</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Icons.qml" line="60"/>
|
||||
<location filename="qml/page/T_Icons.qml" line="51"/>
|
||||
<source>You Copied </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -1968,7 +1964,7 @@ Some contents...</source>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="177"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="478"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="509"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -1988,60 +1984,70 @@ Some contents...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="337"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="365"/>
|
||||
<source>Age</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="412"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="440"/>
|
||||
<source>Clear All</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="473"/>
|
||||
<source>Avatar</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="491"/>
|
||||
<source>Address</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="498"/>
|
||||
<source>Nickname</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="505"/>
|
||||
<source>Long String</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="513"/>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="532"/>
|
||||
<source><Previous</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="533"/>
|
||||
<source>Next></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="419"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="447"/>
|
||||
<source>Delete Selection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="443"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="470"/>
|
||||
<source>Add a row of Data</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="476"/>
|
||||
<source>Insert a Row</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="483"/>
|
||||
<source>Focus not acquired: Please click any item in the form as the target for insertion!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="514"/>
|
||||
<source>Avatar</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="528"/>
|
||||
<source>Address</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="536"/>
|
||||
<source>Nickname</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="543"/>
|
||||
<source>Long String</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="551"/>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="569"/>
|
||||
<source><Previous</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="570"/>
|
||||
<source>Next></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_Text</name>
|
||||
@ -2193,12 +2199,12 @@ Some contents...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Timeline.qml" line="115"/>
|
||||
<location filename="qml/page/T_Timeline.qml" line="114"/>
|
||||
<source>Append</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Timeline.qml" line="121"/>
|
||||
<location filename="qml/page/T_Timeline.qml" line="120"/>
|
||||
<source>clear</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -1378,6 +1378,7 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
|
||||
<message>
|
||||
<location filename="qml/page/T_GroupBox.qml" line="24"/>
|
||||
<source>RadioButton Group</source>
|
||||
<oldsource>RadioButton Group111111111111111111111111</oldsource>
|
||||
<translation type="unfinished">单选框分组</translation>
|
||||
</message>
|
||||
</context>
|
||||
@ -1417,12 +1418,11 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
|
||||
<translation type="unfinished">请输入关键字</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Icons.qml" line="20"/>
|
||||
<source>Search</source>
|
||||
<translation type="unfinished">搜索</translation>
|
||||
<translation type="obsolete">搜索</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Icons.qml" line="60"/>
|
||||
<location filename="qml/page/T_Icons.qml" line="51"/>
|
||||
<source>You Copied </source>
|
||||
<translation type="unfinished">您复制</translation>
|
||||
</message>
|
||||
@ -2110,7 +2110,7 @@ Some contents...</source>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="177"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="478"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="509"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished">名称</translation>
|
||||
</message>
|
||||
@ -2130,57 +2130,67 @@ Some contents...</source>
|
||||
<translation type="unfinished">全选</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="337"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="365"/>
|
||||
<source>Age</source>
|
||||
<translation type="unfinished">年龄</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="412"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="440"/>
|
||||
<source>Clear All</source>
|
||||
<translation type="unfinished">清除所有</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="473"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="476"/>
|
||||
<source>Insert a Row</source>
|
||||
<translation type="unfinished">插入一行</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="483"/>
|
||||
<source>Focus not acquired: Please click any item in the form as the target for insertion!</source>
|
||||
<translation type="unfinished">焦点未获取:请点击表格中的任意一项,作为插入的靶点!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="514"/>
|
||||
<source>Avatar</source>
|
||||
<translation type="unfinished">头像</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="491"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="528"/>
|
||||
<source>Address</source>
|
||||
<translation type="unfinished">地址</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="498"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="536"/>
|
||||
<source>Nickname</source>
|
||||
<translation type="unfinished">昵称</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="505"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="543"/>
|
||||
<source>Long String</source>
|
||||
<translation type="unfinished">长字符串</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="513"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="551"/>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">操作</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="532"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="569"/>
|
||||
<source><Previous</source>
|
||||
<translation type="unfinished"><上一页</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="533"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="570"/>
|
||||
<source>Next></source>
|
||||
<translation type="unfinished">下一页></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="419"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="447"/>
|
||||
<source>Delete Selection</source>
|
||||
<translation type="unfinished">删除选中</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="443"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="470"/>
|
||||
<source>Add a row of Data</source>
|
||||
<translation type="unfinished">添加一行数据</translation>
|
||||
</message>
|
||||
@ -2335,12 +2345,12 @@ Some contents...</source>
|
||||
<translation type="unfinished">时间轴</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Timeline.qml" line="115"/>
|
||||
<location filename="qml/page/T_Timeline.qml" line="114"/>
|
||||
<source>Append</source>
|
||||
<translation type="unfinished">追加</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Timeline.qml" line="121"/>
|
||||
<location filename="qml/page/T_Timeline.qml" line="120"/>
|
||||
<source>clear</source>
|
||||
<translation type="unfinished">清空</translation>
|
||||
</message>
|
||||
|
@ -14,17 +14,8 @@ FluContentPage {
|
||||
anchors{
|
||||
top: parent.top
|
||||
}
|
||||
}
|
||||
|
||||
FluFilledButton{
|
||||
text: qsTr("Search")
|
||||
anchors{
|
||||
left: text_box.right
|
||||
verticalCenter: text_box.verticalCenter
|
||||
leftMargin: 14
|
||||
}
|
||||
onClicked: {
|
||||
grid_view.model = FluApp.iconDatas(text_box.text)
|
||||
onTextChanged: {
|
||||
grid_view.model = FluApp.iconData(text_box.text)
|
||||
}
|
||||
}
|
||||
GridView{
|
||||
@ -33,7 +24,7 @@ FluContentPage {
|
||||
cellHeight: 110
|
||||
clip: true
|
||||
boundsBehavior: GridView.StopAtBounds
|
||||
model: FluApp.iconDatas()
|
||||
model: FluApp.iconData()
|
||||
ScrollBar.vertical: FluScrollBar {}
|
||||
anchors{
|
||||
topMargin: 10
|
||||
|
@ -13,7 +13,7 @@ FluContentPage{
|
||||
|
||||
property var dataSource : []
|
||||
property int sortType: 0
|
||||
property bool seletedAll: true
|
||||
property bool selectedAll: true
|
||||
property string nameKeyword: ""
|
||||
|
||||
onNameKeywordChanged: {
|
||||
@ -32,11 +32,11 @@ FluContentPage{
|
||||
onCheckBoxChanged: {
|
||||
for(var i =0;i< table_view.rows ;i++){
|
||||
if(false === table_view.getRow(i).checkbox.options.checked){
|
||||
root.seletedAll = false
|
||||
root.selectedAll = false
|
||||
return
|
||||
}
|
||||
}
|
||||
root.seletedAll = true
|
||||
root.selectedAll = true
|
||||
}
|
||||
|
||||
onSortTypeChanged: {
|
||||
@ -238,13 +238,15 @@ FluContentPage{
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
FluCheckBox{
|
||||
checked: true === root.seletedAll
|
||||
checked: true === root.selectedAll
|
||||
animationEnabled: false
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
clickListener: function(){
|
||||
root.seletedAll = !root.seletedAll
|
||||
var checked = root.seletedAll
|
||||
itemModel.display = table_view.customItem(com_column_checbox,{"checked":checked})
|
||||
root.selectedAll = !root.selectedAll
|
||||
var checked = root.selectedAll
|
||||
var columnModel = model.display
|
||||
columnModel.title = table_view.customItem(com_column_checbox,{"checked":checked})
|
||||
model.display = columnModel
|
||||
for(var i =0;i< table_view.rows ;i++){
|
||||
var rowData = table_view.getRow(i)
|
||||
rowData.checkbox = table_view.customItem(com_checbox,{"checked":checked})
|
||||
@ -271,7 +273,8 @@ FluContentPage{
|
||||
}
|
||||
Component.onCompleted: {
|
||||
currentIndex=["100","300","500","1000"].findIndex((element) => element === display)
|
||||
selectAll()
|
||||
textBox.forceActiveFocus()
|
||||
textBox.selectAll()
|
||||
}
|
||||
onCommit: {
|
||||
editTextChaged(editText)
|
||||
@ -280,6 +283,29 @@ FluContentPage{
|
||||
}
|
||||
}
|
||||
|
||||
Component{
|
||||
id:com_auto_suggestbox
|
||||
FluAutoSuggestBox {
|
||||
id: textbox
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
Component.onCompleted: {
|
||||
var data = ["傲来国界花果山水帘洞","傲来国界坎源山脏水洞","大唐国界黑风山黑风洞","大唐国界黄风岭黄风洞","大唐国界骷髅山白骨洞","宝象国界碗子山波月洞","宝象国界平顶山莲花洞","宝象国界压龙山压龙洞","乌鸡国界号山枯松涧火云洞","乌鸡国界衡阳峪黑水河河神府"]
|
||||
var result = data.map(function(item) {
|
||||
return {title: item};
|
||||
});
|
||||
items = result
|
||||
textbox.text= String(display)
|
||||
forceActiveFocus()
|
||||
selectAll()
|
||||
}
|
||||
onCommit: {
|
||||
editTextChaged(textbox.text)
|
||||
tableView.closeEditor()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component{
|
||||
id:com_avatar
|
||||
Item{
|
||||
@ -323,7 +349,9 @@ FluContentPage{
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
custom_update_dialog.showDialog(options.title,function(text){
|
||||
itemModel.display = table_view.customItem(com_column_update_title,{"title":text})
|
||||
var columnModel = model.display
|
||||
columnModel.title = table_view.customItem(com_column_update_title,{"title":text})
|
||||
model.display = columnModel
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -421,15 +449,15 @@ FluContentPage{
|
||||
var data = []
|
||||
var rows = []
|
||||
for (var i = 0; i < table_view.rows; i++) {
|
||||
var item = table_view.getRow(i);
|
||||
var item = table_view.getRow(i)
|
||||
rows.push(item)
|
||||
if (!item.checkbox.options.checked) {
|
||||
data.push(item);
|
||||
}
|
||||
}
|
||||
var sourceModel = table_view.sourceModel;
|
||||
var sourceModel = table_view.sourceModel
|
||||
for (i = 0; i < sourceModel.rowCount; i++) {
|
||||
var sourceItem = sourceModel.getRow(i);
|
||||
var sourceItem = sourceModel.getRow(i)
|
||||
const foundItem = rows.find(item=> item._key === sourceItem._key)
|
||||
if (!foundItem) {
|
||||
data.push(sourceItem);
|
||||
@ -438,14 +466,24 @@ FluContentPage{
|
||||
table_view.dataSource = data
|
||||
}
|
||||
}
|
||||
|
||||
FluButton{
|
||||
text: qsTr("Add a row of Data")
|
||||
onClicked: {
|
||||
table_view.appendRow(genTestObject())
|
||||
}
|
||||
}
|
||||
|
||||
FluButton{
|
||||
text: qsTr("Insert a Row")
|
||||
onClicked: {
|
||||
var index = table_view.currentIndex()
|
||||
if(index !== -1){
|
||||
var testObj = genTestObject()
|
||||
table_view.insertRow(index,testObj)
|
||||
}else{
|
||||
showWarning(qsTr("Focus not acquired: Please click any item in the form as the target for insertion!"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -465,20 +503,19 @@ FluContentPage{
|
||||
{
|
||||
title: table_view.customItem(com_column_checbox,{checked:true}),
|
||||
dataIndex: 'checkbox',
|
||||
width:100,
|
||||
minimumWidth:100,
|
||||
maximumWidth:100
|
||||
},
|
||||
{
|
||||
title: table_view.customItem(com_column_update_title,{title:qsTr("Avatar")}),
|
||||
dataIndex: 'avatar',
|
||||
width:100
|
||||
frozen: true
|
||||
},
|
||||
{
|
||||
title: table_view.customItem(com_column_filter_name,{title:qsTr("Name")}),
|
||||
dataIndex: 'name',
|
||||
readOnly:true
|
||||
},
|
||||
{
|
||||
title: table_view.customItem(com_column_update_title,{title:qsTr("Avatar")}),
|
||||
dataIndex: 'avatar',
|
||||
width:100,
|
||||
frozen:true
|
||||
},
|
||||
{
|
||||
title: table_view.customItem(com_column_sort_age,{sort:0}),
|
||||
dataIndex: 'age',
|
||||
@ -490,6 +527,7 @@ FluContentPage{
|
||||
{
|
||||
title: qsTr("Address"),
|
||||
dataIndex: 'address',
|
||||
editDelegate: com_auto_suggestbox,
|
||||
width:200,
|
||||
minimumWidth:100,
|
||||
maximumWidth:250
|
||||
@ -513,8 +551,7 @@ FluContentPage{
|
||||
title: qsTr("Options"),
|
||||
dataIndex: 'action',
|
||||
width:160,
|
||||
minimumWidth:160,
|
||||
maximumWidth:160
|
||||
frozen:true
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -566,7 +603,7 @@ FluContentPage{
|
||||
return avatars[randomIndex];
|
||||
}
|
||||
return {
|
||||
checkbox: table_view.customItem(com_checbox,{checked:root.seletedAll}),
|
||||
checkbox: table_view.customItem(com_checbox,{checked:root.selectedAll}),
|
||||
avatar:table_view.customItem(com_avatar,{avatar:getAvatar()}),
|
||||
name: getRandomName(),
|
||||
age:getRandomAge(),
|
||||
@ -579,7 +616,7 @@ FluContentPage{
|
||||
}
|
||||
}
|
||||
function loadData(page,count){
|
||||
root.seletedAll = true
|
||||
root.selectedAll = true
|
||||
const dataSource = []
|
||||
for(var i=0;i<count;i++){
|
||||
dataSource.push(genTestObject())
|
||||
|
@ -44,7 +44,6 @@ FluScrollablePage{
|
||||
wrapMode: Text.WrapAnywhere
|
||||
horizontalAlignment: isRight ? Qt.AlignRight : Qt.AlignLeft
|
||||
text: modelData.text
|
||||
font.bold: true
|
||||
linkColor: FluTheme.dark ? FluColors.Teal.lighter : FluColors.Teal.dark
|
||||
onLinkActivated:
|
||||
(link)=> {
|
||||
|
@ -15,7 +15,7 @@ FluWindow {
|
||||
title: "FluentUI"
|
||||
width: 1000
|
||||
height: 680
|
||||
minimumWidth: 1000
|
||||
minimumWidth: 800
|
||||
minimumHeight: 200
|
||||
launchMode: FluWindowType.SingleTask
|
||||
fitsAppBarWindows: true
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "FluApp.h"
|
||||
|
||||
#include <QQmlEngine>
|
||||
#include <QGuiApplication>
|
||||
#include <QQuickItem>
|
||||
#include <QTimer>
|
||||
@ -32,7 +31,7 @@ void FluApp::init(QObject *target, QLocale locale) {
|
||||
}
|
||||
}
|
||||
|
||||
[[maybe_unused]] QJsonArray FluApp::iconDatas(const QString &keyword) {
|
||||
[[maybe_unused]] QJsonArray FluApp::iconData(const QString &keyword) {
|
||||
QJsonArray arr;
|
||||
QMetaEnum enumType = Fluent_Icons::staticMetaObject.enumerator(Fluent_Icons::staticMetaObject.indexOfEnumerator("Fluent_IconType"));
|
||||
for (int i = 0; i <= enumType.keyCount() - 1; ++i) {
|
||||
|
@ -36,7 +36,7 @@ SINGLETON(FluApp)
|
||||
|
||||
Q_INVOKABLE void init(QObject *target, QLocale locale = QLocale::system());
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE static QJsonArray iconDatas(const QString &keyword = "");
|
||||
[[maybe_unused]] Q_INVOKABLE static QJsonArray iconData(const QString &keyword = "");
|
||||
|
||||
private:
|
||||
QQmlEngine *_engine{};
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "FluTools.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
#pragma comment (lib, "user32.lib")
|
||||
#pragma comment (lib, "dwmapi.lib")
|
||||
|
||||
@ -14,7 +15,6 @@
|
||||
#include <windowsx.h>
|
||||
#include <dwmapi.h>
|
||||
|
||||
|
||||
static inline QByteArray qtNativeEventType() {
|
||||
static const auto result = "windows_generic_MSG";
|
||||
return result;
|
||||
@ -35,15 +35,28 @@ static inline bool isCompositionEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void setShadow(HWND hwnd) {
|
||||
const MARGINS shadow = {1, 0, 0, 0};
|
||||
typedef HRESULT (WINAPI *DwmExtendFrameIntoClientAreaPtr)(HWND hWnd, const MARGINS *pMarInset);
|
||||
HMODULE module = LoadLibraryW(L"dwmapi.dll");
|
||||
if (module) {
|
||||
DwmExtendFrameIntoClientAreaPtr dwm_extendframe_into_client_area_;
|
||||
dwm_extendframe_into_client_area_ = reinterpret_cast<DwmExtendFrameIntoClientAreaPtr>(GetProcAddress(module, "DwmExtendFrameIntoClientArea"));
|
||||
if (dwm_extendframe_into_client_area_) {
|
||||
dwm_extendframe_into_client_area_(hwnd, &shadow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool containsCursorToItem(QQuickItem *item) {
|
||||
if (!item || !item->isVisible()) {
|
||||
return false;
|
||||
}
|
||||
auto point = QCursor::pos();
|
||||
auto rect = QRectF(item->mapToGlobal(QPoint(0, 0)), item->size());
|
||||
if (point.x() > rect.x() && point.x() < (rect.x() + rect.width()) && point.y() > rect.y() && point.y() < (rect.y() + rect.height())) {
|
||||
auto point = item->window()->mapFromGlobal(QCursor::pos());
|
||||
auto rect = QRectF(item->mapToItem(item->window()->contentItem(), QPointF(0, 0)), item->size());
|
||||
if (rect.contains(point)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -74,11 +87,6 @@ void FluFrameless::componentComplete() {
|
||||
int h = window()->height();
|
||||
_current = window()->winId();
|
||||
window()->setFlags((window()->flags()) | Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::FramelessWindowHint);
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
if (QQuickWindow::sceneGraphBackend() == "software") {
|
||||
window()->setFlag(Qt::FramelessWindowHint, false);
|
||||
}
|
||||
#endif
|
||||
if (!_fixSize) {
|
||||
window()->setFlag(Qt::WindowMaximizeButtonHint);
|
||||
}
|
||||
@ -97,20 +105,31 @@ void FluFrameless::componentComplete() {
|
||||
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
|
||||
DWORD style = ::GetWindowLongPtr(hwnd, GWL_STYLE);
|
||||
if (_fixSize) {
|
||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME);
|
||||
#if (QT_VERSION == QT_VERSION_CHECK(6, 5, 3) || QT_VERSION == QT_VERSION_CHECK(6, 6, 0))
|
||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME);;
|
||||
#else
|
||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME | WS_CAPTION);
|
||||
#endif
|
||||
for (int i = 0; i <= QGuiApplication::screens().count() - 1; ++i) {
|
||||
connect(QGuiApplication::screens().at(i), &QScreen::logicalDotsPerInchChanged, this, [=] {
|
||||
SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_FRAMECHANGED);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
#if (QT_VERSION == QT_VERSION_CHECK(6, 5, 3) || QT_VERSION == QT_VERSION_CHECK(6, 6, 0))
|
||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME);
|
||||
#else
|
||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION);
|
||||
#endif
|
||||
}
|
||||
SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
|
||||
connect(window(), &QQuickWindow::screenChanged, this, [hwnd] {
|
||||
::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOOWNERZORDER);
|
||||
::RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
|
||||
});
|
||||
if (!window()->property("_hideShadow").toBool()) {
|
||||
setShadow(hwnd);
|
||||
}
|
||||
#endif
|
||||
h = qRound(h + _appbar->height());
|
||||
if (_fixSize) {
|
||||
@ -141,7 +160,7 @@ void FluFrameless::componentComplete() {
|
||||
const auto uMsg = msg->message;
|
||||
const auto wParam = msg->wParam;
|
||||
const auto lParam = msg->lParam;
|
||||
static QPoint offsetXY;
|
||||
static int offsetXY;
|
||||
if (uMsg == WM_WINDOWPOSCHANGING) {
|
||||
auto *wp = reinterpret_cast<WINDOWPOS *>(lParam);
|
||||
if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0) {
|
||||
@ -150,42 +169,37 @@ void FluFrameless::componentComplete() {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else if (uMsg == WM_NCCALCSIZE) {
|
||||
const auto clientRect = ((wParam == FALSE) ? reinterpret_cast<LPRECT>(lParam) : &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam))->rgrc[0]);
|
||||
} else if (uMsg == WM_NCCALCSIZE && wParam == TRUE) {
|
||||
const auto clientRect = &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam))->rgrc[0];
|
||||
const LONG originalTop = clientRect->top;
|
||||
const LONG originalLeft = clientRect->left;
|
||||
const LONG originalRight = clientRect->right;
|
||||
const LONG originalBottom = clientRect->bottom;
|
||||
const LONG originalRight = clientRect->right;
|
||||
const LRESULT hitTestResult = ::DefWindowProcW(hwnd, WM_NCCALCSIZE, wParam, lParam);
|
||||
if ((hitTestResult != HTERROR) && (hitTestResult != HTNOWHERE)) {
|
||||
*result = static_cast<QT_NATIVE_EVENT_RESULT_TYPE>(hitTestResult);
|
||||
return true;
|
||||
}
|
||||
int offsetSize;
|
||||
bool isMaximum = ::IsZoomed(hwnd);
|
||||
auto _offsetXY = QPoint(abs(clientRect->left - originalLeft), abs(clientRect->top - originalTop));
|
||||
if (_offsetXY.x() != 0) {
|
||||
offsetXY = _offsetXY;
|
||||
if (clientRect->left - originalLeft != 0) {
|
||||
offsetXY = clientRect->left - originalLeft;
|
||||
}
|
||||
if (isMaximum || _isFullScreen()) {
|
||||
offsetSize = 0;
|
||||
} else {
|
||||
offsetSize = 1;
|
||||
}
|
||||
if (!isCompositionEnabled()) {
|
||||
offsetSize = 0;
|
||||
}
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
clientRect->top = originalTop + offsetSize;
|
||||
clientRect->bottom = originalBottom - offsetSize;
|
||||
clientRect->left = originalLeft + offsetSize;
|
||||
clientRect->right = originalRight - offsetSize;
|
||||
#if (QT_VERSION == QT_VERSION_CHECK(6, 5, 3) || QT_VERSION == QT_VERSION_CHECK(6, 6, 0))
|
||||
clientRect->top = originalTop;
|
||||
clientRect->bottom = originalBottom;
|
||||
clientRect->left = originalLeft;
|
||||
clientRect->right = originalRight;
|
||||
#else
|
||||
bool isMaximum = ::IsZoomed(hwnd);
|
||||
if (!isMaximum) {
|
||||
clientRect->top = originalTop + offsetSize;
|
||||
clientRect->bottom = originalBottom - offsetSize;
|
||||
clientRect->left = originalLeft + offsetSize;
|
||||
clientRect->right = originalRight - offsetSize;
|
||||
clientRect->top = originalTop;
|
||||
clientRect->bottom = originalBottom;
|
||||
clientRect->left = originalLeft;
|
||||
clientRect->right = originalRight;
|
||||
} else {
|
||||
clientRect->top = originalTop + offsetXY;
|
||||
clientRect->bottom = originalBottom - offsetXY;
|
||||
clientRect->left = originalLeft + offsetXY;
|
||||
clientRect->right = originalRight - offsetXY;
|
||||
}
|
||||
#endif
|
||||
_setMaximizeHovered(false);
|
||||
@ -244,6 +258,29 @@ void FluFrameless::componentComplete() {
|
||||
}
|
||||
*result = HTCLIENT;
|
||||
return true;
|
||||
} else if (uMsg == WM_NCPAINT) {
|
||||
if (isCompositionEnabled()) {
|
||||
return false;
|
||||
}
|
||||
*result = FALSE;
|
||||
return true;
|
||||
} else if (uMsg == WM_NCACTIVATE) {
|
||||
if (isCompositionEnabled()) {
|
||||
return false;
|
||||
}
|
||||
*result = TRUE;
|
||||
return true;
|
||||
} else if (uMsg == WM_GETMINMAXINFO) {
|
||||
auto *minmaxInfo = reinterpret_cast<MINMAXINFO *>(lParam);
|
||||
auto pixelRatio = window()->devicePixelRatio();
|
||||
auto geometry = window()->screen()->availableGeometry();
|
||||
RECT rect;
|
||||
SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
|
||||
minmaxInfo->ptMaxPosition.x = rect.left;
|
||||
minmaxInfo->ptMaxPosition.y = rect.top;
|
||||
minmaxInfo->ptMaxSize.x = qRound(geometry.width() * pixelRatio);
|
||||
minmaxInfo->ptMaxSize.y = qRound(geometry.height() * pixelRatio);
|
||||
return false;
|
||||
} else if (_isWindows11OrGreater && (uMsg == WM_NCLBUTTONDBLCLK || uMsg == WM_NCLBUTTONDOWN)) {
|
||||
if (_hitMaximizeButton()) {
|
||||
QMouseEvent event = QMouseEvent(QEvent::MouseButtonPress, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
||||
@ -258,38 +295,11 @@ void FluFrameless::componentComplete() {
|
||||
_setMaximizePressed(false);
|
||||
return true;
|
||||
}
|
||||
} else if (uMsg == WM_NCPAINT) {
|
||||
*result = FALSE;
|
||||
return true;
|
||||
} else if (uMsg == WM_NCACTIVATE) {
|
||||
*result = static_cast<QT_NATIVE_EVENT_RESULT_TYPE>(::DefWindowProcW(hwnd, WM_NCACTIVATE, wParam, -1));
|
||||
return true;
|
||||
} else if (uMsg == WM_GETMINMAXINFO) {
|
||||
auto *minmaxInfo = reinterpret_cast<MINMAXINFO *>(lParam);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
minmaxInfo->ptMaxPosition.x = 0;
|
||||
minmaxInfo->ptMaxPosition.y = 0;
|
||||
minmaxInfo->ptMaxSize.x = 0;
|
||||
minmaxInfo->ptMaxSize.y = 0;
|
||||
return false;
|
||||
#else
|
||||
auto pixelRatio = window()->devicePixelRatio();
|
||||
auto geometry = window()->screen()->availableGeometry();
|
||||
RECT rect;
|
||||
SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
|
||||
if (!_fixSize) {
|
||||
minmaxInfo->ptMinTrackSize.x = qRound(window()->minimumWidth() * pixelRatio + offsetXY.x());
|
||||
minmaxInfo->ptMinTrackSize.y = qRound(window()->minimumHeight() * pixelRatio + offsetXY.y() + _appbar->height() * pixelRatio);
|
||||
}
|
||||
minmaxInfo->ptMaxPosition.x = rect.left - offsetXY.x();
|
||||
minmaxInfo->ptMaxPosition.y = rect.top - offsetXY.x();
|
||||
minmaxInfo->ptMaxSize.x = qRound(geometry.width() * pixelRatio) + offsetXY.x() * 2;
|
||||
minmaxInfo->ptMaxSize.y = qRound(geometry.height() * pixelRatio) + offsetXY.y() * 2;
|
||||
return true;
|
||||
#endif
|
||||
} else if (uMsg == WM_NCRBUTTONDOWN) {
|
||||
if (wParam == HTCAPTION) {
|
||||
_showSystemMenu(QCursor::pos());
|
||||
auto pos = window()->position();
|
||||
auto offset = window()->mapFromGlobal(QCursor::pos());
|
||||
_showSystemMenu(QPoint(pos.x() + offset.x(), pos.y() + offset.y()));
|
||||
}
|
||||
} else if (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN) {
|
||||
const bool altPressed = ((wParam == VK_MENU) || (::GetKeyState(VK_MENU) < 0));
|
||||
@ -327,6 +337,15 @@ bool FluFrameless::_isFullScreen() {
|
||||
|
||||
void FluFrameless::_showSystemMenu(QPoint point) {
|
||||
#ifdef Q_OS_WIN
|
||||
QScreen *screen = window()->screen();
|
||||
if (!screen) {
|
||||
screen = QGuiApplication::primaryScreen();
|
||||
}
|
||||
if (!screen) {
|
||||
return;
|
||||
}
|
||||
const QPoint origin = screen->geometry().topLeft();
|
||||
auto nativePos = QPointF(QPointF(point - origin) * window()->devicePixelRatio()).toPoint() + origin;
|
||||
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
|
||||
DWORD style = ::GetWindowLongPtr(hwnd, GWL_STYLE);
|
||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_SYSMENU);
|
||||
@ -345,8 +364,8 @@ void FluFrameless::_showSystemMenu(QPoint point) {
|
||||
::EnableMenuItem(hMenu, SC_SIZE, MFS_DISABLED);
|
||||
::EnableMenuItem(hMenu, SC_MAXIMIZE, MFS_DISABLED);
|
||||
}
|
||||
const int result = ::TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), qRound(point.x() * window()->devicePixelRatio()),
|
||||
qRound(point.y() * window()->devicePixelRatio()), 0, hwnd, nullptr);
|
||||
const int result = ::TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), nativePos.x(),
|
||||
nativePos.y(), 0, hwnd, nullptr);
|
||||
if (result != FALSE) {
|
||||
::PostMessageW(hwnd, WM_SYSCOMMAND, result, 0);
|
||||
}
|
||||
|
73
src/FluTableModel.cpp
Normal file
73
src/FluTableModel.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include "FluTableModel.h"
|
||||
|
||||
FluTableModel::FluTableModel(QObject *parent) : QAbstractTableModel{parent} {
|
||||
|
||||
}
|
||||
|
||||
int FluTableModel::rowCount(const QModelIndex &parent) const {
|
||||
return _rows.count();
|
||||
}
|
||||
|
||||
int FluTableModel::columnCount(const QModelIndex &parent) const {
|
||||
return this->_columnSource.size();
|
||||
}
|
||||
|
||||
QVariant FluTableModel::data(const QModelIndex &index, int role) const {
|
||||
switch (role) {
|
||||
case FluTableModel::RowModel:
|
||||
return QVariant::fromValue(_rows.at(index.row()));
|
||||
case FluTableModel::ColumnModel:
|
||||
return QVariant::fromValue(_columnSource.at(index.column()));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> FluTableModel::roleNames() const {
|
||||
return {
|
||||
{FluTableModel::RowModel, "rowModel"},
|
||||
{FluTableModel::ColumnModel, "columnModel"}
|
||||
};
|
||||
}
|
||||
|
||||
QModelIndex FluTableModel::parent(const QModelIndex &child) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
QModelIndex FluTableModel::index(int row, int column, const QModelIndex &parent) const {
|
||||
if (!hasIndex(row, column, parent) || parent.isValid())
|
||||
return {};
|
||||
return createIndex(row, column);
|
||||
}
|
||||
|
||||
void FluTableModel::clear() {
|
||||
beginResetModel();
|
||||
this->_rows.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QVariant FluTableModel::getRow(int rowIndex) {
|
||||
return _rows.at(rowIndex);
|
||||
}
|
||||
|
||||
void FluTableModel::setRow(int rowIndex, QVariant row) {
|
||||
_rows.replace(rowIndex, row.toMap());
|
||||
Q_EMIT dataChanged(index(rowIndex, 0), index(rowIndex, columnCount() - 1));
|
||||
}
|
||||
|
||||
void FluTableModel::insertRow(int rowIndex, QVariant row) {
|
||||
beginInsertRows(QModelIndex(), rowIndex, rowIndex);
|
||||
_rows.insert(rowIndex, row.toMap());
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void FluTableModel::removeRow(int rowIndex, int rows) {
|
||||
beginRemoveRows(QModelIndex(), rowIndex, rowIndex + rows - 1);
|
||||
_rows = _rows.mid(0, rowIndex) + _rows.mid(rowIndex + rows);
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void FluTableModel::appendRow(QVariant row) {
|
||||
insertRow(rowCount(), row);
|
||||
}
|
51
src/FluTableModel.h
Normal file
51
src/FluTableModel.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef FLUTABLEMODEL_H
|
||||
#define FLUTABLEMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QAbstractItemModel>
|
||||
#include <QtQml/qqml.h>
|
||||
#include "stdafx.h"
|
||||
|
||||
class FluTableModel : public QAbstractTableModel {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(int, dataSourceSize)
|
||||
Q_PROPERTY_AUTO(QList<QVariantMap>, columnSource)
|
||||
Q_PROPERTY_AUTO(QList<QVariantMap>, rows)
|
||||
Q_PROPERTY(int rowCount READ rowCount CONSTANT)
|
||||
QML_NAMED_ELEMENT(FluTableModel)
|
||||
public:
|
||||
enum TableModelRoles {
|
||||
RowModel = 0x0101,
|
||||
ColumnModel = 0x0102
|
||||
};
|
||||
|
||||
explicit FluTableModel(QObject *parent = nullptr);
|
||||
|
||||
[[nodiscard]] int rowCount(const QModelIndex &parent = {}) const override;
|
||||
|
||||
[[nodiscard]] int columnCount(const QModelIndex &parent = {}) const override;
|
||||
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
[[nodiscard]] QModelIndex parent(const QModelIndex &child) const override;
|
||||
|
||||
[[nodiscard]] QModelIndex index(int row, int column, const QModelIndex &parent = {}) const override;
|
||||
|
||||
Q_INVOKABLE void clear();
|
||||
|
||||
Q_INVOKABLE QVariant getRow(int rowIndex);
|
||||
|
||||
Q_INVOKABLE void setRow(int rowIndex, QVariant row);
|
||||
|
||||
Q_INVOKABLE void insertRow(int rowIndex, QVariant row);
|
||||
|
||||
Q_INVOKABLE void removeRow(int rowIndex, int rows = 1);
|
||||
|
||||
Q_INVOKABLE void appendRow(QVariant row);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // FLUTABLEMODEL_H
|
@ -3,9 +3,8 @@
|
||||
#include <QJSValueList>
|
||||
|
||||
FluTableSortProxyModel::FluTableSortProxyModel(QSortFilterProxyModel *parent) : QSortFilterProxyModel{parent} {
|
||||
_model = nullptr;
|
||||
connect(this, &FluTableSortProxyModel::modelChanged, this, [=] {
|
||||
setSourceModel(this->model());
|
||||
setSourceModel(this->model().value<QAbstractTableModel *>());
|
||||
});
|
||||
}
|
||||
|
||||
@ -59,15 +58,18 @@ bool FluTableSortProxyModel::lessThan(const QModelIndex &source_left, const QMod
|
||||
|
||||
[[maybe_unused]] QVariant FluTableSortProxyModel::getRow(int rowIndex) {
|
||||
QVariant result;
|
||||
QMetaObject::invokeMethod(_model, "getRow", Q_RETURN_ARG(QVariant, result), Q_ARG(int, mapToSource(index(rowIndex, 0)).row()));
|
||||
QMetaObject::invokeMethod(_model.value<QAbstractTableModel *>(), "getRow", Q_RETURN_ARG(QVariant, result), Q_ARG(int, mapToSource(index(rowIndex, 0)).row()));
|
||||
return result;
|
||||
}
|
||||
|
||||
[[maybe_unused]] void FluTableSortProxyModel::setRow(int rowIndex, const QVariant &val) {
|
||||
QMetaObject::invokeMethod(_model, "setRow", Q_ARG(int, mapToSource(index(rowIndex, 0)).row()), Q_ARG(QVariant, val));
|
||||
QMetaObject::invokeMethod(_model.value<QAbstractTableModel *>(), "setRow", Q_ARG(int, mapToSource(index(rowIndex, 0)).row()), Q_ARG(QVariant, val));
|
||||
}
|
||||
|
||||
[[maybe_unused]] void FluTableSortProxyModel::insertRow(int rowIndex, const QVariant &val) {
|
||||
QMetaObject::invokeMethod(_model.value<QAbstractTableModel *>(), "insertRow", Q_ARG(int, mapToSource(index(rowIndex, 0)).row()), Q_ARG(QVariant, val));
|
||||
}
|
||||
|
||||
[[maybe_unused]] void FluTableSortProxyModel::removeRow(int rowIndex, int rows) {
|
||||
QMetaObject::invokeMethod(_model, "removeRow", Q_ARG(int, mapToSource(index(rowIndex, 0)).row()), Q_ARG(int, rows));
|
||||
QMetaObject::invokeMethod(_model.value<QAbstractTableModel *>(), "removeRow", Q_ARG(int, mapToSource(index(rowIndex, 0)).row()), Q_ARG(int, rows));
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
class FluTableSortProxyModel : public QSortFilterProxyModel {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO_P(QAbstractTableModel*, model)
|
||||
Q_PROPERTY_AUTO_P(QVariant, model)
|
||||
QML_NAMED_ELEMENT(FluTableSortProxyModel)
|
||||
public:
|
||||
explicit FluTableSortProxyModel(QSortFilterProxyModel *parent = nullptr);
|
||||
@ -23,6 +23,8 @@ public:
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE void setRow(int rowIndex, const QVariant &val);
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE void insertRow(int rowIndex, const QVariant &val);
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE void removeRow(int rowIndex, int rows);
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE void setComparator(const QJSValue &comparator);
|
||||
|
@ -95,5 +95,5 @@ SINGLETON(FluTools)
|
||||
|
||||
Q_INVOKABLE QString getWallpaperFilePath();
|
||||
|
||||
Q_INVOKABLE QColor imageMainColor(const QImage& image, double bright = 1);
|
||||
Q_INVOKABLE QColor imageMainColor(const QImage &image, double bright = 1);
|
||||
};
|
||||
|
@ -1,12 +1,11 @@
|
||||
#include "FluTreeModel.h"
|
||||
|
||||
#include <QMetaEnum>
|
||||
#include <utility>
|
||||
|
||||
FluTreeNode::FluTreeNode(QObject *parent) : QObject{parent} {
|
||||
}
|
||||
|
||||
FluTreeModel::FluTreeModel(QObject *parent) : QAbstractItemModel{parent} {
|
||||
FluTreeModel::FluTreeModel(QObject *parent) : QAbstractTableModel{parent} {
|
||||
_dataSourceSize = 0;
|
||||
}
|
||||
|
||||
@ -17,7 +16,7 @@ QModelIndex FluTreeModel::parent(const QModelIndex &child) const {
|
||||
QModelIndex FluTreeModel::index(int row, int column, const QModelIndex &parent) const {
|
||||
if (!hasIndex(row, column, parent) || parent.isValid())
|
||||
return {};
|
||||
return createIndex(row, column, _rows.at(row));
|
||||
return createIndex(row, column);
|
||||
}
|
||||
|
||||
int FluTreeModel::rowCount(const QModelIndex &parent) const {
|
||||
@ -265,7 +264,7 @@ void FluTreeModel::allCollapse() {
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QVariant FluTreeModel::selectionModel(){
|
||||
QVariant FluTreeModel::selectionModel() {
|
||||
QList<FluTreeNode *> data;
|
||||
foreach (auto item, _dataSource) {
|
||||
if (item->checked()) {
|
||||
|
@ -86,12 +86,11 @@ public:
|
||||
FluTreeNode *_parent = nullptr;
|
||||
};
|
||||
|
||||
class FluTreeModel : public QAbstractItemModel {
|
||||
class FluTreeModel : public QAbstractTableModel {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(int, dataSourceSize)
|
||||
Q_PROPERTY_AUTO(QList<QVariantMap>, columnSource)
|
||||
QML_NAMED_ELEMENT(FluTreeModel)
|
||||
QML_ADDED_IN_MINOR_VERSION(1)
|
||||
public:
|
||||
enum TreeModelRoles {
|
||||
RowModel = 0x0101,
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "FluQrCodeItem.h"
|
||||
#include "FluTableSortProxyModel.h"
|
||||
#include "FluFrameless.h"
|
||||
#include "FluTableModel.h"
|
||||
|
||||
void FluentUI::registerTypes(QQmlEngine *engine) {
|
||||
initializeEngine(engine, _uri);
|
||||
@ -32,6 +33,7 @@ void FluentUI::registerTypes(const char *uri) const {
|
||||
qmlRegisterType<FluWatermark>(uri, major, minor, "FluWatermark");
|
||||
qmlRegisterType<FluAccentColor>(uri, major, minor, "FluAccentColor");
|
||||
qmlRegisterType<FluTreeModel>(uri, major, minor, "FluTreeModel");
|
||||
qmlRegisterType<FluTableModel>(uri, major, minor, "FluTableModel");
|
||||
qmlRegisterType<FluRectangle>(uri, major, minor, "FluRectangle");
|
||||
qmlRegisterType<FluFrameless>(uri, major, minor, "FluFrameless");
|
||||
qmlRegisterType<FluTableSortProxyModel>(uri, major, minor, "FluTableSortProxyModel");
|
||||
|
@ -7,6 +7,7 @@ FluTextBox{
|
||||
property var items:[]
|
||||
property string emptyText: qsTr("No results found")
|
||||
property int autoSuggestBoxReplacement: FluentIcons.Search
|
||||
property string textRole: "title"
|
||||
property var filter: function(item){
|
||||
if(item.title.indexOf(control.text)!==-1){
|
||||
return true
|
||||
@ -25,7 +26,7 @@ FluTextBox{
|
||||
function handleClick(modelData){
|
||||
control_popup.visible = false
|
||||
control.itemClicked(modelData)
|
||||
control.updateText(modelData.title)
|
||||
control.updateText(modelData[textRole])
|
||||
}
|
||||
function loadData(){
|
||||
var result = []
|
||||
@ -48,7 +49,6 @@ FluTextBox{
|
||||
}
|
||||
Popup{
|
||||
id:control_popup
|
||||
y:control.height
|
||||
focus: false
|
||||
padding: 0
|
||||
enter: Transition {
|
||||
@ -62,7 +62,7 @@ FluTextBox{
|
||||
contentItem: FluClip{
|
||||
radius: [5,5,5,5]
|
||||
ListView{
|
||||
id:list_view
|
||||
id: list_view
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
boundsBehavior: ListView.StopAtBounds
|
||||
@ -72,7 +72,7 @@ FluTextBox{
|
||||
height: visible ? 38 : 0
|
||||
visible: list_view.count === 0
|
||||
FluText{
|
||||
text:emptyText
|
||||
text: emptyText
|
||||
anchors{
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.left
|
||||
@ -81,10 +81,10 @@ FluTextBox{
|
||||
}
|
||||
}
|
||||
delegate:FluControl{
|
||||
id:item_control
|
||||
id: item_control
|
||||
height: 38
|
||||
width: control.width
|
||||
onClicked:{
|
||||
onClicked: {
|
||||
d.handleClick(modelData)
|
||||
}
|
||||
background: Rectangle{
|
||||
@ -103,7 +103,7 @@ FluTextBox{
|
||||
}
|
||||
}
|
||||
contentItem: FluText{
|
||||
text:modelData.title
|
||||
text: modelData[textRole]
|
||||
leftPadding: 10
|
||||
rightPadding: 10
|
||||
verticalAlignment : Qt.AlignVCenter
|
||||
@ -128,7 +128,7 @@ FluTextBox{
|
||||
if(d.flagVisible){
|
||||
var pos = control.mapToItem(null, 0, 0)
|
||||
if(d.window.height>pos.y+control.height+rect_background.implicitHeight){
|
||||
control_popup.y = control.height
|
||||
control_popup.y = Qt.binding(function(){return control.height})
|
||||
} else if(pos.y>rect_background.implicitHeight){
|
||||
control_popup.y = -rect_background.implicitHeight
|
||||
} else {
|
||||
|
@ -11,6 +11,7 @@ T.ComboBox {
|
||||
property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1)
|
||||
property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1)
|
||||
property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1)
|
||||
property alias textBox: text_field
|
||||
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
|
||||
implicitContentWidth + leftPadding + rightPadding)
|
||||
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
|
||||
@ -39,6 +40,7 @@ T.ComboBox {
|
||||
opacity: enabled ? 1 : 0.3
|
||||
}
|
||||
contentItem: T.TextField {
|
||||
id: text_field
|
||||
property bool disabled: !control.editable
|
||||
leftPadding: !control.mirrored ? 10 : control.editable && activeFocus ? 3 : 1
|
||||
rightPadding: control.mirrored ? 10 : control.editable && activeFocus ? 3 : 1
|
||||
|
@ -48,9 +48,6 @@ T.MenuBarItem {
|
||||
radius: 3
|
||||
color: {
|
||||
if(control.highlighted){
|
||||
return FluTheme.itemCheckColor
|
||||
}
|
||||
if(control.hovered){
|
||||
return FluTheme.itemHoverColor
|
||||
}
|
||||
return FluTheme.itemNormalColor
|
||||
|
@ -99,9 +99,9 @@ T.MenuItem {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 3
|
||||
radius: 4
|
||||
color:{
|
||||
color: {
|
||||
if(control.highlighted){
|
||||
return FluTheme.itemCheckColor
|
||||
return FluTheme.itemHoverColor
|
||||
}
|
||||
return FluTheme.itemNormalColor
|
||||
}
|
||||
|
@ -3,98 +3,107 @@ import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import FluentUI 1.0
|
||||
|
||||
|
||||
Item {
|
||||
signal requestPage(int page,int count)
|
||||
signal requestPage(int page, int count)
|
||||
|
||||
property string previousText: qsTr("<Previous")
|
||||
property string nextText: qsTr("Next>")
|
||||
property int pageCurrent: 0
|
||||
property int itemCount: 0
|
||||
property int pageButtonCount: 5
|
||||
property int pageCount: itemCount>0?Math.ceil(itemCount/__itemPerPage):0
|
||||
property int pageCount: itemCount > 0 ? Math.ceil(itemCount / __itemPerPage) : 0
|
||||
property int __itemPerPage: 10
|
||||
property int __pageButtonHalf: Math.floor(pageButtonCount/2)+1
|
||||
property int __pageButtonHalf: Math.floor(pageButtonCount / 2) + 1
|
||||
property Component header: null
|
||||
property Component footer: null
|
||||
id: control
|
||||
implicitHeight: 40
|
||||
implicitWidth: content.width
|
||||
Row{
|
||||
Row {
|
||||
id: content
|
||||
height: control.height
|
||||
spacing: 10
|
||||
padding: 10
|
||||
FluToggleButton{
|
||||
visible: control.pageCount>1
|
||||
disabled: control.pageCurrent<=1
|
||||
text:control.previousText
|
||||
clickListener:function() {
|
||||
control.calcNewPage(control.pageCurrent-1);
|
||||
Loader {
|
||||
sourceComponent: header
|
||||
}
|
||||
FluToggleButton {
|
||||
visible: control.pageCount > 1
|
||||
disabled: control.pageCurrent <= 1
|
||||
text: control.previousText
|
||||
clickListener: function () {
|
||||
control.calcNewPage(control.pageCurrent - 1);
|
||||
}
|
||||
}
|
||||
Row{
|
||||
Row {
|
||||
spacing: 5
|
||||
FluToggleButton{
|
||||
property int pageNumber:1
|
||||
visible: control.pageCount>0
|
||||
FluToggleButton {
|
||||
property int pageNumber: 1
|
||||
visible: control.pageCount > 0
|
||||
checked: pageNumber === control.pageCurrent
|
||||
text:String(pageNumber)
|
||||
clickListener:function() {
|
||||
text: String(pageNumber)
|
||||
clickListener: function () {
|
||||
control.calcNewPage(pageNumber);
|
||||
}
|
||||
}
|
||||
FluText{
|
||||
visible: (control.pageCount>control.pageButtonCount&&
|
||||
control.pageCurrent>control.__pageButtonHalf)
|
||||
FluText {
|
||||
visible: (control.pageCount > control.pageButtonCount &&
|
||||
control.pageCurrent > control.__pageButtonHalf)
|
||||
text: "..."
|
||||
}
|
||||
Repeater{
|
||||
Repeater {
|
||||
id: button_repeator
|
||||
model: (control.pageCount<2)?0:(control.pageCount>=control.pageButtonCount)?(control.pageButtonCount-2):(control.pageCount-2)
|
||||
delegate:FluToggleButton{
|
||||
model: (control.pageCount < 2) ? 0 : (control.pageCount >= control.pageButtonCount) ? (control.pageButtonCount - 2) : (control.pageCount - 2)
|
||||
delegate: FluToggleButton {
|
||||
property int pageNumber: {
|
||||
return (control.pageCurrent<=control.__pageButtonHalf)
|
||||
?(2+index)
|
||||
:(control.pageCount-control.pageCurrent<=control.pageButtonCount-control.__pageButtonHalf)
|
||||
?(control.pageCount-button_repeator.count+index)
|
||||
:(control.pageCurrent+2+index-control.__pageButtonHalf)
|
||||
return (control.pageCurrent <= control.__pageButtonHalf)
|
||||
? (2 + index)
|
||||
: (control.pageCount - control.pageCurrent <= control.pageButtonCount - control.__pageButtonHalf)
|
||||
? (control.pageCount - button_repeator.count + index)
|
||||
: (control.pageCurrent + 2 + index - control.__pageButtonHalf)
|
||||
}
|
||||
text:String(pageNumber)
|
||||
text: String(pageNumber)
|
||||
checked: pageNumber === control.pageCurrent
|
||||
clickListener:function(){
|
||||
clickListener: function () {
|
||||
control.calcNewPage(pageNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
FluText{
|
||||
visible: (control.pageCount>control.pageButtonCount&&
|
||||
control.pageCount-control.pageCurrent>control.pageButtonCount-control.__pageButtonHalf)
|
||||
FluText {
|
||||
visible: (control.pageCount > control.pageButtonCount &&
|
||||
control.pageCount - control.pageCurrent > control.pageButtonCount - control.__pageButtonHalf)
|
||||
text: "..."
|
||||
}
|
||||
FluToggleButton{
|
||||
property int pageNumber:control.pageCount
|
||||
visible: control.pageCount>1
|
||||
FluToggleButton {
|
||||
property int pageNumber: control.pageCount
|
||||
visible: control.pageCount > 1
|
||||
checked: pageNumber === control.pageCurrent
|
||||
text:String(pageNumber)
|
||||
clickListener:function(){
|
||||
text: String(pageNumber)
|
||||
clickListener: function () {
|
||||
control.calcNewPage(pageNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
FluToggleButton{
|
||||
visible: control.pageCount>1
|
||||
disabled: control.pageCurrent>=control.pageCount
|
||||
text:control.nextText
|
||||
clickListener:function() {
|
||||
control.calcNewPage(control.pageCurrent+1);
|
||||
FluToggleButton {
|
||||
visible: control.pageCount > 1
|
||||
disabled: control.pageCurrent >= control.pageCount
|
||||
text: control.nextText
|
||||
clickListener: function () {
|
||||
control.calcNewPage(control.pageCurrent + 1);
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
sourceComponent: footer
|
||||
}
|
||||
function calcNewPage(page)
|
||||
{
|
||||
if(!page)
|
||||
}
|
||||
function calcNewPage(page) {
|
||||
if (!page)
|
||||
return
|
||||
let page_num=Number(page)
|
||||
if(page_num<1||page_num>control.pageCount||page_num===control.pageCurrent)
|
||||
let page_num = Number(page)
|
||||
if (page_num < 1 || page_num > control.pageCount || page_num === control.pageCurrent)
|
||||
return
|
||||
control.pageCurrent=page_num
|
||||
control.requestPage(page_num,control.__itemPerPage)
|
||||
control.pageCurrent = page_num
|
||||
control.requestPage(page_num, control.__itemPerPage)
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ T.ScrollBar {
|
||||
,Transition {
|
||||
to: "show"
|
||||
SequentialAnimation {
|
||||
PauseAnimation { duration: 450 }
|
||||
PauseAnimation { duration: 150 }
|
||||
NumberAnimation {
|
||||
target: rect_bar
|
||||
properties: vertical ? "width" : "height"
|
||||
|
@ -4,7 +4,7 @@ import FluentUI 1.0
|
||||
|
||||
Item {
|
||||
//高性能阴影!!!比DropShadow阴影性能高出数倍!!!
|
||||
property color color: FluTheme.dark ? "#AAAAAA" : "#999999"
|
||||
property color color: FluTheme.dark ? "#000000" : "#999999"
|
||||
property int elevation: 5
|
||||
property int radius: 4
|
||||
id:control
|
||||
|
@ -9,8 +9,10 @@ Rectangle {
|
||||
readonly property alias rows: table_view.rows
|
||||
readonly property alias columns: table_view.columns
|
||||
readonly property alias current: d.current
|
||||
readonly property alias sourceModel: table_model
|
||||
property var columnSource
|
||||
property var sourceModel:FluTableModel {
|
||||
columnSource: control.columnSource
|
||||
}
|
||||
property var columnSource: []
|
||||
property var dataSource
|
||||
property color borderColor: FluTheme.dark ? Qt.rgba(37/255,37/255,37/255,1) : Qt.rgba(228/255,228/255,228/255,1)
|
||||
property bool horizonalHeaderVisible: true
|
||||
@ -27,17 +29,20 @@ Rectangle {
|
||||
onColumnSourceChanged: {
|
||||
if(columnSource.length!==0){
|
||||
var columns= []
|
||||
var columnsData = []
|
||||
var headerRow = {}
|
||||
columnSource.forEach(function(item){
|
||||
var column = Qt.createQmlObject('import Qt.labs.qmlmodels 1.0;TableModelColumn{}',table_model);
|
||||
var offsetX = 0
|
||||
for(var i=0;i<=columnSource.length-1;i++){
|
||||
var item = columnSource[i]
|
||||
if(!item.width){
|
||||
item.width = d.defaultItemWidth
|
||||
}
|
||||
item.x = offsetX
|
||||
offsetX = offsetX + item.width
|
||||
var column = Qt.createQmlObject('import Qt.labs.qmlmodels 1.0;TableModelColumn{}',sourceModel);
|
||||
column.display = item.dataIndex
|
||||
columnsData.push(item)
|
||||
columns.push(column)
|
||||
headerRow[item.dataIndex] = item.title
|
||||
})
|
||||
d.columns_data = columnsData
|
||||
table_model.columns = columns
|
||||
headerRow[item.dataIndex] = item
|
||||
}
|
||||
header_column_model.columns = columns
|
||||
header_column_model.rows = [headerRow]
|
||||
}
|
||||
@ -48,46 +53,42 @@ Rectangle {
|
||||
property int rowHoverIndex: -1
|
||||
property int defaultItemWidth: 100
|
||||
property int defaultItemHeight: 42
|
||||
property var columns_data: []
|
||||
property var editDelegate
|
||||
property var editPosition
|
||||
signal tableItemLayout(int column)
|
||||
function getEditDelegate(column){
|
||||
var obj =d.columns_data[column].editDelegate
|
||||
var obj =control.columnSource[column].editDelegate
|
||||
if(obj){
|
||||
return obj
|
||||
}
|
||||
if(d.columns_data[column].editMultiline === true){
|
||||
if(control.columnSource[column].editMultiline === true){
|
||||
return com_edit_multiline
|
||||
}
|
||||
return com_edit
|
||||
}
|
||||
}
|
||||
onDataSourceChanged: {
|
||||
table_model.clear()
|
||||
table_model.rows = dataSource
|
||||
}
|
||||
TableModel {
|
||||
id:table_model
|
||||
TableModelColumn {}
|
||||
sourceModel.clear()
|
||||
sourceModel.rows = dataSource
|
||||
}
|
||||
TableModel{
|
||||
id:header_column_model
|
||||
TableModelColumn {}
|
||||
id: header_column_model
|
||||
TableModelColumn { display : "title"}
|
||||
}
|
||||
TableModel{
|
||||
id:header_row_model
|
||||
id: header_row_model
|
||||
TableModelColumn { display: "rowIndex" }
|
||||
}
|
||||
FluTableSortProxyModel{
|
||||
id:table_sort_model
|
||||
model: table_model
|
||||
id: table_sort_model
|
||||
model: control.sourceModel
|
||||
}
|
||||
Component{
|
||||
id:com_edit
|
||||
FluTextBox{
|
||||
id:text_box
|
||||
text: String(display)
|
||||
readOnly: true === d.columns_data[column].readOnly
|
||||
readOnly: true === control.columnSource[column].readOnly
|
||||
Component.onCompleted: {
|
||||
forceActiveFocus()
|
||||
selectAll()
|
||||
@ -113,7 +114,7 @@ Rectangle {
|
||||
TextArea.flickable: FluMultilineTextBox {
|
||||
id:text_box
|
||||
text: String(display)
|
||||
readOnly: true === d.columns_data[column].readOnly
|
||||
readOnly: true === control.columnSource[column].readOnly
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
isCtrlEnterForNewline: true
|
||||
Component.onCompleted: {
|
||||
@ -196,14 +197,39 @@ Rectangle {
|
||||
id:com_table_delegate
|
||||
MouseArea{
|
||||
id:item_table_mouse
|
||||
property var rowObject : control.getRow(row)
|
||||
property var itemModel: model
|
||||
implicitWidth: TableView.view.width
|
||||
property var _model: model
|
||||
property bool isMainTable: TableView.view == table_view
|
||||
property var currentTableView: TableView.view
|
||||
visible: {
|
||||
if(isMainTable && columnModel.frozen){
|
||||
return false
|
||||
}
|
||||
if(!isMainTable){
|
||||
if(currentTableView.dataIndex !== columnModel.dataIndex)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
property bool isRowSelected: {
|
||||
if(rowModel === null)
|
||||
return false
|
||||
if(d.current){
|
||||
return rowModel._key === d.current._key
|
||||
}
|
||||
return false
|
||||
}
|
||||
property bool editVisible: {
|
||||
if(rowObject && d.editPosition && d.editPosition._key === rowObject._key && d.editPosition.column === column){
|
||||
if(d.editPosition && d.editPosition._key === rowModel._key && d.editPosition.column === column){
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
TableView.onPooled: {
|
||||
if(d.editPosition && d.editPosition.row === row && d.editPosition.column === column){
|
||||
control.closeEditor()
|
||||
}
|
||||
}
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
d.rowHoverIndex = row
|
||||
@ -212,25 +238,37 @@ Rectangle {
|
||||
if(editVisible){
|
||||
updateEditPosition()
|
||||
}
|
||||
if(isMainTable){
|
||||
updateTableItem()
|
||||
}
|
||||
}
|
||||
onHeightChanged: {
|
||||
if(editVisible){
|
||||
updateEditPosition()
|
||||
}
|
||||
if(isMainTable){
|
||||
updateTableItem()
|
||||
}
|
||||
}
|
||||
onXChanged: {
|
||||
if(editVisible){
|
||||
updateEditPosition()
|
||||
}
|
||||
if(isMainTable){
|
||||
updateTableItem()
|
||||
}
|
||||
}
|
||||
onYChanged: {
|
||||
if(editVisible){
|
||||
updateEditPosition()
|
||||
}
|
||||
if(isMainTable){
|
||||
updateTableItem()
|
||||
}
|
||||
}
|
||||
function updateEditPosition(){
|
||||
var obj = {}
|
||||
obj._key = rowObject._key
|
||||
obj._key = rowModel._key
|
||||
obj.column = column
|
||||
obj.row = row
|
||||
obj.x = item_table_mouse.x
|
||||
@ -239,26 +277,22 @@ Rectangle {
|
||||
obj.height = item_table_mouse.height - 2
|
||||
d.editPosition = obj
|
||||
}
|
||||
function updateTableItem(){
|
||||
var columnModel = control.columnSource[column]
|
||||
columnModel.x = item_table_mouse.x
|
||||
columnModel.y = item_table_mouse.y
|
||||
d.tableItemLayout(column)
|
||||
}
|
||||
Rectangle{
|
||||
id:item_table
|
||||
anchors.fill: parent
|
||||
property point position: Qt.point(column,row)
|
||||
property bool isRowSelected: {
|
||||
if(rowObject === null)
|
||||
return false
|
||||
if(d.current){
|
||||
return rowObject._key === d.current._key
|
||||
}
|
||||
return false
|
||||
}
|
||||
color:{
|
||||
if(item_table.isRowSelected){
|
||||
if(item_table_mouse.isRowSelected){
|
||||
return control.selectedColor
|
||||
}
|
||||
if(d.rowHoverIndex === row || item_table.isRowSelected){
|
||||
if(d.rowHoverIndex === row || item_table_mouse.isRowSelected){
|
||||
return FluTheme.dark ? Qt.rgba(1,1,1,0.06) : Qt.rgba(0,0,0,0.06)
|
||||
}
|
||||
return (row%2!==0) ? control.color : (FluTheme.dark ? Qt.rgba(1,1,1,0.015) : Qt.rgba(0,0,0,0.015))
|
||||
return (row%2!==0) ? control.color : (FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03))
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
@ -271,25 +305,28 @@ Rectangle {
|
||||
onReleased: {
|
||||
}
|
||||
onDoubleClicked:{
|
||||
if(typeof(display) == "object"){
|
||||
if(item_table_loader.isObject){
|
||||
return
|
||||
}
|
||||
loader_edit.display = item_table_loader.display
|
||||
d.editDelegate = d.getEditDelegate(column)
|
||||
updateEditPosition()
|
||||
loader_edit.display = display
|
||||
item_table_mouse.updateEditPosition()
|
||||
}
|
||||
onClicked:
|
||||
(event)=>{
|
||||
d.current = rowObject
|
||||
d.current = rowModel
|
||||
control.closeEditor()
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
FluLoader{
|
||||
property var model: itemModel
|
||||
property var display: itemModel.display
|
||||
property int row: item_table.position.y
|
||||
property int column: item_table.position.x
|
||||
id: item_table_loader
|
||||
property var model: item_table_mouse._model
|
||||
property var display: rowModel[columnModel.dataIndex]
|
||||
property var rowModel : model.rowModel
|
||||
property var columnModel : model.columnModel
|
||||
property int row : model.row
|
||||
property int column: model.column
|
||||
property bool isObject: typeof(display) == "object"
|
||||
property var options: {
|
||||
if(isObject){
|
||||
@ -299,15 +336,53 @@ Rectangle {
|
||||
}
|
||||
anchors.fill: parent
|
||||
sourceComponent: {
|
||||
if(item_table_mouse.visible){
|
||||
if(isObject){
|
||||
return display.comId
|
||||
}
|
||||
return com_text
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
FluLoader{
|
||||
id: loader_edit
|
||||
property var tableView: control
|
||||
property var display
|
||||
property int column: {
|
||||
if(d.editPosition){
|
||||
return d.editPosition.column
|
||||
}
|
||||
return 0
|
||||
}
|
||||
property int row: {
|
||||
if(d.editPosition){
|
||||
return d.editPosition.row
|
||||
}
|
||||
return 0
|
||||
}
|
||||
anchors{
|
||||
fill: parent
|
||||
margins: 1
|
||||
}
|
||||
signal editTextChaged(string text)
|
||||
sourceComponent: {
|
||||
if(item_table_mouse.visible && d.editPosition && d.editPosition.column === model.column && d.editPosition.row === model.row){
|
||||
return d.editDelegate
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
onEditTextChaged:
|
||||
(text)=>{
|
||||
var obj = control.getRow(row)
|
||||
obj[control.columnSource[column].dataIndex] = text
|
||||
control.setRow(row,obj)
|
||||
}
|
||||
z:999
|
||||
}
|
||||
Item{
|
||||
anchors.fill: parent
|
||||
visible: item_table.isRowSelected
|
||||
visible: item_table_mouse.isRowSelected
|
||||
Rectangle{
|
||||
width: 1
|
||||
height: parent.height
|
||||
@ -360,24 +435,24 @@ Rectangle {
|
||||
ScrollBar.horizontal:scroll_bar_h
|
||||
ScrollBar.vertical:scroll_bar_v
|
||||
columnWidthProvider: function(column) {
|
||||
var columnObject = d.columns_data[column]
|
||||
var width = columnObject.width
|
||||
var columnModel = control.columnSource[column]
|
||||
var width = columnModel.width
|
||||
if(width){
|
||||
return width
|
||||
}
|
||||
var minimumWidth = columnObject.minimumWidth
|
||||
var minimumWidth = columnModel.minimumWidth
|
||||
if(minimumWidth){
|
||||
return minimumWidth
|
||||
}
|
||||
return d.defaultItemWidth
|
||||
}
|
||||
rowHeightProvider: function(row) {
|
||||
var rowObject = control.getRow(row)
|
||||
var height = rowObject.height
|
||||
var rowModel = control.getRow(row)
|
||||
var height = rowModel.height
|
||||
if(height){
|
||||
return height
|
||||
}
|
||||
var minimumHeight = rowObject._minimumHeight
|
||||
var minimumHeight = rowModel._minimumHeight
|
||||
if(minimumHeight){
|
||||
return minimumHeight
|
||||
}
|
||||
@ -390,70 +465,37 @@ Rectangle {
|
||||
table_view.flick(0,1)
|
||||
}
|
||||
delegate: com_table_delegate
|
||||
FluLoader{
|
||||
id:loader_edit
|
||||
property var tableView: control
|
||||
property var display
|
||||
property int column: {
|
||||
if(d.editPosition){
|
||||
return d.editPosition.column
|
||||
}
|
||||
return 0
|
||||
}
|
||||
property int row: {
|
||||
if(d.editPosition){
|
||||
return d.editPosition.row
|
||||
}
|
||||
return 0
|
||||
}
|
||||
signal editTextChaged(string text)
|
||||
sourceComponent: d.editPosition ? d.editDelegate : undefined
|
||||
onEditTextChaged:
|
||||
(text)=>{
|
||||
var obj = control.getRow(row)
|
||||
obj[d.columns_data[column].dataIndex] = text
|
||||
control.setRow(row,obj)
|
||||
}
|
||||
width: {
|
||||
if(d.editPosition){
|
||||
return d.editPosition.width
|
||||
}
|
||||
return 0
|
||||
}
|
||||
height: {
|
||||
if(d.editPosition){
|
||||
return d.editPosition.height
|
||||
}
|
||||
return 0
|
||||
}
|
||||
x:{
|
||||
if(d.editPosition){
|
||||
return d.editPosition.x
|
||||
}
|
||||
return 0
|
||||
}
|
||||
y:{
|
||||
if(d.editPosition){
|
||||
return d.editPosition.y
|
||||
}
|
||||
return 0
|
||||
}
|
||||
z:999
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component{
|
||||
id:com_column_header_delegate
|
||||
Rectangle{
|
||||
id:column_item_control
|
||||
id: column_item_control
|
||||
property var currentTableView : TableView.view
|
||||
readonly property real cellPadding: 8
|
||||
property bool canceled: false
|
||||
property int columnIndex: column
|
||||
readonly property var columnObject : d.columns_data[column]
|
||||
property var _model: model
|
||||
readonly property var columnModel : control.columnSource[_index]
|
||||
readonly property int _index : {
|
||||
const isDataIndex = (element) => {
|
||||
return element.dataIndex === display.dataIndex
|
||||
}
|
||||
return control.columnSource.findIndex(isDataIndex)
|
||||
}
|
||||
readonly property bool isHeaderHorizontal: TableView.view == header_horizontal
|
||||
implicitWidth: {
|
||||
if(column_item_control.isHeaderHorizontal){
|
||||
return (item_column_loader.item && item_column_loader.item.implicitWidth) + (cellPadding * 2)
|
||||
}
|
||||
implicitHeight: Math.max(36, (item_column_loader.item&&item_column_loader.item.implicitHeight) + (cellPadding * 2))
|
||||
return TableView.view.width
|
||||
}
|
||||
implicitHeight: {
|
||||
if(column_item_control.isHeaderHorizontal){
|
||||
return Math.max(36, (item_column_loader.item&&item_column_loader.item.implicitHeight) + (cellPadding * 2))
|
||||
}
|
||||
return TableView.view.height
|
||||
}
|
||||
color: FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(247/255,247/255,247/255,1)
|
||||
Rectangle{
|
||||
border.color: control.borderColor
|
||||
@ -474,7 +516,7 @@ Rectangle {
|
||||
width: 1
|
||||
height: parent.height
|
||||
anchors.left: parent.left
|
||||
visible: column !== 0
|
||||
visible: column_item_control._index !== 0
|
||||
color:"#00000000"
|
||||
}
|
||||
Rectangle{
|
||||
@ -483,7 +525,7 @@ Rectangle {
|
||||
height: parent.height
|
||||
anchors.right: parent.right
|
||||
color:"#00000000"
|
||||
visible: column === table_view.columns - 1
|
||||
visible: column_item_control._index === table_view.columns - 1
|
||||
}
|
||||
MouseArea{
|
||||
id:column_item_control_mouse
|
||||
@ -505,22 +547,23 @@ Rectangle {
|
||||
}
|
||||
FluLoader{
|
||||
id:item_column_loader
|
||||
property var itemModel: model
|
||||
property var modelData: model.display
|
||||
property var model: column_item_control._model
|
||||
property var display: model.display.title
|
||||
property var tableView: table_view
|
||||
property var tableModel: table_model
|
||||
property var sourceModel: control.sourceModel
|
||||
property bool isObject: typeof(display) == "object"
|
||||
property var options:{
|
||||
if(typeof(modelData) == "object"){
|
||||
return modelData.options
|
||||
if(isObject){
|
||||
return display.options
|
||||
}
|
||||
return {}
|
||||
}
|
||||
property int column: column_item_control.columnIndex
|
||||
property int column: column_item_control._index
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
sourceComponent: {
|
||||
if(typeof(modelData) == "object"){
|
||||
return modelData.comId
|
||||
if(isObject){
|
||||
return display.comId
|
||||
}
|
||||
return com_column_text
|
||||
}
|
||||
@ -532,7 +575,7 @@ Rectangle {
|
||||
anchors.right: parent.right
|
||||
acceptedButtons: Qt.LeftButton
|
||||
hoverEnabled: true
|
||||
visible: !(columnObject.width === columnObject.minimumWidth && columnObject.width === columnObject.maximumWidth && columnObject.width)
|
||||
visible: !columnModel.frozen && !(columnModel.width === columnModel.minimumWidth && columnModel.width === columnModel.maximumWidth && columnModel.width)
|
||||
cursorShape: Qt.SplitHCursor
|
||||
preventStealing: true
|
||||
onPressed :
|
||||
@ -552,9 +595,9 @@ Rectangle {
|
||||
return
|
||||
}
|
||||
var delta = Qt.point(mouse.x - clickPos.x, mouse.y - clickPos.y)
|
||||
var minimumWidth = columnObject.minimumWidth
|
||||
var maximumWidth = columnObject.maximumWidth
|
||||
var w = columnObject.width
|
||||
var minimumWidth = columnModel.minimumWidth
|
||||
var maximumWidth = columnModel.maximumWidth
|
||||
var w = columnModel.width
|
||||
if(!w){
|
||||
w = d.defaultItemWidth
|
||||
}
|
||||
@ -564,9 +607,10 @@ Rectangle {
|
||||
if(!maximumWidth){
|
||||
maximumWidth = 65535
|
||||
}
|
||||
columnObject.width = Math.min(Math.max(minimumWidth, w + delta.x),maximumWidth)
|
||||
columnModel.width = Math.min(Math.max(minimumWidth, w + delta.x),maximumWidth)
|
||||
table_view.forceLayout()
|
||||
header_horizontal.forceLayout()
|
||||
// column_item_control.currentTableView.forceLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -577,7 +621,7 @@ Rectangle {
|
||||
id:item_control
|
||||
readonly property real cellPadding: 8
|
||||
property bool canceled: false
|
||||
property var rowObject: control.getRow(row)
|
||||
property var rowModel: control.getRow(row)
|
||||
implicitWidth: Math.max(30, row_text.implicitWidth + (cellPadding * 2))
|
||||
implicitHeight: row_text.implicitHeight + (cellPadding * 2)
|
||||
color: FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(247/255,247/255,247/255,1)
|
||||
@ -643,9 +687,9 @@ Rectangle {
|
||||
cursorShape: Qt.SplitVCursor
|
||||
preventStealing: true
|
||||
visible: {
|
||||
if(rowObject === null)
|
||||
if(rowModel === null)
|
||||
return false
|
||||
return !(rowObject.height === rowObject._minimumHeight && rowObject.height === rowObject._maximumHeight && rowObject.height)
|
||||
return !(rowModel.height === rowModel._minimumHeight && rowModel.height === rowModel._maximumHeight && rowModel.height)
|
||||
}
|
||||
onPressed :
|
||||
(mouse)=>{
|
||||
@ -663,11 +707,11 @@ Rectangle {
|
||||
if(!pressed){
|
||||
return
|
||||
}
|
||||
var rowObject = control.getRow(row)
|
||||
var rowModel = control.getRow(row)
|
||||
var delta = Qt.point(mouse.x - clickPos.x, mouse.y - clickPos.y)
|
||||
var minimumHeight = rowObject._minimumHeight
|
||||
var maximumHeight = rowObject._maximumHeight
|
||||
var h = rowObject.height
|
||||
var minimumHeight = rowModel._minimumHeight
|
||||
var maximumHeight = rowModel._maximumHeight
|
||||
var h = rowModel.height
|
||||
if(!h){
|
||||
h = d.defaultItemHeight
|
||||
}
|
||||
@ -677,8 +721,8 @@ Rectangle {
|
||||
if(!maximumHeight){
|
||||
maximumHeight = 65535
|
||||
}
|
||||
rowObject.height = Math.min(Math.max(minimumHeight, h + delta.y),maximumHeight)
|
||||
control.setRow(row,rowObject)
|
||||
rowModel.height = Math.min(Math.max(minimumHeight, h + delta.y),maximumHeight)
|
||||
control.setRow(row,rowModel)
|
||||
table_view.forceLayout()
|
||||
}
|
||||
}
|
||||
@ -688,7 +732,7 @@ Rectangle {
|
||||
id:com_column_text
|
||||
FluText {
|
||||
id: column_text
|
||||
text: modelData
|
||||
text: String(display)
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@ -791,6 +835,124 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
Item{
|
||||
anchors{
|
||||
left: header_vertical.right
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
Component{
|
||||
id: com_table_frozen
|
||||
Rectangle{
|
||||
id: item_layout_frozen
|
||||
anchors.fill: parent
|
||||
color: {
|
||||
if(Window.active){
|
||||
return FluTheme.dark ? Qt.rgba(48/255,48/255,48/255,1) :Qt.rgba(1,1,1,1)
|
||||
}
|
||||
return FluTheme.dark ? Qt.rgba(56/255,56/255,56/255,1) :Qt.rgba(243/255,243/255,243/255,1)
|
||||
}
|
||||
visible: table_view.rows !== 0
|
||||
Rectangle{
|
||||
z:99
|
||||
anchors.fill: parent
|
||||
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,0.6) : Qt.rgba(191/255,191/255,191/255,0.3)
|
||||
FluShadow{
|
||||
radius: 0
|
||||
anchors.fill: parent
|
||||
}
|
||||
color: "#00000000"
|
||||
}
|
||||
TableView {
|
||||
id:item_table_frozen_header
|
||||
model: header_column_model
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
clip: true
|
||||
interactive: false
|
||||
anchors{
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
bottom: item_table_frozen.top
|
||||
}
|
||||
delegate: com_column_header_delegate
|
||||
}
|
||||
TableView{
|
||||
property string dataIndex: columnModel.dataIndex
|
||||
id: item_table_frozen
|
||||
clip: true
|
||||
interactive: false
|
||||
anchors{
|
||||
fill: parent
|
||||
topMargin: header_horizontal.height
|
||||
}
|
||||
boundsBehavior: TableView.StopAtBounds
|
||||
model: table_sort_model
|
||||
delegate: com_table_delegate
|
||||
syncDirection: Qt.Vertical
|
||||
syncView: table_view
|
||||
Component.onCompleted: {
|
||||
item_table_frozen_header.contentX = columnModel.width * _index
|
||||
item_table_frozen.contentX = columnModel.width * _index
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Repeater{
|
||||
model: control.columnSource
|
||||
delegate: FluLoader{
|
||||
id: item_layout_frozen
|
||||
readonly property int _index : model.index
|
||||
readonly property var columnModel : control.columnSource[_index]
|
||||
Connections{
|
||||
target: d
|
||||
function onTableItemLayout(column){
|
||||
if(item_layout_frozen._index === column){
|
||||
updateLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
Connections{
|
||||
target: table_view
|
||||
function onContentXChanged(){
|
||||
updateLayout()
|
||||
}
|
||||
}
|
||||
function updateLayout(){
|
||||
width = table_view.columnWidthProvider(_index)
|
||||
x = Qt.binding(function(){
|
||||
var minX = 0
|
||||
var maxX = table_view.width-item_layout_frozen.width
|
||||
for(var i=0;i<_index;i++){
|
||||
var item = control.columnSource[i]
|
||||
if(item.frozen){
|
||||
minX = minX + item.width
|
||||
}
|
||||
}
|
||||
for(i=_index+1;i<control.columnSource.length;i++){
|
||||
item = control.columnSource[i]
|
||||
if(item.frozen){
|
||||
maxX = maxX- item.width
|
||||
}
|
||||
}
|
||||
return Math.min(Math.max(columnModel.x - table_view.contentX,minX),maxX)}
|
||||
)
|
||||
}
|
||||
Component.onCompleted: {
|
||||
updateLayout()
|
||||
}
|
||||
height: control.height
|
||||
visible: {
|
||||
if(modelData.frozen){
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
sourceComponent: visible ? com_table_frozen : undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
FluScrollBar {
|
||||
id: scroll_bar_h
|
||||
anchors{
|
||||
@ -837,7 +999,7 @@ Rectangle {
|
||||
function sort(callback=undefined){
|
||||
if(callback){
|
||||
table_sort_model.setComparator(function(left,right){
|
||||
return callback(table_model.getRow(left),table_model.getRow(right))
|
||||
return callback(sourceModel.getRow(left),sourceModel.getRow(right))
|
||||
})
|
||||
}else{
|
||||
table_sort_model.setComparator(undefined)
|
||||
@ -846,7 +1008,7 @@ Rectangle {
|
||||
function filter(callback=undefined){
|
||||
if(callback){
|
||||
table_sort_model.setFilter(function(index){
|
||||
return callback(table_model.getRow(index))
|
||||
return callback(sourceModel.getRow(index))
|
||||
})
|
||||
}else{
|
||||
table_sort_model.setFilter(undefined)
|
||||
@ -868,7 +1030,26 @@ Rectangle {
|
||||
table_view.model.removeRow(rowIndex,rows)
|
||||
}
|
||||
}
|
||||
function insertRow(rowIndex,obj){
|
||||
if(rowIndex>=0 && rowIndex<table_view.rows){
|
||||
sourceModel.insertRow(rowIndex,obj)
|
||||
}
|
||||
}
|
||||
function currentIndex(){
|
||||
var index = -1
|
||||
if(!d.current){
|
||||
return index
|
||||
}
|
||||
for (var i = 0; i <= sourceModel.rowCount-1; i++) {
|
||||
var sourceItem = sourceModel.getRow(i);
|
||||
if(sourceItem._key === d.current._key){
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
return index
|
||||
}
|
||||
function appendRow(obj){
|
||||
table_model.appendRow(obj)
|
||||
sourceModel.appendRow(obj)
|
||||
}
|
||||
}
|
||||
|
@ -60,8 +60,9 @@ Window {
|
||||
signal lazyLoad()
|
||||
property var _windowRegister
|
||||
property string _route
|
||||
id:window
|
||||
color:"transparent"
|
||||
property bool _hideShadow: false
|
||||
id: window
|
||||
color: FluTools.isSoftware() ? window.backgroundColor : "transparent"
|
||||
Component.onCompleted: {
|
||||
FluRouter.addWindow(window)
|
||||
useSystemAppBar = FluApp.useSystemAppBar
|
||||
@ -142,7 +143,7 @@ Window {
|
||||
}
|
||||
Timer{
|
||||
id:timer_update_image
|
||||
interval: 500
|
||||
interval: 150
|
||||
onTriggered: {
|
||||
img_back.source = ""
|
||||
img_back.source = FluTools.getUrlByFilePath(FluTheme.desktopImagePath)
|
||||
@ -279,13 +280,7 @@ Window {
|
||||
id:loader_border
|
||||
anchors.fill: parent
|
||||
sourceComponent: {
|
||||
if(window.useSystemAppBar){
|
||||
return undefined
|
||||
}
|
||||
if(FluTools.isWindows10OrGreater()){
|
||||
return undefined
|
||||
}
|
||||
if(window.visibility === Window.Maximized || window.visibility === Window.FullScreen){
|
||||
if(window.useSystemAppBar || FluTools.isWin() || window.visibility === Window.Maximized || window.visibility === Window.FullScreen){
|
||||
return undefined
|
||||
}
|
||||
return com_border
|
||||
@ -307,7 +302,6 @@ Window {
|
||||
info_bar.showError(text,duration,moremsg)
|
||||
}
|
||||
function moveWindowToDesktopCenter(){
|
||||
screen = Qt.application.screens[FluTools.cursorScreenIndex()]
|
||||
var availableGeometry = FluTools.desktopAvailableGeometry(window)
|
||||
window.setGeometry((availableGeometry.width-window.width)/2+Screen.virtualX,(availableGeometry.height-window.height)/2+Screen.virtualY,window.width,window.height)
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ FluTextBox{
|
||||
property var items:[]
|
||||
property string emptyText: qsTr("No results found")
|
||||
property int autoSuggestBoxReplacement: FluentIcons.Search
|
||||
property string textRole: "title"
|
||||
property var filter: function(item){
|
||||
if(item.title.indexOf(control.text)!==-1){
|
||||
return true
|
||||
@ -24,7 +25,7 @@ FluTextBox{
|
||||
function handleClick(modelData){
|
||||
control_popup.visible = false
|
||||
control.itemClicked(modelData)
|
||||
control.updateText(modelData.title)
|
||||
control.updateText(modelData[textRole])
|
||||
}
|
||||
function loadData(){
|
||||
var result = []
|
||||
@ -47,7 +48,6 @@ FluTextBox{
|
||||
}
|
||||
Popup{
|
||||
id:control_popup
|
||||
y:control.height
|
||||
focus: false
|
||||
padding: 0
|
||||
enter: Transition {
|
||||
@ -61,7 +61,7 @@ FluTextBox{
|
||||
contentItem: FluClip{
|
||||
radius: [5,5,5,5]
|
||||
ListView{
|
||||
id:list_view
|
||||
id: list_view
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
boundsBehavior: ListView.StopAtBounds
|
||||
@ -71,7 +71,7 @@ FluTextBox{
|
||||
height: visible ? 38 : 0
|
||||
visible: list_view.count === 0
|
||||
FluText{
|
||||
text:emptyText
|
||||
text: emptyText
|
||||
anchors{
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.left
|
||||
@ -80,10 +80,10 @@ FluTextBox{
|
||||
}
|
||||
}
|
||||
delegate:FluControl{
|
||||
id:item_control
|
||||
id: item_control
|
||||
height: 38
|
||||
width: control.width
|
||||
onClicked:{
|
||||
onClicked: {
|
||||
d.handleClick(modelData)
|
||||
}
|
||||
background: Rectangle{
|
||||
@ -102,7 +102,7 @@ FluTextBox{
|
||||
}
|
||||
}
|
||||
contentItem: FluText{
|
||||
text:modelData.title
|
||||
text: modelData[textRole]
|
||||
leftPadding: 10
|
||||
rightPadding: 10
|
||||
verticalAlignment : Qt.AlignVCenter
|
||||
@ -127,7 +127,7 @@ FluTextBox{
|
||||
if(d.flagVisible){
|
||||
var pos = control.mapToItem(null, 0, 0)
|
||||
if(d.window.height>pos.y+control.height+rect_background.implicitHeight){
|
||||
control_popup.y = control.height
|
||||
control_popup.y = Qt.binding(function(){return control.height})
|
||||
} else if(pos.y>rect_background.implicitHeight){
|
||||
control_popup.y = -rect_background.implicitHeight
|
||||
} else {
|
||||
|
@ -11,6 +11,7 @@ T.ComboBox {
|
||||
property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1)
|
||||
property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1)
|
||||
property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1)
|
||||
property alias textBox: text_field
|
||||
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
|
||||
implicitContentWidth + leftPadding + rightPadding)
|
||||
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
|
||||
@ -39,6 +40,7 @@ T.ComboBox {
|
||||
opacity: enabled ? 1 : 0.3
|
||||
}
|
||||
contentItem: T.TextField {
|
||||
id: text_field
|
||||
property bool disabled: !control.editable
|
||||
leftPadding: !control.mirrored ? 10 : control.editable && activeFocus ? 3 : 1
|
||||
rightPadding: control.mirrored ? 10 : control.editable && activeFocus ? 3 : 1
|
||||
|
@ -49,9 +49,6 @@ T.MenuBarItem {
|
||||
radius: 3
|
||||
color: {
|
||||
if(control.highlighted){
|
||||
return FluTheme.itemCheckColor
|
||||
}
|
||||
if(control.hovered){
|
||||
return FluTheme.itemHoverColor
|
||||
}
|
||||
return FluTheme.itemNormalColor
|
||||
|
@ -100,9 +100,9 @@ T.MenuItem {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 3
|
||||
radius: 4
|
||||
color:{
|
||||
color: {
|
||||
if(control.highlighted){
|
||||
return FluTheme.itemCheckColor
|
||||
return FluTheme.itemHoverColor
|
||||
}
|
||||
return FluTheme.itemNormalColor
|
||||
}
|
||||
|
@ -4,97 +4,105 @@ import QtQuick.Layouts
|
||||
import FluentUI
|
||||
|
||||
Item {
|
||||
signal requestPage(int page,int count)
|
||||
signal requestPage(int page, int count)
|
||||
|
||||
property string previousText: qsTr("<Previous")
|
||||
property string nextText: qsTr("Next>")
|
||||
property int pageCurrent: 0
|
||||
property int itemCount: 0
|
||||
property int pageButtonCount: 5
|
||||
property int pageCount: itemCount>0?Math.ceil(itemCount/__itemPerPage):0
|
||||
property int pageCount: itemCount > 0 ? Math.ceil(itemCount / __itemPerPage) : 0
|
||||
property int __itemPerPage: 10
|
||||
property int __pageButtonHalf: Math.floor(pageButtonCount/2)+1
|
||||
property int __pageButtonHalf: Math.floor(pageButtonCount / 2) + 1
|
||||
property Component header: null
|
||||
property Component footer: null
|
||||
id: control
|
||||
implicitHeight: 40
|
||||
implicitWidth: content.width
|
||||
Row{
|
||||
Row {
|
||||
id: content
|
||||
height: control.height
|
||||
spacing: 10
|
||||
padding: 10
|
||||
FluToggleButton{
|
||||
visible: control.pageCount>1
|
||||
disabled: control.pageCurrent<=1
|
||||
text:control.previousText
|
||||
clickListener:function() {
|
||||
control.calcNewPage(control.pageCurrent-1);
|
||||
Loader {
|
||||
sourceComponent: header
|
||||
}
|
||||
FluToggleButton {
|
||||
visible: control.pageCount > 1
|
||||
disabled: control.pageCurrent <= 1
|
||||
text: control.previousText
|
||||
clickListener: function () {
|
||||
control.calcNewPage(control.pageCurrent - 1);
|
||||
}
|
||||
}
|
||||
Row{
|
||||
Row {
|
||||
spacing: 5
|
||||
FluToggleButton{
|
||||
property int pageNumber:1
|
||||
visible: control.pageCount>0
|
||||
FluToggleButton {
|
||||
property int pageNumber: 1
|
||||
visible: control.pageCount > 0
|
||||
checked: pageNumber === control.pageCurrent
|
||||
text:String(pageNumber)
|
||||
clickListener:function() {
|
||||
text: String(pageNumber)
|
||||
clickListener: function () {
|
||||
control.calcNewPage(pageNumber);
|
||||
}
|
||||
}
|
||||
FluText{
|
||||
visible: (control.pageCount>control.pageButtonCount&&
|
||||
control.pageCurrent>control.__pageButtonHalf)
|
||||
FluText {
|
||||
visible: (control.pageCount > control.pageButtonCount &&
|
||||
control.pageCurrent > control.__pageButtonHalf)
|
||||
text: "..."
|
||||
}
|
||||
Repeater{
|
||||
Repeater {
|
||||
id: button_repeator
|
||||
model: (control.pageCount<2)?0:(control.pageCount>=control.pageButtonCount)?(control.pageButtonCount-2):(control.pageCount-2)
|
||||
delegate:FluToggleButton{
|
||||
model: (control.pageCount < 2) ? 0 : (control.pageCount >= control.pageButtonCount) ? (control.pageButtonCount - 2) : (control.pageCount - 2)
|
||||
delegate: FluToggleButton {
|
||||
property int pageNumber: {
|
||||
return (control.pageCurrent<=control.__pageButtonHalf)
|
||||
?(2+index)
|
||||
:(control.pageCount-control.pageCurrent<=control.pageButtonCount-control.__pageButtonHalf)
|
||||
?(control.pageCount-button_repeator.count+index)
|
||||
:(control.pageCurrent+2+index-control.__pageButtonHalf)
|
||||
return (control.pageCurrent <= control.__pageButtonHalf)
|
||||
? (2 + index)
|
||||
: (control.pageCount - control.pageCurrent <= control.pageButtonCount - control.__pageButtonHalf)
|
||||
? (control.pageCount - button_repeator.count + index)
|
||||
: (control.pageCurrent + 2 + index - control.__pageButtonHalf)
|
||||
}
|
||||
text:String(pageNumber)
|
||||
text: String(pageNumber)
|
||||
checked: pageNumber === control.pageCurrent
|
||||
clickListener:function(){
|
||||
clickListener: function () {
|
||||
control.calcNewPage(pageNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
FluText{
|
||||
visible: (control.pageCount>control.pageButtonCount&&
|
||||
control.pageCount-control.pageCurrent>control.pageButtonCount-control.__pageButtonHalf)
|
||||
FluText {
|
||||
visible: (control.pageCount > control.pageButtonCount &&
|
||||
control.pageCount - control.pageCurrent > control.pageButtonCount - control.__pageButtonHalf)
|
||||
text: "..."
|
||||
}
|
||||
FluToggleButton{
|
||||
property int pageNumber:control.pageCount
|
||||
visible: control.pageCount>1
|
||||
FluToggleButton {
|
||||
property int pageNumber: control.pageCount
|
||||
visible: control.pageCount > 1
|
||||
checked: pageNumber === control.pageCurrent
|
||||
text:String(pageNumber)
|
||||
clickListener:function(){
|
||||
text: String(pageNumber)
|
||||
clickListener: function () {
|
||||
control.calcNewPage(pageNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
FluToggleButton{
|
||||
visible: control.pageCount>1
|
||||
disabled: control.pageCurrent>=control.pageCount
|
||||
text:control.nextText
|
||||
clickListener:function() {
|
||||
control.calcNewPage(control.pageCurrent+1);
|
||||
FluToggleButton {
|
||||
visible: control.pageCount > 1
|
||||
disabled: control.pageCurrent >= control.pageCount
|
||||
text: control.nextText
|
||||
clickListener: function () {
|
||||
control.calcNewPage(control.pageCurrent + 1);
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
sourceComponent: footer
|
||||
}
|
||||
function calcNewPage(page)
|
||||
{
|
||||
if(!page)
|
||||
}
|
||||
function calcNewPage(page) {
|
||||
if (!page)
|
||||
return
|
||||
let page_num=Number(page)
|
||||
if(page_num<1||page_num>control.pageCount||page_num===control.pageCurrent)
|
||||
let page_num = Number(page)
|
||||
if (page_num < 1 || page_num > control.pageCount || page_num === control.pageCurrent)
|
||||
return
|
||||
control.pageCurrent=page_num
|
||||
control.requestPage(page_num,control.__itemPerPage)
|
||||
control.pageCurrent = page_num
|
||||
control.requestPage(page_num, control.__itemPerPage)
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,9 @@ QtObject {
|
||||
var launchMode = win.launchMode
|
||||
if(launchMode === 1){
|
||||
win.argument = argument
|
||||
win.show()
|
||||
if(!win.visible){
|
||||
win.visible = true
|
||||
}
|
||||
win.raise()
|
||||
win.requestActivate()
|
||||
return
|
||||
|
@ -173,7 +173,7 @@ T.ScrollBar {
|
||||
,Transition {
|
||||
to: "show"
|
||||
SequentialAnimation {
|
||||
PauseAnimation { duration: 450 }
|
||||
PauseAnimation { duration: 150 }
|
||||
NumberAnimation {
|
||||
target: rect_bar
|
||||
properties: vertical ? "width" : "height"
|
||||
|
@ -4,7 +4,7 @@ import FluentUI
|
||||
|
||||
Item {
|
||||
//高性能阴影!!!比DropShadow阴影性能高出数倍!!!
|
||||
property color color: FluTheme.dark ? "#AAAAAA" : "#999999"
|
||||
property color color: FluTheme.dark ? "#000000" : "#999999"
|
||||
property int elevation: 5
|
||||
property int radius: 4
|
||||
id:control
|
||||
|
@ -9,8 +9,10 @@ Rectangle {
|
||||
readonly property alias rows: table_view.rows
|
||||
readonly property alias columns: table_view.columns
|
||||
readonly property alias current: d.current
|
||||
readonly property alias sourceModel: table_model
|
||||
property var columnSource
|
||||
property var sourceModel:FluTableModel {
|
||||
columnSource: control.columnSource
|
||||
}
|
||||
property var columnSource: []
|
||||
property var dataSource
|
||||
property color borderColor: FluTheme.dark ? Qt.rgba(37/255,37/255,37/255,1) : Qt.rgba(228/255,228/255,228/255,1)
|
||||
property bool horizonalHeaderVisible: true
|
||||
@ -27,17 +29,20 @@ Rectangle {
|
||||
onColumnSourceChanged: {
|
||||
if(columnSource.length!==0){
|
||||
var columns= []
|
||||
var columnsData = []
|
||||
var headerRow = {}
|
||||
columnSource.forEach(function(item){
|
||||
var column = Qt.createQmlObject('import Qt.labs.qmlmodels 1.0;TableModelColumn{}',table_model);
|
||||
var offsetX = 0
|
||||
for(var i=0;i<=columnSource.length-1;i++){
|
||||
var item = columnSource[i]
|
||||
if(!item.width){
|
||||
item.width = d.defaultItemWidth
|
||||
}
|
||||
item.x = offsetX
|
||||
offsetX = offsetX + item.width
|
||||
var column = Qt.createQmlObject('import Qt.labs.qmlmodels 1.0;TableModelColumn{}',sourceModel);
|
||||
column.display = item.dataIndex
|
||||
columnsData.push(item)
|
||||
columns.push(column)
|
||||
headerRow[item.dataIndex] = item.title
|
||||
})
|
||||
d.columns_data = columnsData
|
||||
table_model.columns = columns
|
||||
headerRow[item.dataIndex] = item
|
||||
}
|
||||
header_column_model.columns = columns
|
||||
header_column_model.rows = [headerRow]
|
||||
}
|
||||
@ -48,46 +53,42 @@ Rectangle {
|
||||
property int rowHoverIndex: -1
|
||||
property int defaultItemWidth: 100
|
||||
property int defaultItemHeight: 42
|
||||
property var columns_data: []
|
||||
property var editDelegate
|
||||
property var editPosition
|
||||
signal tableItemLayout(int column)
|
||||
function getEditDelegate(column){
|
||||
var obj =d.columns_data[column].editDelegate
|
||||
var obj =control.columnSource[column].editDelegate
|
||||
if(obj){
|
||||
return obj
|
||||
}
|
||||
if(d.columns_data[column].editMultiline === true){
|
||||
if(control.columnSource[column].editMultiline === true){
|
||||
return com_edit_multiline
|
||||
}
|
||||
return com_edit
|
||||
}
|
||||
}
|
||||
onDataSourceChanged: {
|
||||
table_model.clear()
|
||||
table_model.rows = dataSource
|
||||
}
|
||||
TableModel {
|
||||
id:table_model
|
||||
TableModelColumn {}
|
||||
sourceModel.clear()
|
||||
sourceModel.rows = dataSource
|
||||
}
|
||||
TableModel{
|
||||
id:header_column_model
|
||||
TableModelColumn {}
|
||||
id: header_column_model
|
||||
TableModelColumn { display : "title"}
|
||||
}
|
||||
TableModel{
|
||||
id:header_row_model
|
||||
id: header_row_model
|
||||
TableModelColumn { display: "rowIndex" }
|
||||
}
|
||||
FluTableSortProxyModel{
|
||||
id:table_sort_model
|
||||
model: table_model
|
||||
id: table_sort_model
|
||||
model: control.sourceModel
|
||||
}
|
||||
Component{
|
||||
id:com_edit
|
||||
FluTextBox{
|
||||
id:text_box
|
||||
text: String(display)
|
||||
readOnly: true === d.columns_data[column].readOnly
|
||||
readOnly: true === control.columnSource[column].readOnly
|
||||
Component.onCompleted: {
|
||||
forceActiveFocus()
|
||||
selectAll()
|
||||
@ -113,7 +114,7 @@ Rectangle {
|
||||
TextArea.flickable: FluMultilineTextBox {
|
||||
id:text_box
|
||||
text: String(display)
|
||||
readOnly: true === d.columns_data[column].readOnly
|
||||
readOnly: true === control.columnSource[column].readOnly
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
isCtrlEnterForNewline: true
|
||||
Component.onCompleted: {
|
||||
@ -196,14 +197,39 @@ Rectangle {
|
||||
id:com_table_delegate
|
||||
MouseArea{
|
||||
id:item_table_mouse
|
||||
property var rowObject : control.getRow(row)
|
||||
property var itemModel: model
|
||||
implicitWidth: TableView.view.width
|
||||
property var _model: model
|
||||
property bool isMainTable: TableView.view == table_view
|
||||
property var currentTableView: TableView.view
|
||||
visible: {
|
||||
if(isMainTable && columnModel.frozen){
|
||||
return false
|
||||
}
|
||||
if(!isMainTable){
|
||||
if(currentTableView.dataIndex !== columnModel.dataIndex)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
property bool isRowSelected: {
|
||||
if(rowModel === null)
|
||||
return false
|
||||
if(d.current){
|
||||
return rowModel._key === d.current._key
|
||||
}
|
||||
return false
|
||||
}
|
||||
property bool editVisible: {
|
||||
if(rowObject && d.editPosition && d.editPosition._key === rowObject._key && d.editPosition.column === column){
|
||||
if(d.editPosition && d.editPosition._key === rowModel._key && d.editPosition.column === column){
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
TableView.onPooled: {
|
||||
if(d.editPosition && d.editPosition.row === row && d.editPosition.column === column){
|
||||
control.closeEditor()
|
||||
}
|
||||
}
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
d.rowHoverIndex = row
|
||||
@ -212,25 +238,37 @@ Rectangle {
|
||||
if(editVisible){
|
||||
updateEditPosition()
|
||||
}
|
||||
if(isMainTable){
|
||||
updateTableItem()
|
||||
}
|
||||
}
|
||||
onHeightChanged: {
|
||||
if(editVisible){
|
||||
updateEditPosition()
|
||||
}
|
||||
if(isMainTable){
|
||||
updateTableItem()
|
||||
}
|
||||
}
|
||||
onXChanged: {
|
||||
if(editVisible){
|
||||
updateEditPosition()
|
||||
}
|
||||
if(isMainTable){
|
||||
updateTableItem()
|
||||
}
|
||||
}
|
||||
onYChanged: {
|
||||
if(editVisible){
|
||||
updateEditPosition()
|
||||
}
|
||||
if(isMainTable){
|
||||
updateTableItem()
|
||||
}
|
||||
}
|
||||
function updateEditPosition(){
|
||||
var obj = {}
|
||||
obj._key = rowObject._key
|
||||
obj._key = rowModel._key
|
||||
obj.column = column
|
||||
obj.row = row
|
||||
obj.x = item_table_mouse.x
|
||||
@ -239,26 +277,22 @@ Rectangle {
|
||||
obj.height = item_table_mouse.height - 2
|
||||
d.editPosition = obj
|
||||
}
|
||||
function updateTableItem(){
|
||||
var columnModel = control.columnSource[column]
|
||||
columnModel.x = item_table_mouse.x
|
||||
columnModel.y = item_table_mouse.y
|
||||
d.tableItemLayout(column)
|
||||
}
|
||||
Rectangle{
|
||||
id:item_table
|
||||
anchors.fill: parent
|
||||
property point position: Qt.point(column,row)
|
||||
property bool isRowSelected: {
|
||||
if(rowObject === null)
|
||||
return false
|
||||
if(d.current){
|
||||
return rowObject._key === d.current._key
|
||||
}
|
||||
return false
|
||||
}
|
||||
color:{
|
||||
if(item_table.isRowSelected){
|
||||
if(item_table_mouse.isRowSelected){
|
||||
return control.selectedColor
|
||||
}
|
||||
if(d.rowHoverIndex === row || item_table.isRowSelected){
|
||||
if(d.rowHoverIndex === row || item_table_mouse.isRowSelected){
|
||||
return FluTheme.dark ? Qt.rgba(1,1,1,0.06) : Qt.rgba(0,0,0,0.06)
|
||||
}
|
||||
return (row%2!==0) ? control.color : (FluTheme.dark ? Qt.rgba(1,1,1,0.015) : Qt.rgba(0,0,0,0.015))
|
||||
return (row%2!==0) ? control.color : (FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03))
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
@ -271,25 +305,28 @@ Rectangle {
|
||||
onReleased: {
|
||||
}
|
||||
onDoubleClicked:{
|
||||
if(typeof(display) == "object"){
|
||||
if(item_table_loader.isObject){
|
||||
return
|
||||
}
|
||||
loader_edit.display = item_table_loader.display
|
||||
d.editDelegate = d.getEditDelegate(column)
|
||||
updateEditPosition()
|
||||
loader_edit.display = display
|
||||
item_table_mouse.updateEditPosition()
|
||||
}
|
||||
onClicked:
|
||||
(event)=>{
|
||||
d.current = rowObject
|
||||
d.current = rowModel
|
||||
control.closeEditor()
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
FluLoader{
|
||||
property var model: itemModel
|
||||
property var display: itemModel.display
|
||||
property int row: item_table.position.y
|
||||
property int column: item_table.position.x
|
||||
id: item_table_loader
|
||||
property var model: item_table_mouse._model
|
||||
property var display: rowModel[columnModel.dataIndex]
|
||||
property var rowModel : model.rowModel
|
||||
property var columnModel : model.columnModel
|
||||
property int row : model.row
|
||||
property int column: model.column
|
||||
property bool isObject: typeof(display) == "object"
|
||||
property var options: {
|
||||
if(isObject){
|
||||
@ -299,15 +336,53 @@ Rectangle {
|
||||
}
|
||||
anchors.fill: parent
|
||||
sourceComponent: {
|
||||
if(item_table_mouse.visible){
|
||||
if(isObject){
|
||||
return display.comId
|
||||
}
|
||||
return com_text
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
FluLoader{
|
||||
id: loader_edit
|
||||
property var tableView: control
|
||||
property var display
|
||||
property int column: {
|
||||
if(d.editPosition){
|
||||
return d.editPosition.column
|
||||
}
|
||||
return 0
|
||||
}
|
||||
property int row: {
|
||||
if(d.editPosition){
|
||||
return d.editPosition.row
|
||||
}
|
||||
return 0
|
||||
}
|
||||
anchors{
|
||||
fill: parent
|
||||
margins: 1
|
||||
}
|
||||
signal editTextChaged(string text)
|
||||
sourceComponent: {
|
||||
if(item_table_mouse.visible && d.editPosition && d.editPosition.column === model.column && d.editPosition.row === model.row){
|
||||
return d.editDelegate
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
onEditTextChaged:
|
||||
(text)=>{
|
||||
var obj = control.getRow(row)
|
||||
obj[control.columnSource[column].dataIndex] = text
|
||||
control.setRow(row,obj)
|
||||
}
|
||||
z:999
|
||||
}
|
||||
Item{
|
||||
anchors.fill: parent
|
||||
visible: item_table.isRowSelected
|
||||
visible: item_table_mouse.isRowSelected
|
||||
Rectangle{
|
||||
width: 1
|
||||
height: parent.height
|
||||
@ -360,24 +435,24 @@ Rectangle {
|
||||
ScrollBar.horizontal:scroll_bar_h
|
||||
ScrollBar.vertical:scroll_bar_v
|
||||
columnWidthProvider: function(column) {
|
||||
var columnObject = d.columns_data[column]
|
||||
var width = columnObject.width
|
||||
var columnModel = control.columnSource[column]
|
||||
var width = columnModel.width
|
||||
if(width){
|
||||
return width
|
||||
}
|
||||
var minimumWidth = columnObject.minimumWidth
|
||||
var minimumWidth = columnModel.minimumWidth
|
||||
if(minimumWidth){
|
||||
return minimumWidth
|
||||
}
|
||||
return d.defaultItemWidth
|
||||
}
|
||||
rowHeightProvider: function(row) {
|
||||
var rowObject = control.getRow(row)
|
||||
var height = rowObject.height
|
||||
var rowModel = control.getRow(row)
|
||||
var height = rowModel.height
|
||||
if(height){
|
||||
return height
|
||||
}
|
||||
var minimumHeight = rowObject._minimumHeight
|
||||
var minimumHeight = rowModel._minimumHeight
|
||||
if(minimumHeight){
|
||||
return minimumHeight
|
||||
}
|
||||
@ -390,70 +465,37 @@ Rectangle {
|
||||
table_view.flick(0,1)
|
||||
}
|
||||
delegate: com_table_delegate
|
||||
FluLoader{
|
||||
id:loader_edit
|
||||
property var tableView: control
|
||||
property var display
|
||||
property int column: {
|
||||
if(d.editPosition){
|
||||
return d.editPosition.column
|
||||
}
|
||||
return 0
|
||||
}
|
||||
property int row: {
|
||||
if(d.editPosition){
|
||||
return d.editPosition.row
|
||||
}
|
||||
return 0
|
||||
}
|
||||
signal editTextChaged(string text)
|
||||
sourceComponent: d.editPosition ? d.editDelegate : undefined
|
||||
onEditTextChaged:
|
||||
(text)=>{
|
||||
var obj = control.getRow(row)
|
||||
obj[d.columns_data[column].dataIndex] = text
|
||||
control.setRow(row,obj)
|
||||
}
|
||||
width: {
|
||||
if(d.editPosition){
|
||||
return d.editPosition.width
|
||||
}
|
||||
return 0
|
||||
}
|
||||
height: {
|
||||
if(d.editPosition){
|
||||
return d.editPosition.height
|
||||
}
|
||||
return 0
|
||||
}
|
||||
x:{
|
||||
if(d.editPosition){
|
||||
return d.editPosition.x
|
||||
}
|
||||
return 0
|
||||
}
|
||||
y:{
|
||||
if(d.editPosition){
|
||||
return d.editPosition.y
|
||||
}
|
||||
return 0
|
||||
}
|
||||
z:999
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component{
|
||||
id:com_column_header_delegate
|
||||
Rectangle{
|
||||
id:column_item_control
|
||||
id: column_item_control
|
||||
property var currentTableView : TableView.view
|
||||
readonly property real cellPadding: 8
|
||||
property bool canceled: false
|
||||
property int columnIndex: column
|
||||
readonly property var columnObject : d.columns_data[column]
|
||||
property var _model: model
|
||||
readonly property var columnModel : control.columnSource[_index]
|
||||
readonly property int _index : {
|
||||
const isDataIndex = (element) => {
|
||||
return element.dataIndex === display.dataIndex
|
||||
}
|
||||
return control.columnSource.findIndex(isDataIndex)
|
||||
}
|
||||
readonly property bool isHeaderHorizontal: TableView.view == header_horizontal
|
||||
implicitWidth: {
|
||||
if(column_item_control.isHeaderHorizontal){
|
||||
return (item_column_loader.item && item_column_loader.item.implicitWidth) + (cellPadding * 2)
|
||||
}
|
||||
implicitHeight: Math.max(36, (item_column_loader.item&&item_column_loader.item.implicitHeight) + (cellPadding * 2))
|
||||
return TableView.view.width
|
||||
}
|
||||
implicitHeight: {
|
||||
if(column_item_control.isHeaderHorizontal){
|
||||
return Math.max(36, (item_column_loader.item&&item_column_loader.item.implicitHeight) + (cellPadding * 2))
|
||||
}
|
||||
return TableView.view.height
|
||||
}
|
||||
color: FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(247/255,247/255,247/255,1)
|
||||
Rectangle{
|
||||
border.color: control.borderColor
|
||||
@ -474,7 +516,7 @@ Rectangle {
|
||||
width: 1
|
||||
height: parent.height
|
||||
anchors.left: parent.left
|
||||
visible: column !== 0
|
||||
visible: column_item_control._index !== 0
|
||||
color:"#00000000"
|
||||
}
|
||||
Rectangle{
|
||||
@ -483,7 +525,7 @@ Rectangle {
|
||||
height: parent.height
|
||||
anchors.right: parent.right
|
||||
color:"#00000000"
|
||||
visible: column === table_view.columns - 1
|
||||
visible: column_item_control._index === table_view.columns - 1
|
||||
}
|
||||
MouseArea{
|
||||
id:column_item_control_mouse
|
||||
@ -505,22 +547,23 @@ Rectangle {
|
||||
}
|
||||
FluLoader{
|
||||
id:item_column_loader
|
||||
property var itemModel: model
|
||||
property var modelData: model.display
|
||||
property var model: column_item_control._model
|
||||
property var display: model.display.title
|
||||
property var tableView: table_view
|
||||
property var tableModel: table_model
|
||||
property var sourceModel: control.sourceModel
|
||||
property bool isObject: typeof(display) == "object"
|
||||
property var options:{
|
||||
if(typeof(modelData) == "object"){
|
||||
return modelData.options
|
||||
if(isObject){
|
||||
return display.options
|
||||
}
|
||||
return {}
|
||||
}
|
||||
property int column: column_item_control.columnIndex
|
||||
property int column: column_item_control._index
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
sourceComponent: {
|
||||
if(typeof(modelData) == "object"){
|
||||
return modelData.comId
|
||||
if(isObject){
|
||||
return display.comId
|
||||
}
|
||||
return com_column_text
|
||||
}
|
||||
@ -532,7 +575,7 @@ Rectangle {
|
||||
anchors.right: parent.right
|
||||
acceptedButtons: Qt.LeftButton
|
||||
hoverEnabled: true
|
||||
visible: !(columnObject.width === columnObject.minimumWidth && columnObject.width === columnObject.maximumWidth && columnObject.width)
|
||||
visible: !columnModel.frozen && !(columnModel.width === columnModel.minimumWidth && columnModel.width === columnModel.maximumWidth && columnModel.width)
|
||||
cursorShape: Qt.SplitHCursor
|
||||
preventStealing: true
|
||||
onPressed :
|
||||
@ -552,9 +595,9 @@ Rectangle {
|
||||
return
|
||||
}
|
||||
var delta = Qt.point(mouse.x - clickPos.x, mouse.y - clickPos.y)
|
||||
var minimumWidth = columnObject.minimumWidth
|
||||
var maximumWidth = columnObject.maximumWidth
|
||||
var w = columnObject.width
|
||||
var minimumWidth = columnModel.minimumWidth
|
||||
var maximumWidth = columnModel.maximumWidth
|
||||
var w = columnModel.width
|
||||
if(!w){
|
||||
w = d.defaultItemWidth
|
||||
}
|
||||
@ -564,9 +607,10 @@ Rectangle {
|
||||
if(!maximumWidth){
|
||||
maximumWidth = 65535
|
||||
}
|
||||
columnObject.width = Math.min(Math.max(minimumWidth, w + delta.x),maximumWidth)
|
||||
columnModel.width = Math.min(Math.max(minimumWidth, w + delta.x),maximumWidth)
|
||||
table_view.forceLayout()
|
||||
header_horizontal.forceLayout()
|
||||
// column_item_control.currentTableView.forceLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -577,7 +621,7 @@ Rectangle {
|
||||
id:item_control
|
||||
readonly property real cellPadding: 8
|
||||
property bool canceled: false
|
||||
property var rowObject: control.getRow(row)
|
||||
property var rowModel: control.getRow(row)
|
||||
implicitWidth: Math.max(30, row_text.implicitWidth + (cellPadding * 2))
|
||||
implicitHeight: row_text.implicitHeight + (cellPadding * 2)
|
||||
color: FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(247/255,247/255,247/255,1)
|
||||
@ -643,9 +687,9 @@ Rectangle {
|
||||
cursorShape: Qt.SplitVCursor
|
||||
preventStealing: true
|
||||
visible: {
|
||||
if(rowObject === null)
|
||||
if(rowModel === null)
|
||||
return false
|
||||
return !(rowObject.height === rowObject._minimumHeight && rowObject.height === rowObject._maximumHeight && rowObject.height)
|
||||
return !(rowModel.height === rowModel._minimumHeight && rowModel.height === rowModel._maximumHeight && rowModel.height)
|
||||
}
|
||||
onPressed :
|
||||
(mouse)=>{
|
||||
@ -663,11 +707,11 @@ Rectangle {
|
||||
if(!pressed){
|
||||
return
|
||||
}
|
||||
var rowObject = control.getRow(row)
|
||||
var rowModel = control.getRow(row)
|
||||
var delta = Qt.point(mouse.x - clickPos.x, mouse.y - clickPos.y)
|
||||
var minimumHeight = rowObject._minimumHeight
|
||||
var maximumHeight = rowObject._maximumHeight
|
||||
var h = rowObject.height
|
||||
var minimumHeight = rowModel._minimumHeight
|
||||
var maximumHeight = rowModel._maximumHeight
|
||||
var h = rowModel.height
|
||||
if(!h){
|
||||
h = d.defaultItemHeight
|
||||
}
|
||||
@ -677,8 +721,8 @@ Rectangle {
|
||||
if(!maximumHeight){
|
||||
maximumHeight = 65535
|
||||
}
|
||||
rowObject.height = Math.min(Math.max(minimumHeight, h + delta.y),maximumHeight)
|
||||
control.setRow(row,rowObject)
|
||||
rowModel.height = Math.min(Math.max(minimumHeight, h + delta.y),maximumHeight)
|
||||
control.setRow(row,rowModel)
|
||||
table_view.forceLayout()
|
||||
}
|
||||
}
|
||||
@ -688,7 +732,7 @@ Rectangle {
|
||||
id:com_column_text
|
||||
FluText {
|
||||
id: column_text
|
||||
text: modelData
|
||||
text: String(display)
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@ -791,6 +835,124 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
Item{
|
||||
anchors{
|
||||
left: header_vertical.right
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
Component{
|
||||
id: com_table_frozen
|
||||
Rectangle{
|
||||
id: item_layout_frozen
|
||||
anchors.fill: parent
|
||||
color: {
|
||||
if(Window.active){
|
||||
return FluTheme.dark ? Qt.rgba(48/255,48/255,48/255,1) :Qt.rgba(1,1,1,1)
|
||||
}
|
||||
return FluTheme.dark ? Qt.rgba(56/255,56/255,56/255,1) :Qt.rgba(243/255,243/255,243/255,1)
|
||||
}
|
||||
visible: table_view.rows !== 0
|
||||
Rectangle{
|
||||
z:99
|
||||
anchors.fill: parent
|
||||
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,0.6) : Qt.rgba(191/255,191/255,191/255,0.3)
|
||||
FluShadow{
|
||||
radius: 0
|
||||
anchors.fill: parent
|
||||
}
|
||||
color: "#00000000"
|
||||
}
|
||||
TableView {
|
||||
id:item_table_frozen_header
|
||||
model: header_column_model
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
clip: true
|
||||
interactive: false
|
||||
anchors{
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
bottom: item_table_frozen.top
|
||||
}
|
||||
delegate: com_column_header_delegate
|
||||
}
|
||||
TableView{
|
||||
property string dataIndex: columnModel.dataIndex
|
||||
id: item_table_frozen
|
||||
clip: true
|
||||
interactive: false
|
||||
anchors{
|
||||
fill: parent
|
||||
topMargin: header_horizontal.height
|
||||
}
|
||||
boundsBehavior: TableView.StopAtBounds
|
||||
model: table_sort_model
|
||||
delegate: com_table_delegate
|
||||
syncDirection: Qt.Vertical
|
||||
syncView: table_view
|
||||
Component.onCompleted: {
|
||||
item_table_frozen_header.contentX = columnModel.width * _index
|
||||
item_table_frozen.contentX = columnModel.width * _index
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Repeater{
|
||||
model: control.columnSource
|
||||
delegate: FluLoader{
|
||||
id: item_layout_frozen
|
||||
readonly property int _index : model.index
|
||||
readonly property var columnModel : control.columnSource[_index]
|
||||
Connections{
|
||||
target: d
|
||||
function onTableItemLayout(column){
|
||||
if(item_layout_frozen._index === column){
|
||||
updateLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
Connections{
|
||||
target: table_view
|
||||
function onContentXChanged(){
|
||||
updateLayout()
|
||||
}
|
||||
}
|
||||
function updateLayout(){
|
||||
width = table_view.columnWidthProvider(_index)
|
||||
x = Qt.binding(function(){
|
||||
var minX = 0
|
||||
var maxX = table_view.width-item_layout_frozen.width
|
||||
for(var i=0;i<_index;i++){
|
||||
var item = control.columnSource[i]
|
||||
if(item.frozen){
|
||||
minX = minX + item.width
|
||||
}
|
||||
}
|
||||
for(i=_index+1;i<control.columnSource.length;i++){
|
||||
item = control.columnSource[i]
|
||||
if(item.frozen){
|
||||
maxX = maxX- item.width
|
||||
}
|
||||
}
|
||||
return Math.min(Math.max(columnModel.x - table_view.contentX,minX),maxX)}
|
||||
)
|
||||
}
|
||||
Component.onCompleted: {
|
||||
updateLayout()
|
||||
}
|
||||
height: control.height
|
||||
visible: {
|
||||
if(modelData.frozen){
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
sourceComponent: visible ? com_table_frozen : undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
FluScrollBar {
|
||||
id: scroll_bar_h
|
||||
anchors{
|
||||
@ -837,7 +999,7 @@ Rectangle {
|
||||
function sort(callback=undefined){
|
||||
if(callback){
|
||||
table_sort_model.setComparator(function(left,right){
|
||||
return callback(table_model.getRow(left),table_model.getRow(right))
|
||||
return callback(sourceModel.getRow(left),sourceModel.getRow(right))
|
||||
})
|
||||
}else{
|
||||
table_sort_model.setComparator(undefined)
|
||||
@ -846,7 +1008,7 @@ Rectangle {
|
||||
function filter(callback=undefined){
|
||||
if(callback){
|
||||
table_sort_model.setFilter(function(index){
|
||||
return callback(table_model.getRow(index))
|
||||
return callback(sourceModel.getRow(index))
|
||||
})
|
||||
}else{
|
||||
table_sort_model.setFilter(undefined)
|
||||
@ -868,7 +1030,26 @@ Rectangle {
|
||||
table_view.model.removeRow(rowIndex,rows)
|
||||
}
|
||||
}
|
||||
function insertRow(rowIndex,obj){
|
||||
if(rowIndex>=0 && rowIndex<table_view.rows){
|
||||
sourceModel.insertRow(rowIndex,obj)
|
||||
}
|
||||
}
|
||||
function currentIndex(){
|
||||
var index = -1
|
||||
if(!d.current){
|
||||
return index
|
||||
}
|
||||
for (var i = 0; i <= sourceModel.rowCount-1; i++) {
|
||||
var sourceItem = sourceModel.getRow(i);
|
||||
if(sourceItem._key === d.current._key){
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
return index
|
||||
}
|
||||
function appendRow(obj){
|
||||
table_model.appendRow(obj)
|
||||
sourceModel.appendRow(obj)
|
||||
}
|
||||
}
|
||||
|
@ -59,8 +59,9 @@ Window {
|
||||
signal lazyLoad()
|
||||
property var _windowRegister
|
||||
property string _route
|
||||
id:window
|
||||
color:"transparent"
|
||||
property bool _hideShadow: false
|
||||
id: window
|
||||
color: FluTools.isSoftware() ? window.backgroundColor : "transparent"
|
||||
Component.onCompleted: {
|
||||
FluRouter.addWindow(window)
|
||||
useSystemAppBar = FluApp.useSystemAppBar
|
||||
@ -141,7 +142,7 @@ Window {
|
||||
}
|
||||
Timer{
|
||||
id:timer_update_image
|
||||
interval: 500
|
||||
interval: 150
|
||||
onTriggered: {
|
||||
img_back.source = ""
|
||||
img_back.source = FluTools.getUrlByFilePath(FluTheme.desktopImagePath)
|
||||
@ -278,13 +279,7 @@ Window {
|
||||
id:loader_border
|
||||
anchors.fill: parent
|
||||
sourceComponent: {
|
||||
if(window.useSystemAppBar){
|
||||
return undefined
|
||||
}
|
||||
if(FluTools.isWindows10OrGreater()){
|
||||
return undefined
|
||||
}
|
||||
if(window.visibility === Window.Maximized || window.visibility === Window.FullScreen){
|
||||
if(window.useSystemAppBar || FluTools.isWin() || window.visibility === Window.Maximized || window.visibility === Window.FullScreen){
|
||||
return undefined
|
||||
}
|
||||
return com_border
|
||||
@ -306,7 +301,6 @@ Window {
|
||||
info_bar.showError(text,duration,moremsg)
|
||||
}
|
||||
function moveWindowToDesktopCenter(){
|
||||
screen = Qt.application.screens[FluTools.cursorScreenIndex()]
|
||||
var availableGeometry = FluTools.desktopAvailableGeometry(window)
|
||||
window.setGeometry((availableGeometry.width-window.width)/2+Screen.virtualX,(availableGeometry.height-window.height)/2+Screen.virtualY,window.width,window.height)
|
||||
}
|
||||
|
Reference in New Issue
Block a user