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(""));