fe034ff15e0840faa023fb8e95621cc263005587
[roobuilder] / src / Project / Project.vala
1 //<Script type="text/javascript">
2
3 /**
4  * Project Object
5  * 
6  * Projects can only contain one directory... - it can import other projects..(later)
7  * 
8  * we need to sort out that - paths is currently a key/value array..
9  * 
10  * currently we store projects in ~/.Builder/{md5}.json
11    - then for Gtk projects we have a file config1.builder - which contains dependancies, and a list of files for each target
12      (for builder it's ended up in src/Builder/config1.builder? by accident.
13    - should really support something like 
14        roobuilder --build {path_to_cfg} {target} - or local directory if not set..
15        roobuilder --build-errors {path_to_cfg} {target} - or local directory if not set..
16        
17        
18    
19    
20    should really store project data in the directory of the project?
21    
22    
23    // steps:
24    // List of projects - just an array of paths in .Builder/Projects.json
25    
26    // .roobuilder.jcfg  << hidden file with project details?
27    
28    
29    
30  
31  * 
32  * 
33  */
34 namespace Project {
35          public errordomain Error {
36                 INVALID_TYPE,
37                 NEED_IMPLEMENTING,
38                 MISSING_FILE,
39                 INVALID_VALUE,
40                 INVALID_FORMAT
41         }
42
43         // static array of all projects.
44         private Gee.ArrayList<Project>  projects;
45         
46         
47         
48         public bool  projects_loaded = false;
49
50         
51         
52         public abstract class Project : Object {
53                 
54                 public signal void on_changed (); 
55         
56                 //public string id;
57                 //public string fn = ""; // just a md5...
58                 public string name  { 
59                         private set {} 
60                         owned get {
61                                 return GLib.Path.get_basename(path);
62                         }
63                          
64                 }
65                                 
66                 
67                 public string path = "";
68                 private Gee.ArrayList<JsRender.JsRender> sub_paths;
69                 
70                 private Gee.HashMap<string,JsRender.JsRender> files ;  // contains full list of files.
71                 //tree : false,
72                 public  string xtype;
73                 
74                 //public Json.Object json_project_data;
75
76                 public Palete.Palete palete;
77                  
78                 private bool is_scanned = false; 
79                 public  Gee.HashMap<string,Palete.GirObject> gir_cache = null; // used by Gir ??? is this used by Roo?
80                  public Palete.ValaCompileRequest last_request = null;
81                 
82                 protected Project (string path) {
83                         
84                          
85                         //this.json_project_data = new Json.Object();
86                         
87                         this.is_scanned = false;
88                         this.sub_paths = new Gee.ArrayList<JsRender.JsRender>();
89                         this.files = new Gee.HashMap<string,JsRender.JsRender>();
90                         //XObject.extend(this, cfg);
91                         //this.files = { }; 
92                         this.path = path;
93                          
94                         
95                         
96                 }
97                  
98                 
99                 
100                 
101                 public static void loadAll(bool force = false)
102                 {
103                         if (projects_loaded && !force) {
104                                 return;
105                         }
106
107                         var dirname = GLib.Environment.get_home_dir() + "/.Builder";
108                         var dir = File.new_for_path(dirname);
109                         if (!dir.query_exists()) {
110                                 try {
111                                         dir.make_directory();
112                                 } catch(GLib.Error e) {
113                                         GLib.error("could not make builder directory");
114                                 }
115                                 return;
116                         }
117                         projects = new  Gee.ArrayList<Project>();
118                           
119                     
120                     if (FileUtils.test(dirname + "/Projects.list", GLib.FileTest.IS_REGULAR)) {
121                         loadProjectList();
122                         projects_loaded = true;
123                         return;
124                 }
125                 convertOldProjects(); // this saves..
126                 foreach(var p in projects) {
127                         p.save();
128                 }
129                         projects_loaded = true;
130  
131         }
132          
133         public static void remove(Project p) {
134                 projects.remove(p);
135                 saveProjectList();
136         
137         }
138         
139         public static void saveProjectList()
140         {
141                         var f = new Json.Object();
142                         foreach(var p in projects) {
143                                 f.set_string_member(p.path, p.xtype);
144                         }
145                         
146                         var  generator = new Json.Generator ();
147                         var  root = new Json.Node(Json.NodeType.OBJECT);
148                         root.init_object(f);
149                         generator.set_root (root);
150                         generator.pretty = true;
151                         generator.indent = 4;
152
153                         var data = generator.to_data (null);
154                         var dirname = GLib.Environment.get_home_dir() + "/.Builder";
155                 GLib.debug("Write new Project list\n %s", data);
156                 //Posix.exit(0);
157                 
158                 try {
159                                 //FileUtils.set_contents(dirname + "/" + this.fn + ".json", s, s.length);  
160                                 FileUtils.set_contents(dirname + "/Projects.list", data, data.length);  
161                         } catch (GLib.Error e) {
162                                 GLib.error("failed  to save file %s", e.message);
163                         }
164                 
165         }
166         
167         
168         
169         public static void convertOldProjects()
170         {
171         
172                         var dirname = GLib.Environment.get_home_dir() + "/.Builder";
173                         var  dir = File.new_for_path(dirname);
174                         try {
175                                 var file_enum = dir.enumerate_children(
176                                                                 GLib.FileAttribute.STANDARD_DISPLAY_NAME, 
177                                         GLib.FileQueryInfoFlags.NONE, 
178                                         null
179                                 );
180                                  
181                                 FileInfo next_file; 
182                                 while ((next_file = file_enum.next_file(null)) != null) {
183                                         var fn = next_file.get_display_name();
184                                         if (!Regex.match_simple("\\.json$", fn)) {
185                                                 continue;
186                                         }
187                                         Project.factoryFromFileOld(dirname + "/" + fn);
188                                 }       
189                         } catch(GLib.Error e) {
190                                 GLib.warning("oops - something went wrong scanning the projects\n");
191                         }
192                         GLib.debug("Loaded all old Projects - saving");
193                         Project.saveProjectList();
194
195                 }
196
197                 public static Gee.ArrayList<Project> allProjectsByName()
198                 {
199                         
200                         return projects;
201                 
202                 }
203                 
204                 public static Project? getProjectByName(string name)
205                 {
206                         
207                         foreach (var p in projects) {
208                                 if (p.name == name) {
209                                         return p;
210                                 }
211                         }
212                         
213                         return null;
214                 
215                 }
216                 public static Project? getProjectByPath(string path)
217                 {
218                         
219                         foreach (var p in projects) {
220                                 if (p.path == path) {
221                                         return p;
222                                 }
223                         }
224                         
225                         return null;
226                 
227                 }
228                 public static string listAllToString()
229                 {
230                         var all = projects;
231
232                          
233                         
234                         all.sort((fa,fb) => {
235                                 return ((Project)fa).name.collate(((Project)fb).name);
236
237                         });
238
239                         var iter = all.list_iterator();
240                         var ret = "ID\tName\tDirectory\n";
241                         while (iter.next()) {
242                                 ret += "%s\t%s\n".printf(
243                                                  
244                                                 iter.get().name,
245                                                 iter.get().path
246                                                 );
247                          
248                                 
249                         }
250                         
251                         return ret;
252                 
253                 }
254                 
255                 
256                 public static void loadIntoStore(GLib.ListStore st)
257                 {
258                         st.remove_all();
259                         foreach (var p in projects) {
260                                 st.append(p);
261                         }
262                         
263                 }
264                         
265                 
266  
267                 
268                 static void loadProjectList()
269                 {
270                 
271                         var dirname = GLib.Environment.get_home_dir() + "/.Builder";
272                          
273                         projects = new  Gee.ArrayList<Project>();
274                           
275                     var pa = new Json.Parser();
276                         try { 
277                                 pa.load_from_file(dirname + "/Projects.list");  
278                         } catch (GLib.Error e) {
279                                 GLib.error("could not load json file %s", e.message);
280                         }
281                         var node = pa.get_root();
282                         if (node == null || node.get_node_type () != Json.NodeType.OBJECT) {
283                                 GLib.error( dirname + "/Projects.list - invalid format?");
284                                  
285                         }
286
287                         
288                         var obj = node.get_object ();
289                         obj.foreach_member((sobj, key, val) => {
290                                 GLib.debug("read ProjectList %s: %s", key, val.get_string());
291                                 // facotry adds project!
292                                 try {
293                                         Project.factory(val.get_string(), key );
294                                 } catch (GLib.Error e ) {
295                                         GLib.debug("error createing project %s", e.message);
296                                 }
297                                  
298                         });
299                         
300                 
301                 }
302                 
303                 // load project data from project file.
304                 public static void   factoryFromFileOld(string jsonfile)
305                 {
306                          
307                         GLib.debug("parse %s", jsonfile);
308
309                         var pa = new Json.Parser();
310                         try { 
311                                 pa.load_from_file(jsonfile);
312                         } catch (GLib.Error e) {
313                                 GLib.error("could not load json file %s", e.message);
314                         }
315                         var node = pa.get_root();
316
317                         
318                         if (node == null || node.get_node_type () != Json.NodeType.OBJECT) {
319                                 GLib.debug("SKIP " + jsonfile + " - invalid format?");
320                                 return;
321                         }
322                         
323                         var obj = node.get_object ();
324                         var xtype =  obj.get_string_member("xtype");
325
326
327                         var paths = obj.get_object_member("paths");
328                         var i = 0;
329                         var fpath = "";
330                         paths.foreach_member((sobj, key, val) => {
331                                 if (i ==0 ) {
332                                         fpath = key;
333                                 }
334                                         
335                         });
336                         
337                         if (fpath.length < 0 || !FileUtils.test(fpath,FileTest.IS_DIR)) {
338                                 return;
339                         }
340                         
341                         Project proj;
342                         try {
343                                 proj = factory(xtype, fpath);
344                         } catch (Error e)  {
345                                 GLib.debug("Skip file - invalid file type");
346                                 return;
347                         }
348
349                         //proj.json_project_data  = obj; // store the original object...
350                         
351                         //proj.fn =  Path.get_basename(jsonfile).split(".")[0];
352
353                         proj.loadJson(obj);
354                         // might not exist?
355  
356                         proj.name = obj.get_string_member("name");
357
358                         // used to load paths..
359                         //proj.initSubDirectories();
360                         
361                          
362                         //proj.initDatabase();
363                         
364                         GLib.debug("Add Project %s", proj.name);
365                         
366                         projects.add(proj);
367                          
368                         
369                 }
370                 
371                 
372                 public static Project factory(string xtype, string path) throws Error
373                 {
374
375                         // check to see if it's already loaded..
376
377                          foreach(var p in projects) {
378                                   if (p.path == path) {
379                                         return p;
380                                  }
381                         }
382
383                         
384                         switch(xtype) {
385                                 case "Gtk":
386                                         var ret =  new Gtk(path);
387                                         projects.add(ret);
388                                         
389                                         return ret;
390                                 case "Roo":
391                                         var ret = new Roo(path);
392                                         projects.add(ret);
393                                  
394                                         return ret;
395                                 //case "Flutter":
396                                 //      return new Flutter(path);
397                         }
398                         throw new Error.INVALID_TYPE("invalid project type");
399                                 
400                 }
401                 
402                 
403          
404
405                 public void save()
406                 {
407                                 // fixme..
408                         
409                  
410
411                         
412
413                         //var dirname = GLib.Environment.get_home_dir() + "/.Builder";
414                         
415                         var  s =  this.toJSON();
416                         GLib.debug("Save Project %s\n%s", this.name, s);
417                         try {
418                                 //FileUtils.set_contents(dirname + "/" + this.fn + ".json", s, s.length);  
419                                 FileUtils.set_contents(this.path + "/.roobuilder.jcfg", s, s.length);  
420                         } catch (GLib.Error e) {
421                                 GLib.error("failed  to save file %s", e.message);
422                         }
423                         
424                 }
425
426         
427                 
428                 
429                 public string toJSON( )
430                 {
431                         
432                         var obj = new Json.Object();
433                         obj.set_string_member("xtype", this.xtype);
434                                                 
435                         
436                         this.saveJson(obj);
437                 
438                         var  generator = new Json.Generator ();
439                         var  root = new Json.Node(Json.NodeType.OBJECT);
440                         root.init_object(obj);
441                         generator.set_root (root);
442                         //if (show_all) {
443                                 generator.pretty = true;
444                                 generator.indent = 4;
445                         //}
446
447                         return  generator.to_data (null);
448                           
449                           
450                 }
451                 
452                 // used to check what type a project might be..
453                 // for 'new'
454                 public static string peekProjectType(string fn) 
455                 {
456                         var pa = new Json.Parser();
457                         try { 
458                                 pa.load_from_file(fn);
459                         } catch (GLib.Error e) {
460                                 GLib.debug("could not load json file %s", e.message);
461                                 return "";
462                                 
463                         }
464                         var node = pa.get_root();
465
466                         if (node == null || node.get_node_type () != Json.NodeType.OBJECT) {
467                                 GLib.debug("SKIP %s/.roobuilder.jcfg  - invalid format?",fn);
468                                 return "";
469                         }
470                         
471                         var obj = node.get_object ();
472
473                         var xtype =  obj.get_string_member("xtype");
474                         return xtype == null ? "" : xtype;
475                 
476                 }
477                 
478                 
479                 // this will do a full scan - should only be done on viewing project..
480                 // not initial load.. - may take time.
481                 
482                 public   void   load()
483                 {
484                         if (this.is_scanned) {
485                                 return;
486                         }
487                         GLib.debug("load is_scanned = false");
488                         
489                         if (FileUtils.test(this.path + "/.roobuilder.jcfg", FileTest.EXISTS)) {
490                                   
491                                 var pa = new Json.Parser();
492                                 try { 
493                                         pa.load_from_file(this.path + "/.roobuilder.jcfg");
494                                 } catch (GLib.Error e) {
495                                         GLib.error("could not load json file %s", e.message);
496                                 }
497                                 var node = pa.get_root();
498
499                                 
500                                 if (node == null || node.get_node_type () != Json.NodeType.OBJECT) {
501                                         GLib.debug("SKIP %s/.roobuilder.jcfg  - invalid format?",this.path);
502                                         return;
503                                 }
504                                 
505                                 var obj = node.get_object ();
506                                  
507                                 this.loadJson(obj);
508                         } 
509                         // used to load paths..
510                         this.sub_paths = new Gee.ArrayList<JsRender.JsRender>();
511                         this.files = new Gee.HashMap<string,JsRender.JsRender>();
512                         this.loadSubDirectories("", 0);
513                          
514                         this.initDatabase();
515                         this.is_scanned = true; // loaded.. dont need to do it again..
516                          GLib.debug("load is_scanned = true");
517                         
518                 }
519                 
520                 public abstract void loadJson(Json.Object obj); 
521                 public abstract void saveJson(Json.Object obj);
522                 
523                 /*
524                 
525                 public string firstPath()
526                 {
527                         var iter = this.paths.map_iterator();
528                         while (iter.next()) {
529                                 return iter.get_key();
530                         }
531                   
532                         return "";
533                 }
534
535                 public bool hasPath(string path)
536                 {
537                         var iter = this.paths.map_iterator();
538                         while (iter.next()) {
539                                 if (iter.get_key() == path) {
540                                 return true;
541                         }
542                         }
543                   
544                         return false;
545                 }
546
547                 
548                 // returns the first path
549                 public string getName()
550                 {
551                         var iter = this.paths.map_iterator();
552                         while (iter.next()) {
553                                 return GLib.Path.get_basename(iter.get_key());
554                         }
555                   
556                         return "";
557                 }
558                 */
559
560                 public Gee.ArrayList<JsRender.JsRender> sortedFiles()
561                 {
562                         var files = new Gee.ArrayList<JsRender.JsRender>();
563
564                         var fiter = this.files.map_iterator();
565                         while(fiter.next()) {
566                                 files.add(fiter.get_value());
567                         }
568                         files.sort((fa,fb) => {
569                                 return ((JsRender.JsRender)fa).name.collate(((JsRender.JsRender)fb).name);
570
571                         });
572                         return files;
573
574                 }
575                 
576          
577          
578                 public string listAllFilesToString()
579                 {
580                  
581                         var iter = this.sortedFiles().list_iterator();
582                         var ret = "ID\tName\tDirectory\n";
583                         while (iter.next()) {
584                                 ret += "%s\n".printf(
585                                                  
586                                                 iter.get().name
587                                                  
588                                                 );
589                          
590                                 
591                         }
592                         
593                         return ret;
594                 
595                 }
596                 
597          
598          
599          
600                 public JsRender.JsRender? getByName(string name)
601                 {
602                         foreach(var f in this.files.values) {
603                                 if (f.name == name) {
604                                         return f;
605                                 }
606                         };
607                         return null;
608                 }
609                 // this get's a file using the full path ( replaces vala->bjs if they exist);
610                 
611                 public JsRender.JsRender? getByPath(string path)
612                 {
613                  
614                         // keys are not paths...
615                         foreach(var f in this.files.values) {
616                                 GLib.debug("check %s = %s ? %s", path, f.path, f.targetName());
617                                 if (f.path == path || f.targetName() == path) {
618                                         return f;
619                                 }
620                         };
621                         return null;                    
622                 }
623                 
624                 public JsRender.JsRender? getById(string id)
625                 {
626                         foreach(var f in this.files.values) {
627                                 if (f.id == id) {
628                                         return f;
629                                 }
630                         };
631                         return null;
632                 }
633  
634                 // name should include extension.       
635                 /*
636                 public JsRender.JsRender? newFile (string xtype, string sub_dir, string name)
637                 {
638                         try {
639                                 var fp = this.path + (sub_dir.length > 0  ? "/" : "") + sub_dir;
640                                 if (this.files.has_key(fp + "/" +  name)) {
641                                         return null;
642                                 }
643                                  
644                                 
645                                 var ret =  JsRender.JsRender.factory(xtype, 
646                                                                                          this, 
647                                                                                          fp + "/" +  name
648                                                                                          );
649                                 this.files.set(fp + "/" +  name , ret);
650                                 return ret;
651                         } catch (JsRender.Error e) {
652                                 GLib.error("failed to create file %s", e.message);
653                         }
654                 }
655                 */
656          
657                 public JsRender.JsRender loadFileOnly (string path)
658                 {
659                         var xt = this.xtype;
660                         try {
661                                 return JsRender.JsRender.factory(xt, this, path);
662                         } catch (JsRender.Error e) {
663                                 GLib.error("failed to create file %s", e.message);
664                         } 
665                         
666                 } 
667                 
668                 /* 
669                 public JsRender.JsRender create(string filename)
670                 {
671                         var ret = this.loadFileOnly(filename);
672                         ret.save();
673                         this.addFile(ret);
674                         return ret;
675                         
676                 }
677                 */
678                 private void loadSubDirectories(string subdir, int dp) 
679                 {
680                         //dp = dp || 0;
681                         //print("Project.Base: Running scandir on " + dir +"\n");
682                         if (dp > 5) { // no more than 5 deep?
683                                 return;
684                         }
685                         if (subdir == "build") { // cmake!
686                                 return;
687                         }
688                         
689                         if (subdir == "autom4te.cache") { // automake?
690                                 return;
691                         }
692                         if (subdir == "debian") { // debian!?
693                                 return;
694                         }
695
696                         
697                         var dir = this.path + (subdir.length > 0 ? "/" : "") + subdir;
698                         
699                         
700                         GLib.debug("Project %s Scan Dir: %s", this.name, dir);
701                         var jsDir = new JsRender.Dir(this, dir);
702                         this.sub_paths.add(jsDir); // might be ''...
703                         
704                         
705                         // this should be done async -- but since we are getting the proto up ...
706                         var other_files = new Gee.ArrayList<string>();
707                         var bjs_files = new Gee.ArrayList<string>();
708                         var vala_files = new Gee.ArrayList<string>();
709                         var subs = new Gee.ArrayList<string>();
710                         
711                         
712                         var f = File.new_for_path(dir);
713                         try {
714                                 var file_enum = f.enumerate_children(GLib.FileAttribute.STANDARD_DISPLAY_NAME, GLib.FileQueryInfoFlags.NONE, null);
715                                 
716                                  
717                                 FileInfo next_file; 
718                                 while ((next_file = file_enum.next_file(null)) != null) {
719                                         var fn = next_file.get_display_name();
720                         
721                                          
722                                         //print("trying"  + dir + "/" + fn +"\n");
723                                         
724                                         if (fn[0] == '.') { // skip hidden
725                                                 continue;
726                                         }
727                                         
728                                         if (FileUtils.test(dir  + "/" + fn, GLib.FileTest.IS_DIR)) {
729                                                 subs.add(dir  + "/" + fn);
730                                                 continue;
731                                         }
732                                         if (Regex.match_simple("\\.(o|cache|gif|jpg|png|gif|out|stamp|~)$", fn)) { // object..
733                                                 continue;
734                                         }
735                                         if (Regex.match_simple("^(config1.builder|a.out|stamp-h1|depcomp|config.log|config.status)$", fn)) { // object..
736                                                 continue;
737                                         }
738                                         
739                                         
740                                         if (Regex.match_simple("\\.vala$", fn)) {
741                                                 vala_files.add(fn);
742                                                 other_files.add(fn);
743                                                 //print("no a bjs\n");
744                                                 continue;
745                                         }
746                                         if (!Regex.match_simple("\\.bjs$", fn)) {
747                                                 other_files.add(fn);
748                                                 //print("no a bjs\n");
749                                                 continue;
750                                         }
751                                         bjs_files.add(fn.substring(0, fn.length-4));
752                                         
753                                         var xt = this.xtype;
754                                         var el = JsRender.JsRender.factory(xt,this, dir + "/" + fn);
755                                         this.files.set( dir + "/" + fn, el);
756                                         jsDir.childfiles.append(el);
757                                         
758                                         // parent ?? 
759                                         
760                                          
761                                 }
762                         } catch (Error e) {
763                                 GLib.warning("Project::scanDirs failed : " + e.message + "\n");
764                         } catch (GLib.Error e) {
765                                 GLib.warning("Project::scanDirs failed : " + e.message + "\n");
766                         } 
767
768                         foreach(var fn in other_files) {
769                                 var dpos = fn.last_index_of(".");
770                                 var without_ext = fn.substring(0, dpos);
771                                 if (bjs_files.contains(without_ext)) {  // will remove vala and c.
772                                         continue;
773                                 }
774                                 // c with a vala - skip
775                                 if (Regex.match_simple("\\.c$", fn) && vala_files.contains(without_ext + ".vala")) {
776                                         continue;
777                                 }
778                                 // Makefile (only allow am files at present.
779                                 if (without_ext == "Makefile") {
780                                         if (!Regex.match_simple("\\.am$", fn)) {
781                                                 continue;
782                                         }
783                                 }
784                                 if (without_ext == "configure") {
785                                         if (!Regex.match_simple("\\.ac$", fn)) {
786                                                 continue;
787                                         }
788                                 }
789                                 
790                                 
791                                 
792                                 
793                                 
794                                 //GLib.debug("Could have added %s/%s", dir, fn);
795                                 try {
796                                          var el = JsRender.JsRender.factory("PlainFile",this, dir + "/" + fn);
797                                          this.files.set( dir + "/" + fn, el);
798                                         jsDir.childfiles.append(el);
799                                 } catch (JsRender.Error e) {
800                                         GLib.warning("Project::scanDirs failed : " + e.message + "\n");
801                                 }
802                         }
803                         
804                         foreach (var sd in subs) {
805                                  this.loadSubDirectories(sd.substring(this.path.length+1), dp+1);
806                         }
807                         
808                 
809                 }
810                 
811                 // calle dfrom new file dialog
812                 // add files to dires 
813                 // update 
814                         
815                  
816                 public void addFile(JsRender.JsRender pfile)
817                 { // add a single file, and trigger changed.
818                 
819                         if (pfile.xtype == "Gtk" || pfile.xtype == "Roo" ) {
820                                 this.files.set(pfile.path, pfile); // duplicate check
821                                 
822                                 if (pfile.xtype == "Gtk" && pfile.build_module != "") {
823                                 
824                                         var gfile = (JsRender.Gtk) pfile;
825                                         gfile.updateCompileGroup("", pfile.build_module);
826                                          
827                                 }
828                         }
829                         var sp = this.findDir(pfile.dir);
830                         sp.childfiles.append(pfile);    
831                                 
832
833                         this.on_changed();
834                 }
835                 
836                 
837                 
838                 public void deleteFile(JsRender.JsRender file) 
839                 {
840                         if (file.xtype =="Dir") {
841                                 return;
842                         }
843                         var sp = this.findDir(file.dir);
844                         for(var i =0;i < sp.childfiles.n_items; i++) {
845                                 var jf = (JsRender.JsRender) sp.childfiles.get_item(i);
846                                 if (jf.path == file.path) {
847                                         sp.childfiles.remove(i);
848                                         break;
849                                 }
850                         }
851                         if (this.files.has_key(file.path)) {
852                                 this.files.unset(file.path);
853                         }
854
855                         
856                         file.remove();
857                         // remove it from 
858                         
859                         
860                 }
861                         
862                 // but do not add it to our list.!!!
863                 public void makeProjectSubdir(string name)
864                 {
865                         var dir = File.new_for_path(this.path + "/" + name);
866                         if (FileUtils.test(this.path + "/" + name, FileTest.EXISTS)) {
867                                 return;
868                         }
869                         try {
870                                  
871                                 dir.make_directory();   
872                         } catch (GLib.Error e) {
873                                 GLib.error("Failed to make directory %s", this.path + "/" + name);
874                         } 
875                 }
876                 
877                 public void createDir(string subdir)   // add a single dir, and trigger changed.
878                 {
879                         if (subdir.strip() == "" || this.subpathsContains(subdir)) {
880                                 return;
881                         }
882                         var dir= File.new_for_path(this.path + "/" + subdir);
883
884                         if (!dir.query_exists()) {
885                         
886                                 try {
887                                          
888                                         dir.make_directory();   
889                                 } catch (GLib.Error e) {
890                                         GLib.error("Failed to make directory %s", this.path + "/" + name);
891                                 }
892
893                         }
894                         this.sub_paths.add(new JsRender.Dir(this,this.path + "/" + subdir));
895                         this.on_changed();  // not sure if it's needed - adding a dir doesnt really change much.
896                 }
897                 
898                 // this store is used in the icon view ?? do we need to store and update it?
899                 public void loadFilesIntoStore(GLib.ListStore ls) 
900                 {
901                         ls.remove_all();
902                         //GLib.debug("Load files (into grid) %s", this.name);                   
903                         foreach(var f in this.files.values) {
904                         //      GLib.debug("Add file %s", f.name);
905                                 if (f.xtype == "PlainFile") {
906                                         continue;
907                                 }
908                                 ls.append(f);
909                         }
910                         
911                 }
912                 public void loadDirsIntoStore(GLib.ListStore  ls) 
913                 {
914                         ls.remove_all();
915                         foreach(var f in this.sub_paths) {
916                                 //GLib.debug("Add %s", f.name);
917                                 ls.append(f);
918                         }
919                          ;
920                 }
921                 
922                 public bool subpathsContains(string subpath) 
923                 {
924                         foreach(var sp in this.sub_paths) {
925
926                                 if (sp.path == this.path + "/" + subpath) {
927                                         return true;
928                                 }
929                         }
930                         return false;
931                         
932                 }
933                 public void loadDirsToStringList( global::Gtk.StringList sl) 
934                 {
935                          
936                         while (sl.get_n_items() > 0) {
937                                 sl.remove(0);
938                         }
939                         
940                         foreach(var sp in this.sub_paths) {
941                                  
942                                 sl.append( sp.path == this.path ? "/" : sp.path.substring(this.path.length));
943                         }
944                 
945                 }
946                 
947                 public JsRender.Dir? findDir(string path) {
948                         
949                         foreach(var jdir in this.sub_paths) { 
950                                 if (path == jdir.path) {
951                                         return (JsRender.Dir)jdir;
952                                 }
953                         }
954                         return null;
955                 }
956                 
957                 public string[] pathsMatching(string name, bool full_path)
958                 {
959                         string[] ret = {};
960                          
961                         foreach(var jdir in this.sub_paths) { 
962                                 
963
964                                 
965                                 if (Path.get_basename (jdir.path) == name) {
966                                         GLib.debug("pathsMatching %s\n", jdir.path);
967                                         ret += full_path ? jdir.path : jdir.relpath;
968                                 }
969                                 
970                         }
971                         return ret;
972                         
973                 }
974                 public Gee.ArrayList<string> readArray(Json.Array ar) 
975                 {
976                         var ret = new Gee.ArrayList<string>();
977                         for(var i =0; i< ar.get_length(); i++) {
978                                 var add = ar.get_string_element(i);
979                                 if (ret.contains(add)) {
980                                         continue;
981                                 }
982                         
983                                 ret.add(add);
984                         }
985                         return ret;
986                 }
987                 
988                  
989                  public abstract void initDatabase();
990                  public abstract void initialize(); // for new projects (make dirs?);
991                   
992         }
993 }
994