diff --git a/src/configPanel.cpp b/src/configPanel.cpp index 4e89f697843b625f357de73279a2b18d104898fb..f9670a5a18a8dbc85ae4aefe86d3d229c1dae7ee 100644 --- a/src/configPanel.cpp +++ b/src/configPanel.cpp @@ -39,11 +39,13 @@ ConfigPanel::ConfigPanel(QWidget* parent) : QDockWidget{parent} stackedWidget->addWidget(fileWidget); QHBoxLayout* fileLayout = new QHBoxLayout(); fileWidget->setLayout(fileLayout); - openButton = new QPushButton("Open..."); + fileLayout->setContentsMargins(0, 0, 0, 0); + openButton = new QPushButton("Browse..."); fileWidget->layout()->addWidget(openButton); - fileLine = new QLineEdit("YourFile"); + fileLine = new QLineEdit(); + fileLine->setPlaceholderText("/path/to/yourFile.csv"); fileWidget->layout()->addWidget(fileLine); - fileGenerateButton = new QPushButton("Generate"); + fileGenerateButton = new QPushButton("Preview"); fileLayout->addWidget(fileGenerateButton); fileLayout->addStretch(); connect(openButton, &QPushButton::clicked, this, &ConfigPanel::onOpenButton); @@ -53,16 +55,33 @@ ConfigPanel::ConfigPanel(QWidget* parent) : QDockWidget{parent} QHBoxLayout* randomLayout = new QHBoxLayout(); randomWidget->setLayout(randomLayout); + randomLayout->setContentsMargins(0, 0, 0, 0); problemSizeBox = new QSpinBox(); randomLayout->addWidget(problemSizeBox); - randomGenerateButton = new QPushButton("Generate"); + randomGenerateButton = new QPushButton("Preview"); randomLayout->addWidget(randomGenerateButton); randomLayout->addStretch(); problemSizeBox->setMinimum(1); problemSizeBox->setMaximum(INT_MAX); - stackedWidget->setCurrentWidget(randomWidget); + pasteWidget = new QWidget(); + stackedWidget->addWidget(pasteWidget); + QHBoxLayout* pasteLayout = new QHBoxLayout(); + pasteWidget->setLayout(pasteLayout); + pasteLayout->setContentsMargins(0, 0, 0, 0); + + pasteBox = new QPlainTextEdit(); + pasteLayout->addWidget(pasteBox, 1); + pasteBox->setPlaceholderText("Paste or Drop here..."); + pasteBox->setMinimumHeight(25); + pasteBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + + pasteGenerateButton = new QPushButton("Preview"); + pasteLayout->addWidget(pasteGenerateButton); + pasteLayout->addStretch(); + + stackedWidget->setCurrentWidget(pasteWidget); } void ConfigPanel::setRunning(bool running) diff --git a/src/configPanel.h b/src/configPanel.h index 50a54cd81079c0c8c00dad00938c7ae8fdbc6eda..05cefdf9c8847c164bafd6d8e8277225c9eeca7e 100644 --- a/src/configPanel.h +++ b/src/configPanel.h @@ -4,6 +4,7 @@ #include <QCheckBox> #include <QComboBox> #include <QDockWidget> +#include <QPlainTextEdit> #include <QPushButton> #include <QSpinBox> #include <QStackedWidget> @@ -18,13 +19,16 @@ public: QPushButton* openButton; QPushButton* randomGenerateButton; QPushButton* fileGenerateButton; + QPushButton* pasteGenerateButton; QLineEdit* fileLine; + QPlainTextEdit* pasteBox; QComboBox* algoBox; QSpinBox* problemSizeBox; QComboBox* verbosityBox; QStackedWidget* stackedWidget; QWidget* fileWidget; QWidget* randomWidget; + QWidget* pasteWidget; public: explicit ConfigPanel(QWidget* parent = nullptr); diff --git a/src/control.cpp b/src/control.cpp index 1e4cb8e26bd790ba98d6cfdfce48e0a0d9759fc7..382baba97e927e59a0d52b4870af4bc899d4e81e 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -47,6 +47,7 @@ void Control::makeConnections() connect(w->configPanel->runButton, &QPushButton::clicked, this, &Control::onRunButton); connect(w->configPanel->fileGenerateButton, &QPushButton::clicked, this, &Control::onGenerateButton); connect(w->configPanel->randomGenerateButton, &QPushButton::clicked, this, &Control::onGenerateButton); + connect(w->configPanel->pasteGenerateButton, &QPushButton::clicked, this, &Control::onGenerateButton); connect(w->configPanel->fileLine, &QLineEdit::textChanged, this, &Control::onProblemSettingChanged); connect(w->configPanel->problemSizeBox, &QSpinBox::textChanged, this, &Control::onProblemSettingChanged); connect(w, &MainWindow::saveProblem, this, &Control::saveProblem); @@ -264,8 +265,8 @@ void Control::generateProblem() else if (w->configPanel->stackedWidget->currentWidget() == w->configPanel->fileWidget) { std::string filename = w->configPanel->fileLine->text().toStdString(); - CSVParser csv(filename); - bool success = csv.parse(); + CSVParser csv; + bool success = csv.parseFile(filename); if (!success) { std::string errorMessage = "Error parsing file: " + filename; @@ -284,6 +285,25 @@ void Control::generateProblem() problem.emplace_back(cute::Point{row[0], row[1]}); } } + else if (w->configPanel->stackedWidget->currentWidget() == w->configPanel->pasteWidget) + { + std::string input = w->configPanel->pasteBox->toPlainText().toStdString(); + CSVParser csv; + csv.parseString(input); + + auto data = csv.getFloatRows(); + for (auto&& row : data) + { + if (row.size() < 2) + continue; + else if (std::isnan(row[0]) || std::isnan(row[1])) + continue; + else if (std::isinf(row[0]) || std::isinf(row[1])) + continue; + else + problem.emplace_back(cute::Point{row[0], row[1]}); + } + } } void Control::onGenerateButton() diff --git a/src/csvParser.h b/src/csvParser.h index 8132cb8fa98b3eeb0fde82eb94e8e92c157dba5d..8750f7e8038702761c8214cc1a94ef1366d9df7c 100644 --- a/src/csvParser.h +++ b/src/csvParser.h @@ -26,34 +26,24 @@ Below is the complete, self-contained code: class CSVParser { public: - // Constructor: takes the filename, an optional delimiter (default is comma), - // and an option to skip the header line (default is false). - CSVParser(const std::string& filename, char delimiter = ',', bool skipHeader = false) - : filename(filename), delimiter(delimiter), skipHeader(skipHeader) {} + CSVParser(char delimiter = ',') : delimiter(delimiter) {} - // Parses the CSV file. - bool parse() { - rows.clear(); // Ensure that rows is empty before starting. + bool parseFile(const std::string& filename) { std::ifstream file(filename); if (!file.is_open()) { std::cerr << "Error opening file: " << filename << std::endl; return false; } - - std::string line; - // If skipHeader is true, read and discard the first line. - if (skipHeader && std::getline(file, line)) { - // Optionally process or log the header if needed. - } - - // Read each subsequent line and parse it. - while (std::getline(file, line)) { - rows.push_back(parseLine(line)); - } + parseStream(file); file.close(); return true; } + void parseString(const std::string& rawInput) { + std::istringstream input(rawInput); + parseStream(input); + } + // Returns the parsed CSV data as a vector of rows containing strings. const std::vector<std::vector<std::string>>& getRows() const { return rows; @@ -83,11 +73,19 @@ public: } private: - std::string filename; - char delimiter; - bool skipHeader; + char delimiter; std::vector<std::vector<std::string>> rows; + void parseStream(std::istream& input) + { + rows.clear(); // Ensure that rows is empty before starting. + std::string line; + // Read each subsequent line and parse it. + while (std::getline(input, line)) { + rows.push_back(parseLine(line)); + } + } + // Helper function that parses a single line of CSV. // It supports quoted fields and the basic escaping of quotes by doubling (""). std::vector<std::string> parseLine(const std::string& line) { diff --git a/src/mainWindow.cpp b/src/mainWindow.cpp index 1de9468d80bba1ce1dcd695ad2132b7dcfcce528..8cccb70c7c46d6b790c442036dd2fc84a3f854bd 100644 --- a/src/mainWindow.cpp +++ b/src/mainWindow.cpp @@ -71,6 +71,12 @@ void MainWindow::setupMenuBar() probM->addAction(probMenuFile); connect(probMenuFile, &QAction::triggered, this, &MainWindow::switchToFile); + probMenuPaste = new QAction("Paste", this); + probMenuPaste->setCheckable(true); + probMenuPaste->setChecked(false); + probM->addAction(probMenuPaste); + connect(probMenuPaste, &QAction::triggered, this, &MainWindow::switchToPaste); + QAction* probSave = new QAction("Save...", this); probM->addAction(probSave); connect(probSave, &QAction::triggered, this, &MainWindow::saveProblem); @@ -85,8 +91,10 @@ void MainWindow::switchToFile() { probMenuFile->setChecked(true); probMenuRandom->setChecked(false); + probMenuPaste->setChecked(false); probMenuFile->setDisabled(true); probMenuRandom->setDisabled(false); + probMenuPaste->setDisabled(false); configPanel->stackedWidget->setCurrentWidget(configPanel->fileWidget); } @@ -94,11 +102,24 @@ void MainWindow::switchToRandom() { probMenuFile->setChecked(false); probMenuRandom->setChecked(true); + probMenuPaste->setChecked(false); probMenuFile->setDisabled(false); probMenuRandom->setDisabled(true); + probMenuPaste->setDisabled(false); configPanel->stackedWidget->setCurrentWidget(configPanel->randomWidget); } +void MainWindow::switchToPaste() +{ + probMenuFile->setChecked(false); + probMenuRandom->setChecked(false); + probMenuPaste->setChecked(true); + probMenuFile->setDisabled(false); + probMenuRandom->setDisabled(false); + probMenuPaste->setDisabled(true); + configPanel->stackedWidget->setCurrentWidget(configPanel->pasteWidget); +} + void MainWindow::setupCharts() { @@ -183,4 +204,4 @@ void MainWindow::chartContextMenu(const QPoint& pos) void MainWindow::changeVerbosity(int level) { configPanel->verbosityBox->setCurrentIndex(level); -} \ No newline at end of file +} diff --git a/src/mainWindow.h b/src/mainWindow.h index 43ffb80f7cdaf17581c68f152ad0bd7457e401a9..42ae7fe3acefbd9fb1263fabf3ea4bb8697337a1 100644 --- a/src/mainWindow.h +++ b/src/mainWindow.h @@ -19,6 +19,7 @@ class MainWindow : public QMainWindow private: QAction* probMenuFile; QAction* probMenuRandom; + QAction* probMenuPaste; void incrementChartTheme(); public: @@ -46,6 +47,7 @@ private slots: public slots: void switchToFile(); void switchToRandom(); + void switchToPaste(); void changeChartTheme(int themeNumber); void changeVerbosity(int level);