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
18
19#include <ROOT/RLogger.hxx>
20
21#include "TKey.h"
22#include "TDirectory.h"
23#include "TROOT.h"
24#include "TFile.h"
25#include "TClass.h"
26#include "TEnv.h"
27
28#include <cstring>
29#include <string>
30
31using namespace std::string_literals;
32
33using namespace ROOT::Experimental::Browsable;
34
35
36/** \class TDirectoryLevelIter
37\ingroup rbrowser
38
39Iterator over keys in TDirectory
40*/
41
42
44 TDirectory *fDir{nullptr}; ///<! current directory handle
45 std::unique_ptr<TIterator> fIter; ///<! created iterator
46 Bool_t fKeysIter{kTRUE}; ///<! iterating over keys list (default)
47 Bool_t fOnlyLastCycle{kFALSE}; ///<! show only last cycle in list of keys
48 TKey *fKey{nullptr}; ///<! currently selected key
49 TObject *fObj{nullptr}; ///<! currently selected object
50 std::string fCurrentName; ///<! current key name
51
53 {
54 if (!fDir) return false;
55 fObj = nullptr;
56 fKey = nullptr;
57 auto lst = fDir->GetListOfKeys();
58 if (lst->GetSize() == 0) {
59 auto olst = fDir->GetList();
60 if (olst->GetSize() > 0) {
61 fKeysIter = false;
62 fIter.reset(olst->MakeIterator());
63 return true;
64 }
65 }
66 fKeysIter = true;
67 fIter.reset(lst->MakeIterator());
68 return true;
69 }
70
72 {
73 fCurrentName.clear();
74 if (!fIter) return false;
75
76 fObj = fIter->Next();
77 if (!fObj) {
78 fIter.reset();
79 return false;
80 }
81 if (!fKeysIter) {
83 return true;
84 }
85
86 while(true) {
87
88 fKey = dynamic_cast<TKey *>(fObj);
89
90 if (!fKey) {
91 fIter.reset();
92 return false;
93 }
94
95 if (!fOnlyLastCycle) break;
96
97 TIter iter(fDir->GetListOfKeys());
98 TKey *key = nullptr;
99 bool found_newer = false;
100 while ((key = dynamic_cast<TKey*>(iter())) != nullptr) {
101 if ((key != fKey) && !strcmp(key->GetName(), fKey->GetName()) && (key->GetCycle() > fKey->GetCycle())) {
102 found_newer = true;
103 break;
104 }
105 }
106
107 if (!found_newer) break;
108
109 fObj = fIter->Next();
110 }
111
113 fCurrentName.append(";");
114 fCurrentName.append(std::to_string(fKey->GetCycle()));
115
116 return true;
117 }
118
119public:
120 explicit TDirectoryLevelIter(TDirectory *dir) : fDir(dir)
121 {
122 const char *undef = "<undefined>";
123 const char *value = gEnv->GetValue("WebGui.LastCycle", undef);
124 if (value) {
125 std::string svalue = value;
126 if (svalue != undef) {
127 if (svalue == "yes")
129 else if (svalue == "no")
131 else
132 R__LOG_ERROR(ROOT::Experimental::BrowsableLog()) << "WebGui.LastCycle must be yes or no";
133 }
134 }
135
136 CreateIter();
137 }
138
139 virtual ~TDirectoryLevelIter() = default;
140
141 bool Next() override { return NextDirEntry(); }
142
143 // use default implementation for now
144 // bool Find(const std::string &name) override { return FindDirEntry(name); }
145
146 std::string GetItemName() const override { return fCurrentName; }
147
148 bool CanItemHaveChilds() const override
149 {
150 if (!fKeysIter && fObj)
151 return RProvider::CanHaveChilds(fObj->IsA());
152
153 if (fKeysIter && fKey) {
155 return true;
157 return RProvider::CanHaveChilds(cl);
158 }
159 return false;
160 }
161
162 /** Create element for the browser */
163 std::unique_ptr<RItem> CreateItem() override
164 {
165 if (!fKeysIter && fObj) {
166 auto item = std::make_unique<TObjectItem>(GetItemName(), CanItemHaveChilds() ? -1 : 0);
167 item->SetClassName(fObj->IsA()->GetName());
168 item->SetIcon(RProvider::GetClassIcon(fObj->IsA()->GetName()));
169 item->SetTitle(fObj->GetTitle());
170 return item;
171 }
172
173 auto item = std::make_unique<TKeyItem>(GetItemName(), CanItemHaveChilds() ? -1 : 0);
174 item->SetClassName(fKey->GetClassName());
175 item->SetIcon(RProvider::GetClassIcon(fKey->GetClassName()));
176 item->SetTitle(fKey->GetTitle());
177 item->SetSize(std::to_string(fKey->GetNbytes()));
178 return item;
179 }
180
181 /** Returns full information for current element */
182 std::shared_ptr<RElement> GetElement() override;
183
184};
185
186// ===============================================================================================================
187
188
189/** \class TKeyElement
190\ingroup rbrowser
191
192Element representing TKey from TDirectory
193*/
194
195
196class TKeyElement : public RElement {
197 TDirectory *fDir{nullptr};
198 std::string fKeyName;
199 std::string fKeyTitle;
201 std::string fKeyClass;
202 std::shared_ptr<RElement> fElement; ///<! holder of read object
203
204public:
205 TKeyElement(TDirectory *dir, TKey *key) : fDir(dir)
206 {
207 fKeyName = key->GetName();
208 fKeyTitle = key->GetTitle();
209 fKeyCycle = key->GetCycle();
210 fKeyClass = key->GetClassName();
211 }
212
213 virtual ~TKeyElement() = default;
214
215 /** Name of TKeyElement, includes key cycle */
216 std::string GetName() const override
217 {
218 if (fElement)
219 return fElement->GetName();
220 std::string name = fKeyName;
221 name.append(";");
222 name.append(std::to_string(fKeyCycle));
223
224 return name;
225 }
226
227 /** Title of TKeyElement (optional) */
228 std::string GetTitle() const override
229 {
230 if (fElement)
231 return fElement->GetTitle();
232
233 return fKeyTitle;
234 }
235
236 /** Create iterator for childs elements if any
237 * Means we should try to browse inside.
238 * Either it is directory or some complex object */
239 std::unique_ptr<RLevelIter> GetChildsIter() override
240 {
241 if (fElement)
242 return fElement->GetChildsIter();
243
244 if (fKeyClass.find("TDirectory") == 0) {
245 auto subdir = fDir->GetDirectory(fKeyName.c_str());
246 if (!subdir)
247 subdir = fDir->GetDirectory(GetName().c_str());
248 if (!subdir) return nullptr;
249 return std::make_unique<TDirectoryLevelIter>(subdir);
250 }
251
252 auto obj = GetObject();
253
254 if (obj)
256
257 if (fElement)
258 return fElement->GetChildsIter();
259
260 return nullptr;
261 }
262
263 /** Return object associated with TKey, if TDirectory has object of that name it will be returned */
264 std::unique_ptr<RHolder> GetObject() override
265 {
266 if (fElement)
267 return fElement->GetObject();
268
269 auto obj_class = TClass::GetClass(fKeyClass.c_str());
270 if (!obj_class)
271 return nullptr;
272
273 if (!obj_class->HasDictionary()) {
274 R__LOG_ERROR(ROOT::Experimental::BrowsableLog()) << "Class " << fKeyClass << " does not have dictionary, object " << fKeyName << " cannot be read";
275 return nullptr;
276 }
277
278 std::string namecycle = fKeyName + ";"s + std::to_string(fKeyCycle);
279
280 void *obj = fDir->GetObjectChecked(namecycle.c_str(), obj_class);
281 if (!obj)
282 return nullptr;
283
284 TObject *tobj = (TObject *) obj_class->DynamicCast(TObject::Class(), obj);
285
286 if (tobj) {
287 bool owned_by_dir = (fDir->FindObject(tobj) == tobj) || (fKeyClass == "TGeoManager");
288
289 return std::make_unique<TObjectHolder>(tobj, !owned_by_dir);
290 }
291
292 return std::make_unique<RAnyObjectHolder>(obj_class, obj, true);
293 }
294
295
297 {
298 if (fElement)
299 return fElement->GetDefaultAction();
300
301 if (fKeyClass.empty()) return kActNone;
302 if ((fKeyClass == "TCanvas"s) || (fKeyClass == "ROOT::Experimental::RCanvas"s)) return kActCanvas;
303 if (fKeyClass == "TGeoManager"s) return kActGeom;
307 return kActNone;
308 }
309
310 bool IsCapable(EActionKind action) const override
311 {
312 if (fElement)
313 return fElement->IsCapable(action);
314
315 if (fKeyClass.empty()) return false;
316
317 switch(action) {
318 case kActBrowse: {
320 return true;
322 }
323 case kActEdit: return true;
324 case kActImage:
325 case kActDraw6: {
326 // if can draw in TCanvas, can produce image
328 return true;
330 }
331 case kActDraw7: {
333 return true;
335 }
336 case kActCanvas: return (fKeyClass == "TCanvas"s) || (fKeyClass == "ROOT::Experimental::RCanvas"s);
337 case kActGeom: return (fKeyClass == "TGeoManager"s);
338 default: return false;
339 }
340
341 return false;
342 }
343
344};
345
346// ==============================================================================================
347
348/** \class TDirectoryElement
349\ingroup rbrowser
350
351Element representing TDirectory
352*/
353
354
356 std::string fFileName; ///<! file name
357 TDirectory *fDir{nullptr}; ///<! subdirectory (ifany)
358
359 ///////////////////////////////////////////////////////////////////
360 /// Get TDirectory. Checks if parent file is still there. If not, means it was closed outside ROOT
361
363 {
364 if (fDir) {
365 if (fDir->IsZombie())
366 fDir = nullptr;
367 else if (!gROOT->GetListOfFiles()->FindObject(fDir->GetFile()))
368 fDir = nullptr;
369 } else if (!fFileName.empty()) {
370 fDir = TFile::Open(fFileName.c_str());
371 }
372
373 return fDir;
374 }
375
376public:
377
378 TDirectoryElement(const std::string &fname, TDirectory *dir = nullptr)
379 {
380 fFileName = fname;
381 fDir = dir;
382 }
383
384 virtual ~TDirectoryElement() = default;
385
386 /** Name of TDirectoryElement */
387 std::string GetName() const override
388 {
389 if (fDir)
390 return fDir->GetName();
391
392 if (!fFileName.empty()) {
393 auto pos = fFileName.rfind("/");
394 return ((pos == std::string::npos) || (pos > fFileName.length() - 2)) ? fFileName : fFileName.substr(pos + 1);
395 }
396
397 return ""s;
398 }
399
400 /** Title of TDirectoryElement */
401 std::string GetTitle() const override
402 {
403 if (fDir)
404 return fDir->GetTitle();
405
406 return "ROOT file "s + fFileName;
407 }
408
409 /** Provide iterator over TDirectory */
410 std::unique_ptr<RLevelIter> GetChildsIter() override
411 {
412 auto dir = GetDir();
413
414 return dir ? std::make_unique<TDirectoryLevelIter>(dir) : nullptr;
415 }
416
417 /** Get default action - browsing for the TFile/TDirectory*/
418 EActionKind GetDefaultAction() const override { return kActBrowse; }
419
420 /** Select directory as active */
421 bool cd() override
422 {
423 if (fDir && !fDir->IsZombie()) {
424 fDir->cd();
425 return true;
426 }
427 return false;
428 }
429
430 std::string GetContent(const std::string &kind) override
431 {
432 if (GetContentKind(kind) == kFileName)
433 return fFileName;
434
435 return ""s;
436 }
437
438};
439
440// ==============================================================================================
441
442/////////////////////////////////////////////////////////////////////////////////
443/// Return element for current TKey object in TDirectory
444
445std::shared_ptr<RElement> TDirectoryLevelIter::GetElement()
446{
447 if (!fKeysIter && fObj)
448 return std::make_shared<TObjectElement>(fObj);
449
450 if ("ROOT::Experimental::RNTuple"s == fKey->GetClassName())
452
453 std::string key_class = fKey->GetClassName();
454 if (key_class.find("TDirectory") == 0) {
455 auto subdir = fDir->GetDirectory(fKey->GetName());
456 if (subdir) return std::make_shared<TDirectoryElement>("", subdir);
457 }
458
459 return std::make_shared<TKeyElement>(fDir, fKey);
460}
461
462
463
464// ==============================================================================================
465
466
467/** \class RTFileProvider
468\ingroup rbrowser
469
470Provides access to ROOT files with extension "root"
471Other extensions can be registered
472*/
473
474
475class RTFileProvider : public RProvider {
476
477public:
479 {
480 RegisterFile("root", [] (const std::string &fullname) -> std::shared_ptr<RElement> {
481 auto f = dynamic_cast<TFile *> (gROOT->GetListOfFiles()->FindObject(fullname.c_str()));
482 if (!f) f = TFile::Open(fullname.c_str());
483 if (!f) return nullptr;
484 return std::make_shared<TDirectoryElement>(fullname, f);
485 });
486
487 RegisterBrowse(TFile::Class(), [](std::unique_ptr<RHolder> &object) -> std::shared_ptr<RElement> {
488 return std::make_shared<TDirectoryElement>("", const_cast<TFile*>(object->Get<TFile>()));
489 });
490
491 RegisterBrowse(TDirectory::Class(), [](std::unique_ptr<RHolder> &object) -> std::shared_ptr<RElement> {
492 return std::make_shared<TDirectoryElement>("", const_cast<TDirectory*>(object->Get<TDirectory>()));
493 });
494 }
495
497
498
#define R__LOG_ERROR(...)
Definition RLogger.hxx:362
#define f(i)
Definition RSha256.hxx:104
const Bool_t kFALSE
Definition RtypesCore.h:101
short Short_t
Definition RtypesCore.h:39
const Bool_t kTRUE
Definition RtypesCore.h:100
RTFileProvider newRTFileProvider
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
char name[80]
Definition TGX11.cxx:110
#define gROOT
Definition TROOT.h:404
Basic element of browsable hierarchy.
Definition RElement.hxx:33
@ kFileName
"filename" - file name if applicable
Definition RElement.hxx:43
static EContentKind GetContentKind(const std::string &kind)
Find item with specified name Default implementation, should work for all.
Definition RElement.cxx:49
EActionKind
Possible actions on double-click.
Definition RElement.hxx:49
@ kActEdit
can provide data for text editor
Definition RElement.hxx:52
@ kActCanvas
indicate that it is canvas and should be drawn directly
Definition RElement.hxx:56
@ kActBrowse
just browse (expand) item
Definition RElement.hxx:51
@ kActGeom
can be shown in geometry viewer
Definition RElement.hxx:57
@ kActDraw7
can be drawn inside ROOT7 canvas
Definition RElement.hxx:55
@ kActImage
can be shown in image viewer, can provide image
Definition RElement.hxx:53
@ kActDraw6
can be drawn inside ROOT6 canvas
Definition RElement.hxx:54
Iterator over single level hierarchy like any array, keys list, ...
Provider of different browsing methods for supported classes.
Definition RProvider.hxx:36
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:88
void RegisterBrowse(const TClass *cl, BrowseFunc_t func)
static bool CanHaveChilds(const ClassArg &)
Return true if provided class can have childs.
Provides access to ROOT files with extension "root" Other extensions can be registered.
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:2966
Element representing TDirectory.
bool cd() override
Select directory as active.
virtual ~TDirectoryElement()=default
EActionKind GetDefaultAction() const override
Get default action - browsing for the TFile/TDirectory.
std::string GetContent(const std::string &kind) override
Returns element content, depends from kind.
std::unique_ptr< RLevelIter > GetChildsIter() override
Provide iterator over TDirectory.
TDirectory * fDir
! subdirectory (ifany)
std::string GetName() const override
Name of TDirectoryElement.
TDirectoryElement(const std::string &fname, TDirectory *dir=nullptr)
std::string fFileName
! file name
std::string GetTitle() const override
Title of TDirectoryElement.
TDirectory * GetDir()
Get TDirectory. Checks if parent file is still there. If not, means it was closed outside ROOT.
Iterator over keys in TDirectory.
TDirectoryLevelIter(TDirectory *dir)
std::shared_ptr< RElement > GetElement() override
Returns full information for current element.
Bool_t fOnlyLastCycle
! show only last cycle in list of keys
std::string GetItemName() const override
Returns current entry name
std::unique_ptr< RItem > CreateItem() override
Create element for the browser.
TKey * fKey
! currently selected key
std::string fCurrentName
! current key name
Bool_t fKeysIter
! iterating over keys list (default)
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
virtual TList * GetList() const
Definition TDirectory.h:222
virtual TDirectory * GetDirectory(const char *namecycle, Bool_t printError=false, const char *funcname="GetDirectory")
Find a directory using apath.
virtual TFile * GetFile() const
Definition TDirectory.h:220
TObject * FindObject(const char *name) const override
Find object by name in the list of memory objects.
virtual Bool_t cd()
Change current directory to "this" directory.
virtual TList * GetListOfKeys() const
Definition TDirectory.h:223
virtual void * GetObjectChecked(const char *namecycle, const char *classname)
See documentation of TDirectory::GetObjectCheck(const char *namecycle, const TClass *cl)
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition TFile.h:54
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:4025
Element representing TKey from TDirectory.
TDirectory * fDir
bool IsCapable(EActionKind action) const override
Check if want to perform action.
EActionKind GetDefaultAction() const override
Get default action.
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 TKey, if TDirectory has object of that name it will be returned.
std::string fKeyClass
TKeyElement(TDirectory *dir, TKey *key)
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
Int_t GetNbytes() const
Definition TKey.h:87
virtual const char * GetClassName() const
Definition TKey.h:76
virtual const char * GetTitle() const
Returns title (title can contain 32x32 xpm thumbnail/icon).
Definition TKey.cxx:1532
Short_t GetCycle() const
Return cycle number associated to this key.
Definition TKey.cxx:577
virtual const char * GetTitle() const
Returns title of object.
Definition TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:429
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:153
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:473
RLogChannel & BrowsableLog()
Log channel for Browsable diagnostics.
Definition RElement.cxx:18