From 1bed9545c91ca57146b07ca1d62e37f94180aacf Mon Sep 17 00:00:00 2001
From: Shaun Reed <shaunrd0@gmail.com>
Date: Sat, 8 Mar 2025 11:24:13 -0500
Subject: [PATCH] Clean up qtk.

---
 .clang-format                    |  3 ++-
 .clang-tidy                      |  1 -
 .gitignore                       |  2 +-
 README.md                        | 23 ++++++++---------------
 example-app/examplescene.cpp     |  5 ++++-
 src/app/debugconsole.h           |  2 +-
 src/app/main.cpp                 |  7 +------
 src/app/qtkmainwindow.cpp        |  8 ++++++--
 src/app/qtkscene.cpp             |  2 +-
 src/app/qtkscene.h               |  4 ++--
 src/app/qtkwidget.h              |  2 +-
 src/app/treeview.cpp             |  2 +-
 src/app/widgetplugin.cpp         |  2 +-
 src/app/widgetplugincollection.h |  2 +-
 src/qtk/input.cpp                | 16 ++++++++--------
 src/qtk/meshrenderer.h           |  4 ++--
 src/qtk/model.h                  |  4 ++--
 src/qtk/modelmesh.h              |  6 ++++--
 src/qtk/object.h                 |  2 +-
 19 files changed, 47 insertions(+), 50 deletions(-)

diff --git a/.clang-format b/.clang-format
index 14b0695..df6159e 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,6 +1,6 @@
 ---
 BasedOnStyle: Google
-AlignAfterOpenBracket: AlwaysBreak
+AlignAfterOpenBracket: Align
 AlignArrayOfStructures: Left
 AlignConsecutiveAssignments: None
 AlignConsecutiveDeclarations: None
@@ -23,6 +23,7 @@ EmptyLineAfterAccessModifier: Never
 EmptyLineBeforeAccessModifier: LogicalBlock
 BinPackArguments: true
 BinPackParameters: true
+BreakBeforeBraces: Linux
 BreakBeforeBinaryOperators: NonAssignment
 BreakBeforeTernaryOperators: true
 BreakConstructorInitializers: AfterColon
diff --git a/.clang-tidy b/.clang-tidy
index b043ca7..734aa39 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -206,7 +206,6 @@ CheckOptions:
   llvm-else-after-return.WarnOnUnfixable: 'false'
   llvm-qualified-auto.AddConstToQualified: 'false'
   misc-throw-by-value-catch-by-reference.CheckThrowTemporaries: 'true'
-  misc-throw-by-value-catch-by-reference.MaxSize: '-1'
   misc-throw-by-value-catch-by-reference.WarnOnLargeObjects: 'false'
   misc-uniqueptr-reset-release.IncludeStyle: llvm
   modernize-avoid-bind.PermissiveParameterList: 'false'
diff --git a/.gitignore b/.gitignore
index 776470a..9465261 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,7 +5,7 @@
 **/.vscode/**
 
 # CMake build files
-**/cmake-build-debug/**
+**/cmake-build-*/**
 **/build/**
 install
 
diff --git a/README.md b/README.md
index b2aa49f..c47468f 100644
--- a/README.md
+++ b/README.md
@@ -195,29 +195,22 @@ on standalone builds.
 
 #### Development
 
-This project uses version `15.0.5` of `clang-format`.
-Before merging any branch we should run `clang-tidy` followed by `clang-format`.
+This project is using `clang-format` version `>=15.0.5`.
+On Ubuntu 24.04, clang-format 18 is available to install in apt repositories.
 
 ```bash
-git clone git@github.com:llvm/llvm-project.git -b llvmorg-15.0.5
-cd llvm-project
-cmake -B build -DLLVM_ENABLE_PROJECTS=clang -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" llvm
-cmake --build build -j $(nproc --ignore=2)
-sudo cmake --build build -j $(nproc --ignore=2) --target install
+sudo apt install clang-format
 ```
 
-If the `clang-format` version is any earlier than `15.0.0`,
-running `clang-format` will fail because this project uses configuration options
-made available since `15.0.0`.
+If `clang-format --version` is any earlier than `15.0.0`, running `clang-format` will fail because this project uses configuration options made available since `15.0.0`.
 
 ```bash
 clang-format --version
-clang-format version 15.0.5 (git@github.com:llvm/llvm-project.git 154e88af7ec97d9b9f389e55d45bf07108a9a097)
+Ubuntu clang-format version 18.1.3 (1ubuntu1)
 ```
 
 CLion has integration for IDE code reformatting actions with `clang-format`.
-If you're using CLion, the `.clang-format` configuration will be picked up by
-CLion automatically.
+If you're using CLion, the `.clang-format` configuration will be picked up by CLion automatically.
 
 `clang-tidy` can be run with the following commands.
 
@@ -226,14 +219,14 @@ CLion automatically.
 cd qtk
 # Build
 cmake -B build && cmake --build build -- -j $(nproc)
-clang-tidy -p build/ --fix --config-file=.clang-tidy src/*.cpp src/*.h app/*.cpp app/*.h
+clang-tidy -p build/ --fix --config-file=.clang-tidy src/**/*.cpp src/**/*.h example-app/*.cpp example-app/*.h
 ```
 
 Last we need to run `clang-format`, this can be done with the command directly.
 This will reformat all the code in the repository.
 
 ```bash
-clang-format -i --style=file:.clang-format src/app/*.cpp src/app/*.h src/qtk/*.cpp src/qtk/*.h example-app/*.cpp example-app/*.h
+clang-format -i --style=file:.clang-format src/**/*.cpp src/**/*.h example-app/*.cpp example-app/*.h
 ```
 
 `clang-format` can be run with git integration (or CLion if you prefer).
diff --git a/example-app/examplescene.cpp b/example-app/examplescene.cpp
index 68869c6..26a68b0 100644
--- a/example-app/examplescene.cpp
+++ b/example-app/examplescene.cpp
@@ -58,8 +58,11 @@ void ExampleScene::init()
 
 void ExampleScene::draw()
 {
-  // No custom draw logic for this example.
+  // The base class method _must_ be called first, before additional logic.
   Scene::draw();
+
+  // No additional custom draw logic for this example.
+  // QtkScene in Qtk desktop application is an example using custom draw logic.
 }
 
 void ExampleScene::update()
diff --git a/src/app/debugconsole.h b/src/app/debugconsole.h
index a2fc69e..b123beb 100644
--- a/src/app/debugconsole.h
+++ b/src/app/debugconsole.h
@@ -72,7 +72,7 @@ namespace Qtk {
        *
        * @param name Base name for the DebugConsole window.
        */
-      inline void setTitle(QString name) {
+      inline void setTitle(const QString& name) {
         setWindowTitle(name + " Debug Console");
       }
 
diff --git a/src/app/main.cpp b/src/app/main.cpp
index cb1801f..d9fd676 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -17,12 +17,7 @@ int main(int argc, char * argv[]) {
   QApplication a(argc, argv);
 
   auto window = MainWindow::getMainWindow();
-
-  // Qtk currently uses the decorator pattern to save / load scenes.
-  // This is a temporary solution and will be improved in the future.
-  auto emptyScene = new Qtk::SceneEmpty;
-  window->getQtkWidget()->setScene(new QtkScene(emptyScene));
-
   window->show();
+
   return QApplication::exec();
 }
diff --git a/src/app/qtkmainwindow.cpp b/src/app/qtkmainwindow.cpp
index 8c74bf8..2317cb8 100644
--- a/src/app/qtkmainwindow.cpp
+++ b/src/app/qtkmainwindow.cpp
@@ -27,7 +27,9 @@ MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) {
   // Initialize static container for all active QtkWidgets
   auto qtkWidgets = findChildren<Qtk::QtkWidget *>();
   for(auto & qtkWidget : qtkWidgets) {
-    qtkWidget->setScene(new Qtk::SceneEmpty);
+    // Qtk currently uses the decorator pattern to save / load scenes.
+    // This is a temporary solution and will be improved in the future.
+    qtkWidget->setScene(new QtkScene);
     views_.emplace(qtkWidget->getScene()->getSceneName(), qtkWidget);
 
     // Add GUI 'view' toolbar option to show debug console.
@@ -77,7 +79,9 @@ Qtk::QtkWidget * MainWindow::getQtkWidget(int64_t index) {
   if(views_.size() <= index) {
     return Q_NULLPTR;
   }
-  return views_.begin(index)->second;
+  auto it = views_.begin();
+  std::advance(it, index);
+  return it->second;
 }
 
 Qtk::QtkWidget * MainWindow::getQtkWidget(const QString & name) {
diff --git a/src/app/qtkscene.cpp b/src/app/qtkscene.cpp
index 4216d9c..e82ffd1 100644
--- a/src/app/qtkscene.cpp
+++ b/src/app/qtkscene.cpp
@@ -14,7 +14,7 @@ using namespace Qtk;
  * Constructors, Destructors
  ******************************************************************************/
 
-QtkScene::QtkScene(Qtk::Scene * scene) : Qtk::SceneInterface(scene) {
+QtkScene::QtkScene() {
   setSceneName("Qtk Scene");
   getCamera().getTransform().setTranslation(0.0f, 0.0f, 20.0f);
   getCamera().getTransform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
diff --git a/src/app/qtkscene.h b/src/app/qtkscene.h
index eca09e0..eda309b 100644
--- a/src/app/qtkscene.h
+++ b/src/app/qtkscene.h
@@ -29,13 +29,13 @@
  *
  * To create your own Scene from scratch see Qtk::Scene.
  */
-class QtkScene : public Qtk::SceneInterface {
+class QtkScene : public Qtk::Scene {
   public:
     /***************************************************************************
      * Contructors / Destructors
      **************************************************************************/
 
-    QtkScene(Qtk::Scene * scene);
+    QtkScene();
 
     ~QtkScene();
 
diff --git a/src/app/qtkwidget.h b/src/app/qtkwidget.h
index a028700..4475ad7 100644
--- a/src/app/qtkwidget.h
+++ b/src/app/qtkwidget.h
@@ -133,7 +133,7 @@ namespace Qtk {
 
       // TODO: Use this signal in treeview and toolbox to update object
       // properties
-      void objectFocusChanged(const QString objectName);
+      void objectFocusChanged(QString objectName);
 
     protected:
       /*************************************************************************
diff --git a/src/app/treeview.cpp b/src/app/treeview.cpp
index 0239b90..68fda65 100644
--- a/src/app/treeview.cpp
+++ b/src/app/treeview.cpp
@@ -46,7 +46,7 @@ void Qtk::TreeView::updateView(const Qtk::Scene * scene) {
 void Qtk::TreeView::itemFocus(QTreeWidgetItem * item, int column) {
   QString name = item->text(column);
   auto scene = MainWindow::getMainWindow()->getQtkWidget()->getScene();
-  auto & transform = scene->getCamera().getTransform();
+  auto & transform = Qtk::Scene::getCamera().getTransform();
   auto object = scene->getObject(name);
   Transform3D * objectTransform;
   // If the object is a mesh or model, focus the camera on it.
diff --git a/src/app/widgetplugin.cpp b/src/app/widgetplugin.cpp
index c79bc4b..5cf66a5 100644
--- a/src/app/widgetplugin.cpp
+++ b/src/app/widgetplugin.cpp
@@ -24,7 +24,7 @@ WidgetPlugin::WidgetPlugin(
     WidgetPlugin::Factory factory) :
     m_group(std::move(group)),
     m_className(std::move(class_name)), m_includeFile(std::move(include)),
-    m_factory(std::move(factory)), m_objectName(class_name) {}
+    m_factory(std::move(factory)), m_objectName(m_className) {}
 
 WidgetPlugin::WidgetPlugin(QObject * parent) : QObject(parent) {}
 
diff --git a/src/app/widgetplugincollection.h b/src/app/widgetplugincollection.h
index f420084..ec0b047 100644
--- a/src/app/widgetplugincollection.h
+++ b/src/app/widgetplugincollection.h
@@ -36,7 +36,7 @@ class WidgetPluginCollection :
     /**
      * @return QList of all custom widgets pointers.
      */
-    [[nodiscard]] QList<QDesignerCustomWidgetInterface *> customWidgets() const;
+    [[nodiscard]] QList<QDesignerCustomWidgetInterface *> customWidgets() const override;
 
   private:
     /***************************************************************************
diff --git a/src/qtk/input.cpp b/src/qtk/input.cpp
index 366787d..bb3fc80 100644
--- a/src/qtk/input.cpp
+++ b/src/qtk/input.cpp
@@ -152,7 +152,7 @@ void Input::update() {
 void Input::registerKeyPress(int k) {
   auto it = FindKey((Qt::Key)k);
   if(it == sg_keyInstances.end()) {
-    sg_keyInstances.push_back(KeyInstance((Qt::Key)k, InputRegistered));
+    sg_keyInstances.emplace_back((Qt::Key)k, InputRegistered);
   }
 }
 
@@ -163,15 +163,15 @@ void Input::registerKeyRelease(int k) {
   }
 }
 
-void Input::registerMousePress(Qt::MouseButton btn) {
-  auto it = FindButton(btn);
+void Input::registerMousePress(Qt::MouseButton button) {
+  auto it = FindButton(button);
   if(it == sg_buttonInstances.end()) {
-    sg_buttonInstances.push_back(ButtonInstance(btn, InputRegistered));
+    sg_buttonInstances.emplace_back(button, InputRegistered);
   }
 }
 
-void Input::registerMouseRelease(Qt::MouseButton btn) {
-  auto it = FindButton(btn);
+void Input::registerMouseRelease(Qt::MouseButton button) {
+  auto it = FindButton(button);
   if(it != sg_buttonInstances.end()) {
     it->second = InputUnregistered;
   }
@@ -187,8 +187,8 @@ Input::InputState Input::keyState(Qt::Key k) {
   return (it != sg_keyInstances.end()) ? it->second : InputInvalid;
 }
 
-Input::InputState Input::buttonState(Qt::MouseButton k) {
-  auto it = FindButton(k);
+Input::InputState Input::buttonState(Qt::MouseButton button) {
+  auto it = FindButton(button);
   return (it != sg_buttonInstances.end()) ? it->second : InputInvalid;
 }
 
diff --git a/src/qtk/meshrenderer.h b/src/qtk/meshrenderer.h
index cf5ddea..c1fcdd6 100644
--- a/src/qtk/meshrenderer.h
+++ b/src/qtk/meshrenderer.h
@@ -211,11 +211,11 @@ namespace Qtk {
        */
       inline Transform3D & getTransform() { return mTransform; }
 
-      inline std::string getVertexShader() const override {
+      [[nodiscard]] inline std::string getVertexShader() const override {
         return mVertexShader;
       }
 
-      inline std::string getFragmentShader() const override {
+      [[nodiscard]] inline std::string getFragmentShader() const override {
         return mFragmentShader;
       }
 
diff --git a/src/qtk/model.h b/src/qtk/model.h
index f81575d..5c38def 100644
--- a/src/qtk/model.h
+++ b/src/qtk/model.h
@@ -127,11 +127,11 @@ namespace Qtk {
        */
       inline Transform3D & getTransform() { return mTransform; }
 
-      inline std::string getVertexShader() const override {
+      [[nodiscard]] inline std::string getVertexShader() const override {
         return mVertexShader;
       }
 
-      inline std::string getFragmentShader() const override {
+      [[nodiscard]] inline std::string getFragmentShader() const override {
         return mFragmentShader;
       }
 
diff --git a/src/qtk/modelmesh.h b/src/qtk/modelmesh.h
index 3860dcf..caa379a 100644
--- a/src/qtk/modelmesh.h
+++ b/src/qtk/modelmesh.h
@@ -9,6 +9,8 @@
 #ifndef QTK_MODELMESH_H
 #define QTK_MODELMESH_H
 
+#include <utility>
+
 #include <QOpenGLFunctions>
 
 #include "object.h"
@@ -39,8 +41,8 @@ namespace Qtk {
        * @param type Type of texture in string format.
        * @param path Path to the texture on disk.
        */
-      ModelTexture(const std::string & type, const std::string & path) :
-          mType(type), mPath(path) {
+      ModelTexture(std::string  type, const std::string & path) :
+          mType(std::move(type)), mPath(path) {
         mTexture = OpenGLTextureFactory::initTexture(path.c_str());
         mID = mTexture->textureId();
       }
diff --git a/src/qtk/object.h b/src/qtk/object.h
index bbf8382..3fe8eae 100644
--- a/src/qtk/object.h
+++ b/src/qtk/object.h
@@ -104,7 +104,7 @@ namespace Qtk {
         return "Base Object has no vertex shader.";
       }
 
-      virtual inline std::string getFragmentShader() const {
+      [[nodiscard]] virtual inline std::string getFragmentShader() const {
         return "Base Object has no fragment shader.";
       }