I clear all the existing controls from the form using this code.
QFormLayout *formLayoutFunction;
void DeleteExistingControls()
{
QLayoutItem *child;
comboBoxFunctions->blockSignals(true);
comboBoxFunctions->clear();
comboBoxFunctions->blockSignals(false);
while ((child = formLayoutFunction->takeAt(0)) != 0) {
delete child->widget();
delete child;
}
}
The problem is that after executing this function the widgets of QHBoxLayout are still present.
In the form i have multiple QHBoxLayouts and i want to delete them all.
This is how i deleted the widgets of QHboxLayout.
while ((child = formLayoutFunction->takeAt(0)) != 0) {
if (child->layout() != 0)
{
QLayout *ly = child->layout();
QLayoutItem* layoutItem ;
while (ly->count() != 0){
layoutItem = ly->takeAt(0);
delete layoutItem->widget();
delete layoutItem;
}
}
delete child->widget();
delete child;
}
Related
I am trying to add a new row to my QFormLayout after I have loaded two QLineEdits from a file, which works, but when I run my code it doesnt add anything, ot atleast anything that I can see. And I am also not able to add any wigets using QLayout::addWidget(QWidget* widget) anymore, which I used to be able to.
Thanks
The code, where it doesnt work:
void Kegelbuch::load(QString path, QString tab) {
//Load json file
Datastream* loadStream = new Datastream;
QJsonObject data = loadStream->loadData(path);
//Declaring all important Variables
QJsonArray keglerFullName;
QJsonArray keglerShortName;
QFormLayout* formLayout = (QFormLayout*)ui.keglerTab->layout();
int defaultRows = 2, width = 155;
//Retriev arrays from file
if (data.contains("KeglerFullName") && data["KeglerFullName"].isArray()) {
keglerFullName = data["KeglerFullName"].toArray();
}
if (data.contains("KeglerShortName") && data["KeglerShortName"].isArray()) {
keglerShortName = data["KeglerShortName"].toArray();
}
//Correctly add QLineEdits to the FormLayout
for (auto names : boost::combine(keglerFullName, keglerShortName)) {
QLineEdit fullNameEdit;
QLineEdit shortNameEdit;
QJsonValue fullNameValue, shortNameValue;
boost::tie(fullNameValue, shortNameValue) = names;
if (fullNameValue.isString()) {
fullNameEdit.setText(fullNameValue.toString());
fullNameEdit.setObjectName("fullName");
fullNameEdit.setMinimumWidth(width);
}
if (shortNameValue.isString()) {
shortNameEdit.setText(shortNameValue.toString());
shortNameEdit.setMaximumWidth(width);
shortNameEdit.setObjectName("shortName");
}
/*
if (keglerFullName.at(1).isString()) {
fullNameEdit->setText(keglerFullName.at(1).toString());
fullNameEdit->setObjectName("fullName");
fullNameEdit->setMinimumWidth(width);
}
if (keglerShortName.at(1).isString()) {
shortNameEdit->setText(keglerShortName.at(1).toString());
shortNameEdit->setMaximumWidth(width);
shortNameEdit->setObjectName("shortName");
}
*/
formLayout->addRow(&fullNameEdit, &shortNameEdit);
}
}
Ok I did it. It works fine. Thanks for help. Here is my code. Now I only need to call my command button in a differend form to disable it and create a info there. Anyone could look about it ? In my code I got reference errors.
[ExtensionOf(formdatasourcestr(ProdTableListPage, ProdTable))]
final class ProdParmReportFinishedActiveWG_Extension
{
public int active()
{
int ret;
next Active();
{
ProdTable tableBuffer = this.cursor();
ProdTable prodtable;
if(tableBuffer.ProdId == tableBuffer.CollectRefProdId
&& tableBuffer.ProdStatus != ProdStatus::ReportedFinished)
{
select firstonly RecId,ProdId from ProdTable where
ProdTable.CollectRefProdId == tableBuffer.ProdId
&& ProdTable.Prodstatus != ProdStatus::ReportedFinished
&& tableBuffer.RecId != prodtable.RecId;
{
Global::info(strFmt("%1 , %2",
prodtable.prodid, prodtable.recid));
// FormButtonControl mybutton = this.FormRun().design().controlname(formControlStr(ProdParmReportFinished, Ok)) as FormButtonControl;
// mybutton.enabled(false);
}
}
else
{
Global::info(strFmt("%1 , %2, %3, %4",
tableBuffer.prodid, tableBuffer.CollectRefProdId, tableBuffer.InventRefType, tableBuffer.ProdStatus));
}
}
return ret;
}
}
"I want to use this code everytime user changes his actual row but instead it runs just once and apply to all my rows."
Use the selectionChanged() method instead of active().
In fact most use cases where you think you should use active(), you're probably looking for selectionChanged() (or the OnSelectionChanged event for handlers) instead.
I'm currently using TAB to navigate to next cell. selectNext() or selectRightCell() works fine when I'm using SelectionMode.SINGLE.
However, when using SelectionMode.MULTIPLE, its selecting multiple cells as I TAB.
I'm using a TableView. I need SelectionMode.MULTIPLE for the copy & paste function.
Is there a way to make it work in SelectionMode.MULTIPLE?
fixedTable.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
switch (event.getCode()){
case TAB:
if (event.isShiftDown()) {
fixedTable.getSelectionModel().selectPrevious();
} else {
fixedTable.getSelectionModel().selectNext();
}
event.consume();
break;
case ENTER:
return;
case C:
if(event.isControlDown()){
copySelectionToClipboard(fixedTable) ;
}
event.consume();
break;
case V:
if(event.isControlDown()){
pasteFromClipboard(fixedTable);
}
event.consume();
break;
default:
if (fixedTable.getEditingCell() == null) {
if (event.getCode().isLetterKey() || event.getCode().isDigitKey()) {
TablePosition focusedCellPosition = fixedTable.getFocusModel().getFocusedCell();
fixedTable.edit(focusedCellPosition.getRow(), focusedCellPosition.getTableColumn());
}
}
break;
}
}
});
You will need to handle the selection on your own. The reason is because the methods selectPrevious() and selectNext() tries to select the previous ( or the next ) without removing the current selected row ( when you set the selection mode to be SelectionMode.MULTIPLE) , also you can't use them and just remove the previous selecting by just calling clearSelection() because this will set the selected index to -1 and then the methods selectPrevious() and selectNext() will select the last or the first row only.
Here is how you could implement the selection on your own :
// the rest of your switch statement
...
case TAB:
// Find the current selected row
int currentSelection = table.getSelectionModel().getSelectedIndex();
// remove the previous selection
table.getSelectionModel().clearSelection();
if (event.isShiftDown()) {
currentSelection--;
} else {
currentSelection++;
}
// find the size of our table
int size = table.getItems().size() - 1;
// we was on the first element and we try to go back
if(currentSelection < 0){
// either do nothing or select the last entry
table.getSelectionModel().select(size);
}else if(currentSelection > size) {
// we are at the last index, do nothing or go to 0
table.getSelectionModel().select(0);
}else {
// we are between (0,size)
table.getSelectionModel().select(currentSelection);
}
event.consume();
break;
...
I have a custom QTreeWidget class with the dropEvent() method overridden.
Here is the method:
void QCustomTreeWidget::dropEvent(QDropEvent * event)
{
QModelIndex droppedIndex = indexAt(event->pos());
if (!droppedIndex.isValid())
return;
// other logic
QTreeWidget::dropEvent(event);
}
How can I determine if the item will be inserted above, inside or below the item on which it is dropped?
You need to use the DropIndicatorPosition. With a switch statement, you can easily achieve what you want.
bool bAbove = false; // boolean for the case when you are above an item
QModelIndex dropIndex = indexAt(event->pos());
DropIndicatorPosition dropIndicator = dropIndicatorPosition();
if (!dropIndex.parent().isValid() && dropIndex.row() != -1)
{
switch (dropIndicator)
{
case QAbstractItemView::AboveItem:
// manage a boolean for the case when you are above an item
bAbove = true;
break;
case QAbstractItemView::BelowItem:
// something when being below an item
break;
case QAbstractItemView::OnItem:
// you're on an item, maybe add the current one as a child
break;
case QAbstractItemView::OnViewport:
// you are not on your tree
break;
}
if(bAbove) // you are above an item
{
// manage this case
}
}
What i want is that if i enter an ID in the textbox and then press enter,then if the ID is present ,then it gets displayed on the table the valuesof the table are inserted with the help of map in another window from which this window Box1 is opened as map.So as far as i have an idea,we have to run find command of map and then using if loop if that entered value in textbox is presentthen will display it in the same way as dummy data is displayed.
code used
Box1::Box1(QWidget *parent)
:QDialog(parent)
{
searchgroup = new QGroupBox(tr("Data Search"));
QHBoxLayout *layout2 = new QHBoxLayout;
text = new QLineEdit(this);
searchh = new QLabel(tr("&Enter ID:"));
searchh->setBuddy(text);
layout2->addWidget(searchh);
layout2->addWidget(text);
searchgroup->setLayout(layout2);
tableegroup = new QGroupBox(tr("Searched Data"));
QVBoxLayout *layout1 = new QVBoxLayout;
tablee = new QTableView(this);
mode1 = new QStandardItemModel(1,2,this);
mode1->setHorizontalHeaderItem(0, new QStandardItem(QString("ID")));
mode1->setHorizontalHeaderItem(1, new QStandardItem(QString("DATA")));
map<int,QString>::iterator itt;
itt=dataa.begin();
for (int colu = 0; colu < 2; colu++)
{
item1 = new QStandardItem();
if (colu == 0)
{
item1->setData(((*itt).first), Qt::DisplayRole);
mode1->setItem(0,0,item1);
} else
{
item1->setData(((*itt).second), Qt::DisplayRole);
mode1->setItem(0,1,item1);
}
}
tablee->setModel(mode1);
layout1->addWidget(tablee);
tableegroup->setLayout(layout1);
QVBoxLayout *mainlayout1 = new QVBoxLayout;
//mainlayout1->addWidget(menubarr);
mainlayout1->addWidget(searchgroup);
mainlayout1->addWidget(tableegroup);
setLayout(mainlayout1);
}
Thanks for any help in advance
EDIT
what i want
void Box1::textReturn()
{
bool ok;
int id = text->text().toInt(&ok);
// map<int,QString>::iterator itt;
if (ok && dataa.contains(id))
{
// add row (id, data[id] to table
}
else
{
QMessageBox msgbox = new QMessagebox();
msgbox->setWindowTitle("Alert");
msgbox->setText("No such ID present!");
msgbox->show();
}
}
EDIT2
void Box1::textReturn()
{
int id = (text->text()).toInt();
map<int,QString>::iterator itt;
itt = dataa.find(id);
if(itt != dataa.end()) //returns 1 if we found something
{
QList<QStandardItem *> items;
items << new QStandardItem(QString("%1").arg(id));
items << new QStandardItem((*itt).second);
mode1->appendRow(items);
tablee->update();
}
else
{
QMessageBox *msgbox = new QMessageBox();
msgbox->setWindowTitle("Alert");
msgbox->setText("INVALID ID ENTERED");
msgbox->show();
}
}
As #KCiebiera said, you have to do this connection
connect(text, SIGNAL(returnPressed()), this, SLOT(textReturnPressed());
Then you need to find your key in the table using
QList<QStandardItem *> QStandardItemModel::findItems ( const QString & text,
Qt::MatchFlags flags = Qt::MatchExactly, int column = 0 )
As you have map, so elements shouldn't repeat, your QList should be NULL or contains just one element. When u'll get your element (as QStandardItem) you just need to invoke
tablee->showColumn ( int column )
tablee->showRow ( int row )
Where your column will be QStandarItem->column() and row QStandardItem->row();
EDIT
void Box1::textReturnPressed()
{
int id = (test->text()).toInt();
map<int, string>::iterator it;
it = dataa.find(id);
if(it != dataa.end()) //we found something
{
QList<QStandardItem *> items;
items << new QStandardItem(QString("%1").arg(id));
items << new QStandardItem((*it).second);
mode1->appendRow(items);
}
else
QMessageBox::information(this, "Info", "ID not found!", QMessageBox::ok);
}
Something like this;
As far as I understand your question. You need to create a new slot in the Box1 class. Let's call it textReturnPressed(). Then you have to connect it to returnPressed() signal from text
connect(text, SIGNAL(returnPressed()), this, SLOT(textReturnPressed());
and here is textReturnPressed (I hope it compiles)
void textReturnPressed()
{
bool ok;
int id = text->text().toInt(&ok);
if (ok && dataa.count(id) > 0) {
QList<QStandardItem *> items;
items << new QStandardItem(QString("%1").arg(id));
items << new QStandardItem(dataa[id]);
mode1.appendRow(items);
}
}
You don't need an iterator to check if an item is in the map. Just call map.count() function.