i tried to entre data from a form " means from QlineEdit as integer "
the programm is compiled successfully but when i open the form and entre data , the programm crach
her's the erreur
Object::connect: No such slot FenArticle::chercheParFamille() in ..\stockmanagement\fenarticle.cpp:113
QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.
QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.
hers my code
*
#include "fenajoutearticle.h"
#include <QIntValidator>
#include <QValidator>
FenAjouteArticle::FenAjouteArticle(QWidget *parent) :
QWidget(parent)
{
resize(500,450);
setWindowModality(Qt::ApplicationModal);
// init member widgets
//*****************************Signals SLots ******************************//
signalSlots();
//***********************************Base de donnée Traitement***********************************//
db = new QSqlDatabase;
*db = QSqlDatabase::addDatabase("QSQLITE") ;
db->setHostName("localhost");
db->setDatabaseName("gestionstockDB.db");
db->setPassword("");
db->setUserName("");
db->open();
if(!db->open())
QMessageBox::critical(this,"Erreur","Erreur connexion base de données") ;
else{
QSqlQuery *chercheParFamilleQuery = new QSqlQuery("select Famille from Produit");
SelectFamille->clear();
while(chercheParFamilleQuery->next())
SelectFamille->addItem(chercheParFamilleQuery->value(0).toString());
QSqlQuery *chercheParUniteQuery = new QSqlQuery("select Unite from Produit");
selectUnit->clear();
while(chercheParUniteQuery->next())
selectUnit->addItem(chercheParUniteQuery->value(0).toString());
}
// basic layouting
}
void FenAjouteArticle::signalSlots()
{
connect(buttonOkUtilisateur,SIGNAL(clicked()),this,SLOT(ajoutDonne())) ;
connect(buttonAnnulerUtilisateur,SIGNAL(clicked()),this,SLOT(close())) ;
}
//********************* Signal Slots coeurs ***********************************//
void FenAjouteArticle::ajoutDonne()
{
if(db->open())
{
QSqlQuery *ajouterDonneeQuery = new QSqlQuery;
ajouterDonneeQuery->prepare("insert into Produit (Reference,Designation,localisation,Famille,Qte_min,Qte_max,Qte_stock,Unite,Prix_achat,Prix_vente) VALUES(:ref,:design,:local,:fam,:qtmin,:qtmax,:qtstock ,:unite,:pachat,:pvente)");
//QString Stock = champStockInit->text();
ajouterDonneeQuery->bindValue(":ref",champRef->text()); // QlineEdit
ajouterDonneeQuery->bindValue(":design",champDesignation->text()); // QlineEdit
ajouterDonneeQuery->bindValue(":local",champLocalisation->text()); // QlineEdit
ajouterDonneeQuery->bindValue(":fam","fam"); // QcomboBox
ajouterDonneeQuery->bindValue(":qtmin",200); // QlineEdit
ajouterDonneeQuery->bindValue(":qtmax",20); // QlineEdit
ajouterDonneeQuery->bindValue(":qtstock",20); // QlineEdit
ajouterDonneeQuery->bindValue(":unite","unite"); // QlineEdit
ajouterDonneeQuery->bindValue(":pachat",20); // QlineEdit
ajouterDonneeQuery->bindValue(":pvente",champPrixVente->text()); // QlineEdit
ajouterDonneeQuery->exec();
}
}
the DB message with the duplication is caused by (i guess) multiple instances of that class.
set up your database connection at a "global" spot, like main() or inside your main window class. (except you want and need multiple connections, but i dont think this is good when working with sqlite)
when using multiple connections, you need to add them to the QSqlQuery constructor, otherwise it will use the default connection, mostly the first created one.
no slot existing named FenArticle::chercheParFamille() should be message enough. maybe some characters are incorrect or the parameters given differs from declaration.
to the value binding, sqlite should be cool with a string as value for an integer and will use it correct, IF the value is a valid integer.
you could alternatively use:
QString intText = lineEdit->text();
bool test = false;
intText.toInt(&test);
if (test == true)
// it is a valid integer, use it
else
// message or whatever
Related
I keep getting rocksdb_column_family_error_test: /rocksdb/db/column_family.cc:1236: rocksdb::ColumnFamilySet::~ColumnFamilySet(): Assertion `last_ref' failed. when I try to close/delete or go out of scope with rocksdb. It throws SIGABRT. That is, when I use std::unique_pointers for the database and column family handlers. I have attached the test file that I'm using which mimics our production code. Main exception is that in our production code we have a class that handles the database stuff. Either way, SIGABRT is thrown when the database is closed out. I've searched for answers and have found similar issues. The main conclusion to the issues was that the column family handlers were not being released from the database before closing. Also, there seems to have been a bug in previous releases of rocksdb concerning this. Is that bug still there? Am I just doing something incorrectly? Although not in this code, I have also tested with drop/destroy of the default column family too.
Rockdb version.h
#define ROCKSDB_MAJOR 6
#define ROCKSDB_MINOR 2
#define ROCKSDB_PATCH 0
Below is the test file:
#include <gtest/gtest.h>
#include <rocksdb/db.h>
#include <rocksdb/filter_policy.h>
#include <rocksdb/table.h>
namespace testing {
namespace {
static const std::string db_directory = std::string("/tmp/database");
static const std::string kFeaturesColumnFamilyName = "keypoints_and_descriptors";
static const std::string kMatchesColumnFamilyName = "image_pair_matches";
static const std::string kIntrinsicsColumnFamilyName = "camera_intrinsics_prior";
} // namespace
TEST(RocksdbColumnFamilyError, RocksBasicPointers) {
std::unique_ptr<rocksdb::Options> options_;
std::unique_ptr<rocksdb::DB> database_;
std::unique_ptr<rocksdb::ColumnFamilyHandle> intrinsics_prior_handle_;
std::unique_ptr<rocksdb::ColumnFamilyHandle> features_handle_;
std::unique_ptr<rocksdb::ColumnFamilyHandle> matches_handle_;
options_.reset(new rocksdb::Options);
options_->max_background_jobs = 4;
options_->db_write_buffer_size = 1 << 30;
options_->bytes_per_sync = 1 << 20;
options_->compaction_pri = rocksdb::kMinOverlappingRatio;
options_->create_if_missing = true;
options_->level_compaction_dynamic_level_bytes = true;
options_->statistics = rocksdb::CreateDBStatistics();
rocksdb::BlockBasedTableOptions table_options;
table_options.block_cache = rocksdb::NewLRUCache(512 << 20);
table_options.block_size = 16 * 1024;
table_options.cache_index_and_filter_blocks = true;
table_options.pin_l0_filter_and_index_blocks_in_cache = true;
table_options.filter_policy.reset(rocksdb::NewBloomFilterPolicy(10, false));
options_->table_factory.reset(rocksdb::NewBlockBasedTableFactory(table_options));
std::vector<rocksdb::ColumnFamilyDescriptor> column_descriptors;
column_descriptors.emplace_back(rocksdb::kDefaultColumnFamilyName, *options_);
// Open the DB, creating it if necessary.
rocksdb::DB* temp_db = nullptr;
std::vector<rocksdb::ColumnFamilyHandle*> temp_col_family_handles;
rocksdb::Status status = rocksdb::DB::Open(*options_,
db_directory,
column_descriptors,
&temp_col_family_handles,
&temp_db);
// Take ownership of the database object.
database_.reset(temp_db);
// Create intrinsics_prior_handle_
rocksdb::ColumnFamilyHandle * intrinsics_prior_;
database_->CreateColumnFamily(*options_, kIntrinsicsColumnFamilyName, &intrinsics_prior_);
intrinsics_prior_handle_.reset(intrinsics_prior_);
// Create features_handle_
rocksdb::ColumnFamilyHandle * features_;
database_->CreateColumnFamily(*options_, kFeaturesColumnFamilyName, &features_);
features_handle_.reset(features_);
// Create matches_handle_
rocksdb::ColumnFamilyHandle * matches_;
database_->CreateColumnFamily(*options_, kMatchesColumnFamilyName, &matches_);
matches_handle_.reset(matches_);
/*
* .... proform database operation get stuff, put stuff so on ....
*/
// Drop handles
database_->DropColumnFamily(intrinsics_prior_handle_.get());
database_->DropColumnFamily(features_handle_.get());
database_->DropColumnFamily(matches_handle_.get());
// Destroy handles
database_->DestroyColumnFamilyHandle(intrinsics_prior_handle_.get());
database_->DestroyColumnFamilyHandle(features_handle_.get());
database_->DestroyColumnFamilyHandle(matches_handle_.get());
// Close db
database_->Close(); // Causes SIGABRT
// delete database_.get(); // Causes SIGABRT
// rocksdb::DestroyDB(db_directory, rocksdb::Options()); // Causes SIGABRT // Options doesn't have any affect
rocksdb::DestroyDB(db_directory, *options_); // Causes SIGABRT // Options doesn't have any affect
}
} // namespace testing
In addition to Dropping and Destroying ColumnFamilies that you have created, I think, you also need to Destroy the default column family.
database_->DestroyColumnFamilyHandle(default_family_handle_);
The default family should not be dropped.
I've a question that couldn't find anywhere. I have a QMap that's ignoring the QMap.insert(Key, Value) command. Here's the code:
//gets the selected problem index on the ProblemList
int selProblem = ui->tree_projects->currentItem()->data(0, Qt::UserRole).toInt();
//creates a new problem, sets its values and then replaces the old one on the ProblemsList variable
ProblemSets nProblem;
if(!problemsList.isEmpty()) //problemsList is an attribute of MainWindow
nProblem = problemsList.value(selProblem);
// some data collection that has been omitted because isn't important
// temporary maps that will carry the modifications
QMap<int, QString> nResName, nResType;
//data insertion into the maps
//these are fine
nResName.insert(fIdx, results_model->data(results_model->index(fIdx, 0)).toString());
nResType.insert(fIdx, results_model->data(results_model->index(fIdx, 1)).toString());
//replaces the old maps with the new ones
nProblem.SetProbResultsNames(nResName);
nProblem.SetProbResultsTypes(nResType);
//replaces the old problem with the new one
problemsList.insert(selProblem, nProblem); //this is the line that's doing nothing
}
That last line appears to be doing nothing! I've even tried to use
problemsList.remove(selProblem);
problemList.insert(selProblem, nProblem);
but got a similar result: the map not being inserted at the index selProblem. It got inserted, but with an outdated value - the same one of the deleted index -. I've checked on Debug and all the indexes and variables are correct, but when the .insert hits, nothing happens.
The most awkward thing is that this code is a copy/paste that I made from another method that I'm using that does similar thing, just changing the variable names, but that one works.
EDIT 1: This is the contents of nProblem, selProb and problemsList.value(selProblem)
Just before the Line:
problemsList.insert(selProblem, nProblem);
selProb: 0
nProblem:
ProbResultsNames: "NewRow0"
ProbResultsType: "Real"
problemsList.value(selProblem):
ProbResultsNames: non-existent
ProbResultsType: non-existent
After the line
problemsList.insert(selProblem, nProblem);
selProb: 0
nProblem:
ProbResultsNames: "NewRow0"
ProbResultsType: "Real"
problemsList.value(selProblem):
ProbResultsNames: non-existent
ProbResultsType: non-existent
EDIT 2:
class ProblemSets
{
public:
ProblemSets();
virtual ~ProblemSets();
ProblemSets(const ProblemSets& other);
ProblemSets& operator=(const ProblemSets& other);
//I hid getters and setters to avoid pollution on the post
private:
int index;
bool usingBenchmark;
QString functionSelected;
QString info;
QMap<int, QString> probVars_name, probVars_type, probResultsNames, probResultsTypes;
QMap<int, float> probVars_min, probVars_max;
QMap<int, int> probVars_stpSize, probVars_stp;
int varsNumber; // holds how many vars has been created, just for display purposes
int resNumber; // holds how many results has been created, just for display purposes
};
A simple test proves that QMap works as expected:
QMap<int, QString> mm;
mm.insert(1, "Test1");
qDebug() << mm[1]; // "Test1"
mm.remove(1);
qDebug() << mm[1]; // "" (default constructed value)
mm.insert(1, "Test2");
qDebug() << mm[1]; // "Test2"
Which means that the problem lies in your code.
This statement itself is highly suspicious:
That last line appears to be doing nothing!
Because then you go on to say that the map still contains the "old value". But you removed that key, so if the insert() method didn't work, you shouldn't be getting the old value, but a default constructed value.
Which means that the problem is most likely that nProblem has the same value as the one that is previously associated to that key in the map. The map works, you values are likely wrong.
Found the issue! I didn't have both the variables declared on the copy method of the ProblemSets class.
Solved simply adding them to the copy method
MainWindow::ProblemSets::ProblemSets(const ProblemSets& other)
{
// copy
index = other.index;
usingBenchmark = other.usingBenchmark;
functionSelected = other.functionSelected;
info = other.info;
probVars_name = other.probVars_name;
probVars_type = other.probVars_type;
probVars_min = other.probVars_min;
probVars_max = other.probVars_max;
probVars_stpSize = other.probVars_stpSize;
probVars_stp = other.probVars_stp;
//here
probResultsNames = other.probResultsNames;
probResultsTypes = other.probResultsTypes;
//
varsNumber = other.varsNumber;
resNumber = other.resNumber;
}
I had this issue before with the std::vector class, and that's why I suspected that could be that. Thanks to everyone that helped!
I have a SQL model that connects to a single table, this table will change the number of columns depending on certain conditions during the execution of the program. The model is connected to a QTableView.
I have a function that controls the number of columns at the end of the function i have a call to model->select(), to update the information of the model and tableView->reset(), to what i thought would rearrange the view adding or taking away columns.
The problem is that the view does not change from the original number of columns that it had. If i reduce the number i can see that the data change and show empty on the missing columns. Is there a command for the tableView to resize it self?
Editing the question
in the constructor of the class i'm reading the table and setting it to the view:
header = new QSqlTableModel(parent,data->m_db);
header->setTable("C"+QString::number(markTime.toSecsSinceEpoch())+"T");
header->select();
ui->heading->setModel(header);
ui->heading->show();
Every time that that the number of columns is changed is an SQL procedure to change the number of columns:
void ImportProcess::copyTable(QString oldTable, QString newTable)
{
QSqlQuery queryOld, queryNew;
queryOld.prepare("select * from :oldTable");
queryOld.bindValue(":oldTable",oldTable);
queryOld.exec();
if(queryOld.record().isEmpty()==true) return; //Old table was empty, nothing to copy
int oldColumn=queryOld.record().count();
QString replaceLine="insert into "+newTable+" values(";
while(queryOld.next()==true)
{
replaceLine.append(QString::number(queryOld.value(0).toInt()));
replaceLine.append(", "+queryOld.value(1).toString());
for(int y=0;y<(oldColumn < ui->columns->value() ? oldColumn : ui->columns->value());y++)
{
replaceLine.append(", "+QString::number(queryOld.value(y+2).toFloat()));
}
replaceLine.append(")");
queryNew.exec(replaceLine);
}
}
Then the header file is updated, and here is where I thought that the tableview will be redrawn:
void ImportProcess::updateHeadingTable()
{
QSqlQuery query;
query.exec("delete from C"+QString::number(markTime.toSecsSinceEpoch())+"T");
QString description= ui->Week->isChecked() == true ? "Week" : "Size";
query.exec("insert into C"+QString::number(markTime.toSecsSinceEpoch())+"T (id, description) values (101, '"+description+"')");
for(int x=0;x<ui->columns->value();x++)
{
query.exec("update C"+QString::number(markTime.toSecsSinceEpoch())+"T set col"+QString::number(x)+" = '30'");
}
header->select();
ui->heading->reset();
}
I believe you forgot about some protected methods:
void QAbstractItemModel::beginInsertColumns(const QModelIndex &parent, int first, int last);
void QAbstractItemModel::beginRemoveColumns(const QModelIndex &parent, int first, int last);
void QAbstractItemModel::endInsertColumns();
void QAbstractItemModel::endRemoveColumns();
Every time the number of column about to be change you should call first or second method. After change you should call third or fours method.
You can read about these methods in Qt documentation.
During runtime I have inserted QCombobox in my QTreeWidget like this:
//global defines
#define COLUMN_1 (0)
#define COLUMN_2 (1)
//Init QComboBox to QTreeWidget - works fine.
QTreeWidgetItem *item = new QTreeWidgetItem(_myTreeWidget);
item->setText(COLUMN_1,"testing");
QComboBox *box = new QComboBox();
box->addItem("select1");
box->addItem("select2");
box->addItem("select3");
_myTreeWidget->setItemWidget(item, 1, box);
The above code works, but I also want to read the data text in these columns. Eg. get the strings "testing" & "select2" from code above. The problem is that I can't figure out how to read the "QComboBox::currentText()" in the comboboxes.
I have tried:
QTreeWidgetItemIterator it(_myTreeWidget);
while(*it)
{
QTreeWidgetItem *item = *it;
QVariant first = item->text(COLUMN_1);
QString firstStr = loggerName.toString(); //this works
QComboBox *box = (QComboBox*)item->data(COLUMN_2, 0);
QString boxValStr = box->text().toString(); //this doesn't works, always empty string
//... more code to handle strings...
it++;
}
Feels like the "item->data(COLUMN_2, 0)" is wrong way to go cause it returns a QVariant.
Solution on this problem?
QComboBox *box = (QComboBox*)item->data(COLUMN_2, 0);
When I read this code, I went into panic mode. Look at the signature:
QVariant QTreeWidgetItem::data ( int column, int role ) const
As you used setItemWidget, you should probably use
QWidget * QTreeWidget::itemWidget ( QTreeWidgetItem * item, int column ) const
ps: If you want to cast, use C++ casts. Much better, use qobject_cast<SubtypeofQObjectPtr> for QObject. It returns null when the cast is invalid.
Indeed, I mean retrieve the combobox using a call similar to :
QComboBox* box = qobject_cast<QComboBox*>(treeWidget->itemWidget(item, column));
Solved it thanks to the help from #Umnyobe and #Zaiborg above. Here is a total working example:
Init QTreeWidget with text in column1 and QComboBox in column2:
//global defines
#define COLUMN_1 (0)
#define COLUMN_2 (1)
QTreeWidgetItem *item = new QTreeWidgetItem(_myTreeWidgetPtr);//item to put in tree
item->setText(COLUMN_1,"animal"); //item for column 1 in the tree.
QComboBox *box = new QComboBox();
box->addItem("mouse"); //adds selections for comboboxes
box->addItem("cat");
box->addItem("dog");
_myTreeWidgetPtr->setItemWidget(item, COLUMN_2, box); //insert items in tree.
Read values from tree:
QTreeWidgetItemIterator it(_myTreeWidgetPtr);
while(*it)
{
QTreeWidgetItem *item = *it;
//Init pointer to current combobox
QComboBox* box = qobject_cast<QComboBox*>(_myTreeWidgetPtr->itemWidget(item, COLUMN_2));
//Get data from QTreeWidget
QString col1Str = item->text(COLUMN_LOGGER);
QString col2Str = box->currentText();
it++;
}
hope it can help someone :)
use the QSignalMapper class to collect the different boxes in the treewidget.
then connect the QSignalMapper::mapped() signal to some slot and use the combobox
edit:
QSignalMapper* mapper = new QSignalMapper(this);
QComboBox *box = new QComboBox();
connect( box, SLOT(/*whatever*/), mapper, SLOT( map() ) );
mapper->setMapping( box );
myTreeWidget->setItemWidget(item, 1, comboBox);
For anyone who is looking for a Python solution,
(PySide / PyQt QComboBox in QTreeWidget), here is it:
item = QTreeWidgetItem(self.treeWidgetAnimals)
item.setText(0, "animal")
combo_box = QComboBox()
combo_box.addItem('mouse')
combo_box.addItem('cat')
combo_box.addItem('dog')
self.treeWidgetAnimals.setItemWidget(item, 1, combo_box)
I was looking for hours but no other forum like pass reference "parent" like a "delegation":
item = QTreeWidgetItem (self.myTreeWidgetItemObject)
if you do not pass the parent, error ir not returned but the ComboBox not appears in display TreeWidget.
I used Qt Creator to make a "keyboard" window with sixty QPushButtons and one QLineEdit. How can I make the buttons to add characters into QLineEdit text box? If I press a QPushButton with the label 'Q' on it, I want the program to add the Unicode character 'Q' on the text box.
One way to do this would be to just connect the 'clicked' signal from all the buttons to a slot, and then handle the adding of the character there.
For example, if the all keyboard buttons are inside a layout called 'buttonLayout', in your MainWindow constructor you can do this:
for (int i = 0; i < ui->buttonLayout->count(); ++i)
{
QWidget* widget = ui->buttonLayout->itemAt( i )->widget();
QPushButton* button = qobject_cast<QPushButton*>( widget );
if ( button )
{
connect( button, SIGNAL(clicked()), this, SLOT(keyboardButtonPressed()) );
}
}
Then in the slot implementation, you can use QObject::sender(), which returns the object that sent the signal:
void MainWindow::keyboardButtonPressed()
{
QPushButton* button = qobject_cast<QPushButton*>( sender() );
if ( button )
{
ui->lineEdit->insert( button->text() );
}
}
OPTION 1 - Multiple signals and slots
Connect all pushbuttons clicked() signal to a slot
// Let button01 be the A
connect(ui->button01, SIGNAL(clicked()), this, SLOT(buttonClicked()));
...
// Let button 60 be the Q
connect(ui->button60, SIGNAL(clicked()), this, SLOT(buttonClicked()));
In the buttonClicked() slot you have to figure out which button was clicked and append the corresponding letter to the line edit.
void buttonClicked()
{
QObject* callingButton = QObject::sender();
if (callingButton == button01)
ui->lineEdit->setText(ui->lineEdit->text()+ "A");
...
else if (callingButton == button60)
ui->lineEdit->setText(ui->lineEdit->text()+ "Q");
}
OPTION 2 - Subclass QPushButton
You could subclass QPushButton in order to avoid the multiple ifs. In your subclass just catch the mouse release event and emit a new signal which will contain the button's text
void KeyboardButton::mouseReleaseEvent(QMouseEvent* event)
{
emit clicked(buttonLetter); // Where button letter a variable of every item of your subclass
}
Similarly connect the clicked(QString) signal with a slot
connect(ui->button01, SIGNAL(clicked(QString)), this, SLOT(buttonClicked(QString)));
...
connect(ui->button60, SIGNAL(clicked(QString)), this, SLOT(buttonClicked(QString)));
void buttonClicked(QString t)
{
ui->lineEdit->setText(ui->lineEdit->text()+ t);
}
I have created an application with a similar issue, trying to convert the qpushbutton text to the qlineedit itself. The key is how you initialize the buttons and to use polymorphism in your function. To create an emit signal wont work for individual characters. The .digitValue will work if the case if for numerics (which the buttons would be of type int), but qt doesnt have a character value (I should say after 6hrs of reading qt doc and another 4 of trying different combinations it would not work), I think it has to do with how many bits it takes to store each variable type in an array. I even tried converting the button->text to QString to use with the emit function as a signal prototyped.
I do not know what your button layout is, but I will give you a synopsis of what I did. I first created a global, static const char array containing all the letters needed e.g.
static const char vowelarray[] = "AEIOU";
Then initialized the QPushButtons with in the MainWindow function, using iteration, setting a for loop's terminating condition equal to the size char array (in your case 60?). This all depends on your button layout though. I personally created a void function (setLocation) for the button->setGeometry of each button and iterated the setGeometry, and then passed the function to the MainWindow Function, at end of fucntion. The following code was used to initialize the buttons, connect signals to slots, and use polymorphism to connect to lineedit.
for (int i = 0; i < 26; i++){
characterButton[i] = new QPushButton(chararry[i], this); `
characterButton[i] -> setStyleSheet("QPushButton{background: grey; color: brown}");
connect(characterButton[i],SIGNAL(released(),this,SLOT(characterPushed()));
}
setLocation();
Then created a void function (e.g. void MainWindow::characterPuched()) where the following code was used:
void MainWindow::characterPushed(){
QPushButton *characterButton = (QPushButton*) sender();
if (characterButton )
{
lineEdit -> setText(letters.insert(letters.size(), characterButton -> text()));
}
lineEdit -> setText(letters);
}
of course letters was a global variable as well as:
QString letters = "";
and of course the QPushButtons and the function were prototype in the header file as a private variables and slots, e.g.
private:
QPushButton *characterButton[26];
the variable 'letters' was used to extract and input text to and from the line edit for further functions throughout the application.
Best Luck!!``