File indexing completed on 2022-10-04 15:37:19

0001 /*
0002 SPDX-FileCopyrightText: 2012 Jean-Baptiste Mardelle <jb@kdenlive.org>
0003 SPDX-FileCopyrightText: 2014 Till Theato <root@ttill.de>
0004 SPDX-FileCopyrightText: 2020 Julius Künzel <jk.kdedev@smartlab.uber.space>
0005 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006 */
0007 
0008 #include "layoutmanagement.h"
0009 #include "core.h"
0010 #include "mainwindow.h"
0011 #include <KMessageBox>
0012 #include <QButtonGroup>
0013 #include <QDialog>
0014 #include <QDialogButtonBox>
0015 #include <QFileDialog>
0016 #include <QInputDialog>
0017 #include <QListWidget>
0018 #include <QMenu>
0019 #include <QMenuBar>
0020 #include <QVBoxLayout>
0021 
0022 #include <KColorScheme>
0023 #include <KConfigGroup>
0024 #include <KLocalizedString>
0025 #include <KSharedConfig>
0026 #include <KXMLGUIFactory>
0027 
0028 LayoutManagement::LayoutManagement(QObject *parent)
0029     : QObject(parent)
0030 {
0031     m_translatedNames = {{QStringLiteral("kdenlive_logging"), i18n("Logging")},
0032                          {QStringLiteral("kdenlive_editing"), i18n("Editing")},
0033                          {QStringLiteral("kdenlive_audio"), i18n("Audio")},
0034                          {QStringLiteral("kdenlive_effects"), i18n("Effects")},
0035                          {QStringLiteral("kdenlive_color"), i18n("Color")}};
0036 
0037     // Prepare layout actions
0038     KActionCategory *layoutActions = new KActionCategory(i18n("Layouts"), pCore->window()->actionCollection());
0039     m_loadLayout = new KSelectAction(i18n("Load Layout"), pCore->window()->actionCollection());
0040     pCore->window()->actionCollection()->setShortcutsConfigurable(m_loadLayout, false);
0041 
0042     // Required to enable user to add the load layout action to toolbar
0043     layoutActions->addAction(QStringLiteral("load_layouts"), m_loadLayout);
0044     connect(m_loadLayout, static_cast<void (KSelectAction::*)(QAction *)>(&KSelectAction::triggered), this, &LayoutManagement::slotLoadLayout);
0045 
0046     QAction *saveLayout = new QAction(i18n("Save Layout…"), pCore->window()->actionCollection());
0047     layoutActions->addAction(QStringLiteral("save_layout"), saveLayout);
0048     connect(saveLayout, &QAction::triggered, this, &LayoutManagement::slotSaveLayout);
0049 
0050     QAction *manageLayout = new QAction(i18n("Manage Layouts…"), pCore->window()->actionCollection());
0051     layoutActions->addAction(QStringLiteral("manage_layout"), manageLayout);
0052     connect(manageLayout, &QAction::triggered, this, &LayoutManagement::slotManageLayouts);
0053     // Create 9 layout actions
0054     for (int i = 1; i < 10; i++) {
0055         QAction *load = new QAction(QIcon(), QString(), this);
0056         m_layoutActions << layoutActions->addAction("load_layout" + QString::number(i), load);
0057     }
0058 
0059     // Dock Area Oriantation
0060     QAction *rowDockAreaAction = new QAction(QIcon::fromTheme(QStringLiteral("object-rows")), i18n("Arrange Dock Areas In Rows"), this);
0061     layoutActions->addAction(QStringLiteral("horizontal_dockareaorientation"), rowDockAreaAction);
0062     connect(rowDockAreaAction, &QAction::triggered, this, &LayoutManagement::slotDockAreaRows);
0063 
0064     QAction *colDockAreaAction = new QAction(QIcon::fromTheme(QStringLiteral("object-columns")), i18n("Arrange Dock Areas In Columns"), this);
0065     layoutActions->addAction(QStringLiteral("vertical_dockareaorientation"), colDockAreaAction);
0066     connect(colDockAreaAction, &QAction::triggered, this, &LayoutManagement::slotDockAreaColumns);
0067 
0068     // Create layout switcher for the menu bar
0069     MainWindow *main = pCore->window();
0070     m_container = new QWidget(main);
0071     m_containerGrp = new QButtonGroup(m_container);
0072     connect(m_containerGrp, QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked), this, &LayoutManagement::activateLayout);
0073     auto *l1 = new QVBoxLayout;
0074     l1->addStretch();
0075     m_containerLayout = new QHBoxLayout;
0076     m_containerLayout->setSpacing(0);
0077     m_containerLayout->setContentsMargins(0, 0, 0, 0);
0078     l1->addLayout(m_containerLayout);
0079     m_container->setLayout(l1);
0080     KColorScheme scheme(main->palette().currentColorGroup(), KColorScheme::Button);
0081     QColor bg = scheme.background(KColorScheme::AlternateBackground).color();
0082     QString style = QString("padding-left: %4; padding-right: %4;background-color: rgb(%1,%2,%3);")
0083                         .arg(bg.red())
0084                         .arg(bg.green())
0085                         .arg(bg.blue())
0086                         .arg(main->fontInfo().pixelSize() / 2);
0087     m_container->setStyleSheet(style);
0088     main->menuBar()->setCornerWidget(m_container, Qt::TopRightCorner);
0089     initializeLayouts();
0090 }
0091 
0092 void LayoutManagement::initializeLayouts()
0093 {
0094     if (m_loadLayout == nullptr) {
0095         return;
0096     }
0097     QString current;
0098     if (m_containerGrp->checkedButton()) {
0099         current = m_containerGrp->checkedButton()->text();
0100     }
0101     MainWindow *main = pCore->window();
0102     // Delete existing buttons
0103     while (auto item = m_containerLayout->takeAt(0)) {
0104         delete item->widget();
0105     }
0106 
0107     // Load default base layouts
0108     KConfig defaultConfig(QStringLiteral("kdenlivedefaultlayouts.rc"), KConfig::CascadeConfig, QStandardPaths::AppDataLocation);
0109     KConfigGroup defaultOrder(&defaultConfig, "Order");
0110     KConfigGroup defaultLayout(&defaultConfig, "Layouts");
0111     QStringList defaultLayouts;
0112 
0113     // Load User defined layouts
0114     KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("kdenlive-layoutsrc"), KConfig::NoCascade);
0115     KConfigGroup layoutGroup(config, "Layouts");
0116     KConfigGroup layoutOrder(config, "Order");
0117     // If we don't have any layout saved, check in main config file
0118     if (!layoutGroup.exists()) {
0119         config = KSharedConfig::openConfig();
0120         KConfigGroup layoutGroup2(config, "Layouts");
0121         if (layoutGroup2.exists()) {
0122             // Migrate to new config file
0123             layoutGroup2.copyTo(&layoutGroup);
0124         }
0125     }
0126     m_loadLayout->removeAllActions();
0127     QStringList entries;
0128     bool addedDefault = false;
0129     if (!layoutOrder.exists()) {
0130         // This is an old or newly created config file, import defaults
0131         defaultLayouts = defaultOrder.entryMap().values();
0132         entries = layoutGroup.keyList();
0133         addedDefault = true;
0134     } else {
0135         // User sorted list
0136         entries = layoutOrder.entryMap().values();
0137     }
0138 
0139     // Add default layouts to user config in they don't exist
0140     for (const QString &lay : qAsConst(defaultLayouts)) {
0141         if (!entries.contains(lay)) {
0142             entries.insert(defaultLayouts.indexOf(lay), lay);
0143             layoutGroup.writeEntry(lay, defaultLayout.readEntry(lay));
0144             addedDefault = true;
0145         }
0146     }
0147     if (addedDefault) {
0148         // Write updated order
0149         layoutOrder.deleteGroup();
0150         int j = 1;
0151         for (const QString &entry : qAsConst(entries)) {
0152             layoutOrder.writeEntry(QString::number(j), entry);
0153             j++;
0154         }
0155         config->reparseConfiguration();
0156     }
0157     for (int i = 1; i < 10; i++) {
0158         QString layoutName;
0159         if (i <= entries.count()) {
0160             layoutName = entries.at(i - 1);
0161         } else {
0162             break;
0163         }
0164         QAction *load = m_layoutActions.at(i - 1);
0165         if (layoutName.isEmpty()) {
0166             load->setText(QString());
0167             load->setIcon(QIcon());
0168         } else {
0169             load->setText(i18n("Layout %1: %2", i, translatedName(layoutName)));
0170             if (i < 6) {
0171                 auto *lab = new QPushButton(translatedName(layoutName), m_container);
0172                 lab->setProperty("layoutid", layoutName);
0173                 lab->setFocusPolicy(Qt::NoFocus);
0174                 lab->setCheckable(true);
0175                 lab->setFlat(true);
0176                 lab->setFont(main->menuBar()->font());
0177                 m_containerGrp->addButton(lab);
0178                 m_containerLayout->addWidget(lab);
0179                 if (!current.isEmpty() && current == layoutName) {
0180                     lab->setChecked(true);
0181                 }
0182             }
0183         }
0184 
0185         load->setData(layoutName);
0186         if (!layoutName.isEmpty()) {
0187             load->setEnabled(true);
0188             m_loadLayout->addAction(load);
0189         } else {
0190             load->setEnabled(false);
0191         }
0192     }
0193     // Required to trigger a refresh of the container buttons
0194     main->menuBar()->resize(main->menuBar()->sizeHint());
0195 }
0196 
0197 void LayoutManagement::activateLayout(QAbstractButton *button)
0198 {
0199     if (!button) {
0200         return;
0201     }
0202     loadLayout(button->property("layoutid").toString(), false);
0203 }
0204 
0205 void LayoutManagement::slotLoadLayout(QAction *action)
0206 {
0207     if (!action) {
0208         return;
0209     }
0210 
0211     QString layoutId = action->data().toString();
0212     if (layoutId.isEmpty()) {
0213         return;
0214     }
0215     loadLayout(layoutId, true);
0216 }
0217 
0218 bool LayoutManagement::loadLayout(const QString &layoutId, bool selectButton)
0219 {
0220     KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("kdenlive-layoutsrc"));
0221     KConfigGroup layouts(config, "Layouts");
0222     if (!layouts.hasKey(layoutId)) {
0223         // Error, layout not found
0224         return false;
0225     }
0226     emit connectDocks(false);
0227     QByteArray state = QByteArray::fromBase64(layouts.readEntry(layoutId).toLatin1());
0228     bool timelineVisible = true;
0229     if (state.startsWith("NO-TL")) {
0230         timelineVisible = false;
0231         state.remove(0, 5);
0232     }
0233     pCore->window()->centralWidget()->setHidden(!timelineVisible);
0234     pCore->window()->processRestoreState(state);
0235     pCore->window()->tabifyBins();
0236     emit connectDocks(true);
0237     if (selectButton) {
0238         // Activate layout button
0239         QList<QAbstractButton *> buttons = m_containerGrp->buttons();
0240         bool buttonFound = false;
0241         for (auto *button : qAsConst(buttons)) {
0242             if (button->property("layoutid").toString() == layoutId) {
0243                 QSignalBlocker bk(m_containerGrp);
0244                 button->setChecked(true);
0245                 buttonFound = true;
0246             }
0247         }
0248         if (!buttonFound && m_containerGrp->checkedButton()) {
0249             m_containerGrp->setExclusive(false);
0250             m_containerGrp->checkedButton()->setChecked(false);
0251             m_containerGrp->setExclusive(true);
0252         }
0253     }
0254     emit updateTitleBars();
0255     return true;
0256 }
0257 
0258 std::pair<QString, QString> LayoutManagement::saveLayout(const QString &layout, const QString &suggestedName)
0259 {
0260 
0261     QString visibleName = translatedName(suggestedName);
0262 
0263     QString layoutName = QInputDialog::getText(pCore->window(), i18nc("@title:window", "Save Layout"), i18n("Layout name:"), QLineEdit::Normal, visibleName);
0264     if (layoutName.isEmpty()) {
0265         return {nullptr, nullptr};
0266     }
0267 
0268     QString saveName;
0269     if (m_translatedNames.contains(layoutName)) {
0270         saveName = m_translatedNames.key(layoutName);
0271     } else {
0272         saveName = layoutName;
0273     }
0274 
0275     KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("kdenlive-layoutsrc"));
0276     KConfigGroup layouts(config, "Layouts");
0277     KConfigGroup order(config, "Order");
0278 
0279     if (layouts.hasKey(saveName)) {
0280         // Layout already exists
0281         int res = KMessageBox::questionYesNo(pCore->window(), i18n("The layout %1 already exists. Do you want to replace it?", layoutName));
0282         if (res != KMessageBox::ButtonCode::Yes) {
0283             return {nullptr, nullptr};
0284         }
0285     }
0286 
0287     layouts.writeEntry(saveName, layout);
0288     if (!order.entryMap().values().contains(saveName)) {
0289         int pos = order.keyList().constLast().toInt() + 1;
0290         order.writeEntry(QString::number(pos), saveName);
0291     }
0292     return {layoutName, saveName};
0293 }
0294 
0295 void LayoutManagement::slotSaveLayout()
0296 {
0297     QAbstractButton *button = m_containerGrp->checkedButton();
0298     QString saveName;
0299     if (button) {
0300         saveName = button->text();
0301     }
0302 
0303     QByteArray st = pCore->window()->saveState();
0304     if (!pCore->window()->timelineVisible()) {
0305         st.prepend("NO-TL");
0306     }
0307     std::pair<QString, QString> names = saveLayout(st.toBase64(), saveName);
0308 
0309     // Activate layout button
0310     if (names.first != nullptr) {
0311         QList<QAbstractButton *> buttons = m_containerGrp->buttons();
0312         for (auto *button : qAsConst(buttons)) {
0313             if (button->text() == names.first) {
0314                 QSignalBlocker bk(m_containerGrp);
0315                 button->setChecked(true);
0316             }
0317         }
0318     }
0319 }
0320 
0321 void LayoutManagement::slotManageLayouts()
0322 {
0323     KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("kdenlive-layoutsrc"));
0324     KConfigGroup layouts(config, "Layouts");
0325     KConfigGroup order(config, "Order");
0326     QStringList names = order.entryMap().values();
0327     QString current;
0328     if (m_containerGrp->checkedButton()) {
0329         current = m_containerGrp->checkedButton()->text();
0330     }
0331     QDialog d(pCore->window());
0332     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
0333     auto *l = new QVBoxLayout;
0334     d.setLayout(l);
0335     l->addWidget(new QLabel(i18n("Current Layouts"), &d));
0336     QListWidget list(&d);
0337     list.setAlternatingRowColors(true);
0338     l->addWidget(&list);
0339     // Delete button
0340     QToolButton tb(&d);
0341     tb.setIcon(QIcon::fromTheme(QStringLiteral("edit-delete")));
0342     tb.setAutoRaise(true);
0343     connect(&tb, &QToolButton::clicked, this, [&layouts, &list]() {
0344         if (list.currentItem()) {
0345             layouts.deleteEntry(list.currentItem()->data(Qt::UserRole).toString());
0346             delete list.currentItem();
0347         }
0348     });
0349     tb.setToolTip(i18n("Delete the layout."));
0350     auto *l2 = new QHBoxLayout;
0351     l->addLayout(l2);
0352     l2->addWidget(&tb);
0353     // Up button
0354     QToolButton tb2(&d);
0355     tb2.setIcon(QIcon::fromTheme(QStringLiteral("go-up")));
0356     tb2.setAutoRaise(true);
0357     connect(&tb2, &QToolButton::clicked, this, [&list]() {
0358         if (list.currentItem() && list.currentRow() > 0) {
0359             int updatedRow = list.currentRow() - 1;
0360             QListWidgetItem *item = list.takeItem(list.currentRow());
0361             list.insertItem(updatedRow, item);
0362             list.setCurrentRow(updatedRow);
0363         }
0364     });
0365     l2->addWidget(&tb2);
0366 
0367     // Down button
0368     QToolButton tb3(&d);
0369     tb3.setIcon(QIcon::fromTheme(QStringLiteral("go-down")));
0370     tb3.setAutoRaise(true);
0371     connect(&tb3, &QToolButton::clicked, this, [&list]() {
0372         if (list.currentItem() && list.currentRow() < list.count() - 1) {
0373             int updatedRow = list.currentRow() + 1;
0374             QListWidgetItem *item = list.takeItem(list.currentRow());
0375             list.insertItem(updatedRow, item);
0376             list.setCurrentRow(updatedRow);
0377         }
0378     });
0379     l2->addWidget(&tb3);
0380 
0381     // Reset button
0382     QToolButton tb4(&d);
0383     tb4.setIcon(QIcon::fromTheme(QStringLiteral("view-refresh")));
0384     tb4.setAutoRaise(true);
0385     tb4.setToolTip(i18n("Reset"));
0386     connect(&tb4, &QToolButton::clicked, this, [this, &config, &list, &layouts, current]() {
0387         // Load default base layouts
0388         KConfig defaultConfig(QStringLiteral("kdenlivedefaultlayouts.rc"), KConfig::CascadeConfig, QStandardPaths::AppDataLocation);
0389         KConfigGroup defaultOrder(&defaultConfig, "Order");
0390         KConfigGroup defaultLayout(&defaultConfig, "Layouts");
0391         QStringList defaultLayoutNames = defaultOrder.entryMap().values();
0392         // Get list of current layouts
0393         QStringList currentNames;
0394         for (int i = 0; i < list.count(); i++) {
0395             currentNames << list.item(i)->data(Qt::UserRole).toString();
0396         }
0397         int pos = 0;
0398         // Reset selected layout if it is a default one
0399         if (list.currentItem()) {
0400             QString selectedName = list.currentItem()->data(Qt::UserRole).toString();
0401             if (defaultLayoutNames.contains(selectedName)) {
0402                 layouts.writeEntry(selectedName, defaultLayout.readEntry(selectedName));
0403                 if (!current.isEmpty() && selectedName == current) {
0404                     config->reparseConfiguration();
0405                     loadLayout(current, false);
0406                 }
0407             }
0408         }
0409 
0410         // Re-add missing default layouts
0411         for (const QString &name : qAsConst(defaultLayoutNames)) {
0412             if (!currentNames.contains(name) && m_translatedNames.contains(name)) {
0413                 // Insert default layout
0414                 QListWidgetItem *item = new QListWidgetItem(translatedName(name));
0415                 item->setData(Qt::UserRole, name);
0416                 item->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
0417                 list.insertItem(pos, item);
0418                 // Write layout data
0419                 layouts.writeEntry(name, defaultLayout.readEntry(name));
0420             }
0421             pos++;
0422         }
0423     });
0424     l2->addWidget(&tb4);
0425 
0426     // Import button
0427     QToolButton tb5(&d);
0428     tb5.setIcon(QIcon::fromTheme(QStringLiteral("document-import")));
0429     tb5.setAutoRaise(true);
0430     tb5.setToolTip(i18n("Import"));
0431     connect(&tb5, &QToolButton::clicked, this, [this, &d, &list]() {
0432         QScopedPointer<QFileDialog> fd(new QFileDialog(&d, i18nc("@title:window", "Load Layout")));
0433         fd->setMimeTypeFilters(QStringList() << QStringLiteral("application/kdenlivelayout"));
0434         fd->setFileMode(QFileDialog::ExistingFile);
0435         if (fd->exec() != QDialog::Accepted) {
0436             return;
0437         }
0438         QStringList selection = fd->selectedFiles();
0439         QString url;
0440         if (!selection.isEmpty()) {
0441             url = selection.first();
0442         }
0443         if (url.isEmpty()) {
0444             return;
0445         }
0446         QFile file(url);
0447         if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
0448             KMessageBox::error(&d, i18n("Cannot open file %1", QUrl::fromLocalFile(url).fileName()));
0449             return;
0450         }
0451         QString state = QString::fromUtf8(file.readAll());
0452         file.close();
0453 
0454         QFileInfo fileInfo(url);
0455         QString suggestedName(fileInfo.baseName());
0456 
0457         std::pair<QString, QString> names = saveLayout(state, suggestedName);
0458 
0459         if (names.first != nullptr && names.second != nullptr && list.findItems(names.first, Qt::MatchFlag::MatchExactly).length() == 0) {
0460             auto *item = new QListWidgetItem(names.first, &list);
0461             item->setData(Qt::UserRole, names.second);
0462             item->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
0463         }
0464     });
0465     l2->addWidget(&tb5);
0466 
0467     // Export selected button
0468     QToolButton tb6(&d);
0469     tb6.setIcon(QIcon::fromTheme(QStringLiteral("document-export")));
0470     tb6.setAutoRaise(true);
0471     tb6.setToolTip(i18n("Export selected"));
0472     connect(&tb6, &QToolButton::clicked, this, [&d, &list]() {
0473         if (!list.currentItem()) {
0474             // Error, no layout selected
0475             KMessageBox::error(&d, i18n("No layout selected"));
0476             return;
0477         }
0478 
0479         QListWidgetItem *item = list.item(list.currentRow());
0480         QString layoutId = item->data(Qt::UserRole).toString();
0481 
0482         KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("kdenlive-layoutsrc"));
0483         KConfigGroup layouts(config, "Layouts");
0484         if (!layouts.hasKey(layoutId)) {
0485             // Error, layout not found
0486             KMessageBox::error(&d, i18n("Cannot find layout %1", layoutId));
0487             return;
0488         }
0489 
0490         QScopedPointer<QFileDialog> fd(new QFileDialog(&d, i18nc("@title:window", "Export Layout")));
0491         fd->setMimeTypeFilters(QStringList() << QStringLiteral("application/kdenlivelayout"));
0492         fd->selectFile(layoutId + ".kdenlivelayout");
0493         fd->setDefaultSuffix(QStringLiteral("kdenlivelayout"));
0494         fd->setFileMode(QFileDialog::AnyFile);
0495         fd->setAcceptMode(QFileDialog::AcceptSave);
0496         if (fd->exec() != QDialog::Accepted) {
0497             return;
0498         }
0499         QStringList selection = fd->selectedFiles();
0500         QString url;
0501         if (!selection.isEmpty()) {
0502             url = selection.first();
0503         }
0504         if (url.isEmpty()) {
0505             return;
0506         }
0507         QFile file(url);
0508         if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
0509             KMessageBox::error(&d, i18n("Cannot open file %1", QUrl::fromLocalFile(url).fileName()));
0510             return;
0511         }
0512         file.write(layouts.readEntry(layoutId).toUtf8());
0513         file.close();
0514     });
0515     l2->addWidget(&tb6);
0516 
0517     connect(&list, &QListWidget::currentRowChanged, this, [&list, &tb2, &tb3](int row) {
0518         tb2.setEnabled(row > 0);
0519         tb3.setEnabled(row < list.count() - 1);
0520     });
0521 
0522     l2->addStretch();
0523 
0524     // Add layouts to list
0525     for (const QString &name : qAsConst(names)) {
0526         auto *item = new QListWidgetItem(translatedName(name), &list);
0527         item->setData(Qt::UserRole, name);
0528         item->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
0529     }
0530     int ix = 0;
0531     if (!current.isEmpty()) {
0532         QList<QListWidgetItem *> res = list.findItems(current, Qt::MatchExactly);
0533         if (!res.isEmpty()) {
0534             ix = list.row(res.first());
0535         }
0536     }
0537     list.setCurrentRow(ix);
0538     l->addWidget(buttonBox);
0539     d.connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
0540     d.connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
0541     if (d.exec() != QDialog::Accepted) {
0542         return;
0543     }
0544     // Reset order
0545     order.deleteGroup();
0546     // Update order and new names
0547     for (int i = 0; i < list.count(); i++) {
0548         QListWidgetItem *item = list.item(i);
0549         QString layoutId = item->data(Qt::UserRole).toString();
0550         if (m_translatedNames.contains(layoutId)) {
0551             // This is a default layout, no rename
0552             if (item->text() != translatedName(layoutId)) {
0553                 // A default layout was renamed
0554                 order.writeEntry(QString::number(i + 1), item->text());
0555                 layouts.writeEntry(item->text(), layouts.readEntry(layoutId));
0556                 layouts.deleteEntry(layoutId);
0557             } else {
0558                 order.writeEntry(QString::number(i + 1), layoutId);
0559             }
0560             continue;
0561         }
0562         order.writeEntry(QString::number(i + 1), layoutId);
0563         if (item->text() != layoutId && !item->text().isEmpty()) {
0564             layouts.writeEntry(item->text(), layouts.readEntry(layoutId));
0565             layouts.deleteEntry(layoutId);
0566         }
0567     }
0568     config->reparseConfiguration();
0569     initializeLayouts();
0570 }
0571 
0572 const QString LayoutManagement::translatedName(const QString &name)
0573 {
0574     return m_translatedNames.contains(name) ? m_translatedNames.constFind(name).value() : name;
0575 }
0576 
0577 void LayoutManagement::slotDockAreaRows()
0578 {
0579     // Use the corners for top and bottom DockWidgetArea
0580     pCore->window()->setCorner(Qt::TopRightCorner, Qt::TopDockWidgetArea);
0581     pCore->window()->setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
0582     pCore->window()->setCorner(Qt::TopLeftCorner, Qt::TopDockWidgetArea);
0583     pCore->window()->setCorner(Qt::BottomLeftCorner, Qt::BottomDockWidgetArea);
0584 }
0585 
0586 void LayoutManagement::slotDockAreaColumns()
0587 {
0588     // Use the corners for left and right DockWidgetArea
0589     pCore->window()->setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
0590     pCore->window()->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
0591     pCore->window()->setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
0592     pCore->window()->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
0593 }