43using namespace std::string_literals;
77 std::string
GetUrl()
override {
return ""s; }
79 void Show(
const std::string &)
override {}
81 bool DrawElement(std::shared_ptr<Browsable::RElement> &elem,
const std::string & =
"")
override
84 auto code = elem->GetContent(
"text");
91 auto json = elem->GetContent(
"json");
95 fTitle = elem->GetName() +
".json";
106 auto img = elem->GetContent(
"image64");
111 fFileName = elem->GetContent(
"filename");
128 std::string msg =
fIsEditor ?
"EDITOR:"s :
"IMAGE:"s;
155 std::string
GetKind()
const override {
return "info"s; }
157 std::string
GetUrl()
override {
return ""s; }
159 void Show(
const std::string &)
override {}
161 bool DrawElement(std::shared_ptr<Browsable::RElement> &,
const std::string & =
"")
override {
return false; }
168 std::ostringstream pathtmp;
171 std::ofstream ofs(pathtmp.str(), std::ofstream::out | std::ofstream::app);
176 gROOT->ProcessLine(
".g");
179 std::ifstream infile(pathtmp.str());
193 int indx = 0, last_prompt = -1;
194 for (
auto &
line : logs) {
200 if (last_prompt < 0) {
209 for (
auto &
line : logs) {
241 void Show(
const std::string &)
override {}
243 std::string
GetKind()
const override {
return "catched"s; }
275 if (
gROOT->IsWebDisplayBatch()) {
276 ::Warning(
"RBrowser::RBrowser",
"The RBrowser cannot run in web batch mode");
280 std::ostringstream pathtmp;
288 fTimer = std::make_unique<RBrowserTimer>(10,
kTRUE, *
this);
291 fWebWindow->SetDefaultPage(
"file:rootui5sys/browser/browser.html");
295 [
this](
unsigned connid,
const std::string &arg) {
if ((connid ==
fConnId) && (
fConnId != 0xffffff))
ProcessMsg(connid, arg); });
322 return widget ? true :
false;
345 fWebWindow->GetManager()->SetShowCallback(
nullptr);
353 std::unique_ptr<RBrowserRequest> request;
356 request = std::make_unique<RBrowserRequest>();
358 request->number = 100;
360 request = TBufferJSON::FromJSON<RBrowserRequest>(msg);
377 if (fname.empty())
return;
379 std::ofstream
f(fname);
388 if (file_path.rfind(
".py") == file_path.length() - 3) {
390 exec.
Form(
"TPython::ExecScript(\"%s\");", file_path.c_str());
404 std::string opt = args.back();
408 path.insert(path.end(), args.begin(), args.end());
413 if (!elem)
return ""s;
415 auto dflt_action = elem->GetDefaultAction();
419 std::string widget_kind;
422 widget_kind =
"rcanvas";
424 widget_kind =
"tcanvas";
434 new_widget->fBrowser =
this;
436 new_widget->Show(
"embed");
445 elem->GetChildsIter();
450 SendProgress(connid, progress);
454 if (widget && widget->DrawElement(elem, opt)) {
455 widget->SetPath(path);
456 return widget->SendWidgetContent();
461 [path](
const std::shared_ptr<RBrowserWidget> &wg) { return path == wg->GetPath(); });
464 return "SELECT_WIDGET:"s + (*iter)->GetName();
470 std::string widget_kind;
471 switch(dflt_action) {
478 default: widget_kind.clear();
481 if (!widget_kind.empty()) {
482 auto new_widget =
AddWidget(widget_kind);
486 if (new_widget->DrawElement(elem, opt))
487 new_widget->SetPath(path);
494 for (
auto &pathelem : path)
511 if (!
fWebWindow->NumConnections() || always_start_new_browser) {
535 std::shared_ptr<RBrowserWidget> widget;
537 if (kind ==
"editor"s)
538 widget = std::make_shared<RBrowserEditorWidget>(
name,
true);
539 else if (kind ==
"image"s)
540 widget = std::make_shared<RBrowserEditorWidget>(
name,
false);
541 else if (kind ==
"info"s)
542 widget = std::make_shared<RBrowserInfoWidget>(
name);
551 widget->fBrowser =
this;
552 widget->Show(
"embed");
565 if (url.empty())
return nullptr;
569 auto widget = std::make_shared<RBrowserCatchedWidget>(
name, url, kind);
595 [
name, kind](
const std::shared_ptr<RBrowserWidget> &widget) {
596 return kind.empty() ? name == widget->GetName() : kind == widget->GetKind();
610 auto iter = std::find_if(
fWidgets.begin(),
fWidgets.end(), [
name](std::shared_ptr<RBrowserWidget> &widget) { return name == widget->GetName(); });
623 std::vector<std::string> arr;
626 path +=
"/.root_hist" ;
627 std::ifstream infile(path);
631 while (std::getline(infile,
line) && (arr.size() < 1000)) {
632 if(!(std::find(arr.begin(), arr.end(),
line) != arr.end())) {
633 arr.emplace_back(
line);
646 std::vector<std::string> arr;
651 while (std::getline(infile,
line) && (arr.size() < 10000)) {
652 arr.emplace_back(
line);
664 std::vector<std::vector<std::string>> reply;
670 reply.emplace_back(std::vector<std::string>({ widget->GetKind(), widget->GetUrl(), widget->GetName(), widget->GetTitle() }));
674 reply.emplace_back(std::vector<std::string>({
"active"s, fActiveWidgetName }));
677 if (history.size() > 0) {
678 history.insert(history.begin(),
"history"s);
679 reply.emplace_back(history);
683 if (logs.size() > 0) {
684 logs.insert(logs.begin(),
"logs"s);
685 reply.emplace_back(logs);
688 reply.emplace_back(std::vector<std::string>({
695 std::string msg =
"INMSG:";
713 fWebWindow->Send(connid,
"PROGRESS:"s + std::to_string(progr));
734 std::vector<std::string> arr = { widget->GetKind(), widget->GetUrl(), widget->GetName(), widget->GetTitle(),
745 widget->CheckModified();
763 unsigned connid = std::stoul(arr.back()); arr.pop_back();
764 std::string kind = arr.back(); arr.pop_back();
766 if (kind ==
"DBLCLK") {
768 if (reply.empty()) reply =
"NOPE";
781 R__LOG_DEBUG(0,
BrowserLog()) <<
"ProcessMsg len " << arg0.length() <<
" substr(30) " << arg0.substr(0, 30);
783 std::string kind, msg;
784 auto pos = arg0.find(
":");
785 if (pos == std::string::npos) {
788 kind = arg0.substr(0, pos);
789 msg = arg0.substr(pos+1);
792 if (kind ==
"QUIT_ROOT") {
796 }
else if (kind ==
"BRREQ") {
801 }
else if (kind ==
"DBLCLK") {
803 auto arr = TBufferJSON::FromJSON<std::vector<std::string>>(msg);
804 if (arr && (arr->size() > 2)) {
805 arr->push_back(kind);
806 arr->push_back(std::to_string(connid));
814 }
else if (kind ==
"WIDGET_SELECTED") {
818 auto reply = widget->SendWidgetContent();
819 if (!reply.empty())
fWebWindow->Send(connid, reply);
821 }
else if (kind ==
"CLOSE_TAB") {
823 }
else if (kind ==
"GETWORKPATH") {
825 }
else if (kind ==
"CHPATH") {
826 auto path = TBufferJSON::FromJSON<Browsable::RElementPath_t>(msg);
829 }
else if (kind ==
"CMD") {
830 std::string sPrompt =
"root []";
833 sPrompt = ((
TRint*)
gROOT->GetApplication())->GetPrompt();
834 Gl_histadd((
char *)msg.c_str());
838 ofs << sPrompt << msg << std::endl;
842 gROOT->ProcessLine(msg.c_str());
846 auto widget = std::dynamic_pointer_cast<RBrowserInfoWidget>(
FindWidget(
""s,
"info"s));
850 widget = std::dynamic_pointer_cast<RBrowserInfoWidget>(new_widget);
852 fWebWindow->Send(connid,
"SELECT_WIDGET:"s + widget->GetName());
857 widget->RefreshFromLogs(sPrompt + msg,
GetRootLogs());
861 }
else if (kind ==
"GETHISTORY") {
866 }
else if (kind ==
"GETLOGS") {
875 }
else if (kind ==
"SYNCEDITOR") {
876 auto arr = TBufferJSON::FromJSON<std::vector<std::string>>(msg);
877 if (arr && (arr->size() > 4)) {
878 auto editor = std::dynamic_pointer_cast<RBrowserEditorWidget>(
FindWidget(arr->at(0)));
880 editor->fFirstSend =
true;
881 editor->fTitle = arr->at(1);
882 editor->fFileName = arr->at(2);
883 if (!arr->at(3).empty()) editor->fContent = arr->at(4);
884 if ((arr->size() == 6) && (arr->at(5) ==
"SAVE"))
886 if ((arr->size() == 6) && (arr->at(5) ==
"RUN")) {
892 }
else if (kind ==
"GETINFO") {
893 auto info = std::dynamic_pointer_cast<RBrowserInfoWidget>(
FindWidget(msg));
896 fWebWindow->Send(connid, info->SendWidgetContent());
898 }
else if (kind ==
"NEWWIDGET") {
902 }
else if (kind ==
"CDWORKDIR") {
910 }
else if (kind ==
"OPTIONS") {
911 auto arr = TBufferJSON::FromJSON<std::vector<std::string>>(msg);
912 if (arr && (arr->size() == 3)) {
945 if (widget->GetTitle() != title)
948 if (!kind.empty() && (widget->GetKind() != kind))
952 fWebWindow->Send(0,
"SELECT_WIDGET:"s + widget->GetName());
#define R__LOG_ERROR(...)
#define R__LOG_DEBUG(DEBUGLEVEL,...)
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 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
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.
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 Browser in specified place
std::string GetCurrentWorkingDirectory()
Return the current directory of ROOT.
std::shared_ptr< RBrowserWidget > AddCatchedWidget(const std::string &url, const std::string &kind)
Add widget catched from external scripts.
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.
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.
void CheckWidgtesModified()
Check if any widget was modified and update if necessary.
float fLastProgressSend
! last value of send progress
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 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.
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.
static std::shared_ptr< RWebWindow > Create()
Create new RWebWindow Using default RWebWindowsManager.
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 Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
const char * Data() const
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.
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
ROOT::Experimental::RLogChannel & BrowserLog()
Log channel for Browser diagnostics.