4 #include "TApplication.h"
6 #include "TGListTree.h"
8 #include "TGComboBox.h"
9 #include "TContextMenu.h"
10 #include "TGTextEntry.h"
13 #include "TSystemDirectory.h"
14 #include "TGMimeTypes.h"
16 #include "TInterpreter.h"
24 #include "TGFileBrowser.h"
25 #include "TGNewBrowser.h"
28 const char rootdir[] = "\\";
30 const char rootdir[] = "/";
33 const char *filters[] = {
41 ////////////////////////////////////////////////////////////////////////////////////
42 class TCursorSwitcher {
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));
52 if (fW1) gVirtualX->SetCursor(fW1->GetId(), gVirtualX->CreateCursor(kPointer));
53 if (fW2) gVirtualX->SetCursor(fW2->GetId(), gVirtualX->CreateCursor(kPointer));
57 ClassImp(TGFileBrowser)
59 //______________________________________________________________________________
60 TGFileBrowser::TGFileBrowser(TBrowser* b, const char *name, UInt_t w, UInt_t h) :
61 TGMainFrame(gClient->GetRoot(), w, h), TBrowserImp(b),
69 //______________________________________________________________________________
70 TGFileBrowser::TGFileBrowser(TBrowser* b, const char *name, Int_t x, Int_t y,
72 TGMainFrame(gClient->GetRoot(), w, h), TBrowserImp(b),
76 MoveResize(x, y, w, h);
81 //______________________________________________________________________________
82 void TGFileBrowser::CreateBrowser(const char *name)
85 SetCleanup(kDeepCleanup);
89 if (p && p != gClient->GetDefaultRoot())
90 fNewBrowser = (TGNewBrowser *)p->GetMainFrame();
92 fNewBrowser->SetBrowserFrame(this);
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);
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,
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)");
133 fRootIcon = gClient->GetPicture("rootdb_t.xpm");
134 fFileIcon = gClient->GetPicture("doc_t.xpm");
136 fBotFrame = new TGHorizontalFrame(this, 100, 30);
137 fBotFrame->AddFrame(new TGLabel(fBotFrame, "Filter: "),
138 new TGLayoutHints(kLHintsCenterY | kLHintsLeft,
140 fFileType = new TGComboBox(fBotFrame, " All Files (*.*)");
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));
153 fContextMenu = new TContextMenu("FileBrowserContextMenu") ;
159 TString gv = gEnv->GetValue("Browser.GroupView", "10000");
160 Int_t igv = atoi(gv.Data());
164 if (gEnv->GetValue("Browser.ShowHidden", 0))
167 fShowHidden = kFALSE;
170 Resize(GetDefaultSize());
176 //______________________________________________________________________________
177 void TGFileBrowser::ReallyDelete()
179 // Really delete the browser and the this GUI.
181 gInterpreter->DeleteGlobal(fBrowser);
182 delete fBrowser; // will in turn delete this object
185 //______________________________________________________________________________
186 TGFileBrowser::~TGFileBrowser()
196 /**************************************************************************/
197 // TBrowserImp virtuals
198 /**************************************************************************/
200 //______________________________________________________________________________
201 void TGFileBrowser::Add(TObject *obj, const char *name, Int_t check)
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.
208 if (obj && obj->InheritsFrom("TSystemDirectory"))
210 const TGPicture *pic=0;
211 if (obj && obj->InheritsFrom("TKey"))
212 AddKey(fListLevel, obj, name);
214 GetObjPicture(&pic, obj);
215 if (!name) name = obj->GetName();
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()) {
223 tip += obj->GetTitle();
225 fListTree->SetToolTipItem(item, tip.Data());
229 if (!fListTree->FindChildByName(fListLevel, name))
230 fListTree->AddItem(fListLevel, name, obj, pic, pic);
233 //fListTree->ClearViewPort();
236 //______________________________________________________________________________
237 void TGFileBrowser::BrowseObj(TObject *obj)
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*)".
243 obj->Browse(fBrowser);
246 //______________________________________________________________________________
247 Option_t *TGFileBrowser::GetDrawOption() const
249 // returns drawing option
251 return fDrawOption->GetTextEntry()->GetText();
254 //______________________________________________________________________________
255 void TGFileBrowser::RecursiveRemove(TObject *obj)
258 TGListTreeItem *itm = 0, *item = 0;
259 if (obj->InheritsFrom("TFile")) {
260 itm = fListTree->FindChildByData(0, gROOT->GetListOfFiles());
262 item = fListTree->FindChildByData(itm, obj);
264 fListTree->DeleteItem(item);
265 itm = fRootDir ? fRootDir->GetFirstChild() : 0;
267 item = fListTree->FindItemByObj(itm, obj);
269 fListTree->DeleteChildren(item);
270 item->SetUserData(0);
272 itm = itm->GetNextSibling();
275 if (!obj->InheritsFrom("TFile") && fRootDir)
276 fListTree->RecursiveDeleteItem(fRootDir, obj);
277 fListTree->ClearViewPort();
280 //______________________________________________________________________________
281 void TGFileBrowser::Refresh(Bool_t /*force*/)
284 TCursorSwitcher cursorSwitcher(this, fListTree);
285 static UInt_t prev = 0;
286 UInt_t curr = gROOT->GetListOfBrowsables()->GetSize();
287 if (!prev) prev = curr;
289 if (prev != curr) { // refresh gROOT
290 TGListTreeItem *sav = fListLevel;
299 /**************************************************************************/
301 /**************************************************************************/
303 //______________________________________________________________________________
304 void TGFileBrowser::AddFSDirectory(const char* /*entry*/, const char* path)
306 if (path == 0 && fRootDir == 0) {
307 fRootDir = fListTree->AddItem(0, rootdir);
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);
316 //______________________________________________________________________________
317 void TGFileBrowser::AddKey(TGListTreeItem *itm, TObject *obj, const char *name)
319 // display content of ROOT file
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");
328 if ((fCnt == 0) || (olditem != itm)) {
329 olditem = item = itm;
331 if (!name) name = obj->GetName();
332 if (fNKeys > fGroupSize) {
333 where = itm->GetFirstChild();
335 if (fListTree->FindItemByObj(where, obj))
337 where = where->GetNextSibling();
340 if ((fNKeys > fGroupSize) && (fCnt % fGroupSize == 0)) {
342 TString newname = Form("%s-%s", item->GetText(), name);
343 item->Rename(newname.Data());
345 item = fListTree->AddItem(itm, name);
347 if ((fCnt > fGroupSize) && (fCnt >= fNKeys-1)) {
348 TString newname = Form("%s-%s", item->GetText(), name);
349 item->Rename(newname.Data());
351 GetObjPicture(&pic, obj);
352 if (!pic) pic = pic2;
353 if (!fListTree->FindChildByName(item, name)) {
354 fListTree->AddItem(item, name, obj, pic, pic);
359 //______________________________________________________________________________
360 void TGFileBrowser::ApplyFilter(Int_t id)
362 // Apply filter selected in combo box to the file tree view.
365 // Long_t fid, flags, modtime;
367 if (fFilter) delete fFilter;
370 fFilter = new TRegexp(filters[id], kTRUE);
371 TGListTreeItem *item = fCurrentDir;
374 fListTree->DeleteChildren(item);
375 DoubleClicked(item, 1);
376 //fListTree->AdjustPosition(item);
377 fListTree->ClearViewPort();
380 //______________________________________________________________________________
381 void TGFileBrowser::Chdir(TGListTreeItem *item)
383 // Make object associated with item the current directory.
386 TGListTreeItem *i = item;
388 TObject *obj = (TObject*) i->GetUserData();
389 if ((obj) && obj->InheritsFrom("TFile")) {
390 gROOT->ProcessLine(Form("((TFile *)0x%lx)->cd()", obj));
398 //______________________________________________________________________________
399 void TGFileBrowser::Clicked(TGListTreeItem *item, Int_t btn, Int_t x, Int_t y)
404 Long_t id = 0, flags = 0, modtime = 0;
406 if (item && btn == kButton3) {
407 TObject *obj = (TObject *) item->GetUserData();
409 if (obj->InheritsFrom("TKey")) {
411 const char *clname = (const char *)gROOT->ProcessLine(Form("((TKey *)0x%lx)->GetClassName();", obj));
413 TClass *cl = TClass::GetClass(clname);
414 void *add = gROOT->FindObject((char *) obj->GetName());
415 if (add && cl->IsTObject()) {
417 item->SetUserData(obj);
421 fContextMenu->Popup(x, y, obj);
424 fListTree->GetPathnameFromItem(item, path);
425 if (strlen(path) > 3) {
426 TString dirname = DirName(item);
427 gSystem->GetPathInfo(dirname.Data(), &id, &size, &flags, &modtime);
430 TSystemDirectory d(item->GetText(), dirname.Data());
431 fContextMenu->Popup(x, y, &d);
434 fCurrentDir = item->GetParent();
435 TSystemFile f(item->GetText(), dirname.Data());
436 fContextMenu->Popup(x, y, &f);
440 fListTree->ClearViewPort();
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);
451 fCurrentDir = item->GetParent();
457 //______________________________________________________________________________
458 TString TGFileBrowser::DirName(TGListTreeItem* item)
460 // returns an absolute path
462 TGListTreeItem* parent;
463 TString dirname = item->GetText();
465 while ((parent=item->GetParent())) {
466 dirname = gSystem->ConcatFileName(parent->GetText(),dirname);
473 //______________________________________________________________________________
474 static Bool_t IsTextFile(const char *candidate)
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
483 Int_t weirdcount = 0;
488 gSystem->GetPathInfo(candidate, buf);
489 if (!(buf.fMode & kS_IFREG))
492 infile = fopen(candidate, "r");
495 nchars = fread(buffer, 1, 512, infile);
498 for (i = 0; i < nchars; i++) {
501 if (buffer[i] == '\0')
502 // No NULLs in text files
505 if ((nchars > 0) && ((weirdcount * 100 / nchars) > 30))
508 // Couldn't open it. Not a text file then
514 //______________________________________________________________________________
515 void TGFileBrowser::DoubleClicked(TGListTreeItem *item, Int_t /*btn*/)
517 // Process double clicks in TGListTree.
519 const TGPicture *pic=0;
520 TString dirname = DirName(item);
524 Long_t id, flags, modtime;
526 TCursorSwitcher switcher(this, fListTree);
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));
533 if (obj->InheritsFrom("TKey")) {
535 const char *clname = (const char *)gROOT->ProcessLine(Form("((TKey *)0x%lx)->GetClassName();", obj));
537 TClass *cl = TClass::GetClass(clname);
538 void *add = gROOT->FindObject((char *) obj->GetName());
539 if (add && cl->IsTObject()) {
541 item->SetUserData(obj);
545 obj->Browse(fBrowser);
548 fListTree->ClearViewPort();
551 flags = id = size = modtime = 0;
552 gSystem->GetPathInfo(dirname.Data(), &id, &size, &flags, &modtime);
553 Int_t isdir = (Int_t)flags & 2;
555 TString savdir = gSystem->WorkingDirectory();
558 TSystemDirectory dir(item->GetText(),DirName(item));
559 TList *files = dir.GetListOfFiles();
566 while ((file=(TSystemFile*)next())) {
567 fname = file->GetName();
568 if (file->IsDirectory()) {
569 if (!fShowHidden && fname.BeginsWith("."))
571 if ((fname!="..") && (fname!=".")) { // skip it
572 if (!fListTree->FindChildByName(item, fname)) {
573 itm = fListTree->AddItem(item, fname);
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("."))
587 if (gSystem->GetPathInfo(fname, sbuf) == 0) {
589 modtime = sbuf.fMtime;
591 pic = gClient->GetMimeTypeList()->GetIcon(fname, kTRUE);
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);
608 fCurrentDir = item->GetParent();
609 TSystemFile f(item->GetText(), dirname.Data());
610 TString fname = f.GetName();
611 if (fname.EndsWith(".root")) {
613 gSystem->ChangeDirectory(gSystem->DirName(dirname.Data()));
614 rfile = gROOT->GetListOfFiles()->FindObject(obj);
616 rfile = (TObject *)gROOT->ProcessLine(Form("new TFile(\"%s\")",fname.Data()));
617 item->SetUserData(rfile);
620 fNKeys = gROOT->ProcessLine(Form("((TFile *)0x%lx)->GetListOfKeys()->GetEntries();", rfile));
622 gROOT->ProcessLine(Form("((TFile *)0x%lx)->Browse((TBrowser *)0x%lx)", rfile, fBrowser));
627 else if (fname.EndsWith(".png")) {
628 gSystem->ChangeDirectory(gSystem->DirName(dirname.Data()));
629 XXExecuteDefaultAction(&f);
631 else if (IsTextFile(dirname.Data())) {
632 gSystem->ChangeDirectory(gSystem->DirName(dirname.Data()));
634 TGTab *tabRight = fNewBrowser->GetTabRight();
635 TGCompositeFrame *frame = tabRight->GetCurrentContainer();
636 TGFrameElement *fe = (TGFrameElement *)frame->GetList()->First();
638 TGCompositeFrame *embed = (TGCompositeFrame *)fe->fFrame;
639 if (embed->InheritsFrom("TGTextEditor")) {
640 gROOT->ProcessLine(Form("((TGTextEditor *)0x%lx)->LoadFile(\"%s\");",
641 embed, f.GetName()));
643 else if (embed->InheritsFrom("TGTextEdit")) {
644 gROOT->ProcessLine(Form("((TGTextEdit *)0x%lx)->LoadFile(\"%s\");",
645 embed, f.GetName()));
648 XXExecuteDefaultAction(&f);
654 gSystem->ChangeDirectory(gSystem->DirName(dirname.Data()));
655 XXExecuteDefaultAction(&f);
658 gSystem->ChangeDirectory(savdir.Data());
659 fListTree->ClearViewPort();
662 //____________________________________________________________________________
663 Long_t TGFileBrowser::XXExecuteDefaultAction(TObject *obj)
665 // Execute default action for selected object (action is specified
666 // in the $HOME/.root.mimes or $ROOTSYS/etc/root.mimes file.
670 TString ext = obj->GetName();
671 fBrowser->SetDrawOption(GetDrawOption());
673 if (gClient->GetMimeTypeList()->GetAction(obj->GetName(), action)) {
675 act.ReplaceAll("%s", obj->GetName());
676 gInterpreter->SaveGlobalsContext();
680 gSystem->Exec(act.Data());
683 return gApplication->ProcessLine(act.Data());
689 //______________________________________________________________________________
690 char *TGFileBrowser::FormatFileInfo(const char *fname, Long64_t size, Long_t modtime)
693 Long64_t fsize, bsize;
694 TString infos = fname;
697 fsize = bsize = size;
701 // 3.7MB is more informative than just 3MB
702 infos += Form("Size: %lld.%lldM", fsize/1024, (fsize%1024)/103);
704 infos += Form("Size: %lld.%lldK", bsize/1024, (bsize%1024)/103);
707 infos += Form("Size: %lld", bsize);
710 time_t loctime = (time_t) modtime;
711 newtime = localtime(&loctime);
713 infos += Form("%d-%02d-%02d %02d:%02d", newtime->tm_year + 1900,
714 newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour,
716 return StrDup(infos.Data());
719 //______________________________________________________________________________
720 void TGFileBrowser::GetObjPicture(const TGPicture **pic, TObject *obj)
722 // Retrieve icons associated with class "name". Association is made
723 // via the user's ~/.root.mimes file or via $ROOTSYS/etc/root.mimes.
725 TClass *objClass = 0;
726 static TImage *im = 0;
728 im = TImage::Create();
731 if (obj->InheritsFrom("TKey")) {
732 const char *clname = (const char *)gROOT->ProcessLine(Form("((TKey *)0x%lx)->GetClassName();", obj));
734 objClass = TClass::GetClass(clname);
736 else if (obj->InheritsFrom("TKeyMapFile")) {
737 const char *title = (const char *)gROOT->ProcessLine(Form("((TKeyMapFile *)0x%lx)->GetTitle();", obj));
739 objClass = TClass::GetClass(title);
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;
748 if (obj->IsA()->InheritsFrom("TGeoVolume")) {
749 iconname = obj->GetIconName() ? obj->GetIconName() : obj->IsA()->GetName();
752 if (fCachedPicName == iconname) {
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(),
763 gClient->GetMimeTypeList()->AddType("[thumbnail]", iconname, iconname, iconname, "->Browse()");
767 if (!obj->IsFolder())
771 fCachedPicName = iconname;
774 //______________________________________________________________________________
775 void TGFileBrowser::GotoDir(const char *path)
778 TGListTreeItem *item, *itm;
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
785 if (item == 0) return;
786 fListTree->HighlightItem(item);
787 fListTree->OpenItem(item);
788 DoubleClicked(item, 1);
790 // while there are tokens in path
791 itm = fListTree->FindChildByName(item, token);
794 fListTree->HighlightItem(item);
795 fListTree->OpenItem(item);
796 DoubleClicked(item, 1);
799 token = strtok( NULL, seps );
801 fListTree->ClearViewPort();
802 fListTree->AdjustPosition(item);