diff --git a/src/commonfrontend/worksheet/WorksheetView.cpp b/src/commonfrontend/worksheet/WorksheetView.cpp index 6d51bda1c..92c5eda33 100644 --- a/src/commonfrontend/worksheet/WorksheetView.cpp +++ b/src/commonfrontend/worksheet/WorksheetView.cpp @@ -1,2069 +1,2069 @@ /*************************************************************************** File : WorksheetView.cpp Project : LabPlot Description : Worksheet view -------------------------------------------------------------------- Copyright : (C) 2009-2019 Alexander Semke (alexander.semke@web.de) Copyright : (C) 2016-2018 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 "commonfrontend/worksheet/WorksheetView.h" #include "backend/core/AbstractColumn.h" #include "backend/worksheet/plots/cartesian/Axis.h" #include "backend/worksheet/plots/cartesian/XYCurve.h" #include "backend/worksheet/plots/cartesian/XYCurvePrivate.h" #include "backend/worksheet/Image.h" #include "backend/worksheet/TextLabel.h" #include "commonfrontend/core/PartMdiView.h" #include "kdefrontend/widgets/ThemesWidget.h" #include "kdefrontend/worksheet/GridDialog.h" #include "kdefrontend/worksheet/PresenterWidget.h" #include "kdefrontend/worksheet/DynamicPresenterWidget.h" #include "backend/lib/trace.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_MAC #include "3rdparty/kdmactouchbar/src/kdmactouchbar.h" #endif #include /** * \class WorksheetView * \brief Worksheet view */ /*! Constructur of the class. Creates a view for the Worksheet \c worksheet and initializes the internal model. */ WorksheetView::WorksheetView(Worksheet* worksheet) : QGraphicsView(), m_worksheet(worksheet) { setScene(m_worksheet->scene()); setRenderHint(QPainter::Antialiasing); setRubberBandSelectionMode(Qt::ContainsItemBoundingRect); setTransformationAnchor(QGraphicsView::AnchorViewCenter); setResizeAnchor(QGraphicsView::AnchorViewCenter); setMinimumSize(16, 16); setFocusPolicy(Qt::StrongFocus); if (m_worksheet->useViewSize()) { setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } viewport()->setAttribute( Qt::WA_OpaquePaintEvent ); viewport()->setAttribute( Qt::WA_NoSystemBackground ); setAcceptDrops(true); setCacheMode(QGraphicsView::CacheBackground); m_gridSettings.style = WorksheetView::NoGrid; //signal/slot connections connect(m_worksheet, &Worksheet::requestProjectContextMenu, this, &WorksheetView::createContextMenu); connect(m_worksheet, &Worksheet::itemSelected, this, &WorksheetView::selectItem); connect(m_worksheet, &Worksheet::itemDeselected, this, &WorksheetView::deselectItem); connect(m_worksheet, &Worksheet::requestUpdate, this, &WorksheetView::updateBackground); connect(m_worksheet, &Worksheet::aspectAboutToBeRemoved, this, &WorksheetView::aspectAboutToBeRemoved); connect(m_worksheet, &Worksheet::useViewSizeRequested, this, &WorksheetView::useViewSizeRequested); connect(m_worksheet, &Worksheet::layoutChanged, this, &WorksheetView::layoutChanged); connect(scene(), &QGraphicsScene::selectionChanged, this, &WorksheetView::selectionChanged); //resize the view to make the complete scene visible. //no need to resize the view when the project is being opened, //all views will be resized to the stored values at the end if (!m_worksheet->isLoading()) { float w = Worksheet::convertFromSceneUnits(sceneRect().width(), Worksheet::Unit::Inch); float h = Worksheet::convertFromSceneUnits(sceneRect().height(), Worksheet::Unit::Inch); w *= QApplication::desktop()->physicalDpiX(); h *= QApplication::desktop()->physicalDpiY(); resize(w*1.1, h*1.1); } //rescale to the original size static const float hscale = QApplication::desktop()->physicalDpiX()/(Worksheet::convertToSceneUnits(1, Worksheet::Unit::Inch)); static const float vscale = QApplication::desktop()->physicalDpiY()/(Worksheet::convertToSceneUnits(1, Worksheet::Unit::Inch)); setTransform(QTransform::fromScale(hscale, vscale)); initBasicActions(); } /*! * initializes couple of actions that have shortcuts assigned in the constructor as opposed * to other actions in initAction() that are create on demand only if the context menu is requested */ void WorksheetView::initBasicActions() { selectAllAction = new QAction(QIcon::fromTheme("edit-select-all"), i18n("Select All"), this); this->addAction(selectAllAction); connect(selectAllAction, &QAction::triggered, this, &WorksheetView::selectAllElements); deleteAction = new QAction(QIcon::fromTheme("edit-delete"), i18n("Delete"), this); this->addAction(deleteAction); connect(deleteAction, &QAction::triggered, this, &WorksheetView::deleteElement); backspaceAction = new QAction(this); this->addAction(backspaceAction); connect(backspaceAction, &QAction::triggered, this, &WorksheetView::deleteElement); //Zoom actions zoomInViewAction = new QAction(QIcon::fromTheme("zoom-in"), i18n("Zoom In"), this); zoomOutViewAction = new QAction(QIcon::fromTheme("zoom-out"), i18n("Zoom Out"), this); zoomOriginAction = new QAction(QIcon::fromTheme("zoom-original"), i18n("Original Size"), this); } void WorksheetView::initActions() { auto* addNewActionGroup = new QActionGroup(this); auto* zoomActionGroup = new QActionGroup(this); auto* mouseModeActionGroup = new QActionGroup(this); auto* layoutActionGroup = new QActionGroup(this); auto* gridActionGroup = new QActionGroup(this); gridActionGroup->setExclusive(true); auto* magnificationActionGroup = new QActionGroup(this); zoomActionGroup->addAction(zoomInViewAction); zoomActionGroup->addAction(zoomOutViewAction); zoomActionGroup->addAction(zoomOriginAction); zoomFitPageHeightAction = new QAction(QIcon::fromTheme("zoom-fit-height"), i18n("Fit to Height"), zoomActionGroup); zoomFitPageWidthAction = new QAction(QIcon::fromTheme("zoom-fit-width"), i18n("Fit to Width"), zoomActionGroup); zoomFitSelectionAction = new QAction(i18n("Fit to Selection"), zoomActionGroup); // Mouse mode actions selectionModeAction = new QAction(QIcon::fromTheme("labplot-cursor-arrow"), i18n("Select and Edit"), mouseModeActionGroup); selectionModeAction->setCheckable(true); navigationModeAction = new QAction(QIcon::fromTheme("input-mouse"), i18n("Navigate"), mouseModeActionGroup); navigationModeAction->setCheckable(true); zoomSelectionModeAction = new QAction(QIcon::fromTheme("page-zoom"), i18n("Select and Zoom"), mouseModeActionGroup); zoomSelectionModeAction->setCheckable(true); //Magnification actions noMagnificationAction = new QAction(QIcon::fromTheme("labplot-1x-zoom"), i18n("No Magnification"), magnificationActionGroup); noMagnificationAction->setCheckable(true); noMagnificationAction->setChecked(true); twoTimesMagnificationAction = new QAction(QIcon::fromTheme("labplot-2x-zoom"), i18n("2x Magnification"), magnificationActionGroup); twoTimesMagnificationAction->setCheckable(true); threeTimesMagnificationAction = new QAction(QIcon::fromTheme("labplot-3x-zoom"), i18n("3x Magnification"), magnificationActionGroup); threeTimesMagnificationAction->setCheckable(true); fourTimesMagnificationAction = new QAction(QIcon::fromTheme("labplot-4x-zoom"), i18n("4x Magnification"), magnificationActionGroup); fourTimesMagnificationAction->setCheckable(true); fiveTimesMagnificationAction = new QAction(QIcon::fromTheme("labplot-5x-zoom"), i18n("5x Magnification"), magnificationActionGroup); fiveTimesMagnificationAction->setCheckable(true); //TODO implement later "group selection action" where multiple objects can be selected by drawing a rectangular // selectionModeAction = new QAction(QIcon::fromTheme("select-rectangular"), i18n("Selection"), mouseModeActionGroup); // selectionModeAction->setCheckable(true); //"Add new" related actions addCartesianPlot1Action = new QAction(QIcon::fromTheme("labplot-xy-plot-four-axes"), i18n("Box Plot, Four Axes"), addNewActionGroup); addCartesianPlot2Action = new QAction(QIcon::fromTheme("labplot-xy-plot-two-axes"), i18n("Box Plot, Two Axes"), addNewActionGroup); addCartesianPlot3Action = new QAction(QIcon::fromTheme("labplot-xy-plot-two-axes-centered"), i18n("Two Axes, Centered"), addNewActionGroup); addCartesianPlot4Action = new QAction(QIcon::fromTheme("labplot-xy-plot-two-axes-centered-origin"), i18n("Two Axes, Crossing at Origin"), addNewActionGroup); addTextLabelAction = new QAction(QIcon::fromTheme("draw-text"), i18n("Text Label"), addNewActionGroup); addImageAction = new QAction(QIcon::fromTheme("viewimage"), i18n("Image"), addNewActionGroup); //Layout actions //TODO: the icons labplot-editvlayout and labplot-edithlayout are confusing for the user. //the orientation is visualized as a horizontal or vertical line on the icon, but the user //percieves the two objects (resembles plots on the worksheet) separated by this line much stronger than the line itself. //with this, the two objects separated by a vertical line are percieved to be layed out in a _horizontal_ order and the //same for the vertical line. Because of this we change the icons here. We can rename the icons later in the breeze icon set. verticalLayoutAction = new QAction(QIcon::fromTheme("labplot-edithlayout"), i18n("Vertical Layout"), layoutActionGroup); verticalLayoutAction->setCheckable(true); horizontalLayoutAction = new QAction(QIcon::fromTheme("labplot-editvlayout"), i18n("Horizontal Layout"), layoutActionGroup); horizontalLayoutAction->setCheckable(true); gridLayoutAction = new QAction(QIcon::fromTheme("labplot-editgrid"), i18n("Grid Layout"), layoutActionGroup); gridLayoutAction->setCheckable(true); - breakLayoutAction = new QAction(QIcon::fromTheme("labplot-editbreaklayout"), i18n("Break Layout"), layoutActionGroup); + breakLayoutAction = new QAction(QIcon::fromTheme("labplot-editbreaklayout"), i18n("No Layout"), layoutActionGroup); breakLayoutAction->setEnabled(false); //Grid actions noGridAction = new QAction(i18n("No Grid"), gridActionGroup); noGridAction->setCheckable(true); noGridAction->setChecked(true); noGridAction->setData(WorksheetView::NoGrid); denseLineGridAction = new QAction(i18n("Dense Line Grid"), gridActionGroup); denseLineGridAction->setCheckable(true); sparseLineGridAction = new QAction(i18n("Sparse Line Grid"), gridActionGroup); sparseLineGridAction->setCheckable(true); denseDotGridAction = new QAction(i18n("Dense Dot Grid"), gridActionGroup); denseDotGridAction->setCheckable(true); sparseDotGridAction = new QAction(i18n("Sparse Dot Grid"), gridActionGroup); sparseDotGridAction->setCheckable(true); customGridAction = new QAction(i18n("Custom Grid"), gridActionGroup); customGridAction->setCheckable(true); snapToGridAction = new QAction(i18n("Snap to Grid"), this); snapToGridAction->setCheckable(true); showPresenterMode = new QAction(QIcon::fromTheme("view-fullscreen"), i18n("Show in Presenter Mode"), this); //check the action corresponding to the currently active layout in worksheet this->layoutChanged(m_worksheet->layout()); connect(addNewActionGroup, &QActionGroup::triggered, this, &WorksheetView::addNew); connect(mouseModeActionGroup, &QActionGroup::triggered, this, &WorksheetView::mouseModeChanged); connect(zoomActionGroup, &QActionGroup::triggered, this, &WorksheetView::changeZoom); connect(magnificationActionGroup, &QActionGroup::triggered, this, &WorksheetView::magnificationChanged); connect(layoutActionGroup, &QActionGroup::triggered, this, &WorksheetView::changeLayout); connect(gridActionGroup, &QActionGroup::triggered, this, &WorksheetView::changeGrid); connect(snapToGridAction, &QAction::triggered, this, &WorksheetView::changeSnapToGrid); connect(showPresenterMode, &QAction::triggered, this, &WorksheetView::presenterMode); //worksheet control actions plotsLockedAction = new QAction(i18n("Non-interactive Plots"), this); plotsLockedAction->setToolTip(i18n("If activated, plots on the worksheet don't react on drag and mouse wheel events.")); plotsLockedAction->setCheckable(true); plotsLockedAction->setChecked(m_worksheet->plotsLocked()); connect(plotsLockedAction, &QAction::triggered, this, &WorksheetView::plotsLockedActionChanged); //action for cartesian plots auto* cartesianPlotActionModeActionGroup = new QActionGroup(this); cartesianPlotActionModeActionGroup->setExclusive(true); cartesianPlotApplyToSelectionAction = new QAction(i18n("Selected Plots"), cartesianPlotActionModeActionGroup); cartesianPlotApplyToSelectionAction->setCheckable(true); cartesianPlotApplyToAllAction = new QAction(i18n("All Plots"), cartesianPlotActionModeActionGroup); cartesianPlotApplyToAllAction->setCheckable(true); setCartesianPlotActionMode(m_worksheet->cartesianPlotActionMode()); connect(cartesianPlotActionModeActionGroup, &QActionGroup::triggered, this, &WorksheetView::cartesianPlotActionModeChanged); // cursor apply to all/selected auto* cartesianPlotActionCursorGroup = new QActionGroup(this); cartesianPlotActionCursorGroup->setExclusive(true); cartesianPlotApplyToSelectionCursor = new QAction(i18n("Selected Plots"), cartesianPlotActionCursorGroup); cartesianPlotApplyToSelectionCursor->setCheckable(true); cartesianPlotApplyToAllCursor = new QAction(i18n("All Plots"), cartesianPlotActionCursorGroup); cartesianPlotApplyToAllCursor->setCheckable(true); setCartesianPlotCursorMode(m_worksheet->cartesianPlotCursorMode()); connect(cartesianPlotActionCursorGroup, &QActionGroup::triggered, this, &WorksheetView::cartesianPlotCursorModeChanged); auto* cartesianPlotMouseModeActionGroup = new QActionGroup(this); cartesianPlotMouseModeActionGroup->setExclusive(true); cartesianPlotSelectionModeAction = new QAction(QIcon::fromTheme("labplot-cursor-arrow"), i18n("Select and Edit"), cartesianPlotMouseModeActionGroup); cartesianPlotSelectionModeAction->setCheckable(true); cartesianPlotSelectionModeAction->setChecked(true); cartesianPlotZoomSelectionModeAction = new QAction(QIcon::fromTheme("labplot-zoom-select"), i18n("Select Region and Zoom In"), cartesianPlotMouseModeActionGroup); cartesianPlotZoomSelectionModeAction->setCheckable(true); cartesianPlotZoomXSelectionModeAction = new QAction(QIcon::fromTheme("labplot-zoom-select-x"), i18n("Select x-region and Zoom In"), cartesianPlotMouseModeActionGroup); cartesianPlotZoomXSelectionModeAction->setCheckable(true); cartesianPlotZoomYSelectionModeAction = new QAction(QIcon::fromTheme("labplot-zoom-select-y"), i18n("Select y-region and Zoom In"), cartesianPlotMouseModeActionGroup); cartesianPlotZoomYSelectionModeAction->setCheckable(true); // TODO: change ICON cartesianPlotCursorModeAction = new QAction(QIcon::fromTheme("debug-execute-from-cursor"), i18n("Cursor"), cartesianPlotMouseModeActionGroup); cartesianPlotCursorModeAction->setCheckable(true); connect(cartesianPlotMouseModeActionGroup, &QActionGroup::triggered, this, &WorksheetView::cartesianPlotMouseModeChanged); auto* cartesianPlotAddNewActionGroup = new QActionGroup(this); addCurveAction = new QAction(QIcon::fromTheme("labplot-xy-curve"), i18n("xy-curve"), cartesianPlotAddNewActionGroup); addHistogramAction = new QAction(QIcon::fromTheme("view-object-histogram-linear"), i18n("Histogram"), cartesianPlotAddNewActionGroup); addEquationCurveAction = new QAction(QIcon::fromTheme("labplot-xy-equation-curve"), i18n("xy-curve from a mathematical Equation"), cartesianPlotAddNewActionGroup); // TODO: no own icons yet addDataOperationCurveAction = new QAction(QIcon::fromTheme("labplot-xy-curve"), i18n("Data Operation"), cartesianPlotAddNewActionGroup); // addDataOperationCurveAction = new QAction(QIcon::fromTheme("labplot-xy-data-operation-curve"), i18n("Data Operation"), cartesianPlotAddNewActionGroup); addDataReductionCurveAction = new QAction(QIcon::fromTheme("labplot-xy-curve"), i18n("Data Reduction"), cartesianPlotAddNewActionGroup); // addDataReductionCurveAction = new QAction(QIcon::fromTheme("labplot-xy-data-reduction-curve"), i18n("Data Reduction"), cartesianPlotAddNewActionGroup); addDifferentiationCurveAction = new QAction(QIcon::fromTheme("labplot-xy-curve"), i18n("Differentiation"), cartesianPlotAddNewActionGroup); // addDifferentiationCurveAction = new QAction(QIcon::fromTheme("labplot-xy-differentiation-curve"), i18n("Differentiation"), cartesianPlotAddNewActionGroup); addIntegrationCurveAction = new QAction(QIcon::fromTheme("labplot-xy-curve"), i18n("Integration"), cartesianPlotAddNewActionGroup); // addIntegrationCurveAction = new QAction(QIcon::fromTheme("labplot-xy-integration-curve"), i18n("Integration"), cartesianPlotAddNewActionGroup); addConvolutionCurveAction = new QAction(QIcon::fromTheme("labplot-xy-curve"), i18n("(De-)Convolution"), cartesianPlotAddNewActionGroup); // addConvolutionCurveAction = new QAction(QIcon::fromTheme("labplot-xy-convolution-curve"), i18n("(De-)Convolution"), cartesianPlotAddNewActionGroup); addCorrelationCurveAction = new QAction(QIcon::fromTheme("labplot-xy-curve"), i18n("Auto-/Cross-Correlation"), cartesianPlotAddNewActionGroup); // addCorrelationCurveAction = new QAction(QIcon::fromTheme("labplot-xy-convolution-curve"), i18n("Auto-/Cross-Correlation"), cartesianPlotAddNewActionGroup); addInterpolationCurveAction = new QAction(QIcon::fromTheme("labplot-xy-interpolation-curve"), i18n("Interpolation"), cartesianPlotAddNewActionGroup); addSmoothCurveAction = new QAction(QIcon::fromTheme("labplot-xy-smoothing-curve"), i18n("Smooth"), cartesianPlotAddNewActionGroup); addFitCurveAction = new QAction(QIcon::fromTheme("labplot-xy-fit-curve"), i18n("Fit"), cartesianPlotAddNewActionGroup); addFourierFilterCurveAction = new QAction(QIcon::fromTheme("labplot-xy-fourier-filter-curve"), i18n("Fourier Filter"), cartesianPlotAddNewActionGroup); addFourierTransformCurveAction = new QAction(QIcon::fromTheme("labplot-xy-fourier-transform-curve"), i18n("Fourier Transform"), cartesianPlotAddNewActionGroup); addLegendAction = new QAction(QIcon::fromTheme("text-field"), i18n("Legend"), cartesianPlotAddNewActionGroup); addHorizontalAxisAction = new QAction(QIcon::fromTheme("labplot-axis-horizontal"), i18n("Horizontal Axis"), cartesianPlotAddNewActionGroup); addVerticalAxisAction = new QAction(QIcon::fromTheme("labplot-axis-vertical"), i18n("Vertical Axis"), cartesianPlotAddNewActionGroup); addPlotTextLabelAction = new QAction(QIcon::fromTheme("draw-text"), i18n("Text Label"), cartesianPlotAddNewActionGroup); addPlotImageAction = new QAction(QIcon::fromTheme("viewimage"), i18n("Image"), cartesianPlotAddNewActionGroup); addCustomPointAction = new QAction(QIcon::fromTheme("draw-cross"), i18n("Custom Point"), cartesianPlotAddNewActionGroup); // Analysis menu // TODO: no own icons yet addDataOperationAction = new QAction(QIcon::fromTheme("labplot-xy-curve"), i18n("Data Operation"), cartesianPlotAddNewActionGroup); // addDataOperationAction = new QAction(QIcon::fromTheme("labplot-xy-data-operation-curve"), i18n("Data Operation"), cartesianPlotAddNewActionGroup); addDataReductionAction = new QAction(QIcon::fromTheme("labplot-xy-curve"), i18n("Data Reduction"), cartesianPlotAddNewActionGroup); // addDataReductionAction = new QAction(QIcon::fromTheme("labplot-xy-data-reduction-curve"), i18n("Data Reduction"), cartesianPlotAddNewActionGroup); addDifferentiationAction = new QAction(QIcon::fromTheme("labplot-xy-curve"), i18n("Differentiation"), cartesianPlotAddNewActionGroup); // addDifferentiationAction = new QAction(QIcon::fromTheme("labplot-xy-differentiation-curve"), i18n("Differentiation"), cartesianPlotAddNewActionGroup); addIntegrationAction = new QAction(QIcon::fromTheme("labplot-xy-curve"), i18n("Integration"), cartesianPlotAddNewActionGroup); // addIntegrationAction = new QAction(QIcon::fromTheme("labplot-xy-integration-curve"), i18n("Integration"), cartesianPlotAddNewActionGroup); addConvolutionAction = new QAction(QIcon::fromTheme("labplot-xy-curve"), i18n("Convolution/Deconvolution"), cartesianPlotAddNewActionGroup); // addConvolutionAction = new QAction(QIcon::fromTheme("labplot-xy-convolution-curve"), i18n("Convolution/Deconvolution"), cartesianPlotAddNewActionGroup); addCorrelationAction = new QAction(QIcon::fromTheme("labplot-xy-curve"), i18n("Auto-/Cross-Correlation"), cartesianPlotAddNewActionGroup); // addCorrelationAction = new QAction(QIcon::fromTheme("labplot-xy-correlation-curve"), i18n("Auto-/Cross-Correlation"), cartesianPlotAddNewActionGroup); addInterpolationAction = new QAction(QIcon::fromTheme("labplot-xy-interpolation-curve"), i18n("Interpolation"), cartesianPlotAddNewActionGroup); addSmoothAction = new QAction(QIcon::fromTheme("labplot-xy-smoothing-curve"), i18n("Smooth"), cartesianPlotAddNewActionGroup); addFitAction = new QAction(QIcon::fromTheme("labplot-xy-fit-curve"), i18n("Fit"), cartesianPlotAddNewActionGroup); addFourierFilterAction = new QAction(QIcon::fromTheme("labplot-xy-fourier-filter-curve"), i18n("Fourier Filter"), cartesianPlotAddNewActionGroup); addFourierTransformAction = new QAction(QIcon::fromTheme("labplot-xy-fourier-transform-curve"), i18n("Fourier Transform"), cartesianPlotAddNewActionGroup); connect(cartesianPlotAddNewActionGroup, &QActionGroup::triggered, this, &WorksheetView::cartesianPlotAddNew); auto* cartesianPlotNavigationGroup = new QActionGroup(this); scaleAutoAction = new QAction(QIcon::fromTheme("labplot-auto-scale-all"), i18n("Auto Scale"), cartesianPlotNavigationGroup); scaleAutoAction->setData(CartesianPlot::ScaleAuto); scaleAutoXAction = new QAction(QIcon::fromTheme("labplot-auto-scale-x"), i18n("Auto Scale X"), cartesianPlotNavigationGroup); scaleAutoXAction->setData(CartesianPlot::ScaleAutoX); scaleAutoYAction = new QAction(QIcon::fromTheme("labplot-auto-scale-y"), i18n("Auto Scale Y"), cartesianPlotNavigationGroup); scaleAutoYAction->setData(CartesianPlot::ScaleAutoY); zoomInAction = new QAction(QIcon::fromTheme("zoom-in"), i18n("Zoom In"), cartesianPlotNavigationGroup); zoomInAction->setData(CartesianPlot::ZoomIn); zoomOutAction = new QAction(QIcon::fromTheme("zoom-out"), i18n("Zoom Out"), cartesianPlotNavigationGroup); zoomOutAction->setData(CartesianPlot::ZoomOut); zoomInXAction = new QAction(QIcon::fromTheme("labplot-zoom-in-x"), i18n("Zoom In X"), cartesianPlotNavigationGroup); zoomInXAction->setData(CartesianPlot::ZoomInX); zoomOutXAction = new QAction(QIcon::fromTheme("labplot-zoom-out-x"), i18n("Zoom Out X"), cartesianPlotNavigationGroup); zoomOutXAction->setData(CartesianPlot::ZoomOutX); zoomInYAction = new QAction(QIcon::fromTheme("labplot-zoom-in-y"), i18n("Zoom In Y"), cartesianPlotNavigationGroup); zoomInYAction->setData(CartesianPlot::ZoomInY); zoomOutYAction = new QAction(QIcon::fromTheme("labplot-zoom-out-y"), i18n("Zoom Out Y"), cartesianPlotNavigationGroup); zoomOutYAction->setData(CartesianPlot::ZoomOutY); shiftLeftXAction = new QAction(QIcon::fromTheme("labplot-shift-left-x"), i18n("Shift Left X"), cartesianPlotNavigationGroup); shiftLeftXAction->setData(CartesianPlot::ShiftLeftX); shiftRightXAction = new QAction(QIcon::fromTheme("labplot-shift-right-x"), i18n("Shift Right X"), cartesianPlotNavigationGroup); shiftRightXAction->setData(CartesianPlot::ShiftRightX); shiftUpYAction = new QAction(QIcon::fromTheme("labplot-shift-up-y"), i18n("Shift Up Y"), cartesianPlotNavigationGroup); shiftUpYAction->setData(CartesianPlot::ShiftUpY); shiftDownYAction = new QAction(QIcon::fromTheme("labplot-shift-down-y"), i18n("Shift Down Y"), cartesianPlotNavigationGroup); shiftDownYAction->setData(CartesianPlot::ShiftDownY); connect(cartesianPlotNavigationGroup, &QActionGroup::triggered, this, &WorksheetView::cartesianPlotNavigationChanged); //set some default values selectionModeAction->setChecked(true); handleCartesianPlotActions(); currentZoomAction = zoomInViewAction; currentMagnificationAction = noMagnificationAction; m_actionsInitialized = true; } void WorksheetView::initMenus() { if (!m_actionsInitialized) initActions(); m_addNewCartesianPlotMenu = new QMenu(i18n("xy-plot"), this); m_addNewCartesianPlotMenu->addAction(addCartesianPlot1Action); m_addNewCartesianPlotMenu->addAction(addCartesianPlot2Action); m_addNewCartesianPlotMenu->addAction(addCartesianPlot3Action); m_addNewCartesianPlotMenu->addAction(addCartesianPlot4Action); m_addNewMenu = new QMenu(i18n("Add New"), this); m_addNewMenu->setIcon(QIcon::fromTheme("list-add")); m_addNewMenu->addMenu(m_addNewCartesianPlotMenu)->setIcon(QIcon::fromTheme("office-chart-line")); m_addNewMenu->addSeparator(); m_addNewMenu->addAction(addTextLabelAction); m_addNewMenu->addAction(addImageAction); m_viewMouseModeMenu = new QMenu(i18n("Mouse Mode"), this); m_viewMouseModeMenu->setIcon(QIcon::fromTheme("input-mouse")); m_viewMouseModeMenu->addAction(selectionModeAction); m_viewMouseModeMenu->addAction(navigationModeAction); m_viewMouseModeMenu->addAction(zoomSelectionModeAction); m_zoomMenu = new QMenu(i18n("Zoom"), this); m_zoomMenu->setIcon(QIcon::fromTheme("zoom-draw")); m_zoomMenu->addAction(zoomInViewAction); m_zoomMenu->addAction(zoomOutViewAction); m_zoomMenu->addAction(zoomOriginAction); m_zoomMenu->addAction(zoomFitPageHeightAction); m_zoomMenu->addAction(zoomFitPageWidthAction); m_zoomMenu->addAction(zoomFitSelectionAction); m_magnificationMenu = new QMenu(i18n("Magnification"), this); m_magnificationMenu->setIcon(QIcon::fromTheme("zoom-in")); m_magnificationMenu->addAction(noMagnificationAction); m_magnificationMenu->addAction(twoTimesMagnificationAction); m_magnificationMenu->addAction(threeTimesMagnificationAction); m_magnificationMenu->addAction(fourTimesMagnificationAction); m_magnificationMenu->addAction(fiveTimesMagnificationAction); m_layoutMenu = new QMenu(i18n("Layout"), this); m_layoutMenu->setIcon(QIcon::fromTheme("labplot-editbreaklayout")); m_layoutMenu->addAction(verticalLayoutAction); m_layoutMenu->addAction(horizontalLayoutAction); m_layoutMenu->addAction(gridLayoutAction); m_layoutMenu->addSeparator(); m_layoutMenu->addAction(breakLayoutAction); m_gridMenu = new QMenu(i18n("Grid"), this); m_gridMenu->setIcon(QIcon::fromTheme("view-grid")); m_gridMenu->addAction(noGridAction); m_gridMenu->addSeparator(); m_gridMenu->addAction(sparseLineGridAction); m_gridMenu->addAction(denseLineGridAction); m_gridMenu->addSeparator(); m_gridMenu->addAction(sparseDotGridAction); m_gridMenu->addAction(denseDotGridAction); m_gridMenu->addSeparator(); m_gridMenu->addAction(customGridAction); //TODO: implement "snap to grid" and activate this action // m_gridMenu->addSeparator(); // m_gridMenu->addAction(snapToGridAction); m_cartesianPlotMenu = new QMenu(i18n("Cartesian Plot"), this); m_cartesianPlotMenu->setIcon(QIcon::fromTheme("office-chart-line")); m_cartesianPlotMouseModeMenu = new QMenu(i18n("Mouse Mode"), this); m_cartesianPlotMouseModeMenu->setIcon(QIcon::fromTheme("input-mouse")); m_cartesianPlotMouseModeMenu->addAction(cartesianPlotSelectionModeAction); m_cartesianPlotMouseModeMenu->addAction(cartesianPlotZoomSelectionModeAction); m_cartesianPlotMouseModeMenu->addAction(cartesianPlotZoomXSelectionModeAction); m_cartesianPlotMouseModeMenu->addAction(cartesianPlotZoomYSelectionModeAction); m_cartesianPlotMouseModeMenu->addSeparator(); m_cartesianPlotMouseModeMenu->addAction(cartesianPlotCursorModeAction); m_cartesianPlotMouseModeMenu->addSeparator(); m_cartesianPlotAddNewMenu = new QMenu(i18n("Add New"), this); m_cartesianPlotAddNewMenu->setIcon(QIcon::fromTheme("list-add")); m_cartesianPlotAddNewMenu->addAction(addCurveAction); m_cartesianPlotAddNewMenu->addAction(addHistogramAction); m_cartesianPlotAddNewMenu->addAction(addEquationCurveAction); m_cartesianPlotAddNewMenu->addSeparator(); m_cartesianPlotAddNewAnalysisMenu = new QMenu(i18n("Analysis Curve")); m_cartesianPlotAddNewAnalysisMenu->addAction(addFitCurveAction); m_cartesianPlotAddNewAnalysisMenu->addSeparator(); m_cartesianPlotAddNewAnalysisMenu->addAction(addDifferentiationCurveAction); m_cartesianPlotAddNewAnalysisMenu->addAction(addIntegrationCurveAction); m_cartesianPlotAddNewAnalysisMenu->addSeparator(); m_cartesianPlotAddNewAnalysisMenu->addAction(addInterpolationCurveAction); m_cartesianPlotAddNewAnalysisMenu->addAction(addSmoothCurveAction); m_cartesianPlotAddNewAnalysisMenu->addSeparator(); m_cartesianPlotAddNewAnalysisMenu->addAction(addFourierFilterCurveAction); m_cartesianPlotAddNewAnalysisMenu->addAction(addFourierTransformCurveAction); m_cartesianPlotAddNewAnalysisMenu->addSeparator(); m_cartesianPlotAddNewAnalysisMenu->addAction(addConvolutionCurveAction); m_cartesianPlotAddNewAnalysisMenu->addAction(addCorrelationCurveAction); m_cartesianPlotAddNewAnalysisMenu->addSeparator(); // m_cartesianPlotAddNewAnalysisMenu->addAction(addDataOperationCurveAction); m_cartesianPlotAddNewAnalysisMenu->addAction(addDataReductionCurveAction); m_cartesianPlotAddNewMenu->addMenu(m_cartesianPlotAddNewAnalysisMenu); m_cartesianPlotAddNewMenu->addSeparator(); m_cartesianPlotAddNewMenu->addAction(addLegendAction); m_cartesianPlotAddNewMenu->addSeparator(); m_cartesianPlotAddNewMenu->addAction(addHorizontalAxisAction); m_cartesianPlotAddNewMenu->addAction(addVerticalAxisAction); m_cartesianPlotAddNewMenu->addSeparator(); m_cartesianPlotAddNewMenu->addAction(addPlotTextLabelAction); m_cartesianPlotAddNewMenu->addAction(addPlotImageAction); m_cartesianPlotAddNewMenu->addSeparator(); m_cartesianPlotAddNewMenu->addAction(addCustomPointAction); m_cartesianPlotZoomMenu = new QMenu(i18n("Zoom/Navigate"), this); m_cartesianPlotZoomMenu->setIcon(QIcon::fromTheme("zoom-draw")); m_cartesianPlotZoomMenu->addAction(scaleAutoAction); m_cartesianPlotZoomMenu->addAction(scaleAutoXAction); m_cartesianPlotZoomMenu->addAction(scaleAutoYAction); m_cartesianPlotZoomMenu->addSeparator(); m_cartesianPlotZoomMenu->addAction(zoomInAction); m_cartesianPlotZoomMenu->addAction(zoomOutAction); m_cartesianPlotZoomMenu->addSeparator(); m_cartesianPlotZoomMenu->addAction(zoomInXAction); m_cartesianPlotZoomMenu->addAction(zoomOutXAction); m_cartesianPlotZoomMenu->addSeparator(); m_cartesianPlotZoomMenu->addAction(zoomInYAction); m_cartesianPlotZoomMenu->addAction(zoomOutYAction); m_cartesianPlotZoomMenu->addSeparator(); m_cartesianPlotZoomMenu->addAction(shiftLeftXAction); m_cartesianPlotZoomMenu->addAction(shiftRightXAction); m_cartesianPlotZoomMenu->addSeparator(); m_cartesianPlotZoomMenu->addAction(shiftUpYAction); m_cartesianPlotZoomMenu->addAction(shiftDownYAction); m_cartesianPlotActionModeMenu = new QMenu(i18n("Apply Actions to"), this); m_cartesianPlotActionModeMenu->setIcon(QIcon::fromTheme("dialog-ok-apply")); m_cartesianPlotActionModeMenu->addAction(cartesianPlotApplyToSelectionAction); m_cartesianPlotActionModeMenu->addAction(cartesianPlotApplyToAllAction); m_cartesianPlotCursorModeMenu = new QMenu(i18n("Apply Cursor to"), this); m_cartesianPlotCursorModeMenu->addAction(cartesianPlotApplyToSelectionCursor); m_cartesianPlotCursorModeMenu->addAction(cartesianPlotApplyToAllCursor); m_cartesianPlotMenu->addMenu(m_cartesianPlotAddNewMenu); m_cartesianPlotMenu->addSeparator(); m_cartesianPlotMenu->addMenu(m_cartesianPlotMouseModeMenu); m_cartesianPlotMenu->addMenu(m_cartesianPlotZoomMenu); m_cartesianPlotMenu->addSeparator(); m_cartesianPlotMenu->addMenu(m_cartesianPlotActionModeMenu); m_cartesianPlotMenu->addMenu(m_cartesianPlotCursorModeMenu); m_cartesianPlotMenu->addSeparator(); m_cartesianPlotMenu->addAction(plotsLockedAction); // Data manipulation menu m_dataManipulationMenu = new QMenu(i18n("Data Manipulation") ,this); m_dataManipulationMenu->setIcon(QIcon::fromTheme("zoom-draw")); m_dataManipulationMenu->addAction(addDataOperationAction); m_dataManipulationMenu->addAction(addDataReductionAction); //themes menu m_themeMenu = new QMenu(i18n("Apply Theme"), this); m_themeMenu->setIcon(QIcon::fromTheme("color-management")); auto* themeWidget = new ThemesWidget(nullptr); connect(themeWidget, &ThemesWidget::themeSelected, m_worksheet, &Worksheet::setTheme); connect(themeWidget, &ThemesWidget::themeSelected, m_themeMenu, &QMenu::close); auto* widgetAction = new QWidgetAction(this); widgetAction->setDefaultWidget(themeWidget); m_themeMenu->addAction(widgetAction); m_menusInitialized = true; } /*! * Populates the menu \c menu with the worksheet and worksheet view relevant actions. * The menu is used * - as the context menu in WorksheetView * - as the "worksheet menu" in the main menu-bar (called form MainWin) * - as a part of the worksheet context menu in project explorer */ void WorksheetView::createContextMenu(QMenu* menu) { Q_ASSERT(menu != nullptr); if (!m_menusInitialized) initMenus(); QAction* firstAction = nullptr; // if we're populating the context menu for the project explorer, then //there're already actions available there. Skip the first title-action //and insert the action at the beginning of the menu. if (menu->actions().size() > 1) firstAction = menu->actions().at(1); menu->insertMenu(firstAction, m_addNewMenu); menu->insertSeparator(firstAction); menu->insertMenu(firstAction, m_viewMouseModeMenu); menu->insertMenu(firstAction, m_zoomMenu); menu->insertMenu(firstAction, m_magnificationMenu); menu->insertMenu(firstAction, m_layoutMenu); menu->insertMenu(firstAction, m_gridMenu); menu->insertMenu(firstAction, m_themeMenu); menu->insertSeparator(firstAction); menu->insertAction(firstAction, plotsLockedAction); menu->insertSeparator(firstAction); menu->insertMenu(firstAction, m_cartesianPlotMenu); menu->insertSeparator(firstAction); menu->insertAction(firstAction, showPresenterMode); menu->insertSeparator(firstAction); } void WorksheetView::createAnalysisMenu(QMenu* menu) { Q_ASSERT(menu != nullptr); if (!m_menusInitialized) initMenus(); // Data manipulation menu // menu->insertMenu(nullptr, m_dataManipulationMenu); menu->addAction(addFitAction); menu->addSeparator(); menu->addAction(addDifferentiationAction); menu->addAction(addIntegrationAction); menu->addSeparator(); menu->addAction(addInterpolationAction); menu->addAction(addSmoothAction); menu->addSeparator(); menu->addAction(addFourierFilterAction); menu->addAction(addFourierTransformAction); menu->addSeparator(); menu->addAction(addConvolutionAction); menu->addAction(addCorrelationAction); menu->addSeparator(); menu->addAction(addDataReductionAction); } void WorksheetView::fillToolBar(QToolBar* toolBar) { toolBar->addSeparator(); tbNewCartesianPlot = new QToolButton(toolBar); tbNewCartesianPlot->setPopupMode(QToolButton::MenuButtonPopup); tbNewCartesianPlot->setMenu(m_addNewCartesianPlotMenu); tbNewCartesianPlot->setDefaultAction(addCartesianPlot1Action); toolBar->addWidget(tbNewCartesianPlot); toolBar->addAction(addTextLabelAction); toolBar->addAction(addImageAction); toolBar->addSeparator(); toolBar->addAction(verticalLayoutAction); toolBar->addAction(horizontalLayoutAction); toolBar->addAction(gridLayoutAction); toolBar->addAction(breakLayoutAction); toolBar->addSeparator(); toolBar->addAction(selectionModeAction); toolBar->addAction(navigationModeAction); toolBar->addAction(zoomSelectionModeAction); toolBar->addSeparator(); tbZoom = new QToolButton(toolBar); tbZoom->setPopupMode(QToolButton::MenuButtonPopup); tbZoom->setMenu(m_zoomMenu); tbZoom->setDefaultAction(currentZoomAction); toolBar->addWidget(tbZoom); tbMagnification = new QToolButton(toolBar); tbMagnification->setPopupMode(QToolButton::MenuButtonPopup); tbMagnification->setMenu(m_magnificationMenu); tbMagnification->setDefaultAction(currentMagnificationAction); toolBar->addWidget(tbMagnification); } #ifdef Q_OS_MAC void WorksheetView::fillTouchBar(KDMacTouchBar* touchBar){ //touchBar->addAction(addCartesianPlot1Action); touchBar->addAction(zoomInViewAction); touchBar->addAction(zoomOutViewAction); touchBar->addAction(showPresenterMode); } #endif void WorksheetView::fillCartesianPlotToolBar(QToolBar* toolBar) { toolBar->addAction(cartesianPlotSelectionModeAction); toolBar->addAction(cartesianPlotZoomSelectionModeAction); toolBar->addAction(cartesianPlotZoomXSelectionModeAction); toolBar->addAction(cartesianPlotZoomYSelectionModeAction); toolBar->addAction(cartesianPlotCursorModeAction); toolBar->addSeparator(); toolBar->addAction(addCurveAction); toolBar->addAction(addHistogramAction); toolBar->addAction(addEquationCurveAction); // don't over-populate the tool bar // toolBar->addAction(addDifferentiationCurveAction); // toolBar->addAction(addIntegrationCurveAction); // toolBar->addAction(addDataOperationCurveAction); // toolBar->addAction(addDataReductionCurveAction); // toolBar->addAction(addInterpolationCurveAction); // toolBar->addAction(addSmoothCurveAction); // toolBar->addAction(addFitCurveAction); // toolBar->addAction(addFourierFilterCurveAction); // toolBar->addAction(addFourierTransformCurveAction); // toolBar->addAction(addConvolutionCurveAction); // toolBar->addAction(addCorrelationCurveAction); toolBar->addSeparator(); toolBar->addAction(addLegendAction); toolBar->addSeparator(); toolBar->addAction(addHorizontalAxisAction); toolBar->addAction(addVerticalAxisAction); toolBar->addSeparator(); toolBar->addAction(addPlotTextLabelAction); toolBar->addAction(addPlotImageAction); toolBar->addSeparator(); toolBar->addAction(scaleAutoAction); toolBar->addAction(scaleAutoXAction); toolBar->addAction(scaleAutoYAction); toolBar->addAction(zoomInAction); toolBar->addAction(zoomOutAction); toolBar->addAction(zoomInXAction); toolBar->addAction(zoomOutXAction); toolBar->addAction(zoomInYAction); toolBar->addAction(zoomOutYAction); toolBar->addAction(shiftLeftXAction); toolBar->addAction(shiftRightXAction); toolBar->addAction(shiftUpYAction); toolBar->addAction(shiftDownYAction); toolBar->addSeparator(); handleCartesianPlotActions(); } void WorksheetView::setScene(QGraphicsScene* scene) { QGraphicsView::setScene(scene); } void WorksheetView::setIsClosing() { m_isClosing = true; } void WorksheetView::setCartesianPlotActionMode(Worksheet::CartesianPlotActionMode mode) { if (mode == Worksheet::CartesianPlotActionMode::ApplyActionToAll) cartesianPlotApplyToAllAction->setChecked(true); else cartesianPlotApplyToSelectionAction->setChecked(true); } void WorksheetView::setCartesianPlotCursorMode(Worksheet::CartesianPlotActionMode mode) { if (mode == Worksheet::CartesianPlotActionMode::ApplyActionToAll) cartesianPlotApplyToAllCursor->setChecked(true); else cartesianPlotApplyToSelectionCursor->setChecked(true); } void WorksheetView::setPlotLock(bool lock) { plotsLockedAction->setChecked(lock); } void WorksheetView::drawForeground(QPainter* painter, const QRectF& rect) { if (m_mouseMode == ZoomSelectionMode && m_selectionBandIsShown) { painter->save(); const QRectF& selRect = mapToScene(QRect(m_selectionStart, m_selectionEnd).normalized()).boundingRect(); //TODO: don't hardcode for black here, use a a different color depending on the theme of the worksheet/plot under the mouse cursor? painter->setPen(QPen(Qt::black, 5/transform().m11())); painter->drawRect(selRect); painter->setBrush(QApplication::palette().color(QPalette::Highlight)); painter->setOpacity(0.2); painter->drawRect(selRect); painter->restore(); } QGraphicsView::drawForeground(painter, rect); } void WorksheetView::drawBackgroundItems(QPainter* painter, const QRectF& scene_rect) { // canvas painter->setOpacity(m_worksheet->backgroundOpacity()); if (m_worksheet->backgroundType() == PlotArea::BackgroundType::Color) { switch (m_worksheet->backgroundColorStyle()) { case PlotArea::BackgroundColorStyle::SingleColor: { painter->setBrush(QBrush(m_worksheet->backgroundFirstColor())); break; } case PlotArea::BackgroundColorStyle::HorizontalLinearGradient: { QLinearGradient linearGrad(scene_rect.topLeft(), scene_rect.topRight()); linearGrad.setColorAt(0, m_worksheet->backgroundFirstColor()); linearGrad.setColorAt(1, m_worksheet->backgroundSecondColor()); painter->setBrush(QBrush(linearGrad)); break; } case PlotArea::BackgroundColorStyle::VerticalLinearGradient: { QLinearGradient linearGrad(scene_rect.topLeft(), scene_rect.bottomLeft()); linearGrad.setColorAt(0, m_worksheet->backgroundFirstColor()); linearGrad.setColorAt(1, m_worksheet->backgroundSecondColor()); painter->setBrush(QBrush(linearGrad)); break; } case PlotArea::BackgroundColorStyle::TopLeftDiagonalLinearGradient: { QLinearGradient linearGrad(scene_rect.topLeft(), scene_rect.bottomRight()); linearGrad.setColorAt(0, m_worksheet->backgroundFirstColor()); linearGrad.setColorAt(1, m_worksheet->backgroundSecondColor()); painter->setBrush(QBrush(linearGrad)); break; } case PlotArea::BackgroundColorStyle::BottomLeftDiagonalLinearGradient: { QLinearGradient linearGrad(scene_rect.bottomLeft(), scene_rect.topRight()); linearGrad.setColorAt(0, m_worksheet->backgroundFirstColor()); linearGrad.setColorAt(1, m_worksheet->backgroundSecondColor()); painter->setBrush(QBrush(linearGrad)); break; } case PlotArea::BackgroundColorStyle::RadialGradient: { QRadialGradient radialGrad(scene_rect.center(), scene_rect.width()/2); radialGrad.setColorAt(0, m_worksheet->backgroundFirstColor()); radialGrad.setColorAt(1, m_worksheet->backgroundSecondColor()); painter->setBrush(QBrush(radialGrad)); break; } //default: // painter->setBrush(QBrush(m_worksheet->backgroundFirstColor())); } painter->drawRect(scene_rect); } else if (m_worksheet->backgroundType() == PlotArea::BackgroundType::Image) { // background image const QString& backgroundFileName = m_worksheet->backgroundFileName().trimmed(); if ( !backgroundFileName.isEmpty() ) { QPixmap pix(backgroundFileName); switch (m_worksheet->backgroundImageStyle()) { case PlotArea::BackgroundImageStyle::ScaledCropped: pix = pix.scaled(scene_rect.size().toSize(),Qt::KeepAspectRatioByExpanding,Qt::SmoothTransformation); painter->drawPixmap(scene_rect.topLeft(),pix); break; case PlotArea::BackgroundImageStyle::Scaled: pix = pix.scaled(scene_rect.size().toSize(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation); painter->drawPixmap(scene_rect.topLeft(),pix); break; case PlotArea::BackgroundImageStyle::ScaledAspectRatio: pix = pix.scaled(scene_rect.size().toSize(),Qt::KeepAspectRatio,Qt::SmoothTransformation); painter->drawPixmap(scene_rect.topLeft(),pix); break; case PlotArea::BackgroundImageStyle::Centered: painter->drawPixmap(QPointF(scene_rect.center().x()-pix.size().width()/2,scene_rect.center().y()-pix.size().height()/2),pix); break; case PlotArea::BackgroundImageStyle::Tiled: painter->drawTiledPixmap(scene_rect,pix); break; case PlotArea::BackgroundImageStyle::CenterTiled: painter->drawTiledPixmap(scene_rect,pix,QPoint(scene_rect.size().width()/2,scene_rect.size().height()/2)); break; //default: // painter->drawPixmap(scene_rect.topLeft(),pix); } } } else if (m_worksheet->backgroundType() == PlotArea::BackgroundType::Pattern) { // background pattern painter->setBrush(QBrush(m_worksheet->backgroundFirstColor(),m_worksheet->backgroundBrushStyle())); painter->drawRect(scene_rect); } //grid if (m_gridSettings.style != WorksheetView::NoGrid) { QColor c = m_gridSettings.color; c.setAlphaF(m_gridSettings.opacity); painter->setPen(c); qreal x, y; qreal left = scene_rect.left(); qreal right = scene_rect.right(); qreal top = scene_rect.top(); qreal bottom = scene_rect.bottom(); if (m_gridSettings.style == WorksheetView::LineGrid) { QLineF line; //horizontal lines y = top + m_gridSettings.verticalSpacing; while (y < bottom) { line.setLine( left, y, right, y ); painter->drawLine(line); y += m_gridSettings.verticalSpacing; } //vertical lines x = left + m_gridSettings.horizontalSpacing; while (x < right) { line.setLine( x, top, x, bottom ); painter->drawLine(line); x += m_gridSettings.horizontalSpacing; } } else { //DotGrid y = top + m_gridSettings.verticalSpacing; while (y < bottom) { x = left;// + m_gridSettings.horizontalSpacing; while (x < right) { x += m_gridSettings.horizontalSpacing; painter->drawPoint(x, y); } y += m_gridSettings.verticalSpacing; } } } } void WorksheetView::drawBackground(QPainter* painter, const QRectF& rect) { painter->save(); //painter->setRenderHint(QPainter::Antialiasing); QRectF scene_rect = sceneRect(); if (!m_worksheet->useViewSize()) { // background KColorScheme scheme(QPalette::Active, KColorScheme::Window); const QColor& color = scheme.background().color(); if (!scene_rect.contains(rect)) painter->fillRect(rect, color); //shadow // int shadowSize = scene_rect.width()*0.02; // QRectF rightShadowRect(scene_rect.right(), scene_rect.top() + shadowSize, shadowSize, scene_rect.height()); // QRectF bottomShadowRect(scene_rect.left() + shadowSize, scene_rect.bottom(), scene_rect.width(), shadowSize); // // const QColor& shadeColor = scheme.shade(color, KColorScheme::MidShade); // painter->fillRect(rightShadowRect.intersected(rect), shadeColor); // painter->fillRect(bottomShadowRect.intersected(rect), shadeColor); } drawBackgroundItems(painter, scene_rect); invalidateScene(rect, QGraphicsScene::BackgroundLayer); painter->restore(); } bool WorksheetView::isPlotAtPos(QPoint pos) const { bool plot = false; QGraphicsItem* item = itemAt(pos); if (item) { plot = item->data(0).toInt() == static_cast(WorksheetElement::WorksheetElementName::NameCartesianPlot); if (!plot && item->parentItem()) plot = item->parentItem()->data(0).toInt() == static_cast(WorksheetElement::WorksheetElementName::NameCartesianPlot); } return plot; } CartesianPlot* WorksheetView::plotAt(QPoint pos) const { QGraphicsItem* item = itemAt(pos); if (!item) return nullptr; QGraphicsItem* plotItem = nullptr; if (item->data(0).toInt() == static_cast(WorksheetElement::WorksheetElementName::NameCartesianPlot)) plotItem = item; else { if (item->parentItem() && item->parentItem()->data(0).toInt() == static_cast(WorksheetElement::WorksheetElementName::NameCartesianPlot)) plotItem = item->parentItem(); } if (plotItem == nullptr) return nullptr; CartesianPlot* plot = nullptr; for (auto* p : m_worksheet->children()) { if (p->graphicsItem() == plotItem) { plot = p; break; } } return plot; } //############################################################################## //#################################### Events ############################### //############################################################################## void WorksheetView::resizeEvent(QResizeEvent* event) { if (m_isClosing) return; if (m_worksheet->useViewSize()) this->processResize(); QGraphicsView::resizeEvent(event); } void WorksheetView::wheelEvent(QWheelEvent* event) { //https://wiki.qt.io/Smooth_Zoom_In_QGraphicsView if (m_mouseMode == ZoomSelectionMode || (QApplication::keyboardModifiers() & Qt::ControlModifier)) { int numDegrees = event->delta() / 8; int numSteps = numDegrees / 15; // see QWheelEvent documentation zoom(numSteps); } else QGraphicsView::wheelEvent(event); } void WorksheetView::zoom(int numSteps) { m_numScheduledScalings += numSteps; if (m_numScheduledScalings * numSteps < 0) // if user moved the wheel in another direction, we reset previously scheduled scalings m_numScheduledScalings = numSteps; auto* anim = new QTimeLine(350, this); anim->setUpdateInterval(20); connect(anim, &QTimeLine::valueChanged, this, &WorksheetView::scalingTime); connect(anim, &QTimeLine::finished, this, &WorksheetView::animFinished); anim->start(); } void WorksheetView::scalingTime() { qreal factor = 1.0 + qreal(m_numScheduledScalings) / 300.0; scale(factor, factor); } void WorksheetView::animFinished() { if (m_numScheduledScalings > 0) m_numScheduledScalings--; else m_numScheduledScalings++; sender()->~QObject(); } void WorksheetView::mousePressEvent(QMouseEvent* event) { //prevent the deselection of items when context menu event //was triggered (right button click) if (event->button() == Qt::RightButton) { event->accept(); return; } if (event->button() == Qt::LeftButton && m_mouseMode == ZoomSelectionMode) { m_selectionStart = event->pos(); m_selectionEnd = m_selectionStart; //select&zoom'g starts -> reset the end point to the start point m_selectionBandIsShown = true; QGraphicsView::mousePressEvent(event); return; } // select the worksheet in the project explorer if the view was clicked // and there is no selection currently. We need this for the case when // there is a single worksheet in the project and we change from the project-node // in the project explorer to the worksheet-node by clicking the view. if ( scene()->selectedItems().isEmpty() ) m_worksheet->setSelectedInView(true); QGraphicsView::mousePressEvent(event); } void WorksheetView::mouseReleaseEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton && m_mouseMode == ZoomSelectionMode) { m_selectionBandIsShown = false; viewport()->repaint(QRect(m_selectionStart, m_selectionEnd).normalized()); //don't zoom if very small region was selected, avoid occasional/unwanted zooming m_selectionEnd = event->pos(); if ( abs(m_selectionEnd.x() - m_selectionStart.x()) > 20 && abs(m_selectionEnd.y() - m_selectionStart.y()) > 20 ) fitInView(mapToScene(QRect(m_selectionStart, m_selectionEnd).normalized()).boundingRect(), Qt::KeepAspectRatio); } QGraphicsView::mouseReleaseEvent(event); } void WorksheetView::mouseDoubleClickEvent(QMouseEvent*) { emit propertiesExplorerRequested(); } void WorksheetView::mouseMoveEvent(QMouseEvent* event) { if (m_mouseMode == SelectionMode && m_cartesianPlotMouseMode != CartesianPlot::SelectionMode ) { //check whether there is a cartesian plot under the cursor //and set the cursor appearance according to the current mouse mode for the cartesian plots if ( isPlotAtPos(event->pos()) ) { if (m_cartesianPlotMouseMode == CartesianPlot::ZoomSelectionMode) setCursor(Qt::CrossCursor); else if (m_cartesianPlotMouseMode == CartesianPlot::ZoomXSelectionMode) setCursor(Qt::SizeHorCursor); else if (m_cartesianPlotMouseMode == CartesianPlot::ZoomYSelectionMode) setCursor(Qt::SizeVerCursor); } else setCursor(Qt::ArrowCursor); } else if (m_mouseMode == SelectionMode && m_cartesianPlotMouseMode == CartesianPlot::SelectionMode ) setCursor(Qt::ArrowCursor); else if (m_selectionBandIsShown) { QRect rect = QRect(m_selectionStart, m_selectionEnd).normalized(); m_selectionEnd = event->pos(); rect = rect.united(QRect(m_selectionStart, m_selectionEnd).normalized()); qreal penWidth = 5/transform().m11(); rect.setX(rect.x()-penWidth); rect.setY(rect.y()-penWidth); rect.setHeight(rect.height()+2*penWidth); rect.setWidth(rect.width()+2*penWidth); viewport()->repaint(rect); } //show the magnification window if (magnificationFactor /*&& m_mouseMode == SelectAndEditMode*/) { if (!m_magnificationWindow) { m_magnificationWindow = new QGraphicsPixmapItem(nullptr); m_magnificationWindow->setZValue(std::numeric_limits::max()); scene()->addItem(m_magnificationWindow); } m_magnificationWindow->setVisible(false); //copy the part of the view to be shown magnified QPointF pos = mapToScene(event->pos()); const int size = Worksheet::convertToSceneUnits(2.0, Worksheet::Unit::Centimeter)/transform().m11(); const QRectF copyRect(pos.x() - size/(2*magnificationFactor), pos.y() - size/(2*magnificationFactor), size/magnificationFactor, size/magnificationFactor); QPixmap px = grab(mapFromScene(copyRect).boundingRect()); px = px.scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); //draw the bounding rect QPainter painter(&px); const QPen pen = QPen(Qt::lightGray, 2/transform().m11()); painter.setPen(pen); QRect rect = px.rect(); rect.setWidth(rect.width()-pen.widthF()/2); rect.setHeight(rect.height()-pen.widthF()/2); painter.drawRect(rect); //set the pixmap m_magnificationWindow->setPixmap(px); m_magnificationWindow->setPos(pos.x()- px.width()/2, pos.y()- px.height()/2); m_magnificationWindow->setVisible(true); } else if (m_magnificationWindow) m_magnificationWindow->setVisible(false); QGraphicsView::mouseMoveEvent(event); } void WorksheetView::contextMenuEvent(QContextMenuEvent* e) { if ( (m_magnificationWindow && m_magnificationWindow->isVisible() && items(e->pos()).size() == 1) || !itemAt(e->pos()) ) { //no item or only the magnification window under the cursor -> show the context menu for the worksheet QMenu *menu = new QMenu(this); this->createContextMenu(menu); menu->exec(QCursor::pos()); } else { //propagate the event to the scene and graphics items QGraphicsView::contextMenuEvent(e); } } void WorksheetView::keyPressEvent(QKeyEvent* event) { if (event->matches(QKeySequence::Copy)) { //add here copying of objects exportToClipboard(); } QGraphicsView::keyPressEvent(event); } void WorksheetView::keyReleaseEvent(QKeyEvent* event) { QGraphicsView::keyReleaseEvent(event); } void WorksheetView::dragEnterEvent(QDragEnterEvent* event) { //ignore events not related to internal drags of columns etc., e.g. dropping of external files onto LabPlot const QMimeData* mimeData = event->mimeData(); if (!mimeData) { event->ignore(); return; } if (mimeData->formats().at(0) != QLatin1String("labplot-dnd")) { event->ignore(); return; } //select the worksheet in the project explorer and bring the view to the foreground m_worksheet->setSelectedInView(true); m_worksheet->mdiSubWindow()->mdiArea()->setActiveSubWindow(m_worksheet->mdiSubWindow()); event->setAccepted(true); } void WorksheetView::dragMoveEvent(QDragMoveEvent* event) { // only accept drop events if we have a plot under the cursor where we can drop columns onto bool plot = isPlotAtPos(event->pos()); event->setAccepted(plot); } void WorksheetView::dropEvent(QDropEvent* event) { CartesianPlot* plot = plotAt(event->pos()); if (plot != nullptr) plot->processDropEvent(event); } //############################################################################## //#################################### SLOTs ################################ //############################################################################## void WorksheetView::useViewSizeRequested() { if (!m_actionsInitialized) initActions(); if (m_worksheet->useViewSize()) { setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); zoomFitPageHeightAction->setVisible(false); zoomFitPageWidthAction->setVisible(false); currentZoomAction = zoomInViewAction; if (tbZoom) tbZoom->setDefaultAction(zoomInViewAction); //determine and set the current view size this->processResize(); } else { setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); zoomFitPageHeightAction->setVisible(true); zoomFitPageWidthAction->setVisible(true); } } void WorksheetView::processResize() { if (size() != sceneRect().size()) { static const float hscale = QApplication::desktop()->physicalDpiX()/(Worksheet::convertToSceneUnits(1, Worksheet::Unit::Inch)); static const float vscale = QApplication::desktop()->physicalDpiY()/(Worksheet::convertToSceneUnits(1, Worksheet::Unit::Inch)); m_worksheet->setUndoAware(false); m_worksheet->setPageRect(QRectF(0.0, 0.0, width()/hscale, height()/vscale)); m_worksheet->setUndoAware(true); } } void WorksheetView::changeZoom(QAction* action) { if (action == zoomInViewAction) zoom(1); else if (action == zoomOutViewAction) zoom(-1); else if (action == zoomOriginAction) { static const float hscale = QApplication::desktop()->physicalDpiX()/(Worksheet::convertToSceneUnits(1, Worksheet::Unit::Inch)); static const float vscale = QApplication::desktop()->physicalDpiY()/(Worksheet::convertToSceneUnits(1, Worksheet::Unit::Inch)); setTransform(QTransform::fromScale(hscale, vscale)); } else if (action == zoomFitPageWidthAction) { float scaleFactor = viewport()->width()/scene()->sceneRect().width(); setTransform(QTransform::fromScale(scaleFactor, scaleFactor)); } else if (action == zoomFitPageHeightAction) { float scaleFactor = viewport()->height()/scene()->sceneRect().height(); setTransform(QTransform::fromScale(scaleFactor, scaleFactor)); } else if (action == zoomFitSelectionAction) fitInView(scene()->selectionArea().boundingRect(),Qt::KeepAspectRatio); currentZoomAction = action; if (tbZoom) tbZoom->setDefaultAction(action); } void WorksheetView::magnificationChanged(QAction* action) { if (action == noMagnificationAction) magnificationFactor = 0; else if (action == twoTimesMagnificationAction) magnificationFactor = 2; else if (action == threeTimesMagnificationAction) magnificationFactor = 3; else if (action == fourTimesMagnificationAction) magnificationFactor = 4; else if (action == fiveTimesMagnificationAction) magnificationFactor = 5; currentMagnificationAction = action; if (tbMagnification) tbMagnification->setDefaultAction(action); } void WorksheetView::mouseModeChanged(QAction* action) { if (action == selectionModeAction) { m_mouseMode = SelectionMode; setInteractive(true); setDragMode(QGraphicsView::NoDrag); } else if (action == navigationModeAction) { m_mouseMode = NavigationMode; setInteractive(false); setDragMode(QGraphicsView::ScrollHandDrag); } else { m_mouseMode = ZoomSelectionMode; setInteractive(false); setDragMode(QGraphicsView::NoDrag); } } //"Add new" related slots void WorksheetView::addNew(QAction* action) { WorksheetElement* aspect = nullptr; if (action == addCartesianPlot1Action) { CartesianPlot* plot = new CartesianPlot(i18n("xy-plot")); plot->initDefault(CartesianPlot::FourAxes); plot->setMouseMode(m_cartesianPlotMouseMode); aspect = plot; if (tbNewCartesianPlot) tbNewCartesianPlot->setDefaultAction(addCartesianPlot1Action); } else if (action == addCartesianPlot2Action) { CartesianPlot* plot = new CartesianPlot(i18n("xy-plot")); plot->initDefault(CartesianPlot::TwoAxes); plot->setMouseMode(m_cartesianPlotMouseMode); aspect = plot; if (tbNewCartesianPlot) tbNewCartesianPlot->setDefaultAction(addCartesianPlot2Action); } else if (action == addCartesianPlot3Action) { CartesianPlot* plot = new CartesianPlot(i18n("xy-plot")); plot->initDefault(CartesianPlot::TwoAxesCentered); plot->setMouseMode(m_cartesianPlotMouseMode); aspect = plot; if (tbNewCartesianPlot) tbNewCartesianPlot->setDefaultAction(addCartesianPlot3Action); } else if (action == addCartesianPlot4Action) { CartesianPlot* plot = new CartesianPlot(i18n("xy-plot")); plot->initDefault(CartesianPlot::TwoAxesCenteredZero); plot->setMouseMode(m_cartesianPlotMouseMode); aspect = plot; if (tbNewCartesianPlot) tbNewCartesianPlot->setDefaultAction(addCartesianPlot4Action); } else if (action == addTextLabelAction) { TextLabel* l = new TextLabel(i18n("Text Label")); l->setText(i18n("Text Label")); aspect = l; } else if (action == addImageAction) { Image* l = new Image(i18n("Image")); aspect = l; } if (!aspect) return; m_worksheet->addChild(aspect); //labels and images with their initial positions need to be retransformed //ater they have gotten a parent if (aspect->type() == AspectType::TextLabel || aspect->type() == AspectType::Image) aspect->retransform(); handleCartesianPlotActions(); if (!m_fadeInTimeLine) { m_fadeInTimeLine = new QTimeLine(1000, this); m_fadeInTimeLine->setFrameRange(0, 100); connect(m_fadeInTimeLine, &QTimeLine::valueChanged, this, &WorksheetView::fadeIn); } //if there is already an element fading in, stop the time line and show the element with the full opacity. if (m_fadeInTimeLine->state() == QTimeLine::Running) { m_fadeInTimeLine->stop(); auto* effect = new QGraphicsOpacityEffect(); effect->setOpacity(1); lastAddedWorksheetElement->graphicsItem()->setGraphicsEffect(effect); } //fade-in the newly added element lastAddedWorksheetElement = aspect; auto* effect = new QGraphicsOpacityEffect(); effect->setOpacity(0); lastAddedWorksheetElement->graphicsItem()->setGraphicsEffect(effect); m_fadeInTimeLine->start(); } /*! * select all top-level items */ void WorksheetView::selectAllElements() { //deselect all previously selected items since there can be some non top-level items belong them m_suppressSelectionChangedEvent = true; for (auto* item : m_selectedItems) m_worksheet->setItemSelectedInView(item, false); //select top-level items for (auto* item : scene()->items()) { if (!item->parentItem()) item->setSelected(true); } m_suppressSelectionChangedEvent = false; this->selectionChanged(); } /*! * deletes selected worksheet elements */ void WorksheetView::deleteElement() { if (m_selectedItems.isEmpty()) return; int rc = KMessageBox::warningYesNo( this, i18np("Do you really want to delete the selected object?", "Do you really want to delete the selected %1 objects?", m_selectedItems.size()), i18np("Delete selected object", "Delete selected objects", m_selectedItems.size())); if (rc == KMessageBox::No) return; m_suppressSelectionChangedEvent = true; m_worksheet->beginMacro(i18n("%1: Remove selected worksheet elements.", m_worksheet->name())); for (auto* item : m_selectedItems) m_worksheet->deleteAspectFromGraphicsItem(item); m_worksheet->endMacro(); m_suppressSelectionChangedEvent = false; } void WorksheetView::aspectAboutToBeRemoved(const AbstractAspect* aspect) { lastAddedWorksheetElement = dynamic_cast(const_cast(aspect)); if (!lastAddedWorksheetElement) return; //FIXME: fading-out doesn't work //also, the following code collides with undo/redo of the deletion //of a worksheet element (after redoing the element is not shown with the full opacity /* if (!m_fadeOutTimeLine) { m_fadeOutTimeLine = new QTimeLine(1000, this); m_fadeOutTimeLine->setFrameRange(0, 100); connect(m_fadeOutTimeLine, SIGNAL(valueChanged(qreal)), this, SLOT(fadeOut(qreal))); } //if there is already an element fading out, stop the time line if (m_fadeOutTimeLine->state() == QTimeLine::Running) m_fadeOutTimeLine->stop(); m_fadeOutTimeLine->start(); */ } void WorksheetView::fadeIn(qreal value) { auto* effect = new QGraphicsOpacityEffect(); effect->setOpacity(value); lastAddedWorksheetElement->graphicsItem()->setGraphicsEffect(effect); } void WorksheetView::fadeOut(qreal value) { auto* effect = new QGraphicsOpacityEffect(); effect->setOpacity(1 - value); lastAddedWorksheetElement->graphicsItem()->setGraphicsEffect(effect); } /*! * called when one of the layout-actions in WorkseetView was triggered. * sets the layout in Worksheet and enables/disables the layout actions. */ void WorksheetView::changeLayout(QAction* action) { if (action == breakLayoutAction) { verticalLayoutAction->setEnabled(true); verticalLayoutAction->setChecked(false); horizontalLayoutAction->setEnabled(true); horizontalLayoutAction->setChecked(false); gridLayoutAction->setEnabled(true); gridLayoutAction->setChecked(false); breakLayoutAction->setEnabled(false); m_worksheet->setLayout(Worksheet::Layout::NoLayout); } else { verticalLayoutAction->setEnabled(false); horizontalLayoutAction->setEnabled(false); gridLayoutAction->setEnabled(false); breakLayoutAction->setEnabled(true); if (action == verticalLayoutAction) { verticalLayoutAction->setChecked(true); m_worksheet->setLayout(Worksheet::Layout::VerticalLayout); } else if (action == horizontalLayoutAction) { horizontalLayoutAction->setChecked(true); m_worksheet->setLayout(Worksheet::Layout::HorizontalLayout); } else { gridLayoutAction->setChecked(true); m_worksheet->setLayout(Worksheet::Layout::GridLayout); } } } void WorksheetView::changeGrid(QAction* action) { if (action == noGridAction) { m_gridSettings.style = WorksheetView::NoGrid; snapToGridAction->setEnabled(false); } else if (action == sparseLineGridAction) { m_gridSettings.style = WorksheetView::LineGrid; m_gridSettings.color = Qt::gray; m_gridSettings.opacity = 0.7; m_gridSettings.horizontalSpacing = 15; m_gridSettings.verticalSpacing = 15; } else if (action == denseLineGridAction) { m_gridSettings.style = WorksheetView::LineGrid; m_gridSettings.color = Qt::gray; m_gridSettings.opacity = 0.7; m_gridSettings.horizontalSpacing = 5; m_gridSettings.verticalSpacing = 5; } else if (action == denseDotGridAction) { m_gridSettings.style = WorksheetView::DotGrid; m_gridSettings.color = Qt::black; m_gridSettings.opacity = 0.7; m_gridSettings.horizontalSpacing = 5; m_gridSettings.verticalSpacing = 5; } else if (action == sparseDotGridAction) { m_gridSettings.style = WorksheetView::DotGrid; m_gridSettings.color = Qt::black; m_gridSettings.opacity = 0.7; m_gridSettings.horizontalSpacing = 15; m_gridSettings.verticalSpacing = 15; } else if (action == customGridAction) { auto* dlg = new GridDialog(this); if (dlg->exec() == QDialog::Accepted) dlg->save(m_gridSettings); else return; } if (m_gridSettings.style == WorksheetView::NoGrid) snapToGridAction->setEnabled(false); else snapToGridAction->setEnabled(true); invalidateScene(sceneRect(), QGraphicsScene::BackgroundLayer); } //TODO void WorksheetView::changeSnapToGrid() { } /*! * Selects the QGraphicsItem \c item in \c WorksheetView. * The selection in \c ProjectExplorer is forwarded to \c Worksheet * and is finally handled here. */ void WorksheetView::selectItem(QGraphicsItem* item) { m_suppressSelectionChangedEvent = true; item->setSelected(true); m_selectedItems<setSelected(false); m_selectedItems.removeOne(item); handleCartesianPlotActions(); m_suppressSelectionChangedEvent = false; } /*! * Called on selection changes in the view. * Determines which items were selected and deselected * and forwards these changes to \c Worksheet */ void WorksheetView::selectionChanged() { //if the project is being closed, the scene items are being removed and the selection can change. //don't react on these changes since this can lead crashes (worksheet object is already in the destructor). if (m_isClosing) return; if (m_suppressSelectionChangedEvent) return; QList items = scene()->selectedItems(); //When making a graphics item invisible, it gets deselected in the scene. //In this case we don't want to deselect the item in the project explorer. bool invisibleDeselected = false; //check, whether the previously selected items were deselected now. //Forward the deselection prior to the selection of new items //in order to avoid the unwanted multiple selection in project explorer for (auto* item : m_selectedItems ) { if ( items.indexOf(item) == -1 ) { if (item->isVisible()) m_worksheet->setItemSelectedInView(item, false); else invisibleDeselected = true; } } //select new items if (items.isEmpty() && invisibleDeselected == false) { //no items selected -> select the worksheet again. m_worksheet->setSelectedInView(true); //if one of the "zoom&select" plot mouse modes was selected before, activate the default "selection mode" again //since no plots are selected now. if (m_mouseMode == SelectionMode && m_cartesianPlotMouseMode!= CartesianPlot::SelectionMode) { cartesianPlotSelectionModeAction->setChecked(true); cartesianPlotMouseModeChanged(cartesianPlotSelectionModeAction); } } else { for (const auto* item : items) m_worksheet->setItemSelectedInView(item, true); //items selected -> deselect the worksheet in the project explorer //prevents unwanted multiple selection with worksheet (if it was selected before) m_worksheet->setSelectedInView(false); } m_selectedItems = items; handleCartesianPlotActions(); } //check whether we have cartesian plots selected and activate/deactivate void WorksheetView::handleCartesianPlotActions() { if (!m_menusInitialized) return; bool plot = false; if (m_worksheet->cartesianPlotActionMode() == Worksheet::CartesianPlotActionMode::ApplyActionToSelection) { //check whether we have cartesian plots selected for (auto* item : m_selectedItems) { //TODO: or if a children of a plot is selected if (item->data(0).toInt() == static_cast(WorksheetElement::WorksheetElementName::NameCartesianPlot)) { plot = true; break; } } } else { //actions are applied to all available plots -> check whether we have plots plot = (m_worksheet->children().size() != 0); } cartesianPlotSelectionModeAction->setEnabled(plot); cartesianPlotZoomSelectionModeAction->setEnabled(plot); cartesianPlotZoomXSelectionModeAction->setEnabled(plot); cartesianPlotZoomYSelectionModeAction->setEnabled(plot); cartesianPlotCursorModeAction->setEnabled(plot); m_cartesianPlotAddNewMenu->setEnabled(plot); m_cartesianPlotZoomMenu->setEnabled(plot); m_cartesianPlotMouseModeMenu->setEnabled(plot); // analysis menu //TODO: enable also if children of plots are selected // m_dataManipulationMenu->setEnabled(plot); // addDataOperationAction->setEnabled(false); addDataReductionAction->setEnabled(false); addDifferentiationAction->setEnabled(plot); addIntegrationAction->setEnabled(plot); addInterpolationAction->setEnabled(plot); addSmoothAction->setEnabled(plot); addFitAction->setEnabled(plot); addFourierFilterAction->setEnabled(plot); addFourierTransformAction->setEnabled(plot); addConvolutionAction->setEnabled(plot); addCorrelationAction->setEnabled(plot); } void WorksheetView::exportToFile(const QString& path, const ExportFormat format, const ExportArea area, const bool background, const int resolution) { QRectF sourceRect; //determine the rectangular to print if (area == WorksheetView::ExportBoundingBox) sourceRect = scene()->itemsBoundingRect(); else if (area == WorksheetView::ExportSelection) { //TODO doesn't work: rect = scene()->selectionArea().boundingRect(); for (const auto* item : m_selectedItems) sourceRect = sourceRect.united( item->mapToScene(item->boundingRect()).boundingRect() ); } else sourceRect = scene()->sceneRect(); //print if (format == WorksheetView::Pdf) { QPrinter printer(QPrinter::HighResolution); printer.setOutputFormat(QPrinter::PdfFormat); printer.setOutputFileName(path); int w = Worksheet::convertFromSceneUnits(sourceRect.width(), Worksheet::Unit::Millimeter); int h = Worksheet::convertFromSceneUnits(sourceRect.height(), Worksheet::Unit::Millimeter); printer.setPaperSize( QSizeF(w, h), QPrinter::Millimeter); printer.setPageMargins(0,0,0,0, QPrinter::Millimeter); printer.setPrintRange(QPrinter::PageRange); printer.setCreator(QLatin1String("LabPlot ") + LVERSION); QPainter painter(&printer); painter.setRenderHint(QPainter::Antialiasing); QRectF targetRect(0, 0, painter.device()->width(),painter.device()->height()); painter.begin(&printer); exportPaint(&painter, targetRect, sourceRect, background); painter.end(); } else if (format == WorksheetView::Svg) { QSvgGenerator generator; generator.setFileName(path); // if (!generator.isValid()) { // RESET_CURSOR; // QMessageBox::critical(nullptr, i18n("Failed to export"), i18n("Failed to write to '%1'. Please check the path.", path)); // } int w = Worksheet::convertFromSceneUnits(sourceRect.width(), Worksheet::Unit::Millimeter); int h = Worksheet::convertFromSceneUnits(sourceRect.height(), Worksheet::Unit::Millimeter); w = w*QApplication::desktop()->physicalDpiX()/25.4; h = h*QApplication::desktop()->physicalDpiY()/25.4; generator.setSize(QSize(w, h)); QRectF targetRect(0, 0, w, h); generator.setViewBox(targetRect); QPainter painter; painter.begin(&generator); exportPaint(&painter, targetRect, sourceRect, background); painter.end(); } else { //PNG //TODO add all formats supported by Qt in QImage int w = Worksheet::convertFromSceneUnits(sourceRect.width(), Worksheet::Unit::Millimeter); int h = Worksheet::convertFromSceneUnits(sourceRect.height(), Worksheet::Unit::Millimeter); w = w*resolution/25.4; h = h*resolution/25.4; QImage image(QSize(w, h), QImage::Format_ARGB32_Premultiplied); image.fill(Qt::transparent); QRectF targetRect(0, 0, w, h); QPainter painter; painter.begin(&image); painter.setRenderHint(QPainter::Antialiasing); exportPaint(&painter, targetRect, sourceRect, background); painter.end(); if (!path.isEmpty()) { bool rc = image.save(path, "PNG"); if (!rc) { RESET_CURSOR; QMessageBox::critical(nullptr, i18n("Failed to export"), i18n("Failed to write to '%1'. Please check the path.", path)); } } else QApplication::clipboard()->setImage(image, QClipboard::Clipboard); } } void WorksheetView::exportToClipboard() { QRectF sourceRect; if (m_selectedItems.size() == 0) sourceRect = scene()->itemsBoundingRect(); else { //export selection for (const auto* item : m_selectedItems) sourceRect = sourceRect.united( item->mapToScene(item->boundingRect()).boundingRect() ); } int w = Worksheet::convertFromSceneUnits(sourceRect.width(), Worksheet::Unit::Millimeter); int h = Worksheet::convertFromSceneUnits(sourceRect.height(), Worksheet::Unit::Millimeter); w = w*QApplication::desktop()->physicalDpiX()/25.4; h = h*QApplication::desktop()->physicalDpiY()/25.4; QImage image(QSize(w, h), QImage::Format_ARGB32_Premultiplied); image.fill(Qt::transparent); QRectF targetRect(0, 0, w, h); QPainter painter; painter.begin(&image); painter.setRenderHint(QPainter::Antialiasing); exportPaint(&painter, targetRect, sourceRect, true); painter.end(); QApplication::clipboard()->setImage(image, QClipboard::Clipboard); } void WorksheetView::exportPaint(QPainter* painter, const QRectF& targetRect, const QRectF& sourceRect, const bool background) { //draw the background if (background) { painter->save(); painter->scale(targetRect.width()/sourceRect.width(), targetRect.height()/sourceRect.height()); drawBackground(painter, sourceRect); painter->restore(); } //draw the scene items m_worksheet->setPrinting(true); scene()->render(painter, QRectF(), sourceRect); m_worksheet->setPrinting(false); } void WorksheetView::print(QPrinter* printer) { m_worksheet->setPrinting(true); QPainter painter(printer); painter.setRenderHint(QPainter::Antialiasing); // draw background QRectF page_rect = printer->pageRect(); QRectF scene_rect = scene()->sceneRect(); float scale = qMax(scene_rect.width()/page_rect.width(),scene_rect.height()/page_rect.height()); drawBackgroundItems(&painter, QRectF(0,0,scene_rect.width()/scale,scene_rect.height()/scale)); // draw scene scene()->render(&painter); m_worksheet->setPrinting(false); } void WorksheetView::updateBackground() { invalidateScene(sceneRect(), QGraphicsScene::BackgroundLayer); } /*! * called when the layout was changed in Worksheet, * enables the corresponding action */ void WorksheetView::layoutChanged(Worksheet::Layout layout) { if (layout == Worksheet::Layout::NoLayout) { verticalLayoutAction->setEnabled(true); verticalLayoutAction->setChecked(false); horizontalLayoutAction->setEnabled(true); horizontalLayoutAction->setChecked(false); gridLayoutAction->setEnabled(true); gridLayoutAction->setChecked(false); breakLayoutAction->setEnabled(false); } else { verticalLayoutAction->setEnabled(false); horizontalLayoutAction->setEnabled(false); gridLayoutAction->setEnabled(false); breakLayoutAction->setEnabled(true); if (layout == Worksheet::Layout::VerticalLayout) verticalLayoutAction->setChecked(true); else if (layout == Worksheet::Layout::HorizontalLayout) horizontalLayoutAction->setChecked(true); else gridLayoutAction->setChecked(true); } } void WorksheetView::registerShortcuts() { selectAllAction->setShortcut(Qt::CTRL+Qt::Key_A); deleteAction->setShortcut(Qt::Key_Delete); backspaceAction->setShortcut(Qt::Key_Backspace); zoomInViewAction->setShortcut(Qt::CTRL+Qt::Key_Plus); zoomOutViewAction->setShortcut(Qt::CTRL+Qt::Key_Minus); zoomOriginAction->setShortcut(Qt::CTRL+Qt::Key_1); } void WorksheetView::unregisterShortcuts() { selectAllAction->setShortcut(QKeySequence()); deleteAction->setShortcut(QKeySequence()); backspaceAction->setShortcut(QKeySequence()); zoomInViewAction->setShortcut(QKeySequence()); zoomOutViewAction->setShortcut(QKeySequence()); zoomOriginAction->setShortcut(QKeySequence()); } //############################################################################## //######################## SLOTs for cartesian plots ######################## //############################################################################## void WorksheetView::cartesianPlotActionModeChanged(QAction* action) { if (action == cartesianPlotApplyToSelectionAction) m_worksheet->setCartesianPlotActionMode(Worksheet::CartesianPlotActionMode::ApplyActionToSelection); else m_worksheet->setCartesianPlotActionMode(Worksheet::CartesianPlotActionMode::ApplyActionToAll); handleCartesianPlotActions(); } void WorksheetView::cartesianPlotCursorModeChanged(QAction* action) { if (action == cartesianPlotApplyToSelectionCursor) m_worksheet->setCartesianPlotCursorMode(Worksheet::CartesianPlotActionMode::ApplyActionToSelection); else m_worksheet->setCartesianPlotCursorMode(Worksheet::CartesianPlotActionMode::ApplyActionToAll); handleCartesianPlotActions(); } void WorksheetView::plotsLockedActionChanged(bool checked) { m_worksheet->setPlotsLocked(checked); } void WorksheetView::cartesianPlotMouseModeChanged(QAction* action) { if (m_suppressMouseModeChange) return; if (action == cartesianPlotSelectionModeAction) m_cartesianPlotMouseMode = CartesianPlot::SelectionMode; else if (action == cartesianPlotZoomSelectionModeAction) m_cartesianPlotMouseMode = CartesianPlot::ZoomSelectionMode; else if (action == cartesianPlotZoomXSelectionModeAction) m_cartesianPlotMouseMode = CartesianPlot::ZoomXSelectionMode; else if (action == cartesianPlotZoomYSelectionModeAction) m_cartesianPlotMouseMode = CartesianPlot::ZoomYSelectionMode; else if (action == cartesianPlotCursorModeAction) m_cartesianPlotMouseMode = CartesianPlot::Cursor; for (auto* plot : m_worksheet->children() ) plot->setMouseMode(m_cartesianPlotMouseMode); } void WorksheetView::cartesianPlotMouseModeChangedSlot(CartesianPlot::MouseMode mouseMode) { if (!m_menusInitialized) return; m_suppressMouseModeChange = true; if (mouseMode == CartesianPlot::MouseMode::SelectionMode) cartesianPlotSelectionModeAction->setChecked(true); else if (mouseMode == CartesianPlot::MouseMode::ZoomSelectionMode) cartesianPlotZoomSelectionModeAction->setChecked(true); else if (mouseMode == CartesianPlot::MouseMode::ZoomXSelectionMode) cartesianPlotZoomXSelectionModeAction->setChecked(true); else if (mouseMode == CartesianPlot::MouseMode::ZoomYSelectionMode) cartesianPlotZoomYSelectionModeAction->setChecked(true); else if (mouseMode == CartesianPlot::MouseMode::Cursor) cartesianPlotCursorModeAction->setChecked(true); m_suppressMouseModeChange = false; } void WorksheetView::cartesianPlotAddNew(QAction* action) { QVector plots = m_worksheet->children(); if (m_worksheet->cartesianPlotActionMode() == Worksheet::CartesianPlotActionMode::ApplyActionToSelection) { int selectedPlots = 0; for (auto* plot : plots) { if (m_selectedItems.indexOf(plot->graphicsItem()) != -1) ++selectedPlots; else { //current plot is not selected, check if one of its children is selected auto children = plot->children(); for (auto* child : children) { if (m_selectedItems.indexOf(child->graphicsItem()) != -1) { ++selectedPlots; break; } } } } if (selectedPlots > 1) m_worksheet->beginMacro(i18n("%1: Add curve to %2 plots", m_worksheet->name(), selectedPlots)); for (auto* plot : plots) { if (m_selectedItems.indexOf(plot->graphicsItem()) != -1) this->cartesianPlotAdd(plot, action); else { //current plot is not selected, check if one of its children is selected auto children = plot->children(); for (auto* child : children) { if (m_selectedItems.indexOf(child->graphicsItem()) != -1) { this->cartesianPlotAdd(plot, action); break; } } } } if (selectedPlots > 1) m_worksheet->endMacro(); } else { if (plots.size() > 1) m_worksheet->beginMacro(i18n("%1: Add curve to %2 plots", m_worksheet->name(), plots.size())); for (auto* plot : plots) this->cartesianPlotAdd(plot, action); if (plots.size() > 1) m_worksheet->endMacro(); } } void WorksheetView::cartesianPlotAdd(CartesianPlot* plot, QAction* action) { DEBUG("WorksheetView::cartesianPlotAdd()"); if (action == addCurveAction) plot->addCurve(); else if (action == addHistogramAction) plot->addHistogram(); else if (action == addEquationCurveAction) plot->addEquationCurve(); else if (action == addDataReductionCurveAction) plot->addDataReductionCurve(); else if (action == addDifferentiationCurveAction) plot->addDifferentiationCurve(); else if (action == addIntegrationCurveAction) plot->addIntegrationCurve(); else if (action == addInterpolationCurveAction) plot->addInterpolationCurve(); else if (action == addSmoothCurveAction) plot->addSmoothCurve(); else if (action == addFitCurveAction) plot->addFitCurve(); else if (action == addFourierFilterCurveAction) plot->addFourierFilterCurve(); else if (action == addFourierTransformCurveAction) plot->addFourierTransformCurve(); else if (action == addConvolutionCurveAction) plot->addConvolutionCurve(); else if (action == addCorrelationCurveAction) plot->addCorrelationCurve(); else if (action == addLegendAction) plot->addLegend(); else if (action == addHorizontalAxisAction) plot->addHorizontalAxis(); else if (action == addVerticalAxisAction) plot->addVerticalAxis(); else if (action == addPlotTextLabelAction) plot->addTextLabel(); else if (action == addPlotImageAction) plot->addImage(); else if (action == addCustomPointAction) plot->addCustomPoint(); // analysis actions else if (action == addDataReductionAction) plot->addDataReductionCurve(); else if (action == addDifferentiationAction) plot->addDifferentiationCurve(); else if (action == addIntegrationAction) plot->addIntegrationCurve(); else if (action == addInterpolationAction) plot->addInterpolationCurve(); else if (action == addSmoothAction) plot->addSmoothCurve(); else if (action == addFitAction) plot->addFitCurve(); else if (action == addFourierFilterAction) plot->addFourierFilterCurve(); else if (action == addFourierTransformAction) plot->addFourierTransformCurve(); else if (action == addConvolutionAction) plot->addConvolutionCurve(); else if (action == addCorrelationAction) plot->addCorrelationCurve(); } void WorksheetView::cartesianPlotNavigationChanged(QAction* action) { CartesianPlot::NavigationOperation op = (CartesianPlot::NavigationOperation)action->data().toInt(); if (m_worksheet->cartesianPlotActionMode() == Worksheet::CartesianPlotActionMode::ApplyActionToSelection) { for (auto* plot : m_worksheet->children() ) { if (m_selectedItems.indexOf(plot->graphicsItem()) != -1) plot->navigate(op); else { // check if one of the plots childrend is selected. Do the operation there too. for (auto* child : plot->children()) { if (m_selectedItems.indexOf(child->graphicsItem()) != -1) { plot->navigate(op); break; } } } } } else { for (auto* plot : m_worksheet->children() ) plot->navigate(op); } } Worksheet::CartesianPlotActionMode WorksheetView::getCartesianPlotActionMode() { return m_worksheet->cartesianPlotActionMode(); } void WorksheetView::presenterMode() { KConfigGroup group = KSharedConfig::openConfig()->group("Settings_Worksheet"); //show dynamic presenter widget, if enabled if (group.readEntry("PresenterModeInteractive", false)) { auto* dynamicPresenterWidget = new DynamicPresenterWidget(m_worksheet); dynamicPresenterWidget->showFullScreen(); return; } //show static presenter widget (default) QRectF sourceRect(scene()->sceneRect()); int w = Worksheet::convertFromSceneUnits(sourceRect.width(), Worksheet::Unit::Millimeter); int h = Worksheet::convertFromSceneUnits(sourceRect.height(), Worksheet::Unit::Millimeter); w *= QApplication::desktop()->physicalDpiX()/25.4; h *= QApplication::desktop()->physicalDpiY()/25.4; QRectF targetRect(0, 0, w, h); const QRectF& screenSize = QGuiApplication::primaryScreen()->availableGeometry();; if (targetRect.width() > screenSize.width() || ((targetRect.height() > screenSize.height()))) { const double ratio = qMin(screenSize.width() / targetRect.width(), screenSize.height() / targetRect.height()); targetRect.setWidth(targetRect.width()* ratio); targetRect.setHeight(targetRect.height() * ratio); } QImage image(QSize(targetRect.width(), targetRect.height()), QImage::Format_ARGB32_Premultiplied); image.fill(Qt::transparent); QPainter painter; painter.begin(&image); painter.setRenderHint(QPainter::Antialiasing); exportPaint(&painter, targetRect, sourceRect, true); painter.end(); PresenterWidget* presenterWidget = new PresenterWidget(QPixmap::fromImage(image), m_worksheet->name()); presenterWidget->showFullScreen(); } diff --git a/src/kdefrontend/dockwidgets/CartesianPlotDock.cpp b/src/kdefrontend/dockwidgets/CartesianPlotDock.cpp index 1e8991877..e124c8711 100644 --- a/src/kdefrontend/dockwidgets/CartesianPlotDock.cpp +++ b/src/kdefrontend/dockwidgets/CartesianPlotDock.cpp @@ -1,1834 +1,1823 @@ /*************************************************************************** File : CartesianPlotDock.cpp Project : LabPlot Description : widget for cartesian plot properties -------------------------------------------------------------------- Copyright : (C) 2011-2020 by Alexander Semke (alexander.semke@web.de) Copyright : (C) 2012-2013 by Stefan Gerlach (stefan.gerlach@uni-konstanz.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 * * * ***************************************************************************/ #include "CartesianPlotDock.h" #include "backend/worksheet/plots/PlotArea.h" #include "backend/worksheet/plots/cartesian/XYCurve.h" #include "backend/core/column/Column.h" #include "kdefrontend/widgets/LabelWidget.h" #include "kdefrontend/GuiTools.h" #include "kdefrontend/TemplateHandler.h" #include "kdefrontend/ThemeHandler.h" #include #include #include #include #include #include #include #include #include #include /*! \class CartesianPlotDock \brief Provides a widget for editing the properties of the cartesian plot currently selected in the project explorer. \ingroup kdefrontend */ CartesianPlotDock::CartesianPlotDock(QWidget* parent) : BaseDock(parent) { ui.setupUi(this); m_leName = ui.leName; m_leComment = ui.leComment; //"General"-tab auto* rangeButtonsGroup(new QButtonGroup); rangeButtonsGroup->addButton(ui.rbRangeFirst); rangeButtonsGroup->addButton(ui.rbRangeLast); rangeButtonsGroup->addButton(ui.rbRangeFree); //"Range breaks"-tab ui.bAddXBreak->setIcon( QIcon::fromTheme("list-add") ); ui.bRemoveXBreak->setIcon( QIcon::fromTheme("list-remove") ); ui.cbXBreak->addItem("1"); ui.bAddYBreak->setIcon( QIcon::fromTheme("list-add") ); ui.bRemoveYBreak->setIcon( QIcon::fromTheme("list-remove") ); ui.cbYBreak->addItem("1"); //"Background"-tab ui.bOpen->setIcon( QIcon::fromTheme("document-open") ); ui.leBackgroundFileName->setCompleter(new QCompleter(new QDirModel, this)); //"Title"-tab auto* hboxLayout = new QHBoxLayout(ui.tabTitle); labelWidget = new LabelWidget(ui.tabTitle); hboxLayout->addWidget(labelWidget); hboxLayout->setContentsMargins(2,2,2,2); hboxLayout->setSpacing(2); //adjust layouts in the tabs for (int i = 0; i < ui.tabWidget->count(); ++i) { auto* layout = qobject_cast(ui.tabWidget->widget(i)->layout()); if (!layout) continue; layout->setContentsMargins(2,2,2,2); layout->setHorizontalSpacing(2); layout->setVerticalSpacing(2); } // "Cursor"-tab QStringList list = {i18n("NoPen"), i18n("SolidLine"), i18n("DashLine"), i18n("DotLine"), i18n("DashDotLine"), i18n("DashDotDotLine")}; ui.cbCursorLineStyle->clear(); for (int i = 0; i < list.count(); i++) ui.cbCursorLineStyle->addItem(list[i], i); //Validators ui.leRangeFirst->setValidator( new QIntValidator(ui.leRangeFirst) ); ui.leRangeLast->setValidator( new QIntValidator(ui.leRangeLast) ); ui.leXBreakStart->setValidator( new QDoubleValidator(ui.leXBreakStart) ); ui.leXBreakEnd->setValidator( new QDoubleValidator(ui.leXBreakEnd) ); ui.leYBreakStart->setValidator( new QDoubleValidator(ui.leYBreakStart) ); ui.leYBreakEnd->setValidator( new QDoubleValidator(ui.leYBreakEnd) ); //SIGNAL/SLOT //General connect(ui.leName, &QLineEdit::textChanged, this, &CartesianPlotDock::nameChanged); connect(ui.leComment, &QLineEdit::textChanged, this, &CartesianPlotDock::commentChanged); connect( ui.chkVisible, SIGNAL(clicked(bool)), this, SLOT(visibilityChanged(bool)) ); connect( ui.sbLeft, SIGNAL(valueChanged(double)), this, SLOT(geometryChanged()) ); connect( ui.sbTop, SIGNAL(valueChanged(double)), this, SLOT(geometryChanged()) ); connect( ui.sbWidth, SIGNAL(valueChanged(double)), this, SLOT(geometryChanged()) ); connect( ui.sbHeight, SIGNAL(valueChanged(double)), this, SLOT(geometryChanged()) ); connect( ui.leRangeFirst, SIGNAL(textChanged(QString)), this, SLOT(rangeFirstChanged(QString)) ); connect( ui.leRangeLast, SIGNAL(textChanged(QString)), this, SLOT(rangeLastChanged(QString)) ); connect( rangeButtonsGroup, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(rangeTypeChanged()) ); connect(ui.chkAutoScaleX, &QCheckBox::stateChanged, this, &CartesianPlotDock::autoScaleXChanged); connect(ui.leXMin, &QLineEdit::textChanged, this, &CartesianPlotDock::xMinChanged); connect(ui.leXMax, &QLineEdit::textChanged, this, &CartesianPlotDock::xMaxChanged); connect(ui.dateTimeEditXMin, &QDateTimeEdit::dateTimeChanged, this, &CartesianPlotDock::xMinDateTimeChanged); connect(ui.dateTimeEditXMax, &QDateTimeEdit::dateTimeChanged, this, &CartesianPlotDock::xMaxDateTimeChanged); connect( ui.cbXScaling, SIGNAL(currentIndexChanged(int)), this, SLOT(xScaleChanged(int)) ); connect(ui.cbXRangeFormat, static_cast(&QComboBox::currentIndexChanged), this, &CartesianPlotDock::xRangeFormatChanged); connect(ui.chkAutoScaleY, &QCheckBox::stateChanged, this, &CartesianPlotDock::autoScaleYChanged); connect(ui.leYMin, &QLineEdit::textChanged, this, &CartesianPlotDock::yMinChanged); connect(ui.leYMax, &QLineEdit::textChanged, this, &CartesianPlotDock::yMaxChanged); connect(ui.dateTimeEditYMin, &QDateTimeEdit::dateTimeChanged, this, &CartesianPlotDock::yMinDateTimeChanged); connect(ui.dateTimeEditYMax, &QDateTimeEdit::dateTimeChanged, this, &CartesianPlotDock::yMaxDateTimeChanged); connect( ui.cbYScaling, SIGNAL(currentIndexChanged(int)), this, SLOT(yScaleChanged(int)) ); connect(ui.cbYRangeFormat, static_cast(&QComboBox::currentIndexChanged), this, &CartesianPlotDock::yRangeFormatChanged); //Range breaks connect( ui.chkXBreak, SIGNAL(toggled(bool)), this, SLOT(toggleXBreak(bool)) ); connect( ui.bAddXBreak, SIGNAL(clicked()), this, SLOT(addXBreak()) ); connect( ui.bRemoveXBreak, SIGNAL(clicked()), this, SLOT(removeXBreak()) ); connect( ui.cbXBreak, SIGNAL(currentIndexChanged(int)), this, SLOT(currentXBreakChanged(int)) ); connect( ui.leXBreakStart, SIGNAL(textChanged(QString)), this, SLOT(xBreakStartChanged()) ); connect( ui.leXBreakEnd, SIGNAL(textChanged(QString)), this, SLOT(xBreakEndChanged()) ); connect( ui.sbXBreakPosition, SIGNAL(valueChanged(int)), this, SLOT(xBreakPositionChanged(int)) ); connect( ui.cbXBreakStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(xBreakStyleChanged(int)) ); connect( ui.chkYBreak, SIGNAL(toggled(bool)), this, SLOT(toggleYBreak(bool)) ); connect( ui.bAddYBreak, SIGNAL(clicked()), this, SLOT(addYBreak()) ); connect( ui.bRemoveYBreak, SIGNAL(clicked()), this, SLOT(removeYBreak()) ); connect( ui.cbYBreak, SIGNAL(currentIndexChanged(int)), this, SLOT(currentYBreakChanged(int)) ); connect( ui.leYBreakStart, SIGNAL(textChanged(QString)), this, SLOT(yBreakStartChanged()) ); connect( ui.leYBreakEnd, SIGNAL(textChanged(QString)), this, SLOT(yBreakEndChanged()) ); connect( ui.sbYBreakPosition, SIGNAL(valueChanged(int)), this, SLOT(yBreakPositionChanged(int)) ); connect( ui.cbYBreakStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(yBreakStyleChanged(int)) ); //Background connect( ui.cbBackgroundType, SIGNAL(currentIndexChanged(int)), this, SLOT(backgroundTypeChanged(int)) ); connect( ui.cbBackgroundColorStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(backgroundColorStyleChanged(int)) ); connect( ui.cbBackgroundImageStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(backgroundImageStyleChanged(int)) ); connect( ui.cbBackgroundBrushStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(backgroundBrushStyleChanged(int)) ); connect( ui.bOpen, SIGNAL(clicked(bool)), this, SLOT(selectFile()) ); connect( ui.leBackgroundFileName, SIGNAL(textChanged(QString)), this, SLOT(fileNameChanged()) ); connect( ui.leBackgroundFileName, SIGNAL(textChanged(QString)), this, SLOT(fileNameChanged()) ); connect( ui.kcbBackgroundFirstColor, SIGNAL(changed(QColor)), this, SLOT(backgroundFirstColorChanged(QColor)) ); connect( ui.kcbBackgroundSecondColor, SIGNAL(changed(QColor)), this, SLOT(backgroundSecondColorChanged(QColor)) ); connect( ui.sbBackgroundOpacity, SIGNAL(valueChanged(int)), this, SLOT(backgroundOpacityChanged(int)) ); //Border connect( ui.cbBorderStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(borderStyleChanged(int)) ); connect( ui.kcbBorderColor, SIGNAL(changed(QColor)), this, SLOT(borderColorChanged(QColor)) ); connect( ui.sbBorderWidth, SIGNAL(valueChanged(double)), this, SLOT(borderWidthChanged(double)) ); connect( ui.sbBorderCornerRadius, SIGNAL(valueChanged(double)), this, SLOT(borderCornerRadiusChanged(double)) ); connect( ui.sbBorderOpacity, SIGNAL(valueChanged(int)), this, SLOT(borderOpacityChanged(int)) ); //Padding connect( ui.sbPaddingHorizontal, SIGNAL(valueChanged(double)), this, SLOT(horizontalPaddingChanged(double)) ); connect( ui.sbPaddingVertical, SIGNAL(valueChanged(double)), this, SLOT(verticalPaddingChanged(double)) ); connect( ui.sbPaddingRight, static_cast(&QDoubleSpinBox::valueChanged), this, &CartesianPlotDock::rightPaddingChanged); connect( ui.sbPaddingBottom, static_cast(&QDoubleSpinBox::valueChanged), this, &CartesianPlotDock::bottomPaddingChanged); connect( ui.cbPaddingSymmetric, &QCheckBox::toggled, this, &CartesianPlotDock::symmetricPaddingChanged); // Cursor connect(ui.sbCursorLineWidth, SIGNAL(valueChanged(int)), this, SLOT(cursorLineWidthChanged(int))); //connect(ui.sbCursorLineWidth, qOverload(&QDoubleSpinBox::valueChanged), this, &CartesianPlotDock::cursorLineWidthChanged); connect(ui.kcbCursorLineColor, &KColorButton::changed, this, &CartesianPlotDock::cursorLineColorChanged); //connect(ui.cbCursorLineStyle, qOverload(&QComboBox::currentIndexChanged), this, &CartesianPlotDock::cursorLineStyleChanged); connect(ui.cbCursorLineStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(cursorLineStyleChanged(int))); //theme and template handlers auto* frame = new QFrame(this); auto* layout = new QHBoxLayout(frame); layout->setContentsMargins(0, 11, 0, 11); m_themeHandler = new ThemeHandler(this); layout->addWidget(m_themeHandler); connect(m_themeHandler, SIGNAL(loadThemeRequested(QString)), this, SLOT(loadTheme(QString))); connect(m_themeHandler, SIGNAL(saveThemeRequested(KConfig&)), this, SLOT(saveTheme(KConfig&))); connect(m_themeHandler, SIGNAL(info(QString)), this, SIGNAL(info(QString))); //connect(this, SIGNAL(saveThemeEnable(bool)), m_themeHandler, SLOT(saveThemeEnable(bool))); auto* templateHandler = new TemplateHandler(this, TemplateHandler::CartesianPlot); layout->addWidget(templateHandler); connect(templateHandler, SIGNAL(loadConfigRequested(KConfig&)), this, SLOT(loadConfigFromTemplate(KConfig&))); connect(templateHandler, SIGNAL(saveConfigRequested(KConfig&)), this, SLOT(saveConfigAsTemplate(KConfig&))); connect(templateHandler, SIGNAL(info(QString)), this, SIGNAL(info(QString))); ui.verticalLayout->addWidget(frame); //TODO: activate the tab again once the functionality is implemented ui.tabWidget->removeTab(2); init(); } void CartesianPlotDock::init() { this->retranslateUi(); GuiTools::updatePenStyles(ui.cbCursorLineStyle, Qt::black); /* //TODO: activate later once range breaking is implemented //create icons for the different styles for scale breaking QPainter pa; pa.setPen( QPen(Qt::SolidPattern, 0) ); QPixmap pm(20, 20); ui.cbXBreakStyle->setIconSize( QSize(20,20) ); ui.cbYBreakStyle->setIconSize( QSize(20,20) ); //simple pm.fill(Qt::transparent); pa.begin( &pm ); pa.setRenderHint(QPainter::Antialiasing); pa.setBrush(Qt::SolidPattern); pa.drawLine(3,10,8,10); pa.drawLine(12,10,17,10); pa.end(); ui.cbXBreakStyle->setItemIcon(0, pm); ui.cbYBreakStyle->setItemIcon(0, pm); //vertical pm.fill(Qt::transparent); pa.begin( &pm ); pa.setRenderHint(QPainter::Antialiasing); pa.setBrush(Qt::SolidPattern); pa.drawLine(3,10,8,10); pa.drawLine(12,10,17,10); pa.drawLine(8,14,8,6); pa.drawLine(12,14,12,6); pa.end(); ui.cbXBreakStyle->setItemIcon(1, pm); ui.cbYBreakStyle->setItemIcon(1, pm); //sloped pm.fill(Qt::transparent); pa.begin( &pm ); pa.setRenderHint(QPainter::Antialiasing); pa.setBrush(Qt::SolidPattern); pa.drawLine(3,10,8,10); pa.drawLine(12,10,17,10); pa.drawLine(6,14,10,6); pa.drawLine(10,14,14,6); pa.end(); ui.cbXBreakStyle->setItemIcon(2, pm); ui.cbYBreakStyle->setItemIcon(2, pm); */ } void CartesianPlotDock::setPlots(QList list) { m_initializing = true; m_plotList = list; m_plot = list.first(); m_aspect = list.first(); QList labels; for (auto* plot : list) labels.append(plot->title()); labelWidget->setLabels(labels); //if there is more then one plot in the list, disable the name and comment fields in the tab "general" if (list.size() == 1) { ui.lName->setEnabled(true); ui.leName->setEnabled(true); ui.lComment->setEnabled(true); ui.leComment->setEnabled(true); ui.leName->setText(m_plot->name()); ui.leComment->setText(m_plot->comment()); } else { ui.lName->setEnabled(false); ui.leName->setEnabled(false); ui.lComment->setEnabled(false); ui.leComment->setEnabled(false); ui.leName->setText(QString()); ui.leComment->setText(QString()); } - bool symmetric = m_plot->symmetricPadding(); - ui.lPaddingHorizontalRight->setVisible(!symmetric); - ui.sbPaddingRight->setVisible(!symmetric); - ui.lPaddingVerticalDown->setVisible(!symmetric); - ui.sbPaddingBottom->setVisible(!symmetric); - if (symmetric) { - ui.lPaddingHorizontal->setText(i18n("Horizontal")); - ui.lPaddingVertical->setText(i18n("Vertical")); - } else { - ui.lPaddingHorizontal->setText(i18n("Left")); - ui.lPaddingVertical->setText(i18n("Top")); - } + symmetricPaddingChanged(m_plot->symmetricPadding()); ui.leName->setStyleSheet(""); ui.leName->setToolTip(""); //show the properties of the first plot this->load(); //update active widgets backgroundTypeChanged(ui.cbBackgroundType->currentIndex()); m_themeHandler->setCurrentTheme(m_plot->theme()); //Deactivate the geometry related widgets, if the worksheet layout is active. //Currently, a plot can only be a child of the worksheet itself, so we only need to ask the parent aspect (=worksheet). //TODO redesign this, if the hierarchy will be changend in future (a plot is a child of a new object group/container or so) auto* w = dynamic_cast(m_plot->parentAspect()); if (w) { bool b = (w->layout() == Worksheet::Layout::NoLayout); ui.sbTop->setEnabled(b); ui.sbLeft->setEnabled(b); ui.sbWidth->setEnabled(b); ui.sbHeight->setEnabled(b); connect(w, SIGNAL(layoutChanged(Worksheet::Layout)), this, SLOT(layoutChanged(Worksheet::Layout))); } //SIGNALs/SLOTs connect( m_plot, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)), this, SLOT(plotDescriptionChanged(const AbstractAspect*)) ); connect( m_plot, SIGNAL(rectChanged(QRectF&)), this, SLOT(plotRectChanged(QRectF&)) ); connect( m_plot, SIGNAL(rangeTypeChanged(CartesianPlot::RangeType)), this, SLOT(plotRangeTypeChanged(CartesianPlot::RangeType)) ); connect( m_plot, SIGNAL(rangeFirstValuesChanged(int)), this, SLOT(plotRangeFirstValuesChanged(int)) ); connect( m_plot, SIGNAL(rangeLastValuesChanged(int)), this, SLOT(plotRangeLastValuesChanged(int)) ); connect( m_plot, SIGNAL(xAutoScaleChanged(bool)), this, SLOT(plotXAutoScaleChanged(bool)) ); connect( m_plot, SIGNAL(xMinChanged(double)), this, SLOT(plotXMinChanged(double)) ); connect( m_plot, SIGNAL(xMaxChanged(double)), this, SLOT(plotXMaxChanged(double)) ); connect( m_plot, SIGNAL(xScaleChanged(int)), this, SLOT(plotXScaleChanged(int)) ); connect(m_plot, &CartesianPlot::xRangeFormatChanged, this, &CartesianPlotDock::plotXRangeFormatChanged); connect( m_plot, SIGNAL(yAutoScaleChanged(bool)), this, SLOT(plotYAutoScaleChanged(bool)) ); connect( m_plot, SIGNAL(yMinChanged(double)), this, SLOT(plotYMinChanged(double)) ); connect( m_plot, SIGNAL(yMaxChanged(double)), this, SLOT(plotYMaxChanged(double)) ); connect( m_plot, SIGNAL(yScaleChanged(int)), this, SLOT(plotYScaleChanged(int)) ); connect(m_plot, &CartesianPlot::yRangeFormatChanged, this, &CartesianPlotDock::plotYRangeFormatChanged); connect( m_plot, SIGNAL(visibleChanged(bool)), this, SLOT(plotVisibleChanged(bool)) ); //range breaks connect( m_plot, SIGNAL(xRangeBreakingEnabledChanged(bool)), this, SLOT(plotXRangeBreakingEnabledChanged(bool)) ); connect( m_plot, SIGNAL(xRangeBreaksChanged(CartesianPlot::RangeBreaks)), this, SLOT(plotXRangeBreaksChanged(CartesianPlot::RangeBreaks)) ); connect( m_plot, SIGNAL(yRangeBreakingEnabledChanged(bool)), this, SLOT(plotYRangeBreakingEnabledChanged(bool)) ); connect( m_plot, SIGNAL(yRangeBreaksChanged(CartesianPlot::RangeBreaks)), this, SLOT(plotYRangeBreaksChanged(CartesianPlot::RangeBreaks)) ); // Plot Area connect( m_plot->plotArea(), SIGNAL(backgroundTypeChanged(PlotArea::BackgroundType)), this, SLOT(plotBackgroundTypeChanged(PlotArea::BackgroundType)) ); connect( m_plot->plotArea(), SIGNAL(backgroundColorStyleChanged(PlotArea::BackgroundColorStyle)), this, SLOT(plotBackgroundColorStyleChanged(PlotArea::BackgroundColorStyle)) ); connect( m_plot->plotArea(), SIGNAL(backgroundImageStyleChanged(PlotArea::BackgroundImageStyle)), this, SLOT(plotBackgroundImageStyleChanged(PlotArea::BackgroundImageStyle)) ); connect( m_plot->plotArea(), SIGNAL(backgroundBrushStyleChanged(Qt::BrushStyle)), this, SLOT(plotBackgroundBrushStyleChanged(Qt::BrushStyle)) ); connect( m_plot->plotArea(), SIGNAL(backgroundFirstColorChanged(QColor&)), this, SLOT(plotBackgroundFirstColorChanged(QColor&)) ); connect( m_plot->plotArea(), SIGNAL(backgroundSecondColorChanged(QColor&)), this, SLOT(plotBackgroundSecondColorChanged(QColor&)) ); connect( m_plot->plotArea(), SIGNAL(backgroundFileNameChanged(QString&)), this, SLOT(plotBackgroundFileNameChanged(QString&)) ); connect( m_plot->plotArea(), SIGNAL(backgroundOpacityChanged(float)), this, SLOT(plotBackgroundOpacityChanged(float)) ); connect( m_plot->plotArea(), SIGNAL(borderPenChanged(QPen&)), this, SLOT(plotBorderPenChanged(QPen&)) ); connect( m_plot->plotArea(), SIGNAL(borderOpacityChanged(float)), this, SLOT(plotBorderOpacityChanged(float)) ); connect( m_plot, SIGNAL(horizontalPaddingChanged(float)), this, SLOT(plotHorizontalPaddingChanged(float)) ); connect( m_plot, SIGNAL(verticalPaddingChanged(float)), this, SLOT(plotVerticalPaddingChanged(float)) ); connect(m_plot, &CartesianPlot::rightPaddingChanged, this, &CartesianPlotDock::plotRightPaddingChanged); connect(m_plot, &CartesianPlot::bottomPaddingChanged, this, &CartesianPlotDock::plotBottomPaddingChanged); connect(m_plot, &CartesianPlot::symmetricPaddingChanged, this, &CartesianPlotDock::plotSymmetricPaddingChanged); m_initializing = false; } void CartesianPlotDock::activateTitleTab() { ui.tabWidget->setCurrentWidget(ui.tabTitle); } void CartesianPlotDock::updateUnits() { const KConfigGroup group = KSharedConfig::openConfig()->group(QLatin1String("Settings_General")); BaseDock::Units units = (BaseDock::Units)group.readEntry("Units", (int)MetricUnits); if (units == m_units) return; m_units = units; Lock lock(m_initializing); QString suffix; if (m_units == BaseDock::MetricUnits) { //convert from imperial to metric m_worksheetUnit = Worksheet::Unit::Centimeter; - suffix = QLatin1String("cm"); + suffix = QLatin1String(" cm"); ui.sbLeft->setValue(ui.sbLeft->value()*2.54); ui.sbTop->setValue(ui.sbTop->value()*2.54); ui.sbWidth->setValue(ui.sbWidth->value()*2.54); ui.sbHeight->setValue(ui.sbHeight->value()*2.54); ui.sbBorderCornerRadius->setValue(ui.sbBorderCornerRadius->value()*2.54); ui.sbPaddingHorizontal->setValue(ui.sbPaddingHorizontal->value()*2.54); ui.sbPaddingVertical->setValue(ui.sbPaddingVertical->value()*2.54); ui.sbPaddingRight->setValue(ui.sbPaddingRight->value()*2.54); ui.sbPaddingBottom->setValue(ui.sbPaddingBottom->value()*2.54); } else { //convert from metric to imperial m_worksheetUnit = Worksheet::Unit::Inch; - suffix = QLatin1String("in"); + suffix = QLatin1String(" in"); ui.sbLeft->setValue(ui.sbLeft->value()/2.54); ui.sbTop->setValue(ui.sbTop->value()/2.54); ui.sbWidth->setValue(ui.sbWidth->value()/2.54); ui.sbHeight->setValue(ui.sbHeight->value()/2.54); ui.sbBorderCornerRadius->setValue(ui.sbBorderCornerRadius->value()/2.54); ui.sbPaddingHorizontal->setValue(ui.sbPaddingHorizontal->value()/2.54); ui.sbPaddingVertical->setValue(ui.sbPaddingVertical->value()/2.54); ui.sbPaddingRight->setValue(ui.sbPaddingRight->value()/2.54); ui.sbPaddingBottom->setValue(ui.sbPaddingBottom->value()/2.54); } ui.sbLeft->setSuffix(suffix); ui.sbTop->setSuffix(suffix); ui.sbWidth->setSuffix(suffix); ui.sbHeight->setSuffix(suffix); ui.sbBorderCornerRadius->setSuffix(suffix); ui.sbPaddingHorizontal->setSuffix(suffix); ui.sbPaddingVertical->setSuffix(suffix); ui.sbPaddingRight->setSuffix(suffix); ui.sbPaddingBottom->setSuffix(suffix); labelWidget->updateUnits(); } //************************************************************ //**** SLOTs for changes triggered in CartesianPlotDock ****** //************************************************************ void CartesianPlotDock::retranslateUi() { Lock lock(m_initializing); //general - ui.cbXRangeFormat->addItem(i18n("numeric")); - ui.cbXRangeFormat->addItem(i18n("datetime")); - ui.cbYRangeFormat->addItem(i18n("numeric")); - ui.cbYRangeFormat->addItem(i18n("datetime")); + ui.cbXRangeFormat->addItem(i18n("Numeric")); + ui.cbXRangeFormat->addItem(i18n("Date and Time")); + ui.cbYRangeFormat->addItem(i18n("Numeric")); + ui.cbYRangeFormat->addItem(i18n("Date and Time")); ui.cbXScaling->addItem( i18n("linear") ); ui.cbXScaling->addItem( i18n("log(x)") ); ui.cbXScaling->addItem( i18n("log2(x)") ); ui.cbXScaling->addItem( i18n("ln(x)") ); ui.cbXScaling->addItem( i18n("log(abs(x))") ); ui.cbXScaling->addItem( i18n("log2(abs(x))") ); ui.cbXScaling->addItem( i18n("ln(abs(x))") ); ui.cbYScaling->addItem( i18n("linear") ); ui.cbYScaling->addItem( i18n("log(y)") ); ui.cbYScaling->addItem( i18n("log2(y)") ); ui.cbYScaling->addItem( i18n("ln(y)") ); ui.cbYScaling->addItem( i18n("log(abs(y))") ); ui.cbYScaling->addItem( i18n("log2(abs(y))") ); ui.cbYScaling->addItem( i18n("ln(abs(y))") ); //scale breakings ui.cbXBreakStyle->addItem( i18n("Simple") ); ui.cbXBreakStyle->addItem( i18n("Vertical") ); ui.cbXBreakStyle->addItem( i18n("Sloped") ); ui.cbYBreakStyle->addItem( i18n("Simple") ); ui.cbYBreakStyle->addItem( i18n("Vertical") ); ui.cbYBreakStyle->addItem( i18n("Sloped") ); //plot area ui.cbBackgroundType->addItem(i18n("Color")); ui.cbBackgroundType->addItem(i18n("Image")); ui.cbBackgroundType->addItem(i18n("Pattern")); ui.cbBackgroundColorStyle->addItem(i18n("Single Color")); ui.cbBackgroundColorStyle->addItem(i18n("Horizontal Gradient")); ui.cbBackgroundColorStyle->addItem(i18n("Vertical Gradient")); ui.cbBackgroundColorStyle->addItem(i18n("Diag. Gradient (From Top Left)")); ui.cbBackgroundColorStyle->addItem(i18n("Diag. Gradient (From Bottom Left)")); ui.cbBackgroundColorStyle->addItem(i18n("Radial Gradient")); ui.cbBackgroundImageStyle->addItem(i18n("Scaled and Cropped")); ui.cbBackgroundImageStyle->addItem(i18n("Scaled")); ui.cbBackgroundImageStyle->addItem(i18n("Scaled, Keep Proportions")); ui.cbBackgroundImageStyle->addItem(i18n("Centered")); ui.cbBackgroundImageStyle->addItem(i18n("Tiled")); ui.cbBackgroundImageStyle->addItem(i18n("Center Tiled")); GuiTools::updatePenStyles(ui.cbBorderStyle, Qt::black); GuiTools::updateBrushStyles(ui.cbBackgroundBrushStyle, Qt::SolidPattern); QString suffix; if (m_units == BaseDock::MetricUnits) - suffix = QLatin1String("cm"); + suffix = QLatin1String(" cm"); else - suffix = QLatin1String("in"); + suffix = QLatin1String(" in"); ui.sbLeft->setSuffix(suffix); ui.sbTop->setSuffix(suffix); ui.sbWidth->setSuffix(suffix); ui.sbHeight->setSuffix(suffix); ui.sbBorderCornerRadius->setSuffix(suffix); ui.sbPaddingHorizontal->setSuffix(suffix); ui.sbPaddingVertical->setSuffix(suffix); ui.sbPaddingRight->setSuffix(suffix); ui.sbPaddingBottom->setSuffix(suffix); } // "General"-tab void CartesianPlotDock::visibilityChanged(bool state) { if (m_initializing) return; for (auto* plot : m_plotList) plot->setVisible(state); } void CartesianPlotDock::geometryChanged() { if (m_initializing) return; float x = Worksheet::convertToSceneUnits(ui.sbLeft->value(), m_worksheetUnit); float y = Worksheet::convertToSceneUnits(ui.sbTop->value(), m_worksheetUnit); float w = Worksheet::convertToSceneUnits(ui.sbWidth->value(), m_worksheetUnit); float h = Worksheet::convertToSceneUnits(ui.sbHeight->value(), m_worksheetUnit); QRectF rect(x, y, w, h); m_plot->setRect(rect); } /*! Called when the layout in the worksheet gets changed. Enables/disables the geometry widgets if the layout was deactivated/activated. Shows the new geometry values of the first plot if the layout was activated. */ void CartesianPlotDock::layoutChanged(Worksheet::Layout layout) { bool b = (layout == Worksheet::Layout::NoLayout); ui.sbTop->setEnabled(b); ui.sbLeft->setEnabled(b); ui.sbWidth->setEnabled(b); ui.sbHeight->setEnabled(b); } void CartesianPlotDock::rangeTypeChanged() { CartesianPlot::RangeType type; if (ui.rbRangeFirst->isChecked()) { ui.leRangeFirst->setEnabled(true); ui.leRangeLast->setEnabled(false); type = CartesianPlot::RangeFirst; } else if (ui.rbRangeLast->isChecked()) { ui.leRangeFirst->setEnabled(false); ui.leRangeLast->setEnabled(true); type = CartesianPlot::RangeLast; } else { ui.leRangeFirst->setEnabled(false); ui.leRangeLast->setEnabled(false); type = CartesianPlot::RangeFree; } if (m_initializing) return; for (auto* plot : m_plotList) plot->setRangeType(type); } void CartesianPlotDock::rangeFirstChanged(const QString& text) { if (m_initializing) return; const int value = text.toInt(); for (auto* plot : m_plotList) plot->setRangeFirstValues(value); } void CartesianPlotDock::rangeLastChanged(const QString& text) { if (m_initializing) return; const int value = text.toInt(); for (auto* plot : m_plotList) plot->setRangeLastValues(value); } void CartesianPlotDock::autoScaleXChanged(int state) { bool checked = (state == Qt::Checked); ui.cbXRangeFormat->setEnabled(!checked); ui.leXMin->setEnabled(!checked); ui.leXMax->setEnabled(!checked); ui.dateTimeEditXMin->setEnabled(!checked); ui.dateTimeEditXMax->setEnabled(!checked); if (m_initializing) return; for (auto* plot : m_plotList) plot->setAutoScaleX(checked); } void CartesianPlotDock::xMinChanged(const QString& value) { if (m_initializing) return; const Lock lock(m_initializing); const float min = value.toDouble(); for (auto* plot : m_plotList) plot->setXMin(min); } void CartesianPlotDock::xMaxChanged(const QString& value) { if (m_initializing) return; const Lock lock(m_initializing); const float max = value.toDouble(); for (auto* plot : m_plotList) plot->setXMax(max); } void CartesianPlotDock::xMinDateTimeChanged(const QDateTime& dateTime) { if (m_initializing) return; quint64 value = dateTime.toMSecsSinceEpoch(); for (auto* plot : m_plotList) plot->setXMin(value); } void CartesianPlotDock::xMaxDateTimeChanged(const QDateTime& dateTime) { if (m_initializing) return; quint64 value = dateTime.toMSecsSinceEpoch(); for (auto* plot : m_plotList) plot->setXMax(value); } /*! called on scale changes (linear, log) for the x-axis */ void CartesianPlotDock::xScaleChanged(int scale) { if (m_initializing) return; for (auto* plot : m_plotList) plot->setXScale((CartesianPlot::Scale) scale); } void CartesianPlotDock::xRangeFormatChanged(int index) { bool numeric = (index == 0); ui.lXMin->setVisible(numeric); ui.leXMin->setVisible(numeric); ui.lXMax->setVisible(numeric); ui.leXMax->setVisible(numeric); ui.lXMinDateTime->setVisible(!numeric); ui.dateTimeEditXMin->setVisible(!numeric); ui.lXMaxDateTime->setVisible(!numeric); ui.dateTimeEditXMax->setVisible(!numeric); if (m_initializing) return; auto format = (CartesianPlot::RangeFormat)index; for (auto* plot : m_plotList) plot->setXRangeFormat(format); } void CartesianPlotDock::autoScaleYChanged(int state) { bool checked = (state == Qt::Checked); ui.cbYRangeFormat->setEnabled(!checked); ui.leYMin->setEnabled(!checked); ui.leYMax->setEnabled(!checked); ui.dateTimeEditYMin->setEnabled(!checked); ui.dateTimeEditYMax->setEnabled(!checked); if (m_initializing) return; for (auto* plot : m_plotList) plot->setAutoScaleY(checked); } void CartesianPlotDock::yMinChanged(const QString& value) { if (m_initializing) return; const Lock lock(m_initializing); const float min = value.toDouble(); for (auto* plot : m_plotList) plot->setYMin(min); } void CartesianPlotDock::yMaxChanged(const QString& value) { if (m_initializing) return; const Lock lock(m_initializing); const float max = value.toDouble(); for (auto* plot : m_plotList) plot->setYMax(max); } void CartesianPlotDock::yMinDateTimeChanged(const QDateTime& dateTime) { if (m_initializing) return; quint64 value = dateTime.toMSecsSinceEpoch(); for (auto* plot : m_plotList) plot->setXMin(value); } void CartesianPlotDock::yMaxDateTimeChanged(const QDateTime& dateTime) { if (m_initializing) return; quint64 value = dateTime.toMSecsSinceEpoch(); for (auto* plot : m_plotList) plot->setXMax(value); } /*! called on scale changes (linear, log) for the y-axis */ void CartesianPlotDock::yScaleChanged(int index) { if (m_initializing) return; auto scale = (CartesianPlot::Scale)index; for (auto* plot : m_plotList) plot->setYScale(scale); } void CartesianPlotDock::yRangeFormatChanged(int index) { bool numeric = (index == 0); ui.lYMin->setVisible(numeric); ui.leYMin->setVisible(numeric); ui.lYMax->setVisible(numeric); ui.leYMax->setVisible(numeric); ui.lYMinDateTime->setVisible(!numeric); ui.dateTimeEditYMin->setVisible(!numeric); ui.lYMaxDateTime->setVisible(!numeric); ui.dateTimeEditYMax->setVisible(!numeric); if (m_initializing) return; auto format = (CartesianPlot::RangeFormat)index; for (auto* plot : m_plotList) plot->setYRangeFormat(format); } // "Range Breaks"-tab // x-range breaks void CartesianPlotDock::toggleXBreak(bool b) { ui.frameXBreakEdit->setEnabled(b); ui.leXBreakStart->setEnabled(b); ui.leXBreakEnd->setEnabled(b); ui.sbXBreakPosition->setEnabled(b); ui.cbXBreakStyle->setEnabled(b); if (m_initializing) return; for (auto* plot : m_plotList) plot->setXRangeBreakingEnabled(b); } void CartesianPlotDock::addXBreak() { ui.bRemoveXBreak->setVisible(true); CartesianPlot::RangeBreaks breaks = m_plot->xRangeBreaks(); CartesianPlot::RangeBreak b; breaks.list<setXRangeBreaks(breaks); ui.cbXBreak->addItem(QString::number(ui.cbXBreak->count()+1)); ui.cbXBreak->setCurrentIndex(ui.cbXBreak->count()-1); } void CartesianPlotDock::removeXBreak() { ui.bRemoveXBreak->setVisible(m_plot->xRangeBreaks().list.size()>1); int index = ui.cbXBreak->currentIndex(); CartesianPlot::RangeBreaks breaks = m_plot->xRangeBreaks(); breaks.list.takeAt(index); breaks.lastChanged = -1; for (auto* plot : m_plotList) plot->setXRangeBreaks(breaks); ui.cbXBreak->clear(); for (int i = 1; i <= breaks.list.size(); ++i) ui.cbXBreak->addItem(QString::number(i)); if (index < ui.cbXBreak->count()-1) ui.cbXBreak->setCurrentIndex(index); else ui.cbXBreak->setCurrentIndex(ui.cbXBreak->count()-1); ui.bRemoveXBreak->setVisible(ui.cbXBreak->count()!=1); } void CartesianPlotDock::currentXBreakChanged(int index) { if (m_initializing) return; if (index == -1) return; m_initializing = true; const CartesianPlot::RangeBreak rangeBreak = m_plot->xRangeBreaks().list.at(index); QString str = std::isnan(rangeBreak.start) ? QString() : QString::number(rangeBreak.start); ui.leXBreakStart->setText(str); str = std::isnan(rangeBreak.end) ? QString() : QString::number(rangeBreak.end); ui.leXBreakEnd->setText(str); ui.sbXBreakPosition->setValue(rangeBreak.position*100); ui.cbXBreakStyle->setCurrentIndex((int)rangeBreak.style); m_initializing = false; } void CartesianPlotDock::xBreakStartChanged() { if (m_initializing) return; int index = ui.cbXBreak->currentIndex(); CartesianPlot::RangeBreaks breaks = m_plot->xRangeBreaks(); breaks.list[index].start = ui.leXBreakStart->text().toDouble(); breaks.lastChanged = index; for (auto* plot : m_plotList) plot->setXRangeBreaks(breaks); } void CartesianPlotDock::xBreakEndChanged() { if (m_initializing) return; int index = ui.cbXBreak->currentIndex(); CartesianPlot::RangeBreaks breaks = m_plot->xRangeBreaks(); breaks.list[index].end = ui.leXBreakEnd->text().toDouble(); breaks.lastChanged = index; for (auto* plot : m_plotList) plot->setXRangeBreaks(breaks); } void CartesianPlotDock::xBreakPositionChanged(int value) { if (m_initializing) return; int index = ui.cbXBreak->currentIndex(); CartesianPlot::RangeBreaks breaks = m_plot->xRangeBreaks(); breaks.list[index].position = (float)value/100.; breaks.lastChanged = index; for (auto* plot : m_plotList) plot->setXRangeBreaks(breaks); } void CartesianPlotDock::xBreakStyleChanged(int styleIndex) { if (m_initializing) return; int index = ui.cbXBreak->currentIndex(); auto style = CartesianPlot::RangeBreakStyle(styleIndex); CartesianPlot::RangeBreaks breaks = m_plot->xRangeBreaks(); breaks.list[index].style = style; breaks.lastChanged = index; for (auto* plot : m_plotList) plot->setXRangeBreaks(breaks); } // y-range breaks void CartesianPlotDock::toggleYBreak(bool b) { ui.frameYBreakEdit->setEnabled(b); ui.leYBreakStart->setEnabled(b); ui.leYBreakEnd->setEnabled(b); ui.sbYBreakPosition->setEnabled(b); ui.cbYBreakStyle->setEnabled(b); if (m_initializing) return; for (auto* plot : m_plotList) plot->setYRangeBreakingEnabled(b); } void CartesianPlotDock::addYBreak() { ui.bRemoveYBreak->setVisible(true); CartesianPlot::RangeBreaks breaks = m_plot->yRangeBreaks(); CartesianPlot::RangeBreak b; breaks.list << b; breaks.lastChanged = breaks.list.size() - 1; for (auto* plot : m_plotList) plot->setYRangeBreaks(breaks); ui.cbYBreak->addItem(QString::number(ui.cbYBreak->count()+1)); ui.cbYBreak->setCurrentIndex(ui.cbYBreak->count()-1); } void CartesianPlotDock::removeYBreak() { ui.bRemoveYBreak->setVisible(m_plot->yRangeBreaks().list.size()>1); int index = ui.cbYBreak->currentIndex(); CartesianPlot::RangeBreaks breaks = m_plot->yRangeBreaks(); breaks.list.takeAt(index); breaks.lastChanged = -1; for (auto* plot : m_plotList) plot->setYRangeBreaks(breaks); ui.cbYBreak->clear(); for (int i = 1; i <= breaks.list.size(); ++i) ui.cbYBreak->addItem(QString::number(i)); if (index < ui.cbYBreak->count()-1) ui.cbYBreak->setCurrentIndex(index); else ui.cbYBreak->setCurrentIndex(ui.cbYBreak->count()-1); ui.bRemoveYBreak->setVisible(ui.cbYBreak->count() != 1); } void CartesianPlotDock::currentYBreakChanged(int index) { if (m_initializing) return; if (index == -1) return; m_initializing = true; const CartesianPlot::RangeBreak rangeBreak = m_plot->yRangeBreaks().list.at(index); QString str = std::isnan(rangeBreak.start) ? QString() : QString::number(rangeBreak.start); ui.leYBreakStart->setText(str); str = std::isnan(rangeBreak.end) ? QString() : QString::number(rangeBreak.end); ui.leYBreakEnd->setText(str); ui.sbYBreakPosition->setValue(rangeBreak.position*100); ui.cbYBreakStyle->setCurrentIndex((int)rangeBreak.style); m_initializing = false; } void CartesianPlotDock::yBreakStartChanged() { if (m_initializing) return; int index = ui.cbYBreak->currentIndex(); CartesianPlot::RangeBreaks breaks = m_plot->yRangeBreaks(); breaks.list[index].start = ui.leYBreakStart->text().toDouble(); breaks.lastChanged = index; for (auto* plot : m_plotList) plot->setYRangeBreaks(breaks); } void CartesianPlotDock::yBreakEndChanged() { if (m_initializing) return; int index = ui.cbYBreak->currentIndex(); CartesianPlot::RangeBreaks breaks = m_plot->yRangeBreaks(); breaks.list[index].end = ui.leYBreakEnd->text().toDouble(); breaks.lastChanged = index; for (auto* plot : m_plotList) plot->setYRangeBreaks(breaks); } void CartesianPlotDock::yBreakPositionChanged(int value) { if (m_initializing) return; int index = ui.cbYBreak->currentIndex(); CartesianPlot::RangeBreaks breaks = m_plot->yRangeBreaks(); breaks.list[index].position = (float)value/100.; breaks.lastChanged = index; for (auto* plot : m_plotList) plot->setYRangeBreaks(breaks); } void CartesianPlotDock::yBreakStyleChanged(int styleIndex) { if (m_initializing) return; int index = ui.cbYBreak->currentIndex(); auto style = CartesianPlot::RangeBreakStyle(styleIndex); CartesianPlot::RangeBreaks breaks = m_plot->yRangeBreaks(); breaks.list[index].style = style; breaks.lastChanged = index; for (auto* plot : m_plotList) plot->setYRangeBreaks(breaks); } // "Plot area"-tab void CartesianPlotDock::backgroundTypeChanged(int index) { auto type = (PlotArea::BackgroundType)index; if (type == PlotArea::BackgroundType::Color) { ui.lBackgroundColorStyle->show(); ui.cbBackgroundColorStyle->show(); ui.lBackgroundImageStyle->hide(); ui.cbBackgroundImageStyle->hide(); ui.lBackgroundBrushStyle->hide(); ui.cbBackgroundBrushStyle->hide(); ui.lBackgroundFileName->hide(); ui.leBackgroundFileName->hide(); ui.bOpen->hide(); ui.lBackgroundFirstColor->show(); ui.kcbBackgroundFirstColor->show(); auto style = (PlotArea::BackgroundColorStyle) ui.cbBackgroundColorStyle->currentIndex(); if (style == PlotArea::BackgroundColorStyle::SingleColor) { ui.lBackgroundFirstColor->setText(i18n("Color:")); ui.lBackgroundSecondColor->hide(); ui.kcbBackgroundSecondColor->hide(); } else { ui.lBackgroundFirstColor->setText(i18n("First color:")); ui.lBackgroundSecondColor->show(); ui.kcbBackgroundSecondColor->show(); } } else if (type == PlotArea::BackgroundType::Image) { ui.lBackgroundColorStyle->hide(); ui.cbBackgroundColorStyle->hide(); ui.lBackgroundImageStyle->show(); ui.cbBackgroundImageStyle->show(); ui.lBackgroundBrushStyle->hide(); ui.cbBackgroundBrushStyle->hide(); ui.lBackgroundFileName->show(); ui.leBackgroundFileName->show(); ui.bOpen->show(); ui.lBackgroundFirstColor->hide(); ui.kcbBackgroundFirstColor->hide(); ui.lBackgroundSecondColor->hide(); ui.kcbBackgroundSecondColor->hide(); } else if (type == PlotArea::BackgroundType::Pattern) { ui.lBackgroundFirstColor->setText(i18n("Color:")); ui.lBackgroundColorStyle->hide(); ui.cbBackgroundColorStyle->hide(); ui.lBackgroundImageStyle->hide(); ui.cbBackgroundImageStyle->hide(); ui.lBackgroundBrushStyle->show(); ui.cbBackgroundBrushStyle->show(); ui.lBackgroundFileName->hide(); ui.leBackgroundFileName->hide(); ui.bOpen->hide(); ui.lBackgroundFirstColor->show(); ui.kcbBackgroundFirstColor->show(); ui.lBackgroundSecondColor->hide(); ui.kcbBackgroundSecondColor->hide(); } if (m_initializing) return; for (auto* plot : m_plotList) plot->plotArea()->setBackgroundType(type); } void CartesianPlotDock::backgroundColorStyleChanged(int index) { auto style = (PlotArea::BackgroundColorStyle)index; if (style == PlotArea::BackgroundColorStyle::SingleColor) { ui.lBackgroundFirstColor->setText(i18n("Color:")); ui.lBackgroundSecondColor->hide(); ui.kcbBackgroundSecondColor->hide(); } else { ui.lBackgroundFirstColor->setText(i18n("First color:")); ui.lBackgroundSecondColor->show(); ui.kcbBackgroundSecondColor->show(); ui.lBackgroundBrushStyle->hide(); ui.cbBackgroundBrushStyle->hide(); } if (m_initializing) return; for (auto* plot : m_plotList) plot->plotArea()->setBackgroundColorStyle(style); } void CartesianPlotDock::backgroundImageStyleChanged(int index) { if (m_initializing) return; auto style = (PlotArea::BackgroundImageStyle)index; for (auto* plot : m_plotList) plot->plotArea()->setBackgroundImageStyle(style); } void CartesianPlotDock::backgroundBrushStyleChanged(int index) { if (m_initializing) return; auto style = (Qt::BrushStyle)index; for (auto* plot : m_plotList) plot->plotArea()->setBackgroundBrushStyle(style); } void CartesianPlotDock::backgroundFirstColorChanged(const QColor& c) { if (m_initializing) return; for (auto* plot : m_plotList) plot->plotArea()->setBackgroundFirstColor(c); } void CartesianPlotDock::backgroundSecondColorChanged(const QColor& c) { if (m_initializing) return; for (auto* plot : m_plotList) plot->plotArea()->setBackgroundSecondColor(c); } /*! opens a file dialog and lets the user select the image file. */ void CartesianPlotDock::selectFile() { KConfigGroup conf(KSharedConfig::openConfig(), "CartesianPlotDock"); QString dir = conf.readEntry("LastImageDir", ""); QString formats; for (const auto& format : QImageReader::supportedImageFormats()) { QString f = "*." + QString(format.constData()); if (f == QLatin1String("*.svg")) continue; formats.isEmpty() ? formats += f : formats += ' ' + f; } QString path = QFileDialog::getOpenFileName(this, i18n("Select the image file"), dir, i18n("Images (%1)", formats)); if (path.isEmpty()) return; //cancel was clicked in the file-dialog int pos = path.lastIndexOf(QLatin1String("/")); if (pos != -1) { QString newDir{path.left(pos)}; if (newDir != dir) conf.writeEntry("LastImageDir", newDir); } ui.leBackgroundFileName->setText(path); for (auto* plot : m_plotList) plot->plotArea()->setBackgroundFileName(path); } void CartesianPlotDock::fileNameChanged() { if (m_initializing) return; QString fileName = ui.leBackgroundFileName->text(); if (!fileName.isEmpty() && !QFile::exists(fileName)) ui.leBackgroundFileName->setStyleSheet("QLineEdit{background:red;}"); else ui.leBackgroundFileName->setStyleSheet(QString()); for (auto* plot : m_plotList) plot->plotArea()->setBackgroundFileName(fileName); } void CartesianPlotDock::backgroundOpacityChanged(int value) { if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* plot : m_plotList) plot->plotArea()->setBackgroundOpacity(opacity); } // "Border"-tab void CartesianPlotDock::borderStyleChanged(int index) { if (m_initializing) return; auto penStyle = Qt::PenStyle(index); QPen pen; for (auto* plot : m_plotList) { pen = plot->plotArea()->borderPen(); pen.setStyle(penStyle); plot->plotArea()->setBorderPen(pen); } } void CartesianPlotDock::borderColorChanged(const QColor& color) { if (m_initializing) return; QPen pen; for (auto* plot : m_plotList) { pen = plot->plotArea()->borderPen(); pen.setColor(color); plot->plotArea()->setBorderPen(pen); } m_initializing = true; GuiTools::updatePenStyles(ui.cbBorderStyle, color); m_initializing = false; } void CartesianPlotDock::borderWidthChanged(double value) { if (m_initializing) return; QPen pen; for (auto* plot : m_plotList) { pen = plot->plotArea()->borderPen(); pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point) ); plot->plotArea()->setBorderPen(pen); } } void CartesianPlotDock::borderCornerRadiusChanged(double value) { if (m_initializing) return; for (auto* plot : m_plotList) plot->plotArea()->setBorderCornerRadius(Worksheet::convertToSceneUnits(value, m_worksheetUnit)); } void CartesianPlotDock::borderOpacityChanged(int value) { if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* plot : m_plotList) plot->plotArea()->setBorderOpacity(opacity); } void CartesianPlotDock::symmetricPaddingChanged(bool checked) { - if (m_initializing) - return; - ui.lPaddingHorizontalRight->setVisible(!checked); ui.sbPaddingRight->setVisible(!checked); ui.lPaddingVerticalDown->setVisible(!checked); ui.sbPaddingBottom->setVisible(!checked); if (checked) { ui.lPaddingHorizontal->setText(i18n("Horizontal:")); ui.lPaddingVertical->setText(i18n("Vertical:")); } else { ui.lPaddingHorizontal->setText(i18n("Left:")); ui.lPaddingVertical->setText(i18n("Top:")); } + if (m_initializing) + return; + for (auto* plot : m_plotList) plot->setSymmetricPadding(checked); if (checked) { rightPaddingChanged(ui.sbPaddingHorizontal->value()); bottomPaddingChanged(ui.sbPaddingVertical->value()); } } void CartesianPlotDock::horizontalPaddingChanged(double value) { if (m_initializing) return; double padding = Worksheet::convertToSceneUnits(value, m_worksheetUnit); for (auto* plot : m_plotList) plot->setHorizontalPadding(padding); if (m_plot->symmetricPadding()) { for (auto* plot: m_plotList) plot->setRightPadding(padding); } } void CartesianPlotDock::rightPaddingChanged(double value) { if (m_initializing) return; double padding = Worksheet::convertToSceneUnits(value, m_worksheetUnit); for (auto* plot : m_plotList) plot->setRightPadding(padding); } void CartesianPlotDock::verticalPaddingChanged(double value) { if (m_initializing) return; // TODO: find better solution (set spinbox range). When plot->rect().width() does change? double padding = Worksheet::convertToSceneUnits(value, m_worksheetUnit); for (auto* plot : m_plotList) plot->setVerticalPadding(padding); if (m_plot->symmetricPadding()) { for (auto* plot: m_plotList) plot->setBottomPadding(padding); } } void CartesianPlotDock::bottomPaddingChanged(double value) { if (m_initializing) return; double padding = Worksheet::convertToSceneUnits(value, m_worksheetUnit); for (auto* plot : m_plotList) plot->setBottomPadding(padding); } void CartesianPlotDock::cursorLineWidthChanged(int width) { if (m_initializing) return; for (auto* plot : m_plotList) { QPen pen = plot->cursorPen(); pen.setWidthF( Worksheet::convertToSceneUnits(width, Worksheet::Unit::Point) ); plot->setCursorPen(pen); } } void CartesianPlotDock::cursorLineColorChanged(const QColor& color) { if (m_initializing) return; for (auto* plot : m_plotList) { QPen pen = plot->cursorPen(); pen.setColor(color); plot->setCursorPen(pen); } m_initializing = true; GuiTools::updatePenStyles(ui.cbCursorLineStyle, color); m_initializing = false; } void CartesianPlotDock::cursorLineStyleChanged(int index) { if (m_initializing) return; if (index > 5) return; for (auto* plot : m_plotList) { QPen pen = plot->cursorPen(); pen.setStyle(static_cast(index)); plot->setCursorPen(pen); } } //************************************************************* //****** SLOTs for changes triggered in CartesianPlot ********* //************************************************************* //general void CartesianPlotDock::plotDescriptionChanged(const AbstractAspect* aspect) { if (m_plot != aspect) return; m_initializing = true; if (aspect->name() != ui.leName->text()) ui.leName->setText(aspect->name()); else if (aspect->comment() != ui.leComment->text()) ui.leComment->setText(aspect->comment()); m_initializing = false; } void CartesianPlotDock::plotRectChanged(QRectF& rect) { m_initializing = true; ui.sbLeft->setValue(Worksheet::convertFromSceneUnits(rect.x(), m_worksheetUnit)); ui.sbTop->setValue(Worksheet::convertFromSceneUnits(rect.y(), m_worksheetUnit)); ui.sbWidth->setValue(Worksheet::convertFromSceneUnits(rect.width(), m_worksheetUnit)); ui.sbHeight->setValue(Worksheet::convertFromSceneUnits(rect.height(), m_worksheetUnit)); m_initializing = false; } void CartesianPlotDock::plotRangeTypeChanged(CartesianPlot::RangeType type) { m_initializing = true; switch (type) { case CartesianPlot::RangeFree: ui.rbRangeFree->setChecked(true); break; case CartesianPlot::RangeFirst: ui.rbRangeFirst->setChecked(true); break; case CartesianPlot::RangeLast: ui.rbRangeLast->setChecked(true); break; } m_initializing = false; } void CartesianPlotDock::plotRangeFirstValuesChanged(int value) { m_initializing = true; ui.leRangeFirst->setText(QString::number(value)); m_initializing = false; } void CartesianPlotDock::plotRangeLastValuesChanged(int value) { m_initializing = true; ui.leRangeLast->setText(QString::number(value)); m_initializing = false; } void CartesianPlotDock::plotXAutoScaleChanged(bool value) { m_initializing = true; ui.chkAutoScaleX->setChecked(value); m_initializing = false; } void CartesianPlotDock::plotXMinChanged(double value) { if (m_initializing)return; const Lock lock(m_initializing); ui.leXMin->setText( QString::number(value) ); ui.dateTimeEditXMin->setDateTime( QDateTime::fromMSecsSinceEpoch(value) ); } void CartesianPlotDock::plotXMaxChanged(double value) { if (m_initializing)return; const Lock lock(m_initializing); ui.leXMax->setText( QString::number(value) ); ui.dateTimeEditXMax->setDateTime( QDateTime::fromMSecsSinceEpoch(value) ); } void CartesianPlotDock::plotXScaleChanged(int scale) { m_initializing = true; ui.cbXScaling->setCurrentIndex( scale ); m_initializing = false; } void CartesianPlotDock::plotXRangeFormatChanged(CartesianPlot::RangeFormat format) { m_initializing = true; ui.cbXRangeFormat->setCurrentIndex(format); m_initializing = false; } void CartesianPlotDock::plotYAutoScaleChanged(bool value) { m_initializing = true; ui.chkAutoScaleY->setChecked(value); m_initializing = false; } void CartesianPlotDock::plotYMinChanged(double value) { if (m_initializing)return; const Lock lock(m_initializing); ui.leYMin->setText( QString::number(value) ); ui.dateTimeEditYMin->setDateTime( QDateTime::fromMSecsSinceEpoch(value) ); } void CartesianPlotDock::plotYMaxChanged(double value) { if (m_initializing)return; const Lock lock(m_initializing); ui.leYMax->setText( QString::number(value) ); ui.dateTimeEditYMax->setDateTime( QDateTime::fromMSecsSinceEpoch(value) ); } void CartesianPlotDock::plotYScaleChanged(int scale) { m_initializing = true; ui.cbYScaling->setCurrentIndex( scale ); m_initializing = false; } void CartesianPlotDock::plotYRangeFormatChanged(CartesianPlot::RangeFormat format) { m_initializing = true; ui.cbYRangeFormat->setCurrentIndex(format); m_initializing = false; } void CartesianPlotDock::plotVisibleChanged(bool on) { m_initializing = true; ui.chkVisible->setChecked(on); m_initializing = false; } //range breaks void CartesianPlotDock::plotXRangeBreakingEnabledChanged(bool on) { m_initializing = true; ui.chkXBreak->setChecked(on); m_initializing = false; } void CartesianPlotDock::plotXRangeBreaksChanged(const CartesianPlot::RangeBreaks& breaks) { Q_UNUSED(breaks); } void CartesianPlotDock::plotYRangeBreakingEnabledChanged(bool on) { m_initializing = true; ui.chkYBreak->setChecked(on); m_initializing = false; } void CartesianPlotDock::plotYRangeBreaksChanged(const CartesianPlot::RangeBreaks& breaks) { Q_UNUSED(breaks); } //background void CartesianPlotDock::plotBackgroundTypeChanged(PlotArea::BackgroundType type) { m_initializing = true; ui.cbBackgroundType->setCurrentIndex(static_cast(type)); m_initializing = false; } void CartesianPlotDock::plotBackgroundColorStyleChanged(PlotArea::BackgroundColorStyle style) { m_initializing = true; ui.cbBackgroundColorStyle->setCurrentIndex(static_cast(style)); m_initializing = false; } void CartesianPlotDock::plotBackgroundImageStyleChanged(PlotArea::BackgroundImageStyle style) { m_initializing = true; ui.cbBackgroundImageStyle->setCurrentIndex(static_cast(style)); m_initializing = false; } void CartesianPlotDock::plotBackgroundBrushStyleChanged(Qt::BrushStyle style) { m_initializing = true; ui.cbBackgroundBrushStyle->setCurrentIndex(style); m_initializing = false; } void CartesianPlotDock::plotBackgroundFirstColorChanged(QColor& color) { m_initializing = true; ui.kcbBackgroundFirstColor->setColor(color); m_initializing = false; } void CartesianPlotDock::plotBackgroundSecondColorChanged(QColor& color) { m_initializing = true; ui.kcbBackgroundSecondColor->setColor(color); m_initializing = false; } void CartesianPlotDock::plotBackgroundFileNameChanged(QString& filename) { m_initializing = true; ui.leBackgroundFileName->setText(filename); m_initializing = false; } void CartesianPlotDock::plotBackgroundOpacityChanged(float opacity) { m_initializing = true; ui.sbBackgroundOpacity->setValue( round(opacity*100.0) ); m_initializing = false; } void CartesianPlotDock::plotBorderPenChanged(QPen& pen) { m_initializing = true; if (ui.cbBorderStyle->currentIndex() != pen.style()) ui.cbBorderStyle->setCurrentIndex(pen.style()); if (ui.kcbBorderColor->color() != pen.color()) ui.kcbBorderColor->setColor(pen.color()); if (ui.sbBorderWidth->value() != pen.widthF()) ui.sbBorderWidth->setValue(Worksheet::convertFromSceneUnits(pen.widthF(), Worksheet::Unit::Point)); m_initializing = false; } void CartesianPlotDock::plotBorderCornerRadiusChanged(float value) { m_initializing = true; ui.sbBorderCornerRadius->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void CartesianPlotDock::plotBorderOpacityChanged(float value) { m_initializing = true; float v = (float)value*100.; ui.sbBorderOpacity->setValue(v); m_initializing = false; } void CartesianPlotDock::plotHorizontalPaddingChanged(float value) { m_initializing = true; ui.sbPaddingHorizontal->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void CartesianPlotDock::plotVerticalPaddingChanged(float value) { m_initializing = true; ui.sbPaddingVertical->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void CartesianPlotDock::plotRightPaddingChanged(double value) { m_initializing = true; ui.sbPaddingRight->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void CartesianPlotDock::plotBottomPaddingChanged(double value) { m_initializing = true; ui.sbPaddingBottom->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void CartesianPlotDock::plotSymmetricPaddingChanged(bool symmetric) { m_initializing = true; ui.cbPaddingSymmetric->setChecked(symmetric); m_initializing = false; } void CartesianPlotDock::plotCursorPenChanged(const QPen& pen) { m_initializing = true; ui.sbCursorLineWidth->setValue(Worksheet::convertFromSceneUnits(pen.widthF(), Worksheet::Unit::Point)); ui.kcbCursorLineColor->setColor(pen.color()); ui.cbCursorLineStyle->setCurrentIndex(pen.style()); m_initializing = false; } //************************************************************* //******************** SETTINGS ******************************* //************************************************************* void CartesianPlotDock::loadConfigFromTemplate(KConfig& config) { //extract the name of the template from the file name QString name; int index = config.name().lastIndexOf(QLatin1String("/")); if (index != -1) name = config.name().right(config.name().size() - index - 1); else name = config.name(); int size = m_plotList.size(); if (size > 1) m_plot->beginMacro(i18n("%1 cartesian plots: template \"%2\" loaded", size, name)); else m_plot->beginMacro(i18n("%1: template \"%2\" loaded", m_plot->name(), name)); this->loadConfig(config); m_plot->endMacro(); } void CartesianPlotDock::load() { //General-tab ui.chkVisible->setChecked(m_plot->isVisible()); ui.sbLeft->setValue(Worksheet::convertFromSceneUnits(m_plot->rect().x(), m_worksheetUnit)); ui.sbTop->setValue(Worksheet::convertFromSceneUnits(m_plot->rect().y(), m_worksheetUnit)); ui.sbWidth->setValue(Worksheet::convertFromSceneUnits(m_plot->rect().width(), m_worksheetUnit)); ui.sbHeight->setValue(Worksheet::convertFromSceneUnits(m_plot->rect().height(), m_worksheetUnit)); switch (m_plot->rangeType()) { case CartesianPlot::RangeFree: ui.rbRangeFree->setChecked(true); break; case CartesianPlot::RangeFirst: ui.rbRangeFirst->setChecked(true); break; case CartesianPlot::RangeLast: ui.rbRangeLast->setChecked(true); break; } rangeTypeChanged(); ui.leRangeFirst->setText( QString::number(m_plot->rangeFirstValues()) ); ui.leRangeLast->setText( QString::number(m_plot->rangeLastValues()) ); ui.chkAutoScaleX->setChecked(m_plot->autoScaleX()); ui.leXMin->setText( QString::number(m_plot->xMin()) ); ui.leXMax->setText( QString::number(m_plot->xMax()) ); ui.dateTimeEditXMin->setDisplayFormat(m_plot->xRangeDateTimeFormat()); ui.dateTimeEditXMax->setDisplayFormat(m_plot->xRangeDateTimeFormat()); ui.dateTimeEditXMin->setDateTime(QDateTime::fromMSecsSinceEpoch(m_plot->xMin())); ui.dateTimeEditXMax->setDateTime(QDateTime::fromMSecsSinceEpoch(m_plot->xMax())); ui.cbXScaling->setCurrentIndex( (int) m_plot->xScale() ); ui.cbXRangeFormat->setCurrentIndex( (int) m_plot->xRangeFormat() ); ui.chkAutoScaleY->setChecked(m_plot->autoScaleY()); ui.leYMin->setText( QString::number(m_plot->yMin()) ); ui.leYMax->setText( QString::number(m_plot->yMax()) ); ui.dateTimeEditYMin->setDisplayFormat(m_plot->yRangeDateTimeFormat()); ui.dateTimeEditYMax->setDisplayFormat(m_plot->yRangeDateTimeFormat()); ui.dateTimeEditYMin->setDateTime(QDateTime::fromMSecsSinceEpoch(m_plot->yMin())); ui.dateTimeEditYMax->setDateTime(QDateTime::fromMSecsSinceEpoch(m_plot->yMax())); ui.cbYScaling->setCurrentIndex( (int)m_plot->yScale() ); ui.cbYRangeFormat->setCurrentIndex( (int) m_plot->yRangeFormat() ); //Title labelWidget->load(); //x-range breaks, show the first break ui.chkXBreak->setChecked(m_plot->xRangeBreakingEnabled()); this->toggleXBreak(m_plot->xRangeBreakingEnabled()); ui.bRemoveXBreak->setVisible(m_plot->xRangeBreaks().list.size()>1); ui.cbXBreak->clear(); if (!m_plot->xRangeBreaks().list.isEmpty()) { for (int i = 1; i <= m_plot->xRangeBreaks().list.size(); ++i) ui.cbXBreak->addItem(QString::number(i)); } else ui.cbXBreak->addItem("1"); ui.cbXBreak->setCurrentIndex(0); //y-range breaks, show the first break ui.chkYBreak->setChecked(m_plot->yRangeBreakingEnabled()); this->toggleYBreak(m_plot->yRangeBreakingEnabled()); ui.bRemoveYBreak->setVisible(m_plot->yRangeBreaks().list.size()>1); ui.cbYBreak->clear(); if (!m_plot->yRangeBreaks().list.isEmpty()) { for (int i = 1; i <= m_plot->yRangeBreaks().list.size(); ++i) ui.cbYBreak->addItem(QString::number(i)); } else ui.cbYBreak->addItem("1"); ui.cbYBreak->setCurrentIndex(0); //"Plot Area"-tab //Background ui.cbBackgroundType->setCurrentIndex( (int)m_plot->plotArea()->backgroundType() ); ui.cbBackgroundColorStyle->setCurrentIndex( (int) m_plot->plotArea()->backgroundColorStyle() ); ui.cbBackgroundImageStyle->setCurrentIndex( (int) m_plot->plotArea()->backgroundImageStyle() ); ui.cbBackgroundBrushStyle->setCurrentIndex( (int) m_plot->plotArea()->backgroundBrushStyle() ); ui.leBackgroundFileName->setText( m_plot->plotArea()->backgroundFileName() ); ui.kcbBackgroundFirstColor->setColor( m_plot->plotArea()->backgroundFirstColor() ); ui.kcbBackgroundSecondColor->setColor( m_plot->plotArea()->backgroundSecondColor() ); ui.sbBackgroundOpacity->setValue( round(m_plot->plotArea()->backgroundOpacity()*100.0) ); //highlight the text field for the background image red if an image is used and cannot be found if (!m_plot->plotArea()->backgroundFileName().isEmpty() && !QFile::exists(m_plot->plotArea()->backgroundFileName())) ui.leBackgroundFileName->setStyleSheet("QLineEdit{background:red;}"); else ui.leBackgroundFileName->setStyleSheet(QString()); //Padding ui.sbPaddingHorizontal->setValue( Worksheet::convertFromSceneUnits(m_plot->horizontalPadding(), m_worksheetUnit) ); ui.sbPaddingVertical->setValue( Worksheet::convertFromSceneUnits(m_plot->verticalPadding(), m_worksheetUnit) ); ui.sbPaddingRight->setValue(Worksheet::convertFromSceneUnits(m_plot->rightPadding(), m_worksheetUnit)); ui.sbPaddingBottom->setValue(Worksheet::convertFromSceneUnits(m_plot->bottomPadding(), m_worksheetUnit)); ui.cbPaddingSymmetric->setChecked(m_plot->symmetricPadding()); //Border ui.kcbBorderColor->setColor( m_plot->plotArea()->borderPen().color() ); ui.cbBorderStyle->setCurrentIndex( (int) m_plot->plotArea()->borderPen().style() ); ui.sbBorderWidth->setValue( Worksheet::convertFromSceneUnits(m_plot->plotArea()->borderPen().widthF(), Worksheet::Unit::Point) ); ui.sbBorderCornerRadius->setValue( Worksheet::convertFromSceneUnits(m_plot->plotArea()->borderCornerRadius(), m_worksheetUnit) ); ui.sbBorderOpacity->setValue( round(m_plot->plotArea()->borderOpacity()*100) ); GuiTools::updatePenStyles(ui.cbBorderStyle, ui.kcbBorderColor->color()); // Cursor QPen pen = m_plot->cursorPen(); ui.cbCursorLineStyle->setCurrentIndex(pen.style()); ui.kcbCursorLineColor->setColor(pen.color()); ui.sbCursorLineWidth->setValue(pen.width()); GuiTools::updatePenStyles(ui.cbCursorLineStyle, pen.color()); } void CartesianPlotDock::loadConfig(KConfig& config) { KConfigGroup group = config.group("CartesianPlot"); //General //we don't load/save the settings in the general-tab, since they are not style related. //It doesn't make sense to load/save them in the template. //This data is read in CartesianPlotDock::setPlots(). //Title KConfigGroup plotTitleGroup = config.group("CartesianPlotTitle"); labelWidget->loadConfig(plotTitleGroup); //Scale breakings //TODO //Background-tab ui.cbBackgroundType->setCurrentIndex( group.readEntry("BackgroundType", (int) m_plot->plotArea()->backgroundType()) ); ui.cbBackgroundColorStyle->setCurrentIndex( group.readEntry("BackgroundColorStyle", (int) m_plot->plotArea()->backgroundColorStyle()) ); ui.cbBackgroundImageStyle->setCurrentIndex( group.readEntry("BackgroundImageStyle", (int) m_plot->plotArea()->backgroundImageStyle()) ); ui.cbBackgroundBrushStyle->setCurrentIndex( group.readEntry("BackgroundBrushStyle", (int) m_plot->plotArea()->backgroundBrushStyle()) ); ui.leBackgroundFileName->setText( group.readEntry("BackgroundFileName", m_plot->plotArea()->backgroundFileName()) ); ui.kcbBackgroundFirstColor->setColor( group.readEntry("BackgroundFirstColor", m_plot->plotArea()->backgroundFirstColor()) ); ui.kcbBackgroundSecondColor->setColor( group.readEntry("BackgroundSecondColor", m_plot->plotArea()->backgroundSecondColor()) ); ui.sbBackgroundOpacity->setValue( round(group.readEntry("BackgroundOpacity", m_plot->plotArea()->backgroundOpacity())*100.0) ); ui.sbPaddingHorizontal->setValue(Worksheet::convertFromSceneUnits(group.readEntry("HorizontalPadding", m_plot->horizontalPadding()), m_worksheetUnit)); ui.sbPaddingVertical->setValue(Worksheet::convertFromSceneUnits(group.readEntry("VerticalPadding", m_plot->verticalPadding()), m_worksheetUnit)); ui.sbPaddingRight->setValue(Worksheet::convertFromSceneUnits(group.readEntry("RightPadding", m_plot->rightPadding()), m_worksheetUnit)); ui.sbPaddingBottom->setValue(Worksheet::convertFromSceneUnits(group.readEntry("BottomPadding", m_plot->bottomPadding()), m_worksheetUnit)); ui.cbPaddingSymmetric->setChecked(group.readEntry("SymmetricPadding", m_plot->symmetricPadding())); //Border-tab ui.kcbBorderColor->setColor( group.readEntry("BorderColor", m_plot->plotArea()->borderPen().color()) ); ui.cbBorderStyle->setCurrentIndex( group.readEntry("BorderStyle", (int) m_plot->plotArea()->borderPen().style()) ); ui.sbBorderWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("BorderWidth", m_plot->plotArea()->borderPen().widthF()), Worksheet::Unit::Point) ); ui.sbBorderCornerRadius->setValue( Worksheet::convertFromSceneUnits(group.readEntry("BorderCornerRadius", m_plot->plotArea()->borderCornerRadius()), m_worksheetUnit) ); ui.sbBorderOpacity->setValue( group.readEntry("BorderOpacity", m_plot->plotArea()->borderOpacity())*100 ); m_initializing = true; GuiTools::updatePenStyles(ui.cbBorderStyle, ui.kcbBorderColor->color()); GuiTools::updatePenStyles(ui.cbCursorLineStyle, m_plot->cursorPen().color()); m_initializing = false; } void CartesianPlotDock::saveConfigAsTemplate(KConfig& config) { KConfigGroup group = config.group("CartesianPlot"); //General //we don't load/save the settings in the general-tab, since they are not style related. //It doesn't make sense to load/save them in the template. //Title KConfigGroup plotTitleGroup = config.group("CartesianPlotTitle"); labelWidget->saveConfig(plotTitleGroup); //Scale breakings //TODO //Background group.writeEntry("BackgroundType", ui.cbBackgroundType->currentIndex()); group.writeEntry("BackgroundColorStyle", ui.cbBackgroundColorStyle->currentIndex()); group.writeEntry("BackgroundImageStyle", ui.cbBackgroundImageStyle->currentIndex()); group.writeEntry("BackgroundBrushStyle", ui.cbBackgroundBrushStyle->currentIndex()); group.writeEntry("BackgroundFileName", ui.leBackgroundFileName->text()); group.writeEntry("BackgroundFirstColor", ui.kcbBackgroundFirstColor->color()); group.writeEntry("BackgroundSecondColor", ui.kcbBackgroundSecondColor->color()); group.writeEntry("BackgroundOpacity", ui.sbBackgroundOpacity->value()/100.0); group.writeEntry("HorizontalPadding", Worksheet::convertToSceneUnits(ui.sbPaddingHorizontal->value(), m_worksheetUnit)); group.writeEntry("VerticalPadding", Worksheet::convertToSceneUnits(ui.sbPaddingVertical->value(), m_worksheetUnit)); group.writeEntry("RightPadding", Worksheet::convertToSceneUnits(ui.sbPaddingRight->value(), m_worksheetUnit)); group.writeEntry("BottomPadding", Worksheet::convertToSceneUnits(ui.sbPaddingBottom->value(), m_worksheetUnit)); group.writeEntry("SymmetricPadding", ui.cbPaddingSymmetric->isChecked()); //Border group.writeEntry("BorderStyle", ui.cbBorderStyle->currentIndex()); group.writeEntry("BorderColor", ui.kcbBorderColor->color()); group.writeEntry("BorderWidth", Worksheet::convertToSceneUnits(ui.sbBorderWidth->value(), Worksheet::Unit::Point)); group.writeEntry("BorderCornerRadius", Worksheet::convertToSceneUnits(ui.sbBorderCornerRadius->value(), m_worksheetUnit)); group.writeEntry("BorderOpacity", ui.sbBorderOpacity->value()/100.0); config.sync(); } void CartesianPlotDock::loadTheme(const QString& theme) { for (auto* plot : m_plotList) plot->setTheme(theme); } void CartesianPlotDock::saveTheme(KConfig& config) const { if (!m_plotList.isEmpty()) m_plotList.at(0)->saveTheme(config); } diff --git a/src/kdefrontend/dockwidgets/CartesianPlotLegendDock.cpp b/src/kdefrontend/dockwidgets/CartesianPlotLegendDock.cpp index e085657b0..711b12559 100644 --- a/src/kdefrontend/dockwidgets/CartesianPlotLegendDock.cpp +++ b/src/kdefrontend/dockwidgets/CartesianPlotLegendDock.cpp @@ -1,1169 +1,1169 @@ /*************************************************************************** File : CartesianPlotLegendDock.cpp Project : LabPlot -------------------------------------------------------------------- Copyright : (C) 2013-2020 by Alexander Semke (alexander.semke@web.de) Description : widget for cartesian plot legend properties ***************************************************************************/ /*************************************************************************** * * * 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 "CartesianPlotLegendDock.h" #include "backend/worksheet/plots/PlotArea.h" #include "backend/worksheet/Worksheet.h" #include "kdefrontend/widgets/LabelWidget.h" #include "kdefrontend/GuiTools.h" #include "kdefrontend/TemplateHandler.h" #include #include #include #include #include #include #include /*! \class CartesianPlotLegendDock \brief Provides a widget for editing the properties of the cartesian plot legend currently selected in the project explorer. \ingroup kdefrontend */ CartesianPlotLegendDock::CartesianPlotLegendDock(QWidget* parent) : BaseDock(parent) { ui.setupUi(this); m_leName = ui.leName; m_leComment = ui.leComment; //"Title"-tab auto hboxLayout = new QHBoxLayout(ui.tabTitle); labelWidget = new LabelWidget(ui.tabTitle); labelWidget->setGeometryAvailable(false); labelWidget->setBorderAvailable(false); hboxLayout->addWidget(labelWidget); hboxLayout->setContentsMargins(2,2,2,2); hboxLayout->setSpacing(2); //"Background"-tab ui.bOpen->setIcon( QIcon::fromTheme("document-open") ); ui.leBackgroundFileName->setCompleter(new QCompleter(new QDirModel, this)); //adjust layouts in the tabs for (int i = 0; i < ui.tabWidget->count(); ++i) { auto layout = dynamic_cast(ui.tabWidget->widget(i)->layout()); if (!layout) continue; layout->setContentsMargins(2,2,2,2); layout->setHorizontalSpacing(2); layout->setVerticalSpacing(2); } //SIGNAL/SLOT //General connect(ui.leName, &QLineEdit::textChanged, this, &CartesianPlotLegendDock::nameChanged); connect(ui.leComment, &QLineEdit::textChanged, this, &CartesianPlotLegendDock::commentChanged); connect(ui.chkVisible, &QCheckBox::clicked, this, &CartesianPlotLegendDock::visibilityChanged); connect(ui.kfrLabelFont, &KFontRequester::fontSelected, this, &CartesianPlotLegendDock::labelFontChanged); connect(ui.kcbLabelColor, &KColorButton::changed, this, &CartesianPlotLegendDock::labelColorChanged); connect(ui.cbOrder, QOverload::of(&QComboBox::currentIndexChanged), this, &CartesianPlotLegendDock::labelOrderChanged); connect(ui.sbLineSymbolWidth, QOverload::of(&QDoubleSpinBox::valueChanged), this, &CartesianPlotLegendDock::lineSymbolWidthChanged); connect(ui.cbPositionX, QOverload::of(&QComboBox::currentIndexChanged), this, &CartesianPlotLegendDock::positionXChanged); connect(ui.cbPositionY, QOverload::of(&QComboBox::currentIndexChanged), this, &CartesianPlotLegendDock::positionYChanged); connect(ui.sbPositionX, QOverload::of(&QDoubleSpinBox::valueChanged), this, &CartesianPlotLegendDock::customPositionXChanged); connect(ui.sbPositionY, QOverload::of(&QDoubleSpinBox::valueChanged), this, &CartesianPlotLegendDock::customPositionYChanged); connect(ui.sbRotation, QOverload::of(&QSpinBox::valueChanged), this, &CartesianPlotLegendDock::rotationChanged); //Background connect(ui.cbBackgroundType, QOverload::of(&QComboBox::currentIndexChanged), this, &CartesianPlotLegendDock::backgroundTypeChanged); connect(ui.cbBackgroundColorStyle, QOverload::of(&QComboBox::currentIndexChanged), this, &CartesianPlotLegendDock::backgroundColorStyleChanged); connect(ui.cbBackgroundImageStyle, QOverload::of(&QComboBox::currentIndexChanged), this, &CartesianPlotLegendDock::backgroundImageStyleChanged); connect(ui.cbBackgroundBrushStyle, QOverload::of(&QComboBox::currentIndexChanged), this, &CartesianPlotLegendDock::backgroundBrushStyleChanged); connect(ui.bOpen, &QPushButton::clicked, this, &CartesianPlotLegendDock::selectFile); connect(ui.leBackgroundFileName, &QLineEdit::returnPressed, this, &CartesianPlotLegendDock::fileNameChanged); connect(ui.leBackgroundFileName, &QLineEdit::textChanged, this, &CartesianPlotLegendDock::fileNameChanged); connect(ui.kcbBackgroundFirstColor, &KColorButton::changed, this, &CartesianPlotLegendDock::backgroundFirstColorChanged); connect(ui.kcbBackgroundSecondColor, &KColorButton::changed, this, &CartesianPlotLegendDock::backgroundSecondColorChanged); connect(ui.sbBackgroundOpacity, QOverload::of(&QSpinBox::valueChanged), this, &CartesianPlotLegendDock::backgroundOpacityChanged); //Border connect(ui.cbBorderStyle, QOverload::of(&QComboBox::currentIndexChanged), this, &CartesianPlotLegendDock::borderStyleChanged); connect(ui.kcbBorderColor, &KColorButton::changed, this, &CartesianPlotLegendDock::borderColorChanged); connect(ui.sbBorderWidth, QOverload::of(&QDoubleSpinBox::valueChanged), this, &CartesianPlotLegendDock::borderWidthChanged); connect(ui.sbBorderCornerRadius, QOverload::of(&QDoubleSpinBox::valueChanged), this, &CartesianPlotLegendDock::borderCornerRadiusChanged); connect(ui.sbBorderOpacity, QOverload::of(&QSpinBox::valueChanged), this, &CartesianPlotLegendDock::borderOpacityChanged); //Layout connect(ui.sbLayoutTopMargin, QOverload::of(&QDoubleSpinBox::valueChanged), this, &CartesianPlotLegendDock::layoutTopMarginChanged); connect(ui.sbLayoutBottomMargin, QOverload::of(&QDoubleSpinBox::valueChanged), this, &CartesianPlotLegendDock::layoutBottomMarginChanged); connect(ui.sbLayoutLeftMargin, QOverload::of(&QDoubleSpinBox::valueChanged), this, &CartesianPlotLegendDock::layoutLeftMarginChanged); connect(ui.sbLayoutRightMargin, QOverload::of(&QDoubleSpinBox::valueChanged), this, &CartesianPlotLegendDock::layoutRightMarginChanged); connect(ui.sbLayoutHorizontalSpacing, QOverload::of(&QDoubleSpinBox::valueChanged), this, &CartesianPlotLegendDock::layoutHorizontalSpacingChanged); connect(ui.sbLayoutVerticalSpacing, QOverload::of(&QDoubleSpinBox::valueChanged), this, &CartesianPlotLegendDock::layoutVerticalSpacingChanged); connect(ui.sbLayoutColumnCount, QOverload::of(&QSpinBox::valueChanged), this, &CartesianPlotLegendDock::layoutColumnCountChanged); //template handler auto* frame = new QFrame(this); auto* layout = new QHBoxLayout(frame); layout->setContentsMargins(0, 11, 0, 11); auto* templateHandler = new TemplateHandler(this, TemplateHandler::CartesianPlotLegend); layout->addWidget(templateHandler); connect(templateHandler, &TemplateHandler::loadConfigRequested, this, &CartesianPlotLegendDock::loadConfigFromTemplate); connect(templateHandler, &TemplateHandler::saveConfigRequested, this, &CartesianPlotLegendDock::saveConfigAsTemplate); connect(templateHandler, &TemplateHandler::info, this, &CartesianPlotLegendDock::info); ui.verticalLayout->addWidget(frame); init(); } void CartesianPlotLegendDock::init() { this->retranslateUi(); } void CartesianPlotLegendDock::setLegends(QList list) { Lock lock(m_initializing); m_legendList = list; m_legend = list.first(); m_aspect = list.first(); //if there is more then one legend in the list, disable the tab "general" if (list.size() == 1) { ui.lName->setEnabled(true); ui.leName->setEnabled(true); ui.lComment->setEnabled(true); ui.leComment->setEnabled(true); ui.leName->setText(m_legend->name()); ui.leComment->setText(m_legend->comment()); } else { ui.lName->setEnabled(false); ui.leName->setEnabled(false); ui.lComment->setEnabled(false); ui.leComment->setEnabled(false); ui.leName->setText(QString()); ui.leComment->setText(QString()); } ui.leName->setStyleSheet(""); ui.leName->setToolTip(""); //show the properties of the first curve this->load(); //on the very first start the column count shown in UI is 1. //if the this count for m_legend is also 1 then the slot layoutColumnCountChanged is not called //and we need to disable the "order" widgets here. ui.lOrder->setVisible(m_legend->layoutColumnCount()!=1); ui.cbOrder->setVisible(m_legend->layoutColumnCount()!=1); //legend title QList labels; for (auto* legend : list) labels.append(legend->title()); labelWidget->setLabels(labels); //update active widgets backgroundTypeChanged(ui.cbBackgroundType->currentIndex()); //SIGNALs/SLOTs //General connect(m_legend, &AbstractAspect::aspectDescriptionChanged, this, &CartesianPlotLegendDock::legendDescriptionChanged); connect(m_legend, &CartesianPlotLegend::labelFontChanged, this, &CartesianPlotLegendDock::legendLabelFontChanged); connect(m_legend, &CartesianPlotLegend::labelColorChanged, this, &CartesianPlotLegendDock::legendLabelColorChanged); connect(m_legend, &CartesianPlotLegend::labelColumnMajorChanged, this, &CartesianPlotLegendDock::legendLabelOrderChanged); connect(m_legend, QOverload::of(&CartesianPlotLegend::positionChanged), this, &CartesianPlotLegendDock::legendPositionChanged); connect(m_legend, &CartesianPlotLegend::rotationAngleChanged, this, &CartesianPlotLegendDock::legendRotationAngleChanged); connect(m_legend, &CartesianPlotLegend::lineSymbolWidthChanged, this, &CartesianPlotLegendDock::legendLineSymbolWidthChanged); connect(m_legend, &CartesianPlotLegend::visibilityChanged, this, &CartesianPlotLegendDock::legendVisibilityChanged); //background connect(m_legend, &CartesianPlotLegend::backgroundTypeChanged, this, &CartesianPlotLegendDock::legendBackgroundTypeChanged); connect(m_legend, &CartesianPlotLegend::backgroundColorStyleChanged, this, &CartesianPlotLegendDock::legendBackgroundColorStyleChanged); connect(m_legend, &CartesianPlotLegend::backgroundImageStyleChanged, this, &CartesianPlotLegendDock::legendBackgroundImageStyleChanged); connect(m_legend, &CartesianPlotLegend::backgroundBrushStyleChanged, this, &CartesianPlotLegendDock::legendBackgroundBrushStyleChanged); connect(m_legend, &CartesianPlotLegend::backgroundFirstColorChanged, this, &CartesianPlotLegendDock::legendBackgroundFirstColorChanged); connect(m_legend, &CartesianPlotLegend::backgroundSecondColorChanged, this, &CartesianPlotLegendDock::legendBackgroundSecondColorChanged); connect(m_legend, &CartesianPlotLegend::backgroundFileNameChanged, this, &CartesianPlotLegendDock::legendBackgroundFileNameChanged); connect(m_legend, &CartesianPlotLegend::backgroundOpacityChanged, this, &CartesianPlotLegendDock::legendBackgroundOpacityChanged); connect(m_legend, &CartesianPlotLegend::borderPenChanged, this, &CartesianPlotLegendDock::legendBorderPenChanged); connect(m_legend, &CartesianPlotLegend::borderCornerRadiusChanged, this, &CartesianPlotLegendDock::legendBorderCornerRadiusChanged); connect(m_legend, &CartesianPlotLegend::borderOpacityChanged, this, &CartesianPlotLegendDock::legendBorderOpacityChanged); //layout connect(m_legend, &CartesianPlotLegend::layoutTopMarginChanged, this, &CartesianPlotLegendDock::legendLayoutTopMarginChanged); connect(m_legend, &CartesianPlotLegend::layoutBottomMarginChanged, this, &CartesianPlotLegendDock::legendLayoutBottomMarginChanged); connect(m_legend, &CartesianPlotLegend::layoutLeftMarginChanged, this, &CartesianPlotLegendDock::legendLayoutLeftMarginChanged); connect(m_legend, &CartesianPlotLegend::layoutRightMarginChanged, this, &CartesianPlotLegendDock::legendLayoutRightMarginChanged); connect(m_legend, &CartesianPlotLegend::layoutVerticalSpacingChanged, this, &CartesianPlotLegendDock::legendLayoutVerticalSpacingChanged); connect(m_legend, &CartesianPlotLegend::layoutHorizontalSpacingChanged, this, &CartesianPlotLegendDock::legendLayoutHorizontalSpacingChanged); connect(m_legend, &CartesianPlotLegend::layoutColumnCountChanged, this, &CartesianPlotLegendDock::legendLayoutColumnCountChanged); } void CartesianPlotLegendDock::activateTitleTab() const{ ui.tabWidget->setCurrentWidget(ui.tabTitle); } void CartesianPlotLegendDock::updateUnits() { const KConfigGroup group = KSharedConfig::openConfig()->group(QLatin1String("Settings_General")); BaseDock::Units units = (BaseDock::Units)group.readEntry("Units", (int)MetricUnits); if (units == m_units) return; m_units = units; Lock lock(m_initializing); QString suffix; if (m_units == BaseDock::MetricUnits) { //convert from imperial to metric m_worksheetUnit = Worksheet::Unit::Centimeter; - suffix = QLatin1String("cm"); + suffix = QLatin1String(" cm"); ui.sbLineSymbolWidth->setValue(ui.sbLineSymbolWidth->value()*2.54); ui.sbPositionX->setValue(ui.sbPositionX->value()*2.54); ui.sbPositionY->setValue(ui.sbPositionY->value()*2.54); ui.sbBorderCornerRadius->setValue(ui.sbBorderCornerRadius->value()*2.54); ui.sbLayoutTopMargin->setValue(ui.sbLayoutTopMargin->value()*2.54); ui.sbLayoutBottomMargin->setValue(ui.sbLayoutBottomMargin->value()*2.54); ui.sbLayoutLeftMargin->setValue(ui.sbLayoutLeftMargin->value()*2.54); ui.sbLayoutRightMargin->setValue(ui.sbLayoutRightMargin->value()*2.54); ui.sbLayoutHorizontalSpacing->setValue(ui.sbLayoutHorizontalSpacing->value()*2.54); ui.sbLayoutVerticalSpacing->setValue(ui.sbLayoutVerticalSpacing->value()*2.54); } else { //convert from metric to imperial m_worksheetUnit = Worksheet::Unit::Inch; - suffix = QLatin1String("in"); + suffix = QLatin1String(" in"); ui.sbLineSymbolWidth->setValue(ui.sbLineSymbolWidth->value()/2.54); ui.sbPositionX->setValue(ui.sbPositionX->value()/2.54); ui.sbPositionY->setValue(ui.sbPositionY->value()/2.54); ui.sbBorderCornerRadius->setValue(ui.sbBorderCornerRadius->value()/2.54); ui.sbLayoutTopMargin->setValue(ui.sbLayoutTopMargin->value()/2.54); ui.sbLayoutBottomMargin->setValue(ui.sbLayoutBottomMargin->value()/2.54); ui.sbLayoutLeftMargin->setValue(ui.sbLayoutLeftMargin->value()/2.54); ui.sbLayoutRightMargin->setValue(ui.sbLayoutRightMargin->value()/2.54); ui.sbLayoutHorizontalSpacing->setValue(ui.sbLayoutHorizontalSpacing->value()/2.54); ui.sbLayoutVerticalSpacing->setValue(ui.sbLayoutVerticalSpacing->value()/2.54); } ui.sbLineSymbolWidth->setSuffix(suffix); ui.sbPositionX->setSuffix(suffix); ui.sbPositionY->setSuffix(suffix); ui.sbBorderCornerRadius->setSuffix(suffix); ui.sbLayoutTopMargin->setSuffix(suffix); ui.sbLayoutBottomMargin->setSuffix(suffix); ui.sbLayoutLeftMargin->setSuffix(suffix); ui.sbLayoutRightMargin->setSuffix(suffix); ui.sbLayoutHorizontalSpacing->setSuffix(suffix); ui.sbLayoutVerticalSpacing->setSuffix(suffix); labelWidget->updateUnits(); } //************************************************************ //** SLOTs for changes triggered in CartesianPlotLegendDock ** //************************************************************ void CartesianPlotLegendDock::retranslateUi() { Lock lock(m_initializing); ui.cbBackgroundType->addItem(i18n("Color")); ui.cbBackgroundType->addItem(i18n("Image")); ui.cbBackgroundType->addItem(i18n("Pattern")); ui.cbBackgroundColorStyle->addItem(i18n("Single Color")); ui.cbBackgroundColorStyle->addItem(i18n("Horizontal Gradient")); ui.cbBackgroundColorStyle->addItem(i18n("Vertical Gradient")); ui.cbBackgroundColorStyle->addItem(i18n("Diag. Gradient (From Top Left)")); ui.cbBackgroundColorStyle->addItem(i18n("Diag. Gradient (From Bottom Left)")); ui.cbBackgroundColorStyle->addItem(i18n("Radial Gradient")); ui.cbBackgroundImageStyle->addItem(i18n("Scaled and Cropped")); ui.cbBackgroundImageStyle->addItem(i18n("Scaled")); ui.cbBackgroundImageStyle->addItem(i18n("Scaled, Keep Proportions")); ui.cbBackgroundImageStyle->addItem(i18n("Centered")); ui.cbBackgroundImageStyle->addItem(i18n("Tiled")); ui.cbBackgroundImageStyle->addItem(i18n("Center Tiled")); ui.cbOrder->addItem(i18n("Column Major")); ui.cbOrder->addItem(i18n("Row Major")); ui.cbPositionX->addItem(i18n("Left")); ui.cbPositionX->addItem(i18n("Center")); ui.cbPositionX->addItem(i18n("Right")); ui.cbPositionX->addItem(i18n("Custom")); ui.cbPositionY->addItem(i18n("Top")); ui.cbPositionY->addItem(i18n("Center")); ui.cbPositionY->addItem(i18n("Bottom")); ui.cbPositionY->addItem(i18n("Custom")); GuiTools::updatePenStyles(ui.cbBorderStyle, Qt::black); GuiTools::updateBrushStyles(ui.cbBackgroundBrushStyle, Qt::SolidPattern); QString suffix; if (m_units == BaseDock::MetricUnits) - suffix = QLatin1String("cm"); + suffix = QLatin1String(" cm"); else - suffix = QLatin1String("in"); + suffix = QLatin1String(" in"); ui.sbLineSymbolWidth->setSuffix(suffix); ui.sbPositionX->setSuffix(suffix); ui.sbPositionY->setSuffix(suffix); ui.sbBorderCornerRadius->setSuffix(suffix); ui.sbLayoutTopMargin->setSuffix(suffix); ui.sbLayoutBottomMargin->setSuffix(suffix); ui.sbLayoutLeftMargin->setSuffix(suffix); ui.sbLayoutRightMargin->setSuffix(suffix); ui.sbLayoutHorizontalSpacing->setSuffix(suffix); ui.sbLayoutVerticalSpacing->setSuffix(suffix); } // "General"-tab void CartesianPlotLegendDock::visibilityChanged(bool state) { if (m_initializing) return; for (auto* legend : m_legendList) legend->setVisible(state); } //General void CartesianPlotLegendDock::labelFontChanged(const QFont& font) { if (m_initializing) return; QFont labelsFont = font; labelsFont.setPixelSize( Worksheet::convertToSceneUnits(font.pointSizeF(), Worksheet::Unit::Point) ); for (auto* legend : m_legendList) legend->setLabelFont(labelsFont); } void CartesianPlotLegendDock::labelColorChanged(const QColor& color) { if (m_initializing) return; for (auto* legend : m_legendList) legend->setLabelColor(color); } void CartesianPlotLegendDock::labelOrderChanged(const int index) { if (m_initializing) return; bool columnMajor = (index == 0); for (auto* legend : m_legendList) legend->setLabelColumnMajor(columnMajor); } void CartesianPlotLegendDock::lineSymbolWidthChanged(double value) { if (m_initializing) return; for (auto* legend : m_legendList) legend->setLineSymbolWidth(Worksheet::convertToSceneUnits(value, m_worksheetUnit)); } /*! called when legend's current horizontal position relative to its parent (left, center, right, custom ) is changed. */ void CartesianPlotLegendDock::positionXChanged(int index) { //Enable/disable the spinbox for the x- oordinates if the "custom position"-item is selected/deselected if (index == ui.cbPositionX->count()-1 ) { ui.sbPositionX->setEnabled(true); } else { ui.sbPositionX->setEnabled(false); } if (m_initializing) return; CartesianPlotLegend::PositionWrapper position = m_legend->position(); position.horizontalPosition = CartesianPlotLegend::HorizontalPosition(index); for (auto* legend : m_legendList) legend->setPosition(position); } /*! called when legend's current horizontal position relative to its parent (top, center, bottom, custom ) is changed. */ void CartesianPlotLegendDock::positionYChanged(int index) { //Enable/disable the spinbox for the y- oordinates if the "custom position"-item is selected/deselected if (index == ui.cbPositionY->count()-1 ) { ui.sbPositionY->setEnabled(true); } else { ui.sbPositionY->setEnabled(false); } if (m_initializing) return; CartesianPlotLegend::PositionWrapper position = m_legend->position(); position.verticalPosition = CartesianPlotLegend::VerticalPosition(index); for (auto* legend : m_legendList) legend->setPosition(position); } void CartesianPlotLegendDock::customPositionXChanged(double value) { if (m_initializing) return; CartesianPlotLegend::PositionWrapper position = m_legend->position(); position.point.setX(Worksheet::convertToSceneUnits(value, m_worksheetUnit)); for (auto* legend : m_legendList) legend->setPosition(position); } void CartesianPlotLegendDock::customPositionYChanged(double value) { if (m_initializing) return; CartesianPlotLegend::PositionWrapper position = m_legend->position(); position.point.setY(Worksheet::convertToSceneUnits(value, m_worksheetUnit)); for (auto* legend : m_legendList) legend->setPosition(position); } void CartesianPlotLegendDock::rotationChanged(int value) { if (m_initializing) return; for (auto* curve : m_legendList) curve->setRotationAngle(value); } // "Background"-tab void CartesianPlotLegendDock::backgroundTypeChanged(int index) { const auto type = (PlotArea::BackgroundType)index; if (type == PlotArea::BackgroundType::Color) { ui.lBackgroundColorStyle->show(); ui.cbBackgroundColorStyle->show(); ui.lBackgroundImageStyle->hide(); ui.cbBackgroundImageStyle->hide(); ui.lBackgroundBrushStyle->hide(); ui.cbBackgroundBrushStyle->hide(); ui.lBackgroundFileName->hide(); ui.leBackgroundFileName->hide(); ui.bOpen->hide(); ui.lBackgroundFirstColor->show(); ui.kcbBackgroundFirstColor->show(); auto style = (PlotArea::BackgroundColorStyle) ui.cbBackgroundColorStyle->currentIndex(); if (style == PlotArea::BackgroundColorStyle::SingleColor) { ui.lBackgroundFirstColor->setText(i18n("Color:")); ui.lBackgroundSecondColor->hide(); ui.kcbBackgroundSecondColor->hide(); } else { ui.lBackgroundFirstColor->setText(i18n("First color:")); ui.lBackgroundSecondColor->show(); ui.kcbBackgroundSecondColor->show(); } } else if (type == PlotArea::BackgroundType::Image) { ui.lBackgroundColorStyle->hide(); ui.cbBackgroundColorStyle->hide(); ui.lBackgroundImageStyle->show(); ui.cbBackgroundImageStyle->show(); ui.lBackgroundBrushStyle->hide(); ui.cbBackgroundBrushStyle->hide(); ui.lBackgroundFileName->show(); ui.leBackgroundFileName->show(); ui.bOpen->show(); ui.lBackgroundFirstColor->hide(); ui.kcbBackgroundFirstColor->hide(); ui.lBackgroundSecondColor->hide(); ui.kcbBackgroundSecondColor->hide(); } else if (type == PlotArea::BackgroundType::Pattern) { ui.lBackgroundFirstColor->setText(i18n("Color:")); ui.lBackgroundColorStyle->hide(); ui.cbBackgroundColorStyle->hide(); ui.lBackgroundImageStyle->hide(); ui.cbBackgroundImageStyle->hide(); ui.lBackgroundBrushStyle->show(); ui.cbBackgroundBrushStyle->show(); ui.lBackgroundFileName->hide(); ui.leBackgroundFileName->hide(); ui.bOpen->hide(); ui.lBackgroundFirstColor->show(); ui.kcbBackgroundFirstColor->show(); ui.lBackgroundSecondColor->hide(); ui.kcbBackgroundSecondColor->hide(); } if (m_initializing) return; for (auto* legend : m_legendList) legend->setBackgroundType(type); } void CartesianPlotLegendDock::backgroundColorStyleChanged(int index) { auto style = (PlotArea::BackgroundColorStyle)index; if (style == PlotArea::BackgroundColorStyle::SingleColor) { ui.lBackgroundFirstColor->setText(i18n("Color:")); ui.lBackgroundSecondColor->hide(); ui.kcbBackgroundSecondColor->hide(); } else { ui.lBackgroundFirstColor->setText(i18n("First color:")); ui.lBackgroundSecondColor->show(); ui.kcbBackgroundSecondColor->show(); ui.lBackgroundBrushStyle->hide(); ui.cbBackgroundBrushStyle->hide(); } if (m_initializing) return; for (auto* legend : m_legendList) legend->setBackgroundColorStyle(style); } void CartesianPlotLegendDock::backgroundImageStyleChanged(int index) { if (m_initializing) return; auto style = (PlotArea::BackgroundImageStyle)index; for (auto* legend : m_legendList) legend->setBackgroundImageStyle(style); } void CartesianPlotLegendDock::backgroundBrushStyleChanged(int index) { if (m_initializing) return; auto style = (Qt::BrushStyle)index; for (auto* legend : m_legendList) legend->setBackgroundBrushStyle(style); } void CartesianPlotLegendDock::backgroundFirstColorChanged(const QColor& c) { if (m_initializing) return; for (auto* legend : m_legendList) legend->setBackgroundFirstColor(c); } void CartesianPlotLegendDock::backgroundSecondColorChanged(const QColor& c) { if (m_initializing) return; for (auto* legend : m_legendList) legend->setBackgroundSecondColor(c); } /*! opens a file dialog and lets the user select the image file. */ void CartesianPlotLegendDock::selectFile() { KConfigGroup conf(KSharedConfig::openConfig(), "CartesianPlotLegendDock"); QString dir = conf.readEntry("LastImageDir", ""); QString formats; for (const QByteArray& format : QImageReader::supportedImageFormats()) { QString f = "*." + QString(format.constData()); if (f == QLatin1String("*.svg")) continue; formats.isEmpty() ? formats += f : formats += ' ' + f; } QString path = QFileDialog::getOpenFileName(this, i18n("Select the image file"), dir, i18n("Images (%1)", formats)); if (path.isEmpty()) return; //cancel was clicked in the file-dialog int pos = path.lastIndexOf(QLatin1String("/")); if (pos != -1) { QString newDir = path.left(pos); if (newDir != dir) conf.writeEntry("LastImageDir", newDir); } ui.leBackgroundFileName->setText( path ); for (auto* legend : m_legendList) legend->setBackgroundFileName(path); } void CartesianPlotLegendDock::fileNameChanged() { if (m_initializing) return; QString fileName = ui.leBackgroundFileName->text(); if (!fileName.isEmpty() && !QFile::exists(fileName)) ui.leBackgroundFileName->setStyleSheet("QLineEdit{background:red;}"); else ui.leBackgroundFileName->setStyleSheet(""); for (auto* legend : m_legendList) legend->setBackgroundFileName(fileName); } void CartesianPlotLegendDock::backgroundOpacityChanged(int value) { if (m_initializing) return; float opacity = (float)value/100.; for (auto* legend : m_legendList) legend->setBackgroundOpacity(opacity); } // "Border"-tab void CartesianPlotLegendDock::borderStyleChanged(int index) { if (m_initializing) return; auto penStyle = Qt::PenStyle(index); QPen pen; for (auto* legend : m_legendList) { pen = legend->borderPen(); pen.setStyle(penStyle); legend->setBorderPen(pen); } } void CartesianPlotLegendDock::borderColorChanged(const QColor& color) { if (m_initializing) return; QPen pen; for (auto* legend : m_legendList) { pen = legend->borderPen(); pen.setColor(color); legend->setBorderPen(pen); } m_initializing = true; GuiTools::updatePenStyles(ui.cbBorderStyle, color); m_initializing = false; } void CartesianPlotLegendDock::borderWidthChanged(double value) { if (m_initializing) return; QPen pen; for (auto* legend : m_legendList) { pen = legend->borderPen(); pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point) ); legend->setBorderPen(pen); } } void CartesianPlotLegendDock::borderCornerRadiusChanged(double value) { if (m_initializing) return; for (auto* legend : m_legendList) legend->setBorderCornerRadius(Worksheet::convertToSceneUnits(value, m_worksheetUnit)); } void CartesianPlotLegendDock::borderOpacityChanged(int value) { if (m_initializing) return; float opacity = (float)value/100.; for (auto* legend : m_legendList) legend->setBorderOpacity(opacity); } //Layout void CartesianPlotLegendDock::layoutTopMarginChanged(double margin) { if (m_initializing) return; for (auto* legend : m_legendList) legend->setLayoutTopMargin(Worksheet::convertToSceneUnits(margin, m_worksheetUnit)); } void CartesianPlotLegendDock::layoutBottomMarginChanged(double margin) { if (m_initializing) return; for (auto* legend : m_legendList) legend->setLayoutBottomMargin(Worksheet::convertToSceneUnits(margin, m_worksheetUnit)); } void CartesianPlotLegendDock::layoutLeftMarginChanged(double margin) { if (m_initializing) return; for (auto* legend : m_legendList) legend->setLayoutLeftMargin(Worksheet::convertToSceneUnits(margin, m_worksheetUnit)); } void CartesianPlotLegendDock::layoutRightMarginChanged(double margin) { if (m_initializing) return; for (auto* legend : m_legendList) legend->setLayoutRightMargin(Worksheet::convertToSceneUnits(margin, m_worksheetUnit)); } void CartesianPlotLegendDock::layoutHorizontalSpacingChanged(double spacing) { if (m_initializing) return; for (auto* legend : m_legendList) legend->setLayoutHorizontalSpacing(Worksheet::convertToSceneUnits(spacing, m_worksheetUnit)); } void CartesianPlotLegendDock::layoutVerticalSpacingChanged(double spacing) { if (m_initializing) return; for (auto* legend : m_legendList) legend->setLayoutVerticalSpacing(Worksheet::convertToSceneUnits(spacing, m_worksheetUnit)); } void CartesianPlotLegendDock::layoutColumnCountChanged(int count) { ui.lOrder->setVisible(count!=1); ui.cbOrder->setVisible(count!=1); if (m_initializing) return; for (auto* legend : m_legendList) legend->setLayoutColumnCount(count); } //************************************************************* //**** SLOTs for changes triggered in CartesianPlotLegend ***** //************************************************************* //General void CartesianPlotLegendDock::legendDescriptionChanged(const AbstractAspect* aspect) { if (m_legend != aspect) return; m_initializing = true; if (aspect->name() != ui.leName->text()) { ui.leName->setText(aspect->name()); } else if (aspect->comment() != ui.leComment->text()) { ui.leComment->setText(aspect->comment()); } m_initializing = false; } void CartesianPlotLegendDock::legendLabelFontChanged(QFont& font) { m_initializing = true; //we need to set the font size in points for KFontRequester QFont f(font); f.setPointSizeF( Worksheet::convertFromSceneUnits(f.pixelSize(), Worksheet::Unit::Point) ); ui.kfrLabelFont->setFont(f); m_initializing = false; } void CartesianPlotLegendDock::legendLabelColorChanged(QColor& color) { m_initializing = true; ui.kcbLabelColor->setColor(color); m_initializing = false; } void CartesianPlotLegendDock::legendLabelOrderChanged(bool b) { m_initializing = true; if (b) ui.cbOrder->setCurrentIndex(0); //column major else ui.cbOrder->setCurrentIndex(1); //row major m_initializing = false; } void CartesianPlotLegendDock::legendLineSymbolWidthChanged(float value) { m_initializing = true; ui.sbLineSymbolWidth->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void CartesianPlotLegendDock::legendPositionChanged(const CartesianPlotLegend::PositionWrapper& position) { m_initializing = true; ui.sbPositionX->setValue( Worksheet::convertFromSceneUnits(position.point.x(), m_worksheetUnit) ); ui.sbPositionY->setValue( Worksheet::convertFromSceneUnits(position.point.y(), m_worksheetUnit) ); ui.cbPositionX->setCurrentIndex( static_cast(position.horizontalPosition) ); ui.cbPositionY->setCurrentIndex( static_cast(position.verticalPosition) ); m_initializing = false; } void CartesianPlotLegendDock::legendRotationAngleChanged(qreal angle) { m_initializing = true; ui.sbRotation->setValue(angle); m_initializing = false; } void CartesianPlotLegendDock::legendVisibilityChanged(bool on) { m_initializing = true; ui.chkVisible->setChecked(on); m_initializing = false; } //Background void CartesianPlotLegendDock::legendBackgroundTypeChanged(PlotArea::BackgroundType type) { m_initializing = true; ui.cbBackgroundType->setCurrentIndex(static_cast(type)); m_initializing = false; } void CartesianPlotLegendDock::legendBackgroundColorStyleChanged(PlotArea::BackgroundColorStyle style) { m_initializing = true; ui.cbBackgroundColorStyle->setCurrentIndex(static_cast(style)); m_initializing = false; } void CartesianPlotLegendDock::legendBackgroundImageStyleChanged(PlotArea::BackgroundImageStyle style) { m_initializing = true; ui.cbBackgroundImageStyle->setCurrentIndex(static_cast(style)); m_initializing = false; } void CartesianPlotLegendDock::legendBackgroundBrushStyleChanged(Qt::BrushStyle style) { m_initializing = true; ui.cbBackgroundBrushStyle->setCurrentIndex(style); m_initializing = false; } void CartesianPlotLegendDock::legendBackgroundFirstColorChanged(QColor& color) { m_initializing = true; ui.kcbBackgroundFirstColor->setColor(color); m_initializing = false; } void CartesianPlotLegendDock::legendBackgroundSecondColorChanged(QColor& color) { m_initializing = true; ui.kcbBackgroundSecondColor->setColor(color); m_initializing = false; } void CartesianPlotLegendDock::legendBackgroundFileNameChanged(QString& filename) { m_initializing = true; ui.leBackgroundFileName->setText(filename); m_initializing = false; } void CartesianPlotLegendDock::legendBackgroundOpacityChanged(float opacity) { m_initializing = true; ui.sbBackgroundOpacity->setValue( qRound(opacity*100.0) ); m_initializing = false; } //Border void CartesianPlotLegendDock::legendBorderPenChanged(QPen& pen) { if (m_initializing) return; m_initializing = true; if (ui.cbBorderStyle->currentIndex() != pen.style()) ui.cbBorderStyle->setCurrentIndex(pen.style()); if (ui.kcbBorderColor->color() != pen.color()) ui.kcbBorderColor->setColor(pen.color()); if (ui.sbBorderWidth->value() != pen.widthF()) ui.sbBorderWidth->setValue(Worksheet::convertFromSceneUnits(pen.widthF(), Worksheet::Unit::Point)); m_initializing = false; } void CartesianPlotLegendDock::legendBorderCornerRadiusChanged(float value) { m_initializing = true; ui.sbBorderCornerRadius->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void CartesianPlotLegendDock::legendBorderOpacityChanged(float opacity) { m_initializing = true; ui.sbBorderOpacity->setValue( qRound(opacity*100.0) ); m_initializing = false; } //Layout void CartesianPlotLegendDock::legendLayoutTopMarginChanged(float value) { m_initializing = true; ui.sbLayoutTopMargin->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void CartesianPlotLegendDock::legendLayoutBottomMarginChanged(float value) { m_initializing = true; ui.sbLayoutBottomMargin->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void CartesianPlotLegendDock::legendLayoutLeftMarginChanged(float value) { m_initializing = true; ui.sbLayoutLeftMargin->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void CartesianPlotLegendDock::legendLayoutRightMarginChanged(float value) { m_initializing = true; ui.sbLayoutRightMargin->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void CartesianPlotLegendDock::legendLayoutVerticalSpacingChanged(float value) { m_initializing = true; ui.sbLayoutVerticalSpacing->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void CartesianPlotLegendDock::legendLayoutHorizontalSpacingChanged(float value) { m_initializing = true; ui.sbLayoutHorizontalSpacing->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void CartesianPlotLegendDock::legendLayoutColumnCountChanged(int value) { m_initializing = true; ui.sbLayoutColumnCount->setValue(value); m_initializing = false; } //************************************************************* //******************** SETTINGS ******************************* //************************************************************* void CartesianPlotLegendDock::load() { //General-tab //Format //we need to set the font size in points for KFontRequester QFont font = m_legend->labelFont(); font.setPointSizeF( qRound(Worksheet::convertFromSceneUnits(font.pixelSize(), Worksheet::Unit::Point)) ); ui.kfrLabelFont->setFont(font); ui.kcbLabelColor->setColor( m_legend->labelColor() ); bool columnMajor = m_legend->labelColumnMajor(); if (columnMajor) ui.cbOrder->setCurrentIndex(0); //column major else ui.cbOrder->setCurrentIndex(1); //row major ui.sbLineSymbolWidth->setValue( Worksheet::convertFromSceneUnits(m_legend->lineSymbolWidth(), m_worksheetUnit) ); //Geometry ui.cbPositionX->setCurrentIndex(static_cast(m_legend->position().horizontalPosition)); ui.sbPositionX->setValue( Worksheet::convertFromSceneUnits(m_legend->position().point.x(), m_worksheetUnit) ); ui.cbPositionY->setCurrentIndex(static_cast(m_legend->position().verticalPosition)); ui.sbPositionY->setValue( Worksheet::convertFromSceneUnits(m_legend->position().point.y(), m_worksheetUnit) ); ui.sbRotation->setValue(m_legend->rotationAngle()); ui.chkVisible->setChecked( m_legend->isVisible() ); //Background-tab ui.cbBackgroundType->setCurrentIndex( (int) m_legend->backgroundType() ); ui.cbBackgroundColorStyle->setCurrentIndex( (int) m_legend->backgroundColorStyle() ); ui.cbBackgroundImageStyle->setCurrentIndex( (int) m_legend->backgroundImageStyle() ); ui.cbBackgroundBrushStyle->setCurrentIndex( (int) m_legend->backgroundBrushStyle() ); ui.leBackgroundFileName->setText( m_legend->backgroundFileName() ); ui.kcbBackgroundFirstColor->setColor( m_legend->backgroundFirstColor() ); ui.kcbBackgroundSecondColor->setColor( m_legend->backgroundSecondColor() ); ui.sbBackgroundOpacity->setValue( qRound(m_legend->backgroundOpacity()*100.0) ); //highlight the text field for the background image red if an image is used and cannot be found if (!m_legend->backgroundFileName().isEmpty() && !QFile::exists(m_legend->backgroundFileName())) ui.leBackgroundFileName->setStyleSheet("QLineEdit{background:red;}"); else ui.leBackgroundFileName->setStyleSheet(""); //Border ui.kcbBorderColor->setColor( m_legend->borderPen().color() ); ui.cbBorderStyle->setCurrentIndex( (int) m_legend->borderPen().style() ); ui.sbBorderWidth->setValue( Worksheet::convertFromSceneUnits(m_legend->borderPen().widthF(), Worksheet::Unit::Point) ); ui.sbBorderCornerRadius->setValue( Worksheet::convertFromSceneUnits(m_legend->borderCornerRadius(), m_worksheetUnit) ); ui.sbBorderOpacity->setValue( qRound(m_legend->borderOpacity()*100.0) ); // Layout ui.sbLayoutTopMargin->setValue( Worksheet::convertFromSceneUnits(m_legend->layoutTopMargin(), m_worksheetUnit) ); ui.sbLayoutBottomMargin->setValue( Worksheet::convertFromSceneUnits(m_legend->layoutBottomMargin(), m_worksheetUnit) ); ui.sbLayoutLeftMargin->setValue( Worksheet::convertFromSceneUnits(m_legend->layoutLeftMargin(), m_worksheetUnit) ); ui.sbLayoutRightMargin->setValue( Worksheet::convertFromSceneUnits(m_legend->layoutRightMargin(), m_worksheetUnit) ); ui.sbLayoutHorizontalSpacing->setValue( Worksheet::convertFromSceneUnits(m_legend->layoutHorizontalSpacing(), m_worksheetUnit) ); ui.sbLayoutVerticalSpacing->setValue( Worksheet::convertFromSceneUnits(m_legend->layoutVerticalSpacing(), m_worksheetUnit) ); ui.sbLayoutColumnCount->setValue( m_legend->layoutColumnCount() ); m_initializing = true; GuiTools::updatePenStyles(ui.cbBorderStyle, ui.kcbBorderColor->color()); m_initializing = false; } void CartesianPlotLegendDock::loadConfigFromTemplate(KConfig& config) { //extract the name of the template from the file name QString name; int index = config.name().lastIndexOf(QLatin1String("/")); if (index != -1) name = config.name().right(config.name().size() - index - 1); else name = config.name(); int size = m_legendList.size(); if (size > 1) m_legend->beginMacro(i18n("%1 cartesian plot legends: template \"%2\" loaded", size, name)); else m_legend->beginMacro(i18n("%1: template \"%2\" loaded", m_legend->name(), name)); this->loadConfig(config); m_legend->endMacro(); } void CartesianPlotLegendDock::loadConfig(KConfig& config) { KConfigGroup group = config.group( "CartesianPlotLegend" ); //General-tab //Format //we need to set the font size in points for KFontRequester QFont font = m_legend->labelFont(); font.setPointSizeF( qRound(Worksheet::convertFromSceneUnits(font.pixelSize(), Worksheet::Unit::Point)) ); ui.kfrLabelFont->setFont( group.readEntry("LabelFont", font) ); ui.kcbLabelColor->setColor( group.readEntry("LabelColor", m_legend->labelColor()) ); bool columnMajor = group.readEntry("LabelColumMajor", m_legend->labelColumnMajor()); if (columnMajor) ui.cbOrder->setCurrentIndex(0); //column major else ui.cbOrder->setCurrentIndex(1); //row major ui.sbLineSymbolWidth->setValue(group.readEntry("LineSymbolWidth", Worksheet::convertFromSceneUnits(m_legend->lineSymbolWidth(), m_worksheetUnit)) ); // Geometry ui.cbPositionX->setCurrentIndex( group.readEntry("PositionX", (int) m_legend->position().horizontalPosition ) ); ui.sbPositionX->setValue( Worksheet::convertFromSceneUnits(group.readEntry("PositionXValue", m_legend->position().point.x()),m_worksheetUnit) ); ui.cbPositionY->setCurrentIndex( group.readEntry("PositionY", (int) m_legend->position().verticalPosition ) ); ui.sbPositionY->setValue( Worksheet::convertFromSceneUnits(group.readEntry("PositionYValue", m_legend->position().point.y()),m_worksheetUnit) ); ui.sbRotation->setValue( group.readEntry("Rotation", (int) m_legend->rotationAngle() ) ); ui.chkVisible->setChecked( group.readEntry("Visible", m_legend->isVisible()) ); //Background-tab ui.cbBackgroundType->setCurrentIndex( group.readEntry("BackgroundType", (int) m_legend->backgroundType()) ); ui.cbBackgroundColorStyle->setCurrentIndex( group.readEntry("BackgroundColorStyle", (int) m_legend->backgroundColorStyle()) ); ui.cbBackgroundImageStyle->setCurrentIndex( group.readEntry("BackgroundImageStyle", (int) m_legend->backgroundImageStyle()) ); ui.cbBackgroundBrushStyle->setCurrentIndex( group.readEntry("BackgroundBrushStyle", (int) m_legend->backgroundBrushStyle()) ); ui.leBackgroundFileName->setText( group.readEntry("BackgroundFileName", m_legend->backgroundFileName()) ); ui.kcbBackgroundFirstColor->setColor( group.readEntry("BackgroundFirstColor", m_legend->backgroundFirstColor()) ); ui.kcbBackgroundSecondColor->setColor( group.readEntry("BackgroundSecondColor", m_legend->backgroundSecondColor()) ); ui.sbBackgroundOpacity->setValue( qRound(group.readEntry("BackgroundOpacity", m_legend->backgroundOpacity())*100.0) ); //Border ui.kcbBorderColor->setColor( group.readEntry("BorderColor", m_legend->borderPen().color()) ); ui.cbBorderStyle->setCurrentIndex( group.readEntry("BorderStyle", (int) m_legend->borderPen().style()) ); ui.sbBorderWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("BorderWidth", m_legend->borderPen().widthF()), Worksheet::Unit::Point) ); ui.sbBorderCornerRadius->setValue( Worksheet::convertFromSceneUnits(group.readEntry("BorderCornerRadius", m_legend->borderCornerRadius()), m_worksheetUnit) ); ui.sbBorderOpacity->setValue( qRound(group.readEntry("BorderOpacity", m_legend->borderOpacity())*100.0) ); // Layout ui.sbLayoutTopMargin->setValue(group.readEntry("LayoutTopMargin", Worksheet::convertFromSceneUnits(m_legend->layoutTopMargin(), m_worksheetUnit)) ); ui.sbLayoutBottomMargin->setValue(group.readEntry("LayoutBottomMargin", Worksheet::convertFromSceneUnits(m_legend->layoutBottomMargin(), m_worksheetUnit)) ); ui.sbLayoutLeftMargin->setValue(group.readEntry("LayoutLeftMargin", Worksheet::convertFromSceneUnits(m_legend->layoutLeftMargin(), m_worksheetUnit)) ); ui.sbLayoutRightMargin->setValue(group.readEntry("LayoutRightMargin", Worksheet::convertFromSceneUnits(m_legend->layoutRightMargin(), m_worksheetUnit)) ); ui.sbLayoutHorizontalSpacing->setValue(group.readEntry("LayoutHorizontalSpacing", Worksheet::convertFromSceneUnits(m_legend->layoutHorizontalSpacing(), m_worksheetUnit)) ); ui.sbLayoutVerticalSpacing->setValue(group.readEntry("LayoutVerticalSpacing", Worksheet::convertFromSceneUnits(m_legend->layoutVerticalSpacing(), m_worksheetUnit)) ); ui.sbLayoutColumnCount->setValue(group.readEntry("LayoutColumnCount", m_legend->layoutColumnCount())); //Title group = config.group("PlotLegend"); labelWidget->loadConfig(group); m_initializing = true; GuiTools::updatePenStyles(ui.cbBorderStyle, ui.kcbBorderColor->color()); m_initializing = false; } void CartesianPlotLegendDock::saveConfigAsTemplate(KConfig& config) { KConfigGroup group = config.group( "CartesianPlotLegend" ); //General-tab //Format QFont font = m_legend->labelFont(); font.setPointSizeF( Worksheet::convertFromSceneUnits(font.pointSizeF(), Worksheet::Unit::Point) ); group.writeEntry("LabelFont", font); group.writeEntry("LabelColor", ui.kcbLabelColor->color()); group.writeEntry("LabelColumMajorOrder", ui.cbOrder->currentIndex() == 0);// true for "column major", false for "row major" group.writeEntry("LineSymbolWidth", Worksheet::convertToSceneUnits(ui.sbLineSymbolWidth->value(), m_worksheetUnit)); //Geometry group.writeEntry("PositionX", ui.cbPositionX->currentIndex()); group.writeEntry("PositionXValue", Worksheet::convertToSceneUnits(ui.sbPositionX->value(),m_worksheetUnit) ); group.writeEntry("PositionY", ui.cbPositionY->currentIndex()); group.writeEntry("PositionYValue", Worksheet::convertToSceneUnits(ui.sbPositionY->value(),m_worksheetUnit) ); group.writeEntry("Rotation", ui.sbRotation->value()); group.writeEntry("Visible", ui.chkVisible->isChecked()); //Background group.writeEntry("BackgroundType", ui.cbBackgroundType->currentIndex()); group.writeEntry("BackgroundColorStyle", ui.cbBackgroundColorStyle->currentIndex()); group.writeEntry("BackgroundImageStyle", ui.cbBackgroundImageStyle->currentIndex()); group.writeEntry("BackgroundBrushStyle", ui.cbBackgroundBrushStyle->currentIndex()); group.writeEntry("BackgroundFileName", ui.leBackgroundFileName->text()); group.writeEntry("BackgroundFirstColor", ui.kcbBackgroundFirstColor->color()); group.writeEntry("BackgroundSecondColor", ui.kcbBackgroundSecondColor->color()); group.writeEntry("BackgroundOpacity", ui.sbBackgroundOpacity->value()/100.0); //Border group.writeEntry("BorderStyle", ui.cbBorderStyle->currentIndex()); group.writeEntry("BorderColor", ui.kcbBorderColor->color()); group.writeEntry("BorderWidth", Worksheet::convertToSceneUnits(ui.sbBorderWidth->value(), Worksheet::Unit::Point)); group.writeEntry("BorderCornerRadius", Worksheet::convertToSceneUnits(ui.sbBorderCornerRadius->value(), m_worksheetUnit)); group.writeEntry("BorderOpacity", ui.sbBorderOpacity->value()/100.0); //Layout group.writeEntry("LayoutTopMargin",Worksheet::convertToSceneUnits(ui.sbLayoutTopMargin->value(), m_worksheetUnit)); group.writeEntry("LayoutBottomMargin",Worksheet::convertToSceneUnits(ui.sbLayoutBottomMargin->value(), m_worksheetUnit)); group.writeEntry("LayoutLeftMargin",Worksheet::convertToSceneUnits(ui.sbLayoutLeftMargin->value(), m_worksheetUnit)); group.writeEntry("LayoutRightMargin",Worksheet::convertToSceneUnits(ui.sbLayoutRightMargin->value(), m_worksheetUnit)); group.writeEntry("LayoutVerticalSpacing",Worksheet::convertToSceneUnits(ui.sbLayoutVerticalSpacing->value(), m_worksheetUnit)); group.writeEntry("LayoutHorizontalSpacing",Worksheet::convertToSceneUnits(ui.sbLayoutHorizontalSpacing->value(), m_worksheetUnit)); group.writeEntry("LayoutColumnCount", ui.sbLayoutColumnCount->value()); //Title group = config.group("PlotLegend"); labelWidget->saveConfig(group); config.sync(); } diff --git a/src/kdefrontend/dockwidgets/ImageDock.cpp b/src/kdefrontend/dockwidgets/ImageDock.cpp index 7821cf98d..06d5fd30a 100644 --- a/src/kdefrontend/dockwidgets/ImageDock.cpp +++ b/src/kdefrontend/dockwidgets/ImageDock.cpp @@ -1,586 +1,586 @@ /*************************************************************************** File : ImageDock.cpp Project : LabPlot Description : widget for image properties -------------------------------------------------------------------- Copyright : (C) 2019-2020 by 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 * * * ***************************************************************************/ #include "ImageDock.h" #include "backend/worksheet/Image.h" #include "backend/worksheet/Worksheet.h" #include "kdefrontend/GuiTools.h" #include "kdefrontend/ThemeHandler.h" #include "kdefrontend/TemplateHandler.h" #include #include #include #include #include #include #include #include #include /*! \class ImageDock \brief Provides a widget for editing the properties of the worksheets image element. \ingroup kdefrontend */ ImageDock::ImageDock(QWidget* parent) : BaseDock(parent) { ui.setupUi(this); m_leName = ui.leName; m_leComment = ui.leComment; ui.bOpen->setIcon( QIcon::fromTheme("document-open") ); ui.leFileName->setCompleter(new QCompleter(new QDirModel, this)); // ui.cbSize->addItem(i18n("Original")); // ui.cbSize->addItem(i18n("Custom")); //Positioning and alignment ui.cbPositionX->addItem(i18n("Left")); ui.cbPositionX->addItem(i18n("Center")); ui.cbPositionX->addItem(i18n("Right")); ui.cbPositionX->addItem(i18n("Custom")); ui.cbPositionY->addItem(i18n("Top")); ui.cbPositionY->addItem(i18n("Center")); ui.cbPositionY->addItem(i18n("Bottom")); ui.cbPositionY->addItem(i18n("Custom")); ui.cbHorizontalAlignment->addItem(i18n("Left")); ui.cbHorizontalAlignment->addItem(i18n("Center")); ui.cbHorizontalAlignment->addItem(i18n("Right")); ui.cbVerticalAlignment->addItem(i18n("Top")); ui.cbVerticalAlignment->addItem(i18n("Center")); ui.cbVerticalAlignment->addItem(i18n("Bottom")); QString suffix; if (m_units == BaseDock::MetricUnits) - suffix = QLatin1String("cm"); + suffix = QLatin1String(" cm"); else - suffix = QLatin1String("in"); + suffix = QLatin1String(" in"); ui.sbWidth->setSuffix(suffix); ui.sbHeight->setSuffix(suffix); ui.sbPositionX->setSuffix(suffix); ui.sbPositionY->setSuffix(suffix); //border ui.cbBorderStyle->addItem(i18n("No line")); ui.cbBorderStyle->addItem(i18n("Solid line")); ui.cbBorderStyle->addItem(i18n("Dash line")); ui.cbBorderStyle->addItem(i18n("Dot line")); ui.cbBorderStyle->addItem(i18n("Dash dot line")); ui.cbBorderStyle->addItem(i18n("Dash dot dot line")); //SLOTs //General connect(ui.leName, &QLineEdit::textChanged, this, &ImageDock::nameChanged); connect(ui.leComment, &QLineEdit::textChanged, this, &ImageDock::commentChanged); connect(ui.bOpen, &QPushButton::clicked, this, &ImageDock::selectFile); connect(ui.leFileName, &QLineEdit::returnPressed, this, &ImageDock::fileNameChanged); connect(ui.leFileName, &QLineEdit::textChanged, this, &ImageDock::fileNameChanged); connect(ui.sbOpacity, static_cast(&QSpinBox::valueChanged), this, &ImageDock::opacityChanged); //Size connect(ui.sbWidth, static_cast(&QDoubleSpinBox::valueChanged), this, &ImageDock::widthChanged); connect(ui.sbHeight, static_cast(&QDoubleSpinBox::valueChanged), this, &ImageDock::heightChanged); connect(ui.chbKeepRatio, &QCheckBox::clicked, this, &ImageDock::keepRatioChanged); //Position connect(ui.cbPositionX, static_cast(&QComboBox::currentIndexChanged), this, &ImageDock::positionXChanged); connect(ui.cbPositionY, static_cast(&QComboBox::currentIndexChanged), this, &ImageDock::positionYChanged); connect(ui.sbPositionX, static_cast(&QDoubleSpinBox::valueChanged), this, &ImageDock::customPositionXChanged); connect(ui.sbPositionY, static_cast(&QDoubleSpinBox::valueChanged), this, &ImageDock::customPositionYChanged); connect(ui.cbHorizontalAlignment, static_cast(&QComboBox::currentIndexChanged), this, &ImageDock::horizontalAlignmentChanged); connect(ui.cbVerticalAlignment, static_cast(&QComboBox::currentIndexChanged), this, &ImageDock::verticalAlignmentChanged); connect(ui.sbRotation, static_cast(&QSpinBox::valueChanged), this, &ImageDock::rotationChanged); connect(ui.chbVisible, &QCheckBox::clicked, this, &ImageDock::visibilityChanged); //Border connect(ui.cbBorderStyle, static_cast(&QComboBox::currentIndexChanged), this, &ImageDock::borderStyleChanged); connect(ui.kcbBorderColor, &KColorButton::changed, this, &ImageDock::borderColorChanged); connect(ui.sbBorderWidth, static_cast(&QDoubleSpinBox::valueChanged), this, &ImageDock::borderWidthChanged); connect(ui.sbBorderOpacity, static_cast(&QSpinBox::valueChanged), this, &ImageDock::borderOpacityChanged); } void ImageDock::setImages(QList list) { Lock lock(m_initializing); m_imageList = list; m_image = list.first(); m_aspect = list.first(); //if there are more then one image in the list, disable the name and comment field in the tab "general" if (list.size() == 1) { ui.lName->setEnabled(true); ui.leName->setEnabled(true); ui.lComment->setEnabled(true); ui.leComment->setEnabled(true); ui.leName->setText(m_image->name()); ui.leComment->setText(m_image->comment()); } else { ui.lName->setEnabled(false); ui.leName->setEnabled(false); ui.lComment->setEnabled(false); ui.leComment->setEnabled(false); ui.leName->setText(QString()); ui.leComment->setText(QString()); } ui.leName->setStyleSheet(""); ui.leName->setToolTip(""); //show the properties of the first image this->load(); //init connections //General connect(m_image, &Image::fileNameChanged, this, &ImageDock::imageFileNameChanged); connect(m_image, &Image::opacityChanged, this, &ImageDock::imageOpacityChanged); connect(m_image, &Image::visibleChanged, this, &ImageDock::imageVisibleChanged); //Size connect(m_image, &Image::widthChanged, this, &ImageDock::imageWidthChanged); connect(m_image, &Image::heightChanged, this, &ImageDock::imageHeightChanged); connect(m_image, &Image::keepRatioChanged, this, &ImageDock::imageKeepRatioChanged); //Position connect(m_image, &Image::positionChanged, this, &ImageDock::imagePositionChanged); connect(m_image, &Image::horizontalAlignmentChanged, this, &ImageDock::imageHorizontalAlignmentChanged); connect(m_image, &Image::verticalAlignmentChanged, this, &ImageDock::imageVerticalAlignmentChanged); connect(m_image, &Image::rotationAngleChanged, this, &ImageDock::imageRotationAngleChanged); //Border connect(m_image, &Image::borderPenChanged, this, &ImageDock::imageBorderPenChanged); connect(m_image, &Image::borderOpacityChanged, this, &ImageDock::imageBorderOpacityChanged); } void ImageDock::updateUnits() { const KConfigGroup group = KSharedConfig::openConfig()->group(QLatin1String("Settings_General")); BaseDock::Units units = (BaseDock::Units)group.readEntry("Units", (int)MetricUnits); if (units == m_units) return; m_units = units; Lock lock(m_initializing); QString suffix; if (m_units == BaseDock::MetricUnits) { //convert from imperial to metric m_worksheetUnit = Worksheet::Unit::Centimeter; - suffix = QLatin1String("cm"); + suffix = QLatin1String(" cm"); ui.sbWidth->setValue(ui.sbWidth->value()*2.54); ui.sbHeight->setValue(ui.sbHeight->value()*2.54); ui.sbPositionX->setValue(ui.sbPositionX->value()*2.54); ui.sbPositionY->setValue(ui.sbPositionY->value()*2.54); } else { //convert from metric to imperial m_worksheetUnit = Worksheet::Unit::Inch; - suffix = QLatin1String("in"); + suffix = QLatin1String(" in"); ui.sbWidth->setValue(ui.sbWidth->value()/2.54); ui.sbHeight->setValue(ui.sbHeight->value()/2.54); ui.sbPositionX->setValue(ui.sbPositionX->value()/2.54); ui.sbPositionY->setValue(ui.sbPositionY->value()/2.54); } ui.sbWidth->setSuffix(suffix); ui.sbHeight->setSuffix(suffix); ui.sbPositionX->setSuffix(suffix); ui.sbPositionY->setSuffix(suffix); } //************************************************************* //******** SLOTs for changes triggered in ImageDock *********** //************************************************************* /*! opens a file dialog and lets the user select the image file. */ void ImageDock::selectFile() { KConfigGroup conf(KSharedConfig::openConfig(), "ImageDock"); QString dir = conf.readEntry("LastImageDir", ""); QString formats; for (const QByteArray& format : QImageReader::supportedImageFormats()) { QString f = "*." + QString(format.constData()); if (f == QLatin1String("*.svg")) continue; formats.isEmpty() ? formats += f : formats += ' ' + f; } QString path = QFileDialog::getOpenFileName(this, i18n("Select the image file"), dir, i18n("Images (%1)", formats)); if (path.isEmpty()) return; //cancel was clicked in the file-dialog int pos = path.lastIndexOf(QLatin1String("/")); if (pos != -1) { QString newDir = path.left(pos); if (newDir != dir) conf.writeEntry("LastImageDir", newDir); } ui.leFileName->setText(path); } void ImageDock::fileNameChanged() { if (m_initializing) return; QString fileName = ui.leFileName->text(); if (!fileName.isEmpty() && !QFile::exists(fileName)) ui.leFileName->setStyleSheet("QLineEdit{background:red;}"); else ui.leFileName->setStyleSheet(QString()); for (auto* image : m_imageList) image->setFileName(fileName); } void ImageDock::opacityChanged(int value) { if (m_initializing) return; float opacity = (float)value/100; for (auto* image : m_imageList) image->setOpacity(opacity); } //Size void ImageDock::sizeChanged(int index) { Q_UNUSED(index); } void ImageDock::widthChanged(double value) { if (m_initializing) return; int width = Worksheet::convertToSceneUnits(value, m_worksheetUnit); for (auto* image : m_imageList) image->setWidth(width); } void ImageDock::heightChanged(double value) { if (m_initializing) return; int height = Worksheet::convertToSceneUnits(value, m_worksheetUnit); for (auto* image : m_imageList) image->setHeight(height); } void ImageDock::keepRatioChanged(int state) { if (m_initializing) return; for (auto* image : m_imageList) image->setKeepRatio(state); } //Position /*! called when label's current horizontal position relative to its parent (left, center, right, custom ) is changed. */ void ImageDock::positionXChanged(int index) { //Enable/disable the spinbox for the x- oordinates if the "custom position"-item is selected/deselected if (index == ui.cbPositionX->count()-1 ) ui.sbPositionX->setEnabled(true); else ui.sbPositionX->setEnabled(false); if (m_initializing) return; WorksheetElement::PositionWrapper position = m_image->position(); position.horizontalPosition = WorksheetElement::HorizontalPosition(index); for (auto* image : m_imageList) image->setPosition(position); } /*! called when label's current horizontal position relative to its parent (top, center, bottom, custom ) is changed. */ void ImageDock::positionYChanged(int index) { //Enable/disable the spinbox for the y-coordinates if the "custom position"-item is selected/deselected if (index == ui.cbPositionY->count()-1 ) ui.sbPositionY->setEnabled(true); else ui.sbPositionY->setEnabled(false); if (m_initializing) return; WorksheetElement::PositionWrapper position = m_image->position(); position.verticalPosition = WorksheetElement::VerticalPosition(index); for (auto* image : m_imageList) image->setPosition(position); } void ImageDock::customPositionXChanged(double value) { if (m_initializing) return; WorksheetElement::PositionWrapper position = m_image->position(); position.point.setX(Worksheet::convertToSceneUnits(value, m_worksheetUnit)); for (auto* image : m_imageList) image->setPosition(position); } void ImageDock::customPositionYChanged(double value) { if (m_initializing) return; WorksheetElement::PositionWrapper position = m_image->position(); position.point.setY(Worksheet::convertToSceneUnits(value, m_worksheetUnit)); for (auto* image : m_imageList) image->setPosition(position); } void ImageDock::horizontalAlignmentChanged(int index) { if (m_initializing) return; for (auto* image : m_imageList) image->setHorizontalAlignment(WorksheetElement::HorizontalAlignment(index)); } void ImageDock::verticalAlignmentChanged(int index) { if (m_initializing) return; for (auto* image : m_imageList) image->setVerticalAlignment(WorksheetElement::VerticalAlignment(index)); } void ImageDock::rotationChanged(int value) { if (m_initializing) return; for (auto* image : m_imageList) image->setRotationAngle(value); } void ImageDock::visibilityChanged(bool state) { if (m_initializing) return; for (auto* image : m_imageList) image->setVisible(state); } //border void ImageDock::borderStyleChanged(int index) { if (m_initializing) return; auto penStyle = Qt::PenStyle(index); QPen pen; for (auto* image : m_imageList) { pen = image->borderPen(); pen.setStyle(penStyle); image->setBorderPen(pen); } } void ImageDock::borderColorChanged(const QColor& color) { if (m_initializing) return; QPen pen; for (auto* image : m_imageList) { pen = image->borderPen(); pen.setColor(color); image->setBorderPen(pen); } m_initializing = true; GuiTools::updatePenStyles(ui.cbBorderStyle, color); m_initializing = false; } void ImageDock::borderWidthChanged(double value) { if (m_initializing) return; QPen pen; for (auto* image : m_imageList) { pen = image->borderPen(); pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point) ); image->setBorderPen(pen); } } void ImageDock::borderOpacityChanged(int value) { if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* image : m_imageList) image->setBorderOpacity(opacity); } //************************************************************* //********** SLOTs for changes triggered in Image ************* //************************************************************* void ImageDock::imageDescriptionChanged(const AbstractAspect* aspect) { if (m_image != aspect) return; m_initializing = true; if (aspect->name() != ui.leName->text()) ui.leName->setText(aspect->name()); else if (aspect->comment() != ui.leComment->text()) ui.leComment->setText(aspect->comment()); m_initializing = false; } void ImageDock::imageFileNameChanged(const QString& name) { m_initializing = true; ui.leFileName->setText(name); m_initializing = false; } void ImageDock::imageOpacityChanged(float opacity) { m_initializing = true; ui.sbOpacity->setValue( qRound(opacity*100.0) ); m_initializing = false; } //Size void ImageDock::imageWidthChanged(int width) { m_initializing = true; ui.sbWidth->setValue( Worksheet::convertFromSceneUnits(width, m_worksheetUnit) ); m_initializing = false; } void ImageDock::imageHeightChanged(int height) { m_initializing = true; ui.sbHeight->setValue( Worksheet::convertFromSceneUnits(height, m_worksheetUnit) ); m_initializing = false; } void ImageDock::imageKeepRatioChanged(bool keep) { m_initializing = true; ui.chbKeepRatio->setChecked(keep); m_initializing = false; } //Position void ImageDock::imagePositionChanged(const WorksheetElement::PositionWrapper& position) { m_initializing = true; ui.sbPositionX->setValue( Worksheet::convertFromSceneUnits(position.point.x(), m_worksheetUnit) ); ui.sbPositionY->setValue( Worksheet::convertFromSceneUnits(position.point.y(), m_worksheetUnit) ); ui.cbPositionX->setCurrentIndex( static_cast(position.horizontalPosition) ); ui.cbPositionY->setCurrentIndex( static_cast(position.verticalPosition) ); m_initializing = false; } void ImageDock::imageHorizontalAlignmentChanged(WorksheetElement::HorizontalAlignment index) { m_initializing = true; ui.cbHorizontalAlignment->setCurrentIndex(static_cast(index)); m_initializing = false; } void ImageDock::imageVerticalAlignmentChanged(WorksheetElement::VerticalAlignment index) { m_initializing = true; ui.cbVerticalAlignment->setCurrentIndex(static_cast(index)); m_initializing = false; } void ImageDock::imageRotationAngleChanged(qreal angle) { m_initializing = true; ui.sbRotation->setValue(angle); m_initializing = false; } void ImageDock::imageVisibleChanged(bool on) { m_initializing = true; ui.chbVisible->setChecked(on); m_initializing = false; } //Border void ImageDock::imageBorderPenChanged(const QPen& pen) { m_initializing = true; if (ui.cbBorderStyle->currentIndex() != pen.style()) ui.cbBorderStyle->setCurrentIndex(pen.style()); if (ui.kcbBorderColor->color() != pen.color()) ui.kcbBorderColor->setColor(pen.color()); if (ui.sbBorderWidth->value() != pen.widthF()) ui.sbBorderWidth->setValue(Worksheet::convertFromSceneUnits(pen.widthF(), Worksheet::Unit::Point)); m_initializing = false; } void ImageDock::imageBorderOpacityChanged(float value) { m_initializing = true; float v = (float)value*100.; ui.sbBorderOpacity->setValue(v); m_initializing = false; } //************************************************************* //******************** SETTINGS ******************************* //************************************************************* void ImageDock::load() { if (!m_image) return; m_initializing = true; ui.leFileName->setText(m_image->fileName()); ui.chbVisible->setChecked(m_image->isVisible()); //Size ui.sbWidth->setValue( Worksheet::convertFromSceneUnits(m_image->width(), m_worksheetUnit) ); ui.sbHeight->setValue( Worksheet::convertFromSceneUnits(m_image->height(), m_worksheetUnit) ); ui.chbKeepRatio->setChecked(m_image->keepRatio()); //Position ui.cbPositionX->setCurrentIndex( (int) m_image->position().horizontalPosition ); positionXChanged(ui.cbPositionX->currentIndex()); ui.sbPositionX->setValue( Worksheet::convertFromSceneUnits(m_image->position().point.x(), m_worksheetUnit) ); ui.cbPositionY->setCurrentIndex( (int) m_image->position().verticalPosition ); positionYChanged(ui.cbPositionY->currentIndex()); ui.sbPositionY->setValue( Worksheet::convertFromSceneUnits(m_image->position().point.y(), m_worksheetUnit) ); ui.cbHorizontalAlignment->setCurrentIndex( (int) m_image->horizontalAlignment() ); ui.cbVerticalAlignment->setCurrentIndex( (int) m_image->verticalAlignment() ); ui.sbRotation->setValue( m_image->rotationAngle() ); //Border ui.kcbBorderColor->setColor( m_image->borderPen().color() ); ui.cbBorderStyle->setCurrentIndex( (int) m_image->borderPen().style() ); ui.sbBorderWidth->setValue( Worksheet::convertFromSceneUnits(m_image->borderPen().widthF(), Worksheet::Unit::Point) ); ui.sbBorderOpacity->setValue( round(m_image->borderOpacity()*100) ); GuiTools::updatePenStyles(ui.cbBorderStyle, ui.kcbBorderColor->color()); m_initializing = false; } diff --git a/src/kdefrontend/dockwidgets/WorksheetDock.cpp b/src/kdefrontend/dockwidgets/WorksheetDock.cpp index 20d06cf11..c7100c940 100644 --- a/src/kdefrontend/dockwidgets/WorksheetDock.cpp +++ b/src/kdefrontend/dockwidgets/WorksheetDock.cpp @@ -1,1030 +1,1030 @@ /*************************************************************************** File : WorksheetDock.cpp Project : LabPlot Description : widget for worksheet properties -------------------------------------------------------------------- Copyright : (C) 2010-2016 by Alexander Semke (alexander.semke@web.de) Copyright : (C) 2012-2013 by Stefan Gerlach (stefan.gerlach@uni-konstanz.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 * * * ***************************************************************************/ #include "WorksheetDock.h" #include "kdefrontend/GuiTools.h" #include "kdefrontend/ThemeHandler.h" #include "kdefrontend/TemplateHandler.h" #include #include #include #include #include #include #include #include #include /*! \class WorksheetDock \brief Provides a widget for editing the properties of the worksheets currently selected in the project explorer. \ingroup kdefrontend */ WorksheetDock::WorksheetDock(QWidget *parent): BaseDock(parent) { ui.setupUi(this); m_leName = ui.leName; m_leComment = ui.leComment; //Background-tab ui.cbBackgroundColorStyle->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); ui.bOpen->setIcon( QIcon::fromTheme("document-open") ); ui.leBackgroundFileName->setCompleter(new QCompleter(new QDirModel, this)); //Layout-tab ui.chScaleContent->setToolTip(i18n("If checked, rescale the content of the worksheet on size changes. Otherwise resize the canvas only.")); ui.cbLayout->addItem(QIcon::fromTheme("labplot-editbreaklayout"), i18n("No Layout")); ui.cbLayout->addItem(QIcon::fromTheme("labplot-editvlayout"), i18n("Vertical Layout")); ui.cbLayout->addItem(QIcon::fromTheme("labplot-edithlayout"), i18n("Horizontal Layout")); ui.cbLayout->addItem(QIcon::fromTheme("labplot-editgrid"), i18n("Grid Layout")); //adjust layouts in the tabs for (int i = 0; i < ui.tabWidget->count(); ++i) { auto* layout = dynamic_cast(ui.tabWidget->widget(i)->layout()); if (!layout) continue; layout->setContentsMargins(2, 2, 2, 2); layout->setHorizontalSpacing(2); layout->setVerticalSpacing(2); } //SLOTs //General connect(ui.leName, &QLineEdit::textChanged, this, &WorksheetDock::nameChanged); connect(ui.leComment, &QLineEdit::textChanged, this, &WorksheetDock::commentChanged); connect(ui.cbSize, static_cast(&QComboBox::currentIndexChanged), this, static_cast(&WorksheetDock::sizeChanged)); connect(ui.sbWidth, static_cast(&QDoubleSpinBox::valueChanged), this, static_cast(&WorksheetDock::sizeChanged)); connect(ui.sbHeight, static_cast(&QDoubleSpinBox::valueChanged), this, static_cast(&WorksheetDock::sizeChanged)); connect(ui.cbOrientation, static_cast(&QComboBox::currentIndexChanged), this, &WorksheetDock::orientationChanged); //Background connect(ui.cbBackgroundType, static_cast(&QComboBox::currentIndexChanged), this, &WorksheetDock::backgroundTypeChanged); connect(ui.cbBackgroundColorStyle, static_cast(&QComboBox::currentIndexChanged), this, &WorksheetDock::backgroundColorStyleChanged); connect(ui.cbBackgroundImageStyle, static_cast(&QComboBox::currentIndexChanged), this, &WorksheetDock::backgroundImageStyleChanged); connect(ui.cbBackgroundBrushStyle, static_cast(&QComboBox::currentIndexChanged), this, &WorksheetDock::backgroundBrushStyleChanged); connect(ui.bOpen, &QPushButton::clicked, this, &WorksheetDock::selectFile); connect(ui.leBackgroundFileName, &QLineEdit::returnPressed, this, &WorksheetDock::fileNameChanged); connect(ui.leBackgroundFileName, &QLineEdit::textChanged, this, &WorksheetDock::fileNameChanged); connect(ui.kcbBackgroundFirstColor, &KColorButton::changed, this, &WorksheetDock::backgroundFirstColorChanged); connect(ui.kcbBackgroundSecondColor, &KColorButton::changed, this, &WorksheetDock::backgroundSecondColorChanged); connect(ui.sbBackgroundOpacity, static_cast(&QSpinBox::valueChanged), this, &WorksheetDock::backgroundOpacityChanged); //Layout connect(ui.cbLayout, static_cast(&QComboBox::currentIndexChanged), this, &WorksheetDock::layoutChanged); connect( ui.chScaleContent, &QCheckBox::clicked, this, &WorksheetDock::scaleContentChanged); connect( ui.sbLayoutTopMargin, static_cast(&QDoubleSpinBox::valueChanged), this, &WorksheetDock::layoutTopMarginChanged); connect( ui.sbLayoutBottomMargin, static_cast(&QDoubleSpinBox::valueChanged), this, &WorksheetDock::layoutBottomMarginChanged); connect( ui.sbLayoutLeftMargin, static_cast(&QDoubleSpinBox::valueChanged), this, &WorksheetDock::layoutLeftMarginChanged); connect( ui.sbLayoutRightMargin, static_cast(&QDoubleSpinBox::valueChanged), this, &WorksheetDock::layoutRightMarginChanged); connect( ui.sbLayoutHorizontalSpacing, static_cast(&QDoubleSpinBox::valueChanged), this, &WorksheetDock::layoutHorizontalSpacingChanged); connect( ui.sbLayoutVerticalSpacing, static_cast(&QDoubleSpinBox::valueChanged), this, &WorksheetDock::layoutVerticalSpacingChanged); connect( ui.sbLayoutRowCount, static_cast(&QSpinBox::valueChanged), this, &WorksheetDock::layoutRowCountChanged); connect( ui.sbLayoutColumnCount, static_cast(&QSpinBox::valueChanged), this, &WorksheetDock::layoutColumnCountChanged); //theme and template handlers auto* frame = new QFrame(this); auto* layout = new QHBoxLayout(frame); layout->setContentsMargins(0, 11, 0, 11); m_themeHandler = new ThemeHandler(this); layout->addWidget(m_themeHandler); connect(m_themeHandler, &ThemeHandler::loadThemeRequested, this, &WorksheetDock::loadTheme); connect(m_themeHandler, &ThemeHandler::info, this, &WorksheetDock::info); auto* templateHandler = new TemplateHandler(this, TemplateHandler::Worksheet); layout->addWidget(templateHandler); connect(templateHandler, &TemplateHandler::loadConfigRequested, this, &WorksheetDock::loadConfigFromTemplate); connect(templateHandler, &TemplateHandler::saveConfigRequested, this, &WorksheetDock::saveConfigAsTemplate); connect(templateHandler, &TemplateHandler::info, this, &WorksheetDock::info); ui.verticalLayout->addWidget(frame); this->retranslateUi(); } void WorksheetDock::setWorksheets(QList list) { m_initializing = true; m_worksheetList = list; m_worksheet = list.first(); m_aspect = list.first(); //if there are more then one worksheet in the list, disable the name and comment field in the tab "general" if (list.size() == 1) { ui.lName->setEnabled(true); ui.leName->setEnabled(true); ui.lComment->setEnabled(true); ui.leComment->setEnabled(true); ui.leName->setText(m_worksheet->name()); ui.leComment->setText(m_worksheet->comment()); } else { ui.lName->setEnabled(false); ui.leName->setEnabled(false); ui.lComment->setEnabled(false); ui.leComment->setEnabled(false); ui.leName->setText(QString()); ui.leComment->setText(QString()); } ui.leName->setStyleSheet(""); ui.leName->setToolTip(""); //show the properties of the first worksheet this->load(); this->worksheetLayoutChanged(m_worksheet->layout()); m_themeHandler->setCurrentTheme(m_worksheet->theme()); connect(m_worksheet, &Worksheet::aspectDescriptionChanged, this, &WorksheetDock::worksheetDescriptionChanged); connect(m_worksheet, &Worksheet::pageRectChanged, this, &WorksheetDock::worksheetPageRectChanged); connect(m_worksheet, &Worksheet::scaleContentChanged, this, &WorksheetDock::worksheetScaleContentChanged); connect(m_worksheet, &Worksheet::backgroundTypeChanged, this, &WorksheetDock::worksheetBackgroundTypeChanged); connect(m_worksheet, &Worksheet::backgroundColorStyleChanged, this, &WorksheetDock::worksheetBackgroundColorStyleChanged); connect(m_worksheet, &Worksheet::backgroundImageStyleChanged, this, &WorksheetDock::worksheetBackgroundImageStyleChanged); connect(m_worksheet, &Worksheet::backgroundBrushStyleChanged, this, &WorksheetDock::worksheetBackgroundBrushStyleChanged); connect(m_worksheet, &Worksheet::backgroundFirstColorChanged, this, &WorksheetDock::worksheetBackgroundFirstColorChanged); connect(m_worksheet, &Worksheet::backgroundSecondColorChanged, this, &WorksheetDock::worksheetBackgroundSecondColorChanged); connect(m_worksheet, &Worksheet::backgroundFileNameChanged, this, &WorksheetDock::worksheetBackgroundFileNameChanged); connect(m_worksheet, &Worksheet::backgroundOpacityChanged, this, &WorksheetDock::worksheetBackgroundOpacityChanged); connect(m_worksheet, &Worksheet::layoutChanged, this, &WorksheetDock::worksheetLayoutChanged); connect(m_worksheet, &Worksheet::layoutTopMarginChanged, this, &WorksheetDock::worksheetLayoutTopMarginChanged); connect(m_worksheet, &Worksheet::layoutBottomMarginChanged, this, &WorksheetDock::worksheetLayoutBottomMarginChanged); connect(m_worksheet, &Worksheet::layoutLeftMarginChanged, this, &WorksheetDock::worksheetLayoutLeftMarginChanged); connect(m_worksheet, &Worksheet::layoutRightMarginChanged, this, &WorksheetDock::worksheetLayoutRightMarginChanged); connect(m_worksheet, &Worksheet::layoutVerticalSpacingChanged, this, &WorksheetDock::worksheetLayoutVerticalSpacingChanged); connect(m_worksheet, &Worksheet::layoutHorizontalSpacingChanged, this, &WorksheetDock::worksheetLayoutHorizontalSpacingChanged); connect(m_worksheet, &Worksheet::layoutRowCountChanged, this, &WorksheetDock::worksheetLayoutRowCountChanged); connect(m_worksheet, &Worksheet::layoutColumnCountChanged, this, &WorksheetDock::worksheetLayoutColumnCountChanged); connect(m_worksheet, &Worksheet::themeChanged, m_themeHandler, &ThemeHandler::setCurrentTheme); m_initializing = false; } void WorksheetDock::updateUnits() { const KConfigGroup group = KSharedConfig::openConfig()->group(QLatin1String("Settings_General")); BaseDock::Units units = (BaseDock::Units)group.readEntry("Units", (int)MetricUnits); if (units == m_units) return; m_units = units; Lock lock(m_initializing); QString suffix; if (m_units == BaseDock::MetricUnits) { //convert from imperial to metric m_worksheetUnit = Worksheet::Unit::Centimeter; - suffix = QLatin1String("cm"); + suffix = QLatin1String(" cm"); ui.sbWidth->setValue(ui.sbWidth->value()*2.54); ui.sbHeight->setValue(ui.sbHeight->value()*2.54); ui.sbLayoutTopMargin->setValue(ui.sbLayoutTopMargin->value()*2.54); ui.sbLayoutBottomMargin->setValue(ui.sbLayoutBottomMargin->value()*2.54); ui.sbLayoutLeftMargin->setValue(ui.sbLayoutLeftMargin->value()*2.54); ui.sbLayoutRightMargin->setValue(ui.sbLayoutRightMargin->value()*2.54); ui.sbLayoutHorizontalSpacing->setValue(ui.sbLayoutHorizontalSpacing->value()*2.54); ui.sbLayoutVerticalSpacing->setValue(ui.sbLayoutVerticalSpacing->value()*2.54); } else { //convert from metric to imperial m_worksheetUnit = Worksheet::Unit::Inch; - suffix = QLatin1String("in"); + suffix = QLatin1String(" in"); ui.sbWidth->setValue(ui.sbWidth->value()/2.54); ui.sbHeight->setValue(ui.sbHeight->value()/2.54); ui.sbLayoutTopMargin->setValue(ui.sbLayoutTopMargin->value()/2.54); ui.sbLayoutBottomMargin->setValue(ui.sbLayoutBottomMargin->value()/2.54); ui.sbLayoutLeftMargin->setValue(ui.sbLayoutLeftMargin->value()/2.54); ui.sbLayoutRightMargin->setValue(ui.sbLayoutRightMargin->value()/2.54); ui.sbLayoutHorizontalSpacing->setValue(ui.sbLayoutHorizontalSpacing->value()/2.54); ui.sbLayoutVerticalSpacing->setValue(ui.sbLayoutVerticalSpacing->value()/2.54); } ui.sbWidth->setSuffix(suffix); ui.sbHeight->setSuffix(suffix); ui.sbLayoutTopMargin->setSuffix(suffix); ui.sbLayoutBottomMargin->setSuffix(suffix); ui.sbLayoutLeftMargin->setSuffix(suffix); ui.sbLayoutRightMargin->setSuffix(suffix); ui.sbLayoutHorizontalSpacing->setSuffix(suffix); ui.sbLayoutVerticalSpacing->setSuffix(suffix); } /*! Checks whether the size is one of the QPageSize::PageSizeId and updates Size and Orientation checkbox when width/height changes. */ void WorksheetDock::updatePaperSize() { if (m_worksheet->useViewSize()) { ui.cbSize->setCurrentIndex(0); return; } double w = ui.sbWidth->value(); double h = ui.sbHeight->value(); if (m_units == BaseDock::MetricUnits) { //In UI we use cm, so we need to convert to mm first before we check with QPageSize w *= 10; h *= 10; } const QSizeF s = QSizeF(w, h); const QSizeF st = s.transposed(); //determine the position of the QPageSize::PageSizeId in the combobox bool found = false; for (int i = 0; i < ui.cbSize->count(); ++i) { const QVariant v = ui.cbSize->itemData(i); if (!v.isValid()) continue; const auto id = v.value(); QPageSize::Unit pageUnit = (m_units == BaseDock::MetricUnits) ? QPageSize::Millimeter : QPageSize::Inch; const QSizeF ps = QPageSize::size(id, pageUnit); if (s == ps) { //check the portrait-orientation first ui.cbSize->setCurrentIndex(i); ui.cbOrientation->setCurrentIndex(0); //a QPageSize::PaperSize in portrait-orientation was found found = true; break; } else if (st == ps) { //check for the landscape-orientation ui.cbSize->setCurrentIndex(i); ui.cbOrientation->setCurrentIndex(1); //a QPageSize::PaperSize in landscape-orientation was found found = true; break; } } if (!found) ui.cbSize->setCurrentIndex(ui.cbSize->count() - 1); //select "Custom" size } //************************************************************* //****** SLOTs for changes triggered in WorksheetDock ********* //************************************************************* void WorksheetDock::retranslateUi() { Lock lock(m_initializing); //Geometry ui.cbOrientation->clear(); ui.cbOrientation->addItem(i18n("Portrait")); ui.cbOrientation->addItem(i18n("Landscape")); QString suffix; if (m_units == BaseDock::MetricUnits) - suffix = QLatin1String("cm"); + suffix = QLatin1String(" cm"); else - suffix = QLatin1String("in"); + suffix = QLatin1String(" in"); ui.sbWidth->setSuffix(suffix); ui.sbHeight->setSuffix(suffix); ui.sbLayoutTopMargin->setSuffix(suffix); ui.sbLayoutBottomMargin->setSuffix(suffix); ui.sbLayoutLeftMargin->setSuffix(suffix); ui.sbLayoutRightMargin->setSuffix(suffix); ui.sbLayoutHorizontalSpacing->setSuffix(suffix); ui.sbLayoutVerticalSpacing->setSuffix(suffix); const QVector pageSizeIds = { QPageSize::A0, QPageSize::A1, QPageSize::A2, QPageSize::A3, QPageSize::A4, QPageSize::A5, QPageSize::A6, QPageSize::A7, QPageSize::A8, QPageSize::A9, QPageSize::B0, QPageSize::B1, QPageSize::B2, QPageSize::B3, QPageSize::B4, QPageSize::B5, QPageSize::B6, QPageSize::B7, QPageSize::B8, QPageSize::B9, QPageSize::B10, QPageSize::C5E, QPageSize::DLE, QPageSize::Executive, QPageSize::Folio, QPageSize::Ledger, QPageSize::Legal, QPageSize::Letter, QPageSize::Tabloid, QPageSize::Comm10E, QPageSize::Custom, }; ui.cbSize->clear(); ui.cbSize->addItem(i18n("View Size")); for (auto id : pageSizeIds) ui.cbSize->addItem(QPageSize::name(id), id); ui.cbSize->insertSeparator(1); //Background ui.cbBackgroundType->clear(); ui.cbBackgroundType->addItem(i18n("Color")); ui.cbBackgroundType->addItem(i18n("Image")); ui.cbBackgroundType->addItem(i18n("Pattern")); ui.cbBackgroundColorStyle->clear(); ui.cbBackgroundColorStyle->addItem(i18n("Single Color")); ui.cbBackgroundColorStyle->addItem(i18n("Horizontal Gradient")); ui.cbBackgroundColorStyle->addItem(i18n("Vertical Gradient")); ui.cbBackgroundColorStyle->addItem(i18n("Diag. Gradient (From Top Left)")); ui.cbBackgroundColorStyle->addItem(i18n("Diag. Gradient (From Bottom Left)")); ui.cbBackgroundColorStyle->addItem(i18n("Radial Gradient")); ui.cbBackgroundImageStyle->clear(); ui.cbBackgroundImageStyle->addItem(i18n("Scaled and Cropped")); ui.cbBackgroundImageStyle->addItem(i18n("Scaled")); ui.cbBackgroundImageStyle->addItem(i18n("Scaled, Keep Proportions")); ui.cbBackgroundImageStyle->addItem(i18n("Centered")); ui.cbBackgroundImageStyle->addItem(i18n("Tiled")); ui.cbBackgroundImageStyle->addItem(i18n("Center Tiled")); GuiTools::updateBrushStyles(ui.cbBackgroundBrushStyle, Qt::SolidPattern); } // "General"-tab void WorksheetDock::scaleContentChanged(bool scaled) { if (m_initializing) return; for (auto* worksheet : m_worksheetList) worksheet->setScaleContent(scaled); } void WorksheetDock::sizeChanged(int i) { const auto index = ui.cbSize->itemData(i).value(); if (index == QPageSize::Custom) { ui.sbWidth->setEnabled(true); ui.sbHeight->setEnabled(true); ui.lOrientation->hide(); ui.cbOrientation->hide(); } else { ui.sbWidth->setEnabled(false); ui.sbHeight->setEnabled(false); if (i == 0) { //no orientation available when using the complete view size (first item in the combox is selected) ui.lOrientation->hide(); ui.cbOrientation->hide(); } else { ui.lOrientation->show(); ui.cbOrientation->show(); } } if (m_initializing) return; Lock lock(m_initializing); if (i == 0) { //use the complete view size (first item in the combox is selected) for (auto* worksheet : m_worksheetList) worksheet->setUseViewSize(true); } else if (index == QPageSize::Custom) { if (m_worksheet->useViewSize()) { for (auto* worksheet : m_worksheetList) worksheet->setUseViewSize(false); } } else { //determine the width and the height of the to be used predefined layout QSizeF s = QPageSize::size(index, QPageSize::Millimeter); if (ui.cbOrientation->currentIndex() == 1) s.transpose(); //s is in mm, in UI we show everything in cm/in if (m_units == BaseDock::MetricUnits) { ui.sbWidth->setValue(s.width()/10); ui.sbHeight->setValue(s.height()/10); } else { ui.sbWidth->setValue(s.width()/25.4); ui.sbHeight->setValue(s.height()/25.4); } float w = Worksheet::convertToSceneUnits(s.width(), Worksheet::Unit::Millimeter); float h = Worksheet::convertToSceneUnits(s.height(), Worksheet::Unit::Millimeter); for (auto* worksheet : m_worksheetList) { worksheet->setUseViewSize(false); worksheet->setPageRect(QRect(0,0,w,h)); } } } void WorksheetDock::sizeChanged() { if (m_initializing) return; int w = Worksheet::convertToSceneUnits(ui.sbWidth->value(), m_worksheetUnit); int h = Worksheet::convertToSceneUnits(ui.sbHeight->value(), m_worksheetUnit); for (auto* worksheet : m_worksheetList) worksheet->setPageRect(QRect(0,0,w,h)); } void WorksheetDock::orientationChanged(int index) { Q_UNUSED(index); if (m_initializing) return; this->sizeChanged(ui.cbSize->currentIndex()); } // "Background"-tab void WorksheetDock::backgroundTypeChanged(int index) { auto type = (PlotArea::BackgroundType)index; if (type == PlotArea::BackgroundType::Color) { ui.lBackgroundColorStyle->show(); ui.cbBackgroundColorStyle->show(); ui.lBackgroundImageStyle->hide(); ui.cbBackgroundImageStyle->hide(); ui.lBackgroundBrushStyle->hide(); ui.cbBackgroundBrushStyle->hide(); ui.lBackgroundFileName->hide(); ui.leBackgroundFileName->hide(); ui.bOpen->hide(); ui.lBackgroundFirstColor->show(); ui.kcbBackgroundFirstColor->show(); auto style = (PlotArea::BackgroundColorStyle)ui.cbBackgroundColorStyle->currentIndex(); if (style == PlotArea::BackgroundColorStyle::SingleColor) { ui.lBackgroundFirstColor->setText(i18n("Color:")); ui.lBackgroundSecondColor->hide(); ui.kcbBackgroundSecondColor->hide(); } else { ui.lBackgroundFirstColor->setText(i18n("First color:")); ui.lBackgroundSecondColor->show(); ui.kcbBackgroundSecondColor->show(); } } else if (type == PlotArea::BackgroundType::Image) { ui.lBackgroundFirstColor->hide(); ui.kcbBackgroundFirstColor->hide(); ui.lBackgroundSecondColor->hide(); ui.kcbBackgroundSecondColor->hide(); ui.lBackgroundColorStyle->hide(); ui.cbBackgroundColorStyle->hide(); ui.lBackgroundImageStyle->show(); ui.cbBackgroundImageStyle->show(); ui.lBackgroundBrushStyle->hide(); ui.cbBackgroundBrushStyle->hide(); ui.lBackgroundFileName->show(); ui.leBackgroundFileName->show(); ui.bOpen->show(); } else if (type == PlotArea::BackgroundType::Pattern) { ui.lBackgroundFirstColor->setText(i18n("Color:")); ui.lBackgroundFirstColor->show(); ui.kcbBackgroundFirstColor->show(); ui.lBackgroundSecondColor->hide(); ui.kcbBackgroundSecondColor->hide(); ui.lBackgroundColorStyle->hide(); ui.cbBackgroundColorStyle->hide(); ui.lBackgroundImageStyle->hide(); ui.cbBackgroundImageStyle->hide(); ui.lBackgroundBrushStyle->show(); ui.cbBackgroundBrushStyle->show(); ui.lBackgroundFileName->hide(); ui.leBackgroundFileName->hide(); ui.bOpen->hide(); } if (m_initializing) return; for (auto* worksheet : m_worksheetList) worksheet->setBackgroundType(type); } void WorksheetDock::backgroundColorStyleChanged(int index) { auto style = (PlotArea::BackgroundColorStyle)index; if (style == PlotArea::BackgroundColorStyle::SingleColor) { ui.lBackgroundFirstColor->setText(i18n("Color:")); ui.lBackgroundSecondColor->hide(); ui.kcbBackgroundSecondColor->hide(); } else { ui.lBackgroundFirstColor->setText(i18n("First color:")); ui.lBackgroundSecondColor->show(); ui.kcbBackgroundSecondColor->show(); } if (m_initializing) return; int size = m_worksheetList.size(); if (size>1) { m_worksheet->beginMacro(i18n("%1 worksheets: background color style changed", size)); for (auto* w : m_worksheetList) w->setBackgroundColorStyle(style); m_worksheet->endMacro(); } else m_worksheet->setBackgroundColorStyle(style); } void WorksheetDock::backgroundImageStyleChanged(int index) { if (m_initializing) return; auto style = (PlotArea::BackgroundImageStyle)index; for (auto* worksheet : m_worksheetList) worksheet->setBackgroundImageStyle(style); } void WorksheetDock::backgroundBrushStyleChanged(int index) { if (m_initializing) return; auto style = (Qt::BrushStyle)index; for (auto* worksheet : m_worksheetList) worksheet->setBackgroundBrushStyle(style); } void WorksheetDock::backgroundFirstColorChanged(const QColor& c) { if (m_initializing) return; for (auto* worksheet : m_worksheetList) worksheet->setBackgroundFirstColor(c); } void WorksheetDock::backgroundSecondColorChanged(const QColor& c) { if (m_initializing) return; for (auto* worksheet : m_worksheetList) worksheet->setBackgroundSecondColor(c); } void WorksheetDock::backgroundOpacityChanged(int value) { if (m_initializing) return; float opacity = (float)value/100; for (auto* worksheet : m_worksheetList) worksheet->setBackgroundOpacity(opacity); } //"Layout"-tab void WorksheetDock::layoutChanged(int index) { auto layout = (Worksheet::Layout)index; bool b = (layout != Worksheet::Layout::NoLayout); ui.sbLayoutTopMargin->setEnabled(b); ui.sbLayoutBottomMargin->setEnabled(b); ui.sbLayoutLeftMargin->setEnabled(b); ui.sbLayoutRightMargin->setEnabled(b); ui.sbLayoutHorizontalSpacing->setEnabled(b); ui.sbLayoutVerticalSpacing->setEnabled(b); ui.sbLayoutRowCount->setEnabled(b); ui.sbLayoutColumnCount->setEnabled(b); //show the "scale content" option if no layout active ui.lScaleContent->setVisible(!b); ui.chScaleContent->setVisible(!b); if (b) { //show grid specific settings if grid layout selected bool grid = (layout == Worksheet::Layout::GridLayout); ui.lGrid->setVisible(grid); ui.lRowCount->setVisible(grid); ui.sbLayoutRowCount->setVisible(grid); ui.lColumnCount->setVisible(grid); ui.sbLayoutColumnCount->setVisible(grid); } else { //no layout selected, hide grid specific settings that were potentially shown before ui.lGrid->setVisible(false); ui.lRowCount->setVisible(false); ui.sbLayoutRowCount->setVisible(false); ui.lColumnCount->setVisible(false); ui.sbLayoutColumnCount->setVisible(false); } if (m_initializing) return; for (auto* worksheet : m_worksheetList) worksheet->setLayout(layout); } void WorksheetDock::layoutTopMarginChanged(double margin) { if (m_initializing) return; for (auto* worksheet : m_worksheetList) worksheet->setLayoutTopMargin(Worksheet::convertToSceneUnits(margin, m_worksheetUnit)); } void WorksheetDock::layoutBottomMarginChanged(double margin) { if (m_initializing) return; for (auto* worksheet : m_worksheetList) worksheet->setLayoutBottomMargin(Worksheet::convertToSceneUnits(margin, m_worksheetUnit)); } void WorksheetDock::layoutLeftMarginChanged(double margin) { if (m_initializing) return; for (auto* worksheet : m_worksheetList) worksheet->setLayoutLeftMargin(Worksheet::convertToSceneUnits(margin, m_worksheetUnit)); } void WorksheetDock::layoutRightMarginChanged(double margin) { if (m_initializing) return; for (auto* worksheet : m_worksheetList) worksheet->setLayoutRightMargin(Worksheet::convertToSceneUnits(margin, m_worksheetUnit)); } void WorksheetDock::layoutHorizontalSpacingChanged(double spacing) { if (m_initializing) return; for (auto* worksheet : m_worksheetList) worksheet->setLayoutHorizontalSpacing(Worksheet::convertToSceneUnits(spacing, m_worksheetUnit)); } void WorksheetDock::layoutVerticalSpacingChanged(double spacing) { if (m_initializing) return; for (auto* worksheet : m_worksheetList) worksheet->setLayoutVerticalSpacing(Worksheet::convertToSceneUnits(spacing, m_worksheetUnit)); } void WorksheetDock::layoutRowCountChanged(int count) { if (m_initializing) return; for (auto* worksheet : m_worksheetList) worksheet->setLayoutRowCount(count); } void WorksheetDock::layoutColumnCountChanged(int count) { if (m_initializing) return; for (auto* worksheet : m_worksheetList) worksheet->setLayoutColumnCount(count); } /*! opens a file dialog and lets the user select the image file. */ void WorksheetDock::selectFile() { KConfigGroup conf(KSharedConfig::openConfig(), "WorksheetDock"); QString dir = conf.readEntry("LastImageDir", ""); QString formats; for (const QByteArray& format : QImageReader::supportedImageFormats()) { QString f = "*." + QString(format.constData()); if (f == QLatin1String("*.svg")) continue; formats.isEmpty() ? formats += f : formats += ' ' + f; } QString path = QFileDialog::getOpenFileName(this, i18n("Select the image file"), dir, i18n("Images (%1)", formats)); if (path.isEmpty()) return; //cancel was clicked in the file-dialog int pos = path.lastIndexOf(QLatin1String("/")); if (pos != -1) { QString newDir = path.left(pos); if (newDir != dir) conf.writeEntry("LastImageDir", newDir); } ui.leBackgroundFileName->setText( path ); for (auto* worksheet : m_worksheetList) worksheet->setBackgroundFileName(path); } void WorksheetDock::fileNameChanged() { if (m_initializing) return; QString fileName = ui.leBackgroundFileName->text(); if (!fileName.isEmpty() && !QFile::exists(fileName)) ui.leBackgroundFileName->setStyleSheet("QLineEdit{background:red;}"); else ui.leBackgroundFileName->setStyleSheet(QString()); for (auto* worksheet : m_worksheetList) worksheet->setBackgroundFileName(fileName); } //************************************************************* //******** SLOTs for changes triggered in Worksheet *********** //************************************************************* void WorksheetDock::worksheetDescriptionChanged(const AbstractAspect* aspect) { if (m_worksheet != aspect) return; m_initializing = true; if (aspect->name() != ui.leName->text()) ui.leName->setText(aspect->name()); else if (aspect->comment() != ui.leComment->text()) ui.leComment->setText(aspect->comment()); m_initializing = false; } void WorksheetDock::worksheetScaleContentChanged(bool scaled) { m_initializing = true; ui.chScaleContent->setChecked(scaled); m_initializing = false; } void WorksheetDock::worksheetPageRectChanged(const QRectF& rect) { m_initializing = true; ui.sbWidth->setValue(Worksheet::convertFromSceneUnits(rect.width(), m_worksheetUnit)); ui.sbHeight->setValue(Worksheet::convertFromSceneUnits(rect.height(), m_worksheetUnit)); updatePaperSize(); m_initializing = false; } void WorksheetDock::worksheetBackgroundTypeChanged(PlotArea::BackgroundType type) { m_initializing = true; ui.cbBackgroundType->setCurrentIndex(static_cast(type)); m_initializing = false; } void WorksheetDock::worksheetBackgroundColorStyleChanged(PlotArea::BackgroundColorStyle style) { m_initializing = true; ui.cbBackgroundColorStyle->setCurrentIndex(static_cast(style)); m_initializing = false; } void WorksheetDock::worksheetBackgroundImageStyleChanged(PlotArea::BackgroundImageStyle style) { m_initializing = true; ui.cbBackgroundImageStyle->setCurrentIndex(static_cast(style)); m_initializing = false; } void WorksheetDock::worksheetBackgroundBrushStyleChanged(Qt::BrushStyle style) { m_initializing = true; ui.cbBackgroundBrushStyle->setCurrentIndex(style); m_initializing = false; } void WorksheetDock::worksheetBackgroundFirstColorChanged(const QColor& color) { m_initializing = true; ui.kcbBackgroundFirstColor->setColor(color); m_initializing = false; } void WorksheetDock::worksheetBackgroundSecondColorChanged(const QColor& color) { m_initializing = true; ui.kcbBackgroundSecondColor->setColor(color); m_initializing = false; } void WorksheetDock::worksheetBackgroundFileNameChanged(const QString& name) { m_initializing = true; ui.leBackgroundFileName->setText(name); m_initializing = false; } void WorksheetDock::worksheetBackgroundOpacityChanged(float opacity) { m_initializing = true; ui.sbBackgroundOpacity->setValue( qRound(opacity*100.0) ); m_initializing = false; } void WorksheetDock::worksheetLayoutChanged(Worksheet::Layout layout) { m_initializing = true; ui.cbLayout->setCurrentIndex(static_cast(layout)); m_initializing = false; } void WorksheetDock::worksheetLayoutTopMarginChanged(float value) { m_initializing = true; ui.sbLayoutTopMargin->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void WorksheetDock::worksheetLayoutBottomMarginChanged(float value) { m_initializing = true; ui.sbLayoutBottomMargin->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void WorksheetDock::worksheetLayoutLeftMarginChanged(float value) { m_initializing = true; ui.sbLayoutLeftMargin->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void WorksheetDock::worksheetLayoutRightMarginChanged(float value) { m_initializing = true; ui.sbLayoutRightMargin->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void WorksheetDock::worksheetLayoutVerticalSpacingChanged(float value) { m_initializing = true; ui.sbLayoutVerticalSpacing->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void WorksheetDock::worksheetLayoutHorizontalSpacingChanged(float value) { m_initializing = true; ui.sbLayoutHorizontalSpacing->setValue(Worksheet::convertFromSceneUnits(value, m_worksheetUnit)); m_initializing = false; } void WorksheetDock::worksheetLayoutRowCountChanged(int value) { m_initializing = true; ui.sbLayoutRowCount->setValue(value); m_initializing = false; } void WorksheetDock::worksheetLayoutColumnCountChanged(int value) { m_initializing = true; ui.sbLayoutColumnCount->setValue(value); m_initializing = false; } //************************************************************* //******************** SETTINGS ******************************* //************************************************************* void WorksheetDock::load() { // Geometry ui.chScaleContent->setChecked(m_worksheet->scaleContent()); ui.sbWidth->setValue(Worksheet::convertFromSceneUnits( m_worksheet->pageRect().width(), m_worksheetUnit) ); ui.sbHeight->setValue(Worksheet::convertFromSceneUnits( m_worksheet->pageRect().height(), m_worksheetUnit) ); updatePaperSize(); // Background-tab ui.cbBackgroundType->setCurrentIndex( (int) m_worksheet->backgroundType() ); ui.cbBackgroundColorStyle->setCurrentIndex( (int) m_worksheet->backgroundColorStyle() ); ui.cbBackgroundImageStyle->setCurrentIndex( (int) m_worksheet->backgroundImageStyle() ); ui.cbBackgroundBrushStyle->setCurrentIndex( (int) m_worksheet->backgroundBrushStyle() ); ui.leBackgroundFileName->setText( m_worksheet->backgroundFileName() ); ui.kcbBackgroundFirstColor->setColor( m_worksheet->backgroundFirstColor() ); ui.kcbBackgroundSecondColor->setColor( m_worksheet->backgroundSecondColor() ); ui.sbBackgroundOpacity->setValue( qRound(m_worksheet->backgroundOpacity()*100) ); //highlight the text field for the background image red if an image is used and cannot be found if (!m_worksheet->backgroundFileName().isEmpty() && !QFile::exists(m_worksheet->backgroundFileName())) ui.leBackgroundFileName->setStyleSheet("QLineEdit{background:red;}"); else ui.leBackgroundFileName->setStyleSheet(QString()); // Layout ui.cbLayout->setCurrentIndex( (int) m_worksheet->layout() ); ui.sbLayoutTopMargin->setValue( Worksheet::convertFromSceneUnits(m_worksheet->layoutTopMargin(), m_worksheetUnit) ); ui.sbLayoutBottomMargin->setValue( Worksheet::convertFromSceneUnits(m_worksheet->layoutBottomMargin(), m_worksheetUnit) ); ui.sbLayoutLeftMargin->setValue( Worksheet::convertFromSceneUnits(m_worksheet->layoutLeftMargin(), m_worksheetUnit) ); ui.sbLayoutRightMargin->setValue( Worksheet::convertFromSceneUnits(m_worksheet->layoutRightMargin(), m_worksheetUnit) ); ui.sbLayoutHorizontalSpacing->setValue( Worksheet::convertFromSceneUnits(m_worksheet->layoutHorizontalSpacing(), m_worksheetUnit) ); ui.sbLayoutVerticalSpacing->setValue( Worksheet::convertFromSceneUnits(m_worksheet->layoutVerticalSpacing(), m_worksheetUnit) ); ui.sbLayoutRowCount->setValue( m_worksheet->layoutRowCount() ); ui.sbLayoutColumnCount->setValue( m_worksheet->layoutColumnCount() ); } void WorksheetDock::loadConfigFromTemplate(KConfig& config) { //extract the name of the template from the file name QString name; int index = config.name().lastIndexOf(QLatin1String("/")); if (index != -1) name = config.name().right(config.name().size() - index - 1); else name = config.name(); int size = m_worksheetList.size(); if (size > 1) m_worksheet->beginMacro(i18n("%1 worksheets: template \"%2\" loaded", size, name)); else m_worksheet->beginMacro(i18n("%1: template \"%2\" loaded", m_worksheet->name(), name)); this->loadConfig(config); m_worksheet->endMacro(); } void WorksheetDock::loadConfig(KConfig& config) { KConfigGroup group = config.group( "Worksheet" ); // Geometry ui.chScaleContent->setChecked(group.readEntry("ScaleContent", false)); ui.sbWidth->setValue(Worksheet::convertFromSceneUnits(group.readEntry("Width", m_worksheet->pageRect().width()), m_worksheetUnit)); ui.sbHeight->setValue(Worksheet::convertFromSceneUnits(group.readEntry("Height", m_worksheet->pageRect().height()), m_worksheetUnit)); if (group.readEntry("UseViewSize", false)) ui.cbSize->setCurrentIndex(0); else updatePaperSize(); // Background-tab ui.cbBackgroundType->setCurrentIndex( group.readEntry("BackgroundType", (int) m_worksheet->backgroundType()) ); ui.cbBackgroundColorStyle->setCurrentIndex( group.readEntry("BackgroundColorStyle", (int) m_worksheet->backgroundColorStyle()) ); ui.cbBackgroundImageStyle->setCurrentIndex( group.readEntry("BackgroundImageStyle", (int) m_worksheet->backgroundImageStyle()) ); ui.cbBackgroundBrushStyle->setCurrentIndex( group.readEntry("BackgroundBrushStyle", (int) m_worksheet->backgroundBrushStyle()) ); ui.leBackgroundFileName->setText( group.readEntry("BackgroundFileName", m_worksheet->backgroundFileName()) ); ui.kcbBackgroundFirstColor->setColor( group.readEntry("BackgroundFirstColor", m_worksheet->backgroundFirstColor()) ); ui.kcbBackgroundSecondColor->setColor( group.readEntry("BackgroundSecondColor", m_worksheet->backgroundSecondColor()) ); ui.sbBackgroundOpacity->setValue( qRound(group.readEntry("BackgroundOpacity", m_worksheet->backgroundOpacity())*100) ); // Layout ui.sbLayoutTopMargin->setValue( Worksheet::convertFromSceneUnits(group.readEntry("LayoutTopMargin", m_worksheet->layoutTopMargin()), m_worksheetUnit) ); ui.sbLayoutBottomMargin->setValue( Worksheet::convertFromSceneUnits(group.readEntry("LayoutBottomMargin", m_worksheet->layoutBottomMargin()), m_worksheetUnit) ); ui.sbLayoutLeftMargin->setValue( Worksheet::convertFromSceneUnits(group.readEntry("LayoutLeftMargin", m_worksheet->layoutLeftMargin()), m_worksheetUnit) ); ui.sbLayoutRightMargin->setValue( Worksheet::convertFromSceneUnits(group.readEntry("LayoutRightMargin", m_worksheet->layoutRightMargin()), m_worksheetUnit) ); ui.sbLayoutHorizontalSpacing->setValue( Worksheet::convertFromSceneUnits(group.readEntry("LayoutHorizontalSpacing", m_worksheet->layoutHorizontalSpacing()), m_worksheetUnit) ); ui.sbLayoutVerticalSpacing->setValue( Worksheet::convertFromSceneUnits(group.readEntry("LayoutVerticalSpacing", m_worksheet->layoutVerticalSpacing()), m_worksheetUnit) ); ui.sbLayoutRowCount->setValue(group.readEntry("LayoutRowCount", m_worksheet->layoutRowCount())); ui.sbLayoutColumnCount->setValue(group.readEntry("LayoutColumnCount", m_worksheet->layoutColumnCount())); } void WorksheetDock::saveConfigAsTemplate(KConfig& config) { KConfigGroup group = config.group( "Worksheet" ); //General group.writeEntry("ScaleContent",ui.chScaleContent->isChecked()); group.writeEntry("UseViewSize",ui.cbSize->currentIndex() == 0); group.writeEntry("Width",Worksheet::convertToSceneUnits(ui.sbWidth->value(), m_worksheetUnit)); group.writeEntry("Height",Worksheet::convertToSceneUnits(ui.sbHeight->value(), m_worksheetUnit)); //Background group.writeEntry("BackgroundType",ui.cbBackgroundType->currentIndex()); group.writeEntry("BackgroundColorStyle", ui.cbBackgroundColorStyle->currentIndex()); group.writeEntry("BackgroundImageStyle", ui.cbBackgroundImageStyle->currentIndex()); group.writeEntry("BackgroundBrushStyle", ui.cbBackgroundBrushStyle->currentIndex()); group.writeEntry("BackgroundFileName", ui.leBackgroundFileName->text()); group.writeEntry("BackgroundFirstColor", ui.kcbBackgroundFirstColor->color()); group.writeEntry("BackgroundSecondColor", ui.kcbBackgroundSecondColor->color()); group.writeEntry("BackgroundOpacity", ui.sbBackgroundOpacity->value()/100.0); //Layout group.writeEntry("LayoutTopMargin",Worksheet::convertToSceneUnits(ui.sbLayoutTopMargin->value(), m_worksheetUnit)); group.writeEntry("LayoutBottomMargin",Worksheet::convertToSceneUnits(ui.sbLayoutBottomMargin->value(), m_worksheetUnit)); group.writeEntry("LayoutLeftMargin",Worksheet::convertToSceneUnits(ui.sbLayoutLeftMargin->value(), m_worksheetUnit)); group.writeEntry("LayoutRightMargin",Worksheet::convertToSceneUnits(ui.sbLayoutRightMargin->value(), m_worksheetUnit)); group.writeEntry("LayoutVerticalSpacing",Worksheet::convertToSceneUnits(ui.sbLayoutVerticalSpacing->value(), m_worksheetUnit)); group.writeEntry("LayoutHorizontalSpacing",Worksheet::convertToSceneUnits(ui.sbLayoutHorizontalSpacing->value(), m_worksheetUnit)); group.writeEntry("LayoutRowCount", ui.sbLayoutRowCount->value()); group.writeEntry("LayoutColumnCount", ui.sbLayoutColumnCount->value()); config.sync(); } void WorksheetDock::loadTheme(const QString& theme) { for (auto* worksheet : m_worksheetList) worksheet->setTheme(theme); } diff --git a/src/kdefrontend/ui/datapickerimagewidget.ui b/src/kdefrontend/ui/datapickerimagewidget.ui index ae64121a3..1c97824dd 100644 --- a/src/kdefrontend/ui/datapickerimagewidget.ui +++ b/src/kdefrontend/ui/datapickerimagewidget.ui @@ -1,1102 +1,1102 @@ DatapickerImageWidget 0 0 - 813 + 656 1181 0 0 0 General Name: 0 0 true Comment: 0 0 true Qt::Vertical QSizePolicy::Fixed 20 18 75 true Plot Image: Specify the name of the image file. true 0 0 Select the image file Type: Rotation: 0 0 ° -360.000000000000000 360.000000000000000 Qt::Vertical QSizePolicy::Fixed 20 18 1. 0 0 -99999.000000000000000 99999.000000000000000 0 0 -99999.000000000000000 99999.000000000000000 0 0 -99999.000000000000000 99999.000000000000000 y= Qt::AlignCenter x= Qt::AlignCenter z= Qt::AlignCenter 0 0 -99999.000000000000000 99999.000000000000000 0 0 -99999.000000000000000 9999.000000000000000 y= Qt::AlignCenter 0 0 -99999.000000000000000 99999.000000000000000 0 0 -99999.000000000000000 99999.000000000000000 x= Qt::AlignCenter Qt::Horizontal 40 20 Qt::Horizontal 40 20 z= Qt::AlignCenter 0 0 -99999.000000000000000 99999.000000000000000 y= Qt::AlignCenter Qt::Horizontal 40 20 0 0 -99999.000000000000000 99999.000000000000000 z= Qt::AlignCenter x= Qt::AlignCenter 2. 3. x+y+z= 75 true Segments Length: 0 0 - px + px Point separation: Qt::Horizontal QSizePolicy::Fixed 13 23 0 0 - px + px Qt::Vertical 20 231 Qt::Vertical QSizePolicy::Fixed 20 18 Qt::Vertical QSizePolicy::Fixed 20 18 75 true Reference Points Ref. Points Symbol 75 true General Style: Qt::Horizontal QSizePolicy::Fixed 13 23 0 0 Size: pt 0.500000000000000 Rotation: 0 0 ° -360 360 10 0 Opacity: 0 0 The opacity ranges from 0 to 100, where 0 is fully transparent and 100 is fully opaque. % 0 100 10 100 Qt::Vertical QSizePolicy::Fixed 20 18 75 true Filling Style: Color: 0 0 Qt::Vertical QSizePolicy::Fixed 20 18 75 true Border Style: Color: 0 0 Width: pt 0.500000000000000 Qt::Vertical 20 40 Visible Edit Image Intensity: 0 0 Vertical position relative to label's parent Qt::Vertical QSizePolicy::Fixed 20 18 Value: Hue: Qt::Vertical 20 40 Current image: Saturation: Foreground: Qt::Horizontal QSizePolicy::Fixed 13 23 KColorButton QPushButton
kcolorbutton.h
leName leComment leFileName bOpen cbGraphType sbRotation sbPositionX1 sbPositionY1 sbPositionZ1 sbPositionX2 sbPositionY2 sbPositionZ2 sbPositionX3 sbPositionY3 sbPositionZ3 sbTernaryScale sbMinSegmentLength sbPointSeparation sbSymbolBorderWidth sbSymbolRotation cbSymbolStyle sbSymbolOpacity chbSymbolVisible cbSymbolFillingStyle cbPlotImageType tabWidget kcbSymbolFillingColor sbSymbolSize cbSymbolBorderStyle kcbSymbolBorderColor
diff --git a/src/kdefrontend/ui/dockwidgets/cartesianplotdock.ui b/src/kdefrontend/ui/dockwidgets/cartesianplotdock.ui index c5ec17ca2..36c9e68f8 100644 --- a/src/kdefrontend/ui/dockwidgets/cartesianplotdock.ui +++ b/src/kdefrontend/ui/dockwidgets/cartesianplotdock.ui @@ -1,1473 +1,1473 @@ CartesianPlotDock 0 0 422 1204 0 General Name: Qt::Horizontal QSizePolicy::Fixed 10 23 true Comment: true Qt::Vertical QSizePolicy::Fixed 28 18 75 true Geometry Left: cm 1000.000000000000000 0.100000000000000 Top: cm 1000.000000000000000 0.100000000000000 Width: cm 1000.000000000000000 0.100000000000000 Height: cm 1000.000000000000000 0.100000000000000 Qt::Vertical QSizePolicy::Fixed 28 40 75 true Data range Show &last points Show f&irst points Free ranges true Qt::Vertical QSizePolicy::Fixed 28 18 75 true x-Range: Auto Format: Minimum: Auto true Maximum: Auto true Minimum: true Maximum: true Scaling: Qt::Vertical QSizePolicy::Fixed 28 18 75 true y-Range: Auto Format: Minimum: Auto true Maximum: Auto true Minimum: Maximum: Scaling: Qt::Vertical 20 178 Visible Title Range Breaks 75 true x-Range Enabled: Qt::Horizontal QSizePolicy::Fixed 13 23 Qt::Horizontal 25 20 0 0 QFrame::NoFrame QFrame::Raised 0 Add new scale breaking Remove scale breaking Current scale breaking From: To: Position: Style: Qt::Vertical QSizePolicy::Fixed 28 18 75 true y-Range Enabled: Qt::Horizontal 31 20 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Add new scale breaking Remove scale breaking Current scale breaking From: To: Position: Style: Qt::Vertical 20 13 % 10 % 10 Plot Area pt 0.500000000000000 Style: Opacity: cm 1000.000000000000000 0.100000000000000 Opacity: Type: Style: Qt::Vertical QSizePolicy::Fixed 72 18 0 0 The opacity ranges from 0 to 100, where 0 is fully transparent and 100 is fully opaque. % 0 100 10 100 Qt::Vertical QSizePolicy::Fixed 72 18 Horizontal: 0 0 Width: cm 1000.000000000000000 0.100000000000000 Qt::Horizontal QSizePolicy::Fixed 10 23 75 true Border 75 true Padding 75 true Background Color: Right: cm 1000.000000000000000 0.100000000000000 First color: 0 0 Select the file to import Style: - cm + cm 0.500000000000000 Specify the name of the image file. true Corner radius: 0 0 The opacity ranges from 0 to 100, where 0 is fully transparent and 100 is fully opaque. % 0 100 10 100 Qt::Vertical 20 79 0 0 Style: Second color: Vertical: Bottom: File name: 0 0 cm 1000.000000000000000 0.100000000000000 Symmetric: Cursor Qt::Vertical 20 1238 0 0 Width: - pt + pt 0 0 Style: 0 0 Color: 75 true Line Qt::Horizontal QSizePolicy::Fixed 10 20 KColorButton QPushButton
kcolorbutton.h
tabWidget leName leComment sbLeft sbTop sbWidth sbHeight rbRangeLast leRangeLast rbRangeFirst leRangeFirst rbRangeFree chkAutoScaleX cbXRangeFormat leXMin leXMax dateTimeEditXMin dateTimeEditXMax cbXScaling chkAutoScaleY cbYRangeFormat leYMin leYMax dateTimeEditYMin dateTimeEditYMax cbYScaling chkVisible chkXBreak bAddXBreak bRemoveXBreak cbXBreak leXBreakStart leXBreakEnd sbXBreakPosition cbXBreakStyle chkYBreak bAddYBreak bRemoveYBreak cbYBreak leYBreakStart leYBreakEnd sbYBreakPosition cbYBreakStyle cbBackgroundType leBackgroundFileName bOpen cbBackgroundColorStyle cbBackgroundImageStyle cbBackgroundBrushStyle kcbBackgroundFirstColor kcbBackgroundSecondColor sbBackgroundOpacity cbBorderStyle kcbBorderColor sbBorderWidth sbBorderCornerRadius sbBorderOpacity sbPaddingHorizontal sbPaddingVertical sbPaddingRight sbPaddingBottom
diff --git a/src/kdefrontend/ui/labelwidget.ui b/src/kdefrontend/ui/labelwidget.ui index b4be2073b..ae316bd06 100644 --- a/src/kdefrontend/ui/labelwidget.ui +++ b/src/kdefrontend/ui/labelwidget.ui @@ -1,685 +1,685 @@ LabelWidget 0 0 505 1017 Qt::Horizontal QSizePolicy::Fixed 10 23 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 0 0 TeX mode true true Qt::Horizontal QSizePolicy::Expanding 20 18 0 0 16777215 16777215 true true true true true - Foreground color: + Font color: 0 0 20 20 Background color: 0 0 20 20 0 0 Vertical position relative to label's parent 0 0 Vertical position relative to label's parent cm -99.989999999999995 0.500000000000000 Distance to the axis tick labels pt -99.989999999999995 0.500000000000000 Distance to the axis tick labels pt -99.989999999999995 0.500000000000000 ° -360 360 5 0 0 0 0 pt 0.500000000000000 0 0 The opacity ranges from 0 to 100, where 0 is fully transparent and 100 is fully opaque. % 0 100 10 100 0 0 Horizontal position relative to label's parent 0 0 Horizontal position relative to label's parent cm -99.989999999999995 0.500000000000000 75 true QFrame::NoFrame Text: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Font: Main font: Size: 75 true QFrame::NoFrame Geometry Horizontal position relative to label's parent x: Vertical position relative to label's parent y: Distance to the axis tick labels Offset X: Distance to the axis tick labels Offset Y: Hor. align.: Vert. align.: Rotation: 75 true QFrame::NoFrame Border Shape: Style: Color: Width: Opacity: Visible Qt::Vertical QSizePolicy::Fixed 58 20 Qt::Vertical QSizePolicy::Fixed 58 20 Qt::Vertical 20 37 KComboBox QComboBox
kcombobox.h
KColorButton QPushButton
kcolorbutton.h
KFontRequester QWidget
kfontrequester.h
ResizableTextEdit QTextEdit
src/kdefrontend/widgets/ResizableTextEdit.h
diff --git a/src/kdefrontend/widgets/LabelWidget.cpp b/src/kdefrontend/widgets/LabelWidget.cpp index 1b896560e..7c5ffba25 100644 --- a/src/kdefrontend/widgets/LabelWidget.cpp +++ b/src/kdefrontend/widgets/LabelWidget.cpp @@ -1,1232 +1,1232 @@ /*************************************************************************** File : LabelWidget.cc Project : LabPlot -------------------------------------------------------------------- Copyright : (C) 2008-2020 Alexander Semke (alexander.semke@web.de) Copyright : (C) 2012-2017 Stefan Gerlach (stefan.gerlach@uni-konstanz.de) Description : label settings widget ***************************************************************************/ /*************************************************************************** * * * 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 "LabelWidget.h" #include "backend/worksheet/Worksheet.h" #include "backend/worksheet/plots/cartesian/Axis.h" #include "backend/worksheet/plots/cartesian/CartesianPlot.h" #include "backend/worksheet/plots/cartesian/CartesianPlotLegend.h" #include "kdefrontend/GuiTools.h" #include "kdefrontend/dockwidgets/BaseDock.h" #include "tools/TeXRenderer.h" #include #include #include #include #include #include #include #include #include #ifdef HAVE_KF5_SYNTAX_HIGHLIGHTING #include #include #include #endif #include /*! \class LabelWidget \brief Widget for editing the properties of a TextLabel object, mostly used in an appropriate dock widget. In order the properties of the label to be shown, \c loadConfig() has to be called with the corresponding KConfigGroup (settings for a label in *Plot, Axis etc. or for an independent label on the worksheet). \ingroup kdefrontend */ LabelWidget::LabelWidget(QWidget* parent) : QWidget(parent), m_dateTimeMenu(new QMenu(this)) { ui.setupUi(this); const KConfigGroup group = KSharedConfig::openConfig()->group(QLatin1String("Settings_General")); m_units = (BaseDock::Units)group.readEntry("Units", (int)BaseDock::MetricUnits); if (m_units == BaseDock::ImperialUnits) m_worksheetUnit = Worksheet::Unit::Inch; m_dateTimeMenu->setSeparatorsCollapsible(false); //we don't want the first separator to be removed ui.kcbFontColor->setColor(Qt::black); // default color //Icons ui.tbFontBold->setIcon( QIcon::fromTheme(QLatin1String("format-text-bold")) ); ui.tbFontItalic->setIcon( QIcon::fromTheme(QLatin1String("format-text-italic")) ); ui.tbFontUnderline->setIcon( QIcon::fromTheme(QLatin1String("format-text-underline")) ); ui.tbFontStrikeOut->setIcon( QIcon::fromTheme(QLatin1String("format-text-strikethrough")) ); ui.tbFontSuperScript->setIcon( QIcon::fromTheme(QLatin1String("format-text-superscript")) ); ui.tbFontSubScript->setIcon( QIcon::fromTheme(QLatin1String("format-text-subscript")) ); ui.tbSymbols->setIcon( QIcon::fromTheme(QLatin1String("labplot-format-text-symbol")) ); ui.tbDateTime->setIcon( QIcon::fromTheme(QLatin1String("chronometer")) ); ui.tbTexUsed->setIcon( QIcon::fromTheme(QLatin1String("labplot-TeX-logo")) ); ui.tbFontBold->setToolTip(i18n("Bold")); ui.tbFontItalic->setToolTip(i18n("Italic")); ui.tbFontUnderline->setToolTip(i18n("Underline")); ui.tbFontStrikeOut->setToolTip(i18n("Strike Out")); ui.tbFontSuperScript->setToolTip(i18n("Super Script")); ui.tbFontSubScript->setToolTip(i18n("Sub-Script")); ui.tbSymbols->setToolTip(i18n("Insert Symbol")); ui.tbDateTime->setToolTip(i18n("Insert Date/Time")); ui.tbTexUsed->setToolTip(i18n("Switch to TeX mode")); //Positioning and alignment ui.cbPositionX->addItem(i18n("Left")); ui.cbPositionX->addItem(i18n("Center")); ui.cbPositionX->addItem(i18n("Right")); ui.cbPositionX->addItem(i18n("Custom")); ui.cbPositionY->addItem(i18n("Top")); ui.cbPositionY->addItem(i18n("Center")); ui.cbPositionY->addItem(i18n("Bottom")); ui.cbPositionY->addItem(i18n("Custom")); QString suffix; if (m_units == BaseDock::MetricUnits) - suffix = QLatin1String("cm"); + suffix = QLatin1String(" cm"); else - suffix = QLatin1String("in"); + suffix = QLatin1String(" in"); ui.sbPositionX->setSuffix(suffix); ui.sbPositionY->setSuffix(suffix); ui.cbHorizontalAlignment->addItem(i18n("Left")); ui.cbHorizontalAlignment->addItem(i18n("Center")); ui.cbHorizontalAlignment->addItem(i18n("Right")); ui.cbVerticalAlignment->addItem(i18n("Top")); ui.cbVerticalAlignment->addItem(i18n("Center")); ui.cbVerticalAlignment->addItem(i18n("Bottom")); ui.cbBorderShape->addItem(i18n("No Border")); ui.cbBorderShape->addItem(i18n("Rectangle")); ui.cbBorderShape->addItem(i18n("Ellipse")); ui.cbBorderShape->addItem(i18n("Round sided rectangle")); ui.cbBorderShape->addItem(i18n("Round corner rectangle")); ui.cbBorderShape->addItem(i18n("Inwards round corner rectangle")); ui.cbBorderShape->addItem(i18n("Dented border rectangle")); ui.cbBorderShape->addItem(i18n("Cuboid")); ui.cbBorderShape->addItem(i18n("Up Pointing rectangle")); ui.cbBorderShape->addItem(i18n("Down Pointing rectangle")); ui.cbBorderShape->addItem(i18n("Left Pointing rectangle")); ui.cbBorderShape->addItem(i18n("Right Pointing rectangle")); ui.cbBorderStyle->addItem(i18n("No line")); ui.cbBorderStyle->addItem(i18n("Solid line")); ui.cbBorderStyle->addItem(i18n("Dash line")); ui.cbBorderStyle->addItem(i18n("Dot line")); ui.cbBorderStyle->addItem(i18n("Dash dot line")); ui.cbBorderStyle->addItem(i18n("Dash dot dot line")); ui.kcbBackgroundColor->setAlphaChannelEnabled(true); ui.kcbBackgroundColor->setColor(QColor(0,0,0, 0)); // transparent ui.kcbFontColor->setAlphaChannelEnabled(true); ui.kcbFontColor->setColor(QColor(255,255,255, 255)); // black ui.kcbBorderColor->setAlphaChannelEnabled(true); ui.kcbBorderColor->setColor(QColor(255,255,255, 255)); // black //check whether the used latex compiler is available. //Following logic is implemented (s.a. LabelWidget::teXUsedChanged()): //1. in case latex was used to generate the text label in the stored project //and no latex is available on the target system, latex button is toggled and //the user still can switch to the non-latex mode. //2. in case the label was in the non-latex mode and no latex is available, //deactivate the latex button so the user cannot switch to this mode. m_teXEnabled = TeXRenderer::enabled(); #ifdef HAVE_KF5_SYNTAX_HIGHLIGHTING m_highlighter = new KSyntaxHighlighting::SyntaxHighlighter(ui.teLabel->document()); m_highlighter->setDefinition(m_repository.definitionForName(QLatin1String("LaTeX"))); m_highlighter->setTheme( (palette().color(QPalette::Base).lightness() < 128) ? m_repository.defaultTheme(KSyntaxHighlighting::Repository::DarkTheme) : m_repository.defaultTheme(KSyntaxHighlighting::Repository::LightTheme) ); #endif //SLOTS // text properties connect(ui.tbTexUsed, &QToolButton::clicked, this, &LabelWidget::teXUsedChanged ); connect(ui.teLabel, &ResizableTextEdit::textChanged, this, &LabelWidget::textChanged); connect(ui.teLabel, &ResizableTextEdit::currentCharFormatChanged, this, &LabelWidget::charFormatChanged); connect(ui.kcbFontColor, &KColorButton::changed, this, &LabelWidget::fontColorChanged); connect(ui.kcbBackgroundColor, &KColorButton::changed, this, &LabelWidget::backgroundColorChanged); connect(ui.tbFontBold, &QToolButton::clicked, this, &LabelWidget::fontBoldChanged); connect(ui.tbFontItalic, &QToolButton::clicked, this, &LabelWidget::fontItalicChanged); connect(ui.tbFontUnderline, &QToolButton::clicked, this, &LabelWidget::fontUnderlineChanged); connect(ui.tbFontStrikeOut, &QToolButton::clicked, this, &LabelWidget::fontStrikeOutChanged); connect(ui.tbFontSuperScript, &QToolButton::clicked, this, &LabelWidget::fontSuperScriptChanged); connect(ui.tbFontSubScript, &QToolButton::clicked, this, &LabelWidget::fontSubScriptChanged); connect(ui.tbSymbols, &QToolButton::clicked, this, &LabelWidget::charMenu); connect(ui.tbDateTime, &QToolButton::clicked, this, &LabelWidget::dateTimeMenu); connect(m_dateTimeMenu, &QMenu::triggered, this, &LabelWidget::insertDateTime ); connect(ui.kfontRequester, &KFontRequester::fontSelected, this, &LabelWidget::fontChanged); connect(ui.kfontRequesterTeX, &KFontRequester::fontSelected, this, &LabelWidget::teXFontChanged); connect(ui.sbFontSize, QOverload::of(&QSpinBox::valueChanged), this, &LabelWidget::fontSizeChanged); // geometry connect( ui.cbPositionX, QOverload::of(&KComboBox::currentIndexChanged), this, &LabelWidget::positionXChanged); connect( ui.cbPositionY, QOverload::of(&KComboBox::currentIndexChanged), this, &LabelWidget::positionYChanged); connect( ui.sbPositionX, QOverload::of(&QDoubleSpinBox::valueChanged), this, &LabelWidget::customPositionXChanged); connect( ui.sbPositionY, QOverload::of(&QDoubleSpinBox::valueChanged), this, &LabelWidget::customPositionYChanged); connect( ui.cbHorizontalAlignment, QOverload::of(&KComboBox::currentIndexChanged), this, &LabelWidget::horizontalAlignmentChanged); connect( ui.cbVerticalAlignment, QOverload::of(&KComboBox::currentIndexChanged), this, &LabelWidget::verticalAlignmentChanged); connect( ui.sbRotation, QOverload::of(&QSpinBox::valueChanged), this, &LabelWidget::rotationChanged); connect( ui.sbOffsetX, QOverload::of(&QDoubleSpinBox::valueChanged), this, &LabelWidget::offsetXChanged); connect( ui.sbOffsetY, QOverload::of(&QDoubleSpinBox::valueChanged), this, &LabelWidget::offsetYChanged); connect( ui.chbVisible, &QCheckBox::clicked, this, &LabelWidget::visibilityChanged); //Border connect(ui.cbBorderShape, QOverload::of(&QComboBox::currentIndexChanged), this, &LabelWidget::borderShapeChanged); connect(ui.cbBorderStyle, QOverload::of(&QComboBox::currentIndexChanged), this, &LabelWidget::borderStyleChanged); connect(ui.kcbBorderColor, &KColorButton::changed, this, &LabelWidget::borderColorChanged); connect(ui.sbBorderWidth, QOverload::of(&QDoubleSpinBox::valueChanged), this, &LabelWidget::borderWidthChanged); connect(ui.sbBorderOpacity, QOverload::of(&QSpinBox::valueChanged), this, &LabelWidget::borderOpacityChanged); //TODO: https://bugreports.qt.io/browse/QTBUG-25420 ui.tbFontUnderline->hide(); ui.tbFontStrikeOut->hide(); } void LabelWidget::setLabels(QList labels) { m_labelsList = labels; m_label = labels.first(); ui.lOffsetX->hide(); ui.lOffsetY->hide(); ui.sbOffsetX->hide(); ui.sbOffsetY->hide(); this->load(); initConnections(); updateBackground(); } void LabelWidget::setAxes(QList axes) { m_labelsList.clear(); for (auto* axis : axes) { m_labelsList.append(axis->title()); connect(axis, &Axis::titleOffsetXChanged, this, &LabelWidget::labelOffsetxChanged); connect(axis, &Axis::titleOffsetYChanged, this, &LabelWidget::labelOffsetyChanged ); connect(axis->title(), &TextLabel::rotationAngleChanged, this, &LabelWidget::labelRotationAngleChanged ); } m_axesList = axes; m_label = m_labelsList.first(); this->load(); initConnections(); updateBackground(); } /*! * this function keeps the background color of the TextEdit in LabelWidget in sync with * the background color of the parent aspect. This is to avoid the situations where the * text wouldn't be readable anymore if the foreground color is close or equal to the * background color of TextEdit - e.g., a label with white foreground color on a dark worksheet * and with white background color in TextEdit (desktop default color). * * Called if the background color of the parent aspect has changed. */ void LabelWidget::updateBackground() const { if (ui.tbTexUsed->isChecked()) return; QColor color; AspectType type = m_label->parentAspect()->type(); if (type == AspectType::Worksheet) color = static_cast(m_label->parentAspect())->backgroundFirstColor(); else if (type == AspectType::CartesianPlot) color = static_cast(m_label->parentAspect())->plotArea()->backgroundFirstColor(); else if (type == AspectType::CartesianPlotLegend) color = static_cast(m_label->parentAspect())->backgroundFirstColor(); if (type == AspectType::Axis) color = static_cast(m_label->parentAspect()->parentAspect())->plotArea()->backgroundFirstColor(); QPalette p = ui.teLabel->palette(); p.setColor(QPalette::Base, color); ui.teLabel->setPalette(p); } void LabelWidget::initConnections() const { connect(m_label, &TextLabel::textWrapperChanged, this, &LabelWidget::labelTextWrapperChanged); connect(m_label, &TextLabel::teXImageUpdated, this, &LabelWidget::labelTeXImageUpdated); connect(m_label, &TextLabel::teXFontChanged, this, &LabelWidget::labelTeXFontChanged); connect(m_label, &TextLabel::fontColorChanged, this, &LabelWidget::labelFontColorChanged); connect(m_label, &TextLabel::backgroundColorChanged, this, &LabelWidget::labelBackgroundColorChanged); connect(m_label, &TextLabel::positionChanged, this, &LabelWidget::labelPositionChanged); connect(m_label, &TextLabel::horizontalAlignmentChanged, this, &LabelWidget::labelHorizontalAlignmentChanged); connect(m_label, &TextLabel::verticalAlignmentChanged, this, &LabelWidget::labelVerticalAlignmentChanged); connect(m_label, &TextLabel::rotationAngleChanged, this, &LabelWidget::labelRotationAngleChanged); connect(m_label, &TextLabel::borderShapeChanged, this, &LabelWidget::labelBorderShapeChanged); connect(m_label, &TextLabel::borderPenChanged, this, &LabelWidget::labelBorderPenChanged); connect(m_label, &TextLabel::borderOpacityChanged, this, &LabelWidget::labelBorderOpacityChanged); connect(m_label, &TextLabel::visibleChanged, this, &LabelWidget::labelVisibleChanged); AspectType type = m_label->parentAspect()->type(); if (type == AspectType::Worksheet) { auto* worksheet = static_cast(m_label->parentAspect()); connect(worksheet, &Worksheet::backgroundFirstColorChanged, this, &LabelWidget::updateBackground); }else if (type == AspectType::CartesianPlot) { auto* plotArea = static_cast(m_label->parentAspect())->plotArea(); connect(plotArea, &PlotArea::backgroundFirstColorChanged, this, &LabelWidget::updateBackground); } else if (type == AspectType::CartesianPlotLegend) { auto* legend = static_cast(m_label->parentAspect()); connect(legend, &CartesianPlotLegend::backgroundFirstColorChanged, this, &LabelWidget::updateBackground); } else if (type == AspectType::Axis) { auto* plotArea = static_cast(m_label->parentAspect()->parentAspect())->plotArea(); connect(plotArea, &PlotArea::backgroundFirstColorChanged, this, &LabelWidget::updateBackground); } } /*! * enables/disables the "fixed label"-mode, used when displaying * the properties of axis' title label. * In this mode, in the "geometry"-part only the offset (offset to the axis) * and the rotation of the label are available. */ void LabelWidget::setFixedLabelMode(const bool b) { ui.lPositionX->setVisible(!b); ui.cbPositionX->setVisible(!b); ui.sbPositionX->setVisible(!b); ui.lPositionY->setVisible(!b); ui.cbPositionY->setVisible(!b); ui.sbPositionY->setVisible(!b); ui.lHorizontalAlignment->setVisible(!b); ui.cbHorizontalAlignment->setVisible(!b); ui.lVerticalAlignment->setVisible(!b); ui.cbVerticalAlignment->setVisible(!b); ui.lOffsetX->setVisible(b); ui.lOffsetY->setVisible(b); ui.sbOffsetX->setVisible(b); ui.sbOffsetY->setVisible(b); } /*! * enables/disables all geometry relevant widgets. * Used when displaying legend's title label. */ void LabelWidget::setGeometryAvailable(const bool b) { ui.lGeometry->setVisible(b); ui.lPositionX->setVisible(b); ui.cbPositionX->setVisible(b); ui.sbPositionX->setVisible(b); ui.lPositionY->setVisible(b); ui.cbPositionY->setVisible(b); ui.sbPositionY->setVisible(b); ui.lHorizontalAlignment->setVisible(b); ui.cbHorizontalAlignment->setVisible(b); ui.lVerticalAlignment->setVisible(b); ui.cbVerticalAlignment->setVisible(b); ui.lOffsetX->setVisible(b); ui.lOffsetY->setVisible(b); ui.sbOffsetX->setVisible(b); ui.sbOffsetY->setVisible(b); ui.lRotation->setVisible(b); ui.sbRotation->setVisible(b); } /*! * enables/disables all border relevant widgets. * Used when displaying legend's title label. */ void LabelWidget::setBorderAvailable(bool b) { ui.lBorder->setVisible(b); ui.lBorderShape->setVisible(b); ui.cbBorderShape->setVisible(b); ui.lBorderStyle->setVisible(b); ui.cbBorderStyle->setVisible(b); ui.lBorderColor->setVisible(b); ui.kcbBorderColor->setVisible(b); ui.lBorderWidth->setVisible(b); ui.sbBorderWidth->setVisible(b); ui.lBorderOpacity->setVisible(b); ui.sbBorderOpacity->setVisible(b); } void LabelWidget::updateUnits() { const KConfigGroup group = KSharedConfig::openConfig()->group(QLatin1String("Settings_General")); BaseDock::Units units = (BaseDock::Units)group.readEntry("Units", (int)BaseDock::MetricUnits); if (units == m_units) return; m_units = units; Lock lock(m_initializing); QString suffix; if (m_units == BaseDock::MetricUnits) { //convert from imperial to metric m_worksheetUnit = Worksheet::Unit::Centimeter; - suffix = QLatin1String("cm"); + suffix = QLatin1String(" cm"); ui.sbPositionX->setValue(ui.sbPositionX->value()*2.54); ui.sbPositionY->setValue(ui.sbPositionX->value()*2.54); } else { //convert from metric to imperial m_worksheetUnit = Worksheet::Unit::Inch; - suffix = QLatin1String("in"); + suffix = QLatin1String(" in"); ui.sbPositionX->setValue(ui.sbPositionX->value()/2.54); ui.sbPositionY->setValue(ui.sbPositionY->value()/2.54); } ui.sbPositionX->setSuffix(suffix); ui.sbPositionY->setSuffix(suffix); } //********************************************************** //****** SLOTs for changes triggered in LabelWidget ******** //********************************************************** // text formatting slots void LabelWidget::textChanged() { if (m_initializing) return; const Lock lock(m_initializing); if (ui.tbTexUsed->isChecked()) { QString text = ui.teLabel->toPlainText(); TextLabel::TextWrapper wrapper(text, true); for (auto* label : m_labelsList) label->setText(wrapper); } else { //save an empty string instead of a html-string with empty body, //if no text available in QTextEdit QString text; if (!ui.teLabel->toPlainText().isEmpty()) { //if the current label text is empty, set the color first if (m_label->text().text.isEmpty()) { ui.teLabel->selectAll(); ui.teLabel->setTextColor(m_label->fontColor()); } text = ui.teLabel->toHtml(); } TextLabel::TextWrapper wrapper(text, false, true); for (auto* label : m_labelsList) label->setText(wrapper); } //background color gets lost on every text change... updateBackground(); } /*! * \brief LabelWidget::charFormatChanged * \param format * Used to update the colors, font,... in the color font widgets to show the style of the selected text */ void LabelWidget::charFormatChanged(const QTextCharFormat& format) { if (m_initializing) return; if (ui.tbTexUsed->isChecked()) return; const Lock lock(m_initializing); // update button state ui.tbFontBold->setChecked(ui.teLabel->fontWeight() == QFont::Bold); ui.tbFontItalic->setChecked(ui.teLabel->fontItalic()); ui.tbFontUnderline->setChecked(ui.teLabel->fontUnderline()); ui.tbFontStrikeOut->setChecked(format.fontStrikeOut()); ui.tbFontSuperScript->setChecked(format.verticalAlignment() == QTextCharFormat::AlignSuperScript); ui.tbFontSubScript->setChecked(format.verticalAlignment() == QTextCharFormat::AlignSubScript); //font and colors if (format.foreground().color().isValid()) ui.kcbFontColor->setColor(format.foreground().color()); else ui.kcbFontColor->setColor(m_label->fontColor()); if (format.background().color().isValid()) ui.kcbBackgroundColor->setColor(format.background().color()); else ui.kcbBackgroundColor->setColor(m_label->backgroundColor()); ui.kfontRequester->setFont(format.font()); } void LabelWidget::teXUsedChanged(bool checked) { //hide text editing elements if TeX-option is used ui.tbFontBold->setVisible(!checked); ui.tbFontItalic->setVisible(!checked); //TODO: https://bugreports.qt.io/browse/QTBUG-25420 // ui.tbFontUnderline->setVisible(!checked); // ui.tbFontStrikeOut->setVisible(!checked); ui.tbFontSubScript->setVisible(!checked); ui.tbFontSuperScript->setVisible(!checked); ui.tbSymbols->setVisible(!checked); ui.lFont->setVisible(!checked); ui.kfontRequester->setVisible(!checked); //TODO: //for normal text we need to hide the background color because of QTBUG-25420 ui.kcbBackgroundColor->setVisible(checked); ui.lBackgroundColor->setVisible(checked); if (checked) { ui.tbTexUsed->setToolTip(i18n("Switch to TeX mode")); //reset all applied formattings when switching from html to tex mode QTextCursor cursor = ui.teLabel->textCursor(); int position = cursor.position(); ui.teLabel->selectAll(); QTextCharFormat format; ui.teLabel->setCurrentCharFormat(format); cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, position); ui.teLabel->setTextCursor(cursor); #ifdef HAVE_KF5_SYNTAX_HIGHLIGHTING m_highlighter->setDocument(ui.teLabel->document()); #endif KConfigGroup conf(KSharedConfig::openConfig(), QLatin1String("Settings_Worksheet")); QString engine = conf.readEntry(QLatin1String("LaTeXEngine"), ""); if (engine == QLatin1String("xelatex") || engine == QLatin1String("lualatex")) { ui.lFontTeX->setVisible(true); ui.kfontRequesterTeX->setVisible(true); ui.lFontSize->setVisible(false); ui.sbFontSize->setVisible(false); } else { ui.lFontTeX->setVisible(false); ui.kfontRequesterTeX->setVisible(false); ui.lFontSize->setVisible(true); ui.sbFontSize->setVisible(true); } //update TeX colors ui.kcbFontColor->setColor(m_label->fontColor()); ui.kcbBackgroundColor->setColor(m_label->backgroundColor()); } else { ui.tbTexUsed->setToolTip(i18n("Switch to text mode")); #ifdef HAVE_KF5_SYNTAX_HIGHLIGHTING m_highlighter->setDocument(nullptr); #endif ui.lFontTeX->setVisible(false); ui.kfontRequesterTeX->setVisible(false); ui.lFontSize->setVisible(false); ui.sbFontSize->setVisible(false); //when switching to the text mode, set the background color to white just for the case the latex code provided by the user //in the TeX-mode is not valid and the background was set to red (s.a. LabelWidget::labelTeXImageUpdated()) ui.teLabel->setStyleSheet(QString()); } //no latex is available and the user switched to the text mode, //deactivate the button since it shouldn't be possible anymore to switch to the TeX-mode if (!m_teXEnabled && !checked) { ui.tbTexUsed->setEnabled(false); ui.tbTexUsed->setToolTip(i18n("LaTeX typesetting not possible. Please check the settings.")); } else ui.tbTexUsed->setEnabled(true); if (m_initializing) return; QString text = checked ? ui.teLabel->toPlainText() : ui.teLabel->toHtml(); TextLabel::TextWrapper wrapper(text, checked); for (auto* label : m_labelsList) label->setText(wrapper); } void LabelWidget::fontColorChanged(const QColor& color) { if (m_initializing) return; QTextCursor c = ui.teLabel->textCursor(); if (c.selectedText().isEmpty()) ui.teLabel->selectAll(); ui.teLabel->setTextColor(color); } void LabelWidget::backgroundColorChanged(const QColor& color) { if (m_initializing) return; if (!m_teXEnabled && m_label->text().teXUsed) { QTextCursor c = ui.teLabel->textCursor(); if (c.selectedText().isEmpty()) ui.teLabel->selectAll(); ui.teLabel->setTextBackgroundColor(color); } else { // Latex text does not support html code. For this the backgroundColor variable is used // Only single color background is supported for (auto* label : m_labelsList) label->setBackgroundColor(color); } } void LabelWidget::fontSizeChanged(int value) { if (m_initializing) return; QFont font = m_label->teXFont(); font.setPointSize(value); for (auto* label : m_labelsList) label->setTeXFont(font); } void LabelWidget::fontBoldChanged(bool checked) { if (m_initializing) return; QTextCursor c = ui.teLabel->textCursor(); if (c.selectedText().isEmpty()) ui.teLabel->selectAll(); if (checked) ui.teLabel->setFontWeight(QFont::Bold); else ui.teLabel->setFontWeight(QFont::Normal); } void LabelWidget::fontItalicChanged(bool checked) { if (m_initializing) return; QTextCursor c = ui.teLabel->textCursor(); if (c.selectedText().isEmpty()) ui.teLabel->selectAll(); ui.teLabel->setFontItalic(checked); } void LabelWidget::fontUnderlineChanged(bool checked) { if (m_initializing) return; QTextCursor c = ui.teLabel->textCursor(); if (c.selectedText().isEmpty()) ui.teLabel->selectAll(); ui.teLabel->setFontUnderline(checked); } void LabelWidget::fontStrikeOutChanged(bool checked) { if (m_initializing) return; QTextCursor c = ui.teLabel->textCursor(); if (c.selectedText().isEmpty()) ui.teLabel->selectAll(); QTextCharFormat format = ui.teLabel->currentCharFormat(); format.setFontStrikeOut(checked); ui.teLabel->setCurrentCharFormat(format); } void LabelWidget::fontSuperScriptChanged(bool checked) { if (m_initializing) return; QTextCursor c = ui.teLabel->textCursor(); if (c.selectedText().isEmpty()) ui.teLabel->selectAll(); QTextCharFormat format = ui.teLabel->currentCharFormat(); if (checked) format.setVerticalAlignment(QTextCharFormat::AlignSuperScript); else format.setVerticalAlignment(QTextCharFormat::AlignNormal); ui.teLabel->setCurrentCharFormat(format); } void LabelWidget::fontSubScriptChanged(bool checked) { if (m_initializing) return; QTextCursor c = ui.teLabel->textCursor(); if (c.selectedText().isEmpty()) ui.teLabel->selectAll(); QTextCharFormat format = ui.teLabel->currentCharFormat(); if (checked) format.setVerticalAlignment(QTextCharFormat::AlignSubScript); else format.setVerticalAlignment(QTextCharFormat::AlignNormal); ui.teLabel->setCurrentCharFormat(format); } void LabelWidget::fontChanged(const QFont& font) { if (m_initializing) return; QTextCursor c = ui.teLabel->textCursor(); if (c.selectedText().isEmpty()) ui.teLabel->selectAll(); // use format instead of using ui.teLabel->setFontFamily(font.family()); // because this calls after every command textChanged() which is inefficient QTextCharFormat format; format.setFontFamily(font.family()); format.setFontPointSize(font.pointSize()); format.setFontItalic(font.italic()); format.setFontWeight(font.weight()); if (font.underline()) format.setUnderlineStyle(QTextCharFormat::UnderlineStyle::SingleUnderline); if (font.strikeOut()) // anytime true. don't know why format.setFontStrikeOut(font.strikeOut()); ui.teLabel->mergeCurrentCharFormat(format); } void LabelWidget::teXFontChanged(const QFont& font) { if (m_initializing) return; for (auto* label : m_labelsList) label->setTeXFont(font); } void LabelWidget::charMenu() { QMenu menu; KCharSelect selection(this, nullptr, KCharSelect::SearchLine | KCharSelect::CharacterTable | KCharSelect::BlockCombos | KCharSelect::HistoryButtons); QFont font = ui.teLabel->currentFont(); // use the system default size, otherwise the symbols might be hard to read // if the current label font size is too small font.setPointSize(QFont().pointSize()); selection.setCurrentFont(font); connect(&selection, &KCharSelect::charSelected, this, &LabelWidget::insertChar); connect(&selection, &KCharSelect::charSelected, &menu, &LabelWidget::close); auto* widgetAction = new QWidgetAction(this); widgetAction->setDefaultWidget(&selection); menu.addAction(widgetAction); QPoint pos(-menu.sizeHint().width()+ui.tbSymbols->width(),-menu.sizeHint().height()); menu.exec(ui.tbSymbols->mapToGlobal(pos)); } void LabelWidget::insertChar(QChar c) { ui.teLabel->insertPlainText(QString(c)); } void LabelWidget::dateTimeMenu() { m_dateTimeMenu->clear(); const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); const QString configFile = configPath + QLatin1String("/klanguageoverridesrc"); if (!QFile::exists(configFile)) { QDate date = QDate::currentDate(); m_dateTimeMenu->addSeparator()->setText(i18n("Date")); m_dateTimeMenu->addAction( date.toString(Qt::TextDate) ); m_dateTimeMenu->addAction( date.toString(Qt::ISODate) ); m_dateTimeMenu->addAction( date.toString(Qt::SystemLocaleShortDate) ); m_dateTimeMenu->addAction( date.toString(Qt::SystemLocaleLongDate) ); m_dateTimeMenu->addAction( date.toString(Qt::RFC2822Date) ); QDateTime time = QDateTime::currentDateTime(); m_dateTimeMenu->addSeparator()->setText(i18n("Date and Time")); m_dateTimeMenu->addAction( time.toString(Qt::TextDate) ); m_dateTimeMenu->addAction( time.toString(Qt::ISODate) ); m_dateTimeMenu->addAction( time.toString(Qt::SystemLocaleShortDate) ); m_dateTimeMenu->addAction( time.toString(Qt::SystemLocaleLongDate) ); m_dateTimeMenu->addAction( time.toString(Qt::RFC2822Date) ); } else { //application language was changed: //determine the currently used language and use QLocale::toString() //to get the strings translated into the currently used language QSettings settings (configFile, QSettings::IniFormat); settings.beginGroup(QLatin1String("Language")); QByteArray languageCode; languageCode = settings.value(qAppName(), languageCode).toByteArray(); QLocale locale(QString::fromLatin1(languageCode.data())); QDate date = QDate::currentDate(); m_dateTimeMenu->addSeparator()->setText(i18n("Date")); m_dateTimeMenu->addAction( locale.toString(date, QLatin1String("ddd MMM d yyyy")) ); //Qt::TextDate m_dateTimeMenu->addAction( locale.toString(date, QLatin1String("yyyy-MM-dd")) ); //Qt::ISODate m_dateTimeMenu->addAction( locale.system().toString(date, QLocale::ShortFormat) ); //Qt::SystemLocaleShortDate //no LongFormat here since it would contain strings in system's language which (potentially) is not the current application language m_dateTimeMenu->addAction( locale.toString(date, QLatin1String("dd MMM yyyy")) ); //Qt::RFC2822Date QDateTime time = QDateTime::currentDateTime(); m_dateTimeMenu->addSeparator()->setText(i18n("Date and Time")); m_dateTimeMenu->addAction( locale.toString(time, QLatin1String("ddd MMM d hh:mm:ss yyyy")) ); //Qt::TextDate m_dateTimeMenu->addAction( locale.toString(time, QLatin1String("yyyy-MM-ddTHH:mm:ss")) ); //Qt::ISODate m_dateTimeMenu->addAction( locale.system().toString(time, QLocale::ShortFormat) ); //Qt::SystemLocaleShortDate //no LongFormat here since it would contain strings in system's language which (potentially) is not the current application language //TODO: RFC2822 requires time zone but Qt QLocale::toString() seems to ignore TZD (time zone designator) completely, //which works correctly with QDateTime::toString() m_dateTimeMenu->addAction( locale.toString(time, QLatin1String("dd MMM yyyy hh:mm:ss")) ); //Qt::RFC2822Date } m_dateTimeMenu->exec( mapToGlobal(ui.tbDateTime->rect().bottomLeft())); } void LabelWidget::insertDateTime(QAction* action) { ui.teLabel->insertPlainText( action->text().remove('&') ); } // geometry slots /*! called when label's current horizontal position relative to its parent (left, center, right, custom ) is changed. */ void LabelWidget::positionXChanged(int index) { //Enable/disable the spinbox for the x- oordinates if the "custom position"-item is selected/deselected if (index == ui.cbPositionX->count()-1 ) ui.sbPositionX->setEnabled(true); else ui.sbPositionX->setEnabled(false); if (m_initializing) return; TextLabel::PositionWrapper position = m_label->position(); position.horizontalPosition = TextLabel::HorizontalPosition(index); for (auto* label : m_labelsList) label->setPosition(position); } /*! called when label's current horizontal position relative to its parent (top, center, bottom, custom ) is changed. */ void LabelWidget::positionYChanged(int index) { //Enable/disable the spinbox for the y-coordinates if the "custom position"-item is selected/deselected if (index == ui.cbPositionY->count()-1 ) ui.sbPositionY->setEnabled(true); else ui.sbPositionY->setEnabled(false); if (m_initializing) return; TextLabel::PositionWrapper position = m_label->position(); position.verticalPosition = TextLabel::VerticalPosition(index); for (auto* label : m_labelsList) label->setPosition(position); } void LabelWidget::customPositionXChanged(double value) { if (m_initializing) return; TextLabel::PositionWrapper position = m_label->position(); position.point.setX(Worksheet::convertToSceneUnits(value, m_worksheetUnit)); for (auto* label : m_labelsList) label->setPosition(position); } void LabelWidget::customPositionYChanged(double value) { if (m_initializing) return; TextLabel::PositionWrapper position = m_label->position(); position.point.setY(Worksheet::convertToSceneUnits(value, m_worksheetUnit)); for (auto* label : m_labelsList) label->setPosition(position); } void LabelWidget::horizontalAlignmentChanged(int index) { if (m_initializing) return; for (auto* label : m_labelsList) label->setHorizontalAlignment(TextLabel::HorizontalAlignment(index)); } void LabelWidget::verticalAlignmentChanged(int index) { if (m_initializing) return; for (auto* label : m_labelsList) label->setVerticalAlignment(TextLabel::VerticalAlignment(index)); } void LabelWidget::rotationChanged(int value) { if (m_initializing) return; for (auto* label : m_labelsList) label->setRotationAngle(value); } void LabelWidget::offsetXChanged(double value) { if (m_initializing) return; for (auto* axis : m_axesList) axis->setTitleOffsetX( Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point) ); } void LabelWidget::offsetYChanged(double value) { if (m_initializing) return; for (auto* axis : m_axesList) axis->setTitleOffsetY( Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point) ); } void LabelWidget::visibilityChanged(bool state) { if (m_initializing) return; for (auto* label : m_labelsList) label->setVisible(state); } //border void LabelWidget::borderShapeChanged(int index) { auto shape = (TextLabel::BorderShape)index; bool b = (shape != TextLabel::BorderShape::NoBorder); ui.lBorderStyle->setVisible(b); ui.cbBorderStyle->setVisible(b); ui.lBorderWidth->setVisible(b); ui.sbBorderWidth->setVisible(b); ui.lBorderColor->setVisible(b); ui.kcbBorderColor->setVisible(b); ui.lBorderOpacity->setVisible(b); ui.sbBorderOpacity->setVisible(b); if (m_initializing) return; for (auto* label : m_labelsList) label->setBorderShape(shape); } void LabelWidget::borderStyleChanged(int index) { if (m_initializing) return; auto penStyle = Qt::PenStyle(index); QPen pen; for (auto* label : m_labelsList) { pen = label->borderPen(); pen.setStyle(penStyle); label->setBorderPen(pen); } } void LabelWidget::borderColorChanged(const QColor& color) { if (m_initializing) return; QPen pen; for (auto* label : m_labelsList) { pen = label->borderPen(); pen.setColor(color); label->setBorderPen(pen); } m_initializing = true; GuiTools::updatePenStyles(ui.cbBorderStyle, color); m_initializing = false; } void LabelWidget::borderWidthChanged(double value) { if (m_initializing) return; QPen pen; for (auto* label : m_labelsList) { pen = label->borderPen(); pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point) ); label->setBorderPen(pen); } } void LabelWidget::borderOpacityChanged(int value) { if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* label : m_labelsList) label->setBorderOpacity(opacity); } //********************************************************* //****** SLOTs for changes triggered in TextLabel ********* //********************************************************* void LabelWidget::labelTextWrapperChanged(const TextLabel::TextWrapper& text) { if (m_initializing)return; const Lock lock(m_initializing); //save and restore the current cursor position after changing the text QTextCursor cursor = ui.teLabel->textCursor(); int position = cursor.position(); if (text.teXUsed) ui.teLabel->setText(text.text); else ui.teLabel->setHtml(text.text); cursor.movePosition(QTextCursor::Start); cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, position); ui.teLabel->setTextCursor(cursor); ui.tbTexUsed->setChecked(text.teXUsed); this->teXUsedChanged(text.teXUsed); } /*! * \brief Highlights the text field red if wrong latex syntax was used (null image was produced) * or something else went wrong during rendering (\sa ExpressionTextEdit::validateExpression()) */ void LabelWidget::labelTeXImageUpdated(bool valid) { if (!valid) { if (ui.teLabel->styleSheet().isEmpty()) ui.teLabel->setStyleSheet(QLatin1String("QTextEdit{background: red;}")); } else ui.teLabel->setStyleSheet(QString()); } void LabelWidget::labelTeXFontChanged(const QFont& font) { m_initializing = true; ui.kfontRequesterTeX->setFont(font); ui.sbFontSize->setValue(font.pointSize()); m_initializing = false; } void LabelWidget::labelFontColorChanged(const QColor color) { // this function is only called when the theme is changed. Otherwise the color // is directly in the html text. // when the theme changes, the hole text should change color regardless of the color it has m_initializing = true; ui.kcbFontColor->setColor(color); ui.teLabel->selectAll(); ui.teLabel->setTextColor(color); m_initializing = false; } void LabelWidget::labelPositionChanged(const TextLabel::PositionWrapper& position) { m_initializing = true; ui.sbPositionX->setValue( Worksheet::convertFromSceneUnits(position.point.x(), m_worksheetUnit) ); ui.sbPositionY->setValue( Worksheet::convertFromSceneUnits(position.point.y(), m_worksheetUnit) ); ui.cbPositionX->setCurrentIndex( static_cast(position.horizontalPosition) ); ui.cbPositionY->setCurrentIndex( static_cast(position.verticalPosition) ); m_initializing = false; } void LabelWidget::labelBackgroundColorChanged(const QColor color) { m_initializing = true; ui.kcbBackgroundColor->setColor(color); m_initializing = false; } void LabelWidget::labelHorizontalAlignmentChanged(TextLabel::HorizontalAlignment index) { m_initializing = true; ui.cbHorizontalAlignment->setCurrentIndex(static_cast(index)); m_initializing = false; } void LabelWidget::labelVerticalAlignmentChanged(TextLabel::VerticalAlignment index) { m_initializing = true; ui.cbVerticalAlignment->setCurrentIndex(static_cast(index)); m_initializing = false; } void LabelWidget::labelOffsetxChanged(qreal offset) { m_initializing = true; ui.sbOffsetX->setValue(Worksheet::convertFromSceneUnits(offset, Worksheet::Unit::Point)); m_initializing = false; } void LabelWidget::labelOffsetyChanged(qreal offset) { m_initializing = true; ui.sbOffsetY->setValue(Worksheet::convertFromSceneUnits(offset, Worksheet::Unit::Point)); m_initializing = false; } void LabelWidget::labelRotationAngleChanged(qreal angle) { m_initializing = true; ui.sbRotation->setValue(angle); m_initializing = false; } void LabelWidget::labelVisibleChanged(bool on) { m_initializing = true; ui.chbVisible->setChecked(on); m_initializing = false; } //border void LabelWidget::labelBorderShapeChanged(TextLabel::BorderShape shape) { m_initializing = true; ui.cbBorderShape->setCurrentIndex(static_cast(shape)); m_initializing = false; } void LabelWidget::labelBorderPenChanged(const QPen& pen) { m_initializing = true; if (ui.cbBorderStyle->currentIndex() != pen.style()) ui.cbBorderStyle->setCurrentIndex(pen.style()); if (ui.kcbBorderColor->color() != pen.color()) ui.kcbBorderColor->setColor(pen.color()); if (ui.sbBorderWidth->value() != pen.widthF()) ui.sbBorderWidth->setValue(Worksheet::convertFromSceneUnits(pen.widthF(), Worksheet::Unit::Point)); m_initializing = false; } void LabelWidget::labelBorderOpacityChanged(float value) { m_initializing = true; float v = (float)value*100.; ui.sbBorderOpacity->setValue(v); m_initializing = false; } //********************************************************** //******************** SETTINGS **************************** //********************************************************** void LabelWidget::load() { if (!m_label) return; m_initializing = true; ui.chbVisible->setChecked(m_label->isVisible()); //Text/TeX ui.tbTexUsed->setChecked( (bool) m_label->text().teXUsed ); if (m_label->text().teXUsed) ui.teLabel->setText(m_label->text().text); else { ui.teLabel->setHtml(m_label->text().text); ui.teLabel->selectAll(); // must be done to retrieve font ui.kfontRequester->setFont(ui.teLabel->currentFont()); } // if the text is empty yet, user LabelWidget::fontColor(), //extract the color from the html formatted text otherwise if (!m_label->text().text.isEmpty()) { QTextCharFormat format = ui.teLabel->currentCharFormat(); ui.kcbFontColor->setColor(format.foreground().color()); //ui.kcbBackgroundColor->setColor(format.background().color()); } else ui.kcbFontColor->setColor(m_label->fontColor()); //used for latex text only ui.kcbBackgroundColor->setColor(m_label->backgroundColor()); this->teXUsedChanged(m_label->text().teXUsed); ui.kfontRequesterTeX->setFont(m_label->teXFont()); ui.sbFontSize->setValue( m_label->teXFont().pointSize() ); //move the cursor to the end and set the focus to the text editor QTextCursor cursor = ui.teLabel->textCursor(); cursor.movePosition(QTextCursor::End); ui.teLabel->setTextCursor(cursor); ui.teLabel->setFocus(); // Geometry ui.cbPositionX->setCurrentIndex( (int)m_label->position().horizontalPosition ); positionXChanged(ui.cbPositionX->currentIndex()); ui.sbPositionX->setValue( Worksheet::convertFromSceneUnits(m_label->position().point.x(), m_worksheetUnit) ); ui.cbPositionY->setCurrentIndex( (int)m_label->position().verticalPosition ); positionYChanged(ui.cbPositionY->currentIndex()); ui.sbPositionY->setValue( Worksheet::convertFromSceneUnits(m_label->position().point.y(), m_worksheetUnit) ); if (!m_axesList.isEmpty()) { ui.sbOffsetX->setValue( Worksheet::convertFromSceneUnits(m_axesList.first()->titleOffsetX(), Worksheet::Unit::Point) ); ui.sbOffsetY->setValue( Worksheet::convertFromSceneUnits(m_axesList.first()->titleOffsetY(), Worksheet::Unit::Point) ); } ui.cbHorizontalAlignment->setCurrentIndex( (int) m_label->horizontalAlignment() ); ui.cbVerticalAlignment->setCurrentIndex( (int) m_label->verticalAlignment() ); ui.sbRotation->setValue( m_label->rotationAngle() ); //Border ui.cbBorderShape->setCurrentIndex(static_cast(m_label->borderShape())); ui.kcbBorderColor->setColor( m_label->borderPen().color() ); ui.cbBorderStyle->setCurrentIndex( (int) m_label->borderPen().style() ); ui.sbBorderWidth->setValue( Worksheet::convertFromSceneUnits(m_label->borderPen().widthF(), Worksheet::Unit::Point) ); ui.sbBorderOpacity->setValue( round(m_label->borderOpacity()*100) ); GuiTools::updatePenStyles(ui.cbBorderStyle, ui.kcbBorderColor->color()); m_initializing = false; } void LabelWidget::loadConfig(KConfigGroup& group) { if (!m_label) return; m_initializing = true; //TeX ui.tbTexUsed->setChecked(group.readEntry("TeXUsed", (bool) m_label->text().teXUsed)); this->teXUsedChanged(m_label->text().teXUsed); ui.sbFontSize->setValue( group.readEntry("TeXFontSize", m_label->teXFont().pointSize()) ); ui.kfontRequesterTeX->setFont(group.readEntry("TeXFont", m_label->teXFont())); // Geometry ui.cbPositionX->setCurrentIndex( group.readEntry("PositionX", (int) m_label->position().horizontalPosition ) ); ui.sbPositionX->setValue( Worksheet::convertFromSceneUnits(group.readEntry("PositionXValue", m_label->position().point.x()), m_worksheetUnit) ); ui.cbPositionY->setCurrentIndex( group.readEntry("PositionY", (int) m_label->position().verticalPosition ) ); ui.sbPositionY->setValue( Worksheet::convertFromSceneUnits(group.readEntry("PositionYValue", m_label->position().point.y()), m_worksheetUnit) ); if (!m_axesList.isEmpty()) { ui.sbOffsetX->setValue( Worksheet::convertFromSceneUnits(group.readEntry("OffsetX", m_axesList.first()->titleOffsetX()), Worksheet::Unit::Point) ); ui.sbOffsetY->setValue( Worksheet::convertFromSceneUnits(group.readEntry("OffsetY", m_axesList.first()->titleOffsetY()), Worksheet::Unit::Point) ); } ui.cbHorizontalAlignment->setCurrentIndex( group.readEntry("HorizontalAlignment", (int) m_label->horizontalAlignment()) ); ui.cbVerticalAlignment->setCurrentIndex( group.readEntry("VerticalAlignment", (int) m_label->verticalAlignment()) ); ui.sbRotation->setValue( group.readEntry("Rotation", m_label->rotationAngle()) ); //Border ui.cbBorderShape->setCurrentIndex(group.readEntry("BorderShape").toInt()); ui.kcbBorderColor->setColor( group.readEntry("BorderColor", m_label->borderPen().color()) ); ui.cbBorderStyle->setCurrentIndex( group.readEntry("BorderStyle", (int)m_label->borderPen().style()) ); ui.sbBorderWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("BorderWidth", m_label->borderPen().widthF()), Worksheet::Unit::Point) ); ui.sbBorderOpacity->setValue( group.readEntry("BorderOpacity", m_label->borderOpacity())*100 ); m_initializing = false; } void LabelWidget::saveConfig(KConfigGroup& group) { //TeX group.writeEntry("TeXUsed", ui.tbTexUsed->isChecked()); group.writeEntry("TeXFontColor", ui.kcbFontColor->color()); group.writeEntry("TeXBackgroundColor", ui.kcbBackgroundColor->color()); group.writeEntry("TeXFont", ui.kfontRequesterTeX->font()); // Geometry group.writeEntry("PositionX", ui.cbPositionX->currentIndex()); group.writeEntry("PositionXValue", Worksheet::convertToSceneUnits(ui.sbPositionX->value(),m_worksheetUnit) ); group.writeEntry("PositionY", ui.cbPositionY->currentIndex()); group.writeEntry("PositionYValue", Worksheet::convertToSceneUnits(ui.sbPositionY->value(),m_worksheetUnit) ); if (!m_axesList.isEmpty()) { group.writeEntry("OffsetX", Worksheet::convertToSceneUnits(ui.sbOffsetX->value(), Worksheet::Unit::Point) ); group.writeEntry("OffsetY", Worksheet::convertToSceneUnits(ui.sbOffsetY->value(), Worksheet::Unit::Point) ); } group.writeEntry("HorizontalAlignment", ui.cbHorizontalAlignment->currentIndex()); group.writeEntry("VerticalAlignment", ui.cbVerticalAlignment->currentIndex()); group.writeEntry("Rotation", ui.sbRotation->value()); //Border group.writeEntry("BorderShape", ui.cbBorderShape->currentIndex()); group.writeEntry("BorderStyle", ui.cbBorderStyle->currentIndex()); group.writeEntry("BorderColor", ui.kcbBorderColor->color()); group.writeEntry("BorderWidth", Worksheet::convertToSceneUnits(ui.sbBorderWidth->value(), Worksheet::Unit::Point)); group.writeEntry("BorderOpacity", ui.sbBorderOpacity->value()/100.0); }