File indexing completed on 2024-05-12 15:27:35

0001 /***************************************************************************
0002     File                 : CantorWorksheetView.cpp
0003     Project              : LabPlot
0004     Description          : View class for CantorWorksheet
0005     --------------------------------------------------------------------
0006     Copyright            : (C) 2015 Garvit Khatri (garvitdelhi@gmail.com)
0007 
0008  ***************************************************************************/
0009 
0010 /***************************************************************************
0011  *                                                                         *
0012  *  This program is free software; you can redistribute it and/or modify   *
0013  *  it under the terms of the GNU General Public License as published by   *
0014  *  the Free Software Foundation; either version 2 of the License, or      *
0015  *  (at your option) any later version.                                    *
0016  *                                                                         *
0017  *  This program is distributed in the hope that it will be useful,        *
0018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0020  *  GNU General Public License for more details.                           *
0021  *                                                                         *
0022  *   You should have received a copy of the GNU General Public License     *
0023  *   along with this program; if not, write to the Free Software           *
0024  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0025  *   Boston, MA  02110-1301  USA                                           *
0026  *                                                                         *
0027  ***************************************************************************/
0028 
0029 #include "CantorWorksheetView.h"
0030 #include "backend/cantorWorksheet/CantorWorksheet.h"
0031 
0032 #include <QHBoxLayout>
0033 #include <QLabel>
0034 #include <QMenu>
0035 #include <QToolBar>
0036 
0037 #include <KToggleAction>
0038 #include <KLocalizedString>
0039 #include <KParts/ReadWritePart>
0040 
0041 CantorWorksheetView::CantorWorksheetView(CantorWorksheet* worksheet) : QWidget(),
0042     m_worksheet(worksheet) {
0043 
0044     auto* layout = new QHBoxLayout(this);
0045     layout->setContentsMargins(0, 0, 0, 0);
0046     m_part = worksheet->part();
0047     if (m_part) {
0048         layout->addWidget(m_part->widget());
0049         initActions();
0050         connect(m_worksheet, &CantorWorksheet::requestProjectContextMenu, this, &CantorWorksheetView::createContextMenu);
0051         connect(m_worksheet, &CantorWorksheet::statusChanged, this, &CantorWorksheetView::statusChanged);
0052     } else {
0053         QLabel* label = new QLabel(i18n("Failed to initialize %1", m_worksheet->backendName()));
0054         label->setAlignment(Qt::AlignHCenter);
0055         layout->addWidget(label);
0056     }
0057 }
0058 
0059 void CantorWorksheetView::initActions() {
0060     auto* cantorActionGroup = new QActionGroup(this);
0061     cantorActionGroup->setExclusive(false);
0062 
0063     m_restartBackendAction = new QAction(QIcon::fromTheme("system-reboot"), i18n("Restart Backend"), cantorActionGroup);
0064     m_restartBackendAction->setData("restart_backend");
0065 
0066     m_evaluateWorsheetAction = new QAction(QIcon::fromTheme("system-run"), i18n("Evaluate Worksheet"), cantorActionGroup);
0067     m_evaluateWorsheetAction->setData("evaluate_worksheet");
0068 
0069     m_evaluateEntryAction = new QAction(QIcon::fromTheme(QLatin1String("media-playback-start")), i18n("Evaluate Entry"), cantorActionGroup);
0070     m_evaluateEntryAction->setShortcut(Qt::SHIFT + Qt::Key_Return);
0071     m_evaluateEntryAction->setData("evaluate_current");
0072 
0073     m_insertCommandEntryAction = new QAction(QIcon::fromTheme(QLatin1String("run-build")), i18n("Insert Command Entry"), cantorActionGroup);
0074     m_insertCommandEntryAction->setData("insert_command_entry");
0075     m_insertCommandEntryAction->setShortcut(Qt::CTRL + Qt::Key_Return);
0076 
0077     m_insertTextEntryAction = new QAction(QIcon::fromTheme(QLatin1String("draw-text")), i18n("Insert Text Entry"), cantorActionGroup);
0078     m_insertTextEntryAction->setData("insert_text_entry");
0079 
0080     //markdown entry is only available if cantor was compiled with libdiscovery (cantor 18.12 and later)
0081     if (m_part->action("insert_markdown_entry")) {
0082         m_insertTextEntryAction = new QAction(QIcon::fromTheme(QLatin1String("text-x-markdown")), i18n("Insert Markdown Entry"), cantorActionGroup);
0083         m_insertTextEntryAction->setData("insert_markdown_entry");
0084     }
0085 
0086     m_insertLatexEntryAction = new QAction(QIcon::fromTheme(QLatin1String("text-x-tex")), i18n("Insert LaTeX Entry"), cantorActionGroup);
0087     m_insertLatexEntryAction->setData("insert_latex_entry");
0088 
0089     m_insertPageBreakAction = new QAction(QIcon::fromTheme(QLatin1String("go-next-view-page")), i18n("Insert Page Break"), cantorActionGroup);
0090     m_insertPageBreakAction->setData("insert_page_break_entry");
0091 
0092     m_removeCurrentEntryAction = new QAction(QIcon::fromTheme(QLatin1String("edit-delete")), i18n("Remove Current Entry"), cantorActionGroup);
0093     m_removeCurrentEntryAction->setData("remove_current");
0094 
0095     m_zoomIn = new QAction(QIcon::fromTheme(QLatin1String("zoom-in")), i18n("Zoom In"), cantorActionGroup);
0096     m_zoomIn->setData("view_zoom_in");
0097     m_zoomIn->setShortcut(Qt::CTRL+Qt::Key_Plus);
0098 
0099     m_zoomOut = new QAction(QIcon::fromTheme(QLatin1String("zoom-out")), i18n("Zoom Out"), cantorActionGroup);
0100     m_zoomOut->setData("view_zoom_out");
0101     m_zoomOut->setShortcut(Qt::CTRL+Qt::Key_Minus);
0102 
0103     m_find = new QAction(QIcon::fromTheme(QLatin1String("edit-find")), i18n("Find"), cantorActionGroup);
0104     m_find->setData("edit_find");
0105     m_find->setShortcut(Qt::CTRL+Qt::Key_F);
0106 
0107     m_replace = new QAction(QIcon::fromTheme(QLatin1String("edit-find-replace")), i18n("Replace"), cantorActionGroup);
0108     m_replace->setData("edit_replace");
0109     m_replace->setShortcut(Qt::CTRL+Qt::Key_R);
0110 
0111     m_lineNumbers = new KToggleAction(i18n("Line Numbers"), cantorActionGroup);
0112     m_lineNumbers->setChecked(false);
0113     m_lineNumbers->setData("enable_expression_numbers");
0114 
0115     m_animateWorksheet = new KToggleAction(i18n("Animate Worksheet"), cantorActionGroup);
0116     m_animateWorksheet->setChecked(true);
0117     m_animateWorksheet->setData("enable_animations");
0118 
0119     m_latexTypesetting = new KToggleAction(i18n("LaTeX Typesetting"), cantorActionGroup);
0120     m_latexTypesetting->setChecked(true);
0121     m_latexTypesetting->setData("enable_typesetting");
0122 
0123     m_showCompletion = new QAction(i18n("Syntax Completion"), cantorActionGroup);
0124     m_showCompletion->setShortcut(Qt::CTRL + Qt::Key_Space);
0125     m_showCompletion->setData("show_completion");
0126 
0127     //actions, that are CAS-backend specific and not always available
0128     if (m_part->action("eigenvectors_assistant")) {
0129         m_computeEigenvectorsAction = new QAction(i18n("Compute Eigenvectors"), cantorActionGroup);
0130         m_computeEigenvectorsAction->setData("eigenvectors_assistant");
0131     }
0132 
0133     if (m_part->action("creatematrix_assistant")) {
0134         m_createMatrixAction = new QAction(i18n("Create Matrix"), cantorActionGroup);
0135         m_createMatrixAction->setData("creatematrix_assistant");
0136     }
0137 
0138     if (m_part->action("eigenvalues_assistant")) {
0139         m_computeEigenvaluesAction = new QAction(i18n("Compute Eigenvalues"), cantorActionGroup);
0140         m_computeEigenvaluesAction->setData("eigenvalues_assistant");
0141     }
0142 
0143     if (m_part->action("invertmatrix_assistant")) {
0144         m_invertMatrixAction = new QAction(i18n("Invert Matrix"), cantorActionGroup);
0145         m_invertMatrixAction->setData("invertmatrix_assistant");
0146     }
0147 
0148     if (m_part->action("differentiate_assistant")) {
0149         m_differentiationAction = new QAction(i18n("Differentiation"), cantorActionGroup);
0150         m_differentiationAction->setData("differentiate_assistant");
0151     }
0152 
0153     if (m_part->action("integrate_assistant")) {
0154         m_integrationAction = new QAction(i18n("Integration"), cantorActionGroup);
0155         m_integrationAction->setData("integrate_assistant");
0156     }
0157 
0158     if (m_part->action("solve_assistant")) {
0159         m_solveEquationsAction = new QAction(i18n("Solve Equations"), cantorActionGroup);
0160         m_solveEquationsAction->setData("solve_assistant");
0161     }
0162 
0163     connect(cantorActionGroup, &QActionGroup::triggered, this, &CantorWorksheetView::triggerCantorAction);
0164 }
0165 
0166 void CantorWorksheetView::initMenus() {
0167     m_worksheetMenu = new QMenu(i18n("Worksheet"), m_part->widget());
0168     m_worksheetMenu->addAction(m_evaluateWorsheetAction);
0169     m_worksheetMenu->addSeparator();
0170     m_worksheetMenu->addAction(m_evaluateEntryAction);
0171     m_worksheetMenu->addAction(m_insertCommandEntryAction);
0172     m_worksheetMenu->addAction(m_insertTextEntryAction);
0173     if (m_insertMarkdownEntryAction)
0174         m_worksheetMenu->addAction(m_insertMarkdownEntryAction);
0175     m_worksheetMenu->addAction(m_insertLatexEntryAction);
0176     m_worksheetMenu->addAction(m_insertPageBreakAction);
0177     m_worksheetMenu->addSeparator();
0178     m_worksheetMenu->addAction(m_removeCurrentEntryAction);
0179 
0180     if (m_invertMatrixAction || m_createMatrixAction || m_computeEigenvectorsAction || m_computeEigenvaluesAction) {
0181         m_linearAlgebraMenu = new QMenu("Linear Algebra", m_part->widget());
0182         if (m_invertMatrixAction)
0183             m_linearAlgebraMenu->addAction(m_invertMatrixAction);
0184         if (m_createMatrixAction)
0185             m_linearAlgebraMenu->addAction(m_createMatrixAction);
0186         if (m_computeEigenvectorsAction)
0187             m_linearAlgebraMenu->addAction(m_computeEigenvectorsAction);
0188         if (m_computeEigenvaluesAction)
0189             m_linearAlgebraMenu->addAction(m_computeEigenvaluesAction);
0190     }
0191 
0192     if (m_solveEquationsAction || m_integrationAction || m_differentiationAction) {
0193         m_calculateMenu = new QMenu(i18n("Calculate"), m_part->widget());
0194         if (m_solveEquationsAction)
0195             m_calculateMenu->addAction(m_solveEquationsAction);
0196         if (m_integrationAction)
0197             m_calculateMenu->addAction(m_integrationAction);
0198         if (m_differentiationAction)
0199             m_calculateMenu->addAction(m_differentiationAction);
0200     }
0201 
0202     m_settingsMenu = new QMenu(i18n("Settings"), m_part->widget());
0203     m_settingsMenu->setIcon(QIcon::fromTheme(QLatin1String("settings-configure")));
0204     m_settingsMenu->addAction(m_lineNumbers);
0205     m_settingsMenu->addAction(m_animateWorksheet);
0206     m_settingsMenu->addAction(m_latexTypesetting);
0207     m_settingsMenu->addAction(m_showCompletion);
0208 }
0209 
0210 /*!
0211  * Populates the menu \c menu with the CantorWorksheet and CantorWorksheet view relevant actions.
0212  * The menu is used
0213  *   - as the context menu in CantorWorksheetView
0214  *   - as the "CantorWorksheet menu" in the main menu-bar (called form MainWin)
0215  *   - as a part of the CantorWorksheet context menu in project explorer
0216  */
0217 void CantorWorksheetView::createContextMenu(QMenu* menu) {
0218     Q_ASSERT(menu);
0219     if (!m_part)
0220         return;
0221 
0222     QAction* firstAction = nullptr;
0223     // if we're populating the context menu for the project explorer, then
0224     //there're already actions available there. Skip the first title-action
0225     //and insert the action at the beginning of the menu.
0226     if (menu->actions().size()>1)
0227         firstAction = menu->actions().at(1);
0228 
0229     if (!m_worksheetMenu)
0230         initMenus();
0231 
0232     menu->insertMenu(firstAction, m_worksheetMenu);
0233     if (m_linearAlgebraMenu)
0234         menu->insertMenu(firstAction, m_linearAlgebraMenu);
0235     if (m_calculateMenu)
0236         menu->insertMenu(firstAction, m_calculateMenu);
0237     menu->insertSeparator(firstAction);
0238     menu->insertAction(firstAction, m_zoomIn);
0239     menu->insertAction(firstAction, m_zoomOut);
0240     menu->insertSeparator(firstAction);
0241     menu->insertAction(firstAction, m_find);
0242     menu->insertAction(firstAction, m_replace);
0243     menu->insertSeparator(firstAction);
0244     menu->insertMenu(firstAction, m_settingsMenu);
0245     menu->insertSeparator(firstAction);
0246     menu->insertAction(firstAction, m_restartBackendAction);
0247     menu->insertSeparator(firstAction);
0248 }
0249 
0250 void CantorWorksheetView::fillToolBar(QToolBar* toolbar) {
0251     if (!m_part)
0252         return;
0253     toolbar->addAction(m_restartBackendAction);
0254     toolbar->addAction(m_evaluateWorsheetAction);
0255 }
0256 
0257 /*!
0258  * Slot for actions triggered
0259  */
0260 void CantorWorksheetView::triggerCantorAction(QAction* action) {
0261     QString actionName = action->data().toString();
0262     if (!actionName.isEmpty()) m_part->action(actionName.toStdString().c_str())->trigger();
0263 }
0264 
0265 CantorWorksheetView::~CantorWorksheetView() {
0266     if (m_part)
0267         m_part->widget()->setParent(nullptr);
0268 }
0269 
0270 void CantorWorksheetView::statusChanged(Cantor::Session::Status status) {
0271     if (status == Cantor::Session::Running) {
0272         m_evaluateWorsheetAction->setText(i18n("Interrupt"));
0273         m_evaluateWorsheetAction->setIcon(QIcon::fromTheme(QLatin1String("dialog-close")));
0274         emit m_worksheet->statusInfo(i18n("Calculating..."));
0275     } else {
0276         m_evaluateWorsheetAction->setText(i18n("Evaluate Worksheet"));
0277         m_evaluateWorsheetAction->setIcon(QIcon::fromTheme(QLatin1String("system-run")));
0278         emit m_worksheet->statusInfo(i18n("Ready"));
0279     }
0280 }