]>
Commit | Line | Data |
---|---|---|
32e219c2 | 1 | |
2 | #include "TROOT.h" | |
3 | #include "TSystem.h" | |
4 | #include "TApplication.h" | |
5 | #include "TGClient.h" | |
6 | #include "TGListTree.h" | |
7 | #include "TGLayout.h" | |
8 | #include "TGComboBox.h" | |
9 | #include "TContextMenu.h" | |
10 | #include "TGTextEntry.h" | |
11 | #include "TGTab.h" | |
12 | #include "TGLabel.h" | |
13 | #include "TSystemDirectory.h" | |
14 | #include "TGMimeTypes.h" | |
15 | #include "TClass.h" | |
16 | #include "TInterpreter.h" | |
17 | #include "TRegexp.h" | |
18 | #include "TEnv.h" | |
19 | #include "TImage.h" | |
20 | #include "TBrowser.h" | |
21 | #include <time.h> | |
22 | #include <string.h> | |
23 | ||
24 | #include "TGFileBrowser.h" | |
25 | #include "TGNewBrowser.h" | |
26 | ||
27 | #ifdef WIN32 | |
28 | const char rootdir[] = "\\"; | |
29 | #else | |
30 | const char rootdir[] = "/"; | |
31 | #endif | |
32 | ||
33 | const char *filters[] = { | |
34 | "", | |
35 | "*.*", | |
36 | "*.[C|c|h]*", | |
37 | "*.root", | |
38 | "*.txt" | |
39 | }; | |
40 | ||
41 | //////////////////////////////////////////////////////////////////////////////////// | |
42 | class TCursorSwitcher { | |
43 | private: | |
44 | TGWindow *fW1; | |
45 | TGWindow *fW2; | |
46 | public: | |
47 | TCursorSwitcher(TGWindow *w1, TGWindow *w2) : fW1(w1), fW2(w2) { | |
48 | if (w1) gVirtualX->SetCursor(w1->GetId(), gVirtualX->CreateCursor(kWatch)); | |
49 | if (w2) gVirtualX->SetCursor(w2->GetId(), gVirtualX->CreateCursor(kWatch)); | |
50 | } | |
51 | ~TCursorSwitcher() { | |
52 | if (fW1) gVirtualX->SetCursor(fW1->GetId(), gVirtualX->CreateCursor(kPointer)); | |
53 | if (fW2) gVirtualX->SetCursor(fW2->GetId(), gVirtualX->CreateCursor(kPointer)); | |
54 | } | |
55 | }; | |
56 | ||
57 | ClassImp(TGFileBrowser) | |
58 | ||
59 | //______________________________________________________________________________ | |
60 | TGFileBrowser::TGFileBrowser(TBrowser* b, const char *name, UInt_t w, UInt_t h) : | |
61 | TGMainFrame(gClient->GetRoot(), w, h), TBrowserImp(b), | |
62 | fNewBrowser(0) | |
63 | { | |
64 | CreateBrowser(name); | |
65 | Resize(w, h); | |
66 | if (fBrowser) Show(); | |
67 | } | |
68 | ||
69 | //______________________________________________________________________________ | |
70 | TGFileBrowser::TGFileBrowser(TBrowser* b, const char *name, Int_t x, Int_t y, | |
71 | UInt_t w, UInt_t h) : | |
72 | TGMainFrame(gClient->GetRoot(), w, h), TBrowserImp(b), | |
73 | fNewBrowser(0) | |
74 | { | |
75 | CreateBrowser(name); | |
76 | MoveResize(x, y, w, h); | |
77 | SetWMPosition(x, y); | |
78 | if (fBrowser) Show(); | |
79 | } | |
80 | ||
81 | //______________________________________________________________________________ | |
82 | void TGFileBrowser::CreateBrowser(const char *name) | |
83 | { | |
84 | fCachedPic = 0; | |
85 | SetCleanup(kDeepCleanup); | |
86 | ||
87 | /* | |
88 | fNewBrowser = 0; | |
89 | if (p && p != gClient->GetDefaultRoot()) | |
90 | fNewBrowser = (TGNewBrowser *)p->GetMainFrame(); | |
91 | if (fNewBrowser) | |
92 | fNewBrowser->SetBrowserFrame(this); | |
93 | */ | |
94 | fTopFrame = new TGHorizontalFrame(this, 100, 30); | |
95 | fDrawOption = new TGComboBox(fTopFrame, ""); | |
96 | TGTextEntry *dropt_entry = fDrawOption->GetTextEntry(); | |
97 | dropt_entry->SetToolTipText("Object Draw Option", 300); | |
98 | fDrawOption->Resize(80, 20); | |
99 | TGListBox *lb = fDrawOption->GetListBox(); | |
100 | lb->Resize(lb->GetWidth(), 120); | |
101 | Int_t dropt = 1; | |
102 | fDrawOption->AddEntry("", dropt++); | |
103 | fDrawOption->AddEntry(" alp", dropt++); | |
104 | fDrawOption->AddEntry(" box", dropt++); | |
105 | fDrawOption->AddEntry(" colz", dropt++); | |
106 | fDrawOption->AddEntry(" lego", dropt++); | |
107 | fDrawOption->AddEntry(" lego1", dropt++); | |
108 | fDrawOption->AddEntry(" lego2", dropt++); | |
109 | fDrawOption->AddEntry(" same", dropt++); | |
110 | fDrawOption->AddEntry(" surf", dropt++); | |
111 | fDrawOption->AddEntry(" surf1", dropt++); | |
112 | fDrawOption->AddEntry(" surf2", dropt++); | |
113 | fDrawOption->AddEntry(" surf3", dropt++); | |
114 | fDrawOption->AddEntry(" surf4", dropt++); | |
115 | fDrawOption->AddEntry(" surf5", dropt++); | |
116 | fDrawOption->AddEntry(" text", dropt++); | |
117 | fTopFrame->AddFrame(fDrawOption, new TGLayoutHints(kLHintsCenterY | | |
118 | kLHintsRight, 2, 2, 2, 2)); | |
119 | fTopFrame->AddFrame(new TGLabel(fTopFrame, "Draw Option: "), | |
120 | new TGLayoutHints(kLHintsCenterY | kLHintsRight, | |
121 | 2, 2, 2, 2)); | |
122 | AddFrame(fTopFrame, new TGLayoutHints(kLHintsLeft | kLHintsTop | | |
123 | kLHintsExpandX, 2, 2, 2, 2)); | |
124 | fCanvas = new TGCanvas(this, 100, 100); | |
125 | fListTree = new TGListTree(fCanvas, kHorizontalFrame); | |
126 | AddFrame(fCanvas, new TGLayoutHints(kLHintsLeft | kLHintsTop | | |
127 | kLHintsExpandX | kLHintsExpandY)); | |
128 | fListTree->Connect("DoubleClicked(TGListTreeItem *, Int_t)", | |
129 | "TGFileBrowser", this, "DoubleClicked(TGListTreeItem *, Int_t)"); | |
130 | fListTree->Connect("Clicked(TGListTreeItem *, Int_t, Int_t, Int_t)", | |
131 | "TGFileBrowser", this, "Clicked(TGListTreeItem *, Int_t, Int_t, Int_t)"); | |
132 | ||
133 | fRootIcon = gClient->GetPicture("rootdb_t.xpm"); | |
134 | fFileIcon = gClient->GetPicture("doc_t.xpm"); | |
135 | ||
136 | fBotFrame = new TGHorizontalFrame(this, 100, 30); | |
137 | fBotFrame->AddFrame(new TGLabel(fBotFrame, "Filter: "), | |
138 | new TGLayoutHints(kLHintsCenterY | kLHintsLeft, | |
139 | 2, 2, 2, 2)); | |
140 | fFileType = new TGComboBox(fBotFrame, " All Files (*.*)"); | |
141 | Int_t ftype = 1; | |
142 | fFileType->AddEntry(" All Files (*.*)", ftype++); | |
143 | fFileType->AddEntry(" C/C++ Files (*.c;*.cxx;*.h;...)", ftype++); | |
144 | fFileType->AddEntry(" ROOT Files (*.root)", ftype++); | |
145 | fFileType->AddEntry(" Text Files (*.txt)", ftype++); | |
146 | fFileType->Resize(200, fFileType->GetTextEntry()->GetDefaultHeight()); | |
147 | fBotFrame->AddFrame(fFileType, new TGLayoutHints(kLHintsLeft | kLHintsTop | | |
148 | kLHintsExpandX, 2, 2, 2, 2)); | |
149 | fFileType->Connect("Selected(Int_t)", "TGFileBrowser", this, "ApplyFilter(Int_t)"); | |
150 | AddFrame(fBotFrame, new TGLayoutHints(kLHintsLeft | kLHintsTop | | |
151 | kLHintsExpandX, 2, 2, 2, 2)); | |
152 | ||
153 | fContextMenu = new TContextMenu("FileBrowserContextMenu") ; | |
154 | fFilter = 0; | |
155 | fGroupSize = 1000; | |
156 | fListLevel = 0; | |
157 | fCurrentDir = 0; | |
158 | fRootDir = 0; | |
159 | TString gv = gEnv->GetValue("Browser.GroupView", "10000"); | |
160 | Int_t igv = atoi(gv.Data()); | |
161 | if (igv > 10) | |
162 | fGroupSize = igv; | |
163 | ||
164 | if (gEnv->GetValue("Browser.ShowHidden", 0)) | |
165 | fShowHidden = kTRUE; | |
166 | else | |
167 | fShowHidden = kFALSE; | |
168 | ||
169 | MapSubwindows(); | |
170 | Resize(GetDefaultSize()); | |
171 | SetWindowName(name); | |
172 | SetIconName(name); | |
173 | MapWindow(); | |
174 | } | |
175 | ||
176 | //______________________________________________________________________________ | |
177 | void TGFileBrowser::ReallyDelete() | |
178 | { | |
179 | // Really delete the browser and the this GUI. | |
180 | ||
181 | gInterpreter->DeleteGlobal(fBrowser); | |
182 | delete fBrowser; // will in turn delete this object | |
183 | } | |
184 | ||
185 | //______________________________________________________________________________ | |
186 | TGFileBrowser::~TGFileBrowser() | |
187 | { | |
188 | // Destructor. | |
189 | ||
190 | delete fContextMenu; | |
191 | delete fListTree; | |
192 | Cleanup(); | |
193 | } | |
194 | ||
195 | ||
196 | /**************************************************************************/ | |
197 | // TBrowserImp virtuals | |
198 | /**************************************************************************/ | |
199 | ||
200 | //______________________________________________________________________________ | |
201 | void TGFileBrowser::Add(TObject *obj, const char *name, Int_t check) | |
202 | { | |
203 | // Add items to the browser. This function has to be called | |
204 | // by the Browse() member function of objects when they are | |
205 | // called by a browser. If check < 0 (default) no check box is drawn, | |
206 | // if 0 then unchecked checkbox is added, if 1 checked checkbox is added. | |
207 | ||
208 | if (obj && obj->InheritsFrom("TSystemDirectory")) | |
209 | return; | |
210 | const TGPicture *pic=0; | |
211 | if (obj && obj->InheritsFrom("TKey")) | |
212 | AddKey(fListLevel, obj, name); | |
213 | else if (obj) { | |
214 | GetObjPicture(&pic, obj); | |
215 | if (!name) name = obj->GetName(); | |
216 | if(check > -1) { | |
217 | if (!fListTree->FindChildByName(fListLevel, name)) { | |
218 | TGListTreeItem *item = fListTree->AddItem(fListLevel, name, obj, pic, pic, kTRUE); | |
219 | fListTree->CheckItem(item, (Bool_t)check); | |
220 | TString tip(obj->ClassName()); | |
221 | if (obj->GetTitle()) { | |
222 | tip += " "; | |
223 | tip += obj->GetTitle(); | |
224 | } | |
225 | fListTree->SetToolTipItem(item, tip.Data()); | |
226 | } | |
227 | } | |
228 | else { | |
229 | if (!fListTree->FindChildByName(fListLevel, name)) | |
230 | fListTree->AddItem(fListLevel, name, obj, pic, pic); | |
231 | } | |
232 | } | |
233 | //fListTree->ClearViewPort(); | |
234 | } | |
235 | ||
236 | //______________________________________________________________________________ | |
237 | void TGFileBrowser::BrowseObj(TObject *obj) | |
238 | { | |
239 | // Browse object. This, in turn, will trigger the calling of | |
240 | // TRootBrowser::Add() which will fill the IconBox and the tree. | |
241 | // Emits signal "BrowseObj(TObject*)". | |
242 | ||
243 | obj->Browse(fBrowser); | |
244 | } | |
245 | ||
246 | //______________________________________________________________________________ | |
247 | Option_t *TGFileBrowser::GetDrawOption() const | |
248 | { | |
249 | // returns drawing option | |
250 | ||
251 | return fDrawOption->GetTextEntry()->GetText(); | |
252 | } | |
253 | ||
254 | //______________________________________________________________________________ | |
255 | void TGFileBrowser::RecursiveRemove(TObject *obj) | |
256 | { | |
257 | ||
258 | TGListTreeItem *itm = 0, *item = 0; | |
259 | if (obj->InheritsFrom("TFile")) { | |
260 | itm = fListTree->FindChildByData(0, gROOT->GetListOfFiles()); | |
261 | if (itm) | |
262 | item = fListTree->FindChildByData(itm, obj); | |
263 | if (item) | |
264 | fListTree->DeleteItem(item); | |
265 | itm = fRootDir ? fRootDir->GetFirstChild() : 0; | |
266 | while (itm) { | |
267 | item = fListTree->FindItemByObj(itm, obj); | |
268 | if (item) { | |
269 | fListTree->DeleteChildren(item); | |
270 | item->SetUserData(0); | |
271 | } | |
272 | itm = itm->GetNextSibling(); | |
273 | } | |
274 | } | |
275 | if (!obj->InheritsFrom("TFile") && fRootDir) | |
276 | fListTree->RecursiveDeleteItem(fRootDir, obj); | |
277 | fListTree->ClearViewPort(); | |
278 | } | |
279 | ||
280 | //______________________________________________________________________________ | |
281 | void TGFileBrowser::Refresh(Bool_t /*force*/) | |
282 | { | |
283 | ||
284 | TCursorSwitcher cursorSwitcher(this, fListTree); | |
285 | static UInt_t prev = 0; | |
286 | UInt_t curr = gROOT->GetListOfBrowsables()->GetSize(); | |
287 | if (!prev) prev = curr; | |
288 | ||
289 | if (prev != curr) { // refresh gROOT | |
290 | TGListTreeItem *sav = fListLevel; | |
291 | fListLevel = 0; | |
292 | BrowseObj(gROOT); | |
293 | fListLevel = sav; | |
294 | prev = curr; | |
295 | } | |
296 | } | |
297 | ||
298 | ||
299 | /**************************************************************************/ | |
300 | // Other | |
301 | /**************************************************************************/ | |
302 | ||
303 | //______________________________________________________________________________ | |
304 | void TGFileBrowser::AddFSDirectory(const char* /*entry*/, const char* path) | |
305 | { | |
306 | if (path == 0 && fRootDir == 0) { | |
307 | fRootDir = fListTree->AddItem(0, rootdir); | |
308 | } else { | |
309 | // MT: i give up! wanted to place entries for selected | |
310 | // directories like home, pwd, alice-macros. | |
311 | // TGListTreeItem *lti = fListTree->AddItem(0, entry); | |
312 | // | |
313 | } | |
314 | } | |
315 | ||
316 | //______________________________________________________________________________ | |
317 | void TGFileBrowser::AddKey(TGListTreeItem *itm, TObject *obj, const char *name) | |
318 | { | |
319 | // display content of ROOT file | |
320 | ||
321 | // Int_t from, to; | |
322 | TGListTreeItem *where; | |
323 | static TGListTreeItem *olditem = itm; | |
324 | static TGListTreeItem *item = itm; | |
325 | static const TGPicture *pic = 0; | |
326 | static const TGPicture *pic2 = gClient->GetPicture("leaf_t.xpm"); | |
327 | ||
328 | if ((fCnt == 0) || (olditem != itm)) { | |
329 | olditem = item = itm; | |
330 | } | |
331 | if (!name) name = obj->GetName(); | |
332 | if (fNKeys > fGroupSize) { | |
333 | where = itm->GetFirstChild(); | |
334 | while (where) { | |
335 | if (fListTree->FindItemByObj(where, obj)) | |
336 | return; | |
337 | where = where->GetNextSibling(); | |
338 | } | |
339 | } | |
340 | if ((fNKeys > fGroupSize) && (fCnt % fGroupSize == 0)) { | |
341 | if (item != itm) { | |
342 | TString newname = Form("%s-%s", item->GetText(), name); | |
343 | item->Rename(newname.Data()); | |
344 | } | |
345 | item = fListTree->AddItem(itm, name); | |
346 | } | |
347 | if ((fCnt > fGroupSize) && (fCnt >= fNKeys-1)) { | |
348 | TString newname = Form("%s-%s", item->GetText(), name); | |
349 | item->Rename(newname.Data()); | |
350 | } | |
351 | GetObjPicture(&pic, obj); | |
352 | if (!pic) pic = pic2; | |
353 | if (!fListTree->FindChildByName(item, name)) { | |
354 | fListTree->AddItem(item, name, obj, pic, pic); | |
355 | } | |
356 | fCnt++; | |
357 | } | |
358 | ||
359 | //______________________________________________________________________________ | |
360 | void TGFileBrowser::ApplyFilter(Int_t id) | |
361 | { | |
362 | // Apply filter selected in combo box to the file tree view. | |
363 | ||
364 | // Long64_t size; | |
365 | // Long_t fid, flags, modtime; | |
366 | ||
367 | if (fFilter) delete fFilter; | |
368 | fFilter = 0; | |
369 | if (id > 1) | |
370 | fFilter = new TRegexp(filters[id], kTRUE); | |
371 | TGListTreeItem *item = fCurrentDir; | |
372 | if (!item) | |
373 | item = fRootDir; | |
374 | fListTree->DeleteChildren(item); | |
375 | DoubleClicked(item, 1); | |
376 | //fListTree->AdjustPosition(item); | |
377 | fListTree->ClearViewPort(); | |
378 | } | |
379 | ||
380 | //______________________________________________________________________________ | |
381 | void TGFileBrowser::Chdir(TGListTreeItem *item) | |
382 | { | |
383 | // Make object associated with item the current directory. | |
384 | ||
385 | if (item) { | |
386 | TGListTreeItem *i = item; | |
387 | while (i) { | |
388 | TObject *obj = (TObject*) i->GetUserData(); | |
389 | if ((obj) && obj->InheritsFrom("TFile")) { | |
390 | gROOT->ProcessLine(Form("((TFile *)0x%lx)->cd()", obj)); | |
391 | break; | |
392 | } | |
393 | i = i->GetParent(); | |
394 | } | |
395 | } | |
396 | } | |
397 | ||
398 | //______________________________________________________________________________ | |
399 | void TGFileBrowser::Clicked(TGListTreeItem *item, Int_t btn, Int_t x, Int_t y) | |
400 | { | |
401 | ||
402 | char path[1024]; | |
403 | Long64_t size = 0; | |
404 | Long_t id = 0, flags = 0, modtime = 0; | |
405 | fListLevel = item; | |
406 | if (item && btn == kButton3) { | |
407 | TObject *obj = (TObject *) item->GetUserData(); | |
408 | if (obj) { | |
409 | if (obj->InheritsFrom("TKey")) { | |
410 | Chdir(item); | |
411 | const char *clname = (const char *)gROOT->ProcessLine(Form("((TKey *)0x%lx)->GetClassName();", obj)); | |
412 | if (clname) { | |
413 | TClass *cl = TClass::GetClass(clname); | |
414 | void *add = gROOT->FindObject((char *) obj->GetName()); | |
415 | if (add && cl->IsTObject()) { | |
416 | obj = (TObject*)add; | |
417 | item->SetUserData(obj); | |
418 | } | |
419 | } | |
420 | } | |
421 | fContextMenu->Popup(x, y, obj); | |
422 | } | |
423 | else { | |
424 | fListTree->GetPathnameFromItem(item, path); | |
425 | if (strlen(path) > 3) { | |
426 | TString dirname = DirName(item); | |
427 | gSystem->GetPathInfo(dirname.Data(), &id, &size, &flags, &modtime); | |
428 | if (flags & 2) { | |
429 | fCurrentDir = item; | |
430 | TSystemDirectory d(item->GetText(), dirname.Data()); | |
431 | fContextMenu->Popup(x, y, &d); | |
432 | } | |
433 | else { | |
434 | fCurrentDir = item->GetParent(); | |
435 | TSystemFile f(item->GetText(), dirname.Data()); | |
436 | fContextMenu->Popup(x, y, &f); | |
437 | } | |
438 | } | |
439 | } | |
440 | fListTree->ClearViewPort(); | |
441 | } | |
442 | else { | |
443 | if (!item->GetUserData()) { | |
444 | fListTree->GetPathnameFromItem(item, path); | |
445 | if (strlen(path) > 1) { | |
446 | TString dirname = DirName(item); | |
447 | gSystem->GetPathInfo(dirname.Data(), &id, &size, &flags, &modtime); | |
448 | if (flags & 2) | |
449 | fCurrentDir = item; | |
450 | else | |
451 | fCurrentDir = item->GetParent(); | |
452 | } | |
453 | } | |
454 | } | |
455 | } | |
456 | ||
457 | //______________________________________________________________________________ | |
458 | TString TGFileBrowser::DirName(TGListTreeItem* item) | |
459 | { | |
460 | // returns an absolute path | |
461 | ||
462 | TGListTreeItem* parent; | |
463 | TString dirname = item->GetText(); | |
464 | ||
465 | while ((parent=item->GetParent())) { | |
466 | dirname = gSystem->ConcatFileName(parent->GetText(),dirname); | |
467 | item = parent; | |
468 | } | |
469 | ||
470 | return dirname; | |
471 | } | |
472 | ||
473 | //______________________________________________________________________________ | |
474 | static Bool_t IsTextFile(const char *candidate) | |
475 | { | |
476 | // Returns true if given a text file | |
477 | // Uses the specification given on p86 of the Camel book | |
478 | // - Text files have no NULLs in the first block | |
479 | // - and less than 30% of characters with high bit set | |
480 | ||
481 | Int_t i; | |
482 | Int_t nchars; | |
483 | Int_t weirdcount = 0; | |
484 | char buffer[512]; | |
485 | FILE *infile; | |
486 | FileStat_t buf; | |
487 | ||
488 | gSystem->GetPathInfo(candidate, buf); | |
489 | if (!(buf.fMode & kS_IFREG)) | |
490 | return kFALSE; | |
491 | ||
492 | infile = fopen(candidate, "r"); | |
493 | if (infile) { | |
494 | // Read a block | |
495 | nchars = fread(buffer, 1, 512, infile); | |
496 | fclose (infile); | |
497 | // Examine the block | |
498 | for (i = 0; i < nchars; i++) { | |
499 | if (buffer[i] & 128) | |
500 | weirdcount++; | |
501 | if (buffer[i] == '\0') | |
502 | // No NULLs in text files | |
503 | return kFALSE; | |
504 | } | |
505 | if ((nchars > 0) && ((weirdcount * 100 / nchars) > 30)) | |
506 | return kFALSE; | |
507 | } else { | |
508 | // Couldn't open it. Not a text file then | |
509 | return kFALSE; | |
510 | } | |
511 | return kTRUE; | |
512 | } | |
513 | ||
514 | //______________________________________________________________________________ | |
515 | void TGFileBrowser::DoubleClicked(TGListTreeItem *item, Int_t /*btn*/) | |
516 | { | |
517 | // Process double clicks in TGListTree. | |
518 | ||
519 | const TGPicture *pic=0; | |
520 | TString dirname = DirName(item); | |
521 | TGListTreeItem *itm; | |
522 | FileStat_t sbuf; | |
523 | Long64_t size; | |
524 | Long_t id, flags, modtime; | |
525 | ||
526 | TCursorSwitcher switcher(this, fListTree); | |
527 | fListLevel = item; | |
528 | TObject *obj = (TObject *) item->GetUserData(); | |
529 | if (obj && !obj->InheritsFrom("TSystemFile")) { | |
530 | if (obj->InheritsFrom("TFile")) { | |
531 | fNKeys = gROOT->ProcessLine(Form("((TFile *)0x%lx)->GetListOfKeys()->GetEntries();", obj)); | |
532 | } | |
533 | if (obj->InheritsFrom("TKey")) { | |
534 | Chdir(item); | |
535 | const char *clname = (const char *)gROOT->ProcessLine(Form("((TKey *)0x%lx)->GetClassName();", obj)); | |
536 | if (clname) { | |
537 | TClass *cl = TClass::GetClass(clname); | |
538 | void *add = gROOT->FindObject((char *) obj->GetName()); | |
539 | if (add && cl->IsTObject()) { | |
540 | obj = (TObject*)add; | |
541 | item->SetUserData(obj); | |
542 | } | |
543 | } | |
544 | } | |
545 | obj->Browse(fBrowser); | |
546 | fNKeys = 0; | |
547 | fCnt = 0; | |
548 | fListTree->ClearViewPort(); | |
549 | return; | |
550 | } | |
551 | flags = id = size = modtime = 0; | |
552 | gSystem->GetPathInfo(dirname.Data(), &id, &size, &flags, &modtime); | |
553 | Int_t isdir = (Int_t)flags & 2; | |
554 | ||
555 | TString savdir = gSystem->WorkingDirectory(); | |
556 | if (isdir) { | |
557 | fCurrentDir = item; | |
558 | TSystemDirectory dir(item->GetText(),DirName(item)); | |
559 | TList *files = dir.GetListOfFiles(); | |
560 | if (files) { | |
561 | files->Sort(); | |
562 | TIter next(files); | |
563 | TSystemFile *file; | |
564 | TString fname; | |
565 | // directories first | |
566 | while ((file=(TSystemFile*)next())) { | |
567 | fname = file->GetName(); | |
568 | if (file->IsDirectory()) { | |
569 | if (!fShowHidden && fname.BeginsWith(".")) | |
570 | continue; | |
571 | if ((fname!="..") && (fname!=".")) { // skip it | |
572 | if (!fListTree->FindChildByName(item, fname)) { | |
573 | itm = fListTree->AddItem(item, fname); | |
574 | } | |
575 | } | |
576 | } | |
577 | } | |
578 | // then files... | |
579 | TIter nextf(files); | |
580 | while ((file=(TSystemFile*)nextf())) { | |
581 | fname = file->GetName(); | |
582 | if (!file->IsDirectory() && (fFilter == 0 || | |
583 | (fFilter && fname.Index(*fFilter) != kNPOS))) { | |
584 | if (!fShowHidden && fname.BeginsWith(".")) | |
585 | continue; | |
586 | size = modtime = 0; | |
587 | if (gSystem->GetPathInfo(fname, sbuf) == 0) { | |
588 | size = sbuf.fSize; | |
589 | modtime = sbuf.fMtime; | |
590 | } | |
591 | pic = gClient->GetMimeTypeList()->GetIcon(fname, kTRUE); | |
592 | if (!pic) | |
593 | pic = fFileIcon; | |
594 | if (!fListTree->FindChildByName(item, fname)) { | |
595 | itm = fListTree->AddItem(item,fname,pic,pic); | |
596 | if (size && modtime) { | |
597 | char *tiptext = FormatFileInfo(fname.Data(), size, modtime); | |
598 | itm->SetTipText(tiptext); | |
599 | delete [] tiptext; | |
600 | } | |
601 | } | |
602 | } | |
603 | } | |
604 | delete files; | |
605 | } | |
606 | } | |
607 | else { | |
608 | fCurrentDir = item->GetParent(); | |
609 | TSystemFile f(item->GetText(), dirname.Data()); | |
610 | TString fname = f.GetName(); | |
611 | if (fname.EndsWith(".root")) { | |
612 | TObject *rfile = 0; | |
613 | gSystem->ChangeDirectory(gSystem->DirName(dirname.Data())); | |
614 | rfile = gROOT->GetListOfFiles()->FindObject(obj); | |
615 | if (!rfile) { | |
616 | rfile = (TObject *)gROOT->ProcessLine(Form("new TFile(\"%s\")",fname.Data())); | |
617 | item->SetUserData(rfile); | |
618 | } | |
619 | if (rfile) { | |
620 | fNKeys = gROOT->ProcessLine(Form("((TFile *)0x%lx)->GetListOfKeys()->GetEntries();", rfile)); | |
621 | fCnt = 0; | |
622 | gROOT->ProcessLine(Form("((TFile *)0x%lx)->Browse((TBrowser *)0x%lx)", rfile, fBrowser)); | |
623 | fNKeys = 0; | |
624 | fCnt = 0; | |
625 | } | |
626 | } | |
627 | else if (fname.EndsWith(".png")) { | |
628 | gSystem->ChangeDirectory(gSystem->DirName(dirname.Data())); | |
629 | XXExecuteDefaultAction(&f); | |
630 | } | |
631 | else if (IsTextFile(dirname.Data())) { | |
632 | gSystem->ChangeDirectory(gSystem->DirName(dirname.Data())); | |
633 | if (fNewBrowser) { | |
634 | TGTab *tabRight = fNewBrowser->GetTabRight(); | |
635 | TGCompositeFrame *frame = tabRight->GetCurrentContainer(); | |
636 | TGFrameElement *fe = (TGFrameElement *)frame->GetList()->First(); | |
637 | if (fe) { | |
638 | TGCompositeFrame *embed = (TGCompositeFrame *)fe->fFrame; | |
639 | if (embed->InheritsFrom("TGTextEditor")) { | |
640 | gROOT->ProcessLine(Form("((TGTextEditor *)0x%lx)->LoadFile(\"%s\");", | |
641 | embed, f.GetName())); | |
642 | } | |
643 | else if (embed->InheritsFrom("TGTextEdit")) { | |
644 | gROOT->ProcessLine(Form("((TGTextEdit *)0x%lx)->LoadFile(\"%s\");", | |
645 | embed, f.GetName())); | |
646 | } | |
647 | else { | |
648 | XXExecuteDefaultAction(&f); | |
649 | } | |
650 | } | |
651 | } | |
652 | } | |
653 | else { | |
654 | gSystem->ChangeDirectory(gSystem->DirName(dirname.Data())); | |
655 | XXExecuteDefaultAction(&f); | |
656 | } | |
657 | } | |
658 | gSystem->ChangeDirectory(savdir.Data()); | |
659 | fListTree->ClearViewPort(); | |
660 | } | |
661 | ||
662 | //____________________________________________________________________________ | |
663 | Long_t TGFileBrowser::XXExecuteDefaultAction(TObject *obj) | |
664 | { | |
665 | // Execute default action for selected object (action is specified | |
666 | // in the $HOME/.root.mimes or $ROOTSYS/etc/root.mimes file. | |
667 | ||
668 | char action[512]; | |
669 | TString act; | |
670 | TString ext = obj->GetName(); | |
671 | fBrowser->SetDrawOption(GetDrawOption()); | |
672 | ||
673 | if (gClient->GetMimeTypeList()->GetAction(obj->GetName(), action)) { | |
674 | act = action; | |
675 | act.ReplaceAll("%s", obj->GetName()); | |
676 | gInterpreter->SaveGlobalsContext(); | |
677 | ||
678 | if (act[0] == '!') { | |
679 | act.Remove(0, 1); | |
680 | gSystem->Exec(act.Data()); | |
681 | return 0; | |
682 | } else { | |
683 | return gApplication->ProcessLine(act.Data()); | |
684 | } | |
685 | } | |
686 | return 0; | |
687 | } | |
688 | ||
689 | //______________________________________________________________________________ | |
690 | char *TGFileBrowser::FormatFileInfo(const char *fname, Long64_t size, Long_t modtime) | |
691 | { | |
692 | ||
693 | Long64_t fsize, bsize; | |
694 | TString infos = fname; | |
695 | infos += "\n"; | |
696 | ||
697 | fsize = bsize = size; | |
698 | if (fsize > 1024) { | |
699 | fsize /= 1024; | |
700 | if (fsize > 1024) { | |
701 | // 3.7MB is more informative than just 3MB | |
702 | infos += Form("Size: %lld.%lldM", fsize/1024, (fsize%1024)/103); | |
703 | } else { | |
704 | infos += Form("Size: %lld.%lldK", bsize/1024, (bsize%1024)/103); | |
705 | } | |
706 | } else { | |
707 | infos += Form("Size: %lld", bsize); | |
708 | } | |
709 | struct tm *newtime; | |
710 | time_t loctime = (time_t) modtime; | |
711 | newtime = localtime(&loctime); | |
712 | infos += "\n"; | |
713 | infos += Form("%d-%02d-%02d %02d:%02d", newtime->tm_year + 1900, | |
714 | newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, | |
715 | newtime->tm_min); | |
716 | return StrDup(infos.Data()); | |
717 | } | |
718 | ||
719 | //______________________________________________________________________________ | |
720 | void TGFileBrowser::GetObjPicture(const TGPicture **pic, TObject *obj) | |
721 | { | |
722 | // Retrieve icons associated with class "name". Association is made | |
723 | // via the user's ~/.root.mimes file or via $ROOTSYS/etc/root.mimes. | |
724 | ||
725 | TClass *objClass = 0; | |
726 | static TImage *im = 0; | |
727 | if (!im) { | |
728 | im = TImage::Create(); | |
729 | } | |
730 | ||
731 | if (obj->InheritsFrom("TKey")) { | |
732 | const char *clname = (const char *)gROOT->ProcessLine(Form("((TKey *)0x%lx)->GetClassName();", obj)); | |
733 | if (clname) | |
734 | objClass = TClass::GetClass(clname); | |
735 | } | |
736 | else if (obj->InheritsFrom("TKeyMapFile")) { | |
737 | const char *title = (const char *)gROOT->ProcessLine(Form("((TKeyMapFile *)0x%lx)->GetTitle();", obj)); | |
738 | if (title) | |
739 | objClass = TClass::GetClass(title); | |
740 | } | |
741 | else | |
742 | objClass = obj->IsA(); | |
743 | const char *name = obj->GetIconName() ? obj->GetIconName() : objClass->GetName(); | |
744 | TString xpm_magic(name, 3); | |
745 | Bool_t xpm = xpm_magic == "/* "; | |
746 | const char *iconname = xpm ? obj->GetName() : name; | |
747 | ||
748 | if (obj->IsA()->InheritsFrom("TGeoVolume")) { | |
749 | iconname = obj->GetIconName() ? obj->GetIconName() : obj->IsA()->GetName(); | |
750 | } | |
751 | ||
752 | if (fCachedPicName == iconname) { | |
753 | *pic = fCachedPic; | |
754 | return; | |
755 | } | |
756 | *pic = gClient->GetMimeTypeList()->GetIcon(iconname, kTRUE); | |
757 | if (!(*pic) && xpm) { | |
758 | if (im && im->SetImageBuffer((char**)&name, TImage::kXpm)) { | |
759 | im->Scale(im->GetWidth()/4, im->GetHeight()/4); | |
760 | *pic = gClient->GetPicturePool()->GetPicture(iconname, im->GetPixmap(), | |
761 | im->GetMask()); | |
762 | } | |
763 | gClient->GetMimeTypeList()->AddType("[thumbnail]", iconname, iconname, iconname, "->Browse()"); | |
764 | return; | |
765 | } | |
766 | if (*pic == 0) { | |
767 | if (!obj->IsFolder()) | |
768 | *pic = fFileIcon; | |
769 | } | |
770 | fCachedPic = *pic; | |
771 | fCachedPicName = iconname; | |
772 | } | |
773 | ||
774 | //______________________________________________________________________________ | |
775 | void TGFileBrowser::GotoDir(const char *path) | |
776 | { | |
777 | ||
778 | TGListTreeItem *item, *itm; | |
779 | char *token; | |
780 | static const char seps[] = "/\\"; | |
781 | // Establish string and get the first token: | |
782 | token = strtok(strdup(path), seps); | |
783 | // Note: strtok is deprecated; consider using strtok_s instead | |
784 | item = fRootDir; | |
785 | if (item == 0) return; | |
786 | fListTree->HighlightItem(item); | |
787 | fListTree->OpenItem(item); | |
788 | DoubleClicked(item, 1); | |
789 | while (token) { | |
790 | // while there are tokens in path | |
791 | itm = fListTree->FindChildByName(item, token); | |
792 | if (itm) { | |
793 | item = itm; | |
794 | fListTree->HighlightItem(item); | |
795 | fListTree->OpenItem(item); | |
796 | DoubleClicked(item, 1); | |
797 | } | |
798 | // get next token: | |
799 | token = strtok( NULL, seps ); | |
800 | } | |
801 | fListTree->ClearViewPort(); | |
802 | fListTree->AdjustPosition(item); | |
803 | } | |
804 | ||
805 |