diff options
author | Tobias Lippert <drtl@fastmail.fm> | 2014-02-09 00:53:28 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2014-02-21 17:23:50 +0000 |
commit | 076a7eacca48f203f0a8b9aa537e88fea9a88409 (patch) | |
tree | cd95446ac0b80b29658fa2a44030dacb5304a63d /vcl | |
parent | 1ec263e25d8606c70ac2089d5ceea22750d25daf (diff) |
Bug #63962 Dynamically scan the config directory for icon themes
The hard-coded icon themes have been replaced by a dynamic list
which is filled by scanning the config directory
Conflicts:
include/vcl/settings.hxx
vcl/source/app/settings.cxx
vcl/source/window/window.cxx
Change-Id: Ie3680ffe27d06e375acf22753e036cb6ddabc4ed
Reviewed-on: https://gerrit.libreoffice.org/7935
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/CppunitTest_vcl_app_test.mk | 30 | ||||
-rw-r--r-- | vcl/Library_vcl.mk | 3 | ||||
-rw-r--r-- | vcl/Module_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/inc/toolbox.h | 7 | ||||
-rw-r--r-- | vcl/qa/cppunit/app/test_IconThemeInfo.cxx | 143 | ||||
-rw-r--r-- | vcl/qa/cppunit/app/test_IconThemeScanner.cxx | 86 | ||||
-rw-r--r-- | vcl/qa/cppunit/app/test_IconThemeSelector.cxx | 198 | ||||
-rw-r--r-- | vcl/source/app/IconThemeInfo.cxx | 180 | ||||
-rw-r--r-- | vcl/source/app/IconThemeScanner.cxx | 185 | ||||
-rw-r--r-- | vcl/source/app/IconThemeSelector.cxx | 156 | ||||
-rw-r--r-- | vcl/source/app/settings.cxx | 265 | ||||
-rw-r--r-- | vcl/source/control/fixed.cxx | 8 | ||||
-rw-r--r-- | vcl/source/gdi/bitmapex.cxx | 4 | ||||
-rw-r--r-- | vcl/source/gdi/image.cxx | 4 | ||||
-rw-r--r-- | vcl/source/gdi/imagerepository.cxx | 8 | ||||
-rw-r--r-- | vcl/source/window/toolbox2.cxx | 40 | ||||
-rw-r--r-- | vcl/source/window/window.cxx | 1 | ||||
-rw-r--r-- | vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx | 2 | ||||
-rw-r--r-- | vcl/unx/kde/salnativewidgets-kde.cxx | 2 |
19 files changed, 1089 insertions, 234 deletions
diff --git a/vcl/CppunitTest_vcl_app_test.mk b/vcl/CppunitTest_vcl_app_test.mk new file mode 100644 index 000000000000..0aa3202abe32 --- /dev/null +++ b/vcl/CppunitTest_vcl_app_test.mk @@ -0,0 +1,30 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,vcl_app_test)) + +$(eval $(call gb_CppunitTest_add_exception_objects,vcl_app_test, \ + vcl/qa/cppunit/app/test_IconThemeInfo \ + vcl/qa/cppunit/app/test_IconThemeScanner \ + vcl/qa/cppunit/app/test_IconThemeSelector \ +)) + +# add a list of all needed libraries here +$(eval $(call gb_CppunitTest_use_libraries,vcl_app_test, \ +sal \ +vcl \ +$(gb_STDLIBS) \ +)) + +$(eval $(call gb_CppunitTest_set_include,vcl_app_test, \ +$$(INCLUDE) \ +-I$(OUTDIR)/inc \ + )) + +# vim: set noet sw=4 ts=4: diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 17258235a8e1..ff915330308f 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -112,6 +112,9 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/app/salvtables \ vcl/source/app/session \ vcl/source/app/settings \ + vcl/source/app/IconThemeInfo \ + vcl/source/app/IconThemeScanner \ + vcl/source/app/IconThemeSelector \ vcl/source/app/solarmutex \ vcl/source/app/sound \ vcl/source/app/stdtext \ diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk index 4dc64347ae63..1f3c8e2bde59 100644 --- a/vcl/Module_vcl.mk +++ b/vcl/Module_vcl.mk @@ -88,6 +88,7 @@ endif $(eval $(call gb_Module_add_check_targets,vcl,\ CppunitTest_vcl_complextext \ CppunitTest_vcl_filters_test \ + CppunitTest_vcl_app_test \ )) # vim: set noet sw=4 ts=4: diff --git a/vcl/inc/toolbox.h b/vcl/inc/toolbox.h index bfffe7bcffd6..cf89d02d9759 100644 --- a/vcl/inc/toolbox.h +++ b/vcl/inc/toolbox.h @@ -34,13 +34,6 @@ #define TB_MENUBUTTON_SIZE 12 #define TB_MENUBUTTON_OFFSET 2 -#define TB_SMALLIMAGESIZE 16 - -#define TB_LARGEIMAGESIZE 26 -#define TB_LARGEIMAGESIZE_INDUSTRIAL 24 -#define TB_LARGEIMAGESIZE_CRYSTAL 22 -#define TB_LARGEIMAGESIZE_OXYGEN 22 - class Window; struct ImplToolItem diff --git a/vcl/qa/cppunit/app/test_IconThemeInfo.cxx b/vcl/qa/cppunit/app/test_IconThemeInfo.cxx new file mode 100644 index 000000000000..e401046757ba --- /dev/null +++ b/vcl/qa/cppunit/app/test_IconThemeInfo.cxx @@ -0,0 +1,143 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/types.h> + +#include <rtl/ustring.hxx> +#include <vcl/IconThemeInfo.hxx> + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +using namespace vcl; + +class IconThemeInfoTest : public CppUnit::TestFixture +{ + void + UpperCaseDisplayNameIsReturnedForNonDefaultId(); + + void + ImagesZipIsNotValid(); + + void + ImagesOxygenZipIsValid(); + + void + DefaultZipIsValid(); + + void + ThemeIdIsDetectedFromFileNameWithUnderscore(); + + void + ExceptionIsThrownWhenIdCannotBeDetermined1(); + + void + ExceptionIsThrownWhenIdCannotBeDetermined2(); + + void + GalaxyIsReturnedAsDisplayNameForDefaultZip(); + + // Adds code needed to register the test suite + CPPUNIT_TEST_SUITE(IconThemeInfoTest); + CPPUNIT_TEST(UpperCaseDisplayNameIsReturnedForNonDefaultId); + CPPUNIT_TEST(ThemeIdIsDetectedFromFileNameWithUnderscore); + CPPUNIT_TEST(ImagesZipIsNotValid); + CPPUNIT_TEST(ImagesOxygenZipIsValid); + CPPUNIT_TEST(DefaultZipIsValid); + CPPUNIT_TEST(GalaxyIsReturnedAsDisplayNameForDefaultZip); + CPPUNIT_TEST(ExceptionIsThrownWhenIdCannotBeDetermined1); + CPPUNIT_TEST(ExceptionIsThrownWhenIdCannotBeDetermined2); + + // End of test suite definition + CPPUNIT_TEST_SUITE_END(); +}; + +void +IconThemeInfoTest::UpperCaseDisplayNameIsReturnedForNonDefaultId() +{ + OUString id("katze"); + OUString displayName = vcl::IconThemeInfo::ThemeIdToDisplayName(id); + CPPUNIT_ASSERT_EQUAL_MESSAGE("theme id is properly uppercased", OUString("Katze"), displayName); +} + +void +IconThemeInfoTest::ImagesZipIsNotValid() +{ + OUString id("file://images.zip"); + bool valid = vcl::IconThemeInfo::UrlCanBeParsed(id); + CPPUNIT_ASSERT_EQUAL_MESSAGE("images.zip is not a valid theme name", false, valid); +} + +void +IconThemeInfoTest::ImagesOxygenZipIsValid() +{ + OUString id("file://images_oxygen.zip"); + bool valid = vcl::IconThemeInfo::UrlCanBeParsed(id); + CPPUNIT_ASSERT_EQUAL_MESSAGE("images_oxygen.zip is a valid theme name", true, valid); +} + +void +IconThemeInfoTest::DefaultZipIsValid() +{ + OUString id("file://default.zip"); + bool valid = vcl::IconThemeInfo::UrlCanBeParsed(id); + CPPUNIT_ASSERT_EQUAL_MESSAGE("default.zip is a valid theme name", true, valid); +} + + +void +IconThemeInfoTest::ThemeIdIsDetectedFromFileNameWithUnderscore() +{ + OUString fname("images_oxygen.zip"); + OUString sname = vcl::IconThemeInfo::FileNameToThemeId(fname); + CPPUNIT_ASSERT_EQUAL_MESSAGE("'oxygen' theme id is returned for 'images_oxygen.zip'", OUString("oxygen"), sname); +} + +void +IconThemeInfoTest::ExceptionIsThrownWhenIdCannotBeDetermined1() +{ + bool thrown = false; + OUString fname("images_oxygen"); + try { + OUString sname = vcl::IconThemeInfo::FileNameToThemeId(fname); + } + catch (std::runtime_error&) { + thrown = true; + } + CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception was thrown",true, thrown); +} + +void +IconThemeInfoTest::ExceptionIsThrownWhenIdCannotBeDetermined2() +{ + bool thrown = false; + OUString fname("image_oxygen.zip"); + try { + OUString sname = vcl::IconThemeInfo::FileNameToThemeId(fname); + } + catch (std::runtime_error&) { + thrown = true; + } + CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception was thrown", true, thrown); +} + +void +IconThemeInfoTest::GalaxyIsReturnedAsDisplayNameForDefaultZip() +{ + OUString id("file://default.zip"); + IconThemeInfo i(id); + CPPUNIT_ASSERT_EQUAL_MESSAGE("default.zip is displayed as Galaxy", OUString("Galaxy"), i.GetDisplayName()); +} + +// Put the test suite in the registry +CPPUNIT_TEST_SUITE_REGISTRATION(IconThemeInfoTest); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/qa/cppunit/app/test_IconThemeScanner.cxx b/vcl/qa/cppunit/app/test_IconThemeScanner.cxx new file mode 100644 index 000000000000..af2e95703953 --- /dev/null +++ b/vcl/qa/cppunit/app/test_IconThemeScanner.cxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/types.h> + +#include <rtl/ustring.hxx> +#include <vcl/IconThemeScanner.hxx> +#include <vcl/IconThemeInfo.hxx> + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +class IconThemeScannerTest : public CppUnit::TestFixture +{ + void + AddedThemeIsFoundById(); + + void + AddedThemeInfoIsReturned(); + + void + ExceptionIsThrownIfInvalidInfoIsRequested(); + + // Adds code needed to register the test suite + CPPUNIT_TEST_SUITE(IconThemeScannerTest); + CPPUNIT_TEST(AddedThemeIsFoundById); + CPPUNIT_TEST(AddedThemeInfoIsReturned); + CPPUNIT_TEST(ExceptionIsThrownIfInvalidInfoIsRequested); + + // End of test suite definition + CPPUNIT_TEST_SUITE_END(); +}; + +void +IconThemeScannerTest::AddedThemeIsFoundById() +{ + vcl::IconThemeScanner scanner; + OUString theme("file:://images_katze.zip"); + scanner.AddIconThemeByPath(theme); + OUString id = vcl::IconThemeInfo::FileNameToThemeId("images_katze.zip"); + bool found = false; + found = scanner.IconThemeIsInstalled(id); + CPPUNIT_ASSERT_EQUAL_MESSAGE("icon theme could be added by url", true, found); +} + +void +IconThemeScannerTest::AddedThemeInfoIsReturned() +{ + vcl::IconThemeScanner scanner; + OUString theme("file:://images_katze.zip"); + scanner.AddIconThemeByPath(theme); + OUString id = vcl::IconThemeInfo::FileNameToThemeId("images_katze.zip"); + const vcl::IconThemeInfo& info = scanner.GetIconThemeInfo(id); + CPPUNIT_ASSERT_EQUAL_MESSAGE("'katze' icon theme is found from id", theme, info.GetUrlToFile()); +} + +void +IconThemeScannerTest::ExceptionIsThrownIfInvalidInfoIsRequested() +{ + vcl::IconThemeScanner scanner; + OUString theme("file:://images_katze.zip"); + scanner.AddIconThemeByPath(theme); + bool thrown = false; + try + { + scanner.GetIconThemeInfo("hund"); + } + catch (const std::runtime_error&) + { + thrown = true; + } + CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception is thrown if invalid theme info is requested", true, thrown); +} + +// Put the test suite in the registry +CPPUNIT_TEST_SUITE_REGISTRATION(IconThemeScannerTest); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/qa/cppunit/app/test_IconThemeSelector.cxx b/vcl/qa/cppunit/app/test_IconThemeSelector.cxx new file mode 100644 index 000000000000..34961e761dcc --- /dev/null +++ b/vcl/qa/cppunit/app/test_IconThemeSelector.cxx @@ -0,0 +1,198 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <vcl/IconThemeSelector.hxx> + +#include <vcl/IconThemeScanner.hxx> +#include <vcl/IconThemeInfo.hxx> + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +class IconThemeSelectorTest : public CppUnit::TestFixture +{ + void + OxygenThemeIsReturnedForKde4Desktop(); + + void + TangoThemeIsReturnedForGtkDesktop(); + + void + ThemeIsOverriddenByPreferredTheme(); + + void + ThemeIsOverriddenByHighContrastMode(); + + void + NotInstalledThemeDoesNotOverride(); + + void + InstalledThemeIsFound(); + + void + FirstThemeIsReturnedIfRequestedThemeIsNotFound(); + + void + FallbackThemeIsReturnedForEmptyInput(); + + void + DifferentPreferredThemesAreInequal(); + + void + DifferentHighContrastModesAreInequal(); + + static std::vector<vcl::IconThemeInfo> + GetFakeInstalledThemes(); + + // Adds code needed to register the test suite + CPPUNIT_TEST_SUITE(IconThemeSelectorTest); + + CPPUNIT_TEST(OxygenThemeIsReturnedForKde4Desktop); + CPPUNIT_TEST(TangoThemeIsReturnedForGtkDesktop); + CPPUNIT_TEST(ThemeIsOverriddenByPreferredTheme); + CPPUNIT_TEST(ThemeIsOverriddenByHighContrastMode); + CPPUNIT_TEST(NotInstalledThemeDoesNotOverride); + CPPUNIT_TEST(InstalledThemeIsFound); + CPPUNIT_TEST(FirstThemeIsReturnedIfRequestedThemeIsNotFound); + CPPUNIT_TEST(FallbackThemeIsReturnedForEmptyInput); + CPPUNIT_TEST(DifferentPreferredThemesAreInequal); + CPPUNIT_TEST(DifferentHighContrastModesAreInequal); + + // End of test suite definition + + + CPPUNIT_TEST_SUITE_END(); +}; + +/*static*/ std::vector<vcl::IconThemeInfo> +IconThemeSelectorTest::GetFakeInstalledThemes() +{ + std::vector<vcl::IconThemeInfo> r; + vcl::IconThemeInfo a{}; + a.mThemeId = "tango"; + r.push_back(a); + a.mThemeId = "oxygen"; + r.push_back(a); + a.mThemeId = vcl::IconThemeSelector::HIGH_CONTRAST_ICON_THEME_ID; + r.push_back(a); + return r; +} + +void +IconThemeSelectorTest::OxygenThemeIsReturnedForKde4Desktop() +{ + std::vector<vcl::IconThemeInfo> themes = GetFakeInstalledThemes(); + vcl::IconThemeSelector s; + OUString r = s.SelectIconThemeForDesktopEnvironment(themes, "kde4"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("'oxygen' theme is returned for kde4 desktop", OUString("oxygen"), r); +} + +void +IconThemeSelectorTest::TangoThemeIsReturnedForGtkDesktop() +{ + std::vector<vcl::IconThemeInfo> themes = GetFakeInstalledThemes(); + vcl::IconThemeSelector s; + OUString r = s.SelectIconThemeForDesktopEnvironment(themes, "gtk"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("'tango' theme is returned for kde4 desktop", OUString("tango"), r); +} + +void +IconThemeSelectorTest::ThemeIsOverriddenByPreferredTheme() +{ + vcl::IconThemeSelector s; + OUString preferred("oxygen"); + s.SetPreferredIconTheme(preferred); + std::vector<vcl::IconThemeInfo> themes = GetFakeInstalledThemes(); + OUString selected = s.SelectIconThemeForDesktopEnvironment(themes, "gtk"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("'tango' theme is overridden by oxygen", preferred, selected); +} + +void +IconThemeSelectorTest::ThemeIsOverriddenByHighContrastMode() +{ + vcl::IconThemeSelector s; + s.SetUseHighContrastTheme(true); + std::vector<vcl::IconThemeInfo> themes = GetFakeInstalledThemes(); + OUString selected = s.SelectIconTheme(themes, "tango"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("'tango' theme is overridden by high contrast mode", + vcl::IconThemeSelector::HIGH_CONTRAST_ICON_THEME_ID, selected); + s.SetUseHighContrastTheme(false); + selected = s.SelectIconTheme(themes, "tango"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("'tango' theme is no longer overridden by high contrast mode", + OUString("tango"), selected); +} + +void +IconThemeSelectorTest::NotInstalledThemeDoesNotOverride() +{ + vcl::IconThemeSelector s; + s.SetPreferredIconTheme("oxygen_katze"); + std::vector<vcl::IconThemeInfo> themes = GetFakeInstalledThemes(); + OUString selected = s.SelectIconTheme(themes, "oxygen"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("'oxygen' theme is not overridden by 'oxygen_katze'", OUString("oxygen"), selected); +} + +void +IconThemeSelectorTest::InstalledThemeIsFound() +{ + vcl::IconThemeSelector s; + std::vector<vcl::IconThemeInfo> themes = GetFakeInstalledThemes(); + OUString selected = s.SelectIconTheme(themes, "oxygen"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("'oxygen' theme is found", OUString("oxygen"), selected); +} + +void +IconThemeSelectorTest::FirstThemeIsReturnedIfRequestedThemeIsNotFound() +{ + vcl::IconThemeSelector s; + std::vector<vcl::IconThemeInfo> themes = GetFakeInstalledThemes(); + OUString selected = s.SelectIconTheme(themes, "oxygen_katze"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("'oxygen' theme is found", themes.front().GetThemeId(), selected); +} + +void +IconThemeSelectorTest::FallbackThemeIsReturnedForEmptyInput() +{ + vcl::IconThemeSelector s; + OUString selected = s.SelectIconTheme(std::vector<vcl::IconThemeInfo>{}, "oxygen"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("fallback is returned for empty input", + vcl::IconThemeSelector::FALLBACK_ICON_THEME_ID, selected); +} + +void +IconThemeSelectorTest::DifferentHighContrastModesAreInequal() +{ + vcl::IconThemeSelector s1; + vcl::IconThemeSelector s2; + s1.SetUseHighContrastTheme(true); + s2.SetUseHighContrastTheme(false); + bool equal = (s1 == s2); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Different high contrast modes are detected as inequal", false, equal); +} + +void +IconThemeSelectorTest::DifferentPreferredThemesAreInequal() +{ + vcl::IconThemeSelector s1; + vcl::IconThemeSelector s2; + s1.SetPreferredIconTheme("oxygen"); + s2.SetUseHighContrastTheme("katze"); + bool equal = (s1 == s2); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Different preferred themes are detected as inequal", false, equal); +} + + +// Put the test suite in the registry +CPPUNIT_TEST_SUITE_REGISTRATION(IconThemeSelectorTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/app/IconThemeInfo.cxx b/vcl/source/app/IconThemeInfo.cxx new file mode 100644 index 000000000000..69f0302b6909 --- /dev/null +++ b/vcl/source/app/IconThemeInfo.cxx @@ -0,0 +1,180 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <vcl/IconThemeInfo.hxx> +#include <rtl/character.hxx> + +#include <stdexcept> +#include <algorithm> + +namespace { + +OUString +filename_from_url(const OUString& url) +{ + sal_Int32 slashPosition = url.lastIndexOf( '/' ); + if (slashPosition < 0) { + return OUString(""); + } + OUString filename = url.copy( slashPosition+1 ); + return filename; +} + +} + +namespace vcl { + +static const char ICON_THEME_PACKAGE_PREFIX[] = "images_"; + +static const char EXTENSION_FOR_ICON_PACKAGES[] = ".zip"; + +IconThemeInfo::IconThemeInfo() +{ +} + +IconThemeInfo::IconThemeInfo(const OUString& urlToFile) +: mUrlToFile(urlToFile) +{ + OUString filename = filename_from_url(urlToFile); + if (filename.isEmpty()) { + throw std::runtime_error("invalid URL passed to IconThemeInfo()"); + } + + mThemeId = FileNameToThemeId(filename); + mDisplayName = ThemeIdToDisplayName(mThemeId); + +} + +/*static*/ Size +IconThemeInfo::SizeByThemeName(const OUString& themeName) +{ + if (themeName == "tango") { + return Size( 24, 24 ); + } + else if (themeName == "crystal") { + return Size( 22, 22 ); + } + else if (themeName == "default") { + return Size( 22, 22 ); + } + else { + return Size( 26, 26 ); + } +} + +/*static*/ bool +IconThemeInfo::UrlCanBeParsed(const OUString& url) +{ + OUString fname = filename_from_url(url); + if (fname.isEmpty()) { + return false; + } + + if (fname == "default.zip") { + return true; + } + + if (!fname.startsWithIgnoreAsciiCase(ICON_THEME_PACKAGE_PREFIX)) { + return false; + } + + if (!fname.endsWithIgnoreAsciiCase(EXTENSION_FOR_ICON_PACKAGES, nullptr)) { + return false; + } + + return true; +} + +/*static*/ OUString +IconThemeInfo::FileNameToThemeId(const OUString& filename) +{ + if (filename == "default.zip") { + return OUString("default"); + } + OUString r; + sal_Int32 positionOfLastDot = filename.lastIndexOf(EXTENSION_FOR_ICON_PACKAGES); + if (positionOfLastDot < 0) { // -1 means index not found + throw std::runtime_error("IconThemeInfo::FileNameToThemeId() called with invalid filename."); + } + sal_Int32 positionOfFirstUnderscore = filename.indexOf(ICON_THEME_PACKAGE_PREFIX); + if (positionOfFirstUnderscore < 0) { // -1 means index not found. Use the whole name instead + throw std::runtime_error("IconThemeInfo::FileNameToThemeId() called with invalid filename."); + } + positionOfFirstUnderscore += RTL_CONSTASCII_LENGTH(ICON_THEME_PACKAGE_PREFIX); + r = filename.copy(positionOfFirstUnderscore, positionOfLastDot - positionOfFirstUnderscore); + return r; +} + +/*static*/ OUString +IconThemeInfo::ThemeIdToDisplayName(const OUString& themeId) +{ + if (themeId.isEmpty()) { + throw std::runtime_error("IconThemeInfo::ThemeIdToDisplayName() called with invalid id."); + } + + if (themeId == "default") { + return OUString("Galaxy"); + } + + // make the first letter uppercase + OUString r; + sal_Unicode firstLetter = themeId[0]; + if (rtl::isAsciiLowerCase(firstLetter)) { + r = OUString(rtl::toAsciiUpperCase(firstLetter)); + r += themeId.copy(1); + } + else { + r = themeId; + } + return r; +} + +namespace +{ + class SameTheme : + public std::unary_function<const vcl::IconThemeInfo &, bool> + { + private: + const OUString& m_rThemeId; + public: + SameTheme(const OUString &rThemeId) : m_rThemeId(rThemeId) {} + bool operator()(const vcl::IconThemeInfo &rInfo) + { + return m_rThemeId == rInfo.GetThemeId(); + } + }; +} + +/*static*/ const vcl::IconThemeInfo& +IconThemeInfo::FindIconThemeById(const std::vector<vcl::IconThemeInfo>& themes, const OUString& themeId) +{ + std::vector<vcl::IconThemeInfo>::const_iterator it = std::find_if(themes.begin(), themes.end(), + SameTheme(themeId)); + if (it == themes.end()) + { + throw std::runtime_error("Could not find theme id in theme vector."); + } + return *it; +} + +/*static*/ bool +IconThemeInfo::IconThemeIsInVector(const std::vector<vcl::IconThemeInfo>& themes, const OUString& themeId) +{ + std::vector<vcl::IconThemeInfo>::const_iterator it = std::find_if(themes.begin(), themes.end(), + SameTheme(themeId)); + if (it != themes.end()) { + return true; + } + else { + return false; + } +} + +} // end namespace vcl + + diff --git a/vcl/source/app/IconThemeScanner.cxx b/vcl/source/app/IconThemeScanner.cxx new file mode 100644 index 000000000000..e6a6a130b92f --- /dev/null +++ b/vcl/source/app/IconThemeScanner.cxx @@ -0,0 +1,185 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <vcl/IconThemeScanner.hxx> + +#include <config_folders.h> +#include <osl/file.hxx> +#include <rtl/bootstrap.hxx> + +#include <vcl/svapp.hxx> +#include <vcl/IconThemeInfo.hxx> + +namespace vcl { + +namespace { + +bool +search_path_is_valid(const OUString& dir) +{ + osl::DirectoryItem dirItem; + osl::FileBase::RC retvalGet = osl::DirectoryItem::get(dir, dirItem); + if (retvalGet != osl::FileBase::RC::E_None) { + return false; + } + osl::FileStatus fileStatus(osl_FileStatus_Mask_Type); + osl::FileBase::RC retvalStatus = dirItem.getFileStatus(fileStatus); + if (retvalStatus != osl::FileBase::RC::E_None) { + return false; + } + + if (!fileStatus.isDirectory()) { + return false; + } + return true; +} + +} + +IconThemeScanner::IconThemeScanner() +{;} + +bool +IconThemeScanner::ScanDirectoryForIconThemes(const OUString& path) +{ + bool pathIsValid = search_path_is_valid(path); + if (!pathIsValid) { + return false; + } + std::vector<OUString> iconThemePaths = ReadIconThemesFromPath(path); + if (iconThemePaths.empty()) { + return false; + } + mFoundIconThemes.clear(); + for (const OUString& pathToTheme : iconThemePaths) { + AddIconThemeByPath(pathToTheme); + } + return true; +} + +bool +IconThemeScanner::AddIconThemeByPath(const OUString &url) +{ + if (!IconThemeInfo::UrlCanBeParsed(url)) { + return false; + } + IconThemeInfo newTheme{url}; + mFoundIconThemes.push_back(newTheme); + return true; +} + +/*static*/ std::vector<OUString> +IconThemeScanner::ReadIconThemesFromPath(const OUString& dir) +{ + std::vector<OUString> found; + + osl::Directory dirToScan(dir); + osl::FileBase::RC retvalOpen = dirToScan.open(); + if (retvalOpen != osl::FileBase::RC::E_None) { + return found; + } + + osl::DirectoryItem directoryItem; + while (dirToScan.getNextItem(directoryItem) == osl::FileBase::RC::E_None) { + osl::FileStatus status(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL | osl_FileStatus_Mask_FileName); + osl::FileBase::RC retvalStatus = directoryItem.getFileStatus(status); + if (retvalStatus != osl::FileBase::RC::E_None) { + continue; + } + if (!status.isRegular()) { + continue; + } + if (!FileIsValidIconTheme(status.getFileURL())) { + continue; + } + OUString entry; + entry = status.getFileURL(); + found.push_back(entry); + } + return found; +} + +/*static*/ bool +IconThemeScanner::FileIsValidIconTheme(const OUString& filename) +{ + // check whether we can construct a IconThemeInfo from it + if (!IconThemeInfo::UrlCanBeParsed(filename)) { + return false; + } + + // check whether the file is a regular file + osl::DirectoryItem dirItem; + osl::FileBase::RC retvalGet = osl::DirectoryItem::get(filename, dirItem); + if (retvalGet != osl::FileBase::RC::E_None) { + return false; + } + osl::FileStatus fileStatus(osl_FileStatus_Mask_Type); + osl::FileBase::RC retvalStatus = dirItem.getFileStatus(fileStatus); + if (retvalStatus != osl::FileBase::RC::E_None) { + return false; + } + if (!fileStatus.isRegular()) { + return false; + } + return true; +} + +bool +IconThemeScanner::IconThemeIsInstalled(const OUString& themeId) const +{ + return IconThemeInfo::IconThemeIsInVector(mFoundIconThemes, themeId); +} + +/*static*/ boost::shared_ptr<IconThemeScanner> +IconThemeScanner::Create(const OUString &path) +{ + boost::shared_ptr<IconThemeScanner> retval(new IconThemeScanner{}); + retval->ScanDirectoryForIconThemes(path); + return retval; +} + +/*static*/ OUString +IconThemeScanner::GetStandardIconThemePath() +{ + OUString url( "$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/config/" ); + rtl::Bootstrap::expandMacros(url); + return url; +} + +IconThemeScanner::~IconThemeScanner() +{;} + +namespace +{ + class SameTheme : + public std::unary_function<const vcl::IconThemeInfo &, bool> + { + private: + const OUString& m_rThemeId; + public: + SameTheme(const OUString &rThemeId) : m_rThemeId(rThemeId) {} + bool operator()(const vcl::IconThemeInfo &rInfo) + { + return m_rThemeId == rInfo.GetThemeId(); + } + }; +} + +const vcl::IconThemeInfo& +IconThemeScanner::GetIconThemeInfo(const OUString& themeId) +{ + std::vector<IconThemeInfo>::iterator info = std::find_if(mFoundIconThemes.begin(), mFoundIconThemes.end(), + SameTheme(themeId)); + if (info == mFoundIconThemes.end()) { + throw std::runtime_error("Requested information on not-installed icon theme"); + } + return *info; +} + + +} // end namespace vcl diff --git a/vcl/source/app/IconThemeSelector.cxx b/vcl/source/app/IconThemeSelector.cxx new file mode 100644 index 000000000000..023745bf9bcd --- /dev/null +++ b/vcl/source/app/IconThemeSelector.cxx @@ -0,0 +1,156 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <vcl/IconThemeSelector.hxx> + +#include <vcl/IconThemeScanner.hxx> +#include <vcl/IconThemeInfo.hxx> + +#include <algorithm> + +namespace vcl { + +/*static*/ const OUString +IconThemeSelector::HIGH_CONTRAST_ICON_THEME_ID("hicontrast"); + +/*static*/ const OUString +IconThemeSelector::FALLBACK_ICON_THEME_ID("tango"); + + +namespace { + + class SameTheme : + public std::unary_function<const vcl::IconThemeInfo &, bool> + { + private: + const OUString& m_rThemeId; + public: + SameTheme(const OUString &rThemeId) : m_rThemeId(rThemeId) {} + bool operator()(const vcl::IconThemeInfo &rInfo) + { + return m_rThemeId == rInfo.GetThemeId(); + } + }; + +bool icon_theme_is_in_installed_themes(const OUString& theme, + const std::vector<IconThemeInfo>& installedThemes) +{ + return std::find_if(installedThemes.begin(), installedThemes.end(), + SameTheme(theme) + ) != installedThemes.end(); +} + +} // end anonymous namespace + +IconThemeSelector::IconThemeSelector() +: mUseHighContrastTheme(false) +{ +} + +/*static*/ OUString +IconThemeSelector::GetIconThemeForDesktopEnvironment(const OUString& desktopEnvironment) +{ + OUString r; + if ( desktopEnvironment.equalsIgnoreAsciiCase("tde") || + desktopEnvironment.equalsIgnoreAsciiCase("kde") ) { + r = "crystal"; + } + else if ( desktopEnvironment.equalsIgnoreAsciiCase("kde4") ) { + r = "oxygen"; + } + else { + r = FALLBACK_ICON_THEME_ID; + } + return r; +} + +OUString +IconThemeSelector::SelectIconThemeForDesktopEnvironment( + const std::vector<IconThemeInfo>& installedThemes, + const OUString& desktopEnvironment) const +{ + if (!mPreferredIconTheme.isEmpty()) { + if (icon_theme_is_in_installed_themes(mPreferredIconTheme, installedThemes)) { + return mPreferredIconTheme; + } + } + + OUString themeForDesktop = GetIconThemeForDesktopEnvironment(desktopEnvironment); + if (icon_theme_is_in_installed_themes(themeForDesktop, installedThemes)) { + return themeForDesktop; + } + + return ReturnFallback(installedThemes); +} + +OUString +IconThemeSelector::SelectIconTheme( + const std::vector<IconThemeInfo>& installedThemes, + const OUString& theme) const +{ + if (mUseHighContrastTheme) { + if (icon_theme_is_in_installed_themes(HIGH_CONTRAST_ICON_THEME_ID, installedThemes)) { + return HIGH_CONTRAST_ICON_THEME_ID; + } + } + + if (icon_theme_is_in_installed_themes(theme, installedThemes)) { + return theme; + } + + return ReturnFallback(installedThemes); +} + +void +IconThemeSelector::SetUseHighContrastTheme(bool v) +{ + mUseHighContrastTheme = v; +} + +void +IconThemeSelector::SetPreferredIconTheme(const OUString& theme) +{ + mPreferredIconTheme = theme; +} + +bool +IconThemeSelector::operator==(const vcl::IconThemeSelector& other) const +{ + if (this == &other) { + return true; + } + if (mPreferredIconTheme != other.mPreferredIconTheme) { + return false; + } + if (mUseHighContrastTheme != other.mUseHighContrastTheme) { + return false; + } + return true; +} + +bool +IconThemeSelector::operator!=(const vcl::IconThemeSelector& other) const +{ + return !((*this) == other); +} + +/*static*/ OUString +IconThemeSelector::ReturnFallback(const std::vector<IconThemeInfo>& installedThemes) +{ + if (!installedThemes.empty()) { + return installedThemes.front().GetThemeId(); + } + else { + return FALLBACK_ICON_THEME_ID; + } +} + +} /* namespace vcl */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/app/settings.cxx b/vcl/source/app/settings.cxx index 97147478d3b0..c6c93dda5579 100644 --- a/vcl/source/app/settings.cxx +++ b/vcl/source/app/settings.cxx @@ -25,11 +25,14 @@ #include "comphelper/processfactory.hxx" #include <rtl/bootstrap.hxx> #include "tools/debug.hxx" -#include <vcl/graphicfilter.hxx> #include "i18nlangtag/mslangid.hxx" #include "i18nlangtag/languagetag.hxx" +#include <vcl/graphicfilter.hxx> +#include <vcl/IconThemeScanner.hxx> +#include <vcl/IconThemeSelector.hxx> +#include <vcl/IconThemeInfo.hxx> #include "vcl/svapp.hxx" #include "vcl/event.hxx" #include "vcl/settings.hxx" @@ -53,9 +56,6 @@ using namespace ::com::sun::star; // ======================================================================= - -// ======================================================================= - ImplMouseData::ImplMouseData() { mnOptions = 0; @@ -182,6 +182,8 @@ bool MouseSettings::operator ==( const MouseSettings& rSet ) const // ======================================================================= ImplStyleData::ImplStyleData() : + mIconThemeScanner(vcl::IconThemeScanner::Create(vcl::IconThemeScanner::GetStandardIconThemePath())), + mIconThemeSelector(new vcl::IconThemeSelector()), maPersonaHeaderFooter(), maPersonaHeaderBitmap(), maPersonaFooterBitmap() @@ -205,9 +207,7 @@ ImplStyleData::ImplStyleData() : mnOptions = 0; mnAutoMnemonic = 1; mnToolbarIconSize = STYLE_TOOLBAR_ICONSIZE_UNKNOWN; - mnSymbolsStyle = STYLE_SYMBOLS_AUTO; mnUseImagesInMenus = AUTO_STATE_AUTO; - mnPreferredSymbolsStyle = STYLE_SYMBOLS_AUTO; mpFontOptions = NULL; mnEdgeBlending = 35; maEdgeBlendingTopLeftColor = RGB_COLORDATA(0xC0, 0xC0, 0xC0); @@ -288,6 +288,7 @@ ImplStyleData::ImplStyleData( const ImplStyleData& rData ) : maFieldFont( rData.maFieldFont ), maIconFont( rData.maIconFont ), maGroupFont( rData.maGroupFont ), + mIconTheme(rData.mIconTheme), maWorkspaceGradient( rData.maWorkspaceGradient ), maDialogStyle( rData.maDialogStyle ), maFrameStyle( rData.maFrameStyle ), @@ -317,20 +318,20 @@ ImplStyleData::ImplStyleData( const ImplStyleData& rData ) : mnSelectionOptions = rData.mnSelectionOptions; mnDisplayOptions = rData.mnDisplayOptions; mnOptions = rData.mnOptions; - mnHighContrast = rData.mnHighContrast; - mnUseSystemUIFonts = rData.mnUseSystemUIFonts; + mbHighContrast = rData.mbHighContrast; + mbUseSystemUIFonts = rData.mbUseSystemUIFonts; mnUseFlatBorders = rData.mnUseFlatBorders; mnUseFlatMenus = rData.mnUseFlatMenus; mnAutoMnemonic = rData.mnAutoMnemonic; mnUseImagesInMenus = rData.mnUseImagesInMenus; mbPreferredUseImagesInMenus = rData.mbPreferredUseImagesInMenus; - mnSkipDisabledInMenus = rData.mnSkipDisabledInMenus; + mbSkipDisabledInMenus = rData.mbSkipDisabledInMenus; mbHideDisabledMenuItems = rData.mbHideDisabledMenuItems; mbAcceleratorsInContextMenus = rData.mbAcceleratorsInContextMenus; mbPrimaryButtonWarpsSlider = rData.mbPrimaryButtonWarpsSlider; mnToolbarIconSize = rData.mnToolbarIconSize; - mnSymbolsStyle = rData.mnSymbolsStyle; - mnPreferredSymbolsStyle = rData.mnPreferredSymbolsStyle; + mIconThemeScanner.reset(new vcl::IconThemeScanner(*rData.mIconThemeScanner)); + mIconThemeSelector.reset(new vcl::IconThemeSelector(*rData.mIconThemeSelector)); mpFontOptions = rData.mpFontOptions; mnEdgeBlending = rData.mnEdgeBlending; maEdgeBlendingTopLeftColor = rData.maEdgeBlendingTopLeftColor; @@ -422,12 +423,12 @@ void ImplStyleData::SetStandardStyles() mnFloatTitleHeight = 13; mnTearOffTitleHeight = 8; mnMenuBarHeight = 14; - mnHighContrast = false; - mnUseSystemUIFonts = true; + mbHighContrast = false; + mbUseSystemUIFonts = true; mnUseFlatBorders = false; mnUseFlatMenus = false; mbPreferredUseImagesInMenus = true; - mnSkipDisabledInMenus = false; + mbSkipDisabledInMenus = false; mbHideDisabledMenuItems = false; mbAcceleratorsInContextMenus = true; mbPrimaryButtonWarpsSlider = false; @@ -500,75 +501,6 @@ void StyleSettings::Set3DColors( const Color& rColor ) } } -// ----------------------------------------------------------------------- - -OUString StyleSettings::ImplSymbolsStyleToName( sal_uLong nStyle ) const -{ - switch ( nStyle ) - { - case STYLE_SYMBOLS_DEFAULT: return OUString("default"); - case STYLE_SYMBOLS_HICONTRAST: return OUString("hicontrast"); - case STYLE_SYMBOLS_INDUSTRIAL: return OUString("tango"); // industrial is dead - case STYLE_SYMBOLS_CRYSTAL: return OUString("crystal"); - case STYLE_SYMBOLS_TANGO: return OUString("tango"); - case STYLE_SYMBOLS_OXYGEN: return OUString("oxygen"); - case STYLE_SYMBOLS_CLASSIC: return OUString("classic"); - case STYLE_SYMBOLS_HUMAN: return OUString("human"); - case STYLE_SYMBOLS_SIFR: return OUString("sifr"); - case STYLE_SYMBOLS_TANGO_TESTING: return OUString("tango_testing"); - } - - return OUString("auto"); -} - -// ----------------------------------------------------------------------- - -sal_uLong StyleSettings::ImplNameToSymbolsStyle( const OUString &rName ) const -{ - if ( rName == "default" ) - return STYLE_SYMBOLS_DEFAULT; - else if ( rName == "hicontrast" ) - return STYLE_SYMBOLS_HICONTRAST; - else if ( rName == "industrial" ) - return STYLE_SYMBOLS_TANGO; // industrial is dead - else if ( rName == "crystal" ) - return STYLE_SYMBOLS_CRYSTAL; - else if ( rName == "tango" ) - return STYLE_SYMBOLS_TANGO; - else if ( rName == "oxygen" ) - return STYLE_SYMBOLS_OXYGEN; - else if ( rName == "classic" ) - return STYLE_SYMBOLS_CLASSIC; - else if ( rName == "human" ) - return STYLE_SYMBOLS_HUMAN; - else if ( rName == "sifr" ) - return STYLE_SYMBOLS_SIFR; - else if ( rName == "tango_testing" ) - return STYLE_SYMBOLS_TANGO_TESTING; - - return STYLE_SYMBOLS_AUTO; -} - -// ----------------------------------------------------------------------- - -/** - The preferred style name can be read from the desktop setting. We - need to find the closest theme name registered in OOo. Therefore - we check if any registered style name is a case-insensitive - substring of the preferred style name. -*/ -void StyleSettings::SetPreferredSymbolsStyleName( const OUString &rName ) -{ - if ( !rName.isEmpty() ) - { - OUString rNameLowCase( rName.toAsciiLowerCase() ); - - for( sal_uInt32 n = 0; n <= STYLE_SYMBOLS_THEMES_MAX; n++ ) - if ( rNameLowCase.indexOf( ImplSymbolsStyleToName( n ) ) != -1 ) - SetPreferredSymbolsStyle( n ); - } -} - void StyleSettings::SetCheckedColorSpecialCase( ) { CopyData(); @@ -584,99 +516,6 @@ void StyleSettings::SetCheckedColorSpecialCase( ) } } -// ----------------------------------------------------------------------- - -sal_uLong StyleSettings::GetCurrentSymbolsStyle() const -{ - // style selected in Tools -> Options... -> LibreOffice -> View - sal_uLong nStyle = GetSymbolsStyle(); - - if ( nStyle == STYLE_SYMBOLS_AUTO || ( !CheckSymbolStyle (nStyle) ) ) - { - // the preferred style can be read from the desktop setting by the desktop native widgets modules - sal_uLong nPreferredStyle = GetPreferredSymbolsStyle(); - - if ( nPreferredStyle == STYLE_SYMBOLS_AUTO || ( !CheckSymbolStyle (nPreferredStyle) ) ) - { - - // use a hardcoded desktop-specific fallback if no preferred style has been detected - static bool sbFallbackDesktopChecked = false; - static sal_uLong snFallbackDesktopStyle = STYLE_SYMBOLS_DEFAULT; - - if ( !sbFallbackDesktopChecked ) - { - snFallbackDesktopStyle = GetAutoSymbolsStyle(); - sbFallbackDesktopChecked = true; - } - - nPreferredStyle = snFallbackDesktopStyle; - } - - if (GetHighContrastMode() && CheckSymbolStyle (STYLE_SYMBOLS_HICONTRAST) ) - nStyle = STYLE_SYMBOLS_HICONTRAST; - else - nStyle = nPreferredStyle; - } - - return nStyle; -} - -// ----------------------------------------------------------------------- - -sal_uLong StyleSettings::GetAutoSymbolsStyle() const -{ - OUString const & env = Application::GetDesktopEnvironment(); - - sal_uLong nRet; - if ( env.equalsIgnoreAsciiCase("tde") || - env.equalsIgnoreAsciiCase("kde") ) - nRet = STYLE_SYMBOLS_CRYSTAL; - else if ( env.equalsIgnoreAsciiCase("kde4") ) - nRet = STYLE_SYMBOLS_OXYGEN; - else - nRet = STYLE_SYMBOLS_TANGO; - - // fallback to any existing style - if ( ! CheckSymbolStyle (nRet) ) - { - for ( sal_uLong n = 0 ; n <= STYLE_SYMBOLS_THEMES_MAX ; n++ ) - { - sal_uLong nStyleToCheck = n; - - // auto is not a real theme => can't be fallback - if ( nStyleToCheck == STYLE_SYMBOLS_AUTO ) - continue; - - // will check hicontrast in the end - if ( nStyleToCheck == STYLE_SYMBOLS_HICONTRAST ) - continue; - if ( nStyleToCheck == STYLE_SYMBOLS_THEMES_MAX ) - nStyleToCheck = STYLE_SYMBOLS_HICONTRAST; - - if ( CheckSymbolStyle ( nStyleToCheck ) ) - { - nRet = nStyleToCheck; - n = STYLE_SYMBOLS_THEMES_MAX; - } - } - } - - return nRet; -} - -// ----------------------------------------------------------------------- - -bool StyleSettings::CheckSymbolStyle( sal_uLong nStyle ) const -{ - if ( nStyle == STYLE_SYMBOLS_INDUSTRIAL ) - return false; // industrial is dead - - static ImplImageTreeSingletonRef aImageTree; - return aImageTree->checkStyle( ImplSymbolsStyleToName( nStyle ) ); -} - -// ----------------------------------------------------------------------- - bool StyleSettings::GetUseImagesInMenus() const { // icon mode selected in Tools -> Options... -> OpenOffice.org -> View @@ -841,6 +680,14 @@ bool StyleSettings::operator ==( const StyleSettings& rSet ) const if ( mpData == rSet.mpData ) return true; + if (mpData->mIconTheme != rSet.mpData->mIconTheme) { + return sal_False; + } + + if (*mpData->mIconThemeSelector != *rSet.mpData->mIconThemeSelector) { + return sal_False; + } + if ( (mpData->mnOptions == rSet.mpData->mnOptions) && (mpData->mnAutoMnemonic == rSet.mpData->mnAutoMnemonic) && (mpData->mnLogoDisplayTime == rSet.mpData->mnLogoDisplayTime) && @@ -864,12 +711,10 @@ bool StyleSettings::operator ==( const StyleSettings& rSet ) const (mpData->mnAntialiasedMin == rSet.mpData->mnAntialiasedMin) && (mpData->mnScreenZoom == rSet.mpData->mnScreenZoom) && (mpData->mnScreenFontZoom == rSet.mpData->mnScreenFontZoom) && - (mpData->mnHighContrast == rSet.mpData->mnHighContrast) && - (mpData->mnUseSystemUIFonts == rSet.mpData->mnUseSystemUIFonts) && + (mpData->mbHighContrast == rSet.mpData->mbHighContrast) && + (mpData->mbUseSystemUIFonts == rSet.mpData->mbUseSystemUIFonts) && (mpData->mnUseFlatBorders == rSet.mpData->mnUseFlatBorders) && (mpData->mnUseFlatMenus == rSet.mpData->mnUseFlatMenus) && - (mpData->mnSymbolsStyle == rSet.mpData->mnSymbolsStyle) && - (mpData->mnPreferredSymbolsStyle == rSet.mpData->mnPreferredSymbolsStyle) && (mpData->maFaceColor == rSet.mpData->maFaceColor) && (mpData->maCheckedColor == rSet.mpData->maCheckedColor) && (mpData->maLightColor == rSet.mpData->maLightColor) && @@ -931,7 +776,7 @@ bool StyleSettings::operator ==( const StyleSettings& rSet ) const (mpData->maIconFont == rSet.mpData->maIconFont) && (mpData->mnUseImagesInMenus == rSet.mpData->mnUseImagesInMenus) && (mpData->mbPreferredUseImagesInMenus == rSet.mpData->mbPreferredUseImagesInMenus) && - (mpData->mnSkipDisabledInMenus == rSet.mpData->mnSkipDisabledInMenus) && + (mpData->mbSkipDisabledInMenus == rSet.mpData->mbSkipDisabledInMenus) && (mpData->mbHideDisabledMenuItems == rSet.mpData->mbHideDisabledMenuItems) && (mpData->mbAcceleratorsInContextMenus == rSet.mpData->mbAcceleratorsInContextMenus)&& (mpData->mbPrimaryButtonWarpsSlider == rSet.mpData->mbPrimaryButtonWarpsSlider) && @@ -1635,4 +1480,62 @@ StyleSettings::GetOptions() const return mpData->mnOptions; } +std::vector<vcl::IconThemeInfo> +StyleSettings::GetInstalledIconThemes() const +{ + return mpData->mIconThemeScanner->GetFoundIconThemes(); +} + +/*static*/ OUString +StyleSettings::GetAutomaticallyChosenIconTheme() const +{ + OUString desktopEnvironment = Application::GetDesktopEnvironment(); + OUString themeName = mpData->mIconThemeSelector->SelectIconThemeForDesktopEnvironment( + mpData->mIconThemeScanner->GetFoundIconThemes(), + desktopEnvironment + ); + return themeName; +} + +void +StyleSettings::SetIconTheme(const OUString& theme) +{ + CopyData(); + mpData->mIconTheme = theme; +} + +OUString +StyleSettings::DetermineIconTheme() const +{ + OUString r = mpData->mIconThemeSelector->SelectIconTheme( + mpData->mIconThemeScanner->GetFoundIconThemes(), + mpData->mIconTheme + ); + return r; +} + +void +StyleSettings::SetHighContrastMode(bool bHighContrast ) +{ + if (mpData->mbHighContrast == bHighContrast) { + return; + } + + CopyData(); + mpData->mbHighContrast = bHighContrast; + mpData->mIconThemeSelector->SetUseHighContrastTheme(bHighContrast); +} + +bool +StyleSettings::GetHighContrastMode() const +{ + return mpData->mbHighContrast; +} + +void +StyleSettings::SetPreferredIconTheme(const OUString& theme) +{ + mpData->mIconThemeSelector->SetPreferredIconTheme(theme); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/control/fixed.cxx b/vcl/source/control/fixed.cxx index fe988dd0637c..695d3ae6b8e7 100644 --- a/vcl/source/control/fixed.cxx +++ b/vcl/source/control/fixed.cxx @@ -1210,13 +1210,13 @@ const Image& FixedImage::GetModeImage( ) const Image FixedImage::loadThemeImage(const OString &rFileName) { static ImplImageTreeSingletonRef aImageTree; - OUString sCurrentSymbolsStyle = - Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyleName(); + OUString sIconTheme = + Application::GetSettings().GetStyleSettings().DetermineIconTheme(); const OUString sFileName(OStringToOUString(rFileName, RTL_TEXTENCODING_UTF8)); BitmapEx aBitmap; - bool bSuccess = aImageTree->loadImage(sFileName, sCurrentSymbolsStyle, aBitmap, true); + bool bSuccess = aImageTree->loadImage(sFileName, sIconTheme, aBitmap, true); SAL_WARN_IF(!bSuccess, "vcl.layout", "Unable to load " << sFileName - << " from theme " << sCurrentSymbolsStyle); + << " from theme " << sIconTheme); return Image(aBitmap); } diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx index a8b287724478..0e9cd05d7abc 100644 --- a/vcl/source/gdi/bitmapex.cxx +++ b/vcl/source/gdi/bitmapex.cxx @@ -96,9 +96,9 @@ BitmapEx::BitmapEx( const ResId& rResId ) : pResMgr->ReadLong(); const OUString aFileName( pResMgr->ReadString() ); - OUString aCurrentSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyleName(); + OUString aIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme(); - if( !aImageTree->loadImage( aFileName, aCurrentSymbolsStyle, *this, true ) ) + if( !aImageTree->loadImage( aFileName, aIconTheme, *this, true ) ) { #ifdef DBG_UTIL OStringBuffer aErrorStr( diff --git a/vcl/source/gdi/image.cxx b/vcl/source/gdi/image.cxx index 8400942651a5..77dd01ee1fdb 100644 --- a/vcl/source/gdi/image.cxx +++ b/vcl/source/gdi/image.cxx @@ -379,7 +379,7 @@ void ImageAryData::Load(const OUString &rPrefix) { static ImplImageTreeSingletonRef aImageTree; - OUString aSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyleName(); + OUString aIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme(); BitmapEx aBmpEx; @@ -388,7 +388,7 @@ void ImageAryData::Load(const OUString &rPrefix) #if OSL_DEBUG_LEVEL > 0 bool bSuccess = #endif - aImageTree->loadImage( aFileName, aSymbolsStyle, maBitmapEx, true ); + aImageTree->loadImage( aFileName, aIconTheme, maBitmapEx, true ); #if OSL_DEBUG_LEVEL > 0 if ( !bSuccess ) { diff --git a/vcl/source/gdi/imagerepository.cxx b/vcl/source/gdi/imagerepository.cxx index 43ee86e58764..f83981ecd22e 100644 --- a/vcl/source/gdi/imagerepository.cxx +++ b/vcl/source/gdi/imagerepository.cxx @@ -28,17 +28,17 @@ namespace vcl { bool ImageRepository::loadImage( const OUString& _rName, BitmapEx& _out_rImage, bool _bSearchLanguageDependent, bool loadMissing ) { - OUString sCurrentSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyleName(); + OUString sIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme(); ImplImageTreeSingletonRef aImplImageTree; - return aImplImageTree->loadImage( _rName, sCurrentSymbolsStyle, _out_rImage, _bSearchLanguageDependent, loadMissing ); + return aImplImageTree->loadImage( _rName, sIconTheme, _out_rImage, _bSearchLanguageDependent, loadMissing ); } bool ImageRepository::loadDefaultImage( BitmapEx& _out_rImage) { - OUString sCurrentSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyleName(); + OUString sIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme(); ImplImageTreeSingletonRef aImplImageTree; - return aImplImageTree->loadDefaultImage( sCurrentSymbolsStyle,_out_rImage); + return aImplImageTree->loadDefaultImage( sIconTheme,_out_rImage); } } // namespace vcl diff --git a/vcl/source/window/toolbox2.cxx b/vcl/source/window/toolbox2.cxx index 9c5667a96209..72039beca9bc 100644 --- a/vcl/source/window/toolbox2.cxx +++ b/vcl/source/window/toolbox2.cxx @@ -32,6 +32,7 @@ #include <vcl/menu.hxx> #include <vcl/ImageListProvider.hxx> #include <vcl/settings.hxx> +#include <vcl/IconThemeInfo.hxx> #include <svdata.hxx> #include <brdwin.hxx> @@ -995,42 +996,19 @@ ToolBoxButtonSize ToolBox::GetToolboxButtonSize() const // ----------------------------------------------------------------------- -const Size& ToolBox::GetDefaultImageSize(bool bLarge) +/*static*/ Size +ToolBox::GetDefaultImageSize(bool bLarge) { - static Size aSmallButtonSize( TB_SMALLIMAGESIZE, TB_SMALLIMAGESIZE ); - - static sal_uLong s_nSymbolsStyle = STYLE_SYMBOLS_DEFAULT; - static Size aLargeButtonSize( TB_LARGEIMAGESIZE, TB_LARGEIMAGESIZE ); - - sal_uLong nSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyle(); - if ( s_nSymbolsStyle != nSymbolsStyle ) - { - s_nSymbolsStyle = nSymbolsStyle; - switch ( nSymbolsStyle ) - { - case STYLE_SYMBOLS_TANGO: - case STYLE_SYMBOLS_TANGO_TESTING: - case STYLE_SYMBOLS_HUMAN: - case STYLE_SYMBOLS_INDUSTRIAL: - aLargeButtonSize = Size( TB_LARGEIMAGESIZE_INDUSTRIAL, TB_LARGEIMAGESIZE_INDUSTRIAL ); - break; - case STYLE_SYMBOLS_CRYSTAL: - aLargeButtonSize = Size( TB_LARGEIMAGESIZE_CRYSTAL, TB_LARGEIMAGESIZE_CRYSTAL ); - break; - case STYLE_SYMBOLS_OXYGEN: - aLargeButtonSize = Size( TB_LARGEIMAGESIZE_OXYGEN, TB_LARGEIMAGESIZE_OXYGEN ); - break; - case STYLE_SYMBOLS_DEFAULT: // galaxy - case STYLE_SYMBOLS_HICONTRAST: - default: - aLargeButtonSize = Size( TB_LARGEIMAGESIZE, TB_LARGEIMAGESIZE ); - } + const long TB_SMALLIMAGESIZE = 16; + if (!bLarge) { + return Size(TB_SMALLIMAGESIZE, TB_SMALLIMAGESIZE); } - return bLarge ? aLargeButtonSize : aSmallButtonSize; + OUString iconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme(); + return vcl::IconThemeInfo::SizeByThemeName(iconTheme); } -const Size& ToolBox::GetDefaultImageSize() const +Size ToolBox::GetDefaultImageSize() const { return GetDefaultImageSize( GetToolboxButtonSize() == TOOLBOX_BUTTONSIZE_LARGE ); } diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index ed057f78fcd5..8a3f00645e13 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -661,7 +661,6 @@ void Window::ImplUpdateGlobalSettings( AllSettings& rSettings, bool bCallHdl ) { aStyleSettings = rSettings.GetStyleSettings(); aStyleSettings.SetHighContrastMode( true ); - aStyleSettings.SetSymbolsStyle( STYLE_SYMBOLS_HICONTRAST ); rSettings.SetStyleSettings( aStyleSettings ); } diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx index 6056a84e0f7a..4ae67fef72a2 100644 --- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx +++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx @@ -4082,7 +4082,7 @@ void GtkSalGraphics::updateSettings( AllSettings& rSettings ) // preferred icon style gchar* pIconThemeName = NULL; g_object_get( pSettings, "gtk-icon-theme-name", &pIconThemeName, (char *)NULL ); - aStyleSet.SetPreferredSymbolsStyleName( OUString::createFromAscii( pIconThemeName ) ); + aStyleSet.SetPreferredIconTheme( OUString::createFromAscii( pIconThemeName ) ); g_free( pIconThemeName ); aStyleSet.SetToolbarIconSize( STYLE_TOOLBAR_ICONSIZE_LARGE ); diff --git a/vcl/unx/kde/salnativewidgets-kde.cxx b/vcl/unx/kde/salnativewidgets-kde.cxx index 86096366d563..378930a3202b 100644 --- a/vcl/unx/kde/salnativewidgets-kde.cxx +++ b/vcl/unx/kde/salnativewidgets-kde.cxx @@ -1884,7 +1884,7 @@ void KDESalFrame::UpdateSettings( AllSettings& rSettings ) pKey = "Theme"; if ( pConfig->hasKey( pKey ) ) - aStyleSettings.SetPreferredSymbolsStyleName( readEntryUntranslated( pConfig, pKey ) ); + aStyleSettings.SetPreferredIconTheme( readEntryUntranslated( pConfig, pKey ) ); } // General settings |