Changeset View
Changeset View
Standalone View
Standalone View
kcmkwin/common/effectsmodel.cpp
Show First 20 Lines • Show All 109 Lines • ▼ Show 20 Line(s) | 94 | { | |||
---|---|---|---|---|---|
110 | roleNames[ConfigurableRole] = "ConfigurableRole"; | 110 | roleNames[ConfigurableRole] = "ConfigurableRole"; | ||
111 | roleNames[ScriptedRole] = QByteArrayLiteral("ScriptedRole"); | 111 | roleNames[ScriptedRole] = QByteArrayLiteral("ScriptedRole"); | ||
112 | roleNames[EnabledByDefaultRole] = "EnabledByDefaultRole"; | 112 | roleNames[EnabledByDefaultRole] = "EnabledByDefaultRole"; | ||
113 | return roleNames; | 113 | return roleNames; | ||
114 | } | 114 | } | ||
115 | 115 | | |||
116 | QModelIndex EffectsModel::index(int row, int column, const QModelIndex &parent) const | 116 | QModelIndex EffectsModel::index(int row, int column, const QModelIndex &parent) const | ||
117 | { | 117 | { | ||
118 | if (parent.isValid() || column > 0 || column < 0 || row < 0 || row >= m_effectsList.count()) { | 118 | if (parent.isValid() || column > 0 || column < 0 || row < 0 || row >= m_effects.count()) { | ||
119 | return {}; | 119 | return {}; | ||
120 | } | 120 | } | ||
121 | 121 | | |||
122 | return createIndex(row, column); | 122 | return createIndex(row, column); | ||
123 | } | 123 | } | ||
124 | 124 | | |||
125 | QModelIndex EffectsModel::parent(const QModelIndex &child) const | 125 | QModelIndex EffectsModel::parent(const QModelIndex &child) const | ||
126 | { | 126 | { | ||
127 | Q_UNUSED(child) | 127 | Q_UNUSED(child) | ||
128 | return {}; | 128 | return {}; | ||
129 | } | 129 | } | ||
130 | 130 | | |||
131 | int EffectsModel::columnCount(const QModelIndex &parent) const | 131 | int EffectsModel::columnCount(const QModelIndex &parent) const | ||
132 | { | 132 | { | ||
133 | Q_UNUSED(parent) | 133 | Q_UNUSED(parent) | ||
134 | return 1; | 134 | return 1; | ||
135 | } | 135 | } | ||
136 | 136 | | |||
137 | int EffectsModel::rowCount(const QModelIndex &parent) const | 137 | int EffectsModel::rowCount(const QModelIndex &parent) const | ||
138 | { | 138 | { | ||
139 | if (parent.isValid()) { | 139 | if (parent.isValid()) { | ||
140 | return 0; | 140 | return 0; | ||
141 | } | 141 | } | ||
142 | return m_effectsList.count(); | 142 | return m_effects.count(); | ||
143 | } | 143 | } | ||
144 | 144 | | |||
145 | QVariant EffectsModel::data(const QModelIndex &index, int role) const | 145 | QVariant EffectsModel::data(const QModelIndex &index, int role) const | ||
146 | { | 146 | { | ||
147 | if (!index.isValid()) { | 147 | if (!index.isValid()) { | ||
148 | return {}; | 148 | return {}; | ||
149 | } | 149 | } | ||
150 | 150 | | |||
151 | const EffectData effect = m_effectsList.at(index.row()); | 151 | const EffectData effect = m_effects.at(index.row()); | ||
152 | switch (role) { | 152 | switch (role) { | ||
153 | case Qt::DisplayRole: | 153 | case Qt::DisplayRole: | ||
154 | case NameRole: | 154 | case NameRole: | ||
155 | return effect.name; | 155 | return effect.name; | ||
156 | case DescriptionRole: | 156 | case DescriptionRole: | ||
157 | return effect.description; | 157 | return effect.description; | ||
158 | case AuthorNameRole: | 158 | case AuthorNameRole: | ||
159 | return effect.authorName; | 159 | return effect.authorName; | ||
Show All 37 Lines | 196 | { | |||
197 | if (!index.isValid()) { | 197 | if (!index.isValid()) { | ||
198 | return QAbstractItemModel::setData(index, value, role); | 198 | return QAbstractItemModel::setData(index, value, role); | ||
199 | } | 199 | } | ||
200 | 200 | | |||
201 | if (role == StatusRole) { | 201 | if (role == StatusRole) { | ||
202 | // note: whenever the StatusRole is modified (even to the same value) the entry | 202 | // note: whenever the StatusRole is modified (even to the same value) the entry | ||
203 | // gets marked as changed and will get saved to the config file. This means the | 203 | // gets marked as changed and will get saved to the config file. This means the | ||
204 | // config file could get polluted | 204 | // config file could get polluted | ||
205 | EffectData &data = m_effectsList[index.row()]; | 205 | EffectData &data = m_effects[index.row()]; | ||
206 | data.status = Status(value.toInt()); | 206 | data.status = Status(value.toInt()); | ||
207 | data.changed = data.status != data.originalStatus; | 207 | data.changed = data.status != data.originalStatus; | ||
208 | emit dataChanged(index, index); | 208 | emit dataChanged(index, index); | ||
209 | 209 | | |||
210 | if (data.status == Status::Enabled && !data.exclusiveGroup.isEmpty()) { | 210 | if (data.status == Status::Enabled && !data.exclusiveGroup.isEmpty()) { | ||
211 | // need to disable all other exclusive effects in the same category | 211 | // need to disable all other exclusive effects in the same category | ||
212 | for (int i = 0; i < m_effectsList.size(); ++i) { | 212 | for (int i = 0; i < m_effects.size(); ++i) { | ||
213 | if (i == index.row()) { | 213 | if (i == index.row()) { | ||
214 | continue; | 214 | continue; | ||
215 | } | 215 | } | ||
216 | EffectData &otherData = m_effectsList[i]; | 216 | EffectData &otherData = m_effects[i]; | ||
217 | if (otherData.exclusiveGroup == data.exclusiveGroup) { | 217 | if (otherData.exclusiveGroup == data.exclusiveGroup) { | ||
218 | otherData.status = Status::Disabled; | 218 | otherData.status = Status::Disabled; | ||
219 | otherData.changed = otherData.status != otherData.originalStatus; | 219 | otherData.changed = otherData.status != otherData.originalStatus; | ||
220 | emit dataChanged(this->index(i, 0), this->index(i, 0)); | 220 | emit dataChanged(this->index(i, 0), this->index(i, 0)); | ||
221 | } | 221 | } | ||
222 | } | 222 | } | ||
223 | } | 223 | } | ||
224 | 224 | | |||
Show All 39 Lines | 234 | for (auto builtin : builtins) { | |||
264 | 264 | | |||
265 | effect.configurable = std::any_of(configs.constBegin(), configs.constEnd(), | 265 | effect.configurable = std::any_of(configs.constBegin(), configs.constEnd(), | ||
266 | [data](const KPluginInfo &info) { | 266 | [data](const KPluginInfo &info) { | ||
267 | return info.property(QStringLiteral("X-KDE-ParentComponents")).toString() == data.name; | 267 | return info.property(QStringLiteral("X-KDE-ParentComponents")).toString() == data.name; | ||
268 | } | 268 | } | ||
269 | ); | 269 | ); | ||
270 | 270 | | |||
271 | if (shouldStore(effect)) { | 271 | if (shouldStore(effect)) { | ||
272 | m_effectsList << effect; | 272 | m_effects << effect; | ||
273 | } | 273 | } | ||
274 | } | 274 | } | ||
275 | } | 275 | } | ||
276 | 276 | | |||
277 | void EffectsModel::loadJavascriptEffects(const KConfigGroup &kwinConfig) | 277 | void EffectsModel::loadJavascriptEffects(const KConfigGroup &kwinConfig) | ||
278 | { | 278 | { | ||
279 | const auto plugins = KPackage::PackageLoader::self()->listPackages( | 279 | const auto plugins = KPackage::PackageLoader::self()->listPackages( | ||
280 | QStringLiteral("KWin/Effect"), | 280 | QStringLiteral("KWin/Effect"), | ||
Show All 28 Lines | 283 | for (const KPluginMetaData &metaData : plugins) { | |||
309 | if (!pluginKeyword.isEmpty()) { | 309 | if (!pluginKeyword.isEmpty()) { | ||
310 | // scripted effects have their pluginName() as the keyword | 310 | // scripted effects have their pluginName() as the keyword | ||
311 | effect.configurable = plugin.property(QStringLiteral("X-KDE-ParentComponents")).toString() == pluginKeyword; | 311 | effect.configurable = plugin.property(QStringLiteral("X-KDE-ParentComponents")).toString() == pluginKeyword; | ||
312 | } else { | 312 | } else { | ||
313 | effect.configurable = false; | 313 | effect.configurable = false; | ||
314 | } | 314 | } | ||
315 | 315 | | |||
316 | if (shouldStore(effect)) { | 316 | if (shouldStore(effect)) { | ||
317 | m_effectsList << effect; | 317 | m_effects << effect; | ||
318 | } | 318 | } | ||
319 | } | 319 | } | ||
320 | } | 320 | } | ||
321 | 321 | | |||
322 | void EffectsModel::loadPluginEffects(const KConfigGroup &kwinConfig, const KPluginInfo::List &configs) | 322 | void EffectsModel::loadPluginEffects(const KConfigGroup &kwinConfig, const KPluginInfo::List &configs) | ||
323 | { | 323 | { | ||
324 | const auto pluginEffects = KPluginLoader::findPlugins( | 324 | const auto pluginEffects = KPluginLoader::findPlugins( | ||
325 | QStringLiteral("kwin/effects/plugins/"), | 325 | QStringLiteral("kwin/effects/plugins/"), | ||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Line(s) | 330 | for (const KPluginMetaData &pluginEffect : pluginEffects) { | |||
377 | 377 | | |||
378 | effect.configurable = std::any_of(configs.constBegin(), configs.constEnd(), | 378 | effect.configurable = std::any_of(configs.constBegin(), configs.constEnd(), | ||
379 | [pluginEffect](const KPluginInfo &info) { | 379 | [pluginEffect](const KPluginInfo &info) { | ||
380 | return info.property(QStringLiteral("X-KDE-ParentComponents")).toString() == pluginEffect.pluginId(); | 380 | return info.property(QStringLiteral("X-KDE-ParentComponents")).toString() == pluginEffect.pluginId(); | ||
381 | } | 381 | } | ||
382 | ); | 382 | ); | ||
383 | 383 | | |||
384 | if (shouldStore(effect)) { | 384 | if (shouldStore(effect)) { | ||
385 | m_effectsList << effect; | 385 | m_effects << effect; | ||
386 | } | 386 | } | ||
387 | } | 387 | } | ||
388 | } | 388 | } | ||
389 | 389 | | |||
390 | void EffectsModel::load(LoadOptions options) | 390 | void EffectsModel::load(LoadOptions options) | ||
391 | { | 391 | { | ||
392 | KConfigGroup kwinConfig(KSharedConfig::openConfig("kwinrc"), "Plugins"); | 392 | KConfigGroup kwinConfig(KSharedConfig::openConfig("kwinrc"), "Plugins"); | ||
393 | 393 | | |||
394 | const QVector<EffectData> oldEffects = m_effectsList; | 394 | const QVector<EffectData> oldEffects = m_effects; | ||
395 | 395 | | |||
396 | beginResetModel(); | 396 | beginResetModel(); | ||
397 | m_effectsList.clear(); | 397 | m_effects.clear(); | ||
398 | const KPluginInfo::List configs = KPluginTrader::self()->query(QStringLiteral("kwin/effects/configs/")); | 398 | const KPluginInfo::List configs = KPluginTrader::self()->query(QStringLiteral("kwin/effects/configs/")); | ||
399 | loadBuiltInEffects(kwinConfig, configs); | 399 | loadBuiltInEffects(kwinConfig, configs); | ||
400 | loadJavascriptEffects(kwinConfig); | 400 | loadJavascriptEffects(kwinConfig); | ||
401 | loadPluginEffects(kwinConfig, configs); | 401 | loadPluginEffects(kwinConfig, configs); | ||
402 | 402 | | |||
403 | if (options == LoadOptions::KeepDirty) { | 403 | if (options == LoadOptions::KeepDirty) { | ||
404 | for (const EffectData &oldEffect : oldEffects) { | 404 | for (const EffectData &oldEffect : oldEffects) { | ||
405 | if (!oldEffect.changed) { | 405 | if (!oldEffect.changed) { | ||
406 | continue; | 406 | continue; | ||
407 | } | 407 | } | ||
408 | auto effectIt = std::find_if(m_effectsList.begin(), m_effectsList.end(), | 408 | auto effectIt = std::find_if(m_effects.begin(), m_effects.end(), | ||
409 | [serviceName = oldEffect.serviceName](const EffectData &data) { | 409 | [serviceName = oldEffect.serviceName](const EffectData &data) { | ||
410 | return data.serviceName == serviceName; | 410 | return data.serviceName == serviceName; | ||
411 | } | 411 | } | ||
412 | ); | 412 | ); | ||
413 | if (effectIt == m_effectsList.end()) { | 413 | if (effectIt == m_effects.end()) { | ||
414 | continue; | 414 | continue; | ||
415 | } | 415 | } | ||
416 | effectIt->status = oldEffect.status; | 416 | effectIt->status = oldEffect.status; | ||
417 | effectIt->changed = effectIt->status != effectIt->originalStatus; | 417 | effectIt->changed = effectIt->status != effectIt->originalStatus; | ||
418 | } | 418 | } | ||
419 | } | 419 | } | ||
420 | 420 | | |||
421 | qSort(m_effectsList.begin(), m_effectsList.end(), [](const EffectData &a, const EffectData &b) { | 421 | qSort(m_effects.begin(), m_effects.end(), [](const EffectData &a, const EffectData &b) { | ||
422 | if (a.category == b.category) { | 422 | if (a.category == b.category) { | ||
423 | if (a.exclusiveGroup == b.exclusiveGroup) { | 423 | if (a.exclusiveGroup == b.exclusiveGroup) { | ||
424 | return a.name < b.name; | 424 | return a.name < b.name; | ||
425 | } | 425 | } | ||
426 | return a.exclusiveGroup < b.exclusiveGroup; | 426 | return a.exclusiveGroup < b.exclusiveGroup; | ||
427 | } | 427 | } | ||
428 | return a.category < b.category; | 428 | return a.category < b.category; | ||
429 | }); | 429 | }); | ||
430 | 430 | | |||
431 | OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"), | 431 | OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"), | ||
432 | QStringLiteral("/Effects"), | 432 | QStringLiteral("/Effects"), | ||
433 | QDBusConnection::sessionBus()); | 433 | QDBusConnection::sessionBus()); | ||
434 | 434 | | |||
435 | if (interface.isValid()) { | 435 | if (interface.isValid()) { | ||
436 | QStringList effectNames; | 436 | QStringList effectNames; | ||
437 | effectNames.reserve(m_effectsList.count()); | 437 | effectNames.reserve(m_effects.count()); | ||
438 | for (const EffectData &data : m_effectsList) { | 438 | for (const EffectData &data : m_effects) { | ||
439 | effectNames.append(data.serviceName); | 439 | effectNames.append(data.serviceName); | ||
440 | } | 440 | } | ||
441 | 441 | | |||
442 | QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(interface.areEffectsSupported(effectNames), this); | 442 | QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(interface.areEffectsSupported(effectNames), this); | ||
443 | watcher->setProperty("effectNames", effectNames); | 443 | watcher->setProperty("effectNames", effectNames); | ||
444 | connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *self) { | 444 | connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *self) { | ||
445 | const QStringList effectNames = self->property("effectNames").toStringList(); | 445 | const QStringList effectNames = self->property("effectNames").toStringList(); | ||
446 | const QDBusPendingReply<QList<bool > > reply = *self; | 446 | const QDBusPendingReply<QList<bool > > reply = *self; | ||
447 | QList<bool> supportValues; | 447 | QList<bool> supportValues; | ||
448 | if (reply.isValid()) { | 448 | if (reply.isValid()) { | ||
449 | supportValues.append(reply.value()); | 449 | supportValues.append(reply.value()); | ||
450 | } | 450 | } | ||
451 | if (effectNames.size() == supportValues.size()) { | 451 | if (effectNames.size() == supportValues.size()) { | ||
452 | for (int i = 0; i < effectNames.size(); ++i) { | 452 | for (int i = 0; i < effectNames.size(); ++i) { | ||
453 | const bool supportedValue = supportValues.at(i); | 453 | const bool supportedValue = supportValues.at(i); | ||
454 | const QString &effectName = effectNames.at(i); | 454 | const QString &effectName = effectNames.at(i); | ||
455 | auto it = std::find_if(m_effectsList.begin(), m_effectsList.end(), [effectName](const EffectData &data) { | 455 | auto it = std::find_if(m_effects.begin(), m_effects.end(), [effectName](const EffectData &data) { | ||
456 | return data.serviceName == effectName; | 456 | return data.serviceName == effectName; | ||
457 | }); | 457 | }); | ||
458 | if (it != m_effectsList.end()) { | 458 | if (it != m_effects.end()) { | ||
459 | if ((*it).supported != supportedValue) { | 459 | if ((*it).supported != supportedValue) { | ||
460 | (*it).supported = supportedValue; | 460 | (*it).supported = supportedValue; | ||
461 | QModelIndex i = findByPluginId(effectName); | 461 | QModelIndex i = findByPluginId(effectName); | ||
462 | if (i.isValid()) { | 462 | if (i.isValid()) { | ||
463 | emit dataChanged(i, i, QVector<int>() << SupportedRole); | 463 | emit dataChanged(i, i, QVector<int>() << SupportedRole); | ||
464 | } | 464 | } | ||
465 | } | 465 | } | ||
466 | } | 466 | } | ||
Show All 12 Lines | |||||
479 | } | 479 | } | ||
480 | 480 | | |||
481 | void EffectsModel::save() | 481 | void EffectsModel::save() | ||
482 | { | 482 | { | ||
483 | KConfigGroup kwinConfig(KSharedConfig::openConfig("kwinrc"), "Plugins"); | 483 | KConfigGroup kwinConfig(KSharedConfig::openConfig("kwinrc"), "Plugins"); | ||
484 | 484 | | |||
485 | QVector<EffectData> dirtyEffects; | 485 | QVector<EffectData> dirtyEffects; | ||
486 | 486 | | |||
487 | for (EffectData &effect : m_effectsList) { | 487 | for (EffectData &effect : m_effects) { | ||
488 | if (!effect.changed) { | 488 | if (!effect.changed) { | ||
489 | continue; | 489 | continue; | ||
490 | } | 490 | } | ||
491 | 491 | | |||
492 | effect.changed = false; | 492 | effect.changed = false; | ||
493 | effect.originalStatus = effect.status; | 493 | effect.originalStatus = effect.status; | ||
494 | 494 | | |||
495 | const QString key = effect.serviceName + QStringLiteral("Enabled"); | 495 | const QString key = effect.serviceName + QStringLiteral("Enabled"); | ||
Show All 30 Lines | 523 | for (const EffectData &effect : dirtyEffects) { | |||
526 | } else { | 526 | } else { | ||
527 | interface.unloadEffect(effect.serviceName); | 527 | interface.unloadEffect(effect.serviceName); | ||
528 | } | 528 | } | ||
529 | } | 529 | } | ||
530 | } | 530 | } | ||
531 | 531 | | |||
532 | void EffectsModel::defaults() | 532 | void EffectsModel::defaults() | ||
533 | { | 533 | { | ||
534 | for (int i = 0; i < m_effectsList.count(); ++i) { | 534 | for (int i = 0; i < m_effects.count(); ++i) { | ||
535 | const auto &effect = m_effectsList.at(i); | 535 | const auto &effect = m_effects.at(i); | ||
536 | if (effect.enabledByDefaultFunction && effect.status != Status::EnabledUndeterminded) { | 536 | if (effect.enabledByDefaultFunction && effect.status != Status::EnabledUndeterminded) { | ||
537 | updateEffectStatus(index(i, 0), Status::EnabledUndeterminded); | 537 | updateEffectStatus(index(i, 0), Status::EnabledUndeterminded); | ||
538 | } else if ((bool)effect.status != effect.enabledByDefault) { | 538 | } else if ((bool)effect.status != effect.enabledByDefault) { | ||
539 | updateEffectStatus(index(i, 0), effect.enabledByDefault ? Status::Enabled : Status::Disabled); | 539 | updateEffectStatus(index(i, 0), effect.enabledByDefault ? Status::Enabled : Status::Disabled); | ||
540 | } | 540 | } | ||
541 | } | 541 | } | ||
542 | } | 542 | } | ||
543 | 543 | | |||
544 | bool EffectsModel::needsSave() const | 544 | bool EffectsModel::needsSave() const | ||
545 | { | 545 | { | ||
546 | return std::any_of(m_effectsList.constBegin(), m_effectsList.constEnd(), | 546 | return std::any_of(m_effects.constBegin(), m_effects.constEnd(), | ||
547 | [](const EffectData &data) { | 547 | [](const EffectData &data) { | ||
548 | return data.changed; | 548 | return data.changed; | ||
549 | } | 549 | } | ||
550 | ); | 550 | ); | ||
551 | } | 551 | } | ||
552 | 552 | | |||
553 | QModelIndex EffectsModel::findByPluginId(const QString &pluginId) const | 553 | QModelIndex EffectsModel::findByPluginId(const QString &pluginId) const | ||
554 | { | 554 | { | ||
555 | auto it = std::find_if(m_effectsList.constBegin(), m_effectsList.constEnd(), | 555 | auto it = std::find_if(m_effects.constBegin(), m_effects.constEnd(), | ||
556 | [pluginId](const EffectData &data) { | 556 | [pluginId](const EffectData &data) { | ||
557 | return data.serviceName == pluginId; | 557 | return data.serviceName == pluginId; | ||
558 | } | 558 | } | ||
559 | ); | 559 | ); | ||
560 | if (it == m_effectsList.constEnd()) { | 560 | if (it == m_effects.constEnd()) { | ||
561 | return {}; | 561 | return {}; | ||
562 | } | 562 | } | ||
563 | return index(std::distance(m_effectsList.constBegin(), it), 0); | 563 | return index(std::distance(m_effects.constBegin(), it), 0); | ||
564 | } | 564 | } | ||
565 | 565 | | |||
566 | static KCModule *findBinaryConfig(const QString &pluginId, QObject *parent) | 566 | static KCModule *findBinaryConfig(const QString &pluginId, QObject *parent) | ||
567 | { | 567 | { | ||
568 | return KPluginTrader::createInstanceFromQuery<KCModule>( | 568 | return KPluginTrader::createInstanceFromQuery<KCModule>( | ||
569 | QStringLiteral("kwin/effects/configs/"), | 569 | QStringLiteral("kwin/effects/configs/"), | ||
570 | QString(), | 570 | QString(), | ||
571 | QStringLiteral("'%1' in [X-KDE-ParentComponents]").arg(pluginId), | 571 | QStringLiteral("'%1' in [X-KDE-ParentComponents]").arg(pluginId), | ||
▲ Show 20 Lines • Show All 73 Lines • Show Last 20 Lines |