LINUX.ORG.RU

Qt, не работает QCloseEvent::ignore()

 closeevent, mainwindow,


0

2

Подскажите, куда копнуть?

Вот реализация обработчика событий закрытия главного окна:

void MainWindow::closeEvent(QCloseEvent *eClose)
{
    qDebug() << "TRY TO EXIT";
    bool check = false;
    if (!this->_setsStorage->value("adminPass").toString().isEmpty()
            &&
            this->_setsStorage->value("adminPass") != QString(QCryptographicHash::hash(QString("").toAscii(),QCryptographicHash::Md5).toHex())
            &&
            this->passwordCheck()
    ) {
        qDebug() << "correct pass";
        //this->close();
        check = true;
    } else {
        eClose->ignore();
        qDebug() << "wrong pass";
        QMessageBox msg(this);
        msg.setText("Wrong password!");
        msg.setModal(true);
        msg.exec();
        qDebug() << "after warning";
        check = false;
    }

    if (!check) {
        eClose->ignore();
    }
}

как бы я не исголялся - в любом случае закрывает. но если закомментить весь код метода и вставить лишь одно игнорирование - то работает!

В чем дело? Как пофиксить?

★★★★★
Ответ на: комментарий от trex6

на консоле вот что:

TRY TO EXIT 
wrong pass 
after warning 
I:\Qt\ScreenShotter\ScreenShotter-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK_______\release\ScreenShotter.exe завершился с кодом 0

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от trex6

Это уже эксперименты. Было и один раз, и разные варианты (ignore, accept) в разных «ветках» условий... все едино.

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от pztrn

да у меня вроде тоже в конце... :(

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от trex6

я не совем пойму, что так разнится с примером у меня?

 void MainWindow::closeEvent(QCloseEvent *event)
 {
     if (maybeSave()) {
         writeSettings();
         event->accept();
     } else {
         event->ignore();
     }
 }
bvn13 ★★★★★
() автор топика
Ответ на: комментарий от pztrn

Выяснил путем эксперимента

что во все виновата моя проверка пароля при выходе:

bool MainWindow::passwordCheck()
{
    if (this->_setsStorage->value("adminPass")
        ==
        QString(QCryptographicHash::hash(QString("").toAscii(),QCryptographicHash::Md5).toHex())
    ) {
        return true;
    }

    PasswordDialog *dlg = new PasswordDialog(this);
    connect(dlg, SIGNAL(destroyed()), this, SLOT(on_dlgPasswordCheck_close()));

    dlg->setModal(true);
    dlg->exec();
    this->isDlgPasswordCheckOpen = true;

    //while (this->isDlgPasswordCheckOpen) {}; //waits...

    QString passwordCheck = dlg->getPassword();

    disconnect(dlg, SIGNAL(destroyed()), this, SLOT(on_dlgPasswordCheck_close()));
    delete dlg;

    return
        this->_setsStorage->value("adminPass")
        ==
        QString(QCryptographicHash::hash(passwordCheck.toAscii(),QCryptographicHash::Md5).toHex())
    ;
}

если этот метод не вызывать, то все ок, выйти нельзя. А если вызывать - то выходит.

Как с этим бороться, если цель - спросить пароль перед выходом?

bvn13 ★★★★★
() автор топика
Ответ на: Выяснил путем эксперимента от bvn13

спросить пароль перед выходом

Про прямоту подобного решения тебе еще расскажут. В целом - это не есть гуд.

если этот метод не вызывать, то все ок, выйти нельзя. А если вызывать - то выходит.

Игнорируй клосеевент, выводи окошко для ввода пароля, не дожидайся, когда там что-то выберут. После того, как введут верный пароль - выставь какую-нибудь переменную типа
«bool m_closable» в труЪ.
Есом получаешь клосеевент и клосабл тру - закрывайся.

P.S. Мне страшно становится от того, что где-то в этой стране, совсем рядом со мной, живут такие вот «программисты».

trex6 ★★★★★
()
Последнее исправление: trex6 (всего исправлений: 1)
Ответ на: комментарий от pztrn

Да что тут советовать, если ТС не студент одного из первых курсов, то тут лучше всего сменить профессию посоветовать.

trex6 ★★★★★
()
Ответ на: комментарий от frozenix

Тут дело совсем не в говнокоде.
Человек не может придумать алгоритм для решения простой проблемы. Элементарной.

trex6 ★★★★★
()
Ответ на: комментарий от trex6

Не судите людей свысока. Алгоритм с булевом я делал в одном из прошлых проектов. Давно это было. В основном, я 1с-ник. Но мне показалось, что можно пойти «влоб». Ан, не вышло. Что ж, спасибо в любом случае за помощь. Буду переделывать чудок.

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от pztrn

а можно еще совета спросить?

вот я переделал на скорую руку:

void MainWindow::on_closeTry()
{
    if (!this->_setsStorage->value("adminPass").toString().isEmpty()
            &&
            this->_setsStorage->value("adminPass") != QString(QCryptographicHash::hash(QString("").toAscii(),QCryptographicHash::Md5).toHex())
    ) {
        if (this->passwordCheck()) {
            this->isCloseable = true;
            qDebug() << "correct pass";
            //this->close();
        } else {
            QMessageBox msg(this);
            msg.setText("Wrong password!");
            msg.setModal(true);
            msg.exec();
            this->isCloseable = false;
        }
    } else {
        this->isCloseable = true;
        //this->close();
    }
    emit this->close();
}

void MainWindow::closeEvent(QCloseEvent *eClose)
{
    if (!this->isCloseable) {
        qDebug() << "couldnot exit";
        eClose->ignore();
    }
}

void MainWindow::on_closeTry() - это публичный слот, привязанный явно к пункту контекстного меню на иконке в трее. Только вот одно НО. А как перехватить сигнал закрытия, посылаемый приложению при закрытии через таскбар? Там же правой кнопкой мыши - Закрыть окно (и подобное) - вызовет напрямую closeEvent, а не мою заглушку. Хотя, я сейчас соображаю, что в моем случае будет безусловный отлуп на этот сигнал. Что тоже вполне меня устраивает. Просто хочется до конца вникнуть.

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от bvn13

Если не падает, то это еще не значит, что оно работает правильно. Ты один раз освобождаешь и Qt еще раз, по этому я и сказал тебе читать книги.

frozenix ★★★
()

Обязательно прочитай Макконнелла, «Совершенный код».

unfo ★★★★★
()
Ответ на: комментарий от frozenix

Эх... давно я не писал на куте... он уже сборщиками мусора обзавелся? а почему тогда эти сборщики такие «неумные», если после того, как я освободил память сам, они тоже ее освобождают?

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от bvn13

Это не совсем сборщик мусора. Просто родители убивают своих детей. Да, это в Кьюте уже достаточно давно.

panter_dsd ★★★★
()
Ответ на: комментарий от bvn13

Там нет сборщика мусора, читайте документацию.

P.S. Теперь я понял, почему все так не любят «программистов» 1с.

trex6 ★★★★★
()
Ответ на: комментарий от trex6

И это... Если я правильно помню, то процесс убивания потомков инициируется при убивании текущего Qt-объекта. А у меня форма живет только в пределах одного метода. Дальше она не нужна. И не нужно ее хранить. Вот скажите, раз Вы такой умный, если я не стану вручную делать delete dlg, и вызову 300 раз этот метод, порождающий новую MyDialog *dlg = MyDlg(this) Qt-сущность, не будет ли тут утечки памяти, а?

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от bvn13

Читайте документацию. Там все написано.

Если есть неотвратимое желание, могу провести для вас несколько занятий по Qt (на полном серьезе, у меня есть достаточный опыт преподавательской деятельности), но это будет не бесплатно.

trex6 ★★★★★
()
Ответ на: комментарий от panter_dsd

Если бы вы уделили больше внимания всему треду, а не только его окончанию, то поняли бы, что если попытаться дождаться ответа от messageBox в самом методе, то ничего не выйдет, приложение закроется.

Если же из метода выйти, то объект на куче будет уничтожен.

Единственный способ выйти из метода и отобразить messageBox на достаточное для пользователя время - создать объект на куче. Есть еще вариант создания этого MessageBox как поля класса (лучший вариант на мой взгляд, если этот класс QMainWindow).

trex6 ★★★★★
()
Ответ на: комментарий от trex6

Да, извиняюсь, начало топика забыл. В данном случае лучше в куче и делетОнКлоуз.

panter_dsd ★★★★
()
Ответ на: комментарий от trex6

Ух... да, видимо, я действительно отстал/недочитал... Не могли бы Вы поделиться прямыми ссылками по поводу всего Вами сказанного на документацию? Какой раздел ее посмотеть?

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от trex6

Вчитался внимательней, чудок погуглил. Кажется, я Вас понял. :)

bvn13 ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.