File indexing completed on 2024-12-01 11:10:42

0001 /*
0002     SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "originalview.h"
0007 #include "clonedview.h"
0008 #include "positioner.h"
0009 #include "../lattecorona.h"
0010 #include "../screenpool.h"
0011 #include "../layouts/storage.h"
0012 
0013 // KDE
0014 #include <KLocalizedString>
0015 
0016 namespace Latte {
0017 OriginalView::OriginalView(Plasma::Corona *corona, QScreen *targetScreen, bool byPassX11WM)
0018     : View(corona, targetScreen, byPassX11WM)
0019 {
0020     connect(this, &View::containmentChanged, this, [&]() {
0021         if (!this->containment()) {
0022             return;
0023         }
0024 
0025         connect(containment(), &Plasma::Applet::destroyedChanged, this, &OriginalView::syncClonesToScreens);
0026         restoreConfig();
0027     });
0028 
0029     connect(this, &View::layoutChanged, this, &OriginalView::syncClonesToScreens);
0030     connect(this, &OriginalView::screensGroupChanged, this, &OriginalView::syncClonesToScreens);
0031     connect(this, &OriginalView::screensGroupChanged, this, &OriginalView::saveConfig);
0032 }
0033 
0034 OriginalView::~OriginalView()
0035 {
0036     cleanClones();
0037 }
0038 
0039 bool OriginalView::isSingle() const
0040 {
0041     return m_screensGroup == Latte::Types::SingleScreenGroup;
0042 }
0043 
0044 bool OriginalView::isOriginal() const
0045 {
0046     return true;
0047 }
0048 
0049 bool OriginalView::isCloned() const
0050 {
0051     return !isOriginal();
0052 }
0053 
0054 int OriginalView::clonesCount() const
0055 {
0056     return m_clones.count();
0057 }
0058 
0059 int OriginalView::expectedScreenIdFromScreenGroup(const Latte::Types::ScreensGroup &nextScreensGroup) const
0060 {
0061     Data::View view = data();
0062     view.screensGroup = nextScreensGroup;
0063     return Latte::Layouts::Storage::self()->expectedViewScreenId(m_corona, view);
0064 }
0065 
0066 Latte::Types::ScreensGroup OriginalView::screensGroup() const
0067 {
0068     return m_screensGroup;
0069 }
0070 
0071 void OriginalView::setScreensGroup(const Latte::Types::ScreensGroup &group)
0072 {
0073     if (m_screensGroup == group) {
0074         return;
0075     }
0076 
0077     m_screensGroup = group;
0078     emit screensGroupChanged();
0079 }
0080 
0081 void OriginalView::addClone(Latte::ClonedView *view)
0082 {
0083     if (m_clones.contains(view)) {
0084         return;
0085     }
0086 
0087     m_clones << view;
0088     m_waitingCreation.removeAll(view->positioner()->currentScreenId());
0089 }
0090 
0091 void OriginalView::removeClone(Latte::ClonedView *view)
0092 {
0093     if (!m_clones.contains(view)) {
0094         return;
0095     }
0096 
0097     int idx = m_clones.indexOf(view);
0098     auto cloned = m_clones.takeAt(idx);
0099 
0100     if (!cloned->layout()) {
0101         return;
0102     }
0103     cloned->positioner()->slideOutDuringExit();
0104     cloned->layout()->removeView(cloned->data());
0105 }
0106 
0107 void OriginalView::createClone(int screenId)
0108 {
0109     if (!layout() || !containment()) {
0110         return;
0111     }
0112 
0113     QString templateFile = layout()->storedView(containment()->id());
0114 
0115     if (templateFile.isEmpty()) {
0116         return;
0117     }
0118 
0119     Data::ViewsTable templateviews = Layouts::Storage::self()->views(templateFile);
0120 
0121     if (templateviews.rowCount() <= 0) {
0122         return;
0123     }
0124 
0125     Data::View nextdata = templateviews[0];
0126     nextdata.name = i18nc("clone of original dock panel, name","Clone of %1", name());
0127     nextdata.onPrimary = false;
0128     nextdata.screensGroup = Latte::Types::SingleScreenGroup;
0129     nextdata.isClonedFrom = containment()->id();
0130     nextdata.screen = screenId;
0131 
0132     nextdata.setState(Data::View::OriginFromViewTemplate, templateFile);
0133 
0134     if (!m_waitingCreation.contains(screenId)) {
0135         m_waitingCreation << screenId;
0136         layout()->newView(nextdata);
0137     }
0138 }
0139 
0140 void OriginalView::cleanClones()
0141 {
0142     if (m_clones.count()==0) {
0143         return;
0144     }
0145 
0146     while(!m_clones.isEmpty()) {
0147         removeClone(m_clones[0]);
0148     }
0149 }
0150 
0151 void OriginalView::reconsiderScreen()
0152 {
0153     View::reconsiderScreen();
0154     syncClonesToScreens();
0155 }
0156 
0157 void OriginalView::setNextLocationForClones(const QString layoutName, int edge, int alignment)
0158 {
0159     if (m_clones.count()==0) {
0160         return;
0161     }
0162 
0163     for (const auto clone : m_clones) {
0164         clone->positioner()->setNextLocation(layoutName, Latte::Types::SingleScreenGroup, "", edge, alignment);
0165     }
0166 }
0167 
0168 void OriginalView::addApplet(const QString &pluginId, const int &excludecloneid)
0169 {
0170     if (m_clones.count() == 0) {
0171         return;
0172     }
0173 
0174     // add applet in original view
0175     extendedInterface()->addApplet(pluginId);
0176 
0177     // add applet in clones and exclude the one that probably produced this triggering
0178     for(const auto clone: m_clones) {
0179         if (clone->containment()->id() == excludecloneid) {
0180             // this way we make sure that an applet will not be double added
0181             continue;
0182         }
0183 
0184         clone->extendedInterface()->addApplet(pluginId);
0185     }
0186 }
0187 
0188 void OriginalView::addApplet(QObject *mimedata, const int &x, const int &y, const int &excludecloneid)
0189 {
0190     if (m_clones.count() == 0) {
0191         return;
0192     }
0193 
0194     // add applet in original view
0195     extendedInterface()->addApplet(mimedata, x, y);
0196 
0197     // add applet in clones and exclude the one that probably produced this triggering
0198     for(const auto clone: m_clones) {
0199         if (clone->containment()->id() == excludecloneid) {
0200             // this way we make sure that an applet will not be double added
0201             continue;
0202         }
0203 
0204         clone->extendedInterface()->addApplet(mimedata, x, y);
0205     }
0206 }
0207 
0208 void OriginalView::syncClonesToScreens()
0209 {
0210     if (isSingle() || (containment() && containment()->destroyed())) {
0211         cleanClones();
0212         return;
0213     }
0214 
0215     QList<int> secondaryscreens = m_corona->screenPool()->secondaryScreenIds();
0216 
0217     for (const auto scrid : secondaryscreens) {
0218         if (m_waitingCreation.contains(scrid)) {
0219             secondaryscreens.removeAll(scrid);
0220         }
0221     }
0222 
0223     if (m_screensGroup == Latte::Types::AllSecondaryScreensGroup) {
0224         //! occuped screen from original view in "allsecondaryscreensgroup" must be ignored
0225         secondaryscreens.removeAll(expectedScreenIdFromScreenGroup(m_screensGroup));
0226     }
0227 
0228     QList<Latte::ClonedView *> removable;
0229 
0230     for (const auto clone : m_clones) {
0231         if (secondaryscreens.contains(clone->positioner()->currentScreenId())) {
0232             // do nothing valid clone
0233             secondaryscreens.removeAll(clone->positioner()->currentScreenId());
0234         } else {
0235             // must be removed the screen is not active
0236             removable << clone;
0237         }
0238     }
0239 
0240     for (const auto scrid : secondaryscreens) {
0241         if (removable.count() > 0) {
0242             //! move deprecated and available clone to valid secondary screen
0243             auto clone = removable.takeFirst();
0244             clone->positioner()->setScreenToFollow(m_corona->screenPool()->screenForId(scrid));
0245         } else {
0246             //! create a new clone
0247             createClone(scrid);
0248         }
0249     }
0250 
0251     for (auto removableclone : removable) {
0252         //! remove deprecated clones
0253         removeClone(removableclone);
0254     }
0255 }
0256 
0257 void OriginalView::saveConfig()
0258 {
0259 
0260     if (!this->containment()) {
0261         return;
0262     }
0263 
0264     auto config = this->containment()->config();
0265     config.writeEntry("screensGroup", (int)m_screensGroup);
0266 }
0267 
0268 void OriginalView::restoreConfig()
0269 {
0270     if (!this->containment()) {
0271         return;
0272     }
0273 
0274     auto config = this->containment()->config();
0275     m_screensGroup = static_cast<Latte::Types::ScreensGroup>(config.readEntry("screensGroup", (int)Latte::Types::SingleScreenGroup));
0276 
0277     //! Send changed signals at the end in order to be sure that saveConfig
0278     //! wont rewrite default/invalid values
0279     emit screensGroupChanged();
0280 }
0281 
0282 }