QListWidget, how to post a question to the user before allowing change?
-
Example:
#include <QListWidget> #include <QApplication> #include <QMessageBox> int main(int argc, char *argv[]) { QApplication app(argc,argv); QListWidget mainWid; mainWid.setSelectionMode(QAbstractItemView::ExtendedSelection); for(int i=0;i<5;++i) mainWid.addItem(QStringLiteral("Item ") + QString::number(i)); bool userSelected = true; QObject::connect(mainWid.selectionModel(),&QItemSelectionModel::selectionChanged,[&mainWid,&userSelected](const QItemSelection &selected, const QItemSelection &deselected){ if(!userSelected) return; if(QMessageBox::question(&mainWid,QStringLiteral("Are you sure?"),QStringLiteral("Are you sure you want to change the selection?")) != QMessageBox::StandardButton::Yes){ userSelected=false; mainWid.selectionModel()->select(selected,QItemSelectionModel::Deselect); mainWid.selectionModel()->select(deselected,QItemSelectionModel::Select); userSelected=true; } }); mainWid.show(); return app.exec(); } -
Ok, the problem can be solved with a simple reimplementation of the selection model:
#include <QItemSelectionModel> class AskSelectionModel : public QItemSelectionModel{ Q_OBJECT Q_DISABLE_COPY_MOVE(AskSelectionModel) public: using QItemSelectionModel::QItemSelectionModel; public slots: void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) override{ askSelect(selection,command); } virtual void actuallySelect(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command){ QItemSelectionModel::select(selection,command); } signals: void askSelect(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command); };int main(int argc, char *argv[]) { QApplication app(argc,argv); QListWidget mainWid; AskSelectionModel* askModel = new AskSelectionModel(mainWid.model(),&mainWid); mainWid.setSelectionMode(QAbstractItemView::ExtendedSelection); mainWid.setSelectionModel(askModel); for(int i=0;i<5;++i) mainWid.addItem(QStringLiteral("Item ") + QString::number(i)); QObject::connect(askModel,&AskSelectionModel::askSelect,[&mainWid,askModel](const QItemSelection &selection, QItemSelectionModel::SelectionFlags command){ if(QMessageBox::question(&mainWid,QStringLiteral("Are you sure?"),QStringLiteral("Are you sure you want to change the selection?")) == QMessageBox::StandardButton::Yes){ askModel->actuallySelect(selection, command); } }); mainWid.show(); return app.exec(); } -
Ok, the problem can be solved with a simple reimplementation of the selection model:
#include <QItemSelectionModel> class AskSelectionModel : public QItemSelectionModel{ Q_OBJECT Q_DISABLE_COPY_MOVE(AskSelectionModel) public: using QItemSelectionModel::QItemSelectionModel; public slots: void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) override{ askSelect(selection,command); } virtual void actuallySelect(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command){ QItemSelectionModel::select(selection,command); } signals: void askSelect(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command); };int main(int argc, char *argv[]) { QApplication app(argc,argv); QListWidget mainWid; AskSelectionModel* askModel = new AskSelectionModel(mainWid.model(),&mainWid); mainWid.setSelectionMode(QAbstractItemView::ExtendedSelection); mainWid.setSelectionModel(askModel); for(int i=0;i<5;++i) mainWid.addItem(QStringLiteral("Item ") + QString::number(i)); QObject::connect(askModel,&AskSelectionModel::askSelect,[&mainWid,askModel](const QItemSelection &selection, QItemSelectionModel::SelectionFlags command){ if(QMessageBox::question(&mainWid,QStringLiteral("Are you sure?"),QStringLiteral("Are you sure you want to change the selection?")) == QMessageBox::StandardButton::Yes){ askModel->actuallySelect(selection, command); } }); mainWid.show(); return app.exec(); }@VRonin said in QListWidget, how to post a question to the user before allowing change?:
QItemSelectionModel
I know this is quite old now, I'm looking at implementing this now, in the slot:void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) override{ askSelect(selection,command); }Is the line askSelect correct? because its a signal in the class, shouldn't it read:
emit askSelect(selection, command);?
-
@VRonin said in QListWidget, how to post a question to the user before allowing change?:
QItemSelectionModel
I know this is quite old now, I'm looking at implementing this now, in the slot:void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) override{ askSelect(selection,command); }Is the line askSelect correct? because its a signal in the class, shouldn't it read:
emit askSelect(selection, command);?
@SPlatten You don't have to use emit.
emit is an empty macro and is only used to make clear to the reader of the code that a signal is emitted.
Also, trying to execute the code is faster than asking in a forum and waiting for an answer :-) -
@VRonin said in QListWidget, how to post a question to the user before allowing change?:
QItemSelectionModel
I know this is quite old now, I'm looking at implementing this now, in the slot:void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) override{ askSelect(selection,command); }Is the line askSelect correct? because its a signal in the class, shouldn't it read:
emit askSelect(selection, command);?
-
Ok, the problem can be solved with a simple reimplementation of the selection model:
#include <QItemSelectionModel> class AskSelectionModel : public QItemSelectionModel{ Q_OBJECT Q_DISABLE_COPY_MOVE(AskSelectionModel) public: using QItemSelectionModel::QItemSelectionModel; public slots: void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) override{ askSelect(selection,command); } virtual void actuallySelect(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command){ QItemSelectionModel::select(selection,command); } signals: void askSelect(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command); };int main(int argc, char *argv[]) { QApplication app(argc,argv); QListWidget mainWid; AskSelectionModel* askModel = new AskSelectionModel(mainWid.model(),&mainWid); mainWid.setSelectionMode(QAbstractItemView::ExtendedSelection); mainWid.setSelectionModel(askModel); for(int i=0;i<5;++i) mainWid.addItem(QStringLiteral("Item ") + QString::number(i)); QObject::connect(askModel,&AskSelectionModel::askSelect,[&mainWid,askModel](const QItemSelection &selection, QItemSelectionModel::SelectionFlags command){ if(QMessageBox::question(&mainWid,QStringLiteral("Are you sure?"),QStringLiteral("Are you sure you want to change the selection?")) == QMessageBox::StandardButton::Yes){ askModel->actuallySelect(selection, command); } }); mainWid.show(); return app.exec(); }@VRonin , can you help with this implementation?
//ABC = Ask Before Change QString strABC(mpobjNode->strGetAttribute (clsXMLnode::mscszAttrAskBeforeChange)); if ( strABC.isEmpty() != true ) { //Use "clsQtAskBeforeChange" to prompt user for confirmation if //changes in child nodes before allowing change clsQtAskBeforeChange* pobjABC(new clsQtAskBeforeChange(model(), this)); setSelectionMode(QAbstractItemView::ExtendedSelection); setSelectionModel(pobjABC); //Now the widget should be set-up, finalise set-up clsXMLinterface::setup(); //Connect signal clsQtListWidget* pobjThis(this); QObject::connect(pobjABC, &clsQtAskBeforeChange::pendingSelect ,[pobjABC, strABC, pobjThis](const QItemSelection& crobjSelection ,QItemSelectionModel::SelectionFlags cmdFlags) { if ( QMessageBox::question(pobjThis, QStringLiteral("Please confirm...") , strABC) == QMessageBox::StandardButton::Yes) { pobjABC->actuallySelect(crobjSelection, cmdFlags); } }); }The above is in my implementation of QListWidget constructor. On the line that contains:
QObject::connect(pobjABC, &clsQtAskBeforeChange::pendingSelectTo the right of it I have the message:
Pass a context object as 3rd connect parameter [clazy-connect-3arg-lambda]This is cryptic, I don't understand what it is telling me, have I done anything wrong because the code seems to work fine?
-
@VRonin , can you help with this implementation?
//ABC = Ask Before Change QString strABC(mpobjNode->strGetAttribute (clsXMLnode::mscszAttrAskBeforeChange)); if ( strABC.isEmpty() != true ) { //Use "clsQtAskBeforeChange" to prompt user for confirmation if //changes in child nodes before allowing change clsQtAskBeforeChange* pobjABC(new clsQtAskBeforeChange(model(), this)); setSelectionMode(QAbstractItemView::ExtendedSelection); setSelectionModel(pobjABC); //Now the widget should be set-up, finalise set-up clsXMLinterface::setup(); //Connect signal clsQtListWidget* pobjThis(this); QObject::connect(pobjABC, &clsQtAskBeforeChange::pendingSelect ,[pobjABC, strABC, pobjThis](const QItemSelection& crobjSelection ,QItemSelectionModel::SelectionFlags cmdFlags) { if ( QMessageBox::question(pobjThis, QStringLiteral("Please confirm...") , strABC) == QMessageBox::StandardButton::Yes) { pobjABC->actuallySelect(crobjSelection, cmdFlags); } }); }The above is in my implementation of QListWidget constructor. On the line that contains:
QObject::connect(pobjABC, &clsQtAskBeforeChange::pendingSelectTo the right of it I have the message:
Pass a context object as 3rd connect parameter [clazy-connect-3arg-lambda]This is cryptic, I don't understand what it is telling me, have I done anything wrong because the code seems to work fine?
@SPlatten
Although this 3-argumentconnect()works, it is more usual to pass 4 arguments, with the 3rd argument being the "context" object for the slot'sthis. That is what the warning is telling you. I believe you can get rid of that via (something like):QObject::connect(pobjABC, &clsQtAskBeforeChange::pendingSelect , pobjABC, [strABC, pobjThis](const QItemSelection& crobjSelection ,QItemSelectionModel::SelectionFlags cmdFlags) { if ( QMessageBox::question(pobjThis, QStringLiteral("Please confirm...") , strABC) == QMessageBox::StandardButton::Yes) { this->actuallySelect(crobjSelection, cmdFlags); } }); -
@SPlatten
Although this 3-argumentconnect()works, it is more usual to pass 4 arguments, with the 3rd argument being the "context" object for the slot'sthis. That is what the warning is telling you. I believe you can get rid of that via (something like):QObject::connect(pobjABC, &clsQtAskBeforeChange::pendingSelect , pobjABC, [strABC, pobjThis](const QItemSelection& crobjSelection ,QItemSelectionModel::SelectionFlags cmdFlags) { if ( QMessageBox::question(pobjThis, QStringLiteral("Please confirm...") , strABC) == QMessageBox::StandardButton::Yes) { this->actuallySelect(crobjSelection, cmdFlags); } });@JonB Since the lambda accesses
this, the third parameter should bethistoo. Otherwise the disconnect will not be done whenthisis deleted but pobjABC is still alive. -
@JonB Since the lambda accesses
this, the third parameter should bethistoo. Otherwise the disconnect will not be done whenthisis deleted but pobjABC is still alive.@Christian-Ehrlicher
I'm lost --- where does the (original) lambda accessthis? The onlythisis the one I put in for thepobjABCwhich I have made the context? In the body I replacedpobjABC->actuallySelect()bythis->actuallySelect(), for clarity; and I chosepobjABCas the context as it felt like that was the primary slot object there. (I did get this right, didn't I? The slot-context-object, mypobjABC, becomesthisin the lambda body?) My thought was to pass that as it won't be disconnected ifpobjABCdies. I admit I didn't look terribly closely, I get awfully mixed with all the OP'spobj...s :) -
@Christian-Ehrlicher
I'm lost --- where does the (original) lambda accessthis? The onlythisis the one I put in for thepobjABCwhich I have made the context? In the body I replacedpobjABC->actuallySelect()bythis->actuallySelect(), for clarity; and I chosepobjABCas the context as it felt like that was the primary slot object there. (I did get this right, didn't I? The slot-context-object, mypobjABC, becomesthisin the lambda body?) My thought was to pass that as it won't be disconnected ifpobjABCdies. I admit I didn't look terribly closely, I get awfully mixed with all the OP'spobj...s :)@JonB I only looked at your answer - the slot accesses
thisand not pobjABC so the signals scope should bethistoo :) -
@Christian-Ehrlicher
I'm lost --- where does the (original) lambda accessthis? The onlythisis the one I put in for thepobjABCwhich I have made the context? In the body I replacedpobjABC->actuallySelect()bythis->actuallySelect(), for clarity; and I chosepobjABCas the context as it felt like that was the primary slot object there. (I did get this right, didn't I? The slot-context-object, mypobjABC, becomesthisin the lambda body?) My thought was to pass that as it won't be disconnected ifpobjABCdies. I admit I didn't look terribly closely, I get awfully mixed with all the OP'spobj...s :)@JonB , pobjABC does become this in the lambda because the connection is created using pobjABC.
I've tried various suggestions, however I'm still getting the same result:
Pass a context object or 3rd connect parameter [clazy-connect-3ard-lambda]This is gibberish because there are already 3 parameters passed. I even changed the parameters to:
[strABC, pobjABC, this, pobjThis]Still get the same message.
-
@JonB , pobjABC does become this in the lambda because the connection is created using pobjABC.
I've tried various suggestions, however I'm still getting the same result:
Pass a context object or 3rd connect parameter [clazy-connect-3ard-lambda]This is gibberish because there are already 3 parameters passed. I even changed the parameters to:
[strABC, pobjABC, this, pobjThis]Still get the same message.
@SPlatten said in QListWidget, how to post a question to the user before allowing change?:
This is gibberish because there are already 3 parameters passed.
This is not gibberish - you only have to read it properly and our answers... you have to pass a context as third parameter, not the lambda (this should be the forth then)
-
@JonB , pobjABC does become this in the lambda because the connection is created using pobjABC.
I've tried various suggestions, however I'm still getting the same result:
Pass a context object or 3rd connect parameter [clazy-connect-3ard-lambda]This is gibberish because there are already 3 parameters passed. I even changed the parameters to:
[strABC, pobjABC, this, pobjThis]Still get the same message.
@SPlatten
I posted mine with a 4th parameter and explained. Did you actually copy it and get the same error message? I don't think so. The issue is the number of parameters toconnect(). You are looking at the number of items in the[...]context for the lambda, which is not what the message refers to. -
@SPlatten
I posted mine with a 4th parameter and explained. Did you actually copy it and get the same error message? I don't think so. The issue is the number of parameters toconnect(). You are looking at the number of items in the[...]context for the lambda, which is not what the message refers to.@JonB , @Christian-Ehrlicher , sorry, it wasn't clear to me at first that the actual 3rd parameter you were referring to was of the connect, I thought it was the 3rd parameter of the lambda set.
It was more confusing because when compiled the connect worked without the 3rd parameter. being correct.
-
@JonB , @Christian-Ehrlicher , sorry, it wasn't clear to me at first that the actual 3rd parameter you were referring to was of the connect, I thought it was the 3rd parameter of the lambda set.
It was more confusing because when compiled the connect worked without the 3rd parameter. being correct.