Qt message box - show message box until timeout - c++

I have to show the saving message box until timeout.
Once the timeout happens go to slot and do some function.
timerToSave=new QTimer(this);
connect(timerToSave,SIGNAL(timeout()),this,SLOT(SavingStatusSlot()));
Above code is the timer, when timeout moves to the saveslot.
bool PopUpManager::PopUpSaveStaus()
{
timerToSave->start(3000);
saveStatus=false;
if(SetThread::getInstance()->UISaveStatus==ST_PROCESSING)
{
msgBox = new QMessageBox(0);
msgBox->setModal(true);
msgBox->setText("Saving ... ");
msgBox->setIcon(QMessageBox::Information);
msgBox->setStandardButtons(QMessageBox::Ok);
msgBox->setCursor(Qt::WaitCursor);
msgBox->setWindowFlags(Qt::FramelessWindowHint| Qt::WindowStaysOnTopHint);
msgBox->setStyleSheet("background-color:#444;color:#FFF;outline:none;");
msgBox->exec();
}
else
SavingStatusSlot();
return saveStatus;
}
Above method called from other classes, when the user click on the save button.
once the method called, starting the timer then displaying the message box.
if timeout happens calling slot [given below]
void PopUpManager::SavingStatusSlot()
{
msgBox->button(QMessageBox::Ok)->animateClick();
timerToSave->stop();
if(SetThread::getInstance()->UISaveStatus==ST_OK)
{
saveStatus=true;
}
else
{
PopUpWithOKButton(" Saving Error ");
saveStatus=false;
}
}
this code is working, I have used the message box with OK button and when the timeout creating the animated click and doing some function.
Now I want to show the Message box without button and when timeout, close the message box then do some function
But the Message box close() is not working.
void PopUpManager::ClosePopUP()
{
if(msgBox->isEnabled())
msgBox->close();
}
if I call the above code the message box has to close, but it is displaying.
Can anyone help me on this.
Thanks in advance.

I have solved the issue
used msgBox->show(); instead of the msgBox->exec();
and msgBox->hide(); insted of msgBox->close();
code is given below.
bool PopUpManager::PopUpSaveStaus()
{
timerToSave->start(3000);
saveStatus=false;
if(UISaveStatus==ST_PROCESSING)
{
msgBox = new QMessageBox(QMessageBox::Information,"Error","Processing ... ",0,0,Qt::FramelessWindowHint| Qt::WindowStaysOnTopHint);
msgBox->setStandardButtons(0);
msgBox->setCursor(Qt::WaitCursor);
msgBox->setStyleSheet("background-color:#444;color:#FFF;outline:none;");
msgBox->show();
}
else
{
SavingStatusSlot();
}
return saveStatus;
}
void PopUpManager::SavingStatusSlot()
{
msgBox->hide();
timerToSave->stop();
if(UISaveStatus==ST_OK)
{
saveStatus=true;
}
else
{
PopUpWithOKButton(" communication Failed ");
saveStatus=false;
}
}

Related

Blocking signal one time in Qt doesn't work correctly

Hi i have following code:
void MainWindow::on_listWidgetNotes_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)//Test!
{
if(current != NULL)
{
ui->plainTextEditContent->setEnabled(true);
change = false;
if(isModified)
{
auto reply = QMessageBox::question(this, "Test", "Do you want save changes?", QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel);
if (reply == QMessageBox::Yes) on_pushButtonSave_clicked();
else if(reply == QMessageBox::No) notes.closeFile();
else
{
//ui->listWidgetNotes->blockSignals(true);
ui->listWidgetNotes->setCurrentItem(previous);
//ui->listWidgetNotes->blockSignals(false);
return;
}
}
isModified = false;
this->setWindowTitle(current->text()+" - VfNotes 1.0");
ui->plainTextEditContent->setPlainText(notes.openFile(current->text()));
}
}
In specified case code have to show message box and set focus on previous item, after select cancel button.
But setCurrentItem calls on_listWidgetNotes_currentItemChanged again with this message box. After use blockSignals focus doesn't come back on previous element. What to do to set focus on previous item after click cancel, that on_listWidgetNotes_currentItemChanged wasn't call again?
So, if this is the slot that gets called when the selection changes, then instead this slot getting called , create another slot and from there, you call this function..
Now this new slot will have the previous item and from there if the function returns a book instead of void signifying that a cancel is pressed, then you call setCurrentItem again...

Quit application call twice the closeevent

I have wrote an application in Qt/c++ on OSX. When quitting the app, I'm catching the closeevent to display dialog box
void MainUI::closeEvent (QCloseEvent *event)
{
if( DeviceUnplugged == false) {
ExitDialog = new DialogExit;
ExitDialog->exec();
if(ExitDialog->result() == QDialog::Accepted) {
m_device.CloseDevice();
event->accept();
}
else {
event->ignore();
}
}
}
The dialog box is correctly displayed when closing using the red cross or using the menu "quit".
but when I'm closing the app using the right click on the icon in the dock, the dialog box appears twice the close event is called twice.
Any idea why ?
Yes, I think it is normal for Mac, at least I had this in my Qt application, too (only on Mac).
I used the following workaround:
void MainUI::closeEvent (QCloseEvent *event)
{
if (m_closing)
{
event->accept();
return;
}
if( DeviceUnplugged == false) {
ExitDialog = new DialogExit;
ExitDialog->exec();
if(ExitDialog->result() == QDialog::Accepted) {
m_device.CloseDevice();
m_closing = true;
event->accept();
}
else {
event->ignore();
}
}
}
By default, boolean variable m_closing should be initialized by false of course in your class. This way second time nothing will be done (processing will be skipped). This worked for me.
Looks like this is a QT bug:
See: https://bugreports.qt.io/browse/QTBUG-43344
Also had this problem when using qt-5.6_4 ,
In my case it happened when using CMD+Q but didn't happen when using the red x button.
Used a similar patch.
I avoided accept or ignore since this is a bug and I don't think we should "talk to it" :-)
Instead I simply return when called more then once.
static int numCalled = 0;
if (numCalled++ >= 1)
return;

Canceling an accepted dialog in Qt (aka user error checking)

I feel like I'm missing something obvious, but I want to be able to error check what the user inputted in a modal dialog when they hit 'OK', and allow them to go back and fix it without closing the dialog.
Is there something I can set within the 'OK' button's slot callback that will tell the dialog not to close?
You can use done method which you could know return value is rejected or not.
for example:
void ExDialog::done(int res)
{
if (res == QDialog::Accepted)
{
// check if it is ok or not
if(not)
{
ShowErrPopUp();
return;
}
}
QDialog::done(res);
}
// when ok button is clicked
void ExDialog::action_ok_bt_clicked()
{
this->accept();
}

qslider sliderReleased value

I m trying to make a media player . The time status of the track is shown using QSlider. Track seek should happen when the user releases the slider somewhere on the QSlider. I had a look on the list of QSlider signals. The one that seems to fit is sliderReleased() which happens when the user releases the slider, but it does not get the latest value of where slider is. So to get sliders latest value I used sliderMoved() and stored reference.
Signal and slot connection
connect(this->ui->songProgress, SIGNAL(sliderMoved(int)), this,
SLOT(searchSliderMoved(int)));
connect(this->ui->songProgress, SIGNAL(sliderReleased()), this,
SLOT(searchSliderReleased()));
Functions
void MainWindow::searchSliderMoved(int search_percent)
{
value=this->ui->songProgress->value();
std::cout<<"Moved: Slider value"<<value<<std::endl;
}
Now I am Using the "value" variable inside searchSliderReleased for seeking
void MainWindow::searchSliderReleased()
{
std::cout<<"Released: Slider value"<<value<<std::endl;
emit search(value);//seek the track to location value
}
But the problem with above technique is that sliderMoved signal does not give the value where the slider is dropped but it give the location from where the slider was moved. How do I obtain the value where the slider was dropped?
You can use the valueChanged(int) signal of the slider, but set the flag
ui->horizontalSlider->setTracking(false);
Just finished building a DiectShow media player with QSlider here at work. Here's a few slot snippets on how I did it.
Widget::sliderPressed()
{
if( isPlaying() )
{
m_wasPlaying = true;
pause();
}
else
{
m_wasPlaying = false;
}
// Set a flag to denote slider drag is starting.
m_isSliderPressed = true;
}
Widget::sliderReleased()
{
if( m_wasPlaying )
{
play();
}
m_wasPlaying = false;
m_isSliderPressed = false;
}
Widget::valueChanged( int value )
{
if( m_isSliderPressed )
{
// Do seeking code here
}
else
{
// Sometime Qt when the user clicks the slider
// (no drag, just a click) Qt will signals
// pressed, released, valueChanged.
// So lets handle that here.
}
}
Had the same problem and calling sliderPosition() instead of value() directly when handling sliderReleased() worked for me.
I prefer to save the last value set by our app, like this pseudocode:
// Save our last value
lastSoftwareVal = 0;
// Set value from program
slider_set_value(value){
lastSoftwareVal = value;
slider.setValue(value)
}
// Slider on change callback
slider_on_change(value){
if(value == lastSoftwareVal){
// Value was changed by our app
return false;
}
// User has changed the value, do something
}

Problems creating progress bar in Visual Studio using MFC

i'm trying to simply fill a progress bar, full when a check box is checked, and empty when the box is unchecked. there is an ONCLICK action for the check box, so i figured i would check the value every time it was clicked, and would fill the bar only when it was checked.
this code includes a couple different things i tried, anything with progCtrl gave me a runtime error. any thoughts would be helpful, thanks!
void Cgui1Dlg::OnBnClickedsetkill()
{
// TODO: Add your control notification handler code here
//IDC_PROGRESS.Value = 100;
//CProgressCtrl progCtrl;
//progCtrl.SetDlgCtrlID(IDC_PROGRESS);
//UpdateData();
//if(changefill)
//{
//IDC_PROGRESS.PBM_SETPOS(100);
//SendMessage(IDC_PROGRESS, PBM_SETPOS, 100);
//progCtrl.SetPos(100);
//}
//else
//{
//filled = FALSE;
//}
UpdateData(FALSE);
}
I would create a control variable for the progress control and the check button. Then, do:
void Cgui1Dlg::OnBnClickedsetkill()
{
if(c_Check.GetCheck()==BST_CHECKED)
{
c_Progress.SetPos(100);
}
else
{
c_Progress.SetPos(0);
}
}