summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Lippert <drtl@fastmail.fm>2014-02-09 00:53:28 +0100
committerCaolán McNamara <caolanm@redhat.com>2014-02-21 17:23:50 +0000
commit076a7eacca48f203f0a8b9aa537e88fea9a88409 (patch)
treecd95446ac0b80b29658fa2a44030dacb5304a63d
parent1ec263e25d8606c70ac2089d5ceea22750d25daf (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>
-rw-r--r--cui/source/options/optgdlg.cxx88
-rw-r--r--cui/source/options/optgdlg.hxx8
-rw-r--r--framework/inc/uielement/menubarmanager.hxx2
-rw-r--r--framework/inc/uielement/toolbarmanager.hxx2
-rw-r--r--framework/source/uiconfiguration/imagemanagerimpl.cxx9
-rw-r--r--framework/source/uiconfiguration/imagemanagerimpl.hxx2
-rw-r--r--framework/source/uielement/menubarmanager.cxx12
-rw-r--r--framework/source/uielement/toolbarmanager.cxx12
-rw-r--r--include/sfx2/mnuitem.hxx2
-rw-r--r--include/svtools/miscopt.hxx7
-rw-r--r--include/vcl/IconThemeInfo.hxx97
-rw-r--r--include/vcl/IconThemeScanner.hxx103
-rw-r--r--include/vcl/IconThemeSelector.hxx101
-rw-r--r--include/vcl/settings.hxx116
-rw-r--r--include/vcl/toolbox.hxx4
-rw-r--r--sfx2/source/menu/mnuitem.cxx14
-rw-r--r--svtools/source/config/miscopt.cxx155
-rw-r--r--svtools/source/misc/imagemgr.cxx7
-rw-r--r--vcl/CppunitTest_vcl_app_test.mk30
-rw-r--r--vcl/Library_vcl.mk3
-rw-r--r--vcl/Module_vcl.mk1
-rw-r--r--vcl/inc/toolbox.h7
-rw-r--r--vcl/qa/cppunit/app/test_IconThemeInfo.cxx143
-rw-r--r--vcl/qa/cppunit/app/test_IconThemeScanner.cxx86
-rw-r--r--vcl/qa/cppunit/app/test_IconThemeSelector.cxx198
-rw-r--r--vcl/source/app/IconThemeInfo.cxx180
-rw-r--r--vcl/source/app/IconThemeScanner.cxx185
-rw-r--r--vcl/source/app/IconThemeSelector.cxx156
-rw-r--r--vcl/source/app/settings.cxx265
-rw-r--r--vcl/source/control/fixed.cxx8
-rw-r--r--vcl/source/gdi/bitmapex.cxx4
-rw-r--r--vcl/source/gdi/image.cxx4
-rw-r--r--vcl/source/gdi/imagerepository.cxx8
-rw-r--r--vcl/source/window/toolbox2.cxx40
-rw-r--r--vcl/source/window/window.cxx1
-rw-r--r--vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx2
-rw-r--r--vcl/unx/kde/salnativewidgets-kde.cxx2
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