1 /**
2 * \file subframeseditor.cpp
3 * Editor for subframes contained in a frame.
4 *
5 * \b Project: Kid3
6 * \author Urs Fleisch
7 * \date 18 Sep 2015
8 *
9 * Copyright (C) 2015-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 #include "subframeseditor.h"
28 #include <QVBoxLayout>
29 #include <QHBoxLayout>
30 #include <QPushButton>
31 #include <QInputDialog>
32 #include <QCoreApplication>
33 #include "frametablemodel.h"
34 #include "genremodel.h"
35 #include "frametable.h"
36 #include "framelist.h"
37 #include "taggedfile.h"
38 #include "editframefieldsdialog.h"
39 #include "iplatformtools.h"
40
41 /**
42 * Constructor.
43 *
44 * @param platformTools platform tools
45 * @param app application context
46 * @param taggedFile tagged file
47 * @param parent parent widget
48 */
SubframesEditor(IPlatformTools * platformTools,Kid3Application * app,const TaggedFile * taggedFile,Frame::TagNumber tagNr,QWidget * parent)49 SubframesEditor::SubframesEditor(IPlatformTools* platformTools,
50 Kid3Application* app,
51 const TaggedFile* taggedFile,
52 Frame::TagNumber tagNr,
53 QWidget* parent)
54 : QWidget(parent), m_platformTools(platformTools), m_app(app),
55 m_taggedFile(taggedFile), m_tagNr(tagNr),
56 m_editFrameDialog(nullptr), m_editFrameRow(-1)
57 {
58 setObjectName(QLatin1String("SubframesEditor"));
59 auto layout = new QHBoxLayout(this);
60 m_frameTableModel = new FrameTableModel(
61 false, platformTools->iconProvider(), this);
62 m_frameTable = new FrameTable(m_frameTableModel, new GenreModel(false, this),
63 this);
64 layout->addWidget(m_frameTable);
65 auto buttonLayout = new QVBoxLayout;
66 m_editButton = new QPushButton(tr("Edit..."));
67 m_editButton->setDefault(false);
68 m_editButton->setAutoDefault(false);
69 connect(m_editButton, &QAbstractButton::clicked, this, &SubframesEditor::onEditClicked);
70 buttonLayout->addWidget(m_editButton);
71 m_addButton = new QPushButton(tr("Add..."));
72 m_addButton->setDefault(false);
73 m_addButton->setAutoDefault(false);
74 connect(m_addButton, &QAbstractButton::clicked, this, &SubframesEditor::onAddClicked);
75 buttonLayout->addWidget(m_addButton);
76 m_deleteButton = new QPushButton(tr("Delete"));
77 m_deleteButton->setDefault(false);
78 m_deleteButton->setAutoDefault(false);
79 connect(m_deleteButton, &QAbstractButton::clicked, this, &SubframesEditor::onDeleteClicked);
80 buttonLayout->addWidget(m_deleteButton);
81 buttonLayout->addStretch();
82 layout->addLayout(buttonLayout);
83 }
84
85 /**
86 * Set subframes.
87 * @param frames subframes, will be cleared
88 */
setFrames(FrameCollection & frames)89 void SubframesEditor::setFrames(FrameCollection& frames)
90 {
91 m_frameTableModel->transferFrames(frames);
92 }
93
94 /**
95 * Get subframes.
96 * @param frames the subframes are returned here
97 */
getFrames(FrameCollection & frames) const98 void SubframesEditor::getFrames(FrameCollection& frames) const
99 {
100 frames = m_frameTableModel->frames();
101 for (auto it = frames.begin(); it != frames.end(); ++it) {
102 auto& frame = const_cast<Frame&>(*it);
103 if (frame.isValueChanged()) {
104 frame.setFieldListFromValue();
105 }
106 }
107 }
108
109 /**
110 * Called when the Edit button is clicked.
111 */
onEditClicked()112 void SubframesEditor::onEditClicked()
113 {
114 QModelIndex index = m_frameTable->currentIndex();
115 if (const Frame* selectedFrame = m_frameTableModel->getFrameOfIndex(index)) {
116 editFrame(*selectedFrame, index.row());
117 }
118 }
119
120 /**
121 * Called when the Add button is clicked.
122 */
onAddClicked()123 void SubframesEditor::onAddClicked()
124 {
125 bool ok = false;
126 QStringList frameIds = m_taggedFile->getFrameIds(m_tagNr);
127 QMap<QString, QString> nameMap = Frame::getDisplayNameMap(frameIds);
128 QString displayName = QInputDialog::getItem(
129 this, tr("Add Frame"),
130 tr("Select the frame ID"), nameMap.keys(), 0, true, &ok);
131 if (ok) {
132 QString name = nameMap.value(displayName, displayName);
133 Frame::Type type = Frame::getTypeFromName(name);
134 Frame frame(type, QLatin1String(""), name, -1);
135 m_taggedFile->addFieldList(m_tagNr, frame);
136 editFrame(frame, -1);
137 }
138 }
139
140 /**
141 * Called when the Delete button is clicked.
142 */
onDeleteClicked()143 void SubframesEditor::onDeleteClicked()
144 {
145 QModelIndex index = m_frameTable->currentIndex();
146 if (index.isValid()) {
147 m_frameTableModel->removeRow(index.row());
148 }
149 }
150
151 /**
152 * Let user edit a frame and then update the fields
153 * when the edits are accepted.
154 *
155 * @param frame frame to edit
156 * @param row row of edited frame in frame table, -1 if newly added frame
157 */
editFrame(const Frame & frame,int row)158 void SubframesEditor::editFrame(const Frame& frame, int row)
159 {
160 m_editFrame = frame;
161 if (m_editFrame.isValueChanged()) {
162 m_editFrame.setFieldListFromValue();
163 }
164 m_editFrameRow = row;
165 QString name(m_editFrame.getInternalName());
166 if (name.isEmpty()) {
167 name = m_editFrame.getName();
168 }
169 if (!name.isEmpty()) {
170 int nlPos = name.indexOf(QLatin1Char('\n'));
171 if (nlPos > 0) {
172 // probably "TXXX - User defined text information\nDescription" or
173 // "WXXX - User defined URL link\nDescription"
174 name.truncate(nlPos);
175 }
176 name = QCoreApplication::translate("@default", name.toLatin1().data());
177 }
178 if (!m_editFrameDialog) {
179 m_editFrameDialog = new EditFrameFieldsDialog(m_platformTools, m_app, this);
180 connect(m_editFrameDialog, &QDialog::finished,
181 this, &SubframesEditor::onEditFrameDialogFinished);
182 }
183 m_editFrameDialog->setWindowTitle(name);
184 m_editFrameDialog->setFrame(m_editFrame, m_taggedFile, m_tagNr);
185 m_editFrameDialog->show();
186 }
187
188 /**
189 * Called when the edit frame dialog is finished.
190 * @param result dialog result
191 */
onEditFrameDialogFinished(int result)192 void SubframesEditor::onEditFrameDialogFinished(int result)
193 {
194 if (auto dialog =
195 qobject_cast<EditFrameFieldsDialog*>(sender())) {
196 if (result == QDialog::Accepted) {
197 const Frame::FieldList& fields = dialog->getUpdatedFieldList();
198 if (fields.isEmpty()) {
199 m_editFrame.setValue(dialog->getFrameValue());
200 } else {
201 m_editFrame.setFieldList(fields);
202 m_editFrame.setValueFromFieldList();
203 }
204 if (m_editFrameRow != -1) {
205 m_frameTableModel->removeRow(m_editFrameRow);
206 }
207 m_frameTableModel->insertFrame(m_editFrame);
208 }
209 }
210 }
211