mirror of
https://github.com/QuasarApp/qt-solutions.git
synced 2025-05-19 16:29:33 +00:00
Change-Id: I4520cf54a4c8d6ff6119dc3762d9aeac42b66af5 Reviewed-by: Andy Shaw <andy.shaw@digia.com>
460 lines
14 KiB
HTML
460 lines
14 KiB
HTML
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
<!DOCTYPE html
|
|
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<!-- grapher.qdoc -->
|
|
<head>
|
|
<title>Grapher Plugin</title>
|
|
<link href="classic.css" rel="stylesheet" type="text/css" />
|
|
</head>
|
|
<body>
|
|
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
|
<tr>
|
|
<td align="left" valign="top" width="32"><img src="images/qt-logo.png" align="left" width="57" height="67" border="0" /></td>
|
|
<td width="1"> </td><td class="postheader" valign="center"><a href="index.html"><font color="#004faf">Home</font></a></td>
|
|
</tr></table><h1 class="title">Grapher Plugin<br /><span class="subtitle"></span>
|
|
</h1>
|
|
<object type="application/x-graphable" data="http://qt.nokia.com/doc/3.3/graph.g1n" WIDTH=250 HEIGHT=250></object>
|
|
<p>Implementation:</p>
|
|
<pre><span class="comment"> /****************************************************************************
|
|
**
|
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
|
** Contact: http://www.qt-project.org/legal
|
|
**
|
|
** This file is part of the Qt Solutions component.
|
|
**
|
|
** You may use this file under the terms of the BSD license as follows:
|
|
**
|
|
** "Redistribution and use in source and binary forms, with or without
|
|
** modification, are permitted provided that the following conditions are
|
|
** met:
|
|
** * Redistributions of source code must retain the above copyright
|
|
** notice, this list of conditions and the following disclaimer.
|
|
** * Redistributions in binary form must reproduce the above copyright
|
|
** notice, this list of conditions and the following disclaimer in
|
|
** the documentation and/or other materials provided with the
|
|
** distribution.
|
|
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
|
** the names of its contributors may be used to endorse or promote
|
|
** products derived from this software without specific prior written
|
|
** permission.
|
|
**
|
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
|
**
|
|
****************************************************************************/</span>
|
|
|
|
#include <QtGui>
|
|
#include <qtbrowserplugin.h>
|
|
|
|
#ifdef QAXSERVER
|
|
#include <ActiveQt/QAxBindable>
|
|
#include <ActiveQt/QAxFactory>
|
|
#include <qt_windows.h>
|
|
#endif
|
|
|
|
class Graph : public QWidget, public QtNPBindable
|
|
#ifdef QAXSERVER
|
|
, public QAxBindable
|
|
#endif
|
|
{
|
|
Q_OBJECT
|
|
Q_ENUMS(GraphStyle)
|
|
Q_PROPERTY(GraphStyle graphStyle READ graphStyle WRITE setGraphStyle)
|
|
Q_PROPERTY(QString src READ dataSourceUrl WRITE setDataSourceUrl)
|
|
|
|
Q_CLASSINFO("ClassID", "{2e5b2715-46b2-4831-ba9b-6a3b195d5ec8}")
|
|
Q_CLASSINFO("InterfaceID", "{94581136-3c0c-46cc-97a1-066061356d43}")
|
|
Q_CLASSINFO("EventsID", "{8c191b77-1894-45c7-9d6b-201dede95410}")
|
|
|
|
Q_CLASSINFO("MIME", "application/x-graphable:g1n:Graphable ASCII numeric data")
|
|
public:
|
|
Graph(QWidget *parent = 0);
|
|
~Graph();
|
|
|
|
enum GraphStyle
|
|
{
|
|
Pie,
|
|
Bar
|
|
};
|
|
void setGraphStyle(GraphStyle style);
|
|
GraphStyle graphStyle() const;
|
|
|
|
void setDataSourceUrl(const QString &url);
|
|
QString dataSourceUrl() const;
|
|
|
|
bool readData(QIODevice *source, const QString &format);
|
|
bool writeData(QIODevice *sink);
|
|
|
|
void transferComplete(const QString &url, int id, Reason r);
|
|
|
|
protected:
|
|
void timerEvent(QTimerEvent*);
|
|
void enterEvent(QEvent *);
|
|
void leaveEvent(QEvent *);
|
|
void paintEvent(QPaintEvent*);
|
|
void mousePressEvent(QMouseEvent *me);
|
|
|
|
void paintWait();
|
|
void paintBar(QPaintEvent*);
|
|
void paintPie(QPaintEvent*);
|
|
|
|
private slots:
|
|
void stylePie();
|
|
void styleBar();
|
|
void aboutPlugin();
|
|
void aboutData();
|
|
void aboutQt();
|
|
void aboutQtDevelopmentFrameworks();
|
|
|
|
private:
|
|
|
|
struct Datum {
|
|
double value;
|
|
QString label;
|
|
};
|
|
QList<Datum> data;
|
|
void processData(QTextStream &in);
|
|
|
|
QMenu *menu;
|
|
QStatusBar *statusbar;
|
|
QAction *pie, *bar;
|
|
|
|
int pieRotation;
|
|
int pieTimer;
|
|
GraphStyle m_style;
|
|
|
|
<span class="comment">// Developer information for the About Data dialog:</span>
|
|
QString sourceUrl;
|
|
int lastReqId, lastConfId;
|
|
QString lastConfUrl;
|
|
Reason lastConfReason;
|
|
};
|
|
|
|
Graph::Graph(QWidget *parent)
|
|
: QWidget(parent), pieRotation(0), pieTimer(0)
|
|
{
|
|
menu = new QMenu(this);
|
|
QMenu *styles = menu->addMenu("&Styles");
|
|
|
|
pie = styles->addAction("&Pie",this,SLOT(stylePie()));
|
|
pie->setShortcut(QString("Ctrl+P"));
|
|
pie->setCheckable(true);
|
|
|
|
bar = styles->addAction("&Bar", this, SLOT(styleBar()));
|
|
bar->setShortcut(QString("Ctrl+B"));
|
|
bar->setCheckable(true);
|
|
|
|
QActionGroup *group = new QActionGroup(this);
|
|
group->setExclusive(true);
|
|
|
|
group->addAction(pie);
|
|
group->addAction(bar);
|
|
|
|
QMenu* help = menu->addMenu("&Help");
|
|
help->addAction("About &plugin...", this, SLOT(aboutPlugin()))->setShortcut(QString("Ctrl+A"));
|
|
help->addAction("About &data...", this, SLOT(aboutData()));
|
|
help->addAction("About &Qt...", this, SLOT(aboutQt()));
|
|
help->addAction("About Qt &Development Frameworks...", this, SLOT(aboutQtDevelopmentFrameworks()));
|
|
|
|
QShortcut *shortcut = new QShortcut(QKeySequence("Ctrl+F5"), this);
|
|
connect(shortcut, SIGNAL(activated()), this, SLOT(aboutQt()));
|
|
|
|
statusbar = new QStatusBar(this);
|
|
|
|
setFocusPolicy(Qt::StrongFocus);
|
|
setGraphStyle(Pie);
|
|
|
|
QPalette pal = palette();
|
|
pal.setColor(QPalette::Window,Qt::white);
|
|
setPalette(pal);
|
|
|
|
lastReqId = 0;
|
|
lastConfId = 0;
|
|
lastConfReason = ReasonUnknown;
|
|
}
|
|
|
|
Graph::~Graph()
|
|
{
|
|
}
|
|
|
|
void Graph::setGraphStyle(GraphStyle style)
|
|
{
|
|
if (pieTimer)
|
|
killTimer(pieTimer);
|
|
|
|
m_style = style;
|
|
switch(m_style) {
|
|
case Pie:
|
|
pieTimer = startTimer(50);
|
|
pie->setChecked(true);
|
|
break;
|
|
case Bar:
|
|
bar->setChecked(true);
|
|
break;
|
|
}
|
|
|
|
repaint();
|
|
}
|
|
|
|
Graph::GraphStyle Graph::graphStyle() const
|
|
{
|
|
return m_style;
|
|
}
|
|
|
|
void Graph::setDataSourceUrl(const QString &url)
|
|
{
|
|
sourceUrl = url;
|
|
|
|
#ifdef QAXSERVER
|
|
<span class="comment">// IE does not call our readData() if plugin is fullpage, so do it here</span>
|
|
if (QAxFactory::isServer() && clientSite()) {
|
|
TCHAR cFileName[512];
|
|
if (URLDownloadToCacheFile(0, url.utf16(), cFileName, 512, 0, 0) == S_OK)
|
|
readData(&QFile(QString::fromUtf16(cFileName)), QString());
|
|
}
|
|
#endif
|
|
}
|
|
|
|
QString Graph::dataSourceUrl() const
|
|
{
|
|
return sourceUrl;
|
|
}
|
|
|
|
void Graph::aboutPlugin()
|
|
{
|
|
openUrl("http:<span class="comment">//qt.nokia.com/products/appdev/add-on-products/catalog/4/Utilities/qtbrowserplugin/");</span>
|
|
}
|
|
|
|
void Graph::aboutData()
|
|
{
|
|
QString page = parameters().value("datapage").toString();
|
|
if (!page.isEmpty()) {
|
|
openUrl(page);
|
|
} else {
|
|
QByteArray table;
|
|
table += "<b>Data loaded from " + sourceUrl.toLatin1() + "</b>\n";
|
|
table += "<p>This data has been loaded with streammode = '";
|
|
table += parameters().contains("streammode") ? parameters().value("streammode").toByteArray() : QByteArray("Default");
|
|
table += "'</p>\n";
|
|
table += "<table>\n";
|
|
for (int i = 0; i < data.count(); ++i) {
|
|
Datum datum = data.at(i);
|
|
table += "<tr><td>" + datum.label + "</td><td>" + QString::number(datum.value) + "</td></tr>\n";
|
|
}
|
|
table += "</table>\n";
|
|
|
|
table += "<p><b>OpenURL() API usage information:</b>\n";
|
|
table += "<br>Last OpenURL() request id: " + QString::number(lastReqId);
|
|
table += "<br>Last confirmation id: " + QString::number(lastConfId);
|
|
table += " Reason: " + QString::number((int)lastConfReason);
|
|
table += "<br>URL: " + lastConfUrl;
|
|
table += "</p>\n";
|
|
QMessageBox::information(this, "Data information", QLatin1String(table));
|
|
}
|
|
}
|
|
|
|
void Graph::transferComplete(const QString &url, int id, Reason r)
|
|
{
|
|
lastConfId = id;
|
|
lastConfUrl = url;
|
|
lastConfReason = r;
|
|
}
|
|
|
|
void Graph::aboutQt()
|
|
{
|
|
QMessageBox::aboutQt(this);
|
|
}
|
|
|
|
void Graph::aboutQtDevelopmentFrameworks()
|
|
{
|
|
lastReqId = openUrl("http:<span class="comment">//qt.nokia.com");</span>
|
|
}
|
|
|
|
void Graph::stylePie()
|
|
{
|
|
setGraphStyle(Pie);
|
|
}
|
|
|
|
void Graph::styleBar()
|
|
{
|
|
setGraphStyle(Bar);
|
|
}
|
|
|
|
bool Graph::readData(QIODevice *source, const QString &<span class="comment">/*format*/</span>)
|
|
{
|
|
if (!source->open(QIODevice::ReadOnly|QIODevice::Text))
|
|
return false;
|
|
|
|
data.clear();
|
|
|
|
QTextStream in(source);
|
|
processData(in);
|
|
|
|
update();
|
|
|
|
return true;
|
|
}
|
|
|
|
void Graph::processData(QTextStream &in)
|
|
{
|
|
while (!in.atEnd()) {
|
|
Datum datum;
|
|
QString value;
|
|
in >> value;
|
|
in >> datum.label;
|
|
bool ok;
|
|
datum.value = value.toDouble(&ok);
|
|
if (ok)
|
|
data += datum;
|
|
}
|
|
}
|
|
|
|
bool Graph::writeData(QIODevice *target)
|
|
{
|
|
if (!target->open(QIODevice::WriteOnly|QIODevice::Text))
|
|
return false;
|
|
|
|
QTextStream out(target);
|
|
foreach(Datum datum, data) {
|
|
out << datum.value << "\t" << datum.label << endl;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void Graph::timerEvent(QTimerEvent *e)
|
|
{
|
|
if (e->timerId() == pieTimer) {
|
|
pieRotation = (pieRotation + 1) % 360;
|
|
update();
|
|
}
|
|
QWidget::timerEvent(e);
|
|
}
|
|
|
|
void Graph::enterEvent(QEvent *)
|
|
{
|
|
statusbar->showMessage(QString("Qt Grapher plugin [%1]").arg(mimeType()));
|
|
}
|
|
|
|
void Graph::leaveEvent(QEvent *)
|
|
{
|
|
if (!QApplication::activePopupWidget()) {
|
|
statusbar->clearMessage();
|
|
}
|
|
}
|
|
|
|
void Graph::paintEvent(QPaintEvent* event)
|
|
{
|
|
if (!data.count()) {
|
|
paintWait();
|
|
} else {
|
|
switch (m_style) {
|
|
case Pie:
|
|
paintPie(event);
|
|
break;
|
|
default:
|
|
paintBar(event);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Graph::mousePressEvent(QMouseEvent *me)
|
|
{
|
|
menu->exec(me->globalPos());
|
|
}
|
|
|
|
void Graph::paintWait()
|
|
{
|
|
QPainter p(this);
|
|
p.drawText(rect(), Qt::AlignCenter, "Loading...");
|
|
}
|
|
|
|
void Graph::paintBar(QPaintEvent* event)
|
|
{
|
|
const int count = data.count();
|
|
double max = 0.0;
|
|
for (int i = 0; i < count; ++i) {
|
|
double value = data.at(i).value;
|
|
if (value > max)
|
|
max = value;
|
|
}
|
|
|
|
QPainter painter(this);
|
|
painter.setClipRect(event->rect());
|
|
painter.save();
|
|
painter.setWindow(0, qRound(max), count * 20, qRound(-max));
|
|
painter.setViewport(20, 5, width() - 40, height() - 40);
|
|
|
|
for (int i = 0; i < count; ++i) {
|
|
double value = data.at(i).value;
|
|
QColor c;
|
|
c.setHsv((i * 255)/count, 255, 255);<span class="comment">// rainbow effect</span>
|
|
painter.setBrush(c);
|
|
|
|
painter.drawRect(i * 20, 0, 20, qRound(value));
|
|
}
|
|
painter.restore();
|
|
painter.setClipRect(QRect());
|
|
}
|
|
|
|
void Graph::paintPie(QPaintEvent* event)
|
|
{
|
|
const int count = data.count();
|
|
double total = 0.0;
|
|
|
|
for (int i = 0; i < count; ++i) {
|
|
double value = data.at(i).value;
|
|
total += value;
|
|
}
|
|
|
|
int apos = (pieRotation-90)*16;
|
|
|
|
QPainter painter(this);
|
|
painter.setRenderHint(QPainter::Antialiasing);
|
|
painter.setClipRect(event->rect());
|
|
QRect r(rect());
|
|
r.adjust(10, 10, -10, -10);
|
|
|
|
for (int i = 0; i < count; ++i) {
|
|
double value = data.at(i).value;
|
|
QColor c;
|
|
c.setHsv((i * 255)/count, 255, 255);<span class="comment">// rainbow effect</span>
|
|
painter.setBrush( c );
|
|
|
|
int a = int((value * 360.0) / total * 16.0 + 0.5);
|
|
painter.drawPie(r, -apos, -a);
|
|
apos += a;
|
|
}
|
|
}
|
|
|
|
#include "grapher.moc"
|
|
|
|
QTNPFACTORY_BEGIN("Qt-based Graph Plugin", "A Qt-based NSAPI plug-in that graphs numeric data");
|
|
QTNPCLASS(Graph)
|
|
QTNPFACTORY_END()
|
|
|
|
#ifdef QAXSERVER
|
|
#include <ActiveQt/QAxFactory>
|
|
QAXFACTORY_BEGIN("{89ab08da-df8c-4bd0-8327-72f73741c1a6}", "{082bd921-0832-4ca7-ab5a-ec06ca7f3350}")
|
|
QAXCLASS(Graph)
|
|
QAXFACTORY_END()
|
|
#endif</pre>
|
|
<p /><address><hr /><div align="center">
|
|
<table width="100%" cellspacing="0" border="0"><tr class="address">
|
|
<td width="30%" align="left">Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)</td>
|
|
<td width="40%" align="center"><a href="http://qt.nokia.com/doc/trademarks.html">Trademarks</a></td>
|
|
<td width="30%" align="right"><div align="right">Qt Solutions</div></td>
|
|
</tr></table></div></address></body>
|
|
</html>
|