]> Nutra Git (v1) - nutratech/gui.git/commitdiff
allow deleting search history items, lint/format.
authorShane Jaroch <chown_tee@proton.me>
Mon, 26 Jan 2026 04:54:32 +0000 (23:54 -0500)
committerShane Jaroch <chown_tee@proton.me>
Mon, 26 Jan 2026 04:54:45 +0000 (23:54 -0500)
CMakeLists.txt
Makefile
include/widgets/searchwidget.h
src/widgets/searchwidget.cpp

index 8b80074fb22e366195a296cae7aa158e19971d4c..f523a119b45ba1a0fa21c77e78c7a0dd98d3efc8 100644 (file)
@@ -54,6 +54,8 @@ find_package(Qt${QT_VERSION_MAJOR}Test REQUIRED)
 # Dynamic Test Discovery
 file(GLOB TEST_SOURCES "tests/test_*.cpp")
 
+add_custom_target(build_tests)
+
 foreach(TEST_SOURCE ${TEST_SOURCES})
     get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE)
     
@@ -61,6 +63,7 @@ foreach(TEST_SOURCE ${TEST_SOURCES})
     target_link_libraries(${TEST_NAME} PRIVATE nutra_lib Qt${QT_VERSION_MAJOR}::Test)
     
     add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
+    add_dependencies(build_tests ${TEST_NAME})
 endforeach()
 
 
index dc5d837b1c7934aca26f76794fffc700ad542fa0..e0f41e296cf2248bc0f81b5f6625d97ce5842c31 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -43,7 +43,7 @@ clean:
 
 .PHONY: test
 test: release
-       $(CMAKE) --build $(BUILD_DIR) --target test_nutra --config Release
+       $(CMAKE) --build $(BUILD_DIR) --target build_tests --config Release
        cd $(BUILD_DIR) && $(CTEST) --output-on-failure -C Release
 
 .PHONY: run
@@ -61,7 +61,7 @@ format:
 lint: config
        @echo "Linting..."
        @# Build test target first to generate MOC files for tests
-       @$(CMAKE) --build $(BUILD_DIR) --target test_nutra --config Debug 2>/dev/null || true
+       @$(CMAKE) --build $(BUILD_DIR) --target build_tests --config Debug 2>/dev/null || true
        @echo "Running cppcheck..."
        cppcheck --enable=warning,performance,portability \
                --language=c++ --std=c++17 \
index 1088fa30582ee51ba65ce404365e4361c4ecca39..530533c31aa657cf4bd950159c159b42bbf985e2 100644 (file)
@@ -17,6 +17,7 @@ class SearchWidget : public QWidget {
 
 public:
     explicit SearchWidget(QWidget* parent = nullptr);
+    bool eventFilter(QObject* obj, QEvent* event) override;
 
     void reloadSettings();
 
@@ -29,10 +30,12 @@ private slots:
     void performSearch();
     void onRowDoubleClicked(int row, int column);
     void onCustomContextMenu(const QPoint& pos);
+    void onHistoryContextMenu(const QPoint& pos);
     void onCompleterActivated(const QString& text);
 
 private:
     void addToHistory(int foodId, const QString& foodName);
+    void removeFromHistory(int index);
     void loadHistory();
     void updateCompleterModel();
 
index 738f3945056e07b7a25f0a79ad9a264a8dee3048..2b31aa34fcd12cc18ae642be5fa64cf29011b342 100644 (file)
@@ -1,10 +1,13 @@
 #include "widgets/searchwidget.h"
 
+#include <QAbstractItemView>
 #include <QAction>
 #include <QDateTime>
 #include <QElapsedTimer>
+#include <QEvent>
 #include <QHBoxLayout>
 #include <QHeaderView>
+#include <QKeyEvent>
 #include <QMenu>
 #include <QMessageBox>
 #include <QPushButton>
@@ -33,6 +36,13 @@ SearchWidget::SearchWidget(QWidget* parent) : QWidget(parent) {
     historyCompleter->setCompletionMode(QCompleter::PopupCompletion);
     searchInput->setCompleter(historyCompleter);
 
+    QAbstractItemView* popup = historyCompleter->popup();
+    popup->setContextMenuPolicy(Qt::CustomContextMenu);
+    popup->installEventFilter(this);
+
+    connect(popup, &QAbstractItemView::customContextMenuRequested, this,
+            &SearchWidget::onHistoryContextMenu);
+
     connect(historyCompleter, QOverload<const QString&>::of(&QCompleter::activated), this,
             &SearchWidget::onCompleterActivated);
 
@@ -256,3 +266,51 @@ void SearchWidget::reloadSettings() {
     debounce = std::max(debounce, 250);
     searchTimer->setInterval(debounce);
 }
+
+bool SearchWidget::eventFilter(QObject* obj, QEvent* event) {
+    if (obj == historyCompleter->popup() && event->type() == QEvent::KeyPress) {
+        auto* keyEvent = static_cast<QKeyEvent*>(event);
+        if (keyEvent->key() == Qt::Key_Delete) {
+            QModelIndex index = historyCompleter->popup()->currentIndex();
+            if (index.isValid()) {
+                removeFromHistory(index.row());
+                return true;
+            }
+        }
+    }
+    return QWidget::eventFilter(obj, event);
+}
+
+void SearchWidget::onHistoryContextMenu(const QPoint& pos) {
+    QAbstractItemView* popup = historyCompleter->popup();
+    QModelIndex index = popup->indexAt(pos);
+    if (!index.isValid()) return;
+
+    QMenu menu(this);
+    QAction* deleteAction = menu.addAction("Remove from history");
+    QAction* selectedAction = menu.exec(popup->viewport()->mapToGlobal(pos));
+
+    if (selectedAction == deleteAction) {
+        removeFromHistory(index.row());
+    }
+}
+
+void SearchWidget::removeFromHistory(int index) {
+    if (index < 0 || index >= recentHistory.size()) return;
+
+    recentHistory.removeAt(index);
+
+    // Save to settings
+    QSettings settings("NutraTech", "Nutra");
+    QList<QVariant> list;
+    for (const auto& h : recentHistory) {
+        QVariantMap m;
+        m["id"] = h.id;
+        m["name"] = h.name;
+        m["timestamp"] = h.timestamp;
+        list.append(m);
+    }
+    settings.setValue("recentFoods", list);
+
+    updateCompleterModel();
+}