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 TKey *fKey{nullptr}; ///<! currently selected key
47 TObject *fObj{nullptr}; ///<! currently selected object
48 std::string fCurrentName; ///<! current key name
49
51 {
52 if (!fDir) return false;
53 fObj = nullptr;
54 fKey = nullptr;
55 auto lst = fDir->GetListOfKeys();
56 if (lst->GetSize() == 0) {
57 auto olst = fDir->GetList();
58 if (olst->GetSize() > 0) {
59 fKeysIter = false;
60 fIter.reset(olst->MakeIterator());
61 return true;
62 }
63 }
64 fKeysIter = true;
65 fIter.reset(lst->MakeIterator());
66 return true;
67 }
68
70 {
71 fCurrentName.clear();
72 if (!fIter) return false;
73
74 fObj = fIter->Next();
75 if (!fObj) {
76 fIter.reset();
77 if (!fKeysIter || !fDir)
78 return false;
79 fKeysIter = false;
80 fIter.reset(fDir->GetList()->MakeIterator());
81 fObj = fIter->Next();
82 if (!fObj) {
83 fIter.reset();
84 return false;
85 }
86 }
87 if (!fKeysIter) {
88 // exclude object with duplicated name as keys
89 while (fObj) {
90 if (!fDir->GetListOfKeys()->FindObject(fObj->GetName()))
91 break;
92 fObj = fIter->Next();
93 }
94 if (!fObj) {
95 fIter.reset();
96 return false;
97 }
98
100 return true;
101 }
102
103 while(true) {
104
105 fKey = dynamic_cast<TKey *>(fObj);
106
107 if (!fKey) {
108 fIter.reset();
109 return false;
110 }
111
113 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
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 CreateIter();
141 }
142
143 ~TDirectoryLevelIter() override = default;
144
145 bool Next() override { return NextDirEntry(); }
146
147 // use default implementation for now
148 // bool Find(const std::string &name) override { return FindDirEntry(name); }
149
150 std::string GetItemName() const override { return fCurrentName; }
151
152 bool CanItemHaveChilds() const override
153 {
154 if (!fKeysIter && fObj)
156
157 if (fKeysIter && fKey) {
159 return true;
161 return RProvider::CanHaveChilds(cl);
162 }
163 return false;
164 }
165
166 /** Create item for the client */
167 std::unique_ptr<RItem> CreateItem() override
168 {
169 if (!fKeysIter && fObj) {
170 std::unique_ptr<RHolder> holder = std::make_unique<TObjectHolder>(fObj, kFALSE);
171
173
174 return elem ? elem->CreateItem() : nullptr;
175 }
176
177 auto item = GetDirElement(false)->CreateItem();
178 item->SetName(fCurrentName);
179 return item;
180 }
181
182 std::shared_ptr<RElement> GetDirElement(bool read_dir);
183
184 /** Returns full information for current element */
185 std::shared_ptr<RElement> GetElement() override { return GetDirElement(true); }
186};
187
188// ===============================================================================================================
189
190/** \class TDirectoryElement
191\ingroup rbrowser
192
193Element representing TDirectory
194*/
195
197 std::string fFileName; ///<! file name
198 bool fIsFile{false}; ///<! is TFile instance registered in global list of files
199
200protected:
201
202 const TObject *CheckObject() const override
203 {
204 // during TROOT destructor just forget about file reference
205 if (!gROOT || gROOT->TestBit(TObject::kInvalidObject)) {
206 ForgetObject();
207 return nullptr;
208 }
209
211 return nullptr;
212
213 if (fIsFile) {
214 if (!gROOT->GetListOfFiles()->FindObject(fObj))
215 ForgetObject();
216 } else if (!gROOT->GetListOfFiles()->FindObject(((TDirectory *) fObj)->GetFile()))
217 ForgetObject();
218
219 return fObj;
220 }
221
223 {
224 if (!CheckObject() && fIsFile && fFileName.empty())
225 (const_cast<TDirectoryElement *>(this))->SetObject(TFile::Open(fFileName.c_str()));
226
227 return dynamic_cast<TDirectory *>(fObj);
228 }
229
230 TFile *GetFile() const
231 {
232 if (!fIsFile)
233 return nullptr;
234
235 return dynamic_cast<TFile *>(GetDir());
236 }
237
238
239public:
240
241 TDirectoryElement(const std::string &fname, TDirectory *dir = nullptr, bool isfile = false) : TObjectElement(dir)
242 {
244 fIsFile = isfile;
245 if (fIsFile && fObj && !gROOT->GetListOfFiles()->FindObject(fObj)) {
246 fIsFile = false;
247 ForgetObject();
248 }
249 }
250
251 ~TDirectoryElement() override = default;
252
253 /** Name of TDirectoryElement */
254 std::string GetName() const override
255 {
256 if (CheckObject())
257 return fObj->GetName();
258
259 if (!fFileName.empty()) {
260 auto pos = fFileName.rfind("/");
261 return ((pos == std::string::npos) || (pos > fFileName.length() - 2)) ? fFileName : fFileName.substr(pos + 1);
262 }
263
264 return ""s;
265 }
266
267 /** Title of TDirectoryElement */
268 std::string GetTitle() const override
269 {
270 if (CheckObject())
271 return fObj->GetTitle();
272
273 return "ROOT file "s + fFileName;
274 }
275
276 bool IsFolder() const override { return true; }
277
278 /** Provide iterator over TDirectory */
279 std::unique_ptr<RLevelIter> GetChildsIter() override
280 {
281 auto dir = GetDir();
282
283 return dir ? std::make_unique<TDirectoryLevelIter>(dir) : nullptr;
284 }
285
286 /** Get default action - browsing for the TFile/TDirectory */
287 EActionKind GetDefaultAction() const override { return kActBrowse; }
288
289 /** Select directory as active */
290 bool cd() override
291 {
292 auto dir = GetDir();
293 if (dir) {
294 dir->cd();
295 return true;
296 }
297 return false;
298 }
299
300 /** Size of TDirectory */
301 Long64_t GetSize() const override
302 {
303 auto f = GetFile();
304 if (f) return f->GetSize();
305 return -1;
306 }
307
308 std::string GetMTime() const override
309 {
310 auto f = GetFile();
311 if (f) return f->GetModificationDate().AsSQLString();
312 return ""s;
313 }
314
315 std::string GetContent(const std::string &kind) override
316 {
317 if (GetContentKind(kind) == kFileName)
318 return fFileName;
319
320 return ""s;
321 }
322
323};
324
325// ===============================================================================================================
326
327
328/** \class TKeyElement
329\ingroup rbrowser
330
331Element representing TKey from TDirectory
332*/
333
338 std::shared_ptr<RElement> fElement; ///<! holder of read object
339
340 std::string GetMTime() const override { return fKeyMTime; }
341
342 Long64_t GetSize() const override { return fKeyObjSize; }
343
344public:
346 {
347 fKeyName = key->GetName();
348 fKeyTitle = key->GetTitle();
349 fKeyCycle = key->GetCycle();
350 fKeyClass = key->GetClassName();
351 fKeyMTime = key->GetDatime().AsSQLString();
352 fKeyObjSize = key->GetNbytes();
353 }
354
355 ~TKeyElement() override = default;
356
357 /** Name of TKeyElement, includes key cycle */
358 std::string GetName() const override
359 {
360 if (fElement)
361 return fElement->GetName();
362
363 std::string name = fKeyName;
364 name.append(";");
365 name.append(std::to_string(fKeyCycle));
366
367 return name;
368 }
369
370 /** Title of TKeyElement (optional) */
371 std::string GetTitle() const override
372 {
373 if (fElement)
374 return fElement->GetTitle();
375
376 return fKeyTitle;
377 }
378
379 /** Create iterator for childs elements if any
380 * Means we should try to browse inside.
381 * Either it is directory or some complex object */
382 std::unique_ptr<RLevelIter> GetChildsIter() override
383 {
384 if (fElement)
385 return fElement->GetChildsIter();
386
387 if (fKeyClass.find("TDirectory") == 0) {
388 auto dir = GetDir();
389 if (!dir) return nullptr;
390
391 auto subdir = dir->GetDirectory(fKeyName.c_str());
392 if (!subdir)
393 subdir = dir->GetDirectory(GetName().c_str());
394 if (!subdir) return nullptr;
395 return std::make_unique<TDirectoryLevelIter>(subdir);
396 }
397
398 auto obj = GetObject();
399
400 if (obj)
402
403 if (fElement)
404 return fElement->GetChildsIter();
405
406 return nullptr;
407 }
408
409 /** Return object associated with the TKey */
410 std::unique_ptr<RHolder> GetObject() override
411 {
412 if (fElement)
413 return fElement->GetObject();
414
415 auto obj_class = TClass::GetClass(fKeyClass.c_str());
416 if (!obj_class)
417 return nullptr;
418
419 if (!obj_class->HasDictionary()) {
420 R__LOG_ERROR(ROOT::BrowsableLog()) << "Class " << fKeyClass << " does not have dictionary, object " << fKeyName << " cannot be read";
421 return nullptr;
422 }
423 auto dir = GetDir();
424 if (!dir)
425 return nullptr;
426
427 std::string namecycle = fKeyName + ";"s + std::to_string(fKeyCycle);
428
429 void *obj = dir->GetObjectChecked(namecycle.c_str(), obj_class);
430
431 if (!obj)
432 return nullptr;
433
434 TObject *tobj = (TObject *) obj_class->DynamicCast(TObject::Class(), obj);
435
436 if (tobj) {
437 bool in_dir = dir->FindObject(tobj) != nullptr,
438 special_class = (fKeyClass == "TGeoManager"s) || (fKeyClass == "TTree"s) || (fKeyClass == "TNtuple"s);
439
440 if (in_dir && !special_class)
441 dir->Remove(tobj);
442
443 return std::make_unique<TObjectHolder>(tobj, !special_class);
444 }
445
446 return std::make_unique<RAnyObjectHolder>(obj_class, obj, true);
447 }
448
450 {
451 if (fElement)
452 return fElement->GetDefaultAction();
453
454 if (fKeyClass.empty()) return kActNone;
455 if ((fKeyClass == "TCanvas"s) || (fKeyClass == "ROOT::Experimental::RCanvas"s)) return kActCanvas;
456 if ((fKeyClass == "TTree"s) || (fKeyClass == "TNtuple"s)) return kActTree;
457 if (fKeyClass == "TGeoManager"s) return kActGeom;
461 return kActNone;
462 }
463
464 bool IsFolder() const override
465 {
466 if (fElement)
467 return fElement->IsFolder();
468
469 if (!fKeyClass.empty()) {
471 return true;
472 auto cl = TClass::GetClass(fKeyClass.c_str(), kFALSE, kTRUE);
473 return RProvider::CanHaveChilds(cl);
474 }
475
476 return false;
477 }
478
479 bool IsCapable(EActionKind action) const override
480 {
481 if (fElement)
482 return fElement->IsCapable(action);
483
484 if (fKeyClass.empty()) return false;
485
486 switch(action) {
487 case kActBrowse: {
489 return true;
491 }
492 case kActEdit: return true;
493 case kActImage:
494 case kActDraw6: {
495 // if can draw in TCanvas, can produce image
497 return true;
499 }
500 case kActDraw7: {
502 return true;
504 }
505 case kActCanvas: return (fKeyClass == "TCanvas"s) || (fKeyClass == "ROOT::Experimental::RCanvas"s);
506 case kActTree: return (fKeyClass == "TTree"s) || (fKeyClass == "TNtuple"s);
507 case kActGeom: return (fKeyClass == "TGeoManager"s);
508 default: return false;
509 }
510
511 return false;
512 }
513
514 std::unique_ptr<RItem> CreateItem() const override
515 {
516 if (fElement)
517 return fElement->CreateItem();
518
519 bool is_folder = IsFolder();
520
521 auto item = std::make_unique<TObjectItem>(GetName(), is_folder ? -1 : 0);
522 item->SetTitle(fKeyTitle);
523 item->SetClassName(fKeyClass);
525 item->SetSize(fKeyObjSize);
526 item->SetMTime(fKeyMTime);
527
528 return item;
529 }
530
531};
532
533// ==============================================================================================
534
535/////////////////////////////////////////////////////////////////////////////////
536/// Return element for current TKey object in TDirectory
537
538std::shared_ptr<RElement> TDirectoryLevelIter::GetDirElement(bool read_dir)
539{
540 if (!fKeysIter && fObj)
541 return std::make_shared<TObjectElement>(fObj);
542
543 if ("ROOT::RNTuple"s == fKey->GetClassName())
544 return RProvider::BrowseNTuple(fKey->GetName(), fDir->GetFile()->GetName());
545
546 std::string key_class = fKey->GetClassName();
547 if (read_dir && (key_class.find("TDirectory") == 0)) {
548 auto subdir = fDir->GetDirectory(fKey->GetName());
549 if (subdir) return std::make_shared<TDirectoryElement>("", subdir);
550 }
551
552 return std::make_shared<TKeyElement>(fDir, fKey);
553}
554
555// ==============================================================================================
556
557
558/** \class RTFileProvider
559\ingroup rbrowser
560
561Provides access to ROOT files with extension "root"
562Other extensions can be registered
563*/
564
565class RTFileProvider : public RProvider {
566
567public:
569 {
570 RegisterFile("root", [] (const std::string &fullname) -> std::shared_ptr<RElement> {
571 auto f = dynamic_cast<TFile *> (gROOT->GetListOfFiles()->FindObject(fullname.c_str()));
572 if (!f) f = TFile::Open(fullname.c_str());
573 if (!f) return nullptr;
574 return std::make_shared<TDirectoryElement>(fullname, f, true);
575 });
576
577 RegisterBrowse(TFile::Class(), [](std::unique_ptr<RHolder> &object) -> std::shared_ptr<RElement> {
578 return std::make_shared<TDirectoryElement>("", const_cast<TFile*>(object->Get<TFile>()), true);
579 });
580
581 RegisterBrowse(TDirectory::Class(), [](std::unique_ptr<RHolder> &object) -> std::shared_ptr<RElement> {
582 return std::make_shared<TDirectoryElement>("", const_cast<TDirectory*>(object->Get<TDirectory>()));
583 });
584 }
585
#define R__LOG_ERROR(...)
Definition RLogger.hxx:357
#define f(i)
Definition RSha256.hxx:104
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:53
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
RTFileProvider newRTFileProvider
char name[80]
Definition TGX11.cxx:110
#define gROOT
Definition TROOT.h:411
static bool IsLastKeyCycle()
Is only last cycle from the list of keys is shown.
Definition RElement.cxx:195
static EContentKind GetContentKind(const std::string &kind)
Find item with specified name Default implementation, should work for all.
Definition RElement.cxx:54
@ 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.
Access to TObject basic properties for RBrowsable.
virtual const TObject * CheckObject() const
Check if object still exists.
void ForgetObject() const
Forget object, use when it was deleted behind the scene.
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:2974
Element representing TDirectory.
~TDirectoryElement() override=default
bool cd() override
Select directory as active.
bool fIsFile
! is TFile instance registered in global list of files
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.
Iterator over keys in TDirectory.
TDirectoryLevelIter(TDirectory *dir)
std::shared_ptr< RElement > GetElement() override
Returns full information for current element.
~TDirectoryLevelIter() override=default
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
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
bool Next() override
Shift to next entry.
Describe directory structure in memory.
Definition TDirectory.h:45
static TClass * Class()
virtual TList * GetList() const
Definition TDirectory.h:223
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:221
virtual TList * GetListOfKeys() const
Definition TDirectory.h:224
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:131
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:3765
Element representing TKey from TDirectory.
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
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
~TKeyElement() override=default
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:1524
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:580
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:458
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:422
static TClass * Class()
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:502
virtual TClass * IsA() const
Definition TObject.h:246
@ kInvalidObject
if object ctor succeeded but object should not be used
Definition TObject.h:78
ROOT::RLogChannel & BrowsableLog()
Log channel for Browsable diagnostics.
Definition RElement.cxx:22