Plasma Media Center and state machines

Christophe Olinger olingerc at binarylooks.com
Thu Apr 1 19:44:51 CEST 2010


Hallo everybody,

Since I am still realy new to Qt, plasma and KDE, I made a small draft
of how I would imagine handling implemeting state machines in the PMC
code.
Please feel very free on adding and commenting ideas, and pointing out
stupid things. Marco and Aaron were already so nice to give me a small
nudge in the hopefully right direction.

Thanks all,

Chris (aka binarylooks)
___________________________

1) the top level libs (mediacenter.h) class knows about which types of
applets (=UIComponents) exist and which states exist

Example:
enum State {
    BrowseVideos;
    PlayVideos;
    PlayMusic;
    MusicVisualizations;
    BrowsePictures;
    SinglePictures;
    PicturesSlideshow;
}

enum UIComponent {
    ControlBar;
    InfoBar;
    Browser;
    Player;
    Playlist;
    HomeScreen;
}
_________________________________

2) there is a MediaCenterState class which keeps track of all possible
smallwidgets (=subComponents) for the whole PMC and can hand out
pointers to them.
(Maybe the state objects can do that for the widgets that are needed
in their state)

Example:
enum subComponent {
    iconVideoMode;
    iconMusciMode;
    iconPictureMode;
    iconHomeScreen;
    iconTogglePlaylistAutohide;
    iconToggleControlBarAutohide;
    iconToggleInfoBarAutohide;
    iconVideoModePlayPause;
    iconVideoModeSkipForward;
    iconVideoModeSkipBackward;
    iconVideoModeStop;
    iconMusicModePlayPause;
    iconMusicModeSkipForward;
    iconMusicModeSkipBackward;
    iconMusicModeStop;
    sliderMusicModeVolume;
    sliderMusicModeSeek;
    iconSlideshow;
    iconRotateCW;
    iconRotateCCW;
    ...
}

class MEDIACENTER_EXPORT MediaCenterState(QObject *parent)
    : QAbstractState(parent)
    m_iconVideosMode(new Plasma::IconWidget(this))
    //initialize all of them
{
}

//here we handle the pointers of the created objects (the enum,
initialilzation and pointer handling could be in the actual subclass
of the state objects
QGraphicsWidget
*BrowseVideoState::giveComponent(MediaCenter::subComponent component)
{
   if (component == iconVideoMode) {
       m_videoModeWidget->setIcon("bla");
       return m_videoModeWidget;
   }
}
_________________________________

3) there will be subclasses (like BrowseVideoState) of the above class
that can handle each mode
_________________________________



4) The MediaContainment starts the state machine

Example:
//Prepare StateMachine
QStateMachine machine; //this is not a pointer

//Set up all possible states
MediaCenterState mediaCenterState = new MediaCenterState(); //these are pointers
VideoBrowserState videoBrowserState = new VideoBrowserState(mediaCenterState);
....
//Define state change buttons
mediaCenterState->addTransition(m_control,
SIGNAL(switchToVideoBrowseState()), videoBrowseState);
mediaCenterState->addTransition(m_control,
SIGNAL(switchToPicturesBrowseState()), pictureBrowseState);

//Define other signals for state change
mediaCenterState->addTransition(player, SIGNAL(slideshowStopped()),
pictureBrowseState);

//Setup and start statemachine
machine.addState(mediaCenterState); //this is our toplevel state
mediaCenterState->setInitialState(videoBrowserState); //set this to
the homescreen state eventually
machine.start();

_________________________________


5) these sublasses will be used by the MediaContainment to create state objects
The mediacontainment initiates state switches while handing pointers
of the UIComponents to the state objects

Example:
QList<MediaCenter::UIComponent> uiComponentsList; //pointer will be
added in the setApplet functions

_________________________________

6) the state objects (i.e. BrowseVideoState) use the pointers of the
UIComponents to tell them to add subComponents to them
They also configure the UIComponents. This all happens on state change
(enter and exit methods)
The pointers of the subComponents are either created in each state
class, or they are created and handed out by another class (maybe
MediaCenterState).

Example of functions to be reimplemented:
assignPoperty(Object, "property", "value")
invokeMethodOnEntry(this, "method")

Example of code:
void BrowseVideoState::invokeOnEntry(QList<MediaCenter::UIComponents> list)
{
    For each UIComponent in list {
        if (UIComponent == "ControlBar") {
            subComponentsList.clear();
            subComponentsList <<
addSubComponent(MediaCenterState::giveComponent(MediaCenter::iconVideoMode));
            subComponentsList <<
addSubComponent(MediaCenterState::giveComponent(MediaCenter::iconPictureMode));
            ...//add all widgets
            configure UIComponent (show, hide, autohide,...)
        }
        if UIComponent = "InfolBar" {
            ...//add widgets
        }
        ...//treat all UIComponents
    }
}

void BrowseVideoState::exit() {
    For each UIComponent in list {
        if (UIComponent == "ControlBar") {
            UIComponent->removeSubComponents(subComponentsList);
        }
    }
}
_________________________________

7) The type definitions of the UIComponents in the libs
(playbackcontrol.h, browser.h,...) predefine the necessary functions
for adding and removing subComponents which need to be reimplemented
by the actual UIComponents themselves
The type definitions also need to show which public slots and signals
need to be available by the actual applets.
Important are the switchState slots. that each UIComponent needs to have.

Example:
//This class defines what an actual implementation of a controlbar
needs to be able to do

//When adding a subComponent we need to return it. This is necessary
to keep a track of them in a list in the state object
MediaCenter::subComponent addSubComponent(MediaCenter::SubComponent)
{
}

//This class gets the exact pointers of who do remove in a list
void removeSubComponents(MediaCenter::SubComponent(QList<MediaCenter::SubComponents>)
{
}

_________________________________

8) The actual UIComponents (mediacontroller.h, mediabrowser.h,...)
need to reimplement how to layout subComponents to themsleves and how
to remove them from their layouts.They will get the pointers to the
subComponents during state change by the state objects. (see point 6)

Example:
MediaCenter::subComponent addSubComponent(MediaCenter::SubComponent)
{
create layout
add subComponent
show subComponent
}

void removeSubComponents(QList<MediaCenter::SubComponents>)
{
for each subComponent
hide subcomponent
remove them from layout
}


More information about the Plasma-devel mailing list