~ubuntu-branches/debian/sid/kexi/sid

« back to all changes in this revision

Viewing changes to src/widget/relations/KexiRelationsView.cpp

  • Committer: Package Import Robot
  • Author(s): Pino Toscano
  • Date: 2017-06-24 20:10:10 UTC
  • Revision ID: package-import@ubuntu.com-20170624201010-5lrzd5r2vwthwifp
Tags: upstream-3.0.1.1
ImportĀ upstreamĀ versionĀ 3.0.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of the KDE project
 
2
   Copyright (C) 2002   Lucijan Busch <lucijan@gmx.at>
 
3
   Copyright (C) 2003   Joseph Wenninger<jowenn@kde.org>
 
4
   Copyright (C) 2003-2007 Jarosław Staniek <staniek@kde.org>
 
5
 
 
6
   This program is free software; you can redistribute it and/or
 
7
   modify it under the terms of the GNU Library General Public
 
8
   License as published by the Free Software Foundation; either
 
9
   version 2 of the License, or (at your option) any later version.
 
10
 
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
   Library General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU Library General Public License
 
17
   along with this program; see the file COPYING.  If not, write to
 
18
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
19
 * Boston, MA 02110-1301, USA.
 
20
*/
 
21
 
 
22
#include "KexiRelationsView.h"
 
23
#include <KexiIcon.h>
 
24
#include <kexiutils/utils.h>
 
25
#include <kexiproject.h>
 
26
#include <KexiMainWindowIface.h>
 
27
#include "KexiRelationsScrollArea.h"
 
28
#include "KexiRelationsConnection.h"
 
29
 
 
30
#include <KDbConnection>
 
31
#include <KDbTableOrQuerySchema>
 
32
 
 
33
#include <KComboBox>
 
34
#include <KLocalizedString>
 
35
 
 
36
#include <QTimer>
 
37
#include <QHBoxLayout>
 
38
#include <QLabel>
 
39
#include <QGridLayout>
 
40
#include <QMenu>
 
41
#include <QPushButton>
 
42
#include <QDebug>
 
43
 
 
44
//! @internal
 
45
class KexiRelationsView::Private
 
46
{
 
47
public:
 
48
    Private()
 
49
    {
 
50
    }
 
51
 
 
52
    KComboBox *tableCombo;
 
53
    QPushButton *btnAdd;
 
54
    KexiRelationsScrollArea *scrollArea;
 
55
    KDbConnection *conn;
 
56
 
 
57
    QMenu *tableQueryPopup; //!< over table/query
 
58
    QMenu *connectionPopup; //!< over connection
 
59
    QMenu *areaPopup; //!< over outer area
 
60
    QAction *openSelectedTableAction, *designSelectedTableAction,
 
61
    *appendSelectedFieldAction, *appendSelectedFieldsAction, *hideTableAction;
 
62
};
 
63
 
 
64
//---------------
 
65
 
 
66
KexiRelationsView::KexiRelationsView(QWidget *parent)
 
67
        : KexiView(parent)
 
68
        , d(new Private)
 
69
{
 
70
    QWidget *mainWidget = new QWidget(this);
 
71
    QGridLayout *g = new QGridLayout(mainWidget);
 
72
    g->setContentsMargins(0, 0, 0, 0);
 
73
    g->setSpacing(KexiUtils::spacingHint());
 
74
 
 
75
    QWidget *horWidget = new QWidget(mainWidget);
 
76
    QHBoxLayout *hlyr = new QHBoxLayout(horWidget);
 
77
    hlyr->setContentsMargins(0, 0, 0, 0);
 
78
    g->addWidget(horWidget, 0, 0);
 
79
 
 
80
    d->tableCombo = new KComboBox(horWidget);
 
81
    d->tableCombo->setObjectName("tables_combo");
 
82
    d->tableCombo->setMinimumWidth(QFontMetrics(font()).width("w")*20);
 
83
    d->tableCombo->setInsertPolicy(QComboBox::NoInsert);
 
84
    d->tableCombo->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred));
 
85
    QLabel *lbl = new QLabel(xi18n("Table:"), horWidget);
 
86
    lbl->setBuddy(d->tableCombo);
 
87
    lbl->setIndent(3);
 
88
    hlyr->addWidget(lbl);
 
89
    hlyr->addWidget(d->tableCombo);
 
90
 
 
91
    d->btnAdd = new QPushButton(xi18nc("Insert table/query into relations view", "&Insert"), horWidget);
 
92
    hlyr->addWidget(d->btnAdd);
 
93
    hlyr->addStretch(1);
 
94
    connect(d->btnAdd, SIGNAL(clicked()), this, SLOT(slotAddTable()));
 
95
 
 
96
    d->scrollArea = new KexiRelationsScrollArea(mainWidget);
 
97
    d->scrollArea->setObjectName("scroll_area");
 
98
    setViewWidget(mainWidget, false/* no focus proxy */);
 
99
    setFocusProxy(d->scrollArea);
 
100
    g->addWidget(d->scrollArea, 1, 0);
 
101
 
 
102
    //actions
 
103
    d->tableQueryPopup = new QMenu(this);
 
104
    d->tableQueryPopup->setObjectName("tableQueryPopup");
 
105
    connect(d->tableQueryPopup, SIGNAL(aboutToShow()), this, SLOT(aboutToShowPopupMenu()));
 
106
 
 
107
    d->hideTableAction = plugSharedAction("edit_delete", xi18n("&Hide Table"), d->tableQueryPopup);
 
108
    if (d->hideTableAction)
 
109
        d->hideTableAction->setIcon(QIcon());
 
110
 
 
111
    d->connectionPopup = new QMenu(this);
 
112
    d->connectionPopup->setObjectName("connectionPopup");
 
113
    connect(d->connectionPopup, SIGNAL(aboutToShow()), this, SLOT(aboutToShowPopupMenu()));
 
114
 
 
115
//! @todo areaPopup
 
116
    d->areaPopup = new QMenu(this);
 
117
    d->areaPopup->setObjectName("areaPopup");
 
118
 
 
119
    d->appendSelectedFieldAction = new QAction(KexiIcon("add-field"), xi18n("&Append Field"), this);
 
120
    d->appendSelectedFieldAction->setObjectName("relationsview_appendField");
 
121
    connect(d->appendSelectedFieldAction, SIGNAL(triggered()),
 
122
            this, SLOT(appendSelectedFields()));
 
123
 
 
124
    d->appendSelectedFieldsAction = new QAction(KexiIcon("add-field"), xi18n("&Append Fields"), this);
 
125
    d->appendSelectedFieldsAction->setObjectName("relationsview_appendFields");
 
126
    connect(d->appendSelectedFieldsAction, SIGNAL(triggered()),
 
127
            this, SLOT(appendSelectedFields()));
 
128
 
 
129
    d->openSelectedTableAction = new QAction(koIcon("document-open"), xi18n("&Open Table"), this);
 
130
    d->openSelectedTableAction->setObjectName("relationsview_openTable");
 
131
    connect(d->openSelectedTableAction, SIGNAL(triggered()),
 
132
            this, SLOT(openSelectedTable()));
 
133
 
 
134
    d->designSelectedTableAction = new QAction(koIcon("document-properties"), xi18n("&Design Table"), this);
 
135
    connect(d->designSelectedTableAction, SIGNAL(triggered()),
 
136
            this, SLOT(designSelectedTable()));
 
137
    d->designSelectedTableAction->setObjectName("relationsview_designTable");
 
138
 
 
139
    plugSharedAction("edit_delete", this, SLOT(removeSelectedObject()));
 
140
 
 
141
    connect(d->scrollArea, SIGNAL(tableViewGotFocus()),
 
142
            this, SLOT(tableViewGotFocus()));
 
143
    connect(d->scrollArea, SIGNAL(connectionViewGotFocus()),
 
144
            this, SLOT(connectionViewGotFocus()));
 
145
    connect(d->scrollArea, SIGNAL(emptyAreaGotFocus()),
 
146
            this, SLOT(emptyAreaGotFocus()));
 
147
    connect(d->scrollArea, SIGNAL(tableContextMenuRequest(QPoint)),
 
148
            this, SLOT(tableContextMenuRequest(QPoint)));
 
149
    connect(d->scrollArea, SIGNAL(connectionContextMenuRequest(QPoint)),
 
150
            this, SLOT(connectionContextMenuRequest(QPoint)));
 
151
    connect(d->scrollArea, SIGNAL(tableHidden(KDbTableSchema*)),
 
152
            this, SLOT(slotTableHidden(KDbTableSchema*)));
 
153
    connect(d->scrollArea, SIGNAL(tablePositionChanged(KexiRelationsTableContainer*)),
 
154
            this, SIGNAL(tablePositionChanged(KexiRelationsTableContainer*)));
 
155
    connect(d->scrollArea, SIGNAL(aboutConnectionRemove(KexiRelationsConnection*)),
 
156
            this, SIGNAL(aboutConnectionRemove(KexiRelationsConnection*)));
 
157
 
 
158
    //! @todo
 
159
#if 0
 
160
    if (!embedd) {
 
161
        /*todo  setContextHelp(xi18n("Relations"), xi18n("To create a relationship simply drag the source field onto the target field. "
 
162
              "An arrowhead is used to show which table is the parent (master) and which table is the child (slave) in the relationship."));*/
 
163
    }
 
164
#endif
 
165
 
 
166
#ifdef TESTING_KexiRelationWidget
 
167
    for (int i = 0;i < (int)d->db->tableNames().count();i++)
 
168
        QTimer::singleShot(100, this, SLOT(slotAddTable()));
 
169
#endif
 
170
 
 
171
    invalidateActions();
 
172
}
 
173
 
 
174
KexiRelationsView::~KexiRelationsView()
 
175
{
 
176
    delete d;
 
177
}
 
178
 
 
179
TablesHash* KexiRelationsView::tables() const
 
180
{
 
181
    return d->scrollArea->tables();
 
182
}
 
183
 
 
184
KexiRelationsTableContainer* KexiRelationsView::table(const QString& name) const
 
185
{
 
186
    return d->scrollArea->tables()->value(name);
 
187
}
 
188
 
 
189
const QSet<KexiRelationsConnection*>* KexiRelationsView::relationsConnections() const
 
190
{
 
191
    return d->scrollArea->relationsConnections();
 
192
}
 
193
 
 
194
void
 
195
KexiRelationsView::slotAddTable()
 
196
{
 
197
    if (d->tableCombo->currentIndex() == -1)
 
198
        return;
 
199
    const QString tname = d->tableCombo->itemText(d->tableCombo->currentIndex());
 
200
    KDbTableSchema *t = d->conn->tableSchema(tname);
 
201
    addTable(t);
 
202
}
 
203
 
 
204
void
 
205
KexiRelationsView::addTable(KDbTableSchema *t, const QRect &rect)
 
206
{
 
207
    if (!t)
 
208
        return;
 
209
    if (!d->scrollArea->tableContainer(t)) {
 
210
        KexiRelationsTableContainer *c = d->scrollArea->addTableContainer(t, rect);
 
211
        qDebug() << "adding table" << t->name();
 
212
        if (!c)
 
213
            return;
 
214
        connect(c, SIGNAL(fieldsDoubleClicked(KDbTableOrQuerySchema&,QStringList)),
 
215
                this, SIGNAL(appendFields(KDbTableOrQuerySchema&,QStringList)));
 
216
    }
 
217
 
 
218
    const QString tname = t->name().toLower();
 
219
    const int count = d->tableCombo->count();
 
220
    int i = 0;
 
221
    for (; i < count; i++) {
 
222
        if (d->tableCombo->itemText(i).toLower() == tname)
 
223
            break;
 
224
    }
 
225
    if (i < count) {
 
226
        int oi = d->tableCombo->currentIndex();
 
227
        qDebug() << "removing a table from the combo box";
 
228
        d->tableCombo->removeItem(i);
 
229
        if (d->tableCombo->count() > 0) {
 
230
            if (oi >= d->tableCombo->count()) {
 
231
                oi = d->tableCombo->count() - 1;
 
232
            }
 
233
            d->tableCombo->setCurrentIndex(oi);
 
234
        } else {
 
235
            d->tableCombo->setEnabled(false);
 
236
            d->btnAdd->setEnabled(false);
 
237
        }
 
238
    }
 
239
    emit tableAdded(t);
 
240
}
 
241
 
 
242
void
 
243
KexiRelationsView::addConnection(const SourceConnection& conn)
 
244
{
 
245
    d->scrollArea->addConnection(conn);
 
246
}
 
247
 
 
248
void
 
249
KexiRelationsView::addTable(const QString& t)
 
250
{
 
251
    for (int i = 0; i < d->tableCombo->count(); i++) {
 
252
        if (d->tableCombo->itemText(i) == t) {
 
253
            d->tableCombo->setCurrentIndex(i);
 
254
            slotAddTable();
 
255
        }
 
256
    }
 
257
}
 
258
 
 
259
void KexiRelationsView::tableViewGotFocus()
 
260
{
 
261
    invalidateActions();
 
262
}
 
263
 
 
264
void KexiRelationsView::connectionViewGotFocus()
 
265
{
 
266
    invalidateActions();
 
267
}
 
268
 
 
269
void KexiRelationsView::emptyAreaGotFocus()
 
270
{
 
271
    invalidateActions();
 
272
}
 
273
 
 
274
void KexiRelationsView::tableContextMenuRequest(const QPoint& pos)
 
275
{
 
276
    invalidateActions();
 
277
    executePopup(pos);
 
278
}
 
279
 
 
280
void KexiRelationsView::connectionContextMenuRequest(const QPoint& pos)
 
281
{
 
282
    invalidateActions();
 
283
    executePopup(pos);
 
284
}
 
285
 
 
286
void KexiRelationsView::emptyAreaContextMenuRequest(const QPoint& /*pos*/)
 
287
{
 
288
    invalidateActions();
 
289
    //! @todo
 
290
}
 
291
 
 
292
void KexiRelationsView::invalidateActions()
 
293
{
 
294
    setAvailable("edit_delete", d->scrollArea->selectedConnection() || d->scrollArea->focusedTableContainer());
 
295
}
 
296
 
 
297
void KexiRelationsView::executePopup(QPoint pos)
 
298
{
 
299
    if (pos == QPoint(-1, -1)) {
 
300
        pos = mapToGlobal(
 
301
                  d->scrollArea->focusedTableContainer() ? d->scrollArea->focusedTableContainer()->pos() + d->scrollArea->focusedTableContainer()->rect().center() : rect().center());
 
302
    }
 
303
    if (d->scrollArea->focusedTableContainer())
 
304
        d->tableQueryPopup->exec(pos);
 
305
    else if (d->scrollArea->selectedConnection())
 
306
        d->connectionPopup->exec(pos);
 
307
}
 
308
 
 
309
void KexiRelationsView::removeSelectedObject()
 
310
{
 
311
    d->scrollArea->removeSelectedObject();
 
312
}
 
313
 
 
314
void KexiRelationsView::appendSelectedFields()
 
315
{
 
316
    KexiRelationsTableContainer* currentTableContainer = d->scrollArea->focusedTableContainer();
 
317
    if (!currentTableContainer)
 
318
        return;
 
319
    emit appendFields(*currentTableContainer->schema(), currentTableContainer->selectedFieldNames());
 
320
}
 
321
 
 
322
void KexiRelationsView::openSelectedTable()
 
323
{
 
324
    /*! @todo what about query? */
 
325
    if (!d->scrollArea->focusedTableContainer() || !d->scrollArea->focusedTableContainer()->schema()->table())
 
326
        return;
 
327
    bool openingCancelled;
 
328
    KexiMainWindowIface::global()->openObject(
 
329
        "kexi/table", d->scrollArea->focusedTableContainer()->schema()->name(),
 
330
        Kexi::DataViewMode, &openingCancelled);
 
331
}
 
332
 
 
333
void KexiRelationsView::designSelectedTable()
 
334
{
 
335
    /*! @todo what about query? */
 
336
    if (!d->scrollArea->focusedTableContainer() || !d->scrollArea->focusedTableContainer()->schema()->table())
 
337
        return;
 
338
    bool openingCancelled;
 
339
    KexiMainWindowIface::global()->openObject(
 
340
        "kexi/table", d->scrollArea->focusedTableContainer()->schema()->name(),
 
341
        Kexi::DesignViewMode, &openingCancelled);
 
342
}
 
343
 
 
344
QSize KexiRelationsView::sizeHint() const
 
345
{
 
346
    return d->scrollArea->sizeHint();
 
347
}
 
348
 
 
349
void KexiRelationsView::slotTableHidden(KDbTableSchema* table)
 
350
{
 
351
    const QString &t = table->name().toLower();
 
352
    int i;
 
353
    for (i = 0; i < d->tableCombo->count() && t > d->tableCombo->itemText(i).toLower(); i++) {
 
354
    }
 
355
    d->tableCombo->insertItem(i, table->name());
 
356
    if (!d->tableCombo->isEnabled()) {
 
357
        d->tableCombo->setCurrentIndex(0);
 
358
        d->tableCombo->setEnabled(true);
 
359
        d->btnAdd->setEnabled(true);
 
360
    }
 
361
 
 
362
    emit tableHidden(table);
 
363
}
 
364
 
 
365
void KexiRelationsView::aboutToShowPopupMenu()
 
366
{
 
367
    KexiRelationsTableContainer* currentTableContainer = d->scrollArea->focusedTableContainer();
 
368
    if (currentTableContainer /*&& currentTableContainer->schema()->table()*/) {
 
369
        /*! @todo what about query? */
 
370
        d->tableQueryPopup->clear();
 
371
        d->tableQueryPopup->addSection(KexiIcon("table"),
 
372
                                     QString(d->scrollArea->focusedTableContainer()->schema()->name()) + " : " + xi18n("Table"));
 
373
        QStringList selectedFieldNames(currentTableContainer->selectedFieldNames());
 
374
        if (currentTableContainer && !selectedFieldNames.isEmpty()) {
 
375
            if (selectedFieldNames.count() > 1 || selectedFieldNames.first() == "*") //multiple
 
376
                d->tableQueryPopup->addAction(d->appendSelectedFieldsAction);
 
377
            else
 
378
                d->tableQueryPopup->addAction(d->appendSelectedFieldAction);
 
379
            d->tableQueryPopup->addSeparator();
 
380
        }
 
381
        d->tableQueryPopup->addAction(d->openSelectedTableAction);
 
382
        d->tableQueryPopup->addAction(d->designSelectedTableAction);
 
383
        d->tableQueryPopup->addSeparator();
 
384
        d->tableQueryPopup->addAction(d->hideTableAction);
 
385
    } else if (d->scrollArea->selectedConnection()) {
 
386
        unplugSharedAction("edit_delete", d->connectionPopup);
 
387
        d->connectionPopup->clear();
 
388
        d->connectionPopup->addSection(QIcon(),
 
389
                                     d->scrollArea->selectedConnection()->toString() + " : " + xi18n("Relationship"));
 
390
        plugSharedAction("edit_delete", d->connectionPopup);
 
391
    }
 
392
}
 
393
 
 
394
bool KexiRelationsView::clear()
 
395
{
 
396
    d->scrollArea->clear();
 
397
    return setConnection(d->conn);
 
398
}
 
399
 
 
400
/*! Removes all coonections from the view. */
 
401
void KexiRelationsView::removeAllConnections()
 
402
{
 
403
    d->scrollArea->removeAllConnections();
 
404
}
 
405
 
 
406
bool KexiRelationsView::setConnection(KDbConnection *conn)
 
407
{
 
408
    d->tableCombo->clear();
 
409
    d->conn = conn;
 
410
    if (conn) {
 
411
        bool ok;
 
412
        QStringList result = d->conn->tableNames(false/*no system tables*/, &ok);
 
413
        if (!ok) {
 
414
            return false;
 
415
        }
 
416
        result.sort();
 
417
        d->tableCombo->addItems(result);
 
418
    }
 
419
    return true;
 
420
}
 
421
 
 
422
void
 
423
KexiRelationsView::objectCreated(const QString &mime, const QString& name)
 
424
{
 
425
    if (mime == "kexi/table" || mime == "kexi/query") {
 
426
//! @todo query?
 
427
        const int count = d->tableCombo->count();
 
428
        QString strName(name);
 
429
        int i = 0;
 
430
        for (; i < count && d->tableCombo->itemText(i) <= strName; i++) {
 
431
        }
 
432
        d->tableCombo->insertItem(i, name);
 
433
    }
 
434
}
 
435
 
 
436
void
 
437
KexiRelationsView::objectDeleted(const QString &mime, const QString& name)
 
438
{
 
439
    if (mime == "kexi/table" || mime == "kexi/query") {
 
440
        for (int i = 0; i < d->tableCombo->count(); i++) {
 
441
//! @todo query?
 
442
            if (d->tableCombo->itemText(i) == name) {
 
443
                d->tableCombo->removeItem(i);
 
444
                if (d->tableCombo->currentIndex() == i) {
 
445
                    if (i == (d->tableCombo->count() - 1))
 
446
                        d->tableCombo->setCurrentIndex(i - 1);
 
447
                    else
 
448
                        d->tableCombo->setCurrentIndex(i);
 
449
                }
 
450
                break;
 
451
            }
 
452
        }
 
453
    }
 
454
}
 
455
 
 
456
void
 
457
KexiRelationsView::objectRenamed(const QString &mime, const QString& name,
 
458
                                 const QString& newName)
 
459
{
 
460
    if (mime == "kexi/table" || mime == "kexi/query") {
 
461
        const int count = d->tableCombo->count();
 
462
        for (int i = 0; i < count; i++) {
 
463
//! @todo query?
 
464
            if (d->tableCombo->itemText(i) == name) {
 
465
                d->tableCombo->removeItem(i);
 
466
                int j = 0;
 
467
                for (; j < count && d->tableCombo->itemText(j) <= newName; j++) {
 
468
                }
 
469
                d->tableCombo->insertItem(j, newName);
 
470
                break;
 
471
            }
 
472
        }
 
473
    }
 
474
}
 
475
 
 
476
void
 
477
KexiRelationsView::hideAllTablesExcept(QList<KDbTableSchema*>* tables)
 
478
{
 
479
    d->scrollArea->hideAllTablesExcept(tables);
 
480
}
 
481