This commit is contained in:
Chenwenxuan
2024-03-06 14:54:30 +08:00
commit edac2715f0
1525 changed files with 809982 additions and 0 deletions

View File

@@ -0,0 +1,257 @@
/******************************************************************************
**
** This file was created for the LibreCAD project, a 2D CAD program.
**
** Copyright (C) 2018 Alexander Pravdin <aledin@mail.ru>
** Copyright (C) 2022 A. Stebich (librecad@mail.lordofbikes.de)
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
******************************************************************************/
#include <QtCore>
#include <QCoreApplication>
#include <QApplication>
#include "rs_debug.h"
#include "rs_fontlist.h"
#include "rs_patternlist.h"
#include "rs_settings.h"
#include "rs_system.h"
#include "main.h"
#include "console_dxf2pdf.h"
#include "pdf_print_loop.h"
static RS_Vector parsePageSizeArg(QString);
static void parsePagesNumArg(QString, PdfPrintParams&);
static void parseMarginsArg(QString, PdfPrintParams&);
int console_dxf2pdf(int argc, char* argv[])
{
RS_DEBUG->setLevel(RS_Debug::D_NOTHING);
QApplication app(argc, argv);
QCoreApplication::setOrganizationName("LibreCAD");
QCoreApplication::setApplicationName("LibreCAD");
QCoreApplication::setApplicationVersion(XSTR(LC_VERSION));
QFileInfo prgInfo(QFile::decodeName(argv[0]));
RS_SETTINGS->init(app.organizationName(), app.applicationName());
RS_SYSTEM->init( app.applicationName(), app.applicationVersion(), XSTR(QC_APPDIR), argv[0]);
QCommandLineParser parser;
QStringList appDesc;
QString librecad( prgInfo.filePath());
if (prgInfo.baseName() != "dxf2pdf") {
librecad += " dxf2pdf"; // executable is not dxf2pdf, thus argv[1] must be 'dxf2pdf'
appDesc << "";
appDesc << "dxf2pdf " + QObject::tr( "usage: ") + librecad + QObject::tr( " [options] <dxf_files>");
}
appDesc << "";
appDesc << "Print a bunch of DXF files to PDF file(s).";
appDesc << "";
appDesc << "Examples:";
appDesc << "";
appDesc << " " + librecad + QObject::tr( " *.dxf");
appDesc << " " + QObject::tr( "-- print all dxf files to pdf files with the same names.");
appDesc << "";
appDesc << " " + librecad + QObject::tr( " -o some.pdf *.dxf");
appDesc << " " + QObject::tr( "-- print all dxf files to 'some.pdf' file.");
parser.setApplicationDescription( appDesc.join( "\n"));
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption fitOpt(QStringList() << "a" << "fit",
QObject::tr( "Auto fit and center drawing to page."));
parser.addOption(fitOpt);
QCommandLineOption centerOpt(QStringList() << "c" << "center",
QObject::tr( "Auto center drawing on page."));
parser.addOption(centerOpt);
QCommandLineOption grayOpt(QStringList() << "k" << "grayscale",
QObject::tr( "Print grayscale."));
parser.addOption(grayOpt);
QCommandLineOption monoOpt(QStringList() << "m" << "monochrome",
QObject::tr( "Print monochrome (black/white)."));
parser.addOption(monoOpt);
QCommandLineOption pageSizeOpt(QStringList() << "p" << "paper",
QObject::tr( "Paper size (Width x Height) in mm.", "WxH"));
parser.addOption(pageSizeOpt);
QCommandLineOption resOpt(QStringList() << "r" << "resolution",
QObject::tr( "Output resolution (DPI).", "integer"));
parser.addOption(resOpt);
QCommandLineOption scaleOpt(QStringList() << "s" << "scale",
QObject::tr( "Output scale. E.g.: 0.01 (for 1:100 scale)."), "double");
parser.addOption(scaleOpt);
QCommandLineOption marginsOpt(QStringList() << "f" << "margins",
QObject::tr( "Paper margins in mm (integer or float)."), "L,T,R,B");
parser.addOption(marginsOpt);
QCommandLineOption pagesNumOpt(QStringList() << "z" << "pages",
QObject::tr( "Print on multiple pages (Horiz. x Vert.)."), "HxV");
parser.addOption(pagesNumOpt);
QCommandLineOption outFileOpt(QStringList() << "o" << "outfile",
QObject::tr( "Output PDF file.", "file"));
parser.addOption(outFileOpt);
QCommandLineOption outDirOpt(QStringList() << "t" << "directory",
QObject::tr( "Target output directory."), "path");
parser.addOption(outDirOpt);
parser.addPositionalArgument(QObject::tr( "<dxf_files>"), QObject::tr( "Input DXF file(s)"));
parser.process(app);
const QStringList args = parser.positionalArguments();
if (args.isEmpty() || (args.size() == 1 && args[0] == "dxf2pdf"))
parser.showHelp(EXIT_FAILURE);
PdfPrintParams params;
params.fitToPage = parser.isSet(fitOpt);
params.centerOnPage = parser.isSet(centerOpt);
params.grayscale = parser.isSet(grayOpt);
params.monochrome = parser.isSet(monoOpt);
params.pageSize = parsePageSizeArg(parser.value(pageSizeOpt));
bool resOk;
int res = parser.value(resOpt).toInt(&resOk);
if (resOk)
params.resolution = res;
bool scaleOk;
double scale = parser.value(scaleOpt).toDouble(&scaleOk);
if (scaleOk)
params.scale = scale;
parseMarginsArg(parser.value(marginsOpt), params);
parsePagesNumArg(parser.value(pagesNumOpt), params);
params.outFile = parser.value(outFileOpt);
params.outDir = parser.value(outDirOpt);
for (auto arg : args) {
QFileInfo dxfFileInfo(arg);
if (dxfFileInfo.suffix().toLower() != "dxf")
continue; // Skip files without .dxf extension
params.dxfFiles.append(arg);
}
if (params.dxfFiles.isEmpty())
parser.showHelp(EXIT_FAILURE);
if (!params.outDir.isEmpty()) {
// Create output directory
if (!QDir().mkpath(params.outDir)) {
qDebug() << "ERROR: Cannot create directory" << params.outDir;
return EXIT_FAILURE;
}
}
RS_FONTLIST->init();
RS_PATTERNLIST->init();
PdfPrintLoop *loop = new PdfPrintLoop(params, &app);
QObject::connect(loop, SIGNAL(finished()), &app, SLOT(quit()));
QTimer::singleShot(0, loop, SLOT(run()));
return app.exec();
}
static RS_Vector parsePageSizeArg(QString arg)
{
RS_Vector v(0.0, 0.0);
if (arg.isEmpty())
return v;
QRegularExpression re("^(?<width>\\d+)[x|X]{1}(?<height>\\d+)$");
QRegularExpressionMatch match = re.match(arg);
if (match.hasMatch()) {
QString width = match.captured("width");
QString height = match.captured("height");
v.x = width.toDouble();
v.y = height.toDouble();
} else {
qDebug() << "WARNING: Ignoring bad page size:" << arg;
}
return v;
}
static void parsePagesNumArg(QString arg, PdfPrintParams& params)
{
if (arg.isEmpty())
return;
QRegularExpression re("^(?<horiz>\\d+)[x|X](?<vert>\\d+)$");
QRegularExpressionMatch match = re.match(arg);
if (match.hasMatch()) {
QString h = match.captured("horiz");
QString v = match.captured("vert");
params.pagesH = h.toInt();
params.pagesV = v.toInt();
} else {
qDebug() << "WARNING: Ignoring bad number of pages:" << arg;
}
}
static void parseMarginsArg(QString arg, PdfPrintParams& params)
{
if (arg.isEmpty())
return;
QRegularExpression re("^(?<left>\\d+(?:\\.\\d+)?),"
"(?<top>\\d+(?:\\.\\d+)?),"
"(?<right>\\d+(?:\\.\\d+)?),"
"(?<bottom>\\d+(?:\\.\\d+)?)$");
QRegularExpressionMatch match = re.match(arg);
if (match.hasMatch()) {
QString left = match.captured("left");
QString top = match.captured("top");
QString right = match.captured("right");
QString bottom = match.captured("bottom");
params.margins.left = left.toDouble();
params.margins.top = top.toDouble();
params.margins.right = right.toDouble();
params.margins.bottom = bottom.toDouble();
} else {
qDebug() << "WARNING: Ignoring bad paper margins:" << arg;
}
}

View File

@@ -0,0 +1,29 @@
/******************************************************************************
**
** This file was created for the LibreCAD project, a 2D CAD program.
**
** Copyright (C) 2018 Alexander Pravdin <aledin@mail.ru>
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
******************************************************************************/
#ifndef CONSOLE_DXF2PDF_H
#define CONSOLE_DXF2PDF_H
int console_dxf2pdf(int argc, char** argv);
#endif

View File

@@ -0,0 +1,300 @@
/******************************************************************************
**
** This file was created for the LibreCAD project, a 2D CAD program.
**
** Copyright (C) 2018 Alexander Pravdin <aledin@mail.ru>
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
******************************************************************************/
#include <QtCore>
#include "rs.h"
#include "rs_graphic.h"
#include "rs_painterqt.h"
#include "lc_printing.h"
#include "rs_staticgraphicview.h"
#include "pdf_print_loop.h"
static bool openDocAndSetGraphic(RS_Document**, RS_Graphic**, QString&);
static void touchGraphic(RS_Graphic*, PdfPrintParams&);
static void setupPrinterAndPaper(RS_Graphic*, QPrinter&, PdfPrintParams&);
static void drawPage(RS_Graphic*, QPrinter&, RS_PainterQt&);
void PdfPrintLoop::run()
{
if (params.outFile.isEmpty()) {
for (auto f : params.dxfFiles) {
printOneDxfToOnePdf(f);
}
} else {
printManyDxfToOnePdf();
}
emit finished();
}
void PdfPrintLoop::printOneDxfToOnePdf(QString& dxfFile) {
// Main code logic and flow for this method is originally stolen from
// QC_ApplicationWindow::slotFilePrint(bool printPDF) method.
// But finally it was split in to smaller parts.
QFileInfo dxfFileInfo(dxfFile);
params.outFile =
(params.outDir.isEmpty() ? dxfFileInfo.path() : params.outDir)
+ "/" + dxfFileInfo.completeBaseName() + ".pdf";
RS_Document *doc;
RS_Graphic *graphic;
if (!openDocAndSetGraphic(&doc, &graphic, dxfFile))
return;
qDebug() << "Printing" << dxfFile << "to" << params.outFile << ">>>>";
touchGraphic(graphic, params);
QPrinter printer(QPrinter::HighResolution);
setupPrinterAndPaper(graphic, printer, params);
RS_PainterQt painter(&printer);
if (params.monochrome)
painter.setDrawingMode(RS2::ModeBW);
drawPage(graphic, printer, painter);
painter.end();
qDebug() << "Printing" << dxfFile << "to" << params.outFile << "DONE";
delete doc;
}
void PdfPrintLoop::printManyDxfToOnePdf() {
struct DxfPage {
RS_Document* doc;
RS_Graphic* graphic;
QString dxfFile;
QPrinter::PageSize paperSize;
};
if (!params.outDir.isEmpty()) {
QFileInfo outFileInfo(params.outFile);
params.outFile = params.outDir + "/" + outFileInfo.fileName();
}
QVector<DxfPage> pages;
int nrPages = 0;
// FIXME: Should probably open and print all dxf files in one 'for' loop.
// Tried but failed to do this. It looks like some 'chicken and egg'
// situation for the QPrinter and RS_PainterQt. Therefore, first open
// all dxf files and apply required actions. Then run another 'for'
// loop for actual printing.
for (auto dxfFile : params.dxfFiles) {
DxfPage page;
page.dxfFile = dxfFile;
if (!openDocAndSetGraphic(&page.doc, &page.graphic, dxfFile))
continue;
qDebug() << "Opened" << dxfFile;
touchGraphic(page.graphic, params);
pages.append(page);
nrPages++;
}
QPrinter printer(QPrinter::HighResolution);
if (nrPages > 0) {
// FIXME: Is it possible to set up printer and paper for every
// opened dxf file and tie them with painter? For now just using
// data extracted from the first opened dxf file for all pages.
setupPrinterAndPaper(pages.at(0).graphic, printer, params);
}
RS_PainterQt painter(&printer);
if (params.monochrome)
painter.setDrawingMode(RS2::ModeBW);
// And now it's time to actually print all previously opened dxf files.
for (auto page : pages) {
nrPages--;
qDebug() << "Printing" << page.dxfFile
<< "to" << params.outFile << ">>>>";
drawPage(page.graphic, printer, painter);
qDebug() << "Printing" << page.dxfFile
<< "to" << params.outFile << "DONE";
delete page.doc;
if (nrPages > 0)
printer.newPage();
}
painter.end();
}
static bool openDocAndSetGraphic(RS_Document** doc, RS_Graphic** graphic,
QString& dxfFile)
{
*doc = new RS_Graphic();
if (!(*doc)->open(dxfFile, RS2::FormatUnknown)) {
qDebug() << "ERROR: Failed to open document" << dxfFile;
delete *doc;
return false;
}
*graphic = (*doc)->getGraphic();
if (*graphic == nullptr) {
qDebug() << "ERROR: No graphic in" << dxfFile;
delete *doc;
return false;
}
return true;
}
static void touchGraphic(RS_Graphic* graphic, PdfPrintParams& params)
{
graphic->calculateBorders();
graphic->setMargins(params.margins.left, params.margins.top,
params.margins.right, params.margins.bottom);
graphic->setPagesNum(params.pagesH, params.pagesV);
if (params.scale > 0.0)
graphic->setPaperScale(params.scale);
if (params.pageSize != RS_Vector(0.0, 0.0))
graphic->setPaperSize(params.pageSize);
if (params.fitToPage)
graphic->fitToPage(); // fit and center
else if (params.centerOnPage)
graphic->centerToPage();
}
static void setupPrinterAndPaper(RS_Graphic* graphic, QPrinter& printer,
PdfPrintParams& params)
{
bool landscape = false;
RS2::PaperFormat pf = graphic->getPaperFormat(&landscape);
QPrinter::PageSize paperSize = LC_Printing::rsToQtPaperFormat(pf);
if (paperSize == QPrinter::Custom){
RS_Vector r = graphic->getPaperSize();
RS_Vector&& s = RS_Units::convert(r, graphic->getUnit(),
RS2::Millimeter);
if (landscape)
s = s.flipXY();
printer.setPaperSize(QSizeF(s.x,s.y), QPrinter::Millimeter);
} else {
printer.setPaperSize(paperSize);
}
if (landscape) {
printer.setOrientation(QPrinter::Landscape);
} else {
printer.setOrientation(QPrinter::Portrait);
}
printer.setOutputFileName(params.outFile);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setResolution(params.resolution);
printer.setFullPage(true);
if (params.grayscale)
printer.setColorMode(QPrinter::GrayScale);
else
printer.setColorMode(QPrinter::Color);
}
static void drawPage(RS_Graphic* graphic, QPrinter& printer,
RS_PainterQt& painter)
{
double printerFx = (double)printer.width() / printer.widthMM();
double printerFy = (double)printer.height() / printer.heightMM();
double marginLeft = graphic->getMarginLeft();
double marginTop = graphic-> getMarginTop();
double marginRight = graphic->getMarginRight();
double marginBottom = graphic->getMarginBottom();
painter.setClipRect(marginLeft * printerFx, marginTop * printerFy,
printer.width() - (marginLeft + marginRight) * printerFx,
printer.height() - (marginTop + marginBottom) * printerFy);
RS_StaticGraphicView gv(printer.width(), printer.height(), &painter);
gv.setPrinting(true);
gv.setBorders(0,0,0,0);
double fx = printerFx * RS_Units::getFactorToMM(graphic->getUnit());
double fy = printerFy * RS_Units::getFactorToMM(graphic->getUnit());
double f = (fx + fy) / 2.0;
double scale = graphic->getPaperScale();
gv.setOffset((int)(graphic->getPaperInsertionBase().x * f),
(int)(graphic->getPaperInsertionBase().y * f));
gv.setFactor(f*scale);
gv.setContainer(graphic);
double baseX = graphic->getPaperInsertionBase().x;
double baseY = graphic->getPaperInsertionBase().y;
int numX = graphic->getPagesNumHoriz();
int numY = graphic->getPagesNumVert();
RS_Vector printArea = graphic->getPrintAreaSize(false);
for (int pY = 0; pY < numY; pY++) {
double offsetY = printArea.y * pY;
for (int pX = 0; pX < numX; pX++) {
double offsetX = printArea.x * pX;
// First page is created automatically.
// Extra pages must be created manually.
if (pX > 0 || pY > 0) printer.newPage();
gv.setOffset((int)((baseX - offsetX) * f),
(int)((baseY - offsetY) * f));
gv.drawEntity(&painter, graphic );
}
}
}

View File

@@ -0,0 +1,82 @@
/******************************************************************************
**
** This file was created for the LibreCAD project, a 2D CAD program.
**
** Copyright (C) 2018 Alexander Pravdin <aledin@mail.ru>
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
******************************************************************************/
#ifndef PDF_PRINT_LOOP_H
#define PDF_PRINT_LOOP_H
#include <QtCore>
#include <QPrinter>
#include "rs_vector.h"
struct PdfPrintParams {
QStringList dxfFiles;
QString outDir;
QString outFile;
int resolution = 1200;
bool centerOnPage;
bool fitToPage;
bool monochrome;
bool grayscale;
double scale = 0.0; // If scale <= 0.0, use value from dxf file.
RS_Vector pageSize; // If zeros, use value from dxf file.
struct {
double left = -1.0;
double top = -1.0;
double right = -1.0;
double bottom = -1.0;
} margins; // If margin < 0.0, use value from dxf file.
int pagesH = 0; // If number of pages < 1,
int pagesV = 0; // use value from dxf file.
};
class PdfPrintLoop : public QObject {
Q_OBJECT
public:
PdfPrintLoop(PdfPrintParams& params, QObject* parent=0) :
QObject(parent) {
this->params = params;
};
public slots:
void run();
signals:
void finished();
private:
PdfPrintParams params;
void printOneDxfToOnePdf(QString&);
void printManyDxfToOnePdf();
};
#endif

File diff suppressed because it is too large Load Diff

140
main/doc_plugin_interface.h Normal file
View File

@@ -0,0 +1,140 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2011 Rallaz (rallazz@gmail.com)
**
**
** This file 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 2 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef DOC_PLUGIN_INTERFACE_H
#define DOC_PLUGIN_INTERFACE_H
#include <QObject>
#include "document_interface.h"
#include "rs_graphic.h"
class Doc_plugin_interface;
class convLTW
{
public:
convLTW();
QString lt2str(enum RS2::LineType lt);
QString lw2str(enum RS2::LineWidth lw);
QString intColor2str(int col);
enum RS2::LineType str2lt(QString s);
enum RS2::LineWidth str2lw(QString w);
private:
QHash<RS2::LineType, QString> lType;
QHash<RS2::LineWidth, QString> lWidth;
};
class Plugin_Entity
{
public:
Plugin_Entity(RS_Entity* ent, Doc_plugin_interface* d);
Plugin_Entity(RS_EntityContainer* parent, enum DPI::ETYPE type);
virtual ~Plugin_Entity();
bool isValid(){if (entity) return true; else return false;}
RS_Entity* getEnt() {return entity;}
virtual void getData(QHash<int, QVariant> *data);
virtual void updateData(QHash<int, QVariant> *data);
virtual void getPolylineData(QList<Plug_VertexData> *data);
virtual void updatePolylineData(QList<Plug_VertexData> *data);
virtual void move(QPointF offset);
virtual void moveRotate(QPointF const& offset, QPointF const& center, double angle);
virtual void rotate(QPointF center, double angle);
virtual void scale(QPointF center, QPointF factor);
virtual QString intColor2str(int color);
private:
RS_Entity* entity;
bool hasContainer;
Doc_plugin_interface* dpi;
};
class Doc_plugin_interface : public Document_Interface
{
public:
Doc_plugin_interface(RS_Document *d, RS_GraphicView* gv, QWidget* parent);
void updateView();
void addPoint(QPointF *start);
void addLine(QPointF *start, QPointF *end);
void addMText(QString txt, QString sty, QPointF *start,
double height, double angle, DPI::HAlign ha, DPI::VAlign va);
void addText(QString txt, QString sty, QPointF *start,
double height, double angle, DPI::HAlign ha, DPI::VAlign va);
void addCircle(QPointF *start, qreal radius);
void addArc(QPointF *start, qreal radius, qreal a1, qreal a2);
void addEllipse(QPointF *start, QPointF *end, qreal ratio, qreal a1, qreal a2);
virtual void addLines(std::vector<QPointF> const& points, bool closed=false);
virtual void addPolyline(std::vector<Plug_VertexData> const& points, bool closed=false);
virtual void addSplinePoints(std::vector<QPointF> const& points, bool closed=false);
void addImage(int handle, QPointF *start, QPointF *uvr, QPointF *vvr,
int w, int h, QString name, int br, int con, int fade);
void addInsert(QString name, QPointF ins, QPointF scale, qreal rot);
QString addBlockfromFromdisk(QString fullName);
void addEntity(Plug_Entity *handle);
Plug_Entity *newEntity( enum DPI::ETYPE type);
void removeEntity(Plug_Entity *ent);
void updateEntity(RS_Entity *org, RS_Entity *newe);
void setLayer(QString name);
QString getCurrentLayer();
QStringList getAllLayer();
QStringList getAllBlocks();
bool deleteLayer(QString name);
void getCurrentLayerProperties(int *c, DPI::LineWidth *w, DPI::LineType *t);
void getCurrentLayerProperties(int *c, QString *w, QString *t);
void setCurrentLayerProperties(int c, DPI::LineWidth w, DPI::LineType t);
void setCurrentLayerProperties(int c, QString const& w, QString const& t);
bool getPoint(QPointF *point, const QString& message, QPointF *base);
Plug_Entity *getEnt(const QString& message);
bool getSelect(QList<Plug_Entity *> *sel, const QString& message);
bool getAllEntities(QList<Plug_Entity *> *sel, bool visible = false);
bool getVariableInt(const QString& key, int *num);
bool getVariableDouble(const QString& key, double *num);
bool addVariable(const QString& key, int value, int code=70);
bool addVariable(const QString& key, double value, int code=40);
bool getInt(int *num, const QString& message, const QString& title);
bool getReal(qreal *num, const QString& message, const QString& title);
bool getString(QString *txt, const QString& message, const QString& title);
QString realToStr(const qreal num, const int units = 0, const int prec = 0);
//method to handle undo in Plugin_Entity
bool addToUndo(RS_Entity* current, RS_Entity* modified);
private:
RS_Document *doc;
RS_Graphic *docGr;
RS_GraphicView *gView;
QWidget* main_window;
};
/*void addArc(QPointF *start); ->Without start
void addCircle(QPointF *start); ->Without start
more...
*/
#endif // DOC_PLUGIN_INTERFACE_H

154
main/emu_c99.cpp Normal file
View File

@@ -0,0 +1,154 @@
#include "emu_c99.h"
#include <cmath>
#include <cfloat>
#ifdef EMU_C99
#if !defined(_MSC_VER) && !defined(_M_IX86)
#error Don't know how to implement C99 math functions here ...
#else
#if defined(_WIN64)
#error Can't use inline assembler on Win 64 platform ...
#endif
#endif
/* Floating point classification functions. */
int __isinfd(double x)
{
int c = _fpclass(x);
return c == _FPCLASS_NINF || c == _FPCLASS_PINF;
}
int __isnand(double x)
{
int c = _fpclass(x);
return c == _FPCLASS_SNAN || c == _FPCLASS_QNAN;
}
int __isnormald(double x)
{
int c = _fpclass(x);
return c == _FPCLASS_NN || c == _FPCLASS_PN;
}
/* Quoted from ISO 9899:1999 (E):
7.12.9.5 The lrint and llrint functions
Synopsis
1 #include <math.h>
long int lrint(double x);
long int lrintf(float x);
long int lrintl(long double x);
long long int llrint(double x);
long long int llrintf(float x);
long long int llrintl(long double x);
Description
2 The lrint and llrint functions round their argument to the nearest
integer value, rounding according to the current rounding direction.
If the rounded value is outside the range of the return type, the
numeric result is unspecified. A range error may occur if the magni-
tude of x is too large.
Returns
3 The lrint and llrint functions return the rounded integer value.
*/
long int lrint(double x)
{
long int i;
__asm {
fld x
fistp i
}
return i;
}
/* Quoted from ISO 9899:1999 (E):
7.12.9.6 The round functions
Synopsis
1 #include <math.h>
double round(double x);
float roundf(float x);
long double roundl(long double x);
Description
2 The round functions round their argument to the nearest integer value in floating-point
format, rounding halfway cases away from zero, regardless of the current rounding
direction.
Returns
3 The round functions return the rounded integer value.
*/
double round(double x)
{
if (x >= 0.0)
return floor(x + 0.5);
else
return ceil(x - 0.5);
}
/* Quoted from ISO 9899:1999 (E):
7.12.10.2 The remainder functions
Synopsis
1 #include <math.h>
double remainder(double x, double y);
float remainderf(float x, float y);
long double remainderl(long double x, long double y);
Description
2 The remainder functions compute the remainder x REM y required
by IEC 60559.201)
Returns
3 The remainder functions return x REM y.
Footnote:
201) "When y != 0, the remainder r = x REM y is defined regardless of the
rounding mode by the mathematical relation r = x - ny, where n is the
integer nearest the exact value of x/y; whenever | n - x/y | = 1/2,
then n is even. Thus, the remainder is always exact. If r = 0, its
sign shall be that of x." This definition is applicable for all
implementations.
*/
double remainder(double x, double y)
{
double r;
__asm {
fld y
fld x
again: fprem1 /* Partial IEEE 754 remainder of x/y. */
fstsw ax /* Move status word into AX. */
fwait /* Wait till move completed. */
sahf /* Move status word into CPU flags. */
jpe again /* Was partial if if C2=PF=1, repeat. */
fstp st(1) /* Move result to TOS. */
fstp r /* Store result and pop stack. */
}
return r;
}
#endif // EMU_C99

36
main/emu_c99.h Normal file
View File

@@ -0,0 +1,36 @@
/*
* Workaround: Emulate some C99 <math.h> functions.
*/
#ifdef EMU_C99
#include <cassert>
long int lrint(double x);
double round(double x);
double remainder(double x, double y);
#define isfinite(x) \
((sizeof (x) == sizeof (float)) ? _finite((double)(x)) : \
(sizeof (x) == sizeof (double)) ? _finite(x) : \
(assert(0),-1))
#define isinf(x) \
((sizeof (x) == sizeof (float)) ? __isinfd((double)(x)) : \
(sizeof (x) == sizeof (double)) ? __isinfd(x) : \
(assert(0),-1))
#define isnan(x) \
((sizeof (x) == sizeof (float)) ? __isnand((double)(x)) : \
(sizeof (x) == sizeof (double)) ? __isnand(x) : \
(assert(0),-1))
#define isnormal(x) \
((sizeof (x) == sizeof (float)) ? __isnormald((double)(x)) : \
(sizeof (x) == sizeof (double)) ? __isnormald(x) : \
(assert(0),-1))
int __isinfd(double);
int __isnand(double);
int __isnormald(double);
#endif

55
main/helpbrowser.cpp Normal file
View File

@@ -0,0 +1,55 @@
/****************************************************************************
**
** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the documentation of Qt. It was originally
** published as part of Qt Quarterly.
**
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License versions 2.0 or 3.0 as published by the Free
** Software Foundation and appearing in the file LICENSE.GPL included in
** the packaging of this file. Please review the following information
** to ensure GNU General Public Licensing requirements will be met:
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html. In addition, as a special
** exception, Nokia gives you certain additional rights. These rights
** are described in the Nokia Qt GPL Exception version 1.3, included in
** the file GPL_EXCEPTION.txt in this package.
**
** Qt for Windows(R) Licensees
** As a special exception, Nokia, as the sole copyright holder for Qt
** Designer, grants users of the Qt/Eclipse Integration plug-in the
** right for the Qt/Eclipse Integration to link to functionality
** provided by Qt Designer and its related libraries.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
****************************************************************************/
#include "helpbrowser.h"
#include <QHelpEngine>
HelpBrowser::HelpBrowser(QHelpEngine *helpEngine, QWidget *parent)
: QTextBrowser(parent), helpEngine(helpEngine)
{
setOpenExternalLinks(true);
}
QVariant HelpBrowser::loadResource(int type, const QUrl &url)
{
if (url.scheme() == "qthelp")
return QVariant(helpEngine->fileData(url));
else
return QTextBrowser::loadResource(type, url);
}

58
main/helpbrowser.h Normal file
View File

@@ -0,0 +1,58 @@
/****************************************************************************
**
** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the documentation of Qt. It was originally
** published as part of Qt Quarterly.
**
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License versions 2.0 or 3.0 as published by the Free
** Software Foundation and appearing in the file LICENSE.GPL included in
** the packaging of this file. Please review the following information
** to ensure GNU General Public Licensing requirements will be met:
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html. In addition, as a special
** exception, Nokia gives you certain additional rights. These rights
** are described in the Nokia Qt GPL Exception version 1.3, included in
** the file GPL_EXCEPTION.txt in this package.
**
** Qt for Windows(R) Licensees
** As a special exception, Nokia, as the sole copyright holder for Qt
** Designer, grants users of the Qt/Eclipse Integration plug-in the
** right for the Qt/Eclipse Integration to link to functionality
** provided by Qt Designer and its related libraries.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
****************************************************************************/
#ifndef TEXTBROWSER_H
#define TEXTBROWSER_H
#include <QTextBrowser>
class QHelpEngine;
class HelpBrowser : public QTextBrowser
{
Q_OBJECT
public:
HelpBrowser(QHelpEngine *helpEngine, QWidget *parent = 0);
QVariant loadResource(int type, const QUrl &url);
private:
QHelpEngine *helpEngine;
};
#endif

53
main/lc_application.cpp Normal file
View File

@@ -0,0 +1,53 @@
/****************************************************************************
**
* QApplication derived class to catch QFileOpenEvent on Mac OS.
* This implements opening files on double click in Finder,
* whether the app is running or not.
* When the event arrives on start up, the file name is cached here,
* later an eventFilter in QC_ApplicationWindow handles the event directly.
Copyright (C) 2018 A. Stebich (librecad@mail.lordofbikes.de)
Copyright (C) 2018 Simon Wells <simonrwells@gmail.com>
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 2
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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#include <QStringList>
#include <QFileOpenEvent>
#include "lc_application.h"
LC_Application::LC_Application(int &argc, char **argv)
: QApplication(argc, argv)
{
}
// This is only used until the event filter is in place in mainwindow
bool LC_Application::event(QEvent *event)
{
#ifdef Q_OS_MAC
if (QEvent::FileOpen == event->type()) {
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(event);
files.append( openEvent->file());
}
#endif
return QApplication::event(event);
}
QStringList const& LC_Application::fileList(void) const
{
return files;
}

50
main/lc_application.h Normal file
View File

@@ -0,0 +1,50 @@
/****************************************************************************
**
* QApplication derived class to catch QFileOpenEvent on Mac OS.
* This implements opening files on double click in Finder,
* whether the app is running or not.
* When the event arrives on start up, the file name is cached here,
* later an eventFilter in QC_ApplicationWindow handles the event directly.
Copyright (C) 2018 A. Stebich (librecad@mail.lordofbikes.de)
Copyright (C) 2018 Simon Wells <simonrwells@gmail.com>
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 2
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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef LC_APPLICATION_H
#define LC_APPLICATION_H
#include <QApplication>
class QStringList;
class LC_Application : public QApplication
{
Q_OBJECT
public:
explicit LC_Application(int &argc, char **argv);
QStringList const& fileList(void) const;
protected:
bool event(QEvent *event) Q_DECL_OVERRIDE;
private:
QStringList files;
};
#endif // LC_APPLICATION_H

406
main/main.cpp Normal file
View File

@@ -0,0 +1,406 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2018 A. Stebich (librecad@mail.lordofbikes.de)
** Copyright (C) 2018 Simon Wells <simonrwells@gmail.com>
** Copyright (C) 2015-2016 ravas (github.com/r-a-v-a-s)
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <clocale>
#include "main.h"
#include <QDebug>
#include <QApplication>
#include <QSplashScreen>
#include <QSettings>
#include <QMessageBox>
#include <QFileInfo>
#include "rs_fontlist.h"
#include "rs_patternlist.h"
#include "rs_settings.h"
#include "rs_system.h"
#include "qg_dlginitial.h"
#include "lc_application.h"
#include "qc_applicationwindow.h"
#include "rs_debug.h"
#include "console_dxf2pdf.h"
/**
* Main. Creates Application window.
*/
int main(int argc, char** argv)
{
QT_REQUIRE_VERSION(argc, argv, "5.2.1");
/* Check first two arguments in order to decide if we want to run librecad
* as console dxf2pdf tool. On Linux we can create a link to librecad
* executable and name it dxf2pdf. So, we can run either:
* librecad dxf2pdf [options] ...
* or just:
* dxf2pdf [options] ...
*/
if(QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
for (int i = 0; i < qMin(argc, 2); i++) {
QString arg(argv[i]);
if (i == 0) {
arg = QFileInfo(QFile::decodeName(argv[i])).baseName();
}
if (arg.compare("dxf2pdf") == 0) {
return console_dxf2pdf(argc, argv);
}
}
RS_DEBUG->setLevel(RS_Debug::D_WARNING);
LC_Application app(argc, argv);
QCoreApplication::setOrganizationName("LibreCAD");
QCoreApplication::setApplicationName("LibreCAD");
QCoreApplication::setApplicationVersion(XSTR(LC_VERSION));
#if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0))
QGuiApplication::setDesktopFileName("librecad.desktop");
#endif
QSettings settings;
bool first_load = settings.value("Startup/FirstLoad", 1).toBool();
const QString lpDebugSwitch0("-d"),lpDebugSwitch1("--debug") ;
const QString help0("-h"), help1("--help");
bool allowOptions=true;
QList<int> argClean;
for (int i=0; i<argc; i++)
{
QString argstr(argv[i]);
if(allowOptions&&QString::compare("--", argstr)==0)
{
allowOptions=false;
continue;
}
if (allowOptions && (help0.compare(argstr, Qt::CaseInsensitive)==0 ||
help1.compare(argstr, Qt::CaseInsensitive)==0 ))
{
qDebug()<<"Usage: librecad [command] <options> <dxf file>";
qDebug()<<"";
qDebug()<<"Commands:";
qDebug()<<"";
qDebug()<<" dxf2pdf\tRun librecad as console dxf2pdf tool. Use -h for help.";
qDebug()<<"";
qDebug()<<"Options:";
qDebug()<<"";
qDebug()<<" -h, --help\tdisplay this message";
qDebug()<<" -d, --debug <level>";
qDebug()<<"";
RS_DEBUG->print( RS_Debug::D_NOTHING, "possible debug levels:");
RS_DEBUG->print( RS_Debug::D_NOTHING, " %d Nothing", RS_Debug::D_NOTHING);
RS_DEBUG->print( RS_Debug::D_NOTHING, " %d Critical", RS_Debug::D_CRITICAL);
RS_DEBUG->print( RS_Debug::D_NOTHING, " %d Error", RS_Debug::D_ERROR);
RS_DEBUG->print( RS_Debug::D_NOTHING, " %d Warning", RS_Debug::D_WARNING);
RS_DEBUG->print( RS_Debug::D_NOTHING, " %d Notice", RS_Debug::D_NOTICE);
RS_DEBUG->print( RS_Debug::D_NOTHING, " %d Informational", RS_Debug::D_INFORMATIONAL);
RS_DEBUG->print( RS_Debug::D_NOTHING, " %d Debugging", RS_Debug::D_DEBUGGING);
exit(0);
}
if ( allowOptions&& (argstr.startsWith(lpDebugSwitch0, Qt::CaseInsensitive) ||
argstr.startsWith(lpDebugSwitch1, Qt::CaseInsensitive) ))
{
argClean<<i;
// to control the level of debugging output use --debug with level 0-6, e.g. --debug3
// for a list of debug levels use --debug?
// if no level follows, the debugging level is set
argstr.remove(QRegExp("^"+lpDebugSwitch0));
argstr.remove(QRegExp("^"+lpDebugSwitch1));
char level;
if(argstr.size()==0)
{
if(i+1<argc)
{
if(QRegExp("\\d*").exactMatch(argv[i+1]))
{
++i;
qDebug()<<"reading "<<argv[i]<<" as debugging level";
level=argv[i][0];
argClean<<i;
}
else
level='3';
}
else
level='3'; //default to D_WARNING
}
else
level=argstr.toStdString()[0];
switch(level)
{
case '?' :
RS_DEBUG->print( RS_Debug::D_NOTHING, "possible debug levels:");
RS_DEBUG->print( RS_Debug::D_NOTHING, " %d Nothing", RS_Debug::D_NOTHING);
RS_DEBUG->print( RS_Debug::D_NOTHING, " %d Critical", RS_Debug::D_CRITICAL);
RS_DEBUG->print( RS_Debug::D_NOTHING, " %d Error", RS_Debug::D_ERROR);
RS_DEBUG->print( RS_Debug::D_NOTHING, " %d Warning", RS_Debug::D_WARNING);
RS_DEBUG->print( RS_Debug::D_NOTHING, " %d Notice", RS_Debug::D_NOTICE);
RS_DEBUG->print( RS_Debug::D_NOTHING, " %d Informational", RS_Debug::D_INFORMATIONAL);
RS_DEBUG->print( RS_Debug::D_NOTHING, " %d Debugging", RS_Debug::D_DEBUGGING);
return 0;
case '0' + RS_Debug::D_NOTHING :
RS_DEBUG->setLevel( RS_Debug::D_NOTHING);
break;
case '0' + RS_Debug::D_CRITICAL :
RS_DEBUG->setLevel( RS_Debug::D_CRITICAL);
break;
case '0' + RS_Debug::D_ERROR :
RS_DEBUG->setLevel( RS_Debug::D_ERROR);
break;
case '0' + RS_Debug::D_WARNING :
RS_DEBUG->setLevel( RS_Debug::D_WARNING);
break;
case '0' + RS_Debug::D_NOTICE :
RS_DEBUG->setLevel( RS_Debug::D_NOTICE);
break;
case '0' + RS_Debug::D_INFORMATIONAL :
RS_DEBUG->setLevel( RS_Debug::D_INFORMATIONAL);
break;
case '0' + RS_Debug::D_DEBUGGING :
RS_DEBUG->setLevel( RS_Debug::D_DEBUGGING);
break;
default :
RS_DEBUG->setLevel(RS_Debug::D_DEBUGGING);
break;
}
}
}
RS_DEBUG->print("param 0: %s", argv[0]);
RS_SETTINGS->init(app.organizationName(), app.applicationName());
RS_SYSTEM->init( app.applicationName(), app.applicationVersion(), XSTR(QC_APPDIR), argv[0]);
// parse command line arguments that might not need a launched program:
QStringList fileList = handleArgs(argc, argv, argClean);
QString unit = settings.value("Defaults/Unit", "Invalid").toString();
// show initial config dialog:
if (first_load)
{
RS_DEBUG->print("main: show initial config dialog..");
QG_DlgInitial di(nullptr);
QPixmap pxm(":/main/intro_librecad.png");
di.setPixmap(pxm);
if (di.exec())
{
RS_SETTINGS->beginGroup("/Defaults");
unit = RS_SETTINGS->readEntry("/Unit", "None");
RS_SETTINGS->endGroup();
}
RS_DEBUG->print("main: show initial config dialog: OK");
}
auto splash = new QSplashScreen;
bool show_splash = settings.value("Startup/ShowSplash", 1).toBool();
if (show_splash)
{
QPixmap pixmap(":/main/splash_librecad.png");
splash->setPixmap(pixmap);
splash->setAttribute(Qt::WA_DeleteOnClose);
splash->show();
splash->showMessage(QObject::tr("Loading.."),
Qt::AlignRight|Qt::AlignBottom, Qt::black);
app.processEvents();
RS_DEBUG->print("main: splashscreen: OK");
}
RS_DEBUG->print("main: init fontlist..");
RS_FONTLIST->init();
RS_DEBUG->print("main: init fontlist: OK");
RS_DEBUG->print("main: init patternlist..");
RS_PATTERNLIST->init();
RS_DEBUG->print("main: init patternlist: OK");
RS_DEBUG->print("main: loading translation..");
settings.beginGroup("Appearance");
QString lang = settings.value("Language", "en").toString();
QString langCmd = settings.value("LanguageCmd", "en").toString();
settings.endGroup();
RS_SYSTEM->loadTranslation(lang, langCmd);
RS_DEBUG->print("main: loading translation: OK");
RS_DEBUG->print("main: creating main window..");
QC_ApplicationWindow appWin;
#ifdef Q_OS_MAC
app.installEventFilter(&appWin);
#endif
RS_DEBUG->print("main: setting caption");
//appWin.setWindowTitle(app.applicationName());
appWin.setWindowTitle("激光加工平台");
RS_DEBUG->print("main: show main window");
settings.beginGroup("Geometry");
int windowWidth = settings.value("WindowWidth", 1024).toInt();
int windowHeight = settings.value("WindowHeight", 1024).toInt();
int windowX = settings.value("WindowX", 32).toInt();
int windowY = settings.value("WindowY", 32).toInt();
settings.endGroup();
settings.beginGroup("Defaults");
if( !settings.contains("UseQtFileOpenDialog")) {
#ifdef Q_OS_LINUX
// on Linux don't use native file dialog
// because of case insensitive filters (issue #791)
settings.setValue("UseQtFileOpenDialog", QVariant(1));
#else
settings.setValue("UseQtFileOpenDialog", QVariant(0));
#endif
}
settings.endGroup();
if (!first_load)
appWin.resize(windowWidth, windowHeight);
appWin.move(windowX, windowY);
bool maximize = settings.value("Startup/Maximize", 0).toBool();
//由于软件使用后窗口不能保持最大,每次都需调整,因此暂时把窗口调到最大。
appWin.showMaximized();
if (maximize || first_load)
appWin.showMaximized();
else
appWin.show();
RS_DEBUG->print("main: set focus");
appWin.setFocus();
RS_DEBUG->print("main: creating main window: OK");
if (show_splash)
{
RS_DEBUG->print("main: updating splash");
splash->raise();
splash->showMessage(QObject::tr("Loading..."),
Qt::AlignRight|Qt::AlignBottom, Qt::black);
RS_DEBUG->print("main: processing events");
qApp->processEvents();
RS_DEBUG->print("main: updating splash: OK");
}
// Set LC_NUMERIC so that entering numeric values uses . as the decimal separator
setlocale(LC_NUMERIC, "C");
RS_DEBUG->print("main: loading files..");
#ifdef Q_OS_MAC
// get the file list from LC_Application
fileList << app.fileList();
#endif
bool files_loaded = false;
for (QStringList::Iterator it = fileList.begin(); it != fileList.end(); ++it )
{
if (show_splash)
{
splash->showMessage(QObject::tr("Loading File %1..")
.arg(QDir::toNativeSeparators(*it)),
Qt::AlignRight|Qt::AlignBottom, Qt::black);
qApp->processEvents();
}
appWin.slotFileOpen(*it);
files_loaded = true;
}
RS_DEBUG->print("main: loading files: OK");
if (!files_loaded)
{
appWin.slotFileNewNew();
}
if (show_splash)
splash->finish(&appWin);
else
delete splash;
if (first_load)
settings.setValue("Startup/FirstLoad", 0);
RS_DEBUG->print("main: entering Qt event loop");
int return_code = app.exec();
RS_DEBUG->print("main: exited Qt event loop");
return return_code;
}
/**
* Handles command line arguments that might not require a GUI.
*
* @return list of files to load on startup.
*/
QStringList handleArgs(int argc, char** argv, const QList<int>& argClean)
{
RS_DEBUG->print("main: handling args..");
QStringList ret;
bool doexit = false;
for (int i=1; i<argc; i++)
{
if(argClean.indexOf(i)>=0) continue;
if (!QString(argv[i]).startsWith("-"))
{
QString fname = QDir::toNativeSeparators(
QFileInfo(QFile::decodeName(argv[i])).absoluteFilePath());
ret.append(fname);
}
else if (QString(argv[i])=="--exit")
{
doexit = true;
}
}
if (doexit)
{
exit(0);
}
RS_DEBUG->print("main: handling args: OK");
return ret;
}

44
main/main.h Normal file
View File

@@ -0,0 +1,44 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef MAIN_H
#define MAIN_H
#include<QStringList>
#define STR(x) #x
#define XSTR(x) STR(x)
/**
* @brief handleArgs
* @param argc cli argument counter from main()
* @param argv cli arguments from main()
* @param argClean a list of indices to be ignored
* @return
*/
QStringList handleArgs(int argc, char** argv, const QList<int>& argClean);
#endif

94
main/mainwindowx.cpp Normal file
View File

@@ -0,0 +1,94 @@
/*
**********************************************************************************
**
** This file was created for the LibreCAD project (librecad.org), a 2D CAD program.
**
** Copyright (C) 2015 ravas (github.com/r-a-v-a-s)
**
** 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 2
** 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**
**********************************************************************************
*/
#include "mainwindowx.h"
#include <QDockWidget>
#include <QToolBar>
namespace Sorting
{
bool byWindowTitle(QWidget* left, QWidget* right)
{
return left->windowTitle() < right->windowTitle();
}
}
MainWindowX::MainWindowX(QWidget* parent)
: QMainWindow(parent) {}
void MainWindowX::sortWidgetsByTitle(QList<QDockWidget*>& list)
{
std::sort(list.begin(), list.end(), Sorting::byWindowTitle);
}
void MainWindowX::sortWidgetsByTitle(QList<QToolBar*>& list)
{
std::sort(list.begin(), list.end(), Sorting::byWindowTitle);
}
void MainWindowX::toggleLeftDockArea(bool state)
{
foreach (QDockWidget* dw, findChildren<QDockWidget*>())
{
if (dockWidgetArea(dw) == Qt::LeftDockWidgetArea && !dw->isFloating())
dw->setVisible(state);
}
}
void MainWindowX::toggleRightDockArea(bool state)
{
foreach (QDockWidget* dw, findChildren<QDockWidget*>())
{
if (dockWidgetArea(dw) == Qt::RightDockWidgetArea && !dw->isFloating())
dw->setVisible(state);
}
}
void MainWindowX::toggleTopDockArea(bool state)
{
foreach (QDockWidget* dw, findChildren<QDockWidget*>())
{
if (dockWidgetArea(dw) == Qt::TopDockWidgetArea && !dw->isFloating())
dw->setVisible(state);
}
}
void MainWindowX::toggleBottomDockArea(bool state)
{
foreach (QDockWidget* dw, findChildren<QDockWidget*>())
{
if (dockWidgetArea(dw) == Qt::BottomDockWidgetArea && !dw->isFloating())
dw->setVisible(state);
}
}
void MainWindowX::toggleFloatingDockwidgets(bool state)
{
foreach (QDockWidget* dw, findChildren<QDockWidget*>())
{
if (dw->isFloating())
dw->setVisible(state);
}
}

29
main/mainwindowx.h Normal file
View File

@@ -0,0 +1,29 @@
#ifndef MAINWINDOWX_H
#define MAINWINDOWX_H
#include <QMainWindow>
/**
* an eXtension of QMainWindow;
* It is intended to be generic,
* for use with other projects.
*/
class MainWindowX : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindowX(QWidget* parent = 0);
void sortWidgetsByTitle(QList<QDockWidget*>& list);
void sortWidgetsByTitle(QList<QToolBar*>& list);
public slots:
void toggleRightDockArea(bool state);
void toggleLeftDockArea(bool state);
void toggleTopDockArea(bool state);
void toggleBottomDockArea(bool state);
void toggleFloatingDockwidgets(bool state);
};
#endif // MAINWINDOWX_H

File diff suppressed because it is too large Load Diff

454
main/qc_applicationwindow.h Normal file
View File

@@ -0,0 +1,454 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
// Changes: https://github.com/LibreCAD/LibreCAD/commits/master/librecad/src/main/qc_applicationwindow.h
#ifndef QC_APPLICATIONWINDOW_H
#define QC_APPLICATIONWINDOW_H
#include "mainwindowx.h"
#include "rs_pen.h"
#include "rs_snapper.h"
#include <QMap>
#include "dd_motor_test_dc.h"
#include "devicecontrolpaneldcwidget.h"
#include "devicectluserdcwidget.h"
#include "devicestateuserdcwidget.h"
#include "devicesysteminfodcwidget.h"
#include "dmplot.h"
#include "cameradcwidget.h"
#include "devicestateinfodcwidget.h"
#include "devicesetdcwidget.h"
#include "devicealarmdcwidget.h"
#include "devicesysteminfodcwidget.h"
class QMdiArea;
class QMdiSubWindow;
class QC_MDIWindow;
class QG_LibraryWidget;
class QG_CadToolBar;
class QG_SnapToolBar;
class QC_DialogFactory;
class QG_LayerWidget;
class QG_BlockWidget;
class QG_CommandWidget;
class QG_CoordinateWidget;
class QG_MouseWidget;
class QG_SelectionWidget;
class QG_RecentFiles;
class QG_PenToolBar;
class QC_PluginInterface;
class QG_ActiveLayerName;
class LC_SimpleTests;
class LC_CustomToolbar;
class QG_ActionHandler;
class RS_GraphicView;
class RS_Document;
class TwoStackedLabels;
class LC_ActionGroupManager;
class LC_PenWizard;
struct DockAreas
{
QAction* left {nullptr};
QAction* right {nullptr};
QAction* top {nullptr};
QAction* bottom {nullptr};
QAction* floating {nullptr};
};
/**
* Main application window. Hold together document, view and controls.
*
* @author Andrew Mustun
*/
class QC_ApplicationWindow: public MainWindowX
{
Q_OBJECT
public:
QC_ApplicationWindow();
~QC_ApplicationWindow();
void initSettings();
void storeSettings();
bool queryExit(bool force);
/** Catch hotkey for giving focus to command line. */
virtual void keyPressEvent(QKeyEvent* e) override;
void setRedoEnable(bool enable);
void setUndoEnable(bool enable);
bool loadStyleSheet(QString path);
bool eventFilter(QObject *obj, QEvent *event) override;
QMap<QString, QAction*> a_map;
LC_ActionGroupManager* ag_manager {nullptr};
DeviceStateInfoDCWidget* deviceStateInfoDCWidget{nullptr};
//dd_motor_test_dc_widget* pDd_motor_test_dc_widget{nullptr};
DeviceControlPanelDCWidget* deviceControlPanelDCWidget{nullptr};
//DeviceCtlUserDCWidget * devicectluserDCWidget{nullptr};
//DeviceStateUserDCWidget * devicestateuserDCWidget{nullptr};
DeviceAlarmDCWidget* deviceAlarmDCWidget{nullptr};
DMPlot* dmPlot{nullptr};
CameraDCWidget* cameraDCWidget{nullptr};
DeviceSetDCWidget* deviceSetDCWidget{nullptr};
DeviceSystemInfoDCWidget* deviceSystemInfoDCWidget{nullptr};
public slots:
void relayAction(QAction* q_action);
void slotFocus();
void slotBack();
void slotKillAllActions();
void slotEnter();
void slotFocusCommandLine();
void slotError(const QString& msg);
void slotWindowActivated(int);
void slotWindowActivated(QMdiSubWindow* w);
void slotWindowsMenuAboutToShow();
void slotWindowsMenuActivated(bool);
void slotCascade();
void slotTile();
void slotTileHorizontal();
void slotTileVertical();
void slotSetMaximized();
void slotTabShapeRounded();
void slotTabShapeTriangular();
void slotTabPositionNorth();
void slotTabPositionSouth();
void slotTabPositionEast();
void slotTabPositionWest();
void slotToggleTab();
void slotZoomAuto();
void slotPenChanged(RS_Pen p);
void slotSnapsChanged(RS_SnapMode s);
void slotEnableActions(bool enable);
/** generates a new document for a graphic. */
QC_MDIWindow* slotFileNew(RS_Document* doc=nullptr);
/** generates a new document based in predefined template */
void slotFileNewNew();
/** generates a new document based in selected template */
void slotFileNewTemplate();
/** opens a document */
void slotFileOpen();
/**
* opens the given file.
*/
void slotFileOpen(const QString& fileName, RS2::FormatType type);
void slotFileOpen(const QString& fileName); // Assume Unknown type
void slotFileOpenRecent(QAction* action);
/** saves a document */
void slotFileSave();
/** saves a document under a different filename*/
void slotFileSaveAs();
/** saves all open documents; return false == operation cancelled **/
bool slotFileSaveAll();
/** auto-save document */
void slotFileAutoSave();
/** exports the document as bitmap */
void slotFileExport();
bool slotFileExport(const QString& name,
const QString& format,
QSize size,
QSize borders,
bool black,
bool bw=true);
/** closing the current file */
void slotFileClosing(QC_MDIWindow*);
/** close all files; return false == operation cancelled */
bool slotFileCloseAll();
/** prints the current file */
void slotFilePrint(bool printPDF=false);
void slotFilePrintPDF();
/** shows print preview of the current file */
void slotFilePrintPreview(bool on);
/** exits the application */
void slotFileQuit();
/** toggle the grid */
void slotViewGrid(bool toggle);
/** toggle the draft mode */
void slotViewDraft(bool toggle);
/** toggle the statusbar */
void slotViewStatusBar(bool toggle);
void slotOptionsGeneral();
void slotImportBlock();
/** shows an about dlg*/
void showAboutWindow();
/**
* @brief slotUpdateActiveLayer
* update layer name when active layer changed
*/
void slotUpdateActiveLayer();
void execPlug();
void invokeLinkList();
void toggleFullscreen(bool checked);
void setPreviousZoomEnable(bool enable);
void hideOptions(QC_MDIWindow*);
void widgetOptionsDialog();
void modifyCommandTitleBar(Qt::DockWidgetArea area);
void reloadStyleSheet();
void updateGridStatus(const QString&);
void showDeviceOptions();
void updateDevice(QString);
void invokeMenuCreator();
void invokeToolbarCreator();
void createToolbar(const QString& toolbar_name);
void destroyToolbar(const QString& toolbar_name);
void destroyMenu(const QString& activator);
void unassignMenu(const QString& activator, const QString& menu_name);
void assignMenu(const QString& activator, const QString& menu_name);
void invokeMenuAssigner(const QString& menu_name);
void updateMenu(const QString& menu_name);
void invokeLicenseWindow();
signals:
void gridChanged(bool on);
void draftChanged(bool on);
void printPreviewChanged(bool on);
void windowsChanged(bool windowsLeft);
public:
/**
* @return Pointer to application window.
*/
static QC_ApplicationWindow* getAppWindow() {
return appWindow;
}
/**
* @return Pointer to MdiArea.
*/
QMdiArea const* getMdiArea() const;
QMdiArea* getMdiArea();
/**
* @return Pointer to the currently active MDI Window or nullptr if no
* MDI Window is active.
*/
const QC_MDIWindow* getMDIWindow() const;
QC_MDIWindow* getMDIWindow();
/**
* Implementation from RS_MainWindowInterface (and QS_ScripterHostInterface).
*
* @return Pointer to the graphic view of the currently active document
* window or nullptr if no window is available.
*/
const RS_GraphicView* getGraphicView() const;
RS_GraphicView* getGraphicView();
/**
* Implementation from RS_MainWindowInterface (and QS_ScripterHostInterface).
*
* @return Pointer to the graphic document of the currently active document
* window or nullptr if no window is available.
*/
const RS_Document* getDocument() const;
RS_Document* getDocument();
/**
* Creates a new document. Implementation from RS_MainWindowInterface.
*/
void createNewDocument(const QString& fileName = QString(), RS_Document* doc=nullptr);
void redrawAll();
void updateGrids();
QG_BlockWidget* getBlockWidget(void)
{
return blockWidget;
}
QG_SnapToolBar* getSnapToolBar(void)
{
return snapToolBar;
}
QG_SnapToolBar const* getSnapToolBar(void) const
{
return snapToolBar;
}
/**
* Find opened window for specified document.
*/
QC_MDIWindow* getWindowWithDoc(const RS_Document* doc);
protected:
void closeEvent(QCloseEvent*) override;
//! \{ accept drop files to open
virtual void dropEvent(QDropEvent* e) override;
virtual void dragEnterEvent(QDragEnterEvent * event) override;
void changeEvent(QEvent* event) override;
//! \}
private:
QMenu* createPopupMenu() override;
QString format_filename_caption(const QString &qstring_in);
/** Helper function for Menu file -> New & New.... */
bool slotFileNewHelper(QString fileName, QC_MDIWindow* w = nullptr);
// more helpers
void doArrangeWindows(RS2::SubWindowMode mode, bool actuallyDont = false);
void setTabLayout(RS2::TabShape s, RS2::TabPosition p);
bool doSave(QC_MDIWindow* w, bool forceSaveAs = false);
void doClose(QC_MDIWindow* w, bool activateNext = true);
void doActivate(QMdiSubWindow* w);
int showCloseDialog(QC_MDIWindow* w, bool showSaveAll = false);
void enableFileActions(QC_MDIWindow* w);
/**
* @brief updateWindowTitle, for draft mode, add "Draft Mode" to window title
* @param w, pointer to window widget
*/
void updateWindowTitle(QWidget* w);
//Plugin support
void loadPlugins();
QMenu *findMenu(const QString &searchMenu, const QObjectList thisMenuList, const QString& currentEntry);
#ifdef LC_DEBUGGING
LC_SimpleTests* m_pSimpleTest {nullptr};
#endif
/** Pointer to the application window (this). */
static QC_ApplicationWindow* appWindow;
QTimer *autosaveTimer {nullptr};
QG_ActionHandler* actionHandler {nullptr};
/** MdiArea for MDI */
QMdiArea* mdiAreaCAD {nullptr};
QMdiSubWindow* activedMdiSubWindow {nullptr};
QMdiSubWindow* current_subwindow {nullptr};
/** Dialog factory */
QC_DialogFactory* dialogFactory {nullptr};
/** Recent files list */
QG_RecentFiles* recentFiles {nullptr};
// --- Dockwidgets ---
//! toggle actions for the dock areas
DockAreas dock_areas;
/** Layer list widget */
QG_LayerWidget* layerWidget {nullptr};
/** Block list widget */
QG_BlockWidget* blockWidget {nullptr};
/** Library browser widget */
QG_LibraryWidget* libraryWidget {nullptr};
/** Command line */
QG_CommandWidget* commandWidget {nullptr};
LC_PenWizard* pen_wiz {nullptr};
// --- Statusbar ---
/** Coordinate widget */
QG_CoordinateWidget* coordinateWidget {nullptr};
/** Mouse widget */
QG_MouseWidget* mouseWidget {nullptr};
/** Selection Status */
QG_SelectionWidget* selectionWidget {nullptr};
QG_ActiveLayerName* m_pActiveLayerName {nullptr};
TwoStackedLabels* grid_status {nullptr};
// --- Menus ---
QMenu* windowsMenu {nullptr};
QMenu* scriptMenu {nullptr};
QMenu* helpMenu {nullptr};
QMenu* testMenu {nullptr};
QMenu* file_menu {nullptr};
// --- Toolbars ---
QG_SnapToolBar* snapToolBar {nullptr};
QG_PenToolBar* penToolBar {nullptr}; //!< for selecting the current pen
QToolBar* optionWidget {nullptr}; //!< for individual tool options
// --- Actions ---
QAction* previousZoom {nullptr};
QAction* undoButton {nullptr};
QAction* redoButton {nullptr};
QAction* scriptOpenIDE {nullptr};
QAction* scriptRun {nullptr};
QAction* helpAboutApp {nullptr};
// --- Flags ---
bool previousZoomEnable{false};
bool undoEnable{false};
bool redoEnable{false};
// --- Lists ---
QList<QC_PluginInterface*> loadedPlugins;
QList<QAction*> toolbar_view_actions;
QList<QAction*> dockwidget_view_actions;
QList<QC_MDIWindow*> window_list;
QList<QAction*> recentFilesAction;
QStringList openedFiles;
// --- Strings ---
QString style_sheet_path;
};
#ifdef _WINDOWS
extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
#endif
#endif

123
main/qc_dialogfactory.cpp Normal file
View File

@@ -0,0 +1,123 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QMdiArea>
#include "rs_grid.h"
#include "qc_dialogfactory.h"
#include "qc_applicationwindow.h"
#include "qg_blockwidget.h"
#include "qc_mdiwindow.h"
#include "qg_graphicview.h"
#include "rs_blocklist.h"
#include "rs_debug.h"
QC_DialogFactory::QC_DialogFactory(QWidget* parent, QToolBar* ow) :
QG_DialogFactory(parent, ow)
{}
/**
* Provides a window for editing the active block.
*/
void QC_DialogFactory::requestEditBlockWindow(RS_BlockList* blockList) {
RS_DEBUG->print(RS_Debug::D_DEBUGGING, "QC_DialogFactory::requestEditBlockWindow()");
QC_ApplicationWindow* appWindow = QC_ApplicationWindow::getAppWindow();
QC_MDIWindow* parent = appWindow->getMDIWindow();
if (!appWindow || !parent) {
RS_DEBUG->print(RS_Debug::D_ERROR, "QC_DialogFactory::requestEditBlockWindow(): nullptr ApplicationWindow or MDIWindow");
return;
}
// If block is opened from another block the parent must be set
// to graphic that contain all these blocks.
if (parent->getDocument()->rtti() == RS2::EntityBlock) {
parent = parent->getParentWindow();
}
//get blocklist from block widget, bug#3497154
if (!blockList ) {
RS_DEBUG->print(RS_Debug::D_NOTICE, "QC_DialogFactory::requestEditBlockWindow(): get blockList from appWindow");
blockList = appWindow->getBlockWidget()->getBlockList();
}
RS_Block* blk = blockList->getActive();
if (!blk) {
RS_DEBUG->print(RS_Debug::D_WARNING, "QC_DialogFactory::requestEditBlockWindow(): no active block is selected");
return;
}
RS_DEBUG->print(RS_Debug::D_DEBUGGING, "QC_DialogFactory::requestEditBlockWindow(): edit block %s", blk->getName().toLatin1().data());
// std::cout<<"QC_DialogFactory::requestEditBlockWindow(): size()="<<((blk==NULL)?0:blk->count() )<<std::endl;
QC_MDIWindow* blockWindow = appWindow->getWindowWithDoc(blk);
if (blockWindow) {
RS_DEBUG->print(RS_Debug::D_DEBUGGING, "QC_DialogFactory::requestEditBlockWindow(): activate existing window");
appWindow->getMdiArea()->setActiveSubWindow(blockWindow);
} else {
RS_DEBUG->print(RS_Debug::D_DEBUGGING, "QC_DialogFactory::requestEditBlockWindow(): create new window");
QC_MDIWindow* w = appWindow->slotFileNew(blk);
if (!w) {
RS_DEBUG->print(RS_Debug::D_ERROR, "QC_DialogFactory::requestEditBlockWindow(): can't create new child window");
return;
}
// the parent needs a pointer to the block window and vice versa
parent->addChildWindow(w);
w->getGraphicView()->zoomAuto(false);
//update grid settings, bug#3443293
w->getGraphicView()->getGrid()->updatePointArray();
}
RS_DEBUG->print(RS_Debug::D_DEBUGGING, "QC_DialogFactory::requestEditBlockWindow(): OK");
}
/**
* Closes the window that is editing the given block.
*/
void QC_DialogFactory::closeEditBlockWindow(RS_Block* block) {
RS_DEBUG->print("QC_DialogFactory::closeEditBlockWindow");
QC_ApplicationWindow* appWindow = QC_ApplicationWindow::getAppWindow();
QC_MDIWindow* blockWindow = appWindow->getWindowWithDoc(block);
if (!blockWindow) {
RS_DEBUG->print("QC_DialogFactory::closeEditBlockWindow: block has no opened window");
return;
}
RS_DEBUG->print("QC_DialogFactory::closeEditBlockWindow: closing mdi");
appWindow->slotFileClosing(blockWindow);
RS_DEBUG->print("QC_DialogFactory::closeEditBlockWindow: OK");
}

47
main/qc_dialogfactory.h Normal file
View File

@@ -0,0 +1,47 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef QC_DIALOGFACTORY_H
#define QC_DIALOGFACTORY_H
#include "qg_dialogfactory.h"
/**
* This is the LibreCAD specific implementation of a widget which can create and
* show dialogs. Some functions cannot be implemented on the
* LibreCAD library level and need to be implemented here,
* on the application level.
*/
class QC_DialogFactory: public QG_DialogFactory {
public:
QC_DialogFactory(QWidget* parent, QToolBar* ow);
virtual ~QC_DialogFactory() = default;
virtual void requestEditBlockWindow(RS_BlockList* blockList = nullptr);
virtual void closeEditBlockWindow(RS_Block* block = nullptr);
};
#endif

57
main/qc_graphicview.cpp Normal file
View File

@@ -0,0 +1,57 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include "qc_graphicview.h"
#include "rs_actiondefault.h"
#include "rs_settings.h"
#include "qc_applicationwindow.h"
#include "rs_debug.h"
QC_GraphicView::QC_GraphicView(RS_Document* doc, QWidget* parent)
:QG_GraphicView(parent, "graphicview") {
RS_DEBUG->print("QC_GraphicView::QC_GraphicView()..");
RS_DEBUG->print(" Setting Container..");
if (doc) {
setContainer(doc);
doc->setGraphicView(this);
}
RS_DEBUG->print(" container set.");
setFactorX(4.0);
setFactorY(4.0);
setOffset(50, 50);
setBorders(10, 10, 10, 10);
if (doc) {
setDefaultAction(new RS_ActionDefault(*doc, *this));
}
}
// EOF

57
main/qc_graphicview.h Normal file
View File

@@ -0,0 +1,57 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef QC_GRAPHICVIEW_H
#define QC_GRAPHICVIEW_H
#include <QWidget>
#include "rs_document.h"
#include "rs_eventhandler.h"
#include "qg_graphicview.h"
class QC_ApplicationWindow;
/**
* A view widget for the visualisation of drawings.
* Very thin wrapper for LibreCAD specific settings.
*
* @author Andrew Mustun
*/
class QC_GraphicView : public QG_GraphicView {
Q_OBJECT
public:
QC_GraphicView(RS_Document* doc, QWidget* parent=0);
virtual ~QC_GraphicView()=default;
private:
//RS_Document* document;
};
#endif

482
main/qc_mdiwindow.cpp Normal file
View File

@@ -0,0 +1,482 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2019 Shawn Curry (noneyabiz@mail.wasent.cz)
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<iostream>
#include "qc_mdiwindow.h"
#include <QtPrintSupport/QPrinter>
#include <QtPrintSupport/QPrintDialog>
#include <QApplication>
#include <QCloseEvent>
#include <QCursor>
#include <QMessageBox>
#include <QFileInfo>
#include <QMdiArea>
#include <QPainter>
#include "rs_graphic.h"
#include "rs_settings.h"
#include "qg_exitdialog.h"
#include "qg_filedialog.h"
#include "rs_insert.h"
#include "rs_mtext.h"
#include "rs_pen.h"
#include "qg_graphicview.h"
#include "rs_debug.h"
int QC_MDIWindow::idCounter = 0;
/**
* Constructor.
*
* @param doc Pointer to an existing document of NULL if a new
* document shall be created for this window.
* @param parent An instance of QMdiArea.
*/
QC_MDIWindow::QC_MDIWindow(RS_Document* doc, QWidget* parent, Qt::WindowFlags wflags)
: QMdiSubWindow(parent, wflags)
{
setAttribute(Qt::WA_DeleteOnClose);
cadMdiArea=qobject_cast<QMdiArea*>(parent);
if (doc==nullptr) {
document = new RS_Graphic();
document->newDoc();
owner = true;
} else {
document = doc;
owner = false;
}
graphicView = new QG_GraphicView(this, 0, document);
graphicView->setObjectName("graphicview");
connect(graphicView, SIGNAL(previous_zoom_state(bool)),
parent->window(), SLOT(setPreviousZoomEnable(bool)));
setWidget(graphicView);
id = idCounter++;
setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
if (document) {
if (document->getLayerList()) {
// Link the graphic view to the layer widget
document->getLayerList()->addListener(graphicView);
// Link this window to the layer widget
document->getLayerList()->addListener(this);
}
if (document->getBlockList()) {
// Link the graphic view to the block widget
document->getBlockList()->addListener(graphicView);
// Link this window to the block widget
document->getBlockList()->addListener(this);
}
}
}
/**
* Destructor.
*
* Deletes the document associated with this window.
*/
QC_MDIWindow::~QC_MDIWindow()
{
RS_DEBUG->print("~QC_MDIWindow");
if(!(graphicView && graphicView->isCleanUp())){
//do not clear layer/block lists, if application is being closed
if (document->getLayerList()) {
document->getLayerList()->removeListener(graphicView);
document->getLayerList()->removeListener(this);
}
if (document->getBlockList()) {
document->getBlockList()->removeListener(graphicView);
document->getBlockList()->removeListener(this);
}
if (owner==true && document) {
delete document;
}
document = nullptr;
}
}
QG_GraphicView* QC_MDIWindow::getGraphicView() const
{
return (graphicView) ? graphicView : nullptr;
}
/** @return Pointer to document */
RS_Document* QC_MDIWindow::getDocument() const{
return document;
}
int QC_MDIWindow::getId() const{
return id;
}
RS_EventHandler* QC_MDIWindow::getEventHandler() const{
if (graphicView) {
return graphicView->getEventHandler();
}
else {
return nullptr;
}
}
void QC_MDIWindow::setParentWindow(QC_MDIWindow* p) {
RS_DEBUG->print("QC_MDIWindow::setParentWindow");
parentWindow = p;
}
QC_MDIWindow* QC_MDIWindow::getParentWindow() const {
RS_DEBUG->print("QC_MDIWindow::getParentWindow");
return parentWindow;
}
RS_Graphic* QC_MDIWindow::getGraphic() const {
return document->getGraphic();
}
/**
* Adds another MDI window to the list of known windows that
* depend on this one. This can be another view or a view for
* a particular block.
*/
void QC_MDIWindow::addChildWindow(QC_MDIWindow* w) {
RS_DEBUG->print("RS_MDIWindow::addChildWindow()");
childWindows.append(w);
w->setParentWindow(this);
RS_DEBUG->print("children: %d", childWindows.count());
}
/**
* Removes a child window.
*
* @see addChildWindow
*/
void QC_MDIWindow::removeChildWindow(QC_MDIWindow* w) {
// RS_DEBUG->print("%s %s()", __FILE__, __func__);
if(childWindows.size()>0 ){
if(childWindows.contains(w)){
childWindows.removeAll(w);
// suc=true;
}
}
// bool suc = childWindows.removeAll(w);
// RS_DEBUG->print("successfully removed child window: %d", (int)suc);
// RS_DEBUG->print("children: %d", childWindows.count());
}
QList<QC_MDIWindow*>& QC_MDIWindow::getChildWindows()
{
return childWindows;
}
/**
* @return pointer to the print preview of this drawing or NULL.
*/
QC_MDIWindow* QC_MDIWindow::getPrintPreview() {
for(auto w: childWindows){
if(w->getGraphicView()->isPrintPreview()){
return w;
}
}
return nullptr;
}
/**
* Called by Qt when the user closes this MDI window.
*/
void QC_MDIWindow::closeEvent(QCloseEvent* ce) {
RS_DEBUG->print("QC_MDIWindow::closeEvent begin");
emit(signalClosing(this));
ce->accept(); // handling delegated to QApplication
RS_DEBUG->print("QC_MDIWindow::closeEvent end");
}
/**
* Called when the current pen (color, style, width) has changed.
* Sets the active pen for the document in this MDI window.
*/
void QC_MDIWindow::slotPenChanged(const RS_Pen& pen) {
RS_DEBUG->print("QC_MDIWindow::slotPenChanged() begin");
if (document) {
document->setActivePen(pen);
}
RS_DEBUG->print("QC_MDIWindow::slotPenChanged() end");
}
/**
* Creates a new empty document in this MDI window.
*/
void QC_MDIWindow::slotFileNew() {
RS_DEBUG->print("QC_MDIWindow::slotFileNew begin");
if (document && graphicView) {
document->newDoc();
graphicView->redraw();
}
RS_DEBUG->print("QC_MDIWindow::slotFileNew end");
}
/**
* Creates a new document, loading template, in this MDI window.
*/
bool QC_MDIWindow::slotFileNewTemplate(const QString& fileName, RS2::FormatType type) {
RS_DEBUG->print("QC_MDIWindow::slotFileNewTemplate begin");
bool ret = false;
if (document==NULL || fileName.isEmpty())
return ret;
document->newDoc();
ret = document->loadTemplate(fileName, type);
if (ret) {
RS_DEBUG->print("QC_MDIWindow::slotFileNewTemplate: autoZoom");
graphicView->zoomAuto(false);
} else
RS_DEBUG->print("QC_MDIWindow::slotFileNewTemplate: failed");
RS_DEBUG->print("QC_MDIWindow::slotFileNewTemplate end");
return ret;
}
/**
* Opens the given file in this MDI window.
*/
bool QC_MDIWindow::slotFileOpen(const QString& fileName, RS2::FormatType type) {
RS_DEBUG->print("QC_MDIWindow::slotFileOpen");
bool ret = false;
if (document && !fileName.isEmpty()) {
document->newDoc();
// cosmetics..
// RVT_PORT qApp->processEvents(1000);
qApp->processEvents(QEventLoop::AllEvents, 1000);
ret = document->open(fileName, type);
if (ret) {
//QString message=tr("Loaded document: ")+fileName;
//statusBar()->showMessage(message, 2000);
if (fileName.endsWith(".lff") || fileName.endsWith(".cxf")) {
drawChars();
RS_DEBUG->print("QC_MDIWindow::slotFileOpen: autoZoom");
graphicView->zoomAuto(false);
RS_DEBUG->print("QC_MDIWindow::slotFileOpen: autoZoom: OK");
} else
graphicView->redraw();
} else {
RS_DEBUG->print("QC_MDIWindow::slotFileOpen: failed");
}
} else {
RS_DEBUG->print("QC_MDIWindow::slotFileOpen: cancelled");
//statusBar()->showMessage(tr("Opening aborted"), 2000);
}
RS_DEBUG->print("QC_MDIWindow::slotFileOpen: OK");
return ret;
}
void QC_MDIWindow::slotZoomAuto() {
if(graphicView){
if(graphicView->isPrintPreview()){
graphicView->zoomPage();
}else{
graphicView->zoomAuto();
}
}
}
void QC_MDIWindow::drawChars() {
RS_BlockList* bl = document->getBlockList();
double sep = document->getGraphic()->getVariableDouble("LetterSpacing", 3.0);
double h = sep/3;
sep = sep*3;
for (int i=0; i<bl->count(); ++i) {
RS_Block* ch = bl->at(i);
RS_InsertData data(ch->getName(), RS_Vector(i*sep,0), RS_Vector(1,1), 0, 1, 1, RS_Vector(0,0));
RS_Insert* in = new RS_Insert(document, data);
document->addEntity(in);
QFileInfo info(document->getFilename() );
QString uCode = (ch->getName()).mid(1,4);
RS_MTextData datatx(RS_Vector(i*sep,-h), h, 4*h, RS_MTextData::VATop,
RS_MTextData::HALeft, RS_MTextData::ByStyle, RS_MTextData::AtLeast,
1, uCode, "standard", 0);
/* RS_MTextData datatx(RS_Vector(i*sep,-h), h, 4*h, RS2::VAlignTop,
RS2::HAlignLeft, RS2::ByStyle, RS2::AtLeast,
1, uCode, info.baseName(), 0);*/
RS_MText *tx = new RS_MText(document, datatx);
document->addEntity(tx);
}
}
/**
* Saves the current file.
*
* @param isAutoSave true if this is an "autosave" operation.
* false if this is "Save" operation requested
* by the user.
* @return true if the file was saved successfully.
* false if the file could not be saved or the document
* is invalid.
*/
bool QC_MDIWindow::slotFileSave(bool &cancelled, bool isAutoSave) {
RS_DEBUG->print("QC_MDIWindow::slotFileSave()");
bool ret = false;
cancelled = false;
if (document) {
document->setGraphicView(graphicView);
if (isAutoSave) {
// Autosave filename is always supposed to be present.
// Autosave does not change the cursor.
ret = document->save(true);
} else {
if (document->getFilename().isEmpty()) {
ret = slotFileSaveAs(cancelled);
} else {
QFileInfo info(document->getFilename());
if (!info.isWritable())
return false;
QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
ret = document->save();
QApplication::restoreOverrideCursor();
}
}
}
return ret;
}
/**
* Saves the current file. The user is asked for a new filename
* and format.
*
* @return true if the file was saved successfully or the user cancelled.
* false if the file could not be saved or the document
* is invalid.
*/
bool QC_MDIWindow::slotFileSaveAs(bool &cancelled) {
RS_DEBUG->print("QC_MDIWindow::slotFileSaveAs");
bool ret = false;
cancelled = false;
RS2::FormatType t = RS2::FormatDXFRW;
QG_FileDialog dlg(this);
QString fn = dlg.getSaveFile(&t);
if (document && !fn.isEmpty()) {
QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
document->setGraphicView(graphicView);
ret = document->saveAs(fn, t, true);
QApplication::restoreOverrideCursor();
} else {
// cancel is not an error - returns true
ret = true;
cancelled = true;
}
return ret;
}
void QC_MDIWindow::slotFilePrint() {
RS_DEBUG->print("QC_MDIWindow::slotFilePrint");
//statusBar()->showMessage(tr("Printing..."));
QPrinter printer;
QPrintDialog dialog(&printer, this);
if (dialog.exec()) {
QPainter painter;
painter.begin(&printer);
///////////////////////////////////////////////////////////////////
// TODO: Define printing by using the QPainter methods here
painter.end();
};
//statusBar()->showMessage(tr("Ready."));
}
/**
* Streams some info about an MDI window to stdout.
*/
std::ostream& operator << (std::ostream& os, QC_MDIWindow& w) {
os << "QC_MDIWindow[" << w.getId() << "]:\n";
if (w.parentWindow) {
os << " parentWindow: " << w.parentWindow->getId() << "\n";
} else {
os << " parentWindow: NULL\n";
}
int i=0;
for(auto p: w.childWindows){
os << " childWindow[" << i++ << "]: "
<< p->getId() << "\n";
}
return os;
}
/**
* Return true if this window has children (QC_MDIWindow).
*/
bool QC_MDIWindow::has_children()
{
return !childWindows.isEmpty();
}

151
main/qc_mdiwindow.h Normal file
View File

@@ -0,0 +1,151 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** 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, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef QC_MDIWINDOW_H
#define QC_MDIWINDOW_H
#include <QMdiSubWindow>
#include <QList>
#include "rs.h"
#include "rs_layerlistlistener.h"
#include "rs_blocklistlistener.h"
class QG_GraphicView;
class RS_Document;
class RS_Graphic;
class RS_Pen;
class QMdiArea;
class RS_EventHandler;
class QCloseEvent;
/**
* MDI document window. Contains a document and a view (window).
*
* @author Andrew Mustun
*/
class QC_MDIWindow: public QMdiSubWindow,
public RS_LayerListListener,
public RS_BlockListListener
{
Q_OBJECT
public:
QC_MDIWindow(RS_Document* doc,
QWidget* parent,
Qt::WindowFlags wflags=0);
~QC_MDIWindow();
public slots:
void slotPenChanged(const RS_Pen& p);
void slotFileNew();
bool slotFileNewTemplate(const QString& fileName, RS2::FormatType type);
bool slotFileOpen(const QString& fileName, RS2::FormatType type);
bool slotFileSave(bool &cancelled, bool isAutoSave=false);
bool slotFileSaveAs(bool &cancelled);
void slotFilePrint();
void slotZoomAuto();
public:
/** @return Pointer to graphic view */
QG_GraphicView* getGraphicView() const;
/** @return Pointer to document */
RS_Document* getDocument() const;
/** @return Pointer to graphic or NULL */
RS_Graphic* getGraphic() const;
/** @return Pointer to current event handler */
RS_EventHandler* getEventHandler() const;
void addChildWindow(QC_MDIWindow* w);
void removeChildWindow(QC_MDIWindow* w);
QList<QC_MDIWindow*>& getChildWindows();
QC_MDIWindow* getPrintPreview();
// Methods from RS_LayerListListener Interface:
void layerListModified(bool) override {
setWindowModified(document->isModified());
}
// Methods from RS_BlockListListener Interface:
void blockListModified(bool) override {
setWindowModified(document->isModified());
}
/**
* Sets the parent window that will be notified if this window
* is closed or NULL.
*/
void setParentWindow(QC_MDIWindow* p);
QC_MDIWindow* getParentWindow() const;
/**
* @return The MDI window id.
*/
int getId() const;
friend std::ostream& operator << (std::ostream& os, QC_MDIWindow& w);
bool has_children();
signals:
void signalClosing(QC_MDIWindow*);
protected:
void closeEvent(QCloseEvent*);
private:
void drawChars();
private:
/** window ID */
int id;
/** ID counter */
static int idCounter;
/** Graphic view */
QG_GraphicView* graphicView;
/** Document */
RS_Document* document;
/** Does the window own the document? */
bool owner;
/**
* List of known child windows that show blocks of the same drawing.
*/
QList<QC_MDIWindow*> childWindows;
/**
* Pointer to parent window which needs to know if this window
* is closed or NULL.
*/
QC_MDIWindow* parentWindow{nullptr};
QMdiArea* cadMdiArea;
};
#endif