Files
create/src/Mod/TechDraw/Gui/CommandDecorate.cpp
Markus Reitböck 0019739095 TechDraw: use CMake to generate precompiled headers on all platforms
"Professional CMake" book suggest the following:

"Targets should build successfully with or without compiler support for precompiled headers. It
 should be considered an optimization, not a requirement. In particular, do not explicitly include a
 precompile header (e.g. stdafx.h) in the source code, let CMake force-include an automatically
 generated precompile header on the compiler command line instead. This is more portable across
 the major compilers and is likely to be easier to maintain. It will also avoid warnings being
 generated from certain code checking tools like iwyu (include what you use)."

Therefore, removed the "#include <PreCompiled.h>" from sources, also
there is no need for the "#ifdef _PreComp_" anymore
2025-09-23 00:50:59 +02:00

345 lines
13 KiB
C++

/***************************************************************************
* Copyright (c) 2014 Luke Parry <l.parry@warwick.ac.uk> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
# include <QMessageBox>
# include <sstream>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <Base/Tools.h>
#include <Gui/Action.h>
#include <Gui/Application.h>
#include <Gui/Command.h>
#include <Gui/Control.h>
#include <Gui/Document.h>
#include <Gui/FileDialog.h>
#include <Gui/MainWindow.h>
#include <Gui/Selection/Selection.h>
#include <Gui/Selection/SelectionObject.h>
#include <Gui/ViewProvider.h>
#include <Mod/TechDraw/App/DrawHatch.h>
#include <Mod/TechDraw/App/DrawGeomHatch.h>
#include <Mod/TechDraw/App/DrawPage.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/DrawView.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/Preferences.h>
#include "DrawGuiUtil.h"
#include "TaskGeomHatch.h"
#include "TaskHatch.h"
#include "ViewProviderGeomHatch.h"
#include "ViewProviderPage.h"
#include "MDIViewPage.h"
#include "CommandHelpers.h"
using namespace TechDrawGui;
using namespace TechDraw;
using DU = DrawUtil;
//internal functions
bool _checkSelectionHatch(Gui::Command* cmd);
//===========================================================================
// TechDraw_Hatch
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawHatch)
CmdTechDrawHatch::CmdTechDrawHatch()
: Command("TechDraw_Hatch")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Image Hatch");
sToolTipText = QT_TR_NOOP("Applies a hatch pattern to the selected faces using an image file");
sWhatsThis = "TechDraw_Hatch";
sStatusTip = sToolTipText;
sPixmap = "actions/TechDraw_Hatch";
}
void CmdTechDrawHatch::activated(int iMsg)
{
Q_UNUSED(iMsg);
if (!_checkSelectionHatch(this)) {
return;
}
std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
auto partFeat( dynamic_cast<TechDraw::DrawViewPart *>(selection[0].getObject()) );
if (!partFeat) {
return;
}
const std::vector<std::string> &subNames = selection[0].getSubNames();
TechDraw::DrawPage* page = partFeat->findParentPage();
std::string PageName = page->getNameInDocument();
std::vector<int> selFaces;
for (auto& s: subNames) {
int f = TechDraw::DrawUtil::getIndexFromName(s);
selFaces.push_back(f);
}
bool removeOld = false;
std::vector<TechDraw::DrawHatch*> hatchObjs = partFeat->getHatches();
for (auto& s: subNames) { //all the faces selected in DVP
int face = TechDraw::DrawUtil::getIndexFromName(s);
if (TechDraw::DrawHatch::faceIsHatched(face, hatchObjs)) {
QMessageBox::StandardButton rc =
QMessageBox::question(Gui::getMainWindow(), QObject::tr("Replace hatch?"),
QObject::tr("Some faces in the selection are already hatched. Replace?"));
if (rc == QMessageBox::StandardButton::NoButton) {
return;
}
removeOld = true;
break;
}
}
if (removeOld) {
openCommand(QT_TRANSLATE_NOOP("Command", "Remove old hatch"));
std::vector<std::pair< int, TechDraw::DrawHatch*> > toRemove;
for (auto& h: hatchObjs) { //all the hatch objects for selected DVP
std::vector<std::string> hatchSubs = h->Source.getSubValues();
for (auto& hs: hatchSubs) { //all the Faces in this hatch object
int hatchFace = TechDraw::DrawUtil::getIndexFromName(hs);
if (auto it = std::ranges::find(selFaces, hatchFace); it != selFaces.end()) {
std::pair< int, TechDraw::DrawHatch*> removeItem;
removeItem.first = hatchFace;
removeItem.second = h;
toRemove.push_back(removeItem);
}
}
}
for (auto& r: toRemove) {
r.second->removeSub(r.first);
if (r.second->empty()) {
doCommand(Doc, "App.activeDocument().removeObject('%s')", r.second->getNameInDocument());
}
}
commitCommand();
}
// dialog to fill in hatch values
Gui::Control().showDialog(new TaskDlgHatch(partFeat, subNames));
// Touch the parent feature so the hatching in tree view appears as a child
partFeat->touch();
getDocument()->recompute();
}
bool CmdTechDrawHatch::isActive()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
//===========================================================================
// TechDraw_GeometricHatch
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawGeometricHatch)
CmdTechDrawGeometricHatch::CmdTechDrawGeometricHatch()
: Command("TechDraw_GeometricHatch")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Geometric Hatch");
sToolTipText = QT_TR_NOOP("Applies a geometric hatch pattern to the selected faces");
sWhatsThis = "TechDraw_GeometricHatch";
sStatusTip = sToolTipText;
sPixmap = "actions/TechDraw_GeometricHatch";
}
void CmdTechDrawGeometricHatch::activated(int iMsg)
{
Q_UNUSED(iMsg);
if (!_checkSelectionHatch(this)) { //same requirements as hatch - page, DrawViewXXX, face
return;
}
std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
auto objFeat( dynamic_cast<TechDraw::DrawViewPart *>(selection[0].getObject()) );
if (!objFeat) {
return;
}
const std::vector<std::string> &subNames = selection[0].getSubNames();
TechDraw::DrawPage* page = objFeat->findParentPage();
std::string PageName = page->getNameInDocument();
std::string FeatName = getUniqueObjectName("GeomHatch");
// TODO: the structured label for GeomHatch (and Hatch) should be retired.
// std::stringstream featLabel;
// featLabel << FeatName << "FX" << TechDraw::DrawUtil::getIndexFromName(subNames.at(0));
openCommand(QT_TRANSLATE_NOOP("Command", "Create GeomHatch"));
doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawGeomHatch', '%s')", FeatName.c_str());
// doCommand(Doc, "App.activeDocument().%s.Label = '%s'", FeatName.c_str(), featLabel.str().c_str());
doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawGeomHatch', 'GeomHatch', '%s')",
FeatName.c_str(), FeatName.c_str());
auto geomhatch( static_cast<TechDraw::DrawGeomHatch *>(getDocument()->getObject(FeatName.c_str())) );
geomhatch->Source.setValue(objFeat, subNames);
Gui::ViewProvider* vp = Gui::Application::Instance->getDocument(getDocument())->getViewProvider(geomhatch);
TechDrawGui::ViewProviderGeomHatch* hvp = dynamic_cast<TechDrawGui::ViewProviderGeomHatch*>(vp);
if (!hvp) {
return;
}
// dialog to fill in hatch values
Gui::Control().showDialog(new TaskDlgGeomHatch(geomhatch, hvp, true));
commitCommand();
// Touch the parent feature so the hatching in tree view appears as a child
objFeat->touch();
getDocument()->recompute();
}
bool CmdTechDrawGeometricHatch::isActive()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
//===========================================================================
// TechDraw_Image
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawImage)
CmdTechDrawImage::CmdTechDrawImage()
: Command("TechDraw_Image")
{
// setting the Gui eye-candy
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Bitmap Image");
sToolTipText = QT_TR_NOOP("Inserts a bitmap from a file into the current page");
sWhatsThis = "TechDraw_Image";
sStatusTip = QT_TR_NOOP("Insert bitmap from a file into a page");
sPixmap = "actions/TechDraw_Image";
}
void CmdTechDrawImage::activated(int iMsg)
{
Q_UNUSED(iMsg);
TechDraw::DrawPage* page = DrawGuiUtil::findPage(this);
if (!page) {
return;
}
std::string PageName = page->getNameInDocument();
// Reading an image
QString fileName = Gui::FileDialog::getOpenFileName(Gui::getMainWindow(),
QString::fromUtf8(QT_TR_NOOP("Select an image file")),
Preferences::defaultSymbolDir(),
QString::fromUtf8(QT_TR_NOOP("Image files (*.jpg *.jpeg *.png *.bmp);;All files (*)")));
if (fileName.isEmpty()) {
return;
}
std::string FeatName = getUniqueObjectName("Image");
fileName = Base::Tools::escapeEncodeFilename(fileName);
auto filespec = DU::cleanFilespecBackslash(fileName.toStdString());
openCommand(QT_TRANSLATE_NOOP("Command", "Create Image"));
doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawViewImage', '%s')", FeatName.c_str());
doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawViewImage', 'Image', '%s')",
FeatName.c_str(), FeatName.c_str());
doCommand(Doc, "App.activeDocument().%s.ImageFile = '%s'", FeatName.c_str(), filespec.c_str());
auto baseView = CommandHelpers::firstViewInSelection(this);
if (baseView) {
auto baseName = baseView->getNameInDocument();
doCommand(Doc, "App.activeDocument().%s.Owner = App.activeDocument().%s",
FeatName.c_str(), baseName);
}
doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", PageName.c_str(), FeatName.c_str());
updateActive();
commitCommand();
}
bool CmdTechDrawImage::isActive()
{
return DrawGuiUtil::needPage(this);
}
void CreateTechDrawCommandsDecorate()
{
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
rcCmdMgr.addCommand(new CmdTechDrawHatch());
rcCmdMgr.addCommand(new CmdTechDrawGeometricHatch());
rcCmdMgr.addCommand(new CmdTechDrawImage());
// rcCmdMgr.addCommand(new CmdTechDrawLeaderLine());
// rcCmdMgr.addCommand(new CmdTechDrawRichTextAnnotation());
}
//===========================================================================
// Selection Validation Helpers
//===========================================================================
bool _checkSelectionHatch(Gui::Command* cmd) {
std::vector<Gui::SelectionObject> selection = cmd->getSelection().getSelectionEx();
if (selection.empty()) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Incorrect selection"),
QObject::tr("Select a face first"));
return false;
}
TechDraw::DrawViewPart * objFeat = dynamic_cast<TechDraw::DrawViewPart *>(selection[0].getObject());
if(!objFeat) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Incorrect selection"),
QObject::tr("No TechDraw object in selection"));
return false;
}
std::vector<App::DocumentObject*> pages = cmd->getDocument()->getObjectsOfType(TechDraw::DrawPage::getClassTypeId());
if (pages.empty()){
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Incorrect selection"),
QObject::tr("Create a page to insert"));
return false;
}
const std::vector<std::string> &SubNames = selection[0].getSubNames();
if (SubNames.empty()) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Incorrect Selection"),
QObject::tr("No faces to hatch in this selection"));
return false;
}
std::string gType = TechDraw::DrawUtil::getGeomTypeFromName(SubNames.at(0));
if (!(gType == "Face")) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Incorrect Selection"),
QObject::tr("No faces to hatch in this selection"));
return false;
}
return true;
}