mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2024-12-25 10:01:38 +08:00
FIXED/REWORKED issue https://github.com/jkriege2/JKQtPlotter/issues/111 : Can't write to PDF files with JKQTPlotter::saveImage() when passing a filename ending in ".pdf" (thanks to https://github.com/fpalazzolo for reporting)
IMPROVED/REWORKED: The functions JKQTBasePlotter::saveImage(), JKQTBasePlotter::saveAsPixelImage(), JKQTBasePlotter::saveAsPDF(), JKQTBasePlotter::saveSVG(), ... gained a bool return value to indicate whether sacing was successful. IMPROVED/REWORKED: More <code>save...()</code> functions will appear in the API of JKQTPlotter, so you don't have to go via JKQTPlotter::getPlotter(). These are merely forwarding the call to the internel JKQTBasePlotter instance.
This commit is contained in:
parent
abad0b01c3
commit
995ca92033
@ -47,6 +47,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
|
||||
<li>FIXED issue <a href="https://github.com/jkriege2/JKQtPlotter/pull/99">#99: Height of one-column key/legend was too large</a> (thanks to <a href="https://github.com/allenbarnett5">user:allenbarnett5/a> for reporting)</li>
|
||||
<li>FIXED/IMPROVED issue <a href="https://github.com/jkriege2/JKQtPlotter/issues/100">#100: Add option to disable resize delay feature by setting the delay to zero</a> (thanks to <a href="https://github.com/fpalazzolo">user:fpalazzolo</a> for reporting)</li>
|
||||
<li>FIXED/NEW: placement of plot-title (was not centerd in its box, but glued to the bottom) by adding a plotstyle parameter JKQTBasePlotterStyle::plotLabelOffset</li>
|
||||
<li>FIXED/REWORKED issue <a href="https://github.com/jkriege2/JKQtPlotter/issues/111">#111: Can't write to PDF files with JKQTPlotter::saveImage() when passing a filename ending in ".pdf"</a> (thanks to <a href="https://github.com/fpalazzolo">user:fpalazzolo/a> for reporting):<br/>While fixing this issue, the functions JKQTBasePlotter::saveImage() etc. gained a bool return value to indicate whether sacing was successful.</li>
|
||||
<li>REORGANIZED: separated line-graphs from jkqtpscatter.h/.cpp into jkqtplines.h/.cpp</li>
|
||||
<li>IMPROVED: QT6-compatibility by removing deprecated warnings</li>
|
||||
<li>IMPROVED: added missing override declarations</li>
|
||||
@ -57,6 +58,8 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
|
||||
<li>IMPROVED/REWORKED: zomm/pan by mouse-wheel: now there are modes that support zoomin AND panning by trakpad and mouse-wheel simultaneously! This can only be implemented using heuristics, due to the way that Qt handles track-pad events, but the current solution should at least improve the behaviour seen before. Mainly <code>jkqtpmwaZoomByWheelAndTrackpadPan</code> was introduced into <code>JKQTPMouseWheelActions</code> und is set as default mode: Here JKQTPlotter tries to distinguish the QWheelEvent s sent by an actual mouse wheel and a trackpad.</li>
|
||||
<li>IMPROVED/REWORKED: better example graphs in \link JKQTPlotterStyling.</li>
|
||||
<li>IMPROVED/REWORKED: legend/key positioning as combination of 3 values, e.g. \c JKQTPKeyOutsideTop|JKQTPKeyTop|JKQTPKeyRight or \c JKQTPKeyInside|JKQTPKeyTopJKQTPKeyRight</li>
|
||||
<li>IMPROVED/REWORKED: The functions JKQTBasePlotter::saveImage(), JKQTBasePlotter::saveAsPixelImage(), JKQTBasePlotter::saveAsPDF(), JKQTBasePlotter::saveSVG(), ... gained a bool return value to indicate whether sacing was successful.</li>
|
||||
<li>IMPROVED/REWORKED: More <code>save...()</code> functions will appear in the API of JKQTPlotter, so you don't have to go via JKQTPlotter::getPlotter(). These are merely forwarding the call to the internel JKQTBasePlotter instance.</li>
|
||||
<li>IMPROVED: documentation of styles: automatized doc image generation.</li>
|
||||
<li>NEW: JKQTPFilledCurveXGraph and JKQTPFilledCurveYGraph can now plot wiggle plots with different fill styles above and below the baseline (feature request <a href="https://github.com/jkriege2/JKQtPlotter/issues/68">#68 Wiggle Plots</a> from <a href="https://github.com/xichaoqiang">user:xichaoqiang</a> </li>
|
||||
<li>NEW/BREAKING CHANGE: data tooltip can now also be shown when "just" moving the mouse (so far this was only possible when dragging the mouse with a button pressed). This also removes JKQtPlotter::getActMouseLeftAsToolTip() and adds JKQtPlotter::getActMouseMoveToolTip() instead! Also the default toolbars and context menus changed!</li>
|
||||
|
@ -3501,7 +3501,7 @@ void JKQTBasePlotter::saveAsGerExcelCSV(const QString& filename) {
|
||||
}
|
||||
|
||||
#ifndef JKQTPLOTTER_COMPILE_WITHOUT_PRINTSUPPORT
|
||||
void JKQTBasePlotter::saveAsPDF(const QString& filename, bool displayPreview) {
|
||||
bool JKQTBasePlotter::saveAsPDF(const QString& filename, bool displayPreview) {
|
||||
loadUserSettings();
|
||||
QString fn=filename;
|
||||
if (fn.isEmpty()) {
|
||||
@ -3513,7 +3513,7 @@ void JKQTBasePlotter::saveAsPDF(const QString& filename, bool displayPreview) {
|
||||
|
||||
if (!fn.isEmpty()) {
|
||||
emit beforeExporting();; auto __finalpaint=JKQTPFinally([&]() { emit afterExporting();});
|
||||
QPrinter* printer=new QPrinter;
|
||||
std::shared_ptr<QPrinter> printer=std::make_shared<QPrinter>();
|
||||
bool doLandscape=widgetWidth>widgetHeight;
|
||||
if (gridPrinting) {
|
||||
gridPrintingCalc();
|
||||
@ -3529,91 +3529,133 @@ void JKQTBasePlotter::saveAsPDF(const QString& filename, bool displayPreview) {
|
||||
printer->setOutputFileName(fn);
|
||||
printer->setPageMargins(QMarginsF(0,0,0,0),QPageLayout::Millimeter);
|
||||
printer->setColorMode(QPrinter::Color);
|
||||
printpreviewNew(printer, true, -1.0, -1.0, displayPreview);
|
||||
delete printer;
|
||||
return printpreviewNew(printer.get(), true, -1.0, -1.0, displayPreview);
|
||||
}
|
||||
saveUserSettings();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void JKQTBasePlotter::saveImage(const QString& filename, bool displayPreview) {
|
||||
bool JKQTBasePlotter::saveImage(const QString& filename, bool displayPreview) {
|
||||
loadUserSettings();
|
||||
QString fn=filename;
|
||||
QStringList filt;
|
||||
QStringList filterstrings;
|
||||
QList<QStringList> filterextensions;
|
||||
|
||||
const auto findExporterByExtension=[&filterextensions](const QString& ext) {
|
||||
const QString extl=ext.toLower();
|
||||
for (int i=0; i<filterextensions.size(); i++) {
|
||||
if (filterextensions[i].contains(extl)) return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
// add default exporters
|
||||
#ifndef JKQTPLOTTER_COMPILE_WITHOUT_PRINTSUPPORT
|
||||
filt<<tr("Portable Document Format PDF [Qt] (*.pdf)");
|
||||
filt<<tr("Scalable Vector Graphics [Qt] (*.svg)");
|
||||
filterstrings<<tr("Portable Document Format PDF [Qt] (*.pdf)"); filterextensions<<(QStringList()<<"pdf");
|
||||
const int idxDefaultPDF=filterstrings.size()-1;
|
||||
filterstrings<<tr("Scalable Vector Graphics [Qt] (*.svg)"); filterextensions<<(QStringList()<<"svg");
|
||||
const int idxDefaultSVG=filterstrings.size()-1;
|
||||
#endif
|
||||
filt<<tr("PNG Image [Qt] (*.png)");
|
||||
filt<<tr("BMP Image [Qt] (*.bmp)");
|
||||
filt<<tr("TIFF Image [Qt] (*.tif *.tiff)");
|
||||
filt<<tr("JPEG Image [Qt] (*.jpg *.jpeg)");
|
||||
const int filtStartSize=filt.size();
|
||||
filterstrings<<tr("PNG Image [Qt] (*.png)"); filterextensions<<(QStringList()<<"png");
|
||||
filterstrings<<tr("BMP Image [Qt] (*.bmp)"); filterextensions<<(QStringList()<<"bmp");
|
||||
filterstrings<<tr("TIFF Image [Qt] (*.tif *.tiff)"); filterextensions<<(QStringList()<<"tif"<<"tiff");
|
||||
filterstrings<<tr("JPEG Image [Qt] (*.jpg *.jpeg)"); filterextensions<<(QStringList()<<"jpg"<<"jpeg");
|
||||
// add JKQTPPaintDeviceAdapter exporters
|
||||
const int filtersIndexFirstExporterPLugin=filterstrings.size();
|
||||
{
|
||||
JKQTPSynchronized<QList<JKQTPPaintDeviceAdapter*>>::Locker lock(jkqtpPaintDeviceAdapters);
|
||||
for (int i=0; i<jkqtpPaintDeviceAdapters.get().size(); i++) {
|
||||
filt<<jkqtpPaintDeviceAdapters.get()[i]->getFilter();
|
||||
filterstrings<<jkqtpPaintDeviceAdapters.get()[i]->getFilter();
|
||||
filterextensions<<QStringList();
|
||||
for (const auto& ext: jkqtpPaintDeviceAdapters.get()[i]->getFileExtension()) filterextensions.last()<<ext.toLower();
|
||||
}
|
||||
}
|
||||
int qtwritersidx=filt.size();
|
||||
QList<QByteArray> writerformats=QImageWriter::supportedImageFormats();
|
||||
const bool isWithSpecialDeviceAdapter=(filterstrings.size()>filtersIndexFirstExporterPLugin);
|
||||
// add remaining QImageWriter exporters
|
||||
const int filtersIndexFirstQtWriter=filterstrings.size();
|
||||
const QList<QByteArray> writerformats=QImageWriter::supportedImageFormats();
|
||||
for (int i=0; i<writerformats.size(); i++) {
|
||||
filt<<QString("%1 Image (*.%2)").arg(QString(writerformats[i]).toUpper()).arg(QString(writerformats[i].toLower()));
|
||||
const QString ext=writerformats[i].toLower();
|
||||
const int extIdx=findExporterByExtension(ext);
|
||||
const QString name=writerformats[i].toUpper();
|
||||
// only add QtWriters that are not yt contained in the default filters options
|
||||
if (extIdx<0 || extIdx>=filtersIndexFirstExporterPLugin) {
|
||||
filterstrings<<QString("%1 Image (*.%2)").arg(name).arg(ext);
|
||||
filterextensions<<(QStringList()<<ext);
|
||||
}
|
||||
}
|
||||
QString selFormat="";
|
||||
|
||||
QString selFormat;
|
||||
if (fn.isEmpty()) {
|
||||
selFormat=currentFileFormat;
|
||||
fn = QFileDialog::getSaveFileName(nullptr, tr("Save Plot"),
|
||||
currentSaveDirectory,
|
||||
filt.join(";;"), &selFormat);
|
||||
filterstrings.join(";;"), &selFormat);
|
||||
if (!fn.isEmpty()) {
|
||||
currentSaveDirectory=QFileInfo(fn).absolutePath();
|
||||
currentFileFormat=selFormat;
|
||||
}
|
||||
} else {
|
||||
const QString fnExt=QFileInfo(filename).suffix().toLower();
|
||||
const int filtidx=findExporterByExtension(fnExt);
|
||||
if (filtidx>=0) selFormat=filterstrings[filtidx];
|
||||
|
||||
}
|
||||
|
||||
//qDebug()<<"fn="<<fn<<" selFormat="<<selFormat;
|
||||
|
||||
saveUserSettings();
|
||||
if (!fn.isEmpty()) {
|
||||
int filtID=filt.indexOf(selFormat);
|
||||
JKQTPSynchronized<QList<JKQTPPaintDeviceAdapter*>>::Locker lock(jkqtpPaintDeviceAdapters);
|
||||
const QString fnExt=QFileInfo(filename).suffix().toLower();
|
||||
|
||||
bool isWithSpecialDeviceAdapter=filtID>=filtStartSize && filtID<filtStartSize+jkqtpPaintDeviceAdapters.get().size();
|
||||
int adapterID=filtID-filtStartSize;
|
||||
QString e=QFileInfo(filename).suffix().toLower();
|
||||
if (!isWithSpecialDeviceAdapter) {
|
||||
for (int i=0; i<jkqtpPaintDeviceAdapters.get().size(); i++) {
|
||||
if (jkqtpPaintDeviceAdapters.get()[i]->getFileExtension().contains(e)) {
|
||||
adapterID=i;
|
||||
isWithSpecialDeviceAdapter=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const int filtID=[&](){
|
||||
// 1. look for the selected format
|
||||
int idx=filterstrings.indexOf(selFormat);
|
||||
// 2. if not found try to match up the file extension
|
||||
if (idx<0) idx=findExporterByExtension(fnExt);
|
||||
return idx;
|
||||
}();
|
||||
JKQTPSynchronized<QList<JKQTPPaintDeviceAdapter*>>::Locker lock(jkqtpPaintDeviceAdapters);
|
||||
// now we determine whether we selected a jkqtpPaintDeviceAdapters, if not adapterID will be <0
|
||||
const int adapterID=[&](){
|
||||
int idx=filtID-filtersIndexFirstExporterPLugin;
|
||||
if (idx<0) idx=-1;
|
||||
if (idx>=jkqtpPaintDeviceAdapters.get().size()) idx=-1;
|
||||
return idx;
|
||||
}();
|
||||
|
||||
|
||||
if (filtID<0) {
|
||||
qWarning()<<"You tried to save an image to to '"<<fn<<"', but JKQTPlottter did not recognize the file format!";
|
||||
return false;
|
||||
}
|
||||
//qDebug()<<"filtID="<<filtID<<" isWithSpecialDeviceAdapter="<<isWithSpecialDeviceAdapter<<" adapterID="<<adapterID;
|
||||
|
||||
|
||||
#ifndef JKQTPLOTTER_COMPILE_WITHOUT_PRINTSUPPORT
|
||||
if (filtID==0) {
|
||||
saveAsPDF(fn, displayPreview);
|
||||
return;
|
||||
// SVG and PDF need to be treated separately!
|
||||
if (filtID==idxDefaultPDF) {
|
||||
return saveAsPDF(fn, displayPreview);
|
||||
}
|
||||
if (filtID==1) {
|
||||
saveAsSVG(fn, displayPreview);
|
||||
return;
|
||||
if (filtID==idxDefaultSVG) {
|
||||
return saveAsSVG(fn, displayPreview);
|
||||
}
|
||||
#endif
|
||||
if (isWithSpecialDeviceAdapter && adapterID>=0 && adapterID<jkqtpPaintDeviceAdapters.get().size()) {
|
||||
|
||||
// we need to use a jkqtpPaintDeviceAdapters
|
||||
if (adapterID>=0) {
|
||||
QString tempFM="";
|
||||
if (QFile::exists(fn)) {
|
||||
// if the file fn already exists, we make a temporary copy, so it is not destroyed by the export process!
|
||||
#ifdef QFWIDLIB_LIBRARY
|
||||
QFTemporaryFile* tf=new QFTemporaryFile();
|
||||
QSharedPointer<QFTemporaryFile> tf=QSharedPointer<QTemporaryFile>(new QFTemporaryFile());
|
||||
#else
|
||||
QTemporaryFile* tf=new QTemporaryFile();
|
||||
QSharedPointer<QTemporaryFile> tf=QSharedPointer<QTemporaryFile>(new QTemporaryFile());
|
||||
#endif
|
||||
tf->open();
|
||||
tempFM=tf->fileName();
|
||||
tf->close();
|
||||
delete tf;
|
||||
tf.reset();
|
||||
QFile::copy(fn, tempFM);
|
||||
}
|
||||
|
||||
@ -3621,35 +3663,33 @@ void JKQTBasePlotter::saveImage(const QString& filename, bool displayPreview) {
|
||||
emit beforeExporting();; auto __finalpaint=JKQTPFinally([&]() { emit afterExporting();});
|
||||
|
||||
gridPrintingCalc();
|
||||
QPaintDevice* paintDevice=jkqtpPaintDeviceAdapters.get()[adapterID]->createPaintdevice(fn, jkqtp_roundTo<int>(gridPrintingSize.width()), jkqtp_roundTo<int>(gridPrintingSize.height()));
|
||||
QSharedPointer<QPaintDevice> paintDevice=QSharedPointer<QPaintDevice>(jkqtpPaintDeviceAdapters.get()[adapterID]->createPaintdevice(fn, jkqtp_roundTo<int>(gridPrintingSize.width()), jkqtp_roundTo<int>(gridPrintingSize.height())));
|
||||
|
||||
#ifndef JKQTPLOTTER_COMPILE_WITHOUT_PRINTSUPPORT
|
||||
if (!printpreviewNew(paintDevice, jkqtpPaintDeviceAdapters.get()[adapterID]->getSetAbsolutePaperSize(), jkqtpPaintDeviceAdapters.get()[adapterID]->getPrintSizeXInMM(), jkqtpPaintDeviceAdapters.get()[adapterID]->getPrintSizeYInMM(), displayPreview)) {
|
||||
delete paintDevice;
|
||||
|
||||
|
||||
if (!printpreviewNew(paintDevice.get(), jkqtpPaintDeviceAdapters.get()[adapterID]->getSetAbsolutePaperSize(), jkqtpPaintDeviceAdapters.get()[adapterID]->getPrintSizeXInMM(), jkqtpPaintDeviceAdapters.get()[adapterID]->getPrintSizeYInMM(), displayPreview)) {
|
||||
if (QFile::exists(tempFM)) {
|
||||
QFile::copy(tempFM, fn);
|
||||
QFile::remove(tempFM);
|
||||
}
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
return false;
|
||||
} else
|
||||
#endif
|
||||
delete paintDevice;
|
||||
paintDevice=jkqtpPaintDeviceAdapters.get()[adapterID]->createPaintdeviceMM(fn,printSizeX_Millimeter,printSizeY_Millimeter);
|
||||
printpreviewPaintRequestedNewPaintDevice(paintDevice);
|
||||
delete paintDevice;
|
||||
{
|
||||
paintDevice.reset(jkqtpPaintDeviceAdapters.get()[adapterID]->createPaintdeviceMM(fn,printSizeX_Millimeter,printSizeY_Millimeter));
|
||||
printpreviewPaintRequestedNewPaintDevice(paintDevice.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
} else {
|
||||
saveAsPixelImage(fn, displayPreview, writerformats.value(filtID-qtwritersidx, QByteArray()));
|
||||
// here we can let Qt figure out the correct exporter
|
||||
return saveAsPixelImage(fn, displayPreview, writerformats.value(filtID-filtersIndexFirstQtWriter, QByteArray()));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void JKQTBasePlotter::saveAsPixelImage(const QString& filename, bool displayPreview, const QByteArray& outputFormat, const QSize &outputSizeIncrease) {
|
||||
bool JKQTBasePlotter::saveAsPixelImage(const QString& filename, bool displayPreview, const QByteArray& outputFormat, const QSize &outputSizeIncrease) {
|
||||
loadUserSettings();
|
||||
QString fn=filename;
|
||||
QStringList filt;
|
||||
@ -3668,15 +3708,17 @@ void JKQTBasePlotter::saveAsPixelImage(const QString& filename, bool displayPrev
|
||||
|
||||
saveUserSettings();
|
||||
if (!fn.isEmpty()) {
|
||||
int filtID=filt.indexOf(selFormat);
|
||||
const int filtID=filt.indexOf(selFormat);
|
||||
//QString ext=tolower(extract_file_ext(fn.toStdString()));
|
||||
QString form="NONE";
|
||||
if (filtID>=0 && filtID<writerformats.size()) {
|
||||
form=writerformats[filtID];
|
||||
}
|
||||
if (outputFormat.size()>0) {
|
||||
form =outputFormat;
|
||||
}
|
||||
const QString form=[&]()->QString{
|
||||
if (filtID>=0 && filtID<writerformats.size()) {
|
||||
return writerformats[filtID];
|
||||
}
|
||||
if (outputFormat.size()>0) {
|
||||
return outputFormat;
|
||||
}
|
||||
return "NONE";
|
||||
}();
|
||||
|
||||
|
||||
emit beforeExporting();; auto __finalpaint=JKQTPFinally([&]() { emit afterExporting();});
|
||||
@ -3692,26 +3734,29 @@ void JKQTBasePlotter::saveAsPixelImage(const QString& filename, bool displayPrev
|
||||
|
||||
QImage png(QSizeF(double(printSizeX_Millimeter)+outputSizeIncrease.width(), double(printSizeY_Millimeter)+outputSizeIncrease.height()).toSize(), QImage::Format_ARGB32);
|
||||
png.fill(Qt::transparent);
|
||||
JKQTPEnhancedPainter painter;
|
||||
painter.begin(&png);
|
||||
painter.setRenderHint(JKQTPEnhancedPainter::Antialiasing);
|
||||
painter.setRenderHint(JKQTPEnhancedPainter::TextAntialiasing);
|
||||
painter.setRenderHint(JKQTPEnhancedPainter::SmoothPixmapTransform);
|
||||
#if (QT_VERSION<QT_VERSION_CHECK(6, 0, 0))
|
||||
painter.setRenderHint(JKQTPEnhancedPainter::NonCosmeticDefaultPen, true);
|
||||
painter.setRenderHint(JKQTPEnhancedPainter::HighQualityAntialiasing);
|
||||
#endif
|
||||
{
|
||||
JKQTPEnhancedPainter painter;
|
||||
painter.begin(&png);
|
||||
painter.setRenderHint(JKQTPEnhancedPainter::Antialiasing);
|
||||
painter.setRenderHint(JKQTPEnhancedPainter::TextAntialiasing);
|
||||
painter.setRenderHint(JKQTPEnhancedPainter::SmoothPixmapTransform);
|
||||
#if (QT_VERSION<QT_VERSION_CHECK(6, 0, 0))
|
||||
painter.setRenderHint(JKQTPEnhancedPainter::NonCosmeticDefaultPen, true);
|
||||
painter.setRenderHint(JKQTPEnhancedPainter::HighQualityAntialiasing);
|
||||
#endif
|
||||
|
||||
/*calcPlotScaling(painter);
|
||||
gridPaint(painter, png.rect().size());*/\
|
||||
//qDebug()<<QSize(printSizeX_Millimeter, printSizeY_Millimeter);
|
||||
exportpreviewPaintRequested(painter, QSize(jkqtp_roundTo<int>(printSizeX_Millimeter), jkqtp_roundTo<int>(printSizeY_Millimeter)));
|
||||
painter.end();
|
||||
if (form=="NONE") png.save(fn);
|
||||
else png.save(fn, form.toLatin1().data());
|
||||
/*calcPlotScaling(painter);
|
||||
gridPaint(painter, png.rect().size());*/\
|
||||
//qDebug()<<QSize(printSizeX_Millimeter, printSizeY_Millimeter);
|
||||
exportpreviewPaintRequested(painter, QSize(jkqtp_roundTo<int>(printSizeX_Millimeter), jkqtp_roundTo<int>(printSizeY_Millimeter)));
|
||||
painter.end();
|
||||
}
|
||||
if (form=="NONE") return png.save(fn);
|
||||
else return png.save(fn, form.toLatin1().data());
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QImage JKQTBasePlotter::grabPixelImage(QSize size, bool showPreview)
|
||||
@ -3843,7 +3888,8 @@ void JKQTBasePlotter::copyPixelImage(bool showPreview) {
|
||||
}
|
||||
|
||||
#ifndef JKQTPLOTTER_COMPILE_WITHOUT_PRINTSUPPORT
|
||||
void JKQTBasePlotter::saveAsSVG(const QString& filename, bool displayPreview) {
|
||||
bool JKQTBasePlotter::saveAsSVG(const QString& filename, bool displayPreview) {
|
||||
bool printed=false;
|
||||
loadUserSettings();
|
||||
QString fn=filename;
|
||||
if (fn.isEmpty()) {
|
||||
@ -3870,23 +3916,23 @@ void JKQTBasePlotter::saveAsSVG(const QString& filename, bool displayPreview) {
|
||||
|
||||
emit beforeExporting();; auto __finalpaint=JKQTPFinally([&]() { emit afterExporting();});
|
||||
gridPrintingCalc();
|
||||
QSvgGenerator* svg=new QSvgGenerator;
|
||||
std::shared_ptr<QSvgGenerator> svg=std::make_shared<QSvgGenerator>();
|
||||
svg->setResolution(96);
|
||||
QSize size=QSizeF(gridPrintingSize.width()*25.4/svg->resolution(), gridPrintingSize.height()*25.4/svg->resolution()).toSize();
|
||||
svg->setSize(size);
|
||||
svg->setFileName(fn);
|
||||
|
||||
if (!printpreviewNew(svg, true, -1.0, -1.0, displayPreview)) {
|
||||
printed=printpreviewNew(svg.get(), true, -1.0, -1.0, displayPreview);
|
||||
if (!printed) {
|
||||
if (QFile::exists(tempFM)) {
|
||||
QFile::copy(tempFM, fn);
|
||||
QFile::remove(tempFM);
|
||||
}
|
||||
}
|
||||
|
||||
delete svg;
|
||||
|
||||
}
|
||||
saveUserSettings();
|
||||
return printed;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -72,7 +72,9 @@ JKQTPLOTTER_LIB_EXPORT void initJKQTBasePlotterResources();
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPSaveDataAdapter {
|
||||
public:
|
||||
virtual ~JKQTPSaveDataAdapter() ;
|
||||
/** \brief Filter-String for a Qt File-Dialog, e.g. <code>"CSV Files (*.csv)"</code> */
|
||||
virtual QString getFilter() const=0;
|
||||
/** \brief actually save the table \a data into file \a filename . The parameter \a columnNames provides a name for each column */
|
||||
virtual void saveJKQTPData(const QString& filename, const QList<QVector<double> >& data, const QStringList& columnNames) const=0;
|
||||
};
|
||||
|
||||
@ -82,9 +84,13 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPSaveDataAdapter {
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPPaintDeviceAdapter {
|
||||
public:
|
||||
virtual ~JKQTPPaintDeviceAdapter() {}
|
||||
/** \brief Filter-String for a Qt File-Dialog, e.g. <code>"JPEG Files (*.jpg)"</code> */
|
||||
virtual QString getFilter() const=0;
|
||||
/** \brief Human readable name for the format */
|
||||
virtual QString getFormatName() const=0;
|
||||
/** \brief a plugin-ID, i.e. a unique name for this format plugin, e.g. \c MyPluginExport_JPEG */
|
||||
virtual QString getFormatID() const=0;
|
||||
/** \brief returns a list (in lower-case) of the file extensions supported by this plugin, e.g. \c {"jpg","jpeg"} */
|
||||
virtual QStringList getFileExtension() const=0;
|
||||
virtual bool getSetAbsolutePaperSize() const=0;
|
||||
virtual double getPrintSizeXInMM() const =0;
|
||||
@ -1731,8 +1737,9 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
|
||||
* \param displayPreview if \c true a dialog is shown that allows to modify the generated output (zoo, scaling, ...)
|
||||
* \param outputFormmat specify the file format for the generated file
|
||||
* \param outputSizeIncrease if given, the size of the generated pixel image is increased by this number of pixels in addition to the required space
|
||||
* \return returns \c true on success
|
||||
*/
|
||||
void saveAsPixelImage(const QString& filename=QString(""), bool displayPreview=true, const QByteArray &outputFormat=QByteArray(), const QSize& outputSizeIncrease=QSize(0,0));
|
||||
bool saveAsPixelImage(const QString& filename=QString(""), bool displayPreview=true, const QByteArray &outputFormat=QByteArray(), const QSize& outputSizeIncrease=QSize(0,0));
|
||||
|
||||
/** \brief save the current plot as a pixel image into a QImage with the given size */
|
||||
QImage grabPixelImage(QSize size=QSize(), bool showPreview=false);
|
||||
@ -1741,21 +1748,34 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
|
||||
|
||||
#ifndef JKQTPLOTTER_COMPILE_WITHOUT_PRINTSUPPORT
|
||||
/** \brief save the current plot as a SVG file, with the current widget aspect ratio, if filename is empty a file selection dialog is displayed
|
||||
*
|
||||
* \param filename the filename to save to, if empty a file save dialog is displayed
|
||||
* \param displayPreview if \C true, a save/print-preview dialog is displayed that allows to make some modifications to the generated image, otherwise the image is saved with default settings.
|
||||
* \return Returns \c true if the file was save successfully
|
||||
*
|
||||
* \note Exporting to SVG requires QPrinter-support, if it is not available on your platform, this function will not be available either!
|
||||
*/
|
||||
void saveAsSVG(const QString& filename=QString(""), bool displayPreview=true);
|
||||
bool saveAsSVG(const QString& filename=QString(""), bool displayPreview=true);
|
||||
|
||||
/** \brief save the current plot as a PDF file, with the current widget aspect ratio, if filename is empty a file selection dialog is displayed
|
||||
*
|
||||
* \param filename the filename to save to, if empty a file save dialog is displayed
|
||||
* \param displayPreview if \C true, a save/print-preview dialog is displayed that allows to make some modifications to the generated image, otherwise the image is saved with default settings.
|
||||
* \return Returns \c true if the file was save successfully
|
||||
*
|
||||
* \note Exporting to PDF requires QPrinter-support, if it is not available on your platform, this function will not be available either!
|
||||
*/
|
||||
void saveAsPDF(const QString& filename=QString(""), bool displayPreview=true);
|
||||
bool saveAsPDF(const QString& filename=QString(""), bool displayPreview=true);
|
||||
#endif
|
||||
|
||||
/** \brief save the current plot as an image file, with the current widget aspect ratio, if filename is empty a file selection dialog is displayed.
|
||||
* The image format is extracted from the file extension (jpeg, tiff, png, pdf, ...) */
|
||||
void saveImage(const QString& filename=QString(""), bool displayPreview=true);
|
||||
* The image format is extracted from the file extension (jpeg, tiff, png, pdf, ...)
|
||||
*
|
||||
* \param filename the filename to save to, if empty a file save dialog is displayed
|
||||
* \param displayPreview if \C true, a save/print-preview dialog is displayed that allows to make some modifications to the generated image, otherwise the image is saved with default settings.
|
||||
* \return Returns \c true if the file was save successfully
|
||||
*/
|
||||
bool saveImage(const QString& filename=QString(""), bool displayPreview=true);
|
||||
|
||||
/** \brief save the data used for the current plot. The file format is extracted from the file extension (csv, ...)
|
||||
*
|
||||
|
@ -408,19 +408,13 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPlotter: public QWidget {
|
||||
const JKQTBasePlotter* getConstplotter() const { return const_cast<const JKQTBasePlotter*>(plotter); }
|
||||
|
||||
|
||||
/** \brief returns the JKQTPBaseKey object representing the main plot key/legend
|
||||
*
|
||||
* \see JKQTBasePlotter::getMainKey()
|
||||
*/
|
||||
/** \copydoc JKQTBasePlotter::getMainKey() */
|
||||
inline JKQTPBaseKey* getMainKey()
|
||||
{
|
||||
return plotter->getMainKey();
|
||||
}
|
||||
|
||||
/** \brief returns the JKQTPBaseKey object representing the main plot key/legend
|
||||
*
|
||||
* \see JKQTBasePlotter::getMainKey()
|
||||
*/
|
||||
/** \copydoc JKQTBasePlotter::getMainKey() */
|
||||
inline const JKQTPBaseKey* getMainKey() const
|
||||
{
|
||||
return plotter->getMainKey();
|
||||
@ -613,18 +607,13 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPlotter: public QWidget {
|
||||
|
||||
|
||||
|
||||
/** \brief returns a pointer to the datastore used by this object */
|
||||
/** \copydoc JKQTBasePlotter::getDatastore() */
|
||||
inline JKQTPDatastore* getDatastore() { return plotter->getDatastore(); }
|
||||
|
||||
/** \brief returns a pointer to the datastore used by this object */
|
||||
/** \copydoc JKQTBasePlotter::getDatastore() */
|
||||
inline const JKQTPDatastore* getDatastore() const { return plotter->getDatastore(); }
|
||||
|
||||
/** \brief tells the plotter object to use the given external datastore.
|
||||
*
|
||||
* If the current datastore is internally managed, this method will free that object and use the supplied datastore
|
||||
* with external management. If the current datastore is already external, this method will simply replace it by the
|
||||
* new one.
|
||||
*/
|
||||
/** \copydoc JKQTBasePlotter::useExternalDatastore() */
|
||||
inline void useExternalDatastore(JKQTPDatastore* newStore) { plotter->useExternalDatastore(newStore); }
|
||||
|
||||
/** \copydoc JKQTBasePlotter::useAsInternalDatastore() */
|
||||
@ -930,7 +919,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPlotter: public QWidget {
|
||||
public Q_SLOTS:
|
||||
/** \brief set the current plot magnification */
|
||||
void setMagnification(double m);
|
||||
/** \brief sets x/ymin and x/ymax to the supplied values and replots the graph (zoom operation!) */
|
||||
/** \copydoc JKQTBasePlotter::zoom() */
|
||||
inline void zoom(double nxmin, double nxmax, double nymin, double nymax) {
|
||||
plotter->zoom(nxmin, nxmax, nymin, nymax);
|
||||
}
|
||||
@ -991,61 +980,70 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPlotter: public QWidget {
|
||||
plotter->setShowZeroAxes(showXY);
|
||||
}
|
||||
|
||||
/** \brief save the current plot as an image file, with the current widget aspect ratio, if filename is empty a file selection dialog is displayed.
|
||||
* The image format is extracted from the file extension (jpeg, tiff, png, pdf, ...) */
|
||||
inline void saveImage(const QString& filename=QString(""), bool displayPreview=true) {
|
||||
plotter->saveImage(filename, displayPreview);
|
||||
/** \copydoc JKQTBasePlotter::saveImage() */
|
||||
inline bool saveImage(const QString& filename=QString(""), bool displayPreview=true) {
|
||||
return plotter->saveImage(filename, displayPreview);
|
||||
}
|
||||
|
||||
/** \brief save the data used for the current plot. The file format is extracted from the file extension (csv, ...)
|
||||
*
|
||||
* The parameter \a format specifies the export format. if it is empty the format will be choosen according to the file extension, or
|
||||
* if \a filename is also empty the format will be choosen according to what is selected in the file selection dialog.
|
||||
*
|
||||
* If \a format is \c "slk" the output will be in SYLK format, if \a format is \c "csv" or \a "dat" the output will be comma separated values
|
||||
* and if \a format is \c "txt" the output will be tab separated values.
|
||||
*/
|
||||
/** \copydoc JKQTBasePlotter::saveAsPixelImage() */
|
||||
inline bool saveAsPixelImage(const QString& filename=QString(""), bool displayPreview=true, const QByteArray &outputFormat=QByteArray(), const QSize& outputSizeIncrease=QSize(0,0)) {
|
||||
return plotter->saveAsPixelImage(filename, displayPreview, outputFormat, outputSizeIncrease);
|
||||
}
|
||||
|
||||
#ifndef JKQTPLOTTER_COMPILE_WITHOUT_PRINTSUPPORT
|
||||
/** \copydoc JKQTBasePlotter::saveAsSVG() */
|
||||
inline bool saveAsSVG(const QString& filename=QString(""), bool displayPreview=true) { return plotter->saveAsSVG(filename, displayPreview); }
|
||||
/** \copydoc JKQTBasePlotter::saveAsPDF() */
|
||||
inline bool saveAsPDF(const QString& filename=QString(""), bool displayPreview=true) { return plotter->saveAsPDF(filename, displayPreview); }
|
||||
#endif
|
||||
|
||||
/** \copydoc JKQTBasePlotter::saveAsCSV() */
|
||||
inline void saveAsCSV(const QString& filename=QString("")) { plotter->saveAsCSV(filename); }
|
||||
/** \copydoc JKQTBasePlotter::saveAsSemicolonSV() */
|
||||
inline void saveAsSemicolonSV(const QString& filename=QString("")) { plotter->saveAsSemicolonSV(filename); }
|
||||
/** \copydoc JKQTBasePlotter::saveAsTabSV() */
|
||||
inline void saveAsTabSV(const QString& filename=QString("")) { plotter->saveAsTabSV(filename); }
|
||||
/** \copydoc JKQTBasePlotter::saveAsDIF() */
|
||||
inline void saveAsDIF(const QString& filename=QString("")) { plotter->saveAsDIF(filename); }
|
||||
/** \copydoc JKQTBasePlotter::saveAsSYLK() */
|
||||
inline void saveAsSYLK(const QString& filename=QString("")) { plotter->saveAsSYLK(filename); }
|
||||
/** \copydoc JKQTBasePlotter::saveAsMatlab() */
|
||||
inline void saveAsMatlab(const QString& filename=QString("")) { plotter->saveAsMatlab(filename); }
|
||||
/** \copydoc JKQTBasePlotter::saveAsGerExcelCSV() */
|
||||
inline void saveAsGerExcelCSV(const QString& filename=QString("")) { plotter->saveAsGerExcelCSV(filename); }
|
||||
|
||||
|
||||
/** \copydoc JKQTBasePlotter::saveData() */
|
||||
inline void saveData(const QString& filename=QString(""), const QString& format=QString("")) {
|
||||
plotter->saveData(filename, format);
|
||||
}
|
||||
|
||||
#ifndef JKQTPLOTTER_COMPILE_WITHOUT_PRINTSUPPORT
|
||||
/** \brief print the current plot, if printer is \c nullptr a printer selection dialog is displayed */
|
||||
/** \copydoc JKQTBasePlotter::print() */
|
||||
inline void print(QPrinter* printer=nullptr) {
|
||||
plotter->print(printer);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \brief copy displayed data to cpliboard */
|
||||
/** \copydoc JKQTBasePlotter::copyData() */
|
||||
inline void copyData() {
|
||||
plotter->copyData();
|
||||
}
|
||||
|
||||
/** \brief copy displayed data to cpliboard in Matlab syntax */
|
||||
/** \copydoc JKQTBasePlotter::copyDataMatlab() */
|
||||
inline void copyDataMatlab() {
|
||||
plotter->copyDataMatlab();
|
||||
}
|
||||
|
||||
|
||||
/** \brief this method zooms the graph so that all plotted datapoints are visible.
|
||||
*
|
||||
* \param zoomX if set \c true (default) zooms the x axis
|
||||
* \param zoomY if set \c true (default) zooms the y axis
|
||||
* \param includeX0 if this is \c true zoomToFit() will ensure that \f$ x=0 \f$ is visible in the plot (only for non-logx plots, default: false)
|
||||
* \param includeY0 if this is \c true zoomToFit() will ensure that \f$ y=0 \f$ is visible in the plot (only for non-logy plots, default: false)
|
||||
* \param scaleX the plot will have a width of \f$ \mbox{Xscale}\cdot\Delta x \f$ where \f$ \Delta x \f$ is the actual x-axis data range
|
||||
* For logx plots we actually use this on the logarithmized data! (default: 1.05)
|
||||
* \param scaleY the plot will have a height of \f$ \mbox{Yscale}\cdot\Delta < \f$ where \f$ \Delta < \f$ is the actual <-axis data range
|
||||
* For log< plots we actually use this on the logarithmized data! (default: 1.05)
|
||||
*
|
||||
*/
|
||||
/** \copydoc JKQTBasePlotter::zoomToFit() */
|
||||
inline void zoomToFit(bool zoomX=true, bool zoomY=true, bool includeX0=false, bool includeY0=false, double scaleX=1.05, double scaleY=1.05) {
|
||||
plotter->zoomToFit(zoomX, zoomY, includeX0, includeY0, scaleX, scaleY);
|
||||
}
|
||||
|
||||
/** \brief zooms into the graph (the same as turning the mouse wheel) by the given factor */
|
||||
/** \copydoc JKQTBasePlotter::zoomIn() */
|
||||
inline void zoomIn(double factor=2.0) { plotter->zoomIn(factor); }
|
||||
/** \brief zooms out of the graph (the same as turning the mouse wheel) by the given factor */
|
||||
/** \copydoc JKQTBasePlotter::zoomOut() */
|
||||
inline void zoomOut(double factor=2.0) { plotter->zoomOut(factor); }
|
||||
|
||||
/** \brief update the plot and the overlays */
|
||||
@ -1151,95 +1149,22 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPlotter: public QWidget {
|
||||
/** \brief open the standard context menu with the special context menu integrated at the mouse position \a x and \a y \see \ref JKQTPLOTTER_CONTEXTMENU , \ref JKQTPLOTTER_SPECIALCONTEXTMENU, \ref JKQTPLOTTER_USERMOUSEINTERACTION */
|
||||
void openStandardAndSpecialContextMenu(int x, int y);
|
||||
|
||||
/** \brief sets absolutely limiting x-range of the plot
|
||||
*
|
||||
* \param xminn absolute minimum of x-axis
|
||||
* \param xmaxx absolute maximum of x-axis
|
||||
*
|
||||
* \note if the aspect ratio of this does not fit into the widget, it is possible that you don't see the complete contents!
|
||||
*
|
||||
* \see setAbsoluteXY(), setAbsoluteY(), JKQTBasePlotter::setAbsoluteX()
|
||||
*/
|
||||
/** \copydoc JKQTBasePlotter::setAbsoluteX() */
|
||||
inline void setAbsoluteX(double xminn, double xmaxx) { plotter->setAbsoluteX(xminn, xmaxx); }
|
||||
|
||||
/** \brief sets absolute minimum and maximum y-value to plot
|
||||
*
|
||||
* \param yminn absolute minimum of y-axis
|
||||
* \param ymaxx absolute maximum of y-axis
|
||||
*
|
||||
* \note if the aspect ratio of this does not fit into the widget, it is possible that you don't see the complete contents!
|
||||
*
|
||||
* \see setAbsoluteXY(), setAbsoluteX(), JKQTBasePlotter::setAbsoluteY()
|
||||
*/
|
||||
/** \copydoc JKQTBasePlotter::setAbsoluteY() */
|
||||
inline void setAbsoluteY(double yminn, double ymaxx) { plotter->setAbsoluteY(yminn, ymaxx); }
|
||||
|
||||
/** \brief sets absolutely limiting x- and y-range of the plot
|
||||
*
|
||||
* The user (or programmer) cannot zoom to a viewport that is larger than the range given to this function.
|
||||
*
|
||||
* \param xminn absolute minimum of x-axis
|
||||
* \param xmaxx absolute maximum of x-axis
|
||||
* \param yminn absolute minimum of y-axis
|
||||
* \param ymaxx absolute maximum of y-axis
|
||||
*
|
||||
* \note if the aspect ratio of this does not fit into the widget, it is possible that you don't see the complete contents!
|
||||
*
|
||||
* \see setAbsoluteX(), setAbsoluteY(), zoomToFit(), JKQTBasePlotter::setAbsoluteXY()
|
||||
*/
|
||||
/** \copydoc JKQTBasePlotter::setAbsoluteXY() */
|
||||
inline void setAbsoluteXY(double xminn, double xmaxx, double yminn, double ymaxx) { plotter->setAbsoluteXY(xminn, xmaxx, yminn, ymaxx); }
|
||||
|
||||
/** \brief sets the x-range of the plot (minimum and maximum x-value on the x-axis)
|
||||
*
|
||||
* \param xminn absolute minimum of x-axis
|
||||
* \param xmaxx absolute maximum of x-axis
|
||||
*
|
||||
* \note You cannot expand the x-range outside the absolute x-range set e.g. by setAbsoluteX()!
|
||||
* Also the range will be limited to possible values (e.g. to positive values if you use
|
||||
* logarithmic axes).
|
||||
*
|
||||
* Uppon setting, this function emits the signal zoomChangedLocally(), if emitting signals
|
||||
* is activated at the moment (e.g. using JKQTBasePlotter::setEmittingSignalsEnabled() ).
|
||||
*
|
||||
* \see setY(), setXY(), zoomToFit(), setAbsoluteXY(), JKQTBasePlotter::setY()
|
||||
*/
|
||||
/** \copydoc JKQTBasePlotter::setX() */
|
||||
inline void setX(double xminn, double xmaxx) { plotter->setX(xminn, xmaxx); }
|
||||
|
||||
/** \brief sets the y-range of the plot (minimum and maximum y-value on the y-axis)
|
||||
*
|
||||
* \param yminn absolute minimum of y-axis
|
||||
* \param ymaxx absolute maximum of y-axis
|
||||
*
|
||||
* \note You cannot expand the y-range outside the absolute y-range set e.g. by setAbsoluteY()!
|
||||
* Also the range will be limited to possible values (e.g. to positive values if you use
|
||||
* logarithmic axes).
|
||||
*
|
||||
* Uppon setting, this function emits the signal zoomChangedLocally(), if emitting signals
|
||||
* is activated at the moment (e.g. using JKQTBasePlotter::setEmittingSignalsEnabled() ).
|
||||
*
|
||||
* \see setX(), setXY(), zoomToFit(), setAbsoluteXY(), JKQTBasePlotter::setX()
|
||||
*/
|
||||
/** \copydoc JKQTBasePlotter::setY() */
|
||||
inline void setY(double yminn, double ymaxx) { plotter->setY(yminn, ymaxx); }
|
||||
|
||||
/** \brief sets the x- and y-range of the plot (minimum and maximum values on the x-/y-axis)
|
||||
*
|
||||
* \param xminn absolute minimum of x-axis
|
||||
* \param xmaxx absolute maximum of x-axis
|
||||
* \param yminn absolute minimum of y-axis
|
||||
* \param ymaxx absolute maximum of y-axis
|
||||
* \param affectsSecondaryAxes if \c true, the secondary axes are affectedtoo, by using a relative zooming scheme,
|
||||
* i.e. if a major axis range shrinks by 50%, also the secondary ranges shrink by 50%
|
||||
* [default: \c false]
|
||||
*
|
||||
*
|
||||
* \note You cannot expand the ranges outside the absolute ranges set e.g. by setAbsoluteXY()!
|
||||
* Also the range will be limited to possible values (e.g. to positive values if you use
|
||||
* logarithmic axes).
|
||||
*
|
||||
* Uppon setting, this function emits the signal zoomChangedLocally(), if emitting signals
|
||||
* is activated at the moment (e.g. using JKQTBasePlotter::setEmittingSignalsEnabled() ).
|
||||
*
|
||||
* \see setX(), setX(), zoomToFit(), setAbsoluteXY(), JKQTBasePlotter::setXY()
|
||||
*/
|
||||
/** \copydoc JKQTBasePlotter::setXY() */
|
||||
inline void setXY(double xminn, double xmaxx, double yminn, double ymaxx, bool affectsSecondaryAxes=false) { plotter->setXY(xminn, xmaxx, yminn, ymaxx, affectsSecondaryAxes); }
|
||||
Q_SIGNALS:
|
||||
/** \brief emitted whenever the mouse moves
|
||||
|
Loading…
Reference in New Issue
Block a user