setObjectValue:nil not called to deleted NSTableCellView - nstableview

I'm using a View Based NSTableView and binding to display content of my objects.
When I delete one of them, the tableView reflect the change, by removing the cell for this object.
The problem is that the NSTableCellView doesn't receive the setObjectValue: with nil or another object, and so the object referenceCount is not decremented, and my object never release.
Is there a way to override the tableView to force calling setObjectValue: when it cache deletedRows?
Thanks for your help.

I just found the solution right here.
https://devforums.apple.com/message/575883#575883
Just in case the link fail, the solution is to set it manually, in the following method
- (void)tableView:(NSTableView *)tableView didRemoveRowView:(NSTableRowView *)rowView forRow:(NSInteger)row NS_AVAILABLE_MAC(10_7);
{
for (NSInteger columnIndex = 0; columnIndex < [rowView numberOfColumns]; columnIndex++) {
[[rowView viewAtColumn:columnIndex] setObjectValue:nil];
}
}

Related

Set PurchReqLine.BuyingLegalEntity default value to blank

I encountered a problem in the development, requesting a new purchase request line of a purchase with a legal person with a default value of empty
I tried a variety of methods, the default value can not be overriden.
The following is my code.
[ExtensionOf(formDataSourceStr(PurchReqTable, PurchReqLine))]
final class IWS_PurchReqTable_FDS_Extension
{
public void initValue()
{
next initValue();
//ttsbegin;
PurchReqLine purchReqLine = this.cursor();
purchReqLine.BuyingLegalEntity = 0;
purchReqLine.modifiedField(fieldNum(PurchReqLine,BuyingLegalEntity));
this.rereadReferenceDataSources(); //Refresh value
this.reread();
this.research(1);
FormReferenceGroupControl BuyingLegalEntity = this.formRun().design().controlName(formControlStr(PurchReqTable, PurchReqLine_BuyingLegalEntity));
FormStringControl BuyingLegalEntity_DataArea = this.formRun().design().controlName(formControlStr(PurchReqTable, PurchReqLine_BuyingLegalEntity_DataArea));
BuyingLegalEntity.value(0);
BuyingLegalEntity.resolveChanges();
BuyingLegalEntity.referenceDataSource().research(1);
BuyingLegalEntity.modified();
//BuyingLegalEntity_DataArea.text('');
//BuyingLegalEntity_DataArea.modified();
purchReqLine.BuyingLegalEntity = 0;
purchReqLine.modifiedField(fieldNum(PurchReqLine,BuyingLegalEntity));
//purchReqLine.update();
//purchReqLine.insert();
//this.rereadReferenceDataSources();
//this.refresh();
//this.reread();
//this.resetLine();
//ttscommit;
}
//End
}
It is not totally clear to me what you are trying to do.
Most values are "born" zero or blank and if that is not the case for this field, something else is setting the field, maybe after your code in initValue is called. The cross reference may be of good value here to find the code that references the field.
First of, you should definitely not reference the controls, also calling modifiedField and research from here is a total no-go.
For a start try this:
public void initValue()
{
next initValue();
purchReqLine.BuyingLegalEntity = 0;
}
It simply sets the field to zero. Do not worry about the field control, it will be rendered from the buffer value after the call to initValue.
If that does not solve your problem, something else is setting the field. You can set a breakpoint here, then follow to code until the field is set. Also add the value to the watch list, maybe do conditional debugging.
If another extension for this datasource exist it may override your behaviour as the execution order of extensions is arbitrary.

Multiple OnSaving event in DevExpress XAF

Im working on a piece of code using DevExpress XAF, I noticed that if im using the event OnSaving that the code executes 2 times, how can i prevent that
protected override void OnSaving()
{
if (PrestamoP != null)
{
PrestamoP.Prestado -= Monto;
PrestamoP.Save();
}
else if (PrestamoG != null)
{
PrestamoG.Prestado -= Monto;
PrestamoG.Save();
}
base.OnSaving();
}
XPO does not guarantee that the OnSaving method is called once. See the corresponding note in the XPO Best Practices article.
I can see that you are changing the PrestamoP.Prestado property based on the value of the Monto property. This code is fine if you execute it only once and only when the Monto property is specified for the first time. This code is not fine if you:
Save this object without changing the Monto property;
Update the early specified Monto value.
So, it appears that a more complex logic is required for the PrestamoG.Prestado property. First, I would move it to the Monto property setter and take the previous value into account (do not forget to check the IsLoading property in this case). Second, I would consider calculating the Prestado value dynamically instead of storing its value. This will allow you to resolve issues with the duplicate business logic execution. See an example here: How to: Calculate a Property Value Based on Values from a Detail Collection.
I can offer different methods for CRUD functions on onSaving method.
IsNewObject, IsDeleted.
// insert
if (Session.IsNewObject(this))
{
a = new a(Session);
a.CreateReferencedProperties(this);
}
// delete
else if (IsDeleted)
{
a= Session.FindObject<A>(PersistentCriteriaEvaluationBehavior.InTransaction, CriteriaOperator.Parse("A=?", this));
if (a!= null)
a.Delete();
}
// update
else
{
a= Session.FindObject<A>(PersistentCriteriaEvaluationBehavior.InTransaction, CriteriaOperator.Parse("A=?", this));
if (a!= null)
a.CreateReferencedProperties(this);
}
You can use the code below to prevent xaf from entering on saving twice.
base.OnSaving();
SessionObjectLayer sessionObjectLayer = this.Session.ObjectLayer as SessionObjectLayer;
if (sessionObjectLayer == null || sessionObjectLayer.ParentSession == null)
{
//Enter only once
}

Qt: two actions in menu (with the same text)

I create a menu dynamically. I add several checkable actions into one menu. Sometimes actions may have the same text that user sees. It's up to user (actually user adds commands into menu).
The problem is in this case clicking works wrong. If I click on the first action (from 2 with the same texts) everything is good but if I click on the second one, both actions are selected. I don't understand why. The code where actions have been created is here:
for (int i = 0; i< currentList.size(); i++)
{
QString lanKey = currentList.at(i)->Language->toString();
QAction* lanAction = new QAction(this);
QString name ="action_" + currentList.at(i)->Id->toString();
lanAction->setObjectName(name);
lanAction->setText(lanKey);
lanAction->setCheckable(true);
lanAction->setData(i);
connect(lanAction, SIGNAL(triggered(bool)), this, SLOT(ShowSomething(bool)));
ui->menuMy->addAction(lanAction);
}
Here, lanKey is language that may be the same for different actions. Anyway click on the specific action should lead only to checking of this action. What's wrong?
The slot is here:
void VMainWindow::ShowSomething(bool IsTriggered)
{
QAction* senderAction = (QAction*)sender();
int listIndex = senderAction->data().toInt();
if (IsTriggered)
{
CreateEditor(subtitles, listIndex);
}
else
{
//hide this editor
QString name = "editor" + editorsList->Id->toString();
QDockWidget* editorDock = this->findChild<QDockWidget*>(name);
if (editorDock != 0)
{
this->removeDockWidget(editorDock);
this->setLayout(layout());
}
}
}
Thanks
The source of problem is found: it turned out that the slot finds the checked action wrong - by text, not by id.
I can't find a logical issue in the code you posted so far. Here are a couple of options which I would try in order to resolve this problem:
Limit the users possibilities when adding items to a menu so that he can't add two items with the same name.
Add qDebug() output to ShowSomething to see if there is a problem with signals&slots. For example, if the slot gets called once for the first item but twice for the second item there is a problem there.
Debug into CreateEditor step-by-step.
As the problem seems to appear only for actions with a similar name, you should make sure that you never make a lookup of an action (or something related) by its text() but rather by its data() or objectName() (assuming that currentList.at(i)->Id will always be unique)

Flex Detecting Dragged Data

I have a list that accepts drops. When an item is dropped (DragEvent.DRAG_DROP) I need to collect the data that is dropped, however I have found nothing in the event that helps me do so, event.dragInitiator.selectedItems would work but gives me an error.
Any help would be appreciated.
The data should be in event.dragSource. You'll have to check for the proper format using hasFormat() and retrieve it with dataForFormat(). Here are the docs for DragSource.
Code would be something like this (assuming this is Flex 4):
// In dragDrop handler or dragComplete
if (event.dragSource.hasFormat("itemsByIndex"))
{
var items:Vector.<Object> = event.dragSource.dataForFormat("itemsByIndex") as Vector.<Object>;
// Do stuff with items
}
You can also listen to changing dataProvider.
list.dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE, list_dataProvider_change);
...
protected function list_dataProvider_change(e :CollectionEvent) :void
{
if (e.kind == CollectionEventKind.REMOVE)
trace('list element removed from - index', e.location);
else if (e.kind == CollectionEventKind.ADD)
trace('list element added to - index', e.location);
}

How do I force all Tree itemrenderers to refresh?

I have item renderers in an mx.controls.Tree that I need to refresh on demand.
I have code in the updateDisplayList that fires for only some of the visible nodes no matter what I do. I've tried triggering a change that they should all be listening for; I have tried clearing and resetting the dataProvider and the itemRenderer properties.
private function forceCategoryTreeRefresh(event : Event = null) : void
{
trace("forceCategoryTreeRefresh");
var prevDataProvider : Object = CategoryTree.dataProvider;
CategoryTree.dataProvider = null;
CategoryTree.validateNow();
CategoryTree.dataProvider = prevDataProvider;
var prevItemRenderer : IFactory = CategoryTree.itemRenderer;
CategoryTree.itemRenderer = null;
CategoryTree.itemRenderer = prevItemRenderer as IFactory;
_categoriesChangeDispatcher.dispatchEvent(new Event(Event.CHANGE));
}
The nodes refresh properly when I scroll them into view (e.g. the .data gets set), but I cannot force the ones that already exist to refresh or reset themselves.
Any ideas?
Try calling this function on change event:
private function refreshList(e:Event):void{
listName.invalidateSize();
listName.invalidateList();
listName.invalidateDisplayList();
listName.validateSize(true);
listName.validateNow();
}
for me work quite well
Try
treeView.dataProvider = treeView.dataProvider;
That should update Tree view.
ItemRenderers in Flex are virtualized so there will not always be one ItemRenderer for each Tree node.
However, you can invalidate the nodes to force a refresh. The answer to this question gives an example of how to do that.

Resources