diff options
| author | Frank Gevaerts <frank@gevaerts.be> | 2008-08-29 21:08:38 +0000 |
|---|---|---|
| committer | Frank Gevaerts <frank@gevaerts.be> | 2008-08-29 21:08:38 +0000 |
| commit | 5d22e3cbdd251819a4d2d07b9a12994d5aef778d (patch) | |
| tree | 4c6a81187ccf065a5f296a903b9f7da88503e403 /utils/wpseditor/gui/src | |
| parent | cc31b1fbdae455f975b69dd6bffc23d8bd021566 (diff) | |
| download | rockbox-5d22e3cbdd251819a4d2d07b9a12994d5aef778d.zip rockbox-5d22e3cbdd251819a4d2d07b9a12994d5aef778d.tar.gz rockbox-5d22e3cbdd251819a4d2d07b9a12994d5aef778d.tar.bz2 rockbox-5d22e3cbdd251819a4d2d07b9a12994d5aef778d.tar.xz | |
Add wpseditor, the Google Summer of Code 2008 project of Rostislav Chekan. Closes FS#9327
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18362 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/wpseditor/gui/src')
25 files changed, 1936 insertions, 0 deletions
diff --git a/utils/wpseditor/gui/src/QPropertyEditor/ColorCombo.cpp b/utils/wpseditor/gui/src/QPropertyEditor/ColorCombo.cpp new file mode 100644 index 0000000..f5eeb03 --- /dev/null +++ b/utils/wpseditor/gui/src/QPropertyEditor/ColorCombo.cpp @@ -0,0 +1,73 @@ +// ************************************************************************************************* +// +// QPropertyEditor v 0.1 +// +// -------------------------------------- +// Copyright (C) 2007 Volker Wiendl +// +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// +// This class is based on the Color Editor Factory Example by Trolltech +// +// ************************************************************************************************* + +#include "ColorCombo.h" + +#include <Qt/qcolordialog.h> + +ColorCombo::ColorCombo(QWidget* parent /*= 0*/) : QComboBox(parent) { + QStringList colorNames = QColor::colorNames(); + for (int i = 0; i < colorNames.size(); ++i) { + QColor color(colorNames[i]); + insertItem(i, colorNames[i]); + setItemData(i, color, Qt::DecorationRole); + } + addItem(tr("Custom"), QVariant((int)QVariant::UserType)); + connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(currentChanged(int))); +} + + +ColorCombo::~ColorCombo() {} + + +QColor ColorCombo::color() const { + return qVariantValue<QColor>(itemData(currentIndex(), Qt::DecorationRole)); +} + +void ColorCombo::setColor(QColor color) { + m_init = color; + setCurrentIndex(findData(color, int(Qt::DecorationRole))); + if (currentIndex() == -1) { + addItem(color.name()); + setItemData(count()-1, color, Qt::DecorationRole); + setCurrentIndex(count()-1); + } +} + +void ColorCombo::currentChanged(int index) { + if (itemData(index).isValid() && itemData(index) == QVariant((int)QVariant::UserType)) { + QColor color = QColorDialog::getColor(m_init, this); + if (color.isValid()) { + if (findData(color, int(Qt::DecorationRole)) == -1) { + addItem(color.name()); + setItemData(count()-1, color, Qt::DecorationRole); + } + setCurrentIndex(findData(color, int(Qt::DecorationRole))); + } else + setCurrentIndex(findData(m_init)); + } +} diff --git a/utils/wpseditor/gui/src/QPropertyEditor/ColorCombo.h b/utils/wpseditor/gui/src/QPropertyEditor/ColorCombo.h new file mode 100644 index 0000000..530b05b --- /dev/null +++ b/utils/wpseditor/gui/src/QPropertyEditor/ColorCombo.h @@ -0,0 +1,49 @@ +// ************************************************************************************************* +// +// QPropertyEditor v 0.1 +// +// -------------------------------------- +// Copyright (C) 2007 Volker Wiendl +// +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// +// This class is based on the Color Editor Factory Example by Trolltech +// +// ************************************************************************************************* + +#ifndef COLORCOMBO_H_ +#define COLORCOMBO_H_ + +#include <Qt/qcombobox.h> + +class ColorCombo : public QComboBox { + Q_OBJECT +public: + ColorCombo(QWidget* parent = 0); + virtual ~ColorCombo(); + + QColor color() const; + void setColor(QColor c); + +private slots: + void currentChanged(int index); + +private: + QColor m_init; + +}; +#endif diff --git a/utils/wpseditor/gui/src/QPropertyEditor/Property.cpp b/utils/wpseditor/gui/src/QPropertyEditor/Property.cpp new file mode 100644 index 0000000..0746d15 --- /dev/null +++ b/utils/wpseditor/gui/src/QPropertyEditor/Property.cpp @@ -0,0 +1,136 @@ +// **************************************************************************************** +// +// QPropertyEditor Library +// -------------------------------------- +// Copyright (C) 2007 Volker Wiendl +// +// This file is part of the Horde3D Scene Editor. +// +// The QPropertyEditor Library 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 version 3 of the License +// +// The Horde3D Scene Editor 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, see <http://www.gnu.org/licenses/>. +// +// **************************************************************************************** + +#include "Property.h" +#include "ColorCombo.h" + +#include <Qt/qmetaobject.h> +#include <Qt/qspinbox.h> + +#include <limits.h> + +Property::Property(const QString& name /*= QString()*/, QObject* propertyObject /*= 0*/, QObject* parent /*= 0*/) : QObject(parent), + m_propertyObject(propertyObject) { + setObjectName(name); +} + +QVariant Property::value(int /*role = Qt::UserRole*/) const { + if (m_propertyObject) + return m_propertyObject->property(qPrintable(objectName())); + else + return QVariant(); +} + +void Property::setValue(const QVariant &value) { + if (m_propertyObject) + m_propertyObject->setProperty(qPrintable(objectName()), value); +} + +bool Property::isReadOnly() { + if (m_propertyObject && m_propertyObject->metaObject()->property(m_propertyObject->metaObject()->indexOfProperty(qPrintable(objectName()))).isWritable()) + return false; + else + return true; +} + +QWidget* Property::createEditor(QWidget *parent, const QStyleOptionViewItem &option) { + (void)option; + QWidget* editor = 0; + switch (value().type()) { + case QVariant::Color: + editor = new ColorCombo(parent); + break; + case QVariant::Int: + editor = new QSpinBox(parent); + editor->setProperty("minimum", -INT_MAX); + editor->setProperty("maximum", INT_MAX); + connect(editor, SIGNAL(valueChanged(int)), this, SLOT(setValue(int))); + break; + case QMetaType::Float: + case QVariant::Double: + editor = new QDoubleSpinBox(parent); + editor->setProperty("minimum", -INT_MAX); + editor->setProperty("maximum", INT_MAX); + connect(editor, SIGNAL(valueChanged(double)), this, SLOT(setValue(double))); + break; + default: + return editor; + } + return editor; +} + +bool Property::setEditorData(QWidget *editor, const QVariant &data) { + switch (value().type()) { + case QVariant::Color: + static_cast<ColorCombo*>(editor)->setColor(data.value<QColor>()); + return true; + ; + case QVariant::Int: + editor->blockSignals(true); + static_cast<QSpinBox*>(editor)->setValue(data.toInt()); + editor->blockSignals(false); + return true; + case QMetaType::Float: + case QVariant::Double: + editor->blockSignals(true); + static_cast<QDoubleSpinBox*>(editor)->setValue(data.toDouble()); + editor->blockSignals(false); + return true; + default: + return false; + } + return false; +} + +QVariant Property::editorData(QWidget *editor) { + switch (value().type()) { + case QVariant::Color: + return QVariant::fromValue(static_cast<ColorCombo*>(editor)->color()); + case QVariant::Int: + return QVariant(static_cast<QSpinBox*>(editor)->value()); + case QMetaType::Float: + case QVariant::Double: + return QVariant(static_cast<QDoubleSpinBox*>(editor)->value()); + break; + default: + return QVariant(); + } +} + +Property* Property::findPropertyObject(QObject* propertyObject) { + if (m_propertyObject == propertyObject) + return this; + for (int i=0; i<children().size(); ++i) { + Property* child = static_cast<Property*>(children()[i])->findPropertyObject(propertyObject); + if (child) + return child; + } + return 0; +} + +void Property::setValue(double value) { + setValue(QVariant(value)); +} + +void Property::setValue(int value) { + setValue(QVariant(value)); +} diff --git a/utils/wpseditor/gui/src/QPropertyEditor/Property.h b/utils/wpseditor/gui/src/QPropertyEditor/Property.h new file mode 100644 index 0000000..52d6842 --- /dev/null +++ b/utils/wpseditor/gui/src/QPropertyEditor/Property.h @@ -0,0 +1,157 @@ +// ************************************************************************************************* +// +// QPropertyEditor v 0.1 +// +// -------------------------------------- +// Copyright (C) 2007 Volker Wiendl +// +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// ************************************************************************************************* + +#ifndef PROPERTY_H_ +#define PROPERTY_H_ + +#include <Qt/qwidget.h> +#include <Qt/qstyleoption.h> +#include <Qt/qvariant.h> + +/** + * The Property class is the base class for all properties in the QPropertyEditor + * You can implement custom properties inherited from this class to further enhence the + * functionality of the QPropertyEditor + */ +class Property : public QObject { + Q_OBJECT + +public: + + /** + * Constructor + * + * @param name the name of the property within the propertyObject (will be used in the QPropertyEditorWidget view too) + * @param propertyObject the object that contains the property + * @param parent optional parent object + */ + Property(const QString& name = QString(), QObject* propertyObject = 0, QObject* parent = 0); + + /** + * The value stored by this property + * @return QVariant the data converted to a QVariant + */ + virtual QVariant value(int role = Qt::UserRole) const; + /** + * Sets the value stored by this property + * @param value the data converted to a QVariant + */ + virtual void setValue(const QVariant& value); + + /** + * Returns the QObject which contains the property managed by this instance + * @return QObject* pointer to the QObject that contains user defined properties + */ + QObject* propertyObject() { + return m_propertyObject; + } + + /** + * Flag if property is used for indicating a group or really manages a property + * @return bool true if this property is only used to display a category in the QPropertyEditorWidget + */ + bool isRoot() { + return m_propertyObject == 0; + } + + /** + * Flag if the property can be set + * @return bool true if this property has no set method + */ + bool isReadOnly(); + + /** + * Returns the row of this instance within the QPropertyModel + * @return int row within the QPropertyModel + */ + int row() { + return parent()->children().indexOf(this); + } + + /** + * returns optional settings for the editor widget that is used to manipulate the properties value + * @return QString a string that contains property settings for the editor widget (e.g. "minimum=1.0;maximum=10.0;") + */ + QString editorHints() { + return m_hints; + } + + /** + * Sets properties for the editor widget that is used to manipulate the data value managed by this instance + * @param hints a string containing property settings for the editor widget that manipulates this property + */ + virtual void setEditorHints(const QString& hints) { + m_hints = hints; + } + + /** + * Creates an editor for the data managed by this instance + * @param parent widget the newly created editor widget will be child of + * @param option currently not used + * @return QWidget* pointer to the editor widget + */ + virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option); + + /** + * Returns the data of the editor widget used to manipulate this instance + * @return QVariant the data converted to a QVariant + */ + virtual QVariant editorData(QWidget *editor); + + /** + * Changes the editor widget's data to a specific value + * @param editor the editor widget + * @param data the data to set in the editor widget + * @return bool true if editor widget was set to the given data successfully, false if the data can not be set in the editor (e.g. wrong datatype) + */ + virtual bool setEditorData(QWidget *editor, const QVariant& data); + + /** + * Tries to find the first property that manages the given propertyObject + * @param propertyObject + * @return Property + */ + Property* findPropertyObject(QObject* propertyObject); + +private slots: + /** + * This slot is used to immediately set the properties when the editor widget's value of a double or float + * property has changed + * @param value the new value + */ + void setValue(double value); + /** + * This slot is used to immediately set the properties when the editor widget's value of an integer + * property has changed + * @param value the new value + */ + void setValue(int value); + +private: + QObject* m_propertyObject; + QString m_hints; + +}; + +#endif diff --git a/utils/wpseditor/gui/src/QPropertyEditor/QPropertyEditor.pro b/utils/wpseditor/gui/src/QPropertyEditor/QPropertyEditor.pro new file mode 100644 index 0000000..85fd29e --- /dev/null +++ b/utils/wpseditor/gui/src/QPropertyEditor/QPropertyEditor.pro @@ -0,0 +1,26 @@ +TEMPLATE = lib +CONFIG += staticlib debug_and_release +SOURCES = ColorCombo.cpp \ + Property.cpp \ + QPropertyEditorWidget.cpp \ + QPropertyModel.cpp \ + QVariantDelegate.cpp +HEADERS = ColorCombo.h \ + Property.h \ + QPropertyEditorWidget.h \ + QPropertyModel.h \ + QVariantDelegate.h +INCLUDEPATH += . +DESTDIR = ../../lib +UI_DIR = . +CONFIG(debug, debug|release) { + TARGET = QPropertyEditord + OBJECTS_DIR = ../../build/QPropertyEditor/debug + MOC_DIR = ../../build/QPropertyEditor/debug +} +CONFIG(release, debug|release) { + TARGET = QPropertyEditor + OBJECTS_DIR = ../../build/QPropertyEditor/release + MOC_DIR = ../../build/QPropertyEditor/release + DEFINES += QT_NO_DEBUG +} diff --git a/utils/wpseditor/gui/src/QPropertyEditor/QPropertyEditorWidget.cpp b/utils/wpseditor/gui/src/QPropertyEditor/QPropertyEditorWidget.cpp new file mode 100644 index 0000000..fc4b90c --- /dev/null +++ b/utils/wpseditor/gui/src/QPropertyEditor/QPropertyEditorWidget.cpp @@ -0,0 +1,56 @@ +// ************************************************************************************************* +// +// QPropertyEditor v 0.1 +// +// -------------------------------------- +// Copyright (C) 2007 Volker Wiendl +// +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// ************************************************************************************************* + +#include "QPropertyEditorWidget.h" +#include "QPropertyModel.h" +#include "QVariantDelegate.h" +#include "Property.h" + +QPropertyEditorWidget::QPropertyEditorWidget(QWidget* parent /*= 0*/) : QTreeView(parent) { + m_model = new QPropertyModel(this); + setModel(m_model); + setItemDelegate(new QVariantDelegate(this)); +} + + +QPropertyEditorWidget::~QPropertyEditorWidget() {} + +void QPropertyEditorWidget::addObject(QObject* propertyObject) { + m_model->addItem(propertyObject); + expandToDepth(0); +} + +void QPropertyEditorWidget::setObject(QObject* propertyObject) { + m_model->clear(); + if (propertyObject) + addObject(propertyObject); +} + +void QPropertyEditorWidget::updateObject(QObject* propertyObject) { + m_model->updateItem(propertyObject); +} + +void QPropertyEditorWidget::setCustomPropertyCB(UserTypeCB callback) { + m_model->setCustomPropertyCB(callback); +} diff --git a/utils/wpseditor/gui/src/QPropertyEditor/QPropertyEditorWidget.h b/utils/wpseditor/gui/src/QPropertyEditor/QPropertyEditorWidget.h new file mode 100644 index 0000000..2dab877 --- /dev/null +++ b/utils/wpseditor/gui/src/QPropertyEditor/QPropertyEditorWidget.h @@ -0,0 +1,113 @@ +// ************************************************************************************************* +// +// QPropertyEditor v 0.1 +// +// -------------------------------------- +// Copyright (C) 2007 Volker Wiendl +// +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// ************************************************************************************************* + +#ifndef QPROPERTYEDITORWIDGET_H_ +#define QPROPERTYEDITORWIDGET_H_ + +#include <Qt/qtreeview.h> + +class QPropertyModel; +class Property; + +/** + * \mainpage QPropertyEditor + * + * \section intro_sec Introduction + * + * The main purpose for the QPropertyEditor is the visualization and manipulation of properties defined via the Q_PROPERTY macro in + * QObject based classes. + */ + +/** + * \brief The QPropertyEditorWidget offers an easy to use mechanism to visualize properties of a class inherited from QObject. + * + * Qt provides a nice way to define class properties by using the Q_PROPERTY macro. The purpose of the QPropertyEditor + * is to visualize these properties in an easy way. + * + * To use the property editor, all you have to do is to create a class that defines it's properties by using Q_PROPERTY + * and to add this class by using the addObject() method of this QPropertyEditorWidget class. + * The QPropertyEditorWidget is inherited from QTreeView and will display the properties in a tree with two columns: Name and Value + * + * For basic data types the build in editor widgets of Qt will be used. The QPropertyEditor itself only defines an additional + * editor for QColor (based on the Color Editor Factory Example from Trolltech). But it can easily be extended by yourself + * either within the library or for special datatypes also outside of the library in your application. + */ +class QPropertyEditorWidget : public QTreeView { + Q_OBJECT +public: + + /** + * A typedef for a callback used to create user defined properties for custom datatypes + */ + typedef Property* (*UserTypeCB)(const QString& name, QObject* propertyObject, Property* parent); + + /** + * \brief Constructor + * + * Creates a new editor widget based on QTreeView + * @param parent optional parent widget + */ + QPropertyEditorWidget(QWidget* parent = 0); + + /// Destructor + virtual ~QPropertyEditorWidget(); + + /** + * Adds the user properties of the given class to the QPropertyModel associated with this view + * + * @param propertyObject the class inherited from QObject that contains user properties that should be + * managed by the QPropertyModel associated with this view + */ + void addObject(QObject* propertyObject); + + /** + * Similar to the addObject() method this method adds the properties of the given class to the QPropertyModel + * associated with this view. But in contrast to addObject() it will clear the model before, removing all + * previously added objects. + * + * @param propertyObject the class inherited from QObject that contains user properties that should be + * managed by the QPropertyModel associated with this view + */ + void setObject(QObject* propertyObject); + + /** + * Updates the view for the given object. This can be usefull if a property was changed programmatically instead + * of using the view. In this case the view normally will display the new property values only after the user clicked + * on it. To overcome this problem you can call updateObject with the object whose property was changed. + */ + void updateObject(QObject* propertyObject); + + /** + * If you define custom datatypes outside of this library the QPropertyModel will check if you + * also defined a callback that is responsible to create custom property classes inherited from Property to handle + * these datatypes. With this method you can set such a callback that will create custom properties for custom datatypes. + */ + void setCustomPropertyCB(UserTypeCB callback); + +private: + /// The Model for this view + QPropertyModel* m_model; + +}; +#endif diff --git a/utils/wpseditor/gui/src/QPropertyEditor/QPropertyModel.cpp b/utils/wpseditor/gui/src/QPropertyEditor/QPropertyModel.cpp new file mode 100644 index 0000000..b147cd0 --- /dev/null +++ b/utils/wpseditor/gui/src/QPropertyEditor/QPropertyModel.cpp @@ -0,0 +1,236 @@ +// ************************************************************************************************* +// +// QPropertyEditor v 0.1 +// +// -------------------------------------- +// Copyright (C) 2007 Volker Wiendl +// +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// ************************************************************************************************* + +#include "QPropertyModel.h" + +#include "Property.h" + +#include <Qt/qapplication.h> +#include <Qt/qmetaobject.h> +#include <Qt/qitemeditorfactory.h> + +struct PropertyPair { + PropertyPair(const QMetaObject* obj, QMetaProperty property) : Property(property), Object(obj) {} + + QMetaProperty Property; + const QMetaObject* Object; + + bool operator==(const PropertyPair& other) const { + return QString(other.Property.name()) == QString(Property.name()); + } +}; + + +QPropertyModel::QPropertyModel(QObject* parent /*= 0*/) : QAbstractItemModel(parent), m_userCallback(0) { + m_rootItem = new Property("Root",0, this); +} + + +QPropertyModel::~QPropertyModel() {} + +QModelIndex QPropertyModel::index ( int row, int column, const QModelIndex & parent /*= QModelIndex()*/ ) const { + Property *parentItem = m_rootItem; + if (parent.isValid()) + parentItem = static_cast<Property*>(parent.internalPointer()); + if (row >= parentItem->children().size()) + return QModelIndex(); + return createIndex(row, column, parentItem->children().at(row)); + +} + +QModelIndex QPropertyModel::parent ( const QModelIndex & index ) const { + if (!index.isValid()) + return QModelIndex(); + + Property *childItem = static_cast<Property*>(index.internalPointer()); + Property *parentItem = qobject_cast<Property*>(childItem->parent()); + + if (!parentItem || parentItem == m_rootItem) + return QModelIndex(); + + return createIndex(parentItem->row(), 0, parentItem); +} + +int QPropertyModel::rowCount ( const QModelIndex & parent /*= QModelIndex()*/ ) const { + Property *parentItem = m_rootItem; + if (parent.isValid()) + parentItem = static_cast<Property*>(parent.internalPointer()); + return parentItem->children().size(); +} + +int QPropertyModel::columnCount ( const QModelIndex & parent /*= QModelIndex()*/ ) const { + (void)parent; + return 2; +} + +QVariant QPropertyModel::data ( const QModelIndex & index, int role /*= Qt::DisplayRole*/ ) const { + if (!index.isValid()) + return QVariant(); + + Property *item = static_cast<Property*>(index.internalPointer()); + switch (role) { + case Qt::ToolTipRole: + case Qt::DecorationRole: + case Qt::DisplayRole: + case Qt::EditRole: + if (index.column() == 0) + return item->objectName(); + if (index.column() == 1) + return item->value(role); + case Qt::BackgroundRole: + if (item->isRoot()) return QApplication::palette("QTreeView").brush(QPalette::Normal, QPalette::Button).color(); + break; + }; + return QVariant(); +} + +// edit methods +bool QPropertyModel::setData ( const QModelIndex & index, const QVariant & value, int role /*= Qt::EditRole*/ ) { + if (index.isValid() && role == Qt::EditRole) { + Property *item = static_cast<Property*>(index.internalPointer()); + item->setValue(value); + emit dataChanged(index, index); + return true; + } + return false; +} + +Qt::ItemFlags QPropertyModel::flags ( const QModelIndex & index ) const { + if (!index.isValid()) + return Qt::ItemIsEnabled; + Property *item = static_cast<Property*>(index.internalPointer()); + // only allow change of value attribute + if (item->isRoot()) + return Qt::ItemIsEnabled; + else if (item->isReadOnly()) + return Qt::ItemIsDragEnabled | Qt::ItemIsSelectable; + else + return Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; +} + + +QVariant QPropertyModel::headerData ( int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole*/ ) const { + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { + switch (section) { + case 0: + return tr("Name"); + case 1: + return tr("Value"); + } + } + return QVariant(); +} + +QModelIndex QPropertyModel::buddy ( const QModelIndex & index ) const { + if (index.isValid() && index.column() == 0) + return createIndex(index.row(), 1, index.internalPointer()); + return index; +} + +void QPropertyModel::addItem(QObject *propertyObject) { + // first create property <-> class hierarchy + QList<PropertyPair> propertyMap; + QList<const QMetaObject*> classList; + const QMetaObject* metaObject = propertyObject->metaObject(); + do { + int count = metaObject->propertyCount(); + for (int i=0; i<count; ++i) { + QMetaProperty property = metaObject->property(i); + if (property.isUser()) // Hide Qt specific properties + { + PropertyPair pair(metaObject, property); + int index = propertyMap.indexOf(pair); + if (index != -1) + propertyMap[index] = pair; + else + propertyMap.push_back(pair); + } + } + classList.push_front(metaObject); + } while ((metaObject = metaObject->superClass())!=0); + + QList<const QMetaObject*> finalClassList; + // remove empty classes from hierarchy list + foreach(const QMetaObject* obj, classList) { + bool keep = false; + foreach(PropertyPair pair, propertyMap) { + if (pair.Object == obj) { + keep = true; + break; + } + } + if (keep) + finalClassList.push_back(obj); + } + + // finally insert properties for classes containing them + int i=rowCount(); + beginInsertRows(QModelIndex(), i, i + finalClassList.count()); + foreach(const QMetaObject* metaObject, finalClassList) { + // Set default name of the hierarchy property to the class name + QString name = metaObject->className(); + // Check if there is a special name for the class + int index = metaObject->indexOfClassInfo(qPrintable(name)); + if (index != -1) + name = metaObject->classInfo(index).value(); + // Create Property Item for class node + Property* propertyItem = new Property(name, 0, m_rootItem); + foreach(PropertyPair pair, propertyMap) { + // Check if the property is associated with the current class from the finalClassList + if (pair.Object == metaObject) { + QMetaProperty property(pair.Property); + Property* p = 0; + if (property.type() == QVariant::UserType && m_userCallback) + p = m_userCallback(property.name(), propertyObject, propertyItem); + else + p = new Property(property.name(), propertyObject, propertyItem); + int index = metaObject->indexOfClassInfo(property.name()); + if (index != -1) + p->setEditorHints(metaObject->classInfo(index).value()); + } + } + } + endInsertRows(); +} + +void QPropertyModel::updateItem ( QObject* propertyObject, const QModelIndex& parent /*= QModelIndex() */ ) { + Property *parentItem = m_rootItem; + if (parent.isValid()) + parentItem = static_cast<Property*>(parent.internalPointer()); + if (parentItem->propertyObject() != propertyObject) + parentItem = parentItem->findPropertyObject(propertyObject); + if (parentItem) // Indicate view that the data for the indices have changed + dataChanged(createIndex(parentItem->row(), 0, static_cast<Property*>(parentItem)), createIndex(parentItem->row(), 1, static_cast<Property*>(parentItem))); +} + +void QPropertyModel::clear() { + beginRemoveRows(QModelIndex(), 0, rowCount()); + delete m_rootItem; + m_rootItem = new Property("Root",0, this); + endRemoveRows(); +} + +void QPropertyModel::setCustomPropertyCB(QPropertyEditorWidget::UserTypeCB callback) { + m_userCallback = callback; +} diff --git a/utils/wpseditor/gui/src/QPropertyEditor/QPropertyModel.h b/utils/wpseditor/gui/src/QPropertyEditor/QPropertyModel.h new file mode 100644 index 0000000..8a52bbe --- /dev/null +++ b/utils/wpseditor/gui/src/QPropertyEditor/QPropertyModel.h @@ -0,0 +1,105 @@ +// ************************************************************************************************* +// +// QPropertyEditor v 0.1 +// +// -------------------------------------- +// Copyright (C) 2007 Volker Wiendl +// +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// ************************************************************************************************* +#ifndef QPROPERTYMODEL_H_ +#define QPROPERTYMODEL_H_ + +#include <Qt/qabstractitemmodel.h> +#include <Qt/qmap.h> + +#include "QPropertyEditorWidget.h" + +class Property; + +/** + * The QPropertyModel handles the user defined properties of QObjects + */ +class QPropertyModel : public QAbstractItemModel { + Q_OBJECT +public: + /** + * Constructor + * @param parent optional parent object + */ + QPropertyModel(QObject* parent = 0); + /// Destructor + virtual ~QPropertyModel(); + + /// QAbstractItemModel implementation + QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const; + + /// QAbstractItemModel implementation + QModelIndex parent ( const QModelIndex & index ) const; + /// QAbstractItemModel implementation + int rowCount ( const QModelIndex & parent = QModelIndex() ) const; + /// QAbstractItemModel implementation + int columnCount ( const QModelIndex & parent = QModelIndex() ) const; + /// QAbstractItemModel implementation + QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const; + + /// QAbstractItemModel implementation + bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); + /// QAbstractItemModel implementation + Qt::ItemFlags flags ( const QModelIndex & index ) const; + + /// QAbstractItemModel implementation + QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; + + /// QAbstractItemModel implementation + QModelIndex buddy ( const QModelIndex & index ) const; + + /** + * Adds the user properties of the given class to the QPropertyModel instance + * + * @param propertyObject the class inherited from QObject that contains user properties that should be + * managed by this instance + */ + void addItem(QObject* propertyObject); + + /** + * Creates a dataChanged signal for the given object + * @param propertyObject the instance of a QObject based class that should be updated + * @param parent optional model index the propertyObject is child of + */ + void updateItem ( QObject* propertyObject, const QModelIndex& parent = QModelIndex() ) ; + + /** + * Removes all objects from the model + */ + void clear(); + + /** + * Sets custom callback that will be used to create Property instances for custom datatypes + */ + void setCustomPropertyCB(QPropertyEditorWidget::UserTypeCB callback); + +private: + + /// The Root Property for all objects + Property* m_rootItem; + + /// Custom callback + QPropertyEditorWidget::UserTypeCB m_userCallback; + +}; +#endif diff --git a/utils/wpseditor/gui/src/QPropertyEditor/QVariantDelegate.cpp b/utils/wpseditor/gui/src/QPropertyEditor/QVariantDelegate.cpp new file mode 100644 index 0000000..ebda9b2 --- /dev/null +++ b/utils/wpseditor/gui/src/QPropertyEditor/QVariantDelegate.cpp @@ -0,0 +1,105 @@ +// ************************************************************************************************* +// +// QPropertyEditor v 0.1 +// +// -------------------------------------- +// Copyright (C) 2007 Volker Wiendl +// +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// ************************************************************************************************* + +#include "QVariantDelegate.h" + +#include "Property.h" + +#include <Qt/qabstractitemview.h> + + +QVariantDelegate::QVariantDelegate(QObject* parent) : QItemDelegate(parent) {} + + +QVariantDelegate::~QVariantDelegate() {} + +QWidget *QVariantDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& option , const QModelIndex & index ) const { + QWidget* editor = 0; + Property* p = static_cast<Property*>(index.internalPointer()); + switch (p->value().type()) { + case QVariant::Color: + case QVariant::Int: + case QMetaType::Float: + case QVariant::Double: + case QVariant::UserType: + editor = p->createEditor(parent, option); + if (editor) break; // if no editor could be created take default case + default: + editor = QItemDelegate::createEditor(parent, option, index); + } + parseEditorHints(editor, p->editorHints()); + return editor; +} + +void QVariantDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { + QVariant data = index.model()->data(index, Qt::EditRole); + switch (data.type()) { + case QVariant::Color: + case QMetaType::Double: + case QMetaType::Float: + case QVariant::UserType: + if (static_cast<Property*>(index.internalPointer())->setEditorData(editor, data)) // if editor couldn't be recognized use default + break; + default: + QItemDelegate::setEditorData(editor, index); + break; + } +} + +void QVariantDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { + QVariant data = index.model()->data(index, Qt::EditRole); + switch (data.type()) { + case QVariant::Color: + case QMetaType::Double: + case QMetaType::Float: + case QVariant::UserType: { + QVariant data = static_cast<Property*>(index.internalPointer())->editorData(editor); + if (data.isValid()) { + model->setData(index, data , Qt::EditRole); + break; + } + } + default: + QItemDelegate::setModelData(editor, model, index); + break; + } +} + +void QVariantDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex& index ) const { + return QItemDelegate::updateEditorGeometry(editor, option, index); +} + +void QVariantDelegate::parseEditorHints(QWidget* editor, const QString& editorHints) const { + if (editor && !editorHints.isEmpty()) { + // Parse for property values + QRegExp rx("(.*)(=\\s*)(.*)(;{1})"); + rx.setMinimal(true); + int pos = 0; + while ((pos = rx.indexIn(editorHints, pos)) != -1) { + qDebug("Setting %s to %s", qPrintable(rx.cap(1)), qPrintable(rx.cap(3))); + editor->setProperty(qPrintable(rx.cap(1).trimmed()), rx.cap(3).trimmed()); + pos += rx.matchedLength(); + } + } +} diff --git a/utils/wpseditor/gui/src/QPropertyEditor/QVariantDelegate.h b/utils/wpseditor/gui/src/QPropertyEditor/QVariantDelegate.h new file mode 100644 index 0000000..e06265a --- /dev/null +++ b/utils/wpseditor/gui/src/QPropertyEditor/QVariantDelegate.h @@ -0,0 +1,78 @@ +// ************************************************************************************************* +// +// QPropertyEditor v 0.1 +// +// -------------------------------------- +// Copyright (C) 2007 Volker Wiendl +// +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// ************************************************************************************************* + +#ifndef COLORSELECTIONBUTTON_H_ +#define COLORSELECTIONBUTTON_H_ + +#include <Qt/qitemdelegate.h> + + +/** + * This class is used to create the editor widgets for datatypes encapsulated in QVariant variables + */ +class QVariantDelegate : public QItemDelegate { + Q_OBJECT + +public: + /** + * Constructor + * @param parent optional parent object + */ + QVariantDelegate(QObject* parent = 0); + /// Destructor + virtual ~QVariantDelegate(); + + /** + * Creates an editor widget as child of a given widget for a specific QModelIndex + * + * @param parent the parent widget for the editor + * @param option some style options that the editor should use + * @param index the index of the item the editor will be created for + * @return QWidget the editor widget + */ + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; + + /** + * Tries to set the editor data based on the value stored at a specific QModelIndex + * @param editor the editor widget + * @param index the model index of the value that should be used in the editor + */ + virtual void setEditorData(QWidget *editor, const QModelIndex &index) const; + + /** + * Sets the data of a specific QModelIndex to tha value of the editor widget + * @param editor the editor widget that contains the new value + * @param model the model that contains the index + * @param index the index within the model whose data value should be set to the data value of the editor + */ + virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; + + /// QItemDelegate implementation + virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; + +protected: + void parseEditorHints(QWidget* editor, const QString& editorHints) const; + +}; +#endif diff --git a/utils/wpseditor/gui/src/main.cpp b/utils/wpseditor/gui/src/main.cpp new file mode 100644 index 0000000..0ba22c9 --- /dev/null +++ b/utils/wpseditor/gui/src/main.cpp @@ -0,0 +1,16 @@ +#include <QApplication> +#include "qwpseditorwindow.h" +#include "utils.h" +#include <QPointer> + +QPointer<QWpsEditorWindow> win; + +int main(int argc, char ** argv) { + QApplication app( argc, argv ); + + win = new QWpsEditorWindow; + win->show(); + app.connect( &app, SIGNAL( lastWindowClosed() ), &app, SLOT( quit() ) ); + + return app.exec(); +} diff --git a/utils/wpseditor/gui/src/qtrackstate.cpp b/utils/wpseditor/gui/src/qtrackstate.cpp new file mode 100644 index 0000000..dad2f9a --- /dev/null +++ b/utils/wpseditor/gui/src/qtrackstate.cpp @@ -0,0 +1,41 @@ +#include "qtrackstate.h" +#include <stdlib.h> + +// +QTrackState::QTrackState( ) + : QObject() { + memset(&state,0,sizeof(state)); + state.title = (char*)"title"; + state.artist = (char*)"artist"; + state.album = (char*)"album"; + state.length = 100; + state.elapsed = 50; +} + +void QTrackState::setTitle(const QString& name) { + state.title = new char[name.length()]; + strcpy(state.title,name.toAscii()); + emit stateChanged(state); +} + +void QTrackState::setArtist(const QString& name) { + state.artist = new char[name.length()]; + strcpy(state.artist,name.toAscii()); + emit stateChanged(state); +} + +void QTrackState::setAlbum(const QString& name) { + state.album = new char[name.length()]; + strcpy(state.album,name.toAscii()); + emit stateChanged(state); +} + +void QTrackState::setLength(int le) { + state.length = le; + emit stateChanged(state); +} + +void QTrackState::setElapsed(int le) { + state.elapsed = le; + emit stateChanged(state); +} diff --git a/utils/wpseditor/gui/src/qtrackstate.h b/utils/wpseditor/gui/src/qtrackstate.h new file mode 100644 index 0000000..b57f7a8 --- /dev/null +++ b/utils/wpseditor/gui/src/qtrackstate.h @@ -0,0 +1,57 @@ +#ifndef __QTRACKSTATE_H__ +#define __QTRACKSTATE_H__ + +#include "wpsstate.h" +#include <QObject> + +class QWpsState; + +class QTrackState : public QObject { + Q_OBJECT + Q_CLASSINFO ( "QTrackState", "Mp3 State" ); + Q_PROPERTY ( QString Title READ title WRITE setTitle DESIGNABLE true USER true ) + Q_PROPERTY ( QString Artist READ artist WRITE setArtist DESIGNABLE true USER true ) + Q_PROPERTY ( QString Album READ album WRITE setAlbum DESIGNABLE true USER true ) + Q_PROPERTY ( int Length READ length WRITE setLength DESIGNABLE true USER true ) + Q_CLASSINFO("Length", "readOnly=true;value=100"); + Q_PROPERTY ( int Elapsed READ elapsed WRITE setElapsed DESIGNABLE true USER true ) + Q_CLASSINFO("Elapsed", "minimum=0;maximum=100;value=50"); + + + trackstate state; + +public: + QTrackState(); + +public slots: + QString title() const { + return state.title; + } + void setTitle ( const QString& name ); + + QString artist() const { + return state.artist; + } + void setArtist ( const QString& name ); + + QString album() const { + return state.album; + } + void setAlbum ( const QString& name ); + + int length() const { + return state.length; + } + void setLength ( int l ); + + int elapsed() const { + return state.elapsed; + } + void setElapsed ( int l ); + +signals: + void stateChanged ( trackstate state ); + +}; + +#endif // __QTRACKSTATE_H__ diff --git a/utils/wpseditor/gui/src/qwpsdrawer.cpp b/utils/wpseditor/gui/src/qwpsdrawer.cpp new file mode 100644 index 0000000..ab8a4b3 --- /dev/null +++ b/utils/wpseditor/gui/src/qwpsdrawer.cpp @@ -0,0 +1,200 @@ +#include "qwpsdrawer.h" +#include "slider.h" +#include "utils.h" +#include <QtGui> +#include <QLibrary> +#include <stdarg.h> +// + + +QPointer<QWpsDrawer> drawer; +QPixmap *QWpsDrawer::pix = NULL; +QString QWpsDrawer::mTmpWpsString; +QImage QWpsDrawer::backdrop; +proxy_api QWpsDrawer::api; + +QWpsDrawer::QWpsDrawer( QWpsState *ws,QTrackState *ms, QWidget *parent ) + : QWidget(parent),wpsState(ws),trackState(ms),showGrid(false),mTargetLibName("libwps") { + + tryResolve(); + memset(&api,0,sizeof(struct proxy_api)); + + api.verbose = 2; + api.putsxy = &QWpsDrawer::putsxy; + api.transparent_bitmap_part = &QWpsDrawer::transparent_bitmap_part; + api.bitmap_part = &QWpsDrawer::bitmap_part; + api.drawpixel = &QWpsDrawer::drawpixel; + api.fillrect = &QWpsDrawer::fillrect; + api.hline = &QWpsDrawer::hline; + api.vline = &QWpsDrawer::vline; + api.clear_viewport = &QWpsDrawer::clear_viewport; + api.load_wps_backdrop = &QWpsDrawer::load_wps_backdrop; + api.read_bmp_file = &QWpsDrawer::read_bmp_file; + api.debugf = &qlogger; + newTempWps(); +} + +bool QWpsDrawer::tryResolve() { + QLibrary lib(qApp->applicationDirPath()+"/"+mTargetLibName); + wps_init = (pfwps_init)lib.resolve("wps_init"); + wps_display = (pfwps_display)lib.resolve("wps_display"); + wps_refresh = (pfwps_refresh)lib.resolve("wps_refresh"); + mResolved = wps_init && wps_display && wps_refresh; + if (!mResolved) + DEBUGF1(tr("ERR: Failed to resolve funcs!")); + return mResolved; +} +QWpsDrawer::~QWpsDrawer() { + qDebug()<<"QWpsDrawer::~QWpsDrawer()"; + cleanTemp(); +} + +void QWpsDrawer::mouseReleaseEvent ( QMouseEvent * event ) { + Q_UNUSED(event); + /*int x = event->x() - (this->width()-pix->width())/2, + y = event->y() - (this->height()-pix->height())/2; + DEBUGF1("x=%d,y=%d",x,y);*/ +} +void QWpsDrawer::newTempWps() { + QTemporaryFile tmpWps; + tmpWps.setAutoRemove(false); + tmpWps.setFileTemplate(QDir::tempPath()+"/XXXXXXXXXX.wps"); + if (tmpWps.open()) { + QString tmpDir = tmpWps.fileName().left(tmpWps.fileName().length()-4); + if (QDir::temp().mkpath(tmpDir)) { + mTmpWpsString = tmpDir; + DEBUGF1(mTmpWpsString); + } + } +} + +void QWpsDrawer::WpsInit(QString buffer, bool isFile) { + + if (!mResolved) + if (!tryResolve()) + return; + if (isFile) { + cleanTemp(); + DEBUGF1( tr("Loading %1").arg(buffer)); + QFile file(buffer); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) + mWpsString = file.readAll(); + newTempWps(); + } else + mWpsString = buffer; + { + QFile tfile(mTmpWpsString+".wps"); + if (tfile.open(QIODevice::WriteOnly | QIODevice::Text)) + tfile.write(mWpsString.toAscii(),mWpsString.length()); + } + + if (isFile) + wps_init(buffer.toAscii(), &api, isFile); + else + wps_init(QString(mTmpWpsString+".wps").toAscii(), &api, true); + pix = new QPixmap(api.getwidth(),api.getheight()); + + drawBackdrop(); + + setMinimumWidth(api.getwidth()); + setMinimumHeight(api.getheight()); + + update(); +} + +void QWpsDrawer::paintEvent(QPaintEvent * event) { + if (!mResolved) + return; + if (pix==NULL) + return; + QPainter p(this); + QRect rect = event->rect(); + + drawBackdrop(); + wps_refresh(); + + if (showGrid) { + QPainter g(pix); + viewport_api avp; + api.get_current_vp(&avp); + + g.setPen(Qt::green); + + for (int i=0;i*avp.fontheight/1.5<avp.width ;i++) { + g.drawLine(int(i*avp.fontheight/1.5), 0, int(i*avp.fontheight/1.5), avp.height); + } + for (int j=0;j*avp.fontheight<avp.height; j++) { + g.drawLine(0,j*avp.fontheight,avp.width,j*avp.fontheight); + } + } + + p.drawPixmap((rect.width()-pix->width())/2,(rect.height()-pix->height())/2,*pix); + +} + +void QWpsDrawer::clear_viewport(int x,int y,int w,int h, int color) { + DEBUGF2("clear_viewport(int x=%d,int y=%d,int w=%d,int h=%d, int color)",x,y,w,h); + QPainter p(pix); + //p.setOpacity(0.1); + //QImage img = backdrop.copy(x,y,w,h); + //p.drawImage(x,y,img); +} + +void QWpsDrawer::slotSetVolume() { + Slider *slider = new Slider(this, tr("Volume"),-74,10); + slider->show(); + connect(slider, SIGNAL(valueChanged(int)), wpsState, SLOT(setVolume(int))); + connect(this, SIGNAL(destroyed()),slider, SLOT(close())); +} + +void QWpsDrawer::slotSetProgress() { + Slider *slider = new Slider(this,tr("Progress"),0,100); + slider->show(); + connect(slider, SIGNAL(valueChanged(int)), trackState, SLOT(setElapsed(int))); + connect(this, SIGNAL(destroyed()),slider, SLOT(close())); +} + +void QWpsDrawer::slotWpsStateChanged(wpsstate ws_) { + if (api.set_wpsstate) + api.set_wpsstate(ws_); + update(); +} + +void QWpsDrawer::slotTrackStateChanged(trackstate ms_) { + if (api.set_wpsstate) + api.set_trackstate(ms_); + update(); +} + +void QWpsDrawer::slotShowGrid(bool show) { + showGrid = show; + update(); +} + +void QWpsDrawer::drawBackdrop() { + QPainter b(pix); + QImage pink = backdrop.createMaskFromColor(qRgb(255,0,255),Qt::MaskOutColor); + backdrop.setAlphaChannel(pink); + b.drawImage(0,0,backdrop); +} + +void QWpsDrawer::slotSetAudioStatus(int status) { + api.set_audio_status(status); + update(); +} + +void QWpsDrawer::cleanTemp(bool fileToo) { + if (fileToo) + QFile::remove(mTmpWpsString+".wps"); + QDirIterator it(mTmpWpsString, QDirIterator::Subdirectories); + while (it.hasNext()) { + QFile::remove(it.next()); + } + QDir(mTmpWpsString).rmdir(mTmpWpsString); +} + +void QWpsDrawer::closeEvent(QCloseEvent *event) { + qDebug()<<"QWpsDrawer::closeEvent()"; + cleanTemp(); + event->accept(); +} diff --git a/utils/wpseditor/gui/src/qwpsdrawer.h b/utils/wpseditor/gui/src/qwpsdrawer.h new file mode 100644 index 0000000..d4dfa6c --- /dev/null +++ b/utils/wpseditor/gui/src/qwpsdrawer.h @@ -0,0 +1,82 @@ +#ifndef WPSDRAWER_H +#define WPSDRAWER_H +// +#include <QWidget> +#include <QPixmap> +#include <QPointer> +#include <QTemporaryFile> +#include "api.h" +#include "qtrackstate.h" +#include "qwpsstate.h" +// + +typedef int (*pfwps_init)(const char* buff,struct proxy_api *api, bool isfile); +typedef int (*pfwps_display)(); +typedef int (*pfwps_refresh)(); + +class QWpsDrawer : public QWidget { + Q_OBJECT + + pfwps_init wps_init; + pfwps_display wps_display; + pfwps_refresh wps_refresh; + + static QPixmap *pix; + static QImage backdrop; + + QWpsState *wpsState; + QTrackState *trackState; + + bool showGrid; + bool mResolved; + QString mWpsString; + QString mTargetLibName; + static QString mTmpWpsString; + + +protected: + virtual void paintEvent(QPaintEvent * event); + virtual void closeEvent(QCloseEvent *event); + virtual void mouseReleaseEvent ( QMouseEvent * event ) ; + void drawBackdrop(); + void newTempWps(); + void cleanTemp(bool fileToo=true); + bool tryResolve(); +public: + QWpsDrawer(QWpsState *ws,QTrackState *ms, QWidget *parent=0); + ~QWpsDrawer(); + void WpsInit(QString buffer, bool isFile = true); + + QString wpsString() const { + return mWpsString; + }; + QString tempWps() const { + return mTmpWpsString; + }; + + + static proxy_api api; + /***********Drawing api******************/ + static void putsxy(int x, int y, const unsigned char *str); + static void transparent_bitmap_part(const void *src, int src_x, int src_y, + int stride, int x, int y, int width, int height); + static void bitmap_part(const void *src, int src_x, int src_y, + int stride, int x, int y, int width, int height); + static void drawpixel(int x, int y); + static void fillrect(int x, int y, int width, int height); + static void hline(int x1, int x2, int y); + static void vline(int x, int y1, int y2); + static void clear_viewport(int x,int y,int w,int h, int color); + static bool load_wps_backdrop(char* filename); + static int read_bmp_file(const char* filename,int *width, int *height); + /****************************************/ +public slots: + void slotSetVolume(); + void slotSetProgress(); + + void slotShowGrid(bool); + void slotWpsStateChanged(wpsstate); + void slotTrackStateChanged(trackstate); + void slotSetAudioStatus(int); +}; +#endif diff --git a/utils/wpseditor/gui/src/qwpsdrawer_static.cpp b/utils/wpseditor/gui/src/qwpsdrawer_static.cpp new file mode 100644 index 0000000..bf94d28 --- /dev/null +++ b/utils/wpseditor/gui/src/qwpsdrawer_static.cpp @@ -0,0 +1,77 @@ +#include "qwpsdrawer.h" +#include <QPainter> +#include <QFile> +#include <QFileInfo> +#include "utils.h" + +void QWpsDrawer::putsxy(int x, int y, const unsigned char *str) { + QPainter p(pix); + viewport_api avp; + api.get_current_vp(&avp); + p.setPen(Qt::gray); + + + QFont font("times",avp.fontheight,QFont::Bold); + p.setFont(font); + p.drawText(x+avp.x,y + avp.fontheight + avp.y,(char*)str); +} +void QWpsDrawer::transparent_bitmap_part(const void *src, int src_x, int src_y, + int stride, int x, int y, int width, int height) { + QImage img; + img.load((char*)src); + DEBUGF2("transparent_bitmap_part(const void *src=%s, int src_x=%d, int src_y=%d,int stride=%d, int x=%d, int y=%d, int width=%d, int height=%d",(char*)src,src_x, src_y,stride, x, y, width, height); + QPainter p(pix); + QPoint target(x,y); + QRectF source(src_x, src_y, width, height); + + QImage pink = img.createMaskFromColor(qRgb(255,0,255),Qt::MaskOutColor); + img.setAlphaChannel(pink); + + p.drawImage(target, img, source); +} +void QWpsDrawer::bitmap_part(const void *src, int src_x, int src_y, + int stride, int x, int y, int width, int height) { + transparent_bitmap_part(src,src_x,src_y,stride,x,y,width,height); +} +void QWpsDrawer::drawpixel(int x, int y) { + QPainter p(pix); + p.setPen(Qt::blue); + p.drawPoint(x,y); +} +void QWpsDrawer::fillrect(int x, int y, int width, int height) { + QPainter p(pix); + DEBUGF2("fillrect(int x=%d, int y=%d, int width=%d, int height=%d)\n",x, y, width, height); + p.setPen(Qt::green); +} +void QWpsDrawer::hline(int x1, int x2, int y) { + QPainter p(pix); + p.setPen(Qt::black); + p.drawLine(x1,y,x2,y); +} +void QWpsDrawer::vline(int x, int y1, int y2) { + QPainter p(pix); + p.setPen(Qt::black); + p.drawLine(x,y1,x,y2); +} +bool QWpsDrawer::load_wps_backdrop(char* filename) { + DEBUGF2("load backdrop: %s", filename); + QFile file(filename); + QFileInfo info(file); + file.copy(mTmpWpsString+"/"+info.fileName()); + backdrop.load(filename); + return true; +} + +int QWpsDrawer::read_bmp_file(const char* filename,int *width, int *height) { + QImage img; + + QFile file(filename); + QFileInfo info(file); + file.copy(mTmpWpsString+"/"+info.fileName()); + + img.load(filename); + //qDebug()<<"QWpsDrawer::read_bmp_file"<<img.width()<<img.height(); + *width = img.width(); + *height = img.height(); + return 1; +} diff --git a/utils/wpseditor/gui/src/qwpseditorwindow.cpp b/utils/wpseditor/gui/src/qwpseditorwindow.cpp new file mode 100644 index 0000000..c3090bd --- /dev/null +++ b/utils/wpseditor/gui/src/qwpseditorwindow.cpp @@ -0,0 +1,120 @@ +#include "qwpseditorwindow.h" +#include "qwpsdrawer.h" +#include "utils.h" +#include <QFileDialog> +#include <QDebug> +#include <QInputDialog> + +enum api_playmode playmodes[PLAYMODES_NUM] = { + API_STATUS_PLAY, + API_STATUS_STOP, + API_STATUS_PAUSE, + API_STATUS_FASTFORWARD, + API_STATUS_FASTBACKWARD + }; + +const char *playmodeNames[] = { + "Play", + "Stop", + "Pause", + "FastForward", + "FastBackward" + }; + +QWpsEditorWindow::QWpsEditorWindow( QWidget * parent, Qt::WFlags f) + : QMainWindow(parent, f) { + logEdit = 0; + setupUi(this); + drawer = new QWpsDrawer(&wpsState,&trackState, this); + QWpsDrawer::api.verbose = 1; + //drawer->WpsInit("iCatcher.wps"); + setCentralWidget(drawer); + connectActions(); + m_propertyEditor->addObject(&trackState); + m_propertyEditor->addObject(&wpsState); +} + +void QWpsEditorWindow::connectActions() { + qDebug()<<"connect actions"; + connect(actOpenWps, SIGNAL(triggered()), this, SLOT(slotOpenWps())); + connect(actSetVolume, SIGNAL(triggered()), drawer, SLOT(slotSetVolume())); + connect(actSetProgress, SIGNAL(triggered()), drawer, SLOT(slotSetProgress())); + connect(actShowGrid, SIGNAL(triggered(bool)), drawer, SLOT(slotShowGrid(bool))); + + connect(actUpdatePlainWps, SIGNAL(triggered()), SLOT(slotUpdatePlainWps())); + connect(plainWpsEdit->document(), SIGNAL(modificationChanged(bool)), SLOT(slotPlainDocModChanged(bool))); + + connect(&wpsState, SIGNAL(stateChanged(wpsstate)), drawer, SLOT(slotWpsStateChanged(wpsstate))); + connect(&trackState, SIGNAL(stateChanged(trackstate)), drawer, SLOT(slotTrackStateChanged(trackstate))); + connect(&wpsState, SIGNAL(stateChanged(wpsstate)), this, SLOT(slotWpsStateChanged(wpsstate))); + connect(&trackState, SIGNAL(stateChanged(trackstate)), this, SLOT(slotTrackStateChanged(trackstate))); + + connect(actClearLog, SIGNAL(triggered()), logEdit, SLOT(clear())); + connect(actVerboseLevel, SIGNAL(triggered()), SLOT(slotVerboseLevel())); + + actGroupAudios = new QActionGroup(this); + signalMapper = new QSignalMapper(this); + for (int i=0;i<PLAYMODES_NUM;i++) { + QAction *act = new QAction(playmodeNames[i],this); + act->setCheckable(true); + actGroupAudios->addAction(act); + connect(act,SIGNAL(triggered()),signalMapper,SLOT(map())); + signalMapper->setMapping(act, i); + menuPlay->addAction(act); + actAudios[playmodes[i]] = act; + } + connect(signalMapper, SIGNAL(mapped(int)), SIGNAL(signalAudioStatusChanged(int))); + connect(this, SIGNAL(signalAudioStatusChanged(int)), drawer, SLOT(slotSetAudioStatus(int))); + actGroupAudios->setEnabled(false); +} + +void QWpsEditorWindow::slotWpsStateChanged(wpsstate) { + m_propertyEditor->updateObject(&wpsState); + m_propertyEditor->update(); +} + +void QWpsEditorWindow::slotTrackStateChanged(trackstate) { + m_propertyEditor->updateObject(&trackState); + m_propertyEditor->update(); +} + +void QWpsEditorWindow::slotOpenWps() { + QString wpsfile = QFileDialog::getOpenFileName(this, + tr("Open WPS"), "", tr("WPS Files (*.wps);; All Files (*.*)")); + if (wpsfile == "") { + DEBUGF1(tr("File wasn't chosen")); + return; + } + m_propertyEditor->setEnabled(true); + drawer->WpsInit(wpsfile); + plainWpsEdit->clear(); + plainWpsEdit->append(drawer->wpsString()); + trackState.setAlbum(trackState.album()); + actGroupAudios->setEnabled(true); +} + +void QWpsEditorWindow::logMsg(QString s) { + logEdit->append(s); +} + +void QWpsEditorWindow::slotVerboseLevel() { + bool ok; + int i = QInputDialog::getInteger(this, tr("Set Verbose Level"),tr("Level:"), QWpsDrawer::api.verbose, 0, 3, 1, &ok); + if (ok) + QWpsDrawer::api.verbose = i; +} + +void QWpsEditorWindow::slotUpdatePlainWps() { + DEBUGF1(tr("Updating WPS")); + plainWpsEdit->document()->setModified(false); + drawer->WpsInit(plainWpsEdit->toPlainText(),false); + +} + +void QWpsEditorWindow::slotPlainDocModChanged(bool changed) { + if (changed) + dockPlainWps->setWindowTitle(tr("PlainWps*")); + else + dockPlainWps->setWindowTitle(tr("PlainWps")); +} + diff --git a/utils/wpseditor/gui/src/qwpseditorwindow.h b/utils/wpseditor/gui/src/qwpseditorwindow.h new file mode 100644 index 0000000..019eb63 --- /dev/null +++ b/utils/wpseditor/gui/src/qwpseditorwindow.h @@ -0,0 +1,45 @@ +#ifndef MAINWINDOWIMPL_H +#define MAINWINDOWIMPL_H +// +#include <QMainWindow> +#include <QActionGroup> +#include <QSignalMapper> +#include "ui_mainwindow.h" +#include "wpsstate.h" +#include "qwpsdrawer.h" +#include "qwpsstate.h" +#include "qtrackstate.h" +// +class QWpsEditorWindow : public QMainWindow, public Ui::MainWindow { + Q_OBJECT + QWpsState wpsState; + QTrackState trackState; + QPointer<QWpsDrawer> drawer; + + QHash<int, QAction*> actAudios; + QActionGroup *actGroupAudios; + QSignalMapper *signalMapper; + +protected: + void connectActions(); +public: + QWpsEditorWindow( QWidget * parent = 0, Qt::WFlags f = 0 ); + void logMsg(QString s); +private slots: + void slotOpenWps(); + void slotVerboseLevel(); + void slotWpsStateChanged(wpsstate); + void slotTrackStateChanged(trackstate); + + void slotUpdatePlainWps(); + void slotPlainDocModChanged(bool m); + +signals: + void signalAudioStatusChanged(int); + +}; +#endif + + + + diff --git a/utils/wpseditor/gui/src/qwpsstate.cpp b/utils/wpseditor/gui/src/qwpsstate.cpp new file mode 100644 index 0000000..4244bf6 --- /dev/null +++ b/utils/wpseditor/gui/src/qwpsstate.cpp @@ -0,0 +1,29 @@ +#include "qwpsstate.h" + +QWpsState::QWpsState(): QObject() { + state.fontheight = 8; + state.fontwidth = 5; + state.volume = -30; + state.battery_level = 50; + +} + +void QWpsState::setFontHeight(int val) { + state.fontheight = val; + emit stateChanged(state); +} + +void QWpsState::setFontWidth(int val) { + state.fontwidth = val; + emit stateChanged(state); +} + +void QWpsState::setVolume(int val) { + state.volume = val; + emit stateChanged(state); +} + +void QWpsState::setBattery(int val) { + state.battery_level = val; + emit stateChanged(state); +} diff --git a/utils/wpseditor/gui/src/qwpsstate.h b/utils/wpseditor/gui/src/qwpsstate.h new file mode 100644 index 0000000..eb43531 --- /dev/null +++ b/utils/wpseditor/gui/src/qwpsstate.h @@ -0,0 +1,54 @@ +#ifndef __WPSSTATE_H__ +#define __WPSSTATE_H__ + +#include <QObject> +#include "wpsstate.h" + +class QWpsState : public QObject { + Q_OBJECT + + + Q_CLASSINFO("QWpsState", "WPS State"); + Q_PROPERTY(int FontHeight READ fontHeight WRITE setFontHeight DESIGNABLE true USER true) + Q_CLASSINFO("FontHeight", "minimum=6;maximum=20;value=10"); + Q_PROPERTY(int FontWidth READ fontWidth WRITE setFontWidth DESIGNABLE true USER true) + Q_CLASSINFO("FontWidth", "minimum=4;maximum=20;value=8"); + Q_PROPERTY(int Volume READ volume WRITE setVolume DESIGNABLE true USER true) + Q_CLASSINFO("Volume", "minimum=-74;maximum=24;value=-15"); + Q_PROPERTY(int Battery READ battery WRITE setBattery DESIGNABLE true USER true) + Q_CLASSINFO("Battery", "minimum=0;maximum=100;value=50"); + + wpsstate state; + +public: + QWpsState(); + + int fontHeight() const { + return state.fontheight; + } + void setFontHeight(int val); + + int fontWidth() const { + return state.fontwidth; + } + void setFontWidth(int val); + + int battery() const { + return state.battery_level; + } + void setBattery(int val); + + int volume() const { + return state.volume; + } +public slots: + void setVolume(int val); + + + + + +signals: + void stateChanged ( wpsstate state ); +}; +#endif // __WPSSTATE_H__ diff --git a/utils/wpseditor/gui/src/slider.cpp b/utils/wpseditor/gui/src/slider.cpp new file mode 100644 index 0000000..7e3c9a9 --- /dev/null +++ b/utils/wpseditor/gui/src/slider.cpp @@ -0,0 +1,20 @@ +#include "slider.h" +#include <QDebug> +// +Slider::Slider(QWidget *parent, QString caption, int min, int max ):QDialog(parent) { + setupUi ( this ); + connect(horslider, SIGNAL(valueChanged(int)), this, SIGNAL(valueChanged(int))); + connect(this, SIGNAL(valueChanged(int)), this, SLOT(slotValueChanged(int))); + setWindowTitle(caption); + horslider->setMinimum(min); + horslider->setMaximum(max); +} +// +int Slider::value() { + return horslider->value(); +} +void Slider::slotValueChanged(int step) { + setWindowTitle(tr("Value =%1 ").arg(step)); +} + + diff --git a/utils/wpseditor/gui/src/slider.h b/utils/wpseditor/gui/src/slider.h new file mode 100644 index 0000000..2620731 --- /dev/null +++ b/utils/wpseditor/gui/src/slider.h @@ -0,0 +1,21 @@ +#ifndef SLIDERIMPL_H +#define SLIDERIMPL_H +// +#include <QWidget> +#include <QDialog> +#include "ui_slider.h" +// +class Slider : public QDialog , Ui::slider { + Q_OBJECT +public slots: + void slotValueChanged(int step); +signals: + void valueChanged(int); +public: + Slider(QWidget *parent, QString caption, int min, int max ); + int value(); + + + +}; +#endif diff --git a/utils/wpseditor/gui/src/utils.cpp b/utils/wpseditor/gui/src/utils.cpp new file mode 100644 index 0000000..f184425 --- /dev/null +++ b/utils/wpseditor/gui/src/utils.cpp @@ -0,0 +1,28 @@ +#include "utils.h" +#include <QPointer> +#include <QtGlobal> +#include "qwpseditorwindow.h" + +extern QPointer<QWpsEditorWindow> win; + +int qlogger(const char* fmt,...) { + va_list ap; + va_start(ap, fmt); + QString s; + s.vsprintf(fmt,ap); + va_end(ap); + s.replace("\n",""); + //qDebug()<<s; + if (win==0) + qDebug()<<s; + if (s.indexOf("ERR")>=0) + s = "<font color=red>"+s+"</font>"; + if (win!=0) + win->logMsg(s); + va_end(ap); + return s.length(); +} + +int qlogger(const QString& s) { + return qlogger(s.toAscii().data()); +} diff --git a/utils/wpseditor/gui/src/utils.h b/utils/wpseditor/gui/src/utils.h new file mode 100644 index 0000000..ae88d78 --- /dev/null +++ b/utils/wpseditor/gui/src/utils.h @@ -0,0 +1,12 @@ +#ifndef __UTILS_H__ +#define __UTILS_H__ + +#include <QDebug> + +#define DEBUGF1 qlogger +#define DEBUGF2(...) + +extern int qlogger(const char* fmt,...); +extern int qlogger(const QString& s); + +#endif // __UTILS_H__ |