1

I have buttons with & and when I do button->text(), it return with '&' because it has a shortcut, we have buttons sometimes with more than 2 &.

This is for automated remote testing. The people who are writing the tests are not programmers and do not know the object names.

How QT deals when showing the labels on the button without the extras ampersand?

A possible solution? :

qAbstractButton->text().replace(QRegExp("SomeRegex"), "");
Lorac
  • 395
  • 1
  • 4
  • 14
  • This is a classic [X-Y problem](http://meta.stackexchange.com/q/66377/232821). You presume a solution, but you don't tell us why you need it. Your proposed solution is wrong since you should be mentioning that this is to determine which widget has focus from a test harness. And for that, you don't ever want to be comparing button text lest your whole setup become very fragile. – Kuba hasn't forgotten Monica Aug 25 '16 at 16:25
  • @KubaOber this is a fragile test, it's UI Testing. – Lorac Aug 25 '16 at 16:50
  • Since you're insisting on comparing `text()` and not `objectName()`, even though it's wrong, why won't you copy-paste whatever text is set on the button into the test? Why are ampersands a problem? And if you now say that the shortcuts may change as the application evolves, then you should already know that the text will, too. Use object names! – Kuba hasn't forgotten Monica Aug 25 '16 at 17:02
  • If text change then test will fail, which is fine, we will update the test case to make it green again. – Lorac Aug 25 '16 at 17:26
  • Good. Then you don't have to worry about ampersands. Use the entire text you set on the button and you're done. You'll need the test to iterate all the visible buttons and ensure their texts are unique, otherwise there's no way to guarantee valid test results. – Kuba hasn't forgotten Monica Aug 25 '16 at 19:46

2 Answers2

2

You shouldn't ever need the text of the button. You're most likely using the text to determine which button was clicked. This is wrong! You should give the buttons sensible object names. If you design the UI in Qt Designer, they'll already be given names. If you code it up yourself, use setObjectName to set the name. The test harness should check the name of the focused widget.

If the names aren't globally unique, the test harness can use the name of the parent widget too, e.g.

auto widget = qApp->focusWidget();
Q_ASSERT(widget->parent() && widget->parent()->objectName() == "...");
Q_ASSERT(widget->objectName() == "...");

See this answer for coded-up example using object names and other means.

Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • I do it because I need to check if the current button that has the focus is the one I expect with tests – Lorac Aug 25 '16 at 16:02
  • 1
    Your tests will fail due to internationalization etc. You need to give buttons unique identifiers, either as object names or using the property system. – Kuba hasn't forgotten Monica Aug 25 '16 at 16:15
  • Doesn't matter. Object names or object properties are meant to be used to identify objects. That's why they're there! – Kuba hasn't forgotten Monica Aug 25 '16 at 17:00
  • People who are writing the UI testing are not programmers and do not know the object names, only know the labels. – Lorac Aug 25 '16 at 17:02
  • You're already setting up some sort of an automated test system that sends some texts out. Instead of sending `button->text()`, send `button->objectName()`. The specification that the testers work with should include object names, and that's what they should test. The spec should also mention that these object names aren't meant to change. And an `objectName()` can be different than the name of the member/variable in the source code. – Kuba hasn't forgotten Monica Aug 25 '16 at 17:04
  • Testers can open `.ui` files in Designer and get either object name or full text (with ampersands) from it. If you don't use `.ui` files, you need some other way of conveying this. You must have a spec of some sort - if you don't, you're doing it wrong anyway. – Kuba hasn't forgotten Monica Aug 25 '16 at 17:06
  • To make testing easier, the buttons can also display the object name, either by replacing `text()` or as an overlay. It's easy to iterate all visible objects and apply such a transformation, e.g. `for (auto top : qApp->topLevelWidgets()) for (auto widget : top->findChildren()) widget->metaObject()->invokeMethod(widget, "setText", Q_ARG(QString, widget->objectName()));` Ideas for overlays are available [here](http://stackoverflow.com/a/19386886/1329652). – Kuba hasn't forgotten Monica Aug 25 '16 at 17:09
0

I ended up using this algorithm :

const QString labelOnButton = qAbstractButton->text();
QString fixedLabel;
int i = 0;
int lastIndex = labelOnButton.length() - 1;
while(i < lastIndex)
{
    if (labelOnButton[i] == '&')
    {
        if (labelOnButton[i + 1] == '&')
        {
            fixedLabel += labelOnButton[i];
            ++i;
        }
    }
    else
    {
        fixedLabel += labelOnButton[i];
    }
    ++i;
}
if (labelOnButton[lastIndex] != '&')
{
    fixedLabel += labelOnButton[lastIndex];
}
return fixedLabel;
Lorac
  • 395
  • 1
  • 4
  • 14