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

0001 /**
0002  * \file subframeseditor.cpp
0003  * Editor for subframes contained in a frame.
0004  *
0005  * \b Project: Kid3
0006  * \author Urs Fleisch
0007  * \date 18 Sep 2015
0008  *
0009  * Copyright (C) 2015-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 #include "subframeseditor.h"
0028 #include <QVBoxLayout>
0029 #include <QHBoxLayout>
0030 #include <QPushButton>
0031 #include <QInputDialog>
0032 #include <QCoreApplication>
0033 #include "frametablemodel.h"
0034 #include "genremodel.h"
0035 #include "frametable.h"
0036 #include "framelist.h"
0037 #include "taggedfile.h"
0038 #include "editframefieldsdialog.h"
0039 #include "iplatformtools.h"
0040 
0041 /**
0042  * Constructor.
0043  *
0044  * @param platformTools platform tools
0045  * @param app application context
0046  * @param taggedFile tagged file
0047  * @param tagNr tag number
0048  * @param parent parent widget
0049  */
0050 SubframesEditor::SubframesEditor(IPlatformTools* platformTools,
0051                                  Kid3Application* app,
0052                                  const TaggedFile* taggedFile,
0053                                  Frame::TagNumber tagNr,
0054                                  QWidget* parent)
0055   : QWidget(parent), m_platformTools(platformTools), m_app(app),
0056     m_taggedFile(taggedFile), m_tagNr(tagNr),
0057     m_editFrameDialog(nullptr), m_editFrameRow(-1)
0058 {
0059   setObjectName(QLatin1String("SubframesEditor"));
0060   auto layout = new QHBoxLayout(this);
0061   m_frameTableModel = new FrameTableModel(
0062         false, platformTools->iconProvider(), this);
0063   m_frameTable = new FrameTable(m_frameTableModel, new GenreModel(false, this),
0064                                 this);
0065   layout->addWidget(m_frameTable);
0066   auto buttonLayout = new QVBoxLayout;
0067   m_editButton = new QPushButton(tr("Edit..."));
0068   m_editButton->setDefault(false);
0069   m_editButton->setAutoDefault(false);
0070   connect(m_editButton, &QAbstractButton::clicked, this, &SubframesEditor::onEditClicked);
0071   buttonLayout->addWidget(m_editButton);
0072   m_addButton = new QPushButton(tr("Add..."));
0073   m_addButton->setDefault(false);
0074   m_addButton->setAutoDefault(false);
0075   connect(m_addButton, &QAbstractButton::clicked, this, &SubframesEditor::onAddClicked);
0076   buttonLayout->addWidget(m_addButton);
0077   m_deleteButton = new QPushButton(tr("Delete"));
0078   m_deleteButton->setDefault(false);
0079   m_deleteButton->setAutoDefault(false);
0080   connect(m_deleteButton, &QAbstractButton::clicked, this, &SubframesEditor::onDeleteClicked);
0081   buttonLayout->addWidget(m_deleteButton);
0082   buttonLayout->addStretch();
0083   layout->addLayout(buttonLayout);
0084 }
0085 
0086 /**
0087  * Set subframes.
0088  * @param frames subframes, will be cleared
0089  */
0090 void SubframesEditor::setFrames(FrameCollection& frames)
0091 {
0092   m_frameTableModel->transferFrames(frames);
0093 }
0094 
0095 /**
0096  * Get subframes.
0097  * @param frames the subframes are returned here
0098  */
0099 void SubframesEditor::getFrames(FrameCollection& frames) const
0100 {
0101   frames = m_frameTableModel->frames();
0102   for (auto it = frames.begin(); it != frames.end(); ++it) {
0103     if (auto& frame = const_cast<Frame&>(*it); frame.isValueChanged()) {
0104       frame.setFieldListFromValue();
0105     }
0106   }
0107 }
0108 
0109 /**
0110  * Called when the Edit button is clicked.
0111  */
0112 void SubframesEditor::onEditClicked()
0113 {
0114   QModelIndex index = m_frameTable->currentIndex();
0115   if (const Frame* selectedFrame = m_frameTableModel->getFrameOfIndex(index)) {
0116     editFrame(*selectedFrame, index.row());
0117   }
0118 }
0119 
0120 /**
0121  * Called when the Add button is clicked.
0122  */
0123 void SubframesEditor::onAddClicked()
0124 {
0125   bool ok = false;
0126   QStringList frameIds = m_taggedFile->getFrameIds(m_tagNr);
0127   QMap<QString, QString> nameMap = Frame::getDisplayNameMap(frameIds);
0128   QString displayName = QInputDialog::getItem(
0129     this, tr("Add Frame"),
0130     tr("Select the frame ID"), nameMap.keys(), 0, true, &ok);
0131   if (ok) {
0132     QString name = nameMap.value(displayName, displayName);
0133     Frame::Type type = Frame::getTypeFromName(name);
0134     Frame frame(type, QLatin1String(""), name, -1);
0135     m_taggedFile->addFieldList(m_tagNr, frame);
0136     editFrame(frame, -1);
0137   }
0138 }
0139 
0140 /**
0141  * Called when the Delete button is clicked.
0142  */
0143 void SubframesEditor::onDeleteClicked()
0144 {
0145   if (QModelIndex index = m_frameTable->currentIndex(); index.isValid()) {
0146     m_frameTableModel->removeRow(index.row());
0147   }
0148 }
0149 
0150 /**
0151  * Let user edit a frame and then update the fields
0152  * when the edits are accepted.
0153  *
0154  * @param frame frame to edit
0155  * @param row row of edited frame in frame table, -1 if newly added frame
0156  */
0157 void SubframesEditor::editFrame(const Frame& frame, int row)
0158 {
0159   m_editFrame = frame;
0160   if (m_editFrame.isValueChanged()) {
0161     m_editFrame.setFieldListFromValue();
0162   }
0163   m_editFrameRow = row;
0164   QString name(m_editFrame.getInternalName());
0165   if (name.isEmpty()) {
0166     name = m_editFrame.getName();
0167   }
0168   if (!name.isEmpty()) {
0169     if (int nlPos = name.indexOf(QLatin1Char('\n')); nlPos > 0) {
0170       // probably "TXXX - User defined text information\nDescription" or
0171       // "WXXX - User defined URL link\nDescription"
0172       name.truncate(nlPos);
0173     }
0174     name = QCoreApplication::translate("@default", name.toLatin1().data());
0175   }
0176   if (!m_editFrameDialog) {
0177     m_editFrameDialog = new EditFrameFieldsDialog(m_platformTools, m_app, this);
0178     connect(m_editFrameDialog, &QDialog::finished,
0179             this, &SubframesEditor::onEditFrameDialogFinished);
0180   }
0181   m_editFrameDialog->setWindowTitle(name);
0182   m_editFrameDialog->setFrame(m_editFrame, m_taggedFile, m_tagNr);
0183   m_editFrameDialog->show();
0184 }
0185 
0186 /**
0187  * Called when the edit frame dialog is finished.
0188  * @param result dialog result
0189  */
0190 void SubframesEditor::onEditFrameDialogFinished(int result)
0191 {
0192   if (auto dialog =
0193       qobject_cast<EditFrameFieldsDialog*>(sender())) {
0194     if (result == QDialog::Accepted) {
0195       if (const Frame::FieldList& fields = dialog->getUpdatedFieldList();
0196           fields.isEmpty()) {
0197         m_editFrame.setValue(dialog->getFrameValue());
0198       } else {
0199         m_editFrame.setFieldList(fields);
0200         m_editFrame.setValueFromFieldList();
0201       }
0202       if (m_editFrameRow != -1) {
0203         m_frameTableModel->removeRow(m_editFrameRow);
0204       }
0205       m_frameTableModel->insertFrame(m_editFrame);
0206     }
0207   }
0208 }