diff --git a/doc/dox/whatsnew.dox b/doc/dox/whatsnew.dox
index 9ced50c674..4212ac00a7 100644
--- a/doc/dox/whatsnew.dox
+++ b/doc/dox/whatsnew.dox
@@ -29,8 +29,9 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
BREAKING/REWORKED: Implement better/more access functions to the graphs (inlcuding sorting, moving up/down, appending/prepending, graphs-iterators ...), solves issue #97, thanks to user:sim186 for bringing this up
BREAKING/FIXED: fixed issue #96: JKQTPlotter::saveAsPixelImage() does not add a border around the image any longer (can be reacivated by a new optional function parameter), thanks to user:nmielcarek for reporting
BREAKING/FIXED: JKQTPXFunctionLineGraph and JKQTPYFunctionLineGraph do no longer contribute to auto-scaling, as that depends on the current plot-axes (hen-egg-problem).
- FIXED/BREAKING: graph symbols were not properly applied when reading styles (in fact they were shuffled under some circumstances)
- NEW/BREAKING: rework layouting of keys/legends: new classes JKQTPBaseKey, JKQTPMainKey ... and removed several styling function for the main key from JKQTBasePlotter and JKQTPlotter (these are now accessible via JKQTBasePlotter::getMainKey()
+ BREAKING/FIXED: graph symbols were not properly applied when reading styles (in fact they were shuffled under some circumstances)
+ BREAKING/NEW: rework layouting of keys/legends: new classes JKQTPBaseKey, JKQTPMainKey ... and removed several styling function for the main key from JKQTBasePlotter and JKQTPlotter (these are now accessible via JKQTBasePlotter::getMainKey()
+ BREAKING/DEPRECATED: deprecated JKQTBasePlotter::zoom() and JKQTPlotter::zoom(), use JKQTBasePlotter::setXY() and JKQTPlotter::setXY() instead
FIXED issue described in #62: Fix custom labels draw, because giving exactly two label-strings did not display all of them, thanks to user:FalsinSoft
FIXED issue #70: Typo in jkqtplotter/CMakeLists.txt, thanks to user:tedlinlab
FIXED issue #80: Bug with multiple inheritance with Q_GDAGET with CLANG, thanks to user:igormironchik, caused by QTBUG-104874
@@ -49,6 +50,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
FIXED/IMPROVED issue #100: Add option to disable resize delay feature by setting the delay to zero (thanks to user:fpalazzolo for reporting)
FIXED/NEW: placement of plot-title (was not centerd in its box, but glued to the bottom) by adding a plotstyle parameter JKQTBasePlotterStyle::plotLabelOffset
FIXED/REWORKED issue #111: Can't write to PDF files with JKQTPlotter::saveImage() when passing a filename ending in ".pdf" (thanks to user:fpalazzolo/a> for reporting):
While fixing this issue, the functions JKQTBasePlotter::saveImage() etc. gained a bool return value to indicate whether sacing was successful.
+ REWORKED JKQTBasePlotter::saveData() with a more consistent interface and a bool return value to indicate success or failure + improved documentation, added methods to JKQTPSaveDataAdapter that allow to specify file extensions and an ID for the plugin.
REORGANIZED: separated line-graphs from jkqtpscatter.h/.cpp into jkqtplines.h/.cpp
IMPROVED: QT6-compatibility by removing deprecated warnings
IMPROVED: added missing override declarations
diff --git a/lib/jkqtplotter/jkqtpbaseplotter.cpp b/lib/jkqtplotter/jkqtpbaseplotter.cpp
index 4117b28b2b..807da11f56 100644
--- a/lib/jkqtplotter/jkqtpbaseplotter.cpp
+++ b/lib/jkqtplotter/jkqtpbaseplotter.cpp
@@ -3264,7 +3264,7 @@ void JKQTBasePlotter::copyDataMatlab() {
saveUserSettings();
}
-void JKQTBasePlotter::saveData(const QString& filename, const QString &format) {
+bool JKQTBasePlotter::saveData(const QString& filename, const QString &format) {
loadUserSettings();
QStringList fileformats;
QStringList fileformatIDs;
@@ -3283,20 +3283,27 @@ void JKQTBasePlotter::saveData(const QString& filename, const QString &format) {
fileformats< saveAdapterFileExtensions;
{
JKQTPSynchronized>::Locker lock(jkqtpSaveDataAdapters);
for (int i=0; igetFormatID();
fileformats<getFilter();
- fileformatIDs<getFileExtension();
}
}
QString fn=filename;
- QString fmt=format.toLower();
+ QString fmt=format.toLower().trimmed();
+ if (fmt=="sylk") fmt="slk";
+ else if (fmt=="ssv") fmt="sem";
+
if (fmt.isEmpty()) {
- QString e=QFileInfo(filename).suffix().toLower();// jkqtp_tolower(extract_file_ext(fn.toStdString()));
+ const QString e=QFileInfo(filename).suffix().toLower();
+ fmt=e;
if (e=="csv" || e=="dat") {
fmt="csv";
} else if (e=="txt") {
@@ -3307,6 +3314,16 @@ void JKQTBasePlotter::saveData(const QString& filename, const QString &format) {
fmt="dif";
} else if (e=="m") {
fmt="m";
+ } else if (e=="ssv") {
+ fmt="sem";
+ }
+ if (!fileformatIDs.contains(fmt)) {
+ for (auto it= saveAdapterFileExtensions.begin(); it!=saveAdapterFileExtensions.end(); ++it) {
+ if (it.value().contains(e)) {
+ fmt=it.key();
+ break;
+ }
+ }
}
}
if (fn.isEmpty()) {
@@ -3322,13 +3339,8 @@ void JKQTBasePlotter::saveData(const QString& filename, const QString &format) {
}
//qDebug()<<"after: currentSaveDirectory="<=0) fmt=fileformatIDs[filtIdx] ;
}
saveUserSettings();
@@ -3336,30 +3348,49 @@ void JKQTBasePlotter::saveData(const QString& filename, const QString &format) {
if (fmt=="csv") {
saveAsCSV(fn);
+ return true;
} else if (fmt=="tab") {
saveAsTabSV(fn);
+ return true;
} else if (fmt=="gex") {
saveAsGerExcelCSV(fn);
+ return true;
} else if (fmt=="sem") {
saveAsSemicolonSV(fn);
+ return true;
} else if (fmt=="slk") {
saveAsSYLK(fn);
+ return true;
} else if (fmt=="dif") {
saveAsDIF(fn);
+ return true;
} else if (fmt=="m") {
saveAsMatlab(fn);
- } else if (fmt.startsWith("custom")) {
+ return true;
+ } else if (fmt.startsWith("custom")) { // for backward compatibility!
QString fidx=fmt;
fidx=fidx.remove(0,6);
int idx=fidx.toInt();
JKQTPSynchronized>::Locker lock(jkqtpSaveDataAdapters);
if (idx>=0 && idx > dataset=datastore->getData(&cn);
- jkqtpSaveDataAdapters.get()[idx]->saveJKQTPData(fn, dataset, cn);
+ QStringList columnNames;
+ const QList > dataset=datastore->getData(&columnNames);
+ jkqtpSaveDataAdapters.get()[idx]->saveJKQTPData(fn, dataset, columnNames);
+ return true;
+ }
+ } else {
+ JKQTPSynchronized>::Locker lock(jkqtpSaveDataAdapters);
+ for (int i=0; igetFormatID()) {
+ QStringList columnNames;
+ const QList > dataset=datastore->getData(&columnNames);
+ jkqtpSaveDataAdapters.get()[i]->saveJKQTPData(fn, dataset, columnNames);
+ return true;
+ }
}
}
}
+ return false;
}
void JKQTBasePlotter::saveAsCSV(const QString& filename) {
diff --git a/lib/jkqtplotter/jkqtpbaseplotter.h b/lib/jkqtplotter/jkqtpbaseplotter.h
index 960974751c..f77af7d247 100644
--- a/lib/jkqtplotter/jkqtpbaseplotter.h
+++ b/lib/jkqtplotter/jkqtpbaseplotter.h
@@ -74,6 +74,11 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPSaveDataAdapter {
virtual ~JKQTPSaveDataAdapter() ;
/** \brief Filter-String for a Qt File-Dialog, e.g. "CSV Files (*.csv)"
*/
virtual QString getFilter() const=0;
+ /** \brief a plugin-ID, i.e. a unique name for this format plugin, e.g. \c MyPluginExport_MATLABMAT */
+ virtual QString getFormatID() const=0;
+ /** \brief returns a list (in lower-case) of the file extensions supported by this plugin, e.g. \c {"mat"} */
+ virtual QStringList getFileExtension() 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 >& data, const QStringList& columnNames) const=0;
};
@@ -1823,19 +1828,32 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
/** \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.
+ * \param filename the filename to save to, if empty a file save dialog is displayed
+ * \param format 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.
+ * See below for a listing of supported values.
+ * \returns returns \c true if the data was exported successfully.
*
- * 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.
+ * These values are supported for \a format (if \a format is not provided, the function tries to guess it from the file extensions liste below):
+ * - \c "csv", Comma Separated Values, dot as decimal separator (see also https://en.wikipedia.org/wiki/Comma-separated_values, extensions: \c *.csv , \c *.dat , see JKQTBasePlotter::saveAsCSV()
+ * - \c "tab" Tab Separated Values, dot as decimal separator, extensions: \c *.txt , see JKQTBasePlotter::saveAsTabSV()
+ * - \c "sem" or \c "ssv", Semicolon Separated Values, dot as decimal separator, extensions: \c *.sem , \c *.ssv , see JKQTBasePlotter::saveAsSemicolonSV()
+ * - \c "gex", Semicolon Separated Values for German Excel, i.e. comma as decimal separator, extensions: \c *.gex , see JKQTBasePlotter::saveAsGerExcelCSV()
+ * - \c "slk" or \c "sylk" , SYmbolik LinK (SYLK) spreadsheet (see https://en.wikipedia.org/wiki/Symbolic_Link_(SYLK) ), extensions: \c *.slk , \c *.sylk , see JKQTBasePlotter::saveAsSYLK()
+ * - \c "dif", Data Interchange Format (see https://en.wikipedia.org/wiki/Data_Interchange_Format), extensions: \c *.dif , see JKQTBasePlotter::saveAsDIF()
+ * - \c "m", Matlab Script, extensions: \c *.m , see JKQTBasePlotter::saveAsMatlab()
+ * .
+ *
+ * In addition you can use the custom exporters implemented as JKQTPSaveDataAdapter and registered using JKQTBasePlotter::registerSaveDataAdapter().
+ * For these you need to use \a format = "customN"
, where N is the index of the exporter in the list of registered exporters.
*/
- void saveData(const QString& filename=QString(""), const QString& jkqtp_format=QString(""));
+ bool saveData(const QString& filename=QString(""), const QString& format=QString(""));
/** \brief copy the data used for the current plot to the clipboard
*
* copies data as tab separated data with the system-decimal point.
*/
void copyData();
- /** \brief copy the data used for the current plot to the clipboard in Matlab format
+ /** \brief copy the data used for the current plot to the clipboard as a Matlab script
*/
void copyDataMatlab();
/** \brief save the current plot data as a Comma Separated Values (CSV) file
@@ -1859,30 +1877,40 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
* \param filename the file to save to, if \a filename is empty, a file open dialog will be shown
*
* \note this function uses CSVdecimalSeparator as decimal separator and CSVcommentInitializer to initialize content lines
+ *
+ * \see saveData()
*/
void saveAsTabSV(const QString& filename=QString(""));
/** \brief save the current plot data as a DIF file
*
* \param filename the file to save to, if \a filename is empty, a file open dialog will be shown
+ *
+ * \see saveData()
*/
void saveAsDIF(const QString& filename=QString(""));
/** \brief save the current plot data as a SYLK spreadsheet file
*
* \param filename the file to save to, if \a filename is empty, a file open dialog will be shown
+ *
+ * \see saveData()
*/
void saveAsSYLK(const QString& filename=QString(""));
/** \brief save the current plot data as a Matlab Script
*
* \param filename the file to save to, if \a filename is empty, a file open dialog will be shown
+ *
+ * \see copyDataMatlab(), saveData()
*/
void saveAsMatlab(const QString& filename=QString(""));
/** \brief save the current plot data as a Semicolon Separated Values (CSV) file for german Excel, i.e. with comma as decimal separator
*
* \param filename the file to save to, if \a filename is empty, a file open dialog will be shown
+ *
+ * \see saveData()
*/
void saveAsGerExcelCSV(const QString& filename=QString(""));