From 3653727e7f84f10caefb6ea7dc33859455ebfa0b Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 10 Oct 2012 14:57:43 -0400 Subject: Introduce new LLDir::findSkinnedFilenames() method. Use as needed. In a number of different places, for different reasons, the viewer wants to load a UI-related file that might be overridden by a non-default skin; and within that skin, might further be overridden by a non-default language. Apparently, for each of those use cases, every individual developer approached it as an entirely new problem, solving it idiosyncratically for that one case. Not only is this a maintenance problem, but it rubs one's nose in the fact that most such solutions consider only a subset of the relevant skin directories. Richard and I evolved an API intended to address all such cases: a central LLDir method returning a list of relevant pathnames, from most general to most localized, filtered to present only existing files; plus a couple of convenience methods to specifically obtain the most general and most localized available file. There were several load-skinned-file methods (LLFloater::buildFromFile(), LLPanel::buildFromFile() and LLUICtrlFactory::createFromFile() -- apparently cloned-and-modified from each other) that contained funky bolted-on logic to output the loaded data to an optional passed LLXMLNodePtr param. The trouble is that passing that param forced each of these methods to subvert its normal search: specifically for that case, it needed to find the baseline XML file instead of the localized one. Richard agreed that for the intended usage (reformatting XML files) we should use XML schema instead, and that the hacky functionality should be removed. Remove it. Also remove LLUICtrlFactory::getLocalizedXMLNode(), only used for those three special cases. Some callers explicitly passed the optional LLXMLNodePtr param as NULL. Remove that. Remove LLFloaterUIPreview::displayFloater(save) param, which relied on the optional output LLXMLNodePtr param. Make onClickSaveFloater() and onClickSaveAll() emit popupAndPrintWarning() about discontinued functionality. Recast LLFloater::buildFromFile(), LLPanel::buildFromFile(), LLUICtrlFactory::createFromFile(), LLNotifications::loadTemplates(), LLUI::locateSkin(), LLFontRegistry::parseFontInfo(), LLUIColorTable::loadFromSettings(), LLUICtrlFactory::loadWidgetTemplate(), LLUICtrlFactory::getLayeredXMLNode(), LLUIImageList::initFromFile(), LLAppViewer::launchUpdater() and LLMediaCtrl::navigateToLocalPage() to use findSkinnedFilenames(). (Is LLAppViewer::launchUpdater() ever called any more? Apparently so -- though the linux-updater.bin logic to process the relevant command-line switch has been disabled. Shrug.) (Is LLMediaCtrl::navigateToLocalPage() ever used?? If so, why?) Remove LLUI::setupPaths(), getXUIPaths(), getSkinPath() and getLocalizedSkinPath(). Remove the skins/paths.xml file read by setupPaths(). The only configuration it contained was the pair of partial paths "xui/en" and "xui/[LANGUAGE]" -- hardly likely to change. getSkinPath() specifically returned the first of these, while getLocalizedSkinPath() specifically returned the second. This knowledge is now embedded in findSkinnedFilenames(). Also remove paths.xml from viewer_manifest.py. Remove injected xui_paths from LLFontGL::initClass() and LLFontRegistry::LLFontRegistry(). These are no longer needed since LLFontRegistry can now directly consult LLDir for its path search. Stop passing LLUI::getXUIPaths() to LLFontGL::initClass() in LLViewerWindow's constructor and initFonts() method. Add LLDir::append() and add() methods for the simple task of combining two path components separated by getDirDelimiter() -- but only if they're both non-empty. Amazing how often that logic is replicated. Replace some existing concatenations with add() or append(). New LLDir::findSkinnedFilenames() method must know current language. Allow injecting current language by adding an LLDir::setSkinFolder(language) param, and pass it where LLAppViewer::init() and initConfiguration() currently call setSkinFolder(). Also add LLDir::getSkinFolder() and getLanguage() methods. Change LLFLoaterUIPreview's LLLocalizationResetForcer helper to "forcibly reset language" using LLDir::setSkinFolder() instead of LLUI::setupPaths(). Update LLDir stubs in lldir_stub.cpp and llupdaterservice_test.cpp. Add LLDir::getUserDefaultSkinDir() to obtain often-overlooked possible skin directory -- like getUserSkinDir() but with "default" in place of the current skin name as the last path component. (However, we hope findSkinnedFilenames() obviates most explicit use of such individual skin directory pathnames.) Add LLDir unit tests for new findSkinnedFilenames() and add() methods -- the latter exercises append() as well. Tweak indra/integration_tests/llui_libtest/llui_libtest.cpp for all the above. Notably, comment out its export_test_floaters() function, since the essential LLFloater::buildFromFile(optional LLXMLNodePtr) functionality has been removed. This may mean that llui_libtest.cpp has little remaining value, not sure. --- indra/llui/llnotifications.cpp | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'indra/llui/llnotifications.cpp') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 629eef2c3b..4fbee8cd80 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1424,25 +1424,18 @@ void addPathIfExists(const std::string& new_path, std::vector& path bool LLNotifications::loadTemplates() { llinfos << "Reading notifications template" << llendl; - std::vector search_paths; - - std::string skin_relative_path = gDirUtilp->getDirDelimiter() + LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + "notifications.xml"; - std::string localized_skin_relative_path = gDirUtilp->getDirDelimiter() + LLUI::getLocalizedSkinPath() + gDirUtilp->getDirDelimiter() + "notifications.xml"; - - addPathIfExists(gDirUtilp->getDefaultSkinDir() + skin_relative_path, search_paths); - addPathIfExists(gDirUtilp->getDefaultSkinDir() + localized_skin_relative_path, search_paths); - addPathIfExists(gDirUtilp->getSkinDir() + skin_relative_path, search_paths); - addPathIfExists(gDirUtilp->getSkinDir() + localized_skin_relative_path, search_paths); - addPathIfExists(gDirUtilp->getUserSkinDir() + skin_relative_path, search_paths); - addPathIfExists(gDirUtilp->getUserSkinDir() + localized_skin_relative_path, search_paths); + // Passing findSkinnedFilenames(merge=true) makes it output all relevant + // pathnames instead of just the ones from the most specific skin. + std::vector search_paths = + gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", true); std::string base_filename = search_paths.front(); LLXMLNodePtr root; BOOL success = LLXMLNode::getLayeredXMLNode(root, search_paths); - + if (!success || root.isNull() || !root->hasName( "notifications" )) { - llerrs << "Problem reading UI Notifications file: " << base_filename << llendl; + llerrs << "Problem reading XML from UI Notifications file: " << base_filename << llendl; return false; } @@ -1452,7 +1445,7 @@ bool LLNotifications::loadTemplates() if(!params.validateBlock()) { - llerrs << "Problem reading UI Notifications file: " << base_filename << llendl; + llerrs << "Problem reading XUI from UI Notifications file: " << base_filename << llendl; return false; } @@ -1508,7 +1501,9 @@ bool LLNotifications::loadTemplates() bool LLNotifications::loadVisibilityRules() { const std::string xml_filename = "notification_visibility.xml"; - std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getXUIPaths().front(), xml_filename); + // Note that here we're looking for the "en" version, the default + // language, rather than the most localized version of this file. + std::string full_filename = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, xml_filename); LLNotificationVisibilityRule::Rules params; LLSimpleXUIParser parser; -- cgit v1.3 From 730d13a76a4b06e6dbdd4bd5829a90bcb98b52b3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 11 Oct 2012 19:51:07 -0400 Subject: Change LLDir::findSkinnedFilenames() to use enum instead of bool. At Richard's suggestion, changed the bool merge parameter to new enum ESkinConstraint with values CURRENT_SKIN and ALL_SKINS. This clarifies what we're requesting at the point of the call. --- indra/llui/llnotifications.cpp | 7 ++++--- indra/llui/lltransutil.cpp | 9 +++++---- indra/llui/lluicolortable.cpp | 5 +++-- indra/llvfs/lldir.cpp | 19 ++++++++++--------- indra/llvfs/lldir.h | 22 ++++++++++++---------- indra/llvfs/tests/lldir_test.cpp | 14 +++++++------- indra/newview/llviewertexturelist.cpp | 7 ++++--- 7 files changed, 45 insertions(+), 38 deletions(-) (limited to 'indra/llui/llnotifications.cpp') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 4fbee8cd80..210a320f41 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1424,10 +1424,11 @@ void addPathIfExists(const std::string& new_path, std::vector& path bool LLNotifications::loadTemplates() { llinfos << "Reading notifications template" << llendl; - // Passing findSkinnedFilenames(merge=true) makes it output all relevant - // pathnames instead of just the ones from the most specific skin. + // Passing findSkinnedFilenames(constraint=LLDir::ALL_SKINS) makes it + // output all relevant pathnames instead of just the ones from the most + // specific skin. std::vector search_paths = - gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", true); + gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", LLDir::ALL_SKINS); std::string base_filename = search_paths.front(); LLXMLNodePtr root; diff --git a/indra/llui/lltransutil.cpp b/indra/llui/lltransutil.cpp index 97a72b55e1..3b7e737dea 100644 --- a/indra/llui/lltransutil.cpp +++ b/indra/llui/lltransutil.cpp @@ -36,11 +36,12 @@ bool LLTransUtil::parseStrings(const std::string& xml_filename, const std::set& default_args) { // LLUICtrlFactory::getLayeredXMLNode() just calls - // gDirUtilp->findSkinnedFilenames(merge=false) and then passes the - // resulting paths to LLXMLNode::getLayeredXMLNode(). Bypass that and call - // LLXMLNode::getLayeredXMLNode() directly: we want merge=true. + // gDirUtilp->findSkinnedFilenames(constraint=LLDir::CURRENT_SKIN) and + // then passes the resulting paths to LLXMLNode::getLayeredXMLNode(). + // Bypass that and call LLXMLNode::getLayeredXMLNode() directly: we want + // constraint=LLDir::ALL_SKINS. std::vector paths = - gDirUtilp->findSkinnedFilenames(LLDir::XUI, xml_filename, true); + gDirUtilp->findSkinnedFilenames(LLDir::XUI, xml_filename, LLDir::ALL_SKINS); if (paths.empty()) { // xml_filename not found at all in any skin -- check whether entire diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp index 2717445396..ffeff15968 100644 --- a/indra/llui/lluicolortable.cpp +++ b/indra/llui/lluicolortable.cpp @@ -207,9 +207,10 @@ bool LLUIColorTable::loadFromSettings() { bool result = false; - // pass merge=true because we want colors.xml from every skin dir + // pass constraint=LLDir::ALL_SKINS because we want colors.xml from every + // skin dir BOOST_FOREACH(std::string colors_path, - gDirUtilp->findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", true)) + gDirUtilp->findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", LLDir::ALL_SKINS)) { result |= loadFromFilename(colors_path, mLoadedColors); } diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index a7d12476a4..2d0adf14e6 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -46,7 +46,6 @@ #include #include #include -#include #if LL_WINDOWS #include "lldir_win32.h" @@ -544,10 +543,10 @@ std::string LLDir::getExtension(const std::string& filepath) const std::string LLDir::findSkinnedFilenameBaseLang(const std::string &subdir, const std::string &filename, - bool merge) const + ESkinConstraint constraint) const { // This implementation is basically just as described in the declaration comments. - std::vector found(findSkinnedFilenames(subdir, filename, merge)); + std::vector found(findSkinnedFilenames(subdir, filename, constraint)); if (found.empty()) { return ""; @@ -557,10 +556,10 @@ std::string LLDir::findSkinnedFilenameBaseLang(const std::string &subdir, std::string LLDir::findSkinnedFilename(const std::string &subdir, const std::string &filename, - bool merge) const + ESkinConstraint constraint) const { // This implementation is basically just as described in the declaration comments. - std::vector found(findSkinnedFilenames(subdir, filename, merge)); + std::vector found(findSkinnedFilenames(subdir, filename, constraint)); if (found.empty()) { return ""; @@ -570,7 +569,7 @@ std::string LLDir::findSkinnedFilename(const std::string &subdir, std::vector LLDir::findSkinnedFilenames(const std::string& subdir, const std::string& filename, - bool merge) const + ESkinConstraint constraint) const { // Recognize subdirs that have no localization. static const char* sUnlocalizedData[] = @@ -582,7 +581,9 @@ std::vector LLDir::findSkinnedFilenames(const std::string& subdir, boost::end(sUnlocalizedData)); LL_DEBUGS("LLDir") << "subdir '" << subdir << "', filename '" << filename - << "', merge " << std::boolalpha << merge << LL_ENDL; + << "', constraint " + << ((constraint == CURRENT_SKIN)? "CURRENT_SKIN" : "ALL_SKINS") + << LL_ENDL; // Cache the default language directory for each subdir we've encountered. // A cache entry whose value is the empty string means "not localized, @@ -672,8 +673,8 @@ std::vector LLDir::findSkinnedFilenames(const std::string& subdir, // Here the desired filename exists in the first subsubdir. That means // this is a skindir we want to record in results. But if the caller - // passed merge=false, we must discard all previous skindirs. - if (! merge) + // passed constraint=CURRENT_SKIN, we must discard all previous skindirs. + if (constraint == CURRENT_SKIN) { results.clear(); } diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index a242802979..ffa2676838 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -119,6 +119,8 @@ class LLDir // these methods search the various skin paths for the specified file in the following order: // getUserSkinDir(), getUserDefaultSkinDir(), getSkinDir(), getDefaultSkinDir() + /// param value for findSkinnedFilenames(), explained below + enum ESkinConstraint { CURRENT_SKIN, ALL_SKINS }; /** * Given a filename within skin, return an ordered sequence of paths to * search. Nonexistent files will be filtered out -- which means that the @@ -130,25 +132,25 @@ class LLDir * level of skin subdirectory). * @param filename Desired filename within subdir within skin, e.g. * "panel_login.xml". DO NOT prepend (e.g.) "xui" or the desired language. - * @param merge Callers perform two different kinds of processing. When - * fetching a XUI file, for instance, the existence of @a filename in the - * specified skin completely supercedes any @a filename in the default - * skin. For that case, leave the default @a merge=false. The returned - * vector will contain only + * @param constraint Callers perform two different kinds of processing. + * When fetching a XUI file, for instance, the existence of @a filename in + * the specified skin completely supercedes any @a filename in the default + * skin. For that case, leave the default @a constraint=CURRENT_SKIN. The + * returned vector will contain only * ".../current_skin/xui/en/filename", * ".../current_skin/xui/current_language/filename". * But for (e.g.) "strings.xml", we want a given skin to be able to * override only specific entries from the default skin. Any string not * defined in the specified skin will be sought in the default skin. For - * that case, pass @a merge=true. The returned vector will contain at - * least ".../default/xui/en/strings.xml", + * that case, pass @a constraint=ALL_SKINS. The returned vector will + * contain at least ".../default/xui/en/strings.xml", * ".../default/xui/current_language/strings.xml", * ".../current_skin/xui/en/strings.xml", * ".../current_skin/xui/current_language/strings.xml". */ std::vector findSkinnedFilenames(const std::string& subdir, const std::string& filename, - bool merge=false) const; + ESkinConstraint constraint=CURRENT_SKIN) const; /// Values for findSkinnedFilenames(subdir) parameter static const char *XUI, *TEXTURES, *SKINBASE; /** @@ -160,7 +162,7 @@ class LLDir */ std::string findSkinnedFilenameBaseLang(const std::string &subdir, const std::string &filename, - bool merge=false) const; + ESkinConstraint constraint=CURRENT_SKIN) const; /** * Return the "most localized" pathname from findSkinnedFilenames(), or * the empty string if no such file exists. Parameters are identical to @@ -170,7 +172,7 @@ class LLDir */ std::string findSkinnedFilename(const std::string &subdir, const std::string &filename, - bool merge=false) const; + ESkinConstraint constraint=CURRENT_SKIN) const; // random filename in common temporary directory std::string getTempFilename() const; diff --git a/indra/llvfs/tests/lldir_test.cpp b/indra/llvfs/tests/lldir_test.cpp index a00fc8684c..15a5b6d4f3 100644 --- a/indra/llvfs/tests/lldir_test.cpp +++ b/indra/llvfs/tests/lldir_test.cpp @@ -584,7 +584,7 @@ namespace tut ensure_equals(lldir.getLanguage(), "en"); // top-level directory of a skin isn't localized - ensure_equals(lldir.findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", true), + ensure_equals(lldir.findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", LLDir::ALL_SKINS), vec(list_of("install/skins/default/colors.xml") ("user/skins/default/colors.xml"))); // We should not have needed to check for skins/default/en. We should @@ -599,13 +599,13 @@ namespace tut StringVec expected(vec(list_of("install/skins/default/xui/en/strings.xml") ("user/skins/default/xui/en/strings.xml"))); - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true), + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), expected); // The first time, we had to probe to find out whether xui was localized. lldir.ensure_checked("install/skins/default/xui/en"); lldir.clear_checked(); // Now make the same call again -- should return same result -- - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true), + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), expected); // but this time it should remember that xui is localized. lldir.ensure_not_checked("install/skins/default/xui/en"); @@ -648,7 +648,7 @@ namespace tut ensure_equals(lldir.getLanguage(), "fr"); // pass merge=true to request this filename in all relevant skins - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true), + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), vec(list_of ("install/skins/default/xui/en/strings.xml") ("install/skins/default/xui/fr/strings.xml") @@ -691,7 +691,7 @@ namespace tut /*------------------------- "steam", "en" --------------------------*/ lldir.setSkinFolder("steam", "en"); - ensure_equals(lldir.findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", true), + ensure_equals(lldir.findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", LLDir::ALL_SKINS), vec(list_of ("install/skins/default/colors.xml") ("install/skins/steam/colors.xml") @@ -715,7 +715,7 @@ namespace tut vec(list_of("user/skins/steam/xui/en/strings.xml"))); // pass merge=true to request this filename in all relevant skins - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true), + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), vec(list_of ("install/skins/default/xui/en/strings.xml") ("install/skins/steam/xui/en/strings.xml") @@ -732,7 +732,7 @@ namespace tut ("user/skins/steam/xui/fr/strings.xml"))); // pass merge=true to request this filename in all relevant skins - ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true), + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS), vec(list_of ("install/skins/default/xui/en/strings.xml") ("install/skins/default/xui/fr/strings.xml") diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 7eb1a202a0..edc43534dd 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -1583,10 +1583,11 @@ struct UIImageDeclarations : public LLInitParam::Block bool LLUIImageList::initFromFile() { - // Look for textures.xml in all the right places. Pass merge=true because - // we want to overlay textures.xml from all the skins directories. + // Look for textures.xml in all the right places. Pass + // constraint=LLDir::ALL_SKINS because we want to overlay textures.xml + // from all the skins directories. std::vector textures_paths = - gDirUtilp->findSkinnedFilenames(LLDir::TEXTURES, "textures.xml", true); + gDirUtilp->findSkinnedFilenames(LLDir::TEXTURES, "textures.xml", LLDir::ALL_SKINS); std::vector::const_iterator pi(textures_paths.begin()), pend(textures_paths.end()); if (pi == pend) { -- cgit v1.3