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 <oling...@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); ...
_______________________________________________ Plasma-devel mailing list Plasma-devel@kde.org https://mail.kde.org/mailman/listinfo/plasma-devel