This commit is contained in:
zhuzichu 2023-09-18 18:10:27 +08:00
parent 257f3a7b3d
commit b27a88d261
8 changed files with 150 additions and 105 deletions

View File

@ -87,22 +87,20 @@ FluScrollablePage {
}
FluSlider{
id:slider_width
value: 200
value: 280
from: 160
to:400
}
}
FluToggleSwitch{
id:switch_showline
text:"showLine"
checked: true
}
FluToggleSwitch{
id:switch_draggable
text:"draggable"
checked: false
checked: true
}
}
}

View File

@ -155,7 +155,7 @@ void FluTreeModel::expand(int row){
}
void FluTreeModel::dragAnddrop(int dragIndex,int dropIndex){
if(dragIndex == dropIndex+1){
if(dragIndex == dropIndex+1 || dropIndex>_rows.count() || dropIndex<0){
return;
}
auto dragItem = _rows[dragIndex];
@ -164,29 +164,48 @@ void FluTreeModel::dragAnddrop(int dragIndex,int dropIndex){
return;
}
if(dragItem->_parent == dropItem->_parent){
if(dragItem->hasChildren()){
}else{
QList<Node*>* children = &(dragItem->_parent->_children);
int srcIndex = children->indexOf(dragItem);
int destIndex = children->indexOf(dropItem);
children->move(srcIndex,destIndex>srcIndex? destIndex : destIndex +1);
_rows.move(dragIndex,dropIndex>dragIndex? dropIndex : dropIndex+1);
}
QList<Node*>* children = &(dragItem->_parent->_children);
int srcIndex = children->indexOf(dragItem);
int destIndex = children->indexOf(dropItem);
children->move(srcIndex,destIndex>srcIndex? destIndex : destIndex +1);
_rows.move(dragIndex,dropIndex>dragIndex? dropIndex : dropIndex+1);
}else{
QList<Node*>* srcChildren = &(dragItem->_parent->_children);
QList<Node*>* destChildren = &(dropItem->_parent->_children);
int srcIndex = srcChildren->indexOf(dragItem);
int destIndex = destChildren->indexOf(dropItem);
dragItem->_depth = dropItem->_depth;
dragItem->_parent = dropItem->_parent;
if(dragItem->hasChildren()){
}else{
QList<Node*>* srcChildren = &(dragItem->_parent->_children);
QList<Node*>* destChildren = &(dropItem->_parent->_children);
int srcIndex = srcChildren->indexOf(dragItem);
int destIndex = destChildren->indexOf(dropItem);
dragItem->_depth = dropItem->_depth;
dragItem->_parent = dropItem->_parent;
srcChildren->removeAt(srcIndex);
destChildren->insert(destIndex+1,dragItem);
_rows.move(dragIndex,dropIndex>dragIndex? dropIndex : dropIndex+1);
QList<Node*> stack = dragItem->_children;
foreach (auto node, stack) {
node->_depth = dragItem->_depth+1;
}
std::reverse(stack.begin(), stack.end());
while (stack.count() > 0) {
auto item = stack.at(stack.count()-1);
stack.pop_back();
QList<Node*> children = item->_children;
if(!children.isEmpty()){
std::reverse(children.begin(), children.end());
foreach (auto c, children) {
c->_depth = item->_depth+1;
stack.append(c);
}
}
}
}
srcChildren->removeAt(srcIndex);
destChildren->insert(destIndex+1,dragItem);
_rows.move(dragIndex,dropIndex>dragIndex? dropIndex : dropIndex+1);
}
endMoveRows();
}
void FluTreeModel::refreshNode(int row){
Q_EMIT dataChanged(index(row,0),index(row,0));
};
Node* FluTreeModel::getNode(int row){
return _rows.at(row);
}

View File

@ -20,6 +20,26 @@ public:
Q_INVOKABLE int depth(){return _depth;};
Q_INVOKABLE bool isExpanded(){return _isExpanded;};
Q_INVOKABLE bool hasChildren(){ return !_children.isEmpty();};
Q_INVOKABLE bool isHeaderNode(){
if(hasChildren() && _isExpanded){
return true;
}
return false;
}
Q_INVOKABLE bool isFooterNode(){
return this->_parent->_children.indexOf(this) == this->_parent->_children.count()-1;
}
Q_INVOKABLE bool hasNextNodeByIndex(int index){
Node* p = this;
for(int i=0;i<(_depth - index -1);i++){
p = p->_parent;
}
if(p->_parent->_children.indexOf(p) == p->_parent->_children.count()-1){
return false;
}
return true;
}
Q_INVOKABLE bool hideLineFooter(){
if(_parent){
auto childIndex = _parent->_children.indexOf(this);
@ -72,6 +92,8 @@ public:
Q_INVOKABLE void collapse(int row);
Q_INVOKABLE void expand(int row);
Q_INVOKABLE void dragAnddrop(int dragIndex,int dropIndex);
Q_INVOKABLE Node* getNode(int row);
Q_INVOKABLE void refreshNode(int row);
private:
QList<Node*> _rows;
QList<Node*> _dataSource;

View File

@ -13,11 +13,14 @@ Rectangle{
property string closeText : "关闭"
property color textColor: FluTheme.dark ? "#FFFFFF" : "#000000"
property color minimizeNormalColor: Qt.rgba(0,0,0,0)
property color minimizeHoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.1) : Qt.rgba(0,0,0,0.06)
property color minimizeHoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03)
property color minimizePressColor: FluTheme.dark ? Qt.rgba(1,1,1,0.06) : Qt.rgba(0,0,0,0.06)
property color maximizeNormalColor: Qt.rgba(0,0,0,0)
property color maximizeHoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.1) : Qt.rgba(0,0,0,0.06)
property color maximizeHoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03)
property color maximizePressColor: FluTheme.dark ? Qt.rgba(1,1,1,0.06) : Qt.rgba(0,0,0,0.06)
property color closeNormalColor: Qt.rgba(0,0,0,0)
property color closeHoverColor: Qt.rgba(251/255,115/255,115/255,1)
property color closePressColor: Qt.rgba(251/255,115/255,115/255,0.8)
property bool showDark: false
property bool showClose: true
property bool showMinimize: true
@ -114,7 +117,12 @@ Rectangle{
radius: 0
visible: !isMac && showMinimize
iconColor: control.textColor
color: hovered ? minimizeHoverColor : minimizeNormalColor
color: {
if(pressed){
return minimizePressColor
}
return hovered ? minimizeHoverColor : minimizeNormalColor
}
onClicked: minClickListener()
}
FluIconButton{
@ -122,7 +130,12 @@ Rectangle{
Layout.preferredWidth: 40
Layout.preferredHeight: 30
iconSource : d.isRestore ? FluentIcons.ChromeRestore : FluentIcons.ChromeMaximize
color: hovered ? maximizeHoverColor : maximizeNormalColor
color: {
if(pressed){
return maximizePressColor
}
return hovered ? maximizeHoverColor : maximizeNormalColor
}
Layout.alignment: Qt.AlignVCenter
visible: d.resizable && !isMac && showMaximize
radius: 0
@ -142,7 +155,12 @@ Rectangle{
radius: 0
iconSize: 10
iconColor: hovered ? Qt.rgba(1,1,1,1) : control.textColor
color:hovered ? closeHoverColor : closeNormalColor
color:{
if(pressed){
return closePressColor
}
return hovered ? closeHoverColor : closeNormalColor
}
onClicked: closeClickListener()
}
}

View File

@ -8,9 +8,8 @@ Rectangle {
id:control
color:Qt.rgba(0,0,0,0)
height: spacing*2+separator.height
Rectangle{
FluRectangle{
id:separator
clip: true
color: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(210/255,210/255,210/255,1)
width:parent.width
anchors.centerIn: parent

View File

@ -56,6 +56,8 @@ Item {
return w
}
height: 30
implicitWidth: width
implicitHeight: height
function toggle(){
if(itemModel.isExpanded){
tree_model.collapse(rowIndex)
@ -63,33 +65,6 @@ Item {
tree_model.expand(rowIndex)
}
}
Rectangle{
anchors.fill: parent
radius: 4
anchors.leftMargin: 6
anchors.rightMargin: 6
border.color: d.hitColor
border.width: d.dragIndex === rowIndex ? 1 : 0
color: {
if(FluTheme.dark){
if(isCurrent){
return Qt.rgba(1,1,1,0.03)
}
if(item_mouse.containsMouse){
return Qt.rgba(1,1,1,0.03)
}
return Qt.rgba(0,0,0,0)
}else{
if(isCurrent){
return Qt.rgba(0,0,0,0.06)
}
if(item_mouse.containsMouse){
return Qt.rgba(0,0,0,0.03)
}
return Qt.rgba(0,0,0,0)
}
}
}
Rectangle{
width: 3
height: 18
@ -104,6 +79,7 @@ Item {
}
MouseArea{
id:item_mouse
property point clickPos: Qt.point(0,0)
anchors.fill: parent
drag.target:control.draggable ? loader_container : undefined
hoverEnabled: true
@ -116,15 +92,18 @@ Item {
loader_container.sourceComponent = com_item_container
}
}
onPressed: {
loader_container.itemControl = itemControl
loader_container.itemModel = itemModel
var cellPosition = item_container.mapToItem(table_view, 0, 0)
loader_container.width = item_container.width
loader_container.height = item_container.height
loader_container.x = table_view.contentX + cellPosition.x
loader_container.y = table_view.contentY + cellPosition.y
}
onPressed: (mouse)=>{
clickPos = Qt.point(mouse.x,mouse.y)
console.debug(clickPos)
loader_container.itemControl = itemControl
loader_container.itemModel = itemModel
var cellPosition = item_container.mapToItem(table_view, 0, 0)
loader_container.width = item_container.width
loader_container.height = item_container.height
loader_container.x = table_view.contentX + cellPosition.x
loader_container.y = table_view.contentY + cellPosition.y
}
onClicked: {
d.current = itemModel
}
@ -151,6 +130,7 @@ Item {
var index = Math.round(y/30)
if(index !== d.dragIndex){
d.dropIndex = index
tree_model.refreshNode(rowIndex)
}else{
d.dropIndex = -1
}
@ -174,10 +154,11 @@ Item {
anchors{
left: parent.left
leftMargin: {
var count = itemModel.depth+1
if(itemModel.hasChildren()){
return 30*(itemModel.depth+1) - 8
return 30*count - 8
}
return 30*(itemModel.depth+1) + 18
return 30*count + 18
}
right: parent.right
rightMargin: 10
@ -202,10 +183,10 @@ Item {
}
}
}
Rectangle{
FluRectangle{
width: 1
color: control.lineColor
visible: itemModel.depth !== 0 && control.showLine && !itemModel.hasChildren()
visible: control.showLine && isItemLoader && itemModel.depth !== 0 && !itemModel.hasChildren()
height: itemModel.hideLineFooter() ? parent.height/2 : parent.height
anchors{
top: parent.top
@ -213,10 +194,10 @@ Item {
rightMargin: -9
}
}
Rectangle{
FluRectangle{
height: 1
color: control.lineColor
visible: itemModel.depth !== 0 && control.showLine && !itemModel.hasChildren()
visible: control.showLine && isItemLoader && itemModel.depth !== 0 && !itemModel.hasChildren()
width: 18
anchors{
right: layout_row.left
@ -226,11 +207,11 @@ Item {
}
Repeater{
model: Math.max(itemModel.depth-1,0)
delegate: Rectangle{
delegate: FluRectangle{
required property int index
width: 1
color: control.lineColor
visible: itemModel.depth !== 0 && control.showLine
visible: control.showLine && isItemLoader && itemModel.depth !== 0 && itemModel.hasNextNodeByIndex(index)
anchors{
top:parent.top
bottom: parent.bottom
@ -239,6 +220,33 @@ Item {
}
}
}
Rectangle{
anchors.fill: parent
radius: 4
anchors.leftMargin: 6
anchors.rightMargin: 6
border.color: d.hitColor
border.width: d.dragIndex === rowIndex ? 1 : 0
color: {
if(FluTheme.dark){
if(isCurrent){
return Qt.rgba(1,1,1,0.03)
}
if(item_mouse.containsMouse){
return Qt.rgba(1,1,1,0.03)
}
return Qt.rgba(0,0,0,0)
}else{
if(isCurrent){
return Qt.rgba(0,0,0,0.06)
}
if(item_mouse.containsMouse){
return Qt.rgba(0,0,0,0.03)
}
return Qt.rgba(0,0,0,0)
}
}
}
RowLayout{
id:layout_row
anchors.verticalCenter: parent.verticalCenter
@ -310,14 +318,9 @@ Item {
property var itemControl: item_control
property var itemModel: modelData
property int rowIndex: row
property bool isItemLoader: true
id:item_loader_container
width: item.width
height: item.height
sourceComponent: {
if(modelData)
return com_item_container
return undefined
}
sourceComponent: com_item_container
}
}
}
@ -326,6 +329,7 @@ Item {
id:loader_container
property var itemControl
property var itemModel
property bool isItemLoader: false
}
}
function count(){

View File

@ -8,9 +8,8 @@ Rectangle {
id:control
color:Qt.rgba(0,0,0,0)
height: spacing*2+separator.height
Rectangle{
FluRectangle{
id:separator
clip: true
color: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(210/255,210/255,210/255,1)
width:parent.width
anchors.centerIn: parent

View File

@ -56,6 +56,8 @@ Item {
return w
}
height: 30
implicitWidth: width
implicitHeight: height
function toggle(){
if(itemModel.isExpanded){
tree_model.collapse(rowIndex)
@ -203,7 +205,7 @@ Item {
}
}
}
Rectangle{
FluRectangle{
width: 1
color: control.lineColor
visible: itemModel.depth !== 0 && control.showLine && !itemModel.hasChildren()
@ -214,7 +216,7 @@ Item {
rightMargin: -9
}
}
Rectangle{
FluRectangle{
height: 1
color: control.lineColor
visible: itemModel.depth !== 0 && control.showLine && !itemModel.hasChildren()
@ -227,7 +229,7 @@ Item {
}
Repeater{
model: Math.max(itemModel.depth-1,0)
delegate: Rectangle{
delegate: FluRectangle{
required property int index
width: 1
color: control.lineColor
@ -312,23 +314,7 @@ Item {
property var itemModel: modelData
property int rowIndex: row
id:item_loader_container
width:{
if(item){
return item.width
}
return 1
}
height: {
if(item){
return item.height
}
return 1
}
sourceComponent: {
if(modelData)
return com_item_container
return undefined
}
sourceComponent: com_item_container
}
}
}