Compare commits

..

28 Commits

Author SHA1 Message Date
18685b17ec update 2024-05-03 16:56:40 +08:00
0eb4d9f346 update 2024-05-03 01:54:38 +08:00
8015dcc2f1 update 2024-05-02 23:52:30 +08:00
0b1755e9eb update 2024-05-01 01:11:25 +08:00
e471d5a230 update 2024-04-30 19:38:05 +08:00
f922978338 update 2024-04-30 19:27:57 +08:00
91bda2a22c update 2024-04-30 13:07:46 +08:00
6638fe2e06 update 2024-04-30 13:06:27 +08:00
bf001d99d2 update 2024-04-30 12:59:09 +08:00
30531079b5 update 2024-04-29 10:12:34 +08:00
a746bc2684 update 2024-04-28 21:05:43 +08:00
96a6d0e7fa update 2024-04-28 20:22:05 +08:00
c733f3c60e update 2024-04-28 18:38:37 +08:00
effd9f3058 update 2024-04-28 18:19:21 +08:00
d93aac3518 update 2024-04-28 15:56:37 +08:00
5f6745b630 udpate 2024-04-28 13:03:20 +08:00
4f202831b8 Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2024-04-28 10:51:29 +08:00
29cee84edd update 2024-04-28 10:51:13 +08:00
2d4e61445e Merge pull request #488 from yanhuacuo/path-for-insertRow
Add the functionality to insert new rows into the table
2024-04-28 10:47:28 +08:00
cc79854191 Merge pull request #489 from w-jt/main
FluPagination.qml 添加自定义控件,通过header和footer属性添加控件
2024-04-28 10:46:47 +08:00
500efa6298 添加自定义控件,通过header和footer属性添加控件
添加自定义控件,通过header和footer属性添加控件
2024-04-27 11:54:42 +08:00
355332da96 添加自定义控件,通过header和footer属性添加控件
添加自定义控件,通过header和footer属性添加控件
2024-04-27 11:53:57 +08:00
a0d662a8a5 添加自定义控件,通过header和footer属性添加控件
添加自定义控件,通过header和footer属性添加控件
2024-04-27 11:49:29 +08:00
aecc3fe3b4 添加自定义控件,通过header和footer属性添加控件
添加自定义控件,通过header和footer属性添加控件
2024-04-27 11:48:19 +08:00
3554fb99cd Add the functionality to insert new rows into the table 2024-04-27 09:40:37 +08:00
24fdff7e35 fix bug 2024-04-25 00:08:18 +08:00
d2fdd08604 update 2024-04-24 17:24:31 +08:00
1f5d6ce1aa update 2024-04-24 17:12:00 +08:00
36 changed files with 1294 additions and 738 deletions

View File

@ -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>&lt;Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="533"/>
<source>Next&gt;</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>&lt;Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="570"/>
<source>Next&gt;</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>

View File

@ -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>&lt;Previous</source>
<translation type="unfinished">&lt;上一页</translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="533"/>
<location filename="qml/page/T_TableView.qml" line="570"/>
<source>Next&gt;</source>
<translation type="unfinished">下一页&gt;</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>

View File

@ -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

View File

@ -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())

View File

@ -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)=> {

View File

@ -15,7 +15,7 @@ FluWindow {
title: "FluentUI"
width: 1000
height: 680
minimumWidth: 1000
minimumWidth: 800
minimumHeight: 200
launchMode: FluWindowType.SingleTask
fitsAppBarWindows: true

View File

@ -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) {

View File

@ -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{};

View File

@ -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
View 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
View 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

View File

@ -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));
}

View File

@ -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);

View File

@ -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);
};

View File

@ -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()) {

View File

@ -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,

View File

@ -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");

View File

@ -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 {

View File

@ -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

View File

@ -48,9 +48,6 @@ T.MenuBarItem {
radius: 3
color: {
if(control.highlighted){
return FluTheme.itemCheckColor
}
if(control.hovered){
return FluTheme.itemHoverColor
}
return FluTheme.itemNormalColor

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -171,7 +171,7 @@ T.ScrollBar {
,Transition {
to: "show"
SequentialAnimation {
PauseAnimation { duration: 450 }
PauseAnimation { duration: 150 }
NumberAnimation {
target: rect_bar
properties: vertical ? "width" : "height"

View File

@ -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

View File

@ -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)
}
}

View File

@ -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)
}

View File

@ -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 {

View File

@ -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

View File

@ -49,9 +49,6 @@ T.MenuBarItem {
radius: 3
color: {
if(control.highlighted){
return FluTheme.itemCheckColor
}
if(control.hovered){
return FluTheme.itemHoverColor
}
return FluTheme.itemNormalColor

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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

View File

@ -173,7 +173,7 @@ T.ScrollBar {
,Transition {
to: "show"
SequentialAnimation {
PauseAnimation { duration: 450 }
PauseAnimation { duration: 150 }
NumberAnimation {
target: rect_bar
properties: vertical ? "width" : "height"

View File

@ -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

View File

@ -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)
}
}

View File

@ -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)
}