How to get the role of a QPushButton created by a QDialogButtonBox? - c++

I'm trying get all the button child widgets of a currently active window. The buttons were created through QDialogButtonBox. I'm trying to get the roles of each button so I can identify which button is the OK, CANCEL, or SAVE button. However I'm getting an error with the following code:
QWidget *pWin = QApplication::activeWindow();
QList<QPushButton *> allPButtons = pWin->findChildren<QPushButton *>();
QListIterator<QPushButton*> i(allPButtons);
while( i.hasNext() )
{
QDialogButtonBox *pButtonRole = new QDialogButtonBox();
QDialogButtonBox::ButtonRole role = pButtonRole->buttonRole(i.next());
qDebug() << "buttonRole: " << role << endl ;
//the value of role here is -1, which means it's an invalid role...
}
I'm getting a negative value when getting the button's role :(
Can somebody tell me what's wrong with the code?

You can't call a non-static method like that. You need to have the QDialogButtonBox variable and call that particular instance for buttonRole() to work.
QDialogButtonBox::ButtonRole role = myButtonBoxPtr->buttonRole(i.next());

You are creating a new empty QDialogButtonBox which has no idea about buttons in allPButtons list. Calling buttonRole() on them returns -1 (InvalidRole) because buttons are not in that button-box.
You must do as jkerian wrote and myButtonBoxPtr must point to the QDialogButtonBox which is already in your window.
You can try something like this (if you have one ButtonBox):
QDialogButtonBox *box = pWin->findChild<QDialogButtonBox *>();
foreach(QAbstractButton* button, box->buttons())
{ qDebug() << box->buttonRole(button); }

Related

Appears an error message when closing the QMdiSubWindow

I have created a QMainWindow which could create one or more QMdiSubWindows, and the following method is the responsible for creating the sub-windows:
void PSubWindow::newFile(){
static ushort newFileCounter = 1;
this->mdiareaContainer = this->mainWindow->findChild<QMdiArea*>("mdiArea");
QMdiSubWindow *window = new QMdiSubWindow();
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWidget(new QPlainTextEdit);
this->subWindow = mdiareaContainer->addSubWindow(window);
QString FileTitle = "Untitled " + QString::number(newFileCounter++);
this->subWindow->setWindowTitle(FileTitle);
this->subWindow->show();
this->mdiareaContainer->setViewMode(QMdiArea::TabbedView);
this->mdiareaContainer->setTabsClosable(true);
this->mdiareaContainer->setTabsMovable(true);
this->tabs = mdiareaContainer->findChild<QTabBar*>();
this->tabs->setExpanding(false);
QObject::connect(this->tabs, SIGNAL(tabCloseRequested(int)), this, SLOT(on_subWindow_tabCloseRequested(int)), Qt::UniqueConnection);
}
As you seen in the code I have created a signal for closing which one of them.
void PSubWindow::on_subWindow_tabCloseRequested(int index) {
QList<QMdiSubWindow*> sub = this->mdiareaContainer->subWindowList();
qDebug()<< sub[index];
}
Always when closing the last window appear an error message during runtime, the message says:
How can I solve that problem?
Check if index is smaller than sub.size(); the list will be empty because the last window has been closed, but index is probably still 0.
When you remove the tab, the window is removed, so that position no longer exists in the list.

Accessing a the click() slot of a button generated during runtime - Qt Creator

I have a GUI project in Qt Creator that functions as a shopping list. I am using a QLineEdit to add items to a QTableWidget. The user types something in, presses the QPushButton. The slot then adds a new row to the QTableWidget with the input, in the first column, and a new QPushButton in the second column. I then want the user to be able to press the button and have it clear that row, but I don't know how to access that slot, or sender (I'm not sure the proper term.) Here is the code so far. itemList is my QTableWidget, itemInput is the QLineEdit.
void MainWindow::on_btnAddItem_clicked()
{
ui->itemList->insertRow(ui->itemList->rowCount());
ui->itemList->setItem((ui->itemList->rowCount())-1,0,new QTableWidgetItem(ui->itemInput->text()));
QPushButton *clear = new QPushButton("Clear",this);
ui->itemList->setIndexWidget(ui->itemList->model()->index(ui->itemList->rowCount()-1, 1), clear);
ui->itemInput->clear();
}
Here is when the program is initially run. Once they click the button, it runs on_btnAddItem_clicked()
Then it looks like this, and I want to make the clear button remove the row it is a part of.
Do I need to create a new slot? Any help?
You will need to make your own button class and inherit QPushButton. Something like this :
class MyButton : public QPushButton {
public:
MyButton();
QTableWidgetItem *titem;
}
And here you MainWindow :
void MainWindow::on_btnAddItem_clicked()
{
ui->itemList->insertRow(ui->itemList->rowCount());
ui->itemList->setItem((ui->itemList->rowCount())-1,0,new QTableWidgetItem(ui->itemInput->text()));
MyButton *clear = new MyButton("Clear",this);
clear->titem = ui->itemList->item(ui->itemList->rowCount()-1, 0);
connect(clear, SIGNAL(clicked()), SLOT(on_btnClear_Clicked()));
ui->itemList->setIndexWidget(ui->itemList->model()->index(ui->itemList->rowCount()-1, 1), clear);
ui->itemInput->clear();
}
void MainWindow::on_btnClear_Clicked()
{
MyButton *btn = (MyButton*)QObject::sender();
ui->itemList->removeRow(btn->titem->row());
}
Please note, it is only step to do it.

The inferior stopped because it received signal from the Operating System error on resizable scrollarea

I have a QScrollArea inside QTabWidget and I have a QWidget beside my QTabWidget. I want QScrollArea to be resized when my main window is resized, so I have made this code like this:
void frmSummaryContact::on_btnAddNewContact_clicked()
{
MainWindow *mnWindow = qobject_cast<MainWindow *>(this->parent()->parent()->parent()->parent()->parent()->parent());
QTabWidget *tbWidget = qobject_cast<QTabWidget *>(this->parent()->parent()->parent()->parent());
frmDetailContact *frm = new frmDetailContact(mnWindow, "input", -1, mnWindow->rightPane());
QScrollArea *scrlForm = new QScrollArea;
scrlForm->setWidgetResizable(true);
scrlForm->setWidget(frm);
mnWindow->AddNewTab(tbWidget, scrlForm, "Add Contact");
}
my QTabWidget is in different form, so I cast it with qobject_cast. Meanwhile in another form, I have a toogle button to hide QWidget so my QTabWidget get wider. So in that form I have a code like this:
void frmDetailContactToggle::on_btnSearch_clicked()
{
MainWindow *mnWindow = qobject_cast<MainWindow *>(this->parent()->parent()->parent());
QLayoutItem *child;
while ((child = mnWindow->rightPane()->layout()->takeAt(0)) != 0)
child->widget()->setVisible(false);
mnWindow->rightPane()->setVisible(false);
QScrollArea *scrlContent = qobject_cast<QScrollArea *>(mnWindow->tabContentWidget()->currentWidget());
scrlContent->setWidgetResizable(false);
mnWindow->tabContentWidget()->setGeometry(mnWindow->tabContentWidget()->x(), mnWindow->tabContentWidget()->y(), m_width - mnWindow->tabContentWidget()->x() - 10, mnWindow->tabContentWidget()->height());
scrlContent->setWidgetResizable(true);
m_showRightPane = false;
}
I have realized that I can't change the geometry when WidgetResizable is true. It showed "The inferior stopped because it received signal from the Operating System" error. So I thought about making it false, changing the geometry, and making it true again. But when I want to make it true, I encounter the same error. Could anyone please help me to solve my problem?
if your program used uninitialized pointers,that may causes SIGSEGV.

Removing item from QListWidget from inside a Widget

I have a QListWidget in my MainWindow that displays a list of VideoWidgets (a custom QWidget).
VideoWidget has a clickable label where on clicking the label it should delete a file and then remove the QListItem which holds the VideoWidget from the QListWidget. Here is my VideoWidget class:
VideoWidget::VideoWidget(QWidget *parent) : QWidget(parent)
{
ClickableLabel *smallRed = new ClickableLabel(this)
//...
QObject::connect(smallRed,SIGNAL(clicked()),this,SLOT(removeVideo()));
}
void VideoWidget::removeVideo(){
//...code to remove a file
QListWidget* list = myParent->getList();
QListWidgetItem* item = list->takeItem(list->currentIndex().row());
myList->removeItemWidget(item);
}
The problem is that clicking the smallRed label will not select its item in the QListWidget which means that list->currentIndex().row() will return -1. Clicking anywhere else in the Widget does select the current item. For the code to work I currently have to first click anywhere in the VideoWidget and then click its ClickableLabel. Is there any way I can achieve the same effect with one single click on my ClickableLabel?
From your previous qestion, we suggested use signal and slots. For example:
for(int r=0;r<3;r++)
{
QListWidgetItem* lwi = new QListWidgetItem;
ui->listWidget->addItem(lwi);
QCheckBox *check = new QCheckBox(QString("checkBox%1").arg(r));
check->setObjectName("filepath");
connect(check,SIGNAL(clicked()),this,SLOT(echo()));
ui->listWidget->setItemWidget(lwi,check);
}
Slot:
void MainWindow::echo()
{
qDebug() << sender()->objectName() << "should be remmoved";
}
It is not unique way to solve this problem, but it shows all main things, with signals and slots mechanism, objectName and sender() you can achieve all what you need.
sender() return object which send signal, you can cast it, but if you need only objectName you should not cast.

Qt, PushButton, id attribute? Any way to know which button was clicked

void MainWindow::addRadioToUI()
{ int button_cunter=4;
while(!database.isEmpty())
{ button_cunter++;
QPushButton *one = new QPushButton("Play: "+name(get_r.getTrackId()));
one->setIcon(QIcon(":/images/play_button.png"));
one->setMaximumWidth(140);
one->setFlat(true);
QGroupBox* get_rGB = new QGroupBox("somethink");
QFormLayout* layout = new QFormLayout;
if(button_cunter%5 == 0){
layout->addWidget(one);
}
get_rGB->setLayout(layout);
scrollAreaWidgetContents->layout()->addWidget(get_rGB);
}
}
I have a few QPushButtons which are added automaticlly.
Is there a way to add "id attribute or sth else" to button and next know which button was clicked? I have different action for each button.
QApplication offers sender() which contains which object sent the signal. So you can do:
//slot, this could also be done in a switch
if(button[X] == QApplication::sender()){
doX();
}else if(button[Y] == QApplication::sender()){
doY();
}
http://doc.qt.io/qt-4.8/qobject.html#sender
QSignalMapper is pretty good for this type of thing.
You would define your slot like this for instance:
public slots:
void clicked(int buttonId); // or maybe trackId
Then add a QSignalMapper* member to your class and connect it to that slot:
signalMapper = new QSignalMapper(this);
connect(signalMapper, SIGNAL(mapped(int)),
this, SLOT(clicked(int)));
In the addRadioToUI, after creating your push button, do:
signalMapper.setMapping(one, button_cunter);
// or trackId if that's more practical
If all you need is a pointer to the object that triggered the signal though, you can use the static QOjbect::sender function in your slot to get a handle to that.
Use QButtonGroup. It takes id as a parameter when a button is added and provides the id to a slot when a button in the group is pressed.