void fetchinventory(object x)
        {
            recursion++;
            invthreaddata itd = (invthreaddata)x;
             			UUID start=itd.key;
            TreeIter iter = itd.iter;
            bool cache = itd.cacheonly;
            bool alreadyseen=true;
            bool recurse = itd.recurse;
            List<InventoryBase> myObjects;
            List <invthreaddata> runners= new List<invthreaddata>();

            System.Threading.AutoResetEvent prefetch=new AutoResetEvent(false);
            TreePath path=null;

            Gtk.Application.Invoke(delegate
            {

                path = inventory.GetPath(iter);

                 if (path == null)
                 {
                     Logger.Log("*!*!*!*! WTF? we got a NULL path in the fetchinventory()",Helpers.LogLevel.Debug);
                     return;
                 }

                 path.Down();

                 if (MainClass.client == null)
                 {
                     recursion--;
                     return;
                 }

                 InventoryNode node = MainClass.client.Inventory.Store.GetNodeFor(start);
                 if (node.NeedsUpdate == true)
                 {
                     alreadyseen = false;
                 }

                 //Check for a waiting here, we need to use this to decide which fetcher to use in a moment
                 if (cache == false)
                 {
                     TreeIter childiter;
                     inventory.GetIter(out childiter, path);
                     if ("Waiting..." == (string)inventory.GetValue(childiter, 1))
                     {
                         alreadyseen = false;
                     }
                 }

                 prefetch.Set();
            });

            prefetch.WaitOne();

            // Use an approprate fetcher based on various flags
            if(cache==true || alreadyseen==true)
                myObjects = MainClass.client.Inventory.Store.GetContents(start);
            else
             	            myObjects = MainClass.client.Inventory.FolderContents(start, MainClass.client.Self.AgentID, true, true, InventorySortOrder.ByDate, 30000);

            //Logger.Log("Got objects # "+myObjects.Count.ToString(),Helpers.LogLevel.Debug);

            AutoResetEvent postfetch = new AutoResetEvent(false);

            Gtk.Application.Invoke(delegate
            {
                if (myObjects == null || myObjects.Count==0)
                {
                    recursion--;
                    postfetch.Set();
                    return;
                }

                //Logger.Log("Possible refilter",Helpers.LogLevel.Debug);
                if(filteractive==true)
                {
                   filter.Refilter();
                   filter.Refilter(); //*sigh*
                }

                this.label_fetched.Text="fetched "+this.no_items.ToString()+" items";

            List<InventoryBase> folders = new List<InventoryBase>();

            foreach (InventoryBase item in myObjects)
            {

                if(item.Name=="Trash" && item is InventoryFolder && trash_folder==UUID.Zero)
                {
                    trash_folder=item.UUID;
                }

                if (assetmap.ContainsKey(item.UUID))
                {
                    TreeIter iterx = assetmap[item.UUID];
                    InventoryBase itemx = (InventoryBase)inventory.GetValue(iterx,3);
                    if (itemx is InventoryFolder)
                    {
                        invthreaddata itd2 = new invthreaddata(item.UUID, path.ToString(), iterx,cache,true);
                        runners.Add(itd2);
                        //fetchinventory((object)itd2);
                    }
                    continue;
                }

                   this.no_items++;
                   Gdk.Pixbuf buf = getprettyicon(item);

                   global_thread_tree = inventory.AppendValues(iter, buf, item.Name, item.UUID, item);

                   if (!assetmap.ContainsKey(item.UUID))
                           assetmap.Add(item.UUID, global_thread_tree);

                    Gtk.TreeIter iter2=global_thread_tree;

                     if (item is InventoryFolder)
                     {
                        inventory.AppendValues(iter2, item_object, "Waiting...", item.UUID, null);
                        invthreaddata itd2 = new invthreaddata(((InventoryFolder)item).UUID, "", iter2,cache,true);
                        runners.Add(itd2);

                        if (abortfetch == true)
                        {
                            postfetch.Set();
                            return;
                        }
                     }
            }

            //We should preserve Waiting... messages for folders we don't yet have the children for
            //or else the user can't open them as there is no + to click on. But we need to get rid
            // of them for folders we have just got the data for!
            if (cache == false || (cache == true && myObjects.Count > 0))
            {
                TreeIter childiter;
                inventory.GetIter(out childiter, path);
                if ("Waiting..." == (string)inventory.GetValue(childiter, 1))
                {
                    inventory.Remove(ref childiter);

                    alreadyseen = false;
                }
            }

            postfetch.Set();
            });

            postfetch.WaitOne();

            if (abortfetch == true)
                return;

            if (myObjects == null || myObjects.Count == 0)
                return;

            if (recurse)
            {
                foreach (invthreaddata itdn in runners)
                {
                    if (abortfetch == true)
                        return;

                    fetchinventory((object)itdn);
                }
            }

            recursion--;

            if (recursion == 0)
            {
                fetcherrunning = false;
                if(cache==false && recurse==true)
                {
                    fetchrun=true;
                    Logger.Log("Fetch Complete",Helpers.LogLevel.Debug);

                    Gtk.Application.Invoke(delegate{
                        this.label_fetched.Text="fetched "+this.no_items.ToString()+" items (Finished)";
                    });
                 }
            }
            return;
        }
        protected virtual void OnEntrySearchChanged(object sender, System.EventArgs e)
        {
            lock(inventory)
            {
            if(fetchrun==false && fetcherrunning==false)
            {
                Logger.Log("Starting Inventory Fetch all",Helpers.LogLevel.Info);
                fetcherrunning = true;
                Thread invRunner = new Thread(new ParameterizedThreadStart(fetchinventory));
                invthreaddata itd = new invthreaddata(MainClass.client.Inventory.Store.RootFolder.UUID, "0:0", TLI,false,true);
                invRunner.Start(itd);
            }

            filteractive = true;

            filter.ClearCache();
            filtered.Clear(); //*sigh*

            if (this.entry_search.Text == "")
            {
                filteractive = false;
                filter.Refilter();
                return;
            }

            //Becuase we use our own filter we have to do two passes at the data to first find matches, then to find parents of matches

            filter.Refilter();
            filter.Refilter(); //*sigh*

            treeview_inv.ExpandAll();
            }
        }
        void populate_top_level_inv()
        {
            lock (inventory)
            {
                if (MainClass.client.Inventory.Store.Items != null)
                {
                    foreach (KeyValuePair<UUID, InventoryNode> kvp in MainClass.client.Inventory.Store.Items)
                    {
                        if (kvp.Value.Data != null)
                        {
                            if (kvp.Value.Data.ParentUUID == UUID.Zero)
                            {
                                if (!assetmap.ContainsKey(MainClass.client.Inventory.Store.RootFolder.UUID))
                                {
                                    InventoryFolder fdr = new InventoryFolder(MainClass.client.Inventory.Store.RootFolder.UUID);
                                    fdr.Name = "My Inventory";
                                    Gtk.TreeIter iterx = inventory.AppendValues(folder_closed, kvp.Value.Data.Name, kvp.Value.Data.UUID, fdr);
                                    Console.Write("Creating top level folder " + kvp.Value.Data.Name + " : " + MainClass.client.Inventory.Store.Items[kvp.Value.Data.UUID].ToString());
                                    assetmap.Add(MainClass.client.Inventory.Store.RootFolder.UUID, iterx);
                                    inventory.AppendValues(iterx, folder_closed, "Waiting...", kvp.Value.Data.UUID, null);
                                    if (kvp.Value.Data.Name == "My Inventory")
                                        TLI = iterx;
                                }

                            }
                            Console.Write(kvp.Value.Data.ParentUUID.ToString() + " : ");
                        }
                    }

                    this.no_items = 0;
                    MainClass.client.Inventory.Store.RestoreFromDisk(MainClass.client.Settings.ASSET_CACHE_DIR + System.IO.Path.DirectorySeparatorChar + MainClass.client.Inventory.Store.RootFolder.UUID.ToString() + ".osl");

                    fetcherrunning = true;
                    Thread invRunner = new Thread(new ParameterizedThreadStart(fetchinventory));
                    invthreaddata itd = new invthreaddata(MainClass.client.Inventory.Store.RootFolder.UUID, "0", TLI, true, true);
                    invRunner.Start(itd);
                }
            }
        }
 protected virtual void OnButtonFetchAllInvClicked(object sender, System.EventArgs e)
 {
     if (fetcherrunning == false)
     {
         fetcherrunning = true;
         Thread invRunner = new Thread(new ParameterizedThreadStart(fetchinventory));
         invthreaddata itd = new invthreaddata(MainClass.client.Inventory.Store.RootFolder.UUID, "0:0", TLI,false,true);
         invRunner.Start(itd);
     }
 }
        void onRowExpanded(object o,Gtk.RowExpandedArgs args)
        {
            lock (inventory)
            {

                // Avoid updaing rows in the middle of a filter operation
                if (filteractive == true)
                    return;

                //We can't do this or it confuses the hell out of stuff
                //if (fetcherrunning == true)
                  //  return;

                try
                {
                    TreeIter iter = filter.ConvertIterToChildIter(args.Iter);

                    UUID key = (UUID)this.inventory.GetValue(iter, 2);

                    if (inventory.GetValue(iter, 0) == folder_closed)
                        inventory.SetValue(iter, 0, folder_open);

                    TreePath path = inventory.GetPath(iter);
                    path.Down();
                    TreeIter iter2;
                    inventory.GetIter(out iter2, path);

                    string Name = inventory.GetValue(iter2, 1).ToString();
                    //if (Name == "Waiting...")
                    {

                        Thread invRunner = new Thread(new ParameterizedThreadStart(fetchinventory));
                        invthreaddata itd = new invthreaddata(key, filter.ConvertPathToChildPath(args.Path).ToString(), iter, false, false);
                        invRunner.Start(itd);

                    }
                }
                catch
                {

                }

            }
        }