diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f8421dfe5..e4bb2bfed 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,370 +1,367 @@ find_package(SharedMimeInfo REQUIRED) set(KDE_FRONTEND true) set(KDEFRONTEND_DIR kdefrontend) set(BACKEND_DIR backend) set(COMMONFRONTEND_DIR commonfrontend) set(CANTOR_DIR cantor) set(TOOLS_DIR tools) set(CMAKE_AUTOMOC ON) set(SRC_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE) set(GUI_SOURCES ${KDEFRONTEND_DIR}/GuiObserver.cpp ${KDEFRONTEND_DIR}/GuiTools.cpp ${KDEFRONTEND_DIR}/HistoryDialog.cpp # ${KDEFRONTEND_DIR}/LabPlot.cpp ${KDEFRONTEND_DIR}/MainWin.cpp ${KDEFRONTEND_DIR}/SettingsDialog.cpp ${KDEFRONTEND_DIR}/SettingsGeneralPage.cpp ${KDEFRONTEND_DIR}/SettingsWorksheetPage.cpp ${KDEFRONTEND_DIR}/SettingsPage.h ${KDEFRONTEND_DIR}/TemplateHandler.cpp ${KDEFRONTEND_DIR}/ThemeHandler.cpp ${KDEFRONTEND_DIR}/datasources/AsciiOptionsWidget.cpp ${KDEFRONTEND_DIR}/datasources/BinaryOptionsWidget.cpp ${KDEFRONTEND_DIR}/datasources/DatabaseManagerDialog.cpp ${KDEFRONTEND_DIR}/datasources/DatabaseManagerWidget.cpp ${KDEFRONTEND_DIR}/datasources/HDFOptionsWidget.cpp ${KDEFRONTEND_DIR}/datasources/FileInfoDialog.cpp ${KDEFRONTEND_DIR}/datasources/ImageOptionsWidget.cpp ${KDEFRONTEND_DIR}/datasources/ImportDialog.cpp ${KDEFRONTEND_DIR}/datasources/ImportFileWidget.cpp ${KDEFRONTEND_DIR}/datasources/ImportFileDialog.cpp ${KDEFRONTEND_DIR}/datasources/ImportProjectDialog.cpp ${KDEFRONTEND_DIR}/datasources/ImportSQLDatabaseDialog.cpp ${KDEFRONTEND_DIR}/datasources/ImportSQLDatabaseWidget.cpp ${KDEFRONTEND_DIR}/datasources/NetCDFOptionsWidget.cpp ${KDEFRONTEND_DIR}/datasources/FITSOptionsWidget.cpp ${KDEFRONTEND_DIR}/dockwidgets/AxisDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/NoteDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/CartesianPlotDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/CartesianPlotLegendDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/HistogramDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/BarChartPlotDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/CustomPointDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/ColumnDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/LiveDataDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/MatrixDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/ProjectDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/SpreadsheetDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/XYCurveDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/XYEquationCurveDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/XYDataReductionCurveDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/XYDifferentiationCurveDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/XYIntegrationCurveDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/XYInterpolationCurveDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/XYSmoothCurveDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/XYFitCurveDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/XYFourierFilterCurveDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/XYFourierTransformCurveDock.cpp ${KDEFRONTEND_DIR}/dockwidgets/WorksheetDock.cpp ${KDEFRONTEND_DIR}/matrix/MatrixFunctionDialog.cpp ${KDEFRONTEND_DIR}/spreadsheet/PlotDataDialog.cpp ${KDEFRONTEND_DIR}/spreadsheet/EquidistantValuesDialog.cpp ${KDEFRONTEND_DIR}/spreadsheet/ExportSpreadsheetDialog.cpp ${KDEFRONTEND_DIR}/spreadsheet/DropValuesDialog.cpp ${KDEFRONTEND_DIR}/spreadsheet/FunctionValuesDialog.cpp ${KDEFRONTEND_DIR}/spreadsheet/RandomValuesDialog.cpp ${KDEFRONTEND_DIR}/spreadsheet/SortDialog.cpp ${KDEFRONTEND_DIR}/spreadsheet/StatisticsDialog.cpp ${KDEFRONTEND_DIR}/worksheet/ExportWorksheetDialog.cpp ${KDEFRONTEND_DIR}/worksheet/GridDialog.cpp ${KDEFRONTEND_DIR}/worksheet/DynamicPresenterWidget.cpp ${KDEFRONTEND_DIR}/worksheet/PresenterWidget.cpp ${KDEFRONTEND_DIR}/worksheet/SlidingPanel.cpp ${KDEFRONTEND_DIR}/widgets/ConstantsWidget.cpp ${KDEFRONTEND_DIR}/widgets/ThemesComboBox.cpp ${KDEFRONTEND_DIR}/widgets/ThemesWidget.cpp ${KDEFRONTEND_DIR}/widgets/ExpressionTextEdit.cpp ${KDEFRONTEND_DIR}/widgets/FitOptionsWidget.cpp ${KDEFRONTEND_DIR}/widgets/FitParametersWidget.cpp ${KDEFRONTEND_DIR}/widgets/FunctionsWidget.cpp ${KDEFRONTEND_DIR}/widgets/LabelWidget.cpp ${KDEFRONTEND_DIR}/widgets/DatapickerImageWidget.cpp ${KDEFRONTEND_DIR}/widgets/DatapickerCurveWidget.cpp ${KDEFRONTEND_DIR}/widgets/FITSHeaderEditWidget.cpp ${KDEFRONTEND_DIR}/widgets/FITSHeaderEditNewKeywordDialog.cpp ${KDEFRONTEND_DIR}/widgets/FITSHeaderEditAddUnitDialog.cpp ${KDEFRONTEND_DIR}/widgets/FITSHeaderEditDialog.cpp ) -IF (USE_LIBORIGIN) - LIST(APPEND GUI_SOURCES ${KDEFRONTEND_DIR}/datasources/ImportOpj.cpp) -ENDIF () set(UI_SOURCES ${KDEFRONTEND_DIR}/ui/constantswidget.ui ${KDEFRONTEND_DIR}/ui/functionswidget.ui ${KDEFRONTEND_DIR}/ui/fitoptionswidget.ui ${KDEFRONTEND_DIR}/ui/fitparameterswidget.ui ${KDEFRONTEND_DIR}/ui/labelwidget.ui ${KDEFRONTEND_DIR}/ui/settingsgeneralpage.ui ${KDEFRONTEND_DIR}/ui/settingsworksheetpage.ui ${KDEFRONTEND_DIR}/ui/settingsprintingpage.ui ${KDEFRONTEND_DIR}/ui/datasources/asciioptionswidget.ui ${KDEFRONTEND_DIR}/ui/datasources/binaryoptionswidget.ui ${KDEFRONTEND_DIR}/ui/datasources/databasemanagerwidget.ui ${KDEFRONTEND_DIR}/ui/datasources/hdfoptionswidget.ui ${KDEFRONTEND_DIR}/ui/datasources/imageoptionswidget.ui ${KDEFRONTEND_DIR}/ui/datasources/importfilewidget.ui ${KDEFRONTEND_DIR}/ui/datasources/importprojectwidget.ui ${KDEFRONTEND_DIR}/ui/datasources/importsqldatabasewidget.ui ${KDEFRONTEND_DIR}/ui/datasources/netcdfoptionswidget.ui ${KDEFRONTEND_DIR}/ui/datasources/fitsoptionswidget.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/axisdock.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/cartesianplotdock.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/cartesianplotlegenddock.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/histogramdock.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/histogramdockgeneraltab.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/barchartplotdock.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/columndock.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/custompointdock.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/livedatadock.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/notedock.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/matrixdock.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/projectdock.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/spreadsheetdock.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/xycurvedock.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/xycurvedockgeneraltab.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/xydatareductioncurvedockgeneraltab.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/xydifferentiationcurvedockgeneraltab.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/xyintegrationcurvedockgeneraltab.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/xyinterpolationcurvedockgeneraltab.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/xysmoothcurvedockgeneraltab.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/xyfitcurvedockgeneraltab.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/xyfourierfiltercurvedockgeneraltab.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/xyfouriertransformcurvedockgeneraltab.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/xyequationcurvedockgeneraltab.ui ${KDEFRONTEND_DIR}/ui/dockwidgets/worksheetdock.ui ${KDEFRONTEND_DIR}/ui/matrix/matrixfunctionwidget.ui ${KDEFRONTEND_DIR}/ui/spreadsheet/plotdatawidget.ui ${KDEFRONTEND_DIR}/ui/spreadsheet/equidistantvalueswidget.ui ${KDEFRONTEND_DIR}/ui/spreadsheet/exportspreadsheetwidget.ui ${KDEFRONTEND_DIR}/ui/spreadsheet/dropvalueswidget.ui ${KDEFRONTEND_DIR}/ui/spreadsheet/functionvalueswidget.ui ${KDEFRONTEND_DIR}/ui/spreadsheet/randomvalueswidget.ui ${KDEFRONTEND_DIR}/ui/worksheet/exportworksheetwidget.ui ${KDEFRONTEND_DIR}/ui/datapickerimagewidget.ui ${KDEFRONTEND_DIR}/ui/datapickercurvewidget.ui ${KDEFRONTEND_DIR}/ui/fitsheadereditwidget.ui ${KDEFRONTEND_DIR}/ui/fitsheadereditnewkeywordwidget.ui ${KDEFRONTEND_DIR}/ui/fitsheadereditaddunitwidget.ui ) set(BACKEND_SOURCES ${BACKEND_DIR}/core/Folder.cpp ${BACKEND_DIR}/core/AbstractAspect.cpp ${BACKEND_DIR}/core/AbstractColumn.cpp ${BACKEND_DIR}/core/AbstractColumnPrivate.cpp ${BACKEND_DIR}/core/abstractcolumncommands.cpp ${BACKEND_DIR}/core/AbstractFilter.cpp ${BACKEND_DIR}/core/AbstractSimpleFilter.cpp ${BACKEND_DIR}/core/column/Column.cpp ${BACKEND_DIR}/core/column/ColumnPrivate.cpp ${BACKEND_DIR}/core/column/ColumnStringIO.cpp ${BACKEND_DIR}/core/column/columncommands.cpp ${BACKEND_DIR}/core/AbstractScriptingEngine.cpp ${BACKEND_DIR}/core/AbstractScript.cpp ${BACKEND_DIR}/core/ScriptingEngineManager.cpp ${BACKEND_DIR}/core/Project.cpp ${BACKEND_DIR}/core/AbstractPart.cpp ${BACKEND_DIR}/core/Workbook.cpp ${BACKEND_DIR}/core/AspectTreeModel.cpp ${BACKEND_DIR}/core/datatypes/SimpleCopyThroughFilter.h ${BACKEND_DIR}/core/datatypes/Double2DateTimeFilter.h ${BACKEND_DIR}/core/datatypes/Double2DayOfWeekFilter.h ${BACKEND_DIR}/core/datatypes/Double2IntegerFilter.h ${BACKEND_DIR}/core/datatypes/Double2MonthFilter.h ${BACKEND_DIR}/core/datatypes/Double2StringFilter.cpp ${BACKEND_DIR}/core/datatypes/Integer2DateTimeFilter.h ${BACKEND_DIR}/core/datatypes/Integer2DayOfWeekFilter.h ${BACKEND_DIR}/core/datatypes/Integer2DoubleFilter.h ${BACKEND_DIR}/core/datatypes/Integer2MonthFilter.h ${BACKEND_DIR}/core/datatypes/Integer2StringFilter.h ${BACKEND_DIR}/core/datatypes/String2DayOfWeekFilter.h ${BACKEND_DIR}/core/datatypes/String2DoubleFilter.h ${BACKEND_DIR}/core/datatypes/String2IntegerFilter.h ${BACKEND_DIR}/core/datatypes/String2MonthFilter.h ${BACKEND_DIR}/core/datatypes/String2DateTimeFilter.cpp ${BACKEND_DIR}/core/datatypes/DateTime2DoubleFilter.h ${BACKEND_DIR}/core/datatypes/DateTime2IntegerFilter.h ${BACKEND_DIR}/core/datatypes/DateTime2StringFilter.cpp ${BACKEND_DIR}/core/datatypes/Month2DoubleFilter.h ${BACKEND_DIR}/core/datatypes/Month2IntegerFilter.h ${BACKEND_DIR}/core/datatypes/DayOfWeek2DoubleFilter.h ${BACKEND_DIR}/core/datatypes/DayOfWeek2IntegerFilter.h ${BACKEND_DIR}/core/plugin/PluginLoader.cpp ${BACKEND_DIR}/core/plugin/PluginManager.cpp ${BACKEND_DIR}/datasources/AbstractDataSource.cpp ${BACKEND_DIR}/datasources/LiveDataSource.cpp ${BACKEND_DIR}/datasources/filters/AbstractFileFilter.cpp ${BACKEND_DIR}/datasources/filters/AsciiFilter.cpp ${BACKEND_DIR}/datasources/filters/BinaryFilter.cpp ${BACKEND_DIR}/datasources/filters/HDFFilter.cpp ${BACKEND_DIR}/datasources/filters/ImageFilter.cpp ${BACKEND_DIR}/datasources/filters/NetCDFFilter.cpp ${BACKEND_DIR}/datasources/filters/FITSFilter.cpp ${BACKEND_DIR}/datasources/projects/ProjectParser.cpp ${BACKEND_DIR}/datasources/projects/LabPlotProjectParser.cpp ${BACKEND_DIR}/datasources/projects/OriginProjectParser.cpp ${BACKEND_DIR}/gsl/ExpressionParser.cpp ${BACKEND_DIR}/matrix/Matrix.cpp ${BACKEND_DIR}/matrix/matrixcommands.cpp ${BACKEND_DIR}/matrix/MatrixModel.cpp ${BACKEND_DIR}/nsl/nsl_dft.c ${BACKEND_DIR}/nsl/nsl_diff.c ${BACKEND_DIR}/nsl/nsl_filter.c ${BACKEND_DIR}/nsl/nsl_fit.c ${BACKEND_DIR}/nsl/nsl_geom.c ${BACKEND_DIR}/nsl/nsl_geom_linesim.c ${BACKEND_DIR}/nsl/nsl_int.c ${BACKEND_DIR}/nsl/nsl_interp.c ${BACKEND_DIR}/nsl/nsl_sf_kernel.c ${BACKEND_DIR}/nsl/nsl_sf_poly.c ${BACKEND_DIR}/nsl/nsl_sf_stats.c ${BACKEND_DIR}/nsl/nsl_sf_window.c ${BACKEND_DIR}/nsl/nsl_smooth.c ${BACKEND_DIR}/nsl/nsl_sort.c ${BACKEND_DIR}/nsl/nsl_stats.c ${BACKEND_DIR}/spreadsheet/Spreadsheet.cpp ${BACKEND_DIR}/spreadsheet/SpreadsheetModel.cpp ${BACKEND_DIR}/lib/XmlStreamReader.cpp ${BACKEND_DIR}/note/Note.cpp ${BACKEND_DIR}/worksheet/WorksheetElement.cpp ${BACKEND_DIR}/worksheet/TextLabel.cpp ${BACKEND_DIR}/worksheet/Worksheet.cpp ${BACKEND_DIR}/worksheet/WorksheetElementContainer.cpp ${BACKEND_DIR}/worksheet/WorksheetElementGroup.cpp ${BACKEND_DIR}/worksheet/plots/AbstractPlot.cpp ${BACKEND_DIR}/worksheet/plots/AbstractCoordinateSystem.cpp ${BACKEND_DIR}/worksheet/plots/PlotArea.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/Axis.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/CartesianCoordinateSystem.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/CartesianPlot.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/CartesianPlotLegend.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/Histogram.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/BarChartPlot.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/CustomPoint.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/Symbol.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/XYAnalysisCurve.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/XYCurve.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/XYEquationCurve.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/XYDataReductionCurve.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/XYDifferentiationCurve.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/XYIntegrationCurve.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/XYInterpolationCurve.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/XYSmoothCurve.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/XYFitCurve.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/XYFourierFilterCurve.cpp ${BACKEND_DIR}/worksheet/plots/cartesian/XYFourierTransformCurve.cpp ${BACKEND_DIR}/lib/SignallingUndoCommand.cpp ${BACKEND_DIR}/datapicker/DatapickerPoint.cpp ${BACKEND_DIR}/datapicker/DatapickerImage.cpp ${BACKEND_DIR}/datapicker/Datapicker.cpp ${BACKEND_DIR}/datapicker/Transform.cpp ${BACKEND_DIR}/datapicker/ImageEditor.cpp ${BACKEND_DIR}/datapicker/Segment.cpp ${BACKEND_DIR}/datapicker/Segments.cpp ${BACKEND_DIR}/datapicker/DatapickerCurve.cpp ) set(COMMONFRONTEND_SOURCES ${COMMONFRONTEND_DIR}/matrix/MatrixView.cpp ${COMMONFRONTEND_DIR}/note/NoteView.cpp ${COMMONFRONTEND_DIR}/spreadsheet/SpreadsheetCommentsHeaderModel.cpp ${COMMONFRONTEND_DIR}/spreadsheet/SpreadsheetHeaderView.cpp ${COMMONFRONTEND_DIR}/spreadsheet/SpreadsheetItemDelegate.cpp ${COMMONFRONTEND_DIR}/spreadsheet/SpreadsheetView.cpp ${COMMONFRONTEND_DIR}/workbook/WorkbookView.cpp ${COMMONFRONTEND_DIR}/worksheet/WorksheetView.cpp ${COMMONFRONTEND_DIR}/ProjectExplorer.cpp ${COMMONFRONTEND_DIR}/core/PartMdiView.cpp ${COMMONFRONTEND_DIR}/widgets/TreeViewComboBox.cpp ${COMMONFRONTEND_DIR}/widgets/qxtspanslider.cpp ${COMMONFRONTEND_DIR}/datapicker/DatapickerView.cpp ${COMMONFRONTEND_DIR}/datapicker/DatapickerImageView.cpp ) IF (${CANTOR_LIBS_FOUND}) set(CANTOR_SOURCES ${KDEFRONTEND_DIR}/dockwidgets/CantorWorksheetDock.cpp ${BACKEND_DIR}/cantorWorksheet/VariableParser.cpp ${BACKEND_DIR}/cantorWorksheet/CantorWorksheet.cpp ${COMMONFRONTEND_DIR}/cantorWorksheet/CantorWorksheetView.cpp ) set(CANTOR_UI_SOURCES ${KDEFRONTEND_DIR}/ui/dockwidgets/cantorworksheetdock.ui) set(UI_SOURCES ${UI_SOURCES} ${CANTOR_UI_SOURCES}) ELSE (${CANTOR_LIBS_FOUND}) set(CANTOR_SOURCES "") ENDIF (${CANTOR_LIBS_FOUND}) set(TOOLS_SOURCES ${TOOLS_DIR}/EquationHighlighter.cpp ${TOOLS_DIR}/ImageTools.cpp ${TOOLS_DIR}/TeXRenderer.cpp ) bison_target(GslParser ${BACKEND_DIR}/gsl/parser.y ${CMAKE_CURRENT_BINARY_DIR}/gsl_parser.c ) set(GENERATED_SOURCES ${BISON_GslParser_OUTPUTS} ) add_subdirectory( pics ) add_subdirectory( pics/gsl_distributions ) add_subdirectory( pics/fit_models ) add_subdirectory( pics/colorchooser ) add_subdirectory( themes ) ############################################################################## INCLUDE_DIRECTORIES( . ${BACKEND_DIR}/gsl ${GSL_INCLUDE_DIR} ${GSL_INCLUDEDIR}/.. ) set( LABPLOT_SRCS ${GUI_SOURCES} ) ki18n_wrap_ui( LABPLOT_SRCS ${UI_SOURCES} ) # static library add_library( labplot2lib STATIC ${LABPLOT_SRCS} ${BACKEND_SOURCES} ${CANTOR_SOURCES} ${DATASOURCES_SOURCES} ${COMMONFRONTEND_SOURCES} ${TOOLS_SOURCES} ${GENERATED_SOURCES} ${QTMOC_HDRS} ) # set_property(TARGET ${objlib} PROPERTY POSITION_INDEPENDENT_CODE 1) target_link_libraries( labplot2lib KF5::KDELibs4Support KF5::Archive KF5::XmlGui Qt5::Svg Qt5::Core ${GSL_LIBRARIES} ${GSL_CBLAS_LIBRARIES} ${QT_QTSQL_LIBRARIES} ) IF (Qt5SerialPort_FOUND) target_link_libraries( labplot2lib Qt5::SerialPort ) ENDIF () IF (KF5SyntaxHighlighting_FOUND) target_link_libraries( labplot2lib KF5::SyntaxHighlighting ) ENDIF () #TODO: KF5::NewStuff IF (CANTOR_LIBS_FOUND) target_link_libraries( labplot2lib ${CANTOR_LIBS} ) ENDIF () IF (HDF5_FOUND) target_link_libraries( labplot2lib ${HDF5_C_LIBRARIES} ) ENDIF () IF (FFTW_FOUND) target_link_libraries( labplot2lib ${FFTW_LIBRARIES} ) ENDIF () IF (NETCDF_FOUND) target_link_libraries( labplot2lib ${NETCDF_LIBRARY} ) ENDIF () IF (CFITSIO_FOUND) target_link_libraries( labplot2lib ${CFITSIO_LIBRARY} ) ENDIF () IF (USE_LIBORIGIN) target_link_libraries( labplot2lib liborigin-static ) ENDIF () # main executable add_executable( labplot2 ${KDEFRONTEND_DIR}/LabPlot.cpp ) target_link_libraries( labplot2 labplot2lib ) ############## installation ################################ install( TARGETS labplot2 DESTINATION ${INSTALL_TARGETS_DEFAULT_ARGS} ) install( FILES ${KDEFRONTEND_DIR}/labplot2ui.rc DESTINATION ${KXMLGUI_INSTALL_DIR}/${PROJECT_NAME} ) install( FILES ${KDEFRONTEND_DIR}/labplot2ui.rc ${KDEFRONTEND_DIR}/splash.png ${KDEFRONTEND_DIR}/labplot2.ico DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME} ) install( PROGRAMS org.kde.labplot2.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} ) install( FILES labplot2.xml DESTINATION ${XDG_MIME_INSTALL_DIR} ) install( FILES labplot2_themes.knsrc DESTINATION ${CONFIG_INSTALL_DIR} ) update_xdg_mimetypes( ${XDG_MIME_INSTALL_DIR} ) diff --git a/src/backend/datasources/projects/OriginProjectParser.cpp b/src/backend/datasources/projects/OriginProjectParser.cpp index 3a6886e0f..1af33d1fd 100644 --- a/src/backend/datasources/projects/OriginProjectParser.cpp +++ b/src/backend/datasources/projects/OriginProjectParser.cpp @@ -1,921 +1,919 @@ /*************************************************************************** File : OriginProjectParser.h Project : LabPlot Description : parser for Origin projects -------------------------------------------------------------------- Copyright : (C) 2017 Alexander Semke (alexander.semke@web.de) Copyright : (C) 2017 Stefan Gerlach (stefan.gerlach@uni.kn) ***************************************************************************/ /*************************************************************************** * * * 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 "backend/datasources/projects/OriginProjectParser.h" #include "backend/core/Project.h" #include "backend/core/AspectTreeModel.h" // #include "kdefrontend/datasources/ImportOpj.h" #include "backend/core/Workbook.h" #include "backend/spreadsheet/Spreadsheet.h" #include "backend/matrix/Matrix.h" #include "backend/note/Note.h" #include "backend/worksheet/Worksheet.h" #include "backend/core/column/Column.h" #include "backend/worksheet/plots/cartesian/CartesianPlot.h" #include "backend/worksheet/plots/cartesian/CartesianPlotLegend.h" #include "backend/worksheet/TextLabel.h" #include "backend/core/datatypes/Double2StringFilter.h" #include "backend/core/datatypes/DateTime2StringFilter.h" #include #include /*! \class OriginProjectParser \brief parser for Origin projects. \ingroup datasources */ OriginProjectParser::OriginProjectParser() : ProjectParser(), m_originFile(nullptr), m_excelIndex(0), m_matrixIndex(0), m_graphIndex(0), m_noteIndex(0) { m_topLevelClasses << "Folder" << "Workbook" << "Spreadsheet" << "Matrix" << "Worksheet"; } QAbstractItemModel* OriginProjectParser::model() { WAIT_CURSOR; if (m_project == nullptr) m_project = new Project(); AspectTreeModel* model = nullptr; bool rc = load(m_project, true); if (rc) { model = new AspectTreeModel(m_project); model->setReadOnly(true); } RESET_CURSOR; return model; } void OriginProjectParser::importTo(Folder* folder, const QStringList& selectedPathes) { QDEBUG("Starting the import of " + m_projectFileName); //import the selected objects into a temporary project Project* project = new Project(); project->setPathesToLoad(selectedPathes); load(project, false); //move all children from the temp project to the target folder for (auto* child : project->children()) { project->removeChild(child); folder->addChild(child); } delete project; QDEBUG("Import of " + m_projectFileName + " done."); } //############################################################################## //############## Deserialization from Origin's project tree #################### //############################################################################## bool OriginProjectParser::load(Project* project, bool preview) { //read and parse the m_originFile-file if (m_originFile) delete m_originFile; m_originFile = new OriginFile((const char*)m_projectFileName.toLocal8Bit()); if (!m_originFile->parse()) { return false; } //Origin project tree and the iterator pointing to the root node const tree* projectTree = m_originFile->project(); tree::iterator projectIt = projectTree->begin(projectTree->begin()); //reset the object indices m_excelIndex = 0; m_matrixIndex = 0; m_graphIndex = 0; m_noteIndex = 0; //convert the project tree from liborigin's representation to LabPlot's project object QString name(projectIt->name.c_str()); project->setName(name); project->setCreationTime(creationTime(projectIt)); loadFolder(project, projectIt, preview); return true; } bool OriginProjectParser::loadFolder(Folder* folder, const tree::iterator& baseIt, bool preview) { const tree* projectTree = m_originFile->project(); //load folder's children: logic for reading the selected objects only is similar to Folder::readChildAspectElement for (tree::sibling_iterator it = projectTree->begin(baseIt); it != projectTree->end(baseIt); ++it) { QString name(it->name.c_str()); //name of the current child //check whether we need to skip the loading of the current child if (!folder->pathesToLoad().isEmpty()) { //child's path is not available yet (child not added yet) -> construct the path manually const QString childPath = folder->path() + '/' + name; //skip the current child aspect it is not in the list of aspects to be loaded if (folder->pathesToLoad().indexOf(childPath) == -1) { //increase the index for the skipped child switch(it->type) { case Origin::ProjectNode::Excel: ++m_excelIndex; break; case Origin::ProjectNode::Matrix: ++m_matrixIndex; break; case Origin::ProjectNode::Graph: ++m_graphIndex; break; case Origin::ProjectNode::Note: ++m_noteIndex; break; case Origin::ProjectNode::SpreadSheet: case Origin::ProjectNode::Graph3D: case Origin::ProjectNode::Folder: default: break; } continue; } } //load top-level children AbstractAspect* aspect = nullptr; switch (it->type) { case Origin::ProjectNode::Folder: { Folder* f = new Folder(name); if (!folder->pathesToLoad().isEmpty()) { //a child folder to be read -> provide the list of aspects to be loaded to the child folder, too. //since the child folder and all its children are not added yet (path() returns empty string), //we need to remove the path of the current child folder from the full pathes provided in pathesToLoad. //E.g. we want to import the path "Project/Folder/Spreadsheet" in the following project // Project // \Spreadsheet // \Folder // \Spreadsheet // //Here, we remove the part "Project/Folder/" and proceed for this child folder with "Spreadsheet" only. //With this the logic above where it is determined whether to import the child aspect or not works out. //manually construct the path of the child folder to be read const QString& curFolderPath = folder->path() + '/' + name; //remove the path of the current child folder QStringList pathesToLoadNew; for (auto path : folder->pathesToLoad()) { if (path.startsWith(curFolderPath)) pathesToLoadNew << path.right(path.length() - curFolderPath.length()); } f->setPathesToLoad(pathesToLoadNew); } loadFolder(f, it, preview); aspect = f; break; } case Origin::ProjectNode::SpreadSheet: { Spreadsheet* spreadsheet = new Spreadsheet(0, name); loadSpreadsheet(spreadsheet, preview); aspect = spreadsheet; break; } case Origin::ProjectNode::Graph: { Worksheet* worksheet = new Worksheet(0, name); loadWorksheet(worksheet, preview); aspect = worksheet; ++m_graphIndex; break; } case Origin::ProjectNode::Matrix: { const Origin::Matrix& matrix = m_originFile->matrix(m_matrixIndex); if (matrix.sheets.size() == 1) { // single sheet -> load into a matrix Matrix* matrix = new Matrix(0, name); loadMatrix(matrix, preview); aspect = matrix; } else { // multiple sheets -> load into a workbook Workbook* workbook = new Workbook(0, name); loadMatrixWorkbook(workbook, preview); aspect = workbook; } ++m_matrixIndex; break; } case Origin::ProjectNode::Excel: { const Origin::Excel& excel = m_originFile->excel(m_excelIndex); if (excel.sheets.size() == 1) { // single sheet -> load into a spreadsheet Spreadsheet* spreadsheet = new Spreadsheet(0, name); loadSpreadsheet(spreadsheet, preview); aspect = spreadsheet; } else { // multiple sheets -> load into a workbook Workbook* workbook = new Workbook(0, name); loadWorkbook(workbook, preview); aspect = workbook; } ++m_excelIndex; break; } case Origin::ProjectNode::Note: { Note* note = new Note(name); loadNote(note, preview); aspect = note; ++m_noteIndex; break; } case Origin::ProjectNode::Graph3D: default: //TODO: add UnsupportedAspect break; } if (aspect) { folder->addChildFast(aspect); aspect->setCreationTime(creationTime(it)); } } return folder; } bool OriginProjectParser::loadWorkbook(Workbook* workbook, bool preview) { //load workbook sheets const Origin::Excel excel = m_originFile->excel(m_excelIndex); for (unsigned int s = 0; s < excel.sheets.size(); ++s) { Spreadsheet* spreadsheet = new Spreadsheet(0, excel.sheets[s].name.c_str()); loadSpreadsheet(spreadsheet, preview, s); workbook->addChildFast(spreadsheet); } return true; } -bool OriginProjectParser::loadSpreadsheet(Spreadsheet* spreadsheet, bool preview, int sheetIndex) { +bool OriginProjectParser::loadSpreadsheet(Spreadsheet* spreadsheet, bool preview, size_t sheetIndex) { if (preview) return true; DEBUG("loadSpreadsheet() excelIndex/sheetIndex = " << m_excelIndex << ' ' << sheetIndex); //load spreadsheet data const Origin::Excel excel = m_originFile->excel(m_excelIndex); Origin::SpreadSheet spread = excel.sheets[sheetIndex]; // or m_originFile->spread(sheetIndex) ? - const int cols = spread.columns.size(); + const size_t cols = spread.columns.size(); int rows = 0; // or = excel.maxRows; - for (int j = 0; j < cols; ++j) + for (size_t j = 0; j < cols; ++j) rows = std::max((int)spread.columns[j].data.size(), rows); DEBUG("loadSpreadsheet() cols/maxRows = " << cols << "/" << rows); - if (rows < 0 || cols < 0) + if (rows < 0 || (int)cols < 0) return false; //TODO QLocale locale = mw->locale(); spreadsheet->setRowCount(rows); spreadsheet->setColumnCount(cols); const int scaling_factor = 10; //in Origin width is measured in characters while here in pixels --- need to be accurate - for (int j = 0; j < cols; ++j) { + for (size_t j = 0; j < cols; ++j) { Origin::SpreadColumn column = spread.columns[j]; - Column *col = spreadsheet->column(j); + Column *col = spreadsheet->column((int)j); QString name(column.name.c_str()); col->setName(name.replace(QRegExp(".*_"),"")); //TODO: we don't support any formulas for cells yet. // if (column.command.size() > 0) // col->setFormula(Interval(0, rows), QString(column.command.c_str())); col->setComment(QString(column.comment.c_str())); col->setWidth((int)column.width * scaling_factor); //plot designation switch (column.type) { case Origin::SpreadColumn::X: col->setPlotDesignation(AbstractColumn::X); break; case Origin::SpreadColumn::Y: col->setPlotDesignation(AbstractColumn::Y); break; case Origin::SpreadColumn::Z: col->setPlotDesignation(AbstractColumn::Z); break; case Origin::SpreadColumn::XErr: col->setPlotDesignation(AbstractColumn::XError); break; case Origin::SpreadColumn::YErr: col->setPlotDesignation(AbstractColumn::YError); break; case Origin::SpreadColumn::Label: case Origin::SpreadColumn::NONE: default: col->setPlotDesignation(AbstractColumn::NoDesignation); } QString format; switch(column.valueType) { case Origin::Numeric: case Origin::TextNumeric: { /* TODO: check this A TextNumeric column in Origin is a column whose filled cells contain either a double or a string. Here there is no equivalent column type. Set the column type as 'Numeric' or 'Text' depending on the type of first element in column. IDEA: Add a "per column" flag, settable at import dialog, to choose between both types. */ double datavalue; bool setAsText = false; col->setColumnMode(AbstractColumn::Numeric); //printf("column has %ld rows\n", column.data.size()); for (int i = 0; i < std::min((int)column.data.size(), rows); ++i) { Origin::variant v(column.data.at(i)); //printf("i=%d type = %d\n", i, v.type); if (v.type() == Origin::Variant::V_DOUBLE) { //printf("DOUBLE !\n"); datavalue = v.as_double(); //printf("datavalue = %g\n", datavalue); if (datavalue == _ONAN) continue; // mark for empty cell if (!setAsText) col->setValueAt(i, datavalue); //TODO else // convert double to string for Text columns // col->setTextAt(i, locale.toString(datavalue, 'g', 16)); } else if (v.type() == Origin::Variant::V_STRING) { // string //printf("STRING !\n"); if (!setAsText && i == 0) { col->setColumnMode(AbstractColumn::Text); setAsText = true; } col->setTextAt(i, v.as_string()); } else { printf("ERROR: data type = %d unknown!\n", v.type()); } } if (column.numericDisplayType != 0) { int f = 0; switch(column.valueTypeSpecification) { case Origin::Decimal: f=1; break; case Origin::Scientific: f=2; break; case Origin::Engineering: case Origin::DecimalWithMarks: break; } Double2StringFilter *filter = static_cast(col->outputFilter()); filter->setNumericFormat(f); filter->setNumDigits(column.decimalPlaces); } break; } case Origin::Text: col->setColumnMode(AbstractColumn::Text); for (int i = 0; i < min((int)column.data.size(), rows); ++i) col->setTextAt(i, column.data[i].as_string()); break; case Origin::Time: { switch(column.valueTypeSpecification + 128) { case Origin::TIME_HH_MM: format="hh:mm"; break; case Origin::TIME_HH: format="hh"; break; case Origin::TIME_HH_MM_SS: format="hh:mm:ss"; break; case Origin::TIME_HH_MM_SS_ZZ: format="hh:mm:ss.zzz"; break; case Origin::TIME_HH_AP: format="hh ap"; break; case Origin::TIME_HH_MM_AP: format="hh:mm ap"; break; case Origin::TIME_MM_SS: format="mm:ss"; break; case Origin::TIME_MM_SS_ZZ: format="mm:ss.zzz"; break; case Origin::TIME_HHMM: format="hhmm"; break; case Origin::TIME_HHMMSS: format="hhmmss"; break; case Origin::TIME_HH_MM_SS_ZZZ: format="hh:mm:ss.zzz"; break; } for (int i = 0; i < min((int)column.data.size(), rows); ++i) col->setValueAt(i, column.data[i].as_double()); col->setColumnMode(AbstractColumn::DateTime); DateTime2StringFilter *filter = static_cast(col->outputFilter()); filter->setFormat(format); break; } case Origin::Date: { switch(column.valueTypeSpecification) { case Origin::DATE_DD_MM_YYYY: format="dd/MM/yyyy"; break; case Origin::DATE_DD_MM_YYYY_HH_MM: format="dd/MM/yyyy HH:mm"; break; case Origin::DATE_DD_MM_YYYY_HH_MM_SS: format="dd/MM/yyyy HH:mm:ss"; break; case Origin::DATE_DDMMYYYY: case Origin::DATE_DDMMYYYY_HH_MM: case Origin::DATE_DDMMYYYY_HH_MM_SS: format="dd.MM.yyyy"; break; case Origin::DATE_MMM_D: format="MMM d"; break; case Origin::DATE_M_D: format="M/d"; break; case Origin::DATE_D: format="d"; break; case Origin::DATE_DDD: case Origin::DATE_DAY_LETTER: format="ddd"; break; case Origin::DATE_YYYY: format="yyyy"; break; case Origin::DATE_YY: format="yy"; break; case Origin::DATE_YYMMDD: case Origin::DATE_YYMMDD_HH_MM: case Origin::DATE_YYMMDD_HH_MM_SS: case Origin::DATE_YYMMDD_HHMM: case Origin::DATE_YYMMDD_HHMMSS: format="yyMMdd"; break; case Origin::DATE_MMM: case Origin::DATE_MONTH_LETTER: format="MMM"; break; case Origin::DATE_M_D_YYYY: format="M-d-yyyy"; break; default: format="dd.MM.yyyy"; } for (int i = 0; i < min((int)column.data.size(), rows); ++i) col->setValueAt(i, column.data[i].as_double()); col->setColumnMode(AbstractColumn::DateTime); DateTime2StringFilter *filter = static_cast(col->outputFilter()); filter->setFormat(format); break; } case Origin::Month: { switch (column.valueTypeSpecification) { case Origin::MONTH_MMM: format = "MMM"; break; case Origin::MONTH_MMMM: format = "MMMM"; break; case Origin::MONTH_LETTER: format = "M"; break; } for (int i = 0; i < min((int)column.data.size(), rows); ++i) col->setValueAt(i, column.data[i].as_double()); col->setColumnMode(AbstractColumn::Month); DateTime2StringFilter *filter = static_cast(col->outputFilter()); filter->setFormat(format); break; } case Origin::Day: { switch(column.valueTypeSpecification) { case Origin::DAY_DDD: format = "ddd"; break; case Origin::DAY_DDDD: format = "dddd"; break; case Origin::DAY_LETTER: format = "d"; break; } for (int i = 0; i < min((int)column.data.size(), rows); ++i) col->setValueAt(i, column.data[i].as_double()); col->setColumnMode(AbstractColumn::Day); DateTime2StringFilter *filter = static_cast(col->outputFilter()); filter->setFormat(format); break; } case Origin::ColumnHeading: case Origin::TickIndexedDataset: case Origin::Categorical: break; } } //TODO // if (spread.hidden || spread.loose) // mw->hideWindow(spreadsheet); return true; } bool OriginProjectParser::loadMatrixWorkbook(Workbook* workbook, bool preview) { //load matrix workbook sheets const Origin::Matrix matrix = m_originFile->matrix(m_matrixIndex); - for (unsigned int s = 0; s < matrix.sheets.size(); ++s) { + for (size_t s = 0; s < matrix.sheets.size(); ++s) { // TODO: name of sheets are not saved in liborigin: "Sheet1", "Sheet2", ...) //TODO: figure out how to set the matrix name Matrix* matrix = new Matrix(0, ""); loadMatrix(matrix, preview, s); workbook->addChildFast(matrix); } return true; } -bool OriginProjectParser::loadMatrix(Matrix* matrix, bool preview, int sheetIndex) { +bool OriginProjectParser::loadMatrix(Matrix* matrix, bool preview, size_t sheetIndex) { if (preview) return true; //import matrix data Q_UNUSED(matrix); Origin::Matrix originMatrix = m_originFile->matrix(m_matrixIndex); - unsigned int layers = originMatrix.sheets.size(); - std::cout << "matrix sheets " << originMatrix.name << " " << layers; int scaling_factor = 10; //in Origin width is measured in characters while here in pixels --- need to be accurate Origin::MatrixSheet layer = originMatrix.sheets[sheetIndex]; const int colCount = layer.columnCount; const int rowCount = layer.rowCount; matrix->setRowCount(rowCount); matrix->setColumnCount(colCount); matrix->setFormula(layer.command.c_str()); for (int j = 0; j < colCount; j++) matrix->setColumnWidth(j, layer.width * scaling_factor); //TODO: check colum major vs. row major to improve the performance here for (int i = 0; i < rowCount; i++) { for (int j = 0; j < colCount; j++) matrix->setCell(i, j, layer.data[j + i*colCount]); } char format = 'g'; int prec = 6; switch (layer.valueTypeSpecification) { case 0: //Decimal 1000 format='f'; prec = layer.decimalPlaces; break; case 1: //Scientific format='e'; prec = layer.decimalPlaces; break; case 2: //Engineering case 3: //Decimal 1,000 format='g'; prec = layer.significantDigits; break; } //TODO: prec not support by Matrix Q_UNUSED(prec); matrix->setNumericFormat(format); return true; } bool OriginProjectParser::loadWorksheet(Worksheet* worksheet, bool preview) { if (preview) return true; //load worksheet data Origin::Graph graph = m_originFile->graph(m_graphIndex); // TODO:worksheet->hide();//!hack used in order to avoid resize and repaint events worksheet->setComment(graph.label.c_str()); //add plots for (const auto& layer: graph.layers) { CartesianPlot* plot = new CartesianPlot(""); //add legend if available if (!layer.legend.text.empty()) { CartesianPlotLegend* legend = new CartesianPlotLegend(plot, ""); legend->title()->setText( parseOriginText(QString::fromLocal8Bit(layer.legend.text.c_str())) ); plot->addChild(legend); } // TODO: we only support one legend //add texts /* for (const auto &s: layer.texts) { DEBUG("EXTRA TEXT =" << s.text.c_str()); // plot->newLegend(parseOriginText(QString::fromLocal8Bit(s.text.c_str()))); } */ // int auto_color = 0; // int style = 0; //add curves for (const auto& curve: layer.curves) { QString data(curve.dataName.c_str()); // int color = 0; switch(curve.type) { case Origin::GraphCurve::Line: // style = Graph::Line; break; case Origin::GraphCurve::Scatter: // style = Graph::Scatter; break; case Origin::GraphCurve::LineSymbol: // style = Graph::LineSymbols; break; case Origin::GraphCurve::ErrorBar: case Origin::GraphCurve::XErrorBar: // style = Graph::ErrorBars; break; case Origin::GraphCurve::Column: // style = Graph::VerticalBars; break; case Origin::GraphCurve::Bar: // style = Graph::HorizontalBars; break; case Origin::GraphCurve::Histogram: // style = Graph::Histogram; break; default: continue; } /* QString tableName; switch(data[0].toAscii()) { case 'T': case 'E': { tableName = data.right(data.length() - 2); Table* table = mw->table(tableName); if (!table) break; if(style == Graph::ErrorBars) { int flags=_curve.symbolType; graph->addErrorBars(QString("%1_%2").arg(tableName, _curve.xColumnName.c_str()), table, QString("%1_%2").arg(tableName, _curve.yColumnName.c_str()), ((flags&0x10)==0x10?0:1), ceil(_curve.lineWidth), ceil(_curve.symbolSize), QColor(Qt::black), (flags&0x40)==0x40, (flags&2)==2, (flags&1)==1); } else if(style == Graph::Histogram) { graph->insertCurve(table, QString("%1_%2").arg(tableName, _curve.yColumnName.c_str()), style); } else { graph->insertCurve(table, QString("%1_%2").arg(tableName, _curve.xColumnName.c_str()), QString("%1_%2").arg(tableName, _curve.yColumnName.c_str()), style); } break; } //TODO } */ /* CurveLayout cl = graph->initCurveLayout(style, layer.curves.size()); cl.sSize = ceil(_curve.symbolSize*0.5); cl.penWidth = _curve.symbolThickness; color = _curve.symbolColor.regular; if((style == Graph::Scatter || style == Graph::LineSymbols) && color == 0xF7) // 0xF7 -Automatic color color = auto_color++; cl.symCol = color; switch(_curve.symbolType & 0xFF) { case 0: //NoSymbol cl.sType = 0; break; //TODO } */ //TODO } worksheet->addChild(plot); } return true; } bool OriginProjectParser::loadNote(Note* note, bool preview) { if (preview) return true; //load note data Origin::Note originNote = m_originFile->note(m_noteIndex); //TODO: do we really need this? // QString name = originNote.name.c_str(); // QRegExp rx("^@(\\S+)$"); // if(rx.indexIn(name) == 0) // name = name.mid(2, name.length() - 3); // note->setName(name); //TODO: note->setWindowLabel(originNote.label.c_str()); note->setNote(QString(originNote.text.c_str())); return true; } //############################################################################## //############## Deserialization from Origin's project tree #################### //############################################################################## QDateTime OriginProjectParser::creationTime(const tree::iterator& it) const { //this logic seems to be correct only for the first node (project node). For other nodes the current time is returned. char time_str[21]; strftime(time_str, sizeof(time_str), "%F %T", gmtime(&(*it).creationDate)); return QDateTime::fromString(QString(time_str), Qt::ISODate); } QString OriginProjectParser::parseOriginText(const QString &str) const { QStringList lines = str.split("\n"); QString text = ""; for (int i = 0; i < lines.size(); ++i) { if(i > 0) text.append("\n"); text.append(parseOriginTags(lines[i])); } return text; } QString strreverse(const QString &str) { //QString reversing QByteArray ba = str.toLocal8Bit(); std::reverse(ba.begin(), ba.end()); return QString(ba); } // taken from SciDAVis QString OriginProjectParser::parseOriginTags(const QString &str) const { QString line = str; //replace \l(...) and %(...) tags QRegExp rxline("\\\\\\s*l\\s*\\(\\s*\\d+\\s*\\)"); QRegExp rxcol("\\%\\(\\d+\\)"); int pos = rxline.indexIn(line); while (pos > -1) { QString value = rxline.cap(0); int len=value.length(); value.replace(QRegExp(" "),""); value="\\c{"+value.mid(3,value.length()-4)+"}"; line.replace(pos, len, value); pos = rxline.indexIn(line); } //Lookbehind conditions are not supported - so need to reverse string QRegExp rx("\\)[^\\)\\(]*\\((?!\\s*[buig\\+\\-]\\s*\\\\)"); QRegExp rxfont("\\)[^\\)\\(]*\\((?![^\\:]*\\:f\\s*\\\\)"); QString linerev = strreverse(line); QString lBracket=strreverse("&lbracket;"); QString rBracket=strreverse("&rbracket;"); QString ltagBracket=strreverse("<agbracket;"); QString rtagBracket=strreverse("&rtagbracket;"); int pos1 = rx.indexIn(linerev); int pos2 = rxfont.indexIn(linerev); while (pos1>-1 || pos2>-1) { if(pos1==pos2) { QString value = rx.cap(0); int len=value.length(); value=rBracket+value.mid(1,len-2)+lBracket; linerev.replace(pos1, len, value); } else if ((pos1>pos2&&pos2!=-1)||pos1==-1) { QString value = rxfont.cap(0); int len=value.length(); value=rtagBracket+value.mid(1,len-2)+ltagBracket; linerev.replace(pos2, len, value); } else if ((pos2>pos1&&pos1!=-1)||pos2==-1) { QString value = rx.cap(0); int len=value.length(); value=rtagBracket+value.mid(1,len-2)+ltagBracket; linerev.replace(pos1, len, value); } pos1=rx.indexIn(linerev); pos2=rxfont.indexIn(linerev); } linerev.replace(ltagBracket, "("); linerev.replace(rtagBracket, ")"); line = strreverse(linerev); //replace \b(...), \i(...), \u(...), \g(...), \+(...), \-(...), \f:font(...) tags const QString rxstr[] = { "\\\\\\s*b\\s*\\(", "\\\\\\s*i\\s*\\(", "\\\\\\s*u\\s*\\(", "\\\\\\s*g\\s*\\(", "\\\\\\s*\\+\\s*\\(", "\\\\\\s*\\-\\s*\\(", "\\\\\\s*f\\:[^\\(]*\\("}; int postag[]={0,0,0,0,0,0,0}; QString ltag[]={"","","","","","",""}; QString rtag[]={"","","","","","",""}; QRegExp rxtags[7]; for(int i=0; i<7; ++i) rxtags[i].setPattern(rxstr[i]+"[^\\(\\)]*\\)"); bool flag=true; while(flag) { for(int i=0; i<7; ++i) { postag[i] = rxtags[i].indexIn(line); while (postag[i] > -1) { QString value = rxtags[i].cap(0); int len = value.length(); pos2 = value.indexOf("("); if(i<6) value=ltag[i]+value.mid(pos2+1,len-pos2-2)+rtag[i]; else { int posfont=value.indexOf("f:"); value=ltag[i].arg(value.mid(posfont+2,pos2-posfont-2))+value.mid(pos2+1,len-pos2-2)+rtag[i]; } line.replace(postag[i], len, value); postag[i] = rxtags[i].indexIn(line); } } flag=false; for(int i=0; i<7; ++i) { if(rxtags[i].indexIn(line)>-1) { flag=true; break; } } } //replace unclosed tags for(int i=0; i<6; ++i) line.replace(QRegExp(rxstr[i]), ltag[i]); rxfont.setPattern(rxstr[6]); pos = rxfont.indexIn(line); while (pos > -1) { QString value = rxfont.cap(0); int len=value.length(); int posfont=value.indexOf("f:"); value=ltag[6].arg(value.mid(posfont+2,len-posfont-3)); line.replace(pos, len, value); pos = rxfont.indexIn(line); } line.replace("&lbracket;", "("); line.replace("&rbracket;", ")"); return line; } diff --git a/src/backend/datasources/projects/OriginProjectParser.h b/src/backend/datasources/projects/OriginProjectParser.h index ad3d24e9e..1ec185e79 100644 --- a/src/backend/datasources/projects/OriginProjectParser.h +++ b/src/backend/datasources/projects/OriginProjectParser.h @@ -1,71 +1,71 @@ /*************************************************************************** File : OriginProjectParser.h Project : LabPlot Description : parser for Origin projects -------------------------------------------------------------------- Copyright : (C) 2017 Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * 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 ORIGINPROJECTPARSER_H #define ORIGINPROJECTPARSER_H #include "backend/datasources/projects/ProjectParser.h" #include class Project; class Workbook; class Spreadsheet; class Matrix; class Worksheet; class Note; class OriginProjectParser : public ProjectParser { Q_OBJECT public: OriginProjectParser(); QAbstractItemModel* model() override; void importTo(Folder*, const QStringList&) override; private: bool load(Project*, bool preview); bool loadFolder(Folder*, const tree::iterator&, bool preview); bool loadWorkbook(Workbook*, bool preview); - bool loadSpreadsheet(Spreadsheet*, bool preview, int sheetIndex = 0); + bool loadSpreadsheet(Spreadsheet*, bool preview, size_t sheetIndex = 0); bool loadMatrixWorkbook(Workbook*, bool preview); - bool loadMatrix(Matrix*, bool preview, int sheetIndex = 0); + bool loadMatrix(Matrix*, bool preview, size_t sheetIndex = 0); bool loadWorksheet(Worksheet*, bool preview); bool loadNote(Note*, bool preview); QString parseOriginText(const QString &str) const; QString parseOriginTags(const QString &str) const; QDateTime creationTime(const tree::iterator&) const; OriginFile* m_originFile; - int m_excelIndex; - int m_matrixIndex; - int m_graphIndex; - int m_noteIndex; + size_t m_excelIndex; + size_t m_matrixIndex; + size_t m_graphIndex; + size_t m_noteIndex; }; #endif // ORIGINPROJECTPARSER_H diff --git a/src/kdefrontend/MainWin.cpp b/src/kdefrontend/MainWin.cpp index 5544eea78..9b6af501e 100644 --- a/src/kdefrontend/MainWin.cpp +++ b/src/kdefrontend/MainWin.cpp @@ -1,1786 +1,1783 @@ /*************************************************************************** File : MainWin.cc Project : LabPlot Description : Main window of the application -------------------------------------------------------------------- Copyright : (C) 2009-2017 Alexander Semke (alexander.semke@web.de) Copyright : (C) 2008-2015 Stefan Gerlach (stefan.gerlach@uni.kn) ***************************************************************************/ /*************************************************************************** * * * 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 "MainWin.h" #include "backend/core/Project.h" #include "backend/core/Folder.h" #include "backend/core/AspectTreeModel.h" #include "backend/core/Workbook.h" #include "backend/spreadsheet/Spreadsheet.h" #include "backend/matrix/Matrix.h" #include "backend/worksheet/Worksheet.h" #include "backend/datasources/LiveDataSource.h" #ifdef HAVE_CANTOR_LIBS #include "backend/cantorWorksheet/CantorWorksheet.h" #endif #include "backend/datapicker/Datapicker.h" #include "backend/note/Note.h" #include "backend/lib/macros.h" #include "commonfrontend/core/PartMdiView.h" #include "commonfrontend/ProjectExplorer.h" #include "commonfrontend/matrix/MatrixView.h" #include "commonfrontend/spreadsheet/SpreadsheetView.h" #include "commonfrontend/worksheet/WorksheetView.h" #ifdef HAVE_CANTOR_LIBS #include "commonfrontend/cantorWorksheet/CantorWorksheetView.h" #endif #include "commonfrontend/datapicker/DatapickerView.h" #include "commonfrontend/datapicker/DatapickerImageView.h" #include "commonfrontend/note/NoteView.h" #include "kdefrontend/datasources/ImportFileDialog.h" #include "kdefrontend/datasources/ImportProjectDialog.h" #include "kdefrontend/datasources/ImportSQLDatabaseDialog.h" -#ifdef HAVE_LIBORIGIN -#include "kdefrontend/datasources/ImportOpj.h" -#endif #include "kdefrontend/dockwidgets/ProjectDock.h" #include "kdefrontend/HistoryDialog.h" #include "kdefrontend/SettingsDialog.h" #include "kdefrontend/GuiObserver.h" #include "kdefrontend/widgets/FITSHeaderEditDialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CANTOR_LIBS #include #endif /*! \class MainWin \brief Main application window. \ingroup kdefrontend */ MainWin::MainWin(QWidget *parent, const QString& filename) : KXmlGuiWindow(parent), m_currentSubWindow(0), m_project(0), m_aspectTreeModel(0), m_projectExplorer(0), m_projectExplorerDock(0), m_propertiesDock(0), m_currentAspect(0), m_currentFolder(0), m_suppressCurrentSubWindowChangedEvent(false), m_closing(false), m_autoSaveActive(false), m_visibilityMenu(0), m_newMenu(0), m_editMenu(0), axisDock(0), notesDock(0), cartesianPlotDock(0), cartesianPlotLegendDock(0), columnDock(0), m_liveDataDock(0), matrixDock(0), spreadsheetDock(0), projectDock(0), xyCurveDock(0), xyEquationCurveDock(0), xyDataReductionCurveDock(0), xyDifferentiationCurveDock(0), xyIntegrationCurveDock(0), xyInterpolationCurveDock(0), xySmoothCurveDock(0), xyFitCurveDock(0), xyFourierFilterCurveDock(0), xyFourierTransformCurveDock(0), histogramDock(0), worksheetDock(0), textLabelDock(0), customPointDock(0), datapickerImageDock(0), datapickerCurveDock(0), #ifdef HAVE_CANTOR_LIBS cantorWorksheetDock(0), #endif m_guiObserver(0) { // QTimer::singleShot( 0, this, SLOT(initGUI(filename)) ); //TODO doesn't work anymore initGUI(filename); setAcceptDrops(true); } MainWin::~MainWin() { //save the recent opened files m_recentProjectsAction->saveEntries( KSharedConfig::openConfig()->group("Recent Files") ); KSharedConfig::openConfig()->sync(); if (m_project != 0) { m_mdiArea->closeAllSubWindows(); disconnect(m_project, 0, this, 0); delete m_project; } if (m_aspectTreeModel) delete m_aspectTreeModel; if (m_guiObserver) delete m_guiObserver; } void MainWin::showPresenter() { Worksheet* w = activeWorksheet(); if (w) { WorksheetView* view = dynamic_cast(w->view()); view->presenterMode(); } else { //currently active object is not a worksheet but we're asked to start in the presenter mode //determine the first available worksheet and show it in the presenter mode QVector worksheets = m_project->children(); if (worksheets.size()>0) { WorksheetView* view = qobject_cast(worksheets.first()->view()); view->presenterMode(); } else { QMessageBox::information(this, i18n("Presenter Mode"), i18n("No worksheets are available in the project. The presenter mode won't be started.")); } } } AspectTreeModel* MainWin::model() const { return m_aspectTreeModel; } Project* MainWin::project() const { return m_project; } void MainWin::initGUI(const QString& fileName) { m_mdiArea = new QMdiArea; setCentralWidget(m_mdiArea); connect(m_mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(handleCurrentSubWindowChanged(QMdiSubWindow*))); #ifdef _WIN32 QIcon::setThemeName("hicolor"); #endif statusBar()->showMessage(i18nc("%1 is the LabPlot version", "Welcome to LabPlot %1", QLatin1String(LVERSION))); initActions(); #ifdef __APPLE__ setupGUI(Default, QLatin1String("/Applications/labplot2.app/Contents/share/labplot2ui.rc")); #else setupGUI(Default, QLatin1String("labplot2ui.rc")); #endif //all toolbars created via the KXMLGUI framework are locked on default: // * on the very first program start, unlock all toolbars // * on later program starts, set stored lock status //Furthermore, we want to show icons only after the first program start. KConfigGroup groupMain = KSharedConfig::openConfig()->group("MainWindow"); if (groupMain.exists()) { //KXMLGUI framework automatically stores "Disabled" for the key "ToolBarsMovable" //in case the toolbars are locked -> load this value const QString& str = groupMain.readEntry(QLatin1String("ToolBarsMovable"), ""); bool locked = (str == QLatin1String("Disabled")); KToolBar::setToolBarsLocked(locked); } else { //first start KToolBar::setToolBarsLocked(false); //show icons only for (auto* container : factory()->containers(QLatin1String("ToolBar"))) { QToolBar* toolbar = dynamic_cast(container); if (toolbar) toolbar->setToolButtonStyle(Qt::ToolButtonIconOnly); } } initMenus(); QToolBar* mainToolBar = qobject_cast(factory()->container("main_toolbar", this)); QToolButton* tbImport = new QToolButton(mainToolBar); tbImport->setPopupMode(QToolButton::MenuButtonPopup); tbImport->setMenu(m_importMenu); tbImport->setDefaultAction(m_importFileAction); mainToolBar->addWidget(tbImport); qobject_cast(factory()->container("import", this))->setIcon(QIcon::fromTheme("document-import")); setWindowIcon(QIcon::fromTheme("LabPlot2")); setAttribute( Qt::WA_DeleteOnClose ); //make the status bar of a fixed size in order to avoid height changes when placing a ProgressBar there. QFont font; font.setFamily(font.defaultFamily()); QFontMetrics fm(font); statusBar()->setFixedHeight(fm.height()+5); //load recently used projects m_recentProjectsAction->loadEntries( KSharedConfig::openConfig()->group("Recent Files") ); //set the view mode of the mdi area KConfigGroup group = KSharedConfig::openConfig()->group( "Settings_General" ); int viewMode = group.readEntry("ViewMode", 0); if (viewMode == 1) { m_mdiArea->setViewMode(QMdiArea::TabbedView); int tabPosition = group.readEntry("TabPosition", 0); m_mdiArea->setTabPosition(QTabWidget::TabPosition(tabPosition)); m_mdiArea->setTabsClosable(true); m_mdiArea->setTabsMovable(true); m_tileWindows->setVisible(false); m_cascadeWindows->setVisible(false); } //auto-save m_autoSaveActive = group.readEntry("AutoSave", 0); int interval = group.readEntry("AutoSaveInterval", 1); interval = interval*60*1000; m_autoSaveTimer.setInterval(interval); connect(&m_autoSaveTimer, SIGNAL(timeout()), this, SLOT(autoSaveProject())); if (!fileName.isEmpty()) openProject(fileName); else { //There is no file to open. Depending on the settings do nothing, //create a new project or open the last used project. int load = group.readEntry("LoadOnStart", 0); if (load == 1) //create new project newProject(); else if (load == 2) { //create new project with a worksheet newProject(); newWorksheet(); } else if (load == 3) { //open last used project if (!m_recentProjectsAction->urls().isEmpty()) { QDEBUG("TO OPEN m_recentProjectsAction->urls() =" << m_recentProjectsAction->urls().first()); openRecentProject( m_recentProjectsAction->urls().first() ); } } } updateGUIOnProjectChanges(); } void MainWin::initActions() { // ******************** File-menu ******************************* //add some standard actions KStandardAction::openNew(this, SLOT(newProject()),actionCollection()); KStandardAction::open(this, SLOT(openProject()),actionCollection()); m_recentProjectsAction = KStandardAction::openRecent(this, SLOT(openRecentProject(QUrl)),actionCollection()); m_closeAction = KStandardAction::close(this, SLOT(closeProject()),actionCollection()); m_saveAction = KStandardAction::save(this, SLOT(saveProject()),actionCollection()); m_saveAsAction = KStandardAction::saveAs(this, SLOT(saveProjectAs()),actionCollection()); m_printAction = KStandardAction::print(this, SLOT(print()),actionCollection()); m_printPreviewAction = KStandardAction::printPreview(this, SLOT(printPreview()),actionCollection()); KStandardAction::fullScreen(this, SLOT(toggleFullScreen()), this, actionCollection()); //New Folder/Workbook/Spreadsheet/Matrix/Worksheet/Datasources m_newWorkbookAction = new QAction(QIcon::fromTheme("labplot-workbook-new"),i18n("Workbook"),this); actionCollection()->addAction("new_workbook", m_newWorkbookAction); connect(m_newWorkbookAction, SIGNAL(triggered()), SLOT(newWorkbook())); m_newDatapickerAction = new QAction(QIcon::fromTheme("color-picker-black"), i18n("Datapicker"), this); actionCollection()->addAction("new_datapicker", m_newDatapickerAction); connect(m_newDatapickerAction, SIGNAL(triggered()), SLOT(newDatapicker())); m_newSpreadsheetAction = new QAction(QIcon::fromTheme("labplot-spreadsheet-new"),i18n("Spreadsheet"),this); // m_newSpreadsheetAction->setShortcut(Qt::CTRL+Qt::Key_Equal); actionCollection()->addAction("new_spreadsheet", m_newSpreadsheetAction); connect(m_newSpreadsheetAction, SIGNAL(triggered()), SLOT(newSpreadsheet())); m_newMatrixAction = new QAction(QIcon::fromTheme("labplot-matrix-new"),i18n("Matrix"),this); // m_newMatrixAction->setShortcut(Qt::CTRL+Qt::Key_Equal); actionCollection()->addAction("new_matrix", m_newMatrixAction); connect(m_newMatrixAction, SIGNAL(triggered()), SLOT(newMatrix())); m_newWorksheetAction= new QAction(QIcon::fromTheme("labplot-worksheet-new"),i18n("Worksheet"),this); // m_newWorksheetAction->setShortcut(Qt::ALT+Qt::Key_X); actionCollection()->addAction("new_worksheet", m_newWorksheetAction); connect(m_newWorksheetAction, SIGNAL(triggered()), SLOT(newWorksheet())); m_newNotesAction= new QAction(QIcon::fromTheme("document-new"),i18n("Note"),this); actionCollection()->addAction("new_notes", m_newNotesAction); connect(m_newNotesAction, SIGNAL(triggered()), SLOT(newNotes())); // m_newScriptAction = new QAction(QIcon::fromTheme("insert-text"),i18n("Note/Script"),this); // actionCollection()->addAction("new_script", m_newScriptAction); // connect(m_newScriptAction, SIGNAL(triggered()),SLOT(newScript())); m_newFolderAction = new QAction(QIcon::fromTheme("folder-new"),i18n("Folder"),this); actionCollection()->addAction("new_folder", m_newFolderAction); connect(m_newFolderAction, SIGNAL(triggered()), SLOT(newFolder())); //"New file datasources" m_newLiveDataSourceAction = new QAction(QIcon::fromTheme("application-octet-stream"),i18n("Live Data Source"),this); actionCollection()->addAction("new_live_datasource", m_newLiveDataSourceAction); connect(m_newLiveDataSourceAction, SIGNAL(triggered()), this, SLOT(newLiveDataSourceActionTriggered())); //Import/Export m_importFileAction = new QAction(QIcon::fromTheme("document-import"), i18n("From File"), this); actionCollection()->setDefaultShortcut(m_importFileAction, Qt::CTRL+Qt::SHIFT+Qt::Key_I); actionCollection()->addAction("import_file", m_importFileAction); connect(m_importFileAction, SIGNAL(triggered()), SLOT(importFileDialog())); m_importSqlAction = new QAction(QIcon::fromTheme("document-import-database"), i18n("From SQL Database"), this); actionCollection()->addAction("import_sql", m_importSqlAction); connect(m_importSqlAction, SIGNAL(triggered()),SLOT(importSqlDialog())); m_importLabPlotAction = new QAction(QIcon::fromTheme("document-import"), i18n("LabPlot Project"), this); actionCollection()->addAction("import_labplot", m_importLabPlotAction); connect(m_importLabPlotAction, SIGNAL(triggered()),SLOT(importProjectDialog())); #ifdef HAVE_LIBORIGIN m_importOpjAction = new QAction(QIcon::fromTheme("document-import-database"), i18n("Origin Project (OPJ)"), this); actionCollection()->addAction("import_opj", m_importOpjAction); connect(m_importOpjAction, SIGNAL(triggered()),SLOT(importProjectDialog())); #endif m_exportAction = new QAction(QIcon::fromTheme("document-export"), i18n("Export"), this); actionCollection()->setDefaultShortcut(m_exportAction, Qt::CTRL+Qt::SHIFT+Qt::Key_E); actionCollection()->addAction("export", m_exportAction); connect(m_exportAction, SIGNAL(triggered()), SLOT(exportDialog())); m_editFitsFileAction = new QAction(i18n("FITS Metadata Editor"), this); actionCollection()->addAction("edit_fits", m_editFitsFileAction); connect(m_editFitsFileAction, SIGNAL(triggered()), SLOT(editFitsFileDialog())); // Edit //Undo/Redo-stuff m_undoAction = KStandardAction::undo(this, SLOT(undo()), actionCollection()); m_redoAction = KStandardAction::redo(this, SLOT(redo()), actionCollection()); m_historyAction = new QAction(QIcon::fromTheme("view-history"), i18n("Undo/Redo History"),this); actionCollection()->addAction("history", m_historyAction); connect(m_historyAction, SIGNAL(triggered()), SLOT(historyDialog())); // TODO: more menus // Appearance // Analysis: see WorksheetView.cpp // Drawing // Script //Windows QAction* action = new QAction(i18n("&Close"), this); actionCollection()->setDefaultShortcut(action, Qt::CTRL+Qt::Key_U); action->setStatusTip(i18n("Close the active window")); actionCollection()->addAction("close window", action); connect(action, SIGNAL(triggered()), m_mdiArea, SLOT(closeActiveSubWindow())); action = new QAction(i18n("Close &All"), this); action->setStatusTip(i18n("Close all the windows")); actionCollection()->addAction("close all windows", action); connect(action, SIGNAL(triggered()), m_mdiArea, SLOT(closeAllSubWindows())); m_tileWindows = new QAction(i18n("&Tile"), this); m_tileWindows->setStatusTip(i18n("Tile the windows")); actionCollection()->addAction("tile windows", m_tileWindows); connect(m_tileWindows, SIGNAL(triggered()), m_mdiArea, SLOT(tileSubWindows())); m_cascadeWindows = new QAction(i18n("&Cascade"), this); m_cascadeWindows->setStatusTip(i18n("Cascade the windows")); actionCollection()->addAction("cascade windows", m_cascadeWindows); connect(m_cascadeWindows, SIGNAL(triggered()), m_mdiArea, SLOT(cascadeSubWindows())); action = new QAction(QIcon::fromTheme("go-next-view"), i18n("Ne&xt"), this); action->setStatusTip(i18n("Move the focus to the next window")); actionCollection()->addAction("next window", action); connect(action, SIGNAL(triggered()), m_mdiArea, SLOT(activateNextSubWindow())); action = new QAction(QIcon::fromTheme("go-previous-view"), i18n("Pre&vious"), this); action->setStatusTip(i18n("Move the focus to the previous window")); actionCollection()->addAction("previous window", action); connect(action, SIGNAL(triggered()), m_mdiArea, SLOT(activatePreviousSubWindow())); //"Standard actions" KStandardAction::preferences(this, SLOT(settingsDialog()), actionCollection()); KStandardAction::quit(this, SLOT(close()), actionCollection()); //Actions for window visibility QActionGroup* windowVisibilityActions = new QActionGroup(this); windowVisibilityActions->setExclusive(true); m_visibilityFolderAction = new QAction(QIcon::fromTheme("folder"), i18n("Current &Folder Only"), windowVisibilityActions); m_visibilityFolderAction->setCheckable(true); m_visibilityFolderAction->setData(Project::folderOnly); m_visibilitySubfolderAction = new QAction(QIcon::fromTheme("folder-documents"), i18n("Current Folder and &Subfolders"), windowVisibilityActions); m_visibilitySubfolderAction->setCheckable(true); m_visibilitySubfolderAction->setData(Project::folderAndSubfolders); m_visibilityAllAction = new QAction(i18n("&All"), windowVisibilityActions); m_visibilityAllAction->setCheckable(true); m_visibilityAllAction->setData(Project::allMdiWindows); connect(windowVisibilityActions, SIGNAL(triggered(QAction*)), this, SLOT(setMdiWindowVisibility(QAction*))); //Actions for hiding/showing the dock widgets QActionGroup * docksActions = new QActionGroup(this); docksActions->setExclusive(false); m_toggleProjectExplorerDockAction = new QAction(QIcon::fromTheme("view-list-tree"), i18n("Project explorer"), docksActions); m_toggleProjectExplorerDockAction->setCheckable(true); m_toggleProjectExplorerDockAction->setChecked(true); actionCollection()->addAction("toggle_project_explorer_dock", m_toggleProjectExplorerDockAction); m_togglePropertiesDockAction = new QAction(QIcon::fromTheme("view-list-details"), i18n("Properties explorer"), docksActions); m_togglePropertiesDockAction->setCheckable(true); m_togglePropertiesDockAction->setChecked(true); actionCollection()->addAction("toggle_properties_explorer_dock", m_togglePropertiesDockAction); connect(docksActions, SIGNAL(triggered(QAction*)), this, SLOT(toggleDockWidget(QAction*))); } void MainWin::initMenus() { //menu for adding new aspects m_newMenu = new QMenu(i18n("Add new"), this); m_newMenu->setIcon(QIcon::fromTheme("document-new")); m_newMenu->addAction(m_newFolderAction); m_newMenu->addAction(m_newWorkbookAction); m_newMenu->addAction(m_newSpreadsheetAction); m_newMenu->addAction(m_newMatrixAction); m_newMenu->addAction(m_newWorksheetAction); m_newMenu->addAction(m_newNotesAction); m_newMenu->addAction(m_newDatapickerAction); m_newMenu->addSeparator(); m_newMenu->addAction(m_newLiveDataSourceAction); //import menu m_importMenu = new QMenu(this); m_importMenu->setIcon(QIcon::fromTheme("document-import")); m_importMenu ->addAction(m_importFileAction); m_importMenu ->addAction(m_importSqlAction); m_importMenu->addSeparator(); m_importMenu->addAction(m_importLabPlotAction); #ifdef HAVE_LIBORIGIN m_importMenu ->addAction(m_importOpjAction); #endif #ifdef HAVE_CANTOR_LIBS m_newMenu->addSeparator(); m_newCantorWorksheetMenu = new QMenu(i18n("CAS Worksheet")); m_newCantorWorksheetMenu->setIcon(QIcon::fromTheme("archive-insert")); //"Adding Cantor backends to menue and context menu" QStringList m_availableBackend = Cantor::Backend::listAvailableBackends(); if(m_availableBackend.count() > 0) { unplugActionList(QLatin1String("backends_list")); QList newBackendActions; for (Cantor::Backend* backend : Cantor::Backend::availableBackends()) { if (!backend->isEnabled()) continue; QAction* action = new QAction(QIcon::fromTheme(backend->icon()), backend->name(),this); action->setData(backend->name()); newBackendActions << action; m_newCantorWorksheetMenu->addAction(action); } connect(m_newCantorWorksheetMenu, SIGNAL(triggered(QAction*)), this, SLOT(newCantorWorksheet(QAction*))); plugActionList(QLatin1String("backends_list"), newBackendActions); } m_newMenu->addMenu(m_newCantorWorksheetMenu); #else delete this->guiFactory()->container("cas_worksheet", this); delete this->guiFactory()->container("new_casWorksheet", this); delete this->guiFactory()->container("cas_worksheet_toolbar", this); #endif //menu subwindow visibility policy m_visibilityMenu = new QMenu(i18n("Window visibility policy"), this); m_visibilityMenu->setIcon(QIcon::fromTheme("window-duplicate")); m_visibilityMenu ->addAction(m_visibilityFolderAction); m_visibilityMenu ->addAction(m_visibilitySubfolderAction); m_visibilityMenu ->addAction(m_visibilityAllAction); //menu for editing files m_editMenu = new QMenu(i18n("Edit"), this); m_editMenu->addAction(m_editFitsFileAction); } /*! Asks to save the project if it was modified. \return \c true if the project still needs to be saved ("cancel" clicked), \c false otherwise. */ bool MainWin::warnModified() { if (m_project->hasChanged()) { int want_save = KMessageBox::warningYesNoCancel( this, i18n("The current project %1 has been modified. Do you want to save it?", m_project->name()), i18n("Save Project")); switch (want_save) { case KMessageBox::Yes: return !saveProject(); case KMessageBox::No: break; case KMessageBox::Cancel: return true; } } return false; } /*! * updates the state of actions, menus and toolbars (enabled or disabled) * on project changes (project closes and opens) */ void MainWin::updateGUIOnProjectChanges() { if (m_closing) return; KXMLGUIFactory* factory = this->guiFactory(); if (factory->container("worksheet", this) == NULL) { //no worksheet menu found, most probably labplot2ui.rc //was not properly installed -> return here in order not to crash return; } //disable all menus if there is no project bool b = (m_project == 0); m_saveAction->setEnabled(!b); m_saveAsAction->setEnabled(!b); m_printAction->setEnabled(!b); m_printPreviewAction->setEnabled(!b); m_importFileAction->setEnabled(!b); m_importSqlAction->setEnabled(!b); #ifdef HAVE_LIBORIGIN m_importOpjAction->setEnabled(!b); #endif m_exportAction->setEnabled(!b); m_newWorkbookAction->setEnabled(!b); m_newSpreadsheetAction->setEnabled(!b); m_newMatrixAction->setEnabled(!b); m_newWorksheetAction->setEnabled(!b); m_newDatapickerAction->setEnabled(!b); m_closeAction->setEnabled(!b); m_toggleProjectExplorerDockAction->setEnabled(!b); m_togglePropertiesDockAction->setEnabled(!b); if (!m_mdiArea->currentSubWindow()) { factory->container("spreadsheet", this)->setEnabled(false); factory->container("matrix", this)->setEnabled(false); factory->container("worksheet", this)->setEnabled(false); factory->container("analysis", this)->setEnabled(false); factory->container("datapicker", this)->setEnabled(false); factory->container("spreadsheet_toolbar", this)->hide(); factory->container("worksheet_toolbar", this)->hide(); factory->container("cartesian_plot_toolbar", this)->hide(); // factory->container("histogram_toolbar",this)->hide(); // factory->container("barchart_toolbar",this)->hide(); factory->container("datapicker_toolbar", this)->hide(); #ifdef HAVE_CANTOR_LIBS factory->container("cas_worksheet", this)->setEnabled(false); factory->container("cas_worksheet_toolbar", this)->hide(); #endif } factory->container("new", this)->setEnabled(!b); factory->container("edit", this)->setEnabled(!b); factory->container("import", this)->setEnabled(!b); if (b) setCaption("LabPlot2"); else setCaption(m_project->name()); // undo/redo actions are disabled in both cases - when the project is closed or opened m_undoAction->setEnabled(false); m_redoAction->setEnabled(false); } /* * updates the state of actions, menus and toolbars (enabled or disabled) * depending on the currently active window (worksheet or spreadsheet). */ void MainWin::updateGUI() { if (m_project->isLoading()) return; if (m_closing) return; KXMLGUIFactory* factory = this->guiFactory(); if (factory->container("worksheet", this) == NULL) { //no worksheet menu found, most probably labplot2ui.rc //was not properly installed -> return here in order not to crash return; } if (!m_mdiArea->currentSubWindow()) { factory->container("spreadsheet", this)->setEnabled(false); factory->container("matrix", this)->setEnabled(false); factory->container("worksheet", this)->setEnabled(false); factory->container("analysis", this)->setEnabled(false); factory->container("datapicker", this)->setEnabled(false); factory->container("spreadsheet_toolbar", this)->hide(); factory->container("worksheet_toolbar", this)->hide(); // factory->container("histogram_toolbar",this)->hide(); // factory->container("barchart_toolbar",this)->hide(); factory->container("cartesian_plot_toolbar", this)->hide(); factory->container("datapicker_toolbar", this)->hide(); #ifdef HAVE_CANTOR_LIBS factory->container("cas_worksheet", this)->setEnabled(false); factory->container("cas_worksheet_toolbar", this)->hide(); #endif return; } //Handle the Worksheet-object Worksheet* w = this->activeWorksheet(); if (w != 0) { //enable worksheet related menus factory->container("worksheet", this)->setEnabled(true); factory->container("analysis", this)->setEnabled(true); //TODO factory->container("drawing", this)->setEnabled(true); //disable spreadsheet and matrix related menus factory->container("spreadsheet", this)->setEnabled(false); factory->container("matrix", this)->setEnabled(false); //populate worksheet menu WorksheetView* view=qobject_cast(w->view()); QMenu* menu = qobject_cast(factory->container("worksheet", this)); menu->clear(); view->createContextMenu(menu); //populate analysis menu menu = qobject_cast(factory->container("analysis", this)); menu->clear(); view->createAnalysisMenu(menu); //populate worksheet-toolbar QToolBar* toolbar = qobject_cast(factory->container("worksheet_toolbar", this)); toolbar->clear(); view->fillToolBar(toolbar); toolbar->setVisible(true); toolbar->setEnabled(true); //populate the toolbar for cartesian plots toolbar=qobject_cast(factory->container("cartesian_plot_toolbar", this)); toolbar->clear(); view->fillCartesianPlotToolBar(toolbar); toolbar->setVisible(true); toolbar->setEnabled(true); //hide the spreadsheet toolbar factory->container("spreadsheet_toolbar", this)->setVisible(false); } else { factory->container("worksheet", this)->setEnabled(false); factory->container("analysis", this)->setEnabled(false); // factory->container("drawing", this)->setEnabled(false); factory->container("worksheet_toolbar", this)->setEnabled(false); factory->container("cartesian_plot_toolbar", this)->setEnabled(false); } //Handle the Spreadsheet-object const Spreadsheet* spreadsheet = this->activeSpreadsheet(); if (spreadsheet) { //enable spreadsheet related menus factory->container("spreadsheet", this)->setEnabled(true); //populate spreadsheet-menu SpreadsheetView* view = qobject_cast(spreadsheet->view()); QMenu* menu = qobject_cast(factory->container("spreadsheet", this)); menu->clear(); view->createContextMenu(menu); //populate spreadsheet-toolbar QToolBar* toolbar = qobject_cast(factory->container("spreadsheet_toolbar", this)); toolbar->clear(); view->fillToolBar(toolbar); toolbar->setVisible(true); toolbar->setEnabled(true); } else { factory->container("spreadsheet", this)->setEnabled(false); factory->container("spreadsheet_toolbar", this)->setEnabled(false); } //Handle the Matrix-object const Matrix* matrix = this->activeMatrix(); if (matrix) { factory->container("matrix", this)->setEnabled(true); //populate matrix-menu MatrixView* view = qobject_cast(matrix->view()); QMenu* menu = qobject_cast(factory->container("matrix", this)); menu->clear(); view->createContextMenu(menu); } else factory->container("matrix", this)->setEnabled(false); #ifdef HAVE_CANTOR_LIBS CantorWorksheet* cantorworksheet = this->activeCantorWorksheet(); if(cantorworksheet) { // enable Cantor Worksheet related menues factory->container("cas_worksheet", this)->setEnabled(true); CantorWorksheetView* view=qobject_cast(cantorworksheet->view()); QMenu* menu=qobject_cast(factory->container("cas_worksheet", this)); menu->clear(); view->createContextMenu(menu); QToolBar* toolbar=qobject_cast(factory->container("cas_worksheet_toolbar", this)); toolbar->setVisible(true); toolbar->clear(); view->fillToolBar(toolbar); } else { //no Cantor worksheet selected -> deactivate Cantor worksheet related menu and toolbar factory->container("cas_worksheet", this)->setEnabled(false); factory->container("cas_worksheet_toolbar", this)->setVisible(false); } #endif const Datapicker* datapicker = this->activeDatapicker(); if (datapicker) { factory->container("datapicker", this)->setEnabled(true); //populate datapicker-menu DatapickerView* view = qobject_cast(datapicker->view()); QMenu* menu = qobject_cast(factory->container("datapicker", this)); menu->clear(); view->createContextMenu(menu); //populate spreadsheet-toolbar QToolBar* toolbar = qobject_cast(factory->container("datapicker_toolbar", this)); toolbar->clear(); view->fillToolBar(toolbar); toolbar->setVisible(true); } else { factory->container("datapicker", this)->setEnabled(false); factory->container("datapicker_toolbar", this)->setVisible(false); } } /*! creates a new empty project. Returns \c true, if a new project was created. */ bool MainWin::newProject() { //close the current project, if available if (!closeProject()) return false; QApplication::processEvents(QEventLoop::AllEvents, 100); if (m_project) delete m_project; if (m_aspectTreeModel) delete m_aspectTreeModel; m_project = new Project(); m_currentAspect = m_project; m_currentFolder = m_project; KConfigGroup group = KSharedConfig::openConfig()->group( "Settings_General" ); Project::MdiWindowVisibility vis = Project::MdiWindowVisibility(group.readEntry("MdiWindowVisibility", 0)); m_project->setMdiWindowVisibility( vis ); if (vis == Project::folderOnly) m_visibilityFolderAction->setChecked(true); else if (vis == Project::folderAndSubfolders) m_visibilitySubfolderAction->setChecked(true); else m_visibilityAllAction->setChecked(true); m_aspectTreeModel = new AspectTreeModel(m_project, this); //newProject is called for the first time, there is no project explorer yet //-> initialize the project explorer, the GUI-observer and the dock widgets. if (m_projectExplorer == 0) { m_projectExplorerDock = new QDockWidget(this); m_projectExplorerDock->setObjectName("projectexplorer"); m_projectExplorerDock->setWindowTitle(i18n("Project Explorer")); addDockWidget(Qt::LeftDockWidgetArea, m_projectExplorerDock); m_projectExplorer = new ProjectExplorer(m_projectExplorerDock); m_projectExplorerDock->setWidget(m_projectExplorer); connect(m_projectExplorer, SIGNAL(currentAspectChanged(AbstractAspect*)), this, SLOT(handleCurrentAspectChanged(AbstractAspect*))); connect(m_projectExplorerDock, SIGNAL(visibilityChanged(bool)), SLOT(projectExplorerDockVisibilityChanged(bool))); //Properties dock m_propertiesDock = new QDockWidget(this); m_propertiesDock->setObjectName("aspect_properties_dock"); m_propertiesDock->setWindowTitle(i18n("Properties")); addDockWidget(Qt::RightDockWidgetArea, m_propertiesDock); QScrollArea* sa = new QScrollArea(m_propertiesDock); stackedWidget = new QStackedWidget(sa); sa->setWidget(stackedWidget); sa->setWidgetResizable(true); m_propertiesDock->setWidget(sa); connect(m_propertiesDock, SIGNAL(visibilityChanged(bool)), SLOT(propertiesDockVisibilityChanged(bool))); //GUI-observer; m_guiObserver = new GuiObserver(this); } m_projectExplorer->setModel(m_aspectTreeModel); m_projectExplorer->setProject(m_project); m_projectExplorer->setCurrentAspect(m_project); m_projectExplorerDock->show(); m_propertiesDock->show(); updateGUIOnProjectChanges(); connect(m_project, SIGNAL(aspectAdded(const AbstractAspect*)), this, SLOT(handleAspectAdded(const AbstractAspect*))); connect(m_project, SIGNAL(aspectRemoved(const AbstractAspect*,const AbstractAspect*,const AbstractAspect*)), this, SLOT(handleAspectRemoved(const AbstractAspect*,const AbstractAspect*,const AbstractAspect*))); connect(m_project, SIGNAL(aspectAboutToBeRemoved(const AbstractAspect*)), this, SLOT(handleAspectAboutToBeRemoved(const AbstractAspect*))); connect(m_project, SIGNAL(statusInfo(QString)), statusBar(), SLOT(showMessage(QString))); connect(m_project, SIGNAL(changed()), this, SLOT(projectChanged())); connect(m_project, SIGNAL(requestProjectContextMenu(QMenu*)), this, SLOT(createContextMenu(QMenu*))); connect(m_project, SIGNAL(requestFolderContextMenu(const Folder*,QMenu*)), this, SLOT(createFolderContextMenu(const Folder*,QMenu*))); connect(m_project, SIGNAL(mdiWindowVisibilityChanged()), this, SLOT(updateMdiWindowVisibility())); m_undoViewEmptyLabel = i18n("%1: created", m_project->name()); setCaption(m_project->name()); return true; } void MainWin::openProject() { KConfigGroup conf(KSharedConfig::openConfig(), "MainWin"); const QString& dir = conf.readEntry("LastOpenDir", ""); const QString& path = QFileDialog::getOpenFileName(this,i18n("Open project"), dir, i18n("LabPlot Projects (*.lml *.lml.gz *.lml.bz2 *.lml.xz *.LML *.LML.GZ *.LML.BZ2 *.LML.XZ)")); if (path.isEmpty())// "Cancel" was clicked return; this->openProject(path); //save new "last open directory" int pos = path.lastIndexOf(QDir::separator()); if (pos != -1) { const QString& newDir = path.left(pos); if (newDir != dir) conf.writeEntry("LastOpenDir", newDir); } } void MainWin::openProject(const QString& filename) { if (filename == m_currentFileName) { KMessageBox::information(this, i18n("The project file %1 is already opened.", filename), i18n("Open project")); return; } if (!newProject()) return; WAIT_CURSOR; QElapsedTimer timer; timer.start(); const bool rc = m_project->load(filename); if (!rc) { closeProject(); RESET_CURSOR; return; } m_currentFileName = filename; m_project->setFileName(filename); m_project->undoStack()->clear(); m_undoViewEmptyLabel = i18n("%1: opened", m_project->name()); m_recentProjectsAction->addUrl( QUrl(filename) ); setCaption(m_project->name()); updateGUIOnProjectChanges(); updateGUI(); //there are most probably worksheets or spreadsheets in the open project -> update the GUI m_saveAction->setEnabled(false); statusBar()->showMessage( i18n("Project successfully opened (in %1 seconds).", (float)timer.elapsed()/1000) ); if (m_autoSaveActive) m_autoSaveTimer.start(); RESET_CURSOR; } void MainWin::openRecentProject(const QUrl& url) { if (url.isLocalFile()) // fix for Windows this->openProject(url.toLocalFile()); else this->openProject(url.path()); } /*! Closes the current project, if available. Return \c true, if the project was closed. */ bool MainWin::closeProject() { if (m_project == 0) return true; //nothing to close if (warnModified()) return false; delete m_aspectTreeModel; m_aspectTreeModel = 0; delete m_project; m_project = 0; m_currentFileName = ""; //update the UI if we're just closing a project //and not closing(quitting) the application if (!m_closing) { m_projectExplorerDock->hide(); m_propertiesDock->hide(); m_currentAspect = 0; m_currentFolder = 0; updateGUIOnProjectChanges(); if (m_autoSaveActive) m_autoSaveTimer.stop(); } return true; } bool MainWin::saveProject() { const QString& fileName = m_project->fileName(); if (fileName.isEmpty()) return saveProjectAs(); else return save(fileName); } bool MainWin::saveProjectAs() { KConfigGroup conf(KSharedConfig::openConfig(), "MainWin"); const QString& dir = conf.readEntry("LastOpenDir", ""); QString path = QFileDialog::getSaveFileName(this, i18n("Save project as"), dir, i18n("LabPlot Projects (*.lml *.lml.gz *.lml.bz2 *.lml.xz *.LML *.LML.GZ *.LML.BZ2 *.LML.XZ)")); if (path.isEmpty())// "Cancel" was clicked return false; if (path.contains(QLatin1String(".lml"), Qt::CaseInsensitive) == false) path.append(QLatin1String(".lml")); //save new "last open directory" int pos = path.lastIndexOf(QDir::separator()); if (pos != -1) { const QString& newDir = path.left(pos); if (newDir != dir) conf.writeEntry("LastOpenDir", newDir); } return save(path); } /*! * auxillary function that does the actual saving of the project */ bool MainWin::save(const QString& fileName) { WAIT_CURSOR; // use file ending to find out how to compress file QIODevice* file; // if ending is .lml, do gzip compression anyway if (fileName.endsWith(QLatin1String(".lml"))) file = new KCompressionDevice(fileName, KCompressionDevice::GZip); else file = new KFilterDev(fileName); if (file == 0) file = new QFile(fileName); bool ok; if (file->open(QIODevice::WriteOnly)) { m_project->setFileName(fileName); QXmlStreamWriter writer(file); m_project->save(&writer); m_project->undoStack()->clear(); m_project->setChanged(false); file->close(); setCaption(m_project->name()); statusBar()->showMessage(i18n("Project saved")); m_saveAction->setEnabled(false); m_recentProjectsAction->addUrl( QUrl(fileName) ); ok = true; //if the project dock is visible, refresh the shown content //(version and modification time might have been changed) if (stackedWidget->currentWidget() == projectDock) projectDock->setProject(m_project); //we have a file name now // -> auto save can be activated now if not happened yet if (m_autoSaveActive && !m_autoSaveTimer.isActive()) m_autoSaveTimer.start(); } else { KMessageBox::error(this, i18n("Sorry. Could not open file for writing.")); ok = false; } delete file; RESET_CURSOR; return ok; } /*! * automatically saves the project in the specified time interval. */ void MainWin::autoSaveProject() { //don't auto save when there are no changes or the file name //was not provided yet (the project was never explicitly saved yet). if ( !m_project->hasChanged() || m_project->fileName().isEmpty()) return; this->saveProject(); } /*! prints the current sheet (worksheet, spreadsheet or matrix) */ void MainWin::print() { QMdiSubWindow* win = m_mdiArea->currentSubWindow(); if (!win) return; AbstractPart* part = dynamic_cast(win)->part(); statusBar()->showMessage(i18n("Preparing printing of %1", part->name())); if (part->printView()) statusBar()->showMessage(i18n("%1 printed", part->name())); else statusBar()->showMessage(""); } void MainWin::printPreview() { QMdiSubWindow* win = m_mdiArea->currentSubWindow(); if (!win) return; AbstractPart* part = dynamic_cast(win)->part(); statusBar()->showMessage(i18n("Preparing printing of %1", part->name())); if (part->printPreview()) statusBar()->showMessage(i18n("%1 printed", part->name())); else statusBar()->showMessage(""); } /**************************************************************************************/ /*! adds a new Folder to the project. */ void MainWin::newFolder() { Folder* folder = new Folder(i18n("Folder")); this->addAspectToProject(folder); } /*! adds a new Workbook to the project. */ void MainWin::newWorkbook() { Workbook* workbook = new Workbook(0, i18n("Workbook")); this->addAspectToProject(workbook); } /*! adds a new Datapicker to the project. */ void MainWin::newDatapicker() { Datapicker* datapicker = new Datapicker(0, i18n("Datapicker")); this->addAspectToProject(datapicker); } /*! adds a new Spreadsheet to the project. */ void MainWin::newSpreadsheet() { Spreadsheet* spreadsheet = new Spreadsheet(0, i18n("Spreadsheet")); //if the current active window is a workbook and no folder/project is selected in the project explorer, //add the new spreadsheet to the workbook Workbook* workbook = activeWorkbook(); if (workbook) { QModelIndex index = m_projectExplorer->currentIndex(); AbstractAspect* aspect = static_cast(index.internalPointer()); if (!aspect->inherits("Folder")) { workbook->addChild(spreadsheet); return; } } this->addAspectToProject(spreadsheet); } /*! adds a new Matrix to the project. */ void MainWin::newMatrix() { Matrix* matrix = new Matrix(0, i18n("Matrix")); //if the current active window is a workbook and no folder/project is selected in the project explorer, //add the new matrix to the workbook Workbook* workbook = activeWorkbook(); if (workbook) { QModelIndex index = m_projectExplorer->currentIndex(); AbstractAspect* aspect = static_cast(index.internalPointer()); if (!aspect->inherits("Folder")) { workbook->addChild(matrix); return; } } this->addAspectToProject(matrix); } /*! adds a new Worksheet to the project. */ void MainWin::newWorksheet() { Worksheet* worksheet = new Worksheet(0, i18n("Worksheet")); this->addAspectToProject(worksheet); } /*! adds a new Note to the project. */ void MainWin::newNotes() { Note* notes = new Note(i18n("Note")); this->addAspectToProject(notes); } /*! returns a pointer to a Workbook-object, if the currently active Mdi-Subwindow is \a WorkbookView. Otherwise returns \a 0. */ Workbook* MainWin::activeWorkbook() const { QMdiSubWindow* win = m_mdiArea->currentSubWindow(); if (!win) return 0; AbstractPart* part = dynamic_cast(win)->part(); Q_ASSERT(part); return dynamic_cast(part); } /*! returns a pointer to a Datapicker-object, if the currently active Mdi-Subwindow is \a DatapickerView. Otherwise returns \a 0. */ Datapicker* MainWin::activeDatapicker() const { QMdiSubWindow* win = m_mdiArea->currentSubWindow(); if (!win) return 0; AbstractPart* part = dynamic_cast(win)->part(); Q_ASSERT(part); return dynamic_cast(part); } /*! returns a pointer to a \c Spreadsheet object, if the currently active Mdi-Subwindow or if the currently selected tab in a \c WorkbookView is a \c SpreadsheetView Otherwise returns \c 0. */ Spreadsheet* MainWin::activeSpreadsheet() const { QMdiSubWindow* win = m_mdiArea->currentSubWindow(); if (!win) return 0; AbstractPart* part = dynamic_cast(win)->part(); Q_ASSERT(part); Spreadsheet* spreadsheet = 0; const Workbook* workbook = dynamic_cast(part); if (workbook) { spreadsheet = workbook->currentSpreadsheet(); if (!spreadsheet) { //potentially, the spreadsheet was not selected in workbook yet since the selection in project explorer //arrives in workbook's slot later than in this function //->check whether we have a spreadsheet or one of its columns currently selected in the project explorer spreadsheet = dynamic_cast(m_currentAspect); if (!spreadsheet) { if (m_currentAspect->parentAspect()) spreadsheet = dynamic_cast(m_currentAspect->parentAspect()); } } } else spreadsheet = dynamic_cast(part); return spreadsheet; } /*! returns a pointer to a \c Matrix object, if the currently active Mdi-Subwindow or if the currently selected tab in a \c WorkbookView is a \c MatrixView Otherwise returns \c 0. */ Matrix* MainWin::activeMatrix() const { QMdiSubWindow* win = m_mdiArea->currentSubWindow(); if (!win) return 0; AbstractPart* part = dynamic_cast(win)->part(); Q_ASSERT(part); Matrix* matrix = 0; Workbook* workbook = dynamic_cast(part); if (workbook) { matrix = workbook->currentMatrix(); if (!matrix) { //potentially, the matrix was not selected in workbook yet since the selection in project explorer //arrives in workbook's slot later than in this function //->check whether we have a matrix currently selected in the project explorer matrix = dynamic_cast(m_currentAspect); } } else matrix = dynamic_cast(part); return matrix; } /*! returns a pointer to a Worksheet-object, if the currently active Mdi-Subwindow is \a WorksheetView Otherwise returns \a 0. */ Worksheet* MainWin::activeWorksheet() const { QMdiSubWindow* win = m_mdiArea->currentSubWindow(); if (!win) return 0; AbstractPart* part = dynamic_cast(win)->part(); Q_ASSERT(part); return dynamic_cast(part); } #ifdef HAVE_CANTOR_LIBS /* adds a new Cantor Spreadsheet to the project. */ void MainWin::newCantorWorksheet(QAction* action) { CantorWorksheet* cantorworksheet = new CantorWorksheet(0, action->data().toString()); this->addAspectToProject(cantorworksheet); } /********************************************************************************/ /*! returns a pointer to a CantorWorksheet-object, if the currently active Mdi-Subwindow is \a CantorWorksheetView Otherwise returns \a 0. */ CantorWorksheet* MainWin::activeCantorWorksheet() const { QMdiSubWindow* win = m_mdiArea->currentSubWindow(); if (!win) return 0; AbstractPart* part = dynamic_cast(win)->part(); Q_ASSERT(part); return dynamic_cast(part); } #endif /*! called if there were changes in the project. Adds "changed" to the window caption and activates the save-Action. */ void MainWin::projectChanged() { setCaption(i18n("%1 [Changed]", m_project->name())); m_saveAction->setEnabled(true); m_undoAction->setEnabled(true); return; } void MainWin::handleCurrentSubWindowChanged(QMdiSubWindow* win) { if (!win) return; PartMdiView *view = qobject_cast(win); if (!view) { updateGUI(); return; } if (view == m_currentSubWindow) { //do nothing, if the current sub-window gets selected again. //This event happens, when labplot loses the focus (modal window is opened or the user switches to another application) //and gets it back (modal window is closed or the user switches back to labplot). return; } else m_currentSubWindow = view; updateGUI(); if (!m_suppressCurrentSubWindowChangedEvent) m_projectExplorer->setCurrentAspect(view->part()); } void MainWin::handleAspectAdded(const AbstractAspect* aspect) { const AbstractPart* part = dynamic_cast(aspect); if (part) { //TODO: export, print and print preview should be handled in the views and not in MainWin. connect(part, SIGNAL(exportRequested()), this, SLOT(exportDialog())); connect(part, SIGNAL(printRequested()), this, SLOT(print())); connect(part, SIGNAL(printPreviewRequested()), this, SLOT(printPreview())); connect(part, SIGNAL(showRequested()), this, SLOT(handleShowSubWindowRequested())); } } void MainWin::handleAspectRemoved(const AbstractAspect* parent,const AbstractAspect* before,const AbstractAspect* aspect) { Q_UNUSED(before); Q_UNUSED(aspect); m_projectExplorer->setCurrentAspect(parent); } void MainWin::handleAspectAboutToBeRemoved(const AbstractAspect *aspect) { const AbstractPart *part = qobject_cast(aspect); if (!part) return; const Workbook* workbook = dynamic_cast(aspect->parentAspect()); const Datapicker* datapicker = dynamic_cast(aspect->parentAspect()); if (!datapicker) datapicker = dynamic_cast(aspect->parentAspect()->parentAspect()); if (!workbook && !datapicker) { PartMdiView* win = part->mdiSubWindow(); if (win) m_mdiArea->removeSubWindow(win); } } /*! called when the current aspect in the tree of the project explorer was changed. Selects the new aspect. */ void MainWin::handleCurrentAspectChanged(AbstractAspect *aspect) { if (!aspect) aspect = m_project; // should never happen, just in case m_suppressCurrentSubWindowChangedEvent = true; if (aspect->folder() != m_currentFolder) { m_currentFolder = aspect->folder(); updateMdiWindowVisibility(); } m_currentAspect = aspect; //activate the corresponding MDI sub window for the current aspect activateSubWindowForAspect(aspect); m_suppressCurrentSubWindowChangedEvent = false; updateGUI(); } void MainWin::activateSubWindowForAspect(const AbstractAspect* aspect) const { const AbstractPart* part = dynamic_cast(aspect); if (part) { //for LiveDataSource we currently don't show any view /*if (dynamic_cast(part)) return;*/ PartMdiView* win; //for aspects being children of a Workbook, we show workbook's window, otherwise the window of the selected part const Workbook* workbook = dynamic_cast(aspect->parentAspect()); const Datapicker* datapicker = dynamic_cast(aspect->parentAspect()); if (!datapicker) datapicker = dynamic_cast(aspect->parentAspect()->parentAspect()); if (workbook) win = workbook->mdiSubWindow(); else if (datapicker) win = datapicker->mdiSubWindow(); else win = part->mdiSubWindow(); if (m_mdiArea->subWindowList().indexOf(win) == -1) { if (dynamic_cast(part)) m_mdiArea->addSubWindow(win, Qt::Tool); else m_mdiArea->addSubWindow(win); win->show(); } m_mdiArea->setActiveSubWindow(win); } else { //activate the mdiView of the parent, if a child was selected const AbstractAspect* parent = aspect->parentAspect(); if (parent) { activateSubWindowForAspect(parent); //if the parent's parent is a Workbook (a column of a spreadsheet in workbook was selected), //we need to select the corresponding tab in WorkbookView too if (parent->parentAspect()) { Workbook* workbook = dynamic_cast(parent->parentAspect()); Datapicker* datapicker = dynamic_cast(parent->parentAspect()); if (!datapicker) datapicker = dynamic_cast(parent->parentAspect()->parentAspect()); if (workbook) workbook->childSelected(parent); else if (datapicker) datapicker->childSelected(parent); } } } return; } void MainWin::setMdiWindowVisibility(QAction * action) { m_project->setMdiWindowVisibility((Project::MdiWindowVisibility)(action->data().toInt())); } /*! shows the sub window of a worksheet, matrix or a spreadsheet. Used if the window was closed before and the user asks to show the window again via the context menu in the project explorer. */ void MainWin::handleShowSubWindowRequested() { activateSubWindowForAspect(m_currentAspect); } /*! this is called on a right click on the root folder in the project explorer */ void MainWin::createContextMenu(QMenu* menu) const { menu->addMenu(m_newMenu); //The tabbed view collides with the visibility policy for the subwindows. //Hide the menus for the visibility policy if the tabbed view is used. if (m_mdiArea->viewMode() != QMdiArea::TabbedView) menu->addMenu(m_visibilityMenu); } /*! this is called on a right click on a non-root folder in the project explorer */ void MainWin::createFolderContextMenu(const Folder* folder, QMenu* menu) const { Q_UNUSED(folder); //Folder provides it's own context menu. Add a separator before adding additional actions. menu->addSeparator(); this->createContextMenu(menu); } void MainWin::undo() { WAIT_CURSOR; m_project->undoStack()->undo(); if (m_project->undoStack()->index()==0) { setCaption(m_project->name()); m_saveAction->setEnabled(false); m_undoAction->setEnabled(false); m_project->setChanged(false); } m_redoAction->setEnabled(true); RESET_CURSOR; } void MainWin::redo() { WAIT_CURSOR; m_project->undoStack()->redo(); projectChanged(); if (m_project->undoStack()->index() == m_project->undoStack()->count()) m_redoAction->setEnabled(false); RESET_CURSOR; } /*! Shows/hides mdi sub-windows depending on the current visibility policy. */ void MainWin::updateMdiWindowVisibility() const { QList windows = m_mdiArea->subWindowList(); PartMdiView* part_view; switch (m_project->mdiWindowVisibility()) { case Project::allMdiWindows: for (auto* window : windows) window->show(); break; case Project::folderOnly: for (auto* window : windows) { part_view = qobject_cast(window); Q_ASSERT(part_view); if (part_view->part()->folder() == m_currentFolder) part_view->show(); else part_view->hide(); } break; case Project::folderAndSubfolders: for (auto* window : windows) { part_view = qobject_cast(window); if (part_view->part()->isDescendantOf(m_currentFolder)) part_view->show(); else part_view->hide(); } break; } } void MainWin::toggleDockWidget(QAction* action) const { if (action->objectName() == "toggle_project_explorer_dock") { if (m_projectExplorerDock->isVisible()) m_projectExplorerDock->hide(); else m_projectExplorerDock->show(); } else if (action->objectName() == "toggle_properties_explorer_dock") { if (m_propertiesDock->isVisible()) m_propertiesDock->hide(); else m_propertiesDock->show(); } } void MainWin::projectExplorerDockVisibilityChanged(bool visible) { m_toggleProjectExplorerDockAction->setChecked(visible); } void MainWin::propertiesDockVisibilityChanged(bool visible) { m_togglePropertiesDockAction->setChecked(visible); } void MainWin::toggleFullScreen() { if (this->windowState() == Qt::WindowFullScreen) this->setWindowState(m_lastWindowState); else { m_lastWindowState = this->windowState(); this->showFullScreen(); } } void MainWin::closeEvent(QCloseEvent* event) { m_closing = true; if (!this->closeProject()) { m_closing = false; event->ignore(); } } void MainWin::dragEnterEvent(QDragEnterEvent* event) { event->accept(); } void MainWin::dropEvent(QDropEvent* event) { if (!m_project) newProject(); if (event->mimeData() && !event->mimeData()->urls().isEmpty()) { QUrl url = event->mimeData()->urls().at(0); const QString& f = url.toLocalFile(); //TODO: add later the handling of Origin files here if ( f.endsWith(QLatin1String(".lml")) || f.endsWith(QLatin1String(".lml.gz")) || f.endsWith(QLatin1String(".lml.bz2")) || f.endsWith(QLatin1String(".lml.xz")) || f.endsWith(QLatin1String(".LML")) || f.endsWith(QLatin1String(".LML.GZ")) || f.endsWith(QLatin1String(".LML.BZ2")) || f.endsWith(QLatin1String(".LML.XZ")) ) openProject(f); else importFileDialog(f); event->accept(); } else event->ignore(); } void MainWin::handleSettingsChanges() { const KConfigGroup group = KSharedConfig::openConfig()->group( "Settings_General" ); QMdiArea::ViewMode viewMode = QMdiArea::ViewMode(group.readEntry("ViewMode", 0)); if (m_mdiArea->viewMode() != viewMode) { m_mdiArea->setViewMode(viewMode); if (viewMode == QMdiArea::SubWindowView) this->updateMdiWindowVisibility(); } if (m_mdiArea->viewMode() == QMdiArea::TabbedView) { m_tileWindows->setVisible(false); m_cascadeWindows->setVisible(false); QTabWidget::TabPosition tabPosition = QTabWidget::TabPosition(group.readEntry("TabPosition", 0)); if (m_mdiArea->tabPosition() != tabPosition) m_mdiArea->setTabPosition(tabPosition); } else { m_tileWindows->setVisible(true); m_cascadeWindows->setVisible(true); } //autosave bool autoSave = group.readEntry("AutoSave", 0); if (m_autoSaveActive != autoSave) { m_autoSaveActive = autoSave; if (autoSave) m_autoSaveTimer.start(); else m_autoSaveTimer.stop(); } int interval = group.readEntry("AutoSaveInterval", 1); interval *= 60*1000; if (interval != m_autoSaveTimer.interval()) m_autoSaveTimer.setInterval(interval); } /***************************************************************************************/ /************************************** dialogs ***************************************/ /***************************************************************************************/ /*! shows the dialog with the Undo-history. */ void MainWin::historyDialog() { if (!m_project->undoStack()) return; HistoryDialog* dialog = new HistoryDialog(this, m_project->undoStack(), m_undoViewEmptyLabel); int index = m_project->undoStack()->index(); if (dialog->exec() != QDialog::Accepted) { if (m_project->undoStack()->count() != 0) m_project->undoStack()->setIndex(index); } //disable undo/redo-actions if the history was cleared //(in both cases, when accepted or rejected in the dialog) if (m_project->undoStack()->count() == 0) { m_undoAction->setEnabled(false); m_redoAction->setEnabled(false); } } /*! Opens the dialog to import data to the selected workbook, spreadsheet or matrix */ void MainWin::importFileDialog(const QString& fileName) { DEBUG("MainWin::importFileDialog()"); ImportFileDialog* dlg = new ImportFileDialog(this, false, fileName); // select existing container if (m_currentAspect->inherits("Spreadsheet") || m_currentAspect->inherits("Matrix") || m_currentAspect->inherits("Workbook")) dlg->setCurrentIndex( m_projectExplorer->currentIndex()); else if (m_currentAspect->inherits("Column")) { if (m_currentAspect->parentAspect()->inherits("Spreadsheet")) dlg->setCurrentIndex(m_aspectTreeModel->modelIndexOfAspect(m_currentAspect->parentAspect())); } if (dlg->exec() == QDialog::Accepted) { dlg->importTo(statusBar()); m_project->setChanged(true); } delete dlg; DEBUG("MainWin::importFileDialog() DONE"); } void MainWin::importSqlDialog() { DEBUG("MainWin::importSqlDialog()"); ImportSQLDatabaseDialog* dlg = new ImportSQLDatabaseDialog(this); // select existing container if (m_currentAspect->inherits("Spreadsheet") || m_currentAspect->inherits("Matrix") || m_currentAspect->inherits("Workbook")) dlg->setCurrentIndex( m_projectExplorer->currentIndex()); else if (m_currentAspect->inherits("Column")) { if (m_currentAspect->parentAspect()->inherits("Spreadsheet")) dlg->setCurrentIndex( m_aspectTreeModel->modelIndexOfAspect(m_currentAspect->parentAspect())); } if (dlg->exec() == QDialog::Accepted) { dlg->importTo(statusBar()); m_project->setChanged(true); } delete dlg; DEBUG("MainWin::importSqlDialog() DONE"); } void MainWin::importProjectDialog() { DEBUG("MainWin::importProjectDialog()"); ImportProjectDialog::ProjectType type; if (QObject::sender() == m_importOpjAction) type = ImportProjectDialog::ProjectOrigin; else type = ImportProjectDialog::ProjectLabPlot; ImportProjectDialog* dlg = new ImportProjectDialog(this, type); // set current folder dlg->setCurrentFolder(m_currentFolder); if (dlg->exec() == QDialog::Accepted) { dlg->importTo(statusBar()); m_project->setChanged(true); } delete dlg; DEBUG("MainWin::importProjectDialog() DONE"); } /*! opens the dialog for the export of the currently active worksheet, spreadsheet or matrix. */ void MainWin::exportDialog() { QMdiSubWindow* win = m_mdiArea->currentSubWindow(); if (!win) return; AbstractPart* part = dynamic_cast(win)->part(); if (part->exportView()) statusBar()->showMessage(i18n("%1 exported", part->name())); } void MainWin::editFitsFileDialog() { FITSHeaderEditDialog* editDialog = new FITSHeaderEditDialog(this); if (editDialog->exec() == QDialog::Accepted) { if (editDialog->saved()) statusBar()->showMessage(i18n("FITS files saved")); } } /*! adds a new file data source to the current project. */ void MainWin::newLiveDataSourceActionTriggered() { ImportFileDialog* dlg = new ImportFileDialog(this, true); if (dlg->exec() == QDialog::Accepted) { LiveDataSource* dataSource = new LiveDataSource(0, i18n("Live data source%1", 1), false); dlg->importToLiveDataSource(dataSource, statusBar()); this->addAspectToProject(dataSource); } delete dlg; } void MainWin::addAspectToProject(AbstractAspect* aspect) { const QModelIndex& index = m_projectExplorer->currentIndex(); if (index.isValid()) { AbstractAspect* parent = static_cast(index.internalPointer()); parent->folder()->addChild(aspect); } else m_project->addChild(aspect); } void MainWin::settingsDialog() { SettingsDialog* dlg = new SettingsDialog(this); connect (dlg, SIGNAL(settingsChanged()), this, SLOT(handleSettingsChanges())); dlg->exec(); } diff --git a/src/kdefrontend/datasources/ImportOpj.cpp b/src/kdefrontend/datasources/ImportOpj.cpp deleted file mode 100644 index 31053ba05..000000000 --- a/src/kdefrontend/datasources/ImportOpj.cpp +++ /dev/null @@ -1,719 +0,0 @@ -/*************************************************************************** - File : ImportOpj.cpp - Project : LabPlot - Description : Import Origin project - -------------------------------------------------------------------- - Copyright : (C) 2017 Stefan Gerlach (stefan.gerlach@uni.kn) - adapted from SciDAVis (importOPJ.cpp) - ***************************************************************************/ - -/*************************************************************************** - * * - * 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 "ImportOpj.h" -#include "backend/lib/macros.h" -#include "backend/core/Project.h" -#include "backend/core/Workbook.h" -#include "backend/core/column/Column.h" -#include "backend/spreadsheet/Spreadsheet.h" -#include "backend/matrix/Matrix.h" -#include "backend/note/Note.h" -#include "backend/worksheet/Worksheet.h" -#include "backend/worksheet/plots/cartesian/CartesianPlot.h" -#include "backend/worksheet/plots/cartesian/CartesianPlotLegend.h" -#include "backend/worksheet/TextLabel.h" -#include "backend/core/datatypes/Double2StringFilter.h" -#include "backend/core/datatypes/DateTime2StringFilter.h" - -#include - -#include -#include -#include - -/*! - \class ImportOpj - \brief Importing an Origin project. - - \ingroup kdefrontend - */ -ImportOpj::ImportOpj(Folder *folder, const QString& filename, bool preview) : p(folder) { - Q_UNUSED(preview); - DEBUG("Opj import started ..."); - - OriginFile opj((const char *)filename.toLocal8Bit()); - int status = opj.parse(); - WARN("Parsing done with status " << status); -// if (status != 0) -// return; - DEBUG("Starting conversion ..."); - - importTables(opj); -//TODO importGraphs(opj); -//TODO importNotes(opj); -// if(filename.endsWith(".opj", Qt::CaseInsensitive)) -// createProjectTree(opj); - -} - -int ImportOpj::importTables(const OriginFile &opj) { - // excels (origin workbook with one or more sheets) - for (unsigned int e = 0; e < opj.excelCount(); ++e) { - DEBUG("Reading Spreadsheet " << e); - Origin::Excel excelwb = opj.excel(e); - if (excelwb.sheets.size() == 1) { // single sheet -> spreadsheet - Origin::SpreadSheet spread = excelwb.sheets[0]; - spread.name = excelwb.name; - spread.label = excelwb.label; - importSpreadsheet(0, opj, spread); - } - else { // multiple sheets -> workbook - Workbook *workbook = new Workbook(0, excelwb.name.c_str() + QString(" - ") + excelwb.label.c_str()); - for (unsigned int s = 0; s < excelwb.sheets.size(); ++s) { - Origin::SpreadSheet spread = excelwb.sheets[s]; - importSpreadsheet(workbook, opj, spread); - } - p->addChildFast(workbook); - } - } - - // matrices - for (unsigned int m = 0; m < opj.matrixCount(); ++m) { - Origin::Matrix matrix = opj.matrix(m); - importMatrix(opj, matrix); - } - - return 0; -} - -int ImportOpj::importSpreadsheet(Workbook* workbook, const OriginFile &opj, const Origin::SpreadSheet &spread) { - Q_UNUSED(opj); - int cols = spread.columns.size(); - int rows = spread.maxRows; - //TODO - if (rows > 1000) - rows = 1000; - if (!cols) // do not create spreadsheet without columns - return -1; - - //TODO QLocale locale = mw->locale(); - Spreadsheet* spreadsheet; - if (workbook == 0 && spread.label.length() > 0) // single sheet with label (long name) - spreadsheet = new Spreadsheet(0, spread.name.c_str() + QString(" - ") + spread.label.c_str()); - else // multiple sheets (TODO: name of sheets are not saved in liborigin: "Sheet1", "Sheet2", ...) - spreadsheet = new Spreadsheet(0, spread.name.c_str()); - DEBUG("OK rows = " << rows); - spreadsheet->setRowCount(rows); - DEBUG("OK DONE"); - spreadsheet->setColumnCount(cols); - - int scaling_factor = 10; //in Origin width is measured in characters while here in pixels --- need to be accurate - for (int j = 0; j < cols; ++j) { - Origin::SpreadColumn column = spread.columns[j]; - Column *col = spreadsheet->column(j); - - QString name(column.name.c_str()); - col->setName(name.replace(QRegExp(".*_"),"")); - if (column.command.size() > 0) - col->setFormula(Interval(0, rows), QString(column.command.c_str())); - col->setComment(QString(column.comment.c_str())); - col->setWidth((int)column.width * scaling_factor); - - switch (column.type) { - case Origin::SpreadColumn::X: - col->setPlotDesignation(AbstractColumn::X); - break; - case Origin::SpreadColumn::Y: - col->setPlotDesignation(AbstractColumn::Y); - break; - case Origin::SpreadColumn::Z: - col->setPlotDesignation(AbstractColumn::Z); - break; - case Origin::SpreadColumn::XErr: - col->setPlotDesignation(AbstractColumn::XError); - break; - case Origin::SpreadColumn::YErr: - col->setPlotDesignation(AbstractColumn::YError); - break; - case Origin::SpreadColumn::Label: - case Origin::SpreadColumn::NONE: - default: - col->setPlotDesignation(AbstractColumn::NoDesignation); - } - - QString format; - switch(column.valueType) { - case Origin::Numeric: - case Origin::TextNumeric: { - /* TODO: check this - A TextNumeric column in Origin is a column whose filled cells contain either a double or a string. - Here there is no equivalent column type. - Set the column type as 'Numeric' or 'Text' depending on the type of first element in column. - IDEA: Add a "per column" flag, settable at import dialog, to choose between both types. - */ - double datavalue; - bool setAsText = false; - col->setColumnMode(AbstractColumn::Numeric); - //printf("column has %ld rows\n", column.data.size()); - for (int i = 0; i < std::min((int)column.data.size(), rows); ++i) { - Origin::variant v(column.data.at(i)); - //printf("i=%d type = %d\n", i, v.type); - if (v.type() == Origin::Variant::V_DOUBLE) { - //printf("DOUBLE !\n"); - datavalue = v.as_double(); - //printf("datavalue = %g\n", datavalue); - if (datavalue == _ONAN) continue; // mark for empty cell - if (!setAsText) - col->setValueAt(i, datavalue); -//TODO else // convert double to string for Text columns -// col->setTextAt(i, locale.toString(datavalue, 'g', 16)); - } else if (v.type() == Origin::Variant::V_STRING) { // string - //printf("STRING !\n"); - if (!setAsText && i == 0) { - col->setColumnMode(AbstractColumn::Text); - setAsText = true; - } - col->setTextAt(i, v.as_string()); - } else { - printf("ERROR: data type = %d unknown!\n", v.type()); - } - } - if (column.numericDisplayType != 0) { - int f = 0; - switch(column.valueTypeSpecification) { - case Origin::Decimal: - f=1; - break; - case Origin::Scientific: - f=2; - break; - case Origin::Engineering: - case Origin::DecimalWithMarks: - break; - } - - Double2StringFilter *filter = static_cast(col->outputFilter()); - filter->setNumericFormat(f); - filter->setNumDigits(column.decimalPlaces); - } - break; - } - case Origin::Text: - col->setColumnMode(AbstractColumn::Text); - for (int i = 0; i < min((int)column.data.size(), rows); ++i) - col->setTextAt(i, column.data[i].as_string()); - break; - case Origin::Time: { - switch(column.valueTypeSpecification + 128) { - case Origin::TIME_HH_MM: - format="hh:mm"; - break; - case Origin::TIME_HH: - format="hh"; - break; - case Origin::TIME_HH_MM_SS: - format="hh:mm:ss"; - break; - case Origin::TIME_HH_MM_SS_ZZ: - format="hh:mm:ss.zzz"; - break; - case Origin::TIME_HH_AP: - format="hh ap"; - break; - case Origin::TIME_HH_MM_AP: - format="hh:mm ap"; - break; - case Origin::TIME_MM_SS: - format="mm:ss"; - break; - case Origin::TIME_MM_SS_ZZ: - format="mm:ss.zzz"; - break; - case Origin::TIME_HHMM: - format="hhmm"; - break; - case Origin::TIME_HHMMSS: - format="hhmmss"; - break; - case Origin::TIME_HH_MM_SS_ZZZ: - format="hh:mm:ss.zzz"; - break; - } - - for (int i = 0; i < min((int)column.data.size(), rows); ++i) - col->setValueAt(i, column.data[i].as_double()); - col->setColumnMode(AbstractColumn::DateTime); - - DateTime2StringFilter *filter = static_cast(col->outputFilter()); - filter->setFormat(format); - break; - } - case Origin::Date: { - switch(column.valueTypeSpecification) { - case Origin::DATE_DD_MM_YYYY: - format="dd/MM/yyyy"; - break; - case Origin::DATE_DD_MM_YYYY_HH_MM: - format="dd/MM/yyyy HH:mm"; - break; - case Origin::DATE_DD_MM_YYYY_HH_MM_SS: - format="dd/MM/yyyy HH:mm:ss"; - break; - case Origin::DATE_DDMMYYYY: - case Origin::DATE_DDMMYYYY_HH_MM: - case Origin::DATE_DDMMYYYY_HH_MM_SS: - format="dd.MM.yyyy"; - break; - case Origin::DATE_MMM_D: - format="MMM d"; - break; - case Origin::DATE_M_D: - format="M/d"; - break; - case Origin::DATE_D: - format="d"; - break; - case Origin::DATE_DDD: - case Origin::DATE_DAY_LETTER: - format="ddd"; - break; - case Origin::DATE_YYYY: - format="yyyy"; - break; - case Origin::DATE_YY: - format="yy"; - break; - case Origin::DATE_YYMMDD: - case Origin::DATE_YYMMDD_HH_MM: - case Origin::DATE_YYMMDD_HH_MM_SS: - case Origin::DATE_YYMMDD_HHMM: - case Origin::DATE_YYMMDD_HHMMSS: - format="yyMMdd"; - break; - case Origin::DATE_MMM: - case Origin::DATE_MONTH_LETTER: - format="MMM"; - break; - case Origin::DATE_M_D_YYYY: - format="M-d-yyyy"; - break; - default: - format="dd.MM.yyyy"; - } - - for (int i = 0; i < min((int)column.data.size(), rows); ++i) - col->setValueAt(i, column.data[i].as_double()); - col->setColumnMode(AbstractColumn::DateTime); - - DateTime2StringFilter *filter = static_cast(col->outputFilter()); - filter->setFormat(format); - break; - } - case Origin::Month: { - switch (column.valueTypeSpecification) { - case Origin::MONTH_MMM: - format = "MMM"; - break; - case Origin::MONTH_MMMM: - format = "MMMM"; - break; - case Origin::MONTH_LETTER: - format = "M"; - break; - } - - for (int i = 0; i < min((int)column.data.size(), rows); ++i) - col->setValueAt(i, column.data[i].as_double()); - col->setColumnMode(AbstractColumn::Month); - - DateTime2StringFilter *filter = static_cast(col->outputFilter()); - filter->setFormat(format); - break; - } - case Origin::Day: { - switch(column.valueTypeSpecification) { - case Origin::DAY_DDD: - format = "ddd"; - break; - case Origin::DAY_DDDD: - format = "dddd"; - break; - case Origin::DAY_LETTER: - format = "d"; - break; - } - - for (int i = 0; i < min((int)column.data.size(), rows); ++i) - col->setValueAt(i, column.data[i].as_double()); - col->setColumnMode(AbstractColumn::Day); - - DateTime2StringFilter *filter = static_cast(col->outputFilter()); - filter->setFormat(format); - break; - } - case Origin::ColumnHeading: - case Origin::TickIndexedDataset: - case Origin::Categorical: - break; - } - } - - //TODO -// if (spread.hidden || spread.loose) -// mw->hideWindow(spreadsheet); - - if (workbook == 0) // single sheet - p->addChildFast(spreadsheet); - else // multiple sheets - workbook->addChild(spreadsheet); - - return 0; -} - -int ImportOpj::importMatrix(const OriginFile &opj, const Origin::Matrix &matrix) { - Q_UNUSED(opj); - - unsigned int layers = matrix.sheets.size(); - int scaling_factor = 10; //in Origin width is measured in characters while here in pixels --- need to be accurate - for (unsigned int l = 0; l < layers; ++l) { - Origin::MatrixSheet layer = matrix.sheets[l]; - int colCount = layer.columnCount; - int rowCount = layer.rowCount; - - Matrix* m = new Matrix(0, matrix.name.c_str()); - m->setRowCount(rowCount); - m->setColumnCount(colCount); - if (!m) - return false; - m->setFormula(layer.command.c_str()); - for (int j = 0; j < colCount; j++) - m->setColumnWidth(j, layer.width * scaling_factor); - - for (int i = 0; i < rowCount; i++) { - for (int j = 0; j < colCount; j++) { - m->setCell(i, j, layer.data[j + i*colCount]); - } - } - - char format = 'g'; - int prec = 6; - switch (layer.valueTypeSpecification) { - case 0: //Decimal 1000 - format='f'; - prec = layer.decimalPlaces; - break; - case 1: //Scientific - format='e'; - prec = layer.decimalPlaces; - break; - case 2: //Engineering - case 3: //Decimal 1,000 - format='g'; - prec = layer.significantDigits; - break; - } - - //TODO: prec not support by Matrix - Q_UNUSED(prec); - m->setNumericFormat(format); - - p->addChildFast(m); - } - - return 0; -} - -int ImportOpj::importNotes(const OriginFile &opj) { -// int visible_count = 0; - for(unsigned int n = 0; n < opj.noteCount(); ++n) { - Origin::Note _note = opj.note(n); - QString name = _note.name.c_str(); - QRegExp rx("^@(\\S+)$"); - if(rx.indexIn(name) == 0) - name = name.mid(2, name.length() - 3); - Note *note = new Note(name); - if(!note) - return -1; - //note->setWindowLabel(_note.label.c_str()); - note->setNote(QString(_note.text.c_str())); - - // TODO - //cascade the notes - //int dx = 20; - //int dy = note->parentWidget()->frameGeometry().height() - note->height(); - //note->parentWidget()->move(QPoint(visible_count*dx+xoffset*OBJECTXOFFSET, visible_count*dy)); - - p->addChildFast(note); - -// visible_count++; - } -// if(visible_count > 0) -// xoffset++; - return 0; -} - -int ImportOpj::importGraphs(const OriginFile &opj) { - for(unsigned int g = 0; g < opj.graphCount(); ++g) { - Origin::Graph graph = opj.graph(g); - Worksheet *worksheet = new Worksheet(0, graph.name.c_str()); - if (!worksheet) - return -1; - -// worksheet->hide();//!hack used in order to avoid resize and repaint events - worksheet->setComment(graph.label.c_str()); - for (const auto& layer: graph.layers) { - CartesianPlot* plot = new CartesianPlot(""); - if (!plot) - return -2; - - if (!layer.legend.text.empty()) { - CartesianPlotLegend* legend = new CartesianPlotLegend(plot, ""); - TextLabel* title = new TextLabel(legend->name(), TextLabel::PlotLegendTitle); - DEBUG("TEXT =" << layer.legend.text.c_str()); - QDEBUG("PARSED TEXT =" << parseOriginText(QString::fromLocal8Bit(layer.legend.text.c_str()))); - title->setText(parseOriginText(QString::fromLocal8Bit(layer.legend.text.c_str()))); - //legend->title() = title; - legend->addChild(title); - plot->addChild(legend); - } - - // TODO: we only support one legend - //add texts -/* for (const auto &s: layer.texts) { - DEBUG("EXTRA TEXT =" << s.text.c_str()); - // plot->newLegend(parseOriginText(QString::fromLocal8Bit(s.text.c_str()))); - } -*/ -// int auto_color = 0; -// int style = 0; - for (const auto& curve: layer.curves) { - QString data(curve.dataName.c_str()); -// int color = 0; - - switch(curve.type) { - case Origin::GraphCurve::Line: -// style = Graph::Line; - break; - case Origin::GraphCurve::Scatter: -// style = Graph::Scatter; - break; - case Origin::GraphCurve::LineSymbol: -// style = Graph::LineSymbols; - break; - case Origin::GraphCurve::ErrorBar: - case Origin::GraphCurve::XErrorBar: -// style = Graph::ErrorBars; - break; - case Origin::GraphCurve::Column: -// style = Graph::VerticalBars; - break; - case Origin::GraphCurve::Bar: -// style = Graph::HorizontalBars; - break; - case Origin::GraphCurve::Histogram: -// style = Graph::Histogram; - break; - default: - continue; - } - -/* QString tableName; - switch(data[0].toAscii()) { - case 'T': - case 'E': { - tableName = data.right(data.length() - 2); - Table* table = mw->table(tableName); - if (!table) - break; - if(style == Graph::ErrorBars) { - int flags=_curve.symbolType; - graph->addErrorBars(QString("%1_%2").arg(tableName, _curve.xColumnName.c_str()), table, QString("%1_%2").arg(tableName, _curve.yColumnName.c_str()), - ((flags&0x10)==0x10?0:1), ceil(_curve.lineWidth), ceil(_curve.symbolSize), QColor(Qt::black), - (flags&0x40)==0x40, (flags&2)==2, (flags&1)==1); - } else if(style == Graph::Histogram) { - graph->insertCurve(table, QString("%1_%2").arg(tableName, _curve.yColumnName.c_str()), style); - } else { - graph->insertCurve(table, QString("%1_%2").arg(tableName, _curve.xColumnName.c_str()), QString("%1_%2").arg(tableName, _curve.yColumnName.c_str()), style); - } - break; - } - //TODO - } -*/ - -/* CurveLayout cl = graph->initCurveLayout(style, layer.curves.size()); - cl.sSize = ceil(_curve.symbolSize*0.5); - cl.penWidth = _curve.symbolThickness; - color = _curve.symbolColor.regular; - if((style == Graph::Scatter || style == Graph::LineSymbols) && color == 0xF7) // 0xF7 -Automatic color - color = auto_color++; - cl.symCol = color; - switch(_curve.symbolType & 0xFF) { - case 0: //NoSymbol - cl.sType = 0; - break; - //TODO - } -*/ - - //TODO - - } - - worksheet->addChild(plot); - } - - p->addChildFast(worksheet); - } - - return 0; -} - -QString ImportOpj::parseOriginText(const QString &str) { - QStringList lines = str.split("\n"); - QString text = ""; - for (int i = 0; i < lines.size(); ++i) { - if(i > 0) - text.append("\n"); - text.append(parseOriginTags(lines[i])); - } - - return text; -} - -QString strreverse(const QString &str) { //QString reversing - QByteArray ba = str.toLocal8Bit(); - std::reverse(ba.begin(), ba.end()); - - return QString(ba); -} - -// taken from SciDAVis -QString ImportOpj::parseOriginTags(const QString &str) { - QString line = str; - - //replace \l(...) and %(...) tags - QRegExp rxline("\\\\\\s*l\\s*\\(\\s*\\d+\\s*\\)"); - QRegExp rxcol("\\%\\(\\d+\\)"); - int pos = rxline.indexIn(line); - while (pos > -1) { - QString value = rxline.cap(0); - int len=value.length(); - value.replace(QRegExp(" "),""); - value="\\c{"+value.mid(3,value.length()-4)+"}"; - line.replace(pos, len, value); - pos = rxline.indexIn(line); - } - //Lookbehind conditions are not supported - so need to reverse string - QRegExp rx("\\)[^\\)\\(]*\\((?!\\s*[buig\\+\\-]\\s*\\\\)"); - QRegExp rxfont("\\)[^\\)\\(]*\\((?![^\\:]*\\:f\\s*\\\\)"); - QString linerev = strreverse(line); - QString lBracket=strreverse("&lbracket;"); - QString rBracket=strreverse("&rbracket;"); - QString ltagBracket=strreverse("<agbracket;"); - QString rtagBracket=strreverse("&rtagbracket;"); - int pos1 = rx.indexIn(linerev); - int pos2 = rxfont.indexIn(linerev); - - while (pos1>-1 || pos2>-1) { - if(pos1==pos2) { - QString value = rx.cap(0); - int len=value.length(); - value=rBracket+value.mid(1,len-2)+lBracket; - linerev.replace(pos1, len, value); - } - else if ((pos1>pos2&&pos2!=-1)||pos1==-1) { - QString value = rxfont.cap(0); - int len=value.length(); - value=rtagBracket+value.mid(1,len-2)+ltagBracket; - linerev.replace(pos2, len, value); - } - else if ((pos2>pos1&&pos1!=-1)||pos2==-1) { - QString value = rx.cap(0); - int len=value.length(); - value=rtagBracket+value.mid(1,len-2)+ltagBracket; - linerev.replace(pos1, len, value); - } - - pos1=rx.indexIn(linerev); - pos2=rxfont.indexIn(linerev); - } - linerev.replace(ltagBracket, "("); - linerev.replace(rtagBracket, ")"); - - line = strreverse(linerev); - - - //replace \b(...), \i(...), \u(...), \g(...), \+(...), \-(...), \f:font(...) tags - const QString rxstr[] = { "\\\\\\s*b\\s*\\(", "\\\\\\s*i\\s*\\(", "\\\\\\s*u\\s*\\(", "\\\\\\s*g\\s*\\(", "\\\\\\s*\\+\\s*\\(", "\\\\\\s*\\-\\s*\\(", "\\\\\\s*f\\:[^\\(]*\\("}; - - int postag[]={0,0,0,0,0,0,0}; - QString ltag[]={"","","","","","",""}; - QString rtag[]={"","","","","","",""}; - QRegExp rxtags[7]; - for(int i=0; i<7; ++i) - rxtags[i].setPattern(rxstr[i]+"[^\\(\\)]*\\)"); - - bool flag=true; - while(flag) { - for(int i=0; i<7; ++i) { - postag[i] = rxtags[i].indexIn(line); - while (postag[i] > -1) { - QString value = rxtags[i].cap(0); - int len = value.length(); - pos2 = value.indexOf("("); - if(i<6) - value=ltag[i]+value.mid(pos2+1,len-pos2-2)+rtag[i]; - else - { - int posfont=value.indexOf("f:"); - value=ltag[i].arg(value.mid(posfont+2,pos2-posfont-2))+value.mid(pos2+1,len-pos2-2)+rtag[i]; - } - line.replace(postag[i], len, value); - postag[i] = rxtags[i].indexIn(line); - } - } - flag=false; - for(int i=0; i<7; ++i) { - if(rxtags[i].indexIn(line)>-1) { - flag=true; - break; - } - } - } - - //replace unclosed tags - for(int i=0; i<6; ++i) - line.replace(QRegExp(rxstr[i]), ltag[i]); - rxfont.setPattern(rxstr[6]); - pos = rxfont.indexIn(line); - while (pos > -1) { - QString value = rxfont.cap(0); - int len=value.length(); - int posfont=value.indexOf("f:"); - value=ltag[6].arg(value.mid(posfont+2,len-posfont-3)); - line.replace(pos, len, value); - pos = rxfont.indexIn(line); - } - - line.replace("&lbracket;", "("); - line.replace("&rbracket;", ")"); - - return line; -} diff --git a/src/kdefrontend/datasources/ImportOpj.h b/src/kdefrontend/datasources/ImportOpj.h deleted file mode 100644 index c09ad69ef..000000000 --- a/src/kdefrontend/datasources/ImportOpj.h +++ /dev/null @@ -1,55 +0,0 @@ -/*************************************************************************** - File : ImportOpj.h - Project : LabPlot - Description : import Origin project - -------------------------------------------------------------------- - Copyright : (C) 2017 Stefan Gerlach (stefan.gerlach@uni.kn) - - ***************************************************************************/ - -/*************************************************************************** - * * - * 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 IMPORTOPJ_H -#define IMPORTOPJ_H - -#include - -class Folder; -class Workbook; -class QString; - -class ImportOpj { - -public: - explicit ImportOpj(Folder*, const QString& filename, bool preview); - ~ImportOpj() {}; - -private: - int importTables(const OriginFile &opj); - int importSpreadsheet(Workbook* workbook, const OriginFile &opj, const Origin::SpreadSheet &spread); - int importMatrix(const OriginFile &opj, const Origin::Matrix &matrix); - int importNotes(const OriginFile &opj); - int importGraphs(const OriginFile &opj); - QString parseOriginText(const QString &str); - QString parseOriginTags(const QString &str); - Folder *p; -}; - -#endif //IMPORTOPJ_H