File indexing completed on 2025-02-23 04:34:22

0001 /**
0002  * \file kid3form.h
0003  * GUI for kid3.
0004  *
0005  * \b Project: Kid3
0006  * \author Urs Fleisch
0007  * \date 8 Apr 2003
0008  *
0009  * Copyright (C) 2003-2024  Urs Fleisch
0010  *
0011  * This file is part of Kid3.
0012  *
0013  * Kid3 is free software; you can redistribute it and/or modify
0014  * it under the terms of the GNU General Public License as published by
0015  * the Free Software Foundation; either version 2 of the License, or
0016  * (at your option) any later version.
0017  *
0018  * Kid3 is distributed in the hope that it will be useful,
0019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0021  * GNU General Public License for more details.
0022  *
0023  * You should have received a copy of the GNU General Public License
0024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0025  */
0026 
0027 #pragma once
0028 
0029 #include <QSplitter>
0030 #include <QLineEdit>
0031 #include "frame.h"
0032 
0033 class QLabel;
0034 class QCheckBox;
0035 class QPushButton;
0036 class QToolButton;
0037 class QSpinBox;
0038 class QGridLayout;
0039 class QGroupBox;
0040 class QPixmap;
0041 class QComboBox;
0042 class QStackedWidget;
0043 class FormatConfig;
0044 class FrameTable;
0045 class FrameTableModel;
0046 class Kid3Application;
0047 class FileList;
0048 class ConfigurableTreeView;
0049 class PictureLabel;
0050 class BaseMainWindowImpl;
0051 class Kid3FormTagContext;
0052 class AbstractFileDecorationProvider;
0053 class SectionActions;
0054 
0055 /**
0056  * Main widget.
0057  */
0058 class KID3_GUI_EXPORT Kid3Form : public QSplitter {
0059   Q_OBJECT
0060 public:
0061   /**
0062    * Constructs an Id3Form as a child of 'parent', with the
0063    * name 'name' and widget flags set to 'f'.
0064    * @param app application
0065    * @param mainWin main window
0066    * @param parent parent widget
0067    */
0068   Kid3Form(Kid3Application* app, BaseMainWindowImpl* mainWin,
0069            QWidget* parent = nullptr);
0070 
0071   /**
0072    * Destructor.
0073    */
0074   ~Kid3Form() override;
0075 
0076   /**
0077    * Set keyboard shortcuts for section actions.
0078    * @param map map of action names to key sequences
0079    */
0080   void setSectionActionShortcuts(const QMap<QString, QKeySequence>& map);
0081 
0082   /**
0083    * Get context for tag.
0084    * @param tagNr tag number
0085    * @return tag context.
0086    */
0087   Kid3FormTagContext* tag(Frame::TagNumber tagNr) const {
0088     return m_tagContext[tagNr];
0089   }
0090 
0091   /**
0092    * Enable or disable controls requiring tags.
0093    * @param tagNr tag number
0094    * @param enable true to enable
0095    */
0096   void enableControls(Frame::TagNumber tagNr, bool enable);
0097 
0098   /**
0099    * Display the tag format.
0100    * @param tagNr tag number
0101    * @param str string describing format, e.g. "ID3v1.1"
0102    */
0103   void setTagFormat(Frame::TagNumber tagNr, const QString& str);
0104 
0105   /**
0106    * Adjust the size of the right half box.
0107    */
0108   void adjustRightHalfBoxSize();
0109 
0110   /**
0111    * Hide or show file controls.
0112    *
0113    * @param hide true to hide, false to show
0114    */
0115   void hideFile(bool hide);
0116 
0117   /**
0118    * Hide or show tag controls.
0119    * @param tagNr tag number
0120    * @param hide true to hide, false to show
0121    */
0122   void hideTag(Frame::TagNumber tagNr, bool hide);
0123 
0124   /**
0125    * Toggle visibility of tag controls.
0126    * @param tagNr tag number
0127    */
0128   void showHideTag(Frame::TagNumber tagNr);
0129 
0130   /**
0131    * Hide or show picture.
0132    *
0133    * @param hide true to hide, false to show
0134    */
0135   void hidePicture(bool hide);
0136 
0137   /**
0138    * Save the local settings to the configuration.
0139    */
0140   void saveConfig();
0141 
0142   /**
0143    * Read the local settings from the configuration.
0144    */
0145   void readConfig();
0146 
0147   /**
0148    * Save file and directory list columns to the configuration.
0149    */
0150   void saveFileAndDirListConfig();
0151 
0152   /**
0153    * Set file and directory list columns from the configuration.
0154    */
0155   void readFileAndDirListConfig();
0156 
0157   /**
0158    * Get filename.
0159    */
0160   QString getFilename() const { return m_nameLineEdit->text(); }
0161 
0162   /**
0163    * Set filename.
0164    * @param fn filename
0165    */
0166   void setFilename(const QString& fn) { m_nameLineEdit->setText(fn); }
0167 
0168   /**
0169    * Check if the filename line edit is enabled.
0170    * @return true if the filename line edit is enabled.
0171    */
0172   bool isFilenameEditEnabled() const { return m_nameLineEdit->isEnabled(); }
0173 
0174   /**
0175    * Enable or disable the filename line edit.
0176    * @param en true to enable
0177    */
0178   void setFilenameEditEnabled(bool en) { m_nameLineEdit->setEnabled(en); }
0179 
0180   /**
0181    * Select in the filename line edit.
0182    * @param start start position
0183    * @param length number of characters to select
0184    */
0185   void setFilenameSelection(int start, int length) {
0186     m_nameLineEdit->setSelection(start, length);
0187     m_nameLineEdit->setFocus();
0188   }
0189 
0190   /**
0191    * Mark the filename as changed.
0192    * @param en true to mark as changed
0193    */
0194   void markChangedFilename(bool en);
0195 
0196   /**
0197    * Set preview picture data.
0198    * @param data picture data, empty if no picture is available
0199    */
0200   void setPictureData(const QByteArray& data);
0201 
0202   /**
0203    * Set details info text.
0204    *
0205    * @param str detail information summary as string
0206    */
0207   void setDetailInfo(const QString& str);
0208 
0209   /**
0210    * Get file list.
0211    * @return file list.
0212    */
0213   FileList* getFileList() { return m_fileListBox; }
0214 
0215   /**
0216    * Get directory list.
0217    * @return directory list.
0218    */
0219   ConfigurableTreeView* getDirList() { return m_dirListBox; }
0220 
0221   /**
0222    * Get frame table.
0223    * @param tagNr tag number
0224    * @return frame table.
0225    */
0226   FrameTable* frameTable(Frame::TagNumber tagNr) { return m_frameTable[tagNr]; }
0227 
0228   /**
0229    * Set a widget to be displayed at the left side instead of the file lists.
0230    * @param widget widget to be shown at the left side
0231    */
0232   void setLeftSideWidget(QWidget* widget);
0233 
0234   /**
0235    * Remove widget set with setLeftSideWidget().
0236    *
0237    * The widget will not be deleted.
0238    *
0239    * @param widget widget to be removed
0240    */
0241   void removeLeftSideWidget(QWidget* widget);
0242 
0243 public slots:
0244   /**
0245    * Filename line edit is changed.
0246    * @param txt contents of line edit
0247    */
0248   void nameLineEditChanged(const QString& txt);
0249 
0250   /**
0251    * Directory list box directory selected.
0252    *
0253    * @param index selected item
0254    */
0255   void dirSelected(const QModelIndex& index);
0256 
0257   /**
0258    * File list box item activated.
0259    *
0260    * @param index selected item
0261    */
0262   void fileActivated(const QModelIndex& index);
0263 
0264   /**
0265    * Open the parent directory of a model index.
0266    *
0267    * @param index current root index of item view
0268    */
0269   void openParentDirectory(const QModelIndex& index);
0270 
0271   /**
0272    * Set focus on filename controls.
0273    */
0274   void setFocusFilename();
0275 
0276   /**
0277    * Set focus on tag controls.
0278    * @param tagNr tag number
0279    */
0280   void setFocusTag(Frame::TagNumber tagNr);
0281 
0282   /**
0283    * Set focus on next tag controls.
0284    * @param tagNr current tag, Frame::Tag_NumValues if not on tag
0285    */
0286   void setFocusNextTag(Frame::TagNumber tagNr);
0287 
0288   /**
0289    * Set focus on previous tag controls.
0290    * @param tagNr current tag, Frame::Tag_NumValues if not on tag
0291    */
0292   void setFocusPreviousTag(Frame::TagNumber tagNr);
0293 
0294   /**
0295    * Set focus on file list.
0296    */
0297   void setFocusFileList();
0298 
0299   /**
0300    * Set focus on directory list.
0301    */
0302   void setFocusDirList();
0303 
0304   /**
0305    * Select all files.
0306    */
0307   void selectAllFiles();
0308 
0309   /**
0310    * Deselect all files.
0311    */
0312   void deselectAllFiles();
0313 
0314   /**
0315    * Set the next file as the current file.
0316    *
0317    * @param select true to select the file
0318    * @param onlyTaggedFiles only consider tagged files
0319    *
0320    * @return true if a next file exists.
0321    */
0322   bool nextFile(bool select = true, bool onlyTaggedFiles = true);
0323 
0324   /**
0325    * Set the previous file as the current file.
0326    *
0327    * @param select true to select the file
0328    * @param onlyTaggedFiles only consider tagged files
0329    *
0330    * @return true if a previous file exists.
0331    */
0332   bool previousFile(bool select = true, bool onlyTaggedFiles = true);
0333 
0334   /**
0335    * Select the next tagged file as the current file.
0336    * Same as nextFile() with default arguments, provided for functor-based
0337    * connections.
0338    * @return true if a next file exists.
0339    */
0340   bool selectNextTaggedFile();
0341 
0342   /**
0343    * Select the previous tagged file as the current file.
0344    * Same as previousFile() with default arguments, provided for functor-based
0345    * connections.
0346    * @return true if a previous file exists.
0347    */
0348   bool selectPreviousTaggedFile();
0349 
0350   /**
0351    * Set the root index of the file list.
0352    *
0353    * @param index root index of directory in file system model
0354    */
0355   void setFileRootIndex(const QModelIndex& index);
0356 
0357   /**
0358    * Set the root index of the directory list.
0359    *
0360    * @param index root index of directory in directory model
0361    */
0362   void setDirRootIndex(const QModelIndex& index);
0363 
0364 protected:
0365   /**
0366    * Accept drag.
0367    *
0368    * @param ev drag event.
0369    */
0370   void dragEnterEvent(QDragEnterEvent* ev) override;
0371 
0372   /**
0373    * Handle event when mouse is moved while dragging.
0374    *
0375    * @param ev drag event.
0376    */
0377   void dragMoveEvent(QDragMoveEvent* ev) override;
0378 
0379   /**
0380    * Handle event when mouse leaves widget while dragging.
0381    *
0382    * @param ev drag event.
0383    */
0384   void dragLeaveEvent(QDragLeaveEvent* ev) override;
0385 
0386   /**
0387    * Handle drop event.
0388    *
0389    * @param ev drop event.
0390    */
0391   void dropEvent(QDropEvent* ev) override;
0392 
0393 private slots:
0394   /**
0395    * Toggle visibility of file controls.
0396    */
0397   void showHideFile();
0398 
0399   /**
0400    * Set format text configuration when format edit text is changed.
0401    * @param text format text
0402    */
0403   void onFormatEditTextChanged(const QString& text);
0404 
0405   /**
0406    * Set format from filename text configuration when edit text is changed.
0407    * @param text format text
0408    */
0409   void onFormatFromFilenameEditTextChanged(const QString& text);
0410 
0411   /**
0412    * Update sorting after directory is opened for the first time.
0413    * The sort order of the file list is not correct if it is not explicitly
0414    * sorted the first time.
0415    */
0416   void onFirstDirectoryOpened();
0417 
0418   /**
0419    * Copy tags using QAction::data().
0420    * The source and destination tag numbers are taken from the first two bytes
0421    * in QAction::data().toByteArray() if the sender() is a QAction.
0422    */
0423   void copyTagsActionData();
0424 
0425   /**
0426    * Set items of "Format <arrow up>" combo box from file configuration.
0427    */
0428   void setToFilenameFormats();
0429 
0430   /**
0431    * Set items of "Format <arrow down>" combo box from file configuration.
0432    */
0433   void setFromFilenameFormats();
0434 
0435 private:
0436   /**
0437    * Format string within line edit.
0438    *
0439    * @param le   line edit
0440    * @param txt  text in line edit
0441    * @param fcfg format configuration
0442    */
0443   void formatLineEdit(QLineEdit* le, const QString& txt,
0444             const FormatConfig* fcfg);
0445 
0446   /**
0447    * Get frame table which is currently in editing state.
0448    * The returned frame table can be used to restore the editing state after
0449    * changing the current file.
0450    * @return frame table which is in editing state, 0 if none.
0451    */
0452   FrameTable* getEditingFrameTable() const;
0453 
0454   FileList* m_fileListBox;
0455   QComboBox* m_formatComboBox;
0456   QComboBox* m_formatFromFilenameComboBox;
0457   QLabel* m_nameLabel;
0458   QLineEdit* m_nameLineEdit;
0459   ConfigurableTreeView* m_dirListBox;
0460   Kid3FormTagContext* m_tagContext[Frame::Tag_NumValues];
0461   FrameTable* m_frameTable[Frame::Tag_NumValues];
0462   QStackedWidget* m_leftSideWidget;
0463   QSplitter* m_vSplitter;
0464   QWidget* m_fileWidget;
0465   QWidget* m_tagWidget[Frame::Tag_NumValues];
0466   QToolButton* m_fileButton;
0467   QToolButton* m_tagButton[Frame::Tag_NumValues];
0468   QLabel* m_fileLabel;
0469   QLabel* m_tagLabel[Frame::Tag_NumValues];
0470   QPushButton* m_fnButton[Frame::Tag_NumValues];
0471   QPushButton* m_toTagButton[Frame::Tag_NumValues];
0472   QPushButton* m_id3PushButton[Frame::Tag_NumValues];
0473   QWidget* m_rightHalfVBox;
0474   PictureLabel* m_pictureLabel;
0475   Kid3Application* m_app;
0476   BaseMainWindowImpl* m_mainWin;
0477   QScopedPointer<AbstractFileDecorationProvider> m_iconProvider;
0478   QList<SectionActions*> m_sectionActions;
0479 
0480   /** Collapse pixmap, will be allocated in constructor */
0481   static QPixmap* s_collapsePixmap;
0482   /** Expand pixmap, will be allocated in constructor */
0483   static QPixmap* s_expandPixmap;
0484 };
0485 
0486 /**
0487  * Facade to have a uniform interface for different tags.
0488  */
0489 class KID3_GUI_EXPORT Kid3FormTagContext : public QObject {
0490   Q_OBJECT
0491 public:
0492   /**
0493    * Constructor.
0494    * @param form GUI form
0495    * @param tagNr tag number
0496    */
0497   Kid3FormTagContext(Kid3Form* form, Frame::TagNumber tagNr) : QObject(form),
0498     m_form(form), m_tagNr(tagNr) {
0499   }
0500 
0501 public slots:
0502   /**
0503    * Set focus on tag controls.
0504    */
0505   void setFocusTag() { m_form->setFocusTag(m_tagNr); }
0506 
0507   /**
0508    * Toggle visibility of tag controls.
0509    */
0510   void showHideTag() { m_form->showHideTag(m_tagNr); }
0511 
0512 private:
0513   Kid3Form* const m_form;
0514   const Frame::TagNumber m_tagNr;
0515 };