Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
QCanvasWidget.cpp
Go to the documentation of this file.
1// Author: Sergey Linev, GSI 26/06/2026
2
3/*************************************************************************
4 * Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11#include "QCanvasWidget.h"
12
13#include "TCanvas.h"
14#include "TROOT.h"
15#include "TMarker.h"
16#include "TApplication.h"
17#include "TTimer.h"
18#include "TFile.h"
19#include "TError.h"
20#include "TColorWheel.h"
21
22#include <QMessageBox>
23#include <QPushButton>
24#include <QFileDialog>
25
26
31
33 const char *fPixmap;
34 const char *fTipText;
37 void *fButton;
38};
39
40
42 // { filename, tooltip, staydown, id, button}
43 { "newcanvas.xpm", "New", kFALSE, kFileNewCanvas, 0 },
44 { "open.xpm", "Open", kFALSE, kFileOpen, 0 },
45 { "save.xpm", "Save As", kFALSE, kFileSaveAs, 0 },
46 { "printer.xpm", "Print", kFALSE, kFilePrint, 0 },
47 { "", "", kFALSE, -1, 0 },
48 { "interrupt.xpm", "Interrupt", kFALSE, kOptionInterrupt,0 },
49 { "refresh2.xpm", "Refresh", kFALSE, kOptionRefresh, 0 },
50 { "", "", kFALSE, -1, 0 },
51 { "inspect.xpm", "Inspect", kFALSE, kInspectRoot, 0 },
52// { "browser.xpm", "Browser", kFALSE, kToolsBrowser, 0 },
53 { "", "", kFALSE, -1, 0 },
54 { "pointer.xpm", "Modify", kFALSE, kToolModify, 0 },
55 { "arc.xpm", "Arc", kFALSE, kToolArc, 0 },
56 { "line.xpm", "Line", kFALSE, kToolLine, 0 },
57 { "arrow.xpm", "Arrow", kFALSE, kToolArrow, 0 },
58 { "diamond.xpm", "Diamond", kFALSE, kToolDiamond, 0 },
59 { "ellipse.xpm", "Ellipse", kFALSE, kToolEllipse, 0 },
60 { "pad.xpm", "Pad", kFALSE, kToolPad, 0 },
61 { "pave.xpm", "Pave", kFALSE, kToolPave, 0 },
62 { "pavelabel.xpm", "Pave Label", kFALSE, kToolPLabel, 0 },
63 { "pavetext.xpm", "Pave Text", kFALSE, kToolPText, 0 },
64 { "pavestext.xpm", "Paves Text", kFALSE, kToolPsText, 0 },
65 { "graph.xpm", "Graph", kFALSE, kToolGraph, 0 },
66 { "curlyline.xpm", "Curly Line", kFALSE, kToolCurlyLine, 0 },
67 { "curlyarc.xpm", "Curly Arc", kFALSE, kToolCurlyArc, 0 },
68 { "latex.xpm", "Text/Latex", kFALSE, kToolLatex, 0 },
69 { "marker.xpm", "Marker", kFALSE, kToolMarker, 0 },
70 { "cut.xpm", "Graphical Cut", kFALSE, kToolCutG, 0 },
71 { 0, 0, kFALSE, 0, 0 }
72};
73
74
75
76/** \class QCanvasWidget
77 \ingroup qt6canvas
78
79Qt widget which display canvas and provides menu, toolbar and status bar
80Actual graphics shown in the \ref QPaintWidget
81*/
82
83
84////////////////////////////////////////////////////////////////////////////////
85/// constructor
86
87QCanvasWidget::QCanvasWidget(QWidget *parent, const char *name) : QWidget(parent)
88{
89 setupUi(this);
90
91 setAttribute(Qt::WA_DeleteOnClose);
92
94
96
97 // fMenuBar = new QMenuBar(fMenuFrame);
98 fMenuBar->setMinimumWidth(50);
99 fMenuBar->setNativeMenuBar(kFALSE); // disable putting this to screen menu. for MAC style WMs
100
101 auto fileMenu = fMenuBar->addMenu("F&ile");
102 fileMenu->addAction("&New canvas", this, &QCanvasWidget::NewCanvas);
103 fileMenu->addAction("Open ...", this, &QCanvasWidget::OpenRootFile);
104 fileMenu->addAction("Cl&ose canvas", this, &QCanvasWidget::CloseCanvas);
105
106 fileMenu->addSeparator();
107
108 auto saveMenu = fileMenu->addMenu("&Save");
110 connect(saveMenu, &QMenu::aboutToShow, this, [this, saveMenu]() {
111 saveMenu->clear();
113 });
114
115 fileMenu->addAction("Save &As...", this, &QCanvasWidget::SaveCanvasAs);
116
117 fileMenu->addSeparator();
118
119 fileMenu->addAction("Print...", this, &QCanvasWidget::PrintCanvas);
120 fileMenu->addSeparator();
121
122 fileMenu->addAction("Quit ROOT", this, &QCanvasWidget::QuitRoot);
123
124
125 fMenuBar->addMenu("&Edit");
126
127 auto viewMenu = fMenuBar->addMenu("&View");
128 auto act = viewMenu->addAction("&Editor");
129 act->setEnabled(false);
130
131 fViewToolbar = viewMenu->addAction("&Toolbar");
132 fViewToolbar->setCheckable(true);
133 connect(fViewToolbar, &QAction::toggled, this, &QCanvasWidget::SetViewToolbar);
134 SetViewToolbar(false);
135
136 fViewEventStatus = viewMenu->addAction("Event &Statusbar");
137 fViewEventStatus->setCheckable(true);
139 SetViewEventStatus(false);
140
141 fViewToolTip = viewMenu->addAction("T&ooltip Info");
142 fViewToolTip->setCheckable(true);
143 connect(fViewToolTip, &QAction::toggled, this, &QCanvasWidget::SetViewToolTip);
144 SetViewToolTip(false);
145
146 viewMenu->addSeparator();
147
148 viewMenu->addAction("&Colors", this, &QCanvasWidget::ShowColors);
149
150 act = viewMenu->addAction("&Fonts");
151 act->setEnabled(false);
152
153 viewMenu->addAction("&Markers", this, &QCanvasWidget::ShowMarkers);
154
155 viewMenu->addSeparator();
156 viewMenu->addAction("&Iconify", this, &QCanvasWidget::IconifyCanvas);
157
158
159 fMenuBar->addMenu("&Options");
160
161 fMenuBar->addMenu("&Tools");
162
163 auto spacer = new QWidget(this);
164 spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
165 fMenuBar->setCornerWidget(spacer, Qt::TopRightCorner);
166
167 fMenuBar->addMenu("&Help");
168
169 // configure tool bar
170
171 //fToolBar->setStyleSheet("QToolBar { layout-spacing: 0px; }"
172 // "QToolBar QToolButton { padding: 0px; margin: 0px; border: none; }");
173 fToolBar->setIconSize(QSize(16, 16));
174 for (int i = 0; qToolBarData[i].fPixmap; i++) {
175 auto btn = &(qToolBarData[i]);
176 if (strlen(btn->fPixmap) == 0) {
177 fToolBar->addSeparator();
178 continue;
179 }
180
181 TString iconname = TROOT::GetIconPath();
182 iconname.Append("/");
183 iconname.Append(btn->fPixmap);
184
185 QIcon buttonIcon(iconname.Data());
186
187 fToolBar->addAction(buttonIcon, btn->fTipText, [btn, this]() {
188 auto canv = GetPaintWidget()->getCanvas();
189
190 switch(btn->fId) {
191 case kFileNewCanvas: NewCanvas(); break;
192 case kFileOpen: OpenRootFile(); break;
193 case kFileSaveAs: SaveCanvasAs(); break;
194 case kFilePrint: PrintCanvas(); break;
195 case kOptionInterrupt: gROOT->SetInterrupt(); break;
196 case kOptionRefresh:
197 if (canv) {
198 canv->Modified(kTRUE);
199 // trigger update of the paint widget, paint will be called
200 canv->Update();
201 }
202 break;
203 case kInspectRoot:
204 if (canv) {
205 canv->cd();
206 gROOT->Inspect();
207 canv->Update();
208 }
209 break;
210
211 case kToolsBrowser: break;
212 case kToolModify: gROOT->SetEditorMode(); break;
213 case kToolArc:
214 gROOT->SetEditorMode("Arc");
215 break;
216 case kToolLine:
217 gROOT->SetEditorMode("Line");
218 break;
219 case kToolArrow:
220 gROOT->SetEditorMode("Arrow");
221 break;
222 case kToolDiamond:
223 gROOT->SetEditorMode("Diamond");
224 break;
225 case kToolEllipse:
226 gROOT->SetEditorMode("Ellipse");
227 break;
228 case kToolPad:
229 gROOT->SetEditorMode("Pad");
230 break;
231 case kToolPave:
232 gROOT->SetEditorMode("Pave");
233 break;
234 case kToolPLabel:
235 gROOT->SetEditorMode("PaveLabel");
236 break;
237 case kToolPText:
238 gROOT->SetEditorMode("PaveText");
239 break;
240 case kToolPsText:
241 gROOT->SetEditorMode("PavesText");
242 break;
243 case kToolGraph:
244 gROOT->SetEditorMode("PolyLine");
245 break;
246 case kToolCurlyLine:
247 gROOT->SetEditorMode("CurlyLine");
248 break;
249 case kToolCurlyArc:
250 gROOT->SetEditorMode("CurlyArc");
251 break;
252 case kToolLatex:
253 gROOT->SetEditorMode("Text");
254 break;
255 case kToolMarker:
256 gROOT->SetEditorMode("Marker");
257 break;
258 case kToolCutG:
259 gROOT->SetEditorMode("CutG");
260 break;
261 }
262 });
263 }
264}
265
266////////////////////////////////////////////////////////////////////////////////
267/// Destructor
268
272
273////////////////////////////////////////////////////////////////////////////////
274/// Create new canvas.
275
277{
278 gROOT->MakeDefCanvas();
279}
280
281////////////////////////////////////////////////////////////////////////////////
282/// Open ROOT file dialog
283
285{
286 QFileDialog fd( this,
287 "Select a ROOT file(s) to open them",
289 QString("Root files (*.root);;Root xml files (*.xml);;All files (*.*)"));
290
291 fd.setFileMode(QFileDialog::ExistingFiles);
292
293 if (fd.exec() != QDialog::Accepted)
294 return;
295
296 QStringList list = fd.selectedFiles();
297 for (auto &fileName : list) {
298 fLastFileDir = QFileInfo(fileName).absolutePath();
299 TFile::Open(fileName.toLatin1().constData(), "update");
300 }
301}
302
303////////////////////////////////////////////////////////////////////////////////
304/// Close the canvas.
305
307{
308 close();
309}
310
311////////////////////////////////////////////////////////////////////////////////
312/// Return vector with supported file formats with description and required option
313
315{
316 return {
317 "Post Script", "ps", "ps",
318 "Post Script Portrait", "ps", "Portrait",
319 "Post Script Landscape", "ps", "Landscape",
320 "Encapsulated Post Script", "eps", "eps",
321 "Encapsulated Post Script preview", "eps", "Preview",
322 "GIF format", "gif", "gif",
323 "PDF format", "pdf", "pdf",
324 "SVG format", "svg", "svg",
325 "XPM format", "xpm", "xpm",
326 "PNG format", "png", "png",
327 "JPG format", "jpg", "jpg",
328 "BMP format", "bmp", "bmp",
329 "TIFF format", "tiff", "tiff",
330 "C++ Macro", "C", "cxx",
331 "json file", "json", "json",
332 "html file", "html", "html",
333 "root file", "root", "root" };
334}
335
336////////////////////////////////////////////////////////////////////////////////
337/// Fill save menu with predefined items
338
340{
341 auto canv = GetPaintWidget()->getCanvas();
342
344
345 for (std::size_t pos = 0; pos < fmts.size(); pos += 3) {
346 auto ext = fmts[pos + 1];
347 if ((ext != "C") && (ext != fmts[pos + 2]))
348 continue;
349
350 QString filename = canv ? canv->GetName() : "c1";
351 filename += ".";
352 filename += ext.c_str();
353 auto act1 = menu->addAction(filename);
354 connect(act1, &QAction::triggered, this, [this, filename]() {
356 });
357 }
358}
359
360////////////////////////////////////////////////////////////////////////////////
361/// Save canvas as file
362
364{
365 auto canv = GetPaintWidget()->getCanvas();
366 if (canv)
367 canv->SaveAs(fname.toLatin1().constData());
368}
369
370////////////////////////////////////////////////////////////////////////////////
371/// Save canvas as
372
374{
375 auto canv = GetPaintWidget()->getCanvas();
376 if (!canv)
377 return;
378
380
381 QFileDialog fd( this, QString("Save ") + canv->GetName() + " As", fLastFileDir);
382 fd.setFileMode( QFileDialog::AnyFile );
383 fd.setAcceptMode(QFileDialog::AcceptSave);
384
385 QStringList flt;
386
387 for (std::size_t pos = 0; pos < fmts.size(); pos += 3) {
388 QString filter = QString(fmts[pos].c_str()) + " (*." + fmts[pos+1].c_str() + ")";
389 flt << filter;
390 }
391
392 fd.setNameFilters(flt);
393
394 QString filename0 = canv->GetName();
395
396 fd.selectFile(filename0 + ".png");
397
398 QObject::connect(&fd, &QFileDialog::filterSelected, [filename0, &fd](const QString &fltr) {
399 QStringList flst = fd.selectedFiles();
400 if (flst.size() > 1)
401 return;
402 if ((flst.size() == 1) && (flst[0].indexOf(filename0 + ".") != 0))
403 return;
404
405 auto p = fltr.indexOf("(*."), p2 = fltr.lastIndexOf(")");
406 fd.selectFile(filename0 + fltr.mid(p + 2, p2 - p - 2));
407 });
408
409 if (fd.exec() != QDialog::Accepted)
410 return;
411
412 QStringList flst = fd.selectedFiles();
413 if (flst.isEmpty()) return;
414
415 QString filename = flst[0];
416
417 fLastFileDir = fd.directory().path();
418
419 std::string opt;
420
421 for (std::size_t pos = 0; pos < fmts.size(); pos += 3) {
422 QString filter = QString(fmts[pos].c_str()) + " (*." + fmts[pos+1].c_str() + ")";
423 if (filter != fd.selectedNameFilter())
424 continue;
425
426 if (!filename.endsWith(QString(".") + fmts[pos+1].c_str())) {
427 filename.append(".");
428 filename.append(fmts[pos+1].c_str());
429 }
430 opt = fmts[pos + 2];
431 break;
432 }
433
434 if (!opt.empty())
435 canv->Print(filename.toLatin1().constData(), opt.c_str());
436}
437
438////////////////////////////////////////////////////////////////////////////////
439/// Print the canvas.
440
442{
443 ::Info("QCanvasWidget::PrintCanvas", "To be implemented");
444}
445
446////////////////////////////////////////////////////////////////////////////////
447/// Quit ROOT
448
450{
451 // set flag which sometimes checked in TSystem::ProcessEvents
452 gROOT->SetInterrupt(kTRUE);
453
454 if (gApplication)
455 TTimer::SingleShot(100, "TApplication", gApplication, "Terminate()");
456}
457
458////////////////////////////////////////////////////////////////////////////////
459/// Set visibility of tool bar
460
462{
463 fToolBar->setVisible(on);
464 fViewToolbar->setChecked(on);
465}
466
467////////////////////////////////////////////////////////////////////////////////
468/// Set visibility of event status
469
471{
472 fStatusBar->setVisible(on);
473 fViewEventStatus->setChecked(on);
474}
475
476////////////////////////////////////////////////////////////////////////////////
477/// Status event handler
478
480{
481 if (fStatusBar && fStatusBar->isVisible())
482 fStatusBar->showMessage(msg);
483}
484
485////////////////////////////////////////////////////////////////////////////////
486/// Set visibility of tooltip
487
489{
490 fViewToolTip->setChecked(on);
491
492 fPaintWidget->SetShowToolTip(on);
493}
494
495////////////////////////////////////////////////////////////////////////////////
496/// Show new canvas with ROOT colors wheel
497
499{
501
502 auto wheel = new TColorWheel();
503 wheel->Draw();
504 gPad->Update();
505}
506
507////////////////////////////////////////////////////////////////////////////////
508/// Show new canvas with ROOT markers
509
511{
513
514 auto m = new TCanvas("markers","Marker Types",600,200);
516 m->Update();
517}
518
519////////////////////////////////////////////////////////////////////////////////
520/// Iconify canvas widget
521
526
527////////////////////////////////////////////////////////////////////////////////
528/// Apply canvas status bits like show tooltip or menu bar
529
531{
532 auto canv = GetPaintWidget()->getCanvas();
533 if (!canv)
534 return;
535
537
538 // canv->TestBit(TCanvas::kShowEditor);
539
541
543
544 fMenuBar->setVisible(canv->TestBit(TCanvas::kMenuBar));
545
546
547}
static QToolBarData_t qToolBarData[]
@ kOptionInterrupt
@ kToolLatex
@ kToolPLabel
@ kToolPad
@ kFilePrint
@ kToolDiamond
@ kToolCurlyLine
@ kToolLine
@ kFileSaveAs
@ kToolEllipse
@ kToolPsText
@ kToolModify
@ kToolArrow
@ kToolArc
@ kToolsBrowser
@ kToolPave
@ kFileNewCanvas
@ kOptionRefresh
@ kInspectRoot
@ kToolPText
@ kToolCurlyArc
@ kToolGraph
@ kToolCutG
@ kToolMarker
@ kFileOpen
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
R__EXTERN TApplication * gApplication
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
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 TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void on
char name[80]
Definition TGX11.cxx:142
#define gROOT
Definition TROOT.h:417
#define gPad
void SetViewEventStatus(bool)
Set visibility of event status.
void QuitRoot()
Quit ROOT.
void OpenRootFile()
Open ROOT file dialog.
void NewCanvas()
Create new canvas.
void FillSaveMenu(QMenu *menu)
Fill save menu with predefined items.
QAction * fViewEventStatus
void SaveCanvas(const QString &fname)
Save canvas as file.
void CanvasStatusEventSlot(const QString &)
Status event handler.
void SetViewToolTip(bool)
Set visibility of tooltip.
QAction * fViewToolTip
void CloseCanvas()
Close the canvas.
void PrintCanvas()
Print the canvas.
QPaintWidget * GetPaintWidget() const
QAction * fViewToolbar
void SetViewToolbar(bool)
Set visibility of tool bar.
QCanvasWidget(QWidget *parent=nullptr, const char *name=nullptr)
constructor
virtual ~QCanvasWidget()
Destructor.
void SaveCanvasAs()
Save canvas as.
void ShowColors()
Show new canvas with ROOT colors wheel.
QString fLastFileDir
void ShowMarkers()
Show new canvas with ROOT markers.
void IconifyCanvas()
Iconify canvas widget.
void ApplyCanvasStatusBits()
Apply canvas status bits like show tooltip or menu bar.
std::vector< std::string > GetSupportedFileFormats()
Return vector with supported file formats with description and required option.
TCanvas * getCanvas()
returns canvas shown in the widget
void CanvasStatusEvent(const QString &msg)
The Canvas class.
Definition TCanvas.h:23
@ kShowToolTips
Definition TCanvas.h:101
@ kShowToolBar
Definition TCanvas.h:96
@ kShowEventStatus
Definition TCanvas.h:93
@ kMenuBar
Definition TCanvas.h:95
Draw the ROOT Color Wheel.
Definition TColorWheel.h:23
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:3802
static void DisplayMarkerTypes()
Display the table of markers with their numbers.
Definition TMarker.cxx:101
static const TString & GetIconPath()
Get the icon path in the installation. Static utility function.
Definition TROOT.cxx:3501
Basic string class.
Definition TString.h:137
const char * Data() const
Definition TString.h:385
TString & Append(const char *cs)
Definition TString.h:582
static void SingleShot(Int_t milliSec, const char *receiver_class, void *receiver, const char *method)
This static function calls a slot after a given time interval.
Definition TTimer.cxx:261
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:61
const char * fTipText
const char * fPixmap
TMarker m
Definition textangle.C:8