On 2/2/07, Kelly Burkhart <[EMAIL PROTECTED]> wrote:
Is it possible to select a portion of text within a cell in a
QTreeView (or QTableView)? I would like to treat one column of cells
as lines of text from which I can select text just like selecting in
an editor. I do not need to select from multiple lines.
Any ideas on how this can be done?
The attached is what I came up with. It's not what I thought I wanted
when I started, but I think functionally it is better.
-- You can select arbitrary cells and on X11 middle-click and the cell
contents are pasted in a sensible way.
-- You can select arbitrary cells, <copy> or <cut>, then paste the
contents somewhere else. (widget is read-only so cut doesn't modify
the contents)
-- You can double click on a cell and select text within a cell and
paste in the usual way.
If any of you see any lossage I'd love to hear it. I feel like to
some extent I've stumbled through this. ;-)
One bit that may cause problems is the TstTreeView.copySelection
method. In X11, it is called on every change to the view selection
and could get quite expensive if a big region is selected.
-K
#!/usr/bin/env python
import sys
import os
from PyQt4 import QtGui, QtCore
class TstModel( QtCore.QAbstractTableModel ):
def __init__( self ):
QtCore.QAbstractTableModel.__init__(self)
self._header = ( 'col0', 'col1', 'col2' )
self._items = [ ('item0', 'item0', 'item0'),
('how do','i select', 'just >this text< from this item'),
('how do','i select', 'what does a multi\nline cell look like?'),
('how do','i select', 'what does a multi\nline cell\nlook\nlike?'),
('item2','item2','item2') ]
def rowCount( self, parent ):
if not parent.isValid():
return len(self._items)
return 0
def columnCount( self, parent ):
return len(self._header)
def data( self, index, role ):
if not index.isValid() or role not in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole):
return QtCore.QVariant()
row = index.row()
col = index.column()
if row < 0 or row >= len(self._items) or col < 0 or col >= len(self._header):
return QtCore.QVariant()
return QtCore.QVariant(self._items[row][col])
def headerData( self, section, orientation, role ):
if orientation == QtCore.Qt.Horizontal and role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole):
return QtCore.QVariant( self._header[section] )
return QtCore.QVariant()
def flags( self, index ):
return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsEditable
class TstTreeView( QtGui.QTreeView ):
def __init__( self, model ):
QtGui.QTreeView.__init__(self)
self.setWindowTitle('TstTreeView')
self.setModel(model)
self.setRootIsDecorated(False)
self.setSortingEnabled(False)
self.setSelectionBehavior( QtGui.QAbstractItemView.SelectItems )
self.setSelectionMode( QtGui.QAbstractItemView.ExtendedSelection )
self.resize( 600, 200 )
self.setItemDelegate( RowDelegate(self) )
self._supportsSelection = QtGui.QApplication.clipboard().supportsSelection()
def selectionChanged( self, selected, deselected ):
QtGui.QTreeView.selectionChanged( self, selected, deselected )
self.copySelection( QtGui.QClipboard.Selection )
def keyPressEvent( self, event ):
if event.matches( QtGui.QKeySequence.Cut ) or event.matches( QtGui.QKeySequence.Copy ):
self.copySelection( QtGui.QClipboard.Clipboard )
else:
QtGui.QTreeView.keyPressEvent( self, event )
def copySelection( self, mode ):
if mode == QtGui.QClipboard.Selection and not self._supportsSelection:
return
maxCol = 0
sel = []
for index in self.selectionModel().selectedIndexes():
if maxCol < index.column():
maxCol = index.column()
sel.append( (index.row(), index.column(), index ) )
sel.sort()
selectionText = ''
for item in sel:
data = self.model().data( item[2], QtCore.Qt.DisplayRole ).toString()
data.replace('\n', '\\n')
selectionText += data
if item[1] == maxCol:
selectionText += '\n'
else:
selectionText += '\t'
QtGui.QApplication.clipboard().setText( selectionText, mode )
class RowDelegate( QtGui.QItemDelegate ):
def __init__(self, parent=0):
QtGui.QItemDelegate.__init__(self, parent)
def createEditor(self, parent, option, index):
rval = QtGui.QItemDelegate.createEditor(self,parent,option,index)
rval.setReadOnly(True)
return rval
class Tst:
def run( self ):
app = QtGui.QApplication(sys.argv)
tm = TstModel()
tv1 = TstTreeView( tm )
tv1.show()
app.connect(app, QtCore.SIGNAL('lastWindowClosed()'), app, QtCore.SLOT('quit()'))
sys.exit(app.exec_())
if __name__ == "__main__":
tst = Tst()
tst.run()
_______________________________________________
PyKDE mailing list [email protected]
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde