summaryrefslogtreecommitdiff
path: root/src/items/database
diff options
context:
space:
mode:
authorLukáš Lalinský <lalinsky@gmail.com>2008-12-07 18:10:23 +0100
committerLukáš Lalinský <lalinsky@gmail.com>2008-12-07 18:10:23 +0100
commit613647f385e6b7d0f1e3eba6d2b29f2d8baf7044 (patch)
tree03bf2e2cf52f3912ac256ce0fc85ae95a5c9e29c /src/items/database
parent0092b62413fa6a5727530f0eb5c5044a322870d3 (diff)
downloaddbmodel-613647f385e6b7d0f1e3eba6d2b29f2d8baf7044.tar.xz
Move database-specific code to items/database/
Diffstat (limited to 'src/items/database')
-rw-r--r--src/items/database/column.cpp68
-rw-r--r--src/items/database/column.h65
-rw-r--r--src/items/database/columnlist.cpp79
-rw-r--r--src/items/database/columnlist.h57
-rw-r--r--src/items/database/columnlistmodel.cpp208
-rw-r--r--src/items/database/columnlistmodel.h55
-rw-r--r--src/items/database/columnlistview.cpp103
-rw-r--r--src/items/database/columnlistview.h47
-rw-r--r--src/items/database/database.pri22
-rw-r--r--src/items/database/databaserelationship.cpp244
-rw-r--r--src/items/database/databaserelationship.h61
-rw-r--r--src/items/database/databasetable.cpp228
-rw-r--r--src/items/database/databasetable.h80
-rw-r--r--src/items/database/tableproperties.cpp97
-rw-r--r--src/items/database/tableproperties.h48
-rw-r--r--src/items/database/tableproperties.ui137
16 files changed, 1599 insertions, 0 deletions
diff --git a/src/items/database/column.cpp b/src/items/database/column.cpp
new file mode 100644
index 0000000..e8a355b
--- /dev/null
+++ b/src/items/database/column.cpp
@@ -0,0 +1,68 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#include "column.h"
+#include "columnlist.h"
+
+Column::Column(ColumnList *columnList)
+ : QObject(columnList), m_primaryKey(false), m_required(false)
+{
+}
+
+void
+Column::setName(const QString &name)
+{
+ if (m_name != name) {
+ m_name = name;
+ emit propertyChanged("name", name);
+ }
+}
+
+void
+Column::setNotes(const QString &notes)
+{
+ if (m_notes != notes) {
+ m_notes = notes;
+ emit propertyChanged("notes", notes);
+ }
+}
+
+void
+Column::setDataType(const QString &dataType)
+{
+ if (m_dataType != dataType) {
+ m_dataType = dataType;
+ emit propertyChanged("dataType", dataType);
+ }
+}
+
+void
+Column::setPrimaryKey(bool primaryKey)
+{
+ if (m_primaryKey != primaryKey) {
+ m_primaryKey = primaryKey;
+ emit propertyChanged("primaryKey", primaryKey);
+ }
+}
+
+void
+Column::setRequired(bool required)
+{
+ if (m_required != required) {
+ m_required = required;
+ emit propertyChanged("required", required);
+ }
+}
diff --git a/src/items/database/column.h b/src/items/database/column.h
new file mode 100644
index 0000000..2930efa
--- /dev/null
+++ b/src/items/database/column.h
@@ -0,0 +1,65 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#ifndef COLUMN_H
+#define COLUMN_H
+
+#include <QObject>
+#include <QString>
+#include "columnlist.h"
+
+class Column : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QString notes READ notes WRITE setNotes)
+ Q_PROPERTY(QString dataType READ dataType WRITE setDataType)
+ Q_PROPERTY(bool primaryKey READ isPrimaryKey WRITE setPrimaryKey)
+ Q_PROPERTY(bool required READ isRequired WRITE setRequired)
+
+public:
+
+ Column(ColumnList *columnList = 0);
+
+ ColumnList *columnList() const { return qobject_cast<ColumnList *>(parent()); }
+
+ QString name() const { return m_name; }
+ void setName(const QString &name);
+
+ QString notes() const { return m_notes; }
+ void setNotes(const QString &notes);
+
+ QString dataType() const { return m_dataType; }
+ void setDataType(const QString &dataType);
+
+ bool isPrimaryKey() const { return m_primaryKey; }
+ void setPrimaryKey(bool primaryKey);
+
+ bool isRequired() const { return m_required; }
+ void setRequired(bool required);
+
+signals:
+ void propertyChanged(const QString &name, const QVariant &value);
+
+private:
+ QString m_name;
+ QString m_notes;
+ QString m_dataType;
+ bool m_primaryKey;
+ bool m_required;
+};
+
+#endif
diff --git a/src/items/database/columnlist.cpp b/src/items/database/columnlist.cpp
new file mode 100644
index 0000000..b1ed623
--- /dev/null
+++ b/src/items/database/columnlist.cpp
@@ -0,0 +1,79 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#include <QDebug>
+#include "columnlist.h"
+#include "column.h"
+#include "databasetable.h"
+
+ColumnList::ColumnList(DatabaseTable *table)
+ : QObject(table)
+{
+}
+
+int
+ColumnList::insertColumn(int index, Column *column)
+{
+ Q_ASSERT(m_columns.contains(column) == false);
+ column->setParent(this);
+ connect(column, SIGNAL(propertyChanged(const QString &, const QVariant &)), this, SLOT(updateColumn(const QString &, const QVariant &)));
+ emit columnAboutToBeInserted(index);
+ m_columns.insert(index, column);
+ emit columnInserted(index);
+ return index;
+}
+
+int
+ColumnList::appendColumn(Column *column)
+{
+ return insertColumn(columnCount(), column);
+}
+
+int
+ColumnList::removeColumn(Column *column)
+{
+ int index = m_columns.indexOf(column);
+ removeColumn(index);
+ return index;
+}
+
+Column *
+ColumnList::removeColumn(int index)
+{
+ emit columnAboutToBeRemoved(index);
+ Column *column = m_columns.takeAt(index);
+ emit columnRemoved(index);
+ disconnect(column, 0, this, 0);
+ column->setParent(0);
+ return column;
+}
+
+void
+ColumnList::swapColumns(int oldIndex, int newIndex)
+{
+ m_columns.move(oldIndex, newIndex);
+ emit columnChanged(oldIndex);
+ emit columnChanged(newIndex);
+}
+
+void
+ColumnList::updateColumn(const QString &, const QVariant &)
+{
+ Column *column = qobject_cast<Column *>(sender());
+ int index = m_columns.indexOf(column);
+ Q_ASSERT(index != -1);
+ emit columnChanged(index);
+}
diff --git a/src/items/database/columnlist.h b/src/items/database/columnlist.h
new file mode 100644
index 0000000..51a25be
--- /dev/null
+++ b/src/items/database/columnlist.h
@@ -0,0 +1,57 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#ifndef COLUMNLIST_H
+#define COLUMNLIST_H
+
+#include <QAbstractTableModel>
+#include "databasetable.h"
+class Column;
+
+class ColumnList : public QObject
+{
+ Q_OBJECT
+
+public:
+ ColumnList(DatabaseTable *table);
+
+ DatabaseTable *table() { return qobject_cast<DatabaseTable *>(parent()); }
+
+ QList<Column *> columns() { return m_columns; }
+ int columnCount() const { return m_columns.size(); }
+ int indexOf(Column *column) const { return m_columns.indexOf(column); }
+ Column *column(int index) { return m_columns[index]; }
+ int insertColumn(int, Column *);
+ int appendColumn(Column *);
+ void swapColumns(int, int);
+ int removeColumn(Column *);
+ Column *removeColumn(int);
+
+signals:
+ void columnAboutToBeInserted(int index);
+ void columnInserted(int index);
+ void columnAboutToBeRemoved(int index);
+ void columnRemoved(int index);
+ void columnChanged(int index);
+
+protected slots:
+ void updateColumn(const QString &name, const QVariant&);
+
+private:
+ QList<Column *> m_columns;
+};
+
+#endif
diff --git a/src/items/database/columnlistmodel.cpp b/src/items/database/columnlistmodel.cpp
new file mode 100644
index 0000000..5a282c8
--- /dev/null
+++ b/src/items/database/columnlistmodel.cpp
@@ -0,0 +1,208 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#include <QDebug>
+#include "columnlistmodel.h"
+#include "diagramdocument.h"
+#include "databasetable.h"
+#include "commands.h"
+#include "column.h"
+#include "columnlist.h"
+
+#define COLUMN_COUNT 5
+
+ColumnListModel::ColumnListModel(QObject *parent)
+ : QAbstractTableModel(parent), m_columnList(0)
+{
+}
+
+void
+ColumnListModel::setColumnList(ColumnList *columnList)
+{
+ if (m_columnList) {
+ disconnect(m_columnList, 0, this, 0);
+ }
+ m_columnList = columnList;
+ if (m_columnList) {
+ connect(m_columnList, SIGNAL(columnAboutToBeInserted(int)), this, SLOT(_columnAboutToBeInserted(int)));
+ connect(m_columnList, SIGNAL(columnInserted(int)), this, SLOT(_columnInserted()));
+ connect(m_columnList, SIGNAL(columnAboutToBeRemoved(int)), this, SLOT(_columnAboutToBeRemoved(int)));
+ connect(m_columnList, SIGNAL(columnRemoved(int)), this, SLOT(_columnRemoved()));
+ connect(m_columnList, SIGNAL(columnChanged(int)), this, SLOT(_columnChanged(int)));
+ }
+ reset();
+}
+
+int
+ColumnListModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+ return m_columnList ? m_columnList->columnCount() : 0;
+}
+
+int
+ColumnListModel::columnCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+ return COLUMN_COUNT;
+}
+
+QVariant
+ColumnListModel::data(const QModelIndex &index, int role) const
+{
+ if (m_columnList) {
+ Q_ASSERT(index.isValid());
+ Column *column = m_columnList->column(index.row());
+ if (role == Qt::DisplayRole || role == Qt::EditRole) {
+ if (index.column() == 0) {
+ return column->name();
+ }
+ if (index.column() == 1) {
+ return column->dataType();
+ }
+ if (index.column() == 4) {
+ return column->notes();
+ }
+ }
+ if (role == Qt::CheckStateRole) {
+ if (index.column() == 2) {
+ return column->isRequired() ? Qt::Checked : Qt::Unchecked;
+ }
+ if (index.column() == 3) {
+ return column->isPrimaryKey() ? Qt::Checked : Qt::Unchecked;
+ }
+ }
+ }
+ return QVariant();
+}
+
+bool
+ColumnListModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (m_columnList) {
+ Q_ASSERT(index.isValid());
+ Column *column = m_columnList->column(index.row());
+ if (role == Qt::DisplayRole || role == Qt::EditRole) {
+ QString text = value.toString();
+ if (index.column() == 0) {
+ m_columnList->table()->model()->undoStack()->push(
+ new SetObjectPropertyCommand(column, "name", text));
+ goto OK;
+ }
+ if (index.column() == 1) {
+ m_columnList->table()->model()->undoStack()->push(
+ new SetObjectPropertyCommand(column, "dataType", text));
+ goto OK;
+ }
+ if (index.column() == 4) {
+ m_columnList->table()->model()->undoStack()->push(
+ new SetObjectPropertyCommand(column, "notes", text));
+ goto OK;
+ }
+ }
+ if (role == Qt::CheckStateRole) {
+ bool checked = value.toInt() == Qt::Checked ? true : false;
+ if (index.column() == 2) {
+ m_columnList->table()->model()->undoStack()->push(
+ new SetObjectPropertyCommand(column, "required", checked));
+ goto OK;
+ }
+ if (index.column() == 3) {
+ m_columnList->table()->model()->undoStack()->push(
+ new SetObjectPropertyCommand(column, "primaryKey", checked));
+ if (!column->isRequired()) {
+ // TODO is there a simple way to group this with the previous command?
+ m_columnList->table()->model()->undoStack()->push(
+ new SetObjectPropertyCommand(column, "required", true));
+ }
+ goto OK;
+ }
+ }
+ }
+ return false;
+OK:
+ emit dataChanged(createIndex(index.row(), 0), createIndex(index.row(), COLUMN_COUNT));
+ return true;
+}
+
+Qt::ItemFlags
+ColumnListModel::flags(const QModelIndex &index) const
+{
+ Q_ASSERT(index.isValid());
+ if (index.column() == 0 || index.column() == 1 || index.column() == 4) {
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
+ }
+ if (index.column() == 2 || index.column() == 3) {
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
+ }
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+}
+
+QVariant
+ColumnListModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
+ if (section == 0)
+ return tr("Name");
+ if (section == 1)
+ return tr("Data Type");
+ if (section == 2)
+ return tr("Req'd");
+ if (section == 3)
+ return tr("PK");
+ if (section == 4)
+ return tr("Notes");
+ }
+ return QVariant();
+}
+
+QModelIndex
+ColumnListModel::indexFromRow(int i) const
+{
+ return createIndex(i, 0);
+}
+
+void
+ColumnListModel::_columnAboutToBeInserted(int index)
+{
+ beginInsertRows(QModelIndex(), index, index);
+}
+
+void
+ColumnListModel::_columnInserted()
+{
+ endInsertRows();
+}
+
+void
+ColumnListModel::_columnAboutToBeRemoved(int index)
+{
+ beginRemoveRows(QModelIndex(), index, index);
+}
+
+void
+ColumnListModel::_columnRemoved()
+{
+ endRemoveRows();
+}
+
+void
+ColumnListModel::_columnChanged(int index)
+{
+ emit dataChanged(createIndex(index, 0), createIndex(index, COLUMN_COUNT));
+}
diff --git a/src/items/database/columnlistmodel.h b/src/items/database/columnlistmodel.h
new file mode 100644
index 0000000..2944223
--- /dev/null
+++ b/src/items/database/columnlistmodel.h
@@ -0,0 +1,55 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#ifndef COLUMNLISTMODEL_H
+#define COLUMNLISTMODEL_H
+
+#include <QAbstractTableModel>
+class Column;
+class ColumnList;
+
+class ColumnListModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ ColumnListModel(QObject *parent = 0);
+
+ ColumnList *columnList() { return m_columnList; }
+ void setColumnList(ColumnList *columnList);
+
+ // QAbstractItemModel methods
+ int rowCount(const QModelIndex &parent) const;
+ int columnCount(const QModelIndex &parent) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+
+ QModelIndex indexFromRow(int i) const;
+
+private slots:
+ void _columnAboutToBeInserted(int index);
+ void _columnInserted();
+ void _columnAboutToBeRemoved(int index);
+ void _columnRemoved();
+ void _columnChanged(int index);
+
+private:
+ ColumnList *m_columnList;
+};
+
+#endif
diff --git a/src/items/database/columnlistview.cpp b/src/items/database/columnlistview.cpp
new file mode 100644
index 0000000..dd73fb6
--- /dev/null
+++ b/src/items/database/columnlistview.cpp
@@ -0,0 +1,103 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#include "columnlist.h"
+#include "columnlistmodel.h"
+#include "columnlistview.h"
+#include "commands.h"
+#include "diagramdocument.h"
+
+ColumnListView::ColumnListView(QWidget *parent)
+ : QTreeView(parent)
+{
+ setModel(new ColumnListModel(this));
+}
+
+void
+ColumnListView::setColumnList(ColumnList *columnList)
+{
+ columnListModel()->setColumnList(columnList);
+}
+
+void
+ColumnListView::addColumn()
+{
+ AddColumnCommand *command = new AddColumnCommand(columnList());
+ columnList()->table()->model()->undoStack()->push(command);
+ QModelIndex index = columnListModel()->indexFromRow(command->index());
+ setCurrentIndex(index);
+ edit(index);
+}
+
+void
+ColumnListView::removeColumn()
+{
+ QList<int> indexes = selectedColumns();
+ if (indexes.size() == 1) {
+ columnList()->table()->model()->undoStack()->push(
+ new RemoveColumnCommand(columnList(), indexes[0]));
+ }
+}
+
+void
+ColumnListView::moveColumnDown()
+{
+ QList<int> indexes = selectedColumns();
+ if (indexes.size() == 1) {
+ int i = indexes[0];
+ if (i + 1 < columnList()->columnCount()) {
+ columnList()->table()->model()->undoStack()->push(
+ new SwapColumnsCommand(columnList(), i, i + 1));
+ setCurrentIndex(columnListModel()->indexFromRow(i + 1));
+ }
+ }
+}
+
+void
+ColumnListView::moveColumnUp()
+{
+ QList<int> indexes = selectedColumns();
+ if (indexes.size() == 1) {
+ int i = indexes[0];
+ if (i > 0) {
+ columnList()->table()->model()->undoStack()->push(
+ new SwapColumnsCommand(columnList(), i, i - 1));
+ setCurrentIndex(columnListModel()->indexFromRow(i - 1));
+ }
+ }
+}
+
+QModelIndexList
+ColumnListView::selectedIndexes() const
+{
+ QModelIndexList indexes;
+ foreach (QModelIndex index, selectionModel()->selectedIndexes()) {
+ if (index.column() == 0) {
+ indexes << index;
+ }
+ }
+ return indexes;
+}
+
+QList<int>
+ColumnListView::selectedColumns() const
+{
+ QList<int> columns;
+ foreach (QModelIndex index, selectedIndexes()) {
+ columns << index.row();
+ }
+ return columns;
+}
diff --git a/src/items/database/columnlistview.h b/src/items/database/columnlistview.h
new file mode 100644
index 0000000..8e2bb47
--- /dev/null
+++ b/src/items/database/columnlistview.h
@@ -0,0 +1,47 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#ifndef COLUMNLISTVIEW_H
+#define COLUMNLISTVIEW_H
+
+#include <QTreeView>
+#include "columnlistmodel.h"
+
+class ColumnListView : public QTreeView
+{
+ Q_OBJECT
+
+public:
+ ColumnListView(QWidget *parent = 0);
+
+ void setColumnList(ColumnList *columnList);
+ ColumnListModel *columnListModel() { return qobject_cast<ColumnListModel *>(model()); }
+
+ ColumnList *columnList() { return columnListModel()->columnList(); }
+
+ QList<int> selectedColumns() const;
+
+public slots:
+ void addColumn();
+ void removeColumn();
+ void moveColumnUp();
+ void moveColumnDown();
+
+protected:
+ QModelIndexList selectedIndexes() const;
+};
+
+#endif
diff --git a/src/items/database/database.pri b/src/items/database/database.pri
new file mode 100644
index 0000000..f673ff6
--- /dev/null
+++ b/src/items/database/database.pri
@@ -0,0 +1,22 @@
+DEPENDPATH += $$PWD
+
+SOURCES += \
+ column.cpp \
+ columnlist.cpp \
+ columnlistmodel.cpp \
+ columnlistview.cpp \
+ databasetable.cpp \
+ databaserelationship.cpp \
+ tableproperties.cpp
+
+HEADERS += \
+ column.h \
+ columnlist.h \
+ columnlistmodel.h \
+ columnlistview.h \
+ databasetable.h \
+ databaserelationship.h \
+ tableproperties.h
+
+FORMS += \
+ tableproperties.ui
diff --git a/src/items/database/databaserelationship.cpp b/src/items/database/databaserelationship.cpp
new file mode 100644
index 0000000..02540c5
--- /dev/null
+++ b/src/items/database/databaserelationship.cpp
@@ -0,0 +1,244 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#include <QGraphicsScene>
+#include <QDebug>
+#include "databasetable.h"
+#include "databaserelationship.h"
+#include "range.h"
+
+DatabaseRelationship::DatabaseRelationship(DiagramItem *parent)
+ : DiagramConnection(parent)
+{
+ setFlag(ItemIsSelectable);
+ connect(this, SIGNAL(endPointChanged()), this, SLOT(updateLayout()));
+}
+
+QRectF
+DatabaseRelationship::boundingRect() const
+{
+ return shape().boundingRect();
+}
+
+QPainterPath
+DatabaseRelationship::shape() const
+{
+ QPainterPath path;
+ if (m_line.isEmpty())
+ return path;
+ path.moveTo(m_line[0]);
+ for (int i = 1; i < m_line.size(); i++)
+ path.lineTo(m_line[i]);
+ path.addPolygon(m_arrowHead);
+ QPen pen(QPen(QColor(0, 0, 0), 1));
+ pen.setJoinStyle(Qt::MiterJoin);
+ QPainterPathStroker ps;
+ ps.setCapStyle(pen.capStyle());
+ ps.setWidth(pen.widthF() + 0.3);
+ ps.setJoinStyle(pen.joinStyle());
+ ps.setMiterLimit(pen.miterLimit());
+ return ps.createStroke(path);
+}
+
+void
+DatabaseRelationship::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ QPen pen(QPen(QColor(0, 0, 0), 1));
+ pen.setJoinStyle(Qt::MiterJoin);
+ painter->setPen(pen);
+ painter->drawPolyline(m_line);
+ painter->setBrush(pen.color());
+ painter->drawPolygon(m_arrowHead);
+}
+
+QVariant
+DatabaseRelationship::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ if (change == ItemSceneHasChanged) {
+ updateLayout();
+ }
+ return QGraphicsItem::itemChange(change, value);
+}
+
+void
+DatabaseRelationship::updatePositions()
+{
+ updateLayout();
+ update();
+}
+
+void
+DatabaseRelationship::updateLayout()
+{
+ if (!scene())
+ return;
+
+ DatabaseTable *source = sourceTable();
+ DatabaseTable *target = targetTable();
+ if (!source || !target)
+ return;
+
+ prepareGeometryChange();
+
+ QRectF rect1 = source->boundingRect().translated(source->pos());
+ QRectF rect2 = target->boundingRect().translated(target->pos());
+
+ bool haveLine = false;
+
+ Range<qreal> verticalRange1(rect1.top(), rect1.bottom());
+ Range<qreal> verticalRange2(rect2.top(), rect2.bottom());
+ Range<qreal> verticalIntersection = verticalRange1.intersected(verticalRange2);
+
+ Range<qreal> horizontalRange1(rect1.left(), rect1.right());
+ Range<qreal> horizontalRange2(rect2.left(), rect2.right());
+ Range<qreal> horizontalIntersection = horizontalRange1.intersected(horizontalRange2);
+
+ // Straight horizontal line
+ if (0 && !haveLine) {
+ if (!verticalIntersection.isNull() && horizontalIntersection.isNull()) {
+ qreal y = verticalIntersection.min() + verticalIntersection.length() / 2;
+ if (rect1.right() < rect2.left()) {
+ m_line = QPolygonF() << QPointF(rect1.right(), y) << QPointF(rect2.left(), y);
+ }
+ else {
+ m_line = QPolygonF() << QPointF(rect1.left(), y) << QPointF(rect2.right(), y);
+ }
+ haveLine = true;
+ }
+ }
+
+ // Straight vertical line
+ if (0 && !haveLine) {
+ if (verticalIntersection.isNull() && !horizontalIntersection.isNull()) {
+ qreal x = horizontalIntersection.min() + horizontalIntersection.length() / 2;
+ if (rect1.bottom() < rect2.top()) {
+ m_line = QPolygonF() << QPointF(x, rect1.bottom()) << QPointF(x, rect2.top());
+ }
+ else {
+ m_line = QPolygonF() << QPointF(x, rect1.top()) << QPointF(x, rect2.bottom());
+ }
+ haveLine = true;
+ }
+ }
+
+ // Two-segment line
+ if (0 && !haveLine) {
+
+ qreal x1, x2, x3, y1, y2, y3;
+
+ if (rect1.right() < rect2.left()) {
+ x1 = rect1.right();
+ y1 = verticalRange1.center();
+
+ x2 = horizontalRange2.center();
+ y2 = verticalRange1.center();
+
+ if (rect1.bottom() < rect2.top()) {
+ x3 = horizontalRange2.center();
+ y3 = rect2.top();
+ }
+ else {
+ x3 = horizontalRange2.center();
+ y3 = rect2.bottom();
+ }
+ }
+ else {
+ x1 = rect1.left();
+ y1 = verticalRange1.center();
+
+ x2 = horizontalRange2.center();
+ y2 = verticalRange1.center();
+
+ if (rect1.bottom() < rect2.top()) {
+ x3 = horizontalRange2.center();
+ y3 = rect2.top();
+ }
+ else {
+ x3 = horizontalRange2.center();
+ y3 = rect2.bottom();
+ }
+ }
+
+ m_line = QPolygonF()
+ << QPointF(x1, y1)
+ << QPointF(x2, y2)
+ << QPointF(x3, y3);
+ haveLine = true;
+ }
+
+ // Simple center<->center line
+ if (!haveLine) {
+ QPointF p1 = rect1.center();
+ QPointF p2 = rect2.center();
+ QLineF finalLine = QLineF(p1, p2);
+
+ QPolygonF polygon;
+
+ polygon = rect1;
+ for (int i = 0; i < 4; i++) {
+ QLineF line(polygon[i], polygon[(i+1)%4]);
+ QPointF intersectionPoint;
+ if (finalLine.intersect(line, &intersectionPoint) == QLineF::BoundedIntersection) {
+ finalLine.setP1(intersectionPoint);
+ break;
+ }
+ }
+
+ polygon = rect2;
+ for (int i = 0; i < 4; i++) {
+ QLineF line(polygon[i], polygon[(i+1)%4]);
+ QPointF intersectionPoint;
+ if (finalLine.intersect(line, &intersectionPoint) == QLineF::BoundedIntersection) {
+ finalLine.setP2(intersectionPoint);
+ break;
+ }
+ }
+
+ m_line = QPolygonF() << finalLine.p1() << finalLine.p2();
+ haveLine = true;
+ }
+
+ Q_ASSERT(haveLine);
+
+ int size = m_line.size();
+ QLineF lastSegment(m_line[size-2], m_line[size-1]);
+
+ m_arrowHead.resize(3);
+ m_arrowHead[0] = QPointF(0.0, 0.0);
+ m_arrowHead[1] = QPointF(-4.5, 10.0);
+ m_arrowHead[2] = QPointF(4.5, 10.0);
+ QMatrix matrix;
+ matrix.rotate(-lastSegment.angle() + 90);
+ m_arrowHead = matrix.map(m_arrowHead);
+ m_arrowHead.translate(lastSegment.p2());
+}
+
+#include "domutils.h"
+
+void
+DatabaseRelationship::loadFromXml(QDomElement element, DiagramDocument *document)
+{
+ DiagramConnection::loadFromXml(element, document);
+}
+
+void
+DatabaseRelationship::saveToXml(QDomDocument doc, QDomElement element)
+{
+ DiagramConnection::saveToXml(doc, element);
+}
diff --git a/src/items/database/databaserelationship.h b/src/items/database/databaserelationship.h
new file mode 100644
index 0000000..e9e26d0
--- /dev/null
+++ b/src/items/database/databaserelationship.h
@@ -0,0 +1,61 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#ifndef DATABASERELATION_H
+#define DATABASERELATION_H
+
+#include <QGraphicsItem>
+#include <QPainter>
+#include "diagramconnection.h"
+#include "databasetable.h"
+
+class DatabaseRelationship : public DiagramConnection
+{
+ Q_OBJECT
+
+public:
+ DatabaseRelationship(DiagramItem *parent = 0);
+
+ QRectF boundingRect() const;
+ QPainterPath shape() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ DatabaseTable *sourceTable() { return qobject_cast<DatabaseTable *>(source()); }
+ DatabaseTable *targetTable() { return qobject_cast<DatabaseTable *>(target()); }
+
+ enum { Type = DiagramItem::Relation };
+ virtual int type() const { return Type; }
+
+ static const char *staticTypeName() { return "database-relationship"; }
+ virtual const char *typeName() { return staticTypeName(); }
+
+ void loadFromXml(QDomElement element, DiagramDocument *document = 0);
+ void saveToXml(QDomDocument doc, QDomElement element);
+
+ void updatePositions();
+
+protected slots:
+ void updateLayout();
+
+protected:
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+
+private:
+ QPolygonF m_line;
+ QPolygonF m_arrowHead;
+};
+
+#endif
diff --git a/src/items/database/databasetable.cpp b/src/items/database/databasetable.cpp
new file mode 100644
index 0000000..911457f
--- /dev/null
+++ b/src/items/database/databasetable.cpp
@@ -0,0 +1,228 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#include <QGraphicsScene>
+#include <QMimeData>
+#include <QDebug>
+#include "databasetable.h"
+#include "diagramdocument.h"
+#include "column.h"
+#include "columnlist.h"
+
+DatabaseTable::DatabaseTable(DiagramItem *parent)
+ : DiagramObject(parent)
+{
+ setFlag(ItemIsMovable);
+ setFlag(ItemIsSelectable);
+ m_name = "Table";
+ m_columnList = new ColumnList(this);
+ connect(m_columnList, SIGNAL(columnInserted(int)), this, SLOT(updateLayout()));
+ connect(m_columnList, SIGNAL(columnRemoved(int)), this, SLOT(updateLayout()));
+ connect(m_columnList, SIGNAL(columnChanged(int)), this, SLOT(updateLayout()));
+}
+
+DiagramDocument *
+DatabaseTable::model() const
+{
+ return qobject_cast<DiagramDocument *>(scene());
+}
+
+QRectF
+DatabaseTable::boundingRect() const
+{
+ return m_outerRect;
+}
+
+void
+DatabaseTable::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ QFont font = scene()->font();
+ QFont boldFont = font;
+ boldFont.setBold(true);
+ QFont boldFontWithUnderline = boldFont;
+ boldFontWithUnderline.setUnderline(true);
+
+ QPen pen(QPen(QColor(0, 0, 0)));
+ pen.setJoinStyle(Qt::MiterJoin);
+ QPen borderPen(pen);
+ if (isSelected()) {
+ borderPen.setColor(QColor(0, 96, 255));
+ borderPen.setWidth(2);
+ }
+
+ painter->setPen(pen);
+ painter->setFont(font);
+
+ painter->fillRect(m_outerRect, QColor(255, 255, 255));
+
+ // Draw the table name
+ painter->fillRect(m_nameBgRect, QColor(205, 205, 205));
+ painter->drawLine(m_nameBgRect.bottomLeft(), m_nameBgRect.bottomRight());
+ painter->drawText(m_namePos, m_name);
+
+ painter->drawLine(
+ m_leftSideWidth, m_nameBgRect.bottom(),
+ m_leftSideWidth, m_outerRect.bottom());
+
+ // Draw the table name
+ QPointF colPos = m_firstColPos;
+ QPointF leftSizePos = colPos - QPointF(m_leftSideWidth, 0);
+ foreach (Column *column, m_columnList->columns()) {
+ painter->setFont(column->isRequired()
+ ? (column->isPrimaryKey() ? boldFontWithUnderline : boldFont)
+ : font);
+ painter->drawText(colPos, column->name());
+ if (column->isPrimaryKey()) {
+ painter->setFont(column->isRequired() ? boldFont : font);
+ painter->drawText(leftSizePos, "PK");
+ }
+ colPos += m_colPosIncrement;
+ leftSizePos += m_colPosIncrement;
+ }
+
+ // Draw the outside border
+ painter->setPen(borderPen);
+ painter->drawRect(m_outerRect);
+}
+
+void
+DatabaseTable::setName(const QString &name)
+{
+ m_name = name;
+ updateLayout();
+ emit propertyChanged("name", name);
+}
+
+QVariant
+DatabaseTable::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ if (change == ItemSceneHasChanged) {
+ updateLayout();
+ }
+ if (change == ItemPositionChange) {
+ DiagramDocument *model = qobject_cast<DiagramDocument *>(scene());
+ if (model) {
+ emit model->itemMoved(this);
+ }
+ }
+ if (change == ItemPositionHasChanged) {
+ DiagramDocument *model = qobject_cast<DiagramDocument *>(scene());
+ if (model)
+ emit model->itemHasMoved(this);
+ }
+ return QGraphicsItem::itemChange(change, value);
+}
+
+void
+DatabaseTable::updateLayout()
+{
+ if (!scene())
+ return;
+
+ prepareGeometryChange();
+
+ QFont font = scene()->font();
+ QFontMetricsF fontMetrics(font);
+
+ QFont boldFont = font;
+ boldFont.setBold(true);
+ QFontMetricsF boldFontMetrics(boldFont);
+
+ qreal spaceWidth = fontMetrics.width(' ');
+ qreal nameWidth = fontMetrics.width(m_name);
+ qreal height = fontMetrics.height();
+
+ m_leftSideWidth = fontMetrics.width("PK");
+
+ qreal width = nameWidth + spaceWidth * 2;
+
+ qreal maxColumnWidth = 0;
+ foreach (Column *column, m_columnList->columns()) {
+ qreal columnWidth = column->isRequired() ? boldFontMetrics.width(column->name()) : fontMetrics.width(column->name());
+ maxColumnWidth = qMax(maxColumnWidth, columnWidth);
+ qreal columnLeftSideWidth = 0;
+ if (column->isPrimaryKey()) {
+ if (column->isRequired()) {
+ columnLeftSideWidth = boldFontMetrics.width("PK");
+ }
+ else {
+ columnLeftSideWidth = fontMetrics.width("PK");
+ }
+ }
+ m_leftSideWidth = qMax(m_leftSideWidth, columnLeftSideWidth);
+ }
+ m_leftSideWidth += spaceWidth * 2;
+ width = qMax(nameWidth + spaceWidth * 4, m_leftSideWidth + maxColumnWidth + spaceWidth * 2);
+
+ qreal nameHeight = height + spaceWidth;
+ m_outerRect = QRectF(0, 0, width, nameHeight + qMax(0.66, qreal(m_columnList->columnCount())) * fontMetrics.lineSpacing()
+ - fontMetrics.leading() + fontMetrics.descent());
+
+ m_nameBgRect = QRectF(0, 0, width, nameHeight);
+ m_namePos = QPointF((width - nameWidth) / 2, fontMetrics.ascent() + spaceWidth / 2);
+
+ m_firstColPos = QPointF(m_leftSideWidth + spaceWidth * 1 - 1, nameHeight + fontMetrics.ascent() + 2);
+ m_colPosIncrement = QPointF(0, fontMetrics.lineSpacing());
+
+ update();
+}
+
+#include "domutils.h"
+
+void
+DatabaseTable::loadFromXml(QDomElement element, DiagramDocument *document)
+{
+ DiagramItem::loadFromXml(element, document);
+ QDomElement tableElement = element.firstChildElement("table");
+ if (!tableElement.isNull()) {
+ setName(readStringElement(tableElement, "name"));
+ QDomElement columnListElement = tableElement.firstChildElement("column-list");
+ QDomElement columnElement = columnListElement.firstChildElement("column");
+ while (!columnElement.isNull()) {
+ Column *column = new Column();
+ column->setName(readStringElement(columnElement, "name"));
+ column->setDataType(readStringElement(columnElement, "data-type"));
+ column->setRequired(readStringElement(columnElement, "required") == "yes");
+ column->setPrimaryKey(readStringElement(columnElement, "primary-key") == "yes");
+ column->setNotes(readStringElement(columnElement, "notes"));
+ columnList()->appendColumn(column);
+ columnElement = columnElement.nextSiblingElement("column");
+ }
+ }
+}
+
+void
+DatabaseTable::saveToXml(QDomDocument doc, QDomElement element)
+{
+ DiagramItem::saveToXml(doc, element);
+ QDomElement tableElement = doc.createElement("table");
+ element.appendChild(tableElement);
+ appendStringElement(doc, tableElement, "name", name());
+ QDomElement columnListElement = doc.createElement("column-list");
+ tableElement.appendChild(columnListElement);
+ foreach (Column *column, columnList()->columns()) {
+ QDomElement columnElement = doc.createElement("column");
+ columnListElement.appendChild(columnElement);
+ appendStringElement(doc, columnElement, "name", column->name());
+ appendStringElement(doc, columnElement, "data-type", column->dataType());
+ appendStringElement(doc, columnElement, "required", column->isRequired() ? "yes" : QString());
+ appendStringElement(doc, columnElement, "primary-key", column->isPrimaryKey() ? "yes" : QString());
+ appendStringElement(doc, columnElement, "notes", column->notes());
+ }
+}
diff --git a/src/items/database/databasetable.h b/src/items/database/databasetable.h
new file mode 100644
index 0000000..8be1ee5
--- /dev/null
+++ b/src/items/database/databasetable.h
@@ -0,0 +1,80 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#ifndef DATABASETABLE_H
+#define DATABASETABLE_H
+
+#include <QGraphicsItem>
+#include <QPainter>
+#include "diagramobject.h"
+
+class Column;
+class ColumnList;
+class DiagramDocument;
+
+class DatabaseTable : public DiagramObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString name READ name WRITE setName)
+
+public:
+ DatabaseTable(DiagramItem *parent = 0);
+
+ DiagramDocument *model() const;
+
+ QRectF boundingRect() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ QString name() const { return m_name; }
+ void setName(const QString &name);
+
+ ColumnList *columnList() { return m_columnList; }
+
+// void setColumn(int index, const QString &name);
+// void removeColumn(int index);
+// Column *addColumn(const QString &name = QString());
+// void swapColumns(int index1, int index2);
+
+ enum { Type = DiagramItem::Table };
+ virtual int type() const { return Type; }
+
+ static const char *staticTypeName() { return "database-table"; }
+ virtual const char *typeName() { return staticTypeName(); }
+
+ void loadFromXml(QDomElement element, DiagramDocument *document = 0);
+ void saveToXml(QDomDocument doc, QDomElement element);
+
+// QMimeData *toMimeData();
+
+signals:
+ void propertyChanged(const QString &name, const QVariant &value);
+
+protected slots:
+ void updateLayout();
+
+protected:
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+
+private:
+ QString m_name;
+ ColumnList *m_columnList;
+
+ QRectF m_outerRect, m_nameBgRect;
+ QPointF m_namePos, m_firstColPos, m_colPosIncrement;
+ qreal m_leftSideWidth;
+};
+
+#endif
diff --git a/src/items/database/tableproperties.cpp b/src/items/database/tableproperties.cpp
new file mode 100644
index 0000000..11b3fc4
--- /dev/null
+++ b/src/items/database/tableproperties.cpp
@@ -0,0 +1,97 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#include "tableproperties.h"
+#include "databasetable.h"
+#include "mainwindow.h"
+#include "commands.h"
+#include "column.h"
+#include <QCheckBox>
+#include <QDebug>
+
+TableProperties::TableProperties(MainWindow *window, QWidget *parent)
+ : QWidget(parent), m_window(window), m_table(0)
+{
+ ui.setupUi(this);
+ setTable(0);
+ connect(ui.nameEdit,
+ SIGNAL(textEdited(const QString &)),
+ SLOT(setSelectedTableName(const QString &)));
+ connect(ui.addColumnButton, SIGNAL(clicked()), ui.columnsWidget, SLOT(addColumn()));
+ connect(ui.removeColumnButton, SIGNAL(clicked()), ui.columnsWidget, SLOT(removeColumn()));
+ connect(ui.moveColumnUpButton, SIGNAL(clicked()), ui.columnsWidget, SLOT(moveColumnUp()));
+ connect(ui.moveColumnDownButton, SIGNAL(clicked()), ui.columnsWidget, SLOT(moveColumnDown()));
+ connect(ui.columnsWidget->selectionModel(),
+ SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
+ SLOT(updateColumnSelection()));
+}
+
+void
+TableProperties::setSelectedTableName(const QString &name)
+{
+ if (m_table) {
+ m_window->currentUndoStack()->push(new SetObjectPropertyCommand(m_table, "name", name));
+ }
+}
+
+void
+TableProperties::setTable(DatabaseTable *table)
+{
+ // Disconnect all connections from the previous table
+ if (m_table) {
+ disconnect(m_table, 0, this, 0);
+ }
+
+ m_table = NULL;
+ if (table == NULL) {
+ setEnabled(false);
+ ui.nameEdit->clear();
+ ui.columnsWidget->setColumnList(0);
+ }
+ else {
+ setEnabled(true);
+ ui.nameEdit->setText(table->name());
+ ui.columnsWidget->setColumnList(table->columnList());
+ connect(table, SIGNAL(propertyChanged(const QString &, const QVariant &)), SLOT(updateProperty(const QString &, const QVariant &)));
+ }
+ m_table = table;
+ updateColumnSelection();
+}
+
+void
+TableProperties::updateProperty(const QString &name, const QVariant &value)
+{
+ if (name == "name") {
+ ui.nameEdit->setText(value.toString());
+ }
+}
+
+void
+TableProperties::updateColumnSelection()
+{
+ QList<int> columns = ui.columnsWidget->selectedColumns();
+ if (columns.isEmpty()) {
+ ui.removeColumnButton->setEnabled(false);
+ ui.moveColumnUpButton->setEnabled(false);
+ ui.moveColumnDownButton->setEnabled(false);
+ }
+ else {
+ int index = columns[0];
+ ui.removeColumnButton->setEnabled(true);
+ ui.moveColumnUpButton->setEnabled(index > 0);
+ ui.moveColumnDownButton->setEnabled(index + 1 < m_table->columnList()->columnCount());
+ }
+}
diff --git a/src/items/database/tableproperties.h b/src/items/database/tableproperties.h
new file mode 100644
index 0000000..6ad51a5
--- /dev/null
+++ b/src/items/database/tableproperties.h
@@ -0,0 +1,48 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#ifndef TABLEPROPERTIES_H
+#define TABLEPROPERTIES_H
+
+#include <QWidget>
+#include <QTreeWidget>
+#include "ui_tableproperties.h"
+
+class DatabaseTable;
+class MainWindow;
+
+class TableProperties : public QWidget
+{
+ Q_OBJECT
+
+public:
+ TableProperties(MainWindow *window, QWidget *parent = 0);
+
+ DatabaseTable *table() { return m_table; }
+ void setTable(DatabaseTable *table);
+
+protected slots:
+ void setSelectedTableName(const QString &name);
+ void updateColumnSelection();
+ void updateProperty(const QString &name, const QVariant &value);
+
+private:
+ MainWindow *m_window;
+ DatabaseTable *m_table;
+ Ui_TableProperties ui;
+};
+
+#endif
diff --git a/src/items/database/tableproperties.ui b/src/items/database/tableproperties.ui
new file mode 100644
index 0000000..0ad531a
--- /dev/null
+++ b/src/items/database/tableproperties.ui
@@ -0,0 +1,137 @@
+<ui version="4.0" >
+ <class>TableProperties</class>
+ <widget class="QWidget" name="TableProperties" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>471</width>
+ <height>192</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTabWidget" name="tabWidget" >
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab" >
+ <attribute name="title" >
+ <string>&amp;Definition</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout_2" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Name:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLineEdit" name="nameEdit" />
+ </item>
+ <item row="1" column="0" colspan="2" >
+ <spacer name="verticalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>158</width>
+ <height>113</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_2" >
+ <attribute name="title" >
+ <string>&amp;Columns</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout_3" >
+ <item rowspan="5" row="0" column="0" >
+ <widget class="ColumnListView" name="columnsWidget" >
+ <property name="rootIsDecorated" >
+ <bool>false</bool>
+ </property>
+ <property name="itemsExpandable" >
+ <bool>false</bool>
+ </property>
+ <property name="expandsOnDoubleClick" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QPushButton" name="addColumnButton" >
+ <property name="toolTip" >
+ <string>Add new column</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Add</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QPushButton" name="removeColumnButton" >
+ <property name="toolTip" >
+ <string>Remove selected column</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QPushButton" name="moveColumnUpButton" >
+ <property name="toolTip" >
+ <string>Move selected column up</string>
+ </property>
+ <property name="text" >
+ <string>Move &amp;Up</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <widget class="QPushButton" name="moveColumnDownButton" >
+ <property name="toolTip" >
+ <string>Move selected column down</string>
+ </property>
+ <property name="text" >
+ <string>Move &amp;Down</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1" >
+ <spacer name="verticalSpacer_2" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>17</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>ColumnListView</class>
+ <extends>QTreeView</extends>
+ <header>items/database/columnlistview.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>