I have a QUndoStack that looks like
2 - something (active)
1 - something
0 - bottom of stack
Two situations are possible now:
I:
open a dialog which pushes several things to the stack merged as one and click "accept", the stack looks like this:
3 - dialog done (active)
2 - something
1 - something
0 - bottom of stack
II:
open a dialog which pushes several things to the stack merged as one and click "cancel", the stack looks like this:
3 - dialog done
2 - something (active)
1 - something
0 - bottom of stack
(I) is ok, (II) is technicaly also ok, but I want (3) be gone:
2 - something (active)
1 - something
0 - bottom of stack
As soon the user does something else the stack looks fine again:
3 - new thing done (active)
2 - something
1 - something
0 - bottom of stack
But I want to remove the command entirely from the stack if the user pushed cancel, the command is never used again and only confuses the user if present. The stack should look like before, as nothing happend.
I found
void QUndoCommand::setObsolete(bool obsolete)
which i assume is the right command to tell the stack to remove the item, documentation says:
If a command is set obsolete
and the clean index is greater than or equal to the current command index,
then the clean index will be reset
when the command is deleted from the stack.
but I wonder how to access the merged commands?
I am afraid
const QUndoCommand *QUndoCommand::child(int index) const
const QUndoCommand *QUndoStack::command(int index) const
are not the right ways to go, since they are given back as const and because of the documentation warnings.
https://doc.qt.io/qt-5/qundostack.html
https://doc.qt.io/qt-5/qundocommand.html#setObsolete
If I understand you correctly, you are using the topmost command as a 'preview' to show what accepting the open dialog would do.
In this case, and if I also understand Qt's documentation correctly, you should setObsolete(true) the topmost ('preview') command and then undo it. That should delete it from the stack.
The merged command is (as I interpret your question) the complete effect that accepting the dialog would have, so this entire command is obsolete.
Related
I would like to display a table which have several thousand rows with complex formatting (color, font, border, etc. done on the ASP.Net Core server).
Initially, I generated an html copy of all the data (stored in a SQL Server database), but realised it wasn't optimal since the generated html data accounted for more than 50MB.
No, I only generate about 200 rows; 100 visible and 50 hidden above and below (cache). I would like to freely scroll the tablen, but when there are only 25 hidden rows above or below, fetch new rows from the controller which are then prepend or append to the table. Basically, I want to give enough room so I can can populate the table when I'm scrolling through the "hidden" (cache) rows.
Everything seems to work well, but I believe I need to use a web-worker to run the function in a background thread which add new rows to the table independently of the table being scrolled.
Below is a excerpt of the code :
I use a debunce function to only catch the lastest position of the mouse scroll.
The scroll function basically only checks whether there are enough hidden rows (cache) above or below the table. If it reaches the threshold, it either prepends (scroll upwards) or appends (scroll downwards) rows obtained from the controller.
The main issue is that I can't scroll the table when the new rows are being fetch as the page freezes. It only takes about 1 to 2 seconds to populate to new (scrollable) rows but it isn't smooth.
Could anyone help me improve the code? (general ideas) I also read that there are already existing libraries but can't really get my head around them..
$('#fields-table > tbody').on('wheel', _.debounce(async function (event) {
await scroll(); // Probably change it to a web-worker or promise?
}
async function scroll() {
var threshold = 200; // Corresponds to approximatively 50 rows (above and below).
var above = $('#fields-table').scrollTop();
var below = $('#fields-table > tbody').height() - $('#fields-table').height() - above;
// Gets the scroll delta based on the table heights.
var delta = 0
if (above < threshold) delta = above - threshold; // Scrolls upwards.
if (below < threshold) delta = threshold - below; // Scrolls downwards.
await addCacheRows(delta); // Prepends (delta < 0) or appends (delta > 0) or appends rows obtained via the fetch API.
}
Your problem is unlikely to resolve with a web worker. Without seeing more code I cannot tell for sure, but I suspect your code to generate new rows is not sufficiently efficient. Remember:
Use DocumentFragment to create the HTML, do not immediately append it to the main DOM tree row by row. Appending elements to a document triggers some recalculations.
Unless this is a LOT of data or requires lots of work serverside, you can immediately start preloading next/previous rows. Keep the promise object and only await it once you need them, that's the simplest way to go around it
Use passive scroll event listener - Firefox even shows a console warning whenever you do not do that
There is no way generating 200 rows of table data should take seconds. Since you use JQuery anyway (really, in 2022?), note that there are plugins for this. I don't remember what I used, but it worked perfect and scrolled smooth with much more data than what you have.
Thank you for your help. I realise it won't be as straightforward as I initally thought (I made some tests with WPF virtualization as well).
Regarding the time it takes to generate the extra rows, I believe it mostly comes from the server. Sure, I can probably load new rows independently of the threshold.
I've never heard about DocumentFragment, but that something I should definitely consider.
I'm using next js for my application and I'm facing some issues with routing to the previous route of the application. I know that there is a function like router.back(), but I do not know if I can go back from the current page.
I have read that we can check history.action !== 'POP' but now I check that history has no action property when using console.log(history)
I am using next/router.
Way too late to be useful but for the next person that comes along: If I read your question correctly, you're wanting to know if there is something in the navigation stack that you can navigate back to - and you want to do something else if there is no history.
You can use window.history.state to get a glimpse; although it doesn't give you clear access to the history stack the state has an "idx" property that is incremented when a location is added to the history stack. This means that if window.history.state.idx is zero there's nothing in the history stack, if it's bigger than zero then there is something in the history stack and you can navigate back.
An example for navigating back if you can or doing something else if not:
if (window.history.state && window.history.state.idx > 0) {
router.back();
} else {
// Do something else
}
I'm getting ready to create a communications widget for use in a Jupyter application. I'm trying to understand when the widget's "value" property can be accessed ... it looks like the "value" can be read anytime, but won't match the widget model "value" until cell execution stops (i.e., the widget's browser state isn't updated back to the widget's kernel state).
To test this, I tried creating a small slider widget, waiting for 10 seconds, and then reading the widget "value" property ... all in the same cell. In the 10 seconds, the user (i.e., me) has time to change the slider to something like "5".
Here's a small test that can be run in a cell. When the sleep() happens, I move the slider to value "5".
from ipywidgets import *
import time
slider = IntSlider(
value=7,
min=1,
max=10.0,
step=1,
description="Input:",
)
display(slider)
time.sleep(10) # move slider to 5
print("done " + str(slider.value))
I expected "done 5" but got "done 7", implying to me that "value" is updated only after the cell completes.
Is this always true? And is there a way to force synchronization between the widget's browser state and its state in the kernel?
(I do get the expected "done 5" if I move the print() to the following cell.)
Thanks!
There is basically at present no way to automatically force code running in a cell
to wait for an event or change in a widget. Things like time.sleep(3) will only
freeze the cell and a slider created in the same cell will not display until the
sleep is complete.
The user could create a slider in cell 1 and then execute a sleep in cell 2 and then adjust the slider and the code in cell 2 may see the change after the sleep
but in this case the synchronization is directed by the user and is not automatic.
You can also start Python code from a widget event, but the Python code does not "run in a cell" and the "prints" will not go to the standard cell output area but
the output can be captured in other ways,.
In the following screenshot I use the "Output" widget to capture output from a widget event
The basic problem is that all communication between widgets and kernels is via
one-way messages -- there are no "return values" or "acknowledgements" of any kind.
Please see https://github.com/AaronWatters/jp_proxy_widget/blob/master/notebooks/Tutorial.ipynb for more discussion.
As it turns out, there does seem to be a library that uses something like asyncio to achieve an inline wait. It's called jupyter-ui-poll at https://github.com/Kirill888/jupyter-ui-poll. The author says it's available on PyPI at https://pypi.org/project/jupyter-ui-poll/
Very promising! ... otherwise, I'm forced to agree with you.
For some reason, when I use the following code in package I'm trying to contribute to, an integral sign (∫) appears in the active document when a button is selected on the dialog.
checkAutoSave: ()->
if atom.workspace.getActiveTextEditor().isModified()
if atom.config.get('build.saveOnBuild') is true
atom.workspace.getActiveTextEditor().save()
return 1
else if atom.config.get('build.promptToSaveOnBuild') is true
diaDirection = atom.confirm
message: 'Do you want to save the current file before building?'
detailedMessage: 'This message can be turned off in the Build settings.'
buttons: ['Yes', 'No', 'Cancel Build']
switch diaDirection
when 0
atom.workspace.getActiveTextEditor().save()
return 1
when 1
return 0
when 2
return -1
else #Current File wasn't changed.
return 0
I have tried narrowing it down and I am 100% it has something to do with the dialog. The problem does not exists without the dialog call. The Integral sign appears in the document regardless of the button pressed.
I've had a similar problem a while ago - see here for more details.
The action I wanted to trigger in the editor was bound to Ctrl+Alt+B, which by default inserts the integral sign on Mac OS X. The integral sign was inserted into the currently open document when I opened a standard alert box from my package's code.
I didn't found out why, but it looks similar to your problem. In the end, I resolved it by removing the alert and using an Atom view instead for showing the message. As soon as I did this, the integral sign was no longer inserted into the document.
It looks like there's an issue with the key binding and preventing event propagation when using some dialogs. In some cases, the key event is handed to the OS and it inserts the character associated with the pressed key.
Maybe you can try using an Atom view instead of the confirm dialog, and it will resolve your issue as well.
On E63 or similar smart phones,there can be three softkeys(the left and right one always named "OK" or "Cancel" and the middle one always named "Select" or 'Query" alike actions' name) on the screen.QAction has this method:
void setSoftKeyRole ( SoftKeyRole softKeyRole )
,and SoftKeyRole goes these descriptions:
QAction::NoSoftKey 0 This action should not be used as a softkey
QAction::PositiveSoftKey 1 This action is used to describe a softkey with a positive or non-destructive role such as Ok, Select, or Options.
QAction::NegativeSoftKey 2 This action is used to describe a softkey with a negative or destructive role role such as Cancel, Discard, or Close.
QAction::SelectSoftKey 3 This action is used to describe a role that selects a particular item or widget in the application.
I have used PositiveSoftKeys and NegativeSoftKey to set the left and right softkey,but I can never do SelectSoftKey to the middle one?I found nothing related to this on qt bug repository.What I want to do is make full use of the three softkeys on most smartphones.Can anybody figure out what happened?Thanks always.
E63 does not have a touch screen,and it seems only smart phones with a touch screen(Nokia series) can set SelectSoftKey to the middle one.