QAbstactTableModel insert at top - qt

I have addFile function in my TableModel class which inserts a new record at the end.
void TableModel::addFile(const QString &path)
{
beginInsertRows(QModelIndex(), list.size(),list.size());
TableItem item;
item.filename = path;
QFile file(path);
item.size = file.size();
item.status = StatusNew;
list << item;
endInsertRows();
}
This function works fine but instead of appending record at the end I would like to insert it at the top. Any pointers on how to update my existing function ?
I have already tried some combinations but there is no Luck.

There are two things that you need to do. First is to adjust the call to beginInsertRows. Because it is here that we are telling the model that we are adding rows, where they will go, and how many we are adding. Here is the method description:
void QAbstractItemModel::beginInsertRows ( const QModelIndex & parent,
int first, int last )
So in your case since you want to add a row at the first index, and only one row, we pass 0 as the index of the first item, and 0 which is the index of the last item we are adding (because of course we are only adding one item).
beginInsertRows(modelIndex(), 0, 0);
Next we have to provide the data for the item. I assume that 'list' is a QList (if not it is probably similar). So we want to call the 'insert' method.
list.insert(0, item);
And that should be it.

For display you can try delegates as explained in the link (I haven't tried the example though). It will help the community if you can add your observations.

Thanks to everyone for replying. I have found the solution by my own:
In case if anyone is interested
void TableModel::addFile(const QString &path)
{
beginInsertRows(QModelIndex(), list.size(), list.size());
TableItem item;
item.filename = path;
QFile file(path);
item.size = file.size();
item.status = StatusNew;
list << item; // Why Assign first? Maybe not required
for (int i = list.size() - 1; i > 0; i--)
{
list[i] = list[i-1];
}
list[0] = item; // set newly added item at the top
endInsertRows();
}

Related

Save a single character

everyone.
I've created a simple textedit application.
I would like to take the single character whenever the user writes it using the keyboard.
I've thought to solve the problem in the following way:
void MainWindow::on_textEdit_textChanged()
{
QString str= ui->textEdit->toPlainText();
if (str.size()==0){
pos=0;
} else {
if(pos<str.size()) {
QChar char_prel=str.at(pos);
pos++;
chars.push_back(char_prel);
} else {
pos=0;
QString str=ui->textEdit->toPlainText();
chars.clear();
for(int i = 0; i < str.length(); i++) {
QChar char_prel=str.at(i);
chars.push_back(char_prel);
pos++;
}
}
}
}
The solution doesn't work because everytime, i read the entire string on the edit block using:
QString str= ui->textEdit->toPlainText();
and from that string i take the last inserted character.
I want to do the same thing without using the toPlaintText().
Thanks for answering
If you handle the KeyPressEvent of the QTextEdit, you'll have a parameter of QKeyEvent* type, let's call this one "e".
Then you can use "e->text()" to get the corresponding character.

QTableView + custom TableModel + lazy loading

I need to load heavy dataset into QTableView. Dataset is no less then 700Mb in memory and I don't want to load all it to memory.
QSqlQueryModel is not ideal for me for 2 reasons - it is not editable and it is not realy load-on-demand (because fetching whole data to memory).
What I want to get
I want to store only some part of data in memory. Just for
displaying and maybe some buffer for fast scrolling.
Model should be editable
It should be low-memory-consumption
Should have no freezes
How I am trying to solve this (straightforward model of my code)
Custom QTableView (tableView)
Custom TableModel (model)
Model wrapper. (wrapper)
Model wrapper select rows count from database, and set this value to model. Now model can answer for int rowCount().
This same value is set for tableView.verticalScrollBar().
tableView.verticalScrollBar signal(valueChanged) is connected to tableview slot(on_valueChanged)
Some code
tableView::on_valueChanged(value)
{
wrapper.changeOffset(value);
}
wrapper::changeOffset(value)
{
if (_offset == value){
return;
}
_selectQuery->seek(value);
int endValue = qMin(value + _cacheSize, model->rowCount());
_list.clear();
for(int i = value; i < endValue-1; i++){
_list.append(_selectQuery->record());
}
model->setRecordList(_list);
_offset = value;
model->setOffset(_offset);
}
_selectQuery in wrapper::changeOffset is previosly executed QSqlQuery cursor for select query results.
I also implemented several methods in model
QVariant SqlRecModel::data(const QModelIndex &index, int role) const
{
int row = index.row() - _offset;
if (row > m_recList.size() || row < 0){
return QVariant();
}
if (role == Qt::DisplayRole)
{
QVariant value = m_recList.at(row).value(index.column());
return value;
}
return QVariant();
}
Setter for model data storage
void SqlRecModel::setRecordList(const QList<QSqlRecord> &records)
{
qDebug() << "r:";
emit layoutAboutToBeChanged();
m_recList = records;
emit layoutChanged();
}
Problem
I can scroll _cacheSize rows, but I get crash (The program has unexpectedly finished.) after going out of old cacheRange.
Any advice? I don't know where to dig. Thanks!
Sorry for disturbing.
Error was in other code block.
This way is just okay to solve the task I have.
btw: if you play with cache buffer you can achive more smooth scroll.

Qt: How to delete locally created multiple QIntValidator pointer object implemented on QlineEdit?

As per the Title, How to delete mulitple QIntValidator pointer Object created locally.I am stuck with an issue of memory leak.
I have a function as below:
void ABC::setTableDataItems(QStringList headerData)
{
int row = headerData.size();
int column = 0;
if (_txtLineEdit != NULL) {
delete _txtLineEdit;
_txtLineEdit = 0;
}
for (int i = 0; i < row ; i++)
{
_txtLineEdit = new QLineEdit();
_txtLineEdit->setMaxLength(_pktStruct[i].ItemDataLength);
_txtLineEdit->setText(headerData.at(i));
_pktStruct[i].currentLine = _txtLineEdit;
QString regExp = "[01]{1,";
regExp.append(QString("%1").arg(_pktStruct[i].ItemDataLength)).append("}");
long maxDigit = getMaxValueForDigit( _pktStruct[i].ItemDataLength );
QIntValidator* decValidator = new QIntValidator( 0, maxDigit, _txtLineEdit );
QRegExpValidator* binValidator = new QRegExpValidator(QRegExp(regExp),_txtLineEdit);
switch (_pktStruct[i].ItemDataType)
{
case DATA_TYPE_ASCII:
break;
case DATA_TYPE_HEX:
break;
case DATA_TYPE_NUM:
_txtLineEdit->setValidator(decValidator);
break;
case DATA_TYPE_BINARY:
_txtLineEdit->setValidator(binValidator);
break;
case DATA_TYPE_MAX:
break;
}
ui->pcusim_cmd_task_tableWidget->setCellWidget(i, column, _txtLineEdit);
connect(_txtLineEdit, SIGNAL(textChanged(QString)), this, SLOT(on_pcusim_cmd_task_tableWidget_linedit_cellChanged(QString)));
}
}
In above function, I need to delete all multiple QIntValidator created dynamically (inside For Loop ) every time before the loop when the above function is called.
Don't know the way. Please give some suggestions / idea to proceed further ??
Thanks in advance
Why don't you do
QValidator* pValidator = NULL;
switch (_pktStruct[i].ItemDataType)
{
case DATA_TYPE_NUM:
// create the proper int validator here
// ...
pValidator = new QIntValidator(0, maxDigit, _txtLineEdit);
break;
case DATA_TYPE_BINARY:
// create the proper regexp validator here
// ...
pValidator = new QRegExpValidator(QRegExp(regExp),_txtLineEdit);
break;
}
_txtLineEdit->setValidator(pValidator);
That way you don't create validators that are not used.
Since you pass _txtLineEdit as parent on construction of validators, they will be deleted when their parent QLineEdit object is destroyed.
By the way, setCellWidget() takes ownership of the widget, so you don't need to delete _txtLineEdit; (assuming this is the one you passed to it, you should have created a list of them in this case)

Level as list in QtreeWidget

I have vector with 6 numbers, which I want insert to list and add this list to QTreeWidget. First number of list is on "root" level and other numbers are sublevel "root".
I don't know how to do it.
Image with describe:
Code:
void modal::zapis() {
ui->listWidget->clear();
ui->treeWidget->clear();
QList<QTreeWidgetItem *> items;
for(int i=0;i<v.size();i++)
{
QString string;
string.setNum(v.at(i));
ui->listWidget->addItem(string);
QTreeWidgetItem *root = new QTreeWidgetItem(ui->treeWidget);
if(i==0)
{
root->setText(0, string);
}
else
{
QTreeWidgetItem *item = new QTreeWidgetItem(root);
item->setText(0, string);
}
}
}
Thank you for any ideas.
You are creating a new root node on every iteration, it just needs creating once per call.

Copying part of QTableView

So I have a question very closely related to another question I've seen on here but when I tried posing my question there I got no responses, I'm hoping by asking this as a fresh question someone can help me out. Basically I want simply copy a portion of my table that I've created so that I can paste it to an excel file. Here's what I have:
QAbstractItemModel *abmodel = ui.tableview->model();
QItemSelectionModel *model = ui.tableview->selectionModel();
QModelIndexList list = model->selectionIndexes();
qSort(list);
QModelIndex index = list.first();
for(int i = 0; i < list.size(); i++)
{
QModelIndex index = list.at(i);
QString text = abmodel->data(index).toString();
copy_table.append(text);
if(index.row() != previous.row())
{
copy_table.append('\n');
}
else
{
copy_table.append('\t');
}
previous = index;
}
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(copy_table);
This will copy a column fine, but when I attempt to copy a row or say a 2x2 subtable the row index gets messed up, incorrectly assigning the row index for the values. Any thoughts?
Well, already figured it out, sorry anyone that wasted their time and looked.
void TestCopyTable::on_pushButton_copy_clicked()
{
QAbstractItemModel *abmodel = ui.tableView->model();
QItemSelectionModel * model = ui.tableView->selectionModel();
QModelIndexList list = model->selectedIndexes();
qSort(list);
if(list.size() < 1)
return;
QString copy_table;
QModelIndex last = list.last();
QModelIndex previous = list.first();
list.removeFirst();
for(int i = 0; i < list.size(); i++)
{
QVariant data = abmodel->data(previous);
QString text = data.toString();
QModelIndex index = list.at(i);
copy_table.append(text);
if(index.row() != previous.row())
{
copy_table.append('\n');
}
else
{
copy_table.append('\t');
}
previous = index;
}
copy_table.append(abmodel->data(list.last()).toString());
copy_table.append('\n');
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(copy_table);
}
I wrote some code based on Phil's to copy the selection when the user types Control-C.
I subclassed QTableWidget and overrode keyPressEvent():
void MyTableWidget::keyPressEvent(QKeyEvent* event) {
// If Ctrl-C typed
// Or use event->matches(QKeySequence::Copy)
if (event->key() == Qt::Key_C && (event->modifiers() & Qt::ControlModifier))
{
QModelIndexList cells = selectedIndexes();
qSort(cells); // Necessary, otherwise they are in column order
QString text;
int currentRow = 0; // To determine when to insert newlines
foreach (const QModelIndex& cell, cells) {
if (text.length() == 0) {
// First item
} else if (cell.row() != currentRow) {
// New row
text += '\n';
} else {
// Next cell
text += '\t';
}
currentRow = cell.row();
text += cell.data().toString();
}
QApplication::clipboard()->setText(text);
}
}
Output example (tab-separated):
foo bar baz qux
bar baz qux foo
baz qux foo bar
qux foo bar baz
Regarding the cdline:
qSort(cells); // Necessary, otherwise they are in column order
currently(20190118) it brings a warning:
Warnung: 'qSort >' is deprecated: Use std::sort
so my solution to replace the line with:
std::sort(cells.begin(),cells.end());
Compile, Run OK -> so far so good. But Question: Benefit of this cdline?
I found there is no one. Made several Test with copy from gui and parsing it to excel. Everything was fine even with the scenario 2x2 or othe XxY.

Resources