text: /*
  Copyright 2021 The Foedag team
  
  GPL License
  
  Copyright (c) 2021 The Open-Source FPGA Foundation
  
  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 <http://www.gnu.org/licenses/>.
  */
  #include "main_window.h"
  
  #include <QTextStream>
  #include <QtWidgets>
  #include <fstream>
  
  #include "Compiler/TaskManager.h"
  #include "Compiler/TaskModel.h"
  #include "Compiler/TaskTableView.h"
  #include "Console/DummyParser.h"
  #include "Console/StreamBuffer.h"
  #include "Console/TclConsole.h"
  #include "Console/TclConsoleBuilder.h"
  #include "Console/TclConsoleWidget.h"
  #include "DesignRuns/runs_form.h"
  #include "Main/CompilerNotifier.h"
  #include "Main/Foedag.h"
  #include "NewFile/new_file.h"
  #include "NewProject/Main/registerNewProjectCommands.h"
  #include "NewProject/new_project_dialog.h"
  #include "ProjNavigator/sources_form.h"
  #include "TextEditor/text_editor.h"
  
  using namespace FOEDAG;
  
  MainWindow::MainWindow(TclInterpreter* interp) : m_interpreter(interp) {
    /* Window settings */
    setWindowTitle(tr("FOEDAG"));
    resize(350, 250);
  
    QDesktopWidget dw;
    setGeometry(dw.width() / 6, dw.height() / 6, dw.width() * 2 / 3,
                dw.height() * 2 / 3);
  
    setDockNestingEnabled(true);
  
    setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North);
  
    /* Create actions that can be added to menu/tool bars */
    createActions();
  
    /* Create menu bars */
    createMenus();
  
    /* Create tool bars */
    createToolBars();
  
    /* Create status bar */
    statusBar();
  
    //  /* Add dummy text editors */
    //  QTextEdit* editor1 = new QTextEdit;
    //  QTextEdit* editor2 = new QTextEdit;
    //  QTextEdit* editor3 = new QTextEdit;
  
    //  /* Add widgets into floorplanning */
    //  QSplitter* leftSplitter = new QSplitter(Qt::Horizontal);
    //  leftSplitter->addWidget(editor1);
    //  leftSplitter->setStretchFactor(1, 1);
  
    //  QDockWidget* texteditorDockWidget = new QDockWidget(tr("Text Editor"));
    //  texteditorDockWidget->setObjectName("texteditorDockWidget");
    //  texteditorDockWidget->setWidget(editor2);
    //  texteditorDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea |
    //                                        Qt::RightDockWidgetArea);
    //  addDockWidget(Qt::RightDockWidgetArea, texteditorDockWidget);
  
    //  QSplitter* mainSplitter = new QSplitter(Qt::Vertical);
    //  mainSplitter->addWidget(leftSplitter);
    //  mainSplitter->addWidget(editor3);
    //  mainSplitter->setStretchFactor(1, 1);
  
    //  setCentralWidget(mainSplitter);
  
    statusBar()->showMessage("Ready");
  }
  
  void MainWindow::Tcl_NewProject(int argc, const char* argv[]) {
    ProjectManager* projectManager = new ProjectManager(this);
    projectManager->Tcl_CreateProject(argc, argv);
  }
  
  void MainWindow::newFile() {
    //  QTextStream out(stdout);
    //  out << "New file is requested\n";
    NewFile* newfile = new NewFile(this);
    newfile->StartNewFile();
  }
  
  void MainWindow::newProjectDlg() {
    int ret = newProjdialog->exec();
    newProjdialog->close();
    if (ret) {
      QString strproject = newProjdialog->getProject();
      newProjectAction->setEnabled(false);
      ReShowWindow(strproject);
    }
  }
  
  void MainWindow::openProject() {
    QString fileName = "";
    fileName = QFileDialog::getOpenFileName(this, tr("Open Project"), "",
                                            "FOEDAG Project File(*.ospr)");
    if ("" != fileName) {
      ReShowWindow(fileName);
    }
  }
  
  void MainWindow::openFileSlot() {
    const QString file = QFileDialog::getOpenFileName(this, tr("Open file"));
    auto editor = findChild<TextEditor*>("textEditor");
    if (editor) editor->SlotOpenFile(file);
  }
  
  void MainWindow::createMenus() {
    fileMenu = menuBar()->addMenu(tr("&File"));
    fileMenu->addAction(newAction);
    fileMenu->addAction(openFile);
    fileMenu->addSeparator();
    fileMenu->addAction(newProjectAction);
    fileMenu->addAction(openProjectAction);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAction);
  }
  
  void MainWindow::createToolBars() {
    fileToolBar = addToolBar(tr("&File"));
    fileToolBar->addAction(newAction);
  }
  
  void MainWindow::createActions() {
    newAction = new QAction(tr("&New"), this);
    newAction->setIcon(QIcon(":/images/icon_newfile.png"));
    newAction->setShortcut(QKeySequence::New);
    newAction->setStatusTip(tr("Create a new source file"));
    connect(newAction, SIGNAL(triggered()), this, SLOT(newFile()));
  
    openProjectAction = new QAction(tr("&Open Project"), this);
    openProjectAction->setStatusTip(tr("Open a new project"));
    connect(openProjectAction, SIGNAL(triggered()), this, SLOT(openProject()));
  
    newProjdialog = new newProjectDialog(this);
    newProjectAction = new QAction(tr("&New Project"), this);
    newProjectAction->setStatusTip(tr("Create a new project"));
    connect(newProjectAction, SIGNAL(triggered()), this, SLOT(newProjectDlg()));
  
    openFile = new QAction(tr("&Open File"), this);
    openFile->setStatusTip(tr("Open file"));
    openFile->setIcon(QIcon(":/images/open-file.png"));
    connect(openFile, SIGNAL(triggered()), this, SLOT(openFileSlot()));
  
    exitAction = new QAction(tr("E&xit"), this);
    exitAction->setShortcut(tr("Ctrl+Q"));
    exitAction->setStatusTip(tr("Exit the application"));
  
    connect(exitAction, &QAction::triggered, qApp, [this]() {
      Command cmd("gui_stop; exit");
      GlobalSession->CmdStack()->push_and_exec(&cmd);
    });
  }
  
  void MainWindow::gui_start() { ReShowWindow(""); }
  
  void MainWindow::ReShowWindow(QString strProject) {
    clearDockWidgets();
    takeCentralWidget();
  
    setWindowTitle(tr(mainWindowName.c_str()) + " - " + strProject);
  
    QDockWidget* sourceDockWidget = new QDockWidget(tr("Source"), this);
    sourceDockWidget->setObjectName("sourcedockwidget");
    SourcesForm* sourForm = new SourcesForm(strProject, this);
    sourceDockWidget->setWidget(sourForm);
    addDockWidget(Qt::LeftDockWidgetArea, sourceDockWidget);
  
    QDockWidget* runDockWidget = new QDockWidget(tr("Design Runs"), this);
    runDockWidget->setObjectName("sourcedockwidget");
    RunsForm* runForm = new RunsForm(strProject, this);
    runDockWidget->setWidget(runForm);
  
    TextEditor* textEditor = new TextEditor(this);
    textEditor->RegisterCommands(GlobalSession);
    textEditor->setObjectName("textEditor");
  
    connect(sourForm, SIGNAL(OpenFile(QString)), textEditor,
            SLOT(SlotOpenFile(QString)));
    connect(textEditor, SIGNAL(CurrentFileChanged(QString)), sourForm,
            SLOT(SetCurrentFileItem(QString)));
  
    QWidget* centralWidget = new QWidget(this);
    QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom, centralWidget);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);
    layout->addWidget(textEditor->GetTextEditor());
    centralWidget->setLayout(layout);
  
    setCentralWidget(centralWidget);
  
    // console
    QDockWidget* consoleDocWidget = new QDockWidget(tr("Console"), this);
    consoleDocWidget->setObjectName("consoledocwidget");
  
    StreamBuffer* buffer = new StreamBuffer;
    auto tclConsole = std::make_unique<FOEDAG::TclConsole>(
        m_interpreter->getInterp(), buffer->getStream());
    FOEDAG::TclConsole* c = tclConsole.get();
    TclConsoleWidget* console{nullptr};
    QWidget* w =
        FOEDAG::createConsole(m_interpreter->getInterp(), std::move(tclConsole),
                              buffer, nullptr, &console);
    consoleDocWidget->setWidget(w);
    connect(console, &TclConsoleWidget::linkActivated, textEditor,
            &TextEditor::SlotOpenFile);
    console->addParser(new DummyParser{});
  
    // Register fake compiler until openFPGA gets available
    std::string design("Some cool design");
    FOEDAG::Compiler* com = new FOEDAG::Compiler{
        m_interpreter, new FOEDAG::Design(design), buffer->getStream(),
        new FOEDAG::CompilerNotifier{c}};
    com->RegisterCommands(m_interpreter, false);
  
    addDockWidget(Qt::BottomDockWidgetArea, consoleDocWidget);
    tabifyDockWidget(consoleDocWidget, runDockWidget);
  
    TaskManager* taskManager = new TaskManager;
    TaskModel* model = new TaskModel{taskManager};
    TaskTableView* view = new TaskTableView;
    view->setModel(model);
    QDockWidget* taskDocWidget = new QDockWidget(tr("Task"), this);
    taskDocWidget->setWidget(view);
    tabifyDockWidget(sourceDockWidget, taskDocWidget);
  
    com->setTaskManager(taskManager);
  }
  
  void MainWindow::clearDockWidgets() {
    auto docks = findChildren<QDockWidget*>();
    for (auto dock : docks) {
      removeDockWidget(dock);
    }
  }
  