CVB++ 15.0
ShapeFinder2/QtShapeFinder2

This example requires Qt5 >= 5.9 setup for building.

You may build it with Ubuntu 18.04's default Qt5 after installing:

1
2
3
4
5
6
7#ifdef _MSC_VER
8#pragma warning ( push, 1)
9#pragma warning ( disable : 4702)
10#endif
11
12#include <QApplication>
13#include <QIcon>
14
15#include "main_widget.hpp"
16
17
18
19#ifdef _MSC_VER
20#pragma warning ( pop)
21#endif
22
23int main(int argc, char* argv[])
24{
25
26 QApplication application(argc, argv);
27 MainWidget mainWidget;
28 mainWidget.setWindowIcon(QIcon(":/qttutorial.png"));
29 mainWidget.show();
30 application.exec();
31}
1#pragma once
2
3#include <QSplitter>
4#include <QCheckBox>
5#include <QLabel>
6
7#include <cvb/ui/image_view.hpp>
8#include <cvb/async/single_stream_handler.hpp>
9#include <cvb/shapefinder2/classifier.hpp>
10
11// The custom image scene to draw overlays
12class CustomImageScene : public Cvb::UI::ImageScene
13{
14Q_OBJECT
15
16public:
17 explicit CustomImageScene(QWidget* parent = 0);
18 void SetSearchResult(const Cvb::Image & image, std::vector<Cvb::ShapeFinder2::SearchResult> result);
19 void ClearScene();
22
23signals:
24 void SelectionDone(QRectF selectedArea);
25
26private:
28 QPointF pointStart_;
29 QPointF pointEnd_;
30};
31
32// The control widget
33class ControlWidget : public QWidget
34{
35Q_OBJECT
36
37public:
38 explicit ControlWidget(QWidget* parent);
39 ~ControlWidget() = default;
40 void EnableGrabCheckBox(bool value);
41 void SetResultInfo(size_t numResults);
42 void SetTrainView(const Cvb::Image & image);
43
44private:
45 Cvb::UI::ImageView* trainImageView_ = nullptr;
46 QCheckBox* grabCheckBox_ = nullptr;
47 QCheckBox* contSearchCheckBox_ = nullptr;
48 QLabel* resultLabel_ = nullptr;
49};
50
51// The main widget
52class MainWidget : public QSplitter
53{
54 Q_OBJECT
55
56public:
57 explicit MainWidget();
58 virtual ~MainWidget() {}
59
60 void Search();
61
62public Q_SLOTS:
63 void HandleLoad();
64 void HandleGrab(int);
65 void HandleSnap();
66 void HandleSave();
67 void HandleLoadModel();
68 void HandleSaveModel();
69 void HandleSearch();
70 void HandleTrain();
71 void HandleContSearch(int);
72 void HandleSelection(QRectF);
73
74protected Q_SLOTS:
75 void ShowSearchResult();
76
77signals:
78 void SearchDone();
79
80private:
81 CustomImageScene* imageScene_ = nullptr;
82 Cvb::UI::ImageView* imageView_ = nullptr;
83 ControlWidget* ctrlWidget_ = nullptr;
84 Cvb::DevicePtr device_ = nullptr;
86 bool continuedSearch_ = false;
87 bool isSelected_ = false;
88 Cvb::ImagePtr selection_ = nullptr;
89 Cvb::Rect<double> selectionRect_;
91
92 // The custom stream handler to handle image processing while grabbing
93 class CustomStreamHandler : public Cvb::SingleStreamHandler
94 {
95 public:
96 static std::unique_ptr<CustomStreamHandler> Create(const Cvb::StreamPtr& stream, MainWidget& mainWidget)
97 {
98 return std::unique_ptr<CustomStreamHandler>(new CustomStreamHandler(stream, mainWidget));
99 }
100
101 ~CustomStreamHandler()
102 {
103 TryFinish();
104 }
105
106 private:
107 CustomStreamHandler(const Cvb::StreamPtr& stream, MainWidget& mainWidget)
108 : Cvb::SingleStreamHandler(stream)
109 , mainWidget_(mainWidget)
110 {}
111
112 void HandleAsyncStream(const Cvb::StreamPtr & stream) override
113 {
114 auto waitResult = stream->WaitFor(std::chrono::milliseconds(10000));
115 if (!waitResult.Image)
116 return;
117
118 if (mainWidget_.continuedSearch_)
119 mainWidget_.Search();
120 }
121
122 MainWidget& mainWidget_;
123
124 };
125
126 std::shared_ptr<CustomStreamHandler> streamHandler_ = nullptr;
127};
128
Handler object for a single stream.
Definition: decl_single_stream_handler.hpp:34
The Common Vision Blox image.
Definition: decl_image.hpp:45
Rectangle object.
Definition: rect.hpp:26
Scene to provide a convenient display for an image.
Definition: decl_image_scene.hpp:54
View to display an image.
Definition: decl_image_view.hpp:75
Root namespace for the Image Manager interface.
Definition: c_barcode.h:24
virtual void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
1// ---------------------------------------------------------------------------
3// ---------------------------------------------------------------------------
4#include "main_widget.hpp"
5
6
7#include <QVBoxLayout>
8#include <QPushButton>
9#include <QFileDialog>
10#include <QGroupBox>
11#include <QMessageBox>
12#include <QElapsedTimer>
13#include <QGraphicsSceneMouseEvent>
14#include <QRubberBand>
15#include <QGraphicsRectItem>
16
17#include <cvb/image.hpp>
18#include <cvb/device_factory.hpp>
19#include <cvb/device.hpp>
20#include <cvb/async/single_stream_handler.hpp>
21#include <cvb/driver/driver.hpp>
22#include <cvb/shapefinder2/classifier_factory.hpp>
23
24MainWidget::MainWidget()
25 : QSplitter()
26{
27 imageScene_ = new CustomImageScene(this);
28
29 imageView_ = new Cvb::UI::ImageView(imageScene_, this);
30 imageView_->SetUploadMode(Cvb::UI::UploadMode::Viewport);
31 imageView_->SetRenderEngine(Cvb::UI::RenderEngine::Raster);
32 imageView_->resize(800, 600);
33
34 imageView_->setDragMode(QGraphicsView::RubberBandDrag);
35 QObject::connect(imageScene_, SIGNAL(SelectionDone(QRectF)), this, SLOT(HandleSelection(QRectF)));
36
37 ctrlWidget_ = new ControlWidget(this);
38 addWidget(imageView_);
39 addWidget(ctrlWidget_);
40
41 device_ = Cvb::DeviceFactory::Open(Cvb::InstallPath() + Cvb::String(CVB_LIT("drivers/CVMock.vin")), Cvb::AcquisitionStack::Vin);
42 // Connect the device with the ImageView
43 imageView_->Refresh(device_->DeviceImage(), Cvb::UI::AutoRefresh::On);
44 // Create a stream handler
45 streamHandler_ = CustomStreamHandler::Create(device_->Stream(), *this);
46 // Enable the grab check box for devices
47 ctrlWidget_->EnableGrabCheckBox(true);
48
49 QObject::connect(this, SIGNAL(SearchDone()), this, SLOT(ShowSearchResult()));
50
51 resize(1000, 800);
52
53 // first snapshot
54 device_->Stream()->GetSnapshot();
55}
56
57// Load an image or driver
58void MainWidget::HandleLoad()
59{
60 imageScene_->ClearScene();
61
62 auto fileName = QFileDialog::getOpenFileName(this, "Load Image"
63 , Cvb::UI::CvbToQt(Cvb::ExpandPath(Cvb::InstallPath() + CVB_LIT("tutorial/ShapeFinder/Images/SF2/Lusterterminal")))
64 , "CVB Emulator Image Lists (*.emu);;CVB Drivers (*.vin);;Images (*.bmp *.png *.tif *.tiff *.jpg)");
65 if (fileName.isEmpty())
66 return;
67
68 if (fileName.contains(".emu", Qt::CaseInsensitive))
69 fileName = fileName.replace("/", "\\"); // necessary for emu files
70
71 try
72 {
73 // Either load an image or device (vin or emu)
74 if (fileName.contains(".bmp", Qt::CaseInsensitive) || fileName.contains(".png", Qt::CaseInsensitive) || fileName.contains(".tif", Qt::CaseInsensitive) || fileName.contains(".jpg", Qt::CaseInsensitive))
75 {
77 imageView_->Refresh(image);
78 // Disable the grab check box for images
79 ctrlWidget_->EnableGrabCheckBox(false);
80 }
81 else
82 {
83 device_ = Cvb::DeviceFactory::Open(Cvb::UI::QtToCvb(fileName), Cvb::AcquisitionStack::Vin);
84 // Connect the device with the ImageView
85 imageView_->Refresh(device_->DeviceImage(), Cvb::UI::AutoRefresh::On);
86 // Create a stream handler
87 streamHandler_ = CustomStreamHandler::Create(device_->Stream(), *this);
88 // Enable the grab check box for devices
89 ctrlWidget_->EnableGrabCheckBox(true);
90 }
91 }
92 catch (const std::exception& error)
93 {
94 QMessageBox::critical(this, "Error", QString(error.what()));
95 }
96}
97
98// Handle start / stop grab
99void MainWidget::HandleGrab(int state)
100{
101 if (state == Qt::CheckState::Checked)
102 {
103 imageScene_->ClearScene();
104
105 // Start streaming
106 streamHandler_->Run();
107 }
108 else
109 {
110 // Disable possible blocking of the UI if necessary
111 bool wait = imageView_->IsWaitForRepaintEnabled();
112 if (wait)
113 imageView_->SetWaitForRepaintEnabled(!wait);
114 // Stop streaming
115 streamHandler_->Finish();
116 // Reset the previous state
117 imageView_->SetWaitForRepaintEnabled(wait);
118 }
119}
120
121// Handle a snap
122void MainWidget::HandleSnap()
123{
124 device_->Stream()->GetSnapshot();
125 if (continuedSearch_)
126 HandleSearch();
127 else
128 imageScene_->ClearScene();
129}
130
131// Save the image
132void MainWidget::HandleSave()
133{
134 auto fileName = QFileDialog::getSaveFileName(this, "Save Image"
135 , Cvb::UI::CvbToQt(Cvb::InstallPath())
136 , "Bitmap File (*.bmp);;CVB Emulator Image Lists (*.emu);;JPEG (*.jpg, *.jpeg);;Portable Network Graphic (*.png);;Tagged Image File Format (*.tif, *.tiff);;All Files (*.*)");
137 if (fileName.isEmpty())
138 return;
139 imageView_->Image()->Save(Cvb::UI::QtToCvb(fileName));
140}
141
142// Load an SF2 model (classifier)
143void MainWidget::HandleLoadModel()
144{
145 imageScene_->ClearScene();
146
147 auto fileName = QFileDialog::getOpenFileName(this, "Load SF2 Model"
148 , Cvb::UI::CvbToQt(Cvb::ExpandPath(Cvb::InstallPath() + CVB_LIT("tutorial/ShapeFinder/Images/SF2/Lusterterminal")))
149 , "ShapeFinder2 models (*.sf2)");
150 if (fileName.isEmpty())
151 return;
152
153 classifier_ = Cvb::Classifier::Create(Cvb::UI::QtToCvb(fileName));
154}
155
156// Save the SF2 model
157void MainWidget::HandleSaveModel()
158{
159 auto fileName = QFileDialog::getSaveFileName(this, "Save SF2 Model"
160 , Cvb::UI::CvbToQt(Cvb::ExpandPath(Cvb::InstallPath() + CVB_LIT("tutorial/ShapeFinder/Images/SF2/Lusterterminal")))
161 , "ShapeFinder2 models (*.sf2)");
162 if (fileName.isEmpty())
163 return;
164
165 classifier_->Save(Cvb::UI::QtToCvb(fileName));
166}
167
168// Train / learn the selection and create classifier
169void MainWidget::HandleTrain()
170{
171 if (isSelected_)
172 {
173 ctrlWidget_->SetTrainView(*selection_);
174 imageScene_->ClearScene();
175 isSelected_ = false;
176 }
177 else
178 {
179 ctrlWidget_->SetTrainView(*imageView_->Image());
180 auto aoi = imageView_->Image()->Bounds();
181 selectionRect_ = Cvb::Rect<double>(aoi.Left(), aoi.Top(), aoi.Right(), aoi.Bottom());
182 }
183
185
186 double centerX = selectionRect_.Left() + ((selectionRect_.Right() - selectionRect_.Left()) / 2);
187 double centerY = selectionRect_.Top() + ((selectionRect_.Bottom() - selectionRect_.Top()) / 2);
188
189 Cvb::Rect<int> teachWindow(selectionRect_.Left() - centerX, selectionRect_.Top() - centerY, selectionRect_.Right() - centerX, selectionRect_.Bottom() - centerY);
190 try
191 {
192 classifier_ = factory.Learn(imageView_->Image()->Plane(0), Cvb::Point2D<double>(centerX, centerY), teachWindow);
193 }
194 catch (const std::exception & e)
195 {
196 QMessageBox::critical(this, "Error", e.what());
197 }
198}
199
200// Run a search (search button clicked)
201void MainWidget::HandleSearch()
202{
203 if (!classifier_)
204 {
205 QMessageBox::warning(this, "SF2 Search", "Please create (train) or load a model/classifier first.");
206 return;
207 }
208
209 Search();
210}
211
212// Activate the continuous search
213void MainWidget::HandleContSearch(int state)
214{
215 imageScene_->ClearScene();
216
217 if (state == Qt::Checked)
218 continuedSearch_ = true;
219 else
220 continuedSearch_ = false;
221}
222
223template <typename T>
224Cvb::Rect<T> AsRect(const Cvb::RectLT<T>& rectLT)
225{
226 return Cvb::Rect<T>(Cvb::Point2D<T>(rectLT.Location()), Cvb::Size2D<T>(rectLT.Size()));
227}
228
229// Area has been selected
230void MainWidget::HandleSelection(QRectF selection)
231{
232 Cvb::Area2D area(AsRect(Cvb::UI::QtToCvb(selection)));
233 // Convert the rectangle to pixel coordinates
234 auto convertedArea = imageView_->Image()->ImageToPixelCoordinates(area);
235 // Get the bounds
236 Cvb::Rect<double> boundingRect = convertedArea.BoundingRectangle();
237 // Get the selected part of the image
238 selection_ = imageView_->Image()->Map(Cvb::Rect<int>(boundingRect.Left(), boundingRect.Top(), boundingRect.Right(), boundingRect.Bottom()));
239 isSelected_ = true;
240
241 selectionRect_ = boundingRect;
242}
243
244// Run the search on the classifier loaded
245void MainWidget::Search()
246{
247 if (!classifier_)
248 return;
249
250 Cvb::ShapeFinder2::PrecisionMode mode = Cvb::ShapeFinder2::PrecisionMode::CorrelationFine; // Defines how many and which search phases will be carried out.
251 double relativeThreshold = 0.55; // Defines the quality span between the best and the worst result candidate.
252 int minimumThreshold = 20; // Absolute quality threshold a result must exceed to make it into the result list.
253 int coarseLocality = 10; // Minimum distance for solutions in the coarse layer before correlation hill climbing happens.
254
255 if (isSelected_)
256 {
257 Cvb::Rect<int> aoi(selectionRect_.Left(), selectionRect_.Top(), selectionRect_.Right(), selectionRect_.Bottom());
258 searchResult_ = classifier_->SearchAll(imageView_->Image()->Plane(0), aoi, mode, relativeThreshold, minimumThreshold, coarseLocality);
259 }
260 else
261 {
262 searchResult_ = classifier_->SearchAll(imageView_->Image()->Plane(0), imageView_->Image()->Bounds(), mode, relativeThreshold, minimumThreshold, coarseLocality);
263 }
264
265 emit SearchDone();
266}
267
268// Display the search result (result info and overlay)
269void MainWidget::ShowSearchResult()
270{
271 isSelected_ = false;
272 ctrlWidget_->SetResultInfo(searchResult_.size());
273 imageScene_->SetSearchResult(*imageView_->Image(), searchResult_);
274}
275
276
277ControlWidget::ControlWidget(QWidget* parent)
278 : QWidget(parent)
279{
280 auto mainLayout = new QGridLayout;
281
282 trainImageView_ = new Cvb::UI::ImageView(this);
283 trainImageView_->SetUploadMode(Cvb::UI::UploadMode::Image);
284 trainImageView_->SetRenderEngine(Cvb::UI::RenderEngine::Raster);
285
286 QPushButton* openImgBtn = new QPushButton(tr("Open Image"));
287 QObject::connect(openImgBtn, SIGNAL(clicked()), parent, SLOT(HandleLoad()));
288
289 grabCheckBox_ = new QCheckBox(tr("Grab"));
290 QObject::connect(grabCheckBox_, SIGNAL(stateChanged(int)), parent, SLOT(HandleGrab(int)));
291
292 QPushButton* snapBtn = new QPushButton(tr("Snap"));
293 QObject::connect(snapBtn, SIGNAL(clicked()), parent, SLOT(HandleSnap()));
294
295 QPushButton* saveBtn = new QPushButton(tr("Save"));
296 QObject::connect(saveBtn, SIGNAL(clicked()), parent, SLOT(HandleSave()));
297
298 contSearchCheckBox_ = new QCheckBox(tr("Continued Search"));
299 QObject::connect(contSearchCheckBox_, SIGNAL(stateChanged(int)), parent, SLOT(HandleContSearch(int)));
300
301 QGroupBox* groupBox = new QGroupBox(tr(""));
302
303 QPushButton* loadModelBtn = new QPushButton(tr("Load Model"));
304 QObject::connect(loadModelBtn, SIGNAL(clicked()), parent, SLOT(HandleLoadModel()));
305
306 QPushButton* saveModelBtn = new QPushButton(tr("Save Model"));
307 QObject::connect(saveModelBtn, SIGNAL(clicked()), parent, SLOT(HandleSaveModel()));
308
309 QPushButton* trainBtn = new QPushButton(tr("Train"));
310 QObject::connect(trainBtn, SIGNAL(clicked()), parent, SLOT(HandleTrain()));
311
312 QPushButton* searchBtn = new QPushButton(tr("Search"));
313 QObject::connect(searchBtn, SIGNAL(clicked()), parent, SLOT(HandleSearch()));
314
315 resultLabel_ = new QLabel(tr("Number of search results: 0"));
316
317 QGridLayout* gbLayout = new QGridLayout;
318 gbLayout->addWidget(trainBtn, 0, 0);
319 gbLayout->addWidget(loadModelBtn, 0, 1);
320 gbLayout->addWidget(searchBtn, 1, 0);
321 gbLayout->addWidget(saveModelBtn, 1, 1);
322 gbLayout->addWidget(resultLabel_, 2, 0, 1, -1);
323 groupBox->setLayout(gbLayout);
324
325 mainLayout->addWidget(trainImageView_, 0, 0, 1, -1);
326 mainLayout->addWidget(openImgBtn, 1, 0, 1, 1);
327 mainLayout->addWidget(grabCheckBox_, 1, 1, 1, 1);
328 mainLayout->addWidget(snapBtn, 1, 2, 1, 1);
329 mainLayout->addWidget(saveBtn, 2, 0, 1, 1);
330 mainLayout->addWidget(contSearchCheckBox_, 2, 1, 1, -1);
331 mainLayout->addWidget(groupBox, 3, 0, 1, -1);
332
333 setLayout(mainLayout);
334}
335
336void ControlWidget::EnableGrabCheckBox(bool value)
337{
338 grabCheckBox_->setEnabled(value);
339}
340
341void ControlWidget::SetResultInfo(size_t numResults)
342{
343 QString count = "Number of search results: " + QString::number(numResults);
344 resultLabel_->setText(count);
345}
346
347void ControlWidget::SetTrainView(const Cvb::Image & image)
348{
349 if (trainImageView_)
350 trainImageView_->Refresh(image);
351}
352
353
354CustomImageScene::CustomImageScene(QWidget* parent)
355 : Cvb::UI::ImageScene(parent)
356{}
357
358void CustomImageScene::SetSearchResult(const Cvb::Image & image, std::vector<Cvb::ShapeFinder2::SearchResult> result)
359{
360 // Clear the scene
361 ClearScene();
362
363 searchResult_ = result;
364
365 // Draw overlays for search results
366 for (int i = 0; i < searchResult_.size(); i++)
367 {
368 Cvb::ShapeFinder2::SearchResult res = result.at(i);
369 double x = res.X();
370 double y = res.Y();
371
372 // Draw a small rectangle at the result pixel location
373 auto point = image.PixelToImageCoordinates(Cvb::Point2D<double>(x, y));
374 QGraphicsRectItem* item = new QGraphicsRectItem(QRectF(point.X(), point.Y(), 5, 5));
375 item->setBrush(QBrush(Qt::red));
376 this->addItem(item);
377
378 // Draw a label right beside the pixel
379 QString label = "Q: " + QString::number(res.Quality(), 'f', 2) + ", A: " + QString::number(res.Rotation().Deg(), 'f', 2);
380 QGraphicsRectItem* textLabel = new QGraphicsRectItem(QRectF(point.X() + 5, point.Y() + 5, 100, 15));
381 textLabel->setBrush(QBrush(Qt::red));
382 this->addItem(textLabel);
383 QGraphicsTextItem* text = this->addText(label);
384 text->setPos(point.X() + 5, point.Y() + 2.5);
385 text->setDefaultTextColor(Qt::black);
386 }
387}
388
389void CustomImageScene::ClearScene()
390{
391 this->clear();
392 this->update();
393}
394
395void CustomImageScene::mousePressEvent(QGraphicsSceneMouseEvent* event)
396{
397 ClearScene();
398 this->ImageView()->setDragMode(QGraphicsView::RubberBandDrag);
399
400 // remember the start point
401 pointStart_ = event->scenePos();
402}
403
404void CustomImageScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
405{
406 // remember the end point
407 pointEnd_ = event->scenePos();
408 // draw a rectangle to mark the selection
409 this->addRect(QRectF(pointStart_, pointEnd_), QPen(Qt::blue, 0));
410 // signal to react to the selection
411 emit SelectionDone(QRectF(pointStart_, pointEnd_));
412}
double Deg() const noexcept
Get the value in degrees.
Definition: angle.hpp:87
Structure that represents an area of interest in the image.
Definition: area_2d.hpp:21
static std::shared_ptr< T > Open(const String &provider, AcquisitionStack acquisitionStack=AcquisitionStack::PreferVin)
Opens a device with the given provider with its default board and port (if applicable).
Definition: decl_device_factory.hpp:55
static std::unique_ptr< Image > Load(const String &fileName)
Loads an image with the given file name.
Definition: detail_image.hpp:32
T Bottom() const noexcept
Gets bottom row of the rectangle (still inside the rectangle).
Definition: rect.hpp:151
T Top() const noexcept
Gets first row of the rectangle.
Definition: rect.hpp:111
T Right() const noexcept
Gets rightmost column of the rectangle (still inside the rectangle).
Definition: rect.hpp:131
T Left() const noexcept
Gets first column of the rectangle.
Definition: rect.hpp:91
Rectangle object.
Definition: rect_lt.hpp:24
Size2D< T > Size() const noexcept
Gets the size of the rectangle.
Definition: rect_lt.hpp:205
Point2D< T > Location() const noexcept
Gets the location of the top left corner of the rectangle.
Definition: rect_lt.hpp:226
ShapeFinder2 classifier factory object.
Definition: classifier_factory.hpp:27
std::unique_ptr< Classifier > Learn(const ImagePlane &plane, Point2D< double > position, Rect< int > teachWindow, const std::vector< Point2D< int > > &dontCarePoints) const
Creates a ShapeFinder2 classifier from plane 0 of the input image.
Definition: classifier_factory.hpp:263
static std::unique_ptr< Classifier > Create(const String &fileName)
Creates a classifier object loading a classifier file.
Definition: classifier.hpp:64
Search result as returned by the classifier.
Definition: search_result.hpp:24
double Quality() const noexcept
Quality measure of the result.
Definition: search_result.hpp:77
Angle Rotation() const noexcept
Rotation angle of the result.
Definition: search_result.hpp:97
double Y() const noexcept
Y position at which the object has been found.
Definition: search_result.hpp:67
double X() const noexcept
X position at which the object has been found.
Definition: search_result.hpp:57
Stores a pair of numbers that represents the width and the height of a subject, typically a rectangle...
Definition: size_2d.hpp:20
T count(T... args)
PrecisionMode
Controls precision over accuracy for ShapeFinder 1 type searches.
Definition: shapefinder2.hpp:47
@ CorrelationFine
In the CorrelationFine mode, after the initial edge model search a correlation and hill climbing will...
Cvb::String QtToCvb(const QString text) noexcept
Convenience converter for strings.
Definition: ui.hpp:238
QString CvbToQt(const Cvb::String &text) noexcept
Convenience converter for strings.
Definition: ui.hpp:253
void setBrush(const QBrush &brush)
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
void setPos(const QPointF &pos)
void setDefaultTextColor(const QColor &col)
void addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
QMessageBox::StandardButton critical(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString number(int n, int base)
void setLayout(QLayout *layout)