1 /***************************************************************************
2 * Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
21 #include "collapsiblegroup.h"
25 #include <QVBoxLayout>
26 #include <QInputDialog>
27 #include <QDragEnterEvent>
32 #include <KGlobalSettings>
34 #include <KMessageBox>
35 #include <KStandardDirs>
36 #include <KFileDialog>
37 #include <KUrlRequester>
38 #include <KColorScheme>
40 MyEditableLabel::MyEditableLabel(QWidget * parent):
45 setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
48 void MyEditableLabel::mouseDoubleClickEvent ( QMouseEvent * e )
55 CollapsibleGroup::CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, QString groupName, QWidget * parent) :
56 AbstractCollapsibleWidget(parent),
60 m_subWidgets = QList <CollapsibleEffect *> ();
61 setFont(KGlobalSettings::smallestReadableFont());
62 QHBoxLayout *l = static_cast <QHBoxLayout *>(framegroup->layout());
63 m_title = new MyEditableLabel(this);
64 l->insertWidget(4, m_title);
65 m_title->setText(groupName.isEmpty() ? i18n("Effect Group") : groupName);
66 connect(m_title, SIGNAL(editingFinished()), this, SLOT(slotRenameGroup()));
67 buttonUp->setIcon(KIcon("kdenlive-up"));
68 buttonUp->setToolTip(i18n("Move effect up"));
69 buttonDown->setIcon(KIcon("kdenlive-down"));
70 buttonDown->setToolTip(i18n("Move effect down"));
72 buttonDel->setIcon(KIcon("kdenlive-deleffect"));
73 buttonDel->setToolTip(i18n("Delete effect"));
74 if (firstGroup) buttonUp->setVisible(false);
75 if (lastGroup) buttonDown->setVisible(false);
77 m_menu->addAction(KIcon("view-refresh"), i18n("Reset effect"), this, SLOT(slotResetEffect()));
78 m_menu->addAction(KIcon("document-save"), i18n("Save effect"), this, SLOT(slotSaveEffect()));
80 effecticon->setPixmap(KIcon("folder").pixmap(16,16));
81 m_menu->addAction(KIcon("list-remove"), i18n("Ungroup"), this, SLOT(slotUnGroup()));
83 menuButton->setIcon(KIcon("kdenlive-menu"));
84 menuButton->setMenu(m_menu);
86 enabledBox->setChecked(true);
88 connect(collapseButton, SIGNAL(clicked()), this, SLOT(slotSwitch()));
89 connect(enabledBox, SIGNAL(toggled(bool)), this, SLOT(slotEnable(bool)));
90 connect(buttonUp, SIGNAL(clicked()), this, SLOT(slotEffectUp()));
91 connect(buttonDown, SIGNAL(clicked()), this, SLOT(slotEffectDown()));
92 connect(buttonDel, SIGNAL(clicked()), this, SLOT(slotDeleteEffect()));
96 CollapsibleGroup::~CollapsibleGroup()
101 void CollapsibleGroup::slotUnGroup()
106 bool CollapsibleGroup::isActive() const
108 return decoframegroup->property("active").toBool();
111 void CollapsibleGroup::setActive(bool activate)
113 decoframegroup->setProperty("active", activate);
114 decoframegroup->setStyleSheet(decoframegroup->styleSheet());
117 void CollapsibleGroup::mouseDoubleClickEvent ( QMouseEvent * event )
119 if (framegroup->underMouse() && collapseButton->isEnabled()) slotSwitch();
120 QWidget::mouseDoubleClickEvent(event);
124 void CollapsibleGroup::slotEnable(bool enable)
126 m_title->setEnabled(enable);
127 enabledBox->blockSignals(true);
128 enabledBox->setChecked(enable);
129 enabledBox->blockSignals(false);
130 QVBoxLayout *vbox = static_cast<QVBoxLayout *>(widgetFrame->layout());
131 if (vbox == NULL) return;
132 for (int i = 0; i < vbox->count(); i++) {
133 CollapsibleGroup *e = static_cast<CollapsibleGroup *>(vbox->itemAt(i)->widget());
134 if (e) e->enabledBox->setChecked(enable);// slotEnable(enable);
138 void CollapsibleGroup::slotDeleteEffect()
140 emit deleteGroup(groupIndex());
143 void CollapsibleGroup::slotEffectUp()
145 emit changeGroupPosition(groupIndex(), true);
148 void CollapsibleGroup::slotEffectDown()
150 emit changeGroupPosition(groupIndex(), false);
153 void CollapsibleGroup::slotSaveEffect()
155 QString name = QInputDialog::getText(this, i18n("Save Effect"), i18n("Name for saved effect: "));
156 if (name.isEmpty()) return;
157 QString path = KStandardDirs::locateLocal("appdata", "effects/", true);
158 path = path + name + ".xml";
159 if (QFile::exists(path)) if (KMessageBox::questionYesNo(this, i18n("File %1 already exists.\nDo you want to overwrite it?", path)) == KMessageBox::No) return;
163 QDomElement effect = m_effect.cloneNode().toElement();
164 doc.appendChild(doc.importNode(effect, true));
165 effect = doc.firstChild().toElement();
166 effect.removeAttribute("kdenlive_ix");
167 effect.setAttribute("id", name);
168 effect.setAttribute("type", "custom");
169 QDomElement effectname = effect.firstChildElement("name");
170 effect.removeChild(effectname);
171 effectname = doc.createElement("name");
172 QDomText nametext = doc.createTextNode(name);
173 effectname.appendChild(nametext);
174 effect.insertBefore(effectname, QDomNode());
175 QDomElement effectprops = effect.firstChildElement("properties");
176 effectprops.setAttribute("id", name);
177 effectprops.setAttribute("type", "custom");
180 if (file.open(QFile::WriteOnly | QFile::Truncate)) {
181 QTextStream out(&file);
182 out << doc.toString();
185 emit reloadEffects();*/
188 void CollapsibleGroup::slotResetEffect()
190 //TODO: emit resetEffect(effectIndex());
193 void CollapsibleGroup::slotSwitch()
195 bool enable = !widgetFrame->isVisible();
199 void CollapsibleGroup::slotShow(bool show)
201 widgetFrame->setVisible(show);
203 collapseButton->setArrowType(Qt::DownArrow);
204 m_info.isCollapsed = false;
207 collapseButton->setArrowType(Qt::RightArrow);
208 m_info.isCollapsed = true;
210 //emit parameterChanged(m_original_effect, m_effect, effectIndex());
213 QWidget *CollapsibleGroup::title() const
218 void CollapsibleGroup::addGroupEffect(CollapsibleEffect *effect)
220 QVBoxLayout *vbox = static_cast<QVBoxLayout *>(widgetFrame->layout());
222 vbox = new QVBoxLayout();
223 vbox->setContentsMargins(0, 0, 0, 0);
225 widgetFrame->setLayout(vbox);
227 effect->setGroupIndex(groupIndex());
228 effect->setGroupName(m_title->text());
229 m_subWidgets.append(effect);
230 vbox->addWidget(effect);
233 QString CollapsibleGroup::infoString() const
235 return m_info.toString();
238 void CollapsibleGroup::removeGroup(int ix, QVBoxLayout *layout)
240 QVBoxLayout *vbox = static_cast<QVBoxLayout *>(widgetFrame->layout());
241 if (vbox == NULL) return;
242 for (int i = m_subWidgets.count() - 1; i >= 0 ; i--) {
243 vbox->removeWidget(m_subWidgets.at(i));
244 layout->insertWidget(ix, m_subWidgets.at(i));
246 m_subWidgets.clear();
249 int CollapsibleGroup::groupIndex() const
254 bool CollapsibleGroup::isGroup() const
259 void CollapsibleGroup::updateTimecodeFormat()
261 QVBoxLayout *vbox = static_cast<QVBoxLayout *>(widgetFrame->layout());
262 if (vbox == NULL) return;
263 for (int j = vbox->count() - 1; j >= 0; j--) {
264 CollapsibleEffect *e = static_cast<CollapsibleEffect *>(vbox->itemAt(j)->widget());
265 if (e) e->updateTimecodeFormat();
269 void CollapsibleGroup::dragEnterEvent(QDragEnterEvent *event)
271 if (event->mimeData()->hasFormat("kdenlive/effectslist")) {
272 framegroup->setProperty("active", true);
273 framegroup->setStyleSheet(framegroup->styleSheet());
274 event->acceptProposedAction();
278 void CollapsibleGroup::dragLeaveEvent(QDragLeaveEvent */*event*/)
280 framegroup->setProperty("active", false);
281 framegroup->setStyleSheet(framegroup->styleSheet());
284 void CollapsibleGroup::dropEvent(QDropEvent *event)
286 framegroup->setProperty("active", false);
287 framegroup->setStyleSheet(framegroup->styleSheet());
288 const QString effects = QString::fromUtf8(event->mimeData()->data("kdenlive/effectslist"));
289 //event->acceptProposedAction();
291 doc.setContent(effects, true);
292 QDomElement e = doc.documentElement();
293 int ix = e.attribute("kdenlive_ix").toInt();
295 // effect dropped from effects list, add it
296 e.setAttribute("kdenlive_ix", ix);
297 event->setDropAction(Qt::CopyAction);
302 if (m_subWidgets.isEmpty()) return;
303 int new_index = m_subWidgets.at(m_subWidgets.count() - 1)->effectIndex();
304 emit moveEffect(ix, new_index, m_index, m_title->text());
305 event->setDropAction(Qt::MoveAction);
309 void CollapsibleGroup::slotRenameGroup()
311 m_title->setReadOnly(true);
312 if (m_title->text().isEmpty()) m_title->setText(i18n("Effect Group"));
313 for (int j = 0; j < m_subWidgets.count(); j++) {
314 m_subWidgets.at(j)->setGroupName(m_title->text());
316 emit groupRenamed(this);
319 QList <CollapsibleEffect*> CollapsibleGroup::effects()
324 QDomDocument CollapsibleGroup::effectsData()
327 QDomElement list = doc.createElement("list");
328 list.setAttribute("name", m_title->text());
329 doc.appendChild(list);
330 for (int j = 0; j < m_subWidgets.count(); j++) {
331 list.appendChild(doc.importNode(m_subWidgets.at(j)->effect(), true));