GTK# treeview hierarchical data display - mono

I am currently working with mono and gtk#.
Regarding the TreeView there is this Tutorial.
I want to achieve the same thing thats presented under "Controlling how the model is used"
So i have the Song Class and the Render-Methods to display artist and title.
But I want to display it via a TreeStore instead of a ListStore. So that I have a Rootnode for each Letter and under this node all Artists starting with this letter should be displayed.
My problem how can I add these RootNodes to the TreeStore? And where should I add them?
songs.Add(new Song("Dancing Djs vs. Roxette", "Fading like a flower"));
songs.Add(new Song("Xaiver","give me the right"));
songs.Add(new Song("Daft Punkt","Technologic"));
TreeStore musicListStore = new TreeStore(typeof(Song));
foreach (var s in songs)
{
musicListStore.AppendValues(s);
}
treeview1.Model = musicListStore;
treeview1.AppendColumn("Artist", new CellRendererText(),new TreeCellDataFunc(RenderArtistName));
treeview1.AppendColumn("Title", new CellRendererText(),new TreeCellDataFunc(RenderSongTitle));
private void RenderArtistName(TreeViewColumn column, CellRenderer cell, TreeModel model, TreeIter iter)
{
Song s = model.GetValue(iter,0) as Song;
(cell as CellRendererText).Text = s.Artist;
}
private void RenderSongTitle(TreeViewColumn column, CellRenderer cell, TreeModel model, TreeIter iter)
{
Song s = model.GetValue(iter,0) as Song;
(cell as CellRendererText).Text = s.Title;
}
So i want to achieve that there are RootNodes for each letter and underneath each letter there should be all Artists listed starting with this letter.
My problem is how to add the letter to the TreeStore plus how do i know where to insert each Song then.
Here is a screenshot how i would like it to look like(I am not allowed to upload them directly. So i Had to use an external hosted. Sry):
Screenshot

You can build up your tree quite easily. Eg;
var store = new Gtk.TreeStore( typeof(string) );
// add a root node
var root = store.AppendValues("hello");
// add a child of the root
store.AppendValues(root,"world");
// add another child
var mono = store.AppendValues(root,"mono");
// add a second level child
store.AppendValues(mono,"gtk");
So, in the context of your music app..
// title, artist
var store = new Gtk.TreeStore( typeof(string), typeof(string) );
// make an index of top level nodes using thier TreeIters
var index = new Dictionary<string,Gtk.TreeIter>();
// add index nodes
foreach ( var letter in new List<string>{ "A", "B", "C" ... "Z" } ){
index[letter.ToLower()] = store.AppendValues( letter );
}
// add songs
foreach ( var song in songlist ){
var title = song.Title;
var artist = song.Artist;
var first = title.SubString(0,1).ToLower();
var iter = store[first];
// add this song
store.AppendValues( iter, title, artist );
}
You will have to do some extra work if you want to dynamically add index nodes, each time you add a node at a level all your treeiter values at that level or deeper become worthless.

Related

using flatbuffers.Builder.Create*()

I want to use flatbuf to save aquadtree structure. here is my fbs file
namespace com.generated;
struct Obj {
hash:int;
geohash:uint64;
}
table Tree {
obj:[Obj];
id:int;
nodes:[Tree];
}
root_type Tree;
and here is the code that I am using to make objects
var builder = new flatbuffers.Builder(0)
var Tree = com.generated.Tree;
var Obj = com.generated.Obj;
Tree.startTree(builder);
Tree.addId(builder, builder.createInt(1));
Tree.addObj(builder, Obj.createObj(builder, 36, 42));
var offset = Tree.endTree(builder);
Tree.startTree(builder);
Tree.addId(builder, builder.createInt(1));
Tree.addObj(builder, Obj.createObj(builder, 36, 42));
offset = Tree.endTree(builder);
builder.finish(offset);
well in code above I have two problems, First the builder.createInt(1) does not exist. So I do not know how I can create an Integer. And my second problem is with the making an array of Trees, I am currently after Tree.end start another Tree with the same builder. Is this the correct way to do that?

Why aren't my Sharepoint List contents being saved to the list?

I'm successfully creating a Sharepoint List (named "XMLToPDFTestList"), which I can see via Site Actions > View All Site Content, but my attempts to add columns to the list has so far proven fruitless.
Here is how I'm trying to do it:
private void ProvisionallyCreateList()
{
SPWeb mySite = SPContext.Current.Web;
// Check to see if list already exists; if so, exit
if (mySite.Lists.TryGetList(listTitle) != null) return;
SPListCollection lists = mySite.Lists;
SPListTemplateType listTemplateType = new SPListTemplateType();
listTemplateType = SPListTemplateType.GenericList;
string listDescription = "This list is to hold inputted vals";
lists.Add(listTitle, listDescription, listTemplateType);
// Now add a couple of columns
SPList list = lists["XMLToPDFTestList"];
string faveNum = list.Fields.Add("favoriteNumber", SPFieldType.Text, false);
list.Fields[faveNum].Description = "favorite number";
list.Fields[faveNum].Update();
string faveCol = list.Fields.Add("favoriteColor", SPFieldType.Text, false);
list.Fields[faveCol].Description = "favorite color";
list.Fields[faveCol].Update();
}
This is all I see when I click "XMLToPDFTestList":
My "gut feeling" is that this line:
SPList list = lists["XMLToPDFTestList"];
...is not right/not specific enough. Instead of "XMLToPDFTestList" it should be something else/prepend something, or so. But what, exactly?
It was, as is so often the case, "my bad" (YMMV?).
The problem is in my list item creation code which, because I was not assigning anything to the default/inherited "Title" field, made it appear to me (as in the scream shot above) that no item was being added.
Once I fixed the code, by changing this:
private void SaveInputToList()
{
using (SPSite site = new SPSite(siteUrl))
{
using (SPWeb web = site.RootWeb)
{
SPList list = web.Lists[listTitle];
SPListItem SPListItemFaveNum = list.Items.Add();
SPListItemFaveNum["favoriteNumber"] = "7"; //inputtedNumber; TODO: Once 7 and teal are being saved and retrieved successfully, assign the var vals - will need to declare the controls created in CreateChildControls() globally
SPListItemFaveNum.Update();
SPListItem SPListItemFaveHue = list.Items.Add();
SPListItemFaveHue["favoriteColor"] = "teal";
SPListItemFaveHue.Update();
}
}
}
...to this:
private void SaveInputToList()
{
using (SPSite site = new SPSite(siteUrl))
{
using (SPWeb web = site.RootWeb)
{
SPList list = web.Lists[listTitle];
SPListItem spli = list.Items.Add();
spli["Title"] = "Write the Title";
spli["favoriteNumber"] = "7";
//SPListItemFaveNum.Update();
//SPListItem SPListItemFaveHue = list.Items.Add();
spli["favoriteColor"] = "teal";
//SPListItemFaveHue.Update();
spli.Update();
}
}
}
...it works fine: an item is added with all three values (Title, favoriteNumber, and favoriteColor).
I was assuming the item wasn't being created because "Title" was blank, and I was calling update on each SPListItem, whereas all I really need to do is call Update once, and on one SPListItem, not multiple.

Sitecore Lucene search - hit count differs from result count

I have the following method to return search results based on a supplied query
private List<Item> GetResults(QueryBase qBase)
{
using (IndexSearchContext sc = SearchManager.GetIndex("story").CreateSearchContext())
{
var hits = sc.Search(qBase, int.MaxValue);
var h1 = hits.FetchResults(0, 25);
var h2 = h1.Select(r => r.GetObject<Item>());
var h3 = h2.Where(item => item != null);
return h3.ToList();
}
}
The index being searched indexes web and master content. If I pass in a query that I know matches a single published item and break at the line beginning var h2 = then I see the variable hits has 2 items. This I expect because actually the items are both the same item, one from web and one from master.
However, the variable h1 only has a single result. The result from web has been omitted.
This is the case whether I'm debugging in the context of web or master. Can anyone explain?
When fetching the items using FetchResults method, Sitecore groups the items from lucene by the id of the item. First of the items becomes a SearchResult in the resulting SearchResultCollection object, and other items become Subresults for this results.
For example if you have a home item with id {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} with one published version and 4 versions in different languages for the home item, what you'll get from lucene is a single result and 4 subresults for this result:
using (IndexSearchContext sc = SearchManager.GetIndex("story").CreateSearchContext())
{
var hits = sc.Search(qBase, int.MaxValue);
var h1 = hits.FetchResults(0, 25);
foreach (SearchResult result in h1)
{
var url = result.Url;
foreach (SearchResult subresult in result.Subresults)
{
var subUrl = subresult.Url; // other versions of this item
}
}
}
The urls for results and subresults in my case would be:
sitecore://web/{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}?lang=en&ver=1
sitecore://master/{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}?lang=en&ver=1 (subresult)
sitecore://master/{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}?lang=ja-JP&ver=1 (subresult)
sitecore://master/{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}?lang=de-DE&ver=1 (subresult)
sitecore://master/{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}?lang=da&ver=1 (subresult)
so for retrieving the all the items with their versions you can use this code:
private List<Item> GetResults(QueryBase qBase)
{
using (IndexSearchContext sc = SearchManager.GetIndex("story").CreateSearchContext())
{
var hits = sc.Search(qBase, int.MaxValue);
var h1 = hits.FetchResults(0, 25);
var h2 = h1.Select(r => r.GetObject<Item>()).ToList();
// add other versions of item to the resulting list
foreach (IEnumerable<SearchResult> subresults in h1.Select(sr => sr.Subresults))
{
h2.AddRange(subresults.Select(r => r.GetObject<Item>()));
}
var h3 = h2.Where(item => item != null);
return h3.ToList();
}
}
You can not assume with item will be returned as the first one from the lucene and which items will be returned as subresults. If you want to get any specific item you need to pass version number, language and database to the query.

How do I iterate through a list of items in a Ext.dataview.List

I'm currently trying to find out how to set items to be selected on a list in ST2.
I've found the following:
l.select(0, true);
l.select(1, true);
which would select the first 2 items on my list. But the data coming from the server is in csv format string with the ids of the items in the list to be selected.
e.g. "4, 10, 15"
So I currently have this code at the moment.
doSetSelectedValues = function(values, scope) {
var l = scope.getComponent("mylist");
var toSet = values.split(",");
// loop through items in list
// if item in list has 'id' property matching whatever is in the toSet array then select it.
}
The problem is I can't seem to find a way of iterating over the items in the list and then inspect the "id" property of the item to see if it matches with the item in the array.
l.getItems()
Doesn't seem to return an array of items. The list is populated via a store with the "id" & "itemdesc" properties. I just want to be able to select those items from a csv string. I've scoured the Api on this and I can't seem to find a way of iterating over the items in the list and being able to inspect its backing data.
the Ext.List's items are not the items you are looking for. The items under the Ext.List object are those:
Ext.create('Ext.List', {
fullscreen: true,
itemTpl: '{title}',
store: theStore,
**items: [item1, item2]**
});
Granted, usually an Ext.List doesn't have items like these. What you are looking for are the Ext.Store items. The Ext.Store items are the exact same items in the same order as presented in the Ext.List.
To iterate over those, and select the corresponding items in the list, do the following:
var s = l.getStore();
var itemIndicesToSelect = [];
for (var i = 0 ; i < s.data.items.length ; i++){
if (arrayContainsValue(toSet, s.data.items[i].data.id)){
itemIndicesToSelect.push(i);
}
}
for (var i = 0 ; i < itemIndicesToSelect.length ; i++){
l.selectRange(itemIndicesToSelect[i], itemIndicesToSelect[i], true);
}
You would have to implement the function arrayContainsValue (one possible solution).
doSetSelectedValues = function(values, scope) {
var l = scope.getComponent("mylist"),
store = l.getStore(),
toSet = values.split(",");
Ext.each(toSet, function(id){
l.select(store.getById(id), true);
});
}

Conditionally adjust visible columns in Rally Cardboard UI

So I want to allow the user to conditionally turn columns on/off in a Cardboard app I built. I have two problems.
I tried using the 'columns' attribute in the config but I can't seem to find a default value for it that would allow ALL columns to display(All check boxes checked) based on the attribute, ie. the default behavior if I don't include 'columns' in the config object at all (tried null, [] but that displays NO columns).
So that gets to my second problem, if there is no default value is there a simple way to only change that value in the config object or do I have to encapsulate the entire variable in 'if-else' statements?
Finally if I have to manually build the string I need to parse the values of an existing custom attribute (a drop list) we have on the portfolio object. I can't seem to get the rally.forEach loop syntax right. Does someone have a simple example?
Thanks
Dax - Autodesk
I found a example in the online SDK from Rally that I could modify to answer the second part (This assumes a custom attribute on Portfolio item called "ADSK Kanban State" and will output values to console) :
var showAttributeValues = function(results) {
for (var property in results) {
for (var i=0 ; i < results[property].length ; i++) {
console.log("Attribute Value : " + results[property][i]);
}
}
};
var queryConfig = [];
queryConfig[0] = {
type: 'Portfolio Item',
key : 'eKanbanState',
attribute: 'ADSK Kanban State'
};
rallyDataSource.findAll(queryConfig, showAttributeValues);
rally.forEach loops over each key in the first argument and will execute the function passed as the second argument each time.
It will work with either objects or arrays.
For an array:
var array = [1];
rally.forEach(array, function(value, i) {
//value = 1
//i = 0
});
For an object:
var obj = {
foo: 'bar'
};
rally.forEach(obj, function(value, key) {
//value = 'bar'
//key = 'foo'
});
I think that the code to dynamically build a config using the "results" collection created by your query above and passed to your sample showAttributeValues callback, is going to look a lot like the example of dynamically building a set of Table columns as shown in:
Rally App SDK: Is there a way to have variable columns for table?
I'm envisioning something like the following:
// Dynamically build column config array for cardboard config
var columnsArray = new Array();
for (var property in results) {
for (var i=0 ; i < results[property].length ; i++) {
columnsArray.push("'" + results[property][i] + "'");
}
}
var cardboardConfig = {
{
attribute: 'eKanbanState',
columns: columnsArray,
// .. rest of config here
}
// .. (re)-construct cardboard...
Sounds like you're building a neat board. You'll have to provide the board with the list of columns to show each time (destroying the old board and creating a new one).
Example config:
{
attribute: 'ScheduleState'
columns: [
'In-Progress',
'Completed'
]
}