1 /**
2  * \file clicommand.h
3  * Command line interface commands.
4  *
5  * \b Project: Kid3
6  * \author Urs Fleisch
7  * \date 11 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 <QObject>
30 #include "frame.h"
31 
32 class QModelIndex;
33 class Kid3Cli;
34 
35 /**
36  * Base class for command line interface command.
37  */
38 class CliCommand : public QObject {
39   Q_OBJECT
40 public:
41   /**
42    * Destructor.
43    */
44   virtual ~CliCommand() override = default;
45 
46   /**
47    * Reset state to defaults.
48    */
49   virtual void clear();
50 
51   /**
52    * Execute command.
53    */
54   virtual void execute();
55 
56   /**
57    * Get command name.
58    * @return name with which command is invoked.
59    */
name()60   QString name() const { return m_name; }
61 
62   /**
63    * Get help text for command.
64    * @return help text for command.
65    */
help()66   QString help() const { return m_help; }
67 
68   /**
69    * Get argument specification
70    * @return argument specification for command.
71    */
argumentSpecification()72   QString argumentSpecification() const { return m_argspec; }
73 
74   /**
75    * Get description of error.
76    * @return error message, empty if no error occurred.
77    */
getErrorMessage()78   QString getErrorMessage() const { return m_errorMsg; }
79 
80   /**
81    * Check if an error occurred.
82    * @return true if an error exists.
83    */
hasError()84   bool hasError() const { return !m_errorMsg.isEmpty(); }
85 
86   /**
87    * Set error message.
88    * @param errorMsg error message, null string to clear error
89    */
setError(const QString & errorMsg)90   void setError(const QString& errorMsg) { m_errorMsg = errorMsg; }
91 
92   /**
93    * Get timeout for operation.
94    * @return timeout in milliseconds.
95    */
getTimeout()96   int getTimeout() const { return m_timeoutMs; }
97 
98   /**
99    * Set timeout for operation.
100    * @param msec timeout in milliseconds, -1 for no timeout
101    */
setTimeout(int msec)102   void setTimeout(int msec) { m_timeoutMs = msec; }
103 
104   /**
105    * Get processor handling commands.
106    * @return processor.
107    */
cli()108   Kid3Cli* cli() const { return m_processor; }
109 
110   /**
111    * Get list of arguments.
112    * @return arguments, the first element is the command name.
113    */
args()114   const QStringList& args() const { return m_args; }
115 
116   /**
117    * Set list of arguments.
118    * @param args arguments, the first element must be the command name
119    */
setArgs(const QStringList & args)120   void setArgs(const QStringList& args) { m_args = args; }
121 
122   /**
123    * Get result code of command.
124    * @return result code, default is 0 for OK.
125    */
result()126   int result() const { return m_result; }
127 
128   /**
129    * Set result code of command.
130    * @param result result code
131    */
setResult(int result)132   void setResult(int result) { m_result = result; }
133 
134 signals:
135   /**
136    * Emitted when the command is finished.
137    */
138   void finished();
139 
140 protected slots:
141   /**
142    * Terminate command.
143    * Must be invoked when command is finished, which is set up in
144    * connectResultSignal().
145    */
146   void terminate();
147 
148 protected:
149   /**
150    * Constructor.
151    * @param processor command line processor
152    * @param name name with which command is invoked
153    * @param help help text for command
154    * @param argspec argument specification
155    */
156   CliCommand(Kid3Cli* processor, const QString& name, const QString& help,
157              const QString& argspec = QString());
158 
159   /**
160    * Called on timeout.
161    * @param event timer event
162    */
163   virtual void timerEvent(QTimerEvent* event) override;
164 
165   /**
166    * Start specific command.
167    * This method has to be implemented by the specific subclasses
168    * to execute the specific command. It should invoke terminate()
169    * when the command is finished.
170    */
171   virtual void startCommand() = 0;
172 
173   /**
174    * Connect signals used to emit finished().
175    * This method is called after startCommand(). The default implementation
176    * invokes terminate() in the event loop. It can be overridden to connect
177    * signals connected to terminate() to signal termination of the command.
178    */
179   virtual void connectResultSignal();
180 
181   /**
182    * Stop command.
183    * This method is called from terminate(). The default implementation
184    * does nothing. It can be overridden to disconnect signals connected
185    * in startCommand().
186    */
187   virtual void disconnectResultSignal();
188 
189   /**
190    * Get parameter for task mask.
191    * @param nr index in args()
192    * @param useDefault if true use cli()->tagMask() if no parameter found
193    * @return tag versions.
194    */
195   Frame::TagVersion getTagMaskParameter(int nr,
196                                         bool useDefault = true) const;
197 
198   /**
199    * Show usage of command.
200    */
201   void showUsage();
202 
203 private:
204   Kid3Cli* m_processor;
205   const QString m_name;
206   const QString m_help;
207   const QString m_argspec;
208   QStringList m_args;
209   QString m_errorMsg;
210   int m_timerId;
211   int m_timeoutMs;
212   int m_result;
213 };
214 
215 
216 /** Display help. */
217 class HelpCommand : public CliCommand {
218   Q_OBJECT
219 public:
220   /** Constructor. */
221   explicit HelpCommand(Kid3Cli* processor);
222 
223 protected:
224   virtual void startCommand() override;
225 };
226 
227 
228 /** Overwrite timeout. */
229 class TimeoutCommand : public CliCommand {
230   Q_OBJECT
231 public:
232   /** Constructor. */
233   explicit TimeoutCommand(Kid3Cli* processor);
234 
235 protected:
236   virtual void startCommand() override;
237 };
238 
239 
240 /** Quit application. */
241 class QuitCommand : public CliCommand {
242   Q_OBJECT
243 public:
244   /** Constructor. */
245   explicit QuitCommand(Kid3Cli* processor);
246 
247 protected:
248   virtual void startCommand() override;
249   virtual void connectResultSignal() override;
250 };
251 
252 
253 /** Change directory. */
254 class CdCommand : public CliCommand {
255   Q_OBJECT
256 public:
257   /** Constructor. */
258   explicit CdCommand(Kid3Cli* processor);
259 
260 protected:
261   virtual void startCommand() override;
262   virtual void connectResultSignal() override;
263   virtual void disconnectResultSignal() override;
264 };
265 
266 
267 /** Print current working directory. */
268 class PwdCommand : public CliCommand {
269   Q_OBJECT
270 public:
271   /** Constructor. */
272   explicit PwdCommand(Kid3Cli* processor);
273 
274 protected:
275   virtual void startCommand() override;
276 };
277 
278 
279 /** List directory. */
280 class LsCommand : public CliCommand {
281   Q_OBJECT
282 public:
283   /** Constructor. */
284   explicit LsCommand(Kid3Cli* processor);
285 
286 protected:
287   virtual void startCommand() override;
288 };
289 
290 
291 /** Save changes. */
292 class SaveCommand : public CliCommand {
293   Q_OBJECT
294 public:
295   /** Constructor. */
296   explicit SaveCommand(Kid3Cli* processor);
297 
298 protected:
299   virtual void startCommand() override;
300 };
301 
302 
303 /** Select file. */
304 class SelectCommand : public CliCommand {
305   Q_OBJECT
306 public:
307   /** Constructor. */
308   explicit SelectCommand(Kid3Cli* processor);
309 
310 protected:
311   virtual void startCommand() override;
312 };
313 
314 
315 /** Display or set tag mask. */
316 class TagCommand : public CliCommand {
317   Q_OBJECT
318 public:
319   /** Constructor. */
320   explicit TagCommand(Kid3Cli* processor);
321 
322 protected:
323   virtual void startCommand() override;
324 };
325 
326 
327 /** Get tag frame or file information. */
328 class GetCommand : public CliCommand {
329   Q_OBJECT
330 public:
331   /** Constructor. */
332   explicit GetCommand(Kid3Cli* processor);
333 
334 protected:
335   virtual void startCommand() override;
336 };
337 
338 
339 /** Set tag frame. */
340 class SetCommand : public CliCommand {
341   Q_OBJECT
342 public:
343   /** Constructor. */
344   explicit SetCommand(Kid3Cli* processor);
345 
346 protected:
347   virtual void startCommand() override;
348 };
349 
350 
351 /** Revert changes. */
352 class RevertCommand : public CliCommand {
353   Q_OBJECT
354 public:
355   /** Constructor. */
356   explicit RevertCommand(Kid3Cli* processor);
357 
358 protected:
359   virtual void startCommand() override;
360 };
361 
362 
363 /** Import from file. */
364 class ImportCommand : public CliCommand {
365   Q_OBJECT
366 public:
367   /** Constructor. */
368   explicit ImportCommand(Kid3Cli* processor);
369 
370 protected:
371   virtual void startCommand() override;
372 };
373 
374 /** Automatic import from servers. */
375 class BatchImportCommand : public CliCommand {
376   Q_OBJECT
377 public:
378   /** Constructor. */
379   explicit BatchImportCommand(Kid3Cli* processor);
380 
381 protected:
382   virtual void startCommand() override;
383   virtual void connectResultSignal() override;
384   virtual void disconnectResultSignal() override;
385 
386 private slots:
387   void onReportImportEvent(int type, const QString& text);
388 };
389 
390 /** Download album cover art. */
391 class AlbumArtCommand : public CliCommand {
392   Q_OBJECT
393 public:
394   /** Constructor. */
395   explicit AlbumArtCommand(Kid3Cli* processor);
396 
397 protected:
398   virtual void startCommand() override;
399   virtual void connectResultSignal() override;
400   virtual void disconnectResultSignal() override;
401 
402 private slots:
403   void onDownloadFinished(const QByteArray& data,
404                           const QString& mimeType, const QString& url);
405 };
406 
407 /** Export to file. */
408 class ExportCommand : public CliCommand {
409   Q_OBJECT
410 public:
411   /** Constructor. */
412   explicit ExportCommand(Kid3Cli* processor);
413 
414 protected:
415   virtual void startCommand() override;
416 };
417 
418 /** Create playlist file. */
419 class PlaylistCommand : public CliCommand {
420   Q_OBJECT
421 public:
422   /** Constructor. */
423   explicit PlaylistCommand(Kid3Cli* processor);
424 
425 protected:
426   virtual void startCommand() override;
427 };
428 
429 /** Apply file name format. */
430 class FilenameFormatCommand : public CliCommand {
431   Q_OBJECT
432 public:
433   /** Constructor. */
434   explicit FilenameFormatCommand(Kid3Cli* processor);
435 
436 protected:
437   virtual void startCommand() override;
438 };
439 
440 /** Apply tag format. */
441 class TagFormatCommand : public CliCommand {
442   Q_OBJECT
443 public:
444   /** Constructor. */
445   explicit TagFormatCommand(Kid3Cli* processor);
446 
447 protected:
448   virtual void startCommand() override;
449 };
450 
451 /** Apply text encoding. */
452 class TextEncodingCommand : public CliCommand {
453   Q_OBJECT
454 public:
455   /** Constructor. */
456   explicit TextEncodingCommand(Kid3Cli* processor);
457 
458 protected:
459   virtual void startCommand() override;
460 };
461 
462 /** Rename directory. */
463 class RenameDirectoryCommand : public CliCommand {
464   Q_OBJECT
465 public:
466   /** Constructor. */
467   explicit RenameDirectoryCommand(Kid3Cli* processor);
468 
469 protected:
470   virtual void startCommand() override;
471   virtual void connectResultSignal() override;
472   virtual void disconnectResultSignal() override;
473 
474 private slots:
475   void onActionScheduled(const QStringList& actionStrs);
476   void onRenameActionsScheduled();
477 
478 private:
479   bool m_dryRun;
480 };
481 
482 /** Number tracks. */
483 class NumberTracksCommand : public CliCommand {
484   Q_OBJECT
485 public:
486   /** Constructor. */
487   explicit NumberTracksCommand(Kid3Cli* processor);
488 
489 protected:
490   virtual void startCommand() override;
491 };
492 
493 /** Filter files. */
494 class FilterCommand : public CliCommand {
495   Q_OBJECT
496 public:
497   /** Constructor. */
498   explicit FilterCommand(Kid3Cli* processor);
499 
500 protected:
501   virtual void startCommand() override;
502   virtual void connectResultSignal() override;
503   virtual void disconnectResultSignal() override;
504 
505 private slots:
506   void onFileFiltered(int type, const QString& fileName);
507 };
508 
509 /** Convert ID3v2.3 to ID3v2.4. */
510 class ToId3v24Command : public CliCommand {
511   Q_OBJECT
512 public:
513   /** Constructor. */
514   explicit ToId3v24Command(Kid3Cli* processor);
515 
516 protected:
517   virtual void startCommand() override;
518 };
519 
520 /** Convert ID3v2.4 to ID3v2.3. */
521 class ToId3v23Command : public CliCommand {
522   Q_OBJECT
523 public:
524   /** Constructor. */
525   explicit ToId3v23Command(Kid3Cli* processor);
526 
527 protected:
528   virtual void startCommand() override;
529 };
530 
531 /** Set file name from tags. */
532 class TagToFilenameCommand : public CliCommand {
533   Q_OBJECT
534 public:
535   /** Constructor. */
536   explicit TagToFilenameCommand(Kid3Cli* processor);
537 
538 protected:
539   virtual void startCommand() override;
540 };
541 
542 /** Set tags from file name. */
543 class FilenameToTagCommand : public CliCommand {
544   Q_OBJECT
545 public:
546   /** Constructor. */
547   explicit FilenameToTagCommand(Kid3Cli* processor);
548 
549 protected:
550   virtual void startCommand() override;
551 };
552 
553 /** Copy between tag 1 and tag 2. */
554 class TagToOtherTagCommand : public CliCommand {
555   Q_OBJECT
556 public:
557   /** Constructor. */
558   explicit TagToOtherTagCommand(Kid3Cli* processor);
559 
560 protected:
561   virtual void startCommand() override;
562 };
563 
564 /** Copy to clipboard. */
565 class CopyCommand : public CliCommand {
566   Q_OBJECT
567 public:
568   /** Constructor. */
569   explicit CopyCommand(Kid3Cli* processor);
570 
571 protected:
572   virtual void startCommand() override;
573 };
574 
575 /** Paste from clipboard. */
576 class PasteCommand : public CliCommand {
577   Q_OBJECT
578 public:
579   /** Constructor. */
580   explicit PasteCommand(Kid3Cli* processor);
581 
582 protected:
583   virtual void startCommand() override;
584 };
585 
586 /** Remove tags. */
587 class RemoveCommand : public CliCommand {
588   Q_OBJECT
589 public:
590   /** Constructor. */
591   explicit RemoveCommand(Kid3Cli* processor);
592 
593 protected:
594   virtual void startCommand() override;
595 };
596 
597 /** Get or set configuration options. */
598 class ConfigCommand : public CliCommand {
599   Q_OBJECT
600 public:
601   /** Constructor. */
602   explicit ConfigCommand(Kid3Cli* processor);
603 
604 protected:
605   virtual void startCommand() override;
606 };
607