I have a treeTable with editable cells within the expanded rows. The editable cells get a dirty flag after editing (in the example the background color is set to red).
The problem i'm running into is that i found no certain way to update the dirty flag on expand/collapse (edited cells get the css class 'edited-cell').
At the moment the code looks like that:
// each editable textfield gets a Listener
textField.attachLiveChange(
var source = oEvent.oSource;
...
jQuery('#' + source.getId()).addClass(EDITED_CELL_CLASS, false)
// list with cell ids, e.g. "__field1-col1-row1"
DIRTY_MODELS.push(model.getId()) //*** add also binding context of row
)
// the table rows are updated on toggleOpenState
new sap.ui.table.TreeTable({
toggleOpenState: function(oEvent) {
...
this.updateRows() // see function below
}
})
// update Rows function is also delegated
oTable.addDelegate({ onAfterRendering : jQuery.proxy(this.updateRows, oTable)});
//http://stackoverflow.com/questions/23683627/access-row-for-styling-in-sap-ui5-template-handler-using-jquery
// this method is called on each expand/collapse: here i can make sure that the whole row has it's correct styling...
// but how to make sure that special cells are dirty?
function updateRows(oEvent) {
if (oEvent.type !== 'AfterRendering'){
this.onvscroll(oEvent);
}
var rows = this.getVisibleRowCount();
var rowStart = this.getFirstVisibleRow();
var actualRow;
for (var i = 0; i < rows; i++){
actualRow = this.getContextByIndex(rowStart + i); //content
var row = this.getRows()[i]
var obj = actualRow.getObject()
var rowId = row.getId()
updateStyleOfRows(obj, rowId, actualRow)
updateDirtyCells(rowId) //*** how to get the binding context in this function???
}
};
// update Dirty Cells in function updateRows():
function updateDirtyCells(rowId){
for (var i = 0; i < DIRTY_MODELS.length; i++){
var dirtyCellId = DIRTY_MODELS[i]
//*** make sure that only the correct expanded/collapsed rows will be updated -> depends on the bindingContext of the row
jQuery('#' + rowId).find('#' + dirtyCellId + '.editable-cell').addClass(EDITED_CELL_CLASS, false)
}
}
This doesn't work correctly, because the ids of the cells change on each layout render (e.g. collapse/expand rows). Please see attached image.
Let me know if i should provide more information.
Picture this: I have a JSON file which has a list of Node objects that contain a list of Link types. Something like:
node1:
links: node1,node2
node3,node1
node1,node6
node2:
links: node2,node1
node2,node9
node7,node2
I need to identify unique pairs of links - ie a (node_a,node_b) pair. Note that (node_b,node_a) represents the same thing.
The Link class has getter methods that return a pointer to either the source/destination Node. In the file, the information about the links is stored as a string that has the source node's name and the destination node name, like: (source,destination).
When I build my structure from file, I first create the Nodes and only then I create the Links. The Link constructor is as follows:
Link::Link(Node *fromNode, Node *toNode)
And my code to create the links:
QList<Link*> consumedLinks; // list where I was trying to place all the non-duplicate links
// for each node in the file
foreach(QVariant nodesMap, allNodesList){
QVariantMap node1 = nodesMap.toMap();
QList<QVariant> nodeDetails = node1["node"].toList();
QVariantMap allLinksMap = nodeDetails.at(9).toMap();
// extract all the links of the node to a list of QVariant
QList<QVariant> linksList = allLinksMap["links"].toList();
// for each Link in that list
foreach(QVariant linkMap, linksList){
QVariantMap details = linkMap.toMap();
Node *savedFromNode;
Node *savedToNode;
// get all the Items in the scene
QList<QGraphicsItem*> itemList = scene->items();
// cast each item to a Node
foreach(QGraphicsItem *item, itemList){
Node* tempNode = qgraphicsitem_cast<Node*>(item);
if(tempNode){
// check what the node name matches in the link list
if(tempNode->text()==details["fromNode"]){
savedFromNode = tempNode;
}
if(tempNode->text()==details["toNode"]){
savedToNode = tempNode;
}
}
}
// create the link
Link *linkToCheck = new Link(savedFromNode,savedToNode);
// add it to the links list (even if duplicate)
consumedLinks.append(linkToCheck);
}
}
// add all the links as graphics items in the scene
foreach(Link *linkToCheck, consumedLinks){
scene->addItem(linkToCheck);
}
So right now this doesn't check for duplicates in the consumedLinks list (obviously). Any ideas on how to achieve this?
NOTE: I know that the pseudo-JSON above isn't valid, it's just to give you an idea of the structure.
NOTE2: I rephrased and added detail and code to the question to make it clearer to understand what I need.
1. Normalize links i.e. replace (a, b) to (b, a) when b < a. Each link should be represented as (a, b), a < b.
2. Create a QSet< QPair<Node*, Node *> > variable and put all links into it. Each link object can be maked using qMakePair(node1, node2). Since QSet is an qnique container, all duplicates will be removed automatically.
Well, I didn't exactly do the same as #Riateche suggested, but something similar.
I basically created a QList<QPair<QString,QString> > so I could check for duplicates easily and then I created a list of Link based on the items in the QPair list. Something like:
QList<Node*> existingNodes;
QList<QPair<QString,QString> > linkPairList;
QList<QGraphicsItem*> itemList = scene->items();
foreach(QGraphicsItem *item, itemList){
Node* tempNode = qgraphicsitem_cast<Node*>(item);
if(tempNode){
existingNodes.append(tempNode);
}
}
foreach(QVariant nodesMap, allNodesList){
QVariantMap node1 = nodesMap.toMap();
QList<QVariant> nodeDetails = node1["node"].toList();
QVariantMap allLinksMap = nodeDetails.at(9).toMap();
QList<QVariant> linksList = allLinksMap["links"].toList();
foreach(QVariant linkMap, linksList){
QVariantMap details = linkMap.toMap();
QPair<QString,QString>linkPair(details["fromNode"].toString(),details["toNode"].toString());
QPair<QString,QString>reversedLinkPair(details["toNode"].toString(),details["fromNode"].toString());
if(!linkPairList.contains(linkPair)){
// !dupe
if(!linkPairList.contains(reversedLinkPair)){
// !reversed dupe
linkPairList.append(linkPair);
}
}
qDebug()<<"number of pairs: "<<linkPairList.size();
}
}
QPair<QString,QString> linkPairInList;
foreach(linkPairInList, linkPairList){
Node *savedFromNode;
Node *savedToNode;
foreach(Node* node, existingNodes){
if(node->text()==linkPairInList.first){
savedFromNode=node;
}
if(node->text()==linkPairInList.second){
savedToNode=node;
}
}
Link *newLink = new Link(savedFromNode,savedToNode, "input");
scene->addItem(newLink);
}
This is the correct answer because it solves what I needed to solve. Since I only got there because of #Riateche's comments, I +1'd his answer.
I want help in linked list implementation of a tree. A tree node has three child.
using pointers: Parent, Siblings and FirstChild.
I have tried making it but couldn't get it to work. I need help in inserting new nodes
void InsertFirstChild(Node newNode)
{
newNode.m_Parent = this;
newNode.m_NextSibling = m_FirstChild;
if (m_FirstChild != null)
m_FirstChild.m_PrevSibling = newNode;
else
m_LastChild = newNode;
m_FirstChild = newNode;
}
I have a set of components that are added to my Flex 4 stage dynamically.
Problem 1:
How do I address these objects when adding them to print.I cant generate objects on the fly and append them because then the print manager does not wait for the dynamic data to populate.
I currently use the following code to address items dynamically which fails:
public function PrintDashPreview():void{
var ItemsDrawn:int = 0;
var printJob:FlexPrintJob = new FlexPrintJob();
if(printJob.start()){
for each (var item:Object in GetDashBoardPreviewItems.lastResult.DashboardItem)
{
ItemsDrawn ++
this.addElement(dashPreview["flexShape" + TheID]);
printJob.addObject(dashPreview["flexShape" + TheID]);
this.removeElement(dashPreview["flexShape" + TheID]);
}
printJob.send()
Alert.show('Sent: ' + ItemsDrawn + ' items to page for printing.','Print Progress Debug');
}
}
How can I tell flex to grab these specific items and add them to the print job.
Problem 2:
How do I tell flex to lay each item out one below the other 2 per page.
Please and thank you for any help you can provide.
Regards
Craig Mc
The recipe for printing dynamic content usually goes like this:
(1) Start the printJob:
printJob = new FlexPrintJob();
printJob.printAsBitmap = false;
printJob.start();
(2) Obtain the print page dimensions. Use it if you have overflowing content:
printerPageHeight = printJob.pageHeight;
printerPageWidth = printJob.pageWidth;
(3) Create all of the dynamic objects and wait for the corresponding CREATION_COMPLETE events:
var componentsToBeInitialized:Number = 0;
var pages:Array = [];
for each (var itemData:Object in dataProvider) {
var component:UIComponent = new PageComponent();
someContainerOnTheDisplayList.addChild(component);
component.data = itemData;
componentsToBeInitialized ++;
pages.push(component);
component.addEventListener(FlexEvent.CREATION_COMPLETE, handlePageCompletion);
}
(4) Waiting for all CREATION_COMPLETE events:
function handlePageCompletion(e:Event):void {
componentsToBeInitialized --;
if (componentsToBeInitialized == 0)
printAllPages();
}
(5) Print the pages:
function printAllPages():void {
for each (var printPage:UIComponent in pages) {
printJob.addObject(printPage);
}
printJob.send();
}
In the big picture I want to create a frame based application in Bada that has a single UI control - a label. So far so good, but I want it to display a number of my choosing and decrement it repeatedly every X seconds. The threading is fine (I think), but I can't pass the label pointer as a class variable.
//MyTask.h
//...
result Construct(Label* pLabel, int seconds);
//...
Label* pLabel;
//MyTask.cpp
//...
result
MyTask::Construct(Label* pLabel, int seconds) {
result r = E_SUCCESS;
r = Thread::Construct(THREAD_TYPE_EVENT_DRIVEN);
AppLog("I'm in da constructor");
this->pLabel = pLabel;
this->seconds = seconds;
return r;
}
//...
bool
Threading::OnAppInitializing(AppRegistry& appRegistry)
{
// ...
Label* pLabel = new Label();
pLabel = static_cast<Label*>(pForm->GetControl(L"IDC_LABEL1"));
MyTask* task = new MyTask();
task->Construct(&pLabel); // HERE IS THE ERROR no matching for Label**
task->Start();
// ...
}
The problem is that I have tried every possible combination of *, &, and just plain pLabel, known in Combinatorics...
It is not extremely important that I get this (it is just for training) but I am dying to understand how to solve the problem.
Have you tried:
task->Construct(pLabel, 0);
And by that I want to point out that you are missing the second parameter for MyTask::Construct.
No, I haven't. I don't know of a second parameter. But this problem is solved. If I declare a variable Object* __pVar, then the constructor should be Init(Object* pVar), and if I want to initialize an instance variable I should write
Object* pVar = new Object();
MyClass* mClass = new MyClass();
mClass->Construct(pVar);