2019-04-05 19:59:15 +03:00
/*
* Copyright 2019 Michail Vourlakos < mvourlakos @ gmail . com >
*
* 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 < http : //www.gnu.org/licenses/>.
*/
# include "genericlayout.h"
2019-04-05 20:39:19 +03:00
// local
# include "abstractlayout.h"
2019-04-06 18:56:24 +03:00
# include "storage.h"
2019-04-06 02:00:37 +03:00
# include "../lattecorona.h"
# include "../screenpool.h"
2019-05-09 17:57:12 +03:00
# include "../layouts/importer.h"
2019-05-09 17:12:57 +03:00
# include "../layouts/manager.h"
2019-05-11 09:23:14 +03:00
# include "../layouts/synchronizer.h"
2019-04-06 02:00:37 +03:00
# include "../shortcuts/shortcutstracker.h"
# include "../view/view.h"
# include "../view/positioner.h"
// Qt
# include <QDebug>
# include <QScreen>
// Plasma
# include <Plasma>
# include <Plasma/Applet>
# include <Plasma/Containment>
// KDE
# include <KConfigGroup>
2019-04-05 20:39:19 +03:00
2019-04-05 19:59:15 +03:00
namespace Latte {
namespace Layout {
2019-04-05 20:39:19 +03:00
GenericLayout : : GenericLayout ( QObject * parent , QString layoutFile , QString assignedName )
2019-04-06 18:56:24 +03:00
: AbstractLayout ( parent , layoutFile , assignedName ) ,
m_storage ( new Storage ( this ) )
2019-04-05 19:59:15 +03:00
{
}
GenericLayout : : ~ GenericLayout ( )
{
}
2019-05-02 12:58:56 +03:00
Type GenericLayout : : type ( ) const
{
return Type : : Generic ;
}
2019-04-06 02:00:37 +03:00
void GenericLayout : : unloadContainments ( )
{
if ( ! m_corona ) {
return ;
}
//!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 ) ;
2019-04-07 17:20:10 +03:00
disconnect ( m_corona - > activityConsumer ( ) , & KActivities : : Consumer : : currentActivityChanged , this , & GenericLayout : : updateLastUsedActivity ) ;
2019-04-06 02:00:37 +03:00
qDebug ( ) < < " Layout - " + name ( ) + " unload: containments ... size ::: " < < 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 < Plasma : : Containment * > systrays ;
//!identify systrays and unload them first
for ( const auto containment : m_containments ) {
if ( Plasma : : Applet * parentApplet = qobject_cast < Plasma : : Applet * > ( 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 ( ) + " unload: latteViews ... size: " < < m_latteViews . size ( ) ;
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 ;
}
2019-05-04 03:01:16 +03:00
bool GenericLayout : : isActive ( ) const
{
if ( ! m_corona ) {
return false ;
}
2019-05-11 09:23:14 +03:00
GenericLayout * generic = m_corona - > layoutsManager ( ) - > synchronizer ( ) - > layout ( m_layoutName ) ;
2019-05-04 03:01:16 +03:00
if ( generic ) {
return true ;
} else {
return false ;
}
}
2019-04-07 20:15:58 +03:00
bool GenericLayout : : isCurrent ( ) const
{
2019-04-08 18:57:32 +03:00
if ( ! m_corona ) {
return false ;
}
2019-05-09 17:12:57 +03:00
return name ( ) = = m_corona - > layoutsManager ( ) - > currentLayoutName ( ) ;
2019-04-07 20:15:58 +03:00
}
2019-04-06 02:00:37 +03:00
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 < int > GenericLayout : : qmlFreeEdges ( int screen ) const
{
if ( ! m_corona ) {
const QList < int > emptyEdges ;
return emptyEdges ;
}
const auto edges = freeEdges ( screen ) ;
QList < int > edgesInt ;
for ( const Plasma : : Types : : Location & edge : edges ) {
edgesInt . append ( static_cast < int > ( edge ) ) ;
}
return edgesInt ;
}
QList < Plasma : : Types : : Location > GenericLayout : : freeEdges ( QScreen * scr ) const
{
using Plasma : : Types ;
QList < Types : : Location > edges { Types : : BottomEdge , Types : : LeftEdge ,
2019-04-07 19:35:55 +03:00
Types : : TopEdge , Types : : RightEdge } ;
2019-04-06 02:00:37 +03:00
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 < Plasma : : Types : : Location > GenericLayout : : freeEdges ( int screen ) const
{
using Plasma : : Types ;
QList < Types : : Location > edges { Types : : BottomEdge , Types : : LeftEdge ,
2019-04-07 19:35:55 +03:00
Types : : TopEdge , Types : : RightEdge } ;
2019-04-06 02:00:37 +03:00
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 ;
}
2019-04-06 18:56:24 +03:00
Latte : : Corona * GenericLayout : : corona ( )
{
return m_corona ;
}
2019-04-06 02:00:37 +03:00
Types : : ViewType GenericLayout : : latteViewType ( int 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 < Latte : : View * > views = sortedLatteViews ( ) ;
2019-04-07 19:35:55 +03:00
return ( views . count ( ) > 0 ? views [ 0 ] : nullptr ) ;
2019-04-06 02:00:37 +03:00
}
2019-05-25 18:05:24 +03:00
Latte : : View * GenericLayout : : lastConfigViewFor ( )
2019-05-25 17:49:02 +03:00
{
2019-05-25 18:05:24 +03:00
if ( ! latteViews ( ) . contains ( m_lastConfigViewFor ) ) {
m_lastConfigViewFor = nullptr ;
return nullptr ;
}
2019-05-25 17:49:02 +03:00
return m_lastConfigViewFor ;
}
void GenericLayout : : setLastConfigViewFor ( Latte : : View * view )
{
if ( m_lastConfigViewFor = = view ) {
return ;
}
m_lastConfigViewFor = view ;
emit lastConfigViewForChanged ( view ) ;
}
2019-06-15 21:38:07 +03:00
Latte : : View * GenericLayout : : viewForContainment ( Plasma : : Containment * containment )
2019-04-06 02:00:37 +03:00
{
2019-06-15 21:38:07 +03:00
if ( m_containments . contains ( containment ) & & m_latteViews . contains ( containment ) ) {
2019-04-07 19:35:55 +03:00
return m_latteViews [ containment ] ;
}
return nullptr ;
}
QList < Latte : : View * > GenericLayout : : latteViews ( )
{
return m_latteViews . values ( ) ;
2019-04-06 02:00:37 +03:00
}
2019-04-07 23:02:13 +03:00
QList < Latte : : View * > GenericLayout : : sortedLatteViews ( QList < Latte : : View * > views )
2019-04-06 02:00:37 +03:00
{
2019-04-07 23:02:13 +03:00
QList < Latte : : View * > sortedViews = views . isEmpty ( ) ? latteViews ( ) : views ;
2019-04-06 02:00:37 +03:00
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 < Plasma : : Types : : Location > 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 ;
}
2019-04-06 18:56:24 +03:00
const QList < Plasma : : Containment * > * GenericLayout : : containments ( )
2019-04-06 02:00:37 +03:00
{
return & m_containments ;
}
QList < Latte : : View * > GenericLayout : : viewsWithPlasmaShortcuts ( )
{
QList < Latte : : View * > views ;
if ( ! m_corona ) {
return views ;
}
QList < int > 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 } ;
2019-05-09 17:12:57 +03:00
if ( m_corona - > layoutsManager ( ) - > memoryUsage ( ) = = Types : : SingleLayout ) {
2019-04-06 02:00:37 +03:00
m_containments . append ( containment ) ;
containmentInLayout = true ;
2019-05-09 17:12:57 +03:00
} else if ( m_corona - > layoutsManager ( ) - > memoryUsage ( ) = = Types : : MultipleLayouts ) {
2019-04-06 02:00:37 +03:00
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 < Plasma : : Containment * > ( 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 ( ) ;
2019-05-10 00:00:47 +03:00
emit viewEdgeChanged ( ) ;
2019-04-06 02:00:37 +03:00
emit viewsCountChanged ( ) ;
}
}
}
void GenericLayout : : destroyedChanged ( bool destroyed )
{
if ( ! m_corona ) {
return ;
}
qDebug ( ) < < " dock containment destroyed changed!!!! " ;
Plasma : : Containment * sender = qobject_cast < Plasma : : Containment * > ( QObject : : sender ( ) ) ;
if ( ! sender ) {
return ;
}
if ( destroyed ) {
m_waitingLatteViews [ sender ] = m_latteViews . take ( static_cast < Plasma : : Containment * > ( sender ) ) ;
} else {
m_latteViews [ sender ] = m_waitingLatteViews . take ( static_cast < Plasma : : Containment * > ( sender ) ) ;
}
2019-05-10 00:00:47 +03:00
emit viewEdgeChanged ( ) ;
2019-04-06 02:00:37 +03:00
emit viewsCountChanged ( ) ;
}
void GenericLayout : : renameLayout ( QString newName )
{
2019-05-09 17:12:57 +03:00
if ( ! m_corona | | m_corona - > layoutsManager ( ) - > memoryUsage ( ) ! = Types : : MultipleLayouts ) {
2019-05-05 17:46:14 +03:00
return ;
}
2019-05-09 17:57:12 +03:00
if ( m_layoutFile ! = Layouts : : Importer : : layoutFilePath ( newName ) ) {
setFile ( Layouts : : Importer : : layoutFilePath ( newName ) ) ;
2019-04-06 02:00:37 +03:00
}
2019-05-05 17:46:14 +03:00
setName ( newName ) ;
2019-04-06 02:00:37 +03:00
2019-05-05 17:46:14 +03:00
for ( const auto containment : m_containments ) {
qDebug ( ) < < " Cont ID :: " < < containment - > id ( ) ;
containment - > config ( ) . writeEntry ( " layoutId " , m_layoutName ) ;
2019-04-06 02:00:37 +03:00
}
}
void GenericLayout : : addNewView ( )
{
if ( ! m_corona ) {
return ;
}
2019-04-08 18:57:32 +03:00
m_corona - > addViewForLayout ( name ( ) ) ;
2019-05-10 00:00:47 +03:00
emit viewEdgeChanged ( ) ;
2019-04-06 02:00:37 +03:00
}
2019-04-08 22:02:50 +03:00
void GenericLayout : : addView ( Plasma : : Containment * containment , bool forceOnPrimary , int explicitScreen , Layout : : ViewsMap * occupied )
2019-04-06 02:00:37 +03:00
{
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... " ;
2019-04-06 18:56:24 +03:00
if ( ! m_storage - > isLatteContainment ( containment ) )
2019-04-06 02:00:37 +03:00
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 ( ) ;
}
2019-05-12 01:36:00 +03:00
if ( onPrimary ) {
id = m_corona - > screenPool ( ) - > primaryScreenId ( ) ;
} else if ( explicitScreen > - 1 ) {
2019-04-06 02:00:37 +03:00
id = explicitScreen ;
}
2019-04-08 22:02:50 +03:00
Plasma : : Types : : Location edge = containment - > location ( ) ;
2019-05-01 18:52:03 +03:00
QString connector = m_corona - > screenPool ( ) - > hasId ( id ) ? m_corona - > screenPool ( ) - > connector ( id ) : " " ;
qDebug ( ) < < " Adding view - containment id: " < < containment - > id ( ) < < " ,screen : " < < id < < " - " < < connector
2019-04-08 22:02:50 +03:00
< < " ,onprimary: " < < onPrimary < < " - " < < " edge: " < < edge < < " ,screenName: " < < qGuiApp - > primaryScreen ( ) - > name ( ) < < " ,forceOnPrimary: " < < forceOnPrimary ;
2019-05-01 18:52:03 +03:00
if ( occupied & & m_corona - > screenPool ( ) - > hasId ( id ) & & ( * occupied ) . contains ( connector ) & & ( * occupied ) [ connector ] . contains ( edge ) ) {
2019-04-08 22:02:50 +03:00
qDebug ( ) < < " Rejected : adding view because the edge is already occupied by a higher priority view ! : " < < ( * occupied ) [ connector ] [ edge ] ;
return ;
}
2019-04-06 02:00:37 +03:00
if ( id > = 0 & & ! onPrimary & & ! forceOnPrimary ) {
2019-04-08 22:02:50 +03:00
qDebug ( ) < < " Add view - connector : " < < connector ;
2019-04-06 02:00:37 +03:00
bool found { false } ;
2019-05-01 18:52:03 +03:00
if ( m_corona - > screenPool ( ) - > hasId ( id ) ) {
for ( const auto scr : qGuiApp - > screens ( ) ) {
if ( scr & & scr - > name ( ) = = connector ) {
found = true ;
nextScreen = scr ;
break ;
}
2019-04-06 02:00:37 +03:00
}
}
if ( ! found ) {
2019-04-08 22:02:50 +03:00
qDebug ( ) < < " Rejected : adding explicit view, screen not available ! : " < < connector ;
2019-04-06 02:00:37 +03:00
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 ( ) ) ) {
2019-04-08 22:02:50 +03:00
qDebug ( ) < < " Rejected : adding explicit view, primary dock occupies edge at screen ! : " < < connector ;
2019-04-06 02:00:37 +03:00
return ;
}
}
if ( id > = 0 & & onPrimary ) {
qDebug ( ) < < " add dock - connector : " < < connector ;
for ( const auto view : m_latteViews ) {
auto testContainment = view - > containment ( ) ;
int testScreenId = testContainment - > screen ( ) ;
if ( testScreenId = = - 1 ) {
testScreenId = testContainment - > lastScreen ( ) ;
}
bool testOnPrimary = testContainment - > config ( ) . readEntry ( " onPrimary " , true ) ;
Plasma : : Types : : Location testLocation = static_cast < Plasma : : Types : : Location > ( ( 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 ( ) ;
}
}
}
2019-04-08 22:02:50 +03:00
qDebug ( ) < < " Adding view passed ALL checks " < < " ,onPrimary: " < < onPrimary < < " ,screen: " < < nextScreen - > name ( ) < < " !!! " ;
2019-04-06 02:00:37 +03:00
//! 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 < Types : : Visibility > ( containment - > config ( ) . readEntry ( " visibility " , static_cast < int > ( Types : : DodgeActive ) ) ) ;
bool byPassWM { false } ;
if ( mode = = Types : : AlwaysVisible | | mode = = Types : : WindowsGoBelow ) {
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 ) ;
}
2019-05-09 23:45:52 +03:00
latteView - > setLayout ( this ) ;
2019-04-06 02:00:37 +03:00
//! 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 ( ) ;
}
bool GenericLayout : : initToCorona ( Latte : : Corona * corona )
{
if ( m_corona ) {
return false ;
}
m_corona = corona ;
for ( const auto containment : m_corona - > containments ( ) ) {
2019-05-09 17:12:57 +03:00
if ( m_corona - > layoutsManager ( ) - > memoryUsage ( ) = = Types : : SingleLayout ) {
2019-04-06 02:00:37 +03:00
addContainment ( containment ) ;
2019-05-09 17:12:57 +03:00
} else if ( m_corona - > layoutsManager ( ) - > memoryUsage ( ) = = Types : : MultipleLayouts ) {
2019-04-06 02:00:37 +03:00
QString layoutId = containment - > config ( ) . readEntry ( " layoutId " , QString ( ) ) ;
if ( ! layoutId . isEmpty ( ) & & ( layoutId = = m_layoutName ) ) {
addContainment ( containment ) ;
}
}
}
qDebug ( ) < < " Layout ::::: " < < name ( ) < < " added containments ::: " < < m_containments . size ( ) ;
2019-05-04 03:01:16 +03:00
updateLastUsedActivity ( ) ;
2019-04-07 15:46:03 +03:00
//! signals
connect ( m_corona - > activityConsumer ( ) , & KActivities : : Consumer : : currentActivityChanged ,
this , & GenericLayout : : updateLastUsedActivity ) ;
2019-04-06 02:00:37 +03:00
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 ;
}
2019-04-07 15:46:03 +03:00
void GenericLayout : : updateLastUsedActivity ( )
{
if ( ! m_corona ) {
return ;
}
2019-05-11 09:23:14 +03:00
if ( ! m_lastUsedActivity . isEmpty ( ) & & ! m_corona - > layoutsManager ( ) - > synchronizer ( ) - > activities ( ) . contains ( m_lastUsedActivity ) ) {
2019-04-07 15:46:03 +03:00
clearLastUsedActivity ( ) ;
}
QString currentId = m_corona - > activitiesConsumer ( ) - > currentActivity ( ) ;
QStringList appliedActivitiesIds = appliedActivities ( ) ;
if ( m_lastUsedActivity ! = currentId
2019-04-07 19:35:55 +03:00
& & ( appliedActivitiesIds . contains ( currentId )
2019-05-09 17:12:57 +03:00
| | m_corona - > layoutsManager ( ) - > memoryUsage ( ) = = Types : : SingleLayout ) ) {
2019-04-07 15:46:03 +03:00
m_lastUsedActivity = currentId ;
emit lastUsedActivityChanged ( ) ;
}
}
2019-04-06 02:00:37 +03:00
void GenericLayout : : assignToLayout ( Latte : : View * latteView , QList < Plasma : : Containment * > 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 ( ) ) ;
2019-05-09 23:45:52 +03:00
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 ) ;
}
2019-04-06 02:00:37 +03:00
}
2019-05-08 23:42:06 +03:00
latteView - > setLayout ( this ) ;
2019-04-06 02:00:37 +03:00
emit viewsCountChanged ( ) ;
}
//! sync the original layout file for integrity
2019-05-09 17:12:57 +03:00
if ( m_corona & & m_corona - > layoutsManager ( ) - > memoryUsage ( ) = = Types : : MultipleLayouts ) {
2019-04-06 18:56:24 +03:00
m_storage - > syncToLayoutFile ( false ) ;
2019-04-06 02:00:37 +03:00
}
}
QList < Plasma : : Containment * > GenericLayout : : unassignFromLayout ( Latte : : View * latteView )
{
QList < Plasma : : Containment * > containments ;
if ( ! m_corona ) {
return containments ;
}
containments < < latteView - > containment ( ) ;
for ( const auto containment : m_containments ) {
Plasma : : Applet * parentApplet = qobject_cast < Plasma : : Applet * > ( containment - > parent ( ) ) ;
//! add systrays from that latteView
if ( parentApplet & & parentApplet - > containment ( ) & & parentApplet - > containment ( ) = = latteView - > containment ( ) ) {
containments < < containment ;
2019-05-09 23:45:52 +03:00
//! unassign signals only to systrays
//! the View::setLayout() is responsible for the View::Containment signals
2019-04-06 02:00:37 +03:00
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
2019-05-09 17:12:57 +03:00
if ( m_corona & & m_corona - > layoutsManager ( ) - > memoryUsage ( ) = = Types : : MultipleLayouts ) {
2019-04-06 18:56:24 +03:00
m_storage - > syncToLayoutFile ( false ) ;
2019-04-06 02:00:37 +03:00
}
return containments ;
}
void GenericLayout : : recreateView ( Plasma : : Containment * containment )
{
if ( ! m_corona ) {
return ;
}
//! give the time to config window to close itself first and then recreate the dock
//! step:1 remove the latteview
QTimer : : singleShot ( 350 , [ this , containment ] ( ) {
auto view = m_latteViews . take ( containment ) ;
if ( view ) {
qDebug ( ) < < " recreate - step 1: removing dock for containment: " < < containment - > id ( ) ;
//! step:2 add the new latteview
connect ( view , & QObject : : destroyed , this , [ this , containment ] ( ) {
QTimer : : singleShot ( 250 , this , [ this , containment ] ( ) {
if ( ! m_latteViews . contains ( containment ) ) {
qDebug ( ) < < " recreate - step 2: adding dock for containment: " < < containment - > id ( ) ;
addView ( containment ) ;
}
} ) ;
} ) ;
view - > deleteLater ( ) ;
}
} ) ;
}
bool GenericLayout : : latteViewExists ( Plasma : : Containment * containment )
{
if ( ! m_corona ) {
return false ;
}
return m_latteViews . keys ( ) . contains ( containment ) ;
}
QList < Plasma : : Types : : Location > GenericLayout : : availableEdgesForView ( QScreen * scr , Latte : : View * forView ) const
{
using Plasma : : Types ;
QList < Types : : Location > edges { Types : : BottomEdge , Types : : LeftEdge ,
2019-04-07 19:35:55 +03:00
Types : : TopEdge , Types : : RightEdge } ;
2019-04-06 02:00:37 +03:00
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 ) {
2019-04-06 18:56:24 +03:00
if ( m_storage - > isLatteContainment ( containment ) ) {
2019-04-06 02:00:37 +03:00
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 ) {
2019-04-06 18:56:24 +03:00
if ( m_storage - > isLatteContainment ( containment ) ) {
2019-04-06 02:00:37 +03:00
bool onPrimary = containment - > config ( ) . readEntry ( " onPrimary " , true ) ;
Plasma : : Types : : Location contLocation = containment - > location ( ) ;
if ( onPrimary & & contLocation = = location ) {
return true ;
}
}
}
return false ;
}
2019-04-08 18:57:32 +03:00
bool GenericLayout : : mapContainsId ( const Layout : : ViewsMap * map , uint viewId ) const
2019-04-07 01:16:59 +03:00
{
for ( const auto & scr : map - > keys ( ) ) {
for ( const auto & edge : ( * map ) [ scr ] . keys ( ) ) {
if ( ( * map ) [ scr ] [ edge ] = = viewId ) {
return true ;
}
}
}
2019-04-06 02:00:37 +03:00
2019-04-07 01:16:59 +03:00
return false ;
}
//! screen name, location, containmentId
2019-04-08 18:57:32 +03:00
Layout : : ViewsMap GenericLayout : : validViewsMap ( Layout : : ViewsMap * occupiedMap )
2019-04-06 02:00:37 +03:00
{
2019-04-08 18:57:32 +03:00
Layout : : ViewsMap map ;
2019-04-07 01:16:59 +03:00
2019-04-06 02:00:37 +03:00
if ( ! m_corona ) {
2019-04-07 01:16:59 +03:00
return map ;
2019-04-06 02:00:37 +03:00
}
2019-04-08 18:57:32 +03:00
if ( occupiedMap ! = nullptr ) {
map = ( * occupiedMap ) ;
}
2019-04-06 02:00:37 +03:00
QString prmScreenName = qGuiApp - > primaryScreen ( ) - > name ( ) ;
//! first step: primary docks must be placed in primary screen free edges
for ( const auto containment : m_containments ) {
2019-04-06 18:56:24 +03:00
if ( m_storage - > isLatteContainment ( containment ) ) {
2019-04-06 02:00:37 +03:00
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 ( ) ;
2019-04-07 01:16:59 +03:00
if ( onPrimary & & ! map [ prmScreenName ] . contains ( location ) ) {
map [ prmScreenName ] [ location ] = containment - > id ( ) ;
2019-04-06 02:00:37 +03:00
}
}
}
//! second step: explicit docks must be placed in their screens if the screen edge is free
for ( const auto containment : m_containments ) {
2019-04-06 18:56:24 +03:00
if ( m_storage - > isLatteContainment ( containment ) ) {
2019-04-06 02:00:37 +03:00
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 ) ;
2019-04-07 01:16:59 +03:00
if ( m_corona - > screenPool ( ) - > screenExists ( screenId ) & & ! map [ expScreenName ] . contains ( location ) ) {
map [ expScreenName ] [ location ] = containment - > id ( ) ;
2019-04-06 02:00:37 +03:00
}
}
}
}
2019-04-07 01:16:59 +03:00
return map ;
}
//! the central functions that updates loading/unloading latteviews
//! concerning screen changed (for multi-screen setups mainly)
2019-04-08 18:57:32 +03:00
void GenericLayout : : syncLatteViewsToScreens ( Layout : : ViewsMap * occupiedMap )
2019-04-07 01:16:59 +03:00
{
if ( ! m_corona ) {
return ;
}
qDebug ( ) < < " START of SyncLatteViewsToScreens .... " ;
qDebug ( ) < < " LAYOUT ::: " < < name ( ) ;
qDebug ( ) < < " screen count changed -+-+ " < < qGuiApp - > screens ( ) . size ( ) ;
2019-04-08 18:57:32 +03:00
Layout : : ViewsMap viewsMap = validViewsMap ( occupiedMap ) ;
if ( occupiedMap ! = nullptr ) {
qDebug ( ) < < " Occupied map used :: " < < * occupiedMap ;
}
2019-04-07 01:16:59 +03:00
QString prmScreenName = qGuiApp - > primaryScreen ( ) - > name ( ) ;
2019-04-06 02:00:37 +03:00
qDebug ( ) < < " PRIMARY SCREEN :: " < < prmScreenName ;
2019-04-07 01:16:59 +03:00
qDebug ( ) < < " LATTEVIEWS MAP :: " < < viewsMap ;
2019-04-06 02:00:37 +03:00
//! add views
for ( const auto containment : m_containments ) {
int screenId = containment - > screen ( ) ;
if ( screenId = = - 1 ) {
screenId = containment - > lastScreen ( ) ;
}
2019-04-07 01:16:59 +03:00
if ( ! latteViewExists ( containment ) & & mapContainsId ( & viewsMap , containment - > id ( ) ) ) {
2019-04-06 02:00:37 +03:00
qDebug ( ) < < " syncLatteViewsToScreens: view must be added... for containment: " < < containment - > id ( ) < < " at screen: " < < m_corona - > screenPool ( ) - > connector ( screenId ) ;
addView ( containment ) ;
}
}
//! remove views
2019-04-08 18:57:32 +03:00
QList < Plasma : : Containment * > viewsToDelete ;
for ( auto view : m_latteViews ) {
auto containment = view - > containment ( ) ;
if ( containment & & ! mapContainsId ( & viewsMap , containment - > id ( ) ) ) {
viewsToDelete < < containment ;
2019-04-06 02:00:37 +03:00
}
}
2019-04-08 18:57:32 +03:00
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 ( ) ;
}
2019-04-06 02:00:37 +03:00
//! reconsider views
for ( const auto view : m_latteViews ) {
2019-04-08 18:57:32 +03:00
if ( view - > containment ( ) & & mapContainsId ( & viewsMap , view - > containment ( ) - > id ( ) ) ) {
2019-04-06 02:00:37 +03:00
//! 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
2019-04-08 18:57:32 +03:00
qDebug ( ) < < " syncLatteViewsToScreens: view must consider its screen... for containment: " < < view - > containment ( ) - > id ( ) < < " at screen: " < < view - > positioner ( ) - > currentScreenName ( ) ;
2019-04-06 02:00:37 +03:00
view - > reconsiderScreen ( ) ;
}
}
qDebug ( ) < < " end of, syncLatteViewsToScreens .... " ;
}
2019-04-06 18:56:24 +03:00
//! STORAGE
2019-04-06 02:00:37 +03:00
bool GenericLayout : : isWritable ( ) const
{
2019-04-06 18:56:24 +03:00
return m_storage - > isWritable ( ) ;
2019-04-06 02:00:37 +03:00
}
void GenericLayout : : lock ( )
{
2019-04-06 18:56:24 +03:00
m_storage - > lock ( ) ;
2019-04-06 02:00:37 +03:00
}
void GenericLayout : : unlock ( )
{
2019-04-06 18:56:24 +03:00
m_storage - > unlock ( ) ;
2019-04-06 02:00:37 +03:00
}
void GenericLayout : : syncToLayoutFile ( bool removeLayoutId )
{
2019-04-06 18:56:24 +03:00
m_storage - > syncToLayoutFile ( removeLayoutId ) ;
2019-04-06 02:00:37 +03:00
}
void GenericLayout : : copyView ( Plasma : : Containment * containment )
{
2019-04-06 18:56:24 +03:00
m_storage - > copyView ( containment ) ;
2019-05-12 01:18:18 +03:00
emit viewEdgeChanged ( ) ;
2019-04-06 02:00:37 +03:00
}
void GenericLayout : : importToCorona ( )
{
2019-04-06 18:56:24 +03:00
m_storage - > importToCorona ( ) ;
2019-04-06 02:00:37 +03:00
}
bool GenericLayout : : layoutIsBroken ( ) const
{
2019-04-06 18:56:24 +03:00
return m_storage - > layoutIsBroken ( ) ;
2019-04-06 02:00:37 +03:00
}
2019-04-05 19:59:15 +03:00
}
}