2014-11-15 03:32:08 +02:00
/*
* Copyright 2007 by Alex Merry < alex . merry @ kdemail . net >
* Copyright 2008 by Alexis Ménard < darktears31 @ gmail . com >
* Copyright 2008 by Aaron Seigo < aseigo @ kde . org >
* Copyright 2009 by Marco Martin < notmart @ gmail . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU Library General Public License version 2 ,
* or ( at your option ) any later version .
*
* This program 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 Library General Public
* License along with this program ; if not , write to the
* Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*/
# include "newspaper.h"
# include "appletoverlay.h"
# include "applettitlebar.h"
# include "appletscontainer.h"
# include "appletsview.h"
# include <limits>
# include <QAction>
# include <QGraphicsLinearLayout>
# include <QTimer>
2015-08-12 13:11:16 +03:00
# include <QtGui/qgraphicssceneevent.h>
2014-11-15 03:32:08 +02:00
# include <KDebug>
# include <KIcon>
# include <Plasma/AbstractToolBox>
# include <Plasma/Corona>
# include <Plasma/FrameSvg>
# include <Plasma/Theme>
# include <Plasma/View>
# include <Plasma/PopupApplet>
# include <Plasma/Frame>
# include <Plasma/ToolButton>
using namespace Plasma ;
Newspaper : : Newspaper ( QObject * parent , const QVariantList & args )
: Containment ( parent , args ) ,
m_orientation ( Qt : : Vertical ) ,
m_expandAll ( false ) ,
m_appletOverlay ( 0 )
{
setContainmentType ( Containment : : CustomContainment ) ;
m_scrollWidget = new AppletsView ( this ) ;
m_container = new AppletsContainer ( m_scrollWidget ) ;
connect ( this , SIGNAL ( appletRemoved ( Plasma : : Applet * ) ) ,
this , SLOT ( refreshLayout ( ) ) ) ;
connect ( m_scrollWidget , SIGNAL ( dropRequested ( QGraphicsSceneDragDropEvent * ) ) ,
this , SLOT ( viewRequestedDrop ( QGraphicsSceneDragDropEvent * ) ) ) ;
connect ( this , SIGNAL ( toolBoxVisibilityChanged ( bool ) ) , this , SLOT ( updateConfigurationMode ( bool ) ) ) ;
}
Newspaper : : ~ Newspaper ( )
{
delete m_appletOverlay ;
config ( ) . writeEntry ( " orientation " , ( int ) m_orientation ) ;
}
void Newspaper : : init ( )
{
m_externalLayout = new QGraphicsLinearLayout ( this ) ;
m_externalLayout - > setContentsMargins ( 0 , 0 , 0 , 0 ) ;
m_externalLayout - > addItem ( m_scrollWidget ) ;
m_scrollWidget - > setAppletsContainer ( m_container ) ;
connect ( m_container , SIGNAL ( appletActivated ( Plasma : : Applet * ) ) , this , SLOT ( appletActivated ( Plasma : : Applet * ) ) ) ;
m_updateSizeTimer = new QTimer ( this ) ;
m_updateSizeTimer - > setSingleShot ( true ) ;
connect ( m_updateSizeTimer , SIGNAL ( timeout ( ) ) , m_container , SLOT ( updateSize ( ) ) ) ;
m_relayoutTimer = new QTimer ( this ) ;
m_relayoutTimer - > setSingleShot ( true ) ;
connect ( m_relayoutTimer , SIGNAL ( timeout ( ) ) , m_container , SLOT ( updateSize ( ) ) ) ;
connect ( m_relayoutTimer , SIGNAL ( timeout ( ) ) , m_container , SLOT ( cleanupColumns ( ) ) ) ;
connect ( m_container , SIGNAL ( appletSizeHintChanged ( ) ) , this , SLOT ( appletSizeHintChanged ( ) ) ) ;
configChanged ( ) ;
m_container - > addColumn ( ) ;
setOrientation ( m_orientation ) ;
Plasma : : Svg * borderSvg = new Plasma : : Svg ( this ) ;
borderSvg - > setImagePath ( " newspaper/border " ) ;
Containment : : init ( ) ;
setHasConfigurationInterface ( true ) ;
setToolBox ( Plasma : : AbstractToolBox : : load ( corona ( ) - > preferredToolBoxPlugin ( Plasma : : Containment : : DesktopContainment ) , QVariantList ( ) , this ) ) ;
QAction * a = action ( " add widgets " ) ;
if ( a ) {
addToolBoxAction ( a ) ;
}
if ( toolBox ( ) ) {
connect ( toolBox ( ) , SIGNAL ( toggled ( ) ) , this , SIGNAL ( toolBoxToggled ( ) ) ) ;
connect ( toolBox ( ) , SIGNAL ( visibilityChanged ( bool ) ) , this , SIGNAL ( toolBoxVisibilityChanged ( bool ) ) ) ;
toolBox ( ) - > show ( ) ;
}
a = new QAction ( KIcon ( " view-fullscreen " ) , i18n ( " Expand widgets " ) , this ) ;
addAction ( " expand widgets " , a ) ;
addToolBoxAction ( a ) ;
connect ( a , SIGNAL ( triggered ( ) ) , this , SLOT ( toggleExpandAllApplets ( ) ) ) ;
if ( m_expandAll ) {
a - > setIcon ( KIcon ( " view-restore " ) ) ;
a - > setText ( i18n ( " Collapse widgets " ) ) ;
}
a - > setEnabled ( m_orientation = = Qt : : Vertical ) ;
a - > setVisible ( m_orientation = = Qt : : Vertical ) ;
a = action ( " configure " ) ;
if ( a ) {
a - > setText ( i18n ( " Configure page " ) ) ;
addToolBoxAction ( a ) ;
}
QAction * lockAction = 0 ;
if ( corona ( ) ) {
lockAction = corona ( ) - > action ( " lock widgets " ) ;
}
if ( ! lockAction | | ! lockAction - > isEnabled ( ) ) {
lockAction = new QAction ( this ) ;
addAction ( " lock page " , lockAction ) ;
lockAction - > setText ( i18n ( " Lock page " ) ) ;
lockAction - > setIcon ( KIcon ( " object-locked " ) ) ;
QObject : : connect ( lockAction , SIGNAL ( triggered ( bool ) ) , this , SLOT ( toggleImmutability ( ) ) ) ;
}
addToolBoxAction ( lockAction ) ;
//FIXME: two different use cases for the desktop and the newspaper, another reason to move the toolbox management out of here
QAction * activityAction = 0 ;
if ( corona ( ) ) {
activityAction = corona ( ) - > action ( " manage activities " ) ;
}
if ( activityAction ) {
addToolBoxAction ( activityAction ) ;
} else {
a = action ( " remove " ) ;
if ( a ) {
a - > setText ( i18n ( " Remove page " ) ) ;
addToolBoxAction ( a ) ;
}
}
a = new QAction ( i18n ( " Next activity " ) , this ) ;
addAction ( " next containment " , a ) ;
a = new QAction ( i18n ( " Previous activity " ) , this ) ;
addAction ( " previous containment " , a ) ;
if ( corona ( ) ) {
connect ( corona ( ) , SIGNAL ( availableScreenRegionChanged ( ) ) , this , SLOT ( availableScreenRegionChanged ( ) ) ) ;
availableScreenRegionChanged ( ) ;
}
}
void Newspaper : : configChanged ( )
{
m_orientation = ( Qt : : Orientation ) config ( ) . readEntry ( " orientation " , ( int ) Qt : : Vertical ) ;
m_container - > setOrientation ( m_orientation ) ;
m_expandAll = config ( ) . readEntry ( " ExpandAllApplets " , false ) ;
m_container - > setExpandAll ( m_expandAll ) ;
}
void Newspaper : : updateSize ( )
{
m_container - > updateSize ( ) ;
}
void Newspaper : : toggleImmutability ( )
{
if ( immutability ( ) = = Plasma : : UserImmutable ) {
setImmutability ( Plasma : : Mutable ) ;
} else if ( immutability ( ) = = Plasma : : Mutable ) {
setImmutability ( Plasma : : UserImmutable ) ;
}
}
void Newspaper : : toggleExpandAllApplets ( )
{
m_expandAll = ! m_expandAll ;
QAction * a = action ( " expand widgets " ) ;
if ( a ) {
if ( m_expandAll ) {
a - > setIcon ( KIcon ( " view-restore " ) ) ;
a - > setText ( i18n ( " Collapse widgets " ) ) ;
} else {
a - > setIcon ( KIcon ( " view-fullscreen " ) ) ;
a - > setText ( i18n ( " Expand widgets " ) ) ;
}
}
m_container - > setExpandAll ( m_expandAll ) ;
config ( ) . writeEntry ( " ExpandAllApplets " , m_expandAll ) ;
}
void Newspaper : : refreshLayout ( )
{
if ( ! m_relayoutTimer - > isActive ( ) ) {
m_relayoutTimer - > start ( 200 ) ;
}
}
void Newspaper : : setOrientation ( Qt : : Orientation orientation )
{
m_orientation = orientation ;
m_container - > setOrientation ( m_orientation ) ;
m_externalLayout - > setOrientation ( m_orientation ) ;
QAction * expandAction = action ( " expand widgets " ) ;
if ( expandAction ) {
expandAction - > setEnabled ( orientation = = Qt : : Vertical ) ;
expandAction - > setVisible ( orientation = = Qt : : Vertical ) ;
}
if ( m_orientation = = Qt : : Vertical ) {
m_container - > setSizePolicy ( QSizePolicy : : Expanding , QSizePolicy : : Fixed ) ;
} else {
m_container - > setSizePolicy ( QSizePolicy : : Preferred , QSizePolicy : : Expanding ) ;
}
for ( int i = 0 ; i < m_container - > count ( ) ; + + i ) {
QGraphicsLinearLayout * lay = dynamic_cast < QGraphicsLinearLayout * > ( m_container - > itemAt ( i ) ) ;
if ( ! lay ) {
continue ;
}
lay - > setOrientation ( orientation ) ;
}
}
Plasma : : Applet * Newspaper : : addApplet ( const QString & appletName , const int row , const int column )
{
m_container - > setAutomaticAppletLayout ( false ) ;
Plasma : : Applet * applet = Containment : : addApplet ( appletName ) ;
m_container - > addApplet ( applet , row , column ) ;
m_container - > setAutomaticAppletLayout ( true ) ;
return applet ;
}
Plasma : : Applet * Newspaper : : addApplet ( Plasma : : Applet * applet , const int row , const int column )
{
m_container - > setAutomaticAppletLayout ( false ) ;
Containment : : addApplet ( applet ) ;
m_container - > addApplet ( applet , row , column ) ;
m_container - > setAutomaticAppletLayout ( true ) ;
return applet ;
}
Qt : : Orientation Newspaper : : orientation ( ) const
{
return m_orientation ;
}
void Newspaper : : appletSizeHintChanged ( )
{
if ( m_updateSizeTimer ) {
m_updateSizeTimer - > start ( 200 ) ;
}
}
void Newspaper : : constraintsEvent ( Plasma : : Constraints constraints )
{
kDebug ( ) < < " constraints updated with " < < constraints < < " !!!!!! " ;
if ( constraints & Plasma : : StartupCompletedConstraint ) {
connect ( this , SIGNAL ( appletAdded ( Plasma : : Applet * , QPointF ) ) ,
m_container , SLOT ( layoutApplet ( Plasma : : Applet * , QPointF ) ) ) ;
Plasma : : Corona * c = corona ( ) ;
if ( c ) {
connect ( c , SIGNAL ( containmentAdded ( Plasma : : Containment * ) ) ,
this , SLOT ( containmentAdded ( Plasma : : Containment * ) ) ) ;
foreach ( Plasma : : Containment * containment , corona ( ) - > containments ( ) ) {
Newspaper * news = qobject_cast < Newspaper * > ( containment ) ;
if ( news ) {
connect ( news , SIGNAL ( destroyed ( QObject * ) ) ,
this , SLOT ( containmentRemoved ( QObject * ) ) ) ;
}
}
QTimer : : singleShot ( 100 , this , SLOT ( updateRemoveActionVisibility ( ) ) ) ;
}
}
if ( constraints & Plasma : : SizeConstraint & & m_appletOverlay ) {
m_appletOverlay - > resize ( size ( ) ) ;
}
if ( constraints & Plasma : : SizeConstraint ) {
availableScreenRegionChanged ( ) ;
m_container - > syncColumnSizes ( ) ;
}
if ( constraints & Plasma : : ImmutableConstraint ) {
QAction * a = action ( " lock page " ) ;
if ( a ) {
switch ( immutability ( ) ) {
case Plasma : : SystemImmutable :
a - > setEnabled ( false ) ;
a - > setVisible ( false ) ;
break ;
case Plasma : : UserImmutable :
a - > setText ( i18n ( " Unlock Page " ) ) ;
a - > setIcon ( KIcon ( " object-unlocked " ) ) ;
a - > setEnabled ( true ) ;
a - > setVisible ( true ) ;
break ;
case Plasma : : Mutable :
a - > setText ( i18n ( " Lock Page " ) ) ;
a - > setIcon ( KIcon ( " object-locked " ) ) ;
a - > setEnabled ( true ) ;
a - > setVisible ( true ) ;
break ;
}
}
a = action ( " add page " ) ;
if ( a ) {
if ( immutability ( ) = = Plasma : : Mutable ) {
a - > setEnabled ( true ) ;
a - > setVisible ( true ) ;
} else {
a - > setEnabled ( false ) ;
a - > setVisible ( false ) ;
}
}
if ( immutability ( ) = = Plasma : : Mutable & & ! m_appletOverlay & & toolBox ( ) & & toolBox ( ) - > isShowing ( ) ) {
m_appletOverlay = new AppletOverlay ( this ) ;
m_appletOverlay - > resize ( size ( ) ) ;
m_scrollWidget - > setImmediateDrag ( true ) ;
} else if ( immutability ( ) ! = Plasma : : Mutable & & m_appletOverlay & & toolBox ( ) & & toolBox ( ) - > isShowing ( ) ) {
m_appletOverlay - > deleteLater ( ) ;
m_appletOverlay = 0 ;
m_scrollWidget - > setImmediateDrag ( false ) ;
}
updateRemoveActionVisibility ( ) ;
}
}
void Newspaper : : updateConfigurationMode ( bool config )
{
if ( config & & ! m_appletOverlay & & immutability ( ) = = Plasma : : Mutable ) {
m_appletOverlay = new AppletOverlay ( this ) ;
m_appletOverlay - > resize ( size ( ) ) ;
m_scrollWidget - > setImmediateDrag ( true ) ;
} else if ( ! config ) {
delete m_appletOverlay ;
m_appletOverlay = 0 ;
m_scrollWidget - > setImmediateDrag ( false ) ;
}
if ( ! config ) {
m_container - > cleanupColumns ( ) ;
}
}
void Newspaper : : changeEvent ( QEvent * event )
{
if ( event - > type ( ) = = QEvent : : ContentsRectChange ) {
if ( toolBox ( ) & & toolBox ( ) - > isShowing ( ) ) {
updateConfigurationMode ( true ) ;
}
}
}
void Newspaper : : restore ( KConfigGroup & group )
{
Containment : : restore ( group ) ;
KConfigGroup appletsConfig ( & group , " Applets " ) ;
//the number of items in orderedApplets is the number of columns
QMap < int , QMap < int , Applet * > > orderedApplets ;
QList < Applet * > unorderedApplets ;
foreach ( Applet * applet , applets ( ) ) {
KConfigGroup appletConfig ( & appletsConfig , QString : : number ( applet - > id ( ) ) ) ;
KConfigGroup layoutConfig ( & appletConfig , " LayoutInformation " ) ;
int column = layoutConfig . readEntry ( " Column " , - 1 ) ;
int order = layoutConfig . readEntry ( " Order " , - 1 ) ;
if ( order > - 1 ) {
if ( column > - 1 ) {
orderedApplets [ column ] [ order ] = applet ;
} else {
unorderedApplets . append ( applet ) ;
}
//if LayoutInformation is not available use the usual way, as a bonus makes it retrocompatible with oler configs
} else {
unorderedApplets . append ( applet ) ;
}
connect ( applet , SIGNAL ( sizeHintChanged ( Qt : : SizeHint ) ) , this , SLOT ( appletSizeHintChanged ( ) ) ) ;
}
//if the required columns does not exist, create them
if ( m_container - > count ( ) < orderedApplets . count ( ) ) {
int columnsToAdd = orderedApplets . count ( ) - m_container - > count ( ) ;
for ( int i = 0 ; i < columnsToAdd ; + + i ) {
m_container - > addColumn ( ) ;
}
}
//finally add all the applets that had a layout information
int column = 0 ;
QMap < int , QMap < int , Applet * > > : : const_iterator it = orderedApplets . constBegin ( ) ;
while ( it ! = orderedApplets . constEnd ( ) ) {
QGraphicsLinearLayout * lay = dynamic_cast < QGraphicsLinearLayout * > ( m_container - > itemAt ( column ) ) ;
+ + column ;
//this should never happen
if ( ! lay ) {
+ + it ;
continue ;
}
foreach ( Applet * applet , it . value ( ) ) {
lay - > insertItem ( lay - > count ( ) - 1 , applet ) ;
m_container - > createAppletTitle ( applet ) ;
}
+ + it ;
}
//add all the remaining applets
foreach ( Applet * applet , unorderedApplets ) {
m_container - > layoutApplet ( applet , applet - > pos ( ) ) ;
}
m_container - > updateSize ( ) ;
}
void Newspaper : : saveContents ( KConfigGroup & group ) const
{
Containment : : saveContents ( group ) ;
KConfigGroup appletsConfig ( & group , " Applets " ) ;
for ( int column = 0 ; column < m_container - > count ( ) ; + + column ) {
QGraphicsLinearLayout * lay = static_cast < QGraphicsLinearLayout * > ( m_container - > itemAt ( column ) ) ;
for ( int row = 0 ; row < lay - > count ( ) ; + + row ) {
const Applet * applet = dynamic_cast < Applet * > ( lay - > itemAt ( row ) ) ;
if ( applet ) {
KConfigGroup appletConfig ( & appletsConfig , QString : : number ( applet - > id ( ) ) ) ;
appletConfig . deleteEntry ( " geometry " ) ;
appletConfig . deleteEntry ( " zvalue " ) ;
appletConfig . deleteEntry ( " transform " ) ;
KConfigGroup layoutConfig ( & appletConfig , " LayoutInformation " ) ;
layoutConfig . writeEntry ( " Column " , column ) ;
layoutConfig . writeEntry ( " Order " , row ) ;
}
}
}
}
void Newspaper : : updateRemoveActionVisibility ( )
{
int newspapers = 0 ;
foreach ( Plasma : : Containment * containment , corona ( ) - > containments ( ) ) {
if ( qobject_cast < Newspaper * > ( containment ) ) {
+ + newspapers ;
}
}
QAction * a = action ( " remove " ) ;
if ( a ) {
a - > setEnabled ( newspapers > 1 ) ;
a - > setVisible ( newspapers > 1 ) ;
}
}
void Newspaper : : containmentAdded ( Plasma : : Containment * containment )
{
//we now are sure there are at least two pages
Newspaper * news = qobject_cast < Newspaper * > ( containment ) ;
if ( news ) {
connect ( news , SIGNAL ( destroyed ( QObject * ) ) , this , SLOT ( containmentRemoved ( QObject * ) ) ) ;
QAction * a = action ( " remove " ) ;
if ( a ) {
a - > setEnabled ( true ) ;
a - > setVisible ( true ) ;
}
}
}
void Newspaper : : availableScreenRegionChanged ( )
{
if ( ! corona ( ) ) {
return ;
}
QRect maxRect ;
int maxArea = 0 ;
//we don't want the bounding rect (that could include panels too), but the maximumone representing the desktop
foreach ( const QRect & rect , corona ( ) - > availableScreenRegion ( screen ( ) ) . rects ( ) ) {
int area = rect . width ( ) * rect . height ( ) ;
if ( area > maxArea ) {
maxRect = rect ;
maxArea = area ;
}
}
QGraphicsView * ownView = view ( ) ;
//FIXME: the second check is a workaround to a qt bug: when a qwidget has just been created, maptoglobal and mapfromglobal aren't symmetryc. remove as soon as the bug is fixed
if ( ownView & & ( ownView - > mapFromGlobal ( QPoint ( 0 , 0 ) ) = = - ownView - > mapToGlobal ( QPoint ( 0 , 0 ) ) ) ) {
maxRect . moveTopLeft ( ownView - > mapFromGlobal ( maxRect . topLeft ( ) ) ) ;
}
maxRect . moveTopLeft ( QPoint ( qMax ( 0 , maxRect . left ( ) ) , qMax ( 0 , maxRect . top ( ) ) ) ) ;
setContentsMargins ( maxRect . left ( ) , maxRect . top ( ) , qMax ( ( qreal ) 0.0 , size ( ) . width ( ) - maxRect . right ( ) ) , qMax ( ( qreal ) 0.0 , size ( ) . height ( ) - maxRect . bottom ( ) ) ) ;
}
void Newspaper : : containmentRemoved ( QObject * containment )
{
if ( ! corona ( ) ) {
return ;
}
if ( qobject_cast < Newspaper * > ( containment ) ) {
updateRemoveActionVisibility ( ) ;
}
}
void Newspaper : : viewRequestedDrop ( QGraphicsSceneDragDropEvent * event )
{
event - > setPos ( mapFromScene ( event - > scenePos ( ) ) ) ;
dropEvent ( event ) ;
}
//They all have to be reimplemented in order to accept them
void Newspaper : : dragEnterEvent ( QGraphicsSceneDragDropEvent * event )
{
Containment : : dragEnterEvent ( event ) ;
}
void Newspaper : : dragLeaveEvent ( QGraphicsSceneDragDropEvent * event )
{
Containment : : dragLeaveEvent ( event ) ;
}
void Newspaper : : dragMoveEvent ( QGraphicsSceneDragDropEvent * event )
{
Containment : : dragMoveEvent ( event ) ;
event - > accept ( ) ;
}
void Newspaper : : dropEvent ( QGraphicsSceneDragDropEvent * event )
{
Containment : : dropEvent ( event ) ;
event - > accept ( ) ;
}
K_EXPORT_PLASMA_APPLET ( newspaper , Newspaper )
2015-02-27 09:28:46 +00:00
# include "moc_newspaper.cpp"
2014-11-15 03:32:08 +02:00