copy and pasting selections in wx.grid cells

Hi,

I am using wx.grid in an application. I notice that copying and pasting
selected text in cells doesn't seem to work out of the box on python2.5,
Ubuntu Feisty, wxPython 2.8.1.1. You can try this with the wxpython
demo, Grid>Simple wx.Grid, catching all events (and also with the other
grid demos).

First method - context menu:
- after you right click the context menu appears but the coloured
background of the selection dissappears. I would have expected that the
selection remained visible. If you choose "copy", it copies indeed the
selection to the clipboard.
- However pasting this in another cell doesn't work. I also would like
that pasting works at the cursor and doesn't replace the whole cell

Second method - keyboard (ctrl+c,ctrl+v):
- as soon as you press ctrl, the cell loses focus. Why is that? Ctrl+C
doesn't do anything.
- paste Ctrl+V also doesn't work

Is there a simple way to enable copy/paste in a grid? Of course I can
start implementing it with custom event handlers, but as there is a
context menu I thought there should be a more simple way. Is this a
platform issue? I wonder why the context menu is provided if the
corresponding actions don't work.

Thanks for any help or hints,

Stani

Is there a simple way to enable copy/paste in a grid? Of course I can

start implementing it with custom event handlers, but as there is a
context menu I thought there should be a more simple way. Is this a
platform issue? I wonder why the context menu is provided if the
corresponding actions don’t work.

Thanks for any help or hints,

AFAIK there is no method for copy/cut/paste of the wxGrid. (It’d be nice to get

confirmation on that from others, though.) Maybe you are stuck with needing
custom event handlers.

On that note, At some point a few months ago I found something online in which
someone had created a custom class that does do it, though, and I tried it and it
worked well , so I recopy it below. I wish I knew where I found this though and who
wrote it. Maybe it will give you some ideas for how you’d want to implement copy/
cut/paste for your own needs.

Lastly, would it be good to include this sort of functionality in the wxGrid as
standard in future versions of wxPython? Or is that not recommendable for some
reason?

···

class MyGrid(wx.grid.Grid):

""" A Copy&Paste enabled grid class"""

def __init__(self, parent, id, pos, size, style):

    wx.grid.Grid.__init__(self, parent, id, pos, size, style)

    wx.EVT_KEY_DOWN(self, self.OnKey)

def selection(self):

    # Show cell selection

    # If selection is cell...

    if self.GetSelectedCells():

        print "Selected cells " + str(self.GetSelectedCells())

    # If selection is block...

    if self.GetSelectionBlockTopLeft():

        print "Selection block top left " + str(self.GetSelectionBlockTopLeft())

    if self.GetSelectionBlockBottomRight():

        print "Selection block bottom right " + str(self.GetSelectionBlockBottomRight())

   

    # If selection is col...

    if self.GetSelectedCols():

        print "Selected cols " + str(self.GetSelectedCols())

   

    # If selection is row...

    if self.GetSelectedRows():

        print "Selected rows " + str(self.GetSelectedRows())



def currentcell(self):

    # Show cursor position

    row = self.GetGridCursorRow()

    col = self.GetGridCursorCol()

    cell = (row, col)

    print "Current cell " + str(cell)

   

def OnKey(self, event):

    # If Ctrl+C is pressed...

    if event.ControlDown() and event.GetKeyCode() == 67:

        print "Ctrl+C"

        self.selection()

        # Call copy method

        self.copy()

       

    # If Ctrl+V is pressed...

    if event.ControlDown() and event.GetKeyCode() == 86:

        print "Ctrl+V"

        self.currentcell()

        # Call paste method

        self.paste()

       

    # If Supr is presed

    if event.GetKeyCode() == 127:

        print "Supr"

        # Call delete method

        self.delete()

       

    # Skip other Key events

    if event.GetKeyCode():

        event.Skip()

        return

def copy(self):

    print "Copy method"

    # Number of rows and cols

    rows = self.GetSelectionBlockBottomRight()[0][0] - self.GetSelectionBlockTopLeft()[0][0] + 1

    cols = self.GetSelectionBlockBottomRight()[0][1] - self.GetSelectionBlockTopLeft()[0][1] + 1

   

    # data variable contain text that must be set in the clipboard

    data = ''

   

    # For each cell in selected range append the cell value in the data variable

    # Tabs '\t' for cols and '\r' for rows

    for r in range(rows):

        for c in range(cols):

            data = data +

str(self.GetCellValue(self.GetSelectionBlockTopLeft()[0][0] + r,
self.GetSelectionBlockTopLeft()[0][1] + c))

            if c < cols - 1:

                data = data + '\t'

        data = data + '\n'

    # Create text data object

    clipboard = wx.TextDataObject()

    # Set data object value

    clipboard.SetText(data)

    # Put the data in the clipboard

    if wx.TheClipboard.Open():

        wx.TheClipboard.SetData(clipboard)

        wx.TheClipboard.Close()

    else:

        wx.MessageBox("Can't open the clipboard", "Error")

       

def paste(self):

    print "Paste method"

    clipboard = wx.TextDataObject()

    if wx.TheClipboard.Open():

        wx.TheClipboard.GetData(clipboard)

        wx.TheClipboard.Close()

    else:

        wx.MessageBox("Can't open the clipboard", "Error")

    data = clipboard.GetText()

    table = []

    y = -1

    # Convert text in a array of lines

    for r in data.splitlines():

        y = y +1

        x = -1

        # Convert c in a array of text separated by tab

        for c in r.split('\t'):

            x = x +1

            self.SetCellValue(self.GetGridCursorRow() + y, self.GetGridCursorCol() + x, c)

           

def delete(self):

    print "Delete method"

    # Number of rows and cols

    rows = self.GetSelectionBlockBottomRight()[0][0] - self.GetSelectionBlockTopLeft()[0][0] + 1

    cols = self.GetSelectionBlockBottomRight()[0][1] - self.GetSelectionBlockTopLeft()[0][1] + 1

    # Clear cells contents

    for r in range(rows):

        for c in range(cols):

            self.SetCellValue(self.GetSelectionBlockTopLeft()[0][0] + r, self.GetSelectionBlockTopLeft()[0][1] + c, '')