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.
Related
so, I encountered a little problem and I am kinda stuck.
Basically I am trying to pass the value of a string** in C-type form to a char* string
The code is as follows:
static int BuildDBListSql( std::string **SqlBuf,
const char* ColumnNames,
const char* TableNames,
const char* CmdText,
sUINT Mode)
{
int rtnval = sSUCCESS;
const char * testSql = ( Mode & 02 ) ? ColumnNames : CmdText;
if ( SU_DbControl::DbCreateTradeTempTables(testSql) != sSUCCESS )
{
sLogMessage("Problem with temporary table results", sLOG_ERROR, 0);
return( sERROR );
}
if ( Mode & 02 )
{
*SqlBuf = new std::string[strlen(ColumnNames) + SQL_MAX_SELECT*40];
*SqlBuf = &std::string(ColumnNames);
if ( !( Mode & 010 ) )
{
// Attach State/Retrieval SQL.
char* SqlBufcopy = (*SqlBuf)->c_str();
sSQLInsertStateAndRetrieval( sDbConvertMode( Mode ), SqlBufcopy);
}
}
// SQL fragments are being passed:
else
{
size_t sqlBufLength = 0;
if ( Mode & 010 )
{
sqlBufLength = strlen(ColumnNames) + strlen(TableNames) + strlen(CmdText) + SQL_MAX_SELECT;
*SqlBuf = new std::string[ sqlBufLength ];
//sprintf( *SqlBuf, "SELECT %s FROM %s %s ",
*SqlBuf = fmt::format("SELECT {} FROM {} {} ", ColumnNames, TableNames, CmdText); // ColumnNames, TableNames, CmdText );
}
else
{
std::string *sqlPtr = new char[strlen(CmdText) + 2*SQL_MAX_SELECT];
strcpy( sqlPtr, CmdText );
sSQLSpecializeWhereClause( TableNames, sqlPtr );
sqlBufLength = strlen(ColumnNames) + strlen(TableNames) + SQL_MAX_SELECT;
sqlBufLength += strchr(TableNames, ',') ? strlen(CmdText) : strlen(sqlPtr);
*SqlBuf = new char[ sqlBufLength ];
sprintf( *SqlBuf, "SELECT %s From %s %s",
ColumnNames,
TableNames,
strchr( TableNames, ',' ) ? CmdText : sqlPtr );
delete [] sqlPtr;
// Attach State/Retrieval SQL
rtnval = sSQLInsertStateAndRetrieval( sDbConvertMode( Mode ),
*SqlBuf );
}
}
if (Mode & 0100)
{
char * tempBuf = sEntitySQLToDbSQL(*SqlBuf);
if( tempBuf )
{
delete [] *SqlBuf;
*SqlBuf = new char[ strlen(tempBuf) + 1];
strcpy(*SqlBuf, tempBuf);
}
else
{
sLogMessage("Error in sEntitySQLToDbSQL", sLOG_ERROR, 0);
return( sERROR );
}
}
return rtnval;
}
i get this error when running the solution: related to this line of code char* SqlBufcopy = (*SqlBuf)->c_str();
left of '.c_str' must have class/struct/union, type is std::string**
I kinda understand that the error is there due to me trying to get a c-type string out of a pointer, but I dont know the correct syntax to do what i want to do.
I tried with
char *SqlBufcopy = *SqlBuf.c_str()
also with
char *SqlBufcopy = *SqlBuf->c_str()
and it didnt work, help pls
To fix the error you ask about, change char *SqlBufcopy = *SqlBuf.c_str(); to
char *SqlBufcopy = (*SqlBuf)->c_str();
Reason: SqlBuf is pointer to pointer (which makes no sense at all), so to get to the actual object, you need to dereference it twice.
Code related to text encoding:
const char* toCode128C( const char* texto ) {
int tamanhoTexto = strlen( texto );
int tamanhoComando = strlen( "{C" ) + tamanhoTexto;
char* printerCodBarras = new char[ tamanhoComando ];
memcpy( printerCodBarras, "{C", tamanhoComando );
for ( int i = 0; i < tamanhoTexto; i += 2 ) {
int num = QString( texto ).mid( i, 2 ).toInt();
QString vl = QString( static_cast<char>( num ) );
strncat( printerCodBarras, vl.toStdString().c_str(), 1 );
}
return printerCodBarras;
}
Encoding occurs successfully, except when it contains a "00" for example code 59900001, the transformation occurs from two characters to two characters, or error occurs when encoding the value "00", thus making the (00) is not printed.
I am really confused on how to pass a 2-dimensional QVariantList from C++ to QML, I basically want to pass a value from C++ which will do the same as assigning it in QML like this:
property var twoDim: [["1-1", "1-2"],["2-1", "2-2"]]
So that I can use the array as a model in a Repeater element by doing: modelData[0] which will return 1st array of values, and modelData[1] which will return 2nd array of values. Names and surnames for example...
Please help
Firstly you can have a QVariantList of QVariantLists:
// main.cpp
int main( int argc, char* argv[] )
{
QGuiApplication app( argc, argv );
auto myList = QVariantList{};
for ( auto i = 0; i < 2; ++i ) {
myList << QVariant::fromValue(
QVariantList{ QString::number( i + 1 ) + "-1",
QString::number( i + 1 ) + "-2" } );
}
auto view = QQuickView{};
view.rootContext()->setContextProperty( "myList", myList );
view.setSource( QUrl{ QStringLiteral{ "qrc:/QmlCppTest.qml" } } );
view.show();
return app.exec();
}
// QmlCppTest.qml
import QtQuick 2.3
Item {
property var listOfLists: myList
Component.onCompleted: {
for ( var i = 0; i < listOfLists.length; ++i ) {
for ( var j = 0; j < listOfLists[i].length; ++j ) {
print( i, j, listOfLists[i][j] );
}
}
}
}
Results in:
qml: 0 0 1-1
qml: 0 1 1-2
qml: 1 0 2-1
qml: 1 1 2-2
But like I said in my comment, if your first dimension represents an entity, and the second dimension represents properties of that entity, the superior approach for performance and maintenance reasons is to use QAbstractItemModel (or one of it's more specific derived classes).
Qt's documentation has lots of stuff on MVC programming, you should take some time to learn the subject as it underpins much of Qt.
I'm currently loading an MD5 model for testing out animations using ASSIMP (from the following tutorial: http://ogldev.atspace.co.uk/www/tutorial38/tutorial38.html).
So far, everything seems to load just fine (static model renders fine), but for some reason the nodes in Assimp do not display bone names. The names of each node is <MD5_Root> or <MD5_Mesh> and not any of the bone names it should display.
The following is a snippet from the code that checks for all the bone names in ASSIMP with the node Name. Never reaching the point where the string becomes "HOI". nodeName should become a bone name like 'pubis' or 'upperarm.L'.
void MeshLoader::ReadNodeHeirarchy(float AnimationTime, const aiNode* pNode, const aiMatrix4x4 ParentTransform)
{
string nodeName = pNode->mName.data;
const aiAnimation* pAnimation = m_pScene->mAnimations[0]; // Update from here if you want different animations! :O
aiMatrix4x4 nodeTransformation(pNode->mTransformation);
const aiNodeAnim* pNodeAnim = FindNodeAnim(pAnimation, nodeName);
if(nodeName != "<MD5_Root>" && nodeName != "<MD5_Mesh>")
nodeName = "HOI";
...
}
const aiNodeAnim* MeshLoader::FindNodeAnim(const aiAnimation* pAnimation, const string NodeName)
{
for (unsigned int i = 0 ; i < pAnimation->mNumChannels ; i++)
{
const aiNodeAnim* pNodeAnim = pAnimation->mChannels[i];
if (string(pNodeAnim->mNodeName.data) == NodeName)
return pNodeAnim;
}
return NULL;
}
Also, a piece of the .MD5 file, which might show something usefull.
MD5Version 10
commandline ""
numJoints 33
numMeshes 6
joints {
"origin" -1 ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000000 0.707107 ) //
"sheath" 0 ( 11.004813 -3.177138 31.702473 ) ( 0.307041 -0.578614 0.354181 ) // origin
"sword" 1 ( 9.809593 -9.361549 40.753730 ) ( 0.305557 -0.578155 0.353505 ) // sheath
"pubis" 0 ( 0.014076 2.064442 26.144581 ) ( -0.466932 -0.531013 -0.466932 ) // origin
"pelvis" 3 ( 0.014076 2.592741 30.241238 ) ( -0.535591 -0.462288 -0.534983 ) // pubis
"spine" 4 ( 0.023039 1.427001 38.133138 ) ( -0.499998 -0.500002 -0.499998 ) // pelvis
"neck" 5 ( 0.023039 1.427122 51.620732 ) ( -0.643897 -0.292228 -0.643896 ) // spine
"head" 6 ( 0.023047 -1.828043 55.341849 ) ( -0.707074 -0.007564 -0.707059 ) // neck
"upperarm.L" 5 ( -7.999740 4.449851 48.597286 ) ( -0.000001 -0.000001 -0.716595 ) // spine
"forearm.L" 8 ( -20.905890 4.101032 48.597330 ) ( -0.000001 -0.000001 -0.746270 ) // upperarm.L
"wrist.L" 9 ( -32.023143 2.795714 48.607747 ) ( 0.009625 0.009713 -0.703812 ) // forearm.L
...
}
mesh {
shader "....OpenGL/Resources/Objects/Bob/guard1_body.png"
numverts 494
vert 0 ( 0.394531 0.513672 ) 0 1
vert 1 ( 0.447266 0.449219 ) 1 2
vert 2 ( 0.453125 0.517578 ) 3 1
...
}
For some reason it's not loading the names correctly or maybe it's an error in the MD5 file itself?
I found the solution to my problem. Appareantly the issue was not in the name section of ASSIMP or the file itself. It was an issue with a loop counter somewhere in the Mesh Loading code for the child traversel of each node. It was currently only traversing the 1st node of all the node's children, so it wouldn't move on to the bone nodes.
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.