Huge cleanups and added open gl window

This commit is contained in:
feedc0de committed 2022-01-15 01:52:55 +01:00
1 parent a477581f6f
commit ffd4c821ef
525 files changed
+1320 -35862

No files matched your search

@@ -0,0 +1,76 @@
#include "actionscontainerwidget.h"
#include "ui_actionscontainerwidget.h"
#include <QDebug>
#include <QMessageBox>
#include <QMenu>
#include "models/actionscontainermodel.h"
#include "dialogs/codeactiondialog.h"
ActionsContainerWidget::ActionsContainerWidget(QWidget *parent) :
QWidget{parent},
m_ui{std::make_unique<Ui::ActionsContainerWidget>()},
m_actionsModel{std::make_unique<ActionsContainerModel>(this)}
{
m_ui->setupUi(this);
m_ui->listViewActions->setModel(m_actionsModel.get());
connect(m_ui->listViewActions, &QListView::customContextMenuRequested,
this, &ActionsContainerWidget::actionsContextMenuRequested);
connect(m_ui->listViewActions, &QListView::doubleClicked,
this, &ActionsContainerWidget::actionDoubleClicked);
connect(m_actionsModel.get(), &QAbstractItemModel::modelAboutToBeReset,
m_ui->listViewActions, [listView=m_ui->listViewActions](){
listView->setCurrentIndex(QModelIndex{});
});
}
ActionsContainerWidget::~ActionsContainerWidget() = default;
ActionsContainer *ActionsContainerWidget::actionsContainer() const
{
return m_actionsModel->actionsContainer();
}
void ActionsContainerWidget::setActionsContainer(ActionsContainer *actionsContainer)
{
m_actionsModel->setActionsContainer(actionsContainer);
}
void ActionsContainerWidget::actionDoubleClicked(const QModelIndex &index)
{
if (!index.isValid())
return;
auto action = m_actionsModel->getAction(index);
if (!action)
return;
CodeActionDialog dialog{*action, this};
if (dialog.exec() == QDialog::Accepted)
emit changed();
}
void ActionsContainerWidget::actionsContextMenuRequested(const QPoint &pos)
{
const auto index = m_ui->listViewActions->indexAt(pos);
auto action = index.isValid() ? m_actionsModel->getAction(index) : nullptr;
QMenu menu{this};
menu.addAction(tr("&Edit Values"), this, [this,index](){ actionDoubleClicked(index); })->setEnabled(action);
menu.addSeparator();
menu.addAction(tr("C&ut"))->setEnabled(false);
menu.addAction(tr("&Copy"))->setEnabled(false);
menu.addAction(tr("&Paste"))->setEnabled(false);
menu.addSeparator();
menu.addAction(tr("&Delete"))->setEnabled(false);
menu.addSeparator();
menu.addAction(tr("Select &All"))->setEnabled(false);
menu.addSeparator();
menu.addAction(tr("C&lear"))->setEnabled(false);
menu.exec(m_ui->listViewActions->viewport()->mapToGlobal(pos));
}
@@ -0,0 +1,34 @@
#pragma once
#include <QWidget>
#include <memory>
#include "projectcontainer.h"
namespace Ui { class ActionsContainerWidget; }
class ActionsContainerModel;
class ActionsContainerWidget : public QWidget
{
Q_OBJECT
public:
explicit ActionsContainerWidget(QWidget *parent = nullptr);
~ActionsContainerWidget();
ActionsContainer *actionsContainer() const;
void setActionsContainer(ActionsContainer *actionsContainer);
signals:
void changed();
private slots:
void actionDoubleClicked(const QModelIndex &index);
void actionsContextMenuRequested(const QPoint &pos);
private:
const std::unique_ptr<Ui::ActionsContainerWidget> m_ui;
const std::unique_ptr<ActionsContainerModel> m_actionsModel;
};
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ActionsContainerWidget</class>
<widget class="QWidget" name="ActionsContainerWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="labelActions">
<property name="text">
<string>Actions:</string>
</property>
<property name="buddy">
<cstring>listViewActions</cstring>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="listViewActions">
<property name="minimumSize">
<size>
<width>250</width>
<height>0</height>
</size>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QToolBox" name="toolBox">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>136</width>
<height>242</height>
</rect>
</property>
<attribute name="label">
<string>Page 1</string>
</attribute>
</widget>
<widget class="QWidget" name="page_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>136</width>
<height>242</height>
</rect>
</property>
<attribute name="label">
<string>Page 2</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+123
View File
@@ -0,0 +1,123 @@
#include "codeeditorwidget.h"
#include <QPainter>
#include <QTextBlock>
CodeEditorWidget::CodeEditorWidget(QWidget *parent) :
QPlainTextEdit{parent}
{
lineNumberArea = new LineNumberArea(this);
connect(this, &CodeEditorWidget::blockCountChanged,
this, &CodeEditorWidget::updateLineNumberAreaWidth);
connect(this, &CodeEditorWidget::updateRequest,
this, &CodeEditorWidget::updateLineNumberArea);
connect(this, &CodeEditorWidget::cursorPositionChanged,
this, &CodeEditorWidget::highlightCurrentLine);
updateLineNumberAreaWidth(0);
highlightCurrentLine();
}
void CodeEditorWidget::updateLineNumberAreaWidth(int newBlockCount)
{
Q_UNUSED(newBlockCount)
setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
}
int CodeEditorWidget::lineNumberAreaWidth()
{
int digits = 1;
int max = qMax(1, blockCount());
while (max >= 10)
{
max /= 10;
++digits;
}
int space = 3 + fontMetrics().horizontalAdvance(QLatin1Char('9')) * digits;
return std::max(space, 40);
}
void CodeEditorWidget::resizeEvent(QResizeEvent *e)
{
QPlainTextEdit::resizeEvent(e);
QRect cr = contentsRect();
lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
}
void CodeEditorWidget::updateLineNumberArea(const QRect &rect, int dy)
{
if (dy)
lineNumberArea->scroll(0, dy);
else
lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());
if (rect.contains(viewport()->rect()))
updateLineNumberAreaWidth(0);
}
void CodeEditorWidget::highlightCurrentLine()
{
QList<QTextEdit::ExtraSelection> extraSelections;
if (!isReadOnly())
{
QTextEdit::ExtraSelection selection;
QColor lineColor = QColor(Qt::yellow).lighter(160);
selection.format.setBackground(lineColor);
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
selection.cursor = textCursor();
selection.cursor.clearSelection();
extraSelections.append(selection);
}
setExtraSelections(extraSelections);
}
void CodeEditorWidget::lineNumberAreaPaintEvent(QPaintEvent *event)
{
QPainter painter(lineNumberArea);
painter.fillRect(event->rect(), Qt::lightGray);
QTextBlock block = firstVisibleBlock();
int blockNumber = block.blockNumber();
int top = qRound(blockBoundingGeometry(block).translated(contentOffset()).top());
int bottom = top + qRound(blockBoundingRect(block).height());
while (block.isValid() && top <= event->rect().bottom())
{
if (block.isVisible() && bottom >= event->rect().top())
{
QString number = QString::number(blockNumber + 1);
painter.setPen(Qt::black);
painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
Qt::AlignRight, number);
}
block = block.next();
top = bottom;
bottom = top + qRound(blockBoundingRect(block).height());
++blockNumber;
}
}
LineNumberArea::LineNumberArea(CodeEditorWidget *editor) :
QWidget{editor},
codeEditor{editor}
{
}
QSize LineNumberArea::sizeHint() const
{
return QSize(codeEditor->lineNumberAreaWidth(), 0);
}
void LineNumberArea::paintEvent(QPaintEvent *event)
{
codeEditor->lineNumberAreaPaintEvent(event);
}
+41
View File
@@ -0,0 +1,41 @@
#pragma once
#include <QPlainTextEdit>
class CodeEditorWidget : public QPlainTextEdit
{
Q_OBJECT
public:
explicit CodeEditorWidget(QWidget *parent = nullptr);
void lineNumberAreaPaintEvent(QPaintEvent *event);
int lineNumberAreaWidth();
protected:
void resizeEvent(QResizeEvent *event) override;
private slots:
void updateLineNumberAreaWidth(int newBlockCount);
void highlightCurrentLine();
void updateLineNumberArea(const QRect &rect, int dy);
private:
QWidget *lineNumberArea;
};
class LineNumberArea : public QWidget
{
Q_OBJECT
public:
LineNumberArea(CodeEditorWidget *editor);
QSize sizeHint() const override;
protected:
void paintEvent(QPaintEvent *event) override;
private:
CodeEditorWidget *codeEditor;
};
@@ -0,0 +1,59 @@
#include "drawingcanvaswidget.h"
#include <QPixmap>
#include <QPainter>
DrawingCanvasWidget::DrawingCanvasWidget(QWidget *parent) :
QWidget{parent}
{
}
void DrawingCanvasWidget::setPixmap(QPixmap &pixmap)
{
m_pixmap = &pixmap;
setFixedSize(m_pixmap->size() * m_scale);
update();
}
void DrawingCanvasWidget::setScale(float scale)
{
if (m_scale == scale)
return;
emit scaleChanged(m_scale = scale);
if (m_pixmap)
setFixedSize(m_pixmap->size() * m_scale);
update();
}
void DrawingCanvasWidget::paintEvent(QPaintEvent *ev)
{
if (!m_pixmap)
{
QWidget::paintEvent(ev);
return;
}
QBrush brush;
{
QPixmap pixmap{32, 32};
{
QPainter painter{&pixmap};
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::gray);
painter.drawRect(0, 0, 16, 16);
painter.drawRect(16, 16, 16, 16);
painter.setBrush(Qt::white);
painter.drawRect(0, 16, 16, 16);
painter.drawRect(16, 0, 16, 16);
}
brush.setTexture(std::move(pixmap));
}
QPainter painter{this};
painter.setPen(Qt::NoPen);
painter.setBrush(std::move(brush));
painter.drawRect(rect());
painter.drawPixmap(rect(), *m_pixmap);
}
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#include <QWidget>
class QPixmap;
class DrawingCanvasWidget : public QWidget
{
Q_OBJECT
public:
explicit DrawingCanvasWidget(QWidget *parent = nullptr);
QPixmap *pixmap() { return m_pixmap; }
const QPixmap *pixmap() const { return m_pixmap; }
void setPixmap(QPixmap &pixmap);
float scale() const { return m_scale; }
void setScale(float scale);
signals:
void scaleChanged(float scale);
protected:
void paintEvent(QPaintEvent *ev) override;
private:
QPixmap *m_pixmap{};
float m_scale{4.f};
};
+225
View File
@@ -0,0 +1,225 @@
#include "pathpointswidget.h"
#include <QDebug>
#include <QPainter>
#include <QMouseEvent>
#include <algorithm>
PathPointsWidget::PathPointsWidget(QWidget *parent) :
QWidget{parent}
{
setMouseTracking(true);
}
PathPointsWidget::PathPointsWidget(std::vector<Path::Point> *points, QWidget *parent) :
QWidget{parent},
m_points{points}
{
}
void PathPointsWidget::setPoints(std::vector<Path::Point> *points)
{
m_points = points;
update();
}
void PathPointsWidget::setShowGrid(bool showGrid)
{
if (m_showGrid == showGrid)
return;
emit showGridChanged(m_showGrid = showGrid);
update();
}
void PathPointsWidget::setGridX(int gridX)
{
if (m_gridX == gridX)
return;
emit gridXChanged(m_gridX = gridX);
update();
}
void PathPointsWidget::setGridY(int gridY)
{
if (m_gridY == gridY)
return;
emit gridYChanged(m_gridY = gridY);
update();
}
void PathPointsWidget::setClosed(bool closed)
{
if (m_closed == closed)
return;
emit closedChanged(m_closed = closed);
update();
}
void PathPointsWidget::setSelectedIndex(const std::optional<std::size_t> &selectedIndex)
{
if (m_selectedIndex == selectedIndex)
return;
emit selectedIndexChanged(m_selectedIndex = selectedIndex);
update();
}
void PathPointsWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
if (m_showGrid)
{
if (!m_gridBrush || m_gridBrush->gridX != m_gridX || m_gridBrush->gridY != m_gridY)
{
QPixmap pixmap{m_gridX, m_gridY};
{
QPainter painter{&pixmap};
painter.setPen(palette().color(m_gridRole));
painter.drawLine(0, 0, m_gridX, 0);
painter.drawLine(0, 0, 0, m_gridY);
painter.fillRect(1, 1, m_gridX - 1, m_gridY - 1, palette().color(backgroundRole()));
}
m_gridBrush = GridBrush {
.gridX = m_gridX,
.gridY = m_gridY,
.brush = QBrush{std:: move(pixmap)}
};
}
}
else
m_gridBrush = std::nullopt;
QPainter painter{this};
painter.fillRect(rect(), m_gridBrush ? m_gridBrush->brush : palette().color(backgroundRole()));
if (!m_points)
return;
const auto drawLine = [&](const auto &point0, const auto &point1){
painter.setPen(QPen{Qt::black, 2});
painter.drawLine(point0.point, point1.point);
painter.setPen(QPen{Qt::yellow, 1});
painter.drawLine(point0.point, point1.point);
};
std::adjacent_find(std::cbegin(*m_points), std::cend(*m_points),
[&](const Path::Point &point0, const Path::Point &point1){
drawLine(point0, point1);
return false;
});
if (m_closed && m_points->size() >= 2)
drawLine(m_points->back(), m_points->front());
painter.setPen(Qt::black);
std::size_t i{};
for (const auto &point : *m_points)
{
if (i == m_selectedIndex)
painter.setBrush(Qt::red);
else if (i == 0)
painter.setBrush(Qt::green);
else
painter.setBrush(Qt::blue);
painter.drawEllipse(point.point, 2, 2);
i++;
}
}
void PathPointsWidget::mousePressEvent(QMouseEvent *event)
{
QWidget::mousePressEvent(event);
switch (event->button())
{
case Qt::LeftButton:
if (!m_points)
return;
if (!m_points->empty())
{
auto points = *m_points;
const auto distance = [&](const Path::Point &point){ return QLineF{point.point, event->pos()}.length(); };
std::sort(std::begin(points), std::end(points), [&](const Path::Point &left, const Path::Point &right){
return distance(left) < distance(right);
});
if (distance(points.front()) > 8)
goto createNew;
const auto iter = std::find_if(std::cbegin(*m_points), std::cend(*m_points),
[&minPoint=points.front().point](const Path::Point &point){ return point.point == minPoint; });
if (iter == std::cend(*m_points))
{
qWarning() << "unexpected end";
goto createNew;
}
const auto index = std::distance(std::cbegin(*m_points), iter);
emit pointInserted(index);
emit selectedIndexChanged(m_selectedIndex = index);
m_dragIndex = index;
}
else
{
createNew:
m_points->push_back(Path::Point{.point = snapPoint(event->pos()), .sp=100});
const auto index = m_points->size() - 1;
emit pointInserted(index);
emit selectedIndexChanged(m_selectedIndex = index);
m_dragIndex = index;
}
update();
break;
default:;
}
}
void PathPointsWidget::mouseReleaseEvent(QMouseEvent *event)
{
QWidget::mouseReleaseEvent(event);
switch (event->button())
{
case Qt::LeftButton:
m_dragIndex = std::nullopt;
break;
default:;
}
}
void PathPointsWidget::mouseMoveEvent(QMouseEvent *event)
{
QWidget::mouseMoveEvent(event);
emit cursorMoved(snapPoint(event->pos()));
if (m_dragIndex)
{
if (event->buttons().testFlag(Qt::LeftButton))
{
const auto point = snapPoint(event->pos());
if ((*m_points)[*m_dragIndex].point != point)
{
(*m_points)[*m_dragIndex].point = point;
emit pointMoved(*m_dragIndex);
update();
}
}
else
m_dragIndex = std::nullopt;
}
}
QPoint PathPointsWidget::snapPoint(const QPoint &point) const
{
if (!m_showGrid)
return point;
return QPoint{
(point.x() + (m_gridX / 2)) / m_gridX * m_gridX,
(point.y() + (m_gridY / 2)) / m_gridY * m_gridY,
};
}
+84
View File
@@ -0,0 +1,84 @@
#pragma once
#include <QWidget>
#include <QPalette>
#include <vector>
#include <optional>
#include "projectcontainer.h"
class PathPointsWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY(bool showGrid READ showGrid WRITE setShowGrid NOTIFY showGridChanged)
Q_PROPERTY(int gridX READ gridX WRITE setGridX NOTIFY gridXChanged)
Q_PROPERTY(int gridY READ gridY WRITE setGridY NOTIFY gridYChanged)
Q_PROPERTY(bool closed READ closed WRITE setClosed NOTIFY closedChanged)
public:
explicit PathPointsWidget(QWidget *parent = nullptr);
explicit PathPointsWidget(std::vector<Path::Point> *points, QWidget *parent = nullptr);
void setPoints(std::vector<Path::Point> *points);
bool showGrid() const { return m_showGrid; }
void setShowGrid(bool showGrid);
int gridX() const { return m_gridX; }
void setGridX(int gridX);
int gridY() const { return m_gridY; }
void setGridY(int gridY);
bool closed() const { return m_closed; }
void setClosed(bool closed);
const std::optional<std::size_t> &selectedIndex() const { return m_selectedIndex; }
void setSelectedIndex(const std::optional<std::size_t> &selectedIndex);
QPalette::ColorRole gridRole() const { return m_gridRole; }
void setGridRole(QPalette::ColorRole gridRole) { if (gridRole == m_gridRole) return; m_gridRole = gridRole; update(); }
signals:
void showGridChanged(bool showGrid);
void gridXChanged(int gridX);
void gridYChanged(int gridY);
void closedChanged(bool closed);
void selectedIndexChanged(const std::optional<std::size_t> &selectedIndex);
void cursorMoved(const QPoint &point);
void pointInserted(std::size_t index);
void pointMoved(std::size_t index);
protected:
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
private:
QPoint snapPoint(const QPoint &point) const;
std::vector<Path::Point> *m_points{};
bool m_showGrid{true};
int m_gridX{16};
int m_gridY{16};
bool m_closed{true};
std::optional<std::size_t> m_selectedIndex;
std::optional<std::size_t> m_dragIndex;
struct GridBrush {
int gridX;
int gridY;
QBrush brush;
};
std::optional<GridBrush> m_gridBrush;
QPalette::ColorRole m_gridRole{QPalette::Dark};
};