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

0001 /*
0002     SPDX-License-Identifier: GPL-2.0-or-later
0003     SPDX-FileCopyrightText: 2009 Alexander Rieder <alexanderrieder@gmail.com>
0004 */
0005 
0006 #ifndef _EXTENSION_H
0007 #define _EXTENSION_H
0008 
0009 #include <QObject>
0010 #include <QPair>
0011 #include <QVector>
0012 #include <QDebug>
0013 #include <QWidget>
0014 #include "cantor_export.h"
0015 
0016 namespace Cantor
0017 {
0018 /**
0019  * This is the base class for all Extensions.
0020  * An Extension provides a set of Methods to
0021  * accomplish specific tasks. This is used to
0022  * abstract away the backends syntax for common
0023  * tasks like solving equations etc. to be able
0024  * to provide Backend independent Dialogs
0025  *
0026  * @author Alexander Rieder
0027  */
0028 class CANTOR_EXPORT Extension : public QObject
0029 {
0030   Q_OBJECT
0031   public:
0032     ///Default constructor
0033     Extension( const QString& name, QObject* parent );
0034     ~Extension() override = default;
0035 };
0036 
0037 
0038 //Some basic interfaces for extensions
0039 
0040 /**
0041  * An Extension providing commands for command history
0042  */
0043 class CANTOR_EXPORT HistoryExtension : public Extension
0044 {
0045   Q_OBJECT
0046   public:
0047     explicit HistoryExtension(QObject* parent);
0048     ~HistoryExtension() override;
0049   public Q_SLOTS:
0050     /**
0051      * Returns a command that retrieves the last result
0052      * @return command that retrieves the last result
0053      */
0054     virtual QString lastResult() = 0;
0055 };
0056 
0057 /**
0058  * An Extension providing commands to interact
0059  * with external scripts
0060  */
0061 class CANTOR_EXPORT ScriptExtension : public Extension
0062 {
0063   Q_OBJECT
0064   public:
0065     explicit ScriptExtension(QObject* parent);
0066     ~ScriptExtension() override;
0067   public Q_SLOTS:
0068     /**
0069      * returns the command for running a script
0070      * @param path path to the script file
0071      * @return command for running a script
0072      */
0073     virtual QString runExternalScript(const QString& path) = 0;
0074     /**
0075      * returns the file filter used for Script Files (e.g. *.py)
0076      * @return file filter used for Script Files (e.g. *.py)
0077      */
0078     virtual QString scriptFileFilter() = 0;
0079     /**
0080      * returns the name of the language to use for syntax highlighting
0081      * in the script editor (e.g. python). The value returned must match
0082      * the name attribute from the xml language description in KTexteditor.
0083      * @return name of the language to use for syntax highlighting (e.g. python)
0084      */
0085     virtual QString highlightingMode() = 0;
0086     /**
0087      * returns a string used to separate commands (usually ;)
0088      * @return a string used to separate commands (usually ;)
0089      */
0090     virtual QString commandSeparator();
0091     /**
0092      * returns a string used to start a comment (usually #)
0093      * @return a string used to start a comment (usually #)
0094      */
0095     virtual QString commentStartingSequence();
0096     /**
0097      * returns a string used to end a comment (usually "")
0098      * @return a string used to end a comment (usually "")
0099      */
0100     virtual QString commentEndingSequence();
0101 };
0102 
0103 /**
0104  * An extension providing the basic computations
0105  * in computer algebra, like solving, simplifying
0106  * etc
0107 **/
0108 class CANTOR_EXPORT CASExtension : public Extension
0109 {
0110   Q_OBJECT
0111   public:
0112     explicit CASExtension(QObject* parent);
0113     ~CASExtension() override;
0114 
0115   public Q_SLOTS:
0116     /**
0117      * returns the command for solving a set of equations
0118      * @param equations a list of equations
0119      * @param variables a list of variables that should be solved for
0120      * @return command for solving a set of equations
0121      */
0122     virtual QString solve(const QStringList& equations, const QStringList& variables) = 0;
0123     /**
0124      * returns the command for simplifying an expression
0125      * @param expression the expression that should be simplified
0126      * @return command for simplifying the expression
0127      */
0128     virtual QString simplify(const QString& expression) = 0;
0129     /**
0130      * returns the command for expanding an expression
0131      * @param expression the expression that should be expanded
0132      * @return command for expanded the expression
0133      */
0134     virtual QString expand(const QString& expression) = 0;
0135 };
0136 
0137 /**
0138  * An extension providing the basic calculus
0139  * stuff like limits, differentiate, integrate etc.
0140  */
0141 class CANTOR_EXPORT CalculusExtension : public Extension
0142 {
0143   Q_OBJECT
0144   public:
0145     explicit CalculusExtension(QObject* parent);
0146     ~CalculusExtension() override;
0147 
0148   public Q_SLOTS:
0149     /**
0150      * returns the command for calculating a limit if an expression
0151      * @param expression the expression
0152      * @param variable the variable
0153      * @param limit the value, the variable approaches
0154      * @return the limit of the expression
0155      */
0156     virtual QString limit(const QString& expression, const QString& variable, const QString& limit) = 0;
0157     /**
0158      * returns the command for calculating a differential
0159      * @param function the function
0160      * @param variable the variable, after which should be differentiated
0161      * @param times how often should be differentiated
0162      * @return the command to compute the differential
0163      */
0164     virtual QString differentiate(const QString& function,const QString& variable, int times) = 0;
0165     /**
0166      * returns the command for calculating an integral
0167      * @param function the function
0168      * @param variable the variable, after which should be integrated
0169      * @return the command to compute the integrate
0170      */
0171     virtual QString integrate(const QString& function, const QString& variable) = 0;
0172     /**
0173      * returns the command for calculating a definite integral
0174      * @param function the function
0175      * @param variable the variable, after which should be integrated
0176      * @param left the left border of the integral
0177      * @param right the right border of the integral
0178      * @return the command to compute the integrate
0179      */
0180     virtual QString integrate(const QString& function,const QString& variable, const QString& left, const QString& right) = 0;
0181 };
0182 
0183 /**
0184  * An extension providing basic plotting facilities
0185  */
0186 class CANTOR_EXPORT PlotExtension : public Extension
0187 {
0188   Q_OBJECT
0189   public:
0190     typedef QPair<QString,QString> Interval;
0191     typedef QPair<QString, Interval> VariableParameter;
0192 
0193     explicit PlotExtension(QObject* parent);
0194     ~PlotExtension() override;
0195 
0196   public Q_SLOTS:
0197     /**
0198      * returns the command for plotting a 2 dimensional function.
0199      * @param function the function to plot
0200      * @param variable the variable
0201      * @param left the left border of the plot
0202      * @param right the right border of the plot
0203      * @return the command for plotting
0204      */
0205     virtual QString plotFunction2d(const QString& function, const QString& variable, const QString& left, const QString& right) = 0;
0206     /**
0207      * returns the command for plotting a 3 dimensional function.
0208      * @param function the function to plot
0209      * @param var1 the parameters for Variable1 (name, interval)
0210      * @param var2 the parameters for Variable2 (name, interval)
0211      * @return the command for plotting
0212      */
0213     virtual QString plotFunction3d(const QString& function, const VariableParameter& var1, const VariableParameter& var2) = 0;
0214 };
0215 
0216 #define PLOT_DIRECTIVE_DISPATCHING(x) QString dispatch(const Cantor::AdvancedPlotExtension::AcceptorBase& acc) const \
0217   { \
0218     const Cantor::AdvancedPlotExtension::DirectiveAcceptor<x>* adaptor= \
0219         dynamic_cast<const Cantor::AdvancedPlotExtension::DirectiveAcceptor<x>*>(&acc); \
0220     if (adaptor==NULL) { qDebug()<<"Backend incapable of processing directives of type "#x;  return QLatin1String(""); } \
0221     else \
0222         return adaptor->accept(*this); \
0223  }
0224 
0225 /**
0226  * An extension providing advanced plotting facilities. Will supersede PlotExtension
0227  */
0228 class CANTOR_EXPORT AdvancedPlotExtension : public Extension
0229 {
0230   Q_OBJECT
0231   public:
0232     explicit AdvancedPlotExtension(QObject* parent);
0233     ~AdvancedPlotExtension() override;
0234 
0235     // TODO comment
0236 
0237     class PlotDirective;
0238 
0239     // TODO move the hell out of here
0240     class CANTOR_EXPORT DirectiveProducer : public QWidget
0241     {
0242         public:
0243             explicit DirectiveProducer(QWidget* parent);
0244             virtual PlotDirective* produceDirective() const=0;
0245     };
0246 
0247     template <class UI> class DirectiveControl : protected UI, public DirectiveProducer
0248     {
0249         public:
0250             DirectiveControl(QWidget* parent) : DirectiveProducer(parent) { UI::setupUi(this); }
0251         protected:
0252             using AbstractParent = DirectiveControl<UI>;
0253     };
0254 
0255     class CANTOR_EXPORT AcceptorBase
0256     {
0257         public:
0258             /**
0259              * utilitary typename for easing the code
0260              */
0261             using widgetProc = DirectiveProducer *(*)(QWidget *);
0262 
0263             /**
0264              * returns a constant reference to the list of widget generating procedures
0265              * which contains means of creating all the widgets a backend knows how to process
0266              * @return the constant reference to a QVector of QWidget* (*)(QWidget*) pointers
0267              */
0268             const QVector<widgetProc>& widgets() const;
0269 
0270         protected:
0271             /**
0272              * constructor only allowed for derived classes
0273              **/
0274             AcceptorBase();
0275             virtual ~AcceptorBase() = default;
0276 
0277             QVector<widgetProc> m_widgets;
0278     };
0279 
0280     template <class Directive> class DirectiveAcceptor : virtual public AcceptorBase
0281     {
0282 
0283         public:
0284             /**
0285              * virtual interface to acceptor function mechanics
0286              * @param directive the directive to process
0287              * @return the parameter corresponding the directive
0288              */
0289             virtual QString accept(const Directive& directive) const=0;
0290 
0291         protected:
0292             /**
0293              * constructor only allowed for derived classes
0294              **/
0295             DirectiveAcceptor();
0296     };
0297 
0298     class CANTOR_EXPORT PlotDirective
0299     {
0300         public:
0301             virtual ~PlotDirective() = default;
0302 
0303             /**
0304              * creates a new widget for editing the value and returns the pointer to it
0305              * @param parent the pointer to parent widget passed to newly created widget
0306              * @return pointer to the newly-created widget
0307              */
0308             static QWidget* widget(QWidget* parent);
0309 
0310             /**
0311              * in order to make dual dispatching this should be present in any derived class
0312              * without virtual keyword and with correct class name
0313              **/
0314             virtual PLOT_DIRECTIVE_DISPATCHING(PlotDirective);
0315             // TODO: find a workaround not to put class names manually
0316 
0317         protected:
0318             /**
0319              * only derived classes may construct
0320              **/
0321             PlotDirective() = default;
0322     };
0323 
0324   public Q_SLOTS:
0325     /**
0326      * returns the command for plotting a 2 dimensional data set.
0327      * @param expression the expression to plot
0328      * @param directives the array of directives toward the generator
0329      * @return the command for plotting
0330      */
0331     QString plotFunction2d(const QString& expression, const QVector<Cantor::AdvancedPlotExtension::PlotDirective*>& directives) const;
0332 
0333     /**
0334      * returns the parameter expression according to a directive.
0335      * @param directive the directive toward the generator
0336      * @return the parameter for plotting
0337      */
0338     QString dispatchDirective(const Cantor::AdvancedPlotExtension::PlotDirective& directive) const;
0339 
0340   protected:
0341     /**
0342      * returns the command name for plotting a 2 dimensional data set.
0343      * @return the command for plotting
0344      */
0345     virtual QString plotCommand() const=0;
0346     /**
0347      * returns the separator symbol in a plotting command.
0348      * @return the separator symbol or string
0349      */
0350     virtual QString separatorSymbol() const;
0351 };
0352 
0353 template <class Directive> AdvancedPlotExtension::DirectiveAcceptor<Directive>::DirectiveAcceptor()
0354 {
0355     m_widgets.push_back(&Directive::widget);
0356 }
0357 
0358 /**
0359  * An extension for basic Linear Algebra
0360  */
0361 class CANTOR_EXPORT LinearAlgebraExtension : public Extension
0362 {
0363   Q_OBJECT
0364   public:
0365     enum VectorType { ColumnVector, RowVector };
0366     using Matrix = QList<QStringList>;
0367 
0368     explicit LinearAlgebraExtension(QObject* parent);
0369     ~LinearAlgebraExtension() override;
0370 
0371   public Q_SLOTS:
0372     //Commands to create Vectors/Matrices
0373     /**
0374      * creates a vector with the given entries
0375      * @param entries the entries of the new vector
0376      * @param type the type of the vector (row/column)
0377      * @return the command for creating the vector
0378      */
0379     virtual QString createVector(const QStringList& entries, Cantor::LinearAlgebraExtension::VectorType type) = 0;
0380     /**
0381      * creates a null vector, of the given size/type
0382      * @param size size of the vector
0383      * @param type type of the vector
0384      * @return the command used for creating a nullvector
0385      **/
0386     virtual QString nullVector(int size, Cantor::LinearAlgebraExtension::VectorType type);
0387     /**
0388      * creates a matrix with the given entries
0389      * @param matrix the entries of the matrix
0390      * @return the command to create this matrix
0391      */
0392     virtual QString createMatrix(const Matrix& matrix) = 0;
0393     /**
0394      * creates an identity matrix of the given size
0395      * @param size size of the matrix
0396      * @return the command used to create the matrix
0397      */
0398     virtual QString identityMatrix(int size);
0399     /**
0400      * creates a null matrix, of the given size
0401      * @param rows number of rows
0402      * @param columns number of columns
0403      * @return the command to create this matrix
0404      */
0405     virtual QString nullMatrix(int rows,int columns);
0406 
0407     //basic functions
0408     /**
0409      * compute the rank of a matrix
0410      * @param matrix the name of the matrix, the rank should be computed of
0411      * @return the command for calculating the rank
0412      */
0413     virtual QString rank(const QString& matrix) = 0;
0414     /**
0415      * invert a given matrix
0416      * @param matrix the name of the matrix, that should be inverted
0417      * @return the command for inverting the matrix
0418      */
0419     virtual QString invertMatrix(const QString& matrix) = 0;
0420     /**
0421      * calculate the characteristic polynom of a matrix
0422      * @param matrix the name of the matrix, the charpoly should be computed of
0423      * @return the command
0424      */
0425     virtual QString charPoly(const QString& matrix) = 0;
0426     /**
0427      * calculate the eigen vectors of a matrix
0428      * @param matrix the name of the matrix, the eigenvectors should be computed of
0429      * @return the command
0430      */
0431     virtual QString eigenVectors(const QString& matrix) = 0;
0432     /**
0433      * calculate the eigen values of a matrix
0434      * @param matrix the name of the matrix, the eigenvalues should be computed of
0435      * @return the command
0436      */
0437     virtual QString eigenValues(const QString& matrix) = 0;
0438 
0439 };
0440 
0441 class CANTOR_EXPORT VariableManagementExtension : public Extension
0442 {
0443   Q_OBJECT
0444   public:
0445     explicit VariableManagementExtension( QObject* parent );
0446     ~VariableManagementExtension() override;
0447 
0448   public Q_SLOTS:
0449     virtual QString addVariable(const QString& name, const QString& value) = 0;
0450     virtual QString setValue(const QString& name,const QString& value) = 0;
0451     virtual QString removeVariable(const QString& name) = 0;
0452 
0453     virtual QString saveVariables(const QString& fileName) = 0;
0454     virtual QString loadVariables(const QString& fileName) = 0;
0455     virtual QString clearVariables() = 0;
0456 };
0457 
0458 /**
0459  * An extension for library/module import
0460  */
0461 class CANTOR_EXPORT PackagingExtension : public Extension
0462 {
0463   Q_OBJECT
0464   public:
0465     explicit PackagingExtension(QObject* parent);
0466     ~PackagingExtension() override;
0467 
0468   public Q_SLOTS:
0469     /**
0470      * import library/module
0471      * @param package the library/module name
0472      * @return the command for import library/module
0473      */
0474     virtual QString importPackage(const QString& package) = 0;
0475 };
0476 
0477 }
0478 #endif /* _EXTENSION_H */