kexi

kexidatasourcecombobox.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2005-2006 Jaroslaw Staniek <js@iidea.pl>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include "kexidatasourcecombobox.h"
21
22#include <kdebug.h>
23#include <kiconloader.h>
24#include <tdelistbox.h>
25
26#include <kexi.h>
27#include <kexiproject.h>
28#include <keximainwindow.h>
29#include <kexipart.h>
30#include <kexipartmanager.h>
31#include <kexipartinfo.h>
32#include <kexipartitem.h>
33
34#include <kexidb/connection.h>
35
36#ifdef KEXI_SHOW_UNIMPLEMENTED
37#define ADD_DEFINEQUERY_ROW
38#endif
39
41class KexiDataSourceComboBox::Private
42{
43 public:
44 Private()
45 : tablesCount(0)
46 , prevIndex(-1)
47 , showTables(true)
48 , showQueries(true)
49 {
50 }
51 int firstTableIndex() const {
52 int index = 1; //skip empty row
53#ifdef ADD_DEFINEQUERY_ROW
54 index++; /*skip 'define query' row*/
55#endif
56 return index;
57 }
58 int firstQueryIndex() const {
59 return firstTableIndex() + tablesCount;
60 }
61
62 TQGuardedPtr<KexiProject> prj;
63 TQPixmap tableIcon, queryIcon;
64 int tablesCount;
65 int prevIndex;
66 bool showTables : 1;
67 bool showQueries : 1;
68};
69
70//------------------------
71
72KexiDataSourceComboBox::KexiDataSourceComboBox(TQWidget *parent, const char *name)
73 : KComboBox(true/*rw*/, parent, name)
74 , d(new Private())
75{
76 setInsertionPolicy(NoInsertion);
77 setCompletionMode(TDEGlobalSettings::CompletionPopupAuto);
78 setSizeLimit( 16 );
79 connect(this, TQ_SIGNAL(activated(int)), this, TQ_SLOT(slotActivated(int)));
80 connect(this, TQ_SIGNAL(returnPressed(const TQString &)), this, TQ_SLOT(slotReturnPressed(const TQString &)));
81
82 d->tableIcon = SmallIcon("table");
83 d->queryIcon = SmallIcon("query");
84}
85
86KexiDataSourceComboBox::~KexiDataSourceComboBox()
87{
88 delete d;
89}
90
92{
93 return d->prj;
94}
95
96void KexiDataSourceComboBox::setProject(KexiProject *prj, bool showTables, bool showQueries)
97{
98 if ((KexiProject*)d->prj == prj)
99 return;
100
101 if (d->prj) {
102 disconnect(d->prj, 0, this, 0);
103 }
104 d->prj = prj;
105 d->showTables = showTables;
106 d->showQueries = showQueries;
107 clear();
108 d->tablesCount = 0;
109 if (!d->prj)
110 return;
111
112 //needed for updating contents of the combo box
113 connect(d->prj, TQ_SIGNAL(newItemStored(KexiPart::Item&)),
114 this, TQ_SLOT(slotNewItemStored(KexiPart::Item&)));
115 connect(d->prj, TQ_SIGNAL(itemRemoved(const KexiPart::Item&)),
116 this, TQ_SLOT(slotItemRemoved(const KexiPart::Item&)));
117 connect(d->prj, TQ_SIGNAL(itemRenamed(const KexiPart::Item&, const TQCString&)),
118 this, TQ_SLOT(slotItemRenamed(const KexiPart::Item&, const TQCString&)));
119
120 KexiDB::Connection *conn = d->prj->dbConnection();
121 if (!conn)
122 return;
123
124 //special item: empty
125 insertItem("");
126#ifdef ADD_DEFINEQUERY_ROW
127 //special item: define query
128 insertItem(i18n("Define Query..."));
129#endif
130
131 TDECompletion *comp = completionObject();
132
133 if (d->showTables) {
134 //tables
135 KexiPart::Info* partInfo = Kexi::partManager().infoForMimeType("kexi/table");
136 if (!partInfo)
137 return;
139 prj->getSortedItems(list, partInfo);
140 list.sort();
141 d->tablesCount = 0;
142 for (KexiPart::ItemListIterator it(list); it.current(); ++it, d->tablesCount++) {
143 insertItem(d->tableIcon, it.current()->name()); //or caption()?
144 comp->addItem(it.current()->name());
145 }
146 }
147
148 if (d->showQueries) {
149 //queries
150 KexiPart::Info* partInfo = Kexi::partManager().infoForMimeType("kexi/query");
151 if (!partInfo)
152 return;
154 prj->getSortedItems(list, partInfo);
155 list.sort();
156 for (KexiPart::ItemListIterator it(list); it.current(); ++it) {
157 insertItem(d->queryIcon, it.current()->name()); //or caption()?
158 comp->addItem(it.current()->name());
159 }
160 }
161// setCurrentText("");
162 setCurrentItem(0);
163}
164
165void KexiDataSourceComboBox::setDataSource(const TQString& mimeType, const TQString& name)
166{
167 if (name.isEmpty()) {
168 clearEdit();
169 setCurrentItem(0);
170 d->prevIndex = -1;
171 emit dataSourceChanged();
172 return;
173 }
174
175 TQString mt(mimeType);
176 if (mimeType.isEmpty())
177 mt="kexi/table";
178 int i = findItem(mt, name);
179 if (i==-1) {
180 if (mimeType.isEmpty())
181 i = findItem("kexi/query", name);
182 if (i==-1) {
183 setCurrentItem(0);
184 return;
185 }
186 }
187 setCurrentItem(i);
188 slotActivated(i);
189}
190
191void KexiDataSourceComboBox::slotNewItemStored(KexiPart::Item& item)
192{
193 TQString name(item.name());
194 //insert a new item, maintaining sort order and splitting to tables and queries
195 if (item.mimeType()=="kexi/table") {
196 int i = 1; /*skip empty row*/
197#ifdef ADD_DEFINEQUERY_ROW
198 i++; /*skip 'define query' row*/
199#endif
200 for (; i < d->firstQueryIndex() && name>=text(i); i++)
201 ;
202 insertItem(d->tableIcon, name, i);
203 completionObject()->addItem(name);
204 d->tablesCount++;
205 }
206 else if (item.mimeType()=="kexi/query") {
207 int i;
208 for (i=d->firstQueryIndex(); i<count() && name>=text(i); i++)
209 ;
210 insertItem(d->queryIcon, name, i);
211 completionObject()->addItem(name);
212 }
213}
214
215int KexiDataSourceComboBox::findItem(const TQString& mimeType, const TQString& name)
216{
217 int i, end;
218 if (mimeType=="kexi/table") {
219 i = 0;
220#ifdef ADD_DEFINEQUERY_ROW
221 i++; //skip 'define query'
222#endif
223 end = d->firstQueryIndex();
224 }
225 else if (mimeType=="kexi/query") {
226 i = d->firstQueryIndex();
227 end = count();
228 }
229 else
230 return -1;
231
232 TQString nameString(name);
233
234 for (; i<end; i++)
235 if (text(i)==nameString)
236 return i;
237
238 return -1;
239}
240
241void KexiDataSourceComboBox::slotItemRemoved(const KexiPart::Item& item)
242{
243 const int i = findItem(item.mimeType(), item.name());
244 if (i==-1)
245 return;
246 removeItem(i);
247 completionObject()->removeItem(item.name());
248 if (item.mimeType()=="kexi/table")
249 d->tablesCount--;
250#if 0 //disabled because even invalid data source can be set
251 if (currentItem()==i) {
252 if (i==(count()-1))
253 setCurrentItem(i-1);
254 else
255 setCurrentItem(i);
256 }
257#endif
258}
259
260void KexiDataSourceComboBox::slotItemRenamed(const KexiPart::Item& item, const TQCString& oldName)
261{
262 const int i = findItem(item.mimeType(), TQString(oldName));
263 if (i==-1)
264 return;
265 changeItem(item.name(), i);
266 completionObject()->removeItem(TQString(oldName));
267 completionObject()->addItem(item.name());
268 setCurrentText(oldName); //still keep old name
269}
270
271void KexiDataSourceComboBox::slotActivated( int index )
272{
273 if (index >= d->firstTableIndex() && index < count() && d->prevIndex!=currentItem()) {
274 d->prevIndex = currentItem();
275 emit dataSourceChanged();
276 }
277}
278
280{
281 if (selectedName().isEmpty())
282 return "";
283 const int index = currentItem();
284 if (index >= d->firstTableIndex() && index < (int)d->firstQueryIndex())
285 return "kexi/table";
286 else if (index >= (int)d->firstQueryIndex() && index < count())
287 return "kexi/query";
288 return "";
289}
290
292{
293 if (isSelectionValid())
294 return text(currentItem());
295 return currentText();
296}
297
299{
300 const int index = currentItem();
301 return index >= d->firstTableIndex() && index < count() && text(index)==currentText();
302}
303
304void KexiDataSourceComboBox::slotReturnPressed(const TQString & text)
305{
306 //text is available: select item for this text:
307 bool changed = false;
308 if (text.isEmpty() && 0!=currentItem()) {
309 setCurrentItem(0);
310 changed = true;
311 }
312 else {
313 TQListBoxItem *item = listBox()->findItem( text, TQt::ExactMatch );
314 if (item) {
315 int index = listBox()->index( item );
316 //if (index < d->firstTableIndex())
317 if (index>=0 && index!=currentItem()) {
318 setCurrentItem( index );
319 changed = true;
320 }
321 }
322 }
323 if (changed)
324 emit dataSourceChanged();
325}
326
327void KexiDataSourceComboBox::focusOutEvent( TQFocusEvent *e )
328{
329 KComboBox::focusOutEvent( e );
330 slotReturnPressed(currentText());
331}
332
333#include "kexidatasourcecombobox.moc"
Provides database connection, allowing queries and data modification.
Definition connection.h:62
void dataSourceChanged()
Emitted whenever data source changes.
KexiProject * project() const
void setDataSource(const TQString &mimeType, const TQString &name)
int findItem(const TQString &mimeType, const TQString &name)
void setProject(KexiProject *prj, bool showTables=true, bool showQueries=true)
Sets global project that is used to retrieve schema informationm for this combo box.
Information about a Kexi Part (plugin).
Part item list with reimplemented compareItems() method.
Information about a single object that can be instantiated using Kexi Part.
Info * infoForMimeType(const TQString &mimeType)
A project's main controller.
Definition kexiproject.h:68
void getSortedItems(KexiPart::ItemList &list, KexiPart::Info *i)
Puts a list of items of a type i in this project into list.
KEXICORE_EXPORT KexiPart::Manager & partManager()
shared part manager
Definition kexi.cpp:97