SeanM
17th April 2014, 22:53
I’m trying to duplicate the functionality of how many other applications handle tabs where the last tab is treated as a special case and is used solely to create new tabs. So when my widget launches it looks like:
\ Tab 1 /\ + /
With “Tab 1†set as the current index. Left clicking on the ‘+’ will add a new tab called â€Tab 2â€, and sets “Tab 2†as the current index, like so:
\ Tab 1 /\ Tab 2 /\ + /
To achieve this, I’ve connected the currentChanged(int index) signal to a slot that checks to see if the current index is the last index, and if so it adds a new tab, and sets the newly created one as current. If any other tab is the current index, the slot does nothing. Here’s the code for the slot:
void customTabWidget::slotTabBarClicked(int index)
{
if (index != (count() - 1))
{
// if it's not the last one, we don't need to do anything
return;
}
// if it's the last tab, we add a new tab
slotAddTab();
}
This works great when the user left-clicks on the ‘+’ tab.
I’ve also added a contextual menu that allows the user to rename or delete a tab by right-clicking one of the tabs. I’m handling that in mousePressEvent(). This functionality should work for all tabs EXCEPT the final tab; the user should never be able to rename or delete the ‘+’ tab, since it’s a special case. In mousePressEvent(), I’m attempting to detect which index the user right-clicked on so that I can put the contextual menu in the right place as well as rename/delete the correct tab. Here’s the code for mousePressEvent:
void customTabWidget::mousePressEvent(QMouseEvent *event)
{
QTabWidget::mousePressEvent(event);
if (event->button() == Qt::RightButton)
{
for (int i=0; i < tabBar()->count()-1; i++)
{
QPoint clickPos = mapToGlobal(event->pos());
if (tabBar()->tabRect(i).contains(tabBar()->mapFromGlobal(clickPos)))
{
qDebug("Tab count %d, right click on %d", tabBar()->count(), i);
setCurrentIndex(i);
slotShowContextualMenu(clickPos);
}
}
}
}
Since there’s no reason to show that contextual menu on the ‘+’ tab, I’d like to disable the right click functionality just on the last tab, which I’m trying to do in the mousePressEvent for loop, by only looping to bar->count() – 1. But the problem I’m having is that the right-click on the ‘+’ tab emits currentChanged(int) BEFORE mousePressEvent() is called, causing creation of a new tab in slotTabBarClicked(). Before the user right clicks, count() is 2, current index is 0, and the ‘+’ is at index 1. Once the user right clicks on the ‘+’ tab, by the time we get to mousePressEvent(), count() is 3, current index is 1, and the ‘+’ tab is at index 2. So the mapping doesn’t work and I end up displaying a contextual menu on the newly created “Tab 2â€, even though the user right-clicked on the ‘+’ tab.
The behavior I want is right-clicking on the ‘+’ tab should do nothing; it shouldn’t add a new tab, it shouldn’t show a contextual menu. Right-clicking on any other tab should bring up the contextual menu. Left-clicking on the '+' tab should add a new tab.
What am I missing, or how should I be trying to do this? If there was a separate signal for left vs. right clicks, it’d be easy. But I don’t see a way to easily detect in slotTabBarClicked(int) that it was a right-click that caused currentChanged(int) to be emitted, or that that right-click was on the '+' tab and that I shouldn't do anything...
\ Tab 1 /\ + /
With “Tab 1†set as the current index. Left clicking on the ‘+’ will add a new tab called â€Tab 2â€, and sets “Tab 2†as the current index, like so:
\ Tab 1 /\ Tab 2 /\ + /
To achieve this, I’ve connected the currentChanged(int index) signal to a slot that checks to see if the current index is the last index, and if so it adds a new tab, and sets the newly created one as current. If any other tab is the current index, the slot does nothing. Here’s the code for the slot:
void customTabWidget::slotTabBarClicked(int index)
{
if (index != (count() - 1))
{
// if it's not the last one, we don't need to do anything
return;
}
// if it's the last tab, we add a new tab
slotAddTab();
}
This works great when the user left-clicks on the ‘+’ tab.
I’ve also added a contextual menu that allows the user to rename or delete a tab by right-clicking one of the tabs. I’m handling that in mousePressEvent(). This functionality should work for all tabs EXCEPT the final tab; the user should never be able to rename or delete the ‘+’ tab, since it’s a special case. In mousePressEvent(), I’m attempting to detect which index the user right-clicked on so that I can put the contextual menu in the right place as well as rename/delete the correct tab. Here’s the code for mousePressEvent:
void customTabWidget::mousePressEvent(QMouseEvent *event)
{
QTabWidget::mousePressEvent(event);
if (event->button() == Qt::RightButton)
{
for (int i=0; i < tabBar()->count()-1; i++)
{
QPoint clickPos = mapToGlobal(event->pos());
if (tabBar()->tabRect(i).contains(tabBar()->mapFromGlobal(clickPos)))
{
qDebug("Tab count %d, right click on %d", tabBar()->count(), i);
setCurrentIndex(i);
slotShowContextualMenu(clickPos);
}
}
}
}
Since there’s no reason to show that contextual menu on the ‘+’ tab, I’d like to disable the right click functionality just on the last tab, which I’m trying to do in the mousePressEvent for loop, by only looping to bar->count() – 1. But the problem I’m having is that the right-click on the ‘+’ tab emits currentChanged(int) BEFORE mousePressEvent() is called, causing creation of a new tab in slotTabBarClicked(). Before the user right clicks, count() is 2, current index is 0, and the ‘+’ is at index 1. Once the user right clicks on the ‘+’ tab, by the time we get to mousePressEvent(), count() is 3, current index is 1, and the ‘+’ tab is at index 2. So the mapping doesn’t work and I end up displaying a contextual menu on the newly created “Tab 2â€, even though the user right-clicked on the ‘+’ tab.
The behavior I want is right-clicking on the ‘+’ tab should do nothing; it shouldn’t add a new tab, it shouldn’t show a contextual menu. Right-clicking on any other tab should bring up the contextual menu. Left-clicking on the '+' tab should add a new tab.
What am I missing, or how should I be trying to do this? If there was a separate signal for left vs. right clicks, it’d be easy. But I don’t see a way to easily detect in slotTabBarClicked(int) that it was a right-click that caused currentChanged(int) to be emitted, or that that right-click was on the '+' tab and that I shouldn't do anything...