How to quit QApplication gracefully on logout? - c++

I have an application with notification area icon, so the main window may ignore close event. I am trying to save preferences and history on application quit. I also want to handle logout when the application is running. While the application is cross-platform, it is most convenient/useful in GNU/Linux, so Windows logout behavior is of much less concern.
This is a minimal compilable example that was used for testing behavior of different desktop environments/window managers:
// main.cpp
# include <QApplication>
# include <QMainWindow>
# include <QCloseEvent>
# include <QTimer>
# include <iostream>
class M : public QMainWindow
{
Q_OBJECT
public:
~M();
public slots:
void onAboutToQuit();
private:
void closeEvent(QCloseEvent *);
};
M::~M()
{
std::cout << "M::~M()" << std::endl;
}
void M::onAboutToQuit()
{
std::cout << "onAboutToQuit()" << std::endl;
}
void M::closeEvent(QCloseEvent * e)
{
std::cout << "closeEvent()" << std::endl;
hide();
QTimer::singleShot(5000, this, SLOT(show()));
e->ignore();
}
int main(int argc, char * argv[])
{
QApplication app(argc, argv);
M m;
m.setWindowModality(Qt::NonModal);
m.connect(& app, SIGNAL(aboutToQuit()),
SLOT(onAboutToQuit()));
m.show();
return app.exec();
}
# include "main.moc"
// CMakeLists.txt
cmake_minimum_required(VERSION 2.6)
project(closeeventbug)
option(QT5 "Use Qt5" OFF)
if(QT5)
find_package(Qt5Core REQUIRED)
find_package(Qt5Widgets REQUIRED)
else()
find_package(Qt4 REQUIRED)
include_directories(${QT_INCLUDES})
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_AUTOMOC ON)
add_executable(closeeventbug main.cpp)
if(QT5)
qt5_use_modules(closeeventbug Core Widgets)
else()
target_link_libraries(closeeventbug ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY})
endif()
Most full-blown desktop environments on logout attempt to close visible window. But since the test app does not exit when closed, logging out is interrupted/cancelled. If logging out is performed while the window is invisible, it quits gracefully (just like I want it to). Less feature-full desktop environments/window managers ignore the still-running application and exit. Most of them don't even warn the application about logging out, so there is neither "closeEvent()", nor "onAboutToQuit()", nor "M::~M()" in the file, to which the program output is redirected.
The detailed results (all non-Windows results are from Manjaro GNU/Linux):
Full-blown desktop environments that cancel logging out if the visible window refuses to exit, finish invisible application gracefully:
closeEvent()
onAboutToQuit()
M::~M()
{ KDE, XFCE, Mate, GNOME, Cinnamon }
All others don't cancel quit, but some of them try to warn the application.
I have no idea why onAboutToQuit() is present in the log, but M::~M() is not in this case...
closeEvent()
onAboutToQuit()
{ Windows7 }
3.
closeEvent()
{ icewm, E17 }
4.
<nothing in the log>
{ RazorQt, LxDE, LxQt, i3, budgie, fluxbox, awesome, openbox,
wmii, E16, pekWM, uwm, fvwm, xmonad, spectrwm, windowmaker,
herbstluftwm, WindowsXP }
The behaviour is exactly the same for any combination of (GCC 4.9.1 OR Clang 3.4.2) AND (Qt 4.8.6 OR Qt 5.3.1). However when I tried Qt 4.8 and Qt 5.2 on Xubuntu, the results were somewhat different: there was no blocking with Qt 5.2 in XFCE - the application finished gracefully regardless of main window visibility. But blocking was present with Qt 4.8 (just the same as in Manjaro).
I know that it is possible to handle logout properly (without blocking) because there are several applications that do that just fine. All of them have notification area icon, are closed to notification area, but don't block logging out.
Qt-based: GoldenDict, Transmission-Qt, Kopete;
GTK-based: Audacious, Pidgin.
I have examined the source code of Qt-based ones and found nothing special in handling closeEvent:
https://github.com/goldendict/goldendict/blob/master/mainwindow.cc
void MainWindow::closeEvent( QCloseEvent * ev )
{
if ( cfg.preferences.enableTrayIcon && cfg.preferences.closeToTray )
{
ev->ignore();
hide();
}
else
{
ev->accept();
qApp->quit();
}
}
https://github.com/bfleischer/transmission/blob/master/qt/mainwin.cc
void
TrMainWindow :: closeEvent( QCloseEvent * event )
{
// if they're using a tray icon, close to the tray
// instead of exiting
if( !myPrefs.getBool( Prefs :: SHOW_TRAY_ICON ) )
event->accept( );
else {
toggleWindows( false );
event->ignore( );
}
}
void
TrMainWindow :: toggleWindows( bool doShow )
{
if( !doShow )
{
hide( );
}
else
{
if ( !isVisible( ) ) show( );
if ( isMinimized( ) ) showNormal( );
//activateWindow( );
raise( );
QApplication::setActiveWindow( this );
}
}
git clone git://anongit.kde.org/kopete
void KopeteWindow::closeEvent ( QCloseEvent *e )
{
// if we are not ok to exit on close and we are not shutting down then just do what needs to be done if a
// window is closed.
KopeteApplication *app = static_cast<KopeteApplication *> ( kapp );
if ( !shouldExitOnClose() && !app->isShuttingDown() && !app->sessionSaving() ) {
// BEGIN of code borrowed from KMainWindow::closeEvent
// Save settings if auto-save is enabled, and settings have changed
if ( settingsDirty() && autoSaveSettings() )
saveAutoSaveSettings();
if ( queryClose() ) {
e->accept();
}
// END of code borrowed from KMainWindow::closeEvent
kDebug ( 14000 ) << "just closing because we have a system tray icon";
}
else
{
kDebug ( 14000 ) << "delegating to KXmlGuiWindow::closeEvent()";
KXmlGuiWindow::closeEvent ( e );
}
}
So the questions:
How to ensure that my application does not block logging out even if the main window is visible?
How to ensure that onAboutToQuit() and ~M() are called on logout in as many desktop environments/window managers as possible?
I suspect that some system signals should be listened to, but I have no idea which exactly...

QApplication has signal related to OS session actions - you can easily handle it. For more details take a look at Qt docs Session Management page

Related

How to make NSOpenPanel accept keyboard and mouse events in objective-c?

I have C++ console application getting written in XCode, and I need to open a file selector dialog. To do this I'm using Cocoa with objective-c. I'm trying to open an NSOpenPanel to use it for this purpose. I'm using the following code currently:
const char* openDialog()
{
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
[openDlg setCanChooseFiles:YES];
[openDlg setFloatingPanel:YES];
if ( [openDlg runModal] == NSOKButton )
{
for( NSURL* URL in [openDlg URLs] )
{
NSLog( #"%#", [URL path] );
return [URL.path UTF8String];
}
}
return NULL;
}
This works, however the created file selector doesnt accept mouse and keyboard events properly. It's hard to explain, but for example when I run the code from XCode when hovering above the window the mouse still behaves as if were in XCode, showing the caret symbol. When i run the application from the terminal whenever I type something it sends the input to the terminal, even though the file selector is "in front". Command clicking gives the mouse events properly to the file selector though.
I looked through NSOpenPanel's documentation and googled the problem extensively but I couldn't find an answer to this.
/*
To run in Terminal: clang openpanel.m -fobjc-arc -framework Cocoa -o openpanel && ./openpanel
*/
#import <Cocoa/Cocoa.h>
int main() {
NSApplication *application = [NSApplication sharedApplication];
[application setActivationPolicy:NSApplicationActivationPolicyAccessory];
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
[openDlg setCanChooseFiles:YES];
[openDlg setFloatingPanel:YES];
if ( [openDlg runModal] == NSModalResponseOK ) {
for( NSURL* URL in [openDlg URLs] ) {
NSLog( #"%#", [URL path] );
}
}
return 0;
}
Thanks to #Willeke.

Qt - Dialog in a DLL

In my company, we are developing with Embarcadero-C++-IDE (which is very uncomfortable). To start moving away, we port individual dialogs in a dll to Qt. My qt-dll-code Looks like this for example
extern "C" ROBOTECHPOLYLINEDIALOGSHARED_EXPORT void popupRoboTechDialog()
{
if( ! QApplication::instance() )
{
int argc = 1;
char *argv[] = {"Design polyline"};
QApplication app(argc, argv);
RoboTechPolyline dialog;
dialog.show();
app.exec();
}
else
{
RoboTechPolyline Dialog;
Dialog.exec();
}
}
Trying to start the Dialog from another thread like here Starting Qt GUI from dll (in DLLStart function) did make my Dialog unresponsive, but I don't think the question and mine relate too much.
I'm loading this Dll dynamically from the main-application and it works fine. However, when I make the Dialog Pop up a second time I get an "Access Violation at address .. in module MSVCR110D.dll" and on the third time, I get "ASSERT failure in QCoreApplication , there should be only one application object". So I always Need to Close the whole application in order to make the Dialog appear a second time, which greaty slows down work.
If I add at the bottom the line
QApplication::quit()
the Dialog appears a second time, but the Programm crashes on closing this second Dialog.
The code to load the dll is as follows
HINSTANCE lib = ::LoadLibrary(L"RoboTechPolylineDialog.dll");
if(!lib)
{
ShowMessage("Unable to load RoboTechPolylineDialog.dll");
return;
}
typedef void ( *POPUP_ROBO_TECH_DIALOG )();
POPUP_ROBO_TECH_DIALOG fp = (POPUP_ROBO_TECH_DIALOG) ::GetProcAddress(lib, "popupRoboTechDialog");
if(!fp)
{
ShowMessage("Unable to load function popupRoboTechDialog from RoboTechPolylineDialog.dll");
::FreeLibrary(lib);
return;
}
(*fp)( );
FreeLibrary(lib);
So why am I constructing more than one QApplication at a time? I can in above code replace the line
(*fp)();
with
(*fp)();
(*fp)();
and the Dialog appears twice and everything works greatly. But how can the call to ::FreeLibrary(lib) make things fail.
Can anyone help me? Any help, Workarounds, etc.. is appreciated.
This should work:
#include <QApplication>
#include <QString>
#include <QDialog>
class App {
QApplication *_app;
public:
App(int argc = 0, char** argv = NULL)
: _app(new QApplication(argc, argv))
{
}
~App() {
delete _app;
}
};
void dialog()
{
static int argc = 1;
static char *argv[] = {"Design polyline"};
static App(argc, argv);
QDialog dlg;
dlg.exec();
}
void main()
{
dialog();
dialog();
dialog();
}
Another advice: load Qt libs from as subpath since you could find dll conflict with other apps using it on the same folder (personal experience)

Using SDL2 with wxWidgets 3.0

My goal is to build a Game Boy emulator. In order to do this, I would like to embed an SDL2 surface into a wxWidgets window.
I found this tutorial: http://code.technoplaza.net/wx-sdl/part1/, but my program crashes as soon as I run it. However I suspect this was intended for SDL1.2. Part of the program is shown below.
It seems that if I call SDL_Init() and also attempt to show a wxFrame (which, in this case, is MainWindow), it shows the window for a second and then the program crashes. I commented all other calls to SDL in my program so far, so it seems the problem lies with calling Show() on a wxFrame and initing SDL2 in the same program.
So the question is: can SDL2 and wxWidgets 3 work together? If not, could you guys suggest to me good alternatives a GUI of a Game Boy emulator? Does wxWidgets have its own graphics frame like Qt does (I'd rather avoid Qt)?
Thanks very much!
#include "MainApp.h"
#include "MainWindow.h"
#include <stdexcept>
namespace GBEmu {
static void initSDL() {
//This and SDL_Quit() are the only calls to the SDL library in my code
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
throw std::runtime_error("Fatal Error: Could not init SDL");
}
}
bool MainApp::OnInit()
{
try {
//If I comment out this line, the MainWindow wxFrame shows up fine.
//If I leave both uncommented, the window shows up quickly and then
//crashes.
initSDL();
//If I comment out this line and leave initSDL() uncommented,
//the program will not crash, but just run forever.
(new MainWindow("GBEmu", {50,50}, {640,480}))->Show();
} catch(std::exception &e) {
wxLogMessage(_("Fatal Error: " + std::string(e.what())));
}
return true;
}
int MainApp::OnExit() {
SDL_Quit();
return wxApp::OnExit();
}
}
wxIMPLEMENT_APP(GBEmu::MainApp);
EDIT: Here is more information on how it crashes: It crashes with a Segfault in what seems to be the pthread_mutex_lock disassembly file. This is the output in the console with stack trace:
Starting /home/dan/Documents/devStuff/GBEmuWx-build/GBEmuWx...
The program has unexpectedly finished.
/home/dan/Documents/devStuff/GBEmuWx-build/GBEmuWx crashed
Stack trace:
Error: signal 11:
/home/dan/Documents/devStuff/GBEmuWx-build/GBEmuWx(_ZN5GBEmu7handlerEi+0x1c)[0x414805]
/lib/x86_64-linux-gnu/libc.so.6(+0x36ff0)[0x7fb88e136ff0]
/lib/x86_64-linux-gnu/libpthread.so.0(pthread_mutex_lock+0x30)[0x7fb88c12ffa0]
/usr/lib/x86_64-linux-gnu/libX11.so.6(XrmQGetResource+0x3c)[0x7fb88d1ca15c]
/usr/lib/x86_64-linux-gnu/libX11.so.6(XGetDefault+0xc2)[0x7fb88d1a7a92]
/usr/lib/x86_64-linux-gnu/libcairo.so.2(+0x94dcf)[0x7fb88af8edcf]
/usr/lib/x86_64-linux-gnu/libcairo.so.2(+0x97110)[0x7fb88af91110]
/usr/lib/x86_64-linux-gnu/libcairo.so.2(cairo_surface_get_font_options+0x87)[0x7fb88af63e07]
/usr/lib/x86_64-linux-gnu/libcairo.so.2(+0x2b61f)[0x7fb88af2561f]
/usr/lib/x86_64-linux-gnu/libcairo.so.2(+0x2ef95)[0x7fb88af28f95]
This is a screenshot of where it seems to fail (line 7):
Update: In my MainWindow class, I attach a menu bar to the window. However, it seems when I comment out the setting of the menu bar, the window will show up fine even with initing of SDL. The menu bar will show up fine if I have initSDL() commented out but not the setting of the menu bar. Here is where I set the menu bar:
MainWindow::MainWindow(const wxString &title, const wxPoint &pos, const wxSize &size)
:wxFrame(nullptr, wxIDs::MainWindow, title, pos, size){
wxMenu *fileMenu = new wxMenu;
fileMenu->Append(wxID_EXIT);
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(fileMenu, "&File");
//commenting this line out will allow the window to showup
//and not crash the program
SetMenuBar(menuBar);
}
You are experiencing an old heisenbug.
The workaround is simple: you have to initialize SDL before wxWidgets (basically, before GTK). To achieve this, you have to change
wxIMPLEMENT_APP(GBEmu::MainApp);
to
wxIMPLEMENT_APP_NO_MAIN(GBEmu::MainApp);
so that wxWidgets doesn't hijack your main().
Then you have to create main() manually. In it, initialize SDL, then call wxEntry():
int main(int argc, char** argv)
{
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
std::cerr << "Could not initialize SDL.\n";
return 1;
}
return wxEntry(argc, argv);
}
More about the bug:
I have googled around a bit and found that this bug has come up in a few places over the years. There are open reports in many bug trackers that have stack traces very similar to the one you get here (with debug symbols).
The oldest report I could find is from 2005 (!!) from the cairo bug tracker (https://bugs.freedesktop.org/show_bug.cgi?id=4373).
My best guess is that the real hiding place of this bug in either in GTK, cairo, or X. Unfortunately I do not currently have the time to look into it more in depth.

Qt C++ signals and slots did not fire

I have programmed Qt a couple of times already and I really like the signals and slots feature. But now, I guess I'm having a problem when a signal is emitted from one thread, the corresponding slot from another thread is not fired. The connection was made in the main program.
This is also my first time to use Qt for ROS which uses CMake. The signal fired by the QThread triggered their corresponding slots but the emitted signal of my class UserInput did not trigger the slot in tflistener where it supposed to. I have tried everything I can. Any help? The code is provided below.
Main.cpp
#include <QCoreApplication>
#include <QThread>
#include "userinput.h"
#include "tfcompleter.h"
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
QThread *thread1 = new QThread();
QThread *thread2 = new QThread();
UserInput *input1 = new UserInput();
TfCompleter *completer = new TfCompleter();
QObject::connect(input1, SIGNAL(togglePause2()), completer, SLOT(toggle()));
QObject::connect(thread1, SIGNAL(started()), completer, SLOT(startCounting()));
QObject::connect(thread2, SIGNAL(started()), input1, SLOT(start()));
completer->moveToThread(thread1);
input1->moveToThread(thread2);
thread1->start();
thread2->start();
app.exec();
return 0;
}
What I want to do is.. There are two seperate threads. One thread is for the user input. When the user enters [space], the thread emits a signal to toggle the boolean member field of the other thread. The other thread 's task is to just continue its process if the user wants it to run, otherwise, the user does not want it to run. I wanted to grant the user to toggle the processing anytime that he wants, that's why I decided to bring them into seperate threads.
The following codes are the tflistener and userinput.
tfcompleter.h
#ifndef TFCOMPLETER_H
#define TFCOMPLETER_H
#include <QObject>
#include <QtCore>
class TfCompleter : public QObject
{
Q_OBJECT
private:
bool isCount;
public Q_SLOTS:
void toggle();
void startCounting();
};
#endif
tflistener.cpp
#include "tfcompleter.h"
#include <iostream>
void TfCompleter::startCounting()
{
static uint i = 0;
while(true)
{
if(isCount)
std::cout << i++ << std::endl;
}
}
void TfCompleter::toggle()
{
// isCount = ~isCount;
std::cout << "isCount " << std::endl;
}
UserInput.h
#ifndef USERINPUT_H
#define USERINPUT_H
#include <QObject>
#include <QtCore>
class UserInput : public QObject
{
Q_OBJECT
public Q_SLOTS:
void start(); // Waits for the keypress from the user and emits the corresponding signal.
public:
Q_SIGNALS:
void togglePause2();
};
#endif
UserInput.cpp
#include "userinput.h"
#include <iostream>
#include <cstdio>
// Implementation of getch
#include <termios.h>
#include <unistd.h>
/* reads from keypress, doesn't echo */
int getch(void)
{
struct termios oldattr, newattr;
int ch;
tcgetattr( STDIN_FILENO, &oldattr );
newattr = oldattr;
newattr.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
ch = getchar();
tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
return ch;
}
void UserInput::start()
{
char c = 0;
while (true)
{
c = getch();
if (c == ' ')
{
Q_EMIT togglePause2();
std::cout << "SPACE" << std::endl;
}
c = 0;
}
}
Here is the CMakeLists.txt. I just placed it here also since I don't know maybe the CMake has also a factor here.
CMakeLists.txt
##############################################################################
# CMake
##############################################################################
cmake_minimum_required(VERSION 2.4.6)
##############################################################################
# Ros Initialisation
##############################################################################
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
set(CMAKE_AUTOMOC ON)
#set the default path for built executables to the "bin" directory
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#set the default path for built libraries to the "lib" directory
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
# Set the build type. Options are:
# Coverage : w/ debug symbols, w/o optimization, w/ code-coverage
# Debug : w/ debug symbols, w/o optimization
# Release : w/o debug symbols, w/ optimization
# RelWithDebInfo : w/ debug symbols, w/ optimization
# MinSizeRel : w/o debug symbols, w/ optimization, stripped binaries
#set(ROS_BUILD_TYPE Debug)
##############################################################################
# Qt Environment
##############################################################################
# Could use this, but qt-ros would need an updated deb, instead we'll move to catkin
# rosbuild_include(qt_build qt-ros)
rosbuild_find_ros_package(qt_build)
include(${qt_build_PACKAGE_PATH}/qt-ros.cmake)
rosbuild_prepare_qt4(QtCore) # Add the appropriate components to the component list here
ADD_DEFINITIONS(-DQT_NO_KEYWORDS)
##############################################################################
# Sections
##############################################################################
#file(GLOB QT_FORMS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ui/*.ui)
#file(GLOB QT_RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} resources/*.qrc)
file(GLOB_RECURSE QT_MOC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} FOLLOW_SYMLINKS include/rgbdslam_client/*.hpp)
#QT4_ADD_RESOURCES(QT_RESOURCES_CPP ${QT_RESOURCES})
#QT4_WRAP_UI(QT_FORMS_HPP ${QT_FORMS})
QT4_WRAP_CPP(QT_MOC_HPP ${QT_MOC})
##############################################################################
# Sources
##############################################################################
file(GLOB_RECURSE QT_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} FOLLOW_SYMLINKS src/*.cpp)
##############################################################################
# Binaries
##############################################################################
rosbuild_add_executable(rgbdslam_client ${QT_SOURCES} ${QT_MOC_HPP})
#rosbuild_add_executable(rgbdslam_client ${QT_SOURCES} ${QT_RESOURCES_CPP} ${QT_FORMS_HPP} ${QT_MOC_HPP})
target_link_libraries(rgbdslam_client ${QT_LIBRARIES})
It is hard to find bug from your posted code. I just want to point out one issue:
You are first making the connection and then moving the objects to new threads. Since they were created in same thread they had same Thread Affinity. So by default the connection type will be direct, which means, the slot will be executed from the same thread from which signal is emitted.
But after moving to new threads, thread affinity for both objects gets changed. Although you did not say how you could find out it is not working, I recommend to look at this matter. If you expect the slot to be executed in different thread, and tested that way, then you may not get desired output and think it is not working.
When signal and slot are meant to be executed in different thread, it is better to connect them after moving the corresponding objects to new threads. Qt::AutoConnection will by default use Qt::QueuedConnection when objects are in different thread.

Qt: some slots don't get executed in release mode

I am doing some simple program in Qt (MSVC++2008) with few checkboxes and buttons. In debug mode, everything works fine, but I can't distribute such executable, because most people don't have Visual Studio installed. When I do compile it in release mode, only 2 pushbuttons work.
I have designed my window using Qt Creator's 'drawing tool' (Qt Designer, I guess).
I do have such slots defined in my header file:
private slots:
void on_goButton_clicked(); // Works fine
void on_InputCheckBox_stateChanged(int arg1); // Don't work
void on_outputFileCheckBox_stateChanged(int arg1); // Same as above
void on_inputBrowseButton_clicked(); // Don't work, since theyre disabled
void on_outputBrowseButton_clicked(); // Same as above
void replyFinished(QNetworkReply *);
My implentation of those signals looks like this:
void MainWindow::on_InputCheckBox_stateChanged(int arg1)
{
if (arg1 == Qt::Checked)
{
ui->inputEdit->setEnabled(true);
ui->inputBrowseButton->setEnabled(true);
}
else
{
ui->inputEdit->setEnabled(false);
ui->inputBrowseButton->setEnabled(false);
}
}
void MainWindow::on_outputFileCheckBox_stateChanged(int arg1)
{
if (arg1 == Qt::Checked)
{
ui->outputEdit->setEnabled(true);
ui->outputBrowseButton->setEnabled(true);
}
else
{
ui->outputEdit->setEnabled(false);
ui->outputBrowseButton->setEnabled(false);
}
}
void MainWindow::on_inputBrowseButton_clicked()
{
QString documents = DesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
QString filename = QFileDialog::getOpenFileName(
this,
tr("Select input file"),
documents,
tr("Text files (*.txt);;All files (*)"));
if (filename.size() == 0)
return;
else
ui->inputEdit->setText(filename);
}
void MainWindow::on_outputBrowseButton_clicked()
{
QString documents = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
QString filename = QFileDialog::getOpenFileName(
this,
tr("Select output file"),
documents,
tr("Text files (*.txt);;All files (*)"));
if (filename.size() == 0)
return;
else
ui->inputEdit->setText(filename);
}
Pardon for my English and thank you in advance.
Your code looks good.
Try running "make clean" or "qmake". Your "ui_" or "moc_" files might need updating.
Are you sure the slots aren't being called - or simply not doing what you expect?
The most common reason for 'it works in debug but not release' is unitialised variables. In debug mode the variables are generally set to some null/zero value but not in release mode.
Another common problem are debug macros with side effects. Have you (or some lib) rewritten the connect() call as a macro for debugging and it's doing something different in release?
Time for some printf() debugging ?