diff --git a/src/backend/core/Project.cpp b/src/backend/core/Project.cpp index 916653615..03d98c089 100644 --- a/src/backend/core/Project.cpp +++ b/src/backend/core/Project.cpp @@ -1,506 +1,507 @@ /*************************************************************************** File : Project.cpp Project : LabPlot Description : Represents a LabPlot project. -------------------------------------------------------------------- Copyright : (C) 2011-2014 Alexander Semke (alexander.semke@web.de) Copyright : (C) 2007-2008 Tilman Benkert (thzs@gmx.net) Copyright : (C) 2007 Knut Franke (knut.franke@gmx.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 "backend/core/Project.h" #include "backend/lib/XmlStreamReader.h" #include "backend/datasources/LiveDataSource.h" #include "backend/spreadsheet/Spreadsheet.h" #include "backend/worksheet/Worksheet.h" #include "backend/worksheet/plots/cartesian/CartesianPlot.h" #include "backend/worksheet/plots/cartesian/XYEquationCurve.h" #include "backend/worksheet/plots/cartesian/XYDataReductionCurve.h" #include "backend/worksheet/plots/cartesian/XYDifferentiationCurve.h" #include "backend/worksheet/plots/cartesian/XYIntegrationCurve.h" #include "backend/worksheet/plots/cartesian/XYInterpolationCurve.h" #include "backend/worksheet/plots/cartesian/XYSmoothCurve.h" #include "backend/worksheet/plots/cartesian/XYFitCurve.h" #include "backend/worksheet/plots/cartesian/XYFourierFilterCurve.h" #include "backend/worksheet/plots/cartesian/XYFourierTransformCurve.h" #include "backend/worksheet/plots/cartesian/Axis.h" #include "backend/worksheet/plots/3d/Surface3D.h" #include "backend/worksheet/plots/3d/Curve3D.h" #include "backend/matrix/Matrix.h" #include "backend/datapicker/DatapickerCurve.h" #include #include #include #include #include #include #include #include #include #include /** * \class Project * \brief Represents a project. * \ingroup core * Project represents the root node of all objects created during the runtime of the program. * Manages also the undo stack. */ /** * \enum Project::MdiWindowVisibility * \brief MDI subwindow visibility setting */ /** * \var Project::folderOnly * \brief only show MDI windows corresponding to Parts in the current folder */ /** * \var Project::foldAndSubfolders * \brief show MDI windows corresponding to Parts in the current folder and its subfolders */ /** * \var Project::allMdiWindows * \brief show MDI windows for all Parts in the project simultaneously */ class Project::Private { public: Private() : mdiWindowVisibility(Project::folderOnly), scriptingEngine(0), version(LVERSION), author(QString(qgetenv("USER"))), modificationTime(QDateTime::currentDateTime()), changed(false), loading(false) { } QUndoStack undo_stack; MdiWindowVisibility mdiWindowVisibility; AbstractScriptingEngine* scriptingEngine; QString fileName; QString version; QString author; QDateTime modificationTime; bool changed; bool loading; }; Project::Project() : Folder(i18n("Project")), d(new Private()) { //load default values for name, comment and author from config KConfig config; KConfigGroup group = config.group("Project"); d->author = group.readEntry("Author", QString()); //we don't have direct access to the members name and comment //->temporaly disable the undo stack and call the setters setUndoAware(false); d->loading = true; setName(group.readEntry("Name", i18n("Project"))); setComment(group.readEntry("Comment", QString())); setUndoAware(true); d->loading = false; d->changed = false; // TODO: intelligent engine choosing // Q_ASSERT(ScriptingEngineManager::instance()->engineNames().size() > 0); // QString engine_name = ScriptingEngineManager::instance()->engineNames()[0]; // d->scriptingEngine = ScriptingEngineManager::instance()->engine(engine_name); connect(this, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)),this, SLOT(descriptionChanged(const AbstractAspect*))); } Project::~Project() { //if the project is being closed and the live data sources still continue reading the data, //the dependend objects (columns, etc.), which are already deleted maybe here, are still being notified about the changes. //->stop reading the live data sources prior to deleting all objects. for (auto* lds : children()) lds->pauseReading(); //if the project is being closed, in Worksheet the scene items are being removed and the selection in the view can change. //don't react on these changes since this can lead crashes (worksheet object is already in the destructor). //->notify all worksheets about the project being closed. for (auto* w : children()) w->setIsClosing(); d->undo_stack.clear(); delete d; } QUndoStack* Project::undoStack() const { return &d->undo_stack; } QMenu* Project::createContextMenu() { QMenu* menu = new QMenu(); // no remove action from AbstractAspect in the project context menu emit requestProjectContextMenu(menu); return menu; } QMenu* Project::createFolderContextMenu(const Folder* folder) { QMenu* menu = const_cast(folder)->AbstractAspect::createContextMenu(); Q_ASSERT(menu); emit requestFolderContextMenu(folder, menu); return menu; } void Project::setMdiWindowVisibility(MdiWindowVisibility visibility) { d->mdiWindowVisibility = visibility; emit mdiWindowVisibilityChanged(); } Project::MdiWindowVisibility Project::mdiWindowVisibility() const { return d->mdiWindowVisibility; } AbstractScriptingEngine* Project::scriptingEngine() const { return d->scriptingEngine; } CLASS_D_ACCESSOR_IMPL(Project, QString, fileName, FileName, fileName) BASIC_D_ACCESSOR_IMPL(Project, QString, version, Version, version) CLASS_D_ACCESSOR_IMPL(Project, QString, author, Author, author) CLASS_D_ACCESSOR_IMPL(Project, QDateTime, modificationTime, ModificationTime, modificationTime) void Project::setChanged(const bool value) { if (d->loading) return; if (value) emit changed(); d->changed = value; } bool Project ::hasChanged() const { return d->changed ; } void Project::descriptionChanged(const AbstractAspect* aspect) { if (d->loading) return; if (this!=aspect) return; d->changed = true; emit changed(); } void Project::navigateTo(const QString& path) { requestNavigateTo(path); } bool Project::isLoading() const { return d->loading; } //############################################################################## //################## Serialization/Deserialization ########################### //############################################################################## /** * \brief Save as XML */ void Project::save(QXmlStreamWriter* writer) const { //set the version and the modification time to the current values d->version = LVERSION; d->modificationTime = QDateTime::currentDateTime(); writer->setAutoFormatting(true); writer->writeStartDocument(); writer->writeDTD(""); writer->writeStartElement("project"); writer->writeAttribute("version", version()); writer->writeAttribute("fileName", fileName()); writer->writeAttribute("modificationTime", modificationTime().toString("yyyy-dd-MM hh:mm:ss:zzz")); writer->writeAttribute("author", author()); writeBasicAttributes(writer); writeCommentElement(writer); //save all children for (auto* child : children(IncludeHidden)) { writer->writeStartElement("child_aspect"); child->save(writer); writer->writeEndElement(); } //save the state of the views (visible, maximized/minimized/geometry) //and the state of the project explorer (expanded items, currently selected item) emit requestSaveState(writer); writer->writeEndElement(); writer->writeEndDocument(); } bool Project::load(const QString& filename, bool preview) { QIODevice *file; // first try gzip compression, because projects can be gzipped and end with .lml if (filename.endsWith(QLatin1String(".lml"), Qt::CaseInsensitive)) file = new KCompressionDevice(filename,KFilterDev::compressionTypeForMimeType("application/x-gzip")); else // opens filename using file ending file = new KFilterDev(filename); if (file == 0) file = new QFile(filename); if (!file->open(QIODevice::ReadOnly)) { KMessageBox::error(0, i18n("Sorry. Could not open file for reading.")); return false; } char c; const bool rc = file->getChar(&c); if (!rc) { KMessageBox::error(0, i18n("The project file is empty."), i18n("Error opening project")); file->close(); delete file; return false; } file->seek(0); //parse XML XmlStreamReader reader(file); if (this->load(&reader, preview) == false) { RESET_CURSOR; QString msg_text = reader.errorString(); KMessageBox::error(0, msg_text, i18n("Error when opening the project")); return false; } if (reader.hasWarnings()) { QString msg = i18n("The following problems occurred when loading the project file:\n"); const QStringList& warnings = reader.warningStrings(); foreach (const QString& str, warnings) msg += str + '\n'; qWarning() << msg; //TODO: show warnings in a kind of "log window" but not in message box // KMessageBox::error(this, msg, i18n("Project loading partly failed")); } file->close(); delete file; return true; } /** * \brief Load from XML */ bool Project::load(XmlStreamReader* reader, bool preview) { d->loading = true; while (!(reader->isStartDocument() || reader->atEnd())) reader->readNext(); if(!(reader->atEnd())) { if (!reader->skipToNextTag()) return false; if (reader->name() == "project") { QString version = reader->attributes().value("version").toString(); if(version.isEmpty()) reader->raiseWarning(i18n("Attribute 'version' is missing.")); else d->version = version; if (!readBasicAttributes(reader)) return false; if (!readProjectAttributes(reader)) return false; while (!reader->atEnd()) { reader->readNext(); if (reader->isEndElement()) break; if (reader->isStartElement()) { if (reader->name() == "comment") { if (!readCommentElement(reader)) return false; } else if(reader->name() == "child_aspect") { if (!readChildAspectElement(reader, preview)) return false; } else if(reader->name() == "state") { //load the state of the views (visible, maximized/minimized/geometry) //and the state of the project explorer (expanded items, currently selected item) emit requestLoadState(reader); } else { reader->raiseWarning(i18n("unknown element '%1'", reader->name().toString())); if (!reader->skipToEndElement()) return false; } } } //wait until all columns are decoded from base64-encoded data QThreadPool::globalInstance()->waitForDone(); //everything is read now. //restore the pointer to the data sets (columns) in xy-curves etc. QVector curves = children(AbstractAspect::Recursive); QVector axes = children(AbstractAspect::Recursive); QVector dataPickerCurves = children(AbstractAspect::Recursive); - QList surfaces = children(AbstractAspect::Recursive); - QList curves3d = children(AbstractAspect::Recursive); + QVector surfaces = children(AbstractAspect::Recursive); + QVector curves3d = children(AbstractAspect::Recursive); if (!curves.isEmpty() || !axes.isEmpty()) { QVector columns = children(AbstractAspect::Recursive); + QVector matrices = children(AbstractAspect::Recursive); //XY-curves for (auto* curve : curves) { if (!curve) continue; curve->suppressRetransform(true); XYEquationCurve* equationCurve = dynamic_cast(curve); XYDataReductionCurve* dataReductionCurve = dynamic_cast(curve); XYDifferentiationCurve* differentiationCurve = dynamic_cast(curve); XYIntegrationCurve* integrationCurve = dynamic_cast(curve); XYInterpolationCurve* interpolationCurve = dynamic_cast(curve); XYSmoothCurve* smoothCurve = dynamic_cast(curve); XYFitCurve* fitCurve = dynamic_cast(curve); XYFourierFilterCurve* filterCurve = dynamic_cast(curve); XYFourierTransformCurve* dftCurve = dynamic_cast(curve); if (equationCurve) { //curves defined by a mathematical equations recalculate their own columns on load again. if (!preview) equationCurve->recalculate(); } else if (dataReductionCurve) { RESTORE_COLUMN_POINTER(dataReductionCurve, xDataColumn, XDataColumn); RESTORE_COLUMN_POINTER(dataReductionCurve, yDataColumn, YDataColumn); } else if (differentiationCurve) { RESTORE_COLUMN_POINTER(differentiationCurve, xDataColumn, XDataColumn); RESTORE_COLUMN_POINTER(differentiationCurve, yDataColumn, YDataColumn); } else if (integrationCurve) { RESTORE_COLUMN_POINTER(integrationCurve, xDataColumn, XDataColumn); RESTORE_COLUMN_POINTER(integrationCurve, yDataColumn, YDataColumn); } else if (interpolationCurve) { RESTORE_COLUMN_POINTER(interpolationCurve, xDataColumn, XDataColumn); RESTORE_COLUMN_POINTER(interpolationCurve, yDataColumn, YDataColumn); } else if (smoothCurve) { RESTORE_COLUMN_POINTER(smoothCurve, xDataColumn, XDataColumn); RESTORE_COLUMN_POINTER(smoothCurve, yDataColumn, YDataColumn); } else if (fitCurve) { RESTORE_COLUMN_POINTER(fitCurve, xDataColumn, XDataColumn); RESTORE_COLUMN_POINTER(fitCurve, yDataColumn, YDataColumn); RESTORE_COLUMN_POINTER(fitCurve, xErrorColumn, XErrorColumn); RESTORE_COLUMN_POINTER(fitCurve, yErrorColumn, YErrorColumn); } else if (filterCurve) { RESTORE_COLUMN_POINTER(filterCurve, xDataColumn, XDataColumn); RESTORE_COLUMN_POINTER(filterCurve, yDataColumn, YDataColumn); } else if (dftCurve) { RESTORE_COLUMN_POINTER(dftCurve, xDataColumn, XDataColumn); RESTORE_COLUMN_POINTER(dftCurve, yDataColumn, YDataColumn); } else { RESTORE_COLUMN_POINTER(curve, xColumn, XColumn); RESTORE_COLUMN_POINTER(curve, yColumn, YColumn); RESTORE_COLUMN_POINTER(curve, valuesColumn, ValuesColumn); RESTORE_COLUMN_POINTER(curve, xErrorPlusColumn, XErrorPlusColumn); RESTORE_COLUMN_POINTER(curve, xErrorMinusColumn, XErrorMinusColumn); RESTORE_COLUMN_POINTER(curve, yErrorPlusColumn, YErrorPlusColumn); RESTORE_COLUMN_POINTER(curve, yErrorMinusColumn, YErrorMinusColumn); } RESTORE_POINTER(curve, dataSourceCurve, DataSourceCurve, XYCurve, curves); curve->suppressRetransform(false); } // 3D surfaces foreach (AbstractAspect* aspect, surfaces) { Surface3D* surface = dynamic_cast(aspect); if (!surface) continue; RESTORE_MATRIX_POINTER(surface, matrix, Matrix); RESTORE_COLUMN_POINTER(surface, xColumn, XColumn); RESTORE_COLUMN_POINTER(surface, yColumn, YColumn); RESTORE_COLUMN_POINTER(surface, yColumn, ZColumn); RESTORE_COLUMN_POINTER(surface, firstNode, FirstNode); RESTORE_COLUMN_POINTER(surface, secondNode, SecondNode); RESTORE_COLUMN_POINTER(surface, thirdNode, ThirdNode); } // 3D curves foreach (AbstractAspect* aspect, curves3d) { Curve3D* curve = dynamic_cast(aspect); if (!curve) continue; RESTORE_COLUMN_POINTER(curve, xColumn, XColumn); RESTORE_COLUMN_POINTER(curve, yColumn, YColumn); RESTORE_COLUMN_POINTER(curve, zColumn, ZColumn); } //Axes for (auto* axis : axes) { if (!axis) continue; RESTORE_COLUMN_POINTER(axis, majorTicksColumn, MajorTicksColumn); RESTORE_COLUMN_POINTER(axis, minorTicksColumn, MinorTicksColumn); } for (auto* dataPickerCurve : dataPickerCurves) { if (!dataPickerCurve) continue; RESTORE_COLUMN_POINTER(dataPickerCurve, posXColumn, PosXColumn); RESTORE_COLUMN_POINTER(dataPickerCurve, posYColumn, PosYColumn); RESTORE_COLUMN_POINTER(dataPickerCurve, plusDeltaXColumn, PlusDeltaXColumn); RESTORE_COLUMN_POINTER(dataPickerCurve, minusDeltaXColumn, MinusDeltaXColumn); RESTORE_COLUMN_POINTER(dataPickerCurve, plusDeltaYColumn, PlusDeltaYColumn); RESTORE_COLUMN_POINTER(dataPickerCurve, minusDeltaYColumn, MinusDeltaYColumn); } } } else // no project element reader->raiseError(i18n("no project element found")); } else // no start document reader->raiseError(i18n("no valid XML document found")); if (!preview) { for (auto* plot : children(AbstractAspect::Recursive)) plot->retransform(); } d->loading = false; emit loaded(); return !reader->hasError(); } bool Project::readProjectAttributes(XmlStreamReader* reader) { QXmlStreamAttributes attribs = reader->attributes(); QString str = attribs.value(reader->namespaceUri().toString(), "fileName").toString(); if(str.isEmpty()) { reader->raiseError(i18n("Project file name missing.")); return false; } d->fileName = str; str = attribs.value(reader->namespaceUri().toString(), "modificationTime").toString(); QDateTime modificationTime = QDateTime::fromString(str, "yyyy-dd-MM hh:mm:ss:zzz"); if(str.isEmpty() || !modificationTime.isValid()) { reader->raiseWarning(i18n("Invalid project modification time. Using current time.")); d->modificationTime = QDateTime::currentDateTime(); } else d->modificationTime = modificationTime; str = attribs.value(reader->namespaceUri().toString(), "author").toString(); d->author = str; return true; } diff --git a/src/backend/worksheet/Worksheet.cpp b/src/backend/worksheet/Worksheet.cpp index cb8cdee75..8a2a38417 100644 --- a/src/backend/worksheet/Worksheet.cpp +++ b/src/backend/worksheet/Worksheet.cpp @@ -1,1054 +1,1053 @@ /*************************************************************************** File : Worksheet.cpp Project : LabPlot Description : Worksheet -------------------------------------------------------------------- Copyright : (C) 2009 Tilman Benkert (thzs@gmx.net) Copyright : (C) 2011-2016 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 "Worksheet.h" #include "WorksheetPrivate.h" #include "WorksheetElement.h" #include "commonfrontend/worksheet/WorksheetView.h" #include "backend/worksheet/plots/cartesian/CartesianPlot.h" #include "backend/worksheet/plots/3d/Plot3D.h" #include "backend/worksheet/TextLabel.h" #include "backend/lib/commandtemplates.h" #include "backend/lib/XmlStreamReader.h" #include "kdefrontend/worksheet/ExportWorksheetDialog.h" #include "kdefrontend/ThemeHandler.h" #include #include #include #include #include #include #include #include -#include #include #include /** * \class Worksheet * \brief Top-level container for worksheet elements like plot, labels, etc. * * The worksheet is, besides the data containers \c Spreadsheet and \c Matrix, another central part of the application * and provides an area for showing and grouping together different kinds of worksheet objects - plots, labels &etc; * * * \ingroup worksheet */ Worksheet::Worksheet(AbstractScriptingEngine* engine, const QString& name, bool loading) : AbstractPart(name), scripted(engine), d(new WorksheetPrivate(this)) { connect(this, SIGNAL(aspectAdded(const AbstractAspect*)), this, SLOT(handleAspectAdded(const AbstractAspect*))); connect(this, SIGNAL(aspectAboutToBeRemoved(const AbstractAspect*)), this, SLOT(handleAspectAboutToBeRemoved(const AbstractAspect*))); connect(this, SIGNAL(aspectRemoved(const AbstractAspect*,const AbstractAspect*,const AbstractAspect*)), this, SLOT(handleAspectRemoved(const AbstractAspect*,const AbstractAspect*,const AbstractAspect*)) ); if (!loading) init(); } Worksheet::~Worksheet() { delete d; } void Worksheet::init() { KConfig config; KConfigGroup group = config.group( "Worksheet" ); //size d->scaleContent = group.readEntry("ScaleContent", false); d->useViewSize = group.readEntry("UseViewSize", false); d->pageRect.setX(0); d->pageRect.setY(0); d->pageRect.setWidth(group.readEntry("Width", 1500)); d->pageRect.setHeight(group.readEntry("Height",1500)); d->m_scene->setSceneRect(d->pageRect); //background d->backgroundType = (PlotArea::BackgroundType) group.readEntry("BackgroundType", (int) PlotArea::Color); d->backgroundColorStyle = (PlotArea::BackgroundColorStyle) group.readEntry("BackgroundColorStyle", (int) PlotArea::SingleColor); d->backgroundImageStyle = (PlotArea::BackgroundImageStyle) group.readEntry("BackgroundImageStyle", (int) PlotArea::Scaled); d->backgroundBrushStyle = (Qt::BrushStyle) group.readEntry("BackgroundBrushStyle", (int) Qt::SolidPattern); d->backgroundFileName = group.readEntry("BackgroundFileName", QString()); d->backgroundFirstColor = group.readEntry("BackgroundFirstColor", QColor(Qt::white)); d->backgroundSecondColor = group.readEntry("BackgroundSecondColor", QColor(Qt::black)); d->backgroundOpacity = group.readEntry("BackgroundOpacity", 1.0); //layout d->layout = (Worksheet::Layout) group.readEntry("Layout", (int) Worksheet::VerticalLayout); d->layoutTopMargin = group.readEntry("LayoutTopMargin", convertToSceneUnits(1, Centimeter)); d->layoutBottomMargin = group.readEntry("LayoutBottomMargin", convertToSceneUnits(1, Centimeter)); d->layoutLeftMargin = group.readEntry("LayoutLeftMargin", convertToSceneUnits(1, Centimeter)); d->layoutRightMargin = group.readEntry("LayoutRightMargin", convertToSceneUnits(1, Centimeter)); d->layoutVerticalSpacing = group.readEntry("LayoutVerticalSpacing", convertToSceneUnits(1, Centimeter)); d->layoutHorizontalSpacing = group.readEntry("LayoutHorizontalSpacing", convertToSceneUnits(1, Centimeter)); d->layoutRowCount = group.readEntry("LayoutRowCount", 2); d->layoutColumnCount = group.readEntry("LayoutColumnCount", 2); //default theme KConfigGroup settings = KSharedConfig::openConfig()->group(QLatin1String("Settings_Worksheet")); d->theme = settings.readEntry(QLatin1String("Theme"), ""); if (!d->theme.isEmpty()) loadTheme(d->theme); } /*! converts from \c unit to the scene units. At the moment, 1 scene unit corresponds to 1/10 mm. */ float Worksheet::convertToSceneUnits(const float value, const Worksheet::Unit unit) { switch (unit) { case Worksheet::Millimeter: return value*10.0; case Worksheet::Centimeter: return value*100.0; case Worksheet::Inch: return value*25.4*10.; case Worksheet::Point: return value*25.4/72.*10.; } return 0; } /*! converts from the scene units to \c unit . At the moment, 1 scene unit corresponds to 1/10 mm. */ float Worksheet::convertFromSceneUnits(const float value, const Worksheet::Unit unit) { switch (unit) { case Worksheet::Millimeter: return value/10.0; case Worksheet::Centimeter: return value/100.0; case Worksheet::Inch: return value/25.4/10.; case Worksheet::Point: return value/25.4/10.*72.; } return 0; } QIcon Worksheet::icon() const { return QIcon::fromTheme("labplot-worksheet"); } /** * Return a new context menu. The caller takes ownership of the menu. */ QMenu* Worksheet::createContextMenu() { QMenu* menu = AbstractPart::createContextMenu(); Q_ASSERT(menu); emit requestProjectContextMenu(menu); return menu; } //! Construct a primary view on me. /** * This method may be called multiple times during the life time of an Aspect, or it might not get * called at all. Aspects must not depend on the existence of a view for their operation. */ QWidget* Worksheet::view() const { if (!m_view) { m_view = new WorksheetView(const_cast(this)); connect(m_view, SIGNAL(statusInfo(QString)), this, SIGNAL(statusInfo(QString))); } return m_view; } bool Worksheet::exportView() const { ExportWorksheetDialog* dlg = new ExportWorksheetDialog(m_view); dlg->setFileName(name()); bool ret; if ( (ret = (dlg->exec()==QDialog::Accepted)) ) { QString path = dlg->path(); const WorksheetView::ExportFormat format = dlg->exportFormat(); const WorksheetView::ExportArea area = dlg->exportArea(); const bool background = dlg->exportBackground(); const int resolution = dlg->exportResolution(); WorksheetView* view = reinterpret_cast(m_view); WAIT_CURSOR; view->exportToFile(path, format, area, background, resolution); RESET_CURSOR; } delete dlg; return ret; } bool Worksheet::printView() { QPrinter printer; QPrintDialog* dlg = new QPrintDialog(&printer, m_view); dlg->setWindowTitle(i18n("Print Worksheet")); bool ret; if ( (ret = (dlg->exec() == QDialog::Accepted)) ) { WorksheetView* view = reinterpret_cast(m_view); view->print(&printer); } delete dlg; return ret; } bool Worksheet::printPreview() const { const WorksheetView* view = reinterpret_cast(m_view); QPrintPreviewDialog* dlg = new QPrintPreviewDialog(m_view); connect(dlg, SIGNAL(paintRequested(QPrinter*)), view, SLOT(print(QPrinter*))); return dlg->exec(); } void Worksheet::handleAspectAdded(const AbstractAspect* aspect) { const WorksheetElement* addedElement = qobject_cast(aspect); if (!addedElement) return; if (aspect->parentAspect() != this) return; //add the GraphicsItem of the added child to the scene QGraphicsItem* item = addedElement->graphicsItem(); d->m_scene->addItem(item); qreal zVal = 0; for (auto* child : children(IncludeHidden)) child->graphicsItem()->setZValue(zVal++); //if a theme was selected in the worksheet, apply this theme for newly added children if (!d->theme.isEmpty() && !isLoading()) { KConfig config(ThemeHandler::themeFilePath(d->theme), KConfig::SimpleConfig); const_cast(addedElement)->loadThemeConfig(config); } //recalculated the layout if (!isLoading()) { if (d->layout != Worksheet::NoLayout) d->updateLayout(false); } } void Worksheet::handleAspectAboutToBeRemoved(const AbstractAspect* aspect) { const WorksheetElement* removedElement = qobject_cast(aspect); if (removedElement) { QGraphicsItem* item = removedElement->graphicsItem(); Q_ASSERT(item != NULL); d->m_scene->removeItem(item); } } void Worksheet::handleAspectRemoved(const AbstractAspect* parent, const AbstractAspect* before, const AbstractAspect* child) { Q_UNUSED(parent); Q_UNUSED(before); Q_UNUSED(child); if (d->layout != Worksheet::NoLayout) d->updateLayout(false); } QGraphicsScene* Worksheet::scene() const { return d->m_scene; } QRectF Worksheet::pageRect() const { return d->m_scene->sceneRect(); } /*! this slot is called when a worksheet element is selected in the project explorer. emits \c itemSelected() which forwards this event to the \c WorksheetView in order to select the corresponding \c QGraphicsItem. */ void Worksheet::childSelected(const AbstractAspect* aspect) { WorksheetElement* element=qobject_cast(const_cast(aspect)); if (element) emit itemSelected(element->graphicsItem()); } /*! this slot is called when a worksheet element is deselected in the project explorer. emits \c itemDeselected() which forwards this event to \c WorksheetView in order to deselect the corresponding \c QGraphicsItem. */ void Worksheet::childDeselected(const AbstractAspect* aspect) { WorksheetElement* element=qobject_cast(const_cast(aspect)); if (element) emit itemDeselected(element->graphicsItem()); } /*! * Emits the signal to select or to deselect the aspect corresponding to \c QGraphicsItem \c item in the project explorer, * if \c selected=true or \c selected=false, respectively. * The signal is handled in \c AspectTreeModel and forwarded to the tree view in \c ProjectExplorer. * This function is called in \c WorksheetView upon selection changes. */ void Worksheet::setItemSelectedInView(const QGraphicsItem* item, const bool b) { //determine the corresponding aspect const AbstractAspect* aspect = 0; for (const auto* child : children(IncludeHidden) ) { aspect = this->aspectFromGraphicsItem(child, item); if (aspect) break; } if (!aspect) return; //forward selection/deselection to AbstractTreeModel if (b) emit childAspectSelectedInView(aspect); else emit childAspectDeselectedInView(aspect); } /*! * helper function: checks whether \c aspect or one of its children has the \c GraphicsItem \c item * Returns a pointer to \c WorksheetElement having this item. */ WorksheetElement* Worksheet::aspectFromGraphicsItem(const WorksheetElement* aspect, const QGraphicsItem* item) const { if ( aspect->graphicsItem() == item ) return const_cast(aspect); else { for (const auto* child : aspect->children(AbstractAspect::IncludeHidden) ) { WorksheetElement* a = this->aspectFromGraphicsItem(child, item); if (a) return a; } return 0; } } /*! Selects or deselects the worksheet in the project explorer. This function is called in \c WorksheetView. The worksheet gets deselected if there are selected items in the view, and selected if there are no selected items in the view. */ void Worksheet::setSelectedInView(const bool b) { if (b) emit childAspectSelectedInView(this); else emit childAspectDeselectedInView(this); } void Worksheet::deleteAspectFromGraphicsItem(const QGraphicsItem* item) { Q_ASSERT(item); //determine the corresponding aspect AbstractAspect* aspect = 0; for (const auto* child : children(IncludeHidden) ) { aspect = this->aspectFromGraphicsItem(child, item); if (aspect) break; } if (!aspect) return; if (aspect->parentAspect()) aspect->parentAspect()->removeChild(aspect); else this->removeChild(aspect); } void Worksheet::setIsClosing() { if (m_view) { WorksheetView* view = reinterpret_cast(m_view); view->setIsClosing(); } } void Worksheet::update() { emit requestUpdate(); } void Worksheet::setSuppressLayoutUpdate(bool value) { d->suppressLayoutUpdate = value; } void Worksheet::updateLayout() { d->updateLayout(); } /* =============================== getter methods for general options ==================================== */ BASIC_D_READER_IMPL(Worksheet, bool, scaleContent, scaleContent) BASIC_D_READER_IMPL(Worksheet, bool, useViewSize, useViewSize) /* =============================== getter methods for background options ================================= */ BASIC_D_READER_IMPL(Worksheet, PlotArea::BackgroundType, backgroundType, backgroundType) BASIC_D_READER_IMPL(Worksheet, PlotArea::BackgroundColorStyle, backgroundColorStyle, backgroundColorStyle) BASIC_D_READER_IMPL(Worksheet, PlotArea::BackgroundImageStyle, backgroundImageStyle, backgroundImageStyle) BASIC_D_READER_IMPL(Worksheet, Qt::BrushStyle, backgroundBrushStyle, backgroundBrushStyle) CLASS_D_READER_IMPL(Worksheet, QColor, backgroundFirstColor, backgroundFirstColor) CLASS_D_READER_IMPL(Worksheet, QColor, backgroundSecondColor, backgroundSecondColor) CLASS_D_READER_IMPL(Worksheet, QString, backgroundFileName, backgroundFileName) BASIC_D_READER_IMPL(Worksheet, float, backgroundOpacity, backgroundOpacity) /* =============================== getter methods for layout options ====================================== */ BASIC_D_READER_IMPL(Worksheet, Worksheet::Layout, layout, layout) BASIC_D_READER_IMPL(Worksheet, float, layoutTopMargin, layoutTopMargin) BASIC_D_READER_IMPL(Worksheet, float, layoutBottomMargin, layoutBottomMargin) BASIC_D_READER_IMPL(Worksheet, float, layoutLeftMargin, layoutLeftMargin) BASIC_D_READER_IMPL(Worksheet, float, layoutRightMargin, layoutRightMargin) BASIC_D_READER_IMPL(Worksheet, float, layoutHorizontalSpacing, layoutHorizontalSpacing) BASIC_D_READER_IMPL(Worksheet, float, layoutVerticalSpacing, layoutVerticalSpacing) BASIC_D_READER_IMPL(Worksheet, int, layoutRowCount, layoutRowCount) BASIC_D_READER_IMPL(Worksheet, int, layoutColumnCount, layoutColumnCount) CLASS_D_READER_IMPL(Worksheet, QString, theme, theme) /* ============================ setter methods and undo commands for general options ===================== */ void Worksheet::setUseViewSize(bool useViewSize) { if (useViewSize != d->useViewSize) { d->useViewSize = useViewSize; emit useViewSizeRequested(); } } STD_SETTER_CMD_IMPL_S(Worksheet, SetScaleContent, bool, scaleContent) void Worksheet::setScaleContent(bool scaleContent) { if (scaleContent != d->scaleContent) exec(new WorksheetSetScaleContentCmd(d, scaleContent, i18n("%1: change \"rescale the content\" property"))); } /* ============================ setter methods and undo commands for background options ================= */ STD_SETTER_CMD_IMPL_F_S(Worksheet, SetBackgroundType, PlotArea::BackgroundType, backgroundType, update) void Worksheet::setBackgroundType(PlotArea::BackgroundType type) { if (type != d->backgroundType) exec(new WorksheetSetBackgroundTypeCmd(d, type, i18n("%1: background type changed"))); } STD_SETTER_CMD_IMPL_F_S(Worksheet, SetBackgroundColorStyle, PlotArea::BackgroundColorStyle, backgroundColorStyle, update) void Worksheet::setBackgroundColorStyle(PlotArea::BackgroundColorStyle style) { if (style != d->backgroundColorStyle) exec(new WorksheetSetBackgroundColorStyleCmd(d, style, i18n("%1: background color style changed"))); } STD_SETTER_CMD_IMPL_F_S(Worksheet, SetBackgroundImageStyle, PlotArea::BackgroundImageStyle, backgroundImageStyle, update) void Worksheet::setBackgroundImageStyle(PlotArea::BackgroundImageStyle style) { if (style != d->backgroundImageStyle) exec(new WorksheetSetBackgroundImageStyleCmd(d, style, i18n("%1: background image style changed"))); } STD_SETTER_CMD_IMPL_F_S(Worksheet, SetBackgroundBrushStyle, Qt::BrushStyle, backgroundBrushStyle, update) void Worksheet::setBackgroundBrushStyle(Qt::BrushStyle style) { if (style != d->backgroundBrushStyle) exec(new WorksheetSetBackgroundBrushStyleCmd(d, style, i18n("%1: background brush style changed"))); } STD_SETTER_CMD_IMPL_F_S(Worksheet, SetBackgroundFirstColor, QColor, backgroundFirstColor, update) void Worksheet::setBackgroundFirstColor(const QColor &color) { if (color!= d->backgroundFirstColor) exec(new WorksheetSetBackgroundFirstColorCmd(d, color, i18n("%1: set background first color"))); } STD_SETTER_CMD_IMPL_F_S(Worksheet, SetBackgroundSecondColor, QColor, backgroundSecondColor, update) void Worksheet::setBackgroundSecondColor(const QColor &color) { if (color!= d->backgroundSecondColor) exec(new WorksheetSetBackgroundSecondColorCmd(d, color, i18n("%1: set background second color"))); } STD_SETTER_CMD_IMPL_F_S(Worksheet, SetBackgroundFileName, QString, backgroundFileName, update) void Worksheet::setBackgroundFileName(const QString& fileName) { if (fileName!= d->backgroundFileName) exec(new WorksheetSetBackgroundFileNameCmd(d, fileName, i18n("%1: set background image"))); } STD_SETTER_CMD_IMPL_F_S(Worksheet, SetBackgroundOpacity, float, backgroundOpacity, update) void Worksheet::setBackgroundOpacity(float opacity) { if (opacity != d->backgroundOpacity) exec(new WorksheetSetBackgroundOpacityCmd(d, opacity, i18n("%1: set opacity"))); } /* ============================ setter methods and undo commands for layout options ================= */ STD_SETTER_CMD_IMPL_F_S(Worksheet, SetLayout, Worksheet::Layout, layout, updateLayout) void Worksheet::setLayout(Worksheet::Layout layout) { if (layout != d->layout) { beginMacro(i18n("%1: set layout", name())); exec(new WorksheetSetLayoutCmd(d, layout, i18n("%1: set layout"))); endMacro(); } } STD_SETTER_CMD_IMPL_M_F_S(Worksheet, SetLayoutTopMargin, float, layoutTopMargin, updateLayout) void Worksheet::setLayoutTopMargin(float margin) { if (margin != d->layoutTopMargin) { beginMacro(i18n("%1: set layout top margin", name())); exec(new WorksheetSetLayoutTopMarginCmd(d, margin, i18n("%1: set layout top margin"))); endMacro(); } } STD_SETTER_CMD_IMPL_M_F_S(Worksheet, SetLayoutBottomMargin, float, layoutBottomMargin, updateLayout) void Worksheet::setLayoutBottomMargin(float margin) { if (margin != d->layoutBottomMargin) { beginMacro(i18n("%1: set layout bottom margin", name())); exec(new WorksheetSetLayoutBottomMarginCmd(d, margin, i18n("%1: set layout bottom margin"))); endMacro(); } } STD_SETTER_CMD_IMPL_M_F_S(Worksheet, SetLayoutLeftMargin, float, layoutLeftMargin, updateLayout) void Worksheet::setLayoutLeftMargin(float margin) { if (margin != d->layoutLeftMargin) { beginMacro(i18n("%1: set layout left margin", name())); exec(new WorksheetSetLayoutLeftMarginCmd(d, margin, i18n("%1: set layout left margin"))); endMacro(); } } STD_SETTER_CMD_IMPL_M_F_S(Worksheet, SetLayoutRightMargin, float, layoutRightMargin, updateLayout) void Worksheet::setLayoutRightMargin(float margin) { if (margin != d->layoutRightMargin) { beginMacro(i18n("%1: set layout right margin", name())); exec(new WorksheetSetLayoutRightMarginCmd(d, margin, i18n("%1: set layout right margin"))); endMacro(); } } STD_SETTER_CMD_IMPL_M_F_S(Worksheet, SetLayoutVerticalSpacing, float, layoutVerticalSpacing, updateLayout) void Worksheet::setLayoutVerticalSpacing(float spacing) { if (spacing != d->layoutVerticalSpacing) { beginMacro(i18n("%1: set layout vertical spacing", name())); exec(new WorksheetSetLayoutVerticalSpacingCmd(d, spacing, i18n("%1: set layout vertical spacing"))); endMacro(); } } STD_SETTER_CMD_IMPL_M_F_S(Worksheet, SetLayoutHorizontalSpacing, float, layoutHorizontalSpacing, updateLayout) void Worksheet::setLayoutHorizontalSpacing(float spacing) { if (spacing != d->layoutHorizontalSpacing) { beginMacro(i18n("%1: set layout horizontal spacing", name())); exec(new WorksheetSetLayoutHorizontalSpacingCmd(d, spacing, i18n("%1: set layout horizontal spacing"))); endMacro(); } } STD_SETTER_CMD_IMPL_M_F_S(Worksheet, SetLayoutRowCount, int, layoutRowCount, updateLayout) void Worksheet::setLayoutRowCount(int count) { if (count != d->layoutRowCount) { beginMacro(i18n("%1: set layout row count", name())); exec(new WorksheetSetLayoutRowCountCmd(d, count, i18n("%1: set layout row count"))); endMacro(); } } STD_SETTER_CMD_IMPL_M_F_S(Worksheet, SetLayoutColumnCount, int, layoutColumnCount, updateLayout) void Worksheet::setLayoutColumnCount(int count) { if (count != d->layoutColumnCount) { beginMacro(i18n("%1: set layout column count", name())); exec(new WorksheetSetLayoutColumnCountCmd(d, count, i18n("%1: set layout column count"))); endMacro(); } } class WorksheetSetPageRectCmd : public StandardMacroSetterCmd { public: WorksheetSetPageRectCmd(Worksheet::Private* target, QRectF newValue, const QString& description) : StandardMacroSetterCmd(target, &Worksheet::Private::pageRect, newValue, description) {} virtual void finalize() { m_target->updatePageRect(); m_target->q->pageRectChanged(m_target->*m_field); } virtual void finalizeUndo() { m_target->m_scene->setSceneRect(m_target->*m_field); m_target->q->pageRectChanged(m_target->*m_field); } }; void Worksheet::setPageRect(const QRectF& rect) { //don't allow any rectangulars of width/height equal to zero if (qFuzzyCompare(rect.width(), 0.) || qFuzzyCompare(rect.height(), 0.)) { pageRectChanged(d->pageRect); return; } if (rect != d->pageRect) { if (!d->useViewSize) { beginMacro(i18n("%1: set page size", name())); exec(new WorksheetSetPageRectCmd(d, rect, i18n("%1: set page size"))); endMacro(); } else { d->pageRect = rect; d->updatePageRect(); pageRectChanged(d->pageRect); } } } void Worksheet::setPrinting(bool on) const { QVector childElements = children(AbstractAspect::Recursive | AbstractAspect::IncludeHidden); for (auto* child : childElements) child->setPrinting(on); } STD_SETTER_CMD_IMPL_S(Worksheet, SetTheme, QString, theme) void Worksheet::setTheme(const QString& theme) { if (theme != d->theme) { if (!theme.isEmpty()) { beginMacro( i18n("%1: load theme %2", name(), theme) ); exec(new WorksheetSetThemeCmd(d, theme, i18n("%1: set theme"))); loadTheme(theme); endMacro(); } else { exec(new WorksheetSetThemeCmd(d, theme, i18n("%1: disable theming"))); } } } //############################################################################## //###################### Private implementation ############################### //############################################################################## WorksheetPrivate::WorksheetPrivate(Worksheet* owner):q(owner), pageRect(0, 0, 1500, 1500), m_scene(new QGraphicsScene()), scaleContent(false), suppressLayoutUpdate(false) { } QString WorksheetPrivate::name() const { return q->name(); } void WorksheetPrivate::updatePageRect() { QRectF oldRect = m_scene->sceneRect(); m_scene->setSceneRect(pageRect); if (layout != Worksheet::NoLayout) updateLayout(); else { if (scaleContent) { qreal horizontalRatio = pageRect.width() / oldRect.width(); qreal verticalRatio = pageRect.height() / oldRect.height(); QVector childElements = q->children(AbstractAspect::IncludeHidden); if (useViewSize) { //don't make the change of the geometry undoable/redoable if the view size is used. for (auto* elem : childElements) { elem->setUndoAware(false); elem->handleResize(horizontalRatio, verticalRatio, true); elem->setUndoAware(true); } } else { for (auto* child : childElements) child->handleResize(horizontalRatio, verticalRatio, true); } } } } void WorksheetPrivate::update() { q->update(); } WorksheetPrivate::~WorksheetPrivate() { delete m_scene; } void WorksheetPrivate::updateLayout(bool undoable) { if (suppressLayoutUpdate) return; QVector list = q->children(); if (layout==Worksheet::NoLayout) { for(auto* elem : list) elem->graphicsItem()->setFlag(QGraphicsItem::ItemIsMovable, true); return; } float x=layoutLeftMargin; float y=layoutTopMargin; float w, h; int count=list.count(); if (layout == Worksheet::VerticalLayout) { w= m_scene->sceneRect().width() - layoutLeftMargin - layoutRightMargin; h=(m_scene->sceneRect().height()-layoutTopMargin-layoutBottomMargin- (count-1)*layoutVerticalSpacing)/count; foreach(WorksheetElementContainer* elem, list) { setContainerRect(elem, x, y, h, w, undoable); y+=h + layoutVerticalSpacing; } } else if (layout == Worksheet::HorizontalLayout) { w=(m_scene->sceneRect().width()-layoutLeftMargin-layoutRightMargin- (count-1)*layoutHorizontalSpacing)/count; h= m_scene->sceneRect().height() - layoutTopMargin-layoutBottomMargin; foreach(WorksheetElementContainer* elem, list) { setContainerRect(elem, x, y, h, w, undoable); x+=w + layoutHorizontalSpacing; } } else { //GridLayout //add new rows, if not sufficient if (count>layoutRowCount*layoutColumnCount) { layoutRowCount = floor( (float)count/layoutColumnCount + 0.5); emit q->layoutRowCountChanged(layoutRowCount); } w=(m_scene->sceneRect().width()-layoutLeftMargin-layoutRightMargin- (layoutColumnCount-1)*layoutHorizontalSpacing)/layoutColumnCount; h=(m_scene->sceneRect().height()-layoutTopMargin-layoutBottomMargin- (layoutRowCount-1)*layoutVerticalSpacing)/layoutRowCount; int columnIndex=0; //counts the columns in a row foreach(WorksheetElementContainer* elem, list) { setContainerRect(elem, x, y, h, w, undoable); x+=w + layoutHorizontalSpacing; columnIndex++; if (columnIndex==layoutColumnCount) { columnIndex=0; x=layoutLeftMargin; y+=h + layoutVerticalSpacing; } } } } void WorksheetPrivate::setContainerRect(WorksheetElementContainer* elem, float x, float y, float h, float w, bool undoable) { if (useViewSize) { //when using the view size, no need to put rect changes onto the undo-stack elem->setUndoAware(false); elem->setRect(QRectF(x,y,w,h)); elem->setUndoAware(true); } else { //don't put rect changed onto the undo-stack if undoable-flag is set to true, //e.g. when new child is added or removed (the layout and the childrend rects will be updated anyway) if (!undoable) { elem->setUndoAware(false); elem->setRect(QRectF(x,y,w,h)); elem->setUndoAware(true); } else elem->setRect(QRectF(x,y,w,h)); } elem->graphicsItem()->setFlag(QGraphicsItem::ItemIsMovable, false); } //############################################################################## //################## Serialization/Deserialization ########################### //############################################################################## //! Save as XML void Worksheet::save(QXmlStreamWriter* writer) const { writer->writeStartElement( "worksheet" ); writeBasicAttributes(writer); writeCommentElement(writer); //applied theme if (!d->theme.isEmpty()){ writer->writeStartElement( "theme" ); writer->writeAttribute("name", d->theme); writer->writeEndElement(); } //geometry writer->writeStartElement( "geometry" ); QRectF rect = d->m_scene->sceneRect(); writer->writeAttribute( "x", QString::number(rect.x()) ); writer->writeAttribute( "y", QString::number(rect.y()) ); writer->writeAttribute( "width", QString::number(rect.width()) ); writer->writeAttribute( "height", QString::number(rect.height()) ); writer->writeAttribute( "useViewSize", QString::number(d->useViewSize) ); writer->writeEndElement(); //layout writer->writeStartElement( "layout" ); writer->writeAttribute( "layout", QString::number(d->layout) ); writer->writeAttribute( "topMargin", QString::number(d->layoutTopMargin) ); writer->writeAttribute( "bottomMargin", QString::number(d->layoutBottomMargin) ); writer->writeAttribute( "leftMargin", QString::number(d->layoutLeftMargin) ); writer->writeAttribute( "rightMargin", QString::number(d->layoutRightMargin) ); writer->writeAttribute( "verticalSpacing", QString::number(d->layoutVerticalSpacing) ); writer->writeAttribute( "horizontalSpacing", QString::number(d->layoutHorizontalSpacing) ); writer->writeAttribute( "columnCount", QString::number(d->layoutColumnCount) ); writer->writeAttribute( "rowCount", QString::number(d->layoutRowCount) ); writer->writeEndElement(); //background properties writer->writeStartElement( "background" ); writer->writeAttribute( "type", QString::number(d->backgroundType) ); writer->writeAttribute( "colorStyle", QString::number(d->backgroundColorStyle) ); writer->writeAttribute( "imageStyle", QString::number(d->backgroundImageStyle) ); writer->writeAttribute( "brushStyle", QString::number(d->backgroundBrushStyle) ); writer->writeAttribute( "firstColor_r", QString::number(d->backgroundFirstColor.red()) ); writer->writeAttribute( "firstColor_g", QString::number(d->backgroundFirstColor.green()) ); writer->writeAttribute( "firstColor_b", QString::number(d->backgroundFirstColor.blue()) ); writer->writeAttribute( "secondColor_r", QString::number(d->backgroundSecondColor.red()) ); writer->writeAttribute( "secondColor_g", QString::number(d->backgroundSecondColor.green()) ); writer->writeAttribute( "secondColor_b", QString::number(d->backgroundSecondColor.blue()) ); writer->writeAttribute( "fileName", d->backgroundFileName ); writer->writeAttribute( "opacity", QString::number(d->backgroundOpacity) ); writer->writeEndElement(); //serialize all children for (auto* child : children(IncludeHidden)) child->save(writer); writer->writeEndElement(); // close "worksheet" section } //! Load from XML bool Worksheet::load(XmlStreamReader* reader, bool preview) { if(!reader->isStartElement() || reader->name() != "worksheet") { reader->raiseError(i18n("no worksheet element found")); return false; } if (!readBasicAttributes(reader)) return false; //clear the theme that was potentially set in init() in order to correctly load here the worksheets without any theme used d->theme = ""; QString attributeWarning = i18n("Attribute '%1' missing or empty, default value is used"); QXmlStreamAttributes attribs; QString str; QRectF rect; while (!reader->atEnd()) { reader->readNext(); if (reader->isEndElement() && reader->name() == "worksheet") break; if (!reader->isStartElement()) continue; if (reader->name() == "comment") { if (!readCommentElement(reader)) return false; } else if (!preview && reader->name() == "theme") { attribs = reader->attributes(); d->theme = attribs.value("name").toString(); } else if (!preview && reader->name() == "geometry") { attribs = reader->attributes(); str = attribs.value("x").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("'x'")); else rect.setX(str.toDouble()); str = attribs.value("y").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("'y'")); else rect.setY(str.toDouble()); str = attribs.value("width").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("'width'")); else rect.setWidth(str.toDouble()); str = attribs.value("height").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("'height'")); else rect.setHeight(str.toDouble()); str = attribs.value("useViewSize").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("'useViewSize'")); else d->useViewSize = str.toInt(); } else if (!preview && reader->name() == "layout") { attribs = reader->attributes(); str = attribs.value("layout").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("layout")); else d->layout = Worksheet::Layout(str.toInt()); str = attribs.value("topMargin").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("topMargin")); else d->layoutTopMargin = str.toDouble(); str = attribs.value("bottomMargin").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("bottomMargin")); else d->layoutBottomMargin = str.toDouble(); str = attribs.value("leftMargin").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("leftMargin")); else d->layoutLeftMargin = str.toDouble(); str = attribs.value("rightMargin").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("rightMargin")); else d->layoutRightMargin = str.toDouble(); str = attribs.value("verticalSpacing").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("verticalSpacing")); else d->layoutVerticalSpacing = str.toDouble(); str = attribs.value("horizontalSpacing").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("horizontalSpacing")); else d->layoutHorizontalSpacing = str.toDouble(); str = attribs.value("columnCount").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("columnCount")); else d->layoutColumnCount = str.toInt(); str = attribs.value("rowCount").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("rowCount")); else d->layoutRowCount = str.toInt(); } else if (!preview && reader->name() == "background") { attribs = reader->attributes(); str = attribs.value("type").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("type")); else d->backgroundType = PlotArea::BackgroundType(str.toInt()); str = attribs.value("colorStyle").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("colorStyle")); else d->backgroundColorStyle = PlotArea::BackgroundColorStyle(str.toInt()); str = attribs.value("imageStyle").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("imageStyle")); else d->backgroundImageStyle = PlotArea::BackgroundImageStyle(str.toInt()); str = attribs.value("brushStyle").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("brushStyle")); else d->backgroundBrushStyle = Qt::BrushStyle(str.toInt()); str = attribs.value("firstColor_r").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("firstColor_r")); else d->backgroundFirstColor.setRed(str.toInt()); str = attribs.value("firstColor_g").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("firstColor_g")); else d->backgroundFirstColor.setGreen(str.toInt()); str = attribs.value("firstColor_b").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("firstColor_b")); else d->backgroundFirstColor.setBlue(str.toInt()); str = attribs.value("secondColor_r").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("secondColor_r")); else d->backgroundSecondColor.setRed(str.toInt()); str = attribs.value("secondColor_g").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("secondColor_g")); else d->backgroundSecondColor.setGreen(str.toInt()); str = attribs.value("secondColor_b").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("secondColor_b")); else d->backgroundSecondColor.setBlue(str.toInt()); str = attribs.value("fileName").toString(); d->backgroundFileName = str; str = attribs.value("opacity").toString(); if (str.isEmpty()) reader->raiseWarning(attributeWarning.arg("opacity")); else d->backgroundOpacity = str.toDouble(); } else if (reader->name() == "cartesianPlot") { CartesianPlot* plot = new CartesianPlot(""); plot->setIsLoading(true); if (!plot->load(reader, preview)) { delete plot; return false; } else { addChildFast(plot); plot->setIsLoading(false); } } else if (reader->name() == "Plot3D") { Plot3D* plot = new Plot3D(""); - if (!plot->load(reader)) { + if (!plot->load(reader, preview)) { delete plot; return false; } else { addChild(plot); } } else if (reader->name() == "textLabel") { TextLabel* label = new TextLabel(""); if (!label->load(reader, preview)) { delete label; return false; } else addChildFast(label); } else { // unknown element reader->raiseWarning(i18n("unknown element '%1'", reader->name().toString())); if (!reader->skipToEndElement()) return false; } } if (!preview) { d->m_scene->setSceneRect(rect); d->updateLayout(); } return true; } //############################################################################## //######################### Theme management ################################## //############################################################################## void Worksheet::loadTheme(const QString& theme) { KConfig config(ThemeHandler::themeFilePath(theme), KConfig::SimpleConfig); //apply the same background color for Worksheet as for the CartesianPlot const KConfigGroup group = config.group("CartesianPlot"); this->setBackgroundBrushStyle((Qt::BrushStyle)group.readEntry("BackgroundBrushStyle",(int) this->backgroundBrushStyle())); this->setBackgroundColorStyle((PlotArea::BackgroundColorStyle)(group.readEntry("BackgroundColorStyle",(int) this->backgroundColorStyle()))); this->setBackgroundFirstColor(group.readEntry("BackgroundFirstColor",(QColor) this->backgroundFirstColor())); this->setBackgroundImageStyle((PlotArea::BackgroundImageStyle)group.readEntry("BackgroundImageStyle",(int) this->backgroundImageStyle())); this->setBackgroundOpacity(group.readEntry("BackgroundOpacity", this->backgroundOpacity())); this->setBackgroundSecondColor(group.readEntry("BackgroundSecondColor",(QColor) this->backgroundSecondColor())); this->setBackgroundType((PlotArea::BackgroundType)(group.readEntry("BackgroundType",(int) this->backgroundType()))); //load the theme for all the children const QVector& childElements = children(AbstractAspect::IncludeHidden); for (auto* child : childElements) child->loadThemeConfig(config); } diff --git a/src/backend/worksheet/plots/3d/Plot3D.cpp b/src/backend/worksheet/plots/3d/Plot3D.cpp index 1a1cc3bc4..88a5882e6 100644 --- a/src/backend/worksheet/plots/3d/Plot3D.cpp +++ b/src/backend/worksheet/plots/3d/Plot3D.cpp @@ -1,1351 +1,1351 @@ /*************************************************************************** File : Plot3D.cpp Project : LabPlot Description : 3D plot -------------------------------------------------------------------- Copyright : (C) 2015 by Minh Ngo (minh@fedoraproject.org) ***************************************************************************/ /*************************************************************************** * * * 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 "Plot3D.h" #include "Plot3DPrivate.h" #include "Surface3D.h" #include "Curve3D.h" #include "Axes.h" #include "MouseInteractor.h" #include "VTKGraphicsItem.h" #include "XmlAttributeReader.h" #include "backend/lib/commandtemplates.h" #include "backend/lib/XmlStreamReader.h" #include "backend/worksheet/plots/PlotArea.h" #include "backend/worksheet/Worksheet.h" #include "backend/core/AbstractAspect.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Plot3D::Plot3D(const QString& name) : AbstractPlot(name, new Plot3DPrivate(this)){ } void Plot3D::childSelected(const AbstractAspect* aspect) { Base3D* object = qobject_cast(const_cast(aspect)); if (object != 0) object->select(true); AbstractPlot::childSelected(aspect); Q_D(Plot3D); d->vtkItem->refresh(); } void Plot3D::childDeselected(const AbstractAspect* aspect) { Base3D* object = qobject_cast(const_cast(aspect)); if (object != 0) object->select(false); AbstractPlot::childDeselected(aspect); Q_D(Plot3D); d->vtkItem->refresh(); } void Plot3D::handleAspectAdded(const AbstractAspect* aspect) { Q_D(Plot3D); if (d->isInitialized) { Base3D* object = dynamic_cast(const_cast(aspect)); if (object != 0) object->recover(); if (d->axes) d->axes->updateBounds(); d->resetCamera(); d->vtkItem->refresh(); Surface3D* surface = dynamic_cast(object); if (surface) { d->surfaces.insert(surface); } else { Curve3D* curve = dynamic_cast(object); if (curve) { d->curves.insert(curve); } else d->axes = dynamic_cast(object); } } } void Plot3D::init(bool transform){ Q_D(Plot3D); if (d->isInitialized) return; if (d->context == 0) return; qDebug() << Q_FUNC_INFO << "Init"; m_plotArea = new PlotArea(name() + " plot area"); addChild(m_plotArea); initActions(); d->init(); d->isInitialized = true; initMenus(); if (transform) retransform(); } void Plot3D::setContext(QGLContext *context) { Q_D(Plot3D); d->context = context; } Plot3D::~Plot3D(){ } QIcon Plot3D::icon() const { // TODO: Replace by some 3D chart return KIcon("office-chart-line"); } BoundingBox Plot3D::ranges() const { Q_D(const Plot3D); if (!d->ranges.isInitialized()) { qDebug() << Q_FUNC_INFO << "ranges has not been initialized. returning bounds"; return bounds(); } qDebug() << Q_FUNC_INFO << "returning ranges"; return d->ranges; } BoundingBox Plot3D::bounds() const { Q_D(const Plot3D); return d->bounds; } void Plot3D::configureAspect(AbstractAspect* aspect) { Q_D(Plot3D); addChild(aspect); connect(aspect, SIGNAL(parametersChanged()), SLOT(onParametersChanged())); connect(aspect, SIGNAL(removed()), d->vtkItem, SLOT(refresh())); connect(aspect, SIGNAL(removed()), SLOT(onItemRemoved())); connect(aspect, SIGNAL(boundsChanged(const BoundingBox&)), SLOT(updateBounds())); } void Plot3D::onParametersChanged() { Q_D(Plot3D); if (d->axes) d->axes->updateBounds(); d->resetCamera(); d->vtkItem->refresh(); } void Plot3D::addSurface() { Q_D(Plot3D); Surface3D* newSurface = new Surface3D; newSurface->setXScaling(d->xScaling); newSurface->setYScaling(d->yScaling); newSurface->setZScaling(d->zScaling); newSurface->setRenderer(d->renderer); d->surfaces.insert(newSurface); configureAspect(newSurface); d->resetCamera(); if (d->axes) d->axes->updateBounds(); d->vtkItem->refresh(); } void Plot3D::addCurve() { Q_D(Plot3D); Curve3D* newCurve = new Curve3D; newCurve->setXScaling(d->xScaling); newCurve->setYScaling(d->yScaling); newCurve->setZScaling(d->zScaling); newCurve->setRenderer(d->renderer); d->curves.insert(newCurve); configureAspect(newCurve); d->resetCamera(); d->vtkItem->refresh(); if (d->axes) d->axes->updateBounds(); } void Plot3D::setupAxes() { Q_D(Plot3D); d->axes->setRenderer(d->renderer); configureAspect(d->axes); d->interactor->setAxes(d->axes); addAxesAction->setEnabled(false); } void Plot3D::addAxes() { Q_D(Plot3D); d->axes = new Axes; setupAxes(); } void Plot3D::onItemRemoved() { Q_D(Plot3D); // TODO: Update axes bounding box Surface3D* surface = qobject_cast(sender()); if (surface != 0) { qDebug() << "Remove surface"; d->surfaces.remove(surface); if (d->axes) d->axes->updateBounds(); d->resetCamera(); return; } Curve3D* curve = qobject_cast(sender()); if (curve != 0) { qDebug() << "Remove curve"; d->curves.remove(curve); if (d->axes) d->axes->updateBounds(); d->resetCamera(); return; } Axes* axes = qobject_cast(sender()); if (axes != 0) { qDebug() << "Remove axes"; d->axes = 0; addAxesAction->setEnabled(true); d->interactor->setAxes(0); return; } } void Plot3D::onAxesClicked() { qDebug() << Q_FUNC_INFO; Q_D(Plot3D); if (d->axes) { deselectObjects(); emit currentAspectChanged(d->axes); } } void Plot3D::onAxesHovered() { qDebug() << Q_FUNC_INFO; Q_D(Plot3D); if (d->axes) { foreach(Surface3D* surface, d->surfaces) { surface->highlight(false); } foreach(Curve3D* curve, d->curves) { curve->highlight(false); } d->axes->highlight(true); d->vtkItem->refresh(); } } void Plot3D::deselectObjects() { Q_D(Plot3D); foreach(Surface3D* surface, d->surfaces) { surface->select(false); } foreach(Curve3D* curve, d->curves) { curve->select(false); } if (d->axes) d->axes->select(false); } void Plot3D::dehighlightObjects() { Q_D(Plot3D); foreach(Surface3D* surface, d->surfaces) surface->highlight(false); foreach(Curve3D* curve, d->curves) curve->highlight(false); if (d->axes) d->axes->highlight(false); } void Plot3D::onObjectClicked(vtkProp* object) { Q_D(Plot3D); if (object == 0) { // Deselect all Plot3D children qDebug() << Q_FUNC_INFO << "Deselect"; deselectObjects(); emit currentAspectChanged(this); } else { foreach(Surface3D* surface, d->surfaces) { if (*surface == object) { qDebug() << Q_FUNC_INFO << "Surface clicked" << surface->name(); emit currentAspectChanged(surface); surface->select(true); } else { surface->select(false); } } foreach(Curve3D* curve, d->curves) { if (*curve == object) { qDebug() << Q_FUNC_INFO << "Curve clicked" << curve->name(); emit currentAspectChanged(curve); curve->select(true); } else { curve->select(false); } } if (d->axes && *d->axes != object) d->axes->select(false); } } void Plot3D::onObjectHovered(vtkProp* object) { Q_D(Plot3D); if (object == 0) { dehighlightObjects(); } else { foreach(Surface3D* surface, d->surfaces) surface->highlight(*surface == object); foreach(Curve3D* curve, d->curves) curve->highlight(*curve == object); if (d->axes && *d->axes != object) d->axes->highlight(false); } d->vtkItem->refresh(); } void Plot3D::setPrinting(bool pred) { plotArea()->setVisible(!pred); AbstractPlot::setPrinting(pred); } void Plot3D::updateBounds() { BoundingBox bb; Q_D(Plot3D); foreach(Surface3D* surface, d->surfaces) bb.AddBox(surface->bounds()); foreach(Curve3D* curve, d->curves) bb.AddBox(curve->bounds()); if (bb != d->bounds) { d->bounds = bb; d->lightAbove->SetPosition(bb.xMax(), bb.yMax(), bb.zMax()); d->lightBelow->SetPosition(bb.xMin(), bb.yMin(), bb.zMin()); emit boundsChanged(bb); } } void Plot3D::initActions() { Q_D(Plot3D); //"add new" actions addCurveAction = new KAction(KIcon("3d-curve"), i18n("3D-curve"), this); addEquationCurveAction = new KAction(KIcon("3d-equation-curve"), i18n("3D-curve from a mathematical equation"), this); // TODO: Implement addEquationCurveAction->setVisible(false); addSurfaceAction = new KAction(KIcon("3d-surface"), i18n("3D-surface"), this); addAxesAction = new KAction(KIcon("axis-horizontal"), i18n("Axes"), this); if (d->axes) addAxesAction->setEnabled(false); connect(addCurveAction, SIGNAL(triggered()), SLOT(addCurve())); // connect(addEquationCurveAction, SIGNAL(triggered()), SLOT(addEquationCurve())); connect(addSurfaceAction, SIGNAL(triggered()), SLOT(addSurface())); connect(addAxesAction, SIGNAL(triggered()), SLOT(addAxes())); //zoom/navigate actions scaleAutoAction = new KAction(KIcon("auto-scale-all"), i18n("auto scale"), this); scaleAutoXAction = new KAction(KIcon("auto-scale-x"), i18n("auto scale X"), this); scaleAutoYAction = new KAction(KIcon("auto-scale-y"), i18n("auto scale Y"), this); scaleAutoZAction = new KAction(KIcon("auto-scale-y"), i18n("auto scale Z"), this); zoomInAction = new KAction(KIcon("zoom-in"), i18n("zoom in"), this); zoomOutAction = new KAction(KIcon("zoom-out"), i18n("zoom out"), this); zoomInXAction = new KAction(KIcon("zoom-in-x"), i18n("zoom in X"), this); zoomOutXAction = new KAction(KIcon("zoom-out-x"), i18n("zoom out X"), this); zoomInYAction = new KAction(KIcon("zoom-in-y"), i18n("zoom in Y"), this); zoomOutYAction = new KAction(KIcon("zoom-out-y"), i18n("zoom out Y"), this); zoomInZAction = new KAction(KIcon("zoom-in-z"), i18n("zoom in Z"), this); zoomOutZAction = new KAction(KIcon("zoom-out-z"), i18n("zoom out Z"), this); shiftLeftXAction = new KAction(KIcon("shift-left-x"), i18n("shift left X"), this); shiftRightXAction = new KAction(KIcon("shift-right-x"), i18n("shift right X"), this); shiftUpYAction = new KAction(KIcon("shift-up-y"), i18n("shift up Y"), this); shiftDownYAction = new KAction(KIcon("shift-down-y"), i18n("shift down Y"), this); shiftUpZAction = new KAction(KIcon("shift-up-y"), i18n("shift up Z"), this); shiftDownZAction = new KAction(KIcon("shift-down-y"), i18n("shift down Z"), this); connect(scaleAutoAction, SIGNAL(triggered()), SLOT(autoScale())); connect(scaleAutoXAction, SIGNAL(triggered()), SLOT(autoScaleX())); connect(scaleAutoYAction, SIGNAL(triggered()), SLOT(autoScaleY())); connect(scaleAutoZAction, SIGNAL(triggered()), SLOT(autoScaleZ())); connect(zoomInAction, SIGNAL(triggered()), SLOT(zoomIn())); connect(zoomOutAction, SIGNAL(triggered()), SLOT(zoomOut())); connect(zoomInXAction, SIGNAL(triggered()), SLOT(zoomInX())); connect(zoomOutXAction, SIGNAL(triggered()), SLOT(zoomOutX())); connect(zoomInYAction, SIGNAL(triggered()), SLOT(zoomInY())); connect(zoomOutYAction, SIGNAL(triggered()), SLOT(zoomOutY())); connect(zoomOutZAction, SIGNAL(triggered()), SLOT(zoomOutZ())); connect(zoomInZAction, SIGNAL(triggered()), SLOT(zoomInZ())); connect(shiftLeftXAction, SIGNAL(triggered()), SLOT(shiftLeftX())); connect(shiftRightXAction, SIGNAL(triggered()), SLOT(shiftRightX())); connect(shiftUpYAction, SIGNAL(triggered()), SLOT(shiftUpY())); connect(shiftDownYAction, SIGNAL(triggered()), SLOT(shiftDownY())); connect(shiftUpZAction, SIGNAL(triggered()), SLOT(shiftUpZ())); connect(shiftDownZAction, SIGNAL(triggered()), SLOT(shiftDownZ())); //rotation action rotateClockwiseAction = new KAction(KIcon("rotate-clockwise"), i18n("rotate clockwise"), this); rotateCounterclockwiseAction = new KAction(KIcon("rotate-counterclockwise"), i18n("rotate counterclockwise"), this); tiltLeftAction = new KAction(KIcon("tilt-left"), i18n("tilt left"), this); tiltRightAction = new KAction(KIcon("tilt-right"), i18n("tilt right"), this); tiltUpAction = new KAction(KIcon("tilt-up"), i18n("tilt up"), this); tiltDownAction = new KAction(KIcon("tilt-down"), i18n("tilt down"), this); resetRotationAction = new KAction(KIcon("reset-rotation"), i18n("reset rotation"), this); //visibility action visibilityAction = new QAction(i18n("visible"), this); visibilityAction->setCheckable(true); connect(visibilityAction, SIGNAL(triggered()), this, SLOT(onVisibilityChanged())); } void Plot3D::onVisibilityChanged(){ Q_D(Plot3D); setVisible(!d->isVisible()); } void Plot3D::autoScale() { setRanges(bounds()); } void Plot3D::autoScaleX() { const BoundingBox& bb = bounds(); BoundingBox r = ranges(); r.setXMin(bb.xMin()); r.setXMax(bb.xMax()); setRanges(r); } void Plot3D::autoScaleY() { const BoundingBox& bb = bounds(); BoundingBox r = ranges(); r.setYMin(bb.yMin()); r.setYMax(bb.yMax()); setRanges(r); } void Plot3D::autoScaleZ() { const BoundingBox& bb = bounds(); BoundingBox r = ranges(); r.setZMin(bb.zMin()); r.setZMax(bb.zMax()); setRanges(r); } void Plot3D::zoomIn() { BoundingBox r = ranges(); r.Scale(0.9, 0.9, 0.9); setRanges(r); } void Plot3D::zoomOut() { BoundingBox r = ranges(); r.Scale(1.1, 1.1, 1.1); setRanges(r); } void Plot3D::zoomInX() { BoundingBox r = ranges(); r.Scale(0.9, 1, 1); setRanges(r); } void Plot3D::zoomOutX() { BoundingBox r = ranges(); r.Scale(1.1, 1, 1); setRanges(r); } void Plot3D::zoomInY() { BoundingBox r = ranges(); r.Scale(1, 0.9, 1); setRanges(r); } void Plot3D::zoomOutY() { BoundingBox r = ranges(); r.Scale(1, 1.1, 1); setRanges(r); } void Plot3D::zoomInZ() { BoundingBox r = ranges(); r.Scale(1, 1, 0.9); setRanges(r); } void Plot3D::zoomOutZ() { BoundingBox r = ranges(); r.Scale(1, 1, 1.1); setRanges(r); } void Plot3D::shiftLeftX() { BoundingBox r = ranges(); const double dx = (r.xMax() - r.xMin()) * 0.1; r.setXMin(r.xMin() - dx); r.setXMax(r.xMax() - dx); setRanges(r); } void Plot3D::shiftRightX() { BoundingBox r = ranges(); const double dx = (r.xMax() - r.xMin()) * 0.1; r.setXMin(r.xMin() + dx); r.setXMax(r.xMax() + dx); setRanges(r); } void Plot3D::shiftUpY() { BoundingBox r = ranges(); const double dy = (r.yMax() - r.yMin()) * 0.1; r.setYMin(r.yMin() + dy); r.setYMax(r.yMax() + dy); setRanges(r); } void Plot3D::shiftDownY() { BoundingBox r = ranges(); const double dy = (r.yMax() - r.yMin()) * 0.1; r.setYMin(r.yMin() - dy); r.setYMax(r.yMax() - dy); setRanges(r); } void Plot3D::shiftUpZ() { BoundingBox r = ranges(); const double dz = (r.zMax() - r.zMin()) * 0.1; r.setZMin(r.zMin() + dz); r.setZMax(r.zMax() + dz); setRanges(r); } void Plot3D::shiftDownZ() { BoundingBox r = ranges(); const double dz = (r.zMax() - r.zMin()) * 0.1; r.setZMin(r.zMin() - dz); r.setZMax(r.zMax() - dz); setRanges(r); } void Plot3D::initMenus(){ addNewMenu = new QMenu(i18n("Add new")); addNewMenu->addAction(addAxesAction); addNewMenu->addAction(addCurveAction); addNewMenu->addAction(addEquationCurveAction); addNewMenu->addAction(addSurfaceAction); zoomMenu = new QMenu(i18n("Zoom")); zoomMenu->addAction(scaleAutoAction); zoomMenu->addAction(scaleAutoXAction); zoomMenu->addAction(scaleAutoYAction); zoomMenu->addAction(scaleAutoZAction); zoomMenu->addSeparator(); zoomMenu->addAction(zoomInAction); zoomMenu->addAction(zoomOutAction); zoomMenu->addSeparator(); zoomMenu->addAction(zoomInXAction); zoomMenu->addAction(zoomOutXAction); zoomMenu->addSeparator(); zoomMenu->addAction(zoomInYAction); zoomMenu->addAction(zoomOutYAction); zoomMenu->addSeparator(); zoomMenu->addAction(zoomInZAction); zoomMenu->addAction(zoomOutZAction); zoomMenu->addSeparator(); zoomMenu->addAction(shiftLeftXAction); zoomMenu->addAction(shiftRightXAction); zoomMenu->addSeparator(); zoomMenu->addAction(shiftUpYAction); zoomMenu->addAction(shiftDownYAction); zoomMenu->addSeparator(); zoomMenu->addAction(shiftUpZAction); zoomMenu->addAction(shiftDownZAction); rotateMenu = new QMenu(i18n("Rotate")); rotateMenu->addAction(rotateClockwiseAction); rotateMenu->addAction(rotateCounterclockwiseAction); rotateMenu->addSeparator(); rotateMenu->addAction(tiltLeftAction); rotateMenu->addAction(tiltRightAction); rotateMenu->addAction(tiltUpAction); rotateMenu->addAction(tiltDownAction); rotateMenu->addSeparator(); rotateMenu->addAction(resetRotationAction); rotateMenu->addSeparator(); QMenu* angleMenu = new QMenu(i18n("rotation angle")); //TODO: use QActionGroup and exlusive actions for this later. angleMenu->addAction("1°"); angleMenu->addAction("2°"); angleMenu->addAction("5°"); angleMenu->addAction("10°"); angleMenu->addAction("20°"); angleMenu->addAction("30°"); angleMenu->addAction("40°"); angleMenu->addAction("50°"); angleMenu->addAction("60°"); angleMenu->addAction("70°"); angleMenu->addAction("80°"); angleMenu->addAction("90°"); rotateMenu->addMenu(angleMenu); } QMenu* Plot3D::createContextMenu(){ QMenu* menu = WorksheetElement::createContextMenu(); QAction* firstAction = menu->actions().at(1); visibilityAction->setChecked(isVisible()); menu->insertAction(firstAction, visibilityAction); menu->insertMenu(firstAction, addNewMenu); menu->insertMenu(firstAction, zoomMenu); // TODO: Implement // menu->insertMenu(firstAction, rotateMenu); menu->insertSeparator(firstAction); return menu; } void Plot3D::retransform() { Q_D(Plot3D); if (d->context == 0) return; if (!d->isInitialized) init(false); d->retransform(); WorksheetElementContainer::retransform(); } //############################################################################## //########################## getter methods ################################## //############################################################################## // General BASIC_SHARED_D_READER_IMPL(Plot3D, Plot3D::Scaling, xScaling, xScaling) BASIC_SHARED_D_READER_IMPL(Plot3D, Plot3D::Scaling, yScaling, yScaling) BASIC_SHARED_D_READER_IMPL(Plot3D, Plot3D::Scaling, zScaling, zScaling) // Background BASIC_SHARED_D_READER_IMPL(Plot3D, PlotArea::BackgroundType, backgroundType, backgroundType) BASIC_SHARED_D_READER_IMPL(Plot3D, PlotArea::BackgroundColorStyle, backgroundColorStyle, backgroundColorStyle) BASIC_SHARED_D_READER_IMPL(Plot3D, PlotArea::BackgroundImageStyle, backgroundImageStyle, backgroundImageStyle) BASIC_SHARED_D_READER_IMPL(Plot3D, Qt::BrushStyle, backgroundBrushStyle, backgroundBrushStyle) CLASS_SHARED_D_READER_IMPL(Plot3D, QColor, backgroundFirstColor, backgroundFirstColor) CLASS_SHARED_D_READER_IMPL(Plot3D, QColor, backgroundSecondColor, backgroundSecondColor) CLASS_SHARED_D_READER_IMPL(Plot3D, QString, backgroundFileName, backgroundFileName) BASIC_SHARED_D_READER_IMPL(Plot3D, float, backgroundOpacity, backgroundOpacity) // Light BASIC_SHARED_D_READER_IMPL(Plot3D, double, intensity, intensity) BASIC_SHARED_D_READER_IMPL(Plot3D, QColor, ambient, ambient) BASIC_SHARED_D_READER_IMPL(Plot3D, QColor, diffuse, diffuse) BASIC_SHARED_D_READER_IMPL(Plot3D, QColor, specular, specular) BASIC_SHARED_D_READER_IMPL(Plot3D, double, elevation, elevation) BASIC_SHARED_D_READER_IMPL(Plot3D, double, azimuth, azimuth) BASIC_SHARED_D_READER_IMPL(Plot3D, double, coneAngle, coneAngle) //############################################################################## //################# setter methods and undo commands ########################## //############################################################################## // Geometry and data ranges STD_SETTER_CMD_IMPL_F_S(Plot3D, SetRect, QRectF, rect, retransform) STD_SETTER_IMPL(Plot3D, Rect, const QRectF&, rect, "%1: set geometry rect"); // General STD_SETTER_CMD_IMPL_F_S(Plot3D, SetXScaling, Plot3D::Scaling, xScaling, updateXScaling) STD_SETTER_IMPL(Plot3D, XScaling, Plot3D::Scaling, xScaling, "%1: X axis scaling changed") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetYScaling, Plot3D::Scaling, yScaling, updateYScaling) STD_SETTER_IMPL(Plot3D, YScaling, Plot3D::Scaling, yScaling, "%1: Y axis scaling changed") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetZScaling, Plot3D::Scaling, zScaling, updateZScaling) STD_SETTER_IMPL(Plot3D, ZScaling, Plot3D::Scaling, zScaling, "%1: Z axis scaling changed") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetRanges, BoundingBox, ranges, updateRanges) STD_SETTER_IMPL(Plot3D, Ranges, const BoundingBox&, ranges, "%1: bound range changed") // Background STD_SETTER_CMD_IMPL_F_S(Plot3D, SetBackgroundType, PlotArea::BackgroundType, backgroundType, updateBackground) STD_SETTER_IMPL(Plot3D, BackgroundType, PlotArea::BackgroundType, backgroundType, "%1: background type changed") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetBackgroundColorStyle, PlotArea::BackgroundColorStyle, backgroundColorStyle, updateBackground) STD_SETTER_IMPL(Plot3D, BackgroundColorStyle, PlotArea::BackgroundColorStyle, backgroundColorStyle, "%1: background color style changed") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetBackgroundImageStyle, PlotArea::BackgroundImageStyle, backgroundImageStyle, updateBackground) STD_SETTER_IMPL(Plot3D, BackgroundImageStyle, PlotArea::BackgroundImageStyle, backgroundImageStyle, "%1: background image style changed") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetBackgroundBrushStyle, Qt::BrushStyle, backgroundBrushStyle, updateBackground) STD_SETTER_IMPL(Plot3D, BackgroundBrushStyle, Qt::BrushStyle, backgroundBrushStyle, "%1: background brush style changed") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetBackgroundFirstColor, QColor, backgroundFirstColor, updateBackground) STD_SETTER_IMPL(Plot3D, BackgroundFirstColor, const QColor&, backgroundFirstColor, "%1: set background first color") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetBackgroundSecondColor, QColor, backgroundSecondColor, updateBackground) STD_SETTER_IMPL(Plot3D, BackgroundSecondColor, const QColor&, backgroundSecondColor, "%1: set background second color") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetBackgroundFileName, QString, backgroundFileName, updateBackground) STD_SETTER_IMPL(Plot3D, BackgroundFileName, const QString&, backgroundFileName, "%1: set background image") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetBackgroundOpacity, float, backgroundOpacity, updateBackground) STD_SETTER_IMPL(Plot3D, BackgroundOpacity, float, backgroundOpacity, "%1: set opacity") // Light STD_SETTER_CMD_IMPL_F_S(Plot3D, SetIntensity, double, intensity, updateLight) STD_SETTER_IMPL(Plot3D, Intensity, double, intensity, "%1: intensity changed") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetAmbient, QColor, ambient, updateLight) STD_SETTER_IMPL(Plot3D, Ambient, const QColor&, ambient, "%1: ambient changed") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetDiffuse, QColor, diffuse, updateLight) STD_SETTER_IMPL(Plot3D, Diffuse, const QColor&, diffuse, "%1: diffuse changed") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetSpecular, QColor, specular, updateLight) STD_SETTER_IMPL(Plot3D, Specular, const QColor&, specular, "%1: specular changed") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetElevation, double, elevation, updateLight) STD_SETTER_IMPL(Plot3D, Elevation, double, elevation, "%1: elevation changed") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetAzimuth, double, azimuth, updateLight) STD_SETTER_IMPL(Plot3D, Azimuth, double, azimuth, "%1: azimuth changed") STD_SETTER_CMD_IMPL_F_S(Plot3D, SetConeAngle, double, coneAngle, updateLight) STD_SETTER_IMPL(Plot3D, ConeAngle, double, coneAngle, "%1: coneAngle changed") //############################################################################## //######################### Private implementation ############################# //############################################################################## Plot3DPrivate::Plot3DPrivate(Plot3D* owner) : AbstractPlotPrivate(owner) , q(owner) , context(0) , vtkItem(0) , isInitialized(false) , axes(0) , xScaling(Plot3D::Scaling_Linear) , yScaling(Plot3D::Scaling_Linear) , zScaling(Plot3D::Scaling_Linear) , intensity(1.0) , ambient(Qt::white) , diffuse(Qt::white) , specular(Qt::white) , elevation(15) , azimuth(15) , coneAngle(15) { //read default settings KConfig config; KConfigGroup group = config.group("Plot3D"); //general //background backgroundType = (PlotArea::BackgroundType) group.readEntry("BackgroundType", (int) PlotArea::Color); backgroundColorStyle = (PlotArea::BackgroundColorStyle) group.readEntry("BackgroundColorStyle", (int) PlotArea::HorizontalLinearGradient); backgroundImageStyle = (PlotArea::BackgroundImageStyle) group.readEntry("BackgroundImageStyle", (int) PlotArea::Scaled); backgroundBrushStyle = (Qt::BrushStyle) group.readEntry("BackgroundBrushStyle", (int) Qt::SolidPattern); backgroundFileName = group.readEntry("BackgroundFileName", QString()); backgroundFirstColor = group.readEntry("BackgroundFirstColor", QColor(Qt::white)); backgroundSecondColor = group.readEntry("BackgroundSecondColor", QColor(Qt::black)); backgroundOpacity = group.readEntry("BackgroundOpacity", 1.0); //Geometry, specify the plot rect in scene coordinates. const float x = Worksheet::convertToSceneUnits(2, Worksheet::Centimeter); const float y = Worksheet::convertToSceneUnits(2, Worksheet::Centimeter); const float w = Worksheet::convertToSceneUnits(10, Worksheet::Centimeter); const float h = Worksheet::convertToSceneUnits(10, Worksheet::Centimeter); rect = QRectF(x,y,w,h); } Plot3DPrivate::~Plot3DPrivate() { } void Plot3DPrivate::mousePressEvent(QGraphicsSceneMouseEvent* event) { Q_UNUSED(event); AbstractPlotPrivate::mousePressEvent(event); } void Plot3DPrivate::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { Q_UNUSED(event); } namespace { // http://www.vtk.org/Wiki/VTK/Examples/Cxx/Qt/ImageDataToQImage QImage vtkImageDataToQImage(vtkImageData* imageData) { if (!imageData) return QImage(); int width = imageData->GetDimensions()[0]; int height = imageData->GetDimensions()[1]; QImage image(width, height, QImage::Format_RGB32); QRgb* rgbPtr = reinterpret_cast(image.bits()) + width * (height-1); unsigned char* colorsPtr = reinterpret_cast(imageData->GetScalarPointer()); for(int row = 0; row < height; ++row) { for (int col = 0; col < width; ++col) { *(rgbPtr++) = QColor(colorsPtr[0], colorsPtr[1], colorsPtr[2]).rgb(); colorsPtr += 3; } rgbPtr -= width * 2; } return image; } } void Plot3DPrivate::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { Q_UNUSED(option); Q_UNUSED(widget); if (!q->isVisible()) return; const double halfWidth = rect.width() / 2; const double halfHeight = rect.height() / 2; if (m_printing){ vtkSmartPointer wti = vtkSmartPointer::New(); wti->SetInput(vtkItem->GetRenderWindow()); wti->Update(); vtkSmartPointer image = wti->GetOutput(); const QPixmap pixmap(QPixmap::fromImage(vtkImageDataToQImage(image))); painter->drawPixmap(-halfWidth, -halfHeight, pixmap); painter->setPen(QPen(Qt::black, 5)); painter->drawRect(-halfWidth, -halfHeight, rect.width(), rect.height()); } else { painter->save(); painter->setPen(QPen(Qt::black, 5)); painter->drawRect(-halfWidth, -halfHeight, rect.width(), rect.height()); painter->restore(); AbstractPlotPrivate::paint(painter, option, widget); } } void Plot3DPrivate::updateLight(bool notify) { vtkLight* lights[] = {lightAbove, lightBelow}; for (int i = 0; i < 2; ++i) { lights[i]->SetIntensity(intensity); lights[i]->SetAmbientColor(ambient.redF(), ambient.greenF(), ambient.blueF()); lights[i]->SetDiffuseColor(diffuse.redF(), diffuse.greenF(), diffuse.blueF()); lights[i]->SetSpecularColor(specular.redF(), specular.greenF(), specular.blueF()); lights[i]->SetDirectionAngle(elevation, azimuth); lights[i]->SetConeAngle(coneAngle); } if (notify) emit q->parametersChanged(); } void Plot3DPrivate::initLights() { //light lightAbove = vtkSmartPointer::New(); lightBelow = vtkSmartPointer::New(); lightAbove->SetFocalPoint(1.876, 0.6125, 0); lightAbove->SetPosition(0.875, 1.6125, 1); lightBelow->SetFocalPoint(-1.876, -0.6125, 0); lightBelow->SetPosition(-0.875, -1.612, -1); renderer->AddLight(lightAbove); renderer->AddLight(lightBelow); } void Plot3DPrivate::init() { //initialize VTK vtkItem = new VTKGraphicsItem(context, this); vtkItem->connect(q, SIGNAL(parametersChanged()), SLOT(refresh())); //foreground renderer renderer = vtkSmartPointer::New(); //background renderer backgroundRenderer = vtkSmartPointer::New(); //render window and layers vtkGenericOpenGLRenderWindow* renderWindow = vtkItem->GetRenderWindow(); renderWindow->SetNumberOfLayers(2); renderWindow->AddRenderer(backgroundRenderer); renderWindow->AddRenderer(renderer); backgroundRenderer->SetLayer(0); renderer->SetLayer(1); backgroundRenderer->InteractiveOff(); interactor = vtkSmartPointer::New(); interactor->SetDefaultRenderer(renderer); q->connect(&interactor->broadcaster, SIGNAL(objectClicked(vtkProp*)), SLOT(onObjectClicked(vtkProp*))); q->connect(&interactor->broadcaster, SIGNAL(objectHovered(vtkProp*)), SLOT(onObjectHovered(vtkProp*))); q->connect(&interactor->broadcaster, SIGNAL(axesClicked()), SLOT(onAxesClicked())); q->connect(&interactor->broadcaster, SIGNAL(axesHovered()), SLOT(onAxesHovered())); renderWindow->GetInteractor()->SetInteractorStyle(interactor); initLights(); backgroundImageActor = vtkSmartPointer::New(); backgroundRenderer->AddActor(backgroundImageActor); foreach(Surface3D* surface, surfaces) { surface->setRenderer(renderer); q->configureAspect(surface); } foreach(Curve3D* curve, curves) { curve->setRenderer(renderer); q->configureAspect(curve); } if (axes) { qDebug() << Q_FUNC_INFO << "Setup axes"; q->setupAxes(); } } void Plot3DPrivate::setupCamera() { //set the background camera in front of the background image (fill the complete layer) vtkCamera* camera = backgroundRenderer->GetActiveCamera(); camera->ParallelProjectionOn(); const double x = rect.width() / 2; const double y = rect.height() / 2; camera->SetFocalPoint(x, y, 0.0); camera->SetParallelScale(y); camera->SetPosition(x, y, 900); } void Plot3DPrivate::retransform() { if (!isInitialized) return; prepareGeometryChange(); const double halfWidth = rect.width() / 2; const double halfHeight = rect.height() / 2; setPos(rect.x() + halfWidth, rect.y() + halfHeight); //plotArea position is always (0, 0) in parent's coordinates, don't need to update here q->plotArea()->setRect(rect); if (halfHeight < 0.1 || halfWidth < 0.1) { vtkItem->hide(); } else { vtkItem->show(); vtkItem->setGeometry(-halfWidth, -halfHeight, rect.width(), rect.height()); setupCamera(); updateBackground(false); updateLight(); } WorksheetElementContainerPrivate::recalcShapeAndBoundingRect(); } void Plot3DPrivate::resetCamera() { qDebug() << Q_FUNC_INFO; renderer->ResetCamera(); renderer->GetActiveCamera()->Azimuth(15); } void Plot3DPrivate::updateXScaling() { qDebug() << Q_FUNC_INFO; foreach (Surface3D* surface, surfaces) { surface->setXScaling(xScaling); } foreach (Curve3D* curve, curves) { curve->setXScaling(xScaling); } axes->setXScaling(xScaling); foreach (Surface3D* surface, surfaces) { surface->refresh(); } foreach (Curve3D* curve, curves) { curve->refresh(); } resetCamera(); vtkItem->refresh(); } void Plot3DPrivate::updateYScaling() { foreach (Surface3D* surface, surfaces) { surface->setYScaling(yScaling); } foreach (Curve3D* curve, curves) { curve->setYScaling(yScaling); } axes->setYScaling(yScaling); foreach (Surface3D* surface, surfaces) { surface->refresh(); } foreach (Curve3D* curve, curves) { curve->refresh(); } resetCamera(); vtkItem->refresh(); } void Plot3DPrivate::updateZScaling() { foreach (Surface3D* surface, surfaces) { surface->setZScaling(zScaling); } foreach (Curve3D* curve, curves) { curve->setZScaling(zScaling); } axes->setZScaling(zScaling); foreach (Surface3D* surface, surfaces) { surface->refresh(); } foreach (Curve3D* curve, curves) { curve->refresh(); } resetCamera(); vtkItem->refresh(); } void Plot3DPrivate::updateRanges(bool notify) { qDebug() << Q_FUNC_INFO << __LINE__; foreach(Surface3D* surface, surfaces) { surface->setRanges(ranges); } foreach(Curve3D* curve, curves) { curve->setRanges(ranges); } axes->setRanges(ranges); axes->updateBounds(); if (notify) emit q->parametersChanged(); } void Plot3DPrivate::updateBackground(bool notify) { const QRectF rect(0, 0, this->rect.width(), this->rect.height()); //prepare the image QImage image(rect.width(), rect.height(), QImage::Format_ARGB32_Premultiplied); double borderCornerRadius = 0.0; //TODO QPainter painter(&image); painter.setOpacity(backgroundOpacity); painter.setPen(Qt::NoPen); if (backgroundType == PlotArea::Color){ switch (backgroundColorStyle){ case PlotArea::SingleColor:{ painter.setBrush(QBrush(backgroundFirstColor)); break; } case PlotArea::HorizontalLinearGradient:{ QLinearGradient linearGrad(rect.topLeft(), rect.topRight()); linearGrad.setColorAt(0, backgroundFirstColor); linearGrad.setColorAt(1, backgroundSecondColor); painter.setBrush(QBrush(linearGrad)); break; } case PlotArea::VerticalLinearGradient:{ QLinearGradient linearGrad(rect.topLeft(), rect.bottomLeft()); linearGrad.setColorAt(0, backgroundFirstColor); linearGrad.setColorAt(1, backgroundSecondColor); painter.setBrush(QBrush(linearGrad)); break; } case PlotArea::TopLeftDiagonalLinearGradient:{ QLinearGradient linearGrad(rect.topLeft(), rect.bottomRight()); linearGrad.setColorAt(0, backgroundFirstColor); linearGrad.setColorAt(1, backgroundSecondColor); painter.setBrush(QBrush(linearGrad)); break; } case PlotArea::BottomLeftDiagonalLinearGradient:{ QLinearGradient linearGrad(rect.bottomLeft(), rect.topRight()); linearGrad.setColorAt(0, backgroundFirstColor); linearGrad.setColorAt(1, backgroundSecondColor); painter.setBrush(QBrush(linearGrad)); break; } case PlotArea::RadialGradient:{ QRadialGradient radialGrad(rect.center(), rect.width()/2); radialGrad.setColorAt(0, backgroundFirstColor); radialGrad.setColorAt(1, backgroundSecondColor); painter.setBrush(QBrush(radialGrad)); break; } } }else if (backgroundType == PlotArea::Image){ if ( !backgroundFileName.trimmed().isEmpty() ) { QPixmap pix(backgroundFileName); if (pix.width() > 0 && pix.height() > 0) { const QImage img(pix.toImage()); painter.fillRect(rect, img.pixel(QPoint(0, 0))); } else { painter.fillRect(rect, Qt::white); } switch (backgroundImageStyle){ case PlotArea::ScaledCropped: pix = pix.scaled(rect.size().toSize(),Qt::KeepAspectRatioByExpanding,Qt::SmoothTransformation); painter.setBrush(QBrush(pix)); painter.setBrushOrigin(0, 0); painter.drawRoundedRect(rect, borderCornerRadius, borderCornerRadius); break; case PlotArea::Scaled: pix = pix.scaled(rect.size().toSize(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation); painter.setBrush(QBrush(pix)); painter.setBrushOrigin(0, 0); painter.drawRoundedRect(rect, borderCornerRadius, borderCornerRadius); break; case PlotArea::ScaledAspectRatio: pix = pix.scaled(rect.size().toSize(),Qt::KeepAspectRatio,Qt::SmoothTransformation); painter.setBrush(QBrush(pix)); painter.setBrushOrigin(0, 0); painter.drawRoundedRect(rect, borderCornerRadius, borderCornerRadius); break; case PlotArea::Centered: painter.drawPixmap(QPointF(rect.center().x()-pix.size().width()/2,rect.center().y()-pix.size().height()/2),pix); break; case PlotArea::Tiled: painter.setBrush(QBrush(pix)); painter.drawRoundedRect(rect, borderCornerRadius, borderCornerRadius); break; case PlotArea::CenterTiled: painter.setBrush(QBrush(pix)); painter.setBrushOrigin(rect.center().x()-pix.size().width()/2, 0); painter.drawRoundedRect(rect, borderCornerRadius, borderCornerRadius); } } else { painter.fillRect(rect, Qt::white); } } else if (backgroundType == PlotArea::Pattern){ painter.fillRect(rect, Qt::white); painter.setBrush(QBrush(backgroundFirstColor, backgroundBrushStyle)); } if ( qFuzzyIsNull(borderCornerRadius) ) painter.drawRect(rect); else painter.drawRoundedRect(rect, borderCornerRadius, borderCornerRadius); //set the prepared image in the background actor vtkSmartPointer qimageToImageSource = vtkSmartPointer::New(); qimageToImageSource->SetQImage(&image); backgroundImageActor->SetInputData(qimageToImageSource->GetOutput()); qimageToImageSource->Update(); if (notify) emit q->parametersChanged(); } //############################################################################## //################## Serialization/Deserialization ########################### //############################################################################## //! Save as XML void Plot3D::save(QXmlStreamWriter* writer) const { Q_D(const Plot3D); writer->writeStartElement("Plot3D"); writeBasicAttributes(writer); writeCommentElement(writer); writer->writeStartElement("general"); writer->writeAttribute("xMinRange", QString::number(d->ranges.xMin())); writer->writeAttribute("xMaxRange", QString::number(d->ranges.xMax())); writer->writeAttribute("yMinRange", QString::number(d->ranges.yMin())); writer->writeAttribute("yMaxRange", QString::number(d->ranges.yMax())); writer->writeAttribute("zMinRange", QString::number(d->ranges.zMin())); writer->writeAttribute("zMaxRange", QString::number(d->ranges.zMax())); writer->writeAttribute("xScaling", QString::number(d->xScaling)); writer->writeAttribute("yScaling", QString::number(d->yScaling)); writer->writeAttribute("zScaling", QString::number(d->zScaling)); writer->writeEndElement(); writer->writeStartElement("background"); writer->writeAttribute("type", QString::number(d->backgroundType)); writer->writeAttribute("colorStyle", QString::number(d->backgroundColorStyle)); writer->writeAttribute("imageStyle", QString::number(d->backgroundImageStyle)); writer->writeAttribute("brushStyle", QString::number(d->backgroundBrushStyle)); writer->writeAttribute("firstColor", d->backgroundFirstColor.name()); writer->writeAttribute("secondColor", d->backgroundSecondColor.name()); writer->writeAttribute("fileName", d->backgroundFileName); writer->writeAttribute("opacity", QString::number(d->backgroundOpacity)); writer->writeEndElement(); writer->writeStartElement("light"); writer->writeAttribute("intensity", QString::number(d->intensity)); writer->writeAttribute("ambient", d->ambient.name()); writer->writeAttribute("diffuse", d->diffuse.name()); writer->writeAttribute("specular", d->specular.name()); writer->writeAttribute("elevation", QString::number(d->elevation)); writer->writeAttribute("azimuth", QString::number(d->azimuth)); writer->writeAttribute("coneAngle", QString::number(d->coneAngle)); writer->writeEndElement(); d->axes->save(writer); foreach(const Surface3D* surface, d->surfaces) surface->save(writer); - + foreach(const Curve3D* curve, d->curves) curve->save(writer); writer->writeEndElement(); } //! Load from XML -bool Plot3D::load(XmlStreamReader* reader) { +bool Plot3D::load(XmlStreamReader* reader, bool preview) { Q_D(Plot3D); if(!reader->isStartElement() || reader->name() != "Plot3D"){ reader->raiseError(i18n("no Plot3D element found")); return false; } if(!readBasicAttributes(reader)){ return false; } const QString attributeWarning = i18n("Attribute '%1' missing or empty, default value is used"); while(!reader->atEnd()){ reader->readNext(); const QStringRef& sectionName = reader->name(); if (reader->isEndElement() && sectionName == "Plot3D") break; if (reader->isEndElement()) continue; if(sectionName == "comment"){ if(!readCommentElement(reader)){ return false; } } else if(sectionName == "general"){ const QXmlStreamAttributes& attribs = reader->attributes(); XmlAttributeReader attributeReader(reader, attribs); attributeReader.checkAndLoadAttribute("xScaling", d->xScaling); attributeReader.checkAndLoadAttribute("yScaling", d->yScaling); attributeReader.checkAndLoadAttribute("zScaling", d->zScaling); double value = VTK_DOUBLE_MAX; attributeReader.checkAndLoadAttribute("xMinRange", value); d->ranges.setXMin(value); value = VTK_DOUBLE_MAX; attributeReader.checkAndLoadAttribute("yMinRange", value); d->ranges.setYMin(value); value = VTK_DOUBLE_MAX; attributeReader.checkAndLoadAttribute("zMinRange", value); d->ranges.setZMin(value); value = VTK_DOUBLE_MIN; attributeReader.checkAndLoadAttribute("xMaxRange", value); d->ranges.setXMax(value); value = VTK_DOUBLE_MIN; attributeReader.checkAndLoadAttribute("yMaxRange", value); d->ranges.setYMax(value); value = VTK_DOUBLE_MIN; attributeReader.checkAndLoadAttribute("zMaxRange", value); d->ranges.setZMax(value); }else if(sectionName == "axes"){ qDebug() << Q_FUNC_INFO << "Load axes"; if (!d->axes) { d->axes = new Axes; if(!d->axes->load(reader)) return false; } }else if(sectionName == "surface3d"){ Surface3D* newSurface = new Surface3D(); newSurface->load(reader); qDebug() << Q_FUNC_INFO << "Load surface" << newSurface->name(); // Scaling has been already initialized in the general section newSurface->setXScaling(d->xScaling); newSurface->setYScaling(d->yScaling); newSurface->setZScaling(d->zScaling); d->surfaces.insert(newSurface); }else if(sectionName == "curve3d"){ Curve3D* newCurve = new Curve3D(); qDebug() << Q_FUNC_INFO << "Load curve" << newCurve->name(); newCurve->load(reader); newCurve->setXScaling(d->xScaling); newCurve->setYScaling(d->yScaling); newCurve->setZScaling(d->zScaling); d->curves.insert(newCurve); }else if(sectionName == "background"){ const QXmlStreamAttributes& attribs = reader->attributes(); XmlAttributeReader attributeReader(reader, attribs); attributeReader.checkAndLoadAttribute("type", d->backgroundType); attributeReader.checkAndLoadAttribute("colorStyle", d->backgroundColorStyle); attributeReader.checkAndLoadAttribute("imageStyle", d->backgroundImageStyle); attributeReader.checkAndLoadAttribute("brushStyle", d->backgroundBrushStyle); attributeReader.checkAndLoadAttribute("firstColor", d->backgroundFirstColor); attributeReader.checkAndLoadAttribute("secondColor", d->backgroundSecondColor); attributeReader.checkAndLoadAttribute("fileName", d->backgroundFileName); attributeReader.checkAndLoadAttribute("opacity", d->backgroundOpacity); }else if(sectionName == "light"){ const QXmlStreamAttributes& attribs = reader->attributes(); XmlAttributeReader attributeReader(reader, attribs); attributeReader.checkAndLoadAttribute("intensity", d->intensity); attributeReader.checkAndLoadAttribute("ambient", d->ambient); attributeReader.checkAndLoadAttribute("diffuse", d->diffuse); attributeReader.checkAndLoadAttribute("specular", d->specular); attributeReader.checkAndLoadAttribute("elevation", d->elevation); attributeReader.checkAndLoadAttribute("azimuth", d->azimuth); attributeReader.checkAndLoadAttribute("coneAngle", d->coneAngle); } } return true; } diff --git a/src/backend/worksheet/plots/3d/Plot3D.h b/src/backend/worksheet/plots/3d/Plot3D.h index 3c21b2ffe..84fc1d4d8 100644 --- a/src/backend/worksheet/plots/3d/Plot3D.h +++ b/src/backend/worksheet/plots/3d/Plot3D.h @@ -1,245 +1,245 @@ /*************************************************************************** File : Plot3D.h Project : LabPlot Description : 3D plot -------------------------------------------------------------------- Copyright : (C) 2015 by Minh Ngo (minh@fedoraproject.org) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #ifndef PLOT3D_H #define PLOT3D_H #include "backend/worksheet/plots/AbstractPlot.h" #include "backend/worksheet/plots/PlotArea.h" class QMenu; class QGLContext; class vtkProp; class BoundingBox; class Plot3DPrivate; class Plot3D : public AbstractPlot { Q_OBJECT Q_DECLARE_PRIVATE(Plot3D) Q_DISABLE_COPY(Plot3D) public: enum Scaling { Scaling_Linear, Scaling_Log10, Scaling_Log2, Scaling_Ln }; explicit Plot3D(const QString &name); virtual ~Plot3D(); void init(bool transform = true); void retransform(); void setPrinting(bool); QIcon icon() const; virtual QMenu* createContextMenu(); - virtual void save(QXmlStreamWriter*) const; - virtual bool load(XmlStreamReader*); + virtual void save(QXmlStreamWriter*) const override; + virtual bool load(XmlStreamReader*, bool preview) override; void setRect(const QRectF&); void setContext(QGLContext *context); BoundingBox bounds() const; // General parameters BASIC_D_ACCESSOR_DECL(Plot3D::Scaling, xScaling, XScaling) BASIC_D_ACCESSOR_DECL(Plot3D::Scaling, yScaling, YScaling) BASIC_D_ACCESSOR_DECL(Plot3D::Scaling, zScaling, ZScaling) CLASS_D_ACCESSOR_DECL(BoundingBox, ranges, Ranges) // Background parameters BASIC_D_ACCESSOR_DECL(float, backgroundOpacity, BackgroundOpacity) BASIC_D_ACCESSOR_DECL(PlotArea::BackgroundType, backgroundType, BackgroundType) BASIC_D_ACCESSOR_DECL(PlotArea::BackgroundColorStyle, backgroundColorStyle, BackgroundColorStyle) BASIC_D_ACCESSOR_DECL(PlotArea::BackgroundImageStyle, backgroundImageStyle, BackgroundImageStyle) BASIC_D_ACCESSOR_DECL(Qt::BrushStyle, backgroundBrushStyle, BackgroundBrushStyle) CLASS_D_ACCESSOR_DECL(QColor, backgroundFirstColor, BackgroundFirstColor) CLASS_D_ACCESSOR_DECL(QColor, backgroundSecondColor, BackgroundSecondColor) CLASS_D_ACCESSOR_DECL(QString, backgroundFileName, BackgroundFileName) // Light parameters BASIC_D_ACCESSOR_DECL(double, intensity, Intensity); // From 1 to 0 CLASS_D_ACCESSOR_DECL(QColor, ambient, Ambient); CLASS_D_ACCESSOR_DECL(QColor, diffuse, Diffuse); CLASS_D_ACCESSOR_DECL(QColor, specular, Specular); BASIC_D_ACCESSOR_DECL(double, elevation, Elevation); BASIC_D_ACCESSOR_DECL(double, azimuth, Azimuth); BASIC_D_ACCESSOR_DECL(double, coneAngle, ConeAngle); typedef Plot3D BaseClass; typedef Plot3DPrivate Private; public slots: // Zoom void autoScale(); void autoScaleX(); void autoScaleY(); void autoScaleZ(); void zoomIn(); void zoomOut(); void zoomInX(); void zoomOutX(); void zoomInY(); void zoomOutY(); void zoomInZ(); void zoomOutZ(); void shiftLeftX(); void shiftRightX(); void shiftUpY(); void shiftDownY(); void shiftUpZ(); void shiftDownZ(); private: void initActions(); void initMenus(); void configureAspect(AbstractAspect* aspect); QAction* visibilityAction; QAction* addCurveAction; QAction* addEquationCurveAction; QAction* addSurfaceAction; QAction* addAxesAction; QAction* scaleAutoXAction; QAction* scaleAutoYAction; QAction* scaleAutoZAction; QAction* scaleAutoAction; QAction* zoomInAction; QAction* zoomOutAction; QAction* zoomInXAction; QAction* zoomOutXAction; QAction* zoomInYAction; QAction* zoomOutYAction; QAction* zoomInZAction; QAction* zoomOutZAction; QAction* shiftLeftXAction; QAction* shiftRightXAction; QAction* shiftUpYAction; QAction* shiftDownYAction; QAction* shiftUpZAction; QAction* shiftDownZAction; QAction* rotateClockwiseAction; QAction* rotateCounterclockwiseAction; QAction* tiltLeftAction; QAction* tiltRightAction; QAction* tiltUpAction; QAction* tiltDownAction; QAction* resetRotationAction; QMenu* addNewMenu; QMenu* zoomMenu; QMenu* rotateMenu; protected slots: void childSelected(const AbstractAspect*); void childDeselected(const AbstractAspect*); void handleAspectAdded(const AbstractAspect*); private: void setupAxes(); void deselectObjects(); void dehighlightObjects(); private slots: void addSurface(); void addCurve(); void addAxes(); void onItemRemoved(); void onObjectClicked(vtkProp*); void onObjectHovered(vtkProp*); void onAxesClicked(); void onAxesHovered(); void onParametersChanged(); void updateBounds(); //SLOTs for changes triggered via QActions in the context menu void onVisibilityChanged(); signals: friend class Plot3DSetRectCmd; void rectChanged(const QRectF&); // General friend class Plot3DSetXScalingCmd; friend class Plot3DSetYScalingCmd; friend class Plot3DSetZScalingCmd; friend class Plot3DSetRangesCmd; void xScalingChanged(Plot3D::Scaling); void yScalingChanged(Plot3D::Scaling); void zScalingChanged(Plot3D::Scaling); void rangesChanged(const BoundingBox&); // Background friend class Plot3DSetBackgroundTypeCmd; friend class Plot3DSetBackgroundColorStyleCmd; friend class Plot3DSetBackgroundImageStyleCmd; friend class Plot3DSetBackgroundBrushStyleCmd; friend class Plot3DSetBackgroundFirstColorCmd; friend class Plot3DSetBackgroundSecondColorCmd; friend class Plot3DSetBackgroundFileNameCmd; friend class Plot3DSetBackgroundOpacityCmd; void backgroundTypeChanged(PlotArea::BackgroundType); void backgroundColorStyleChanged(PlotArea::BackgroundColorStyle); void backgroundImageStyleChanged(PlotArea::BackgroundImageStyle); void backgroundBrushStyleChanged(Qt::BrushStyle); void backgroundFirstColorChanged(const QColor&); void backgroundSecondColorChanged(const QColor&); void backgroundFileNameChanged(const QString&); void backgroundOpacityChanged(float); // Light friend class Plot3DSetIntensityCmd; friend class Plot3DSetAmbientCmd; friend class Plot3DSetDiffuseCmd; friend class Plot3DSetSpecularCmd; friend class Plot3DSetElevationCmd; friend class Plot3DSetAzimuthCmd; friend class Plot3DSetConeAngleCmd; void intensityChanged(double); void ambientChanged(const QColor&); void diffuseChanged(const QColor&); void specularChanged(const QColor&); void elevationChanged(double); void azimuthChanged(double); void coneAngleChanged(double); void parametersChanged(); void currentAspectChanged(const AbstractAspect*); void boundsChanged(const BoundingBox&); }; #endif diff --git a/src/kdefrontend/GuiObserver.cpp b/src/kdefrontend/GuiObserver.cpp index faa57429f..0a037b531 100644 --- a/src/kdefrontend/GuiObserver.cpp +++ b/src/kdefrontend/GuiObserver.cpp @@ -1,662 +1,662 @@ /*************************************************************************** File : GuiObserver.cpp Project : LabPlot Description : GUI observer -------------------------------------------------------------------- Copyright : (C) 2010-2015 Alexander Semke (alexander.semke@web.de) Copyright : (C) 2015-2017 Stefan Gerlach (stefan.gerlach@uni.kn) Copyright : (C) 2016 Garvit Khatri (garvitdelhi@gmail.com) ***************************************************************************/ /*************************************************************************** * * * 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 "kdefrontend/GuiObserver.h" #include "backend/core/AspectTreeModel.h" #include "backend/core/AbstractAspect.h" #include "backend/datasources/LiveDataSource.h" #include "backend/matrix/Matrix.h" #include "backend/spreadsheet/Spreadsheet.h" #include "backend/worksheet/Worksheet.h" #include "backend/worksheet/plots/cartesian/CartesianPlot.h" #include "backend/worksheet/plots/cartesian/CartesianPlotLegend.h" #include "backend/worksheet/plots/cartesian/XYCurve.h" #include "backend/worksheet/plots/cartesian/Axis.h" #include "backend/worksheet/plots/3d/Plot3D.h" #include "backend/worksheet/plots/3d/Surface3D.h" #include "backend/worksheet/plots/3d/Curve3D.h" #include "backend/worksheet/plots/3d/Axes.h" #include "backend/worksheet/plots/cartesian/CustomPoint.h" #include "backend/worksheet/plots/cartesian/Histogram.h" #include "backend/worksheet/plots/cartesian/BarChartPlot.h" #include "backend/worksheet/TextLabel.h" #ifdef HAVE_CANTOR_LIBS #include "backend/cantorWorksheet/CantorWorksheet.h" #endif #include "backend/core/Project.h" #include "backend/datapicker/Datapicker.h" #include "backend/datapicker/DatapickerImage.h" #include "backend/datapicker/DatapickerCurve.h" #include "commonfrontend/ProjectExplorer.h" #include "kdefrontend/MainWin.h" #include "kdefrontend/dockwidgets/AxisDock.h" #include "kdefrontend/dockwidgets/NoteDock.h" #include "kdefrontend/dockwidgets/CartesianPlotDock.h" #include "kdefrontend/dockwidgets/Plot3DDock.h" #include "kdefrontend/dockwidgets/Axes3DDock.h" #include "kdefrontend/dockwidgets/Surface3DDock.h" #include "kdefrontend/dockwidgets/Curve3DDock.h" #include "kdefrontend/dockwidgets/CartesianPlotLegendDock.h" #include "kdefrontend/dockwidgets/ColumnDock.h" #include "kdefrontend/dockwidgets/LiveDataDock.h" #include "kdefrontend/dockwidgets/MatrixDock.h" #include "kdefrontend/dockwidgets/ProjectDock.h" #include "kdefrontend/dockwidgets/SpreadsheetDock.h" #include "kdefrontend/dockwidgets/XYCurveDock.h" #include "kdefrontend/dockwidgets/HistogramDock.h" #include "kdefrontend/dockwidgets/XYEquationCurveDock.h" #include "kdefrontend/dockwidgets/XYDataReductionCurveDock.h" #include "kdefrontend/dockwidgets/XYDifferentiationCurveDock.h" #include "kdefrontend/dockwidgets/XYIntegrationCurveDock.h" #include "kdefrontend/dockwidgets/XYInterpolationCurveDock.h" #include "kdefrontend/dockwidgets/XYFitCurveDock.h" #include "kdefrontend/dockwidgets/XYFourierFilterCurveDock.h" #include "kdefrontend/dockwidgets/XYFourierTransformCurveDock.h" #include "kdefrontend/dockwidgets/XYSmoothCurveDock.h" #include "kdefrontend/dockwidgets/CustomPointDock.h" #include "kdefrontend/dockwidgets/WorksheetDock.h" #ifdef HAVE_CANTOR_LIBS #include "kdefrontend/dockwidgets/CantorWorksheetDock.h" #endif #include "kdefrontend/widgets/LabelWidget.h" #include "kdefrontend/widgets/DatapickerImageWidget.h" #include "kdefrontend/widgets/DatapickerCurveWidget.h" #include #include #include #include #include #include /*! \class GuiObserver \brief The GUI observer looks for the selection changes in the main window and shows/hides the correspondings dock widgets, toolbars etc. This class is intended to simplify (or not to overload) the code in MainWin. \ingroup kdefrontend */ GuiObserver::GuiObserver(MainWin* mainWin) : m_lastCartesianPlot(0) { connect(mainWin->m_projectExplorer, SIGNAL(selectedAspectsChanged(QList&)), this, SLOT(selectedAspectsChanged(QList&)) ); connect(mainWin->m_projectExplorer, SIGNAL(hiddenAspectSelected(const AbstractAspect*)), this, SLOT(hiddenAspectSelected(const AbstractAspect*)) ); m_mainWindow = mainWin; } /*! called on selection changes in the project explorer. Determines the type of the currently selected objects (aspects) and activates the corresponding dockwidgets, toolbars etc. */ void GuiObserver::selectedAspectsChanged(QList& selectedAspects) const { if (selectedAspects.isEmpty()) { if (m_mainWindow->stackedWidget->currentWidget()) m_mainWindow->stackedWidget->currentWidget()->hide(); m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Properties")); return; } QString prevClassName, className; //check, whether objects of different types where selected //don't show any dock widgets in this case. for (auto* aspect: selectedAspects) { className = aspect->metaObject()->className(); if (className != prevClassName && !prevClassName.isEmpty()) { if (m_mainWindow->stackedWidget->currentWidget()) m_mainWindow->stackedWidget->currentWidget()->hide(); m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Properties")); return; } prevClassName = className; } if (m_mainWindow->stackedWidget->currentWidget()) m_mainWindow->stackedWidget->currentWidget()->show(); if (className == "Spreadsheet") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Spreadsheet")); if (!m_mainWindow->spreadsheetDock) { m_mainWindow->spreadsheetDock = new SpreadsheetDock(m_mainWindow->stackedWidget); connect(m_mainWindow->spreadsheetDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->spreadsheetDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->spreadsheetDock->setSpreadsheets(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->spreadsheetDock); } else if (className == "Column") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Column")); if (!m_mainWindow->columnDock) { m_mainWindow->columnDock = new ColumnDock(m_mainWindow->stackedWidget); connect(m_mainWindow->columnDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->columnDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->columnDock->setColumns(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->columnDock); } else if (className == "Matrix") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Matrix")); if (!m_mainWindow->matrixDock) { m_mainWindow->matrixDock = new MatrixDock(m_mainWindow->stackedWidget); connect(m_mainWindow->matrixDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->matrixDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->matrixDock->setMatrices(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->matrixDock); } else if (className == "Worksheet") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Worksheet")); if (!m_mainWindow->worksheetDock) { m_mainWindow->worksheetDock = new WorksheetDock(m_mainWindow->stackedWidget); connect(m_mainWindow->worksheetDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->worksheetDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->worksheetDock->setWorksheets(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->worksheetDock); }else if (className=="Plot3D"){ if (!m_mainWindow->plot3dDock){ m_mainWindow->plot3dDock = new Plot3DDock(m_mainWindow->stackedWidget); m_mainWindow->stackedWidget->addWidget(m_mainWindow->plot3dDock); } m_mainWindow->m_propertiesDock->setWindowTitle(i18n("3D Plot Properties")); QList list; - foreach(aspect, selectedAspects){ + for (auto* aspect : selectedAspects){ Plot3D *plot3D = qobject_cast(aspect); connect(plot3D, SIGNAL(currentAspectChanged(const AbstractAspect*)), - mainWindow->m_projectExplorer, + m_mainWindow->m_projectExplorer, SLOT(setCurrentAspect(const AbstractAspect*))); list<plot3dDock->setPlots(list); - m_mainWindow->stackedWidget->setCurrentWidget(mainWindow->plot3dDock); + m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->plot3dDock); }else if (className=="Axes"){ if (!m_mainWindow->axes3dDock){ m_mainWindow->axes3dDock = new Axes3DDock(m_mainWindow->stackedWidget); m_mainWindow->stackedWidget->addWidget(m_mainWindow->axes3dDock); } m_mainWindow->m_propertiesDock->setWindowTitle(i18n("3D Axes properties")); - foreach(aspect, selectedAspects){ + for (auto* aspect : selectedAspects){ Axes* axes = qobject_cast(aspect); if (axes) { m_mainWindow->axes3dDock->setAxes(axes); break; } } - m_mainWindow->stackedWidget->setCurrentWidget(mainWindow->axes3dDock); + m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->axes3dDock); }else if (className=="Surface3D"){ if (!m_mainWindow->surface3dDock){ m_mainWindow->surface3dDock = new Surface3DDock(m_mainWindow->stackedWidget); m_mainWindow->stackedWidget->addWidget(m_mainWindow->surface3dDock); } m_mainWindow->m_propertiesDock->setWindowTitle(i18n("3D Surface properties")); QList list; - foreach(aspect, selectedAspects){ + for (auto* aspect : selectedAspects){ Surface3D* surface = qobject_cast(aspect); if (surface) { list << surface; } } m_mainWindow->surface3dDock->setSurfaces(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->surface3dDock); }else if(className == "Curve3D"){ if (!m_mainWindow->curve3dDock){ m_mainWindow->curve3dDock = new Curve3DDock(m_mainWindow->stackedWidget); m_mainWindow->stackedWidget->addWidget(m_mainWindow->curve3dDock); } m_mainWindow->m_propertiesDock->setWindowTitle(i18n("3D Curve properties")); - foreach(aspect, selectedAspects){ + for (auto* aspect : selectedAspects){ Curve3D* curve = qobject_cast(aspect); if (curve) { m_mainWindow->curve3dDock->setCurve(curve); break; } } m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->curve3dDock); } else if (className == "CartesianPlot") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Cartesian Plot")); if (!m_mainWindow->cartesianPlotDock) { m_mainWindow->cartesianPlotDock = new CartesianPlotDock(m_mainWindow->stackedWidget); connect(m_mainWindow->cartesianPlotDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->cartesianPlotDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->cartesianPlotDock->setPlots(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->cartesianPlotDock); } else if (className == "CartesianPlotLegend") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Legend")); if (!m_mainWindow->cartesianPlotLegendDock) { m_mainWindow->cartesianPlotLegendDock = new CartesianPlotLegendDock(m_mainWindow->stackedWidget); connect(m_mainWindow->cartesianPlotLegendDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->cartesianPlotLegendDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->cartesianPlotLegendDock->setLegends(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->cartesianPlotLegendDock); } else if (className == "Axis") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Axis")); if (!m_mainWindow->axisDock) { m_mainWindow->axisDock = new AxisDock(m_mainWindow->stackedWidget); connect(m_mainWindow->axisDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->axisDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->axisDock->setAxes(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->axisDock); } else if (className == "XYCurve") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("xy-Curve")); if (!m_mainWindow->xyCurveDock) { m_mainWindow->xyCurveDock = new XYCurveDock(m_mainWindow->stackedWidget); m_mainWindow->xyCurveDock->setupGeneral(); connect(m_mainWindow->xyCurveDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->xyCurveDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->xyCurveDock->setCurves(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->xyCurveDock); } else if (className == "XYEquationCurve") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("xy-Equation")); if (!m_mainWindow->xyEquationCurveDock) { m_mainWindow->xyEquationCurveDock = new XYEquationCurveDock(m_mainWindow->stackedWidget); m_mainWindow->xyEquationCurveDock->setupGeneral(); connect(m_mainWindow->xyEquationCurveDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->xyEquationCurveDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->xyEquationCurveDock->setCurves(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->xyEquationCurveDock); } else if (className == "XYDataReductionCurve") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Data reduction")); if (!m_mainWindow->xyDataReductionCurveDock) { m_mainWindow->xyDataReductionCurveDock = new XYDataReductionCurveDock(m_mainWindow->stackedWidget, m_mainWindow->statusBar()); m_mainWindow->xyDataReductionCurveDock->setupGeneral(); connect(m_mainWindow->xyDataReductionCurveDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->xyDataReductionCurveDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->xyDataReductionCurveDock->setCurves(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->xyDataReductionCurveDock); } else if (className == "XYDifferentiationCurve") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Differentiation")); if (!m_mainWindow->xyDifferentiationCurveDock) { m_mainWindow->xyDifferentiationCurveDock = new XYDifferentiationCurveDock(m_mainWindow->stackedWidget); m_mainWindow->xyDifferentiationCurveDock->setupGeneral(); connect(m_mainWindow->xyDifferentiationCurveDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->xyDifferentiationCurveDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->xyDifferentiationCurveDock->setCurves(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->xyDifferentiationCurveDock); } else if (className == "XYIntegrationCurve") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Integration")); if (!m_mainWindow->xyIntegrationCurveDock) { m_mainWindow->xyIntegrationCurveDock = new XYIntegrationCurveDock(m_mainWindow->stackedWidget); m_mainWindow->xyIntegrationCurveDock->setupGeneral(); connect(m_mainWindow->xyIntegrationCurveDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->xyIntegrationCurveDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->xyIntegrationCurveDock->setCurves(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->xyIntegrationCurveDock); } else if (className == "XYInterpolationCurve") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Interpolation")); if (!m_mainWindow->xyInterpolationCurveDock) { m_mainWindow->xyInterpolationCurveDock = new XYInterpolationCurveDock(m_mainWindow->stackedWidget); m_mainWindow->xyInterpolationCurveDock->setupGeneral(); connect(m_mainWindow->xyInterpolationCurveDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->xyInterpolationCurveDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->xyInterpolationCurveDock->setCurves(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->xyInterpolationCurveDock); } else if (className == "XYFitCurve") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Fit")); if (!m_mainWindow->xyFitCurveDock) { m_mainWindow->xyFitCurveDock = new XYFitCurveDock(m_mainWindow->stackedWidget); m_mainWindow->xyFitCurveDock->setupGeneral(); connect(m_mainWindow->xyFitCurveDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->xyFitCurveDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->xyFitCurveDock->setCurves(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->xyFitCurveDock); } else if (className == "XYFourierTransformCurve") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Fourier Transform")); if (!m_mainWindow->xyFourierTransformCurveDock) { m_mainWindow->xyFourierTransformCurveDock = new XYFourierTransformCurveDock(m_mainWindow->stackedWidget); m_mainWindow->xyFourierTransformCurveDock->setupGeneral(); connect(m_mainWindow->xyFourierTransformCurveDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->xyFourierTransformCurveDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->xyFourierTransformCurveDock->setCurves(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->xyFourierTransformCurveDock); } else if (className == "XYFourierFilterCurve") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Fourier Filter")); if (!m_mainWindow->xyFourierFilterCurveDock) { m_mainWindow->xyFourierFilterCurveDock = new XYFourierFilterCurveDock(m_mainWindow->stackedWidget); m_mainWindow->xyFourierFilterCurveDock->setupGeneral(); connect(m_mainWindow->xyFourierFilterCurveDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->xyFourierFilterCurveDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->xyFourierFilterCurveDock->setCurves(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->xyFourierFilterCurveDock); } else if (className == "XYSmoothCurve") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Smoothing")); if (!m_mainWindow->xySmoothCurveDock) { m_mainWindow->xySmoothCurveDock = new XYSmoothCurveDock(m_mainWindow->stackedWidget); m_mainWindow->xySmoothCurveDock->setupGeneral(); connect(m_mainWindow->xySmoothCurveDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->xySmoothCurveDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->xySmoothCurveDock->setCurves(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->xySmoothCurveDock); } else if (className=="Histogram") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Histogram properties")); if (!m_mainWindow->histogramDock) { m_mainWindow->histogramDock = new HistogramDock(m_mainWindow->stackedWidget); m_mainWindow->histogramDock->setupGeneral(); connect(m_mainWindow->histogramDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->histogramDock); } QList list; for (auto* aspect: selectedAspects) list<(aspect); m_mainWindow->histogramDock->setCurves(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->histogramDock); } else if (className == "TextLabel") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Text Label")); if (!m_mainWindow->textLabelDock) { m_mainWindow->textLabelDock = new LabelWidget(m_mainWindow->stackedWidget); m_mainWindow->stackedWidget->addWidget(m_mainWindow->textLabelDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->textLabelDock->setLabels(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->textLabelDock); } else if (className == "CustomPoint") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Custom Point")); if (!m_mainWindow->customPointDock) { m_mainWindow->customPointDock = new CustomPointDock(m_mainWindow->stackedWidget); m_mainWindow->stackedWidget->addWidget(m_mainWindow->customPointDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->customPointDock->setPoints(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->customPointDock); } else if (className == "DatapickerCurve") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Datapicker Curve")); if (!m_mainWindow->datapickerCurveDock) { m_mainWindow->datapickerCurveDock = new DatapickerCurveWidget(m_mainWindow->stackedWidget); m_mainWindow->stackedWidget->addWidget(m_mainWindow->datapickerCurveDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->datapickerCurveDock->setCurves(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->datapickerCurveDock); } else if (className == "Datapicker") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Datapicker")); if (!m_mainWindow->datapickerImageDock) { m_mainWindow->datapickerImageDock = new DatapickerImageWidget(m_mainWindow->stackedWidget); m_mainWindow->stackedWidget->addWidget(m_mainWindow->datapickerImageDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect)->image(); m_mainWindow->datapickerImageDock->setImages(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->datapickerImageDock); } else if (className == "Project") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Project")); if (!m_mainWindow->projectDock) { m_mainWindow->projectDock = new ProjectDock(m_mainWindow->stackedWidget); m_mainWindow->stackedWidget->addWidget(m_mainWindow->projectDock); } m_mainWindow->projectDock->setProject(m_mainWindow->m_project); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->projectDock); } else if (className=="CantorWorksheet") { #ifdef HAVE_CANTOR_LIBS if (!m_mainWindow->cantorWorksheetDock) { m_mainWindow->cantorWorksheetDock = new CantorWorksheetDock(m_mainWindow->stackedWidget); connect(m_mainWindow->cantorWorksheetDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString))); m_mainWindow->stackedWidget->addWidget(m_mainWindow->cantorWorksheetDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); if (list.size() == 1) m_mainWindow->m_propertiesDock->setWindowTitle(list.first()->backendName() + " Properties"); else m_mainWindow->m_propertiesDock->setWindowTitle("CAS Properties"); m_mainWindow->cantorWorksheetDock->setCantorWorksheets(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->cantorWorksheetDock); #endif } else if (className == "Notes") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Notes")); if (!m_mainWindow->notesDock) { m_mainWindow->notesDock = new NoteDock(m_mainWindow->stackedWidget); m_mainWindow->stackedWidget->addWidget(m_mainWindow->notesDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->notesDock->setNotesList(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->notesDock); } else if (className == "LiveDataSource") { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Live data source")); if (!m_mainWindow->m_liveDataDock) { m_mainWindow->m_liveDataDock = new LiveDataDock(m_mainWindow->stackedWidget); m_mainWindow->stackedWidget->addWidget(m_mainWindow->m_liveDataDock); } QList list; for (auto* aspect: selectedAspects) list << qobject_cast(aspect); m_mainWindow->m_liveDataDock->setLiveDataSources(list); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->m_liveDataDock); } else { m_mainWindow->m_propertiesDock->setWindowTitle(i18n("Properties")); if (m_mainWindow->stackedWidget->currentWidget()) m_mainWindow->stackedWidget->currentWidget()->hide(); } } template -void GuiObserver::initDockWidget(TDockWidget*& dockWidget){ +void GuiObserver::initDockWidget(TDockWidget*& dockWidget) const { if (dockWidget == 0){ - dockWidget = new TDockWidget(mainWindow->stackedWidget); - mainWindow->stackedWidget->addWidget(dockWidget); + dockWidget = new TDockWidget(m_mainWindow->stackedWidget); + m_mainWindow->stackedWidget->addWidget(dockWidget); } } /*! handles the selection of a hidden aspect \c aspect in the view (relevant for WorksheetView only at the moment). Currently, a hidden aspect can only be a plot title lable or an axis label. -> Activate the corresponding DockWidget and make the title tab current. */ void GuiObserver::hiddenAspectSelected(const AbstractAspect* aspect) const { const AbstractAspect* parent = aspect->parentAspect(); if (!parent) return; QString className = parent->metaObject()->className(); if (className == "Axis") { if (!m_mainWindow->axisDock) { m_mainWindow->axisDock = new AxisDock(m_mainWindow->stackedWidget); m_mainWindow->stackedWidget->addWidget(m_mainWindow->axisDock); } m_mainWindow->axisDock->activateTitleTab(); } else if (className == "CartesianPlot") { if (!m_mainWindow->cartesianPlotDock) { m_mainWindow->cartesianPlotDock = new CartesianPlotDock(m_mainWindow->stackedWidget); m_mainWindow->stackedWidget->addWidget(m_mainWindow->cartesianPlotDock); } m_mainWindow->cartesianPlotDock->activateTitleTab(); } else if (className == "CartesianPlotLegend") { if (!m_mainWindow->cartesianPlotLegendDock) { m_mainWindow->cartesianPlotLegendDock = new CartesianPlotLegendDock(m_mainWindow->stackedWidget); m_mainWindow->stackedWidget->addWidget(m_mainWindow->cartesianPlotLegendDock); } m_mainWindow->cartesianPlotLegendDock->activateTitleTab(); } else if (className == "Plot3D"){ - initDockWidget(mainWindow->plot3dDock); + initDockWidget(m_mainWindow->plot3dDock); } } diff --git a/src/kdefrontend/GuiObserver.h b/src/kdefrontend/GuiObserver.h index 26e1890f4..f9a48dd15 100644 --- a/src/kdefrontend/GuiObserver.h +++ b/src/kdefrontend/GuiObserver.h @@ -1,56 +1,56 @@ /*************************************************************************** File : GuiObserver.h Project : LabPlot Description : GUI observer -------------------------------------------------------------------- Copyright : (C) 2010-2016 Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #ifndef GUIOBSERVER_H #define GUIOBSERVER_H #include class MainWin; class AbstractAspect; class CartesianPlot; class Histogram; class GuiObserver : public QObject { Q_OBJECT public: explicit GuiObserver(MainWin*); private: MainWin* m_mainWindow; CartesianPlot* m_lastCartesianPlot; Histogram* m_lastHistogram; template - void initDockWidget(TDockWidget*& dockWidget); + void initDockWidget(TDockWidget*& dockWidget) const; private slots: void selectedAspectsChanged(QList&) const; void hiddenAspectSelected(const AbstractAspect*) const; }; #endif diff --git a/src/kdefrontend/dockwidgets/Curve3DDock.cpp b/src/kdefrontend/dockwidgets/Curve3DDock.cpp index 245eb3edf..e2c2a98c7 100644 --- a/src/kdefrontend/dockwidgets/Curve3DDock.cpp +++ b/src/kdefrontend/dockwidgets/Curve3DDock.cpp @@ -1,260 +1,262 @@ /*************************************************************************** File : Curve3DDock.cpp Project : LabPlot Description : widget for 3D curves properties -------------------------------------------------------------------- Copyright : (C) 2015 Minh Ngo (minh@fedoraproject.org) ***************************************************************************/ /*************************************************************************** * * * 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 "Curve3DDock.h" #include "backend/core/AbstractColumn.h" #include "backend/core/Project.h" #include "backend/worksheet/plots/3d/Curve3D.h" #include "backend/core/AspectTreeModel.h" #include "kdefrontend/TemplateHandler.h" #include +#include +#include using namespace DockHelpers; Curve3DDock::Curve3DDock(QWidget* parent) : QWidget(parent) , recorder(this) , curve(0) , aspectTreeModel(0) , m_initializing(false) { ui.setupUi(this); // TODO: Implement ui.tabWidget->removeTab(1); ui.tabWidget->removeTab(1); ui.tabWidget->removeTab(1); ui.tabLine->setVisible(false); ui.tabSymbol->setVisible(false); ui.tabErrorBars->setVisible(false); QList list; list << "Folder" << "Workbook" << "Spreadsheet" << "FileDataSource" << "Column"; const QVector treeViews(QVector() << ui.cbXCoordinate << ui.cbYCoordinate << ui.cbZCoordinate); foreach(TreeViewComboBox* view, treeViews) { view->setTopLevelClasses(list); } list.clear(); list << "Column"; //template handler TemplateHandler* templateHandler = new TemplateHandler(this, TemplateHandler::Curve3D); ui.verticalLayout->addWidget(templateHandler); templateHandler->show(); foreach(TreeViewComboBox* view, treeViews) { - view->setSelectableClasses(list); +// view->setSelectableClasses(list); recorder.connect(view, SIGNAL(currentModelIndexChanged(const QModelIndex&)), SLOT(onTreeViewIndexChanged(const QModelIndex&))); } recorder.connect(ui.leName, SIGNAL(returnPressed()), SLOT(onNameChanged())); recorder.connect(ui.leComment, SIGNAL(returnPressed()), SLOT(onCommentChanged())); recorder.connect(ui.chkVisible, SIGNAL(toggled(bool)), SLOT(onVisibilityChanged(bool))); recorder.connect(ui.cbShowEdges, SIGNAL(toggled(bool)), SLOT(onShowEdgesChanged(bool))); recorder.connect(ui.cbClosedCurve, SIGNAL(toggled(bool)), SLOT(onIsClosedChanged(bool))); recorder.connect(ui.sbPointSize, SIGNAL(valueChanged(double)), SLOT(onPointRadiusChanged(double))); recorder.connect(templateHandler, SIGNAL(loadConfigRequested(KConfig&)), SLOT(loadConfigFromTemplate(KConfig&))); recorder.connect(templateHandler, SIGNAL(saveConfigRequested(KConfig&)), SLOT(saveConfigAsTemplate(KConfig&))); recorder.connect(templateHandler, SIGNAL(info(QString)), SIGNAL(info(QString))); } void Curve3DDock::setCurve(Curve3D* curve) { this->curve = curve; { const SignalBlocker blocker(recorder.children()); ui.leName->setText(curve->name()); ui.leComment->setText(curve->comment()); ui.chkVisible->setChecked(curve->isVisible()); pointRadiusChanged(curve->pointRadius()); aspectTreeModel = new AspectTreeModel(curve->project()); ui.cbXCoordinate->setModel(aspectTreeModel); ui.cbYCoordinate->setModel(aspectTreeModel); ui.cbZCoordinate->setModel(aspectTreeModel); xColumnChanged(curve->xColumn()); yColumnChanged(curve->yColumn()); zColumnChanged(curve->zColumn()); isClosedChanged(curve->isClosed()); showEdgesChanged(curve->showEdges()); } connect(curve, SIGNAL(xColumnChanged(const AbstractColumn*)), SLOT(xColumnChanged(const AbstractColumn*))); connect(curve, SIGNAL(yColumnChanged(const AbstractColumn*)), SLOT(yColumnChanged(const AbstractColumn*))); connect(curve, SIGNAL(zColumnChanged(const AbstractColumn*)), SLOT(zColumnChanged(const AbstractColumn*))); connect(curve, SIGNAL(pointRadiusChanged(float)), SLOT(pointRadiusChanged(float))); connect(curve, SIGNAL(isClosedChanged(bool)), SLOT(isClosedChanged(bool))); connect(curve, SIGNAL(showEdgesChanged(bool)), SLOT(showEdgesChanged(bool))); connect(curve, SIGNAL(visibilityChanged(bool)), ui.chkVisible, SLOT(setChecked(bool))); } void Curve3DDock::onNameChanged() { const Lock lock(m_initializing); curve->setName(ui.leName->text()); } void Curve3DDock::onCommentChanged() { const Lock lock(m_initializing); curve->setComment(ui.leComment->text()); } void Curve3DDock::onTreeViewIndexChanged(const QModelIndex& index) { const AbstractColumn* column = getColumn(index); const QObject *senderW = sender(); const Lock lock(m_initializing); if(senderW == ui.cbXCoordinate) curve->setXColumn(column); else if(senderW == ui.cbYCoordinate) curve->setYColumn(column); else curve->setZColumn(column); } void Curve3DDock::onShowEdgesChanged(bool checked) { ui.cbClosedCurve->setEnabled(checked); const Lock lock(m_initializing); curve->setShowEdges(checked); } void Curve3DDock::onVisibilityChanged(bool visible) { const Lock lock(m_initializing); curve->show(visible); } void Curve3DDock::onXColumnChanged(const AbstractColumn* column) { const Lock lock(m_initializing); curve->setXColumn(column); } void Curve3DDock::onYColumnChanged(const AbstractColumn* column) { const Lock lock(m_initializing); curve->setYColumn(column); } void Curve3DDock::onZColumnChanged(const AbstractColumn* column) { const Lock lock(m_initializing); curve->setZColumn(column); } void Curve3DDock::onPointRadiusChanged(double radius) { const Lock lock(m_initializing); curve->setPointRadius(static_cast(radius)); } void Curve3DDock::onIsClosedChanged(bool checked) { const Lock lock(m_initializing); curve->setIsClosed(checked); } void Curve3DDock::showEdgesChanged(bool checked) { if (m_initializing) return; ui.cbShowEdges->setChecked(checked); } void Curve3DDock::isClosedChanged(bool checked) { if (m_initializing) return; ui.cbClosedCurve->setChecked(checked); } void Curve3DDock::pointRadiusChanged(float radius) { if (m_initializing) return; ui.sbPointSize->setValue(radius); } // TODO: Move to the common place void Curve3DDock::setModelFromAspect(TreeViewComboBox* cb, const AbstractAspect* aspect) { if (m_initializing) return; cb->setCurrentModelIndex(modelIndexOfAspect(aspectTreeModel, aspect)); } void Curve3DDock::xColumnChanged(const AbstractColumn* column) { setModelFromAspect(ui.cbXCoordinate, column); } void Curve3DDock::yColumnChanged(const AbstractColumn* column) { setModelFromAspect(ui.cbYCoordinate, column); } void Curve3DDock::zColumnChanged(const AbstractColumn* column) { setModelFromAspect(ui.cbZCoordinate, column); } //************************************************************* //************************* Settings ************************** //************************************************************* void Curve3DDock::load() { //TODO } void Curve3DDock::loadConfigFromTemplate(KConfig& config) { //extract the name of the template from the file name QString name; int index = config.name().lastIndexOf(QDir::separator()); if (index!=-1) name = config.name().right(config.name().size() - index - 1); else name = config.name(); //TODO // int size = m_curvesList.size(); // if (size>1) // m_curve->beginMacro(i18n("%1 3D-curves: template \"%2\" loaded", size, name)); // else // m_curve->beginMacro(i18n("%1: template \"%2\" loaded", m_curve->name(), name)); this->loadConfig(config); // m_curve->endMacro(); } void Curve3DDock::loadConfig(KConfig& config) { KConfigGroup group = config.group( "XYCurve" ); //TODO } void Curve3DDock::saveConfigAsTemplate(KConfig& config) { KConfigGroup group = config.group( "XYCurve" ); //TODO config.sync(); } diff --git a/src/kdefrontend/dockwidgets/Curve3DDock.h b/src/kdefrontend/dockwidgets/Curve3DDock.h index e7d10d342..e5f7fa1e4 100644 --- a/src/kdefrontend/dockwidgets/Curve3DDock.h +++ b/src/kdefrontend/dockwidgets/Curve3DDock.h @@ -1,92 +1,93 @@ /*************************************************************************** File : Curve3DDock.h Project : LabPlot Description : widget for 3D curves properties -------------------------------------------------------------------- Copyright : (C) 2015 Minh Ngo (minh@fedoraproject.org) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #ifndef CURVE3DDOCK_H #define CURVE3DDOCK_H #include #include "ui_curve3ddock.h" #include "DockHelpers.h" class Curve3D; class AbstractColumn; class AspectTreeModel; +class KConfig; class Curve3DDock : public QWidget { Q_OBJECT public: explicit Curve3DDock(QWidget* parent); void setCurve(Curve3D* curve); private: void setModelFromAspect(TreeViewComboBox* cb, const AbstractAspect* aspect); private slots: //SLOTs for changes triggered in Curve3DDock void onTreeViewIndexChanged(const QModelIndex& index); void onNameChanged(); void onCommentChanged(); void onVisibilityChanged(bool visible); void onShowEdgesChanged(bool checked); void onIsClosedChanged(bool checked); void onPointRadiusChanged(double size); void onXColumnChanged(const AbstractColumn* column); void onYColumnChanged(const AbstractColumn* column); void onZColumnChanged(const AbstractColumn* column); void showEdgesChanged(bool checked); void isClosedChanged(bool checked); void pointRadiusChanged(float radius); void xColumnChanged(const AbstractColumn* column); void yColumnChanged(const AbstractColumn* column); void zColumnChanged(const AbstractColumn* column); //load and save void loadConfigFromTemplate(KConfig&); void saveConfigAsTemplate(KConfig&); private: Ui::Curve3DDock ui; DockHelpers::ChildrenRecorder recorder; Curve3D *curve; AspectTreeModel *aspectTreeModel; bool m_initializing; void load(); void loadConfig(KConfig&); }; #endif diff --git a/src/kdefrontend/dockwidgets/Plot3DDock.cpp b/src/kdefrontend/dockwidgets/Plot3DDock.cpp index 373b3929c..22ad8c556 100644 --- a/src/kdefrontend/dockwidgets/Plot3DDock.cpp +++ b/src/kdefrontend/dockwidgets/Plot3DDock.cpp @@ -1,825 +1,827 @@ /*************************************************************************** File : Plot3DDock.h Project : LabPlot Description : widget for 3D plot properties -------------------------------------------------------------------- Copyright : (C) 2015 Minh Ngo (minh@fedoraproject.org) ***************************************************************************/ /*************************************************************************** * * * 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 "Plot3DDock.h" #include "backend/worksheet/plots/3d/Plot3D.h" #include "backend/worksheet/plots/3d/BoundingBox.h" #include "backend/core/AbstractAspect.h" #include "backend/core/AbstractColumn.h" #include "backend/core/AspectTreeModel.h" #include "backend/core/Project.h" #include "commonfrontend/widgets/TreeViewComboBox.h" #include "kdefrontend/GuiTools.h" #include "kdefrontend/TemplateHandler.h" #include #include #include #include #include +#include +#include #include #include #include #include #include #include using namespace DockHelpers; Plot3DDock::Plot3DDock(QWidget* parent) : QWidget(parent) , recorder(this) , m_plot(0) , m_initializing(false) { ui.setupUi(this); retranslateUi(); //Background-tab ui.cbBackgroundColorStyle->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); ui.kleBackgroundFileName->setClearButtonShown(true); - ui.bBackgroundOpen->setIcon( KIcon("document-open") ); + ui.bBackgroundOpen->setIcon( QIcon::fromTheme(QLatin1String("document-open")) ); KUrlCompletion *comp = new KUrlCompletion(); ui.kleBackgroundFileName->setCompletionObject(comp); GuiTools::updateBrushStyles(ui.cbBackgroundBrushStyle, Qt::SolidPattern); //adjust layouts in the tabs for (int i=0; icount(); ++i){ QGridLayout* layout = dynamic_cast(ui.tabWidget->widget(i)->layout()); if (!layout) continue; layout->setContentsMargins(2,2,2,2); layout->setHorizontalSpacing(2); layout->setVerticalSpacing(2); } //SIGNALs/SLOTs //General recorder.connect(ui.leName, SIGNAL(returnPressed()), SLOT(onNameChanged())); recorder.connect(ui.leComment, SIGNAL(returnPressed()), SLOT(onCommentChanged())); recorder.connect(ui.chkVisible, SIGNAL(stateChanged(int)), SLOT(onVisibilityChanged(int))); recorder.connect(ui.sbLeft, SIGNAL(valueChanged(double)), SLOT(onGeometryChanged())); recorder.connect(ui.sbTop, SIGNAL(valueChanged(double)), SLOT(onGeometryChanged())); recorder.connect(ui.sbWidth, SIGNAL(valueChanged(double)), SLOT(onGeometryChanged())); recorder.connect(ui.sbHeight, SIGNAL(valueChanged(double)), SLOT(onGeometryChanged())); recorder.connect(ui.cbXScaling, SIGNAL(currentIndexChanged(int)), SLOT(onXScalingChanged(int))); recorder.connect(ui.cbYScaling, SIGNAL(currentIndexChanged(int)), SLOT(onYScalingChanged(int))); recorder.connect(ui.cbZScaling, SIGNAL(currentIndexChanged(int)), SLOT(onZScalingChanged(int))); recorder.connect(ui.chkAutoScaleX, SIGNAL(stateChanged(int)), SLOT(onAutoScaleXChanged(int))); recorder.connect(ui.chkAutoScaleY, SIGNAL(stateChanged(int)), SLOT(onAutoScaleYChanged(int))); recorder.connect(ui.chkAutoScaleZ, SIGNAL(stateChanged(int)), SLOT(onAutoScaleZChanged(int))); recorder.connect(ui.kleXMin, SIGNAL(returnPressed()), SLOT(onXMinChanged())); recorder.connect(ui.kleYMin, SIGNAL(returnPressed()), SLOT(onYMinChanged())); recorder.connect(ui.kleZMin, SIGNAL(returnPressed()), SLOT(onZMinChanged())); recorder.connect(ui.kleXMax, SIGNAL(returnPressed()), SLOT(onXMaxChanged())); recorder.connect(ui.kleYMax, SIGNAL(returnPressed()), SLOT(onYMaxChanged())); recorder.connect(ui.kleZMax, SIGNAL(returnPressed()), SLOT(onZMaxChanged())); //Background recorder.connect(ui.cbBackgroundType, SIGNAL(currentIndexChanged(int)), SLOT(onBackgroundTypeChanged(int))); recorder.connect(ui.cbBackgroundColorStyle, SIGNAL(currentIndexChanged(int)), SLOT(onBackgroundColorStyleChanged(int))); recorder.connect(ui.cbBackgroundImageStyle, SIGNAL(currentIndexChanged(int)), SLOT(onBackgroundImageStyleChanged(int))); recorder.connect(ui.cbBackgroundBrushStyle, SIGNAL(currentIndexChanged(int)), SLOT(onBackgroundBrushStyleChanged(int))); recorder.connect(ui.bBackgroundOpen, SIGNAL(clicked(bool)), SLOT(onBackgroundSelectFile())); recorder.connect(ui.kleBackgroundFileName, SIGNAL(returnPressed()), SLOT(onBackgroundFileNameChanged())); recorder.connect(ui.kleBackgroundFileName, SIGNAL(clearButtonClicked()), SLOT(onBackgroundFileNameChanged())); recorder.connect(ui.kcbBackgroundFirstColor, SIGNAL(changed(const QColor&)), SLOT(onBackgroundFirstColorChanged(const QColor&))); recorder.connect(ui.kcbBackgroundSecondColor, SIGNAL(changed(const QColor&)), SLOT(onBackgroundSecondColorChanged(const QColor&))); recorder.connect(ui.sbBackgroundOpacity, SIGNAL(valueChanged(int)), SLOT(onBackgroundOpacityChanged(int))); // Light recorder.connect(ui.sbLightIntensity, SIGNAL(valueChanged(double)), SLOT(onIntensityChanged(double))); recorder.connect(ui.kcbLightAmbientColor, SIGNAL(changed(const QColor&)), SLOT(onAmbientChanged(const QColor&))); recorder.connect(ui.kcbLightDiffuseColor, SIGNAL(changed(const QColor&)), SLOT(onDiffuseChanged(const QColor&))); recorder.connect(ui.kcbLightSpecularColor, SIGNAL(changed(const QColor&)), SLOT(onSpecularChanged(const QColor&))); recorder.connect(ui.sbLightElevation, SIGNAL(valueChanged(int)), SLOT(onElevationChanged(int))); recorder.connect(ui.sbLightAzimuth, SIGNAL(valueChanged(int)), SLOT(onAzimuthChanged(int))); recorder.connect(ui.sbLightConeAngle, SIGNAL(valueChanged(int)), SLOT(onConeAngleChanged(int))); //Template handler TemplateHandler* templateHandler = new TemplateHandler(this, TemplateHandler::Worksheet); ui.verticalLayout->addWidget(templateHandler, 0, 0); templateHandler->show(); recorder.connect(templateHandler, SIGNAL(loadConfigRequested(KConfig&)), SLOT(loadConfigFromTemplate(KConfig&))); recorder.connect(templateHandler, SIGNAL(saveConfigRequested(KConfig&)), SLOT(saveConfigAsTemplate(KConfig&))); // TODO: Uncomment later //connect(templateHandler, SIGNAL(info(QString)), this, SIGNAL(info(QString))); } void Plot3DDock::setPlots(const QList& plots){ m_plotsList = plots; Q_ASSERT(m_plotsList.size()); m_plot = m_plotsList.first(); { const SignalBlocker blocker(recorder.children()); //if there is more then one plot in the list, disable the name and comment fields in the tab "general" if (m_plotsList.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(""); ui.leComment->setText(""); } //show the properties of the first plot this->load(); } //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) Worksheet* w = dynamic_cast(m_plot->parentAspect()); if (w){ bool b = (w->layout()==Worksheet::NoLayout); ui.sbTop->setEnabled(b); ui.sbLeft->setEnabled(b); ui.sbWidth->setEnabled(b); ui.sbHeight->setEnabled(b); connect(w, SIGNAL(layoutChanged(Worksheet::Layout)), SLOT(onLayoutChanged(Worksheet::Layout))); } //SIGNALs/SLOTs connect(m_plot, SIGNAL(rectChanged(const QRectF&)), this, SLOT(rectChanged(const QRectF&))); //general connect(m_plot, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)), SLOT(descriptionChanged(const AbstractAspect*))); connect(m_plot, SIGNAL(xScalingChanged(Plot3D::Scaling)), SLOT(xScalingChanged(Plot3D::Scaling))); connect(m_plot, SIGNAL(yScalingChanged(Plot3D::Scaling)), SLOT(yScalingChanged(Plot3D::Scaling))); connect(m_plot, SIGNAL(zScalingChanged(Plot3D::Scaling)), SLOT(zScalingChanged(Plot3D::Scaling))); connect(m_plot, SIGNAL(boundsChanged(const BoundingBox&)), SLOT(boundsChanged(const BoundingBox&))); //background connect(m_plot, SIGNAL(backgroundTypeChanged(PlotArea::BackgroundType)), SLOT(backgroundTypeChanged(PlotArea::BackgroundType))); connect(m_plot, SIGNAL(backgroundColorStyleChanged(PlotArea::BackgroundColorStyle)), SLOT(backgroundColorStyleChanged(PlotArea::BackgroundColorStyle))); connect(m_plot, SIGNAL(backgroundImageStyleChanged(PlotArea::BackgroundImageStyle)), SLOT(backgroundImageStyleChanged(PlotArea::BackgroundImageStyle))); connect(m_plot, SIGNAL(backgroundBrushStyleChanged(Qt::BrushStyle)), SLOT(backgroundBrushStyleChanged(Qt::BrushStyle))); connect(m_plot, SIGNAL(backgroundFirstColorChanged(const QColor&)), SLOT(backgroundFirstColorChanged(const QColor&))); connect(m_plot, SIGNAL(backgroundSecondColorChanged(const QColor&)), SLOT(backgroundSecondColorChanged(const QColor&))); connect(m_plot, SIGNAL(backgroundFileNameChanged(const QString&)), SLOT(backgroundFileNameChanged(const QString&))); connect(m_plot, SIGNAL(backgroundOpacityChanged(float)), SLOT(backgroundOpacityChanged(float))); //light connect(m_plot, SIGNAL(intensityChanged(double)), SLOT(intensityChanged(double))); connect(m_plot, SIGNAL(ambientChanged(const QColor&)), SLOT(ambientChanged(const QColor&))); connect(m_plot, SIGNAL(diffuseChanged(const QColor&)), SLOT(diffuseChanged(const QColor&))); connect(m_plot, SIGNAL(specularChanged(const QColor&)), SLOT(specularChanged(const QColor&))); connect(m_plot, SIGNAL(elevationChanged(double)), SLOT(elevationChanged(double))); connect(m_plot, SIGNAL(azimuthChanged(double)), SLOT(azimuthChanged(double))); connect(m_plot, SIGNAL(coneAngleChanged(double)), SLOT(coneAngleChanged(double))); } //************************************************************* //****** SLOTs for changes triggered in Plot3DDock ********* //************************************************************* void Plot3DDock::retranslateUi(){ //general KComboBox* scalingWidgets[3] = {ui.cbXScaling, ui.cbYScaling, ui.cbZScaling}; for (int i = 0; i < 3; ++i) { scalingWidgets[i]->insertItem( Plot3D::Scaling_Linear, i18n("linear") ); scalingWidgets[i]->insertItem( Plot3D::Scaling_Log10, i18n("log(x)") ); scalingWidgets[i]->insertItem( Plot3D::Scaling_Log2, i18n("log2(x)") ); scalingWidgets[i]->insertItem( Plot3D::Scaling_Ln, i18n("ln(x)") ); } //background 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 linear gradient")); ui.cbBackgroundColorStyle->addItem(i18n("vertical linear gradient")); ui.cbBackgroundColorStyle->addItem(i18n("diagonal linear gradient (start from top left)")); ui.cbBackgroundColorStyle->addItem(i18n("diagonal linear gradient (start 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")); //light } // "General"-tab void Plot3DDock::onNameChanged(){ const Lock lock(m_initializing); m_plot->setName(ui.leName->text()); } void Plot3DDock::onCommentChanged(){ const Lock lock(m_initializing); m_plot->setComment(ui.leComment->text()); } void Plot3DDock::onVisibilityChanged(int state){ const Lock lock(m_initializing); const bool b = (state==Qt::Checked); foreach(Plot3D* plot, m_plotsList) plot->setVisible(b); } void Plot3DDock::onGeometryChanged(){ const float x = Worksheet::convertToSceneUnits(ui.sbLeft->value(), Worksheet::Centimeter); const float y = Worksheet::convertToSceneUnits(ui.sbTop->value(), Worksheet::Centimeter); const float w = Worksheet::convertToSceneUnits(ui.sbWidth->value(), Worksheet::Centimeter); const float h = Worksheet::convertToSceneUnits(ui.sbHeight->value(), Worksheet::Centimeter); const QRectF rect(x,y,w,h); const Lock lock(m_initializing); m_plot->setRect(rect); } void Plot3DDock::onXScalingChanged(int index) { const Lock lock(m_initializing); m_plot->setXScaling(static_cast(index)); } void Plot3DDock::onYScalingChanged(int index) { const Lock lock(m_initializing); m_plot->setYScaling(static_cast(index)); } void Plot3DDock::onZScalingChanged(int index) { const Lock lock(m_initializing); m_plot->setZScaling(static_cast(index)); } void Plot3DDock::onAutoScaleXChanged(int state) { const Lock lock(m_initializing); const bool b = (state == Qt::Checked); ui.kleXMin->setEnabled(!b); ui.kleXMax->setEnabled(!b); if (b) { m_plot->autoScaleX(); const BoundingBox& bounds = m_plot->bounds(); ui.kleXMin->setText(QString::number(bounds.xMin())); ui.kleXMax->setText(QString::number(bounds.xMax())); } } void Plot3DDock::onAutoScaleYChanged(int state) { const Lock lock(m_initializing); const bool b = (state == Qt::Checked); ui.kleYMin->setEnabled(!b); ui.kleYMax->setEnabled(!b); if (b) { m_plot->autoScaleY(); const BoundingBox& bounds = m_plot->bounds(); ui.kleYMin->setText(QString::number(bounds.yMin())); ui.kleYMax->setText(QString::number(bounds.yMax())); } } void Plot3DDock::onAutoScaleZChanged(int state) { const Lock lock(m_initializing); const bool b = (state == Qt::Checked); ui.kleZMin->setEnabled(!b); ui.kleZMax->setEnabled(!b); if (b) { m_plot->autoScaleZ(); const BoundingBox& bounds = m_plot->bounds(); ui.kleZMin->setText(QString::number(bounds.zMin())); ui.kleZMax->setText(QString::number(bounds.zMax())); } } void Plot3DDock::onXMinChanged() { const Lock lock(m_initializing); BoundingBox ranges = m_plot->ranges(); ranges.setXMin(ui.kleXMin->text().toDouble()); m_plot->setRanges(ranges); } void Plot3DDock::onYMinChanged() { const Lock lock(m_initializing); BoundingBox ranges = m_plot->ranges(); ranges.setYMin(ui.kleYMin->text().toDouble()); m_plot->setRanges(ranges); } void Plot3DDock::onZMinChanged() { const Lock lock(m_initializing); BoundingBox ranges = m_plot->ranges(); ranges.setZMin(ui.kleZMin->text().toDouble()); m_plot->setRanges(ranges); } void Plot3DDock::onXMaxChanged() { const Lock lock(m_initializing); BoundingBox ranges = m_plot->ranges(); ranges.setXMax(ui.kleXMax->text().toDouble()); m_plot->setRanges(ranges); } void Plot3DDock::onYMaxChanged() { const Lock lock(m_initializing); BoundingBox ranges = m_plot->ranges(); ranges.setYMax(ui.kleYMax->text().toDouble()); m_plot->setRanges(ranges); } void Plot3DDock::onZMaxChanged() { const Lock lock(m_initializing); BoundingBox ranges = m_plot->ranges(); ranges.setZMax(ui.kleZMax->text().toDouble()); m_plot->setRanges(ranges); } /*! 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 Plot3DDock::onLayoutChanged(Worksheet::Layout layout){ bool b = (layout == Worksheet::NoLayout); ui.sbTop->setEnabled(b); ui.sbLeft->setEnabled(b); ui.sbWidth->setEnabled(b); ui.sbHeight->setEnabled(b); if (!b) rectChanged(m_plot->rect()); } // "Background"-tab void Plot3DDock::onBackgroundTypeChanged(int index){ PlotArea::BackgroundType type = (PlotArea::BackgroundType)index; const Lock lock(m_initializing); foreach(Plot3D* plot, m_plotsList) plot->setBackgroundType(type); backgroundTypeChanged(type); } void Plot3DDock::onBackgroundColorStyleChanged(int index){ PlotArea::BackgroundColorStyle style = (PlotArea::BackgroundColorStyle)index; if (style == PlotArea::SingleColor){ ui.lBackgroundFirstColor->setText(i18n("Color")); hideItem(ui.lBackgroundSecondColor, ui.kcbBackgroundSecondColor); }else{ ui.lBackgroundFirstColor->setText(i18n("First Color")); showItem(ui.lBackgroundSecondColor, ui.kcbBackgroundSecondColor); } const Lock lock(m_initializing); foreach(Plot3D* plot, m_plotsList) plot->setBackgroundColorStyle(style); } void Plot3DDock::onBackgroundImageStyleChanged(int index){ const Lock lock(m_initializing); PlotArea::BackgroundImageStyle style = (PlotArea::BackgroundImageStyle)index; foreach(Plot3D* plot, m_plotsList) plot->setBackgroundImageStyle(style); } void Plot3DDock::onBackgroundBrushStyleChanged(int index){ const Lock lock(m_initializing); Qt::BrushStyle style = (Qt::BrushStyle)index; foreach(Plot3D* plot, m_plotsList){ plot->setBackgroundBrushStyle(style); } } void Plot3DDock::onBackgroundFirstColorChanged(const QColor& c){ const Lock lock(m_initializing); foreach(Plot3D* plot, m_plotsList){ plot->setBackgroundFirstColor(c); } } void Plot3DDock::onBackgroundSecondColorChanged(const QColor& c){ const Lock lock(m_initializing); foreach(Plot3D* plot, m_plotsList){ plot->setBackgroundSecondColor(c); } } void Plot3DDock::onBackgroundOpacityChanged(int value){ const Lock lock(m_initializing); float opacity = (float)value/100; foreach(Plot3D* plot, m_plotsList) plot->setBackgroundOpacity(opacity); } void Plot3DDock::onBackgroundSelectFile() { KConfigGroup conf(KSharedConfig::openConfig(), "Plot3DDock"); QString dir = conf.readEntry("LastImageDir", ""); QString path = QFileDialog::getOpenFileName(this, i18n("Select the image file"), dir); if (path.isEmpty()) return; //cancel was clicked in the file-dialog int pos = path.lastIndexOf(QDir::separator()); if (pos!=-1) { QString newDir = path.left(pos); if (newDir!=dir) conf.writeEntry("LastImageDir", newDir); } ui.kleBackgroundFileName->setText( path ); const Lock lock(m_initializing); foreach(Plot3D* plot, m_plotsList) plot->setBackgroundFileName(path); } void Plot3DDock::onBackgroundFileNameChanged(){ if (m_initializing) return; const Lock lock(m_initializing); QString fileName = ui.kleBackgroundFileName->text(); foreach(Plot3D* plot, m_plotsList) plot->setBackgroundFileName(fileName); } // Light void Plot3DDock::onIntensityChanged(double value) { const Lock lock(m_initializing); m_plot->setIntensity(value); } void Plot3DDock::onAmbientChanged(const QColor& color) { const Lock lock(m_initializing); m_plot->setAmbient(color); } void Plot3DDock::onDiffuseChanged(const QColor& color) { const Lock lock(m_initializing); m_plot->setDiffuse(color); } void Plot3DDock::onSpecularChanged(const QColor& color) { const Lock lock(m_initializing); m_plot->setSpecular(color); } void Plot3DDock::onElevationChanged(int elevation) { const Lock lock(m_initializing); m_plot->setElevation(elevation); } void Plot3DDock::onAzimuthChanged(int azimuth) { const Lock lock(m_initializing); m_plot->setAzimuth(azimuth); } void Plot3DDock::onConeAngleChanged(int angle) { const Lock lock(m_initializing); m_plot->setConeAngle(angle); } //************************************************************* //******** SLOTs for changes triggered in Plot3D ************** //************************************************************* // "General"-tab void Plot3DDock::descriptionChanged(const AbstractAspect* aspect) { if (m_plot != aspect) return; if (m_initializing) return; if (aspect->name() != ui.leName->text()) { ui.leName->setText(aspect->name()); } else if (aspect->comment() != ui.leComment->text()) { ui.leComment->setText(aspect->comment()); } } void Plot3DDock::rectChanged(const QRectF& rect){ if (m_initializing) return; ui.sbLeft->setValue(Worksheet::convertFromSceneUnits(rect.x(), Worksheet::Centimeter)); ui.sbTop->setValue(Worksheet::convertFromSceneUnits(rect.y(), Worksheet::Centimeter)); ui.sbWidth->setValue(Worksheet::convertFromSceneUnits(rect.width(), Worksheet::Centimeter)); ui.sbHeight->setValue(Worksheet::convertFromSceneUnits(rect.height(), Worksheet::Centimeter)); } void Plot3DDock::boundsChanged(const BoundingBox&) { rangesChanged(m_plot->ranges()); } void Plot3DDock::visibleChanged(bool on){ if (m_initializing) return; ui.chkVisible->setChecked(on); } // "Background"-tab void Plot3DDock::backgroundTypeChanged(PlotArea::BackgroundType type) { if (type == PlotArea::Color){ showItem(ui.lBackgroundColorStyle, ui.cbBackgroundColorStyle); hideItem(ui.lBackgroundImageStyle, ui.cbBackgroundImageStyle); hideItem(ui.lBackgroundBrushStyle, ui.cbBackgroundBrushStyle); hideItem(ui.lBackgroundFileName, ui.kleBackgroundFileName); ui.bBackgroundOpen->hide(); showItem(ui.lBackgroundFirstColor, ui.kcbBackgroundFirstColor); PlotArea::BackgroundColorStyle style = (PlotArea::BackgroundColorStyle) ui.cbBackgroundColorStyle->currentIndex(); if (style == PlotArea::SingleColor){ ui.lBackgroundFirstColor->setText(i18n("Color")); hideItem(ui.lBackgroundSecondColor, ui.kcbBackgroundSecondColor); }else{ ui.lBackgroundFirstColor->setText(i18n("First Color")); showItem(ui.lBackgroundSecondColor, ui.kcbBackgroundSecondColor); } }else if(type == PlotArea::Image){ hideItem(ui.lBackgroundFirstColor, ui.kcbBackgroundFirstColor); hideItem(ui.lBackgroundSecondColor, ui.kcbBackgroundSecondColor); hideItem(ui.lBackgroundColorStyle, ui.cbBackgroundColorStyle); showItem(ui.lBackgroundImageStyle, ui.cbBackgroundImageStyle); hideItem(ui.lBackgroundBrushStyle, ui.cbBackgroundBrushStyle); showItem(ui.lBackgroundFileName, ui.kleBackgroundFileName); ui.bBackgroundOpen->show(); }else if(type == PlotArea::Pattern){ ui.lBackgroundFirstColor->setText(i18n("Color")); showItem(ui.lBackgroundFirstColor, ui.kcbBackgroundFirstColor); hideItem(ui.lBackgroundSecondColor, ui.kcbBackgroundSecondColor); hideItem(ui.lBackgroundColorStyle, ui.cbBackgroundColorStyle); hideItem(ui.lBackgroundImageStyle, ui.cbBackgroundImageStyle); showItem(ui.lBackgroundBrushStyle, ui.cbBackgroundBrushStyle); hideItem(ui.lBackgroundFileName, ui.kleBackgroundFileName); ui.bBackgroundOpen->hide(); } if (m_initializing) return; ui.cbBackgroundType->setCurrentIndex(type); } void Plot3DDock::backgroundColorStyleChanged(PlotArea::BackgroundColorStyle style) { if (m_initializing) return; ui.cbBackgroundColorStyle->setCurrentIndex(style); } void Plot3DDock::backgroundImageStyleChanged(PlotArea::BackgroundImageStyle style) { if (m_initializing) return; ui.cbBackgroundImageStyle->setCurrentIndex(style); } void Plot3DDock::backgroundBrushStyleChanged(Qt::BrushStyle style) { if (m_initializing) return; ui.cbBackgroundBrushStyle->setCurrentIndex(style); } void Plot3DDock::backgroundFirstColorChanged(const QColor& color) { if (m_initializing) return; ui.kcbBackgroundFirstColor->setColor(color); } void Plot3DDock::backgroundSecondColorChanged(const QColor& color) { if (m_initializing) return; ui.kcbBackgroundSecondColor->setColor(color); } void Plot3DDock::backgroundFileNameChanged(const QString& name) { if (m_initializing) return; ui.kleBackgroundFileName->setText(name); } void Plot3DDock::backgroundOpacityChanged(float opacity) { if (m_initializing) return; ui.sbBackgroundOpacity->setValue( round(opacity*100.0) ); } // Light void Plot3DDock::intensityChanged(double val) { if (m_initializing) return; ui.sbLightIntensity->setValue(val); } void Plot3DDock::ambientChanged(const QColor& color) { if (m_initializing) return; ui.kcbLightAmbientColor->setColor(color); } void Plot3DDock::diffuseChanged(const QColor& color) { if (m_initializing) return; ui.kcbLightDiffuseColor->setColor(color); } void Plot3DDock::specularChanged(const QColor& color) { if (m_initializing) return; ui.kcbLightSpecularColor->setColor(color); } void Plot3DDock::elevationChanged(double val) { if (m_initializing) return; ui.sbLightElevation->setValue(val); } void Plot3DDock::azimuthChanged(double val) { if (m_initializing) return; ui.sbLightAzimuth->setValue(val); } void Plot3DDock::coneAngleChanged(double val) { if (m_initializing) return; ui.sbLightConeAngle->setValue(val); } void Plot3DDock::xScalingChanged(Plot3D::Scaling scaling) { if (m_initializing) return; ui.cbXScaling->setCurrentIndex(scaling); } void Plot3DDock::yScalingChanged(Plot3D::Scaling scaling) { if (m_initializing) return; ui.cbYScaling->setCurrentIndex(scaling); } void Plot3DDock::zScalingChanged(Plot3D::Scaling scaling) { if (m_initializing) return; ui.cbZScaling->setCurrentIndex(scaling); } void Plot3DDock::rangesChanged(const BoundingBox& bounds) { if (m_initializing) return; ui.kleXMin->setText(QString::number(bounds.xMin())); ui.kleYMin->setText(QString::number(bounds.yMin())); ui.kleZMin->setText(QString::number(bounds.zMin())); ui.kleXMax->setText(QString::number(bounds.xMax())); ui.kleYMax->setText(QString::number(bounds.yMax())); ui.kleZMax->setText(QString::number(bounds.zMax())); } //************************************************************* //******************** SETTINGS ******************************* //************************************************************* void Plot3DDock::load(){ qDebug() << Q_FUNC_INFO; //General visibleChanged(m_plot->isVisible()); rectChanged(m_plot->rect()); //TODO: //ui.cbType->setCurrentIndex((int)m_plot->visualizationType()) // General ui.leName->setText(m_plot->name()); ui.leComment->setText(m_plot->comment()); xScalingChanged(m_plot->xScaling()); yScalingChanged(m_plot->yScaling()); zScalingChanged(m_plot->zScaling()); rangesChanged(m_plot->ranges()); //Background backgroundTypeChanged(m_plot->backgroundType()); backgroundColorStyleChanged(m_plot->backgroundColorStyle()); backgroundImageStyleChanged(m_plot->backgroundImageStyle()); backgroundBrushStyleChanged(m_plot->backgroundBrushStyle()); backgroundFileNameChanged(m_plot->backgroundFileName()); backgroundFirstColorChanged(m_plot->backgroundFirstColor()); backgroundSecondColorChanged(m_plot->backgroundSecondColor()); backgroundOpacityChanged(m_plot->backgroundOpacity()); //Light intensityChanged(m_plot->intensity()); ambientChanged(m_plot->ambient()); diffuseChanged(m_plot->diffuse()); specularChanged(m_plot->specular()); elevationChanged(m_plot->elevation()); azimuthChanged(m_plot->azimuth()); coneAngleChanged(m_plot->coneAngle()); } void Plot3DDock::loadConfigFromTemplate(KConfig& config) { //extract the name of the template from the file name QString name; int index = config.name().lastIndexOf(QDir::separator()); if (index!=-1) name = config.name().right(config.name().size() - index - 1); else name = config.name(); int size = m_plotsList.size(); if (size>1) m_plot->beginMacro(i18n("%1 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 Plot3DDock::loadConfig(KConfig& config){ KConfigGroup group = config.group("Plot3D"); //General //Background ui.cbBackgroundType->setCurrentIndex( group.readEntry("BackgroundType", (int) m_plot->backgroundType()) ); ui.cbBackgroundColorStyle->setCurrentIndex( group.readEntry("BackgroundColorStyle", (int) m_plot->backgroundColorStyle()) ); ui.cbBackgroundImageStyle->setCurrentIndex( group.readEntry("BackgroundImageStyle", (int) m_plot->backgroundImageStyle()) ); ui.cbBackgroundBrushStyle->setCurrentIndex( group.readEntry("BackgroundBrushStyle", (int) m_plot->backgroundBrushStyle()) ); ui.kleBackgroundFileName->setText( group.readEntry("BackgroundFileName", m_plot->backgroundFileName()) ); ui.kcbBackgroundFirstColor->setColor( group.readEntry("BackgroundFirstColor", m_plot->backgroundFirstColor()) ); ui.kcbBackgroundSecondColor->setColor( group.readEntry("BackgroundSecondColor", m_plot->backgroundSecondColor()) ); backgroundOpacityChanged(group.readEntry("BackgroundOpacity", m_plot->backgroundOpacity())); //Light } void Plot3DDock::saveConfigAsTemplate(KConfig& config) { KConfigGroup group = config.group("Plot3D"); //General //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.kleBackgroundFileName->text()); group.writeEntry("BackgroundFirstColor", ui.kcbBackgroundFirstColor->color()); group.writeEntry("BackgroundSecondColor", ui.kcbBackgroundSecondColor->color()); group.writeEntry("BackgroundOpacity", ui.sbBackgroundOpacity->value()/100.0); //Light config.sync(); -} \ No newline at end of file +} diff --git a/src/kdefrontend/dockwidgets/Surface3DDock.cpp b/src/kdefrontend/dockwidgets/Surface3DDock.cpp index 1670612fe..60bb5c360 100644 --- a/src/kdefrontend/dockwidgets/Surface3DDock.cpp +++ b/src/kdefrontend/dockwidgets/Surface3DDock.cpp @@ -1,526 +1,530 @@ /*************************************************************************** File : Surface3DDock.cpp Project : LabPlot Description : widget for 3D surfaces properties -------------------------------------------------------------------- Copyright : (C) 2015 Minh Ngo (minh@fedoraproject.org) ***************************************************************************/ /*************************************************************************** * * * 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 "Surface3DDock.h" #include "backend/core/AbstractAspect.h" #include "backend/core/AbstractColumn.h" #include "backend/core/AspectTreeModel.h" #include "backend/core/Project.h" #include "backend/matrix/Matrix.h" #include "kdefrontend/TemplateHandler.h" #include "commonfrontend/widgets/ColorMapSelector.h" #include #include +#include +#include +#include + using namespace DockHelpers; Surface3DDock::Surface3DDock(QWidget* parent) : QWidget(parent) , recorder(this) , aspectTreeModel(0) , m_initializing(false) { ui.setupUi(this); this->retranslateUi(); QList list; list << "Folder" << "Workbook" << "Spreadsheet" << "FileDataSource" << "Column"; const QVector treeViews(QVector() << ui.cbXCoordinate << ui.cbYCoordinate << ui.cbZCoordinate << ui.cbNode1 << ui.cbNode2 << ui.cbNode3); foreach(TreeViewComboBox* view, treeViews) { view->setTopLevelClasses(list); } list.clear(); list << "Column"; foreach(TreeViewComboBox* view, treeViews) { - view->setSelectableClasses(list); +// view->setSelectableClasses(list); recorder.connect(view, SIGNAL(currentModelIndexChanged(const QModelIndex&)), SLOT(onTreeViewIndexChanged(const QModelIndex&))); } //Matrix data source list.clear(); list<<"Folder"<<"Workbook"<<"Matrix"; ui.cbMatrix->setTopLevelClasses(list); list.clear(); list<<"Matrix"; - ui.cbMatrix->setSelectableClasses(list); +// ui.cbMatrix->setSelectableClasses(list); //Tab "Color Filling" QGridLayout* gridLayout = qobject_cast(ui.tabColorFilling->layout()); cmsColorFilling = new ColorMapSelector(ui.tabColorFilling); gridLayout->addWidget(cmsColorFilling, 2, 2, 1, 1); //SIGNALs/SLOTs //General recorder.connect(ui.leName, SIGNAL(returnPressed()), SLOT(onNameChanged())); recorder.connect(ui.leComment, SIGNAL(returnPressed()), SLOT(onCommentChanged())); recorder.connect(ui.cbDataSource, SIGNAL(currentIndexChanged(int)), SLOT(onDataSourceChanged(int))); recorder.connect(ui.cbFileRequester, SIGNAL(urlSelected(const KUrl&)), SLOT(onFileChanged(const KUrl&))); recorder.connect(ui.cbMatrix, SIGNAL(currentModelIndexChanged(const QModelIndex&)), SLOT(onTreeViewIndexChanged(const QModelIndex&))); recorder.connect(ui.chkVisible, SIGNAL(toggled(bool)), SLOT(onVisibilityChanged(bool))); //Color filling recorder.connect(ui.cbColorFillingType, SIGNAL(currentIndexChanged(int)), SLOT(onColorFillingTypeChanged(int))); recorder.connect(ui.kcbColorFilling, SIGNAL(changed(QColor)), SLOT(onColorChanged(const QColor&))); recorder.connect(cmsColorFilling, SIGNAL(changed(ColorMapManager::ColorMapId)), SLOT(onColorMapChanged(ColorMapManager::ColorMapId))); recorder.connect(ui.sbColorFillingOpacity, SIGNAL(valueChanged(int)), SLOT(onOpacityChanged(int))); //Mesh recorder.connect(ui.cbType, SIGNAL(currentIndexChanged(int)), SLOT(onVisualizationTypeChanged(int))); //Projection recorder.connect(ui.chbXYProjection, SIGNAL(toggled(bool)), SLOT(onXYProjection(bool))); recorder.connect(ui.chbXZProjection, SIGNAL(toggled(bool)), SLOT(onXZProjection(bool))); recorder.connect(ui.chbYZProjection, SIGNAL(toggled(bool)), SLOT(onYZProjection(bool))); //template handler TemplateHandler* templateHandler = new TemplateHandler(this, TemplateHandler::Surface3D); ui.verticalLayout->addWidget(templateHandler); templateHandler->show(); recorder.connect(templateHandler, SIGNAL(loadConfigRequested(KConfig&)), SLOT(loadConfigFromTemplate(KConfig&))); recorder.connect(templateHandler, SIGNAL(saveConfigRequested(KConfig&)), SLOT(saveConfigAsTemplate(KConfig&))); recorder.connect(templateHandler, SIGNAL(info(QString)), SIGNAL(info(QString))); } void Surface3DDock::onXYProjection(bool show) { const Lock lock(m_initializing); foreach (Surface3D* surface, surfaces) surface->setShowXYProjection(show); } void Surface3DDock::onXZProjection(bool show) { const Lock lock(m_initializing); foreach (Surface3D* surface, surfaces) surface->setShowXZProjection(show); } void Surface3DDock::onYZProjection(bool show) { const Lock lock(m_initializing); foreach (Surface3D* surface, surfaces) surface->setShowYZProjection(show); } void Surface3DDock::xyProjection(bool show) { if (m_initializing) return; ui.chbXYProjection->setChecked(show); } void Surface3DDock::xzProjection(bool show) { if (m_initializing) return; ui.chbXZProjection->setChecked(show); } void Surface3DDock::yzProjection(bool show) { if (m_initializing) return; ui.chbYZProjection->setChecked(show); } void Surface3DDock::setSurfaces(const QList& surfaces) { this->surfaces = surfaces; { const SignalBlocker blocker(recorder.children()); if (surfaces.size() == 1) { ui.leName->setText(surfaces.first()->name()); ui.leComment->setText(surfaces.first()->comment()); ui.leName->setEnabled(true); ui.leComment->setEnabled(true); ui.chkVisible->setEnabled(true); ui.chkVisible->setChecked(surfaces.first()->isVisible()); } else { ui.leName->setEnabled(false); ui.leComment->setEnabled(false); ui.chkVisible->setEnabled(false); } aspectTreeModel = new AspectTreeModel(surfaces.first()->project()); ui.cbXCoordinate->setModel(aspectTreeModel); ui.cbYCoordinate->setModel(aspectTreeModel); ui.cbZCoordinate->setModel(aspectTreeModel); ui.cbNode1->setModel(aspectTreeModel); ui.cbNode2->setModel(aspectTreeModel); ui.cbNode3->setModel(aspectTreeModel); ui.cbMatrix->setModel(aspectTreeModel); ui.cbColorFillingMatrix->setModel(aspectTreeModel); foreach (Surface3D* surface, surfaces) { visualizationTypeChanged(surface->visualizationType()); sourceTypeChanged(surface->dataSource()); colorFillingChanged(surface->colorFilling()); colorChanged(surface->color()); opacityChanged(surface->opacity()); pathChanged(surface->file()); xyProjection(surface->showXYProjection()); xzProjection(surface->showXZProjection()); yzProjection(surface->showYZProjection()); matrixChanged(surface->matrix()); xColumnChanged(surface->xColumn()); yColumnChanged(surface->yColumn()); zColumnChanged(surface->zColumn()); firstNodeChanged(surface->firstNode()); secondNodeChanged(surface->secondNode()); thirdNodeChanged(surface->thirdNode()); } } foreach (Surface3D* surface, surfaces) { connect(surface, SIGNAL(visualizationTypeChanged(Surface3D::VisualizationType)), SLOT(visualizationTypeChanged(Surface3D::VisualizationType))); connect(surface, SIGNAL(sourceTypeChanged(Surface3D::DataSource)), SLOT(sourceTypeChanged(Surface3D::DataSource))); connect(surface, SIGNAL(visibilityChanged(bool)), ui.chkVisible, SLOT(setChecked(bool))); connect(surface, SIGNAL(colorFillingChanged(Surface3D::ColorFilling)), SLOT(colorFillingChanged(Surface3D::ColorFilling))); connect(surface, SIGNAL(colorChanged(const QColor&)), SLOT(colorChanged(const QColor&))); connect(surface, SIGNAL(opacityChanged(double)), SLOT(opacityChanged(double))); connect(surface, SIGNAL(showXYProjectionChanged(bool)), SLOT(xyProjection(bool))); connect(surface, SIGNAL(showXZProjectionChanged(bool)), SLOT(xzProjection(bool))); connect(surface, SIGNAL(showYZProjectionChanged(bool)), SLOT(yzProjection(bool))); // DataHandlers connect(surface, SIGNAL(pathChanged(const KUrl&)), SLOT(pathChanged(const KUrl&))); connect(surface, SIGNAL(matrixChanged(const Matrix*)), SLOT(matrixChanged(const Matrix*))); connect(surface, SIGNAL(xColumnChanged(const AbstractColumn*)), SLOT(xColumnChanged(const AbstractColumn*))); connect(surface, SIGNAL(yColumnChanged(const AbstractColumn*)), SLOT(yColumnChanged(const AbstractColumn*))); connect(surface, SIGNAL(zColumnChanged(const AbstractColumn*)), SLOT(zColumnChanged(const AbstractColumn*))); connect(surface, SIGNAL(firstNodeChanged(const AbstractColumn*)), SLOT(firstNodeChanged(const AbstractColumn*))); connect(surface, SIGNAL(secondNodeChanged(const AbstractColumn*)), SLOT(secondNodeChanged(const AbstractColumn*))); connect(surface, SIGNAL(thirdNodeChanged(const AbstractColumn*)), SLOT(thirdNodeChanged(const AbstractColumn*))); } } void Surface3DDock::showTriangleInfo(bool pred) { if (m_initializing) return; showItem(ui.labelX, ui.cbXCoordinate, pred); showItem(ui.labelY, ui.cbYCoordinate, pred); showItem(ui.labelZ, ui.cbZCoordinate, pred); showItem(ui.labelNode1, ui.cbNode1, pred); showItem(ui.labelNode2, ui.cbNode2, pred); showItem(ui.labelNode3, ui.cbNode3, pred); ui.labelNodeHeader->setVisible(pred); emit elementVisibilityChanged(); } //************************************************************* //****** SLOTs for changes triggered in Surface3DDock ********* //************************************************************* void Surface3DDock::retranslateUi(){ //color filling ui.cbColorFillingType->insertItem(Surface3D::ColorFilling_Empty, i18n("no filling")); ui.cbColorFillingType->insertItem(Surface3D::ColorFilling_SolidColor, i18n("solid color")); ui.cbColorFillingType->insertItem(Surface3D::ColorFilling_ColorMap, i18n("color map")); ui.cbColorFillingType->insertItem(Surface3D::ColorFilling_ElevationLevel, i18n("elevation level")); ui.cbColorFillingType->insertItem(Surface3D::ColorFilling_ColorMapFromMatrix, i18n("color map from matrix")); ui.cbDataSource->insertItem(Surface3D::DataSource_File, i18n("File")); ui.cbDataSource->insertItem(Surface3D::DataSource_Spreadsheet, i18n("Spreadsheet")); ui.cbDataSource->insertItem(Surface3D::DataSource_Matrix, i18n("Matrix")); ui.cbDataSource->insertItem(Surface3D::DataSource_Empty, i18n("Demo")); ui.cbType->insertItem(Surface3D::VisualizationType_Triangles, i18n("Triangles")); ui.cbType->insertItem(Surface3D::VisualizationType_Wireframe, i18n("Wireframe")); } void Surface3DDock::onTreeViewIndexChanged(const QModelIndex& index) { const AbstractColumn* column = getColumn(index); QObject *senderW = sender(); const Lock lock(m_initializing); foreach (Surface3D* surface, surfaces) { if(senderW == ui.cbXCoordinate) surface->setXColumn(column); else if(senderW == ui.cbYCoordinate) surface->setYColumn(column); else if(senderW == ui.cbZCoordinate) surface->setZColumn(column); else if(senderW == ui.cbNode1) surface->setFirstNode(column); else if(senderW == ui.cbNode2) surface->setSecondNode(column); else if(senderW == ui.cbNode3) surface->setThirdNode(column); else if(senderW == ui.cbMatrix) surface->setMatrix(getMatrix(index)); } } void Surface3DDock::onVisibilityChanged(bool visible) { const Lock lock(m_initializing); foreach (Surface3D* surface, surfaces) { surface->show(visible); } } void Surface3DDock::onColorChanged(const QColor& color) { const Lock lock(m_initializing); foreach (Surface3D* surface, surfaces) { surface->setColor(color); } } void Surface3DDock::onColorMapChanged(ColorMapManager::ColorMapId id) { const Lock lock(m_initializing); // surface->setColorMap(id); } void Surface3DDock::onOpacityChanged(int val) { const Lock lock(m_initializing); foreach (Surface3D* surface, surfaces) { surface->setOpacity(val / 100.0); } } void Surface3DDock::onDataSourceChanged(int index) { if (m_initializing) return; const Surface3D::DataSource type = static_cast(index); { const Lock lock(m_initializing); foreach (Surface3D* surface, surfaces) surface->setDataSource(type); } updateUiVisibility(); } void Surface3DDock::updateUiVisibility() { const int type = ui.cbType->currentIndex(); const int dataType = ui.cbDataSource->currentIndex(); if (type == Surface3D::VisualizationType_Triangles || type == Surface3D::VisualizationType_Wireframe) { showItem(ui.labelSource, ui.cbDataSource); showItem(ui.labelFile, ui.cbFileRequester, dataType == Surface3D::DataSource_File); showItem(ui.labelMatrix, ui.cbMatrix, dataType == Surface3D::DataSource_Matrix); showTriangleInfo(dataType == Surface3D::DataSource_Spreadsheet); } else { hideItem(ui.labelSource, ui.cbDataSource); hideItem(ui.labelFile, ui.cbFileRequester); showTriangleInfo(false); } emit elementVisibilityChanged(); } void Surface3DDock::onVisualizationTypeChanged(int index) { { const Lock lock(m_initializing); foreach (Surface3D* surface, surfaces) surface->setVisualizationType(static_cast(index)); } if(index == Surface3D::VisualizationType_Triangles) onDataSourceChanged(ui.cbDataSource->currentIndex()); else updateUiVisibility(); } void Surface3DDock::onFileChanged(const KUrl& path) { if (!path.isLocalFile()) return; const Lock lock(m_initializing); - + foreach (Surface3D* surface, surfaces) surface->setFile(path); } void Surface3DDock::visualizationTypeChanged(Surface3D::VisualizationType type) { if (m_initializing) return; ui.cbType->setCurrentIndex(type); updateUiVisibility(); } void Surface3DDock::sourceTypeChanged(Surface3D::DataSource type) { if (m_initializing) return; ui.cbDataSource->setCurrentIndex(type); updateUiVisibility(); } void Surface3DDock::pathChanged(const KUrl& url) { if (m_initializing) return; ui.cbFileRequester->setUrl(url); } void Surface3DDock::setModelFromAspect(TreeViewComboBox* cb, const AbstractAspect* aspect) { if (m_initializing) return; cb->setCurrentModelIndex(modelIndexOfAspect(aspectTreeModel, aspect)); } void Surface3DDock::matrixChanged(const Matrix* matrix) { setModelFromAspect(ui.cbMatrix, matrix); } void Surface3DDock::xColumnChanged(const AbstractColumn* column) { setModelFromAspect(ui.cbXCoordinate, column); } void Surface3DDock::yColumnChanged(const AbstractColumn* column) { setModelFromAspect(ui.cbYCoordinate, column); } void Surface3DDock::zColumnChanged(const AbstractColumn* column) { setModelFromAspect(ui.cbZCoordinate, column); } void Surface3DDock::firstNodeChanged(const AbstractColumn* column) { setModelFromAspect(ui.cbNode1, column); } void Surface3DDock::secondNodeChanged(const AbstractColumn* column) { setModelFromAspect(ui.cbNode2, column); } void Surface3DDock::thirdNodeChanged(const AbstractColumn* column) { setModelFromAspect(ui.cbNode3, column); } void Surface3DDock::colorFillingChanged(Surface3D::ColorFilling type) { if (type == Surface3D::ColorFilling_Empty || type == Surface3D::ColorFilling_ElevationLevel) { hideItem(ui.lColorFilling, ui.kcbColorFilling); hideItem(ui.lColorFillingMap, cmsColorFilling); hideItem(ui.lColorFillingMatrix, ui.cbColorFillingMatrix); hideItem(ui.lColorFillingOpacity, ui.sbColorFillingOpacity); } else if (type == Surface3D::ColorFilling_SolidColor) { showItem(ui.lColorFilling, ui.kcbColorFilling); hideItem(ui.lColorFillingMap, cmsColorFilling); hideItem(ui.lColorFillingMatrix, ui.cbColorFillingMatrix); showItem(ui.lColorFillingOpacity, ui.sbColorFillingOpacity); } else if (type == Surface3D::ColorFilling_ColorMap) { hideItem(ui.lColorFilling, ui.kcbColorFilling); showItem(ui.lColorFillingMap, cmsColorFilling); hideItem(ui.lColorFillingMatrix, ui.cbColorFillingMatrix); showItem(ui.lColorFillingOpacity, ui.sbColorFillingOpacity); } else if (type == Surface3D::ColorFilling_ColorMapFromMatrix) { hideItem(ui.lColorFilling, ui.kcbColorFilling); hideItem(ui.lColorFillingMap, cmsColorFilling); showItem(ui.lColorFillingMatrix, ui.cbColorFillingMatrix); showItem(ui.lColorFillingOpacity, ui.sbColorFillingOpacity); } if (m_initializing) return; ui.cbColorFillingType->setCurrentIndex(type); } void Surface3DDock::colorChanged(const QColor& color) { if (m_initializing) return; ui.kcbColorFilling->setColor(color); } void Surface3DDock::opacityChanged(double val) { if (m_initializing) return; ui.sbColorFillingOpacity->setValue(qRound(val * 100)); } void Surface3DDock::onNameChanged() { const Lock lock(m_initializing); surfaces.first()->setName(ui.leName->text()); } void Surface3DDock::onCommentChanged() { const Lock lock(m_initializing); surfaces.first()->setComment(ui.leComment->text()); } //Collor filling void Surface3DDock::onColorFillingTypeChanged(int index) { const Surface3D::ColorFilling type = static_cast(index); { const Lock lock(m_initializing); foreach (Surface3D* surface, surfaces) surface->setColorFilling(type); } colorFillingChanged(type); emit elementVisibilityChanged(); } //************************************************************* //************************* Settings ************************** //************************************************************* void Surface3DDock::load() { //TODO } void Surface3DDock::loadConfigFromTemplate(KConfig& config) { //extract the name of the template from the file name QString name; int index = config.name().lastIndexOf(QDir::separator()); if (index!=-1) name = config.name().right(config.name().size() - index - 1); else name = config.name(); //TODO // int size = m_curvesList.size(); // if (size>1) // m_curve->beginMacro(i18n("%1 3D-surfaces: template \"%2\" loaded", size, name)); // else // m_curve->beginMacro(i18n("%1: template \"%2\" loaded", m_surface->name(), name)); this->loadConfig(config); // m_surface->endMacro(); } void Surface3DDock::loadConfig(KConfig& config) { KConfigGroup group = config.group("Surface3D"); //TODO } void Surface3DDock::saveConfigAsTemplate(KConfig& config) { KConfigGroup group = config.group("Surface3D"); //TODO config.sync(); }