Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TDirectoryElement.cxx
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. *
3 * All rights reserved. *
4 * *
5 * For the licensing terms see $ROOTSYS/LICENSE. *
6 * For the list of contributors see $ROOTSYS/README/CREDITS. *
7 *************************************************************************/
8
9
17
18#include <ROOT/RLogger.hxx>
19
20#include "TKey.h"
21#include "TDirectory.h"
22#include "TROOT.h"
23#include "TFile.h"
24#include "TClass.h"
25#include "TEnv.h"
26
27#include <cstring>
28#include <string>
29
30using namespace std::string_literals;
31
32using namespace ROOT::Browsable;
33
34
35/** \class TDirectoryLevelIter
36\ingroup rbrowser
37
38Iterator over keys in TDirectory
39*/
40
41
43 TDirectory *fDir{nullptr}; ///<! current directory handle
44 std::unique_ptr<TIterator> fIter; ///<! created iterator
45 bool fKeysIter{true}; ///<! iterating over keys list (default)
46 bool fOnlyLastCycle{false}; ///<! show only last cycle in list of keys
47 TKey *fKey{nullptr}; ///<! currently selected key
48 TObject *fObj{nullptr}; ///<! currently selected object
49 std::string fCurrentName; ///<! current key name
50
52 {
53 if (!fDir) return false;
54 fObj = nullptr;
55 fKey = nullptr;
56 auto lst = fDir->GetListOfKeys();
57 if (lst->GetSize() == 0) {
58 auto olst = fDir->GetList();
59 if (olst->GetSize() > 0) {
60 fKeysIter = false;
61 fIter.reset(olst->MakeIterator());
62 return true;
63 }
64 }
65 fKeysIter = true;
66 fIter.reset(lst->MakeIterator());
67 return true;
68 }
69
71 {
72 fCurrentName.clear();
73 if (!fIter) return false;
74
75 fObj = fIter->Next();
76 if (!fObj) {
77 fIter.reset();
78 if (!fKeysIter || !fDir)
79 return false;
80 fKeysIter = false;
81 fIter.reset(fDir->GetList()->MakeIterator());
82 fObj = fIter->Next();
83 if (!fObj) {
84 fIter.reset();
85 return false;
86 }
87 }
88 if (!fKeysIter) {
89 // exclude object with duplicated name as keys
90 while (fObj) {
91 if (!fDir->GetListOfKeys()->FindObject(fObj->GetName()))
92 break;
93 fObj = fIter->Next();
94 }
95 if (!fObj) {
96 fIter.reset();
97 return false;
98 }
99
100 fCurrentName = fObj->GetName();
101 return true;
102 }
103
104 while(true) {
105
106 fKey = dynamic_cast<TKey *>(fObj);
107
108 if (!fKey) {
109 fIter.reset();
110 return false;
111 }
112
113 if (!fOnlyLastCycle) break;
114
115 TIter iter(fDir->GetListOfKeys());
116 TKey *key = nullptr;
117 bool found_newer = false;
118 while ((key = dynamic_cast<TKey*>(iter())) != nullptr) {
119 if ((key != fKey) && !strcmp(key->GetName(), fKey->GetName()) && (key->GetCycle() > fKey->GetCycle())) {
120 found_newer = true;
121 break;
122 }
123 }
124
125 if (!found_newer) break;
126
127 fObj = fIter->Next();
128 }
129
130 fCurrentName = fKey->GetName();
131 fCurrentName.append(";");
132 fCurrentName.append(std::to_string(fKey->GetCycle()));
133
134 return true;
135 }
136
137public:
138 explicit TDirectoryLevelIter(TDirectory *dir) : fDir(dir)
139 {
140 const char *undef = "<undefined>";
141 const char *value = gEnv->GetValue("WebGui.LastCycle", undef);
142 if (value) {
143 std::string svalue = value;
144 if (svalue != undef) {
145 if (svalue == "yes")
146 fOnlyLastCycle = true;
147 else if (svalue == "no")
148 fOnlyLastCycle = false;
149 else
150 R__LOG_ERROR(ROOT::BrowsableLog()) << "WebGui.LastCycle must be yes or no";
151 }
152 }
153
154 CreateIter();
155 }
156
157 virtual ~TDirectoryLevelIter() = default;
158
159 bool Next() override { return NextDirEntry(); }
160
161 // use default implementation for now
162 // bool Find(const std::string &name) override { return FindDirEntry(name); }
163
164 std::string GetItemName() const override { return fCurrentName; }
165
166 bool CanItemHaveChilds() const override
167 {
168 if (!fKeysIter && fObj)
169 return RProvider::CanHaveChilds(fObj->IsA());
170
171 if (fKeysIter && fKey) {
172 if (RProvider::CanHaveChilds(fKey->GetClassName()))
173 return true;
174 auto cl = TClass::GetClass(fKey->GetClassName(), kFALSE, kTRUE);
175 return RProvider::CanHaveChilds(cl);
176 }
177 return false;
178 }
179
180 /** Create item for the client */
181 std::unique_ptr<RItem> CreateItem() override
182 {
183 if (!fKeysIter && fObj) {
184 std::unique_ptr<RHolder> holder = std::make_unique<TObjectHolder>(fObj, kFALSE);
185
186 auto elem = RProvider::Browse(holder);
187
188 return elem ? elem->CreateItem() : nullptr;
189 }
190
191 auto item = GetDirElement(false)->CreateItem();
192 item->SetName(fCurrentName);
193 return item;
194 }
195
196 std::shared_ptr<RElement> GetDirElement(bool read_dir);
197
198 /** Returns full information for current element */
199 std::shared_ptr<RElement> GetElement() override { return GetDirElement(true); }
200};
201
202// ===============================================================================================================
203
204/** \class TDirectoryElement
205\ingroup rbrowser
206
207Element representing TDirectory
208*/
209
211 std::string fFileName; ///<! file name
212 bool fIsFile{false}; ///<! is TFile instance registered in global list of files
213
214protected:
215
216 const TObject *CheckObject() const override
217 {
218 // during TROOT destructor just forget about file reference
219 if (!gROOT || gROOT->TestBit(TObject::kInvalidObject)) {
220 ForgetObject();
221 return nullptr;
222 }
223
225 return nullptr;
226
227 if (fIsFile) {
228 if (!gROOT->GetListOfFiles()->FindObject(fObj))
229 ForgetObject();
230 } else if (!gROOT->GetListOfFiles()->FindObject(((TDirectory *) fObj)->GetFile()))
231 ForgetObject();
232
233 return fObj;
234 }
235
237 {
238 if (!CheckObject() && fIsFile && fFileName.empty())
239 (const_cast<TDirectoryElement *>(this))->SetObject(TFile::Open(fFileName.c_str()));
240
241 return dynamic_cast<TDirectory *>(fObj);
242 }
243
244 TFile *GetFile() const
245 {
246 if (!fIsFile)
247 return nullptr;
248
249 return dynamic_cast<TFile *>(GetDir());
250 }
251
252
253public:
254
255 TDirectoryElement(const std::string &fname, TDirectory *dir = nullptr, bool isfile = false) : TObjectElement(dir)
256 {
257 fFileName = fname;
258 fIsFile = isfile;
259 if (fIsFile && fObj && !gROOT->GetListOfFiles()->FindObject(fObj)) {
260 fIsFile = false;
261 ForgetObject();
262 }
263 }
264
265 virtual ~TDirectoryElement() = default;
266
267 /** Name of TDirectoryElement */
268 std::string GetName() const override
269 {
270 if (CheckObject())
271 return fObj->GetName();
272
273 if (!fFileName.empty()) {
274 auto pos = fFileName.rfind("/");
275 return ((pos == std::string::npos) || (pos > fFileName.length() - 2)) ? fFileName : fFileName.substr(pos + 1);
276 }
277
278 return ""s;
279 }
280
281 /** Title of TDirectoryElement */
282 std::string GetTitle() const override
283 {
284 if (CheckObject())
285 return fObj->GetTitle();
286
287 return "ROOT file "s + fFileName;
288 }
289
290 bool IsFolder() const override { return true; }
291
292 /** Provide iterator over TDirectory */
293 std::unique_ptr<RLevelIter> GetChildsIter() override
294 {
295 auto dir = GetDir();
296
297 return dir ? std::make_unique<TDirectoryLevelIter>(dir) : nullptr;
298 }
299
300 /** Get default action - browsing for the TFile/TDirectory */
301 EActionKind GetDefaultAction() const override { return kActBrowse; }
302
303 /** Select directory as active */
304 bool cd() override
305 {
306 auto dir = GetDir();
307 if (dir) {
308 dir->cd();
309 return true;
310 }
311 return false;
312 }
313
314 /** Size of TDirectory */
315 Long64_t GetSize() const override
316 {
317 auto f = GetFile();
318 if (f) return f->GetSize();
319 return -1;
320 }
321
322 std::string GetMTime() const override
323 {
324 auto f = GetFile();
325 if (f) return f->GetModificationDate().AsSQLString();
326 return ""s;
327 }
328
329 std::string GetContent(const std::string &kind) override
330 {
331 if (GetContentKind(kind) == kFileName)
332 return fFileName;
333
334 return ""s;
335 }
336
337};
338
339// ===============================================================================================================
340
341
342/** \class TKeyElement
343\ingroup rbrowser
344
345Element representing TKey from TDirectory
346*/
347
352 std::shared_ptr<RElement> fElement; ///<! holder of read object
353
354 std::string GetMTime() const override { return fKeyMTime; }
355
356 Long64_t GetSize() const override { return fKeyObjSize; }
357
358public:
359 TKeyElement(TDirectory *dir, TKey *key) : TDirectoryElement("", dir, false)
360 {
361 fKeyName = key->GetName();
362 fKeyTitle = key->GetTitle();
363 fKeyCycle = key->GetCycle();
364 fKeyClass = key->GetClassName();
365 fKeyMTime = key->GetDatime().AsSQLString();
366 fKeyObjSize = key->GetNbytes();
367 }
368
369 virtual ~TKeyElement() = default;
370
371 /** Name of TKeyElement, includes key cycle */
372 std::string GetName() const override
373 {
374 if (fElement)
375 return fElement->GetName();
376
377 std::string name = fKeyName;
378 name.append(";");
379 name.append(std::to_string(fKeyCycle));
380
381 return name;
382 }
383
384 /** Title of TKeyElement (optional) */
385 std::string GetTitle() const override
386 {
387 if (fElement)
388 return fElement->GetTitle();
389
390 return fKeyTitle;
391 }
392
393 /** Create iterator for childs elements if any
394 * Means we should try to browse inside.
395 * Either it is directory or some complex object */
396 std::unique_ptr<RLevelIter> GetChildsIter() override
397 {
398 if (fElement)
399 return fElement->GetChildsIter();
400
401 if (fKeyClass.find("TDirectory") == 0) {
402 auto dir = GetDir();
403 if (!dir) return nullptr;
404
405 auto subdir = dir->GetDirectory(fKeyName.c_str());
406 if (!subdir)
407 subdir = dir->GetDirectory(GetName().c_str());
408 if (!subdir) return nullptr;
409 return std::make_unique<TDirectoryLevelIter>(subdir);
410 }
411
412 auto obj = GetObject();
413
414 if (obj)
416
417 if (fElement)
418 return fElement->GetChildsIter();
419
420 return nullptr;
421 }
422
423 /** Return object associated with the TKey */
424 std::unique_ptr<RHolder> GetObject() override
425 {
426 if (fElement)
427 return fElement->GetObject();
428
429 auto obj_class = TClass::GetClass(fKeyClass.c_str());
430 if (!obj_class)
431 return nullptr;
432
433 if (!obj_class->HasDictionary()) {
434 R__LOG_ERROR(ROOT::BrowsableLog()) << "Class " << fKeyClass << " does not have dictionary, object " << fKeyName << " cannot be read";
435 return nullptr;
436 }
437 auto dir = GetDir();
438 if (!dir)
439 return nullptr;
440
441 std::string namecycle = fKeyName + ";"s + std::to_string(fKeyCycle);
442
443 void *obj = dir->GetObjectChecked(namecycle.c_str(), obj_class);
444
445 if (!obj)
446 return nullptr;
447
448 TObject *tobj = (TObject *) obj_class->DynamicCast(TObject::Class(), obj);
449
450 if (tobj) {
451 bool in_dir = dir->FindObject(tobj) != nullptr,
452 special_class = (fKeyClass == "TGeoManager"s) || (fKeyClass == "TTree"s) || (fKeyClass == "TNtuple"s);
453
454 if (in_dir && !special_class)
455 dir->Remove(tobj);
456
457 return std::make_unique<TObjectHolder>(tobj, !special_class);
458 }
459
460 return std::make_unique<RAnyObjectHolder>(obj_class, obj, true);
461 }
462
464 {
465 if (fElement)
466 return fElement->GetDefaultAction();
467
468 if (fKeyClass.empty()) return kActNone;
469 if ((fKeyClass == "TCanvas"s) || (fKeyClass == "ROOT::Experimental::RCanvas"s)) return kActCanvas;
470 if ((fKeyClass == "TTree"s) || (fKeyClass == "TNtuple"s)) return kActTree;
471 if (fKeyClass == "TGeoManager"s) return kActGeom;
475 return kActNone;
476 }
477
478 bool IsFolder() const override
479 {
480 if (fElement)
481 return fElement->IsFolder();
482
483 if (!fKeyClass.empty()) {
485 return true;
486 auto cl = TClass::GetClass(fKeyClass.c_str(), kFALSE, kTRUE);
487 return RProvider::CanHaveChilds(cl);
488 }
489
490 return false;
491 }
492
493 bool IsCapable(EActionKind action) const override
494 {
495 if (fElement)
496 return fElement->IsCapable(action);
497
498 if (fKeyClass.empty()) return false;
499
500 switch(action) {
501 case kActBrowse: {
503 return true;
505 }
506 case kActEdit: return true;
507 case kActImage:
508 case kActDraw6: {
509 // if can draw in TCanvas, can produce image
511 return true;
513 }
514 case kActDraw7: {
516 return true;
518 }
519 case kActCanvas: return (fKeyClass == "TCanvas"s) || (fKeyClass == "ROOT::Experimental::RCanvas"s);
520 case kActTree: return (fKeyClass == "TTree"s) || (fKeyClass == "TNtuple"s);
521 case kActGeom: return (fKeyClass == "TGeoManager"s);
522 default: return false;
523 }
524
525 return false;
526 }
527
528 std::unique_ptr<RItem> CreateItem() const override
529 {
530 if (fElement)
531 return fElement->CreateItem();
532
533 bool is_folder = IsFolder();
534
535 auto item = std::make_unique<TObjectItem>(GetName(), is_folder ? -1 : 0);
536 item->SetTitle(fKeyTitle);
537 item->SetClassName(fKeyClass);
538 item->SetIcon(RProvider::GetClassIcon(fKeyClass, is_folder));
539 item->SetSize(fKeyObjSize);
540 item->SetMTime(fKeyMTime);
541
542 return item;
543 }
544
545};
546
547// ==============================================================================================
548
549/////////////////////////////////////////////////////////////////////////////////
550/// Return element for current TKey object in TDirectory
551
552std::shared_ptr<RElement> TDirectoryLevelIter::GetDirElement(bool read_dir)
553{
554 if (!fKeysIter && fObj)
555 return std::make_shared<TObjectElement>(fObj);
556
557 if ("ROOT::Experimental::RNTuple"s == fKey->GetClassName())
558 return RProvider::BrowseNTuple(fKey->GetName(), fDir->GetFile()->GetName());
559
560 std::string key_class = fKey->GetClassName();
561 if (read_dir && (key_class.find("TDirectory") == 0)) {
562 auto subdir = fDir->GetDirectory(fKey->GetName());
563 if (subdir) return std::make_shared<TDirectoryElement>("", subdir);
564 }
565
566 return std::make_shared<TKeyElement>(fDir, fKey);
567}
568
569// ==============================================================================================
570
571
572/** \class RTFileProvider
573\ingroup rbrowser
574
575Provides access to ROOT files with extension "root"
576Other extensions can be registered
577*/
578
579class RTFileProvider : public RProvider {
580
581public:
583 {
584 RegisterFile("root", [] (const std::string &fullname) -> std::shared_ptr<RElement> {
585 auto f = dynamic_cast<TFile *> (gROOT->GetListOfFiles()->FindObject(fullname.c_str()));
586 if (!f) f = TFile::Open(fullname.c_str());
587 if (!f) return nullptr;
588 return std::make_shared<TDirectoryElement>(fullname, f, true);
589 });
590
591 RegisterBrowse(TFile::Class(), [](std::unique_ptr<RHolder> &object) -> std::shared_ptr<RElement> {
592 return std::make_shared<TDirectoryElement>("", const_cast<TFile*>(object->Get<TFile>()), true);
593 });
594
595 RegisterBrowse(TDirectory::Class(), [](std::unique_ptr<RHolder> &object) -> std::shared_ptr<RElement> {
596 return std::make_shared<TDirectoryElement>("", const_cast<TDirectory*>(object->Get<TDirectory>()));
597 });
598 }
599
#define R__LOG_ERROR(...)
Definition RLogger.hxx:362
#define f(i)
Definition RSha256.hxx:104
short Short_t
Definition RtypesCore.h:39
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
RTFileProvider newRTFileProvider
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition TGX11.cxx:110
#define gROOT
Definition TROOT.h:414
static EContentKind GetContentKind(const std::string &kind)
Find item with specified name Default implementation, should work for all.
Definition RElement.cxx:52
@ kFileName
"filename" - file name if applicable
Definition RElement.hxx:44
EActionKind
Possible actions on double-click.
Definition RElement.hxx:50
@ kActImage
can be shown in image viewer, can provide image
Definition RElement.hxx:54
@ kActDraw6
can be drawn inside ROOT6 canvas
Definition RElement.hxx:55
@ kActCanvas
indicate that it is canvas and should be drawn directly
Definition RElement.hxx:57
@ kActTree
can be shown in tree viewer
Definition RElement.hxx:58
@ kActGeom
can be shown in geometry viewer
Definition RElement.hxx:59
@ kActBrowse
just browse (expand) item
Definition RElement.hxx:52
@ kActEdit
can provide data for text editor
Definition RElement.hxx:53
@ kActDraw7
can be drawn inside ROOT7 canvas
Definition RElement.hxx:56
Iterator over single level hierarchy like any array, keys list, ...
Provider of different browsing methods for supported classes.
Definition RProvider.hxx:37
static std::shared_ptr< RElement > BrowseNTuple(const std::string &tuplename, const std::string &filename)
Start browsing of RNTuple.
static bool CanDraw6(const ClassArg &)
Return true if provided class can be drawn on the TCanvas.
static std::shared_ptr< RElement > Browse(std::unique_ptr< RHolder > &obj)
Create browsable element for the object Created element may take ownership over the object.
static bool CanDraw7(const ClassArg &)
Return true if provided class can be drawn on the RCanvas.
static std::string GetClassIcon(const ClassArg &, bool=false)
Return icon name for the given class - either class name or TClass *.
void RegisterFile(const std::string &extension, FileFunc_t func)
Definition RProvider.cxx:95
void RegisterBrowse(const TClass *cl, BrowseFunc_t func)
static bool CanHaveChilds(const ClassArg &)
Return true if provided class can have childs.
TObjectElement(TObject *obj, const std::string &name="", bool _hide_childs=false)
Constructor with plain TObject* as argument - ownership is not defined.
void SetObject(TObject *obj)
Constructor with std::unique_ptr<RHolder> as argument.
virtual const TObject * CheckObject() const
Check if object still exists.
void ForgetObject() const
Forget object, use when it was deleted behind the scene.
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2969
bool cd() override
Select directory as active.
bool fIsFile
! is TFile instance registered in global list of files
virtual ~TDirectoryElement()=default
EActionKind GetDefaultAction() const override
Get default action - browsing for the TFile/TDirectory.
Long64_t GetSize() const override
Size of TDirectory.
std::string GetContent(const std::string &kind) override
Returns element content, depends from kind.
TDirectory * GetDir() const
std::unique_ptr< RLevelIter > GetChildsIter() override
Provide iterator over TDirectory.
bool IsFolder() const override
Check if element can have childs.
TDirectoryElement(const std::string &fname, TDirectory *dir=nullptr, bool isfile=false)
std::string GetMTime() const override
TFile * GetFile() const
std::string GetName() const override
Name of TDirectoryElement.
const TObject * CheckObject() const override
Check if object still exists.
std::string fFileName
! file name
std::string GetTitle() const override
Title of TDirectoryElement.
TDirectoryLevelIter(TDirectory *dir)
std::shared_ptr< RElement > GetElement() override
Returns full information for current element.
bool fKeysIter
! iterating over keys list (default)
std::string GetItemName() const override
Returns current entry name.
std::unique_ptr< RItem > CreateItem() override
Create item for the client.
TKey * fKey
! currently selected key
bool fOnlyLastCycle
! show only last cycle in list of keys
std::shared_ptr< RElement > GetDirElement(bool read_dir)
Return element for current TKey object in TDirectory.
std::string fCurrentName
! current key name
std::unique_ptr< TIterator > fIter
! created iterator
bool CanItemHaveChilds() const override
Returns true if current item can have childs.
TDirectory * fDir
! current directory handle
TObject * fObj
! currently selected object
virtual ~TDirectoryLevelIter()=default
bool Next() override
Shift to next entry.
Describe directory structure in memory.
Definition TDirectory.h:45
static TClass * Class()
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Definition TFile.h:53
static TClass * Class()
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:4110
bool IsCapable(EActionKind action) const override
Check if want to perform action.
std::string fKeyMTime
EActionKind GetDefaultAction() const override
Get default action - browsing for the TFile/TDirectory.
std::unique_ptr< RLevelIter > GetChildsIter() override
Create iterator for childs elements if any Means we should try to browse inside.
std::string fKeyName
std::string GetTitle() const override
Title of TKeyElement (optional)
std::shared_ptr< RElement > fElement
! holder of read object
virtual ~TKeyElement()=default
std::string fKeyTitle
std::unique_ptr< RHolder > GetObject() override
Return object associated with the TKey.
std::unique_ptr< RItem > CreateItem() const override
Returns item with element description.
std::string fKeyClass
Long64_t GetSize() const override
Size of TDirectory.
bool IsFolder() const override
Check if element can have childs.
TKeyElement(TDirectory *dir, TKey *key)
std::string GetMTime() const override
std::string GetName() const override
Name of TKeyElement, includes key cycle.
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition TKey.h:28
const char * GetTitle() const override
Returns title (title can contain 32x32 xpm thumbnail/icon).
Definition TKey.cxx:1577
Int_t GetNbytes() const
Definition TKey.h:86
virtual const char * GetClassName() const
Definition TKey.h:75
const TDatime & GetDatime() const
Definition TKey.h:81
Short_t GetCycle() const
Return cycle number associated to this key.
Definition TKey.cxx:582
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
Mother of all ROOT objects.
Definition TObject.h:41
static TClass * Class()
@ kInvalidObject
if object ctor succeeded but object should not be used
Definition TObject.h:72
ROOT::Experimental::RLogChannel & BrowsableLog()
Log channel for Browsable diagnostics.
Definition RElement.cxx:20