1 /* This file is part of the KDE project
2 Copyright (C) 2003-2011 Jarosław Staniek <staniek@kde.org>
3
4 This program 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 program 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 program; see the file COPYING. 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 "KexiProjectSelectorWidget.h"
21 #include <core/kexi.h>
22 #include <KexiIcon.h>
23
24 #include <KDbDriverManager>
25 #include <KDbDriverMetaData>
26 #include <KDbConnectionData>
27 #include <KDbUtils>
28 #include <KDbMessageHandler>
29
30 #include <KLocalizedString>
31 #include <KGuiItem>
32
33 #include <QDebug>
34 #include <QLabel>
35 #include <QPushButton>
36 #include <QKeyEvent>
37
38 #include <assert.h>
39
40 //! @internal
41 class Q_DECL_HIDDEN KexiProjectSelectorWidget::Private
42 {
43 public:
Private(KexiProjectSet * prj_set_)44 explicit Private(KexiProjectSet *prj_set_)
45 : prj_set(prj_set_)
46 {
47 selectable = true;
48 }
49
50 QIcon fileicon, dbicon;
51 bool showProjectNameColumn;
52 bool showConnectionColumns;
53 bool selectable;
54
55 KexiProjectSet *prj_set;
56 };
57
58 class Q_DECL_HIDDEN KexiProjectSelectorDialog::Private
59 {
60 public:
Private()61 Private() {}
62 KexiProjectSelectorWidget* sel;
63 };
64
65 /*================================================================*/
66
67 //! helper class
68 class ProjectDataLVItem : public QTreeWidgetItem
69 {
70 public:
ProjectDataLVItem(KexiProjectData * d,const KDbDriverMetaData & driverMetaData,KexiProjectSelectorWidget * selector)71 ProjectDataLVItem(KexiProjectData *d,
72 const KDbDriverMetaData &driverMetaData,
73 KexiProjectSelectorWidget *selector)
74 : QTreeWidgetItem(selector->list())
75 , data(d)
76 {
77 int colnum = 0;
78 const KDbConnectionData cdata = *data->connectionData();
79 if (selector->d->showProjectNameColumn)
80 setText(colnum++, data->caption() + " ");
81
82 setText(colnum++, data->databaseName() + " ");
83
84 if (selector->d->showConnectionColumns) {
85 QString driverName = driverMetaData.name();
86 if (driverName.isEmpty()) {
87 KDbDriverManager manager;
88 const KDbDriverMetaData *driverMetaDataFromCdata = manager.driverMetaData(cdata.driverId());
89 if (driverMetaDataFromCdata) {
90 driverName = driverMetaDataFromCdata->name();
91 }
92 }
93 if (driverMetaData.isFileBased()) {
94 setText(colnum++, xi18n("File (%1)", driverName) + " ");
95 } else {
96 setText(colnum++, driverName + " ");
97 }
98 QString conn;
99 if (cdata.caption().isEmpty()) {
100 conn = cdata.toUserVisibleString();
101 }
102 else {
103 conn = xi18nc("caption: server_info", "%1: %2",
104 cdata.caption(), cdata.toUserVisibleString());
105 }
106 setText(colnum++, conn + " ");
107 }
108 }
~ProjectDataLVItem()109 ~ProjectDataLVItem() {}
110
111 KexiProjectData *data;
112 };
113
114 /*================================================================*/
115
116 /*!
117 * Constructs a KexiProjectSelector which is a child of 'parent', with the
118 * name 'name' and widget flags set to 'f'
119 */
KexiProjectSelectorWidget(QWidget * parent,KexiProjectSet * prj_set,bool showProjectNameColumn,bool showConnectionColumns)120 KexiProjectSelectorWidget::KexiProjectSelectorWidget(QWidget* parent,
121 KexiProjectSet* prj_set, bool showProjectNameColumn, bool showConnectionColumns)
122 : QWidget(parent)
123 , d(new Private(prj_set))
124 {
125 setupUi(this);
126 setObjectName("KexiProjectSelectorWidget");
127 d->showProjectNameColumn = showProjectNameColumn;
128 d->showConnectionColumns = showConnectionColumns;
129 list()->installEventFilter(this);
130
131 d->fileicon = Kexi::defaultFileBasedDriverIcon();
132 setWindowIcon(d->fileicon);
133 d->dbicon = koIcon("server-database");
134
135 QTreeWidgetItem *headerItem = list()->headerItem();
136 QTreeWidgetItem *newHeaderItem = new QTreeWidgetItem;
137 int newHeaderItemIndex = 0;
138 if (d->showProjectNameColumn) {
139 newHeaderItem->setText(newHeaderItemIndex++, headerItem->text(0)); // project name
140 }
141 newHeaderItem->setText(newHeaderItemIndex++, headerItem->text(1)); // database
142 if (d->showConnectionColumns) {
143 newHeaderItem->setText(newHeaderItemIndex++, headerItem->text(2)); // type
144 newHeaderItem->setText(newHeaderItemIndex++, headerItem->text(3)); // connection
145 }
146 list()->setHeaderItem(newHeaderItem);
147 setFocusProxy(list());
148
149 //show projects
150 setProjectSet(d->prj_set);
151 connect(list(), SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
152 this, SLOT(slotItemExecuted(QTreeWidgetItem*)));
153 connect(list(), SIGNAL(itemSelectionChanged()),
154 this, SLOT(slotItemSelected()));
155 }
156
157 /*!
158 * Destroys the object and frees any allocated resources
159 */
~KexiProjectSelectorWidget()160 KexiProjectSelectorWidget::~KexiProjectSelectorWidget()
161 {
162 delete d;
163 }
164
selectedProjectData() const165 KexiProjectData* KexiProjectSelectorWidget::selectedProjectData() const
166 {
167 QList<QTreeWidgetItem *> items = list()->selectedItems();
168 if (items.isEmpty())
169 return 0;
170 ProjectDataLVItem *item = static_cast<ProjectDataLVItem*>(items.first());
171 if (item)
172 return item->data;
173 return 0;
174 }
175
slotItemExecuted(QTreeWidgetItem * item)176 void KexiProjectSelectorWidget::slotItemExecuted(QTreeWidgetItem *item)
177 {
178 if (!d->selectable)
179 return;
180 ProjectDataLVItem *ditem = static_cast<ProjectDataLVItem*>(item);
181 if (ditem)
182 emit projectExecuted(ditem->data);
183 }
184
slotItemExecuted()185 void KexiProjectSelectorWidget::slotItemExecuted()
186 {
187 if (!d->selectable)
188 return;
189 QList<QTreeWidgetItem *> items = list()->selectedItems();
190 if (items.isEmpty())
191 return;
192 slotItemExecuted(items.first());
193 }
194
slotItemSelected()195 void KexiProjectSelectorWidget::slotItemSelected()
196 {
197 if (!d->selectable)
198 return;
199 QList<QTreeWidgetItem *> items = list()->selectedItems();
200 ProjectDataLVItem *ditem = static_cast<ProjectDataLVItem*>(items.isEmpty() ? 0 : items.first());
201 emit selectionChanged(ditem ? ditem->data : 0);
202 }
203
setProjectSet(KexiProjectSet * prj_set)204 void KexiProjectSelectorWidget::setProjectSet(KexiProjectSet* prj_set)
205 {
206 if (prj_set) {
207 //old list
208 list()->clear();
209 }
210 d->prj_set = prj_set;
211 if (!d->prj_set)
212 return;
213 //! @todo what with project set's ownership?
214 if (d->prj_set->result().isError()) {
215 qDebug() << "d->prj_set->error()" << d->prj_set->result();
216 return;
217 }
218 KDbDriverManager manager;
219 KexiProjectData::List prjlist = d->prj_set->list();
220 foreach(KexiProjectData* data, prjlist) {
221 KDbMessageGuard mg(manager.resultable());
222 const KDbDriverMetaData *driverMetaData = manager.driverMetaData(data->connectionData()->driverId());
223 if (driverMetaData) {
224 ProjectDataLVItem *item = new ProjectDataLVItem(data, *driverMetaData, this);
225 if (!d->selectable) {
226 Qt::ItemFlags flags = item->flags();
227 (flags |= Qt::ItemIsSelectable) ^= Qt::ItemIsSelectable;
228 item->setFlags(flags);
229 }
230 if (driverMetaData->isFileBased())
231 item->setIcon(0, d->fileicon);
232 else
233 item->setIcon(0, d->dbicon);
234 }
235 else {
236 qWarning() << "no driver found for" << data->connectionData()->driverId();
237 }
238 }
239 list()->setSortingEnabled(true);
240 list()->sortItems(0, Qt::AscendingOrder);
241 list()->resizeColumnToContents(0);
242 if (list()->topLevelItemCount() > 0) {
243 list()->topLevelItem(0)->setSelected(true);
244 }
245 }
246
projectSet()247 KexiProjectSet *KexiProjectSelectorWidget::projectSet() {
248 return d->prj_set;
249 }
250
setSelectable(bool set)251 void KexiProjectSelectorWidget::setSelectable(bool set)
252 {
253 if (d->selectable == set)
254 return;
255 d->selectable = set;
256 //update items' state
257 QTreeWidgetItemIterator it(list());
258 while (*it) {
259 Qt::ItemFlags flags = (*it)->flags();
260 flags |= Qt::ItemIsSelectable;
261 if (!d->selectable)
262 flags ^= Qt::ItemIsSelectable;
263 (*it)->setFlags(flags);
264 }
265 }
266
isSelectable() const267 bool KexiProjectSelectorWidget::isSelectable() const
268 {
269 return d->selectable;
270 }
271
label() const272 QLabel *KexiProjectSelectorWidget::label() const
273 {
274 return Ui_KexiProjectSelector::label;
275 }
276
list() const277 QTreeWidget* KexiProjectSelectorWidget::list() const
278 {
279 return Ui_KexiProjectSelector::list;
280 }
281
eventFilter(QObject * watched,QEvent * event)282 bool KexiProjectSelectorWidget::eventFilter(QObject* watched, QEvent* event)
283 {
284 if (event->type() == QEvent::KeyPress) {
285 QKeyEvent *ke = static_cast<QKeyEvent*>(event);
286 if ((ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return)
287 && ke->modifiers() == Qt::NoModifier)
288 {
289 slotItemExecuted();
290 return true;
291 }
292 }
293 return QWidget::eventFilter(watched, event);
294 }
295
296 /*================================================================*/
297
KexiProjectSelectorDialog(QWidget * parent,const KDbConnectionData & cdata,bool showProjectNameColumn,bool showConnectionColumns)298 KexiProjectSelectorDialog::KexiProjectSelectorDialog(QWidget *parent,
299 const KDbConnectionData& cdata,
300 bool showProjectNameColumn, bool showConnectionColumns)
301 : KPageDialog(parent)
302 , d(new Private)
303 {
304 setWindowTitle(xi18nc("@title:window", "Open Project"));
305 KDbConnectionData _cdata(cdata);
306 // errors are handled in KexiStartupHandler::selectProject() ...
307 KexiProjectSet *prj_set = new KexiProjectSet;
308 init(prj_set, showProjectNameColumn, showConnectionColumns);
309 KGuiItem okItem(xi18nc("@action:button", "&Open"), koIconName("document-open"),
310 xi18n("Open Database Connection"));
311 KGuiItem::assign(button(QDialogButtonBox::Ok), okItem);
312
313 d->sel->label()->setText(
314 xi18n("Select a project on <resource>%1</resource> database server to open:",
315 _cdata.toUserVisibleString(KDbConnectionData::UserVisibleStringOption::None)));
316 }
317
~KexiProjectSelectorDialog()318 KexiProjectSelectorDialog::~KexiProjectSelectorDialog()
319 {
320 delete d;
321 }
322
init(KexiProjectSet * prj_set,bool showProjectNameColumn,bool showConnectionColumns)323 void KexiProjectSelectorDialog::init(KexiProjectSet* prj_set, bool showProjectNameColumn,
324 bool showConnectionColumns)
325 {
326 setObjectName("KexiProjectSelectorDialog");
327 setModal(true);
328 setStandardButtons(
329 #ifdef KEXI_SHOW_UNFINISHED
330 //! @todo re-add Help when doc is available
331 QDialogButtonBox::Help |
332 #endif
333 QDialogButtonBox::Ok | QDialogButtonBox::Cancel
334 );
335 button(QDialogButtonBox::Ok)->setDefault(true);
336 setFaceType(Plain);
337 setSizeGripEnabled(true);
338
339 d->sel = new KexiProjectSelectorWidget(this, prj_set,
340 showProjectNameColumn, showConnectionColumns);
341 //! @todo KEXI3 test this
342 addPage(d->sel, QString());
343 setWindowIcon(d->sel->windowIcon());
344 d->sel->setFocus();
345
346 connect(d->sel, SIGNAL(projectExecuted(KexiProjectData*)),
347 this, SLOT(slotProjectExecuted(KexiProjectData*)));
348 connect(d->sel, SIGNAL(selectionChanged(KexiProjectData*)),
349 this, SLOT(slotProjectSelectionChanged(KexiProjectData*)));
350 }
351
selectedProjectData() const352 KexiProjectData* KexiProjectSelectorDialog::selectedProjectData() const
353 {
354 return d->sel->selectedProjectData();
355 }
356
slotProjectExecuted(KexiProjectData *)357 void KexiProjectSelectorDialog::slotProjectExecuted(KexiProjectData*)
358 {
359 accept();
360 }
361
slotProjectSelectionChanged(KexiProjectData * pdata)362 void KexiProjectSelectorDialog::slotProjectSelectionChanged(KexiProjectData* pdata)
363 {
364 button(QDialogButtonBox::Ok)->setEnabled(pdata);
365 }
366
showEvent(QShowEvent * event)367 void KexiProjectSelectorDialog::showEvent(QShowEvent * event)
368 {
369 KPageDialog::showEvent(event);
370 //! @todo KPageDialog::centerOnScreen(this);
371 }
372
projectSet() const373 KexiProjectSet* KexiProjectSelectorDialog::projectSet() const
374 {
375 return d->sel->projectSet();
376 }
377