How do i get the current text of a QCombobox edited? - c++

i want get the current text of a QComboBox edited.
QString nome = ui->taxas_existentes->currentText();
I have this, but if the initial text was "Test" and i change to "Test1", the variable "nome" will have "Test" as value instead of "Test1"...
Edit:
I've this, then i click on icon of edit
I change the name "Teste" to "Teste1" and i click on green icone
Then, after i clicked on green icone, i have this code:
QString nome = ui->taxas_existentes->currentText();
The variable nome have a value of "Teste" instead of "Teste1"...
edit2:
void WidgetDefinicoes::on_editar_taxa_clicked()
{
GereTaxa gereTaxas = GereTaxa();
if(ui->taxas_existentes->isEditable()) {
ui->taxas_existentes->setEditable(false);
QString nome = ui->taxas_existentes->currentText();
if(!nome.isEmpty()){
GereTaxa gereTaxa = GereTaxa();
int idTaxa = gereTaxas.obtemId(taxas.at(0)->getNome());
if(nome == taxas.at(0)->getNome()) {
Taxa * taxa = new Taxa(idTaxa, taxaInt, nome);
qDebug() << taxa->getTaxa();
qDebug() << taxa->getNome();
if(gereTaxa.editTaxa(* taxa) == 1) {
QMessageBox::information(this,tr("SalesQ"),tr("A taxa foi alterada com sucesso!"));
} else {
QMessageBox::warning(this,tr("SalesQ"),tr("Ocorreu um erro a alterar a taxa!"));
}
}
}
}

Found the error!
ui->taxas_existentes->setEditable(false);
Must be after of
QString nome = ui->taxas_existentes->currentText();
And not before

Related

SQL Parameter count mismatch on QTableView

I have a GUI composed of:
N.1 GraphicsView
N.1 QTableView
N.1 dialog that opens up as needed by the user after doubleclicking on each row of the QTableView
I can capture features on the QGraphicsView with the mouse click. After the feature is drawn I right click and open up a dialog like the one in the figure:
After hitting accept: I register the feature as the row index of the QTableView as shown below:
If I doubleclick on each row I am able to open again the same dialog with the information previously saved. I do that because I may need to change the name of the image and call it differently.
The problem I currently have is that I ma receiving a weird Parameter count mismatch from the compiler and I don't understand why and it should be due to QSQLITE
Below is what I am trying to do along with the most important part of the code:
parameters.h
typedef struct Param
{
int mId;
QString mName;
QByteArray mSave;
} Param;
class Parameters
{
public:
Parameters() = default;
Parameters(Param newdata);
Parameters(int id, const QString &name, const QByteArray &save);
int id() const { return data.mId; }
QString name() const {return data.mName; }
QByteArray save() const {return data.mSave; }
Param getData() const { return data; }
void setData(Param ndat) { data = ndat; }
private:
Param data;
};
parameters.cpp
#include "parameters.h"
Parameters::Parameters(Param newdata) {
data = newdata;
}
Parameters::Parameters(int id, const QString &name,
const QByteArray &save) {
data.mId = id;
data.mSave = save;
data.mName = name;
}
the database is set in the following dataleftcamera.h part:
public:
explicit dataLeftCamera(QObject *parent = nullptr);
bool addItem(Parameters* mParameters);
bool updateItem(int itemId, Parameters* mParameters);
QSqlDatabase getDatabase();
private:
QString mError;
QSqlDatabase mDatabaseLeft;
The table is initiated here on dataleftcamera.cpp and here is where the compiler is giving the Parameter count mismatch error specifically on the function updateItem
#define CREATE_TABLE \
" CREATE TABLE IF NOT EXISTS leftCamTable" \
" (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL" \
", name TEXT NOT NULL" \
", save BLOB NOT NULL)"
dataLeftCamera::dataLeftCamera(QObject *parent) : QObject (parent)
{}
bool dataLeftCamera::addItem(Parameters *mParameters)
{
QSqlQuery qry;
qry.prepare("INSERT INTO leftCamTable (name, save)"\
" VALUES (?,?)");
qry.addBindValue(mParameters->name());
qry.addBindValue(mParameters->save());
bool ok = qry.exec();
if(!ok) {
mError = qry.lastError().text();
qDebug() << mError;
}
}
bool dataLeftCamera::updateItem(int itemId, Parameters *mParameters)
{
QSqlQuery qry;
qry.prepare(" UPDATE lefCamTable SET " \
" name = ?," \
" save = ?" \
" WHERE id = ?");
qry.addBindValue(mParameters->name());
qry.addBindValue(mParameters->save());
qry.addBindValue(itemId);
bool ok = qry.exec();
if(!ok) {
mError = qry.lastError().text();
qDebug() << mError;
}
}
On the mainwindow.cpp is the part where I update the item after I doubleclick on the row to change the name of the image and accept again the modification:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
mDatabaseLeftCamera = new dataLeftCamera(this);
mModelLeftCamera = nullptr;
mModelLeftCamera = new QSqlTableModel(this);
ui->tableView->setModel(mModelLeftCamera);
connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)),
this, SLOT(onTableClick(QModelIndex)));
// temporary folder
temporaryFolder = "/home/name/Desktop/tempDBFolder/tmp.db";
QFile dbRem(temporaryFolder);
dbRem.remove();
mDatabaseLeftCamera->inizializationDatabaseLeftCamera(temporaryFolder);
mDatabaseLeftCamera->configurationDatabaseLeftCamera();
mModelLeftCamera = new QSqlTableModel(this, mDatabaseLeftCamera->getDatabase());
mModelLeftCamera->setTable("leftCamTable");
mModelLeftCamera->select();
ui->tableView->setModel(mModelLeftCamera);
ui->tableView->showColumn(true);
}
// opening the dialog for the first time after capturing the image
void MainWindow::contextMenuEvent(QContextMenuEvent *event)
{
// operations
Param result = d.getData();
Parameters* param = new Parameters(result);
mDatabaseLeftCamera->addItem(param);
mModelLeftCamera->select();
ui->tableView->show();
}
// This is the doubleclick that re-opens the small dialog to change the name of the feature
void MainWindow::onTableClick(const QModelIndex &index)
{
int row = index.row();
Param currentData;
int ItemId = index.sibling(row, 0).data().toInt();
currentData.mName = index.sibling(row, 1).data().toString();
currentData.mSave = index.sibling(row, 2).data().toByteArray();
QPixmap iconPix;
if(!iconPix.loadFromData(index.sibling(row, 2).data().toByteArray())) {
}
clipSceneDialog d(this);
d.show();
d.setData(currentData);
d.setImage(iconPix.toImage());
if(d.exec() == QDialog::Rejected) {
return;
} else {
//
}
Param result = d.getData();
Parameters* param = new Parameters(result);
mDatabaseLeftCamera->updateItem(ItemId,param);
mModelLeftCamera->select();
ui->tableView->show();
}
For completeness see the error the compiler is giving if that helps:
I am sorry if this is trivial but I checked the updateItem(ItemId,param)
and thanks for shedding light on this.
Try and add some debug printing. Especially for the parameters that you add to the prepared statement. qry.addBindValue converts your value to a QVariant. Based on the documentation QVariants become NULL when they contain no data:
QVariant x(QString());
// x.isNull() == true
In case there is a problem retrieving your parameters, this could explain the violation of the NOT NULL constraints.

Qt WebEngine incorrect page margins when printing

I implement the ability to print reports in my project. Reports are presented as HTML content. There is an instance of QPrinter with custom fields:
printer = new QPrinter(QPrinter::ScreenResolution);
qreal topMargin = 15;
qreal bottomMargin = 15;
qreal leftMargin = 20;
qreal rightMargin = 15;
QPrinter::Unit units = QPrinter::Millimeter;
printer->setPageMargins(leftMargin,topMargin,rightMargin,bottomMargin,units);
When printing in PDF, everything is fine
view->printToPdf([=] (QByteArray bd) {
//Запись файла
}, printer->pageLayout());
But when printing with the "print" function, the fields are set incorrectly:
QWebEnginePage *page = new QWebEnginePage;
page->setHtml(currentForPrint);
connect(page, &QWebEnginePage::loadFinished, [page, printer] (bool ok) {
if (!ok) {
qDebug() << "error"; return;
}
page->print(printer, [=] (bool ok) {
if (ok)
qDebug() << "success";
else
qDebug() << "error 2";
});
});
image
Qt Version - 5.9.3.
This is a bug in WebEngine. I have reported it and will fix it as soon as it's possible. As a workaround you could enable full page printing in your QPrinter:
printer->setFullPage(true);
This works for me.

Connecting SLOTS in Qt

I have a context menu and edit menu. I want to connect context menu slots with the edit menu.
Like EDIT menu has menu Items: cut, copy and paste
My context menu slots are:
void CadGraphicsScene::cut(getEntity *obj)
{
// id of item pasted is kept same as that of the item being cut
removeItem(obj);
clipboardStack::instance()->push(obj->clone(contextItemId));
}
void CadGraphicsScene::copy(getEntity *obj)
{
// id of item pasted is one more than total number of items in the scene
clipboardStack::instance()->push(obj->clone(++id));
}
void CadGraphicsScene::paste(const QPointF &pos)
{
// gets the items cut/copy from clipboardStack to paste
getEntity *pasteEntity = clipboardStack::instance()->pop();
if (pasteEntity->type() == Point::Type)
{
Point *itemPtr = dynamic_cast<Point *>(pasteEntity);
itemPtr->position = pos;
drawEntity(itemPtr);
}
if (pasteEntity->type() == Line::Type)
{
Line *itemPtr = dynamic_cast<Line *>(pasteEntity);
itemPtr->startP = pos;
/* calculates difference between startP of line being cut/copy and line
* being pasted for proper pasting of line
*/
differenceX = itemPtr->startP.x() - lineStartPoint.x();
differenceY = itemPtr->startP.y() - lineStartPoint.y();
itemPtr->endP = QPointF(lineEndPoint.x() + differenceX,
lineEndPoint.y() + differenceY);
drawEntity(itemPtr);
}
if (pasteEntity->type() == Circle::Type)
{
Circle *itemPtr = dynamic_cast<Circle *>(pasteEntity);
itemPtr->centerP = pos;
drawEntity(itemPtr);
}
if (pasteEntity->type() == Ellipse::Type)
{
Ellipse *itemPtr = dynamic_cast<Ellipse *>(pasteEntity);
itemPtr->p1 = pos;
drawEntity(itemPtr);
}
if (pasteEntity->type() == Text::Type)
{
Text *itemPtr = dynamic_cast<Text *>(pasteEntity);
itemPtr->position = pos;
drawEntity(itemPtr);
}
setMode(NoMode);
}
//context menu actions
void CadGraphicsScene::menuAction(QAction *action)
{
if (action == cutAction)
{
cut(static_cast<getEntity *>(contextItem));
}
else if (action == copyAction)
{
copy(static_cast<getEntity *>(contextItem));
}
else if (action == pasteAction)
{
paste(contextPosition);
}
}
How can the same be done from edit menu? How can the same slots be used?
for cut in the edit menu I made another slot:
void CadgraphicsScene::cut()
{
cutAction
}
connect(actionCut, SIGNAL(triggered), this, SLOT(cut()));
If you want to reuse the same slots in your application's Edit menu, just use existing cutAction, copyAction and pasteAction actions when constructing it. So if you has established the connections for that actions the same slots will be called both when user triggers actions from context menu and from Edit menu.

Qt - Updating in the function called by QSignalMapper

I have a QTreeWidget in which each of its items has a QComboBox in a column. I have connected it to a slot with a QSignalMapper, and I'm successfully retrieving both the item and the index in the combobox when it is triggered. I did it like this:
foreach(Workplace *wp, allWorkplaces){
QTreeWidgetItem *workplaceItem = new QTreeWidgetItem;
workplaceItem->setText(0, wp->workplaceName());
workplaceItem->setText(1, wp->workplaceDescription());
myWorkplaceUi->treeWidget->addTopLevelItem(workplaceItem);
QComboBox *combo = new QComboBox();
combo->addItems(allShiftModels);
combo->setAutoFillBackground(true);
ShiftModel *shiftModel = qobject_cast<ShiftModel *>(wp->usedShiftModel);
myWorkplaceUi->treeWidget->setItemWidget(workplaceItem,2, combo);
if(shiftModel && !shiftModel->shiftModelName().isEmpty()){
qDebug()<<"after the cast: "<< shiftModel->shiftModelName();
combo->setCurrentIndex(combo->findText(shiftModel->shiftModelName(), Qt::MatchExactly));
}else{
combo->setCurrentIndex(combo->findText("None", Qt::MatchExactly));
}
connect(combo, SIGNAL(currentIndexChanged(int)), signalMapper, SLOT(map()));
signalMapper->setMapping(combo, QString("%1").arg(wp->workplaceName()));
}
connect(signalMapper, SIGNAL(mapped(const QString &)),this, SLOT(changed(const QString &)));
My objective is, after retrieving both the Workplace and the ShiftModel, to update them in the instances of my already created Workplaces. So, basically, I try to find the Workplace and the ShiftModel that were selected, because depending on the ShiftModel selected, I will change a pointer to the ShiftModel in the Workplace class:
class Workplace : public QObject
{
Q_OBJECT
public:
(...)
ShiftModel *usedShiftModel;
(...)
}
And the changed slot:
void workplacesdialog::changed(QString position){
QList<Workplace* > allWorkplaces = this->myProject->listMyWorkplaces();
QList<ShiftModel*> allShiftModels = this->myProject->myFactory->listShiftModels();
foreach(Workplace* workplace, allWorkplaces){
foreach(ShiftModel *shiftmodel, allShiftModels){
qDebug() <<"workplace:"<< workplace->workplaceName();
qDebug() <<"shiftmodel:"<< shiftmodel->shiftModelName();
QString wp = position;
QTreeWidgetItem* item=(QTreeWidgetItem*)myWorkplaceUi->treeWidget->findItems(wp,Qt::MatchExactly,0).at(0);
QComboBox *combo = (QComboBox*)myWorkplaceUi->treeWidget->itemWidget(item,2);
if(combo && item){
QString sm = combo->currentText();
qDebug() << "selected shiftmodel "<< sm << " on workplace "<< wp;
if(workplace->workplaceName()==wp && shiftmodel->shiftModelName()==sm){
workplace->usedShiftModel = shiftmodel;
break;
}
else{
workplace->usedShiftModel = 0;
return;
}
}else{
qDebug() << "cast failed!";
return;
}
}
}
}
So, my problem with this is, when I click one of the comboboxes, successfully retrieve both the item and index selected, but then, when I try to traverse them with the two foreach loops in the slot, it does not work as I expected. I hoped that every time I clicked on an index in one of the comboboxes, this would be called, and it is. Although, for some reason, the method I'm using to match what the user selected with what was already instatiated doesn't work.
Also, it looks like it only hits both the 1st workplace on the allWorkplaces list as well as the 1st shiftmodel on the ShiftModels list, and this is my problem.
If anyone knows how to fix this or has any ideas to share, please let me know. Thank you.
The problem is this:
if(workplace->workplaceName()==wp && shiftmodel->shiftModelName()==sm){
workplace->usedShiftModel = shiftmodel;
break;
}
else{
workplace->usedShiftModel = 0;
return;
}
If either the workplace name does not match, or the shift model name does not match, the relation between the work place and its currently linked shift model is removed and your function returns.
I could restructure the two for-loops for you, but there is an easier and less error-prone way:
Note: I marked some code paths with "TODO" which I skipped due to lack of time. You should be able to figure them out yourself though.
// Set up hashes for quick lookup
QHash< QString, Workplace* > workplaceHash;
QList<Workplace* > allWorkplaces = this->myProject->listMyWorkplaces();
foreach( Workplace* workplace, allWorkplaces )
{
workplaceHash.insert( workplace, workplace->workplaceName() );
}
// TODO: Do a similar thing for the shift models here
// Find the selected workplace
if( !workplaceHash.contains( position ) )
{
// TODO: Error handling (An unknown/No workplace was selected)
return;
}
// else: A valid workplace was selected
Workplace* selectedWorkplace = workplaceHash.value( position );
// TODO: Retrieve the name of the shift model (stored in variable sm)
// Find the selected shiftmodel
if( !shiftplaceHash.contains( sm ) )
{
// No shift model was selected
selectedWorkplace->usedShiftModel= 0;
return;
}
// Else: Both work place and shift model were selected
Shiftplace* selectedShiftModel = shiftplaceHash.value( sm );
selectedWorkplace->usedShiftModel = selectedShiftModel;
A few ideas for refactoring:
You could maybe do the creation of the hashes outside of this method and store them in member variables. Just make sure that the hash is always updated when a workplace is added or removed.
You could make spotting errors easier by extracting parts of the code into separate methods, e.g. QString getSelectedShiftModelName() etc.
So, In the end I figured out my loops were really messed up... This is working now:
void workplacesdialog::changed(QString position){
QList<Workplace* > allWorkplaces = this->myProject->listMyWorkplaces();
QList<ShiftModel*> allShiftModels = this->myProject->myFactory->listShiftModels();
qDebug() << allWorkplaces.size() << " workplaces";
qDebug() << allShiftModels.size() << " ShiftModels";
QString wp = position;
QString sm;
QTreeWidgetItem* item=(QTreeWidgetItem*)myWorkplaceUi->treeWidget->findItems(wp,Qt::MatchExactly,0).at(0);
QComboBox *combo = (QComboBox*)myWorkplaceUi->treeWidget->itemWidget(item,2);
if(combo && item){
sm = combo->currentText();
qDebug() << "selected shiftmodel "<< sm << " on workplace "<< wp;
}else{
qDebug() << "cast failed!";
return;
}
foreach(Workplace* workplace, allWorkplaces){
foreach(ShiftModel *shiftmodel, allShiftModels){
qDebug() <<"workplace:"<< workplace->workplaceName();
qDebug() <<"shiftmodel:"<< shiftmodel->shiftModelName();
if(workplace->workplaceName()==wp && shiftmodel->shiftModelName()==sm){
qDebug() << "found match!: "<< wp << " >>>>> " << sm;
workplace->usedShiftModel = shiftmodel;
return;
}else if(workplace->workplaceName()==wp && sm=="None"){
qDebug() << "clear match: "<< wp << " >>>>> " << sm;
workplace->usedShiftModel = 0;
return;
}
}
}
}

Add icon from array to QListWidget item

I've written a loop which adds some items to my QListWidget. Now I want them to have an icon from my qrc file. For this I would use a loop in which I add a unique icon to each item.
void Test::Query()
{
ui->listWidget_Available->clear();
QString CmdList[4] = {"kcmshell4 --list|grep -q kcm_grub2",
"kcmshell4 --list|grep -q kcm_networkmanagement",
"which pastebunz",
"[ -z $ink3_ver ]"};
QString NameList[4] = {"kcm_grub2",
"kcm_networkmanagement",
"pastebunz",
"Shellmenu"};
QString IconList[4] = {":/icons/icons/GNU.png",
":/icons/icons/networkmanager.png",
":/icons/icons/edit-paste.png",
":/icons/icons/menu.png"};
QIcon ItemIcon;
int iCntSize = sizeof(CmdList) / sizeof(CmdList[0]);
Next thing is to clear the List:
for(int iItem = 0; iItem < iCntSize; iItem++)
{
ui->listWidget_Available->addItem(NameList[iItem]);
ui->listWidget_Available->item(iItem)->setCheckState(Qt::PartiallyChecked);
}
Now the ugly part:
for(int iRow = 0; iRow < iCntSize; iRow++)
{
int BarValue = ui->progressBar->value();
ui->progressBar->setValue(BarValue+(100/iCntSize));
QString status = QString("Processing index %1 of %2. Name: %3").arg(iRow).arg(iCntSize).arg(NameList[iRow]);
qDebug() << status << (BarValue+25);
And here is my problem:
ItemIcon.addFile(IconList[iRow], QSize(), QIcon::Normal, QIcon::Off);
ui->listWidget_Available->item(iRow)->setIcon(ItemIcon); <--- how to do THIS?
How can I do this?
ui->textEdit_Informations->append("Searching for "+NameList[iRow]);
mProcess = new QProcess();
mProcess->start("/bin/bash", QStringList() << "-c" << QString(CmdList[iRow]));
mProcess->waitForFinished();
if ( mProcess->exitStatus() == QProcess::CrashExit )
{
ui->textEdit_Informations->setTextColor(Qt::red);
ui->textEdit_Informations->append("\t[FATAL]");
}
else if ( mProcess->exitCode() != 0 )
{
ui->textEdit_Informations->setTextColor(Qt::magenta);
ui->textEdit_Informations->append("\t[MISSED]");
ui->listWidget_Available->item(iRow)->setCheckState(Qt::Unchecked);
}
else if ( mProcess->exitCode() == 0 )
{
ui->textEdit_Informations->setTextColor(Qt::green);
ui->textEdit_Informations->append("\t[FOUND]");
ui->listWidget_Available->item(iRow)->setCheckState(Qt::Checked);
}
ui->textEdit_Informations->setTextColor(Qt::white);
}
}
Any suggestions?
You should use the constructor and a new QIcon each time instead of QIcon::addFile:
QIcon ItemIcon(IconList[iRow]);
ui->listWidget_Available->item(iRow)->setIcon(ItemIcon);
addFile would only be useful if you had a different image for each state of the item the icon is in (normal, activated, disabled, ...).