I want to create a simple Python app which would interact with currently selected text and do some things with it when user presses a keyboard shortcut. The obvious way to do this would be to copy the text to clipboard using pyautogui.hotkey("ctrl", "c") and then interact with it. Problem is, this method overwrites whatever the user currently has in their clipboard.
The only workaround I've been able to think of would be something like:
#make a backup of current clipboard contents
tmpClipboard = pyperclip.paste()
#copy selected text and store it
pyautogui.hotkey("ctrl", "c")
selectedText = pyperclip.paste()
#copy old clipboard contents back inside
pyperclip.copy(tmpClipboard)
#process selected text
doStuff(selectedText)
What would be a better way of handling this (as I'm not sure how well this would perform when user has, say, an image in their clipboard instead of plain text)?
You can try to let the user define hotkey for interactions. I do not know your end application, therefore it depends on the user experience you want to achieve. If the user is an engineer, for example, I think he would prefer to be prompted about the default hotkey, and change it if he wants.
Regarding grabbing the selected text - it depends on your GUI binding - are you using Tk, Qt, etc..?
For instance, Qt has a QTextCursor that you can use to obtain information about the cursor and user selection, and then grab the text without using the whole clipboard trick. This way you can also be sure you get the data you desire.
As for images, etc: if you still choose to go with clipboard, you can assert the type of data. However, it has really vast amount of possible values and it seems to be very cumbersome and inefficient.
Good luck!
Related
I want to create a suggestions system for a console I'm embedding into my interface, but there's one feature I want to add that I don't see how to. My inspiration is how minecraft consoles work:
As you can see, the autocomplete tries to fill up the rest of the lineEdit based on what the first suggestion in the input is. I assume that this behaviour could be replicated using the placeholder text system we have now, but I don't really see how to make the placeholder show when there's text written. Any ideas?
I am currently developing an automated test case which performs actions on a console application (very simple, just clicking buttons and inputting text).
I have been able to successfully click through the application and input data without many problems, which includes identifying elements and things like that.
I have not been able to verify the existence of GUI elements that aren't clickable, ie an image that is loaded into the console application. I have tried looking through the output when using print_control_identifiers() for any indication of where data about an image in the window might be stored. I have tried looking at the tree diagram of the windows before and after loading the image in to see if it changes (it does not).
I have also then looked into verifying basic things, like font type or other properties that exist in the VS development platform, without success. To do this I used handleprops.font among other things. I have also read through the handleprops class and tried to find anything in there that I can use, but none of it is working.
My question is: is there a way to access an image's information that is stored in the window? I am able to identify where it is stored (picturebox1) and get information about that window (handleprops.rectangle) but cannot get anything about whether the image is there (like a path to image for example). All I can access is 'controllable' items, those that show up in print_control_identifiers()
I'm not sure this is possible with pywinauto but I have been stuck on this for a while and wondered if there were any suggestions people had.
Thanks
I have a 2d list in a Python utility that writes to a table using PyQt. I also want to copy all of the data from that list to the clipboard, with the caveat that it must be formatted for insertion into an excel document or a table in Word (as excel-formatted data generally is).
The question, then, is two-fold:
1) How do I go about formatting the data, stringwise, to match Excel's standards, and 2) how do I copy that to the clipboard?
From what I understand, Excel-formatted data, when viewed directly as plaintext, is XML-formatted in some way, but I don't know how to find out exactly what that XML looks like. I have not found a text editor that copies the formatting information upon pasting; they all just drop the formatting and paste the cell contents as plaintext. Copying to the clipboard once I have that should be pretty straightforward, I think.
The easiest way is probably to use TAB seperated values, for example:
15.117 0.681 39.871 533.47
14.771 0.755 47.559 652.65
11.849 0.682 47.561 660.76
10.92 0.63 46.908 658.26
10.087 0.613 47.649 676.23
This pastes well in Word and Excel (however, tabs are replaced with spaces in the example above - choose 'edit' to copy tha sample data).
For a real table in Word, you could format your data as a html table.
It is also possible to put multiple formats on the clipboard, but I'm not sure how this would be done in Python.
Mark Ransom's answer uses the Windows API to copy to the clipboard. This allows you to set the clipboard format.
See this for the standard formats.
For the html format you'll need to add some header data.
You're actually asking two questions, so I'll limit myself to the first one about the clipboard. You should probably ask another question about the behavior of Excell since it's completely unrelated to Python.
The best way to send text to the clipboard seems to be with Tk since it's usually shipped with Python so it's way more portable:
from Tkinter import Tk
r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append('i can has clipboardz?')
r.update() # now it stays on the clipboard after the window is closed
r.destroy()
This code was written by atomizer here
I also suggest you searching a bit more before asking. I had no idea on how to do this until now.
Good luck with the Excell thing!
In a console application, I need to take in credentials. I do it using lineEdit.text() and then clear it. In case I need to edit it, I want to bring back the text on the lineEdit space. How do I do that? Didn't figure out much from the documentation.
I want to apply some function to the text of a document.
Like for example run a regexp replacement and then convert the resulting text to lowercase (or some more complicated example that cannot be easily done with the provided tools).
I know how to do this using python, so I could just run a simple script from a python interpreter to load, modify, and save the data back.
This can however be quite annoying, and given the existence of a python API for sublime text there should be a way to directly run a script to modify the open document.
I would also prefer to avoid macros because those would require me to save a .sublime-macro file, but alternative solutions of this sort are equally welcome.
How can I achieve this?
In the sublime console, the symbol view represents the currently focused view (file) while window represents the current window.
So you can use the plugin API method sublime.View.substr() to collect the contents of the currently selected view as a string for further manipulation:
content = view.substr(sublime.Region(0, view.size()))
Or if you wanted, you could select some text first and then grab the contents of the selection. This example grabs only the content of the first selection; modify as needed if you wanted to grab the contents of multiple selections at once.
content = view.substr(view.sel()[0])
From here you can do whatever you want to content. Your issue is in putting the contents back into the buffer when you're done.
All edit operations need to be tracked to allow Sublime the ability to undo the change. For this reason the underlying API requires all calls that would modify the buffer (inserting, appending, or replacing text, etc) to provide an edit object. However these objects are strictly controlled; only Sublime can create one on your behalf.
So the only way to modify the buffer is to either implement your own TextCommand that does it for you, or utilize an existing command via the sublime.View.run_command() method.
content = view.substr(sublime.Region(0, view.size()))
content = content.replace("Hello", "Bonjour")
content = content.replace("Goodbye", "Au Revoir")
view.run_command("select_all")
view.run_command("insert", {"characters": content})
Here I've pulled the text out of the buffer, done some replacements, and then put the entire modified string back into the buffer by first selecting everything and then inserting the new content back.
Note that if you were doing this from a TextCommand, you would need to use self.view everywhere and not just view.
You can launch your script from the Python API, and use and get the contents of the entire file with:
contents = self.view.substr(sublime.Region(0, self.view.size()))