QSqlTableModel: Where can I get whether a row is marked as removed - qt

If I call removeRows on records which were read from the database a ! will be displayed in the first column of the tableView.
The only thing which I would like to achieve is that this row will not be displayed in the view. I tried it with QSortFilterProxyModel but I don't know where I can get the flag which is used to display the ! in the first column. Is there a way to set a filter in QSortFilterProxyModel that it only contains the rows which don't have this flag?
From where does the view take the information, that the removed row is marked with a "!" ? This information might be hidden somewhere in the model, but I cannot find out where.
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
m_ui(new Ui::MainWindow),
m_model(new QSqlTableModel(this)),
m_proxyModel(new QSortFilterProxyModel(this))
{
m_ui->setupUi(this);
m_model->setTable("test");
m_model->setEditStrategy(QSqlTableModel::OnManualSubmit);
m_model->select();
m_proxyModel->setSourceModel(m_model);
m_ui->tableView->setModel(m_proxyModel);
qDebug() << "Select : Row count:" << m_model->rowCount();
connect(m_ui->tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &MainWindow::on_selectionChanged);
}
MainWindow::~MainWindow()
{
delete m_ui;
}
void MainWindow::on_pushButtonNewRecord_clicked()
{
qDebug() << "New Record";
m_record = m_model->record();
m_record.setValue("firstname", "john");
m_record.setValue("lastname", "doe");
m_record.setValue("email", "john.doe#email.com");
m_model->insertRecord(-1, m_record);
qDebug() << "New Record : Row count:" << m_model->rowCount();
}
void MainWindow::on_pushButtonRemoveRow_clicked()
{
qDebug() << "Remove Row";
if (m_row >= 0) {
m_proxyModel->removeRow(m_row);
qDebug() << "Remove Record: Row count:" << m_model->rowCount();
}
for (int i = 0; i < m_model->rowCount(); i++) {
qDebug() << "\n";
qDebug() << "Remove Row: index :" << m_model->index(i, 0);
qDebug() << "Remove Row: isValid:" << m_model->index(i, 0).isValid();
qDebug() << "Remove Row: isDirty:" << m_model->isDirty(m_model->index(i, 0));
qDebug() << "Remove Row: flags :" << m_model->index(i, 0).flags();
qDebug() << "Remove Row: data :" << m_model->index(i, 0).data(Qt::DisplayRole);
qDebug() << "Remove Row: heaader:" << m_model->headerData(i, Qt::Vertical);
QVariant verticalHeader = m_model->headerData(i, Qt::Vertical);
if (verticalHeader == "!") {
qDebug() << "Deleted";
}
//qDebug() << m_model->record(i);
}
}
void MainWindow::on_pushButtonSubmit_clicked()
{
qDebug() << "Submit";
m_model->submitAll();
m_model->select();
}
void MainWindow::on_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
Q_UNUSED(deselected)
if (!selected.isEmpty()) {
m_row = selected.indexes().first().row();
}
}

You have to implement a QSortFilterProxyModel that filters the rows that are Dirty and whose vertical header text is "!", You must also call the invalidate() method to force the application of the filter.
dirtyfilterproxymodel.h
#ifndef DIRTYFILTERPROXYMODEL_H
#define DIRTYFILTERPROXYMODEL_H
#include <QSortFilterProxyModel>
#include <QSqlTableModel>
class DirtyFilterProxyModel : public QSortFilterProxyModel
{
public:
using QSortFilterProxyModel::QSortFilterProxyModel;
protected:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
if(QSqlTableModel *source_model = qobject_cast<QSqlTableModel *>(sourceModel())){
QModelIndex ix = source_model->index(source_row, 0, source_parent);
QString row_header_item = source_model->headerData(source_row, Qt::Vertical, Qt::DisplayRole).toString();
return !(source_model->isDirty(ix) && row_header_item == QLatin1String("!"));
}
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
};
#endif // DIRTYFILTERPROXYMODEL_H
mainwindow.h
// ...
class DirtyFilterProxyModel;
// ...
class MainWindow : public QMainWindow
{
// ...
private:
Ui::MainWindow *m_ui;
DirtyFilterProxyModel *m_proxyModel;
// ...
mainwindow.cpp
#include "dirtyfilterproxymodel.h"
// ...
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
m_ui(new Ui::MainWindow),
m_model(new QSqlTableModel(this)),
m_proxyModel(new DirtyFilterProxyModel(this))
{
// ...
}
void MainWindow::on_pushButtonNewRecord_clicked()
{
// ...
m_model->insertRecord(-1, m_record);
m_proxyModel->invalidate();
}
// ...
void MainWindow::on_pushButtonRemoveRow_clicked()
{ if (m_row >= 0) {
m_proxyModel->removeRow(m_row);
m_proxyModel->invalidate();
}
}

Related

Qt QCompleter do not pop out

Problem description
  I want to be able to recognize the corresponding Chinese person name and complete the prompt by entering a short Chinese phonetic alphabet.
  For example, I have a map (("lvbu", "吕布"), ("lvbuwei", "吕不韦")) , then enter "lv" or "bu",The completer should pop up "吕布" and "吕不韦", but it seems that the stringlist must contain the content currently being entered to complete the prompt. The completer cannot recognize the mapping relationship.
  How can I solve it? I can hardly find a solution on the Internet because it involves Chinese.
My code
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "Pinyin2Hanzi/myPinyin.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QString N = "吕布 吕不韦 南宫问天";
QStringList Names = N.split(" ");
// qDebug() << Names;
ui->comboBox->addItem("");
ui->comboBox->addItems(Names);
ui->comboBox->lineEdit()->setClearButtonEnabled(true);
CreateCompleter(Names, ui->comboBox->lineEdit());
ui->comboBox->setMaxCount(ui->comboBox->count()); //这行代码可以防止按回车键自动往combobox里addItem
}
MainWindow::~MainWindow()
{
delete ui;
}
std::map<std::string, std::vector<QString>> pinyin2NameMap; // This is a private variable
// 把所有人名按照拼音分类并存入map中
void MainWindow::PreparePinyinData(const QStringList &names)
{
for (auto & name : names)
{
QString outFristPy,outFullPy;
getComPingyinForStr(name, outFristPy, outFullPy);
// QString pinyin = GetPinyin(name);
QString pinyin = outFullPy;
// qDebug() <<"FristPy:" << outFristPy << "FullPy:" << outFullPy;
// qDebug() <<"pinyin:" << pinyin;
// QString fist, last;
// myNameSplit(name, last, fist); // 自动切分 [姓、名]
// last = getNamePingyin(last, true); // 获取 [姓] 的拼音
// fist = getNamePingyin(fist, false);// 获取 [名] 的拼音
// qDebug() << name + " : " + last + " " + fist << endl;
pinyin2NameMap[pinyin.toStdString()].push_back(name);
}
}
// 根据输入的拼音进行匹配并获取提示列表
QStringList MainWindow::GetMatchByPinyin(const QString &pinyin)
{
QStringList result;
if("" == pinyin.trimmed()){
return QStringList();
}
for (const auto & iter : pinyin2NameMap){
if (iter.first.find(pinyin.toStdString()) != std::string::npos){
auto vec = iter.second;
for(const auto & name : vec){
result.append(name);
}
}
}
return result;
}
// 创建QCompleter并设置自动补全模型
void MainWindow::CreateCompleter(const QStringList &names, QLineEdit *lineEdit)
{
PreparePinyinData(names);
QStringListModel *model = new QStringListModel(names);
QCompleter *completer = new QCompleter(model, lineEdit);
completer->setCaseSensitivity(Qt::CaseInsensitive);
completer->setFilterMode(Qt::MatchContains);
completer->setCompletionMode(QCompleter::PopupCompletion);
lineEdit->setCompleter(completer);
connect(lineEdit, &QLineEdit::textEdited, [this,completer,lineEdit, model](const QString &text)
{
QStringList matchList = GetMatchByPinyin(text);
qDebug() << "listmodel:" << matchList;
// QString N = "lv不bu 可lvbuwei nan够gongwentian";
// QStringList matchList = N.split(" ");
model->setStringList(matchList);
completer->setModel(model);
completer->complete();
});
}

Why do I get false when I try to insert a record to a QSqlTableModel in QT?

I'm creating a QSqlRecord object and then I set the values to that QSqlRecord object. But even if I insert the QSqlRecord object to the QSqlTableModel object, the function of inserting records, returns false.
I have this C++ code and it create a QSqlRecord object and set the values. It setting the values in the correct indexed order as how the table was created.
/* Insert data */
int column_index = 0; /* Index 0 is the ID column */
QSqlRecord record;
qDebug() << CALIBRATION_COLUMNS.at(column_index).first;
record.setValue(CALIBRATION_COLUMNS.at(column_index++).first, 1); /* ID */
qDebug() << CALIBRATION_COLUMNS.at(column_index).first;
record.setValue(CALIBRATION_COLUMNS.at(column_index++).first, calibration_id);
qDebug() << CALIBRATION_COLUMNS.at(column_index).first;
record.setValue(CALIBRATION_COLUMNS.at(column_index++).first, calibration_comment);
qDebug() << CALIBRATION_COLUMNS.at(column_index).first;
record.setValue(CALIBRATION_COLUMNS.at(column_index++).first, calibration_date_time);
for(int i = 0; i < 12; i++){
record.setValue(CALIBRATION_COLUMNS.at(column_index++).first, min_adc[i]);
record.setValue(CALIBRATION_COLUMNS.at(column_index++).first, max_adc[i]);
record.setValue(CALIBRATION_COLUMNS.at(column_index++).first, bias_adc[i]);
}
for(int i = 0; i < 5; i++){
record.setValue(CALIBRATION_COLUMNS.at(column_index++).first, min_dadc[i]);
record.setValue(CALIBRATION_COLUMNS.at(column_index++).first, max_dadc[i]);
record.setValue(CALIBRATION_COLUMNS.at(column_index++).first, bias_dadc[i]);
}
for(int i = 0; i < 2; i++)
record.setValue(CALIBRATION_COLUMNS.at(column_index++).first, pulses_per_revolution_encoder[i]);
/* -1 means append record */
qDebug() << calibration_model->insertRecord(-1, record);
qDebug() << calibration_model->lastError().text();
qDebug() << "Submit:";
if(!calibration_model->submitAll()){
qDebug() << calibration_model->lastError().text();
return DATABASE_STATUS_COULD_NOT_INSERT_ROW;
}
return DATABASE_STATUS_OK;
But even if I insert the record, this function calibration_model->insertRecord(-1, record); returns false but the calibration_model->submitAll() returns true.
Output:
"ID"
"calibration_id"
"calibration_comment"
"calibration_date_time"
false
"No Fields to update"
Submit:
So tell me. What I'm I doing wrong here?
I'm getting the error No Fields to update, but what does that mean? I have an empty table and I just want to append with one row.
Not sure why you're getting that error. I have a small example for QSqlTableModel. Let me put it here. Maybe you could compare with your code.
main.cpp
#include <QApplication>
#include "mysqltablemodel.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("mydb");
if(!db.open()) {
qDebug() << db.lastError().text();
return 0;
}
QSqlQuery query(db);
if(!query.exec("DROP TABLE IF EXISTS mytable")) {
qDebug() << "create table error: " << query.lastError().text();
return 0;
}
if(!query.exec("CREATE TABLE IF NOT EXISTS mytable \
(id integer primary key autoincrement, name varchar(15), salary integer)")) {
qDebug() << "create table error: " << query.lastError().text();
return 0;
}
MySqlTableModel *model = new MySqlTableModel(0, db);
model->setTable("mytable");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
QSqlRecord rec = model->record();
rec.setValue(1, "peter");
rec.setValue(2, 100);
qDebug() << model->insertRecord(-1, rec);
rec.setValue(1, "luke");
rec.setValue(2, 200);
qDebug() << model->insertRecord(-1, rec);
if(model->submitAll()) {
model->database().commit();
} else {
model->database().rollback();
qDebug() << "database error: " << model->lastError().text();
}
query.exec("SELECT name, salary FROM mytable");
while (query.next()){
QString name = query.value(0).toString();
int salary = query.value(1).toInt();
qDebug() << name << salary;
}
return app.exec();
}
mysqltablemodel.h
#ifndef MYSQLTABLEMODEL_H
#define MYSQLTABLEMODEL_H
#include <QSqlTableModel>
#include <QSqlRecord>
#include <QSqlError>
#include <QSqlQuery>
#include <QDebug>
class MySqlTableModel : public QSqlTableModel
{
Q_OBJECT
public:
MySqlTableModel(QObject *parent = 0, QSqlDatabase db = QSqlDatabase());
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole ) const;
protected:
QHash<int, QByteArray> roleNames() const;
private:
QHash<int, QByteArray> roles;
};
#endif // MYSQLTABLEMODEL_H
mysqltablemodel.cpp
#include "mysqltablemodel.h"
MySqlTableModel::MySqlTableModel(QObject *parent, QSqlDatabase db): QSqlTableModel(parent, db) {}
QVariant MySqlTableModel::data ( const QModelIndex & index, int role ) const
{
if(index.row() >= rowCount()) {
return QString("");
}
if(role < Qt::UserRole) {
return QSqlQueryModel::data(index, role);
}
else {
return QSqlQueryModel::data(this->index(index.row(), role - Qt::UserRole), Qt::DisplayRole);
}
}
QHash<int, QByteArray> MySqlTableModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[Qt::UserRole + 1] = "name";
roles[Qt::UserRole + 2] = "salary";
return roles;
}

Different color for different word in QML TextArea without RichText

I am trying to make a code editor and want to change color of keywords in TextArea after user types a keyword. I read that textFormat:Text.StyledText could change color without changing the whole text to Html but adding tags to the text is not changing the color. Here I used bold tag for code
Code -
TextArea{
Layout.alignment: Qt.AlignTop
id:ta
selectByMouse: true
selectByKeyboard: true
Layout.fillWidth:true
Layout.fillHeight: true
font.pointSize: 12
textMargin: 16
font.family:"courier new"
persistentSelection: true
textFormat: Text.StyledText
onActiveFocusChanged: {
menu_trig=0
}
onTextChanged: {
// check text
console.log(ta.text.slice(0,ta.text.length-3))
if(ta.text.slice(ta.text.length-3,ta.text.length)=="def")
{
ta_text.text=ta.text.substring(0,ta.text.length-3)+"<b>def</b>"}
}
Keys.onPressed: {
if(codeChange==0)
{codeChange=1
mainWindow.title=title.toString()+" *"}
}
Component.onCompleted: forceActiveFocus()
// color:"orange"}
You have to use a QSyntaxHighlighter and because it seems to me you are trying to make it an editor for python I have implemented based on this post.
syntaxhighlighter.h
#ifndef SYNTAXHIGHLIGHTER_H
#define SYNTAXHIGHLIGHTER_H
#include <QRegularExpression>
#include <QSyntaxHighlighter>
class QQuickTextDocument;
class HighlightingRule
{
public:
HighlightingRule(const QString &patternStr, int n, const QTextCharFormat &matchingFormat);
QString originalRuleStr;
QRegularExpression pattern;
int nth;
QTextCharFormat format;
};
class PythonSyntaxHighlighter : public QSyntaxHighlighter
{
Q_OBJECT
public:
PythonSyntaxHighlighter(QTextDocument *parent);
const QTextCharFormat getTextCharFormat(const QString &colorName, const QString &style = QString());
void initializeRules();
bool matchMultiline(const QString &text, const QRegularExpression &delimiter, const int inState, const QTextCharFormat &style);
protected:
void highlightBlock(const QString &text);
private:
QStringList keywords;
QStringList operators;
QStringList braces;
QHash<QString, QTextCharFormat> basicStyles;
QList<HighlightingRule> rules;
QRegularExpression triSingleQuote;
QRegularExpression triDoubleQuote;
};
class SyntaxHighlighterHelper: public QObject
{
Q_OBJECT
Q_PROPERTY(QQuickTextDocument *quickdocument READ quickdocument WRITE setQuickdocument NOTIFY quickdocumentChanged)
public:
SyntaxHighlighterHelper(QObject *parent=nullptr):
QObject(parent),
m_quickdocument(nullptr)
{}
QQuickTextDocument *quickdocument() const;
void setQuickdocument(QQuickTextDocument *quickdocument);
signals:
void quickdocumentChanged();
private:
QQuickTextDocument *m_quickdocument;
};
#endif // SYNTAXHIGHLIGHTER_H
syntaxhighlighter.cpp
#include "syntaxhighlighter.h"
#include <QQuickTextDocument>
HighlightingRule::HighlightingRule(const QString &patternStr, int n, const QTextCharFormat &matchingFormat)
{
originalRuleStr = patternStr;
pattern = QRegularExpression(patternStr);
nth = n;
format = matchingFormat;
}
PythonSyntaxHighlighter::PythonSyntaxHighlighter(QTextDocument *parent)
: QSyntaxHighlighter(parent)
{
keywords = QStringList() << "and" << "assert" << "break" << "class" << "continue" << "def" <<
"del" << "elif" << "else" << "except" << "exec" << "finally" <<
"for" << "from" << "global" << "if" << "import" << "in" <<
"is" << "lambda" << "not" << "or" << "pass" << "print" <<
"raise" << "return" << "try" << "while" << "yield" <<
"None" << "True" << "False";
operators = QStringList() << "=" <<
// Comparison
"==" << "!=" << "<" << "<=" << ">" << ">=" <<
// Arithmetic
"\\+" << "-" << "\\*" << "/" << "//" << "%" << "\\*\\*" <<
// In-place
"\\+=" << "-=" << "\\*=" << "/=" << "%=" <<
// Bitwise
"\\^" << "\\|" << "&" << "~" << ">>" << "<<";
braces = QStringList() << "{" << "}" << "\\(" << "\\)" << "\\[" << "]";
basicStyles.insert("keyword", getTextCharFormat("blue"));
basicStyles.insert("operator", getTextCharFormat("red"));
basicStyles.insert("brace", getTextCharFormat("darkGray"));
basicStyles.insert("defclass", getTextCharFormat("black", "bold"));
basicStyles.insert("brace", getTextCharFormat("darkGray"));
basicStyles.insert("string", getTextCharFormat("magenta"));
basicStyles.insert("string2", getTextCharFormat("darkMagenta"));
basicStyles.insert("comment", getTextCharFormat("darkGreen", "italic"));
basicStyles.insert("self", getTextCharFormat("black", "italic"));
basicStyles.insert("numbers", getTextCharFormat("brown"));
triSingleQuote.setPattern("'''");
triDoubleQuote.setPattern("\"\"\"");
initializeRules();
}
void PythonSyntaxHighlighter::initializeRules()
{
for(const QString & currKeyword: keywords)
{
rules.append(HighlightingRule(QString("\\b%1\\b").arg(currKeyword), 0, basicStyles.value("keyword")));
}
for(const QString & currOperator: operators)
{
rules.append(HighlightingRule(QString("%1").arg(currOperator), 0, basicStyles.value("operator")));
}
for(const QString &currBrace: braces)
{
rules.append(HighlightingRule(QString("%1").arg(currBrace), 0, basicStyles.value("brace")));
}
// 'self'
rules.append(HighlightingRule("\\bself\\b", 0, basicStyles.value("self")));
// Double-quoted string, possibly containing escape sequences
// FF: originally in python : r'"[^"\\]*(\\.[^"\\]*)*"'
rules.append(HighlightingRule("\"[^\"\\\\]*(\\\\.[^\"\\\\]*)*\"", 0, basicStyles.value("string")));
// Single-quoted string, possibly containing escape sequences
// FF: originally in python : r"'[^'\\]*(\\.[^'\\]*)*'"
rules.append(HighlightingRule("'[^'\\\\]*(\\\\.[^'\\\\]*)*'", 0, basicStyles.value("string")));
// 'def' followed by an identifier
// FF: originally: r'\bdef\b\s*(\w+)'
rules.append(HighlightingRule("\\bdef\\b\\s*(\\w+)", 1, basicStyles.value("defclass")));
// 'class' followed by an identifier
// FF: originally: r'\bclass\b\s*(\w+)'
rules.append(HighlightingRule("\\bclass\\b\\s*(\\w+)", 1, basicStyles.value("defclass")));
// From '#' until a newline
// FF: originally: r'#[^\\n]*'
rules.append(HighlightingRule("#[^\\n]*", 0, basicStyles.value("comment")));
// Numeric literals
rules.append(HighlightingRule("\\b[+-]?[0-9]+[lL]?\\b", 0, basicStyles.value("numbers"))); // r'\b[+-]?[0-9]+[lL]?\b'
rules.append(HighlightingRule("\\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\\b", 0, basicStyles.value("numbers"))); // r'\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b'
rules.append(HighlightingRule("\\b[+-]?[0-9]+(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\\b", 0, basicStyles.value("numbers"))); // r'\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b'
}
void PythonSyntaxHighlighter::highlightBlock(const QString &text)
{
for(const HighlightingRule &rule: rules) {
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
while (matchIterator.hasNext()) {
QRegularExpressionMatch match = matchIterator.next();
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
}
}
setCurrentBlockState(0);
bool isInMultilne = matchMultiline(text, triSingleQuote, 1, basicStyles.value("string2"));
if (!isInMultilne)
isInMultilne = matchMultiline(text, triDoubleQuote, 2, basicStyles.value("string2"));
}
bool PythonSyntaxHighlighter::matchMultiline(const QString &text, const QRegularExpression &delimiter, const int inState, const QTextCharFormat &style)
{
QRegularExpressionMatch match;
int startIndex = 0;
if (previousBlockState() != 1)
startIndex = text.indexOf(delimiter);
while (startIndex >= 0) {
QRegularExpressionMatch match = delimiter.match(text, startIndex);
int endIndex = match.capturedStart();
int commentLength = 0;
if (endIndex == -1) {
setCurrentBlockState(1);
commentLength = text.length() - startIndex;
} else {
commentLength = endIndex - startIndex
+ match.capturedLength();
}
setFormat(startIndex, commentLength, style);
startIndex = text.indexOf(delimiter, startIndex + commentLength);
}
return currentBlockState() == inState;
}
const QTextCharFormat PythonSyntaxHighlighter::getTextCharFormat(const QString &colorName, const QString &style)
{
QTextCharFormat charFormat;
QColor color(colorName);
charFormat.setForeground(color);
if (style.contains("bold", Qt::CaseInsensitive))
charFormat.setFontWeight(QFont::Bold);
if (style.contains("italic", Qt::CaseInsensitive))
charFormat.setFontItalic(true);
return charFormat;
}
QQuickTextDocument *SyntaxHighlighterHelper::quickdocument() const
{
return m_quickdocument;
}
void SyntaxHighlighterHelper::setQuickdocument(QQuickTextDocument *quickdocument)
{
m_quickdocument = quickdocument;
if(m_quickdocument){
new PythonSyntaxHighlighter(m_quickdocument->textDocument());
}
}
main.cpp
// ...
qmlRegisterType<SyntaxHighlighterHelper>("Foo", 1, 0, "SyntaxHighlighterHelper");
// ...
main.qml
// ...
import Foo 1.0
// ...
SyntaxHighlighterHelper{
quickdocument: ta.textDocument
}
TextArea{
id:ta
anchors.fill: parent
selectByMouse: true
selectByKeyboard: true
font.pointSize: 12
textMargin: 16
font.family:"courier new"
persistentSelection: true
textFormat: Text.StyledText
tabStopDistance: 4*fontMetrics.advanceWidth(" ")
FontMetrics {
id: fontMetrics
font.family: ta.font
}
}
// ...
The example can be found here.

send Qevent from thread

Please can some-one suggest on this question..? I have to send data from my TX thread to mainwindow using class derived from QEvent.
I want my RX thread to throw an event whenever some data is received so hat i can display that data in the Mainwindow.
I start a main thread when button start is pressed. I save the pointer to my mainwindow inside the object of main thread. I will use this pointer to post events to the mainwindow object.
When first time i enter the Qthread function dowork_rx(). Event is thrown & i am able to catch it in customEvent() handler. But when dowork_rx() while loop starts when i throws the event it does not trigger the customEvent() function.
Please suggest how to resolve this problem.
My qevent class :---
//String event derived class
template <typename T> class StringEvent : public QEvent
{
QString m_str;
public:
explicit StringEvent(const QString val) : QEvent(staticType()), m_str(val)
{
}
void setvalue(QString val)
{
m_str = val;
}
QString value() const
{
return m_str;
}
static QEvent::Type staticType()
{
static int type = QEvent::registerEventType();
return static_cast<QEvent::Type>(type);
/*
static int type;
if(type == 0)
{
type = QEvent::registerEventType();
}
return static_cast<QEvent::Type>(type);*/
}
static bool is(const QEvent * ev)
{
return ev->type() == staticType();
}
};
class UpdateEvent : public StringEvent<UpdateEvent>
{
public:
explicit UpdateEvent(QString val): StringEvent(val)
{
//qDebug() << "hello";
}
};
class ClearEvent : public StringEvent<ClearEvent>
{
public:
explicit ClearEvent(QString val): StringEvent(val)
{
}
};
Dowork function of the thread :----
// Common slot for the rx - thread
void RxThreadObject::dowork_rx()
{
int i =0;
qDebug() << "\nrx start \n";
myUpdateEvent_rx = new UpdateEvent("UpdateEventObject - dowork_rx");
//myUpdateEvent_rx->setvalue("first");
QCoreApplication::postEvent(m_pMainThreadObj->ptrmainwindow, myUpdateEvent_rx);
qDebug() << "\nrx throw event - done \n";
while(!m_bQuitRx)
{
SleepTimerDelay::sleep(2);
if(i==0){
//qDebug() << "\nrx throw event - done 11 \n";
myUpdateEvent_rx = new UpdateEvent("first");
myUpdateEvent_rx->setvalue("first");
QCoreApplication::postEvent(m_pMainThreadObj->ptrmainwindow, myUpdateEvent_rx);
i++;
}else{
//qDebug() << "\nrx throw event - done 22 \n";
myUpdateEvent_rx = new UpdateEvent("second");
myUpdateEvent_rx->setvalue("second");
QCoreApplication::postEvent(m_pMainThreadObj->ptrmainwindow, myUpdateEvent_rx);
i=0;
}
}
qDebug() << "\nrx end \n";
}
Event handler :----
/*!
** Custom event handler
*/
void MainWindow::customEvent(QEvent *event)
{
qDebug() << "oo customEvent";
if (UpdateEvent::is(event)) {
UpdateEvent *tempUpdateEvent = static_cast<UpdateEvent *>(event);
qDebug() << tempUpdateEvent->value();
}
else if (ClearEvent::is(event)) {
ClearEvent *tempClearEvent = static_cast<ClearEvent *>(event);
qDebug() << tempClearEvent->value();
}
}
/*!
** event filter handler
*/
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
qDebug() << "oo eventFilter";
if (UpdateEvent::is(event)) {
UpdateEvent *tempUpdateEvent = static_cast<UpdateEvent *>(event);
qDebug() << tempUpdateEvent->value();
}
else if (ClearEvent::is(event)) {
ClearEvent *tempClearEvent = static_cast<ClearEvent *>(event);
qDebug() << tempClearEvent->value();
}
return true;
}

How to select child's items checkBoxs in QTreeView when select their parent's checkbox

I want to select/unselect all child's items QCheckBoxs when I select/unselect their parent's item QCheckBox.
i inherit from QTreeView and detect when the QCheckBox is selected then i call function to do selecting/unselecting process.
here my code:
#ifndef MYQTREEVIEW_H
#define MYQTREEVIEW_H
#include <QTreeView>
#include <QMouseEvent>
#include <QDebug>
#include <QStandardItem>
class MyQTreeView: public QTreeView {
public:
MyQTreeView(QWidget* parent=0): QTreeView(parent){}
virtual ~MyQTreeView() {}
protected:
void resettingCheckBox (QModelIndex& parentIndex) {
if ( ! parentIndex.isValid() )
return;
QString text = parentIndex.data( Qt::DisplayRole ).value<QString>();
qDebug() << "parent is: " << text;
if ( model()->hasChildren(parentIndex) ) {
for( int i = 0; i < model()->rowCount(parentIndex) ; i++ ) {
QModelIndex childIndex = model()->index( i, 0, parentIndex );
if ( model()->hasChildren(childIndex) )
resettingCheckBox(childIndex);
else {
QString text = childIndex.data( Qt::DisplayRole ).value<QString>();
qDebug() << "child is: " << text;
QStandardItem *parentItem = static_cast<QStandardItem*> (parentIndex.internalPointer());
QStandardItem *childItem = static_cast<QStandardItem*> (childIndex.internalPointer());
if ( parentItem->checkState() == Qt::Checked ) {
qDebug() << "child item " << childItem->checkState();
childItem->setCheckState( Qt::Unchecked);
}
else {
qDebug() << "child item " << childItem->checkState();
childItem->setCheckState( Qt::Checked);
}
}
}
}
}
void mousePressEvent (QMouseEvent *event) {
QModelIndex index = indexAt(event->pos());
if(index.isValid()) {
QStyleOptionButton opt;
opt.QStyleOption::operator=(viewOptions());
opt.rect = visualRect(index);
QRect rect = style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt);
if (rect.contains(event->pos())) {
resettingCheckBox(index);
}
QTreeView::mousePressEvent(event);
}
}
};
#endif // MYQTREEVIEW_H
the code is not working probably when i select/unselect parent checkBox (subchilds is not selected/unselected).
Thanks in advance.
I believe the best way to manipulate treeview items is through the model. It looks like you're using QStandardItemModel; so you can override your model's setData method and reset child items values for the item index passed as a parameter to this method. Below is a small example:
class TestModel : public QStandardItemModel
{
public:
TestModel() {}
bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole)
{
QStandardItem *item = itemFromIndex(index);
for( int i = 0; i < item->rowCount() ; i++ )
{
QStandardItem *childItem = item->child(i);
setData(childItem->index(), value, role);
}
return QStandardItemModel::setData(index, value, role);
}
};
here's how this model gets initialized:
QStandardItemModel* tableModel = new TestModel();
QStandardItem* parentItem = tableModel->invisibleRootItem();
for (int i = 0; i < 4; ++i)
{
QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
item->setCheckable(true);
parentItem->appendRow(item);
parentItem = item;
}
treeView->setModel(tableModel);
hope this helps, regards
It seems to me that you should call QTreeView::mousePressEvent(event) before resettingCheckBox(index), to let QTreeView update the checkState.
override mouseReleaseEvent() instead of mousePressEvent()!
because the checkState changes when mouse Release not mouse - press!

Resources