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

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 ?

Related

osX - How to Start Another Program from my QT Application

I am trying to run iBooks from my QT application.
I tried both QProcess::execute() and QProcess::start(), but none of them worked. Here is my code:
QString program ="/Users/muhammed/Applications/iBooks.dmg";
QStringList arguments;
QProcess *q=new QProcess(this);
q->start(program,(QStringList) arguments<<"/Users/muhammed/Applications/iBooks.dmg");
Nothing happens when i use this. Thanks in advance.
You cannot run a .dmg file directly. You need to pass the .dmg file path to open command like this:
$ open application.dmg
So, your Qt code would look like this with QProcess::execute static method:
QProcess::execute( "open", { "your-dmg-file-path-here" } );
Or,
const QString dmgPathArg { "your-dmg-file-path-here" };
QProcess process {};
process.start( "open", { dmgPathArg } );
if ( !process.waitForFinished( -1 ) )
{
qDebug() << process.readAllStandardError();
return;
}
qDebug() << process.readAllStandardOutput();
Actually, there'll be some error string that you can see using the readAllStandardError() and readAllStandardOutput() methods.
Take a look at the documentation of QProcess. It has some pretty good examples to start with.
Hope that helps.

QClipboard cannot get clipboard data if copied from Notepad/Chrome

In my program, my users can copy a string of text from anywhere and paste it into my program. I use the simple QApplication::clipboard()->text(); function and everything works as expected. However, several of my users are having problems when trying to copy and paste on Windows 8.1
Here is how I access the clipboard text from my paste function:
QString clipboard = QApplication::clipboard()->text();
//check if the clipboard is empty
if(QApplication::clipboard()->text().isEmpty())
return;
//do something with clipboard
But if the text was copied from Notepad or Chrome, the text is ALWAYS empty. Windows 7 users have not had any problems. Not ALL Windows 8 users have this issue, it's only a handful but the issue it consistent. When copied from some other random places or within my program itself, the clipboard works fine.
I've tried using mimeData. When using the function formats(), only plain text is an available format, but the text is always empty.
The text being copied from Notepad/Chrome shows up fine in clipboard viewers and stuff and can be pasted elsewhere in other programs.
Copying and pasting is a very important feature in my program and its frustrating that my users can't copy and paste from Notepad or Chrome.
Any ideas? Thanks for your time. :)
EDIT: I tried using the "windows" style technique. There was no change. Here is my current, still unworking code:
QString clipboard = QApplication::clipboard()->text();
//check if the clipboard is empty
if(clipboard.isEmpty())
{
//might not actually be empty. Check using the other technique
if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL))
{
HGLOBAL hGlobal = GetClipboardData(CF_TEXT) ;//hGlobal is NULL
if (hGlobal != NULL)//This never gets called because it is NULL
{
LPTSTR lpszData = (LPTSTR) GlobalLock(hGlobal) ;
if (lpszData != NULL)
{
clipboard.fromLocal8Bit((const char *)lpszData);
GlobalUnlock(hGlobal) ;
}
}
CloseClipboard() ;
}
if(clipboard.isEmpty())
return;
}
The copied text shows up fine in a clipboard viewer, but my program can't get to it no matter what:
How come GetClipboardData() isn't picking anything up? Again, the copied text CAN be pasted in any other program I've tried... just not mine. But if copied from somewhere else, it works no problem.
EDIT: With this version, When the user copies text and text gets to clipboard, a function copies the text this time to an internal text file not directly to your program, using QFile. Another function copies the text from the internal text file to your program. By this way, i think your program wouldn't have to directly deal with text in the clipboard
clipboard.h
#ifndef CLIPBOARD_H
#define CLIPBOARD_H
#include <QDialog>
#include <QClipboard>
#include <QLabel>
#include <QHBoxLayout>
#include <QTextEdit>
#include <QPushButton>
#include <QFile>
#include <QTextStream>
class ClipBoard : public QDialog {
Q_OBJECT
public:
explicit ClipBoard(QWidget *parent = 0);
~ClipBoard();
private slots:
//the functions that will copy and paste text from the text file
void copyToTextFile();
void paste();
private:
QPushButton *button;
QTextEdit *edit;
QString textFromClipBoard;
QClipboard *clipBoardText;
QString clipboard;
};
#endif // CLIPBOARD_H
clipboard.cpp
#include "clipboard.h"
#include "ui_clipboard.h"
ClipBoard::ClipBoard(QWidget *parent) : QDialog(parent) {
button = new QPushButton("&Paste Copied Text");
edit = new QTextEdit;
/*when user copies text and text gets to clipboard, the text is copied
from clipboard to a text file then copied from the text file to the
program*/
connect(button, SIGNAL(clicked()), this, SLOT(copyToNotepad()));
connect(button, SIGNAL(clicked()), this, SLOT(paste()));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(button);
layout->addWidget(edit);
setLayout(layout);
}
/*This function copies text from the clipboard to an internal text file
created by the program*/
void ClipBoard::copyToTextFile() {
clipboard = QApplication::clipboard()->text();
QFile output("out.txt");
if (output.open(QIODevice::ReadWrite | QFile::Truncate |
QIODevice::Text)) {
QTextStream out(&output);
out << clipboard;
}
}
/*This function then copies the text from the internal text file and pastes
it to the text edit. So the program doesn't have to deal directly with the
clipboard*/
void ClipBoard::paste() {
QFile input("out.txt");
if (input.exists()) {
if (input.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&input);
clipboard = in.readAll();
}
}
edit->setText(clipboard);
}
ClipBoard::~ClipBoard() {
}
main.cpp
#include "clipboard.h"
#include <QApplication>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
ClipBoard w;
w.show();
return a.exec();
}
Look through and compare with your part of the code to see if there's something you did wrong. But as to how you claim it works on some Windows 8.1 systems and don't on others baffles me.
I had similar issue,
the solution for me is sleep.
void MainWindow::on_clipboard_change(){
QThread::msleep(1); //without this line I get allways empty clipboard
QString text = QGuiApplication::clipboard()->text();
qDebug() << "clipboard change event triggered ( " << text << " )";
}

application-name has encountered a p‌r‌o‌b‌l‌e‌m and needs to close. We are sorry for the inconvenience error when running Qt app on xp

I have this piece of code that takes a ppt document and transforms it to a series of images I want to integrate into my Qt application .
#include "stdafx.h"
#include "msword.h"
#include "ExcelToPic.h"
#include "ppttopic.h"
#include "WordToPic.h"
......
void Widget::on_transformButton_clicked()
{
//DO THE BULK OF YOUR TRANSFORMATIONS HERE
QString filepath=ui->chooseDocLineEdit->text();
QString outDir=ui->outputLocationLineEdit->text();
QFileInfo mFile(filepath);
QString filename=mFile.baseName();
QString fileExt=mFile.suffix();
//TRANSFORM THOSE INTO CSTRINGS.
QByteArray destBa1 = filepath.toLocal8Bit();
const char *filepathCString1 = destBa1.data();
CString strFilePath(filepathCString1,destBa1.size());
QByteArray destBa4 = outDir.toLocal8Bit();
const char *outDirCString1 = destBa4.data();
CString szOutDir(outDirCString1,destBa4.size());
PowerPointToPic(strFilePath, szOutDir,outDir);
QMessageBox message;
message.setText("Transformtion successful");
message.exec();
}
The PowerPointToPic function is implemented as follows:
void PowerPointToPic(CString szDocName, CString szOutDir,QString outDir)
{
CPPTApplication m_powerpointApp;
CPPTPresentations m_powerpointPres;
CPPTPresentation m_powerpointPre;
CPPTSlide slide;
CPPTSlides slides;
m_powerpointPres.ReleaseDispatch();
m_powerpointPre.ReleaseDispatch();
try{
CoInitialize(NULL);
if(!m_powerpointApp.CreateDispatch(_T("PowerPoint.Application"), NULL))
{
//AfxMessageBox(_T("创建PowerPoint服务失败!"));
return;
}
}
catch(...)
{
return;
}
m_powerpointApp.m_bAutoRelease=true;
m_powerpointApp.put_Visible(long(1));
m_powerpointApp.put_WindowState(long(2));
m_powerpointPres.AttachDispatch(m_powerpointApp.get_Presentations());
m_powerpointPres.Open(szDocName,TRUE, 1, 1);
m_powerpointPre.AttachDispatch(m_powerpointApp.get_ActivePresentation(),TRUE);
slides = m_powerpointPre.get_Slides();
int pageCount = slides.get_Count();
for( int i = 1; i <= pageCount; i++ )
{
slide = slides.Range(COleVariant((long)i));
slide.Copy();
//_T("c:\\test-%d.bmp")
//CString temp;
//QString sohokafile="sohokaImage"+QString::number(i);
QString sohokafile=outDir+"/sohokaImage"+QString::number(i)+".png";
QByteArray destBa4 = sohokafile.toLocal8Bit();
const char *outDirCString1 = destBa4.data();
CString temp(outDirCString1,destBa4.size());
//slide.Export(_T("c:\\amaImages\\slide1.png"), _T("png"),900,900 );
slide.Export(temp, _T("png"),900,900 );
}
m_powerpointPre.Close();
m_powerpointApp.Quit();
m_powerpointPre.ReleaseDispatch();
m_powerpointPres.ReleaseDispatch();
slides.ReleaseDispatch();
slide.ReleaseDispatch();
m_powerpointApp.ReleaseDispatch();
CoUninitialize();
}
When I wrap this into a test widget application to see if all works as expected the code turns the ppt document into png images on both win7 and winxp without problems. But when I integrate it within my Qt app ,It only runs on win7 without problems and throws the [application name] has encountered a problem and needs to close. We are sorry for the inconvenience error.
From my search [superuser.com] this is probably due to incompatibilities I can’t figure out .I also updated my virtual machine xp system to no avail.The application links to normal Qt 4 dlls and a few other third party libraries.
I would appreciate it if somebody helped with this .Thank you for your time.

How to quit QApplication gracefully on logout?

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

C++/SFML program crashes on exit

I just recently started playing around with SFML and I wrote this simple program.
I'm using visual studio 2010 btw.
The program compiles and runs fine when using the "start debugging" option.
but if I open the .exe file as if I was running a normal desktop application or something, it will crash on exit.
I've spent a while trying to figure it out but all I can say is that it's probably a heap corruption.
here's all the code:
#include <iostream>
#include <sstream>
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
void moveSquare();
void avgFPS();
class displayFPS : public sf::Thread{
public:
private:
virtual void Run();
};
int checkEvent(sf::RenderWindow &win){
sf::Event Event;
while(win.GetEvent(Event)){
// Window closed
if (Event.Type == sf::Event::Closed){
return 0;
}
// Escape key pressed
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape)){
return 0;
}
}
return -1;
}
sf::RenderWindow win(sf::VideoMode(800,600,32),"Mario Clone Test");
sf::Image img1(200,200,sf::Color(255,255,0));
sf::Sprite sprite1;
std::stringstream ss;
sf::String fps;
bool threadFPS;
int main(){
sprite1.SetImage(img1);
sprite1.SetCenter(-300,-300);
win.SetFramerateLimit(30);
moveSquare();
win.Close();
sf::Sleep(0.5);
return 0;
}
void moveSquare(){
displayFPS dispFPS;
threadFPS = true;
dispFPS.Launch();
fps.SetSize(20);
while(1){
if(!win.IsOpened() || checkEvent(win) == 0){
threadFPS = false;
dispFPS.Wait();
break;
}
win.Draw(sprite1);
win.Draw(fps);
win.Display();
win.Clear();
if(win.GetInput().IsKeyDown(sf::Key::Left)){
sprite1.Move(-100*win.GetFrameTime(),0);
}
if(win.GetInput().IsKeyDown(sf::Key::Right)){
sprite1.Move(100*win.GetFrameTime(),0);
}
if(win.GetInput().IsKeyDown(sf::Key::Up)){
sprite1.Move(0,-100*win.GetFrameTime());
}
if(win.GetInput().IsKeyDown(sf::Key::Down)){
sprite1.Move(0,100*win.GetFrameTime());
}
}
return;
}
void avgFPS(){
double frames=0.0,avg=0.0;
int j=0;
while(threadFPS){
if(win.GetFrameTime() != 0){
j++;
frames = frames+(1.0/win.GetFrameTime());
avg = frames/j;
}
ss << "avg FPS: " << avg << std::endl << "Arrow Keys to Move" << std::endl << "Press ESC to Exit";
fps.SetText(ss.str());
ss.str("");
}
return;
}
void displayFPS::Run(){
avgFPS();
}
I've had the same issue.
You need to recompile SFML when using VS2010.
Few things for you to try:
If you are suspecting heap corruption, run gflags (found in Debugging Tools for Windows) and enable page heap. Some instructions on how it works can be found here. Basically when page heap is enabled, your app will crash at the point of the memory error, not sometime later.
You said you get a crash on exit. When that happens, I'm assuming windows throws up a crash dialog box. Open one of those links that say something like "see what information is being uploaded". Somewhere among those files will be a minidump of your process. You can load that up in visual studio (open file and hit F5). Sometimes visual studio is glitchy, so another, more reliable but more difficult but more difficult to use alternative is WinDbg, also part of Debugging Tools for Windows.
SFML has multiple versions of their .lib's for release and debug.
Examples:
sfml-audio.lib
sfml-audio-d.lib
sfml-audio-s.lib
sfml-audio-s-d.lib
Make sure you are using the lib without the -d in it.
Also, when you put the .dll's with your exe (assuming you are using the dynamic libraries) make sure to use the normal versions not the debug (-d) versions.
Finally, when you are building the project make sure you build for release and not debug.