[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-panel-devel
Subject:    Re: Plasma Media Center and state machines
From:       Christophe Olinger <olingerc () binarylooks ! com>
Date:       2010-04-01 19:48:42
Message-ID: t2j1718db771004011248ne9bb3f82w15e4d8a6ddd9e9d2 () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


Replies inline,

Adapted workflow at the end of this message.

(I think its almost time to start coding this)


On Thu, Apr 1, 2010 at 8:16 PM, Christophe Olinger <olingerc@binarylooks.com>
wrote:
> From Aaron:
>
>> //This class knows about things that are important for every toplevel
>> thing needed in the MediaCenter like
>>  MediaType for example
>>
>> enum State {
>>     BrowseVideos;
>>     PlayVideos;
>>     PlayMusic;
>>     MusicVisualizations;
>>     BrowsePictures;
>>     SinglePictures;
>>     PicturesSlideshow;
>> }
>
> is this enum really needed? it's really only something the state machine
needs
> to know about.

moved to the MediaCenterState class

>
> the only thing that needs to get at this would be the Home Page (or
whatever
> it's being called :), but if that was also part of the state machine
system
> then the states could quite easily just add themselves to the home page.
>
>> //Not sure if we need this enum
>> enum playbackState {
>>     Playing;
>>     Paused;
>>     Stopped;
>> }
>
> maybe just playing/paused as a global setting. this is probably separate
from
> the state machine work, however.

will remove the stopped state eventually

>
>> Important: The main MediaCenter lib knwos which types of UIComponents
>> exist. If we add a new type, it needs to be included here
>
> correct..
>
>> ________________________________________________
>>
>> ***MediaCenterState (subclass of QAbstractState)***
>>
>> //This class allows for the MediaCenter to have states. In here we
>> have only things that are needed for the containment to do its work.
>> It also hands out pointers to widgets
>> //It also keeps a collection of all subComponents needed within all
>> states (maybe each state should keep its own subcomponents instead)
>> // the problem would be that if we change between states that have the
>> same subComponents, we would delete and recreate them?)
>>
>>
>> #include "mediacenter.h"
>> #include "mediacenter_export.h"
>>
>> namespace MediaCenter
>> {
>>
>> enum subComponent {
>>     iconVideoMode;
>
> small detail: the first letter should be capitalized as well. also,
instead of
> pepending "icon", "slider", etc. i'd recommend just stating what it does.
> "JumpToVideoMode", "MusicModeVolume". that way if we switch the actual UI
> elements that accomplish these tasks, we don't end up with odd / outdated
> enums :)

will do.

>
>>     iconMusciMode;
>>     iconPictureMode;
>>     iconHomeScreen;
>>     iconTogglePlaylistAutohide;
>>     iconToggleControlBarAutohide;
>>     iconToggleInfoBarAutohide;
>>     iconVideoModePlayPause;
>>     iconVideoModeSkipForward;
>>     iconVideoModeSkipBackward;
>>     iconVideoModeStop;
>>     iconMusicModePlayPause;
>>     iconMusicModeSkipForward;
>>     iconMusicModeSkipBackward;
>>     iconMusicModeStop;
>>     sliderMusicModeVolume;
>>     sliderMusicModeSeek;
>>     iconSlideshow;
>>     iconRotateCW;
>>     iconRotateCCW;
>
> would these rotation ones belong to the image browser, and be provided as
> "custom" elements rather than named elements in the main enum?

I thought we could to this:
Have a main enum with things common to the states (enum MainSubComponents)
Have an enum with things specific to a state. (enum
BrowseVideoModeSubComponents)
In that case, the rotate buttons would be part of the BrowsePictureMode and
BrowseSinglePictureMode enums?
Custom widgets always belong to some state, don't they?

>
>> //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? makes it easier to add modes/plugins?)
>>
>> QGraphicsWidget
>> *BrowseVideoState::giveComponent(MediaCenter::subComponent component)
>
> should probably be createComponent(..) or just component(..)
>
>> {
>>    if (component == iconVideoMode) {
>>
>>        m_videoModeWidget->setIcon("bla");
>>
>>        return m_videoModeWidget;
>>    }
>> }
>
> this is probably a bad example; the standard items such as JumpToVideoMode
> should be provided by the base class. it will be shared by all modes,
after
> all. only custom items specific to the state should be here. for instance,
the
> VideoState might offer (as a made up example) a channel listing display
and a
> button for that should appear in the top bar. in this case, that buton
would
> be provided by VideoState as a custom item.

I agree. Separation of general widgets and specific widgets will be in the
indiviual state object classes or the main MediaCenterState class.

>
>> }//ending namesapce MediaCenter
>>
>> __________________________________
>>
>> ***PlaybackControl (=ControlBar)***
>> //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::SubCompon
>> ents>) {
>> }
>
>
>
>> //these are all empty classes
>>
>> Important: The correct public slots and signals need to exist and
>> reimplememted in the actual applet.
>>
>> signals
>>     browserGoPrevious
>>     playerPlayPauseVideo
>>     playerPlayPauseMusic
>>     playerPlayPausePictures
>
> what would thse signals be used for, exactly? and why are there separate
ones
> for Video, Music, Pictures, etc?

I thought that if the controlBar needs to tell the browser to go up one
levelm it needs a signal to do that and the browser needs a slot to accept
that. When we handle connecting applets between them in the mediacontainment
or whereever, we only have the type implemenations of the applets available.
By adding public slots and signals to the type classes, we make sure that we
do not forget reimplementing these in the actual applets.

They have "duplicates", since for some modes, the buttons look the same, but
they do different things. To avoid having to disconnect and reconnect
things, I thought that having distinctive signals and slots would allow us
to connect things once and not think about them anymore. Maybe I am wrong?

> - Show quoted text -
> why is a subComponentList needed? should the definition of which
components to
> show be done in the constructor instead, and only action taken to reflect
that
> in the actual UI done in the enter event?

On enter event, the applets get told which widgets to add to themselves. By
collecting in a list it would be easy to know on exit which widgets to hide.

if there are multiple possible
> states for a mode, then those could be child states, which would make it
such
> that each state object would represent one configuration of widgets which
> wouldn't change within that state object.

Hmm, for me, mode and state were actuall the same. When in a state, the UI
configuration is fix.

>
>> subComponentsList <<
>>
addSubComponent(MediaCenterState::giveComponent(MediaCenter::iconPictureMod
>> e)); ...//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);
>>         }
>>     }
>> }
>
> i think the MediaCenterState object should simply remove/hide all
components
> that were visible in the last state but which are not visible in the now-
> current state.

Thats why I thought keeping a list when entering a state would be a good
idea.
When each state object adds widgets to applets, how can the MediaCenterState
object know about this?
Would this be done by having the list defined in the MediaCenterState Object
and the individual states would use that list. A simple public (or
protected) member variable?

>
> iow, if we have the current state and it's list of components (set up
using
> addComponent or whatever), and a mapping between each UI element (e.g. a
> button) and the corresponding component enum, then the code can iterate
over
> each item and check to see if it should be shown. sth like this:
>

the below code should go into the entry() function of all state objects?

> QList<MediaCenter::SubComponent> components = newState->subComponents();

Okay, so in each State class I need a subComponents() function that returns
pointers of all subComponents needed in that state. What about the general
ones from the MediaCenterState class? "newState" will be replaced by the
actual object that is the next stage?

> QListIterator<MediaCenter::SubComponent> it (m_visibleSubComponents);

The m_VisibleSubComponents was filled on state change by the last state and
is stored in the MediaCeterState object?

>
> while (it.hasNext()) {
>   MediaCenter::SubComponent c = it.next();
>   if (!components.contains(c)) {
>       MediaCenterComponent *w = m_subComponents.value(c);
>        if (w) {
>             w->hide(); // TODO animate
>         }
>   }
> }
>
> m_visibleSubComponents = components;
> it = m_visibleSubComponents;
> int index = 0;
> while (it.hasNext()) {
>   MediaCenter::SubComponent c = it.next();
>   MediaCenterComponent *w = m_subComponents.value(c);
>   if (!w && c > MediaCenter::CustomComponent) {
>        w = newState->customComponent(c);
>   }
>
>   if (w) {
>        // insert into the layout appropriately
>   }
> }
>

>> applets//
>> _________________________________________
>>
>> ***MediaController class (or any other applet implementation)***
>>
>> controller will be told to add a widget, how this is done is its own
>> problem and needs to be implememnted in the actual applet of type
>> playbackcontrol.
>> also the alignement and stuff
>>
>> reimplement addSunComponent (with return of subComponent
>>
>> we need to connect signal clicked() stuff to the external signals,
>> how? can we be sure that all widgets will arrive. I guess yes.
>> we need to get the pointers of the actual widgets.
>>
>>
>> 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
>> }
>
> again, i don't think an explicit remove is needed. just switch between
states,
> where each state defines all the SubComponents it contains.

Understood, the code in the actual state classes just tells the
SubComponents to hide

>
> i do think we'll end up wanting a QGraphicsWidget subclass for
SubComponents
> (if there isn't aleady one?). this would be used to store information for
> layouting, such as where it belongs in a bar (left, center, right?) and
the
> precedence (Home button should always be first precedent, left)

okay, another class for the libs (tehre is none yet): MediaCenterWidgets
with things like this:
void precedence(int);
int precedence();

void alignement(QtAlignment);
...

____________________________________________

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

Example:

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

2) there is a *MediaCenterState class* which keeps track of all smallwidgets
(=subComponents) which are common for all states for the whole PMC and can
hand out pointers to them. These are widgets like buttons, icons slider,
labels in the control or information bar.
This class also knows which states exist

Example:

enum State {
    BrowseVideos,
    PlayVideos,
    PlayMusic,
    MusicVisualizations,
    BrowsePictures,
    SinglePictures,
    PicturesSlideshow,
    HomeScreen
}

enum MainSubComponent {
    JumpToVideoMode,
    JumpToMusicMode,
    JumpToPictureMode,
    JumpToHomeScreen,
    ToggleControlBarAutohide,
    ToggleInfoBarAutohide,
    ...
}

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. They have enums of things that are specific to
their state and can also hand out pointers using a similar fucntion to the
one in the MediaCenterState Class.

Example:

enum BrowseVideoModeSubComponent {
    PlayPause,
    SkipForward,
    SkipBackward,
    Stop,
    Volume,
    Seek,
    ...
}

enum BrowsePicturesModeSubComponent {
    StartSlideShow
    RotatePictureCCW
    ...
}

_________________________________



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)
Here, previous widgets that are not needed will simply be hidden. Easy,
since we have the pinters to them

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);
        }
    }
}

Aaron's way of doing this:

QList<MediaCenter::SubComponent> components = newState->subComponents();
QListIterator<MediaCenter::SubComponent> it (m_visibleSubComponents);

while (it.hasNext()) {
  MediaCenter::SubComponent c = it.next();
  if (!components.contains(c)) {
      MediaCenterComponent *w = m_subComponents.value(c);
       if (w) {
            w->hide(); // TODO animate
        }
  }
}

m_visibleSubComponents = components;
it = m_visibleSubComponents;
int index = 0;
while (it.hasNext()) {
  MediaCenter::SubComponent c = it.next();
  MediaCenterComponent *w = m_subComponents.value(c);
  if (!w && c > MediaCenter::CustomComponent) {
       w = newState->customComponent(c);
  }

  if (w) {
       // insert into the layout appropriately
  }
}

_________________________________

7) The type definitions of the UIComponents in the libs (*playbackcontrol.h*,
browser.h,...) predefine the necessary functions for adding 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.

The public signals/slots part is still under discussion)

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.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
}


9) All Widgets will be sublcasses by a MediaCenterWidget class (itslef
derived from QGraphicsWidget). which stores general layout information like
alignment or precedence.

Example:

void precedence(int);
int precedence();

void alignement(QtAlignment);
...

[Attachment #5 (text/html)]

<div>Replies inline,</div><div><br></div><div>Adapted workflow at the end of this \
message.</div><div><br></div><div>(I think its almost time to start coding \
this)</div><div><br></div><div><br></div>On Thu, Apr 1, 2010 at 8:16 PM, Christophe \
Olinger &lt;<a href="mailto:olingerc@binarylooks.com">olingerc@binarylooks.com</a>&gt; \
wrote:<br> &gt; From Aaron:<br>&gt;<br>&gt;&gt; //This class knows about things that \
are important for every toplevel<br>&gt;&gt; thing needed in the MediaCenter \
like<br>&gt;&gt;  MediaType for example<br>&gt;&gt;<br>&gt;&gt; enum State {<br> \
&gt;&gt;     BrowseVideos;<br>&gt;&gt;     PlayVideos;<br>&gt;&gt;     \
PlayMusic;<br>&gt;&gt;     MusicVisualizations;<br>&gt;&gt;     \
BrowsePictures;<br>&gt;&gt;     SinglePictures;<br>&gt;&gt;     \
PicturesSlideshow;<br> &gt;&gt; }<br>&gt;<br>&gt; is this enum really needed? \
it&#39;s really only something the state machine needs<br>&gt; to know \
about.<br><br>moved to the MediaCenterState class<br><br>&gt;<br>&gt; the only thing \
that needs to get at this would be the Home Page (or whatever<br> &gt; it&#39;s being \
called :), but if that was also part of the state machine system<br>&gt; then the \
states could quite easily just add themselves to the home page.<br>&gt;<br>&gt;&gt; \
//Not sure if we need this enum<br> &gt;&gt; enum playbackState {<br>&gt;&gt;     \
Playing;<br>&gt;&gt;     Paused;<br>&gt;&gt;     Stopped;<br>&gt;&gt; \
}<br>&gt;<br>&gt; maybe just playing/paused as a global setting. this is probably \
separate from<br>&gt; the state machine work, however.<br> <br>will remove the \
stopped state eventually<br><br>&gt;<br>&gt;&gt; Important: The main MediaCenter lib \
knwos which types of UIComponents<br>&gt;&gt; exist. If we add a new type, it needs \
to be included here<br>&gt;<br>&gt; correct..<br> &gt;<br>&gt;&gt; \
________________________________________________<br>&gt;&gt;<br>&gt;&gt; \
***MediaCenterState (subclass of QAbstractState)***<br>&gt;&gt;<br>&gt;&gt; //This \
class allows for the MediaCenter to have states. In here we<br> &gt;&gt; have only \
things that are needed for the containment to do its work.<br>&gt;&gt; It also hands \
out pointers to widgets<br>&gt;&gt; //It also keeps a collection of all subComponents \
needed within all<br>&gt;&gt; states (maybe each state should keep its own \
subcomponents instead)<br> &gt;&gt; // the problem would be that if we change between \
states that have the<br>&gt;&gt; same subComponents, we would delete and recreate \
them?)<br>&gt;&gt;<br>&gt;&gt;<br>&gt;&gt; #include &quot;mediacenter.h&quot;<br> \
&gt;&gt; #include &quot;mediacenter_export.h&quot;<br>&gt;&gt;<br>&gt;&gt; namespace \
MediaCenter<br>&gt;&gt; {<br>&gt;&gt;<br>&gt;&gt; enum subComponent {<br>&gt;&gt;     \
iconVideoMode;<br>&gt;<br>&gt; small detail: the first letter should be capitalized \
as well. also, instead of<br> &gt; pepending &quot;icon&quot;, &quot;slider&quot;, \
etc. i&#39;d recommend just stating what it does.<br>&gt; \
&quot;JumpToVideoMode&quot;, &quot;MusicModeVolume&quot;. that way if we switch the \
actual UI<br>&gt; elements that accomplish these tasks, we don&#39;t end up with odd \
/ outdated<br> &gt; enums :)<br><br>will do.<br><br>&gt;<br>&gt;&gt;     \
iconMusciMode;<br>&gt;&gt;     iconPictureMode;<br>&gt;&gt;     \
iconHomeScreen;<br>&gt;&gt;     iconTogglePlaylistAutohide;<br>&gt;&gt;     \
iconToggleControlBarAutohide;<br> &gt;&gt;     iconToggleInfoBarAutohide;<br>&gt;&gt; \
iconVideoModePlayPause;<br>&gt;&gt;     iconVideoModeSkipForward;<br>&gt;&gt;     \
iconVideoModeSkipBackward;<br>&gt;&gt;     iconVideoModeStop;<br>&gt;&gt;     \
iconMusicModePlayPause;<br> &gt;&gt;     iconMusicModeSkipForward;<br>&gt;&gt;     \
iconMusicModeSkipBackward;<br>&gt;&gt;     iconMusicModeStop;<br>&gt;&gt;     \
sliderMusicModeVolume;<br>&gt;&gt;     sliderMusicModeSeek;<br>&gt;&gt;     \
iconSlideshow;<br> &gt;&gt;     iconRotateCW;<br>&gt;&gt;     \
iconRotateCCW;<br>&gt;<br>&gt; would these rotation ones belong to the image browser, \
and be provided as<br>&gt; &quot;custom&quot; elements rather than named elements in \
the main enum?<br> <br>I thought we could to this:<br>Have a main enum with things \
common to the states (enum MainSubComponents)<br>Have an enum with things specific to \
a state. (enum BrowseVideoModeSubComponents)<br>In that case, the rotate buttons \
would be part of the BrowsePictureMode and BrowseSinglePictureMode enums?<br> Custom \
widgets always belong to some state, don&#39;t they?<br><br>&gt;<br>&gt;&gt; //here \
we handle the pointers of the created objects (the enum,<br>&gt;&gt; initialilzation \
and pointer handling could be in the actual subclass<br> &gt;&gt; of the state \
objects? makes it easier to add modes/plugins?)<br>&gt;&gt;<br>&gt;&gt; \
QGraphicsWidget<br>&gt;&gt; \
*BrowseVideoState::giveComponent(MediaCenter::subComponent component)<br>&gt;<br>&gt; \
should probably be createComponent(..) or just component(..)<br> &gt;<br>&gt;&gt; \
{<br>&gt;&gt;    if (component == iconVideoMode) {<br>&gt;&gt;<br>&gt;&gt;        \
m_videoModeWidget-&gt;setIcon(&quot;bla&quot;);<br>&gt;&gt;<br>&gt;&gt;        return \
m_videoModeWidget;<br>&gt;&gt;    }<br> &gt;&gt; }<br>&gt;<br>&gt; this is probably a \
bad example; the standard items such as JumpToVideoMode<br>&gt; should be provided by \
the base class. it will be shared by all modes, after<br>&gt; all. only custom items \
specific to the state should be here. for instance, the<br> &gt; VideoState might \
offer (as a made up example) a channel listing display and a<br>&gt; button for that \
should appear in the top bar. in this case, that buton would<br>&gt; be provided by \
VideoState as a custom item.<br> <br>I agree. Separation of general widgets and \
specific widgets will be in the indiviual state object classes or the main \
MediaCenterState class.<br><br>&gt;<br>&gt;&gt; }//ending namesapce \
MediaCenter<br>&gt;&gt;<br>&gt;&gt; __________________________________<br> \
&gt;&gt;<br>&gt;&gt; ***PlaybackControl (=ControlBar)***<br>&gt;&gt; //This class \
defines what an actual implementation of a controlbar<br>&gt;&gt; needs to be able to \
do<br>&gt;&gt;<br>&gt;&gt; //When adding a subComponent we need to return it. This is \
necessary<br> &gt;&gt; to keep a track of them in a list in the state \
object<br>&gt;&gt; MediaCenter::subComponent \
addSubComponent(MediaCenter::SubComponent)<br>&gt;&gt; {<br>&gt;&gt; \
}<br>&gt;&gt;<br>&gt;&gt; //This class gets the exact pointers of who do remove in a \
list<br> &gt;&gt; void<br>&gt;&gt; \
removeSubComponents(MediaCenter::SubComponent(QList&lt;MediaCenter::SubCompon<br>&gt;&gt; \
ents&gt;) {<br>&gt;&gt; }<br>&gt;<br>&gt;<br>&gt;<br>&gt;&gt; //these are all empty \
classes<br>&gt;&gt;<br> &gt;&gt; Important: The correct public slots and signals need \
to exist and<br>&gt;&gt; reimplememted in the actual applet.<br>&gt;&gt;<br>&gt;&gt; \
signals<br>&gt;&gt;     browserGoPrevious<br>&gt;&gt;     playerPlayPauseVideo<br> \
&gt;&gt;     playerPlayPauseMusic<br>&gt;&gt;     \
playerPlayPausePictures<br>&gt;<br>&gt; what would thse signals be used for, exactly? \
and why are there separate ones<br>&gt; for Video, Music, Pictures, etc?<br><br>I \
thought that if the controlBar needs to tell the browser to go up one levelm it needs \
a signal to do that and the browser needs a slot to accept that. When we handle \
connecting applets between them in the mediacontainment or whereever, we only have \
the type implemenations of the applets available. By adding public slots and signals \
to the type classes, we make sure that we do not forget reimplementing these in the \
actual applets.<br> <br>They have &quot;duplicates&quot;, since for some modes, the \
buttons look the same, but they do different things. To avoid having to disconnect \
and reconnect things, I thought that having distinctive signals and slots would allow \
us to connect things once and not think about them anymore. Maybe I am wrong?<br> \
<br>&gt; - Show quoted text -<br>&gt; why is a subComponentList needed? should the \
definition of which components to<br>&gt; show be done in the constructor instead, \
and only action taken to reflect that<br>&gt; in the actual UI done in the enter \
event? <br> <br>On enter event, the applets get told which widgets to add to \
themselves. By collecting in a list it would be easy to know on exit which widgets to \
hide.<br><br>if there are multiple possible<br>&gt; states for a mode, then those \
could be child states, which would make it such<br> &gt; that each state object would \
represent one configuration of widgets which<br>&gt; wouldn&#39;t change within that \
state object.<br><br>Hmm, for me, mode and state were actuall the same. When in a \
state, the UI configuration is fix.<br> <br>&gt;<br>&gt;&gt; subComponentsList \
&lt;&lt;<br>&gt;&gt; \
addSubComponent(MediaCenterState::giveComponent(MediaCenter::iconPictureMod<br>&gt;&gt; \
e)); ...//add all widgets<br>&gt;&gt;             configure UIComponent (show, hide, \
autohide,...)<br> &gt;&gt;         }<br>&gt;&gt;         if UIComponent = \
&quot;InfolBar&quot; {<br>&gt;&gt;             ...//add widgets<br>&gt;&gt;         \
}<br>&gt;&gt;         ...//treat all UIComponents<br>&gt;&gt;     }<br>&gt;&gt; }<br> \
&gt;<br>&gt;&gt; void BrowseVideoState::exit() {<br>&gt;&gt;     For each UIComponent \
in list {<br>&gt;&gt;         if (UIComponent == &quot;ControlBar&quot;) \
{<br>&gt;&gt;             UIComponent-&gt;removeSubComponents(subComponentsList);<br> \
&gt;&gt;         }<br>&gt;&gt;     }<br>&gt;&gt; }<br>&gt;<br>&gt; i think the \
MediaCenterState object should simply remove/hide all components<br>&gt; that were \
visible in the last state but which are not visible in the now-<br> &gt; current \
state.<br><br>Thats why I thought keeping a list when entering a state would be a \
good idea.<br>When each state object adds widgets to applets, how can the \
MediaCenterState object know about this?<br>Would this be done by having the list \
defined in the MediaCenterState Object and the individual states would use that list. \
A simple public (or protected) member variable?<br> <br>&gt;<br>&gt; iow, if we have \
the current state and it&#39;s list of components (set up using<br>&gt; addComponent \
or whatever), and a mapping between each UI element (e.g. a<br>&gt; button) and the \
corresponding component enum, then the code can iterate over<br> &gt; each item and \
check to see if it should be shown. sth like this:<br>&gt;<br><br>the below code \
should go into the entry() function of all state objects?<br><br>&gt; \
QList&lt;MediaCenter::SubComponent&gt; components = \
newState-&gt;subComponents();<div> <br></div><div>Okay, so in each State class I need \
a subComponents() function that returns pointers of all subComponents needed in that \
state. What about the general ones from the MediaCenterState class? \
&quot;newState&quot; will be replaced by the actual object that is the next \
stage?</div> <div><br>&gt; QListIterator&lt;MediaCenter::SubComponent&gt; it \
(m_visibleSubComponents);</div><div><br></div><div>The m_VisibleSubComponents was \
filled on state change by the last state and is stored in the MediaCeterState \
object?</div> <div><br>&gt;<br>&gt; while (it.hasNext()) {<br>&gt;   \
MediaCenter::SubComponent c = it.next();<br>&gt;   if (!components.contains(c)) \
{<br>&gt;       MediaCenterComponent *w = m_subComponents.value(c);<br>&gt;        if \
(w) {<br> &gt;             w-&gt;hide(); // TODO animate<br>&gt;         }<br>&gt;   \
}<br>&gt; }<br>&gt;<br>&gt; m_visibleSubComponents = components;<br>&gt; it = \
m_visibleSubComponents;<br>&gt; int index = 0;<br>&gt; while (it.hasNext()) {<br> \
&gt;   MediaCenter::SubComponent c = it.next();<br>&gt;   MediaCenterComponent *w = \
m_subComponents.value(c);<br>&gt;   if (!w &amp;&amp; c &gt; \
MediaCenter::CustomComponent) {<br>&gt;        w = \
newState-&gt;customComponent(c);<br> &gt;   }<br>&gt;<br>&gt;   if (w) {<br>&gt;      \
// insert into the layout appropriately<br>&gt;   }<br>&gt; \
}<br>&gt;</div><div><br></div><div>&gt;&gt; applets//<br>&gt;&gt; \
_________________________________________<br> &gt;&gt;<br>&gt;&gt; ***MediaController \
class (or any other applet implementation)***<br>&gt;&gt;<br>&gt;&gt; controller will \
be told to add a widget, how this is done is its own<br>&gt;&gt; problem and needs to \
be implememnted in the actual applet of type<br> &gt;&gt; \
playbackcontrol.<br>&gt;&gt; also the alignement and stuff<br>&gt;&gt;<br>&gt;&gt; \
reimplement addSunComponent (with return of subComponent<br>&gt;&gt;<br>&gt;&gt; we \
need to connect signal clicked() stuff to the external signals,<br> &gt;&gt; how? can \
we be sure that all widgets will arrive. I guess yes.<br>&gt;&gt; we need to get the \
pointers of the actual widgets.<br>&gt;&gt;<br>&gt;&gt;<br>&gt;&gt; \
MediaCenter::subComponent addSubComponent(MediaCenter::SubComponent)<br> &gt;&gt; \
{<br>&gt;&gt; create layout<br>&gt;&gt; add subComponent<br>&gt;&gt; show \
subComponent<br>&gt;&gt; }<br>&gt;&gt;<br>&gt;&gt; void \
removeSubComponents(QList&lt;MediaCenter::SubComponents&gt;)<br>&gt;&gt; \
{<br>&gt;&gt; for each subComponent<br> &gt;&gt; hide subcomponent<br>&gt;&gt; remove \
them from layout<br>&gt;&gt; }<br>&gt;<br>&gt; again, i don&#39;t think an explicit \
remove is needed. just switch between states,<br>&gt; where each state defines all \
the SubComponents it contains.</div> <div><br></div><div>Understood, the code in the \
actual state classes just tells the SubComponents to hide</div><div><br>&gt;<br>&gt; \
i do think we&#39;ll end up wanting a QGraphicsWidget subclass for \
SubComponents<br>&gt; (if there isn&#39;t aleady one?). this would be used to store \
information for<br> &gt; layouting, such as where it belongs in a bar (left, center, \
right?) and the<br>&gt; precedence (Home button should always be first precedent, \
left)</div><div><br></div><div>okay, another class for the libs (tehre is none yet): \
MediaCenterWidgets with things like this:</div> <div>void \
precedence(int);</div><div>int precedence();</div><div><br></div><div>void \
alignement(QtAlignment);</div><div>...</div><div><br>____________________________________________</div><div><br></div><div><span \
class="Apple-style-span" style="font-family: Arial; font-size: 13px; ">1) the top \
level libs (<b>mediacenter.h</b>) class knows about which types of applets \
(=UIComponents) exist<br> <br><div style="margin-top: 0px; margin-bottom: 0px; \
">Example:</div><br><div style="margin-top: 0px; margin-bottom: 0px; "><font \
class="Apple-style-span" size="1">enum UIComponent {</font></div><div \
style="margin-top: 0px; margin-bottom: 0px; "> <font class="Apple-style-span" \
size="1">    ControlBar;<br>    InfoBar;<br>    Browser;<br>    Player;<br>    \
Playlist;<br>    HomeScreen;<br>}</font><br></div>_________________________________<br><br>2) \
there is a <b>MediaCenterState class</b> which keeps track of all smallwidgets \
(=subComponents) which are common for all states for the whole PMC and can hand out \
pointers to them. These are widgets like buttons, icons slider, labels in the control \
or information bar.<br> This class also knows which states exist<br><br><div \
style="margin-top: 0px; margin-bottom: 0px; ">Example:</div><font \
class="Apple-style-span" size="1"><br></font><div style="margin-top: 0px; \
margin-bottom: 0px; "><font class="Apple-style-span" size="1">enum State {<br>  \
BrowseVideos,<br>    PlayVideos,<br>    PlayMusic,<br>    MusicVisualizations,<br>    \
BrowsePictures,<br>    SinglePictures,<br>    PicturesSlideshow,</font></div><div \
style="margin-top: 0px; margin-bottom: 0px; "><font class="Apple-style-span" \
size="1">    HomeScreen<br> }</font></div><br><div style="margin-top: 0px; \
margin-bottom: 0px; "><font class="Apple-style-span" size="1">enum MainSubComponent \
{</font></div><div style="margin-top: 0px; margin-bottom: 0px; "><font \
class="Apple-style-span" size="1">    JumpToVideoMode,<br>  JumpToMusicMode,<br>    \
JumpToPictureMode,<br>    JumpToHomeScreen,<br>    ToggleControlBarAutohide,<br>    \
ToggleInfoBarAutohide,<br>    ...<br>}<br><br></font><p style="margin-top: 0px; \
margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "> <font \
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; \
"><font class="Apple-style-span" size="1">    m_iconVideosMode(new \
Plasma::IconWidget(this))<br></font></p><p style="margin-top: 0px; margin-right: 0px; \
margin-bottom: 0px; margin-left: 0px; "> <font class="Apple-style-span" size="1">    \
//initialize all of them<br></font></p><p style="margin-top: 0px; margin-right: 0px; \
margin-bottom: 0px; margin-left: 0px; "><font class="Apple-style-span" \
size="1">{</font></p> <p style="margin-top: 0px; margin-right: 0px; margin-bottom: \
0px; margin-left: 0px; "><font class="Apple-style-span" size="1">}</font></p><p \
style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "> \
<br></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; \
margin-left: 0px; "><font class="Apple-style-span" size="1">//here we handle the \
pointers of the created objects </font><font class="Apple-style-span" \
color="#38761d"><font class="Apple-style-span" size="1">(the enum, initialilzation \
and pointer handling could be in the actual subclass of the state \
objects</font></font><br> </p><p style="margin-top: 0px; margin-right: 0px; \
margin-bottom: 0px; margin-left: 0px; "><font class="Apple-style-span" face="arial, \
sans-serif"><font class="Apple-style-span" size="1">QGraphicsWidget \
*BrowseVideoState::giveComponent(MediaCenter::subComponent component)<br> {<br>   if \
(component == iconVideoMode) {</font></font></p><p style="margin-top: 0px; \
margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font \
class="Apple-style-span" face="arial, sans-serif"><font class="Apple-style-span" \
size="1">       m_videoModeWidget-&gt;setIcon(&quot;bla&quot;);<br> \
</font></font></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; \
margin-left: 0px; "><font class="Apple-style-span" face="arial, sans-serif"><font \
class="Apple-style-span" size="1">       return m_videoModeWidget;<br>  \
}<br>}</font></font></p><div style="margin-top: 0px; margin-bottom: 0px; \
">_________________________________</div><div style="margin-top: 0px; margin-bottom: \
0px; "><br>3) there will be subclasses (like <b>BrowseVideoState</b>) of the above \
class that can handle each mode. They have enums of things that are specific to their \
state and can also hand out pointers using a similar fucntion to the one in the \
MediaCenterState Class.</div> <br><div style="margin-top: 0px; margin-bottom: 0px; \
">Example:</div><br><div style="margin-top: 0px; margin-bottom: 0px; "><font \
class="Apple-style-span" size="1">enum BrowseVideoModeSubComponent {</font></div><div \
style="margin-top: 0px; margin-bottom: 0px; "> <font class="Apple-style-span" \
size="1">    PlayPause,<br>    SkipForward,<br>    SkipBackward,<br>    Stop,<br>    \
Volume,<br>    Seek,<br>    ...<br>}</font></div><font class="Apple-style-span" \
size="1"><br></font><div style="margin-top: 0px; margin-bottom: 0px; "> <font \
class="Apple-style-span" size="1">enum BrowsePicturesModeSubComponent \
{</font></div><div style="margin-top: 0px; margin-bottom: 0px; "><font \
class="Apple-style-span" size="1">    StartSlideShow</font></div><div \
style="margin-top: 0px; margin-bottom: 0px; "> <font class="Apple-style-span" \
size="1">    RotatePictureCCW<br>    ...<br>}</font></div><br><div style="margin-top: \
0px; margin-bottom: 0px; ">_________________________________</div><br><br><br><div \
style="margin-top: 0px; margin-bottom: 0px; "> 4) The <b>MediaContainment</b> starts \
the state machine</div><br><div style="margin-top: 0px; margin-bottom: 0px; \
">Example:</div><div style="margin-top: 0px; margin-bottom: 0px; "><font \
class="Apple-style-span" size="1">//Prepare StateMachine</font><br> <font \
class="Apple-style-span" size="1">QStateMachine machine;</font><font \
class="Apple-style-span" size="1"> //this is not a pointer</font><br><br><font \
class="Apple-style-span" size="1">//Set up all possible states</font><br> <font \
class="Apple-style-span" size="1">MediaCenterState mediaCenterState = new \
MediaCenterState();</font><font class="Apple-style-span" size="1"> //these are \
pointers</font><br><font class="Apple-style-span" size="1">VideoBrowserState \
videoBrowserState = new VideoBrowserState(mediaCenterState);</font><font \
                class="Apple-style-span" size="1"><br>
....<br>//Define state change buttons<br></font><font class="Apple-style-span" \
face="Courier New"><font class="Apple-style-span" \
size="1">mediaCenterState-&gt;addTransition(m_control, \
SIGNAL(switchToVideoBrowseState()), videoBrowseState);<br> </font><font \
class="Apple-style-span" face="Courier New"><font class="Apple-style-span" \
size="1">mediaCenterState-&gt;addTransition(m_control, \
SIGNAL(switchToPicturesBrowseState()), pictureBrowseState);</font></font><br><br> \
</font><font class="Apple-style-span" size="1">//Define other signals for state \
change</font><br><font class="Apple-style-span" face="Courier New"><font \
class="Apple-style-span" size="1">mediaCenterState-&gt;addTransition(player, \
SIGNAL(slideshowStopped()), pictureBrowseState);</font></font><br> <font \
class="Apple-style-span" size="1"><br>//Setup and start \
statemachine<br>machine.addState(mediaCenterState); //this is our toplevel \
state<br></font><font class="Apple-style-span" \
size="1">mediaCenterState-&gt;setInitialState(videoBrowserState); //set this to the \
homescreen state eventually</font><br> <font class="Apple-style-span" \
size="1">machine.start();</font><br></div><br><div style="margin-top: 0px; \
margin-bottom: 0px; ">_________________________________</div><br><br><div \
style="margin-top: 0px; margin-bottom: 0px; "> 5) these sublasses will be used by the \
<b>MediaContainment</b> to create state objects</div><div style="margin-top: 0px; \
margin-bottom: 0px; ">The mediacontainment initiates state switches while handing \
pointers of the UIComponents to the state objects</div> <br><div style="margin-top: \
0px; margin-bottom: 0px; ">Example:</div><div style="margin-top: 0px; margin-bottom: \
0px; "><font class="Apple-style-span" size="1">QList&lt;MediaCenter::UIComponent&gt; \
uiComponentsList; //pointer will be added in the setApplet functions</font></div> \
<br><div style="margin-top: 0px; margin-bottom: 0px; \
">_________________________________</div><br>6) the state objects (i<b>.e. \
BrowseVideoState</b>) use the pointers of the UIComponents to tell them to add \
subComponents to them<div style="margin-top: 0px; margin-bottom: 0px; "> They also \
configure the UIComponents. This all happens on state change (enter and exit \
methods)</div><div style="margin-top: 0px; margin-bottom: 0px; ">Here, previous \
widgets that are not needed will simply be hidden. Easy, since we have the pinters to \
them</div> <br><div style="margin-top: 0px; margin-bottom: 0px; ">Example of \
functions to be reimplemented:</div><div style="margin-top: 0px; margin-bottom: 0px; \
"><font class="Apple-style-span" color="#0000ff"><font class="Apple-style-span" \
size="1">assignPoperty(Object, &quot;property&quot;, \
&quot;value&quot;)</font></font><br> <font class="Apple-style-span" \
color="#0000ff"><font class="Apple-style-span" size="1">invokeMethodOnEntry(this, \
&quot;method&quot;)</font></font><br></div><br>Example of code:<br><div \
style="margin-top: 0px; margin-bottom: 0px; "> <font class="Apple-style-span" \
size="1">void BrowseVideoState::invokeOnEntry(QList&lt;MediaCenter::UIComponents&gt; \
list)<br>{<br>    For each UIComponent in list {<br>        if (UIComponent == \
&quot;ControlBar&quot;) {<br>  subComponentsList.clear();    <br>            \
subComponentsList &lt;&lt; \
addSubComponent(MediaCenterState::giveComponent(MediaCenter::iconVideoMode));<br>     \
subComponentsList &lt;&lt; \
                addSubComponent(MediaCenterState::giveComponent(MediaCenter::iconPictureMode));<br>
                
            ...//add all widgets<br>            configure UIComponent (show, hide, \
autohide,...)<br>        }<br>        if UIComponent = &quot;InfolBar&quot; {<br>     \
...//add widgets<br>        }<br>        ...//treat all UIComponents<br>  \
}<br>}<br><br>void BrowseVideoState::exit() {<br>    For each UIComponent in list \
{<br>        if (UIComponent == &quot;ControlBar&quot;) {<br>            \
UIComponent-&gt;removeSubComponents(subComponentsList);<br>        }<br>  \
}<br>}</font></div><br><font class="Apple-style-span" size="1"><font \
class="Apple-style-span" size="2">Aaron&#39;s way of doing \
this:</font><br></font><br><font class="Apple-style-span" face="arial"><font \
class="Apple-style-span" size="1">QList&lt;MediaCenter::SubComponent&gt; components = \
newState-&gt;subComponents();<br> QListIterator&lt;MediaCenter::SubComponent&gt; it \
(m_visibleSubComponents);<br><br></font></font></div><div style="margin-top: 0px; \
margin-bottom: 0px; "><font class="Apple-style-span" face="arial"><font \
class="Apple-style-span" size="2"><font class="Apple-style-span" size="1">while \
(it.hasNext()) {<br>  MediaCenter::SubComponent c = it.next();<br>  if \
(!components.contains(c)) {<br>      MediaCenterComponent *w = \
m_subComponents.value(c);<br>       if (w) {<br>            w-&gt;hide(); // TODO \
animate<br>        }<br>  }<br> }<br><br>m_visibleSubComponents = components;<br>it = \
m_visibleSubComponents;<br>int index = 0;<br>while (it.hasNext()) {<br>  \
MediaCenter::SubComponent c = it.next();<br>  MediaCenterComponent *w = \
m_subComponents.value(c);<br>  if (!w &amp;&amp; c &gt; MediaCenter::CustomComponent) \
{<br>       w = newState-&gt;customComponent(c);<br>  }<br><br>  if (w) {<br>       \
// insert into the layout appropriately<br>  }<br>}<br></font><br></font></font><div \
style="margin-top: 0px; margin-bottom: 0px; "> <div style="margin-top: 0px; \
margin-bottom: 0px; ">_________________________________</div><br>7) The type \
definitions of the UIComponents in the libs (<b>playbackcontrol.h</b>, browser.h,...) \
predefine the necessary functions for adding subComponents which need to be \
reimplemented by the actual UIComponents themselves<br> The type definitions also \
need to show which public slots and signals need to be available by the actual \
applets. </div><div style="margin-top: 0px; margin-bottom: 0px; ">Important are the \
switchState slots. that each UIComponent needs to have.</div> <br><div \
style="margin-top: 0px; margin-bottom: 0px; ">The public signals/slots part is still \
under discussion)</div><br><div style="margin-top: 0px; margin-bottom: 0px; \
">Example:</div><div style="margin-top: 0px; margin-bottom: 0px; "> <font \
class="Apple-style-span" size="1">//This class defines what an actual implementation \
of a controlbar needs to be able to do<br><br>//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<br> MediaCenter::subComponent \
addSubComponent(MediaCenter::SubComponent)<br>{<br>}<br><br>//This class gets the \
exact pointers of who do remove in a list<br>void \
removeSubComponents(MediaCenter::SubComponent(QList&lt;MediaCenter::SubComponents&gt;)<br>
 {<br>}</font><br></div><br><div style="margin-top: 0px; margin-bottom: 0px; \
">_________________________________</div><br>8) The actual UIComponents \
(<b>mediacontroller.h</b>, mediabrowser.h,...) need to reimplement how to layout \
subComponents to themsleves.They will get the pointers to the subComponents during \
state change by the state objects. (see point 6)<br> <br></div><div \
style="margin-top: 0px; margin-bottom: 0px; ">Example:</div><div style="margin-top: \
0px; margin-bottom: 0px; "><font class="Apple-style-span" \
size="1">MediaCenter::subComponent addSubComponent(MediaCenter::SubComponent)<br> \
{<br>create layout<br>add subComponent<br>show subComponent<br>}<br><font \
class="Apple-style-span" size="3"><br></font></font><br></div>9) All Widgets will be \
sublcasses by a MediaCenterWidget class (itslef derived from QGraphicsWidget). which \
stores general layout information like alignment or precedence.<br> <br><div \
style="margin-top: 0px; margin-bottom: 0px; ">Example:</div><br><div \
style="margin-top: 0px; margin-bottom: 0px; "><font class="Apple-style-span" \
face="arial"><font class="Apple-style-span" size="1">void \
precedence(int);</font></font></div> <div style="margin-top: 0px; margin-bottom: 0px; \
"><font class="Apple-style-span" face="arial"><font class="Apple-style-span" \
size="1">int precedence();</font></font></div><br><div style="margin-top: 0px; \
margin-bottom: 0px; "> <font class="Apple-style-span" face="arial"><font \
class="Apple-style-span" size="1">void \
alignement(QtAlignment);</font></font></div><div style="margin-top: 0px; \
margin-bottom: 0px; "><font class="Apple-style-span" face="arial"><font \
class="Apple-style-span" size="1">...</font></font></div> <div><font \
class="Apple-style-span" face="arial"><font class="Apple-style-span" \
size="1"><br></font></font></div></span></div><div><br></div><div><br><br></div>



_______________________________________________
Plasma-devel mailing list
Plasma-devel@kde.org
https://mail.kde.org/mailman/listinfo/plasma-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic