diff --git a/app/settings/controllers/layoutscontroller.cpp b/app/settings/controllers/layoutscontroller.cpp index 93e4f11b..110bce36 100644 --- a/app/settings/controllers/layoutscontroller.cpp +++ b/app/settings/controllers/layoutscontroller.cpp @@ -1,958 +1,963 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "layoutscontroller.h" // local #include "ui_settingsdialog.h" #include "../universalsettings.h" #include "../dialogs/settingsdialog.h" #include "../data/uniqueidinfo.h" #include "../delegates/activitiesdelegate.h" #include "../delegates/backgroundcmbdelegate.h" #include "../delegates/checkboxdelegate.h" #include "../delegates/layoutnamedelegate.h" #include "../delegates/shareddelegate.h" #include "../handlers/tablayoutshandler.h" #include "../tools/settingstools.h" #include "../../layout/genericlayout.h" #include "../../layout/centrallayout.h" #include "../../layout/sharedlayout.h" #include "../../layouts/importer.h" #include "../../layouts/manager.h" #include "../../layouts/synchronizer.h" // Qt #include #include #include #include #include #include // KDE #include #include #include #include namespace Latte { namespace Settings { namespace Controller { Layouts::Layouts(Settings::Handler::TabLayouts *parent) : QObject(parent), m_handler(parent), m_model(new Model::Layouts(this, m_handler->corona())), m_proxyModel(new QSortFilterProxyModel(this)), m_view(m_handler->ui()->layoutsView), m_headerView(new Settings::Layouts::HeaderView(Qt::Horizontal, m_handler->dialog())), m_storage(KConfigGroup(KSharedConfig::openConfig(),"LatteSettingsDialog").group("TabLayouts")) { loadConfig(); m_proxyModel->setSourceModel(m_model); connect(m_model, &Model::Layouts::inMultipleModeChanged, this, &Layouts::updateLastColumnWidth); connect(m_model, &QAbstractItemModel::dataChanged, this, &Layouts::dataChanged); connect(m_model, &Model::Layouts::rowsInserted, this, &Layouts::dataChanged); connect(m_model, &Model::Layouts::rowsRemoved, this, &Layouts::dataChanged); connect(m_model, &Model::Layouts::nameDuplicated, this, &Layouts::on_nameDuplicatedFrom); connect(m_headerView, &QObject::destroyed, this, [&]() { m_viewSortColumn = m_headerView->sortIndicatorSection(); m_viewSortOrder = m_headerView->sortIndicatorOrder(); }); initView(); loadLayouts(); } Layouts::~Layouts() { saveConfig(); //! remove qDeleteAll(m_layouts); for (const auto &tempDir : m_tempDirectories) { QDir tDir(tempDir); if (tDir.exists() && tempDir.startsWith("/tmp/")) { tDir.removeRecursively(); } } } QAbstractItemModel *Layouts::model() const { return m_proxyModel; } QTableView *Layouts::view() const { return m_view; } void Layouts::initView() { m_view->setModel(m_proxyModel); m_view->setHorizontalHeader(m_headerView); m_view->horizontalHeader()->setStretchLastSection(true); m_view->verticalHeader()->setVisible(false); m_view->setSortingEnabled(true); m_proxyModel->setSortRole(Model::Layouts::SORTINGROLE); m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); m_view->sortByColumn(m_viewSortColumn, m_viewSortOrder); //!find the available colors m_iconsPath = m_handler->corona()->kPackage().path() + "../../plasmoids/org.kde.latte.containment/contents/icons/"; m_model->setIconsPath(m_iconsPath); QDir layoutDir(m_iconsPath); QStringList filter; filter.append(QString("*print.jpg")); QStringList files = layoutDir.entryList(filter, QDir::Files | QDir::NoSymLinks); QStringList colors; for (auto &file : files) { int colorEnd = file.lastIndexOf("print.jpg"); QString color = file.remove(colorEnd, 9); colors.append(color); } m_view->setItemDelegateForColumn(Model::Layouts::NAMECOLUMN, new Settings::Layout::Delegate::LayoutName(this)); m_view->setItemDelegateForColumn(Model::Layouts::BACKGROUNDCOLUMN, new Settings::Layout::Delegate::BackgroundCmbBox(this, m_iconsPath, colors)); m_view->setItemDelegateForColumn(Model::Layouts::MENUCOLUMN, new Settings::Layout::Delegate::CheckBox(this)); m_view->setItemDelegateForColumn(Model::Layouts::BORDERSCOLUMN, new Settings::Layout::Delegate::CheckBox(this)); m_view->setItemDelegateForColumn(Model::Layouts::ACTIVITYCOLUMN, new Settings::Layout::Delegate::Activities(this)); m_view->setItemDelegateForColumn(Model::Layouts::SHAREDCOLUMN, new Settings::Layout::Delegate::Shared(this)); connect(m_view, &QObject::destroyed, this, &Controller::Layouts::storeColumnWidths); } bool Layouts::dataAreChanged() const { return m_model->dataAreChanged(); } bool Layouts::hasSelectedLayout() const { int selectedRow = m_view->currentIndex().row(); return (selectedRow >= 0); } bool Layouts::selectedLayoutIsCurrentActive() const { Settings::Data::Layout selectedLayoutCurrent = selectedLayoutCurrentData(); Settings::Data::Layout selectedLayoutOriginal = selectedLayoutOriginalData(); selectedLayoutOriginal = selectedLayoutOriginal.isEmpty() ? selectedLayoutCurrent : selectedLayoutOriginal; return (selectedLayoutCurrent.isActive && (selectedLayoutOriginal.name == m_handler->corona()->layoutsManager()->currentLayoutName())); } QString Layouts::colorPath(const QString color) const { QString path = m_iconsPath + color + "print.jpg"; if (!QFileInfo(path).exists()) { return m_iconsPath + "blueprint.jpg"; } return path; } QString Layouts::iconsPath() const { return m_iconsPath; } const Data::Layout Layouts::selectedLayoutCurrentData() const { int selectedRow = m_view->currentIndex().row(); if (selectedRow >= 0) { QString selectedId = m_proxyModel->data(m_proxyModel->index(selectedRow, Model::Layouts::IDCOLUMN), Qt::UserRole).toString(); return m_model->currentData(selectedId); } else { return Data::Layout(); } } const Data::Layout Layouts::selectedLayoutOriginalData() const { int selectedRow = m_view->currentIndex().row(); QString selectedId = m_proxyModel->data(m_proxyModel->index(selectedRow, Model::Layouts::IDCOLUMN), Qt::UserRole).toString(); return m_model->originalData(selectedId);; } bool Layouts::inMultipleMode() const { return m_model->inMultipleMode(); } void Layouts::setInMultipleMode(bool inMultiple) { m_model->setInMultipleMode(inMultiple); } void Layouts::updateLastColumnWidth() { if (m_model->inMultipleMode()) { m_view->setColumnHidden(Model::Layouts::SHAREDCOLUMN, false); //! column widths if (m_viewColumnWidths.count()>=5) { m_view->setColumnWidth(Model::Layouts::ACTIVITYCOLUMN, m_viewColumnWidths[4].toInt()); } } else { m_view->setColumnHidden(Model::Layouts::SHAREDCOLUMN, true); } } int Layouts::rowForId(QString id) const { for (int i = 0; i < m_proxyModel->rowCount(); ++i) { QString rowId = m_proxyModel->data(m_proxyModel->index(i, Model::Layouts::IDCOLUMN), Qt::UserRole).toString(); if (rowId == id) { return i; } } return -1; } int Layouts::rowForName(QString layoutName) const { for (int i = 0; i < m_proxyModel->rowCount(); ++i) { QString rowName = m_proxyModel->data(m_proxyModel->index(i, Model::Layouts::NAMECOLUMN), Qt::UserRole).toString(); if (rowName == layoutName) { return i; } } return -1; } QString Layouts::uniqueTempDirectory() { QTemporaryDir tempDir; tempDir.setAutoRemove(false); m_tempDirectories.append(tempDir.path()); return tempDir.path(); } QString Layouts::uniqueLayoutName(QString name) { int pos_ = name.lastIndexOf(QRegExp(QString(" - [0-9]+"))); if (m_model->containsCurrentName(name) && pos_ > 0) { name = name.left(pos_); } int i = 2; QString namePart = name; while (m_model->containsCurrentName(name)) { name = namePart + " - " + QString::number(i); i++; } return name; } void Layouts::removeSelected() { if (m_view->currentIndex().row() < 0) { return; } Data::Layout selectedOriginal = selectedLayoutOriginalData(); if (m_handler->corona()->layoutsManager()->synchronizer()->layout(selectedOriginal.name)) { return; } int row = m_view->currentIndex().row(); row = qMin(row, m_proxyModel->rowCount() - 1); m_view->selectRow(row); Data::Layout selected = selectedLayoutCurrentData(); m_model->removeLayout(selected.id); } void Layouts::toggleLockedForSelected() { if (!hasSelectedLayout()) { return; } Data::Layout selected = selectedLayoutCurrentData(); m_proxyModel->setData(m_proxyModel->index(m_view->currentIndex().row(), Model::Layouts::NAMECOLUMN), !selected.isLocked, Settings::Model::Layouts::ISLOCKEDROLE); } void Layouts::toggleSharedForSelected() { if (!hasSelectedLayout()) { return; } int row = m_view->currentIndex().row(); Data::Layout selected = selectedLayoutCurrentData(); if (selected.isShared()) { m_proxyModel->setData(m_proxyModel->index(row, Model::Layouts::SHAREDCOLUMN), QStringList(), Qt::UserRole); } else { QStringList assignedIds; QStringList availableShareIds = m_model->availableShareIdsFor(selected.id); for (const auto &id : availableShareIds) { Data::Layout iLayoutCurrent = m_model->currentData(id); Data::Layout iLayoutOriginal = m_model->originalData(id); iLayoutOriginal = iLayoutOriginal.isEmpty() ? iLayoutCurrent : iLayoutOriginal; if (m_handler->corona()->layoutsManager()->synchronizer()->layout(iLayoutOriginal.name)) { assignedIds << id; m_proxyModel->setData(m_proxyModel->index(row, Model::Layouts::SHAREDCOLUMN), assignedIds, Qt::UserRole); break; } } if (assignedIds.isEmpty() && availableShareIds.count()>0) { assignedIds << availableShareIds[0]; m_proxyModel->setData(m_proxyModel->index(row, Model::Layouts::SHAREDCOLUMN), assignedIds, Qt::UserRole); } } } void Layouts::selectRow(int index) { m_view->selectRow(index); } +void Layouts::setLayoutProperties(const Data::Layout &layout) +{ + m_model->setLayoutProperties(layout); +} + QString Layouts::layoutNameForFreeActivities() const { return m_model->layoutNameForFreeActivities(); } void Layouts::setOriginalLayoutForFreeActivities(const QString &id) { m_model->setOriginalLayoutForFreeActivities(id); emit dataChanged(); } void Layouts::loadLayouts() { m_model->clear(); bool inMultiple{m_handler->corona()->layoutsManager()->memoryUsage() == Types::MultipleLayouts}; setInMultipleMode(inMultiple); //! The shares map needs to be constructed for start/scratch. //! We start feeding information with layout_names and during the process //! we update them to valid layout_ids Latte::Layouts::SharesMap sharesMap; int i = 0; QStringList brokenLayouts; if (m_handler->corona()->layoutsManager()->memoryUsage() == Types::MultipleLayouts) { m_handler->corona()->layoutsManager()->synchronizer()->syncActiveLayoutsToOriginalFiles(); } Settings::Data::LayoutsTable layoutsBuffer; for (const auto layout : m_handler->corona()->layoutsManager()->layouts()) { Settings::Data::Layout original; original.id = QDir::homePath() + "/.config/latte/" + layout + ".layout.latte"; CentralLayout *central = new CentralLayout(this, original.id); original.name = central->name(); original.backgroundStyle = central->backgroundStyle(); original.color = central->color(); original.background = central->customBackground(); original.textColor = central->customTextColor(); original.isActive = (m_handler->corona()->layoutsManager()->synchronizer()->layout(original.name) != nullptr); original.isLocked = !central->isWritable(); original.isShownInMenu = central->showInMenu(); original.hasDisabledBorders = central->disableBordersForMaximizedWindows(); original.activities = central->activities(); m_layouts[original.id] = central; //! create initial SHARES maps QString shared = central->sharedLayoutName(); if (!shared.isEmpty()) { sharesMap[shared].append(original.id); } layoutsBuffer << original; qDebug() << "counter:" << i << " total:" << m_model->rowCount(); i++; Latte::Layout::GenericLayout *generic = m_handler->corona()->layoutsManager()->synchronizer()->layout(central->name()); if ((generic && generic->layoutIsBroken()) || (!generic && central->layoutIsBroken())) { brokenLayouts.append(central->name()); } } //! update SHARES map keys in order to use the #settingsid(s) QStringList tempSharedNames; //! remove these records after updating for (QHash::iterator i=sharesMap.begin(); i!=sharesMap.end(); ++i) { tempSharedNames << i.key(); } //! update keys for (QHash::iterator i=sharesMap.begin(); i!=sharesMap.end(); ++i) { QString shareid = layoutsBuffer.idForName(i.key()); if (!shareid.isEmpty()) { sharesMap[shareid] = i.value(); } } //! remove deprecated keys for (const auto &key : tempSharedNames) { sharesMap.remove(key); } qDebug() << "SHARES MAP ::: " << sharesMap; for (QHash::iterator i=sharesMap.begin(); i!=sharesMap.end(); ++i) { layoutsBuffer[i.key()].shares = i.value(); } //! Send original loaded data to model m_model->setOriginalData(layoutsBuffer, inMultiple); m_model->setOriginalLayoutForFreeActivities(layoutsBuffer.idForName(m_handler->corona()->universalSettings()->lastNonAssignedLayoutName())); m_view->selectRow(rowForName(m_handler->corona()->layoutsManager()->currentLayoutName())); //! this line should be commented for debugging layouts window functionality m_view->setColumnHidden(Model::Layouts::IDCOLUMN, true); m_view->setColumnHidden(Model::Layouts::HIDDENTEXTCOLUMN, true); if (m_handler->corona()->universalSettings()->canDisableBorders()) { m_view->setColumnHidden(Model::Layouts::BORDERSCOLUMN, false); } else { m_view->setColumnHidden(Model::Layouts::BORDERSCOLUMN, true); } m_view->resizeColumnsToContents(); if (!m_viewColumnWidths.isEmpty()) { int lastColumn = inMultiple ? 5 : 4; for (int i=0; isetColumnWidth(Model::Layouts::BACKGROUNDCOLUMN+i, m_viewColumnWidths[i].toInt()); } } updateLastColumnWidth(); //! there are broken layouts and the user must be informed! if (brokenLayouts.count() > 0) { if (brokenLayouts.count() == 1) { m_handler->showInlineMessage(i18nc("settings:broken layout", "Layout %0 is broken! Please remove to improve stability...").arg(brokenLayouts.join(",")), KMessageWidget::Error, true); } else { m_handler->showInlineMessage(i18nc("settings:broken layouts", "Layouts %0 are broken! Please remove to improve stability...").arg(brokenLayouts.join(",")), KMessageWidget::Error, true); } } } const Data::Layout Layouts::addLayoutForFile(QString file, QString layoutName, bool newTempDirectory) { if (layoutName.isEmpty()) { layoutName = CentralLayout::layoutName(file); } layoutName = uniqueLayoutName(layoutName); Data::Layout copied; if (newTempDirectory) { copied.id = uniqueTempDirectory() + "/" + layoutName + ".layout.latte"; QFile(file).copy(copied.id); } else { copied.id = file; } QFileInfo newFileInfo(copied.id); if (newFileInfo.exists() && !newFileInfo.isWritable()) { QFile(copied.id).setPermissions(QFileDevice::ReadUser | QFileDevice::WriteUser | QFileDevice::ReadGroup | QFileDevice::ReadOther); } if (m_layouts.contains(copied.id)) { CentralLayout *oldSettings = m_layouts.take(copied.id); delete oldSettings; } CentralLayout *settings = new CentralLayout(this, copied.id); m_layouts[copied.id] = settings; copied.name = uniqueLayoutName(layoutName); copied.backgroundStyle = settings->backgroundStyle(); copied.color = settings->color(); copied.textColor = settings->customTextColor(); copied.background = settings->customBackground(); copied.isLocked = !settings->isWritable(); copied.isShownInMenu = settings->showInMenu(); copied.hasDisabledBorders = settings->disableBordersForMaximizedWindows(); m_model->appendLayout(copied); m_view->selectRow(rowForId(copied.id)); return copied; } void Layouts::copySelectedLayout() { int row = m_view->currentIndex().row(); if (row < 0) { return; } Settings::Data::Layout selectedLayoutCurrent = selectedLayoutCurrentData(); Settings::Data::Layout selectedLayoutOriginal = selectedLayoutOriginalData(); selectedLayoutOriginal = selectedLayoutOriginal.isEmpty() ? selectedLayoutCurrent : selectedLayoutOriginal; //! Update original layout before copying if this layout is active if (m_handler->corona()->layoutsManager()->memoryUsage() == Types::MultipleLayouts) { Latte::Layout::GenericLayout *generic = m_handler->corona()->layoutsManager()->synchronizer()->layout(selectedLayoutOriginal.name); if (generic) { generic->syncToLayoutFile(); } } Settings::Data::Layout copied = selectedLayoutCurrent; copied.name = uniqueLayoutName(selectedLayoutCurrent.name); copied.id = uniqueTempDirectory() + "/" + copied.name + ".layout.latte";; copied.isActive = false; copied.isLocked = false; copied.activities = QStringList(); copied.shares = QStringList(); QFile(selectedLayoutCurrent.id).copy(copied.id); QFileInfo newFileInfo(copied.id); if (newFileInfo.exists() && !newFileInfo.isWritable()) { QFile(copied.id).setPermissions(QFileDevice::ReadUser | QFileDevice::WriteUser | QFileDevice::ReadGroup | QFileDevice::ReadOther); } CentralLayout *settings = new CentralLayout(this, copied.id); settings->clearLastUsedActivity(); m_layouts[copied.id] = settings; m_model->appendLayout(copied); m_view->selectRow(rowForId(copied.id)); } bool Layouts::importLayoutsFromV1ConfigFile(QString file) { KTar archive(file, QStringLiteral("application/x-tar")); archive.open(QIODevice::ReadOnly); //! if the file isnt a tar archive if (archive.isOpen()) { QDir tempDir{uniqueTempDirectory()}; const auto archiveRootDir = archive.directory(); for (const auto &name : archiveRootDir->entries()) { auto fileEntry = archiveRootDir->file(name); fileEntry->copyTo(tempDir.absolutePath()); } QString name = Latte::Layouts::Importer::nameOfConfigFile(file); QString applets(tempDir.absolutePath() + "/" + "lattedock-appletsrc"); if (QFile(applets).exists()) { QStringList importedlayouts; if (m_handler->corona()->layoutsManager()->importer()->importOldLayout(applets, name, false, tempDir.absolutePath())) { Settings::Data::Layout imported = addLayoutForFile(tempDir.absolutePath() + "/" + name + ".layout.latte", name); importedlayouts << imported.name; } QString alternativeName = name + "-" + i18nc("layout", "Alternative"); if (m_handler->corona()->layoutsManager()->importer()->importOldLayout(applets, alternativeName, false, tempDir.absolutePath())) { Settings::Data::Layout imported = addLayoutForFile(tempDir.absolutePath() + "/" + alternativeName + ".layout.latte", alternativeName, false); importedlayouts << imported.name; } if (importedlayouts.count() > 0) { if (importedlayouts.count() == 1) { m_handler->showInlineMessage(i18n("Layout %0 imported successfully...").arg(importedlayouts[0]), KMessageWidget::Information); } else { m_handler->showInlineMessage(i18n("Layouts %0 imported successfully...").arg(importedlayouts.join(",")), KMessageWidget::Information); } return true; } } } return false; } void Layouts::on_sharedToInEditChanged(const QString &id, const bool &inEdit) { int row = m_model->rowForId(id); if (row >= 0) { m_model->setData(m_model->index(row, Model::Layouts::SHAREDCOLUMN), inEdit, Model::Layouts::SHAREDTOINEDITROLE); } } void Layouts::reset() { m_model->resetData(); m_view->selectRow(rowForName(m_handler->corona()->layoutsManager()->currentLayoutName())); } void Layouts::save() { //! Update Layouts QStringList knownActivities = m_handler->corona()->layoutsManager()->synchronizer()->activities(); QTemporaryDir layoutTempDir; qDebug() << "Temporary Directory ::: " << layoutTempDir.path(); QString switchToLayout; QHash activeLayoutsToRename; Settings::Data::LayoutsTable originalLayouts = m_model->originalLayoutsData(); Settings::Data::LayoutsTable currentLayouts = m_model->currentLayoutsData(); Settings::Data::LayoutsTable removedLayouts = originalLayouts.subtracted(currentLayouts); //! remove layouts that have been removed from the user for (int i=0; i alteredIdsInfo; QList alteredLayouts = m_model->alteredLayouts(); for (int i = 0; i < alteredLayouts.count(); ++i) { Data::Layout iLayoutCurrentData = alteredLayouts[i]; Data::Layout iLayoutOriginalData = m_model->originalData(iLayoutCurrentData.id); iLayoutOriginalData = iLayoutOriginalData.isEmpty() ? iLayoutCurrentData : iLayoutOriginalData; QStringList cleanedActivities; //!update only activities that are valid for (const auto &activity : iLayoutCurrentData.activities) { if (knownActivities.contains(activity) && activity != Settings::Data::Layout::FREEACTIVITIESID) { cleanedActivities.append(activity); } } //qDebug() << i << ". " << id << " - " << color << " - " << name << " - " << menu << " - " << lActivities; //! update the generic parts of the layouts bool isOriginalLayout = m_model->originalLayoutsData().containsId(iLayoutCurrentData.id); Latte::Layout::GenericLayout *genericActive= isOriginalLayout ? m_handler->corona()->layoutsManager()->synchronizer()->layout(iLayoutOriginalData.name) : nullptr; Latte::Layout::GenericLayout *generic = genericActive ? genericActive : m_layouts[iLayoutCurrentData.id]; //! unlock read-only layout if (!generic->isWritable()) { generic->unlock(); } /* if (iLayoutCurrentData.color.startsWith("/")) { //it is image file in such case if (iLayoutCurrentData.color != generic->background()) { generic->setBackground(iLayoutCurrentData.color); } if (generic->textColor() != iLayoutCurrentData.textColor) { generic->setTextColor(iLayoutCurrentData.textColor); } } else { if (iLayoutCurrentData.color != generic->color()) { generic->setColor(iLayoutCurrentData.color); generic->setBackground(QString()); generic->setTextColor(QString()); } }*/ //! update only the Central-specific layout parts CentralLayout *centralActive = isOriginalLayout ? m_handler->corona()->layoutsManager()->synchronizer()->centralLayout(iLayoutOriginalData.name) : nullptr; CentralLayout *central = centralActive ? centralActive : m_layouts[iLayoutCurrentData.id]; if (central->showInMenu() != iLayoutCurrentData.isShownInMenu) { central->setShowInMenu(iLayoutCurrentData.isShownInMenu); } if (central->disableBordersForMaximizedWindows() != iLayoutCurrentData.hasDisabledBorders) { central->setDisableBordersForMaximizedWindows(iLayoutCurrentData.hasDisabledBorders); } if (central->activities() != cleanedActivities) { central->setActivities(cleanedActivities); } //! If the layout name changed OR the layout path is a temporary one if ((iLayoutCurrentData.name != iLayoutOriginalData.name) || iLayoutCurrentData.isTemporary()) { //! If the layout is Active in MultipleLayouts if (m_handler->corona()->layoutsManager()->memoryUsage() == Types::MultipleLayouts && generic->isActive()) { qDebug() << " Active Layout Should Be Renamed From : " << generic->name() << " TO :: " << iLayoutCurrentData.name; activeLayoutsToRename[iLayoutCurrentData.name] = generic; } QString tempFile = layoutTempDir.path() + "/" + QString(generic->name() + ".layout.latte"); qDebug() << "new temp file ::: " << tempFile; if ((m_handler->corona()->layoutsManager()->memoryUsage() == Types::SingleLayout) && (generic->name() == m_handler->corona()->layoutsManager()->currentLayoutName())) { switchToLayout = iLayoutCurrentData.name; } generic = m_layouts.take(iLayoutCurrentData.id); delete generic; QFile(iLayoutCurrentData.id).rename(tempFile); Data::UniqueIdInfo idInfo; idInfo.oldId = iLayoutCurrentData.id; idInfo.newId = tempFile; idInfo.newName = iLayoutCurrentData.name; alteredIdsInfo << idInfo; } } //! this is necessary in case two layouts have to swap names //! so we copy first the layouts in a temp directory and afterwards all //! together we move them in the official layout directory for (int i = 0; i < alteredIdsInfo.count(); ++i) { Data::UniqueIdInfo idInfo = alteredIdsInfo[i]; QString newFile = QDir::homePath() + "/.config/latte/" + idInfo.newName + ".layout.latte"; QFile(idInfo.newId).rename(newFile); CentralLayout *nLayout = new CentralLayout(this, newFile); m_layouts[newFile] = nLayout; //! updating the #SETTINGSID in the model for the layout that was renamed for (int j = 0; j < m_model->rowCount(); ++j) { Data::Layout jLayout = m_model->at(j); if (jLayout.id == idInfo.oldId) { m_model->setData(m_model->index(j, Model::Layouts::IDCOLUMN), newFile, Qt::UserRole); } } } if (m_handler->corona()->layoutsManager()->memoryUsage() == Types::MultipleLayouts) { for (const auto &newLayoutName : activeLayoutsToRename.keys()) { Latte::Layout::GenericLayout *layoutPtr = activeLayoutsToRename[newLayoutName]; qDebug() << " Active Layout of Type: " << layoutPtr->type() << " Is Renamed From : " << activeLayoutsToRename[newLayoutName]->name() << " TO :: " << newLayoutName; layoutPtr->renameLayout(newLayoutName); } } //! lock layouts in the end when the user has chosen it for (int i = 0; i < alteredLayouts.count(); ++i) { Data::Layout layoutCurrentData = alteredLayouts[i]; Data::Layout layoutOriginalData = m_model->originalData(layoutCurrentData.id); layoutOriginalData = layoutOriginalData.isEmpty() ? layoutCurrentData : layoutOriginalData; Latte::Layout::GenericLayout *layoutPtr = m_handler->corona()->layoutsManager()->synchronizer()->layout(layoutOriginalData.name); if (!layoutPtr && m_layouts.contains(layoutCurrentData.id)) { layoutPtr = m_layouts[layoutCurrentData.id]; } if (layoutCurrentData.isLocked && layoutPtr && layoutPtr->isWritable()) { layoutPtr->lock(); } } //! update SharedLayouts that are Active syncActiveShares(); //! reload layouts in layoutsmanager m_handler->corona()->layoutsManager()->synchronizer()->loadLayouts(); if (!m_model->layoutNameForFreeActivities().isEmpty()) { //! make sure that there is a layout for free activities //! send to layout manager in which layout to switch Latte::Types::LayoutsMemoryUsage inMemoryOption = Latte::Types::SingleLayout; if (inMultipleMode()) { inMemoryOption = Latte::Types::MultipleLayouts; } if (m_handler->corona()->layoutsManager()->memoryUsage() != inMemoryOption) { Types::LayoutsMemoryUsage previousMemoryUsage = m_handler->corona()->layoutsManager()->memoryUsage(); m_handler->corona()->layoutsManager()->setMemoryUsage(inMemoryOption); m_handler->corona()->layoutsManager()->switchToLayout(m_model->layoutNameForFreeActivities(), previousMemoryUsage); } else { if (m_handler->corona()->layoutsManager()->memoryUsage() == Types::MultipleLayouts) { m_handler->corona()->layoutsManager()->synchronizer()->syncMultipleLayoutsToActivities(m_model->layoutNameForFreeActivities()); } else { m_handler->corona()->layoutsManager()->switchToLayout(m_model->layoutNameForFreeActivities()); } } } m_model->applyData(); emit dataChanged(); } void Layouts::syncActiveShares() { if (m_handler->corona()->layoutsManager()->memoryUsage() != Types::MultipleLayouts) { return; } Settings::Data::LayoutsTable currentLayoutsData = m_model->currentLayoutsData(); Settings::Data::LayoutsTable originalLayoutsData = m_model->originalLayoutsData(); Latte::Layouts::SharesMap currentSharesNamesMap = currentLayoutsData.sharesMap(); QStringList originalSharesIds = originalLayoutsData.allSharesIds(); QStringList currentSharesIds = currentLayoutsData.allSharesIds(); QStringList deprecatedSharesIds = Latte::subtracted(originalSharesIds, currentSharesIds); QStringList deprecatedSharesNames; for(int i=0; icorona()->layoutsManager()->synchronizer()->syncActiveShares(currentSharesNamesMap, deprecatedSharesNames); } void Layouts::storeColumnWidths() { //! save column widths m_viewColumnWidths.clear(); m_viewColumnWidths << QString::number(m_view->columnWidth(Model::Layouts::BACKGROUNDCOLUMN)); m_viewColumnWidths << QString::number(m_view->columnWidth(Model::Layouts::NAMECOLUMN)); m_viewColumnWidths << QString::number(m_view->columnWidth(Model::Layouts::MENUCOLUMN)); m_viewColumnWidths << QString::number(m_view->columnWidth(Model::Layouts::BORDERSCOLUMN)); if (inMultipleMode()) { m_viewColumnWidths << QString::number(m_view->columnWidth(Model::Layouts::ACTIVITYCOLUMN)); } else { //! In Single Mode, keed recorded value for ACTIVITYCOLUMN if (m_viewColumnWidths.count()>=5) { m_viewColumnWidths << m_viewColumnWidths[4]; } } } void Layouts::on_nameDuplicatedFrom(const QString &provenId, const QString &trialId) { //! duplicated layout name int pRow = rowForId(provenId); int tRow = rowForId(trialId); int originalRow = m_model->rowForId(provenId); Data::Layout provenLayout = m_model->at(originalRow); m_handler->showInlineMessage(i18nc("settings: layout name used","Layout %0 is already used, please provide a different name...").arg(provenLayout.name), KMessageWidget::Error); QModelIndex tIndex = m_proxyModel->index(tRow, Model::Layouts::NAMECOLUMN); //! avoid losing focuse QTimer::singleShot(0, [this, tIndex]() { m_view->edit(tIndex); }); } void Layouts::loadConfig() { //! remove old unneeded oprtions KConfigGroup deprecatedStorage(KConfigGroup(KSharedConfig::openConfig(), "UniversalSettings")); QStringList columnWidths = deprecatedStorage.readEntry("layoutsColumnWidths", QStringList()); if (!columnWidths.isEmpty()) { //! migrating m_viewColumnWidths = columnWidths; } else { //! new storage m_viewColumnWidths = m_storage.readEntry("columnWidths", QStringList()); m_viewSortColumn = m_storage.readEntry("sortColumn", (int)Model::Layouts::NAMECOLUMN); m_viewSortOrder = static_cast(m_storage.readEntry("sortOrder", (int)Qt::AscendingOrder)); } } void Layouts::saveConfig() { m_storage.writeEntry("columnWidths", m_viewColumnWidths); m_storage.writeEntry("sortColumn", m_viewSortColumn); m_storage.writeEntry("sortOrder", (int)m_viewSortOrder); } } } } diff --git a/app/settings/controllers/layoutscontroller.h b/app/settings/controllers/layoutscontroller.h index 22e90b0e..efb56791 100644 --- a/app/settings/controllers/layoutscontroller.h +++ b/app/settings/controllers/layoutscontroller.h @@ -1,150 +1,151 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef SETTINGSLAYOUTSCONTROLLER_H #define SETTINGSLAYOUTSCONTROLLER_H // local #include "../data/layoutdata.h" #include "../data/layoutstable.h" #include "../views/layoutsheaderview.h" #include "../models/layoutsmodel.h" #include "../../lattecorona.h" #include "../../../liblatte2/types.h" // Qt #include #include #include #include namespace Latte { class Corona; class CentralLayout; class SettingsDialog; namespace Settings { namespace Handler { class TabLayouts; } } } namespace Latte { namespace Settings { namespace Controller { class Layouts : public QObject { Q_OBJECT public: explicit Layouts(Settings::Handler::TabLayouts *parent); ~Layouts(); QAbstractItemModel *model() const; QTableView *view() const; bool dataAreChanged() const; bool inMultipleMode() const; void setInMultipleMode(bool inMultiple); bool hasSelectedLayout() const; bool selectedLayoutIsCurrentActive() const; const Data::Layout selectedLayoutCurrentData() const; const Data::Layout selectedLayoutOriginalData() const; void selectRow(int index); + void setLayoutProperties(const Data::Layout &layout); //! actions void reset(); void save(); void loadLayouts(); void removeSelected(); void toggleLockedForSelected(); void toggleSharedForSelected(); QString iconsPath() const; QString colorPath(const QString color) const; QString layoutNameForFreeActivities() const; void setOriginalLayoutForFreeActivities(const QString &id); void copySelectedLayout(); const Data::Layout addLayoutForFile(QString file, QString layoutName = QString(), bool newTempDirectory = true); //! import layouts from Latte versions <= v0.7.x bool importLayoutsFromV1ConfigFile(QString file); signals: void dataChanged(); public slots: //! needed for Delegate::Shared void on_sharedToInEditChanged(const QString &row, const bool &inEdit); private slots: void loadConfig(); void saveConfig(); void storeColumnWidths(); void updateLastColumnWidth(); void on_nameDuplicatedFrom(const QString &provenId, const QString &trialId); private: void initView(); void syncActiveShares(); int rowForId(QString id) const; int rowForName(QString layoutName) const; QString uniqueTempDirectory(); QString uniqueLayoutName(QString name); private: Settings::Handler::TabLayouts *m_handler{nullptr}; QString m_iconsPath; QTableView *m_view{nullptr}; Settings::Layouts::HeaderView *m_headerView{nullptr}; //! layoutsView ui settings int m_viewSortColumn; Qt::SortOrder m_viewSortOrder; QStringList m_viewColumnWidths; KConfigGroup m_storage; //! current data Model::Layouts *m_model{nullptr}; QSortFilterProxyModel *m_proxyModel{nullptr}; QHash m_layouts; //! temp data QStringList m_tempDirectories; }; } } } #endif diff --git a/app/settings/dialogs/detailsdialog.cpp b/app/settings/dialogs/detailsdialog.cpp index 1cf885dd..91a1c0ed 100644 --- a/app/settings/dialogs/detailsdialog.cpp +++ b/app/settings/dialogs/detailsdialog.cpp @@ -1,61 +1,84 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "detailsdialog.h" // local #include "ui_detailsdialog.h" #include "../controllers/layoutscontroller.h" #include "../handlers/detailshandler.h" namespace Latte { namespace Settings { namespace Dialog { DetailsDialog::DetailsDialog(SettingsDialog *parent, Controller::Layouts *controller) : GenericDialog(parent), m_parentDlg(parent), m_ui(new Ui::DetailsDialog), m_layoutsController(controller) { //! first we need to setup the ui m_ui->setupUi(this); //! we must create handlers after creating/adjusting the ui m_handler = new Handler::DetailsHandler(this); + + connect(m_ui->buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, + this, &DetailsDialog::on_apply); + + connect(m_ui->buttonBox->button(QDialogButtonBox::Reset), &QPushButton::clicked, + this, &DetailsDialog::on_reset); } DetailsDialog::~DetailsDialog() { } Controller::Layouts *DetailsDialog::layoutsController() const { return m_layoutsController; } Ui::DetailsDialog *DetailsDialog::ui() const { return m_ui; } +void DetailsDialog::accept() +{ + qDebug() << Q_FUNC_INFO; +} + +void DetailsDialog::on_apply() +{ + qDebug() << Q_FUNC_INFO; + m_layoutsController->setLayoutProperties(m_handler->currentData()); +} + +void DetailsDialog::on_reset() +{ + qDebug() << Q_FUNC_INFO; + m_handler->reset(); +} + } } } diff --git a/app/settings/dialogs/detailsdialog.h b/app/settings/dialogs/detailsdialog.h index 08916bf0..8b3df89d 100644 --- a/app/settings/dialogs/detailsdialog.h +++ b/app/settings/dialogs/detailsdialog.h @@ -1,74 +1,80 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef DETAILSDIALOG_H #define DETAILSDIALOG_H // local #include "genericdialog.h" #include "settingsdialog.h" // Qt #include #include namespace Ui { class DetailsDialog; } namespace Latte { namespace Settings { namespace Controller { class Layouts; } namespace Handler { class DetailsHandler; } } } namespace Latte { namespace Settings { namespace Dialog { class DetailsDialog : public GenericDialog { Q_OBJECT public: DetailsDialog(SettingsDialog *parent, Controller::Layouts *controller); ~DetailsDialog(); Ui::DetailsDialog *ui() const; Controller::Layouts *layoutsController() const; +private slots: + void accept() override; + + void on_apply(); + void on_reset(); + private: SettingsDialog *m_parentDlg{nullptr}; Ui::DetailsDialog *m_ui; Controller::Layouts *m_layoutsController{nullptr}; Handler::DetailsHandler *m_handler; }; } } } #endif diff --git a/app/settings/dialogs/detailsdialog.ui b/app/settings/dialogs/detailsdialog.ui index 118856f9..5c75de2a 100644 --- a/app/settings/dialogs/detailsdialog.ui +++ b/app/settings/dialogs/detailsdialog.ui @@ -1,431 +1,431 @@ DetailsDialog 0 0 783 593 - Dialog + Details Qt::Horizontal QSizePolicy::Fixed 15 20 Qt::Vertical QSizePolicy::Fixed 15 15 - 160 + 220 60 Qt::Horizontal 40 20 Qt::Horizontal 40 20 Icon: Qt::Horizontal 40 20 0 0 Background: Qt::Horizontal 40 20 Behavior: 50 50 .. 0 0 30 50 .. Qt::Horizontal 40 20 0 0 0 0 16777215 16777215 Hide window borders for maximized windows Show in layouts context menu 0 0 16777215 16777215 - 160 + 220 60 Qt::Horizontal 40 20 Qt::Horizontal QSizePolicy::Fixed 15 20 Qt::Vertical 20 40 - + Qt::Horizontal QDialogButtonBox::Apply|QDialogButtonBox::Reset Latte::Settings::Widget::PatternWidget QWidget
settings/widgets/patternwidget.h
1
- mainButtonBox + buttonBox accepted() DetailsDialog accept() 248 254 157 274 - mainButtonBox + buttonBox rejected() DetailsDialog reject() 316 260 286 274
diff --git a/app/settings/dialogs/settingsdialog.cpp b/app/settings/dialogs/settingsdialog.cpp index 7dcf8305..521fa877 100644 --- a/app/settings/dialogs/settingsdialog.cpp +++ b/app/settings/dialogs/settingsdialog.cpp @@ -1,713 +1,709 @@ /* * Copyright 2017 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "settingsdialog.h" // local #include "ui_settingsdialog.h" #include "../universalsettings.h" #include "../data/layoutdata.h" #include "../tools/settingstools.h" #include "../../lattecorona.h" #include "../../screenpool.h" #include "../../layout/centrallayout.h" #include "../../layouts/importer.h" #include "../../layouts/manager.h" #include "../../layouts/synchronizer.h" #include "../../liblatte2/types.h" #include "../../plasma/extended/theme.h" // Qt #include #include #include #include #include #include #include // KDE #include #include #include -#define TWINENABLED "Enabled" -#define TWINVISIBLE "Visible" -#define TWINCHECKED "Checked" - namespace Latte { namespace Settings { namespace Dialog { SettingsDialog::SettingsDialog(QWidget *parent, Latte::Corona *corona) : GenericDialog(parent), m_ui(new Ui::SettingsDialog), m_corona(corona), m_storage(KConfigGroup(KSharedConfig::openConfig(),"LatteSettingsDialog")) { setAcceptDrops(true); m_ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose, true); setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); //! load window size loadConfig(); - connect(m_ui->buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked - , this, &SettingsDialog::apply); - connect(m_ui->buttonBox->button(QDialogButtonBox::Reset), &QPushButton::clicked - , this, &SettingsDialog::reset); - connect(m_ui->buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked - , this, &SettingsDialog::restoreDefaults); + connect(m_ui->buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, + this, &SettingsDialog::apply); + connect(m_ui->buttonBox->button(QDialogButtonBox::Reset), &QPushButton::clicked, + this, &SettingsDialog::reset); + connect(m_ui->buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, + this, &SettingsDialog::restoreDefaults); //! Global Menu initGlobalMenu(); m_tabLayoutsHandler = new Settings::Handler::TabLayouts(this); m_tabPreferencesHandler = new Settings::Handler::TabPreferences(this); //! load settings after handlers in order to make migration process correctly //! and remove deprecated values totally from universalsettings loadConfig(); resize(m_windowSize); m_ui->buttonBox->button(QDialogButtonBox::Apply)->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); m_ui->buttonBox->button(QDialogButtonBox::Reset)->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); //! SIGNALS connect(m_ui->tabWidget, &QTabWidget::currentChanged, this, &SettingsDialog::on_currentTabChanged); connect(m_tabLayoutsHandler, &Settings::Handler::TabLayouts::dataChanged, this, &SettingsDialog::updateApplyButtonsState); connect(m_tabPreferencesHandler, &Settings::Handler::TabPreferences::dataChanged, this, &SettingsDialog::updateApplyButtonsState); connect(m_tabPreferencesHandler, &Settings::Handler::TabPreferences::borderlessMaximizedChanged, this, [&]() { bool noBordersForMaximized = m_ui->noBordersForMaximizedChkBox->isChecked(); if (noBordersForMaximized) { m_ui->layoutsView->setColumnHidden(Settings::Model::Layouts::BORDERSCOLUMN, false); } else { m_ui->layoutsView->setColumnHidden(Settings::Model::Layouts::BORDERSCOLUMN, true); } }); //! timers m_activitiesTimer.setSingleShot(true); m_activitiesTimer.setInterval(750); connect(&m_activitiesTimer, &QTimer::timeout, this, &SettingsDialog::updateWindowActivities); m_activitiesTimer.start(); updateApplyButtonsState(); } SettingsDialog::~SettingsDialog() { qDebug() << Q_FUNC_INFO; setStoredWindowSize(size()); saveConfig(); } void SettingsDialog::initGlobalMenu() { m_globalMenuBar = new QMenuBar(this); layout()->setMenuBar(m_globalMenuBar); initFileMenu(); initHelpMenu(); } void SettingsDialog::initFileMenu() { if (!m_fileMenu) { m_fileMenu = new QMenu(i18n("File"), m_globalMenuBar); m_globalMenuBar->addMenu(m_fileMenu); } m_importFullAction = m_fileMenu->addAction(i18n("Import Configuration...")); m_importFullAction->setIcon(QIcon::fromTheme("document-import")); m_importFullAction->setShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_I)); m_importFullAction->setToolTip(i18n("Import your full configuration from previous backup")); connect(m_importFullAction, &QAction::triggered, this, &SettingsDialog::on_import_fullconfiguration); m_exportFullAction = m_fileMenu->addAction(i18n("Export Configuration...")); m_exportFullAction->setIcon(QIcon::fromTheme("document-export")); m_exportFullAction->setShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_E)); m_exportFullAction->setToolTip(i18n("Export your full configuration to create backup")); connect(m_exportFullAction, &QAction::triggered, this, &SettingsDialog::on_export_fullconfiguration); m_fileMenu->addSeparator(); QAction *screensAction = m_fileMenu->addAction(i18n("Sc&reens...")); screensAction->setIcon(QIcon::fromTheme("document-properties")); //screensAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R)); QAction *quitAction = m_fileMenu->addAction(i18n("&Quit Latte")); quitAction->setIcon(QIcon::fromTheme("application-exit")); quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); //! triggers connect(quitAction, &QAction::triggered, this, [&]() { bool accepted = saveChanges(); if (accepted) { close(); m_corona->quitApplication(); } }); } void SettingsDialog::initHelpMenu() { if (!m_helpMenu) { m_helpMenu = new KHelpMenu(m_globalMenuBar); m_globalMenuBar->addMenu(m_helpMenu->menu()); } //! hide help menu actions that are not used m_helpMenu->action(KHelpMenu::menuHelpContents)->setVisible(false); m_helpMenu->action(KHelpMenu::menuWhatsThis)->setVisible(false); } Latte::Corona *SettingsDialog::corona() const { return m_corona; } Ui::SettingsDialog *SettingsDialog::ui() const { return m_ui; } QSize SettingsDialog::storedWindowSize() const { return m_windowSize; } void SettingsDialog::setStoredWindowSize(const QSize &size) { if (m_windowSize == size) { return; } m_windowSize = size; } QSize SettingsDialog::downloadWindowSize() const { return m_downloadWindowSize; } void SettingsDialog::setDownloadWindowSize(const QSize &size) { if (m_downloadWindowSize == size) { return; } m_downloadWindowSize = size; } QMenuBar *SettingsDialog::appMenuBar() const { return m_globalMenuBar; } QMenu *SettingsDialog::fileMenu() const { return m_fileMenu; } QMenu *SettingsDialog::helpMenu() const { return m_helpMenu->menu(); } Types::LatteConfigPage SettingsDialog::currentPage() { Types::LatteConfigPage cPage= static_cast(m_ui->tabWidget->currentIndex()); return cPage; } void SettingsDialog::toggleCurrentPage() { if (m_ui->tabWidget->currentIndex() == 0) { m_ui->tabWidget->setCurrentIndex(1); } else { m_ui->tabWidget->setCurrentIndex(0); } } void SettingsDialog::setCurrentPage(int page) { m_ui->tabWidget->setCurrentIndex(page); } void SettingsDialog::on_import_fullconfiguration() { qDebug() << Q_FUNC_INFO; QFileDialog *importFileDialog = new QFileDialog(this, i18nc("import full configuration", "Import Full Configuration") , QDir::homePath() , QStringLiteral("latterc")); importFileDialog->setWindowIcon(QIcon::fromTheme("document-import")); importFileDialog->setLabelText(QFileDialog::Accept, i18nc("import full configuration","Import")); importFileDialog->setFileMode(QFileDialog::AnyFile); importFileDialog->setAcceptMode(QFileDialog::AcceptOpen); importFileDialog->setDefaultSuffix("latterc"); QStringList filters; filters << QString(i18nc("import full configuration", "Latte Dock Full Configuration file") + "(*.latterc)"); importFileDialog->setNameFilters(filters); connect(importFileDialog, &QFileDialog::finished, importFileDialog, &QFileDialog::deleteLater); connect(importFileDialog, &QFileDialog::fileSelected, this, [&](const QString & file) { Latte::Layouts::Importer::LatteFileVersion version = Latte::Layouts::Importer::fileVersion(file); qDebug() << "VERSION :::: " << version; if (version == Latte::Layouts::Importer::ConfigVersion2 || version == Latte::Layouts::Importer::ConfigVersion1) { auto msg = new QMessageBox(this); msg->setIcon(QMessageBox::Warning); msg->setWindowTitle(i18n("Import: Full Configuration File")); msg->setText(i18n("You are importing full configuration file. Be careful, all current settings and layouts will be lost. It is advised to take backup first!
")); msg->setStandardButtons(QMessageBox::Cancel); QPushButton *takeBackupBtn = new QPushButton(msg); takeBackupBtn->setText(i18nc("export full configuration", "Take Backup...")); takeBackupBtn->setIcon(QIcon::fromTheme("document-export")); takeBackupBtn->setToolTip(i18n("Export your full configuration in order to take backup")); QPushButton *importBtn = new QPushButton(msg); importBtn->setText(i18nc("import full configuration", "Import")); importBtn->setIcon(QIcon::fromTheme("document-import")); importBtn->setToolTip(i18n("Import your full configuration and drop all your current settings and layouts")); msg->addButton(takeBackupBtn, QMessageBox::AcceptRole); msg->addButton(importBtn, QMessageBox::AcceptRole); msg->setDefaultButton(takeBackupBtn); connect(msg, &QFileDialog::finished, msg, &QFileDialog::deleteLater); connect(importBtn, &QPushButton::clicked, this, [&, file](bool check) { m_corona->importFullConfiguration(file); }); connect(takeBackupBtn, &QPushButton::clicked, this, [&](bool check) { on_export_fullconfiguration(); }); msg->open(); } }); importFileDialog->open(); } void SettingsDialog::on_export_fullconfiguration() { //! Update ALL active original layouts before exporting, m_corona->layoutsManager()->synchronizer()->syncActiveLayoutsToOriginalFiles(); QFileDialog *exportFileDialog = new QFileDialog(this, i18n("Export Full Configuration"), QDir::homePath(), QStringLiteral("latterc")); exportFileDialog->setLabelText(QFileDialog::Accept, i18nc("export full configuration","Export")); exportFileDialog->setFileMode(QFileDialog::AnyFile); exportFileDialog->setAcceptMode(QFileDialog::AcceptSave); exportFileDialog->setDefaultSuffix("latterc"); QStringList filters; QString filter2(i18nc("export full configuration", "Latte Dock Full Configuration file v0.2") + "(*.latterc)"); filters << filter2; exportFileDialog->setNameFilters(filters); connect(exportFileDialog, &QFileDialog::finished, exportFileDialog, &QFileDialog::deleteLater); connect(exportFileDialog, &QFileDialog::fileSelected, this, [&](const QString & file) { auto showExportConfigurationError = [this]() { showInlineMessage(i18n("Full configuration export failed..."), KMessageWidget::Error, true); }; if (m_corona->layoutsManager()->importer()->exportFullConfiguration(file)) { QAction *openUrlAction = new QAction(i18n("Open Location..."), this); openUrlAction->setData(file); QList actions; actions << openUrlAction; connect(openUrlAction, &QAction::triggered, this, [&, openUrlAction]() { QString file = openUrlAction->data().toString(); if (!file.isEmpty()) { KIO::highlightInFileManager({file}); } }); showInlineMessage(i18n("Full configuration export succeeded..."), KMessageWidget::Information, false, actions); } else { showExportConfigurationError(); } }); exportFileDialog->open(); QDate currentDate = QDate::currentDate(); QString proposedName = QStringLiteral("Latte Dock (") + currentDate.toString("yyyy-MM-dd")+")"; exportFileDialog->selectFile(proposedName); } void SettingsDialog::requestImagesDialog(int row) { QStringList mimeTypeFilters; mimeTypeFilters << "image/jpeg" // will show "JPEG image (*.jpeg *.jpg) << "image/png"; // will show "PNG image (*.png)" QFileDialog dialog(this); dialog.setMimeTypeFilters(mimeTypeFilters); QString background = "";// m_model->data(m_model->index(row, COLORCOLUMN), Qt::BackgroundRole).toString(); if (background.startsWith("/") && QFileInfo(background).exists()) { dialog.setDirectory(QFileInfo(background).absolutePath()); dialog.selectFile(background); } if (dialog.exec()) { QStringList files = dialog.selectedFiles(); if (files.count() > 0) { // m_model->setData(m_model->index(row, COLORCOLUMN), files[0], Qt::BackgroundRole); } } } void SettingsDialog::requestColorsDialog(int row) { /*QColorDialog dialog(this); QString textColor = m_model->data(m_model->index(row, Settings::Model::Layouts::BACKGROUNDCOLUMN), Qt::UserRole).toString(); dialog.setCurrentColor(QColor(textColor)); if (dialog.exec()) { qDebug() << dialog.selectedColor().name(); m_model->setData(m_model->index(row, COLORCOLUMN), dialog.selectedColor().name(), Qt::UserRole); }*/ } void SettingsDialog::accept() { //! disable accept totally in order to avoid closing with ENTER key with no real reason qDebug() << Q_FUNC_INFO; } void SettingsDialog::reject() { bool accepted = saveChanges(); if (accepted) { QDialog::reject(); } } void SettingsDialog::apply() { qDebug() << Q_FUNC_INFO; if (!m_ui->buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) { return; } save(); } void SettingsDialog::reset() { qDebug() << Q_FUNC_INFO; if (!m_ui->buttonBox->button(QDialogButtonBox::Reset)->isEnabled()) { return; } if (m_ui->tabWidget->currentIndex() == Latte::Types::LayoutPage) { m_tabLayoutsHandler->reset(); } else if (m_ui->tabWidget->currentIndex() == Latte::Types::PreferencesPage) { m_tabPreferencesHandler->reset(); } } void SettingsDialog::restoreDefaults() { qDebug() << Q_FUNC_INFO; if (m_ui->tabWidget->currentIndex() == Latte::Types::LayoutPage) { //! do nothing, should be disabled } else if (m_ui->tabWidget->currentIndex() == Latte::Types::PreferencesPage) { m_tabPreferencesHandler->resetDefaults(); } } void SettingsDialog::updateApplyButtonsState() { bool changed{false}; //! Ok, Apply Buttons if ((currentPage() == Latte::Types::LayoutPage && m_tabLayoutsHandler->dataAreChanged()) ||(currentPage() == Latte::Types::PreferencesPage && m_tabPreferencesHandler->dataAreChanged())) { changed = true; } if (changed) { m_ui->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(true); m_ui->buttonBox->button(QDialogButtonBox::Reset)->setEnabled(true); } else { m_ui->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); m_ui->buttonBox->button(QDialogButtonBox::Reset)->setEnabled(false); } //! RestoreDefaults Button if (m_ui->tabWidget->currentIndex() == Latte::Types::LayoutPage) { m_ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setVisible(false); } else if (m_ui->tabWidget->currentIndex() == Latte::Types::PreferencesPage) { m_ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setVisible(true); //! Defaults for general Latte settings if (m_tabPreferencesHandler->inDefaultValues() ) { m_ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setEnabled(false); } else { m_ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setEnabled(true); } } } int SettingsDialog::saveChangesConfirmation() { auto msg = new QMessageBox(this); msg->setIcon(QMessageBox::Warning); msg->setWindowTitle(i18n("Apply Settings")); QString tabName = m_ui->tabWidget->tabBar()->tabText(m_acceptedPage).remove("&"); msg->setText(i18n("The settings of %0 tab have changed. Do you want to apply the changes or discard them?").arg(tabName)); msg->setStandardButtons(QMessageBox::Apply | QMessageBox::Discard | QMessageBox::Cancel); msg->setDefaultButton(QMessageBox::Apply); connect(msg, &QFileDialog::finished, msg, &QFileDialog::deleteLater); return msg->exec(); } bool SettingsDialog::saveChanges() { if ((m_acceptedPage == Latte::Types::LayoutPage && m_tabLayoutsHandler->dataAreChanged()) || (m_acceptedPage == Latte::Types::PreferencesPage && m_tabPreferencesHandler->dataAreChanged())) { int result = saveChangesConfirmation(); if (result == QMessageBox::Apply) { save(); } else if (result == QMessageBox::Discard) { reset(); } else { return false; } } return true; } void SettingsDialog::on_currentTabChanged(int index) { //! Before switching into a new tab the user must confirm first if the data should be saved or not if ((m_acceptedPage == Latte::Types::LayoutPage && m_tabLayoutsHandler->dataAreChanged()) || (m_acceptedPage == Latte::Types::PreferencesPage && m_tabPreferencesHandler->dataAreChanged())) { if (index != m_acceptedPage) { m_nextPage = index; setCurrentPage(m_acceptedPage); return; } bool approvedNext = saveChanges(); if (!approvedNext) { m_nextPage = m_acceptedPage; return; } } else { m_nextPage = index; } m_acceptedPage = m_nextPage >= 0 ? m_nextPage : index/*initialize*/; m_nextPage = m_acceptedPage; setCurrentPage(m_acceptedPage); updateApplyButtonsState(); } void SettingsDialog::showLayoutInformation() { /* int currentRow = m_ui->layoutsView->currentIndex().row(); QString id = m_model->data(m_model->index(currentRow, IDCOLUMN), Qt::DisplayRole).toString(); QString name = m_model->data(m_model->index(currentRow, NAMECOLUMN), Qt::DisplayRole).toString(); Layout::GenericLayout *genericActive= m_corona->layoutsManager()->synchronizer()->layout(o_layoutsOriginalData[id].originalName()); Layout::GenericLayout *generic = genericActive ? genericActive : m_layouts[id]; auto msg = new QMessageBox(this); msg->setWindowTitle(name); msg->setText(generic->reportHtml(m_corona->screenPool())); msg->open();*/ } void SettingsDialog::showScreensInformation() { /* QList assignedScreens; for (int i = 0; i < m_model->rowCount(); ++i) { QString id = m_model->data(m_model->index(i, IDCOLUMN), Qt::DisplayRole).toString(); QString name = m_model->data(m_model->index(i, NAMECOLUMN), Qt::DisplayRole).toString(); Layout::GenericLayout *genericActive= m_corona->layoutsManager()->synchronizer()->layout(o_layoutsOriginalData[id].originalName()); Layout::GenericLayout *generic = genericActive ? genericActive : m_layouts[id]; QList vScreens = generic->viewsScreens(); for (const int scrId : vScreens) { if (!assignedScreens.contains(scrId)) { assignedScreens << scrId; } } } auto msg = new QMessageBox(this); msg->setWindowTitle(i18n("Screens Information")); msg->setText(m_corona->screenPool()->reportHtml(assignedScreens)); msg->open();*/ } void SettingsDialog::dragEnterEvent(QDragEnterEvent *event) { if (currentPage() == Types::LayoutPage){ m_tabLayoutsHandler->on_dragEnterEvent(event); } else { QDialog::dragEnterEvent(event); } } void SettingsDialog::dragLeaveEvent(QDragLeaveEvent *event) { if (currentPage() == Types::LayoutPage){ m_tabLayoutsHandler->on_dragLeaveEvent(event); } else { QDialog::dragLeaveEvent(event); } } void SettingsDialog::dragMoveEvent(QDragMoveEvent *event) { if (currentPage() == Types::LayoutPage){ m_tabLayoutsHandler->on_dragMoveEvent(event); } else { QDialog::dragMoveEvent(event); } } void SettingsDialog::dropEvent(QDropEvent *event) { if (currentPage() == Types::LayoutPage){ m_tabLayoutsHandler->on_dropEvent(event); } else { QDialog::dropEvent(event); } } void SettingsDialog::keyReleaseEvent(QKeyEvent *event) { if (event && currentPage() == Types::LayoutPage){ m_tabLayoutsHandler->on_keyReleaseEvent(event); } QDialog::keyReleaseEvent(event); } void SettingsDialog::updateWindowActivities() { if (KWindowSystem::isPlatformX11()) { KWindowSystem::setOnActivities(winId(), QStringList()); } } void SettingsDialog::save() { qDebug() << Q_FUNC_INFO; if (currentPage() == Latte::Types::LayoutPage) { m_tabLayoutsHandler->save(); } else if (currentPage() == Latte::Types::PreferencesPage) { m_tabPreferencesHandler->save(); } } void SettingsDialog::loadConfig() { //! remove old unneeded oprtions KConfigGroup deprecatedStorage(KConfigGroup(KSharedConfig::openConfig(), "UniversalSettings")); QStringList columnWidths = deprecatedStorage.readEntry("layoutsColumnWidths", QStringList()); if (!columnWidths.isEmpty()) { //! migrating m_windowSize = deprecatedStorage.readEntry("layoutsWindowSize", QSize(700, 450)); m_downloadWindowSize = deprecatedStorage.readEntry("downloadWindowSize", QSize(800, 550)); deprecatedStorage.writeEntry("layoutsColumnWidths", QStringList()); deprecatedStorage.writeEntry("layoutsWindowSize", QSize()); deprecatedStorage.writeEntry("downloadWindowSize", QSize()); } else { //! new storage m_windowSize = m_storage.readEntry("windowSize", QSize(700, 450)); m_downloadWindowSize = m_storage.readEntry("downloadWindowSize", QSize(800, 550)); } } void SettingsDialog::saveConfig() { m_storage.writeEntry("windowSize", m_windowSize); m_storage.writeEntry("downloadWindowSize", m_downloadWindowSize); } } } }//end of namespace diff --git a/app/settings/handlers/detailshandler.cpp b/app/settings/handlers/detailshandler.cpp index 99030e58..557a4af6 100644 --- a/app/settings/handlers/detailshandler.cpp +++ b/app/settings/handlers/detailshandler.cpp @@ -1,108 +1,120 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "detailshandler.h" // local #include "ui_detailsdialog.h" #include "../controllers/layoutscontroller.h" #include "../data/layoutdata.h" #include "../data/layoutstable.h" #include "../dialogs/detailsdialog.h" #include "../models/layoutsmodel.h" namespace Latte { namespace Settings { namespace Handler { DetailsHandler::DetailsHandler(Dialog::DetailsDialog *parentDialog) : Generic(parentDialog), m_parentDialog(parentDialog), m_ui(m_parentDialog->ui()) { init(); //! create it after initializing m_infoHandler = new DetailsInfoHandler(parentDialog, this); } DetailsHandler::~DetailsHandler() { } void DetailsHandler::init() { connect(m_ui->layoutsCmb, QOverload::of(&QComboBox::currentIndexChanged), this, &DetailsHandler::on_currentIndexChanged); reload(); } void DetailsHandler::reload() { o_data = m_parentDialog->layoutsController()->selectedLayoutCurrentData(); c_data = o_data; m_ui->layoutsCmb->setModel(m_parentDialog->layoutsController()->model()); m_ui->layoutsCmb->setModelColumn(Model::Layouts::NAMECOLUMN); m_ui->layoutsCmb->setCurrentText(o_data.name); } Data::Layout DetailsHandler::currentData() const { return c_data; } bool DetailsHandler::dataAreChanged() const { return o_data != c_data; } bool DetailsHandler::inDefaultValues() const { //nothing special return true; } void DetailsHandler::reset() { + c_data = o_data; + emit currentLayoutChanged(); } void DetailsHandler::resetDefaults() { //do nothing } void DetailsHandler::save() { } void DetailsHandler::on_currentIndexChanged(int index) { m_parentDialog->layoutsController()->selectRow(index); init(); emit currentLayoutChanged(); } +void DetailsHandler::setIsShownInMenu(bool inMenu) +{ + c_data.isShownInMenu = inMenu; +} + +void DetailsHandler::setHasDisabledBorders(bool disabled) +{ + c_data.hasDisabledBorders = disabled; +} + } } } diff --git a/app/settings/handlers/detailshandler.h b/app/settings/handlers/detailshandler.h index f46a7826..3c750a57 100644 --- a/app/settings/handlers/detailshandler.h +++ b/app/settings/handlers/detailshandler.h @@ -1,89 +1,92 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef DETAILSDIALOGHANDLER_H #define DETAILSDIALOGHANDLER_H //! local #include "generichandler.h" #include "detailsinfohandler.h" namespace Ui { class DetailsDialog; } namespace Latte{ namespace Settings{ namespace Dialog{ class DetailsDialog; } } } namespace Latte { namespace Settings { namespace Handler { //! Handlers are objects to handle the UI elements that semantically associate with specific //! ui::tabs or different windows. They are responsible also to handle the user interaction //! between controllers and views class DetailsHandler : public Generic { Q_OBJECT public: DetailsHandler(Dialog::DetailsDialog *parentDialog); ~DetailsHandler(); bool dataAreChanged() const override; bool inDefaultValues() const override; void reset() override; void resetDefaults() override; void save() override; Data::Layout currentData() const; + void setIsShownInMenu(bool inMenu); + void setHasDisabledBorders(bool disabled); + signals: void currentLayoutChanged(); private: void on_currentIndexChanged(int index); private: void init(); void reload(); private: Dialog::DetailsDialog *m_parentDialog{nullptr}; Ui::DetailsDialog *m_ui{nullptr}; DetailsInfoHandler *m_infoHandler{nullptr}; Data::Layout o_data; Data::Layout c_data; }; } } } #endif diff --git a/app/settings/handlers/detailsinfohandler.cpp b/app/settings/handlers/detailsinfohandler.cpp index 38ee015c..c6e5cae4 100644 --- a/app/settings/handlers/detailsinfohandler.cpp +++ b/app/settings/handlers/detailsinfohandler.cpp @@ -1,118 +1,126 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "detailsinfohandler.h" // local #include "ui_detailsdialog.h" #include "detailshandler.h" #include "../dialogs/detailsdialog.h" #include "../widgets/patternwidget.h" #include "../../layout/abstractlayout.h" #include "../../../liblatte2/types.h" namespace Latte { namespace Settings { namespace Handler { DetailsInfoHandler::DetailsInfoHandler(Dialog::DetailsDialog *parentDialog, DetailsHandler *parentHandler) : Generic(parentDialog, parentHandler), m_parentDialog(parentDialog), m_ui(m_parentDialog->ui()), m_parentHandler(parentHandler) { init(); } DetailsInfoHandler::~DetailsInfoHandler() { } void DetailsInfoHandler::init() { m_backButtonsGroup = new QButtonGroup(this); m_backButtonsGroup->addButton(m_ui->colorRadioBtn, Types::ColorStyle); m_backButtonsGroup->addButton(m_ui->backRadioBtn, Types::CustomBackgroundStyle); m_backButtonsGroup->setExclusive(true); connect(m_backButtonsGroup, static_cast(&QButtonGroup::buttonToggled), [ = ](int id, bool checked) { if (checked) { //m_layoutsController->setInMultipleMode(id == Latte::Types::MultipleLayouts); } }); + connect(m_ui->inMenuChk, &QCheckBox::stateChanged, this, [&]() { + m_parentHandler->setIsShownInMenu(m_ui->inMenuChk->isChecked()); + }); + + connect(m_ui->borderlessChk, &QCheckBox::stateChanged, this, [&]() { + m_parentHandler->setHasDisabledBorders(m_ui->borderlessChk->isChecked()); + }); + connect(m_parentHandler, &DetailsHandler::currentLayoutChanged, this, &DetailsInfoHandler::reload); reload(); } void DetailsInfoHandler::reload() { loadLayout(m_parentHandler->currentData()); } void DetailsInfoHandler::loadLayout(const Data::Layout &data) { if (data.backgroundStyle == Types::ColorStyle) { m_ui->colorRadioBtn->setChecked(true); } else { m_ui->backRadioBtn->setChecked(true); } m_ui->colorPatternWidget->setBackground(m_parentDialog->layoutsController()->colorPath(data.color)); m_ui->backPatternWidget->setBackground(data.background); m_ui->colorPatternWidget->setTextColor(Layout::AbstractLayout::defaultTextColor(data.color)); m_ui->backPatternWidget->setTextColor(data.textColor); m_ui->inMenuChk->setChecked(data.isShownInMenu); m_ui->borderlessChk->setChecked(data.hasDisabledBorders); } bool DetailsInfoHandler::dataAreChanged() const { return true; } bool DetailsInfoHandler::inDefaultValues() const { //nothing special return true; } void DetailsInfoHandler::reset() { } void DetailsInfoHandler::resetDefaults() { //do nothing } void DetailsInfoHandler::save() { } } } } diff --git a/app/settings/models/layoutsmodel.cpp b/app/settings/models/layoutsmodel.cpp index bb850f55..0ed2ca65 100644 --- a/app/settings/models/layoutsmodel.cpp +++ b/app/settings/models/layoutsmodel.cpp @@ -1,1100 +1,1113 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "layoutsmodel.h" // local #include "../data/layoutdata.h" #include "../../layouts/manager.h" #include "../../layouts/synchronizer.h" #include "../../settings/universalsettings.h" // Qt #include #include #include #include // KDE #include // KActivities #include #include namespace Latte { namespace Settings { namespace Model { Layouts::Layouts(QObject *parent, Latte::Corona *corona) : QAbstractTableModel(parent), m_corona(corona) { initActivities(); connect(this, &Layouts::inMultipleModeChanged, this, [&]() { QVector roles; roles << Qt::DisplayRole; roles << Qt::UserRole; roles << ISSHAREDROLE; roles << INMULTIPLELAYOUTSROLE; emit dataChanged(index(0, NAMECOLUMN), index(rowCount()-1, SHAREDCOLUMN), roles); }); connect(this, &Layouts::inMultipleModeChanged, this, &Layouts::updateActiveStates); connect(m_corona->layoutsManager(), &Latte::Layouts::Manager::currentLayoutNameChanged, this, &Layouts::updateActiveStates); connect(m_corona->layoutsManager(), &Latte::Layouts::Manager::centralLayoutsChanged, this, &Layouts::updateActiveStates); connect(m_corona->universalSettings(), &Latte::UniversalSettings::lastNonAssignedLayoutNameChanged, this, [&]() { //FREE ACTIVITES LAYOUT changed and our model must be updated... assignFreeActivitiesLayoutAt(m_corona->universalSettings()->lastNonAssignedLayoutName()); }); } Layouts::~Layouts() { qDeleteAll(m_activitiesInfo); } bool Layouts::containsCurrentName(const QString &name) const { return m_layoutsTable.containsName(name); } bool Layouts::dataAreChanged() const { return ((o_inMultipleMode != m_inMultipleMode) || (o_layoutsTable != m_layoutsTable)); } bool Layouts::inMultipleMode() const { return m_inMultipleMode; } void Layouts::setInMultipleMode(bool inMultiple) { if (m_inMultipleMode == inMultiple) { return; } m_inMultipleMode = inMultiple; emit inMultipleModeChanged(); } int Layouts::rowCount() const { return m_layoutsTable.rowCount(); } int Layouts::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return m_layoutsTable.rowCount(); } int Layouts::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return SHAREDCOLUMN+1; } void Layouts::clear() { if (m_layoutsTable.rowCount() > 0) { beginRemoveRows(QModelIndex(), 0, m_layoutsTable.rowCount() - 1); m_layoutsTable.clear(); endRemoveRows(); } } void Layouts::appendLayout(const Settings::Data::Layout &layout) { beginInsertRows(QModelIndex(), m_layoutsTable.rowCount(), m_layoutsTable.rowCount()); m_layoutsTable << layout; endInsertRows(); emit rowsInserted(); } void Layouts::applyData() { QVector roles; roles << Qt::DisplayRole; roles << Qt::UserRole; o_inMultipleMode = m_inMultipleMode; o_layoutsTable = m_layoutsTable; emit dataChanged(index(0, BACKGROUNDCOLUMN), index(rowCount()-1,SHAREDCOLUMN), roles); } void Layouts::resetData() { clear(); setOriginalData(o_layoutsTable, o_inMultipleMode); } void Layouts::removeLayout(const QString &id) { int index = m_layoutsTable.indexOf(id); if (index >= 0) { beginRemoveRows(QModelIndex(), index, index); m_layoutsTable.remove(index); endRemoveRows(); } } +void Layouts::setLayoutProperties(const Data::Layout &layout) +{ + if (m_layoutsTable.containsId(layout.id) && m_layoutsTable[layout.id] != layout) { + m_layoutsTable[layout.id] = layout; + int dataRow = m_layoutsTable.indexOf(layout.id); + + QVector roles; + roles << Qt::DisplayRole; + roles << Qt::UserRole; + emit dataChanged(index(dataRow, IDCOLUMN), index(dataRow, SHAREDCOLUMN), roles); + } +} + bool Layouts::removeRows(int row, int count, const QModelIndex &parent) { Q_UNUSED(parent) int firstRow = row; int lastRow = row+count-1; if (count > 0 && m_layoutsTable.rowExists(firstRow) && (m_layoutsTable.rowExists(lastRow))) { bool freeActivitiesLayoutIsRemoved{false}; for(int i=firstRow; i<=lastRow; ++i) { if (m_layoutsTable[i].activities.contains(Data::Layout::FREEACTIVITIESID)) { //! we need to reassign it properly freeActivitiesLayoutIsRemoved = true; break; } } beginRemoveRows(QModelIndex(), firstRow, lastRow); for(int i=0; i roles; roles << Qt::DisplayRole; roles << Qt::UserRole; emit dataChanged(index(0, ACTIVITYCOLUMN), index(rowCount()-1, ACTIVITYCOLUMN), roles); } } void Layouts::setOriginalLayoutForFreeActivities(const QString &id) { if (o_layoutsTable.containsId(id)) { o_layoutsTable.setLayoutForFreeActivities(id); m_layoutsTable.setLayoutForFreeActivities(id); QVector roles; roles << Qt::DisplayRole; roles << Qt::UserRole; emit dataChanged(index(0, ACTIVITYCOLUMN), index(rowCount()-1, ACTIVITYCOLUMN), roles); } } QStringList Layouts::assignedActivitiesFromShared(const int &row) const { QStringList assigns; if (!m_layoutsTable.rowExists(row)) { return assigns; } if (m_layoutsTable[row].isShared()) { for (int i=0; i=0 && !m_layoutsTable[shareRow].activities.isEmpty()) { assigns << m_layoutsTable[shareRow].activities; } } } return assigns; } QVariant Layouts::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation != Qt::Horizontal) { return QAbstractTableModel::headerData(section, orientation, role); } if (role == Qt::FontRole) { QFont font = qvariant_cast(QAbstractTableModel::headerData(section, orientation, role)); font.setBold(true); return font; } switch(section) { case IDCOLUMN: if (role == Qt::DisplayRole) { return QString("#path"); } break; case HIDDENTEXTCOLUMN: if (role == Qt::DisplayRole) { return QString(""); } break; case BACKGROUNDCOLUMN: if (role == Qt::DisplayRole) { return QString(""); } else if (role == Qt::DecorationRole) { return QIcon::fromTheme("games-config-background"); } else if (role == Qt::TextAlignmentRole ){ return QVariant::fromValue(Qt::AlignHCenter | Qt::AlignVCenter); } break; case NAMECOLUMN: if (role == Qt::DisplayRole) { return QString(i18nc("column for layout name", "Name")); }/* else if (role == Qt::TextAlignmentRole) { return QVariant::fromValue(Qt::AlignLeft | Qt::AlignVCenter); }*/ break; case MENUCOLUMN: if (role == Qt::DisplayRole) { return QString(i18nc("column for layout to show in menu", "In Menu")); }/* else if (role == Qt::TextAlignmentRole ){ return QVariant::fromValue(Qt::AlignHCenter | Qt::AlignVCenter); }*/ break; case BORDERSCOLUMN: if (role == Qt::DisplayRole) { return QString(i18nc("column for layout to hide borders for maximized windows", "Borderless")); }/* else if (role == Qt::TextAlignmentRole ){ return QVariant::fromValue(Qt::AlignHCenter | Qt::AlignVCenter); }*/ break; case ACTIVITYCOLUMN: if (role == Qt::DisplayRole) { return QString(i18nc("column for layout to show which activities is assigned to", "Activities")); } else if (role == Qt::DecorationRole) { return QIcon::fromTheme("activities"); }/* else if (role == Qt::TextAlignmentRole ){ return QVariant::fromValue(Qt::AlignLeft | Qt::AlignVCenter); }*/ break; case SHAREDCOLUMN: if (role == Qt::DisplayRole) { return QString(i18nc("column for shared layout to show which layouts is assigned to", "Shared To")); } else if (role == Qt::DecorationRole) { return QIcon::fromTheme("document-share"); }/* else if (role == Qt::TextAlignmentRole ){ return QVariant::fromValue(Qt::AlignLeft | Qt::AlignVCenter); }*/ break; default: break; }; return QAbstractTableModel::headerData(section, orientation, role); } Qt::ItemFlags Layouts::flags(const QModelIndex &index) const { const int column = index.column(); const int row = index.row(); auto flags = QAbstractTableModel::flags(index); if (column == MENUCOLUMN || column == BORDERSCOLUMN) { flags |= Qt::ItemIsUserCheckable; } if (column == ACTIVITYCOLUMN || column == BACKGROUNDCOLUMN || column == NAMECOLUMN || column == SHAREDCOLUMN) { flags |= Qt::ItemIsEditable; } return flags; } void Layouts::setIconsPath(QString iconsPath) { m_iconsPath = iconsPath; } QList Layouts::icons(const int &row) const { QList icons; QStringList activitiesIds = m_layoutsTable[row].isShared() ? assignedActivitiesFromShared(row) : m_layoutsTable[row].activities; int freeActivitiesPos = -1; for(int i=0; i= 0) { Data::LayoutIcon freeActsData = icons.takeAt(freeActivitiesPos); icons.prepend(freeActsData); } //! background image if (icons.count() == 0) { QString colorPath = m_layoutsTable[row].background.startsWith("/") ? m_layoutsTable[row].background : m_iconsPath + m_layoutsTable[row].color + "print.jpg"; if (QFileInfo(colorPath).exists()) { Data::LayoutIcon icon; icon.isBackgroundFile = true; icon.isFreeActivities = false; icon.name = colorPath; icons << icon; } } return icons; } QString Layouts::sortableText(const int &priority, const int &row) const { QString numberPart; if (priority < 10) { numberPart = "00000" + QString::number(priority); } else if (priority < 100) { numberPart = "0000" + QString::number(priority); } else if (priority < 1000) { numberPart = "000" + QString::number(priority); } else if (priority < 10000) { numberPart = "00" + QString::number(priority); } else if (priority < 100000) { numberPart = "0" + QString::number(priority); } return (numberPart + m_layoutsTable[row].name); } QString Layouts::sortingPriority(const SortingPriority &priority, const int &row) const { int iPriority = (int)priority; iPriority = (m_layoutsTable[row].isActive ? iPriority - 1000 : iPriority); return sortableText(iPriority, row); } QVariant Layouts::data(const QModelIndex &index, int role) const { const int row = index.row(); int column = index.column(); bool isNewLayout = !o_layoutsTable.containsId(m_layoutsTable[row].id); if (!m_layoutsTable.rowExists(row)) { return QVariant{}; } if (role == IDROLE) { return m_layoutsTable[row].id; } else if (role == ISACTIVEROLE) { return m_layoutsTable[row].isActive; } else if (role == ISLOCKEDROLE) { return m_layoutsTable[row].isLocked; } else if (role == ISSHAREDROLE) { return m_layoutsTable[row].isShared(); } else if (role == INMULTIPLELAYOUTSROLE) { return inMultipleMode(); } else if (role == ASSIGNEDACTIVITIESROLE) { return m_layoutsTable[row].activities; } else if (role == ASSIGNEDACTIVITIESFROMSHAREDROLE) { return assignedActivitiesFromShared(row); } else if (role == ALLACTIVITIESSORTEDROLE) { QStringList activities; activities << QString(Data::Layout::FREEACTIVITIESID); activities << m_corona->layoutsManager()->synchronizer()->activities(); return activities; } else if (role == ALLACTIVITIESDATAROLE) { QVariant activitiesData; activitiesData.setValue(m_activitiesMap); return activitiesData; } else if (role == ALLLAYOUTSROLE) { QVariant layouts; layouts.setValue(m_layoutsTable); return layouts; } else if (role == SHAREDTOINEDITROLE) { return (m_sharedToInEditRow == row); } else if (role == ISNEWLAYOUTROLE) { return isNewLayout; } else if (role == LAYOUTHASCHANGESROLE) { return (isNewLayout ? true : o_layoutsTable[m_layoutsTable[row].id] != m_layoutsTable[row]); } switch (column) { case IDCOLUMN: if (role == Qt::DisplayRole || role == Qt::UserRole){ return m_layoutsTable[row].id; } break; case HIDDENTEXTCOLUMN: return QVariant{}; case BACKGROUNDCOLUMN: if (role == SORTINGROLE) { return m_layoutsTable[row].name; } if (role == Qt::DisplayRole) { return m_layoutsTable[row].background; } else if (role == Qt::UserRole) { QList iconsList = icons(row); QVariant iconsVariant; iconsVariant.setValue>(iconsList); return iconsVariant; } break; case NAMECOLUMN: if (role == SORTINGROLE) { return m_layoutsTable[row].name; } if ((role == Qt::DisplayRole) || (role == Qt::UserRole)) { return m_layoutsTable[row].name; } break; case MENUCOLUMN: if (role == SORTINGROLE) { if ((m_inMultipleMode && m_layoutsTable[row].isShared())) { return sortingPriority(MEDIUMPRIORITY, row); } else if (m_layoutsTable[row].isShownInMenu) { return sortingPriority(HIGHESTPRIORITY, row); } return sortingPriority(NORMALPRIORITY, row); } if (role == ORIGINALISSHOWNINMENUROLE) { return isNewLayout ? false : o_layoutsTable[row].isShownInMenu; } if (role == Qt::UserRole) { return m_layoutsTable[row].isShownInMenu; } break; case BORDERSCOLUMN: if (role == SORTINGROLE) { if ((m_inMultipleMode && m_layoutsTable[row].isShared())) { return sortingPriority(MEDIUMPRIORITY, row); } else if (m_layoutsTable[row].hasDisabledBorders) { return sortingPriority(HIGHESTPRIORITY, row); } return sortingPriority(NORMALPRIORITY, row); } if (role == ORIGINALHASBORDERSROLE) { return isNewLayout ? false : o_layoutsTable[row].hasDisabledBorders; } if (role == Qt::UserRole) { return m_layoutsTable[row].hasDisabledBorders; } break; case ACTIVITYCOLUMN: if (role == SORTINGROLE) { if ((m_inMultipleMode && m_layoutsTable[row].isShared())) { return sortingPriority(MEDIUMPRIORITY, row) + m_layoutsTable[row].shares.count(); } else if (m_layoutsTable[row].activities.count() > 0) { if (m_layoutsTable[row].activities.contains(Data::Layout::FREEACTIVITIESID)) { return sortingPriority(HIGHESTPRIORITY, row); } else { return sortingPriority(HIGHPRIORITY, row) + m_layoutsTable[row].activities.count(); } } return sortingPriority(NORMALPRIORITY, row) + m_layoutsTable[row].activities.count(); } if (role == ORIGINALASSIGNEDACTIVITIESROLE) { return isNewLayout ? QStringList() : o_layoutsTable[row].activities; } if (role == Qt::UserRole) { return m_layoutsTable[row].activities; } break; case SHAREDCOLUMN: if (role == SORTINGROLE) { if (m_layoutsTable[row].shares.count() > 0) { //! highest priority based on number of shares return HIGHESTPRIORITY + m_layoutsTable[row].shares.count(); } if (m_layoutsTable[row].activities.contains(Data::Layout::FREEACTIVITIESID)) { //! high activity priority return HIGHPRIORITY; } return NORMALPRIORITY; } if (role == ORIGINALSHARESROLE) { return isNewLayout ? QStringList() : o_layoutsTable[row].shares; } if (role == Qt::UserRole) { return m_layoutsTable[row].shares; } break; default: return QVariant{}; }; return QVariant{}; } QStringList Layouts::cleanStrings(const QStringList &original, const QStringList &occupied) { QStringList result; for(int i=0; i roles; roles << Qt::DisplayRole; roles << Qt::UserRole; //! ActiveCurrent with no activities has highest priority QString activeCurrentId = o_layoutsTable.idForName(m_corona->layoutsManager()->currentLayoutName()); int row = m_layoutsTable.indexOf(activeCurrentId); if (row>=0 && !(m_inMultipleMode && m_layoutsTable[row].isShared()) && m_layoutsTable[row].activities.isEmpty()) { m_layoutsTable[row].activities << Data::Layout::FREEACTIVITIESID; emit dataChanged(index(row,BACKGROUNDCOLUMN), index(row,ACTIVITYCOLUMN), roles); return; } //! Active layouts with no activities have mid priority for(int i=0; i roles; roles << Qt::DisplayRole; roles << Qt::UserRole; roles << ASSIGNEDACTIVITIESROLE; bool freeActivitiesLayoutIsMissing{false}; if (m_layoutsTable[row].activities.contains(Data::Layout::FREEACTIVITIESID) && !activities.contains(Data::Layout::FREEACTIVITIESID)) { //! we need to reassign it properly freeActivitiesLayoutIsMissing = true; } m_layoutsTable[row].activities = activities; emit dataChanged(index(row, BACKGROUNDCOLUMN), index(row,ACTIVITYCOLUMN), roles); for(int i=0; i roles; roles << Qt::DisplayRole; QString oldId = m_layoutsTable[row].id; m_layoutsTable[row].id = newId; emit dataChanged(index(row, NAMECOLUMN), index(row,NAMECOLUMN), roles); for(int i=0; i= 0) { m_layoutsTable[i].shares[pos] = newId; emit dataChanged(index(i, NAMECOLUMN), index(i, NAMECOLUMN), roles); } } } bool Layouts::shareIsAvailable(const QString id) const { for(int i=0; i roles; roles << Qt::DisplayRole; roles << Qt::UserRole; m_layoutsTable[row].shares = shares; emit dataChanged(index(row,IDCOLUMN), index(row,SHAREDCOLUMN), roles); for(int i=0; i SHAREDCOLUMN) { return false; } QVector roles; roles << role; //! common roles for all row cells if (role == ISLOCKEDROLE) { m_layoutsTable[row].isLocked = value.toBool(); emit dataChanged(this->index(row,0), this->index(row,SHAREDCOLUMN), roles); return true; } //! specific roles to each independent cell switch (column) { case IDCOLUMN: if (role==Qt::UserRole) { setId(row, value.toString()); emit dataChanged(index, index, roles); return true; } break; case HIDDENTEXTCOLUMN: return true; break; case BACKGROUNDCOLUMN: if (role == Qt::UserRole) { QString back = value.toString(); if (back.startsWith("/")) { m_layoutsTable[row].background = back; } else { m_layoutsTable[row].background = QString(); m_layoutsTable[row].color = back; } emit dataChanged(index, index, roles); return true; } break; case NAMECOLUMN: if (role == Qt::UserRole) { QString provenId = m_layoutsTable.idForName(value.toString()); if (!provenId.isEmpty() && provenId != m_layoutsTable[row].id /*not the same row*/ ){ //! duplicate name should be rejected emit nameDuplicated(provenId, m_layoutsTable[row].id); return false; } else { m_layoutsTable[row].name = value.toString(); emit dataChanged(index, index, roles); return true; } } break; case MENUCOLUMN: if (role == Qt::UserRole) { m_layoutsTable[row].isShownInMenu = value.toBool(); emit dataChanged(index, index, roles); emit dataChanged(this->index(row, NAMECOLUMN), this->index(row,NAMECOLUMN), roles); return true; } break; case BORDERSCOLUMN: if (role == Qt::UserRole) { m_layoutsTable[row].hasDisabledBorders = value.toBool(); emit dataChanged(index, index, roles); emit dataChanged(this->index(row, NAMECOLUMN), this->index(row,NAMECOLUMN), roles); return true; } break; case ACTIVITYCOLUMN: if (role == Qt::UserRole) { setActivities(row, value.toStringList()); emit dataChanged(this->index(row, NAMECOLUMN), this->index(row,NAMECOLUMN), roles); return true; } break; case SHAREDCOLUMN: if (role == Qt::UserRole) { setShares(row, value.toStringList()); emit dataChanged(this->index(row, NAMECOLUMN), this->index(row,NAMECOLUMN), roles); return true; } else if (role == SHAREDTOINEDITROLE) { bool inEdit = value.toBool(); m_sharedToInEditRow = inEdit ? row : -1; roles << Qt::DisplayRole; roles << Qt::UserRole; roles << SHAREDTOINEDITROLE; emit dataChanged(this->index(row, ACTIVITYCOLUMN), this->index(row, SHAREDCOLUMN), roles); emit dataChanged(this->index(row, NAMECOLUMN), this->index(row,NAMECOLUMN), roles); return true; } break; }; return false; } void Layouts::updateActiveStates() { QVector roles; roles << Qt::DisplayRole; roles << Qt::UserRole; roles << ISACTIVEROLE; for(int i=0; ilayoutsManager()->synchronizer()->layout(m_layoutsTable[i].name) || (!m_inMultipleMode && o_layoutsTable[i].name == m_corona->layoutsManager()->currentLayoutName())) { iActive = true; } if (m_layoutsTable[i].isActive != iActive) { m_layoutsTable[i].isActive = iActive; emit dataChanged(index(i, BACKGROUNDCOLUMN), index(i,SHAREDCOLUMN), roles); } } } int Layouts::rowForId(const QString &id) const { return m_layoutsTable.indexOf(id); } const Data::Layout &Layouts::at(const int &row) { return m_layoutsTable[row]; } const Data::Layout &Layouts::currentData(const QString &id) { return m_layoutsTable[id]; } const Data::Layout Layouts::originalData(const QString &id) { if (o_layoutsTable.containsId(id)){ return o_layoutsTable[id]; } return Data::Layout(); } const Data::LayoutsTable &Layouts::originalLayoutsData() { return o_layoutsTable; } const Data::LayoutsTable &Layouts::currentLayoutsData() { return m_layoutsTable; } void Layouts::setOriginalData(Data::LayoutsTable &data, const bool &inmultiple) { clear(); beginInsertRows(QModelIndex(), 0, data.rowCount() - 1); o_inMultipleMode = inmultiple; o_layoutsTable = data; m_layoutsTable = data; for(int i=0; ilayoutsManager()->synchronizer()->layout(o_layoutsTable[i].name); } endInsertRows(); setInMultipleMode(inmultiple); emit rowsInserted(); } QList Layouts::alteredLayouts() const { QList layouts; for(int i=0; ilayoutsManager()->synchronizer()->activities();; for(const auto &id: activities) { KActivities::Info info(id); if (info.state() != KActivities::Info::Invalid) { on_activityAdded(id); } } connect(m_corona->activitiesConsumer(), &KActivities::Consumer::activityAdded, this, &Layouts::on_activityAdded); connect(m_corona->activitiesConsumer(), &KActivities::Consumer::activityRemoved, this, &Layouts::on_activityRemoved); connect(m_corona->activitiesConsumer(), &KActivities::Consumer::runningActivitiesChanged, this, &Layouts::on_runningActivitiesChanged); activitiesStatesChanged(); } void Layouts::activitiesStatesChanged() { QVector roles; roles << Qt::DisplayRole; roles << Qt::UserRole; roles << ALLACTIVITIESDATAROLE; roles << ALLACTIVITIESSORTEDROLE; emit dataChanged(index(0, BACKGROUNDCOLUMN), index(rowCount()-1, BACKGROUNDCOLUMN), roles); emit dataChanged(index(0, ACTIVITYCOLUMN), index(rowCount()-1, ACTIVITYCOLUMN), roles); } void Layouts::on_activityAdded(const QString &id) { m_activitiesInfo[id] = new KActivities::Info(id, this); Data::Activity activity; activity.id = m_activitiesInfo[id]->id(); activity.name = m_activitiesInfo[id]->name(); activity.icon = m_activitiesInfo[id]->icon(); activity.state = m_activitiesInfo[id]->state(); m_activitiesMap[id] = activity; connect(m_activitiesInfo[id], &KActivities::Info::nameChanged, [this, id]() { on_activityChanged(id); }); connect(m_activitiesInfo[id], &KActivities::Info::iconChanged, [this, id]() { on_activityChanged(id); }); } void Layouts::on_activityRemoved(const QString &id) { if (m_activitiesMap.contains(id)) { m_activitiesMap.remove(id); } if (m_activitiesInfo.contains(id)) { KActivities::Info *info = m_activitiesInfo.take(id); info->deleteLater(); } activitiesStatesChanged(); } void Layouts::on_activityChanged(const QString &id) { if (m_activitiesMap.contains(id) && m_activitiesInfo.contains(id)) { m_activitiesMap[id].name = m_activitiesInfo[id]->name(); m_activitiesMap[id].icon = m_activitiesInfo[id]->icon(); m_activitiesMap[id].state = m_activitiesInfo[id]->state(); activitiesStatesChanged(); } } void Layouts::on_runningActivitiesChanged(const QStringList &runningIds) { Data::ActivitiesMap::iterator i; for (i = m_activitiesMap.begin(); i != m_activitiesMap.end(); ++i){ if (runningIds.contains(i.key())) { m_activitiesMap[i.key()].state = KActivities::Info::Running; } else { m_activitiesMap[i.key()].state = KActivities::Info::Stopped; } } activitiesStatesChanged(); } } } } diff --git a/app/settings/models/layoutsmodel.h b/app/settings/models/layoutsmodel.h index c4b38f85..9c64e8bd 100644 --- a/app/settings/models/layoutsmodel.h +++ b/app/settings/models/layoutsmodel.h @@ -1,198 +1,199 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef SETTINGSLAYOUTSMODEL_H #define SETTINGSLAYOUTSMODEL_H // local #include "../data/activitydata.h" #include "../data/layoutdata.h" #include "../data/layouticondata.h" #include "../data/layoutstable.h" #include "../../lattecorona.h" // Qt #include #include namespace Latte { namespace Settings { namespace Model { class Layouts : public QAbstractTableModel { Q_OBJECT public: enum Columns { IDCOLUMN = 0, HIDDENTEXTCOLUMN, BACKGROUNDCOLUMN, NAMECOLUMN, MENUCOLUMN, BORDERSCOLUMN, ACTIVITYCOLUMN, SHAREDCOLUMN }; enum LayoutUserRoles { IDROLE = Qt::UserRole + 1, ISACTIVEROLE, ISLOCKEDROLE, ISSHAREDROLE, INMULTIPLELAYOUTSROLE, ASSIGNEDACTIVITIESROLE, ASSIGNEDACTIVITIESFROMSHAREDROLE, ALLACTIVITIESSORTEDROLE, ALLACTIVITIESDATAROLE, ALLLAYOUTSROLE, SHAREDTOINEDITROLE, SORTINGROLE, ISNEWLAYOUTROLE, LAYOUTHASCHANGESROLE, ORIGINALISSHOWNINMENUROLE, ORIGINALHASBORDERSROLE, ORIGINALASSIGNEDACTIVITIESROLE, ORIGINALSHARESROLE }; enum SortingPriority { NORMALPRIORITY = 8000, MEDIUMPRIORITY = 6000, HIGHPRIORITY = 4000, HIGHESTPRIORITY = 2000 }; explicit Layouts(QObject *parent, Latte::Corona *corona); ~Layouts(); bool containsCurrentName(const QString &name) const; bool dataAreChanged() const; bool inMultipleMode() const; void setInMultipleMode(bool inMultiple); int rowCount() const; int rowCount(const QModelIndex &parent) const override; int columnCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; const Data::Layout &at(const int &row); const Data::Layout ¤tData(const QString &id); const Data::Layout originalData(const QString &id); bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; int rowForId(const QString &id) const; void clear(); //! all current data will become also original void applyData(); //! all original data will become also current void resetData(); - void appendLayout(const Settings::Data::Layout &layout); + void appendLayout(const Data::Layout &layout); void removeLayout(const QString &id); + void setLayoutProperties(const Data::Layout &layout); QString layoutNameForFreeActivities() const; void setCurrentLayoutForFreeActivities(const QString &id); void setOriginalLayoutForFreeActivities(const QString &id); void setIconsPath(QString iconsPath); bool shareIsAvailable(const QString id) const; QStringList availableShareIdsFor(const QString id) const; QList alteredLayouts() const; const Data::LayoutsTable ¤tLayoutsData(); const Data::LayoutsTable &originalLayoutsData(); void setOriginalData(Data::LayoutsTable &data, const bool &inmultiple); signals: void inMultipleModeChanged(); void nameDuplicated(const QString &provenId, const QString &trialId); void rowsInserted(); private slots: void updateActiveStates(); void activitiesStatesChanged(); void on_activityAdded(const QString &id); void on_activityRemoved(const QString &id); void on_activityChanged(const QString &id); void on_runningActivitiesChanged(const QStringList &runningIds); private: void initActivities(); void assignFreeActivitiesLayoutAt(const QString &layoutName); void autoAssignFreeActivitiesLayout(); void setActivities(const int &row, const QStringList &activities); void setId(const int &row, const QString &newId); void setShares(const int &row, const QStringList &shares); QString sortingPriority(const SortingPriority &priority, const int &row) const; QString sortableText(const int &priority, const int &row) const; QStringList cleanStrings(const QStringList &original, const QStringList &occupied); QStringList assignedActivitiesFromShared(const int &row) const; QList icons(const int &row) const; private: //! break MVC only when a SharedTo editor is created //! because we want to move the dot indicator in the Activities delegate //! when that happens int m_sharedToInEditRow; QString m_iconsPath; Data::ActivitiesMap m_activitiesMap; QHash m_activitiesInfo; //! original data bool o_inMultipleMode{false}; Settings::Data::LayoutsTable o_layoutsTable; //! current data bool m_inMultipleMode{false}; Data::LayoutsTable m_layoutsTable; Latte::Corona *m_corona{nullptr}; }; } } } #endif