File indexing completed on 2024-05-12 03:47:26
0001 /* 0002 File : AbstractPart.cpp 0003 Project : LabPlot 0004 Description : Base class of Aspects with MDI windows as views. 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2008 Knut Franke <knut.franke@gmx.de> 0007 SPDX-FileCopyrightText: 2012-2024 Alexander Semke <alexander.semke@web.de> 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #include "backend/core/AbstractPart.h" 0012 #include "backend/core/Settings.h" 0013 #include "commonfrontend/core/ContentDockWidget.h" 0014 0015 #include <DockManager.h> 0016 #include <QMenu> 0017 #include <QStyle> 0018 0019 #include <KLocalizedString> 0020 0021 /** 0022 * \class AbstractPart 0023 * \brief Base class of Aspects with MDI windows as views (AspectParts). 0024 */ 0025 AbstractPart::AbstractPart(const QString& name, AspectType type) 0026 : AbstractAspect(name, type) { 0027 } 0028 0029 AbstractPart::~AbstractPart() { 0030 if (m_dockWidget) 0031 delete m_dockWidget; 0032 } 0033 0034 /** 0035 * \fn QWidget *AbstractPart::view() const 0036 * \brief Construct a primary view on me. 0037 * 0038 * The caller receives ownership of the view. 0039 * 0040 * This method may be called multiple times during the life time of a Part, or it might not get 0041 * called at all. Parts must not depend on the existence of a view for their operation. 0042 */ 0043 0044 /** 0045 * \brief Wrap the view() into a PartMdiView. 0046 * 0047 * A new view is only created the first time this method is called; 0048 * after that, a pointer to the pre-existing view is returned. 0049 */ 0050 ContentDockWidget* AbstractPart::dockWidget() const { 0051 #ifndef SDK 0052 if (!m_dockWidget) { 0053 m_dockWidget = new ContentDockWidget(const_cast<AbstractPart*>(this)); 0054 connect(m_dockWidget, &ads::CDockWidget::closed, [this] { 0055 const bool deleteOnClose = Settings::readDockPosBehaviour() == Settings::DockPosBehaviour::AboveLastActive; 0056 if (deleteOnClose && !m_suppressDeletion) { 0057 m_dockWidget->dockManager()->removeDockWidget(m_dockWidget); 0058 m_dockWidget = nullptr; 0059 deleteView(); 0060 } 0061 }); 0062 } 0063 #endif 0064 return m_dockWidget; 0065 } 0066 0067 bool AbstractPart::dockWidgetExists() const { 0068 return m_dockWidget != nullptr; 0069 } 0070 0071 void AbstractPart::suppressDeletion(bool suppress) { 0072 m_suppressDeletion = suppress; 0073 } 0074 0075 bool AbstractPart::hasMdiSubWindow() const { 0076 return m_dockWidget; 0077 } 0078 0079 /*! 0080 * this function is called when PartMdiView, the mdi-subwindow-wrapper of the actual view, 0081 * is closed (=deleted) in MainWindow. Makes sure that the view also gets deleted. 0082 */ 0083 void AbstractPart::deleteView() const { 0084 // if the parent is a Workbook or Datapicker, the actual view was already deleted when QTabWidget was deleted. 0085 // here just set the pointer to 0. 0086 auto* parent = parentAspect(); 0087 auto type = parent->type(); 0088 if (type == AspectType::Workbook || type == AspectType::Datapicker 0089 || (parent->parentAspect() && parent->parentAspect()->type() == AspectType::Datapicker)) { 0090 m_partView = nullptr; 0091 return; 0092 } 0093 0094 if (m_partView) { 0095 Q_EMIT viewAboutToBeDeleted(); 0096 delete m_partView; 0097 m_partView = nullptr; 0098 } 0099 } 0100 0101 /** 0102 * \brief Return AbstractAspect::createContextMenu() plus operations on the primary view. 0103 */ 0104 QMenu* AbstractPart::createContextMenu() { 0105 auto type = this->type(); 0106 QMenu* menu; 0107 if (type != AspectType::StatisticsSpreadsheet) { 0108 menu = AbstractAspect::createContextMenu(); 0109 menu->addSeparator(); 0110 } else 0111 menu = new QMenu(); 0112 0113 // import actions for spreadsheet and matrix 0114 if ((type == AspectType::Spreadsheet || type == AspectType::Matrix) && type != AspectType::LiveDataSource && type != AspectType::MQTTTopic) { 0115 QMenu* subMenu = new QMenu(i18n("Import Data"), menu); 0116 subMenu->addAction(QIcon::fromTheme(QLatin1String("document-import")), i18n("From File..."), this, &AbstractPart::importFromFileRequested); 0117 subMenu->addAction(QIcon::fromTheme(QLatin1String("document-import")), 0118 i18n("From SQL Database..."), 0119 this, 0120 &AbstractPart::importFromSQLDatabaseRequested); 0121 menu->addMenu(subMenu); 0122 menu->addSeparator(); 0123 } 0124 0125 // export/print actions 0126 if (type != AspectType::CantorWorksheet) 0127 menu->addAction(QIcon::fromTheme(QLatin1String("document-export-database")), i18n("Export"), this, &AbstractPart::exportRequested); 0128 menu->addAction(QIcon::fromTheme(QLatin1String("document-print")), i18n("Print"), this, &AbstractPart::printRequested); 0129 menu->addAction(QIcon::fromTheme(QLatin1String("document-print-preview")), i18n("Print Preview"), this, &AbstractPart::printPreviewRequested); 0130 menu->addSeparator(); 0131 0132 // window state related actions 0133 if (m_dockWidget) { 0134 const QStyle* style = m_dockWidget->style(); 0135 if (!m_dockWidget->isClosed()) { 0136 auto* action = menu->addAction(i18n("&Close"), [this]() { 0137 m_dockWidget->toggleView(false); 0138 }); 0139 action->setIcon(style->standardIcon(QStyle::SP_TitleBarCloseButton)); 0140 } else { 0141 menu->addAction(i18n("Show"), [this]() { 0142 m_dockWidget->toggleView(true); 0143 }); 0144 } 0145 } else { 0146 // if the mdi window was closed, add the "Show" action. 0147 // Don't add it for: 0148 //* children of a workbook, cannot be hidden/minimized 0149 //* data spreadsheets in datapicker curves 0150 auto parentType = parentAspect()->type(); 0151 bool disableShow = ((type == AspectType::Spreadsheet || type == AspectType::Matrix) && parentType == AspectType::Workbook) 0152 || (type == AspectType::Spreadsheet && parentType == AspectType::DatapickerCurve); 0153 if (!disableShow) { 0154 menu->addAction(i18n("Show"), [this]() { 0155 m_dockWidget->toggleView(true); 0156 }); 0157 } 0158 } 0159 0160 return menu; 0161 } 0162 0163 bool AbstractPart::isDraggable() const { 0164 // TODO: moving workbook children doesn't work at the moment, don't allow to move it for now 0165 if ((type() == AspectType::Spreadsheet || type() == AspectType::Matrix) && parentAspect()->type() == AspectType::Workbook) 0166 return false; 0167 else 0168 return true; 0169 } 0170 0171 QVector<AspectType> AbstractPart::dropableOn() const { 0172 return QVector<AspectType>{AspectType::Folder, AspectType::Project}; 0173 }