1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "rtl/ustring.hxx"
25 #include "vcl/scrbar.hxx"
26 #include "vcl/fixed.hxx"
27 #include "vcl/dialog.hxx"
28 
29 #include "svtools/extensionlistbox.hxx"
30 #include "svtools/fixedhyper.hxx"
31 #include "cppuhelper/implbase1.hxx"
32 #include "unotools/collatorwrapper.hxx"
33 
34 #include "com/sun/star/lang/Locale.hpp"
35 #include "com/sun/star/lang/XEventListener.hpp"
36 #include "com/sun/star/deployment/XPackage.hpp"
37 
38 #include <boost/shared_ptr.hpp>
39 
40 namespace dp_gui {
41 
42 #define SMALL_ICON_SIZE     16
43 #define TOP_OFFSET           5
44 #define ICON_HEIGHT         42
45 #define ICON_WIDTH          47
46 #define ICON_OFFSET         72
47 #define RIGHT_ICON_OFFSET    5
48 #define SPACE_BETWEEN        3
49 
50 class TheExtensionManager;
51 
52 typedef ::boost::shared_ptr< svt::FixedHyperlink > TFixedHyperlink;
53 
54 //------------------------------------------------------------------------------
55 //                          struct Entry_Impl
56 //------------------------------------------------------------------------------
57 struct Entry_Impl;
58 
59 typedef ::boost::shared_ptr< Entry_Impl > TEntry_Impl;
60 
61 struct Entry_Impl
62 {
63     bool            m_bActive       :1;
64     bool            m_bLocked       :1;
65     bool            m_bHasOptions   :1;
66     bool            m_bUser         :1;
67     bool            m_bShared       :1;
68     bool            m_bNew          :1;
69     bool            m_bChecked      :1;
70     bool            m_bMissingDeps  :1;
71     bool            m_bHasButtons   :1;
72     bool            m_bMissingLic   :1;
73     PackageState    m_eState;
74     String          m_sTitle;
75     String          m_sVersion;
76     String          m_sDescription;
77     String          m_sPublisher;
78     String          m_sPublisherURL;
79     String          m_sErrorText;
80     String          m_sLicenseText;
81     Image           m_aIcon;
82     Image           m_aIconHC;
83     svt::FixedHyperlink *m_pPublisher;
84 
85     ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> m_xPackage;
86 
87     Entry_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage,
88                 const PackageState eState, const bool bReadOnly );
89    ~Entry_Impl();
90 
91     StringCompare CompareTo( const CollatorWrapper *pCollator, const TEntry_Impl pEntry ) const;
92     void          checkDependencies();
93 };
94 
95 //------------------------------------------------------------------------------
96 //                          class ExtensionBox_Impl
97 //------------------------------------------------------------------------------
98 
99 class ExtensionBox_Impl;
100 
101 //------------------------------------------------------------------------------
102 class ExtensionRemovedListener : public ::cppu::WeakImplHelper1< ::com::sun::star::lang::XEventListener >
103 {
104     ExtensionBox_Impl   *m_pParent;
105 
106 public:
107 
ExtensionRemovedListener(ExtensionBox_Impl * pParent)108     ExtensionRemovedListener( ExtensionBox_Impl *pParent ) { m_pParent = pParent; }
109    ~ExtensionRemovedListener();
110 
111     //===================================================================================
112     // XEventListener
113     virtual void SAL_CALL disposing( ::com::sun::star::lang::EventObject const & evt )
114         throw (::com::sun::star::uno::RuntimeException);
115 };
116 
117 //------------------------------------------------------------------------------
118 class ExtensionBox_Impl : public ::svt::IExtensionListBox
119 {
120     bool            m_bHasScrollBar;
121     bool            m_bHasActive;
122     bool            m_bNeedsRecalc;
123     bool            m_bHasNew;
124     bool            m_bInCheckMode;
125     bool            m_bAdjustActive;
126     bool            m_bInDelete;
127     //Must be guarded together with m_vEntries to ensure a valid index at all times.
128     //Use m_entriesMutex as guard.
129     long            m_nActive;
130     long            m_nTopIndex;
131     long            m_nStdHeight;
132     long            m_nActiveHeight;
133     long            m_nExtraHeight;
134     Size            m_aOutputSize;
135     Image           m_aSharedImage;
136     Image           m_aSharedImageHC;
137     Image           m_aLockedImage;
138     Image           m_aLockedImageHC;
139     Image           m_aWarningImage;
140     Image           m_aWarningImageHC;
141     Image           m_aDefaultImage;
142     Image           m_aDefaultImageHC;
143     Link            m_aClickHdl;
144 
145     ScrollBar      *m_pScrollBar;
146 
147     com::sun::star::uno::Reference< ExtensionRemovedListener > m_xRemoveListener;
148 
149     TheExtensionManager      *m_pManager;
150     //This mutex is used for synchronizing access to m_vEntries.
151     //Currently it is used to synchronize adding, removing entries and
152     //functions like getItemName, getItemDescription, etc. to prevent
153     //that m_vEntries is accessed at an invalid index.
154     //ToDo: There are many more places where m_vEntries is read and which may
155     //fail. For example the Paint method is probable called from the main thread
156     //while new entries are added / removed in a separate thread.
157     mutable ::osl::Mutex    m_entriesMutex;
158     std::vector< TEntry_Impl > m_vEntries;
159     std::vector< TEntry_Impl > m_vRemovedEntries;
160 
161 	::com::sun::star::lang::Locale    *m_pLocale;
162 	CollatorWrapper *m_pCollator;
163 
164     //Holds weak references to extensions to which is we have added an XEventListener
165     std::vector< ::com::sun::star::uno::WeakReference<
166         ::com::sun::star::deployment::XPackage> > m_vListenerAdded;
167     //Removes the dead weak references from m_vListenerAdded
168     void cleanVecListenerAdded();
169     void addEventListenerOnce( ::com::sun::star::uno::Reference<
170                                ::com::sun::star::deployment::XPackage> const & extension);
171 
172     void            CalcActiveHeight( const long nPos );
173     long            GetTotalHeight() const;
174     void            SetupScrollBar();
175     void            DrawRow( const Rectangle& rRect, const TEntry_Impl pEntry );
176     bool            HandleTabKey( bool bReverse );
177     bool            HandleCursorKey( sal_uInt16 nKeyCode );
178     bool            FindEntryPos( const TEntry_Impl pEntry, long nStart, long nEnd, long &nFound );
179     bool            isHCMode();
180     void            DeleteRemoved();
181 
182     //-----------------
183     DECL_DLLPRIVATE_LINK( ScrollHdl, ScrollBar * );
184 
185     //Index starts with 1.
186     //Throws an com::sun::star::lang::IllegalArgumentException, when the index is invalid.
187     void checkIndex(sal_Int32 pos) const;
188 
189 
190 public:
191                     ExtensionBox_Impl( Dialog* pParent, TheExtensionManager *pManager );
192                    ~ExtensionBox_Impl();
193 
194     virtual void    MouseButtonDown( const MouseEvent& rMEvt );
195     virtual void    Paint( const Rectangle &rPaintRect );
196     virtual void    Resize();
197     virtual long    Notify( NotifyEvent& rNEvt );
198 
199     const Size      GetMinOutputSizePixel() const;
SetExtraSize(long nSize)200     void            SetExtraSize( long nSize ) { m_nExtraHeight = nSize; }
GetEntryData(long nPos)201     TEntry_Impl     GetEntryData( long nPos ) { return m_vEntries[ nPos ]; }
GetEntryCount()202     long            GetEntryCount() { return (long) m_vEntries.size(); }
203     Rectangle       GetEntryRect( const long nPos ) const;
HasActive()204     bool            HasActive() { return m_bHasActive; }
205     long            PointToPos( const Point& rPos );
206     void            SetScrollHdl( const Link& rLink );
207     void            DoScroll( long nDelta );
SetHyperlinkHdl(const Link & rLink)208     void            SetHyperlinkHdl( const Link& rLink ){ m_aClickHdl = rLink; }
209     virtual void    RecalcAll();
210     void            RemoveUnlocked();
211 
212     //-----------------
213     virtual void    selectEntry( const long nPos );
214     long            addEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage,
215                               bool bLicenseMissing = false );
216     void            updateEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage );
217     void            removeEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage );
218 
219     void            prepareChecking();
220     void            checkEntries();
221 
getExtensionManager() const222     TheExtensionManager*    getExtensionManager() const { return m_pManager; }
223 
224     //===================================================================================
225     //These functions are used for automatic testing
226 
227     /** @return  The count of the entries in the list box. */
228     virtual sal_Int32 getItemCount() const;
229 
230     /** @return  The index of the first selected entry in the list box.
231         When nothing is selected, which is the case when getItemCount returns '0',
232         then this function returns EXTENSION_LISTBOX_ENTRY_NOTFOUND */
233     virtual sal_Int32 getSelIndex() const;
234 
235     /** @return  The item name of the entry with the given index
236         The index starts with 0.
237         Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */
238     virtual ::rtl::OUString getItemName( sal_Int32 index ) const;
239 
240     /** @return  The version string of the entry with the given index
241         The index starts with 0.
242         Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */
243     virtual ::rtl::OUString getItemVersion( sal_Int32 index ) const;
244 
245     /** @return  The description string of the entry with the given index
246         The index starts with 0.
247         Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */
248     virtual ::rtl::OUString getItemDescription( sal_Int32 index ) const;
249 
250     /** @return  The publisher string of the entry with the given index
251         The index starts with 0.
252         Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */
253     virtual ::rtl::OUString getItemPublisher( sal_Int32 index ) const;
254 
255     /** @return  The link behind the publisher text of the entry with the given index
256         The index starts with 0.
257         Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */
258     virtual ::rtl::OUString getItemPublisherLink( sal_Int32 index ) const;
259 
260     /** The entry at the given position will be selected
261         Index starts with 0.
262         Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */
263     virtual void select( sal_Int32 pos );
264 
265     /** The first found entry with the given name will be selected
266         When there was no entry found with the name, the selection doesn't change.
267         Please note that there might be more than one entry with the same
268         name, because:
269             1. the name is not unique
270             2. one extension can be installed as user and shared extension.
271     */
272     virtual void select( const ::rtl::OUString & sName );
273 };
274 
275 }
276