File indexing completed on 2024-04-28 11:21:03
0001 /* 0002 SPDX-License-Identifier: GPL-2.0-or-later 0003 SPDX-FileCopyrightText: 2009 Alexander Rieder <alexanderrieder@gmail.com> 0004 SPDX-FileCopyrightText: 2012 Martin Kuettler <martin.kuettler@gmail.com> 0005 SPDX-FileCopyrightText: 2017-2021 Alexander Semke <alexander.semke@web.de> 0006 */ 0007 0008 #ifndef WORKSHEET_H 0009 #define WORKSHEET_H 0010 0011 #include <QDomDocument> 0012 #include <QGraphicsScene> 0013 #include <QQueue> 0014 0015 #include "lib/renderer.h" 0016 #include "mathrender.h" 0017 #include "worksheetcursor.h" 0018 0019 namespace Cantor { 0020 class Backend; 0021 class Session; 0022 class Expression; 0023 } 0024 0025 class WorksheetEntry; 0026 class WorksheetView; 0027 class HierarchyEntry; 0028 class PlaceHolderEntry; 0029 class WorksheetTextItem; 0030 0031 class QAction; 0032 class QDrag; 0033 class QGraphicsObject; 0034 class QMenu; 0035 class QPrinter; 0036 class QSyntaxHighlighter; 0037 class KActionCollection; 0038 class KToggleAction; 0039 class KFontAction; 0040 class KFontSizeAction; 0041 class KZip; 0042 0043 class Worksheet : public QGraphicsScene 0044 { 0045 Q_OBJECT 0046 public: 0047 enum Type { 0048 CantorWorksheet, 0049 JupyterNotebook 0050 }; 0051 0052 Worksheet(Cantor::Backend*, QWidget*, bool useDeafultWorksheetParameters = true); 0053 ~Worksheet() override; 0054 0055 Cantor::Session* session(); 0056 0057 void loginToSession(); 0058 0059 bool isRunning(); 0060 bool isReadOnly(); 0061 bool showExpressionIds(); 0062 bool animationsEnabled(); 0063 bool embeddedMathEnabled(); 0064 0065 bool isPrinting(); 0066 0067 WorksheetView* worksheetView(); 0068 0069 void stopAnimations(); 0070 void resumeAnimations(); 0071 0072 void makeVisible(WorksheetEntry*); 0073 void makeVisible(const WorksheetCursor&); 0074 0075 void setModified(); 0076 0077 void startDrag(WorksheetEntry*, QDrag*); 0078 void startDragWithHierarchy(HierarchyEntry*, QDrag*, QSizeF responsibleZoneSize); 0079 0080 void setActionCollection(KActionCollection*); 0081 QMenu* createContextMenu(); 0082 void populateMenu(QMenu*, QPointF); 0083 Cantor::Renderer* renderer(); 0084 MathRenderer* mathRenderer(); 0085 bool isEmpty(); 0086 bool isLoadingFromFile(); 0087 0088 WorksheetEntry* currentEntry(); 0089 WorksheetEntry* firstEntry(); 0090 WorksheetEntry* lastEntry(); 0091 WorksheetTextItem* currentTextItem(); 0092 WorksheetTextItem* lastFocusedTextItem(); 0093 0094 WorksheetEntry* cutSubentriesForHierarchy(HierarchyEntry*); 0095 void insertSubentriesForHierarchy(HierarchyEntry*, WorksheetEntry*); 0096 0097 WorksheetCursor worksheetCursor(); 0098 void setWorksheetCursor(const WorksheetCursor&); 0099 0100 // For WorksheetEntry::startDrag 0101 void resetEntryCursor(); 0102 0103 /** 0104 * How it works: 0105 * There are two information streams 0106 * 1. WorksheetView -> Worksheet -> subelemenets (ex. entries) about view width 0107 * View width used by some sub elements for better visual appearance (for example, entries with text often are fitted to width of view). 0108 * 2. Subelements -> Worksheet 0109 * Sub elements notify Worksheet about their needed widths and worksheet, used this information, set proper scene size. 0110 */ 0111 /// First information stream 0112 void setViewSize(qreal w, qreal h, qreal s, bool forceUpdate = false); 0113 0114 /// Second information stream 0115 void setRequestedWidth(QGraphicsObject*, qreal width); 0116 void removeRequestedWidth(QGraphicsObject*); 0117 0118 bool isShortcut(const QKeySequence&); 0119 0120 void setType(Worksheet::Type); 0121 Worksheet::Type type() const; 0122 0123 void notifyEntryFocus(WorksheetEntry*); 0124 0125 // richtext 0126 struct RichTextInfo { 0127 bool bold; 0128 bool italic; 0129 bool underline; 0130 bool strikeOut; 0131 QString font; 0132 qreal fontSize; 0133 Qt::Alignment align; 0134 }; 0135 0136 public: 0137 static int typeForTagName(const QString&); 0138 0139 public Q_SLOTS: 0140 WorksheetEntry* appendCommandEntry(); 0141 void appendCommandEntry(const QString&); 0142 WorksheetEntry* appendTextEntry(); 0143 WorksheetEntry* appendMarkdownEntry(); 0144 WorksheetEntry* appendImageEntry(); 0145 WorksheetEntry* appendPageBreakEntry(); 0146 WorksheetEntry* appendLatexEntry(); 0147 WorksheetEntry* appendHorizontalRuleEntry(); 0148 WorksheetEntry* appendHierarchyEntry(); 0149 0150 WorksheetEntry* insertCommandEntry(WorksheetEntry* current = nullptr); 0151 WorksheetEntry* insertTextEntry(WorksheetEntry* current = nullptr); 0152 WorksheetEntry* insertMarkdownEntry(WorksheetEntry* current = nullptr); 0153 WorksheetEntry* insertImageEntry(WorksheetEntry* current = nullptr); 0154 WorksheetEntry* insertPageBreakEntry(WorksheetEntry* current = nullptr); 0155 WorksheetEntry* insertLatexEntry(WorksheetEntry* current = nullptr); 0156 WorksheetEntry* insertHorizontalRuleEntry(WorksheetEntry* current = nullptr); 0157 WorksheetEntry* insertHierarchyEntry(WorksheetEntry* current = nullptr); 0158 0159 WorksheetEntry* insertCommandEntryBefore(WorksheetEntry* current = nullptr); 0160 WorksheetEntry* insertTextEntryBefore(WorksheetEntry* current = nullptr); 0161 WorksheetEntry* insertMarkdownEntryBefore(WorksheetEntry* current = nullptr); 0162 WorksheetEntry* insertImageEntryBefore(WorksheetEntry* current = nullptr); 0163 WorksheetEntry* insertPageBreakEntryBefore(WorksheetEntry* current = nullptr); 0164 WorksheetEntry* insertLatexEntryBefore(WorksheetEntry* current = nullptr); 0165 WorksheetEntry* insertHorizontalRuleEntryBefore(WorksheetEntry* current = nullptr); 0166 WorksheetEntry* insertHierarchyEntryBefore(WorksheetEntry* current = nullptr); 0167 0168 void updateLayout(); 0169 void updateHierarchyLayout(); 0170 void updateHierarchyControlsLayout(WorksheetEntry* startEntry = nullptr); 0171 void updateEntrySize(WorksheetEntry*); 0172 0173 void print(QPrinter*); 0174 void paste(); 0175 void focusEntry(WorksheetEntry*); 0176 0177 void evaluate(); 0178 void evaluateCurrentEntry(); 0179 void interrupt(); 0180 void interruptCurrentEntryEvaluation(); 0181 0182 bool completionEnabled(); 0183 void showCompletion(); 0184 0185 void highlightItem(WorksheetTextItem*); 0186 void rehighlight(); 0187 0188 void enableHighlighting(bool); 0189 void enableCompletion(bool); 0190 void enableExpressionNumbering(bool); 0191 void enableAnimations(bool); 0192 void enableEmbeddedMath(bool); 0193 0194 QDomDocument toXML(KZip* archive = nullptr); 0195 0196 void save(const QString&); 0197 void save(QIODevice*); 0198 QByteArray saveToByteArray(); 0199 void savePlain(const QString&); 0200 void saveLatex(const QString&); 0201 bool load(QIODevice*); 0202 void load(QByteArray*); 0203 bool load(const QString&); 0204 0205 void gotResult(Cantor::Expression* expr = nullptr); 0206 0207 void removeCurrentEntry(); 0208 0209 void setFirstEntry(WorksheetEntry*); 0210 void setLastEntry(WorksheetEntry*); 0211 void invalidateFirstEntry(); 0212 void invalidateLastEntry(); 0213 0214 void updateFocusedTextItem(WorksheetTextItem*); 0215 0216 void updateDragScrollTimer(); 0217 0218 void registerShortcut(QAction*); 0219 void updateShortcut(); 0220 0221 // richtext 0222 void setRichTextInformation(const Worksheet::RichTextInfo&); 0223 void setAcceptRichText(bool b); 0224 0225 void setTextForegroundColor(); 0226 void setTextBackgroundColor(); 0227 void setTextBold(bool b); 0228 void setTextItalic(bool b); 0229 void setTextUnderline(bool b); 0230 void setTextStrikeOut(bool b); 0231 void setAlignLeft(); 0232 void setAlignRight(); 0233 void setAlignCenter(); 0234 void setAlignJustify(); 0235 void setFontFamily(const QString&); 0236 void setFontSize(int size); 0237 0238 void changeEntryType(WorksheetEntry* target, int newType); 0239 0240 void collapseSelectionResults(); 0241 void collapseAllResults(); 0242 void uncollapseSelectionResults(); 0243 void uncollapseAllResults(); 0244 void removeSelectionResults(); 0245 void removeAllResults(); 0246 void addToExectuionSelection(); 0247 void excludeFromExecutionSelection(); 0248 0249 void requestScrollToHierarchyEntry(QString); 0250 void handleSettingsChanges(); 0251 0252 Q_SIGNALS: 0253 void modified(); 0254 void loaded(); 0255 void showHelp(const QString&); 0256 void hierarchyChanged(QStringList, QStringList, QList<int>); 0257 void hierarhyEntryNameChange(QString name, QString searchName, int depth); 0258 void updatePrompt(); 0259 void undoAvailable(bool); 0260 void redoAvailable(bool); 0261 void undo(); 0262 void redo(); 0263 void cutAvailable(bool); 0264 void copyAvailable(bool); 0265 void pasteAvailable(bool); 0266 void cut(); 0267 void copy(); 0268 void requestDocumentation(const QString&); 0269 0270 protected: 0271 void contextMenuEvent(QGraphicsSceneContextMenuEvent*) override; 0272 void mousePressEvent(QGraphicsSceneMouseEvent*) override; 0273 0274 void dragEnterEvent(QGraphicsSceneDragDropEvent*) override; 0275 void dragLeaveEvent(QGraphicsSceneDragDropEvent*) override; 0276 void dragMoveEvent(QGraphicsSceneDragDropEvent*) override; 0277 void dropEvent(QGraphicsSceneDragDropEvent*) override; 0278 0279 void keyPressEvent(QKeyEvent*) override; 0280 0281 QJsonDocument toJupyterJson(); 0282 0283 bool isValidEntry(WorksheetEntry*); 0284 0285 private Q_SLOTS: 0286 //void checkEntriesForSanity(); 0287 0288 WorksheetEntry* appendEntry(int type, bool focus = true); 0289 WorksheetEntry* insertEntry(int type, WorksheetEntry* current = nullptr); 0290 WorksheetEntry* insertEntryBefore(int type, WorksheetEntry* current = nullptr); 0291 0292 //Actions for selection 0293 void selectionRemove(); 0294 void selectionEvaluate(); 0295 void selectionMoveUp(); 0296 void selectionMoveDown(); 0297 0298 void animateEntryCursor(); 0299 0300 private: 0301 WorksheetEntry* entryAt(qreal x, qreal y); 0302 WorksheetEntry* entryAt(QPointF); 0303 WorksheetEntry* entryAt(int row); 0304 void updateEntryCursor(QGraphicsSceneMouseEvent*); 0305 void addEntryFromEntryCursor(); 0306 void drawEntryCursor(); 0307 int entryCount(); 0308 bool loadCantorWorksheet(const KZip& archive); 0309 bool loadJupyterNotebook(const QJsonDocument& doc); 0310 void showInvalidNotebookSchemeError(QString additionalInfo = QString()); 0311 void initSession(Cantor::Backend*); 0312 void initActions(); 0313 std::vector<WorksheetEntry*> hierarchySubelements(HierarchyEntry*) const; 0314 0315 static const double LeftMargin; 0316 static const double RightMargin; 0317 static const double TopMargin; 0318 static const double EntryCursorLength; 0319 static const double EntryCursorWidth; 0320 0321 Cantor::Session* m_session{nullptr}; 0322 QSyntaxHighlighter* m_highlighter{nullptr}; 0323 Cantor::Renderer m_epsRenderer; 0324 MathRenderer m_mathRenderer; 0325 WorksheetEntry* m_firstEntry{nullptr}; 0326 WorksheetEntry* m_lastEntry{nullptr}; 0327 WorksheetEntry* m_dragEntry{nullptr}; 0328 std::vector<WorksheetEntry*> m_hierarchySubentriesDrag; 0329 QSizeF m_hierarchyDragSize; 0330 WorksheetEntry* m_choosenCursorEntry{nullptr}; 0331 bool m_isCursorEntryAfterLastEntry{false}; 0332 QTimer* m_cursorItemTimer; 0333 QGraphicsLineItem* m_entryCursorItem{nullptr}; 0334 PlaceHolderEntry* m_placeholderEntry{nullptr}; 0335 WorksheetTextItem* m_lastFocusedTextItem{nullptr}; 0336 QTimer* m_dragScrollTimer{nullptr}; 0337 0338 qreal m_viewWidth{0}; 0339 QMap<QGraphicsObject*, qreal> m_itemWidths; 0340 qreal m_maxWidth{0}; 0341 qreal m_maxPromptWidth{0}; 0342 0343 QMap<QKeySequence, QAction*> m_shortcuts; 0344 0345 KActionCollection* m_collection{nullptr}; 0346 QList<QAction *> m_richTextActionList; 0347 KToggleAction* m_boldAction{nullptr}; 0348 KToggleAction* m_italicAction{nullptr}; 0349 KToggleAction* m_underlineAction{nullptr}; 0350 KToggleAction* m_strikeOutAction{nullptr}; 0351 KFontAction* m_fontAction{nullptr}; 0352 KFontSizeAction* m_fontSizeAction{nullptr}; 0353 KToggleAction* m_alignLeftAction{nullptr}; 0354 KToggleAction* m_alignCenterAction{nullptr}; 0355 KToggleAction* m_alignRightAction{nullptr}; 0356 KToggleAction* m_alignJustifyAction{nullptr}; 0357 0358 bool m_useDefaultWorksheetParameters{true}; 0359 0360 bool m_completionEnabled{false}; 0361 bool m_embeddedMathEnabled{false}; 0362 bool m_showExpressionIds{false}; 0363 bool m_animationsEnabled{false}; 0364 0365 bool m_isPrinting{false}; 0366 bool m_isLoadingFromFile{false}; 0367 bool m_isClosing{false}; 0368 bool m_readOnly{false}; 0369 0370 Type m_type = CantorWorksheet; 0371 0372 QString m_backendName; 0373 QJsonObject* m_jupyterMetadata{nullptr}; 0374 0375 QVector<WorksheetEntry*> m_selectedEntries; 0376 QQueue<WorksheetEntry*> m_circularFocusBuffer; 0377 0378 size_t m_hierarchyMaxDepth{0}; 0379 }; 0380 0381 #endif // WORKSHEET_H