[ref]同步-711

This commit is contained in:
shi_jq 2025-03-13 10:47:10 +08:00
parent 50296a077f
commit 60b7dc10c6
236 changed files with 39103 additions and 0 deletions

View File

@ -0,0 +1,492 @@
#include "CNewElfShape.h"
#include "CShapeAdaptor.h"
#include "../hmi/CGraphScene.h"
#include "CLinkLine.h"
#include "CTextShape.h"
#include "CIconShape.h"
CNewElfShape::CNewElfShape(char type, QGraphicsItem *parent)
: CGroupShape(type, parent)
{
}
CNewElfShape::~CNewElfShape()
{
}
void CNewElfShape::clear()
{
QList<CShape *>::iterator it = m_mergeList.begin();
for (; it != m_mergeList.end(); it++)
{
getScene()->removeItem(*it);
}
m_mergeList.clear();
m_tempInstMap.clear();
m_txtReplaceMap.clear();
m_pIconInfo = NULL;
}
int CNewElfShape::read(CGStream &stream, char flag)
{
Q_UNUSED(flag)
CShape::read(stream);
if (stream.GetMode() == CGStream::xmlfile)
{
CXMLStream &xmls = stream.m_XMLStream;
xmls.GetValue("icon_name", m_pokeFile);
QRectF rect;
xmls.GetValue("rect", rect);
m_initWidth = rect.width();
m_initHeight = rect.height();
float wFactor = 1.;
float hFactor = 1.;
xmls.GetValue("WFactor", wFactor);
xmls.GetValue("HFactor", hFactor);
int replace_nums = 0;
xmls.GetValue("replace_nums", replace_nums);
QString replace;
for(int n=0; n<replace_nums; ++n)
{
xmls.GetValue(QString("replace%1").arg(n), replace);
QStringList tmp = replace.split(":");
if(tmp.size() == 2)
{
m_txtReplaceMap[QString(tmp[0]).toInt()] = tmp[1];
}
}
setIconInfo(m_pokeFile, true);
setWFactor(wFactor);
setHFactor(hFactor);
setPos(rect.topLeft());
setObjOpacity(opacity());
}
else
{
std::string tmp;
stream >> tmp;
m_pokeFile = QString::fromStdString(tmp);
int x = 0;
int y = 0;
stream >> x;
stream >> y;
stream >> m_initWidth;
stream >> m_initHeight;
setPos(x, y);
double wFactor = 1.;
double hFactor = 1.;
stream >> wFactor;
stream >> hFactor;
int replace_nums;
stream >> replace_nums;
std::string replace_txt;
for(int n=0; n<replace_nums; ++n)
{
stream >> replace_txt;
QStringList tmp = QString::fromStdString(replace_txt).split(":");
if(tmp.size() == 2)
{
m_txtReplaceMap[QString(tmp[0]).toInt()] = tmp[1];
}
}
setIconInfo(m_pokeFile, true);
setWFactor(wFactor);
setHFactor(hFactor);
setObjOpacity(opacity());
}
return 1;
}
int CNewElfShape::write(CGStream &stream, char flag)
{
Q_UNUSED(flag)
CShape::write(stream);
int count = 0;
if (stream.GetMode() == CGStream::xmlfile)
{
CXMLStream &xmls = stream.m_XMLStream;
QRect tmprect(pos().x(), pos().y(), m_initWidth, m_initHeight);
tmprect.normalized();
xmls.PutValue("rect", tmprect);
xmls.PutValue("icon_name", m_pokeFile);
xmls.PutValue("WFactor", getWFactor());
xmls.PutValue("HFactor", getHFactor());
xmls.PutValue("replace_nums", m_txtReplaceMap.size());
QMap<long, QString>::iterator iter = m_txtReplaceMap.begin();
for(int n=0; iter != m_txtReplaceMap.end(); iter++,n++)
{
xmls.PutValue(QString("replace%1").arg(n),
QString("%1:%2").arg(QString::number(iter.key())).arg(iter.value()));
}
return 1;
}
stream << m_pokeFile.toStdString();
count += sizeof(int) + m_pokeFile.size();
stream << (int)pos().x();
count += sizeof(int);
stream << (int)pos().y();
count += sizeof(int);
stream << m_initWidth;
count += sizeof(int);
stream << m_initHeight;
count += sizeof(int);
stream << getWFactor();
count += sizeof(double);
stream << getHFactor();
count += sizeof(double);
stream << m_txtReplaceMap.size();
count += sizeof(int);
QString replace_txt;
QMap<long, QString>::iterator iter = m_txtReplaceMap.begin();
for(int n=0; iter != m_txtReplaceMap.end(); iter++,n++)
{
replace_txt = QString("%1:%2").arg(QString::number(iter.key())).arg(iter.value());
stream << replace_txt.toStdString();
count += sizeof(int) + replace_txt.size();
}
return count;
}
qreal CNewElfShape::getWFactor() const
{
if(m_initWidth <= 0)
return 1.0;
return m_width / m_initWidth;
}
qreal CNewElfShape::getHFactor() const
{
if(m_initHeight <= 0)
return 1.0;
return m_height / m_initHeight;
}
void CNewElfShape::setWFactor(float value)
{
if(value <= 0)
return;
prepareGeometryChange();
m_width = m_initWidth * value;
QList<CShape *>::iterator it = m_mergeList.begin();
for (; it != m_mergeList.end(); it++)
{
(*it)->zoomWidth(value);
}
}
void CNewElfShape::setHFactor(float value)
{
if(value <= 0)
return;
prepareGeometryChange();
m_height = m_initHeight * value;
QList<CShape *>::iterator it = m_mergeList.begin();
for (; it != m_mergeList.end(); it++)
{
(*it)->zoomHeight(value);
}
}
bool CNewElfShape::setIconInfo(QString &name, bool addToScene)
{
m_pokeFile = name;
m_pIconInfo = IconInfoControlInstance()->getIconInfoPtr(28, name);
if (m_pIconInfo != NULL)
{
m_initWidth = m_pIconInfo->m_iconWidth;
m_initHeight = m_pIconInfo->m_iconHeight;
m_width = m_initWidth;
m_height = m_initHeight;
}
else
{
m_pIconInfo = IconInfoControlInstance()->getUnknowIconInfoPtr();
m_initWidth = m_pIconInfo->m_iconWidth;
m_initHeight = m_pIconInfo->m_iconHeight;
m_width = m_initWidth;
m_height = m_initHeight;
}
QList<CShape *> *objlist = m_pIconInfo->getObjListPtr();
QList<CShape *>::iterator it = objlist->begin();
CShape *obj;
CShape *cloneObj = NULL;
for (; it != objlist->end(); it++)
{
obj = *it;
cloneObj = obj->clone();
cloneObj->setObjId(obj->getObjId());
cloneObj->setPos(obj->pos()+pos());
cloneObj->m_prePos = cloneObj->pos();
addObj(cloneObj);
if(addToScene){
getScene()->addItem(cloneObj);
}
}
return true;
}
void CNewElfShape::addObj(CShape *obj)
{
if(obj == NULL)
{
return;
}
m_mergeList.push_back(obj);
obj->setParentObj(this);
obj->setFlag(QGraphicsItem::ItemIsMovable, false);
obj->setFlag(QGraphicsItem::ItemIsSelectable, false);
obj->setScene(getScene());
if(obj->getObjType() == OBJTYPE_RELATIVE)
{
CLinkLine *link = dynamic_cast<CLinkLine*>(obj);
link->setStartDevId(getInstObjId(link->getStartDevId()));
link->setEndDevId(getInstObjId(link->getEndDevId()));
}
else if(obj->getObjType() == OBJTYPE_STRING || obj->getObjType() == OBJTYPE_POKE || obj->getObjType() == OBJTYPE_DBDATA)
{
obj->setFlag(QGraphicsItem::ItemIsSelectable, true);
QMap<long, QString>::iterator iter = m_txtReplaceMap.find(obj->getObjId());
if(iter != m_txtReplaceMap.end())
{
CTextShape *text = dynamic_cast<CTextShape*>(obj);
text->setString(iter.value());
}
}
replaceDynamic(obj);
addObjIdMap(obj->getObjId(), getScene()->getElfObjID());
obj->setObjId(getScene()->getElfObjID());
getScene()->increaseElfObjID();
}
void CNewElfShape::setPropertyValue(const QString &name, QVariant value)
{
CShape::setPropertyValue(name, value);
if (name == "纵向缩放比例")
{
if(value.toDouble() < 0.1)
{
return;
}
setHFactor(value.toDouble());
}
else if (name == "横向缩放比例")
{
if(value.toDouble() < 0.1)
{
return;
}
setWFactor(value.toDouble());
}
else if(name == QObject::tr("调用图形"))
{
QString v = value.toString().replace("QFile--", "").replace("\\", "/");
if(v.contains(".elx"))
{
QString name;
CBaseInstance()->getPathName(CBase::PATH_TYPE_ELF, name);
QDir dir(name);
m_pokeFile = dir.relativeFilePath(v).remove(-4, 4);
}
else
{
m_pokeFile = v;
}
clear();
setIconInfo(m_pokeFile, true);
}
}
void CNewElfShape::getPropertyList(std::list<std::pair<QString, QVariant> > &propertyList)
{
updateMergeRectList();
QString str = m_pokeFile;
str = str.section('/', -1);
str = "QFile--" + str;
propertyList.push_back(std::pair<QString, QVariant>(QObject::tr("对象名称"), m_nameString));
propertyList.push_back(std::pair<QString, QVariant>(QObject::tr("位置"), QVariant(pos().toPoint())));
propertyList.push_back(std::pair<QString, QVariant>(QObject::tr("横向缩放比例"), getWFactor()));
propertyList.push_back(std::pair<QString, QVariant>(QObject::tr("纵向缩放比例"), getHFactor()));
propertyList.push_back(std::pair<QString, QVariant>(QObject::tr("是否显示"), getInitVisible()));
// propertyList.push_back(std::pair<QString, QVariant>(QObject::tr("轴Z坐标"), zValue()));
propertyList.push_back(std::pair<QString, QVariant>(QObject::tr("透明度"), opacity()));
propertyList.push_back(std::pair<QString, QVariant>(QObject::tr("调用图形"), str));
}
void CNewElfShape::updateGeometry(qreal x, qreal y, qreal width, qreal height)
{
prepareGeometryChange();
setPos(x, y);
m_width = width;
m_height = height;
setWFactor(m_width / m_initWidth);
setHFactor(m_height / m_initHeight);
}
void CNewElfShape::addObjIdMap(const long &temp, const long &inst)
{
m_tempInstMap[temp] = inst;
}
long CNewElfShape::getTempObjId(long nInstObjId)
{
QMap<long, long>::iterator iter = m_tempInstMap.begin();
for(; iter != m_tempInstMap.end(); ++iter)
{
if(iter.value() == nInstObjId)
{
return iter.key();
}
}
return -1;
}
long CNewElfShape::getInstObjId(long nTempObjId)
{
QMap<long, long>::iterator iter = m_tempInstMap.find(nTempObjId);
if(iter == m_tempInstMap.end())
{
return -1;
}
return iter.value();
}
void CNewElfShape::addReplaceTxt(long nInstObjId, const QString &text)
{
m_txtReplaceMap[getTempObjId(nInstObjId)] = text;
}
void CNewElfShape::replaceDynamic(CShape *obj)
{
int group,num;
QString cTag,pTag;
CDynamic *cDy,*pDy;
obj->getDynamicPtrInfo(group, num);
for(int n=0; n < group; ++n)
{
cDy = obj->getDynamicPtr(n, num);
if(cDy)
{
pDy = getDynamicPtr(n,num);
if(!pDy)
{
break;
}
cTag = cDy->getTagName(); //< "station1.PSCADA.digital.station1.G01_dlq.Pos.value"
pTag = pDy->getTagName(); //< "PSCADA.station1.G02"
QStringList cList = cTag.split(".");
QStringList pList = pTag.split(".");
if(cList.size() != 7 || pList.size() != 3)
{
continue;
}
cList[0] = pList[1];
cList[1] = pList[0];
cList[3] = pList[1];
cList[4] = QString(cList[4]).replace(QString(cList[4]).section("_", 0, 0), pList[2]);
cDy->setTagName(cList.join("."));
}
}
}
void CNewElfShape::paint(QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget *w)
{
Q_UNUSED(style)
Q_UNUSED(w)
painter->save();
auto objP = QRectF(m_startX, m_startY, m_width, m_height);
subDraw(painter, objP, Qt::darkBlue, Qt::DotLine, 0, Qt::NoBrush, 1);
drawHandles(painter);
painter->restore();
}
void CNewElfShape::mouseMoveEvent(QGraphicsSceneMouseEvent *e)
{
if(parentItem())
{
return QGraphicsItem::mouseMoveEvent(e);
}
if ((e -> buttons() & Qt::LeftButton) && (m_selPoint > -1) && scene())
{
QPointF mousePoint = (e -> pos());
prepareGeometryChange();
m_pos2 = pos() - mapToScene(mousePoint);
switch (m_selPoint)
{
case 3:
// m_width = mousePoint.x();
break;
case 6:
// m_width = mousePoint.x();
// m_height = mousePoint.y();
break;
case 5:
// m_height = mousePoint.y();
break;
default:
break;
}
if(m_width <= 4)
{
m_width = 4;
}
if(m_height <= 4)
{
m_height = 4;
}
setWFactor(m_width / m_initWidth);
setHFactor(m_height / m_initHeight);
}
else
{
QGraphicsItem::mouseMoveEvent(e);
}
}
QVariant CNewElfShape::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
switch (change)
{
case ItemSelectedChange:
{
QList<CShape *>::iterator it = m_mergeList.begin();
for (; it != m_mergeList.end(); it++)
{
(*it)->setFlag(QGraphicsItem::ItemIsSelectable, !value.toBool());
if(!dynamic_cast<CTextShape*>(*it))
{
(*it)->setFlag(QGraphicsItem::ItemIsSelectable, false);
}
}
if(value.toInt() == 1)
{
setZaxisTop();
}
else
{
setZaxisBottom();
}
}
default:
break;
};
return CShape::itemChange(change,value);
}

View File

@ -0,0 +1,236 @@
#include "CDyLinkLine.h"
#include "CLinkLine.h"
#include "../hmi/CGraphScene.h"
CDyLinkLine::CDyLinkLine(char type, QGraphicsItem *parent) : CLineShape(type, parent)
{
m_objType = type;
m_arrowType = ArrowType::End;
m_IslandState = 254;
setFlag(QGraphicsItem::ItemIsMovable, true);
setFlag(QGraphicsItem::ItemIsSelectable, true);
m_hoverPin = -1;
m_selPin = -1;
m_pinList << QPointF(m_startX, m_startY);
m_pinStatus << 0;
m_nodeNoVec << 0;
}
int CDyLinkLine::read(CGStream &stream, char flag)
{
CLineShape::read(stream, flag);
m_pinList.clear();
m_pinStatus.clear();
m_pinList << QPointF(m_startX, m_startY) << QPointF(m_endX, m_endY);
m_pinStatus << 0 << 0;
return 1;
}
CShape *CDyLinkLine::clone(char flag)
{
CDyLinkLine *pObj = new CDyLinkLine(m_objType, NULL);
pObj->copy((CShape *)this, flag);
return (CShape *)pObj;
}
int CDyLinkLine::copy(CShape *src, char flag)
{
Q_UNUSED(flag)
if (src == NULL)
{
return -1;
}
CLineShape::copy(src, flag);
m_pinList = ((CDyLinkLine*)src)->m_pinList;
m_pinStatus = ((CDyLinkLine*)src)->m_pinStatus;
return 0;
}
bool CDyLinkLine::IsPscadaLinkObj()
{
return true;
}
QPointF CDyLinkLine::getScenePin(qreal pin)
{
QPointF pinPoint;
if (pin >=0 && pin < m_pinList.count())
{
pinPoint = mapToScene(m_pinList.at(pin));
}
return pinPoint;
}
bool CDyLinkLine::getSelectScenePin(QPointF &pin)
{
if (m_selPin == -1)
{
return false;
}
else
{
pin = mapToScene(m_pinList.at(m_selPin));
}
return true;
}
qreal CDyLinkLine::getSelectPin()
{
return m_selPin;
}
int CDyLinkLine::getPinStatus(int pin)
{
int status = -1;
if (pin >= 0 && pin < 3)
{
status = m_pinStatus[pin];
}
return status;
}
void CDyLinkLine::setPinSelected(int pin)
{
m_selPin = pin;
}
void CDyLinkLine::setPinHovered(int pin)
{
m_hoverPin = pin;
}
void CDyLinkLine::setEndPoint(const QPointF &point)
{
CLineShape::setEndPoint(point);
if(m_pinList.size() > 1)
{
m_pinList.removeLast();
m_pinStatus.removeLast();
}
m_pinList << QPointF(m_endX, m_endY);
m_pinStatus << 0;
}
bool CDyLinkLine::getIslandState(int &state)
{
if (m_IslandState == 254)
{
return false;
}
else
{
state = m_IslandState;
return true;
}
}
void CDyLinkLine::setIslandState(int state)
{
m_IslandState= state;
}
QVariant CDyLinkLine::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
switch (change)
{
case ItemPositionHasChanged:
foreach (CLinkLine *edge, m_edgeList)
edge->adjust();
break;
default:
break;
};
return QGraphicsItem::itemChange(change,value);
}
void CDyLinkLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
unsigned char envFlag = getScene()->getEnvTypeFlag();
if(envFlag == AppMode::ExplorerMode)
{
CDynamic *pdyn = getDynamicPtr(0);
if (pdyn)
{
int qcolor = 0;
getIslandState(qcolor);
if(!qcolor)
{
int c = CBaseInstance()->getOffColor();
pdyn->setDyLineColor(c);
pdyn->setDyFillColor(c);
}
else
{
pdyn->setDyLineColor(getLineColor());
pdyn->setDyFillColor(getFillColor());
}
}
}
else
{
QPointF hander(3, 3);
QPointF pin;
for (int i = 0; i < m_pinList.count(); i++)
{
pin = m_pinList.at(i);
if (i == m_hoverPin)
{
painter->setBrush(QBrush(Qt::red));
}
painter->setPen(QPen(Qt::black));
painter->drawEllipse(QRectF(pin - hander, pin + hander));
}
}
CLineShape::paint(painter, option, widget);
}
void CDyLinkLine::mousePressEvent(QGraphicsSceneMouseEvent *e)
{
m_selPin = m_hoverPin;
CLineShape::mousePressEvent(e);
}
void CDyLinkLine::hoverMoveEvent(QGraphicsSceneHoverEvent *e)
{
CLineShape::hoverMoveEvent(e);
QPointF hoverPoint = e->pos();
{
for (m_hoverPin = 0; m_hoverPin < m_pinList.count(); m_hoverPin++)
{
if (hasClickedOn(hoverPoint, m_pinList.at(m_hoverPin)))
{
break;
}
}
if (m_hoverPin == m_pinList.count())
{
m_hoverPin = -1;
}
update();
}
}
void CDyLinkLine::hoverLeaveEvent(QGraphicsSceneHoverEvent *e)
{
if (m_hoverPin > -1)
{
m_hoverPin = -1;
update();
}
CLineShape::hoverLeaveEvent(e);
}

View File

@ -0,0 +1,47 @@
#ifndef CDYLINKLINE_H
#define CDYLINKLINE_H
#include "CLineShape.h"
class DLL_CLASS CDyLinkLine : public CLineShape
{
Q_OBJECT
public:
CDyLinkLine(char type, QGraphicsItem *parent = NULL);
int read(CGStream &stream, char flag);
CShape *clone(char flag = RW_PART_ALL);
int copy(CShape *src, char flag = RW_PART_ALL);
bool IsPscadaLinkObj();
QPointF getScenePin(qreal pin);
bool getSelectScenePin(QPointF &pin);
qreal getSelectPin();
int getPinStatus(int pin);
void setPinSelected(int pin);
void setPinHovered(int pin);
void setEndPoint(const QPointF &point);
bool getIslandState(int &state);
void setIslandState(int state);
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
void mousePressEvent(QGraphicsSceneMouseEvent *e);
void hoverMoveEvent(QGraphicsSceneHoverEvent *e);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *e);
public:
void getObjName(QString &name)
{
name = QObject::tr("自由连接线");
}
private:
int m_IslandState;
};
#endif // CDYLINKLINE_H

View File

@ -0,0 +1,60 @@
#ifndef CNEWELFSHAPE_H
#define CNEWELFSHAPE_H
#include "CGroupShape.h"
#include "../IconInfo/CIconInfo.h"
#include "../IconInfo/CIconInfoControl.h"
class DLL_CLASS CNewElfShape : public CGroupShape
{
Q_OBJECT
public:
CNewElfShape(char type, QGraphicsItem *parent = NULL);
virtual ~CNewElfShape();
void getObjName(QString &name)
{
name = m_pokeFile;
}
QString getPokeFile()
{
return m_pokeFile;
}
void clear();
int read(CGStream &stream, char flag);
int write(CGStream &stream, char flag);
qreal getWFactor() const;
qreal getHFactor() const;
void setWFactor(float value);
void setHFactor(float value);
bool setIconInfo(QString &name, bool addToScene = false);
void addObj(CShape *obj);
void setPropertyValue(const QString &name, QVariant value);
void getPropertyList(std::list< std::pair<QString, QVariant> > &propertyList);
void updateGeometry(qreal x, qreal y, qreal width, qreal height);
void addObjIdMap(const long &temp, const long &inst);
long getTempObjId(long nInstObjId);
long getInstObjId(long nTempObjId);
void addReplaceTxt(long nInstObjId, const QString &text);
void replaceDynamic(CShape *obj);
protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget *w);
void mouseMoveEvent(QGraphicsSceneMouseEvent *e);
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
public:
CIconInfo *m_pIconInfo;
QMap<long, long> m_tempInstMap; //< 模板obj_id - 实例obj_id
QMap<long, QString> m_txtReplaceMap; //< 模板obj_id - 文本
QString m_pokeFile;
qreal m_initWidth;
qreal m_initHeight;
};
#endif // CNEWELFSHAPE_H

View File

@ -0,0 +1,50 @@
#-------------------------------------------------
#
# Project created by QtCreator 2024-12-17T17:51:45
#
#-------------------------------------------------
QT += core gui widgets sql xml script
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = AutoCreateElement
TEMPLATE = lib
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
INCLUDEPATH += $$PWD
INCLUDEPATH += ../../PropertyEditor
SOURCES += \
CAutoCreate.cpp
HEADERS += \
CAutoCreate.h \
AutoCreateExport.h \
CAutoListModel.h
DEFINES += DLL_OUT_AUTOCREATE
LIBS += -lGraphPub -lGraphShape
LIBS += -llog4cplus -ldb_base_api -ldb_api_ex -lpub_logger_api -lpub_utility_api -ldb_sysinfo_api -lpub_widget
LIBS += -lPropertyEditor -lToolBoxTree
COMMON_PRI=$$PWD/../../../common.pri
exists($$COMMON_PRI) {
include($$COMMON_PRI)
}else {
error("FATAL error: can not find common.pri")
}
FORMS += \
CAutoCreate.ui

View File

@ -0,0 +1,26 @@
#ifndef AUTOCREATEEXPORT_H
#define AUTOCREATEEXPORT_H
#ifndef G_DECL_EXPORT_AUTOCREATE
# ifdef WIN32
# define G_DECL_EXPORT_AUTOCREATE __declspec(dllexport)
# else
# define G_DECL_EXPORT_AUTOCREATE __attribute__((visibility("default")))
# endif
#endif
#ifndef G_DECL_IMPORT_AUTOCREATE
# ifdef WIN32
# define G_DECL_IMPORT_AUTOCREATE __declspec(dllimport)
# else
# define G_DECL_IMPORT_AUTOCREATE
# endif
#endif
#ifdef DLL_OUT_AUTOCREATE
# define DLL_CLASS_AUTOCREATE G_DECL_EXPORT_AUTOCREATE
#else
# define DLL_CLASS_AUTOCREATE G_DECL_IMPORT_AUTOCREATE
#endif
#endif // AUTOCREATEEXPORT_H

View File

@ -0,0 +1,854 @@
#include "CAutoCreate.h"
#include "ui_CAutoCreate.h"
#include "dbms/db_sysinfo_api/CDbSysInfo.h"
#include "pub_logger_api/logger.h"
#include "pub_utility_api/FileUtil.h"
#include "pub_utility_api/I18N.h"
#include "pub_utility_api/FileStyle.h"
#include "pub_widget/PubWidgetInit.h"
#include "../ToolBoxTree/CBoxListView.h"
#include "../../include/CXMLStream.h"
#include "../../include/CShape.h"
#include "../GraphShape/include/CIconShape.h"
#include "../GraphShape/include/CDrawObjFactory.h"
#include "../GraphShape/include/CLinkLine.h"
#include "../GraphShape/include/CNewElfShape.h"
#include <QCompleter>
#include <QColorDialog>
#include <QButtonGroup>
#include <QGridLayout>
CAutoCreate::CAutoCreate(QWidget *parent, Qt::WindowFlags f) :
CustomUiDialog(parent),
ui(new Ui::CAutoCreate),
m_pReadDb(Q_NULLPTR),
m_devGroupModel(Q_NULLPTR),
m_devPointModel(Q_NULLPTR),
m_devPointSelModel(Q_NULLPTR),
m_pPropertyBox(Q_NULLPTR),
m_pToolBox(Q_NULLPTR),
m_pCurrentObj(Q_NULLPTR),
m_pGroupRadio(Q_NULLPTR)
{
ui->setupUi(this);
setWindowTitle(tr("批量生成图元"));
initial();
if(!parent)
{
setWindowFlag(Qt::WindowStaysOnTopHint);
setAttribute(Qt::WA_DeleteOnClose);
}
CustomUiDialog::setAutoLayout(true);
}
CAutoCreate::~CAutoCreate()
{
if(m_pReadDb != NULL)
{
m_pReadDb->close();
delete m_pReadDb;
}
m_pReadDb = NULL;
if( m_pCurrentObj )
{
delete m_pCurrentObj;
}
m_pCurrentObj = NULL;
delete ui;
}
void CAutoCreate::initial()
{
initDBConnect();
initVar();
loadSheet();
initUi();
initConn();
if ( m_pReadDb->isOpen())
{
QSqlQuery query;
//查询所有专业名称
m_pReadDb->execute(QString("select tag_name, description from sys_model_sub_system_info where sub_system_id > %1").arg(CN_AppId_COMAPP), query);
if(query.isActive())
{
while(query.next())
{
QString strSubSystemName = query.value(0).toString();
QString strSubSystemDesc = query.value(1).toString();
ui->Profession->addItem(strSubSystemDesc, strSubSystemName);
}
}
//查询所有位置名称
m_pReadDb->execute("select tag_name, description from sys_model_location_info", query);
if(query.isActive())
{
while(query.next())
{
QString strLocationName = query.value(0).toString();
QString strLocationDesc = query.value(1).toString();
ui->Location->addItem(strLocationDesc, strLocationName);
}
}
}
ui->Profession->adjustSize();
ui->Location->adjustSize();
}
void CAutoCreate::initDBConnect()
{
m_pReadDb = new CDbApi(DB_CONN_MODEL_READ);
m_pReadDb->open();
if(m_pReadDb->isOpen())
{
LOGINFO("initialize autoCreateElements database success!");
}
else
{
LOGERROR("initialize autoCreateElements database failed!");
}
}
void CAutoCreate::initUi()
{
ui->Device_TableView->setModel(m_devGroupModel);
ui->select_listView->setModel(m_devPointSelModel);
ui->select_listView->setDragEnabled(true);
ui->select_listView->setDropIndicatorShown(true);
ui->select_listView->setDragDropMode(QAbstractItemView::InternalMove);
ui->select_listView->setDefaultDropAction(Qt::MoveAction);
ui->TagNameView->setModel(m_devPointModel);
ui->TagNameView->setSelectionMode(QAbstractItemView::ExtendedSelection);
ui->TagTypeComboBox->addItem(tr("数字量"), "digital");
ui->TagTypeComboBox->addItem(tr("模拟量"), "analog");
ui->TagTypeComboBox->addItem(tr("混合量"), "mix");
ui->TagTypeComboBox->addItem(tr("累积量"), "accuml");
ui->TagTypeComboBox->addItem(tr("常量"), "const");
ui->TagTypeComboBox->setCurrentIndex(0);
QCompleter *completer = new QCompleter(ui->DeviceGroupComboBox->model()); //补全器
completer->setFilterMode(Qt::MatchContains);
ui->DeviceGroupComboBox->setEditable(true);
ui->DeviceGroupComboBox->setCompleter(completer);
ui->DeviceGroupComboBox->setInsertPolicy(QComboBox::NoInsert);
m_pGroupRadio = new QButtonGroup(this);
m_pGroupRadio->addButton(ui->radio_column , 0);
m_pGroupRadio->addButton(ui->radio_row , 1);
ui->radio_column->setChecked(true);
QPushButton * pDeviceFilter = new QPushButton(this);
pDeviceFilter->setObjectName("filterBtn");
pDeviceFilter->setCursor(QCursor(Qt::ArrowCursor));
QHBoxLayout * pDeviceLayout = new QHBoxLayout();
pDeviceLayout->setContentsMargins(1, 1, 1, 1);
pDeviceLayout->addStretch();
pDeviceLayout->addWidget(pDeviceFilter);
ui->DeviceFilter->setLayout(pDeviceLayout);
QPushButton * pPointFilter = new QPushButton(this);
pPointFilter->setObjectName("filterBtn");
pPointFilter->setCursor(QCursor(Qt::ArrowCursor));
QHBoxLayout * pPointLayout = new QHBoxLayout();
pPointLayout->setContentsMargins(1, 1, 1, 1);
pPointLayout->addStretch();
pPointLayout->addWidget(pPointFilter);
ui->DeviceFilter_point->setLayout(pPointLayout);
connect(pDeviceFilter, SIGNAL(clicked()), this, SLOT(slot_devGroupFilter()));
connect(pPointFilter, SIGNAL(clicked()), this, SLOT(slot_devPointFilter()));
//加载图元
loadToolBox();
}
void CAutoCreate::initVar()
{
m_devGroupModel = new QStandardItemModel(this);
m_devPointModel = new QStandardItemModel(this);
m_devPointSelModel = new CAutoListModel(this);
m_devPointModel->setColumnCount(2);
m_devPointSelModel->setColumnCount(2);
m_pPropertyBox = ui->widget;
m_pToolBox = ui->treeWidget;
}
void CAutoCreate::initConn()
{
connect(ui->Location, SIGNAL(currentIndexChanged(QString)), this, SLOT(slot_currentLocationChanged(QString)));
connect(ui->Profession, SIGNAL(currentIndexChanged(QString)), this, SLOT(slot_currentProfessionChanged(QString)));
connect(ui->DeviceGroupComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(slot_currentDevGroupChanged(QString)));
connect(ui->TagTypeComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(slot_currentDevGroupChanged(QString)));
connect(ui->Device_TableView, SIGNAL(clicked(QModelIndex)), this, SLOT(slot_currentSelectDeviceChanged(QModelIndex)));
connect(ui->DeviceFilter , SIGNAL(textEdited(QString)) , this , SLOT(slot_devGroupFilter()));
connect(ui->DeviceFilter_point , SIGNAL(textEdited(QString)) , this , SLOT(slot_devPointFilter()));
connect(ui->TagNameView , &QListView::doubleClicked , this , &CAutoCreate::slot_tagNameListViewDoubleClicked );
connect(ui->select_listView , &QListView::doubleClicked , this , &CAutoCreate::slot_selectListViewDoubleClicked );
connect(ui->btn_delAll , &QPushButton::clicked , this , &CAutoCreate::slot_deleAllBtnClicked);
connect(ui->btn_delSelect , &QPushButton::clicked , this , &CAutoCreate::slot_deleSelectBtnClicked);
connect(ui->btn_addAll , &QPushButton::clicked , this , &CAutoCreate::slot_addAllBtnClicked);
connect(ui->btn_addSelect , &QPushButton::clicked , this , &CAutoCreate::slot_addSelectBtnClicked);
connect(m_devPointSelModel , &QStandardItemModel::rowsInserted , this , &CAutoCreate::slot_updateLabel);
connect(m_devPointSelModel , &QStandardItemModel::rowsRemoved , this , &CAutoCreate::slot_updateLabel);
connect(ui->btn_confirm , &QPushButton::clicked , this , &CAutoCreate::slot_btnConfirmCreate);
connect(ui->btn_cancel , &QPushButton::clicked , this , &CAutoCreate::reject);
connect(m_pPropertyBox, SIGNAL(propertyValueChanged(QString, QVariant, bool)),
this, SLOT(updateCurrentProperty(QString, QVariant, bool)));
}
void CAutoCreate::loadSheet()
{
QString qss = QString();
std::string strFullPath = iot_public::CFileStyle::getPathOfStyleFile("public.qss","zh","light");
QFile qssfile1(QString::fromStdString(strFullPath));
qssfile1.open(QFile::ReadOnly);
if (qssfile1.isOpen())
{
qss += QLatin1String(qssfile1.readAll());
qssfile1.close();
}
strFullPath = iot_public::CFileStyle::getPathOfStyleFile("AutoCreate.qss","zh","light") ;
QFile qssfile(QString::fromStdString(strFullPath)) ;
qssfile.open(QFile::ReadOnly);
if (qssfile.isOpen())
{
qss += QLatin1String(qssfile.readAll());
qssfile.close();
}
if (!qss.isEmpty())
{
qApp->setStyleSheet(qss);
}
iot_public::installTranslator(iot_public::getCurLanguage());
}
void CAutoCreate::updatePointList()
{
m_devPointModel->clear();
QString professionDescription = ui->Profession->currentText();
QString locationDescription = ui->Location->currentText();
professionDescription = professionDescription.replace("'", "''");
locationDescription = locationDescription.replace("'", "''");
if( professionDescription.isEmpty() || locationDescription.isEmpty() || !ui->Device_TableView->currentIndex().isValid())
{
return;
}
QString strDeviceName = m_devGroupModel->item(ui->Device_TableView->currentIndex().row())->data().toString().split(",").first();
QString typeValue = ui->TagTypeComboBox->currentData().toString();
//获取当前设备 点位
if(m_pReadDb->isOpen())
{
QSqlQuery query;
QString queryStr = QString(
"SELECT l.tag_name AS location_tag_name,"
"s.tag_name AS sub_system_tag_name,"
"'%1' AS table_name,"
"t.tag_name AS point_tag_name,t.description "
"FROM %1 t "
"JOIN sys_model_sub_system_info s ON t.sub_system = s.sub_system_id "
"JOIN sys_model_location_info l ON t.location_id = l.location_id "
"WHERE t.sub_system = ("
"SELECT sub_system_id "
"FROM sys_model_sub_system_info "
"WHERE description = '%2' "
"AND sub_system_id > %3"
") "
"AND t.location_id = ("
"SELECT location_id "
"FROM sys_model_location_info "
"WHERE description = '%4'"
") "
"AND t.device = '%5'"
"ORDER BY t.seq_no ASC"
).arg(typeValue).arg(professionDescription).arg(CN_AppId_COMAPP).arg(locationDescription).arg(strDeviceName);
if( m_pReadDb->execute(queryStr, query) )
{
if(query.isActive())
{
while(query.next())
{
QString tagInfo = QString("%1.%2.%3.%4").arg(query.value(0).toString()).arg(query.value(1).toString()).arg(query.value(2).toString()).arg(query.value(3).toString());
QString desc = query.value(4).toString();
m_devPointModel->appendRow({new QStandardItem(desc) , new QStandardItem(tagInfo)});
}
}
}else
{
LOGERROR("AutoCreate: updatePointList sql failed! sqlStr: %s" , queryStr.toStdString().c_str());
}
}
if( m_devPointModel->index(0,0).isValid() )
{
ui->TagNameView->setCurrentIndex(m_devPointModel->index(0,0));
}
}
void CAutoCreate::loadToolBox()
{
loadIconTrans();
for (int j = 0; j < DrawObjDatabase::numWidgetGroups(); j++)
{
QString grp = DrawObjDatabase::widgetGroup(j);
//目前只开放基本图元以及电气图元
if ( (grp != tr("基本图元") && grp != tr("电气图元")) || !DrawObjDatabase::isGroupVisible(grp))
{
continue;
}
QTreeWidgetItem *tb2 = new QTreeWidgetItem(m_pToolBox);
tb2->setText(0, s_iconTransMap[grp]);
tb2->setData(0, Qt::UserRole + 3, grp);
CBoxListView * listView = m_pToolBox->addListView(tb2, true);
connect(listView, &CBoxListView::itemPressed, this, &CAutoCreate::slot_updataProPerty);
for (int i = 0; i < DrawObjDatabase::count(); ++i)
{
if (DrawObjDatabase::group(i) != grp)
{
continue;
}
DrawObjDatabaseRecord * record = DrawObjDatabase::at(i);
if(record)
{
record->name = s_iconTransMap[record->name];
DrawObjDatabase::iconSet(i);
listView->addWidget(record);
}
}
m_pToolBox->adjustSubListSize(tb2);
}
}
void CAutoCreate::loadIconTrans()
{
if(!s_iconTransMap.isEmpty())
return;
CXMLStream xmls;
QString toolTrans;
CBaseInstance()->getPathName(CBase::PATH_TYPE_ICONTRANS, toolTrans);
for(int j = 0; j < DrawObjDatabase::numWidgetGroups(); j++)
{
QString grp = DrawObjDatabase::widgetGroup(j);
s_iconTransMap[grp] = grp;
for(int i = 0; i < DrawObjDatabase::count(); ++i)
{
QString atext = DrawObjDatabase::className(i);
s_iconTransMap[atext] = atext;
}
}
int ret = xmls.OPEN(toolTrans.toLocal8Bit().data(), 100, 1);
if(ret == -1)
{
return;
}
QDomElement contextItem, transItem;
contextItem = xmls.GetChild("context");
QDomNode transNode = contextItem.firstChild();
QString source, trans;
while(!transNode.isNull())
{
transItem = transNode.toElement();
source = transItem.attribute("source");
trans = transItem.attribute("trans");
s_iconTransMap[source] = trans.isEmpty() ? source : trans;
transNode = transNode.nextSibling();
}
xmls.CLOSE();
}
void CAutoCreate::getAllSelectPointInfo(QList<QPair<QString, QString> > &listInfo)
{
listInfo.clear();
int rowCount = m_devPointSelModel->rowCount();
for (int row = 0; row < rowCount; ++row)
{
QStandardItem *descItem = m_devPointSelModel->item(row, 0);
QStandardItem *valueItem = m_devPointSelModel->item(row, 1);
if (descItem && valueItem)
{
QString desc = descItem->text();
QString value = valueItem->text();
listInfo.append(qMakePair(desc, value));
}
}
}
void CAutoCreate::updateCurrentProperty(const QString &name, const QVariant &value, bool sub)
{
Q_UNUSED(sub)
if( m_pCurrentObj == NULL)
{
return;
}
m_pCurrentObj->setPropertyValue(name, value);
m_pCurrentObj->update();
}
void CAutoCreate::slot_btnConfirmCreate()
{
int count = ui->spinBox_num->value();
int lineSpace = ui->spinBox_index->value();
int checkId = m_pGroupRadio->checkedId();
QList<QPair<QString, QString>> allData;
getAllSelectPointInfo(allData);
if( m_pCurrentObj && count > 0 )
{
CShape * tmp = m_pCurrentObj->clone(RW_PART_SHAPE | RW_PART_LINK);
emit signal_createBatchObj(tmp , allData ,count , checkId ,lineSpace);
}
}
void CAutoCreate::slot_currentLocationChanged(const QString &text)
{
Q_UNUSED(text);
slot_currentProfessionChanged(text);
}
void CAutoCreate::slot_currentDevGroupChanged(const QString &text)
{
Q_UNUSED(text)
m_devGroupModel->clear();
QString dev_grp = ui->DeviceGroupComboBox->currentData().toString();
QString professionDescription = ui->Profession->currentText();
QString locationDescription = ui->Location->currentText();
if( dev_grp.isEmpty() || professionDescription.isEmpty() || locationDescription.isEmpty())
{
updatePointList();
return;
}
dev_grp = dev_grp.replace("'", "''");
professionDescription = professionDescription.replace("'", "''");
locationDescription = locationDescription.replace("'", "''");
if(m_pReadDb->isOpen())
{
QSqlQuery query;
QString queryStr = QString(
"SELECT description, tag_name, dev_type "
"FROM dev_info "
"WHERE sub_system = ("
"SELECT sub_system_id "
"FROM sys_model_sub_system_info "
"WHERE description = '%1' "
"AND sub_system_id > %2"
") "
"AND location_id = ("
"SELECT location_id "
"FROM sys_model_location_info "
"WHERE description = '%3'"
") "
"AND group_tag_name = '%4'"
).arg(professionDescription).arg(CN_AppId_COMAPP).arg(locationDescription).arg(dev_grp);
if( m_pReadDb->execute(queryStr, query) )
{
if(query.isActive())
{
while(query.next())
{
QStandardItem *item = new QStandardItem();
item->setText(query.value(0).toString());
item->setData(query.value(1).toString() + "," + query.value(2).toString());
m_devGroupModel->appendRow(item);
}
}
}else
{
LOGERROR("AutoCreate slot_currentDevGroupChanged sql failed! sqlstr: %s" , queryStr.toStdString().c_str());
}
}
if( m_devGroupModel->index(0,0).isValid() )
{
ui->Device_TableView->setCurrentIndex(m_devGroupModel->index(0,0));
emit ui->Device_TableView->clicked(m_devGroupModel->index(0,0));
}
updatePointList();
}
void CAutoCreate::slot_currentTypeChanged(const QString &text)
{
Q_UNUSED(text)
updatePointList();
}
void CAutoCreate::slot_currentSelectDeviceChanged(const QModelIndex &index)
{
Q_UNUSED(index)
//updateTableType();
updatePointList();
}
void CAutoCreate::slot_devGroupFilter()
{
QString filterName = ui->DeviceFilter->text();
int nRowCount = m_devGroupModel->rowCount();
for (int nIndex = 0; nIndex < nRowCount; nIndex++)
{
if (filterName.isEmpty() || m_devGroupModel->item(nIndex)->text().contains(filterName,Qt::CaseInsensitive))
{
ui->Device_TableView->setRowHidden(nIndex,false);
}
else
{
ui->Device_TableView->setRowHidden(nIndex,true);
}
}
}
void CAutoCreate::slot_devPointFilter()
{
QString filterName = ui->DeviceFilter_point->text();
int nRowCount = m_devPointModel->rowCount();
for (int nIndex = 0; nIndex < nRowCount; nIndex++)
{
if (filterName.isEmpty() || m_devPointModel->item(nIndex , 0)->text().contains(filterName,Qt::CaseInsensitive))
{
ui->TagNameView->setRowHidden(nIndex,false);
}
else
{
ui->TagNameView->setRowHidden(nIndex,true);
}
}
}
void CAutoCreate::slot_tagNameListViewDoubleClicked(const QModelIndex &index)
{
if( index.isValid() )
{
QStandardItem *item1 = m_devPointModel->itemFromIndex(m_devPointModel->index(index.row(), 0));
QStandardItem *item2 = m_devPointModel->itemFromIndex(m_devPointModel->index(index.row(), 1));
if (item1 && item2)
{
QList<QStandardItem *> newRow;
QStandardItem *tmp = new QStandardItem(item1->text());
QStandardItem *tmp2 = new QStandardItem(item2->text()+ QString(".value"));
tmp->setFlags(tmp->flags() | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
tmp2->setFlags(tmp2->flags() | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
newRow.append(tmp);
newRow.append(tmp2);
m_devPointSelModel->appendRow(newRow);
}
}
}
void CAutoCreate::slot_selectListViewDoubleClicked(const QModelIndex &index)
{
if (index.isValid())
{
QStandardItem *item = m_devPointSelModel->itemFromIndex(index);
if (item) {
m_devPointSelModel->removeRow(item->row());
}
}
}
void CAutoCreate::slot_deleSelectBtnClicked()
{
QItemSelectionModel *selectionModel = ui->select_listView->selectionModel();
QModelIndexList list = selectionModel->selectedIndexes();
for( const QModelIndex &index : list)
{
if( index.isValid() )
{
m_devPointSelModel->removeRow(index.row());
}
}
slot_updateLabel();
}
void CAutoCreate::slot_deleAllBtnClicked()
{
m_devPointSelModel->clear();
slot_updateLabel();
}
void CAutoCreate::slot_addAllBtnClicked()
{
int rowCount = m_devPointModel->rowCount();
for (int row = 0; row < rowCount; ++row) {
QStandardItem *item = m_devPointModel->item(row , 0);
QStandardItem *item2 = m_devPointModel->item(row , 1);
if (item && item2) {
QList<QStandardItem *> newRow;
newRow.append(new QStandardItem(item->text()));
newRow.append(new QStandardItem(item2->text()+ QString(".value")));
m_devPointSelModel->appendRow(newRow);
}
}
}
void CAutoCreate::slot_addSelectBtnClicked()
{
QItemSelectionModel *tmp = ui->TagNameView->selectionModel();
QModelIndexList list = tmp->selectedIndexes();
for( const QModelIndex &index : list)
{
slot_tagNameListViewDoubleClicked(index);
}
}
void CAutoCreate::slot_updateLabel()
{
ui->label_selectCount->setText(QString::number(m_devPointSelModel->rowCount()));
ui->spinBox_num->setValue(m_devPointSelModel->rowCount());
}
void CAutoCreate::constructLink(CGroupShape *obj, QVector<int> &subIdx)
{
if(!obj) return;
qDebug() << "subIdx:" << subIdx;
QList<CShape *> *sublist = obj->getMergeListPtr();
if(sublist)
{
CShape *tmp = NULL;
QList<CShape *>::iterator it = sublist->begin();
for(; it != sublist->end(); it++)
{
tmp = (*it);
qDebug() << "tmp:" << tmp->getObjId();
if(tmp->getObjType() == OBJTYPE_RELATIVE)
{
CLinkLine *link = dynamic_cast<CLinkLine *>(tmp);
CShape *startDev = NULL;
CShape *endDev = NULL;
qDebug() << "link:" << link->getStartDevId();
if(link->getStartDevId() > 0 && link->getEndDevId() > 0)
{
int idxs = subIdx.indexOf(link->getStartDevId());
int idxe = subIdx.indexOf(link->getEndDevId());
qDebug() << idxs << " " << idxe;
if(idxs != idxe && idxs >= 0 && idxe >= 0)
{
startDev = sublist->at(idxs);
endDev = sublist->at(idxe);
}
}
if(startDev && endDev)
{
link->initLink(startDev, endDev, link->getStartDevPin(), link->getEndDevPin());
link->adjust(true);
link->setFlag(QGraphicsItem::ItemIsMovable, false);
}
}
}
}
}
CShape* CAutoCreate::shapeTwin(CShape *obj)
{
if(!obj) return NULL;
CGStream bofs;
bofs.Init(CGStream::buffer);
obj->copyToClipboard(bofs);
bofs.GoStart();
CShape *twin = NULL;
QList<CShape *> retlist;
CDrawObjFactory *fac;
getDrawObjFactory(&fac);
fac->createDrawObj(obj->getObjType(), &twin);
// twin->setScene(this);
// twin->setParentWidget((QWidget *)views().front()->viewport(), getEnvTypeFlag());
twin->pasteFromClipboard(bofs, &retlist, RW_PART_SHAPE | RW_PART_LINK);
twin = retlist.first();
fac->release();
return twin;
}
void CAutoCreate::slot_updataProPerty(const DrawObjDatabaseRecord *record)
{
std::list< std::pair<QString, QVariant> > propertylist;
std::list< std::pair<QString, QVariant> >::iterator iter;
QMap<QString, QVariant> propertymap;
QString propertyname;
QVariant propertyvalue;
QString splitname;
QMap<QString, QMap<QString, QVariant> > myproperty;
QMap<QString, QStringList> propertyOrderMap;
if( NULL == record)
{
return;
}
if( m_pCurrentObj )
{
delete m_pCurrentObj;
}
m_pCurrentObj = NULL;
int objType = record->toolType;
QString typeN = record->typeSub;
QString mark = record->mark;
QString strategy = record->strategy;
QString name = record->name;
//创建一个临时图元
CDrawObjFactory *fac;
getDrawObjFactory(&fac);
fac->createDrawObj(objType, &m_pCurrentObj, typeN);
fac->release();
if(NULL == m_pCurrentObj)
{
return;
}
if (objType == OBJTYPE_ICON + 20 && !name.isEmpty())
{
(dynamic_cast<CIconShape *>(m_pCurrentObj))->setIconInfo(objType - 100, name);
}
else if (objType == OBJTYPE_ICON + 25 && !name.isEmpty())
{
CIconInfo * iconInfo = IconInfoControlInstance()->getIconInfoPtr(objType - 100, name);
if (iconInfo == NULL)
{
iconInfo = IconInfoControlInstance()->getUnknowIconInfoPtr();
}
QList<CShape *> *objlist = iconInfo->getObjListPtr();
if(!objlist->isEmpty())
{
delete m_pCurrentObj;
m_pCurrentObj = NULL;
QVector<int> subIdx;
CShape *tmp = objlist->first();
if(tmp->getObjType() != OBJTYPE_MERGE)
{
return;
}
foreach (CShape *obj, dynamic_cast<CGroupShape *>(tmp)->m_mergeList)
{
subIdx.push_back(obj->getObjId());
}
constructLink(dynamic_cast<CGroupShape *>(tmp), subIdx);
m_pCurrentObj = shapeTwin(tmp);
}else if (objType == OBJTYPE_ELF && !name.isEmpty() && name != "精灵图元")
{
CNewElfShape * tmp = dynamic_cast<CNewElfShape *>(m_pCurrentObj);
tmp->setIconInfo(name, false);
}
}
m_pCurrentObj->m_dyStrategy = strategy;
m_pCurrentObj->m_mark = mark;
//获取属性
m_pCurrentObj->getPropertyList(propertylist);
m_pCurrentObj->getObjName(splitname);
if(m_pCurrentObj->IsIconObj())
{
splitname = s_iconTransMap[splitname];
}
QStringList propertyOrder;
for (iter = propertylist.begin(); iter != propertylist.end(); iter ++)
{
propertyname = (*iter).first;
propertyvalue = (*iter).second;
//跳过对象名称和位置
if( propertyname == tr("对象名称") || propertyname == tr("位置"))
{
continue;
}
propertyOrder.append(propertyname);
propertymap.insert(propertyname, propertyvalue);
}
propertyOrderMap.insert(splitname, propertyOrder);
myproperty.insert(splitname, propertymap);
m_pPropertyBox->CreatePropertySheet(propertyOrderMap, myproperty);
}
void CAutoCreate::slot_currentProfessionChanged(const QString &text)
{
Q_UNUSED(text);
ui->DeviceGroupComboBox->clear();
QString professionDescription = ui->Profession->currentText();
QString locationDescription = ui->Location->currentText();
professionDescription = professionDescription.replace("'", "''");
locationDescription = locationDescription.replace("'", "''");
if(m_pReadDb->isOpen())
{
QSqlQuery query;
//查询该专业、车站下所有设备组
QString queryStr = QString(
"SELECT description, tag_name "
"FROM dev_group "
"WHERE sub_system = ("
"SELECT sub_system_id "
"FROM sys_model_sub_system_info "
"WHERE description = '%1' "
"AND sub_system_id > %2"
") "
"AND location_id = ("
"SELECT location_id "
"FROM sys_model_location_info "
"WHERE description = '%3'"
") "
"ORDER BY dev_group_no ASC"
).arg(professionDescription).arg(CN_AppId_COMAPP).arg(locationDescription);
if( m_pReadDb->execute(queryStr, query) )
{
if(query.isActive())
{
while(query.next())
{
ui->DeviceGroupComboBox->addItem(query.value(0).toString(), query.value(1).toString());
}
}
}else
{
LOGERROR("AutoCreate: slot_currentProfessionChanged sql failed! sqlStr: %s" , queryStr.toStdString().c_str());
}
}
if( ui->DeviceGroupComboBox->count() > 0 )
{
ui->DeviceGroupComboBox->setCurrentIndex(0);
}else
{
ui->DeviceGroupComboBox->setCurrentIndex(-1);
}
}

View File

@ -0,0 +1,86 @@
#ifndef CAUTOCREATE_H
#define CAUTOCREATE_H
#include "db_api_ex/CDbApi.h"
#include "AutoCreateExport.h"
#include "pub_widget/CustomDialog.h"
#include "../../include/propertyeditor.h"
#include "../ToolBoxTree/CBoxTreeWidget.h"
#include "../ToolBoxTree/CDrawObjDatabase.h"
#include "../../include/CShape.h"
#include "../GraphShape/include/CGroupShape.h"
#include "CAutoListModel.h"
#include <QWidget>
#include <QStandardItemModel>
namespace Ui {
class CAutoCreate;
}
using namespace iot_dbms;
class DLL_CLASS_AUTOCREATE CAutoCreate : public CustomUiDialog
{
Q_OBJECT
public:
explicit CAutoCreate(QWidget *parent = 0, Qt::WindowFlags f = Qt::WindowFlags());
~CAutoCreate();
private:
void initial(); //初始化
void initDBConnect(); //初始化数据库连接
void initUi(); //界面初始化
void initConn(); //连接初始化
void initVar(); //变量初始化
void loadSheet();
void updatePointList(); //更新点位数据
void loadToolBox(); //加载图元
void loadIconTrans(); //加载翻译
void getAllSelectPointInfo(QList<QPair<QString,QString>> &listInfo); //获取选中的点位信息
void constructLink(CGroupShape *obj, QVector<int> &subIdx);
CShape *shapeTwin(CShape *obj);
private slots:
void slot_currentProfessionChanged(const QString &text);
void slot_currentLocationChanged(const QString &text);
void slot_currentDevGroupChanged(const QString &text);
void slot_currentTypeChanged(const QString &text);
void slot_currentSelectDeviceChanged(const QModelIndex &index);
void slot_devGroupFilter();
void slot_devPointFilter();
void slot_tagNameListViewDoubleClicked(const QModelIndex &index);
void slot_selectListViewDoubleClicked(const QModelIndex &index);
void slot_deleSelectBtnClicked();
void slot_deleAllBtnClicked();
void slot_addAllBtnClicked();
void slot_addSelectBtnClicked();
void slot_updateLabel();
void slot_updataProPerty(const DrawObjDatabaseRecord *record);
void updateCurrentProperty(const QString &name, const QVariant &value, bool sub);
void slot_btnConfirmCreate();
signals:
void signal_createBatchObj(CShape *obj , QList<QPair<QString,QString>> listInfo, int count , int rowOrCol , int lineSpace);
private:
Ui::CAutoCreate *ui;
CDbApi * m_pReadDb;
QStandardItemModel *m_devGroupModel;
QStandardItemModel *m_devPointModel;
CAutoListModel *m_devPointSelModel;
PropertyEditor *m_pPropertyBox;
CBoxTreeWidget *m_pToolBox;
DrawObjDatabaseRecord *m_pSelectRecord; //当前所选择的图元
QButtonGroup *m_pGroupRadio;
public:
QMap<QString, QString> s_iconTransMap;
CShape *m_pCurrentObj; //当前选中的对象
};
#endif // CAUTOCREATE_H

View File

@ -0,0 +1,686 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CAutoCreate</class>
<widget class="QWidget" name="CAutoCreate">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>950</width>
<height>733</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="1" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_confirm">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>75</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>确定</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_cancel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>75</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>取消</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<widget class="QFrame" name="frame_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<item row="1" column="0" rowspan="2" colspan="2">
<widget class="CBoxTreeWidget" name="treeWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QFrame" name="frame_5">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBox_num"/>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="spinBox_index">
<property name="value">
<number>10</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>数量:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QRadioButton" name="radio_column">
<property name="text">
<string>按列排</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QRadioButton" name="radio_row">
<property name="text">
<string>按行排</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>行列距:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="PropertyEditor" name="widget" native="true"/>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QFrame" name="frame_4">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>520</width>
<height>640</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="4" column="0">
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>500</width>
<height>330</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QFrame" name="frame_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout_10">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_5" columnstretch="0,0,0,0,0,0">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="5">
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_16">
<property name="text">
<string>点类型:</string>
</property>
</widget>
</item>
<item row="0" column="2" colspan="2">
<widget class="QComboBox" name="TagTypeComboBox">
<property name="styleSheet">
<string notr="true">QComboBox QAbstractItemView::item{min-height: 23px;}</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLineEdit" name="DeviceFilter_point">
<property name="maximumSize">
<size>
<width>160</width>
<height>16777215</height>
</size>
</property>
<property name="inputMask">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="cursorPosition">
<number>0</number>
</property>
<property name="placeholderText">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QListView" name="TagNameView">
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="Line" name="line_12">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="btn_addAll">
<property name="text">
<string>添加全部</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_addSelect">
<property name="text">
<string>添加</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_delSelect">
<property name="text">
<string>删除</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_delAll">
<property name="text">
<string>删除全部</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<widget class="QListView" name="select_listView"/>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QFrame" name="frame_6">
<property name="minimumSize">
<size>
<width>0</width>
<height>50</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout_18">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="1" column="0">
<widget class="Line" name="line_6">
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_20" columnstretch="0,2,1">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<property name="horizontalSpacing">
<number>2</number>
</property>
<property name="verticalSpacing">
<number>4</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>设备组:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLineEdit" name="DeviceFilter">
<property name="maximumSize">
<size>
<width>160</width>
<height>16777215</height>
</size>
</property>
<property name="inputMask">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="cursorPosition">
<number>0</number>
</property>
<property name="placeholderText">
<string/>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="DeviceGroupComboBox"/>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QListView" name="Device_TableView">
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QFrame" name="frame_9">
<property name="minimumSize">
<size>
<width>0</width>
<height>60</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout_3" columnstretch="0,0,0,0">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<property name="spacing">
<number>4</number>
</property>
<item row="0" column="1">
<widget class="QComboBox" name="Profession">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QComboBox QAbstractItemView::item{min-height: 23px;}</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
</property>
<property name="minimumContentsLength">
<number>12</number>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QComboBox" name="Location">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>25</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QComboBox QAbstractItemView::item{min-height: 23px;}</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
</property>
<property name="minimumContentsLength">
<number>12</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>位置:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>专业:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>已选择测点数:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_selectCount">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>PropertyEditor</class>
<extends>QWidget</extends>
<header>../../include/propertyeditor.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>CBoxTreeWidget</class>
<extends>QTreeWidget</extends>
<header>../ToolBoxTree/CBoxTreeWidget.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,68 @@
#ifndef CAUTOLISTMODEL_H
#define CAUTOLISTMODEL_H
#include <QObject>
#include "AutoCreateExport.h"
#include <QStandardItemModel>
#include <QMimeData>
#include <QListView>
class DLL_CLASS_AUTOCREATE CAutoListModel: public QStandardItemModel
{
Q_OBJECT
public:
using QStandardItemModel::QStandardItemModel;
Qt::DropActions supportedDropActions() const override {
return Qt::MoveAction;
}
bool dropMimeData(const QMimeData *data, Qt::DropAction action,
int row, int column, const QModelIndex &parent) override {
Q_UNUSED(column)
if (action == Qt::IgnoreAction)
return true;
row = parent.row();
if (!data->hasFormat("application/x-qabstractitemmodeldatalist"))
return false;
QByteArray encoded = data->data("application/x-qabstractitemmodeldatalist");
QDataStream stream(&encoded, QIODevice::ReadOnly);
int sourceRow = -1;
while (!stream.atEnd()) {
int r, c;
QMap<int, QVariant> roles;
stream >> r >> c >> roles;
if (sourceRow == -1)
sourceRow = r;
}
if (row == -1)
row = rowCount();
if (sourceRow == row)
return false;
if (sourceRow >= 0 && sourceRow < rowCount()) {
QList<QStandardItem*> items = takeRow(sourceRow);
if( row >= rowCount())
{
appendRow(items);
}else
{
insertRow(row, items);
}
return true;
}
return false;
}
};
#endif // CAUTOLISTMODEL_H

View File

@ -0,0 +1,181 @@
#include "CAutoListView.h"
#include <QDrag>
#include <QPainter>
CAutoListView::CAutoListView(QWidget *parent)
:QListView(parent)
{
// setSelectionMode(QAbstractItemView::ExtendedSelection);
// setDragEnabled(true);
// setAcceptDrops(true);
// setDropIndicatorShown(true);
// setDefaultDropAction(Qt::MoveAction);
}
void CAutoListView::mousePressEvent(QMouseEvent *event)
{
if(event->buttons() & Qt::LeftButton){
startPos = event->pos();
}
QListView::mousePressEvent(event);
}
void CAutoListView::mouseReleaseEvent(QMouseEvent *event)
{
QListView::mouseReleaseEvent(event);
if((event->pos() - startPos).manhattanLength() > 5) return;
QModelIndex index = indexAt(event->pos());
setCurrentIndex(index); //鼠标relesse时才选中
}
void CAutoListView::mouseMoveEvent(QMouseEvent *event)
{
QListView::mouseMoveEvent(event);
if(event->buttons() & Qt::LeftButton){
if((event->pos() - startPos).manhattanLength() < QApplication::startDragDistance()) return;
QModelIndex theDragIndex = indexAt(startPos);
theDragRow = theDragIndex.row();
setCurrentIndex(theDragIndex); //拖拽即选中
QStandardItemModel *listModel = qobject_cast<QStandardItemModel *>(model());
QStandardItem *theDragItem = static_cast<QStandardItem *>(listModel->item(theDragRow));
//[1]把拖拽数据放在QMimeData容器中
QString text = theDragItem->text();
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << text;
QMimeData *mimeData = new QMimeData;
mimeData->setData(myMimeType(), itemData);
//[1]
// 创建 QDrag 对象并设置拖拽数据和预览图
QPixmap pixmap = QPixmap(100, 50); // 创建一个固定大小的预览图
pixmap.fill(Qt::transparent); // 透明背景
QPainter painter(&pixmap);
painter.setPen(Qt::black);
painter.setFont(QFont("Arial", 10));
painter.drawText(pixmap.rect(), Qt::AlignCenter, text); // 在图像上绘制文本
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setPixmap(pixmap);
drag->setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2)); // 设置热点位置为图像中心
//删除的行需要根据theInsertRow和theDragRow的大小关系来判断(这个也是我根据实际情况测试发现的)
if(drag->exec(Qt::MoveAction) == Qt::MoveAction){
int theRemoveRow = -1;
if(theInsertRow < theDragRow) theRemoveRow = theDragRow + 1;
else theRemoveRow = theDragRow;
model()->removeRow(theRemoveRow);
}
}
}
void CAutoListView::dragEnterEvent(QDragEnterEvent *event)
{
CAutoListView *source = qobject_cast<CAutoListView *>(event->source());
if (source && source == this) {
//IsDraging(标志位)判断是否正在拖拽
IsDraging = true;
event->setDropAction(Qt::MoveAction);
event->accept();
}
}
void CAutoListView::dragLeaveEvent(QDragLeaveEvent *event)
{
oldHighlightedRow = theHighlightedRow;
theHighlightedRow = -2;
//之前QListWidget用的是update(QRect)这里用的是update(QModelIndex)当然这里也可以使用update(QRect),只是想换一种方法而已
update(model()->index(oldHighlightedRow, 0)); //UpRow
update(model()->index(oldHighlightedRow + 1, 0)); //DownRow
IsDraging = false; //IsDraging(标志位)判断是否正在拖拽
theInsertRow = -1;
event->accept();
}
void CAutoListView::dragMoveEvent(QDragMoveEvent *event)
{
CAutoListView *source = qobject_cast<CAutoListView *>(event->source());
if (source && source == this) {
oldHighlightedRow = theHighlightedRow;
theHighlightedRow = indexAt(event->pos() - QPoint(0, offset())).row();
//offset() = 19 = 40 / 2 - 1其中40是行高
if(event->pos().y() >= offset()){
if(oldHighlightedRow != theHighlightedRow){
//刷新旧区域使dropIndicator消失
update(model()->index(oldHighlightedRow, 0));
update(model()->index(oldHighlightedRow + 1, 0));
//刷新新区域使dropIndicator显示
update(model()->index(theHighlightedRow, 0));
update(model()->index(theHighlightedRow + 1, 0));
}else{
update(model()->index(theHighlightedRow, 0));
update(model()->index(theHighlightedRow + 1, 0));
}
theInsertRow = theHighlightedRow + 1;
}else{
theHighlightedRow = -1;
update(model()->index(0, 0));
update(model()->index(1, 0));
theInsertRow = 0;
}
event->setDropAction(Qt::MoveAction);
event->accept();
}
}
void CAutoListView::dropEvent(QDropEvent *event)
{
CAutoListView *source = qobject_cast<CAutoListView *>(event->source());
if (source && source == this){
IsDraging = false; //IsDraging(标志位)判断是否正在拖拽
oldHighlightedRow = theHighlightedRow;
theHighlightedRow = -2;
//刷新旧区域使dropIndicator消失
update(model()->index(oldHighlightedRow, 0));
update(model()->index(oldHighlightedRow + 1, 0));
if(theInsertRow == theDragRow || theInsertRow == theDragRow + 1) return;
//这里我像QListWidget那样调用父类dropEvent(event)发现不起作用(原因尚不明),没办法,只能删除旧行,插入新行
//if(theSelectedRow == theDragRow){
//QListView::dropEvent(event);
//return;
//}
QString text;
QIcon icon, icon_hover;
QByteArray itemData = event->mimeData()->data(myMimeType());
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
dataStream >> text;
model()->insertRow(theInsertRow);
QStandardItemModel *listModel = qobject_cast<QStandardItemModel *>(model());
listModel->setItem(theInsertRow, 0, new QStandardItem(text));
setCurrentIndex(model()->index(theInsertRow, 0)); //插入行保持选中状态
event->setDropAction(Qt::MoveAction);
event->accept();
}
}

View File

@ -0,0 +1,93 @@
#ifndef CAUTOLISTVIEW_H
#define CAUTOLISTVIEW_H
#include <QObject>
#include <QListView>
#include "Export.h"
#include "CAutoCreate.h"
class DLL_CLASS CAutoListView : public QListView
{
Q_OBJECT
public:
CAutoListView(QWidget *parent = Q_NULLPTR);
bool isDraging() const {return IsDraging;}
int offset() const {return 19;}
int highlightedRow() const {return theHighlightedRow;}
int dragRow() const {return theDragRow;}
static QString myMimeType() { return QStringLiteral("TestListView/text-icon-icon_hover"); }
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void dragEnterEvent(QDragEnterEvent *event) override;
void dragLeaveEvent(QDragLeaveEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
void dropEvent(QDropEvent *event) override;
//protected:
// void dragEnterEvent(QDragEnterEvent *event) override {
// CAutoListView *source = qobject_cast<CAutoListView *>(event->source());
// if (source && source == this) {
// //IsDraging(标志位)判断是否正在拖拽
// //IsDraging = true;
// event->setDropAction(Qt::MoveAction);
// event->accept();
// }
// }
// void dragMoveEvent(QDragMoveEvent *event) override {
// event->setDropAction(Qt::MoveAction);
// event->accept();
// }
// void dropEvent(QDropEvent *event) override {
// CAutoListView *source = qobject_cast<CAutoListView *>(event->source());
// if (source && source == this) {
// // 设置拖放操作类型
// event->setDropAction(Qt::MoveAction);
// // 调用父类的 dropEvent 处理
// QListView::dropEvent(event);
// // 获取当前模型
// QAbstractItemModel *model = this->model();
// // 获取拖动到的索引
// QModelIndex dropIndex = indexAt(event->pos());
// if (!dropIndex.isValid()) return;
// // 获取所选项索引
// QModelIndexList selectedIndexes = selectionModel()->selectedIndexes();
// if (selectedIndexes.isEmpty()) return;
// // 排序索引列表,确保从上到下的顺序
// std::sort(selectedIndexes.begin(), selectedIndexes.end(), [](const QModelIndex &a, const QModelIndex &b) {
// return a.row() < b.row();
// });
// // 遍历所选项,逐个删除它们
// for (const QModelIndex &index : selectedIndexes) {
// model->removeRow(index.row());
// }
// // 将删除的项插入到目标位置
// for (const QModelIndex &index : selectedIndexes) {
// // 插入项,插入的位置为拖动的目标索引
// model->insertRow(dropIndex.row());
// model->setData(model->index(dropIndex.row(), 0), model->data(index));
// }
// }
// }
private:
QPoint startPos;
bool IsDraging = false;
int theHighlightedRow = -2;
int oldHighlightedRow = -2;
int theDragRow = -1;
int theInsertRow = -1;
};
#endif // CAUTOLISTVIEW_H

Binary file not shown.

View File

@ -0,0 +1,76 @@
#include "CBoxDelegate.h"
#include "CBoxListView.h"
#include "CBoxTreeWidget.h"
CListDelegate::CListDelegate(QObject *parent)
: m_pView(dynamic_cast<CBoxListView*>(parent))
{
}
QSize CListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(m_pView)
{
if(m_pView->model()->data(index, Qt::DisplayRole) != QVariant())
{
return QSize(m_pView->getMaxTextWidth(), QStyledItemDelegate::sizeHint(option, index).height());
}
}
return QStyledItemDelegate::sizeHint(option, index);
}
CTreeDelegate::CTreeDelegate(QObject *parent)
: m_pView(dynamic_cast<QTreeWidget*>(parent))
{
}
void CTreeDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyledItemDelegate::paint(painter, option, index);
bool bExpanded = m_pView->isExpanded(index);
bExpanded ? drawRightArrow(painter, option) : drawDownArrow(painter, option);
}
void CTreeDelegate::drawDownArrow(QPainter *painter, const QStyleOptionViewItem &option) const
{
painter->save();
QPen pen;
pen.setColor(QColor(0,0,0));
pen.setWidthF(1.5);
painter->setPen(pen);
QStyleOptionViewItem viewOption(option);
qreal x = viewOption.rect.left() + viewOption.rect.width() - 15;
qreal y = viewOption.rect.top() + viewOption.rect.height() / 2 + 2;
QPointF p1(x - 5, y - 5);
QPointF p2(x, y);
QPointF p3(x + 5, y - 5);
painter->drawLine(p1, p2);
painter->drawLine(p2, p3);
painter->restore();
}
void CTreeDelegate::drawRightArrow(QPainter *painter, const QStyleOptionViewItem &option) const
{
painter->save();
QPen pen;
pen.setColor(QColor(0,0,0));
pen.setWidthF(1.5);
painter->setPen(pen);
QStyleOptionViewItem viewOption(option);
qreal x = viewOption.rect.left() + viewOption.rect.width() - 10;
qreal y = viewOption.rect.top() + viewOption.rect.height() / 2;
QPointF p1(x - 5, y - 5);
QPointF p2(x, y);
QPointF p3(x - 5, y + 5);
painter->drawLine(p1, p2);
painter->drawLine(p2, p3);
painter->restore();
}

View File

@ -0,0 +1,38 @@
#ifndef CBOXDELEGATE_H
#define CBOXDELEGATE_H
#include <QStyledItemDelegate>
#include "Export.h"
class CBoxListView;
class DLL_CLASS CListDelegate : public QStyledItemDelegate
{
public:
CListDelegate(QObject *parent = Q_NULLPTR);
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
private:
CBoxListView * m_pView;
};
class QTreeWidget;
class CTreeDelegate : public QStyledItemDelegate
{
public:
CTreeDelegate(QObject *parent = Q_NULLPTR);
void paint(QPainter *painter,
const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void drawDownArrow(QPainter *painter,
const QStyleOptionViewItem &option) const;
void drawRightArrow(QPainter *painter,
const QStyleOptionViewItem &option) const;
private:
QTreeWidget * m_pView;
};
#endif // CBOXDELEGATE_H

View File

@ -0,0 +1,102 @@
#include "CBoxListModel.h"
CBoxListModel::CBoxListModel(QObject *parent)
: QAbstractListModel(parent)
{
}
CBoxListModel::~CBoxListModel()
{
m_items.clear();
}
bool CBoxListModel::isExist(const QString &name)
{
for(int nIndex(0); nIndex < m_items.size(); ++nIndex)
{
if(m_items[nIndex]->name == name)
{
return true;
}
}
return false;
}
DrawObjDatabaseRecord *CBoxListModel::record(const QModelIndex &index) const
{
const int row = index.row();
if (row < 0 || row >= m_items.size())
return Q_NULLPTR;
return m_items.at(row);
}
QVariant CBoxListModel::data(const QModelIndex &index, int role) const
{
const int row = index.row();
if (row < 0 || row >= m_items.size())
return QVariant();
const DrawObjDatabaseRecord *item = m_items.at(row);
switch (role) {
case Qt::DisplayRole:
{
if(item->icon && !item->icon->isNull())
{
return QVariant();
}
return QVariant(item->name);
}
case Qt::DecorationRole:
return QVariant(*(item->icon));
case Qt::WhatsThisRole:
return QVariant(item->toolType);
case Qt::ToolTipRole:
return QVariant(item->name);
case Qt::UserRole:
return QVariant(item->typeSub);
case Qt::UserRole + 1:
return QVariant(item->mark);
case Qt::UserRole + 2:
return QVariant(item->strategy);
case Qt::UserRole + 3:
return QVariant(item->name);
}
return QVariant();
}
int CBoxListModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_items.size();
}
Qt::ItemFlags CBoxListModel::flags(const QModelIndex &index) const
{
Q_UNUSED(index)
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
}
bool CBoxListModel::removeRows(int row, int count, const QModelIndex &parent)
{
if (row < 0 || count < 1)
return false;
const int size = m_items.size();
const int last = row + count - 1;
if (row >= size || last >= size)
return false;
beginRemoveRows(parent, row, last);
for (int r = last; r >= row; r--)
m_items.removeAt(r);
endRemoveRows();
return true;
}
void CBoxListModel::addWidget(DrawObjDatabaseRecord *record)
{
const int row = m_items.size();
beginInsertRows(QModelIndex(), row, row);
m_items.push_back(record);
endInsertRows();
}

View File

@ -0,0 +1,28 @@
#ifndef CBOXLISTMODEL_H
#define CBOXLISTMODEL_H
#include "Export.h"
#include "QAbstractListModel"
#include "CDrawObjDatabase.h"
class DLL_CLASS CBoxListModel : public QAbstractListModel
{
Q_OBJECT
public:
CBoxListModel(QObject *parent = Q_NULLPTR);
~CBoxListModel();
bool isExist(const QString &name);
DrawObjDatabaseRecord* record(const QModelIndex &index) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
Qt::ItemFlags flags (const QModelIndex & index ) const override;
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
void addWidget(DrawObjDatabaseRecord *record);
private:
QList<DrawObjDatabaseRecord*> m_items;
};
#endif // CBOXLISTMODEL_H

View File

@ -0,0 +1,122 @@
#include "CBoxListView.h"
#include "CBoxListModel.h"
#include "CBoxDelegate.h"
CBoxListView::CBoxListView(QWidget *parent)
: QListView(parent),
m_pModel(new CBoxListModel(this)),
m_nMaxTextWidth(0)
{
setFocusPolicy(Qt::NoFocus);
setFrameShape(QFrame::NoFrame);
setIconSize(QSize(30, 30));
setSpacing(1);
setTextElideMode(Qt::ElideMiddle);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setResizeMode(QListView::Adjust);
setDragEnabled(true);
setDragDropMode(QAbstractItemView::DragOnly);
QFont font = qApp->font();
font.setPointSize(font.pointSize() + 1);
setFont(font);
//setUniformItemSizes(true);
setModel(m_pModel);
setItemDelegate(new CListDelegate(this));
connect(this, &CBoxListView::pressed, this, &CBoxListView::slotItemPressed);
}
bool CBoxListView::isExist(const QString &name)
{
return m_pModel->isExist(name);
}
DrawObjDatabaseRecord *CBoxListView::selectedRecord()
{
QModelIndex curIndex = currentIndex();
if( !curIndex.isValid() )
{
return NULL;
}
return m_pModel->record(curIndex);
}
void CBoxListView::addWidget(DrawObjDatabaseRecord *record)
{
if(record->icon && record->icon->isNull()){
setMaxTextWidth(record->name);
}
m_pModel->addWidget(record);
}
void CBoxListView::removeSelectedWidget()
{
QModelIndex curIndex = currentIndex();
if( !curIndex.isValid() )
{
return;
}
m_pModel->removeRows(curIndex.row(), 1);
}
int CBoxListView::getMaxTextWidth()
{
return m_nMaxTextWidth;
}
void CBoxListView::setMaxTextWidth(const QString &text)
{
QFontMetrics font = this->fontMetrics();
int width = font.boundingRect(text+"AA").width();
if(width > m_nMaxTextWidth)
{
m_nMaxTextWidth = width;
}
}
bool CBoxListView::filter(const QString &text)
{
bool isHidden = true;
DrawObjDatabaseRecord * record;
for(int nIndex(0); nIndex<m_pModel->rowCount(); ++nIndex)
{
record = m_pModel->record(m_pModel->index(nIndex, 0));
if(text.isEmpty() || (record && record->name.contains(text)))
{
setRowHidden(nIndex, false);
isHidden = false;
}
else
{
setRowHidden(nIndex, true);
}
}
return isHidden;
}
void CBoxListView::dragMoveEvent(QDragMoveEvent *e)
{
e->setAccepted(false);
}
void CBoxListView::startDrag(Qt::DropActions supportedActions)
{
Q_UNUSED(supportedActions)
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData();
mimeData->setText("toolBox");
drag->setMimeData(mimeData);
drag->exec(Qt::CopyAction);
}
void CBoxListView::slotItemPressed(const QModelIndex &index)
{
emit itemSelected();
CBoxListModel * model = dynamic_cast<CBoxListModel *>(this->model());
DrawObjDatabaseRecord * record = model->record(index);
if(record)
{
emit itemPressed(record);
}
}

View File

@ -0,0 +1,44 @@
#ifndef CBOXLISTVIEW_H
#define CBOXLISTVIEW_H
#include "Export.h"
#include <QListView>
#include "CDrawObjDatabase.h"
class CBoxListModel;
class DLL_CLASS CBoxListView : public QListView
{
Q_OBJECT
public:
CBoxListView(QWidget *parent = Q_NULLPTR);
using QListView::contentsSize;
bool isExist(const QString &name);
DrawObjDatabaseRecord * selectedRecord();
void addWidget(DrawObjDatabaseRecord *record);
void removeSelectedWidget();
int getMaxTextWidth();
void setMaxTextWidth(const QString &text);
bool filter(const QString &text);
signals:
void itemSelected();
void itemPressed(const DrawObjDatabaseRecord *record);
protected:
void dragMoveEvent(QDragMoveEvent *e);
void startDrag(Qt::DropActions supportedActions);
private slots:
void slotItemPressed(const QModelIndex &index);
private:
CBoxListModel * m_pModel;
int m_nMaxTextWidth;
};
#endif // CBOXLISTVIEW_H

View File

@ -0,0 +1,190 @@
#include <QHeaderView>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLineEdit>
#include "CBoxTreeWidget.h"
#include "CBoxListView.h"
#include "CBoxDelegate.h"
CBoxTreeWidget::CBoxTreeWidget(QWidget *parent)
: QTreeWidget(parent)
{
setFocusPolicy(Qt::NoFocus);
setRootIsDecorated(false);
setIndentation(0);
setColumnCount(1);
setTextElideMode(Qt::ElideMiddle);
setVerticalScrollMode(QTreeView::ScrollPerPixel);
setStyleSheet("QTreeView::item{height:26px;}");
QFont font = qApp->font();
font.setPointSize(font.pointSize() + 1);
setFont(font);
QPalette palette = this->palette();
palette.setColor(QPalette::Shadow, Qt::blue);
setIconSize(QSize(30, 30));
setPalette(palette);
setAutoFillBackground(true);
setItemDelegate(new CTreeDelegate(this));
initHeaderView();
}
bool CBoxTreeWidget::isExist(const QString &name)
{
for(int nIndex = 0; nIndex < topLevelItemCount(); ++nIndex)
{
QTreeWidgetItem * item = topLevelItem(nIndex);
if(item->childCount() <= 0)
{
continue;
}
CBoxListView *listView = static_cast<CBoxListView*>(itemWidget(item->child(0), 0));
if(listView == NULL)
{
continue;
}
if(listView->isExist(name))
{
return true;
}
}
return false;
}
QString CBoxTreeWidget::currentName()
{
QTreeWidgetItem * item = currentItem();
if(item)
{
CBoxListView *listWidget = static_cast<CBoxListView*>(itemWidget(item, 0));
if(listWidget)
{
return listWidget->model()->data(listWidget->currentIndex(), Qt::UserRole + 3).toString();
}
else
{
return item->data(0, Qt::UserRole + 3).toString();
}
}
return QString();
}
CBoxListView *CBoxTreeWidget::addListView(QTreeWidgetItem *parent, bool iconMode)
{
QTreeWidgetItem *embed_item = new QTreeWidgetItem(parent);
CBoxListView *listView = new CBoxListView(this);
listView->setViewMode(iconMode ? QListView::IconMode : QListView::ListMode);
connect(listView, &CBoxListView::itemSelected, this, &CBoxTreeWidget::slotItemWidgetSelected);
setItemWidget(embed_item, 0, listView);
m_itemWidgetMap[listView] = embed_item;
return listView;
}
CBoxListView *CBoxTreeWidget::getListView(QTreeWidgetItem *parent)
{
if(parent == NULL)
{
return NULL;
}
QMap<QWidget *, QTreeWidgetItem *>::const_iterator iter = m_itemWidgetMap.constBegin();
for( ; iter != m_itemWidgetMap.constEnd(); ++iter)
{
if(iter.value() == parent)
{
return dynamic_cast<CBoxListView *>(iter.key());
}
}
return NULL;
}
void CBoxTreeWidget::adjustSubListSize(QTreeWidgetItem *cat_item)
{
QTreeWidgetItem *embedItem = cat_item->child(0);
if (embedItem == 0)
return;
CBoxListView *listWidget = static_cast<CBoxListView*>(itemWidget(embedItem, 0));
listWidget->setFixedWidth(header()->width());
listWidget->doItemsLayout();
const int height = qMax(listWidget->contentsSize().height() ,1);
listWidget->setFixedHeight(height);
embedItem->setSizeHint(0, QSize(-1, height - 1));
}
void CBoxTreeWidget::resizeEvent(QResizeEvent *e)
{
QTreeWidget::resizeEvent(e);
if (const int numTopLevels = topLevelItemCount()) {
for (int i = numTopLevels - 1; i >= 0; --i)
adjustSubListSize(topLevelItem(i));
}
}
void CBoxTreeWidget::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
QTreeWidgetItem * item = itemAt(event->pos());
if(item){
item->isExpanded() ? collapseItem(item) : expandItem(item);
}
}
return QTreeWidget::mousePressEvent(event);
}
void CBoxTreeWidget::filter(const QString &text)
{
for(int nIndex(0); nIndex < topLevelItemCount(); ++nIndex)
{
QTreeWidgetItem * top = topLevelItem(nIndex);
if(!top->child(0))
{
top->setHidden(true);
continue;
}
CBoxListView *listWidget = static_cast<CBoxListView*>(itemWidget(top->child(0), 0));
if(listWidget)
{
top->setHidden(listWidget->filter(text));
}
else
{
top->setHidden(true);
}
adjustSubListSize(top);
}
text.isEmpty() ? collapseAll() : expandAll();
}
void CBoxTreeWidget::slotItemWidgetSelected()
{
QWidget * widget = dynamic_cast<QWidget *>(sender());
QMap<QWidget *, QTreeWidgetItem *>::const_iterator iter = m_itemWidgetMap.find(widget);
if(iter != m_itemWidgetMap.constEnd())
{
clearSelection();
setCurrentItem(iter.value());
iter.value()->parent()->setSelected(true);
}
}
void CBoxTreeWidget::initHeaderView()
{
QHBoxLayout * hLayout = new QHBoxLayout;
QLineEdit * edit = new QLineEdit(this);
edit->setFrame(false);
edit->setPlaceholderText(tr("搜索..."));
edit->setFixedHeight(21);
hLayout->setContentsMargins(3,0,0,0);
hLayout->addWidget(edit);
QVBoxLayout * vLayout = new QVBoxLayout;
vLayout->addLayout(hLayout);
QFrame * line = new QFrame(this);
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
vLayout->addWidget(line);
vLayout->setMargin(1);
vLayout->setSpacing(1);
header()->setLayout(vLayout);
connect(edit, SIGNAL(textChanged(QString)), this, SLOT(filter(QString)));
}

View File

@ -0,0 +1,36 @@
#ifndef CBOXTREEWIDGET_H
#define CBOXTREEWIDGET_H
#include "Export.h"
#include "QTreeWidget"
class CBoxListView;
class DLL_CLASS CBoxTreeWidget : public QTreeWidget
{
Q_OBJECT
public:
CBoxTreeWidget(QWidget *parent = Q_NULLPTR);
bool isExist(const QString &name);
QString currentName();
CBoxListView *addListView(QTreeWidgetItem *parent, bool iconMode);
CBoxListView *getListView(QTreeWidgetItem *parent);
void adjustSubListSize(QTreeWidgetItem *cat_item);
protected:
void resizeEvent(QResizeEvent *e);
void mousePressEvent(QMouseEvent *event);
private slots:
void filter(const QString &text);
private:
void slotItemWidgetSelected();
void initHeaderView();
private:
QMap<QWidget *, QTreeWidgetItem *> m_itemWidgetMap;
};
#endif // CBOXTREEWIDGET_H

View File

@ -0,0 +1,422 @@
#include <QHash>
#include <QtXml>
#include "../../include/CXMLStream.h"
#include "../../include/CStream.h"
#include "CDrawObjDatabase.h"
#include "../../include/public/pub_utility_api/FileUtil.h"
const int dbsize = 500;
const int dbcustom = 200;
const int dbdictsize = 211;
static DrawObjDatabaseRecord *db[dbsize];
static QHash<QString, int> className2Id;
static int dbcount = 0;
static int dbcustomcount = 200;
static QStringList *wGroups;
static QStringList *invisibleGroups;
static bool was_in_setup = false;
DrawObjDatabaseRecord::DrawObjDatabaseRecord()
{
toolType = 0;
icon = 0;
nameCounter = 0;
isCommon = false;
}
DrawObjDatabaseRecord::~DrawObjDatabaseRecord()
{
delete icon;
icon = NULL;
}
DrawObjDatabase::DrawObjDatabase()
{
}
void DrawObjDatabase::setupDataBase(int id)
{
was_in_setup = true;
// Q_UNUSED(id)
if (dbcount && (id != -2))
{
return;
}
if (id == -2)
{
dbcount = 0;
}
wGroups = new QStringList;
invisibleGroups = new QStringList;
invisibleGroups->append("Forms");
invisibleGroups->append("Temp");
DrawObjDatabaseRecord *r = 0;
QString iconbuf;
QDomElement rootItem, groupItem, bodyItem, objItem;
QDomNode groupNode, objNode;
QString sysPath, fileName;
CBaseInstance()->getPathName(CBase::PATH_TYPE_SYS, sysPath);
fileName = sysPath + "toolbox.xml";
CGStream iofs;
iofs.SetMode(CGStream::xmlfile);
CXMLStream &xmls = iofs.m_XMLStream;
int ret = xmls.OPEN(fileName.toLocal8Bit().data(), std::ios::in, 1);
if (ret < 0)
{
//qDebug("open fileName %s error", fileName.c_str());
return;
}
QString name, stragey, mark;
QString groupName, iconSetName, subType, tipSetName;
int type, isCommon;
rootItem = xmls.GetChild("graph");
bodyItem = xmls.GetChild("body");
//groupItem = xmls.GetChild("group",&bodyItem);
groupNode = bodyItem.firstChild();
while (!groupNode.isNull())
{
groupItem = groupNode.toElement();
groupName = groupItem.tagName();
objNode = groupNode.firstChild();
if(objNode.isNull())
{
widgetGroup(groupName);
}
else
{
while (!objNode.isNull())
{
objItem = objNode.toElement();
name = objItem.tagName();
stragey = objItem.attribute("strategy");
mark = objItem.attribute("mark");
type = objItem.attribute("type").toInt();
subType = objItem.attribute("sub_type");
iconSetName = objItem.attribute("icon");
CBaseInstance()->getFilePathName(CBase::PATH_TYPE_ICONSET, iconSetName, iconbuf);
isCommon = objItem.attribute("common").toInt();
objNode = objNode.nextSibling();
r = new DrawObjDatabaseRecord;
if (type > 100)
{
tipSetName = name + ".png";
}
else
{
r->toolTip.clear();
}
r->iconSet = iconbuf;
r->name = name;
r->group = widgetGroup(groupName);
r->toolType = type;
r->typeSub = subType;
r->isCommon = isCommon;
r->strategy = stragey;
r->mark = mark;
append(r);
}
}
groupNode = groupNode.nextSibling();
}
xmls.CLOSE();
}
int DrawObjDatabase::count()
{
setupDataBase(-1);
return dbcount;
}
int DrawObjDatabase::startCustom()
{
setupDataBase(-1);
return dbcustom;
}
QIcon DrawObjDatabase::iconSet(int id)
{
setupDataBase(id);
DrawObjDatabaseRecord *r = at(id);
if (!r)
{
return QIcon();
}
if (!r->icon)
{
if (r->iconSet.isEmpty())
{
return QIcon();
}
QPixmap pix = QPixmap(QObject::tr(r->iconSet.toLocal8Bit().data()));
// QSize size = pix.size();
// pix = pix.scaled(size*5);
// size = pix.size();
if (pix.isNull())
{
pix = QPixmap(QObject::tr(r->iconSet.toLocal8Bit().data()));
}
r->icon = new QIcon(pix);
}
return *r->icon;
}
QString DrawObjDatabase::className(int id)
{
setupDataBase(id);
DrawObjDatabaseRecord *r = at(id);
if (!r)
{
return QString();
}
return r->name;
}
int DrawObjDatabase::curToolType(int id)
{
setupDataBase(id);
DrawObjDatabaseRecord *r = at(id);
if (!r)
{
return 0;
}
return r->toolType;
}
QString DrawObjDatabase::curToolTypeN(int id)
{
setupDataBase(id);
DrawObjDatabaseRecord *r = at(id);
if (!r)
{
return 0;
}
return r->typeSub;
}
QString DrawObjDatabase::mark(int id)
{
setupDataBase(id);
DrawObjDatabaseRecord *r = at(id);
if (!r)
{
return 0;
}
return r->mark;
}
QString DrawObjDatabase::strategy(int id)
{
setupDataBase(id);
DrawObjDatabaseRecord *r = at(id);
if (!r)
{
return 0;
}
return r->strategy;
}
QString DrawObjDatabase::group(int id)
{
setupDataBase(id);
DrawObjDatabaseRecord *r = at(id);
if (!r)
{
return QString();
}
return r->group;
}
QString DrawObjDatabase::toolTip(int id)
{
setupDataBase(id);
DrawObjDatabaseRecord *r = at(id);
if (!r)
{
return QString();
}
return r->toolTip;
}
QString DrawObjDatabase::whatsThis(int id)
{
setupDataBase(id);
DrawObjDatabaseRecord *r = at(id);
if (!r)
{
return QString();
}
return r->whatsThis;
}
QString DrawObjDatabase::includeFile(int id)
{
setupDataBase(id);
DrawObjDatabaseRecord *r = at(id);
if (!r)
{
return QString();
}
if (r->includeFile.isNull())
{
return r->name.toLower() + ".h";
}
return r->includeFile;
}
bool DrawObjDatabase::isCommon(int id)
{
setupDataBase(id);
DrawObjDatabaseRecord *r = at(id);
if (!r)
{
return false;
}
return r->isCommon;
}
int DrawObjDatabase::idFromClassName(const QString &name)
{
setupDataBase(-1);
if (name.isEmpty())
{
return 0;
}
QHash<QString, int>::iterator it = className2Id.find(name);
if (it != className2Id.end())
{
return it.value();
}
if (name == "FormWindow")
{
return idFromClassName("QLayoutWidget");
}
return -1;
}
bool DrawObjDatabase::hasWidget(const QString &name)
{
return className2Id.find(name) != className2Id.end();
}
DrawObjDatabaseRecord *DrawObjDatabase::at(int index)
{
if (index < 0)
{
return 0;
}
if (index >= dbcustom && index < dbcustomcount)
{
return db[index];
}
if (index < dbcount)
{
return db[index];
}
return 0;
}
void DrawObjDatabase::insert(int index, DrawObjDatabaseRecord *r)
{
if (index < 0 || index >= dbsize)
{
return;
}
db[index] = r;
className2Id.insert(r->name, index);
if (index < dbcustom)
{
dbcount = qMax(dbcount, index);
}
}
void DrawObjDatabase::append(DrawObjDatabaseRecord *r)
{
if (!was_in_setup)
{
setupDataBase(-1);
}
insert(dbcount++, r);
}
QString DrawObjDatabase::widgetGroup(const QString &g)
{
if (!wGroups->contains(g))
{
wGroups->append(g);
}
return g;
}
bool DrawObjDatabase::isGroupEmpty(const QString &grp)
{
DrawObjDatabaseRecord *r = 0;
for (int i = 0; i < dbcount; ++i)
{
if (!(r = db[ i ]))
{
continue;
}
if (r->group == grp)
{
return false;
}
}
return true;
}
QString DrawObjDatabase::widgetGroup(int i)
{
setupDataBase(-1);
if (i >= 0 && i < (int)wGroups->count())
{
return wGroups->at(i);
}
return QString();
}
int DrawObjDatabase::numWidgetGroups()
{
setupDataBase(-1);
return wGroups->count();
}
bool DrawObjDatabase::isGroupVisible(const QString &g)
{
setupDataBase(-1);
//return invisibleGroups->find(g) == -1;
return !invisibleGroups->contains(g);
}
int DrawObjDatabase::addCustomWidget(DrawObjDatabaseRecord *r)
{
insert(dbcustomcount++, r);
return dbcustomcount - 1;
}
bool DrawObjDatabase::isCustomWidget(int id)
{
if (id >= dbcustom && id < dbcustomcount)
{
return true;
}
return false;
}

View File

@ -0,0 +1,60 @@

#ifndef CDROWOBJDATABASE_H
#define CDROWOBJDATABASE_H
#include <QString>
#include <QIcon>
#include "Export.h"
#include "../../include/CBase.h"
struct DLL_CLASS DrawObjDatabaseRecord
{
DrawObjDatabaseRecord();
~DrawObjDatabaseRecord();
QString iconSet, name, group, typeSub, toolTip, whatsThis, includeFile;
QString strategy;
QString mark;
uint isCommon : 1;
QIcon *icon;
int nameCounter;
int toolType;
};
class DLL_CLASS DrawObjDatabase
{
public:
DrawObjDatabase();
static void setupDataBase(int id);
static int count();
static int startCustom();
static QIcon iconSet(int id);
static QString className(int id);
static int curToolType(int id);
static QString curToolTypeN(int id);
static QString group(int id);
static QString mark(int id);
static QString strategy(int id);
static QString toolTip(int id);
static QString whatsThis(int id);
static QString includeFile(int id);
static bool isCommon(int id);
static int idFromClassName(const QString &name);
static DrawObjDatabaseRecord *at(int inde);
static void insert(int index, DrawObjDatabaseRecord *r);
static void append(DrawObjDatabaseRecord *r);
static QString widgetGroup(const QString &g);
static QString widgetGroup(int i);
static int numWidgetGroups();
static bool isGroupVisible(const QString &g);
static bool isGroupEmpty(const QString &grp);
static int addCustomWidget(DrawObjDatabaseRecord *r);
static bool isCustomWidget(int id);
static bool isCustomPluginWidget(int id);
static bool hasWidget(const QString &name);
};
#endif

View File

@ -0,0 +1,36 @@
# 原文件本来存放在hmi项目下当时由于批量生成需要复用到hmi的工具箱树结构就直接将其提了出来单独做成了dll
QT += core gui widgets sql xml
TARGET = ToolBoxTree
TEMPLATE = lib
INCLUDEPATH += $$PWD
HEADERS += \
CBoxDelegate.h \
CBoxListModel.h \
CBoxListView.h \
CBoxTreeWidget.h \
CDrawObjDatabase.h
SOURCES += \
CBoxDelegate.cpp \
CBoxListModel.cpp \
CBoxListView.cpp \
CBoxTreeWidget.cpp \
CDrawObjDatabase.cpp
DEFINES += DLL_OUT
LIBS += -lpub_widget
LIBS += -lGraphPub -lGraphShape
LIBS += -llog4cplus -lpub_logger_api -lpub_utility_api -ldb_base_api -ldb_api_ex -lprotobuf -lpub_sysinfo_api
COMMON_PRI=$$PWD/../../../common.pri
exists($$COMMON_PRI) {
include($$COMMON_PRI)
}else {
error("FATAL error: can not find common.pri")
}

View File

@ -0,0 +1,175 @@
#include <QDir>
#include <QMenu>
#include <QLineEdit>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QHeaderView>
#include "../../include/CBase.h"
#include "CGraphFileTree.h"
CGraphFileTree::CGraphFileTree(QWidget *parent)
: QTreeWidget(parent)
{
initStyle();
m_strBasePath = CBaseInstance()->getSysHome() + QDir::separator() + QString("data") + QDir::separator() + QString("pic");
QHBoxLayout * hLayout = new QHBoxLayout;
QLineEdit * edit = new QLineEdit(this);
edit->setFrame(false);
edit->setPlaceholderText(tr("搜索..."));
edit->setFixedHeight(21);
hLayout->setContentsMargins(3,0,0,0);
hLayout->addWidget(edit);
QVBoxLayout * vLayout = new QVBoxLayout;
vLayout->addLayout(hLayout);
QFrame * line = new QFrame(this);
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
vLayout->addWidget(line);
vLayout->setMargin(1);
vLayout->setSpacing(1);
header()->setLayout(vLayout);
connect(edit, SIGNAL(textChanged(QString)), this, SLOT(filter(QString)));
reload();
}
void CGraphFileTree::reload(const QString &path)
{
if(m_strBasePath != path)
{
m_strBasePath = path;
reload();
}
}
void CGraphFileTree::mousePressEvent(QMouseEvent *event)
{
QTreeWidgetItem * pItem = static_cast<QTreeWidgetItem*>(indexAt(event->pos()).internalPointer());
if(pItem)
{
if(pItem->type() == FileType)
{
emit sigFileClicked(pItem->data(0, Qt::UserRole).toString());
}
}
return QTreeWidget::mousePressEvent(event);
}
void CGraphFileTree::contextMenuEvent(QContextMenuEvent *event)
{
QMenu menu;
menu.addAction(tr("刷新"), this, SLOT(reload()));
menu.exec(event->globalPos());
}
void CGraphFileTree::reload()
{
clear();
buildTree(NULL, m_strBasePath);
}
void CGraphFileTree::filter(const QString &text)
{
for(int nIndex(0); nIndex<topLevelItemCount(); ++nIndex)
{
filter(topLevelItem(nIndex), text);
}
if(text.isEmpty())
{
collapseAll();
}
else
{
expandAll();
}
}
bool CGraphFileTree::filter(QTreeWidgetItem *item, const QString &text)
{
bool isHidden = true;
QString temp = item->text(0);
if(text.isEmpty() || temp.contains(text))
{
setChildShow(item);
isHidden = false;
}
else
{
if(item->childCount() > 0)
{
for(int nIndex(0); nIndex<item->childCount(); ++nIndex)
{
if(!filter(item->child(nIndex), text))
{
isHidden = false;
}
}
}
else
{
isHidden = true;
}
}
setItemHidden(item, isHidden);
return isHidden;
}
void CGraphFileTree::setChildShow(QTreeWidgetItem *item)
{
int childCount = item->childCount();
for(int nIndex(0); nIndex < childCount; ++nIndex)
{
setItemHidden(item->child(nIndex), false);
setChildShow(item->child(nIndex));
}
}
void CGraphFileTree::initStyle()
{
QFont font = qApp->font();
font.setPointSize(font.pointSize() + 1);
setFont(font);
QPalette palette = this->palette();
palette.setColor(QPalette::Shadow, Qt::blue);
setIconSize(QSize(30, 30));
setPalette(palette);
setAutoFillBackground(true);
setStyleSheet("QTreeView::item{height:26px;}");
}
void CGraphFileTree::buildTree(QTreeWidgetItem * parent, QString basePath)
{
QDir dir(basePath);
QFileInfoList folderList = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
foreach (QFileInfo folder, folderList) {
QTreeWidgetItem * item = new QTreeWidgetItem(FolderType);
item->setText(0, folder.baseName());
if(parent == NULL)
{
addTopLevelItem(item);
}
else
{
parent->addChild(item);
}
buildTree(item, folder.absoluteFilePath());
}
QFileInfoList fileList = dir.entryInfoList(QDir::Files | QDir::NoSymLinks);
foreach (QFileInfo file, fileList) {
QTreeWidgetItem * item = new QTreeWidgetItem(FileType);
item->setText(0, file.baseName() + "." + file.suffix());
item->setData(0, Qt::UserRole, file.filePath());
if(parent == NULL)
{
addTopLevelItem(item);
}
else
{
parent->addChild(item);
}
}
}

View File

@ -0,0 +1,35 @@
#ifndef CGRAPHFILETREE_H
#define CGRAPHFILETREE_H
#include <QTreeWidget>
class CGraphFileTree : public QTreeWidget
{
Q_OBJECT
enum NodeType{ FolderType = QTreeWidgetItem::UserType + 1, FileType };
public:
CGraphFileTree(QWidget *parent = Q_NULLPTR);
void reload(const QString& path);
signals:
void sigFileClicked(const QString& path);
protected:
void mousePressEvent(QMouseEvent *event);
void contextMenuEvent(QContextMenuEvent *event);
private slots:
void reload();
void filter(const QString &text);
private:
void initStyle();
void buildTree(QTreeWidgetItem *parent, QString basePath);
bool filter(QTreeWidgetItem *item, const QString &text);
void setChildShow(QTreeWidgetItem *item);
private:
QString m_strBasePath;
};
#endif // CGRAPHFILETREE_H

View File

@ -0,0 +1,39 @@
#include "CComboxDelegate.h"
#include <QDesktopWidget>
#include <QApplication>
#include <QComboBox>
CComboxDelegate::CComboxDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
QWidget *CComboxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(option)
Q_UNUSED(index)
QComboBox * box = new QComboBox(parent);
QDesktopWidget *dw = QApplication::desktop();
int count = dw->screenCount();
for(int n = 0; n < count; n++)
{
box->addItem(QString::number(n));
}
return box;
}
void CComboxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
QComboBox * box = static_cast<QComboBox*>(editor);
box->setCurrentIndex(box->findText(index.data(Qt::DisplayRole).toString()));
}
void CComboxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QComboBox * box = static_cast<QComboBox*>(editor);
if(model->data(index, Qt::DisplayRole) != box->currentText())
{
model->setData(index, box->currentText(), Qt::DisplayRole);
}
}

View File

@ -0,0 +1,21 @@
#ifndef CCOMBOXDELEGATE_H
#define CCOMBOXDELEGATE_H
#include <QObject>
#include <QStyledItemDelegate>
class CComboxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
CComboxDelegate(QObject *parent = Q_NULLPTR);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const override;
};
#endif // CCOMBOXDELEGATE_H

View File

@ -0,0 +1,76 @@
#include "CBoxDelegate.h"
#include "CBoxListView.h"
#include "CBoxTreeWidget.h"
CListDelegate::CListDelegate(QObject *parent)
: m_pView(dynamic_cast<CBoxListView*>(parent))
{
}
QSize CListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(m_pView)
{
if(m_pView->model()->data(index, Qt::DisplayRole) != QVariant())
{
return QSize(m_pView->getMaxTextWidth(), QStyledItemDelegate::sizeHint(option, index).height());
}
}
return QStyledItemDelegate::sizeHint(option, index);
}
CTreeDelegate::CTreeDelegate(QObject *parent)
: m_pView(dynamic_cast<QTreeWidget*>(parent))
{
}
void CTreeDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyledItemDelegate::paint(painter, option, index);
bool bExpanded = m_pView->isExpanded(index);
bExpanded ? drawRightArrow(painter, option) : drawDownArrow(painter, option);
}
void CTreeDelegate::drawDownArrow(QPainter *painter, const QStyleOptionViewItem &option) const
{
painter->save();
QPen pen;
pen.setColor(QColor(0,0,0));
pen.setWidthF(1.5);
painter->setPen(pen);
QStyleOptionViewItem viewOption(option);
qreal x = viewOption.rect.left() + viewOption.rect.width() - 15;
qreal y = viewOption.rect.top() + viewOption.rect.height() / 2 + 2;
QPointF p1(x - 5, y - 5);
QPointF p2(x, y);
QPointF p3(x + 5, y - 5);
painter->drawLine(p1, p2);
painter->drawLine(p2, p3);
painter->restore();
}
void CTreeDelegate::drawRightArrow(QPainter *painter, const QStyleOptionViewItem &option) const
{
painter->save();
QPen pen;
pen.setColor(QColor(0,0,0));
pen.setWidthF(1.5);
painter->setPen(pen);
QStyleOptionViewItem viewOption(option);
qreal x = viewOption.rect.left() + viewOption.rect.width() - 10;
qreal y = viewOption.rect.top() + viewOption.rect.height() / 2;
QPointF p1(x - 5, y - 5);
QPointF p2(x, y);
QPointF p3(x - 5, y + 5);
painter->drawLine(p1, p2);
painter->drawLine(p2, p3);
painter->restore();
}

View File

@ -0,0 +1,37 @@
#ifndef CBOXDELEGATE_H
#define CBOXDELEGATE_H
#include <QStyledItemDelegate>
class CBoxListView;
class CListDelegate : public QStyledItemDelegate
{
public:
CListDelegate(QObject *parent = Q_NULLPTR);
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
private:
CBoxListView * m_pView;
};
class QTreeWidget;
class CTreeDelegate : public QStyledItemDelegate
{
public:
CTreeDelegate(QObject *parent = Q_NULLPTR);
void paint(QPainter *painter,
const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void drawDownArrow(QPainter *painter,
const QStyleOptionViewItem &option) const;
void drawRightArrow(QPainter *painter,
const QStyleOptionViewItem &option) const;
private:
QTreeWidget * m_pView;
};
#endif // CBOXDELEGATE_H

View File

@ -0,0 +1,102 @@
#include "CBoxListModel.h"
CBoxListModel::CBoxListModel(QObject *parent)
: QAbstractListModel(parent)
{
}
CBoxListModel::~CBoxListModel()
{
m_items.clear();
}
bool CBoxListModel::isExist(const QString &name)
{
for(int nIndex(0); nIndex < m_items.size(); ++nIndex)
{
if(m_items[nIndex]->name == name)
{
return true;
}
}
return false;
}
DrawObjDatabaseRecord *CBoxListModel::record(const QModelIndex &index) const
{
const int row = index.row();
if (row < 0 || row >= m_items.size())
return Q_NULLPTR;
return m_items.at(row);
}
QVariant CBoxListModel::data(const QModelIndex &index, int role) const
{
const int row = index.row();
if (row < 0 || row >= m_items.size())
return QVariant();
const DrawObjDatabaseRecord *item = m_items.at(row);
switch (role) {
case Qt::DisplayRole:
{
if(item->icon && !item->icon->isNull())
{
return QVariant();
}
return QVariant(item->name);
}
case Qt::DecorationRole:
return QVariant(*(item->icon));
case Qt::WhatsThisRole:
return QVariant(item->toolType);
case Qt::ToolTipRole:
return QVariant(item->name);
case Qt::UserRole:
return QVariant(item->typeSub);
case Qt::UserRole + 1:
return QVariant(item->mark);
case Qt::UserRole + 2:
return QVariant(item->strategy);
case Qt::UserRole + 3:
return QVariant(item->name);
}
return QVariant();
}
int CBoxListModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_items.size();
}
Qt::ItemFlags CBoxListModel::flags(const QModelIndex &index) const
{
Q_UNUSED(index)
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
}
bool CBoxListModel::removeRows(int row, int count, const QModelIndex &parent)
{
if (row < 0 || count < 1)
return false;
const int size = m_items.size();
const int last = row + count - 1;
if (row >= size || last >= size)
return false;
beginRemoveRows(parent, row, last);
for (int r = last; r >= row; r--)
m_items.removeAt(r);
endRemoveRows();
return true;
}
void CBoxListModel::addWidget(DrawObjDatabaseRecord *record)
{
const int row = m_items.size();
beginInsertRows(QModelIndex(), row, row);
m_items.push_back(record);
endInsertRows();
}

View File

@ -0,0 +1,27 @@
#ifndef CBOXLISTMODEL_H
#define CBOXLISTMODEL_H
#include "QAbstractListModel"
#include "CDrawObjDatabase.h"
class CBoxListModel : public QAbstractListModel
{
Q_OBJECT
public:
CBoxListModel(QObject *parent = Q_NULLPTR);
~CBoxListModel();
bool isExist(const QString &name);
DrawObjDatabaseRecord* record(const QModelIndex &index) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
Qt::ItemFlags flags (const QModelIndex & index ) const override;
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
void addWidget(DrawObjDatabaseRecord *record);
private:
QList<DrawObjDatabaseRecord*> m_items;
};
#endif // CBOXLISTMODEL_H

View File

@ -0,0 +1,122 @@
#include "CBoxListView.h"
#include "CBoxListModel.h"
#include "CBoxDelegate.h"
CBoxListView::CBoxListView(QWidget *parent)
: QListView(parent),
m_pModel(new CBoxListModel(this)),
m_nMaxTextWidth(0)
{
setFocusPolicy(Qt::NoFocus);
setFrameShape(QFrame::NoFrame);
setIconSize(QSize(30, 30));
setSpacing(1);
setTextElideMode(Qt::ElideMiddle);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setResizeMode(QListView::Adjust);
setDragEnabled(true);
setDragDropMode(QAbstractItemView::DragOnly);
QFont font = qApp->font();
font.setPointSize(font.pointSize() + 1);
setFont(font);
//setUniformItemSizes(true);
setModel(m_pModel);
setItemDelegate(new CListDelegate(this));
connect(this, &CBoxListView::pressed, this, &CBoxListView::slotItemPressed);
}
bool CBoxListView::isExist(const QString &name)
{
return m_pModel->isExist(name);
}
DrawObjDatabaseRecord *CBoxListView::selectedRecord()
{
QModelIndex curIndex = currentIndex();
if( !curIndex.isValid() )
{
return NULL;
}
return m_pModel->record(curIndex);
}
void CBoxListView::addWidget(DrawObjDatabaseRecord *record)
{
if(record->icon && record->icon->isNull()){
setMaxTextWidth(record->name);
}
m_pModel->addWidget(record);
}
void CBoxListView::removeSelectedWidget()
{
QModelIndex curIndex = currentIndex();
if( !curIndex.isValid() )
{
return;
}
m_pModel->removeRows(curIndex.row(), 1);
}
int CBoxListView::getMaxTextWidth()
{
return m_nMaxTextWidth;
}
void CBoxListView::setMaxTextWidth(const QString &text)
{
QFontMetrics font = this->fontMetrics();
int width = font.boundingRect(text+"AA").width();
if(width > m_nMaxTextWidth)
{
m_nMaxTextWidth = width;
}
}
bool CBoxListView::filter(const QString &text)
{
bool isHidden = true;
DrawObjDatabaseRecord * record;
for(int nIndex(0); nIndex<m_pModel->rowCount(); ++nIndex)
{
record = m_pModel->record(m_pModel->index(nIndex, 0));
if(text.isEmpty() || (record && record->name.contains(text)))
{
setRowHidden(nIndex, false);
isHidden = false;
}
else
{
setRowHidden(nIndex, true);
}
}
return isHidden;
}
void CBoxListView::dragMoveEvent(QDragMoveEvent *e)
{
e->setAccepted(false);
}
void CBoxListView::startDrag(Qt::DropActions supportedActions)
{
Q_UNUSED(supportedActions)
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData();
mimeData->setText("toolBox");
drag->setMimeData(mimeData);
drag->exec(Qt::CopyAction);
}
void CBoxListView::slotItemPressed(const QModelIndex &index)
{
emit itemSelected();
CBoxListModel * model = dynamic_cast<CBoxListModel *>(this->model());
DrawObjDatabaseRecord * record = model->record(index);
if(record)
{
emit itemPressed(record);
}
}

View File

@ -0,0 +1,42 @@
#ifndef CBOXLISTVIEW_H
#define CBOXLISTVIEW_H
#include <QListView>
#include "CDrawObjDatabase.h"
class CBoxListModel;
class CBoxListView : public QListView
{
Q_OBJECT
public:
CBoxListView(QWidget *parent = Q_NULLPTR);
using QListView::contentsSize;
bool isExist(const QString &name);
DrawObjDatabaseRecord * selectedRecord();
void addWidget(DrawObjDatabaseRecord *record);
void removeSelectedWidget();
int getMaxTextWidth();
void setMaxTextWidth(const QString &text);
bool filter(const QString &text);
signals:
void itemSelected();
void itemPressed(const DrawObjDatabaseRecord *record);
protected:
void dragMoveEvent(QDragMoveEvent *e);
void startDrag(Qt::DropActions supportedActions);
private slots:
void slotItemPressed(const QModelIndex &index);
private:
CBoxListModel * m_pModel;
int m_nMaxTextWidth;
};
#endif // CBOXLISTVIEW_H

View File

@ -0,0 +1,190 @@
#include <QHeaderView>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLineEdit>
#include "CBoxTreeWidget.h"
#include "CBoxListView.h"
#include "CBoxDelegate.h"
CBoxTreeWidget::CBoxTreeWidget(QWidget *parent)
: QTreeWidget(parent)
{
setFocusPolicy(Qt::NoFocus);
setRootIsDecorated(false);
setIndentation(0);
setColumnCount(1);
setTextElideMode(Qt::ElideMiddle);
setVerticalScrollMode(QTreeView::ScrollPerPixel);
setStyleSheet("QTreeView::item{height:26px;}");
QFont font = qApp->font();
font.setPointSize(font.pointSize() + 1);
setFont(font);
QPalette palette = this->palette();
palette.setColor(QPalette::Shadow, Qt::blue);
setIconSize(QSize(30, 30));
setPalette(palette);
setAutoFillBackground(true);
setItemDelegate(new CTreeDelegate(this));
initHeaderView();
}
bool CBoxTreeWidget::isExist(const QString &name)
{
for(int nIndex = 0; nIndex < topLevelItemCount(); ++nIndex)
{
QTreeWidgetItem * item = topLevelItem(nIndex);
if(item->childCount() <= 0)
{
continue;
}
CBoxListView *listView = static_cast<CBoxListView*>(itemWidget(item->child(0), 0));
if(listView == NULL)
{
continue;
}
if(listView->isExist(name))
{
return true;
}
}
return false;
}
QString CBoxTreeWidget::currentName()
{
QTreeWidgetItem * item = currentItem();
if(item)
{
CBoxListView *listWidget = static_cast<CBoxListView*>(itemWidget(item, 0));
if(listWidget)
{
return listWidget->model()->data(listWidget->currentIndex(), Qt::UserRole + 3).toString();
}
else
{
return item->data(0, Qt::UserRole + 3).toString();
}
}
return QString();
}
CBoxListView *CBoxTreeWidget::addListView(QTreeWidgetItem *parent, bool iconMode)
{
QTreeWidgetItem *embed_item = new QTreeWidgetItem(parent);
CBoxListView *listView = new CBoxListView(this);
listView->setViewMode(iconMode ? QListView::IconMode : QListView::ListMode);
connect(listView, &CBoxListView::itemSelected, this, &CBoxTreeWidget::slotItemWidgetSelected);
setItemWidget(embed_item, 0, listView);
m_itemWidgetMap[listView] = embed_item;
return listView;
}
CBoxListView *CBoxTreeWidget::getListView(QTreeWidgetItem *parent)
{
if(parent == NULL)
{
return NULL;
}
QMap<QWidget *, QTreeWidgetItem *>::const_iterator iter = m_itemWidgetMap.constBegin();
for( ; iter != m_itemWidgetMap.constEnd(); ++iter)
{
if(iter.value() == parent)
{
return dynamic_cast<CBoxListView *>(iter.key());
}
}
return NULL;
}
void CBoxTreeWidget::adjustSubListSize(QTreeWidgetItem *cat_item)
{
QTreeWidgetItem *embedItem = cat_item->child(0);
if (embedItem == 0)
return;
CBoxListView *listWidget = static_cast<CBoxListView*>(itemWidget(embedItem, 0));
listWidget->setFixedWidth(header()->width());
listWidget->doItemsLayout();
const int height = qMax(listWidget->contentsSize().height() ,1);
listWidget->setFixedHeight(height);
embedItem->setSizeHint(0, QSize(-1, height - 1));
}
void CBoxTreeWidget::resizeEvent(QResizeEvent *e)
{
QTreeWidget::resizeEvent(e);
if (const int numTopLevels = topLevelItemCount()) {
for (int i = numTopLevels - 1; i >= 0; --i)
adjustSubListSize(topLevelItem(i));
}
}
void CBoxTreeWidget::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
QTreeWidgetItem * item = itemAt(event->pos());
if(item){
item->isExpanded() ? collapseItem(item) : expandItem(item);
}
}
return QTreeWidget::mousePressEvent(event);
}
void CBoxTreeWidget::filter(const QString &text)
{
for(int nIndex(0); nIndex < topLevelItemCount(); ++nIndex)
{
QTreeWidgetItem * top = topLevelItem(nIndex);
if(!top->child(0))
{
top->setHidden(true);
continue;
}
CBoxListView *listWidget = static_cast<CBoxListView*>(itemWidget(top->child(0), 0));
if(listWidget)
{
top->setHidden(listWidget->filter(text));
}
else
{
top->setHidden(true);
}
adjustSubListSize(top);
}
text.isEmpty() ? collapseAll() : expandAll();
}
void CBoxTreeWidget::slotItemWidgetSelected()
{
QWidget * widget = dynamic_cast<QWidget *>(sender());
QMap<QWidget *, QTreeWidgetItem *>::const_iterator iter = m_itemWidgetMap.find(widget);
if(iter != m_itemWidgetMap.constEnd())
{
clearSelection();
setCurrentItem(iter.value());
iter.value()->parent()->setSelected(true);
}
}
void CBoxTreeWidget::initHeaderView()
{
QHBoxLayout * hLayout = new QHBoxLayout;
QLineEdit * edit = new QLineEdit(this);
edit->setFrame(false);
edit->setPlaceholderText(tr("搜索..."));
edit->setFixedHeight(21);
hLayout->setContentsMargins(3,0,0,0);
hLayout->addWidget(edit);
QVBoxLayout * vLayout = new QVBoxLayout;
vLayout->addLayout(hLayout);
QFrame * line = new QFrame(this);
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
vLayout->addWidget(line);
vLayout->setMargin(1);
vLayout->setSpacing(1);
header()->setLayout(vLayout);
connect(edit, SIGNAL(textChanged(QString)), this, SLOT(filter(QString)));
}

View File

@ -0,0 +1,35 @@
#ifndef CBOXTREEWIDGET_H
#define CBOXTREEWIDGET_H
#include "QTreeWidget"
class CBoxListView;
class CBoxTreeWidget : public QTreeWidget
{
Q_OBJECT
public:
CBoxTreeWidget(QWidget *parent = Q_NULLPTR);
bool isExist(const QString &name);
QString currentName();
CBoxListView *addListView(QTreeWidgetItem *parent, bool iconMode);
CBoxListView *getListView(QTreeWidgetItem *parent);
void adjustSubListSize(QTreeWidgetItem *cat_item);
protected:
void resizeEvent(QResizeEvent *e);
void mousePressEvent(QMouseEvent *event);
private slots:
void filter(const QString &text);
private:
void slotItemWidgetSelected();
void initHeaderView();
private:
QMap<QWidget *, QTreeWidgetItem *> m_itemWidgetMap;
};
#endif // CBOXTREEWIDGET_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,148 @@
/********************************************************************************
* @file FbdDiagOptCmdApi.h
* @brief Diagram
* @author caodingfa
* @version 1.0
* @date 2024/10/23
**********************************************************************************/
#pragma once
#include "FbdCommonExport.h"
#include "operate_server_api/JsonOptCommand.h"
#include "net_msg_bus_api/CMbCommunicator.h"
namespace iot_app
{
namespace app_fbd
{
typedef boost::shared_ptr<SOptCtrlReply> SOptCtrlReplyPtr;
//< 功能块图Diagram控制接口内部有锁线程安全
class CFbdDiagOptCmdApi
{
public:
virtual ~CFbdDiagOptCmdApi() = default;
/********************************************************************************
* @brief
* @param strVarName
* @return iotSuccess
**********************************************************************************/
//virtual int unregGlobalStringVar(const std::string &strVarName) = 0;
/*********************************************************************************
* @brief addSub添加订阅
* @param[in] nAppID ID0
* @param[in] nChannelID ID0
* @return
* @retval true
* false
**********************************************************************************/
/*********************************************************************************
* @brief
* @return
**********************************************************************************/
virtual std::string getMbCommName() = 0;
/*********************************************************************************
* @brief CH_OPT_TO_HMI_OPTCMD_UP通道
* @param[in] strInstName
* @return
* @retval true
* false
**********************************************************************************/
virtual bool subOptCtrlReplyTopic(const std::string &strInstName) = 0;
/*********************************************************************************
* @brief
* @param[in] strInstName
* @return
* @retval true
* false
**********************************************************************************/
virtual bool unsubOptCtrlReplyTopic(const std::string &strInstName) = 0;
/*********************************************************************************
* @brief
* @param[in] strInstName
* @return
* @retval
**********************************************************************************/
virtual SOptCtrlReplyPtr getOptCtrlReply(const std::string &strInstName) = 0;
//消息中strHostName要求赋值为本节点名strInstName要与subOptCtrlReplyTopic中一致
/*********************************************************************************
* @brief sendMsgToDomain发送消息给指定域的所有订阅者
* @details IDID
*
*
* @param[in] msgSend isValid()true
* msgSend的内容将被取走
* msgSend的所有内容
* @param[in] nDomainID ID-1
*
* @return 线bool
* @retval true线
* falsemsgSend无效isValid()false
*
**********************************************************************************/
virtual bool sendOptCtrReqToDomain(iot_net::CMbMessage &msgSend, const int nDomainID) = 0;
/*********************************************************************************
* @brief pushOptCtrlMessageCache
* @details
*
*
* @param[in] msgSend
* @param[in] diagName
* @param[in] nAppId id
* @return
**********************************************************************************/
virtual bool pushOptCtrlMessageCache(SOptCtrlRequest msgSend,const std::string diagName,const int nAppId) = 0;
/*********************************************************************************
* @brief trigerSendMessage
* @details
*
*
* @param[in]
* @return
**********************************************************************************/
virtual bool trigerSendMessage(const std::vector<std::string> vecDiagName) = 0;
/*********************************************************************************
* @brief removeGroup
* @details 线
*
*
* @param[in]
* @return
**********************************************************************************/
virtual bool removeGroup(const std::vector<std::string> vecDiagName) = 0;
/******************************************************************************
* @brief sendMsgToDomain发送消息给指定域的所有订阅者,使
* @details IDID
*
*
* @param[in] msgSend isValid()true
* msgSend的内容将被取走
* msgSend的所有内容
* @param[in] nDomainID ID-1
*
* @return 线bool
* @retval true线
* falsemsgSend无效isValid()false
*
**********************************************************************************/
virtual bool sendMsgToDomainByPublishCommunicator(iot_net::CMbMessage &msgSend, const int nDomainID )=0;
};
typedef boost::shared_ptr<CFbdDiagOptCmdApi> CFbdDiagOptCmdApiPtr;
//< 获取单例对象,内部有锁,线程安全
FBD_COMMON_API CFbdDiagOptCmdApiPtr getFbdDiagOptCmdApi();
} //< namespace app_fbd
} //< namespace iot_app

View File

@ -0,0 +1,13 @@
#ifndef EXCELLIB_H
#define EXCELLIB_H
#include "excellib_global.h"
class EXCELLIBSHARED_EXPORT ExcelLib
{
public:
ExcelLib();
};
#endif // EXCELLIB_H

View File

@ -0,0 +1,12 @@
#ifndef EXCELLIB_GLOBAL_H
#define EXCELLIB_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(EXCELLIB_LIBRARY)
# define EXCELLIBSHARED_EXPORT Q_DECL_EXPORT
#else
# define EXCELLIBSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // EXCELLIB_GLOBAL_H

View File

@ -0,0 +1,119 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxabstractooxmlfile.h"
#include "xlsxabstractooxmlfile_p.h"
#include <QBuffer>
#include <QByteArray>
QT_BEGIN_NAMESPACE_XLSX
AbstractOOXmlFilePrivate::AbstractOOXmlFilePrivate(AbstractOOXmlFile *q, AbstractOOXmlFile::CreateFlag flag=AbstractOOXmlFile::F_NewFromScratch)
:relationships(new Relationships), flag(flag), q_ptr(q)
{
}
AbstractOOXmlFilePrivate::~AbstractOOXmlFilePrivate()
{
}
/*!
* \internal
*
* \class AbstractOOXmlFile
*
* Base class of all the ooxml part file.
*/
AbstractOOXmlFile::AbstractOOXmlFile(CreateFlag flag)
:d_ptr(new AbstractOOXmlFilePrivate(this, flag))
{
}
AbstractOOXmlFile::AbstractOOXmlFile(AbstractOOXmlFilePrivate *d)
:d_ptr(d)
{
}
AbstractOOXmlFile::~AbstractOOXmlFile()
{
if (d_ptr->relationships)
delete d_ptr->relationships;
delete d_ptr;
}
QByteArray AbstractOOXmlFile::saveToXmlData() const
{
QByteArray data;
QBuffer buffer(&data);
buffer.open(QIODevice::WriteOnly);
saveToXmlFile(&buffer);
return data;
}
bool AbstractOOXmlFile::loadFromXmlData(const QByteArray &data)
{
QBuffer buffer;
buffer.setData(data);
buffer.open(QIODevice::ReadOnly);
return loadFromXmlFile(&buffer);
}
/*!
* \internal
*/
void AbstractOOXmlFile::setFilePath(const QString path)
{
Q_D(AbstractOOXmlFile);
d->filePathInPackage = path;
}
/*!
* \internal
*/
QString AbstractOOXmlFile::filePath() const
{
Q_D(const AbstractOOXmlFile);
return d->filePathInPackage;
}
/*!
* \internal
*/
Relationships *AbstractOOXmlFile::relationships() const
{
Q_D(const AbstractOOXmlFile);
return d->relationships;
}
QT_END_NAMESPACE_XLSX

View File

@ -0,0 +1,70 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_XLSXABSTRACTOOXMLFILE_H
#define QXLSX_XLSXABSTRACTOOXMLFILE_H
#include "xlsxglobal.h"
class QIODevice;
class QByteArray;
QT_BEGIN_NAMESPACE_XLSX
class Relationships;
class AbstractOOXmlFilePrivate;
class Q_XLSX_EXPORT AbstractOOXmlFile
{
Q_DECLARE_PRIVATE(AbstractOOXmlFile)
public:
enum CreateFlag
{
F_NewFromScratch,
F_LoadFromExists
};
virtual ~AbstractOOXmlFile();
virtual void saveToXmlFile(QIODevice *device) const = 0;
virtual bool loadFromXmlFile(QIODevice *device) = 0;
virtual QByteArray saveToXmlData() const;
virtual bool loadFromXmlData(const QByteArray &data);
Relationships *relationships() const;
void setFilePath(const QString path);
QString filePath() const;
protected:
AbstractOOXmlFile(CreateFlag flag);
AbstractOOXmlFile(AbstractOOXmlFilePrivate *d);
AbstractOOXmlFilePrivate *d_ptr;
};
QT_END_NAMESPACE_XLSX
#endif // QXLSX_XLSXABSTRACTOOXMLFILE_H

View File

@ -0,0 +1,64 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXOOXMLFILE_P_H
#define XLSXOOXMLFILE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxabstractooxmlfile.h"
#include "xlsxrelationships_p.h"
#include <QString>
QT_BEGIN_NAMESPACE_XLSX
class XLSX_AUTOTEST_EXPORT AbstractOOXmlFilePrivate
{
Q_DECLARE_PUBLIC(AbstractOOXmlFile)
public:
AbstractOOXmlFilePrivate(AbstractOOXmlFile *q, AbstractOOXmlFile::CreateFlag flag);
virtual ~AbstractOOXmlFilePrivate();
QString filePathInPackage;//such as "xl/worksheets/sheet1.xml"
//used when load the .xlsx file
Relationships *relationships;
AbstractOOXmlFile::CreateFlag flag;
AbstractOOXmlFile *q_ptr;
};
QT_END_NAMESPACE_XLSX
#endif // XLSXOOXMLFILE_P_H

View File

@ -0,0 +1,206 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxabstractsheet.h"
#include "xlsxabstractsheet_p.h"
#include "xlsxworkbook.h"
QT_BEGIN_NAMESPACE_XLSX
AbstractSheetPrivate::AbstractSheetPrivate(AbstractSheet *p, AbstractSheet::CreateFlag flag)
: AbstractOOXmlFilePrivate(p, flag)
{
type = AbstractSheet::ST_WorkSheet;
sheetState = AbstractSheet::SS_Visible;
}
AbstractSheetPrivate::~AbstractSheetPrivate()
{
}
/*!
\class AbstractSheet
\inmodule QtXlsx
\brief Base class for worksheet, chartsheet, etc.
*/
/*!
\enum AbstractSheet::SheetType
\value ST_WorkSheet
\value ST_ChartSheet
\omitvalue ST_DialogSheet
\omitvalue ST_MacroSheet
*/
/*!
\enum AbstractSheet::SheetState
\value SS_Visible
\value SS_Hidden
\value SS_VeryHidden User cann't make a veryHidden sheet visible in normal way.
*/
/*!
\fn AbstractSheet::copy(const QString &distName, int distId) const
Copies the current sheet to a sheet called \a distName with \a distId.
Returns the new sheet.
*/
/*!
* \internal
*/
AbstractSheet::AbstractSheet(const QString &name, int id, Workbook *workbook, AbstractSheetPrivate *d) :
AbstractOOXmlFile(d)
{
d_func()->name = name;
d_func()->id = id;
d_func()->workbook = workbook;
}
/*!
* Returns the name of the sheet.
*/
QString AbstractSheet::sheetName() const
{
Q_D(const AbstractSheet);
return d->name;
}
/*!
* \internal
*/
void AbstractSheet::setSheetName(const QString &sheetName)
{
Q_D(AbstractSheet);
d->name = sheetName;
}
/*!
* Returns the type of the sheet.
*/
AbstractSheet::SheetType AbstractSheet::sheetType() const
{
Q_D(const AbstractSheet);
return d->type;
}
/*!
* \internal
*/
void AbstractSheet::setSheetType(SheetType type)
{
Q_D(AbstractSheet);
d->type = type;
}
/*!
* Returns the state of the sheet.
*
* \sa isHidden(), isVisible(), setSheetState()
*/
AbstractSheet::SheetState AbstractSheet::sheetState() const
{
Q_D(const AbstractSheet);
return d->sheetState;
}
/*!
* Set the state of the sheet to \a state.
*/
void AbstractSheet::setSheetState(SheetState state)
{
Q_D(AbstractSheet);
d->sheetState = state;
}
/*!
* Returns true if the sheet is not visible, otherwise false will be returned.
*
* \sa sheetState(), setHidden()
*/
bool AbstractSheet::isHidden() const
{
Q_D(const AbstractSheet);
return d->sheetState != SS_Visible;
}
/*!
* Returns true if the sheet is visible.
*/
bool AbstractSheet::isVisible() const
{
return !isHidden();
}
/*!
* Make the sheet hiden or visible based on \a hidden.
*/
void AbstractSheet::setHidden(bool hidden)
{
Q_D(AbstractSheet);
if (hidden == isHidden())
return;
d->sheetState = hidden ? SS_Hidden : SS_Visible;
}
/*!
* Convenience function, equivalent to setHidden(! \a visible).
*/
void AbstractSheet::setVisible(bool visible)
{
setHidden(!visible);
}
/*!
* \internal
*/
int AbstractSheet::sheetId() const
{
Q_D(const AbstractSheet);
return d->id;
}
/*!
* \internal
*/
Drawing *AbstractSheet::drawing() const
{
Q_D(const AbstractSheet);
return d->drawing.data();
}
/*!
* Return the workbook
*/
Workbook *AbstractSheet::workbook() const
{
Q_D(const AbstractSheet);
return d->workbook;
}
QT_END_NAMESPACE_XLSX

View File

@ -0,0 +1,76 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXABSTRACTSHEET_H
#define XLSXABSTRACTSHEET_H
#include "xlsxabstractooxmlfile.h"
#include <QStringList>
#include <QSharedPointer>
QT_BEGIN_NAMESPACE_XLSX
class Workbook;
class Drawing;
class AbstractSheetPrivate;
class Q_XLSX_EXPORT AbstractSheet : public AbstractOOXmlFile
{
Q_DECLARE_PRIVATE(AbstractSheet)
public:
enum SheetType {
ST_WorkSheet,
ST_ChartSheet,
ST_DialogSheet,
ST_MacroSheet
};
enum SheetState {
SS_Visible,
SS_Hidden,
SS_VeryHidden
};
QString sheetName() const;
SheetType sheetType() const;
SheetState sheetState() const;
void setSheetState(SheetState ss);
bool isHidden() const;
bool isVisible() const;
void setHidden(bool hidden);
void setVisible(bool visible);
Workbook *workbook() const;
protected:
friend class Workbook;
AbstractSheet(const QString &sheetName, int sheetId, Workbook *book, AbstractSheetPrivate *d);
virtual AbstractSheet *copy(const QString &distName, int distId) const = 0;
void setSheetName(const QString &sheetName);
void setSheetType(SheetType type);
int sheetId() const;
Drawing *drawing() const;
};
QT_END_NAMESPACE_XLSX
#endif // XLSXABSTRACTSHEET_H

View File

@ -0,0 +1,64 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXABSTRACTSHEET_P_H
#define XLSXABSTRACTSHEET_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxglobal.h"
#include "xlsxabstractsheet.h"
#include "xlsxabstractooxmlfile_p.h"
#include <QSharedPointer>
namespace QXlsx {
class XLSX_AUTOTEST_EXPORT AbstractSheetPrivate : public AbstractOOXmlFilePrivate
{
Q_DECLARE_PUBLIC(AbstractSheet)
public:
AbstractSheetPrivate(AbstractSheet *p, AbstractSheet::CreateFlag flag);
~AbstractSheetPrivate();
Workbook *workbook;
QSharedPointer<Drawing> drawing;
QString name;
int id;
AbstractSheet::SheetState sheetState;
AbstractSheet::SheetType type;
};
}
#endif // XLSXABSTRACTSHEET_P_H

View File

@ -0,0 +1,178 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxcell.h"
#include "xlsxcell_p.h"
#include "xlsxformat.h"
#include "xlsxformat_p.h"
#include "xlsxutility_p.h"
#include "xlsxworksheet.h"
#include "xlsxworkbook.h"
#include <QDateTime>
QT_BEGIN_NAMESPACE_XLSX
CellPrivate::CellPrivate(Cell *p) :
q_ptr(p)
{
}
CellPrivate::CellPrivate(const CellPrivate * const cp)
: value(cp->value), formula(cp->formula), cellType(cp->cellType)
, format(cp->format), richString(cp->richString), parent(cp->parent)
{
}
/*!
\class Cell
\inmodule QtXlsx
\brief The Cell class provides a API that is used to handle the worksheet cell.
*/
/*!
\enum Cell::CellType
\value BooleanType Boolean type
\value NumberType Number type, can be blank or used with forumula
\value ErrorType Error type
\value SharedStringType Shared string type
\value StringType String type, can be used with forumula
\value InlineStringType Inline string type
*/
/*!
* \internal
* Created by Worksheet only.
*/
Cell::Cell(const QVariant &data, CellType type, const Format &format, Worksheet *parent) :
d_ptr(new CellPrivate(this))
{
d_ptr->value = data;
d_ptr->cellType = type;
d_ptr->format = format;
d_ptr->parent = parent;
}
/*!
* \internal
*/
Cell::Cell(const Cell * const cell):
d_ptr(new CellPrivate(cell->d_ptr))
{
d_ptr->q_ptr = this;
}
/*!
* Destroys the Cell and cleans up.
*/
Cell::~Cell()
{
delete d_ptr;
}
/*!
* Return the dataType of this Cell
*/
Cell::CellType Cell::cellType() const
{
Q_D(const Cell);
return d->cellType;
}
/*!
* Return the data content of this Cell
*/
QVariant Cell::value() const
{
Q_D(const Cell);
return d->value;
}
/*!
* Return the style used by this Cell. If no style used, 0 will be returned.
*/
Format Cell::format() const
{
Q_D(const Cell);
return d->format;
}
/*!
* Returns true if the cell has one formula.
*/
bool Cell::hasFormula() const
{
Q_D(const Cell);
return d->formula.isValid();
}
/*!
* Return the formula contents if the dataType is Formula
*/
CellFormula Cell::formula() const
{
Q_D(const Cell);
return d->formula;
}
/*!
* Returns whether the value is probably a dateTime or not
*/
bool Cell::isDateTime() const
{
Q_D(const Cell);
if (d->cellType == NumberType && d->value.toDouble() >=0
&& d->format.isValid() && d->format.isDateTimeFormat()) {
return true;
}
return false;
}
/*!
* Return the data time value.
*/
QDateTime Cell::dateTime() const
{
Q_D(const Cell);
if (!isDateTime())
return QDateTime();
return datetimeFromNumber(d->value.toDouble(), d->parent->workbook()->isDate1904());
}
/*!
* Returns whether the cell is probably a rich string or not
*/
bool Cell::isRichString() const
{
Q_D(const Cell);
if (d->cellType != SharedStringType && d->cellType != InlineStringType
&& d->cellType != StringType)
return false;
return d->richString.isRichString();
}
QT_END_NAMESPACE_XLSX

View File

@ -0,0 +1,77 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_XLSXCELL_H
#define QXLSX_XLSXCELL_H
#include "xlsxglobal.h"
#include "xlsxformat.h"
#include <QVariant>
QT_BEGIN_NAMESPACE_XLSX
class Worksheet;
class Format;
class CellFormula;
class CellPrivate;
class WorksheetPrivate;
class Q_XLSX_EXPORT Cell
{
Q_DECLARE_PRIVATE(Cell)
public:
enum CellType {
BooleanType, //t="b"
NumberType, //t="n" (default)
ErrorType, //t="e"
SharedStringType, //t="s"
StringType, //t="str"
InlineStringType //t="inlineStr"
};
CellType cellType() const;
QVariant value() const;
Format format() const;
bool hasFormula() const;
CellFormula formula() const;
bool isDateTime() const;
QDateTime dateTime() const;
bool isRichString() const;
~Cell();
private:
friend class Worksheet;
friend class WorksheetPrivate;
Cell(const QVariant &data=QVariant(), CellType type=NumberType, const Format &format=Format(), Worksheet *parent=0);
Cell(const Cell * const cell);
CellPrivate * const d_ptr;
};
QT_END_NAMESPACE_XLSX
#endif // QXLSX_XLSXCELL_H

View File

@ -0,0 +1,69 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXCELL_P_H
#define XLSXCELL_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxglobal.h"
#include "xlsxcell.h"
#include "xlsxcellrange.h"
#include "xlsxrichstring.h"
#include "xlsxcellformula.h"
#include <QList>
#include <QSharedPointer>
QT_BEGIN_NAMESPACE_XLSX
class CellPrivate
{
Q_DECLARE_PUBLIC(Cell)
public:
CellPrivate(Cell *p);
CellPrivate(const CellPrivate * const cp);
QVariant value;
CellFormula formula;
Cell::CellType cellType;
Format format;
RichString richString;
Worksheet *parent;
Cell *q_ptr;
};
QT_END_NAMESPACE_XLSX
#endif // XLSXCELL_P_H

View File

@ -0,0 +1,259 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxcellformula.h"
#include "xlsxcellformula_p.h"
#include "xlsxutility_p.h"
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
QT_BEGIN_NAMESPACE_XLSX
CellFormulaPrivate::CellFormulaPrivate(const QString &formula_, const CellRange &ref_, CellFormula::FormulaType type_)
:formula(formula_), type(type_), reference(ref_), ca(false), si(0)
{
//Remove the formula '=' sign if exists
if (formula.startsWith(QLatin1String("=")))
formula.remove(0,1);
else if (formula.startsWith(QLatin1String("{=")) && formula.endsWith(QLatin1String("}")))
formula = formula.mid(2, formula.length()-3);
}
CellFormulaPrivate::CellFormulaPrivate(const CellFormulaPrivate &other)
: QSharedData(other)
, formula(other.formula), type(other.type), reference(other.reference)
, ca(other.ca), si(other.si)
{
}
CellFormulaPrivate::~CellFormulaPrivate()
{
}
/*!
\class CellFormula
\inmodule QtXlsx
\brief The CellFormula class provides a API that is used to handle the cell formula.
*/
/*!
\enum CellFormula::FormulaType
\value NormalType
\value ArrayType
\value DataTableType
\value SharedType
*/
/*!
* Creates a new formula.
*/
CellFormula::CellFormula()
{
//The d pointer is initialized with a null pointer
}
/*!
* Creates a new formula with the given \a formula and \a type.
*/
CellFormula::CellFormula(const char *formula, FormulaType type)
:d(new CellFormulaPrivate(QString::fromLatin1(formula), CellRange(), type))
{
}
/*!
* Creates a new formula with the given \a formula and \a type.
*/
CellFormula::CellFormula(const QString &formula, FormulaType type)
:d(new CellFormulaPrivate(formula, CellRange(), type))
{
}
/*!
* Creates a new formula with the given \a formula, \a ref and \a type.
*/
CellFormula::CellFormula(const QString &formula, const CellRange &ref, FormulaType type)
:d(new CellFormulaPrivate(formula, ref, type))
{
}
/*!
Creates a new formula with the same attributes as the \a other formula.
*/
CellFormula::CellFormula(const CellFormula &other)
:d(other.d)
{
}
/*!
Assigns the \a other formula to this formula, and returns a
reference to this formula.
*/
CellFormula &CellFormula::operator =(const CellFormula &other)
{
d = other.d;
return *this;
}
/*!
* Destroys this formula.
*/
CellFormula::~CellFormula()
{
}
/*!
* Returns the type of the formula.
*/
CellFormula::FormulaType CellFormula::formulaType() const
{
return d ? d->type : NormalType;
}
/*!
* Returns the contents of the formula.
*/
QString CellFormula::formulaText() const
{
return d ? d->formula : QString();
}
/*!
* Returns the reference cells of the formula. For normal formula,
* this will return an invalid CellRange object.
*/
CellRange CellFormula::reference() const
{
return d ? d->reference : CellRange();
}
/*!
* Returns whether the formula is valid.
*/
bool CellFormula::isValid() const
{
return d;
}
/*!
* Returns the shared index for shared formula.
*/
int CellFormula::sharedIndex() const
{
return d && d->type == SharedType ? d->si : -1;
}
/*!
* \internal
*/
bool CellFormula::saveToXml(QXmlStreamWriter &writer) const
{
writer.writeStartElement(QStringLiteral("f"));
QString t;
switch (d->type) {
case CellFormula::ArrayType:
t = QStringLiteral("array");
break;
case CellFormula::SharedType:
t = QStringLiteral("shared");
break;
default:
break;
}
if (!t.isEmpty())
writer.writeAttribute(QStringLiteral("t"), t);
if (d->reference.isValid())
writer.writeAttribute(QStringLiteral("ref"), d->reference.toString());
if (d->ca)
writer.writeAttribute(QStringLiteral("ca"), QStringLiteral("1"));
if (d->type == CellFormula::SharedType)
writer.writeAttribute(QStringLiteral("si"), QString::number(d->si));
if (!d->formula.isEmpty())
writer.writeCharacters(d->formula);
writer.writeEndElement(); //f
return true;
}
/*!
* \internal
*/
bool CellFormula::loadFromXml(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("f"));
if (!d)
d = new CellFormulaPrivate(QString(), CellRange(), NormalType);
QXmlStreamAttributes attributes = reader.attributes();
QString typeString = attributes.value(QLatin1String("t")).toString();
if (typeString == QLatin1String("array"))
d->type = ArrayType;
else if (typeString == QLatin1String("shared"))
d->type = SharedType;
else
d->type = NormalType;
if (attributes.hasAttribute(QLatin1String("ref"))) {
QString refString = attributes.value(QLatin1String("ref")).toString();
d->reference = CellRange(refString);
}
QString ca = attributes.value(QLatin1String("si")).toString();
d->ca = parseXsdBoolean(ca, false);
if (attributes.hasAttribute(QLatin1String("si")))
d->si = attributes.value(QLatin1String("si")).toString().toInt();
d->formula = reader.readElementText();
return true;
}
/*!
* \internal
*/
bool CellFormula::operator ==(const CellFormula &formula) const
{
return d->formula == formula.d->formula && d->type == formula.d->type
&& d->si ==formula.d->si;
}
/*!
* \internal
*/
bool CellFormula::operator !=(const CellFormula &formula) const
{
return d->formula != formula.d->formula || d->type != formula.d->type
|| d->si !=formula.d->si;
}
QT_END_NAMESPACE_XLSX

View File

@ -0,0 +1,78 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_XLSXCELLFORMULA_H
#define QXLSX_XLSXCELLFORMULA_H
#include "xlsxglobal.h"
#include <QExplicitlySharedDataPointer>
class QXmlStreamWriter;
class QXmlStreamReader;
QT_BEGIN_NAMESPACE_XLSX
class CellFormulaPrivate;
class CellRange;
class Worksheet;
class WorksheetPrivate;
class Q_XLSX_EXPORT CellFormula
{
public:
enum FormulaType {
NormalType,
ArrayType,
DataTableType,
SharedType
};
CellFormula();
CellFormula(const char *formula, FormulaType type=NormalType);
CellFormula(const QString &formula, FormulaType type=NormalType);
CellFormula(const QString &formula, const CellRange &ref, FormulaType type);
CellFormula(const CellFormula &other);
~CellFormula();
CellFormula &operator =(const CellFormula &other);
bool isValid() const;
FormulaType formulaType() const;
QString formulaText() const;
CellRange reference() const;
int sharedIndex() const;
bool operator == (const CellFormula &formula) const;
bool operator != (const CellFormula &formula) const;
bool saveToXml(QXmlStreamWriter &writer) const;
bool loadFromXml(QXmlStreamReader &reader);
private:
friend class Worksheet;
friend class WorksheetPrivate;
QExplicitlySharedDataPointer<CellFormulaPrivate> d;
};
QT_END_NAMESPACE_XLSX
#endif // QXLSX_XLSXCELLFORMULA_H

View File

@ -0,0 +1,64 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXCELLFORMULA_P_H
#define XLSXCELLFORMULA_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxglobal.h"
#include "xlsxcellformula.h"
#include "xlsxcellrange.h"
#include <QSharedData>
#include <QString>
QT_BEGIN_NAMESPACE_XLSX
class CellFormulaPrivate : public QSharedData
{
public:
CellFormulaPrivate(const QString &formula, const CellRange &reference, CellFormula::FormulaType type);
CellFormulaPrivate(const CellFormulaPrivate &other);
~CellFormulaPrivate();
QString formula; //formula contents
CellFormula::FormulaType type;
CellRange reference;
bool ca; //Calculate Cell
int si; //Shared group index
};
QT_END_NAMESPACE_XLSX
#endif // XLSXCELLFORMULA_P_H

View File

@ -0,0 +1,147 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxcellrange.h"
#include "xlsxcellreference.h"
#include <QString>
#include <QPoint>
#include <QStringList>
QT_BEGIN_NAMESPACE_XLSX
/*!
\class CellRange
\brief For a range "A1:B2" or single cell "A1"
\inmodule QtXlsx
The CellRange class stores the top left and bottom
right rows and columns of a range in a worksheet.
*/
/*!
Constructs an range, i.e. a range
whose rowCount() and columnCount() are 0.
*/
CellRange::CellRange()
: top(-1), left(-1), bottom(-2), right(-2)
{
}
/*!
Constructs the range from the given \a top, \a
left, \a bottom and \a right rows and columns.
\sa topRow(), leftColumn(), bottomRow(), rightColumn()
*/
CellRange::CellRange(int top, int left, int bottom, int right)
: top(top), left(left), bottom(bottom), right(right)
{
}
CellRange::CellRange(const CellReference &topLeft, const CellReference &bottomRight)
: top(topLeft.row()), left(topLeft.column())
, bottom(bottomRight.row()), right(bottomRight.column())
{
}
/*!
\overload
Constructs the range form the given \a range string.
*/
CellRange::CellRange(const QString &range)
{
init(range);
}
/*!
\overload
Constructs the range form the given \a range string.
*/
CellRange::CellRange(const char *range)
{
init(QString::fromLatin1(range));
}
void CellRange::init(const QString &range)
{
QStringList rs = range.split(QLatin1Char(':'));
if (rs.size() == 2) {
CellReference start(rs[0]);
CellReference end(rs[1]);
top = start.row();
left = start.column();
bottom = end.row();
right = end.column();
} else {
CellReference p(rs[0]);
top = p.row();
left = p.column();
bottom = p.row();
right = p.column();
}
}
/*!
Constructs a the range by copying the given \a
other range.
*/
CellRange::CellRange(const CellRange &other)
: top(other.top), left(other.left), bottom(other.bottom), right(other.right)
{
}
/*!
Destroys the range.
*/
CellRange::~CellRange()
{
}
/*!
Convert the range to string notation, such as "A1:B5".
*/
QString CellRange::toString(bool row_abs, bool col_abs) const
{
if (!isValid())
return QString();
if (left == right && top == bottom) {
//Single cell
return CellReference(top, left).toString(row_abs, col_abs);
}
QString cell_1 = CellReference(top, left).toString(row_abs, col_abs);
QString cell_2 = CellReference(bottom, right).toString(row_abs, col_abs);
return cell_1 + QLatin1String(":") + cell_2;
}
/*!
* Returns true if the Range is valid.
*/
bool CellRange::isValid() const
{
return left <= right && top <= bottom;
}
QT_END_NAMESPACE_XLSX

View File

@ -0,0 +1,79 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_XLSXCELLRANGE_H
#define QXLSX_XLSXCELLRANGE_H
#include "xlsxglobal.h"
#include "xlsxcellreference.h"
QT_BEGIN_NAMESPACE_XLSX
class Q_XLSX_EXPORT CellRange
{
public:
CellRange();
CellRange(int firstRow, int firstColumn, int lastRow, int lastColumn);
CellRange(const CellReference &topLeft, const CellReference &bottomRight);
CellRange(const QString &range);
CellRange(const char *range);
CellRange(const CellRange &other);
~CellRange();
QString toString(bool row_abs=false, bool col_abs=false) const;
bool isValid() const;
inline void setFirstRow(int row) { top = row; }
inline void setLastRow(int row) { bottom = row; }
inline void setFirstColumn(int col) { left = col; }
inline void setLastColumn(int col) { right = col; }
inline int firstRow() const { return top; }
inline int lastRow() const { return bottom; }
inline int firstColumn() const { return left; }
inline int lastColumn() const { return right; }
inline int rowCount() const { return bottom - top + 1; }
inline int columnCount() const { return right - left + 1; }
inline CellReference topLeft() const { return CellReference(top, left); }
inline CellReference topRight() const { return CellReference(top, right); }
inline CellReference bottomLeft() const { return CellReference(bottom, left); }
inline CellReference bottomRight() const { return CellReference(bottom, right); }
inline bool operator ==(const CellRange &other) const
{
return top==other.top && bottom==other.bottom
&& left == other.left && right == other.right;
}
inline bool operator !=(const CellRange &other) const
{
return top!=other.top || bottom!=other.bottom
|| left != other.left || right != other.right;
}
private:
void init(const QString &range);
int top, left, bottom, right;
};
QT_END_NAMESPACE_XLSX
Q_DECLARE_TYPEINFO(QXlsx::CellRange, Q_MOVABLE_TYPE);
#endif // QXLSX_XLSXCELLRANGE_H

View File

@ -0,0 +1,174 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxcellreference.h"
#include <QStringList>
#include <QMap>
#include <QRegularExpression>
QT_BEGIN_NAMESPACE_XLSX
namespace {
int intPow(int x, int p)
{
if (p == 0) return 1;
if (p == 1) return x;
int tmp = intPow(x, p/2);
if (p%2 == 0) return tmp * tmp;
else return x * tmp * tmp;
}
QString col_to_name(int col_num)
{
static QMap<int, QString> col_cache;
if (!col_cache.contains(col_num)) {
QString col_str;
int remainder;
while (col_num) {
remainder = col_num % 26;
if (remainder == 0)
remainder = 26;
col_str.prepend(QChar('A'+remainder-1));
col_num = (col_num - 1) / 26;
}
col_cache.insert(col_num, col_str);
}
return col_cache[col_num];
}
int col_from_name(const QString &col_str)
{
int col = 0;
int expn = 0;
for (int i=col_str.size()-1; i>-1; --i) {
col += (col_str[i].unicode() - 'A' + 1) * intPow(26, expn);
expn++;
}
return col;
}
} //namespace
/*!
\class CellReference
\brief For one single cell such as "A1"
\inmodule QtXlsx
The CellReference class stores the cell location in a worksheet.
*/
/*!
Constructs an invalid Cell Reference
*/
CellReference::CellReference()
: _row(-1), _column(-1)
{
}
/*!
Constructs the Reference from the given \a row, and \a column.
*/
CellReference::CellReference(int row, int column)
: _row(row), _column(column)
{
}
/*!
\overload
Constructs the Reference form the given \a cell string.
*/
CellReference::CellReference(const QString &cell)
{
init(cell);
}
/*!
\overload
Constructs the Reference form the given \a cell string.
*/
CellReference::CellReference(const char *cell)
{
init(QString::fromLatin1(cell));
}
void CellReference::init(const QString &cell_str)
{
static QRegularExpression re(QStringLiteral("^\\$?([A-Z]{1,3})\\$?(\\d+)$"));
QRegularExpressionMatch match = re.match(cell_str);
if (match.hasMatch()) {
const QString col_str = match.captured(1);
const QString row_str = match.captured(2);
_row = row_str.toInt();
_column = col_from_name(col_str);
}
}
/*!
Constructs a Reference by copying the given \a
other Reference.
*/
CellReference::CellReference(const CellReference &other)
: _row(other._row), _column(other._column)
{
}
/*!
Destroys the Reference.
*/
CellReference::~CellReference()
{
}
/*!
Convert the Reference to string notation, such as "A1" or "$A$1".
If current object is invalid, an empty string will be returned.
*/
QString CellReference::toString(bool row_abs, bool col_abs) const
{
if (!isValid())
return QString();
QString cell_str;
if (col_abs)
cell_str.append(QLatin1Char('$'));
cell_str.append(col_to_name(_column));
if (row_abs)
cell_str.append(QLatin1Char('$'));
cell_str.append(QString::number(_row));
return cell_str;
}
/*!
* Returns true if the Reference is valid.
*/
bool CellReference::isValid() const
{
return _row > 0 && _column > 0;
}
QT_END_NAMESPACE_XLSX

View File

@ -0,0 +1,66 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_XLSXCELLREFERENCE_H
#define QXLSX_XLSXCELLREFERENCE_H
#include "xlsxglobal.h"
QT_BEGIN_NAMESPACE_XLSX
class Q_XLSX_EXPORT CellReference
{
public:
CellReference();
CellReference(int row, int column);
CellReference(const QString &cell);
CellReference(const char *cell);
CellReference(const CellReference &other);
~CellReference();
QString toString(bool row_abs=false, bool col_abs=false) const;
static CellReference fromString(const QString &cell);
bool isValid() const;
inline void setRow(int row) { _row = row; }
inline void setColumn(int col) { _column = col; }
inline int row() const { return _row; }
inline int column() const { return _column; }
inline bool operator ==(const CellReference &other) const
{
return _row==other._row && _column==other._column;
}
inline bool operator !=(const CellReference &other) const
{
return _row!=other._row || _column!=other._column;
}
private:
void init(const QString &cell);
int _row, _column;
};
QT_END_NAMESPACE_XLSX
Q_DECLARE_TYPEINFO(QXlsx::CellReference, Q_MOVABLE_TYPE);
#endif // QXLSX_XLSXCELLREFERENCE_H

View File

@ -0,0 +1,645 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxchart_p.h"
#include "xlsxworksheet.h"
#include "xlsxcellrange.h"
#include "xlsxutility_p.h"
#include <QIODevice>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QDebug>
QT_BEGIN_NAMESPACE_XLSX
ChartPrivate::ChartPrivate(Chart *q, Chart::CreateFlag flag)
:AbstractOOXmlFilePrivate(q, flag), chartType(static_cast<Chart::ChartType>(0))
{
}
ChartPrivate::~ChartPrivate()
{
}
/*!
* \class Chart
* \inmodule QtXlsx
* \brief Main class for the charts.
*/
/*!
\enum Chart::ChartType
\value CT_Area
\value CT_Area3D,
\value CT_Line,
\value CT_Line3D,
\value CT_Scatter,
\value CT_Pie,
\value CT_Pie3D,
\value CT_Doughnut,
\value CT_Bar,
\value CT_Bar3D,
\omitvalue CT_Stock,
\omitvalue CT_Radar,
\omitvalue CT_OfPie,
\omitvalue CT_Surface,
\omitvalue CT_Surface3D,
\omitvalue CT_Bubble
*/
/*!
* \internal
*/
Chart::Chart(AbstractSheet *parent, CreateFlag flag)
:AbstractOOXmlFile(new ChartPrivate(this, flag))
{
d_func()->sheet = parent;
}
/*!
* Destroys the chart.
*/
Chart::~Chart()
{
}
/*!
* Add the data series which is in the range \a range of the \a sheet.
*/
void Chart::addSeries(const CellRange &range, AbstractSheet *sheet)
{
Q_D(Chart);
if (!range.isValid())
return;
if (sheet && sheet->sheetType() != AbstractSheet::ST_WorkSheet)
return;
if (!sheet && d->sheet->sheetType() != AbstractSheet::ST_WorkSheet)
return;
QString sheetName = sheet ? sheet->sheetName() : d->sheet->sheetName();
//In case sheetName contains space or '
sheetName = escapeSheetName(sheetName);
if (range.columnCount() == 1 || range.rowCount() == 1) {
QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries);
series->numberDataSource_numRef = sheetName + QLatin1String("!") + range.toString(true, true);
d->seriesList.append(series);
} else if (range.columnCount() < range.rowCount()) {
//Column based series
int firstDataColumn = range.firstColumn();
QString axDataSouruce_numRef;
if (d->chartType == CT_Scatter || d->chartType == CT_Bubble) {
firstDataColumn += 1;
CellRange subRange(range.firstRow(), range.firstColumn(), range.lastRow(), range.firstColumn());
axDataSouruce_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
}
for (int col=firstDataColumn; col<=range.lastColumn(); ++col) {
CellRange subRange(range.firstRow(), col, range.lastRow(), col);
QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries);
series->axDataSource_numRef = axDataSouruce_numRef;
series->numberDataSource_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
d->seriesList.append(series);
}
} else {
//Row based series
int firstDataRow = range.firstRow();
QString axDataSouruce_numRef;
if (d->chartType == CT_Scatter || d->chartType == CT_Bubble) {
firstDataRow += 1;
CellRange subRange(range.firstRow(), range.firstColumn(), range.firstRow(), range.lastColumn());
axDataSouruce_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
}
for (int row=firstDataRow; row<=range.lastRow(); ++row) {
CellRange subRange(row, range.firstColumn(), row, range.lastColumn());
QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries);
series->axDataSource_numRef = axDataSouruce_numRef;
series->numberDataSource_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
d->seriesList.append(series);
}
}
}
/*!
* Set the type of the chart to \a type
*/
void Chart::setChartType(ChartType type)
{
Q_D(Chart);
d->chartType = type;
}
/*!
* \internal
*
*/
void Chart::setChartStyle(int id)
{
Q_UNUSED(id)
//!Todo
}
/*!
* \internal
*/
void Chart::saveToXmlFile(QIODevice *device) const
{
Q_D(const Chart);
QXmlStreamWriter writer(device);
writer.writeStartDocument(QStringLiteral("1.0"), true);
writer.writeStartElement(QStringLiteral("c:chartSpace"));
writer.writeAttribute(QStringLiteral("xmlns:c"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/chart"));
writer.writeAttribute(QStringLiteral("xmlns:a"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/main"));
writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"));
d->saveXmlChart(writer);
writer.writeEndElement();//c:chartSpace
writer.writeEndDocument();
}
/*!
* \internal
*/
bool Chart::loadFromXmlFile(QIODevice *device)
{
Q_D(Chart);
QXmlStreamReader reader(device);
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("chart")) {
if (!d->loadXmlChart(reader))
return false;
}
}
}
return true;
}
bool ChartPrivate::loadXmlChart(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("chart"));
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("plotArea")) {
if (!loadXmlPlotArea(reader))
return false;
} else if (reader.name() == QLatin1String("legend")) {
//!Todo
}
} else if (reader.tokenType() == QXmlStreamReader::EndElement &&
reader.name() == QLatin1String("chart")) {
break;
}
}
return true;
}
bool ChartPrivate::loadXmlPlotArea(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("plotArea"));
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("layout")) {
//!ToDo
} else if (reader.name().endsWith(QLatin1String("Chart"))) {
//For pieChart, barChart, ...
loadXmlXxxChart(reader);
} else if (reader.name().endsWith(QLatin1String("Ax"))) {
//For valAx, catAx, serAx, dateAx
loadXmlAxis(reader);
}
} else if (reader.tokenType() == QXmlStreamReader::EndElement &&
reader.name() == QLatin1String("plotArea")) {
break;
}
}
return true;
}
bool ChartPrivate::loadXmlXxxChart(QXmlStreamReader &reader)
{
QStringRef name = reader.name();
if (name == QLatin1String("pieChart")) chartType = Chart::CT_Pie;
else if (name == QLatin1String("pie3DChart")) chartType = Chart::CT_Pie3D;
else if (name == QLatin1String("barChart")) chartType = Chart::CT_Bar;
else if (name == QLatin1String("bar3DChart")) chartType = Chart::CT_Bar3D;
else if (name == QLatin1String("lineChart")) chartType = Chart::CT_Line;
else if (name == QLatin1String("line3DChart")) chartType = Chart::CT_Line3D;
else if (name == QLatin1String("scatterChart")) chartType = Chart::CT_Scatter;
else if (name == QLatin1String("areaChart")) chartType = Chart::CT_Area;
else if (name == QLatin1String("area3DChart")) chartType = Chart::CT_Area3D;
else if (name == QLatin1String("doughnutChart")) chartType = Chart::CT_Doughnut;
else qDebug()<<"Cann't load chart: "<<name;
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("ser")) {
loadXmlSer(reader);
} else if (reader.name() == QLatin1String("axId")) {
}
} else if (reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == name) {
break;
}
}
return true;
}
bool ChartPrivate::loadXmlSer(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("ser"));
QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries);
seriesList.append(series);
while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == QLatin1String("ser"))) {
if (reader.readNextStartElement()) {
QStringRef name = reader.name();
if (name == QLatin1String("cat") || name == QLatin1String("xVal")) {
while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == name)) {
if (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("numRef"))
series->axDataSource_numRef = loadXmlNumRef(reader);
}
}
} else if (name == QLatin1String("val") || name == QLatin1String("yVal")) {
while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == name)) {
if (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("numRef"))
series->numberDataSource_numRef = loadXmlNumRef(reader);
}
}
} else if (name == QLatin1String("extLst")) {
while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == name)) {
reader.readNextStartElement();
}
}
}
}
return true;
}
QString ChartPrivate::loadXmlNumRef(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("numRef"));
while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == QLatin1String("numRef"))) {
if (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("f"))
return reader.readElementText();
}
}
return QString();
}
void ChartPrivate::saveXmlChart(QXmlStreamWriter &writer) const
{
writer.writeStartElement(QStringLiteral("c:chart"));
writer.writeStartElement(QStringLiteral("c:plotArea"));
switch (chartType) {
case Chart::CT_Pie:
case Chart::CT_Pie3D:
saveXmlPieChart(writer);
break;
case Chart::CT_Bar:
case Chart::CT_Bar3D:
saveXmlBarChart(writer);
break;
case Chart::CT_Line:
case Chart::CT_Line3D:
saveXmlLineChart(writer);
break;
case Chart::CT_Scatter:
saveXmlScatterChart(writer);
break;
case Chart::CT_Area:
case Chart::CT_Area3D:
saveXmlAreaChart(writer);
break;
case Chart::CT_Doughnut:
saveXmlDoughnutChart(writer);
break;
default:
break;
}
saveXmlAxes(writer);
writer.writeEndElement(); //plotArea
// saveXmlLegend(writer);
writer.writeEndElement(); //chart
}
void ChartPrivate::saveXmlPieChart(QXmlStreamWriter &writer) const
{
QString name = chartType==Chart::CT_Pie ? QStringLiteral("c:pieChart") : QStringLiteral("c:pie3DChart");
writer.writeStartElement(name);
//Do the same behavior as Excel, Pie prefer varyColors
writer.writeEmptyElement(QStringLiteral("c:varyColors"));
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1"));
for (int i=0; i<seriesList.size(); ++i)
saveXmlSer(writer, seriesList[i].data(), i);
writer.writeEndElement(); //pieChart, pie3DChart
}
void ChartPrivate::saveXmlBarChart(QXmlStreamWriter &writer) const
{
QString name = chartType==Chart::CT_Bar ? QStringLiteral("c:barChart") : QStringLiteral("c:bar3DChart");
writer.writeStartElement(name);
writer.writeEmptyElement(QStringLiteral("c:barDir"));
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("col"));
for (int i=0; i<seriesList.size(); ++i)
saveXmlSer(writer, seriesList[i].data(), i);
if (axisList.isEmpty()) {
//The order the axes??
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1)));
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0)));
}
//Note: Bar3D have 2~3 axes
Q_ASSERT(axisList.size()==2 || (axisList.size()==3 && chartType==Chart::CT_Bar3D));
for (int i=0; i<axisList.size(); ++i) {
writer.writeEmptyElement(QStringLiteral("c:axId"));
writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
}
writer.writeEndElement(); //barChart, bar3DChart
}
void ChartPrivate::saveXmlLineChart(QXmlStreamWriter &writer) const
{
QString name = chartType==Chart::CT_Line ? QStringLiteral("c:lineChart") : QStringLiteral("c:line3DChart");
writer.writeStartElement(name);
writer.writeEmptyElement(QStringLiteral("grouping"));
for (int i=0; i<seriesList.size(); ++i)
saveXmlSer(writer, seriesList[i].data(), i);
if (axisList.isEmpty()) {
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1)));
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0)));
if (chartType==Chart::CT_Line3D)
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Ser, XlsxAxis::Bottom, 2, 0)));
}
Q_ASSERT((axisList.size()==2||chartType==Chart::CT_Line)|| (axisList.size()==3 && chartType==Chart::CT_Line3D));
for (int i=0; i<axisList.size(); ++i) {
writer.writeEmptyElement(QStringLiteral("c:axId"));
writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
}
writer.writeEndElement(); //lineChart, line3DChart
}
void ChartPrivate::saveXmlScatterChart(QXmlStreamWriter &writer) const
{
const QString name = QStringLiteral("c:scatterChart");
writer.writeStartElement(name);
writer.writeEmptyElement(QStringLiteral("c:scatterStyle"));
for (int i=0; i<seriesList.size(); ++i)
saveXmlSer(writer, seriesList[i].data(), i);
if (axisList.isEmpty()) {
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Bottom, 0, 1)));
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0)));
}
Q_ASSERT(axisList.size()==2);
for (int i=0; i<axisList.size(); ++i) {
writer.writeEmptyElement(QStringLiteral("c:axId"));
writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
}
writer.writeEndElement(); //c:scatterChart
}
void ChartPrivate::saveXmlAreaChart(QXmlStreamWriter &writer) const
{
QString name = chartType==Chart::CT_Area ? QStringLiteral("c:areaChart") : QStringLiteral("c:area3DChart");
writer.writeStartElement(name);
writer.writeEmptyElement(QStringLiteral("grouping"));
for (int i=0; i<seriesList.size(); ++i)
saveXmlSer(writer, seriesList[i].data(), i);
if (axisList.isEmpty()) {
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1)));
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0)));
}
//Note: Area3D have 2~3 axes
Q_ASSERT(axisList.size()==2 || (axisList.size()==3 && chartType==Chart::CT_Area3D));
for (int i=0; i<axisList.size(); ++i) {
writer.writeEmptyElement(QStringLiteral("c:axId"));
writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
}
writer.writeEndElement(); //lineChart, line3DChart
}
void ChartPrivate::saveXmlDoughnutChart(QXmlStreamWriter &writer) const
{
QString name = QStringLiteral("c:doughnutChart");
writer.writeStartElement(name);
writer.writeEmptyElement(QStringLiteral("c:varyColors"));
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1"));
for (int i=0; i<seriesList.size(); ++i)
saveXmlSer(writer, seriesList[i].data(), i);
writer.writeStartElement(QStringLiteral("c:holeSize"));
writer.writeAttribute(QStringLiteral("val"), QString::number(50));
writer.writeEndElement();
}
void ChartPrivate::saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) const
{
writer.writeStartElement(QStringLiteral("c:ser"));
writer.writeEmptyElement(QStringLiteral("c:idx"));
writer.writeAttribute(QStringLiteral("val"), QString::number(id));
writer.writeEmptyElement(QStringLiteral("c:order"));
writer.writeAttribute(QStringLiteral("val"), QString::number(id));
if (!ser->axDataSource_numRef.isEmpty()) {
if (chartType == Chart::CT_Scatter || chartType == Chart::CT_Bubble)
writer.writeStartElement(QStringLiteral("c:xVal"));
else
writer.writeStartElement(QStringLiteral("c:cat"));
writer.writeStartElement(QStringLiteral("c:numRef"));
writer.writeTextElement(QStringLiteral("c:f"), ser->axDataSource_numRef);
writer.writeEndElement();//c:numRef
writer.writeEndElement();//c:cat or c:xVal
}
if (!ser->numberDataSource_numRef.isEmpty()) {
if (chartType == Chart::CT_Scatter || chartType == Chart::CT_Bubble)
writer.writeStartElement(QStringLiteral("c:yVal"));
else
writer.writeStartElement(QStringLiteral("c:val"));
writer.writeStartElement(QStringLiteral("c:numRef"));
writer.writeTextElement(QStringLiteral("c:f"), ser->numberDataSource_numRef);
writer.writeEndElement();//c:numRef
writer.writeEndElement();//c:val or c:yVal
}
writer.writeEndElement();//c:ser
}
bool ChartPrivate::loadXmlAxis(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name().endsWith(QLatin1String("Ax")));
QString name = reader.name().toString();
XlsxAxis *axis = new XlsxAxis;
if (name == QLatin1String("valAx"))
axis->type = XlsxAxis::T_Val;
else if (name == QLatin1String("catAx"))
axis->type = XlsxAxis::T_Cat;
else if (name == QLatin1String("serAx"))
axis->type = XlsxAxis::T_Ser;
else
axis->type = XlsxAxis::T_Date;
axisList.append(QSharedPointer<XlsxAxis>(axis));
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("axPos")) {
QXmlStreamAttributes attrs = reader.attributes();
QStringRef pos = attrs.value(QLatin1String("val"));
if (pos==QLatin1String("l"))
axis->axisPos = XlsxAxis::Left;
else if (pos==QLatin1String("r"))
axis->axisPos = XlsxAxis::Right;
else if (pos==QLatin1String("b"))
axis->axisPos = XlsxAxis::Bottom;
else
axis->axisPos = XlsxAxis::Top;
} else if (reader.name() == QLatin1String("axId")) {
axis->axisId = reader.attributes().value(QLatin1String("val")).toString().toInt();
} else if (reader.name() == QLatin1String("crossAx")) {
axis->crossAx = reader.attributes().value(QLatin1String("val")).toString().toInt();
}
} else if (reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == name) {
break;
}
}
return true;
}
void ChartPrivate::saveXmlAxes(QXmlStreamWriter &writer) const
{
for (int i=0; i<axisList.size(); ++i) {
XlsxAxis *axis = axisList[i].data();
QString name;
switch (axis->type) {
case XlsxAxis::T_Cat: name = QStringLiteral("c:catAx"); break;
case XlsxAxis::T_Val: name = QStringLiteral("c:valAx"); break;
case XlsxAxis::T_Ser: name = QStringLiteral("c:serAx"); break;
case XlsxAxis::T_Date: name = QStringLiteral("c:dateAx"); break;
default: break;
}
QString pos;
switch (axis->axisPos) {
case XlsxAxis::Top: pos = QStringLiteral("t"); break;
case XlsxAxis::Bottom: pos = QStringLiteral("b"); break;
case XlsxAxis::Left: pos = QStringLiteral("l"); break;
case XlsxAxis::Right: pos = QStringLiteral("r"); break;
default: break;
}
writer.writeStartElement(name);
writer.writeEmptyElement(QStringLiteral("c:axId"));
writer.writeAttribute(QStringLiteral("val"), QString::number(axis->axisId));
writer.writeStartElement(QStringLiteral("c:scaling"));
writer.writeEmptyElement(QStringLiteral("c:orientation"));
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("minMax"));
writer.writeEndElement();//c:scaling
writer.writeEmptyElement(QStringLiteral("c:axPos"));
writer.writeAttribute(QStringLiteral("val"), pos);
writer.writeEmptyElement(QStringLiteral("c:crossAx"));
writer.writeAttribute(QStringLiteral("val"), QString::number(axis->crossAx));
writer.writeEndElement();//name
}
}
QT_END_NAMESPACE_XLSX

View File

@ -0,0 +1,89 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_CHART_H
#define QXLSX_CHART_H
#include "xlsxabstractooxmlfile.h"
#include <QSharedPointer>
class QXmlStreamReader;
class QXmlStreamWriter;
QT_BEGIN_NAMESPACE_XLSX
class AbstractSheet;
class Worksheet;
class ChartPrivate;
class CellRange;
class DrawingAnchor;
class Q_XLSX_EXPORT Chart : public AbstractOOXmlFile
{
Q_DECLARE_PRIVATE(Chart)
public:
enum ChartType {
CT_Area = 1, //Zero is internally used for unknown types
CT_Area3D,
CT_Line,
CT_Line3D,
CT_Stock,
CT_Radar,
CT_Scatter,
CT_Pie,
CT_Pie3D,
CT_Doughnut,
CT_Bar,
CT_Bar3D,
CT_OfPie,
CT_Surface,
CT_Surface3D,
CT_Bubble
};
~Chart();
void addSeries(const CellRange &range, AbstractSheet *sheet=0);
void setChartType(ChartType type);
void setChartStyle(int id);
void saveToXmlFile(QIODevice *device) const;
bool loadFromXmlFile(QIODevice *device);
private:
friend class AbstractSheet;
friend class Worksheet;
friend class Chartsheet;
friend class DrawingAnchor;
Chart(AbstractSheet *parent, CreateFlag flag);
};
QT_END_NAMESPACE_XLSX
#endif // QXLSX_CHART_H

View File

@ -0,0 +1,125 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_CHART_P_H
#define QXLSX_CHART_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxabstractooxmlfile_p.h"
#include "xlsxchart.h"
#include <QSharedPointer>
class QXmlStreamReader;
class QXmlStreamWriter;
namespace QXlsx {
class XlsxSeries
{
public:
//At present, we care about number cell ranges only!
QString numberDataSource_numRef; //yval, val
QString axDataSource_numRef; //xval, cat
};
class XlsxAxis
{
public:
enum Type
{
T_Cat,
T_Val,
T_Date,
T_Ser
};
enum Pos
{
Left,
Right,
Top,
Bottom
};
XlsxAxis(){}
XlsxAxis(Type t, Pos p, int id, int crossId)
:type(t), axisPos(p), axisId(id), crossAx(crossId)
{
}
Type type;
Pos axisPos; //l,r,b,t
int axisId;
int crossAx;
};
class ChartPrivate : public AbstractOOXmlFilePrivate
{
Q_DECLARE_PUBLIC(Chart)
public:
ChartPrivate(Chart *q, Chart::CreateFlag flag);
~ChartPrivate();
bool loadXmlChart(QXmlStreamReader &reader);
bool loadXmlPlotArea(QXmlStreamReader &reader);
bool loadXmlXxxChart(QXmlStreamReader &reader);
bool loadXmlSer(QXmlStreamReader &reader);
QString loadXmlNumRef(QXmlStreamReader &reader);
bool loadXmlAxis(QXmlStreamReader &reader);
void saveXmlChart(QXmlStreamWriter &writer) const;
void saveXmlPieChart(QXmlStreamWriter &writer) const;
void saveXmlBarChart(QXmlStreamWriter &writer) const;
void saveXmlLineChart(QXmlStreamWriter &writer) const;
void saveXmlScatterChart(QXmlStreamWriter &writer) const;
void saveXmlAreaChart(QXmlStreamWriter &writer) const;
void saveXmlDoughnutChart(QXmlStreamWriter &writer) const;
void saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) const;
void saveXmlAxes(QXmlStreamWriter &writer) const;
Chart::ChartType chartType;
QList<QSharedPointer<XlsxSeries> > seriesList;
QList<QSharedPointer<XlsxAxis> > axisList;
AbstractSheet *sheet;
};
} // namespace QXlsx
#endif // QXLSX_CHART_P_H

View File

@ -0,0 +1,159 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxchartsheet.h"
#include "xlsxchartsheet_p.h"
#include "xlsxworkbook.h"
#include "xlsxutility_p.h"
#include "xlsxdrawing_p.h"
#include "xlsxdrawinganchor_p.h"
#include "xlsxchart.h"
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QDir>
QT_BEGIN_NAMESPACE_XLSX
ChartsheetPrivate::ChartsheetPrivate(Chartsheet *p, Chartsheet::CreateFlag flag)
: AbstractSheetPrivate(p, flag), chart(0)
{
}
ChartsheetPrivate::~ChartsheetPrivate()
{
}
/*!
\class Chartsheet
\inmodule QtXlsx
\brief Represent one chartsheet in the workbook.
*/
/*!
* \internal
*/
Chartsheet::Chartsheet(const QString &name, int id, Workbook *workbook, CreateFlag flag)
:AbstractSheet(name, id, workbook, new ChartsheetPrivate(this, flag))
{
setSheetType(ST_ChartSheet);
if (flag == Chartsheet::F_NewFromScratch) {
d_func()->drawing = QSharedPointer<Drawing>(new Drawing(this, flag));
DrawingAbsoluteAnchor *anchor = new DrawingAbsoluteAnchor(drawing(), DrawingAnchor::Picture);
anchor->pos = QPoint(0, 0);
anchor->ext = QSize(9293679, 6068786);
QSharedPointer<Chart> chart = QSharedPointer<Chart>(new Chart(this, flag));
chart->setChartType(Chart::CT_Bar);
anchor->setObjectGraphicFrame(chart);
d_func()->chart = chart.data();
}
}
/*!
* \internal
*
* Make a copy of this sheet.
*/
Chartsheet *Chartsheet::copy(const QString &distName, int distId) const
{
//:Todo
Q_UNUSED(distName)
Q_UNUSED(distId)
return 0;
}
/*!
* Destroys this workssheet.
*/
Chartsheet::~Chartsheet()
{
}
/*!
* Returns the chart object of the sheet.
*/
Chart *Chartsheet::chart()
{
Q_D(Chartsheet);
return d->chart;
}
void Chartsheet::saveToXmlFile(QIODevice *device) const
{
Q_D(const Chartsheet);
d->relationships->clear();
QXmlStreamWriter writer(device);
writer.writeStartDocument(QStringLiteral("1.0"), true);
writer.writeDefaultNamespace(QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main"));
writer.writeNamespace(QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), QStringLiteral("r"));
writer.writeStartElement(QStringLiteral("chartsheet"));
writer.writeStartElement(QStringLiteral("sheetViews"));
writer.writeEmptyElement(QStringLiteral("sheetView"));
writer.writeAttribute(QStringLiteral("workbookViewId"), QString::number(0));
writer.writeAttribute(QStringLiteral("zoomToFit"), QStringLiteral("1"));
writer.writeEndElement(); //sheetViews
int idx = d->workbook->drawings().indexOf(d->drawing.data());
d->relationships->addWorksheetRelationship(QStringLiteral("/drawing"), QStringLiteral("../drawings/drawing%1.xml").arg(idx+1));
writer.writeEmptyElement(QStringLiteral("drawing"));
writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(d->relationships->count()));
writer.writeEndElement();//chartsheet
writer.writeEndDocument();
}
bool Chartsheet::loadFromXmlFile(QIODevice *device)
{
Q_D(Chartsheet);
QXmlStreamReader reader(device);
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("drawing")) {
QString rId = reader.attributes().value(QStringLiteral("r:id")).toString();
QString name = d->relationships->getRelationshipById(rId).target;
QString path = QDir::cleanPath(splitPath(filePath())[0] + QLatin1String("/") + name);
d->drawing = QSharedPointer<Drawing>(new Drawing(this, F_LoadFromExists));
d->drawing->setFilePath(path);
}
}
}
return true;
}
QT_END_NAMESPACE_XLSX

View File

@ -0,0 +1,56 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXCHARTSHEET_H
#define XLSXCHARTSHEET_H
#include "xlsxabstractsheet.h"
#include <QStringList>
#include <QSharedPointer>
QT_BEGIN_NAMESPACE_XLSX
class Workbook;
class DocumentPrivate;
class ChartsheetPrivate;
class Chart;
class Q_XLSX_EXPORT Chartsheet : public AbstractSheet
{
Q_DECLARE_PRIVATE(Chartsheet)
public:
~Chartsheet();
Chart *chart();
private:
friend class DocumentPrivate;
friend class Workbook;
Chartsheet(const QString &sheetName, int sheetId, Workbook *book, CreateFlag flag);
Chartsheet *copy(const QString &distName, int distId) const;
void saveToXmlFile(QIODevice *device) const;
bool loadFromXmlFile(QIODevice *device);
};
QT_END_NAMESPACE_XLSX
#endif // XLSXCHARTSHEET_H

View File

@ -0,0 +1,56 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXCHARTSHEET_P_H
#define XLSXCHARTSHEET_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxglobal.h"
#include "xlsxchartsheet.h"
#include "xlsxabstractsheet_p.h"
namespace QXlsx {
class XLSX_AUTOTEST_EXPORT ChartsheetPrivate : public AbstractSheetPrivate
{
Q_DECLARE_PUBLIC(Chartsheet)
public:
ChartsheetPrivate(Chartsheet *p, Chartsheet::CreateFlag flag);
~ChartsheetPrivate();
Chart *chart;
};
}
#endif // XLSXCHARTSHEET_P_H

View File

@ -0,0 +1,198 @@
#include "xlsxcolor_p.h"
#include "xlsxstyles_p.h"
#include "xlsxutility_p.h"
#include <QDataStream>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QDebug>
namespace QXlsx {
XlsxColor::XlsxColor(const QColor &color)
{
if (color.isValid())
val.setValue(color);
}
XlsxColor::XlsxColor(const QString &theme, const QString &tint)
:val(QStringList()<<theme<<tint)
{
}
XlsxColor::XlsxColor(int index)
:val(index)
{
}
bool XlsxColor::isRgbColor() const
{
if (val.userType() == qMetaTypeId<QColor>() && val.value<QColor>().isValid())
return true;
return false;
}
bool XlsxColor::isIndexedColor() const
{
return val.userType() == QMetaType::Int;
}
bool XlsxColor::isThemeColor() const
{
return val.userType() == QMetaType::QStringList;
}
bool XlsxColor::isInvalid() const
{
return !val.isValid();
}
QColor XlsxColor::rgbColor() const
{
if (isRgbColor())
return val.value<QColor>();
return QColor();
}
int XlsxColor::indexedColor() const
{
if (isIndexedColor())
return val.toInt();
return -1;
}
QStringList XlsxColor::themeColor() const
{
if (isThemeColor())
return val.toStringList();
return QStringList();
}
bool XlsxColor::saveToXml(QXmlStreamWriter &writer, const QString &node) const
{
if (!node.isEmpty())
writer.writeEmptyElement(node); //color, bgColor, fgColor
else
writer.writeEmptyElement(QStringLiteral("color"));
if (val.userType() == qMetaTypeId<QColor>()) {
writer.writeAttribute(QStringLiteral("rgb"), XlsxColor::toARGBString(val.value<QColor>()));
} else if (val.userType() == QMetaType::QStringList) {
QStringList themes = val.toStringList();
writer.writeAttribute(QStringLiteral("theme"), themes[0]);
if (!themes[1].isEmpty())
writer.writeAttribute(QStringLiteral("tint"), themes[1]);
} else if (val.userType() == QMetaType::Int) {
writer.writeAttribute(QStringLiteral("indexed"), val.toString());
} else {
writer.writeAttribute(QStringLiteral("auto"), QStringLiteral("1"));
}
return true;
}
bool XlsxColor::loadFromXml(QXmlStreamReader &reader)
{
QXmlStreamAttributes attributes = reader.attributes();
if (attributes.hasAttribute(QLatin1String("rgb"))) {
QString colorString = attributes.value(QLatin1String("rgb")).toString();
val.setValue(fromARGBString(colorString));
} else if (attributes.hasAttribute(QLatin1String("indexed"))) {
int index = attributes.value(QLatin1String("indexed")).toString().toInt();
val.setValue(index);
} else if (attributes.hasAttribute(QLatin1String("theme"))) {
QString theme = attributes.value(QLatin1String("theme")).toString();
QString tint = attributes.value(QLatin1String("tint")).toString();
val.setValue(QStringList()<<theme<<tint);
}
return true;
}
XlsxColor::operator QVariant() const
{
return QVariant(qMetaTypeId<XlsxColor>(), this);
}
QColor XlsxColor::fromARGBString(const QString &c)
{
Q_ASSERT(c.length() == 8);
QColor color;
color.setAlpha(c.mid(0, 2).toInt(0, 16));
color.setRed(c.mid(2, 2).toInt(0, 16));
color.setGreen(c.mid(4, 2).toInt(0, 16));
color.setBlue(c.mid(6, 2).toInt(0, 16));
return color;
}
QString XlsxColor::toARGBString(const QColor &c)
{
QString color;
color.sprintf("%02X%02X%02X%02X", c.alpha(), c.red(), c.green(), c.blue());
return color;
}
#if !defined(QT_NO_DATASTREAM)
QDataStream &operator<<(QDataStream &s, const XlsxColor &color)
{
if (color.isInvalid())
s<<0;
else if (color.isRgbColor())
s<<1<<color.rgbColor();
else if (color.isIndexedColor())
s<<2<<color.indexedColor();
else if (color.isThemeColor())
s<<3<<color.themeColor();
else
s<<4;
return s;
}
QDataStream &operator>>(QDataStream &s, XlsxColor &color)
{
int marker(4);
s>>marker;
if (marker == 0) {
color = XlsxColor();
} else if (marker == 1) {
QColor c;
s>>c;
color = XlsxColor(c);
} else if (marker == 2) {
int indexed;
s>>indexed;
color = XlsxColor(indexed);
} else if (marker == 3) {
QStringList list;
s>>list;
color = XlsxColor(list[0], list[1]);
}
return s;
}
#endif
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const XlsxColor &c)
{
if (c.isInvalid())
dbg.nospace() << "XlsxColor(invalid)";
else if (c.isRgbColor())
dbg.nospace() << c.rgbColor();
else if (c.isIndexedColor())
dbg.nospace() << "XlsxColor(indexed," << c.indexedColor() << ")";
else if (c.isThemeColor())
dbg.nospace() << "XlsxColor(theme," << c.themeColor().join(QLatin1Char(':')) << ")";
return dbg.space();
}
#endif
} // namespace QXlsx

View File

@ -0,0 +1,92 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_XLSXCOLOR_P_H
#define QXLSX_XLSXCOLOR_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxglobal.h"
#include <QVariant>
#include <QColor>
class QXmlStreamWriter;
class QXmlStreamReader;
namespace QXlsx {
class Styles;
class Q_XLSX_EXPORT XlsxColor
{
public:
explicit XlsxColor(const QColor &color = QColor());
explicit XlsxColor(const QString &theme, const QString &tint=QString());
explicit XlsxColor (int index);
bool isThemeColor() const;
bool isIndexedColor() const;
bool isRgbColor() const;
bool isInvalid() const;
QColor rgbColor() const;
int indexedColor() const;
QStringList themeColor() const;
operator QVariant() const;
static QColor fromARGBString(const QString &c);
static QString toARGBString(const QColor &c);
bool saveToXml(QXmlStreamWriter &writer, const QString &node=QString()) const;
bool loadFromXml(QXmlStreamReader &reader);
private:
QVariant val;
};
#if !defined(QT_NO_DATASTREAM)
Q_XLSX_EXPORT QDataStream &operator<<(QDataStream &, const XlsxColor &);
Q_XLSX_EXPORT QDataStream &operator>>(QDataStream &, XlsxColor &);
#endif
#ifndef QT_NO_DEBUG_STREAM
Q_XLSX_EXPORT QDebug operator<<(QDebug dbg, const XlsxColor &c);
#endif
} // namespace QXlsx
Q_DECLARE_METATYPE(QXlsx::XlsxColor)
#endif // QXLSX_XLSXCOLOR_P_H

View File

@ -0,0 +1,735 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxconditionalformatting.h"
#include "xlsxconditionalformatting_p.h"
#include "xlsxworksheet.h"
#include "xlsxcellrange.h"
#include "xlsxstyles_p.h"
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QDebug>
QT_BEGIN_NAMESPACE_XLSX
ConditionalFormattingPrivate::ConditionalFormattingPrivate()
{
}
ConditionalFormattingPrivate::ConditionalFormattingPrivate(const ConditionalFormattingPrivate &other)
:QSharedData(other)
{
}
ConditionalFormattingPrivate::~ConditionalFormattingPrivate()
{
}
void ConditionalFormattingPrivate::writeCfVo(QXmlStreamWriter &writer, const XlsxCfVoData &cfvo) const
{
writer.writeEmptyElement(QStringLiteral("cfvo"));
QString type;
switch(cfvo.type) {
case ConditionalFormatting::VOT_Formula: type=QStringLiteral("formula"); break;
case ConditionalFormatting::VOT_Max: type=QStringLiteral("max"); break;
case ConditionalFormatting::VOT_Min: type=QStringLiteral("min"); break;
case ConditionalFormatting::VOT_Num: type=QStringLiteral("num"); break;
case ConditionalFormatting::VOT_Percent: type=QStringLiteral("percent"); break;
case ConditionalFormatting::VOT_Percentile: type=QStringLiteral("percentile"); break;
default: break;
}
writer.writeAttribute(QStringLiteral("type"), type);
writer.writeAttribute(QStringLiteral("val"), cfvo.value);
if (!cfvo.gte)
writer.writeAttribute(QStringLiteral("gte"), QStringLiteral("0"));
}
/*!
* \class ConditionalFormatting
* \brief Conditional formatting for single cell or ranges
* \inmodule QtXlsx
*
* The conditional formatting can be applied to a single cell or ranges of cells.
*/
/*!
\enum ConditionalFormatting::HighlightRuleType
\value Highlight_LessThan
\value Highlight_LessThanOrEqual
\value Highlight_Equal
\value Highlight_NotEqual
\value Highlight_GreaterThanOrEqual
\value Highlight_GreaterThan
\value Highlight_Between
\value Highlight_NotBetween
\value Highlight_ContainsText
\value Highlight_NotContainsText
\value Highlight_BeginsWith
\value Highlight_EndsWith
\value Highlight_TimePeriod
\value Highlight_Duplicate
\value Highlight_Unique
\value Highlight_Blanks
\value Highlight_NoBlanks
\value Highlight_Errors
\value Highlight_NoErrors
\value Highlight_Top
\value Highlight_TopPercent
\value Highlight_Bottom
\value Highlight_BottomPercent
\value Highlight_AboveAverage
\value Highlight_AboveOrEqualAverage
\value Highlight_BelowAverage
\value Highlight_BelowOrEqualAverage
\value Highlight_AboveStdDev1
\value Highlight_AboveStdDev2
\value Highlight_AboveStdDev3
\value Highlight_BelowStdDev1
\value Highlight_BelowStdDev2
\value Highlight_BelowStdDev3
\value Highlight_Expression
*/
/*!
\enum ConditionalFormatting::ValueObjectType
\value VOT_Formula
\value VOT_Max
\value VOT_Min
\value VOT_Num
\value VOT_Percent
\value VOT_Percentile
*/
/*!
Construct a conditional formatting object
*/
ConditionalFormatting::ConditionalFormatting()
:d(new ConditionalFormattingPrivate())
{
}
/*!
Constructs a copy of \a other.
*/
ConditionalFormatting::ConditionalFormatting(const ConditionalFormatting &other)
:d(other.d)
{
}
/*!
Assigns \a other to this conditional formatting and returns a reference to
this conditional formatting.
*/
ConditionalFormatting &ConditionalFormatting::operator=(const ConditionalFormatting &other)
{
this->d = other.d;
return *this;
}
/*!
* Destroy the object.
*/
ConditionalFormatting::~ConditionalFormatting()
{
}
/*!
* Add a hightlight rule with the given \a type, \a formula1, \a formula2,
* \a format and \a stopIfTrue.
* Return false if failed.
*/
bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type, const QString &formula1, const QString &formula2, const Format &format, bool stopIfTrue)
{
if (format.isEmpty())
return false;
bool skipFormula = false;
QSharedPointer<XlsxCfRuleData> cfRule(new XlsxCfRuleData);
if (type >= Highlight_LessThan && type <= Highlight_NotBetween) {
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("cellIs");
QString op;
switch (type) {
case Highlight_Between: op = QStringLiteral("between"); break;
case Highlight_Equal: op = QStringLiteral("equal"); break;
case Highlight_GreaterThan: op = QStringLiteral("greaterThan"); break;
case Highlight_GreaterThanOrEqual: op = QStringLiteral("greaterThanOrEqual"); break;
case Highlight_LessThan: op = QStringLiteral("lessThan"); break;
case Highlight_LessThanOrEqual: op = QStringLiteral("lessThanOrEqual"); break;
case Highlight_NotBetween: op = QStringLiteral("notBetween"); break;
case Highlight_NotEqual: op = QStringLiteral("notEqual"); break;
default: break;
}
cfRule->attrs[XlsxCfRuleData::A_operator] = op;
} else if (type >= Highlight_ContainsText && type <= Highlight_EndsWith) {
if (type == Highlight_ContainsText) {
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsText");
cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("containsText");
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("NOT(ISERROR(SEARCH(\"%1\",%2)))").arg(formula1);
} else if (type == Highlight_NotContainsText) {
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsText");
cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("notContains");
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("ISERROR(SEARCH(\"%2\",%1))").arg(formula1);
} else if (type == Highlight_BeginsWith) {
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("beginsWith");
cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("beginsWith");
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEFT(%2,LEN(\"%1\"))=\"%1\"").arg(formula1);
} else {
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("endsWith");
cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("endsWith");
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("RIGHT(%2,LEN(\"%1\"))=\"%1\"").arg(formula1);
}
cfRule->attrs[XlsxCfRuleData::A_text] = formula1;
skipFormula = true;
} else if (type == Highlight_TimePeriod) {
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("timePeriod");
//:Todo
return false;
} else if (type == Highlight_Duplicate) {
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("duplicateValues");
} else if (type == Highlight_Unique) {
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("uniqueValues");
} else if (type == Highlight_Errors) {
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsErrors");
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("ISERROR(%1)");
skipFormula = true;
} else if (type == Highlight_NoErrors) {
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsErrors");
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("NOT(ISERROR(%1))");
skipFormula = true;
} else if (type == Highlight_Blanks) {
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsBlanks");
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEN(TRIM(%1))=0");
skipFormula = true;
} else if (type == Highlight_NoBlanks) {
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsBlanks");
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEN(TRIM(%1))>0");
skipFormula = true;
} else if (type >= Highlight_Top && type <= Highlight_BottomPercent) {
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("top10");
if (type == Highlight_Bottom || type == Highlight_BottomPercent)
cfRule->attrs[XlsxCfRuleData::A_bottom] = QStringLiteral("1");
if (type == Highlight_TopPercent || type == Highlight_BottomPercent)
cfRule->attrs[XlsxCfRuleData::A_percent] = QStringLiteral("1");
cfRule->attrs[XlsxCfRuleData::A_rank] = !formula1.isEmpty() ? formula1 : QStringLiteral("10");
skipFormula = true;
} else if (type >= Highlight_AboveAverage && type <= Highlight_BelowStdDev3) {
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("aboveAverage");
if (type >= Highlight_BelowAverage && type <= Highlight_BelowStdDev3)
cfRule->attrs[XlsxCfRuleData::A_aboveAverage] = QStringLiteral("0");
if (type == Highlight_AboveOrEqualAverage || type == Highlight_BelowOrEqualAverage)
cfRule->attrs[XlsxCfRuleData::A_equalAverage] = QStringLiteral("1");
if (type == Highlight_AboveStdDev1 || type == Highlight_BelowStdDev1)
cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("1");
else if (type == Highlight_AboveStdDev2 || type == Highlight_BelowStdDev2)
cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("2");
else if (type == Highlight_AboveStdDev3 || type == Highlight_BelowStdDev3)
cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("3");
} else if (type == Highlight_Expression){
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("expression");
} else {
return false;
}
cfRule->dxfFormat = format;
if (stopIfTrue)
cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true;
if (!skipFormula) {
if (!formula1.isEmpty())
cfRule->attrs[XlsxCfRuleData::A_formula1] = formula1.startsWith(QLatin1String("=")) ? formula1.mid(1) : formula1;
if (!formula2.isEmpty())
cfRule->attrs[XlsxCfRuleData::A_formula2] = formula2.startsWith(QLatin1String("=")) ? formula2.mid(1) : formula2;
}
d->cfRules.append(cfRule);
return true;
}
/*!
* \overload
*
* Add a hightlight rule with the given \a type \a format and \a stopIfTrue.
*/
bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type, const Format &format, bool stopIfTrue)
{
if ((type >= Highlight_AboveAverage && type <= Highlight_BelowStdDev3)
|| (type >= Highlight_Duplicate && type <= Highlight_NoErrors)) {
return addHighlightCellsRule(type, QString(), QString(), format, stopIfTrue);
}
return false;
}
/*!
* \overload
*
* Add a hightlight rule with the given \a type, \a formula, \a format and \a stopIfTrue.
* Return false if failed.
*/
bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type, const QString &formula, const Format &format, bool stopIfTrue)
{
if (type == Highlight_Between || type == Highlight_NotBetween)
return false;
return addHighlightCellsRule(type, formula, QString(), format, stopIfTrue);
}
/*!
* Add a dataBar rule with the given \a color, \a type1, \a val1
* , \a type2, \a val2, \a showData and \a stopIfTrue.
* Return false if failed.
*/
bool ConditionalFormatting::addDataBarRule(const QColor &color, ValueObjectType type1, const QString &val1, ValueObjectType type2, const QString &val2, bool showData, bool stopIfTrue)
{
QSharedPointer<XlsxCfRuleData> cfRule(new XlsxCfRuleData);
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("dataBar");
cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(color);
if (stopIfTrue)
cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true;
if (!showData)
cfRule->attrs[XlsxCfRuleData::A_hideData] = true;
XlsxCfVoData cfvo1(type1, val1);
XlsxCfVoData cfvo2(type2, val2);
cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1);
cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2);
d->cfRules.append(cfRule);
return true;
}
/*!
* \overload
* Add a dataBar rule with the given \a color, \a showData and \a stopIfTrue.
*/
bool ConditionalFormatting::addDataBarRule(const QColor &color, bool showData, bool stopIfTrue)
{
return addDataBarRule(color, VOT_Min, QStringLiteral("0"), VOT_Max, QStringLiteral("0"), showData, stopIfTrue);
}
/*!
* Add a colorScale rule with the given \a minColor, \a maxColor and \a stopIfTrue.
* Return false if failed.
*/
bool ConditionalFormatting::add2ColorScaleRule(const QColor &minColor, const QColor &maxColor, bool stopIfTrue)
{
ValueObjectType type1 = VOT_Min;
ValueObjectType type2 = VOT_Max;
QString val1 = QStringLiteral("0");
QString val2 = QStringLiteral("0");
QSharedPointer<XlsxCfRuleData> cfRule(new XlsxCfRuleData);
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("colorScale");
cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(minColor);
cfRule->attrs[XlsxCfRuleData::A_color2] = XlsxColor(maxColor);
if (stopIfTrue)
cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true;
XlsxCfVoData cfvo1(type1, val1);
XlsxCfVoData cfvo2(type2, val2);
cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1);
cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2);
d->cfRules.append(cfRule);
return true;
}
/*!
* Add a colorScale rule with the given \a minColor, \a midColor, \a maxColor and \a stopIfTrue.
* Return false if failed.
*/
bool ConditionalFormatting::add3ColorScaleRule(const QColor &minColor, const QColor &midColor, const QColor &maxColor, bool stopIfTrue)
{
ValueObjectType type1 = VOT_Min;
ValueObjectType type2 = VOT_Percent;
ValueObjectType type3 = VOT_Max;
QString val1 = QStringLiteral("0");
QString val2 = QStringLiteral("50");
QString val3 = QStringLiteral("0");
QSharedPointer<XlsxCfRuleData> cfRule(new XlsxCfRuleData);
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("colorScale");
cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(minColor);
cfRule->attrs[XlsxCfRuleData::A_color2] = XlsxColor(midColor);
cfRule->attrs[XlsxCfRuleData::A_color3] = XlsxColor(maxColor);
if (stopIfTrue)
cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true;
XlsxCfVoData cfvo1(type1, val1);
XlsxCfVoData cfvo2(type2, val2);
XlsxCfVoData cfvo3(type3, val3);
cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1);
cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2);
cfRule->attrs[XlsxCfRuleData::A_cfvo3] = QVariant::fromValue(cfvo3);
d->cfRules.append(cfRule);
return true;
}
/*!
Returns the ranges on which the validation will be applied.
*/
QList<CellRange> ConditionalFormatting::ranges() const
{
return d->ranges;
}
/*!
Add the \a cell on which the conditional formatting will apply to.
*/
void ConditionalFormatting::addCell(const CellReference &cell)
{
d->ranges.append(CellRange(cell, cell));
}
/*!
\overload
Add the cell(\a row, \a col) on which the conditional formatting will apply to.
*/
void ConditionalFormatting::addCell(int row, int col)
{
d->ranges.append(CellRange(row, col, row, col));
}
/*!
\overload
Add the range(\a firstRow, \a firstCol, \a lastRow, \a lastCol) on
which the conditional formatting will apply to.
*/
void ConditionalFormatting::addRange(int firstRow, int firstCol, int lastRow, int lastCol)
{
d->ranges.append(CellRange(firstRow, firstCol, lastRow, lastCol));
}
/*!
Add the \a range on which the conditional formatting will apply to.
*/
void ConditionalFormatting::addRange(const CellRange &range)
{
d->ranges.append(range);
}
bool ConditionalFormattingPrivate::readCfRule(QXmlStreamReader &reader, XlsxCfRuleData *rule, Styles *styles)
{
Q_ASSERT(reader.name() == QLatin1String("cfRule"));
QXmlStreamAttributes attrs = reader.attributes();
if (attrs.hasAttribute(QLatin1String("type")))
rule->attrs[XlsxCfRuleData::A_type] = attrs.value(QLatin1String("type")).toString();
if (attrs.hasAttribute(QLatin1String("dxfId"))) {
int id = attrs.value(QLatin1String("dxfId")).toString().toInt();
if (styles)
rule->dxfFormat = styles->dxfFormat(id);
else
rule->dxfFormat.setDxfIndex(id);
}
rule->priority = attrs.value(QLatin1String("priority")).toString().toInt();
if (attrs.value(QLatin1String("stopIfTrue")) == QLatin1String("1")) {
//default is false
rule->attrs[XlsxCfRuleData::A_stopIfTrue] = QLatin1String("1");
}
if (attrs.value(QLatin1String("aboveAverage")) == QLatin1String("0")) {
//default is true
rule->attrs[XlsxCfRuleData::A_aboveAverage] = QLatin1String("0");
}
if (attrs.value(QLatin1String("percent")) == QLatin1String("1")) {
//default is false
rule->attrs[XlsxCfRuleData::A_percent] = QLatin1String("1");
}
if (attrs.value(QLatin1String("bottom")) == QLatin1String("1")) {
//default is false
rule->attrs[XlsxCfRuleData::A_bottom] = QLatin1String("1");
}
if (attrs.hasAttribute(QLatin1String("operator")))
rule->attrs[XlsxCfRuleData::A_operator] = attrs.value(QLatin1String("operator")).toString();
if (attrs.hasAttribute(QLatin1String("text")))
rule->attrs[XlsxCfRuleData::A_text] = attrs.value(QLatin1String("text")).toString();
if (attrs.hasAttribute(QLatin1String("timePeriod")))
rule->attrs[XlsxCfRuleData::A_timePeriod] = attrs.value(QLatin1String("timePeriod")).toString();
if (attrs.hasAttribute(QLatin1String("rank")))
rule->attrs[XlsxCfRuleData::A_rank] = attrs.value(QLatin1String("rank")).toString();
if (attrs.hasAttribute(QLatin1String("stdDev")))
rule->attrs[XlsxCfRuleData::A_stdDev] = attrs.value(QLatin1String("stdDev")).toString();
if (attrs.value(QLatin1String("equalAverage")) == QLatin1String("1")) {
//default is false
rule->attrs[XlsxCfRuleData::A_equalAverage] = QLatin1String("1");
}
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("formula")) {
QString f = reader.readElementText();
if (!rule->attrs.contains(XlsxCfRuleData::A_formula1))
rule->attrs[XlsxCfRuleData::A_formula1] = f;
else if (!rule->attrs.contains(XlsxCfRuleData::A_formula2))
rule->attrs[XlsxCfRuleData::A_formula2] = f;
else if (!rule->attrs.contains(XlsxCfRuleData::A_formula3))
rule->attrs[XlsxCfRuleData::A_formula3] = f;
} else if (reader.name() == QLatin1String("dataBar")) {
readCfDataBar(reader, rule);
} else if (reader.name() == QLatin1String("colorScale")) {
readCfColorScale(reader, rule);
}
}
if (reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == QStringLiteral("conditionalFormatting")) {
break;
}
}
return true;
}
bool ConditionalFormattingPrivate::readCfDataBar(QXmlStreamReader &reader, XlsxCfRuleData *rule)
{
Q_ASSERT(reader.name() == QLatin1String("dataBar"));
QXmlStreamAttributes attrs = reader.attributes();
if (attrs.value(QLatin1String("showValue")) == QLatin1String("0"))
rule->attrs[XlsxCfRuleData::A_hideData] = QStringLiteral("1");
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("cfvo")) {
XlsxCfVoData data;
readCfVo(reader, data);
if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo1))
rule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(data);
else
rule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(data);
} else if (reader.name() == QLatin1String("color")) {
XlsxColor color;
color.loadFromXml(reader);
rule->attrs[XlsxCfRuleData::A_color1] = color;
}
}
if (reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == QStringLiteral("dataBar")) {
break;
}
}
return true;
}
bool ConditionalFormattingPrivate::readCfColorScale(QXmlStreamReader &reader, XlsxCfRuleData *rule)
{
Q_ASSERT(reader.name() == QLatin1String("colorScale"));
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("cfvo")) {
XlsxCfVoData data;
readCfVo(reader, data);
if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo1))
rule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(data);
else if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo2))
rule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(data);
else
rule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(data);
} else if (reader.name() == QLatin1String("color")) {
XlsxColor color;
color.loadFromXml(reader);
if (!rule->attrs.contains(XlsxCfRuleData::A_color1))
rule->attrs[XlsxCfRuleData::A_color1] = color;
else if (!rule->attrs.contains(XlsxCfRuleData::A_color2))
rule->attrs[XlsxCfRuleData::A_color2] = color;
else
rule->attrs[XlsxCfRuleData::A_color3] = color;
}
}
if (reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == QStringLiteral("colorScale")) {
break;
}
}
return true;
}
bool ConditionalFormattingPrivate::readCfVo(QXmlStreamReader &reader, XlsxCfVoData &cfvo)
{
Q_ASSERT(reader.name() == QStringLiteral("cfvo"));
QXmlStreamAttributes attrs = reader.attributes();
QString type = attrs.value(QLatin1String("type")).toString();
ConditionalFormatting::ValueObjectType t;
if (type == QLatin1String("formula"))
t = ConditionalFormatting::VOT_Formula;
else if (type == QLatin1String("max"))
t = ConditionalFormatting::VOT_Max;
else if (type == QLatin1String("min"))
t = ConditionalFormatting::VOT_Min;
else if (type == QLatin1String("num"))
t = ConditionalFormatting::VOT_Num;
else if (type == QLatin1String("percent"))
t = ConditionalFormatting::VOT_Percent;
else //if (type == QLatin1String("percentile"))
t = ConditionalFormatting::VOT_Percentile;
cfvo.type = t;
cfvo.value = attrs.value(QLatin1String("val")).toString();
if (attrs.value(QLatin1String("gte")) == QLatin1String("0")) {
//default is true
cfvo.gte = false;
}
return true;
}
bool ConditionalFormatting::loadFromXml(QXmlStreamReader &reader, Styles *styles)
{
Q_ASSERT(reader.name() == QStringLiteral("conditionalFormatting"));
d->ranges.clear();
d->cfRules.clear();
QXmlStreamAttributes attrs = reader.attributes();
QString sqref = attrs.value(QLatin1String("sqref")).toString();
foreach (QString range, sqref.split(QLatin1Char(' ')))
this->addRange(range);
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("cfRule")) {
QSharedPointer<XlsxCfRuleData> cfRule(new XlsxCfRuleData);
d->readCfRule(reader, cfRule.data(), styles);
d->cfRules.append(cfRule);
}
}
if (reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == QStringLiteral("conditionalFormatting")) {
break;
}
}
return true;
}
bool ConditionalFormatting::saveToXml(QXmlStreamWriter &writer) const
{
writer.writeStartElement(QStringLiteral("conditionalFormatting"));
QStringList sqref;
foreach (CellRange range, ranges())
sqref.append(range.toString());
writer.writeAttribute(QStringLiteral("sqref"), sqref.join(QLatin1Char(' ')));
for (int i=0; i<d->cfRules.size(); ++i) {
const QSharedPointer<XlsxCfRuleData> &rule = d->cfRules[i];
writer.writeStartElement(QStringLiteral("cfRule"));
writer.writeAttribute(QStringLiteral("type"), rule->attrs[XlsxCfRuleData::A_type].toString());
if (rule->dxfFormat.dxfIndexValid())
writer.writeAttribute(QStringLiteral("dxfId"), QString::number(rule->dxfFormat.dxfIndex()));
writer.writeAttribute(QStringLiteral("priority"), QString::number(rule->priority));
if (rule->attrs.contains(XlsxCfRuleData::A_stopIfTrue))
writer.writeAttribute(QStringLiteral("stopIfTrue"), rule->attrs[XlsxCfRuleData::A_stopIfTrue].toString());
if (rule->attrs.contains(XlsxCfRuleData::A_aboveAverage))
writer.writeAttribute(QStringLiteral("aboveAverage"), rule->attrs[XlsxCfRuleData::A_aboveAverage].toString());
if (rule->attrs.contains(XlsxCfRuleData::A_percent))
writer.writeAttribute(QStringLiteral("percent"), rule->attrs[XlsxCfRuleData::A_percent].toString());
if (rule->attrs.contains(XlsxCfRuleData::A_bottom))
writer.writeAttribute(QStringLiteral("bottom"), rule->attrs[XlsxCfRuleData::A_bottom].toString());
if (rule->attrs.contains(XlsxCfRuleData::A_operator))
writer.writeAttribute(QStringLiteral("operator"), rule->attrs[XlsxCfRuleData::A_operator].toString());
if (rule->attrs.contains(XlsxCfRuleData::A_text))
writer.writeAttribute(QStringLiteral("text"), rule->attrs[XlsxCfRuleData::A_text].toString());
if (rule->attrs.contains(XlsxCfRuleData::A_timePeriod))
writer.writeAttribute(QStringLiteral("timePeriod"), rule->attrs[XlsxCfRuleData::A_timePeriod].toString());
if (rule->attrs.contains(XlsxCfRuleData::A_rank))
writer.writeAttribute(QStringLiteral("rank"), rule->attrs[XlsxCfRuleData::A_rank].toString());
if (rule->attrs.contains(XlsxCfRuleData::A_stdDev))
writer.writeAttribute(QStringLiteral("stdDev"), rule->attrs[XlsxCfRuleData::A_stdDev].toString());
if (rule->attrs.contains(XlsxCfRuleData::A_equalAverage))
writer.writeAttribute(QStringLiteral("equalAverage"), rule->attrs[XlsxCfRuleData::A_equalAverage].toString());
if (rule->attrs[XlsxCfRuleData::A_type] == QLatin1String("dataBar")) {
writer.writeStartElement(QStringLiteral("dataBar"));
if (rule->attrs.contains(XlsxCfRuleData::A_hideData))
writer.writeAttribute(QStringLiteral("showValue"), QStringLiteral("0"));
d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo1].value<XlsxCfVoData>());
d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo2].value<XlsxCfVoData>());
rule->attrs[XlsxCfRuleData::A_color1].value<XlsxColor>().saveToXml(writer);
writer.writeEndElement();//dataBar
} else if (rule->attrs[XlsxCfRuleData::A_type] == QLatin1String("colorScale")) {
writer.writeStartElement(QStringLiteral("colorScale"));
d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo1].value<XlsxCfVoData>());
d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo2].value<XlsxCfVoData>());
if (rule->attrs.contains(XlsxCfRuleData::A_cfvo3))
d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo3].value<XlsxCfVoData>());
rule->attrs[XlsxCfRuleData::A_color1].value<XlsxColor>().saveToXml(writer);
rule->attrs[XlsxCfRuleData::A_color2].value<XlsxColor>().saveToXml(writer);
if (rule->attrs.contains(XlsxCfRuleData::A_color3))
rule->attrs[XlsxCfRuleData::A_color3].value<XlsxColor>().saveToXml(writer);
writer.writeEndElement();//colorScale
}
if (rule->attrs.contains(XlsxCfRuleData::A_formula1_temp)) {
QString startCell = ranges()[0].toString().split(QLatin1Char(':'))[0];
writer.writeTextElement(QStringLiteral("formula"), rule->attrs[XlsxCfRuleData::A_formula1_temp].toString().arg(startCell));
} else if (rule->attrs.contains(XlsxCfRuleData::A_formula1)) {
writer.writeTextElement(QStringLiteral("formula"), rule->attrs[XlsxCfRuleData::A_formula1].toString());
}
if (rule->attrs.contains(XlsxCfRuleData::A_formula2))
writer.writeTextElement(QStringLiteral("formula"), rule->attrs[XlsxCfRuleData::A_formula2].toString());
if (rule->attrs.contains(XlsxCfRuleData::A_formula3))
writer.writeTextElement(QStringLiteral("formula"), rule->attrs[XlsxCfRuleData::A_formula3].toString());
writer.writeEndElement(); //cfRule
}
writer.writeEndElement(); //conditionalFormatting
return true;
}
QT_END_NAMESPACE_XLSX

View File

@ -0,0 +1,135 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_XLSXCONDITIONALFORMATTING_H
#define QXLSX_XLSXCONDITIONALFORMATTING_H
#include "xlsxglobal.h"
#include "xlsxcellrange.h"
#include "xlsxcellreference.h"
#include <QSharedDataPointer>
#include <QString>
#include <QList>
class QXmlStreamReader;
class QXmlStreamWriter;
class QColor;
class ConditionalFormattingTest;
QT_BEGIN_NAMESPACE_XLSX
class Format;
class Worksheet;
class Styles;
class ConditionalFormattingPrivate;
class Q_XLSX_EXPORT ConditionalFormatting
{
public:
enum HighlightRuleType {
Highlight_LessThan,
Highlight_LessThanOrEqual,
Highlight_Equal,
Highlight_NotEqual,
Highlight_GreaterThanOrEqual,
Highlight_GreaterThan,
Highlight_Between,
Highlight_NotBetween,
Highlight_ContainsText,
Highlight_NotContainsText,
Highlight_BeginsWith,
Highlight_EndsWith,
Highlight_TimePeriod,
Highlight_Duplicate,
Highlight_Unique,
Highlight_Blanks,
Highlight_NoBlanks,
Highlight_Errors,
Highlight_NoErrors,
Highlight_Top,
Highlight_TopPercent,
Highlight_Bottom,
Highlight_BottomPercent,
Highlight_AboveAverage,
Highlight_AboveOrEqualAverage,
Highlight_AboveStdDev1,
Highlight_AboveStdDev2,
Highlight_AboveStdDev3,
Highlight_BelowAverage,
Highlight_BelowOrEqualAverage,
Highlight_BelowStdDev1,
Highlight_BelowStdDev2,
Highlight_BelowStdDev3,
Highlight_Expression
};
enum ValueObjectType
{
VOT_Formula,
VOT_Max,
VOT_Min,
VOT_Num,
VOT_Percent,
VOT_Percentile
};
ConditionalFormatting();
ConditionalFormatting(const ConditionalFormatting &other);
~ConditionalFormatting();
bool addHighlightCellsRule(HighlightRuleType type, const Format &format, bool stopIfTrue=false);
bool addHighlightCellsRule(HighlightRuleType type, const QString &formula1, const Format &format, bool stopIfTrue=false);
bool addHighlightCellsRule(HighlightRuleType type, const QString &formula1, const QString &formula2, const Format &format, bool stopIfTrue=false);
bool addDataBarRule(const QColor &color, bool showData=true, bool stopIfTrue=false);
bool addDataBarRule(const QColor &color, ValueObjectType type1, const QString &val1, ValueObjectType type2, const QString &val2, bool showData=true, bool stopIfTrue=false);
bool add2ColorScaleRule(const QColor &minColor, const QColor &maxColor, bool stopIfTrue=false);
bool add3ColorScaleRule(const QColor &minColor, const QColor &midColor, const QColor &maxColor, bool stopIfTrue=false);
QList<CellRange> ranges() const;
void addCell(const CellReference &cell);
void addCell(int row, int col);
void addRange(int firstRow, int firstCol, int lastRow, int lastCol);
void addRange(const CellRange &range);
//needed by QSharedDataPointer!!
ConditionalFormatting &operator=(const ConditionalFormatting &other);
private:
friend class Worksheet;
friend class ::ConditionalFormattingTest;
bool saveToXml(QXmlStreamWriter &writer) const;
bool loadFromXml(QXmlStreamReader &reader, Styles *styles=0);
QSharedDataPointer<ConditionalFormattingPrivate> d;
};
QT_END_NAMESPACE_XLSX
#endif // QXLSX_XLSXCONDITIONALFORMATTING_H

View File

@ -0,0 +1,131 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXCONDITIONALFORMATTING_P_H
#define XLSXCONDITIONALFORMATTING_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxconditionalformatting.h"
#include "xlsxformat.h"
#include "xlsxcolor_p.h"
#include <QSharedData>
#include <QSharedPointer>
#include <QMap>
QT_BEGIN_NAMESPACE_XLSX
class XlsxCfVoData
{
public:
XlsxCfVoData()
:gte(true)
{
}
XlsxCfVoData(ConditionalFormatting::ValueObjectType type, const QString &value, bool gte=true)
:type(type), value(value), gte(gte)
{
}
ConditionalFormatting::ValueObjectType type;
QString value;
bool gte;
};
class XlsxCfRuleData
{
public:
enum Attribute {
A_type,
A_dxfId,
//A_priority,
A_stopIfTrue,
A_aboveAverage,
A_percent,
A_bottom,
A_operator,
A_text,
A_timePeriod,
A_rank,
A_stdDev,
A_equalAverage,
A_dxfFormat,
A_formula1,
A_formula2,
A_formula3,
A_formula1_temp,
A_color1,
A_color2,
A_color3,
A_cfvo1,
A_cfvo2,
A_cfvo3,
A_hideData
};
XlsxCfRuleData()
:priority(1)
{}
int priority;
Format dxfFormat;
QMap<int, QVariant> attrs;
};
class ConditionalFormattingPrivate : public QSharedData
{
public:
ConditionalFormattingPrivate();
ConditionalFormattingPrivate(const ConditionalFormattingPrivate &other);
~ConditionalFormattingPrivate();
void writeCfVo(QXmlStreamWriter &writer, const XlsxCfVoData& cfvo) const;
bool readCfVo(QXmlStreamReader &reader, XlsxCfVoData& cfvo);
bool readCfRule(QXmlStreamReader &reader, XlsxCfRuleData *cfRule, Styles *styles);
bool readCfDataBar(QXmlStreamReader &reader, XlsxCfRuleData *cfRule);
bool readCfColorScale(QXmlStreamReader &reader, XlsxCfRuleData *cfRule);
QList<QSharedPointer<XlsxCfRuleData> >cfRules;
QList<CellRange> ranges;
};
QT_END_NAMESPACE_XLSX
Q_DECLARE_METATYPE(QXlsx::XlsxCfVoData)
#endif // XLSXCONDITIONALFORMATTING_P_H

View File

@ -0,0 +1,205 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxcontenttypes_p.h"
#include <QXmlStreamWriter>
#include <QXmlStreamReader>
#include <QFile>
#include <QMapIterator>
#include <QBuffer>
#include <QDebug>
namespace QXlsx {
ContentTypes::ContentTypes(CreateFlag flag)
:AbstractOOXmlFile(flag)
{
m_package_prefix = QStringLiteral("application/vnd.openxmlformats-package.");
m_document_prefix = QStringLiteral("application/vnd.openxmlformats-officedocument.");
m_defaults.insert(QStringLiteral("rels"), m_package_prefix + QStringLiteral("relationships+xml"));
m_defaults.insert(QStringLiteral("xml"), QStringLiteral("application/xml"));
}
void ContentTypes::addDefault(const QString &key, const QString &value)
{
m_defaults.insert(key, value);
}
void ContentTypes::addOverride(const QString &key, const QString &value)
{
m_overrides.insert(key, value);
}
void ContentTypes::addDocPropApp()
{
addOverride(QStringLiteral("/docProps/app.xml"), m_document_prefix + QStringLiteral("extended-properties+xml"));
}
void ContentTypes::addDocPropCore()
{
addOverride(QStringLiteral("/docProps/core.xml"), m_package_prefix + QStringLiteral("core-properties+xml"));
}
void ContentTypes::addStyles()
{
addOverride(QStringLiteral("/xl/styles.xml"), m_document_prefix + QStringLiteral("spreadsheetml.styles+xml"));
}
void ContentTypes::addTheme()
{
addOverride(QStringLiteral("/xl/theme/theme1.xml"), m_document_prefix + QStringLiteral("theme+xml"));
}
void ContentTypes::addWorkbook()
{
addOverride(QStringLiteral("/xl/workbook.xml"), m_document_prefix + QStringLiteral("spreadsheetml.sheet.main+xml"));
}
void ContentTypes::addWorksheetName(const QString &name)
{
addOverride(QStringLiteral("/xl/worksheets/%1.xml").arg(name), m_document_prefix + QStringLiteral("spreadsheetml.worksheet+xml"));
}
void ContentTypes::addChartsheetName(const QString &name)
{
addOverride(QStringLiteral("/xl/chartsheets/%1.xml").arg(name), m_document_prefix + QStringLiteral("spreadsheetml.chartsheet+xml"));
}
void ContentTypes::addDrawingName(const QString &name)
{
addOverride(QStringLiteral("/xl/drawings/%1.xml").arg(name), m_document_prefix + QStringLiteral("drawing+xml"));
}
void ContentTypes::addChartName(const QString &name)
{
addOverride(QStringLiteral("/xl/charts/%1.xml").arg(name), m_document_prefix + QStringLiteral("drawingml.chart+xml"));
}
void ContentTypes::addCommentName(const QString &name)
{
addOverride(QStringLiteral("/xl/%1.xml").arg(name), m_document_prefix + QStringLiteral("spreadsheetml.comments+xml"));
}
void ContentTypes::addTableName(const QString &name)
{
addOverride(QStringLiteral("/xl/tables/%1.xml").arg(name), m_document_prefix + QStringLiteral("spreadsheetml.table+xml"));
}
void ContentTypes::addExternalLinkName(const QString &name)
{
addOverride(QStringLiteral("/xl/externalLinks/%1.xml").arg(name), m_document_prefix + QStringLiteral("spreadsheetml.externalLink+xml"));
}
void ContentTypes::addSharedString()
{
addOverride(QStringLiteral("/xl/sharedStrings.xml"), m_document_prefix + QStringLiteral("spreadsheetml.sharedStrings+xml"));
}
void ContentTypes::addVmlName()
{
addOverride(QStringLiteral("vml"), m_document_prefix + QStringLiteral("vmlDrawing"));
}
void ContentTypes::addCalcChain()
{
addOverride(QStringLiteral("/xl/calcChain.xml"), m_document_prefix + QStringLiteral("spreadsheetml.calcChain+xml"));
}
void ContentTypes::addVbaProject()
{
//:TODO
addOverride(QStringLiteral("bin"), QStringLiteral("application/vnd.ms-office.vbaProject"));
}
void ContentTypes::clearOverrides()
{
m_overrides.clear();
}
void ContentTypes::saveToXmlFile(QIODevice *device) const
{
QXmlStreamWriter writer(device);
writer.writeStartDocument(QStringLiteral("1.0"), true);
writer.writeStartElement(QStringLiteral("Types"));
writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/package/2006/content-types"));
{
QMapIterator<QString, QString> it(m_defaults);
while (it.hasNext()) {
it.next();
writer.writeStartElement(QStringLiteral("Default"));
writer.writeAttribute(QStringLiteral("Extension"), it.key());
writer.writeAttribute(QStringLiteral("ContentType"), it.value());
writer.writeEndElement();//Default
}
}
{
QMapIterator<QString, QString> it(m_overrides);
while (it.hasNext()) {
it.next();
writer.writeStartElement(QStringLiteral("Override"));
writer.writeAttribute(QStringLiteral("PartName"), it.key());
writer.writeAttribute(QStringLiteral("ContentType"), it.value());
writer.writeEndElement(); //Override
}
}
writer.writeEndElement();//Types
writer.writeEndDocument();
}
bool ContentTypes::loadFromXmlFile(QIODevice *device)
{
m_defaults.clear();
m_overrides.clear();
QXmlStreamReader reader(device);
while (!reader.atEnd()) {
QXmlStreamReader::TokenType token = reader.readNext();
if (token == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("Default")) {
QXmlStreamAttributes attrs = reader.attributes();
QString extension = attrs.value(QLatin1String("Extension")).toString();
QString type = attrs.value(QLatin1String("ContentType")).toString();
m_defaults.insert(extension, type);
} else if (reader.name() == QLatin1String("Override")) {
QXmlStreamAttributes attrs = reader.attributes();
QString partName = attrs.value(QLatin1String("PartName")).toString();
QString type = attrs.value(QLatin1String("ContentType")).toString();
m_overrides.insert(partName, type);
}
}
if (reader.hasError()) {
qDebug()<<reader.errorString();
}
}
return true;
}
} //namespace QXlsx

View File

@ -0,0 +1,88 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXCONTENTTYPES_H
#define XLSXCONTENTTYPES_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxabstractooxmlfile.h"
#include <QString>
#include <QStringList>
#include <QMap>
class QIODevice;
namespace QXlsx {
class ContentTypes : public AbstractOOXmlFile
{
public:
ContentTypes(CreateFlag flag);
void addDefault(const QString &key, const QString &value);
void addOverride(const QString &key, const QString &value);
//Convenient funcation for addOverride()
void addDocPropCore();
void addDocPropApp();
void addStyles();
void addTheme();
void addWorkbook();
void addWorksheetName(const QString &name);
void addChartsheetName(const QString &name);
void addChartName(const QString &name);
void addDrawingName(const QString &name);
void addCommentName(const QString &name);
void addTableName(const QString &name);
void addExternalLinkName(const QString &name);
void addSharedString();
void addVmlName();
void addCalcChain();
void addVbaProject();
void clearOverrides();
void saveToXmlFile(QIODevice *device) const;
bool loadFromXmlFile(QIODevice *device);
private:
QMap<QString, QString> m_defaults;
QMap<QString, QString> m_overrides;
QString m_package_prefix;
QString m_document_prefix;
};
}
#endif // XLSXCONTENTTYPES_H

View File

@ -0,0 +1,552 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxdatavalidation.h"
#include "xlsxdatavalidation_p.h"
#include "xlsxworksheet.h"
#include "xlsxcellrange.h"
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
QT_BEGIN_NAMESPACE_XLSX
DataValidationPrivate::DataValidationPrivate()
:validationType(DataValidation::None), validationOperator(DataValidation::Between)
, errorStyle(DataValidation::Stop), allowBlank(false), isPromptMessageVisible(true)
, isErrorMessageVisible(true)
{
}
DataValidationPrivate::DataValidationPrivate(DataValidation::ValidationType type, DataValidation::ValidationOperator op, const QString &formula1, const QString &formula2, bool allowBlank)
:validationType(type), validationOperator(op)
, errorStyle(DataValidation::Stop), allowBlank(allowBlank), isPromptMessageVisible(true)
, isErrorMessageVisible(true), formula1(formula1), formula2(formula2)
{
}
DataValidationPrivate::DataValidationPrivate(const DataValidationPrivate &other)
:QSharedData(other)
, validationType(DataValidation::None), validationOperator(DataValidation::Between)
, errorStyle(DataValidation::Stop), allowBlank(false), isPromptMessageVisible(true)
, isErrorMessageVisible(true)
{
}
DataValidationPrivate::~DataValidationPrivate()
{
}
/*!
* \class DataValidation
* \brief Data validation for single cell or a range
* \inmodule QtXlsx
*
* The data validation can be applied to a single cell or a range of cells.
*/
/*!
* \enum DataValidation::ValidationType
*
* The enum type defines the type of data that you wish to validate.
*
* \value None the type of data is unrestricted. This is the same as not applying a data validation.
* \value Whole restricts the cell to integer values. Means "Whole number"?
* \value Decimal restricts the cell to decimal values.
* \value List restricts the cell to a set of user specified values.
* \value Date restricts the cell to date values.
* \value Time restricts the cell to time values.
* \value TextLength restricts the cell data based on an integer string length.
* \value Custom restricts the cell based on an external Excel formula that returns a true/false value.
*/
/*!
* \enum DataValidation::ValidationOperator
*
* The enum type defines the criteria by which the data in the
* cell is validated
*
* \value Between
* \value NotBetween
* \value Equal
* \value NotEqual
* \value LessThan
* \value LessThanOrEqual
* \value GreaterThan
* \value GreaterThanOrEqual
*/
/*!
* \enum DataValidation::ErrorStyle
*
* The enum type defines the type of error dialog that
* is displayed.
*
* \value Stop
* \value Warning
* \value Information
*/
/*!
* Construct a data validation object with the given \a type, \a op, \a formula1
* \a formula2, and \a allowBlank.
*/
DataValidation::DataValidation(ValidationType type, ValidationOperator op, const QString &formula1, const QString &formula2, bool allowBlank)
:d(new DataValidationPrivate(type, op, formula1, formula2, allowBlank))
{
}
/*!
Construct a data validation object
*/
DataValidation::DataValidation()
:d(new DataValidationPrivate())
{
}
/*!
Constructs a copy of \a other.
*/
DataValidation::DataValidation(const DataValidation &other)
:d(other.d)
{
}
/*!
Assigns \a other to this validation and returns a reference to this validation.
*/
DataValidation &DataValidation::operator=(const DataValidation &other)
{
this->d = other.d;
return *this;
}
/*!
* Destroy the object.
*/
DataValidation::~DataValidation()
{
}
/*!
Returns the validation type.
*/
DataValidation::ValidationType DataValidation::validationType() const
{
return d->validationType;
}
/*!
Returns the validation operator.
*/
DataValidation::ValidationOperator DataValidation::validationOperator() const
{
return d->validationOperator;
}
/*!
Returns the validation error style.
*/
DataValidation::ErrorStyle DataValidation::errorStyle() const
{
return d->errorStyle;
}
/*!
Returns the formula1.
*/
QString DataValidation::formula1() const
{
return d->formula1;
}
/*!
Returns the formula2.
*/
QString DataValidation::formula2() const
{
return d->formula2;
}
/*!
Returns whether blank is allowed.
*/
bool DataValidation::allowBlank() const
{
return d->allowBlank;
}
/*!
Returns the error message.
*/
QString DataValidation::errorMessage() const
{
return d->errorMessage;
}
/*!
Returns the error message title.
*/
QString DataValidation::errorMessageTitle() const
{
return d->errorMessageTitle;
}
/*!
Returns the prompt message.
*/
QString DataValidation::promptMessage() const
{
return d->promptMessage;
}
/*!
Returns the prompt message title.
*/
QString DataValidation::promptMessageTitle() const
{
return d->promptMessageTitle;
}
/*!
Returns the whether prompt message is shown.
*/
bool DataValidation::isPromptMessageVisible() const
{
return d->isPromptMessageVisible;
}
/*!
Returns the whether error message is shown.
*/
bool DataValidation::isErrorMessageVisible() const
{
return d->isErrorMessageVisible;
}
/*!
Returns the ranges on which the validation will be applied.
*/
QList<CellRange> DataValidation::ranges() const
{
return d->ranges;
}
/*!
Sets the validation type to \a type.
*/
void DataValidation::setValidationType(DataValidation::ValidationType type)
{
d->validationType = type;
}
/*!
Sets the validation operator to \a op.
*/
void DataValidation::setValidationOperator(DataValidation::ValidationOperator op)
{
d->validationOperator = op;
}
/*!
Sets the error style to \a es.
*/
void DataValidation::setErrorStyle(DataValidation::ErrorStyle es)
{
d->errorStyle = es;
}
/*!
Sets the formula1 to \a formula.
*/
void DataValidation::setFormula1(const QString &formula)
{
if (formula.startsWith(QLatin1Char('=')))
d->formula1 = formula.mid(1);
else
d->formula1 = formula;
}
/*!
Sets the formulas to \a formula.
*/
void DataValidation::setFormula2(const QString &formula)
{
if (formula.startsWith(QLatin1Char('=')))
d->formula2 = formula.mid(1);
else
d->formula2 = formula;
}
/*!
Sets the error message to \a error with title \a title.
*/
void DataValidation::setErrorMessage(const QString &error, const QString &title)
{
d->errorMessage = error;
d->errorMessageTitle = title;
}
/*!
Sets the prompt message to \a prompt with title \a title.
*/
void DataValidation::setPromptMessage(const QString &prompt, const QString &title)
{
d->promptMessage = prompt;
d->promptMessageTitle = title;
}
/*!
Enable/disabe blank allow based on \a enable.
*/
void DataValidation::setAllowBlank(bool enable)
{
d->allowBlank = enable;
}
/*!
Enable/disabe prompt message visible based on \a visible.
*/
void DataValidation::setPromptMessageVisible(bool visible)
{
d->isPromptMessageVisible = visible;
}
/*!
Enable/disabe error message visible based on \a visible.
*/
void DataValidation::setErrorMessageVisible(bool visible)
{
d->isErrorMessageVisible = visible;
}
/*!
Add the \a cell on which the DataValidation will apply to.
*/
void DataValidation::addCell(const CellReference &cell)
{
d->ranges.append(CellRange(cell, cell));
}
/*!
\overload
Add the cell(\a row, \a col) on which the DataValidation will apply to.
*/
void DataValidation::addCell(int row, int col)
{
d->ranges.append(CellRange(row, col, row, col));
}
/*!
\overload
Add the range(\a firstRow, \a firstCol, \a lastRow, \a lastCol) on
which the DataValidation will apply to.
*/
void DataValidation::addRange(int firstRow, int firstCol, int lastRow, int lastCol)
{
d->ranges.append(CellRange(firstRow, firstCol, lastRow, lastCol));
}
/*!
Add the \a range on which the DataValidation will apply to.
*/
void DataValidation::addRange(const CellRange &range)
{
d->ranges.append(range);
}
/*!
* \internal
*/
bool DataValidation::saveToXml(QXmlStreamWriter &writer) const
{
static QMap<DataValidation::ValidationType, QString> typeMap;
static QMap<DataValidation::ValidationOperator, QString> opMap;
static QMap<DataValidation::ErrorStyle, QString> esMap;
if (typeMap.isEmpty()) {
typeMap.insert(DataValidation::None, QStringLiteral("none"));
typeMap.insert(DataValidation::Whole, QStringLiteral("whole"));
typeMap.insert(DataValidation::Decimal, QStringLiteral("decimal"));
typeMap.insert(DataValidation::List, QStringLiteral("list"));
typeMap.insert(DataValidation::Date, QStringLiteral("date"));
typeMap.insert(DataValidation::Time, QStringLiteral("time"));
typeMap.insert(DataValidation::TextLength, QStringLiteral("textLength"));
typeMap.insert(DataValidation::Custom, QStringLiteral("custom"));
opMap.insert(DataValidation::Between, QStringLiteral("between"));
opMap.insert(DataValidation::NotBetween, QStringLiteral("notBetween"));
opMap.insert(DataValidation::Equal, QStringLiteral("equal"));
opMap.insert(DataValidation::NotEqual, QStringLiteral("notEqual"));
opMap.insert(DataValidation::LessThan, QStringLiteral("lessThan"));
opMap.insert(DataValidation::LessThanOrEqual, QStringLiteral("lessThanOrEqual"));
opMap.insert(DataValidation::GreaterThan, QStringLiteral("greaterThan"));
opMap.insert(DataValidation::GreaterThanOrEqual, QStringLiteral("greaterThanOrEqual"));
esMap.insert(DataValidation::Stop, QStringLiteral("stop"));
esMap.insert(DataValidation::Warning, QStringLiteral("warning"));
esMap.insert(DataValidation::Information, QStringLiteral("information"));
}
writer.writeStartElement(QStringLiteral("dataValidation"));
if (validationType() != DataValidation::None)
writer.writeAttribute(QStringLiteral("type"), typeMap[validationType()]);
if (errorStyle() != DataValidation::Stop)
writer.writeAttribute(QStringLiteral("errorStyle"), esMap[errorStyle()]);
if (validationOperator() != DataValidation::Between)
writer.writeAttribute(QStringLiteral("operator"), opMap[validationOperator()]);
if (allowBlank())
writer.writeAttribute(QStringLiteral("allowBlank"), QStringLiteral("1"));
// if (dropDownVisible())
// writer.writeAttribute(QStringLiteral("showDropDown"), QStringLiteral("1"));
if (isPromptMessageVisible())
writer.writeAttribute(QStringLiteral("showInputMessage"), QStringLiteral("1"));
if (isErrorMessageVisible())
writer.writeAttribute(QStringLiteral("showErrorMessage"), QStringLiteral("1"));
if (!errorMessageTitle().isEmpty())
writer.writeAttribute(QStringLiteral("errorTitle"), errorMessageTitle());
if (!errorMessage().isEmpty())
writer.writeAttribute(QStringLiteral("error"), errorMessage());
if (!promptMessageTitle().isEmpty())
writer.writeAttribute(QStringLiteral("promptTitle"), promptMessageTitle());
if (!promptMessage().isEmpty())
writer.writeAttribute(QStringLiteral("prompt"), promptMessage());
QStringList sqref;
foreach (CellRange range, ranges())
sqref.append(range.toString());
writer.writeAttribute(QStringLiteral("sqref"), sqref.join(QLatin1Char(' ')));
if (!formula1().isEmpty())
writer.writeTextElement(QStringLiteral("formula1"), formula1());
if (!formula2().isEmpty())
writer.writeTextElement(QStringLiteral("formula2"), formula2());
writer.writeEndElement(); //dataValidation
return true;
}
/*!
* \internal
*/
DataValidation DataValidation::loadFromXml(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("dataValidation"));
static QMap<QString, DataValidation::ValidationType> typeMap;
static QMap<QString, DataValidation::ValidationOperator> opMap;
static QMap<QString, DataValidation::ErrorStyle> esMap;
if (typeMap.isEmpty()) {
typeMap.insert(QStringLiteral("none"), DataValidation::None);
typeMap.insert(QStringLiteral("whole"), DataValidation::Whole);
typeMap.insert(QStringLiteral("decimal"), DataValidation::Decimal);
typeMap.insert(QStringLiteral("list"), DataValidation::List);
typeMap.insert(QStringLiteral("date"), DataValidation::Date);
typeMap.insert(QStringLiteral("time"), DataValidation::Time);
typeMap.insert(QStringLiteral("textLength"), DataValidation::TextLength);
typeMap.insert(QStringLiteral("custom"), DataValidation::Custom);
opMap.insert(QStringLiteral("between"), DataValidation::Between);
opMap.insert(QStringLiteral("notBetween"), DataValidation::NotBetween);
opMap.insert(QStringLiteral("equal"), DataValidation::Equal);
opMap.insert(QStringLiteral("notEqual"), DataValidation::NotEqual);
opMap.insert(QStringLiteral("lessThan"), DataValidation::LessThan);
opMap.insert(QStringLiteral("lessThanOrEqual"), DataValidation::LessThanOrEqual);
opMap.insert(QStringLiteral("greaterThan"), DataValidation::GreaterThan);
opMap.insert(QStringLiteral("greaterThanOrEqual"), DataValidation::GreaterThanOrEqual);
esMap.insert(QStringLiteral("stop"), DataValidation::Stop);
esMap.insert(QStringLiteral("warning"), DataValidation::Warning);
esMap.insert(QStringLiteral("information"), DataValidation::Information);
}
DataValidation validation;
QXmlStreamAttributes attrs = reader.attributes();
QString sqref = attrs.value(QLatin1String("sqref")).toString();
foreach (QString range, sqref.split(QLatin1Char(' ')))
validation.addRange(range);
if (attrs.hasAttribute(QLatin1String("type"))) {
QString t = attrs.value(QLatin1String("type")).toString();
validation.setValidationType(typeMap.contains(t) ? typeMap[t] : DataValidation::None);
}
if (attrs.hasAttribute(QLatin1String("errorStyle"))) {
QString es = attrs.value(QLatin1String("errorStyle")).toString();
validation.setErrorStyle(esMap.contains(es) ? esMap[es] : DataValidation::Stop);
}
if (attrs.hasAttribute(QLatin1String("operator"))) {
QString op = attrs.value(QLatin1String("operator")).toString();
validation.setValidationOperator(opMap.contains(op) ? opMap[op] : DataValidation::Between);
}
if (attrs.hasAttribute(QLatin1String("allowBlank"))) {
validation.setAllowBlank(true);
} else {
validation.setAllowBlank(false);
}
if (attrs.hasAttribute(QLatin1String("showInputMessage"))) {
validation.setPromptMessageVisible(true);
} else {
validation.setPromptMessageVisible(false);
}
if (attrs.hasAttribute(QLatin1String("showErrorMessage"))) {
validation.setErrorMessageVisible(true);
} else {
validation.setErrorMessageVisible(false);
}
QString et = attrs.value(QLatin1String("errorTitle")).toString();
QString e = attrs.value(QLatin1String("error")).toString();
if (!e.isEmpty() || !et.isEmpty())
validation.setErrorMessage(e, et);
QString pt = attrs.value(QLatin1String("promptTitle")).toString();
QString p = attrs.value(QLatin1String("prompt")).toString();
if (!p.isEmpty() || !pt.isEmpty())
validation.setPromptMessage(p, pt);
//find the end
while(!(reader.name() == QLatin1String("dataValidation") && reader.tokenType() == QXmlStreamReader::EndElement)) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("formula1")) {
validation.setFormula1(reader.readElementText());
} else if (reader.name() == QLatin1String("formula2")) {
validation.setFormula2(reader.readElementText());
}
}
}
return validation;
}
QT_END_NAMESPACE_XLSX

View File

@ -0,0 +1,123 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_XLSXDATAVALIDATION_H
#define QXLSX_XLSXDATAVALIDATION_H
#include "xlsxglobal.h"
#include <QSharedDataPointer>
#include <QString>
#include <QList>
class QXmlStreamReader;
class QXmlStreamWriter;
QT_BEGIN_NAMESPACE_XLSX
class Worksheet;
class CellRange;
class CellReference;
class DataValidationPrivate;
class Q_XLSX_EXPORT DataValidation
{
public:
enum ValidationType
{
None,
Whole,
Decimal,
List,
Date,
Time,
TextLength,
Custom
};
enum ValidationOperator
{
Between,
NotBetween,
Equal,
NotEqual,
LessThan,
LessThanOrEqual,
GreaterThan,
GreaterThanOrEqual
};
enum ErrorStyle
{
Stop,
Warning,
Information
};
DataValidation();
DataValidation(ValidationType type, ValidationOperator op=Between, const QString &formula1=QString()
, const QString &formula2=QString(), bool allowBlank=false);
DataValidation(const DataValidation &other);
~DataValidation();
ValidationType validationType() const;
ValidationOperator validationOperator() const;
ErrorStyle errorStyle() const;
QString formula1() const;
QString formula2() const;
bool allowBlank() const;
QString errorMessage() const;
QString errorMessageTitle() const;
QString promptMessage() const;
QString promptMessageTitle() const;
bool isPromptMessageVisible() const;
bool isErrorMessageVisible() const;
QList<CellRange> ranges() const;
void setValidationType(ValidationType type);
void setValidationOperator(ValidationOperator op);
void setErrorStyle(ErrorStyle es);
void setFormula1(const QString &formula);
void setFormula2(const QString &formula);
void setErrorMessage(const QString &error, const QString &title=QString());
void setPromptMessage(const QString &prompt, const QString &title=QString());
void setAllowBlank(bool enable);
void setPromptMessageVisible(bool visible);
void setErrorMessageVisible(bool visible);
void addCell(const CellReference &cell);
void addCell(int row, int col);
void addRange(int firstRow, int firstCol, int lastRow, int lastCol);
void addRange(const CellRange &range);
DataValidation &operator=(const DataValidation &other);
bool saveToXml(QXmlStreamWriter &writer) const;
static DataValidation loadFromXml(QXmlStreamReader &reader);
private:
QSharedDataPointer<DataValidationPrivate> d;
};
QT_END_NAMESPACE_XLSX
#endif // QXLSX_XLSXDATAVALIDATION_H

View File

@ -0,0 +1,69 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXDATAVALIDATION_P_H
#define XLSXDATAVALIDATION_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxdatavalidation.h"
#include <QSharedData>
QT_BEGIN_NAMESPACE_XLSX
class Q_XLSX_EXPORT DataValidationPrivate : public QSharedData
{
public:
DataValidationPrivate();
DataValidationPrivate(DataValidation::ValidationType type, DataValidation::ValidationOperator op, const QString &formula1, const QString &formula2, bool allowBlank);
DataValidationPrivate(const DataValidationPrivate &other);
~DataValidationPrivate();
DataValidation::ValidationType validationType;
DataValidation::ValidationOperator validationOperator;
DataValidation::ErrorStyle errorStyle;
bool allowBlank;
bool isPromptMessageVisible;
bool isErrorMessageVisible;
QString formula1;
QString formula2;
QString errorMessage;
QString errorMessageTitle;
QString promptMessage;
QString promptMessageTitle;
QList<CellRange> ranges;
};
QT_END_NAMESPACE_XLSX
#endif // XLSXDATAVALIDATION_P_H

View File

@ -0,0 +1,157 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxdocpropsapp_p.h"
#include <QXmlStreamWriter>
#include <QXmlStreamReader>
#include <QDir>
#include <QFile>
#include <QDateTime>
#include <QVariant>
#include <QBuffer>
namespace QXlsx {
DocPropsApp::DocPropsApp(CreateFlag flag)
:AbstractOOXmlFile(flag)
{
}
void DocPropsApp::addPartTitle(const QString &title)
{
m_titlesOfPartsList.append(title);
}
void DocPropsApp::addHeadingPair(const QString &name, int value)
{
m_headingPairsList.append(qMakePair(name, value));
}
bool DocPropsApp::setProperty(const QString &name, const QString &value)
{
static QStringList validKeys;
if (validKeys.isEmpty()) {
validKeys << QStringLiteral("manager") << QStringLiteral("company");
}
if (!validKeys.contains(name))
return false;
if (value.isEmpty())
m_properties.remove(name);
else
m_properties[name] = value;
return true;
}
QString DocPropsApp::property(const QString &name) const
{
if (m_properties.contains(name))
return m_properties[name];
return QString();
}
QStringList DocPropsApp::propertyNames() const
{
return m_properties.keys();
}
void DocPropsApp::saveToXmlFile(QIODevice *device) const
{
QXmlStreamWriter writer(device);
QString vt = QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
writer.writeStartDocument(QStringLiteral("1.0"), true);
writer.writeStartElement(QStringLiteral("Properties"));
writer.writeDefaultNamespace(QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"));
writer.writeNamespace(vt, QStringLiteral("vt"));
writer.writeTextElement(QStringLiteral("Application"), QStringLiteral("Microsoft Excel"));
writer.writeTextElement(QStringLiteral("DocSecurity"), QStringLiteral("0"));
writer.writeTextElement(QStringLiteral("ScaleCrop"), QStringLiteral("false"));
writer.writeStartElement(QStringLiteral("HeadingPairs"));
writer.writeStartElement(vt, QStringLiteral("vector"));
writer.writeAttribute(QStringLiteral("size"), QString::number(m_headingPairsList.size()*2));
writer.writeAttribute(QStringLiteral("baseType"), QStringLiteral("variant"));
typedef QPair<QString,int> PairType; //Make foreach happy
foreach (PairType pair, m_headingPairsList) {
writer.writeStartElement(vt, QStringLiteral("variant"));
writer.writeTextElement(vt, QStringLiteral("lpstr"), pair.first);
writer.writeEndElement(); //vt:variant
writer.writeStartElement(vt, QStringLiteral("variant"));
writer.writeTextElement(vt, QStringLiteral("i4"), QString::number(pair.second));
writer.writeEndElement(); //vt:variant
}
writer.writeEndElement();//vt:vector
writer.writeEndElement();//HeadingPairs
writer.writeStartElement(QStringLiteral("TitlesOfParts"));
writer.writeStartElement(vt, QStringLiteral("vector"));
writer.writeAttribute(QStringLiteral("size"), QString::number(m_titlesOfPartsList.size()));
writer.writeAttribute(QStringLiteral("baseType"), QStringLiteral("lpstr"));
foreach (QString title, m_titlesOfPartsList)
writer.writeTextElement(vt, QStringLiteral("lpstr"), title);
writer.writeEndElement();//vt:vector
writer.writeEndElement();//TitlesOfParts
if (m_properties.contains(QStringLiteral("manager")))
writer.writeTextElement(QStringLiteral("Manager"), m_properties[QStringLiteral("manager")]);
//Not like "manager", "company" always exists for Excel generated file.
writer.writeTextElement(QStringLiteral("Company"), m_properties.contains(QStringLiteral("company")) ? m_properties[QStringLiteral("company")]: QString());
writer.writeTextElement(QStringLiteral("LinksUpToDate"), QStringLiteral("false"));
writer.writeTextElement(QStringLiteral("SharedDoc"), QStringLiteral("false"));
writer.writeTextElement(QStringLiteral("HyperlinksChanged"), QStringLiteral("false"));
writer.writeTextElement(QStringLiteral("AppVersion"), QStringLiteral("12.0000"));
writer.writeEndElement(); //Properties
writer.writeEndDocument();
}
bool DocPropsApp::loadFromXmlFile(QIODevice *device)
{
QXmlStreamReader reader(device);
while (!reader.atEnd()) {
QXmlStreamReader::TokenType token = reader.readNext();
if (token == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("Properties"))
continue;
if (reader.name() == QStringLiteral("Manager")) {
setProperty(QStringLiteral("manager"), reader.readElementText());
} else if (reader.name() == QStringLiteral("Company")) {
setProperty(QStringLiteral("company"), reader.readElementText());
}
}
if (reader.hasError()) {
qDebug("Error when read doc props app file.");
}
}
return true;
}
} //namespace

View File

@ -0,0 +1,72 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXDOCPROPSAPP_H
#define XLSXDOCPROPSAPP_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxglobal.h"
#include "xlsxabstractooxmlfile.h"
#include <QList>
#include <QPair>
#include <QStringList>
#include <QMap>
class QIODevice;
namespace QXlsx {
class XLSX_AUTOTEST_EXPORT DocPropsApp : public AbstractOOXmlFile
{
public:
DocPropsApp(CreateFlag flag);
void addPartTitle(const QString &title);
void addHeadingPair(const QString &name, int value);
bool setProperty(const QString &name, const QString &value);
QString property(const QString &name) const;
QStringList propertyNames() const;
void saveToXmlFile(QIODevice *device) const;
bool loadFromXmlFile(QIODevice *device);
private:
QStringList m_titlesOfPartsList;
QList<QPair<QString, int> > m_headingPairsList;
QMap<QString, QString> m_properties;
};
}
#endif // XLSXDOCPROPSAPP_H

View File

@ -0,0 +1,168 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxdocpropscore_p.h"
#include <QXmlStreamWriter>
#include <QXmlStreamReader>
#include <QDir>
#include <QFile>
#include <QDateTime>
#include <QDebug>
#include <QBuffer>
namespace QXlsx {
DocPropsCore::DocPropsCore(CreateFlag flag)
:AbstractOOXmlFile(flag)
{
}
bool DocPropsCore::setProperty(const QString &name, const QString &value)
{
static QStringList validKeys;
if (validKeys.isEmpty()) {
validKeys << QStringLiteral("title") << QStringLiteral("subject")
<< QStringLiteral("keywords") << QStringLiteral("description")
<< QStringLiteral("category") << QStringLiteral("status")
<< QStringLiteral("created") << QStringLiteral("creator");
}
if (!validKeys.contains(name))
return false;
if (value.isEmpty())
m_properties.remove(name);
else
m_properties[name] = value;
return true;
}
QString DocPropsCore::property(const QString &name) const
{
if (m_properties.contains(name))
return m_properties[name];
return QString();
}
QStringList DocPropsCore::propertyNames() const
{
return m_properties.keys();
}
void DocPropsCore::saveToXmlFile(QIODevice *device) const
{
QXmlStreamWriter writer(device);
const QString cp = QStringLiteral("http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
const QString dc = QStringLiteral("http://purl.org/dc/elements/1.1/");
const QString dcterms = QStringLiteral("http://purl.org/dc/terms/");
const QString dcmitype = QStringLiteral("http://purl.org/dc/dcmitype/");
const QString xsi = QStringLiteral("http://www.w3.org/2001/XMLSchema-instance");
writer.writeStartDocument(QStringLiteral("1.0"), true);
writer.writeStartElement(QStringLiteral("cp:coreProperties"));
writer.writeNamespace(cp, QStringLiteral("cp"));
writer.writeNamespace(dc, QStringLiteral("dc"));
writer.writeNamespace(dcterms, QStringLiteral("dcterms"));
writer.writeNamespace(dcmitype, QStringLiteral("dcmitype"));
writer.writeNamespace(xsi, QStringLiteral("xsi"));
if (m_properties.contains(QStringLiteral("title")))
writer.writeTextElement(dc, QStringLiteral("title"), m_properties[QStringLiteral("title")]);
if (m_properties.contains(QStringLiteral("subject")))
writer.writeTextElement(dc, QStringLiteral("subject"), m_properties[QStringLiteral("subject")]);
writer.writeTextElement(dc, QStringLiteral("creator"), m_properties.contains(QStringLiteral("creator")) ? m_properties[QStringLiteral("creator")] : QStringLiteral("Qt Xlsx Library"));
if (m_properties.contains(QStringLiteral("keywords")))
writer.writeTextElement(cp, QStringLiteral("keywords"), m_properties[QStringLiteral("keywords")]);
if (m_properties.contains(QStringLiteral("description")))
writer.writeTextElement(dc, QStringLiteral("description"), m_properties[QStringLiteral("description")]);
writer.writeTextElement(cp, QStringLiteral("lastModifiedBy"), m_properties.contains(QStringLiteral("creator")) ? m_properties[QStringLiteral("creator")] : QStringLiteral("Qt Xlsx Library"));
writer.writeStartElement(dcterms, QStringLiteral("created"));
writer.writeAttribute(xsi, QStringLiteral("type"), QStringLiteral("dcterms:W3CDTF"));
writer.writeCharacters(m_properties.contains(QStringLiteral("created")) ? m_properties[QStringLiteral("created")] : QDateTime::currentDateTime().toString(Qt::ISODate));
writer.writeEndElement();//dcterms:created
writer.writeStartElement(dcterms, QStringLiteral("modified"));
writer.writeAttribute(xsi, QStringLiteral("type"), QStringLiteral("dcterms:W3CDTF"));
writer.writeCharacters(QDateTime::currentDateTime().toString(Qt::ISODate));
writer.writeEndElement();//dcterms:created
if (m_properties.contains(QStringLiteral("category")))
writer.writeTextElement(cp, QStringLiteral("category"), m_properties[QStringLiteral("category")]);
if (m_properties.contains(QStringLiteral("status")))
writer.writeTextElement(cp, QStringLiteral("contentStatus"), m_properties[QStringLiteral("status")]);
writer.writeEndElement(); //cp:coreProperties
writer.writeEndDocument();
}
bool DocPropsCore::loadFromXmlFile(QIODevice *device)
{
QXmlStreamReader reader(device);
const QString cp = QStringLiteral("http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
const QString dc = QStringLiteral("http://purl.org/dc/elements/1.1/");
const QString dcterms = QStringLiteral("http://purl.org/dc/terms/");
while (!reader.atEnd()) {
QXmlStreamReader::TokenType token = reader.readNext();
if (token == QXmlStreamReader::StartElement) {
const QStringRef nsUri = reader.namespaceUri();
const QStringRef name = reader.name();
if (name == QStringLiteral("subject") && nsUri == dc) {
setProperty(QStringLiteral("subject"), reader.readElementText());
} else if (name == QStringLiteral("title") && nsUri == dc) {
setProperty(QStringLiteral("title"), reader.readElementText());
} else if (name == QStringLiteral("creator") && nsUri == dc) {
setProperty(QStringLiteral("creator"), reader.readElementText());
} else if (name == QStringLiteral("description") && nsUri == dc) {
setProperty(QStringLiteral("description"), reader.readElementText());
} else if (name == QStringLiteral("keywords") && nsUri == cp) {
setProperty(QStringLiteral("keywords"), reader.readElementText());
} else if (name == QStringLiteral("created") && nsUri == dcterms) {
setProperty(QStringLiteral("created"), reader.readElementText());
} else if (name == QStringLiteral("category") && nsUri == cp) {
setProperty(QStringLiteral("category"), reader.readElementText());
} else if (name == QStringLiteral("contentStatus") && nsUri == cp) {
setProperty(QStringLiteral("status"), reader.readElementText());
}
}
if (reader.hasError()) {
qDebug()<<"Error when read doc props core file."<<reader.errorString();
}
}
return true;
}
} //namespace

View File

@ -0,0 +1,65 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXDOCPROPSCORE_H
#define XLSXDOCPROPSCORE_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxglobal.h"
#include "xlsxabstractooxmlfile.h"
#include <QMap>
#include <QStringList>
class QIODevice;
namespace QXlsx {
class XLSX_AUTOTEST_EXPORT DocPropsCore : public AbstractOOXmlFile
{
public:
explicit DocPropsCore(CreateFlag flag);
bool setProperty(const QString &name, const QString &value);
QString property(const QString &name) const;
QStringList propertyNames() const;
void saveToXmlFile(QIODevice *device) const;
bool loadFromXmlFile(QIODevice *device);
private:
QMap<QString, QString> m_properties;
};
}
#endif // XLSXDOCPROPSCORE_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,133 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_XLSXDOCUMENT_H
#define QXLSX_XLSXDOCUMENT_H
#include "xlsxglobal.h"
#include "xlsxformat.h"
#include "xlsxworksheet.h"
#include <QObject>
#include <QVariant>
class QIODevice;
class QImage;
QT_BEGIN_NAMESPACE_XLSX
class Workbook;
class Cell;
class CellRange;
class DataValidation;
class ConditionalFormatting;
class Chart;
class CellReference;
class DocumentPrivate;
class Q_XLSX_EXPORT Document : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(Document)
public:
explicit Document(QObject *parent = 0);
Document(const QString &xlsxName, QObject *parent=0);
Document(QIODevice *device, QObject *parent=0);
~Document();
bool write(const CellReference &cell, const QVariant &value, const Format &format=Format());
bool write(int row, int col, const QVariant &value, const Format &format=Format());
QVariant read(const CellReference &cell) const;
QVariant read(int row, int col) const;
bool insertImage(int row, int col, const QImage &image);
Chart *insertChart(int row, int col, const QSize &size);
bool mergeCells(const CellRange &range, const Format &format=Format());
bool unmergeCells(const CellRange &range);
bool setColumnWidth(const CellRange &range, double width);
bool setColumnFormat(const CellRange &range, const Format &format);
bool setColumnHidden(const CellRange &range, bool hidden);
bool setColumnWidth(int column, double width);
bool setColumnFormat(int column, const Format &format);
bool setColumnHidden(int column, bool hidden);
bool setColumnWidth(int colFirst, int colLast, double width);
bool setColumnFormat(int colFirst, int colLast, const Format &format);
bool setColumnHidden(int colFirst, int colLast, bool hidden);
double columnWidth(int column);
Format columnFormat(int column);
bool isColumnHidden(int column);
bool setRowHeight(int row, double height);
bool setRowFormat(int row, const Format &format);
bool setRowHidden(int row, bool hidden);
bool setRowHeight(int rowFirst, int rowLast, double height);
bool setRowFormat(int rowFirst, int rowLast, const Format &format);
bool setRowHidden(int rowFirst, int rowLast, bool hidden);
double rowHeight(int row);
Format rowFormat(int row);
bool isRowHidden(int row);
bool groupRows(int rowFirst, int rowLast, bool collapsed = true);
bool groupColumns(int colFirst, int colLast, bool collapsed = true);
bool addDataValidation(const DataValidation &validation);
bool addConditionalFormatting(const ConditionalFormatting &cf);
Cell *cellAt(const CellReference &cell) const;
Cell *cellAt(int row, int col) const;
bool defineName(const QString &name, const QString &formula, const QString &comment=QString(), const QString &scope=QString());
CellRange dimension() const;
QString documentProperty(const QString &name) const;
void setDocumentProperty(const QString &name, const QString &property);
QStringList documentPropertyNames() const;
QStringList sheetNames() const;
bool addSheet(const QString &name = QString(), AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet);
bool insertSheet(int index, const QString &name = QString(), AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet);
bool selectSheet(const QString &name);
bool renameSheet(const QString &oldName, const QString &newName);
bool copySheet(const QString &srcName, const QString &distName = QString());
bool moveSheet(const QString &srcName, int distIndex);
bool deleteSheet(const QString &name);
Workbook *workbook() const;
AbstractSheet *sheet(const QString &sheetName) const;
AbstractSheet *currentSheet() const;
Worksheet *currentWorksheet() const;
bool save() const;
bool saveAs(const QString &xlsXname) const;
bool saveAs(QIODevice *device) const;
private:
Q_DISABLE_COPY(Document)
DocumentPrivate * const d_ptr;
};
QT_END_NAMESPACE_XLSX
#endif // QXLSX_XLSXDOCUMENT_H

View File

@ -0,0 +1,69 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXDOCUMENT_P_H
#define XLSXDOCUMENT_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxdocument.h"
#include "xlsxworkbook.h"
#include "xlsxcontenttypes_p.h"
#include <QMap>
namespace QXlsx {
class DocumentPrivate
{
Q_DECLARE_PUBLIC(Document)
public:
DocumentPrivate(Document *p);
void init();
bool loadPackage(QIODevice *device);
bool savePackage(QIODevice *device) const;
Document *q_ptr;
const QString defaultPackageName; //default name when package name not specified
QString packageName; //name of the .xlsx file
QMap<QString, QString> documentProperties; //core, app and custom properties
QSharedPointer<Workbook> workbook;
QSharedPointer<ContentTypes> contentTypes;
};
}
#endif // XLSXDOCUMENT_P_H

View File

@ -0,0 +1,87 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxdrawing_p.h"
#include "xlsxdrawinganchor_p.h"
#include "xlsxabstractsheet.h"
#include <QXmlStreamWriter>
#include <QXmlStreamReader>
#include <QBuffer>
namespace QXlsx {
Drawing::Drawing(AbstractSheet *sheet, CreateFlag flag)
:AbstractOOXmlFile(flag), sheet(sheet)
{
workbook = sheet->workbook();
}
Drawing::~Drawing()
{
qDeleteAll(anchors);
}
void Drawing::saveToXmlFile(QIODevice *device) const
{
relationships()->clear();
QXmlStreamWriter writer(device);
writer.writeStartDocument(QStringLiteral("1.0"), true);
writer.writeStartElement(QStringLiteral("xdr:wsDr"));
writer.writeAttribute(QStringLiteral("xmlns:xdr"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"));
writer.writeAttribute(QStringLiteral("xmlns:a"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/main"));
foreach (DrawingAnchor *anchor, anchors)
anchor->saveToXml(writer);
writer.writeEndElement();//xdr:wsDr
writer.writeEndDocument();
}
bool Drawing::loadFromXmlFile(QIODevice *device)
{
QXmlStreamReader reader(device);
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("absoluteAnchor")) {
DrawingAbsoluteAnchor * anchor = new DrawingAbsoluteAnchor(this);
anchor->loadFromXml(reader);
} else if (reader.name() == QLatin1String("oneCellAnchor")) {
DrawingOneCellAnchor * anchor = new DrawingOneCellAnchor(this);
anchor->loadFromXml(reader);
} else if (reader.name() == QLatin1String("twoCellAnchor")) {
DrawingTwoCellAnchor * anchor = new DrawingTwoCellAnchor(this);
anchor->loadFromXml(reader);
}
}
}
return true;
}
} // namespace QXlsx

View File

@ -0,0 +1,72 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_DRAWING_H
#define QXLSX_DRAWING_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxrelationships_p.h"
#include "xlsxabstractooxmlfile.h"
#include <QList>
#include <QString>
#include <QSharedPointer>
class QIODevice;
class QXmlStreamWriter;
namespace QXlsx {
class DrawingAnchor;
class Workbook;
class AbstractSheet;
class MediaFile;
class Drawing : public AbstractOOXmlFile
{
public:
Drawing(AbstractSheet *sheet, CreateFlag flag);
~Drawing();
void saveToXmlFile(QIODevice *device) const;
bool loadFromXmlFile(QIODevice *device);
AbstractSheet *sheet;
Workbook *workbook;
QList<DrawingAnchor *> anchors;
};
} // namespace QXlsx
#endif // QXLSX_DRAWING_H

View File

@ -0,0 +1,529 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxdrawinganchor_p.h"
#include "xlsxdrawing_p.h"
#include "xlsxmediafile_p.h"
#include "xlsxchart.h"
#include "xlsxworkbook.h"
#include "xlsxutility_p.h"
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QBuffer>
#include <QDir>
namespace QXlsx {
/*
The vertices that define the position of a graphical object
within the worksheet in pixels.
+------------+------------+
| A | B |
+-----+------------+------------+
| |(x1,y1) | |
| 1 |(A1)._______|______ |
| | | | |
| | | | |
+-----+----| OBJECT |-----+
| | | | |
| 2 | |______________. |
| | | (B2)|
| | | (x2,y2)|
+---- +------------+------------+
Example of an object that covers some of the area from cell A1 to B2.
Based on the width and height of the object we need to calculate 8 vars:
col_start, row_start, col_end, row_end, x1, y1, x2, y2.
We also calculate the absolute x and y position of the top left vertex of
the object. This is required for images.
The width and height of the cells that the object occupies can be
variable and have to be taken into account.
*/
//anchor
DrawingAnchor::DrawingAnchor(Drawing *drawing, ObjectType objectType)
:m_drawing(drawing), m_objectType(objectType)
{
m_drawing->anchors.append(this);
m_id = m_drawing->anchors.size();//must be unique in one drawing{x}.xml file.
}
DrawingAnchor::~DrawingAnchor()
{
}
void DrawingAnchor::setObjectPicture(const QImage &img)
{
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
img.save(&buffer, "PNG");
m_pictureFile = QSharedPointer<MediaFile>(new MediaFile(ba, QStringLiteral("png"), QStringLiteral("image/png")));
m_drawing->workbook->addMediaFile(m_pictureFile);
m_objectType = Picture;
}
void DrawingAnchor::setObjectGraphicFrame(QSharedPointer<Chart> chart)
{
m_chartFile = chart;
m_drawing->workbook->addChartFile(chart);
m_objectType = GraphicFrame;
}
QPoint DrawingAnchor::loadXmlPos(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("pos"));
QPoint pos;
QXmlStreamAttributes attrs = reader.attributes();
pos.setX(attrs.value(QLatin1String("x")).toString().toInt());
pos.setY(attrs.value(QLatin1String("y")).toString().toInt());
return pos;
}
QSize DrawingAnchor::loadXmlExt(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("ext"));
QSize size;
QXmlStreamAttributes attrs = reader.attributes();
size.setWidth(attrs.value(QLatin1String("cx")).toString().toInt());
size.setHeight(attrs.value(QLatin1String("cy")).toString().toInt());
return size;
}
XlsxMarker DrawingAnchor::loadXmlMarker(QXmlStreamReader &reader, const QString &node)
{
Q_ASSERT(reader.name() == node);
int col = 0;
int colOffset = 0;
int row = 0;
int rowOffset = 0;
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("col")) {
col = reader.readElementText().toInt();
} else if (reader.name() == QLatin1String("colOff")) {
colOffset = reader.readElementText().toInt();
} else if (reader.name() == QLatin1String("row")) {
row = reader.readElementText().toInt();
} else if (reader.name() == QLatin1String("rowOff")) {
rowOffset = reader.readElementText().toInt();
}
} else if (reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == node) {
break;
}
}
return XlsxMarker(row, col, rowOffset, colOffset);
}
void DrawingAnchor::loadXmlObject(QXmlStreamReader &reader)
{
if (reader.name() == QLatin1String("sp")) {
//Shape
m_objectType = Shape;
loadXmlObjectShape(reader);
} else if (reader.name() == QLatin1String("grpSp")) {
//Group Shape
m_objectType = GroupShape;
loadXmlObjectGroupShape(reader);
} else if (reader.name() == QLatin1String("graphicFrame")) {
//Graphic Frame
m_objectType = GraphicFrame;
loadXmlObjectGraphicFrame(reader);
} else if (reader.name() == QLatin1String("cxnSp")) {
//Connection Shape
m_objectType = ConnectionShape;
loadXmlObjectConnectionShape(reader);
} else if (reader.name() == QLatin1String("pic")) {
//Picture
m_objectType = Picture;
loadXmlObjectPicture(reader);
}
}
void DrawingAnchor::loadXmlObjectConnectionShape(QXmlStreamReader &reader)
{
Q_UNUSED(reader)
}
void DrawingAnchor::loadXmlObjectGraphicFrame(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("graphicFrame"));
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("chart")) {
QString rId = reader.attributes().value(QLatin1String("r:id")).toString();
QString name = m_drawing->relationships()->getRelationshipById(rId).target;
QString path = QDir::cleanPath(splitPath(m_drawing->filePath())[0] + QLatin1String("/") + name);
bool exist = false;
QList<QSharedPointer<Chart> > cfs = m_drawing->workbook->chartFiles();
for (int i=0; i<cfs.size(); ++i) {
if (cfs[i]->filePath() == path) {
//already exist
exist = true;
m_chartFile = cfs[i];
}
}
if (!exist) {
m_chartFile = QSharedPointer<Chart> (new Chart(m_drawing->sheet, Chart::F_LoadFromExists));
m_chartFile->setFilePath(path);
m_drawing->workbook->addChartFile(m_chartFile);
}
}
} else if (reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == QLatin1String("graphicFrame")) {
break;
}
}
return;
}
void DrawingAnchor::loadXmlObjectGroupShape(QXmlStreamReader &reader)
{
Q_UNUSED(reader)
}
void DrawingAnchor::loadXmlObjectPicture(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("pic"));
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("blip")) {
QString rId = reader.attributes().value(QLatin1String("r:embed")).toString();
QString name = m_drawing->relationships()->getRelationshipById(rId).target;
QString path = QDir::cleanPath(splitPath(m_drawing->filePath())[0] + QLatin1String("/") + name);
bool exist = false;
QList<QSharedPointer<MediaFile> > mfs = m_drawing->workbook->mediaFiles();
for (int i=0; i<mfs.size(); ++i) {
if (mfs[i]->fileName() == path) {
//already exist
exist = true;
m_pictureFile = mfs[i];
}
}
if (!exist) {
m_pictureFile = QSharedPointer<MediaFile> (new MediaFile(path));
m_drawing->workbook->addMediaFile(m_pictureFile, true);
}
}
} else if (reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == QLatin1String("pic")) {
break;
}
}
return;
}
void DrawingAnchor::loadXmlObjectShape(QXmlStreamReader &reader)
{
Q_UNUSED(reader)
}
void DrawingAnchor::saveXmlPos(QXmlStreamWriter &writer, const QPoint &pos) const
{
writer.writeEmptyElement(QStringLiteral("xdr:pos"));
writer.writeAttribute(QStringLiteral("x"), QString::number(pos.x()));
writer.writeAttribute(QStringLiteral("y"), QString::number(pos.y()));
}
void DrawingAnchor::saveXmlExt(QXmlStreamWriter &writer, const QSize &ext) const
{
writer.writeStartElement(QStringLiteral("xdr:ext"));
writer.writeAttribute(QStringLiteral("cx"), QString::number(ext.width()));
writer.writeAttribute(QStringLiteral("cy"), QString::number(ext.height()));
writer.writeEndElement(); //xdr:ext
}
void DrawingAnchor::saveXmlMarker(QXmlStreamWriter &writer, const XlsxMarker &marker, const QString &node) const
{
writer.writeStartElement(node); //xdr:from or xdr:to
writer.writeTextElement(QStringLiteral("xdr:col"), QString::number(marker.col()));
writer.writeTextElement(QStringLiteral("xdr:colOff"), QString::number(marker.colOff()));
writer.writeTextElement(QStringLiteral("xdr:row"), QString::number(marker.row()));
writer.writeTextElement(QStringLiteral("xdr:rowOff"), QString::number(marker.rowOff()));
writer.writeEndElement();
}
void DrawingAnchor::saveXmlObject(QXmlStreamWriter &writer) const
{
if (m_objectType == Picture)
saveXmlObjectPicture(writer);
else if (m_objectType == ConnectionShape)
saveXmlObjectConnectionShape(writer);
else if (m_objectType == GraphicFrame)
saveXmlObjectGraphicFrame(writer);
else if (m_objectType == GroupShape)
saveXmlObjectGroupShape(writer);
else if (m_objectType == Shape)
saveXmlObjectShape(writer);
}
void DrawingAnchor::saveXmlObjectConnectionShape(QXmlStreamWriter &writer) const
{
Q_UNUSED(writer)
}
void DrawingAnchor::saveXmlObjectGraphicFrame(QXmlStreamWriter &writer) const
{
writer.writeStartElement(QStringLiteral("xdr:graphicFrame"));
writer.writeAttribute(QStringLiteral("macro"), QString());
writer.writeStartElement(QStringLiteral("xdr:nvGraphicFramePr"));
writer.writeEmptyElement(QStringLiteral("xdr:cNvPr"));
writer.writeAttribute(QStringLiteral("id"), QString::number(m_id));
writer.writeAttribute(QStringLiteral("name"),QStringLiteral("Chart %1").arg(m_id));
writer.writeEmptyElement(QStringLiteral("xdr:cNvGraphicFramePr"));
writer.writeEndElement();//xdr:nvGraphicFramePr
writer.writeStartElement(QStringLiteral("xdr:xfrm"));
writer.writeEndElement(); //xdr:xfrm
writer.writeStartElement(QStringLiteral("a:graphic"));
writer.writeStartElement(QStringLiteral("a:graphicData"));
writer.writeAttribute(QStringLiteral("uri"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/chart"));
int idx = m_drawing->workbook->chartFiles().indexOf(m_chartFile);
m_drawing->relationships()->addDocumentRelationship(QStringLiteral("/chart"), QStringLiteral("../charts/chart%1.xml").arg(idx+1));
writer.writeEmptyElement(QStringLiteral("c:chart"));
writer.writeAttribute(QStringLiteral("xmlns:c"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/chart"));
writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"));
writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(m_drawing->relationships()->count()));
writer.writeEndElement(); //a:graphicData
writer.writeEndElement(); //a:graphic
writer.writeEndElement(); //xdr:graphicFrame
}
void DrawingAnchor::saveXmlObjectGroupShape(QXmlStreamWriter &writer) const
{
Q_UNUSED(writer)
}
void DrawingAnchor::saveXmlObjectPicture(QXmlStreamWriter &writer) const
{
Q_ASSERT(m_objectType == Picture && !m_pictureFile.isNull());
writer.writeStartElement(QStringLiteral("xdr:pic"));
writer.writeStartElement(QStringLiteral("xdr:nvPicPr"));
writer.writeEmptyElement(QStringLiteral("xdr:cNvPr"));
writer.writeAttribute(QStringLiteral("id"), QString::number(m_id));
writer.writeAttribute(QStringLiteral("name"), QStringLiteral("Picture %1").arg(m_id));
writer.writeStartElement(QStringLiteral("xdr:cNvPicPr"));
writer.writeEmptyElement(QStringLiteral("a:picLocks"));
writer.writeAttribute(QStringLiteral("noChangeAspect"), QStringLiteral("1"));
writer.writeEndElement(); //xdr:cNvPicPr
writer.writeEndElement(); //xdr:nvPicPr
m_drawing->relationships()->addDocumentRelationship(QStringLiteral("/image"), QStringLiteral("../media/image%1.%2")
.arg(m_pictureFile->index()+1)
.arg(m_pictureFile->suffix()));
writer.writeStartElement(QStringLiteral("xdr:blipFill"));
writer.writeEmptyElement(QStringLiteral("a:blip"));
writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"));
writer.writeAttribute(QStringLiteral("r:embed"), QStringLiteral("rId%1").arg(m_drawing->relationships()->count()));
writer.writeStartElement(QStringLiteral("a:stretch"));
writer.writeEmptyElement(QStringLiteral("a:fillRect"));
writer.writeEndElement(); //a:stretch
writer.writeEndElement();//xdr:blipFill
writer.writeStartElement(QStringLiteral("xdr:spPr"));
writer.writeStartElement(QStringLiteral("a:prstGeom"));
writer.writeAttribute(QStringLiteral("prst"), QStringLiteral("rect"));
writer.writeEmptyElement(QStringLiteral("a:avLst"));
writer.writeEndElement(); //a:prstGeom
writer.writeEndElement(); //xdr:spPr
writer.writeEndElement(); //xdr:pic
}
void DrawingAnchor::saveXmlObjectShape(QXmlStreamWriter &writer) const
{
Q_UNUSED(writer)
}
//absolute anchor
DrawingAbsoluteAnchor::DrawingAbsoluteAnchor(Drawing *drawing, ObjectType objectType)
:DrawingAnchor(drawing, objectType)
{
}
bool DrawingAbsoluteAnchor::loadFromXml(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("absoluteAnchor"));
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("pos")) {
pos = loadXmlPos(reader);
} else if (reader.name() == QLatin1String("ext")) {
ext = loadXmlExt(reader);
} else {
loadXmlObject(reader);
}
} else if (reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == QLatin1String("absoluteAnchor")) {
break;
}
}
return true;
}
void DrawingAbsoluteAnchor::saveToXml(QXmlStreamWriter &writer) const
{
writer.writeStartElement(QStringLiteral("xdr:absoluteAnchor"));
saveXmlPos(writer, pos);
saveXmlExt(writer, ext);
saveXmlObject(writer);
writer.writeEmptyElement(QStringLiteral("xdr:clientData"));
writer.writeEndElement(); //xdr:absoluteAnchor
}
//one cell anchor
DrawingOneCellAnchor::DrawingOneCellAnchor(Drawing *drawing, ObjectType objectType)
:DrawingAnchor(drawing, objectType)
{
}
bool DrawingOneCellAnchor::loadFromXml(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("oneCellAnchor"));
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("from")) {
from = loadXmlMarker(reader, QLatin1String("from"));
} else if (reader.name() == QLatin1String("ext")) {
ext = loadXmlExt(reader);
} else {
loadXmlObject(reader);
}
} else if (reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == QLatin1String("oneCellAnchor")) {
break;
}
}
return true;
}
void DrawingOneCellAnchor::saveToXml(QXmlStreamWriter &writer) const
{
writer.writeStartElement(QStringLiteral("xdr:oneCellAnchor"));
saveXmlMarker(writer, from, QStringLiteral("xdr:from"));
saveXmlExt(writer, ext);
saveXmlObject(writer);
writer.writeEmptyElement(QStringLiteral("xdr:clientData"));
writer.writeEndElement(); //xdr:oneCellAnchor
}
/*
Two cell anchor
This class specifies a two cell anchor placeholder for a group
, a shape, or a drawing element. It moves with
cells and its extents are in EMU units.
*/
DrawingTwoCellAnchor::DrawingTwoCellAnchor(Drawing *drawing, ObjectType objectType)
:DrawingAnchor(drawing, objectType)
{
}
bool DrawingTwoCellAnchor::loadFromXml(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("twoCellAnchor"));
while (!reader.atEnd()) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("from")) {
from = loadXmlMarker(reader, QLatin1String("from"));
} else if (reader.name() == QLatin1String("to")) {
to = loadXmlMarker(reader, QLatin1String("to"));
} else {
loadXmlObject(reader);
}
} else if (reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == QLatin1String("twoCellAnchor")) {
break;
}
}
return true;
}
void DrawingTwoCellAnchor::saveToXml(QXmlStreamWriter &writer) const
{
writer.writeStartElement(QStringLiteral("xdr:twoCellAnchor"));
writer.writeAttribute(QStringLiteral("editAs"), QStringLiteral("oneCell"));
saveXmlMarker(writer, from, QStringLiteral("xdr:from"));
saveXmlMarker(writer, to, QStringLiteral("xdr:to"));
saveXmlObject(writer);
writer.writeEmptyElement(QStringLiteral("xdr:clientData"));
writer.writeEndElement(); //xdr:twoCellAnchor
}
} // namespace QXlsx

View File

@ -0,0 +1,151 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_XLSXDRAWINGANCHOR_P_H
#define QXLSX_XLSXDRAWINGANCHOR_P_H
#include "xlsxglobal.h"
#include <QPoint>
#include <QSize>
#include <QString>
#include <QSharedPointer>
class QXmlStreamReader;
class QXmlStreamWriter;
namespace QXlsx {
class Drawing;
class MediaFile;
class Chart;
//Helper class
struct XlsxMarker
{
XlsxMarker(){}
XlsxMarker(int row, int column, int rowOffset, int colOffset)
:cell(QPoint(row, column)), offset(rowOffset, colOffset)
{
}
int row() const {return cell.x();}
int col() const {return cell.y();}
int rowOff() const {return offset.width();}
int colOff() const {return offset.height();}
QPoint cell;
QSize offset;
};
class DrawingAnchor
{
public:
enum ObjectType {
GraphicFrame,
Shape,
GroupShape,
ConnectionShape,
Picture,
Unknown
};
DrawingAnchor(Drawing *drawing, ObjectType objectType);
virtual ~DrawingAnchor();
void setObjectPicture(const QImage &img);
void setObjectGraphicFrame(QSharedPointer<Chart> chart);
virtual bool loadFromXml(QXmlStreamReader &reader) = 0;
virtual void saveToXml(QXmlStreamWriter &writer) const = 0;
protected:
QPoint loadXmlPos(QXmlStreamReader &reader);
QSize loadXmlExt(QXmlStreamReader &reader);
XlsxMarker loadXmlMarker(QXmlStreamReader &reader, const QString &node);
void loadXmlObject(QXmlStreamReader &reader);
void loadXmlObjectShape(QXmlStreamReader &reader);
void loadXmlObjectGroupShape(QXmlStreamReader &reader);
void loadXmlObjectGraphicFrame(QXmlStreamReader &reader);
void loadXmlObjectConnectionShape(QXmlStreamReader &reader);
void loadXmlObjectPicture(QXmlStreamReader &reader);
void saveXmlPos(QXmlStreamWriter &writer, const QPoint &pos) const;
void saveXmlExt(QXmlStreamWriter &writer, const QSize &ext) const;
void saveXmlMarker(QXmlStreamWriter &writer, const XlsxMarker &marker, const QString &node) const;
void saveXmlObject(QXmlStreamWriter &writer) const;
void saveXmlObjectShape(QXmlStreamWriter &writer) const;
void saveXmlObjectGroupShape(QXmlStreamWriter &writer) const;
void saveXmlObjectGraphicFrame(QXmlStreamWriter &writer) const;
void saveXmlObjectConnectionShape(QXmlStreamWriter &writer) const;
void saveXmlObjectPicture(QXmlStreamWriter &writer) const;
Drawing *m_drawing;
ObjectType m_objectType;
QSharedPointer<MediaFile> m_pictureFile;
QSharedPointer<Chart> m_chartFile;
int m_id;
};
class DrawingAbsoluteAnchor : public DrawingAnchor
{
public:
DrawingAbsoluteAnchor(Drawing *drawing, ObjectType objectType=Unknown);
QPoint pos;
QSize ext;
bool loadFromXml(QXmlStreamReader &reader);
void saveToXml(QXmlStreamWriter &writer) const;
};
class DrawingOneCellAnchor : public DrawingAnchor
{
public:
DrawingOneCellAnchor(Drawing *drawing, ObjectType objectType=Unknown);
XlsxMarker from;
QSize ext;
bool loadFromXml(QXmlStreamReader &reader);
void saveToXml(QXmlStreamWriter &writer) const;
};
class DrawingTwoCellAnchor : public DrawingAnchor
{
public:
DrawingTwoCellAnchor(Drawing *drawing, ObjectType objectType=Unknown);
XlsxMarker from;
XlsxMarker to;
bool loadFromXml(QXmlStreamReader &reader);
void saveToXml(QXmlStreamWriter &writer) const;
};
} // namespace QXlsx
#endif // QXLSX_XLSXDRAWINGANCHOR_P_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,282 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_FORMAT_H
#define QXLSX_FORMAT_H
#include "xlsxglobal.h"
#include <QFont>
#include <QColor>
#include <QByteArray>
#include <QList>
#include <QExplicitlySharedDataPointer>
#include <QVariant>
class FormatTest;
QT_BEGIN_NAMESPACE_XLSX
class Styles;
class Worksheet;
class WorksheetPrivate;
class RichStringPrivate;
class SharedStrings;
class FormatPrivate;
class Q_XLSX_EXPORT Format
{
public:
enum FontScript
{
FontScriptNormal,
FontScriptSuper,
FontScriptSub
};
enum FontUnderline
{
FontUnderlineNone,
FontUnderlineSingle,
FontUnderlineDouble,
FontUnderlineSingleAccounting,
FontUnderlineDoubleAccounting
};
enum HorizontalAlignment
{
AlignHGeneral,
AlignLeft,
AlignHCenter,
AlignRight,
AlignHFill,
AlignHJustify,
AlignHMerge,
AlignHDistributed
};
enum VerticalAlignment
{
AlignTop,
AlignVCenter,
AlignBottom,
AlignVJustify,
AlignVDistributed
};
enum BorderStyle
{
BorderNone,
BorderThin,
BorderMedium,
BorderDashed,
BorderDotted,
BorderThick,
BorderDouble,
BorderHair,
BorderMediumDashed,
BorderDashDot,
BorderMediumDashDot,
BorderDashDotDot,
BorderMediumDashDotDot,
BorderSlantDashDot
};
enum DiagonalBorderType
{
DiagonalBorderNone,
DiagonalBorderDown,
DiagonalBorderUp,
DiagnoalBorderBoth
};
enum FillPattern
{
PatternNone,
PatternSolid,
PatternMediumGray,
PatternDarkGray,
PatternLightGray,
PatternDarkHorizontal,
PatternDarkVertical,
PatternDarkDown,
PatternDarkUp,
PatternDarkGrid,
PatternDarkTrellis,
PatternLightHorizontal,
PatternLightVertical,
PatternLightDown,
PatternLightUp,
PatternLightTrellis,
PatternGray125,
PatternGray0625,
PatternLightGrid
};
Format();
Format(const Format &other);
Format &operator=(const Format &rhs);
~Format();
int numberFormatIndex() const;
void setNumberFormatIndex(int format);
QString numberFormat() const;
void setNumberFormat(const QString &format);
void setNumberFormat(int id, const QString &format);
bool isDateTimeFormat() const;
int fontSize() const;
void setFontSize(int size);
bool fontItalic() const;
void setFontItalic(bool italic);
bool fontStrikeOut() const;
void setFontStrikeOut(bool);
QColor fontColor() const;
void setFontColor(const QColor &);
bool fontBold() const;
void setFontBold(bool bold);
FontScript fontScript() const;
void setFontScript(FontScript);
FontUnderline fontUnderline() const;
void setFontUnderline(FontUnderline);
bool fontOutline() const;
void setFontOutline(bool outline);
QString fontName() const;
void setFontName(const QString &);
QFont font() const;
void setFont(const QFont &font);
HorizontalAlignment horizontalAlignment() const;
void setHorizontalAlignment(HorizontalAlignment align);
VerticalAlignment verticalAlignment() const;
void setVerticalAlignment(VerticalAlignment align);
bool textWrap() const;
void setTextWarp(bool textWrap);
int rotation() const;
void setRotation(int rotation);
int indent() const;
void setIndent(int indent);
bool shrinkToFit() const;
void setShrinkToFit(bool shink);
void setBorderStyle(BorderStyle style);
void setBorderColor(const QColor &color);
BorderStyle leftBorderStyle() const;
void setLeftBorderStyle(BorderStyle style);
QColor leftBorderColor() const;
void setLeftBorderColor(const QColor &color);
BorderStyle rightBorderStyle() const;
void setRightBorderStyle(BorderStyle style);
QColor rightBorderColor() const;
void setRightBorderColor(const QColor &color);
BorderStyle topBorderStyle() const;
void setTopBorderStyle(BorderStyle style);
QColor topBorderColor() const;
void setTopBorderColor(const QColor &color);
BorderStyle bottomBorderStyle() const;
void setBottomBorderStyle(BorderStyle style);
QColor bottomBorderColor() const;
void setBottomBorderColor(const QColor &color);
BorderStyle diagonalBorderStyle() const;
void setDiagonalBorderStyle(BorderStyle style);
DiagonalBorderType diagonalBorderType() const;
void setDiagonalBorderType(DiagonalBorderType style);
QColor diagonalBorderColor() const;
void setDiagonalBorderColor(const QColor &color);
FillPattern fillPattern() const;
void setFillPattern(FillPattern pattern);
QColor patternForegroundColor() const;
void setPatternForegroundColor(const QColor &color);
QColor patternBackgroundColor() const;
void setPatternBackgroundColor(const QColor &color);
bool locked() const;
void setLocked(bool locked);
bool hidden() const;
void setHidden(bool hidden);
void mergeFormat(const Format &modifier);
bool isValid() const;
bool isEmpty() const;
bool operator == (const Format &format) const;
bool operator != (const Format &format) const;
QVariant property(int propertyId, const QVariant &defaultValue=QVariant()) const;
void setProperty(int propertyId, const QVariant &value, const QVariant &clearValue=QVariant(), bool detach=true);
void clearProperty(int propertyId);
bool hasProperty(int propertyId) const;
bool boolProperty(int propertyId, bool defaultValue=false) const;
int intProperty(int propertyId, int defaultValue=0) const;
double doubleProperty(int propertyId, double defaultValue = 0.0) const;
QString stringProperty(int propertyId, const QString &defaultValue = QString()) const;
QColor colorProperty(int propertyId, const QColor &defaultValue = QColor()) const;
bool hasNumFmtData() const;
bool hasFontData() const;
bool hasFillData() const;
bool hasBorderData() const;
bool hasAlignmentData() const;
bool hasProtectionData() const;
bool fontIndexValid() const;
int fontIndex() const;
QByteArray fontKey() const;
bool borderIndexValid() const;
QByteArray borderKey() const;
int borderIndex() const;
bool fillIndexValid() const;
QByteArray fillKey() const;
int fillIndex() const;
QByteArray formatKey() const;
bool xfIndexValid() const;
int xfIndex() const;
bool dxfIndexValid() const;
int dxfIndex() const;
void fixNumberFormat(int id, const QString &format);
void setFontIndex(int index);
void setBorderIndex(int index);
void setFillIndex(int index);
void setXfIndex(int index);
void setDxfIndex(int index);
private:
friend class Styles;
friend class ::FormatTest;
friend Q_XLSX_EXPORT QDebug operator<<(QDebug, const Format &f);
int theme() const;
QExplicitlySharedDataPointer<FormatPrivate> d;
};
#ifndef QT_NO_DEBUG_STREAM
Q_XLSX_EXPORT QDebug operator<<(QDebug dbg, const Format &f);
#endif
QT_END_NAMESPACE_XLSX
#endif // QXLSX_FORMAT_H

View File

@ -0,0 +1,161 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXFORMAT_P_H
#define XLSXFORMAT_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxformat.h"
#include <QSharedData>
#include <QMap>
#include <QSet>
namespace QXlsx {
class FormatPrivate : public QSharedData
{
public:
enum FormatType
{
FT_Invalid = 0,
FT_NumFmt = 0x01,
FT_Font = 0x02,
FT_Alignment = 0x04,
FT_Border = 0x08,
FT_Fill = 0x10,
FT_Protection = 0x20
};
enum Property {
P_STARTID,
//numFmt
P_NumFmt_Id,
P_NumFmt_FormatCode,
//font
P_Font_STARTID,
P_Font_Size = P_Font_STARTID,
P_Font_Italic,
P_Font_StrikeOut,
P_Font_Color,
P_Font_Bold,
P_Font_Script,
P_Font_Underline,
P_Font_Outline,
P_Font_Shadow,
P_Font_Name,
P_Font_Family,
P_Font_Charset,
P_Font_Scheme,
P_Font_Condense,
P_Font_Extend,
P_Font_ENDID,
//border
P_Border_STARTID,
P_Border_LeftStyle = P_Border_STARTID,
P_Border_RightStyle,
P_Border_TopStyle,
P_Border_BottomStyle,
P_Border_DiagonalStyle,
P_Border_LeftColor,
P_Border_RightColor,
P_Border_TopColor,
P_Border_BottomColor,
P_Border_DiagonalColor,
P_Border_DiagonalType,
P_Border_ENDID,
//fill
P_Fill_STARTID,
P_Fill_Pattern = P_Fill_STARTID,
P_Fill_BgColor,
P_Fill_FgColor,
P_Fill_ENDID,
//alignment
P_Alignment_STARTID,
P_Alignment_AlignH = P_Alignment_STARTID,
P_Alignment_AlignV,
P_Alignment_Wrap,
P_Alignment_Rotation,
P_Alignment_Indent,
P_Alignment_ShinkToFit,
P_Alignment_ENDID,
//protection
P_Protection_Locked,
P_Protection_Hidden,
P_ENDID
};
FormatPrivate();
FormatPrivate(const FormatPrivate &other);
~FormatPrivate();
bool dirty; //The key re-generation is need.
QByteArray formatKey;
bool font_dirty;
bool font_index_valid;
QByteArray font_key;
int font_index;
bool fill_dirty;
bool fill_index_valid;
QByteArray fill_key;
int fill_index;
bool border_dirty;
bool border_index_valid;
QByteArray border_key;
int border_index;
int xf_index;
bool xf_indexValid;
bool is_dxf_fomat;
int dxf_index;
bool dxf_indexValid;
int theme;
QMap<int, QVariant> properties;
};
}
#endif // XLSXFORMAT_P_H

View File

@ -0,0 +1,49 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXGLOBAL_H
#define XLSXGLOBAL_H
#include <QtGlobal>
#define QT_BEGIN_NAMESPACE_XLSX namespace QXlsx {
#define QT_END_NAMESPACE_XLSX }
#define QTXLSX_USE_NAMESPACE using namespace QXlsx;
#if !defined(QT_STATIC) && !defined(XLSX_NO_LIB)
# if defined(QT_BUILD_XLSX_LIB)
# define Q_XLSX_EXPORT Q_DECL_EXPORT
# else
# define Q_XLSX_EXPORT Q_DECL_IMPORT
# endif
#else
# define Q_XLSX_EXPORT
#endif
#ifdef XLSX_TEST
# define XLSX_AUTOTEST_EXPORT Q_XLSX_EXPORT
#else
# define XLSX_AUTOTEST_EXPORT
#endif
#endif // XLSXGLOBAL_H

View File

@ -0,0 +1,99 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxmediafile_p.h"
#include <QCryptographicHash>
namespace QXlsx {
MediaFile::MediaFile(const QByteArray &bytes, const QString &suffix, const QString &mimeType)
: m_contents(bytes), m_suffix(suffix), m_mimeType(mimeType)
, m_index(0), m_indexValid(false)
{
m_hashKey = QCryptographicHash::hash(m_contents, QCryptographicHash::Md5);
}
MediaFile::MediaFile(const QString &fileName)
:m_fileName(fileName), m_index(0), m_indexValid(false)
{
}
void MediaFile::set(const QByteArray &bytes, const QString &suffix, const QString &mimeType)
{
m_contents = bytes;
m_suffix = suffix;
m_mimeType = mimeType;
m_hashKey = QCryptographicHash::hash(m_contents, QCryptographicHash::Md5);
m_indexValid = false;
}
void MediaFile::setFileName(const QString &name)
{
m_fileName = name;
}
QString MediaFile::fileName() const
{
return m_fileName;
}
QString MediaFile::suffix() const
{
return m_suffix;
}
QString MediaFile::mimeType() const
{
return m_mimeType;
}
QByteArray MediaFile::contents() const
{
return m_contents;
}
int MediaFile::index() const
{
return m_index;
}
bool MediaFile::isIndexValid() const
{
return m_indexValid;
}
void MediaFile::setIndex(int idx)
{
m_index = idx;
m_indexValid = true;
}
QByteArray MediaFile::hashKey() const
{
return m_hashKey;
}
} // namespace QXlsx

View File

@ -0,0 +1,80 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_XLSXMEDIAFILE_H
#define QXLSX_XLSXMEDIAFILE_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxglobal.h"
#include <QString>
#include <QByteArray>
namespace QXlsx {
class MediaFile
{
public:
MediaFile(const QString &fileName);
MediaFile(const QByteArray &bytes, const QString &suffix, const QString &mimeType=QString());
void set(const QByteArray &bytes, const QString &suffix, const QString &mimeType=QString());
QString suffix() const;
QString mimeType() const;
QByteArray contents() const;
bool isIndexValid() const;
int index() const;
void setIndex(int idx);
QByteArray hashKey() const;
void setFileName(const QString &name);
QString fileName() const;
private:
QString m_fileName; //...
QByteArray m_contents;
QString m_suffix;
QString m_mimeType;
int m_index;
bool m_indexValid;
QByteArray m_hashKey;
};
} // namespace QXlsx
#endif // QXLSX_XLSXMEDIAFILE_H

View File

@ -0,0 +1,94 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxnumformatparser_p.h"
#include <QString>
namespace QXlsx {
bool NumFormatParser::isDateTime(const QString &formatCode)
{
for (int i = 0; i < formatCode.length(); ++i) {
const QChar &c = formatCode[i];
switch (c.unicode()) {
case '[':
// [h], [m], [s] are valid format for time
if (i < formatCode.length()-2 && formatCode[i+2] == QLatin1Char(']')) {
const QChar cc = formatCode[i+1].toLower();
if (cc == QLatin1Char('h') || cc == QLatin1Char('m') || cc == QLatin1Char('s'))
return true;
i+=2;
break;
} else {
// condition or color: don't care, ignore
while (i < formatCode.length() && formatCode[i] != QLatin1Char(']'))
++i;
break;
}
// quoted plain text block: don't care, ignore
case '"':
while (i < formatCode.length()-1 && formatCode[++i] != QLatin1Char('"'))
;
break;
// escaped char: don't care, ignore
case '\\':
if (i < formatCode.length() - 1)
++i;
break;
// date/time can only be positive number,
// so only the first section of the format make sense.
case ';':
return false;
break;
// days
case 'D':
case 'd':
// years
case 'Y':
case 'y':
// hours
case 'H':
case 'h':
// seconds
case 'S':
case 's':
// minutes or months, depending on context
case 'M':
case 'm':
return true;
default:
break;
}
}
return false;
}
} // namespace QXlsx

View File

@ -0,0 +1,51 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_NUMFORMATPARSER_H
#define QXLSX_NUMFORMATPARSER_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxglobal.h"
namespace QXlsx {
class NumFormatParser
{
public:
static bool isDateTime(const QString &formatCode);
};
} // namespace QXlsx
#endif // QXLSX_NUMFORMATPARSER_H

View File

@ -0,0 +1,189 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxrelationships_p.h"
#include <QXmlStreamWriter>
#include <QXmlStreamReader>
#include <QDir>
#include <QFile>
#include <QBuffer>
namespace QXlsx {
const QString schema_doc = QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
const QString schema_msPackage = QStringLiteral("http://schemas.microsoft.com/office/2006/relationships");
const QString schema_package = QStringLiteral("http://schemas.openxmlformats.org/package/2006/relationships");
//const QString schema_worksheet = QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
Relationships::Relationships()
{
}
QList<XlsxRelationship> Relationships::documentRelationships(const QString &relativeType) const
{
return relationships(schema_doc + relativeType);
}
void Relationships::addDocumentRelationship(const QString &relativeType, const QString &target)
{
addRelationship(schema_doc + relativeType, target);
}
QList<XlsxRelationship> Relationships::msPackageRelationships(const QString &relativeType) const
{
return relationships(schema_msPackage + relativeType);
}
void Relationships::addMsPackageRelationship(const QString &relativeType, const QString &target)
{
addRelationship(schema_msPackage + relativeType, target);
}
QList<XlsxRelationship> Relationships::packageRelationships(const QString &relativeType) const
{
return relationships(schema_package + relativeType);
}
void Relationships::addPackageRelationship(const QString &relativeType, const QString &target)
{
addRelationship(schema_package + relativeType, target);
}
QList<XlsxRelationship> Relationships::worksheetRelationships(const QString &relativeType) const
{
return relationships(schema_doc + relativeType);
}
void Relationships::addWorksheetRelationship(const QString &relativeType, const QString &target, const QString &targetMode)
{
addRelationship(schema_doc + relativeType, target, targetMode);
}
QList<XlsxRelationship> Relationships::relationships(const QString &type) const
{
QList<XlsxRelationship> res;
foreach (XlsxRelationship ship, m_relationships) {
if (ship.type == type)
res.append(ship);
}
return res;
}
void Relationships::addRelationship(const QString &type, const QString &target, const QString &targetMode)
{
XlsxRelationship relation;
relation.id = QStringLiteral("rId%1").arg(m_relationships.size()+1);
relation.type = type;
relation.target = target;
relation.targetMode = targetMode;
m_relationships.append(relation);
}
void Relationships::saveToXmlFile(QIODevice *device) const
{
QXmlStreamWriter writer(device);
writer.writeStartDocument(QStringLiteral("1.0"), true);
writer.writeStartElement(QStringLiteral("Relationships"));
writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/package/2006/relationships"));
foreach (XlsxRelationship relation, m_relationships) {
writer.writeStartElement(QStringLiteral("Relationship"));
writer.writeAttribute(QStringLiteral("Id"), relation.id);
writer.writeAttribute(QStringLiteral("Type"), relation.type);
writer.writeAttribute(QStringLiteral("Target"), relation.target);
if (!relation.targetMode.isNull())
writer.writeAttribute(QStringLiteral("TargetMode"), relation.targetMode);
writer.writeEndElement();
}
writer.writeEndElement();//Relationships
writer.writeEndDocument();
}
QByteArray Relationships::saveToXmlData() const
{
QByteArray data;
QBuffer buffer(&data);
buffer.open(QIODevice::WriteOnly);
saveToXmlFile(&buffer);
return data;
}
bool Relationships::loadFromXmlFile(QIODevice *device)
{
clear();
QXmlStreamReader reader(device);
while (!reader.atEnd()) {
QXmlStreamReader::TokenType token = reader.readNext();
if (token == QXmlStreamReader::StartElement) {
if (reader.name() == QStringLiteral("Relationship")) {
QXmlStreamAttributes attributes = reader.attributes();
XlsxRelationship relationship;
relationship.id = attributes.value(QLatin1String("Id")).toString();
relationship.type = attributes.value(QLatin1String("Type")).toString();
relationship.target = attributes.value(QLatin1String("Target")).toString();
relationship.targetMode = attributes.value(QLatin1String("TargetMode")).toString();
m_relationships.append(relationship);
}
}
if (reader.hasError())
return false;
}
return true;
}
bool Relationships::loadFromXmlData(const QByteArray &data)
{
QBuffer buffer;
buffer.setData(data);
buffer.open(QIODevice::ReadOnly);
return loadFromXmlFile(&buffer);
}
XlsxRelationship Relationships::getRelationshipById(const QString &id) const
{
foreach (XlsxRelationship ship, m_relationships) {
if (ship.id == id)
return ship;
}
return XlsxRelationship();
}
void Relationships::clear()
{
m_relationships.clear();
}
int Relationships::count() const
{
return m_relationships.count();
}
bool Relationships::isEmpty() const
{
return m_relationships.isEmpty();
}
} //namespace

View File

@ -0,0 +1,87 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXRELATIONSHIPS_H
#define XLSXRELATIONSHIPS_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxglobal.h"
#include <QList>
#include <QString>
class QIODevice;
namespace QXlsx {
struct XlsxRelationship
{
QString id;
QString type;
QString target;
QString targetMode;
};
class XLSX_AUTOTEST_EXPORT Relationships
{
public:
Relationships();
QList<XlsxRelationship> documentRelationships(const QString &relativeType) const;
QList<XlsxRelationship> packageRelationships(const QString &relativeType) const;
QList<XlsxRelationship> msPackageRelationships(const QString &relativeType) const;
QList<XlsxRelationship> worksheetRelationships(const QString &relativeType) const;
void addDocumentRelationship(const QString &relativeType, const QString &target);
void addPackageRelationship(const QString &relativeType, const QString &target);
void addMsPackageRelationship(const QString &relativeType, const QString &target);
void addWorksheetRelationship(const QString &relativeType, const QString &target, const QString &targetMode=QString());
void saveToXmlFile(QIODevice *device) const;
QByteArray saveToXmlData() const;
bool loadFromXmlFile(QIODevice *device);
bool loadFromXmlData(const QByteArray &data);
XlsxRelationship getRelationshipById(const QString &id) const;
void clear();
int count() const;
bool isEmpty() const;
private:
QList<XlsxRelationship> relationships(const QString &type) const;
void addRelationship(const QString &type, const QString &target, const QString &targetMode=QString());
QList<XlsxRelationship> m_relationships;
};
}
#endif // XLSXRELATIONSHIPS_H

View File

@ -0,0 +1,343 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxrichstring.h"
#include "xlsxrichstring_p.h"
#include "xlsxformat_p.h"
#include <QDebug>
#include <QTextDocument>
#include <QTextFragment>
QT_BEGIN_NAMESPACE_XLSX
RichStringPrivate::RichStringPrivate()
:_dirty(true)
{
}
RichStringPrivate::RichStringPrivate(const RichStringPrivate &other)
:QSharedData(other), fragmentTexts(other.fragmentTexts)
,fragmentFormats(other.fragmentFormats)
, _idKey(other.idKey()), _dirty(other._dirty)
{
}
RichStringPrivate::~RichStringPrivate()
{
}
/*!
\class RichString
\inmodule QtXlsx
\brief This class add support for the rich text string of the cell.
*/
/*!
Constructs a null string.
*/
RichString::RichString()
:d(new RichStringPrivate)
{
}
/*!
Constructs a plain string with the given \a text.
*/
RichString::RichString(const QString text)
:d(new RichStringPrivate)
{
addFragment(text, Format());
}
/*!
Constructs a copy of \a other.
*/
RichString::RichString(const RichString &other)
:d(other.d)
{
}
/*!
Destructs the string.
*/
RichString::~RichString()
{
}
/*!
Assigns \a other to this string and returns a reference to this string
*/
RichString &RichString::operator =(const RichString &other)
{
this->d = other.d;
return *this;
}
/*!
Returns the rich string as a QVariant
*/
RichString::operator QVariant() const
{
return QVariant(qMetaTypeId<RichString>(), this);
}
/*!
Returns true if this is rich text string.
*/
bool RichString::isRichString() const
{
if (fragmentCount() > 1) //Is this enough??
return true;
return false;
}
/*!
Returns true is this is an Null string.
*/
bool RichString::isNull() const
{
return d->fragmentTexts.size() == 0;
}
/*!
Returns true is this is an empty string.
*/
bool RichString::isEmtpy() const
{
foreach (const QString str, d->fragmentTexts) {
if (!str.isEmpty())
return false;
}
return true;
}
/*!
Converts to plain text string.
*/
QString RichString::toPlainString() const
{
if (isEmtpy())
return QString();
if (d->fragmentTexts.size() == 1)
return d->fragmentTexts[0];
return d->fragmentTexts.join(QString());
}
/*!
Converts to html string
*/
QString RichString::toHtml() const
{
//: Todo
return QString();
}
/*!
Replaces the entire contents of the document
with the given HTML-formatted text in the \a text string
*/
void RichString::setHtml(const QString &text)
{
QTextDocument doc;
doc.setHtml(text);
QTextBlock block = doc.firstBlock();
QTextBlock::iterator it;
for (it = block.begin(); !(it.atEnd()); ++it) {
QTextFragment textFragment = it.fragment();
if (textFragment.isValid()) {
Format fmt;
fmt.setFont(textFragment.charFormat().font());
fmt.setFontColor(textFragment.charFormat().foreground().color());
addFragment(textFragment.text(), fmt);
}
}
}
/*!
Returns fragment count.
*/
int RichString::fragmentCount() const
{
return d->fragmentTexts.size();
}
/*!
Appends a fragment with the given \a text and \a format.
*/
void RichString::addFragment(const QString &text, const Format &format)
{
d->fragmentTexts.append(text);
d->fragmentFormats.append(format);
d->_dirty = true;
}
/*!
Returns fragment text at the position \a index.
*/
QString RichString::fragmentText(int index) const
{
if (index < 0 || index >= fragmentCount())
return QString();
return d->fragmentTexts[index];
}
/*!
Returns fragment format at the position \a index.
*/
Format RichString::fragmentFormat(int index) const
{
if (index < 0 || index >= fragmentCount())
return Format();
return d->fragmentFormats[index];
}
/*!
* \internal
*/
QByteArray RichStringPrivate::idKey() const
{
if (_dirty) {
RichStringPrivate *rs = const_cast<RichStringPrivate *>(this);
QByteArray bytes;
if (fragmentTexts.size() == 1) {
bytes = fragmentTexts[0].toUtf8();
} else {
//Generate a hash value base on QByteArray ?
bytes.append("@@QtXlsxRichString=");
for (int i=0; i<fragmentTexts.size(); ++i) {
bytes.append("@Text");
bytes.append(fragmentTexts[i].toUtf8());
bytes.append("@Format");
if (fragmentFormats[i].hasFontData())
bytes.append(fragmentFormats[i].fontKey());
}
}
rs->_idKey = bytes;
rs->_dirty = false;
}
return _idKey;
}
/*!
Returns true if this string \a rs1 is equal to string \a rs2;
otherwise returns false.
*/
bool operator==(const RichString &rs1, const RichString &rs2)
{
if (rs1.fragmentCount() != rs2.fragmentCount())
return false;
return rs1.d->idKey() == rs2.d->idKey();
}
/*!
Returns true if this string \a rs1 is not equal to string \a rs2;
otherwise returns false.
*/
bool operator!=(const RichString &rs1, const RichString &rs2)
{
if (rs1.fragmentCount() != rs2.fragmentCount())
return true;
return rs1.d->idKey() != rs2.d->idKey();
}
/*!
* \internal
*/
bool operator<(const RichString &rs1, const RichString &rs2)
{
return rs1.d->idKey() < rs2.d->idKey();
}
/*!
\overload
Returns true if this string \a rs1 is equal to string \a rs2;
otherwise returns false.
*/
bool operator ==(const RichString &rs1, const QString &rs2)
{
if (rs1.fragmentCount() == 1 && rs1.fragmentText(0) == rs2) //format == 0
return true;
return false;
}
/*!
\overload
Returns true if this string \a rs1 is not equal to string \a rs2;
otherwise returns false.
*/
bool operator !=(const RichString &rs1, const QString &rs2)
{
if (rs1.fragmentCount() == 1 && rs1.fragmentText(0) == rs2) //format == 0
return false;
return true;
}
/*!
\overload
Returns true if this string \a rs1 is equal to string \a rs2;
otherwise returns false.
*/
bool operator ==(const QString &rs1, const RichString &rs2)
{
return rs2 == rs1;
}
/*!
\overload
Returns true if this string \a rs1 is not equal to string \a rs2;
otherwise returns false.
*/
bool operator !=(const QString &rs1, const RichString &rs2)
{
return rs2 != rs1;
}
uint qHash(const RichString &rs, uint seed) Q_DECL_NOTHROW
{
return qHash(rs.d->idKey(), seed);
}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const RichString &rs)
{
dbg.nospace() << "QXlsx::RichString(" << rs.d->fragmentTexts << ")";
return dbg.space();
}
#endif
QT_END_NAMESPACE_XLSX

View File

@ -0,0 +1,89 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXRICHSTRING_H
#define XLSXRICHSTRING_H
#include "xlsxglobal.h"
#include "xlsxformat.h"
#include <QVariant>
#include <QStringList>
#include <QSharedDataPointer>
QT_BEGIN_NAMESPACE_XLSX
class RichStringPrivate;
class RichString;
// qHash is a friend, but we can't use default arguments for friends (§8.3.6.4)
Q_XLSX_EXPORT uint qHash(const RichString &rs, uint seed = 0) Q_DECL_NOTHROW;
class Q_XLSX_EXPORT RichString
{
public:
RichString();
explicit RichString(const QString text);
RichString(const RichString &other);
~RichString();
bool isRichString() const;
bool isNull() const;
bool isEmtpy() const;
QString toPlainString() const;
QString toHtml() const;
void setHtml(const QString &text);
int fragmentCount() const;
void addFragment(const QString &text, const Format &format);
QString fragmentText(int index) const;
Format fragmentFormat(int index) const;
operator QVariant() const;
RichString &operator=(const RichString &other);
private:
friend Q_XLSX_EXPORT uint qHash(const RichString &rs, uint seed) Q_DECL_NOTHROW;
friend Q_XLSX_EXPORT bool operator==(const RichString &rs1, const RichString &rs2);
friend Q_XLSX_EXPORT bool operator!=(const RichString &rs1, const RichString &rs2);
friend Q_XLSX_EXPORT bool operator<(const RichString &rs1, const RichString &rs2);
friend Q_XLSX_EXPORT QDebug operator<<(QDebug dbg, const RichString &rs);
QSharedDataPointer<RichStringPrivate> d;
};
Q_XLSX_EXPORT bool operator==(const RichString &rs1, const RichString &rs2);
Q_XLSX_EXPORT bool operator!=(const RichString &rs1, const RichString &rs2);
Q_XLSX_EXPORT bool operator<(const RichString &rs1, const RichString &rs2);
Q_XLSX_EXPORT bool operator==(const RichString &rs1, const QString &rs2);
Q_XLSX_EXPORT bool operator==(const QString &rs1, const RichString &rs2);
Q_XLSX_EXPORT bool operator!=(const RichString &rs1, const QString &rs2);
Q_XLSX_EXPORT bool operator!=(const QString &rs1, const RichString &rs2);
#ifndef QT_NO_DEBUG_STREAM
Q_XLSX_EXPORT QDebug operator<<(QDebug dbg, const RichString &rs);
#endif
QT_END_NAMESPACE_XLSX
Q_DECLARE_METATYPE(QXlsx::RichString)
#endif // XLSXRICHSTRING_H

View File

@ -0,0 +1,60 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXRICHSTRING_P_H
#define XLSXRICHSTRING_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxrichstring.h"
QT_BEGIN_NAMESPACE_XLSX
class RichStringPrivate : public QSharedData
{
public:
RichStringPrivate();
RichStringPrivate(const RichStringPrivate &other);
~RichStringPrivate();
QByteArray idKey() const;
QStringList fragmentTexts;
QList<Format> fragmentFormats;
QByteArray _idKey;
bool _dirty;
};
QT_END_NAMESPACE_XLSX
#endif // XLSXRICHSTRING_P_H

View File

@ -0,0 +1,400 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxrichstring.h"
#include "xlsxsharedstrings_p.h"
#include "xlsxutility_p.h"
#include "xlsxformat_p.h"
#include "xlsxcolor_p.h"
#include <QXmlStreamWriter>
#include <QXmlStreamReader>
#include <QDir>
#include <QFile>
#include <QDebug>
#include <QBuffer>
namespace QXlsx {
/*
* Note that, when we open an existing .xlsx file (broken file?),
* duplicated string items may exist in the shared string table.
*
* In such case, the size of stringList will larger than stringTable.
* Duplicated items can be removed once we loaded all the worksheets.
*/
SharedStrings::SharedStrings(CreateFlag flag)
:AbstractOOXmlFile(flag)
{
m_stringCount = 0;
}
int SharedStrings::count() const
{
return m_stringCount;
}
bool SharedStrings::isEmpty() const
{
return m_stringList.isEmpty();
}
int SharedStrings::addSharedString(const QString &string)
{
return addSharedString(RichString(string));
}
int SharedStrings::addSharedString(const RichString &string)
{
m_stringCount += 1;
if (m_stringTable.contains(string)) {
XlsxSharedStringInfo &item = m_stringTable[string];
item.count += 1;
return item.index;
}
int index = m_stringList.size();
m_stringTable[string] = XlsxSharedStringInfo(index);
m_stringList.append(string);
return index;
}
void SharedStrings::incRefByStringIndex(int idx)
{
if (idx <0 || idx >= m_stringList.size()) {
qDebug("SharedStrings: invlid index");
return;
}
addSharedString(m_stringList[idx]);
}
/*
* Broken, don't use.
*/
void SharedStrings::removeSharedString(const QString &string)
{
removeSharedString(RichString(string));
}
/*
* Broken, don't use.
*/
void SharedStrings::removeSharedString(const RichString &string)
{
if (!m_stringTable.contains(string))
return;
m_stringCount -= 1;
XlsxSharedStringInfo &item = m_stringTable[string];
item.count -= 1;
if (item.count <= 0) {
for (int i=item.index+1; i<m_stringList.size(); ++i)
m_stringTable[m_stringList[i]].index -= 1;
m_stringList.removeAt(item.index);
m_stringTable.remove(string);
}
}
int SharedStrings::getSharedStringIndex(const QString &string) const
{
return getSharedStringIndex(RichString(string));
}
int SharedStrings::getSharedStringIndex(const RichString &string) const
{
if (m_stringTable.contains(string))
return m_stringTable[string].index;
return -1;
}
RichString SharedStrings::getSharedString(int index) const
{
if (index < m_stringList.count() && index >= 0)
return m_stringList[index];
return RichString();
}
QList<RichString> SharedStrings::getSharedStrings() const
{
return m_stringList;
}
void SharedStrings::writeRichStringPart_rPr(QXmlStreamWriter &writer, const Format &format) const
{
if (!format.hasFontData())
return;
if (format.fontBold())
writer.writeEmptyElement(QStringLiteral("b"));
if (format.fontItalic())
writer.writeEmptyElement(QStringLiteral("i"));
if (format.fontStrikeOut())
writer.writeEmptyElement(QStringLiteral("strike"));
if (format.fontOutline())
writer.writeEmptyElement(QStringLiteral("outline"));
if (format.boolProperty(FormatPrivate::P_Font_Shadow))
writer.writeEmptyElement(QStringLiteral("shadow"));
if (format.hasProperty(FormatPrivate::P_Font_Underline)) {
Format::FontUnderline u = format.fontUnderline();
if (u != Format::FontUnderlineNone) {
writer.writeEmptyElement(QStringLiteral("u"));
if (u== Format::FontUnderlineDouble)
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("double"));
else if (u == Format::FontUnderlineSingleAccounting)
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("singleAccounting"));
else if (u == Format::FontUnderlineDoubleAccounting)
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("doubleAccounting"));
}
}
if (format.hasProperty(FormatPrivate::P_Font_Script)) {
Format::FontScript s = format.fontScript();
if (s != Format::FontScriptNormal) {
writer.writeEmptyElement(QStringLiteral("vertAlign"));
if (s == Format::FontScriptSuper)
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("superscript"));
else
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("subscript"));
}
}
if (format.hasProperty(FormatPrivate::P_Font_Size)) {
writer.writeEmptyElement(QStringLiteral("sz"));
writer.writeAttribute(QStringLiteral("val"), QString::number(format.fontSize()));
}
if (format.hasProperty(FormatPrivate::P_Font_Color)) {
XlsxColor color = format.property(FormatPrivate::P_Font_Color).value<XlsxColor>();
color.saveToXml(writer);
}
if (!format.fontName().isEmpty()) {
writer.writeEmptyElement(QStringLiteral("rFont"));
writer.writeAttribute(QStringLiteral("val"), format.fontName());
}
if (format.hasProperty(FormatPrivate::P_Font_Family)) {
writer.writeEmptyElement(QStringLiteral("family"));
writer.writeAttribute(QStringLiteral("val"), QString::number(format.intProperty(FormatPrivate::P_Font_Family)));
}
if (format.hasProperty(FormatPrivate::P_Font_Scheme)) {
writer.writeEmptyElement(QStringLiteral("scheme"));
writer.writeAttribute(QStringLiteral("val"), format.stringProperty(FormatPrivate::P_Font_Scheme));
}
}
void SharedStrings::saveToXmlFile(QIODevice *device) const
{
QXmlStreamWriter writer(device);
if (m_stringList.size() != m_stringTable.size()) {
//Duplicated string items exist in m_stringList
//Clean up can not be done here, as the indices
//have been used when we save the worksheets part.
}
writer.writeStartDocument(QStringLiteral("1.0"), true);
writer.writeStartElement(QStringLiteral("sst"));
writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main"));
writer.writeAttribute(QStringLiteral("count"), QString::number(m_stringCount));
writer.writeAttribute(QStringLiteral("uniqueCount"), QString::number(m_stringList.size()));
foreach (RichString string, m_stringList) {
writer.writeStartElement(QStringLiteral("si"));
if (string.isRichString()) {
//Rich text string
for (int i=0; i<string.fragmentCount(); ++i) {
writer.writeStartElement(QStringLiteral("r"));
if (string.fragmentFormat(i).hasFontData()) {
writer.writeStartElement(QStringLiteral("rPr"));
writeRichStringPart_rPr(writer, string.fragmentFormat(i));
writer.writeEndElement();// rPr
}
writer.writeStartElement(QStringLiteral("t"));
if (isSpaceReserveNeeded(string.fragmentText(i)))
writer.writeAttribute(QStringLiteral("xml:space"), QStringLiteral("preserve"));
writer.writeCharacters(string.fragmentText(i));
writer.writeEndElement();// t
writer.writeEndElement(); //r
}
} else {
writer.writeStartElement(QStringLiteral("t"));
QString pString = string.toPlainString();
if (isSpaceReserveNeeded(pString))
writer.writeAttribute(QStringLiteral("xml:space"), QStringLiteral("preserve"));
writer.writeCharacters(pString);
writer.writeEndElement();//t
}
writer.writeEndElement();//si
}
writer.writeEndElement(); //sst
writer.writeEndDocument();
}
void SharedStrings::readString(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("si"));
RichString richString;
while (!reader.atEnd() && !(reader.name() == QLatin1String("si") && reader.tokenType() == QXmlStreamReader::EndElement)) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("r"))
readRichStringPart(reader, richString);
else if (reader.name() == QLatin1String("t"))
readPlainStringPart(reader, richString);
}
}
int idx = m_stringList.size();
m_stringTable[richString] = XlsxSharedStringInfo(idx, 0);
m_stringList.append(richString);
}
void SharedStrings::readRichStringPart(QXmlStreamReader &reader, RichString &richString)
{
Q_ASSERT(reader.name() == QLatin1String("r"));
QString text;
Format format;
while (!reader.atEnd() && !(reader.name() == QLatin1String("r") && reader.tokenType() == QXmlStreamReader::EndElement)) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("rPr")) {
format = readRichStringPart_rPr(reader);
} else if (reader.name() == QLatin1String("t")) {
text = reader.readElementText();
}
}
}
richString.addFragment(text, format);
}
void SharedStrings::readPlainStringPart(QXmlStreamReader &reader, RichString &richString)
{
Q_ASSERT(reader.name() == QLatin1String("t"));
//QXmlStreamAttributes attributes = reader.attributes();
QString text = reader.readElementText();
richString.addFragment(text, Format());
}
Format SharedStrings::readRichStringPart_rPr(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("rPr"));
Format format;
while (!reader.atEnd() && !(reader.name() == QLatin1String("rPr") && reader.tokenType() == QXmlStreamReader::EndElement)) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
QXmlStreamAttributes attributes = reader.attributes();
if (reader.name() == QLatin1String("rFont")) {
format.setFontName(attributes.value(QLatin1String("val")).toString());
} else if (reader.name() == QLatin1String("charset")) {
format.setProperty(FormatPrivate::P_Font_Charset, attributes.value(QLatin1String("val")).toString().toInt());
} else if (reader.name() == QLatin1String("family")) {
format.setProperty(FormatPrivate::P_Font_Family, attributes.value(QLatin1String("val")).toString().toInt());
} else if (reader.name() == QLatin1String("b")) {
format.setFontBold(true);
} else if (reader.name() == QLatin1String("i")) {
format.setFontItalic(true);
} else if (reader.name() == QLatin1String("strike")) {
format.setFontStrikeOut(true);
} else if (reader.name() == QLatin1String("outline")) {
format.setFontOutline(true);
} else if (reader.name() == QLatin1String("shadow")) {
format.setProperty(FormatPrivate::P_Font_Shadow, true);
} else if (reader.name() == QLatin1String("condense")) {
format.setProperty(FormatPrivate::P_Font_Condense, attributes.value(QLatin1String("val")).toString().toInt());
} else if (reader.name() == QLatin1String("extend")) {
format.setProperty(FormatPrivate::P_Font_Extend, attributes.value(QLatin1String("val")).toString().toInt());
} else if (reader.name() == QLatin1String("color")) {
XlsxColor color;
color.loadFromXml(reader);
format.setProperty(FormatPrivate::P_Font_Color, color);
} else if (reader.name() == QLatin1String("sz")) {
format.setFontSize(attributes.value(QLatin1String("val")).toString().toInt());
} else if (reader.name() == QLatin1String("u")) {
QString value = attributes.value(QLatin1String("val")).toString();
if (value == QLatin1String("double"))
format.setFontUnderline(Format::FontUnderlineDouble);
else if (value == QLatin1String("doubleAccounting"))
format.setFontUnderline(Format::FontUnderlineDoubleAccounting);
else if (value == QLatin1String("singleAccounting"))
format.setFontUnderline(Format::FontUnderlineSingleAccounting);
else
format.setFontUnderline(Format::FontUnderlineSingle);
} else if (reader.name() == QLatin1String("vertAlign")) {
QString value = attributes.value(QLatin1String("val")).toString();
if (value == QLatin1String("superscript"))
format.setFontScript(Format::FontScriptSuper);
else if (value == QLatin1String("subscript"))
format.setFontScript(Format::FontScriptSub);
} else if (reader.name() == QLatin1String("scheme")) {
format.setProperty(FormatPrivate::P_Font_Scheme, attributes.value(QLatin1String("val")).toString());
}
}
}
return format;
}
bool SharedStrings::loadFromXmlFile(QIODevice *device)
{
QXmlStreamReader reader(device);
int count = 0;
bool hasUniqueCountAttr=true;
while (!reader.atEnd()) {
QXmlStreamReader::TokenType token = reader.readNext();
if (token == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("sst")) {
QXmlStreamAttributes attributes = reader.attributes();
if ((hasUniqueCountAttr = attributes.hasAttribute(QLatin1String("uniqueCount"))))
count = attributes.value(QLatin1String("uniqueCount")).toString().toInt();
} else if (reader.name() == QLatin1String("si")) {
readString(reader);
}
}
}
if (hasUniqueCountAttr && m_stringList.size() != count) {
qDebug("Error: Shared string count");
return false;
}
if (m_stringList.size() != m_stringTable.size()) {
//qDebug("Warning: Duplicated items exist in shared string table.");
//Nothing we can do here, as indices of the strings will be used when loading sheets.
}
return true;
}
} //namespace

View File

@ -0,0 +1,98 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXSHAREDSTRINGS_H
#define XLSXSHAREDSTRINGS_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxglobal.h"
#include "xlsxrichstring.h"
#include "xlsxabstractooxmlfile.h"
#include <QHash>
#include <QStringList>
#include <QSharedPointer>
class QIODevice;
class QXmlStreamReader;
class QXmlStreamWriter;
namespace QXlsx {
class XlsxSharedStringInfo
{
public:
XlsxSharedStringInfo(int index=0, int count = 1) :
index(index), count(count)
{
}
int index;
int count;
};
class XLSX_AUTOTEST_EXPORT SharedStrings : public AbstractOOXmlFile
{
public:
SharedStrings(CreateFlag flag);
int count() const;
bool isEmpty() const;
int addSharedString(const QString &string);
int addSharedString(const RichString &string);
void removeSharedString(const QString &string);
void removeSharedString(const RichString &string);
void incRefByStringIndex(int idx);
int getSharedStringIndex(const QString &string) const;
int getSharedStringIndex(const RichString &string) const;
RichString getSharedString(int index) const;
QList<RichString> getSharedStrings() const;
void saveToXmlFile(QIODevice *device) const;
bool loadFromXmlFile(QIODevice *device);
private:
void readString(QXmlStreamReader &reader); // <si>
void readRichStringPart(QXmlStreamReader &reader, RichString &rich); // <r>
void readPlainStringPart(QXmlStreamReader &reader, RichString &rich); // <v>
Format readRichStringPart_rPr(QXmlStreamReader &reader);
void writeRichStringPart_rPr(QXmlStreamWriter &writer, const Format &format) const;
QHash<RichString, XlsxSharedStringInfo> m_stringTable; //for fast lookup
QList<RichString> m_stringList;
int m_stringCount;
};
}
#endif // XLSXSHAREDSTRINGS_H

View File

@ -0,0 +1,56 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxsimpleooxmlfile_p.h"
#include <QIODevice>
namespace QXlsx {
SimpleOOXmlFile::SimpleOOXmlFile(CreateFlag flag)
:AbstractOOXmlFile(flag)
{
}
void SimpleOOXmlFile::saveToXmlFile(QIODevice *device) const
{
device->write(xmlData);
}
QByteArray SimpleOOXmlFile::saveToXmlData() const
{
return xmlData;
}
bool SimpleOOXmlFile::loadFromXmlData(const QByteArray &data)
{
xmlData = data;
return true;
}
bool SimpleOOXmlFile::loadFromXmlFile(QIODevice *device)
{
xmlData = device->readAll();
return true;
}
}

View File

@ -0,0 +1,59 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXSIMPLEOOXMLFILE_H
#define XLSXSIMPLEOOXMLFILE_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxabstractooxmlfile.h"
#include <QString>
class QIODevice;
namespace QXlsx {
class SimpleOOXmlFile : public AbstractOOXmlFile
{
public:
SimpleOOXmlFile(CreateFlag flag);
void saveToXmlFile(QIODevice *device) const;
QByteArray saveToXmlData() const;
bool loadFromXmlData(const QByteArray &data);
bool loadFromXmlFile(QIODevice *device);
QByteArray xmlData;
};
}
#endif // XLSXSIMPLEOOXMLFILE_H

Some files were not shown because too many files have changed in this diff Show More