1 /**
2  * \file kid3cli.h
3  * Command line interface for Kid3.
4  *
5  * \b Project: Kid3
6  * \author Urs Fleisch
7  * \date 10 Aug 2013
8  *
9  * Copyright (C) 2013-2018  Urs Fleisch
10  *
11  * This file is part of Kid3.
12  *
13  * Kid3 is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * Kid3 is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
25  */
26 
27 #pragma once
28 
29 #include "abstractcli.h"
30 #include "frame.h"
31 #include "cliconfig.h"
32 #ifdef HAVE_READLINE
33 #include <QScopedPointer>
34 #endif
35 
36 class QTimer;
37 class Kid3Application;
38 class FileProxyModel;
39 class CliCommand;
40 class AbstractCliFormatter;
41 enum class CliError : int;
42 
43 #ifdef HAVE_READLINE
44 class Kid3CliCompleter;
45 #endif
46 
47 /**
48  * Command line interface for Kid3.
49  */
50 class Kid3Cli : public AbstractCli {
51   Q_OBJECT
52 public:
53   /**
54    * Constructor.
55    * @param app application context
56    * @param io I/O handler
57    * @param args command line arguments
58    * @param parent parent object
59    */
60   explicit Kid3Cli(Kid3Application* app,
61                    AbstractCliIO* io, const QStringList& args,
62                    QObject* parent = nullptr);
63 
64   /**
65    * Destructor.
66    */
67   virtual ~Kid3Cli() override;
68 
69   /**
70    * Execute process.
71    */
72   virtual void execute() override;
73 
74   /**
75    * Write a line to standard error.
76    * @param line line to write
77    */
78   virtual void writeErrorLine(const QString& line) override;
79 
80   /**
81    * Write result of command.
82    * @param str result as string
83    */
84   void writeResult(const QString& str);
85 
86   /**
87    * Write result of command.
88    * @param strs result as string list
89    */
90   void writeResult(const QStringList& strs);
91 
92   /**
93    * Write result of command.
94    * @param map result as map
95    */
96   void writeResult(const QVariantMap& map);
97 
98   /**
99    * Write result of command.
100    * @param map result as boolean
101    */
102   void writeResult(bool result);
103 
104   /**
105    * Called when a command is finished.
106    */
107   void finishWriting();
108 
109   /**
110    * Access to application.
111    * @return application.
112    */
app()113   Kid3Application* app() const { return m_app; }
114 
115   /**
116    * Open directory.
117    * @param paths directory or file paths
118    * @return true if ok.
119    */
120   bool openDirectory(const QStringList& paths);
121 
122   /**
123    * Select files in the current directory.
124    * @param paths file names
125    * @return true if files found and selected.
126    */
127   bool selectFile(const QStringList &paths);
128 
129   /**
130    * Display help about available commands.
131    * @param cmdName command name, for all commands if empty
132    * @param usageMessage true if this is a usage error message
133    */
134   void writeHelp(const QString& cmdName = QString(),
135                  bool usageMessage = false);
136 
137   /**
138    * Display information about selected files.
139    * @param tagMask tag bits (1 for tag 1, 2 for tag 2)
140    */
141   void writeFileInformation(int tagMask);
142 
143   /**
144    * Write currently active tag mask.
145    */
146   void writeTagMask();
147 
148   /**
149    * List files.
150    */
151   void writeFileList();
152 
153   /**
154    * Respond with an error message.
155    * @param errorCode error code
156    */
157   void writeErrorCode(CliError errorCode);
158 
159   /**
160    * Respond with an error message.
161    * @param msg error message
162    * @param errorCode error code
163    */
164   void writeError(const QString& msg, CliError errorCode);
165 
166   /**
167    * Get currently active tag mask.
168    * @return tag bits.
169    */
tagMask()170   Frame::TagVersion tagMask() const { return m_tagMask; }
171 
172   /**
173    * Set currently active tag mask.
174    *
175    * @param tagMask tag bits
176    */
177   void setTagMask(Frame::TagVersion tagMask);
178 
179   /**
180    * Get timeout value.
181    * @return timeout in ms, 0 to use defaults, -1 to switch off.
182    */
getTimeout()183   int getTimeout() const { return m_timeoutMs; }
184 
185   /**
186    * Set timeout value.
187    * @param timeout timeout in ms, 0 to use defaults, -1 to switch off
188    */
setTimeout(int timeout)189   void setTimeout(int timeout) { m_timeoutMs = timeout; }
190 
191   /**
192    * Expand wildcards in path list.
193    * @param paths paths to expand
194    * @return expanded paths.
195    */
196   static QStringList expandWildcards(const QStringList& paths);
197 
198 public slots:
199   /**
200    * Update the currently selected files from the frame tables.
201    */
202   void updateSelectedFiles();
203 
204   /**
205    * Has to be called when the selection changes to update the frame tables
206    * and the information about the selected files.
207    */
208   void updateSelection();
209 
210   /**
211    * Called when a command is finished.
212    */
213   void onCommandFinished();
214 
215 protected:
216   /**
217    * Process command line.
218    * @param line command line
219    */
220   virtual void readLine(const QString& line) override;
221 
222 private slots:
223   /**
224    * Select files passed as command line arguments after the initial directory has
225    * been opened. Start execution of commands if existing.
226    */
227   void onInitialDirectoryOpened();
228 
229   /**
230    * Called when an argument command is finished.
231    */
232   void onArgCommandFinished();
233 
234 private:
235   /**
236    * Get command for a command line.
237    * @param line command line
238    * @return command, 0 if no command found.
239    */
240   CliCommand* commandForArgs(const QString& line);
241 
242   QVariantList listFiles(const FileProxyModel* model,
243                            const QModelIndex& parent);
244   bool parseOptions();
245   void executeNextArgCommand();
246 
247   Kid3Application* m_app;
248   QStringList m_args;
249 #ifdef HAVE_READLINE
250   QScopedPointer<Kid3CliCompleter> m_completer;
251 #endif
252   AbstractCliFormatter* m_formatter;
253   QList<AbstractCliFormatter*> m_formatters;
254   QList<CliCommand*> m_cmds;
255   QStringList m_argCommands;
256   QString m_detailInfo;
257   QString m_filename;
258   QString m_tagFormat[Frame::Tag_NumValues];
259   Frame::TagVersion m_tagMask;
260   /** Overwrites command timeout, -1 to switch off, 0 for defaults, else ms. */
261   int m_timeoutMs;
262   bool m_fileNameChanged;
263 };
264