PDA

View Full Version : Make QHeaderView Editable



mechsin
13th June 2011, 17:51
I have been searching around the fourm for a way to make the QHeadView editable when double clicked. The best link I found had only had and example file and the link was broken. I have been searching on and off for two weeks or so.

Anyway as I stated before I am trying to make a QHeaderView that is editable when double clicked. The best I have gotten it to create a line edit box and un hide it when a section is clicked. However none of the close edit signals are triggered when editting is done so I have no good way to pass the info of what was changed back to the dataset. I know that I need to use a delegate I just don't know how. I am writting in Python but at this point I will take help in any programming language.

Below is a sample of what I have come up with


class MyHeaderView(QtGui.QHeaderView):

def __init__(self,orientation,dataset,parent=None):
super(MyHeaderView, self).__init__(orientation,parent)
self.data = dataset
# This block sets up the edit line by making setting the parent
# to the Headers Viewport.
self.line = QtGui.QLineEdit(parent=self.viewport()) #Create
self.line.setAlignment(QtCore.Qt.AlignTop) # Set the Alignmnet
self.line.setHidden(True) # Hide it till its needed

self.sectionedit = 0

# Connects to double click
self.sectionDoubleClicked.connect(self.editHeader)
self.line.editingFinished.connect(self.setHeaderDa ta)

def editHeader(self,section):

# This block sets up the geometry for the line edit
edit_geometry = self.line.geometry()
edit_geometry.setWidth(self.sectionSize(section))
edit_geometry.moveLeft(self.sectionViewportPositio n(section))
self.line.setGeometry(edit_geometry)

self.line.setHidden(False) # Make it visiable
self.line.setFocus()
self.sectionedit = section

def setHeaderData(self, section, orientation, value,
role = QtCore.Qt.EditRole):
# Update dataset
pass

wysota
13th June 2011, 23:57
A delegate won't help you for QHeaderView. It doesn't have a full implementation of the model-view scheme and it doesn't use delegates. The only way to get an inline editor is what you're already trying -- put a line edit over the header section and intercept proper signals or reimplement event handlers. I would probably make the line edit a Qt::Popup and I would probably react to its close event as well as its returnPressed signal.

mechsin
14th October 2011, 00:00
Ok thanks for the help. I finally had time to get back to this project and tried making the QLineEdit a popup by setting its window flag I ran into problems however. This causes the line edit to show up at 0,0 absolute position, the upper left hand corner of my screen. On top of that it grabs focus when it shows up but then will not release it unless I click another window down on my applications bar(Windows), at which point it disappears it does reappear when I double click a section header.
Below is the updated code, just one line. I am going to continue to work on this just though I should reply


class MyHeaderView(QtGui.QHeaderView):

def __init__(self,orientation,dataset,parent=None):
super(MyHeaderView, self).__init__(orientation,parent)
self.data = dataset
# This block sets up the edit line by making setting the parent
# to the Headers Viewport.
self.line = QtGui.QLineEdit(parent=self.viewport()) #Create
self.line.setAlignment(QtCore.Qt.AlignTop) # Set the Alignmnet
self.line.setHidden(True) # Hide it till its needed
self.line.setWindowFlags(QtCore.Qt.Popup)

self.sectionedit = 0

# Connects to double click
self.sectionDoubleClicked.connect(self.editHeader)
self.line.editingFinished.connect(self.setHeaderDa ta)

def editHeader(self,section):

# This block sets up the geometry for the line edit
edit_geometry = self.line.geometry()
edit_geometry.setWidth(self.sectionSize(section))
edit_geometry.moveLeft(self.sectionViewportPositio n(section))
self.line.setGeometry(edit_geometry)

self.line.setHidden(False) # Make it visiable
self.line.setFocus()
self.sectionedit = section

def setHeaderData(self, section, orientation, value,
role = QtCore.Qt.EditRole):
# Update dataset
pass

wysota
14th October 2011, 00:50
Most of what you describe is caused by the popup flag. If you reposition the element to its proper place it should behave correctly. If that's not what you want, you can resign from using the popup flag however you'll have hard time determining when to hide the widget.

mechsin
14th October 2011, 22:00
I tried using the popup flag but placing the line edit became troublesome. It seems that when I made it a popup it changes it positioning coordinates from being with reference to the widget to being global. This made it difficult to place the line edit in the right place. Also this made the line edit slightly larger than the header. So this got me thinking really all I need is to be able to connect the editingFinished signal to be connected to the setHeaderData slot. The initial problem of course is setHeaderData is expecting section orientation and value arguments from its caller. Is there a way to add those into my connecting declaration or is there some way to redefine the editingFinished signal to output these.

I guess what I am asking is, is there a way to overload the editingFinshed signal or create a new signal that will output the proper arguments?

wysota
14th October 2011, 23:31
I tried using the popup flag but placing the line edit became troublesome. It seems that when I made it a popup it changes it positioning coordinates from being with reference to the widget to being global. This made it difficult to place the line edit in the right place.
QWidget::mapToGlobal()


So this got me thinking really all I need is to be able to connect the editingFinished signal to be connected to the setHeaderData slot.
I don't think that's enough.

mechsin
12th July 2012, 13:37
I finally came up with a solution for this and wanted to post it here it seemed to be a common problem.


class MetaHeaderView(QtGui.QHeaderView):

def __init__(self,orientation,parent=None):
super(MetaHeaderView, self).__init__(orientation,parent)
self.setMovable(True)
self.setClickable(True)
# This block sets up the edit line by making setting the parent
# to the Headers Viewport.
self.line = QtGui.QLineEdit(parent=self.viewport()) #Create
self.line.setAlignment(QtCore.Qt.AlignTop) # Set the Alignmnet
self.line.setHidden(True) # Hide it till its needed
# This is needed because I am having a werid issue that I believe has
# to do with it losing focus after editing is done.
self.line.blockSignals(True)
self.sectionedit = 0
# Connects to double click
self.sectionDoubleClicked.connect(self.editHeader)
self.line.editingFinished.connect(self.doneEditing )

def doneEditing(self):
# This block signals needs to happen first otherwise I have lose focus
# problems again when there are no rows
self.line.blockSignals(True)
self.line.setHidden(True)
oldname = self.model().dataset.field(self.sectionedit)
newname = str(self.line.text())
self.model().dataset.changeFieldName(oldname, newname)
self.line.setText('')
self.setCurrentIndex(QtCore.QModelIndex())

def editHeader(self,section):
# This block sets up the geometry for the line edit
edit_geometry = self.line.geometry()
edit_geometry.setWidth(self.sectionSize(section))
edit_geometry.moveLeft(self.sectionViewportPositio n(section))
self.line.setGeometry(edit_geometry)

self.line.setText(self.model().dataset.field(secti on).name)
self.line.setHidden(False) # Make it visiable
self.line.blockSignals(False) # Let it send signals
self.line.setFocus()
self.line.selectAll()
self.sectionedit = section