File indexing completed on 2024-05-12 16:40:56

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003-2011 Jarosław Staniek <staniek@kde.org>
0003 
0004    This program is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This program is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this program; see the file COPYING.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018  */
0019 
0020 #include "KexiProjectSelectorWidget.h"
0021 #include <core/kexi.h>
0022 #include <KexiIcon.h>
0023 
0024 #include <KDbDriverManager>
0025 #include <KDbDriverMetaData>
0026 #include <KDbConnectionData>
0027 #include <KDbUtils>
0028 #include <KDbMessageHandler>
0029 
0030 #include <KLocalizedString>
0031 #include <KGuiItem>
0032 
0033 #include <QDebug>
0034 #include <QLabel>
0035 #include <QPushButton>
0036 #include <QKeyEvent>
0037 
0038 #include <assert.h>
0039 
0040 //! @internal
0041 class Q_DECL_HIDDEN KexiProjectSelectorWidget::Private
0042 {
0043 public:
0044     explicit Private(KexiProjectSet *prj_set_)
0045          : prj_set(prj_set_)
0046     {
0047         selectable = true;
0048     }
0049 
0050     QIcon fileicon, dbicon;
0051     bool showProjectNameColumn;
0052     bool showConnectionColumns;
0053     bool selectable;
0054 
0055     KexiProjectSet *prj_set;
0056 };
0057 
0058 class Q_DECL_HIDDEN KexiProjectSelectorDialog::Private
0059 {
0060 public:
0061   Private() {}
0062   KexiProjectSelectorWidget* sel;
0063 };
0064 
0065 /*================================================================*/
0066 
0067 //! helper class
0068 class ProjectDataLVItem : public QTreeWidgetItem
0069 {
0070 public:
0071     ProjectDataLVItem(KexiProjectData *d,
0072                       const KDbDriverMetaData &driverMetaData,
0073                       KexiProjectSelectorWidget *selector)
0074             : QTreeWidgetItem(selector->list())
0075             , data(d)
0076     {
0077         int colnum = 0;
0078         const KDbConnectionData cdata = *data->connectionData();
0079         if (selector->d->showProjectNameColumn)
0080             setText(colnum++, data->caption() + "  ");
0081 
0082         setText(colnum++, data->databaseName() + "  ");
0083 
0084         if (selector->d->showConnectionColumns) {
0085             QString driverName = driverMetaData.name();
0086             if (driverName.isEmpty()) {
0087                 KDbDriverManager manager;
0088                 const KDbDriverMetaData *driverMetaDataFromCdata = manager.driverMetaData(cdata.driverId());
0089                 if (driverMetaDataFromCdata) {
0090                     driverName = driverMetaDataFromCdata->name();
0091                 }
0092             }
0093             if (driverMetaData.isFileBased()) {
0094                 setText(colnum++, xi18n("File (%1)", driverName) + "  ");
0095             } else {
0096                 setText(colnum++, driverName + "  ");
0097             }
0098             QString conn;
0099             if (cdata.caption().isEmpty()) {
0100                 conn = cdata.toUserVisibleString();
0101             }
0102             else {
0103                 conn = xi18nc("caption: server_info", "%1: %2",
0104                               cdata.caption(), cdata.toUserVisibleString());
0105             }
0106             setText(colnum++, conn + "  ");
0107         }
0108     }
0109     ~ProjectDataLVItem() {}
0110 
0111     KexiProjectData *data;
0112 };
0113 
0114 /*================================================================*/
0115 
0116 /*!
0117  *  Constructs a KexiProjectSelector which is a child of 'parent', with the
0118  *  name 'name' and widget flags set to 'f'
0119  */
0120 KexiProjectSelectorWidget::KexiProjectSelectorWidget(QWidget* parent,
0121         KexiProjectSet* prj_set, bool showProjectNameColumn, bool showConnectionColumns)
0122         : QWidget(parent)
0123         , d(new Private(prj_set))
0124 {
0125     setupUi(this);
0126     setObjectName("KexiProjectSelectorWidget");
0127     d->showProjectNameColumn = showProjectNameColumn;
0128     d->showConnectionColumns = showConnectionColumns;
0129     list()->installEventFilter(this);
0130 
0131     d->fileicon = Kexi::defaultFileBasedDriverIcon();
0132     setWindowIcon(d->fileicon);
0133     d->dbicon = koIcon("server-database");
0134 
0135     QTreeWidgetItem *headerItem = list()->headerItem();
0136     QTreeWidgetItem *newHeaderItem = new QTreeWidgetItem;
0137     int newHeaderItemIndex = 0;
0138     if (d->showProjectNameColumn) {
0139         newHeaderItem->setText(newHeaderItemIndex++, headerItem->text(0)); // project name
0140     }
0141     newHeaderItem->setText(newHeaderItemIndex++, headerItem->text(1)); // database
0142     if (d->showConnectionColumns) {
0143         newHeaderItem->setText(newHeaderItemIndex++, headerItem->text(2)); // type
0144         newHeaderItem->setText(newHeaderItemIndex++, headerItem->text(3)); // connection
0145     }
0146     list()->setHeaderItem(newHeaderItem);
0147     setFocusProxy(list());
0148 
0149     //show projects
0150     setProjectSet(d->prj_set);
0151     connect(list(), SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
0152             this, SLOT(slotItemExecuted(QTreeWidgetItem*)));
0153     connect(list(), SIGNAL(itemSelectionChanged()),
0154             this, SLOT(slotItemSelected()));
0155 }
0156 
0157 /*!
0158  *  Destroys the object and frees any allocated resources
0159  */
0160 KexiProjectSelectorWidget::~KexiProjectSelectorWidget()
0161 {
0162     delete d;
0163 }
0164 
0165 KexiProjectData* KexiProjectSelectorWidget::selectedProjectData() const
0166 {
0167     QList<QTreeWidgetItem *> items = list()->selectedItems();
0168     if (items.isEmpty())
0169         return 0;
0170     ProjectDataLVItem *item = static_cast<ProjectDataLVItem*>(items.first());
0171     if (item)
0172         return item->data;
0173     return 0;
0174 }
0175 
0176 void KexiProjectSelectorWidget::slotItemExecuted(QTreeWidgetItem *item)
0177 {
0178     if (!d->selectable)
0179         return;
0180     ProjectDataLVItem *ditem = static_cast<ProjectDataLVItem*>(item);
0181     if (ditem)
0182         emit projectExecuted(ditem->data);
0183 }
0184 
0185 void KexiProjectSelectorWidget::slotItemExecuted()
0186 {
0187     if (!d->selectable)
0188         return;
0189     QList<QTreeWidgetItem *> items = list()->selectedItems();
0190     if (items.isEmpty())
0191         return;
0192     slotItemExecuted(items.first());
0193 }
0194 
0195 void KexiProjectSelectorWidget::slotItemSelected()
0196 {
0197     if (!d->selectable)
0198         return;
0199     QList<QTreeWidgetItem *> items = list()->selectedItems();
0200     ProjectDataLVItem *ditem = static_cast<ProjectDataLVItem*>(items.isEmpty() ? 0 : items.first());
0201     emit selectionChanged(ditem ? ditem->data : 0);
0202 }
0203 
0204 void KexiProjectSelectorWidget::setProjectSet(KexiProjectSet* prj_set)
0205 {
0206     if (prj_set) {
0207         //old list
0208         list()->clear();
0209     }
0210     d->prj_set = prj_set;
0211     if (!d->prj_set)
0212         return;
0213 //! @todo what with project set's ownership?
0214     if (d->prj_set->result().isError()) {
0215         qDebug() << "d->prj_set->error()" << d->prj_set->result();
0216         return;
0217     }
0218     KDbDriverManager manager;
0219     KexiProjectData::List prjlist = d->prj_set->list();
0220     foreach(KexiProjectData* data, prjlist) {
0221         KDbMessageGuard mg(manager.resultable());
0222         const KDbDriverMetaData *driverMetaData = manager.driverMetaData(data->connectionData()->driverId());
0223         if (driverMetaData) {
0224             ProjectDataLVItem *item = new ProjectDataLVItem(data, *driverMetaData, this);
0225             if (!d->selectable) {
0226                 Qt::ItemFlags flags = item->flags();
0227                 (flags |= Qt::ItemIsSelectable) ^= Qt::ItemIsSelectable;
0228                 item->setFlags(flags);
0229             }
0230             if (driverMetaData->isFileBased())
0231                 item->setIcon(0, d->fileicon);
0232             else
0233                 item->setIcon(0, d->dbicon);
0234         }
0235         else {
0236             qWarning() << "no driver found for" << data->connectionData()->driverId();
0237         }
0238     }
0239     list()->setSortingEnabled(true);
0240     list()->sortItems(0, Qt::AscendingOrder);
0241     list()->resizeColumnToContents(0);
0242     if (list()->topLevelItemCount() > 0) {
0243         list()->topLevelItem(0)->setSelected(true);
0244     }
0245 }
0246 
0247 KexiProjectSet *KexiProjectSelectorWidget::projectSet() {
0248     return d->prj_set;
0249 }
0250 
0251 void KexiProjectSelectorWidget::setSelectable(bool set)
0252 {
0253     if (d->selectable == set)
0254         return;
0255     d->selectable = set;
0256     //update items' state
0257     QTreeWidgetItemIterator it(list());
0258     while (*it) {
0259         Qt::ItemFlags flags = (*it)->flags();
0260         flags |= Qt::ItemIsSelectable;
0261         if (!d->selectable)
0262             flags ^= Qt::ItemIsSelectable;
0263         (*it)->setFlags(flags);
0264     }
0265 }
0266 
0267 bool KexiProjectSelectorWidget::isSelectable() const
0268 {
0269     return d->selectable;
0270 }
0271 
0272 QLabel *KexiProjectSelectorWidget::label() const
0273 {
0274     return Ui_KexiProjectSelector::label;
0275 }
0276 
0277 QTreeWidget* KexiProjectSelectorWidget::list() const
0278 {
0279     return Ui_KexiProjectSelector::list;
0280 }
0281 
0282 bool KexiProjectSelectorWidget::eventFilter(QObject* watched, QEvent* event)
0283 {
0284     if (event->type() == QEvent::KeyPress) {
0285         QKeyEvent *ke = static_cast<QKeyEvent*>(event);
0286         if ((ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return)
0287             && ke->modifiers() == Qt::NoModifier)
0288         {
0289             slotItemExecuted();
0290             return true;
0291         }
0292     }
0293     return QWidget::eventFilter(watched, event);
0294 }
0295 
0296 /*================================================================*/
0297 
0298 KexiProjectSelectorDialog::KexiProjectSelectorDialog(QWidget *parent,
0299         const KDbConnectionData& cdata,
0300         bool showProjectNameColumn, bool showConnectionColumns)
0301         : KPageDialog(parent)
0302         , d(new Private)
0303 {
0304     setWindowTitle(xi18nc("@title:window", "Open Project"));
0305     KDbConnectionData _cdata(cdata);
0306     // errors are handled in KexiStartupHandler::selectProject() ...
0307     KexiProjectSet *prj_set = new KexiProjectSet;
0308     init(prj_set, showProjectNameColumn, showConnectionColumns);
0309     KGuiItem okItem(xi18nc("@action:button", "&Open"), koIconName("document-open"),
0310                     xi18n("Open Database Connection"));
0311     KGuiItem::assign(button(QDialogButtonBox::Ok), okItem);
0312 
0313     d->sel->label()->setText(
0314         xi18n("Select a project on <resource>%1</resource> database server to open:",
0315               _cdata.toUserVisibleString(KDbConnectionData::UserVisibleStringOption::None)));
0316 }
0317 
0318 KexiProjectSelectorDialog::~KexiProjectSelectorDialog()
0319 {
0320     delete d;
0321 }
0322 
0323 void KexiProjectSelectorDialog::init(KexiProjectSet* prj_set, bool showProjectNameColumn,
0324                                      bool showConnectionColumns)
0325 {
0326     setObjectName("KexiProjectSelectorDialog");
0327     setModal(true);
0328     setStandardButtons(
0329 #ifdef KEXI_SHOW_UNFINISHED
0330         //! @todo re-add Help when doc is available
0331         QDialogButtonBox::Help |
0332 #endif
0333         QDialogButtonBox::Ok | QDialogButtonBox::Cancel
0334     );
0335     button(QDialogButtonBox::Ok)->setDefault(true);
0336     setFaceType(Plain);
0337     setSizeGripEnabled(true);
0338 
0339     d->sel = new KexiProjectSelectorWidget(this, prj_set,
0340                                           showProjectNameColumn, showConnectionColumns);
0341     //! @todo KEXI3 test this
0342     addPage(d->sel, QString());
0343     setWindowIcon(d->sel->windowIcon());
0344     d->sel->setFocus();
0345 
0346     connect(d->sel, SIGNAL(projectExecuted(KexiProjectData*)),
0347             this, SLOT(slotProjectExecuted(KexiProjectData*)));
0348     connect(d->sel, SIGNAL(selectionChanged(KexiProjectData*)),
0349             this, SLOT(slotProjectSelectionChanged(KexiProjectData*)));
0350 }
0351 
0352 KexiProjectData* KexiProjectSelectorDialog::selectedProjectData() const
0353 {
0354     return d->sel->selectedProjectData();
0355 }
0356 
0357 void KexiProjectSelectorDialog::slotProjectExecuted(KexiProjectData*)
0358 {
0359     accept();
0360 }
0361 
0362 void KexiProjectSelectorDialog::slotProjectSelectionChanged(KexiProjectData* pdata)
0363 {
0364     button(QDialogButtonBox::Ok)->setEnabled(pdata);
0365 }
0366 
0367 void KexiProjectSelectorDialog::showEvent(QShowEvent * event)
0368 {
0369     KPageDialog::showEvent(event);
0370     //! @todo KPageDialog::centerOnScreen(this);
0371 }
0372 
0373 KexiProjectSet* KexiProjectSelectorDialog::projectSet() const
0374 {
0375     return d->sel->projectSet();
0376 }