44using namespace std::string_literals;
79 bool DrawElement(std::shared_ptr<Browsable::RElement> &elem,
const std::string & =
"")
override
82 auto code = elem->GetContent(
"text");
89 auto json = elem->GetContent(
"json");
93 fTitle = elem->GetName() +
".json";
104 auto img = elem->GetContent(
"image64");
109 fFileName = elem->GetContent(
"filename");
126 std::string msg =
fIsEditor ?
"EDITOR:"s :
"IMAGE:"s;
153 std::string
GetKind()
const override {
return "info"s; }
156 bool DrawElement(std::shared_ptr<Browsable::RElement> &,
const std::string & =
"")
override {
return false; }
163 std::ostringstream pathtmp;
166 std::ofstream ofs(pathtmp.str(), std::ofstream::out | std::ofstream::app);
171 gROOT->ProcessLine(
".g");
174 std::ifstream infile(pathtmp.str());
188 int indx = 0, last_prompt = -1;
189 for (
auto &
line : logs) {
195 if (last_prompt < 0) {
204 for (
auto &
line : logs) {
236 std::string
GetKind()
const override {
return "catched"s; }
287 if (
gROOT->IsWebDisplayBatch()) {
288 ::Warning(
"RBrowser::RBrowser",
"The RBrowser cannot run in web batch mode");
292 std::ostringstream pathtmp;
300 fTimer = std::make_unique<RBrowserTimer>(10,
kTRUE, *
this);
306 fWebWindow->SetDefaultPage(
"file:rootui5sys/browser/browser.html");
308 std::string sortby =
gEnv->
GetValue(
"WebGui.Browser.SortBy",
"name"),
309 reverse =
gEnv->
GetValue(
"WebGui.Browser.Reverse",
"no"),
310 hidden =
gEnv->
GetValue(
"WebGui.Browser.ShowHidden",
"no"),
311 lastcycle =
gEnv->
GetValue(
"WebGui.Browser.LastCycle",
"");
313 if (sortby !=
"name" && sortby !=
"size" && sortby !=
"none")
316 reverse = (reverse ==
"on" || reverse ==
"yes" || reverse ==
"1") ?
"true" :
"false";
317 hidden = (hidden ==
"on" || hidden ==
"yes" || hidden ==
"1") ?
"true" :
"false";
318 if (lastcycle ==
"on" || lastcycle ==
"yes" || lastcycle ==
"1")
320 else if (lastcycle ==
"off" || lastcycle ==
"no" || lastcycle ==
"0")
323 fWebWindow->SetUserArgs(
TString::Format(
"{ sort: \"%s\", reverse: %s, hidden: %s }", sortby.c_str(), reverse.c_str(), hidden.c_str()).
Data());
327 [
this](
unsigned connid,
const std::string &arg) {
ProcessMsg(connid, arg); });
353 widget->fBrowser =
this;
363 return widget ? true :
false;
369 if (catched && (catched->fWindow == &
win))
386 fWebWindow->GetManager()->SetShowCallback(
nullptr);
387 fWebWindow->GetManager()->SetDeleteCallback(
nullptr);
397 std::unique_ptr<RBrowserRequest> request;
400 request = std::make_unique<RBrowserRequest>();
402 request->number = 100;
404 request = TBufferJSON::FromJSON<RBrowserRequest>(msg);
421 if (fname.empty())
return;
423 std::ofstream
f(fname);
432 if (file_path.rfind(
".py") == file_path.length() - 3) {
434 exec.
Form(
"TPython::ExecScript(\"%s\");", file_path.c_str());
448 std::string opt = args.back();
452 path.insert(path.end(), args.begin(), args.end());
457 if (!elem)
return ""s;
459 auto dflt_action = elem->GetDefaultAction();
463 std::string widget_kind;
466 widget_kind =
"rcanvas";
468 widget_kind =
"tcanvas";
478 new_widget->fBrowser =
this;
487 elem->GetChildsIter();
492 SendProgress(connid, progress);
496 if (widget && widget->DrawElement(elem, opt)) {
497 widget->SetPath(path);
498 return widget->SendWidgetContent();
503 [path](
const std::shared_ptr<RBrowserWidget> &wg) { return path == wg->GetPath(); });
506 return "SELECT_WIDGET:"s + (*iter)->GetName();
512 std::string widget_kind;
513 switch(dflt_action) {
520 default: widget_kind.clear();
523 if (!widget_kind.empty()) {
524 auto new_widget =
AddWidget(widget_kind);
528 if (new_widget->DrawElement(elem, opt))
529 new_widget->SetPath(path);
536 for (
auto &pathelem : path)
551 path.insert(path.end(), args.begin(), args.end());
556 if (!elem)
return ""s;
560 SendProgress(connid, progress);
564 if (widget && widget->DrawElement(elem,
"<append>")) {
565 widget->SetPath(path);
566 return widget->SendWidgetContent();
581 if (!
fWebWindow->NumConnections() || always_start_new_browser) {
624 std::shared_ptr<RBrowserWidget> widget;
626 if (kind ==
"editor"s)
627 widget = std::make_shared<RBrowserEditorWidget>(
name,
true);
628 else if (kind ==
"image"s)
629 widget = std::make_shared<RBrowserEditorWidget>(
name,
false);
630 else if (kind ==
"info"s)
631 widget = std::make_shared<RBrowserInfoWidget>(
name);
640 widget->fBrowser =
this;
652 if (!
win || kind.empty())
657 auto widget = std::make_shared<RBrowserCatchedWidget>(
name,
win, kind);
683 [
name, kind](
const std::shared_ptr<RBrowserWidget> &widget) {
684 return kind.empty() ? name == widget->GetName() : kind == widget->GetKind();
698 auto iter = std::find_if(
fWidgets.begin(),
fWidgets.end(), [
name](std::shared_ptr<RBrowserWidget> &widget) { return name == widget->GetName(); });
711 std::vector<std::string> arr;
714 path +=
"/.root_hist" ;
715 std::ifstream infile(path);
719 while (std::getline(infile,
line) && (arr.size() < 1000)) {
720 if(!(std::find(arr.begin(), arr.end(),
line) != arr.end())) {
721 arr.emplace_back(
line);
734 std::vector<std::string> arr;
739 while (std::getline(infile,
line) && (arr.size() < 10000)) {
740 arr.emplace_back(
line);
752 std::vector<std::vector<std::string>> reply;
758 reply.emplace_back(std::vector<std::string>({ widget->GetKind(), widget->GetUrl(), widget->GetName(), widget->GetTitle() }));
762 reply.emplace_back(std::vector<std::string>({
"active"s, fActiveWidgetName }));
765 if (history.size() > 0) {
766 history.insert(history.begin(),
"history"s);
767 reply.emplace_back(history);
771 if (logs.size() > 0) {
772 logs.insert(logs.begin(),
"logs"s);
773 reply.emplace_back(logs);
776 reply.emplace_back(std::vector<std::string>({
783 reply.emplace_back(std::vector<std::string>({
789 std::string msg =
"INMSG:";
807 fWebWindow->Send(connid,
"PROGRESS:"s + std::to_string(progr));
828 std::vector<std::string> arr = { widget->GetKind(), widget->GetUrl(), widget->GetName(), widget->GetTitle(),
838 std::vector<std::string> del_names;
841 if (!widget->IsValid())
842 del_names.push_back(widget->GetName());
844 if (!del_names.empty())
847 for (
auto name : del_names)
851 widget->CheckModified();
869 unsigned connid = std::stoul(arr.back()); arr.pop_back();
870 std::string kind = arr.back(); arr.pop_back();
872 if (kind ==
"DBLCLK") {
874 if (reply.empty()) reply =
"NOPE";
875 }
else if (kind ==
"DROP") {
877 if (reply.empty()) reply =
"NOPE";
890 R__LOG_DEBUG(0,
BrowserLog()) <<
"ProcessMsg len " << arg0.length() <<
" substr(30) " << arg0.substr(0, 30);
892 std::string kind, msg;
893 auto pos = arg0.find(
":");
894 if (pos == std::string::npos) {
897 kind = arg0.substr(0, pos);
898 msg = arg0.substr(pos+1);
901 if (kind ==
"QUIT_ROOT") {
905 }
else if (kind ==
"BRREQ") {
910 }
else if (kind ==
"LASTCYCLE") {
914 }
else if (kind ==
"DBLCLK") {
916 auto arr = TBufferJSON::FromJSON<std::vector<std::string>>(msg);
917 if (arr && (arr->size() > 2)) {
918 arr->push_back(kind);
919 arr->push_back(std::to_string(connid));
927 }
else if (kind ==
"DROP") {
929 auto arr = TBufferJSON::FromJSON<std::vector<std::string>>(msg);
930 if (arr && arr->size()) {
931 arr->push_back(kind);
932 arr->push_back(std::to_string(connid));
940 }
else if (kind ==
"WIDGET_SELECTED") {
944 auto reply = widget->SendWidgetContent();
945 if (!reply.empty())
fWebWindow->Send(connid, reply);
947 }
else if (kind ==
"CLOSE_TAB") {
949 }
else if (kind ==
"GETWORKPATH") {
951 }
else if (kind ==
"CHPATH") {
952 auto path = TBufferJSON::FromJSON<Browsable::RElementPath_t>(msg);
955 }
else if (kind ==
"CMD") {
956 std::string sPrompt =
"root []";
959 sPrompt = ((
TRint*)
gROOT->GetApplication())->GetPrompt();
960 Gl_histadd((
char *)msg.c_str());
964 ofs << sPrompt << msg << std::endl;
968 gROOT->ProcessLine(msg.c_str());
972 auto widget = std::dynamic_pointer_cast<RBrowserInfoWidget>(
FindWidget(
""s,
"info"s));
976 widget = std::dynamic_pointer_cast<RBrowserInfoWidget>(new_widget);
978 fWebWindow->Send(connid,
"SELECT_WIDGET:"s + widget->GetName());
983 widget->RefreshFromLogs(sPrompt + msg,
GetRootLogs());
987 }
else if (kind ==
"GETHISTORY") {
992 }
else if (kind ==
"GETLOGS") {
1001 }
else if (kind ==
"SYNCEDITOR") {
1002 auto arr = TBufferJSON::FromJSON<std::vector<std::string>>(msg);
1003 if (arr && (arr->size() > 4)) {
1004 auto editor = std::dynamic_pointer_cast<RBrowserEditorWidget>(
FindWidget(arr->at(0)));
1006 editor->fFirstSend =
true;
1007 editor->fTitle = arr->at(1);
1008 editor->fFileName = arr->at(2);
1009 if (!arr->at(3).empty()) editor->fContent = arr->at(4);
1010 if ((arr->size() == 6) && (arr->at(5) ==
"SAVE"))
1012 if ((arr->size() == 6) && (arr->at(5) ==
"RUN")) {
1019 }
else if (kind ==
"GETINFO") {
1020 auto info = std::dynamic_pointer_cast<RBrowserInfoWidget>(
FindWidget(msg));
1023 fWebWindow->Send(connid, info->SendWidgetContent());
1025 }
else if (kind ==
"NEWWIDGET") {
1029 }
else if (kind ==
"NEWCHANNEL") {
1030 auto arr = TBufferJSON::FromJSON<std::vector<std::string>>(msg);
1031 if (arr && (arr->size() == 2)) {
1036 }
else if (kind ==
"CDWORKDIR") {
1044 }
else if (kind ==
"OPTIONS") {
1045 auto arr = TBufferJSON::FromJSON<std::vector<std::string>>(msg);
1046 if (arr && (arr->size() == 3)) {
1079 if (widget->GetTitle() != title)
1082 if (!kind.empty() && (widget->GetKind() != kind))
1086 fWebWindow->Send(0,
"SELECT_WIDGET:"s + widget->GetName());
#define R__LOG_ERROR(...)
#define R__LOG_DEBUG(DEBUGLEVEL,...)
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t win
Option_t Option_t TPoint TPoint const char mode
R__EXTERN TSystem * gSystem
static bool IsLastKeyCycle()
Is only last cycle from the list of keys is shown.
static void SetLastKeyCycle(bool on=true)
Set flag to show only last cycle from the list of keys.
static int ExtractItemIndex(std::string &name)
Extract index from name Index coded by client with ###<indx>$$$ suffix Such coding used by browser to...
@ kActImage
can be shown in image viewer, can provide image
@ kActDraw6
can be drawn inside ROOT6 canvas
@ kActCanvas
indicate that it is canvas and should be drawn directly
@ kActTree
can be shown in tree viewer
@ kActGeom
can be shown in geometry viewer
@ kActBrowse
just browse (expand) item
@ kActEdit
can provide data for text editor
@ kActDraw7
can be drawn inside ROOT7 canvas
static std::string GetPathAsString(const RElementPath_t &path)
Converts element path back to string.
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...
static bool SetClassDrawOption(const ClassArg &, const std::string &)
Set draw option for the class Return true if entry for the class exists.
static std::string GetClassDrawOption(const ClassArg &)
Return configured draw option for the class.
static RElementPath_t GetWorkingPath(const std::string &workdir="")
Return working path in browser hierarchy.
std::shared_ptr< Browsable::RElement > GetSubElement(const Browsable::RElementPath_t &path)
Returns sub-element starting from top, using cached data.
void ClearCache()
Clear internal objects cache.
std::string ProcessRequest(const RBrowserRequest &request)
Process browser request, returns string with JSON of RBrowserReply data.
void SetWorkingPath(const Browsable::RElementPath_t &path)
set working directory relative to top element
const Browsable::RElementPath_t & GetWorkingPath() const
void CreateDefaultElements()
Create default elements shown in the RBrowser.
RBrowserTimer(Long_t milliSec, Bool_t mode, RBrowser &br)
!< browser processing postponed requests
void Timeout() override
timeout handler used to process postponed requests in main ROOT thread
Web-based ROOT files and objects browser.
std::unique_ptr< RBrowserTimer > fTimer
! timer to handle postponed requests
RBrowserData fBrowsable
! central browsing element
std::shared_ptr< RBrowserWidget > AddWidget(const std::string &kind)
Creates new widget.
std::vector< std::string > GetRootHistory()
Get content of history file.
void AddInitWidget(const std::string &kind)
Create new widget and send init message to the client.
std::vector< std::vector< std::string > > fPostponed
! postponed messages, handled in timer
std::shared_ptr< RWebWindow > fWebWindow
! web window to browser
std::string ProcessDrop(unsigned connid, std::vector< std::string > &args)
Process drop of item in the current tab.
int fWidgetCnt
! counter for created widgets
std::shared_ptr< RBrowserWidget > GetActiveWidget() const
std::string ProcessDblClick(unsigned connid, std::vector< std::string > &args)
Process dbl click on browser item.
void ClearOnClose(const std::shared_ptr< void > &handle)
Set handle which will be cleared when connection is closed.
std::string fActiveWidgetName
! name of active widget
RBrowser(bool use_rcanvas=false)
constructor
void SetWorkingPath(const std::string &path)
Set working path in the browser.
void Hide()
Hide ROOT Browser.
std::string NewWidgetMsg(std::shared_ptr< RBrowserWidget > &widget)
Create message which send to client to create new widget.
bool fCatchWindowShow
! if arbitrary RWebWindow::Show calls should be catched by browser
std::string fPromptFileOutput
! file name for prompt output
void Show(const RWebDisplayArgs &args="", bool always_start_new_browser=false)
Show or update RBrowser in web window If web window already started - just refresh it like "reload" b...
std::string GetCurrentWorkingDirectory()
Return the current directory of ROOT.
void SetUseRCanvas(bool on=true)
std::shared_ptr< RBrowserWidget > FindWidget(const std::string &name, const std::string &kind="") const
Find widget by name or kind.
std::shared_ptr< RBrowserWidget > AddCatchedWidget(RWebWindow *win, const std::string &kind)
Add widget catched from external scripts.
bool GetUseRCanvas() const
std::vector< std::shared_ptr< RBrowserWidget > > fWidgets
! all browser widgets
virtual ~RBrowser()
destructor
void ProcessSaveFile(const std::string &fname, const std::string &content)
Process file save command in the editor.
float fLastProgressSend
! last value of send progress
std::string GetWindowUrl(bool remote)
Return URL parameter for the window showing ROOT Browser See ROOT::RWebWindow::GetUrl docu for more d...
std::string ProcessBrowserRequest(const std::string &msg)
Process browser request.
std::vector< std::string > GetRootLogs()
Get content of log file.
void ProcessMsg(unsigned connid, const std::string &arg)
Process received message from the client.
void CheckWidgtesModified(unsigned connid)
Check if any widget was modified and update if necessary.
void CloseTab(const std::string &name)
Close and delete specified widget.
void ProcessPostponedRequests()
Process postponed requests - decouple from websocket handling Only requests which can take longer tim...
unsigned fConnId
! default connection id
bool ActivateWidget(const std::string &title, const std::string &kind="")
Activate widget in RBrowser One should specify title and (optionally) kind of widget like "tcanvas" o...
void SendInitMsg(unsigned connid)
Process client connect.
void SendProgress(unsigned connid, float progr)
Send generic progress message to the web window Should show progress bar on client side.
long long fLastProgressSendTm
! time when last progress message was send
void ProcessRunMacro(const std::string &file_path)
Process run macro command in the editor.
void Sync()
Run widget Sync method - processing pending actions.
static bool IsMessageToStartDialog(const std::string &msg)
Check if this could be the message send by client to start new file dialog If returns true,...
static std::shared_ptr< RFileDialog > Embed(const std::shared_ptr< RWebWindow > &window, unsigned connid, const std::string &args)
Create dialog instance to use as embedded dialog inside other widget Embedded dialog started on the c...
Holds different arguments for starting browser with RWebDisplayHandle::Display() method.
const std::string & GetWidgetKind() const
returns widget kind
Represents web window, which can be shown in web browser or any other supported environment.
std::string GetUrl(bool remote=true)
Return URL string to connect web window URL typically includes extra parameters required for connecti...
static std::shared_ptr< RWebWindow > Create()
Create new RWebWindow Using default RWebWindowsManager.
static unsigned ShowWindow(std::shared_ptr< RWebWindow > window, const RWebDisplayArgs &args="")
Static method to show web window Has to be used instead of RWebWindow::Show() when window potentially...
This class creates the ROOT Application Environment that interfaces to the windowing system eventloop...
static TString ToJSON(const T *obj, Int_t compact=0, const char *member_name=nullptr)
@ kNoSpaces
no new lines plus remove all spaces around "," and ":" symbols
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
const char * Data() const
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
virtual Int_t RedirectOutput(const char *name, const char *mode="a", RedirectHandle_t *h=nullptr)
Redirect standard output (stdout, stderr) to the specified file.
virtual int GetPid()
Get process id.
virtual TTime Now()
Get current time in milliseconds since 0:00 Jan 1 1995.
virtual const char * UnixPathName(const char *unixpathname)
Convert from a local pathname to a Unix pathname.
virtual const char * HomeDirectory(const char *userName=nullptr)
Return the user's home directory.
virtual int Unlink(const char *name)
Unlink, i.e.
virtual const char * TempDirectory() const
Return a user configured or systemwide directory to create temporary files in.
Handles synchronous and a-synchronous timer events.
ROOT::RLogChannel & BrowserLog()
Log channel for Browser diagnostics.