Decoupled History from QML

This commit is contained in:
Adsooi 2024-10-11 01:14:52 +02:00
parent 54363b25bc
commit 2dc9234b22
Signed by: Ad5001
GPG key ID: EF45F9C6AFE20160
10 changed files with 239 additions and 191 deletions

View file

@ -76,18 +76,16 @@ MenuBar {
Action {
text: qsTr("&Undo")
shortcut: StandardKey.Undo
onTriggered: history.undo()
onTriggered: Modules.History.undo()
icon.name: 'edit-undo'
icon.color: enabled ? sysPalette.windowText : sysPaletteIn.windowText
enabled: history.undoCount > 0
}
Action {
text: qsTr("&Redo")
shortcut: StandardKey.Redo
onTriggered: history.redo()
onTriggered: Modules.History.redo()
icon.name: 'edit-redo'
icon.color: enabled ? sysPalette.windowText : sysPaletteIn.windowText
enabled: history.redoCount > 0
}
Action {
text: qsTr("&Copy plot")

View file

@ -64,10 +64,7 @@ Item {
Clears both undo and redo stacks completly.
*/
function clear() {
undoCount = 0
redoCount = 0
undoStack = []
redoStack = []
Modules.History.clear()
}
@ -76,18 +73,7 @@ Item {
Serializes history into JSON-able content.
*/
function serialize() {
let undoSt = [], redoSt = [];
for(let i = 0; i < undoCount; i++)
undoSt.push([
undoStack[i].type(),
undoStack[i].export()
]);
for(let i = 0; i < redoCount; i++)
redoSt.push([
redoStack[i].type(),
redoStack[i].export()
]);
return [undoSt, redoSt]
return Modules.History.serialize()
}
/*!
@ -95,14 +81,7 @@ Item {
Unserializes both \c undoSt stack and \c redoSt stack from serialized content.
*/
function unserialize(undoSt, redoSt) {
clear();
for(let i = 0; i < undoSt.length; i++)
undoStack.push(new JS.HistoryLib.Actions[undoSt[i][0]](...undoSt[i][1]))
for(let i = 0; i < redoSt.length; i++)
redoStack.push(new JS.HistoryLib.Actions[redoSt[i][0]](...redoSt[i][1]))
undoCount = undoSt.length;
redoCount = redoSt.length;
objectLists.update()
Modules.History.unserialize(undoSt, redoSt)
}
/*!
@ -110,16 +89,7 @@ Item {
Adds an instance of HistoryLib.Action to history.
*/
function addToHistory(action) {
if(action instanceof JS.HistoryLib.Action) {
console.log("Added new entry to history: " + action.getReadableString())
undoStack.push(action)
undoCount++;
if(Helper.getSettingBool("reset_redo_stack")) {
redoStack = []
redoCount = 0
}
saved = false
}
Modules.History.addToHistory(action)
}
/*!
@ -128,16 +98,7 @@ Item {
By default, will update the graph and the object list. This behavior can be disabled by setting the \c updateObjectList to false.
*/
function undo(updateObjectList = true) {
if(undoStack.length > 0) {
var action = undoStack.pop()
action.undo()
if(updateObjectList)
objectLists.update()
redoStack.push(action)
undoCount--;
redoCount++;
saved = false
}
Modules.History.undo()
}
/*!
@ -146,77 +107,6 @@ Item {
By default, will update the graph and the object list. This behavior can be disabled by setting the \c updateObjectList to false.
*/
function redo(updateObjectList = true) {
if(redoStack.length > 0) {
var action = redoStack.pop()
action.redo()
if(updateObjectList)
objectLists.update()
undoStack.push(action)
undoCount++;
redoCount--;
saved = false
}
}
/*!
\qmlmethod void History::undoMultipleDefered(int toUndoCount)
Undoes several HistoryLib.Action at the top of the undo stack and pushes them to the top of the redo stack.
It undoes them deferedly to avoid overwhelming the computer while creating a cool short accelerated summary of all changes.
*/
function undoMultipleDefered(toUndoCount) {
undoTimer.toUndoCount = toUndoCount;
undoTimer.start()
if(toUndoCount > 0)
saved = false
}
/*!
\qmlmethod void History::redoMultipleDefered(int toRedoCount)
Redoes several HistoryLib.Action at the top of the redo stack and pushes them to the top of the undo stack.
It redoes them deferedly to avoid overwhelming the computer while creating a cool short accelerated summary of all changes.
*/
function redoMultipleDefered(toRedoCount) {
redoTimer.toRedoCount = toRedoCount;
redoTimer.start()
if(toRedoCount > 0)
saved = false
}
Timer {
id: undoTimer
interval: 5; running: false; repeat: true
property int toUndoCount: 0
onTriggered: {
if(toUndoCount > 0) {
historyObj.undo(toUndoCount % 4 == 1) // Only redraw once every 4 changes.
toUndoCount--;
} else {
running = false;
}
}
}
Timer {
id: redoTimer
interval: 5; running: false; repeat: true
property int toRedoCount: 0
onTriggered: {
if(toRedoCount > 0) {
historyObj.redo(toRedoCount % 4 == 1) // Only redraw once every 4 changes.
toRedoCount--;
} else {
running = false;
}
}
}
Component.onCompleted: {
Modules.History.initialize({
historyObj,
themeTextColor: sysPalette.windowText.toString(),
imageDepth: Screen.devicePixelRatio,
fontSize: 14
})
Modules.History.redo()
}
}

View file

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
pragma ComponentBehavior: Bound
import QtQuick.Controls
import QtQuick
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
@ -46,6 +48,18 @@ Item {
true when the system is running with a dark theme, false otherwise.
*/
property bool darkTheme: isDarkTheme()
/*!
\qmlproperty int HistoryBrowser::undoCount
Number of actions in the undo stack.
*/
property int undoCount: 0
/*!
\qmlproperty int HistoryBrowser::redoCount
Number of actions in the redo stack.
*/
property int redoCount: 0
Setting.TextSetting {
id: filterInput
@ -76,19 +90,22 @@ Item {
id: redoColumn
anchors.right: parent.right
anchors.top: parent.top
width: actionWidth
width: historyBrowser.actionWidth
Repeater {
model: history.redoCount
model: historyBrowser.redoCount
HistoryItem {
id: redoButton
width: actionWidth
width: historyBrowser.actionWidth
//height: actionHeight
isRedo: true
idx: index
darkTheme: historyBrowser.darkTheme
hidden: !(filterInput.value == "" || content.includes(filterInput.value))
onClicked: {
redoTimer.toRedoCount = Modules.History.redoStack.length-index
redoTimer.start()
}
}
}
}
@ -101,14 +118,14 @@ Item {
transform: Rotation { origin.x: 30; origin.y: 30; angle: 270}
height: 70
width: 20
visible: history.redoCount > 0
visible: historyBrowser.redoCount > 0
}
Rectangle {
id: nowRect
anchors.right: parent.right
anchors.top: redoColumn.bottom
width: actionWidth
width: historyBrowser.actionWidth
height: 40
color: sysPalette.highlight
Text {
@ -124,20 +141,24 @@ Item {
id: undoColumn
anchors.right: parent.right
anchors.top: nowRect.bottom
width: actionWidth
width: historyBrowser.actionWidth
Repeater {
model: history.undoCount
model: historyBrowser.undoCount
HistoryItem {
id: undoButton
width: actionWidth
width: historyBrowser.actionWidth
//height: actionHeight
isRedo: false
idx: index
darkTheme: historyBrowser.darkTheme
hidden: !(filterInput.value == "" || content.includes(filterInput.value))
onClicked: {
undoTimer.toUndoCount = +index+1
undoTimer.start()
}
}
}
}
@ -150,7 +171,39 @@ Item {
transform: Rotation { origin.x: 30; origin.y: 30; angle: 270}
height: 60
width: 20
visible: history.undoCount > 0
visible: historyBrowser.undoCount > 0
}
}
}
Timer {
id: undoTimer
interval: 5; running: false; repeat: true
property int toUndoCount: 0
onTriggered: {
if(toUndoCount > 0) {
Modules.History.undo()
if(toUndoCount % 3 === 1)
Modules.Canvas.requestPaint()
toUndoCount--;
} else {
running = false;
}
}
}
Timer {
id: redoTimer
interval: 5; running: false; repeat: true
property int toRedoCount: 0
onTriggered: {
if(toRedoCount > 0) {
Modules.History.redo()
if(toRedoCount % 3 === 1)
Modules.Canvas.requestPaint()
toRedoCount--;
} else {
running = false;
}
}
}
@ -163,6 +216,18 @@ Item {
let hex = sysPalette.windowText.toString()
// We only check the first parameter, as on all normal OSes, text color is grayscale.
return parseInt(hex.substr(1,2), 16) > 128
}
Component.onCompleted: {
Modules.History.initialize({
helper: Helper,
themeTextColor: sysPalette.windowText.toString(),
imageDepth: Screen.devicePixelRatio,
fontSize: 14
})
Modules.History.on("updated undone redone", () => {
undoCount = Modules.History.undoStack.length
redoCount = Modules.History.redoStack.length
})
}
}

View file

@ -41,17 +41,17 @@ Button {
\qmlproperty bool HistoryItem::isRedo
true if the action is in the redo stack, false othewise.
*/
property bool isRedo
required property bool isRedo
/*!
\qmlproperty int HistoryItem::idx
\qmlproperty int HistoryItem::index
Index of the item within the HistoryBrowser list.
*/
property int idx
required property int index
/*!
\qmlproperty bool HistoryItem::darkTheme
true when the system is running with a dark theme, false otherwise.
*/
property bool darkTheme
required property bool darkTheme
/*!
\qmlproperty bool HistoryItem::hidden
true when the item is filtered out, false otherwise.
@ -61,7 +61,7 @@ Button {
\qmlproperty int HistoryItem::historyAction
Associated history action.
*/
readonly property var historyAction: isRedo ? history.redoStack[idx] : history.undoStack[history.undoCount-idx-1]
readonly property var historyAction: isRedo ? Modules.History.redoStack.at(index) : Modules.History.undoStack.at(-index-1)
/*!
\qmlproperty int HistoryItem::actionHeight
@ -147,13 +147,6 @@ Button {
ToolTip.visible: hovered
ToolTip.delay: 200
ToolTip.text: content
onClicked: {
if(isRedo)
history.redoMultipleDefered(history.redoCount-idx)
else
history.undoMultipleDefered(+idx+1)
}
}