File indexing completed on 2024-04-28 17:06:31

0001 /*
0002     SPDX-FileCopyrightText: 2004 Jonas Bähr <jonas.baehr@web.de>
0003     SPDX-FileCopyrightText: 2004 Shie Erlich <erlich@users.sourceforge.net>
0004     SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #ifndef EXPANDER_H
0010 #define EXPANDER_H
0011 
0012 // QtCore
0013 #include <QList>
0014 #include <QString>
0015 #include <QStringList>
0016 
0017 #include "tstring.h"
0018 
0019 class KrPanel;
0020 class Expander;
0021 class Error;
0022 
0023 typedef TagString_t<QStringList> TagString;
0024 typedef QList<TagString> TagStringList;
0025 
0026 /**
0027  * This holds the information about each parameter
0028  */
0029 class exp_parameter
0030 {
0031 public:
0032     exp_parameter()
0033     {
0034     }
0035     inline exp_parameter(QString desc, QString pre, bool ness)
0036     {
0037         _description = desc;
0038         _preset = pre;
0039         _necessary = ness;
0040     }
0041     inline QString description() const
0042     { ///< A description of the parameter
0043         return _description;
0044     }
0045     inline QString preset() const
0046     { ///< the default of the parameter
0047         return _preset;
0048     }
0049     inline bool necessary() const
0050     { ///< false if the parameter is optional
0051         return _necessary;
0052     }
0053 
0054 private:
0055     QString _description;
0056     QString _preset;
0057     bool _necessary;
0058 };
0059 
0060 #define EXP_FUNC virtual TagString expFunc(const KrPanel *, const TagStringList &, const bool &, Expander &) const
0061 #define SIMPLE_EXP_FUNC virtual TagString expFunc(const KrPanel *, const QStringList &, const bool &, Expander &) const
0062 /**
0063  * Abstract baseclass for all expander-functions (which replace placeholder).
0064  * A Placeholder is an entry containing the expression,
0065  * its expanding function and Parameter.
0066  *
0067  * Not to be created on the heap
0068  */
0069 class exp_placeholder
0070 {
0071 public:
0072     inline QString expression() const
0073     { ///< The placeholder (without '%' or panel-prefix)
0074         return _expression;
0075     }
0076     inline QString description() const
0077     { ///< A description of the placeholder
0078         return _description;
0079     }
0080     inline bool needPanel() const
0081     { ///< true if the placeholder needs a panel to operate on
0082         return _needPanel;
0083     }
0084     inline void addParameter(exp_parameter parameter)
0085     { ///< adds parameter to the placeholder
0086         _parameter.append(parameter);
0087     }
0088     inline int parameterCount() const
0089     { ///< returns the number of placeholders
0090         return _parameter.count();
0091     }
0092     inline const exp_parameter &parameter(int id) const
0093     { ///< returns a specific parameter
0094         return _parameter[id];
0095     }
0096 
0097     EXP_FUNC = 0;
0098 
0099 protected:
0100     static void setError(Expander &exp, const Error &e);
0101     static void panelMissingError(const QString &s, Expander &exp);
0102     static QStringList splitEach(const TagString &s);
0103     static QStringList
0104     fileList(const KrPanel *const panel, const QString &type, const QString &mask, const bool omitPath, const bool useUrl, Expander &, const QString &);
0105     exp_placeholder();
0106     exp_placeholder(const exp_placeholder &p);
0107     virtual ~exp_placeholder()
0108     {
0109     }
0110     QString _expression;
0111     QString _description;
0112     QList<exp_parameter> _parameter;
0113     bool _needPanel;
0114 };
0115 
0116 class Error
0117 {
0118 public:
0119     enum Cause { exp_C_USER, exp_C_SYNTAX, exp_C_WORLD, exp_C_ARGUMENT };
0120     enum Severity { exp_S_OK, exp_S_WARNING, exp_S_ERROR, exp_S_FATAL };
0121 
0122     Error()
0123         : m_severity(exp_S_OK)
0124     {
0125     }
0126     Error(Severity severity, Cause cause)
0127         : m_severity(severity)
0128         , m_cause(cause)
0129         , m_description()
0130     {
0131     }
0132     Error(Severity severity, Cause cause, QString description)
0133         : m_severity(severity)
0134         , m_cause(cause)
0135         , m_description(description)
0136     {
0137     }
0138 
0139     operator bool() const
0140     {
0141         return m_severity != exp_S_OK;
0142     }
0143     Cause cause() const
0144     {
0145         return m_cause;
0146     }
0147     const QString &description() const
0148     {
0149         return m_description;
0150     }
0151 
0152 private:
0153     Severity m_severity;
0154     Cause m_cause;
0155     QString m_description;
0156 };
0157 
0158 /**
0159  * The Expander expands the command of an UserAction by replacing all
0160  * placeholders by their current values.@n
0161  * Each placeholder begins with a '%'-sign, followed by one char indicating
0162  * the panel, followed by a command which may have some parameter enclosed
0163  * in brackets and also ends with a '%'-sign.
0164  * Examples are %aPath% or %rBookmark("/home/jonas/src/krusader_kde3", "yes")%.@n
0165  * The panel-indicator has to be either
0166  * 'a' for the active
0167  * 'o' for the other
0168  * 'r' for the right
0169  * 'l' for the left
0170  * '_' for panel-independence.
0171  *
0172  * Currently supported are these commands can be ordered in three groups
0173  * (children are the parameter in the right order):
0174  * - Placeholders for Krusaders panel-data (panel-indicator has to be 'a', 'o', 'r' or 'l')
0175  *    - @em Path is replaced by the panel's path
0176  *    - @em Count is replaced by a nomber of
0177  *       -# Either "All", "Files", "Dirs", "Selected"
0178  *       .
0179  *    - @em Filter is preplaced by the panels filter-mask (ex: "*.cpp *.h")
0180  *    - @em Current is replaced by the current item or, in case of onmultiple="call_each", by each selected item.
0181  *       -# If "yes", only the filename (without path) is returned
0182  *       .
0183  *    - @em List isreplaced by a list of
0184  *       -# Either "All", "Files", "Dirs", "Selected"
0185  *       -# A separator between the items (default: " " [one space])
0186  *       -# If "yes", only the filename (without path) is returned
0187  *       -# (for all but "Selected") a filter-mask (default: "*")
0188  *       .
0189  *   .
0190  * - Access to panel-dependent, krusader-internal, parameter-needed functions
0191  *   (panel-indicator has to be 'a', 'o', 'r' or 'l')
0192  *    - @em Select manipulates the selection of the panel
0193  *       -# A filter-mask (necessary)
0194  *       -# Either "Add", "Remove", "Set" (default)
0195  *       .
0196  *    - @em Bookmark manipulates the selection of the panel
0197  *       -# A path or URL (necessary)
0198  *       -# If "yes", the location is opened in a new tab
0199  *       .
0200  *   .
0201  * - Access to panel-independent, krusader-internal, parameter-needed functions
0202  *   (panel-indicator doesn't matter but should be set to '_')
0203  *    - @em Ask displays a lineedit and is replaced by its return
0204  *       -# The question (necessary)
0205  *       -# A default answer
0206  *       -# A cation for the popup
0207  *       .
0208  *    - @em Clipboard manipulates the system-wide clipboard
0209  *       -# The string copied to clip (ex: "%aCurrent%") (necessary)
0210  *       -# A separator. If set, parameter1 is append with this to the current clipboard content
0211  *       .
0212  *    .
0213  * .
0214  * Since all placeholders are expanded in the order they appear in the command,
0215  * little one-line-scripts are possible
0216  */
0217 class Expander
0218 {
0219 public:
0220     inline static int placeholderCount()
0221     { ///< returns the number of placeholders
0222         return _placeholder().count();
0223     }
0224     inline static const exp_placeholder *placeholder(int id)
0225     {
0226         return _placeholder()[id];
0227     }
0228 
0229     /**
0230      * This expands a whole commandline
0231      *
0232      * @param stringToExpand the commandline with the placeholder
0233      * @param useUrl true iff the path's should be expanded to an URL instead of an local path
0234      * @return a list of all commands
0235      */
0236     void expand(const QString &stringToExpand, bool useUrl);
0237 
0238     /**
0239      * Returns the list of all commands to be executed, provided that #expand was called
0240      * before, and there was no error (see #error).
0241      *
0242      * @return The list of commands to be executed
0243      */
0244     const QStringList &result() const
0245     {
0246         assert(!error());
0247         return resultList;
0248     }
0249 
0250     /**
0251      *  Returns the error object of this Expander. You can test whether there was
0252      * any error by
0253      * \code
0254      * if(exp.error())
0255      *  error behaviour...
0256      * else
0257      *   no error...
0258      * \endcode
0259      *
0260      * @return The error object
0261      */
0262     const Error &error() const
0263     {
0264         return _err;
0265     }
0266 
0267 protected:
0268     /**
0269      * This expands a whole commandline by calling for each Placeholder the corresponding expander
0270      *
0271      * @param stringToExpand the commandline with the placeholder
0272      * @param useUrl true if the path's should be expanded to an URL instead of an local path
0273      * @return the expanded commanline for the current item
0274      */
0275     TagString expandCurrent(const QString &stringToExpand, bool useUrl);
0276     /**
0277      * This function searches for "\@EACH"-marks to split the string in a list for each %_Each%-item
0278      *
0279      * @param stringToSplit the string which should be split
0280      * @return the split list
0281      */
0282     static QStringList splitEach(TagString stringToSplit);
0283     /**
0284      * @param panelIndicator either '_' for panel-independent placeholders, 'a', 'o', 'r', or 'l' for the active, other (inactive), right or left panel
0285      * @param pl placeholder
0286      * @param exp expander
0287      * @return a pointer to the right panel or NULL if no panel is needed.
0288      */
0289     static KrPanel *getPanel(const char panelIndicator, const exp_placeholder *, Expander &);
0290     /**
0291      *  This splits the parameter-string into separate parameter and expands each
0292      * @param exp the string holding all parameter
0293      * @param useUrl true if the path's should be expanded to an URL instead of an local path
0294      * @return a list of all parameter
0295      */
0296     TagStringList separateParameter(QString *const exp, bool useUrl);
0297     /**
0298      * This finds the end of a placeholder, taking care of the parameter
0299      * @return the position where the placeholder ends
0300      */
0301     int findEnd(const QString &str, int start);
0302 
0303     void setError(const Error &e)
0304     {
0305         _err = e;
0306     }
0307     friend class exp_placeholder;
0308 
0309 private:
0310     static QList<const exp_placeholder *> &_placeholder();
0311     Error _err;
0312     QStringList resultList;
0313 };
0314 
0315 #endif // ifndef EXPANDER_H