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 | |
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>
37 files changed, 1621 insertions, 443 deletions
diff --git a/cui/source/options/optgdlg.cxx b/cui/source/options/optgdlg.cxx index f93dc04f52f6..92fe1dfdcf08 100644 --- a/cui/source/options/optgdlg.cxx +++ b/cui/source/options/optgdlg.cxx @@ -85,6 +85,7 @@ #include <vcl/svapp.hxx> #include <vcl/settings.hxx> +#include <vcl/IconThemeInfo.hxx> #include "optgdlg.hxx" #include <svx/ofaitem.hxx> @@ -538,7 +539,6 @@ OfaViewTabPage::OfaViewTabPage(Window* pParent, const SfxItemSet& rSet) : SfxTabPage(pParent, "OptViewPage", "cui/ui/optviewpage.ui", rSet) , nSizeLB_InitialSelection(0) , nStyleLB_InitialSelection(0) - , aIconStyleItemId(STYLE_SYMBOLS_THEMES_MAX, 0) , pAppearanceCfg(new SvtTabAppearanceCfg) , pCanvasSettings(new CanvasSettings) , mpDrawinglayerOpt(new SvtOptionsDrawinglayer) @@ -593,50 +593,27 @@ OfaViewTabPage::OfaViewTabPage(Window* pParent, const SfxItemSet& rSet) m_pSystemFont->Enable(false); } - const StyleSettings& aStyleSettings = Application::GetSettings().GetStyleSettings(); + // Set known icon themes + m_pIconStyleLB->Clear(); + StyleSettings aStyleSettings = Application::GetSettings().GetStyleSettings(); + mInstalledIconThemes = aStyleSettings.GetInstalledIconThemes(); - // remove non-installed icon themes - if( m_pIconStyleLB->GetEntryCount() == STYLE_SYMBOLS_THEMES_MAX ) - { - // do not check 0th item == auto; it is not a real theme - aIconStyleItemId[0] = 0; - sal_uLong nItem = 1; - for ( sal_uLong n=0; ++n < STYLE_SYMBOLS_THEMES_MAX; ) - { - if ( aStyleSettings.CheckSymbolStyle( n ) ) - { - // existing style => save the item id - aIconStyleItemId[n] = nItem++; - } - else - { - // non-existing style => remove item; - m_pIconStyleLB->RemoveEntry( nItem ); - aIconStyleItemId[n] = 0; - } - } - } + // Start with the automatically chosen icon theme + OUString autoThemeId = aStyleSettings.GetAutomaticallyChosenIconTheme(); + const vcl::IconThemeInfo& autoIconTheme = vcl::IconThemeInfo::FindIconThemeById(mInstalledIconThemes, autoThemeId); - // add real theme name to 'auto' theme, e.g. 'auto' => 'auto (classic)' - if( m_pIconStyleLB->GetEntryCount() > 1 ) - { - OUString aAutoStr( m_pIconStyleLB->GetEntry( 0 ) ); + OUString entryForAuto = OUString("Auto (") + + autoIconTheme.GetDisplayName() + + OUString(")"); + m_pIconStyleLB->InsertEntry(entryForAuto); - aAutoStr += " ("; - - // prefer the icon style set by the desktop native widgets modules - sal_uLong nAutoStyle = aStyleSettings.GetPreferredSymbolsStyle(); - // fallback to the statically defined values - if ( nAutoStyle == STYLE_SYMBOLS_AUTO || !aIconStyleItemId.at(nAutoStyle) ) - nAutoStyle = aStyleSettings.GetAutoSymbolsStyle(); - if ( aIconStyleItemId.at(nAutoStyle) ) - aAutoStr += m_pIconStyleLB->GetEntry( aIconStyleItemId.at(nAutoStyle) ); - - m_pIconStyleLB->RemoveEntry( 0 ); - m_pIconStyleLB->InsertEntry( aAutoStr += ")", 0 ); - // separate auto and other icon themes - m_pIconStyleLB->SetSeparatorPos( 0 ); + for (const vcl::IconThemeInfo& i : mInstalledIconThemes) { + m_pIconStyleLB->InsertEntry(i.GetDisplayName()); } + + // separate auto and other icon themes + m_pIconStyleLB->SetSeparatorPos( 0 ); + m_pIconStyleLB->SelectEntryPos(0); } OfaViewTabPage::~OfaViewTabPage() @@ -703,16 +680,16 @@ sal_Bool OfaViewTabPage::FillItemSet( SfxItemSet& ) sal_uInt16 nStyleLB_NewSelection = m_pIconStyleLB->GetSelectEntryPos(); if( nStyleLB_InitialSelection != nStyleLB_NewSelection ) { - // find the style name in the aIconStyleItemId table - // items from the non-installed icon themes were removed - for ( sal_uLong n=0; n < STYLE_SYMBOLS_THEMES_MAX; n++ ) - { - if ( aIconStyleItemId[n] == nStyleLB_NewSelection ) - { - aMiscOptions.SetSymbolsStyle( n ); - n = STYLE_SYMBOLS_THEMES_MAX; - } + // 0 means choose style automatically + if (nStyleLB_NewSelection == 0) { + aMiscOptions.SetIconThemeAutomatically(); + } + else { + sal_uInt16 pos = m_pIconStyleLB->GetSelectEntryPos(); + const vcl::IconThemeInfo& iconThemeId = mInstalledIconThemes.at(pos-1); + aMiscOptions.SetIconTheme(iconThemeId.GetThemeId()); } + nStyleLB_InitialSelection = nStyleLB_NewSelection; } sal_Bool bAppearanceChanged = sal_False; @@ -880,8 +857,15 @@ void OfaViewTabPage::Reset( const SfxItemSet& ) m_pIconSizeLB->SelectEntryPos( nSizeLB_InitialSelection ); m_pIconSizeLB->SaveValue(); - if( aMiscOptions.GetSymbolsStyle() != STYLE_SYMBOLS_AUTO ) - nStyleLB_InitialSelection = aIconStyleItemId.at(aMiscOptions.GetCurrentSymbolsStyle()); + if (aMiscOptions.IconThemeWasSetAutomatically()) { + nStyleLB_InitialSelection = 0; + } + else { + const OUString& selected = aMiscOptions.GetIconTheme(); + const vcl::IconThemeInfo& selectedInfo = + vcl::IconThemeInfo::FindIconThemeById(mInstalledIconThemes, selected); + nStyleLB_InitialSelection = m_pIconStyleLB->GetEntryPos(selectedInfo.GetDisplayName()); + } m_pIconStyleLB->SelectEntryPos( nStyleLB_InitialSelection ); m_pIconStyleLB->SaveValue(); diff --git a/cui/source/options/optgdlg.hxx b/cui/source/options/optgdlg.hxx index 6f2f7c80fc99..79aaeaed8c8a 100644 --- a/cui/source/options/optgdlg.hxx +++ b/cui/source/options/optgdlg.hxx @@ -28,6 +28,9 @@ // predeclarations class CanvasSettings; class SvtOptionsDrawinglayer; +namespace vcl { +class IconThemeInfo; +} // class OfaMiscTabPage -------------------------------------------------- @@ -104,13 +107,12 @@ private: sal_uInt16 nSizeLB_InitialSelection; sal_uInt16 nStyleLB_InitialSelection; - // item ID for the given icon theme - // might be zero when the theme is not installed and the item is removed - std::vector<unsigned> aIconStyleItemId; SvtTabAppearanceCfg* pAppearanceCfg; CanvasSettings* pCanvasSettings; SvtOptionsDrawinglayer* mpDrawinglayerOpt; + std::vector<vcl::IconThemeInfo> mInstalledIconThemes; + #if defined( UNX ) DECL_LINK( OnAntialiasingToggled, void* ); #endif diff --git a/framework/inc/uielement/menubarmanager.hxx b/framework/inc/uielement/menubarmanager.hxx index ce61dda63f7c..88ef560c91fd 100644 --- a/framework/inc/uielement/menubarmanager.hxx +++ b/framework/inc/uielement/menubarmanager.hxx @@ -246,7 +246,7 @@ class MenuBarManager : public com::sun::star::frame::XStatusListener ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; ::com::sun::star::uno::Reference< ::com::sun::star::util::XURLTransformer > m_xURLTransformer; ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > m_xDeferedItemContainer; - sal_Int16 m_nSymbolsStyle; + OUString m_sIconTheme; Timer m_aAsyncSettingsTimer; }; diff --git a/framework/inc/uielement/toolbarmanager.hxx b/framework/inc/uielement/toolbarmanager.hxx index 7542b2950206..14462bba0648 100644 --- a/framework/inc/uielement/toolbarmanager.hxx +++ b/framework/inc/uielement/toolbarmanager.hxx @@ -210,7 +210,7 @@ class ToolBarManager : public ToolbarManager_Base, CommandToInfoMap m_aCommandMap; SubToolBarToSubToolBarControllerMap m_aSubToolBarControllerMap; Timer m_aAsyncUpdateControllersTimer; - sal_Int16 m_nSymbolsStyle; + OUString m_sIconTheme; MenuDescriptionMap m_aMenuMap; sal_Bool m_bAcceleratorCfg; ::com::sun::star::uno::Reference< ::com::sun::star::ui::XAcceleratorConfiguration > m_xDocAcceleratorManager; diff --git a/framework/source/uiconfiguration/imagemanagerimpl.cxx b/framework/source/uiconfiguration/imagemanagerimpl.cxx index 7cf71e82addf..b83766c41fb7 100644 --- a/framework/source/uiconfiguration/imagemanagerimpl.cxx +++ b/framework/source/uiconfiguration/imagemanagerimpl.cxx @@ -153,7 +153,7 @@ CmdImageList::CmdImageList( const uno::Reference< uno::XComponentContext >& rxCo m_bVectorInit( sal_False ), m_aModuleIdentifier( aModuleIdentifier ), m_xContext( rxContext ), - m_nSymbolsStyle( SvtMiscOptions().GetCurrentSymbolsStyle() ) + m_sIconTheme( SvtMiscOptions().GetIconTheme() ) { for ( sal_Int32 n=0; n < ImageType_COUNT; n++ ) m_pImageList[n] = 0; @@ -260,10 +260,10 @@ ImageList* CmdImageList::impl_getImageList( sal_Int16 nImageType ) { SvtMiscOptions aMiscOptions; - sal_Int16 nSymbolsStyle = aMiscOptions.GetCurrentSymbolsStyle(); - if ( nSymbolsStyle != m_nSymbolsStyle ) + const OUString& rIconTheme = aMiscOptions.GetIconTheme(); + if ( rIconTheme != m_sIconTheme ) { - m_nSymbolsStyle = nSymbolsStyle; + m_sIconTheme = rIconTheme; for ( sal_Int32 n=0; n < ImageType_COUNT; n++ ) delete m_pImageList[n], m_pImageList[n] = NULL; } @@ -647,6 +647,7 @@ sal_Bool ImageManagerImpl::implts_storeUserImages( return sal_False; } + const rtl::Reference< GlobalImageList >& ImageManagerImpl::implts_getGlobalImageList() { ResetableGuard aGuard( m_aLock ); diff --git a/framework/source/uiconfiguration/imagemanagerimpl.hxx b/framework/source/uiconfiguration/imagemanagerimpl.hxx index 2040dbea6222..b8888d2a0b8e 100644 --- a/framework/source/uiconfiguration/imagemanagerimpl.hxx +++ b/framework/source/uiconfiguration/imagemanagerimpl.hxx @@ -81,7 +81,7 @@ namespace framework ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; ::std::vector< OUString > m_aImageNameVector; ::std::vector< OUString > m_aImageCommandNameVector; - sal_Int16 m_nSymbolsStyle; + OUString m_sIconTheme; }; class GlobalImageList : public CmdImageList, public rtl::IReference diff --git a/framework/source/uielement/menubarmanager.cxx b/framework/source/uielement/menubarmanager.cxx index ec6e8469257e..aca7a24becaf 100644 --- a/framework/source/uielement/menubarmanager.cxx +++ b/framework/source/uielement/menubarmanager.cxx @@ -178,7 +178,7 @@ MenuBarManager::MenuBarManager( , m_aListenerContainer( m_aLock.getShareableOslMutex() ) , m_xContext(rxContext) , m_xURLTransformer(_xURLTransformer) - , m_nSymbolsStyle( SvtMiscOptions().GetCurrentSymbolsStyle() ) + , m_sIconTheme( SvtMiscOptions().GetIconTheme() ) { m_xPopupMenuControllerFactory = frame::thePopupMenuControllerFactory::get(m_xContext); FillMenuManager( pMenu, rFrame, rDispatchProvider, rModuleIdentifier, bDelete, bDeleteChildren ); @@ -200,7 +200,7 @@ MenuBarManager::MenuBarManager( , m_aListenerContainer( m_aLock.getShareableOslMutex() ) , m_xContext(rxContext) , m_xURLTransformer(_xURLTransformer) - , m_nSymbolsStyle( SvtMiscOptions().GetCurrentSymbolsStyle() ) + , m_sIconTheme( SvtMiscOptions().GetIconTheme() ) { Init(rFrame,pAddonMenu,bDelete,bDeleteChildren); } @@ -221,7 +221,7 @@ MenuBarManager::MenuBarManager( , m_aListenerContainer( m_aLock.getShareableOslMutex() ) , m_xContext(rxContext) , m_xURLTransformer(_xURLTransformer) - , m_nSymbolsStyle( SvtMiscOptions().GetCurrentSymbolsStyle() ) + , m_sIconTheme( SvtMiscOptions().GetIconTheme() ) { Init(rFrame,pAddonPopupMenu,bDelete,bDeleteChildren,true); } @@ -821,15 +821,15 @@ IMPL_LINK( MenuBarManager, Activate, Menu *, pMenu ) MenuManager::UpdateSpecialWindowMenu( pMenu, m_xContext, m_aLock ); // Check if some modes have changed so we have to update our menu images - sal_Int16 nSymbolsStyle = SvtMiscOptions().GetCurrentSymbolsStyle(); + OUString sIconTheme = SvtMiscOptions().GetIconTheme(); if ( m_bRetrieveImages || bShowMenuImages != m_bShowMenuImages || - nSymbolsStyle != m_nSymbolsStyle ) + sIconTheme != m_sIconTheme ) { m_bShowMenuImages = bShowMenuImages; m_bRetrieveImages = sal_False; - m_nSymbolsStyle = nSymbolsStyle; + m_sIconTheme = sIconTheme; MenuManager::FillMenuImages( m_xFrame, pMenu, bShowMenuImages ); } diff --git a/framework/source/uielement/toolbarmanager.cxx b/framework/source/uielement/toolbarmanager.cxx index cecbb66ab78e..a1afbab0d253 100644 --- a/framework/source/uielement/toolbarmanager.cxx +++ b/framework/source/uielement/toolbarmanager.cxx @@ -201,7 +201,7 @@ ToolBarManager::ToolBarManager( const Reference< XComponentContext >& rxContext, m_xFrame( rFrame ), m_aListenerContainer( m_aLock.getShareableOslMutex() ), m_xContext( rxContext ), - m_nSymbolsStyle( SvtMiscOptions().GetCurrentSymbolsStyle() ), + m_sIconTheme( SvtMiscOptions().GetIconTheme() ), m_bAcceleratorCfg( sal_False ) { OSL_ASSERT( m_xContext.is() ); @@ -318,15 +318,15 @@ void ToolBarManager::CheckAndUpdateImages() bool bCurrentSymbolsSmall = !aMiscOptions.AreCurrentSymbolsLarge(); if ( m_bSmallSymbols != bCurrentSymbolsSmall ) { - bRefreshImages = sal_True; + bRefreshImages = true; m_bSmallSymbols = bCurrentSymbolsSmall; } - sal_Int16 nCurrentSymbolsStyle = aMiscOptions.GetCurrentSymbolsStyle(); - if ( m_nSymbolsStyle != nCurrentSymbolsStyle ) + const OUString& sCurrentIconTheme = aMiscOptions.GetIconTheme(); + if ( m_sIconTheme != sCurrentIconTheme ) { - bRefreshImages = sal_True; - m_nSymbolsStyle = nCurrentSymbolsStyle; + bRefreshImages = true; + m_sIconTheme = sCurrentIconTheme; } // Refresh images if requested diff --git a/include/sfx2/mnuitem.hxx b/include/sfx2/mnuitem.hxx index 51d2c65d69d0..72f5c2f21b07 100644 --- a/include/sfx2/mnuitem.hxx +++ b/include/sfx2/mnuitem.hxx @@ -122,7 +122,7 @@ inline SfxVirtualMenu* SfxMenuControl::GetPopupMenu() const class SfxAppMenuControl_Impl : public SfxMenuControl { PopupMenu* pMenu; - sal_uIntPtr m_nSymbolsStyle; + OUString m_sIconTheme; sal_Bool m_bShowMenuImages; protected: diff --git a/include/svtools/miscopt.hxx b/include/svtools/miscopt.hxx index 5c5da5851b17..14ff1168bf29 100644 --- a/include/svtools/miscopt.hxx +++ b/include/svtools/miscopt.hxx @@ -86,9 +86,10 @@ class SVT_DLLPUBLIC SvtMiscOptions: public utl::detail::Options sal_Int16 GetCurrentSymbolsSize() const; bool AreCurrentSymbolsLarge() const; - sal_Int16 GetSymbolsStyle() const; - void SetSymbolsStyle( sal_Int16 eSet ); - sal_Int16 GetCurrentSymbolsStyle() const; + OUString GetIconTheme() const; + void SetIconTheme(const OUString&); + void SetIconThemeAutomatically(); + bool IconThemeWasSetAutomatically(); sal_Int16 GetToolboxStyle() const; void SetToolboxStyle( sal_Int16 nStyle ); diff --git a/include/vcl/IconThemeInfo.hxx b/include/vcl/IconThemeInfo.hxx new file mode 100644 index 000000000000..f745884e8cdc --- /dev/null +++ b/include/vcl/IconThemeInfo.hxx @@ -0,0 +1,97 @@ +/* -*- 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/. + */ + +#ifndef VCL_ICONTHEMEINFO_HXX_ +#define VCL_ICONTHEMEINFO_HXX_ + +#include <vcl/dllapi.h> +// for Size +#include <tools/gen.hxx> +#include <rtl/ustring.hxx> + +#include <vector> + +// forward declaration of unit test classes. Required for friend relationship. +class IconThemeInfoTest; +class IconThemeSelectorTest; +class IconThemeScannerTest; + +namespace vcl { + +/** This class provides information about an icon theme. + */ +class SAL_DLLPUBLIC_EXPORT IconThemeInfo { + +public: + + /** Construct an IconThemeInfo from the URL to a file. + * This method will throw a std::runtime_error if the URL cannot be properly parsed. + * Check the URL with UrlCanBeParsed() first. + */ + IconThemeInfo(const OUString& urlToFile); + + const OUString& GetDisplayName() const {return mDisplayName;} + + const OUString& GetThemeId() const { return mThemeId; } + + const OUString& GetUrlToFile() const { return mUrlToFile; } + + /** Obtain the icon size by theme name. + * @internal + * It is not clear where this information belongs to. The sizes were hard-coded before they moved here. + * Maybe there is a way to determine the sizes from the icon theme packages. + */ + static Size SizeByThemeName(const OUString&); + + /** Check whether a IconThemeInfo can be constructed from an URL */ + static bool UrlCanBeParsed(const OUString& url); + + /** Find an icon theme by its id in a vector. + * Throws a runtime_error if the theme is not contained in the vector + */ + static const vcl::IconThemeInfo& + FindIconThemeById(const std::vector<vcl::IconThemeInfo>& themes, const OUString& themeId); + + /** Check whether a theme with a specified id is in a vector of IconThemeInfo */ + static bool + IconThemeIsInVector(const std::vector<vcl::IconThemeInfo>& themes, const OUString& themeId); + +private: + /** private constructor for testing purposes only */ + IconThemeInfo(); + + /** Determine the icon theme name from the filename + * If the name has an underscore, the name is taken from the first underscore to the last dot, + * e.g., images_oxygen.zip becomes oxygen + * If the name does not have an underscore in it, the whole name until the last dot is returned, + * e.g. default.zip becomes default + */ + static OUString FileNameToThemeId(const OUString&); + + /** Creates the display name for the given id of a file. + * Currently, we only uppercase the id. + */ + static OUString ThemeIdToDisplayName(const OUString&); + + /** The name which is presented to the user */ + OUString mDisplayName; + /** The theme id. This id is used in ... to determine the file name */ + OUString mThemeId; + /** The url to the icon theme package */ + OUString mUrlToFile; + + friend class ::IconThemeInfoTest; + friend class ::IconThemeScannerTest; + friend class ::IconThemeSelectorTest; +}; + +} // namespace vcl + + +#endif /* VCL_ICONTHEMEINFO_HXX_ */ diff --git a/include/vcl/IconThemeScanner.hxx b/include/vcl/IconThemeScanner.hxx new file mode 100644 index 000000000000..3f6ad25a0a7a --- /dev/null +++ b/include/vcl/IconThemeScanner.hxx @@ -0,0 +1,103 @@ +/* -*- 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/. + */ + +#ifndef VCL_ICONTHEMESCANNER_HXX_ +#define VCL_ICONTHEMESCANNER_HXX_ + +#include <vcl/dllapi.h> +#include <tools/solar.h> + +#include <rtl/ustring.hxx> + +#include <boost/shared_ptr.hpp> +#include <vector> + +// forward declaration of unit test class. Required for friend relationship. +class IconThemeScannerTest; + +namespace osl { +class Directory; +class DirectoryItem; +} + +namespace vcl { +class IconThemeInfo; + +/** This class scans a folder for icon themes and provides the results. + */ +class SAL_DLLPUBLIC_EXPORT IconThemeScanner +{ +public: + ~IconThemeScanner(); + + /** Factory method to create the object. + * Provide a path to search for IconThemes. + */ + static boost::shared_ptr<IconThemeScanner> + Create(const OUString &path); + + /** This method will return the standard path where icon themes are located. + */ + static OUString + GetStandardIconThemePath(); + + const std::vector<IconThemeInfo>& + GetFoundIconThemes() const {return mFoundIconThemes;} + + /** Get the IconThemeInfo for a theme. + * If the theme id is not among the found themes, a std::runtime_error will be thrown. + * Use IconThemeIsInstalled() to check whether it is available. + */ + const IconThemeInfo& GetIconThemeInfo(const OUString& themeId); + + /** Checks whether the theme with the provided name has been found in the + * scanned directory. + */ + bool + IconThemeIsInstalled(const OUString& themeId) const; + +private: + IconThemeScanner(); + + /** Scan a directory for icon themes. + * + * @return + * This method will return true on success. + * There are several cases when this method will fail: + * - The directory does not exist + * - There are no files which which match the pattern images_xxx.zip + */ + bool + ScanDirectoryForIconThemes(const OUString &path); + + /** Adds the provided icon theme by path. + */ + bool + AddIconThemeByPath(const OUString &path); + + /** Scans the provided directory for icon themes. + * The returned strings will contain the URLs to the icon themes. + */ + static std::vector<OUString> + ReadIconThemesFromPath(const OUString& dir); + + /** Check whether a single file is valid */ + static bool + FileIsValidIconTheme(const OUString&); + + std::vector<IconThemeInfo> mFoundIconThemes; + + friend class ::IconThemeScannerTest; +}; + +} // end namespace vcl + +#endif /* VCL_ICONTHEMESCANNER_HXX_ */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/IconThemeSelector.hxx b/include/vcl/IconThemeSelector.hxx new file mode 100644 index 000000000000..35bde9e510f6 --- /dev/null +++ b/include/vcl/IconThemeSelector.hxx @@ -0,0 +1,101 @@ +/* -*- 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/. + */ + +#ifndef VCL_ICONTHEMESELECTOR_HXX_ +#define VCL_ICONTHEMESELECTOR_HXX_ + +#include <rtl/ustring.hxx> + +#include <vcl/dllapi.h> + +#include <vector> + +// forward declaration of unit test class. Required for friend relationship. +class IconThemeSelectorTest; + +namespace vcl { +struct IconThemeInfo; + +/** This class helps to choose an icon theme from a list of installed themes. + * + * The following factors influence the selection: + * -# When high contrast mode is enabled, the high contrast icon theme is selected (if it is installed). + * -# When a preferred theme has been set (e.g., in the gnome desktop settings), that theme is selected. + */ +class SAL_DLLPUBLIC_EXPORT IconThemeSelector { +public: + IconThemeSelector(); + + /** Select an icon theme from the list of installed themes. + * + * If high contrast mode has been enabled, the highcontrast theme will be selected (if it is available). + * + * @pre + * @p installedThemes must not be empty + */ + OUString + SelectIconTheme( + const std::vector<IconThemeInfo>& installedThemes, + const OUString& theme + ) const; + + /** Select the standard icon theme for a desktop environment from a list of installed themes. + * + * If a preferred theme has been set, this one will take precedence. + * + * The same logic as in SelectIconTheme() will apply. + * + * @pre + * @p installedThemes must not be empty + */ + OUString + SelectIconThemeForDesktopEnvironment( + const std::vector<IconThemeInfo>& installedThemes, + const OUString& desktopEnvironment) const; + + void + SetUseHighContrastTheme(bool); + + void + SetPreferredIconTheme(const OUString&); + + bool + operator==(const vcl::IconThemeSelector&) const; + + bool + operator!=(const vcl::IconThemeSelector&) const; + +private: + /** Return the first element of the themes, or the fallback if the vector is empty */ + static OUString + ReturnFallback(const std::vector<IconThemeInfo>& installedThemes); + + /** The name of the icon theme to use for high contrast mode */ + static const OUString + HIGH_CONTRAST_ICON_THEME_ID; + + /** The name of the icon theme which is used as fallback */ + static const OUString + FALLBACK_ICON_THEME_ID; + + + static OUString + GetIconThemeForDesktopEnvironment(const OUString& desktopEnvironment); + + OUString mPreferredIconTheme; + bool mUseHighContrastTheme; + + friend class ::IconThemeSelectorTest; +}; + +} /* namespace vcl */ + +#endif /* VCL_ICONTHEMESELECTOR_HXX_ */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/settings.hxx b/include/vcl/settings.hxx index 828c7a1105ff..ee50d38b1ae8 100644 --- a/include/vcl/settings.hxx +++ b/include/vcl/settings.hxx @@ -37,6 +37,9 @@ class LocaleDataWrapper; namespace vcl { class I18nHelper; + class IconThemeScanner; + class IconThemeSelector; + class IconThemeInfo; } // ----------------- @@ -248,6 +251,7 @@ public: private: void SetStandardStyles(); + Color maActiveBorderColor; Color maActiveColor; Color maActiveColor2; @@ -330,21 +334,25 @@ private: sal_uLong mnDisplayOptions; sal_uLong mnToolbarIconSize; bool mnUseFlatMenus; - sal_uLong mnOptions; - sal_uInt16 mnScreenZoom; - sal_uInt16 mnScreenFontZoom; - bool mnHighContrast; - bool mnUseSystemUIFonts; - sal_uInt16 mnAutoMnemonic; - AutoState mnUseImagesInMenus; + sal_uLong mnOptions; + sal_uInt16 mnScreenZoom; + sal_uInt16 mnScreenFontZoom; + bool mbHighContrast; + bool mbUseSystemUIFonts; + sal_uInt16 mnAutoMnemonic; + AutoState mnUseImagesInMenus; bool mnUseFlatBorders; - bool mbPreferredUseImagesInMenus; - long mnMinThumbSize; - sal_uLong mnSymbolsStyle; - sal_uLong mnPreferredSymbolsStyle; - bool mnSkipDisabledInMenus; - bool mbHideDisabledMenuItems; - bool mbAcceleratorsInContextMenus; + bool mbPreferredUseImagesInMenus; + long mnMinThumbSize; + boost::shared_ptr<vcl::IconThemeScanner> + mIconThemeScanner; + boost::shared_ptr<vcl::IconThemeSelector> + mIconThemeSelector; + + OUString mIconTheme; + bool mbSkipDisabledInMenus; + bool mbHideDisabledMenuItems; + bool mbAcceleratorsInContextMenus; //mbPrimaryButtonWarpsSlider == true for "jump to here" behavior for primary button, otherwise //primary means scroll by single page. Secondary button takes the alternative behaviour bool mbPrimaryButtonWarpsSlider; @@ -414,19 +422,6 @@ private: #define STYLE_TOOLBAR_ICONSIZE_SMALL ((sal_uLong)1) #define STYLE_TOOLBAR_ICONSIZE_LARGE ((sal_uLong)2) -#define STYLE_SYMBOLS_AUTO ((sal_uLong)0) -#define STYLE_SYMBOLS_DEFAULT ((sal_uLong)1) -#define STYLE_SYMBOLS_HICONTRAST ((sal_uLong)2) -#define STYLE_SYMBOLS_INDUSTRIAL ((sal_uLong)3) -#define STYLE_SYMBOLS_CRYSTAL ((sal_uLong)4) -#define STYLE_SYMBOLS_TANGO ((sal_uLong)5) -#define STYLE_SYMBOLS_OXYGEN ((sal_uLong)6) -#define STYLE_SYMBOLS_CLASSIC ((sal_uLong)7) -#define STYLE_SYMBOLS_HUMAN ((sal_uLong)8) -#define STYLE_SYMBOLS_SIFR ((sal_uLong)9) -#define STYLE_SYMBOLS_TANGO_TESTING ((sal_uLong)10) -#define STYLE_SYMBOLS_THEMES_MAX ((sal_uLong)11) - #define STYLE_CURSOR_NOBLINKTIME ((sal_uLong)0xFFFFFFFF) class VCL_DLLPUBLIC StyleSettings @@ -640,14 +635,13 @@ public: const Color& GetInactiveTabColor() const { return mpData->maInactiveTabColor; } - void SetHighContrastMode( bool bHighContrast ) - { CopyData(); mpData->mnHighContrast = bHighContrast; } - bool GetHighContrastMode() const - { return mpData->mnHighContrast; } + void SetHighContrastMode(bool bHighContrast ); + bool GetHighContrastMode() const; + void SetUseSystemUIFonts( bool bUseSystemUIFonts ) - { CopyData(); mpData->mnUseSystemUIFonts = bUseSystemUIFonts; } + { CopyData(); mpData->mbUseSystemUIFonts = bUseSystemUIFonts; } bool GetUseSystemUIFonts() const - { return mpData->mnUseSystemUIFonts; } + { return mpData->mbUseSystemUIFonts; } void SetUseFlatBorders( bool bUseFlatBorders ) { CopyData(); mpData->mnUseFlatBorders = bUseFlatBorders; } bool GetUseFlatBorders() const @@ -664,9 +658,9 @@ public: bool GetPreferredUseImagesInMenus() const { return mpData->mbPreferredUseImagesInMenus; } void SetSkipDisabledInMenus( bool bSkipDisabledInMenus ) - { CopyData(); mpData->mnSkipDisabledInMenus = bSkipDisabledInMenus; } + { CopyData(); mpData->mbSkipDisabledInMenus = bSkipDisabledInMenus; } bool GetSkipDisabledInMenus() const - { return mpData->mnSkipDisabledInMenus; } + { return mpData->mbSkipDisabledInMenus; } void SetHideDisabledMenuItems( bool bHideDisabledMenuItems ) { CopyData(); mpData->mbHideDisabledMenuItems = bHideDisabledMenuItems; } bool GetHideDisabledMenuItems() const @@ -850,28 +844,32 @@ public: sal_uLong GetToolbarIconSize() const { return mpData->mnToolbarIconSize; } - void SetSymbolsStyle( sal_uLong nStyle ) - { CopyData(); mpData->mnSymbolsStyle = nStyle; } - sal_uLong GetSymbolsStyle() const - { return mpData->mnSymbolsStyle; } - - void SetPreferredSymbolsStyle( sal_uLong nStyle ) - { CopyData(); mpData->mnPreferredSymbolsStyle = nStyle; } - void SetPreferredSymbolsStyleName( const OUString &rName ); - sal_uLong GetPreferredSymbolsStyle() const - { return mpData->mnPreferredSymbolsStyle; } - // check whether the symbols style is supported (icons are installed) - bool CheckSymbolStyle( sal_uLong nStyle ) const; - sal_uLong GetAutoSymbolsStyle() const; - - sal_uLong GetCurrentSymbolsStyle() const; - - void SetSymbolsStyleName( const OUString &rName ) - { return SetSymbolsStyle( ImplNameToSymbolsStyle( rName ) ); } - OUString GetSymbolsStyleName() const - { return ImplSymbolsStyleToName( GetSymbolsStyle() ); } - OUString GetCurrentSymbolsStyleName() const - { return ImplSymbolsStyleToName( GetCurrentSymbolsStyle() ); } + /** Set the icon theme to use. */ + void SetIconTheme(const OUString&); + + /** Determine which icon theme should be used. + * + * This might not be the same as the one which has been set with SetIconTheme(), + * e.g., if high contrast mode is enabled. + * + * (for the detailed logic @see vcl::IconThemeSelector) + */ + OUString DetermineIconTheme() const; + + /** Obtain the list of icon themes which were found in the config folder + * @see vcl::IconThemeScanner for more details. + */ + std::vector<vcl::IconThemeInfo> GetInstalledIconThemes() const; + + /** Obtain the name of the icon theme which will be chosen automatically for the desktop environment. + * This method will only return icon themes which were actually found on the system. + */ + OUString GetAutomaticallyChosenIconTheme() const; + + /** Set a preferred icon theme. + * This theme will be preferred in GetAutomaticallyChosenIconTheme() + */ + void SetPreferredIconTheme(const OUString&); const Wallpaper& GetWorkspaceGradient() const { return mpData->maWorkspaceGradient; } @@ -945,10 +943,6 @@ public: bool operator ==( const StyleSettings& rSet ) const; bool operator !=( const StyleSettings& rSet ) const { return !(*this == rSet); } - -protected: - OUString ImplSymbolsStyleToName( sal_uLong nStyle ) const; - sal_uLong ImplNameToSymbolsStyle( const OUString &rName ) const; }; // ---------------- diff --git a/include/vcl/toolbox.hxx b/include/vcl/toolbox.hxx index d595191c9d32..4ca253f9df0b 100644 --- a/include/vcl/toolbox.hxx +++ b/include/vcl/toolbox.hxx @@ -569,8 +569,8 @@ public: // if an index is found the corresponding item id is filled in (else 0) long GetIndexForPoint( const Point& rPoint, sal_uInt16& rItemID ) const; - static const Size& GetDefaultImageSize(bool bLarge); - const Size& GetDefaultImageSize() const; + static Size GetDefaultImageSize(bool bLarge); + Size GetDefaultImageSize() const; void ChangeHighlight( sal_uInt16 nPos ); void SetImageListProvider(vcl::IImageListProvider* _pProvider); diff --git a/sfx2/source/menu/mnuitem.cxx b/sfx2/source/menu/mnuitem.cxx index ad4432cbb248..dfae122b03ab 100644 --- a/sfx2/source/menu/mnuitem.cxx +++ b/sfx2/source/menu/mnuitem.cxx @@ -308,8 +308,8 @@ SfxAppMenuControl_Impl::SfxAppMenuControl_Impl( { // Determine the current background color setting for menus const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); - m_nSymbolsStyle = rSettings.GetSymbolsStyle(); - m_bShowMenuImages = rSettings.GetUseImagesInMenus(); + m_sIconTheme = rSettings.DetermineIconTheme(); + m_bShowMenuImages = rSettings.GetUseImagesInMenus(); ::framework::MenuConfiguration aConf( ::comphelper::getProcessComponentContext() ); Reference<com::sun::star::frame::XFrame> aXFrame( GetBindings().GetDispatcher_Impl()->GetFrame()->GetFrame().GetFrameInterface() ); @@ -332,14 +332,14 @@ IMPL_LINK( SfxAppMenuControl_Impl, Activate, Menu *, pActMenu ) if ( pActMenu ) { const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); - sal_uIntPtr nSymbolsStyle = rSettings.GetSymbolsStyle(); + OUString sIconTheme = rSettings.DetermineIconTheme(); sal_Bool bShowMenuImages = rSettings.GetUseImagesInMenus(); - if (( nSymbolsStyle != m_nSymbolsStyle ) || + if (( sIconTheme != m_sIconTheme ) || ( bShowMenuImages != m_bShowMenuImages )) { - m_nSymbolsStyle = nSymbolsStyle; - m_bShowMenuImages = bShowMenuImages; + m_sIconTheme = sIconTheme; + m_bShowMenuImages = bShowMenuImages; sal_uInt16 nCount = pActMenu->GetItemCount(); for ( sal_uInt16 nSVPos = 0; nSVPos < nCount; nSVPos++ ) @@ -350,7 +350,7 @@ IMPL_LINK( SfxAppMenuControl_Impl, Activate, Menu *, pActMenu ) if ( bShowMenuImages ) { sal_Bool bImageSet = sal_False; - ::rtl::OUString aImageId; + OUString aImageId; ::framework::MenuConfiguration::Attributes* pMenuAttributes = (::framework::MenuConfiguration::Attributes*)pMenu->GetUserValue( nItemId ); diff --git a/svtools/source/config/miscopt.cxx b/svtools/source/config/miscopt.cxx index 77ce11d48a74..0d3ac13806d9 100644 --- a/svtools/source/config/miscopt.cxx +++ b/svtools/source/config/miscopt.cxx @@ -51,7 +51,7 @@ using namespace ::com::sun::star; #define PROPERTYHANDLE_TOOLBOXSTYLE 2 #define PROPERTYNAME_USESYSTEMFILEDIALOG "UseSystemFileDialog" #define PROPERTYHANDLE_USESYSTEMFILEDIALOG 3 -#define PROPERTYNAME_SYMBOLSTYLE "SymbolStyle" +#define PROPERTYNAME_ICONTHEME "SymbolStyle" #define PROPERTYHANDLE_SYMBOLSTYLE 4 #define PROPERTYNAME_USESYSTEMPRINTDIALOG "UseSystemPrintDialog" #define PROPERTYHANDLE_USESYSTEMPRINTDIALOG 5 @@ -89,6 +89,7 @@ class SvtMiscOptions_Impl : public ConfigItem sal_Bool m_bAlwaysAllowSave; sal_Bool m_bExperimentalMode; sal_Bool m_bMacroRecorderMode; + sal_Bool m_bIconThemeWasSetAutomatically; public: @@ -180,15 +181,32 @@ class SvtMiscOptions_Impl : public ConfigItem inline sal_Bool IsGetSymbolsSizeReadOnly() { return m_bIsSymbolsSizeRO; } - sal_Int16 GetSymbolsStyle() const; - OUString GetSymbolsStyleName() const; - sal_Int16 GetCurrentSymbolsStyle() const; + OUString GetIconTheme() const; + + enum SetModifiedFlag { SET_MODIFIED, DONT_SET_MODIFIED }; + + /** Set the icon theme + * + * @param theme + * The name of the icon theme to use. + * + * @param setModified + * Whether to call SetModified() and CallListeners(). + * + * @internal + * The @p setModified flag was introduced because the unittests fail if we call SetModified() + * during initialization in the constructor. + */ + void + SetIconTheme(const OUString &theme, SetModifiedFlag setModified = SET_MODIFIED ); - inline void SetSymbolsStyle( sal_Int16 nSet ) - { ImplSetSymbolsStyle( true, nSet, OUString() ); } + bool IconThemeWasSetAutomatically() + {return m_bIconThemeWasSetAutomatically;} - inline void SetSymbolsStyleName( OUString &rName ) - { ImplSetSymbolsStyle( false, 0, rName ); } + /** Set the icon theme automatically by detecting the best theme for the desktop environment. + * The parameter setModified controls whether SetModified() will be called. + */ + void SetIconThemeAutomatically(SetModifiedFlag = SET_MODIFIED); inline sal_Bool IsGetSymbolsStyleReadOnly() { return m_bIsSymbolsStyleRO; } @@ -246,8 +264,9 @@ class SvtMiscOptions_Impl : public ConfigItem static Sequence< OUString > GetPropertyNames(); - protected: - void ImplSetSymbolsStyle( bool bValue, sal_Int16 nSet, const OUString &rName ); + private: + // The unittests fail if we call SetModified during initialization in the constructor. + void ImplSetSymbolsStyleWithoutSettingModifiedFlag( bool bValue, sal_Int16 nSet, const OUString &rName ); }; //***************************************************************************************************************** @@ -273,7 +292,7 @@ SvtMiscOptions_Impl::SvtMiscOptions_Impl() , m_bAlwaysAllowSave( sal_False ) , m_bExperimentalMode( sal_False ) , m_bMacroRecorderMode( sal_False ) - + , m_bIconThemeWasSetAutomatically( sal_False ) { // Use our static list of configuration keys to get his values. Sequence< OUString > seqNames = GetPropertyNames ( ); @@ -356,9 +375,15 @@ SvtMiscOptions_Impl::SvtMiscOptions_Impl() case PROPERTYHANDLE_SYMBOLSTYLE : { - OUString aSymbolsStyle; - if( seqValues[nProperty] >>= aSymbolsStyle ) - SetSymbolsStyleName( aSymbolsStyle ); + OUString aIconTheme; + if( seqValues[nProperty] >>= aIconTheme ) { + if (aIconTheme == "auto") { + SetIconThemeAutomatically(DONT_SET_MODIFIED); + } + else { + SetIconTheme(aIconTheme, DONT_SET_MODIFIED); + } + } else { OSL_FAIL("Wrong type of \"Misc\\SymbolStyle\"!" ); @@ -483,11 +508,16 @@ void SvtMiscOptions_Impl::Load( const Sequence< OUString >& rPropertyNames ) } break; case PROPERTYHANDLE_SYMBOLSTYLE : { - OUString aSymbolsStyle; - if( seqValues[nProperty] >>= aSymbolsStyle ) - SetSymbolsStyleName( aSymbolsStyle ); - else - { + OUString aIconTheme; + if( seqValues[nProperty] >>= aIconTheme ) { + if (aIconTheme == "auto") { + SetIconThemeAutomatically(DONT_SET_MODIFIED); + } + else { + SetIconTheme(aIconTheme, DONT_SET_MODIFIED); + } + } + else { OSL_FAIL("Wrong type of \"Misc\\SymbolStyle\"!" ); } } @@ -545,41 +575,27 @@ void SvtMiscOptions_Impl::SetSymbolsSize( sal_Int16 nSet ) CallListeners(); } -sal_Int16 SvtMiscOptions_Impl::GetSymbolsStyle() const +OUString SvtMiscOptions_Impl::GetIconTheme() const { - return (sal_Int16)Application::GetSettings().GetStyleSettings().GetSymbolsStyle(); + return Application::GetSettings().GetStyleSettings().DetermineIconTheme(); } -OUString SvtMiscOptions_Impl::GetSymbolsStyleName() const +void +SvtMiscOptions_Impl::SetIconTheme(const OUString &rName, SetModifiedFlag setModified) { - return Application::GetSettings().GetStyleSettings().GetSymbolsStyleName(); -} - -sal_Int16 SvtMiscOptions_Impl::GetCurrentSymbolsStyle() const -{ - return (sal_Int16)Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyle(); -} - -void SvtMiscOptions_Impl::ImplSetSymbolsStyle( bool bValue, sal_Int16 nSet, const OUString &rName ) -{ - if ( ( bValue && ( nSet != GetSymbolsStyle() ) ) || - ( !bValue && ( rName != GetSymbolsStyleName() ) ) ) - { - AllSettings aAllSettings = Application::GetSettings(); - StyleSettings aStyleSettings = aAllSettings.GetStyleSettings(); - - if ( bValue ) - aStyleSettings.SetSymbolsStyle( nSet ); - else - aStyleSettings.SetSymbolsStyleName( rName ); + AllSettings aAllSettings = Application::GetSettings(); + StyleSettings aStyleSettings = aAllSettings.GetStyleSettings(); + aStyleSettings.SetIconTheme( rName ); + m_bIconThemeWasSetAutomatically = false; - aAllSettings.SetStyleSettings(aStyleSettings); - Application::MergeSystemSettings( aAllSettings ); - Application::SetSettings(aAllSettings); + aAllSettings.SetStyleSettings(aStyleSettings); + Application::MergeSystemSettings( aAllSettings ); + Application::SetSettings(aAllSettings); + if (setModified == SET_MODIFIED) { SetModified(); - CallListeners(); } + CallListeners(); } //***************************************************************************************************************** @@ -634,8 +650,16 @@ void SvtMiscOptions_Impl::Commit() case PROPERTYHANDLE_SYMBOLSTYLE : { - if ( !m_bIsSymbolsStyleRO ) - seqValues[nProperty] <<= GetSymbolsStyleName(); + if ( !m_bIsSymbolsStyleRO ) { + OUString value; + if (m_bIconThemeWasSetAutomatically) { + value = "auto"; + } + else { + value = GetIconTheme(); + } + seqValues[nProperty] <<= value; + } break; } @@ -691,7 +715,7 @@ Sequence< OUString > SvtMiscOptions_Impl::GetPropertyNames() OUString(PROPERTYNAME_SYMBOLSET), OUString(PROPERTYNAME_TOOLBOXSTYLE), OUString(PROPERTYNAME_USESYSTEMFILEDIALOG), - OUString(PROPERTYNAME_SYMBOLSTYLE), + OUString(PROPERTYNAME_ICONTHEME), OUString(PROPERTYNAME_USESYSTEMPRINTDIALOG), OUString(PROPERTYNAME_SHOWLINKWARNINGDIALOG), OUString(PROPERTYNAME_DISABLEUICUSTOMIZATION), @@ -802,19 +826,14 @@ bool SvtMiscOptions::AreCurrentSymbolsLarge() const return ( GetCurrentSymbolsSize() == SFX_SYMBOLS_SIZE_LARGE ); } -sal_Int16 SvtMiscOptions::GetSymbolsStyle() const -{ - return m_pDataContainer->GetSymbolsStyle(); -} - -sal_Int16 SvtMiscOptions::GetCurrentSymbolsStyle() const +OUString SvtMiscOptions::GetIconTheme() const { - return m_pDataContainer->GetCurrentSymbolsStyle(); + return m_pDataContainer->GetIconTheme(); } -void SvtMiscOptions::SetSymbolsStyle( sal_Int16 nSet ) +void SvtMiscOptions::SetIconTheme(const OUString& iconTheme) { - m_pDataContainer->SetSymbolsStyle( nSet ); + m_pDataContainer->SetIconTheme(iconTheme); } sal_Bool SvtMiscOptions::DisableUICustomization() const @@ -908,4 +927,24 @@ void SvtMiscOptions::RemoveListenerLink( const Link& rLink ) m_pDataContainer->RemoveListenerLink( rLink ); } +void +SvtMiscOptions_Impl::SetIconThemeAutomatically(enum SetModifiedFlag setModified) +{ + OUString theme = Application::GetSettings().GetStyleSettings().GetAutomaticallyChosenIconTheme(); + SetIconTheme(theme, setModified); + m_bIconThemeWasSetAutomatically = true; +} + +void +SvtMiscOptions::SetIconThemeAutomatically() +{ + m_pDataContainer->SetIconThemeAutomatically(); +} + +bool +SvtMiscOptions::IconThemeWasSetAutomatically() +{ + return m_pDataContainer->IconThemeWasSetAutomatically(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svtools/source/misc/imagemgr.cxx b/svtools/source/misc/imagemgr.cxx index 82953df3c97a..767344f8d8b4 100644 --- a/svtools/source/misc/imagemgr.cxx +++ b/svtools/source/misc/imagemgr.cxx @@ -487,14 +487,15 @@ static Image GetImageFromList_Impl( sal_uInt16 nImageId, sal_Bool bBig ) static vcl::DeleteOnDeinit< ImageList > xSmallImageList( NULL ); static vcl::DeleteOnDeinit< ImageList > xBigImageList( NULL ); - static sal_uLong nStyle = Application::GetSettings().GetStyleSettings().GetSymbolsStyle(); + static OUString style = Application::GetSettings().GetStyleSettings().DetermineIconTheme(); // If the style has been changed, throw away our cache of the older images - if ( nStyle != Application::GetSettings().GetStyleSettings().GetSymbolsStyle() ) + OUString currentStyle = Application::GetSettings().GetStyleSettings().DetermineIconTheme(); + if ( style != currentStyle) { xSmallImageList.reset(); xBigImageList.reset(); - nStyle = Application::GetSettings().GetStyleSettings().GetSymbolsStyle(); + style = currentStyle; } if ( bBig ) 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 |