Qt - Adding data to a TableWidget via another TableWidget - c++

I am stuck on a certain problem with table widgets and I am in need of help. Basically, I am trying to get a table widget on a dialogue screen to get the information inside of it and then fill that information on to another table widget on a main window screen. So, when I click the OK button, it should take the text from one table widget and place it in the other table widget. I tried using the below code, and the build ran. But, as soon as I clicked OK, the program crashed. The table called TableWidgetedit is the table I am trying to copy from and send to the table in the mainwindow, named tablewidget. (just to make so I am not vague, I am trying to copy data from the one table and place it in another table, when a user clicks on the OK button.)
int rows = 6;
int columns = 5;
Ui::MainWindow *mainui;
void EditMode1::on_pushButton_clicked()
{
for (int i = 0; i<columns;++i){
for (int j = 0;j<rows;++j){
QTableWidgetItem *celltxt= TableWidgetedit.item(j,i);
mainui->tableWidget->setItem(j,i,celltxt);
}
}
}
Any and all help is appreciated. Thank you!
(I am a not the best with Qt so if you don't mind explaining what changes you have made and why, that would a great help thank you!).
-UPDATE-
#Jeet here are the code for what im trying to do:
tablemainwindow1.h:
#ifndef TABLEMAINWINDOW1_H
#define TABLEMAINWINDOW1_H
#include <QMainWindow>
#include "tabledialougewindow.h"
namespace Ui {
class TableMainWindow1;
}
class TableMainWindow1 : public QMainWindow
{
Q_OBJECT
public:
explicit TableMainWindow1(QWidget *parent = 0);
~TableMainWindow1();
private slots:
void on_pushButton_clicked();
private:
Ui::TableMainWindow1 *ui;
TableDialougeWindow *tbl2;
};
#endif // TABLEMAINWINDOW1_H
tablemainwindow1.cpp:
#include "tablemainwindow1.h"
#include "ui_tablemainwindow1.h"
TableMainWindow1::TableMainWindow1(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::TableMainWindow1)
{
ui->setupUi(this);
ui->tableWidget->setRowCount(3);
ui->tableWidget->setColumnCount(3);
}
TableMainWindow1::~TableMainWindow1()
{
delete ui;
}
void TableMainWindow1::on_pushButton_clicked()
{
tbl2 = new TableDialougeWindow(this);
tbl2->show();
}
tabledialougewindow.h:
#ifndef TABLEDIALOUGEWINDOW_H
#define TABLEDIALOUGEWINDOW_H
#include <QDialog>
namespace Ui {
class TableDialougeWindow;
}
class TableDialougeWindow : public QDialog
{
Q_OBJECT
public:
explicit TableDialougeWindow(QWidget *parent = 0);
~TableDialougeWindow();
private slots:
void on_buttonBox_accepted();
private:
Ui::TableDialougeWindow *ui;
};
#endif // TABLEDIALOUGEWINDOW_H
tabledialougewindow.cpp:
#include "tabledialougewindow.h"
#include "ui_tabledialougewindow.h"
#include "tablemainwindow1.h"
#include "ui_tablemainwindow1.h"
int Rows = 3;
int Columns = 3;
Ui::TableMainWindow1 *mainui;
TableDialougeWindow::TableDialougeWindow(QWidget *parent) :
QDialog(parent),
ui(new Ui::TableDialougeWindow)
{
ui->setupUi(this);
ui->tableWidget->setRowCount(Rows);
ui->tableWidget->setColumnCount(Columns);
}
TableDialougeWindow::~TableDialougeWindow()
{
delete ui;
}
void TableDialougeWindow::on_buttonBox_accepted()
{
for(int i = 0;i<Columns;++i){
for(int j = 0;j<Rows;++j){
QTableWidgetItem *celltxt = ui->tableWidget->item(j,i);
QTableWidgetItem *celltxt2 =new QTableWidgetItem(*celltxt);
mainui->tableWidget->setItem(j,i,celltxt2);
}
}
accept();
}
hope this helps.

The error is we cannot insert an item that is already owned by another QTableWidget. So before make a copy we need to clone the data. we can use copy constructor to achieve this. Code comment will explain in detail. Hope this help.
void MainWindow::on_cmdTransfer_clicked()
{
//Source Table
int rows = ui->tbl1->rowCount();
int columns =ui->tbl1->columnCount();
//Destination Table
ui->tbl2->setColumnCount(columns);
ui->tbl2->setRowCount(rows);
//Copy data form one table to another.
for (int i = 0; i<columns;++i){
for (int j = 0;j<rows;++j){
QTableWidgetItem *celltxt= ui->tbl1->item(j,i);
//Clone the data using copy constructor
QTableWidgetItem *celltxt1=new QTableWidgetItem(*celltxt);
ui->tbl2->setItem(j,i,celltxt1);
}
}
}

Related

Style Sheet ignored on class inherited from QWidget [duplicate]

I have several custom widget in my current project. I wish to apply stylesheets to them and when I do so inside Qt Creator, it appears to work. However, when executing the program, no stylesheet is used. The stylesheets for the Qt widgets are working normally.
Does anyone have any advice?
WidgetUnits.h
#ifndef WIDGETUNITS_H
#define WIDGETUNITS_H
#include <QList>
#include <QWidget>
#include <QPainter>
#include <Widgets/JECButton.h>
#include <Unit.h>
#include <Time.h>
namespace Ui
{
class WidgetUnits;
}
class WidgetUnits : public QWidget
{
Q_OBJECT
public:
explicit WidgetUnits(QWidget *parent = 0);
~WidgetUnits();
void setNumTimes(const int& numTimes);
public slots:
void updatePictures(const Time* time);
protected:
void paintEvent(QPaintEvent *event);
private:
void checkNewQueue(const QList<QList<Unit*>*>* units);
Ui::WidgetUnits *ui;
const int pictureWidth; // The width of the Unit pictures.
const int pictureHeight; // The height of the Unit pictures.
QList<QList<JECButton*>*> buttonPictures; // The Units' pictures. The outer QList stores the QList of pictures for a given tick.
// The inner QList stores the JECButtons for the specific tick.
};
WidgetUnits.cpp
#include "WidgetUnits.h"
#include "ui_WidgetUnits.h"
WidgetUnits::WidgetUnits(QWidget *parent):
QWidget(parent),
ui(new Ui::WidgetUnits),
pictureWidth(36),
pictureHeight(36)
{
ui->setupUi(this);
}
WidgetUnits::~WidgetUnits()
{
delete ui;
}
void WidgetUnits::updatePictures(const Time *time)
{
// Only showing units that started to get built this turn.
checkNewQueue(time->getUnits());
checkNewQueue(time->getBuildings());
checkNewQueue(time->getUpgrades());
// Updating the position of the remaining pictures (after some were removed).
// Checking the maximum number of Units made in one tick.
int maxNewQueue = 0;
for (int a = 0; a < buttonPictures.length(); ++a)
{
if (buttonPictures.at(a)->length() > maxNewQueue)
{
maxNewQueue = buttonPictures.at(a)->length();
}
}
if (buttonPictures.length() > 0)
{
this->setGeometry(0, 0, buttonPictures.length() * 130,
maxNewQueue * (pictureWidth + 10) + 20);
QList<JECButton*>* tickButtons = 0;
for (int a = 0; a < buttonPictures.length(); ++a)
{
tickButtons = buttonPictures.at(a);
for (int b = 0; b < tickButtons->length(); ++b)
{
tickButtons->at(b)->move(a * 130, b * (pictureHeight + 10));
}
}
}
update();
}
void WidgetUnits::checkNewQueue(const QList<QList<Unit *> *> *units)
{
if (units != 0)
{
const Unit* currentUnit = 0;
JECButton* currentButton = 0;
for (int a = 0; a < units->length(); ++a)
{
buttonPictures.append(new QList<JECButton*>());
for (int b = 0; b < units->at(a)->length(); ++b)
{
currentUnit = units->at(a)->at(b);
// Verifying that there is an item in the queue and the queue action was started this turn.
if (currentUnit->getQueue() != 0 && currentUnit->getAction()->getTimeStart() == currentUnit->getAction()->getTimeCurrent()
&& (currentUnit->getAction()->getType() == Action::BUILD || currentUnit->getAction()->getType() == Action::TRAIN ||
currentUnit->getAction()->getType() == Action::UPGRADE))
{
buttonPictures.last()->append(new JECButton(this));
currentButton = buttonPictures.last()->last();
QImage* image = new QImage(currentUnit->getQueue()->getUnitBase()->getImage().scaled(pictureWidth, pictureHeight));
currentButton->setImage(*image);
currentButton->setGeometry(0, 0, currentButton->getImage().width(),
currentButton->getImage().height());
currentButton->setColorHover(QColor(0, 0, 225));
currentButton->setColorPressed(QColor(120, 120, 120));
currentButton->setImageOwner(true);
currentButton->setVisible(true);
}
}
}
}
}
void WidgetUnits::setNumTimes(const int &numTimes)
{
// Appending new button lists for added ticks.
for (int a = buttonPictures.length(); a < numTimes; ++a)
{
buttonPictures.append(new QList<JECButton*>());
}
}
void WidgetUnits::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent(event);
}
The widget is visible- I set a tooltip which it showed me (It's just the same color of the QScrollArea it's sitting in).
I had a similar problem and it was solved using jecjackal's comment. As sjwarner said, it would be much more noticeable in the form of an answer. So I'll provide it. For the benefit of any future viewers. Again, it isn't my answer! Appreciate jecjackal for it!
As it is said in the Qt's stylesheets reference, applying CSS styles to custom widgets inherited from QWidget requires reimplementing paintEvent() in that way:
void CustomWidget::paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
Without doing it your custom widgets will support only the background, background-clip and background-origin properties.
You can read about it here: Qt Stylesheets reference in the section "List of Stylable Widgets" -> QWidget.
There is an answer much easier than writing your own paintEvent: subclass QFrame instead of QWidget and it will work right away:
class WidgetUnits : public QFrame
{
Q_OBJECT
....
For completeness, the same problem is present in PyQt. You can apply a stylesheet to a subclassed QWidget by adding similar code:
def paintEvent(self, pe):
opt = QtGui.QStyleOption()
opt.init(self)
p = QtGui.QPainter(self)
s = self.style()
s.drawPrimitive(QtGui.QStyle.PE_Widget, opt, p, self)
I had same problem with pyside. I post my solution just for completeness.
It is almost like in PyQt as Pieter-Jan Busschaert proposed.
only difference is you need to call initFrom instead of init
def paintEvent(self, evt):
super(FreeDockWidget,self).paintEvent(evt)
opt = QtGui.QStyleOption()
opt.initFrom(self)
p = QtGui.QPainter(self)
s = self.style()
s.drawPrimitive(QtGui.QStyle.PE_Widget, opt, p, self)
One other thing you need to make sure is that you define your custom widget in your css file the following way:
FreeDockWidget{...}
and not like often recommended
QDockWidget#FreeDockWidget{...}
Calling setAttribute(Qt::WA_StyledBackground, true) for the custom widget worked for me.
Setting Qt::WA_StyledBackground to true only works if you remember to add Q_OBJECT to your class. With these two changes you don't need to reimplement paintEvent.

Adding a Gtk::ListStore to Gtk::TreeView and adding rows to ListStore (gtkmm)

I want to be able to add a Gtk::ListStore to a Gtk::TreeView, the treeview was implemented through glade but I have created the ListStore in C++ and added columns and rows to it.
When I run the code it shows the window and the tree_view that has been loaded from the glade file but it is empty.
mainWindow.h:
#pragma once
#include <gtkmm.h>
class MainWindow {
protected:
Gtk::Window *main_window;
Gtk::TreeView *tree_view;
Glib::RefPtr<Gtk::ListStore> list_store;
public:
void init();
class ModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
ModelColumns() { add(name); add(age); }
Gtk::TreeModelColumn<Glib::ustring> name;
Gtk::TreeModelColumn<Glib::ustring> age;
};
};
mainWindow.cpp:
#include "mainWindow.h"
void MainWindow::init() {
auto app = Gtk::Application::create("org.gtkmm.example");
auto builder = Gtk::Builder::create_from_file("test.glade");
builder->get_widget("main_window", main_window);
builder->get_widget("tree_view", tree_view);
ModelColumns columns;
list_store = Gtk::ListStore::create(columns);
tree_view->set_model(list_store);
Gtk::TreeModel::Row row = *(list_store->append());
row[columns.name] = "John";
row[columns.age] = "30";
row = *(list_store->append());
row[columns.name] = "Lisa";
row[columns.age] = "27";
app->run(*main_window);
}
main.cpp:
#include "mainWindow.h"
int main() {
MainWindow m;
m.init();
}
tree_view->set_model(list_store);
tells tree_view to use list_store as its TreeModel, but it does not say what column from the list_store to render. In fact, the default behavior is that no column would be rendered.
To render both columns, you need to ask tree_view to append them.
// "Name" is column title, columns.name is data in the list_store
tree_view->append_column("Name", columns.name);
tree_view->append_column("Age", columns.age);
Gtkmm has an official tutorial book. This is the section on treeview. https://developer.gnome.org/gtkmm-tutorial/stable/sec-treeview.html.en

C++/Qt Threads error without using threads

I am using a special form of the qt framework and it will look a bit complicated. But do not worry. It is the same as the original framework of qt. (And no I can't change it)
My intention of this program is to load a table in a tableview from the ui. The tableview should have as many rows and text as files that are in a directory. I take all files in the directory and put an filter on them. Only the selected one are counted and used afterwards.
And now to my problem:
I want to display the table like an Excel table: it should highlight the cell where my cursor (in my example it is an counter which goes up and down) stands right now (Currently I do not have a cursor, so I have to use a self-created "cursor". You will see it in the program what I mean).
I use a QStandardItemModel to display it and a QStandardItem to define it.
Because I want to change the color of the cells I use an QStandardItem array to save the cells one by one.
form.h:
#ifndef FORM_H
#define FORM_H
#include <QWidget>
#include <QTextTable>
#include <QFont>
#include <QFile>
#include <QDir>
#include <QTextStream>
#include <QString>
#include <QStringList>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QBrush>
namespace Ui {
class Form;
}
class Form : public QWidget
{
Q_OBJECT
public:
explicit Form(QWidget *parent = 0);
~Form();
void my_setCFGFromDirectory();
void my_Highlighted(int, bool);
void my_loadCFG(int);
private:
Ui::Form *ui;
QFile file;
QTextStream textstream;
QDir directory;
QString filename;
QStringList stringlist;
QStringList filter;
QStandardItemModel *model;
QStandardItem *tableitem;
QStandardItem* pointerTableitem[];
int max_files;
int w_counter;
bool check1;
bool check2;
bool check3;
};
#endif // FORM_H
and the
form.cpp
#include "form.h"
#include "ui_form.h"
#include "rbobject.h"
Form::Form(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form)
{
ui->setupUi(this);
}
Form::~Form()
{
delete ui;
}
void Form::my_Highlighted(int actual_count, bool modus){
if(modus == 1){
w_counter = 0;
while(w_counter < max_files){
if(w_counter == actual_count){
pointerTableitem[w_counter]->setBackground(QBrush(QColor(130,180,255)));
}
w_counter++;
}
}
else
{
w_counter = 0;
while(w_counter < max_files){
pointerTableitem[w_counter]->setBackground(QBrush(QColor(255,255,255)));
w_counter++;
}
}
}
void Form::my_setCFGFromDirectory(){
directory.setPath("/etc/rosenbauer/CFG-Files");
filter << "*_CFG.ini";
stringlist = directory.entryList(filter); //takes the selected files and wriths them in a filelist
max_files = stringlist.count(); //Counts the selected files
pointerTableitem [max_files];
memset(pointerTableitem, 0, max_files*sizeof(int)); //The compiler can not see how many elements should be in the array at the time he constructs the array.
//So you have to use this to tell the compiler, how many elements it should create
model = new QStandardItemModel(max_files, 1, this); //Rows , Columns , this
model->setHorizontalHeaderItem(0, new QStandardItem(QString("CFG-Files"))); //Column , QStandarditem...name
for(w_counter = 0; w_counter != max_files; w_counter++){
tableitem = new QStandardItem();
tableitem->setBackground(QBrush(QColor(255,255,255)));
tableitem->setText(QString(stringlist[w_counter])); //Wriths text in the cell
qDebug() << tableitem->text();
pointerTableitem[w_counter] = tableitem; //Stacks the tableitems in a filelist
model->setItem(w_counter, 0, tableitem); //Row, Column , tableitem...text
}
w_counter = 0;
//pointerTableitem[2]->setBackground(QBrush(QColor(130,180,255))); //Test
ui->TableConfig->setModel(model); //Sets the table into the UI
}
void Form::my_loadCFG(int file_position){
check1 = 0;
check2 = 0;
directory.setPath("/etc/rosenbauer/etc/rosenbauer");
check1 = directory.remove("SA008_890560-001_CFG.ini");
check2 = directory.remove("reparsed/SA008_890560-001_CFG.ini_reparsed");
if(check1 && check2){
filename = pointerTableitem[file_position]->text();
check3 = QFile::copy("/etc/rosenbauer/CFG-Files/"+filename, "/etc/rosenbauer/SA008_890560-001_CFG.ini");
if(!check3){
qDebug() << "Error! Could not copy new CFG-file into directory";
}
}
else
{
qDebug() << "Error! Could not delete running CFG-file(s) from directory";
}
}
The main header rbobject45000.h
#ifndef RbObject45000_H
#define RbObject45000_H
#include "rbobject.h"
#include "form.h"
class RbObject45000 : public RbObject{
public:
RbObject45000();
RbObject45000(qint32 rbObjectId, RDataObject *dataobject, qint32 style, QObject *parent = 0);
RbObject45000(qint32 rbObjectId, qint32 style, qint32 prio, QObject *parent);
bool entered_ui;
bool entered_key;
short counter;
short w_count;
short delay_count;
short max_files;
short begin;
short end;
Form *f;
void exec();
~RbObject45000();
};
#endif // RbObject45000_H
And this is the main:
rbobject45000.cpp
RbObject45000::RbObject45000(qint32 rbObjectId, qint32 style, qint32 prio, QObject *parent):
RbObject(rbObjectId, style, prio, parent){
entered_ui = 0;
entered_key = 0;
counter = 0;
w_count = 1; //... whilecounter
delay_count = 0; //... delay for the deadtime
max_files = 0;
begin = 0;
end = 0;
f= new Form(); //f...name of the displayed UI
}
void RbObject45000::exec(){
//Opens the file on the display
if(getKey(RB_KEY_9) && getKey(RB_KEY_7) && entered_ui ==0){
f->show();
entered_ui = 1;
// Geting the Files from Directory
f->my_setCFGFromDirectory();
}
// Prescind them file in the table
if(entered_ui == 1 && delay_count == 2){
if(getKey(RB_KEY_7)){
counter--;
entered_key = 1;
if(counter < 0){
counter = 0;
}
}
else if(getKey(RB_KEY_9)){
counter++;
entered_key = 1;
if(counter > max_files){
counter = max_files;
}
}
if(entered_key == 1){
while(w_count <= max_files){
f->my_Highlighted(w_count, 0); //Cell , not highlighted
w_count++;
}
w_count = 0;
f->my_Highlighted(counter,1); //Cell , highlighted
entered_key = 0;
}
delay_count = 0;
}
else if(delay_count == 2){ //if delay == 2 and nobody hit a button
delay_count = 0;
}
delay_count++;
//Load the coosen file as programm-config in
if(entered_ui == 1){
if(getKey(RB_KEY_8)){
f->my_loadCFG(counter);
}
}
}
(RB_KEY_7-9 are buttons of a hardware-module, only have to click them)
So if I do it like this, the program will compile and start. If I press the buttons and the program run into the my_setCFGFromDirectory() it exits the window and stop running, but if the QStandardItem pointerTableitem is declared in the my_setCFGFromDirectory() everything works fine (but the pointerTableitem needs to be private).
The errors I get are:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Form(0x167498), parent's thread is QThread(0x1414e8), current thread is QThread(0x15d2d8)
Segmentation fault
It appears to say I use a thread (I'm sure I don't). But I know it has something to do with pointerTableitem and the declaration in the header and cpp.
If I'm not mistaken the problem lies here:
model = new QStandardItemModel(max_files, 1, this);
You try to create a QStandardItemModel passing your Form instance this as a parent, the form was created on the main thread, this call apparently happens on another thread (the edits you made were not enough, it is still unclear if RbObject inherits QThread but you could check that yourself) and thus the error message.
Why not call the function on the main thread? Instead of doing this
f->show();
entered_ui = 1;
// Geting the Files from Directory
f->my_setCFGFromDirectory();
in a different thread, make a slot/signal pair for the Form class, put this code in the slot and fire the connected signal from RbObject45000::exec(). It is not correct to do UI manipulation from a non-UI trhead.

QtableWidget does not show data

I have a class that creates random data which I would like to show in a tableview on the main window.
I added via Designer a table view to the main window and called it tblData.
I suspect the problem is related to this because when I call the constructor the ui file with some implementation is already there.
I have taken the "Detailed Description" section from http://qt-project.org/doc/qt-5/qtablewidget.html as guidance....
However, the table remains empty. I do not see why... Thank you very much.
include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QStringList headers;
headers << "Datapoints";
Dataset *myData;
myData = new Dataset();
myData->createRandomData(10); // create a ten element vector
QVector<int> data;
data = myData->getDataVector(); // data vector created in class Dataset
qDebug() << data;
int i;
for (i = 0 ; i < data.size() ; i++){
QString datapoint;
datapoint = QString::number(data[i]);
QTableWidgetItem * newItem = new QTableWidgetItem(datapoint);
ui->tblData->setItem(i, 0, newItem); // works not
qDebug() << datapoint; // works
}
}
MainWindow::~MainWindow()
{
delete ui;
}
I think you have to define your table's dimensions before starting to populate it with the data, i.e.
ui->tblData->setRowCount(data.size());
ui->tblData->setColumnCount(1);
The reason is that by default the initial row and column count of the table is 0, so the newly added items are not visible.

QTableView - Place pointer(highlight selection to the first row of list

I create own widget based on QTableView. It's something like file dialog (list). I want to act intuitively.
a) working with whole rows
b) indicator also worked with whole rows
c) using switched enter the lower level (subdirectory)
d) after run program or moving to a lower level cursor must be on the first row of the table (row 0)
And there is problem. I can not force the program to place the cursor on the first line.
I tried several methods, but none succeeded. setCurrentIndex. selectRow etc. Cursor is always somewhere else. Not highlighted, not on first line, but once it's on 10 position second on 4 position etc. It behaves unpredictably.
How can I do it?
Here my code is:
mFileBoxWidget::mFileBoxWidget(QWidget *parent) :
QTableView(parent)
,model(new QFileSystemModel())
{
this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
this->setShowGrid(false);
this->verticalHeader()->setVisible(false);
this->installEventFilter(this);
model->setReadOnly(true);
this->setModel(model);
this->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch );
this->setColumnWidth(1,70);
this->setColumnWidth(2,70);
this->setColumnWidth(3,110);
this->setRootIndex(model->setRootPath("C://"));
this->setSelectionMode(QAbstractItemView::SingleSelection);
this->setSelectionBehavior(QAbstractItemView::SelectRows);
//this->selectRow(0); //Does not work - goto first row
//this->setCurrentIndes(Index); //Does not work - goto index x=0 y=0
}
Thank you with advance for all your responses.
Solved!
The problem is that the model is asynchronous. So reads the data in another thread. When I tried to set the index to the first line, still basically did not exist. The solution is, of course, to wait for loading the thread. At this point signal directoryLoaded(QString) is send. As a result, it is necessary to wait for the signal, and only then set index.
connect(myModel, SIGNAL(directoryLoaded(QString)), this, SLOT(onLoaded()));
void mFileBoxWidget::onLoaded()
{
QModelIndex index = myModel->index(myModel->rootPath());
this->setCurrentIndex(index.child(0, index.column()));
}
You shouldn't name your member variable model. QTableView has function model(), the compiler thinks this->model is meant to be this->model(), therefore you get the error you mentioned.
This is untested code, but I think something like this should work:
QModelIndex firstRow = QTableView::model()->index(0, 0);
QTableView::selectionModel()->select(firstRow,
QItemSelectionModel::ClearAndSelect |
QItemSelectionModel::Rows );
EDIT: (2013-06-19 06:12:58 UTC)
A simple (and ugly) workaround that worked so far for me is triggering a call to m_tableView->selectRow(0); from a QTimer.
Here's the sample code:
Header:
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
class QTableView;
class QFileSystemModel;
class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *parent = 0);
~MainWidget();
private:
void layoutWidgets();
QFileSystemModel *m_model;
QTableView *m_tableView;
private slots:
void selectFirstRow();
// for debugging only
void selectionChanged();
};
#endif // MAINWIDGET_H
Implementation:
#include "mainwidget.h"
#include <QTableView>
#include <QHBoxLayout>
#include <QFileSystemModel>
#include <QHeaderView>
#include <QTimer>
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
{
m_tableView = new QTableView(this);
m_model = new QFileSystemModel(this);
m_model->setReadOnly(true);
m_tableView->setModel(m_model);
m_tableView->setRootIndex(m_model->setRootPath(QDir::homePath()));
m_tableView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_tableView->setShowGrid(false);
m_tableView->verticalHeader()->setVisible(false);
m_tableView->setColumnWidth(1,70);
m_tableView->setColumnWidth(2,70);
m_tableView-> setColumnWidth(3,110);
m_tableView->setSelectionMode(QAbstractItemView::SingleSelection);
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
//m_tableView->->setSectionResizeMode(0, QHeaderView::Stretch ); // Qt 5?
layoutWidgets();
connect(m_tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged()) );
// This works
QTimer::singleShot(1000, this, SLOT(selectFirstRow()));
// Direct invocation - doesn't works
// selectFirstRow();
}
void MainWidget::layoutWidgets()
{
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addWidget(m_tableView);
setLayout(mainLayout);
setFixedSize(500,500);
}
void MainWidget::selectFirstRow()
{
m_tableView->selectRow(0);
}
void MainWidget::selectionChanged()
{
qDebug("Selection changed");
}
MainWidget::~MainWidget()
{}
The weird thing is, if QTimer::singleShot() needs to be triggered with a delay of at least ~25 ms., otherwise it wouldn't work in my system.
Here's the alternative, subclassing QTableView:
#include "mytableview.h"
#include <QFileSystemModel>
#include <QHeaderView>
#include <QTimer>
MyTableView::MyTableView(QWidget *parent) : QTableView(parent)
{
QFileSystemModel *myModel = new QFileSystemModel;
setModel(myModel);
setRootIndex(myModel->setRootPath(QDir::homePath()));
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setShowGrid(false);
verticalHeader()->setVisible(false);
//installEventFilter(this);
myModel->setReadOnly(true);
//setSectionResizeMode(0, QHeaderView::Stretch ); // Qt 5
setColumnWidth(1,70);
setColumnWidth(2,70);
setColumnWidth(3,110);
setSelectionMode(QAbstractItemView::SingleSelection);
setSelectionBehavior(QAbstractItemView::SelectRows);
QTimer::singleShot(100, this, SLOT(selectFirstRow()));
connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged()));
}
void MyTableView::selectFirstRow()
{
// qDebug("Selecting first row");
// QModelIndex firstRow = QTableView::model()->index(0,0);
// if(firstRow.isValid()){
// selectionModel()->select(firstRow, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
// }else{
// qDebug("Invalid index");
// }
selectRow(0);
}
void MyTableView::selectionChanged()
{
qDebug("Selection changed.");
}