Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RBrowserData.cxx
Go to the documentation of this file.
1// Author: Sergey Linev <S.Linev@gsi.de>
2// Date: 2019-10-14
3// Warning: This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
4
5/*************************************************************************
6 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13#include <ROOT/RBrowserData.hxx>
14
21
22#include <ROOT/RLogger.hxx>
23
24#include "TFolder.h"
25#include "TROOT.h"
26#include "TBufferJSON.h"
27#include "TEnv.h"
28
29#include <algorithm>
30#include <regex>
31
32using namespace ROOT;
33using namespace std::string_literals;
34
36{
37 static ROOT::RLogChannel sLog("ROOT.Browser");
38 return sLog;
39}
40
41namespace ROOT {
42
44
46
47public:
49
50 void RecursiveRemove(TObject *obj) override
51 {
53 }
54};
55
56} // namespace ROOT
57
58
59/** \class ROOT::RBrowserData
60\ingroup rbrowser
61\brief Way to browse (hopefully) everything in %ROOT
62*/
63
64
65/////////////////////////////////////////////////////////////////////
66/// Default constructor
67
69{
70 fCleanupHandle = std::make_unique<RBrowserDataCleanup>(*this);
72 gROOT->GetListOfCleanups()->Add(fCleanupHandle.get());
73}
74
75/////////////////////////////////////////////////////////////////////
76/// Destructor
77
79{
80 // should be here because of fCleanupHandle destructor
82 gROOT->GetListOfCleanups()->Remove(fCleanupHandle.get());
83}
84
85/////////////////////////////////////////////////////////////////////
86/// set top element for browsing
87
88void RBrowserData::SetTopElement(std::shared_ptr<Browsable::RElement> elem)
89{
91
93}
94
95/////////////////////////////////////////////////////////////////////
96/// set working directory relative to top element
97
104
105/////////////////////////////////////////////////////////////////////
106/// Create default elements shown in the RBrowser
107
109{
110 auto comp = std::make_shared<Browsable::RGroup>("top","Root browser");
111
113
114 std::unique_ptr<Browsable::RHolder> rootfold = std::make_unique<Browsable::TObjectHolder>(gROOT->GetRootFolder(), kFALSE);
116 if (elem_root)
117 comp->Add(std::make_shared<Browsable::RWrapper>("root", elem_root));
118
119 std::unique_ptr<Browsable::RHolder> rootfiles = std::make_unique<Browsable::TObjectHolder>(gROOT->GetListOfFiles(), kFALSE);
121 if (elem_files) {
122 auto files = std::make_shared<Browsable::RWrapper>("ROOT Files", elem_files);
123 files->SetExpandByDefault(true);
124 comp->Add(files);
125 // if there are any open files, make them visible by default
126 if (elem_files->GetNumChilds() > 0)
127 seldir = {};
128 }
129
131
133}
134
135/////////////////////////////////////////////////////////////////////
136/// Reset all data correspondent to last request
137
139{
140 fLastAllChilds = false;
141 fLastSortedItems.clear();
142 fLastSortMethod.clear();
143 fLastItems.clear();
144 if (with_element) {
145 fLastPath.clear();
146 fLastElement.reset();
147 }
148}
149
150/////////////////////////////////////////////////////////////////////////
151/// Decompose path to elements
152/// Returns array of names for each element in the path, first element either "/" or "."
153/// If returned array empty - it is error
154
156{
159
160 if (strpath.empty())
161 return arr;
162
164 arr.insert(arr.end(), arr2.begin(), arr2.end());
165 return arr;
166}
167
168/////////////////////////////////////////////////////////////////////////
169/// Process browser request
170
172{
173 auto path = fWorkingPath;
174 path.insert(path.end(), request.path.begin(), request.path.end());
175
176 if ((path != fLastPath) || !fLastElement) {
177
178 auto elem = GetSubElement(path);
179 if (!elem) return false;
180
182
183 fLastPath = path;
184 fLastElement = std::move(elem);
185
186 fLastElement->cd(); // set element active
187 } else if (request.reload) {
188 // only reload items from element, not need to reset element itself
190 }
191
192 // when request childs, always try to make elements
193 if (fLastItems.empty()) {
194
195 auto iter = fLastElement->GetChildsIter();
196
197 if (!iter) return false;
198 int id = 0;
199 fLastAllChilds = true;
200
201 while (iter->Next() && fLastAllChilds) {
202 fLastItems.emplace_back(iter->CreateItem());
203 if (id++ > 10000)
204 fLastAllChilds = false;
205 }
206
207 fLastSortedItems.clear();
208 fLastSortMethod.clear();
209 }
210
211 // create sorted array
212 if ((fLastSortedItems.size() != fLastItems.size()) ||
213 (fLastSortMethod != request.sort) ||
214 (fLastSortReverse != request.reverse)) {
215 fLastSortedItems.resize(fLastItems.size(), nullptr);
216 int id = 0;
217 if (request.sort.empty() || (request.sort == "none")) {
218 // no sorting, just move all folders up
219 for (auto &item : fLastItems)
220 if (item->IsFolder())
221 fLastSortedItems[id++] = item.get();
222 for (auto &item : fLastItems)
223 if (!item->IsFolder())
224 fLastSortedItems[id++] = item.get();
225 } else {
226 // copy items
227 for (auto &item : fLastItems)
228 fLastSortedItems[id++] = item.get();
229
230 if (request.sort != "unsorted")
231 std::sort(fLastSortedItems.begin(), fLastSortedItems.end(),
232 [request](const Browsable::RItem *a, const Browsable::RItem *b) { return a ? a->Compare(b, request.sort) : !b; });
233 }
234
235 if (request.reverse)
236 std::reverse(fLastSortedItems.begin(), fLastSortedItems.end());
237
238 fLastSortMethod = request.sort;
239 fLastSortReverse = request.reverse;
240 }
241
242 const std::regex expr(request.regex);
243
244 int id = 0;
245 for (auto &item : fLastSortedItems) {
246
247 // check if element is hidden
248 if (!request.hidden && item->IsHidden())
249 continue;
250
251 if (!request.regex.empty() && !item->IsFolder() && !std::regex_match(item->GetName(), expr))
252 continue;
253
254 if ((id >= request.first) && ((request.number == 0) || (id < request.first + request.number)))
255 reply.nodes.emplace_back(item);
256
257 id++;
258 }
259
260 reply.first = request.first;
261 reply.nchilds = id; // total number of childs
262
263 return true;
264}
265
266/////////////////////////////////////////////////////////////////////////
267/// Process browser request, returns string with JSON of RBrowserReply data
268
270{
272
273 reply.path = request.path;
274 reply.first = 0;
275 reply.nchilds = 0;
276
278
280}
281
282/////////////////////////////////////////////////////////////////////////
283/// Returns element with path, specified as string
284
285std::shared_ptr<Browsable::RElement> RBrowserData::GetElement(const std::string &str)
286{
287 auto path = DecomposePath(str, true);
288
289 return GetSubElement(path);
290}
291
292/////////////////////////////////////////////////////////////////////////
293/// Returns element with path, specified as Browsable::RElementPath_t
294
295std::shared_ptr<Browsable::RElement> RBrowserData::GetElementFromTop(const Browsable::RElementPath_t &path)
296{
297 return GetSubElement(path);
298}
299
300/////////////////////////////////////////////////////////////////////////
301/// Returns sub-element starting from top, using cached data
302
303std::shared_ptr<Browsable::RElement> RBrowserData::GetSubElement(const Browsable::RElementPath_t &path)
304{
305 if (path.empty())
306 return fTopElement;
307
308 // validate cache - removes no longer actual elements
309 RemoveFromCache(nullptr);
310
311 // first check direct match in cache
312 for (auto &entry : fCache)
313 if (entry.first == path)
314 return entry.second;
315
316 // find best possible entry in cache
317 int pos = 0;
318 auto elem = fTopElement;
319
320 for (auto &entry : fCache) {
321 if (entry.first.size() >= path.size())
322 continue;
323
324 auto comp = Browsable::RElement::ComparePaths(path, entry.first);
325
326 if ((comp > pos) && (comp == (int) entry.first.size())) {
327 pos = comp;
328 elem = entry.second;
329 }
330 }
331
332 while (pos < (int) path.size()) {
333 std::string subname = path[pos];
335
336 auto iter = elem->GetChildsIter();
337 if (!iter)
338 return nullptr;
339
340 if (!iter->Find(subname, indx)) {
341 if (indx < 0)
342 return nullptr;
343 iter = elem->GetChildsIter();
344 if (!iter || !iter->Find(subname))
345 return nullptr;
346 }
347
348 elem = iter->GetElement();
349
350 if (!elem)
351 return nullptr;
352
353 auto subpath = path;
354 subpath.resize(pos+1);
355 fCache.emplace_back(subpath, elem);
356 pos++; // switch to next element
357 }
358
359 return elem;
360}
361
362/////////////////////////////////////////////////////////////////////////
363/// Clear internal objects cache
364
366{
367 fCache.clear();
368}
369
370/////////////////////////////////////////////////////////////////////////
371/// Remove object from cache
372/// If nullptr specified - removes no-longer-valid elements
373/// Returns true if any element was removed
374
376{
377 unsigned pos = 0;
378
379 bool isany = false;
380
381 while (pos < fCache.size()) {
382 if (obj ? !fCache[pos].second->IsObject(obj) : fCache[pos].second->CheckValid()) {
383 pos++;
384 continue;
385 }
386
387 isany = true;
388 auto path = fCache[pos].first;
389 fCache.erase(fCache.begin() + pos);
390 if (RemoveFromCache(path))
391 pos = 0; // start scan from the beginning
392 }
393
394 return isany;
395}
396
397/////////////////////////////////////////////////////////////////////////
398/// Remove path (and all sub-paths) from cache
399/// Returns true if any element was removed
400
402{
403 if (path.size() == 0)
404 return false;
405
406 bool isany = false;
407 unsigned pos = 0;
408 while (pos < fCache.size()) {
409 if (Browsable::RElement::ComparePaths(path, fCache[pos].first) == (int) path.size()) {
410 fCache.erase(fCache.begin() + pos);
411 isany = true;
412 } else {
413 pos++;
414 }
415 }
416 return isany;
417}
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:411
#define R__LOCKGUARD(mutex)
static int ExtractItemIndex(std::string &name)
Extract index from name Index coded by client with ###<indx>$$$ suffix Such coding used by browser to...
Definition RElement.cxx:180
static int ComparePaths(const RElementPath_t &path1, const RElementPath_t &path2)
Compare two paths, Returns number of elements matches in both paths.
Definition RElement.cxx:147
static RElementPath_t ParsePath(const std::string &str)
Parse string path to produce RElementPath_t One should avoid to use string pathes as much as possible...
Definition RElement.cxx:118
Representation of single item in the browser.
Definition RItem.hxx:23
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 RElementPath_t ProvideTopEntries(std::shared_ptr< RGroup > &comp, const std::string &workdir="")
Provide top entries for file system On windows it is list of existing drivers, on Linux it is "File s...
Definition RSysFile.cxx:510
RBrowserDataCleanup(RBrowserData &_data)
void RecursiveRemove(TObject *obj) override
Recursively remove this object from a list.
Way to browse (hopefully) everything in ROOT.
void SetTopElement(std::shared_ptr< Browsable::RElement > elem)
set top element for browsing
std::vector< const Browsable::RItem * > fLastSortedItems
! sorted child items, used in requests
Browsable::RElementPath_t fWorkingPath
! path showed in Breadcrumb
bool RemoveFromCache(void *obj)
Remove object from cache If nullptr specified - removes no-longer-valid elements Returns true if any ...
std::shared_ptr< Browsable::RElement > GetSubElement(const Browsable::RElementPath_t &path)
Returns sub-element starting from top, using cached data.
std::vector< std::pair< Browsable::RElementPath_t, std::shared_ptr< Browsable::RElement > > > fCache
! already requested elements
Browsable::RElementPath_t DecomposePath(const std::string &path, bool relative_to_work_element)
Decompose path to elements Returns array of names for each element in the path, first element either ...
bool fLastAllChilds
! if all chlds were extracted
virtual ~RBrowserData()
Destructor.
bool ProcessBrowserRequest(const RBrowserRequest &request, RBrowserReply &reply)
Process browser request.
std::shared_ptr< Browsable::RElement > GetElementFromTop(const Browsable::RElementPath_t &path)
Returns element with path, specified as Browsable::RElementPath_t.
std::string fLastSortMethod
! last sort method
void ClearCache()
Clear internal objects cache.
std::string ProcessRequest(const RBrowserRequest &request)
Process browser request, returns string with JSON of RBrowserReply data.
std::vector< std::unique_ptr< Browsable::RItem > > fLastItems
! created browser items - used in requests
std::unique_ptr< RBrowserDataCleanup > fCleanupHandle
! cleanup handle for RecursiveRemove
Browsable::RElementPath_t fLastPath
! path to last used element
void SetWorkingPath(const Browsable::RElementPath_t &path)
set working directory relative to top element
std::shared_ptr< Browsable::RElement > fTopElement
! top element
std::shared_ptr< Browsable::RElement > GetElement(const std::string &str)
Returns element with path, specified as string.
bool fLastSortReverse
! last request reverse order
void ResetLastRequestData(bool with_element)
Reset all data correspondent to last request.
std::shared_ptr< Browsable::RElement > fLastElement
! last element used in request
void CreateDefaultElements()
Create default elements shown in the RBrowser.
RBrowserData()
Default constructor.
Reply on browser request.
Request send from client to get content of path element.
bool hidden
show hidden files
int number
number of childs to request, 0 - all childs
bool reverse
reverse item order
std::string sort
kind of sorting
std::vector< std::string > path
requested path
bool reload
force items reload
int first
first child to request
std::string regex
applied regex
A log configuration for a channel, e.g.
Definition RLogger.hxx:98
const_iterator begin() const
const_iterator end() const
static TString ToJSON(const T *obj, Int_t compact=0, const char *member_name=nullptr)
Definition TBufferJSON.h:75
@ kSkipTypeInfo
do not store typenames in JSON
Definition TBufferJSON.h:48
@ kNoSpaces
no new lines plus remove all spaces around "," and ":" symbols
Definition TBufferJSON.h:39
Mother of all ROOT objects.
Definition TObject.h:41
std::vector< std::string > RElementPath_t
Definition RElement.hxx:20
Namespace for new ROOT classes and functions.
ROOT::RLogChannel & BrowserLog()
Log channel for Browser diagnostics.