QAbstractItemModel + ModelTest::rowsInserted ASSERTion problem - c++

I'm trying to debug my model (QAbstractItemModel) with ModelTest. And I can't understand one assertion.
There are two slots in ModelTest that intercept signals generated by my model.
ModelTest::rowsAboutToBeInserted
ModelTest::rowsInserted
Slot/function 1 looks like this
void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int end )
{
Changing c;
// ...
c.last = model->data ( model->index ( start - 1, 0, parent ) );
c.next = model->data ( model->index ( start, 0, parent ) );
insert.push ( c );
}
And slot 2 looks like this
void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end )
{
Changing c = insert.pop();
// other asserts ...
(*) Q_ASSERT ( c.next == model->data ( model->index ( end + 1, 0, c.parent ) ) );
}
I don't understand dla last assertion (*). Lets assume that in my app I add 1 row.
This row is the only row that is stored in my model. So the row number would be 0.
In my model before adding the row I call
beginInsertRows(parentIndex, 0, 0);
So why does modeltest require
model->data ( model->index ( start, 0, parent ) )
to be equal to
model->data ( model->index ( end + 1, 0, c.parent ) )
What am I missing here ? Please help :)

The idea behind this assert is to check if first row after added ones was correctly moved. If there are some rows after inserted ones, then their data are compared. If there aren't any, your model should both in the line
c.next = model->data ( model->index ( start, 0, parent ) );
and in
Q_ASSERT ( c.next == model->data ( model->index ( end + 1, 0, c.parent ) ) );
should return invalid (empty) QVariant. If both return empty QVariant (as they should) assertion succedes, thus providing some level of error-checking even in case of no rows after currently inserted.

Related

ImGui slowing down when using cpr

So I am trying to make a changelogs sort of thing
auto request = cpr::Post (
cpr::Url{ "http://leoservices.xyz/pchangelogs.php" }
);
auto response = request.text.c_str ( );
sprintf_s ( G->changelogsBuffer , "Changelogs: %s" , response );
ImGui::InputTextMultiline ( "##Change Logs" , G->changelogsBuffer , sizeof ( G->changelogsBuffer ) , ImVec2 ( ImGui::GetContentRegionAvail ( ).x - 10 , ImGui::GetContentRegionAvail ( ).y - 58 ) , ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoMarkEdited );
This is the current code but when I got to this tab it just starts laggin' is their something I am doing wrong?

Need to save product twice to have auto tag updated correctly

Thanks to 7uc1f3r, I was able to programatically assign tags to products based on their stock status. Link here
However, I have run into an issue. There is no error. At times, I have to save the product twice for the correct tag to reflect. I have tried the code using else & elseif but the issue persists. If someone could guide me to use switch case, I can try that & see if the tags get assigned correctly on the first save. Alternatively, if there is information on why this would occur & possible remedies, please let me know. Looks like the product is in the process of saving in the backend & the tag gets assigned prior to that but I don't know for sure. Please advise.
add_action( 'woocommerce_admin_process_product_object', 'mycode_woocommerce_stockstatus_tag', 10, 1 );
function mycode_woocommerce_stockstatus_tag( $product ) {
if( !$product->is_in_stock() ) {
$product->set_tag_ids( array (113) );
}
elseif( $product->is_on_backorder(1) ) {
$product->set_tag_ids( array (111) );
}
elseif( $product->is_in_stock() && !$product->is_on_backorder(1) ) {
$product->set_tag_ids( array (112) );
}
}
I am also posting a variant of the code where I split out where stock is being managed or not. The if statements here are independent & appear to do a better job. However, I still request if someone could pitch in & help with switch case as I believe it will execute faster.
add_action( 'woocommerce_admin_process_product_object', 'mycode_woocommerce_stockstatus_tag', 10, 1 );
function mycode_woocommerce_stockstatus_tag( $product ) {
if( $product->managing_stock() && ( $product->get_stock_quantity() > 0 ) ) {
$product->set_tag_ids( array (112) );
}
if( $product->managing_stock() && ( $product->get_stock_quantity() <= 0 ) && ( $product->backorders_allowed() || $product->backorders_require_notification() ) ) {
$product->set_tag_ids( array (111) );
}
if( $product->managing_stock() && ( $product->get_stock_quantity() <= 0 ) && !$product->backorders_allowed() && !$product->backorders_require_notification() ) {
$product->set_tag_ids( array (113) );
}
if( !$product->managing_stock() && $product->is_in_stock() && !$product->is_on_backorder(1) ) {
$product->set_tag_ids( array (112) );
}
if( !$product->managing_stock() && $product->is_on_backorder(1) ) {
$product->set_tag_ids( array (111) );
}
if( !$product->managing_stock() && !$product->is_in_stock() ) {
$product->set_tag_ids( array (113) );
}
}

How to pass QString or QStringList to QTableWidgetItem

I am trying to create a table using QTableView and QTableWidgetItem.
Basically I am trying to create a few rows with some name under first Header.
But the problem is I am passing each row with some name.
Same thing I want to achieve using QString, QStringList array.
Currently I am not passing any value under second header.
Please suggest how to do that. Please find the output window.
Below is my code snippet:
#include <QApplication>
#include <QtGui>
#include <QMainWindow>
#include <QTableWidget>
#include <QString>
#define ROW_NUMBER 20
#define COL_NUMBER 2
int main(int argc , char **argv)
{
QApplication app(argc,argv);
QMainWindow *window = new QMainWindow();
window->setWindowTitle(QString::fromUtf8("TableWidget Resize column width"));
window->resize(200,250);
QTableWidget *table = new QTableWidget();
table->setRowCount(ROW_NUMBER);
table->setColumnCount(COL_NUMBER);
table->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
table->setHorizontalHeaderLabels(QString("Field;Value").split(";"));
table->setItem(0,0,new QTableWidgetItem("Sequence Number"));
table->setItem(1,0,new QTableWidgetItem("Date"));
table->setItem(2,0,new QTableWidgetItem("Seconds"));
table->setItem(3,0,new QTableWidgetItem("Source Date"));
table->setItem(4,0,new QTableWidgetItem("Source Time"));
table->setItem(5,0,new QTableWidgetItem("ServiceType"));
table->setItem(6,0,new QTableWidgetItem("Transtype"));
table->setItem(7,0,new QTableWidgetItem("UserId"));
table->setItem(8,0,new QTableWidgetItem("UserIMSI"));
table->setItem(9,0,new QTableWidgetItem("CorrelationId"));
table->setItem(10,0,new QTableWidgetItem("MajorNumber"));
table->setItem(11,0,new QTableWidgetItem("MinorNumber"));
table->setItem(12,0,new QTableWidgetItem("Source Type"));
table->setItem(13,0,new QTableWidgetItem("Total Consume"));
table->setItem(14,0,new QTableWidgetItem("Source Info"));
table->setItem(15,0,new QTableWidgetItem("Event"));
table->setItem(16,0,new QTableWidgetItem("GroupID"));
table->setItem(17,0,new QTableWidgetItem("ServiceID"));
table->setItem(18,0,new QTableWidgetItem("OperatorId"));
table->setItem(19,0,new QTableWidgetItem("Options Array"));
table->resizeColumnsToContents();
window->setCentralWidget(table);
window->show();
return app.exec();
}
QString test;
test = "a";
// First Column
table->setItem(0,0,new QTableWidgetItem(a));
// Second Column
table->setItem(0,1,new QTableWidgetItem(a));
just like that or:
// 100% working example
QVector< QString > string;
QVector< QString > value;
string.append( "Nr1" );
string.append( "Nr2" );
string.append( "Nr3" );
string.append( "Nr4" );
value.append( "1" );
value.append( "2" );
value.append( "3" );
value.append( "4" );
ui->twTable->setSortingEnabled( false );
for( int i = 0 ; i < string.size( ) && i < value.size( ) ; ++i )
{
ui->twTable->insertRow( 0 );
// First Column
ui->twTable->setItem( 0 , 0 , new QTableWidgetItem( string[i] ) );
// Second Column
ui->twTable->setItem( 0 , 1 , new QTableWidgetItem( value[i] ) );
}
ui->twTable->setSortingEnabled( true );
array , QStringList work the same way just without the append.
array:
QString str[5] = { "a" , "b" , "c" , "d" , "e" };
for( int i = 0 ; i < 5 ; ++i )
{
ui->twTable->insertRow( 0 );
// First Column
ui->twTable->setItem( 0 , 0 , new QTableWidgetItem( str[i] ) );
// Second Column
ui->twTable->setItem( 0 , 1 , new QTableWidgetItem( str[i] + QString::number( i ) ) );
}
QStringList:
QStringList str = { "a" , "b" , "c" , "d" , "e" };
for( int i = 0 ; i < 5 ; ++i )
{
ui->twTable->insertRow( 0 );
// First Column
ui->twTable->setItem( 0 , 0 , new QTableWidgetItem( str[i] ) );
// Second Column
ui->twTable->setItem( 0 , 1 , new QTableWidgetItem( str[i] + QString::number( i ) ) );
}
And in reverse order:
// Probably the output you want:
QString str[5] = { "a" , "b" , "c" , "d" , "e" };
for( int i = 4 ; i >= 0 ; --i )
{
ui->twTable->insertRow( 0 );
// First Column
ui->twTable->setItem( 0 , 0 , new QTableWidgetItem( str[i] ) );
// Second Column
ui->twTable->setItem( 0 , 1 , new QTableWidgetItem( str[i] + QString::number( i ) ) );
}
Remove the ui->twTable->insertRow( 0 ) when you're using a fixed amount of rows like you do in your code.
Side note: I tend to disable sorting while inserting items and enabling it after so the rows don't get auto sorted to a different position when you input them.

C++ SQLite3 how to know if select return 0 rows

C++ SQLite3 how to know if select return 0 rows
I have a select statement for SQLite3, how do I know that if after executing the sql statement, the result is 0 rows , no match found etc..
How can i modify my code so that if 0 rows found, it will not execute the part where it put the result into a vector.
My code below:
sqlstatement = "SELECT * from abe_account where department="+quotesql(department)+" AND name="+quotesql(name)+";";
std::vector< std::vector < std:: string > > result;
for( int i = 0; i < 4; i++ )
result.push_back(std::vector< std::string >());
sqlite3_prepare( db, sqlstatement.c_str() , -1, &stmt2, NULL );//preparing the statement
sqlite3_step( stmt2 );//executing the statement
while( sqlite3_column_text( stmt2, 0 ) )
{
for( int i = 0; i < 4; i++ )
result[i].push_back( std::string( (char *)sqlite3_column_text( stmt2, i ) ) );
sqlite3_step( stmt2 );
counter ++;
}
sqlite3_step returns SQLITE_DONE when there are no (more) rows to process:
int stat = sqlite3_step(stmt2);
if (stat == SQLITE_DONE) {
// no rows to process
}
Remember to check for errors as well, e.g.:
if (stat != SQLITE_DONE && stat != SQLITE_ROW) {
// there's probably a problem
}
You can find the complete list of result codes in the manual.
Lastly, you should use the "v2" interface when using SQLite3. From the manual:
The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are recommended for all new programs. The two older interfaces are retained for backwards compatibility, but their use is discouraged.
Do a SQL Count first, if it returns 0 you can just stop execution without needing to query the select statement.

the this pointer set by Object(this) != this

the constructor for my engine constructs audio, video and input objects with a pointer to itself (this). However when I debug, I see all the classes I construct's enginePtr is not the same as the value of this provided by the debugger.
When I peek inside, I see for example, the enginePtr of pRender has different values than the engine. Most of them are set to NULL, which causes rendering to crash.
Here is my engine constructor:
cEngine::cEngine( int flag ) {
if ( !al_get_system_driver() ) {
this->isRunning = true;
al_init();
// Uses DirectX by default, uncomment ALLEGRO_OPENGL for OpenGL.
if ( flag == OPENGL_WINDOW || flag == OPENGL ) al_set_new_display_flags( ALLEGRO_RESIZABLE | ALLEGRO_OPENGL );
else if ( flag == DIRECTX_WINDOW || flag == DIRECTX ) al_set_new_display_flags( ALLEGRO_RESIZABLE );
else if ( flag == OPENGL_FULLSCREEN ) al_set_new_display_flags( ALLEGRO_FULLSCREEN | ALLEGRO_OPENGL );
else if ( flag == DIRECTX_FULLSCREEN ) al_set_new_display_flags( ALLEGRO_FULLSCREEN );
this->display = createDisplay( "Motherload C++", -1, -1, 640, 480 );
srand( ( unsigned ) time(0) );
pCam = new cCam( this );
pIO = new cIO( this );
pMap = new cMap( this, setPoint( 50, 50 ), setPoint( 13, 20 ) ); // 13, 20
pPlayer = new cPlayer( this );
pAudio = new cAudio( this );
pRender = new cRender( this );
pEvents = new cEvents( this );
}
}
cRender constructor:
cRender::cRender( cEngine* pEngine ) {
this->pPlayerLoc = pPlayerLoc;
this->BLACK = al_map_rgb(30, 100, 200);
this->needsRedraw = false;
this->pEngine = pEngine;
al_init_font_addon();
al_init_ttf_addon();
splitImages();
//this->font = al_load_font( "C:/resource/gisha.ttf", 24, 0 );
//this->img = al_load_bitmap( "C:/resource/rock.png" );
}
Thanks
It's very unlikely. Your code seems logically fine to me. Instead or relying on debugger, try to print out the value of 'this' and whatever you stored in pRenderer. Sometimes, with optimization flags debuggers do not show the values of variables properly.