// SPDX-License-Identifier: LGPL-2.1-or-later #include #include #include #include #include #if defined(Q_WS_X11) # include #endif #include "mainwindow.h" MainWindow::MainWindow() { createActions(); createMenus(); #if defined(Q_WS_X11) setCentralWidget(new QX11EmbedContainer(this)); #else setCentralWidget(new QWidget(this)); #endif } void MainWindow::createActions() { loadAct = new QAction(tr("&Load"), this); loadAct->setStatusTip(tr("Load FreeCAD module")); connect(loadAct, SIGNAL(triggered()), this, SLOT(loadFreeCAD())); newAct = new QAction(tr("New document"), this); newAct->setStatusTip(tr("Create new document in the FreeCAD module")); connect(newAct, SIGNAL(triggered()), this, SLOT(newDocument())); newAct->setDisabled(true); embedAct = new QAction(tr("Embed"), this); embedAct->setStatusTip(tr("Embed FreeCAD as child window")); connect(embedAct, SIGNAL(triggered()), this, SLOT(embedWindow())); embedAct->setDisabled(true); exitAct = new QAction(tr("E&xit"), this); exitAct->setShortcut(tr("Ctrl+Q")); exitAct->setStatusTip(tr("Exit the application")); connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows())); aboutAct = new QAction(tr("&About"), this); aboutAct->setStatusTip(tr("Show the application's About box")); connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); } void MainWindow::createMenus() { fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(exitAct); editMenu = menuBar()->addMenu(tr("Free&CAD")); editMenu->addAction(loadAct); editMenu->addAction(newAct); editMenu->addAction(embedAct); menuBar()->addSeparator(); helpMenu = menuBar()->addMenu(tr("&Help")); helpMenu->addAction(aboutAct); } void MainWindow::loadFreeCAD() { QString path = QFileDialog::getExistingDirectory(this, "FreeCAD module path"); if (!path.isEmpty()) { path.replace('\\', '/'); PyObject* main = PyImport_AddModule("__main__"); PyObject* dict = PyModule_GetDict(main); std::stringstream cmd; cmd << "import sys,os\n" << "sys.path.append(\"" << (const char*)path.toLatin1() << "\")\n" << "os.chdir(\"" << (const char*)path.toLatin1() << "\")\n" << "import FreeCADGui\n" << "FreeCADGui.showMainWindow()\n"; PyObject* result = PyRun_String(cmd.str().c_str(), Py_file_input, dict, dict); if (result) { Py_DECREF(result); loadAct->setDisabled(true); newAct->setEnabled(true); embedAct->setEnabled(true); } else { PyObject *ptype, *pvalue, *ptrace; PyErr_Fetch(&ptype, &pvalue, &ptrace); PyObject* pystring = PyObject_Str(pvalue); const char* error = PyUnicode_AsUTF8(pystring); QMessageBox::warning(this, "Error", error); Py_DECREF(pystring); } Py_DECREF(dict); } } void MainWindow::newDocument() { PyObject* main = PyImport_AddModule("__main__"); PyObject* dict = PyModule_GetDict(main); const char* cmd = "FreeCAD.newDocument()\n"; PyObject* result = PyRun_String(cmd, Py_file_input, dict, dict); if (result) { Py_DECREF(result); } else { PyObject *ptype, *pvalue, *ptrace; PyErr_Fetch(&ptype, &pvalue, &ptrace); PyObject* pystring = PyObject_Str(pvalue); const char* error = PyUnicode_AsUTF8(pystring); QMessageBox::warning(this, "Error", error); Py_DECREF(pystring); } Py_DECREF(dict); } void MainWindow::embedWindow() { PyObject* main = PyImport_AddModule("__main__"); PyObject* dict = PyModule_GetDict(main); std::stringstream cmd; cmd << "class BlankWorkbench (Workbench):\n" << " MenuText = \"Blank\"\n" << " ToolTip = \"Blank workbench\"\n" << "\n" << " def Initialize(self):\n" << " return\n" << " def GetClassName(self):\n" << " return \"Gui::BlankWorkbench\"\n" << "\n" << "FreeCADGui.addWorkbench(BlankWorkbench)\n" << "FreeCADGui.activateWorkbench(\"BlankWorkbench\")\n" << "\n"; #if defined(Q_WS_X11) || defined(Q_OS_WIN) WId hwnd = this->centralWidget()->winId(); cmd << "FreeCADGui.embedToWindow(\"" << hwnd << "\")\n" << "\n"; #endif PyObject* result = PyRun_String(cmd.str().c_str(), Py_file_input, dict, dict); if (result) { Py_DECREF(result); #if !defined(Q_WS_X11) // This is a workaround for the lack of a replacement of QX11EmbedWidget with Qt5 QWidget* mw = nullptr; for (auto it : qApp->topLevelWidgets()) { if (it->inherits("Gui::MainWindow")) { mw = it; break; } } if (mw) { QVBoxLayout* vb = new QVBoxLayout(); centralWidget()->setLayout(vb); vb->addWidget(mw); } #endif embedAct->setDisabled(true); } else { PyObject *ptype, *pvalue, *ptrace; PyErr_Fetch(&ptype, &pvalue, &ptrace); PyObject* pystring = PyObject_Str(pvalue); const char* error = PyUnicode_AsUTF8(pystring); QMessageBox::warning(this, "Error", error); Py_DECREF(pystring); } Py_DECREF(dict); } void MainWindow::about() { QMessageBox::about(this, tr("About"), tr("Demonstrates remote control of FreeCAD")); }