Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Keep GUIControls alive after window deinit #1283

Merged
merged 21 commits into from

6 participants

@pieh
Collaborator

This is resurrection of #127 in much more complete state:

Window's controls are being deleted on window deinit. This results in loading xml, resolving includes, parsing resolved xml and creating controls everytime user activate window.

This will allow to keep controls objects in memory on window deinit. It also will store xml windows root node that could be used if load type is set to load_on_demand (old style - few windows are still like this) or if include condition have changed value.

Some numbers (tested on raspberry pi with slow sd card where it will have biggest impact I guess): compare alloc resources time for first and second window inits. (I didn't really gather data, just ran xbmc 3 times and given that results were similliar I called it done)

===== Results (numbers from Raspberry Pi) ====

  1. Home Window

     -- First window init will be same as usual --

    00:02:33 T:1096794832   DEBUG: ------ Window Init (Home.xml) ------
    00:02:33 T:1096794832    INFO: Loading skin file: Home.xml, load type: on demand and keep in memory after window deinit
    00:02:33 T:1096794832   DEBUG: Load Home.xml: 665.98ms
    00:02:34 T:1096794832   DEBUG: Alloc resources: 723.72ms  (666.55 ms skin load)

     -- Second window init --

    00:03:24 T:1096794832   DEBUG: ------ Window Init (Home.xml) ------
    00:03:24 T:1096794832   DEBUG: Window Home.xml was already loaded
    00:03:24 T:1096794832   DEBUG: Alloc resources: 22.07m

  2. Video Nav

    00:03:18 T:1096794832   DEBUG: ------ Window Init (MyVideoNav.xml) ------
    00:03:18 T:1096794832    INFO: Loading skin file: MyVideoNav.xml, load type: on demand and keep in memory after window deinit
    00:03:19 T:1096794832   DEBUG: Load MyVideoNav.xml: 776.83ms
    00:03:19 T:1096794832   DEBUG: Alloc resources: 827.03ms  (777.33 ms skin load)

    00:03:30 T:1096794832   DEBUG: ------ Window Init (MyVideoNav.xml) ------
    00:03:30 T:1096794832   DEBUG: Window MyVideoNav.xml was already loaded
    00:03:30 T:1096794832   DEBUG: Alloc resources: 27.48m

On android (skin.retouched) Home.xml was loaded 1st time: 126ms and 2nd time: 5ms (that's total alloc resources time). On my desktop with ssd - home.xml = 1st time: 42ms, 2nd time: 4ms. So it's not that spectacular everywhere. Note: alloc resources times don't include time spent in OnWindowInit (f.e. video nav window fetch directory there)!

Here's list of windows that weren't yet adjusted/tested if they will work "as-is":

Still on to-do list but not really high priority:
00:02:30 T:1096794832   DEBUG: GUIWindowManager: LOAD_ON_DEMAND window: screencalibration (file: SettingsScreenCalibration.xml, ID: 10011)
00:02:30 T:1096794832   DEBUG: GUIWindowManager: LOAD_ON_DEMAND window: filestackingdialog (file: DialogFileStacking.xml, ID: 12008)

Didn't have any karaoke samples so at least for now I leave them as they are with old style xml loading every init. Do they still work at all?
00:02:30 T:1096794832   DEBUG: GUIWindowManager: LOAD_ON_DEMAND window: karaokeselector (file: DialogKaraokeSongSelector.xml, ID: 10143)
00:02:30 T:1096794832   DEBUG: GUIWindowManager: LOAD_ON_DEMAND window: karaokelargeselector (file: DialogKaraokeSongSelectorLarge.xml, ID: 10144)
00:02:30 T:1096794832   DEBUG: GUIWindowManager: LOAD_ON_DEMAND window: karaoke (file: MusicKaraokeLyrics.xml, ID: 12009)

For no-xml windows load type doesn't matter so they can stay as they are.
00:02:30 T:1096794832   DEBUG: GUIWindowManager: LOAD_ON_DEMAND window: teletext (file: no xml file, ID: 10600)
00:02:30 T:1096794832   DEBUG: GUIWindowManager: LOAD_ON_DEMAND window: unkown window (file: no xml file, ID: 97) <= Dim Screensaver Window
00:02:30 T:1096794832   DEBUG: GUIWindowManager: LOAD_ON_DEMAND window: unkown window (file: no xml file, ID: 98) <= Debug Overlay Window
00:02:30 T:1096794832   DEBUG: GUIWindowManager: LOAD_ON_DEMAND window: screensaver (file: no xml file, ID: 12900)

CGUIDialogSubMenu class used only as base for "submenu" type custom windows (which wasn't used by any of few skins I have: confluence, aeon-nox, xeebo). No DialogSubMenu.xml in confluence. Nuke that window?
00:02:30 T:1096794832   DEBUG: GUIWindowManager: LOAD_ON_DEMAND window: submenu (file: DialogSubMenu.xml, ID: 10105)

Used only after playing with GUISetting that aren't shown in GUI. No DialogAccessPoints.xml in confluence. Nuke that window?
00:02:30 T:1096794832   DEBUG: GUIWindowManager: LOAD_ON_DEMAND window: accesspoints (file: DialogAccessPoints.xml, ID: 10141)

Loaded and shown once - no sense in keeping it in memory.
00:02:30 T:1096794832   DEBUG: GUIWindowManager: LOAD_ON_DEMAND window: startup (file: Startup.xml, ID: 12999)

And finally - my branch currently contains 2(3) last temporary commits (they will be removed later) to
1. help me notice what windows weren't adjusted yet (it generated window list above)
2. enable/disable feature on runtime (in gui settings) to check what impact it have
(3). add window loadtype to log on window load (depends on how verbose we want to be)

@jmarshallnz
Owner

Ok, main thing is I think we need to clearly identify where we need overriding in the subclasses. Seems to me we have:

  1. After XML load and before control parsing (for python label parsing).
  2. After control parsing (filling default content that anims and control state might need). Should run once we have controls either from in memory or from a load.
  3. After window is up, anims are all setup and we're ready to go (filling in content). Should run every init.

... window cycle ...

  1. After window close animation and before controls are cleared (reset controls to default state).
  2. After controls are cleared and before unload (not sure if needed)
  3. After XML unload.

Not sure about 2/3 vs 5/6

@pieh
Collaborator

I don't understand what You mean with "python label parsing" (or I'm propably totally unaware that we do something like that?).

I don't think we should change where/when we call existing callbacks (this would propably cause serious regressions which I already faced once and it took me quite a long time to finalize it). But adding new callbacks would be ok I think (and wouldn't hurt).

@jmarshallnz
Owner

IIRC winxml windows parse for existing Localise stuff and bumps the string IDs up as needed?

@pieh
Collaborator

Right, found it - CGUIPythonWindowXML is overriding CGUIWindow::LoadXML. It manipulates directly on xml string (before parsing) to replace SCRIPT### to proper ID - do we want callback that will pass xml as string so it can be manipulated? Doesn't seem nice to me.

@pieh
Collaborator

Added bunch of changes (additional commits will be squashed later). Wanted to keep comment history so we can track what is already taken care of.

@jmarshallnz
Owner

Looks like we can do cases 2 and 3 above via OnInitWindow, as that runs every time, right? So we could do:

DerivedClass::OnInitWindow()
{
// do whatever needs doing in 2

BaseClass::OnInitWindow() // sets up animations etc.

// do whatever needs doing in 3
}

So I don't think we need a new callback there.

@jmarshallnz
Owner

Changes look good

@pieh pieh was assigned
pieh added some commits
@pieh pieh allow include resolver to store checked include conditions and their …
…values into map<conditionID:int, value:bool>

store conditions and values used to resolve includes in CGUIWindow
added CGUIInfoManager::ConditionsChangedValues method
fb6a3f0
@pieh pieh change bool m_loadOnDemand to LOAD_TYPE m_loadType 5671a6a
@pieh pieh allow not to free memory (destroy controls objects) when exiting window
added additional checks in AllocResources - we have to load .xml file if:
 - load type is set to LOAD_EVERY_TIME (all windows use it by default)
 - window is loaded and any of include condition have changed value
 - window isn't loaded

we have to unload window before loading if window wasn't unloaded before and include conditions have change value(s)
afffab0
@pieh pieh store and reuse window xml root node
this allows to avoid reading and parsing xml file in windows we already used before and are loaded on demand or their include conditions have changed values
996bd17
@pieh pieh regression fix: override SetInitialVisibility() in CGUIBaseContainer …
…to force restoring static items before restoring control states ( in CGUIWindow::OnInitWindow, SetInitialVisibility() is called before RestoreControlStates() )

not need to call UpdateStaticItems() if we are loading static items from .xml as we do it before SetInitialVisibility is called and it will be called there
f2e9d06
@pieh pieh adjust GUIDialogContextMenu: cleaning up initialization/deinitializat…
…ion of dialog

- we need additional members to remember window coordinates (these are fetched while loading window .xml file and later are changed when setting position of ContextMenu) and size of background image
- we don't need to call SetInitialVisibility - it's alreadu done in CGUIWindow::OnWindowInit
- we need to manually remove choice buttons in OnDeinitWindow
- we need to store size of background image to properly set its size it in consequent showings
e30dbc2
@pieh pieh keep these windows in memory, they're ready as-is 4ce5d78
@pieh pieh adjust GUIDialogBoxBase: store heading,lines,choices and set them whe…
…n initing window and if dialog is already active
158c99b
@pieh pieh adjust GUISlideShow: move stoping background loader to window deinit 53eabbf
@pieh pieh adjust GUIDialogMediaSource: clear list with paths on deinit bb3a2bc
@pieh pieh adjust GUIDialogSelect: don't reset GUIViewControl when leaving windo…
…w, clear it

reset it when we unload window
b5843d8
@pieh pieh adjust GUIDialogNetworkSetup: change control types only when we load …
…window, fill/clear protocol spinner when we init/deinit window
d260bfb
@pieh pieh adjust GUIDialogPeripheralManager: we would run OnInitWindow twice du…
…e to not consuming GUI_MSG_WINDOW_INIT message

also move init actions to OnInitWindow callback
4e00b80
@pieh pieh adjust GUIDialogVideoScan: hide progress controls if not used 83a3f44
@pieh pieh adjust GUIDialogSlider: nullify callbacks on window deinit 5eadd51
@pieh pieh adjust GUIWindowFullscreen: don't toggle DynamicResourceAlloc, shuffl…
…e deinit order a little and let generic window code to handle control unloading/freeing
32fdcd9
@pieh pieh adjust GUIDialogTextViewer: reset textarea and heading controls after…
… deinit
aa037df
@pieh pieh adjust GUIDialogSmartPlaylistEditor: move playlist type specific conf…
…iguration to OnInitWindow
00bd5fb
@pieh pieh adjust GUIDialogSmartPlaylistRule: clear rule spinner before filling …
…it, clear rule and operand spinner on deinit and try to change value button to edit control just once on window load
5649658
@pieh pieh adjust GUIWindowSystemInfo: clear labels on window deinit d11b741
@pieh pieh log: add window loadType to debug log on window load 7614940
@pieh pieh merged commit 2cc5bc9 into from
@Voyager1
Collaborator

I'm noticing problems with stale information still being displayed in some of the labels on the Video Info dialog (CGUIDialogVideoInfo), e.g. the file path, the media labels (1080, xvid, bluray etc.) and others. When some label is "empty" the next time, it does not replace what was there the last time.

I believe that it has to do with this new feature. Just like what was done with other windows/dialogs part of this change, we probably need to clear the labels in the DEINIT event?

@pieh
Collaborator

right, I must have missed it, will fix it

@Voyager1
Collaborator

just confirming that as a temp fix, I commented out m_loadType = KEEP_IN_MEMORY; in the CGUIDialogVideoInfo constructor.

@Voyager1
Collaborator

Same problem with CGUIDialogMusicInfo. Just get the album info for one, then for the next. Doesn't update.

@pieh
Collaborator

hmm, this is weird - what skin are you using?

@Voyager1
Collaborator

Confluence, the standard!

@Voyager1
Collaborator

just tested with commenting out the keep in memory, fixes the issue again for the album info (CGUIDialogMusicInfo)

@Voyager1
Collaborator

you have to look closely, it's the artist, genre, rating, year and the artwork that remain the same as the first one you opened...

@pieh
Collaborator

right, it's something with rendering - if you'll hover mouse on it it will refresh

@Voyager1
Collaborator

i saw that too. (although I used the keyboard arrows). So how to fix?

@elupus
Collaborator
@pieh
Collaborator

this is problem with controls in containers - they refresh only when layout is marked invalid, will fix that
EDIT: well that's not the problem - will fix layout not being invalidated

@pieh
Collaborator

fixed in 8b796ee

@Voyager1
Collaborator

just tried it. it's not entirely fixed: the media flags still don't update correctly. Eg. the first one I view is bluray, the next one not, but the flag is still there.

EDIT: same with the music albums. Try an album with cover art, then another without. The first album art is still displayed...

@pieh
Collaborator

@Voyager-xbmc
here's my proposed fix for that pieh@affcec9 - it fixes given issue, just not sure it won't cause another. Won't push it yet because i'm going off for the weekend and don't won't to introduce any unknown bug when I'm bit available.

@Voyager1
Collaborator

@pieh - thanks for the great work. I was close to the same solution (only the 2nd if though) but I think this is it. I'll play with it - happy to report experiences after the weekend :-)

@jmarshallnz
Owner
@Voyager1
Collaborator

@jmarshallnz - the issue is that pieh's PR altered the way windows get loaded. Previously they were loaded every time, now they stay in memory and get reused, thereby speeding up the GUI. This means that controls don't get reinitialised via constructor. In between inits an image on a window should be able to change, e.g. the album art, the media flag images... The problem was that if we went from an "old" image with an actual texture in it (e.g the 720.png flag) to a "new" image path that was empty (e.g. no flag set), somehow it didn't change the texture. By debugging I found that the m_currentTexture would indeed be empty, but the m_texture.m_info filename was still the old one (e.g. 720.png). It turned out m_texture.SetFileName wasn't called, nor did we mark the dirtyregion.

Edit:
don't know if this is useful, but anyway, I first tried to resolve it by calling m_texture.setFileName in CGUIImage::FreeTextures, to resolve the issue of the old filename still being there, but that didn't help. You also need to mark the image dirty, but that caused too many issues so I abandoned.

@pieh
Collaborator
@jmarshallnz
Owner
@Voyager1
Collaborator

tried this, and it works. Just don't empty the m_currentTexture anymore, so the comparison with strFileName in ::SetFileName works properly. I checked and m_currentTexture isn't much used anywhere else. I also tried messing with clearing out the texture info (m_info.filename) in the free texture method, but that creates a lot of issues with the gui...

void CGUIImage::FreeTextures(bool immediately /* = false */)
{
  m_texture.FreeResources(immediately);
  for (unsigned int i = 0; i < m_fadingTextures.size(); i++)
    delete m_fadingTextures[i];
  m_fadingTextures.clear();
  //m_currentTexture.Empty(); <-- remove this!
} 
@jmarshallnz
Owner
@Voyager1
Collaborator

the problem is more than just keeping them in sync.
Here's what happens if you call m_texture.SetFilename in CGUIImage::FreeTextures:

http://imageshack.us/a/img703/5720/screenshot001yo.png

@Voyager1
Collaborator

and when you move the m_texture.SetFileName(m_currentTexture); as the first line to CGUIImage::AllocResources, results are even worse. Lots of textures missing.

http://imageshack.us/a/img152/6313/screenshot000u.png

Somehow, I think that my proposal to NOT clear m_currentTexture is the least intrusive. This member variable is just used to carry the latest texture filename used, nothing else. Not clearing it means you can appropriately track a change from a non-empty to an empty picture...

@pieh
Collaborator

@Voyager-xbmc
this line ( abbacb5 ) was added as part of the fix for http://trac.xbmc.org/ticket/9926 . Not sure if it's ok to remove it completely, so here's my next attempt: pieh@13c843b

this won't make textures dissapear - problem with disappearing textures is that if texture path is constant (as in no InfoLabels are used, so all confluence textures) we will only update texture once - when we create image control. This won't break it because constant texture path doesn't use m_currentFile (leaving it empty) so when I try to set file name in ::FreeTextures it won't have any effect (as new and old path are both empty)

it still isn't as nice as I would like it (mostly part that it won't break constant textures "only by accident"), but at least better than previous "fix"

@jmarshallnz
Owner

Isn't that identical to calling m_texture.SetFilename("") after resetting m_current texture ?

@Voyager1
Collaborator

@jmarshallnz : I would say it's almost identical, with the exception of two things: checking the value already in m_currentTexture (don't do anything if already empty) and the dirty region handling. With pieh's solution working fine, I have adapted it as follows. Note that without the if (!m_currentTexture.Equals("")) you get again a lot of empty/missing images as in my screenshots above.

void CGUIImage::FreeTextures(bool immediately /* = false */)
{
  m_texture.FreeResources(immediately);
  for (unsigned int i = 0; i < m_fadingTextures.size(); i++)
    delete m_fadingTextures[i];
  m_fadingTextures.clear();
  if (!m_currentTexture.Equals(""))
  {
    m_currentTexture = "";
    if (m_texture.SetFileName(m_currentTexture))
      MarkDirtyRegion();
  }
}
@jmarshallnz
Owner
@Voyager1
Collaborator

You're right. Reduced it to the following, and still works ok:

void CGUIImage::FreeTextures(bool immediately /* = false */)
{
  m_texture.FreeResources(immediately);
  for (unsigned int i = 0; i < m_fadingTextures.size(); i++)
    delete m_fadingTextures[i];
  m_fadingTextures.clear();
  if (!m_currentTexture.IsEmpty())
  {
    m_currentTexture.Empty();
    m_texture.SetFileName(m_currentTexture);
  }
}

So it seems that the if guard is what is making the difference. Probably FreeTextures is called when m_currentTexture is already empty but m_texture is not, in which case without the if guard we would empty the m_texture's filename, thus causing the missing images from my screenshots above.

@Voyager1
Collaborator

Additional info: So it seems to work fine with the code I posted above. However, there are now still cases where m_currentTexture is empty while m_texture's filename is not. Apparently m_texture's filename is set in a number of places in CGUIImage, without syncing m_currentTexture, e.g. the contstructors, CGUIImage::Process and CGUIImage::SetInfo. I tried to make sure we sync it in all those places, but then the problem I described with the screenshots reappears. Similarly, I removed m_currentTexture everywhere and replaced it with m_texture.GetFileName() - same issue. I don't know the code enough, but it seems that those two are not really meant to be in sync at all times.

@pieh
Collaborator

Additional info: So it seems to work fine with the code I posted above. However, there are now still cases where m_currentTexture is empty while m_texture's filename is not. Apparently m_texture's filename is set in a number of places in CGUIImage, without syncing m_currentTexture, e.g. the contstructors, CGUIImage::Process and CGUIImage::SetInfo. I tried to make sure we sync it in all those places, but then the problem I described with the screenshots reappears. Similarly, I removed m_currentTexture everywhere and replaced it with m_texture.GetFileName() - same issue. I don't know the code enough, but it seems that those two are not really meant to be in sync at all times.

There are 2 cases: we use constant texture path: f.e. "floor.png" or we use dynamic texture path: f.e. "$INFO[ListItem.Icon]". First one will just set texture's filename in CGUI::SetInfo without using m_currentTexture at all (so it will stay empty) - in this case we can't simply reset texture's filename as we won't update texture next time we load window (that's why there are missing textures as texture has empty path). Second one will be evaluated each frame and compared to m_currentTexture and update both m_currentTexture and texture object if it changed - so as long as we keep m_texture and m_currentTexture in sync it will be good.

So IMO good solution would be to both clear m_currentTexture and m_texture and set texture path in method that is called when window is inited. There's obviously catch as this method would be ::AllocResources but CGUIImage has DynamicResourceAlloc flag set which means AllocResoures won't be called on window init and image control itself is in charge of allocating resources. I will try to get around this and see what I can come up with.

@pieh
Collaborator

here's another take on it: pieh@a5b3b36

@Voyager1
Collaborator

tried it, and looks good. I don't know if there is a real reason to keep m_currentTexture empty for the constant textures. In any case I tried your solution, it works. I have also tried modifying it to also sync m_currentTexture in ::AllocResources and that works too.

    if (m_info.IsConstant()) 
    {
      m_texture.SetFileName(m_info.GetLabel(0)); 
      m_currentTexture = m_texture.GetFileName();
    }
@jmarshallnz
Owner
@Voyager1
Collaborator

@jmarshallnz - just to make sure, you mean it like this?

void CGUIImage::FreeTextures(bool immediately /* = false */)
{
  m_texture.FreeResources(immediately);
  for (unsigned int i = 0; i < m_fadingTextures.size(); i++)
    delete m_fadingTextures[i];
  m_fadingTextures.clear();
  if (!m_info.IsConstant()) // constant textures never change 
  {
    m_currentTexture.Empty();
    m_texture.SetFileName(m_currentTexture);
  }
}
@jmarshallnz
Owner
@Voyager1
Collaborator

@jmarshallnz - got it. This works too. Thanks!!

void CGUIImage::FreeTextures(bool immediately /* = false */)
{
  m_texture.FreeResources(immediately);
  for (unsigned int i = 0; i < m_fadingTextures.size(); i++)
    delete m_fadingTextures[i];
  m_fadingTextures.clear();
  m_currentTexture.Empty();
  if (!m_info.IsConstant()) // constant textures never change 
    m_texture.SetFileName("");
}
@pieh
Collaborator

@jmarshallnz
here's pack of fixes for regressions I've introduced (first 3 commits), including one we were discussing + additional "improvment" for multiimage to avoid loading directory 2 times on alloc: https://github.com/pieh/xbmc/compare/empty_image_fix

push them or they need more work?

@jmarshallnz
Owner
@dersphere

This causes issue #13351 (http://trac.xbmc.org/ticket/13351).
In short: "Choose a Scraper" and "Current Scraper" are empty on second enter of CGUIDialogContentSettings:
On first init m_scrapers are being filled, on deinit they are cleared and on second open they are not beeing re-filled.

I would fix that with an PR but I don't know what is the desired way ;-)

@t-nelson
@LongChair LongChair referenced this pull request from a commit in plexinc/plex-home-theater-public
@LongChair LongChair Fix Cannot jump to home from Extras strip #1283
When you have a scrolling list, Application will try first to send the message to the window rather than processing it.
in the case of 'h' key, and on preplay window, the BUILTIN message will come down to preplay window and be handled by a controlgroup that will put it in an onclick message forwarded to the controls. this is pretty much insane.

So we just say that we dont wanna handle builtins, then Application will handle them properly.
427b5a8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 8, 2012
  1. @pieh

    allow include resolver to store checked include conditions and their …

    pieh authored
    …values into map<conditionID:int, value:bool>
    
    store conditions and values used to resolve includes in CGUIWindow
    added CGUIInfoManager::ConditionsChangedValues method
  2. @pieh
  3. @pieh

    allow not to free memory (destroy controls objects) when exiting window

    pieh authored
    added additional checks in AllocResources - we have to load .xml file if:
     - load type is set to LOAD_EVERY_TIME (all windows use it by default)
     - window is loaded and any of include condition have changed value
     - window isn't loaded
    
    we have to unload window before loading if window wasn't unloaded before and include conditions have change value(s)
  4. @pieh

    store and reuse window xml root node

    pieh authored
    this allows to avoid reading and parsing xml file in windows we already used before and are loaded on demand or their include conditions have changed values
  5. @pieh

    regression fix: override SetInitialVisibility() in CGUIBaseContainer …

    pieh authored
    …to force restoring static items before restoring control states ( in CGUIWindow::OnInitWindow, SetInitialVisibility() is called before RestoreControlStates() )
    
    not need to call UpdateStaticItems() if we are loading static items from .xml as we do it before SetInitialVisibility is called and it will be called there
  6. @pieh

    adjust GUIDialogContextMenu: cleaning up initialization/deinitializat…

    pieh authored
    …ion of dialog
    
    - we need additional members to remember window coordinates (these are fetched while loading window .xml file and later are changed when setting position of ContextMenu) and size of background image
    - we don't need to call SetInitialVisibility - it's alreadu done in CGUIWindow::OnWindowInit
    - we need to manually remove choice buttons in OnDeinitWindow
    - we need to store size of background image to properly set its size it in consequent showings
  7. @pieh
  8. @pieh

    adjust GUIDialogBoxBase: store heading,lines,choices and set them whe…

    pieh authored
    …n initing window and if dialog is already active
  9. @pieh
  10. @pieh
  11. @pieh

    adjust GUIDialogSelect: don't reset GUIViewControl when leaving windo…

    pieh authored
    …w, clear it
    
    reset it when we unload window
  12. @pieh

    adjust GUIDialogNetworkSetup: change control types only when we load …

    pieh authored
    …window, fill/clear protocol spinner when we init/deinit window
  13. @pieh

    adjust GUIDialogPeripheralManager: we would run OnInitWindow twice du…

    pieh authored
    …e to not consuming GUI_MSG_WINDOW_INIT message
    
    also move init actions to OnInitWindow callback
  14. @pieh
  15. @pieh
  16. @pieh

    adjust GUIWindowFullscreen: don't toggle DynamicResourceAlloc, shuffl…

    pieh authored
    …e deinit order a little and let generic window code to handle control unloading/freeing
  17. @pieh
  18. @pieh

    adjust GUIDialogSmartPlaylistEditor: move playlist type specific conf…

    pieh authored
    …iguration to OnInitWindow
  19. @pieh

    adjust GUIDialogSmartPlaylistRule: clear rule spinner before filling …

    pieh authored
    …it, clear rule and operand spinner on deinit and try to change value button to edit control just once on window load
  20. @pieh
  21. @pieh
This page is out of date. Refresh to see the latest.
Showing with 464 additions and 172 deletions.
  1. +1 −0  xbmc/Application.cpp
  2. +10 −0 xbmc/GUIInfoManager.cpp
  3. +3 −0  xbmc/GUIInfoManager.h
  4. +1 −2  xbmc/addons/AddonCallbacksGUI.cpp
  5. +1 −0  xbmc/addons/GUIDialogAddonInfo.cpp
  6. +5 −2 xbmc/addons/Skin.cpp
  7. +1 −1  xbmc/addons/Skin.h
  8. +51 −24 xbmc/dialogs/GUIDialogBoxBase.cpp
  9. +12 −0 xbmc/dialogs/GUIDialogBoxBase.h
  10. +1 −1  xbmc/dialogs/GUIDialogBusy.cpp
  11. +1 −0  xbmc/dialogs/GUIDialogButtonMenu.cpp
  12. +36 −8 xbmc/dialogs/GUIDialogContextMenu.cpp
  13. +4 −1 xbmc/dialogs/GUIDialogContextMenu.h
  14. +1 −1  xbmc/dialogs/GUIDialogExtendedProgressBar.cpp
  15. +1 −0  xbmc/dialogs/GUIDialogFavourites.cpp
  16. +1 −0  xbmc/dialogs/GUIDialogFileBrowser.cpp
  17. +1 −1  xbmc/dialogs/GUIDialogKaiToast.cpp
  18. +1 −0  xbmc/dialogs/GUIDialogKeyboardGeneric.cpp
  19. +10 −0 xbmc/dialogs/GUIDialogMediaSource.cpp
  20. +1 −0  xbmc/dialogs/GUIDialogMediaSource.h
  21. +1 −1  xbmc/dialogs/GUIDialogMuteBug.cpp
  22. +1 −0  xbmc/dialogs/GUIDialogNumeric.cpp
  23. +7 −0 xbmc/dialogs/GUIDialogOK.cpp
  24. +2 −0  xbmc/dialogs/GUIDialogOK.h
  25. +1 −0  xbmc/dialogs/GUIDialogPlayerControls.cpp
  26. +4 −10 xbmc/dialogs/GUIDialogProgress.cpp
  27. +2 −3 xbmc/dialogs/GUIDialogProgress.h
  28. +1 −1  xbmc/dialogs/GUIDialogSeekBar.cpp
  29. +8 −1 xbmc/dialogs/GUIDialogSelect.cpp
  30. +1 −0  xbmc/dialogs/GUIDialogSelect.h
  31. +5 −0 xbmc/dialogs/GUIDialogSlider.cpp
  32. +18 −15 xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp
  33. +2 −0  xbmc/dialogs/GUIDialogSmartPlaylistEditor.h
  34. +19 −1 xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp
  35. +2 −0  xbmc/dialogs/GUIDialogSmartPlaylistRule.h
  36. +14 −1 xbmc/dialogs/GUIDialogTextViewer.cpp
  37. +2 −0  xbmc/dialogs/GUIDialogTextViewer.h
  38. +1 −1  xbmc/dialogs/GUIDialogVolumeBar.cpp
  39. +21 −2 xbmc/dialogs/GUIDialogYesNo.cpp
  40. +2 −0  xbmc/dialogs/GUIDialogYesNo.h
  41. +10 −3 xbmc/guilib/GUIBaseContainer.cpp
  42. +2 −1  xbmc/guilib/GUIBaseContainer.h
  43. +11 −5 xbmc/guilib/GUIIncludes.cpp
  44. +2 −2 xbmc/guilib/GUIIncludes.h
  45. +14 −0 xbmc/guilib/GUIMessage.h
  46. +75 −22 xbmc/guilib/GUIWindow.cpp
  47. +8 −5 xbmc/guilib/GUIWindow.h
  48. +3 −2 xbmc/guilib/GUIWindowManager.cpp
  49. +1 −1  xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp
  50. +1 −1  xbmc/interfaces/python/xbmcmodule/GUIPythonWindowDialog.cpp
  51. +2 −2 xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp
  52. +1 −1  xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXMLDialog.cpp
  53. +1 −0  xbmc/music/dialogs/GUIDialogMusicInfo.cpp
  54. +1 −0  xbmc/music/dialogs/GUIDialogMusicOSD.cpp
  55. +1 −0  xbmc/music/dialogs/GUIDialogMusicOverlay.cpp
  56. +1 −0  xbmc/music/dialogs/GUIDialogMusicScan.cpp
  57. +1 −0  xbmc/music/dialogs/GUIDialogSongInfo.cpp
  58. +1 −0  xbmc/music/dialogs/GUIDialogVisualisationPresetList.cpp
  59. +1 −0  xbmc/music/windows/GUIWindowVisualisation.cpp
  60. +17 −1 xbmc/network/GUIDialogNetworkSetup.cpp
  61. +2 −0  xbmc/network/GUIDialogNetworkSetup.h
  62. +3 −9 xbmc/peripherals/dialogs/GUIDialogPeripheralManager.cpp
  63. +1 −1  xbmc/peripherals/dialogs/GUIDialogPeripheralManager.h
  64. +1 −0  xbmc/pictures/GUIDialogPictureInfo.cpp
  65. +18 −19 xbmc/pictures/GUIWindowSlideShow.cpp
  66. +1 −1  xbmc/pictures/GUIWindowSlideShow.h
  67. +1 −0  xbmc/settings/GUIDialogSettings.cpp
  68. +1 −0  xbmc/settings/GUIWindowSettings.cpp
  69. +1 −0  xbmc/settings/GUIWindowSettingsCategory.cpp
  70. +1 −0  xbmc/settings/GUIWindowSettingsProfile.cpp
  71. +1 −0  xbmc/video/dialogs/GUIDialogFullScreenInfo.cpp
  72. +1 −0  xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp
  73. +1 −0  xbmc/video/dialogs/GUIDialogVideoInfo.cpp
  74. +1 −0  xbmc/video/dialogs/GUIDialogVideoOSD.cpp
  75. +1 −0  xbmc/video/dialogs/GUIDialogVideoOverlay.cpp
  76. +6 −0 xbmc/video/dialogs/GUIDialogVideoScan.cpp
  77. +4 −16 xbmc/video/windows/GUIWindowFullScreen.cpp
  78. +0 −2  xbmc/video/windows/GUIWindowFullScreen.h
  79. +1 −0  xbmc/windows/GUIMediaWindow.cpp
  80. +1 −0  xbmc/windows/GUIWindowFileManager.cpp
  81. +1 −0  xbmc/windows/GUIWindowHome.cpp
  82. +1 −0  xbmc/windows/GUIWindowLoginScreen.cpp
  83. +1 −1  xbmc/windows/GUIWindowPointer.cpp
  84. +2 −0  xbmc/windows/GUIWindowSystemInfo.cpp
  85. +1 −0  xbmc/windows/GUIWindowWeather.cpp
View
1  xbmc/Application.cpp
@@ -2185,6 +2185,7 @@ bool CApplication::LoadUserWindows()
continue;
}
pWindow->SetVisibleCondition(visibleCondition);
+ pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
g_windowManager.AddCustomWindow(pWindow);
}
}
View
10 xbmc/GUIInfoManager.cpp
@@ -5271,3 +5271,13 @@ CStdString CGUIInfoManager::GetSkinVariableString(int info,
return "";
}
+
+bool CGUIInfoManager::ConditionsChangedValues(const std::map<int, bool>& map)
+{
+ for (std::map<int, bool>::const_iterator it = map.begin() ; it != map.end() ; it++)
+ {
+ if (GetBoolValue(it->first) != it->second)
+ return true;
+ }
+ return false;
+}
View
3  xbmc/GUIInfoManager.h
@@ -801,6 +801,9 @@ class CGUIInfoManager : public IMsgTargetCallback, public Observable
int RegisterSkinVariableString(const INFO::CSkinVariableString* info);
int TranslateSkinVariableString(const CStdString& name, int context);
CStdString GetSkinVariableString(int info, bool preferImage = false, const CGUIListItem *item=NULL);
+
+ /// \brief iterates through boolean conditions and compares their stored values to current values. Returns true if any condition changed value.
+ bool ConditionsChangedValues(const std::map<int, bool>& map);
protected:
friend class INFO::InfoSingle;
bool GetBool(int condition, int contextWindow = 0, const CGUIListItem *item=NULL);
View
3  xbmc/addons/AddonCallbacksGUI.cpp
@@ -1234,7 +1234,7 @@ CGUIAddonWindow::CGUIAddonWindow(int id, CStdString strXML, CAddon* addon)
, m_actionEvent(true)
, m_addon(addon)
{
- m_loadOnDemand = false;
+ m_loadType = LOAD_ON_GUI_INIT;
CBOnInit = NULL;
CBOnFocus = NULL;
CBOnClick = NULL;
@@ -1482,7 +1482,6 @@ CGUIAddonWindowDialog::CGUIAddonWindowDialog(int id, CStdString strXML, CAddon*
: CGUIAddonWindow(id,strXML,addon)
{
m_bRunning = false;
- m_loadOnDemand = false;
m_bIsDialog = true;
}
View
1  xbmc/addons/GUIDialogAddonInfo.cpp
@@ -54,6 +54,7 @@ CGUIDialogAddonInfo::CGUIDialogAddonInfo(void)
: CGUIDialog(WINDOW_DIALOG_ADDON_INFO, "DialogAddonInfo.xml")
{
m_item = CFileItemPtr(new CFileItem);
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogAddonInfo::~CGUIDialogAddonInfo(void)
View
7 xbmc/addons/Skin.cpp
@@ -180,9 +180,12 @@ void CSkinInfo::LoadIncludes()
m_includes.LoadIncludes(includesPath);
}
-void CSkinInfo::ResolveIncludes(TiXmlElement *node)
+void CSkinInfo::ResolveIncludes(TiXmlElement *node, std::map<int, bool>* xmlIncludeConditions /* = NULL */)
{
- m_includes.ResolveIncludes(node);
+ if(xmlIncludeConditions)
+ xmlIncludeConditions->clear();
+
+ m_includes.ResolveIncludes(node, xmlIncludeConditions);
}
int CSkinInfo::GetStartWindow() const
View
2  xbmc/addons/Skin.h
@@ -92,7 +92,7 @@ class CSkinInfo : public CAddon
*/
static bool TranslateResolution(const CStdString &name, RESOLUTION_INFO &res);
- void ResolveIncludes(TiXmlElement *node);
+ void ResolveIncludes(TiXmlElement *node, std::map<int, bool>* xmlIncludeConditions = NULL);
float GetEffectsSlowdown() const { return m_effectsSlowDown; };
View
75 xbmc/dialogs/GUIDialogBoxBase.cpp
@@ -26,10 +26,15 @@
using namespace std;
+#define CONTROL_HEADING 1
+#define CONTROL_LINES_START 2
+#define CONTROL_CHOICES_START 10
+
CGUIDialogBoxBase::CGUIDialogBoxBase(int id, const CStdString &xmlFile)
: CGUIDialog(id, xmlFile)
{
m_bConfirmed = false;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogBoxBase::~CGUIDialogBoxBase(void)
@@ -58,47 +63,58 @@ bool CGUIDialogBoxBase::IsConfirmed() const
void CGUIDialogBoxBase::SetHeading(const CVariant& heading)
{
- Initialize();
- CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), 1);
- msg.SetLabel(GetLocalized(heading));
-
- if(g_application.IsCurrentThread())
- OnMessage(msg);
- else
- g_windowManager.SendThreadMessage(msg, GetID());
+ m_strHeading = GetLocalized(heading);
+ if (IsActive())
+ SET_CONTROL_LABEL_THREAD_SAFE(1, m_strHeading);
}
void CGUIDialogBoxBase::SetLine(int iLine, const CVariant& line)
{
- Initialize();
- CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), iLine + 2);
- msg.SetLabel(GetLocalized(line));
-
- if(g_application.IsCurrentThread())
- OnMessage(msg);
- else
- g_windowManager.SendThreadMessage(msg, GetID());
+ if (iLine < 0 || iLine >= DIALOG_MAX_LINES)
+ return;
+
+ m_strLines[iLine] = GetLocalized(line);
+ if (IsActive())
+ SET_CONTROL_LABEL_THREAD_SAFE(CONTROL_LINES_START + iLine, m_strLines[iLine]);
}
void CGUIDialogBoxBase::SetChoice(int iButton, const CVariant &choice) // iButton == 0 for no, 1 for yes
{
- Initialize();
- CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), 10+iButton);
- msg.SetLabel(GetLocalized(choice));
-
- if(g_application.IsCurrentThread())
- OnMessage(msg);
- else
- g_windowManager.SendThreadMessage(msg, GetID());
+ if (iButton < 0 || iButton >= DIALOG_MAX_CHOICES)
+ return;
+
+ m_strChoices[iButton] = GetLocalized(choice);
+ if (IsActive())
+ SET_CONTROL_LABEL_THREAD_SAFE(CONTROL_CHOICES_START + iButton, m_strChoices[iButton]);
}
void CGUIDialogBoxBase::OnInitWindow()
{
// set focus to default
m_lastControlID = m_defaultControl;
+
+ // set control labels
+ SET_CONTROL_LABEL(CONTROL_HEADING, m_strHeading);
+ for (int i = 0 ; i < DIALOG_MAX_LINES ; ++i)
+ SET_CONTROL_LABEL(CONTROL_LINES_START + i, m_strLines[i]);
+ for (int i = 0 ; i < DIALOG_MAX_CHOICES ; ++i)
+ SET_CONTROL_LABEL(CONTROL_CHOICES_START + i, m_strChoices[i]);
+
CGUIDialog::OnInitWindow();
}
+void CGUIDialogBoxBase::OnDeinitWindow(int nextWindowID)
+{
+ // make sure we set default labels for heading, lines and choices
+ SetHeading(GetDefaultLabel(CONTROL_HEADING));
+ for (int i = 0 ; i < DIALOG_MAX_LINES ; ++i)
+ SetLine(i, GetDefaultLabel(CONTROL_LINES_START + i));
+ for (int i = 0 ; i < DIALOG_MAX_CHOICES ; ++i)
+ SetChoice(i, GetDefaultLabel(CONTROL_CHOICES_START + i));
+
+ CGUIDialog::OnDeinitWindow(nextWindowID);
+}
+
CStdString CGUIDialogBoxBase::GetLocalized(const CVariant &var) const
{
if (var.isString())
@@ -107,3 +123,14 @@ CStdString CGUIDialogBoxBase::GetLocalized(const CVariant &var) const
return g_localizeStrings.Get((uint32_t)var.asInteger());
return "";
}
+
+CStdString CGUIDialogBoxBase::GetDefaultLabel(int controlId) const
+{
+ int labelId = GetDefaultLabelID(controlId);
+ return labelId != -1 ? g_localizeStrings.Get(labelId) : "";
+}
+
+int CGUIDialogBoxBase::GetDefaultLabelID(int controlId) const
+{
+ return -1;
+}
View
12 xbmc/dialogs/GUIDialogBoxBase.h
@@ -24,6 +24,9 @@
#include "guilib/GUIDialog.h"
#include "utils/Variant.h"
+#define DIALOG_MAX_LINES 3
+#define DIALOG_MAX_CHOICES 2
+
class CGUIDialogBoxBase :
public CGUIDialog
{
@@ -36,6 +39,8 @@ class CGUIDialogBoxBase :
void SetHeading(const CVariant &heading);
void SetChoice(int iButton, const CVariant &choice);
protected:
+ CStdString GetDefaultLabel(int controlId) const;
+ virtual int GetDefaultLabelID(int controlId) const;
/*! \brief Get a localized string from a variant
If the varaint is already a string we return directly, else if it's an integer we return the corresponding
localized string.
@@ -44,5 +49,12 @@ class CGUIDialogBoxBase :
CStdString GetLocalized(const CVariant &var) const;
virtual void OnInitWindow();
+ virtual void OnDeinitWindow(int nextWindowID);
+
bool m_bConfirmed;
+
+ // actual strings
+ std::string m_strHeading;
+ std::string m_strLines[DIALOG_MAX_LINES];
+ std::string m_strChoices[DIALOG_MAX_CHOICES];
};
View
2  xbmc/dialogs/GUIDialogBusy.cpp
@@ -25,7 +25,7 @@
CGUIDialogBusy::CGUIDialogBusy(void)
: CGUIDialog(WINDOW_DIALOG_BUSY, "DialogBusy.xml"), m_bLastVisible(false)
{
- m_loadOnDemand = false;
+ m_loadType = LOAD_ON_GUI_INIT;
m_bModal = true;
}
View
1  xbmc/dialogs/GUIDialogButtonMenu.cpp
@@ -29,6 +29,7 @@
CGUIDialogButtonMenu::CGUIDialogButtonMenu(int id, const CStdString &xmlFile)
: CGUIDialog(id, xmlFile)
{
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogButtonMenu::~CGUIDialogButtonMenu(void)
View
44 xbmc/dialogs/GUIDialogContextMenu.cpp
@@ -71,9 +71,12 @@ void CContextButtons::Add(unsigned int button, int label)
push_back(pair<unsigned int, CStdString>(button, g_localizeStrings.Get(label)));
}
-CGUIDialogContextMenu::CGUIDialogContextMenu(void):CGUIDialog(WINDOW_DIALOG_CONTEXT_MENU, "DialogContextMenu.xml")
+CGUIDialogContextMenu::CGUIDialogContextMenu(void)
+ : CGUIDialog(WINDOW_DIALOG_CONTEXT_MENU, "DialogContextMenu.xml")
{
m_clickedButton = -1;
+ m_backgroundImageSize = 0;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogContextMenu::~CGUIDialogContextMenu(void)
@@ -184,12 +187,12 @@ void CGUIDialogContextMenu::SetupButtons()
if (pGroupList->GetOrientation() == VERTICAL)
{
// keep gap between bottom edges of grouplist and background image
- pControl->SetHeight(pControl->GetHeight() - pGroupList->Size() + pGroupList->GetHeight());
+ pControl->SetHeight(m_backgroundImageSize - pGroupList->Size() + pGroupList->GetHeight());
}
else
{
// keep gap between right edges of grouplist and background image
- pControl->SetWidth(pControl->GetWidth() - pGroupList->Size() + pGroupList->GetWidth());
+ pControl->SetWidth(m_backgroundImageSize - pGroupList->Size() + pGroupList->GetWidth());
}
}
#if PRE_SKIN_VERSION_11_COMPATIBILITY
@@ -671,15 +674,39 @@ CMediaSource *CGUIDialogContextMenu::GetShare(const CStdString &type, const CFil
void CGUIDialogContextMenu::OnWindowLoaded()
{
+ m_coordX = m_posX;
+ m_coordY = m_posY;
+
+ const CGUIControlGroupList* pGroupList = NULL;
+ const CGUIControl* pControl = GetControl(GROUP_LIST);
+ if (pControl && pControl->GetControlType() == GUICONTROL_GROUPLIST)
+ pGroupList = (CGUIControlGroupList*)pControl;
+
+ pControl = (CGUIControl *)GetControl(BACKGROUND_IMAGE);
+ if (pControl && pGroupList)
+ {
+ if (pGroupList->GetOrientation() == VERTICAL)
+ m_backgroundImageSize = pControl->GetHeight();
+ else
+ m_backgroundImageSize = pControl->GetWidth();
+ }
+
CGUIDialog::OnWindowLoaded();
- SetInitialVisibility();
- SetupButtons();
}
-void CGUIDialogContextMenu::OnWindowUnload()
+void CGUIDialogContextMenu::OnDeinitWindow(int nextWindowID)
{
+ //we can't be sure that controls are removed on window unload
+ //we have to remove them to be sure that they won't stay for next use of context menu
+ for (unsigned int i = 0; i < m_buttons.size(); i++)
+ {
+ const CGUIControl *control = GetControl(BUTTON_START + i);
+ if (control)
+ RemoveControl(control);
+ }
+
m_buttons.clear();
- CGUIDialog::OnWindowUnload();
+ CGUIDialog::OnDeinitWindow(nextWindowID);
}
CStdString CGUIDialogContextMenu::GetDefaultShareNameByType(const CStdString &strType)
@@ -746,6 +773,7 @@ int CGUIDialogContextMenu::ShowAndGetChoice(const CContextButtons &choices)
{
pMenu->m_buttons = choices;
pMenu->Initialize();
+ pMenu->SetupButtons();
pMenu->PositionAtCurrentFocus();
pMenu->DoModal();
return pMenu->m_clickedButton;
@@ -763,7 +791,7 @@ void CGUIDialogContextMenu::PositionAtCurrentFocus()
{
CPoint pos = focusedControl->GetRenderPosition() + CPoint(focusedControl->GetWidth() * 0.5f, focusedControl->GetHeight() * 0.5f)
+ window->GetRenderPosition();
- SetPosition(m_posX + pos.x - GetWidth() * 0.5f, m_posY + pos.y - GetHeight() * 0.5f);
+ SetPosition(m_coordX + pos.x - GetWidth() * 0.5f, m_coordY + pos.y - GetHeight() * 0.5f);
return;
}
}
View
5 xbmc/dialogs/GUIDialogContextMenu.h
@@ -179,13 +179,16 @@ class CGUIDialogContextMenu :
virtual float GetHeight() const;
virtual void OnInitWindow();
virtual void OnWindowLoaded();
- virtual void OnWindowUnload();
+ virtual void OnDeinitWindow(int nextWindowID);
static CStdString GetDefaultShareNameByType(const CStdString &strType);
static void SetDefault(const CStdString &strType, const CStdString &strDefault);
static void ClearDefault(const CStdString &strType);
static CMediaSource *GetShare(const CStdString &type, const CFileItem *item);
private:
+ float m_coordX, m_coordY;
+ /// \brief Stored size of background image (height or width depending on grouplist orientation)
+ float m_backgroundImageSize;
int m_clickedButton;
CContextButtons m_buttons;
};
View
2  xbmc/dialogs/GUIDialogExtendedProgressBar.cpp
@@ -58,7 +58,7 @@ void CGUIDialogProgressBarHandle::SetProgress(int currentItem, int itemCount)
CGUIDialogExtendedProgressBar::CGUIDialogExtendedProgressBar(void)
: CGUIDialog(WINDOW_DIALOG_EXT_PROGRESS, "DialogExtendedProgressBar.xml")
{
- m_loadOnDemand = false;
+ m_loadType = LOAD_ON_GUI_INIT;
m_iLastSwitchTime = 0;
m_iCurrentItem = 0;
}
View
1  xbmc/dialogs/GUIDialogFavourites.cpp
@@ -39,6 +39,7 @@ CGUIDialogFavourites::CGUIDialogFavourites(void)
: CGUIDialog(WINDOW_DIALOG_FAVOURITES, "DialogFavourites.xml")
{
m_favourites = new CFileItemList;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogFavourites::~CGUIDialogFavourites(void)
View
1  xbmc/dialogs/GUIDialogFileBrowser.cpp
@@ -72,6 +72,7 @@ CGUIDialogFileBrowser::CGUIDialogFileBrowser()
m_thumbLoader.SetObserver(this);
m_flipEnabled = false;
m_multipleSelection = false;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogFileBrowser::~CGUIDialogFileBrowser()
View
2  xbmc/dialogs/GUIDialogKaiToast.cpp
@@ -37,7 +37,7 @@ CGUIDialogKaiToast::CGUIDialogKaiToast(void)
: CGUIDialog(WINDOW_DIALOG_KAI_TOAST, "DialogKaiToast.xml")
{
m_defaultIcon = "";
- m_loadOnDemand = false;
+ m_loadType = LOAD_ON_GUI_INIT;
m_timer = 0;
m_toastDisplayTime = 0;
m_toastMessageTime = 0;
View
1  xbmc/dialogs/GUIDialogKeyboardGeneric.cpp
@@ -68,6 +68,7 @@ CGUIDialogKeyboardGeneric::CGUIDialogKeyboardGeneric()
m_keyType = LOWER;
m_strHeading = "";
m_lastRemoteClickTime = 0;
+ m_loadType = KEEP_IN_MEMORY;
}
void CGUIDialogKeyboardGeneric::OnInitWindow()
View
10 xbmc/dialogs/GUIDialogMediaSource.cpp
@@ -60,6 +60,7 @@ CGUIDialogMediaSource::CGUIDialogMediaSource(void)
: CGUIDialog(WINDOW_DIALOG_MEDIA_SOURCE, "DialogMediaSource.xml")
{
m_paths = new CFileItemList;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogMediaSource::~CGUIDialogMediaSource()
@@ -548,3 +549,12 @@ vector<CStdString> CGUIDialogMediaSource::GetPaths()
}
return paths;
}
+
+void CGUIDialogMediaSource::OnDeinitWindow(int nextWindowID)
+{
+ CGUIDialog::OnDeinitWindow(nextWindowID);
+
+ // clear paths container
+ CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), CONTROL_PATH, 0);
+ OnMessage(msg);
+}
View
1  xbmc/dialogs/GUIDialogMediaSource.h
@@ -33,6 +33,7 @@ class CGUIDialogMediaSource :
CGUIDialogMediaSource(void);
virtual ~CGUIDialogMediaSource(void);
virtual bool OnMessage(CGUIMessage& message);
+ virtual void OnDeinitWindow(int nextWindowID);
virtual bool OnBack(int actionID);
virtual void OnWindowLoaded();
static bool ShowAndAddMediaSource(const CStdString &type);
View
2  xbmc/dialogs/GUIDialogMuteBug.cpp
@@ -28,7 +28,7 @@
CGUIDialogMuteBug::CGUIDialogMuteBug(void)
: CGUIDialog(WINDOW_DIALOG_MUTE_BUG, "DialogMuteBug.xml")
{
- m_loadOnDemand = false;
+ m_loadType = LOAD_ON_GUI_INIT;
}
CGUIDialogMuteBug::~CGUIDialogMuteBug(void)
View
1  xbmc/dialogs/GUIDialogNumeric.cpp
@@ -49,6 +49,7 @@ CGUIDialogNumeric::CGUIDialogNumeric(void)
m_block = 0;
memset(&m_datetime, 0, sizeof(SYSTEMTIME));
m_dirty = false;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogNumeric::~CGUIDialogNumeric(void)
View
7 xbmc/dialogs/GUIDialogOK.cpp
@@ -59,3 +59,10 @@ void CGUIDialogOK::ShowAndGetInput(const CVariant &heading, const CVariant &line
dialog->SetLine(2, line2);
dialog->DoModal();
}
+
+int CGUIDialogOK::GetDefaultLabelID(int controlId) const
+{
+ if (controlId == ID_BUTTON_OK)
+ return 186;
+ return CGUIDialogBoxBase::GetDefaultLabelID(controlId);
+}
View
2  xbmc/dialogs/GUIDialogOK.h
@@ -31,4 +31,6 @@ class CGUIDialogOK :
virtual ~CGUIDialogOK(void);
virtual bool OnMessage(CGUIMessage& message);
static void ShowAndGetInput(const CVariant &heading, const CVariant &line0, const CVariant &line1, const CVariant &line2);
+protected:
+ virtual int GetDefaultLabelID(int controlId) const;
};
View
1  xbmc/dialogs/GUIDialogPlayerControls.cpp
@@ -25,6 +25,7 @@
CGUIDialogPlayerControls::CGUIDialogPlayerControls(void)
: CGUIDialog(WINDOW_DIALOG_PLAYER_CONTROLS, "PlayerControls.xml")
{
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogPlayerControls::~CGUIDialogPlayerControls(void)
View
14 xbmc/dialogs/GUIDialogProgress.cpp
@@ -199,15 +199,9 @@ void CGUIDialogProgress::ShowProgressBar(bool bOnOff)
g_windowManager.SendThreadMessage(msg, GetID());
}
-void CGUIDialogProgress::SetHeading(const string& strLine)
+int CGUIDialogProgress::GetDefaultLabelID(int controlId) const
{
- m_strHeading = strLine;
- CGUIDialogBoxBase::SetHeading(m_strHeading);
+ if (controlId == CONTROL_CANCEL_BUTTON)
+ return 222;
+ return CGUIDialogBoxBase::GetDefaultLabelID(controlId);
}
-
-void CGUIDialogProgress::SetHeading(int iString)
-{
- m_strHeading = g_localizeStrings.Get(iString);
- CGUIDialogBoxBase::SetHeading(m_strHeading);
-}
-
View
5 xbmc/dialogs/GUIDialogProgress.h
@@ -41,8 +41,6 @@ class CGUIDialogProgress :
void SetPercentage(int iPercentage);
int GetPercentage() const { return m_percentage; };
void ShowProgressBar(bool bOnOff);
- void SetHeading(const std::string& strLine);
- void SetHeading(int iString); // for convenience to lookup in strings.xml
// Implements IProgressCallback
virtual void SetProgressMax(int iMax);
@@ -52,9 +50,10 @@ class CGUIDialogProgress :
void SetCanCancel(bool bCanCancel);
protected:
+ virtual int GetDefaultLabelID(int controlId) const;
+
bool m_bCanCancel;
bool m_bCanceled;
- std::string m_strHeading;
int m_iCurrent;
int m_iMax;
View
2  xbmc/dialogs/GUIDialogSeekBar.cpp
@@ -37,7 +37,7 @@
CGUIDialogSeekBar::CGUIDialogSeekBar(void)
: CGUIDialog(WINDOW_DIALOG_SEEK_BAR, "DialogSeekBar.xml")
{
- m_loadOnDemand = false; // the application class handles our resources
+ m_loadType = LOAD_ON_GUI_INIT; // the application class handles our resources
}
CGUIDialogSeekBar::~CGUIDialogSeekBar(void)
View
9 xbmc/dialogs/GUIDialogSelect.cpp
@@ -40,6 +40,7 @@ CGUIDialogSelect::CGUIDialogSelect(void)
m_multiSelection = false;
m_vecList = m_vecListInternal;
m_iSelected = -1;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogSelect::~CGUIDialogSelect(void)
@@ -55,7 +56,7 @@ bool CGUIDialogSelect::OnMessage(CGUIMessage& message)
case GUI_MSG_WINDOW_DEINIT:
{
CGUIDialog::OnMessage(message);
- m_viewControl.Reset();
+ m_viewControl.Clear();
m_bButtonEnabled = false;
m_useDetails = false;
@@ -337,3 +338,9 @@ void CGUIDialogSelect::OnInitWindow()
if (m_iSelected >= 0)
m_viewControl.SetSelectedItem(m_iSelected);
}
+
+void CGUIDialogSelect::OnWindowUnload()
+{
+ CGUIDialog::OnWindowUnload();
+ m_viewControl.Reset();
+}
View
1  xbmc/dialogs/GUIDialogSelect.h
@@ -59,6 +59,7 @@ class CGUIDialogSelect :
virtual CGUIControl *GetFirstFocusableControl(int id);
virtual void OnWindowLoaded();
virtual void OnInitWindow();
+ virtual void OnWindowUnload();
bool m_bButtonEnabled;
bool m_bButtonPressed;
View
5 xbmc/dialogs/GUIDialogSlider.cpp
@@ -33,6 +33,7 @@ CGUIDialogSlider::CGUIDialogSlider(void)
{
m_callback = NULL;
m_callbackData = NULL;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogSlider::~CGUIDialogSlider(void)
@@ -64,6 +65,10 @@ bool CGUIDialogSlider::OnMessage(CGUIMessage& message)
}
}
break;
+ case GUI_MSG_WINDOW_DEINIT:
+ m_callback = NULL;
+ m_callbackData = NULL;
+ break;
}
return CGUIDialog::OnMessage(message);
}
View
33 xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp
@@ -72,6 +72,7 @@ CGUIDialogSmartPlaylistEditor::CGUIDialogSmartPlaylistEditor(void)
{
m_cancelled = false;
m_ruleLabels = new CFileItemList;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogSmartPlaylistEditor::~CGUIDialogSmartPlaylistEditor()
@@ -122,21 +123,6 @@ bool CGUIDialogSmartPlaylistEditor::OnMessage(CGUIMessage& message)
return true;
}
break;
- case GUI_MSG_WINDOW_INIT:
- {
- m_cancelled = false;
- UpdateButtons();
- }
- break;
- case GUI_MSG_WINDOW_DEINIT:
- {
- CGUIDialog::OnMessage(message);
- // clear the rule list
- CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), CONTROL_RULE_LIST);
- OnMessage(msg);
- m_ruleLabels->Clear();
- }
- break;
case GUI_MSG_FOCUSED:
if (message.GetControlId() == CONTROL_RULE_REMOVE ||
message.GetControlId() == CONTROL_RULE_EDIT)
@@ -340,6 +326,13 @@ void CGUIDialogSmartPlaylistEditor::OnWindowLoaded()
msg.SetLabel(label);
OnMessage(msg);
}
+}
+
+void CGUIDialogSmartPlaylistEditor::OnInitWindow()
+{
+ m_cancelled = false;
+ UpdateButtons();
+
SendMessage(GUI_MSG_ITEM_SELECT, CONTROL_LIMIT, m_playlist.m_limit);
vector<PLAYLIST_TYPE> allowedTypes;
@@ -386,6 +379,16 @@ void CGUIDialogSmartPlaylistEditor::OnWindowLoaded()
SendMessage(GUI_MSG_ITEM_SELECT, CONTROL_TYPE, type);
m_playlist.SetType(ConvertType(type));
+
+ CGUIDialog::OnInitWindow();
+}
+
+void CGUIDialogSmartPlaylistEditor::OnDeinitWindow(int nextWindowID)
+{
+ CGUIDialog::OnDeinitWindow(nextWindowID);
+ CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), CONTROL_RULE_LIST);
+ OnMessage(msg);
+ m_ruleLabels->Clear();
}
CGUIDialogSmartPlaylistEditor::PLAYLIST_TYPE CGUIDialogSmartPlaylistEditor::ConvertType(const CStdString &type)
View
2  xbmc/dialogs/GUIDialogSmartPlaylistEditor.h
@@ -37,6 +37,8 @@ class CGUIDialogSmartPlaylistEditor :
virtual bool OnMessage(CGUIMessage& message);
virtual bool OnBack(int actionID);
virtual void OnWindowLoaded();
+ virtual void OnInitWindow();
+ virtual void OnDeinitWindow(int nextWindowID);
static bool EditPlaylist(const CStdString &path, const CStdString &type = "");
static bool NewPlaylist(const CStdString &type);
View
20 xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp
@@ -45,6 +45,7 @@ CGUIDialogSmartPlaylistRule::CGUIDialogSmartPlaylistRule(void)
: CGUIDialog(WINDOW_DIALOG_SMART_PLAYLIST_RULE, "SmartPlaylistRule.xml")
{
m_cancelled = false;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogSmartPlaylistRule::~CGUIDialogSmartPlaylistRule()
@@ -412,10 +413,17 @@ void CGUIDialogSmartPlaylistRule::AddOperatorLabel(CSmartPlaylistRule::SEARCH_OP
OnMessage(select);
}
-void CGUIDialogSmartPlaylistRule::OnInitWindow()
+void CGUIDialogSmartPlaylistRule::OnWindowLoaded()
{
+ CGUIWindow::OnWindowLoaded();
ChangeButtonToEdit(CONTROL_VALUE, true); // true for single label
+}
+
+void CGUIDialogSmartPlaylistRule::OnInitWindow()
+{
CGUIDialog::OnInitWindow();
+
+ SendMessage(GUI_MSG_LABEL_RESET, CONTROL_FIELD);
// add the fields to the field spincontrol
vector<Field> fields = CSmartPlaylistRule::GetFields(m_type);
for (unsigned int i = 0; i < fields.size(); i++)
@@ -427,6 +435,16 @@ void CGUIDialogSmartPlaylistRule::OnInitWindow()
UpdateButtons();
}
+void CGUIDialogSmartPlaylistRule::OnDeinitWindow(int nextWindowID)
+{
+ CGUIDialog::OnDeinitWindow(nextWindowID);
+
+ // reset field spincontrolex
+ SendMessage(GUI_MSG_LABEL_RESET, CONTROL_FIELD);
+ // reset operator spincontrolex
+ SendMessage(GUI_MSG_LABEL_RESET, CONTROL_OPERATOR);
+}
+
bool CGUIDialogSmartPlaylistRule::EditRule(CSmartPlaylistRule &rule, const CStdString& type)
{
CGUIDialogSmartPlaylistRule *editor = (CGUIDialogSmartPlaylistRule *)g_windowManager.GetWindow(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
View
2  xbmc/dialogs/GUIDialogSmartPlaylistRule.h
@@ -33,6 +33,8 @@ class CGUIDialogSmartPlaylistRule :
virtual bool OnMessage(CGUIMessage& message);
virtual bool OnBack(int actionID);
virtual void OnInitWindow();
+ virtual void OnWindowLoaded();
+ virtual void OnDeinitWindow(int nextWindowID);
static bool EditRule(CSmartPlaylistRule &rule, const CStdString& type="songs");
View
15 xbmc/dialogs/GUIDialogTextViewer.cpp
@@ -27,7 +27,9 @@
CGUIDialogTextViewer::CGUIDialogTextViewer(void)
: CGUIDialog(WINDOW_DIALOG_TEXT_VIEWER, "DialogTextViewer.xml")
-{}
+{
+ m_loadType = KEEP_IN_MEMORY;
+}
CGUIDialogTextViewer::~CGUIDialogTextViewer(void)
{}
@@ -79,3 +81,14 @@ void CGUIDialogTextViewer::SetHeading()
OnMessage(msg);
}
+void CGUIDialogTextViewer::OnDeinitWindow(int nextWindowID)
+{
+ CGUIDialog::OnDeinitWindow(nextWindowID);
+
+ // reset text area
+ CGUIMessage msgReset(GUI_MSG_LABEL_RESET, GetID(), CONTROL_TEXTAREA);
+ OnMessage(msgReset);
+
+ // reset heading
+ SET_CONTROL_LABEL(CONTROL_HEADING, "");
+}
View
2  xbmc/dialogs/GUIDialogTextViewer.h
@@ -34,6 +34,8 @@ class CGUIDialogTextViewer :
void SetText(const CStdString& strText) { m_strText = strText; }
void SetHeading(const CStdString& strHeading) { m_strHeading = strHeading; }
protected:
+ virtual void OnDeinitWindow(int nextWindowID);
+
CStdString m_strText;
CStdString m_strHeading;
View
2  xbmc/dialogs/GUIDialogVolumeBar.cpp
@@ -27,7 +27,7 @@
CGUIDialogVolumeBar::CGUIDialogVolumeBar(void)
: CGUIDialog(WINDOW_DIALOG_VOLUME_BAR, "DialogVolumeBar.xml")
{
- m_loadOnDemand = false;
+ m_loadType = LOAD_ON_GUI_INIT;
SetAutoClose(VOLUME_BAR_DISPLAY_TIME);
}
View
23 xbmc/dialogs/GUIDialogYesNo.cpp
@@ -22,6 +22,9 @@
#include "GUIDialogYesNo.h"
#include "guilib/GUIWindowManager.h"
+#define CONTROL_NO_BUTTON 10
+#define CONTROL_YES_BUTTON 11
+
CGUIDialogYesNo::CGUIDialogYesNo(int overrideId /* = -1 */)
: CGUIDialogBoxBase(overrideId == -1 ? WINDOW_DIALOG_YES_NO : overrideId, "DialogYesNo.xml")
{
@@ -42,13 +45,13 @@ bool CGUIDialogYesNo::OnMessage(CGUIMessage& message)
int iAction = message.GetParam1();
if (1 || ACTION_SELECT_ITEM == iAction)
{
- if (iControl == 10)
+ if (iControl == CONTROL_NO_BUTTON)
{
m_bConfirmed = false;
Close();
return true;
}
- if (iControl == 11)
+ if (iControl == CONTROL_YES_BUTTON)
{
m_bConfirmed = true;
Close();
@@ -93,8 +96,12 @@ bool CGUIDialogYesNo::ShowAndGetInput(int heading, int line0, int line1, int lin
dialog->SetAutoClose(autoCloseTime);
if (iNoLabel != -1)
dialog->SetChoice(0,iNoLabel);
+ else
+ dialog->SetChoice(0,106);
if (iYesLabel != -1)
dialog->SetChoice(1,iYesLabel);
+ else
+ dialog->SetChoice(1,107);
dialog->m_bCanceled = false;
dialog->DoModal();
bCanceled = dialog->m_bCanceled;
@@ -118,10 +125,22 @@ bool CGUIDialogYesNo::ShowAndGetInput(const CStdString& heading, const CStdStrin
dialog->m_bCanceled = false;
if (!noLabel.IsEmpty())
dialog->SetChoice(0,noLabel);
+ else
+ dialog->SetChoice(0,106);
if (!yesLabel.IsEmpty())
dialog->SetChoice(1,yesLabel);
+ else
+ dialog->SetChoice(1,107);
dialog->DoModal();
bCanceled = dialog->m_bCanceled;
return (dialog->IsConfirmed()) ? true : false;
}
+int CGUIDialogYesNo::GetDefaultLabelID(int controlId) const
+{
+ if (controlId == CONTROL_NO_BUTTON)
+ return 106;
+ else if (controlId == CONTROL_YES_BUTTON)
+ return 107;
+ return CGUIDialogBoxBase::GetDefaultLabelID(controlId);
+}
View
2  xbmc/dialogs/GUIDialogYesNo.h
@@ -38,5 +38,7 @@ class CGUIDialogYesNo :
static bool ShowAndGetInput(const CStdString& heading, const CStdString& line0, const CStdString& line1, const CStdString& line2, const CStdString& noLabel="", const CStdString& yesLabel="");
static bool ShowAndGetInput(const CStdString& heading, const CStdString& line0, const CStdString& line1, const CStdString& line2, bool &bCanceled, const CStdString& noLabel="", const CStdString& yesLabel="");
protected:
+ virtual int GetDefaultLabelID(int controlId) const;
+
bool m_bCanceled;
};
View
13 xbmc/guilib/GUIBaseContainer.cpp
@@ -891,6 +891,12 @@ void CGUIBaseContainer::UpdateStaticItems(bool refreshItems)
}
}
+void CGUIBaseContainer::SetInitialVisibility()
+{
+ UpdateStaticItems(true);
+ CGUIControl::SetInitialVisibility();
+}
+
void CGUIBaseContainer::CalculateLayout()
{
CGUIListItemLayout *oldFocusedLayout = m_focusedLayout;
@@ -1041,16 +1047,17 @@ void CGUIBaseContainer::LoadContent(TiXmlElement *content)
}
item = item->NextSiblingElement("item");
}
- SetStaticContent(items);
+ SetStaticContent(items, false);
}
-void CGUIBaseContainer::SetStaticContent(const vector<CGUIListItemPtr> &items)
+void CGUIBaseContainer::SetStaticContent(const vector<CGUIListItemPtr> &items, bool forceUpdate /* = true */)
{
m_staticContent = true;
m_staticUpdateTime = 0;
m_staticItems.clear();
m_staticItems.assign(items.begin(), items.end());
- UpdateStaticItems(true);
+ if (forceUpdate)
+ UpdateStaticItems(true);
}
void CGUIBaseContainer::SetRenderOffset(const CPoint &offset)
View
3  xbmc/guilib/GUIBaseContainer.h
@@ -56,6 +56,7 @@ class CGUIBaseContainer : public CGUIControl
virtual void AllocResources();
virtual void FreeResources(bool immediately = false);
virtual void UpdateVisibility(const CGUIListItem *item = NULL);
+ virtual void SetInitialVisibility();
virtual unsigned int GetRows() const;
@@ -85,7 +86,7 @@ class CGUIBaseContainer : public CGUIControl
virtual bool GetCondition(int condition, int data) const;
CStdString GetLabel(int info) const;
- void SetStaticContent(const std::vector<CGUIListItemPtr> &items);
+ void SetStaticContent(const std::vector<CGUIListItemPtr> &items, bool forceUpdate = true);
/*! \brief Set the offset of the first item in the container from the container's position
Useful for lists/panels where the focused item may be larger than the non-focused items and thus
View
16 xbmc/guilib/GUIIncludes.cpp
@@ -175,21 +175,21 @@ bool CGUIIncludes::HasIncludeFile(const CStdString &file) const
return false;
}
-void CGUIIncludes::ResolveIncludes(TiXmlElement *node)
+void CGUIIncludes::ResolveIncludes(TiXmlElement *node, std::map<int, bool>* xmlIncludeConditions /* = NULL */)
{
if (!node)
return;
- ResolveIncludesForNode(node);
+ ResolveIncludesForNode(node, xmlIncludeConditions);
TiXmlElement *child = node->FirstChildElement();
while (child)
{
- ResolveIncludes(child);
+ ResolveIncludes(child, xmlIncludeConditions);
child = child->NextSiblingElement();
}
}
-void CGUIIncludes::ResolveIncludesForNode(TiXmlElement *node)
+void CGUIIncludes::ResolveIncludesForNode(TiXmlElement *node, std::map<int, bool>* xmlIncludeConditions /* = NULL */)
{
// we have a node, find any <include file="fileName">tagName</include> tags and replace
// recursively with their real includes
@@ -226,7 +226,13 @@ void CGUIIncludes::ResolveIncludesForNode(TiXmlElement *node)
const char *condition = include->Attribute("condition");
if (condition)
{ // check this condition
- if (!g_infoManager.EvaluateBool(condition))
+ int conditionID = g_infoManager.Register(condition);
+ bool value = g_infoManager.GetBoolValue(conditionID);
+
+ if (xmlIncludeConditions)
+ (*xmlIncludeConditions)[conditionID] = value;
+
+ if (!value)
{
include = include->NextSiblingElement("include");
continue;
View
4 xbmc/guilib/GUIIncludes.h
@@ -48,11 +48,11 @@ class CGUIIncludes
"bar" from the include file "foo".
\param node an XML Element - all child elements are traversed.
*/
- void ResolveIncludes(TiXmlElement *node);
+ void ResolveIncludes(TiXmlElement *node, std::map<int, bool>* xmlIncludeConditions = NULL);
const INFO::CSkinVariableString* CreateSkinVariable(const CStdString& name, int context);
private:
- void ResolveIncludesForNode(TiXmlElement *node);
+ void ResolveIncludesForNode(TiXmlElement *node, std::map<int, bool>* xmlIncludeConditions = NULL);
CStdString ResolveConstant(const CStdString &constant) const;
bool HasIncludeFile(const CStdString &includeFile) const;
std::map<CStdString, TiXmlElement> m_includes;
View
14 xbmc/guilib/GUIMessage.h
@@ -212,6 +212,20 @@ do { \
/*!
\ingroup winmsg
+ \brief Set the label of the current control
+ */
+#define SET_CONTROL_LABEL_THREAD_SAFE(controlID,label) \
+{ \
+ CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), controlID); \
+ msg.SetLabel(label); \
+ if(g_application.IsCurrentThread()) \
+ OnMessage(msg); \
+ else \
+ g_windowManager.SendThreadMessage(msg, GetID()); \
+}
+
+/*!
+ \ingroup winmsg
\brief Set the second label of the current control
*/
#define SET_CONTROL_LABEL2(controlID,label) \
View
97 xbmc/guilib/GUIWindow.cpp
@@ -60,7 +60,7 @@ CGUIWindow::CGUIWindow(int id, const CStdString &xmlFile)
m_isDialog = false;
m_needsScaling = true;
m_windowLoaded = false;
- m_loadOnDemand = true;
+ m_loadType = LOAD_EVERY_TIME;
m_closing = false;
m_active = false;
m_renderOrder = 0;
@@ -70,10 +70,13 @@ CGUIWindow::CGUIWindow(int id, const CStdString &xmlFile)
m_manualRunActions = false;
m_exclusiveMouseControl = 0;
m_clearBackground = 0xff000000; // opaque black -> always clear
+ m_windowXMLRootElement = NULL;
}
CGUIWindow::~CGUIWindow(void)
-{}
+{
+ delete m_windowXMLRootElement;
+}
bool CGUIWindow::Load(const CStdString& strFileName, bool bContainsPath)
{
@@ -88,7 +91,21 @@ bool CGUIWindow::Load(const CStdString& strFileName, bool bContainsPath)
int64_t start;
start = CurrentHostCounter();
#endif
- CLog::Log(LOGINFO, "Loading skin file: %s", strFileName.c_str());
+ const char* strLoadType;
+ switch (m_loadType)
+ {
+ case LOAD_ON_GUI_INIT:
+ strLoadType = "LOAD_ON_GUI_INIT";
+ break;
+ case KEEP_IN_MEMORY:
+ strLoadType = "KEEP_IN_MEMORY";
+ break;
+ case LOAD_EVERY_TIME:
+ default:
+ strLoadType = "LOAD_EVERY_TIME";
+ break;
+ }
+ CLog::Log(LOGINFO, "Loading skin file: %s, load type: %s", strFileName.c_str(), strLoadType);
// Find appropriate skin folder + resolution to load from
CStdString strPath;
@@ -115,20 +132,29 @@ bool CGUIWindow::Load(const CStdString& strFileName, bool bContainsPath)
bool CGUIWindow::LoadXML(const CStdString &strPath, const CStdString &strLowerPath)
{
- CXBMCTinyXML xmlDoc;
- if ( !xmlDoc.LoadFile(strPath) && !xmlDoc.LoadFile(CStdString(strPath).ToLower()) && !xmlDoc.LoadFile(strLowerPath))
+ // load window xml if we don't have it stored yet
+ if (!m_windowXMLRootElement)
{
- CLog::Log(LOGERROR, "unable to load:%s, Line %d\n%s", strPath.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
- SetID(WINDOW_INVALID);
- return false;
+ CXBMCTinyXML xmlDoc;
+ if ( !xmlDoc.LoadFile(strPath) && !xmlDoc.LoadFile(CStdString(strPath).ToLower()) && !xmlDoc.LoadFile(strLowerPath))
+ {
+ CLog::Log(LOGERROR, "unable to load:%s, Line %d\n%s", strPath.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
+ SetID(WINDOW_INVALID);
+ return false;
+ }
+ m_windowXMLRootElement = (TiXmlElement*)xmlDoc.RootElement()->Clone();
}
+ else
+ CLog::Log(LOGDEBUG, "Using already stored xml root node for %s", strPath.c_str());
- return Load(xmlDoc);
+ return Load(m_windowXMLRootElement);
}
-bool CGUIWindow::Load(CXBMCTinyXML &xmlDoc)
+bool CGUIWindow::Load(TiXmlElement* pRootElement)
{
- TiXmlElement* pRootElement = xmlDoc.RootElement();
+ if (!pRootElement)
+ return false;
+
if (strcmpi(pRootElement->Value(), "window"))
{
CLog::Log(LOGERROR, "file : XML file doesnt contain <window>");
@@ -139,8 +165,8 @@ bool CGUIWindow::Load(CXBMCTinyXML &xmlDoc)
// be done with respect to the correct aspect ratio
g_graphicsContext.SetScalingResolution(m_coordsRes, m_needsScaling);
- // Resolve any includes that may be present
- g_SkinInfo->ResolveIncludes(pRootElement);
+ // Resolve any includes that may be present and save conditions used to do it
+ g_SkinInfo->ResolveIncludes(pRootElement, &m_xmlIncludeConditions);
// now load in the skin file
SetDefaults();
@@ -685,13 +711,29 @@ void CGUIWindow::AllocResources(bool forceLoad /*= FALSE */)
int64_t start;
start = CurrentHostCounter();
#endif
- // load skin xml fil
- CStdString xmlFile = GetProperty("xmlfile").asString();
- bool bHasPath=false;
- if (xmlFile.Find("\\") > -1 || xmlFile.Find("/") > -1 )
- bHasPath = true;
- if (xmlFile.size() && (forceLoad || m_loadOnDemand || !m_windowLoaded))
- Load(xmlFile,bHasPath);
+ // use forceLoad to determine if xml file needs loading
+ forceLoad |= (m_loadType == LOAD_EVERY_TIME);
+
+ // if window is loaded (not cleared before) and we aren't forced to load
+ // we will have to load it only if include conditions values were changed
+ if (m_windowLoaded && !forceLoad)
+ forceLoad = g_infoManager.ConditionsChangedValues(m_xmlIncludeConditions);
+
+ // if window is loaded and load is forced we have to free window resources first
+ if (m_windowLoaded && forceLoad)
+ FreeResources(true);
+
+ // load skin xml file only if we are forced to load or window isn't loaded yet
+ forceLoad |= !m_windowLoaded;
+ if (forceLoad)
+ {
+ CStdString xmlFile = GetProperty("xmlfile").asString();
+ if (xmlFile.size())
+ {
+ bool bHasPath = xmlFile.Find("\\") > -1 || xmlFile.Find("/") > -1;
+ Load(xmlFile,bHasPath);
+ }
+ }
int64_t slend;
slend = CurrentHostCounter();
@@ -703,7 +745,13 @@ void CGUIWindow::AllocResources(bool forceLoad /*= FALSE */)
int64_t end, freq;
end = CurrentHostCounter();
freq = CurrentHostFrequency();
- CLog::Log(LOGDEBUG,"Alloc resources: %.2fms (%.2f ms skin load)", 1000.f * (end - start) / freq, 1000.f * (slend - start) / freq);
+ if (forceLoad)
+ CLog::Log(LOGDEBUG,"Alloc resources: %.2fms (%.2f ms skin load)", 1000.f * (end - start) / freq, 1000.f * (slend - start) / freq);
+ else
+ {
+ CLog::Log(LOGDEBUG,"Window %s was already loaded", GetProperty("xmlfile").c_str());
+ CLog::Log(LOGDEBUG,"Alloc resources: %.2fm", 1000.f * (end - start) / freq);
+ }
#endif
m_bAllocated = true;
}
@@ -714,7 +762,12 @@ void CGUIWindow::FreeResources(bool forceUnload /*= FALSE */)
CGUIControlGroup::FreeResources();
//g_TextureManager.Dump();
// unload the skin
- if (m_loadOnDemand || forceUnload) ClearAll();
+ if (m_loadType == LOAD_EVERY_TIME || forceUnload) ClearAll();
+ if (forceUnload)
+ {
+ delete m_windowXMLRootElement;
+ m_windowXMLRootElement = NULL;
+ }
}
void CGUIWindow::DynamicResourceAlloc(bool bOnOff)
View
13 xbmc/guilib/GUIWindow.h
@@ -80,6 +80,7 @@ class CGUIWindow : public CGUIControlGroup, protected CCriticalSection
public:
enum WINDOW_TYPE { WINDOW = 0, MODAL_DIALOG, MODELESS_DIALOG, BUTTON_MENU, SUB_MENU };
+ enum LOAD_TYPE { LOAD_EVERY_TIME, LOAD_ON_GUI_INIT, KEEP_IN_MEMORY };
CGUIWindow(int id, const CStdString &xmlFile);
virtual ~CGUIWindow(void);
@@ -144,8 +145,8 @@ class CGUIWindow : public CGUIControlGroup, protected CCriticalSection
virtual bool IsActive() const;
void SetCoordsRes(const RESOLUTION_INFO &res) { m_coordsRes = res; };
const RESOLUTION_INFO &GetCoordsRes() const { return m_coordsRes; };
- void LoadOnDemand(bool loadOnDemand) { m_loadOnDemand = loadOnDemand; };
- bool GetLoadOnDemand() { return m_loadOnDemand; }
+ void SetLoadType(LOAD_TYPE loadType) { m_loadType = loadType; };
+ LOAD_TYPE GetLoadType() { return m_loadType; } const
int GetRenderOrder() { return m_renderOrder; };
virtual void SetInitialVisibility();
virtual bool IsVisible() const { return true; }; // windows are always considered visible as they implement their own
@@ -193,7 +194,7 @@ class CGUIWindow : public CGUIControlGroup, protected CCriticalSection
protected:
virtual EVENT_RESULT OnMouseEvent(const CPoint &point, const CMouseEvent &event);
virtual bool LoadXML(const CStdString& strPath, const CStdString &strLowerPath); ///< Loads from the given file
- bool Load(CXBMCTinyXML &xmlDoc); ///< Loads from the given XML document
+ bool Load(TiXmlElement *pRootElement); ///< Loads from the given XML root element
virtual void LoadAdditionalTags(TiXmlElement *root) {}; ///< Load additional information from the XML document
virtual void SetDefaults();
@@ -235,7 +236,7 @@ class CGUIWindow : public CGUIControlGroup, protected CCriticalSection
RESOLUTION_INFO m_coordsRes; // resolution that the window coordinates are in.
bool m_needsScaling;
bool m_windowLoaded; // true if the window's xml file has been loaded
- bool m_loadOnDemand; // true if the window should be loaded only as needed
+ LOAD_TYPE m_loadType;
bool m_isDialog; // true if we have a dialog, false otherwise.
bool m_dynamicResourceAlloc;
bool m_closing;
@@ -269,13 +270,15 @@ class CGUIWindow : public CGUIControlGroup, protected CCriticalSection
CGUIAction m_loadActions;
CGUIAction m_unloadActions;
+ TiXmlElement* m_windowXMLRootElement;
+
bool m_manualRunActions;
int m_exclusiveMouseControl; ///< \brief id of child control that wishes to receive all mouse events \sa GUI_MSG_EXCLUSIVE_MOUSE
private:
std::map<CStdString, CVariant, icompare> m_mapProperties;
-
+ std::map<int, bool> m_xmlIncludeConditions; ///< \brief used to store conditions used to resolve includes for this window
};
#endif
View
5 xbmc/guilib/GUIWindowManager.cpp
@@ -856,7 +856,7 @@ void CGUIWindowManager::LoadNotOnDemandWindows()
for (WindowMap::iterator it = m_mapWindows.begin(); it != m_mapWindows.end(); it++)
{
CGUIWindow *pWindow = (*it).second;
- if (!pWindow ->GetLoadOnDemand())
+ if (pWindow->GetLoadType() == CGUIWindow::LOAD_ON_GUI_INIT)
{
pWindow->FreeResources(true);
pWindow->Initialize();
@@ -870,7 +870,8 @@ void CGUIWindowManager::UnloadNotOnDemandWindows()
for (WindowMap::iterator it = m_mapWindows.begin(); it != m_mapWindows.end(); it++)
{
CGUIWindow *pWindow = (*it).second;
- if (!pWindow->GetLoadOnDemand())
+ if (pWindow->GetLoadType() == CGUIWindow::LOAD_ON_GUI_INIT ||
+ pWindow->GetLoadType() == CGUIWindow::KEEP_IN_MEMORY)
{
pWindow->FreeResources(true);
}
View
2  xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp
@@ -60,7 +60,7 @@ CGUIPythonWindow::CGUIPythonWindow(int id)
{
pCallbackWindow = NULL;
m_threadState = NULL;
- m_loadOnDemand = false;
+ m_loadType = LOAD_ON_GUI_INIT;
m_destroyAfterDeinit = false;
}
View
2  xbmc/interfaces/python/xbmcmodule/GUIPythonWindowDialog.cpp
@@ -26,7 +26,7 @@
CGUIPythonWindowDialog::CGUIPythonWindowDialog(int id)
:CGUIPythonWindow(id)
{
- m_loadOnDemand = false;
+ m_loadType = LOAD_ON_GUI_INIT;
}
CGUIPythonWindowDialog::~CGUIPythonWindowDialog(void)
View
4 xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp
@@ -49,7 +49,7 @@ CGUIPythonWindowXML::CGUIPythonWindowXML(int id, CStdString strXML, CStdString s
{
pCallbackWindow = NULL;
m_threadState = NULL;
- m_loadOnDemand = false;
+ m_loadType = LOAD_ON_GUI_INIT;
m_scriptPath = strFallBackPath;
m_destroyAfterDeinit = false;
}
@@ -352,7 +352,7 @@ bool CGUIPythonWindowXML::LoadXML(const CStdString &strPath, const CStdString &s
if (xmlDoc.Error())
return false;
- return Load(xmlDoc);
+ return Load(xmlDoc.RootElement());
}
void CGUIPythonWindowXML::FreeResources(bool forceUnLoad /*= FALSE */)
View
2  xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXMLDialog.cpp
@@ -26,7 +26,7 @@
CGUIPythonWindowXMLDialog::CGUIPythonWindowXMLDialog(int id, CStdString strXML, CStdString strFallBackPath)
: CGUIPythonWindowXML(id,strXML,strFallBackPath)
{
- m_loadOnDemand = false;
+ m_loadType = LOAD_ON_GUI_INIT;
}
CGUIPythonWindowXMLDialog::~CGUIPythonWindowXMLDialog(void)
View
1  xbmc/music/dialogs/GUIDialogMusicInfo.cpp
@@ -61,6 +61,7 @@ CGUIDialogMusicInfo::CGUIDialogMusicInfo(void)
{
m_bRefresh = false;
m_albumSongs = new CFileItemList;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogMusicInfo::~CGUIDialogMusicInfo(void)
View
1  xbmc/music/dialogs/GUIDialogMusicOSD.cpp
@@ -33,6 +33,7 @@
CGUIDialogMusicOSD::CGUIDialogMusicOSD(void)
: CGUIDialog(WINDOW_DIALOG_MUSIC_OSD, "MusicOSD.xml")
{
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogMusicOSD::~CGUIDialogMusicOSD(void)
View
1  xbmc/music/dialogs/GUIDialogMusicOverlay.cpp
@@ -29,6 +29,7 @@ CGUIDialogMusicOverlay::CGUIDialogMusicOverlay()
: CGUIDialog(WINDOW_DIALOG_MUSIC_OVERLAY, "MusicOverlay.xml")
{
m_renderOrder = 0;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogMusicOverlay::~CGUIDialogMusicOverlay()
View
1  xbmc/music/dialogs/GUIDialogMusicScan.cpp
@@ -40,6 +40,7 @@ using namespace MUSIC_INFO;
CGUIDialogMusicScan::CGUIDialogMusicScan(void)
: CGUIDialog(WINDOW_DIALOG_MUSIC_SCAN, "DialogMusicScan.xml")
{
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogMusicScan::~CGUIDialogMusicScan(void)
View
1  xbmc/music/dialogs/GUIDialogSongInfo.cpp
@@ -53,6 +53,7 @@ CGUIDialogSongInfo::CGUIDialogSongInfo(void)
m_cancelled = false;
m_needsUpdate = false;
m_startRating = -1;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogSongInfo::~CGUIDialogSongInfo(void)
View
1  xbmc/music/dialogs/GUIDialogVisualisationPresetList.cpp
@@ -39,6 +39,7 @@ CGUIDialogVisualisationPresetList::CGUIDialogVisualisationPresetList(void)
m_currentPreset = 0;
m_vecPresets = new CFileItemList;
m_viz = NULL;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogVisualisationPresetList::~CGUIDialogVisualisationPresetList(void)
View
1  xbmc/music/windows/GUIWindowVisualisation.cpp
@@ -40,6 +40,7 @@ CGUIWindowVisualisation::CGUIWindowVisualisation(void)
m_initTimer(true), m_lockedTimer(true)
{
m_bShowPreset = false;
+ m_loadType = KEEP_IN_MEMORY;
}
bool CGUIWindowVisualisation::OnAction(const CAction &action)
View
18 xbmc/network/GUIDialogNetworkSetup.cpp
@@ -43,6 +43,7 @@ CGUIDialogNetworkSetup::CGUIDialogNetworkSetup(void)
{
m_protocol = NET_PROTOCOL_SMB;
m_confirmed = false;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogNetworkSetup::~CGUIDialogNetworkSetup()
@@ -106,7 +107,7 @@ bool CGUIDialogNetworkSetup::ShowAndGetNetworkAddress(CStdString &path)
return dialog->IsConfirmed();
}
-void CGUIDialogNetworkSetup::OnInitWindow()
+void CGUIDialogNetworkSetup::OnWindowLoaded()
{
// replace our buttons with edits
ChangeButtonToEdit(CONTROL_SERVER_ADDRESS);
@@ -115,6 +116,11 @@ void CGUIDialogNetworkSetup::OnInitWindow()
ChangeButtonToEdit(CONTROL_PORT_NUMBER);
ChangeButtonToEdit(CONTROL_PASSWORD);
+ CGUIDialog::OnWindowLoaded();
+}
+
+void CGUIDialogNetworkSetup::OnInitWindow()
+{
// start as unconfirmed
m_confirmed = false;
@@ -156,6 +162,16 @@ void CGUIDialogNetworkSetup::OnInitWindow()
OnProtocolChange();
}
+void CGUIDialogNetworkSetup::OnDeinitWindow(int nextWindowID)
+{
+ // clear protocol spinner
+ CGUISpinControlEx *pSpin = (CGUISpinControlEx *)GetControl(CONTROL_PROTOCOL);
+ if (pSpin)
+ pSpin->Clear();
+
+ CGUIDialog::OnDeinitWindow(nextWindowID);
+}
+
void CGUIDialogNetworkSetup::OnServerBrowse()
{
// open a filebrowser dialog with the current address
View
2  xbmc/network/GUIDialogNetworkSetup.h
@@ -49,6 +49,8 @@ class CGUIDialogNetworkSetup :
virtual bool OnMessage(CGUIMessage& message);
virtual bool OnBack(int actionID);
virtual void OnInitWindow();
+ virtual void OnWindowLoaded();
+ virtual void OnDeinitWindow(int nextWindowID);
static bool ShowAndGetNetworkAddress(CStdString &path);
View
12 xbmc/peripherals/dialogs/GUIDialogPeripheralManager.cpp
@@ -39,6 +39,7 @@ CGUIDialogPeripheralManager::CGUIDialogPeripheralManager(void) :
m_iSelected(0),
m_peripheralItems(new CFileItemList)
{
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogPeripheralManager::~CGUIDialogPeripheralManager(void)
@@ -69,13 +70,11 @@ bool CGUIDialogPeripheralManager::OnAction(const CAction &action)
return CGUIDialog::OnAction(action);
}
-bool CGUIDialogPeripheralManager::OnMessageInit(CGUIMessage &message)
+void CGUIDialogPeripheralManager::OnInitWindow()
{
- CGUIWindow::OnMessage(message);
+ CGUIWindow::OnInitWindow();
m_iSelected = 0;
Update();
-
- return true;
}
bool CGUIDialogPeripheralManager::OnClickList(CGUIMessage &message)
@@ -137,11 +136,6 @@ bool CGUIDialogPeripheralManager::OnMessage(CGUIMessage& message)
break;
case GUI_MSG_ITEM_SELECT:
return true;
- case GUI_MSG_WINDOW_INIT:
- {
- OnMessageInit(message);
- break;
- }
case GUI_MSG_CLICKED:
return OnMessageClick(message);
}
View
2  xbmc/peripherals/dialogs/GUIDialogPeripheralManager.h
@@ -32,6 +32,7 @@ namespace PERIPHERALS
virtual ~CGUIDialogPeripheralManager(void);
virtual bool OnMessage(CGUIMessage& message);
virtual bool OnAction(const CAction& action);
+ virtual void OnInitWindow();
virtual void OnWindowLoaded(void);
virtual void OnWindowUnload(void);
virtual bool HasListItems() const { return true; };
@@ -39,7 +40,6 @@ namespace PERIPHERALS
virtual void Update(void);
protected:
- virtual bool OnMessageInit(CGUIMessage &message);
virtual bool OnMessageClick(CGUIMessage &message);
virtual bool OnClickList(CGUIMessage &message);
View
1  xbmc/pictures/GUIDialogPictureInfo.cpp
@@ -34,6 +34,7 @@ CGUIDialogPictureInfo::CGUIDialogPictureInfo(void)
: CGUIDialog(WINDOW_DIALOG_PICTURE_INFO, "DialogPictureInfo.xml")
{
m_pictureInfo = new CFileItemList;
+ m_loadType = KEEP_IN_MEMORY;
}
CGUIDialogPictureInfo::~CGUIDialogPictureInfo(void)
View
37 xbmc/pictures/GUIWindowSlideShow.cpp
@@ -144,6 +144,7 @@ CGUIWindowSlideShow::CGUIWindowSlideShow(void)
m_pBackgroundLoader = NULL;
m_slides = new CFileItemList;
m_Resolution = RES_INVALID;
+ m_loadType = KEEP_IN_MEMORY;
Reset();
}
@@ -187,8 +188,21 @@ void CGUIWindowSlideShow::Reset()
m_Resolution = g_graphicsContext.GetVideoResolution();
}
-void CGUIWindowSlideShow::FreeResources()
-{ // wait for any outstanding picture loads
+void CGUIWindowSlideShow::OnDeinitWindow(int nextWindowID)
+{
+ if (m_Resolution != g_guiSettings.m_LookAndFeelResolution)
+ {
+ //FIXME: Use GUI resolution for now
+ //g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution, TRUE);
+ }
+
+ // Reset();
+ if (nextWindowID != WINDOW_PICTURES)
+ m_ImageLib.Unload();
+
+ g_windowManager.ShowOverlay(OVERLAY_STATE_SHOWN);
+
+ // wait for any outstanding picture loads
if (m_pBackgroundLoader)
{
// sleep until the loader finishes loading the current pic
@@ -205,6 +219,8 @@ void CGUIWindowSlideShow::FreeResources()
m_Image[0].Close();
m_Image[1].Close();
g_infoManager.ResetCurrentSlide();
+
+ CGUIWindow::OnDeinitWindow(nextWindowID);
}
void CGUIWindowSlideShow::Add(const CFileItem *picture)
@@ -722,23 +738,6 @@ bool CGUIWindowSlideShow::OnMessage(CGUIMessage& message)
{
switch ( message.GetMessage() )
{
- case GUI_MSG_WINDOW_DEINIT:
- {
- if (m_Resolution != g_guiSettings.m_LookAndFeelResolution)
- {
- /