diff --git a/ApplicationController.cpp b/ApplicationController.cpp
new file mode 100644
index 0000000..efd2c7b
--- /dev/null
+++ b/ApplicationController.cpp
@@ -0,0 +1,67 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#include "ApplicationController.hpp"
+
+
+ApplicationController *ApplicationController::_instance = nullptr;
+
+
+ApplicationController::ApplicationController(QObject *parent)
+ : QObject(parent)
+{
+ _instance = this;
+
+ // Start as soon the main loop is running.
+ QMetaObject::invokeMethod(this, &ApplicationController::start, Qt::QueuedConnection);
+}
+
+
+QFont ApplicationController::monospaceFont() const
+{
+ QFont monospaceFont;
+#ifdef Q_OS_WIN32
+ monospaceFont = QFont("Consolas", 12);
+#else
+#ifdef Q_OS_MAC
+ monospaceFont = QFont("Menlo", 12);
+#else
+ monospaceFont = QFont("Lucida Console", 12);
+#endif
+#endif
+ return monospaceFont;
+}
+
+
+void ApplicationController::start()
+{
+ _mainWindow = new MainWindow();
+ _mainWindow->show();
+}
+
+
+ApplicationController *ApplicationController::instance()
+{
+ return _instance;
+}
+
+
+ApplicationController* gApp()
+{
+ return ApplicationController::instance();
+}
+
+
diff --git a/ApplicationController.hpp b/ApplicationController.hpp
new file mode 100644
index 0000000..be7700e
--- /dev/null
+++ b/ApplicationController.hpp
@@ -0,0 +1,57 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#pragma once
+
+
+#include "MainWindow.hpp"
+
+#include
+
+
+/// The application controller
+///
+class ApplicationController : public QObject
+{
+ Q_OBJECT
+
+public:
+ /// ctor
+ ///
+ explicit ApplicationController(QObject *parent = nullptr);
+
+public:
+ /// Get the default monospaced font.
+ ///
+ QFont monospaceFont() const;
+
+public:
+ /// Get the global instance.
+ ///
+ static ApplicationController* instance();
+
+private:
+ /// Start the application.
+ ///
+ Q_SLOT void start();
+
+private:
+ static ApplicationController *_instance; ///< The controller instance.
+ MainWindow *_mainWindow; ///< The main window.
+};
+
+
+ApplicationController* gApp();
diff --git a/BitmapConverter.cpp b/BitmapConverter.cpp
new file mode 100644
index 0000000..f15f3c5
--- /dev/null
+++ b/BitmapConverter.cpp
@@ -0,0 +1,29 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#include "BitmapConverter.hpp"
+
+
+BitmapConverter::BitmapConverter(const QString &displayName)
+ : Converter(displayName)
+{
+}
+
+
+Converter::Mode BitmapConverter::mode() const
+{
+ return Mode::Bitmap;
+}
diff --git a/BitmapConverter.hpp b/BitmapConverter.hpp
new file mode 100644
index 0000000..757e712
--- /dev/null
+++ b/BitmapConverter.hpp
@@ -0,0 +1,45 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#pragma once
+
+
+#include "Converter.hpp"
+
+
+/// The base class for all bitmap converters.
+///
+class BitmapConverter : public Converter
+{
+public:
+ /// ctor
+ ///
+ BitmapConverter(const QString &displayName);
+
+public: // implement Converter
+ Mode mode() const override;
+
+public:
+ /// Generate the code from the given image.
+ ///
+ /// @param image The image to convert.
+ /// @param parameter A map with parameters passed to this converter.
+ /// @return The generated code.
+ ///
+ virtual QString generateCode(const QImage &image, const QVariantMap ¶meter) const = 0;
+};
+
+
diff --git a/BitmapPanel.cpp b/BitmapPanel.cpp
index e6db3ab..f71e71a 100644
--- a/BitmapPanel.cpp
+++ b/BitmapPanel.cpp
@@ -17,16 +17,19 @@
#include "BitmapPanel.hpp"
+#include "ApplicationController.hpp"
#include "Converter.hpp"
#include "BitmapPreview.hpp"
-#include
-#include
-#include
-#include
+#include
+#include
+#include
+#include
+#include
-BitmapPanel::BitmapPanel(QWidget *parent) : QWidget(parent)
+BitmapPanel::BitmapPanel(QWidget *parent)
+ : QWidget(parent), _converter(nullptr)
{
initializeUi();
}
@@ -35,16 +38,49 @@ BitmapPanel::BitmapPanel(QWidget *parent) : QWidget(parent)
void BitmapPanel::setImage(const QImage &image)
{
_bitmapPreview->setImage(image);
+ _bitmapPreview->setFixedSize(_bitmapPreview->sizeHint());
}
void BitmapPanel::setConverter(const Converter *converter)
{
- _bitmapPreview->setConverter(converter);
+ if (_converter != converter) {
+ _converter = converter;
+ _bitmapPreview->setConverter(converter);
+ _bitmapPreview->setFixedSize(_bitmapPreview->sizeHint());
+ _characterSelector->setVisible(_converter->mode() == Converter::Mode::Font);
+ }
+}
+
+
+void BitmapPanel::setCharacters(const QString &characters)
+{
+ if (_characters != characters) {
+ _characters = characters;
+ _characterSelector->clear();
+ for (int i = 0; i < characters.size(); ++i) {
+ const auto c = _characters.at(i);
+ _characterSelector->addItem(QString("%1: %2 0x%3").arg(i, 3, 10, QChar('0'))
+ .arg(QString(c)).arg(c.unicode(), 4, 16, QChar('0')), c);
+ }
+ _characterSelector->setCurrentIndex(0);
+ }
+}
+
+
+void BitmapPanel::setParameter(const QVariantMap ¶meter)
+{
+ _bitmapPreview->setParameter(parameter);
_bitmapPreview->setFixedSize(_bitmapPreview->sizeHint());
}
+QChar BitmapPanel::selectedCharacter() const
+{
+ return _characterSelector->currentData().toChar();
+}
+
+
void BitmapPanel::initializeUi()
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
@@ -72,6 +108,35 @@ void BitmapPanel::initializeUi()
auto previewSettingsLayout = new QHBoxLayout(previewSettingsPanel);
previewSettingsLayout->setContentsMargins(0, 0, 0, 0);
previewSettingsLayout->setSpacing(4);
+
+ _fontConversionTools = new QFrame();
+ auto fontConversionLayout = new QHBoxLayout(_fontConversionTools);
+ fontConversionLayout->setContentsMargins(0, 0, 0, 0);
+ fontConversionLayout->setSpacing(2);
+ previewSettingsLayout->addWidget(_fontConversionTools);
+
+ auto previousCharButton = new QPushButton("<");
+ fontConversionLayout->addWidget(previousCharButton);
+ _characterSelector = new QComboBox();
+ _characterSelector->setFont(gApp()->monospaceFont());
+ fontConversionLayout->addWidget(_characterSelector);
+ auto nextCharButton = new QPushButton(">");
+ fontConversionLayout->addWidget(nextCharButton);
+ connect(_characterSelector, &QComboBox::currentIndexChanged, [=]{
+ Q_EMIT selectedCharacterChanged(_characterSelector->currentData().toChar());
+ });
+ connect(previousCharButton, &QPushButton::clicked, [=]{
+ auto currentIndex = _characterSelector->currentIndex();
+ if (currentIndex > 0) {
+ _characterSelector->setCurrentIndex(currentIndex - 1);
+ }
+ });
+ connect(nextCharButton, &QPushButton::clicked, [=]{
+ auto currentIndex = _characterSelector->currentIndex();
+ if (currentIndex < (_characterSelector->count()-1)) {
+ _characterSelector->setCurrentIndex(currentIndex + 1);
+ }
+ });
previewSettingsLayout->addStretch();
previewSettingsLayout->addWidget(new QLabel(tr("Overlay Mode:")));
_overlaySelector = new QComboBox();
diff --git a/BitmapPanel.hpp b/BitmapPanel.hpp
index d51e3fb..f30a7f0 100644
--- a/BitmapPanel.hpp
+++ b/BitmapPanel.hpp
@@ -23,13 +23,18 @@
class BitmapPreview;
class Converter;
class QComboBox;
+class QFrame;
+/// A panel with the scrollable bitmap preview.
+///
class BitmapPanel : public QWidget
{
Q_OBJECT
public:
+ /// Create the panel.
+ ///
explicit BitmapPanel(QWidget *parent = nullptr);
public:
@@ -41,11 +46,34 @@ public:
///
void setConverter(const Converter *converter);
-private:
- void initializeUi();
+ /// Set the current character set.
+ ///
+ void setCharacters(const QString &characters);
+
+ /// Set the current parameter.
+ ///
+ void setParameter(const QVariantMap ¶meter);
+
+ /// Get the current selected character
+ ///
+ QChar selectedCharacter() const;
private:
+ /// Initialize all UI elements.
+ ///
+ void initializeUi();
+
+Q_SIGNALS:
+ /// Emitted if the selected character changes.
+ ///
+ void selectedCharacterChanged(QChar c);
+
+private:
+ const Converter *_converter; ///< The current converter.
+ QString _characters; ///< The list of characters to convert.
BitmapPreview *_bitmapPreview; ///< The bitmap preview;
+ QFrame *_fontConversionTools; ///< The area with tools for font conversion.
+ QComboBox *_characterSelector; ///< The selector for a single character.
QComboBox *_overlaySelector; ///< The selector for the overlays.
};
diff --git a/BitmapPreview.cpp b/BitmapPreview.cpp
index 6080adb..e8c88ba 100644
--- a/BitmapPreview.cpp
+++ b/BitmapPreview.cpp
@@ -48,9 +48,7 @@ void BitmapPreview::setImage(const QImage &image)
if (_image != image) {
_image = image;
_pixmap = QPixmap::fromImage(image);
- if (_converter != nullptr) {
- setGeneratedSize(_converter->generatedSize(_image.size()));
- }
+ updateGeneratedSize();
recalculate();
update();
}
@@ -80,9 +78,18 @@ void BitmapPreview::setConverter(const Converter *converter)
{
if (_converter != converter) {
_converter = converter;
- if (_converter != nullptr) {
- setGeneratedSize(_converter->generatedSize(_image.size()));
- }
+ updateGeneratedSize();
+ update();
+ }
+}
+
+
+void BitmapPreview::setParameter(const QVariantMap ¶meter)
+{
+ if (_parameter != parameter) {
+ _parameter = parameter;
+ updateGeneratedSize();
+ recalculate();
update();
}
}
@@ -118,7 +125,7 @@ void BitmapPreview::paintEvent(QPaintEvent *pe)
p.setOpacity(1.0);
p.translate(x, y);
OverlayPainter op(&p, pe->rect(), _displayFactor, _pixmap.size(), _generatedSize);
- _converter->paintOverlay(op, _overlayMode, _image);
+ _converter->paintOverlay(op, _overlayMode, _image, _parameter);
}
} else {
p.setPen(Qt::white);
@@ -134,6 +141,16 @@ void BitmapPreview::resizeEvent(QResizeEvent *e)
}
+void BitmapPreview::updateGeneratedSize()
+{
+ if (_converter != nullptr && _converter->mode() == Converter::Mode::Bitmap) {
+ setGeneratedSize(_converter->generatedSize(_image.size(), _parameter));
+ } else {
+ setGeneratedSize(_image.size());
+ }
+}
+
+
void BitmapPreview::recalculate()
{
if (_pixmap.isNull()) {
diff --git a/BitmapPreview.hpp b/BitmapPreview.hpp
index c8b39d3..8b32032 100644
--- a/BitmapPreview.hpp
+++ b/BitmapPreview.hpp
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
class Converter;
@@ -49,6 +50,10 @@ public:
///
void setConverter(const Converter *converter);
+ /// Set the current parameter.
+ ///
+ void setParameter(const QVariantMap ¶meter);
+
public:
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
@@ -58,6 +63,10 @@ protected: // QWidget interface
void resizeEvent(QResizeEvent *event) override;
private:
+ /// update the generated size
+ ///
+ void updateGeneratedSize();
+
/// Recalculate all sizes
///
void recalculate();
@@ -74,5 +83,6 @@ private:
QSize _minimumSize; ///< The preferred size of this widget.
OverlayMode _overlayMode; ///< The overlay mode.
const Converter *_converter; ///< The current converter.
+ QVariantMap _parameter; ///< The current set of parameter.
};
diff --git a/Converter.cpp b/Converter.cpp
index 48db2f8..f15f825 100644
--- a/Converter.cpp
+++ b/Converter.cpp
@@ -29,12 +29,18 @@ QString Converter::displayName() const
}
-QSize Converter::generatedSize(const QSize &imageSize) const
+QSize Converter::generatedSize(const QSize &imageSize, const QVariantMap&) const
{
return imageSize;
}
+ParameterDefinitionPtr Converter::createParameterDefinition() const
+{
+ return ParameterDefinition::create();
+}
+
+
LegendDataPtr Converter::legendData(OverlayMode) const
{
auto ld = LegendData::create();
@@ -43,7 +49,7 @@ LegendDataPtr Converter::legendData(OverlayMode) const
}
-void Converter::paintOverlay(OverlayPainter &op, OverlayMode, const QImage&) const
+void Converter::paintOverlay(OverlayPainter &op, OverlayMode, const QImage&, const QVariantMap&) const
{
op.drawPixelOutline(op.imageRect(), colorBitmapSizeOriginal, 1, 2);
if (op.generatedSize().isValid() && !op.generatedSize().isEmpty()) {
diff --git a/Converter.hpp b/Converter.hpp
index c0cd353..fe0a188 100644
--- a/Converter.hpp
+++ b/Converter.hpp
@@ -20,6 +20,7 @@
#include "LegendData.hpp"
#include "OverlayPainter.hpp"
#include "OverlayMode.hpp"
+#include "ParameterDefinition.hpp"
#include
#include
@@ -30,10 +31,17 @@
///
class Converter
{
+public:
+ enum class Mode {
+ Bitmap,
+ Font
+ };
+
public:
/// Create a new converter.
///
/// @param displayName The name displayed in the UI for this coonverter.
+ /// @param mode The converter mode.
///
Converter(const QString &displayName);
@@ -46,21 +54,21 @@ public:
///
QString displayName() const;
+ /// Get the mode for this converter.
+ ///
+ virtual Mode mode() const = 0;
+
public:
/// Return the size of the generated bitmap data.
///
/// @param imageSize The size of the image.
/// @return The size of the generated bitmap data.
///
- virtual QSize generatedSize(const QSize &imageSize) const;
+ virtual QSize generatedSize(const QSize &imageSize, const QVariantMap ¶meter) const;
- /// Generate the code from the given image.
+ /// Create the parameter definition for the converter.
///
- /// @param image The image to convert.
- /// @param parameter A map with parameters passed to this converter.
- /// @return The generated code.
- ///
- virtual QString generateCode(const QImage &image, const QVariantMap ¶meter) const = 0;
+ virtual ParameterDefinitionPtr createParameterDefinition() const;
/// Return a legend for the bitmap preview.
///
@@ -71,8 +79,9 @@ public:
/// @param p The painter.
/// @param mode The overlay mode (never `None`).
/// @param image The image.
+ /// @param parameter The current set of parameter.
///
- virtual void paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image) const;
+ virtual void paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image, const QVariantMap ¶meter) const;
protected:
/// The color for the image frame.
diff --git a/ConverterFramebuf.cpp b/ConverterFramebuf.cpp
index 058e900..173744d 100644
--- a/ConverterFramebuf.cpp
+++ b/ConverterFramebuf.cpp
@@ -21,7 +21,7 @@
ConverterFramebuf::ConverterFramebuf(const QString &displayName)
- : Converter(displayName)
+ : BitmapConverter(displayName)
{
}
diff --git a/ConverterFramebuf.hpp b/ConverterFramebuf.hpp
index 8a261fc..58d1e7a 100644
--- a/ConverterFramebuf.hpp
+++ b/ConverterFramebuf.hpp
@@ -17,12 +17,12 @@
#pragma once
-#include "Converter.hpp"
+#include "BitmapConverter.hpp"
/// Base class of framebuf converters.
///
-class ConverterFramebuf : public Converter
+class ConverterFramebuf : public BitmapConverter
{
public:
ConverterFramebuf(const QString &displayName);
diff --git a/ConverterFramebufMono.cpp b/ConverterFramebufMono.cpp
index faa0496..ab6cc7b 100644
--- a/ConverterFramebufMono.cpp
+++ b/ConverterFramebufMono.cpp
@@ -25,124 +25,29 @@ ConverterFramebufMono::ConverterFramebufMono(
int unitSize)
:
ConverterFramebuf(displayName),
- _unitOrientation(unitOrientation),
- _bitDirection(bitDirection),
- _unitSize(unitSize)
+ MonoTools(unitOrientation, bitDirection, unitSize)
{
}
-QSize ConverterFramebufMono::generatedSize(const QSize &imageSize) const
+QSize ConverterFramebufMono::generatedSize(const QSize &imageSize, const QVariantMap ¶meter) const
{
- if (_unitOrientation == UnitOrientation::Vertical) {
- if ((imageSize.height() % _unitSize) != 0) {
- return QSize(imageSize.width(), ((imageSize.height()/_unitSize)+1)*_unitSize);
- } else {
- return imageSize;
- }
- } else {
- if ((imageSize.width() % _unitSize) != 0) {
- return QSize(((imageSize.width()/_unitSize)+1)*_unitSize, imageSize.height());
- } else {
- return imageSize;
- }
- }
+ return monoGeneratedSize(imageSize, parameter);
}
LegendDataPtr ConverterFramebufMono::legendData(OverlayMode mode) const
{
auto data = ConverterFramebuf::legendData(mode);
- if (mode == OverlayMode::BitAssigments) {
- data->addEntry(colorBitAssignment1, colorBitAssignment2, QObject::tr("Bit Assignment"));
- } else {
- data->addEntry(colorPixelInterpretation, QObject::tr("Pixel Interpretation"));
- }
+ addMonoLegendData(data, mode);
return data;
}
-void ConverterFramebufMono::paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image) const
+void ConverterFramebufMono::paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image, const QVariantMap ¶meter) const
{
- ConverterFramebuf::paintOverlay(p, mode, image);
- if (mode == OverlayMode::BitAssigments) {
- const auto bitL = (_bitDirection == BitDirection::LSB ? "0" : QString::number(_unitSize-1));
- const auto bitH = (_bitDirection == BitDirection::LSB ? QString::number(_unitSize-1) : "0");
- bool colorFlag = false;
- if (_unitOrientation == UnitOrientation::Vertical) {
- for (int y = 0; y < p.imageSize().height(); y += _unitSize) {
- for (int x = 0; x < p.imageSize().width(); ++x) {
- QRect rect(x, y, 1, _unitSize);
- if (p.arePixelUpdated(rect)) {
- const auto color = colorFlag ? colorBitAssignment1 : colorBitAssignment2;
- p.drawPixelOutline(rect, color, 1);
- p.drawPixelText(QRect(x, y, 1, 1), color, bitL);
- p.drawPixelText(QRect(x, y+_unitSize-1, 1, 1), color, bitH);
- }
- colorFlag = !colorFlag;
- }
- if (p.imageSize().width() % 2 == 0) {
- colorFlag = !colorFlag;
- }
- }
- } else {
- for (int y = 0; y < p.imageSize().height(); ++y) {
- for (int x = 0; x < p.imageSize().width(); x += _unitSize) {
- QRect rect(x, y, _unitSize, 1);
- if (p.arePixelUpdated(rect)) {
- const auto color = colorFlag ? colorBitAssignment1 : colorBitAssignment2;
- p.drawPixelOutline(rect, color, 1);
- p.drawPixelText(QRect(x, y, 1, 1), color, bitH);
- p.drawPixelText(QRect(x+_unitSize-1, y, 1, 1), color, bitL);
- }
- colorFlag = !colorFlag;
- }
- if ((p.imageSize().width()/_unitSize) % 2 == 0) {
- colorFlag = !colorFlag;
- }
- }
- }
- } else if (mode == OverlayMode::PixelInterpretation) {
- for (int y = 0; y < p.generatedSize().height(); ++y) {
- for (int x = 0; x < p.generatedSize().width(); ++x) {
- auto text = (getPixel(x, y, image) ? "1" : "0");
- const QRect rect(x, y, 1, 1);
- if (p.arePixelUpdated(rect)) {
- p.drawPixelText(rect, colorPixelInterpretation, text);
- }
- }
- }
- }
-}
-
-
-bool ConverterFramebufMono::getPixel(int x, int y, const QImage &image)
-{
- if (x < 0 || y < 0 || x >= image.width() || y >= image.height()) {
- return false;
- }
- auto color = image.pixelColor(x, y);
- float h, s, l, a;
- color.getHslF(&h, &s, &l, &a);
- if (a < 0.5) {
- return false;
- }
- return l < 0.5;
-}
-
-
-uint32_t ConverterFramebufMono::readUnit(int x, int y, int dx, int dy, int count, const QImage &image)
-{
- uint32_t result = 0;
- for (int i = 0; i < count; ++i) {
- result <<= 1;
- if (getPixel(x, y, image)) {
- result |= 0b1;
- }
- x += dx;
- y += dy;
- }
- return result;
+ ConverterFramebuf::paintOverlay(p, mode, image, parameter);
+ monoPaintOverlay(p, mode, image, parameter);
}
diff --git a/ConverterFramebufMono.hpp b/ConverterFramebufMono.hpp
index 54bd17b..442bde2 100644
--- a/ConverterFramebufMono.hpp
+++ b/ConverterFramebufMono.hpp
@@ -17,24 +17,14 @@
#pragma once
+#include "MonoTools.hpp"
#include "ConverterFramebuf.hpp"
/// The base class of all mono converters
///
-class ConverterFramebufMono : public ConverterFramebuf
+class ConverterFramebufMono : public ConverterFramebuf, public MonoTools
{
-protected:
- enum class UnitOrientation {
- Horizontal,
- Vertical
- };
-
- enum class BitDirection {
- LSB,
- MSB
- };
-
public:
/// Create a new mono converter.
///
@@ -49,30 +39,8 @@ public:
int unitSize);
public: // Converter interface
- QSize generatedSize(const QSize &imageSize) const override;
+ QSize generatedSize(const QSize &imageSize, const QVariantMap ¶meter) const override;
LegendDataPtr legendData(OverlayMode mode) const override;
- void paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image) const override;
-
-protected:
- /// Interpret a single pixel.
- ///
- /// Returns `false` if the pixel is out of bounds.
- ///
- static bool getPixel(int x, int y, const QImage &image);
-
- /// Read a single unit.
- ///
- static uint32_t readUnit(int x, int y, int dx, int dy, int count, const QImage &image);
-
- /// The colors for the bit assignments
- ///
- static constexpr QColor colorBitAssignment1 = QColor(240, 40, 40);
- static constexpr QColor colorBitAssignment2 = QColor(240, 80, 80);
- static constexpr QColor colorPixelInterpretation = QColor(240, 240, 40);
-
-protected:
- UnitOrientation _unitOrientation; ///< The unit orientatioon.
- BitDirection _bitDirection; ///< The bit direction.
- int _unitSize; ///< The number of bits per unit.
+ void paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image, const QVariantMap ¶meter) const override;
};
diff --git a/ConverterFramebufMonoHLSB.cpp b/ConverterFramebufMonoHLSB.cpp
index 779e881..814af7c 100644
--- a/ConverterFramebufMonoHLSB.cpp
+++ b/ConverterFramebufMonoHLSB.cpp
@@ -26,7 +26,7 @@ ConverterFramebufMonoHLSB::ConverterFramebufMonoHLSB()
}
-QString ConverterFramebufMonoHLSB::generateCode(const QImage &image, const QVariantMap&) const
+QString ConverterFramebufMonoHLSB::generateCode(const QImage &image, const QVariantMap ¶meter) const
{
QByteArray data;
for (int y = 0; y < image.height(); ++y) {
@@ -34,5 +34,5 @@ QString ConverterFramebufMonoHLSB::generateCode(const QImage &image, const QVari
data.append(static_cast(readUnit(x, y, 1, 0, 8, image)));
}
}
- return createCode(data, generatedSize(image.size()), "MONO_HLSB");
+ return createCode(data, generatedSize(image.size(), parameter), "MONO_HLSB");
}
diff --git a/ConverterFramebufMonoHMSB.cpp b/ConverterFramebufMonoHMSB.cpp
index fed9891..da7c7c8 100644
--- a/ConverterFramebufMonoHMSB.cpp
+++ b/ConverterFramebufMonoHMSB.cpp
@@ -23,7 +23,7 @@ ConverterFramebufMonoHMSB::ConverterFramebufMonoHMSB()
}
-QString ConverterFramebufMonoHMSB::generateCode(const QImage &image, const QVariantMap&) const
+QString ConverterFramebufMonoHMSB::generateCode(const QImage &image, const QVariantMap ¶meter) const
{
QByteArray data;
for (int y = 0; y < image.height(); ++y) {
@@ -31,6 +31,6 @@ QString ConverterFramebufMonoHMSB::generateCode(const QImage &image, const QVari
data.append(static_cast(readUnit(x+7, y, -1, 0, 8, image)));
}
}
- return createCode(data, generatedSize(image.size()), "MONO_HMSB");
+ return createCode(data, generatedSize(image.size(), parameter), "MONO_HMSB");
}
diff --git a/ConverterFramebufMonoVLSB.cpp b/ConverterFramebufMonoVLSB.cpp
index 868f6c1..2c2443c 100644
--- a/ConverterFramebufMonoVLSB.cpp
+++ b/ConverterFramebufMonoVLSB.cpp
@@ -23,7 +23,7 @@ ConverterFramebufMonoVLSB::ConverterFramebufMonoVLSB()
}
-QString ConverterFramebufMonoVLSB::generateCode(const QImage &image, const QVariantMap&) const
+QString ConverterFramebufMonoVLSB::generateCode(const QImage &image, const QVariantMap ¶meter) const
{
QByteArray data;
for (int y = 0; y < image.height(); y += 8) {
@@ -31,6 +31,6 @@ QString ConverterFramebufMonoVLSB::generateCode(const QImage &image, const QVari
data.append(static_cast(readUnit(x, y+7, 0, -1, 8, image)));
}
}
- return createCode(data, generatedSize(image.size()), "MONO_VLSB");
+ return createCode(data, generatedSize(image.size(), parameter), "MONO_VLSB");
}
diff --git a/FontConverter.cpp b/FontConverter.cpp
new file mode 100644
index 0000000..5ee49bf
--- /dev/null
+++ b/FontConverter.cpp
@@ -0,0 +1,149 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#include "FontConverter.hpp"
+
+
+FontConverter::FontConverter(const QString &displayName)
+ : Converter(displayName)
+{
+}
+
+
+Converter::Mode FontConverter::mode() const
+{
+ return Mode::Font;
+}
+
+
+ParameterDefinitionPtr FontConverter::createParameterDefinition() const
+{
+ auto pd = Converter::createParameterDefinition();
+ pd->addIntegerSize("maximumSize", QObject::tr("Maximum Size"),
+ QSize(12, 16), QSize(8, 8), QSize(256, 256));
+ pd->addIntegerPosition("charOffset", QObject::tr("Char Offset"),
+ QPoint(0, 0), QPoint(-256, -256), QPoint(256, 256));
+ pd->addCheckbox("convertMono", QObject::tr("Convert to Mono"), false);
+ pd->addInteger("convertMonoThreshold", QObject::tr("Conversion Threshold"), 128, 0, 255);
+ pd->addCheckbox("preferBitmapFont", QObject::tr("Prefer Bitmap Font"), false);
+ pd->addCheckbox("noAntialiasFont", QObject::tr("No Antialias Font"), false);
+ pd->addCheckbox("trimLeft", QObject::tr("Trim Left Side"), true);
+ pd->addCheckbox("trimRight", QObject::tr("Trim Right Side"), true);
+ pd->addCheckbox("invertFont", QObject::tr("Invert the Font"), false);
+ return pd;
+}
+
+
+QImage FontConverter::generateImage(const QFont &font, QChar c, const QVariantMap ¶meter) const
+{
+ auto maximumSize = parameter["maximumSize"].toSize();
+ if (!maximumSize.isValid() || maximumSize.isNull()) {
+ maximumSize = QSize(8, 8);
+ }
+ const auto charOffset = parameter["charOffset"].toPoint();
+ QImage result(maximumSize, QImage::Format_ARGB32_Premultiplied);
+ result.setDevicePixelRatio(1.0);
+ QPainter p;
+ p.begin(&result);
+ p.fillRect(result.rect(), Qt::white);
+ p.setRenderHint(QPainter::TextAntialiasing, false);
+ auto fontForDrawing = font;
+ int fontStyleStrategy = 0;
+ if (parameter["preferBitmapFont"].toBool()) {
+ fontStyleStrategy |= QFont::PreferBitmap;
+ }
+ if (parameter["noAntialiasFont"].toBool()) {
+ fontStyleStrategy |= QFont::NoAntialias;
+ }
+ fontStyleStrategy |= QFont::NoSubpixelAntialias;
+ fontForDrawing.setStyleStrategy(static_cast(fontStyleStrategy));
+ QFontMetrics fontMetrics(fontForDrawing);
+ auto charBoundingRect = fontMetrics.boundingRect(c);
+ // Make sure the first pixel is in the bitmap, draw baseline at ascent.
+ QPoint targetPoint(-charBoundingRect.left(), fontMetrics.ascent());
+ targetPoint += charOffset;
+ p.setFont(fontForDrawing);
+ p.drawText(targetPoint, QString(c));
+ p.end();
+ // Postprocess the font.
+ const auto threshold = static_cast(parameter["convertMonoThreshold"].toInt());
+ if (parameter["convertMono"].toBool()) {
+ for (int x = 0; x < result.width(); ++x) {
+ for (int y = 0; y < result.height(); ++y) {
+ const auto pixel = result.pixel(x, y);
+ if ((pixel & 0xff) <= threshold) {
+ result.setPixel(x, y, qRgb(0, 0, 0));
+ } else {
+ result.setPixel(x, y, qRgb(255, 255, 255));
+ }
+ }
+ }
+ }
+ // Trim the font.
+ const auto trimLeft = parameter["trimLeft"].toBool();
+ const auto trimRight = parameter["trimRight"].toBool();
+ if (trimLeft || trimRight) {
+ auto resultRect = result.rect();
+ int leftTrim = 0;
+ int rightTrim = 0;
+ if (trimLeft) {
+ for (int x = 0; x < result.width(); ++x) {
+ bool hasPixelSet = false;
+ for (int y = 0; y < result.height(); ++y) {
+ const auto pixel = result.pixel(x, y);
+ if ((pixel & 0xff) <= threshold) {
+ hasPixelSet = true;
+ break;
+ }
+ }
+ if (hasPixelSet) {
+ break;
+ }
+ leftTrim += 1;
+ }
+ }
+ if (trimRight) {
+ for (int x = result.width()-1; x >= 0; --x) {
+ bool hasPixelSet = false;
+ for (int y = 0; y < result.width(); ++y) {
+ const auto pixel = result.pixel(x, y);
+ if ((pixel & 0xff) <= threshold) {
+ hasPixelSet = true;
+ break;
+ }
+ }
+ if (hasPixelSet) {
+ break;
+ }
+ rightTrim += 1;
+ }
+ }
+ if ((resultRect.width() - leftTrim - rightTrim) <= 0) {
+ // The font image is empty, use one pixel line.
+ resultRect.setWidth(1);
+ } else {
+ resultRect = resultRect.marginsRemoved(QMargins(leftTrim, 0, rightTrim, 0));
+ }
+ if (resultRect != result.rect()) {
+ result = result.copy(resultRect);
+ }
+ }
+ // Invert the font.
+ if (parameter["invertFont"].toBool()) {
+ result.invertPixels();
+ }
+ return result;
+}
diff --git a/FontConverter.hpp b/FontConverter.hpp
new file mode 100644
index 0000000..cf34d99
--- /dev/null
+++ b/FontConverter.hpp
@@ -0,0 +1,58 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#pragma once
+
+
+#include "Converter.hpp"
+
+
+/// The base class for all font converters.
+///
+class FontConverter : public Converter
+{
+public:
+ /// ctor
+ ///
+ FontConverter(const QString &displayName);
+
+public: // implement Converter
+ Mode mode() const override;
+ ParameterDefinitionPtr createParameterDefinition() const override;
+
+public:
+ /// Create a bitmap for a given character.
+ ///
+ /// This method should return the given character in exact the size and format it will
+ /// be converted as bitmap.
+ ///
+ /// @param font The font for the character.
+ /// @param c The character to convert.
+ /// @param parameter The current map of parameters.
+ ///
+ virtual QImage generateImage(const QFont &font, QChar c, const QVariantMap ¶meter) const;
+
+ /// Generate the code from the given font.
+ ///
+ /// The string with all characters to convert is passed as parameter 'characters'.
+ ///
+ /// @param font The font to convert.
+ /// @param parameter A map with parameters passed to this converter.
+ /// @return The generated code.
+ ///
+ virtual QString generateCode(const QFont &font, const QVariantMap ¶meter) const = 0;
+};
+
diff --git a/FontConverterFramebufMono.cpp b/FontConverterFramebufMono.cpp
new file mode 100644
index 0000000..c36232c
--- /dev/null
+++ b/FontConverterFramebufMono.cpp
@@ -0,0 +1,52 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#include "FontConverterFramebufMono.hpp"
+
+
+FontConverterFramebufMono::FontConverterFramebufMono()
+:
+ FontConverter("MicroPython Font Mono VLSB"),
+ MonoTools(UnitOrientation::Vertical, BitDirection::LSB, 8)
+{
+}
+
+
+QSize FontConverterFramebufMono::generatedSize(const QSize &imageSize, const QVariantMap ¶meter) const
+{
+ return monoGeneratedSize(imageSize, parameter);
+}
+
+
+QString FontConverterFramebufMono::generateCode(const QFont&, const QVariantMap&) const
+{
+ return "The generated format is not decided yet.";
+}
+
+
+LegendDataPtr FontConverterFramebufMono::legendData(OverlayMode mode) const
+{
+ auto data = FontConverter::legendData(mode);
+ addMonoLegendData(data, mode);
+ return data;
+}
+
+
+void FontConverterFramebufMono::paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image, const QVariantMap ¶meter) const
+{
+ FontConverter::paintOverlay(p, mode, image, parameter);
+ monoPaintOverlay(p, mode, image, parameter);
+}
diff --git a/FontConverterFramebufMono.hpp b/FontConverterFramebufMono.hpp
new file mode 100644
index 0000000..aaca602
--- /dev/null
+++ b/FontConverterFramebufMono.hpp
@@ -0,0 +1,39 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#pragma once
+
+
+#include "FontConverter.hpp"
+#include "MonoTools.hpp"
+
+
+/// A simple converter to create mono bitmap fonts.
+///
+class FontConverterFramebufMono : public FontConverter, public MonoTools
+{
+public:
+ /// ctor
+ ///
+ FontConverterFramebufMono();
+
+public: // implement FontConverter
+ QSize generatedSize(const QSize &imageSize, const QVariantMap ¶meter) const override;
+ QString generateCode(const QFont &font, const QVariantMap ¶meter) const override;
+ LegendDataPtr legendData(OverlayMode mode) const override;
+ void paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image, const QVariantMap ¶meter) const override;
+};
+
diff --git a/MainWindow.cpp b/MainWindow.cpp
index 522e40c..5597f8a 100644
--- a/MainWindow.cpp
+++ b/MainWindow.cpp
@@ -17,10 +17,12 @@
#include "MainWindow.hpp"
+#include "ApplicationController.hpp"
#include "BitmapPanel.hpp"
#include "ConverterFramebufMonoVLSB.hpp"
#include "ConverterFramebufMonoHLSB.hpp"
#include "ConverterFramebufMonoHMSB.hpp"
+#include "FontConverterFramebufMono.hpp"
#include
#include
@@ -37,6 +39,11 @@
#include
#include
#include
+#include
+#include
+#include
+#include
+#include
#include
@@ -47,6 +54,9 @@ MainWindow::MainWindow(QWidget *parent)
initializeUi();
initializeMenu();
loadSettings();
+ onFormatChanged();
+ onFontChanged();
+ onCharactersChanged();
}
@@ -60,13 +70,16 @@ void MainWindow::initializeConverterList()
_converterList.append(new ConverterFramebufMonoVLSB());
_converterList.append(new ConverterFramebufMonoHMSB());
_converterList.append(new ConverterFramebufMonoHLSB());
+ _converterList.append(new FontConverterFramebufMono());
}
void MainWindow::initializeUi()
{
+ const int cFixedWidth = 400;
+
setMinimumSize(800, 600);
- setWindowTitle(tr("Micropython Bitmap Tool - V%1 - Lucky Resistor").arg(qApp->applicationVersion()));
+ setWindowTitle(tr("MicroPython Bitmap Tool - V%1 - Lucky Resistor").arg(qApp->applicationVersion()));
auto centralWidget = new QWidget();
centralWidget->setObjectName("CentralWidget");
@@ -83,15 +96,16 @@ void MainWindow::initializeUi()
settingsLayout->setSpacing(4);
auto logo = new QLabel();
- logo->setFixedSize(300, 250);
+ logo->setFixedSize(cFixedWidth, 100);
logo->setPixmap(QPixmap(":/images/AppLogo.png"));
+ logo->setAlignment(Qt::AlignCenter);
settingsLayout->addWidget(logo);
auto versionLabel = new QLabel(tr("Version %1").arg(qApp->applicationVersion()));
versionLabel->setAlignment(Qt::AlignCenter);
settingsLayout->addWidget(versionLabel);
settingsLayout->addSpacing(16);
- settingsLayout->addWidget(new QLabel(tr("Generated Format:")));
+ settingsLayout->addWidget(new QLabel(tr("Generated Format:")));
_formatSelector = new QComboBox();
for (auto converter : _converterList) {
_formatSelector->addItem(converter->displayName());
@@ -99,20 +113,96 @@ void MainWindow::initializeUi()
_formatSelector->setCurrentIndex(0);
settingsLayout->addWidget(_formatSelector);
- settingsLayout->addStretch();
+ settingsLayout->addWidget(new QLabel(tr("Parameters:")));
- settingsLayout->addWidget(new QLabel(tr("Loaded Bitmap Info:")));
+ auto parameterScroll = new QScrollArea();
+ parameterScroll->setObjectName("ParameterScrollArea");
+ _parameterFrame = new QFrame();
+ _parameterFrame->setObjectName("ParameterFrame");
+ _parameterFrame->setFixedWidth(cFixedWidth);
+ _parameterLayout = new QFormLayout(_parameterFrame);
+ _parameterLayout->setContentsMargins(8, 8, 8, 8);
+ parameterScroll->setWidget(_parameterFrame);
+ parameterScroll->setWidgetResizable(true);
+ parameterScroll->setFixedWidth(cFixedWidth);
+ parameterScroll->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
+ //parameterScroll->setBackgroundRole(QPalette::Window);
+ settingsLayout->addWidget(parameterScroll);
+
+ _bitmapConverterFrame = new QFrame();
+ auto bitmapConverterLayout = new QVBoxLayout(_bitmapConverterFrame);
+ bitmapConverterLayout->setContentsMargins(0, 0, 0, 0);
+ bitmapConverterLayout->setSpacing(4);
+ settingsLayout->addWidget(_bitmapConverterFrame);
+
+ bitmapConverterLayout->addWidget(new QLabel(tr("Loaded Bitmap Info:")));
_bitmapInfo = new QLabel(tr("No Bitmap Loaded"));
_bitmapInfo->setObjectName("BitmapInfo");
- _bitmapInfo->setMinimumHeight(200);
+ _bitmapInfo->setMinimumHeight(100);
_bitmapInfo->setAlignment(Qt::AlignTop|Qt::AlignLeft);
- settingsLayout->addWidget(_bitmapInfo);
+ bitmapConverterLayout->addWidget(_bitmapInfo);
auto loadButton = new QPushButton();
loadButton->setText(tr("Load Bitmap"));
- settingsLayout->addWidget(loadButton);
+ bitmapConverterLayout->addWidget(loadButton);
connect(loadButton, &QPushButton::clicked, this, &MainWindow::onLoadBitmap);
+ _fontConverterFrame = new QFrame();
+ auto fontConverterLayout = new QVBoxLayout(_fontConverterFrame);
+ fontConverterLayout->setContentsMargins(0, 0, 0, 0);
+ fontConverterLayout->setSpacing(4);
+ settingsLayout->addWidget(_fontConverterFrame);
+
+ fontConverterLayout->addWidget(new QLabel(tr("Selected Font Info:")));
+ _fontInfo = new QLabel(tr("No Font Seleccted"));
+ _fontInfo->setObjectName("FontInfo");
+ _fontInfo->setMinimumHeight(100);
+ _fontInfo->setAlignment(Qt::AlignTop|Qt::AlignLeft);
+ fontConverterLayout->addWidget(_fontInfo);
+
+ fontConverterLayout->addWidget(new QLabel(tr("Selected Font:")));
+ _fontSelector = new QFontComboBox();
+ fontConverterLayout->addWidget(_fontSelector);
+ auto fontDetailsLayout = new QHBoxLayout();
+ fontDetailsLayout->setContentsMargins(0, 0, 0, 0);
+ fontDetailsLayout->setSpacing(4);
+ fontConverterLayout->addLayout(fontDetailsLayout);
+ _fontWeightSelector = new QComboBox();
+ _fontWeightSelector->addItem(tr("Thin"), static_cast(QFont::Thin));
+ _fontWeightSelector->addItem(tr("Extra Light"), static_cast(QFont::ExtraLight));
+ _fontWeightSelector->addItem(tr("Light"), static_cast(QFont::Light));
+ _fontWeightSelector->addItem(tr("Normal"), static_cast(QFont::Normal));
+ _fontWeightSelector->addItem(tr("Medium"), static_cast(QFont::Medium));
+ _fontWeightSelector->addItem(tr("Demi Bold"), static_cast(QFont::DemiBold));
+ _fontWeightSelector->addItem(tr("Bold"), static_cast(QFont::Bold));
+ _fontWeightSelector->addItem(tr("Extra Bold"), static_cast(QFont::ExtraBold));
+ _fontWeightSelector->addItem(tr("Black"), static_cast(QFont::Black));
+ _fontWeightSelector->setCurrentIndex(3);
+ _fontSizeSelector = new QSpinBox();
+ _fontSizeSelector->setRange(4, 200);
+ _fontSizeSelector->setValue(12);
+ _fontHinting = new QComboBox();
+ _fontHinting->addItem(tr("Default"), static_cast(QFont::PreferDefaultHinting));
+ _fontHinting->addItem(tr("None"), static_cast(QFont::PreferNoHinting));
+ _fontHinting->addItem(tr("Vertical"), static_cast(QFont::PreferVerticalHinting));
+ _fontHinting->addItem(tr("Full"), static_cast(QFont::PreferFullHinting));
+ _fontHinting->setCurrentIndex(0);
+ fontDetailsLayout->addWidget(new QLabel(tr("Size:")));
+ fontDetailsLayout->addWidget(_fontSizeSelector);
+ fontDetailsLayout->addWidget(new QLabel(tr("Weight:")));
+ fontDetailsLayout->addWidget(_fontWeightSelector);
+ fontDetailsLayout->addWidget(new QLabel(tr("Hinting:")));
+ fontDetailsLayout->addWidget(_fontHinting);
+ fontConverterLayout->addWidget(new QLabel(tr("Characters to convert:")));
+ _fontCharacters = new QPlainTextEdit();
+ _fontCharacters->setFixedHeight(100);
+ _fontCharacters->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
+ _fontCharacters->setWordWrapMode(QTextOption::WrapAnywhere);
+ _fontCharacters->setPlainText("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,:;!?()+-=\"'<>");
+ _fontCharacters->setReadOnly(true);
+ fontConverterLayout->addWidget(_fontCharacters);
+ connect(_fontCharacters, &QPlainTextEdit::textChanged, this, &MainWindow::onCharactersChanged);
+
auto previewSplittter = new QSplitter(Qt::Vertical);
previewSplittter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
previewSplittter->setChildrenCollapsible(false);
@@ -133,15 +223,9 @@ void MainWindow::initializeUi()
_codePreview->setWordWrapMode(QTextOption::NoWrap);
codeLayout->addWidget(_codePreview);
-#ifdef Q_OS_WIN32
- _codePreview->setFont(QFont("Consolas", 12));
-#else
-#ifdef Q_OS_MAC
- _codePreview->setFont(QFont("Menlo", 12));
-#else
- _codePreview->setFont(QFont("Lucida Console", 12));
-#endif
-#endif
+ const auto monospaceFont = gApp()->monospaceFont();
+ _codePreview->setFont(monospaceFont);
+ _fontCharacters->setFont(monospaceFont);
auto codeActions = new QFrame();
auto codeActionsLayout = new QHBoxLayout(codeActions);
@@ -161,11 +245,12 @@ void MainWindow::initializeUi()
previewSplittter->setStretchFactor(0, 4);
previewSplittter->setStretchFactor(1, 1);
- connect(_formatSelector, &QComboBox::currentIndexChanged, [=]{
- _bitmapPanel->setConverter(selectedConverter());
- updateBitmapInfo();
- updateCode();
- });
+ connect(_formatSelector, &QComboBox::currentIndexChanged, this, &MainWindow::onFormatChanged);
+ connect(_fontSelector, &QFontComboBox::currentFontChanged, this, &MainWindow::onFontChanged);
+ connect(_fontSizeSelector, &QSpinBox::valueChanged, this, &MainWindow::onFontChanged);
+ connect(_fontWeightSelector, &QComboBox::currentIndexChanged, this, &MainWindow::onFontChanged);
+ connect(_fontHinting, &QComboBox::currentIndexChanged, this, &MainWindow::onFontChanged);
+ connect(_bitmapPanel, &BitmapPanel::selectedCharacterChanged, this, &MainWindow::onSelectedCharacterChanged);
}
@@ -229,6 +314,18 @@ void MainWindow::loadSettings()
restoreGeometry(settings.value("mainWindow.geometry").toByteArray());
restoreState(settings.value("mainWindow.state").toByteArray());
_formatSelector->setCurrentIndex(settings.value("format.index").toInt(0));
+ _currentFont = QFont(settings.value("font.family", "Arial").toString());
+ _currentFont.setPixelSize(settings.value("font.size", 12).toInt());
+ _currentFont.setWeight(static_cast(settings.value("font.weight", 500).toInt()));
+ _fontSelector->setCurrentFont(_currentFont);
+ _fontSizeSelector->setValue(_currentFont.pixelSize());
+ const int index = _fontWeightSelector->findData(static_cast(_currentFont.weight()));
+ if (index >= 0) {
+ _fontWeightSelector->setCurrentIndex(index);
+ } else {
+ _fontWeightSelector->setCurrentIndex(3); // normal
+ }
+ _fontHinting->setCurrentIndex(settings.value("font.hinting", 0).toInt());
}
@@ -238,6 +335,10 @@ void MainWindow::saveSettings()
settings.setValue("mainWindow.geometry", saveGeometry());
settings.setValue("mainWindow.state", saveState());
settings.setValue("format.index", _formatSelector->currentIndex());
+ settings.setValue("font.family", _currentFont.family());
+ settings.setValue("font.size", _currentFont.pixelSize());
+ settings.setValue("font.weight", static_cast(_currentFont.weight()));
+ settings.setValue("font.hinting", _fontHinting->currentIndex());
}
@@ -251,42 +352,120 @@ Converter *MainWindow::selectedConverter() const
}
-void MainWindow::updateBitmapInfo()
+void MainWindow::updateInfoBox()
{
QString text;
QTextStream ts(&text);
- ts << "";
- ts << "Bitmap Size: " << _currentImage.width() << "x" << _currentImage.height() << "
";
- ts << "Bit Depth: " << _currentImage.depth() << "
";
- ts << "Color Format: ";
- switch (_currentImage.pixelFormat().colorModel()) {
- case QPixelFormat::RGB: ts << "RGB"; break;
- case QPixelFormat::BGR: ts << "BGR"; break;
- case QPixelFormat::Indexed: ts << "Indexed"; break;
- case QPixelFormat::Grayscale: ts << "Grayscale"; break;
- case QPixelFormat::CMYK: ts << "CMYK"; break;
- case QPixelFormat::HSL: ts << "HSL"; break;
- case QPixelFormat::HSV: ts << "HSV"; break;
- case QPixelFormat::YUV: ts << "YUV"; break;
- case QPixelFormat::Alpha: ts << "Alpha"; break;
+ if (selectedConverter()->mode() == Converter::Mode::Bitmap) {
+ ts << "
";
+ ts << "Bitmap Size: " << _currentImage.width() << "x" << _currentImage.height() << "
";
+ ts << "Bit Depth: " << _currentImage.depth() << "
";
+ ts << "Color Format: ";
+ switch (_currentImage.pixelFormat().colorModel()) {
+ case QPixelFormat::RGB: ts << "RGB"; break;
+ case QPixelFormat::BGR: ts << "BGR"; break;
+ case QPixelFormat::Indexed: ts << "Indexed"; break;
+ case QPixelFormat::Grayscale: ts << "Grayscale"; break;
+ case QPixelFormat::CMYK: ts << "CMYK"; break;
+ case QPixelFormat::HSL: ts << "HSL"; break;
+ case QPixelFormat::HSV: ts << "HSV"; break;
+ case QPixelFormat::YUV: ts << "YUV"; break;
+ case QPixelFormat::Alpha: ts << "Alpha"; break;
+ }
+ ts << "
";
+ const auto gs = selectedConverter()->generatedSize(_currentImage.size(), createParameterMap());
+ ts << "Generated Size: " << gs.width() << "x" << gs.height() << "
";
+ _bitmapInfo->setText(text);
+ } else {
+ ts << "";
+ ts << "Family: " << _currentFont.family() << "
";
+ ts << "Weight: ";
+ switch (_currentFont.weight()) {
+ case QFont::Thin: ts << tr("Thin"); break;
+ case QFont::ExtraLight: ts << tr("Extra Light"); break;
+ case QFont::Light: ts << tr("Light"); break;
+ case QFont::Normal: ts << tr("Normal"); break;
+ case QFont::Medium: ts << tr("Medium"); break;
+ case QFont::DemiBold: ts << tr("Demi Bold"); break;
+ case QFont::Bold: ts << tr("Bold"); break;
+ case QFont::ExtraBold: ts << tr("Extra Bold"); break;
+ case QFont::Black: ts << tr("Black"); break;
+ }
+ ts << "
";
+ ts << "Pixel Size: " << _currentFont.pixelSize() << "
";
+ ts << "
";
+ _fontInfo->setText(text);
}
- ts << "
";
- const auto gs = selectedConverter()->generatedSize(_currentImage.size());
- ts << "Generated Size: " << gs.width() << "x" << gs.height() << "
";
- _bitmapInfo->setText(text);
}
void MainWindow::updateCode()
{
QString code;
- if (!_currentImage.isNull()) {
- code = selectedConverter()->generateCode(_currentImage, QVariantMap());
+ if (selectedConverter()->mode() == Converter::Mode::Bitmap) {
+ auto bitmapConverter = static_cast(selectedConverter());
+ if (!_currentImage.isNull()) {
+ code = bitmapConverter->generateCode(_currentImage, QVariantMap());
+ }
+ } else {
+ auto fontConverter = static_cast(selectedConverter());
+ code = fontConverter->generateCode(_currentFont, createParameterMap());
}
_codePreview->setPlainText(code);
}
+void MainWindow::updateParameters()
+{
+ auto converter = selectedConverter();
+ if (converter == nullptr) {
+ return;
+ }
+
+ // Replace the current parameter definition.
+ _displayedParameters = converter->createParameterDefinition();
+ // Remove the previous UI
+ while (_parameterLayout->count() > 0) {
+ auto item = _parameterLayout->takeAt(0);
+ delete item;
+ }
+ for (auto w : _parameterFrame->findChildren()) {
+ w->deleteLater();
+ }
+ // Build the new parameter UI.
+ if (_displayedParameters->parameterList().isEmpty()) {
+ auto label = new QLabel();
+ label->setText(tr("No Parameters"));
+ _parameterLayout->addWidget(label);
+ } else {
+ for (const auto ¶meter : _displayedParameters->parameterList()) {
+ auto pw = parameterFactory.createWidget(parameter);
+ pw->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+ pw->setObjectName(parameter->identifier());
+ _parameterLayout->addRow(parameter->label() + ":", pw);
+ connect(pw, &ParameterWidget::valueChanged, this, &MainWindow::onParameterChanged);
+ }
+ }
+ auto stretchItem = new QWidget();
+ stretchItem->setFixedWidth(10);
+ stretchItem->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
+ _parameterLayout->addRow(stretchItem);
+}
+
+
+QVariantMap MainWindow::createParameterMap() const
+{
+ QVariantMap result;
+ result["characters"] = _fontCharacters->toPlainText();
+ result["font"] = _currentFont;
+ result["char"] = _bitmapPanel->selectedCharacter();
+ for (auto pw : _parameterFrame->findChildren()) {
+ result[pw->objectName()] = pw->value();
+ }
+ return result;
+}
+
+
void MainWindow::onLoadBitmap()
{
QSettings settings;
@@ -320,11 +499,78 @@ void MainWindow::onLoadBitmap()
_currentImage = newImage;
_bitmapPanel->setImage(newImage);
_bitmapPanel->setConverter(selectedConverter());
- updateBitmapInfo();
+ updateInfoBox();
updateCode();
}
+void MainWindow::onFormatChanged()
+{
+ const auto converter = selectedConverter();
+ _bitmapPanel->setConverter(converter);
+ if (converter->mode() == Converter::Mode::Bitmap) {
+ _bitmapConverterFrame->setVisible(true);
+ _fontConverterFrame->setVisible(false);
+ } else {
+ _bitmapConverterFrame->setVisible(false);
+ _fontConverterFrame->setVisible(true);
+ }
+ updateParameters();
+ updateInfoBox();
+ updateCode();
+ _bitmapPanel->setParameter(createParameterMap());
+ onSelectedCharacterChanged(_bitmapPanel->selectedCharacter());
+}
+
+
+void MainWindow::onFontChanged()
+{
+ _currentFont = _fontSelector->currentFont();
+ _currentFont.setWeight(static_cast(_fontWeightSelector->currentData().toInt()));
+ _currentFont.setPixelSize(_fontSizeSelector->value());
+ const auto hintingPreferences = static_cast(_fontHinting->currentData().toInt());
+ _currentFont.setHintingPreference(hintingPreferences);
+ updateInfoBox();
+ updateCode();
+ _bitmapPanel->setParameter(createParameterMap());
+ onSelectedCharacterChanged(_bitmapPanel->selectedCharacter());
+}
+
+
+void MainWindow::onCharactersChanged()
+{
+ auto characters = _fontCharacters->toPlainText();
+ _bitmapPanel->setCharacters(characters);
+ _bitmapPanel->setConverter(selectedConverter());
+ _bitmapPanel->setParameter(createParameterMap());
+ onSelectedCharacterChanged(_bitmapPanel->selectedCharacter());
+}
+
+
+void MainWindow::onSelectedCharacterChanged(QChar c)
+{
+ auto converter = selectedConverter();
+ if (converter == nullptr) {
+ return;
+ }
+ if (converter->mode() == Converter::Mode::Font) {
+ auto fontConverter = static_cast(converter);
+ auto newImage = fontConverter->generateImage(_currentFont, c, createParameterMap());
+ _currentImage = newImage;
+ _bitmapPanel->setImage(newImage);
+ _bitmapPanel->setConverter(selectedConverter());
+ _bitmapPanel->setParameter(createParameterMap());
+ }
+}
+
+
+void MainWindow::onParameterChanged()
+{
+ _bitmapPanel->setParameter(createParameterMap());
+ onSelectedCharacterChanged(_bitmapPanel->selectedCharacter());
+}
+
+
void MainWindow::closeEvent(QCloseEvent *event)
{
saveSettings();
diff --git a/MainWindow.hpp b/MainWindow.hpp
index 4107239..e9d7b84 100644
--- a/MainWindow.hpp
+++ b/MainWindow.hpp
@@ -17,6 +17,10 @@
#pragma once
+#include "ParameterDefinition.hpp"
+#include "ParameterFactory.hpp"
+
+#include
#include
@@ -25,6 +29,11 @@ class QPlainTextEdit;
class QComboBox;
class QLabel;
class BitmapPanel;
+class QFrame;
+class QFontComboBox;
+class QLineEdit;
+class QSpinBox;
+class QFormLayout;
/// The main widnow
@@ -64,26 +73,73 @@ private:
/// Update the bitmap info.
///
- void updateBitmapInfo();
+ void updateInfoBox();
/// Update the code.
///
void updateCode();
+ /// Update the parameter frame for the current converter.
+ ///
+ void updateParameters();
+
+ /// Get the current parameters
+ ///
+ QVariantMap createParameterMap() const;
+
private Q_SLOTS:
/// Load a bitmap.
///
void onLoadBitmap();
+ /// After a new converter is selected.
+ ///
+ void onFormatChanged();
+
+ /// After a new font is selected.
+ ///
+ void onFontChanged();
+
+ /// After the character list has changed
+ ///
+ void onCharactersChanged();
+
+ /// If the selected character changed
+ ///
+ void onSelectedCharacterChanged(QChar c);
+
+ /// After a parameter has changed.
+ ///
+ void onParameterChanged();
+
protected: // Implement QWidget
void closeEvent(QCloseEvent *event) override;
private:
+ ParameterFactory parameterFactory; ///< The parameter factory.
+
QComboBox *_formatSelector; ///< The format selector.
QPlainTextEdit *_codePreview; ///< The generated code.
BitmapPanel *_bitmapPanel; ///< The bitmap panel.
- QImage _currentImage; ///< The current loaded image
+
+ QFrame *_parameterFrame; ///< The frame with the parameters.
+ QFormLayout *_parameterLayout; ///< The parameter layout.
+ ParameterDefinitionPtr _displayedParameters; ///< The currently displayed parameters.
+
+ QImage _currentImage; ///< The current loaded image for bitmap converters.
+ QFont _currentFont; ///< The currently selected font for font converters.
+
+ QFrame *_bitmapConverterFrame; ///< The frame for bitmap converters.
QLabel *_bitmapInfo; ///< The label with the image info.
+
+ QFrame *_fontConverterFrame; ///< The frame for font converters.
+ QLabel *_fontInfo; ///< The label with the font info.
+ QFontComboBox *_fontSelector; ///< The combo box to select a new font.
+ QComboBox *_fontWeightSelector; ///< The selector for the font weight.
+ QSpinBox *_fontSizeSelector; ///< The selector for the used font size.
+ QComboBox *_fontHinting; ///< The hinting settings for the font.
+ QPlainTextEdit *_fontCharacters; ///< The characters of the font to be converted.
+
QList _converterList; ///< A list of available converters.
};
diff --git a/MicropythonBitmapTool.pro b/MicropythonBitmapTool.pro
index 29fb710..9d04c53 100644
--- a/MicropythonBitmapTool.pro
+++ b/MicropythonBitmapTool.pro
@@ -3,6 +3,7 @@ QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
+CONFIG += sdk_no_version_check
TARGET = "MicroPythonBitmapTool"
@@ -11,6 +12,8 @@ TARGET = "MicroPythonBitmapTool"
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
+ ApplicationController.cpp \
+ BitmapConverter.cpp \
BitmapPanel.cpp \
BitmapPreview.cpp \
Converter.cpp \
@@ -19,13 +22,22 @@ SOURCES += \
ConverterFramebufMonoHLSB.cpp \
ConverterFramebufMonoHMSB.cpp \
ConverterFramebufMonoVLSB.cpp \
+ FontConverter.cpp \
+ FontConverterFramebufMono.cpp \
LegendData.cpp \
LegendEntry.cpp \
+ MonoTools.cpp \
OverlayPainter.cpp \
+ ParameterDefinition.cpp \
+ ParameterEntry.cpp \
+ ParameterFactory.cpp \
+ ParameterWidget.cpp \
main.cpp \
MainWindow.cpp
HEADERS += \
+ ApplicationController.hpp \
+ BitmapConverter.hpp \
BitmapPanel.hpp \
BitmapPreview.hpp \
Converter.hpp \
@@ -34,11 +46,19 @@ HEADERS += \
ConverterFramebufMonoHLSB.hpp \
ConverterFramebufMonoHMSB.hpp \
ConverterFramebufMonoVLSB.hpp \
+ FontConverter.hpp \
+ FontConverterFramebufMono.hpp \
LegendData.hpp \
LegendEntry.hpp \
MainWindow.hpp \
+ MonoTools.hpp \
OverlayMode.hpp \
- OverlayPainter.hpp
+ OverlayPainter.hpp \
+ ParameterDefinition.hpp \
+ ParameterEntry.hpp \
+ ParameterFactory.hpp \
+ ParameterType.hpp \
+ ParameterWidget.hpp
RESOURCES += \
data/data.qrc
diff --git a/MonoTools.cpp b/MonoTools.cpp
new file mode 100644
index 0000000..f48dbee
--- /dev/null
+++ b/MonoTools.cpp
@@ -0,0 +1,134 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#include "MonoTools.hpp"
+
+
+MonoTools::MonoTools(MonoTools::UnitOrientation unitOrientation, MonoTools::BitDirection bitDirection, int unitSize)
+ : _unitOrientation(unitOrientation), _bitDirection(bitDirection), _unitSize(unitSize)
+{
+}
+
+
+void MonoTools::addMonoLegendData(LegendDataPtr data, OverlayMode mode) const
+{
+ if (mode == OverlayMode::BitAssigments) {
+ data->addEntry(colorBitAssignment1, colorBitAssignment2, QObject::tr("Bit Assignment"));
+ } else {
+ data->addEntry(colorPixelInterpretation, QObject::tr("Pixel Interpretation"));
+ }
+}
+
+
+QSize MonoTools::monoGeneratedSize(const QSize &imageSize, const QVariantMap&) const
+{
+ if (_unitOrientation == UnitOrientation::Vertical) {
+ if ((imageSize.height() % _unitSize) != 0) {
+ return QSize(imageSize.width(), ((imageSize.height()/_unitSize)+1)*_unitSize);
+ } else {
+ return imageSize;
+ }
+ } else {
+ if ((imageSize.width() % _unitSize) != 0) {
+ return QSize(((imageSize.width()/_unitSize)+1)*_unitSize, imageSize.height());
+ } else {
+ return imageSize;
+ }
+ }
+}
+
+
+void MonoTools::monoPaintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image, const QVariantMap&) const
+{
+ if (mode == OverlayMode::BitAssigments) {
+ const auto bitL = (_bitDirection == BitDirection::LSB ? "0" : QString::number(_unitSize-1));
+ const auto bitH = (_bitDirection == BitDirection::LSB ? QString::number(_unitSize-1) : "0");
+ bool colorFlag = false;
+ if (_unitOrientation == UnitOrientation::Vertical) {
+ for (int y = 0; y < p.imageSize().height(); y += _unitSize) {
+ for (int x = 0; x < p.imageSize().width(); ++x) {
+ QRect rect(x, y, 1, _unitSize);
+ if (p.arePixelUpdated(rect)) {
+ const auto color = colorFlag ? colorBitAssignment1 : colorBitAssignment2;
+ p.drawPixelOutline(rect, color, 1);
+ p.drawPixelText(QRect(x, y, 1, 1), color, bitL);
+ p.drawPixelText(QRect(x, y+_unitSize-1, 1, 1), color, bitH);
+ }
+ colorFlag = !colorFlag;
+ }
+ if (p.imageSize().width() % 2 == 0) {
+ colorFlag = !colorFlag;
+ }
+ }
+ } else {
+ for (int y = 0; y < p.imageSize().height(); ++y) {
+ for (int x = 0; x < p.imageSize().width(); x += _unitSize) {
+ QRect rect(x, y, _unitSize, 1);
+ if (p.arePixelUpdated(rect)) {
+ const auto color = colorFlag ? colorBitAssignment1 : colorBitAssignment2;
+ p.drawPixelOutline(rect, color, 1);
+ p.drawPixelText(QRect(x, y, 1, 1), color, bitH);
+ p.drawPixelText(QRect(x+_unitSize-1, y, 1, 1), color, bitL);
+ }
+ colorFlag = !colorFlag;
+ }
+ if ((p.imageSize().width()/_unitSize) % 2 == 0) {
+ colorFlag = !colorFlag;
+ }
+ }
+ }
+ } else if (mode == OverlayMode::PixelInterpretation) {
+ for (int y = 0; y < p.generatedSize().height(); ++y) {
+ for (int x = 0; x < p.generatedSize().width(); ++x) {
+ auto text = (getPixel(x, y, image) ? "1" : "0");
+ const QRect rect(x, y, 1, 1);
+ if (p.arePixelUpdated(rect)) {
+ p.drawPixelText(rect, colorPixelInterpretation, text);
+ }
+ }
+ }
+ }
+}
+
+
+bool MonoTools::getPixel(int x, int y, const QImage &image)
+{
+ if (x < 0 || y < 0 || x >= image.width() || y >= image.height()) {
+ return false;
+ }
+ auto color = image.pixelColor(x, y);
+ float h, s, l, a;
+ color.getHslF(&h, &s, &l, &a);
+ if (a < 0.5) {
+ return false;
+ }
+ return l < 0.5;
+}
+
+
+uint32_t MonoTools::readUnit(int x, int y, int dx, int dy, int count, const QImage &image)
+{
+ uint32_t result = 0;
+ for (int i = 0; i < count; ++i) {
+ result <<= 1;
+ if (getPixel(x, y, image)) {
+ result |= 0b1;
+ }
+ x += dx;
+ y += dy;
+ }
+ return result;
+}
diff --git a/MonoTools.hpp b/MonoTools.hpp
new file mode 100644
index 0000000..f31b8cd
--- /dev/null
+++ b/MonoTools.hpp
@@ -0,0 +1,83 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#pragma once
+
+
+#include "LegendData.hpp"
+#include "OverlayPainter.hpp"
+#include "OverlayMode.hpp"
+#include "ParameterDefinition.hpp"
+
+#include
+#include
+
+
+class MonoTools
+{
+public:
+ enum class UnitOrientation {
+ Horizontal,
+ Vertical
+ };
+
+ enum class BitDirection {
+ LSB,
+ MSB
+ };
+
+public:
+ /// ctor
+ ///
+ MonoTools(UnitOrientation unitOrientation,
+ BitDirection bitDirection,
+ int unitSize);
+
+ /// Legend data for mono conversion
+ ///
+ void addMonoLegendData(LegendDataPtr data, OverlayMode mode) const;
+
+ /// The generated size for mono conversion.
+ ///
+ QSize monoGeneratedSize(const QSize &imageSize, const QVariantMap ¶meter) const;
+
+ /// Paint overlay for mono data.
+ ///
+ void monoPaintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image, const QVariantMap ¶meter) const;
+
+ /// Interpret a single pixel.
+ ///
+ /// Returns `false` if the pixel is out of bounds.
+ ///
+ static bool getPixel(int x, int y, const QImage &image);
+
+ /// Read a single unit.
+ ///
+ static uint32_t readUnit(int x, int y, int dx, int dy, int count, const QImage &image);
+
+public:
+ /// The colors for the bit assignments
+ ///
+ static constexpr QColor colorBitAssignment1 = QColor(240, 40, 40);
+ static constexpr QColor colorBitAssignment2 = QColor(240, 80, 80);
+ static constexpr QColor colorPixelInterpretation = QColor(240, 240, 40);
+
+protected:
+ UnitOrientation _unitOrientation; ///< The unit orientatioon.
+ BitDirection _bitDirection; ///< The bit direction.
+ int _unitSize; ///< The number of bits per unit.
+};
+
diff --git a/ParameterDefinition.cpp b/ParameterDefinition.cpp
new file mode 100644
index 0000000..2d05662
--- /dev/null
+++ b/ParameterDefinition.cpp
@@ -0,0 +1,81 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#include "ParameterDefinition.hpp"
+
+
+ParameterDefinitionPtr ParameterDefinition::create()
+{
+ return ParameterDefinitionPtr(new ParameterDefinition());
+}
+
+
+void ParameterDefinition::addCheckbox(
+ const QString &identifier,
+ const QString &label,
+ bool defaultValue)
+{
+ QVariantMap settings;
+ settings["default"] = defaultValue;
+ _parameterList.append(ParameterEntry::create(
+ ParameterType::Checkbox, identifier, label, settings));
+}
+
+
+void ParameterDefinition::addInteger(
+ const QString &identifier,
+ const QString &label,
+ int defaultValue,
+ int minimum,
+ int maximum)
+{
+ QVariantMap settings;
+ settings["default"] = defaultValue;
+ settings["minimum"] = minimum;
+ settings["maximum"] = maximum;
+ _parameterList.append(ParameterEntry::create(ParameterType::IntegerValue, identifier, label, settings));
+}
+
+
+void ParameterDefinition::addIntegerSize(const QString &identifier, const QString &label, QSize defaultValue, QSize minimum, QSize maximum)
+{
+ QVariantMap settings;
+ settings["default"] = defaultValue;
+ settings["minimum"] = minimum;
+ settings["maximum"] = maximum;
+ _parameterList.append(ParameterEntry::create(ParameterType::IntegerSize, identifier, label, settings));
+}
+
+
+void ParameterDefinition::addIntegerPosition(const QString &identifier, const QString &label, QPoint defaultValue, QPoint minimum, QPoint maximum)
+{
+ QVariantMap settings;
+ settings["default"] = defaultValue;
+ settings["minimum"] = minimum;
+ settings["maximum"] = maximum;
+ _parameterList.append(ParameterEntry::create(ParameterType::IntegerPosition, identifier, label, settings));
+}
+
+
+const ParameterDefinition::ParameterList &ParameterDefinition::parameterList() const
+{
+ return _parameterList;
+}
+
+
+ParameterDefinition::ParameterDefinition()
+{
+}
diff --git a/ParameterDefinition.hpp b/ParameterDefinition.hpp
new file mode 100644
index 0000000..5e61b8a
--- /dev/null
+++ b/ParameterDefinition.hpp
@@ -0,0 +1,73 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#pragma once
+
+
+#include "ParameterEntry.hpp"
+
+#include
+#include
+#include
+
+
+class ParameterDefinition;
+using ParameterDefinitionPtr = QSharedPointer;
+using ParameterDefinitionPtrConst = QSharedPointer;
+
+
+/// The definition of parameters, returned by a converter.
+///
+class ParameterDefinition
+{
+public:
+ /// A parameter list.
+ ///
+ using ParameterList = QList;
+
+public:
+ /// Create a new parameter definition.
+ ///
+ static ParameterDefinitionPtr create();
+
+public:
+ /// Add a checkbox parameter.
+ ///
+ void addCheckbox(const QString &identifier, const QString &label, bool defaultValue);
+
+ /// Add an integer parameter.
+ ///
+ void addInteger(const QString &identifier, const QString &label, int defaultValue, int minimum, int maximum);
+
+ /// Add an integer size parameter.
+ ///
+ void addIntegerSize(const QString &identifier, const QString &label, QSize defaultValue, QSize minimum, QSize maximum);
+
+ /// Add an integer position parameter.
+ ///
+ void addIntegerPosition(const QString &identifier, const QString &label, QPoint defaultValue, QPoint minimum, QPoint maximum);
+
+ /// Get the parameter list.
+ ///
+ const ParameterList& parameterList() const;
+
+private:
+ ParameterDefinition();
+
+private:
+ ParameterList _parameterList; ///< The list with all parameters.
+};
+
diff --git a/ParameterEntry.cpp b/ParameterEntry.cpp
new file mode 100644
index 0000000..12c776b
--- /dev/null
+++ b/ParameterEntry.cpp
@@ -0,0 +1,65 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#include "ParameterEntry.hpp"
+
+
+ParameterEntryPtr ParameterEntry::create(
+ ParameterType type,
+ const QString &identifier,
+ const QString &label,
+ const QVariantMap &settings)
+{
+ return ParameterEntryPtr(new ParameterEntry(type, identifier, label, settings));
+}
+
+
+ParameterType ParameterEntry::type() const
+{
+ return _type;
+}
+
+
+QString ParameterEntry::identifier() const
+{
+ return _identifier;
+}
+
+
+QString ParameterEntry::label() const
+{
+ return _label;
+}
+
+
+QVariantMap ParameterEntry::settings() const
+{
+ return _settings;
+}
+
+
+ParameterEntry::ParameterEntry(
+ ParameterType type,
+ const QString &identifier,
+ const QString &label,
+ const QVariantMap &settings)
+:
+ _type(type),
+ _identifier(identifier),
+ _label(label),
+ _settings(settings)
+{
+}
diff --git a/ParameterEntry.hpp b/ParameterEntry.hpp
new file mode 100644
index 0000000..c68bc7c
--- /dev/null
+++ b/ParameterEntry.hpp
@@ -0,0 +1,74 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#pragma once
+
+
+#include "ParameterType.hpp"
+
+#include
+#include
+#include
+
+
+class ParameterEntry;
+using ParameterEntryPtr = QSharedPointer;
+
+
+/// One entry in the parameter definition.
+///
+class ParameterEntry
+{
+public:
+ static ParameterEntryPtr create(
+ ParameterType type,
+ const QString &identifier,
+ const QString &label,
+ const QVariantMap &settings);
+
+public:
+ /// The parameter type.
+ ///
+ ParameterType type() const;
+
+ /// The identifier of the parameter.
+ ///
+ QString identifier() const;
+
+ /// The label for the parameter.
+ ///
+ QString label() const;
+
+ /// Settings for the parameter.
+ ///
+ QVariantMap settings() const;
+
+private:
+ /// Create a new raw paremeter entry.
+ ///
+ ParameterEntry(
+ ParameterType type,
+ const QString &identifier,
+ const QString &label,
+ const QVariantMap &settings);
+
+private:
+ ParameterType _type;
+ QString _identifier;
+ QString _label;
+ QVariantMap _settings;
+};
+
diff --git a/ParameterFactory.cpp b/ParameterFactory.cpp
new file mode 100644
index 0000000..3c18a51
--- /dev/null
+++ b/ParameterFactory.cpp
@@ -0,0 +1,40 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#include "ParameterFactory.hpp"
+
+
+ParameterFactory::ParameterFactory()
+{
+}
+
+
+ParameterWidget *ParameterFactory::createWidget(const ParameterEntryPtr ¶meter) const
+{
+ switch (parameter->type()) {
+ case ParameterType::Checkbox:
+ return new CheckBoxParameter(parameter);
+ case ParameterType::IntegerValue:
+ return new IntegerParameter(parameter);
+ case ParameterType::IntegerSize:
+ return new IntegerSizeParameter(parameter);
+ case ParameterType::IntegerPosition:
+ return new IntegerPositionParameter(parameter);
+ default:
+ break;
+ }
+ return nullptr;
+}
diff --git a/ParameterFactory.hpp b/ParameterFactory.hpp
new file mode 100644
index 0000000..ef767ea
--- /dev/null
+++ b/ParameterFactory.hpp
@@ -0,0 +1,37 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#pragma once
+
+
+#include "ParameterWidget.hpp"
+
+#include
+
+
+/// A factory to handle the generic parameters.
+///
+class ParameterFactory
+{
+public:
+ ParameterFactory();
+
+public:
+ /// Create the widget for to edit a parameter.
+ ///
+ ParameterWidget *createWidget(const ParameterEntryPtr ¶meter) const;
+};
+
diff --git a/ParameterType.hpp b/ParameterType.hpp
new file mode 100644
index 0000000..8ee36ff
--- /dev/null
+++ b/ParameterType.hpp
@@ -0,0 +1,28 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#pragma once
+
+
+/// The parameter type.
+///
+enum class ParameterType {
+ Checkbox, ///< A boolean parameter
+ IntegerValue, ///< An integer value.
+ IntegerSize, ///< A size value
+ IntegerPosition, ///< A position value.
+};
+
diff --git a/ParameterWidget.cpp b/ParameterWidget.cpp
new file mode 100644
index 0000000..c42536b
--- /dev/null
+++ b/ParameterWidget.cpp
@@ -0,0 +1,173 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#include "ParameterWidget.hpp"
+
+
+#include
+#include
+#include
+#include
+
+
+ParameterWidget::ParameterWidget(const ParameterEntryPtr ¶meter, QWidget *parent)
+ : QWidget(parent), _currentValue(parameter->settings()["default"])
+{
+}
+
+
+CheckBoxParameter::CheckBoxParameter(const ParameterEntryPtr ¶meter, QWidget *parent)
+ : ParameterWidget(parameter, parent)
+{
+ auto mainLayout = new QHBoxLayout(this);
+ mainLayout->setContentsMargins(0, 0, 0, 0);
+ mainLayout->setSpacing(2);
+ _value = new QCheckBox();
+ mainLayout->addWidget(_value);
+ _value->setChecked(_currentValue.toBool());
+ connect(_value, &QCheckBox::toggled, this, &CheckBoxParameter::valueChanged);
+}
+
+
+QVariant CheckBoxParameter::value() const
+{
+ return static_cast(_value->isChecked());
+}
+
+
+void CheckBoxParameter::setValue(const QVariant &value)
+{
+ if (value != _currentValue) {
+ _currentValue = value;
+ _value->setChecked(value.toBool());
+ }
+}
+
+
+IntegerParameter::IntegerParameter(const ParameterEntryPtr ¶meter, QWidget *parent)
+ : ParameterWidget(parameter, parent)
+{
+ auto mainLayout = new QHBoxLayout(this);
+ mainLayout->setContentsMargins(0, 0, 0, 0);
+ mainLayout->setSpacing(2);
+ _value = new QSpinBox();
+ _value->setRange(
+ parameter->settings()["minimum"].toInt(),
+ parameter->settings()["maximum"].toInt()
+ );
+ mainLayout->addWidget(_value);
+ _value->setValue(_currentValue.toInt());
+ connect(_value, &QSpinBox::valueChanged, this, &CheckBoxParameter::valueChanged);
+}
+
+
+QVariant IntegerParameter::value() const
+{
+ return _value->value();
+}
+
+
+void IntegerParameter::setValue(const QVariant &value)
+{
+ if (value != _currentValue) {
+ _value->setValue(value.toInt());
+ }
+}
+
+
+IntegerSizeParameter::IntegerSizeParameter(const ParameterEntryPtr ¶meter, QWidget *parent)
+ : ParameterWidget(parameter, parent)
+{
+ auto mainLayout = new QHBoxLayout(this);
+ mainLayout->setContentsMargins(0, 0, 0, 0);
+ mainLayout->setSpacing(2);
+ mainLayout->addWidget(new QLabel(tr("W:")));
+ _a = new QSpinBox();
+ _a->setRange(
+ parameter->settings()["minimum"].toSize().width(),
+ parameter->settings()["maximum"].toSize().width()
+ );
+ mainLayout->addWidget(_a);
+ _a->setValue(_currentValue.toSize().width());
+ connect(_a, &QSpinBox::valueChanged, this, &CheckBoxParameter::valueChanged);
+ mainLayout->addWidget(new QLabel(tr("H:")));
+ _b = new QSpinBox();
+ _b->setRange(
+ parameter->settings()["minimum"].toSize().height(),
+ parameter->settings()["maximum"].toSize().height()
+ );
+ mainLayout->addWidget(_b);
+ _b->setValue(_currentValue.toSize().height());
+ connect(_b, &QSpinBox::valueChanged, this, &CheckBoxParameter::valueChanged);
+}
+
+
+QVariant IntegerSizeParameter::value() const
+{
+ return QSize(_a->value(), _b->value());
+}
+
+
+void IntegerSizeParameter::setValue(const QVariant &value)
+{
+ if (_currentValue != value) {
+ _a->setValue(value.toSize().width());
+ _b->setValue(value.toSize().height());
+ }
+}
+
+
+IntegerPositionParameter::IntegerPositionParameter(const ParameterEntryPtr ¶meter, QWidget *parent)
+ : ParameterWidget(parameter, parent)
+{
+ auto mainLayout = new QHBoxLayout(this);
+ mainLayout->setContentsMargins(0, 0, 0, 0);
+ mainLayout->setSpacing(2);
+ mainLayout->addWidget(new QLabel(tr("X:")));
+ _a = new QSpinBox();
+ _a->setRange(
+ parameter->settings()["minimum"].toPoint().x(),
+ parameter->settings()["maximum"].toPoint().x()
+ );
+ mainLayout->addWidget(_a);
+ _a->setValue(_currentValue.toPoint().x());
+ connect(_a, &QSpinBox::valueChanged, this, &CheckBoxParameter::valueChanged);
+ mainLayout->addWidget(new QLabel(tr("Y:")));
+ _b = new QSpinBox();
+ _b->setRange(
+ parameter->settings()["minimum"].toPoint().y(),
+ parameter->settings()["maximum"].toPoint().y()
+ );
+ mainLayout->addWidget(_b);
+ _b->setValue(_currentValue.toPoint().y());
+ connect(_b, &QSpinBox::valueChanged, this, &CheckBoxParameter::valueChanged);
+}
+
+
+QVariant IntegerPositionParameter::value() const
+{
+ return QPoint(_a->value(), _b->value());
+}
+
+
+void IntegerPositionParameter::setValue(const QVariant &value)
+{
+ if (_currentValue != value) {
+ _a->setValue(value.toPoint().x());
+ _b->setValue(value.toPoint().y());
+ }
+}
+
diff --git a/ParameterWidget.hpp b/ParameterWidget.hpp
new file mode 100644
index 0000000..99d72f2
--- /dev/null
+++ b/ParameterWidget.hpp
@@ -0,0 +1,114 @@
+//
+// (c)2021 by Lucky Resistor. https://luckyresistor.me/
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+#pragma once
+
+
+#include "ParameterEntry.hpp"
+
+#include
+
+
+class QCheckBox;
+class QSpinBox;
+
+
+/// The base class of all parameter widgets.
+///
+class ParameterWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ /// Create the widget.
+ ///
+ ParameterWidget(const ParameterEntryPtr ¶meter, QWidget *parent = nullptr);
+
+ /// Get the current value for the widget.
+ ///
+ virtual QVariant value() const = 0;
+
+ /// Set the value for this widget.
+ ///
+ virtual void setValue(const QVariant &value) = 0;
+
+signals:
+ /// Emitted if the value for this parameter changes.
+ ///
+ void valueChanged();
+
+protected:
+ QVariant _currentValue; ///< Buffer to limit signals.
+};
+
+
+class CheckBoxParameter : public ParameterWidget
+{
+ Q_OBJECT
+
+public:
+ CheckBoxParameter(const ParameterEntryPtr ¶meter, QWidget *parent = nullptr);
+ QVariant value() const override;
+ void setValue(const QVariant &value) override;
+
+private:
+ QCheckBox *_value;
+};
+
+
+class IntegerParameter : public ParameterWidget
+{
+ Q_OBJECT
+
+public:
+ IntegerParameter(const ParameterEntryPtr ¶meter, QWidget *parent = nullptr);
+ QVariant value() const override;
+ void setValue(const QVariant &value) override;
+
+private:
+ QSpinBox *_value;
+};
+
+
+class IntegerSizeParameter : public ParameterWidget
+{
+ Q_OBJECT
+
+public:
+ IntegerSizeParameter(const ParameterEntryPtr ¶meter, QWidget *parent = nullptr);
+ QVariant value() const override;
+ void setValue(const QVariant &value) override;
+
+private:
+ QSpinBox *_a;
+ QSpinBox *_b;
+};
+
+
+class IntegerPositionParameter : public ParameterWidget
+{
+ Q_OBJECT
+
+public:
+ IntegerPositionParameter(const ParameterEntryPtr ¶meter, QWidget *parent = nullptr);
+ QVariant value() const override;
+ void setValue(const QVariant &value) override;
+
+private:
+ QSpinBox *_a;
+ QSpinBox *_b;
+};
+
diff --git a/data/AppLogo.png b/data/AppLogo.png
index 159a917..c099c94 100644
Binary files a/data/AppLogo.png and b/data/AppLogo.png differ
diff --git a/data/AppLogo@2x.png b/data/AppLogo@2x.png
index a26784f..0cf0af6 100644
Binary files a/data/AppLogo@2x.png and b/data/AppLogo@2x.png differ
diff --git a/data/AppLogo@3x.png b/data/AppLogo@3x.png
index 3c1a363..bf245a2 100644
Binary files a/data/AppLogo@3x.png and b/data/AppLogo@3x.png differ
diff --git a/data/application.css b/data/application.css
index 53ee096..6ff17f5 100644
--- a/data/application.css
+++ b/data/application.css
@@ -14,8 +14,16 @@
color: #f8f8f8;
}
-#BitmapInfo {
+#BitmapInfo, #FontInfo {
border: 1px solid rgba(0,0,0,0.25);
padding: 8px;
margin: 0px 0px 16px 0px;
}
+
+#ParameterScrollArea {
+ border: none;
+}
+
+#ParameterFrame {
+ background-color: #616875;
+}
diff --git a/main.cpp b/main.cpp
index 3cc1424..7b68f09 100644
--- a/main.cpp
+++ b/main.cpp
@@ -14,16 +14,19 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
-#include "MainWindow.hpp"
+
+
+#include "ApplicationController.hpp"
#include
#include
+
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setApplicationName("MicroPython Bitmap Tool");
- a.setApplicationVersion("1.0.1");
+ a.setApplicationVersion("1.2.0");
a.setApplicationDisplayName("MicroPython Bitmap Tool");
a.setOrganizationDomain("luckyresistor.me");
a.setOrganizationName("Lucky Resistoor");
@@ -32,7 +35,6 @@ int main(int argc, char *argv[])
a.setStyleSheet(QString::fromUtf8(styleSheet.readAll()));
styleSheet.close();
- MainWindow w;
- w.show();
+ ApplicationController app;
return a.exec();
}