You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/kexi/widget/kexidatasourcecombobox.cpp

334 lines
8.3 KiB

/* This file is part of the KDE project
Copyright (C) 2005-2006 Jaroslaw Staniek <js@iidea.pl>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "kexidatasourcecombobox.h"
#include <kdebug.h>
#include <kiconloader.h>
#include <tdelistbox.h>
#include <kexi.h>
#include <kexiproject.h>
#include <keximainwindow.h>
#include <kexipart.h>
#include <kexipartmanager.h>
#include <kexipartinfo.h>
#include <kexipartitem.h>
#include <kexidb/connection.h>
#ifdef KEXI_SHOW_UNIMPLEMENTED
#define ADD_DEFINEQUERY_ROW
#endif
//! @internal
class KexiDataSourceComboBox::Private
{
public:
Private()
: tablesCount(0)
, prevIndex(-1)
, showTables(true)
, showQueries(true)
{
}
int firstTableIndex() const {
int index = 1; //skip empty row
#ifdef ADD_DEFINEQUERY_ROW
index++; /*skip 'define query' row*/
#endif
return index;
}
int firstQueryIndex() const {
return firstTableIndex() + tablesCount;
}
TQGuardedPtr<KexiProject> prj;
TQPixmap tableIcon, queryIcon;
int tablesCount;
int prevIndex; //!< Used in slotActivated()
bool showTables : 1;
bool showQueries : 1;
};
//------------------------
KexiDataSourceComboBox::KexiDataSourceComboBox(TQWidget *parent, const char *name)
: KComboBox(true/*rw*/, parent, name)
, d(new Private())
{
setInsertionPolicy(NoInsertion);
setCompletionMode(TDEGlobalSettings::CompletionPopupAuto);
setSizeLimit( 16 );
connect(this, TQ_SIGNAL(activated(int)), this, TQ_SLOT(slotActivated(int)));
connect(this, TQ_SIGNAL(returnPressed(const TQString &)), this, TQ_SLOT(slotReturnPressed(const TQString &)));
d->tableIcon = SmallIcon("table");
d->queryIcon = SmallIcon("query");
}
KexiDataSourceComboBox::~KexiDataSourceComboBox()
{
delete d;
}
KexiProject* KexiDataSourceComboBox::project() const
{
return d->prj;
}
void KexiDataSourceComboBox::setProject(KexiProject *prj, bool showTables, bool showQueries)
{
if ((KexiProject*)d->prj == prj)
return;
if (d->prj) {
disconnect(d->prj, 0, this, 0);
}
d->prj = prj;
d->showTables = showTables;
d->showQueries = showQueries;
clear();
d->tablesCount = 0;
if (!d->prj)
return;
//needed for updating contents of the combo box
connect(d->prj, TQ_SIGNAL(newItemStored(KexiPart::Item&)),
this, TQ_SLOT(slotNewItemStored(KexiPart::Item&)));
connect(d->prj, TQ_SIGNAL(itemRemoved(const KexiPart::Item&)),
this, TQ_SLOT(slotItemRemoved(const KexiPart::Item&)));
connect(d->prj, TQ_SIGNAL(itemRenamed(const KexiPart::Item&, const TQCString&)),
this, TQ_SLOT(slotItemRenamed(const KexiPart::Item&, const TQCString&)));
KexiDB::Connection *conn = d->prj->dbConnection();
if (!conn)
return;
//special item: empty
insertItem("");
#ifdef ADD_DEFINEQUERY_ROW
//special item: define query
insertItem(i18n("Define Query..."));
#endif
TDECompletion *comp = completionObject();
if (d->showTables) {
//tables
KexiPart::Info* partInfo = Kexi::partManager().infoForMimeType("kexi/table");
if (!partInfo)
return;
KexiPart::ItemList list;
prj->getSortedItems(list, partInfo);
list.sort();
d->tablesCount = 0;
for (KexiPart::ItemListIterator it(list); it.current(); ++it, d->tablesCount++) {
insertItem(d->tableIcon, it.current()->name()); //or caption()?
comp->addItem(it.current()->name());
}
}
if (d->showQueries) {
//queries
KexiPart::Info* partInfo = Kexi::partManager().infoForMimeType("kexi/query");
if (!partInfo)
return;
KexiPart::ItemList list;
prj->getSortedItems(list, partInfo);
list.sort();
for (KexiPart::ItemListIterator it(list); it.current(); ++it) {
insertItem(d->queryIcon, it.current()->name()); //or caption()?
comp->addItem(it.current()->name());
}
}
// setCurrentText("");
setCurrentItem(0);
}
void KexiDataSourceComboBox::setDataSource(const TQString& mimeType, const TQString& name)
{
if (name.isEmpty()) {
clearEdit();
setCurrentItem(0);
d->prevIndex = -1;
emit dataSourceChanged();
return;
}
TQString mt(mimeType);
if (mimeType.isEmpty())
mt="kexi/table";
int i = findItem(mt, name);
if (i==-1) {
if (mimeType.isEmpty())
i = findItem("kexi/query", name);
if (i==-1) {
setCurrentItem(0);
return;
}
}
setCurrentItem(i);
slotActivated(i);
}
void KexiDataSourceComboBox::slotNewItemStored(KexiPart::Item& item)
{
TQString name(item.name());
//insert a new item, maintaining sort order and splitting to tables and queries
if (item.mimeType()=="kexi/table") {
int i = 1; /*skip empty row*/
#ifdef ADD_DEFINEQUERY_ROW
i++; /*skip 'define query' row*/
#endif
for (; i < d->firstQueryIndex() && name>=text(i); i++)
;
insertItem(d->tableIcon, name, i);
completionObject()->addItem(name);
d->tablesCount++;
}
else if (item.mimeType()=="kexi/query") {
int i;
for (i=d->firstQueryIndex(); i<count() && name>=text(i); i++)
;
insertItem(d->queryIcon, name, i);
completionObject()->addItem(name);
}
}
int KexiDataSourceComboBox::findItem(const TQString& mimeType, const TQString& name)
{
int i, end;
if (mimeType=="kexi/table") {
i = 0;
#ifdef ADD_DEFINEQUERY_ROW
i++; //skip 'define query'
#endif
end = d->firstQueryIndex();
}
else if (mimeType=="kexi/query") {
i = d->firstQueryIndex();
end = count();
}
else
return -1;
TQString nameString(name);
for (; i<end; i++)
if (text(i)==nameString)
return i;
return -1;
}
void KexiDataSourceComboBox::slotItemRemoved(const KexiPart::Item& item)
{
const int i = findItem(item.mimeType(), item.name());
if (i==-1)
return;
removeItem(i);
completionObject()->removeItem(item.name());
if (item.mimeType()=="kexi/table")
d->tablesCount--;
#if 0 //disabled because even invalid data source can be set
if (currentItem()==i) {
if (i==(count()-1))
setCurrentItem(i-1);
else
setCurrentItem(i);
}
#endif
}
void KexiDataSourceComboBox::slotItemRenamed(const KexiPart::Item& item, const TQCString& oldName)
{
const int i = findItem(item.mimeType(), TQString(oldName));
if (i==-1)
return;
changeItem(item.name(), i);
completionObject()->removeItem(TQString(oldName));
completionObject()->addItem(item.name());
setCurrentText(oldName); //still keep old name
}
void KexiDataSourceComboBox::slotActivated( int index )
{
if (index >= d->firstTableIndex() && index < count() && d->prevIndex!=currentItem()) {
d->prevIndex = currentItem();
emit dataSourceChanged();
}
}
TQString KexiDataSourceComboBox::selectedMimeType() const
{
if (selectedName().isEmpty())
return "";
const int index = currentItem();
if (index >= d->firstTableIndex() && index < (int)d->firstQueryIndex())
return "kexi/table";
else if (index >= (int)d->firstQueryIndex() && index < count())
return "kexi/query";
return "";
}
TQString KexiDataSourceComboBox::selectedName() const
{
if (isSelectionValid())
return text(currentItem());
return currentText();
}
bool KexiDataSourceComboBox::isSelectionValid() const
{
const int index = currentItem();
return index >= d->firstTableIndex() && index < count() && text(index)==currentText();
}
void KexiDataSourceComboBox::slotReturnPressed(const TQString & text)
{
//text is available: select item for this text:
bool changed = false;
if (text.isEmpty() && 0!=currentItem()) {
setCurrentItem(0);
changed = true;
}
else {
TQListBoxItem *item = listBox()->findItem( text, TQt::ExactMatch );
if (item) {
int index = listBox()->index( item );
//if (index < d->firstTableIndex())
if (index>=0 && index!=currentItem()) {
setCurrentItem( index );
changed = true;
}
}
}
if (changed)
emit dataSourceChanged();
}
void KexiDataSourceComboBox::focusOutEvent( TQFocusEvent *e )
{
KComboBox::focusOutEvent( e );
slotReturnPressed(currentText());
}
#include "kexidatasourcecombobox.moc"