File indexing completed on 2024-04-28 11:20:48

0001 /*
0002     SPDX-License-Identifier: GPL-2.0-or-later
0003     SPDX-FileCopyrightText: 2009 Alexander Rieder <alexanderrieder@gmail.com>
0004 */
0005 
0006 #ifndef _SESSION_H
0007 #define _SESSION_H
0008 
0009 #include <QObject>
0010 #include <QStandardPaths>
0011 
0012 #include "cantor_export.h"
0013 
0014 #include "expression.h"
0015 #include "defaultvariablemodel.h"
0016 #include "graphicpackage.h"
0017 
0018 class QTextEdit;
0019 class QSyntaxHighlighter;
0020 class QAbstractItemModel;
0021 
0022 /**
0023  * Namespace collecting all Classes of the Cantor Libraries
0024  */
0025 namespace Cantor
0026 {
0027 class Backend;
0028 class SessionPrivate;
0029 class CompletionObject;
0030 class SyntaxHelpObject;
0031 class DefaultVariableModel;
0032 
0033 /**
0034  * The Session object is the main class used to interact with a Backend.
0035  * It is used to evaluate Expressions, get completions, syntax highlighting, etc.
0036  *
0037  * @author Alexander Rieder
0038  */
0039 class CANTOR_EXPORT Session : public QObject
0040 {
0041   Q_OBJECT
0042   public:
0043     enum Status {
0044       Running, ///< the session is busy, running some expression
0045       Done,    ///< the session has done all the jobs, and is now waiting for more
0046       Disable  ///< the session don't login yet, or already logout
0047     };
0048 
0049     /**
0050      * Create a new Session. This should not yet set up the complete session,
0051      * thats job of the login() function
0052      * @see login()
0053      */
0054     explicit Session(Backend*);
0055 
0056     /**
0057      * Similar to Session::Session, but also specify variable model for automatically handles model's updates
0058      */
0059     explicit Session(Backend*, DefaultVariableModel*);
0060 
0061     /**
0062      * Destructor
0063      */
0064     ~Session() override;
0065 
0066     /**
0067      * Login to the Session. In this function you should do anything needed to set up
0068      * the session, and make it ready for usage. The method should be implemented non-blocking.
0069      * Emit loginStarted() prior to connection to the actual backend in order to notify cantor_part about it.
0070      * If the logging in is completed, the loginDone() signal must be emitted
0071      */
0072     virtual void login() = 0;
0073     /**
0074      * Log out of the Session. Destroy everything specific to a single session, e.g.
0075      * stop all the running processes etc. Also after logout session status must be Status::Disable
0076      * Default implementation does basic operations for all sessions (for example, variable model cleanup)
0077      * NOTE: restarting the session consists of first logout() and then login()
0078      */
0079     virtual void logout();
0080 
0081     /**
0082     * This method run precense test for available graphic packages. The packages, which will sucessfuly pass the test
0083     * will go to @c usableGraphicPackages list
0084     * @param targetPackage If set, precense test will run only for this package. If empty string, then all available packages will be tested
0085     */
0086     void testGraphicsPackages(QList<GraphicPackage> packages);
0087 
0088     /**
0089      * Passes the given command to the backend and returns a Pointer
0090      * to a new Expression object, which will emit the gotResult()
0091      * signal as soon as the computation is done. The result will
0092      * then be accessible by Expression::result()
0093      * @param command the command that should be run by the backend.
0094      * @param finishingBehavior the FinishingBehaviour that should be used for this command. @see Expression::FinishingBehaviour
0095      * @param internal true, if it is an internal command @see Expression::Expression(Session*, bool)
0096      * @return an Expression object, representing this command
0097      */
0098     virtual Expression* evaluateExpression(const QString& command, Expression::FinishingBehavior finishingBehavior = Expression::FinishingBehavior::DoNotDelete, bool internal = false) = 0;
0099 
0100     /**
0101      * Append the expression to queue .
0102      * @see expressionQueue() const
0103      */
0104     void enqueueExpression(Expression*);
0105 
0106     /**
0107      * Interrupts all the running calculations in this session
0108      * After this function expression queue must be clean
0109      */
0110     virtual void interrupt() = 0;
0111 
0112     /**
0113      * Returns tab-completion, for this command/command-part.
0114      * The return type is a CompletionObject. The fetching
0115      * of the completions works asynchronously, you'll have to
0116      * listen to the done() Signal of the returned object
0117      * @param cmd The partial command that should be completed
0118      * @param index The index (cursor position) at which completion
0119      * was invoked. Defaults to -1, indicating the end of the string.
0120      * @return a Completion object, representing this completion
0121      * @see CompletionObject
0122      */
0123     virtual CompletionObject* completionFor(const QString& cmd, int index = -1);
0124 
0125     /**
0126      * Returns Syntax help, for this command.
0127      * It returns a SyntaxHelpObject, that will fetch the
0128      * needed information asynchronously. You need to listen
0129      * to the done() Signal of the Object
0130      * @param cmd the command, syntax help is requested for
0131      * @return SyntaxHelpObject, representing the help request
0132      * @see SyntaxHelpObject
0133      */
0134     virtual SyntaxHelpObject* syntaxHelpFor(const QString& cmd);
0135 
0136     /**
0137      * returns a syntax highlighter for this session
0138      * @param parent QObject the Highlighter's parent
0139      * @return QSyntaxHighlighter doing the highlighting for this Session
0140      */
0141     virtual QSyntaxHighlighter* syntaxHighlighter(QObject* parent);
0142 
0143     /**
0144      * returns a Model to interact with the variables or nullptr, if
0145      * this backend have a variable model, which not inherit from
0146      * default variable model class (in this case @see variableDataModel())
0147      * @return DefaultVariableModel to interact with the variables
0148      */
0149     virtual DefaultVariableModel* variableModel() const;
0150 
0151     /**
0152      * returns QAbstractItemModel to interact with the variables
0153      */
0154     virtual QAbstractItemModel* variableDataModel() const;
0155 
0156     /**
0157      * Enables/disables Typesetting for this session.
0158      * For this setting to make effect, the Backend must support
0159      * LaTeX typesetting (as indicated by the capabilities() flag.
0160      * @param enable true to enable, false to disable typesetting
0161      */
0162     virtual void setTypesettingEnabled(bool);
0163 
0164     /**
0165     * Updates the worksheet path in the session.
0166     * This can be useful to set the path of the currently opened
0167     * Cantor project file in the backend interpreter.
0168     * Default implementation does nothing. Derived classes have
0169     * to implement the proper logic if this feature is supported.
0170     * @param path the new absolute path to the worksheet.
0171     */
0172     virtual void setWorksheetPath(const QString&);
0173 
0174     /**
0175      * Returns the Backend, this Session is for
0176      * @return the Backend, this Session is for
0177      */
0178     Backend* backend();
0179 
0180     /**
0181      * Returns the status this Session has
0182      * @return the status this Session has
0183      */
0184     Cantor::Session::Status status();
0185     /**
0186      * Returns whether typesetting is enabled or not
0187      * @return whether typesetting is enabled or not
0188      */
0189     bool isTypesettingEnabled();
0190 
0191     /**
0192      * Returns the next available Expression id
0193      * It is basically a counter, incremented for
0194      * each new Expression
0195      * @return next Expression id
0196      */
0197     int nextExpressionId();
0198 
0199     /**
0200      * Return list all enabled (which precense in system and choosen for run by user) graphic packages
0201      * Can be empty.
0202      */
0203     const QList<GraphicPackage>& enabledGraphicPackages() const;
0204 
0205 public Q_SLOTS:
0206     void currentExpressionStatusChanged(Cantor::Expression::Status);
0207 
0208   protected:
0209     /**
0210      * Change the status of the Session. This will cause the
0211      * stausChanged signal to be emitted
0212      * @param newStatus the new status of the session
0213      */
0214     void changeStatus(Cantor::Session::Status);
0215 
0216     /**
0217      * Session can process one single expression at one time.
0218      * Any other expressions submitted by the user are queued first until they get processed.
0219      * The expression queue implements the FIFO mechanism.
0220      * The queud expression have the status \c Expression::Queued.
0221      */
0222     QList<Expression*>& expressionQueue() const;
0223 
0224     /**
0225      * Execute first expression in expression queue.
0226      * Also, this function changes the status from Queued to Computing.
0227      * @see expressionQueue() const
0228      */
0229     virtual void runFirstExpression();
0230 
0231     /**
0232      * This method dequeues the expression and goes to the next expression, if the queue is not empty.
0233      * Also, this method updates the variable model, if needed.
0234      * If the queue is empty, the session status is set to Done.
0235      * @param setDoneAfterUpdate enable setting status to Done after variable update, if queue is empty
0236      */
0237     virtual void finishFirstExpression(bool setDoneAfterUpdate = false);
0238 
0239     /**
0240      * Starts variable update immedeatly, useful for subclasses, which run internal command
0241      * which could change variables listen
0242      */
0243     virtual void updateVariables();
0244 
0245     /**
0246      * Setting variable model, useful if model constructor requires functional session
0247      */
0248     void setVariableModel(DefaultVariableModel*);
0249 
0250     /**
0251      * Search file for session in AppDataLocation and in GenericDataLocation
0252      */
0253     QString locateCantorFile(const QString& partialPath, QStandardPaths::LocateOptions options = QStandardPaths::LocateFile);
0254     QStringList locateAllCantorFiles(const QString& partialPath, QStandardPaths::LocateOptions options = QStandardPaths::LocateFile);
0255 
0256     /**
0257      * Sometimes backend process/server could crash, stop responding, in other words, session can't
0258      * continue to work without restart.
0259      * This method will notify about session crashing with automatically logout
0260      * and another actions, which needed to do in situations like that
0261      */
0262     void reportSessionCrash(const QString& additionalInfo = QString());
0263 
0264     /**
0265      * Contains list of usable (which available and can be enabled in current session) graphic packages
0266      */
0267     QList<GraphicPackage> usableGraphicPackages();
0268 
0269     void updateEnabledGraphicPackages(const QList<GraphicPackage>& newEnabledPackages, const QString& additionalInfo = QString());
0270 
0271     /**
0272      * This some hacky function.
0273      * There are messages for situation, when user try to use graphic package, but the package
0274      * can be enabled because of missing dependencies
0275      * information like this should be stored in graphic package scheme, but because the message should be translated,
0276      * the text stored here as i18n text constant.
0277      * This function allows get this message for particular package
0278      */
0279     virtual QString graphicPackageErrorMessage(QString packageId) const;
0280 
0281 Q_SIGNALS:
0282     void statusChanged(Cantor::Session::Status);
0283     void loginStarted();
0284     void loginDone();
0285     void error(const QString&);
0286 
0287   private:
0288     SessionPrivate* d;
0289 };
0290 }
0291 #endif /* _SESSION_H */