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