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
99 fCurrentName = fObj->GetName();
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
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 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)
155 return RProvider::CanHaveChilds(fObj->IsA());
156
157 if (fKeysIter && fKey) {
158 if (RProvider::CanHaveChilds(fKey->GetClassName()))
159 return true;
160 auto cl = TClass::GetClass(fKey->GetClassName(), kFALSE, kTRUE);
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
172 auto elem = RProvider::Browse(holder);
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 {
243 fFileName = fname;
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:
345 TKeyElement(TDirectory *dir, TKey *key) : TDirectoryElement("", dir, false)
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);
524 item->SetIcon(RProvider::GetClassIcon(fKeyClass, is_folder));
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:356
#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
RTFileProvider newRTFileProvider
char name[80]
Definition TGX11.cxx:148
#define gROOT
Definition TROOT.h:417
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.
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:2994
~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.
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()
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Definition TFile.h:130
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:3787
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:1536
Int_t GetNbytes() const
Definition TKey.h:88
virtual const char * GetClassName() const
Definition TKey.h:77
const TDatime & GetDatime() const
Definition TKey.h:83
Short_t GetCycle() const
Return cycle number associated to this key.
Definition TKey.cxx:611
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Mother of all ROOT objects.
Definition TObject.h:42
static TClass * Class()
@ kInvalidObject
if object ctor succeeded but object should not be used
Definition TObject.h:81
ROOT::RLogChannel & BrowsableLog()
Log channel for Browsable diagnostics.
Definition RElement.cxx:22