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