diff --git a/app/layout/genericlayout.cpp b/app/layout/genericlayout.cpp index bdef4ddf..97d39a18 100644 --- a/app/layout/genericlayout.cpp +++ b/app/layout/genericlayout.cpp @@ -1,1687 +1,1688 @@ /* * Copyright 2019 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 "genericlayout.h" // local #include "abstractlayout.h" #include "storage.h" #include "../apptypes.h" #include "../lattecorona.h" #include "../screenpool.h" #include "../layouts/importer.h" #include "../layouts/manager.h" #include "../layouts/synchronizer.h" #include "../shortcuts/shortcutstracker.h" #include "../view/view.h" #include "../view/positioner.h" // Qt #include #include // Plasma #include #include #include // KDE #include namespace Latte { namespace Layout { GenericLayout::GenericLayout(QObject *parent, QString layoutFile, QString assignedName) : AbstractLayout (parent, layoutFile, assignedName), m_storage(new Storage(this)) { } GenericLayout::~GenericLayout() { } Type GenericLayout::type() const { return Type::Generic; } void GenericLayout::unloadContainments() { if (!m_corona) { return; } qDebug() << "Layout - " + name() + " : [unloadContainments]" << "containments ::: " << m_containments.size() << " ,latteViews in memory ::: " << m_latteViews.size() << " ,hidden latteViews in memory ::: " << m_waitingLatteViews.size(); for (const auto view : m_latteViews) { view->disconnectSensitiveSignals(); } for (const auto view : m_waitingLatteViews) { view->disconnectSensitiveSignals(); } m_unloadedContainmentsIds.clear(); QList systrays; //!identify systrays and unload them first for (const auto containment : m_containments) { if (Plasma::Applet *parentApplet = qobject_cast(containment->parent())) { systrays.append(containment); } } while (!systrays.isEmpty()) { Plasma::Containment *systray = systrays.at(0); m_unloadedContainmentsIds << QString::number(systray->id()); systrays.removeFirst(); m_containments.removeAll(systray); delete systray; } while (!m_containments.isEmpty()) { Plasma::Containment *containment = m_containments.at(0); m_unloadedContainmentsIds << QString::number(containment->id()); m_containments.removeFirst(); delete containment; } } void GenericLayout::unloadLatteViews() { if (!m_corona) { return; } qDebug() << "Layout - " + name() + " : [unloadLatteViews]" << "containments ::: " << m_containments.size() << " ,latteViews in memory ::: " << m_latteViews.size() << " ,hidden latteViews in memory ::: " << m_waitingLatteViews.size(); //!disconnect signals in order to avoid crashes when the layout is unloading disconnect(this, &GenericLayout::viewsCountChanged, m_corona, &Plasma::Corona::availableScreenRectChanged); disconnect(this, &GenericLayout::viewsCountChanged, m_corona, &Plasma::Corona::availableScreenRegionChanged); disconnect(m_corona->activitiesConsumer(), &KActivities::Consumer::currentActivityChanged, this, &GenericLayout::updateLastUsedActivity); for (const auto view : m_latteViews) { view->disconnectSensitiveSignals(); } for (const auto view : m_waitingLatteViews) { view->disconnectSensitiveSignals(); } qDeleteAll(m_latteViews); qDeleteAll(m_waitingLatteViews); m_latteViews.clear(); m_waitingLatteViews.clear(); } bool GenericLayout::blockAutomaticLatteViewCreation() const { return m_blockAutomaticLatteViewCreation; } void GenericLayout::setBlockAutomaticLatteViewCreation(bool block) { if (m_blockAutomaticLatteViewCreation == block) { return; } m_blockAutomaticLatteViewCreation = block; } bool GenericLayout::configViewIsShown() const { for (const auto view : m_latteViews) { if (view && view->settingsWindowIsShown()) { return true; } } return false; } bool GenericLayout::isActive() const { if (!m_corona) { return false; } GenericLayout *generic = m_corona->layoutsManager()->synchronizer()->layout(m_layoutName); if (generic) { return true; } else { return false; } } bool GenericLayout::isCurrent() const { if (!m_corona) { return false; } return name() == m_corona->layoutsManager()->currentLayoutName(); } bool GenericLayout::isInternalContainment(Plasma::Applet *applet) const { if (!applet) { return false; } for (const auto containment : m_containments) { Plasma::Applet *parentApplet = qobject_cast(containment->parent()); if (parentApplet && parentApplet == applet) { return true; } } return false; } Plasma::Containment *GenericLayout::internalContainmentOf(Plasma::Applet *applet) const { if (!applet) { return nullptr; } if (isInternalContainment(applet)) { for (const auto containment : m_containments) { Plasma::Applet *parentApplet = qobject_cast(containment->parent()); if (parentApplet && parentApplet == applet) { return containment; } } } return nullptr; } int GenericLayout::viewsCount(int screen) const { if (!m_corona) { return 0; } QScreen *scr = m_corona->screenPool()->screenForId(screen); int views{0}; for (const auto view : m_latteViews) { if (view && view->screen() == scr && !view->containment()->destroyed()) { ++views; } } return views; } int GenericLayout::viewsCount(QScreen *screen) const { if (!m_corona) { return 0; } int views{0}; for (const auto view : m_latteViews) { if (view && view->screen() == screen && !view->containment()->destroyed()) { ++views; } } return views; } int GenericLayout::viewsCount() const { if (!m_corona) { return 0; } int views{0}; for (const auto view : m_latteViews) { if (view && view->containment() && !view->containment()->destroyed()) { ++views; } } return views; } QList GenericLayout::qmlFreeEdges(int screen) const { if (!m_corona) { const QList emptyEdges; return emptyEdges; } const auto edges = freeEdges(screen); QList edgesInt; for (const Plasma::Types::Location &edge : edges) { edgesInt.append(static_cast(edge)); } return edgesInt; } QList GenericLayout::freeEdges(QScreen *scr) const { using Plasma::Types; QList edges{Types::BottomEdge, Types::LeftEdge, Types::TopEdge, Types::RightEdge}; if (!m_corona) { return edges; } for (const auto view : m_latteViews) { if (view && view->positioner()->currentScreenName() == scr->name()) { edges.removeOne(view->location()); } } return edges; } QList GenericLayout::freeEdges(int screen) const { using Plasma::Types; QList edges{Types::BottomEdge, Types::LeftEdge, Types::TopEdge, Types::RightEdge}; if (!m_corona) { return edges; } QScreen *scr = m_corona->screenPool()->screenForId(screen); for (const auto view : m_latteViews) { if (view && scr && view->positioner()->currentScreenName() == scr->name()) { edges.removeOne(view->location()); } } return edges; } int GenericLayout::viewsWithTasks() const { if (!m_corona) { return 0; } int result = 0; for (const auto view : m_latteViews) { if (view->tasksPresent()) { result++; } } return result; } QStringList GenericLayout::unloadedContainmentsIds() { return m_unloadedContainmentsIds; } Latte::Corona *GenericLayout::corona() { return m_corona; } Types::ViewType GenericLayout::latteViewType(uint containmentId) const { for (const auto view : m_latteViews) { if (view->containment() && view->containment()->id() == containmentId) { return view->type(); } } return Types::DockView; } Latte::View *GenericLayout::highestPriorityView() { QList views = sortedLatteViews(); return (views.count() > 0 ? views[0] : nullptr); } Latte::View *GenericLayout::lastConfigViewFor() { if (!latteViews().contains(m_lastConfigViewFor)) { m_lastConfigViewFor = nullptr; return nullptr; } return m_lastConfigViewFor; } void GenericLayout::setLastConfigViewFor(Latte::View *view) { if (m_lastConfigViewFor == view) { return; } m_lastConfigViewFor = view; emit lastConfigViewForChanged(view); } Latte::View *GenericLayout::viewForContainment(Plasma::Containment *containment) { if (m_containments.contains(containment) && m_latteViews.contains(containment)) { return m_latteViews[containment]; } return nullptr; } QList GenericLayout::latteViews() { return m_latteViews.values(); } QList GenericLayout::sortedLatteViews(QList views) { QList sortedViews = views.isEmpty() ? latteViews() : views; qDebug() << " -------- "; for (int i = 0; i < sortedViews.count(); ++i) { qDebug() << i << ". " << sortedViews[i]->screen()->name() << " - " << sortedViews[i]->location(); } //! sort the views based on screens and edges priorities //! views on primary screen have higher priority and //! for views in the same screen the priority goes to //! Bottom,Left,Top,Right for (int i = 0; i < sortedViews.size(); ++i) { for (int j = 0; j < sortedViews.size() - i - 1; ++j) { if (viewAtLowerScreenPriority(sortedViews[j], sortedViews[j + 1]) || (sortedViews[j]->screen() == sortedViews[j + 1]->screen() && viewAtLowerEdgePriority(sortedViews[j], sortedViews[j + 1]))) { Latte::View *temp = sortedViews[j + 1]; sortedViews[j + 1] = sortedViews[j]; sortedViews[j] = temp; } } } Latte::View *highestPriorityView{nullptr}; for (int i = 0; i < sortedViews.size(); ++i) { if (sortedViews[i]->isPreferredForShortcuts()) { highestPriorityView = sortedViews[i]; sortedViews.removeAt(i); break; } } if (highestPriorityView) { sortedViews.prepend(highestPriorityView); } qDebug() << " -------- sorted -----"; for (int i = 0; i < sortedViews.count(); ++i) { qDebug() << i << ". " << sortedViews[i]->isPreferredForShortcuts() << " - " << sortedViews[i]->screen()->name() << " - " << sortedViews[i]->location(); } return sortedViews; } bool GenericLayout::viewAtLowerScreenPriority(Latte::View *test, Latte::View *base) { if (!base || ! test) { return true; } if (base->screen() == test->screen()) { return false; } else if (base->screen() != qGuiApp->primaryScreen() && test->screen() == qGuiApp->primaryScreen()) { return false; } else if (base->screen() == qGuiApp->primaryScreen() && test->screen() != qGuiApp->primaryScreen()) { return true; } else { int basePriority = -1; int testPriority = -1; for (int i = 0; i < qGuiApp->screens().count(); ++i) { if (base->screen() == qGuiApp->screens()[i]) { basePriority = i; } if (test->screen() == qGuiApp->screens()[i]) { testPriority = i; } } if (testPriority <= basePriority) { return true; } else { return false; } } qDebug() << "viewAtLowerScreenPriority : shouldn't had reached here..."; return false; } bool GenericLayout::viewAtLowerEdgePriority(Latte::View *test, Latte::View *base) { if (!base || ! test) { return true; } QList edges{Plasma::Types::RightEdge, Plasma::Types::TopEdge, Plasma::Types::LeftEdge, Plasma::Types::BottomEdge}; int testPriority = -1; int basePriority = -1; for (int i = 0; i < edges.count(); ++i) { if (edges[i] == base->location()) { basePriority = i; } if (edges[i] == test->location()) { testPriority = i; } } if (testPriority < basePriority) { return true; } else { return false; } } bool GenericLayout::viewDataAtLowerScreenPriority(const ViewData &test, const ViewData &base) const { if (test.onPrimary && base.onPrimary) { return false; } else if (!base.onPrimary && test.onPrimary) { return false; } else if (base.onPrimary && !test.onPrimary) { return true; } else { return test.screenId <= base.screenId; } } bool GenericLayout::viewDataAtLowerStatePriority(const ViewData &test, const ViewData &base) const { if (test.active == base.active) { return false; } else if (!base.active && test.active) { return false; } else if (base.active && !test.active) { return true; } return false; } bool GenericLayout::viewDataAtLowerEdgePriority(const ViewData &test, const ViewData &base) const { QList edges{Plasma::Types::RightEdge, Plasma::Types::TopEdge, Plasma::Types::LeftEdge, Plasma::Types::BottomEdge}; int testPriority = -1; int basePriority = -1; for (int i = 0; i < edges.count(); ++i) { if (edges[i] == base.location) { basePriority = i; } if (edges[i] == test.location) { testPriority = i; } } if (testPriority < basePriority) { return true; } else { return false; } } QList GenericLayout::sortedViewsData(const QList &viewsData) { QList sortedData = viewsData; //! sort the views based on screens and edges priorities //! views on primary screen have higher priority and //! for views in the same screen the priority goes to //! Bottom,Left,Top,Right for (int i = 0; i < sortedData.size(); ++i) { for (int j = 0; j < sortedData.size() - i - 1; ++j) { if (viewDataAtLowerStatePriority(sortedData[j], sortedData[j + 1]) || viewDataAtLowerScreenPriority(sortedData[j], sortedData[j + 1]) || (!viewDataAtLowerScreenPriority(sortedData[j], sortedData[j + 1]) && viewDataAtLowerEdgePriority(sortedData[j], sortedData[j + 1])) ) { ViewData temp = sortedData[j + 1]; sortedData[j + 1] = sortedData[j]; sortedData[j] = temp; } } } return sortedData; } const QList *GenericLayout::containments() { return &m_containments; } QList GenericLayout::viewsWithPlasmaShortcuts() { QList views; if (!m_corona) { return views; } QList appletsWithShortcuts = m_corona->globalShortcuts()->shortcutsTracker()->appletsWithPlasmaShortcuts(); for (const auto &appletId : appletsWithShortcuts) { for (const auto view : m_latteViews) { bool found{false}; for (const auto applet : view->containment()->applets()) { if (appletId == applet->id()) { if (!views.contains(view)) { views.append(view); found = true; break; } } } if (found) { break; } } } return views; } //! Containments Actions void GenericLayout::addContainment(Plasma::Containment *containment) { if (!containment || m_containments.contains(containment)) { return; } bool containmentInLayout{false}; if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout) { m_containments.append(containment); containmentInLayout = true; } else if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) { QString layoutId = containment->config().readEntry("layoutId", QString()); if (!layoutId.isEmpty() && (layoutId == m_layoutName)) { m_containments.append(containment); containmentInLayout = true; } } if (containmentInLayout) { if (!blockAutomaticLatteViewCreation()) { addView(containment); } else { qDebug() << "delaying LatteView creation for containment :: " << containment->id(); } connect(containment, &QObject::destroyed, this, &GenericLayout::containmentDestroyed); } } void GenericLayout::appletCreated(Plasma::Applet *applet) { //! In Multiple Layout the orphaned systrays must be assigned to layouts //! when the user adds them KConfigGroup appletSettings = applet->containment()->config().group("Applets").group(QString::number(applet->id())).group("Configuration"); int systrayId = appletSettings.readEntry("SystrayContainmentId", -1); if (systrayId != -1) { uint sId = (uint)systrayId; for (const auto containment : m_corona->containments()) { if (containment->id() == sId) { containment->config().writeEntry("layoutId", m_layoutName); } addContainment(containment); } } } void GenericLayout::containmentDestroyed(QObject *cont) { if (!m_corona) { return; } Plasma::Containment *containment = static_cast(cont); if (containment) { int containmentIndex = m_containments.indexOf(containment); if (containmentIndex >= 0) { m_containments.removeAt(containmentIndex); } qDebug() << "Layout " << name() << " :: containment destroyed!!!!"; auto view = m_latteViews.take(containment); if (!view) { view = m_waitingLatteViews.take(containment); } if (view) { view->disconnectSensitiveSignals(); view->deleteLater(); emit viewEdgeChanged(); emit viewsCountChanged(); } } } void GenericLayout::destroyedChanged(bool destroyed) { if (!m_corona) { return; } qDebug() << "dock containment destroyed changed!!!!"; Plasma::Containment *sender = qobject_cast(QObject::sender()); if (!sender) { return; } if (destroyed) { m_waitingLatteViews[sender] = m_latteViews.take(static_cast(sender)); } else { m_latteViews[sender] = m_waitingLatteViews.take(static_cast(sender)); } emit viewEdgeChanged(); emit viewsCountChanged(); } void GenericLayout::renameLayout(QString newName) { if (!m_corona || m_corona->layoutsManager()->memoryUsage() != MemoryUsage::MultipleLayouts) { return; } if (m_layoutFile != Layouts::Importer::layoutFilePath(newName)) { setFile(Layouts::Importer::layoutFilePath(newName)); } setName(newName); for (const auto containment : m_containments) { qDebug() << "Cont ID :: " << containment->id(); containment->config().writeEntry("layoutId", m_layoutName); } } void GenericLayout::addNewView() { if (!m_corona) { return; } m_corona->addViewForLayout(name()); emit viewEdgeChanged(); } void GenericLayout::addView(Plasma::Containment *containment, bool forceOnPrimary, int explicitScreen, Layout::ViewsMap *occupied) { qDebug() << "Layout :::: " << m_layoutName << " ::: addView was called... m_containments :: " << m_containments.size(); if (!containment || !m_corona || !containment->kPackage().isValid()) { qWarning() << "the requested containment plugin can not be located or loaded"; return; } qDebug() << "step 1..."; if (!m_storage->isLatteContainment(containment)) return; qDebug() << "step 2..."; for (auto *dock : m_latteViews) { if (dock->containment() == containment) return; } qDebug() << "step 3..."; QScreen *nextScreen{qGuiApp->primaryScreen()}; bool onPrimary = containment->config().readEntry("onPrimary", true); int id = containment->screen(); if (id == -1 && explicitScreen == -1) { id = containment->lastScreen(); } if (onPrimary) { id = m_corona->screenPool()->primaryScreenId(); } else if (explicitScreen > -1) { id = explicitScreen; } Plasma::Types::Location edge = containment->location(); QString connector = m_corona->screenPool()->hasId(id) ? m_corona->screenPool()->connector(id) : ""; qDebug() << "Adding view - containment id:" << containment->id() << " ,screen :" << id << " - " << connector << " ,onprimary:" << onPrimary << " - " << " edge:" << edge << " ,screenName:" << qGuiApp->primaryScreen()->name() << " ,forceOnPrimary:" << forceOnPrimary; if (occupied && m_corona->screenPool()->hasId(id) && (*occupied).contains(connector) && (*occupied)[connector].contains(edge)) { qDebug() << "Rejected : adding view because the edge is already occupied by a higher priority view ! : " << (*occupied)[connector][edge]; return; } if (id >= 0 && !onPrimary && !forceOnPrimary) { qDebug() << "Add view - connector : " << connector; bool found{false}; if (m_corona->screenPool()->hasId(id)) { for (const auto scr : qGuiApp->screens()) { if (scr && scr->name() == connector) { found = true; nextScreen = scr; break; } } } if (!found) { qDebug() << "Rejected : adding explicit view, screen not available ! : " << connector; return; } //! explicit dock can not be added at explicit screen when that screen is the same with //! primary screen and that edge is already occupied by a primary dock if (nextScreen == qGuiApp->primaryScreen() && primaryDockOccupyEdge(containment->location())) { qDebug() << "Rejected : adding explicit view, primary dock occupies edge at screen ! : " << connector; return; } } if (id >= 0 && onPrimary) { qDebug() << "add dock - connector : " << connector; for (const Plasma::Containment *testContainment : m_latteViews.keys()) { int testScreenId = testContainment->screen(); if (testScreenId == -1) { testScreenId = testContainment->lastScreen(); } bool testOnPrimary = testContainment->config().readEntry("onPrimary", true); Plasma::Types::Location testLocation = static_cast((int)testContainment->config().readEntry("location", (int)Plasma::Types::BottomEdge)); if (!testOnPrimary && m_corona->screenPool()->primaryScreenId() == testScreenId && testLocation == containment->location()) { qDebug() << "Rejected explicit latteView and removing it in order add an onPrimary with higher priority at screen: " << connector; auto viewToDelete = m_latteViews.take(testContainment); viewToDelete->disconnectSensitiveSignals(); viewToDelete->deleteLater(); } } } qDebug() << "Adding view passed ALL checks" << " ,onPrimary:" << onPrimary << " ,screen:" << nextScreen->name() << " !!!"; //! it is used to set the correct flag during the creation //! of the window... This of course is also used during //! recreations of the window between different visibility modes auto mode = static_cast(containment->config().readEntry("visibility", static_cast(Types::DodgeActive))); bool byPassWM{false}; if (mode == Types::AlwaysVisible || mode == Types::WindowsGoBelow || mode == Types::WindowsCanCover || mode == Types::WindowsAlwaysCover) { byPassWM = false; } else { byPassWM = containment->config().readEntry("byPassWM", false); } auto latteView = new Latte::View(m_corona, nextScreen, byPassWM); latteView->init(); latteView->setContainment(containment); //! force this special dock case to become primary //! even though it isnt if (forceOnPrimary) { qDebug() << "Enforcing onPrimary:true as requested for LatteView..."; latteView->setOnPrimary(true); } latteView->setLayout(this); + //! Qt 5.9 creates a crash for this in wayland, that is why the check is used //! but on the other hand we need this for copy to work correctly and show //! the copied dock under X11 //if (!KWindowSystem::isPlatformWayland()) { latteView->show(); //} m_latteViews[containment] = latteView; emit viewsCountChanged(); } void GenericLayout::toggleHiddenState(QString screenName, Plasma::Types::Location edge) { if (!m_corona) { return; } QString validScreenName = qGuiApp->primaryScreen()->name(); if (!screenName.isEmpty()) { validScreenName = screenName; } int viewsOnEdge{0}; for(const auto view : latteViews()) { if (view->positioner()->currentScreenName() == validScreenName && view->location() == edge) { viewsOnEdge++; } } if (viewsOnEdge >= 1) { for(const auto view : latteViews()) { if (view->positioner()->currentScreenName() == validScreenName && view->location() == edge) { if (viewsOnEdge == 1 || (viewsOnEdge >1 && view->visibility() && view->visibility()->mode() == Latte::Types::SideBar)) { view->visibility()->toggleHiddenState(); return; } } } } } bool GenericLayout::initToCorona(Latte::Corona *corona) { if (m_corona) { return false; } m_corona = corona; for (const auto containment : m_corona->containments()) { if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout) { addContainment(containment); } else if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) { QString layoutId = containment->config().readEntry("layoutId", QString()); if (!layoutId.isEmpty() && (layoutId == m_layoutName)) { addContainment(containment); } } } qDebug() << "Layout ::::: " << name() << " added containments ::: " << m_containments.size(); updateLastUsedActivity(); //! signals connect(m_corona->activitiesConsumer(), &KActivities::Consumer::currentActivityChanged, this, &GenericLayout::updateLastUsedActivity); connect(m_corona, &Plasma::Corona::containmentAdded, this, &GenericLayout::addContainment); //!connect signals after adding the containment connect(this, &GenericLayout::viewsCountChanged, m_corona, &Plasma::Corona::availableScreenRectChanged); connect(this, &GenericLayout::viewsCountChanged, m_corona, &Plasma::Corona::availableScreenRegionChanged); emit viewsCountChanged(); return true; } void GenericLayout::updateLastUsedActivity() { if (!m_corona) { return; } if (!m_lastUsedActivity.isEmpty() && !m_corona->layoutsManager()->synchronizer()->activities().contains(m_lastUsedActivity)) { clearLastUsedActivity(); } QString currentId = m_corona->activitiesConsumer()->currentActivity(); QStringList appliedActivitiesIds = appliedActivities(); if (m_lastUsedActivity != currentId && appliedActivitiesIds.contains(currentId)) { m_lastUsedActivity = currentId; emit lastUsedActivityChanged(); } } void GenericLayout::assignToLayout(Latte::View *latteView, QList containments) { if (!m_corona) { return; } if (latteView) { m_latteViews[latteView->containment()] = latteView; m_containments << containments; for (const auto containment : containments) { containment->config().writeEntry("layoutId", name()); if (latteView->containment() != containment) { //! assign signals only to systrays //! the View::setLayout() is responsible for the View::Containment signals connect(containment, &QObject::destroyed, this, &GenericLayout::containmentDestroyed); connect(containment, &Plasma::Applet::destroyedChanged, this, &GenericLayout::destroyedChanged); connect(containment, &Plasma::Containment::appletCreated, this, &GenericLayout::appletCreated); } } latteView->setLayout(this); emit viewsCountChanged(); } //! sync the original layout file for integrity if (m_corona && m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) { m_storage->syncToLayoutFile(false); } } QList GenericLayout::unassignFromLayout(Latte::View *latteView) { QList containments; if (!m_corona) { return containments; } containments << latteView->containment(); for (const auto containment : m_containments) { Plasma::Applet *parentApplet = qobject_cast(containment->parent()); //! add systrays from that latteView if (parentApplet && parentApplet->containment() && parentApplet->containment() == latteView->containment()) { containments << containment; //! unassign signals only to systrays //! the View::setLayout() is responsible for the View::Containment signals disconnect(containment, &QObject::destroyed, this, &GenericLayout::containmentDestroyed); disconnect(containment, &Plasma::Applet::destroyedChanged, this, &GenericLayout::destroyedChanged); disconnect(containment, &Plasma::Containment::appletCreated, this, &GenericLayout::appletCreated); } } for (const auto containment : containments) { m_containments.removeAll(containment); } if (containments.size() > 0) { m_latteViews.remove(latteView->containment()); } //! sync the original layout file for integrity if (m_corona && m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) { m_storage->syncToLayoutFile(false); } return containments; } void GenericLayout::recreateView(Plasma::Containment *containment, bool delayed) { if (!m_corona || m_viewsToRecreate.contains(containment) || !containment || !m_latteViews.contains(containment)) { return; } int delay = delayed ? 350 : 0; m_viewsToRecreate << containment; //! give the time to config window to close itself first and then recreate the dock //! step:1 remove the latteview QTimer::singleShot(delay, [this, containment]() { auto view = m_latteViews[containment]; view->disconnectSensitiveSignals(); //! step:2 add the new latteview connect(view, &QObject::destroyed, this, [this, containment]() { auto view = m_latteViews.take(containment); QTimer::singleShot(250, this, [this, containment]() { if (!m_latteViews.contains(containment)) { qDebug() << "recreate - step 2: adding dock for containment:" << containment->id(); addView(containment); m_viewsToRecreate.removeAll(containment); } }); }); view->deleteLater(); }); } bool GenericLayout::latteViewExists(Plasma::Containment *containment) { if (!m_corona) { return false; } return m_latteViews.keys().contains(containment); } QList GenericLayout::availableEdgesForView(QScreen *scr, Latte::View *forView) const { using Plasma::Types; QList edges{Types::BottomEdge, Types::LeftEdge, Types::TopEdge, Types::RightEdge}; if (!m_corona) { return edges; } for (const auto view : m_latteViews) { //! make sure that availabe edges takes into account only views that should be excluded, //! this is why the forView should not be excluded if (view && view != forView && view->positioner()->currentScreenName() == scr->name()) { edges.removeOne(view->location()); } } return edges; } bool GenericLayout::explicitDockOccupyEdge(int screen, Plasma::Types::Location location) const { if (!m_corona) { return false; } for (const auto containment : m_containments) { if (m_storage->isLatteContainment(containment)) { bool onPrimary = containment->config().readEntry("onPrimary", true); int id = containment->lastScreen(); Plasma::Types::Location contLocation = containment->location(); if (!onPrimary && id == screen && contLocation == location) { return true; } } } return false; } bool GenericLayout::primaryDockOccupyEdge(Plasma::Types::Location location) const { if (!m_corona) { return false; } for (const auto containment : m_containments) { if (m_storage->isLatteContainment(containment)) { bool onPrimary{false}; if (m_latteViews.contains(containment)) { onPrimary = m_latteViews[containment]->onPrimary(); } else { onPrimary = containment->config().readEntry("onPrimary", true); } Plasma::Types::Location contLocation = containment->location(); if (onPrimary && contLocation == location) { return true; } } } return false; } bool GenericLayout::mapContainsId(const Layout::ViewsMap *map, uint viewId) const { for(const auto &scr : map->keys()) { for(const auto &edge : (*map)[scr].keys()) { if ((*map)[scr][edge].contains(viewId)) { return true; } } } return false; } //! screen name, location, containmentId Layout::ViewsMap GenericLayout::validViewsMap(Layout::ViewsMap *occupiedMap) { //! Shared Views occupy the screen edge first //! Primary Views occupy the screen edge if Shared Views do not exist already on that screen edge //! Explicity Views occypy the screen edge if Shared Views and Primary Views do not exist already on that screen edge Layout::ViewsMap map; if (!m_corona) { return map; } if (occupiedMap != nullptr) { map = (*occupiedMap); } QString prmScreenName = qGuiApp->primaryScreen()->name(); //! first step: primary docks must be placed in primary screen free edges for (const auto containment : m_containments) { if (m_storage->isLatteContainment(containment)) { int screenId = 0; //! valid screen id if (latteViewExists(containment)) { screenId = m_latteViews[containment]->positioner()->currentScreenId(); } else { screenId = containment->screen(); if (screenId == -1) { screenId = containment->lastScreen(); } } bool onPrimary{true}; //! valid onPrimary flag if (latteViewExists(containment)) { onPrimary = m_latteViews[containment]->onPrimary(); } else { onPrimary = containment->config().readEntry("onPrimary", true); } //! valid location Plasma::Types::Location location = containment->location(); if (onPrimary && (!occupiedMap || !(*occupiedMap)[prmScreenName].contains(location))) { map[prmScreenName][location] << containment->id(); } } } Layout::ViewsMap explicitMap; //! second step: explicit docks must be placed in their screens if the screen edge is free for (const auto containment : m_containments) { if (m_storage->isLatteContainment(containment)) { int screenId = 0; //! valid screen id if (latteViewExists(containment)) { screenId = m_latteViews[containment]->positioner()->currentScreenId(); } else { screenId = containment->screen(); if (screenId == -1) { screenId = containment->lastScreen(); } } bool onPrimary{true}; //! valid onPrimary flag if (latteViewExists(containment)) { onPrimary = m_latteViews[containment]->onPrimary(); } else { onPrimary = containment->config().readEntry("onPrimary", true); } //! valid location Plasma::Types::Location location = containment->location(); if (!onPrimary) { QString expScreenName = m_corona->screenPool()->connector(screenId); if (m_corona->screenPool()->screenExists(screenId) && !map[expScreenName].contains(location)) { explicitMap[expScreenName][location] << containment->id(); } } } } for(const QString &expScreenName : explicitMap.keys()) { for(const Plasma::Types::Location &expLocation : explicitMap[expScreenName].keys()) { map[expScreenName][expLocation] << explicitMap[expScreenName][expLocation]; } } return map; } //! the central functions that updates loading/unloading latteviews //! concerning screen changed (for multi-screen setups mainly) void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap) { if (!m_corona) { return; } qDebug() << "START of SyncLatteViewsToScreens ...."; qDebug() << "LAYOUT ::: " << name(); qDebug() << "screen count changed -+-+ " << qGuiApp->screens().size(); Layout::ViewsMap viewsMap = validViewsMap(occupiedMap); if (occupiedMap != nullptr) { qDebug() << "Occupied map used :: " << *occupiedMap; } QString prmScreenName = qGuiApp->primaryScreen()->name(); qDebug() << "PRIMARY SCREEN :: " << prmScreenName; qDebug() << "LATTEVIEWS MAP :: " << viewsMap; //! add views for (const auto containment : m_containments) { int screenId = containment->screen(); if (screenId == -1) { screenId = containment->lastScreen(); } if (!latteViewExists(containment) && mapContainsId(&viewsMap, containment->id())) { qDebug() << "syncLatteViewsToScreens: view must be added... for containment:" << containment->id() << " at screen:" << m_corona->screenPool()->connector(screenId); addView(containment); } } //! remove views QList viewsToDelete; for (auto view : m_latteViews) { auto containment = view->containment(); if (containment && !mapContainsId(&viewsMap, containment->id())) { viewsToDelete << containment; } } while(!viewsToDelete.isEmpty()) { auto containment = viewsToDelete.takeFirst(); auto view = m_latteViews.take(containment); qDebug() << "syncLatteViewsToScreens: view must be deleted... for containment:" << containment->id() << " at screen:" << view->positioner()->currentScreenName(); view->disconnectSensitiveSignals(); view->deleteLater(); } //! reconsider views for (const auto view : m_latteViews) { if (view->containment() && mapContainsId(&viewsMap, view->containment()->id())) { //! if the dock will not be deleted its a very good point to reconsider //! if the screen in which is running is the correct one qDebug() << "syncLatteViewsToScreens: view must consider its screen... for containment:" << view->containment()->id() << " at screen:" << view->positioner()->currentScreenName(); view->reconsiderScreen(); } } qDebug() << "end of, syncLatteViewsToScreens ...."; } QList GenericLayout::containmentSystrays(Plasma::Containment *containment) const { QList trays; if (m_storage->isLatteContainment(containment)) { auto applets = containment->config().group("Applets"); for (const auto &applet : applets.groupList()) { KConfigGroup appletSettings = applets.group(applet).group("Configuration"); int tSysId = appletSettings.readEntry("SystrayContainmentId", -1); if (tSysId != -1) { trays << tSysId; } } } return trays; } QString GenericLayout::reportHtml(const ScreenPool *screenPool) { //qDebug() << "DBUS CALL ::: " << identifier << " - " << value; auto locationText = [this](const int &location) { switch (location) { case Plasma::Types::BottomEdge: return i18nc("bottom edge", "Bottom"); case Plasma::Types::LeftEdge: return i18nc("left edge", "Left"); case Plasma::Types::TopEdge: return i18nc("top edge", "Top"); case Plasma::Types::RightEdge: return i18nc("right edge", "Right"); } return QString(); }; auto idsLineStr = [this](const QList list) { QString line; for(int i=0; i"; if (activeViews == 0) { report += " -- "; } else { report += "" + QString::number(activeViews) +""; } report += ""; //! latte containment ids, systrays QHash> systrays; QList assignedSystrays; QList orphanSystrays; if (isActive()) { //! organize systrays for (const auto containment : m_containments) { QList trays = containmentSystrays(containment); if (trays.count() > 0) { systrays[containment->id()] = trays; assignedSystrays << trays; } } //! orphan systrays for (const auto containment : m_containments) { if (!m_storage->isLatteContainment(containment) && !assignedSystrays.contains(containment->id())) { orphanSystrays << containment->id(); } } } else { m_storage->systraysInformation(systrays, assignedSystrays, orphanSystrays); } report += ""; report += "" + i18n("Orphan Systrays:") +""; if (orphanSystrays.count() == 0) { report += " -- "; } else { report += "" + idsLineStr(orphanSystrays) +""; } report += ""; report += ""; report += ""; report += "" + "" + "" + "" + ""; report += ""; QList viewsData; if (isActive()) { //! collect viewData results for (const auto containment : m_containments) { if (m_storage->isLatteContainment(containment)) { ViewData vData; vData.id = containment->id(); vData.active = latteViewExists(containment); vData.location = containment->location(); //! onPrimary / Screen Id int screenId = -1; bool onPrimary = true; if (latteViewExists(containment)) { screenId = m_latteViews[containment]->positioner()->currentScreenId(); onPrimary = m_latteViews[containment]->onPrimary(); } else { screenId = containment->screen(); onPrimary = containment->config().readEntry("onPrimary", true); if (screenId == -1) { screenId = containment->lastScreen(); } } vData.onPrimary = onPrimary; vData.screenId = screenId; vData.systrays = containmentSystrays(containment); viewsData << vData; } } } else { viewsData = m_storage->viewsData(systrays); } //! sort views data viewsData = sortedViewsData(viewsData); QStringList unknownScreens; //! print viewData results for (int i=0; i"; } report += ""; //! screen QString screenStr = "[" + i18nc("primary screen","Primary") + "]"; if (viewsData[i].active && viewsData[i].onPrimary) { screenStr = "" + screenStr + ""; } if (!viewsData[i].onPrimary) { if (!screenPool->hasId(viewsData[i].screenId)) { screenStr = "[" + QString::number(viewsData[i].screenId) + "]"; unknownScreens << QString("[" + QString::number(viewsData[i].screenId) + "]"); } else { screenStr = screenPool->connector(viewsData[i].screenId); } } if(viewsData[i].active) { screenStr = "" + screenStr + ""; } report += ""; //! edge QString edgeStr = locationText(viewsData[i].location); if(viewsData[i].active) { edgeStr = "" + edgeStr + ""; } report += "" ; //! active QString activeStr = " -- "; if(viewsData[i].active) { activeStr = "" + i18n("Yes") + ""; } report += "" ; //! systrays QString systraysStr = " -- "; if (viewsData[i].systrays.count() > 0) { systraysStr = idsLineStr(viewsData[i].systrays); } if(viewsData[i].active) { systraysStr = "" + systraysStr + ""; } report += ""; report += ""; } report += "
" + i18nc("view id","ID") + "" + i18n("Screen") + "" + i18nc("screen edge","Edge") + "" + i18nc("active dock/panel","Active") + "" + i18n("Systrays") + "

" + idStr + "" + screenStr + "" + edgeStr + "" + activeStr + "" + systraysStr + "
"; report += "

"; QStringList errorsList; bool broken = m_storage->layoutIsBroken(errorsList); if (!broken && unknownScreens.count() == 0) { report += "" + i18n("No errors were identified for this layout...") + "
"; } else { report += "" + i18n("Errors:") + "
"; } if (broken){ for(int i=0; i
"; } } if (unknownScreens.count() > 0) { report += "" + i18n("Unknown screens: ") + unknownScreens.join(", ") + "
"; } return report; } QList GenericLayout::viewsScreens() { QList screens; if (isActive()) { for (const auto containment : m_containments) { if (m_storage->isLatteContainment(containment)) { int screenId = -1; //! valid screen id if (latteViewExists(containment)) { screenId = m_latteViews[containment]->positioner()->currentScreenId(); } else { screenId = containment->screen(); if (screenId == -1) { screenId = containment->lastScreen(); } } if (screenId!=-1 &&!screens.contains(screenId)) { screens << screenId; } } } return screens; } else { return m_storage->viewsScreens(); } } //! STORAGE bool GenericLayout::isWritable() const { return m_storage->isWritable(); } void GenericLayout::lock() { m_storage->lock(); } void GenericLayout::unlock() { m_storage->unlock(); } void GenericLayout::syncToLayoutFile(bool removeLayoutId) { m_storage->syncToLayoutFile(removeLayoutId); } void GenericLayout::copyView(Plasma::Containment *containment) { m_storage->copyView(containment); emit viewEdgeChanged(); } void GenericLayout::importToCorona() { m_storage->importToCorona(); } bool GenericLayout::layoutIsBroken() const { QStringList errors; return m_storage->layoutIsBroken(errors); } } } diff --git a/containment/package/contents/code/LayoutManager.js b/containment/package/contents/code/LayoutManager.js index 69021570..12ed3e9d 100644 --- a/containment/package/contents/code/LayoutManager.js +++ b/containment/package/contents/code/LayoutManager.js @@ -1,496 +1,496 @@ /* * Copyright 2016 Smith AR * 2016-2018 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 . */ var layout; var layoutS; var layoutE; var root; -var container; +var metrics; var plasmoid; var lastSpacer; var childFoundId = 11; var inRestore=false; function restore() { inRestore = true; var configString = String(plasmoid.configuration.appletOrder) //array, a cell for encoded item order var itemsArray = configString.split(";"); //map applet id->order in panel var idsOrder = new Object(); //map order in panel -> applet pointer var appletsOrder = new Object(); for (var i = 0; i < itemsArray.length; i++) { //property name: applet id //property value: order idsOrder[itemsArray[i]] = i; } for (var i = 0; i < plasmoid.applets.length; ++i) { if (idsOrder[plasmoid.applets[i].id] !== undefined) { appletsOrder[idsOrder[plasmoid.applets[i].id]] = plasmoid.applets[i]; //ones that weren't saved in AppletOrder go to the end } else { appletsOrder["unordered"+i] = plasmoid.applets[i]; } } //finally, restore the applets in the correct order for (var i in appletsOrder) { root.addApplet(appletsOrder[i], -1, -1) } if (plasmoid.configuration.alignment === 10 /*Justify*/) { // console.log("splitters restored:"+plasmoid.configuration.splitterPosition+ " - " + plasmoid.configuration.splitterPosition2); //add the splitters in the correct position if they exist var validSplitter1 = -1; if(plasmoid.configuration.splitterPosition !== -1){ var missingApplets = 0; for (var i=0; i= 0; --i) { var child = layout.children[i]; if (child.applet === applet) { child.destroy(); } } } //insert item2 before item1 function insertBefore(item1, item2) { return insertBeforeForLayout(layout, item1, item2); } //insert item2 before item1 function insertBeforeForLayout(tLayout, item1, item2) { if (item1 === item2) { return -1; } var removed = new Array(); var child; var i; for (i = tLayout.children.length - 1; i >= 0; --i) { child = tLayout.children[i]; removed.push(child); child.parent = root; if (child === item1) { break; } } item2.parent = tLayout; for (var j = removed.length - 1; j >= 0; --j) { removed[j].parent = tLayout; } return i; } //insert item2 after item1 function insertAfter(item1, item2) { return insertAfterForLayout(layout, item1, item2); } //insert item2 after item1 function insertAfterForLayout(tLayout, item1, item2) { if (item1 === item2) { return -1; } var removed = new Array(); var child; var i; for (i = tLayout.children.length - 1; i >= 0; --i) { child = tLayout.children[i]; //never ever insert after lastSpacer if (child === lastSpacer && item1 === lastSpacer) { removed.push(child); child.parent = root; break; } else if (child === item1) { //Already in position, do nothing if (tLayout.children[i+1] === item2) { return -1; } break; } removed.push(child); child.parent = root; } item2.parent = tLayout; for (var j = removed.length - 1; j >= 0; --j) { removed[j].parent = tLayout; } return i; } function insertAtIndex(item, position) { var addToEnd = false; if (position < 0 || (position > layout.children.length && !item.isInternalViewSplitter)) { return; } else if (position >= layout.children.length) { addToEnd = true; } //never ever insert after lastSpacer var firstItem = (layout.children.length === 1) && (layout.children[0] === lastSpacer); //Important !!! , this is used to add the first item if(firstItem){ lastSpacer.parent = root; position = 0; } if (addToEnd){ item.parent=layout; return; } if(layout.children.length > 0){ if (layout.children[position] === lastSpacer) { --position; } } var removedItems = new Array(); var totalChildren = layout.children.length; for (var i = position; i < totalChildren; ++i) { var child = layout.children[position]; child.parent = root; removedItems.push(child); } item.parent = layout; for (var i in removedItems) { removedItems[i].parent = layout; } } function insertAtCoordinates(item, x, y) { if (root.isHorizontal) { y = layout.height / 2; } else { x = layout.width / 2; } var child = layout.childAt(x, y); //if we got a place inside the space between 2 applets, we have to find it manually if (!child) { if (root.isHorizontal) { for (var i = 0; i < layout.children.length; ++i) { var candidate = layout.children[i]; if (x >= candidate.x && x < candidate.x + candidate.width + layout.rowSpacing) { child = candidate; break; } } } else { for (var i = 0; i < layout.children.length; ++i) { var candidate = layout.children[i]; if (y >= candidate.x && y < candidate.y + candidate.height + layout.columnSpacing) { child = candidate; break; } } } } //already in position if (child === item) { return; } if (!child) { // check if dragging takes place after the end of the layout if ( ((root.isVertical && y > layout.height)||(root.isHorizontal && x > layout.width)) && layout.children.length>0 ){ child = layout.children[layout.children.length-1]; } else { child = layout.children[0]; } } else { item.parent = root; } if ((root.isVertical && y < child.y + child.height/2) || (root.isHorizontal && x < child.x + child.width/2)) { return insertBefore(child, item); } else { return insertAfter(child, item); } } //this is used only for the start and end layouts function insertAtLayoutCoordinates(tLayout, item, x, y) { if (root.isHorizontal) { y = tLayout.height / 2; } else { x = tLayout.width / 2; } var child = tLayout.childAt(x, y); //if we got a place inside the space between 2 applets, we have to find it manually if (!child) { if (root.isHorizontal) { for (var i = 0; i < tLayout.children.length; ++i) { var candidate = tLayout.children[i]; if (x >= candidate.x && x < candidate.x + candidate.width + tLayout.rowSpacing) { child = candidate; break; } } } else { for (var i = 0; i < tLayout.children.length; ++i) { var candidate = tLayout.children[i]; if (y >= candidate.x && y < candidate.y + candidate.height + tLayout.columnSpacing) { child = candidate; break; } } } } //already in position if (child === item) { // return childFoundId; } if (!child) { // check if dragging takes place after the end of the layout - var neededSpace = 1.5 * (container.iconSize + root.lengthMargin); + var neededSpace = 1.5 * (metrics.iconSize + root.lengthMargin); if ( (((root.isVertical && (y - neededSpace) <= tLayout.height) && y>=0) ||(root.isHorizontal && (x - neededSpace) <= tLayout.width) && x>=0) && tLayout.children.length>0 ){ child = tLayout.children[layout.children.length-1]; // check if dragging takes place before the start of the layout } else if ( ((root.isVertical && (y >= -neededSpace) && (y<=neededSpace)) ||(root.isHorizontal && (x >= -neededSpace) && (x<=neededSpace))) && tLayout.children.length>0 ){ child = tLayout.children[0]; } else { return -1; //child = tLayout.children[0]; } } else { item.parent = root; } if ((root.isVertical && y < child.y + child.height/2) || (root.isHorizontal && x < child.x + child.width/2)) { return insertBeforeForLayout(tLayout, child, item); } else { return insertAfterForLayout(tLayout, child, item); } } function insertAtCoordinates2(item, x, y) { var pos = -1; if (!root.inConfigureAppletsMode) { var layoutPosS = layoutS.mapFromItem(root, x, y); pos = insertAtLayoutCoordinates(layoutS, item, layoutPosS.x, layoutPosS.y); if (pos === -1){ var layoutPosE = layoutE.mapFromItem(root, x, y); pos = insertAtLayoutCoordinates(layoutE, item, layoutPosE.x, layoutPosE.y); } } if (pos!==childFoundId && pos === -1) { var layoutPos = layout.mapFromItem(root, x, y); insertAtCoordinates(item, layoutPos.x, layoutPos.y); } } diff --git a/containment/package/contents/ui/DebugWindow.qml b/containment/package/contents/ui/DebugWindow.qml index fbc21275..c0e79138 100644 --- a/containment/package/contents/ui/DebugWindow.qml +++ b/containment/package/contents/ui/DebugWindow.qml @@ -1,832 +1,832 @@ /* * Copyright 2016 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 . */ import QtQuick 2.1 import QtQuick.Window 2.2 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.latte.core 0.2 as LatteCore Window{ width: mainGrid.width + 10 height: Math.min(mainGrid.height+10, Screen.height - visibilityManager.thicknessNormalOriginal) visible: true property string space:" : " PlasmaExtras.ScrollArea { id: scrollArea anchors.fill: parent verticalScrollBarPolicy: Qt.ScrollBarAsNeeded horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff flickableItem.flickableDirection: Flickable.VerticalFlick Grid{ id:mainGrid columns: 2 Text{ text: "Screen id"+space } Text{ text: latteView && latteView.positioner ? latteView.positioner.currentScreenName : "___" } Text{ text: "Screen Geometry"+space } Text{ text: { if (latteView && latteView.screenGeometry){ return latteView.screenGeometry.x+","+latteView.screenGeometry.y+ " "+latteView.screenGeometry.width+"x"+latteView.screenGeometry.height; } else { return "_,_ _x_"; } } } Text{ text: "Window Geometry"+space } Text{ text: { if (latteView) { return latteView.x + "," + latteView.y + " "+latteView.width+ "x"+latteView.height; } else { return "_,_ _x_"; } } } Text{ text: "On Primary"+space } Text{ text: { if (latteView && latteView.onPrimary) return "Yes"; else return "No"; } } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Contents Width"+space } Text{ text: layoutsContainer.contentsWidth } Text{ text: "Contents Height"+space } Text{ text: layoutsContainer.contentsHeight } Text{ text: "Max Length"+space } Text{ text: root.maxLengthPerCentage +"%" } Text{ text: "Max Length (pixels)"+space } Text{ text: root.maxLength } Text{ text: "Min Length"+space } Text{ text: root.minLengthPerCentage +"%" } Text{ text: "Min Length (pixels)"+space } Text{ text: root.minLength } Text{ text: "Offset (pixels)"+space } Text{ text: root.offset } Text{ text: "Mask"+space } Text{ text: { if (latteView && latteView.effects && latteView.effects.mask) { return latteView.effects.mask.x +", "+ latteView.effects.mask.y+" "+latteView.effects.mask.width+"x"+latteView.effects.mask.height; } else { return "_,_ _x_"; } } } Text{ text: "Absolute Geometry"+space } Text{ text: { if (latteView && latteView.absoluteGeometry) { return latteView.absoluteGeometry.x + ", " + latteView.absoluteGeometry.y + " " + latteView.absoluteGeometry.width + "x" + latteView.absoluteGeometry.height; } else { return "_,_ _x_"; } } } Text{ text: "Local Geometry"+space } Text{ text: { if (latteView && latteView.localGeometry) { return latteView.localGeometry.x + ", " + latteView.localGeometry.y + " " + latteView.localGeometry.width + "x" + latteView.localGeometry.height; } else { return "_,_ _x_"; } } } Text{ text: "Draw Effects"+space } Text{ text: { if (latteView && latteView.effects && latteView.effects.drawEffects) return "Yes"; else return "No"; } } Text{ text: "Effects Area"+space } Text{ text: { if (latteView && latteView.effects && latteView.effects.rect) { return latteView.effects.rect.x + ", " + latteView.effects.rect.y + " " +latteView.effects.rect.width + "x" + latteView.effects.rect.height; } else { return "_,_ _x_"; } } } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Is Hidden (flag)"+space } Text{ text: { if (latteView && latteView.visibility && latteView.visibility.isHidden) return "Yes"; else return "No"; } } Text{ text: "Contains Mouse (flag)"+space } Text{ text: { if (latteView && latteView.visibility && latteView.visibility.containsMouse) return "Yes"; else return "No"; } } Text{ text: "Edit Mode"+space } Text{ text: { if (root.editMode) return "Yes"; else return "No"; } } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Location"+space } Text{ text: { switch(plasmoid.location){ case PlasmaCore.Types.LeftEdge: return "Left Edge"; break; case PlasmaCore.Types.RightEdge: return "Right Edge"; break; case PlasmaCore.Types.TopEdge: return "Top Edge"; break; case PlasmaCore.Types.BottomEdge: return "Bottom Edge"; break; } return " : " + plasmoid.location; } } Text{ text: "Alignment"+space } Text{ text: { switch(plasmoid.configuration.alignment){ case LatteCore.Types.Left: return "Left"; break; case LatteCore.Types.Right: return "Right"; break; case LatteCore.Types.Center: return "Center"; break; case LatteCore.Types.Top: return "Top"; break; case LatteCore.Types.Bottom: return "Bottom"; break; case LatteCore.Types.Justify: return "Justify"; break; } return " : " + plasmoid.configuration.alignment; } } Text{ text: "Visibility"+space } Text{ text: { if (!latteView || !latteView.visibility) return ""; switch(latteView.visibility.mode){ case LatteCore.Types.AlwaysVisible: return "Always Visible"; break; case LatteCore.Types.AutoHide: return "Auto Hide"; break; case LatteCore.Types.DodgeActive: return "Dodge Active"; break; case LatteCore.Types.DodgeMaximized: return "Dodge Maximized"; break; case LatteCore.Types.DodgeAllWindows: return "Dodge All Windows"; break; case LatteCore.Types.DodgeAllWindows: return "Dodge All Windows"; break; case LatteCore.Types.WindowsGoBelow: return "Windows Go Below"; break; case LatteCore.Types.WindowsCanCover: return "Windows Can Cover"; break; case LatteCore.Types.WindowsAlwaysCover: return "Windows Always Cover"; break; case LatteCore.Types.SideBar: return "OnDemand SideBar"; break; case LatteCore.Types.NormalWindow: return "Normal Window"; break; case LatteCore.Types.None: return "None"; break; } return " : " + latteView.visibility.mode; } } Text{ text: "Zoom Factor"+space } Text{ text: root.zoomFactor } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Icon Size (current)"+space } Text{ - text: container.iconSize + text: metrics.iconSize } Text{ text: "Icon Size (user)"+space } Text{ text: plasmoid.configuration.iconSize } Text{ text: "Icon Size (proportion)"+space } Text{ - text: container.proportionIconSize + text: metrics.proportionIconSize } Text{ text: "Icon Size (auto decrease), Enabled"+space } Text{ text: { if (autosize.isActive) return "Yes"; else return "No"; } } Text{ text: "Icon Size (auto decrease)"+space } Text{ text: autosize.iconSize } Text{ text: "Length Internal Margin (pixels)"+space } Text{ text: root.lengthIntMargin } Text{ text: "Length External Margin (pixels)"+space } Text{ text: root.lengthExtMargin } Text{ text: "Thickness Margin"+space } Text{ text: root.thickMargin } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Show Panel Background (user)"+space } Text{ text: { if (plasmoid.configuration.useThemePanel) return "Yes"; else return "No"; } } Text{ text: "Force Transparent Panel (auto)"+space } Text{ text: { if (root.forceTransparentPanel) return "Yes"; else return "No"; } } Text{ text: "Panel Background Length"+space } Text{ text: root.realPanelLength } Text{ text: "Panel Background Thickness(user)"+space } Text{ text: plasmoid.configuration.panelSize + "%" } Text{ text: "Panel Background Thickness(automatic)"+space } Text{ text: root.realPanelSize } Text{ text: "Panel Transparency"+space } Text{ text: root.panelTransparency + "%" } Text{ text: "Panel Shadows Active"+space } Text{ text: { if (root.panelShadowsActive) return "Yes"; else return "No"; } } Text{ text: "Panel Background Shadow"+space } Text{ text: root.panelShadow } Text{ text: "Panel Thickness Margin High"+space } Text{ text: root.panelThickMarginHigh } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Mask - Normal Thickness"+space } Text{ text: visibilityManager.thicknessNormal } Text{ text: "Thickness Uses Panel Size"+space } Text{ text: visibilityManager.panelIsBiggerFromIconSize } Text{ text: "Behave As Plasma Panel"+space } Text{ text: { if (root.behaveAsPlasmaPanel) return "Yes"; else return "No"; } } Text{ text: "Draw Shadows (external)"+space } Text{ text: { if (root.drawShadowsExternal) return "Yes"; else return "No"; } } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Applet Hovered"+space } Text{ text: layoutsContainer.hoveredIndex } Text{ text: "Task Hovered"+space } Text{ text: root.latteAppletHoveredIndex } Text{ text: "In Normal State"+space } Text{ text: visibilityManager.normalState } Text{ text: "Animations Both Axis"+space } Text{ text: animations.needBothAxis.count } Text{ text: "Animations Only Length"+space } Text{ text: animations.needLength.count } Text{ text: "Animations Need Thickness"+space } Text{ text: animations.needThickness.count } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Start Layout Shown Applets"+space } Text{ text: layoutsContainer.startLayout.shownApplets } Text{ text: "Start Layout Applets (with fill)"+space } Text{ text: layoutsContainer.startLayout.fillApplets } Text{ text: "Start Layout Size (no fill applets)"+space } Text{ text: layoutsContainer.startLayout.sizeWithNoFillApplets+" px." } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Main Layout Shown Applets"+space } Text{ text: layoutsContainer.mainLayout.shownApplets } Text{ text: "Main Layout Applets (with fill)"+space } Text{ text: layoutsContainer.mainLayout.fillApplets } Text{ text: "Main Layout Size (no fill applets)"+space } Text{ text: layoutsContainer.mainLayout.sizeWithNoFillApplets+" px." } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "End Layout Shown Applets"+space } Text{ text: layoutsContainer.endLayout.shownApplets } Text{ text: "End Layout Applets (with fill)"+space } Text{ text: layoutsContainer.endLayout.fillApplets } Text{ text: "End Layout Size (no fill applets)"+space } Text{ text: layoutsContainer.endLayout.sizeWithNoFillApplets+" px." } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Applets need Windows Tracking"+space } Text{ text: appletsRecords.windowsTrackingCount } Text{ text: "Last Active Window Current Screen (id)"+space } Text{ text: latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.lastActiveWindow.isValid ? latteView.windowsTracker.currentScreen.lastActiveWindow.winId : "--" } Text{ text: "Last Active Window Current Screen (title)"+space } Text{ text: latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.lastActiveWindow.isValid ? latteView.windowsTracker.currentScreen.lastActiveWindow.display : "--" elide: Text.ElideRight } Text{ text: "Last Active Window All Screens (id)"+space } Text{ text: latteView && latteView.windowsTracker && latteView.windowsTracker.allScreens.lastActiveWindow.isValid ? latteView.windowsTracker.allScreens.lastActiveWindow.winId : "--" } Text{ text: "Last Active Window All Screens (title)"+space } Text{ text: latteView && latteView.windowsTracker && latteView.windowsTracker.allScreens.lastActiveWindow.isValid ? latteView.windowsTracker.allScreens.lastActiveWindow.display : "--" elide: Text.ElideRight } } } } diff --git a/containment/package/contents/ui/PanelBox.qml b/containment/package/contents/ui/PanelBox.qml index 8be70408..8685b946 100644 --- a/containment/package/contents/ui/PanelBox.qml +++ b/containment/package/contents/ui/PanelBox.qml @@ -1,935 +1,935 @@ /* * Copyright 2016 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 . */ import QtQuick 2.1 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 import QtGraphicalEffects 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 import org.kde.latte.core 0.2 as LatteCore import "colorizer" as Colorizer Item{ id:barLine width: root.isHorizontal ? panelWidth : smallSize height: root.isVertical ? panelHeight : smallSize opacity: root.useThemePanel ? 1 : 0 readonly property bool isShown: (solidBackground.opacity > 0) || (overlayedBackground.opacity > 0) property int animationTime: 6*animations.speedFactor.current*animations.duration.small property int screenEdgeMargin: root.screenEdgeMarginEnabled ? root.localScreenEdgeMargin - shadowsSvgItem.screenEdgeShadow : 0 property int lengthMargins: { return root.isVertical ? shadowsSvgItem.marginsHeight : shadowsSvgItem.marginsWidth } property int panelWidth: { if (root.behaveAsPlasmaPanel && LatteCore.WindowSystem.compositingActive && !root.editMode) { return root.width; } else { if ((root.panelAlignment === LatteCore.Types.Justify) && root.isHorizontal) { return root.maxLength; } else { return Math.max(root.minLength, layoutsContainerItem.mainLayout.width + spacing); } } } property int panelHeight: { if (root.behaveAsPlasmaPanel && LatteCore.WindowSystem.compositingActive && !root.editMode) { return root.height; } else { if ((root.panelAlignment === LatteCore.Types.Justify) && root.isVertical) { return root.maxLength; } else { return Math.max(root.minLength, layoutsContainerItem.mainLayout.height + spacing); } } } property int spacing: { if (root.panelAlignment === LatteCore.Types.Justify && root.maxLengthPerCentage === 100) { return 0; } else if (!LatteCore.WindowSystem.compositingActive) { return root.panelEdgeSpacing/2; } else if (root.panelAlignment === LatteCore.Types.Center || root.panelAlignment === LatteCore.Types.Justify || root.offset!==0) { return root.panelEdgeSpacing/2; } else { return root.panelEdgeSpacing/4; } } property int smallSize: 16 //Math.max(3.7*root.statesLineSize, 16) Behavior on opacity{ enabled: LatteCore.WindowSystem.compositingActive NumberAnimation { duration: barLine.animationTime } } Behavior on opacity{ enabled: !LatteCore.WindowSystem.compositingActive NumberAnimation { duration: 0 } } Binding{ target: root property: "currentPanelTransparency" value: overlayedBackground.opacity>0 ? overlayedBackground.opacity*100 : solidBackground.opacity*100 } Binding { target: root property: "realPanelLength" value: root.isVertical ? barLine.height : barLine.width } Binding { target: root property: "totalPanelEdgeSpacing" value: spacing } onXChanged: solidBackground.updateEffectsArea(); onYChanged: solidBackground.updateEffectsArea(); /// plasmoid's default panel /* BorderImage{ anchors.fill:parent source: "../images/panel-west.png" border { left:8; right:8; top:8; bottom:8 } opacity: (!root.useThemePanel) ? 1 : 0 visible: (opacity == 0) ? false : true horizontalTileMode: BorderImage.Stretch verticalTileMode: BorderImage.Stretch Behavior on opacity{ NumberAnimation { duration: 200 } } }*/ /// the current theme's panel PlasmaCore.FrameSvgItem{ id: shadowsSvgItem width: root.isVertical ? panelSize + marginsWidth : Math.min(parent.width + marginsWidth, root.width - marginsWidth) height: root.isVertical ? Math.min(parent.height + marginsHeight, root.height - marginsHeight) : panelSize + marginsHeight imagePath: hideShadow ? "" : "widgets/panel-background" prefix: hideShadow ? "" : "shadow" visible: (opacity == 0) ? false : true opacity: { if ((root.forceTransparentPanel && !root.forcePanelForBusyBackground) || !root.useThemePanel) return 0; else return 1; } enabledBorders: latteView && latteView.effects ? latteView.effects.enabledBorders : PlasmaCore.FrameSvg.NoBorder //! set true by default in order to avoid crash on startup because imagePath is set to "" readonly property bool themeHasShadow: themeExtended ? themeExtended.hasShadow : true readonly property bool hideShadow: (root.behaveAsPlasmaPanel && !root.editMode) || !LatteCore.WindowSystem.compositingActive || !root.panelShadowsActive || !themeHasShadow Behavior on opacity { enabled: LatteCore.WindowSystem.compositingActive NumberAnimation { duration: barLine.animationTime } } Behavior on opacity{ enabled: !LatteCore.WindowSystem.compositingActive NumberAnimation { duration: 0 } } property int screenEdgeShadow: { if (imagePath === "" || !root.screenEdgeMarginEnabled) { return 0; } if (plasmoid.location === PlasmaCore.Types.LeftEdge) { return margins.left; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { return margins.right; } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { return margins.top; } else if (plasmoid.location === PlasmaCore.Types.BottomEdge) { return margins.bottom; } } property int marginsWidth: { if (imagePath === "") { return 0; } else { if (root.panelAlignment === LatteCore.Types.Left && root.offset===0) return margins.right; else if (root.panelAlignment === LatteCore.Types.Right && root.offset===0) return margins.left; else return margins.left+margins.right; } } property int marginsHeight: { if (imagePath === "") { return 0; } else { if (root.panelAlignment === LatteCore.Types.Top && root.offset===0) return margins.bottom; else if (root.panelAlignment === LatteCore.Types.Bottom && root.offset===0) return margins.top; else return margins.top + margins.bottom; } } property int panelSize: automaticPanelSize property int automaticPanelSize: { if (root.behaveAsPlasmaPanel) { - return container.iconSize + root.thickMargins;// + 2; + return metrics.iconSize + root.thickMargins;// + 2; } else { - var icons = container.iconSize + root.thickMargins;// + 2; + var icons = metrics.iconSize + root.thickMargins;// + 2; var panelt = root.themePanelThickness;// + 2; root.realPanelThickness = icons + root.localScreenEdgeMargin; return Math.min(icons, panelt); } } property int shadowsSize: 0 Binding{ target: shadowsSvgItem property: "shadowsSize" value:{ if (shadowsSvgItem && !root.behaveAsPlasmaPanel && root.useThemePanel && root.panelShadowsActive){ if (root.isVertical){ if (plasmoid.location === PlasmaCore.Types.LeftEdge) return shadowsSvgItem.margins.right; else if (plasmoid.location === PlasmaCore.Types.RightEdge) return shadowsSvgItem.margins.left; } else { if (plasmoid.location === PlasmaCore.Types.BottomEdge) return shadowsSvgItem.margins.top; else if (plasmoid.location === PlasmaCore.Types.TopEdge) return shadowsSvgItem.margins.bottom; } } else { return 0; } } } Behavior on opacity{ enabled: LatteCore.WindowSystem.compositingActive NumberAnimation { duration: barLine.animationTime } } Behavior on opacity{ enabled: !LatteCore.WindowSystem.compositingActive NumberAnimation { duration: 0 } } Binding { target: root property: "panelShadow" when: shadowsSvgItem value: shadowsSvgItem.shadowsSize } Binding { target: root property: "realPanelSize" when: shadowsSvgItem value: shadowsSvgItem.panelSize } Binding { target: root property: "panelMarginLength" when: shadowsSvgItem value: root.isVertical ? shadowsSvgItem.marginsHeight : shadowsSvgItem.marginsWidth } //! Show a fake blurness under panel background for editMode visual feedback Loader { anchors.fill: solidBackground active: editModeVisual.inEditMode && root.userShowPanelBackground && plasmoid.configuration.blurEnabled sourceComponent: Item { Image{ id: backTiler anchors.fill: parent visible: false fillMode: Image.Tile source: hasBackground ? latteView.layout.background : "../icons/"+latteView.layout.background+"print.jpg" readonly property bool hasBackground: (latteView && latteView.layout && latteView.layout.background.startsWith("/")) ? true : false } ShaderEffectSource { id: effectSource anchors.fill: parent visible: false sourceItem: backTiler sourceRect: Qt.rect(0,0, width, height) } FastBlur{ id: blur anchors.fill: parent opacity: editModeVisual.appliedOpacity * 1.4 source: effectSource radius: 50 visible: false } OpacityMask { anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenterOffset: overlayedBackground.painterRectangle.anchors.horizontalCenterOffset anchors.verticalCenterOffset: overlayedBackground.painterRectangle.anchors.verticalCenterOffset width: overlayedBackground.painterRectangle.width height: overlayedBackground.painterRectangle.height source: blur maskSource: overlayedBackground.painterRectangle opacity: blur.opacity } } } //! This is used to provide real solidness Colorizer.CustomBackground { id: backgroundLowestRectangle anchors.fill: solidBackground opacity: normalizedOpacity backgroundColor: colorizerManager.backgroundColor roundness: overlayedBackground.roundness visible: LatteCore.WindowSystem.compositingActive && solidBackground.exceedsThemeOpacityLimits readonly property real normalizedOpacity: visible ? Math.min(1, (appliedOpacity - solidBackground.themeMaxOpacity)/(1-solidBackground.themeMaxOpacity)) : 0 readonly property real appliedOpacity: visible ? solidBackground.appliedOpacity : 0 Behavior on opacity{ enabled: LatteCore.WindowSystem.compositingActive NumberAnimation { duration: barLine.animationTime } } Behavior on opacity{ enabled: !LatteCore.WindowSystem.compositingActive NumberAnimation { duration: 0 } } } PlasmaCore.FrameSvgItem{ id: solidBackground anchors.leftMargin: LatteCore.WindowSystem.compositingActive ? shadowsSvgItem.margins.left : 0 anchors.rightMargin: LatteCore.WindowSystem.compositingActive ? shadowsSvgItem.margins.right : 0 anchors.topMargin: LatteCore.WindowSystem.compositingActive ? shadowsSvgItem.margins.top : 0 anchors.bottomMargin: LatteCore.WindowSystem.compositingActive ? shadowsSvgItem.margins.bottom : 0 anchors.fill:parent opacity: normalizedOpacity readonly property bool exceedsThemeOpacityLimits: appliedOpacity > themeMaxOpacity readonly property bool forceSolidness: root.forceSolidPanel || !LatteCore.WindowSystem.compositingActive //! must be normalized to plasma theme maximum opacity readonly property real normalizedOpacity: Math.min(1, appliedOpacity / themeMaxOpacity) readonly property real appliedOpacity: overlayedBackground.opacity > 0 && !paintInstantly ? 0 : overlayedBackground.midOpacity readonly property real themeMaxOpacity: { if (themeExtended) { switch(plasmoid.location) { case PlasmaCore.Types.BottomEdge: return themeExtended.bottomEdgeMaxOpacity; case PlasmaCore.Types.LeftEdge: return themeExtended.leftEdgeMaxOpacity; case PlasmaCore.Types.TopEdge: return themeExtended.topEdgeMaxOpacity; case PlasmaCore.Types.RightEdge: return themeExtended.rightEdgeMaxOpacity; default: return 0; } } return 1; } //! When switching from overlaied background to regular one this must be done //! instantly otherwise the transition is not smooth readonly property bool paintInstantly: (root.hasExpandedApplet && root.plasmaBackgroundForPopups) || root.plasmaStyleBusyForTouchingBusyVerticalView property rect efGeometry: Qt.rect(-1,-1,0,0) imagePath: "widgets/panel-background" onWidthChanged: updateEffectsArea(); onHeightChanged: updateEffectsArea(); Component.onCompleted: { root.updateEffectsArea.connect(updateEffectsArea); adjustPrefix(); } Component.onDestruction: { root.updateEffectsArea.disconnect(updateEffectsArea); } onImagePathChanged: solidBackground.adjustPrefix(); Connections{ target: root onEditModeChanged: { solidBackground.updateEffectsArea(); } } //! Fix for FrameSvgItem QML version not updating its margins after a theme change //! with this hack we enforce such update. I could use the repaintNeeded signal but //! it is called more often than the themeChanged one. Connections { target: themeExtended onThemeChanged: { solidBackground.adjustPrefix(); plasmoid.configuration.panelShadows = !plasmoid.configuration.panelShadows; plasmoid.configuration.panelShadows = !plasmoid.configuration.panelShadows; updateEffectsArea(); } } Connections { target: latteView ? latteView.visibility : null onIsHiddenChanged: solidBackground.updateEffectsArea(); } Connections{ target: plasmoid onLocationChanged: solidBackground.adjustPrefix(); } function updateEffectsArea(){ if (!latteView) return; if (!LatteCore.WindowSystem.compositingActive) { //! NOCOMPOSITING mode is a special case and Effects Area is also used for //! different calculations for View::mask() var rootGeometry = mapToItem(root, 0, 0); efGeometry.x = rootGeometry.x; efGeometry.y = rootGeometry.y; efGeometry.width = width; efGeometry.height = height; } else { if (latteView.visibility.isHidden) { //! valid hide mask efGeometry.x = -1; efGeometry.y = -1; efGeometry.width = 1; efGeometry.height = 1; } else { if (!root.behaveAsPlasmaPanel || root.editMode) { var rootGeometry = mapToItem(root, 0, 0); efGeometry.x = rootGeometry.x; efGeometry.y = rootGeometry.y; } else { efGeometry.x = 0; efGeometry.y = 0; } efGeometry.width = width; efGeometry.height = height; } } latteView.effects.rect = efGeometry; //! needed both for NOCOMPOSITING environments AND //! View::localGeometry calculations visibilityManager.updateMaskArea(); } Binding { target: root property: "panelThickMarginBase" value: { var minimum = root.screenEdgeMarginEnabled && themeExtended ? themeExtended.topEdgeRoundness : 0; if (root.useThemePanel){ if (root.isVertical){ if (plasmoid.location === PlasmaCore.Types.LeftEdge) { return Math.max(minimum, solidBackground.margins.left); } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { return Math.max(minimum, solidBackground.margins.right); } } else { if (plasmoid.location === PlasmaCore.Types.BottomEdge) { return Math.max(minimum, solidBackground.margins.bottom); } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { return Math.max(minimum, solidBackground.margins.top); } } } else { return 0; } } } Binding { target: root property: "panelThickMarginHigh" value: { var minimum = root.screenEdgeMarginEnabled && themeExtended ? themeExtended.topEdgeRoundness : 0; if (root.useThemePanel){ if (root.isVertical){ if (plasmoid.location === PlasmaCore.Types.LeftEdge) { return Math.max(minimum, solidBackground.margins.right); } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { return Math.max(minimum, solidBackground.margins.left); } } else { if (plasmoid.location === PlasmaCore.Types.BottomEdge) { return Math.max(minimum, solidBackground.margins.top); } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { return Math.max(minimum, solidBackground.margins.bottom); } } } else { return 0; } } } onRepaintNeeded: { if (root.behaveAsPlasmaPanel) adjustPrefix(); } enabledBorders: latteView && latteView.effects ? latteView.effects.enabledBorders : PlasmaCore.FrameSvg.NoBorder Behavior on opacity{ enabled: LatteCore.WindowSystem.compositingActive && !solidBackground.paintInstantly NumberAnimation { duration: barLine.animationTime } } Behavior on opacity{ enabled: !LatteCore.WindowSystem.compositingActive NumberAnimation { duration: 0 } } function adjustPrefix() { if (!plasmoid) { return ""; } var pre; switch (plasmoid.location) { case PlasmaCore.Types.LeftEdge: pre = "west"; break; case PlasmaCore.Types.TopEdge: pre = "north"; break; case PlasmaCore.Types.RightEdge: pre = "east"; break; case PlasmaCore.Types.BottomEdge: pre = "south"; break; default: prefix = ""; } prefix = [pre, ""]; } } Colorizer.CustomBackground { id: overlayedBackground anchors.fill: solidBackground readonly property bool busyBackground: root.forcePanelForBusyBackground && (solidBackground.opacity === 0 || !solidBackground.paintInstantly) readonly property bool coloredView: colorizerManager.mustBeShown && colorizerManager.applyTheme !== theme opacity: { if (busyBackground && !forceSolidness) { return plasmoid.configuration.panelTransparency / 100; } if (coloredView) { return midOpacity; } return 0; } backgroundColor: colorizerManager.backgroundColor borderWidth: 1 borderColor: backgroundColor roundness: { if (themeExtended) { switch(plasmoid.location) { case PlasmaCore.Types.BottomEdge: return themeExtended.bottomEdgeRoundness; case PlasmaCore.Types.LeftEdge: return themeExtended.leftEdgeRoundness; case PlasmaCore.Types.TopEdge: return themeExtended.topEdgeRoundness; case PlasmaCore.Types.RightEdge: return themeExtended.rightEdgeRoundness; default: return 0; } } return 0; } property real midOpacity: { if (forceSolidness) { return 1; } else if (!root.userShowPanelBackground || root.forcePanelForBusyBackground || root.forceTransparentPanel) { return 0; } else { return plasmoid.configuration.panelTransparency / 100; } } readonly property bool forceSolidness: root.forceSolidPanel || !LatteCore.WindowSystem.compositingActive Behavior on opacity{ enabled: LatteCore.WindowSystem.compositingActive NumberAnimation { duration: barLine.animationTime } } Behavior on opacity{ enabled: !LatteCore.WindowSystem.compositingActive NumberAnimation { duration: 0 } } Behavior on backgroundColor{ enabled: LatteCore.WindowSystem.compositingActive ColorAnimation { duration: barLine.animationTime } } Behavior on backgroundColor{ enabled: !LatteCore.WindowSystem.compositingActive ColorAnimation { duration: 0 } } } //! Outline drawing Loader{ anchors.fill: solidBackground active: root.panelOutline && !(root.hasExpandedApplet && root.plasmaBackgroundForPopups) sourceComponent: Colorizer.CustomBackground{ backgroundColor: "transparent" borderColor: colorizerManager.outlineColor borderWidth: themeExtended ? themeExtended.outlineWidth : 1 roundness: overlayedBackground.roundness } } //! CustomBackground debugger /*Colorizer.CustomBackground { anchors.fill: solidBackground backgroundColor: "transparent" borderWidth: 1 borderColor: "red" roundness: overlayedBackground.roundness }*/ } transitions: Transition { enabled: editModeVisual.plasmaEditMode AnchorAnimation { duration: 0.8 * animations.duration.proposed easing.type: Easing.OutCubic } } //BEGIN states //user set Panel Positions //0-Center, 1-Left, 2-Right, 3-Top, 4-Bottom states: [ ///Left State { name: "leftCenterOrJustify" when: (plasmoid.location === PlasmaCore.Types.LeftEdge)&&(root.panelAlignment === LatteCore.Types.Center || root.panelAlignment === LatteCore.Types.Justify) AnchorChanges { target: barLine anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } AnchorChanges { target: shadowsSvgItem anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } PropertyChanges{ target: barLine anchors.leftMargin: barLine.screenEdgeMargin; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: (root.panelAlignment === LatteCore.Types.Center ? root.offset : 0); } }, ///Left State { name: "leftTop" when: (plasmoid.location === PlasmaCore.Types.LeftEdge)&&(root.panelAlignment === LatteCore.Types.Top) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: barLine.screenEdgeMargin; anchors.rightMargin:0; anchors.topMargin:root.offset; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, ///Left State { name: "leftBottom" when: (plasmoid.location === PlasmaCore.Types.LeftEdge)&&(root.panelAlignment === LatteCore.Types.Bottom) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: barLine.screenEdgeMargin; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:root.offset; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, ///Right State { name: "rightCenterOrJustify" when: (plasmoid.location === PlasmaCore.Types.RightEdge)&&(root.panelAlignment === LatteCore.Types.Center || root.panelAlignment === LatteCore.Types.Justify) AnchorChanges { target: barLine anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } AnchorChanges { target: shadowsSvgItem anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin: barLine.screenEdgeMargin; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: (root.panelAlignment === LatteCore.Types.Center ? root.offset : 0); } }, State { name: "rightTop" when: (plasmoid.location === PlasmaCore.Types.RightEdge)&&(root.panelAlignment === LatteCore.Types.Top) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin: barLine.screenEdgeMargin; anchors.topMargin:root.offset; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State { name: "rightBottom" when: (plasmoid.location === PlasmaCore.Types.RightEdge)&&(root.panelAlignment === LatteCore.Types.Bottom) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined } } AnchorChanges { target: shadowsSvgItem anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin: barLine.screenEdgeMargin; anchors.topMargin:0; anchors.bottomMargin:root.offset; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, ///Bottom State { name: "bottomCenterOrJustify" when: (plasmoid.location === PlasmaCore.Types.BottomEdge)&&(root.panelAlignment === LatteCore.Types.Center || root.panelAlignment === LatteCore.Types.Justify) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin: barLine.screenEdgeMargin; anchors.horizontalCenterOffset: (root.panelAlignment === LatteCore.Types.Center ? root.offset : 0); anchors.verticalCenterOffset: 0; } }, State { name: "bottomLeft" when: (plasmoid.location === PlasmaCore.Types.BottomEdge) &&(((root.panelAlignment === LatteCore.Types.Left)&&(Qt.application.layoutDirection !== Qt.RightToLeft)) || ((root.panelAlignment === LatteCore.Types.Right)&&(Qt.application.layoutDirection === Qt.RightToLeft))) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: root.offset; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin: barLine.screenEdgeMargin; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State { name: "bottomRight" when: (plasmoid.location === PlasmaCore.Types.BottomEdge) &&(((root.panelAlignment === LatteCore.Types.Right)&&(Qt.application.layoutDirection !== Qt.RightToLeft)) ||((root.panelAlignment === LatteCore.Types.Left)&&(Qt.application.layoutDirection === Qt.RightToLeft))) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin:root.offset; anchors.topMargin:0; anchors.bottomMargin: barLine.screenEdgeMargin; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, ///Top State { name: "topCenterOrJustify" when: (plasmoid.location === PlasmaCore.Types.TopEdge)&&(root.panelAlignment === LatteCore.Types.Center || root.panelAlignment === LatteCore.Types.Justify) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin: barLine.screenEdgeMargin; anchors.bottomMargin:0; anchors.horizontalCenterOffset: (root.panelAlignment === LatteCore.Types.Center ? root.offset : 0); anchors.verticalCenterOffset: 0; } }, State { name: "topLeft" when: (plasmoid.location === PlasmaCore.Types.TopEdge) &&(((root.panelAlignment === LatteCore.Types.Left)&&(Qt.application.layoutDirection !== Qt.RightToLeft)) || ((root.panelAlignment === LatteCore.Types.Right)&&(Qt.application.layoutDirection === Qt.RightToLeft))) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: root.offset; anchors.rightMargin:0; anchors.topMargin: barLine.screenEdgeMargin; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State { name: "topRight" when: (plasmoid.location === PlasmaCore.Types.TopEdge) &&(((root.panelAlignment === LatteCore.Types.Right)&&(Qt.application.layoutDirection !== Qt.RightToLeft)) ||((root.panelAlignment === LatteCore.Types.Left)&&(Qt.application.layoutDirection === Qt.RightToLeft))) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin:root.offset; anchors.topMargin: barLine.screenEdgeMargin; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] //END states } diff --git a/containment/package/contents/ui/VisibilityManager.qml b/containment/package/contents/ui/VisibilityManager.qml index 7f6672ac..f1e54b03 100644 --- a/containment/package/contents/ui/VisibilityManager.qml +++ b/containment/package/contents/ui/VisibilityManager.qml @@ -1,1004 +1,1004 @@ /* * Copyright 2016 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 . */ import QtQuick 2.1 import QtQuick.Window 2.2 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.plasmoid 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.private.containment 0.1 as LatteContainment Item{ id: manager anchors.fill: parent property QtObject window property bool debugManager: Qt.application.arguments.indexOf("--mask") >= 0 property bool blockUpdateMask: false property bool inForceHiding: false //is used when the docks are forced in hiding e.g. when changing layouts property bool normalState : false // this is being set from updateMaskArea property bool previousNormalState : false // this is only for debugging purposes - property bool panelIsBiggerFromIconSize: root.useThemePanel && (root.themePanelThickness >= (container.iconSize + root.thickMargin)) + property bool panelIsBiggerFromIconSize: root.useThemePanel && (root.themePanelThickness >= (metrics.iconSize + root.thickMargin)) property bool maskIsFloating: !root.behaveAsPlasmaPanel && !root.editMode && screenEdgeMarginEnabled && !plasmoid.configuration.fittsLawIsRequested && !inSlidingIn && !inSlidingOut property int maskFloatedGap: maskIsFloating ? Math.max(0, root.localScreenEdgeMargin - root.panelShadow) : 0 property int animationSpeed: LatteCore.WindowSystem.compositingActive ? (editModeVisual.inEditMode ? editModeVisual.speed * 0.8 : animations.speedFactor.normal * 1.62 * animations.duration.large) : 0 property bool inLocationAnimation: latteView && latteView.positioner && latteView.positioner.inLocationAnimation property bool inSlidingIn: false //necessary because of its init structure property alias inSlidingOut: slidingAnimationAutoHiddenOut.running property bool inTempHiding: false property int length: root.isVertical ? Screen.height : Screen.width //screenGeometry.height : screenGeometry.width property int slidingOutToPos: { if (root.behaveAsPlasmaPanel) { var edgeMargin = screenEdgeMarginEnabled ? plasmoid.configuration.screenEdgeMargin : 0 root.isHorizontal ? root.height + edgeMargin - 1 : root.width + edgeMargin - 1; } else { var topOrLeftEdge = ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)); return (topOrLeftEdge ? -thicknessNormal : thicknessNormal); } } property int thicknessAutoHidden: LatteCore.WindowSystem.compositingActive ? 2 : 1 - property int thicknessMid: root.screenEdgeMargin + (1 + (0.65 * (root.maxZoomFactor-1)))*(container.iconSize+root.thickMargins+extraThickMask) //needed in some animations - property int thicknessNormal: root.screenEdgeMargin + Math.max(container.iconSize + root.thickMargins + extraThickMask + 1, root.realPanelSize + root.panelShadow) + property int thicknessMid: root.screenEdgeMargin + (1 + (0.65 * (root.maxZoomFactor-1)))*(metrics.iconSize+root.thickMargins+extraThickMask) //needed in some animations + property int thicknessNormal: root.screenEdgeMargin + Math.max(metrics.iconSize + root.thickMargins + extraThickMask + 1, root.realPanelSize + root.panelShadow) - property int thicknessZoom: root.screenEdgeMargin + ((container.iconSize+root.thickMargins+extraThickMask) * root.maxZoomFactor) + 2 + property int thicknessZoom: root.screenEdgeMargin + ((metrics.iconSize+root.thickMargins+extraThickMask) * root.maxZoomFactor) + 2 //it is used to keep thickness solid e.g. when iconSize changes from auto functions - property int thicknessMidOriginal: root.screenEdgeMargin + Math.max(thicknessNormalOriginal,extraThickMask + (1 + (0.65 * (root.maxZoomFactor-1)))*(container.maxIconSize+root.maxThickMargin)) //needed in some animations - property int thicknessNormalOriginal: root.screenEdgeMargin + container.maxIconSize + (root.maxThickMargin * 2) //this way we always have the same thickness published at all states + property int thicknessMidOriginal: root.screenEdgeMargin + Math.max(thicknessNormalOriginal,extraThickMask + (1 + (0.65 * (root.maxZoomFactor-1)))*(metrics.maxIconSize+root.maxThickMargin)) //needed in some animations + property int thicknessNormalOriginal: root.screenEdgeMargin + metrics.maxIconSize + (root.maxThickMargin * 2) //this way we always have the same thickness published at all states /*property int thicknessNormalOriginal: !root.behaveAsPlasmaPanel || root.editMode ? thicknessNormalOriginalValue : root.realPanelSize + root.panelShadow*/ - property int thicknessNormalOriginalValue: root.screenEdgeMargin + container.maxIconSize + (root.maxThickMargin * 2) + extraThickMask + 1 - property int thicknessZoomOriginal:root.screenEdgeMargin + Math.max( ((container.maxIconSize+(root.maxThickMargin * 2)) * root.maxZoomFactor) + extraThickMask + 2, + property int thicknessNormalOriginalValue: root.screenEdgeMargin + metrics.maxIconSize + (root.maxThickMargin * 2) + extraThickMask + 1 + property int thicknessZoomOriginal:root.screenEdgeMargin + Math.max( ((metrics.maxIconSize+(root.maxThickMargin * 2)) * root.maxZoomFactor) + extraThickMask + 2, root.realPanelSize + root.panelShadow, (LatteCore.WindowSystem.compositingActive ? thicknessEditMode + root.editShadow : thicknessEditMode)) //! is used from Panel in edit mode in order to provide correct masking property int thicknessEditMode: thicknessNormalOriginalValue + editModeVisual.settingsThickness //! when Latte behaves as Plasma panel - property int thicknessAsPanel: container.iconSize + root.thickMargins + property int thicknessAsPanel: metrics.iconSize + root.thickMargins //! is used to increase the mask thickness readonly property int marginBetweenContentsAndRuler: root.editMode ? 10 : 0 property int extraThickMask: marginBetweenContentsAndRuler + Math.max(indicatorsExtraThickMask, shadowsExtraThickMask) //! this is set from indicators when they need extra thickness mask size readonly property int indicatorsExtraThickMask: indicators.info.extraMaskThickness property int shadowsExtraThickMask: { if (LatteCore.WindowSystem.isPlatformWayland) { return 0; } //! 45% of max shadow size in px. var shadowMaxNeededMargin = 0.45 * root.appShadowSizeOriginal; var shadowOpacity = (plasmoid.configuration.shadowOpacity) / 100; //! +40% of shadow opacity in percentage shadowOpacity = shadowOpacity + shadowOpacity*0.4; //! This way we are trying to calculate how many pixels are needed in order for the shadow //! to be drawn correctly without being cut of from View::mask() under X11 shadowMaxNeededMargin = (shadowMaxNeededMargin * shadowOpacity); //! give some more space when items shadows are enabled and extremely big if (root.enableShadows && root.maxThickMargin < shadowMaxNeededMargin) { return shadowMaxNeededMargin - root.maxThickMargin; } return 0; } Binding{ target: latteView property:"maxThickness" //! prevents updating window geometry during closing window in wayland and such fixes a crash when: latteView && !inTempHiding && !inForceHiding value: root.behaveAsPlasmaPanel && !root.editMode ? thicknessAsPanel : thicknessZoomOriginal } - property bool validIconSize: (container.iconSize===container.maxIconSize || container.iconSize === autosize.iconSize) + property bool validIconSize: (metrics.iconSize===metrics.maxIconSize || metrics.iconSize === autosize.iconSize) property bool inPublishingState: validIconSize && !inSlidingIn && !inSlidingOut && !inTempHiding && !inForceHiding Binding{ target: latteView property:"normalThickness" //! workaround Qt 5.14 bindings warning to not restore values because to qt 6.0 changes //when: latteView && inPublishingState readonly property bool inactiveness: latteView && inPublishingState value: { if (!inactiveness) { return; } return root.behaveAsPlasmaPanel && !root.editMode ? thicknessAsPanel : thicknessNormalOriginal } } Binding{ target: latteView property:"editThickness" when: latteView value: thicknessEditMode } Binding{ target: latteView property: "type" when: latteView value: root.viewType } Binding{ target: latteView property: "behaveAsPlasmaPanel" when: latteView value: root.editMode ? false : root.behaveAsPlasmaPanel } Binding{ target: latteView property: "fontPixelSize" when: theme value: theme.defaultFont.pixelSize } Binding{ target: latteView property:"inEditMode" when: latteView value: root.editMode } Binding{ target: latteView property:"latteTasksArePresent" when: latteView value: latteApplet !== null } Binding{ target: latteView property: "maxLength" when: latteView value: root.inConfigureAppletsMode ? 1 : maxLengthPerCentage/100 } Binding{ target: latteView property: "offset" when: latteView value: plasmoid.configuration.offset } Binding{ target: latteView property: "screenEdgeMargin" when: latteView value: plasmoid.configuration.screenEdgeMargin } Binding{ target: latteView property: "screenEdgeMarginEnabled" when: latteView value: root.screenEdgeMarginEnabled && !root.hideThickScreenGap } Binding{ target: latteView property: "alignment" when: latteView value: root.panelAlignment } Binding{ target: latteView property: "isTouchingTopViewAndIsBusy" when: latteView value: { var isTouchingTopScreenEdge = (latteView.y === latteView.screenGeometry.y); var hasTopBorder = ((latteView.effects && (latteView.effects.enabledBorders & PlasmaCore.FrameSvg.TopBorder)) > 0); return root.isVertical && !latteView.visibility.isHidden && !isTouchingTopScreenEdge && !hasTopBorder && panelBoxBackground.isShown; } } Binding{ target: latteView property: "isTouchingBottomViewAndIsBusy" when: latteView value: { var latteBottom = latteView.y + latteView.height; var screenBottom = latteView.screenGeometry.y + latteView.screenGeometry.height; var isTouchingBottomScreenEdge = (latteBottom === screenBottom); var hasBottomBorder = ((latteView.effects && (latteView.effects.enabledBorders & PlasmaCore.FrameSvg.BottomBorder)) > 0); return root.isVertical && !latteView.visibility.isHidden && !isTouchingBottomScreenEdge && !hasBottomBorder && panelBoxBackground.isShown; } } //! View::Effects bindings Binding{ target: latteView && latteView.effects ? latteView.effects : null property: "backgroundOpacity" when: latteView && latteView.effects value: root.currentPanelTransparency } Binding{ target: latteView && latteView.effects ? latteView.effects : null property: "drawEffects" when: latteView && latteView.effects value: LatteCore.WindowSystem.compositingActive && !root.inConfigureAppletsMode && (((root.blurEnabled && root.useThemePanel) || (root.blurEnabled && root.forceSolidPanel && LatteCore.WindowSystem.compositingActive)) && (!root.inStartup || inForceHiding || inTempHiding)) } Binding{ target: latteView && latteView.effects ? latteView.effects : null property: "drawShadows" when: latteView && latteView.effects value: root.drawShadowsExternal && (!root.inStartup || inForceHiding || inTempHiding) && !(latteView && latteView.visibility.isHidden) } Binding{ target: latteView && latteView.effects ? latteView.effects : null property:"editShadow" when: latteView && latteView.effects value: root.editShadow } Binding{ target: latteView && latteView.effects ? latteView.effects : null property:"innerShadow" when: latteView && latteView.effects value: { if (editModeVisual.editAnimationEnded && !root.behaveAsPlasmaPanel) { return root.editShadow; } else { return root.panelShadow; } } } Binding{ target: latteView && latteView.effects ? latteView.effects : null property: "settingsMaskSubtracted" when: latteView && latteView.effects value: { if (LatteCore.WindowSystem.compositingActive && root.editMode && editModeVisual.editAnimationEnded && (animations.needBothAxis.count === 0 || root.zoomFactor===1) ) { return true; } else { return false; } } } //! View::Positioner bindings Binding{ target: latteView && latteView.positioner ? latteView.positioner : null property: "isStickedOnTopEdge" when: latteView && latteView.positioner value: plasmoid.configuration.isStickedOnTopEdge } Binding{ target: latteView && latteView.positioner ? latteView.positioner : null property: "isStickedOnBottomEdge" when: latteView && latteView.positioner value: plasmoid.configuration.isStickedOnBottomEdge } //! View::WindowsTracker bindings Binding{ target: latteView && latteView.windowsTracker ? latteView.windowsTracker : null property: "enabled" when: latteView && latteView.windowsTracker && latteView.visibility value: (latteView && latteView.visibility && !(latteView.visibility.mode === LatteCore.Types.AlwaysVisible /* Visibility */ || latteView.visibility.mode === LatteCore.Types.WindowsGoBelow || latteView.visibility.mode === LatteCore.Types.AutoHide)) || appletsRecords.windowsTrackingCount > 0 /*Applets Need Windows Tracking */ || root.dragActiveWindowEnabled /*Dragging Active Window(Empty Areas)*/ || ((root.backgroundOnlyOnMaximized /*Dynamic Background */ || plasmoid.configuration.solidBackgroundForMaximized || root.disablePanelShadowMaximized || root.windowColors !== LatteContainment.Types.NoneWindowColors)) || (root.screenEdgeMarginsEnabled /*Dynamic Screen Edge Margin*/ && plasmoid.configuration.hideScreenGapForMaximized) } Connections{ target:root onPanelShadowChanged: updateMaskArea(); onPanelThickMarginHighChanged: updateMaskArea(); onRealPanelLengthChanged: updateMaskArea(); } Connections{ target: layoutsManager onCurrentLayoutIsSwitching: { if (LatteCore.WindowSystem.compositingActive && latteView && latteView.layout && latteView.layout.name === layoutName) { manager.inTempHiding = true; manager.inForceHiding = true; root.clearZoom(); manager.slotMustBeHide(); } } } Connections{ target: themeExtended ? themeExtended : null onRoundnessChanged: latteView.effects.forceMaskRedraw(); onThemeChanged: latteView.effects.forceMaskRedraw(); } onMaskIsFloatingChanged: updateMaskArea(); onNormalStateChanged: { if (normalState) { autosize.updateIconSize(); root.updateSizeForAppletsInFill(); } } onThicknessZoomOriginalChanged: { updateMaskArea(); } function slotContainsMouseChanged() { if(latteView.visibility.containsMouse && latteView.visibility.mode !== LatteCore.Types.SideBar) { updateMaskArea(); if (slidingAnimationAutoHiddenOut.running && !inTempHiding && !inForceHiding) { slotMustBeShown(); } } } function slotMustBeShown() { //! WindowsCanCover case if (latteView && latteView.visibility.mode === LatteCore.Types.WindowsCanCover) { latteView.visibility.setViewOnFrontLayer(); return; } //! Normal Dodge/AutoHide case if (!slidingAnimationAutoHiddenIn.running && !inTempHiding && !inForceHiding){ slidingAnimationAutoHiddenIn.init(); } } function slotMustBeHide() { if (latteView && latteView.visibility.mode === LatteCore.Types.WindowsCanCover) { latteView.visibility.setViewOnBackLayer(); return; } //! prevent sliding-in on startup if the dodge modes have sent a hide signal if (inStartupTimer.running && root.inStartup) { root.inStartup = false; } //! Normal Dodge/AutoHide case if((!slidingAnimationAutoHiddenOut.running && !latteView.visibility.blockHiding && (!latteView.visibility.containsMouse || latteView.visibility.mode === LatteCore.Types.SideBar)) || inForceHiding) { slidingAnimationAutoHiddenOut.init(); } } //! functions used for sliding out/in during location/screen changes function slotHideDockDuringLocationChange() { inTempHiding = true; blockUpdateMask = true; if(!slidingAnimationAutoHiddenOut.running) { slidingAnimationAutoHiddenOut.init(); } } function slotShowDockAfterLocationChange() { slidingAnimationAutoHiddenIn.init(); } function sendHideDockDuringLocationChangeFinished(){ blockUpdateMask = false; latteView.positioner.hideDockDuringLocationChangeFinished(); } function sendSlidingOutAnimationEnded() { latteView.visibility.hide(); latteView.visibility.isHidden = true; if (visibilityManager.debugManager) { console.log("hiding animation ended..."); } sendHideDockDuringLocationChangeFinished(); } ///test maskArea function updateMaskArea() { if (!latteView || blockUpdateMask) { return; } var localX = 0; var localY = 0; normalState = ((animations.needBothAxis.count === 0) && (animations.needLength.count === 0)) || (latteView.visibility.isHidden && !latteView.visibility.containsMouse && animations.needThickness.count === 0); // debug maskArea criteria if (debugManager) { console.log(animations.needBothAxis.count + ", " + animations.needLength.count + ", " + animations.needThickness.count + ", " + latteView.visibility.isHidden); if (previousNormalState !== normalState) { console.log("normal state changed to:" + normalState); previousNormalState = normalState; } } var tempLength = root.isHorizontal ? width : height; var tempThickness = root.isHorizontal ? height : width; var space = 0; if (LatteCore.WindowSystem.compositingActive) { if (root.useThemePanel){ space = root.totalPanelEdgeSpacing + root.panelMarginLength + 1; } else { space = root.totalPanelEdgeSpacing + 1; } } else { space = root.totalPanelEdgeSpacing + root.panelMarginLength; } var noCompositingEdit = !LatteCore.WindowSystem.compositingActive && root.editMode; if (LatteCore.WindowSystem.compositingActive || noCompositingEdit) { if (normalState) { //console.log("entered normal state..."); //count panel length //used when !compositing and in editMode if (noCompositingEdit) { tempLength = root.isHorizontal ? root.width : root.height; } else { if(root.isHorizontal) { if (plasmoid.configuration.alignment === LatteCore.Types.Justify) { tempLength = layoutsContainer.width; } else { tempLength = Math.max(root.realPanelLength, layoutsContainer.mainLayout.width); } } else { if (plasmoid.configuration.alignment === LatteCore.Types.Justify) { tempLength = layoutsContainer.height; } else { tempLength = Math.max(root.realPanelLength, layoutsContainer.mainLayout.height); } } tempLength = tempLength + space; } tempThickness = thicknessNormal; if (animations.needThickness.count > 0) { tempThickness = LatteCore.WindowSystem.compositingActive ? thicknessZoom : thicknessNormal; } if (maskIsFloating) { tempThickness = tempThickness - maskFloatedGap; } if (latteView.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = thicknessAutoHidden; } //configure x,y based on plasmoid position and root.panelAlignment(Alignment) if ((plasmoid.location === PlasmaCore.Types.BottomEdge) || (plasmoid.location === PlasmaCore.Types.TopEdge)) { if (plasmoid.location === PlasmaCore.Types.BottomEdge) { if (latteView.visibility.isHidden && latteView.visibility.supportsKWinEdges) { localY = latteView.height + tempThickness; } else if (maskIsFloating && !latteView.visibility.isHidden) { localY = latteView.height - tempThickness - maskFloatedGap; } else { localY = latteView.height - tempThickness; } } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { if (latteView.visibility.isHidden && latteView.visibility.supportsKWinEdges) { localY = -tempThickness; } else if (maskIsFloating && !latteView.visibility.isHidden) { localY = maskFloatedGap; } else { localY = 0; } } if (noCompositingEdit) { localX = 0; } else if (plasmoid.configuration.alignment === LatteCore.Types.Justify) { localX = (latteView.width/2) - tempLength/2 + root.offset; } else if (root.panelAlignment === LatteCore.Types.Left) { localX = root.offset; } else if (root.panelAlignment === LatteCore.Types.Center) { localX = (latteView.width/2) - tempLength/2 + root.offset; } else if (root.panelAlignment === LatteCore.Types.Right) { localX = latteView.width - tempLength - root.offset; } } else if ((plasmoid.location === PlasmaCore.Types.LeftEdge) || (plasmoid.location === PlasmaCore.Types.RightEdge)){ if (plasmoid.location === PlasmaCore.Types.LeftEdge) { if (latteView.visibility.isHidden && latteView.visibility.supportsKWinEdges) { localX = -tempThickness; } else if (maskIsFloating && !latteView.visibility.isHidden) { localX = maskFloatedGap; } else { localX = 0; } } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { if (latteView.visibility.isHidden && latteView.visibility.supportsKWinEdges) { localX = latteView.width + tempThickness; } else if (maskIsFloating && !latteView.visibility.isHidden) { localX = latteView.width - tempThickness - maskFloatedGap; } else { localX = latteView.width - tempThickness; } } if (noCompositingEdit) { localY = 0; } else if (plasmoid.configuration.alignment === LatteCore.Types.Justify) { localY = (latteView.height/2) - tempLength/2 + root.offset; } else if (root.panelAlignment === LatteCore.Types.Top) { localY = root.offset; } else if (root.panelAlignment === LatteCore.Types.Center) { localY = (latteView.height/2) - tempLength/2 + root.offset; } else if (root.panelAlignment === LatteCore.Types.Bottom) { localY = latteView.height - tempLength - root.offset; } } if (latteView.visibility.isHidden && latteView && latteView.visibility.mode === LatteCore.Types.SideBar) { //!hide completely localX = -1; localY = -1; tempThickness = 1; tempLength = 1; } } else { // !inNormalState if(root.isHorizontal) tempLength = Screen.width; //screenGeometry.width; else tempLength = Screen.height; //screenGeometry.height; //grow only on length and not thickness var onlyLengthAnimation = (animations.needLength.count>0 && animations.needBothAxis.count === 0); if(onlyLengthAnimation) { //this is used to fix a bug with shadow showing when the animation of edit mode //is triggered tempThickness = editModeVisual.editAnimationEnded ? thicknessEditMode + root.editShadow : thicknessEditMode if (latteView.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = thicknessAutoHidden; } else if (animations.needThickness.count > 0) { tempThickness = thicknessZoomOriginal; } } else{ //use all thickness space if (latteView.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = LatteCore.WindowSystem.compositingActive ? thicknessAutoHidden : thicknessNormalOriginal; } else { tempThickness = !maskIsFloating ? thicknessZoomOriginal : thicknessZoomOriginal - maskFloatedGap; } } //configure the x,y position based on thickness if(plasmoid.location === PlasmaCore.Types.RightEdge) { localX = !maskIsFloating ? latteView.width - tempThickness : latteView.width - tempThickness - maskFloatedGap; if (localX < 0) { tempThickness = tempThickness + localX; localX = 0; } } else if (plasmoid.location === PlasmaCore.Types.BottomEdge) { localY = !maskIsFloating ? latteView.height - tempThickness : latteView.height - tempThickness - maskFloatedGap; if (localY < 0) { tempThickness = tempThickness + localY; localY = 0; } } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { localY = !maskIsFloating ? 0 : maskFloatedGap; } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { localX = !maskIsFloating ? 0 : maskFloatedGap; } } } // end of compositing calculations var maskArea = latteView.effects.mask; if (LatteCore.WindowSystem.compositingActive) { var maskLength = maskArea.width; //in Horizontal if (root.isVertical) { maskLength = maskArea.height; } var maskThickness = maskArea.height; //in Horizontal if (root.isVertical) { maskThickness = maskArea.width; } } else if (!noCompositingEdit){ //! no compositing case var overridesHidden = latteView.visibility.isHidden && !latteView.visibility.supportsKWinEdges; if (!overridesHidden) { localX = latteView.effects.rect.x; localY = latteView.effects.rect.y; } else { if (plasmoid.location === PlasmaCore.Types.BottomEdge) { localX = latteView.effects.rect.x; localY = root.height - thicknessAutoHidden; } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { localX = latteView.effects.rect.x; localY = 0; } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { localX = 0; localY = latteView.effects.rect.y; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { localX = root.width - thicknessAutoHidden; localY = latteView.effects.rect.y; } } if (root.isHorizontal) { tempThickness = overridesHidden ? thicknessAutoHidden : latteView.effects.rect.height; tempLength = latteView.effects.rect.width; } else { tempThickness = overridesHidden ? thicknessAutoHidden : latteView.effects.rect.width; tempLength = latteView.effects.rect.height; } } // console.log("Not updating mask..."); if( maskArea.x !== localX || maskArea.y !== localY || maskLength !== tempLength || maskThickness !== tempThickness) { // console.log("Updating mask..."); var newMaskArea = Qt.rect(-1,-1,0,0); newMaskArea.x = localX; newMaskArea.y = localY; if (isHorizontal) { newMaskArea.width = tempLength; newMaskArea.height = tempThickness; } else { newMaskArea.width = tempThickness; newMaskArea.height = tempLength; } if (!LatteCore.WindowSystem.compositingActive) { latteView.effects.mask = newMaskArea; } else { if (latteView.behaveAsPlasmaPanel && !root.editMode) { latteView.effects.mask = Qt.rect(0,0,root.width,root.height); } else { latteView.effects.mask = newMaskArea; } } } - var validIconSize = (container.iconSize===container.maxIconSize || container.iconSize === autosize.iconSize); + var validIconSize = (metrics.iconSize===metrics.maxIconSize || metrics.iconSize === autosize.iconSize); //console.log("reached updating geometry ::: "+dock.maskArea); if(inPublishingState && !latteView.visibility.isHidden && (normalState || root.editMode)) { //! Important: Local Geometry must not be updated when view ISHIDDEN //! because it breaks Dodge(s) modes in such case var localGeometry = Qt.rect(0, 0, root.width, root.height); //the shadows size must be removed from the maskArea //before updating the localDockGeometry if (!latteView.behaveAsPlasmaPanel || root.editMode) { - var cleanThickness = container.iconSize + root.thickMargins; + var cleanThickness = metrics.iconSize + root.thickMargins; var edgeMargin = root.screenEdgeMargin; if (plasmoid.location === PlasmaCore.Types.TopEdge) { localGeometry.x = latteView.effects.rect.x; // from effects area localGeometry.width = latteView.effects.rect.width; // from effects area localGeometry.y = edgeMargin; localGeometry.height = cleanThickness ; } else if (plasmoid.location === PlasmaCore.Types.BottomEdge) { localGeometry.x = latteView.effects.rect.x; // from effects area localGeometry.width = latteView.effects.rect.width; // from effects area localGeometry.y = root.height - cleanThickness - edgeMargin; localGeometry.height = cleanThickness; } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { localGeometry.y = latteView.effects.rect.y; // from effects area localGeometry.height = latteView.effects.rect.height; // from effects area localGeometry.x = edgeMargin; localGeometry.width = cleanThickness; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { localGeometry.y = latteView.effects.rect.y; // from effects area localGeometry.height = latteView.effects.rect.height; // from effects area localGeometry.x = root.width - cleanThickness - edgeMargin; localGeometry.width = cleanThickness; } //set the boundaries for latteView local geometry //qBound = qMax(min, qMin(value, max)). localGeometry.x = Math.max(0, Math.min(localGeometry.x, latteView.width)); localGeometry.y = Math.max(0, Math.min(localGeometry.y, latteView.height)); localGeometry.width = Math.min(localGeometry.width, latteView.width); localGeometry.height = Math.min(localGeometry.height, latteView.height); } //console.log("update geometry ::: "+localGeometry); latteView.localGeometry = localGeometry; } } Loader{ anchors.fill: parent active: root.debugMode sourceComponent: Item{ anchors.fill:parent Rectangle{ id: windowBackground anchors.fill: parent border.color: "red" border.width: 1 color: "transparent" } Rectangle{ x: latteView ? latteView.effects.mask.x : -1 y: latteView ? latteView.effects.mask.y : -1 height: latteView ? latteView.effects.mask.height : 0 width: latteView ? latteView.effects.mask.width : 0 border.color: "green" border.width: 1 color: "transparent" } } } /***Hiding/Showing Animations*****/ //////////////// Animations - Slide In - Out SequentialAnimation{ id: slidingAnimationAutoHiddenOut ScriptAction{ script: { root.isHalfShown = true; } } PropertyAnimation { target: !root.behaveAsPlasmaPanel ? layoutsContainer : latteView.positioner property: !root.behaveAsPlasmaPanel ? (root.isVertical ? "x" : "y") : "slideOffset" to: { if (root.behaveAsPlasmaPanel) { return slidingOutToPos; } if (LatteCore.WindowSystem.compositingActive) { return slidingOutToPos; } else { if ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) { return slidingOutToPos + 1; } else { return slidingOutToPos - 1; } } } duration: manager.animationSpeed easing.type: Easing.InQuad } ScriptAction{ script: { latteView.visibility.isHidden = true; if (root.behaveAsPlasmaPanel && latteView.positioner.slideOffset !== 0) { //! hide real panels when they slide-out latteView.visibility.hide(); } } } onStarted: { if (manager.debugManager) { console.log("hiding animation started..."); } } onStopped: { //! Trying to move the ending part of the signals at the end of editing animation if (!manager.inTempHiding) { manager.updateMaskArea(); } else { if (!editModeVisual.inEditMode) { manager.sendSlidingOutAnimationEnded(); } } latteView.visibility.slideOutFinished(); } function init() { if (manager.inLocationAnimation || !latteView.visibility.blockHiding) { start(); } } } SequentialAnimation{ id: slidingAnimationAutoHiddenIn PauseAnimation{ duration: manager.inTempHiding && animations.active ? 500 : 0 } PropertyAnimation { target: !root.behaveAsPlasmaPanel ? layoutsContainer : latteView.positioner property: !root.behaveAsPlasmaPanel ? (root.isVertical ? "x" : "y") : "slideOffset" to: 0 duration: manager.animationSpeed easing.type: Easing.OutQuad } ScriptAction{ script: { root.isHalfShown = false; root.inStartup = false; } } onStarted: { latteView.visibility.show(); if (manager.debugManager) { console.log("showing animation started..."); } } onStopped: { inSlidingIn = false; if (manager.inTempHiding) { manager.inTempHiding = false; autosize.updateIconSize(); } manager.inTempHiding = false; autosize.updateIconSize(); if (manager.debugManager) { console.log("showing animation ended..."); } latteView.visibility.slideInFinished(); //! this is needed in order to update dock absolute geometry correctly in the end AND //! when a floating dock is sliding-in through masking techniques updateMaskArea(); } function init() { inSlidingIn = true; if (slidingAnimationAutoHiddenOut.running) { slidingAnimationAutoHiddenOut.stop(); } latteView.visibility.isHidden = false; updateMaskArea(); start(); } } //! Slides Animations for FLOATING+BEHAVEASPLASMAPANEL when //! HIDETHICKSCREENCAP dynamically is enabled/disabled SequentialAnimation{ id: slidingInRealFloating PropertyAnimation { target: latteView.positioner property: "slideOffset" to: 0 duration: manager.animationSpeed easing.type: Easing.OutQuad } } SequentialAnimation{ id: slidingOutRealFloating PropertyAnimation { target: latteView.positioner property: "slideOffset" to: plasmoid.configuration.screenEdgeMargin duration: manager.animationSpeed easing.type: Easing.InQuad } } Connections { target: root onHideThickScreenGapChanged: { if (root.behaveAsPlasmaPanel && !latteView.visibility.isHidden && !inSlidingIn && !inSlidingOut && !inStartup) { if (hideThickScreenGap) { latteView.positioner.inSlideAnimation = true; slidingInRealFloating.stop(); slidingOutRealFloating.start(); } else { slidingOutRealFloating.stop(); slidingInRealFloating.start(); latteView.positioner.inSlideAnimation = false; } } } } } diff --git a/containment/package/contents/ui/abilities/Animations.qml b/containment/package/contents/ui/abilities/Animations.qml index 83edb2a1..70a85be1 100644 --- a/containment/package/contents/ui/abilities/Animations.qml +++ b/containment/package/contents/ui/abilities/Animations.qml @@ -1,67 +1,67 @@ /* * 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 . */ import QtQuick 2.7 import org.kde.plasma.plasmoid 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.private.app 0.1 as LatteApp import org.kde.latte.abilities.containers 0.1 as ContainerAbility ContainerAbility.Animations { - property Item container: null - property Item settings: null + property Item metrics: null + property QtObject settings: null //! Public Properties active: plasmoid.configuration.animationsEnabled && LatteCore.WindowSystem.compositingActive hasThicknessAnimation: (needBothAxis.count>0) || (needThickness.count>0) duration.large: LatteCore.Environment.longDuration duration.proposed: speedFactor.current * 2.8 * duration.large duration.small: LatteCore.Environment.shortDuration speedFactor.normal: 1.0 speedFactor.current: { if (!active || plasmoid.configuration.durationTime === 0) { return 0; } if (plasmoid.configuration.durationTime === 1 ) { return 0.75; } else if (plasmoid.configuration.durationTime === 2) { return speedFactor.normal; } else if (plasmoid.configuration.durationTime === 3) { return 1.15; } return speedFactor.normal; } //! animations related to parabolic effect hoverPixelSensitivity: { if (!settings || settings.sensitivity === LatteApp.Settings.HighMouseSensitivity) { return 1; } else if (settings.sensitivity === LatteApp.Settings.MediumMouseSensitivity) { - return Math.max(3, container.iconSize / 18); + return Math.max(3, metrics.iconSize / 18); } else if (settings.sensitivity === LatteApp.Settings.LowMouseSensitivity) { - return Math.max(5, container.iconSize / 10); + return Math.max(5, metrics.iconSize / 10); } } } diff --git a/containment/package/contents/ui/abilities/AutoSize.qml b/containment/package/contents/ui/abilities/AutoSize.qml index b624c179..04c13a9f 100644 --- a/containment/package/contents/ui/abilities/AutoSize.qml +++ b/containment/package/contents/ui/abilities/AutoSize.qml @@ -1,249 +1,247 @@ /* * Copyright 2019 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 . */ import QtQuick 2.8 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.plasmoid 2.0 import org.kde.latte.core 0.2 as LatteCore Item { id: sizer // when there are only plasma style task managers OR any applets that fill width or height // the automatic icon size algorithm should better be disabled readonly property bool isActive: !root.containsOnlyPlasmaTasks && layouts.fillApplets<=0 && latteView && latteView.visibility.mode !== LatteCore.Types.SideBar property int iconSize: -1 //it is not set, this is the default - readonly property bool inCalculatedIconSize: ((container.iconSize === sizer.iconSize) || (container.iconSize === container.maxIconSize)) + readonly property bool inCalculatedIconSize: ((metrics.iconSize === sizer.iconSize) || (metrics.iconSize === metrics.maxIconSize)) readonly property bool inAutoSizeAnimation: !inCalculatedIconSize readonly property int automaticStep: 8 readonly property int historyMaxSize: 10 readonly property int historyMinSize: 4 //! Prediction History of the algorithm in order to track cases where the algorithm produces //! grows and shrinks endlessly property variant history: [] //! required elements - property Item container + property Item metrics property Item layouts property Item visibility - - onInAutoSizeAnimationChanged: { if (inAutoSizeAnimation) { animations.needBothAxis.addEvent(sizer); } else { animations.needBothAxis.removeEvent(sizer); } } onIsActiveChanged: clearHistory(); Connections { target: root onContainsOnlyPlasmaTasksChanged: sizer.updateIconSize(); onEditModeChanged: sizer.updateIconSize(); onMaxLengthChanged: { if (root.editMode) { sizer.updateIconSize(); } } } Connections { - target: container + target: metrics onProportionIconSizeChanged: { - if (container.proportionIconSize!==-1) { + if (metrics.proportionIconSize!==-1) { sizer.updateIconSize(); } } } Connections { target: latteView onWidthChanged:{ - if (root.isHorizontal && container.proportionIconSize!==-1) { + if (root.isHorizontal && metrics.proportionIconSize!==-1) { sizer.updateIconSize(); } } onHeightChanged:{ - if (root.isVertical && container.proportionIconSize!==-1) { + if (root.isVertical && metrics.proportionIconSize!==-1) { sizer.updateIconSize(); } } } //! Prediction History Functions function clearHistory() { history.length = 0; } function addPrediction(currentLength, prediction) { history.unshift({current: currentLength, predicted: prediction}); /* console.log(" -- PREDICTION ARRAY -- "); for(var i=0; i historyMaxSize) { history.splice(historyMinSize, history.length - historyMinSize); } } function producesEndlessLoop(currentLength, prediction) { if (history.length < 2) { return false; } if (history[1].current === currentLength && history[1].predicted === prediction) { //! the current prediction is the same like two steps before in prediction history if(history[0].current > history[0].predicted && history[1].current < history[1].predicted) { //! case2: the algorithm that is trying to SHRINK has already produced same results subsequently console.log(" AUTOMATIC ITEM SIZE PROTECTOR, :: ENDLESS AUTOMATIC SIZE LOOP DETECTED"); return true; } } return false; } function updateIconSize() { if ( !doubleCallAutomaticUpdateIconSize.running && !visibility.inTempHiding && ((visibility.normalState || root.editMode) - && (sizer.isActive || (!sizer.isActive && container.iconSize!==container.maxIconSize))) - && (container.iconSize===container.maxIconSize || container.iconSize === sizer.iconSize) ) { + && (sizer.isActive || (!sizer.isActive && metrics.iconSize!==metrics.maxIconSize))) + && (metrics.iconSize===metrics.maxIconSize || metrics.iconSize === sizer.iconSize) ) { //!doubler timer if (!doubleCallAutomaticUpdateIconSize.secondTimeCallApplied) { doubleCallAutomaticUpdateIconSize.start(); } else { doubleCallAutomaticUpdateIconSize.secondTimeCallApplied = false; } var layoutLength; var maxLength = root.maxLength; //console.log("------Entered check-----"); //console.log("max length: "+ maxLength); if (root.isVertical) { layoutLength = (plasmoid.configuration.alignment === LatteCore.Types.Justify) ? layouts.startLayout.height+layouts.mainLayout.height+layouts.endLayout.height : layouts.mainLayout.height } else { layoutLength = (plasmoid.configuration.alignment === LatteCore.Types.Justify) ? layouts.startLayout.width+layouts.mainLayout.width+layouts.endLayout.width : layouts.mainLayout.width } - var itemLength = container.iconSize + lengthMargins; + var itemLength = metrics.iconSize + lengthMargins; var toShrinkLimit = maxLength - (root.zoomFactor * itemLength); //! to grow limit must be a little less than the shrink one in order to be more robust and //! not create endless loops from early calculations var toGrowLimit = maxLength - (1.2 * root.zoomFactor * itemLength); //console.log("toShrinkLimit: "+ toShrinkLimit); //console.log("toGrowLimit: "+ toGrowLimit); var newIconSizeFound = false; if (layoutLength > toShrinkLimit) { //must shrink // console.log("step3"); - var nextIconSize = container.maxIconSize; + var nextIconSize = metrics.maxIconSize; do { nextIconSize = nextIconSize - automaticStep; - var factor = nextIconSize / container.iconSize; + var factor = nextIconSize / metrics.iconSize; var nextLength = factor * layoutLength; } while ( (nextLength>toShrinkLimit) && (nextIconSize !== 16)); var intLength = Math.round(layoutLength); var intNextLength = Math.round(nextLength); iconSize = nextIconSize; newIconSizeFound = true; addPrediction(intLength, intNextLength); // console.log("Step 3 - found:"+iconSize); } else if ((layoutLength 0 && !producesEndlessLoop(intLength2, intNextLength2)) { - if (foundGoodSize === container.maxIconSize) { + if (foundGoodSize === metrics.maxIconSize) { iconSize = -1; } else { iconSize = foundGoodSize; } newIconSizeFound = true addPrediction(intLength2, intNextLength2); // console.log("Step 4 - found:"+iconSize); } else { // console.log("Step 4 - did not found..."); } } } } //! This functions makes sure to call the updateIconSize(); function which is costly //! one more time after its last call to confirm the applied icon size found Timer{ id:doubleCallAutomaticUpdateIconSize interval: 1000 property bool secondTimeCallApplied: false onTriggered: { if (!secondTimeCallApplied) { secondTimeCallApplied = true; sizer.updateIconSize(); } } } } diff --git a/containment/package/contents/ui/abilities/Container.qml b/containment/package/contents/ui/abilities/Metrics.qml similarity index 94% rename from containment/package/contents/ui/abilities/Container.qml rename to containment/package/contents/ui/abilities/Metrics.qml index c10e0bca..4a475272 100644 --- a/containment/package/contents/ui/abilities/Container.qml +++ b/containment/package/contents/ui/abilities/Metrics.qml @@ -1,63 +1,63 @@ /* * 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 . */ import QtQuick 2.7 import org.kde.plasma.plasmoid 2.0 import org.kde.latte.abilities.containers 0.1 as ContainerAbility -ContainerAbility.Container { - id: privateContainer +ContainerAbility.Metrics { + id: mets property Item animations: null property Item autosize: null //! Signals signal iconSizeAnimationEnded(); //! Public Properties iconSize: autosizeEnabled && autosize.iconSize > 0 ? Math.min(autosize.iconSize, maxIconSize) : maxIconSize maxIconSize: proportionIconSize!==-1 ? proportionIconSize : plasmoid.configuration.iconSize //! Private Properties readonly property int proportionIconSize: { //icon size based on screen height if ((plasmoid.configuration.proportionIconSize===-1) || !latteView) return -1; return Math.max(16,Math.round(latteView.screenGeometry.height * plasmoid.configuration.proportionIconSize/100/8)*8); } readonly property bool autosizeEnabled: autosize !== undefined && autosize.isActive //! Behaviors Behavior on iconSize { enabled: !(root.editMode && root.behaveAsPlasmaPanel) NumberAnimation { duration: 0.8 * animations.duration.proposed onRunningChanged: { if (!running) { - privateContainer.iconSizeAnimationEnded(); + mets.iconSizeAnimationEnded(); } } } } } diff --git a/containment/package/contents/ui/applet/AppletItem.qml b/containment/package/contents/ui/applet/AppletItem.qml index 6e7a9a0f..5170b26a 100644 --- a/containment/package/contents/ui/applet/AppletItem.qml +++ b/containment/package/contents/ui/applet/AppletItem.qml @@ -1,1195 +1,1195 @@ /* * Copyright 2016 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 . */ import QtQuick 2.7 import QtQuick.Layouts 1.1 import QtGraphicalEffects 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.components 1.0 as LatteComponents import "colorizer" as Colorizer import "communicator" as Communicator import "indicator" as Indicator Item { id: appletItem visible: false width: isInternalViewSplitter && !root.inConfigureAppletsMode ? 0 : computeWidth height: isInternalViewSplitter && !root.inConfigureAppletsMode ? 0 : computeHeight signal mousePressed(int x, int y, int button); signal mouseReleased(int x, int y, int button); property bool animationsEnabled: true property bool canBeHovered: true property bool canShowAppletNumberBadge: !isSeparator && !isHidden && !isLattePlasmoid && !isSpacer && !isInternalViewSplitter property bool inFillCalculations: false //temp record, is used in calculations for fillWidth,fillHeight applets property bool needsFillSpace: { //fill flag, it is used in calculations for fillWidth,fillHeight applets if (!applet || !applet.Layout) return false; if (((root.isHorizontal && applet.Layout.fillWidth===true) || (root.isVertical && applet.Layout.fillHeight===true)) && (applet.status !== PlasmaCore.Types.HiddenStatus)) return true; else return false; } property bool userBlocksColorizing: false property bool appletBlocksColorizing: !communicator.requires.latteSideColoringEnabled property bool appletBlocksParabolicEffect: communicator.requires.parabolicEffectLocked property bool lockZoom: false property bool isActive: (isExpanded && applet.pluginName !== root.plasmoidName && applet.pluginName !== "org.kde.activeWindowControl" && applet.pluginName !== "org.kde.plasma.appmenu") property bool isExpanded: false property bool isHidden: applet && applet.status === PlasmaCore.Types.HiddenStatus ? true : false property bool isInternalViewSplitter: (internalSplitterId > 0) property bool isLattePlasmoid: latteApplet !== null property bool isZoomed: false property bool isSeparator: applet && (applet.pluginName === "audoban.applet.separator" || applet.pluginName === "org.kde.latte.separator") property bool isSpacer: applet && (applet.pluginName === "org.kde.latte.spacer") property bool isSystray: applet && (applet.pluginName === "org.kde.plasma.systemtray" || applet.pluginName === "org.nomad.systemtray" ) property bool firstChildOfStartLayout: index === layoutsContainer.startLayout.firstVisibleIndex property bool firstChildOfMainLayout: index === layoutsContainer.mainLayout.firstVisibleIndex property bool lastChildOfMainLayout: index === layoutsContainer.mainLayout.lastVisibleIndex property bool lastChildOfEndLayout: index === layoutsContainer.endLayout.lastVisibleIndex readonly property bool atScreenEdge: { if (root.panelAlignment !== LatteCore.Types.Justify || root.inConfigureAppletsMode || plasmoid.configuration.offset!==0) { return false; } if (root.panelAlignment === LatteCore.Types.Justify) { //! Justify case if (root.maxLengthPerCentage!==100) { return false; } if (root.isHorizontal) { if (firstChildOfStartLayout) { return latteView && latteView.x === latteView.screenGeometry.x; } else if (lastChildOfEndLayout) { return latteView && ((latteView.x + latteView.width) === (latteView.screenGeometry.x + latteView.screenGeometry.width)); } } else { if (firstChildOfStartLayout) { return latteView && latteView.y === latteView.screenGeometry.y; } else if (lastChildOfEndLayout) { return latteView && ((latteView.y + latteView.height) === (latteView.screenGeometry.y + latteView.screenGeometry.height)); } } return false; } //! [disabled] because it is probably not needed at all. If in the future there is a report //! describing a case that this would be useful this disablement choice can be rethought /*if (root.panelAlignment === LatteCore.Types.Left) { //! Left case return firstChildOfMainLayout; } else if (root.panelAlignment === LatteCore.Types.Right) { //! Right case return lastChildOfMainLayout } if (root.panelAlignment === LatteCore.Types.Top) { return firstChildOfMainLayout && latteView && latteView.y === latteView.screenGeometry.y; } else if (root.panelAlignment === LatteCore.Types.Bottom) { return lastChildOfMainLayout && latteView && ((latteView.y + latteView.height) === (latteView.screenGeometry.y + latteView.screenGeometry.height)); }*/ return false; } //applet is in starting edge property bool firstAppletInContainer: (index >=0) && ((index === layoutsContainer.startLayout.firstVisibleIndex) || (index === layoutsContainer.mainLayout.firstVisibleIndex) || (index === layoutsContainer.endLayout.firstVisibleIndex)) //applet is in ending edge property bool lastAppletInContainer: (index >=0) && ((index === layoutsContainer.startLayout.lastVisibleIndex) || (index === layoutsContainer.mainLayout.lastVisibleIndex) || (index === layoutsContainer.endLayout.lastVisibleIndex)) readonly property bool acceptMouseEvents: applet && !isLattePlasmoid && !originalAppletBehavior && !appletItem.isSeparator && !communicator.requires.parabolicEffectLocked readonly property bool originalAppletBehavior: (root.zoomFactor === 1 && !lockZoom /*hacky flag to keep Latte behavior*/) || (root.zoomFactor>1 && !canBeHovered) || (root.zoomFactor>1 && canBeHovered && lockZoom) readonly property bool isSquare: communicator.overlayLatteIconIsActive readonly property bool screenEdgeMarginSupported: communicator.requires.screenEdgeMarginSupported property int animationTime: appletItem.animations.speedFactor.normal * (1.2*appletItem.animations.duration.small) property int hoveredIndex: layoutsContainer.hoveredIndex property int index: -1 property int maxWidth: root.isHorizontal ? root.height : root.width property int maxHeight: root.isHorizontal ? root.height : root.width property int internalSplitterId: 0 property int previousIndex: -1 property int sizeForFill: -1 //it is used in calculations for fillWidth,fillHeight applets - property int spacersMaxSize: Math.max(0,Math.ceil(0.55 * container.iconSize) - root.lengthMargins) + property int spacersMaxSize: Math.max(0,Math.ceil(0.55 * metrics.iconSize) - root.lengthMargins) property int status: applet ? applet.status : -1 //! local margins readonly property bool parabolicEffectMarginsEnabled: root.zoomFactor>1 && !originalAppletBehavior property int lengthAppletIntMargin: root.lengthAppletIntMarginFactor === -1 || parabolicEffectMarginsEnabled ? - root.lengthIntMargin : root.lengthAppletIntMarginFactor * container.iconSize + root.lengthIntMargin : root.lengthAppletIntMarginFactor * metrics.iconSize property int lengthAppletFullMargin: lengthAppletIntMargin + root.lengthExtMargin property int lengthAppletFullMargins: 2 * lengthAppletFullMargin property int internalWidthMargins: { if (root.isVertical) { return root.thickMargins; } /*TODO, Fitt's case: is temporary until the atScreenEdge applets are aligned properly to the corner and the wrapper is taking all the space needed in order to fill right. For atScreenEdge appplets that should be: applet size + lengthAppletIntMargin + lengthAppletExtMargin. The indicator should follow also the applet alignment in this in order to feel right */ return 2 * lengthAppletIntMargin; } property int internalHeightMargins: { if (root.isHorizontal) { return root.thickMargins; } /*TODO,Fitt's case: is temporary until the atScreenEdge applets are aligned properly to the corner and the wrapper is taking all the space needed in order to fill right. For atScreenEdge appplets that should be: applet size + lengthAppletIntMargin + lengthAppletExtMargin. The indicator should follow also the applet alignment in this in order to feel right */ return 2 * lengthAppletIntMargin; } //! are set by the indicator property int iconOffsetX: 0 property int iconOffsetY: 0 property real computeWidth: root.isVertical ? wrapper.width : hiddenSpacerLeft.width+wrapper.width+hiddenSpacerRight.width property real computeHeight: root.isVertical ? hiddenSpacerLeft.height + wrapper.height + hiddenSpacerRight.height : wrapper.height property string title: isInternalViewSplitter ? "Now Dock Splitter" : "" property Item applet: null property Item latteApplet: applet && (applet.pluginName === root.plasmoidName) ? (applet.children[0] ? applet.children[0] : null) : null property Item latteStyleApplet: applet && ((applet.pluginName === "org.kde.latte.spacer") || (applet.pluginName === "org.kde.latte.separator")) ? (applet.children[0] ? applet.children[0] : null) : null property Item appletWrapper: applet && (applet.pluginName === root.plasmoidName )? wrapper : wrapper.wrapperContainer property Item tooltipVisualParent: titleTooltipParent property Item communicatorAlias: communicator property Item wrapperAlias: wrapper property Item animations: null property Item appletsRecords: null - property Item container: null + property Item metrics: null property bool containsMouse: appletMouseArea.containsMouse /*|| appletMouseAreaBottom.containsMouse*/ property bool pressed: viewSignalsConnector.pressed || clickedAnimation.running //// BEGIN :: Animate Applet when a new applet is dragged in the view //when the applet moves caused by its resize, don't animate. //this is completely heuristic, but looks way less "jumpy" property bool movingForResize: false property int oldX: x property int oldY: y onXChanged: { if (!foreDropArea.visible || movingForResize || !root.dragInfo.entered) { movingForResize = false; return; } if (!root.isVertical) { translation.x = oldX - x; translation.y = 0; } else { translation.y = oldY - y; translation.x = 0; } translAnim.running = true if (!root.isVertical) { oldX = x; oldY = 0; } else { oldY = y; oldX = 0; } } onYChanged: { if (!foreDropArea.visible || movingForResize || !root.dragInfo.entered) { movingForResize = false; return; } if (!root.isVertical) { translation.x = oldX - x; translation.y = 0; } else { translation.y = oldY - y; translation.x = 0; } translAnim.running = true; if (!root.isVertical) { oldX = x; oldY = 0; } else { oldY = y; oldX = 0; } } transform: Translate { id: translation } NumberAnimation { id: translAnim duration: appletItem.animations.duration.large easing.type: Easing.InOutQuad target: translation properties: "x,y" to: 0 } Behavior on lengthAppletIntMargin { NumberAnimation { duration: 0.8 * appletItem.animations.duration.proposed easing.type: Easing.OutCubic } } //// END :: Animate Applet when a new applet is dragged in the view /// BEGIN functions function activateAppletForNeutralAreas(mouse){ //if the event is at the active indicator or spacers area then try to expand the applet, //unfortunately for other applets there is no other way to activate them yet //for example the icon-only applets var choords = mapToItem(appletItem.appletWrapper, mouse.x, mouse.y); var wrapperContainsMouse = choords.x>=0 && choords.y>=0 && choords.x=0 && mouse.y>=0 && mouse.x0); var appletNeutralAreaEnabled = !(inThicknessNeutralArea && root.dragActiveWindowEnabled); if (appletItemContainsMouse && !wrapperContainsMouse && appletNeutralAreaEnabled) { //console.log("PASSED"); latteView.extendedInterface.toggleAppletExpanded(applet.id); } else { //console.log("REJECTED"); } } function checkIndex(){ index = -1; for(var i=0; i maxSize || applet.Layout.minimumWidth > maxForMinimumSize)) || (applet && root.isVertical && (applet.height > maxSize || applet.Layout.minimumHeight > maxForMinimumSize))) && !appletItem.isSpacer && !communicator.canShowOverlaiedLatteIcon) ) { appletItem.canBeHovered = false; } else { appletItem.canBeHovered = true; } } } function slotDestroyInternalViewSplitters() { if (isInternalViewSplitter) { destroy(); } } //! pos in global root positioning function containsPos(pos) { var relPos = root.mapToItem(appletItem,pos.x, pos.y); if (relPos.x>=0 && relPos.x<=width && relPos.y>=0 && relPos.y<=height) return true; return false; } function refersEntryIndex(entryIndex) { return (entryIndex === parabolicManager.pseudoAppletIndex(appletItem.index)); } ///END functions //BEGIN connections onAppletChanged: { if (!applet) { destroy(); } } onIndexChanged: { if (appletItem.latteApplet) { root.latteAppletPos = index; } if (isHidden) { parabolicManager.setHidden(previousIndex, index); } if (isSeparator) { parabolicManager.setSeparator(previousIndex, index); } if (index>-1) { previousIndex = index; } } onIsExpandedChanged: { if (isExpanded) { root.hideTooltipLabel(); } } onIsHiddenChanged: { if (isHidden) { parabolicManager.setHidden(-1, index); } else { parabolicManager.setHidden(index, -1); } } onIsSeparatorChanged: { if (isSeparator) { parabolicManager.setSeparator(-1, index); } else { parabolicManager.setSeparator(index, -1); } } onIsSystrayChanged: { checkCanBeHovered(); } onLatteAppletChanged: { if(appletItem.latteApplet){ root.latteApplet = appletItem.latteApplet; root.latteAppletContainer = appletItem; root.latteAppletPos = index; appletItem.latteApplet.latteView = root; appletItem.latteApplet.forceHidePanel = true; appletItem.latteApplet.signalPreviewsShown.connect(slotPreviewsShown); appletItem.latteApplet.clearZoomSignal.connect(titleTooltipDialog.hide); } } onNeedsFillSpaceChanged: checkCanBeHovered(); Component.onCompleted: { checkIndex(); root.updateIndexes.connect(checkIndex); root.clearZoomSignal.connect(clearZoom); root.destroyInternalViewSplitters.connect(slotDestroyInternalViewSplitters); } Component.onDestruction: { appletItem.animations.needBothAxis.removeEvent(appletItem); appletItem.appletsRecords.removeApplet(appletItem); if (isSeparator){ parabolicManager.setSeparator(previousIndex, -1); } if (isHidden) { parabolicManager.setHidden(previousIndex, -1); } if(root.latteAppletPos>=0 && root.latteAppletPos === index){ root.latteApplet = null; root.latteAppletContainer = null; root.latteAppletPos = -1; } root.updateIndexes.disconnect(checkIndex); root.clearZoomSignal.disconnect(clearZoom); root.destroyInternalViewSplitters.disconnect(slotDestroyInternalViewSplitters); if (appletItem.latteApplet) { appletItem.latteApplet.signalPreviewsShown.disconnect(slotPreviewsShown); appletItem.latteApplet.clearZoomSignal.disconnect(titleTooltipDialog.hide); } } Connections{ target: root /* onGlobalDirectRenderChanged:{ if (root.globalDirectRender && restoreAnimation.running) { // console.log("CLEAR APPLET SCALE !!!!"); //restoreAnimation.stop(); //wrapper.zoomScale = 1; } }*/ onLatteAppletHoveredIndexChanged: { if ( (root.zoomFactor>1) && (root.latteAppletHoveredIndex >= 0) ){ var distance = 2; //for Tasks plasmoid distance of 2 is not always safe there are //cases that needs to be 3, when an internal separator there is //between the hovered task and the current applet if (root.hasInternalSeparator) { if (index < root.latteAppletPos) { var firstTaskIndex = root.latteApplet.parabolicManager.availableHigherIndex(0); distance = firstTaskIndex+2; } else if (index > root.latteAppletPos) { var lastTaskIndex = root.latteApplet.parabolicManager.availableLowerIndex(root.tasksCount-1); distance = root.tasksCount-1-lastTaskIndex+2; } } if(Math.abs(index-root.latteAppletPos+root.latteAppletHoveredIndex)>=Math.max(2,distance)) { appletItem.clearZoom(); } } } onSignalActivateEntryAtIndex: { if (parabolicManager.pseudoIndexBelongsToLatteApplet(entryIndex) && appletItem.isLattePlasmoid) { latteApplet.activateTaskAtIndex(entryIndex - latteApplet.tasksBaseIndex); } else if (root.unifiedGlobalShortcuts && refersEntryIndex(entryIndex)) { latteView.extendedInterface.toggleAppletExpanded(applet.id); } } onSignalNewInstanceForEntryAtIndex: { if (parabolicManager.pseudoIndexBelongsToLatteApplet(entryIndex) && appletItem.isLattePlasmoid) { latteApplet.newInstanceForTaskAtIndex(entryIndex - latteApplet.tasksBaseIndex); } else if (root.unifiedGlobalShortcuts && refersEntryIndex(entryIndex)) { latteView.extendedInterface.toggleAppletExpanded(applet.id); } } } Connections{ target: layoutsContainer onHoveredIndexChanged:{ //for applets it is safe to consider that a distance of 2 //is enough to clearZoom if ( (root.zoomFactor>1) && (layoutsContainer.hoveredIndex>=0) && (Math.abs(index-layoutsContainer.hoveredIndex)>=2)) appletItem.clearZoom(); if ((restoreAnimation.running) && (layoutsContainer.hoveredIndex !== -1)) { restoreAnimation.stop(); } } } Connections{ target: root onLatteAppletHoveredIndexChanged: { if ((restoreAnimation.running) && (root.latteAppletHoveredIndex !== -1)) { restoreAnimation.stop(); } } } Connections { id: viewSignalsConnector target: root.latteView ? root.latteView : null enabled: !appletItem.isLattePlasmoid && !appletItem.isSeparator && !appletItem.isSpacer && !appletItem.isHidden property bool pressed: false property bool blockWheel: false onMousePressed: { if (appletItem.containsPos(pos)) { viewSignalsConnector.pressed = true; var local = appletItem.mapFromItem(root, pos.x, pos.y); appletItem.mousePressed(local.x, local.y, button); if (button === Qt.LeftButton) { appletItem.activateAppletForNeutralAreas(local); } } } onMouseReleased: { if (appletItem.containsPos(pos)) { viewSignalsConnector.pressed = false; var local = appletItem.mapFromItem(root, pos.x, pos.y); appletItem.mouseReleased(local.x, local.y, button); } } onWheelScrolled: { if (!appletItem.applet || !root.mouseWheelActions || viewSignalsConnector.blockWheel || (root.latteViewIsHidden || root.inSlidingIn || root.inSlidingOut)) { return; } blockWheel = true; scrollDelayer.start(); if (appletItem.containsPos(pos) && root.latteView.extendedInterface.appletIsExpandable(applet.id)) { var angle = angleDelta.y / 8; var expanded = root.latteView.extendedInterface.appletIsExpanded(applet.id); if ((angle > 12 && !expanded) /*positive direction*/ || (angle < -12 && expanded) /*negative direction*/) { latteView.extendedInterface.toggleAppletExpanded(applet.id); } } } } Connections { target: root.latteView ? root.latteView.extendedInterface : null enabled: !appletItem.isLattePlasmoid && !appletItem.isSeparator && !appletItem.isSpacer && !appletItem.isHidden onExpandedAppletStateChanged: { if (latteView.extendedInterface.hasExpandedApplet && appletItem.applet) { appletItem.isExpanded = latteView.extendedInterface.appletIsExpandable(appletItem.applet.id) && latteView.extendedInterface.appletIsExpanded(appletItem.applet.id); } else { appletItem.isExpanded = false; } } } ///END connections //! It is used for any communication needed with the underlying applet Communicator.Engine{ id: communicator //set up the overlayed appletItems and properties for when a overlaiedIconItem must be presented to the user //because the plasma widgets specific implementation breaks the Latte experience onOverlayLatteIconIsActiveChanged:{ if (!overlayLatteIconIsActive && applet.opacity===0) { applet.opacity = 1; wrapper.disableScaleWidth = false; wrapper.disableScaleHeight = false; wrapper.updateLayoutWidth(); wrapper.updateLayoutHeight(); } else if (overlayLatteIconIsActive && applet.opacity>0) { applet.opacity = 0; if (applet.pluginName === "org.kde.plasma.folder") { applet.parent = wrapper.containerForOverlayIcon; applet.anchors.fill = wrapper.containerForOverlayIcon; } wrapper.disableScaleWidth = false; wrapper.disableScaleHeight = false; wrapper.updateLayoutWidth(); wrapper.updateLayoutHeight(); } } } /* Rectangle{ anchors.fill: parent color: "transparent" border.color: "green" border.width: 1 }*/ /* DEPRECATED in favor of VIEW::MouseSignalsTracking MouseArea{ id: appletMouseAreaBottom anchors.fill: parent propagateComposedEvents: true visible: (!appletMouseArea.visible || !appletMouseArea.enabled) && !root.editMode && !originalAppletBehavior onPressed: { appletItem.activateAppletForNeutralAreas(mouse); mouse.accepted = false; } onReleased: { mouse.accepted = false; } }*/ //! Main Applet Shown Area Flow{ id: appletFlow width: appletItem.computeWidth height: appletItem.computeHeight // a hidden spacer for the first element to add stability // IMPORTANT: hidden spacers must be tested on vertical !!! HiddenSpacer{id: hiddenSpacerLeft} Item { width: wrapper.width height: wrapper.height Indicator.Bridge{ id: indicatorBridge } //! Indicator Back Layer Indicator.Loader{ id: indicatorBackLayer level: Indicator.LevelOptions { id: backLevelOptions isBackground: true bridge: indicatorBridge Binding { target: appletItem property: "iconOffsetX" value: backLevelOptions.requested.iconOffsetX } Binding { target: appletItem property: "iconOffsetY" value: backLevelOptions.requested.iconOffsetY } } } ItemWrapper{ id: wrapper TitleTooltipParent{ id: titleTooltipParent - container: appletItem.container + metrics: appletItem.metrics } } //! The Applet Colorizer Colorizer.Applet { id: appletColorizer anchors.fill: parent opacity: mustBeShown ? 1 : 0 readonly property bool mustBeShown: colorizerManager.mustBeShown && !appletItem.userBlocksColorizing && !appletItem.appletBlocksColorizing && !appletItem.isInternalViewSplitter Behavior on opacity { NumberAnimation { duration: 1.2 * appletItem.animations.duration.proposed easing.type: Easing.OutCubic } } } //! Indicator Front Layer Indicator.Loader{ id: indicatorFrontLayer level: Indicator.LevelOptions { isForeground: true bridge: indicatorBridge } } //! Applet Shortcut Visual Badge Item { id: shortcutBadgeContainer width: { if (root.isHorizontal) { - return appletItem.container.iconSize * wrapper.zoomScale + return appletItem.metrics.iconSize * wrapper.zoomScale } else { return badgeThickness; } } height: { if (root.isHorizontal) { return badgeThickness; } else { - return appletItem.container.iconSize * wrapper.zoomScale + return appletItem.metrics.iconSize * wrapper.zoomScale } } readonly property int badgeThickness: { if (plasmoid.location === PlasmaCore.Types.BottomEdge || plasmoid.location === PlasmaCore.Types.RightEdge) { - return ((appletItem.container.iconSize + root.thickMargin) * wrapper.zoomScale) + root.localScreenEdgeMargin; + return ((appletItem.metrics.iconSize + root.thickMargin) * wrapper.zoomScale) + root.localScreenEdgeMargin; } - return ((appletItem.container.iconSize + root.thickMargin) * wrapper.zoomScale); + return ((appletItem.metrics.iconSize + root.thickMargin) * wrapper.zoomScale); } ShortcutBadge{ anchors.fill: parent } states:[ State{ name: "horizontal" when: plasmoid.formFactor === PlasmaCore.Types.Horizontal AnchorChanges{ target: shortcutBadgeContainer; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } }, State{ name: "vertical" when: plasmoid.formFactor === PlasmaCore.Types.Vertical AnchorChanges{ target: shortcutBadgeContainer; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } } ] } } // a hidden spacer on the right for the last item to add stability HiddenSpacer{id: hiddenSpacerRight; rightSpacer: true} }// Flow with hidden spacers inside //Busy Indicator PlasmaComponents.BusyIndicator { z: 1000 visible: applet && applet.busy running: visible anchors.centerIn: parent width: Math.min(parent.width, parent.height) height: width } Loader { id: addingAreaLoader width: root.isHorizontal ? parent.width : parent.width - root.localScreenEdgeMargin height: root.isHorizontal ? parent.height - root.localScreenEdgeMargin : parent.height active: isLattePlasmoid sourceComponent: LatteComponents.AddingArea{ id: addingAreaItem anchors.fill: parent // width: root.isHorizontal ? parent.width : parent.width - root.localScreenEdgeMargin // height: root.isHorizontal ? parent.height - root.localScreenEdgeMargin : parent.height - radius: appletItem.container.iconSize/10 + radius: appletItem.metrics.iconSize/10 opacity: root.addLaunchersMessage ? 1 : 0 backgroundOpacity: 0.75 duration: appletItem.animations.speedFactor.current title: i18n("Tasks Area") } //! AddingAreaItem States states:[ State{ name: "bottom" when: plasmoid.location === PlasmaCore.Types.BottomEdge AnchorChanges{ target: addingAreaLoader anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } PropertyChanges{ target: addingAreaLoader anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: root.localScreenEdgeMargin; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "top" when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges{ target: addingAreaLoader anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; } PropertyChanges{ target: addingAreaLoader anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin: root.localScreenEdgeMargin; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "left" when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges{ target: addingAreaLoader anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: addingAreaLoader anchors.leftMargin: root.localScreenEdgeMargin; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "right" when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges{ target: addingAreaLoader anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: addingAreaLoader anchors.leftMargin: 0; anchors.rightMargin: root.localScreenEdgeMargin; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] } MouseArea{ id: appletMouseArea anchors.fill: parent enabled: visible hoverEnabled: latteApplet ? false : true propagateComposedEvents: true //! a way must be found in order for this be enabled //! only to support springloading for plasma 5.10 //! also on this is based the tooltips behavior by enabling it //! plasma tooltips are disabled visible: acceptMouseEvents property bool blockWheel: false onEntered: { if (containsMouse && !originalAppletBehavior && !communicator.requires.parabolicEffectLocked && appletItem.canBeHovered){ root.stopCheckRestoreZoomTimer(); } if (restoreAnimation.running) { restoreAnimation.stop(); } if (!(isSeparator || isSpacer)) { root.showTooltipLabel(appletItem, applet.title); } //console.log("entered applet:" + layoutsContainer.hoveredIndex); if (layoutsContainer.hoveredIndex === -1 && root.latteAppletHoveredIndex===-1) { root.startDirectRenderDelayerDuringEntering(); } if (!(root.latteViewIsHidden || root.inSlidingIn || root.inSlidingOut)){ layoutsContainer.hoveredIndex = index; } if (originalAppletBehavior || communicator.requires.parabolicEffectLocked || !canBeHovered) { return; } if (root.isHalfShown || (root.latteApplet && (root.latteApplet.noTasksInAnimation>0 || root.latteApplet.contextMenu))) { return; } if (root.isHorizontal){ layoutsContainer.currentSpot = mouseX; wrapper.calculateScales(mouseX); } else{ layoutsContainer.currentSpot = mouseY; wrapper.calculateScales(mouseY); } } onExited:{ if (communicator.appletIconItemIsShown()) { communicator.setAppletIconItemActive(false); } root.hideTooltipLabel(); if (root.zoomFactor>1){ root.startCheckRestoreZoomTimer(); } } onPositionChanged: { if (originalAppletBehavior || !canBeHovered) { mouse.accepted = false; return; } if (root.isHalfShown || (root.latteApplet && (root.latteApplet.noTasksInAnimation>0 || root.latteApplet.contextMenu))) { return; } if (layoutsContainer.hoveredIndex === -1 && root.latteAppletHoveredIndex===-1) { root.startDirectRenderDelayerDuringEntering(); } if (!(root.latteViewIsHidden || root.inSlidingIn || root.inSlidingOut)){ layoutsContainer.hoveredIndex = index; } if (!root.globalDirectRender && !root.directRenderDelayerIsRunning) { root.setGlobalDirectRender(true); } if( ((wrapper.zoomScale == 1 || wrapper.zoomScale === root.zoomFactor) && !root.globalDirectRender) || root.globalDirectRender) { if (root.isHorizontal){ var step = Math.abs(layoutsContainer.currentSpot-mouse.x); if (step >= appletItem.animations.hoverPixelSensitivity){ layoutsContainer.currentSpot = mouse.x; wrapper.calculateScales(mouse.x); } } else{ var step = Math.abs(layoutsContainer.currentSpot-mouse.y); if (step >= appletItem.animations.hoverPixelSensitivity){ layoutsContainer.currentSpot = mouse.y; wrapper.calculateScales(mouse.y); } } } mouse.accepted = false; } //! these are needed in order for these events to be really forwarded underneath //! otherwise there were applets that did not receive them e.g. lock/logout applet //! when parabolic effect was used onPressed: mouse.accepted = false; onReleased: mouse.accepted = false; } //! A timer is needed in order to handle also touchpads that probably //! send too many signals very fast. This way the signals per sec are limited. //! The user needs to have a steady normal scroll in order to not //! notice a annoying delay Timer{ id: scrollDelayer interval: 500 onTriggered: viewSignalsConnector.blockWheel = false; } //BEGIN states states: [ State { name: "left" when: (plasmoid.location === PlasmaCore.Types.LeftEdge) AnchorChanges { target: appletFlow anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined;} } }, State { name: "right" when: (plasmoid.location === PlasmaCore.Types.RightEdge) AnchorChanges { target: appletFlow anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right;} } }, State { name: "bottom" when: (plasmoid.location === PlasmaCore.Types.BottomEdge) AnchorChanges { target: appletFlow anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined;} } }, State { name: "top" when: (plasmoid.location === PlasmaCore.Types.TopEdge) AnchorChanges { target: appletFlow anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined;} } } ] //END states //BEGIN animations ///////Restore Zoom Animation///// ParallelAnimation{ id: restoreAnimation PropertyAnimation { target: wrapper property: "zoomScale" to: 1 duration: 4 * appletItem.animationTime easing.type: Easing.InCubic } } /////Clicked Animation///// SequentialAnimation{ id: clickedAnimation alwaysRunToEnd: true running: appletItem.isSquare && !originalAppletBehavior && appletItem.pressed && (appletItem.animations.speedFactor.current > 0) && !indicators.info.providesClickedAnimation ParallelAnimation{ PropertyAnimation { target: wrapper.clickedEffect property: "brightness" to: -0.35 duration: appletItem.animations.duration.large easing.type: Easing.OutQuad } } ParallelAnimation{ PropertyAnimation { target: wrapper.clickedEffect property: "brightness" to: 0 duration: appletItem.animations.duration.large easing.type: Easing.OutQuad } } } //END animations } diff --git a/containment/package/contents/ui/applet/ItemWrapper.qml b/containment/package/contents/ui/applet/ItemWrapper.qml index 4cb22ade..38c31699 100644 --- a/containment/package/contents/ui/applet/ItemWrapper.qml +++ b/containment/package/contents/ui/applet/ItemWrapper.qml @@ -1,783 +1,783 @@ /* * Copyright 2016 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 . */ import QtQuick 2.1 import QtQuick.Layouts 1.1 import QtGraphicalEffects 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.latte.core 0.2 as LatteCore import "../../code/MathTools.js" as MathTools Item{ id: wrapper width: { if (appletItem.isInternalViewSplitter && !root.inConfigureAppletsMode) return 0; if (isSeparator && root.parabolicEffectEnabled && root.isHorizontal) { return -1; } //! width for applets that use fillWidth/fillHeight such plasma taskmanagers and AWC if (appletItem.needsFillSpace && root.isHorizontal) { if (root.panelAlignment !== LatteCore.Types.Justify) { var maximumValue = (applet.Layout.maximumWidth === Infinity) || applet.Layout.maximumWidth === -1 ? appletItem.sizeForFill : Math.min(appletItem.sizeForFill, applet.Layout.maximumWidth); var constrainedWidth = MathTools.bound(applet.Layout.minimumWidth, applet.Layout.preferredWidth, maximumValue); - return root.inConfigureAppletsMode ? Math.max(constrainedWidth, appletItem.container.iconSize) : constrainedWidth; + return root.inConfigureAppletsMode ? Math.max(constrainedWidth, appletItem.metrics.iconSize) : constrainedWidth; } if(appletItem.sizeForFill>-1){ return appletItem.sizeForFill; } } if (appletItem.latteApplet) { return latteApplet.tasksWidth; } else { if (root.isHorizontal && root.inConfigureAppletsMode) { - return Math.max(Math.min(appletItem.container.iconSize, root.minAppletLengthInConfigure), scaledWidth); + return Math.max(Math.min(appletItem.metrics.iconSize, root.minAppletLengthInConfigure), scaledWidth); } return root.isVertical ? scaledWidth + root.localScreenEdgeMargin : scaledWidth; } } height: { if (appletItem.isInternalViewSplitter && !root.inConfigureAppletsMode) return 0; if (isSeparator && root.parabolicEffectEnabled && root.isVertical) { return -1; } //! height for applets that use fillWidth/fillHeight such plasma taskmanagers and AWC if (appletItem.needsFillSpace && root.isVertical) { if (root.panelAlignment !== LatteCore.Types.Justify) { var maximumValue = (applet.Layout.maximumHeight === Infinity) || applet.Layout.maximumHeight === -1 ? appletItem.sizeForFill : Math.min(appletItem.sizeForFill, applet.Layout.maximumHeight); var constrainedHeight = MathTools.bound(applet.Layout.minimumHeight, applet.Layout.preferredHeight, maximumValue); - return root.inConfigureAppletsMode ? Math.max(constrainedHeight, appletItem.container.iconSize) : constrainedHeight; + return root.inConfigureAppletsMode ? Math.max(constrainedHeight, appletItem.metrics.iconSize) : constrainedHeight; } if (appletItem.sizeForFill>-1){ return appletItem.sizeForFill; } } if (appletItem.latteApplet) { return latteApplet.tasksHeight; } else { if (root.isVertical && root.inConfigureAppletsMode) { - return Math.max(Math.min(appletItem.container.iconSize, root.minAppletLengthInConfigure), scaledHeight); + return Math.max(Math.min(appletItem.metrics.iconSize, root.minAppletLengthInConfigure), scaledHeight); } return root.isHorizontal ? scaledHeight + root.localScreenEdgeMargin : scaledHeight; } } opacity: appletColorizer.mustBeShown && graphicsSystem.isAccelerated ? 0 : 1 property bool disableScaleWidth: false property bool disableScaleHeight: false property bool editMode: root.inConfigureAppletsMode property bool edgeLengthMarginsDisabled: isSeparator || !communicator.requires.lengthMarginsEnabled || !canBeHovered property int appletWidth: applet ? applet.width : -1 property int appletHeight: applet ? applet.height : -1 property int appletMinimumWidth: applet && applet.Layout ? applet.Layout.minimumWidth : -1 property int appletMinimumHeight: applet && applet.Layout ? applet.Layout.minimumHeight : -1 property int appletPreferredWidth: applet && applet.Layout ? applet.Layout.preferredWidth : -1 property int appletPreferredHeight: applet && applet.Layout ? applet.Layout.preferredHeight : -1 property int appletMaximumWidth: applet && applet.Layout ? applet.Layout.maximumWidth : -1 property int appletMaximumHeight: applet && applet.Layout ? applet.Layout.maximumHeight : -1 - property int iconSize: appletItem.container.iconSize + property int iconSize: appletItem.metrics.iconSize property int marginWidth: root.isVertical ? root.thickMargins : (root.inFullJustify && atScreenEdge && !parabolicEffectMarginsEnabled ? edgeLengthMargins : localLengthMargins) //Fitt's Law property int marginHeight: root.isHorizontal ? root.thickMargins : (root.inFullJustify && atScreenEdge && !parabolicEffectMarginsEnabled ? edgeLengthMargins : localLengthMargins) //Fitt's Law property int localLengthMargins: isSeparator || !communicator.requires.lengthMarginsEnabled || isInternalViewSplitter ? 0 : appletItem.lengthAppletFullMargins property int edgeLengthMargins: edgeLengthMarginsDisabled ? 0 : appletItem.lengthAppletIntMargin * 2 property real scaledWidth: zoomScaleWidth * (layoutWidth + marginWidth) property real scaledHeight: zoomScaleHeight * (layoutHeight + marginHeight) property real zoomScaleWidth: disableScaleWidth ? 1 : zoomScale property real zoomScaleHeight: disableScaleHeight ? 1 : zoomScale property int layoutWidthResult: 0 property int layoutWidth property int layoutHeight property real center:root.isHorizontal ? (width + hiddenSpacerLeft.separatorSpace + hiddenSpacerRight.separatorSpace) / 2 : (height + hiddenSpacerLeft.separatorSpace + hiddenSpacerRight.separatorSpace) / 2 property real zoomScale: 1 property int index: appletItem.index property Item wrapperContainer: _wrapperContainer property Item clickedEffect: _clickedEffect property Item containerForOverlayIcon: _containerForOverlayIcon property Item overlayIconLoader: _overlayIconLoader Behavior on opacity { NumberAnimation { duration: 0.8 * appletItem.animations.duration.proposed easing.type: Easing.OutCubic } } // property int pHeight: applet ? applet.Layout.preferredHeight : -10 /*function debugLayouts(){ if(applet){ console.log("---------- "+ applet.pluginName +" ----------"); console.log("MinW "+applet.Layout.minimumWidth); console.log("PW "+applet.Layout.preferredWidth); console.log("MaxW "+applet.Layout.maximumWidth); console.log("FillW "+applet.Layout.fillWidth); console.log("-----"); console.log("MinH "+applet.Layout.minimumHeight); console.log("PH "+applet.Layout.preferredHeight); console.log("MaxH "+applet.Layout.maximumHeight); console.log("FillH "+applet.Layout.fillHeight); console.log("-----"); console.log("Real Applet Width: "+applet.width); console.log("Real Applet Height: "+applet.height); console.log("-----"); console.log("Real Wrapper Width: "+wrapper.width); console.log("Real Wrapper Height: "+wrapper.height); console.log("-----"); console.log("Can be hovered: " + canBeHovered); - console.log("Icon size: " + appletItem.container.iconSize); + console.log("Icon size: " + appletItem.metrics.iconSize); console.log("Thick Margins: " + root.thickMargins); console.log("Intern. Margins: " + (root.lengthIntMargin * 2)); console.log("Intern. Margins: " + (root.lengthExtMargin * 2)); - console.log("Max hovered criteria: " + (appletItem.container.iconSize + thickMargins)); + console.log("Max hovered criteria: " + (appletItem.metrics.iconSize + thickMargins)); console.log("-----"); console.log("LayoutW: " + layoutWidth); console.log("LayoutH: " + layoutHeight); } } onLayoutWidthChanged: { debugLayouts(); } onLayoutHeightChanged: { debugLayouts(); }*/ onAppletWidthChanged: { if(zoomScale === 1) { checkCanBeHovered(); } } onAppletHeightChanged: { if(zoomScale === 1) { checkCanBeHovered(); } } onAppletMinimumWidthChanged: { if(zoomScale === 1) { checkCanBeHovered(); } updateLayoutWidth(); } onAppletMinimumHeightChanged: { if(zoomScale === 1) { checkCanBeHovered(); } updateLayoutHeight(); } onAppletPreferredWidthChanged: updateLayoutWidth(); onAppletPreferredHeightChanged: updateLayoutHeight(); onAppletMaximumWidthChanged: updateLayoutWidth(); onAppletMaximumHeightChanged: updateLayoutHeight(); Connections { target: appletItem onCanBeHoveredChanged: { updateLayoutWidth(); updateLayoutHeight(); } } onIconSizeChanged: { updateLayoutWidth(); updateLayoutHeight(); } onEditModeChanged: { updateLayoutWidth(); updateLayoutHeight(); } onZoomScaleChanged: { if ((zoomScale === root.zoomFactor) && !root.globalDirectRender) { root.setGlobalDirectRender(true); } if ((zoomScale > 1) && !appletItem.isZoomed) { appletItem.isZoomed = true; appletItem.animations.needBothAxis.addEvent(appletItem); } else if (zoomScale == 1) { appletItem.isZoomed = false; appletItem.animations.needBothAxis.removeEvent(appletItem); } } Connections { target: root onIsVerticalChanged: { if (appletItem.latteApplet) { return; } wrapper.disableScaleWidth = false; wrapper.disableScaleHeight = false; if (root.isVertical) { wrapper.updateLayoutHeight(); wrapper.updateLayoutWidth(); } else { wrapper.updateLayoutWidth(); wrapper.updateLayoutHeight(); } } } function updateLayoutHeight(){ appletItem.movingForResize = true; if (appletItem.needsFillSpace && root.isVertical) { layoutsContainer.updateSizeForAppletsInFill(); return; } var blockParabolicEffect = false; if (isLattePlasmoid) { return; } else if (appletItem.isInternalViewSplitter){ if(!root.inConfigureAppletsMode) { layoutHeight = 0; } else { - layoutHeight = (root.isHorizontal ? appletItem.container.iconSize : Math.min(appletItem.container.iconSize, root.maxJustifySplitterSize)); + layoutHeight = (root.isHorizontal ? appletItem.metrics.iconSize : Math.min(appletItem.metrics.iconSize, root.maxJustifySplitterSize)); } } else if(appletItem.isSystray && root.isHorizontal){ - layoutHeight = appletItem.container.iconSize; + layoutHeight = appletItem.metrics.iconSize; } else{ - if(applet && (applet.Layout.minimumHeight > appletItem.container.iconSize) && root.isVertical && !canBeHovered && !communicator.overlayLatteIconIsActive){ + if(applet && (applet.Layout.minimumHeight > appletItem.metrics.iconSize) && root.isVertical && !canBeHovered && !communicator.overlayLatteIconIsActive){ blockParabolicEffect = true; layoutHeight = applet.Layout.minimumHeight; } //it is used for plasmoids that need to scale only one axis... e.g. the Weather Plasmoid else if(applet - && ( applet.Layout.maximumHeight < appletItem.container.iconSize - || applet.Layout.preferredHeight > appletItem.container.iconSize + && ( applet.Layout.maximumHeight < appletItem.metrics.iconSize + || applet.Layout.preferredHeight > appletItem.metrics.iconSize || appletItem.originalAppletBehavior) && root.isVertical && !disableScaleWidth && !communicator.overlayLatteIconIsActive) { //this way improves performance, probably because during animation the preferred sizes update a lot - if((applet.Layout.maximumHeight < appletItem.container.iconSize)){ + if((applet.Layout.maximumHeight < appletItem.metrics.iconSize)){ layoutHeight = applet.Layout.maximumHeight; - } else if (applet.Layout.minimumHeight > appletItem.container.iconSize){ + } else if (applet.Layout.minimumHeight > appletItem.metrics.iconSize){ blockParabolicEffect = true; layoutHeight = applet.Layout.minimumHeight; - } else if ((applet.Layout.preferredHeight > appletItem.container.iconSize) + } else if ((applet.Layout.preferredHeight > appletItem.metrics.iconSize) || (appletItem.originalAppletBehavior && applet.Layout.preferredHeight > 0 )){ blockParabolicEffect = true; layoutHeight = applet.Layout.preferredHeight; } else{ - layoutHeight = appletItem.container.iconSize; + layoutHeight = appletItem.metrics.iconSize; } } else { - layoutHeight = appletItem.container.iconSize; + layoutHeight = appletItem.metrics.iconSize; } } if (wrapper.zoomScale === 1) { if (blockParabolicEffect) { disableScaleHeight = true; } else { disableScaleHeight = false; } } } function updateLayoutWidth(){ appletItem.movingForResize = true; if (appletItem.needsFillSpace && root.isHorizontal) { layoutsContainer.updateSizeForAppletsInFill(); return; } var blockParabolicEffect = false; if (isLattePlasmoid) { return; } else if (appletItem.isInternalViewSplitter){ if(!root.inConfigureAppletsMode) { layoutWidth = 0; } else { - layoutWidth = (root.isVertical ? appletItem.container.iconSize : Math.min(appletItem.container.iconSize, root.maxJustifySplitterSize)); + layoutWidth = (root.isVertical ? appletItem.metrics.iconSize : Math.min(appletItem.metrics.iconSize, root.maxJustifySplitterSize)); } } else if(appletItem.isSystray && root.isVertical){ - layoutWidth = appletItem.container.iconSize; + layoutWidth = appletItem.metrics.iconSize; } else{ - if(applet && (applet.Layout.minimumWidth > appletItem.container.iconSize) && root.isHorizontal && !canBeHovered && !communicator.overlayLatteIconIsActive){ + if(applet && (applet.Layout.minimumWidth > appletItem.metrics.iconSize) && root.isHorizontal && !canBeHovered && !communicator.overlayLatteIconIsActive){ blockParabolicEffect = true; layoutWidth = applet.Layout.minimumWidth; } //it is used for plasmoids that need to scale only one axis... e.g. the Weather Plasmoid else if(applet - && ( applet.Layout.maximumWidth < appletItem.container.iconSize - || applet.Layout.preferredWidth > appletItem.container.iconSize + && ( applet.Layout.maximumWidth < appletItem.metrics.iconSize + || applet.Layout.preferredWidth > appletItem.metrics.iconSize || appletItem.originalAppletBehavior) && root.isHorizontal && !disableScaleHeight && !communicator.overlayLatteIconIsActive){ //this way improves performance, probably because during animation the preferred sizes update a lot - if((applet.Layout.maximumWidth < appletItem.container.iconSize)){ + if((applet.Layout.maximumWidth < appletItem.metrics.iconSize)){ // return applet.Layout.maximumWidth; layoutWidth = applet.Layout.maximumWidth; - } else if (applet.Layout.minimumWidth > appletItem.container.iconSize){ + } else if (applet.Layout.minimumWidth > appletItem.metrics.iconSize){ blockParabolicEffect = true; layoutWidth = applet.Layout.minimumWidth; - } else if ((applet.Layout.preferredWidth > appletItem.container.iconSize) + } else if ((applet.Layout.preferredWidth > appletItem.metrics.iconSize) || (appletItem.originalAppletBehavior && applet.Layout.preferredWidth > 0 )){ blockParabolicEffect = true; layoutWidth = applet.Layout.preferredWidth; } else{ - layoutWidth = appletItem.container.iconSize; + layoutWidth = appletItem.metrics.iconSize; } } else{ - layoutWidth = appletItem.container.iconSize; + layoutWidth = appletItem.metrics.iconSize; } } if (wrapper.zoomScale === 1) { if (blockParabolicEffect) { disableScaleWidth = true; } else { disableScaleWidth = false; } } } Item{ id:_wrapperContainer width:{ if (appletItem.needsFillSpace && (appletItem.sizeForFill>-1) && root.isHorizontal){ return wrapper.width; } if (appletItem.isInternalViewSplitter) { return wrapper.layoutWidth; } else { if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { - var wrapperContainerThickness = parent.zoomScaleWidth * (appletItem.container.iconSize + root.thickMargins); + var wrapperContainerThickness = parent.zoomScaleWidth * (appletItem.metrics.iconSize + root.thickMargins); return appletItem.screenEdgeMarginSupported ? wrapperContainerThickness + root.localScreenEdgeMargin : wrapperContainerThickness; } else { return parent.zoomScaleWidth * wrapper.layoutWidth; } } } height:{ if (appletItem.needsFillSpace && (appletItem.sizeForFill>-1) && root.isVertical){ return wrapper.height; } if (appletItem.isInternalViewSplitter) { return wrapper.layoutHeight; } else { if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) { - var wrapperContainerThickness = parent.zoomScaleHeight * (appletItem.container.iconSize + root.thickMargins); + var wrapperContainerThickness = parent.zoomScaleHeight * (appletItem.metrics.iconSize + root.thickMargins); return appletItem.screenEdgeMarginSupported ? wrapperContainerThickness + root.localScreenEdgeMargin : wrapperContainerThickness; } else { return parent.zoomScaleHeight * wrapper.layoutHeight; } } } opacity: appletShadow.active ? 0 : 1 readonly property int appliedEdgeMargin: { if (appletItem.isInternalViewSplitter) { return root.localScreenEdgeMargin + root.thickMargin; } return appletItem.screenEdgeMarginSupported ? 0 : root.localScreenEdgeMargin; } ///Secret MouseArea to be used by the folder widget Loader{ anchors.fill: parent active: communicator.overlayLatteIconIsActive && applet.pluginName === "org.kde.plasma.folder" && !appletItem.acceptMouseEvents sourceComponent: MouseArea{ onClicked: latteView.extendedInterface.toggleAppletExpanded(applet.id); } } Item{ id: _containerForOverlayIcon anchors.fill: parent } Loader{ id: _overlayIconLoader anchors.fill: parent active: communicator.overlayLatteIconIsActive property color backgroundColor: "black" property color glowColor: "white" sourceComponent: LatteCore.IconItem{ id: overlayIconItem anchors.fill: parent source: { if (communicator.appletIconItemIsShown()) return communicator.appletIconItem.source; else if (communicator.appletImageItemIsShown()) return communicator.appletImageItem.source; return ""; } providesColors: indicators.info.needsIconColors && source != "" usesPlasmaTheme: communicator.appletIconItemIsShown() ? communicator.appletIconItem.usesPlasmaTheme : false Binding{ target: _overlayIconLoader property: "backgroundColor" when: overlayIconItem.providesColors value: overlayIconItem.backgroundColor } Binding{ target: _overlayIconLoader property: "glowColor" when: overlayIconItem.providesColors value: overlayIconItem.glowColor } Loader{ anchors.centerIn: parent active: root.debugModeOverloadedIcons sourceComponent: Rectangle{ width: 30 height: 30 color: "green" opacity: 0.65 } } } } //! WrapperContainer States states:[ State{ name: "bottom" when: plasmoid.location === PlasmaCore.Types.BottomEdge AnchorChanges{ target: _wrapperContainer; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } PropertyChanges{ target: _wrapperContainer; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: _wrapperContainer.appliedEdgeMargin; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "top" when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges{ target:_wrapperContainer; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; } PropertyChanges{ target: _wrapperContainer; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin: _wrapperContainer.appliedEdgeMargin; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "left" when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges{ target: _wrapperContainer; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: _wrapperContainer; anchors.leftMargin: _wrapperContainer.appliedEdgeMargin; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "right" when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges{ target: _wrapperContainer; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: _wrapperContainer; anchors.leftMargin: 0; anchors.rightMargin: _wrapperContainer.appliedEdgeMargin; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] } Loader{ anchors.fill: _wrapperContainer active: appletItem.isInternalViewSplitter && root.inConfigureAppletsMode sourceComponent: Item { anchors.fill: parent PlasmaCore.SvgItem{ id:splitterImage anchors.centerIn: parent - width: Math.min(root.maxJustifySplitterSize, appletItem.container.iconSize) + width: Math.min(root.maxJustifySplitterSize, appletItem.metrics.iconSize) height: width rotation: root.isVertical ? 90 : 0 svg: PlasmaCore.Svg{ imagePath: root.universalSettings.splitterIconPath() } layer.enabled: graphicsSystem.isAccelerated layer.effect: DropShadow { radius: root.appShadowSize fast: true samples: 2 * radius color: root.appShadowColor verticalOffset: 2 } } } } ///Shadow in applets Loader{ id: appletShadow anchors.fill: appletItem.appletWrapper active: appletItem.applet && graphicsSystem.isAccelerated && !appletColorizer.mustBeShown && (root.enableShadows && applet.pluginName !== root.plasmoidName) onActiveChanged: { if (active && !isSeparator && graphicsSystem.isAccelerated) { wrapperContainer.opacity = 0; } else { wrapperContainer.opacity = 1; } } opacity: isSeparator ? 0.4 : 1 sourceComponent: DropShadow{ anchors.fill: parent color: root.appShadowColor //"#ff080808" fast: true samples: 2 * radius source: communicator.overlayLatteIconIsActive ? _wrapperContainer : appletItem.applet radius: shadowSize verticalOffset: root.forceTransparentPanel || root.forcePanelForBusyBackground ? 0 : 2 property int shadowSize : root.appShadowSize } } BrightnessContrast{ id:hoveredImage anchors.fill: _wrapperContainer source: _wrapperContainer enabled: appletItem.isSquare && !originalAppletBehavior && !indicators.info.providesHoveredAnimation && opacity != 0 ? true : false opacity: appletMouseArea.containsMouse ? 1 : 0 brightness: 0.25 contrast: 0.15 visible: !indicators.info.providesHoveredAnimation Behavior on opacity { NumberAnimation { duration: appletItem.animations.speedFactor.current*appletItem.animations.duration.large } } } BrightnessContrast { id: _clickedEffect anchors.fill: _wrapperContainer source: _wrapperContainer visible: clickedAnimation.running && !indicators.info.providesClickedAnimation } /* onHeightChanged: { if ((index == 1)|| (index==3)){ console.log("H: "+index+" ("+zoomScale+"). "+currentLayout.children[1].height+" - "+currentLayout.children[3].height+" - "+(currentLayout.children[1].height+currentLayout.children[3].height)); } } onZoomScaleChanged:{ if ((index == 1)|| (index==3)){ console.log(index+" ("+zoomScale+"). "+currentLayout.children[1].height+" - "+currentLayout.children[3].height+" - "+(currentLayout.children[1].height+currentLayout.children[3].height)); } }*/ Loader{ anchors.fill: parent active: root.debugMode sourceComponent: Rectangle{ anchors.fill: parent color: "transparent" //! red visualizer, in debug mode for the applets that use fillWidth or fillHeight //! green, for the rest border.color: (appletItem.needsFillSpace && (appletItem.sizeForFill>-1) && root.isHorizontal) ? "red" : "green" border.width: 1 } } Behavior on zoomScale { enabled: !root.globalDirectRender NumberAnimation { duration: 3 * appletItem.animationTime easing.type: Easing.OutCubic } } Behavior on zoomScale { enabled: root.globalDirectRender && !restoreAnimation.running NumberAnimation { duration: root.directRenderAnimationTime } } function calculateScales( currentMousePosition ){ if (root.zoomFactor===1) { return; } var distanceFromHovered = Math.abs(index - layoutsContainer.hoveredIndex); // A new algorithm trying to make the zoom calculation only once // and at the same time fixing glitches if ((distanceFromHovered == 0)&& (currentMousePosition > 0) ){ //use the new parabolicManager in order to handle all parabolic effect messages var scales = parabolicManager.applyParabolicEffect(index, currentMousePosition, center); /*if (root.latteApplet && Math.abs(index - root.latteAppletPos) > 2){ root.latteApplet.clearZoom(); }*/ //Left hiddenSpacer if(appletItem.firstAppletInContainer){ hiddenSpacerLeft.nScale = scales.leftScale - 1; } //Right hiddenSpacer ///there is one more item in the currentLayout ???? if(appletItem.lastAppletInContainer){ hiddenSpacerRight.nScale = scales.rightScale - 1; } zoomScale = root.zoomFactor; } } //scale function signalUpdateScale(nIndex, nScale, step){ if(appletItem && !appletItem.containsMouse && (appletItem.index === nIndex)){ if ( ((canBeHovered && !appletItem.originalAppletBehavior) || appletItem.latteApplet) && (applet && applet.status !== PlasmaCore.Types.HiddenStatus) //&& (index != currentLayout.hoveredIndex) ){ if(!appletItem.latteApplet){ if(nScale >= 0) zoomScale = nScale + step; else zoomScale = zoomScale + step; } } } } Component.onCompleted: { root.updateScale.connect(signalUpdateScale); } Component.onDestruction: { root.updateScale.disconnect(signalUpdateScale); } }// Main task area // id:wrapper diff --git a/containment/package/contents/ui/applet/ShortcutBadge.qml b/containment/package/contents/ui/applet/ShortcutBadge.qml index 0266e901..6c92cb6c 100644 --- a/containment/package/contents/ui/applet/ShortcutBadge.qml +++ b/containment/package/contents/ui/applet/ShortcutBadge.qml @@ -1,122 +1,122 @@ /* * Copyright 2019 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 . */ import QtQuick 2.1 import QtGraphicalEffects 1.0 import org.kde.latte.components 1.0 as LatteComponents Loader{ id: appletNumberLoader active: appletItem.canShowAppletNumberBadge && (root.showLatteShortcutBadges || root.showAppletShortcutBadges || root.showMetaBadge && applet.id===applicationLauncherId) asynchronous: true visible: badgeString!=="" property int fixedIndex: -1 property string badgeString: "" onActiveChanged: { if (active && root.showLatteShortcutBadges && root.unifiedGlobalShortcuts) { fixedIndex = parabolicManager.pseudoAppletIndex(index); } else { fixedIndex = -1; } } Component.onCompleted: { if (active && root.showLatteShortcutBadges && root.unifiedGlobalShortcuts) { fixedIndex = parabolicManager.pseudoAppletIndex(index); } else { fixedIndex = -1; } } Binding{ target: appletNumberLoader property:"badgeString" value: { //! don't change value on hiding/releasing if (!root.showMetaBadge && !root.showAppletShortcutBadges) { return; } if (root.showMetaBadge && applet && applet.id === applicationLauncherId) { return '\u2318'; } if (root.showAppletShortcutBadges) { var plasmaShortcut = applet ? shortcutsEngine.appletShortcutBadge(applet.id) : ""; if (plasmaShortcut !== "") { return plasmaShortcut; } } if (appletNumberLoader.fixedIndex>=1 && appletNumberLoader.fixedIndex<20) { return root.badgesForActivate[appletNumberLoader.fixedIndex-1]; } else { return ""; } } } sourceComponent: Item{ Loader{ anchors.fill: appletNumber active: root.enableShadows && graphicsSystem.isAccelerated sourceComponent: DropShadow{ color: root.appShadowColor fast: true samples: 2 * radius source: appletNumber radius: root.appShadowSize/2 verticalOffset: 2 } } LatteComponents.BadgeText { id: appletNumber // when iconSize < 48, height is always = 24, height / iconSize > 50% // we prefer center aligned badges to top-left aligned ones - property bool centerInParent: appletItem.container.iconSize < 48 + property bool centerInParent: appletItem.metrics.iconSize < 48 anchors.left: centerInParent? undefined : parent.left anchors.top: centerInParent? undefined : parent.top anchors.centerIn: centerInParent? parent : undefined - minimumWidth: 0.4 * (wrapper.zoomScale * appletItem.container.iconSize) - height: Math.max(24, 0.4 * (wrapper.zoomScale * appletItem.container.iconSize)) + minimumWidth: 0.4 * (wrapper.zoomScale * appletItem.metrics.iconSize) + height: Math.max(24, 0.4 * (wrapper.zoomScale * appletItem.metrics.iconSize)) borderColor: colorizerManager.originalLightTextColor proportion: 0 radiusPerCentage: 100 showNumber: false showText: true textValue: appletNumberLoader.badgeString style3d: root.badges3DStyle } } } diff --git a/containment/package/contents/ui/applet/TitleTooltipParent.qml b/containment/package/contents/ui/applet/TitleTooltipParent.qml index f178d32b..64d6e4c2 100644 --- a/containment/package/contents/ui/applet/TitleTooltipParent.qml +++ b/containment/package/contents/ui/applet/TitleTooltipParent.qml @@ -1,88 +1,88 @@ /* * 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 . */ import QtQuick 2.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore Item{ id: visual width: root.isVertical ? thickness : size height: root.isVertical ? size : thickness property int size: 1 property int thickness: Math.min(Math.max(minimumThickness, preferredThickness), maximumThickness) property int minimumThickness: 0 - readonly property int preferredThickness: (root.zoomFactor * (container.iconSize + root.thickMargins)) + root.localScreenEdgeMargin + readonly property int preferredThickness: (root.zoomFactor * (metrics.iconSize + root.thickMargins)) + root.localScreenEdgeMargin property int maximumThickness: 9999 - property Item container: null + property Item metrics: null //border.width: 1 //border.color: "green" //color: "transparent" states:[ State{ name: "bottom" when: plasmoid.location === PlasmaCore.Types.BottomEdge AnchorChanges{ target: visual; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } }, State{ name: "top" when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges{ target:visual; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; } }, State{ name: "left" when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges{ target: visual; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; } }, State{ name: "right" when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges{ target: visual; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } } ] } diff --git a/containment/package/contents/ui/applet/communicator/LatteBridge.qml b/containment/package/contents/ui/applet/communicator/LatteBridge.qml index 8cb2713b..8a88d3db 100644 --- a/containment/package/contents/ui/applet/communicator/LatteBridge.qml +++ b/containment/package/contents/ui/applet/communicator/LatteBridge.qml @@ -1,138 +1,138 @@ /* * Copyright 2018 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 . */ import QtQuick 2.7 Item{ id: settings //! EXPOSED SIGNALS //! USAGE: signals from other applets, , //! EXPLANATION: applets can receive signals from other applets //! to catch signals from other applets in order to communicate with //! each other signal broadcasted(string action, variant value); //! EXPOSED PROPERTIES // NAME: version // USAGE: read-only // EXPLANATION: Latte communication version in order for the applet to use only properties // and parameters that are valid // @since: 0.9 readonly property int version: root.version // NAME: inEditMode // USAGE: read-only // EXPLANATION: Latte sets it to true when this applet is in a Latte containment and Latte // is also in EditMode, that means when the user is altering applets and Latte latteView settings // @since: 0.9 readonly property bool inEditMode: root.inConfigureAppletsMode // NAME: inPlasmaPanelStyle // USAGE: read-only // EXPLANATION: Latte sets it to true when this view behaves as Plasma panel concerning // drawing background shadows externally and applets can take this into account in order // to adjust their appearance and behavior // @since: 0.9 readonly property bool inPlasmaPanelStyle: root.behaveAsPlasmaPanel // NAME: palette // USAGE: read-only // EXPLANATION: Latte updates it to its coloring palette in order for the applet // to take responsibility of its coloring. // USE CASE: when Latte is transparent and applets colors need to be adjusted in order // to look consistent with the underlying desktop background // @since: 0.9 readonly property QtObject palette: !applet.latteSideColoringEnabled ? colorizerManager : null // NAME: applyPalette // USAGE: read-only // EXPLANATION: Latte updates it to TRUE when the applet must use the provided // Latte "palette" and FALSE otherwise // USE CASE: when Latte is transparent and applets colors need to be adjusted in order // to look consistent with the underlying desktop background // @since: 0.9 readonly property bool applyPalette: !applet.latteSideColoringEnabled ? colorizerManager.mustBeShown : false // NAME: parabolicEffectEnabled // USAGE: read-only // EXPLANATION: Parabolic Effect is enabled or not for this Latte View // USE CASE: it can be used from applets that want to be adjusted based // on the parabolic Effect or not // @since: 0.9 readonly property bool parabolicEffectEnabled: root.parabolicEffectEnabled && !appletItem.originalAppletBehavior // NAME: iconSize // USAGE: read-only // EXPLANATION: The current icon size used in the Latte View // USE CASE: it can be used from applets that want their size to be always // relevant to the view icon size // @since: 0.9 - readonly property int iconSize: appletItem.container.iconSize + readonly property int iconSize: appletItem.metrics.iconSize // NAME: screenEdgeMargin // USAGE: read-only // EXPLANATION: The screen edge margin applied in pixels // USE CASE: it can be used from applets that want to be informed what is the screen edge margin // currently applied // @since: 0.10 readonly property int screenEdgeMargin: root.localScreenEdgeMargin // NAME: maxZoomFactor // USAGE: read-only // EXPLANATION: The maximum zoom factor currently used // USE CASE: it can be used from applets that want to be informed what is the maximum // zoom factor currently used // @since: 0.9 readonly property real maxZoomFactor: root.zoomFactor // NAME: windowsTracker // USAGE: read-only // EXPLANATION: windows tracking based on the view this applet is present // USE CASE: it can be used from applets that want windows tracking in order // to update their appearance or their behavior accordingly // @since: 0.9 readonly property QtObject windowsTracker: applet.windowsTrackingEnabled && latteView && latteView.windowsTracker ? latteView.windowsTracker : null readonly property Item actions: Actions{} readonly property Item applet: mainCommunicator.requires readonly property Item animations: appletItem.animations.publicApi - readonly property Item container: appletItem.container.publicApi + readonly property Item metrics: appletItem.metrics.publicApi Connections { target: root onBroadcastedToApplet: { if (appletItem.applet && appletItem.applet.pluginName === pluginName) { settings.broadcasted(action, value); } } } //! Initialize Component.onCompleted: { appletRootItem.latteBridge = settings; } Component.onDestruction: { appletRootItem.latteBridge = null; } } diff --git a/containment/package/contents/ui/applet/indicator/Bridge.qml b/containment/package/contents/ui/applet/indicator/Bridge.qml index 03fe5b98..fa69bb3a 100644 --- a/containment/package/contents/ui/applet/indicator/Bridge.qml +++ b/containment/package/contents/ui/applet/indicator/Bridge.qml @@ -1,96 +1,96 @@ /* * Copyright 2019 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 . */ import QtQuick 2.7 Item{ id: indicatorBridge anchors.fill: parent property bool appletIsValid: true readonly property bool active: appletIsValid && ((indicators.isEnabled && appletItem.communicatorAlias.requires.activeIndicatorEnabled && indicators.info.enabledForApplets) || (!indicators.info.enabledForApplets && appletItem.communicatorAlias.overlayLatteIconIsActive)) /* Indicators Properties in order use them*/ readonly property bool isTask: false readonly property bool isApplet: true readonly property bool isEmptySpace: false /*since 0.9.3*/ readonly property bool isLauncher: false readonly property bool isStartup: false readonly property bool isWindow: false readonly property bool isActive: appletIsValid ? appletItem.isActive : false readonly property bool isGroup: false readonly property bool isHovered: appletIsValid ? appletMouseArea.containsMouse : false readonly property bool isMinimized: false readonly property bool isPressed: appletIsValid ? appletMouseArea.pressed : false readonly property bool inAttention: false readonly property bool inRemoving: false readonly property bool isSquare: appletIsValid ? appletItem.isSquare : true readonly property bool hasActive: isActive readonly property bool hasMinimized: false readonly property bool hasShown: false readonly property int windowsCount: 0 readonly property int windowsMinimizedCount: 0 - readonly property int currentIconSize: appletIsValid ? appletItem.container.iconSize : container.iconSize - readonly property int maxIconSize: appletIsValid ? appletItem.container.maxIconSize : container.maxIconSize + readonly property int currentIconSize: appletIsValid ? appletItem.metrics.iconSize : metrics.iconSize + readonly property int maxIconSize: appletIsValid ? appletItem.metrics.maxIconSize : metrics.maxIconSize readonly property real scaleFactor: appletIsValid ? appletItem.wrapperAlias.zoomScale : 1 readonly property real panelOpacity: root.currentPanelOpacity readonly property color shadowColor: root.appShadowColorSolid readonly property bool animationsEnabled: appletIsValid ? appletItem.animations.active : animations.active readonly property real durationTime: appletIsValid ? appletItem.animations.speedFactor.current : animations.speedFactor.current readonly property bool progressVisible: false /*since 0.9.2*/ readonly property real progress: 0 /*since 0.9.2*/ readonly property int screenEdgeMargin: root.localScreenEdgeMargin /*since 0.10*/ readonly property QtObject palette: colorizerManager.applyTheme //!icon colors property color iconBackgroundColor: { if (appletIsValid) { return isSquare ? appletItem.wrapperAlias.overlayIconLoader.backgroundColor : colorizerManager.buttonFocusColor; } return "black"; } property color iconGlowColor:{ if (appletIsValid) { return isSquare ? appletItem.wrapperAlias.overlayIconLoader.glowColor : colorizerManager.focusGlowColor; } return "white"; } //! grouped options readonly property Item shared: indicators readonly property QtObject configuration: indicators.configuration readonly property QtObject resources: indicators.resources } diff --git a/containment/package/contents/ui/applet/indicator/Loader.qml b/containment/package/contents/ui/applet/indicator/Loader.qml index 25298ba3..5bfd9540 100644 --- a/containment/package/contents/ui/applet/indicator/Loader.qml +++ b/containment/package/contents/ui/applet/indicator/Loader.qml @@ -1,89 +1,89 @@ /* * Copyright 2019 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 . */ import QtQuick 2.7 import org.kde.plasma.core 2.0 as PlasmaCore Loader { id: indicatorLoader anchors.bottom: (plasmoid.location === PlasmaCore.Types.BottomEdge) ? parent.bottom : undefined anchors.top: (plasmoid.location === PlasmaCore.Types.TopEdge) ? parent.top : undefined anchors.left: (plasmoid.location === PlasmaCore.Types.LeftEdge) ? parent.left : undefined anchors.right: (plasmoid.location === PlasmaCore.Types.RightEdge) ? parent.right : undefined anchors.horizontalCenter: root.isHorizontal ? parent.horizontalCenter : undefined anchors.verticalCenter: root.isVertical ? parent.verticalCenter : undefined active: level.bridge && level.bridge.active && (level.isBackground || (level.isForeground && indicators.info.providesFrontLayer)) sourceComponent: { if (!indicators.info.enabledForApplets && appletItem.communicatorAlias.overlayLatteIconIsActive) { return indicators.plasmaStyleComponent; } return indicators.indicatorComponent; } width: { if (root.isHorizontal) { if (canBeHovered) { return appletItem.wrapperAlias.zoomScale * visualLockedWidth; } return appletWrapper.width + appletItem.internalWidthMargins; } else { return appletItem.wrapperAlias.width; } } height: { if (root.isVertical) { if (canBeHovered) { return appletItem.wrapperAlias.zoomScale * visualLockedHeight; } return appletWrapper.height + appletItem.internalHeightMargins; } else { return appletItem.wrapperAlias.height; } } readonly property bool locked: appletItem.lockZoom || root.zoomFactor === 1 - property real visualLockedWidth: appletItem.container.iconSize + appletItem.internalWidthMargins - property real visualLockedHeight: appletItem.container.iconSize + appletItem.internalHeightMargins + property real visualLockedWidth: appletItem.metrics.iconSize + appletItem.internalWidthMargins + property real visualLockedHeight: appletItem.metrics.iconSize + appletItem.internalHeightMargins //! Communications !// property Item level Connections { target: appletItem enabled: indicators.info.needsMouseEventCoordinates onMousePressed: { var fixedPos = indicatorLoader.mapFromItem(appletItem, x, y); level.mousePressed(Math.round(fixedPos.x), Math.round(fixedPos.y), button); } onMouseReleased: { var fixedPos = indicatorLoader.mapFromItem(appletItem, x, y); level.mouseReleased(Math.round(fixedPos.x), Math.round(fixedPos.y), button); } } } diff --git a/containment/package/contents/ui/editmode/Visual.qml b/containment/package/contents/ui/editmode/Visual.qml index d841bccd..57575843 100644 --- a/containment/package/contents/ui/editmode/Visual.qml +++ b/containment/package/contents/ui/editmode/Visual.qml @@ -1,457 +1,457 @@ /* * Copyright 2016 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 . */ import QtQuick 2.1 import QtGraphicalEffects 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.components 1.0 as LatteComponents import "../applet" as Applet Item{ id: editVisual width: root.isHorizontal ? (latteView ? latteView.width : root.width) : visibilityManager.thicknessEditMode height: root.isVertical ? (latteView ? latteView.height : root.height) : visibilityManager.thicknessEditMode visible: editVisual.inEditMode readonly property int settingsThickness: settingsOverlay.thickness property int speed: LatteCore.WindowSystem.compositingActive ? animations.speedFactor.normal*3.6*animations.duration.large : 10 property int thickness: visibilityManager.thicknessEditMode + root.editShadow property int rootThickness: visibilityManager.thicknessZoomOriginal + root.editShadow //- visibilityManager.thicknessEditMode - property int editLength: root.isHorizontal ? (root.behaveAsPlasmaPanel ? root.width - container.maxIconSize/4 : root.width)://root.maxLength) : - (root.behaveAsPlasmaPanel ? root.height - container.maxIconSize/4 : root.height) + property int editLength: root.isHorizontal ? (root.behaveAsPlasmaPanel ? root.width - metrics.maxIconSize/4 : root.width)://root.maxLength) : + (root.behaveAsPlasmaPanel ? root.height - metrics.maxIconSize/4 : root.height) property bool farEdge: (plasmoid.location===PlasmaCore.Types.BottomEdge) || (plasmoid.location===PlasmaCore.Types.RightEdge) property bool editAnimationEnded: false property bool editAnimationInFullThickness: false property bool editAnimationRunning: false property bool plasmaEditMode: plasmoid.userConfiguring property bool inEditMode: false property rect efGeometry property string layoutColor: latteView && latteView.layout ? latteView.layout.color : "blue" readonly property real appliedOpacity: imageTiler.opacity readonly property real maxOpacity: root.inConfigureAppletsMode || !LatteCore.WindowSystem.compositingActive ? 1 : plasmoid.configuration.editBackgroundOpacity LatteComponents.ExternalShadow{ id: editExternalShadow width: root.isHorizontal ? imageTiler.width : root.editShadow height: root.isHorizontal ? root.editShadow : imageTiler.height visible: !editTransition.running && root.editMode && LatteCore.WindowSystem.compositingActive shadowSize: root.editShadow shadowOpacity: Math.max(0.35, imageTiler.opacity) shadowDirection: plasmoid.location states: [ ///topShadow State { name: "topShadow" when: (plasmoid.location === PlasmaCore.Types.BottomEdge) AnchorChanges { target: editExternalShadow anchors{ top:undefined; bottom:imageTiler.top; left:undefined; right:undefined; horizontalCenter:imageTiler.horizontalCenter; verticalCenter:undefined} } }, ///bottomShadow State { name: "bottomShadow" when: (plasmoid.location === PlasmaCore.Types.TopEdge) AnchorChanges { target: editExternalShadow anchors{ top:imageTiler.bottom; bottom:undefined; left:undefined; right:undefined; horizontalCenter:imageTiler.horizontalCenter; verticalCenter:undefined} } }, ///leftShadow State { name: "leftShadow" when: (plasmoid.location === PlasmaCore.Types.RightEdge) AnchorChanges { target: editExternalShadow anchors{ top:undefined; bottom:undefined; left:undefined; right:imageTiler.left; horizontalCenter:undefined; verticalCenter:imageTiler.verticalCenter} } }, ///rightShadow State { name: "rightShadow" when: (plasmoid.location === PlasmaCore.Types.LeftEdge) AnchorChanges { target: editExternalShadow anchors{ top:undefined; bottom:undefined; left:imageTiler.right; right:undefined; horizontalCenter:undefined; verticalCenter:imageTiler.verticalCenter} } } ] } Image{ id: imageTiler anchors.centerIn: parent width: parent.width height: parent.height opacity: 0 fillMode: Image.Tile source: hasBackground ? latteView.layout.background : "../../icons/"+latteView.layout.background+"print.jpg" readonly property bool hasBackground: (latteView && latteView.layout && latteView.layout.background.startsWith("/")) ? true : false Connections { target: editVisual onMaxOpacityChanged: { if (editVisual.editAnimationEnded) { imageTiler.opacity = editVisual.maxOpacity; } } } Behavior on opacity { enabled: editVisual.editAnimationEnded NumberAnimation { duration: 0.8 * animations.duration.proposed easing.type: Easing.OutCubic } } } MouseArea { id: editBackMouseArea anchors.fill: imageTiler visible: editModeVisual.editAnimationEnded && !root.inConfigureAppletsMode hoverEnabled: true property bool wheelIsBlocked: false; readonly property double opacityStep: 0.1 readonly property string tooltip: i18nc("opacity for background under edit mode, %0% is opacity percentage", "You can use mouse wheel to change background opacity of %0%").arg(Math.round(plasmoid.configuration.editBackgroundOpacity * 100)) onWheel: { processWheel(wheel); } function processWheel(wheel) { if (wheelIsBlocked) { return; } wheelIsBlocked = true; scrollDelayer.start(); var angle = wheel.angleDelta.y / 8; if (angle > 10) { plasmoid.configuration.editBackgroundOpacity = Math.min(100, plasmoid.configuration.editBackgroundOpacity + opacityStep) } else if (angle < -10) { plasmoid.configuration.editBackgroundOpacity = Math.max(0, plasmoid.configuration.editBackgroundOpacity - opacityStep) } } Connections { target: root onEmptyAreasWheel: { if (root.editMode && !root.inConfigureAppletsMode) { editBackMouseArea.processWheel(wheel); } } } //! A timer is needed in order to handle also touchpads that probably //! send too many signals very fast. This way the signals per sec are limited. //! The user needs to have a steady normal scroll in order to not //! notice a annoying delay Timer{ id: scrollDelayer interval: 80 onTriggered: editBackMouseArea.wheelIsBlocked = false; } } PlasmaComponents.Button { anchors.fill: editBackMouseArea opacity: 0 tooltip: editBackMouseArea.tooltip } //! Settings Overlay SettingsOverlay { id: settingsOverlay anchors.fill: parent visible: root.editMode } Applet.TitleTooltipParent { id: titleTooltipParent - container: root.container + metrics: root.metrics minimumThickness: visibilityManager.thicknessEditMode maximumThickness: root.inConfigureAppletsMode ? visibilityManager.thicknessEditMode : 9999 } Connections{ target: root onThemeColorsChanged: imageTiler.opacity = editVisual.maxOpacity } Connections{ target: plasmoid onLocationChanged: initializeEditPosition(); } onInEditModeChanged: { if (inEditMode) { latteView.visibility.addBlockHidingEvent("EditVisual[qml]::inEditMode()"); } else { latteView.visibility.removeBlockHidingEvent("EditVisual[qml]::inEditMode()"); if (latteView.visibility.isHidden) { latteView.visibility.mustBeShown(); } } } onRootThicknessChanged: { initializeEditPosition(); } onThicknessChanged: { initializeEditPosition(); } onXChanged: updateEffectsArea(); onYChanged: updateEffectsArea(); onWidthChanged: { /*if (root.isHorizontal) { initializeEditPosition(); }*/ updateEffectsArea(); } onHeightChanged: { /* if (root.isVertical) { initializeEditPosition(); }*/ updateEffectsArea(); } function updateEffectsArea(){ if (LatteCore.WindowSystem.compositingActive || !latteView || state !== "edit" || !editAnimationEnded) { return; } var rootGeometry = mapToItem(root, 0, 0); efGeometry.x = rootGeometry.x; efGeometry.y = rootGeometry.y; efGeometry.width = width; efGeometry.height = height; latteView.effects.rect = efGeometry; } function initializeNormalPosition() { if (plasmoid.location === PlasmaCore.Types.BottomEdge) { y = rootThickness; x = 0; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { x = rootThickness; y = 0; } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { x = -editVisual.thickness; y = 0; } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { y = -editVisual.thickness; x = 0; } } function initializeEditPosition() { if (root.editMode) { if (plasmoid.location === PlasmaCore.Types.LeftEdge){ x = 0; y = 0; } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { x = 0; y = 0; } else if (plasmoid.location === PlasmaCore.Types.BottomEdge) { x = 0; y = rootThickness - thickness; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { x = rootThickness - thickness; y = 0; } } } //////////// States //////////////////// states: [ State{ name: "*" //! since qt 5.14 default state can not use "when" property //! it breaks restoring transitions otherwise }, State{ name: "edit" when: plasmaEditMode } ] transitions: [ Transition{ id: editTransition from: "*" to: "edit" SequentialAnimation{ id:normalAnimationTransition ScriptAction{ script:{ editVisual.editAnimationRunning = true; editVisual.inEditMode = true; imageTiler.opacity = 0 editVisual.editAnimationEnded = false; initializeNormalPosition(); animations.needLength.addEvent(editVisual); } } PauseAnimation{ id: pauseAnimation //! give the time to CREATE the settings windows and not break //! the sliding in animation duration: animations.active ? 100 : 0 } ParallelAnimation{ PropertyAnimation { target: imageTiler property: "opacity" to: plasmoid.configuration.inConfigureAppletsMode ? 1 : editVisual.maxOpacity duration: Math.max(0, editVisual.speed - pauseAnimation.duration) easing.type: Easing.InQuad } PropertyAnimation { target: editVisual property: root.isHorizontal ? "y" : "x" to: editVisual.farEdge ? editVisual.rootThickness - editVisual.thickness : 0 duration: Math.max(0, editVisual.speed - pauseAnimation.duration) easing.type: Easing.Linear } } ScriptAction{ script:{ editVisual.editAnimationEnded = true; editVisual.editAnimationInFullThickness = true; updateEffectsArea(); autosize.updateIconSize(); visibilityManager.updateMaskArea(); editVisual.editAnimationRunning = false; } } } }, Transition{ from: "edit" to: "*" SequentialAnimation{ ScriptAction{ script: { editVisual.editAnimationRunning = true; editVisual.editAnimationInFullThickness = false; //! remove kwin effects when starting the animation latteView.effects.rect = Qt.rect(-1, -1, 0, 0); } } PauseAnimation{ id: pauseAnimation2 //! give the time to DELETE the settings windows and not break //! the sliding out animation duration: animations.isActive ? 100 : 0 } ParallelAnimation{ PropertyAnimation { target: editVisual property: root.isHorizontal ? "y" : "x" to: editVisual.farEdge ? editVisual.rootThickness : -editVisual.thickness duration: Math.max(0,editVisual.speed - pauseAnimation2.duration) easing.type: Easing.Linear } PropertyAnimation { target: imageTiler property: "opacity" to: 0 duration: Math.max(0,editVisual.speed - pauseAnimation2.duration) easing.type: Easing.InQuad } } ScriptAction{ script:{ editVisual.inEditMode = false; editVisual.editAnimationEnded = false; animations.needLength.removeEvent(editVisual); //! That part was at the end of the Containers sliding-out animation //! but it looks much better here if (visibilityManager.inTempHiding) { visibilityManager.sendSlidingOutAnimationEnded(); } editVisual.editAnimationRunning = false; } } } } ] } diff --git a/containment/package/contents/ui/layouts/EnvironmentActions.qml b/containment/package/contents/ui/layouts/EnvironmentActions.qml index d3974c7b..6030d6a5 100644 --- a/containment/package/contents/ui/layouts/EnvironmentActions.qml +++ b/containment/package/contents/ui/layouts/EnvironmentActions.qml @@ -1,362 +1,362 @@ /* * Copyright 2019 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 . */ import QtQuick 2.7 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.plasmoid 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.private.containment 0.1 as LatteContainment import "loaders" as Loaders import "indicator" as Indicator import "../applet/indicator" as AppletIndicator Loader { id: environmentLoader width: active ? item.width : 0 height: active ? item.height: 0 property int alignment: LatteCore.Types.BottomEdgeCenterAlign sourceComponent: MouseArea{ id: mainArea width: root.isHorizontal ? length : localThickness + root.localScreenEdgeMargin height: root.isVertical ? length : localThickness + root.localScreenEdgeMargin acceptedButtons: Qt.LeftButton | Qt.MidButton - readonly property int localThickness: (root.isHovered ? (container.iconSize + root.thickMargins)*root.zoomFactor : (container.iconSize + root.thickMargins)) + readonly property int localThickness: (root.isHovered ? (metrics.iconSize + root.thickMargins)*root.zoomFactor : (metrics.iconSize + root.thickMargins)) readonly property int length: { if (screenEdgeMarginEnabled && plasmoid.configuration.fittsLawIsRequested) { return root.isHorizontal ? root.width : root.height; } return useAllLayouts ? root.maxLength : root.realPanelLength; } property bool wheelIsBlocked: false hoverEnabled: true readonly property bool useAllLayouts: panelUserSetAlignment === LatteCore.Types.Justify && !root.inConfigureAppletsMode property int lastPressX: -1 property int lastPressY: -1 onContainsMouseChanged: { if (root.mouseInHoverableArea()) { root.stopCheckRestoreZoomTimer(); } else { root.initializeHoveredIndexes(); root.startCheckRestoreZoomTimer() } } onClicked: { if (root.closeActiveWindowEnabled && mouse.button === Qt.MidButton) { selectedWindowsTracker.lastActiveWindow.requestClose(); } } onPressed: { if (!root.dragActiveWindowEnabled) { return; } if (mouse.button === Qt.LeftButton && selectedWindowsTracker.lastActiveWindow.canBeDragged()) { lastPressX = mouse.x; lastPressY = mouse.y; dragWindowTimer.start(); } } onReleased: { lastPressX = -1; lastPressY = -1; } onPositionChanged: { if (!root.dragActiveWindowEnabled || !(mainArea.pressedButtons & Qt.LeftButton)) { return; } var stepX = Math.abs(lastPressX-mouse.x); var stepY = Math.abs(lastPressY-mouse.y); var threshold = 5; var tryDrag = mainArea.pressed && (stepX>threshold || stepY>threshold); if ( tryDrag && selectedWindowsTracker.lastActiveWindow.canBeDragged()) { dragWindowTimer.stop(); activateDragging(); } } onDoubleClicked: { if (!root.dragActiveWindowEnabled) { return; } dragWindowTimer.stop(); selectedWindowsTracker.lastActiveWindow.requestToggleMaximized(); } onWheel: { if (wheelIsBlocked) { return; } if (root.scrollAction === LatteContainment.Types.ScrollNone) { root.emptyAreasWheel(wheel); return; } wheelIsBlocked = true; scrollDelayer.start(); var delta = 0; if (wheel.angleDelta.y>=0 && wheel.angleDelta.x>=0) { delta = Math.max(wheel.angleDelta.y, wheel.angleDelta.x); } else { delta = Math.min(wheel.angleDelta.y, wheel.angleDelta.x); } var angle = delta / 8; var ctrlPressed = (wheel.modifiers & Qt.ControlModifier); if (angle>10) { //! upwards if (root.scrollAction === LatteContainment.Types.ScrollDesktops) { latteView.windowsTracker.switchToPreviousVirtualDesktop(); } else if (root.scrollAction === LatteContainment.Types.ScrollActivities) { latteView.windowsTracker.switchToPreviousActivity(); } else if (root.scrollAction === LatteContainment.Types.ScrollToggleMinimized) { if (!ctrlPressed) { tasksLoader.item.activateNextPrevTask(true); } else if (!selectedWindowsTracker.lastActiveWindow.isMaximized){ selectedWindowsTracker.lastActiveWindow.requestToggleMaximized(); } } else if (tasksLoader.active) { tasksLoader.item.activateNextPrevTask(true); } } else if (angle<-10) { //! downwards if (root.scrollAction === LatteContainment.Types.ScrollDesktops) { latteView.windowsTracker.switchToNextVirtualDesktop(); } else if (root.scrollAction === LatteContainment.Types.ScrollActivities) { latteView.windowsTracker.switchToNextActivity(); } else if (root.scrollAction === LatteContainment.Types.ScrollToggleMinimized) { if (!ctrlPressed) { if (selectedWindowsTracker.lastActiveWindow.isValid && !selectedWindowsTracker.lastActiveWindow.isMinimized && selectedWindowsTracker.lastActiveWindow.isMaximized){ //! maximized selectedWindowsTracker.lastActiveWindow.requestToggleMaximized(); } else if (selectedWindowsTracker.lastActiveWindow.isValid && !selectedWindowsTracker.lastActiveWindow.isMinimized && !selectedWindowsTracker.lastActiveWindow.isMaximized) { //! normal selectedWindowsTracker.lastActiveWindow.requestToggleMinimized(); } } else if (selectedWindowsTracker.lastActiveWindow.isMaximized) { selectedWindowsTracker.lastActiveWindow.requestToggleMaximized(); } } else if (tasksLoader.active) { tasksLoader.item.activateNextPrevTask(false); } } } Loaders.Tasks{ id: tasksLoader } function activateDragging(){ selectedWindowsTracker.requestMoveLastWindow(mainArea.mouseX, mainArea.mouseY); mainArea.lastPressX = -1; mainArea.lastPressY = -1; } //! Timers Timer { id: dragWindowTimer interval: 500 onTriggered: { if (mainArea.pressed && selectedWindowsTracker.lastActiveWindow.canBeDragged()) { mainArea.activateDragging(); } } } //! A timer is needed in order to handle also touchpads that probably //! send too many signals very fast. This way the signals per sec are limited. //! The user needs to have a steady normal scroll in order to not //! notice a annoying delay Timer{ id: scrollDelayer interval: 200 onTriggered: mainArea.wheelIsBlocked = false; } //! Background Indicator Indicator.Bridge{ id: indicatorBridge } //! Indicator Back Layer Indicator.Loader{ id: indicatorBackLayer level: AppletIndicator.LevelOptions { id: backLevelOptions isBackground: true bridge: indicatorBridge } } } states:[ State { name: "bottomCenter" when: (alignment === LatteCore.Types.BottomEdgeCenterAlign) AnchorChanges { target: environmentLoader anchors{ top:undefined; bottom:_mainLayout.bottom; left:undefined; right:undefined; horizontalCenter: _mainLayout.horizontalCenter; verticalCenter:undefined} } }, State { name: "bottomLeft" when: (alignment === LatteCore.Types.BottomEdgeLeftAlign) AnchorChanges { target: environmentLoader anchors{ top:undefined; bottom:_mainLayout.bottom; left:parent.left; right:undefined; horizontalCenter: undefined; verticalCenter:undefined} } }, State { name: "bottomRight" when: (alignment === LatteCore.Types.BottomEdgeRightAlign) AnchorChanges { target: environmentLoader anchors{ top:undefined; bottom: _mainLayout.bottom; left:undefined; right:parent.right; horizontalCenter: undefined; verticalCenter:undefined} } }, State { name: "topCenter" when: (alignment === LatteCore.Types.TopEdgeCenterAlign) AnchorChanges { target: environmentLoader anchors{ top: _mainLayout.top; bottom:undefined; left:undefined; right:undefined; horizontalCenter: _mainLayout.horizontalCenter; verticalCenter:undefined} } }, State { name: "topLeft" when: (alignment === LatteCore.Types.TopEdgeLeftAlign) AnchorChanges { target: environmentLoader anchors{ top: _mainLayout.top; bottom:undefined; left: _mainLayout.left; right:undefined; horizontalCenter: undefined; verticalCenter:undefined} } }, State { name: "topRight" when: (alignment === LatteCore.Types.TopEdgeRightAlign) AnchorChanges { target: environmentLoader anchors{ top: _mainLayout.top; bottom:undefined; left:undefined; right: _mainLayout.right; horizontalCenter: undefined; verticalCenter:undefined} } }, State { name: "leftCenter" when: (alignment === LatteCore.Types.LeftEdgeCenterAlign) AnchorChanges { target: environmentLoader anchors{ top:undefined; bottom:undefined; left: _mainLayout.left; right:undefined; horizontalCenter:undefined; verticalCenter: _mainLayout.verticalCenter} } }, State { name: "leftTop" when: (alignment === LatteCore.Types.LeftEdgeTopAlign) AnchorChanges { target: environmentLoader anchors{ top:mainLayout.top; bottom:undefined; left: _mainLayout.left; right:undefined; horizontalCenter:undefined; verticalCenter: undefined} } }, State { name: "leftBottom" when: (alignment === LatteCore.Types.LeftEdgeBottomAlign) AnchorChanges { target: environmentLoader anchors{ top:undefined; bottom:_mainLayout.bottom; left: _mainLayout.left; right:undefined; horizontalCenter:undefined; verticalCenter: undefined} } }, State { name: "rightCenter" when: (alignment === LatteCore.Types.RightEdgeCenterAlign) AnchorChanges { target: environmentLoader anchors{ top:undefined; bottom:undefined; left:undefined; right: _mainLayout.right; horizontalCenter:undefined; verticalCenter: _mainLayout.verticalCenter} } }, State { name: "rightTop" when: (alignment === LatteCore.Types.RightEdgeTopAlign) AnchorChanges { target: environmentLoader anchors{ top:_mainLayout.top; bottom:undefined; left:undefined; right: _mainLayout.right; horizontalCenter:undefined; verticalCenter: undefined} } }, State { name: "rightBottom" when: (alignment === LatteCore.Types.RightEdgeBottomAlign) AnchorChanges { target: environmentLoader anchors{ top:undefined; bottom:_mainLayout.bottom; left:undefined; right: _mainLayout.right; horizontalCenter:undefined; verticalCenter: undefined} } } ] } diff --git a/containment/package/contents/ui/layouts/LayoutsContainer.qml b/containment/package/contents/ui/layouts/LayoutsContainer.qml index 27b472bb..b2bd8f66 100644 --- a/containment/package/contents/ui/layouts/LayoutsContainer.qml +++ b/containment/package/contents/ui/layouts/LayoutsContainer.qml @@ -1,323 +1,323 @@ /* * Copyright 2016 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 . */ import QtQuick 2.1 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.private.containment 0.1 as LatteContainment import "../../code/HeuristicTools.js" as HeuristicTools Item{ id: layoutsContainer readonly property bool isHidden: root.inStartup || (latteView && latteView.visibility && latteView.visibility.isHidden) readonly property bool useMaxLength: (plasmoid.configuration.alignment === LatteCore.Types.Justify && !root.inConfigureAppletsMode) /* && ((!root.inConfigureAppletsMode && !root.behaveAsPlasmaPanel ) || (behaveAsPlasmaPanel && root.inConfigureAppletsMode))*/ property int allCount: root.latteApplet ? _mainLayout.count-1+latteApplet.tasksCount : _mainLayout.count property int currentSpot: -1000 property int hoveredIndex: -1 readonly property int fillApplets: _startLayout.fillApplets + _mainLayout.fillApplets + _endLayout.fillApplets property Item startLayout : _startLayout property Item mainLayout: _mainLayout property Item endLayout: _endLayout Binding { target: layoutsContainer property: "x" value: { if (visibilityManager.inLocationAnimation) { return; } if (root.behaveAsPlasmaPanel) { return 0; } if ( latteView && root.isHorizontal && useMaxLength ){ return ((latteView.width/2) - (root.maxLength/2) + root.offset); } else { if ((visibilityManager.inSlidingIn || visibilityManager.inSlidingOut) && root.isVertical){ return; } if (layoutsContainer.isHidden && root.isVertical) { if (LatteCore.WindowSystem.compositingActive) { return visibilityManager.slidingOutToPos; } else { if ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) { return visibilityManager.slidingOutToPos + 1; } else { return visibilityManager.slidingOutToPos - 1; } } } else { return 0; } } } } Binding{ target: layoutsContainer property: "y" value: { if (visibilityManager.inLocationAnimation) { return; } if (root.behaveAsPlasmaPanel) { return 0; } if ( latteView && root.isVertical && useMaxLength ) { return ((latteView.height/2) - (root.maxLength/2) + root.offset); } else { if ((visibilityManager.inSlidingIn || visibilityManager.inSlidingOut) && root.isHorizontal){ return; } if (layoutsContainer.isHidden && root.isHorizontal) { if (LatteCore.WindowSystem.compositingActive) { return visibilityManager.slidingOutToPos; } else { if ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) { return visibilityManager.slidingOutToPos + 1; } else { return visibilityManager.slidingOutToPos - 1; } } } else { return 0; } } } } width: root.isHorizontal && useMaxLength ? root.maxLength : parent.width height: root.isVertical && useMaxLength ? root.maxLength : parent.height z:10 property bool animationSent: false property bool shouldCheckHalfs: (plasmoid.configuration.alignment === LatteCore.Types.Justify) && (_mainLayout.children>1) property int contentsWidth: _startLayout.width + _mainLayout.width + _endLayout.width property int contentsHeight: _startLayout.height + _mainLayout.height + _endLayout.height onContentsWidthChanged: { if (root.isHorizontal){ var firstHalfExited = false; var secondHalfExited = false; if (shouldCheckHalfs){ firstHalfExited = ( (_startLayout.width + _mainLayout.width/2) >= root.maxLength/2 ); secondHalfExited = ( (_endLayout.width + _mainLayout.width/2) >= root.maxLength/2 ); } if (latteView && ((contentsWidth >= root.maxLength) || firstHalfExited || secondHalfExited)) { autosize.updateIconSize(); } if (!animationSent) { animationSent = true; animations.needLength.addEvent(layoutsContainer); } layoutsContainer.updateSizeForAppletsInFill(); delayUpdateMaskArea.start(); } } onContentsHeightChanged: { if (root.isVertical){ var firstHalfExited = false; var secondHalfExited = false; if (shouldCheckHalfs){ firstHalfExited = ( (_startLayout.height + _mainLayout.height/2) >= root.maxLength/2 ); secondHalfExited = ( (_endLayout.height + _mainLayout.height/2) >= root.maxLength/2 ); } if (latteView && ((contentsHeight >= root.maxLength) || firstHalfExited || secondHalfExited)) { autosize.updateIconSize(); } if (!animationSent) { animationSent = true; animations.needLength.removeEvent(layoutsContainer); } layoutsContainer.updateSizeForAppletsInFill(); delayUpdateMaskArea.start(); } } onXChanged: root.updateEffectsArea(); onYChanged: root.updateEffectsArea(); EnvironmentActions { active: root.scrollAction !== LatteContainment.Types.ScrollNone || root.dragActiveWindowEnabled || root.closeActiveWindowEnabled alignment: _mainLayout.alignment } AppletsContainer { id: _startLayout beginIndex: 0 offset: root.totalPanelEdgeSpacing/2 alignment: { switch(plasmoid.location) { case PlasmaCore.Types.BottomEdge: return LatteCore.Types.BottomEdgeLeftAlign; case PlasmaCore.Types.TopEdge: return LatteCore.Types.TopEdgeLeftAlign; case PlasmaCore.Types.LeftEdge: return LatteCore.Types.LeftEdgeTopAlign; case PlasmaCore.Types.RightEdge: return LatteCore.Types.RightEdgeTopAlign; } return LatteCore.Types.BottomEdgeLeftAlign; } } AppletsContainer { id: _mainLayout beginIndex: 100 offset: centered ? appliedOffset : root.offsetFixed readonly property bool centered: (root.panelAlignment === LatteCore.Types.Center) || (root.panelAlignment === LatteCore.Types.Justify) readonly property bool reversed: Qt.application.layoutDirection === Qt.RightToLeft readonly property int appliedOffset: root.panelAlignment === LatteCore.Types.Justify ? 0 : root.offset alignment: { if (plasmoid.location === PlasmaCore.Types.LeftEdge) { if (centered) return LatteCore.Types.LeftEdgeCenterAlign; if (root.panelAlignment === LatteCore.Types.Top) return LatteCore.Types.LeftEdgeTopAlign; if (root.panelAlignment === LatteCore.Types.Bottom) return LatteCore.Types.LeftEdgeBottomAlign; } if (plasmoid.location === PlasmaCore.Types.RightEdge) { if (centered) return LatteCore.Types.RightEdgeCenterAlign; if (root.panelAlignment === LatteCore.Types.Top) return LatteCore.Types.RightEdgeTopAlign; if (root.panelAlignment === LatteCore.Types.Bottom) return LatteCore.Types.RightEdgeBottomAlign; } if (plasmoid.location === PlasmaCore.Types.BottomEdge) { if (centered) return LatteCore.Types.BottomEdgeCenterAlign; if ((root.panelAlignment === LatteCore.Types.Left && !reversed) || (root.panelAlignment === LatteCore.Types.Right && reversed)) { return LatteCore.Types.BottomEdgeLeftAlign; } if ((root.panelAlignment === LatteCore.Types.Right && !reversed) || (root.panelAlignment === LatteCore.Types.Left && reversed)) { return LatteCore.Types.BottomEdgeRightAlign; } } if (plasmoid.location === PlasmaCore.Types.TopEdge) { if (centered) return LatteCore.Types.TopEdgeCenterAlign; if ((root.panelAlignment === LatteCore.Types.Left && !reversed) || (root.panelAlignment === LatteCore.Types.Right && reversed)) { return LatteCore.Types.TopEdgeLeftAlign; } if ((root.panelAlignment === LatteCore.Types.Right && !reversed) || (root.panelAlignment === LatteCore.Types.Left && reversed)) { return LatteCore.Types.TopEdgeRightAlign; } } return LatteCore.Types.BottomEdgeCenterAlign; } transitions: Transition { enabled: editModeVisual.plasmaEditMode AnchorAnimation { duration: 0.8 * animations.duration.proposed easing.type: Easing.OutCubic } } } AppletsContainer { id: _endLayout beginIndex: 200 offset: root.totalPanelEdgeSpacing/2 alignment: { switch(plasmoid.location) { case PlasmaCore.Types.BottomEdge: return LatteCore.Types.BottomEdgeRightAlign; case PlasmaCore.Types.TopEdge: return LatteCore.Types.TopEdgeRightAlign; case PlasmaCore.Types.LeftEdge: return LatteCore.Types.LeftEdgeBottomAlign; case PlasmaCore.Types.RightEdge: return LatteCore.Types.RightEdgeBottomAlign; } return LatteCore.Types.BottomEdgeLeftAlign; } } function updateSizeForAppletsInFill() { if (!updateSizeForAppletsInFillTimer.running) { updateSizeForAppletsInFillTimer.start(); } } Connections { - target: container + target: metrics onIconSizeAnimationEnded: delayUpdateMaskArea.start(); } //! This timer is needed in order to reduce the calls to heavy cpu function //! HeuristicTools.updateSizeForAppletsInFill() Timer{ id: updateSizeForAppletsInFillTimer interval: 10 onTriggered: HeuristicTools.updateSizeForAppletsInFill(); } //! This timer is needed in order to update mask area after ContentsWidth/Height and iconSize changes Timer{ id:delayUpdateMaskArea repeat:false; interval:300; onTriggered: { if (layoutsContainer.animationSent) { animations.needLength.removeEvent(layoutsContainer); layoutsContainer.animationSent = false; } visibilityManager.updateMaskArea(); if (root.debugModeTimers) { console.log("LayoutsContainer timer: delayUpdateMaskArea called..."); } } } } diff --git a/containment/package/contents/ui/layouts/indicator/Bridge.qml b/containment/package/contents/ui/layouts/indicator/Bridge.qml index 0e5c86a4..122d7785 100644 --- a/containment/package/contents/ui/layouts/indicator/Bridge.qml +++ b/containment/package/contents/ui/layouts/indicator/Bridge.qml @@ -1,77 +1,77 @@ /* * Copyright 2019 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 . */ import QtQuick 2.7 Item{ id: indicatorBridge anchors.fill: parent readonly property bool active: true /* Indicators Properties in order use them*/ readonly property bool isTask: false readonly property bool isApplet: false readonly property bool isEmptySpace: true /*since 0.9.3*/ readonly property bool isLauncher: false readonly property bool isStartup: false readonly property bool isWindow: false readonly property bool isActive: false readonly property bool isGroup: false readonly property bool isHovered: false readonly property bool isMinimized: false readonly property bool isPressed: mainArea.pressed readonly property bool inAttention: false readonly property bool inRemoving: false readonly property bool isSquare: false readonly property bool hasActive: false readonly property bool hasMinimized: false readonly property bool hasShown: false readonly property int windowsCount: 0 readonly property int windowsMinimizedCount: 0 - readonly property int currentIconSize: container.iconSize - readonly property int maxIconSize: container.maxIconSize + readonly property int currentIconSize: metrics.iconSize + readonly property int maxIconSize: metrics.maxIconSize readonly property real scaleFactor: 1 readonly property real panelOpacity: root.currentPanelOpacity readonly property color shadowColor: root.appShadowColorSolid readonly property bool animationsEnabled: animations.active readonly property real durationTime: animations.speedFactor.current readonly property bool progressVisible: false /*since 0.9.2*/ readonly property real progress: 0 /*since 0.9.2*/ readonly property int screenEdgeMargin: 0 /*since 0.10*/ readonly property QtObject palette: colorizerManager.applyTheme //!icon colors property color iconBackgroundColor: "brown" property color iconGlowColor: "pink" //! grouped options readonly property Item shared: indicators readonly property QtObject configuration: indicators.configuration readonly property QtObject resources: indicators.resources } diff --git a/containment/package/contents/ui/main.qml b/containment/package/contents/ui/main.qml index 906f04f4..5ed77c8a 100644 --- a/containment/package/contents/ui/main.qml +++ b/containment/package/contents/ui/main.qml @@ -1,1823 +1,1823 @@ /* * Copyright 2016 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 . */ import QtQuick 2.8 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 import QtGraphicalEffects 1.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.plasmoid 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.components 1.0 as LatteComponents import org.kde.latte.private.app 0.1 as LatteApp import org.kde.latte.private.containment 0.1 as LatteContainment import "abilities" as Ability import "applet" as Applet import "colorizer" as Colorizer import "editmode" as EditMode import "indicators" as Indicators import "layouts" as Layouts import "../code/LayoutManager.js" as LayoutManager Item { id: root objectName: "containmentViewLayout" LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft && !root.isVertical LayoutMirroring.childrenInherit: true //// BEGIN SIGNALS signal clearZoomSignal(); signal destroyInternalViewSplitters(); signal emptyAreasWheel(QtObject wheel); signal separatorsUpdated(); signal signalActivateEntryAtIndex(int entryIndex); signal signalNewInstanceForEntryAtIndex(int entryIndex); signal updateEffectsArea(); signal updateIndexes(); signal updateScale(int delegateIndex, real newScale, real step); signal broadcastedToApplet(string pluginName, string action, variant value); //// END SIGNALS ////BEGIN properties property bool debugMode: Qt.application.arguments.indexOf("--graphics")>=0 property bool debugModeLocalGeometry: Qt.application.arguments.indexOf("--localgeometry")>=0 property bool debugModeSpacers: Qt.application.arguments.indexOf("--spacers")>=0 property bool debugModeTimers: Qt.application.arguments.indexOf("--timers")>=0 property bool debugModeWindow: Qt.application.arguments.indexOf("--with-window")>=0 property bool debugModeOverloadedIcons: Qt.application.arguments.indexOf("--overloaded-icons")>=0 readonly property int version: LatteCore.Environment.makeVersion(0,9,4) property bool globalDirectRender: false //it is used as a globalDirectRender for all elements in the dock property int directRenderAnimationTime: 0 property bool addLaunchersMessage: false property bool addLaunchersInTaskManager: plasmoid.configuration.addLaunchersInTaskManager property bool backgroundOnlyOnMaximized: plasmoid.configuration.backgroundOnlyOnMaximized property bool behaveAsPlasmaPanel: { if (!LatteCore.WindowSystem.compositingActive) { //! In NOCOMPOSITING mode VIEWS should behave as real windows and that way //! we gain also the snapping features from KWin return true; } if (!latteView || !latteView.visibility) { return false; } if (screenEdgeMarginEnabled && plasmoid.configuration.fittsLawIsRequested) { //! dont use when floating views are requesting Fitt's Law return false; } return (visibilityManager.panelIsBiggerFromIconSize && (maxZoomFactor === 1.0) && (plasmoid.configuration.alignment === LatteCore.Types.Justify) && !root.editMode && !visibilityManager.inLocationAnimation); } property int viewType: { if ((plasmoid.configuration.alignment === LatteCore.Types.Justify) && (plasmoid.configuration.useThemePanel) && (plasmoid.configuration.panelSize === 100) && (maxZoomFactor === 1.0)) { return LatteCore.Types.PanelView; } return LatteCore.Types.DockView; } property bool blurEnabled: plasmoid.configuration.blurEnabled && (!forceTransparentPanel || forcePanelForBusyBackground) readonly property bool ignoreRegularFilesDragging: !root.editMode && (dragInfo.computationsAreValid || foreDropArea.dragInfo.computationsAreValid) && !root.dragInfo.isPlasmoid && !root.dragInfo.onlyLaunchers readonly property Item dragInfo: Item { property bool entered: backDropArea.dragInfo.entered || foreDropArea.dragInfo.entered property bool isTask: backDropArea.dragInfo.isTask || foreDropArea.dragInfo.isTask property bool isPlasmoid: backDropArea.dragInfo.isPlasmoid || foreDropArea.dragInfo.isPlasmoid property bool isSeparator: backDropArea.dragInfo.isSeparator || foreDropArea.dragInfo.isSeparator property bool isLatteTasks: backDropArea.dragInfo.isLatteTasks || foreDropArea.dragInfo.isLatteTasks property bool onlyLaunchers: backDropArea.dragInfo.onlyLaunchers || foreDropArea.dragInfo.onlyLaunchers // onIsPlasmoidChanged: console.log("isPlasmoid :: " + backDropArea.dragInfo.isPlasmoid + " _ " + foreDropArea.dragInfo.isPlasmoid ); // onEnteredChanged: console.log("entered :: " + backDropArea.dragInfo.entered + " _ " + foreDropArea.dragInfo.entered ); } property bool containsOnlyPlasmaTasks: false //this is flag to indicate when from tasks only a plasma based one is found property bool dockContainsMouse: latteView && latteView.visibility ? latteView.visibility.containsMouse : false property bool disablePanelShadowMaximized: plasmoid.configuration.disablePanelShadowForMaximized && LatteCore.WindowSystem.compositingActive property bool drawShadowsExternal: panelShadowsActive && behaveAsPlasmaPanel && !visibilityManager.inTempHiding property bool editMode: editModeVisual.inEditMode property bool windowIsTouching: latteView && latteView.windowsTracker && (latteView.windowsTracker.currentScreen.activeWindowTouching || hasExpandedApplet) property bool forceSolidPanel: (latteView && latteView.visibility && LatteCore.WindowSystem.compositingActive && !inConfigureAppletsMode && userShowPanelBackground && ( (plasmoid.configuration.solidBackgroundForMaximized && !(hasExpandedApplet && !plasmaBackgroundForPopups) && latteView.windowsTracker.currentScreen.existsWindowTouching) || (hasExpandedApplet && plasmaBackgroundForPopups) )) || solidBusyForTouchingBusyVerticalView || plasmaStyleBusyForTouchingBusyVerticalView || !LatteCore.WindowSystem.compositingActive property bool forceTransparentPanel: root.backgroundOnlyOnMaximized && latteView && latteView.visibility && LatteCore.WindowSystem.compositingActive && !inConfigureAppletsMode && !forceSolidPanel && !latteView.windowsTracker.currentScreen.existsWindowTouching && !(windowColors === LatteContainment.Types.ActiveWindowColors && selectedWindowsTracker.existsWindowActive) property bool forcePanelForBusyBackground: userShowPanelBackground && (root.themeColors === LatteContainment.Types.SmartThemeColors) && ( (root.forceTransparentPanel && colorizerManager.backgroundIsBusy) || normalBusyForTouchingBusyVerticalView ) property bool normalBusyForTouchingBusyVerticalView: (latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers isBusy transparency*/ && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteContainment.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized /*&& !plasmoid.configuration.solidBackgroundForMaximized && !plasmaBackgroundForPopups*/) property bool solidBusyForTouchingBusyVerticalView: false //DISABLED, until to check if the normalBusyForTouchingBusyVerticalView is enough to catch and handle the case /*(latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers solidness*/ /* && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteContainment.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized && plasmoid.configuration.solidBackgroundForMaximized && !plasmaBackgroundForPopups)*/ property bool plasmaStyleBusyForTouchingBusyVerticalView: false //DISABLED, until to check if the normalBusyForTouchingBusyVerticalView is enough to catch and handle the case //(latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers solidness*/ /* && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteContainment.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized && plasmaBackgroundForPopups)*/ property bool hideThickScreenGap: screenEdgeMarginEnabled && plasmoid.configuration.hideScreenGapForMaximized && latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.existsWindowMaximized property bool hideLengthScreenGaps: hideThickScreenGap && (latteView.visibility.mode === LatteCore.Types.AlwaysVisible || latteView.visibility.mode === LatteCore.Types.WindowsGoBelow) && (plasmoid.configuration.alignment === LatteCore.Types.Justify) && plasmoid.configuration.maxLength>85 && !root.editMode property int themeColors: plasmoid.configuration.themeColors property int windowColors: plasmoid.configuration.windowColors property bool colorizerEnabled: themeColors !== LatteContainment.Types.PlasmaThemeColors || windowColors !== LatteContainment.Types.NoneWindowColors property bool plasmaBackgroundForPopups: plasmoid.configuration.plasmaBackgroundForPopups readonly property bool hasExpandedApplet: latteView && latteView.extendedInterface.hasExpandedApplet; readonly property bool hasUserSpecifiedBackground: (latteView && latteView.layout && latteView.layout.background.startsWith("/")) ? true : false readonly property bool inConfigureAppletsMode: root.editMode && (plasmoid.configuration.inConfigureAppletsMode || !LatteCore.WindowSystem.compositingActive) readonly property bool parabolicEffectEnabled: zoomFactor>1 && !inConfigureAppletsMode property bool dockIsShownCompletely: !(dockIsHidden || inSlidingIn || inSlidingOut) && !root.editMode property bool closeActiveWindowEnabled: plasmoid.configuration.closeActiveWindowEnabled property bool dragActiveWindowEnabled: plasmoid.configuration.dragActiveWindowEnabled property bool immutable: plasmoid.immutable property bool inFullJustify: (plasmoid.configuration.alignment === LatteCore.Types.Justify) && (maxLengthPerCentage===100) property bool inSlidingIn: visibilityManager ? visibilityManager.inSlidingIn : false property bool inSlidingOut: visibilityManager ? visibilityManager.inSlidingOut : false property bool inStartup: true property bool isHalfShown: false //is used to disable the zoom hovering effect at sliding in-out the dock property bool isHorizontal: plasmoid.formFactor === PlasmaCore.Types.Horizontal property bool isReady: !(dockIsHidden || inSlidingIn || inSlidingOut) property bool isVertical: !isHorizontal property bool isHovered: latteApplet ? ((latteAppletHoveredIndex !== -1) || (layoutsContainer.hoveredIndex !== -1)) //|| wholeArea.containsMouse : (layoutsContainer.hoveredIndex !== -1) //|| wholeArea.containsMouse property bool mouseWheelActions: plasmoid.configuration.mouseWheelActions property bool onlyAddingStarup: true //is used for the initialization phase in startup where there aren't removals, this variable provides a way to grow icon size property bool shrinkThickMargins: plasmoid.configuration.shrinkThickMargins property bool showLatteShortcutBadges: false property bool showAppletShortcutBadges: false property bool showMetaBadge: false property int applicationLauncherId: -1 //FIXME: possibly this is going to be the default behavior, this user choice //has been dropped from the Dock Configuration Window //property bool smallAutomaticIconJumps: plasmoid.configuration.smallAutomaticIconJumps property bool smallAutomaticIconJumps: true property bool userShowPanelBackground: LatteCore.WindowSystem.compositingActive ? plasmoid.configuration.useThemePanel : true property bool useThemePanel: noApplets === 0 || !LatteCore.WindowSystem.compositingActive ? true : (plasmoid.configuration.useThemePanel || plasmoid.configuration.solidBackgroundForMaximized) property bool plasma515: LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,15,0) property bool plasma518: LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,18,0) property alias hoveredIndex: layoutsContainer.hoveredIndex property alias directRenderDelayerIsRunning: directRenderDelayerForEnteringTimer.running readonly property int minAppletLengthInConfigure: 64 readonly property int maxJustifySplitterSize: 96 property int latteAppletPos: -1 property int minLengthPerCentage: plasmoid.configuration.minLength property int maxLengthPerCentage: hideLengthScreenGaps ? 100 : plasmoid.configuration.maxLength property int minLength: { if (root.isHorizontal) { return behaveAsPlasmaPanel && LatteCore.WindowSystem.compositingActive ? width : width * (minLengthPerCentage/100) } else { return behaveAsPlasmaPanel && LatteCore.WindowSystem.compositingActive ? height : height * (minLengthPerCentage/100) } } property int maxLength: { if (root.isHorizontal) { return behaveAsPlasmaPanel ? width : width * (maxLengthPerCentage/100) } else { return behaveAsPlasmaPanel ? height : height * (maxLengthPerCentage/100) } } property int scrollAction: plasmoid.configuration.scrollAction property bool panelOutline: plasmoid.configuration.panelOutline property int panelEdgeSpacing: Math.max(panelBoxBackground.lengthMargins, 1.5*appShadowSize) property int panelTransparency: plasmoid.configuration.panelTransparency //user set property int currentPanelTransparency: 0 //application override readonly property real currentPanelOpacity: currentPanelTransparency/100 property bool panelShadowsActive: { if (!userShowPanelBackground) { return false; } if (inConfigureAppletsMode) { return plasmoid.configuration.panelShadows; } var forcedNoShadows = (plasmoid.configuration.panelShadows && disablePanelShadowMaximized && latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.activeWindowMaximized); if (forcedNoShadows) { return false; } var transparencyCheck = (blurEnabled || (!blurEnabled && currentPanelTransparency>20)); //! Draw shadows for isBusy state only when current panelTransparency is greater than 10% if (plasmoid.configuration.panelShadows && root.forcePanelForBusyBackground && transparencyCheck) { return true; } if (( (plasmoid.configuration.panelShadows && !root.backgroundOnlyOnMaximized) || (plasmoid.configuration.panelShadows && root.backgroundOnlyOnMaximized && !root.forceTransparentPanel)) && !forcedNoShadows) { return true; } if (hasExpandedApplet && plasmaBackgroundForPopups) { return true; } return false; } property int appShadowOpacity: (plasmoid.configuration.shadowOpacity/100) * 255 - property int appShadowSize: enableShadows ? (0.5*container.iconSize) * (plasmoid.configuration.shadowSize/100) : 0 - property int appShadowSizeOriginal: enableShadows ? (0.5*container.maxIconSize) * (plasmoid.configuration.shadowSize/100) : 0 + property int appShadowSize: enableShadows ? (0.5*metrics.iconSize) * (plasmoid.configuration.shadowSize/100) : 0 + property int appShadowSizeOriginal: enableShadows ? (0.5*metrics.maxIconSize) * (plasmoid.configuration.shadowSize/100) : 0 property string appChosenShadowColor: { if (plasmoid.configuration.shadowColorType === LatteContainment.Types.ThemeColorShadow) { var strC = String(theme.textColor); return strC.indexOf("#") === 0 ? strC.substr(1) : strC; } else if (plasmoid.configuration.shadowColorType === LatteContainment.Types.UserColorShadow) { return plasmoid.configuration.shadowColor; } // default shadow color return "080808"; } property string appShadowColor: "#" + decimalToHex(appShadowOpacity) + appChosenShadowColor property string appShadowColorSolid: "#" + appChosenShadowColor property int totalPanelEdgeSpacing: 0 //this is set by PanelBox property int offset: { if (behaveAsPlasmaPanel) { return 0; } if (root.isHorizontal) { return width * (plasmoid.configuration.offset/100); } else { height * (plasmoid.configuration.offset/100) } } //center the layout correctly when the user uses an offset property int offsetFixed: (offset===0 || panelAlignment === LatteCore.Types.Center || plasmoid.configuration.alignment === LatteCore.Types.Justify)? offset : offset+panelMarginLength/2+totalPanelEdgeSpacing/2 property int realPanelSize: 0 property int realPanelLength: 0 property int realPanelThickness: 0 //this is set by the PanelBox property int panelThickMarginBase: 0 property int panelThickMarginHigh: 0 property int panelMarginLength: 0 property int panelShadow: 0 //shadowsSize property int editShadow: { if (!LatteCore.WindowSystem.compositingActive) { return 0; } else if (latteView && latteView.screenGeometry) { return latteView.screenGeometry.height/90; } else { return 7; } } property int themePanelThickness: { var panelBase = root.panelThickMarginHigh + root.panelThickMarginBase; var margin = shrinkThickMargins ? 0 : thickMargins + localScreenEdgeMargin; - var maxPanelSize = (container.iconSize + margin) - panelBase; + var maxPanelSize = (metrics.iconSize + margin) - panelBase; var percentage = LatteCore.WindowSystem.compositingActive ? plasmoid.configuration.panelSize/100 : 1; return Math.max(panelBase, panelBase + percentage*maxPanelSize); } - property int lengthIntMargin: lengthIntMarginFactor * container.iconSize - property int lengthExtMargin: lengthExtMarginFactor * container.iconSize + property int lengthIntMargin: lengthIntMarginFactor * metrics.iconSize + property int lengthExtMargin: lengthExtMarginFactor * metrics.iconSize property real lengthIntMarginFactor: indicators.isEnabled ? indicators.padding : 0 property real lengthExtMarginFactor: plasmoid.configuration.lengthExtMargin / 100 property real lengthAppletIntMarginFactor: indicators.infoLoaded ? indicators.info.appletLengthPadding : -1 property real thickMarginFactor: { if (shrinkThickMargins) { return indicators.info.minThicknessPadding; } //0.075 old statesLineSize and 0.06 old default thickMargin return Math.max(indicators.info.minThicknessPadding, plasmoid.configuration.thickMargin / 100) } - property int thickMargin: thickMarginFactor * container.iconSize + property int thickMargin: thickMarginFactor * metrics.iconSize property bool screenEdgeMarginEnabled: plasmoid.configuration.screenEdgeMargin >= 0 && !plasmoid.configuration.shrinkThickMargins property int screenEdgeMargin: { //! is used for window geometry calculations if (!screenEdgeMarginEnabled || (hideThickScreenGap && localScreenEdgeMargin === 0)) { /*window geometry is updated after the local screen margin animation was zeroed*/ return 0; } return plasmoid.configuration.screenEdgeMargin; } property int localScreenEdgeMargin: (screenEdgeMarginEnabled && behaveAsPlasmaPanel && !root.editMode) || !screenEdgeMarginEnabled || hideThickScreenGap ? 0 : plasmoid.configuration.screenEdgeMargin //! thickness margins are always two and equal in order for items //! to be always correctly centered property int thickMargins: 2 * thickMargin //it is used in order to not break the calculations for the thickness placement //especially in automatic icon sizes calculations - property int maxThickMargin: thickMarginFactor * container.maxIconSize + property int maxThickMargin: thickMarginFactor * metrics.maxIconSize property int lengthMargin: lengthIntMargin + lengthExtMargin property int lengthMargins: 2 * lengthMargin property int widthMargins: root.isVertical ? thickMargins : lengthMargins property int heightMargins: root.isHorizontal ? thickMargins : lengthMargins ///FIXME: I can't remember why this is needed, maybe for the anchorings!!! In order for the Double Layout to not mess the anchorings... //property int layoutsContainer.mainLayoutPosition: !plasmoid.immutable ? LatteCore.Types.Center : (root.isVertical ? LatteCore.Types.Top : LatteCore.Types.Left) //property int panelAlignment: plasmoid.configuration.alignment !== LatteCore.Types.Justify ? plasmoid.configuration.alignment : layoutsContainer.mainLayoutPosition property int panelAlignment: !root.inConfigureAppletsMode ? plasmoid.configuration.alignment : ( plasmoid.configuration.alignment === LatteCore.Types.Justify ? LatteCore.Types.Center : plasmoid.configuration.alignment ) property int panelUserSetAlignment: plasmoid.configuration.alignment property real zoomFactor: LatteCore.WindowSystem.compositingActive && animations.active ? ( 1 + (plasmoid.configuration.zoomLevel / 20) ) : 1 readonly property string plasmoidName: "org.kde.latte.plasmoid" property var badgesForActivate: { if (!shortcutsEngine) { return ['1','2','3','4','5','6','7','8','9','0', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.']; } return shortcutsEngine.badgesForActivate; } property var iconsArray: [16, 22, 32, 48, 64, 96, 128, 256] property Item dragOverlay property Item toolBox property Item latteAppletContainer property Item latteApplet readonly property alias animations: _animations readonly property alias appletsRecords: _appletsRecords readonly property alias autosize: _autosize - readonly property alias container: _container readonly property alias indicatorsManager: indicators + readonly property alias metrics: _metrics readonly property alias parabolicManager: _parabolicManager readonly property alias maskManager: visibilityManager readonly property alias layoutsContainerItem: layoutsContainer property QtObject latteView: null property QtObject shortcutsEngine: null property QtObject themeExtended: null property QtObject universalSettings: null property QtObject layoutsManager: null property QtObject viewLayout: latteView && latteView.layout ? latteView.layout : null property QtObject selectedWindowsTracker: { if (latteView && latteView.windowsTracker) { switch(plasmoid.configuration.activeWindowFilter) { case LatteContainment.Types.ActiveInCurrentScreen: return latteView.windowsTracker.currentScreen; case LatteContainment.Types.ActiveFromAllScreens: return latteView.windowsTracker.allScreens; } } return null; } // TO BE DELETED, if not needed: property int counter:0; ///BEGIN properties provided to Latte Plasmoid //shadows for applets, it should be removed as the appleitems don't need it any more property bool badges3DStyle: universalSettings ? universalSettings.badges3DStyle : true property bool enableShadows: plasmoid.configuration.appletShadowsEnabled property bool dockIsHidden: latteView ? latteView.visibility.isHidden : true property bool titleTooltips: plasmoid.configuration.titleTooltips property bool unifiedGlobalShortcuts: true readonly property bool hasInternalSeparator: latteApplet ? latteApplet.hasInternalSeparator : false property int latteAppletHoveredIndex: latteApplet ? latteApplet.hoveredIndex : -1 property int tasksCount: latteApplet ? latteApplet.tasksCount : 0 property real maxZoomFactor: Math.max(zoomFactor, _appletsRecords.maxInnerZoomFactor) property rect screenGeometry: latteView ? latteView.screenGeometry : plasmoid.screenGeometry readonly property color minimizedDotColor: colorizerManager.minimizedDotColor ///END properties from latteApplet Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground //// BEGIN properties in functions property int noApplets: { var count1 = 0; var count2 = 0; count1 = layoutsContainer.mainLayout.children.length; var tempLength = layoutsContainer.mainLayout.children.length; for (var i=tempLength-1; i>=0; --i) { var applet = layoutsContainer.mainLayout.children[i]; if (applet && (applet === dndSpacer || applet === lastSpacer || applet.isInternalViewSplitter)) count1--; } count2 = layoutsContainer.endLayout.children.length; tempLength = layoutsContainer.endLayout.children.length; for (var i=tempLength-1; i>=0; --i) { var applet = layoutsContainer.endLayout.children[i]; if (applet && (applet === dndSpacer || applet === lastSpacer || applet.isInternalViewSplitter)) count2--; } return (count1 + count2); } ///The index of user's current icon size property int currentIconIndex:{ for(var i=iconsArray.length-1; i>=0; --i){ - if(iconsArray[i] === container.iconSize){ + if(iconsArray[i] === metrics.iconSize){ return i; } } return 3; } //// END properties in functions ////////////////END properties //// BEGIN OF Behaviors Behavior on thickMargin { NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } Behavior on lengthIntMargin { NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } Behavior on lengthExtMargin { NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } Behavior on localScreenEdgeMargin { enabled: !root.behaveAsPlasmaPanel && !editModeVisual.editAnimationRunning /*avoid slide-out animation when from editMode we change to real floating*/ NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } Behavior on offset { enabled: editModeVisual.editAnimationInFullThickness NumberAnimation { id: offsetAnimation duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } //// END OF Behaviors //////////////START OF CONNECTIONS onEditModeChanged: { if (editMode) { visibilityManager.updateMaskArea(); clearZoom(); } else { layoutsContainer.updateSizeForAppletsInFill(); } //! This is used in case the dndspacer has been left behind //! e.g. the user drops a folder and a context menu is appearing //! but the user decides to not make a choice for the applet type if (dndSpacer.parent !== root) { dndSpacer.parent = root; } } onInConfigureAppletsModeChanged: { if (inConfigureAppletsMode && panelUserSetAlignment===LatteCore.Types.Justify) { joinLayoutsToMainLayout(); } else if (!inConfigureAppletsMode) { splitMainLayoutToLayouts(); } updateIndexes(); } //! It is used only when the user chooses different alignment types //! and not during startup onPanelUserSetAlignmentChanged: { if (!root.editMode) { return; } if (!inConfigureAppletsMode){ if (panelUserSetAlignment===LatteCore.Types.Justify) { addInternalViewSplitters(); splitMainLayoutToLayouts(); } else { joinLayoutsToMainLayout(); root.destroyInternalViewSplitters(); } } else { if (panelUserSetAlignment===LatteCore.Types.Justify) { addInternalViewSplitters(); } else { root.destroyInternalViewSplitters(); } } LayoutManager.save(); updateIndexes(); } onLatteViewChanged: { if (latteView) { latteView.onXChanged.connect(visibilityManager.updateMaskArea); latteView.onYChanged.connect(visibilityManager.updateMaskArea); latteView.onWidthChanged.connect(visibilityManager.updateMaskArea); latteView.onHeightChanged.connect(visibilityManager.updateMaskArea); latteView.positioner.hideDockDuringLocationChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.visibility.onContainsMouseChanged.connect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.connect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.connect(visibilityManager.slotMustBeShown); updateContainsOnlyPlasmaTasks(); } } onDockContainsMouseChanged: { if (!dockContainsMouse) { initializeHoveredIndexes(); } } onMaxLengthChanged: { layoutsContainer.updateSizeForAppletsInFill(); } onToolBoxChanged: { if (toolBox) { toolBox.visible = false; } } onIsReadyChanged: { if (isReady && !titleTooltipDialog.visible && titleTooltipDialog.activeItemHovered){ titleTooltipDialog.show(titleTooltipDialog.activeItem, titleTooltipDialog.activeItemText); } } onIsVerticalChanged: { if (isVertical) { if (plasmoid.configuration.alignment === LatteCore.Types.Left) plasmoid.configuration.alignment = LatteCore.Types.Top; else if (plasmoid.configuration.alignment === LatteCore.Types.Right) plasmoid.configuration.alignment = LatteCore.Types.Bottom; } else { if (plasmoid.configuration.alignment === LatteCore.Types.Top) plasmoid.configuration.alignment = LatteCore.Types.Left; else if (plasmoid.configuration.alignment === LatteCore.Types.Bottom) plasmoid.configuration.alignment = LatteCore.Types.Right; } } Component.onCompleted: { // currentLayout.isLayoutHorizontal = isHorizontal LayoutManager.plasmoid = plasmoid; LayoutManager.root = root; - LayoutManager.container = container; LayoutManager.layout = layoutsContainer.mainLayout; LayoutManager.layoutS = layoutsContainer.startLayout; LayoutManager.layoutE = layoutsContainer.endLayout; LayoutManager.lastSpacer = lastSpacer; + LayoutManager.metrics = metrics; upgrader_v010_alignment(); LayoutManager.restore(); plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; inStartupTimer.start(); } Component.onDestruction: { console.debug("Destroying Latte Dock Containment ui..."); if (latteView) { latteView.onXChanged.disconnect(visibilityManager.updateMaskArea); latteView.onYChanged.disconnect(visibilityManager.updateMaskArea); latteView.onWidthChanged.disconnect(visibilityManager.updateMaskArea); latteView.onHeightChanged.disconnect(visibilityManager.updateMaskArea); latteView.positioner.hideDockDuringLocationChangeStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); if (latteView.visibility) { latteView.visibility.onContainsMouseChanged.disconnect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.disconnect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.disconnect(visibilityManager.slotMustBeShown); } } } Containment.onAppletAdded: { addApplet(applet, x, y); console.log(applet.pluginName); LayoutManager.save(); updateIndexes(); } Containment.onAppletRemoved: { LayoutManager.removeApplet(applet); var flexibleFound = false; for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { var applet = layoutsContainer.mainLayout.children[i].applet; if (applet && ((root.isHorizontal && applet.Layout.fillWidth) || (!root.isHorizontal && applet.Layout.fillHeight)) && applet.visible) { flexibleFound = true; break } } if (!flexibleFound) { lastSpacer.parent = layoutsContainer.mainLayout; } console.log(applet.pluginName); LayoutManager.save(); updateIndexes(); updateContainsOnlyPlasmaTasks(); } Plasmoid.onUserConfiguringChanged: { if (plasmoid.immutable) { if (dragOverlay) { dragOverlay.destroy(); } return; } // console.debug("user configuring", plasmoid.userConfiguring) if (plasmoid.userConfiguring) { // console.log("applets------"); for (var i = 0; i < plasmoid.applets.length; ++i) { // console.log("applet:"+i); plasmoid.applets[i].expanded = false; } if (!dragOverlay) { var component = Qt.createComponent("editmode/ConfigOverlay.qml"); if (component.status == Component.Ready) { dragOverlay = component.createObject(root); } else { console.log("Could not create ConfigOverlay"); console.log(component.errorString()); } component.destroy(); } else { dragOverlay.visible = true; } } else { if (dragOverlay) { dragOverlay.visible = false; dragOverlay.destroy(); } } } Plasmoid.onImmutableChanged: { plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; ///Set Preferred Sizes/// ///Notice: they are set here because if they are set with a binding ///they break the !immutable experience, the latteView becomes too small ///to add applets /* if (plasmoid.immutable) { if(root.isHorizontal) { root.Layout.preferredWidth = (plasmoid.configuration.alignment === LatteCore.Types.Justify ? layoutsContainer.width + 0.5*iconMargin : layoutsContainer.mainLayout.width + iconMargin); } else { root.Layout.preferredHeight = (plasmoid.configuration.alignment === LatteCore.Types.Justify ? layoutsContainer.height + 0.5*iconMargin : layoutsContainer.mainLayout.height + iconMargin); } } else { if (root.isHorizontal) { root.Layout.preferredWidth = Screen.width; } else { root.Layout.preferredHeight = Screen.height; } }*/ visibilityManager.updateMaskArea(); } //////////////END OF CONNECTIONS //////////////START OF FUNCTIONS function addApplet(applet, x, y) { var container = appletContainerComponent.createObject(dndSpacer.parent) container.applet = applet; applet.parent = container.appletWrapper; applet.anchors.fill = container.appletWrapper; applet.visible = true; // don't show applet if it chooses to be hidden but still make it // accessible in the panelcontroller container.visible = Qt.binding(function() { return applet.status !== PlasmaCore.Types.HiddenStatus || (!plasmoid.immutable && root.inConfigureAppletsMode) }) addContainerInLayout(container, applet, x, y); updateContainsOnlyPlasmaTasks(); } function addContainerInLayout(container, applet, x, y){ // Is there a DND placeholder? Replace it! if ( (dndSpacer.parent === layoutsContainer.mainLayout) || (dndSpacer.parent === layoutsContainer.startLayout) || (dndSpacer.parent===layoutsContainer.endLayout)) { LayoutManager.insertBeforeForLayout(dndSpacer.parent, dndSpacer, container); dndSpacer.parent = root; return; // If the provided position is valid, use it. } else if (x >= 0 && y >= 0) { var index = LayoutManager.insertAtCoordinates2(container, x , y); // Fall through to determining an appropriate insert position. } else { var before = null; container.animationsEnabled = false; if (lastSpacer.parent === layoutsContainer.mainLayout) { before = lastSpacer; } // Insert icons to the left of whatever is at the center (usually a Task Manager), // if it exists. // FIXME TODO: This is a real-world fix to produce a sensible initial position for // launcher icons added by launcher menu applets. The basic approach has been used // since Plasma 1. However, "add launcher to X" is a generic-enough concept and // frequent-enough occurrence that we'd like to abstract it further in the future // and get rid of the ugliness of parties external to the containment adding applets // of a specific type, and the containment caring about the applet type. In a better // system the containment would be informed of requested launchers, and determine by // itself what it wants to do with that information. if (applet.pluginName == "org.kde.plasma.icon") { var middle = layoutsContainer.mainLayout.childAt(root.width / 2, root.height / 2); if (middle) { before = middle; } // Otherwise if lastSpacer is here, enqueue before it. } if (before) { LayoutManager.insertBefore(before, container); // Fall through to adding at the end. } else { container.parent = layoutsContainer.mainLayout; } } //Important, removes the first children of the layoutsContainer.mainLayout after the first //applet has been added lastSpacer.parent = root; updateIndexes(); } function addInternalViewSplitters(){ if (internalViewSplittersCount() === 0) { addInternalViewSplitter(plasmoid.configuration.splitterPosition); addInternalViewSplitter(plasmoid.configuration.splitterPosition2); } } function addInternalViewSplitter(pos){ var splittersCount = internalViewSplittersCount(); if(splittersCount<2){ var container = appletContainerComponent.createObject(root); container.internalSplitterId = splittersCount+1; container.visible = true; if(pos>=0 ){ LayoutManager.insertAtIndex(container, pos); } else { LayoutManager.insertAtIndex(container, Math.floor(layoutsContainer.mainLayout.count / 2)); } } } //! it is used in order to check the right click position //! the only way to take into account the visual appearance //! of the applet (including its spacers) function appletContainsPos(appletId, pos){ for (var i = 0; i < layoutsContainer.startLayout.children.length; ++i) { var child = layoutsContainer.startLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { var child = layoutsContainer.mainLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } for (var i = 0; i < layoutsContainer.endLayout.children.length; ++i) { var child = layoutsContainer.endLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } return false; } function checkLastSpacer() { lastSpacer.parent = root var expands = false; if (isHorizontal) { for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if (item.Layout && item.Layout.fillWidth) { expands = true; } } } else { for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if (item.Layout && item.Layout.fillHeight) { expands = true; } } } if (!expands) { lastSpacer.parent = layoutsContainer.mainLayout } } function clearZoom(){ if (latteApplet){ latteApplet.clearZoom(); } root.clearZoomSignal(); } function containmentActions(){ return latteView.containmentActions(); } function decimalToHex(d, padding) { var hex = Number(d).toString(16); padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding; while (hex.length < padding) { hex = "0" + hex; } return hex; } function disableDirectRender(){ // root.globalDirectRender = false; } function internalViewSplittersCount(){ var splitters = 0; for (var container in layoutsContainer.startLayout.children) { var item = layoutsContainer.startLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } for (var container in layoutsContainer.endLayout.children) { var item = layoutsContainer.endLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } return splitters; } function initializeHoveredIndexes() { layoutsContainer.hoveredIndex = -1; layoutsContainer.currentSpot = -1000; if (latteApplet) { latteApplet.initializeHoveredIndex(); } } function layoutManager() { return LayoutManager; } function layoutManagerInsertBefore(place, item) { LayoutManager.insertBefore(place, item); } function layoutManagerInsertAfter(place, item) { LayoutManager.insertAfter(place, item); } function layoutManagerSave() { LayoutManager.save(); } function layoutManagerSaveOptions() { LayoutManager.saveOptions(); } function mouseInCanBeHoveredApplet(){ if (latteApplet && latteApplet.containsMouse()) return true; var applets = layoutsContainer.startLayout.children; for(var i=0; i=0; --i){ if(iconsArray[i] === size){ return true; } } return false; } function slotPreviewsShown(){ if (latteView) { latteView.extendedInterface.deactivateApplets(); } } function startCheckRestoreZoomTimer(){ checkRestoreZoom.start(); } function stopCheckRestoreZoomTimer(){ checkRestoreZoom.stop(); } function startDirectRenderDelayerDuringEntering(){ directRenderDelayerForEnteringTimer.start(); } function setGlobalDirectRender(value) { if (latteApplet && latteApplet.tasksExtendedManager.waitingLaunchersLength() > 0) return; if (value === true) { if (mouseInCanBeHoveredApplet()) { root.globalDirectRender = true; } else { // console.log("direct render true ignored..."); } } else { root.globalDirectRender = false; } } function updateContainsOnlyPlasmaTasks() { if (latteView) { root.containsOnlyPlasmaTasks = (latteView.tasksPresent() && !latteApplet); } else { root.containsOnlyPlasmaTasks = false; } } function updateSizeForAppletsInFill() { layoutsContainer.updateSizeForAppletsInFill(); } function splitMainLayoutToLayouts() { if (internalViewSplittersCount() === 2) { console.log("LAYOUTS: Moving applets from MAIN to THREE Layouts mode..."); var splitter = -1; var splitter2 = -1; var totalChildren = layoutsContainer.mainLayout.children.length; for (var i=0; i=0 && splitter2 === -1) { splitter2 = i; } } // console.log("update layouts 1:"+splitter + " - "+splitter2); for (var i=0; i<=splitter; ++i){ var item = layoutsContainer.mainLayout.children[0]; item.parent = layoutsContainer.startLayout; } splitter2 = splitter2 - splitter - 1; // console.log("update layouts 2:"+splitter + " - "+splitter2); totalChildren = layoutsContainer.mainLayout.children.length; for (var i=splitter2+1; i=0; --i) { var item1 = layoutsContainer.mainLayout.children[0]; item1.parent = layoutsContainer.startLayout; } var totalChildren2 = layoutsContainer.endLayout.children.length; for (var i=totalChildren2-1; i>=0; --i) { var item2 = layoutsContainer.endLayout.children[0]; item2.parent = layoutsContainer.startLayout; } var totalChildrenL = layoutsContainer.startLayout.children.length; for (var i=totalChildrenL-1; i>=0; --i) { var itemL = layoutsContainer.startLayout.children[0]; itemL.parent = layoutsContainer.mainLayout; } } function upgrader_v010_alignment() { //! IMPORTANT, special case because it needs to be loaded on Component constructor if (!plasmoid.configuration.alignmentUpgraded) { plasmoid.configuration.alignment = plasmoid.configuration.panelPosition; plasmoid.configuration.alignmentUpgraded = true; } } //END functions ////BEGIN interfaces Connections { target: LatteCore.WindowSystem onCompositingActiveChanged: { visibilityManager.updateMaskArea(); } } Connections { target: latteView onContextMenuIsShownChanged: { if (!latteView.contextMenuIsShown) { checkRestoreZoom.start(); } else { root.setGlobalDirectRender(false); } } } Connections{ target: latteView && latteView.visibility ? latteView.visibility : root ignoreUnknownSignals : true onContainsMouseChanged: { if (mouseInHoverableArea()) { stopCheckRestoreZoomTimer(); } else { startCheckRestoreZoomTimer(); } } } Connections{ target: layoutsContainer onHoveredIndexChanged: { if (latteApplet && layoutsContainer.hoveredIndex>-1){ latteApplet.setHoveredIndex(-1); } if (latteApplet && latteApplet.windowPreviewIsShown && layoutsContainer.hoveredIndex>-1) { latteApplet.hidePreview(); } } } ////END interfaces /////BEGIN: Title Tooltip/////////// PlasmaCore.Dialog{ id: titleTooltipDialog type: PlasmaCore.Dialog.Tooltip flags: Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus | Qt.ToolTip location: plasmoid.location mainItem: RowLayout{ Layout.fillWidth: true Layout.fillHeight: true PlasmaComponents.Label{ id:titleLbl Layout.leftMargin: 4 Layout.rightMargin: 4 Layout.topMargin: 2 Layout.bottomMargin: 2 text: titleTooltipDialog.title } } visible: false property string title: "" property bool activeItemHovered: false property Item activeItem: null property Item activeItemTooltipParent: null property string activeItemText: "" Component.onCompleted: { root.clearZoomSignal.connect(titleTooltipDialog.hide); } Component.onDestruction: { root.clearZoomSignal.disconnect(titleTooltipDialog.hide); } function hide(debug){ if (!root.titleTooltips) return; activeItemHovered = false; hideTitleTooltipTimer.start(); } function show(taskItem, text){ if (!root.titleTooltips || (latteApplet && latteApplet.contextMenu)){ return; } activeItemHovered = true; if (activeItem !== taskItem) { activeItem = taskItem; activeItemTooltipParent = taskItem.tooltipVisualParent; activeItemText = text; } if (isReady) { showTitleTooltipTimer.start(); } } function update() { activeItemHovered = true title = activeItemText; visualParent = activeItemTooltipParent; if (latteApplet && latteApplet.windowPreviewIsShown) { latteApplet.hidePreview(); } visible = true; } } Timer { id: showTitleTooltipTimer interval: 100 onTriggered: { if (latteView && latteView.visibility && latteView.visibility.containsMouse) { titleTooltipDialog.update(); } if (titleTooltipDialog.visible) { titleTooltipCheckerToNotShowTimer.start(); } if (root.debugModeTimers) { console.log("containment timer: showTitleTooltipTimer called..."); } } } Timer { id: hideTitleTooltipTimer interval: 200 onTriggered: { if (!titleTooltipDialog.activeItemHovered) { titleTooltipDialog.visible = false; } if (root.debugModeTimers) { console.log("containment timer: hideTitleTooltipTimer called..."); } } } //! Timer to fix #811, rare cases that both a window preview and context menu are //! shown Timer { id: titleTooltipCheckerToNotShowTimer interval: 250 onTriggered: { if (titleTooltipDialog.visible && latteApplet && (latteApplet.contextMenu || latteApplet.windowPreviewIsShown)) { titleTooltipDialog.visible = false; } } } /////END: Title Tooltip/////////// ///////////////BEGIN components Component { id: appletContainerComponent Applet.AppletItem{ animations: _animations appletsRecords: _appletsRecords - container: _container + metrics: _metrics } } ParabolicManager{ id: _parabolicManager } Indicators.Manager{ id: indicators } Item { id: graphicsSystem readonly property bool isAccelerated: (GraphicsInfo.api !== GraphicsInfo.Software) && (GraphicsInfo.api !== GraphicsInfo.Unknown) } Upgrader { id: upgrader } ///////////////END components PlasmaCore.ColorScope{ id: colorScopePalette } ///////////////BEGIN UI elements //it is used to check if the mouse is outside the layoutsContainer borders, //so in that case the onLeave event behavior should be trigerred RootMouseArea{ id: rootMouseArea } Loader{ active: root.debugModeWindow sourceComponent: DebugWindow{} } EditMode.Visual{ id:editModeVisual // z: root.behaveAsPlasmaPanel ? 1 : 0 } Item { id: lastSpacer parent: layoutsContainer.mainLayout Layout.fillWidth: true Layout.fillHeight: true z:10 Rectangle{ anchors.fill: parent color: "transparent" border.color: "yellow" border.width: 1 } } Loader{ anchors.fill: parent active: root.debugMode z:10 sourceComponent: Item{ Rectangle{ anchors.fill: parent color: "yellow" opacity: 0.06 } } } VisibilityManager{ id: visibilityManager } DragDropArea { id: backDropArea anchors.fill: parent readonly property bool higherPriority: latteView && latteView.containsDrag && ((root.dragInfo.isPlasmoid && root.dragInfo.isSeparator) || (foreDropArea.dragInfo.computationsAreValid && !root.dragInfo.isPlasmoid && !root.dragInfo.onlyLaunchers)) Item{ id: panelBox anchors.fill: layoutsContainer PanelBox{ id: panelBoxBackground } } Layouts.LayoutsContainer { id: layoutsContainer } DragDropArea { id: foreDropArea anchors.fill: parent visible: !backDropArea.higherPriority isForeground: true /* Rectangle { anchors.fill: parent color: "blue" opacity: 0.5 }*/ } } Colorizer.Manager { id: colorizerManager } Item { id: dndSpacer width: root.isHorizontal ? length : thickness height: root.isHorizontal ? thickness : length - readonly property int length: container.iconSize + root.lengthMargins - readonly property int thickness: container.iconSize + root.thickMargins + root.localScreenEdgeMargin + readonly property int length: metrics.iconSize + root.lengthMargins + readonly property int thickness: metrics.iconSize + root.thickMargins + root.localScreenEdgeMargin Layout.preferredWidth: width Layout.preferredHeight: height opacity: 0 z:1500 LatteComponents.AddItem{ id: dndSpacerAddItem width: root.isHorizontal ? parent.width : parent.width - root.localScreenEdgeMargin height: root.isHorizontal ? parent.height - root.localScreenEdgeMargin : parent.height states:[ State{ name: "bottom" when: plasmoid.location === PlasmaCore.Types.BottomEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: root.localScreenEdgeMargin; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "top" when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin: root.localScreenEdgeMargin; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "left" when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: root.localScreenEdgeMargin; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "right" when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: root.localScreenEdgeMargin; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] } } ///////////////END UI elements ///////////////BEGIN ABILITIES Ability.Animations { id: _animations - container: _container + metrics: _metrics settings: universalSettings } Ability.AppletsRecords { id: _appletsRecords } Ability.AutoSize { id: _autosize - container: _container layouts: layoutsContainer + metrics: _metrics visibility: visibilityManager } - Ability.Container { - id: _container + Ability.Metrics { + id: _metrics animations: _animations autosize: _autosize } ///////////////END ABILITIES ///////////////BEGIN TIMER elements //Timer to check if the mouse is still outside the latteView in order to restore zooms to 1.0 Timer{ id:checkRestoreZoom interval: 90 onTriggered: { if (latteApplet && (latteApplet.previewContainsMouse() || latteApplet.contextMenu)) return; if (latteView.contextMenuIsShown) return; if (!mouseInHoverableArea()) { setGlobalDirectRender(false); root.initializeHoveredIndexes(); root.clearZoom(); } if (root.debugModeTimers) { console.log("containment timer: checkRestoreZoom called..."); } } } //! Delayer in order to not activate directRendering when the mouse //! enters until the timer has ended. This way we make sure that the //! zoom-in animations will have ended. Timer{ id:directRenderDelayerForEnteringTimer interval: 3.2 * animations.speedFactor.current * animations.duration.small } //! It is used in order to slide-in the latteView on startup Timer{ id: inStartupTimer interval: 1500 repeat: false onTriggered: { if (inStartup) { visibilityManager.slotMustBeShown(); } } } ///////////////END TIMER elements Loader{ anchors.fill: parent active: root.debugModeLocalGeometry sourceComponent: Rectangle{ x: latteView.localGeometry.x y: latteView.localGeometry.y width: latteView.localGeometry.width height: latteView.localGeometry.height color: "blue" border.width: 2 border.color: "red" opacity: 0.35 } } } diff --git a/declarativeimports/abilities/applets/Container.qml b/declarativeimports/abilities/applets/Metrics.qml similarity index 74% rename from declarativeimports/abilities/applets/Container.qml rename to declarativeimports/abilities/applets/Metrics.qml index c2380034..dcc85b75 100644 --- a/declarativeimports/abilities/applets/Container.qml +++ b/declarativeimports/abilities/applets/Metrics.qml @@ -1,32 +1,37 @@ /* * 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 . */ import QtQuick 2.0 import org.kde.latte.abilities.definitions 0.1 as AbilityDefinition -AbilityDefinition.Container { +AbilityDefinition.Metrics { id: apis property Item bridge: null - iconSize: bridge ? bridge.container.iconSize : local.iconSize - maxIconSize: bridge ? bridge.container.maxIconSize : local.iconSize + Item { + id: refs + readonly property Item metrics: bridge ? bridge.metrics : local + } - readonly property AbilityDefinition.Container local: AbilityDefinition.Container {} + iconSize: refs.metrics.iconSize + maxIconSize: refs.metrics.maxIconSize + + readonly property AbilityDefinition.Metrics local: AbilityDefinition.Metrics {} } diff --git a/declarativeimports/abilities/applets/qmldir b/declarativeimports/abilities/applets/qmldir index 0e05c8b1..c721d35e 100644 --- a/declarativeimports/abilities/applets/qmldir +++ b/declarativeimports/abilities/applets/qmldir @@ -1,5 +1,5 @@ module org.kde.latte.abilities.applets Animations 0.1 Animations.qml -Container 0.1 Container.qml +Metrics 0.1 Metrics.qml Requirements 0.1 Requirements.qml diff --git a/declarativeimports/abilities/containers/Container.qml b/declarativeimports/abilities/containers/Metrics.qml similarity index 97% rename from declarativeimports/abilities/containers/Container.qml rename to declarativeimports/abilities/containers/Metrics.qml index da629bf8..0c1ce070 100644 --- a/declarativeimports/abilities/containers/Container.qml +++ b/declarativeimports/abilities/containers/Metrics.qml @@ -1,31 +1,31 @@ /* * 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 . */ import QtQuick 2.0 import org.kde.latte.abilities.definitions 0.1 as AbilityDefinition -AbilityDefinition.Container { +AbilityDefinition.Metrics { id: apis readonly property Item publicApi: Item { readonly property alias iconSize: apis.iconSize readonly property alias maxIconSize: apis.maxIconSize } } diff --git a/declarativeimports/abilities/containers/qmldir b/declarativeimports/abilities/containers/qmldir index 16b68fc4..a4666b28 100644 --- a/declarativeimports/abilities/containers/qmldir +++ b/declarativeimports/abilities/containers/qmldir @@ -1,4 +1,4 @@ module org.kde.latte.abilities.containers Animations 0.1 Animations.qml -Container 0.1 Container.qml +Metrics 0.1 Metrics.qml diff --git a/declarativeimports/abilities/definitions/Container.qml b/declarativeimports/abilities/definitions/Metrics.qml similarity index 100% rename from declarativeimports/abilities/definitions/Container.qml rename to declarativeimports/abilities/definitions/Metrics.qml diff --git a/declarativeimports/abilities/definitions/qmldir b/declarativeimports/abilities/definitions/qmldir index 75d550b5..32c1791e 100644 --- a/declarativeimports/abilities/definitions/qmldir +++ b/declarativeimports/abilities/definitions/qmldir @@ -1,6 +1,6 @@ module org.kde.latte.abilities.definitions Animations 0.1 Animations.qml AppletRequirements 0.1 AppletRequirements.qml -Container 0.1 Container.qml +Metrics 0.1 Metrics.qml diff --git a/plasmoid/package/contents/code/tools.js b/plasmoid/package/contents/code/tools.js index 860a28fb..838f5700 100644 --- a/plasmoid/package/contents/code/tools.js +++ b/plasmoid/package/contents/code/tools.js @@ -1,136 +1,136 @@ /* * Copyright 2016 Smith AR * 2016-2018 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 . */ function wheelActivateNextPrevTask(wheelDelta, eventDelta) { // magic number 120 for common "one click" // See: http://qt-project.org/doc/qt-5/qml-qtquick-wheelevent.html#angleDelta-prop wheelDelta += eventDelta; var increment = 0; while (wheelDelta >= 120) { wheelDelta -= 120; increment++; } while (wheelDelta <= -120) { wheelDelta += 120; increment--; } while (increment != 0) { activateNextPrevTask(increment < 0) increment += (increment < 0) ? 1 : -1; } return wheelDelta; } function activateTask(index, model, modifiers, task) { if (modifiers & Qt.ControlModifier) { tasksModel.requestNewInstance(index); } else if (task.isGroupParent) { task.activateNextTask(); // if (backend.canPresentWindows()) { //task.toolTipAreaItem.hideToolTip(); // backend.presentWindows(model.LegacyWinIdList); // } /*} else if (groupDialog.visible) { groupDialog.visible = false; } else { groupDialog.visualParent = task; groupDialog.visible = true; }*/ } else { if (model.IsMinimized === true) { tasksModel.requestToggleMinimized(index); tasksModel.requestActivate(index); } else if (model.IsActive === true) { tasksModel.requestToggleMinimized(index); } else { tasksModel.requestActivate(index); } } } function activateNextPrevTask(next) { // FIXME TODO: Unnecessarily convoluted and costly; optimize. var taskIndexList = []; var activeTaskIndex = tasksModel.activeTask; for (var i = 0; i < taskList.children.length - 1; ++i) { var task = taskList.children[i]; var modelIndex = task.modelIndex(i); if (task !== undefined){ if (task.IsLauncher !== true && task.IsStartup !== true) { if (task.m.IsGroupParent === true) { for (var j = 0; j < tasksModel.rowCount(modelIndex); ++j) { taskIndexList.push(tasksModel.makeModelIndex(i, j)); } } else { taskIndexList.push(modelIndex); } } } } if (!taskIndexList.length) { return; } var target = taskIndexList[0]; for (var i = 0; i < taskIndexList.length; ++i) { if (taskIndexList[i] === activeTaskIndex) { if (next && i < (taskIndexList.length - 1)) { target = taskIndexList[i + 1]; } else if (!next) { if (i) { target = taskIndexList[i - 1]; } else { target = taskIndexList[taskIndexList.length - 1]; } } break; } } tasksModel.requestActivate(target); } function insertIndexAt(above, x, y) { if (above && above.itemIndex) { return above.itemIndex; } else { var distance = root.vertical ? y : x; //var step = root.vertical ? LayoutManager.taskWidth() : LayoutManager.taskHeight(); - var step = container.iconSize + root.lengthMargins; + var step = metrics.iconSize + root.lengthMargins; var stripe = Math.ceil(distance / step); /* if (stripe === LayoutManager.calculateStripes()) { return tasksModel.count - 1; } else { return stripe * LayoutManager.tasksPerStripe(); }*/ return stripe-1; } } diff --git a/plasmoid/package/contents/ui/abilities/Container.qml b/plasmoid/package/contents/ui/abilities/Metrics.qml similarity index 97% rename from plasmoid/package/contents/ui/abilities/Container.qml rename to plasmoid/package/contents/ui/abilities/Metrics.qml index 82bfab44..a443f567 100644 --- a/plasmoid/package/contents/ui/abilities/Container.qml +++ b/plasmoid/package/contents/ui/abilities/Metrics.qml @@ -1,29 +1,29 @@ /* * 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 . */ import QtQuick 2.7 import org.kde.plasma.plasmoid 2.0 import org.kde.latte.abilities.applets 0.1 as AppletAbility -AppletAbility.Container { +AppletAbility.Metrics { //! Public Local Properties local.iconSize: Math.max(plasmoid.configuration.iconSize, 16) } diff --git a/plasmoid/package/contents/ui/main.qml b/plasmoid/package/contents/ui/main.qml index 6cf012ce..8ca199e8 100644 --- a/plasmoid/package/contents/ui/main.qml +++ b/plasmoid/package/contents/ui/main.qml @@ -1,2106 +1,2106 @@ /* * Copyright 2016 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 . */ import QtQuick 2.8 import QtQuick.Layouts 1.1 import QtGraphicalEffects 1.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.plasmoid 2.0 import org.kde.taskmanager 0.1 as TaskManager import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet import org.kde.activities 0.1 as Activities import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.components 1.0 as LatteComponents import org.kde.latte.abilities.applets 0.1 as AppletAbility import org.kde.latte.private.tasks 0.1 as LatteTasks import "abilities" as Ability import "previews" as Previews import "task" as Task import "taskslayout" as TasksLayout import "../code/tools.js" as TaskTools import "../code/activitiesTools.js" as ActivitiesTools import "../code/ColorizerTools.js" as ColorizerTools Item { id:root Layout.fillWidth: scrollingEnabled && !root.vertical Layout.fillHeight: scrollingEnabled && root.vertical Layout.minimumWidth: -1 Layout.minimumHeight: -1 Layout.preferredWidth: tasksWidth Layout.preferredHeight: tasksHeight Layout.maximumWidth: -1 Layout.maximumHeight: -1 LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft && !root.vertical LayoutMirroring.childrenInherit: true //it is used to check both the applet and the containment for direct render property bool globalDirectRender: latteView ? latteView.globalDirectRender : icList.directRender property bool plasma515: latteView ? latteView.plasma515 : LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,15,0) property bool plasma518: latteView ? latteView.plasma518 : LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,18,0) property bool editMode: latteView ? latteView.editMode : plasmoid.userConfiguring property bool inConfigureAppletsMode: latteView ? latteView.inConfigureAppletsMode : true property bool disableRestoreZoom: false //blocks restore animation in rightClick property bool disableAllWindowsFunctionality: root.showWindowsOnlyFromLaunchers && !indicators.isEnabled property bool dropNewLauncher: false readonly property bool hasInternalSeparator: parabolicManager.hasInternalSeparator property bool inActivityChange: false property bool inDraggingPhase: false property bool initializationStep: false //true property bool isHovered: false property bool showBarLine: plasmoid.configuration.showBarLine property bool showTaskShortcutBadges: false property int tasksBaseIndex: 0 property bool useThemePanel: plasmoid.configuration.useThemePanel property bool taskInAnimation: noTasksInAnimation > 0 ? true : false property bool transparentPanel: plasmoid.configuration.transparentPanel property bool vertical: plasmoid.formFactor === PlasmaCore.Types.Vertical ? true : false property int clearWidth property int clearHeight property int newDroppedPosition: -1 property int noInitCreatedBuffers: 0 property int noTasksInAnimation: 0 property int themePanelSize: plasmoid.configuration.panelSize property int location : { if (plasmoid.location === PlasmaCore.Types.LeftEdge || plasmoid.location === PlasmaCore.Types.RightEdge || plasmoid.location === PlasmaCore.Types.TopEdge) { return plasmoid.location; } return PlasmaCore.Types.BottomEdge; } property int tasksStarting: 0 ///Don't use Math.floor it adds one pixel in animations and creates glitches property int widthMargins: root.vertical ? thickMargins : lengthMargins property int heightMargins: !root.vertical ? thickMargins : lengthMargins property int internalWidthMargins: root.vertical ? thickMargins : 2 * lengthIntMargin property int internalHeightMargins: !root.vertical ? thickMargins : 2 * lengthIntMargin property real textColorBrightness: ColorizerTools.colorBrightness(themeTextColor) property color minimizedDotColor: { if (latteView) { return latteView.minimizedDotColor; } return textColorBrightness > 127.5 ? Qt.darker(themeTextColor, 1.7) : Qt.lighter(themeBackgroundColor, 7) } property color themeTextColor: theme.textColor property color themeBackgroundColor: theme.backgroundColor property color lightTextColor: textColorBrightness > 127.5 ? themeTextColor : themeBackgroundColor //a small badgers record (id,value) //in order to track badgers when there are changes //in launcher reference from libtaskmanager property variant badgers:[] property variant launchersOnActivities: [] //global plasmoid reference to the context menu property QtObject contextMenu: null property QtObject contextMenuComponent: Qt.createComponent("ContextMenu.qml"); property Item dragSource: null property Item parabolicManager: _parabolicManager property Item tasksExtendedManager: _tasksExtendedManager readonly property alias animations: _animations - readonly property alias container: _container + readonly property alias metrics: _metrics readonly property alias containsDrag: mouseHandler.containsDrag readonly property bool dragAreaEnabled: latteView ? (root.dragSource !== null || latteView.dragInfo.isSeparator || latteView.dragInfo.isTask || !latteView.dragInfo.isPlasmoid) : true //! it is used to play the animation correct when the user removes a launcher property string launcherForRemoval: "" //BEGIN Latte Dock properties property bool badges3DStyle: latteView ? latteView.badges3DStyle : true property bool dockIsShownCompletely: latteView ? latteView.dockIsShownCompletely : true property bool enableShadows: latteView ? latteView.enableShadows > 0 : plasmoid.configuration.showShadows property bool forceHidePanel: false property bool directRenderDelayerIsRunning: latteView ? latteView.directRenderDelayerIsRunning : directRenderDelayerForEnteringTimer.running property bool disableLeftSpacer: false property bool disableRightSpacer: false property bool dockIsHidden: latteView ? latteView.dockIsHidden : false property bool groupTasksByDefault: plasmoid.configuration.groupTasksByDefault property bool highlightWindows: latteView ? latteView.hoverAction === LatteTasks.Types.HighlightWindows || latteView.hoverAction === LatteTasks.Types.PreviewAndHighlightWindows : plasmoid.configuration.highlightWindows property bool parabolicEffectEnabled: latteView ? latteView.parabolicEffectEnabled : zoomFactor>1 && !root.editMode property bool scrollingEnabled: plasmoid.configuration.scrollTasksEnabled property bool autoScrollTasksEnabled: scrollingEnabled && plasmoid.configuration.autoScrollTasksEnabled property bool manualScrollTasksEnabled: scrollingEnabled && manualScrollTasksType !== LatteTasks.Types.ManualScrollDisabled property int manualScrollTasksType: plasmoid.configuration.manualScrollTasksType property bool showInfoBadge: plasmoid.configuration.showInfoBadge property bool showProgressBadge: plasmoid.configuration.showInfoBadge property bool showAudioBadge: plasmoid.configuration.showAudioBadge property bool infoBadgeProminentColorEnabled: plasmoid.configuration.infoBadgeProminentColorEnabled property bool audioBadgeActionsEnabled: plasmoid.configuration.audioBadgeActionsEnabled property bool showOnlyCurrentScreen: plasmoid.configuration.showOnlyCurrentScreen property bool showOnlyCurrentDesktop: plasmoid.configuration.showOnlyCurrentDesktop property bool showOnlyCurrentActivity: plasmoid.configuration.showOnlyCurrentActivity property bool showPreviews: latteView ? latteView.hoverAction === LatteTasks.Types.PreviewWindows || latteView.hoverAction === LatteTasks.Types.PreviewAndHighlightWindows : plasmoid.configuration.showToolTips property bool showWindowActions: plasmoid.configuration.showWindowActions property bool showWindowsOnlyFromLaunchers: plasmoid.configuration.showWindowsOnlyFromLaunchers property bool titleTooltips: latteView ? latteView.titleTooltips : false property alias windowPreviewIsShown: windowsPreviewDlg.visible property int directRenderAnimationTime: latteView ? latteView.directRenderAnimationTime : 0 property int dockHoveredIndex : latteView ? latteView.hoveredIndex : -1 property int launchersGroup: plasmoid.configuration.launchersGroup property int leftClickAction: plasmoid.configuration.leftClickAction property int middleClickAction: plasmoid.configuration.middleClickAction property int hoverAction: plasmoid.configuration.hoverAction property int modifier: plasmoid.configuration.modifier property int modifierClickAction: plasmoid.configuration.modifierClickAction property int modifierClick: plasmoid.configuration.modifierClick property int modifierQt:{ if (modifier === LatteTasks.Types.Shift) return Qt.ShiftModifier; else if (modifier === LatteTasks.Types.Ctrl) return Qt.ControlModifier; else if (modifier === LatteTasks.Types.Alt) return Qt.AltModifier; else if (modifier === LatteTasks.Types.Meta) return Qt.MetaModifier; else return -1; } property int taskScrollAction: plasmoid.configuration.taskScrollAction onTaskScrollActionChanged: { if (taskScrollAction > LatteTasks.Types.ScrollToggleMinimized) { //! migrating scroll action to LatteTasks.Types.ScrollAction plasmoid.configuration.taskScrollAction = plasmoid.configuration.taskScrollAction-LatteTasks.Types.ScrollToggleMinimized; } } - property int thickMargin: latteView ? latteView.thickMargin : 0.16*container.iconSize + property int thickMargin: latteView ? latteView.thickMargin : 0.16*metrics.iconSize property int thickMargins: 2 * thickMargin - property int lengthIntMargin: latteView ? latteView.lengthIntMargin : 0.04 * container.iconSize - property int lengthExtMargin: latteView ? latteView.lengthExtMargin : 0.1 * container.iconSize + property int lengthIntMargin: latteView ? latteView.lengthIntMargin : 0.04 * metrics.iconSize + property int lengthExtMargin: latteView ? latteView.lengthExtMargin : 0.1 * metrics.iconSize property int lengthMargin: lengthIntMargin + lengthExtMargin property int lengthMargins: 2 * lengthMargin property int tasksHeight: mouseHandler.height property int tasksWidth: mouseHandler.width //updated from Binding property int alignment readonly property real currentPanelOpacity: latteView ? latteView.currentPanelTransparency / 100 : 1 property real maxZoomFactor: latteView ? latteView.maxZoomFactor : Math.max(zoomFactor, animations.maxZoomFactor) property real zoomFactor: latteView ? latteView.zoomFactor : ( 1 + (plasmoid.configuration.zoomLevel / 20) ) - property int appShadowSize: latteView ? latteView.appShadowSize : Math.ceil(0.12*container.iconSize) + property int appShadowSize: latteView ? latteView.appShadowSize : Math.ceil(0.12*metrics.iconSize) property string appShadowColor: latteView ? latteView.appShadowColor : "#ff080808" property string appShadowColorSolid: latteView ? latteView.appShadowColorSolid : "#ff080808" property alias tasksCount: tasksModel.count property alias hoveredIndex: icList.hoveredIndex readonly property rect screenGeometry: latteView ? latteView.screenGeometry : plasmoid.screenGeometry readonly property bool viewLayoutIsCurrent: latteView && viewLayout && latteView.layoutsManager && viewLayout.name === latteView.layoutsManager.currentLayoutName readonly property string viewLayoutName: viewLayout ? viewLayout.name : "" readonly property QtObject viewLayout : latteView && latteView.viewLayout ? latteView.viewLayout : null property var badgesForActivate: latteView ? latteView.badgesForActivate : [] property Item latteView: null readonly property Item indicators: latteView ? latteView.indicatorsManager : indicatorsStandaloneLoader.item //END Latte Dock Panel properties //BEGIN Latte Dock Communicator property QtObject latteBridge: null readonly property bool enforceLattePalette: latteBridge && latteBridge.applyPalette && latteBridge.palette readonly property bool latteInEditMode: latteBridge && latteBridge.inEditMode readonly property int screenEdgeMargin: latteBridge ? latteBridge.screenEdgeMargin : 0 //END Latte Dock Communicator Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground signal clearZoomSignal(); signal draggingFinished(); signal hiddenTasksUpdated(); signal launchersUpdatedFor(string launcher); signal presentWindows(variant winIds); signal requestLayout; signal separatorsUpdated(); signal signalPreviewsShown(); //signal signalDraggingState(bool value); signal showPreviewForTasks(QtObject group); //trigger updating scaling of neighbour delegates of zoomed delegate signal updateScale(int delegateIndex, real newScale, real step) signal mimicEnterForParabolic(); signal publishTasksGeometries(); signal windowsHovered(variant winIds, bool hovered) //onAnimationsChanged: console.log(animations); /* Rectangle{ anchors.fill: parent border.width: 1 border.color: "red" color: "white" } */ onLatteViewChanged: { if (latteView) { plasmoid.action("configure").visible = false; plasmoid.configuration.isInLatteDock = true; if (root.launchersGroup === LatteCore.Types.LayoutLaunchers || root.launchersGroup === LatteCore.Types.GlobalLaunchers) { tasksModel.updateLaunchersList(); } } else { plasmoid.configuration.isInLatteDock = false; } } onLaunchersGroupChanged:{ if(latteView) { tasksModel.updateLaunchersList(); } } Connections { target: plasmoid onLocationChanged: { iconGeometryTimer.start(); } } Connections { target: plasmoid.configuration // onLaunchersChanged: tasksModel.launcherList = plasmoid.configuration.launchers onGroupingAppIdBlacklistChanged: tasksModel.groupingAppIdBlacklist = plasmoid.configuration.groupingAppIdBlacklist; onGroupingLauncherUrlBlacklistChanged: tasksModel.groupingLauncherUrlBlacklist = plasmoid.configuration.groupingLauncherUrlBlacklist; } Connections{ target: latteView onDockIsHiddenChanged:{ if (latteView.dockIsHidden) { windowsPreviewDlg.hide("3.3"); } } } Connections{ target: latteView && latteView.layoutsManager ? latteView.layoutsManager : null onCurrentLayoutNameChanged: root.publishTasksGeometries(); } Connections{ target: icList onHoveredIndexChanged:{ if (latteView && icList.hoveredIndex>-1){ latteView.setHoveredIndex(-1); } } } Binding { target: plasmoid property: "status" value: (tasksModel.anyTaskDemandsAttentionInValidTime || root.dragSource ? PlasmaCore.Types.NeedsAttentionStatus : PlasmaCore.Types.PassiveStatus); } ///// PlasmaCore.ColorScope{ id: colorScopePalette } //! Item { id: graphicsSystem readonly property bool isAccelerated: (GraphicsInfo.api !== GraphicsInfo.Software) && (GraphicsInfo.api !== GraphicsInfo.Unknown) } Loader { id: indicatorsStandaloneLoader active: !latteView && !plasmoid.configuration.isInLatteDock source: "indicators/Manager.qml" } Binding { target: root property: "alignment" value: { if (latteView) { if (latteView.panelUserSetAlignment === -1) { return; } if (inConfigureAppletsMode) { return LatteCore.Types.Center; } else if (latteView.panelUserSetAlignment === LatteCore.Types.Justify) { if (latteView.latteAppletPos>=0 && latteView.latteAppletPos<100) { return plasmoid.formFactor === PlasmaCore.Types.Horizontal ? LatteCore.Types.Left : LatteCore.Types.Top; } else if (latteView.latteAppletPos>=100 && latteView.latteAppletPos<200) { return LatteCore.Types.Center; } else if (latteView.latteAppletPos>=200) { return plasmoid.formFactor === PlasmaCore.Types.Horizontal ? LatteCore.Types.Right : LatteCore.Types.Bottom; } return LatteCore.Types.Center; } return latteView.panelUserSetAlignment; } return LatteCore.Types.Center; } } ///// function initializeHoveredIndex() { icList.hoveredIndex = -1; icList.currentSpot = -1000; } function launchersDropped(urls){ mouseHandler.urlsDropped(urls); } ///UPDATE function launcherExists(url) { return (ActivitiesTools.getIndex(url, tasksModel.launcherList)>=0); } function taskExists(url) { var tasks = icList.contentItem.children; for(var i=0; i -1) { launch.push(explicitLauncher); } } } return launch; } function currentListViewLauncherList() { var launch = []; var tasks = icList.contentItem.children; for(var i=0; i