So I'm learning wxPython and to do so I'm working on a text editor. I know that I can intercept a CUT / COPY / PASTE signal generated from a control, such as wx.TextCtrl by binding the equivalent wx.EVT_TEXT_COPY / wx.EVT_TEXT_PASTE / wx.EVT_TEXT_CUT. What I'm having trouble figuring out is how to override say a paste to the clipboard with other text.
For instance I have a wx.ListBox where a user can store clips of text and then select them latter to paste onto the wx.TextCtrl instead of whatever text is on the system clipboard. So basically I'm trying to intercept the paste signal and in lieu of pasting the system clipboard text have it paste the selected line from the wx.ListBox. Is this possible? If so, how would I go about doing this?
A simple solution is not to use Skip() in your wx.EVT_TEXT_PASTE handler and update control manually, e.g:
textCtrl.Bind(wx.EVT_TEXT_PASTE, self.onPaste)
def onPaste(self, evt):
#do not use evt.Skip()
print "PASTE but nothing happens"
#do some manual update of the control
The evt.Skip() would cause to propagate the event and execute default behaviour which pastes content. Without the call you block the propagation and you are able to replace the default behaviour.
Related
I am trying to find a way to paste a predefined string upon entering a specific keyboard sequence, on any app.
For example if I have to paste an url or a password into a field, I can have said password in a hidden script and when I press, say, [ctrl] + [5], it would write "example123" on the text field where my cursor is.
Ideally without copying to the clipboard (I'd prefer keeping what I have on my clipboard and also avoiding to paste a password or such by mistake elsewhere).
I have tried every solution I've found so far that include xclip, xdotool and xvkdb. All of them either do not work or are really inconsistent: They only paste the string sometimes, and when they do, it's usually only part of the string ("ample123" instead of "example123").
I thought of using compose key, which I heavily use anyway to write in french on an us keyboard, but it seems it only supports 1 character sequences, as nothing is printed when I modify my .XCompose to include custom output sequences of len > 1.
I am using Ubuntu 18.04 with Gnome as a DE. Ideally something that also works when logging back (like compose keys).
You need to walk the Document Object Model for either Gnome or your web-page. My concern is that with a desktop script you wont be able to access the web page because you will need to be able to establish a target to send string to. I see in your question that you tried using using "x{tool-name}" to grab the text field element. Delivering the sting really isn't the problem. The problem is getting the GUI element of text box pragmatically. The easiest way to get access to this in a user loaded web-page is with WebExtensions API which is how to make extensions for most modern browsers. Otherwise, if you can get away with only having access to Gnome's GUI I would try LDTP, it's a library used for testing, but it looks like it can be used for automation too.
For keyboard shortcuts:
It really shouldn't matter what the script is doing to how you want to activate it. I would just go to Gnome/Settings/Keyboard and set the path to where I saved the script to be the Command. If you go the WebExtension route, you will want to build the shortcut into your extension.
I have code that uses sendkeys from Microsoft.VisualStudio.TestTools.UITesting.Keyboard.
Here I am able to set the Sendkeysdelay property and send the text like this:
Keyboard.SendKeysDelay = 10;
Keyboard.SendKeys(textEdit, Constants.BackspaceString, ModifierKeys.None);
Keyboard.SendKeys(textEdit, text, ModifierKeys.None);
The result is too slow, and I would like to speed it up. Is this possible, it seems like the SendKeysDelay property does nothing.
My experiments with Sendkeys found the minimum delay was 10ms. Some delay is needed to provide time for the application to process each keypress.
If you want to enter large amounts of text then putting it into the clipboard and then using a paste command can be much quicker. The paste can often be created by recording a control-V key-press or the paste command from a menu.
I want to override the copy-paste functionality in either Windows/Linux. How can I do that?
Most applications support simple copy-paste functionality, where the text copied is the one that is currently selected. I want to modify this functionality. Instead of just copying the text, I want to also copy to clipboard: the name of the process/application from where the text was copied, datetime of the copy-paste and user of the system.
For example, when a user selects a text (say "Hello World") from a browser and pastes it into say notepad, the pasted text should be something like "Hello World" (author: , source: chrome.exe, datetime: ....)
How can I do this (either in Windows or Linux)?
It's been a while since I looked at the clipboard but basically, you just create list to clipboard change events which the OS will send to all interested applications.
When the clipboard changes, look at the current content. When it's text (it can also be HTML or application specific binary data), then get the current content, append the information you want and set the new clipboard content.
If you use Java, you can use Toolkit.getDefaultToolkit().getSystemClipboard(); to get access to the clipboard and then add listeners for the various events.
Related:
Copying to Clipboard in Java
I am new to python. So I wanted to improve my skills. Before posting this question I tried to find some code or an idea that would guide me with what I intend to do. I did see some examples and posts on SO and other sites. But they all(the ones I came across) showed how to do it for single object. Below is what I want to do.
I want to write a utility in python that would allow me to choose from content I want to paste based on what my last 10,say, copy commands were for.
suppose I clicked copy when selecting a folder and then later I selected some text and pressed ctrl+c. Now I want to get option that would let me paste both the folder as well as the text.
Is that possible?
Thanks.
You could save the last 10 text items from a clipboard using tkinter:
#!/usr/bin/env python3
from tkinter import Tk
from collections import deque
def call_repeatedly(root, delay, func, *args):
func(*args)
root.after(delay, call_repeatedly, root, delay, func, *args)
def poll_clipboard(root, items):
text = root.clipboard_get()
if not items or items[-1] != text:
items.append(text)
def main():
root = Tk()
root.withdraw() # hide GUI
clipboard_items = deque(maxlen=10) # save last 10 clipboard items
call_repeatedly(root, 50, poll_clipboard, root, clipboard_items) # ms
call_repeatedly(root, 1000, print, clipboard_items) # print every second
root.after(10000, root.destroy) # exit in 10 seconds
root.mainloop()
main()
It polls clipboard every 50 ms. Polling is bad in general if there is an alternative interface that could allow you to subscribe to the clipboard events to be notified when new item is copied into the clipboard.
will it work for any kind of content, text, images etc. ?
This code works with text only. In general, you could get/set other types e.g., images (gtk, qt might provide a cross-platform way to do it).
Will it allow me to copy-paste text across all the applications ?
You are working with a clipboard so yes, it should work across all applications that can
work with a clipboard.
Can we make it work as normal ctrl+c (copy command)
Copy command can be implemented using a set command e.g., from pyperclip.py:
def gtkSetClipboard(text):
cb = gtk.Clipboard()
cb.set_text(text)
cb.store()
gtkSetClipboard(text) copies text to the clipboard.
I used some sql command to join two tables and the result was two terminal line long for each row of resulted table.
I dont want so ... i mean is there any way to get scroll bar at the bottom so that a row can be fit into a terminal line. and it will be a well structured and readable output
I hope you get my question.
There is no way on a standard terminal. You could use e.g. less as your pager for you sql-client.
I propose to pipe the output into the command less -S:
$ mysql-command-doing-the-SELECT | less -S
(To achieve this in the interactive mysql console, you can type pager less -S.)
Then all lines are displayed without being wrapped, and you can scroll sideways using the arrow keys. You can also use the command less (without the option -S) and then interactively type - S to achieve the non-wrapping. (Type again to toggle.)
If you need a real scroll bar, I propose to pipe the output into a real file and then use a more sophisticated program like gedit (which can be switched to a non-wrapping display) to display it with a decent scroll bar.
Another solution: copy the data from the terminal and paste it into your favorite editor. The copied text will not have any line breaks "\n".
(Offtopic: on a linux system you can just select the text with a mouse and mouse-middle-click in your editor. This will copy the text without filling out the main copy-paste buffer.)