File indexing completed on 2024-11-10 04:58:29

0001 /*
0002     SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "clonedview.h"
0007 #include "containmentinterface.h"
0008 #include "visibilitymanager.h"
0009 #include "../data/viewdata.h"
0010 #include "../layouts/storage.h"
0011 
0012 namespace Latte {
0013 
0014 const int ClonedView::ERRORAPPLETID;
0015 
0016 QStringList ClonedView::CONTAINMENTMANUALSYNCEDPROPERTIES = QStringList()
0017         << QString("appletOrder")
0018         << QString("lockedZoomApplets")
0019         << QString("userBlocksColorizingApplets");  
0020 
0021 ClonedView::ClonedView(Plasma::Corona *corona, Latte::OriginalView *originalView, QScreen *targetScreen, bool byPassX11WM)
0022     : View(corona, targetScreen, byPassX11WM),
0023       m_originalView(originalView)
0024 {
0025     m_originalView->addClone(this);
0026     initSync();
0027 }
0028 
0029 ClonedView::~ClonedView()
0030 {
0031 }
0032 
0033 void ClonedView::initSync()
0034 {
0035     connect(m_originalView, &View::containmentChanged, this, &View::groupIdChanged);
0036 
0037     //! Update Visibility From Original
0038     connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::modeChanged, this, [&]() {
0039         visibility()->setMode(m_originalView->visibility()->mode());
0040     });
0041 
0042     connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::raiseOnDesktopChanged, this, [&]() {
0043         visibility()->setRaiseOnDesktop(m_originalView->visibility()->raiseOnDesktop());
0044     });
0045 
0046     connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::raiseOnActivityChanged, this, [&]() {
0047         visibility()->setRaiseOnActivity(m_originalView->visibility()->raiseOnActivity());
0048     });
0049 
0050     connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::enableKWinEdgesChanged, this, [&]() {
0051         visibility()->setEnableKWinEdges(m_originalView->visibility()->enableKWinEdges());
0052     });
0053 
0054     connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::timerShowChanged, this, [&]() {
0055         visibility()->setTimerShow(m_originalView->visibility()->timerShow());
0056     });
0057 
0058     connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::timerHideChanged, this, [&]() {
0059         visibility()->setTimerHide(m_originalView->visibility()->timerHide());
0060     });
0061 
0062 
0063     //! Update Applets from Clone -> OriginalView
0064     connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletConfigPropertyChanged, this, &ClonedView::updateOriginalAppletConfigProperty);
0065     connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::initializationCompleted, this, &ClonedView::updateAppletIdsHash);
0066     connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsOrderChanged, this, &ClonedView::updateAppletIdsHash);
0067     connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDataCreated, this, &ClonedView::updateAppletIdsHash);
0068     connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletCreated, this, [&](const QString &pluginId) {
0069         m_originalView->addApplet(pluginId, containment()->id());
0070     });
0071 
0072     connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDropped, this, [&](QObject *data, int x, int y) {
0073         m_originalView->addApplet(data, x, y, containment()->id());
0074     });
0075 
0076     //! Update Applets and Containment from OrigalView -> Clone
0077     connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::containmentConfigPropertyChanged, this, &ClonedView::updateContainmentConfigProperty);
0078     connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletConfigPropertyChanged, this, &ClonedView::onOriginalAppletConfigPropertyChanged);
0079     connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletInScheduledDestructionChanged, this, &ClonedView::onOriginalAppletInScheduledDestructionChanged);
0080     connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletRemoved, this, &ClonedView::onOriginalAppletRemoved);
0081     connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsOrderChanged, this, &ClonedView::onOriginalAppletsOrderChanged);
0082     connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsInLockedZoomChanged, this, &ClonedView::onOriginalAppletsInLockedZoomChanged);
0083     connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsDisabledColoringChanged, this, &ClonedView::onOriginalAppletsDisabledColoringChanged);
0084     connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDataCreated, this, &ClonedView::updateAppletIdsHash);
0085     connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletCreated, this->extendedInterface(), [&](const QString &pluginId) {
0086         extendedInterface()->addApplet(pluginId);
0087     });
0088     connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDropped, this->extendedInterface(), [&](QObject *data, int x, int y) {
0089         extendedInterface()->addApplet(data, x, y);
0090     });
0091 
0092     //! Indicator
0093     connect(m_originalView, &Latte::View::indicatorChanged, this, &ClonedView::indicatorChanged);
0094 }
0095 
0096 bool ClonedView::isSingle() const
0097 {
0098     return false;
0099 }
0100 
0101 bool ClonedView::isOriginal() const
0102 {
0103     return false;
0104 }
0105 
0106 bool ClonedView::isCloned() const
0107 {
0108     return true;
0109 }
0110 
0111 bool ClonedView::isPreferredForShortcuts() const
0112 {
0113     return false;
0114 }
0115 
0116 int ClonedView::groupId() const
0117 {
0118     if (!m_originalView->containment()) {
0119         return -1;
0120     }
0121 
0122     return m_originalView->containment()->id();
0123 }
0124 
0125 Latte::Types::ScreensGroup ClonedView::screensGroup() const
0126 {
0127     return Latte::Types::SingleScreenGroup;
0128 }
0129 
0130 ViewPart::Indicator *ClonedView::indicator() const
0131 {
0132     return m_originalView->indicator();
0133 }
0134 
0135 
0136 bool ClonedView::hasOriginalAppletId(const int &clonedid)
0137 {
0138     if (clonedid < 0) {
0139         return false;
0140     }
0141 
0142     QHash<int, int>::const_iterator i = m_currentAppletIds.constBegin();
0143     while (i != m_currentAppletIds.constEnd()) {
0144         if (i.value() == clonedid) {
0145             return true;
0146         }
0147 
0148         ++i;
0149     }
0150 
0151     return false;
0152 }
0153 
0154 int ClonedView::originalAppletId(const int &clonedid)
0155 {
0156     if (clonedid < 0) {
0157         return -1;
0158     }
0159 
0160     QHash<int, int>::const_iterator i = m_currentAppletIds.constBegin();
0161     while (i != m_currentAppletIds.constEnd()) {
0162         if (i.value() == clonedid) {
0163             return i.key();
0164         }
0165 
0166         ++i;
0167     }
0168 
0169     return -1;
0170 }
0171 
0172 
0173 bool ClonedView::isTranslatableToClonesOrder(const QList<int> &originalOrder)
0174 {
0175     for(int i=0; i<originalOrder.count(); ++i) {
0176         int oid = originalOrder[i];
0177         if (oid < 0 ) {
0178             continue;
0179         }
0180 
0181         if (!m_currentAppletIds.contains(oid)) {
0182             return false;
0183         }
0184     }
0185 
0186     return true;
0187 }
0188 
0189 Latte::Data::View ClonedView::data() const
0190 {
0191     Latte::Data::View vdata = View::data();
0192     vdata.isClonedFrom = m_originalView->containment()->id();
0193     return vdata;
0194 }
0195 
0196 void ClonedView::updateAppletIdsHash()
0197 {
0198     QList<int> originalids = m_originalView->extendedInterface()->appletsOrder();
0199     QList<int> clonedids = extendedInterface()->appletsOrder();
0200 
0201     for (int i=0; i<originalids.count(); ++i) {
0202         int oid = originalids[i];
0203         if (oid < 0 || (m_currentAppletIds.contains(oid) && m_currentAppletIds[oid] > 0)) {
0204             continue;
0205         }
0206 
0207         int oindex = m_originalView->extendedInterface()->indexOfApplet(oid);
0208         ViewPart::AppletInterfaceData originalapplet = m_originalView->extendedInterface()->appletDataForId(oid);
0209         ViewPart::AppletInterfaceData clonedapplet = extendedInterface()->appletDataAtIndex(oindex);
0210 
0211         bool registeredclonedid = (originalAppletId(clonedapplet.id) > 0);
0212 
0213         if (originalapplet.id>0 && clonedapplet.id>0 && originalapplet.plugin == clonedapplet.plugin && !registeredclonedid) {
0214             m_currentAppletIds[originalapplet.id] = clonedapplet.id;
0215         }
0216     }
0217 }
0218 
0219 QList<int> ClonedView::translateToClonesOrder(const QList<int> &originalIds)
0220 {
0221     QList<int> ids;
0222 
0223     for (int i=0; i<originalIds.count(); ++i) {
0224         int originalid = originalIds[i];
0225         if (originalid < 0 ) {
0226             ids << originalid;
0227             continue;
0228         }
0229 
0230         if (m_currentAppletIds.contains(originalid)) {
0231             ids << m_currentAppletIds[originalid];
0232         } else {
0233             ids << ERRORAPPLETID; //error
0234         }
0235     }
0236 
0237     return ids;
0238 }
0239 
0240 void ClonedView::showConfigurationInterface(Plasma::Applet *applet)
0241 {
0242     Plasma::Containment *c = qobject_cast<Plasma::Containment *>(applet);
0243 
0244     if (Layouts::Storage::self()->isLatteContainment(c)) {
0245         m_originalView->showSettingsWindow();
0246     } else {
0247         View::showConfigurationInterface(applet);
0248     }
0249 }
0250 
0251 void ClonedView::onOriginalAppletRemoved(const int &id)
0252 {
0253     if (!m_currentAppletIds.contains(id)) {
0254         return;
0255     }
0256 
0257     extendedInterface()->removeApplet(m_currentAppletIds[id]);
0258     m_currentAppletIds.remove(id);
0259 }
0260 
0261 void ClonedView::onOriginalAppletConfigPropertyChanged(const int &id, const QString &key, const QVariant &value)
0262 {
0263     if (!m_currentAppletIds.contains(id)) {
0264         return;
0265     }
0266 
0267     extendedInterface()->updateAppletConfigProperty(m_currentAppletIds[id], key, value);
0268 }
0269 
0270 void ClonedView::onOriginalAppletInScheduledDestructionChanged(const int &id, const bool &enabled)
0271 {
0272     if (!m_currentAppletIds.contains(id)) {
0273         return;
0274     }
0275 
0276     extendedInterface()->setAppletInScheduledDestruction(m_currentAppletIds[id], enabled);
0277 }
0278 
0279 void ClonedView::updateContainmentConfigProperty(const QString &key, const QVariant &value)
0280 {
0281     if (!CONTAINMENTMANUALSYNCEDPROPERTIES.contains(key)) {
0282         extendedInterface()->updateContainmentConfigProperty(key, value);
0283     } else {
0284         //qDebug() << "org.kde.sync :: containment config value syncing blocked :: " << key;
0285     }
0286 }
0287 
0288 void ClonedView::updateOriginalAppletConfigProperty(const int &clonedid, const QString &key, const QVariant &value)
0289 {
0290     if (!hasOriginalAppletId(clonedid)) {
0291         return;
0292     }
0293 
0294     m_originalView->extendedInterface()->updateAppletConfigProperty(originalAppletId(clonedid), key, value);
0295 }
0296 
0297 void ClonedView::onOriginalAppletsOrderChanged()
0298 {
0299     updateAppletIdsHash();
0300     QList<int> originalorder = m_originalView->extendedInterface()->appletsOrder();
0301 
0302     if (originalorder.count() != extendedInterface()->appletsOrder().count()) {
0303         //probably an applet was removed or added and clone has not been updated yet
0304         return;
0305     }
0306 
0307     if (!isTranslatableToClonesOrder(originalorder)) {
0308         qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original order can not be translated to cloned ids...";
0309         return;
0310     }
0311 
0312     QList<int> newclonesorder = translateToClonesOrder(originalorder);
0313 
0314     if (newclonesorder.contains(ERRORAPPLETID)) {
0315         qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original and clones order map can not be generated...";
0316         return;
0317     }
0318 
0319     extendedInterface()->setAppletsOrder(newclonesorder);
0320 }
0321 
0322 void ClonedView::onOriginalAppletsInLockedZoomChanged(const QList<int> &originalapplets)
0323 {
0324     if (!isTranslatableToClonesOrder(originalapplets)) {
0325         qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original order can not be translated to cloned ids...";
0326         return;
0327     }
0328 
0329     QList<int> newclonesorder = translateToClonesOrder(originalapplets);
0330 
0331     if (newclonesorder.contains(ERRORAPPLETID)) {
0332         qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original and clones order map can not be generated...";
0333         return;
0334     }
0335 
0336     extendedInterface()->setAppletsInLockedZoom(newclonesorder);
0337 }
0338 
0339 void ClonedView::onOriginalAppletsDisabledColoringChanged(const QList<int> &originalapplets)
0340 {
0341     if (!isTranslatableToClonesOrder(originalapplets)) {
0342         qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original order can not be translated to cloned ids...";
0343         return;
0344     }
0345 
0346     QList<int> newclonesorder = translateToClonesOrder(originalapplets);
0347 
0348     if (newclonesorder.contains(ERRORAPPLETID)) {
0349         qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original and clones order map can not be generated...";
0350         return;
0351     }
0352 
0353     extendedInterface()->setAppletsDisabledColoring(newclonesorder);
0354 }
0355 
0356 
0357 }