QSqlRelationalTableModel insertRecord doesn't work if call setRelation - sqlite

editlistofcustomers.h
QSqlRelationalTableModel *RelationalModel;
TreeModel *CategoriesModel;
QSqlRecord Record;
editlistofcustomers.cpp
EditListOfCustomers::EditListOfCustomers // constructor
RelationalModel = new QSqlRelationalTableModel(this, *SupportObj->GetDataBase());
RelationalModel->setTable(SupportObj->GetCustomersTableName());
RelationalModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
RelationalModel->select();
RelationalModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Название/имя покупателя"));
Record = RelationalModel->record();
RelationalModel->setRelation(2, QSqlRelation(SupportObj->GetCategoriesOfCustomersTableName(),
SupportObj->GetCategoriesOfCustomersPattern()[0].GetName(), // ID.
SupportObj->GetCategoriesOfCustomersPattern()[2].GetName())); // Name.
CategoriesModel = new TreeModel(QObject::tr("Категории"),
SupportObj->GetCategoriesOfCustomersTableName(),
SupportObj, this);
//Setup model view delegate.
ui->TV_ListOfCustomers->setModel(RelationalModel);
ui->TV_ListOfCustomers->setItemDelegate(new QSqlRelationalDelegate(ui->TV_ListOfCustomers));
ui->TV_ListOfCustomers->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->TV_ListOfCustomers->setSortingEnabled(true);
ui->TV_CategoryOfCustomer->setModel(CategoriesModel);
SupportObj->GetDataBase()->transaction()
EditListOfCustomers::AddCustomer
QString customerName = ui->LE_CustomerName->text();
if(!customerName.isEmpty())
{
Record.setValue(SupportObj->GetCustomersPattern()[1].GetName(), QVariant(customerName)); // Name.
int categoryID = CategoriesModel->GetItemID(ui->TV_CategoryOfCustomer->currentIndex());
Record.setValue(SupportObj->GetCustomersPattern()[2].GetName(), QVariant(categoryID)); // Category ID.
Record.setValue(SupportObj->GetCustomersPattern()[3].GetName(), QVariant(ui->LE_CustomerTelephoneNumbers->text())); // Telephone numbers.
Record.setValue(SupportObj->GetCustomersPattern()[4].GetName(), QVariant(ui->LE_CustomerAddress->text())); // Address.
Record.setValue(SupportObj->GetCustomersPattern()[5].GetName(), QVariant(ui->TE_CustomerComment->toPlainText())); // Comment.
RelationalModel->insertRecord(-1, Record);
if(!RelationalModel->submitAll())
{
QMessageBox::warning(this, "CategoriesEditor::CategoriesEditor", SupportObj->GetDataBase()->lastError().text());
}
// Clear fields
ui->LE_CustomerName->clear();
ui->TV_CategoryOfCustomer->setCurrentIndex(QModelIndex());
ui->LE_CustomerTelephoneNumbers->clear();
ui->LE_CustomerAddress->clear();
ui->TE_CustomerComment->clear();
ui->LE_CustomerName->setFocus();
ui->TV_ListOfCustomers->sortByColumn(0, Qt::AscendingOrder);
}
If comment "RelationalModel->setRelation( ... )" everything work fine: transaction, adding, deleting, commit or rollback. If uncomment nothing work, but show everything right(ID replaced by category name), but I can't insert new row using "insertRecord". I try this
suggestion, but unsuccessfully.
Any suggestion?

The problem was in the column name. setRelation changes column name category_of_customer_id to category_of_customers_name_2.
The solution use void setValue(int index, const QVariant &val) instead of void setValue(const QString & name, const QVariant &val).
QSqlRecord record = RelationalModel->record();
record.setValue(1, QVariant(customerName)); // Name.
int categoryID = CategoriesModel->GetItemID(ui->TV_CategoryOfCustomer->currentIndex());
record.setValue(2, QVariant(categoryID)); // Category ID.
record.setValue(3, QVariant(ui->LE_CustomerTelephoneNumbers->text())); // Telephone numbers.
record.setValue(4, QVariant(ui->LE_CustomerAddress->text())); // Address.
record.setValue(5, QVariant(ui->TE_CustomerComment->toPlainText())); // Comment.
RelationalModel->insertRecord(-1, record);
if(!RelationalModel->submitAll())
{
QMessageBox::warning(this, "CategoriesEditor::CategoriesEditor", SupportObj->GetDataBase()->lastError().text());
}

Had the same issue. This only needs to happen for the field that has a setRelation. Here's the solution for PyQt:
def insertRow(self):
rec = self.record()
rec.setValue("id", "new id")
rec.setValue("type", 1)
rec.setValue("title", "new title")
return self.insertRecord(-1, rec)
self.submit()
Apologies. Wanted to comment, but don't yet have a reputation of 50+.

Related

How to find employee of system user

I have a form that must be triggered from the Info class startupPost method, as it has to verify a condition, and if the condition is true (if it's the user's birthday), then trigger my form.
The only way I found to verify the BDay of the user is to take it from the EmplTable. Also, I need to relate something between the EmplTable and UserInfo or SysUserInfo tables in order to give me the user ID.
The problem is that I didn't find a proper way to relate the tables, because in my EmplTable I have a DEL_userId field wich is NOT populated and not used.
In conclusion my if block from the following chunk of code does not get executed.
Also I left The emplTable variable intentionally not declared, as I am not sure what's the best way to declare it.
Thanks in advance for any ideas guys!
void startupPost()
{
EmplTable emplTable ; //intentionally left undeclared
int dayOfBirth = dayOfMth(emplTable.BirthDate);
int monthOfBirth = mthOfYr(emplTable.BirthDate);
int dayOfMonth = dayOfMth(systemdateget());
int monthOfYear = mthOfYr(systemdateget());
str emplName = emplTable.name();
Args args = new Args(); //formrun
FormRun formrun;
;
if (dayOfBirth == dayOfMonth && monthOfBirth == monthOfyear )
{
info("ok"); //just to verify if my loop is working
new MenuFunction(menuitemDisplayStr(NET_PALIN_001_HBDay), MenuItemType::Display).run();
// args.name(formStr(NET_PALIN_001_HBDay));
// formRun = classFactory.formRunClass(args);
// formRun.init();
// formrun.run();
}
}
Have a look at the table SysCompanyUserInfo which maps system users from UserInfo to employees of EmplTable.
Below is an example to find the associated record of EmplTable (if it exists) for the current user
static void FindCurUserEmplTable(Args _args)
{
EmplId emplId;
EmplTable emplTable;
;
emplId = EmplTable::userId2EmplId(curuserid());
if (emplId != '')
{
emplTable = EmplTable::find(emplId);
// ... your birthday logic
}
}

Specializing a QAbstractProxyModel for adding a column: the table cells becomes empty

I have created a mixin-like proxy model (Qt5) which just adds an extra first column to another proxy model, for adding a QToolBar of actions to each row of the table view (for example, a "delete" button). The model just provides a way of populating a QList<QVariant> for the first column. The delegate must know what is the meaning of each QVariant (usually ints/enums identifying actions), and populate the QToolBar accordingly. As last feature, if there's no actions, no extra column is added (it behaves like a QIdentityProxyModel in that case). Once added, actions cannot be removed. That's a feature for another day.
The problem of today is that, when I insert actions (which I do before setting the model to the view), the cells are all blanks. So, I'm doing something wrong with the signals or who knows with what (I think the mistake is in the add_action function, at the end of the snippet):
template<class proxy_model>
class action_model : public proxy_model
{
QList<QVariant> l_actions;
public:
using base_t = proxy_model;
using base_t::base_t; // Inheriting constructors.
QModelIndex mapFromSource(const QModelIndex& source_idx) const override
{
if (!l_actions.empty() and source_idx.isValid())
return this->createIndex(source_idx.row(),
source_idx.column() + 1);
else // identity proxy case
return base_t::mapFromSource(source_idx);
} // same for mapToSource but with - 1 instead of + 1.
int columnCount(const QModelIndex& parent = QModelIndex()) const override
{ return this->base_t::columnCount() + !l_actions.empty(); }
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
{
if (!l_actions.empty()) {
if (orientation == Qt::Horizontal and section == 0
and role == Qt::DisplayRole)
return "Actions"; // Testing.
else
return base_t::headerData(section - 1, orientation, role);
} else // identity proxy case
return base_t::headerData(section, orientation, role);
}
QVariant data(const QModelIndex& idx, int role) const override
{
if (!l_actions.empty()) {
if (idx.column() == 0 and role = Qt::DisplayRole)
return l_actions; // All the actions for drawing.
else
return QVariant();
} else // identity proxy case
return base_t::data(idx, role);
}
Qt::ItemFlags flags(QModelIndex const& idx) const
{
if (!l_actions.empty() and idx.column() == 0)
return Qt::NoItemFlags; // No editable or selectable
else
return base_t::flags(idx);
}
// And here, I think, is where the fun starts:
// The action could be added before or after the sourceModel
// is set or this model is connected to a view, but I don't
// how that cases are supposed to be managed.
void add_action(QVariant const& action)
{
bool was_empty = l_actions.empty();
l_actions << action;
if (was_empty and !this->insertColumns(0, 1))
throw std::logic_error("Something went wrong");
Q_EMIT this->dataChanged
(this->createIndex(0, 0),
this->createIndex(this->rowCount(), 0),
{ Qt::DisplayRole });
}
};
Without setting actions, the model works fine, both with QAbstractIdentityProxyModel and QSortFilterProxyModel as proxy_model. But, when setting actions, the view shows every cell blank, both with QSortFilterProxyModel and QAbstractIdentityProxyModel.
Here is a user-land code:
enum sql_action { DELETE };
auto* table_model = /* My QSqlTableModel */;
auto* view_model = new action_model<QIdentityProxyModel>(my_parent);
auto* table_view = new QTableView;
view_model->add_action(static_cast<int>(sql_action::DELETE));
view_model->setSourceModel(table_model);
table_view->setModel(view_model);
table_view->setSortingEnabled(true);
table_view->setAlternatingRowColors(true);
// The last column is printed in white, not with alternate colors.
table_view->show();
table_model->select();
The delegates are not a problem because I have set no one. I expect a first column with white cells, but I get an entirely white table. The column names are shown fine, except the last one, which prints just 0 as column name.
What am I doing wrong?
The problem is in your data() method.
You do not compare role to Qt::DisplayRole you assign to role
If you have actions, you either return the action entry or QVariant(), never any data

Combobox selections disappear when table editing canceled

Ok, I'm starting to lose my mind on this one. I have a tableview where there are 3 combobox table cells. The first is a box where a user can select a job, the job selected changes the next combobox's options (job category). The job category selection changes the options in the labor box. So the flow down is:
job > job category > labor.
I have a very peculiar problem. When editing the table, you can click on any box to get a corresponding list of the available selections based on the other fields. This works fine. Where it blows up is when a selection ISN'T made. To make things more interesting, it only effects the job and job category comboboxes the labor box works flawlessly.
symptom:
-- job category selection disappears when edit is canceled via esc or focus lost
-- selection chosen in the job category field is placed into the job field when editing is canceled via esc or upon loss of focus
Here's the steps to recreate the symptoms:
1) click on job category box and enable editing mode
2) make a new selection from the drop down list
new selection made img
3) click on the job box and enable editing
4) click off the job box and cancel editing by click on job category or labor box in the same row
5) enable job category editing and then cancel job category edit by clicking on either labor / labor boxes or using esc
lose the job category / job selections img
here is the code to initialize the graphic when it comes up:
public void initialize(URL location, ResourceBundle resources) {
/* this is here because the screen handler will load up the Main screen in the
in the hashmap; no connection data will be assigned to the user at that time.
Without this block, when the hashmap attempts to load the Main data this
will cause the screenhandler to error and the main application
to not load correctly. The block below initiatializes the connection to
prevent this from happening.*/
if ( vUsers.getConn() == null){
try {
//establishes a user's connection to the database
vUsers.ConnecrDB();
} catch (SQLException | IOException ex) {
//debugging catch
System.out.println(ex);
}
}
//set the job box list for the user
cmbxJobT.setItems(cmbxPopulator.getJobComboBox());
cmbxJobT.valueProperty().addListener(new ChangeListener<String>(){
#Override
//reads the user's selectino and returns the appropriate labor codes for the Employee
public void changed(ObservableValue o, String oldValue, String newValue){
if (newValue != null){
cmbxJobCatT.getItems().clear();
cmbxJobCatT.getItems().addAll(cmbxPopulator.getJobCatComboBox(newValue));
}else {
cmbxJobCatT.getItems().clear();
cmbxJobCatT.getItems().add(null);
}
}
});
cmbxJobCatT.valueProperty().addListener(new ChangeListener<String>(){
#Override
//reads the user's selectino and returns the appropriate labor codes for the Employee
public void changed(ObservableValue o, String oldValue, String newValue){
if (newValue != null){
cmbxLaborT.getItems().clear();
cmbxLaborT.getItems().addAll(cmbxPopulator.getLaborComboBox(newValue));
}else {
cmbxLaborT.getItems().clear();
cmbxLaborT.getItems().add(null);
}
}
});
tblviewTime.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSel) ->{
if (newSel != null){
Model_Time current = tblviewTime.getSelectionModel().getSelectedItem();
cmbxJobCatT.getItems().clear();
cmbxJobCatT.getItems().addAll(cmbxPopulator.getJobCatComboBox(current.getJob()));
cmbxLaborT.getItems().clear();
cmbxLaborT.getItems().addAll(cmbxPopulator.getLaborComboBox(current.getJobCat()));
}
if (newSel == null){
Model_Time current = tblviewTime.getSelectionModel().getSelectedItem();
cmbxJobCatT.getItems().clear();
cmbxJobCatT.getItems().addAll(cmbxPopulator.getJobCatComboBox(current.getJob()));
cmbxLaborT.getItems().clear();
cmbxLaborT.getItems().addAll(cmbxPopulator.getLaborComboBox(current.getJobCat()));
}
});
addDragListeners(bertaTabPane);
}
here's the code that sets up the tableview:
public void btnTimeSearch(ActionEvent event){
//makes an instance of the toolkit needed to query user time.
Database_RetrievesTime userData = new Database_RetrievesTime();
//grabs data from the userinput fields to set the toolkit
userData.setDateSelect(lblPickDateT.getValue());
userData.setJobBoxSelect(jobTbl.getIdByDesc(cmbxJobT.getValue()));
userData.setLaborBoxSelect(laborTbl.getIdByDesc(cmbxLaborT.getValue()));
userData.setJobCatSelect(jobCatTbl.getIdByDesc(cmbxJobCatT.getValue()));
/*creates cell factories in each column and maps the cell values to the
observable array list's IDs. The section also sets the columns up for user
editing to be available and the methods to execute upon an editted cell
being committed to entry.
**NOTE: The values are retrieved by the model class's getter methods.
Changing a name in the model class requires the user to update the getters.
Naming convention does apply. So for example: a variable
named cscHelp is added, it would need to have a getter called getCscHelp otherwise
the corresponding column will return blanks.*/
//setup ID column
IDcol.setCellValueFactory(new PropertyValueFactory<>("ID"));
//setup Datecol
Datecol.setCellValueFactory(new PropertyValueFactory<>("userDate"));
Datecol.setCellFactory(DatePickerTableCell.forTableColumn());
//created a custom datepicker callback that can be reused throughout the code's interfaces
Datecol.setOnEditCommit((CellEditEvent<Model_Time,LocalDate> t) -> {
//generate a temporary variable to convert the LocalDate returned into a SimpleObjectProperty
ObjectProperty<LocalDate> temp = new SimpleObjectProperty(t.getNewValue());
//store the new value to the object's model
t.getRowValue().setUserDate(temp);
//store row's object to the change list
Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
//signaling to the program that a change had been made
isChanged = true;
});
//job column setup
Jobcol.setCellValueFactory(new PropertyValueFactory<>("Job"));
Jobcol.setCellFactory(ComboBoxTableCell.forTableColumn(cmbxPopulator.getJobComboBox()));
/*creates a combobox filled with the populated items found at initialization of the screen
user inputs are automatically commited
*/
Jobcol.setOnEditCommit((CellEditEvent<Model_Time,String> t) -> {
SimpleStringProperty ssp = new SimpleStringProperty(t.getNewValue());
//store selection to the object's model (unprocessed so values will show something like '6002: Kobota'
t.getRowValue().setJob(ssp);
//store row's object to the change list
Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
cmbxJobCatT.getItems().clear();
cmbxJobCatT.getItems().addAll(cmbxPopulator.getJobCatComboBox(t.getRowValue().getJob()));
//signaling a change has been made
isChanged = true;
});
jobCatCol.setCellValueFactory(new PropertyValueFactory<>("JobCat"));
jobCatCol.setCellFactory(ComboBoxTableCell.forTableColumn(cmbxPopulator.getJobCatComboBox(cmbxJobT.getValue())));
jobCatCol.setOnEditCommit((CellEditEvent<Model_Time,String> t)->{
SimpleStringProperty ssp = new SimpleStringProperty(t.getNewValue());
//store selection to the object's model (unprocessed so values will show something like '6002: Kobota'
t.getRowValue().setJob(ssp);
//store row's object to the change list
Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
cmbxLaborT.getItems().clear();
cmbxLaborT.getItems().addAll(cmbxPopulator.getLaborComboBox(t.getRowValue().getJob()));
//signaling a change has been made
isChanged = true;
});
//labor column setup works just like the job column
Laborcol.setCellValueFactory(new PropertyValueFactory<>("Labor"));
Laborcol.setCellFactory(ComboBoxTableCell.forTableColumn(cmbxPopulator.getLaborComboBox(cmbxJobCatT.getValue())));
Laborcol.setOnEditCommit((CellEditEvent<Model_Time,String> t) -> {
SimpleStringProperty ssp = new SimpleStringProperty(t.getNewValue());
t.getRowValue().setLabor(ssp);
Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
t.getTableView().getItems().get(t.getTablePosition().getRow()).setLabor(ssp);
isChanged = true;
});
//time column setup.
Timecol.setCellValueFactory(new PropertyValueFactory<>("Time"));
Timecol.setCellFactory(TextFieldTableCell.<Model_Time, Float>forTableColumn(new FloatStringConverter()));
Timecol.setOnEditCommit((CellEditEvent<Model_Time,Float> t) -> {
//temp variable initialiation
float token = t.getNewValue();
//generate a temporary variable to convert the float return to a SimpleFloatProperty
SimpleFloatProperty temp = new SimpleFloatProperty(token);
//now update the row's object
t.getRowValue().setTime(temp);
//store row's object to the change list
Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
isChanged = true;
});
//set tableView editable
tblviewTime.setEditable(true);
//sets tableView to allow multiline selection
TableViewSelectionModel<Model_Time> tvt = tblviewTime.getSelectionModel();
tvt.setSelectionMode(SelectionMode.MULTIPLE);
/* checks if edits have been made. If there are edits, it commits to the
database before wiping the arraylists and updating the table*/
if (isChanged == true){
/*makes sure there are no duplicate entries in the arraylist. Throws out
previous edits and takes the most recent*/
Helper_TimShArrGen.validateMatrixEntries();
//commits changes and resets the "isChanged" value.
isChanged = Helper_TimShArrGen.confirmChanges(vUsers, jobTbl, jobCatTbl, laborTbl, isChanged);
}
/*tells the kit to run the querytime Method which uses the user input data
and user data to search the timesheet tables and returns the user's time.*/
if (isChanged == false){
try {
rs = userData.queryTime(vUsers.getConn(), vUsers.getLogin_ID());
} catch (SQLException ex) {
System.out.println(ex);
}
} else {
return;
}
//sets up the observablelist for the tableview
renderTable.setTableView(tblviewTime);
ObservableList n = renderTable.generateTable(jobTbl, jobCatTbl, laborTbl, rs, vUsers.getConn());
//renders the data on the screen`
tblviewTime.setItems(n);
Helper_TimeBreakDown breakdown = new Helper_TimeBreakDown();
breakdown.setTblArr(n);
breakdown.BreakDwnTim();
lblMonTim.setText(String.valueOf(breakdown.getMon()));
lblTuesTim.setText(String.valueOf(breakdown.getTues()));
lblWedsTim.setText(String.valueOf(breakdown.getWeds()));
lblThursTim.setText(String.valueOf(breakdown.getThurs()));
lblFriTim.setText(String.valueOf(breakdown.getFri()));
lblSatTim.setText(String.valueOf(breakdown.getSat()));
lblSunTim.setText(String.valueOf(breakdown.getSun()));
lblWkTim.setText(String.valueOf(breakdown.getWeek()));
}
this is the segment from the class that handles the data that goes into the lists.
public ObservableList<String> getJobComboBox(){
//clear the jobList to clean out junk data between calls
jobList.clear();
//looks at the job table to determine if the job is active. If active, it reads the entry
for (count=0; count<= jobTbl.getTblArray().size()-1; count++){
if(jobTbl.getTblArray().get(count).isActive()){
/*here we scroll through the JobIDList and match the IDs to the jobtbl
data. When a match is hit, we grab up the number on the job and the description
this is added to another array that will become the combobox's list
*/
for(inCount = 0; inCount <= jobIDList.size()-1; inCount++){
if(jobIDList.get(inCount).getCol2ID() == jobTbl.getTblArray().get(count).getID()){
jobList.add(jobTbl.getNumById(jobIDList.get(inCount).getCol2ID())
+ ": " + jobTbl.getDescById(jobIDList.get(inCount).getCol2ID()));
}
}
}
}
/* there's probably a better dataset to use that won't allow duplicates
due to my lack of knowledge at this time, I elected to create a hashset, pass the arrayList
to the hashset to wipe out duplicates, and then pass it back to the arrayList to be used in the combobox
*/
Set<String> tmp = new HashSet();
tmp.addAll(jobList);
jobList.clear();
jobList.addAll(tmp);
jobList.add(null);
return jobList;
}
/**
*
* #param job Argument for the selected Job String
* #return returns the ObservableList of strings for the Job Category ComboBox
*/
public ObservableList<String> getJobCatComboBox(String job){
//clearing out old artifact data from the previous selection
jobCatList.clear();
//splitting the user's string selection apart (number as string, description as string)
int jID=0;
if (job != null){
if (job.contains(": ")){
String[] tmp = job.split(": ");
job = tmp[1];
}
}
// here we comb the job Table for a matching description and vacuum up the associated ID number
for(count=0; count<=jobTbl.getTblArray().size()-1; count++){
if(jobTbl.getTblArray().get(count).getDesc().equals(job)){
jID = jobTbl.getTblArray().get(count).getID();
}
}
/*using that jobID number to examine the fKey in the category table.
once we match the JobID to the fKey ID in the jobCat table, we scoop up the
the job Category code and description to create a list for the combobox
*/
for (count=0; count<= jobCTbl.getTblArray().size()-1; count++){
for(inCount = 0; inCount <= jobCatIDList.size()-1; inCount++){
if(jobCatIDList.get(inCount).getID() == jobCTbl.getTblArray().get(count).getID()){
if(jobCTbl.getTblArray().get(count).getfKeyId() == jID){
jobCatList.add(jobCTbl.getNumById(jobCatIDList.get(inCount).getID())
+ ": " + jobCTbl.getDescById(jobCatIDList.get(inCount).getID()));
}
}
}
}
//same house keeping to remove duplicates as described above
Set<String> tmp = new HashSet();
tmp.addAll(jobCatList);
jobCatList.clear();
jobCatList.addAll(tmp);
jobCatList.add(null);
return jobCatList;
}
/**
*
* #param jobCat Argument for the selected Job Category String
* #return ObservableList of strings for the Labor ComboBox
*/
public ObservableList<String> getLaborComboBox(String jobCat){
//temp arrays I needed to decode the affiliated connections
ArrayList<Integer> jCID = new ArrayList();
ArrayList<Integer> laborID = new ArrayList();
//house keeping to remove artifact data from previous selections
if(jCID != null){
jCID.clear();
}
if(laborID != null){
laborID.clear();
}
if(laborList !=null){
laborList.clear();
}
//split user's string selection for the job category (numerical code as sting, description as string)
if(jobCat != null){
if (jobCat.contains(": ")){
String[] tmp = jobCat.split(": ");
jobCat = tmp[1];
}
}
//use the description to find the affiliated job category ID
for(count=0; count<=jobCTbl.getTblArray().size()-1; count++){
if(jobCTbl.getTblArray().get(count).getDesc().equals(jobCat)){
jCID.add(jobCTbl.getTblArray().get(count).getID());
}
}
//use the job category ID to find the associated labor IDs from the associate entity table
for(count=0; count<=jCLTbl.getTblArray().size()-1; count++){
for(inCount=0; inCount<=jCID.size()-1; inCount++){
if(jCLTbl.getTblArray().get(count).getCol1ID() == jCID.get(inCount)){
laborID.add(jCLTbl.getTblArray().get(count).getCol2ID());
}
}
}
//use the labor ID to look up the needed data from the labor table.
for (count=0; count<= laborTbl.getTblArray().size()-1; count++){
for(inCount = 0; inCount <= laborID.size()-1; inCount++){
if(laborID.get(inCount) == laborTbl.getTblArray().get(count).getID()){
laborList.add(laborTbl.getNumById(laborID.get(inCount))
+ ": " + laborTbl.getDescById(laborID.get(inCount)));
}
}
}
//more housekeeping to remove duplicate entries.
Set<String> tmp = new HashSet();
tmp.addAll(laborList);
laborList.clear();
laborList.addAll(tmp);
laborList.add(null);
return laborList;
}
I know there are probably better ways to do things here. I'm still new to JAVA and coding. I work at a small company so I'm the only coder they employee. Unfortunately this limits me to what I can teach myself, so there are probably some more efficient ways to accomplish the same mission here. Anyway, if anyone could help me figure out what is going on, it would be appreciated.
The answer to this problem is actually found in the SetOnEdit portion of the jobcatCol.
upon closer inspection and a lot of debugging, I found that this line
t.getRowValue().setJob(ssp);
is actually supposed to be
t.getRowValue().setJobCat(ssp);
I also chose to forego the ComboBoxTableCell API and write my own combobox implementations for each cell. It's a very basic version found here:
public class JobComboBoxCell extends TableCell<Model_Time, String>
{
private ComboBox<String> comboBox;
private Helper_UserSpecificTimDat cmbxPopulator = new Helper_UserSpecificTimDat();
public JobComboBoxCell(Helper_UserSpecificTimDat cmbxPopulator)
{
comboBox = new ComboBox<>();
this.cmbxPopulator = cmbxPopulator;
}
#Override
public void startEdit()
{
if ( !isEmpty() )
{
super.startEdit();
comboBox.setItems( cmbxPopulator.getJobComboBox() );
comboBox.getSelectionModel().select( this.getItem() );
comboBox.focusedProperty().addListener( new ChangeListener<Boolean>()
{
#Override
public void changed( ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue )
{
if ( !newValue )
{
commitEdit( comboBox.getSelectionModel().getSelectedItem() );
}
}
} );
setText( null );
setGraphic( comboBox );
}
}
#Override
public void cancelEdit()
{
super.cancelEdit();
setText( ( String ) this.getItem() );
setGraphic( null );
}
#Override
public void updateItem( String item, boolean empty )
{
super.updateItem( item, empty );
if ( empty )
{
setText( null );
setGraphic( null );
}
else
{
if ( isEditing() )
{
setText( null );
setGraphic( comboBox );
}
else
{
setText( this.getItem() );
setGraphic( null );
}
}
}
}
This code was courtesy of Uluk Biy's response in thread:Populate combo box list dynamically for each row in javaFx table view
I adapted his code a little bit to specifically fit my needs. This solved a problem with values disappearing from the job category field and from data transferring from the job category field to the Job field.
This was one of the harder pieces of code I've had to troubleshoot. It was a combination of how the ComboBoxTableCell operates, the dynamic data of my comboboxes, and a slip in the which setter I was calling. It was about a perfect storm of flubs that the program saw no exceptions for as a result.
Thank you for the help

Creating subtree with QTreeWidgetItem

Im trying to create a subtree using QTreeWidgetItem.
Here's code
m_pRoot = new QTreeWidgetItem(treeWidget);
m_pRoot->setText(0, "root");
m_pRoot->setData(0, Qt::UserRole, IT_ROOT);
createTreeItem(m_pRoot, m_pText, "subtree_1", IT_TEXT);
m_pRoot->setExpanded(true);
createTreeItem(m_pText, m_pPlainText, "subtree_2", IT_TEXT);
that's method:
void createTreeItem(PTR(QTreeWidgetItem) parent, PTR(QTreeWidgetItem) item, CREF(QString) name, ItemType itemType)
{
item = new QTreeWidgetItem(parent);
item->setText(0, name);
item->setData(0, Qt::UserRole, QVariant(itemType));
}
It's ok when im creating a "subtree_1" with m_pRoot as root item, but it breaks down when i want to create "subtree_2" with m_pText as root item.
P.S PTR() equal *parent.
Cant understand what's the problem. Any suggestions?
If your PTR(QTreeQWidgetItem) macro yields QTreeWidgetItem*, then item is not initialized by createTreeItem function.
The simplest and most logical fix seems to change createTreeItem function to return new item:
QTreeWidgetItem* createTreeItem(PTR(QTreeWidgetItem) parent, PTR(QTreeWidgetItem) item,
CREF(QString) name, ItemType itemType)
{
item = new QTreeWidgetItem(parent);
item->setText(0, name);
item->setData(0, Qt::UserRole, QVariant(itemType));
return item;
}
and use the returned value to initialize m_pText.

QAbstactTableModel insert at top

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();
}

Resources