PDA

View Full Version : Changing names of QTabWidget tabs



RThaden
26th June 2008, 18:35
Hi all,

any hint, how to make it possible to edit the names on the tabs of a QTabWidget?
I have an application where the tabs have default names but the user should be able to give them his own desired names.
My idea was to react on right mouse click on the tabs and open an editor right where the QTabBar is or alternatively open a small window where the new name can be filled in.

Any direction where I can look at?
Context menu at QTabWidget? Or QTabBar?

Any hint appreciated,

Rainer

jpn
27th June 2008, 18:29
Subclass QTabBar, catch necessary event(s), provide a temporary QLineEdit at QTabBar::tabRect() filled with QTabBar::tabText(). Once QLineEdit::editingFinished() is emitted, use QTabBar::setTabText() and get rid of the temporary QLineEdit.

RThaden
30th June 2008, 15:20
Thanks jpn,

that was exactly what I was looking for. Shouldn't be a big problem for me now.

Kind regards,

Rainer

Fenix Voltres
19th February 2010, 23:52
Got same situation and that's what I exactly did. Also, in mousePressEvent I'm hiding QLineEdit if it's visible in order to avoid situation when tabRect() of the tab being currently edited changes (could also update QLineEdit's geometry, but prefer to do it in that way). One unsolved problem still exists - when tool buttons responsible for rewinding tabs are visible - clicking them WON'T change QLineEdit position nor hide it - and I can't find a way to do that, because those buttons are part of QTabBarPrivate, which's inaccessible for me (can't catch any event, signal or whatever). (Put briefly: when rewinding tabs, QLineEdit remains visible, in wrong position and covers other tabs; It should disappear.)
Any ideas how to avoid it?

Fenix Voltres
27th February 2010, 11:41
BUMP
Anyone can help?

Fenix Voltres
2nd March 2010, 19:46
If anyone would be interested in that problem: only method I found working is to remember i. e. QTabBar::tabRect(0).left(), and check in reimplemented paintEvent() if it changes - if it does and QLineEdit is visible - hide it.

toffkriss
25th March 2010, 11:46
Just a guess:
if another button on the widget is pressed, or the widget is resized, the QLineEdit looses focus. So you could just override QLineEdit::focusOutEvent() and close/hide the (now custom) line edit.
I did my own implementation of this poblem, but the QLineEdit is just floating above the tab. also it closes itself if its done and if the user presses esc, the entered text is discarded. an event "publishText" is emitted, if the user successfully entered text. Its not perfect, but it works. If you have any suggestions, go ahead.

class IndependentLineEdit: public QLineEdit {
Q_OBJECT
public:
IndependentLineEdit(QWidget* parent = 0);
IndependentLineEdit(const QString & contents, QWidget* parent = 0 );
public slots:
void setText(const QString &text);
signals:
void newTextEntered(const QString &text);
protected:
void keyPressEvent(QKeyEvent* event);
void focusOutEvent(QFocusEvent* event);
private slots:
void publishText();
void setupWidget();
};

IndependentLineEdit::IndependentLineEdit(QWidget* parent) :
QLineEdit(parent) {
setupWidget();
}

IndependentLineEdit::IndependentLineEdit(const QString & contents, QWidget* parent) :
QLineEdit(contents, parent) {
setupWidget();
}

void IndependentLineEdit::setText(const QString &text) {
QLineEdit::setText(text);
setFocus();
selectAll();
show();
}

void IndependentLineEdit::keyPressEvent(QKeyEvent* event) {
QLineEdit::keyPressEvent(event);
if (event->key() == Qt::Key_Escape) {
setText("");
hide();
}
}

void IndependentLineEdit::focusOutEvent(QFocusEvent* event) {
QLineEdit::focusOutEvent(event);
emit editingFinished();
}

void IndependentLineEdit::publishText() {
if (text() != "") {
emit newTextEntered(text());
}
hide();
}

void IndependentLineEdit::setupWidget() {
connect(this, SIGNAL(editingFinished()), this, SLOT(publishText()));
setWindowFlags(Qt::CustomizeWindowHint);
}

I use it with a custom QTabBar and a custom QTabWidget:


class EditableTabBar: public QTabBar {
Q_OBJECT
public:
EditableTabBar(QWidget* parent = 0);
virtual ~EditableTabBar();
signals:
void tabTextChanged(int index, const QString &text);
protected:
void mouseDoubleClickEvent(QMouseEvent* event);
private slots:
void setCurrentTabText(const QString &text);
private:
IndependentLineEdit _edit;
};

EditableTabBar::EditableTabBar(QWidget* parent) :
QTabBar(parent), _edit("", 0) {
connect(&_edit, SIGNAL(newTabTextEntered(const QString &)), this,
SLOT( setCurrentTabText(const QString &)));
}

EditableTabBar::~EditableTabBar() {
// TODO Auto-generated destructor stub
}

void EditableTabBar::mouseDoubleClickEvent(QMouseEvent* event) {
_edit.setText(tabText(currentIndex()));
_edit.move(mapToGlobal(event->pos()));
}

void EditableTabBar::setCurrentTabText(const QString &text) {
setTabText(currentIndex(), text);
emit tabTextChanged(currentIndex(), text);
}


the tabTextChanged() signal is needed for my application, but its not needed for everything to work.

The tabwidget:

class EditableTabWidget : public QTabWidget {
Q_OBJECT
public:
EditableTabWidget(QWidget* parent = 0);
signals:
void tabTextChanged(int index,const QString &text);
};

EditableTabWidget::EditableTabWidget(QWidget* parent) :
QTabWidget(parent) {
EditableTabBar* t = new EditableTabBar();
connect(t, SIGNAL(tabTextChanged(int, const QString &)), this,
SIGNAL(tabTextChanged(int, const QString &)));
setTabBar(t);
}

amban
29th January 2019, 21:25
Thanks very much.

I edited your code as follows to display the _edit inside the tab label area. Also fixed the window flags.


EditableTabBar::EditableTabBar(QWidget* parent) :
QTabBar(parent), _edit("", 0) {

_edit.setWindowFlags(Qt::Popup);
connect(&_edit, SIGNAL(newTextEntered(const QString &)), this,
SLOT( setCurrentTabText(const QString &)));
}

void EditableTabBar::mouseDoubleClickEvent(QMouseEvent* event) {
Q_UNUSED(event)
QRect rect = this->tabRect(currentIndex());
_edit.setFixedSize(rect.size());
_edit.move(mapToGlobal(rect.topLeft()));

_edit.setText(tabText(currentIndex()));
//_edit.move(mapToGlobal(event->pos()));
}