]> Nutra Git (v2) - nutratech/gui.git/commitdiff
add some UI components to mainwindow
authorShane Jaroch <chown_tee@proton.me>
Wed, 21 Jan 2026 10:59:23 +0000 (05:59 -0500)
committerShane Jaroch <chown_tee@proton.me>
Wed, 21 Jan 2026 10:59:23 +0000 (05:59 -0500)
CMakeLists.txt
Makefile
include/mainwindow.h
src/main.cpp
src/mainwindow.cpp

index dc3de9a0a2ec4b7abe84ff2bfeaa40570e9a9d34..a638c40228b9af2468d3a90ecfece69a43169893 100644 (file)
@@ -35,7 +35,7 @@ set(PROJECT_SOURCES
 # Versioning
 if(NOT NUTRA_VERSION)
     execute_process(
-        COMMAND git describe --tags --always --dirty
+        COMMAND git describe --tags --always
         WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
         OUTPUT_VARIABLE GIT_VERSION
         ERROR_QUIET
index 3f58b8e95a0a222f0946bff5f0ada933d2902cc0..c7690f02305f9be78fa45c8082116654ef8a3b75 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ CTEST := ctest
 SRC_DIRS := src
 
 # Get version from git
-VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "v0.0.0")
+VERSION := $(shell git describe --tags --always 2>/dev/null || echo "v0.0.0")
 
 # Find source files for linting
 LINT_LOCS_CPP ?= $(shell git ls-files '*.cpp')
index fce7ce965feb1fc60d4653cc0c073387d8b46899..12e4bf22e33d3a352c5a52241fdfa1a12a8ea56a 100644 (file)
@@ -14,16 +14,25 @@ public:
   MainWindow(QWidget *parent = nullptr);
   ~MainWindow() override;
 
+private slots:
+  void onOpenDatabase();
+  void onRecentFileClick();
+  void onSettings();
+  void onAbout();
+
 private:
   void setupUi();
+  void updateRecentFileActions();
+  void addToRecentFiles(const QString &path);
 
   QTabWidget *tabs;
   SearchWidget *searchWidget;
   DetailsWidget *detailsWidget;
   MealWidget *mealWidget;
 
-private slots:
-  void onAbout();
+  QMenu *recentFilesMenu;
+  static constexpr int MaxRecentFiles = 5;
+  QAction *recentFileActions[MaxRecentFiles];
 };
 
 #endif // MAINWINDOW_H
index a6857d0f7f8cc4d04b6c1c97232a99d53bdb2003..3e33a545b3be7692d05275d3738b27b214b60f4e 100644 (file)
@@ -3,6 +3,7 @@
 #include <QApplication>
 #include <QDebug>
 #include <QDir>
+#include <QFileDialog>
 #include <QFileInfo>
 #include <QIcon>
 #include <QMessageBox>
@@ -44,19 +45,32 @@ int main(int argc, char *argv[]) {
   }
 
   if (dbPath.isEmpty()) {
-    // If not found, default to XDG AppData location for error message/setup
-    // But we can't create it here.
-    dbPath = QDir::homePath() + "/.nutra/usda.sqlite3"; // Fallback default
     qWarning() << "Database not found in standard locations.";
+    QMessageBox::StandardButton resBtn = QMessageBox::question(
+        nullptr, "Database Not Found",
+        "The Nutrient database (usda.sqlite3) was not found.\nWould you like "
+        "to browse for it manually?",
+        QMessageBox::No | QMessageBox::Yes, QMessageBox::Yes);
+
+    if (resBtn == QMessageBox::Yes) {
+      dbPath = QFileDialog::getOpenFileName(
+          nullptr, "Find usda.sqlite3", QDir::homePath(),
+          "SQLite Databases (*.sqlite3 *.db)");
+    }
+
+    if (dbPath.isEmpty()) {
+      return 1; // User cancelled or still not found
+    }
   }
 
   if (!DatabaseManager::instance().connect(dbPath)) {
     QString errorMsg =
         QString("Failed to connect to database at:\n%1\n\nPlease ensure the "
-                "database file exists or reinstall the application.")
+                "database file exists or browse for a valid SQLite file.")
             .arg(dbPath);
     qCritical() << errorMsg;
     QMessageBox::critical(nullptr, "Database Error", errorMsg);
+    // Let's try to let the user browse one more time before giving up
     return 1;
   }
   qDebug() << "Connected to database at:" << dbPath;
index f56469d0fe6b7c21a5d7361f115c2f10606e0c99..facd93feec05e5cf1e3cf87a7106f7ca671415d4 100644 (file)
@@ -1,14 +1,26 @@
 #include "mainwindow.h"
+#include "db/databasemanager.h"
+#include <QAction>
+#include <QDebug>
+#include <QFileDialog>
 #include <QMenu>
 #include <QMenuBar>
 #include <QMessageBox>
+#include <QSettings>
+#include <QStringList>
 #include <QVBoxLayout>
-
-#include <QDebug>
-#include <QLabel>
 #include <QWidget>
 
-MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setupUi(); }
+MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
+  for (int i = 0; i < MaxRecentFiles; ++i) {
+    recentFileActions[i] = new QAction(this);
+    recentFileActions[i]->setVisible(false);
+    connect(recentFileActions[i], &QAction::triggered, this,
+            &MainWindow::onRecentFileClick);
+  }
+  setupUi();
+  updateRecentFileActions();
+}
 
 MainWindow::~MainWindow() = default;
 
@@ -17,7 +29,24 @@ void MainWindow::setupUi() {
   setWindowIcon(QIcon(":/resources/nutrition_icon-no_bg.png"));
   resize(1000, 700);
 
-  // Menu Bar
+  // File Menu
+  auto *fileMenu = menuBar()->addMenu("&File");
+  auto *openDbAction = fileMenu->addAction("&Open Database...");
+  recentFilesMenu = fileMenu->addMenu("Recent Databases");
+  fileMenu->addSeparator();
+  auto *exitAction = fileMenu->addAction("E&xit");
+  connect(openDbAction, &QAction::triggered, this, &MainWindow::onOpenDatabase);
+  connect(exitAction, &QAction::triggered, this, &QWidget::close);
+
+  for (int i = 0; i < MaxRecentFiles; ++i)
+    recentFilesMenu->addAction(recentFileActions[i]);
+
+  // Edit Menu
+  auto *editMenu = menuBar()->addMenu("&Edit");
+  auto *settingsAction = editMenu->addAction("&Settings");
+  connect(settingsAction, &QAction::triggered, this, &MainWindow::onSettings);
+
+  // Help Menu
   auto *helpMenu = menuBar()->addMenu("&Help");
   auto *aboutAction = helpMenu->addAction("&About");
   connect(aboutAction, &QAction::triggered, this, &MainWindow::onAbout);
@@ -59,6 +88,76 @@ void MainWindow::setupUi() {
           });
 }
 
+void MainWindow::onOpenDatabase() {
+  QString fileName = QFileDialog::getOpenFileName(
+      this, "Open USDA Database", "", "SQLite Databases (*.sqlite3 *.db)");
+
+  if (!fileName.isEmpty()) {
+    if (DatabaseManager::instance().connect(fileName)) {
+      qDebug() << "Switched to database:" << fileName;
+      addToRecentFiles(fileName);
+      // In a real app, we'd emit a signal or refresh all widgets
+      // For now, let's just log and show success
+      QMessageBox::information(this, "Database Opened",
+                               "Successfully connected to: " + fileName);
+    } else {
+      QMessageBox::critical(this, "Database Error",
+                            "Failed to connect to the database.");
+    }
+  }
+}
+
+void MainWindow::onRecentFileClick() {
+  auto *action = qobject_cast<QAction *>(sender());
+  if (action != nullptr) {
+    QString fileName = action->data().toString();
+    if (DatabaseManager::instance().connect(fileName)) {
+      qDebug() << "Switched to database (recent):" << fileName;
+      addToRecentFiles(fileName);
+      QMessageBox::information(this, "Database Opened",
+                               "Successfully connected to: " + fileName);
+    } else {
+      QMessageBox::critical(this, "Database Error",
+                            "Failed to connect to: " + fileName);
+    }
+  }
+}
+
+void MainWindow::updateRecentFileActions() {
+  QSettings settings("NutraTech", "Nutra");
+  QStringList files = settings.value("recentFiles").toStringList();
+
+  int numRecentFiles = qMin(files.size(), MaxRecentFiles);
+
+  for (int i = 0; i < numRecentFiles; ++i) {
+    QString text =
+        QString("&%1 %2").arg(i + 1).arg(QFileInfo(files[i]).fileName());
+    recentFileActions[i]->setText(text);
+    recentFileActions[i]->setData(files[i]);
+    recentFileActions[i]->setVisible(true);
+  }
+  for (int i = numRecentFiles; i < MaxRecentFiles; ++i)
+    recentFileActions[i]->setVisible(false);
+
+  recentFilesMenu->setEnabled(numRecentFiles > 0);
+}
+
+void MainWindow::addToRecentFiles(const QString &path) {
+  QSettings settings("NutraTech", "Nutra");
+  QStringList files = settings.value("recentFiles").toStringList();
+  files.removeAll(path);
+  files.prepend(path);
+  while (files.size() > MaxRecentFiles)
+    files.removeLast();
+
+  settings.setValue("recentFiles", files);
+  updateRecentFileActions();
+}
+
+void MainWindow::onSettings() {
+  QMessageBox::information(this, "Settings", "Settings dialog coming soon!");
+}
+
 void MainWindow::onAbout() {
   QMessageBox::about(
       this, "About Nutrient Coach",