DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
QtUtil.cpp
Go to the documentation of this file.
1// This file is part of DynExp.
2
3#include "stdafx.h"
4#include "moc_QtUtil.cpp"
5#include "QtUtil.h"
6
7// Placed here to avoid circular dependencies
8#include "DynExpCore.h"
9
10namespace Util
11{
12 const QLocale& GetDefaultQtLocale()
13 {
14 static QLocale Locale(QLocale::Language::English, QLocale::Country::UnitedStates);
15
16 return Locale;
17 }
18
19 std::vector<QDomNode> GetChildDOMNodes(const QDomElement& Parent, const QString& ChildTagName)
20 {
21 if (Parent.isNull())
22 throw Util::InvalidDataException("Error parsing XML tree. The given parent node is invalid.");
23
24 // Must be filtered in the following since it also contains nodes which are down deeper in the
25 // DOM hierarchy (not only direct childs).
26 auto ChildNodeList = Parent.elementsByTagName(ChildTagName);
27
28 std::vector<QDomNode> Nodes;
29 for (int i = 0; i < ChildNodeList.length(); ++i)
30 if (ChildNodeList.at(i).parentNode() == Parent)
31 Nodes.push_back(ChildNodeList.at(i));
32
33 return Nodes;
34 }
35
36 QDomNode GetSingleChildDOMNode(const QDomElement& Parent, const QString& ChildTagName)
37 {
38 if (Parent.isNull())
39 throw Util::InvalidDataException("Error parsing XML tree. The given parent node is invalid.");
40
41 auto ChildNodeList = Parent.elementsByTagName(ChildTagName);
42 int FoundDirectChildIndex = -1;
43 for (int i = 0; i < ChildNodeList.length(); ++i)
44 {
45 if (ChildNodeList.at(i).parentNode() == Parent)
46 {
47 if (FoundDirectChildIndex < 0)
48 FoundDirectChildIndex = i;
49 else
51 "Error parsing XML tree. Expecting exactly one node <" + ChildTagName.toStdString() + ">.");
52 }
53 }
54
55 if (FoundDirectChildIndex < 0)
57 "Node <" + ChildTagName.toStdString() + "> has not been found in XML tree.");
58
59 return ChildNodeList.item(FoundDirectChildIndex);
60 }
61
62 QDomElement GetSingleChildDOMElement(const QDomElement& Parent, const QString& ChildTagName)
63 {
64 auto DOMElement = GetSingleChildDOMNode(Parent, ChildTagName).toElement();
65
66 if (DOMElement.isNull())
68 "Error parsing XML tree. The node <" + ChildTagName.toStdString() + "> is not a DOM element.");
69
70 return DOMElement;
71 }
72
73 std::string GetStringFromDOMElement(const QDomElement& Parent, const QString& ChildTagName)
74 {
75 return GetSingleChildDOMElement(Parent, ChildTagName).text().toStdString();
76 }
77
81 template <>
82 std::string GetTFromDOMElement(const QDomElement& Parent, const QString& ChildTagName)
83 {
84 return GetStringFromDOMElement(Parent, ChildTagName);
85 }
86
87 QDomAttr GetDOMAttribute(const QDomElement& Element, const QString& AttributeName)
88 {
89 if (Element.isNull())
90 throw Util::InvalidDataException("Error parsing XML tree. The given node is invalid.");
91
92 auto Attr = Element.attributes().namedItem(AttributeName).toAttr();
93 if (Attr.isNull())
94 throw Util::InvalidDataException("Error parsing XML tree. A node contains invalid attributes.");
95
96 return Attr;
97 }
98
99 std::string GetStringFromDOMAttribute(const QDomElement& Element, const QString& AttributeName)
100 {
101 return GetDOMAttribute(Element, AttributeName).value().toStdString();
102 }
103
107 template <>
108 std::string GetTFromDOMAttribute(const QDomElement& Element, const QString& AttributeName)
109 {
110 return GetStringFromDOMAttribute(Element, AttributeName);
111 }
112
113 QString PromptOpenFilePath(QWidget* Parent,
114 const QString& Title, const QString& DefaultSuffix, const QString& NameFilter, const QString& InitialDirectory)
115 {
116 QFileDialog FileDialog(Parent, Title);
117 FileDialog.setAcceptMode(QFileDialog::AcceptMode::AcceptOpen);
118 FileDialog.setFilter(QDir::Filter::Files);
119 FileDialog.setFileMode(QFileDialog::FileMode::ExistingFile);
120 FileDialog.setDefaultSuffix(DefaultSuffix);
121 FileDialog.setNameFilter(NameFilter);
122 if (!InitialDirectory.isEmpty())
123 FileDialog.setDirectory(InitialDirectory);
124
125 return FileDialog.exec() == QDialog::Accepted ? *FileDialog.selectedFiles().begin() : "";
126 }
127
128 QString PromptSaveFilePath(QWidget* Parent,
129 const QString& Title, const QString& DefaultSuffix, const QString& NameFilter, const QString& InitialDirectory)
130 {
131 QFileDialog FileDialog(Parent, Title);
132 FileDialog.setAcceptMode(QFileDialog::AcceptMode::AcceptSave);
133 FileDialog.setFilter(QDir::Filter::Files);
134 FileDialog.setFileMode(QFileDialog::FileMode::AnyFile);
135 FileDialog.setDefaultSuffix(DefaultSuffix);
136 FileDialog.setNameFilter(NameFilter);
137 if (!InitialDirectory.isEmpty())
138 FileDialog.setDirectory(InitialDirectory);
139
140 return FileDialog.exec() == QDialog::Accepted ? *FileDialog.selectedFiles().begin() : "";
141 }
142
143 QString PromptSaveFilePathModule(DynExp::QModuleWidget* Parent, const QString& Title, const QString& DefaultSuffix, const QString& NameFilter)
144 {
145 const auto FilePath = PromptSaveFilePath(Parent, Title, DefaultSuffix, NameFilter, QString::fromStdString(Parent->GetDataSaveDirectory()));
146
147 if (!FilePath.isEmpty())
148 Parent->SetDataSaveDirectory(FilePath.toStdString());
149
150 return FilePath;
151 }
152
153 QImage QImageFromBlobData(BlobDataType&& BlobData, int Width, int Height, int BytesPerLine, QImage::Format Format)
154 {
155 if (!Width || !Height || !BytesPerLine || Format == QImage::Format::Format_Invalid)
157 "Width, Height and BytesPerLine cannot be zero, Format must describe a valid image format.");
158
159 if (!BlobData.GetPtr())
160 return {};
161
162 // Probably not exception-safe if QImage constructor throws.
163 auto BufferPtr = BlobData.Release();
164 return QImage(BufferPtr, Width, Height, BytesPerLine, Format, [](void* Info) {
165 // Ugly due to an ugly QImage implementation...
166 auto CastInfo = static_cast<decltype(BufferPtr)>(Info);
167 delete[] CastInfo;
168 }, BufferPtr);
169 }
170
172 {
173 auto IntensityImage = Image.convertToFormat(QImage::Format_Grayscale8);
174 const unsigned char* DataPtr = IntensityImage.constBits();
175
176 // Initialize everything to 0 by {}.
177 ImageHistogramType Histogram{};
178
179 for (auto i = IntensityImage.height() * IntensityImage.width(); i > 0; --i)
180 ++Histogram[*DataPtr++];
181
182 // Histogram moved by copy elision.
183 return Histogram;
184 }
185
187 {
188 auto RGBImage = Image.convertToFormat(QImage::Format_RGB888);
189 const unsigned char* DataPtr = RGBImage.constBits();
190
191 // Initialize everything to 0 by {}.
192 ImageHistogramType HistogramR{}, HistogramG{}, HistogramB{};
193
194 for (auto i = RGBImage.height() * RGBImage.width(); i > 0; --i)
195 {
196 ++HistogramR[*DataPtr++];
197 ++HistogramG[*DataPtr++];
198 ++HistogramB[*DataPtr++];
199 }
200
201 return { std::move(HistogramR), std::move(HistogramG), std::move(HistogramB) };
202 }
203
205 {
206 // Initialize everything to 0 by {}.
207 ImageHistogramType IntensityHistogram{};
208
209 for (int i = 0; i < 256; ++i)
210 IntensityHistogram[i] = (std::get<0>(RGBHistogram)[i] + std::get<1>(RGBHistogram)[i] + std::get<2>(RGBHistogram)[i]) / 3.f;
211
212 // IntensityHistogram moved by copy elision.
213 return IntensityHistogram;
214 }
215
216 QPolygonF MakeCrossPolygon(QPointF Center, unsigned int ArmLength)
217 {
218 return QPolygonF({
219 Center,
220 QPointF(Center.x() - ArmLength, Center.y()),
221 QPointF(Center.x() + ArmLength, Center.y()),
222 Center,
223 QPointF(Center.x(), Center.y() - ArmLength),
224 QPointF(Center.x(), Center.y() + ArmLength),
225 Center,
226 });
227 }
228
229 void ActivateWindow(QWidget& Widget)
230 {
231 Widget.setWindowState((Widget.windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
232 Widget.raise(); // for MacOS
233 Widget.activateWindow(); // for Windows
234 }
235
236 bool SaveToFile(const QString& Filename, std::string_view Text)
237 {
238 QFile File(Filename);
239
240 // QIODevice::WriteOnly implies QIODeviceBase::Truncate.
241 if (!File.open(QIODevice::WriteOnly | QIODevice::Text))
242 return false;
243
244 const auto BytesWriten = File.write(Text.data(), Text.size());
245 File.close();
246
247 return BytesWriten >= 0;
248 }
249
250 std::string ReadFromFile(const QString& Filename)
251 {
252 QFile File(Filename);
253 if (!File.open(QIODevice::ReadOnly | QIODevice::Text))
254 throw FileIOErrorException(Filename.toStdString());
255
256 auto Content = File.readAll();
257 File.close();
258
259 return Content.toStdString();
260 }
261
262 std::string ReadFromFile(const std::string& Filename)
263 {
264 return ReadFromFile(QString::fromStdString(Filename));
265 }
266
267 std::string ReadFromFile(const std::filesystem::path& Filename)
268 {
269 return ReadFromFile(Filename.string());
270 }
271
280
282 {
283 static const DynExp::DynExpCore* const Core = DynExpCore;
284
285 if (!Core)
286 throw Util::InvalidArgException("Core cannot be nullptr.");
287
288 return *Core;
289 }
290
291 void MarkerGraphicsView::MarkerType::SetName(std::string_view NewName)
292 {
293 Name = NewName;
294
295 if (Marker)
296 Marker->setToolTip(QString::fromStdString(Name));
297 }
298
300 : QGraphicsView(parent), MarkersHidden(false), MarkersChanged(true),
301 ContextMenu(new QMenu(this)), EditMarkersAction(nullptr), ShowMarkersAction(nullptr), RemoveMarkersAction(nullptr)
302 {
303 EditMarkersAction = ContextMenu->addAction("&Edit Markers");
304 EditMarkersAction->setCheckable(true);
305 EditMarkersAction->setChecked(false);
306 ShowMarkersAction = ContextMenu->addAction("S&how Markers", this, &MarkerGraphicsView::OnShowMarkers, QKeySequence(Qt::Key_NumberSign));
307 addAction(ShowMarkersAction); // for shortcuts
308 ShowMarkersAction->setCheckable(true);
309 ShowMarkersAction->setChecked(true);
310 RemoveMarkersAction = ContextMenu->addAction(QIcon(DynExpUI::Icons::Delete), "&Remove all Markers", this, &MarkerGraphicsView::OnRemoveMarkers);
311 SaveMarkersAction = ContextMenu->addAction(QIcon(DynExpUI::Icons::Save), "Sa&ve Markers to File", this, &MarkerGraphicsView::OnSaveMarkers);
312
313 setContextMenuPolicy(Qt::CustomContextMenu);
314 connect(this, &MarkerGraphicsView::customContextMenuRequested, this, &MarkerGraphicsView::OnContextMenuRequested);
315 }
316
317 void MarkerGraphicsView::mousePressEvent(QMouseEvent* Event)
318 {
319 if (!scene())
320 return;
321
322 auto LocalPoint = mapFromGlobal(Event->globalPos());
323 const auto MarkerPos = mapToScene(LocalPoint).toPoint();
324
325 if (!MarkersHidden && EditMarkersAction->isChecked() && Event->button() == Qt::MouseButton::LeftButton
326 && !items(LocalPoint).empty()) // Allow markers only on top of the displayed content - not on empty space.
327 {
328 auto HighestIDMarker = std::max_element(Markers.cbegin(), Markers.cend(), [](const auto& a, const auto& b) {
329 return a.GetID() < b.GetID();
330 });
331 auto NewID = HighestIDMarker != Markers.cend() && HighestIDMarker->GetID() >= 0 ? HighestIDMarker->GetID() + 1 : 0;
332
333 AddMarker(MarkerPos, QColorConstants::Magenta, true, NewID);
334 }
335
336 if (!EditMarkersAction->isChecked() && Event->button() == Qt::MouseButton::LeftButton && !items(LocalPoint).empty())
337 emit mouseClickEvent(MarkerPos);
338 }
339
341 {
342 if (!scene() || MarkersHidden)
343 return;
344
345 for (auto it = Markers.begin(); it != Markers.end();)
346 if (it->GetMarker()->isUnderMouse() && it->IsUserDeletable())
347 {
348 if (EditMarkersAction->isChecked())
349 {
350 scene()->removeItem(it->GetMarker());
351 it = Markers.erase(it);
352
353 MarkersChanged = true;
354 }
355 else
356 {
357 bool OKClicked = false;
358 QString Name = QInputDialog::getText(this, "Edit name",
359 QString("Enter name of marker at position (") + QString::number(it->GetMarkerPos().x())
360 + QString(", ") + QString::number(it->GetMarkerPos().y()) + QString("):"),
361 QLineEdit::Normal, it->GetName().data(), &OKClicked);
362
363 if (OKClicked)
364 {
365 it->SetName(Name.toStdString());
366
367 MarkersChanged = true;
368 }
369
370 return;
371 }
372 }
373 else
374 ++it;
375 }
376
377 void MarkerGraphicsView::wheelEvent(QWheelEvent* Event)
378 {
379 if (Event->modifiers().testFlag(Qt::KeyboardModifier::ControlModifier))
380 {
381 if (Event->angleDelta().y() < 0)
382 ZoomOut();
383 if (Event->angleDelta().y() > 0)
384 ZoomIn();
385 }
386 else
387 QGraphicsView::wheelEvent(Event);
388 }
389
391 {
392 bool Changed = MarkersChanged;
393 MarkersChanged = false;
394
395 return Changed;
396 }
397
398 void MarkerGraphicsView::AddMarker(const QPoint& MarkerPos, const QColor& Color, bool IsUserDeletable, MarkerType::IDType ID, std::string Name)
399 {
400 if (!scene())
401 return;
402
403 float ScaleFactor = std::min(scene()->height(), scene()->width()) / 300;
404 QPolygonF MarkerPolygon = Util::MakeCrossPolygon(MarkerPos, 5 * ScaleFactor);
405 Markers.emplace_back(scene()->addPolygon(MarkerPolygon, QPen(Color, ScaleFactor)), MarkerPos, IsUserDeletable, ID, CurrentImagePos);
406 Markers.back().GetMarker()->setOpacity(DeselectedMarkerOpacity);
407 Markers.back().GetMarker()->setVisible(!MarkersHidden);
408 Markers.back().SetName(Name);
409
410 MarkersChanged = true;
411 }
412
413 void MarkerGraphicsView::RemoveMarker(size_t Index, bool OnlyUserDeletableMarkers)
414 {
415 if (!scene())
416 return;
417 if (Index >= Markers.size())
418 throw OutOfRangeException("The given marker index exceeds the amount of markers stored in this MarkerGraphicsView.");
419
420 auto Marker = Markers.cbegin() + Index;
421 if (!OnlyUserDeletableMarkers || Marker->IsUserDeletable())
422 {
423 scene()->removeItem(Marker->GetMarker());
424 Markers.erase(Marker);
425
426 MarkersChanged = true;
427 }
428 }
429
430 void MarkerGraphicsView::RemoveMarker(const QPoint& MarkerPos, bool OnlyUserDeletableMarkers)
431 {
432 if (!scene())
433 return;
434
435 for (auto it = Markers.cbegin(); it != Markers.cend();)
436 if (it->GetMarkerPos() == MarkerPos && (!OnlyUserDeletableMarkers || it->IsUserDeletable()))
437 {
438 scene()->removeItem(it->GetMarker());
439 it = Markers.erase(it);
440
441 MarkersChanged = true;
442 }
443 else
444 ++it;
445 }
446
447 void MarkerGraphicsView::RemoveMarker(std::string_view Name, bool OnlyUserDeletableMarkers)
448 {
449 if (!scene())
450 return;
451
452 for (auto it = Markers.cbegin(); it != Markers.cend();)
453 if (it->GetName() == Name && (!OnlyUserDeletableMarkers || it->IsUserDeletable()))
454 {
455 scene()->removeItem(it->GetMarker());
456 it = Markers.erase(it);
457
458 MarkersChanged = true;
459 }
460 else
461 ++it;
462 }
463
464 void MarkerGraphicsView::RemoveMarkers(bool OnlyUserDeletableMarkers)
465 {
466 if (!scene())
467 return;
468
469 for (auto it = Markers.cbegin(); it != Markers.cend();)
470 if (!OnlyUserDeletableMarkers || it->IsUserDeletable())
471 {
472 scene()->removeItem(it->GetMarker());
473 it = Markers.erase(it);
474
475 MarkersChanged = true;
476 }
477 else
478 ++it;
479 }
480
482 {
483 this->MarkersHidden = MarkersHidden;
484
485 for (auto it = Markers.cbegin(); it != Markers.cend(); ++it)
486 it->GetMarker()->setVisible(!MarkersHidden);
487 }
488
489 void MarkerGraphicsView::RenameMarker(const QPoint& MarkerPos, std::string_view NewName)
490 {
491 for (auto& Marker : Markers)
492 if (Marker.GetMarkerPos() == MarkerPos)
493 {
494 Marker.SetName(NewName);
495
496 MarkersChanged = true;
497 }
498 }
499
500 void MarkerGraphicsView::SelectMarker(const QPoint& MarkerPos)
501 {
502 for (auto& Marker : Markers)
503 Marker.GetMarker()->setOpacity(Marker.GetMarkerPos() == MarkerPos ? SelectedMarkerOpacity : DeselectedMarkerOpacity);
504 }
505
507 {
508 for (auto& Marker : Markers)
509 Marker.GetMarker()->setOpacity(DeselectedMarkerOpacity);
510 }
511
513 {
514 scale(ZoomFactor, ZoomFactor);
515 }
516
518 {
519 scale(1 / ZoomFactor, 1 / ZoomFactor);
520 }
521
523 {
524 resetTransform();
525 }
526
528 {
529 // Except ShowMarkersAction since this action only affects how the markers are displayed.
530 EditMarkersAction->setEnabled(Enable);
531 RemoveMarkersAction->setEnabled(Enable);
532 SaveMarkersAction->setEnabled(Enable);
533 }
534
536 {
537 ContextMenu->exec(mapToGlobal(Position));
538 }
539
541 {
542 setMarkersHidden(!Checked);
543 }
544
546 {
547 RemoveMarkers(true);
548 }
549
551 {
552 if (Markers.empty())
553 {
554 QMessageBox::warning(this, "DynExp - Error", "There are not any markers set.");
555 return;
556 }
557
558 auto Filename = Util::PromptSaveFilePath(this, "Save markers to file", ".csv", " Comma-separated values file (*.csv)");
559 if (Filename.isEmpty())
560 return;
561
562 std::stringstream CSVData;
563 CSVData << std::setprecision(9) << "ID;X(px);Y(px);ImagePosX(nm);ImagePosY(nm);Name\n";
564
565 for (const auto& Marker : Markers)
566 CSVData << Marker.GetID() << ";" << Marker.GetMarkerPos().x() << ";" << Marker.GetMarkerPos().y() << ";"
567 << Marker.GetImagePos().x() << ";" << Marker.GetImagePos().y() << ";"
568 << Marker.GetName() << "\n";
569
570 if (!Util::SaveToFile(Filename, CSVData.str()))
571 QMessageBox::warning(this, "DynExp - Error", "Error writing data to file.");
572 }
573
574 void QSortingListWidget::dropEvent(QDropEvent* event)
575 {
576 QListWidget::dropEvent(event);
577
578 sortItems();
579 }
580
581 bool NumericSortingTableWidgetItem::operator<(const QTableWidgetItem& Other) const
582 {
583 return GetDefaultQtLocale().toDouble(text()) < GetDefaultQtLocale().toDouble(Other.text());
584 }
585
586 QTableWidgetItem* NumericSortingTableWidgetItem::clone() const
587 {
588 return new NumericSortingTableWidgetItem(*this);
589 }
590
591 QWidget* NumericOnlyItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
592 {
593 auto LineEdit = new QLineEdit(parent);
594 auto Validator = new QDoubleValidator(min, max, precision, LineEdit);
595 Validator->setLocale(GetDefaultQtLocale());
596 LineEdit->setValidator(Validator);
597
598 return LineEdit;
599 }
600}
Defines DynExp's core module as an interface between the UI and DynExp objects.
Provides utilities related to Qt and Qt widgets within DynExp's Util namespace.
DynExp's core class acts as the interface between the user interface and DynExp's internal data like ...
Definition DynExpCore.h:127
void MoveQWorkerToWorkerThread(Util::QWorker &Worker, ItemIDType ID) const
Moves a Util::QWorker instance to WorkerThread to run its Qt event queue there. This method is thread...
Window class for Qt-based user interfaces belonging to DynExp modules. User interface Qt window class...
Definition Module.h:1079
std::string GetDataSaveDirectory() const
Recalls a path where modules might save recorded data to. Used by Util::PromptSaveFilePathModule() to...
Definition Module.cpp:431
void SetDataSaveDirectory(std::string_view Directory) const
Sets a path where modules might save recorded data to. Used by Util::PromptSaveFilePathModule() to st...
Definition Module.cpp:436
Data type which manages a binary large object. The reserved memory is freed upon destruction.
Definition Util.h:517
Thrown when reading from or writing to a file failed.
Definition Exception.h:315
An invalid argument like a null pointer has been passed to a function.
Definition Exception.h:137
Data to operate on is invalid for a specific purpose. This indicates a corrupted data structure or fu...
Definition Exception.h:163
void OnSaveMarkers(bool)
Asks the user for a file name and saves all markers to a CSV file.
Definition QtUtil.cpp:550
void OnContextMenuRequested(QPoint Position)
Shows the context menu at position Position.
Definition QtUtil.cpp:535
virtual void mousePressEvent(QMouseEvent *Event) override
Adds a marker to the mouse pointer position assigning the highest ID amongst all markers in the graph...
Definition QtUtil.cpp:317
QAction * SaveMarkersAction
Definition QtUtil.h:557
bool MarkersChanged
Holds whether the markers have changed by any of the marker operations.
Definition QtUtil.h:547
void ZoomReset()
Resets the zoom.
Definition QtUtil.cpp:522
void DeselectMarkers()
Deselects all selected markers.
Definition QtUtil.cpp:506
void EnableActions(bool Enable)
Definition QtUtil.cpp:527
QAction * ShowMarkersAction
Definition QtUtil.h:555
static constexpr double DeselectedMarkerOpacity
Determines the opacity of a marker which is not selected.
Definition QtUtil.h:383
void setMarkersHidden(bool MarkersHidden)
Hides or shows all markers.
Definition QtUtil.cpp:481
void RenameMarker(const QPoint &MarkerPos, std::string_view NewName)
Assigns a name to the marker at position MarkerPos. Affects MarkersChanged.
Definition QtUtil.cpp:489
void SelectMarker(const QPoint &MarkerPos)
Selects the marker at position MarkerPos.
Definition QtUtil.cpp:500
std::vector< MarkerType > Markers
List of the markers.
Definition QtUtil.h:545
bool HaveMarkersChanged() noexcept
Returns whether a marker operation has changed the stored markers. Resets the flag.
Definition QtUtil.cpp:390
void RemoveMarker(size_t Index, bool OnlyUserDeletableMarkers=false)
Removes the n-th marker specified by Index. Affects MarkersChanged.
Definition QtUtil.cpp:413
bool MarkersHidden
Determines whether the markers are currently displayed or not.
Definition QtUtil.h:546
QAction * RemoveMarkersAction
Definition QtUtil.h:556
void AddMarker(const QPoint &MarkerPos, const QColor &Color, bool IsUserDeletable=true, MarkerType::IDType ID=-1, std::string Name={})
Adds a marker to the graphics view at position MarkerPos assigning the properties passed as arguments...
Definition QtUtil.cpp:398
MarkerGraphicsView(QWidget *parent)
Constructs a MarkerGraphicsView.
Definition QtUtil.cpp:299
void ZoomIn()
Zooms in one step.
Definition QtUtil.cpp:512
static constexpr double ZoomFactor
Determines the magnification of one zoom step.
Definition QtUtil.h:382
void OnShowMarkers(bool Checked)
If Checked is true, all markers are made visible, otherwise they become hidden.
Definition QtUtil.cpp:540
void ZoomOut()
Zooms out one step.
Definition QtUtil.cpp:517
static constexpr double SelectedMarkerOpacity
Determines the opacity of a selected marker.
Definition QtUtil.h:384
virtual void mouseDoubleClickEvent(QMouseEvent *Event) override
Removes the marker at the mouse pointer position if it is user-deletable. Affects MarkersChanged.
Definition QtUtil.cpp:340
QPointF CurrentImagePos
Sample position where the image has been recorded (in nm). Refer to MarkerType::ImagePos.
Definition QtUtil.h:548
void OnRemoveMarkers(bool)
Removes all user-deletable markers. Affects MarkersChanged.
Definition QtUtil.cpp:545
virtual void wheelEvent(QWheelEvent *Event) override
Zooms in or out when Control is pressed on the keyboard at the same time.
Definition QtUtil.cpp:377
void mouseClickEvent(QPoint Position)
void RemoveMarkers(bool OnlyUserDeletableMarkers)
Removes all markers from the graphics view. Affects MarkersChanged.
Definition QtUtil.cpp:464
QAction * EditMarkersAction
Definition QtUtil.h:554
Thrown when a requested ressource does not exist.
Definition Exception.h:236
virtual QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
Definition QtUtil.cpp:591
bool operator<(const QTableWidgetItem &Other) const
Compares the content of this table widget item with the content of another table widget item by conve...
Definition QtUtil.cpp:581
virtual QTableWidgetItem * clone() const override
Definition QtUtil.cpp:586
Thrown when an argument passed to a function exceeds the valid range.
Definition Exception.h:211
virtual void dropEvent(QDropEvent *event) override
Definition QtUtil.cpp:574
static const DynExp::DynExpCore & GetDynExpCore(const DynExp::DynExpCore *DynExpCore=nullptr)
Returns the application's DynExp::DynExpCore instance which is globally set in constructor DynExp::Dy...
Definition QtUtil.cpp:281
friend class DynExp::DynExpCore
Definition QtUtil.h:330
void MoveToWorkerThread(DynExp::ItemIDType ID)
Moves the instance to DynExpCore's worker thread. Do not call from constructor since derived classes ...
Definition QtUtil.cpp:272
bool HasBeenMovedToWorkerThread
Indicates whether the worker has already been moved to the worker thread.
Definition QtUtil.h:370
constexpr auto Delete
size_t ItemIDType
ID type of objects/items managed by DynExp.
DynExp's Util namespace contains commonly used functions and templates as well as extensions to Qt an...
std::string GetTFromDOMAttribute(const QDomElement &Element, const QString &AttributeName)
Definition QtUtil.cpp:108
ImageHistogramType ConvertRGBToIntensityHistogram(const ImageRGBHistogramType &RGBHistogram)
Computes an intensity (grayscale) histogram from a RGB histogram.
Definition QtUtil.cpp:204
bool SaveToFile(const QString &Filename, std::string_view Text)
Saves a std::string_view to a file (using QFile). Creates a new file or truncates an existing file's ...
Definition QtUtil.cpp:236
QDomElement GetSingleChildDOMElement(const QDomElement &Parent, const QString &ChildTagName)
Behaves like GetSingleChildDOMNode() but returns the node converted to a DOM element.
Definition QtUtil.cpp:62
std::string GetTFromDOMElement(const QDomElement &Parent, const QString &ChildTagName)
Definition QtUtil.cpp:82
std::string GetStringFromDOMElement(const QDomElement &Parent, const QString &ChildTagName)
Behaves like GetSingleChildDOMElement() but returns the text from a DOM element.
Definition QtUtil.cpp:73
const QLocale & GetDefaultQtLocale()
Returns the default locale properties to be assigned to Qt widgets.
Definition QtUtil.cpp:12
std::vector< QDomNode > GetChildDOMNodes(const QDomElement &Parent, const QString &ChildTagName)
Finds child nodes with a certain tag name.
Definition QtUtil.cpp:19
QPolygonF MakeCrossPolygon(QPointF Center, unsigned int ArmLength)
Returns a QPolygonF representing a cross-style marker.
Definition QtUtil.cpp:216
QImage QImageFromBlobData(BlobDataType &&BlobData, int Width, int Height, int BytesPerLine, QImage::Format Format)
Converts raw pixel data stored in a Util::BlobDataType object to a QImage transfering the ownership o...
Definition QtUtil.cpp:153
std::array< unsigned long long, 256 > ImageHistogramType
Alias which represents a histogram as a std::array with 256 numeric bins. The lowest (highest) index ...
Definition QtUtil.h:244
QString PromptOpenFilePath(QWidget *Parent, const QString &Title, const QString &DefaultSuffix, const QString &NameFilter, const QString &InitialDirectory)
Opens a file dialog to ask the user to select a single existing file.
Definition QtUtil.cpp:113
ImageHistogramType ComputeIntensityHistogram(const QImage &Image)
Computes an intensity (grayscale) histogram from a QImage object.
Definition QtUtil.cpp:171
void ActivateWindow(QWidget &Widget)
Renders a window active and brings it to the front.
Definition QtUtil.cpp:229
std::string ReadFromFile(const QString &Filename)
Reads the entire content from a text file.
Definition QtUtil.cpp:250
QDomAttr GetDOMAttribute(const QDomElement &Element, const QString &AttributeName)
Extracts an attribute from a DOM element.
Definition QtUtil.cpp:87
QDomNode GetSingleChildDOMNode(const QDomElement &Parent, const QString &ChildTagName)
Finds a single child node with a certain tag name.
Definition QtUtil.cpp:36
std::tuple< ImageHistogramType, ImageHistogramType, ImageHistogramType > ImageRGBHistogramType
Alias which represents a RGB histogram as a std::tuple of three ImageHistogramType elements....
Definition QtUtil.h:250
QString PromptSaveFilePath(QWidget *Parent, const QString &Title, const QString &DefaultSuffix, const QString &NameFilter, const QString &InitialDirectory)
Works as PromptOpenFilePath() but asks the user to select a single file which does not need to exist.
Definition QtUtil.cpp:128
ImageRGBHistogramType ComputeRGBHistogram(const QImage &Image)
Computes a RGB histogram from a QImage object.
Definition QtUtil.cpp:186
QString PromptSaveFilePathModule(DynExp::QModuleWidget *Parent, const QString &Title, const QString &DefaultSuffix, const QString &NameFilter)
Works as PromptOpenFilePath() but asks the user to select a single file which does not need to exist....
Definition QtUtil.cpp:143
std::string GetStringFromDOMAttribute(const QDomElement &Element, const QString &AttributeName)
Behaves like GetDOMAttribute() but returns the text from the attribute.
Definition QtUtil.cpp:99
Accumulates include statements to provide a precompiled header.
QGraphicsPolygonItem * Marker
Qt polygon object to draw the marker onto the graphics view.
Definition QtUtil.h:428
void SetName(std::string_view NewName)
Definition QtUtil.cpp:291
std::string Name
Name of the marker to describe it.
Definition QtUtil.h:432