File indexing completed on 2024-10-06 08:01:43
0001 /* 0002 SPDX-FileCopyrightText: 2020 Michail Vourlakos <mvourlakos@gmail.com> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "layoutsmodel.h" 0007 0008 // local 0009 #include "../../data/layoutdata.h" 0010 #include "../../layouts/manager.h" 0011 #include "../../layouts/synchronizer.h" 0012 #include "../../settings/universalsettings.h" 0013 0014 // Qt 0015 #include <QDebug> 0016 #include <QFileInfo> 0017 #include <QFont> 0018 #include <QIcon> 0019 0020 // KDE 0021 #include <KLocalizedString> 0022 0023 // KActivities 0024 #include <KActivities/Consumer> 0025 #include <KActivities/Info> 0026 0027 namespace Latte { 0028 namespace Settings { 0029 namespace Model { 0030 0031 Layouts::Layouts(QObject *parent, Latte::Corona *corona) 0032 : QAbstractTableModel(parent), 0033 m_corona(corona) 0034 { 0035 initActivities(); 0036 0037 connect(this, &Layouts::inMultipleModeChanged, this, [&]() { 0038 QVector<int> roles; 0039 roles << Qt::DisplayRole; 0040 roles << Qt::UserRole; 0041 roles << INMULTIPLELAYOUTSROLE; 0042 0043 emit dataChanged(index(0, NAMECOLUMN), index(rowCount()-1, ACTIVITYCOLUMN), roles); 0044 }); 0045 0046 connect(this, &Layouts::activitiesStatesChanged, this, &Layouts::onActivitiesStatesChanged); 0047 0048 connect(m_corona->universalSettings(), &Latte::UniversalSettings::singleModeLayoutNameChanged, this, &Layouts::updateActiveStates); //! sort properly when switching single layouts 0049 connect(m_corona->layoutsManager()->synchronizer(), &Latte::Layouts::Synchronizer::centralLayoutsChanged, this, &Layouts::updateActiveStates); 0050 0051 connect(this, &Layouts::activitiesStatesChanged, this, &Layouts::updateConsideredActiveStates); 0052 connect(this, &Layouts::inMultipleModeChanged, this, &Layouts::updateConsideredActiveStates); 0053 connect(m_corona->layoutsManager()->synchronizer(), &Latte::Layouts::Synchronizer::centralLayoutsChanged, this, &Layouts::updateConsideredActiveStates); 0054 connect(m_corona->universalSettings(), &Latte::UniversalSettings::singleModeLayoutNameChanged, this, &Layouts::updateConsideredActiveStates); 0055 } 0056 0057 Layouts::~Layouts() 0058 { 0059 qDeleteAll(m_activitiesInfo); 0060 } 0061 0062 bool Layouts::containsCurrentName(const QString &name) const 0063 { 0064 return m_layoutsTable.containsName(name); 0065 } 0066 0067 bool Layouts::hasChangedData() const 0068 { 0069 return modeIsChanged() || layoutsAreChanged(); 0070 } 0071 0072 bool Layouts::modeIsChanged() const 0073 { 0074 return o_inMultipleMode != m_inMultipleMode; 0075 } 0076 0077 bool Layouts::layoutsAreChanged() const 0078 { 0079 return o_layoutsTable != m_layoutsTable; 0080 } 0081 0082 bool Layouts::inMultipleMode() const 0083 { 0084 return m_inMultipleMode; 0085 } 0086 0087 void Layouts::setInMultipleMode(bool inMultiple) 0088 { 0089 if (m_inMultipleMode == inMultiple) { 0090 return; 0091 } 0092 0093 m_inMultipleMode = inMultiple; 0094 emit inMultipleModeChanged(); 0095 } 0096 0097 bool Layouts::hasEnabledLayout() const 0098 { 0099 for (int i=0; i<m_layoutsTable.rowCount(); ++i) { 0100 if (m_layoutsTable[i].activities.count() > 0) { 0101 return true; 0102 } 0103 } 0104 0105 return false; 0106 } 0107 0108 bool Layouts::hasEnabledLayoutInAllActitivities() const 0109 { 0110 for (int i=0; i<m_layoutsTable.rowCount(); ++i) { 0111 if (m_layoutsTable[i].activities.contains(Data::Layout::ALLACTIVITIESID)) { 0112 return true; 0113 } 0114 } 0115 0116 return false; 0117 } 0118 0119 bool Layouts::hasEnabledLayoutInFreeActivities() const 0120 { 0121 for (int i=0; i<m_layoutsTable.rowCount(); ++i) { 0122 if (m_layoutsTable[i].activities.contains(Data::Layout::FREEACTIVITIESID)) { 0123 return true; 0124 } 0125 } 0126 0127 return false; 0128 } 0129 0130 bool Layouts::hasEnabledLayoutInCurrentActivity() const 0131 { 0132 QString curActivityId = currentActivityId(); 0133 0134 for (int i=0; i<m_layoutsTable.rowCount(); ++i) { 0135 if (m_layoutsTable[i].activities.contains(curActivityId)) { 0136 return true; 0137 } 0138 } 0139 0140 return false; 0141 } 0142 0143 int Layouts::rowCount() const 0144 { 0145 return m_layoutsTable.rowCount(); 0146 } 0147 0148 int Layouts::rowCount(const QModelIndex &parent) const 0149 { 0150 Q_UNUSED(parent); 0151 0152 return m_layoutsTable.rowCount(); 0153 } 0154 0155 int Layouts::columnCount(const QModelIndex &parent) const 0156 { 0157 Q_UNUSED(parent); 0158 0159 return ACTIVITYCOLUMN+1; 0160 } 0161 0162 QString Layouts::currentActivityId() const 0163 { 0164 return m_corona->activitiesConsumer()->currentActivity(); 0165 } 0166 0167 void Layouts::clear() 0168 { 0169 if (m_layoutsTable.rowCount() > 0) { 0170 beginRemoveRows(QModelIndex(), 0, m_layoutsTable.rowCount() - 1); 0171 m_layoutsTable.clear(); 0172 endRemoveRows(); 0173 } 0174 } 0175 0176 void Layouts::appendLayout(const Latte::Data::Layout &layout) 0177 { 0178 int newRow = m_layoutsTable.sortedPosForName(layout.name); 0179 0180 beginInsertRows(QModelIndex(), newRow, newRow); 0181 m_layoutsTable.insert(newRow, layout); 0182 endInsertRows(); 0183 0184 emit rowsInserted(); 0185 } 0186 0187 void Layouts::appendOriginalLayout(const Latte::Data::Layout &layout) 0188 { 0189 int newRow = o_layoutsTable.sortedPosForName(layout.name); 0190 o_layoutsTable.insert(newRow, layout); 0191 0192 appendLayout(layout); 0193 } 0194 0195 void Layouts::applyData() 0196 { 0197 QVector<int> roles; 0198 roles << Qt::DisplayRole; 0199 roles << Qt::UserRole; 0200 0201 o_inMultipleMode = m_inMultipleMode; 0202 o_layoutsTable = m_layoutsTable; 0203 0204 emit dataChanged(index(0, BACKGROUNDCOLUMN), index(rowCount()-1, ACTIVITYCOLUMN), roles); 0205 } 0206 0207 void Layouts::resetData() 0208 { 0209 clear(); 0210 setOriginalInMultipleMode(o_inMultipleMode); 0211 setOriginalData(o_layoutsTable); 0212 } 0213 0214 void Layouts::removeLayout(const QString &id) 0215 { 0216 int index = m_layoutsTable.indexOf(id); 0217 0218 if (index >= 0) { 0219 removeRows(index,1); 0220 } 0221 } 0222 0223 void Layouts::setLayoutProperties(const Latte::Data::Layout &layout) 0224 { 0225 if (m_layoutsTable.containsId(layout.id)) { 0226 m_layoutsTable[layout.id] = layout; 0227 int dataRow = m_layoutsTable.indexOf(layout.id); 0228 0229 QVector<int> roles; 0230 roles << Qt::DisplayRole; 0231 roles << Qt::UserRole; 0232 roles << ERRORSROLE; 0233 roles << WARNINGSROLE; 0234 emit dataChanged(index(dataRow, IDCOLUMN), index(dataRow, ACTIVITYCOLUMN), roles); 0235 } 0236 } 0237 0238 bool Layouts::removeRows(int row, int count, const QModelIndex &parent) 0239 { 0240 Q_UNUSED(parent) 0241 0242 int firstRow = row; 0243 int lastRow = row+count-1; 0244 0245 if (count > 0 && m_layoutsTable.rowExists(firstRow) && (m_layoutsTable.rowExists(lastRow))) { 0246 bool freeActivitiesLayoutIsRemoved{false}; 0247 0248 for(int i=firstRow; i<=lastRow; ++i) { 0249 if (m_layoutsTable[i].activities.contains(Latte::Data::Layout::FREEACTIVITIESID)) { 0250 //! we need to reassign it properly 0251 freeActivitiesLayoutIsRemoved = true; 0252 break; 0253 } 0254 } 0255 0256 beginRemoveRows(QModelIndex(), firstRow, lastRow); 0257 for(int i=0; i<count; ++i) { 0258 m_layoutsTable.remove(firstRow); 0259 } 0260 endRemoveRows(); 0261 0262 return true; 0263 } 0264 0265 return false; 0266 } 0267 0268 QString Layouts::layoutNameForFreeActivities() const 0269 { 0270 for(int i=0; i<rowCount(); ++i) { 0271 if (m_layoutsTable[i].activities.contains(Latte::Data::Layout::FREEACTIVITIESID)) { 0272 return m_layoutsTable[i].name; 0273 } 0274 } 0275 0276 return QString(); 0277 } 0278 0279 void Layouts::setCurrentLayoutForFreeActivities(const QString &id) 0280 { 0281 if (m_layoutsTable.containsId(id)) { 0282 m_layoutsTable.setLayoutForFreeActivities(id); 0283 0284 QVector<int> roles; 0285 roles << Qt::DisplayRole; 0286 roles << Qt::UserRole; 0287 emit dataChanged(index(0, ACTIVITYCOLUMN), index(rowCount()-1, ACTIVITYCOLUMN), roles); 0288 } 0289 } 0290 0291 void Layouts::setOriginalLayoutForFreeActivities(const QString &id) 0292 { 0293 if (o_layoutsTable.containsId(id)) { 0294 o_layoutsTable.setLayoutForFreeActivities(id); 0295 m_layoutsTable.setLayoutForFreeActivities(id); 0296 0297 QVector<int> roles; 0298 roles << Qt::DisplayRole; 0299 roles << Qt::UserRole; 0300 emit dataChanged(index(0, ACTIVITYCOLUMN), index(rowCount()-1, ACTIVITYCOLUMN), roles); 0301 } 0302 } 0303 0304 QVariant Layouts::headerData(int section, Qt::Orientation orientation, int role) const 0305 { 0306 if (orientation != Qt::Horizontal) { 0307 return QAbstractTableModel::headerData(section, orientation, role); 0308 } 0309 0310 if (role == Qt::FontRole) { 0311 QFont font = qvariant_cast<QFont>(QAbstractTableModel::headerData(section, orientation, role)); 0312 font.setBold(true); 0313 return font; 0314 } 0315 0316 switch(section) { 0317 case IDCOLUMN: 0318 if (role == Qt::DisplayRole) { 0319 return QString("#path"); 0320 } 0321 break; 0322 case HIDDENTEXTCOLUMN: 0323 if (role == Qt::DisplayRole) { 0324 return QString(""); 0325 } 0326 break; 0327 case BACKGROUNDCOLUMN: 0328 if (role == Qt::DisplayRole) { 0329 return QString(""); 0330 } else if (role == Qt::DecorationRole) { 0331 return QIcon::fromTheme("games-config-background"); 0332 } else if (role == Qt::TextAlignmentRole ){ 0333 return QVariant::fromValue(Qt::AlignHCenter | Qt::AlignVCenter); 0334 } 0335 break; 0336 case NAMECOLUMN: 0337 if (role == Qt::DisplayRole) { 0338 return QString(i18nc("column for layout name", "Name")); 0339 }/* else if (role == Qt::TextAlignmentRole) { 0340 return QVariant::fromValue(Qt::AlignLeft | Qt::AlignVCenter); 0341 }*/ 0342 break; 0343 case MENUCOLUMN: 0344 if (role == Qt::DisplayRole) { 0345 return QString(i18nc("column for layout to show in menu", "In Menu")); 0346 }/* else if (role == Qt::TextAlignmentRole ){ 0347 return QVariant::fromValue(Qt::AlignHCenter | Qt::AlignVCenter); 0348 }*/ 0349 break; 0350 case BORDERSCOLUMN: 0351 if (role == Qt::DisplayRole) { 0352 return QString(i18nc("column for layout to hide borders for maximized windows", "Borderless")); 0353 }/* else if (role == Qt::TextAlignmentRole ){ 0354 return QVariant::fromValue(Qt::AlignHCenter | Qt::AlignVCenter); 0355 }*/ 0356 break; 0357 case ACTIVITYCOLUMN: 0358 if (role == Qt::DisplayRole) { 0359 return QString(i18nc("column for layout to show which activities is assigned to", "Activities")); 0360 } else if (role == Qt::DecorationRole) { 0361 return QIcon::fromTheme("activities"); 0362 }/* else if (role == Qt::TextAlignmentRole ){ 0363 return QVariant::fromValue(Qt::AlignLeft | Qt::AlignVCenter); 0364 }*/ 0365 break; 0366 default: 0367 break; 0368 }; 0369 0370 return QAbstractTableModel::headerData(section, orientation, role); 0371 } 0372 0373 Qt::ItemFlags Layouts::flags(const QModelIndex &index) const 0374 { 0375 const int column = index.column(); 0376 const int row = index.row(); 0377 0378 auto flags = QAbstractTableModel::flags(index); 0379 0380 if (column == MENUCOLUMN || column == BORDERSCOLUMN) { 0381 flags |= Qt::ItemIsUserCheckable; 0382 } 0383 0384 if (column == ACTIVITYCOLUMN 0385 || column == NAMECOLUMN) { 0386 flags |= Qt::ItemIsEditable; 0387 } 0388 0389 return flags; 0390 } 0391 0392 Latte::Data::LayoutIcon Layouts::icon(const int &row) const 0393 { 0394 return m_corona->layoutsManager()->iconForLayout(m_layoutsTable[row]); 0395 } 0396 0397 const Latte::Data::LayoutIcon Layouts::currentLayoutIcon(const QString &id) const 0398 { 0399 int row = rowForId(id); 0400 0401 if (row >= 0) { 0402 return icon(row); 0403 } 0404 0405 return Latte::Data::LayoutIcon(); 0406 } 0407 0408 QString Layouts::sortableText(const int &priority, const int &row) const 0409 { 0410 QString numberPart; 0411 0412 if (priority < 10) { 0413 numberPart = "00000" + QString::number(priority); 0414 } else if (priority < 100) { 0415 numberPart = "0000" + QString::number(priority); 0416 } else if (priority < 1000) { 0417 numberPart = "000" + QString::number(priority); 0418 } else if (priority < 10000) { 0419 numberPart = "00" + QString::number(priority); 0420 } else if (priority < 100000) { 0421 numberPart = "0" + QString::number(priority); 0422 } 0423 0424 return (numberPart + m_layoutsTable[row].name); 0425 } 0426 0427 0428 QString Layouts::sortingPriority(const SortingPriority &priority, const int &row) const 0429 { 0430 int iPriority = (int)priority; 0431 0432 iPriority = (m_layoutsTable[row].isActive && inMultipleMode() ? iPriority - 1000 : iPriority); 0433 0434 return sortableText(iPriority, row); 0435 } 0436 0437 QVariant Layouts::data(const QModelIndex &index, int role) const 0438 { 0439 const int row = index.row(); 0440 int column = index.column(); 0441 bool isNewLayout = !o_layoutsTable.containsId(m_layoutsTable[row].id); 0442 0443 if (!m_layoutsTable.rowExists(row)) { 0444 return QVariant{}; 0445 } 0446 0447 //! original data 0448 Latte::Data::Layout original; 0449 0450 if (!isNewLayout) { 0451 original = o_layoutsTable[m_layoutsTable[row].id]; 0452 } 0453 0454 if (role == IDROLE) { 0455 return m_layoutsTable[row].id; 0456 } else if (role == ISACTIVEROLE) { 0457 return m_layoutsTable[row].isActive; 0458 } else if (role == ISCONSIDEREDACTIVEROLE) { 0459 return m_layoutsTable[row].isConsideredActive; 0460 } else if (role == ISLOCKEDROLE) { 0461 return m_layoutsTable[row].isLocked; 0462 } else if (role == INMULTIPLELAYOUTSROLE) { 0463 return inMultipleMode(); 0464 } else if (role == ASSIGNEDACTIVITIESROLE) { 0465 return m_layoutsTable[row].activities; 0466 } else if (role == ALLACTIVITIESSORTEDROLE) { 0467 QStringList activities; 0468 activities << QString(Latte::Data::Layout::ALLACTIVITIESID); 0469 activities << QString(Latte::Data::Layout::FREEACTIVITIESID); 0470 activities << QString(Latte::Data::Layout::CURRENTACTIVITYID); 0471 activities << m_corona->layoutsManager()->synchronizer()->activities(); 0472 return activities; 0473 } else if (role == ALLACTIVITIESDATAROLE) { 0474 QVariant activitiesData; 0475 activitiesData.setValue(m_activitiesTable); 0476 return activitiesData; 0477 } else if (role == ALLLAYOUTSROLE) { 0478 QVariant layouts; 0479 layouts.setValue(m_layoutsTable); 0480 return layouts; 0481 } else if (role == ISNEWLAYOUTROLE) { 0482 return isNewLayout; 0483 } else if (role == LAYOUTHASCHANGESROLE) { 0484 return isNewLayout ? true : (original != m_layoutsTable[row]); 0485 } else if (role == BACKGROUNDUSERROLE) { 0486 Latte::Data::LayoutIcon _icon = icon(row); 0487 QVariant iconVariant; 0488 iconVariant.setValue<Latte::Data::LayoutIcon>(_icon); 0489 return iconVariant; 0490 } else if (role == ERRORSROLE) { 0491 return m_layoutsTable[row].errors; 0492 } else if (role == WARNINGSROLE) { 0493 return m_layoutsTable[row].warnings; 0494 } 0495 0496 switch (column) { 0497 case IDCOLUMN: 0498 if (role == Qt::DisplayRole || role == Qt::UserRole){ 0499 return m_layoutsTable[row].id; 0500 } 0501 break; 0502 case HIDDENTEXTCOLUMN: 0503 return QVariant{}; 0504 case BACKGROUNDCOLUMN: 0505 if (role == SORTINGROLE) { 0506 return m_layoutsTable[row].name; 0507 } 0508 0509 if (role == Qt::DisplayRole) { 0510 return m_layoutsTable[row].background; 0511 } else if (role == Qt::UserRole) { 0512 Latte::Data::LayoutIcon _icon = icon(row); 0513 QVariant iconVariant; 0514 iconVariant.setValue<Latte::Data::LayoutIcon>(_icon); 0515 return iconVariant; 0516 } 0517 break; 0518 case NAMECOLUMN: 0519 if (role == SORTINGROLE) { 0520 if (m_layoutsTable[row].isConsideredActive) { 0521 return sortingPriority(HIGHESTPRIORITY, row); 0522 } 0523 0524 return sortingPriority(NORMALPRIORITY, row); 0525 } 0526 0527 if ((role == Qt::DisplayRole) || (role == Qt::UserRole)) { 0528 return m_layoutsTable[row].name; 0529 } 0530 break; 0531 case MENUCOLUMN: 0532 if (role == SORTINGROLE) { 0533 if (m_layoutsTable[row].isShownInMenu) { 0534 return sortingPriority(HIGHESTPRIORITY, row); 0535 } 0536 0537 return sortingPriority(NORMALPRIORITY, row); 0538 } 0539 0540 if (role == ORIGINALISSHOWNINMENUROLE) { 0541 return isNewLayout ? false : original.isShownInMenu; 0542 } 0543 0544 if (role == Qt::UserRole) { 0545 return m_layoutsTable[row].isShownInMenu; 0546 } 0547 break; 0548 case BORDERSCOLUMN: 0549 if (role == SORTINGROLE) { 0550 if (m_layoutsTable[row].hasDisabledBorders) { 0551 return sortingPriority(HIGHESTPRIORITY, row); 0552 } 0553 0554 return sortingPriority(NORMALPRIORITY, row); 0555 } 0556 0557 if (role == ORIGINALHASBORDERSROLE) { 0558 return isNewLayout ? false : original.hasDisabledBorders; 0559 } 0560 0561 if (role == Qt::UserRole) { 0562 return m_layoutsTable[row].hasDisabledBorders; 0563 } 0564 break; 0565 case ACTIVITYCOLUMN: 0566 if (role == SORTINGROLE) { 0567 if (m_layoutsTable[row].activities.count() > 0) { 0568 if (m_layoutsTable[row].activities.contains(Latte::Data::Layout::ALLACTIVITIESID)) { 0569 return sortingPriority(HIGHESTPRIORITY, row); 0570 } else if (m_layoutsTable[row].activities.contains(Latte::Data::Layout::FREEACTIVITIESID)) { 0571 return sortingPriority(HIGHPRIORITY, row); 0572 } else { 0573 return sortingPriority(MEDIUMPRIORITY, row) + m_layoutsTable[row].activities.count(); 0574 } 0575 } 0576 0577 return sortingPriority(NORMALPRIORITY, row) + m_layoutsTable[row].activities.count(); 0578 } 0579 0580 if (role == ORIGINALASSIGNEDACTIVITIESROLE) { 0581 return isNewLayout ? QStringList() : original.activities; 0582 } 0583 0584 if (role == Qt::UserRole) { 0585 return m_layoutsTable[row].activities; 0586 } 0587 break; 0588 default: 0589 return QVariant{}; 0590 }; 0591 0592 return QVariant{}; 0593 } 0594 0595 QStringList Layouts::cleanStrings(const QStringList &original, const QStringList &occupied) 0596 { 0597 QStringList result; 0598 0599 for(int i=0; i<original.count(); ++i) { 0600 if (!occupied.contains(original[i])) { 0601 result << original[i]; 0602 } 0603 } 0604 0605 return result; 0606 } 0607 0608 void Layouts::setOriginalActivitiesForLayout(const Latte::Data::Layout &layout) 0609 { 0610 if (o_layoutsTable.containsId(layout.id) && m_layoutsTable.containsId(layout.id)) { 0611 o_layoutsTable[layout.id].activities = layout.activities; 0612 0613 int mrow = rowForId(layout.id); 0614 setActivities(mrow, layout.activities); 0615 } 0616 } 0617 0618 void Layouts::setOriginalViewsForLayout(const Latte::Data::Layout &layout) 0619 { 0620 if (o_layoutsTable.containsId(layout.id) && m_layoutsTable.containsId(layout.id)) { 0621 o_layoutsTable[layout.id].views = layout.views; 0622 } 0623 } 0624 0625 void Layouts::setActivities(const int &row, const QStringList &activities) 0626 { 0627 if (!m_layoutsTable.rowExists(row) || m_layoutsTable[row].activities == activities) { 0628 return; 0629 } 0630 0631 QVector<int> roles; 0632 roles << Qt::DisplayRole; 0633 roles << Qt::UserRole; 0634 roles << ASSIGNEDACTIVITIESROLE; 0635 0636 m_layoutsTable[row].activities = activities; 0637 emit dataChanged(index(row, BACKGROUNDCOLUMN), index(row,ACTIVITYCOLUMN), roles); 0638 } 0639 0640 void Layouts::setId(const int &row, const QString &newId) 0641 { 0642 if (!m_layoutsTable.rowExists(row) || newId.isEmpty() || m_layoutsTable[row].id == newId) { 0643 return; 0644 } 0645 0646 QVector<int> roles; 0647 roles << Qt::DisplayRole; 0648 0649 QString oldId = m_layoutsTable[row].id; 0650 m_layoutsTable[row].id = newId; 0651 emit dataChanged(index(row, NAMECOLUMN), index(row,NAMECOLUMN), roles); 0652 } 0653 0654 bool Layouts::setData(const QModelIndex &index, const QVariant &value, int role) 0655 { 0656 const int row = index.row(); 0657 const int column = index.column(); 0658 0659 if (!m_layoutsTable.rowExists(row) || column<0 || column > ACTIVITYCOLUMN) { 0660 return false; 0661 } 0662 0663 QVector<int> roles; 0664 roles << role; 0665 0666 //! common roles for all row cells 0667 if (role == ISLOCKEDROLE) { 0668 m_layoutsTable[row].isLocked = value.toBool(); 0669 emit dataChanged(this->index(row,0), this->index(row, ACTIVITYCOLUMN), roles); 0670 return true; 0671 } 0672 0673 //! specific roles to each independent cell 0674 switch (column) { 0675 case IDCOLUMN: 0676 if (role==Qt::UserRole) { 0677 setId(row, value.toString()); 0678 emit dataChanged(index, index, roles); 0679 return true; 0680 } 0681 break; 0682 case HIDDENTEXTCOLUMN: 0683 return true; 0684 break; 0685 case BACKGROUNDCOLUMN: 0686 if (role == Qt::UserRole) { 0687 QString back = value.toString(); 0688 0689 if (back.startsWith("/")) { 0690 m_layoutsTable[row].background = back; 0691 } else { 0692 m_layoutsTable[row].background = QString(); 0693 m_layoutsTable[row].color = back; 0694 } 0695 emit dataChanged(index, index, roles); 0696 return true; 0697 } 0698 break; 0699 case NAMECOLUMN: 0700 if (role == Qt::UserRole) { 0701 QString provenId = m_layoutsTable.idForName(value.toString()); 0702 0703 if (!provenId.isEmpty() && provenId != m_layoutsTable[row].id /*not the same row*/ ){ 0704 //! duplicate name should be rejected 0705 emit nameDuplicated(provenId, m_layoutsTable[row].id); 0706 return false; 0707 } else { 0708 m_layoutsTable[row].name = value.toString(); 0709 emit dataChanged(index, index, roles); 0710 return true; 0711 } 0712 } 0713 break; 0714 case MENUCOLUMN: 0715 if (role == Qt::UserRole) { 0716 m_layoutsTable[row].isShownInMenu = value.toBool(); 0717 emit dataChanged(index, index, roles); 0718 emit dataChanged(this->index(row, NAMECOLUMN), this->index(row,NAMECOLUMN), roles); 0719 return true; 0720 } 0721 break; 0722 case BORDERSCOLUMN: 0723 if (role == Qt::UserRole) { 0724 m_layoutsTable[row].hasDisabledBorders = value.toBool(); 0725 emit dataChanged(index, index, roles); 0726 emit dataChanged(this->index(row, NAMECOLUMN), this->index(row,NAMECOLUMN), roles); 0727 return true; 0728 } 0729 break; 0730 case ACTIVITYCOLUMN: 0731 if (role == Qt::UserRole) { 0732 setActivities(row, value.toStringList()); 0733 updateConsideredActiveStates(); 0734 emit dataChanged(this->index(row, NAMECOLUMN), this->index(row,NAMECOLUMN), roles); 0735 return true; 0736 } 0737 break; 0738 }; 0739 0740 return false; 0741 } 0742 0743 void Layouts::updateActiveStates() 0744 { 0745 QVector<int> roles; 0746 roles << Qt::DisplayRole; 0747 roles << Qt::UserRole; 0748 roles << ISACTIVEROLE; 0749 roles << SORTINGROLE; 0750 0751 for(int i=0; i<rowCount(); ++i) { 0752 bool iActive{false}; 0753 0754 if (m_corona->layoutsManager()->synchronizer()->layout(m_layoutsTable[i].name)) { 0755 iActive = true; 0756 } 0757 0758 if (m_layoutsTable[i].isActive != iActive) { 0759 m_layoutsTable[i].isActive = iActive; 0760 emit dataChanged(index(i, BACKGROUNDCOLUMN), index(i,ACTIVITYCOLUMN), roles); 0761 } 0762 } 0763 } 0764 0765 void Layouts::updateConsideredActiveStates() 0766 { 0767 QVector<int> roles; 0768 roles << Qt::DisplayRole; 0769 roles << Qt::UserRole; 0770 roles << ISCONSIDEREDACTIVEROLE; 0771 roles << SORTINGROLE; 0772 0773 if (!m_inMultipleMode) { 0774 //! single mode but not the running one 0775 0776 for(int i=0; i<rowCount(); ++i) { 0777 bool iConsideredActive{false}; 0778 0779 if (m_corona->universalSettings()->singleModeLayoutName() == m_layoutsTable[i].name) { 0780 iConsideredActive = true; 0781 } 0782 0783 if (m_layoutsTable[i].isConsideredActive != iConsideredActive) { 0784 m_layoutsTable[i].isConsideredActive = iConsideredActive; 0785 emit dataChanged(index(i, BACKGROUNDCOLUMN), index(i,ACTIVITYCOLUMN), roles); 0786 } 0787 } 0788 } else if (m_inMultipleMode) { 0789 //! multiple mode but not the running one 0790 0791 QStringList runningActivities = m_corona->layoutsManager()->synchronizer()->runningActivities(); 0792 QStringList freeRunningActivities = m_corona->layoutsManager()->synchronizer()->freeRunningActivities(); 0793 0794 for(int i=0; i<rowCount(); ++i) { 0795 bool iConsideredActive{false}; 0796 0797 if (m_layoutsTable[i].activities.contains(Latte::Data::Layout::ALLACTIVITIESID)) { 0798 iConsideredActive = true; 0799 } else if (freeRunningActivities.count()>0 && m_layoutsTable[i].activities.contains(Latte::Data::Layout::FREEACTIVITIESID)) { 0800 iConsideredActive = true; 0801 } else if (m_layoutsTable[i].activities.count()>0 && containsSpecificRunningActivity(runningActivities, m_layoutsTable[i])) { 0802 iConsideredActive = true; 0803 } else { 0804 iConsideredActive = false; 0805 } 0806 0807 if (m_layoutsTable[i].isConsideredActive != iConsideredActive) { 0808 m_layoutsTable[i].isConsideredActive = iConsideredActive; 0809 emit dataChanged(index(i, BACKGROUNDCOLUMN), index(i,ACTIVITYCOLUMN), roles); 0810 } 0811 } 0812 } 0813 } 0814 0815 int Layouts::rowForId(const QString &id) const 0816 { 0817 return m_layoutsTable.indexOf(id); 0818 } 0819 0820 const Latte::Data::Layout &Layouts::at(const int &row) 0821 { 0822 return m_layoutsTable[row]; 0823 } 0824 0825 const Latte::Data::Layout &Layouts::currentData(const QString &id) 0826 { 0827 if (m_layoutsTable.containsId(id)){ 0828 return m_layoutsTable[id]; 0829 } 0830 0831 return Latte::Data::Layout(); 0832 } 0833 0834 0835 const Latte::Data::Layout Layouts::originalData(const QString &id) 0836 { 0837 if (o_layoutsTable.containsId(id)){ 0838 return o_layoutsTable[id]; 0839 } 0840 0841 return Latte::Data::Layout(); 0842 } 0843 0844 const Latte::Data::LayoutsTable &Layouts::originalLayoutsData() 0845 { 0846 return o_layoutsTable; 0847 } 0848 0849 const Latte::Data::LayoutsTable &Layouts::currentLayoutsData() 0850 { 0851 return m_layoutsTable; 0852 } 0853 0854 void Layouts::setOriginalInMultipleMode(const bool &inmultiple) 0855 { 0856 setInMultipleMode(inmultiple); 0857 0858 if (o_inMultipleMode == inmultiple) { 0859 return; 0860 } 0861 0862 o_inMultipleMode = inmultiple; 0863 } 0864 0865 void Layouts::setOriginalData(Latte::Data::LayoutsTable &data) 0866 { 0867 clear(); 0868 0869 beginInsertRows(QModelIndex(), 0, data.rowCount() - 1); 0870 o_layoutsTable = data; 0871 m_layoutsTable = data; 0872 endInsertRows(); 0873 0874 emit rowsInserted(); 0875 0876 updateActiveStates(); 0877 updateConsideredActiveStates(); 0878 } 0879 0880 QList<Latte::Data::Layout> Layouts::alteredLayouts() const 0881 { 0882 QList<Latte::Data::Layout> layouts; 0883 0884 for(int i=0; i<rowCount(); ++i) { 0885 QString currentId = m_layoutsTable[i].id; 0886 0887 if ((!o_layoutsTable.containsId(currentId)) 0888 || m_layoutsTable[currentId] != o_layoutsTable[currentId]) { 0889 layouts << m_layoutsTable[i]; 0890 } 0891 } 0892 0893 return layouts; 0894 } 0895 0896 //! Activities code 0897 void Layouts::initActivities() 0898 { 0899 Latte::Data::Activity allActivities; 0900 allActivities.id = Latte::Data::Layout::ALLACTIVITIESID; 0901 allActivities.name = QString("[ " + i18n("All Activities") + " ]"); 0902 allActivities.icon = "activities"; 0903 allActivities.state = KActivities::Info::Stopped; 0904 m_activitiesTable << allActivities; 0905 0906 Latte::Data::Activity freeActivities; 0907 freeActivities.id = Latte::Data::Layout::FREEACTIVITIESID; 0908 freeActivities.name = QString("[ " + i18n("Free Activities") + " ]"); 0909 freeActivities.icon = "activities"; 0910 freeActivities.state = KActivities::Info::Stopped; 0911 m_activitiesTable << freeActivities; 0912 0913 Latte::Data::Activity currentActivity; 0914 currentActivity.id = Latte::Data::Layout::CURRENTACTIVITYID; 0915 currentActivity.name = QString("[ " + i18n("Current Activity") + " ]"); 0916 currentActivity.icon = "dialog-yes"; 0917 currentActivity.state = KActivities::Info::Stopped; 0918 m_activitiesTable << currentActivity; 0919 0920 QStringList activities = m_corona->layoutsManager()->synchronizer()->activities();; 0921 0922 for(const auto &id: activities) { 0923 KActivities::Info info(id); 0924 0925 if (info.state() != KActivities::Info::Invalid) { 0926 onActivityAdded(id); 0927 } 0928 } 0929 0930 connect(m_corona->activitiesConsumer(), &KActivities::Consumer::activityAdded, this, &Layouts::onActivityAdded); 0931 connect(m_corona->activitiesConsumer(), &KActivities::Consumer::activityRemoved, this, &Layouts::onActivityRemoved); 0932 connect(m_corona->activitiesConsumer(), &KActivities::Consumer::runningActivitiesChanged, this, &Layouts::onRunningActivitiesChanged); 0933 0934 emit activitiesStatesChanged(); 0935 } 0936 0937 void Layouts::onActivitiesStatesChanged() 0938 { 0939 QVector<int> roles; 0940 roles << Qt::DisplayRole; 0941 roles << Qt::UserRole; 0942 roles << ALLACTIVITIESDATAROLE; 0943 roles << ALLACTIVITIESSORTEDROLE; 0944 0945 emit dataChanged(index(0, BACKGROUNDCOLUMN), index(rowCount()-1, BACKGROUNDCOLUMN), roles); 0946 emit dataChanged(index(0, ACTIVITYCOLUMN), index(rowCount()-1, ACTIVITYCOLUMN), roles); 0947 } 0948 0949 void Layouts::onActivityAdded(const QString &id) 0950 { 0951 m_activitiesInfo[id] = new KActivities::Info(id, this); 0952 0953 Latte::Data::Activity activity; 0954 activity.id = m_activitiesInfo[id]->id(); 0955 activity.name = m_activitiesInfo[id]->name(); 0956 activity.icon = m_activitiesInfo[id]->icon(); 0957 activity.state = m_activitiesInfo[id]->state(); 0958 activity.isCurrent = m_activitiesInfo[id]->isCurrent(); 0959 0960 if (!m_activitiesTable.containsId(id)) { 0961 m_activitiesTable << activity; 0962 } else { 0963 m_activitiesTable[id] = activity; 0964 } 0965 0966 connect(m_activitiesInfo[id], &KActivities::Info::nameChanged, [this, id]() { 0967 onActivityChanged(id); 0968 }); 0969 0970 connect(m_activitiesInfo[id], &KActivities::Info::iconChanged, [this, id]() { 0971 onActivityChanged(id); 0972 }); 0973 0974 connect(m_activitiesInfo[id], &KActivities::Info::isCurrentChanged, [this, id]() { 0975 onActivityChanged(id); 0976 }); 0977 } 0978 0979 void Layouts::onActivityRemoved(const QString &id) 0980 { 0981 if (m_activitiesTable.containsId(id)) { 0982 m_activitiesTable.remove(id); 0983 } 0984 0985 if (m_activitiesInfo.contains(id)) { 0986 KActivities::Info *info = m_activitiesInfo.take(id); 0987 info->deleteLater(); 0988 } 0989 0990 emit activitiesStatesChanged(); 0991 } 0992 0993 void Layouts::onActivityChanged(const QString &id) 0994 { 0995 if (m_activitiesTable.containsId(id) && m_activitiesInfo.contains(id)) { 0996 m_activitiesTable[id].name = m_activitiesInfo[id]->name(); 0997 m_activitiesTable[id].icon = m_activitiesInfo[id]->icon(); 0998 m_activitiesTable[id].state = m_activitiesInfo[id]->state(); 0999 m_activitiesTable[id].isCurrent = m_activitiesInfo[id]->isCurrent(); 1000 1001 emit activitiesStatesChanged(); 1002 } 1003 } 1004 1005 void Layouts::onRunningActivitiesChanged(const QStringList &runningIds) 1006 { 1007 for (int i = 0; i < m_activitiesTable.rowCount(); ++i) { 1008 if (runningIds.contains(m_activitiesTable[i].id)) { 1009 m_activitiesTable[i].state = KActivities::Info::Running; 1010 } else { 1011 m_activitiesTable[i].state = KActivities::Info::Stopped; 1012 } 1013 } 1014 1015 emit activitiesStatesChanged(); 1016 } 1017 1018 bool Layouts::containsSpecificRunningActivity(const QStringList &runningIds, const Latte::Data::Layout &layout) const 1019 { 1020 if (runningIds.count()>0 && layout.activities.count()>0) { 1021 for (int i=0; i<layout.activities.count(); ++i) { 1022 if (runningIds.contains(layout.activities[i])) { 1023 return true; 1024 } 1025 } 1026 } 1027 1028 return false; 1029 } 1030 1031 } 1032 } 1033 }