summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorFrank Gevaerts <frank@gevaerts.be>2008-08-29 21:08:38 +0000
committerFrank Gevaerts <frank@gevaerts.be>2008-08-29 21:08:38 +0000
commit5d22e3cbdd251819a4d2d07b9a12994d5aef778d (patch)
tree4c6a81187ccf065a5f296a903b9f7da88503e403 /utils
parentcc31b1fbdae455f975b69dd6bffc23d8bd021566 (diff)
downloadrockbox-5d22e3cbdd251819a4d2d07b9a12994d5aef778d.tar.gz
rockbox-5d22e3cbdd251819a4d2d07b9a12994d5aef778d.zip
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')
-rw-r--r--utils/wpseditor/README21
-rw-r--r--utils/wpseditor/TODO7
-rw-r--r--utils/wpseditor/gui/gui.pro40
-rw-r--r--utils/wpseditor/gui/src/QPropertyEditor/ColorCombo.cpp73
-rw-r--r--utils/wpseditor/gui/src/QPropertyEditor/ColorCombo.h49
-rw-r--r--utils/wpseditor/gui/src/QPropertyEditor/Property.cpp136
-rw-r--r--utils/wpseditor/gui/src/QPropertyEditor/Property.h157
-rw-r--r--utils/wpseditor/gui/src/QPropertyEditor/QPropertyEditor.pro26
-rw-r--r--utils/wpseditor/gui/src/QPropertyEditor/QPropertyEditorWidget.cpp56
-rw-r--r--utils/wpseditor/gui/src/QPropertyEditor/QPropertyEditorWidget.h113
-rw-r--r--utils/wpseditor/gui/src/QPropertyEditor/QPropertyModel.cpp236
-rw-r--r--utils/wpseditor/gui/src/QPropertyEditor/QPropertyModel.h105
-rw-r--r--utils/wpseditor/gui/src/QPropertyEditor/QVariantDelegate.cpp105
-rw-r--r--utils/wpseditor/gui/src/QPropertyEditor/QVariantDelegate.h78
-rw-r--r--utils/wpseditor/gui/src/main.cpp16
-rw-r--r--utils/wpseditor/gui/src/qtrackstate.cpp41
-rw-r--r--utils/wpseditor/gui/src/qtrackstate.h57
-rw-r--r--utils/wpseditor/gui/src/qwpsdrawer.cpp200
-rw-r--r--utils/wpseditor/gui/src/qwpsdrawer.h82
-rw-r--r--utils/wpseditor/gui/src/qwpsdrawer_static.cpp77
-rw-r--r--utils/wpseditor/gui/src/qwpseditorwindow.cpp120
-rw-r--r--utils/wpseditor/gui/src/qwpseditorwindow.h45
-rw-r--r--utils/wpseditor/gui/src/qwpsstate.cpp29
-rw-r--r--utils/wpseditor/gui/src/qwpsstate.h54
-rw-r--r--utils/wpseditor/gui/src/slider.cpp20
-rw-r--r--utils/wpseditor/gui/src/slider.h21
-rw-r--r--utils/wpseditor/gui/src/utils.cpp28
-rw-r--r--utils/wpseditor/gui/src/utils.h12
-rw-r--r--utils/wpseditor/gui/ui/mainwindow.ui290
-rw-r--r--utils/wpseditor/gui/ui/slider.ui43
-rw-r--r--utils/wpseditor/libwps/Makefile100
-rw-r--r--utils/wpseditor/libwps/buildall.sh7
-rw-r--r--utils/wpseditor/libwps/cleanall.sh7
-rw-r--r--utils/wpseditor/libwps/src/api.c268
-rw-r--r--utils/wpseditor/libwps/src/api.h85
-rw-r--r--utils/wpseditor/libwps/src/defs.h41
-rw-r--r--utils/wpseditor/libwps/src/dummies.c363
-rw-r--r--utils/wpseditor/libwps/src/dummies.h44
-rw-r--r--utils/wpseditor/libwps/src/include/lang.h10
-rw-r--r--utils/wpseditor/libwps/src/include/rockboxlogo.h1
-rw-r--r--utils/wpseditor/libwps/src/include/sysfont.h1
-rw-r--r--utils/wpseditor/libwps/src/include/system-target.h1
-rw-r--r--utils/wpseditor/libwps/src/lcd.c150
-rw-r--r--utils/wpseditor/libwps/src/proxy.c132
-rw-r--r--utils/wpseditor/libwps/src/proxy.h25
-rw-r--r--utils/wpseditor/libwps/src/wpsstate.h34
-rw-r--r--utils/wpseditor/libwps/targets.txt33
-rw-r--r--utils/wpseditor/wpseditor.pro2
48 files changed, 3641 insertions, 0 deletions
diff --git a/utils/wpseditor/README b/utils/wpseditor/README
new file mode 100644
index 0000000000..3a8b87c511
--- /dev/null
+++ b/utils/wpseditor/README
@@ -0,0 +1,21 @@
+ __________ __ ___.
+ Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ \/ \/ \/ \/ \/
+
+Installation
+
+Windows:
+
+ * be sure that you have properly installed mingw, QT > 4.3.*
+ * if you want to debug wpseditor, you'll have to build Qt debug libraries
+ * cd to rockbox/utils/wpseditor/ from Qt command promt and run qmake and then make
+ * >gui\bin\wpseditor.exe
+
+Linux:
+
+ * Make sure you have libqt4-dev installed and you have a working Rockbox environment
+ * cd to utils/wpseditor/ and do 'qmake-qt4 && make'
+ * cd to gui/bin/ and start WPS editor with './wpseditord'
diff --git a/utils/wpseditor/TODO b/utils/wpseditor/TODO
new file mode 100644
index 0000000000..28f559111f
--- /dev/null
+++ b/utils/wpseditor/TODO
@@ -0,0 +1,7 @@
+* Enable ability in gui to load different targets on the fly
+* Enable animation(timers,sliding lines, etc)
+* Test on Mac OS
+* Redesign GUI for more usability
+* Replace checkwps functionality
+* Include 'screenshot utility' functionality
+* Make editing via gui
diff --git a/utils/wpseditor/gui/gui.pro b/utils/wpseditor/gui/gui.pro
new file mode 100644
index 0000000000..db7cfa1343
--- /dev/null
+++ b/utils/wpseditor/gui/gui.pro
@@ -0,0 +1,40 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += . build src ui
+INCLUDEPATH += . src/QPropertyEditor ../libwps/src
+DESTDIR = bin
+OBJECTS_DIR = build
+MOC_DIR = build
+UI_DIR = build
+QMAKE_LIBDIR += lib
+QT = gui core
+CONFIG += qt warn_on console debug_and_release
+libwps.commands += $(MAKE) -C ../libwps shared
+QMAKE_EXTRA_TARGETS += libwps
+PRE_TARGETDEPS += libwps
+HEADERS += ../libwps/src/api.h \
+ ../libwps/src/defs.h \
+ src/slider.h \
+ src/qtrackstate.h \
+ src/qwpsstate.h \
+ src/qwpseditorwindow.h \
+ src/utils.h \
+ src/qwpsdrawer.h
+FORMS += ui/mainwindow.ui ui/slider.ui
+SOURCES += src/main.cpp \
+ src/slider.cpp \
+ src/qtrackstate.cpp \
+ src/qwpsstate.cpp \
+ src/qwpseditorwindow.cpp \
+ src/utils.cpp \
+ src/qwpsdrawer.cpp \
+ src/qwpsdrawer_static.cpp
+LIBS += -Lbin
+CONFIG(debug, debug|release) {
+ LIBS += -lQPropertyEditord
+ TARGET = wpseditord
+}
+CONFIG(release, debug|release) {
+ LIBS += -lQPropertyEditor
+ TARGET = wpseditor
+}
diff --git a/utils/wpseditor/gui/src/QPropertyEditor/ColorCombo.cpp b/utils/wpseditor/gui/src/QPropertyEditor/ColorCombo.cpp
new file mode 100644
index 0000000000..f5eeb030dc
--- /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 0000000000..530b05bbc5
--- /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 0000000000..0746d15140
--- /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 0000000000..52d6842987
--- /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 0000000000..85fd29ee2c
--- /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 0000000000..fc4b90c227
--- /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 0000000000..2dab87722a
--- /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 0000000000..b147cd089d
--- /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 0000000000..8a52bbe87c
--- /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 0000000000..ebda9b2c31
--- /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 0000000000..e06265af82
--- /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 0000000000..0ba22c9fce
--- /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 0000000000..dad2f9a4aa
--- /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 0000000000..b57f7a8376
--- /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 0000000000..ab8a4b32d6
--- /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 0000000000..d4dfa6c7a2
--- /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 0000000000..bf94d28a5a
--- /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 0000000000..c3090bd027
--- /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 0000000000..019eb63808
--- /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 0000000000..4244bf6293
--- /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 0000000000..eb43531de6
--- /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 0000000000..7e3c9a942c
--- /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 0000000000..2620731644
--- /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 0000000000..f18442555b
--- /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 0000000000..ae88d78249
--- /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__
diff --git a/utils/wpseditor/gui/ui/mainwindow.ui b/utils/wpseditor/gui/ui/mainwindow.ui
new file mode 100644
index 0000000000..cd3f52bd66
--- /dev/null
+++ b/utils/wpseditor/gui/ui/mainwindow.ui
@@ -0,0 +1,290 @@
+<ui version="4.0" >
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>882</width>
+ <height>669</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>WPS Editor</string>
+ </property>
+ <widget class="QWidget" name="centralwidget" >
+ <property name="geometry" >
+ <rect>
+ <x>260</x>
+ <y>21</y>
+ <width>344</width>
+ <height>345</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QMenuBar" name="menubar" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>882</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menuFile" >
+ <property name="title" >
+ <string>File</string>
+ </property>
+ <addaction name="actOpenWps" />
+ <addaction name="actSetVolume" />
+ <addaction name="actSetProgress" />
+ <addaction name="actShowGrid" />
+ <addaction name="actClearLog" />
+ <addaction name="actVerboseLevel" />
+ <addaction name="actQuit" />
+ </widget>
+ <widget class="QMenu" name="menuPlay" >
+ <property name="title" >
+ <string>Play</string>
+ </property>
+ </widget>
+ <addaction name="menuFile" />
+ <addaction name="menuPlay" />
+ </widget>
+ <widget class="QStatusBar" name="statusbar" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>650</y>
+ <width>882</width>
+ <height>19</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QDockWidget" name="dockPlainWps" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>370</y>
+ <width>882</width>
+ <height>280</height>
+ </rect>
+ </property>
+ <property name="minimumSize" >
+ <size>
+ <width>0</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="windowTitle" >
+ <string>PlainWps</string>
+ </property>
+ <attribute name="dockWidgetArea" >
+ <number>8</number>
+ </attribute>
+ <widget class="QWidget" name="dockWidgetContents_3" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>22</y>
+ <width>882</width>
+ <height>258</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2" >
+ <item rowspan="2" row="0" column="0" >
+ <widget class="QTextEdit" name="plainWpsEdit" >
+ <property name="autoFillBackground" >
+ <bool>false</bool>
+ </property>
+ <property name="readOnly" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QPushButton" name="btnUpdatePlainWps" >
+ <property name="text" >
+ <string>Update WPS</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <spacer name="verticalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>20</width>
+ <height>211</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <widget class="QDockWidget" name="m_dockWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>21</y>
+ <width>256</width>
+ <height>345</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Property Editor</string>
+ </property>
+ <attribute name="dockWidgetArea" >
+ <number>1</number>
+ </attribute>
+ <widget class="QPropertyEditorWidget" name="m_propertyEditor" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>22</y>
+ <width>256</width>
+ <height>323</height>
+ </rect>
+ </property>
+ </widget>
+ </widget>
+ <widget class="QDockWidget" name="dockWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>608</x>
+ <y>21</y>
+ <width>274</width>
+ <height>345</height>
+ </rect>
+ </property>
+ <property name="minimumSize" >
+ <size>
+ <width>0</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="windowTitle" >
+ <string>Log</string>
+ </property>
+ <attribute name="dockWidgetArea" >
+ <number>2</number>
+ </attribute>
+ <widget class="QWidget" name="dockWidgetContents" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>22</y>
+ <width>274</width>
+ <height>323</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout" >
+ <item row="0" column="0" >
+ <widget class="QTextEdit" name="logEdit" >
+ <property name="autoFillBackground" >
+ <bool>false</bool>
+ </property>
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <action name="actQuit" >
+ <property name="text" >
+ <string>Quit</string>
+ </property>
+ </action>
+ <action name="actOpenWps" >
+ <property name="text" >
+ <string>Open WPS</string>
+ </property>
+ </action>
+ <action name="actSetVolume" >
+ <property name="text" >
+ <string>Set Volume</string>
+ </property>
+ </action>
+ <action name="actSetProgress" >
+ <property name="text" >
+ <string>Set Progress</string>
+ </property>
+ </action>
+ <action name="actShowGrid" >
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="checked" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Show Grid</string>
+ </property>
+ </action>
+ <action name="actClearLog" >
+ <property name="text" >
+ <string>Clear Log</string>
+ </property>
+ </action>
+ <action name="actVerboseLevel" >
+ <property name="text" >
+ <string>Verbose Level</string>
+ </property>
+ </action>
+ <action name="actUpdatePlainWps" >
+ <property name="text" >
+ <string>Update WPS</string>
+ </property>
+ </action>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QPropertyEditorWidget</class>
+ <extends>QTreeView</extends>
+ <header>QPropertyEditorWidget.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>btnUpdatePlainWps</sender>
+ <signal>clicked()</signal>
+ <receiver>actUpdatePlainWps</receiver>
+ <slot>trigger()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>835</x>
+ <y>411</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>-1</x>
+ <y>-1</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>actQuit</sender>
+ <signal>triggered()</signal>
+ <receiver>MainWindow</receiver>
+ <slot>close()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>-1</x>
+ <y>-1</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>440</x>
+ <y>334</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/utils/wpseditor/gui/ui/slider.ui b/utils/wpseditor/gui/ui/slider.ui
new file mode 100644
index 0000000000..24fff0bf23
--- /dev/null
+++ b/utils/wpseditor/gui/ui/slider.ui
@@ -0,0 +1,43 @@
+<ui version="4.0" >
+ <class>slider</class>
+ <widget class="QWidget" name="slider" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>295</width>
+ <height>37</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Value</string>
+ </property>
+ <widget class="QSlider" name="horslider" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>10</y>
+ <width>291</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="minimum" >
+ <number>-78</number>
+ </property>
+ <property name="maximum" >
+ <number>24</number>
+ </property>
+ <property name="singleStep" >
+ <number>1</number>
+ </property>
+ <property name="value" >
+ <number>-78</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/utils/wpseditor/libwps/Makefile b/utils/wpseditor/libwps/Makefile
new file mode 100644
index 0000000000..3779a9ed30
--- /dev/null
+++ b/utils/wpseditor/libwps/Makefile
@@ -0,0 +1,100 @@
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+# $Id$
+#
+ROOT=../../..
+
+OS = w32
+CC = gcc
+MKDIR = mkdir -p
+
+ifeq ($(findstring MINGW,$(shell uname)),MINGW)
+OS = w32
+CC = mingw32-gcc
+COPY = copy
+RM = rm
+endif
+
+ifeq ($(findstring Linux,$(shell uname)),Linux)
+OS = linux
+CC = gcc
+COPY = cp
+RM = rm -f
+endif
+
+
+
+COMMON= \
+ src/dummies.c \
+ src/api.c \
+ src/lcd.c \
+ $(ROOT)/apps/gui/wps_parser.c \
+ $(ROOT)/apps/gui/wps_debug.c \
+ $(ROOT)/firmware/font.c \
+ $(ROOT)/apps/misc.c \
+ $(ROOT)/apps/gui/gwps-common.c \
+ $(ROOT)/apps/status.c \
+ $(ROOT)/apps/recorder/peakmeter.c \
+ $(ROOT)/apps/recorder/icons.c \
+ $(ROOT)/apps/gui/scrollbar.c \
+ $(ROOT)/firmware/common/timefuncs.c \
+ $(ROOT)/firmware/common/unicode.c \
+ $(ROOT)/firmware/common/ctype.c \
+ $(ROOT)/firmware/id3.c \
+ $(ROOT)/firmware/font_cache.c \
+ $(ROOT)/firmware/lru.c \
+ $(ROOT)/firmware/mp3data.c \
+ $(ROOT)/firmware/replaygain.c
+
+# $(ROOT)/apps/recorder/bmp.c
+# $(ROOT)/apps/abrepeat.c \
+# $(ROOT)/apps/action.c \
+# $(ROOT)/apps/cuesheet.c \
+# $(ROOT)/apps/gui/statusbar.c \
+# $(ROOT)/apps/gui/gwps.c \
+
+INCLUDE=-I src/include \
+ -I $(ROOT)/apps/gui \
+ -I $(ROOT)/firmware/export \
+ -I $(ROOT)/firmware/include \
+ -I $(ROOT)/apps/recorder \
+ -I $(ROOT)/apps \
+ -I src
+
+CFLAGS = -g -Wall -D__PCTOOL__ -DWPSEDITOR -DDEBUG -DROCKBOX_DIR_LEN=1 -DBUTTON_REMOTE
+
+all:
+ @echo To build, run the buildall.sh script
+
+build: build-$(OS)
+
+build-w32: src/proxy.c $(COMMON)
+ @echo CC [$(TARGET)]
+ @$(CC) $(INCLUDE) $(CFLAGS) -D$(TARGET) -DTARGET_MODEL=\"$(MODEL)\" -DBUILD_DLL $(COMMON) -shared src/proxy.c -o libwps_$(MODEL).dll
+
+build-linux: src/proxy.c $(COMMON)
+ @echo CC [$(TARGET)]
+ @$(CC) $(INCLUDE) $(CFLAGS) -D$(TARGET) -DTARGET_MODEL=\"$(MODEL)\" -shared -Wl,-soname,libwps_$(MODEL).so,-olibwps_$(MODEL).so -fPIC $(COMMON) src/proxy.c
+
+clean: clean-$(OS)
+
+clean-w32:
+ $(RM) "libwps_$(MODEL).dll"
+
+clean-linux:
+ $(RM) "libwps_$(MODEL).so.1"
+
+shared: shared-$(OS)
+
+shared-w32: src/proxy.c $(COMMON)
+ @echo CC [IRIVER_H10_5GB]
+ @$(CC) $(INCLUDE) $(CFLAGS) -DIRIVER_H10_5GB -DTARGET_MODEL=\"h10_5gb\" -DBUILD_DLL $(COMMON) -shared src/proxy.c -o ../gui/bin/libwps.dll
+
+shared-linux: src/proxy.c $(COMMON)
+ @echo CC [IRIVER_H10_5GB]
+ @$(CC) $(INCLUDE) $(CFLAGS) -DIRIVER_H10_5GB -DTARGET_MODEL=\"h10_5gb\" -shared -Wl,-soname,libwps.so,-olibwps.so -fPIC $(COMMON) src/proxy.c
+ @$(COPY) libwps.so ../gui/bin/libwps.so
diff --git a/utils/wpseditor/libwps/buildall.sh b/utils/wpseditor/libwps/buildall.sh
new file mode 100644
index 0000000000..60677d22b6
--- /dev/null
+++ b/utils/wpseditor/libwps/buildall.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+cat targets.txt | (
+ while read target model
+ do
+ make MODEL=$model TARGET=$target build
+ done
+)
diff --git a/utils/wpseditor/libwps/cleanall.sh b/utils/wpseditor/libwps/cleanall.sh
new file mode 100644
index 0000000000..15b733a6a7
--- /dev/null
+++ b/utils/wpseditor/libwps/cleanall.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+cat targets.txt | (
+ while read target model
+ do
+ make MODEL=$model TARGET=$target clean
+ done
+)
diff --git a/utils/wpseditor/libwps/src/api.c b/utils/wpseditor/libwps/src/api.c
new file mode 100644
index 0000000000..485efa8e00
--- /dev/null
+++ b/utils/wpseditor/libwps/src/api.c
@@ -0,0 +1,268 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "sound.h"
+#include "api.h"
+#include "proxy.h"
+#include "dummies.h"
+#include "scroll_engine.h"
+#include "wpsstate.h"
+#include <string.h>
+
+struct proxy_api *xapi;
+
+void get_current_vp(struct viewport_api *avp);
+/*************************************************************
+
+*************************************************************/
+#ifdef HAVE_LCD_BITMAP
+void screen_clear_area(struct screen * display, int xstart, int ystart,
+ int width, int height) {
+ display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
+ display->fillrect(xstart, ystart, width, height);
+ display->set_drawmode(DRMODE_SOLID);
+}
+#endif
+
+bool load_wps_backdrop(char* filename) {
+ return xapi->load_wps_backdrop(filename);
+}
+
+bool load_remote_wps_backdrop(char* filename) {
+ return xapi->load_remote_wps_backdrop(filename);
+}
+
+int read_bmp_file(const char* filename,struct bitmap *bm, int maxsize,int format) {
+ if (!xapi->read_bmp_file)
+ {
+ DEBUGF1("can't read bmp file! NULL api!\n");
+ return -1;
+ }
+ bm->format = 3;//FORMAT_ANY?
+ bm->data = (unsigned char*)malloc(255);
+ memset(bm->data,0,255);
+ strcpy((char*)bm->data,filename);
+ //bm->data[strlen(filename)] = '\0';
+ xapi->read_bmp_file(filename,&bm->width, &bm->height);
+ return 1;
+}
+
+bool load_wps_backdrop2(char* filename) {
+ DEBUGF1("load_wps_backdrop(char* filename='%s')",filename);
+ return true;
+}
+
+bool load_remote_wps_backdrop2(char* filename) {
+ DEBUGF1("load_remote_wps_backdrop2(char* filename='%s')",filename);
+ return true;
+}
+
+void stop_scroll() {
+ DEBUGF3("stop_scroll\n");
+ return;
+}
+
+void puts_scroll(int x, int y, const unsigned char *string) {
+ DEBUGF2("puts_scroll(int x=%d, int y=%d, const unsigned char *string='%s'\n",x,y,string);
+}
+
+void putsxy(int x, int y, const unsigned char *str) {
+ DEBUGF2("putsxy(int =%d, int y=%d, const unsigned char *str='%s')\n",x,y,str);
+}
+
+void lcd_update() {
+ DEBUGF3("update\n");
+}
+
+void clear_viewport(int x, int y, int w, int h, int color) {
+ DEBUGF3("clear_viewport(int x=%d, int y=%d, int w=%d, int h=%d, int color=%d)\n", x, y, w, h, color);
+};
+
+int getstringsize(const unsigned char *str, int *w, int *h) {
+ //DEBUGF1("getstringsize(const unsigned char *str=\"%s\", int *w=%d, int *h=%d \n",str,*w,*h);
+ *w=strlen((char*)str)*sysfont.maxwidth;
+ *h=sysfont.height;
+ return 1;
+}
+
+void set_wpsstate(struct wpsstate state){
+ sysfont.height = state.fontheight;
+ sysfont.maxwidth = state.fontwidth;
+ global_settings.volume = state.volume;
+ battery_percent = state.battery_level;
+ _audio_status = state.audio_status;
+}
+
+void set_trackstate(struct trackstate state){
+ gui_wps[0].state->id3->title = state.title;
+ gui_wps[0].state->id3->artist = state.artist;
+ gui_wps[0].state->id3->album = state.album;
+ gui_wps[0].state->id3->elapsed = state.elapsed;
+ gui_wps[0].state->id3->length = state.length;
+}
+
+void set_next_trackstate(struct trackstate state)
+{
+ gui_wps[0].state->nid3->title = state.title;
+ gui_wps[0].state->nid3->artist = state.artist;
+ gui_wps[0].state->nid3->album = state.album;
+ gui_wps[0].state->nid3->elapsed = state.elapsed;
+ gui_wps[0].state->nid3->length = state.length;
+}
+
+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"
+};
+
+
+void set_audio_status(int status){
+ DEBUGF1("%s",playmodeNames[status]);
+ switch(status){
+ case API_STATUS_PLAY:
+ _audio_status = AUDIO_STATUS_PLAY;
+ status_set_ffmode(STATUS_PLAY);
+ break;
+ case API_STATUS_STOP:
+ _audio_status = 0;
+ status_set_ffmode(STATUS_STOP);
+ break;
+ case API_STATUS_PAUSE:
+ _audio_status = AUDIO_STATUS_PAUSE;
+ status_set_ffmode(STATUS_PLAY);
+ break;
+ case API_STATUS_FASTFORWARD:
+ status_set_ffmode(STATUS_FASTFORWARD);
+ break;
+ case API_STATUS_FASTBACKWARD:
+ status_set_ffmode(STATUS_FASTBACKWARD);
+ break;
+ default:
+ DEBUGF1("ERR: Unknown status");
+ }
+}
+
+void test_api(struct proxy_api *api) {
+ if (!api->stop_scroll)
+ api->stop_scroll=stop_scroll;
+ if (!api->set_viewport)
+ api->set_viewport=lcd_set_viewport;
+ if (!api->clear_viewport)
+ api->clear_viewport=clear_viewport;
+ if (!api->getstringsize)
+ api->getstringsize=getstringsize;
+ if (!api->getwidth)
+ api->getwidth=lcd_getwidth;
+ if (!api->getheight)
+ api->getheight=lcd_getheight;
+ if (!api->set_drawmode)
+ api->set_drawmode=lcd_set_drawmode;
+ if (!api->puts_scroll)
+ api->puts_scroll=puts_scroll;
+ if (!api->update)
+ api->update=lcd_update;
+ if (!api->clear_display)
+ api->clear_display=lcd_clear_display;
+ if (!api->getfont)
+ api->getfont=lcd_getfont;
+ if (!api->putsxy)
+ api->putsxy=putsxy;
+
+#if LCD_DEPTH > 1
+ if (!api->get_foreground)
+ api->get_foreground=lcd_get_foreground;
+ if (!api->get_background)
+ api->get_background=lcd_get_background;
+#endif
+ if (!api->load_remote_wps_backdrop)
+ api->load_remote_wps_backdrop = load_remote_wps_backdrop2;
+ if (!api->load_wps_backdrop)
+ api->load_wps_backdrop = load_wps_backdrop2;
+ //dbgf = printf;
+}
+
+/**************************************************************
+
+**************************************************************/
+
+int set_api(struct proxy_api* api) {
+ if (api->debugf)
+ dbgf = api->debugf;
+ screens[0].screen_type=SCREEN_MAIN;
+ screens[0].lcdwidth=LCD_WIDTH;
+ screens[0].lcdheight=LCD_HEIGHT;
+ screens[0].depth=LCD_DEPTH;
+#ifdef HAVE_LCD_COLOR
+ screens[0].is_color=true;
+#else
+ screens[0].is_color=false;
+#endif
+ if (api->getwidth)
+ screens[0].getwidth = api->getwidth;
+ if (api->stop_scroll)
+ screens[0].stop_scroll=api->stop_scroll;
+ screens[0].scroll_stop = lcd_scroll_stop;
+ if (api->set_viewport)
+ screens[0].set_viewport=api->set_viewport;
+ if (api->clear_viewport)
+ screens[0].clear_viewport=lcd_clear_viewport;
+ if (api->getstringsize)
+ screens[0].getstringsize=api->getstringsize;
+ if (api->getwidth)
+ screens[0].getwidth=api->getwidth;
+ if (api->getheight)
+ screens[0].getheight=api->getheight;
+ if (api->set_drawmode)
+ screens[0].set_drawmode=api->set_drawmode;
+ if (api->fillrect)
+ screens[0].fillrect=api->fillrect;
+ if (api->puts_scroll)
+ screens[0].puts_scroll=api->puts_scroll;
+ if (api->transparent_bitmap_part)
+ screens[0].transparent_bitmap_part=api->transparent_bitmap_part;
+ if (api->update)
+ screens[0].update=api->update;
+ if (api->clear_display)
+ screens[0].clear_display=api->clear_display;
+ if (api->getfont)
+ screens[0].getfont=api->getfont;
+ if (api->hline)
+ screens[0].hline=api->hline;
+ if (api->vline)
+ screens[0].vline=api->vline;
+ if (api->drawpixel)
+ screens[0].drawpixel=api->drawpixel;
+ if (api->putsxy)
+ screens[0].putsxy=api->putsxy;
+#if LCD_DEPTH > 1
+ if (api->get_foreground)
+ screens[0].get_foreground=api->get_foreground;
+ if (api->get_background)
+ screens[0].get_background=api->get_background;
+#endif
+
+ screens[0].bitmap_part = api->bitmap_part;
+ /**************************
+ * OUT *
+ **************************/
+ api->get_model_name = get_model_name;
+ api->get_current_vp = get_current_vp;
+ api->set_wpsstate = set_wpsstate;
+ api->set_trackstate = set_trackstate;
+ api->set_next_trackstate= set_next_trackstate;
+ api->set_audio_status= set_audio_status;
+ xapi = api;
+ return 0;
+}
+
+
+
+
+
+
diff --git a/utils/wpseditor/libwps/src/api.h b/utils/wpseditor/libwps/src/api.h
new file mode 100644
index 0000000000..86bb1a6597
--- /dev/null
+++ b/utils/wpseditor/libwps/src/api.h
@@ -0,0 +1,85 @@
+#ifndef API_H_INCLUDED
+#define API_H_INCLUDED
+#include <stdbool.h>
+#include <stddef.h>
+#include "defs.h"
+#include "wpsstate.h"
+#ifdef __PCTOOL__
+#include "dummies.h"
+#endif
+
+struct viewport_api {
+ int x;
+ int y;
+ int width;
+ int height;
+ int font;
+ int drawmode;
+ unsigned fg_pattern;
+ unsigned bg_pattern;
+ unsigned lss_pattern;
+ unsigned lse_pattern;
+ unsigned lst_pattern;
+
+ //TODO: ??
+ int fontheight;
+ int fontwidth;
+};
+
+struct proxy_api
+{
+ bool (*load_remote_wps_backdrop)(char* file_name);
+ bool (*load_wps_backdrop)(char* file_name);
+
+ unsigned (*get_foreground)(void);
+ unsigned (*get_background)(void);
+ int (*getwidth)(void);
+ int (*getheight)(void);
+
+ void (*puts_scroll)(int x, int y, const unsigned char *string);
+ void (*putsxy)(int x, int y, const unsigned char *str);
+ int (*getfont)();
+ int (*getstringsize)(const unsigned char *str, int *w, int *h);
+ void (*stop_scroll)();
+
+ void (*transparent_bitmap_part)(const void *src, int src_x, int src_y,
+ int stride, int x, int y, int width, int height);
+ void (*bitmap_part)(const void *src, int src_x, int src_y,
+ int stride, int x, int y, int width, int height);
+ void (*hline)(int x1, int x2, int y);
+ void (*vline)(int x, int y1, int y2);
+ void (*drawpixel)(int x, int y);
+ void (*set_drawmode)(int mode);
+ void (*fillrect)(int x, int y, int width, int height);
+
+
+ void (*update)();
+ void (*set_viewport)(struct viewport* vp);
+ void (*clear_display)(void);
+ void (*clear_viewport)(int x,int y,int w,int h, int color);
+
+ void* (*plugin_get_buffer)(size_t *buffer_size);
+ int (*read_bmp_file)(const char* filename,int *width, int *height);
+ void (*set_wpsstate)(struct wpsstate state);
+ void (*set_trackstate)(struct trackstate state);
+ void (*set_next_trackstate)(struct trackstate state);
+ void (*set_audio_status)(int status);
+
+ pfdebugf debugf;
+ int verbose;
+
+
+/**************************
+* OUT *
+**************************/
+ const char* (*get_model_name)();
+ void (*get_current_vp)(struct viewport_api *avp);
+
+
+};
+
+extern struct proxy_api *xapi;
+
+EXPORT int set_api(struct proxy_api* api);
+
+#endif // API_H_INCLUDED
diff --git a/utils/wpseditor/libwps/src/defs.h b/utils/wpseditor/libwps/src/defs.h
new file mode 100644
index 0000000000..810c8da238
--- /dev/null
+++ b/utils/wpseditor/libwps/src/defs.h
@@ -0,0 +1,41 @@
+#ifndef DEFS_H_INCLUDED
+#define DEFS_H_INCLUDED
+
+typedef int (*pfdebugf)(const char* fmt,...);
+extern pfdebugf dbgf;
+
+#ifdef BUILD_DLL
+# define EXPORT __declspec(dllexport)
+#else
+# define EXPORT
+#endif
+
+#ifndef MIN
+# define MIN(a, b) (((a)<(b))?(a):(b))
+#endif
+
+#ifndef MAX
+# define MAX(a, b) (((a)>(b))?(a):(b))
+#endif
+
+#define SWAP_16(x) ((typeof(x))(unsigned short)(((unsigned short)(x) >> 8) | \
+ ((unsigned short)(x) << 8)))
+
+#define SWAP_32(x) ((typeof(x))(unsigned long)( ((unsigned long)(x) >> 24) | \
+ (((unsigned long)(x) & 0xff0000ul) >> 8) | \
+ (((unsigned long)(x) & 0xff00ul) << 8) | \
+ ((unsigned long)(x) << 24)))
+
+#define PLAYMODES_NUM 5
+enum api_playmode {
+ API_STATUS_PLAY,
+ API_STATUS_STOP,
+ API_STATUS_PAUSE,
+ API_STATUS_FASTFORWARD,
+ API_STATUS_FASTBACKWARD
+};
+
+extern enum api_playmode playmodes[PLAYMODES_NUM];
+extern const char *playmodeNames[];
+
+#endif // DEFS_H_INCLUDED
diff --git a/utils/wpseditor/libwps/src/dummies.c b/utils/wpseditor/libwps/src/dummies.c
new file mode 100644
index 0000000000..8592610701
--- /dev/null
+++ b/utils/wpseditor/libwps/src/dummies.c
@@ -0,0 +1,363 @@
+#include <string.h>
+#include <stdio.h>
+#include "dummies.h"
+#include "proxy.h"
+
+struct user_settings global_settings;
+
+struct wps_state wps_state;
+struct gui_wps gui_wps[NB_SCREENS];
+struct wps_data wps_datas[NB_SCREENS];
+struct cuesheet *curr_cue;
+struct cuesheet *temp_cue;
+struct system_status global_status;
+struct gui_syncstatusbar statusbars;
+struct playlist_info current_playlist;
+struct font sysfont;
+int battery_percent = 100;
+struct mp3entry current_song, next_song;
+int _audio_status;
+
+charger_input_state_type charger_input_state;
+#if CONFIG_CHARGING >= CHARGING_MONITOR
+charge_state_type charge_state;
+#endif
+
+#if defined(CPU_PP) && defined(BOOTLOADER)
+/* We don't enable interrupts in the iPod bootloader, so we need to fake
+the current_tick variable */
+#define current_tick (signed)(USEC_TIMER/10000)
+#else
+volatile long current_tick;
+#endif
+
+
+void dummies_init(){
+ sysfont.height = 9;
+ sysfont.maxwidth = 6;
+ global_settings.statusbar=true;
+}
+
+int playlist_amount_ex(const struct playlist_info* playlist);
+void sound_set_volume(int value)
+{
+ DEBUGF3("sound_set_volume(int value=%d)",value);
+ global_settings.volume = value;
+}
+int sound_get_pitch(void)
+{
+ return 0;
+}
+int sound_min(int setting)
+{
+ DEBUGF3("sound_min(int setting=%d)",setting);
+ return -78; //audiohw_settings[setting].minval;
+}
+
+void sleep(int hz)
+{
+}
+
+void audio_init(void){}
+void audio_wait_for_init(void){}
+void audio_play(long offset){}
+void audio_stop(void){}
+void audio_pause(void){}
+void audio_resume(void){}
+void audio_next(void){}
+void audio_prev(void){}
+int audio_status(void)
+{
+ return _audio_status;
+}
+
+#if CONFIG_CODEC == SWCODEC
+int audio_track_count(void){return 0;} /* SWCODEC only */
+long audio_filebufused(void){return 0;} /* SWCODEC only */
+void audio_pre_ff_rewind(void){} /* SWCODEC only */
+#endif /* CONFIG_CODEC == SWCODEC */
+void audio_ff_rewind(long newtime){}
+void audio_flush_and_reload_tracks(void){}
+#ifdef HAVE_ALBUMART
+int audio_current_aa_hid(void){return -1;}
+#endif
+struct mp3entry* audio_current_track(void){return 0;}
+struct mp3entry* audio_next_track(void){return 0;}
+bool audio_has_changed_track(void)
+{
+ return false;
+}
+
+int get_sleep_timer(void){return 0;}
+
+
+int battery_level(void){return battery_percent;} /* percent */
+int battery_time(void){return 0;} /* minutes */
+unsigned int battery_adc_voltage(void){return 0;} /* voltage from ADC in millivolts */
+unsigned int battery_voltage(void){return 0;} /* filtered batt. voltage in millivolts */
+int get_radio_status(void){return 0;}
+
+
+/* returns full path of playlist (minus extension) */
+char *playlist_name(const struct playlist_info* playlist, char *buf,
+int buf_size)
+{
+ char *sep;
+
+ if (!playlist)
+ return "no";
+
+ snprintf(buf, buf_size, "%s", playlist->filename+playlist->dirlen);
+
+ if (!buf[0])
+ return NULL;
+
+ /* Remove extension */
+ sep = strrchr(buf, '.');
+ if(sep)
+ *sep = 0;
+
+ return buf;
+}
+int playlist_get_display_index(void)
+{
+ return 1;
+}
+
+void gui_syncsplash(int ticks, const unsigned char *fmt, ...)
+{
+
+}
+
+void splash(int ticks, const unsigned char *fmt, ...)
+{
+
+}
+
+void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw){
+ DEBUGF3("gui_statusbar_draw");
+}
+
+void yield(void){}
+
+
+/* returns true if cuesheet support is initialised */
+bool cuesheet_is_enabled(void){return false;}
+
+/* allocates the cuesheet buffer */
+void cuesheet_init(void){}
+
+/* looks if there is a cuesheet file that has a name matching "trackpath" */
+bool look_for_cuesheet_file(const char *trackpath, char *found_cue_path){return false;}
+
+/* parse cuesheet "file" and store the information in "cue" */
+bool parse_cuesheet(char *file, struct cuesheet *cue){return false;}
+
+/* reads a cuesheet to find the audio track associated to it */
+bool get_trackname_from_cuesheet(char *filename, char *buf){return false;}
+
+/* display a cuesheet struct */
+void browse_cuesheet(struct cuesheet *cue){}
+
+/* display a cuesheet file after parsing and loading it to the plugin buffer */
+bool display_cuesheet_content(char* filename){return false;}
+
+/* finds the index of the current track played within a cuesheet */
+int cue_find_current_track(struct cuesheet *cue, unsigned long curpos){return 0;}
+
+/* update the id3 info to that of the currently playing track in the cuesheet */
+void cue_spoof_id3(struct cuesheet *cue, struct mp3entry *id3){}
+
+/* skip to next track in the cuesheet towards "direction" (which is 1 or -1) */
+bool curr_cuesheet_skip(int direction, unsigned long curr_pos){return false;}
+
+#ifdef HAVE_LCD_BITMAP
+/* draw track markers on the progressbar */
+void cue_draw_markers(struct screen *screen, unsigned long tracklen,
+int x1, int x2, int y, int h){}
+#endif
+
+
+void draw_album_art(struct gui_wps *gwps, int handle_id, bool clear)
+{
+ if (!gwps || !gwps->data || !gwps->display || handle_id < 0)
+ return;
+
+ struct wps_data *data = gwps->data;
+
+#ifdef HAVE_REMOTE_LCD
+ /* No album art on RWPS */
+ if (data->remote_wps)
+ return;
+#endif
+
+ struct bitmap *bmp;
+ /* if (bufgetdata(handle_id, 0, (void *)&bmp) <= 0)
+ return;*/
+
+ short x = data->albumart_x;
+ short y = data->albumart_y;
+ short width = bmp->width;
+ short height = bmp->height;
+
+ if (data->albumart_max_width > 0)
+ {
+ /* Crop if the bitmap is too wide */
+ width = MIN(bmp->width, data->albumart_max_width);
+
+ /* Align */
+ if (data->albumart_xalign & WPS_ALBUMART_ALIGN_RIGHT)
+ x += data->albumart_max_width - width;
+ else if (data->albumart_xalign & WPS_ALBUMART_ALIGN_CENTER)
+ x += (data->albumart_max_width - width) / 2;
+ }
+
+ if (data->albumart_max_height > 0)
+ {
+ /* Crop if the bitmap is too high */
+ height = MIN(bmp->height, data->albumart_max_height);
+
+ /* Align */
+ if (data->albumart_yalign & WPS_ALBUMART_ALIGN_BOTTOM)
+ y += data->albumart_max_height - height;
+ else if (data->albumart_yalign & WPS_ALBUMART_ALIGN_CENTER)
+ y += (data->albumart_max_height - height) / 2;
+ }
+
+ if (!clear)
+ {
+ /* Draw the bitmap */
+ gwps->display->set_drawmode(DRMODE_FG);
+ gwps->display->bitmap_part((fb_data*)bmp->data, 0, 0, bmp->width,
+ x, y, width, height);
+ gwps->display->set_drawmode(DRMODE_SOLID);
+ }
+ else
+ {
+ /* Clear the bitmap */
+ gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
+ gwps->display->fillrect(x, y, width, height);
+ gwps->display->set_drawmode(DRMODE_SOLID);
+ }
+}
+
+/* Update the "data" pointer to make the handle's data available to the caller.
+Return the length of the available linear data or < 0 for failure (handle
+not found).
+The caller is blocked until the requested amount of data is available.
+size is the amount of linear data requested. it can be 0 to get as
+much as possible.
+The guard buffer may be used to provide the requested size. This means it's
+unsafe to request more than the size of the guard buffer.
+*/
+size_t bufgetdata(int handle_id, size_t size, void **data)
+{
+
+
+ return size;
+}
+
+
+void gui_syncstatusbar_draw(struct gui_syncstatusbar * bars,
+bool force_redraw)
+{
+#ifdef HAVE_LCD_BITMAP
+ if(!global_settings.statusbar)
+ return;
+#endif /* HAVE_LCD_BITMAP */
+ int i;
+ FOR_NB_SCREENS(i) {
+ gui_statusbar_draw( &(bars->statusbars[i]), force_redraw );
+ }
+}
+void unload_wps_backdrop(void)
+{
+
+}
+
+#if CONFIG_CODEC == SWCODEC
+int get_replaygain_mode(bool have_track_gain, bool have_album_gain)
+{
+ int type;
+
+ bool track = ((global_settings.replaygain_type == REPLAYGAIN_TRACK)
+ || ((global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
+ && global_settings.playlist_shuffle));
+
+ type = (!track && have_album_gain) ? REPLAYGAIN_ALBUM
+ : have_track_gain ? REPLAYGAIN_TRACK : -1;
+
+ return type;
+}
+#endif
+
+/* Common functions for all targets */
+void rtc_init(void){}
+int rtc_read_datetime(unsigned char* buf){return 0;}
+int rtc_write_datetime(unsigned char* buf){return 0;}
+
+void backlight_on(void){}
+void backlight_off(void){}
+
+
+void debugf(const char *fmt, ...)
+{}
+void panicf( const char *fmt, ...)
+{
+}
+
+off_t filesize(int fd){return 0;}
+
+int playlist_amount(void)
+{
+ return playlist_amount_ex(NULL);
+}
+int playlist_amount_ex(const struct playlist_info* playlist)
+{
+ if (!playlist)
+ playlist = &current_playlist;
+
+ return playlist->amount;
+}
+
+int get_action(int context, int timeout)
+{
+ return 0;
+}
+
+void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width,
+ int height){}
+
+void pcm_calculate_rec_peaks(int *left, int *right)
+{
+}
+void pcm_calculate_peaks(int *left, int *right)
+{
+}
+bool led_read(int delayticks) /* read by status bar update */
+{
+ return false;
+}
+
+#ifndef HAS_BUTTON_HOLD
+bool is_keys_locked(void)
+{
+ return false;
+}
+#endif
+
+long default_event_handler_ex(long event, void (*callback)(void *), void *parameter)
+{
+ return 0;
+}
+
+long default_event_handler(long event)
+{
+ return default_event_handler_ex(event, NULL, NULL);
+}
+
+void ab_draw_markers(struct screen * screen, int capacity,
+ int x0, int x1, int y, int h)
+ {
+ }
+void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude){}
diff --git a/utils/wpseditor/libwps/src/dummies.h b/utils/wpseditor/libwps/src/dummies.h
new file mode 100644
index 0000000000..2bfce1d53b
--- /dev/null
+++ b/utils/wpseditor/libwps/src/dummies.h
@@ -0,0 +1,44 @@
+#ifndef DUMMIES_H_INCLUDED
+#define DUMMIES_H_INCLUDED
+
+#include <stdio.h>
+
+#include "settings.h"
+#include "gwps.h"
+#include "lang.h"
+#include "powermgmt.h"
+#include "font.h"
+#include "playlist.h"
+
+#include "defs.h"
+
+extern struct font sysfont;
+extern struct user_settings global_settings;
+extern struct wps_state wps_state;
+extern struct gui_wps gui_wps[NB_SCREENS];
+extern struct wps_data wps_datas[NB_SCREENS];
+extern struct cuesheet *curr_cue;
+extern struct cuesheet *temp_cue;
+extern struct system_status global_status;
+extern struct gui_syncstatusbar statusbars;
+extern struct playlist_info current_playlist;
+extern int battery_percent;
+extern struct mp3entry current_song, next_song;
+extern int _audio_status;
+
+charger_input_state_type charger_input_state;
+#if CONFIG_CHARGING >= CHARGING_MONITOR
+extern charge_state_type charge_state;
+#endif
+
+#if defined(CPU_PP) && defined(BOOTLOADER)
+/* We don't enable interrupts in the iPod bootloader, so we need to fake
+the current_tick variable */
+#define current_tick (signed)(USEC_TIMER/10000)
+#else
+extern volatile long current_tick;
+#endif
+
+void dummies_init();
+
+#endif /*DUMMIES_H_INCLUDED*/
diff --git a/utils/wpseditor/libwps/src/include/lang.h b/utils/wpseditor/libwps/src/include/lang.h
new file mode 100644
index 0000000000..3274bdec6c
--- /dev/null
+++ b/utils/wpseditor/libwps/src/include/lang.h
@@ -0,0 +1,10 @@
+#define LANG_END_PLAYLIST (signed char)1
+#define LANG_KEYLOCK_ON (signed char)2
+#define LANG_KEYLOCK_OFF (signed char)3
+#define LANG_WEEKDAY_SUNDAY (signed char)4
+#define LANG_MONTH_JANUARY (signed char)5
+#define VOICE_PAUSE (signed char)6
+#define LANG_BATTERY_TIME (signed char)7
+#define UNIT_PERCENT (signed char)8
+
+#define str(...) "empty"
diff --git a/utils/wpseditor/libwps/src/include/rockboxlogo.h b/utils/wpseditor/libwps/src/include/rockboxlogo.h
new file mode 100644
index 0000000000..8d1c8b69c3
--- /dev/null
+++ b/utils/wpseditor/libwps/src/include/rockboxlogo.h
@@ -0,0 +1 @@
+
diff --git a/utils/wpseditor/libwps/src/include/sysfont.h b/utils/wpseditor/libwps/src/include/sysfont.h
new file mode 100644
index 0000000000..4ba770347c
--- /dev/null
+++ b/utils/wpseditor/libwps/src/include/sysfont.h
@@ -0,0 +1 @@
+#define SYSFONT_HEIGHT 9
diff --git a/utils/wpseditor/libwps/src/include/system-target.h b/utils/wpseditor/libwps/src/include/system-target.h
new file mode 100644
index 0000000000..8d1c8b69c3
--- /dev/null
+++ b/utils/wpseditor/libwps/src/include/system-target.h
@@ -0,0 +1 @@
+
diff --git a/utils/wpseditor/libwps/src/lcd.c b/utils/wpseditor/libwps/src/lcd.c
new file mode 100644
index 0000000000..1f12332750
--- /dev/null
+++ b/utils/wpseditor/libwps/src/lcd.c
@@ -0,0 +1,150 @@
+#include "font.h"
+#include "screen_access.h"
+//#include <windef.h>
+#include "api.h"
+#include "defs.h"
+#include "proxy.h"
+#include "dummies.h"
+
+static struct viewport default_vp =
+{
+ .x = 0,
+ .y = 0,
+ .width = LCD_WIDTH,
+ .height = LCD_HEIGHT,
+ .font = FONT_SYSFIXED,
+ .drawmode = DRMODE_SOLID,
+ .fg_pattern = LCD_DEFAULT_FG,
+ .bg_pattern = LCD_DEFAULT_BG,
+ .lss_pattern = LCD_DEFAULT_BG,
+ .lse_pattern = LCD_DEFAULT_BG,
+ .lst_pattern = LCD_DEFAULT_BG,
+};
+
+struct viewport* current_vp = &default_vp;
+
+void get_current_vp(struct viewport_api *avp){
+ avp->x = current_vp->x;
+ avp->y = current_vp->y;
+ avp->width = current_vp->width;
+ avp->height = current_vp->height;
+
+ //TODO: font_get(current_vp->font)->height;
+ avp->fontheight = sysfont.height;
+}
+
+void lcd_set_viewport(struct viewport* vp)
+{
+ if (vp == NULL){
+ current_vp = &default_vp;
+ DEBUGF3("lcd_set_viewport(struct viewport* vp= DEFAULT)\n");
+ }
+ else{
+ current_vp = vp;
+ DEBUGF3("lcd_set_viewport(struct viewport* vp=%x,vpx=%d,vpy=%d,vpw=%d,vph=%d)\n",vp,vp->x,vp->y,vp->width,vp->height);
+ }
+}
+
+void lcd_update_viewport(void)
+{
+ //lcd_update_rect(current_vp->x, current_vp->y,current_vp->width, current_vp->height);
+}
+
+void lcd_update_viewport_rect(int x, int y, int width, int height)
+{
+ //lcd_update_rect(current_vp->x + x, current_vp->y + y, width, height);
+}
+/*** parameter handling ***/
+
+void lcd_set_drawmode(int mode)
+{
+ current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
+}
+
+int lcd_get_drawmode(void)
+{
+ return current_vp->drawmode;
+}
+
+void lcd_set_foreground(unsigned color)
+{
+ current_vp->fg_pattern = color;
+}
+
+unsigned lcd_get_foreground(void)
+{
+ return current_vp->fg_pattern;
+}
+
+void lcd_set_background(unsigned color)
+{
+ current_vp->bg_pattern = color;
+}
+
+unsigned lcd_get_background(void)
+{
+ return current_vp->bg_pattern;
+}
+
+void lcd_set_selector_start(unsigned color)
+{
+ current_vp->lss_pattern = color;
+}
+
+void lcd_set_selector_end(unsigned color)
+{
+ current_vp->lse_pattern = color;
+}
+
+void lcd_set_selector_text(unsigned color)
+{
+ current_vp->lst_pattern = color;
+}
+
+void lcd_set_drawinfo(int mode, unsigned fg_color, unsigned bg_color)
+{
+ //lcd_set_drawmode(mode);
+ current_vp->fg_pattern = fg_color;
+ current_vp->bg_pattern = bg_color;
+}
+
+int lcd_getwidth(void)
+{
+ return current_vp->width;
+}
+
+int lcd_getheight(void)
+{
+ return current_vp->height;
+}
+
+void lcd_setfont(int newfont)
+{
+ current_vp->font = newfont;
+}
+
+int lcd_getfont(void)
+{
+ return current_vp->font;
+}
+
+/* Clear the whole display */
+void lcd_clear_display(void)
+{
+ struct viewport* old_vp = current_vp;
+
+ current_vp = &default_vp;
+
+ lcd_clear_viewport();
+
+ current_vp = old_vp;
+}
+
+void lcd_clear_viewport(){
+ DEBUGF2("lcd_clear_viewport()\n");
+ xapi->clear_viewport(current_vp->x,current_vp->y,current_vp->width,current_vp->height,current_vp->bg_pattern);
+
+}
+void lcd_scroll_stop(struct viewport* vp){
+ DEBUGF3("lcd_scroll_stop(struct viewport* vp=%x)\n",vp);
+}
diff --git a/utils/wpseditor/libwps/src/proxy.c b/utils/wpseditor/libwps/src/proxy.c
new file mode 100644
index 0000000000..3a3b8ce4d9
--- /dev/null
+++ b/utils/wpseditor/libwps/src/proxy.c
@@ -0,0 +1,132 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "dummies.h"
+#include "proxy.h"
+#include "api.h"
+#include "gwps.h"
+#include "gwps-common.h"
+#include <string.h>
+
+struct screen screens[NB_SCREENS];
+struct wps_data wpsdata;
+struct gui_wps gwps;
+struct mp3entry id3;
+struct mp3entry nid3;
+
+extern void test_api(struct proxy_api *api);
+
+bool debug_wps = true;
+int wps_verbose_level = 0;
+int errno_;
+pfdebugf dbgf = 0;
+
+static char pluginbuf[PLUGIN_BUFFER_SIZE];
+
+const char* get_model_name(){
+#ifdef TARGET_MODEL
+ return TARGET_MODEL;
+#else
+ return "unknown";
+#endif
+}
+
+int read_line(int fd, char* buffer, int buffer_size)
+{
+ int count = 0;
+ int num_read = 0;
+
+ errno_ = 0;
+
+ while (count < buffer_size)
+ {
+ unsigned char c;
+
+ if (1 != read(fd, &c, 1))
+ break;
+
+ num_read++;
+
+ if ( c == '\n' )
+ break;
+
+ if ( c == '\r' )
+ continue;
+
+ buffer[count++] = c;
+ }
+
+ buffer[MIN(count, buffer_size - 1)] = 0;
+
+ return errno_ ? -1 : num_read;
+}
+
+void* plugin_get_buffer(size_t *buffer_size)
+{
+ *buffer_size = PLUGIN_BUFFER_SIZE;
+ return pluginbuf;
+}
+
+int checkwps(const char *filename, int verbose){
+ int res;
+ int fd;
+
+ struct wps_data wps;
+ wps_verbose_level = verbose;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ DEBUGF1("Failed to open %s\n",filename);
+ return 2;
+ }
+ close(fd);
+
+ res = wps_data_load(&wps, &screens[0], filename, true);
+
+ if (!res) {
+ DEBUGF1("WPS parsing failure\n");
+ return 3;
+ }
+
+ DEBUGF1("WPS parsed OK\n");
+ return 0;
+}
+
+int wps_init(const char* filename,struct proxy_api *api, bool isfile){
+ int res;
+ if (!api)
+ return 4;
+ dummies_init();
+ test_api(api);
+ set_api(api);
+ wps_data_init(&wpsdata);
+ wps_verbose_level = api->verbose;
+ res = wps_data_load(&wpsdata, &screens[0], filename, isfile);
+ if (!res)
+ {
+ DEBUGF1("ERR: WPS parsing failure\n");
+ return 3;
+ }
+ DEBUGF1("WPS parsed OK\n");
+ DEBUGF1("\n-------------------------------------------------\n");
+ wps_state.paused = true;
+ gwps.data = &wpsdata;
+ gwps.display = &screens[0];
+ gwps.state = &wps_state;
+ gwps.state->id3 = &id3;
+ gwps.state->nid3 = &nid3;
+ gui_wps[0] = gwps;
+ return res;
+}
+
+int wps_display(){
+ DEBUGF3("wps_display(): begin\n");
+ int res = gui_wps_display();
+ DEBUGF3("\nWPS %sdisplayed\n", (res ? "" : "not "));
+ return res;
+}
+int wps_refresh(){
+ DEBUGF3("-----------------<wps_refresh(): begin>-----------------\n");
+ int res = gui_wps_refresh(&gwps, 0, WPS_REFRESH_ALL);
+ DEBUGF3("\nWPS %srefreshed\n", (res ? "" : "not "));
+ return res;
+}
diff --git a/utils/wpseditor/libwps/src/proxy.h b/utils/wpseditor/libwps/src/proxy.h
new file mode 100644
index 0000000000..3836ecc6d0
--- /dev/null
+++ b/utils/wpseditor/libwps/src/proxy.h
@@ -0,0 +1,25 @@
+#ifndef PROXY_H
+#define PROXY_h
+
+#include "screen_access.h"
+#include "api.h"
+#include "defs.h"
+
+#define DEBUGF dbgf
+#define DEBUGF1 dbgf
+#define DEBUGF2(...)
+#define DEBUGF3(...)
+
+EXPORT int checkwps(const char *filename, int verbose);
+EXPORT int wps_init(const char* filename,struct proxy_api *api,bool isfile);
+EXPORT int wps_display();
+EXPORT int wps_refresh();
+
+const char* get_model_name();
+
+extern struct screen screens[NB_SCREENS];
+extern bool debug_wps;
+extern int wps_verbose_level;
+
+
+#endif
diff --git a/utils/wpseditor/libwps/src/wpsstate.h b/utils/wpseditor/libwps/src/wpsstate.h
new file mode 100644
index 0000000000..148936a481
--- /dev/null
+++ b/utils/wpseditor/libwps/src/wpsstate.h
@@ -0,0 +1,34 @@
+#ifndef STATES_H
+#define STATES_H
+//
+struct trackstate
+{
+ char* title;
+ char* artist;
+ char* album;
+ char* genre_string;
+ char* disc_string;
+ char* track_string;
+ char* year_string;
+ char* composer;
+ char* comment;
+ char* albumartist;
+ char* grouping;
+ int discnum;
+ int tracknum;
+ int version;
+ int layer;
+ int year;
+
+ int length;
+ int elapsed;
+};
+
+struct wpsstate{
+ int volume;
+ int fontheight;
+ int fontwidth;
+ int battery_level;
+ int audio_status;
+};
+#endif
diff --git a/utils/wpseditor/libwps/targets.txt b/utils/wpseditor/libwps/targets.txt
new file mode 100644
index 0000000000..d2c54378d9
--- /dev/null
+++ b/utils/wpseditor/libwps/targets.txt
@@ -0,0 +1,33 @@
+ARCHOS_RECORDER recorder
+ARCHOS_FMRECORDER fmrecorder
+ARCHOS_RECORDERV2 recorderv2
+ARCHOS_ONDIOSP ondiosp
+ARCHOS_ONDIOFM ondiofm
+IRIVER_H120 h120
+IRIVER_H300 h300
+IRIVER_H100 h100
+IRIVER_IFP7XX ifp7xx
+IRIVER_H10 h10
+IRIVER_H10_5GB h10_5gb
+IPOD_COLOR ipodcolor
+IPOD_NANO ipodnano
+IPOD_VIDEO ipodvideo
+IPOD_3G ipod3g
+IPOD_4G ipod4g
+IPOD_MINI ipodmini
+IPOD_MINI2G ipodmini2g
+IPOD_1G2G ipod1g2g
+IAUDIO_X5 x5
+IAUDIO_M5 m5
+COWON_D2 cowond2
+IAUDIO_M3 m3
+GIGABEAT_F gigabeatf
+GIGABEAT_S gigabeats
+MROBE_500 mrobe500
+MROBE_100 mrobe100
+LOGIK_DAX logikdax
+CREATIVE_ZVM creativezvm
+SANSA_E200 e200
+SANSA_E200 e200r
+SANSA_C200 c200
+ELIO_TPJ1022 tpj1022
diff --git a/utils/wpseditor/wpseditor.pro b/utils/wpseditor/wpseditor.pro
new file mode 100644
index 0000000000..0e9ecbbf51
--- /dev/null
+++ b/utils/wpseditor/wpseditor.pro
@@ -0,0 +1,2 @@
+SUBDIRS =gui/src/QPropertyEditor gui
+TEMPLATE = subdirs