Crash with QItemSelectionModel::selectedIndexes() - c++

I've been searching all around for a solution to this problem and I'm starting to believe this can be a bug in the Qt function itself.
The problem is that after you call QItemSelectionModel::selectedIndexes() the program will crash when the program tries to destruct the QModelIndexList that this function returns. Before the crash, you get the following debug message:
Debug Assertion Failed!
(…)
File:
f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c
Line:1419
Expression:
_pFirstBlock == pHead
(…)
Here is the simplest code that will cause the problem, so you can test it by yourself:
#include <QApplication>
#include <QStringList>
#include <QStringListModel>
#include <QItemSelectionModel>
#include <QModelIndex>
#include <QModelIndexList>
#include <QListView>
#include <QItemSelectionModel>
void doSomethingWithSelection(QItemSelectionModel* selectionmodel);
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QStringList list;
list.push_back("1");
list.push_back("2");
list.push_back("3");
list.push_back("4");
QStringListModel model(list);
QListView view;
view.setModel(&model);
view.setSelectionMode(QAbstractItemView::ExtendedSelection);
QItemSelectionModel *selectionmodel = view.selectionModel();
QModelIndex first = model.index(0);
QModelIndex last = model.index(2);
QItemSelection selection(first, last);
selectionmodel->select(selection,QItemSelectionModel::Select);
doSomethingWithSelection(selectionmodel);
view.show();
return a.exec();
}
void doSomethingWithSelection(QItemSelectionModel* selectionmodel)
{
QModelIndexList indexlist = selectionmodel->selectedIndexes();
// this is what causes the error. I put this inside a function
// so the error will happen when exiting the function,
// when the program try to destroy the list nodes.
}

I have the exact same problem only that I am using selected rows instead of selected indexes. I narrowed it down to function exit when the internal QList in QModelIndexList tries to delete the indexes from the heap. Not sure how to fix it but I read this interesting post here and came up with this function:
QModelIndexList Class::getViewSelection(QAbstractItemView *view , int columnNumber) const
{
QModelIndexList list;
for (int row = 0; row < view->model()->rowCount(view->rootIndex()); ++row)
{
QModelIndex index = view->model()->index(row, columnNumber, view->rootIndex());
if (view->selectionModel()->isSelected(index))
list.push_back(index);
}
return list;
}
I wrote this function to get selected rows so the column parameter is the column you want the index for.

I had the same problem with QTreeView and accessing selectedIndexes() or anything in selectionModel().
It was fixed when I used the correct /MD compiler switch with the correct Qt libraries.
To fix the crash:
compile your code with /MDd and link with debug Qt libs (example Qt5Cored.lib
compile your code with /MD and link with release Qt libs (example Qt5Core.lib)

I managed to solve the problem, but right now I don’t understande why this works, yet: (I'm writing this as an answer hoping that it can help someone with the same problem)
In my Qt project, I was using a Kit with Microsoft Windows SDK for Windows 7 (7.0.7600.16385.40715) (x86) as compiler. When I changed the compiler to Microsoft Visual C++ Compiler 10.0 (x86) this code worked correctly.
As I said, I don't know why this works and if someone can explain this to me I will be happy to hear. I don't know even why Windows SDK is listed as a compiler.. it is not, is it?

Related

Creation of QtChart object creates EXC_BAD_ACCESS error upon runtime

I currently trying to move some code from Python to C++ for practice reasons and tried to create a line chart with the QtCharts library.
I installed the Qt library with the Qt open source installer provided by Qt on their website and finally managed to include the library in the project on Clion with the following code:
CMakelist.txt
cmake_minimum_required(VERSION 3.12)
project(Uebung1)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Qt
# Set this to your Qt installation
set(CMAKE_PREFIX_PATH /Users/DaniBook/Qt/5.11.2/clang_64)
set(RESOURCE_FOLDER res)
set(RESOURCE_FILES ${RESOURCE_FOLDER}/resources.qrc)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
find_package(Qt5Charts CONFIG REQUIRED)
set(PROJECT_SOURCE_DIR src/)
include_directories(${PROJECT_SOURCE_DIR})
add_executable(Uebung1 src/main.cpp src/tools.h src/tools.cpp)
target_link_libraries(Uebung1 Qt5::Charts)
So far so good I was able to then use the library in my code which basically consists of a two functions. One that reads data from a file and converts it to a vector of integers and one that takes this vector and attempts to create a Qt line chart.
tools.cpp
#include "tools.h"
#include <vector>
#include <string>
#include <map>
#include <iostream>
#include <QtCharts>
#include <fstream>
using namespace std;
void GC_skew(vector<long> &gc_data, string &genome_file) {
ifstream gfile(genome_file);
string line;
long g_sum = 0, c_sum = 0;
if(gfile.is_open()) {
//reading file line by line
while(getline(gfile, line)) {
//iterating over string characters to count G and C
for(auto &character : line) {
switch(character) {
case 'G' :
g_sum++;
break;
case 'C' :
c_sum++;
break;
default :
continue;
}
//appending skew to vector
gc_data.push_back(g_sum - c_sum);
}
}
}
else {
cout << "Unable to open file!" << endl;
}
}
void skew_chart(vector<long> &gc_data) {
auto *series = new QLineSeries();//creating new series object
auto *chart = new QChart(); //creating new chart object
auto *chartview = new QChartView(chart); //creating chartview object
QMainWindow window; //window object for display
long pos = 0;
//iterating over the vector and appending data to series
for(auto it : gc_data) {
series->append(pos, it);
pos++;
}
//adding series to chart and viewing chart
chart->addSeries(series);
chartview->setRenderHint(QPainter::Antialiasing);
window.setCentralWidget(chartview);
window.show();
}
main.cpp
#include <iostream>
#include "tools.h"
#include <vector>
#include <map>
using namespace std;
int main() {
vector<long> gc_data = {};
string genome_file = "<path_to_file>";
GC_skew(gc_data, genome_file);
skew_chart(gc_data);
}
The code compiles without an error but when running it terminates with exit code 11 (whatever that means). However, upon debugging I figured there is a problem with the creation of a new QChart object where I keep getting the following exception as stated by the debugger:
Exception = error: use of undeclared identifier 'Exception' //occurs somewhere before the one below but does not effect the application
Exception = EXC_BAD_ACCESS (code=1, address=0x0) //causes the application to crash
Debug information
The way of initialization above is exactly the way given by Qt (https://doc.qt.io/qt-5/qtcharts-linechart-example.html) additional research in their resources did not lead to any solution. Does anybody of you might know what to do?
P.S.: by stepping through the lines one by one I discovered a jump upon initialization into a header which seems to define an exception which is raised at whatever event
qtflags.h (part of Qt lib)
Q_DECL_CONSTEXPR inline QFlags(Zero = Q_NULLPTR) Q_DECL_NOTHROW : i(0) {}
however the stack trace of the debugger indicates a successful object creation.
stack trace of debugger
The Qt version is 5.11.2
Compiler version Apple LLVM version 10.0.0 (clang-1000.11.45.2)
Thanks in advance if anybody can make sense of this
You dont have any QApplication instance.
Here's a quote from Qt Docs:
The QApplication class manages the GUI application's control flow and
main settings.
QApplication contains the main event loop, where all events from the
window system and other sources are processed and dispatched. It also
handles the application's initialization, finalization, and provides
session management. In addition, QApplication handles most of the
system-wide and application-wide settings.
For any GUI application using Qt, there is precisely one QApplication
object, no matter whether the application has 0, 1, 2 or more windows
at any given time. For non-GUI Qt applications, use QCoreApplication
instead, as it does not depend on the QtGui library.
The QApplication object is accessible through the instance() function
that returns a pointer equivalent to the global qApp pointer.
So, the line
QApplication app(argc, argv);
creates an instance of the QApplication class.
In the end you need to call app.exec() which enters the main event loop and waits until exit() is called, then returns the value that was set to exit() (which is 0 if exit() is called via quit()).
It is necessary to call this function to start event handling. The main event loop receives events from the window system and dispatches these to the application widgets.

How to set 3-key sequence shortcut with two key modifiers in Qt?

I have been trying to set a shortcut as Ctrl + Shift +C.
I have tried the following ways:
QAction *generalControlAction = new QAction(this);
generalControlAction->setShortcut(QKeySequence("Ctrl+Shift+c"));
connect(generalControlAction, &QAction::triggered, this, &iBexWorkstation::onGeneralConfiguration);
QShortcut *generalControlShortcut = new QShortcut(QKeySequence("Ctrl+Shift+C"), this);
connect(generalControlShortcut, &QShortcut::activated, this, &iBexWorkstation::onGeneralConfiguration);
They didn't work. Nothing is triggered when I press Ctrl + Shift +C.
Is it impossible to set a shortcut with two modifiers in Qt?
I wrote a minimal, complete sample. It worked in my case how you described it. May be, I added something which you didn't on your side. (That's why "minimal, complete, verifiable samples" are preferred.)
// standard C++ header:
#include <iostream>
// Qt header:
#include <QAction>
#include <QApplication>
#include <QLabel>
#include <QMainWindow>
using namespace std;
int main(int argc, char **argv)
{
cout << QT_VERSION_STR << endl;
// main application
#undef qApp // undef macro qApp out of the way
QApplication qApp(argc, argv);
// the short cut
const char *shortCut = "Ctrl+Shift+Q";
// setup GUI
QMainWindow qWin;
QAction qCmdCtrlShiftQ(&qWin);
qCmdCtrlShiftQ.setShortcut(QKeySequence(shortCut));
qWin.addAction(&qCmdCtrlShiftQ); // DON'T FORGET THIS.
QLabel qLbl(
QString::fromLatin1("Please, press ")
+ QString::fromLatin1(shortCut));
qLbl.setAlignment(Qt::AlignCenter);
qWin.setCentralWidget(&qLbl);
qWin.show();
// add signal handlers
QObject::connect(&qCmdCtrlShiftQ, &QAction::triggered,
[&qLbl, shortCut](bool) {
qLbl.setText(
QString::fromLatin1(shortCut)
+ QString::fromLatin1(" pressed."));
});
// run application
return qApp.exec();
}
I suspect that you didn't call QWidget::addAction(). If I comment it out it does not work anymore in my program also.
Compiled with VS2013 and Qt 5.6 on Windows 10 (64 bit):
This snapshot has been made after pressing Ctrl+Shift+Q.
Note:
I realized afterwards that the actual question was about "Ctrl+Shift+C". To be sure, I checked it. The above sample code works with "Ctrl+Shift+C" as well.
generalControlAction->setShortcut(QKeySequence(Ctrl+Shift+c));
just change above mention statement in your code to
generalControlAction->setShortcut((Ctrl+Shift+C));
this should work fine. "C" should be capital later.
please refer key sequence from below given link
http://doc.qt.io/qt-5/qkeysequence.html

How to retrieve a QWidget from a list of opened windows

In some part of my project, I want to get the reference of a window, from a list of opened windows.
So, i'm doing this way:
QWidget* WindowUtil::mainWindow() {
QWidget* main_window = nullptr;
for(QWidget *window: QApplication::allWidgets()){
if(QString(window>metaObject()->className()).contains("Home")){
main_window = window;
break;
}
}
return main_window;
}
WindowUtil is class of my project and mainWindow() is a static method.
However, this solution doesn't work. The compiler says:
error: incomplete type 'QApplication' used in nested name specifier
for(QWidget *window : QApplication::allWidgets()){
^
And I'm stuck here.
Even though the answer has been already posted as a comment, this error should mean (most of the time) that you have not included right header file, in this case: <QApplication> and your app cannot find the declarations for what it wants.
#include <QApplication>
instruction in the file that raises an error should be an efficient solution for your problem :)

Qt and dead keys in a custom widget

Issue
I'm unable to make dead keys work in my Qt program, while on the same system Qt applications (konsole or kmail for instance) are correctly processing them.
How to reproduce
testcase.pro
TEMPLATE = app
TARGET = testcase
INCLUDEPATH += .
QT += core widgets gui
HEADERS += testcase.hpp
SOURCES += testcase.cpp
testcase.hpp
#include <QWidget>
class TestWindow: public QWidget
{
Q_OBJECT
public:
TestWindow(QWidget* parent=0, Qt::WindowFlags flags=0);
void keyPressEvent(QKeyEvent* event);
};
testcase.cpp
#include <QApplication>
#include <QDebug>
#include <QWidget>
#include <QKeyEvent>
#include "testcase.hpp"
TestWindow::TestWindow(QWidget* parent, Qt::WindowFlags flags)
: QWidget(parent, flags)
{
setAttribute(Qt::WA_KeyCompression);
}
void TestWindow::keyPressEvent(QKeyEvent* event)
{
qDebug() << event;
}
int main(int argc, char** argv)
{
QApplication app(argc, argv);
TestWindow mainWin;
mainWin.show();
return app.exec();
}
Compile the above program (qmake; make), launch it. Dead keys give for instance:
QKeyEvent(KeyPress, 1001252, 0, ""^"", false, 1)
QKeyEvent(KeyPress, 45, 0, ""e"", false, 1)
I was expecting
QKeyEvent(KeyPress, 234, 0, ""ê"", false, 1)
This would also be acceptable:
QKeyEvent(KeyPress, 1001252, 0, ""^"", false, 1)
QKeyEvent(KeyPress, 234, 0, ""ê"", false, 1)
What I've tried
I'm using a Ubuntu 14.10 system with locale fr_FR.UTF-8
I've tried
with Qt 5.3.0 and Qt 4.8.6 as provided on the system.
unseting XMODIFIERS (the default value is #im=ibus is being reported an issue by some)
changing the locale (again, google find reports were the part after the dot is an issue, I've tried the 4 variants UTF-8, utf-8, UTF8 and utf8)
with and without the setAttribute(Qt::WA_KeyCompression); in the constructor.
None changed my observable behavior.
Searching the web show mainly (only?) system related issues. As written above, I've tried the proposed solution, that doesn't solve my problem and the fact that other Qt applications I've tried are able to process the dead key makes me think I miss something in my code, especially that with a slightly more complex example, I'm able to use dead keys with Qt provided widgets (for instance a QLineEdit).
This is a partial answer, but as nobody answered that could be useful for someone later.
Dead keys are handled by input methods which are also handling the compose key and the way Chinese characters and others may be entered.
The widget must signify that it handles input method:
setAttribute(Qt::WA_InputMethodEnabled, true);
Then it has to overwrite two virtual members:
void inputMethodEvent(QInputMethodEvent*);
QVariant inputMethodQuery(Qt::InputMethodQuery) const;
To handle the dead keys and compose, it seems to be enough to have
void TestWindow::inputMethodEvent(QInputMethodEvent* event)
{
if (!event->commitString().isEmpty()) {
QKeyEvent keyEvent(QEvent::KeyPress, 0, Qt::NoModifier,
event->commitString());
keyPressEvent(&keyEvent);
}
event->accept();
}
QVariant TestWindow::inputMethodQuery(Qt::InputMethodQuery) const
{
return QVariant();
}
but that's were my answer is incomplete:
I'm not sure it is really enough even for that
I'm sure it is not enough for more complex writing system and I lack the prerequisite to understand the documentation I've found.

Qt: MainWindow->show() crashes program on call

I've been working on this program using Qt in c++ and so far so good. However I then needed to get this program moved to another machine. I have subversion, so I committed every file in the project folder and checked it out on the new machine. After jumping through some hoops to get it to successfully build and running, I get this error:
ASSERT: "dst.depth() == 32" in file qgl.cpp,.
invalid parameter passed to c runtime function qt
I tried stepping through the program to find the point where it crashes and found that it was after everything had been initialized and show() is called for the class that inherits the QMainWindow class. The c->showView() line calls QMianWindow->show().
----------main.cpp------------
#include <QApplication>
#include "ModelI.h"
#include "ControllerI.h"
#include "Model.h"
#include "Controller.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ModelI *m = new Model();
ControllerI *c = new Controller(m);
c->showView(); <- ERROR HERE
return a.exec();
}
The confusing part of the problem is that the program works perfectly fine on my machine when show() is called. I don't know what could be different between the two machines to make the program behave so differently. Both use the same version of Qt (SDK 2010.05). Both are developing with Eclipse. The only difference I can find is that my compiler is MinGW 4.5.0 and the other machine's is MinGW 4.5.2.
EDIT 1:
This is what Controller::showView() looks like.
void Controller::showView()
{
mView->show();
}
And this is how mView is initialized.
mView = new View(mModel, this);