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::Experimental::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) {
92 break;
93 fObj = fIter->Next();
94 }
95 if (!fObj) {
96 fIter.reset();
97 return false;
98 }
99
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
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::Experimental::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)
170
171 if (fKeysIter && fKey) {
173 return true;
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 {
219 return nullptr;
220
221 if (fIsFile && !gROOT->GetListOfFiles()->FindObject(fObj))
222 ForgetObject();
223 else if (!gROOT->GetListOfFiles()->FindObject(((TDirectory *) fObj)->GetFile()))
224 ForgetObject();
225
226 return fObj;
227 }
228
230 {
231 if (!CheckObject() && fIsFile && fFileName.empty())
232 (const_cast<TDirectoryElement *>(this))->SetObject(TFile::Open(fFileName.c_str()));
233
234 return dynamic_cast<TDirectory *>(fObj);
235 }
236
237 TFile *GetFile() const
238 {
239 if (!fIsFile)
240 return nullptr;
241
242 return dynamic_cast<TFile *>(GetDir());
243 }
244
245
246public:
247
248 TDirectoryElement(const std::string &fname, TDirectory *dir = nullptr, bool isfile = false) : TObjectElement(dir)
249 {
250 fFileName = fname;
251 fIsFile = isfile;
252 if (fIsFile && fObj && !gROOT->GetListOfFiles()->FindObject(fObj)) {
253 fIsFile = false;
254 ForgetObject();
255 }
256 }
257
258 virtual ~TDirectoryElement() = default;
259
260 /** Name of TDirectoryElement */
261 std::string GetName() const override
262 {
263 if (CheckObject())
264 return fObj->GetName();
265
266 if (!fFileName.empty()) {
267 auto pos = fFileName.rfind("/");
268 return ((pos == std::string::npos) || (pos > fFileName.length() - 2)) ? fFileName : fFileName.substr(pos + 1);
269 }
270
271 return ""s;
272 }
273
274 /** Title of TDirectoryElement */
275 std::string GetTitle() const override
276 {
277 if (CheckObject())
278 return fObj->GetTitle();
279
280 return "ROOT file "s + fFileName;
281 }
282
283 bool IsFolder() const override { return true; }
284
285 /** Provide iterator over TDirectory */
286 std::unique_ptr<RLevelIter> GetChildsIter() override
287 {
288 auto dir = GetDir();
289
290 return dir ? std::make_unique<TDirectoryLevelIter>(dir) : nullptr;
291 }
292
293 /** Get default action - browsing for the TFile/TDirectory */
294 EActionKind GetDefaultAction() const override { return kActBrowse; }
295
296 /** Select directory as active */
297 bool cd() override
298 {
299 auto dir = GetDir();
300 if (dir) {
301 dir->cd();
302 return true;
303 }
304 return false;
305 }
306
307 /** Size of TDirectory */
308 Long64_t GetSize() const override
309 {
310 auto f = GetFile();
311 if (f) return f->GetSize();
312 return -1;
313 }
314
315 std::string GetMTime() const override
316 {
317 auto f = GetFile();
318 if (f) return f->GetModificationDate().AsSQLString();
319 return ""s;
320 }
321
322 std::string GetContent(const std::string &kind) override
323 {
324 if (GetContentKind(kind) == kFileName)
325 return fFileName;
326
327 return ""s;
328 }
329
330};
331
332// ===============================================================================================================
333
334
335/** \class TKeyElement
336\ingroup rbrowser
337
338Element representing TKey from TDirectory
339*/
340
345 std::shared_ptr<RElement> fElement; ///<! holder of read object
346
347 std::string GetMTime() const override { return fKeyMTime; }
348
349 Long64_t GetSize() const override { return fKeyObjSize; }
350
351public:
352 TKeyElement(TDirectory *dir, TKey *key) : TDirectoryElement("", dir, false)
353 {
354 fKeyName = key->GetName();
355 fKeyTitle = key->GetTitle();
356 fKeyCycle = key->GetCycle();
357 fKeyClass = key->GetClassName();
359 fKeyObjSize = key->GetNbytes();
360 }
361
362 virtual ~TKeyElement() = default;
363
364 /** Name of TKeyElement, includes key cycle */
365 std::string GetName() const override
366 {
367 if (fElement)
368 return fElement->GetName();
369
370 std::string name = fKeyName;
371 name.append(";");
372 name.append(std::to_string(fKeyCycle));
373
374 return name;
375 }
376
377 /** Title of TKeyElement (optional) */
378 std::string GetTitle() const override
379 {
380 if (fElement)
381 return fElement->GetTitle();
382
383 return fKeyTitle;
384 }
385
386 /** Create iterator for childs elements if any
387 * Means we should try to browse inside.
388 * Either it is directory or some complex object */
389 std::unique_ptr<RLevelIter> GetChildsIter() override
390 {
391 if (fElement)
392 return fElement->GetChildsIter();
393
394 if (fKeyClass.find("TDirectory") == 0) {
395 auto dir = GetDir();
396 if (!dir) return nullptr;
397
398 auto subdir = dir->GetDirectory(fKeyName.c_str());
399 if (!subdir)
400 subdir = dir->GetDirectory(GetName().c_str());
401 if (!subdir) return nullptr;
402 return std::make_unique<TDirectoryLevelIter>(subdir);
403 }
404
405 auto obj = GetObject();
406
407 if (obj)
409
410 if (fElement)
411 return fElement->GetChildsIter();
412
413 return nullptr;
414 }
415
416 /** Return object associated with the TKey */
417 std::unique_ptr<RHolder> GetObject() override
418 {
419 if (fElement)
420 return fElement->GetObject();
421
422 auto obj_class = TClass::GetClass(fKeyClass.c_str());
423 if (!obj_class)
424 return nullptr;
425
426 if (!obj_class->HasDictionary()) {
427 R__LOG_ERROR(ROOT::Experimental::BrowsableLog()) << "Class " << fKeyClass << " does not have dictionary, object " << fKeyName << " cannot be read";
428 return nullptr;
429 }
430 auto dir = GetDir();
431 if (!dir)
432 return nullptr;
433
434 std::string namecycle = fKeyName + ";"s + std::to_string(fKeyCycle);
435
436 void *obj = dir->GetObjectChecked(namecycle.c_str(), obj_class);
437
438 if (!obj)
439 return nullptr;
440
441 TObject *tobj = (TObject *) obj_class->DynamicCast(TObject::Class(), obj);
442
443 if (tobj) {
444 bool in_dir = dir->FindObject(tobj) != nullptr,
445 special_class = (fKeyClass == "TGeoManager"s) || (fKeyClass == "TTree"s) || (fKeyClass == "TNtuple"s);
446
447 if (in_dir && !special_class)
448 dir->Remove(tobj);
449
450 return std::make_unique<TObjectHolder>(tobj, !special_class);
451 }
452
453 return std::make_unique<RAnyObjectHolder>(obj_class, obj, true);
454 }
455
457 {
458 if (fElement)
459 return fElement->GetDefaultAction();
460
461 if (fKeyClass.empty()) return kActNone;
462 if ((fKeyClass == "TCanvas"s) || (fKeyClass == "ROOT::Experimental::RCanvas"s)) return kActCanvas;
463 if ((fKeyClass == "TTree"s) || (fKeyClass == "TNtuple"s)) return kActTree;
464 if (fKeyClass == "TGeoManager"s) return kActGeom;
468 return kActNone;
469 }
470
471 bool IsFolder() const override
472 {
473 if (fElement)
474 return fElement->IsFolder();
475
476 if (!fKeyClass.empty()) {
478 return true;
479 auto cl = TClass::GetClass(fKeyClass.c_str(), kFALSE, kTRUE);
480 return RProvider::CanHaveChilds(cl);
481 }
482
483 return false;
484 }
485
486 bool IsCapable(EActionKind action) const override
487 {
488 if (fElement)
489 return fElement->IsCapable(action);
490
491 if (fKeyClass.empty()) return false;
492
493 switch(action) {
494 case kActBrowse: {
496 return true;
498 }
499 case kActEdit: return true;
500 case kActImage:
501 case kActDraw6: {
502 // if can draw in TCanvas, can produce image
504 return true;
506 }
507 case kActDraw7: {
509 return true;
511 }
512 case kActCanvas: return (fKeyClass == "TCanvas"s) || (fKeyClass == "ROOT::Experimental::RCanvas"s);
513 case kActTree: return (fKeyClass == "TTree"s) || (fKeyClass == "TNtuple"s);
514 case kActGeom: return (fKeyClass == "TGeoManager"s);
515 default: return false;
516 }
517
518 return false;
519 }
520
521 std::unique_ptr<RItem> CreateItem() const override
522 {
523 if (fElement)
524 return fElement->CreateItem();
525
526 bool is_folder = IsFolder();
527
528 auto item = std::make_unique<TObjectItem>(GetName(), is_folder ? -1 : 0);
529 item->SetTitle(fKeyTitle);
530 item->SetClassName(fKeyClass);
531 item->SetIcon(RProvider::GetClassIcon(fKeyClass, is_folder));
532 item->SetSize(fKeyObjSize);
533 item->SetMTime(fKeyMTime);
534
535 return item;
536 }
537
538};
539
540// ==============================================================================================
541
542/////////////////////////////////////////////////////////////////////////////////
543/// Return element for current TKey object in TDirectory
544
545std::shared_ptr<RElement> TDirectoryLevelIter::GetDirElement(bool read_dir)
546{
547 if (!fKeysIter && fObj)
548 return std::make_shared<TObjectElement>(fObj);
549
550 if ("ROOT::Experimental::RNTuple"s == fKey->GetClassName())
552
553 std::string key_class = fKey->GetClassName();
554 if (read_dir && (key_class.find("TDirectory") == 0)) {
555 auto subdir = fDir->GetDirectory(fKey->GetName());
556 if (subdir) return std::make_shared<TDirectoryElement>("", subdir);
557 }
558
559 return std::make_shared<TKeyElement>(fDir, fKey);
560}
561
562// ==============================================================================================
563
564
565/** \class RTFileProvider
566\ingroup rbrowser
567
568Provides access to ROOT files with extension "root"
569Other extensions can be registered
570*/
571
572class RTFileProvider : public RProvider {
573
574public:
576 {
577 RegisterFile("root", [] (const std::string &fullname) -> std::shared_ptr<RElement> {
578 auto f = dynamic_cast<TFile *> (gROOT->GetListOfFiles()->FindObject(fullname.c_str()));
579 if (!f) f = TFile::Open(fullname.c_str());
580 if (!f) return nullptr;
581 return std::make_shared<TDirectoryElement>(fullname, f, true);
582 });
583
584 RegisterBrowse(TFile::Class(), [](std::unique_ptr<RHolder> &object) -> std::shared_ptr<RElement> {
585 return std::make_shared<TDirectoryElement>("", const_cast<TFile*>(object->Get<TFile>()), true);
586 });
587
588 RegisterBrowse(TDirectory::Class(), [](std::unique_ptr<RHolder> &object) -> std::shared_ptr<RElement> {
589 return std::make_shared<TDirectoryElement>("", const_cast<TDirectory*>(object->Get<TDirectory>()));
590 });
591 }
592
#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
long long Long64_t
Definition RtypesCore.h:80
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:405
@ kFileName
"filename" - file name if applicable
Definition RElement.hxx:45
static EContentKind GetContentKind(const std::string &kind)
Find item with specified name Default implementation, should work for all.
Definition RElement.cxx:51
EActionKind
Possible actions on double-click.
Definition RElement.hxx:51
@ kActEdit
can provide data for text editor
Definition RElement.hxx:54
@ kActCanvas
indicate that it is canvas and should be drawn directly
Definition RElement.hxx:58
@ kActBrowse
just browse (expand) item
Definition RElement.hxx:53
@ kActGeom
can be shown in geometry viewer
Definition RElement.hxx:60
@ kActDraw7
can be drawn inside ROOT7 canvas
Definition RElement.hxx:57
@ kActTree
can be shown in tree viewer
Definition RElement.hxx:59
@ kActImage
can be shown in image viewer, can provide image
Definition RElement.hxx:55
@ kActDraw6
can be drawn inside ROOT6 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: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.
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:2968
const char * AsSQLString() const
Return the date & time in SQL compatible string format, like: 1997-01-15 20:16:28.
Definition TDatime.cxx:152
Element representing TDirectory.
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.
Iterator over keys in TDirectory.
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()
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
virtual TList * GetListOfKeys() const
Definition TDirectory.h:223
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:51
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:4053
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
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:1532
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:577
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:578
TIterator * MakeIterator(Bool_t dir=kIterForward) const override
Return a list iterator.
Definition TList.cxx:722
const char * GetName() const override
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:439
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:403
static TClass * Class()
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:483
virtual TClass * IsA() const
Definition TObject.h:245
RLogChannel & BrowsableLog()
Log channel for Browsable diagnostics.
Definition RElement.cxx:20