245 lines
7.3 KiB
QML
245 lines
7.3 KiB
QML
import QtQml 2.15
|
|
import QtQuick 2.15
|
|
import QtQuick.Layouts 1.15
|
|
import QtQuick.Controls 2.0
|
|
import org.kde.plasma.components as PlasmaComponents
|
|
import "../components" as Components
|
|
import "components/Custom" as LayoutComponents
|
|
import org.kde.plasma.plasmoid
|
|
|
|
Item {
|
|
id: customLayout
|
|
|
|
anchors.fill: parent
|
|
|
|
implicitHeight: mainGrid.implicitHeight + editLayoutBtn.height
|
|
|
|
property var customLayoutModel: Plasmoid.configuration.customLayoutModel
|
|
|
|
property var widgetsModel: masterWidgetsModel.widgetsModel
|
|
|
|
property real totalWidgetsHeight: 0
|
|
|
|
Component.onCompleted: {
|
|
|
|
/* If user has used 'Custom' layout it retrieves last configration
|
|
from plasmoid config and sets it to masterWidgetsModel in order to
|
|
be able to manipulate the data */
|
|
|
|
if(customLayoutModel !== "null"){
|
|
var datamodel = JSON.parse(customLayoutModel);
|
|
masterWidgetsModel.widgetsModel = datamodel;
|
|
}
|
|
}
|
|
|
|
|
|
LayoutComponents.Model {
|
|
id: masterWidgetsModel
|
|
defaultCellHeight: mainGrid.cellHeight
|
|
}
|
|
|
|
readonly property var initialDraggedItemCoords: []
|
|
|
|
Connections {
|
|
target: masterWidgetsModel
|
|
function onModelUpdated () {
|
|
customLayout.totalWidgetsHeight = 0;
|
|
repeater.model = widgetsModel;
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: root
|
|
|
|
function onEditingLayoutChanged() {
|
|
repeater.model = null;
|
|
repeater.model = widgetsModel;
|
|
}
|
|
}
|
|
|
|
GridLayout {
|
|
id: mainGrid
|
|
|
|
anchors.fill: parent
|
|
anchors.bottomMargin: editLayoutBtn.height
|
|
|
|
columns: 4
|
|
rows: customLayout.totalWidgetsHeight / (cellWidth*4)
|
|
columnSpacing: root.editingLayout ? 5 : 0
|
|
rowSpacing: root.editingLayout ? 5 : 0
|
|
|
|
property var cellWidth: root.editingLayout ? ((root.fullRepWidth-columnSpacing*columns) / columns) : root.fullRepWidth / columns
|
|
property var cellHeight: (root.sectionHeight*1.3) / 3
|
|
|
|
Repeater {
|
|
|
|
id: repeater
|
|
|
|
model: widgetsModel
|
|
|
|
delegate: Loader {
|
|
id: loader
|
|
|
|
required property var model
|
|
required property var index
|
|
|
|
property int itemIndex: index
|
|
property var name: model.name
|
|
property var modelProps: model.props
|
|
|
|
asynchronous: true
|
|
source: model.componentUrl
|
|
|
|
width: model.width ? model.width : mainGrid.cellWidth * model.colSpan
|
|
height: model.height ? model.height : mainGrid.cellHeight
|
|
|
|
Layout.columnSpan: model.colSpan
|
|
|
|
Layout.rowSpan: model.rowSpan ? model.rowSpan : 1
|
|
|
|
z: Drag.active ? 4 : 1
|
|
|
|
Drag.active: mouseArea.drag.active // Activate drag when mouse is pressed
|
|
Drag.source: loader // Reference to the item being dragged
|
|
|
|
onLoaded: {
|
|
|
|
// Sets properties from model to loaded item
|
|
if (loader.item && loader.modelProps) {
|
|
for (const prop in loader.modelProps){
|
|
loader.item[prop] = loader.modelProps[prop];
|
|
}
|
|
}
|
|
|
|
// Recalculate totalWidgetsHeight to calculate number of rows
|
|
customLayout.totalWidgetsHeight += loader.width
|
|
}
|
|
MouseArea {
|
|
id: mouseArea
|
|
anchors.fill: parent
|
|
drag.target: loader
|
|
enabled: root.editingLayout
|
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
cursorShape: Qt.DragMoveCursor//Qt.PointingHandCursor
|
|
|
|
onClicked: mouse => {
|
|
|
|
if ((mouse.button == Qt.RightButton) && model.actions ) {
|
|
contextMenu.popup(mouse.x, mouse.y);
|
|
}
|
|
|
|
}
|
|
|
|
onPressed: {
|
|
customLayout.initialDraggedItemCoords[0] = loader.x;
|
|
customLayout.initialDraggedItemCoords[1] = loader.y;
|
|
}
|
|
|
|
onReleased: {
|
|
// Ensure the drag operation is completed by calling drop()
|
|
loader.Drag.drop();
|
|
}
|
|
}
|
|
|
|
LayoutComponents.ActionMenu {
|
|
id: contextMenu
|
|
model: loader.model.actions
|
|
}
|
|
|
|
Button {
|
|
id: removeItemButton
|
|
anchors.top: parent.top
|
|
anchors.right: parent.right
|
|
visible: root.editingLayout
|
|
Text {
|
|
text: "x"
|
|
anchors.centerIn: parent
|
|
color: "#ffffff"
|
|
font.pointSize: 11
|
|
}
|
|
z: 10
|
|
width: 20
|
|
height: 20
|
|
background: Rectangle {
|
|
color: root.redColor
|
|
radius: height / 2
|
|
}
|
|
|
|
onClicked: {
|
|
masterWidgetsModel.remove(itemIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
LayoutComponents.Footer {
|
|
id: editLayoutBtn
|
|
height: 40
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.bottom: parent.bottom
|
|
}
|
|
|
|
DropArea {
|
|
id: dropArea
|
|
|
|
anchors.fill: parent // or define specific anchors
|
|
|
|
onDropped: drag => {
|
|
|
|
var above = mainGrid.childAt(drag.x, drag.y);
|
|
|
|
if (above && above !== drag.source) {
|
|
|
|
masterWidgetsModel.move(drag.source.itemIndex, above.itemIndex);
|
|
} else {
|
|
let item = drag.source;
|
|
if(isFreeSpace(item.x, item.y, item)){
|
|
let prevItem = findClosestItem(item.x, item.y, item);
|
|
|
|
if(prevItem){
|
|
|
|
masterWidgetsModel.insert(item.itemIndex, prevItem.itemIndex+1);
|
|
}
|
|
}
|
|
drag.source.x = customLayout.initialDraggedItemCoords[0];
|
|
drag.source.y = customLayout.initialDraggedItemCoords[1];
|
|
}
|
|
}
|
|
|
|
function findClosestItem(initXPoint, initYpoint, item){
|
|
|
|
let foundedItem = null
|
|
let itemYcenter = initYpoint + item.height/2
|
|
let itemWidth = item.width
|
|
|
|
for (let i = initXPoint-10; i > 0; i-=itemWidth ) {
|
|
|
|
foundedItem = mainGrid.childAt(i, itemYcenter);
|
|
if(foundedItem) {
|
|
return foundedItem;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return foundedItem;
|
|
}
|
|
|
|
function isFreeSpace(initXPoint, initYpoint, item) {
|
|
let finalXpoint = initXPoint + item.width;
|
|
let isFree = true;
|
|
let foundedItem = mainGrid.childAt(finalXpoint, initYpoint);
|
|
|
|
if((finalXpoint > mainGrid.width) || foundedItem) {
|
|
|
|
isFree = false;
|
|
return isFree;
|
|
}
|
|
|
|
return isFree;
|
|
}
|
|
}
|
|
}
|