From b58d43e407029f19d313cdc2314cf114c572f692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Arve=20S=C3=A6ther?= Date: Wed, 3 Jun 2009 10:16:35 +0200 Subject: Add an example Should hopefully be easier to test layouts now... --- examples/layouts/anchorlayout/anchorlayout.pro | 15 + examples/layouts/anchorlayout/anchorlayout.ui | 433 +++++++++++++++++ examples/layouts/anchorlayout/layoutitem.cpp | 93 ++++ examples/layouts/anchorlayout/layoutitem.h | 62 +++ examples/layouts/anchorlayout/main.cpp | 10 + examples/layouts/anchorlayout/scene.cpp | 57 +++ examples/layouts/anchorlayout/scene.h | 64 +++ .../layouts/anchorlayout/widgetchooserdelegate.cpp | 134 ++++++ .../layouts/anchorlayout/widgetchooserdelegate.h | 75 +++ examples/layouts/anchorlayout/window.cpp | 517 +++++++++++++++++++++ examples/layouts/anchorlayout/window.h | 60 +++ examples/layouts/anchorlayout/xml/linear.xml | 46 ++ examples/layouts/anchorlayout/xml/snake.xml | 79 ++++ 13 files changed, 1645 insertions(+) create mode 100644 examples/layouts/anchorlayout/anchorlayout.pro create mode 100644 examples/layouts/anchorlayout/anchorlayout.ui create mode 100644 examples/layouts/anchorlayout/layoutitem.cpp create mode 100644 examples/layouts/anchorlayout/layoutitem.h create mode 100644 examples/layouts/anchorlayout/main.cpp create mode 100644 examples/layouts/anchorlayout/scene.cpp create mode 100644 examples/layouts/anchorlayout/scene.h create mode 100644 examples/layouts/anchorlayout/widgetchooserdelegate.cpp create mode 100644 examples/layouts/anchorlayout/widgetchooserdelegate.h create mode 100644 examples/layouts/anchorlayout/window.cpp create mode 100644 examples/layouts/anchorlayout/window.h create mode 100644 examples/layouts/anchorlayout/xml/linear.xml create mode 100644 examples/layouts/anchorlayout/xml/snake.xml diff --git a/examples/layouts/anchorlayout/anchorlayout.pro b/examples/layouts/anchorlayout/anchorlayout.pro new file mode 100644 index 0000000..8c19404 --- /dev/null +++ b/examples/layouts/anchorlayout/anchorlayout.pro @@ -0,0 +1,15 @@ +###################################################################### +# Automatically generated by qmake (2.01a) fr 15. mai 08:51:37 2009 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +HEADERS += layoutitem.h widgetchooserdelegate.h window.h scene.h +FORMS += anchorlayout.ui +SOURCES += layoutitem.cpp main.cpp widgetchooserdelegate.cpp window.cpp scene.cpp + +DEFINES += PRO_FILE_PWD=$$_PRO_FILE_PWD_ \ No newline at end of file diff --git a/examples/layouts/anchorlayout/anchorlayout.ui b/examples/layouts/anchorlayout/anchorlayout.ui new file mode 100644 index 0000000..f4c061a --- /dev/null +++ b/examples/layouts/anchorlayout/anchorlayout.ui @@ -0,0 +1,433 @@ + + + MainWindow + + + + 0 + 0 + 794 + 590 + + + + Anchor layout example + + + + + 0 + + + + + + + 0 + 128 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + + + + + 0 + 0 + 794 + 21 + + + + + &File + + + + + &View + + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + 0 + 0 + + + + Qt::BottomDockWidgetArea|Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea + + + Anchors + + + 1 + + + + + 0 + + + + + + 0 + 0 + + + + + 330 + 0 + + + + 50 + + + + Begin + + + + + Edge + + + + + End + + + + + Edge + + + + + Min + + + + + Max + + + + + + + + Add anchor ^^ + + + Ctrl+A + + + false + + + + + + + + + + 0 + 0 + + + + Item properties + + + 1 + + + + + 0 + + + + + + 0 + 0 + + + + Item properties + + + + + + TextLabel + + + + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + + + + + + + TextLabel + + + + + + + + + + + + + TextLabel + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + Layout presets + + + 1 + + + + + 0 + + + + + + + + + + Add item + + + Ctrl+N + + + + + true + + + true + + + &Anchors + + + + + true + + + true + + + Layout &presets + + + + + true + + + true + + + &Item properties + + + + + + + actionLayout_presets + triggered(bool) + dwPresets + setVisible(bool) + + + -1 + -1 + + + 173 + 345 + + + + + action_Anchors + triggered(bool) + dwAnchors + setVisible(bool) + + + -1 + -1 + + + 173 + 169 + + + + + action_Item_properties + triggered(bool) + dwProperties + setVisible(bool) + + + 173 + 483 + + + 173 + 483 + + + + + dwAnchors + visibilityChanged(bool) + action_Anchors + setChecked(bool) + + + 173 + 169 + + + -1 + -1 + + + + + dwPresets + visibilityChanged(bool) + actionLayout_presets + setChecked(bool) + + + 173 + 345 + + + -1 + -1 + + + + + dwProperties + visibilityChanged(bool) + action_Item_properties + setChecked(bool) + + + 173 + 483 + + + -1 + -1 + + + + + diff --git a/examples/layouts/anchorlayout/layoutitem.cpp b/examples/layouts/anchorlayout/layoutitem.cpp new file mode 100644 index 0000000..b85a589 --- /dev/null +++ b/examples/layouts/anchorlayout/layoutitem.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "layoutitem.h" +#include "scene.h" + +LayoutItem::LayoutItem(const QString &name, QGraphicsItem *parent/* = 0*/) + : QGraphicsWidget(parent) +{ + setData(0, name); + setGraphicsItem(this); + setFocusPolicy(Qt::ClickFocus); +} + +LayoutItem::~LayoutItem() +{ +} + +void LayoutItem::paint(QPainter *painter, + const QStyleOptionGraphicsItem *option, QWidget *widget /*= 0*/) +{ + Q_UNUSED(widget); + Q_UNUSED(option); + + // text + QString name = graphicsItem()->data(0).toString(); + painter->drawText(rect(), Qt::AlignCenter, name); + + // rect + if (Scene *scn = static_cast(scene())) { + if (scn->lastFocusItem() == this) { + QPen pen(Qt::blue, 2.0); + painter->setPen(pen); + } + } + painter->drawRoundedRect(rect(), 5, 5); +} + +void LayoutItem::focusInEvent(QFocusEvent *event) +{ + if (Scene *scn = static_cast(scene())) { + scn->emitFocusItemChanged(this); + } + QGraphicsWidget::focusInEvent(event); +} + +void LayoutItem::focusOutEvent(QFocusEvent *event) +{ + if (Scene *scn = static_cast(scene())) { + scn->emitFocusItemChanged(0); + } + QGraphicsWidget::focusOutEvent(event); +} + + diff --git a/examples/layouts/anchorlayout/layoutitem.h b/examples/layouts/anchorlayout/layoutitem.h new file mode 100644 index 0000000..86c0b06 --- /dev/null +++ b/examples/layouts/anchorlayout/layoutitem.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LAYOUTITEM_H +#define LAYOUTITEM_H + +#include + +class LayoutItem : public QGraphicsWidget +{ + Q_OBJECT +public: + LayoutItem(const QString &name, QGraphicsItem *parent = 0); + ~LayoutItem(); + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, + QWidget *widget = 0); + void focusInEvent(QFocusEvent *event); + void focusOutEvent(QFocusEvent *event); + +}; + + +#endif diff --git a/examples/layouts/anchorlayout/main.cpp b/examples/layouts/anchorlayout/main.cpp new file mode 100644 index 0000000..d0e6ee7 --- /dev/null +++ b/examples/layouts/anchorlayout/main.cpp @@ -0,0 +1,10 @@ +#include "window.h" +#include + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + Window *w = new Window; + w->show(); + return app.exec(); +} \ No newline at end of file diff --git a/examples/layouts/anchorlayout/scene.cpp b/examples/layouts/anchorlayout/scene.cpp new file mode 100644 index 0000000..68b4002 --- /dev/null +++ b/examples/layouts/anchorlayout/scene.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "scene.h" + +Scene::Scene() : QGraphicsScene() +{ + +} + +void Scene::emitFocusItemChanged(QGraphicsItem *item) +{ + if (hasFocus()) { // when leaving the view, we want to remember the last focused item + emit focusItemChanged(item); + m_lastFocusItem = item; + } +} + + diff --git a/examples/layouts/anchorlayout/scene.h b/examples/layouts/anchorlayout/scene.h new file mode 100644 index 0000000..ba7f5d8 --- /dev/null +++ b/examples/layouts/anchorlayout/scene.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SCENE_H +#define SCENE_H + +#include + +class Scene : public QGraphicsScene +{ + Q_OBJECT +public: + Scene(); + + void emitFocusItemChanged(QGraphicsItem *item); + QGraphicsItem *lastFocusItem() { return m_lastFocusItem; } + +Q_SIGNALS: + void focusItemChanged(QGraphicsItem *item); + +private: + QGraphicsItem *m_lastFocusItem; + +}; + +#endif // SCENE_H diff --git a/examples/layouts/anchorlayout/widgetchooserdelegate.cpp b/examples/layouts/anchorlayout/widgetchooserdelegate.cpp new file mode 100644 index 0000000..0f988c1 --- /dev/null +++ b/examples/layouts/anchorlayout/widgetchooserdelegate.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "widgetchooserdelegate.h" + + +WidgetChooserDelegate::WidgetChooserDelegate(QVector *layoutItems, + QGraphicsLayout *layout, + QWidget *parent /*= 0*/) +: QStyledItemDelegate(parent), m_layoutItems(layoutItems), m_layout(layout) +{ +} + +static const char *edges[] = { + "Left", + "HCenter", + "Right", + "Top", + "VCenter", + "Bottom" + }; + +QWidget *WidgetChooserDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem &option, + const QModelIndex &index) const + +{ + int column = index.column(); + if (column == 0 || column == 2) { + // first and second anchor items + QComboBox *chooser = new QComboBox(parent); + chooser->addItem(QLatin1String("layout"), + qVariantFromValue(reinterpret_cast(m_layout))); + for (int i = 0; i < m_layoutItems->count(); ++i) { + QGraphicsLayoutItem *item = m_layoutItems->at(i); + chooser->addItem(item->graphicsItem()->data(0).toString(), + qVariantFromValue(reinterpret_cast(item))); + } + connect(chooser, SIGNAL(currentIndexChanged(int)), + this, SLOT(commitAndCloseEditor())); + return chooser; + } else if (column == 1 || column == 3) { + // first and second anchor edges + QComboBox *chooser = new QComboBox(parent); + for (int i = 0; i < sizeof(edges)/sizeof(char*); ++i) { + chooser->addItem(QLatin1String(edges[i]), i); + } + connect(chooser, SIGNAL(currentIndexChanged(int)), + this, SLOT(commitAndCloseEditor())); + return chooser; + } else { + return QStyledItemDelegate::createEditor(parent, option, index); + } +} + +void WidgetChooserDelegate::setEditorData(QWidget *editor, + const QModelIndex &index) const +{ + if (QComboBox *chooser = qobject_cast(editor)) { + int column = index.column(); + if (column >= 0 && column <= 3) { + QVariant data = index.data(Qt::UserRole); + int index = chooser->findData(data); + if (index >= 0) { + chooser->setCurrentIndex(index); + } + } + } else { + QStyledItemDelegate::setEditorData(editor, index); + } +} + +void WidgetChooserDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + if (QComboBox *chooser = qobject_cast(editor)) { + int column = index.column(); + if (column >= 0 && column <= 3) { + int currentIndex = chooser->currentIndex(); + model->setData(index, chooser->itemText(currentIndex)); + model->setData(index, chooser->itemData(currentIndex), Qt::UserRole); + } + } else { + QStyledItemDelegate::setModelData(editor, model, index); + } +} + +void WidgetChooserDelegate::commitAndCloseEditor() +{ + QComboBox *editor = qobject_cast(sender()); + emit commitData(editor); + emit closeEditor(editor); +} + diff --git a/examples/layouts/anchorlayout/widgetchooserdelegate.h b/examples/layouts/anchorlayout/widgetchooserdelegate.h new file mode 100644 index 0000000..50b9e48 --- /dev/null +++ b/examples/layouts/anchorlayout/widgetchooserdelegate.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef STARDELEGATE_H +#define STARDELEGATE_H + +#include + +#include + +class QGraphicsLayoutItem; +class QGraphicsLayout; + +class WidgetChooserDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + WidgetChooserDelegate(QVector *layoutItems, + QGraphicsLayout *layout, + QWidget *parent = 0); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const; + void setEditorData(QWidget *editor, const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const; + +private slots: + void commitAndCloseEditor(); + +private: + QVector *m_layoutItems; + QGraphicsLayout *m_layout; +}; + +#endif diff --git a/examples/layouts/anchorlayout/window.cpp b/examples/layouts/anchorlayout/window.cpp new file mode 100644 index 0000000..50a1bae --- /dev/null +++ b/examples/layouts/anchorlayout/window.cpp @@ -0,0 +1,517 @@ +#include "window.h" +#include "layoutitem.h" +#include "scene.h" +#include "widgetchooserdelegate.h" + +#include +#include + +static QGraphicsLayoutItem *layoutItem(const QVariant &data) +{ + return reinterpret_cast(qVariantValue(data)); +} + +static QString nodeName(QGraphicsLayoutItem *item) +{ + QString str = item->isLayout() ? QLatin1String("layout") : item->graphicsItem()->data(0).toString(); + str.replace(QLatin1Char(' '), QLatin1Char('_')); + return str; +} + +#define _QUOTEMACRO(x) #x +#define QUOTEMACRO(x) _QUOTEMACRO(x) + +Window::Window(QWidget *parent) + : QMainWindow(parent), m_inAddAnchor(false) +{ + m_ui.setupUi(this); + m_scene = new Scene; + + m_ui.graphicsView->setScene(m_scene); + connect(m_scene, SIGNAL(focusItemChanged(QGraphicsItem*)), this, SLOT(scene_focusItemChanged(QGraphicsItem*))); + + m_window = new QGraphicsWidget(0, Qt::Window); + m_scene->addItem(m_window); + m_layout = new QGraphicsAnchorLayout(m_window); + m_window->setLayout(m_layout); + m_window->resize(400, 300); + + findLayoutFiles(); + + WidgetChooserDelegate *delegate = new WidgetChooserDelegate(&m_layoutItems, m_layout, m_ui.anchors); + m_ui.anchors->setItemDelegate(delegate); + +} + +void Window::findLayoutFiles() +{ + m_ignoreCurrentLayoutChange = true; + QLatin1String s(QUOTEMACRO(PRO_FILE_PWD)"/xml"); + QDirIterator it(s); + while (it.hasNext()) { + it.next(); + QFileInfo fi = it.fileInfo(); + QString baseName = fi.baseName(); + if (!baseName.isEmpty()) { // avoid "." and ".." + m_ui.layouts->addItem(baseName); + } + } + m_ignoreCurrentLayoutChange = false; +} + +void Window::on_layouts_currentRowChanged(int row) +{ + if (m_ignoreCurrentLayoutChange) + return; + + QListWidgetItem *item = m_ui.layouts->item(row); + if (item) { + QString fileName = QString::fromAscii("%1/xml/%2.xml").arg(QUOTEMACRO(PRO_FILE_PWD), item->text()); + if (!loadLayout(fileName, m_layout)) { + qWarning("could not find %s", qPrintable(fileName)); + } + } +} + +void Window::on_anchors_cellChanged(int row, int column) +{ + Q_UNUSED(row); + Q_UNUSED(column); + if (!m_inAddAnchor) + rebuildLayout(); +} + + +void Window::on_pbAddAnchor_clicked(bool) +{ + addAnchorRow(); +} + +void Window::on_actionAdd_item_triggered(bool checked) +{ + addItem(); +} + +void Window::on_itemName_textEdited(const QString & ) +{ + updateItem(); +} + +void Window::on_itemMinW_valueChanged(double ) +{ + updateItem(); +} + +void Window::on_itemMinH_valueChanged(double ) +{ + updateItem(); +} + +void Window::on_itemPrefW_valueChanged(double ) +{ + updateItem(); +} + +void Window::on_itemPrefH_valueChanged(double ) +{ + updateItem(); +} + +void Window::on_itemMaxW_valueChanged(double ) +{ + updateItem(); +} + +void Window::on_itemMaxH_valueChanged(double ) +{ + updateItem(); +} + +void Window::scene_focusItemChanged(QGraphicsItem *item) +{ + bool isItemValid = item && item->isWidget(); + m_ui.groupBox->setEnabled(isItemValid); + QGraphicsLayoutItem *newCurrentItem = m_currentItem; + m_currentItem = 0; + if (isItemValid) { + QGraphicsWidget *w = static_cast(item); + setItemData(item->data(0).toString(), w->minimumSize(), w->preferredSize(), w->maximumSize()); + newCurrentItem = w; + } else { + setItemData(QString(), QSizeF(), QSizeF(), QSizeF()); + } + m_currentItem = newCurrentItem; +} + +void Window::updateItem() +{ + if (!m_currentItem) + return; + if (QGraphicsItem *gi = m_currentItem->graphicsItem()) { + gi->setData(0, m_ui.itemName->text()); + gi->update(); + } + QSizeF min(m_ui.itemMinW->value(), m_ui.itemMinH->value()); + QSizeF pref(m_ui.itemPrefW->value(), m_ui.itemPrefH->value()); + QSizeF max(m_ui.itemMaxW->value(), m_ui.itemMaxH->value()); + + if (min.isValid()) + m_currentItem->setMinimumSize(min); + if (pref.isValid()) + m_currentItem->setPreferredSize(pref); + if (max.isValid()) + m_currentItem->setMaximumSize(max); +} + +void Window::rebuildLayout() +{ + int i; + for (i = m_layout->count(); i > 0; --i) { + m_layout->removeAt(0); + } + + int rc = m_ui.anchors->rowCount(); + for (i = 0; i < rc; ++i) { + bool ok; + + QGraphicsLayoutItem *startItem = layoutItemAt(m_ui.anchors->model(), i, 0); + if (!startItem) + continue; + QGraphicsAnchorLayout::Edge startEdge = (QGraphicsAnchorLayout::Edge)(m_ui.anchors->item(i, 1)->data(Qt::UserRole).toInt(&ok)); + if (!ok) + continue; + QGraphicsLayoutItem *endItem = layoutItemAt(m_ui.anchors->model(), i, 2); + if (!endItem) + continue; + QGraphicsAnchorLayout::Edge endEdge = (QGraphicsAnchorLayout::Edge)(m_ui.anchors->item(i, 3)->data(Qt::UserRole).toInt(&ok)); + if (!ok) + continue; + + QString strStart = nodeName(startItem); + QString strEnd = nodeName(endItem); + m_layout->anchor(startItem, startEdge, endItem, endEdge); + } +} + +void Window::setItemData(const QString &name, const QSizeF &min, const QSizeF &pref, const QSizeF &max) +{ + m_ui.itemName->setText(name); + m_ui.itemMinW->setValue(min.width()); + m_ui.itemMinH->setValue(min.height()); + m_ui.itemPrefW->setValue(pref.width()); + m_ui.itemPrefH->setValue(pref.height()); + m_ui.itemMaxW->setValue(max.width()); + m_ui.itemMaxH->setValue(max.height()); +} + +QGraphicsLayoutItem *Window::addItem(const QString &name) +{ + int rc = m_layoutItems.count(); + QString effectiveName = name.isEmpty() ? QString::fromAscii("item %1").arg(rc + 1) : name; + QGraphicsLayoutItem *layoutItem = new LayoutItem(effectiveName, m_window); + m_layoutItems.append(layoutItem); + m_scene->setFocusItem(layoutItem->graphicsItem()); + return layoutItem; +} + +static const char *strEdges[] = {"Left", + "HCenter", + "Right", + "Top", + "VCenter", + "Bottom"}; + +void Window::setAnchorData(QGraphicsLayoutItem *startItem, const QString &startName, QGraphicsAnchorLayout::Edge startEdge, + QGraphicsLayoutItem *endItem, const QString &endName, QGraphicsAnchorLayout::Edge endEdge, int row /*= -1*/) +{ + if (row == -1) { + row = m_ui.anchors->rowCount(); + m_ui.anchors->insertRow(row); + } + m_inAddAnchor = true; + + QTableWidgetItem *item = new QTableWidgetItem; + item->setData(Qt::UserRole, qVariantFromValue(reinterpret_cast(startItem))); + item->setData(Qt::DisplayRole, startName); + m_ui.anchors->setItem(row, 0, item); + + item = new QTableWidgetItem; + item->setData(Qt::UserRole, int(startEdge)); + item->setData(Qt::DisplayRole, QLatin1String(strEdges[startEdge])); + m_ui.anchors->setItem(row, 1, item); + + item = new QTableWidgetItem; + item->setData(Qt::UserRole, qVariantFromValue(reinterpret_cast(endItem))); + item->setData(Qt::DisplayRole, endName); + m_ui.anchors->setItem(row, 2, item); + + item = new QTableWidgetItem; + item->setData(Qt::UserRole, int(endEdge)); + item->setData(Qt::DisplayRole, QLatin1String(strEdges[endEdge])); + m_ui.anchors->setItem(row, 3, item); + + item = new QTableWidgetItem; + item->setData(Qt::DisplayRole, 6); + m_ui.anchors->setItem(row, 4, item); + + item = new QTableWidgetItem; + item->setData(Qt::DisplayRole, 6); + m_ui.anchors->setItem(row, 5, item); + m_inAddAnchor = false; + +} + +void Window::addAnchorRow() +{ + int rc = m_ui.anchors->rowCount(); + QGraphicsLayoutItem *defaultLayoutItem = m_layout; + if (m_layoutItems.count() > 0) { + defaultLayoutItem = m_layoutItems.at(0); + } + + m_ui.anchors->insertRow(rc); + + if (defaultLayoutItem) { + QString defaultName = defaultLayoutItem->isLayout() ? + QLatin1String("layout") : + defaultLayoutItem->graphicsItem()->data(0).toString(); + setAnchorData(defaultLayoutItem, defaultName, QGraphicsAnchorLayout::Right, defaultLayoutItem, defaultName, QGraphicsAnchorLayout::Left, rc); + rebuildLayout(); + } +} + +QGraphicsLayoutItem *Window::layoutItemAt(QAbstractItemModel *model, int row, int column /*= 0*/) +{ + int rc = model->rowCount(); + QGraphicsLayoutItem *item = 0; + if (row < rc) { + QVariant data = model->data(model->index(row, column), Qt::UserRole); + if (data.isValid()) { + item = layoutItem(data); + } + } + return item; +} + +bool Window::saveLayout(const QString& fileName) +{ + bool ok; +#if 0 + QFile out(fileName); + ok = out.open(QIODevice::WriteOnly); + + if (ok) { + int i; + out.write("graph anchorlayout {\nnode [shape=\"rect\"]\n\n"); + for (i = 0; i < m_ui.items->rowCount(); ++i) { + // name, min, pref, max + QTableWidgetItem *item = m_ui.items->item(i, 0); + QGraphicsLayoutItem *li = layoutItem(item->data(Qt::UserRole)); + if (li == m_layout) + continue; + out.write(qPrintable(QString::fromAscii("%1 [label=\"%1\"]\n").arg(nodeName(li)))); + } + out.write("\n\n"); + static const char *compass = "wnes"; + for (i = 0; i < m_ui.anchors->rowCount(); ++i) { + // name, min, pref, max + bool ok; + QGraphicsLayoutItem *startItem = layoutItem(m_ui.anchors->item(i, 0)->data(Qt::UserRole)); + + QGraphicsAnchorLayout::Edge startEdge = (QGraphicsAnchorLayout::Edge)(m_ui.anchors->item(i, 1)->data(Qt::UserRole).toInt(&ok)); + if (!ok) + continue; + + QGraphicsLayoutItem *endItem = layoutItem(m_ui.anchors->item(i, 2)->data(Qt::UserRole)); + + QGraphicsAnchorLayout::Edge endEdge = (QGraphicsAnchorLayout::Edge)(m_ui.anchors->item(i, 3)->data(Qt::UserRole).toInt(&ok)); + if (!ok) + continue; + + out.write(qPrintable(QString::fromAscii("%1:%2--%3:%4 [label=\"[%5,%6]\"]\n") + .arg(nodeName(startItem)) + .arg(QLatin1Char(compass[int(startEdge)])) + .arg(nodeName(endItem)) + .arg(QLatin1Char(compass[int(endEdge)])) + .arg(1) + .arg(1) + .arg(2))); + } + out.write("}"); + out.close(); + } +#endif + return ok; +} + +static bool parseProperty(QXmlStreamReader *xml, QString *name, QSizeF *size) +{ + QString propName = xml->attributes().value("name").toString(); + QSizeF sz; + while (!xml->atEnd()) { + xml->readNext(); + if (xml->isStartElement() && xml->name() == QLatin1String("size")) { + QXmlStreamAttributes attrs = xml->attributes(); + QString sw = attrs.value("width").toString(); + QString sh = attrs.value("height").toString(); + bool ok; + float w = sw.toFloat(&ok); + if (ok) { + sz.setWidth(w); + } + + float h = sw.toFloat(&ok); + if (ok) { + sz.setHeight(h); + } + + } + if (xml->isEndElement() && xml->name() == QLatin1String("property")) { + if (name && size && sz.isValid()) { + *name = propName; + *size = sz; + return true; + } + } + } + return false; +} + +static bool parseEdge(const QString &itemEdge, QByteArray *id, QGraphicsAnchorLayout::Edge *edge) +{ + QStringList item_edge = itemEdge.split(QLatin1Char('.')); + bool ok = item_edge.count() == 2; + if (ok) { + QByteArray strEdge = item_edge.at(1).toAscii().toLower(); + if (strEdge == "left") { + *edge = QGraphicsAnchorLayout::Left; + } else if (strEdge == "hcenter") { + *edge = QGraphicsAnchorLayout::HCenter; + } else if (strEdge == "right") { + *edge = QGraphicsAnchorLayout::Right; + } else if (strEdge == "top") { + *edge = QGraphicsAnchorLayout::Top; + } else if (strEdge == "vcenter") { + *edge = QGraphicsAnchorLayout::VCenter; + } else if (strEdge == "bottom") { + *edge = QGraphicsAnchorLayout::Bottom; + } else { + ok = false; + } + if (ok) + *id = item_edge.at(0).toAscii(); + } + return ok; +} + +bool Window::loadLayout(const QString& fileName, QGraphicsAnchorLayout *layout) +{ + QFile input(fileName); + bool ok = input.open(QIODevice::ReadOnly | QIODevice::Text); + if (ok) { + int i; + for (i = 0; i < m_layoutItems.count(); ++i) { + QGraphicsLayoutItem *item = m_layoutItems.at(i); + delete item; + } + + m_layoutItems.clear(); + m_ui.anchors->setRowCount(0); + + QLatin1String str_anchorlayout("anchorlayout"); + QLatin1String str_item("item"); + QLatin1String str_property("property"); + QXmlStreamReader xml(&input); + + int level = 0; + QHash hash; + QString item_id; + QSizeF min, pref, max; + + while (!xml.atEnd()) { + QXmlStreamReader::TokenType token = xml.readNext(); + switch (token) { + case QXmlStreamReader::StartDocument: + break; + case QXmlStreamReader::StartElement: + if (level == 0 && xml.name() == str_anchorlayout) { + + } else if (level == 1 && xml.name() == str_item) { + item_id = xml.attributes().value("id").toString(); + } else if (level == 1 && xml.name() == QLatin1String("anchor")) { + QXmlStreamAttributes attrs = xml.attributes(); + QString first = attrs.value("first").toString(); + QString second = attrs.value("second").toString(); + QByteArray startID; + QGraphicsAnchorLayout::Edge startEdge; + QGraphicsLayoutItem *startItem = 0; + if (parseEdge(first, &startID, &startEdge)) { + if (startID == "this") { + startID = "layout"; + startItem = layout; + } else { + startItem = hash.value(startID); + } + } else { + qWarning("%s is not a valid edge description", qPrintable(first)); + break; + } + + QByteArray endID; + QGraphicsAnchorLayout::Edge endEdge; + QGraphicsLayoutItem *endItem = 0; + if (parseEdge(second, &endID, &endEdge)) { + if (endID == "this") { + endID = "layout"; + endItem = layout; + } else { + endItem = hash.value(endID); + } + } else { + qWarning("%s is not a valid edge description", qPrintable(second)); + break; + } + setAnchorData( startItem, startID, startEdge, + endItem, endID, endEdge, -1); + } else if (level == 2 && xml.name() == str_property) { + QString name; + QSizeF size; + if (parseProperty(&xml, &name, &size)) { + if (name == QLatin1String("minimumSize")) { + min = size; + } else if (name == QLatin1String("preferredSize")) { + pref = size; + } else if (name == QLatin1String("maximumSize")) { + max = size; + } + break; + } + } else { + --level; + } + ++level; + break; + case QXmlStreamReader::EndElement: + if (xml.name() == str_anchorlayout) { + } + if (xml.name() == str_item) { + QGraphicsLayoutItem *item = addItem(item_id); + item->setMinimumSize(min); + item->setPreferredSize(pref); + item->setMaximumSize(max); + hash.insert(item_id.toAscii(), item); + } + --level; + break; + } + } + if (xml.hasError()) { + // do error handling + qWarning("%s", qPrintable(xml.errorString())); + } + input.close(); + } + if (ok) + rebuildLayout(); + return ok; +} diff --git a/examples/layouts/anchorlayout/window.h b/examples/layouts/anchorlayout/window.h new file mode 100644 index 0000000..34be649 --- /dev/null +++ b/examples/layouts/anchorlayout/window.h @@ -0,0 +1,60 @@ +#ifndef WINDOW_H +#define WINDOW_H + +#include "ui_anchorlayout.h" +#include + +class QGraphicsWidget; +class Scene; + +class Window : public QMainWindow +{ + Q_OBJECT +public: + Window(QWidget *parent = 0); + +private slots: + void on_anchors_cellChanged(int row, int column); + void on_pbAddAnchor_clicked(bool); + void on_actionAdd_item_triggered(bool checked); + void on_layouts_currentRowChanged(int row); + void on_itemName_textEdited(const QString &text); + void on_itemMinW_valueChanged(double d); + void on_itemMinH_valueChanged(double d); + void on_itemPrefW_valueChanged(double d); + void on_itemPrefH_valueChanged(double d); + void on_itemMaxW_valueChanged(double d); + void on_itemMaxH_valueChanged(double d); + + + + // not in ui file + void scene_focusItemChanged(QGraphicsItem *item); +private: + void updateItem(); + void setItemData(const QString &name, const QSizeF &min, const QSizeF &pref, const QSizeF &max); + QGraphicsLayoutItem *addItem(const QString &name = QString()); + void addAnchorRow(); + void setAnchorData(QGraphicsLayoutItem *startItem, const QString &startName, QGraphicsAnchorLayout::Edge startEdge, + QGraphicsLayoutItem *endItem, const QString &endName, QGraphicsAnchorLayout::Edge endEdge, int row = -1); + + bool saveLayout(const QString& fileName); + bool loadLayout(const QString& fileName, QGraphicsAnchorLayout *layout); + void findLayoutFiles(); + + void rebuildLayout(); + QGraphicsLayoutItem *layoutItemAt(QAbstractItemModel *mode, int row, int column = 0); + + Ui::MainWindow m_ui; + Scene *m_scene; + bool m_changingCell; + QGraphicsWidget *m_window; + QGraphicsAnchorLayout *m_layout; + QVector m_layoutItems; + QGraphicsLayoutItem *m_currentItem; + bool m_inAddAnchor; + bool m_ignoreCurrentLayoutChange; +}; + +#endif // WINDOW_H + diff --git a/examples/layouts/anchorlayout/xml/linear.xml b/examples/layouts/anchorlayout/xml/linear.xml new file mode 100644 index 0000000..723b72b --- /dev/null +++ b/examples/layouts/anchorlayout/xml/linear.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/layouts/anchorlayout/xml/snake.xml b/examples/layouts/anchorlayout/xml/snake.xml new file mode 100644 index 0000000..22b1a6d --- /dev/null +++ b/examples/layouts/anchorlayout/xml/snake.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v0.12