Hi,
I’m writing a custom application using python3 and gtk4, and am running into some issues with the clipboard - I suspect I’m coming across an API quirk I’ve yet to work my way around.
I want to be able to output three types of data to the clipboard:
- A serialised object for internal application use
- A text/csv dump for copying into a spreadsheet
- A text/plain dump for any other application
I have what appears to be error free code conforming to what I understand of the API. I have tested the text/plain output with my own code in a seperate test app for pasting, and it works. However attempting to paste into any other application that is not of my own creation does not result in pasting anything. This includes gEdit 46.2, and LibreOffice Calc.
My copy code:
# Access the default clipboard for the application
clipboard = Gdk.Display.get_default().get_clipboard()
# Generate CSV data for external use
csv_data = self.get_csv_data_for_selected_cells()
# Generate and serialize the selected cell list and sheet reference for internal clipboard use
selection = {
'sheet_name': self.model.sheets[self.model.current_sheet_index]['name'],
'selected_cells': self._all_selected_cells
}
serialized_selection = pickle.dumps(selection)
# Convert serialized data to GLib.Bytes for clipboard use
gbytes_selection = GLib.Bytes.new(serialized_selection)
gbytes_csv = GLib.Bytes.new(csv_data)
# Create content providers for different formats
selection_provider = Gdk.ContentProvider.new_for_bytes("application/x-tab-selection", gbytes_selection)
csv_provider = Gdk.ContentProvider.new_for_bytes("text/csv", gbytes_csv)
text_provider = Gdk.ContentProvider.new_for_bytes("text/plain", gbytes_csv) # Optionally treat CSV as plain text
# Combine content providers into a union provider that offers multiple formats
union_provider = Gdk.ContentProvider.new_union([selection_provider, csv_provider, text_provider])
# Output the supported formats for debugging purposes
print(Gdk.ContentFormats.to_string(union_provider.ref_formats()))
# Set the union provider to the clipboard
clipboard.set_content(union_provider)
# Verify clipboard content by retrieving it immediately
clipboard.read_text_async(None, self.on_retrieve_clipboard_content)
# Set focus back to the main view
self.view.sourceview.grab_focus()
self.view.scrolled_window.grab_focus()
# Attempt to retrieve and verify clipboard content again (redundancy check in case this was a focus/persistancy issue)
clipboard.read_text_async(None, self.on_retrieve_clipboard_content)
And my paste code in a seperately running test application:
self.clipboard.read_text_async(None, self.on_paste_text)
def on_retrieve_clipboard_content(self, clipboard, result):
# Read the text from the clipboard and print it for verification
retrieved_text = clipboard.read_text_finish(result)
if retrieved_text:
print(f"Retrieved clipboard content: {retrieved_text}")
else:
print("Failed to retrieve clipboard content.")
This is an example of what I see in console output, when I trigger my copy:
application/x-tab-selection text/csv text/plain
<__gi__.GdkContentProviderUnion object at 0x7f0389561b80 (GdkContentProviderUnion at 0x555ac7a9ef90)>
Retrieved clipboard content: 42,99.0,12
56,,
,,
,4,88
Retrieved clipboard content: 42,99.0,12
56,,
,,
,4,88
When I go to paste into gEdit however, nothing pastes at all. Only when I access data through my own read_text_async calls can I get anything out of the clipboard.
I am obviously missing something fairly key, so any tips would be appreciated!
Cheers,
dalek