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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_extensions.hxx"
26 #include "listcombowizard.hxx"
27 #include "commonpagesdbp.hxx"
28 #include <com/sun/star/sdbc/XConnection.hpp>
29 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
30 #include <com/sun/star/container/XNameAccess.hpp>
31 #include <com/sun/star/form/ListSourceType.hpp>
32 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
33 #include <tools/debug.hxx>
34 #include <vcl/msgbox.hxx>
35 #include <connectivity/dbtools.hxx>
36 #include "dbpilots.hrc"
37 #include <comphelper/extract.hxx>
38 
39 //.........................................................................
40 namespace dbp
41 {
42 //.........................................................................
43 
44 	using namespace ::com::sun::star::uno;
45 	using namespace ::com::sun::star::lang;
46 	using namespace ::com::sun::star::beans;
47 	using namespace ::com::sun::star::sdbc;
48 	using namespace ::com::sun::star::sdbcx;
49 	using namespace ::com::sun::star::container;
50 	using namespace ::com::sun::star::form;
51 	using namespace ::svt;
52 	using namespace ::dbtools;
53 
54 	//=====================================================================
55 	//= OListComboWizard
56 	//=====================================================================
57 	//---------------------------------------------------------------------
OListComboWizard(Window * _pParent,const Reference<XPropertySet> & _rxObjectModel,const Reference<XMultiServiceFactory> & _rxORB)58 	OListComboWizard::OListComboWizard( Window* _pParent,
59 			const Reference< XPropertySet >& _rxObjectModel, const Reference< XMultiServiceFactory >& _rxORB )
60 		:OControlWizard(_pParent, ModuleRes(RID_DLG_LISTCOMBOWIZARD), _rxObjectModel, _rxORB)
61 		,m_bListBox(sal_False)
62 		,m_bHadDataSelection(sal_True)
63 	{
64 		initControlSettings(&m_aSettings);
65 
66 		m_pPrevPage->SetHelpId(HID_LISTWIZARD_PREVIOUS);
67 		m_pNextPage->SetHelpId(HID_LISTWIZARD_NEXT);
68 		m_pCancel->SetHelpId(HID_LISTWIZARD_CANCEL);
69 		m_pFinish->SetHelpId(HID_LISTWIZARD_FINISH);
70 
71 		// if we do not need the data source selection page ...
72 		if (!needDatasourceSelection())
73 		{	// ... skip it!
74 			skip(1);
75 			m_bHadDataSelection = sal_False;
76 		}
77 	}
78 
79 	//---------------------------------------------------------------------
approveControl(sal_Int16 _nClassId)80 	sal_Bool OListComboWizard::approveControl(sal_Int16 _nClassId)
81 	{
82 		switch (_nClassId)
83 		{
84 			case FormComponentType::LISTBOX:
85 				m_bListBox = sal_True;
86 				setTitleBase(String(ModuleRes(RID_STR_LISTWIZARD_TITLE)));
87 				return sal_True;
88 			case FormComponentType::COMBOBOX:
89 				m_bListBox = sal_False;
90 				setTitleBase(String(ModuleRes(RID_STR_COMBOWIZARD_TITLE)));
91 				return sal_True;
92 		}
93 		return sal_False;
94 	}
95 
96 	//---------------------------------------------------------------------
createPage(WizardState _nState)97 	OWizardPage* OListComboWizard::createPage(WizardState _nState)
98 	{
99 		switch (_nState)
100 		{
101 			case LCW_STATE_DATASOURCE_SELECTION:
102 				return new OTableSelectionPage(this);
103 			case LCW_STATE_TABLESELECTION:
104 				return new OContentTableSelection(this);
105 			case LCW_STATE_FIELDSELECTION:
106 				return new OContentFieldSelection(this);
107 			case LCW_STATE_FIELDLINK:
108 				return new OLinkFieldsPage(this);
109 			case LCW_STATE_COMBODBFIELD:
110 				return new OComboDBFieldPage(this);
111 		}
112 
113 		return NULL;
114 	}
115 
116 	//---------------------------------------------------------------------
determineNextState(WizardState _nCurrentState) const117     WizardTypes::WizardState OListComboWizard::determineNextState( WizardState _nCurrentState ) const
118 	{
119 		switch (_nCurrentState)
120 		{
121 			case LCW_STATE_DATASOURCE_SELECTION:
122 				return LCW_STATE_TABLESELECTION;
123 			case LCW_STATE_TABLESELECTION:
124 				return LCW_STATE_FIELDSELECTION;
125 			case LCW_STATE_FIELDSELECTION:
126 				return getFinalState();
127 		}
128 
129 		return WZS_INVALID_STATE;
130 	}
131 
132 	//---------------------------------------------------------------------
enterState(WizardState _nState)133 	void OListComboWizard::enterState(WizardState _nState)
134 	{
135 		OControlWizard::enterState(_nState);
136 
137 		enableButtons(WZB_PREVIOUS, m_bHadDataSelection ? (LCW_STATE_DATASOURCE_SELECTION < _nState) : LCW_STATE_TABLESELECTION < _nState);
138 		enableButtons(WZB_NEXT, getFinalState() != _nState);
139 		if (_nState < getFinalState())
140 			enableButtons(WZB_FINISH, sal_False);
141 
142 		if (getFinalState() == _nState)
143 			defaultButton(WZB_FINISH);
144 	}
145 
146 	//---------------------------------------------------------------------
leaveState(WizardState _nState)147 	sal_Bool OListComboWizard::leaveState(WizardState _nState)
148 	{
149 		if (!OControlWizard::leaveState(_nState))
150 			return sal_False;
151 
152 		if (getFinalState() == _nState)
153 			defaultButton(WZB_NEXT);
154 
155 		return sal_True;
156 	}
157 
158 	//---------------------------------------------------------------------
implApplySettings()159 	void OListComboWizard::implApplySettings()
160 	{
161 		try
162 		{
163 			// for quoting identifiers, we need the connection meta data
164             Reference< XConnection > xConn = getFormConnection();
165 			DBG_ASSERT(xConn.is(), "OListComboWizard::implApplySettings: no connection, unable to quote!");
166 			Reference< XDatabaseMetaData > xMetaData;
167 			if (xConn.is())
168 				xMetaData = xConn->getMetaData();
169 
170 			// do some quotings
171 			if (xMetaData.is())
172 			{
173 				::rtl::OUString sQuoteString = xMetaData->getIdentifierQuoteString();
174 				if (isListBox()) // only when we have a listbox this should be not empty
175 					getSettings().sLinkedListField = quoteName(sQuoteString, getSettings().sLinkedListField);
176 
177                 ::rtl::OUString sCatalog, sSchema, sName;
178                 ::dbtools::qualifiedNameComponents( xMetaData, getSettings().sListContentTable, sCatalog, sSchema, sName, ::dbtools::eInDataManipulation );
179                 getSettings().sListContentTable = ::dbtools::composeTableNameForSelect( xConn, sCatalog, sSchema, sName );
180 
181 				getSettings().sListContentField = quoteName(sQuoteString, getSettings().sListContentField);
182 			}
183 
184 			// ListSourceType: SQL
185 			getContext().xObjectModel->setPropertyValue(::rtl::OUString::createFromAscii("ListSourceType"), makeAny((sal_Int32)ListSourceType_SQL));
186 
187 			if (isListBox())
188 			{
189 				// BoundColumn: 1
190 				getContext().xObjectModel->setPropertyValue(::rtl::OUString::createFromAscii("BoundColumn"), makeAny((sal_Int16)1));
191 
192 				// build the statement to set as list source
193 				String sStatement;
194 				sStatement.AppendAscii("SELECT ");
195 				sStatement += getSettings().sListContentField;
196 				sStatement.AppendAscii(", ");
197 				sStatement += getSettings().sLinkedListField;
198 				sStatement.AppendAscii(" FROM ");
199 				sStatement += getSettings().sListContentTable;
200 				Sequence< ::rtl::OUString > aListSource(1);
201 				aListSource[0] = sStatement;
202 				getContext().xObjectModel->setPropertyValue(::rtl::OUString::createFromAscii("ListSource"), makeAny(aListSource));
203 			}
204 			else
205 			{
206 				// build the statement to set as list source
207 				String sStatement;
208 				sStatement.AppendAscii("SELECT DISTINCT ");
209 				sStatement += getSettings().sListContentField;
210 				sStatement.AppendAscii(" FROM ");
211 				sStatement += getSettings().sListContentTable;
212 				getContext().xObjectModel->setPropertyValue(::rtl::OUString::createFromAscii("ListSource"), makeAny(::rtl::OUString(sStatement)));
213 			}
214 
215 			// the bound field
216 			getContext().xObjectModel->setPropertyValue(::rtl::OUString::createFromAscii("DataField"), makeAny(::rtl::OUString(getSettings().sLinkedFormField)));
217 		}
218 		catch(Exception&)
219 		{
220 			DBG_ERROR("OListComboWizard::implApplySettings: could not set the property values for the listbox!");
221 		}
222 	}
223 
224 	//---------------------------------------------------------------------
onFinish()225 	sal_Bool OListComboWizard::onFinish()
226 	{
227 		if ( !OControlWizard::onFinish() )
228 			return sal_False;
229 
230 		implApplySettings();
231 		return sal_True;
232 	}
233 
234 	//=====================================================================
235 	//= OLCPage
236 	//=====================================================================
237 	//---------------------------------------------------------------------
getTables(sal_Bool _bNeedIt)238 	Reference< XNameAccess > OLCPage::getTables(sal_Bool _bNeedIt)
239 	{
240 		Reference< XConnection > xConn = getFormConnection();
241 		DBG_ASSERT(!_bNeedIt || xConn.is(), "OLCPage::getTables: should have an active connection when reaching this page!");
242         (void)_bNeedIt;
243 
244 		Reference< XTablesSupplier > xSuppTables(xConn, UNO_QUERY);
245 		Reference< XNameAccess > xTables;
246 		if (xSuppTables.is())
247 			xTables = xSuppTables->getTables();
248 
249 		DBG_ASSERT(!_bNeedIt || xTables.is() || !xConn.is(), "OLCPage::getTables: got no tables from the connection!");
250 
251 		return xTables;
252 	}
253 
254 	//---------------------------------------------------------------------
getTableFields(sal_Bool _bNeedIt)255 	Sequence< ::rtl::OUString > OLCPage::getTableFields(sal_Bool _bNeedIt)
256 	{
257 		Reference< XNameAccess > xTables = getTables(_bNeedIt);
258 		Sequence< ::rtl::OUString > aColumnNames;
259 		if (xTables.is())
260 		{
261 			try
262 			{
263 				// the list table as XColumnsSupplier
264 				Reference< XColumnsSupplier > xSuppCols;
265 				xTables->getByName(getSettings().sListContentTable) >>= xSuppCols;
266 				DBG_ASSERT(!_bNeedIt || xSuppCols.is(), "OLCPage::getTableFields: no columns supplier!");
267 
268 				// the columns
269 				Reference< XNameAccess > xColumns;
270 				if (xSuppCols.is())
271 					xColumns = xSuppCols->getColumns();
272 
273 				// the column names
274 				if (xColumns.is())
275 					aColumnNames = xColumns->getElementNames();
276 			}
277 			catch(Exception&)
278 			{
279 				DBG_ASSERT(!_bNeedIt, "OLinkFieldsPage::initializePage: caught an exception while retrieving the columns!");
280 			}
281 		}
282 		return aColumnNames;
283 	}
284 
285 	//=====================================================================
286 	//= OContentTableSelection
287 	//=====================================================================
288 	//---------------------------------------------------------------------
OContentTableSelection(OListComboWizard * _pParent)289 	OContentTableSelection::OContentTableSelection( OListComboWizard* _pParent )
290 		:OLCPage(_pParent, ModuleRes(RID_PAGE_LCW_CONTENTSELECTION_TABLE))
291 		,m_aFrame				(this, ModuleRes(FL_FRAME))
292 		,m_aSelectTableLabel	(this, ModuleRes(FT_SELECTTABLE_LABEL))
293 		,m_aSelectTable			(this, ModuleRes(LB_SELECTTABLE))
294 	{
295 		FreeResource();
296 
297 		enableFormDatasourceDisplay();
298 
299 		m_aSelectTable.SetDoubleClickHdl(LINK(this, OContentTableSelection, OnTableDoubleClicked));
300 		m_aSelectTable.SetSelectHdl(LINK(this, OContentTableSelection, OnTableSelected));
301 	}
302 
303 	//---------------------------------------------------------------------
ActivatePage()304 	void OContentTableSelection::ActivatePage()
305 	{
306 		OLCPage::ActivatePage();
307 		m_aSelectTable.GrabFocus();
308 	}
309 
310 	//---------------------------------------------------------------------
canAdvance() const311 	bool OContentTableSelection::canAdvance() const
312 	{
313 		if (!OLCPage::canAdvance())
314 			return false;
315 
316 		return 0 != m_aSelectTable.GetSelectEntryCount();
317 	}
318 
319 	//---------------------------------------------------------------------
320 	IMPL_LINK( OContentTableSelection, OnTableSelected, ListBox*, /*_pListBox*/ )
321 	{
322 		updateDialogTravelUI();
323 		return 0L;
324 	}
325 
326 	//---------------------------------------------------------------------
IMPL_LINK(OContentTableSelection,OnTableDoubleClicked,ListBox *,_pListBox)327 	IMPL_LINK( OContentTableSelection, OnTableDoubleClicked, ListBox*, _pListBox )
328 	{
329 		if (_pListBox->GetSelectEntryCount())
330 			getDialog()->travelNext();
331 		return 0L;
332 	}
333 
334 	//---------------------------------------------------------------------
initializePage()335 	void OContentTableSelection::initializePage()
336 	{
337 		OLCPage::initializePage();
338 
339 		// fill the list with the table name
340 		m_aSelectTable.Clear();
341 		try
342 		{
343 			Reference< XNameAccess > xTables = getTables(sal_True);
344 			Sequence< ::rtl::OUString > aTableNames;
345 			if (xTables.is())
346 				aTableNames = xTables->getElementNames();
347 			fillListBox(m_aSelectTable, aTableNames);
348 		}
349 		catch(Exception&)
350 		{
351 			DBG_ERROR("OContentTableSelection::initializePage: could not retrieve the table names!");
352 		}
353 
354 		m_aSelectTable.SelectEntry(getSettings().sListContentTable);
355 	}
356 
357 	//---------------------------------------------------------------------
commitPage(::svt::WizardTypes::CommitPageReason _eReason)358 	sal_Bool OContentTableSelection::commitPage( ::svt::WizardTypes::CommitPageReason _eReason )
359 	{
360 		if (!OLCPage::commitPage(_eReason))
361 			return sal_False;
362 
363 		OListComboSettings& rSettings = getSettings();
364 		rSettings.sListContentTable = m_aSelectTable.GetSelectEntry();
365 		if (!rSettings.sListContentTable.Len() && (::svt::WizardTypes::eTravelBackward != _eReason))
366 			// need to select a table
367 			return sal_False;
368 
369 		return sal_True;
370 	}
371 
372 	//=====================================================================
373 	//= OContentFieldSelection
374 	//=====================================================================
375 	//---------------------------------------------------------------------
OContentFieldSelection(OListComboWizard * _pParent)376 	OContentFieldSelection::OContentFieldSelection( OListComboWizard* _pParent )
377 		:OLCPage(_pParent, ModuleRes(RID_PAGE_LCW_CONTENTSELECTION_FIELD))
378 		,m_aFrame				(this, ModuleRes(FL_FRAME))
379 		,m_aTableFields			(this, ModuleRes(FT_TABLEFIELDS))
380 		,m_aSelectTableField	(this, ModuleRes(LB_SELECTFIELD))
381 		,m_aDisplayedFieldLabel	(this, ModuleRes(FT_DISPLAYEDFIELD))
382 		,m_aDisplayedField		(this, ModuleRes(ET_DISPLAYEDFIELD))
383 		,m_aInfo				(this, ModuleRes(FT_CONTENTFIELD_INFO))
384 	{
385 		m_aInfo.SetText(String(ModuleRes( isListBox() ? STR_FIELDINFO_LISTBOX : STR_FIELDINFO_COMBOBOX)));
386 		FreeResource();
387 		m_aSelectTableField.SetSelectHdl(LINK(this, OContentFieldSelection, OnFieldSelected));
388 		m_aSelectTableField.SetDoubleClickHdl(LINK(this, OContentFieldSelection, OnTableDoubleClicked));
389 	}
390 
391 	//---------------------------------------------------------------------
ActivatePage()392 	void OContentFieldSelection::ActivatePage()
393 	{
394 		OLCPage::ActivatePage();
395 		m_aTableFields.GrabFocus();
396 	}
397 
398 	//---------------------------------------------------------------------
initializePage()399 	void OContentFieldSelection::initializePage()
400 	{
401 		OLCPage::initializePage();
402 
403 		// fill the list of fields
404 		fillListBox(m_aSelectTableField, getTableFields(sal_True));
405 
406 		m_aSelectTableField.SelectEntry(getSettings().sListContentField);
407 		m_aDisplayedField.SetText(getSettings().sListContentField);
408 	}
409 
410 	//---------------------------------------------------------------------
canAdvance() const411 	bool OContentFieldSelection::canAdvance() const
412 	{
413 		if (!OLCPage::canAdvance())
414 			return false;
415 
416 		return 0 != m_aSelectTableField.GetSelectEntryCount();
417 	}
418 
419 	//---------------------------------------------------------------------
420 	IMPL_LINK( OContentFieldSelection, OnTableDoubleClicked, ListBox*, /*NOTINTERESTEDIN*/ )
421 	{
422 		if (m_aSelectTableField.GetSelectEntryCount())
423 			getDialog()->travelNext();
424 		return 0L;
425 	}
426 
427 	//---------------------------------------------------------------------
428 	IMPL_LINK( OContentFieldSelection, OnFieldSelected, ListBox*, /*NOTINTERESTEDIN*/ )
429 	{
430 		updateDialogTravelUI();
431 		m_aDisplayedField.SetText(m_aSelectTableField.GetSelectEntry());
432 		return 0L;
433 	}
434 
435 	//---------------------------------------------------------------------
commitPage(::svt::WizardTypes::CommitPageReason _eReason)436 	sal_Bool OContentFieldSelection::commitPage( ::svt::WizardTypes::CommitPageReason _eReason )
437 	{
438 		if (!OLCPage::commitPage(_eReason))
439 			return sal_False;
440 
441 		getSettings().sListContentField = m_aSelectTableField.GetSelectEntry();
442 
443 		return sal_True;
444 	}
445 
446 	//=====================================================================
447 	//= OLinkFieldsPage
448 	//=====================================================================
449 	//---------------------------------------------------------------------
OLinkFieldsPage(OListComboWizard * _pParent)450 	OLinkFieldsPage::OLinkFieldsPage( OListComboWizard* _pParent )
451 		:OLCPage(_pParent, ModuleRes(RID_PAGE_LCW_FIELDLINK))
452 		,m_aDescription			(this, ModuleRes(FT_FIELDLINK_DESC))
453 		,m_aFrame				(this, ModuleRes(FL_FRAME))
454 		,m_aValueListFieldLabel	(this, ModuleRes(FT_VALUELISTFIELD))
455 		,m_aValueListField		(this, ModuleRes(CMB_VALUELISTFIELD))
456 		,m_aTableFieldLabel		(this, ModuleRes(FT_TABLEFIELD))
457 		,m_aTableField			(this, ModuleRes(CMB_TABLEFIELD))
458 	{
459 		FreeResource();
460 
461 		m_aValueListField.SetModifyHdl(LINK(this, OLinkFieldsPage, OnSelectionModified));
462 		m_aTableField.SetModifyHdl(LINK(this, OLinkFieldsPage, OnSelectionModified));
463 		m_aValueListField.SetSelectHdl(LINK(this, OLinkFieldsPage, OnSelectionModified));
464 		m_aTableField.SetSelectHdl(LINK(this, OLinkFieldsPage, OnSelectionModified));
465 	}
466 
467 	//---------------------------------------------------------------------
ActivatePage()468 	void OLinkFieldsPage::ActivatePage()
469 	{
470 		OLCPage::ActivatePage();
471 		m_aValueListField.GrabFocus();
472 	}
473 
474 	//---------------------------------------------------------------------
initializePage()475 	void OLinkFieldsPage::initializePage()
476 	{
477 		OLCPage::initializePage();
478 
479 		// fill the value list
480 		fillListBox(m_aValueListField, getContext().aFieldNames);
481 		// fill the table field list
482 		fillListBox(m_aTableField, getTableFields(sal_True));
483 
484 		// the initial selections
485 		m_aValueListField.SetText(getSettings().sLinkedFormField);
486 		m_aTableField.SetText(getSettings().sLinkedListField);
487 
488 		implCheckFinish();
489 	}
490 
491 	//---------------------------------------------------------------------
canAdvance() const492 	bool OLinkFieldsPage::canAdvance() const
493 	{
494 		// we're on the last page here, no travelNext allowed ...
495 		return false;
496 	}
497 
498 	//---------------------------------------------------------------------
implCheckFinish()499 	void OLinkFieldsPage::implCheckFinish()
500 	{
501 		sal_Bool bInvalidSelection = (COMBOBOX_ENTRY_NOTFOUND == m_aValueListField.GetEntryPos(m_aValueListField.GetText()));
502 		bInvalidSelection |= (COMBOBOX_ENTRY_NOTFOUND == m_aTableField.GetEntryPos(m_aTableField.GetText()));
503 		getDialog()->enableButtons(WZB_FINISH, !bInvalidSelection);
504 	}
505 
506 	//---------------------------------------------------------------------
IMPL_LINK(OLinkFieldsPage,OnSelectionModified,void *,EMPTYARG)507 	IMPL_LINK(OLinkFieldsPage, OnSelectionModified, void*, EMPTYARG)
508 	{
509 		implCheckFinish();
510 		return 0L;
511 	}
512 
513 	//---------------------------------------------------------------------
commitPage(::svt::WizardTypes::CommitPageReason _eReason)514 	sal_Bool OLinkFieldsPage::commitPage( ::svt::WizardTypes::CommitPageReason _eReason )
515 	{
516 		if (!OLCPage::commitPage(_eReason))
517 			return sal_False;
518 
519 		getSettings().sLinkedFormField = m_aValueListField.GetText();
520 		getSettings().sLinkedListField = m_aTableField.GetText();
521 
522 		return sal_True;
523 	}
524 
525 	//=====================================================================
526 	//= OComboDBFieldPage
527 	//=====================================================================
528 	//---------------------------------------------------------------------
OComboDBFieldPage(OControlWizard * _pParent)529 	OComboDBFieldPage::OComboDBFieldPage( OControlWizard* _pParent )
530 		:ODBFieldPage(_pParent)
531 	{
532 		setDescriptionText(String(ModuleRes(RID_STR_COMBOWIZ_DBFIELD)));
533 	}
534 
535 	//---------------------------------------------------------------------
getDBFieldSetting()536 	String& OComboDBFieldPage::getDBFieldSetting()
537 	{
538 		return getSettings().sLinkedFormField;
539 	}
540 
541 	//---------------------------------------------------------------------
ActivatePage()542 	void OComboDBFieldPage::ActivatePage()
543 	{
544 		ODBFieldPage::ActivatePage();
545 		getDialog()->enableButtons(WZB_FINISH, sal_True);
546 	}
547 
548 	//---------------------------------------------------------------------
canAdvance() const549 	bool OComboDBFieldPage::canAdvance() const
550 	{
551 		// we're on the last page here, no travelNext allowed ...
552 		return false;
553 	}
554 
555 //.........................................................................
556 }	// namespace dbp
557 //.........................................................................
558 
559