2017-07-02 15:02:07 +03:00
/*
* Copyright 2017 Smith AR < audoban @ openmailbox . org >
* 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 "layoutmanager.h"
2017-07-26 10:21:37 +03:00
# include "infoview.h"
2017-07-03 12:58:02 +03:00
# include <QDir>
# include <QFile>
2017-07-25 14:06:48 +03:00
# include <QQmlProperty>
2017-07-03 19:04:37 +03:00
# include <QtDBus/QtDBus>
2017-07-03 12:58:02 +03:00
2017-07-18 21:18:33 +03:00
# include <KActivities/Consumer>
2017-07-23 21:05:34 +03:00
# include <KLocalizedString>
# include <KNotification>
2017-07-03 12:58:02 +03:00
2017-07-02 15:02:07 +03:00
namespace Latte {
LayoutManager : : LayoutManager ( QObject * parent )
: QObject ( parent ) ,
2017-07-31 03:53:39 +03:00
m_importer ( new Importer ( this ) ) ,
m_launchersSignals ( new LaunchersSignals ( this ) )
2017-07-02 15:02:07 +03:00
{
2017-07-02 20:19:18 +03:00
m_corona = qobject_cast < DockCorona * > ( parent ) ;
2017-07-03 19:04:37 +03:00
if ( m_corona ) {
//! create the add widgets action
const QIcon addWidIcon = QIcon : : fromTheme ( " add " ) ;
m_addWidgetsAction = new QAction ( addWidIcon , i18n ( " Add Widgets... " ) , this ) ;
m_addWidgetsAction - > setStatusTip ( i18n ( " Show Plasma Widget Explorer " ) ) ;
connect ( m_addWidgetsAction , & QAction : : triggered , this , & LayoutManager : : showWidgetsExplorer ) ;
2017-07-03 20:40:18 +03:00
connect ( m_corona - > universalSettings ( ) , & UniversalSettings : : currentLayoutNameChanged , this , & LayoutManager : : currentLayoutNameChanged ) ;
2017-07-26 10:30:03 +03:00
connect ( m_corona - > universalSettings ( ) , & UniversalSettings : : showInfoWindowChanged , this , & LayoutManager : : showInfoWindowChanged ) ;
2017-07-23 21:05:34 +03:00
m_dynamicSwitchTimer . setSingleShot ( true ) ;
2017-07-26 10:30:03 +03:00
showInfoWindowChanged ( ) ;
2017-07-23 21:05:34 +03:00
connect ( & m_dynamicSwitchTimer , & QTimer : : timeout , this , & LayoutManager : : confirmDynamicSwitch ) ;
2017-07-03 19:04:37 +03:00
}
2017-07-02 15:02:07 +03:00
}
LayoutManager : : ~ LayoutManager ( )
{
m_importer - > deleteLater ( ) ;
2017-07-31 03:53:39 +03:00
m_launchersSignals - > deleteLater ( ) ;
2017-07-03 19:25:16 +03:00
if ( m_currentLayout ) {
m_currentLayout - > deleteLater ( ) ;
}
2017-07-02 15:02:07 +03:00
}
2017-07-02 20:19:18 +03:00
void LayoutManager : : load ( )
{
int configVer = m_corona - > universalSettings ( ) - > version ( ) ;
qDebug ( ) < < " Universal Settings version : " < < configVer ;
2017-07-03 21:18:13 +03:00
if ( configVer < 2 & & QFile ( QDir : : homePath ( ) + " /.config/lattedockrc " ) . exists ( ) ) {
2017-07-02 20:19:18 +03:00
qDebug ( ) < < " Latte must update its configuration... " ;
m_importer - > updateOldConfiguration ( ) ;
2017-07-23 00:24:26 +03:00
importPresets ( false ) ;
2017-07-03 21:18:13 +03:00
} else if ( ! QFile ( QDir : : homePath ( ) + " /.config/lattedockrc " ) . exists ( ) ) {
2017-07-03 21:09:16 +03:00
//startup create what is necessary....
QDir layoutDir ( QDir : : homePath ( ) + " /.config/latte " ) ;
if ( ! layoutDir . exists ( ) ) {
QDir ( QDir : : homePath ( ) + " /.config " ) . mkdir ( " latte " ) ;
}
newLayout ( i18n ( " My Layout " ) ) ;
2017-07-23 00:24:26 +03:00
importPresets ( false ) ;
2017-07-03 21:09:16 +03:00
m_corona - > universalSettings ( ) - > setCurrentLayoutName ( i18n ( " My Layout " ) ) ;
m_corona - > universalSettings ( ) - > setVersion ( 2 ) ;
2017-07-02 20:19:18 +03:00
}
2017-07-02 21:22:37 +03:00
qDebug ( ) < < " Latte is loading its layouts... " ;
2017-07-03 20:40:18 +03:00
2017-07-23 21:05:34 +03:00
connect ( m_corona - > m_activityConsumer , & KActivities : : Consumer : : currentActivityChanged ,
this , & LayoutManager : : currentActivityChanged ) ;
2017-07-03 20:40:18 +03:00
loadLayouts ( ) ;
2017-07-02 20:19:18 +03:00
}
2017-07-02 21:02:27 +03:00
DockCorona * LayoutManager : : corona ( )
{
return m_corona ;
}
2017-07-22 19:49:28 +03:00
Importer * LayoutManager : : importer ( )
{
return m_importer ;
}
2017-07-03 19:04:37 +03:00
QAction * LayoutManager : : addWidgetsAction ( )
{
return m_addWidgetsAction ;
}
2017-07-03 19:25:16 +03:00
LayoutSettings * LayoutManager : : currentLayout ( )
{
return m_currentLayout ;
}
2017-07-31 03:53:39 +03:00
LaunchersSignals * LayoutManager : : launchersSignals ( )
{
return m_launchersSignals ;
}
2017-07-03 20:40:18 +03:00
QString LayoutManager : : currentLayoutName ( ) const
{
if ( m_corona & & m_corona - > universalSettings ( ) ) {
return m_corona - > universalSettings ( ) - > currentLayoutName ( ) ;
}
return QString ( ) ;
}
2017-12-17 17:01:30 +02:00
QString LayoutManager : : defaultLayoutName ( ) const
{
QByteArray presetNameOrig = QString ( " preset " + QString : : number ( 1 ) ) . toUtf8 ( ) ;
QString presetPath = m_corona - > kPackage ( ) . filePath ( presetNameOrig ) ;
QString presetName = LayoutSettings : : layoutName ( presetPath ) ;
QByteArray presetNameChars = presetName . toUtf8 ( ) ;
presetName = i18n ( presetNameChars ) ;
return presetName ;
}
bool LayoutManager : : layoutExists ( QString layoutName ) const
{
return m_layouts . contains ( layoutName ) ;
}
2017-07-03 20:40:18 +03:00
QStringList LayoutManager : : layouts ( ) const
{
return m_layouts ;
}
2017-07-17 18:47:48 +03:00
QStringList LayoutManager : : menuLayouts ( ) const
{
2017-07-23 21:05:34 +03:00
QStringList fixedMenuLayouts = m_menuLayouts ;
//! in case the current layout isnt checked to be shown in the menus
//! we must add it on top
if ( ! fixedMenuLayouts . contains ( currentLayoutName ( ) ) ) {
fixedMenuLayouts . prepend ( currentLayoutName ( ) ) ;
}
return fixedMenuLayouts ;
2017-07-17 18:47:48 +03:00
}
2017-07-20 18:02:58 +03:00
void LayoutManager : : setMenuLayouts ( QStringList layouts )
{
if ( m_menuLayouts = = layouts ) {
return ;
}
m_menuLayouts = layouts ;
emit menuLayoutsChanged ( ) ;
}
2017-07-18 21:18:33 +03:00
QStringList LayoutManager : : activities ( )
{
return m_corona - > m_activityConsumer - > activities ( ) ;
}
2017-07-22 10:39:35 +03:00
QStringList LayoutManager : : presetsPaths ( ) const
{
return m_presetsPaths ;
}
2017-07-03 10:41:59 +03:00
QString LayoutManager : : layoutPath ( QString layoutName )
{
QString path = QDir : : homePath ( ) + " /.config/latte/ " + layoutName + " .layout.latte " ;
if ( ! QFile ( path ) . exists ( ) ) {
path = " " ;
}
return path ;
}
2017-07-23 21:05:34 +03:00
void LayoutManager : : currentActivityChanged ( const QString & id )
{
qDebug ( ) < < " activity changed :: " < < id ;
m_shouldSwitchToLayout = shouldSwitchToLayout ( id ) ;
m_dynamicSwitchTimer . start ( ) ;
}
2017-07-26 10:30:03 +03:00
void LayoutManager : : showInfoWindowChanged ( )
{
if ( m_corona - > universalSettings ( ) - > showInfoWindow ( ) ) {
m_dynamicSwitchTimer . setInterval ( 1800 ) ;
} else {
m_dynamicSwitchTimer . setInterval ( 2300 ) ;
}
}
2017-07-23 21:05:34 +03:00
QString LayoutManager : : shouldSwitchToLayout ( QString activityId )
{
if ( m_assignedLayouts . contains ( activityId ) & & m_assignedLayouts [ activityId ] ! = currentLayoutName ( ) ) {
return m_assignedLayouts [ activityId ] ;
} else if ( ! m_assignedLayouts . contains ( activityId ) & & ! m_corona - > universalSettings ( ) - > lastNonAssignedLayoutName ( ) . isEmpty ( )
& & m_corona - > universalSettings ( ) - > lastNonAssignedLayoutName ( ) ! = currentLayoutName ( ) ) {
return m_corona - > universalSettings ( ) - > lastNonAssignedLayoutName ( ) ;
}
return QString ( ) ;
}
void LayoutManager : : confirmDynamicSwitch ( )
{
QString tempShouldSwitch = shouldSwitchToLayout ( m_corona - > m_activityConsumer - > currentActivity ( ) ) ;
2017-07-23 22:31:18 +03:00
if ( tempShouldSwitch . isEmpty ( ) ) {
return ;
}
if ( m_shouldSwitchToLayout = = tempShouldSwitch & & m_shouldSwitchToLayout ! = currentLayoutName ( ) ) {
2017-07-23 21:05:34 +03:00
qDebug ( ) < < " dynamic switch to layout :: " < < m_shouldSwitchToLayout ;
2017-07-25 14:19:01 +03:00
if ( m_corona - > universalSettings ( ) - > showInfoWindow ( ) ) {
showInfoWindow ( i18n ( " Switching to layout <b>%0</b> ... " ) . arg ( m_shouldSwitchToLayout ) , 4000 ) ;
QTimer : : singleShot ( 500 , [ this , tempShouldSwitch ] ( ) {
switchToLayout ( tempShouldSwitch ) ;
} ) ;
} else {
switchToLayout ( m_shouldSwitchToLayout ) ;
}
2017-07-23 22:31:18 +03:00
2017-07-23 21:05:34 +03:00
} else {
m_shouldSwitchToLayout = tempShouldSwitch ;
m_dynamicSwitchTimer . start ( ) ;
}
}
2017-07-03 20:40:18 +03:00
void LayoutManager : : loadLayouts ( )
{
m_layouts . clear ( ) ;
2017-07-17 18:47:48 +03:00
m_menuLayouts . clear ( ) ;
2017-07-22 10:39:35 +03:00
m_presetsPaths . clear ( ) ;
2017-07-23 21:05:34 +03:00
m_assignedLayouts . clear ( ) ;
2017-07-03 20:40:18 +03:00
QDir layoutDir ( QDir : : homePath ( ) + " /.config/latte " ) ;
QStringList filter ;
filter . append ( QString ( " *.layout.latte " ) ) ;
QStringList files = layoutDir . entryList ( filter , QDir : : Files | QDir : : NoSymLinks ) ;
foreach ( auto layout , files ) {
2017-07-17 18:47:48 +03:00
LayoutSettings layoutSets ( this , layoutDir . absolutePath ( ) + " / " + layout ) ;
2017-07-03 20:40:18 +03:00
2017-07-23 21:05:34 +03:00
QStringList validActivityIds = validActivities ( layoutSets . activities ( ) ) ;
layoutSets . setActivities ( validActivityIds ) ;
foreach ( auto activity , validActivityIds ) {
m_assignedLayouts [ activity ] = layoutSets . name ( ) ;
}
2017-07-17 18:47:48 +03:00
m_layouts . append ( layoutSets . name ( ) ) ;
if ( layoutSets . showInMenu ( ) ) {
m_menuLayouts . append ( layoutSets . name ( ) ) ;
}
2017-07-03 20:40:18 +03:00
}
2017-07-22 10:39:35 +03:00
m_presetsPaths . append ( m_corona - > kPackage ( ) . filePath ( " preset1 " ) ) ;
m_presetsPaths . append ( m_corona - > kPackage ( ) . filePath ( " preset2 " ) ) ;
m_presetsPaths . append ( m_corona - > kPackage ( ) . filePath ( " preset3 " ) ) ;
m_presetsPaths . append ( m_corona - > kPackage ( ) . filePath ( " preset4 " ) ) ;
2017-07-03 20:40:18 +03:00
emit layoutsChanged ( ) ;
2017-07-17 18:47:48 +03:00
emit menuLayoutsChanged ( ) ;
2017-07-03 20:40:18 +03:00
}
2017-07-03 19:04:37 +03:00
bool LayoutManager : : switchToLayout ( QString layoutName )
2017-07-03 12:58:02 +03:00
{
2017-07-03 19:25:16 +03:00
if ( m_currentLayout & & m_currentLayout - > name ( ) = = layoutName ) {
return false ;
}
2017-07-03 19:04:37 +03:00
QString lPath = layoutPath ( layoutName ) ;
if ( lPath . isEmpty ( ) & & layoutName = = i18n ( " Alternative " ) ) {
lPath = newLayout ( i18n ( " Alternative " ) , i18n ( " Default " ) ) ;
}
if ( ! lPath . isEmpty ( ) ) {
//! this code must be called asynchronously because it is called
//! also from qml (Tasks plasmoid). This change fixes a very important
//! crash when switching sessions through the Tasks plasmoid Context menu
//! Latte was unstable and was crashing very often during changing
2017-07-23 22:31:18 +03:00
//! sessions.
2017-07-19 17:36:55 +03:00
QTimer : : singleShot ( 0 , [ this , layoutName , lPath ] ( ) {
2017-07-03 19:04:37 +03:00
qDebug ( ) < < layoutName < < " - " < < lPath ;
2017-07-23 21:05:34 +03:00
2017-07-03 19:04:37 +03:00
m_corona - > loadLatteLayout ( lPath ) ;
m_corona - > universalSettings ( ) - > setCurrentLayoutName ( layoutName ) ;
2017-07-23 21:05:34 +03:00
if ( ! layoutIsAssigned ( layoutName ) ) {
m_corona - > universalSettings ( ) - > setLastNonAssignedLayoutName ( layoutName ) ;
}
2017-07-03 19:25:16 +03:00
if ( m_currentLayout ) {
m_currentLayout - > deleteLater ( ) ;
}
m_currentLayout = new LayoutSettings ( this , lPath , layoutName ) ;
emit currentLayoutChanged ( ) ;
2017-07-03 19:04:37 +03:00
} ) ;
}
2017-07-25 12:09:14 +03:00
return true ;
2017-07-03 19:04:37 +03:00
}
QString LayoutManager : : newLayout ( QString layoutName , QString preset )
{
QDir layoutDir ( QDir : : homePath ( ) + " /.config/latte " ) ;
QStringList filter ;
filter . append ( QString ( layoutName + " *.layout.latte " ) ) ;
QStringList files = layoutDir . entryList ( filter , QDir : : Files | QDir : : NoSymLinks ) ;
//! if the newLayout already exists provide a newName that doesnt
if ( files . count ( ) > = 1 ) {
int newCounter = files . count ( ) + 1 ;
layoutName = layoutName + " - " + QString : : number ( newCounter ) ;
}
QString newLayoutPath = layoutDir . absolutePath ( ) + " / " + layoutName + " .layout.latte " ;
2017-07-03 12:58:02 +03:00
qDebug ( ) < < " adding layout : " < < layoutName < < " based on preset: " < < preset ;
2017-07-03 19:04:37 +03:00
if ( preset = = i18n ( " Default " ) & & ! QFile ( newLayoutPath ) . exists ( ) ) {
2017-07-03 12:58:02 +03:00
qDebug ( ) < < " adding layout : succeed " ;
2017-07-03 19:04:37 +03:00
QFile ( m_corona - > kPackage ( ) . filePath ( " preset1 " ) ) . copy ( newLayoutPath ) ;
2017-07-03 12:58:02 +03:00
}
2017-07-03 21:33:27 +03:00
return newLayoutPath ;
2017-07-03 19:04:37 +03:00
}
2017-12-17 17:42:49 +02:00
void LayoutManager : : importDefaultLayout ( bool newInstanceIfPresent )
2017-12-17 17:01:30 +02:00
{
2017-12-17 17:42:49 +02:00
importPreset ( 1 , newInstanceIfPresent ) ;
2017-12-17 17:01:30 +02:00
}
2017-07-23 00:24:26 +03:00
void LayoutManager : : importPresets ( bool includeDefault )
{
int start = 1 ;
if ( ! includeDefault ) {
start = 2 ;
}
for ( int i = start ; i < = 4 ; + + i ) {
2017-12-17 17:42:49 +02:00
importPreset ( i , false ) ;
2017-12-17 17:01:30 +02:00
}
}
2017-07-23 00:24:26 +03:00
2017-12-17 17:42:49 +02:00
void LayoutManager : : importPreset ( int presetNo , bool newInstanceIfPresent )
2017-12-17 17:01:30 +02:00
{
QByteArray presetNameOrig = QString ( " preset " + QString : : number ( presetNo ) ) . toUtf8 ( ) ;
QString presetPath = m_corona - > kPackage ( ) . filePath ( presetNameOrig ) ;
QString presetName = LayoutSettings : : layoutName ( presetPath ) ;
QByteArray presetNameChars = presetName . toUtf8 ( ) ;
presetName = i18n ( presetNameChars ) ;
2017-07-23 00:24:26 +03:00
2017-12-17 17:42:49 +02:00
QString newLayoutFile = " " ;
if ( newInstanceIfPresent ) {
newLayoutFile = QDir : : homePath ( ) + " /.config/latte/ " + m_importer - > uniqueLayoutName ( presetName ) + " .layout.latte " ;
} else {
newLayoutFile = QDir : : homePath ( ) + " /.config/latte/ " + presetName + " .layout.latte " ;
}
2017-12-17 17:01:30 +02:00
if ( ! QFile ( newLayoutFile ) . exists ( ) ) {
QFile ( presetPath ) . copy ( newLayoutFile ) ;
2017-07-23 00:24:26 +03:00
}
}
2017-07-23 21:05:34 +03:00
QStringList LayoutManager : : validActivities ( QStringList currentList )
{
QStringList validIds ;
foreach ( auto activity , currentList ) {
if ( activities ( ) . contains ( activity ) ) {
validIds . append ( activity ) ;
}
}
return validIds ;
}
bool LayoutManager : : layoutIsAssigned ( QString layoutName )
{
QHashIterator < const QString , QString > i ( m_assignedLayouts ) ;
while ( i . hasNext ( ) ) {
i . next ( ) ;
if ( i . value ( ) = = layoutName ) {
return true ;
}
}
return false ;
}
2017-07-07 14:06:30 -05:00
void LayoutManager : : showLayoutConfigDialog ( )
{
if ( ! m_layoutConfigDialog )
2017-07-17 22:07:04 +03:00
m_layoutConfigDialog = new LayoutConfigDialog ( nullptr , this ) ;
2017-07-07 14:06:30 -05:00
m_layoutConfigDialog - > show ( ) ;
2017-07-30 19:49:05 +03:00
if ( m_layoutConfigDialog - > isMinimized ( ) ) {
m_layoutConfigDialog - > showNormal ( ) ;
}
m_layoutConfigDialog - > activateWindow ( ) ;
2017-07-07 14:06:30 -05:00
}
2017-07-25 14:06:48 +03:00
void LayoutManager : : showInfoWindow ( QString info , int duration )
{
2017-07-26 10:21:37 +03:00
foreach ( auto screen , qGuiApp - > screens ( ) ) {
InfoView * infoView = new InfoView ( m_corona , info , screen ) ;
2017-07-25 14:06:48 +03:00
2017-07-26 10:21:37 +03:00
infoView - > show ( ) ;
2017-07-25 14:06:48 +03:00
2017-07-26 10:21:37 +03:00
QTimer : : singleShot ( duration , [ this , infoView ] ( ) {
infoView - > deleteLater ( ) ;
} ) ;
}
2017-07-25 14:06:48 +03:00
}
2017-07-03 19:04:37 +03:00
void LayoutManager : : showWidgetsExplorer ( )
{
QDBusInterface iface ( " org.kde.plasmashell " , " /PlasmaShell " , " " , QDBusConnection : : sessionBus ( ) ) ;
if ( iface . isValid ( ) ) {
iface . call ( " toggleWidgetExplorer " ) ;
}
2017-07-03 12:58:02 +03:00
}
2017-07-25 15:59:06 +03:00
//! it is used just in order to provide translations for the presets
void LayoutManager : : ghostForTranslatedPresets ( )
{
QString preset1 = i18n ( " Default " ) ;
QString preset2 = i18n ( " Plasma " ) ;
QString preset3 = i18n ( " Unity " ) ;
QString preset4 = i18n ( " Extended " ) ;
}
2017-07-02 15:02:07 +03:00
}