I want to associate additional data with each QTableWidgetItem inserted into the table, in order to use that data in future, when it is being clicked on a table item. But that data should not be visible. How can I do that?
You can use QTableWidgetItem::setData() like so:
setData(Qt::UserRole, myData); // set
Where myData is a supported QVariant type. You can use QTableWidgetItem::data() to retrieve the value that you store.
If you need more than one you can use Qt::UserRole + 1, + 2, and so on (Qt::UserRole is "The first role that can be used for application-specific purposes.", you can read more about the other types of roles here).
If you're storing a custom type that isn't natively supported by QVariant you will need to register your type with the Qt meta-object system. Look at QMetaType for more details on that.
If you wanted to store an integer, for example:
QTableWidgetItem* widgetItem = tableWidget->item(row, col); // get the item at row, col
int myInteger = 42;
widgetItem->setData(Qt::UserRole, myInteger);
// ...
myInteger = widgetItem->data(Qt::UserRole);
You could derive from QTableItem and provide your own data member, or you could use the QTableView with your own model.
Related
I am using a QCompleter on line edit to get some text. The completer functionality is as such working fine.
The QCompleter is fetching data from Sql Table.
completer = new QCompleter(this);
model = new QSqlRelationalTableModel(this, db);
model->setTable("product");
model->select();
completer->setModel(model);
completer->setCompletionColumn(1); // points to "name" in product table
ui->line_edit->setCompleter(completer);
now on line_edit_returnPressed(), I am able to get the selected text. Is it further possible to get the primary key / row index in Sql Table for the currect selection made from "QCompleter" ?
I see that ui->line_edit->completer()->currentRow(); always return 0.
I am just trying to save one SQL query thats all.
I have to acknowledge #Pavel Strakhov comments, thanks. Had it been put up as answer, I would have accepted it.
The whole time I was using QCompleter::currentIndex with the sql table model I had set with QCompleter::setModel(). I dont know how QCompleter works but I believe it internally derives a list model from the input table model.
From documentation -
QAbstractItemModel* QCompleter::completionModel()
Returns the completion model. The completion model is a read-only list model that contains all the possible matches for the current completion prefix. The completion model is auto-updated to reflect the current completions.
So now my SLOT looks like this -
void MainWindow::on_line_edit_returnPressed()
{
QModelIndex index = ui->le_filter->completer()->currentIndex();
if (index.isValid()) {
int row = index.row();
int key = completer->completionModel()->index(row, 0).data().toInt();
qDebug() << key;
}
}
I am using a QTableView to display user activity in my application.
My model contains four columns, each column displays a different type of text like:
username in the 1st column
user activity in the 2nd column
details of activity in the 3rd column
I want to display both the text of 2nd and 3rd columns in a single column with a different text color separated with a "-".
My application currently looks like this:
However, I want it to look similar to this
Can someone please help me to solve this out, thanks in advance
I would approach to this topic in two steps:
change model in such way that 2nd and 3rd columns are a single column but value from old 2nd column is returned as Qt:DisplayRole (standard way) and value from old 3rd column is returned for Qt::SomeUserRole
Add delegate to table view which will handle visualization of merged columns and display item in "gmail" style. Values for visualization are fetched form model using respective role values from previous step.
You can also treat the whole thing as a list with lots of different data roles: each row as a single item (this could be handled very nicely in qml).
You can override data method of your model and return custom color with Qt::ForegroundRole for necessary columns.
But if you like "gmail" visualisation - than you should create your own delegate (as proposed by #Marek). You may use QTextDocument for advanced text rendering. Pseudo-code:
void QStyledItemDelegate::paint( QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
painter->save();
const QString title = index.model()->data( YourTitleRoleId ).toString();
const QString content = index.model()->data( YourContentRoleId ).toString();
// Use any qt-supported html tags
const QString html = QString( "<html><b>%1</b> - <i>%2</i></html>" ).arg( title ).arg( content );
QTextDocument doc;
doc.setHtml( html );
QRectF rc( option.rect );
doc.drawContents( painter, rc );
painter->restore();
}
Feel free to ask, if something is not clear.
I started to learn Qt, and I would like to implement a table filled with data via QTableView. My problem is, that I don't know how to remove the checkboxes from the cells. It seems like they are put in by default.
However, I read that I had to return a NULL-QVariant, but that's not what I was looking for as I still have data to put in.
That's my code so far:
QVariant MyModel::data(const QModelIndex &index, int role) const
{
int row = index.row();
int col = index.column();
QString daten;
switch (col)
{
case 0:
{
daten = "column 1";
break;
}
case 1:
{
daten = "column 2";
break;
}
case 2:
{
daten = "column 3";
break;
}
case 3:
{
daten = "column 4";
break;
}
}
return daten;
}
Now, as you can see, I want to fill the cell with the QString called "daten". But next to the String there is a Checkbox in every cell.
Does somebody know how to remove the checkbox but still fill the content with "daten"?
Thanks!
The fact that the cells in your QTableView have some checkbox hint that they were defined as user-checkable. Check whether you don't have a Qt.ItemIsUserCheckable flag activated somewhere in the definition of your QTableView, and if that's the case, deactivate it. You could try to modify the flags method, for example, forcing every entry not to be checkable
As an additional comment, you should probably modify your ::data method to take into account the case where index is invalid and to return some value only if the role corresponds to Qt.DisplayRole. In Python, the syntax would be
if index.isvalid():
if (role == Qt.DisplayRole):
(row, col) = (index.row(), index.column()
return_something_depending_on_col
return QVariant()
return QVariant()
That way, you cover the case of an invalid index, your code would likely crash otherwise.
The test on role allows you to choose which type of data you want to access. The documentation states for example that:
Each item in the model has a set of data elements associated with it, each with its own role. The roles are used by the view to indicate to the model which type of data it needs. Custom models should return data in these types.
The basic role is Qt.DisplayRole, where you return the QString corresponding to your current cell. You could also return a QBrush for painting the background if your role is Qt.BackgroundRole...
While not mandatory, these tests on role are still highly encouraged: it makes your code cleaner and easier to maintain.
Say for example if I have a business entity -> Customer, which has customerId, customerName and customerType. I have created an asp:Hidden Variable hdnCustomer to runat="server"
If I wanted to serialize the value of the customer business entity (in the code behind) to the hdnCustomer then how would I do that? Also once serialized how would I deserialize it?
// Pseudo code
Collection<Customer> customerList = new Collection<Customer>();
customerList = BusinessAccess.GetCustomerList();
hdnCustomer = serialize and assign the value of 'customerList' to hdnCustomer;
...
...
// Later on a select index change of one of the drop down lists
Inside the event handler for the drop down list:
{
Collection<Customer> customerList = new Collection<Customer>();
customerList = deserialize the value from hdnCustomer
int a = Convert.ToInt32(ddlDropDown.SelectedValue);
foreach(a in customerList)
{
// Do something
}
}
You can serialise to and from XML using XmlSerializer:
http://support.microsoft.com/kb/815813
However, if you just store the object in the ViewState[] collection that should work better:
ViewState["Customer"] = customerList;
It does the same thing: store the serialisable object in the page, hidden from the user: but it won't be in a human-readable format.
(edit: To deserialise, just get the value of ViewState["Customer"], checking for a null before using it!)
edit 2: a useful link about storing objects in ViewState:
http://www.beansoftware.com/ASP.NET-Tutorials/ViewState-In-ASP.NET.aspx
Hope that helps.
I think .net has already providing some classes to do so, look at this example
I have a script that parses some complex XML. When the XML element is of a certain type, it generates a comboBox using the XML element's children to populate the box. I then want to check all of the values of the all the generated ComboBoxes against their correct answers (which is also info stored in the XML file). When creating the ComboBoxes, I added an "id" property. However, it seems that I cannot them use:
dynamicQuestion.id.selectedItem.labelField
to check the answers. However, I am able to get the labelField if I know the variable name used to create the ComboBox.
dynamicQuestion.selectedItem.labelField
This indicates (to me) that I need to dynamically generate the variable name as I'm creating new instances of the ComboBox. But how do I dynamically generate a variable name? If I use
var thisBox:String = "box"+boxCount;
var newBox:ComboBox = thisBox as ComboBox;
I get an implicit coercion error. I also tried changing the creation statement to a function that accepted an argument, "thisBox," but this didn't work either. Conceptually, this seems quite simple, but I'm having a hard time putting it to practice. It seems that the comboBox's id is what is generated by created the box using script (e.g., var thisBox). How do I dynamically generate this name?
Use an array as Stefan suggested. If you must use string identifiers, you can create an object and use it as an associative array.
var combos:Object = {};
var boxCount:Number = 1;
var thisBox:String = "box"+boxCount;
//you can store comboboxes in the object using the following syntax
combos[thisBox] = new ComboBox();
//or
combos.box2 = new ComboBox();
//or
combos["box3"] = new ComboBox();
trace(combos.box1.selectedItem.labelField);
trace(combos.box2.selectedItem.labelField);
trace(combos.box3.selectedItem.labelField);
Why don't you store all your dynamically created combo boxes in an array? When you want to evaluate them you iterate over the array and access selectedItem.labelField.