Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "scitems.hxx"
21 :
22 : #include <svl/slstitm.hxx>
23 : #include <svl/stritem.hxx>
24 : #include <svl/whiter.hxx>
25 : #include <unotools/moduleoptions.hxx>
26 : #include <svtools/cliplistener.hxx>
27 : #include <svtools/insdlg.hxx>
28 : #include <sot/formats.hxx>
29 : #include <svx/hlnkitem.hxx>
30 : #include <sfx2/app.hxx>
31 : #include <sfx2/bindings.hxx>
32 : #include <sfx2/childwin.hxx>
33 : #include <sfx2/objface.hxx>
34 : #include <sfx2/request.hxx>
35 : #include <sfx2/viewfrm.hxx>
36 : #include <sfx2/sidebar/EnumContext.hxx>
37 : #include <svx/clipfmtitem.hxx>
38 : #include <svx/sidebar/ContextChangeEventMultiplexer.hxx>
39 : #include <editeng/langitem.hxx>
40 :
41 : #include "cellsh.hxx"
42 : #include "sc.hrc"
43 : #include "docsh.hxx"
44 : #include "attrib.hxx"
45 : #include "scresid.hxx"
46 : #include "tabvwsh.hxx"
47 : #include "impex.hxx"
48 : #include "formulacell.hxx"
49 : #include "scmod.hxx"
50 : #include "globstr.hrc"
51 : #include "transobj.hxx"
52 : #include "drwtrans.hxx"
53 : #include "scabstdlg.hxx"
54 : #include "dociter.hxx"
55 : #include "postit.hxx"
56 : #include "cliputil.hxx"
57 : #include "clipparam.hxx"
58 : #include "markdata.hxx"
59 :
60 : #define ScCellShell
61 : #define CellMovement
62 : #include "scslots.hxx"
63 :
64 0 : TYPEINIT1( ScCellShell, ScFormatShell );
65 :
66 0 : SFX_IMPL_INTERFACE(ScCellShell, ScFormatShell , ScResId(SCSTR_CELLSHELL) )
67 : {
68 0 : SFX_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_OBJECT | SFX_VISIBILITY_STANDARD |
69 : SFX_VISIBILITY_SERVER,
70 0 : ScResId(RID_OBJECTBAR_FORMAT));
71 0 : SFX_POPUPMENU_REGISTRATION(ScResId(RID_POPUP_CELLS));
72 0 : }
73 :
74 :
75 0 : ScCellShell::ScCellShell(ScViewData* pData) :
76 : ScFormatShell(pData),
77 : pImpl( new CellShell_Impl() ),
78 0 : bPastePossible(false)
79 : {
80 0 : SetHelpId(HID_SCSHELL_CELLSH);
81 0 : SetName(OUString("Cell"));
82 0 : SfxShell::SetContextName(sfx2::sidebar::EnumContext::GetContextName(sfx2::sidebar::EnumContext::Context_Cell));
83 0 : }
84 :
85 0 : ScCellShell::~ScCellShell()
86 : {
87 0 : if ( pImpl->m_pClipEvtLstnr )
88 : {
89 0 : pImpl->m_pClipEvtLstnr->AddRemoveListener( GetViewData()->GetActiveWin(), false );
90 :
91 : // The listener may just now be waiting for the SolarMutex and call the link
92 : // afterwards, in spite of RemoveListener. So the link has to be reset, too.
93 0 : pImpl->m_pClipEvtLstnr->ClearCallbackLink();
94 :
95 0 : pImpl->m_pClipEvtLstnr->release();
96 : }
97 :
98 0 : delete pImpl->m_pLinkedDlg;
99 0 : delete pImpl->m_pRequest;
100 0 : delete pImpl;
101 0 : }
102 :
103 0 : void ScCellShell::GetBlockState( SfxItemSet& rSet )
104 : {
105 0 : ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell();
106 0 : ScRange aMarkRange;
107 0 : ScMarkType eMarkType = GetViewData()->GetSimpleArea( aMarkRange );
108 0 : bool bSimpleArea = (eMarkType == SC_MARK_SIMPLE);
109 : bool bOnlyNotBecauseOfMatrix;
110 0 : bool bEditable = pTabViewShell->SelectionEditable( &bOnlyNotBecauseOfMatrix );
111 0 : ScDocument* pDoc = GetViewData()->GetDocument();
112 0 : ScDocShell* pDocShell = GetViewData()->GetDocShell();
113 0 : ScMarkData& rMark = GetViewData()->GetMarkData();
114 : SCCOL nCol1, nCol2;
115 : SCROW nRow1, nRow2;
116 0 : nCol1 = aMarkRange.aStart.Col();
117 0 : nRow1 = aMarkRange.aStart.Row();
118 0 : nCol2 = aMarkRange.aEnd.Col();
119 0 : nRow2 = aMarkRange.aEnd.Row();
120 :
121 0 : SfxWhichIter aIter(rSet);
122 0 : sal_uInt16 nWhich = aIter.FirstWhich();
123 0 : while ( nWhich )
124 : {
125 0 : bool bDisable = false;
126 0 : bool bNeedEdit = true; // need selection be editable?
127 0 : switch ( nWhich )
128 : {
129 : case FID_FILL_TO_BOTTOM: // fill to top / bottom
130 : {
131 0 : bDisable = !bSimpleArea || (nRow1 == 0 && nRow2 == 0);
132 0 : if ( !bDisable && bEditable )
133 : { // do not damage matrix
134 : bDisable = pDoc->HasSelectedBlockMatrixFragment(
135 0 : nCol1, nRow1, nCol2, nRow1, rMark ); // first row
136 : }
137 : }
138 0 : break;
139 : case FID_FILL_TO_TOP:
140 : {
141 0 : bDisable = (!bSimpleArea) || (nRow1 == MAXROW && nRow2 == MAXROW);
142 0 : if ( !bDisable && bEditable )
143 : { // do not damage matrix
144 : bDisable = pDoc->HasSelectedBlockMatrixFragment(
145 0 : nCol1, nRow2, nCol2, nRow2, rMark ); // last row
146 : }
147 : }
148 0 : break;
149 : case FID_FILL_TO_RIGHT: // fill to left / right
150 : {
151 0 : bDisable = !bSimpleArea || (nCol1 == 0 && nCol2 == 0);
152 0 : if ( !bDisable && bEditable )
153 : { // do not damage matrix
154 : bDisable = pDoc->HasSelectedBlockMatrixFragment(
155 0 : nCol1, nRow1, nCol1, nRow2, rMark ); // first column
156 : }
157 : }
158 0 : break;
159 : case FID_FILL_TO_LEFT:
160 : {
161 0 : bDisable = (!bSimpleArea) || (nCol1 == MAXCOL && nCol2 == MAXCOL);
162 0 : if ( !bDisable && bEditable )
163 : { // do not damage matrix
164 : bDisable = pDoc->HasSelectedBlockMatrixFragment(
165 0 : nCol2, nRow1, nCol2, nRow2, rMark ); // last column
166 : }
167 : }
168 0 : break;
169 :
170 : case SID_RANDOM_NUMBER_GENERATOR_DIALOG:
171 : case SID_SAMPLING_DIALOG:
172 : case SID_DESCRIPTIVE_STATISTICS_DIALOG:
173 : case SID_ANALYSIS_OF_VARIANCE_DIALOG:
174 : case SID_CORRELATION_DIALOG:
175 : case SID_COVARIANCE_DIALOG:
176 : {
177 0 : bDisable = !bSimpleArea;
178 : }
179 0 : break;
180 :
181 : case FID_FILL_SERIES: // fill block
182 : case SID_OPENDLG_TABOP: // multiple-cell operations, are at least 2 cells marked?
183 0 : if (pDoc->GetChangeTrack()!=NULL &&nWhich ==SID_OPENDLG_TABOP)
184 0 : bDisable = true;
185 : else
186 0 : bDisable = (!bSimpleArea) || (nCol1 == nCol2 && nRow1 == nRow2);
187 :
188 0 : if ( !bDisable && bEditable && nWhich == FID_FILL_SERIES )
189 : { // do not damage matrix
190 : bDisable = pDoc->HasSelectedBlockMatrixFragment(
191 0 : nCol1, nRow1, nCol2, nRow1, rMark ) // first row
192 0 : || pDoc->HasSelectedBlockMatrixFragment(
193 0 : nCol1, nRow2, nCol2, nRow2, rMark ) // last row
194 0 : || pDoc->HasSelectedBlockMatrixFragment(
195 0 : nCol1, nRow1, nCol1, nRow2, rMark ) // first column
196 0 : || pDoc->HasSelectedBlockMatrixFragment(
197 0 : nCol2, nRow1, nCol2, nRow2, rMark ); // last column
198 : }
199 0 : break;
200 :
201 : case SID_CUT: // cut
202 : case FID_INS_CELL: // insert cells, just simple selection
203 0 : bDisable = (!bSimpleArea);
204 0 : break;
205 :
206 : case FID_INS_ROW: // insert rows
207 : case FID_INS_CELLSDOWN:
208 0 : bDisable = (!bSimpleArea) || GetViewData()->SimpleColMarked();
209 0 : break;
210 :
211 : case FID_INS_COLUMN: // insert columns
212 : case FID_INS_CELLSRIGHT:
213 0 : bDisable = (!bSimpleArea) || GetViewData()->SimpleRowMarked();
214 0 : break;
215 :
216 : case SID_COPY: // copy
217 : // not editable because of matrix only? Do not damage matrix
218 : //! is not called, when protected AND matrix, we will have
219 : //! to live with this... is caught in Copy-Routine, otherwise
220 : //! work is to be done once more
221 0 : if ( !(!bEditable && bOnlyNotBecauseOfMatrix) )
222 0 : bNeedEdit = false; // allowed when protected/ReadOnly
223 0 : break;
224 :
225 : case SID_AUTOFORMAT: // Autoformat, at least 3x3 selected
226 0 : bDisable = (!bSimpleArea)
227 0 : || ((nCol2 - nCol1) < 2) || ((nRow2 - nRow1) < 2);
228 0 : break;
229 :
230 : case SID_CELL_FORMAT_RESET :
231 : case FID_CELL_FORMAT :
232 : case SID_ENABLE_HYPHENATION :
233 : // not editable because of matrix only? Attribute ok nonetheless
234 0 : if ( !bEditable && bOnlyNotBecauseOfMatrix )
235 0 : bNeedEdit = false;
236 0 : break;
237 :
238 : case FID_VALIDATION:
239 : {
240 0 : if ( pDocShell && pDocShell->IsDocShared() )
241 : {
242 0 : bDisable = true;
243 : }
244 : }
245 0 : break;
246 :
247 : case SID_TRANSLITERATE_HALFWIDTH:
248 : case SID_TRANSLITERATE_FULLWIDTH:
249 : case SID_TRANSLITERATE_HIRAGANA:
250 : case SID_TRANSLITERATE_KATAGANA:
251 0 : ScViewUtil::HideDisabledSlot( rSet, GetViewData()->GetBindings(), nWhich );
252 0 : break;
253 : }
254 0 : if (!bDisable && bNeedEdit && !bEditable)
255 0 : bDisable = true;
256 :
257 0 : if (bDisable)
258 0 : rSet.DisableItem(nWhich);
259 0 : else if (nWhich == SID_ENABLE_HYPHENATION)
260 : {
261 : // toggle slots need a bool item
262 0 : rSet.Put( SfxBoolItem( nWhich, false ) );
263 : }
264 0 : nWhich = aIter.NextWhich();
265 0 : }
266 0 : }
267 :
268 : // functionen, disabled depending on cursor position
269 : // Default:
270 : // SID_INSERT_POSTIT, SID_CHARMAP, SID_OPENDLG_FUNCTION
271 :
272 0 : void ScCellShell::GetCellState( SfxItemSet& rSet )
273 : {
274 0 : ScDocShell* pDocShell = GetViewData()->GetDocShell();
275 0 : ScDocument* pDoc = GetViewData()->GetDocShell()->GetDocument();
276 0 : ScAddress aCursor( GetViewData()->GetCurX(), GetViewData()->GetCurY(),
277 0 : GetViewData()->GetTabNo() );
278 :
279 0 : SfxWhichIter aIter(rSet);
280 0 : sal_uInt16 nWhich = aIter.FirstWhich();
281 0 : while ( nWhich )
282 : {
283 0 : sal_Bool bDisable = false;
284 0 : sal_Bool bNeedEdit = sal_True; // need cursor position be editable?
285 0 : switch ( nWhich )
286 : {
287 : case SID_THESAURUS:
288 : {
289 0 : CellType eType = pDoc->GetCellType( aCursor );
290 0 : bDisable = ( eType != CELLTYPE_STRING && eType != CELLTYPE_EDIT);
291 0 : if (!bDisable)
292 : {
293 : // test for available languages
294 0 : sal_uInt16 nLang = ScViewUtil::GetEffLanguage( pDoc, aCursor );
295 0 : bDisable = !ScModule::HasThesaurusLanguage( nLang );
296 : }
297 : }
298 0 : break;
299 : case SID_OPENDLG_FUNCTION:
300 : {
301 0 : ScMarkData aMarkData=GetViewData()->GetMarkData();
302 0 : aMarkData.MarkToSimple();
303 0 : ScRange aRange;
304 0 : aMarkData.GetMarkArea(aRange);
305 0 : if(aMarkData.IsMarked())
306 : {
307 0 : if (!pDoc->IsBlockEditable( aCursor.Tab(), aRange.aStart.Col(),aRange.aStart.Row(),
308 0 : aRange.aEnd.Col(),aRange.aEnd.Row() ))
309 : {
310 0 : bDisable = sal_True;
311 : }
312 0 : bNeedEdit=false;
313 0 : }
314 :
315 : }
316 0 : break;
317 : case SID_INSERT_POSTIT:
318 : {
319 0 : if ( pDocShell && pDocShell->IsDocShared() )
320 : {
321 0 : bDisable = sal_True;
322 : }
323 : }
324 0 : break;
325 : }
326 0 : if (!bDisable && bNeedEdit)
327 0 : if (!pDoc->IsBlockEditable( aCursor.Tab(), aCursor.Col(),aCursor.Row(),
328 0 : aCursor.Col(),aCursor.Row() ))
329 0 : bDisable = sal_True;
330 0 : if (bDisable)
331 0 : rSet.DisableItem(nWhich);
332 0 : nWhich = aIter.NextWhich();
333 0 : }
334 0 : }
335 :
336 0 : static sal_Bool lcl_TestFormat( SvxClipboardFmtItem& rFormats, const TransferableDataHelper& rDataHelper,
337 : SotFormatStringId nFormatId )
338 : {
339 0 : if ( rDataHelper.HasFormat( nFormatId ) )
340 : {
341 : // translated format name strings are no longer inserted here,
342 : // handled by "paste special" dialog / toolbox controller instead.
343 : // Only the object type name has to be set here:
344 0 : OUString aStrVal;
345 0 : if ( nFormatId == SOT_FORMATSTR_ID_EMBED_SOURCE )
346 : {
347 0 : TransferableObjectDescriptor aDesc;
348 0 : if ( ((TransferableDataHelper&)rDataHelper).GetTransferableObjectDescriptor(
349 : SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aDesc ) )
350 0 : aStrVal = aDesc.maTypeName;
351 : }
352 0 : else if ( nFormatId == SOT_FORMATSTR_ID_EMBED_SOURCE_OLE
353 0 : || nFormatId == SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE )
354 : {
355 0 : OUString aSource;
356 0 : SvPasteObjectHelper::GetEmbeddedName( rDataHelper, aStrVal, aSource, nFormatId );
357 : }
358 :
359 0 : if ( !aStrVal.isEmpty() )
360 0 : rFormats.AddClipbrdFormat( nFormatId, aStrVal );
361 : else
362 0 : rFormats.AddClipbrdFormat( nFormatId );
363 :
364 0 : return sal_True;
365 : }
366 :
367 0 : return false;
368 : }
369 :
370 0 : void ScCellShell::GetPossibleClipboardFormats( SvxClipboardFmtItem& rFormats )
371 : {
372 0 : Window* pWin = GetViewData()->GetActiveWin();
373 0 : sal_Bool bDraw = ( ScDrawTransferObj::GetOwnClipboard( pWin ) != NULL );
374 :
375 0 : TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
376 :
377 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_DRAWING );
378 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_SVXB );
379 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_GDIMETAFILE );
380 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_PNG );
381 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_BITMAP );
382 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_EMBED_SOURCE );
383 :
384 0 : if ( !bDraw )
385 : {
386 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_LINK );
387 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_STRING );
388 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_DIF );
389 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_RTF );
390 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_HTML );
391 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_HTML_SIMPLE );
392 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_BIFF_8 );
393 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_BIFF_5 );
394 : }
395 :
396 0 : if ( !lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) )
397 0 : lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE );
398 0 : }
399 :
400 : // insert, insert contents
401 :
402 0 : static sal_Bool lcl_IsCellPastePossible( const TransferableDataHelper& rData )
403 : {
404 0 : sal_Bool bPossible = false;
405 0 : if ( ScTransferObj::GetOwnClipboard( NULL ) || ScDrawTransferObj::GetOwnClipboard( NULL ) )
406 0 : bPossible = sal_True;
407 : else
408 : {
409 0 : if ( rData.HasFormat( SOT_FORMATSTR_ID_PNG ) ||
410 0 : rData.HasFormat( SOT_FORMAT_BITMAP ) ||
411 0 : rData.HasFormat( SOT_FORMAT_GDIMETAFILE ) ||
412 0 : rData.HasFormat( SOT_FORMATSTR_ID_SVXB ) ||
413 0 : rData.HasFormat( FORMAT_PRIVATE ) ||
414 0 : rData.HasFormat( SOT_FORMAT_RTF ) ||
415 0 : rData.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) ||
416 0 : rData.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
417 0 : rData.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ||
418 0 : rData.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
419 0 : rData.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ||
420 0 : rData.HasFormat( SOT_FORMAT_STRING ) ||
421 0 : rData.HasFormat( SOT_FORMATSTR_ID_SYLK ) ||
422 0 : rData.HasFormat( SOT_FORMATSTR_ID_LINK ) ||
423 0 : rData.HasFormat( SOT_FORMATSTR_ID_HTML ) ||
424 0 : rData.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) ||
425 0 : rData.HasFormat( SOT_FORMATSTR_ID_DIF ) )
426 : {
427 0 : bPossible = sal_True;
428 : }
429 : }
430 0 : return bPossible;
431 : }
432 :
433 0 : IMPL_LINK( ScCellShell, ClipboardChanged, TransferableDataHelper*, pDataHelper )
434 : {
435 0 : if ( pDataHelper )
436 : {
437 0 : bPastePossible = lcl_IsCellPastePossible( *pDataHelper );
438 :
439 0 : SfxBindings& rBindings = GetViewData()->GetBindings();
440 0 : rBindings.Invalidate( SID_PASTE );
441 0 : rBindings.Invalidate( SID_PASTE_SPECIAL );
442 0 : rBindings.Invalidate( SID_PASTE_ONLY_VALUE );
443 0 : rBindings.Invalidate( SID_PASTE_ONLY_TEXT );
444 0 : rBindings.Invalidate( SID_PASTE_ONLY_FORMULA );
445 0 : rBindings.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS );
446 : }
447 0 : return 0;
448 : }
449 :
450 : namespace {
451 :
452 0 : bool checkDestRanges(ScViewData& rViewData)
453 : {
454 0 : ScRange aDummy;
455 0 : ScMarkType eMarkType = rViewData.GetSimpleArea( aDummy);
456 0 : if (eMarkType != SC_MARK_MULTI)
457 : {
458 : // Single destination range.
459 0 : if (eMarkType != SC_MARK_SIMPLE && eMarkType != SC_MARK_SIMPLE_FILTERED)
460 0 : return false;
461 : }
462 :
463 : // Multiple destination ranges.
464 :
465 0 : ScDocument* pDoc = rViewData.GetDocument();
466 0 : Window* pWin = rViewData.GetActiveWin();
467 0 : if (!pWin)
468 0 : return false;
469 :
470 0 : ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(pWin);
471 0 : if (!pOwnClip)
472 : // If it's not a Calc document, we won't be picky.
473 0 : return true;
474 :
475 0 : ScDocument* pClipDoc = pOwnClip->GetDocument();
476 0 : if (!pClipDoc)
477 0 : return false;
478 :
479 0 : ScRange aSrcRange = pClipDoc->GetClipParam().getWholeRange();
480 0 : SCROW nRowSize = aSrcRange.aEnd.Row() - aSrcRange.aStart.Row() + 1;
481 0 : SCCOL nColSize = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
482 :
483 0 : ScMarkData aMark = rViewData.GetMarkData();
484 0 : ScRangeList aRanges;
485 0 : aMark.MarkToSimple();
486 0 : aMark.FillRangeListWithMarks(&aRanges, false);
487 :
488 0 : return ScClipUtil::CheckDestRanges(pDoc, nColSize, nRowSize, aMark, aRanges);
489 : }
490 :
491 : }
492 :
493 0 : void ScCellShell::GetClipState( SfxItemSet& rSet )
494 : {
495 : // SID_PASTE
496 : // SID_PASTE_SPECIAL
497 : // SID_CLIPBOARD_FORMAT_ITEMS
498 :
499 0 : if ( !pImpl->m_pClipEvtLstnr )
500 : {
501 : // create listener
502 0 : pImpl->m_pClipEvtLstnr = new TransferableClipboardListener( LINK( this, ScCellShell, ClipboardChanged ) );
503 0 : pImpl->m_pClipEvtLstnr->acquire();
504 0 : Window* pWin = GetViewData()->GetActiveWin();
505 0 : pImpl->m_pClipEvtLstnr->AddRemoveListener( pWin, true );
506 :
507 : // get initial state
508 0 : TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
509 0 : bPastePossible = lcl_IsCellPastePossible( aDataHelper );
510 : }
511 :
512 0 : bool bDisable = !bPastePossible;
513 :
514 : // cell protection / multiple selection
515 :
516 0 : if (!bDisable)
517 : {
518 0 : SCCOL nCol = GetViewData()->GetCurX();
519 0 : SCROW nRow = GetViewData()->GetCurY();
520 0 : SCTAB nTab = GetViewData()->GetTabNo();
521 0 : ScDocument* pDoc = GetViewData()->GetDocShell()->GetDocument();
522 0 : if (!pDoc->IsBlockEditable( nTab, nCol,nRow, nCol,nRow ))
523 0 : bDisable = true;
524 :
525 0 : if (!checkDestRanges(*GetViewData()))
526 0 : bDisable = true;
527 : }
528 :
529 0 : if (bDisable)
530 : {
531 0 : rSet.DisableItem( SID_PASTE );
532 0 : rSet.DisableItem( SID_PASTE_SPECIAL );
533 0 : rSet.DisableItem( SID_PASTE_ONLY_VALUE );
534 0 : rSet.DisableItem( SID_PASTE_ONLY_TEXT );
535 0 : rSet.DisableItem( SID_PASTE_ONLY_FORMULA );
536 0 : rSet.DisableItem( SID_CLIPBOARD_FORMAT_ITEMS );
537 : }
538 0 : else if ( rSet.GetItemState( SID_CLIPBOARD_FORMAT_ITEMS ) != SFX_ITEM_UNKNOWN )
539 : {
540 0 : SvxClipboardFmtItem aFormats( SID_CLIPBOARD_FORMAT_ITEMS );
541 0 : GetPossibleClipboardFormats( aFormats );
542 0 : rSet.Put( aFormats );
543 : }
544 0 : }
545 :
546 : // only SID_HYPERLINK_GETLINK:
547 :
548 0 : void ScCellShell::GetHLinkState( SfxItemSet& rSet )
549 : {
550 : // always return an item (or inserting will be disabled)
551 : // if the cell at the cursor contains only a link, return that link
552 :
553 0 : SvxHyperlinkItem aHLinkItem;
554 0 : if ( !GetViewData()->GetView()->HasBookmarkAtCursor( &aHLinkItem ) )
555 : {
556 : //! put selected text into item?
557 : }
558 :
559 0 : rSet.Put(aHLinkItem);
560 0 : }
561 :
562 0 : void ScCellShell::GetState(SfxItemSet &rSet)
563 : {
564 0 : ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell();
565 0 : ScDocShell* pDocSh = GetViewData()->GetDocShell();
566 0 : ScViewData* pData = GetViewData();
567 0 : ScDocument* pDoc = pData->GetDocument();
568 0 : ScMarkData& rMark = pData->GetMarkData();
569 0 : SCCOL nPosX = pData->GetCurX();
570 0 : SCROW nPosY = pData->GetCurY();
571 0 : SCTAB nTab = pData->GetTabNo();
572 :
573 0 : SCTAB nTabCount = pDoc->GetTableCount();
574 0 : SCTAB nTabSelCount = rMark.GetSelectCount();
575 :
576 0 : SfxWhichIter aIter(rSet);
577 0 : sal_uInt16 nWhich = aIter.FirstWhich();
578 0 : while ( nWhich )
579 : {
580 0 : switch ( nWhich )
581 : {
582 : case SID_DETECTIVE_REFRESH:
583 0 : if (!pDoc->HasDetectiveOperations())
584 0 : rSet.DisableItem( nWhich );
585 0 : break;
586 :
587 : case SID_RANGE_ADDRESS:
588 : {
589 0 : ScRange aRange;
590 0 : if ( pData->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
591 : {
592 0 : sal_uInt16 nFlags = SCA_VALID | SCA_TAB_3D;
593 0 : OUString aStr(aRange.Format(nFlags,pDoc));
594 0 : rSet.Put( SfxStringItem( nWhich, aStr ) );
595 : }
596 : }
597 0 : break;
598 :
599 : case SID_RANGE_NOTETEXT:
600 : {
601 : // always take cursor position, do not use top-left cell of selection
602 0 : OUString aNoteText;
603 0 : if ( const ScPostIt* pNote = pDoc->GetNote(nPosX, nPosY, nTab) )
604 0 : aNoteText = pNote->GetText();
605 0 : rSet.Put( SfxStringItem( nWhich, aNoteText ) );
606 : }
607 0 : break;
608 :
609 : case SID_RANGE_ROW:
610 0 : rSet.Put( SfxInt32Item( nWhich, nPosY+1 ) );
611 0 : break;
612 :
613 : case SID_RANGE_COL:
614 0 : rSet.Put( SfxInt16Item( nWhich, nPosX+1 ) );
615 0 : break;
616 :
617 : case SID_RANGE_TABLE:
618 0 : rSet.Put( SfxInt16Item( nWhich, nTab+1 ) );
619 0 : break;
620 :
621 : case SID_RANGE_VALUE:
622 : {
623 : double nValue;
624 0 : pDoc->GetValue( nPosX, nPosY, nTab, nValue );
625 0 : rSet.Put( ScDoubleItem( nWhich, nValue ) );
626 : }
627 0 : break;
628 :
629 : case SID_RANGE_FORMULA:
630 : {
631 0 : OUString aString;
632 0 : pDoc->GetFormula( nPosX, nPosY, nTab, aString );
633 0 : if( aString.isEmpty() )
634 : {
635 0 : pDoc->GetInputString( nPosX, nPosY, nTab, aString );
636 : }
637 0 : rSet.Put( SfxStringItem( nWhich, aString ) );
638 : }
639 0 : break;
640 :
641 : case SID_RANGE_TEXTVALUE:
642 : {
643 0 : OUString aString = pDoc->GetString(nPosX, nPosY, nTab);
644 0 : rSet.Put( SfxStringItem( nWhich, aString ) );
645 : }
646 0 : break;
647 :
648 : case SID_STATUS_SELMODE:
649 : {
650 : /* 0: STD Click cancels Sel
651 : * 1: ER Click extends selection
652 : * 2: ERG Click defines further selection
653 : */
654 0 : sal_uInt16 nMode = pTabViewShell->GetLockedModifiers();
655 :
656 0 : switch ( nMode )
657 : {
658 0 : case KEY_SHIFT: nMode = 1; break;
659 0 : case KEY_MOD1: nMode = 2; break; // Control-key
660 : case 0:
661 : default:
662 0 : nMode = 0;
663 : }
664 :
665 0 : rSet.Put( SfxUInt16Item( nWhich, nMode ) );
666 : }
667 0 : break;
668 :
669 : case SID_STATUS_DOCPOS:
670 : {
671 0 : OUString aStr = ScGlobal::GetRscString( STR_TABLE ) +
672 0 : " " + OUString::number( nTab + 1 ) +
673 0 : " / " + OUString::number( nTabCount );
674 0 : rSet.Put( SfxStringItem( nWhich, aStr ) );
675 : }
676 0 : break;
677 :
678 : case SID_ROWCOL_SELCOUNT:
679 : {
680 0 : ScRange aMarkRange;
681 0 : GetViewData()->GetSimpleArea( aMarkRange );
682 : SCCOL nCol1, nCol2;
683 : SCROW nRow1, nRow2;
684 0 : nCol1 = aMarkRange.aStart.Col();
685 0 : nRow1 = aMarkRange.aStart.Row();
686 0 : nCol2 = aMarkRange.aEnd.Col();
687 0 : nRow2 = aMarkRange.aEnd.Row();
688 0 : if( nCol2 != nCol1 || nRow1 != nRow2 )
689 : {
690 0 : OUString aStr = ScGlobal::GetRscString( STR_ROWCOL_SELCOUNT );
691 0 : aStr = aStr.replaceAll( "$1", OUString::number( nRow2 - nRow1 + 1 ));
692 0 : aStr = aStr.replaceAll( "$2", OUString::number( nCol2 - nCol1 + 1 ));
693 0 : rSet.Put( SfxStringItem( nWhich, aStr ) );
694 : }
695 : }
696 0 : break;
697 :
698 : // calculations etc. with date/time/Fail/position&size together
699 :
700 : // #i34458# The SfxStringItem belongs only into SID_TABLE_CELL. It no longer has to be
701 : // duplicated in SID_ATTR_POSITION or SID_ATTR_SIZE for SvxPosSizeStatusBarControl.
702 : case SID_TABLE_CELL:
703 : {
704 : // Test, if error under cursor
705 : // (not pDoc->GetErrCode, to avoid erasing circular references)
706 :
707 : // In interpreter may happen via rescheduled Basic
708 0 : if ( pDoc->IsInInterpreter() )
709 0 : rSet.Put( SfxStringItem( nWhich, OUString("...") ) );
710 : else
711 : {
712 0 : sal_uInt16 nErrCode = 0;
713 0 : ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(nPosX, nPosY, nTab));
714 0 : if (pCell)
715 : {
716 0 : if (!pCell->IsRunning())
717 0 : nErrCode = pCell->GetErrCode();
718 : }
719 :
720 0 : OUString aFuncStr;
721 0 : if ( pTabViewShell->GetFunction( aFuncStr, nErrCode ) )
722 0 : rSet.Put( SfxStringItem( nWhich, aFuncStr ) );
723 : }
724 : }
725 0 : break;
726 :
727 : case SID_DATA_SELECT:
728 : // HasSelectionData includes column content and validity,
729 : // page fields have to be checked separately.
730 0 : if ( !pDoc->HasSelectionData( nPosX, nPosY, nTab ) &&
731 0 : !pTabViewShell->HasPageFieldDataAtCursor() )
732 0 : rSet.DisableItem( nWhich );
733 0 : break;
734 :
735 : case SID_STATUS_SUM:
736 : {
737 0 : OUString aFuncStr;
738 0 : if ( pTabViewShell->GetFunction( aFuncStr ) )
739 0 : rSet.Put( SfxStringItem( nWhich, aFuncStr ) );
740 : }
741 0 : break;
742 :
743 : case FID_MERGE_ON:
744 0 : if ( pDoc->GetChangeTrack() || !pTabViewShell->TestMergeCells() )
745 0 : rSet.DisableItem( nWhich );
746 0 : break;
747 :
748 : case FID_MERGE_OFF:
749 0 : if ( pDoc->GetChangeTrack() || !pTabViewShell->TestRemoveMerge() )
750 0 : rSet.DisableItem( nWhich );
751 0 : break;
752 :
753 : case FID_MERGE_TOGGLE:
754 0 : if ( pDoc->GetChangeTrack() )
755 0 : rSet.DisableItem( nWhich );
756 : else
757 : {
758 0 : bool bCanMerge = pTabViewShell->TestMergeCells();
759 0 : bool bCanSplit = pTabViewShell->TestRemoveMerge();
760 0 : if( !bCanMerge && !bCanSplit )
761 0 : rSet.DisableItem( nWhich );
762 : else
763 0 : rSet.Put( SfxBoolItem( nWhich, bCanSplit ) );
764 : }
765 0 : break;
766 :
767 : case FID_INS_ROWBRK:
768 0 : if ( nPosY==0 || (pDoc->HasRowBreak(nPosY, nTab) & BREAK_MANUAL) )
769 0 : rSet.DisableItem( nWhich );
770 0 : break;
771 :
772 : case FID_INS_COLBRK:
773 0 : if ( nPosX==0 || (pDoc->HasColBreak(nPosX, nTab) & BREAK_MANUAL) )
774 0 : rSet.DisableItem( nWhich );
775 0 : break;
776 :
777 : case FID_DEL_ROWBRK:
778 0 : if ( nPosY==0 || (pDoc->HasRowBreak(nPosY, nTab) & BREAK_MANUAL) == 0 )
779 0 : rSet.DisableItem( nWhich );
780 0 : break;
781 :
782 : case FID_DEL_COLBRK:
783 0 : if ( nPosX==0 || (pDoc->HasColBreak(nPosX, nTab) & BREAK_MANUAL) == 0 )
784 0 : rSet.DisableItem( nWhich );
785 0 : break;
786 :
787 : case FID_FILL_TAB:
788 0 : if ( nTabSelCount < 2 )
789 0 : rSet.DisableItem( nWhich );
790 0 : break;
791 :
792 : case SID_SELECT_SCENARIO:
793 : {
794 0 : std::vector<OUString> aList;
795 0 : Color aDummyCol;
796 :
797 0 : if ( !pDoc->IsScenario(nTab) )
798 : {
799 0 : OUString aStr;
800 : sal_uInt16 nFlags;
801 0 : SCTAB nScTab = nTab + 1;
802 0 : bool bSheetProtected = pDoc->IsTabProtected(nTab);
803 :
804 0 : while ( pDoc->IsScenario(nScTab) )
805 : {
806 0 : pDoc->GetName( nScTab, aStr );
807 0 : aList.push_back(aStr);
808 0 : pDoc->GetScenarioData( nScTab, aStr, aDummyCol, nFlags );
809 0 : aList.push_back(aStr);
810 : // Protection is sal_True if both Sheet and Scenario are protected
811 0 : aList.push_back((bSheetProtected && (nFlags & SC_SCENARIO_PROTECT)) ? OUString("1") : OUString("0"));
812 0 : ++nScTab;
813 0 : }
814 : }
815 : else
816 : {
817 0 : OUString aComment;
818 : sal_uInt16 nDummyFlags;
819 0 : pDoc->GetScenarioData( nTab, aComment, aDummyCol, nDummyFlags );
820 : OSL_ENSURE( aList.empty(), "List not empty!" );
821 0 : aList.push_back(aComment);
822 : }
823 :
824 0 : rSet.Put( SfxStringListItem( nWhich, &aList ) );
825 : }
826 0 : break;
827 :
828 : case FID_ROW_HIDE:
829 : case FID_ROW_SHOW:
830 : case FID_COL_HIDE:
831 : case FID_COL_SHOW:
832 : case FID_COL_OPT_WIDTH:
833 : case FID_ROW_OPT_HEIGHT:
834 : case FID_DELETE_CELL:
835 0 : if ( pDoc->IsTabProtected(nTab) || pDocSh->IsReadOnly())
836 0 : rSet.DisableItem( nWhich );
837 0 : break;
838 :
839 : case SID_OUTLINE_MAKE:
840 : {
841 0 : if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
842 0 : GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
843 : {
844 : //! test for data pilot operation
845 : }
846 0 : else if (pDoc->GetChangeTrack()!=NULL || GetViewData()->IsMultiMarked())
847 : {
848 0 : rSet.DisableItem( nWhich );
849 : }
850 : }
851 0 : break;
852 : case SID_OUTLINE_SHOW:
853 0 : if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
854 0 : GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
855 : {
856 : //! test for data pilot operation
857 : }
858 0 : else if (!pTabViewShell->OutlinePossible(false))
859 0 : rSet.DisableItem( nWhich );
860 0 : break;
861 :
862 : case SID_OUTLINE_HIDE:
863 0 : if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
864 0 : GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
865 : {
866 : //! test for data pilot operation
867 : }
868 0 : else if (!pTabViewShell->OutlinePossible(true))
869 0 : rSet.DisableItem( nWhich );
870 0 : break;
871 :
872 : case SID_OUTLINE_REMOVE:
873 : {
874 0 : if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
875 0 : GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
876 : {
877 : //! test for data pilot operation
878 : }
879 : else
880 : {
881 : bool bCol, bRow;
882 0 : pTabViewShell->TestRemoveOutline( bCol, bRow );
883 0 : if ( !bCol && !bRow )
884 0 : rSet.DisableItem( nWhich );
885 : }
886 : }
887 0 : break;
888 :
889 : case FID_COL_WIDTH:
890 : {
891 : //GetViewData()->GetCurX();
892 0 : SfxUInt16Item aWidthItem( FID_COL_WIDTH, pDoc->GetColWidth( nPosX , nTab) );
893 0 : rSet.Put( aWidthItem );
894 0 : if ( pDocSh->IsReadOnly())
895 0 : rSet.DisableItem( nWhich );
896 :
897 : //XXX disable if not conclusive
898 : }
899 0 : break;
900 :
901 : case FID_ROW_HEIGHT:
902 : {
903 : //GetViewData()->GetCurY();
904 0 : SfxUInt16Item aHeightItem( FID_ROW_HEIGHT, pDoc->GetRowHeight( nPosY , nTab) );
905 0 : rSet.Put( aHeightItem );
906 : //XXX disable if not conclusive
907 0 : if ( pDocSh->IsReadOnly())
908 0 : rSet.DisableItem( nWhich );
909 : }
910 0 : break;
911 :
912 : case SID_DETECTIVE_FILLMODE:
913 0 : rSet.Put(SfxBoolItem( nWhich, pTabViewShell->IsAuditShell() ));
914 0 : break;
915 :
916 : case FID_INPUTLINE_STATUS:
917 : OSL_FAIL( "Old update method. Use ScTabViewShell::UpdateInputHandler()." );
918 0 : break;
919 :
920 : case SID_SCENARIOS: // scenarios:
921 0 : if (!(rMark.IsMarked() || rMark.IsMultiMarked())) // only, if something selected
922 0 : rSet.DisableItem( nWhich );
923 0 : break;
924 :
925 : case FID_NOTE_VISIBLE:
926 : {
927 0 : const ScPostIt* pNote = pDoc->GetNote(nPosX, nPosY, nTab);
928 0 : if ( pNote && pDoc->IsBlockEditable( nTab, nPosX,nPosY, nPosX,nPosY ) )
929 0 : rSet.Put( SfxBoolItem( nWhich, pNote->IsCaptionShown() ) );
930 : else
931 0 : rSet.DisableItem( nWhich );
932 : }
933 0 : break;
934 :
935 : case FID_HIDE_NOTE:
936 : case FID_SHOW_NOTE:
937 : {
938 0 : bool bEnable = false;
939 0 : bool bSearchForHidden = nWhich == FID_SHOW_NOTE;
940 0 : if (!rMark.IsMarked() && !rMark.IsMultiMarked())
941 : {
942 : // Check current cell
943 0 : const ScPostIt* pNote = pDoc->GetNote(nPosX, nPosY, nTab);
944 0 : if ( pNote && pDoc->IsBlockEditable( nTab, nPosX,nPosY, nPosX,nPosY ) )
945 0 : if ( pNote->IsCaptionShown() != bSearchForHidden)
946 0 : bEnable = true;
947 : }
948 : else
949 : {
950 : // Check selection range
951 0 : ScRangeListRef aRangesRef;
952 0 : pData->GetMultiArea(aRangesRef);
953 0 : ScRangeList aRanges = *aRangesRef;
954 0 : std::vector<sc::NoteEntry> aNotes;
955 0 : pDoc->GetNotesInRange(aRanges, aNotes);
956 0 : for(std::vector<sc::NoteEntry>::const_iterator itr = aNotes.begin(),
957 0 : itrEnd = aNotes.end(); itr != itrEnd; ++itr)
958 : {
959 0 : const ScAddress& rAdr = itr->maPos;
960 0 : if( pDoc->IsBlockEditable( rAdr.Tab(), rAdr.Col(), rAdr.Row(), rAdr.Col(), rAdr.Row() ))
961 : {
962 0 : if (itr->mpNote->IsCaptionShown() != bSearchForHidden)
963 : {
964 0 : bEnable = true;
965 0 : break;
966 : }
967 : }
968 0 : }
969 :
970 : }
971 0 : if ( !bEnable )
972 0 : rSet.DisableItem( nWhich );
973 : }
974 0 : break;
975 :
976 : case SID_DELETE_NOTE:
977 : {
978 0 : bool bEnable = false;
979 0 : if ( rMark.IsMarked() || rMark.IsMultiMarked() )
980 : {
981 0 : if ( pDoc->IsSelectionEditable( rMark ) )
982 : {
983 : // look for at least one note in selection
984 0 : ScRangeList aRanges;
985 0 : rMark.FillRangeListWithMarks( &aRanges, false );
986 0 : bEnable = pDoc->ContainsNotesInRange( aRanges );
987 : }
988 : }
989 : else
990 : {
991 0 : bEnable = pDoc->IsBlockEditable( nTab, nPosX,nPosY, nPosX,nPosY ) &&
992 0 : pDoc->GetNote(nPosX, nPosY, nTab);
993 : }
994 0 : if ( !bEnable )
995 0 : rSet.DisableItem( nWhich );
996 : }
997 0 : break;
998 :
999 : case SID_OPENDLG_CONSOLIDATE:
1000 : case SCITEM_CONSOLIDATEDATA:
1001 : {
1002 0 : if(pDoc->GetChangeTrack()!=NULL)
1003 0 : rSet.DisableItem( nWhich);
1004 : }
1005 0 : break;
1006 :
1007 : case SID_CHINESE_CONVERSION:
1008 : case SID_HANGUL_HANJA_CONVERSION:
1009 0 : ScViewUtil::HideDisabledSlot( rSet, pData->GetBindings(), nWhich );
1010 0 : break;
1011 :
1012 : case FID_USE_NAME:
1013 : {
1014 0 : if ( pDocSh && pDocSh->IsDocShared() )
1015 0 : rSet.DisableItem( nWhich );
1016 : else
1017 : {
1018 0 : ScRange aRange;
1019 0 : if ( pData->GetSimpleArea( aRange ) != SC_MARK_SIMPLE )
1020 0 : rSet.DisableItem( nWhich );
1021 : }
1022 : }
1023 0 : break;
1024 :
1025 : case FID_DEFINE_NAME:
1026 : case FID_INSERT_NAME:
1027 : case FID_ADD_NAME:
1028 : case SID_DEFINE_COLROWNAMERANGES:
1029 : {
1030 0 : if ( pDocSh && pDocSh->IsDocShared() )
1031 : {
1032 0 : rSet.DisableItem( nWhich );
1033 : }
1034 : }
1035 0 : break;
1036 :
1037 : case SID_SPELL_DIALOG:
1038 : {
1039 0 : if ( pDoc && pData && pDoc->IsTabProtected( pData->GetTabNo() ) )
1040 : {
1041 0 : bool bVisible = false;
1042 0 : SfxViewFrame* pViewFrame = ( pTabViewShell ? pTabViewShell->GetViewFrame() : NULL );
1043 0 : if ( pViewFrame && pViewFrame->HasChildWindow( nWhich ) )
1044 : {
1045 0 : SfxChildWindow* pChild = pViewFrame->GetChildWindow( nWhich );
1046 0 : Window* pWin = ( pChild ? pChild->GetWindow() : NULL );
1047 0 : if ( pWin && pWin->IsVisible() )
1048 : {
1049 0 : bVisible = true;
1050 : }
1051 : }
1052 0 : if ( !bVisible )
1053 : {
1054 0 : rSet.DisableItem( nWhich );
1055 : }
1056 : }
1057 : }
1058 0 : break;
1059 :
1060 : } // switch ( nWitch )
1061 0 : nWhich = aIter.NextWhich();
1062 0 : } // while ( nWitch )
1063 0 : }
1064 :
1065 :
1066 :
1067 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|