From ff88d8af4865a7a9ec5259238ee5680c3e11a76f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Fri, 23 Jun 2017 17:31:30 +0800 Subject: [PATCH 01/83] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E7=9A=84=E5=93=8D=E5=BA=94=EF=BC=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/Doc_OFDConvertor.cpp | 42 +++++++ ofdEditor/model/Convert/Doc_OFDConvertor.h | 28 ++++- ofdEditor/model/Convert/OFD_DocConvertor.h | 16 +-- ofdEditor/model/Doc/DocBlock.cpp | 38 +++++- ofdEditor/model/Doc/DocBlock.h | 7 ++ ofdEditor/model/Doc/DocPage.cpp | 34 +++++- ofdEditor/model/Doc/DocPage.h | 8 +- ofdEditor/model/Doc/DocPassage.cpp | 19 ++- ofdEditor/model/Doc/DocPassage.h | 25 ++-- ofdEditor/model/Doc/DocTextBlock.cpp | 114 ++++++++++++++++-- ofdEditor/model/Doc/DocTextBlock.h | 21 ++-- ofdEditor/model/Widget/DocInfoDialog.cpp | 14 +++ ofdEditor/model/Widget/DocInfoDialog.h | 22 ++++ ofdEditor/model/Widget/DocInfoDialog.ui | 71 +++++++++++ ofdEditor/model/Widget/FontSettingDialog.cpp | 2 +- ofdEditor/model/model.pro | 9 +- .../start/ActionConnector/ActionConnector.cpp | 30 ++--- .../start/ActionConnector/ActionConnector.h | 8 +- ofdEditor/start/ui/PassageMainWindow.cpp | 97 ++++++++++++++- ofdEditor/start/ui/PassageMainWindow.h | 19 ++- 20 files changed, 537 insertions(+), 87 deletions(-) create mode 100644 ofdEditor/model/Widget/DocInfoDialog.cpp create mode 100644 ofdEditor/model/Widget/DocInfoDialog.h create mode 100644 ofdEditor/model/Widget/DocInfoDialog.ui diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp index 7943414..82ca3b2 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp @@ -1,7 +1,49 @@ #include "Doc_OFDConvertor.h" +#include "Doc/DocPassage.h" +#include "Doc/DocPage.h" +#include "Doc/DocBlock.h" +#include "Doc/DocTextBlock.h" +#include "Doc/DocLayer.h" + +#include "DataTypes/basic_datatype.h" +#include "DataTypes/document/ofd.h" + + Doc_OFDConvertor::Doc_OFDConvertor(QObject *parent) : QObject(parent) { } + +/** + * @Author Chaoqun + * @brief 将Doc文件转换为ofd文件类型,启动程序 + * @param DocPassage *passage + * @return OFD* + * @date 2017/06/22 + */ +OFD *Doc_OFDConvertor::doc_to_ofd(DocPassage *passage) +{ + +} + +void Doc_OFDConvertor::buildDocInfo() +{ + +} + +void Doc_OFDConvertor::buildPage() +{ + +} + +void Doc_OFDConvertor::buildLayer(DocLayer *layer) +{ + +} + +void Doc_OFDConvertor::buildText(DocTextBlock *textBlock) +{ + +} diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.h b/ofdEditor/model/Convert/Doc_OFDConvertor.h index e3df7be..79b32bd 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.h +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.h @@ -2,17 +2,43 @@ #define DOC_OFDCONVERTOR_H #include +#include "model_global.h" -class Doc_OFDConvertor : public QObject +class DocPassage; // 文章 +class DocPage; // 页 +class DocLayer; // 层 +class DocBlock; // 块 +class DocTextBlock; // 文本框 + +class OFD; // OFD文件模型 + +/** + * @Author Chaoqun + * @brief 将文章转换成为一个 OFD文件,直至保存为.ofd文件 + * @date 2017/06/22 + */ +class MODELSHARED_EXPORT Doc_OFDConvertor + : public QObject { Q_OBJECT public: explicit Doc_OFDConvertor(QObject *parent = 0); + OFD *doc_to_ofd(DocPassage* passage); // 执行程序入口 signals: public slots: +private: + void buildDocInfo(); // 存储DocInfo相关的信息 + void buildPage(); // 储存文本信息,顺便整理文件 + void buildLayer(DocLayer* layer); // 将一层中的信息存储出来 + void buildText(DocTextBlock* textBlock); // 将DocTextBlock中的信息转换处理 + +private: + DocPassage* passage; // 文章 + OFD* ofdFile; // OFD对象 + }; #endif // DOC_OFDCONVERTOR_H diff --git a/ofdEditor/model/Convert/OFD_DocConvertor.h b/ofdEditor/model/Convert/OFD_DocConvertor.h index d10417d..288a4bd 100644 --- a/ofdEditor/model/Convert/OFD_DocConvertor.h +++ b/ofdEditor/model/Convert/OFD_DocConvertor.h @@ -28,33 +28,33 @@ class MODELSHARED_EXPORT OFD_DocConvertor public: OFD_DocConvertor(); - DocPassage * ofd_to_doc(OFD * ofd); // 生成文档 + DocPassage * ofd_to_doc(OFD * ofd); // 生成文档 private: OFD * ofdFile; // 当前处理时使用的ofd文件-用来方便获取到公用的特征 - DocPage * buildDocPage(Page * ct_page); // 生成页 + DocPage * buildDocPage(Page * ct_page); // 生成页 void insertLayer(DocPage * page, - CT_Layer * layer ); // 将每一层加入到页中 + CT_Layer * layer ); // 将每一层加入到页中 void insertPageBlock(DocPage * page, CT_Layer * layer, - CT_PageBlock* pageBlock); // 用于针对块可能嵌套的情况 + CT_PageBlock* pageBlock); // 用于针对块可能嵌套的情况 void insertCT_Text(DocPage * page, DocPage::Layer layer, - CT_Text *text); // 插入CT_Text类 + CT_Text *text); // 插入CT_Text类 void insertCT_Path(DocPage * page, CT_Layer * layer, - CT_Path *path); // 插入CT_Path + CT_Path *path); // 插入CT_Path void insertCT_Image(DocPage * page, DocPage::Layer layer, - CT_Image *image); // 插入CT_Image + CT_Image *image); // 插入CT_Image - QColor ctColorToQColor(CT_Color* ct_color); // 颜色转换 + QColor ctColorToQColor(CT_Color* ct_color); // 颜色转换 }; diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index 2f2c4aa..49d029f 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -155,6 +155,8 @@ void DocBlock::remove() { QGraphicsScene *scene = this->scene(); // 查找到本块所在的场景 scene->removeItem(this); // 从场景中移除该组件 + + emit this->signals_blockRemoved(this); // 发出信号 } @@ -348,12 +350,13 @@ void DocBlock::setWidget(QWidget *widget) void DocBlock::setWidget(DocTextBlock *textBlock) { // 建立connect - connect(textBlock,SIGNAL(signals_remove()), + connect(textBlock,SIGNAL(signals_remove(DocTextBlock*)), this,SLOT(remove())); // 和块做移除连接 connect(textBlock,SIGNAL(signals_setZValue(qreal)), this,SLOT(setZValue(qreal))); // 建立设置Z值的信号连接 - textBlock->setBlock(this); // 设置引用 + textBlock->setBlock(this); // 给DocTextBlock设置引用 + this->textBlock = textBlock; // 给DocBlock设置引用 QGraphicsProxyWidget::setWidget(textBlock); } @@ -407,3 +410,34 @@ DocBlock::RectAdjustStatus DocBlock::currentStatus(const QPointF &pos) return blockNone; } +/** + * @Author Chaoqun + * @brief 判断是其中装的是否是DocTextBlock + * @param void + * @return bool + * @date 2017/06/23 + */ +bool DocBlock::isTextBlock() +{ + if(this->textBlock == NULL) + { + return false; + } + else + { + return true; + } +} + +/** + * @Author Chaoqun + * @brief 获得DocTextBlock + * @param void + * @return DocTextBlock* + * @date 2017/06/23 + */ +DocTextBlock *DocBlock::getTextBlock() +{ + return this->textBlock; +} + diff --git a/ofdEditor/model/Doc/DocBlock.h b/ofdEditor/model/Doc/DocBlock.h index 1895c41..48a842a 100644 --- a/ofdEditor/model/Doc/DocBlock.h +++ b/ofdEditor/model/Doc/DocBlock.h @@ -36,6 +36,8 @@ public: qreal getZValue(){return this->realZValue;} // 获得当前块所在的Z值 RectAdjustStatus currentStatus(const QPointF& pos); // 鼠标所在位置可以进行什么调整 + bool isTextBlock(); // 判断是否DocBlock装的是否是DocTextBlock + DocTextBlock *getTextBlock(); // 获得DocTextBlock public slots: // 槽函数 void setLayer(DocLayer * layer){this->layer = layer;} @@ -73,11 +75,16 @@ private: QSizeF blockSize; // 用来纪录大小 QPointF blockOldPos; // 用来记录旧的位置 + DocTextBlock* textBlock; // 存下引用 + bool isFocused; // 是否被聚焦 bool blockIsResizing; // 是否正在改变大小 bool isInResizeArea(const QPointF& pos); // 检查鼠标是否在重置大小区域 qreal realZValue; // 真实的z值 +signals: + void signals_blockRemoved(DocBlock* block); // 当本块被移除时发出信号 + }; #endif // DOCBLOCK_H diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index 6b871ce..a01ce4a 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -109,10 +109,28 @@ QSize DocPage::getSize() void DocPage::addBlock(DocBlock *block, DocPage::Layer layer) { - qDebug() << "DocPage::addBlock excuted"; +// qDebug() << "DocPage::addBlock excuted"; this->docScene->addItem(block); // 添加元素 // qDebug() << "DocPage::addBlock excuted this->docScene->addItem(block);"; + // 插入DocTextBlock + if(block->isTextBlock()) + { + DocTextBlock* textBlock = block->getTextBlock(); // 获得TextBlock + DocPassage* passage = this->getPassage(); // 获得passage + emit this->signals_insertTextBlock(textBlock); // 发射信号 + + // 转发信号给passage + connect(textBlock,SIGNAL(signals_currentBlockFormatChanged(QTextBlockFormat&)), + passage,SIGNAL(signals_currentBlockFormatChanged(QTextBlockFormat&))); + connect(textBlock,SIGNAL(signals_currentCharFormatChanged(QTextCharFormat&)), + passage,SIGNAL(signals_currentCharFormatChanged(QTextCharFormat&))); + connect(textBlock,SIGNAL(signals_currentTextBlock(DocTextBlock*)), + passage,SIGNAL(signals_currentTextBlock(DocTextBlock*))); + + } + + // 分到层 switch (layer) { case Body: this->bodyLayer->addBlock(block); @@ -130,7 +148,6 @@ void DocPage::addBlock(DocBlock *block, DocPage::Layer layer) break; } - } /** @@ -179,6 +196,19 @@ void DocPage::setInsertBlockType(InsertBlockInfo &blockInfo) // qDebug()<<"Set InsertBlockInfo successfully!"; } +/** + * @Author Chaoqun + * @brief 从passage中移除本页内容 + * @param 参数 + * @return 返回值 + * @date 2017/06/23 + */ +void DocPage::remove() +{ + DocPassage * passage = this->getPassage(); + passage->removePage(this); +} + /** * @Author Chaoqun diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index 6519553..8291d08 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -56,6 +56,7 @@ public slots: void setBlockFlag(BlockFlag flag){this->newBlockFlag = flag;} void setInsertBlockType(InsertBlockInfo& blockInfo); // 设置下一个要插入的block的信息 + void remove(); // 移除本页 protected: void paintEvent(QPaintEvent *event); @@ -69,7 +70,6 @@ private: void init(); // 初始化UI DocPassage * passage; // 页所属文章 DocPageScene* docScene; // 场景数据 - //QVector layers; // 一个文档具有很多层 DocLayer* foregroundLayer; // 前景层 DocLayer* bodyLayer; // 正文层 @@ -88,12 +88,12 @@ private: QPointF newPos; // 新点 BlockFlag newBlockFlag; // 是否画块 - -// QList items; DocBlock * activeBlock; // 正在活跃的那个DocBlock signals: // 信号 - void signals_remove(); // 本页面被移除信号 + + void signals_insertTextBlock(DocTextBlock* textBlock ); // 插入文本框信号 + void signals_removeTextBlock(DocTextBlock* textBlock ); // 移除文本框信号 }; diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index fe833da..d0b3573 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -243,10 +243,10 @@ DocPage *DocPassage::getPage(int index) * @return void * @date 2017/05/23 */ -//void DocPassage::setCommonData(CT_CommonData* commonData) -//{ -// (this->commonData)->copy(commonData); -//} +void DocPassage::setCommonData(CT_CommonData* commonData) +{ + this->commonData = commonData; +} /** * @Author Chaoqun @@ -255,13 +255,10 @@ DocPage *DocPassage::getPage(int index) * @return CT_CommonData * @date 2017/05/23 */ -//CT_CommonData DocPassage::getCommonData() -//{ -// CT_CommonData common; -// common.copy(this->commonData); - -// return common; -//} +CT_CommonData* DocPassage::getCommonData() +{ + return this->commonData; +} /** * @Author Chaoqun diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index 005febf..67817f6 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -10,6 +10,8 @@ #include #include // 树状排布 #include +#include +#include // 类声明 class DocPage; @@ -51,8 +53,8 @@ public slots: void setDocInfo( CT_DocInfo & docInfo ); // CommonData -// void setCommonData(CT_CommonData* commonData); -// CT_CommonData getCommonData(); + void setCommonData(CT_CommonData* commonData); // 注意,设置的是直接的指针 + CT_CommonData* getCommonData(); // 注意,返回的是直接的指针 // Version void setVersion(QString version){this->version = version;} @@ -62,22 +64,16 @@ public slots: void testMessage(); // 测试信号是否走通 - - - - - protected: void resizeEvent(QResizeEvent* event); void closeEvent(QCloseEvent *event); // 继承,关闭前提示保存 - private: // 数据区 QString version; // OFD 版本默认 1.0 QString docType; // 类型默认是 OFD CT_DocInfo* docInfo; // 文档元数据结构 ofd/CT_DocInfo -// CT_CommonData* commonData; // 文档公用文档数据 + CT_CommonData* commonData; // 文档公用文档数据 QVector pages; // 既作为数据,也作为渲染 @@ -92,16 +88,21 @@ private: int horizontalWhite; // 白色页面左右两边的灰色区域 int verticalWhite; // 白色页面上下的灰色区域 - -private: void init(); // 初始化 void adjustScrollBar(QScrollBar *scrollBar, double factor); // 调整滑动条 void adjustScrollBarRange(); //调整滑动条范围 void adjustWidgetSize(); // 根据页数来自动调整widget大小 +signals: + void signals_insertTextBlock(DocTextBlock* textBlock); // 用来转发信号 + void signals_removeTextBlock(DocTextBlock* textBlock); // 用来转发信号 - + void signals_currentCharFormatChanged( + QTextCharFormat& fmt); // 当前选择的charFormat发生了变化 + void signals_currentBlockFormatChanged( + QTextBlockFormat& fmt); // 当前选择的block格式发生了变化 + void signals_currentTextBlock(DocTextBlock* textBlock); // 当前操作的textBlock }; diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 1edb508..af90c27 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -234,7 +234,7 @@ void DocTextBlock::setBlock(DocBlock *block) */ void DocTextBlock::remove() { - emit signals_remove(); // 发送信号,remove + emit signals_remove(this); // 发送信号,remove } /** @@ -599,6 +599,35 @@ void DocTextBlock::setCharFormatOnWordOrSelection( this->setCurrentCharFormat(format); // 合并当前的 QTextCharFormat } +/** + * @Author Chaoqun + * @brief 设置选择文字的格式 + * @param QTextCharFormat &format + * @return void + * @date 2017/06/23 + */ +void DocTextBlock::setCharFormatOnSelection( + QTextCharFormat &format) +{ + QTextCursor cursor = this->textCursor(); // 获得光标 + cursor.setCharFormat(format); // 设置字符格式 + this->setTextCursor(cursor); // 并应用光标 +} + +/** + * @Author Chaoqun + * @brief 设置给定光标的,选择的文字的格式 + * @param QTextCursor &cursor + * @param QTextCharFormat &format + * @return void + * @date 2017/06/23 + */ +void DocTextBlock::serCharFormatOnSelection( + QTextCursor &cursor, QTextCharFormat &format) +{ + cursor.setCharFormat(format); // 设置字符格式 +} + /** * @Author Chaoqun * @brief 显示右键菜单 @@ -641,7 +670,8 @@ void DocTextBlock::contextMenuEvent(QContextMenuEvent *event) void DocTextBlock::focusInEvent(QFocusEvent *e) { this->showBoundaryFrame(true); - emit this->signals_focusIn(); + + emitFormatSignals(); // 当鼠标移进时,必须发出信号 QTextEdit::focusInEvent(e); } @@ -656,7 +686,6 @@ void DocTextBlock::focusInEvent(QFocusEvent *e) void DocTextBlock::focusOutEvent(QFocusEvent *e) { this->showBoundaryFrame(false); - emit this->signals_focusOut(); QTextEdit::focusOutEvent(e); } @@ -674,6 +703,72 @@ void DocTextBlock::contextMenuAboutToHideEvent() this->focusInEvent(new QFocusEvent(QEvent::FocusIn)); // 关注它 } +/** + * @Author Chaoqun + * @brief 用来检查当前的格式是否发生改变,并向外界发出信号 + * @param 参数 + * @return 返回值 + * @date 2017/06/22 + */ +void DocTextBlock::checkCurrentFormat() +{ + QTextCursor cursor = this->textCursor(); //获得当前的光标 + // 比较当前光标位置的类型和已有的是否一致,不一致的话,当前的类型,并发射信号 + QTextBlockFormat blockFormat = cursor.blockFormat(); // 块格式 + QTextCharFormat charFormat = cursor.charFormat(); // 字符格式 + + // 处理字符格式 + if(this->_currentCharFormat == charFormat) + { + // 如果字符格式相等 +// qDebug() << "charFormat does not change!"; + } + else + { +// qDebug() << "charFormat changes! " +// << "And emit signal signals_currentCharFormatChanged!"; + // 如果字符格式变化 + this->_currentCharFormat = charFormat; // 更新char格式 + emit this->signals_currentCharFormatChanged(charFormat); // 发射char格式变更信号 + } + + // 处理块格式 + if(this->_currentBlockFormat == blockFormat) + { + // 格式相等 +// qDebug() << "blockFormat does not change!"; + } + else + { +// qDebug() << "blockFormat changes! " +// << "And emit signal signals_currentBlockFormatChanged!"; + // 格式不相等 + this->_currentBlockFormat = blockFormat; // 存储新格式 + emit this->signals_currentBlockFormatChanged(blockFormat); // 发射blockFormat变更信号 + } + emit this->signals_currentTextBlock(this); // 发射Text Block信号 +// qDebug() << "check format"; +} + +/** + * @Author Chaoqun + * @brief 将所有的信号发出 + * @param void + * @return void + * @date 2017/06/23 + */ +void DocTextBlock::emitFormatSignals() +{ + QTextCursor cursor = this->textCursor(); // 光标 + this->_currentBlockFormat = cursor.blockFormat(); // 获得块格式 + this->_currentCharFormat = cursor.charFormat(); // 获得字符格式 + + // 发射三个信号 + emit this->signals_currentBlockFormatChanged(this->_currentBlockFormat); + emit this->signals_currentCharFormatChanged(this->_currentCharFormat); + emit this->signals_currentTextBlock(this); +} + /** * @Author Chaoqun * @brief 初始化函数 @@ -694,17 +789,15 @@ void DocTextBlock::init() // 无边框 this->setFrameStyle(QFrame::NoFrame); - this->initFormat(); // 初始化格式 + this->initFormat(); // 初始化格式 - - - // 连接当前charFormat改变函数 - connect(this, SIGNAL(currentCharFormatChanged(QTextCharFormat)), - this, SLOT(currentCharFormatChangedEvent(QTextCharFormat))); + QTextCursor cursor = this->textCursor(); // 获得光标 + this->_currentBlockFormat = cursor.blockFormat(); // 块格式 + this->_currentCharFormat = cursor.charFormat(); // 字符格式 // 连接当前光标位置改变事件 connect(this, SIGNAL(cursorPositionChanged()), - this, SLOT(cursorPositionChangedEvent())); + this, SLOT(checkCurrentFormat())); this->initAcitons(); // 初始化QAction相关 } @@ -780,7 +873,6 @@ void DocTextBlock::initAcitons() } - /** * @Author Chaoqun * @brief 初始化文字的样式 diff --git a/ofdEditor/model/Doc/DocTextBlock.h b/ofdEditor/model/Doc/DocTextBlock.h index 267baec..25d5609 100644 --- a/ofdEditor/model/Doc/DocTextBlock.h +++ b/ofdEditor/model/Doc/DocTextBlock.h @@ -59,10 +59,17 @@ public slots: void setCharFormatOnWordOrSelection( QTextCharFormat &format); // 设置选中字段的QTextCharFormat + // 如果没有选中,则会选择光标所在行的字体 void setCharFormatOnWordOrSelection( QTextCursor& cursor, QTextCharFormat &format); // 设置给定光标的QTextCharFormat + void setCharFormatOnSelection( + QTextCharFormat &format); // 设置选中字段的QTextCharFormat + void serCharFormatOnSelection( + QTextCursor& cursor, + QTextCharFormat &format); // 设置给定光标下,文字的格式 + void mergeFormatOnWordOrSelection( QTextCharFormat &format); // 合并格式 void mergeFormatOnWordOrSelection( @@ -93,6 +100,8 @@ protected: private slots: void contextMenuAboutToHideEvent(); // 右键菜单隐藏绑定事件 + void checkCurrentFormat(); // 检查当前的格式是否发生改变 + void emitFormatSignals(); // 发射格式的信号 private: QString content; // 文字内容 @@ -116,20 +125,18 @@ private: qreal tempZValue; // 存储临时Z值 + QTextBlockFormat _currentBlockFormat; // 当前BlockFormat + QTextCharFormat _currentCharFormat; // 当前 + signals: - void signals_remove(); // 移除文本框的信号。 + void signals_remove(DocTextBlock* textBlock); // 移除文本框的信号。 void signals_setZValue(qreal z); // 设置Z值的信号 - // 该块被focus的信号 - void signals_focusIn(); - void signals_focusOut(); - void signals_currentCharFormatChanged( QTextCharFormat& fmt); // 当前选择的charFormat发生了变化 void signals_currentBlockFormatChanged( QTextBlockFormat& fmt); // 当前选择的block格式发生了变化、 - - + void signals_currentTextBlock(DocTextBlock* textBlock); // 当前操作的textBlock }; diff --git a/ofdEditor/model/Widget/DocInfoDialog.cpp b/ofdEditor/model/Widget/DocInfoDialog.cpp new file mode 100644 index 0000000..513a161 --- /dev/null +++ b/ofdEditor/model/Widget/DocInfoDialog.cpp @@ -0,0 +1,14 @@ +#include "DocInfoDialog.h" +#include "ui_DocInfoDialog.h" + +DocInfoDialog::DocInfoDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::DocInfoDialog) +{ + ui->setupUi(this); +} + +DocInfoDialog::~DocInfoDialog() +{ + delete ui; +} diff --git a/ofdEditor/model/Widget/DocInfoDialog.h b/ofdEditor/model/Widget/DocInfoDialog.h new file mode 100644 index 0000000..b911605 --- /dev/null +++ b/ofdEditor/model/Widget/DocInfoDialog.h @@ -0,0 +1,22 @@ +#ifndef DOCINFODIALOG_H +#define DOCINFODIALOG_H + +#include + +namespace Ui { +class DocInfoDialog; +} + +class DocInfoDialog : public QDialog +{ + Q_OBJECT + +public: + explicit DocInfoDialog(QWidget *parent = 0); + ~DocInfoDialog(); + +private: + Ui::DocInfoDialog *ui; +}; + +#endif // DOCINFODIALOG_H diff --git a/ofdEditor/model/Widget/DocInfoDialog.ui b/ofdEditor/model/Widget/DocInfoDialog.ui new file mode 100644 index 0000000..2b9d3bf --- /dev/null +++ b/ofdEditor/model/Widget/DocInfoDialog.ui @@ -0,0 +1,71 @@ + + + + + DocInfoDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + 30 + 240 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + buttonBox + accepted() + DocInfoDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DocInfoDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/ofdEditor/model/Widget/FontSettingDialog.cpp b/ofdEditor/model/Widget/FontSettingDialog.cpp index 84732d1..5b2f4a5 100644 --- a/ofdEditor/model/Widget/FontSettingDialog.cpp +++ b/ofdEditor/model/Widget/FontSettingDialog.cpp @@ -124,7 +124,7 @@ void FontSettingDialog::initConnect() this, SLOT(accept_slots())); // 窗口接受确认的信号 connect(this,SIGNAL(sendFont(QTextCharFormat&)), - this->textBlock,SLOT(setCharFormatOnWordOrSelection(QTextCharFormat&))); // 发送字体 + this->textBlock,SLOT(setCharFormatOnSelection(QTextCharFormat&))); // 发送字体 } diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index e7b846c..b43e9e8 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -50,7 +50,8 @@ SOURCES += model.cpp \ Convert/OFD_DocConvertor.cpp \ Convert/MergeCT_Texts.cpp \ Convert/Doc_OFDConvertor.cpp \ - Convert/Objects/MinTextUnit.cpp + Convert/Objects/MinTextUnit.cpp \ + Widget/DocInfoDialog.cpp HEADERS += model.h\ model_global.h \ @@ -80,7 +81,8 @@ HEADERS += model.h\ Convert/OFD_DocConvertor.h \ Convert/MergeCT_Texts.h \ Convert/Doc_OFDConvertor.h \ - Convert/Objects/MinTextUnit.h + Convert/Objects/MinTextUnit.h \ + Widget/DocInfoDialog.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 @@ -107,4 +109,5 @@ win32{ FORMS += \ Widget/ParagraphFormatWidget.ui \ Widget/ParagraphFormatDialog.ui \ - Widget/FontSettingDialog.ui + Widget/FontSettingDialog.ui \ + Widget/DocInfoDialog.ui diff --git a/ofdEditor/start/ActionConnector/ActionConnector.cpp b/ofdEditor/start/ActionConnector/ActionConnector.cpp index 8608a9a..eaa8186 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.cpp +++ b/ofdEditor/start/ActionConnector/ActionConnector.cpp @@ -34,7 +34,7 @@ void ActionConnector::setMainWindow(PassageMainWindow *mainWindow) */ void ActionConnector::addNewPage() { - this->updateActivePassage(); // 更新选择的文章。 + this->passage->appendNewPage(); // 在队尾增加一页 } @@ -49,7 +49,7 @@ void ActionConnector::addNewPage() void ActionConnector::addNewBlock(InsertBlockInfo& blockInfo) { - this->updateActivePassage(); // 更新文章 +// this->updateActivePassage(); // 更新文章 DocPage * page = qobject_cast(this->passage->focusWidget()); if(page == NULL) { @@ -87,29 +87,29 @@ void ActionConnector::addTableBlock() this->addNewBlock(blockInfo); } - - - /** * @Author Chaoqun - * @brief 更新,确保当前操作的对象是活动窗口 + * @brief 更新当前的活跃窗口 * @param 参数 * @return 返回值 - * @date 2017/05/15 + * @date 2017/06/23 */ -void ActionConnector::updateActivePassage() +void ActionConnector::updateActivePassage(QMdiSubWindow *window) { - DocPassage* temp = this->mainWindow->activeMdiChild(); - if(temp == NULL) + if(window == NULL) + { + qDebug() << "updateActivePassage NULL" + << "there's no actived window"; + return; + } + DocPassage* passage = qobject_cast(window->widget()); // 获得文档 + if(passage == NULL) { - qDebug()<< " You haven't select any passage. " - <<"void ActionConnector::updateActivePassage()"; - this->passage = NULL; + qDebug()<< "The active MdiWindow may not DocPassage"; } else { - this->passage = temp; - // 待CT_DocType配置好了,这里可以输出文档名称 + this->passage = passage; } } diff --git a/ofdEditor/start/ActionConnector/ActionConnector.h b/ofdEditor/start/ActionConnector/ActionConnector.h index ffe0728..62f82d6 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.h +++ b/ofdEditor/start/ActionConnector/ActionConnector.h @@ -3,6 +3,7 @@ #include #include "Doc/DocPage.h" +#include class DocPassage; class PassageMainWindow; @@ -21,6 +22,8 @@ public: ActionConnector(); ActionConnector(PassageMainWindow * mainWindow); + DocPage::Layer getDefaultLayer(){return this->defaultLayer;} + public slots: void setMainWindow(PassageMainWindow * mainWindow); // 设置主窗口 void addNewPage(); // 添加一个新页面 @@ -30,15 +33,14 @@ public slots: void addTableBlock(); // 插入表格 void setDefaultLayer(DocPage::Layer layer){this->defaultLayer = layer;} - DocPage::Layer getDefaultLayer(){return this->defaultLayer;} + + void updateActivePassage(QMdiSubWindow * window ); // 更新当前操作的文章 private: PassageMainWindow * mainWindow; // 主窗口 DocPassage * passage; // 当前活跃文档 DocPage::Layer defaultLayer; // 当前默认插入的层 - void updateActivePassage(); // 更新,确保当前操作的对象是活动的窗口 - void init(); // 初始化 diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index e915072..f7e0505 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include "Doc/DocPassage.h" @@ -23,6 +25,8 @@ #include "ofd_parser.h" #include "DataTypes/document/ofd.h" #include "Convert/OFD_DocConvertor.h" // OFD 转 Doc 工具 +#include "Doc/DocPage.h" +#include "Doc/DocTextBlock.h" PassageMainWindow::PassageMainWindow(QWidget *parent) :QMainWindow(parent) @@ -49,9 +53,11 @@ DocPassage *PassageMainWindow::createMdiChild() DocPassage * child = new DocPassage(this); child->addPage(new DocPage()); // 添加一个空白页 - this->area->addSubWindow(child); - child->setVisible(true); // 设置可见 - child->showMaximized(); +// this->area->addSubWindow(child); +// child->setVisible(true); // 设置可见 +// child->showMaximized(); + this->addDocPassage(child); // 加入到本视区 + return child; } @@ -269,6 +275,15 @@ void PassageMainWindow::connectAction() connect(this->insertTableAction, SIGNAL(triggered()), this->connector, SLOT(addTableBlock())); // 插入表格 + + connect(this->textFormat,SIGNAL(triggered(bool)), + this,SLOT(fontDialog())); // 修改字体 + + connect(this->paragraphFormat,SIGNAL(triggered(bool)), + this,SLOT(paragraphDialog())); // 修改段落 + + connect(this->area, SIGNAL(subWindowActivated(QMdiSubWindow*)), + this->connector, SLOT(updateActivePassage(QMdiSubWindow*))); // 检测ActivePassage更新 } /** @@ -316,15 +331,77 @@ void PassageMainWindow::openFile() OFDParser ofdParser(tempPath + "/OFD.xml"); // 新建临时路径 // OFDParser ofdParser("C:/Users/User/Desktop/表格/OFD.xml"); OFD* data = ofdParser.getData(); // 读取出OFD文件 + qDebug()<< "ofd file open"; OFD_DocConvertor convert; DocPassage* passage = convert.ofd_to_doc(data); this->addDocPassage(passage); // 添加文章 + } +} +/** + * @Author Chaoqun + * @brief 打开字体框 + * @param void + * @return void + * @date 2017/06/23 + */ +void PassageMainWindow::fontDialog() +{ + this->textBlock->customFontDialog(); // 用自定义窗口修改字体 +} +/** + * @Author Chaoqun + * @brief 用自定义窗口修改段落格式 + * @param void + * @return void + * @date 2017/06/23 + */ +void PassageMainWindow::paragraphDialog() +{ + this->textBlock->textParagraph(); // 用自定义段落窗口修改段落 +} - } +/** + * @Author Chaoqun + * @brief 接受当前处理的文字块的更新 + * @param DocTextBlock *textBlock + * @return void + * @date 2017/06/23 + */ +void PassageMainWindow::acceptTextBlock(DocTextBlock *textBlock) +{ + this->textBlock = textBlock; // 修改引用 +} + +/** + * @Author Chaoqun + * @brief 接受当前处理的块格式 + * @param QTextBlockFormat &blockFormat + * @return void + * @date 2017/06/23 + */ +void PassageMainWindow::acceptTextBlockFormat(QTextBlockFormat &blockFormat) +{ + this->_currentBlockFormat = &blockFormat; // 留下引用 + + // 更新界面显示 +} + +/** + * @Author Chaoqun + * @brief 接受字符格式 + * @param QTextCharFormat &charFormat + * @return void + * @date 2017/06/23 + */ +void PassageMainWindow::acceptTextCharFormat(QTextCharFormat &charFormat) +{ + this->_currentCharFormat = &charFormat; // 留下引用 + + // 更新界面显示 } /** @@ -359,5 +436,17 @@ DocPassage *PassageMainWindow::addDocPassage(DocPassage *passage) this->area->addSubWindow(passage); passage->setVisible(true); // 设置可见 passage->showMaximized(); + + // 处理变更的blockFormat + this->connect(passage,SIGNAL(signals_currentBlockFormatChanged(QTextBlockFormat&)), + this,SLOT(acceptTextBlockFormat(QTextBlockFormat&))); + // 处理变更的charFormat + this->connect(passage,SIGNAL(signals_currentCharFormatChanged(QTextCharFormat&)), + this,SLOT(acceptTextCharFormat(QTextCharFormat&))); + // 处理变更的textBlock + this->connect(passage,SIGNAL(signals_currentTextBlock(DocTextBlock*)), + this,SLOT(acceptTextBlock(DocTextBlock*))); + return passage; } + diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index 6d8ed6c..d07719f 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -4,11 +4,16 @@ #include #include #include +#include // 字体框 +#include // 选择框 class QAction; class QMenu; class QMdiArea; class DocPassage; +class DocTextBlock; +class QTextCharFormat; +class QTextBlockFormat; class ActionConnector; // 函数功能的中间件 // 编辑窗口的主界面 @@ -72,6 +77,7 @@ private: QAction * helpAciton; // 帮助文档,如何使用本软件 QMdiArea * area; // 多窗口区域 + QVectorpassages; // 存储所有的passage ActionConnector* connector; // 功能连接中间件 @@ -81,12 +87,19 @@ private: void connectAction(); // 链接QAction的相应事件 void disconnectAction(); // 断开事件响应 -private slots: - void openFile(); // 打开新文件 - + DocTextBlock *textBlock; // 文字块 + QTextCharFormat* _currentCharFormat; // 当前字符格式 + QTextBlockFormat* _currentBlockFormat; // 当前块格式 +private slots: + void openFile(); // 打开新文件 + void fontDialog(); // 打开字体框 + void paragraphDialog(); // 打开段落框 + void acceptTextBlock(DocTextBlock* textBlock); // 接受当前处理的文字块的更新 + void acceptTextBlockFormat(QTextBlockFormat& blockFormat); // 接受当前处理的块格式 + void acceptTextCharFormat(QTextCharFormat& charFormat); // 接受当前处理的字符格式 }; -- Gitee From a2fad887d9b6304bdb7b28a127d661a4bffb70db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Fri, 23 Jun 2017 20:09:09 +0800 Subject: [PATCH 02/83] =?UTF-8?q?=E4=BF=AE=E6=94=B9Model=E5=90=8E=E7=9A=84?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/OFD_DocConvertor.cpp | 26 +++++++++++--------- ofdEditor/model/Convert/OFD_DocConvertor.h | 3 ++- ofdEditor/model/Doc/DocPage.cpp | 1 + 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/ofdEditor/model/Convert/OFD_DocConvertor.cpp b/ofdEditor/model/Convert/OFD_DocConvertor.cpp index 5764488..ba8a2aa 100644 --- a/ofdEditor/model/Convert/OFD_DocConvertor.cpp +++ b/ofdEditor/model/Convert/OFD_DocConvertor.cpp @@ -37,7 +37,7 @@ DocPassage *OFD_DocConvertor::ofd_to_doc(OFD *ofd) try{ passage = new DocPassage(); - + passage->setVisible(false); // version passage->setVersion(ofd->getOfdVersion()); passage->setDocType(ofd->getDocType()); @@ -57,9 +57,8 @@ DocPassage *OFD_DocConvertor::ofd_to_doc(OFD *ofd) { // 生成每一页 - DocPage * newPage = this->buildDocPage((*pages)[i]); + DocPage * newPage = this->buildDocPage(passage, (*pages)[i]); newPage->setVisible(true); - passage->addPage(newPage); } } catch(...) @@ -67,10 +66,11 @@ DocPassage *OFD_DocConvertor::ofd_to_doc(OFD *ofd) qDebug() << "ofd_to_doc:exception."; } + passage->setVisible(true); return passage; } -DocPage *OFD_DocConvertor::buildDocPage(Page *ct_page) +DocPage *OFD_DocConvertor::buildDocPage(DocPassage *passage, Page *ct_page) { DocPage * page; try @@ -91,6 +91,7 @@ DocPage *OFD_DocConvertor::buildDocPage(Page *ct_page) page = new DocPage(); } + passage->addPage(page); // 加入到文章中来 page->setVisible(false); // 先隐藏显示 // 将每一层加入到页中 @@ -98,7 +99,7 @@ DocPage *OFD_DocConvertor::buildDocPage(Page *ct_page) for(int i = 0; i < layers->size(); i++) { CT_Layer* layer = (*layers)[i]; - qDebug() << "excute insertLayer: " << i; +// qDebug() << "excute insertLayer: " << i; this->insertLayer(page,layer); // 将该层的内容加入到页面中 } @@ -193,7 +194,7 @@ void OFD_DocConvertor::insertPageBlock(DocPage *page, */ void OFD_DocConvertor::insertCT_Text(DocPage *page, DocPage::Layer layer, CT_Text *text) { - qDebug() << "execute insert CT_Text" << text->getID(); +// qDebug() << "execute insert CT_Text" << text->getID(); CT_Color * fillColor = text->getFillColor(); // 获得填充颜色 QColor color = this->ctColorToQColor(fillColor); // 获得填充颜色 @@ -208,9 +209,9 @@ void OFD_DocConvertor::insertCT_Text(DocPage *page, DocPage::Layer layer, CT_Tex CT_Font* ctFont = (CT_Font*) base_font; QString font_name = ctFont->getFontName(); // 字体名 QString family_name = ctFont->getFamilyName(); // 字体族名 - qDebug() << font_name << " "<< family_name; +// qDebug() << font_name << " "<< family_name; textFont.setFamily(family_name); - qDebug() << "After setting font family :"<getText(); // 文本内容 qDebug() << "insert Content:" << content; - DocTextBlock *textBlock = new DocTextBlock(); - DocBlock *block = new DocBlock(); - block->setWidget(textBlock); + DocTextBlock *textBlock = new DocTextBlock(); // 新建文本块 + DocBlock *block = new DocBlock(); // 新建块 + block->setWidget(textBlock); // 将块放入文本块中 block->resize(UnitTool::mmToPixel(width), UnitTool::mmToPixel(height)); // 调整块大小 @@ -294,6 +295,7 @@ void OFD_DocConvertor::insertCT_Text(DocPage *page, DocPage::Layer layer, CT_Tex cursor.insertText(content); // 插入文本 +// qDebug()<<"page->addBlock"; page->addBlock(block,layer); // 插入到场景中 } diff --git a/ofdEditor/model/Convert/OFD_DocConvertor.h b/ofdEditor/model/Convert/OFD_DocConvertor.h index 288a4bd..035c000 100644 --- a/ofdEditor/model/Convert/OFD_DocConvertor.h +++ b/ofdEditor/model/Convert/OFD_DocConvertor.h @@ -33,7 +33,8 @@ public: private: OFD * ofdFile; // 当前处理时使用的ofd文件-用来方便获取到公用的特征 - DocPage * buildDocPage(Page * ct_page); // 生成页 + DocPage * buildDocPage(DocPassage * passage , + Page * ct_page); // 生成页 void insertLayer(DocPage * page, CT_Layer * layer ); // 将每一层加入到页中 diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index a01ce4a..e5c94f2 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -129,6 +129,7 @@ void DocPage::addBlock(DocBlock *block, DocPage::Layer layer) passage,SIGNAL(signals_currentTextBlock(DocTextBlock*))); } +// qDebug()<< "connect"; // 分到层 switch (layer) { -- Gitee From d78c8fc4f26d8e07c75d7509d77bad01f1d3d450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 24 Jun 2017 00:53:40 +0800 Subject: [PATCH 03/83] =?UTF-8?q?=E5=AE=8C=E5=96=84=20DocInfo=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E7=9A=84=E5=8A=9F=E8=83=BD=E5=B0=8F=E9=83=A8=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/OFD_DocConvertor.cpp | 3 +- ofdEditor/model/Doc/DocBlock.h | 4 - ofdEditor/model/Doc/DocPassage.cpp | 28 +- ofdEditor/model/Doc/DocPassage.h | 13 +- ofdEditor/model/Widget/DocInfoDialog.cpp | 126 +++ ofdEditor/model/Widget/DocInfoDialog.h | 21 +- ofdEditor/model/Widget/DocInfoDialog.ui | 228 ++++- .../model/Widget/ParagraphFormatDialog.ui | 600 ++++++------ .../model/Widget/ParagraphFormatWidget.ui | 872 +++++++----------- .../start/ActionConnector/ActionConnector.cpp | 33 + .../start/ActionConnector/ActionConnector.h | 1 + ofdEditor/start/ui/PassageMainWindow.cpp | 7 + ofdEditor/start/ui/PassageMainWindow.h | 1 + 13 files changed, 1039 insertions(+), 898 deletions(-) diff --git a/ofdEditor/model/Convert/OFD_DocConvertor.cpp b/ofdEditor/model/Convert/OFD_DocConvertor.cpp index ba8a2aa..ea000f2 100644 --- a/ofdEditor/model/Convert/OFD_DocConvertor.cpp +++ b/ofdEditor/model/Convert/OFD_DocConvertor.cpp @@ -44,7 +44,8 @@ DocPassage *OFD_DocConvertor::ofd_to_doc(OFD *ofd) QVector * bodys = ofd->getDocBodies(); DocBody * docBody = (*bodys)[0]; // DocBody - passage->setDocInfo(*(docBody->getDocInfo())); + + passage->setDocInfo(*(docBody->getDocInfo())); // 设置文档元信息 Document * document = (*(ofd->getDocuments()))[0]; // Document diff --git a/ofdEditor/model/Doc/DocBlock.h b/ofdEditor/model/Doc/DocBlock.h index 48a842a..76fbfde 100644 --- a/ofdEditor/model/Doc/DocBlock.h +++ b/ofdEditor/model/Doc/DocBlock.h @@ -50,8 +50,6 @@ public slots: // 槽函数 void setWidget(QWidget* widget); // 旧的函数 void setWidget(DocTextBlock *textBlock); // SetWidget - - protected: void paint(QPainter *painter, @@ -67,8 +65,6 @@ protected: void mouseReleaseEvent (QGraphicsSceneMouseEvent * event); void contextMenuEvent (QGraphicsSceneContextMenuEvent *event); // 邮件菜单吧 - - private: DocBox boundary; // 该块的外包矩形 DocLayer * layer; // 该块在哪一个层之中 diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index 92cbcc8..3364acf 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -10,7 +10,7 @@ #include #include #include - +#include /** * @Author Chaoqun @@ -193,7 +193,7 @@ void DocPassage::setDocInfo(CT_DocInfo &docInfo) * @brief 测试 * @param 参数 * @return 返回值 - * @date 2017/06/xx + * @date 2017/06/22 */ void DocPassage::testMessage() { @@ -207,11 +207,9 @@ void DocPassage::testMessage() * @return CT_DocInfo * @date 2017/05/23 */ -CT_DocInfo DocPassage::getDocInfo() +CT_DocInfo *DocPassage::getDocInfo() { - CT_DocInfo docInfo; - docInfo.copy( *this->docInfo); - return docInfo; + return this->docInfo; } /** @@ -262,6 +260,22 @@ CT_CommonData* DocPassage::getCommonData() return this->commonData; } +/** + * @Author Chaoqun + * @brief 设置 docID + * @param void + * @return void + * @date 2017/06/23 + */ +void DocPassage::resetDocId() +{ + QUuid uuid = QUuid::createUuid(); // 创建uuid + QString docId = uuid.toString(); // 转换为字符串 + qDebug() << "uuid : " << docId; + + this->docInfo->setDocID(docId); +} + /** * @Author Chaoqun * @brief 设置重置响应事件,窗口大小发生调整,将会调用这个函数u @@ -289,6 +303,8 @@ void DocPassage::closeEvent(QCloseEvent *event) void DocPassage::init() { + this->docInfo = new CT_DocInfo(); // 新建文档 元信息 + this->resetDocId(); // 设置UUID this->layout = new QVBoxLayout; // 新建布局 // 新增widget diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index 0502ecb..9a5e7d2 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -13,6 +13,8 @@ #include #include #include +#include + // 类声明 class DocPage; @@ -36,7 +38,7 @@ public: QString docType,double scaleFactor); ~DocPassage(); - CT_DocInfo getDocInfo(); // 获取CT_DocInfo数据 + CT_DocInfo* getDocInfo(); // 获取CT_DocInfo数据 QString getVersion( ){return this->version;} QString getDocType( ){return this->docType;} QVector& getPages(); // 获得文档中包含的所有页面 @@ -64,6 +66,9 @@ public slots: // DocType void setDocType(QString docType){this->docType = docType;} + // docId + void resetDocId(); // 重新设置DocId + void testMessage(); // 测试信号是否走通 protected: @@ -79,6 +84,12 @@ private: QVector pages; // 既作为数据,也作为渲染 + // 文件信息 + QString filePath; + QString fileName; + QString tempPath; // 保存成文件前的临时路径 + // 个人觉得可以用上UUID tmp/"uuid-fileName" + // 渲染区 QVBoxLayout * layout; // 纵向排列 QWidget * widget; // 用widget做缓冲 diff --git a/ofdEditor/model/Widget/DocInfoDialog.cpp b/ofdEditor/model/Widget/DocInfoDialog.cpp index 513a161..5054d2b 100644 --- a/ofdEditor/model/Widget/DocInfoDialog.cpp +++ b/ofdEditor/model/Widget/DocInfoDialog.cpp @@ -1,6 +1,10 @@ #include "DocInfoDialog.h" #include "ui_DocInfoDialog.h" +#include "DataTypes/document/ct_docinfo.h" +#include +#include + DocInfoDialog::DocInfoDialog(QWidget *parent) : QDialog(parent), ui(new Ui::DocInfoDialog) @@ -8,7 +12,129 @@ DocInfoDialog::DocInfoDialog(QWidget *parent) : ui->setupUi(this); } +DocInfoDialog::DocInfoDialog(CT_DocInfo *docInfo,QWidget *parent = 0): + QDialog(parent), ui(new Ui::DocInfoDialog) +{ + ui->setupUi(this); + this->docInfo = docInfo; + this->init(); + this->initUi(); +} + DocInfoDialog::~DocInfoDialog() { delete ui; } + +/** + * @Author Chaoqun + * @brief 初始化 + * @param void + * @return void + * @date 2017/06/23 + */ +void DocInfoDialog::init() +{ + connect(ui->author, SIGNAL(textChanged(QString)), + this,SLOT(editAuthor(QString))); // 作者 + connect(ui->title, SIGNAL(textChanged(QString)), + this, SLOT(editTitle(QString))); // 题目 + connect(ui->subject, SIGNAL(textChanged(QString)), + this, SLOT(editSubject(QString))); // 主题 + connect(ui->abstract_2, SIGNAL(textChanged(QString)), + this, SLOT(editAbstract(QString))); // 摘要 + connect(ui->fileType, SIGNAL(textChanged(QString)), + this,SLOT(editFileType(QString))); // 文档类型 + connect(ui->fileCover, SIGNAL(textChanged(QString)), + this,SLOT(editFileCover(QString))); // 文档封面 + connect(ui->btn_uuid, SIGNAL(pressed()), + this, SLOT(resetDocId())); // 重置UUID + +} + +/** + * @Author Chaoqun + * @brief 初始化UI界面 + * @param void + * @return void + * @date 2017/06/23 + */ +void DocInfoDialog::initUi() +{ + // 文件名 + + // 文件id + ui->docId->setText(this->docInfo->getDocID()); + + // 标题 + ui->title->setText(this->docInfo->getTitle()); + + // 作者 + ui->author->setText(this->docInfo->getAuthor()); + + // 主题 + ui->subject->setText(this->docInfo->getSubject()); + + // 摘要 + ui->abstract_2->setText(this->docInfo->getAbstract()); + + // 文档类型 + ui->fileType->setText(this->docInfo->getDocUsage()); + + // 文档封面 + ui->fileCover->setText(this->docInfo->getCover()); + + // 创建日期 + ui->creationDate->setText(this->docInfo->getCreationDate()); + + // 最后修改时间 + ui->modDate->setText(this->docInfo->getModDate()); + + // 创建者应用程序 + ui->createApp->setText(this->docInfo->getCreator()); + + // 应用程序版本 + ui->creatorVersion->setText(this->docInfo->getCreatorVersion()); + +} + + +void DocInfoDialog::editTitle(const QString &text) +{ + this->docInfo->setTitle(text); // 设置标题 +} + +void DocInfoDialog::editAuthor(const QString &text) +{ + this->docInfo->setAuthor(text); +} + +void DocInfoDialog::editSubject(const QString &text) +{ + this->docInfo->setSubject(text); +} + +void DocInfoDialog::editAbstract(const QString &text) +{ + this->docInfo->setAbstract(text); +} + +void DocInfoDialog::editFileType(const QString &text) +{ + this->docInfo->setDocUsage(text); +} + +void DocInfoDialog::editFileCover(const QString &text) +{ + this->docInfo->setCover(text); +} + +void DocInfoDialog::resetDocId() +{ + QUuid uuid = QUuid::createUuid(); // 创建一个新的uuid + QString docId = uuid.toString(); + qDebug() << "new uuid: " << docId; + + this->docInfo->setDocID(docId); + ui->docId->setText(docId); +} diff --git a/ofdEditor/model/Widget/DocInfoDialog.h b/ofdEditor/model/Widget/DocInfoDialog.h index b911605..1593f96 100644 --- a/ofdEditor/model/Widget/DocInfoDialog.h +++ b/ofdEditor/model/Widget/DocInfoDialog.h @@ -2,21 +2,40 @@ #define DOCINFODIALOG_H #include +#include "model_global.h" +class CT_DocInfo; // 文档元信息 namespace Ui { class DocInfoDialog; } -class DocInfoDialog : public QDialog +class MODELSHARED_EXPORT DocInfoDialog : public QDialog { Q_OBJECT public: explicit DocInfoDialog(QWidget *parent = 0); + + DocInfoDialog(CT_DocInfo* docInfo,QWidget *parent); + ~DocInfoDialog(); private: Ui::DocInfoDialog *ui; + CT_DocInfo* docInfo; // 文档元信息 + void init(); // 初始化 + + void initUi(); // 初始化ui + +public slots: + void editTitle(const QString & text); // 修改标题 + void editAuthor(const QString & text); // 修改作者 + void editSubject(const QString & text); // 修改主题 + void editAbstract(const QString & text); // 修改摘要 + void editFileType(const QString & text); // 文档类型 + void editFileCover(const QString & text); // 文档封面 + void resetDocId(); // 重置UUID + }; #endif // DOCINFODIALOG_H diff --git a/ofdEditor/model/Widget/DocInfoDialog.ui b/ofdEditor/model/Widget/DocInfoDialog.ui index 2b9d3bf..28d14a4 100644 --- a/ofdEditor/model/Widget/DocInfoDialog.ui +++ b/ofdEditor/model/Widget/DocInfoDialog.ui @@ -1,25 +1,23 @@ + - - - DocInfoDialog - + 0 0 - 400 - 300 + 483 + 641 Dialog - + - 30 - 240 + 70 + 590 341 32 @@ -31,8 +29,218 @@ QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + 10 + 20 + 461 + 361 + + + + 说明 + + + + + 21 + 21 + 411 + 301 + + + + + + + 文件: + + + + + + + 文档ID: + + + + + + + 更改 + + + + + + + 标题: + + + + + + + + + + 作者: + + + + + + + + + + 主题: + + + + + + + + + + 摘要: + + + + + + + + + + 关键字: + + + + + + + + + + 文档类型: + + + + + + + + + + 文档封面: + + + + + + + + + + 创建日期: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10 + 420 + 461 + 151 + + + + 高级 + + + + + 20 + 30 + 431 + 111 + + + + + + + 最近修改时间: + + + + + + + + + + + + + + 创建应用程序: + + + + + + + + + + + + + + 应用程序版本: + + + + + + + + + + + + + - diff --git a/ofdEditor/model/Widget/ParagraphFormatDialog.ui b/ofdEditor/model/Widget/ParagraphFormatDialog.ui index 661cb5e..c5adafc 100644 --- a/ofdEditor/model/Widget/ParagraphFormatDialog.ui +++ b/ofdEditor/model/Widget/ParagraphFormatDialog.ui @@ -22,362 +22,278 @@ false - - - - 10 - 600 - 461 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - + 10 30 - 461 - 131 + 451 + 451 - - 对齐方式 - - - - - 10 - 30 - 70 - 20 - - - - 水平 - - - - - - 100 - 30 - 93 - 24 - - - - 0 - - - QComboBox::AdjustToContents - - - - 左对齐 - - - - - 右对齐 - - - - - 居中 - - - - - 两端对齐 - - - - - - - 10 - 60 - 70 - 20 - - - - 竖直 - - - - - - 100 - 60 - 61 - 24 - - - - QComboBox::AdjustToContents - - - - 居上 - - - - - 居下 - - - - - 居中 - - - - - - - 10 - 90 - 70 - 20 - - - - 文字方向 - - - - - - 100 - 90 - 77 - 24 - - - - QComboBox::AdjustToContents - - - - 左到右 - - - - - 右到左 - - - - - - - - 10 - 170 - 461 - 91 - - - - 缩进 - - - - - 10 - 30 - 70 - 20 - - - - 整体缩进 - - - - - - 100 - 30 - 100 - 20 - - - - 10000 - - - - - - 100 - 60 - 100 - 20 - - - - 10000.000000000000000 - - - - - - 10 - 60 - 70 - 20 - - - - 首行缩进 - - - - - - - 10 - 290 - 461 - 161 - - - - 间距 - - - - - 100 - 60 - 100 - 20 - - - - 10000.000000000000000 - - - - - - 10 - 60 - 70 - 20 - - - - 段后 - - - - - - 100 - 30 - 100 - 20 - - - - 10000.000000000000000 - - - - - - 10 - 30 - 70 - 20 - - - - 段前 - - - - - - 330 - 90 - 100 - 20 - - - - 10000.000000000000000 - - - - - - 240 - 90 - 70 - 20 - - - - - - - - - - 100 - 90 - 93 - 24 - - - - QComboBox::AdjustToContents - + - - 单倍行距 - + + + 对齐方式 + + + + + 10 + 30 + 261 + 91 + + + + + + + 水平 + + + + + + + 0 + + + QComboBox::AdjustToContents + + + + 左对齐 + + + + + 右对齐 + + + + + 居中 + + + + + 两端对齐 + + + + + + + + 竖直 + + + + + + + QComboBox::AdjustToContents + + + + 居上 + + + + + 居下 + + + + + 居中 + + + + + + + + 文字方向 + + + + + + + QComboBox::AdjustToContents + + + + 左到右 + + + + + 右到左 + + + + + + + - - 多倍行距 - + + + 缩进 + + + + + 10 + 30 + 261 + 81 + + + + + + + 整体缩进 + + + + + + + 10000 + + + + + + + 首行缩进 + + + + + + + 10000.000000000000000 + + + + + + - - 固定值 - + + + 间距 + + + + + 10 + 30 + 431 + 91 + + + + + + + 段前 + + + + + + + 10000.000000000000000 + + + + + + + 段后 + + + + + + + 10000.000000000000000 + + + + + + + 行距策略 + + + + + + + QComboBox::AdjustToContents + + + + 单倍行距 + + + + + 多倍行距 + + + + + 固定值 + + + + + 最小值 + + + + + + + + + + + + + + + 10000.000000000000000 + + + + + + - - 最小值 - + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + - - - - - 10 - 90 - 70 - 20 - - - - 行距策略 - - + diff --git a/ofdEditor/model/Widget/ParagraphFormatWidget.ui b/ofdEditor/model/Widget/ParagraphFormatWidget.ui index 993df7d..a4b4401 100644 --- a/ofdEditor/model/Widget/ParagraphFormatWidget.ui +++ b/ofdEditor/model/Widget/ParagraphFormatWidget.ui @@ -34,542 +34,348 @@ 段落属性 - + 0 - 0 - 2 - 2 - - - - - - - - 0 - 10 - 70 - 20 - - - - - 16 - - - - 常规 - - - Qt::AutoText - - - Qt::AlignCenter - - - - - - 10 - 40 - 70 - 25 - - - - 对齐方式: - - - - - - 100 - 40 - 100 - 25 - - - - QComboBox::AdjustToMinimumContentsLength - - - 10 - - - - 左对齐 - - - - - 右对齐 - - - - - 居中 - - - - - 自动对齐 - - - - - - - 0 - 110 - 70 - 20 - - - - - 宋体 - 16 - - - - 缩进 - - - Qt::AlignCenter - - - - - - 10 - 80 - 461 - 20 - - - - Qt::Horizontal - - - - - - 10 - 420 - 461 - 20 - - - - Qt::Horizontal - - - - - - 10 - 230 - 461 - 20 - - - - Qt::Horizontal - - - - - - 10 - 150 - 70 - 20 - - - - 整体缩进 - - - - - - 100 - 150 - 100 - 20 - - - - Qt::AlignCenter - - - - - - 10 - 180 - 70 - 20 - - - - 首行缩进 - - - - - - 100 - 180 - 100 - 20 - - - - Qt::AlignCenter - - - - - - 0 - 260 - 70 - 20 - - - - - 宋体 - 16 - - - - 间距 - - - Qt::AlignCenter - - - - - - 100 - 300 - 100 - 20 - - - - Qt::AlignCenter - - - - - - 10 - 330 - 70 - 20 - - - - 段后 - - - - - - 100 - 330 - 100 - 20 - - - - Qt::AlignCenter - - - - - - 10 - 300 - 70 - 20 - - - - 段前 - - - - - - 10 - 360 - 70 - 25 - - - - 行高策略 - - - - - - 100 - 360 - 100 - 25 - - - - QComboBox::AdjustToMinimumContentsLength - - - 10 - - - - 单倍行高 - - - - - 多倍行高 - - - - - 固定值 - - - - - 最小值 - - - - - - - 250 - 360 - 70 - 20 - - - - 行高值 - - - - - - 320 - 360 - 100 - 20 - - - - Qt::AlignCenter - - - - - - 10 - 490 - 70 - 20 - - - - 上边距 - - - - - - 100 - 520 - 100 - 20 - - - - Qt::AlignCenter - - - - - - 100 - 490 - 100 - 20 - - - - Qt::AlignCenter - - - - - - 0 - 450 - 70 - 20 - - - - - 宋体 - 16 - - - - 边距 - - - Qt::AlignCenter - - - - - - 10 - 520 - 70 - 20 - - - - 下边距 - - - - - - 340 - 520 - 100 - 20 - - - - Qt::AlignCenter - - - - - - 250 - 490 - 70 - 20 - - - - 左边距 - - - - - - 340 - 490 - 100 - 20 - - - - Qt::AlignCenter - - - - - - 250 - 520 - 70 - 20 - - - - 右边距 - - - - - - 270 - 610 - 80 - 25 - - - - 确定 - - - - - - 360 - 610 - 80 - 25 - - - - 取消 - - - - - - 250 - 40 - 70 - 25 - - - - 文字方向 - - - - - - 340 - 40 - 100 - 25 - - - - QComboBox::AdjustToMinimumContentsLength - - - 10 - - - - 自左向右 - - - - - 自右向左 - - + 50 + 431 + 421 + + + + + + + + + + + 16 + + + + 常规 + + + Qt::AutoText + + + Qt::AlignCenter + + + + + + + 对齐方式: + + + + + + + QComboBox::AdjustToMinimumContentsLength + + + 10 + + + + 左对齐 + + + + + 右对齐 + + + + + 居中 + + + + + 自动对齐 + + + + + + + + 文字方向 + + + + + + + QComboBox::AdjustToMinimumContentsLength + + + 10 + + + + 自左向右 + + + + + 自右向左 + + + + + + + + Qt::Horizontal + + + + + + + + 宋体 + 16 + + + + 缩进 + + + Qt::AlignCenter + + + + + + + 整体缩进 + + + + + + + Qt::AlignCenter + + + + + + + 首行缩进 + + + + + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + + + + + + 宋体 + 16 + + + + 间距 + + + Qt::AlignCenter + + + + + + + 段前 + + + + + + + Qt::AlignCenter + + + + + + + 段后 + + + + + + + Qt::AlignCenter + + + + + + + 行高策略 + + + + + + + QComboBox::AdjustToMinimumContentsLength + + + 10 + + + + 单倍行高 + + + + + 多倍行高 + + + + + 固定值 + + + + + 最小值 + + + + + + + + 行高值 + + + + + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + + + + + + 宋体 + 16 + + + + 边距 + + + Qt::AlignCenter + + + + + + + 上边距 + + + + + + + Qt::AlignCenter + + + + + + + 左边距 + + + + + + + Qt::AlignCenter + + + + + + + 下边距 + + + + + + + Qt::AlignCenter + + + + + + + 右边距 + + + + + + + Qt::AlignCenter + + + + + + + 确定 + + + + + + + 取消 + + + + diff --git a/ofdEditor/start/ActionConnector/ActionConnector.cpp b/ofdEditor/start/ActionConnector/ActionConnector.cpp index f26a75e..badff0f 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.cpp +++ b/ofdEditor/start/ActionConnector/ActionConnector.cpp @@ -2,6 +2,8 @@ #include "Doc/DocPassage.h" #include "ui/PassageMainWindow.h" #include "Doc/DocPage.h" +#include "DataTypes/document/ct_docinfo.h" +#include "Widget/DocInfoDialog.h" #include #include @@ -18,6 +20,22 @@ ActionConnector::ActionConnector(PassageMainWindow *mainWindow) init(); } +void ActionConnector::showAttribute() +{ + if(this->passage == NULL) + { + qDebug() << "show attribute"; + return; + } + + + CT_DocInfo * docInfo = this->passage->getDocInfo(); + DocInfoDialog* dialog = new DocInfoDialog(docInfo,this->mainWindow); // 设置窗口 + dialog->exec(); // 运行 + qDebug() << "show Attribute"; + +} + void ActionConnector::setMainWindow(PassageMainWindow *mainWindow) { this->mainWindow = mainWindow; @@ -35,6 +53,8 @@ void ActionConnector::setMainWindow(PassageMainWindow *mainWindow) void ActionConnector::addNewPage() { + if(this->passage == NULL) + return; this->passage->appendNewPage(); // 在队尾增加一页 } @@ -48,6 +68,10 @@ void ActionConnector::addNewPage() */ void ActionConnector::addNewBlock(InsertBlockInfo& blockInfo) { + if(this->passage == NULL) + { + return; + } // this->updateActivePassage(); // 更新文章 DocPage * page = qobject_cast(this->passage->focusWidget()); @@ -71,18 +95,24 @@ void ActionConnector::addNewBlock(InsertBlockInfo& blockInfo) void ActionConnector::addTextBlock() { + if(this->passage == NULL) + return; InsertBlockInfo blockInfo(this->defaultLayer,DocPage::text); // 设置插入文本框信息 this->addNewBlock(blockInfo); } void ActionConnector::addImageBlock() { + if(this->passage == NULL) + return; InsertBlockInfo blockInfo(this->defaultLayer,DocPage::image); // 设置插入文本框信息 this->addNewBlock(blockInfo); } void ActionConnector::addTableBlock() { + if(this->passage == NULL) + return; InsertBlockInfo blockInfo(this->defaultLayer,DocPage::table); // 设置插入文本框信息 this->addNewBlock(blockInfo); } @@ -115,12 +145,14 @@ void ActionConnector::updateActivePassage(QMdiSubWindow *window) { qDebug() << "updateActivePassage NULL" << "there's no actived window"; + this->passage = NULL; return; } DocPassage* passage = qobject_cast(window->widget()); // 获得文档 if(passage == NULL) { qDebug()<< "The active MdiWindow may not DocPassage"; + this->passage = NULL; } else { @@ -131,4 +163,5 @@ void ActionConnector::updateActivePassage(QMdiSubWindow *window) void ActionConnector::init() { this->defaultLayer = DocPage::Body; + this->passage = NULL; // 初始化为空 } diff --git a/ofdEditor/start/ActionConnector/ActionConnector.h b/ofdEditor/start/ActionConnector/ActionConnector.h index 9020998..b2d2eb6 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.h +++ b/ofdEditor/start/ActionConnector/ActionConnector.h @@ -25,6 +25,7 @@ public: DocPage::Layer getDefaultLayer(){return this->defaultLayer;} public slots: + void showAttribute(); // 显示文档元信息 void setMainWindow(PassageMainWindow * mainWindow); // 设置主窗口 void addNewPage(); // 添加一个新页面 void addNewBlock(InsertBlockInfo &blockInfo); // 插入一个块 diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index aa004e8..4fe5af5 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -121,6 +121,9 @@ void PassageMainWindow::initAction() this->printAction->setStatusTip(tr("Print your document")); this->printAction->setIcon(QIcon(":/icons/source/icons/print.png")); + this->attributeAction = new QAction(tr("Attribute"),NULL); // 文档属性 + this->attributeAction->setStatusTip(tr("Show you the attribute of the actived passage")); + this->undoAction = new QAction(tr("Undo"),NULL); // 撤销操作 this->undoAction->setStatusTip(tr("Undo your last action")); this->undoAction->setShortcut(QKeySequence::Undo); @@ -199,6 +202,7 @@ void PassageMainWindow::initAction() this->filesMenu->addAction(this->saveAction); this->filesMenu->addAction(this->saveAsAction); this->filesMenu->addAction(this->printAction); + this->filesMenu->addAction(this->attributeAction); this->editMenu->addAction(this->undoAction); this->editMenu->addAction(this->redoAction); @@ -261,6 +265,9 @@ void PassageMainWindow::connectAction() connect(this->openFileAtcion, SIGNAL(triggered(bool)), this, SLOT(openFile())); //打开文件 + connect(this->attributeAction, SIGNAL(triggered(bool)), + this->connector, SLOT(showAttribute())); // 显示文档属性 + connect(this->insertNewPageAction, SIGNAL(triggered(bool)), this->connector, SLOT(addNewPage())); // 在文章尾部加入新的一页 diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index d07719f..8ac6311 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -51,6 +51,7 @@ private: QAction * saveAction; // 保存 QAction * saveAsAction; // 另存为 QAction * printAction; // 打印 + QAction * attributeAction; // 文档属性 // 编辑 QAction * undoAction; // 撤销 -- Gitee From b4e9402a627a0f546a43061fb24b49fe0ab207bf Mon Sep 17 00:00:00 2001 From: Pan Yanxing Date: Sat, 24 Jun 2017 02:00:12 +0800 Subject: [PATCH 04/83] =?UTF-8?q?=E6=AD=A3=E5=9C=A8=E5=AE=9E=E7=8E=B0DocIm?= =?UTF-8?q?ageBlock=EF=BC=8C=E7=9B=AE=E5=89=8D=E5=9B=BE=E7=89=87=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E6=8F=92=E5=85=A5=E3=80=81=E7=A7=BB=E5=8A=A8=E3=80=82?= =?UTF-8?q?=E5=A4=A7=E5=B0=8F=E8=B0=83=E8=8A=82=E5=87=BA=E4=BA=86=E7=82=B9?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocBlock.cpp | 42 +++++++++++++-- ofdEditor/model/Doc/DocBlock.h | 8 ++- ofdEditor/model/Doc/DocGraph.cpp | 3 +- ofdEditor/model/Doc/DocGraph.h | 5 +- ofdEditor/model/Doc/DocImage.cpp | 7 --- ofdEditor/model/Doc/DocImageBlock.cpp | 54 +++++++++++++++++++ .../model/Doc/{DocImage.h => DocImageBlock.h} | 17 +++--- ofdEditor/model/Doc/DocPage.cpp | 52 ++++++++++++++++-- ofdEditor/model/Doc/DocPage.h | 3 ++ ofdEditor/model/Doc/DocParaStyle.cpp | 2 +- ofdEditor/model/Doc/DocPicture.cpp | 3 +- ofdEditor/model/Doc/DocPicture.h | 6 +-- ofdEditor/model/model.pro | 8 +-- ofdEditor/ofd/DataTypes/basic_datatype.h | 1 - ofdEditor/ofd/ofd_parser.cpp | 27 ++++++---- .../start/ActionConnector/ActionConnector.cpp | 26 ++++++--- ofdEditor/start/main.cpp | 3 +- 17 files changed, 203 insertions(+), 64 deletions(-) delete mode 100644 ofdEditor/model/Doc/DocImage.cpp create mode 100644 ofdEditor/model/Doc/DocImageBlock.cpp rename ofdEditor/model/Doc/{DocImage.h => DocImageBlock.h} (30%) diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index 49d029f..69e685d 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -29,6 +29,8 @@ DocBlock::DocBlock(QGraphicsItem *parent , Qt::WindowFlags wFlags) this->setFlag(QGraphicsProxyWidget::ItemIsSelectable, true); // 可选择 this->setFlag(QGraphicsProxyWidget::ItemIsFocusable, true); // 可关注 this->setAcceptHoverEvents(true); + textBlock = NULL; + imageBlock = NULL; } /** @@ -254,7 +256,7 @@ void DocBlock::hoverMoveEvent(QGraphicsSceneHoverEvent *event) */ void DocBlock::mousePressEvent(QGraphicsSceneMouseEvent *event) { - + qDebug() << "Pressed."; QPointF pos = event->pos(); // 获取鼠标位置 // qDebug()<<"DocBlock Mouse Postion" << pos.x() // << ", "<rectAdjust = this->currentStatus(event->pos()); } - +qDebug() << (rectAdjust == DocBlock::blockResize); QGraphicsProxyWidget::mousePressEvent(event); } @@ -278,9 +280,10 @@ void DocBlock::mousePressEvent(QGraphicsSceneMouseEvent *event) */ void DocBlock::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - + qDebug() << (rectAdjust == DocBlock::blockResize); if (this->rectAdjust == blockResize) { +// qDebug() << "???"; qreal w = event->pos().x(); qreal h = event->pos().y(); @@ -289,6 +292,8 @@ void DocBlock::mouseMoveEvent(QGraphicsSceneMouseEvent *event) if (h > this->minimumHeight()) blockSize.setHeight(h); +// qDebug() << "Block Size Width = " << blockSize.width(); +// qDebug() << "Block Size Height = " << blockSize.height(); this->resize(blockSize); // 调整大小 this->setCursor(Qt::SizeFDiagCursor); } @@ -386,8 +391,10 @@ DocBlock::RectAdjustStatus DocBlock::currentStatus(const QPointF &pos) { if((pos.x() - this->size().width() + 15) > (this->size().height() - pos.y())) + { + //qDebug() << "Mouse resizing."; return blockResize; - + } // 画出可以移动的边缘 qreal moveMargin = 5; // 边缘多少像素内可以移动 QRectF left(0,0, @@ -438,6 +445,31 @@ bool DocBlock::isTextBlock() */ DocTextBlock *DocBlock::getTextBlock() { - return this->textBlock; + if (isTextBlock()) + return this->textBlock; } +/** + * @Author Pan + * @brief 判断是其中装的是否是DocImageBlock + * @param void + * @return bool + * @date 2017/06/23 + */ +bool DocBlock::isImageBlock() +{ + return imageBlock != NULL; +} + +/** + * @Author Pan + * @brief 获得DocImageBlock + * @param void + * @return void + * @date 2017/06/23 + */ +DocImageBlock * DocBlock::getImageBlock() +{ + if (isImageBlock()) + return imageBlock; +} diff --git a/ofdEditor/model/Doc/DocBlock.h b/ofdEditor/model/Doc/DocBlock.h index 48a842a..93aee45 100644 --- a/ofdEditor/model/Doc/DocBlock.h +++ b/ofdEditor/model/Doc/DocBlock.h @@ -5,13 +5,14 @@ #include "Doc/DocBasicTypes.h" #include #include +#include "DocImageBlock.h" class DocLayer; class QPainter; class DocTextBlock; class DocPage; class DocPassage; - +class DocImageBlock; /** * @Author Chaoqun @@ -38,6 +39,8 @@ public: bool isTextBlock(); // 判断是否DocBlock装的是否是DocTextBlock DocTextBlock *getTextBlock(); // 获得DocTextBlock + bool isImageBlock(); + DocImageBlock *getImageBlock(); //获得DocImageBlock public slots: // 槽函数 void setLayer(DocLayer * layer){this->layer = layer;} @@ -75,7 +78,8 @@ private: QSizeF blockSize; // 用来纪录大小 QPointF blockOldPos; // 用来记录旧的位置 - DocTextBlock* textBlock; // 存下引用 + DocTextBlock * textBlock; // 存下引用 + DocImageBlock * imageBlock; //同上 bool isFocused; // 是否被聚焦 bool blockIsResizing; // 是否正在改变大小 diff --git a/ofdEditor/model/Doc/DocGraph.cpp b/ofdEditor/model/Doc/DocGraph.cpp index c554b77..5b9d057 100644 --- a/ofdEditor/model/Doc/DocGraph.cpp +++ b/ofdEditor/model/Doc/DocGraph.cpp @@ -1,8 +1,7 @@ #include "DocGraph.h" -DocGraph::DocGraph(QObject *parent) - :DocImage(parent) +DocGraph::DocGraph() { } diff --git a/ofdEditor/model/Doc/DocGraph.h b/ofdEditor/model/Doc/DocGraph.h index 6e576b1..9828f1a 100644 --- a/ofdEditor/model/Doc/DocGraph.h +++ b/ofdEditor/model/Doc/DocGraph.h @@ -3,14 +3,11 @@ #include "model_global.h" // 导出lib使用 #include "Doc/DocBasicTypes.h" -#include "Doc/DocImage.h" class MODELSHARED_EXPORT DocGraph - :public DocImage { - Q_OBJECT public: - DocGraph(QObject *parent = NULL); + DocGraph(); ~DocGraph(); }; diff --git a/ofdEditor/model/Doc/DocImage.cpp b/ofdEditor/model/Doc/DocImage.cpp deleted file mode 100644 index ba350ba..0000000 --- a/ofdEditor/model/Doc/DocImage.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "DocImage.h" - -// 测试 -DocImage::DocImage(QObject *parent) -{ - -} diff --git a/ofdEditor/model/Doc/DocImageBlock.cpp b/ofdEditor/model/Doc/DocImageBlock.cpp new file mode 100644 index 0000000..42af909 --- /dev/null +++ b/ofdEditor/model/Doc/DocImageBlock.cpp @@ -0,0 +1,54 @@ +#include "DocImageBlock.h" +#include +#include + +DocImageBlock::DocImageBlock(QWidget *parent) + :QLabel(parent) +{ + //图片填满组件 + setScaledContents(true); + this->setMinimumSize(5, 5); + this->setFrameStyle(QFrame::NoFrame); + this->setFocusPolicy(Qt::StrongFocus); + +} + +/** + * @Author Pan + * @brief 设置DocImageBlock中的图像 + * @param QPixmap & + * @return void + * @date 2017/06/23 + */ +void DocImageBlock::setImage(QPixmap & pixmap) +{ + this->setPixmap(pixmap); +} + +/** + * @Author Pan + * @brief 焦点聚焦,显示边框 + * @param QFocusEvent + * @return void + * @date 2017/06/23 + */ +void DocImageBlock::focusInEvent(QFocusEvent *e) +{ + //qDebug() << "focus In Event"; + this->setFrameShape(QFrame::Box); + this->setLineWidth(1); + QLabel::focusInEvent(e); +} + +/** + * @Author Pan + * @brief 焦点移出,隐藏边框 + * @param QFocusEvent *e + * @return void + * @date 2017/06/23 + */ +void DocImageBlock::focusOutEvent(QFocusEvent *e) +{ + this->setFrameStyle(QFrame::NoFrame); + QLabel::focusOutEvent(e); +} diff --git a/ofdEditor/model/Doc/DocImage.h b/ofdEditor/model/Doc/DocImageBlock.h similarity index 30% rename from ofdEditor/model/Doc/DocImage.h rename to ofdEditor/model/Doc/DocImageBlock.h index 3cdff44..ac41d51 100644 --- a/ofdEditor/model/Doc/DocImage.h +++ b/ofdEditor/model/Doc/DocImageBlock.h @@ -1,22 +1,23 @@ -#ifndef DOCIMAGE_H -#define DOCIMAGE_H +#ifndef DOCIMAGEBLOCK_H +#define DOCIMAGEBLOCK_H #include "model_global.h" #include "Doc/DocBlock.h" - -#include // 文档 +#include //存放图片的QWidget // 本类型用来表述文章中的图形、图片之类的 -class MODELSHARED_EXPORT DocImage - :public QTextDocument +class MODELSHARED_EXPORT DocImageBlock : public QLabel { Q_OBJECT public: - DocImage(QObject *parent = NULL); + DocImageBlock(QWidget *parent = NULL); + void setImage(QPixmap & pixmap); + void focusInEvent(QFocusEvent *ev); + void focusOutEvent(QFocusEvent *ev); private: }; -#endif // DOCIMAGE_H +#endif // DOCIMAGEBLOCK_H diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index a01ce4a..07e41c3 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -4,7 +4,7 @@ #include "Doc/DocBlock.h" #include "Doc/DocTextBlock.h" #include "Doc/DocPageScene.h" -#include "Doc/DocImage.h" +#include "Doc/DocImageBlock.h" #include "Doc/DocTable.h" #include "Doc/DocPicture.h" #include "Doc/DocGraph.h" @@ -17,6 +17,12 @@ #include #include #include +#include + +#include +#include +#include +#include "DocImageBlock.h" // #include "DataTypes/page/CT_PageArea.h" // 页面大小 @@ -384,15 +390,12 @@ void DocPage::mouseReleaseEvent(QMouseEvent *event) { newBlock->setWidget(new DocTextBlock()); // 插入文字框 } - else if(this->insertBlockInfo->type == image) - { -// newBlock->setWidget(new DocImage()); // 插入图片框 - } else if(this->insertBlockInfo->type == table) { newBlock->setWidget(new DocTable()); // 插入表格框 } + // 设置位置大小 QRectF rect = UnitTool::getBox(this->oldPos,newPos); newBlock->setPos(rect.x(),rect.y()); @@ -447,3 +450,42 @@ void DocPage::init() // this->setBackgroundRole(QPalette::Dark); this->insertBlockInfo = NULL; } + +void DocPage::addImage() +{ + qDebug() << "???"; + //打开对话框,选取一个图片文件 + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open File"), QDir::currentPath()); + if (!fileName.isEmpty()) { + QPixmap image(fileName); + if (image.isNull()) { + QMessageBox::information(this, tr("OFD Editor"), + tr("Cannot open file %1.").arg(fileName)); + return; + } + //新建一个DocBlock + DocBlock * newBlock = new DocBlock(); + //新建一个图片框 + DocImageBlock * new_image_block = new DocImageBlock(); + newBlock->setWidget(new_image_block); + new_image_block->setImage(image); + double page_width = this->width(), page_height = this->height(); + qDebug() << "Page Width: " << this->width(); + qDebug() << "Page Height: " << this->height(); + qDebug() << "Image Width: " << image.width(); + qDebug() << "Image Height: " << image.height(); + double ratio; + if (image.width() > page_width || image.height() > page_height) + { + ratio = std::min(page_width / image.width(), page_height / image.height()); + ratio *= 0.8; + } + else ratio = 1.0; + qDebug() << "Ratio = " << ratio; + newBlock->setPos((page_width - image.width() * ratio) / 2, (page_height - image.height() * ratio) / 2); + newBlock->resize(image.width() * ratio,image.height() * ratio); + + this->addBlock(newBlock,this->insertBlockInfo->layer); + } +} diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index 8291d08..4ea6cc7 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -44,6 +44,9 @@ public: BlockFlag getBlockFlag(){return this->newBlockFlag;} + //Pan + void addImage(); + public slots: void setSize(double width, double height); // 设置页面大小 void setPassage(DocPassage * passage); // 设置文章 diff --git a/ofdEditor/model/Doc/DocParaStyle.cpp b/ofdEditor/model/Doc/DocParaStyle.cpp index f96a407..c1638e4 100644 --- a/ofdEditor/model/Doc/DocParaStyle.cpp +++ b/ofdEditor/model/Doc/DocParaStyle.cpp @@ -1,5 +1,5 @@ #include "DocParaStyle.h" -#include "Doc/DocImage.h" +#include "Doc/DocImageBlock.h" DocParaStyle::DocParaStyle() diff --git a/ofdEditor/model/Doc/DocPicture.cpp b/ofdEditor/model/Doc/DocPicture.cpp index b851a29..b4743bd 100644 --- a/ofdEditor/model/Doc/DocPicture.cpp +++ b/ofdEditor/model/Doc/DocPicture.cpp @@ -1,8 +1,7 @@ #include "DocPicture.h" -DocPicture::DocPicture(QObject *parent) - :DocImage(parent) +DocPicture::DocPicture() { } diff --git a/ofdEditor/model/Doc/DocPicture.h b/ofdEditor/model/Doc/DocPicture.h index ca9d179..87b6c31 100644 --- a/ofdEditor/model/Doc/DocPicture.h +++ b/ofdEditor/model/Doc/DocPicture.h @@ -3,16 +3,14 @@ #include "model_global.h" // 导出lib使用 #include "Doc/DocBasicTypes.h" -#include "Doc/DocImage.h" +#include "Doc/DocImageBlock.h" // 这个类应该只用来放图片,所以不需要鼠标光标编辑,直接通过菜单进行编辑 class MODELSHARED_EXPORT DocPicture - :public DocImage { - Q_OBJECT public: - DocPicture(QObject *parent = NULL); + DocPicture(); ~DocPicture(); }; diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index 60a6a97..4533645 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -27,7 +27,6 @@ DEFINES += QT_DEPRECATED_WARNINGS SOURCES += model.cpp \ Doc/DocBlock.cpp \ Doc/DocGraph.cpp \ - Doc/DocImage.cpp \ Doc/DocLayer.cpp \ Doc/DocPage.cpp \ Doc/DocParagraph.cpp \ @@ -52,13 +51,13 @@ SOURCES += model.cpp \ Convert/Doc_OFDConvertor.cpp \ Convert/Objects/MinTextUnit.cpp \ Widget/DocInfoDialog.cpp \ - Command/SetTextBlodCmd.cpp + Command/SetTextBlodCmd.cpp \ + Doc/DocImageBlock.cpp HEADERS += model.h\ model_global.h \ Doc/DocBlock.h \ Doc/DocGraph.h \ - Doc/DocImage.h \ Doc/DocLayer.h \ Doc/DocPage.h \ Doc/DocParagraph.h \ @@ -84,7 +83,8 @@ HEADERS += model.h\ Convert/Doc_OFDConvertor.h \ Convert/Objects/MinTextUnit.h \ Widget/DocInfoDialog.h \ - Command/SetTextBlodCmd.h + Command/SetTextBlodCmd.h \ + Doc/DocImageBlock.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 diff --git a/ofdEditor/ofd/DataTypes/basic_datatype.h b/ofdEditor/ofd/DataTypes/basic_datatype.h index ca79756..785b364 100644 --- a/ofdEditor/ofd/DataTypes/basic_datatype.h +++ b/ofdEditor/ofd/DataTypes/basic_datatype.h @@ -47,7 +47,6 @@ public: } // qDebug() << "cur = " << current_path << "rela = " << relative_path << endl; abs_path = current_path + relative_path; - abs_path.replace("/", "\\"); //路径分隔符标准化 } //构造方法,包括对路径的解析 ST_Loc(QString tag, QString _abs_path) : title(tag), abs_path(_abs_path) { //构造方法,在直接已有绝对路径时 abs_path.replace("/", "\\"); diff --git a/ofdEditor/ofd/ofd_parser.cpp b/ofdEditor/ofd/ofd_parser.cpp index a7d5553..a8e738d 100644 --- a/ofdEditor/ofd/ofd_parser.cpp +++ b/ofdEditor/ofd/ofd_parser.cpp @@ -117,7 +117,7 @@ OFD * OFDParser::readOFD() { Document * OFDParser::readDocument() { openFile(); -// qDebug() << "Checkpoint 1"; + qDebug() << "Checkpoint 1: Entering Document..."; QDomElement new_document = document->firstChildElement("ofd:Document"); Document *document_data; if (!new_document.isNull()) { @@ -127,11 +127,12 @@ Document * OFDParser::readDocument() { if (!new_commondata.isNull()) { CT_CommonData * commondata_data = new CT_CommonData(); document_data->common_data = commondata_data; - + qDebug() << "Checkpoint 1.1..."; QDomElement t; if (!(t = new_commondata.firstChildElement("ofd:MaxUnitID")).isNull()) { commondata_data->max_unit_id = t.text().toInt(); } else { + throw ParsingFormatException("缺少MaxID"); //Error } @@ -140,9 +141,9 @@ Document * OFDParser::readDocument() { commondata_data->page_area = pagearea_data; readPageArea(pagearea_data, t); } else { - //Error + throw ParsingFormatException("PageArea"); } - + qDebug() << "Checkpoint 1.1.1..."; t = new_commondata.firstChildElement("ofd:PublicRes"); while (!t.isNull()) { ST_Loc p("PublicRes", t.text(), current_path); @@ -158,7 +159,7 @@ Document * OFDParser::readDocument() { } else { throw ParsingFormatException("Document类型的数据中中缺少必要的CommonData成员\n位于Document.xml"); } - + qDebug() << "Checkpoint 1.2..."; QDomElement new_pages = new_document.firstChildElement("ofd:Pages"); CT_Pages *pages_data; if (!new_pages.isNull()) { @@ -178,7 +179,7 @@ Document * OFDParser::readDocument() { throw ParsingFormatException("Document类型的数据中中缺少必要的Pages成员\n位于Document.xml"); } document_data->pages = pages_data; - + qDebug() << "Checkpoint 1.3..."; QDomElement new_outlines = new_document.firstChildElement("ofd:Outlines"); if (!new_outlines.isNull()) { //to be implemented @@ -228,7 +229,7 @@ Document * OFDParser::readDocument() { void OFDParser::readPage(Page * page_data) { openFile(); QDomElement new_page = document->firstChildElement("ofd:Page"); -// qDebug() << "Checkpoint 2"; + qDebug() << "Checkpoint 2: Entering Page..."; if (!new_page.isNull()) { QDomElement t; if (!(t = new_page.firstChildElement("ofd:Area")).isNull()) { @@ -264,6 +265,7 @@ void OFDParser::readPage(Page * page_data) { if (id_table->contains(ri.getRefID())) layer_data->draw_param = ri; else { + qDebug() << "Checkpoint ID 1..."; throw ParsingIDException("Layer类型数据的DrawParam属性引用了未注册的ID 位于" + current_path.getRelativePath()); } } @@ -284,6 +286,7 @@ void OFDParser::readPage(Page * page_data) { if (id_table->contains(ri.getRefID())) text_data->font = ri; else { + qDebug() << "Checkpoint ID 2..."; throw ParsingIDException("CT_Text类型数据的Font属性引用了未注册的ID:" + QString::number(ri.getRefID()) + " 位于" + current_path.getRelativePath()); } } else { @@ -386,7 +389,9 @@ void OFDParser::readPage(Page * page_data) { if (id_table->contains(ri.getRefID())) image_data->resource_id = ri; else { - throw ParsingIDException("CT_Image类型数据的ResourceID属性引用了未注册的ID 位于" + current_path.getRelativePath()); + qDebug() << ri.getRefID(); + qDebug() << "Checkpoint ID 3..."; + //throw ParsingIDException("CT_Image类型数据的ResourceID属性引用了未注册的ID 位于" + current_path.getRelativePath()); } } else { throw ParsingFormatException("CT_Image类型数据中缺少必要的ResourceID属性\n位于" + current_path.getRelativePath()); @@ -396,6 +401,7 @@ void OFDParser::readPage(Page * page_data) { if (id_table->contains(ri.getRefID())) image_data->substitution = ri; else { + qDebug() << "Checkpoint ID 4..."; throw ParsingIDException("CT_Image类型数据的Substitution属性引用了未注册的ID 位于" + current_path.getRelativePath()); } } @@ -414,6 +420,7 @@ void OFDParser::readPage(Page * page_data) { void OFDParser::readPageArea(CT_PageArea * data, QDomElement & root_node) { QDomElement t; + qDebug() << "Checkpoint PA 1..."; if (!(t = root_node.firstChildElement("ofd:PhysicalBox")).isNull()) { QStringList values = t.text().split(" "); //qDebug() << values[0] << values[1] << values[2] << endl; @@ -426,7 +433,7 @@ void OFDParser::readPageArea(CT_PageArea * data, QDomElement & root_node) { } else { throw ParsingFormatException("CT_PageArea类型的数据中中缺少必要的PhysicalBox成员\n位于" + current_path.getRelativePath()); } - + qDebug() << "Checkpoint PA 2..."; if (!(t = root_node.firstChildElement("ofd:ApplicationBox")).isNull()) { QStringList values = t.text().split(" "); if (values.size() == 4) @@ -435,7 +442,7 @@ void OFDParser::readPageArea(CT_PageArea * data, QDomElement & root_node) { throw ParsingFormatException("CT_PageArea类型数据的ApplicationBox成员的值的数目错误\n位于" + current_path.getRelativePath()); } } - + qDebug() << "Checkpoint PA 3..."; if (!(t = root_node.firstChildElement("ofd:ContentBox")).isNull()) { QStringList values = t.text().split(" "); if (values.size() == 4) diff --git a/ofdEditor/start/ActionConnector/ActionConnector.cpp b/ofdEditor/start/ActionConnector/ActionConnector.cpp index f26a75e..034139c 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.cpp +++ b/ofdEditor/start/ActionConnector/ActionConnector.cpp @@ -58,14 +58,24 @@ void ActionConnector::addNewBlock(InsertBlockInfo& blockInfo) } else { - qDebug() << "get Focus Sucess"; - page->setBlockFlag(DocPage::draw); // 进入绘画状态 - -// InsertBlockInfo blockInfo(type,layer); // 设置插入文本框信息 - page->setInsertBlockType(blockInfo); // 设置插入文本框信息 - - page->viewport()->setCursor(Qt::CrossCursor); // 将鼠标设置为加号形状 - + //插入文本框 + if (blockInfo.type == DocPage::text) + { + qDebug() << "get Focus Sucess"; + page->setBlockFlag(DocPage::draw); // 进入绘画状态 + + // InsertBlockInfo blockInfo(type,layer); // 设置插入文本框信息 + page->setInsertBlockType(blockInfo); // 设置插入文本框信息 + + page->viewport()->setCursor(Qt::CrossCursor); // 将鼠标设置为加号形状 + } + //插入图片框 + else if (blockInfo.type == DocPage::image) + { + page->setInsertBlockType(blockInfo); // 设置插入文本框信息 + qDebug() << "!!!"; + page->addImage(); + } } } diff --git a/ofdEditor/start/main.cpp b/ofdEditor/start/main.cpp index 7b73580..a2ae2ba 100644 --- a/ofdEditor/start/main.cpp +++ b/ofdEditor/start/main.cpp @@ -1,7 +1,8 @@ #include "mainwindow.h" #include #include "ui/PassageMainWindow.h" - +#include +#include <../ofd/ofdexceptions.h> int main(int argc, char *argv[]) { QApplication a(argc, argv); -- Gitee From 0d85d3f4bdb7acc2386628b63a90fc850f57d10d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 24 Jun 2017 15:29:13 +0800 Subject: [PATCH 05/83] =?UTF-8?q?APPInfo=EF=BC=8C=20=E5=87=BA=E7=8E=B0?= =?UTF-8?q?=E4=BA=86=E4=B8=80=E4=BA=9B=E9=97=AE=E9=A2=98=EF=BC=8C=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E8=BD=AC=E7=94=A8XML=E6=96=87=E4=BB=B6=E5=AD=98?= =?UTF-8?q?=E5=82=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocPassage.cpp | 9 ++++ ofdEditor/model/Widget/DocInfoDialog.cpp | 8 ++++ ofdEditor/model/Widget/DocInfoDialog.h | 1 - .../start/ActionConnector/ActionConnector.cpp | 10 ++++- .../start/ActionConnector/ActionConnector.h | 2 + ofdEditor/start/app/APPInfo.cpp | 45 +++++++++++++++++++ ofdEditor/start/app/APPInfo.h | 30 +++++++++++++ ofdEditor/start/appinfo.qrc | 5 +++ ofdEditor/start/source/appInfo.json | 4 ++ ofdEditor/start/start.pro | 9 ++-- ofdEditor/start/ui/PassageMainWindow.cpp | 7 ++- 11 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 ofdEditor/start/app/APPInfo.cpp create mode 100644 ofdEditor/start/app/APPInfo.h create mode 100644 ofdEditor/start/appinfo.qrc create mode 100644 ofdEditor/start/source/appInfo.json diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index 3364acf..66e39e5 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -271,6 +271,15 @@ void DocPassage::resetDocId() { QUuid uuid = QUuid::createUuid(); // 创建uuid QString docId = uuid.toString(); // 转换为字符串 + + // 去掉字符串的链接符号 {0142d46f-60b5-47cf-8310-50008cc7cb3a} + // 0142d46f60b547cf831050008cc7cb3a + docId.remove(docId.length()-1, 1); + docId.remove(docId.length() -13, 1); + docId.remove(docId.length() -17,1); + docId.remove(docId.length() -21, 1); + docId.remove(docId.length() - 25,1); + docId.remove(0,1); qDebug() << "uuid : " << docId; this->docInfo->setDocID(docId); diff --git a/ofdEditor/model/Widget/DocInfoDialog.cpp b/ofdEditor/model/Widget/DocInfoDialog.cpp index 5054d2b..d9d8601 100644 --- a/ofdEditor/model/Widget/DocInfoDialog.cpp +++ b/ofdEditor/model/Widget/DocInfoDialog.cpp @@ -133,6 +133,14 @@ void DocInfoDialog::resetDocId() { QUuid uuid = QUuid::createUuid(); // 创建一个新的uuid QString docId = uuid.toString(); + + docId.remove(docId.length()-1, 1); + docId.remove(docId.length() -13, 1); + docId.remove(docId.length() -17,1); + docId.remove(docId.length() -21, 1); + docId.remove(docId.length() - 25,1); + docId.remove(0,1); + qDebug() << "new uuid: " << docId; this->docInfo->setDocID(docId); diff --git a/ofdEditor/model/Widget/DocInfoDialog.h b/ofdEditor/model/Widget/DocInfoDialog.h index 1593f96..463453a 100644 --- a/ofdEditor/model/Widget/DocInfoDialog.h +++ b/ofdEditor/model/Widget/DocInfoDialog.h @@ -24,7 +24,6 @@ private: Ui::DocInfoDialog *ui; CT_DocInfo* docInfo; // 文档元信息 void init(); // 初始化 - void initUi(); // 初始化ui public slots: diff --git a/ofdEditor/start/ActionConnector/ActionConnector.cpp b/ofdEditor/start/ActionConnector/ActionConnector.cpp index badff0f..d555724 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.cpp +++ b/ofdEditor/start/ActionConnector/ActionConnector.cpp @@ -5,6 +5,8 @@ #include "DataTypes/document/ct_docinfo.h" #include "Widget/DocInfoDialog.h" +#include "app/APPInfo.h" + #include #include @@ -24,7 +26,7 @@ void ActionConnector::showAttribute() { if(this->passage == NULL) { - qDebug() << "show attribute"; + qDebug() << "show attribute this->passage == NULL"; return; } @@ -129,6 +131,11 @@ void ActionConnector::redo() this->passage->undoStack->redo(); } +void ActionConnector::setDocPassage(DocPassage *passage) +{ + this->passage = passage; +} + @@ -164,4 +171,5 @@ void ActionConnector::init() { this->defaultLayer = DocPage::Body; this->passage = NULL; // 初始化为空 + } diff --git a/ofdEditor/start/ActionConnector/ActionConnector.h b/ofdEditor/start/ActionConnector/ActionConnector.h index b2d2eb6..878056b 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.h +++ b/ofdEditor/start/ActionConnector/ActionConnector.h @@ -5,6 +5,7 @@ #include "Doc/DocPage.h" #include + class DocPassage; class PassageMainWindow; @@ -34,6 +35,7 @@ public slots: void addTableBlock(); // 插入表格 void undo(); // undo void redo(); // redo + void setDocPassage(DocPassage* passage); // 设置passage void setDefaultLayer(DocPage::Layer layer){this->defaultLayer = layer;} diff --git a/ofdEditor/start/app/APPInfo.cpp b/ofdEditor/start/app/APPInfo.cpp new file mode 100644 index 0000000..f0d377a --- /dev/null +++ b/ofdEditor/start/app/APPInfo.cpp @@ -0,0 +1,45 @@ +#include "APPInfo.h" +#include +#include +#include +#include + +APPInfo::APPInfo(QObject *parent) : QObject(parent) +{ + +} + +QString APPInfo::GetAppName() +{ + return this->appName; +} + +QString APPInfo::GetAppVersion() +{ + return this->appVersion; +} + +void APPInfo::initFromFile() +{ + QFile file(":/appInfo/source/appInfo.json"); // 将文件存在resource内 + if(!file.open(QIODevice::ReadOnly)) + { + qDebug() << "open app information file failed"; + return; + } + + QTextStream txtInput(&file); // 设置文件流 + QString str = txtInput.readAll(); // 读全部文件 + qDebug() << str; + +} + +void APPInfo::setAppName(QString &name) +{ + this->appName = name; +} + +void APPInfo::setAppVersion(QString &version) +{ + this->appVersion = version; +} diff --git a/ofdEditor/start/app/APPInfo.h b/ofdEditor/start/app/APPInfo.h new file mode 100644 index 0000000..5fe1839 --- /dev/null +++ b/ofdEditor/start/app/APPInfo.h @@ -0,0 +1,30 @@ +#ifndef APPINFO_H +#define APPINFO_H + +#include +#include + +class APPInfo + : public QObject +{ + Q_OBJECT +public: + explicit APPInfo(QObject *parent = 0); + + QString GetAppName(); // 获得应用名称 + QString GetAppVersion(); // 获得应用版本号 + + void initFromFile(); // 从文件中获取版本信息 + +signals: + +public slots: + void setAppName(QString &name); // 设置名称 + void setAppVersion(QString &version); // 设置版本号 + +private: + QString appName; // 应用名称 + QString appVersion; // app版本 +}; + +#endif // APPINFO_H diff --git a/ofdEditor/start/appinfo.qrc b/ofdEditor/start/appinfo.qrc new file mode 100644 index 0000000..e6b0c6e --- /dev/null +++ b/ofdEditor/start/appinfo.qrc @@ -0,0 +1,5 @@ + + + source/appInfo.json + + diff --git a/ofdEditor/start/source/appInfo.json b/ofdEditor/start/source/appInfo.json new file mode 100644 index 0000000..96f1088 --- /dev/null +++ b/ofdEditor/start/source/appInfo.json @@ -0,0 +1,4 @@ +{ + "AppName": "ofdEditor", + "AppVersion": "0.1.0.0" +} diff --git a/ofdEditor/start/start.pro b/ofdEditor/start/start.pro index d56a76b..153a8dc 100644 --- a/ofdEditor/start/start.pro +++ b/ofdEditor/start/start.pro @@ -28,11 +28,13 @@ DEFINES += QT_DEPRECATED_WARNINGS SOURCES += main.cpp\ mainwindow.cpp \ ui/PassageMainWindow.cpp \ - ActionConnector/ActionConnector.cpp + ActionConnector/ActionConnector.cpp \ + app/APPInfo.cpp HEADERS += mainwindow.h \ ui/PassageMainWindow.h \ - ActionConnector/ActionConnector.h + ActionConnector/ActionConnector.h \ + app/APPInfo.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 @@ -53,6 +55,7 @@ win32{ } RESOURCES += \ - icons.qrc + icons.qrc \ + appinfo.qrc FORMS += diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 4fe5af5..76f366d 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -53,9 +53,6 @@ DocPassage *PassageMainWindow::createMdiChild() DocPassage * child = new DocPassage(this); child->addPage(new DocPage()); // 添加一个空白页 -// this->area->addSubWindow(child); -// child->setVisible(true); // 设置可见 -// child->showMaximized(); this->addDocPassage(child); // 加入到本视区 return child; @@ -446,7 +443,9 @@ DocPassage *PassageMainWindow::addDocPassage(DocPassage *passage) return NULL; } - this->area->addSubWindow(passage); + this->area->addSubWindow(passage); // 插入子窗口 + this->connector->setDocPassage(passage); // 设置引用 + passage->setVisible(true); // 设置可见 passage->showMaximized(); -- Gitee From b85f8195d4d792ac8147dac839c634701fec26d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 24 Jun 2017 22:31:36 +0800 Subject: [PATCH 06/83] =?UTF-8?q?=E5=B8=8C=E6=9C=9B=E5=81=9Adoc-ofd?= =?UTF-8?q?=E7=9A=84=E8=BD=AC=E6=8D=A2=EF=BC=8C=E4=BD=86=E5=BD=93=E5=89=8D?= =?UTF-8?q?=E8=BF=98=E6=B2=A1=E6=9C=89=E5=81=9A=E7=8E=A9DocTextBlock->CT?= =?UTF-8?q?=5FText=E7=9A=84=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/Doc_OFDConvertor.cpp | 299 ++++++++++++++++++- ofdEditor/model/Convert/Doc_OFDConvertor.h | 34 ++- ofdEditor/model/Convert/OFD_DocConvertor.cpp | 17 +- ofdEditor/model/Convert/OFD_DocConvertor.h | 3 + ofdEditor/model/Doc/DocBlock.cpp | 1 + ofdEditor/model/Doc/DocPage.cpp | 37 +++ ofdEditor/model/Doc/DocPage.h | 4 + ofdEditor/model/Widget/DocInfoDialog.ui | 12 +- ofdEditor/ofd/DataTypes/document/DocBody.h | 4 +- ofdEditor/ofd/DataTypes/document/docbody.h | 4 +- ofdEditor/ofd/DataTypes/page/Page.h | 1 - ofdEditor/ofd/DataTypes/page/page.h | 1 - 12 files changed, 392 insertions(+), 25 deletions(-) diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp index 82ca3b2..80efd9e 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp @@ -5,9 +5,27 @@ #include "Doc/DocTextBlock.h" #include "Doc/DocLayer.h" +#include +#include +#include +#include + #include "DataTypes/basic_datatype.h" #include "DataTypes/document/ofd.h" - +#include "DataTypes/document/Res.h" +#include "DataTypes/document/docbody.h" +#include "DataTypes/document/ct_docinfo.h" +#include "DataTypes/document/document.h" +#include "DataTypes/page/ct_pages.h" +#include "DataTypes/page/page.h" +#include "DataTypes/page/ct_layer.h" +#include "DataTypes/page/CT_PageArea.h" +#include "DataTypes/Color/CT_Color.h" +#include "DataTypes/Color/CT_ColorSpace.h" +#include "DataTypes/text/CT_Font.h" +#include "DataTypes/text/ct_text.h" +#include "DataTypes/text/textcode.h" +#include "DataTypes/basic_datatype.h" Doc_OFDConvertor::Doc_OFDConvertor(QObject *parent) @@ -25,25 +43,296 @@ Doc_OFDConvertor::Doc_OFDConvertor(QObject *parent) */ OFD *Doc_OFDConvertor::doc_to_ofd(DocPassage *passage) { + this->passage = passage; // 保存passage + this->ofdFile = new OFD( ); // 建立一个新的OFD文件 + + // 构建流程 + this->buildDocBody(); // 构建DocBody + this->buildDocument(); // docment + + } -void Doc_OFDConvertor::buildDocInfo() +/** + * @Author Chaoqun + * @brief 生成DocBody + * @param void + * @return void + * @date 2017/06/24 + */ +void Doc_OFDConvertor::buildDocBody() { + qDebug() << "exec buildDocbody"; + QVector docbodys; // 新建docbodys新建带有……的docbodys + DocBody* docbody = new DocBody(this->passage->getDocInfo()); // 加入docbody + docbodys.append(docbody); // 新建DocBody + docbody->setDocRoot(QString("Doc_0/Document.xml")); // 设置文档根目录 + + this->ofdFile->setDocBodies( &docbodys); // 设置ofd的docbobys } -void Doc_OFDConvertor::buildPage() +/** + * @Author Chaoqun + * @brief 创建document相关的东西 + * @param void + * @return void + * @date 2017/06/24 + */ +void Doc_OFDConvertor::buildDocument() +{ + qDebug() << "exec buildDocument"; + QVector documents; // 新建Documents + Document* document = new Document(); // 新建Document + documents.append(document); // 添加到文件中 + + // 设置ID_Table + this->table = document->getIDTable(); // 获得IDTable + + // 设置publicRes + this->public_res = new Res(); + document->getPublicRes()->append(public_res); // 将公用资源加入到document + + // 设置common_data + CT_CommonData * commonData = new CT_CommonData(); + document->setCommonData(commonData); + // 设置指向资源文件的 + commonData->getPublicRes()->append(ST_Loc(QString("PublicRes.xml"), + QString("PublicRes.xml"), + QString("PublicRes.xml"))); + + this->buildPages(document); // 解析每一页 +} + +/** + * @Author Chaoqun + * @brief 转换所有页面 + * @param void + * @return void + * @date 2017/06/23 + */ +void Doc_OFDConvertor::buildPages(Document* document) { + qDebug() << "exec buildPages"; + QVector docPages = this->passage->getPages(); // 获得页面 + int pagesLength = docPages.size(); // 获得页面的数量 + + if(pagesLength > 1) + { + // 设置公共页大小 + CT_CommonData* commonData = document->getCommonData(); + + CT_PageArea *area = new CT_PageArea(); + + DocPage* page = docPages[0]; + area->setPhysicalBox(0,0, + page->getWidth(),page->getHeight()); + commonData->setPageArea(area); + + } + + CT_Pages * ctpages = new CT_Pages(); // 新建CT_Pages + document->setPages(ctpages); // 设置 + QVector* pages = ctpages->getPages(); // 获得Qvector + + // 遍历每个页面 + for(int i=0; i< pagesLength;i++) + { + DocPage* page = docPages.operator [](i); + + Page* ctPage = new Page(); + ctPage->setID(this->table->size()+1,this->table); // 设置ID + // 设置页的路径 + QString num; + num.setNum(i); + ctPage->setBaseLoc(QString("Pages/Page_") + num); + pages->append(ctPage); // 加入到OFD 文件中 + + this->buildPage(ctPage,page); // 单独处理每一页 + + } } -void Doc_OFDConvertor::buildLayer(DocLayer *layer) +/** + * @Author Chaoqun + * @brief 处理文档中某一页 + * @param Page *ctPage + * @param DocPage *docPage + * @return void + * @date 2017/06/24 + */ +void Doc_OFDConvertor::buildPage(Page *ctPage, DocPage *docPage) { + qDebug() << "exec buildPage"; + QVector *layers = ctPage->getContent(); + + // 分成多个层,对每个层进行处理 + DocLayer* foreground = docPage->getForegroundLayer(); // 获得前景层 + CT_Layer* foreLayer = new CT_Layer(); // 处理前景层 + foreLayer->setType("Foreground"); // 设置类型 + foreLayer->setID(this->table->size()+1,this->table); // 设置ID + layers->append(foreLayer); // 加入到Page中 + this->buildLayer(foreLayer,foreground); // 处理该层的信息 + + + // 处理正文层 + DocLayer* body = docPage->getBodyLayer(); + CT_Layer* bodyLayer = new CT_Layer(); + bodyLayer->setType("Body"); + bodyLayer->setID(this->table->size()+1,this->table); + layers->append(bodyLayer); + this->buildLayer(bodyLayer,body); + + // 背景层 + DocLayer* background = docPage->getBackgroundLayer(); + CT_Layer* backLayer = new CT_Layer(); + backLayer->setType("Background"); + backLayer->setID(this->table->size()+1,this->table); + layers->append(backLayer); + this->buildLayer(backLayer,background); } -void Doc_OFDConvertor::buildText(DocTextBlock *textBlock) +/** + * @Author Chaoqun + * @brief 建造层 + * @param Page* ctPage + * @param DocLayer* layer + * @return 返回值 + * @date 2017/06/24 + */ +void Doc_OFDConvertor::buildLayer(CT_Layer* ctLayer,DocLayer *layer) { + qDebug() << "Exec buildLayer"; + QVector *blocks = layer->getBlocks(); + int blocks_length = blocks->size(); + + // 遍历所有块 + for(int i =0; i< blocks_length; i++) + { + DocBlock* block = blocks->operator [](i); // 获得一个临时的框 + + // 如果是文字框 + if(block->isTextBlock()) + { + // 进入文字框处理模式 + this->buildText(ctLayer,block->getTextBlock()); + } + } + +} + +/** + * @Author Chaoqun + * @brief 处理文字框 + * @param CT_Layer* ctLayer + * @param DocTextBlock*textBlock + * @return void + * @date 2017/06/24 + */ +void Doc_OFDConvertor::buildText(CT_Layer* ctLayer,DocTextBlock *textBlock) +{ + // 分析TextBlock + textBlock->moveCursor(QTextCursor::Start); // 移动到块的开始 + QTextCursor cursor = textBlock->textCursor(); + + +} + +/** + * @Author Chaoqun + * @brief 加入字体 + * @param CT_Font *font + * @return int 插入的Font 的RefId + * @date 2017/06/24 + */ +int Doc_OFDConvertor::addFont(CT_Font *font) +{ + int checkId = this->checkFont(font); // 获得fontID + + if(checkId != -1) + { + // 如果检查后,存在了这个font + return checkId; + } + + // 为字体分配ID + font->setID(this->table->size()+1, this->table); + this->public_res->getFonts()->append(font); // 加入 + qDebug() << "Add Font:" << font->getFontName(); + return font->getID().getID(); +} + +/** + * @Author Chaoqun + * @brief 为公用资源添加颜色空间 + * @param CT_ColorSpace *colorSpace + * @return int + * @date 2017/06/24 + */ +int Doc_OFDConvertor::addColorSpace(CT_ColorSpace *colorSpace) +{ + int checkId = this->checkColorSpace(colorSpace); // 检查是否已有该颜色空间 + if(checkId != -1) + { + return checkId; + } + + // 为颜色空间分派id + colorSpace->setID(this->table->size()+1, this->table); + this->public_res->getColorSpaces()->append(colorSpace); + qDebug() << "Add ColorSpace: " << colorSpace->getType(); + return colorSpace->getID().getID(); +} + +/** + * @Author Chaoqun + * @brief 检查是否已经存在这个字体 + * @param CT_Font* font + * @return int + * @date 2017/06/24 + */ +int Doc_OFDConvertor::checkFont(CT_Font *font) +{ + QVector* fonts = this->public_res->getFonts(); // 获得字体 + int length = fonts->size(); + + // 遍历一遍,检查是否有相同的 + for(int i= 0; i< length; i++) + { + if((*fonts)[i]->getFamilyName() == font->getFamilyName()) + { + return (*fonts)[i]->getID().getID(); // 返回ID + } + } + + qDebug() << "this font is not stored"; + return -1; +} + +/** + * @Author Chaoqun + * @brief 检查是否已经存在此ColorSpace + * @param CT_ColorSpace + * @return int 如果存在,返回ID信息,不存在,则返回-1 + * @date 2017/06/24 + */ +int Doc_OFDConvertor::checkColorSpace(CT_ColorSpace *colorSpace) +{ + QVector* colorSpaces + = this->public_res->getColorSpaces(); // 获得颜色空间 + + int length = colorSpaces->size(); + // 遍历colorSpace检查是否有相同的 + for(int i = 0; i < length; i++) + { + if((*colorSpaces)[i]->getType() == colorSpace->getType()) + { + return (*colorSpaces)[i]->getID().getID(); // 返回ID + } + } + return -1; // 不存在已有的 } diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.h b/ofdEditor/model/Convert/Doc_OFDConvertor.h index 79b32bd..ccf6da4 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.h +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.h @@ -11,6 +11,14 @@ class DocBlock; // 块 class DocTextBlock; // 文本框 class OFD; // OFD文件模型 +class Res; // 资源描述 +class ID_Table; // id table表 +class CT_Font; // ct_font +class CT_ColorSpace; // 颜色空间 +class Page; +class Document; +class CT_Layer; + /** * @Author Chaoqun @@ -30,14 +38,30 @@ signals: public slots: private: - void buildDocInfo(); // 存储DocInfo相关的信息 - void buildPage(); // 储存文本信息,顺便整理文件 - void buildLayer(DocLayer* layer); // 将一层中的信息存储出来 - void buildText(DocTextBlock* textBlock); // 将DocTextBlock中的信息转换处理 + + void buildDocBody(); // 生成DocBody + void buildDocument(); // 生成Document + void buildPages(Document *document); // 处理页面S + + void buildPage(Page* ctPage, + DocPage* docPage); // 处理其中某一页 + + void buildLayer(CT_Layer* ctLayer, + DocLayer* layer); // 将一层中的信息存储出来 + void buildText(CT_Layer* ctLayer,DocTextBlock* textBlock); // 将DocTextBlock中的信息转换处理 + + int addFont(CT_Font* font); // 添加字体类型到资源 + int addColorSpace(CT_ColorSpace* colorSpace); // 添加颜色空间 + + int checkFont(CT_Font* font); // 检查publicRes中是否存在该字体 + int checkColorSpace(CT_ColorSpace* colorSpace); // 检查是否存在该颜色空间 private: DocPassage* passage; // 文章 - OFD* ofdFile; // OFD对象 + OFD* ofdFile; // OFD 对象 + Res* public_res; // Res 公共资源文件 + ID_Table* table; // ID table + }; diff --git a/ofdEditor/model/Convert/OFD_DocConvertor.cpp b/ofdEditor/model/Convert/OFD_DocConvertor.cpp index ea000f2..1b75e10 100644 --- a/ofdEditor/model/Convert/OFD_DocConvertor.cpp +++ b/ofdEditor/model/Convert/OFD_DocConvertor.cpp @@ -16,6 +16,8 @@ #include "DataTypes/image/CT_DrawParam.h" #include "DataTypes/Color/CT_ColorSpace.h" #include "Convert/Objects/MinTextUnit.h" +#include "DataTypes/page/CT_PageArea.h" +#include "DataTypes/document/ct_commondata.h" OFD_DocConvertor::OFD_DocConvertor() { @@ -49,7 +51,8 @@ DocPassage *OFD_DocConvertor::ofd_to_doc(OFD *ofd) Document * document = (*(ofd->getDocuments()))[0]; // Document -// CT_CommonData * commonData = document->getCommonData(); // 获取common_data + CT_CommonData * commonData = document->getCommonData(); // 获取common_data- >内含公用页大小 + this->public_pageArea = commonData->getPageArea(); // 从common_data中获取公用边大小 // CT_Pages pages = document->pages; // 获得文档中的页 QVector * pages = document->getPages()->getPages(); // 获得页属性 @@ -81,8 +84,14 @@ DocPage *OFD_DocConvertor::buildDocPage(DocPassage *passage, Page *ct_page) // 如果定义了纸张尺寸 CT_PageArea* area = ct_page->getArea(); // 获得空间 - - // 物理空间 + if(area == NULL) + { + // 如果没有定义页面大小 + qDebug() <<"buildPage -> there is no pageArea in page"; + area = this->public_pageArea; // 使用公用的页面空间 + } + + // 使用物理空间新建页面 page = new DocPage(area->getPhysicalBox().getDeltaX(), area->getPhysicalBox().getDeltaY(), 1.0); // 设置纸张大小 @@ -110,7 +119,6 @@ DocPage *OFD_DocConvertor::buildDocPage(DocPassage *passage, Page *ct_page) qDebug() << "OFD_DocConvertor::buildDocPage exception."; } - return page; } @@ -183,7 +191,6 @@ void OFD_DocConvertor::insertPageBlock(DocPage *page, } - /** * @Author Chaoqun * @brief 将文字块插入到页面中 diff --git a/ofdEditor/model/Convert/OFD_DocConvertor.h b/ofdEditor/model/Convert/OFD_DocConvertor.h index 035c000..f330308 100644 --- a/ofdEditor/model/Convert/OFD_DocConvertor.h +++ b/ofdEditor/model/Convert/OFD_DocConvertor.h @@ -15,6 +15,7 @@ class CT_Text; class CT_Path; class CT_Image; class CT_Color; +class CT_PageArea; /** * @Author Chaoqun @@ -32,6 +33,8 @@ public: private: OFD * ofdFile; // 当前处理时使用的ofd文件-用来方便获取到公用的特征 + CT_PageArea* public_pageArea; // 公用的页面大小 + DocPage * buildDocPage(DocPassage * passage , Page * ct_page); // 生成页 diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index 49d029f..19b1de1 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -29,6 +29,7 @@ DocBlock::DocBlock(QGraphicsItem *parent , Qt::WindowFlags wFlags) this->setFlag(QGraphicsProxyWidget::ItemIsSelectable, true); // 可选择 this->setFlag(QGraphicsProxyWidget::ItemIsFocusable, true); // 可关注 this->setAcceptHoverEvents(true); + } /** diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index e5c94f2..88a0821 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -17,6 +17,7 @@ #include #include #include +#include // #include "DataTypes/page/CT_PageArea.h" // 页面大小 @@ -98,6 +99,42 @@ QSize DocPage::getSize() UnitTool::mmToPixel(height_mm)); } +/** + * @Author Chaoqun + * @brief 获得前景层 + * @param void + * @return DocLayer* + * @date 2017/06/24 + */ +DocLayer *DocPage::getForegroundLayer() +{ + return this->foregroundLayer; +} + +/** + * @Author Chaoqun + * @brief 获得正文层 + * @param void + * @return DocLayer* + * @date 2017/06/24 + */ +DocLayer *DocPage::getBodyLayer() +{ + return this->bodyLayer; +} + +/** + * @Author Chaoqun + * @brief 获得背景层 + * @param 参数 + * @return DocLayer* + * @date 2017/06/24 + */ +DocLayer *DocPage::getBackgroundLayer() +{ + return this->backgroundLayer; +} + /** * @Author Chaoqun * @brief 添加一个新的块到页面之中 diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index 8291d08..48d5388 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -44,6 +44,10 @@ public: BlockFlag getBlockFlag(){return this->newBlockFlag;} + DocLayer *getForegroundLayer(); // 获得前景层 + DocLayer* getBodyLayer(); // 获得正文层 + DocLayer* getBackgroundLayer(); // 获得背景层 + public slots: void setSize(double width, double height); // 设置页面大小 void setPassage(DocPassage * passage); // 设置文章 diff --git a/ofdEditor/model/Widget/DocInfoDialog.ui b/ofdEditor/model/Widget/DocInfoDialog.ui index 28d14a4..87d36cf 100644 --- a/ofdEditor/model/Widget/DocInfoDialog.ui +++ b/ofdEditor/model/Widget/DocInfoDialog.ui @@ -41,7 +41,7 @@ 说明 - + 21 @@ -149,21 +149,21 @@ - - + + - - + + - + diff --git a/ofdEditor/ofd/DataTypes/document/DocBody.h b/ofdEditor/ofd/DataTypes/document/DocBody.h index 31bf442..dcbbced 100644 --- a/ofdEditor/ofd/DataTypes/document/DocBody.h +++ b/ofdEditor/ofd/DataTypes/document/DocBody.h @@ -13,7 +13,9 @@ public: public: friend class OFDParser; - DocBody(CT_DocInfo * _doc_info = NULL, QString _doc_root = "", QString _signatures = "") { + DocBody(CT_DocInfo * _doc_info = NULL, + QString _doc_root = "", + QString _signatures = "") { if (_doc_info) setDocInfo(_doc_info); if (!_doc_root.isNull()) diff --git a/ofdEditor/ofd/DataTypes/document/docbody.h b/ofdEditor/ofd/DataTypes/document/docbody.h index 31bf442..dcbbced 100644 --- a/ofdEditor/ofd/DataTypes/document/docbody.h +++ b/ofdEditor/ofd/DataTypes/document/docbody.h @@ -13,7 +13,9 @@ public: public: friend class OFDParser; - DocBody(CT_DocInfo * _doc_info = NULL, QString _doc_root = "", QString _signatures = "") { + DocBody(CT_DocInfo * _doc_info = NULL, + QString _doc_root = "", + QString _signatures = "") { if (_doc_info) setDocInfo(_doc_info); if (!_doc_root.isNull()) diff --git a/ofdEditor/ofd/DataTypes/page/Page.h b/ofdEditor/ofd/DataTypes/page/Page.h index 8e168c9..2603a62 100644 --- a/ofdEditor/ofd/DataTypes/page/Page.h +++ b/ofdEditor/ofd/DataTypes/page/Page.h @@ -14,7 +14,6 @@ public: QVector * page_res_locations; QVector *content; //Actions to be implemented - public: friend class OFDParser; Page() { diff --git a/ofdEditor/ofd/DataTypes/page/page.h b/ofdEditor/ofd/DataTypes/page/page.h index 8e168c9..2603a62 100644 --- a/ofdEditor/ofd/DataTypes/page/page.h +++ b/ofdEditor/ofd/DataTypes/page/page.h @@ -14,7 +14,6 @@ public: QVector * page_res_locations; QVector *content; //Actions to be implemented - public: friend class OFDParser; Page() { -- Gitee From 434ff9737bc8f1f6bb9c91b32ca5e8a75906892f Mon Sep 17 00:00:00 2001 From: Pan Yanxing Date: Sun, 25 Jun 2017 01:17:06 +0800 Subject: [PATCH 07/83] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86DocImageBlock?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E6=A1=86=E5=92=8C=E4=B8=80=E4=BA=9B=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E6=93=8D=E4=BD=9C=E3=80=82=E5=AE=9E=E7=8E=B0=E8=BF=87?= =?UTF-8?q?=E7=A8=8B=E4=B8=AD=E5=AF=B9DocPage=E5=A2=9E=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E4=B8=8D=E5=B0=91=E4=BB=A3=E7=A0=81=EF=BC=8C=E5=BA=94=E8=AF=A5?= =?UTF-8?q?=E6=9C=AA=E8=A7=A6=E5=8A=A8=E5=88=B0=E5=85=B6=E4=BB=96=E5=8E=9F?= =?UTF-8?q?=E6=9C=89=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocBlock.cpp | 94 +++- ofdEditor/model/Doc/DocBlock.h | 3 +- ofdEditor/model/Doc/DocImageBlock.cpp | 137 +++++ ofdEditor/model/Doc/DocImageBlock.h | 37 ++ ofdEditor/model/Doc/DocPage.cpp | 45 +- ofdEditor/model/Doc/DocPage.h | 2 +- ofdEditor/model/Widget/DocInfoDialog.h | 2 + .../model/Widget/imagepropertiesdialog.cpp | 202 +++++++ .../model/Widget/imagepropertiesdialog.h | 51 ++ .../model/Widget/imagepropertiesdialog.ui | 527 ++++++++++++++++++ ofdEditor/model/model.pro | 9 +- ofdEditor/test_pan/main.cpp | 14 +- ofdEditor/test_pan/mainwindow.cpp | 2 + ofdEditor/test_pan/mainwindow.h | 22 +- 14 files changed, 1083 insertions(+), 64 deletions(-) create mode 100644 ofdEditor/model/Widget/imagepropertiesdialog.cpp create mode 100644 ofdEditor/model/Widget/imagepropertiesdialog.h create mode 100644 ofdEditor/model/Widget/imagepropertiesdialog.ui diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index 69e685d..ae3ef90 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -224,7 +224,7 @@ void DocBlock::focusOutEvent(QFocusEvent *event) */ void DocBlock::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { - +// qDebug() << "Hovering."; if (this->rectAdjust == blockResize || (this->currentStatus(event->pos()) == blockResize && this->isFocused)) @@ -256,7 +256,7 @@ void DocBlock::hoverMoveEvent(QGraphicsSceneHoverEvent *event) */ void DocBlock::mousePressEvent(QGraphicsSceneMouseEvent *event) { - qDebug() << "Pressed."; +// qDebug() << "Pressed."; QPointF pos = event->pos(); // 获取鼠标位置 // qDebug()<<"DocBlock Mouse Postion" << pos.x() // << ", "<rectAdjust = this->currentStatus(event->pos()); +// qDebug() << (rectAdjust == DocBlock::blockResize); } -qDebug() << (rectAdjust == DocBlock::blockResize); +//qDebug() << (rectAdjust == DocBlock::blockResize); QGraphicsProxyWidget::mousePressEvent(event); - } /** @@ -280,7 +280,7 @@ qDebug() << (rectAdjust == DocBlock::blockResize); */ void DocBlock::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - qDebug() << (rectAdjust == DocBlock::blockResize); +// qDebug() << "???"; if (this->rectAdjust == blockResize) { // qDebug() << "???"; @@ -299,7 +299,6 @@ void DocBlock::mouseMoveEvent(QGraphicsSceneMouseEvent *event) } QGraphicsProxyWidget::mouseMoveEvent(event); // 调用基类的函数 - } /** @@ -367,6 +366,20 @@ void DocBlock::setWidget(DocTextBlock *textBlock) } +/** + * @Author Pan + * @brief em..... + * @param DocImageBlock * imageBlock + * @return void + * @date 2017/06/24 + */ +void DocBlock::setWidget(DocImageBlock * imageBlock) +{ + imageBlock->setBlock(this); + this->imageBlock = imageBlock; + QGraphicsProxyWidget::setWidget(imageBlock); +} + /** * @Author Chaoqun * @brief 检查鼠标是否在重置大小区域 @@ -389,32 +402,53 @@ bool DocBlock::isInResizeArea(const QPointF &pos) */ DocBlock::RectAdjustStatus DocBlock::currentStatus(const QPointF &pos) { - if((pos.x() - this->size().width() + 15) > - (this->size().height() - pos.y())) +// qDebug() << "get current status."; + if (isTextBlock()) { - //qDebug() << "Mouse resizing."; - return blockResize; + if((pos.x() - this->size().width() + 15) > + (this->size().height() - pos.y())) + { + //qDebug() << "Mouse resizing."; + return blockResize; + } + // 画出可以移动的边缘 + qreal moveMargin = 5; // 边缘多少像素内可以移动 + QRectF left(0,0, + moveMargin,this->blockSize.height()); + QRectF right(this->blockSize.width()-moveMargin,0, + moveMargin,this->blockSize.height()); + QRectF top(0,0, + this->blockSize.width(),moveMargin); + QRectF bottom(0,this->blockSize.height() - moveMargin, + this->blockSize.width(),moveMargin); + + if(left.contains(pos) + || right.contains(pos) + || top.contains(pos) + || bottom.contains(pos)) + return blockMove; + + // 如果未得出结果,则默认无操作 + return blockNone; + } + else if (isImageBlock()) + { +// qDebug() << "Is Image Block."; + QRectF rec(0, 0, + this->blockSize.width(), + this->blockSize.height()); + if((pos.x() - this->size().width() + 15) > + (this->size().height() - pos.y())) + { + //qDebug() << "Mouse resizing."; + return blockResize; + } else if (rec.contains(pos)) + { +// qDebug() << "Is moving Image Block"; + return blockMove; + } + } - // 画出可以移动的边缘 - qreal moveMargin = 5; // 边缘多少像素内可以移动 - QRectF left(0,0, - moveMargin,this->blockSize.height()); - QRectF right(this->blockSize.width()-moveMargin,0, - moveMargin,this->blockSize.height()); - QRectF top(0,0, - this->blockSize.width(),moveMargin); - QRectF bottom(0,this->blockSize.height() - moveMargin, - this->blockSize.width(),moveMargin); - - if(left.contains(pos) - || right.contains(pos) - || top.contains(pos) - || bottom.contains(pos)) - return blockMove; - - - // 如果未得出结果,则默认无操作 - return blockNone; } /** diff --git a/ofdEditor/model/Doc/DocBlock.h b/ofdEditor/model/Doc/DocBlock.h index 93aee45..caee591 100644 --- a/ofdEditor/model/Doc/DocBlock.h +++ b/ofdEditor/model/Doc/DocBlock.h @@ -52,11 +52,10 @@ public slots: // 槽函数 void remove(); // 从场景中移除本框 void setWidget(QWidget* widget); // 旧的函数 void setWidget(DocTextBlock *textBlock); // SetWidget - + void setWidget(DocImageBlock * imageBlock); protected: - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); // 用来绘制变化 diff --git a/ofdEditor/model/Doc/DocImageBlock.cpp b/ofdEditor/model/Doc/DocImageBlock.cpp index 42af909..742b5df 100644 --- a/ofdEditor/model/Doc/DocImageBlock.cpp +++ b/ofdEditor/model/Doc/DocImageBlock.cpp @@ -1,6 +1,9 @@ #include "DocImageBlock.h" #include #include +#include +#include +#include "DocPage.h" DocImageBlock::DocImageBlock(QWidget *parent) :QLabel(parent) @@ -11,6 +14,27 @@ DocImageBlock::DocImageBlock(QWidget *parent) this->setFrameStyle(QFrame::NoFrame); this->setFocusPolicy(Qt::StrongFocus); + //Initialization + this->context_menu = new QMenu(this); + change_image = new QAction(tr("Change Image"), NULL); + set_image_properties = new QAction(tr("Set Image Properties"), NULL); + properties_dialog = new ImagePropertiesDialog(this, parent); + width_height_ratio_locked = false; + width_height_ratio = 0.0; + + //signal-slots + this->connect(this->change_image, SIGNAL(triggered()), + this, SLOT(changeImage())); + this->connect(this->set_image_properties, SIGNAL(triggered()), + this, SLOT(setImageProperties())); + this->connect(properties_dialog, + SIGNAL(changeImageProperties(double,double, + double,double, + bool)), + this, SLOT(imagePropertiesChanged(double,double, + double,double, + bool))); + } /** @@ -25,6 +49,43 @@ void DocImageBlock::setImage(QPixmap & pixmap) this->setPixmap(pixmap); } +/** + * @Author Pan + * @brief 设置内部对代理它的DocBlock的引用 + * @param DocBlock * _block + * @return void + * @date 2017/06/25 + */ +void DocImageBlock::setBlock(DocBlock *_block) +{ + block = _block; +} + +/** + * @Author Pan + * @brief 是否锁定纵横比 + * @param none + * @return bool + * @date 2017/06/25 + */ +bool DocImageBlock::isWidthHeightRatioLocked() +{ + return width_height_ratio_locked; +} + +/** + * @Author Pan + * @brief 获取纵横比 + * @param none + * @return double + * @date 2017/06/25 + */ +double DocImageBlock::getWidthHeightRatio() +{ + if (isWidthHeightRatioLocked()) + return width_height_ratio; +} + /** * @Author Pan * @brief 焦点聚焦,显示边框 @@ -35,6 +96,7 @@ void DocImageBlock::setImage(QPixmap & pixmap) void DocImageBlock::focusInEvent(QFocusEvent *e) { //qDebug() << "focus In Event"; + this->setFrameShape(QFrame::Box); this->setLineWidth(1); QLabel::focusInEvent(e); @@ -52,3 +114,78 @@ void DocImageBlock::focusOutEvent(QFocusEvent *e) this->setFrameStyle(QFrame::NoFrame); QLabel::focusOutEvent(e); } + +/** + * @Author Pan + * @brief 右键菜单 + * @param QContextMenuEvent *ev + * @return void + * @date 2017/06/24 + */ +void DocImageBlock::contextMenuEvent(QContextMenuEvent *ev) +{ + context_menu->addAction(this->change_image); + context_menu->addAction(this->set_image_properties); + + context_menu->exec(ev->globalPos()); +} + +/** + * @Author Pan + * @brief 更换图片的槽函数 + * @param none + * @return void + * @date 2017/06/25 + */ +void DocImageBlock::changeImage() +{ + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open File"), QDir::currentPath()); + if (!fileName.isEmpty()) { + QPixmap image(fileName); + if (image.isNull()) { + QMessageBox::information(this, tr("OFD Editor"), + tr("Cannot open file %1.").arg(fileName)); + return; + } + this->setPixmap(image); + } +} + +/** + * @Author Pan + * @brief 跳出属性设置菜单,并向对话框发出信号 + * @param none + * @return void + * @date 2017/06/25 + */ +void DocImageBlock::setImageProperties() +{ + emit sendImageInfo(this->width(), + this->height(), + this->pos().x(), + this->pos().y(), + this->block->getPage()->width(), + this->block->getPage()->height(), + this->width_height_ratio_locked); + properties_dialog->exec(); +} + +/** + * @Author Pan + * @brief 槽函数,根据对话框的信息改动更新自身属性 + * @param 若干参数 + * @return void + * @date 2017/06/25 + */ +void DocImageBlock::imagePropertiesChanged(double new_width, + double new_height, + double new_x, + double new_y, + bool ratio_locked) +{ + this->resize(new_width, new_height); + this->move(new_x, new_y); + this->width_height_ratio_locked = ratio_locked; + this->width_height_ratio = new_width / new_height; +} diff --git a/ofdEditor/model/Doc/DocImageBlock.h b/ofdEditor/model/Doc/DocImageBlock.h index ac41d51..909a075 100644 --- a/ofdEditor/model/Doc/DocImageBlock.h +++ b/ofdEditor/model/Doc/DocImageBlock.h @@ -3,9 +3,14 @@ #include "model_global.h" #include "Doc/DocBlock.h" +#include "../Widget/imagepropertiesdialog.h" #include //存放图片的QWidget +#include +#include // 本类型用来表述文章中的图形、图片之类的 +class DocBlock; +class ImagePropertiesDialog; class MODELSHARED_EXPORT DocImageBlock : public QLabel { @@ -13,10 +18,42 @@ class MODELSHARED_EXPORT DocImageBlock : public QLabel public: DocImageBlock(QWidget *parent = NULL); void setImage(QPixmap & pixmap); + void setBlock(DocBlock * _block); + bool isWidthHeightRatioLocked(); + double getWidthHeightRatio(); + +public slots: + void imagePropertiesChanged(double new_width, + double new_height, + double new_x, + double new_y, + bool ratio_locked); + +protected: void focusInEvent(QFocusEvent *ev); void focusOutEvent(QFocusEvent *ev); + void contextMenuEvent(QContextMenuEvent *ev); + private: + DocBlock * block; //对代理它的DocBlock的引用 + QMenu * context_menu; //右键菜单 + QAction * change_image; //更改图片 + QAction * set_image_properties; //更改图片的位置和尺寸 + ImagePropertiesDialog * properties_dialog; + bool width_height_ratio_locked; + double width_height_ratio; +private slots: + void changeImage(); + void setImageProperties(); +signals: + void sendImageInfo(double image_width, + double image_height, + double image_x, + double image_y, + double page_width, + double page_height, + bool ratio_is_locked); }; #endif // DOCIMAGEBLOCK_H diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index 07e41c3..9b7053b 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -9,7 +9,7 @@ #include "Doc/DocPicture.h" #include "Doc/DocGraph.h" #include "Doc/DocPassage.h" - +#include "DocImageBlock.h" #include #include #include @@ -33,7 +33,8 @@ DocPage::DocPage(QWidget *parent) this->setSize(210,297); // 默认A4纸张大小 this->scaleFactor = 1.0; this->init(); - + activeBlock = NULL; +// this->setMouseTracking(true); } DocPage::DocPage(double width, @@ -307,6 +308,15 @@ void DocPage::mousePressEvent(QMouseEvent *event) // qDebug()<<" Accepted Signal is blockMove"; this->newBlockFlag = blockMove; } + else if (block->currentStatus( + block->mapFromScene(tempPoint)) + == DocBlock::blockResize + && block->isImageBlock()) + { + this->newBlockFlag = DocPage::blockResize; + this->oldPos = activeBlock->pos(); +// qDebug() << "oh yeah"; + } else { // qDebug()<<"not Move"; @@ -365,7 +375,26 @@ void DocPage::mouseMoveEvent(QMouseEvent *event) this->viewport()->update(); // 调用刷新 } - + else if (activeBlock + && activeBlock->isImageBlock() + && this->newBlockFlag == DocPage::blockResize) + { +// qDebug() << "hahaha"; + DocImageBlock * image_block = activeBlock->getImageBlock(); + this->newPos = this->mapToScene(event->pos()); + QPointF point = this->newPos - this->oldPos; + if (!image_block->isWidthHeightRatioLocked()) + this->activeBlock->resize(point.rx(),point.ry()); + else + { + double ratio = image_block->getWidthHeightRatio(); + if(point.rx() < + point.ry() * ratio) + this->activeBlock->resize(point.rx(), point.rx() / ratio); + else + this->activeBlock->resize(point.ry() * ratio, point.ry()); + } + } } /** @@ -453,7 +482,7 @@ void DocPage::init() void DocPage::addImage() { - qDebug() << "???"; + //qDebug() << "???"; //打开对话框,选取一个图片文件 QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), QDir::currentPath()); @@ -471,10 +500,10 @@ void DocPage::addImage() newBlock->setWidget(new_image_block); new_image_block->setImage(image); double page_width = this->width(), page_height = this->height(); - qDebug() << "Page Width: " << this->width(); - qDebug() << "Page Height: " << this->height(); - qDebug() << "Image Width: " << image.width(); - qDebug() << "Image Height: " << image.height(); +// qDebug() << "Page Width: " << this->width(); +// qDebug() << "Page Height: " << this->height(); +// qDebug() << "Image Width: " << image.width(); +// qDebug() << "Image Height: " << image.height(); double ratio; if (image.width() > page_width || image.height() > page_height) { diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index 4ea6cc7..3670091 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -29,7 +29,7 @@ class MODELSHARED_EXPORT DocPage Q_OBJECT public: enum Layer{Body,Foreground,Background}; // 分为三层 - enum BlockFlag{none,draw,drawMove,blockMove}; // 插入时的绘制状态 + enum BlockFlag{none,draw,drawMove,blockMove, blockResize}; // 插入时的绘制状态 enum BlockType{text,image,table}; // 插入时的类型 explicit DocPage(QWidget * parent = 0); diff --git a/ofdEditor/model/Widget/DocInfoDialog.h b/ofdEditor/model/Widget/DocInfoDialog.h index b911605..1cad920 100644 --- a/ofdEditor/model/Widget/DocInfoDialog.h +++ b/ofdEditor/model/Widget/DocInfoDialog.h @@ -17,6 +17,8 @@ public: private: Ui::DocInfoDialog *ui; + + }; #endif // DOCINFODIALOG_H diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.cpp b/ofdEditor/model/Widget/imagepropertiesdialog.cpp new file mode 100644 index 0000000..db6d99c --- /dev/null +++ b/ofdEditor/model/Widget/imagepropertiesdialog.cpp @@ -0,0 +1,202 @@ +#include "imagepropertiesdialog.h" +#include "ui_imagepropertiesdialog.h" +#include +/** + * @Author Pan + * @brief 构造函数,完成了成员组件的初始化、设置,以及信号槽的连接 + * @param DocImageBlock * _block, QWidget * parent + * @return + * @date 2017/06/25 + */ +ImagePropertiesDialog::ImagePropertiesDialog(DocImageBlock * _block, QWidget *parent) : + QDialog(parent), + ui(new Ui::ImagePropertiesDialog), + block(_block) +{ + ui->setupUi(this); + this->connect(_block, + SIGNAL(sendImageInfo(double,double, + double,double, + double,double,bool)), + this, + SLOT(receiveImageInfo(double,double, + double,double, + double,double,bool))); + + ui->WidthInPixel->setRange(0.0, 100000); + ui->HeightInPixel->setRange(0.0, 100000); + ui->xInPixel->setRange(0.0, 10000); + ui->yInPixel->setRange(0.0, 10000); + ui->WidthInPercentage->setRange(0.0, 10000.0); + ui->HeightInPercentage->setRange(0.0, 10000.0); + ui->xInPercentage->setRange(0.0, 100.0); + ui->yInPercentage->setRange(0.0, 100.0); + this->connect(this, SIGNAL(accepted()), this, SLOT(emitMessage())); + this->connect(ui->LockRatio, SIGNAL(stateChanged(int)), this, SLOT(lockRatioStateChanged(int))); + this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), this, SLOT(Percentage2Pixel(double))); + this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), this, SLOT(Percentage2Pixel(double))); + this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), this, SLOT(Percentage2Pixel(double))); + this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), this, SLOT(Percentage2Pixel(double))); + this->connect(ui->HeightInPixel, SIGNAL(valueChanged(double)), this, SLOT(Pixel2Percentage(double))); + this->connect(ui->WidthInPixel, SIGNAL(valueChanged(double)), this, SLOT(Pixel2Percentage(double))); + this->connect(ui->xInPixel, SIGNAL(valueChanged(double)), this, SLOT(Pixel2Percentage(double))); + this->connect(ui->yInPixel, SIGNAL(valueChanged(double)), this, SLOT(Pixel2Percentage(double))); +} +/** + * @Author Pan + * @brief 槽函数,用语接收DocImageBlock的信号后更新自身的信息 + * @param 若干参数 + * @return void + * @date 2017/06/25 + */ +void ImagePropertiesDialog::receiveImageInfo(double image_width, + double image_height, + double image_x, + double image_y, + double page_width, + double page_height, + bool ratio_is_locked) { + ui->LockRatio->setChecked(ratio_is_locked); + ui->InitialSize->setText(tr("Width: ") + QString::number(image_width) + tr(", Height: ") + QString::number(image_height)); + initial_width = image_width; + initial_height = image_height; + ratio_locked = ratio_is_locked; + this->page_width = page_width; + this->page_height = page_height; + +// ui->WidthInPercentage->setValue(100.0); +// ui->HeightInPercentage->setValue(100.0); +// ui->xInPercentage->setValue(image_x / page_width * 100.0); +// ui->yInPercentage->setValue(image_y / page_height * 100.0); + + ui->WidthInPixel->setValue(image_width); + ui->HeightInPixel->setValue(image_height); + ui->xInPixel->setValue(image_x); + ui->yInPixel->setValue(image_y); + + ui->WidthInPercentage->setValue(ui->WidthInPixel->value() / image_width * 100.0); + ui->HeightInPercentage->setValue(ui->HeightInPixel->value() / image_height * 100.0); + ui->xInPercentage->setValue(ui->xInPixel->value() / page_width * 100.0); + ui->yInPercentage->setValue(ui->yInPixel->value() / page_width * 100.0); + +} + + + +ImagePropertiesDialog::~ImagePropertiesDialog() +{ + delete ui; +} + +/** + * @Author Pan + * @brief 发送信号 + * @param void + * @return void + * @date 2017/06/25 + */ +void ImagePropertiesDialog::emitMessage() +{ + emit changeImageProperties(ui->WidthInPixel->value(), + ui->HeightInPixel->value(), + ui->xInPixel->value(), + ui->yInPixel->value(), + ui->LockRatio->isChecked()); +} + +/** + * @Author Pan + * @brief 切换锁定纵横比的模式 + * @param int locked + * @return void + * @date 2017/06/25 + */ +void ImagePropertiesDialog::lockRatioStateChanged(int locked) +{ + if (locked == Qt::Checked && !ratio_locked) + { +// qDebug() << "Set to Checked."; + ratio_locked = true; + this->connect(ui->WidthInPixel, + SIGNAL(valueChanged(double)), + this, SLOT(Width2HeightTrans(double))); + this->connect(ui->HeightInPixel, + SIGNAL(valueChanged(double)), + this, SLOT(Height2WidthTrans(double))); + } + else if (locked == Qt::Unchecked && ratio_locked) + { +// qDebug() << "Set to Unchecked."; + ratio_locked = false; + this->disconnect(ui->WidthInPercentage, + SIGNAL(valueChanged(double)), + this, SLOT(Width2HeightTrans(double))); + this->disconnect(ui->HeightInPercentage, + SIGNAL(valueChanged(double)), + this, SLOT(Height2WidthTrans(double))); + } +} + +/** + * @Author Pan + * @brief 锁定纵横比时,宽度到高度的按比例同步 + * @param double value + * @return void + * @date 2017/06/25 + */ +void ImagePropertiesDialog::Width2HeightTrans(double value) +{ + //qDebug() << "W2H"; + double ratio = initial_height / initial_width; + ui->HeightInPixel->setValue(value * ratio); +} + +/** + * @Author Pan + * @brief 锁定纵横比时,高度到宽度的按比例同步 + * @param double value + * @return void + * @date 2017/06/25 + */ +void ImagePropertiesDialog::Height2WidthTrans(double value) +{ + //qDebug() << "H2W"; + double ratio = initial_width / initial_height; + ui->WidthInPixel->setValue(value * ratio); +} + +/** + * @Author Pan + * @brief 从像素量到比例量的同步 + * @param double value + * @return void + * @date 2017/06/25 + */ +void ImagePropertiesDialog::Pixel2Percentage(double value) +{ +// static int cnt = 1; +// qDebug() << cnt++; + qDebug() << ui->HeightInPixel->value(); + ui->HeightInPercentage->setValue(100.0 * ui->HeightInPixel->value() / initial_height); + ui->WidthInPercentage->setValue(100.0 * ui->WidthInPixel->value() / initial_width); + ui->xInPercentage->setValue(100.0 * ui->xInPixel->value() / page_width); + ui->yInPercentage->setValue(100.0 * ui->yInPixel->value() / page_height); +} + +/** + * @Author Pan + * @brief 从比例量到像素量的同步 + * @param double value + * @return void + * @date 2017/06/25 + */ +void ImagePropertiesDialog::Percentage2Pixel(double value) +{ + ui->HeightInPixel->setValue(ui->HeightInPercentage->value() * initial_height / 100.0); + ui->WidthInPixel->setValue(ui->WidthInPercentage->value() * initial_width / 100.0); + ui->xInPixel->setValue(ui->xInPercentage->value() * page_width / 100.0); + ui->yInPixel->setValue(ui->yInPercentage->value() * page_height / 100.0); +} + + + diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.h b/ofdEditor/model/Widget/imagepropertiesdialog.h new file mode 100644 index 0000000..6faf7f5 --- /dev/null +++ b/ofdEditor/model/Widget/imagepropertiesdialog.h @@ -0,0 +1,51 @@ +#ifndef IMAGEPROPERTIESDIALOG_H +#define IMAGEPROPERTIESDIALOG_H + +#include +#include "../Doc/DocImageBlock.h" + +class DocImageBlock; +namespace Ui { +class ImagePropertiesDialog; +} + +class ImagePropertiesDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ImagePropertiesDialog(DocImageBlock * _block, QWidget *parent = 0); + ~ImagePropertiesDialog(); + +private: + Ui::ImagePropertiesDialog *ui; + DocImageBlock * block; + double initial_width; + double initial_height; + bool ratio_locked; + double page_width; + double page_height; +private slots: + void emitMessage(); + void lockRatioStateChanged(int locked); + void Width2HeightTrans(double value); + void Height2WidthTrans(double value); + void Pixel2Percentage(double value); + void Percentage2Pixel(double value); +public slots: + void receiveImageInfo(double image_width, + double image_height, + double image_x, + double image_y, + double page_width, + double page_height, + bool ratio_is_locked); +signals: + void changeImageProperties(double new_width, + double new_height, + double new_x, + double new_y, + bool ratio_locked); +}; + +#endif // IMAGEPROPERTIESDIALOG_H diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.ui b/ofdEditor/model/Widget/imagepropertiesdialog.ui new file mode 100644 index 0000000..e9fa6f1 --- /dev/null +++ b/ofdEditor/model/Widget/imagepropertiesdialog.ui @@ -0,0 +1,527 @@ + + + ImagePropertiesDialog + + + + 0 + 0 + 436 + 389 + + + + Dialog + + + + + 70 + 340 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 30 + 40 + 54 + 12 + + + + + + + + + + 30 + 20 + 71 + 21 + + + + + 宋体 + 12 + + + + 图片尺寸 + + + + + + 130 + 60 + 71 + 22 + + + + + + + 280 + 60 + 62 + 22 + + + + + + + 100 + 22 + 311 + 16 + + + + Qt::Horizontal + + + + + + 40 + 60 + 41 + 20 + + + + + 宋体 + 12 + + + + 高度 + + + + + + 40 + 100 + 41 + 20 + + + + + 宋体 + 12 + + + + 宽度 + + + + + + 130 + 100 + 71 + 22 + + + + + + + 280 + 100 + 62 + 22 + + + + + + + 210 + 60 + 31 + 20 + + + + + 宋体 + 11 + false + + + + 像素 + + + + + + 210 + 100 + 31 + 20 + + + + + 宋体 + 11 + false + + + + 像素 + + + + + + 350 + 60 + 71 + 20 + + + + + 宋体 + 11 + false + + + + %原尺寸 + + + + + + 350 + 100 + 71 + 16 + + + + + 宋体 + 11 + false + + + + %原尺寸 + + + + + + 290 + 140 + 110 + 20 + + + + + 宋体 + 12 + + + + 锁定纵横比 + + + + + + 40 + 140 + 81 + 20 + + + + + 宋体 + 11 + + + + 原始尺寸: + + + + + + 130 + 140 + 101 + 16 + + + + + Agency FB + 11 + + + + QFrame::WinPanel + + + QFrame::Sunken + + + 122 ,122 + + + Qt::AlignCenter + + + + + + 30 + 180 + 71 + 21 + + + + + 宋体 + 12 + + + + 图片位置 + + + + + + 100 + 183 + 311 + 16 + + + + Qt::Horizontal + + + + + + 40 + 220 + 41 + 20 + + + + + 宋体 + 12 + + + + 水平 + + + + + + 40 + 260 + 41 + 20 + + + + + 宋体 + 12 + + + + 垂直 + + + + + + 130 + 220 + 71 + 22 + + + + + + + 210 + 220 + 31 + 20 + + + + + 宋体 + 11 + false + + + + 像素 + + + + + + 280 + 260 + 62 + 22 + + + + + + + 130 + 260 + 71 + 22 + + + + + + + 210 + 260 + 31 + 20 + + + + + 宋体 + 11 + false + + + + 像素 + + + + + + 350 + 220 + 71 + 20 + + + + + 宋体 + 11 + false + + + + %页面 + + + + + + 350 + 260 + 71 + 16 + + + + + 宋体 + 11 + false + + + + %页面 + + + + + + 280 + 220 + 62 + 22 + + + + + + + + EnableChangeOfProperties + accepted() + ImagePropertiesDialog + accept() + + + 298 + 294 + + + 157 + 274 + + + + + EnableChangeOfProperties + rejected() + ImagePropertiesDialog + reject() + + + 366 + 300 + + + 286 + 274 + + + + + diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index 4533645..5cdc451 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -52,7 +52,8 @@ SOURCES += model.cpp \ Convert/Objects/MinTextUnit.cpp \ Widget/DocInfoDialog.cpp \ Command/SetTextBlodCmd.cpp \ - Doc/DocImageBlock.cpp + Doc/DocImageBlock.cpp \ + Widget/imagepropertiesdialog.cpp HEADERS += model.h\ model_global.h \ @@ -84,7 +85,8 @@ HEADERS += model.h\ Convert/Objects/MinTextUnit.h \ Widget/DocInfoDialog.h \ Command/SetTextBlodCmd.h \ - Doc/DocImageBlock.h + Doc/DocImageBlock.h \ + Widget/imagepropertiesdialog.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 @@ -112,4 +114,5 @@ FORMS += \ Widget/ParagraphFormatWidget.ui \ Widget/ParagraphFormatDialog.ui \ Widget/FontSettingDialog.ui \ - Widget/DocInfoDialog.ui + Widget/DocInfoDialog.ui \ + Widget/imagepropertiesdialog.ui diff --git a/ofdEditor/test_pan/main.cpp b/ofdEditor/test_pan/main.cpp index 0258359..3188f32 100644 --- a/ofdEditor/test_pan/main.cpp +++ b/ofdEditor/test_pan/main.cpp @@ -27,13 +27,9 @@ using namespace std; int main(int argc, char *argv[]) { - try { - OFDParser t("F:/第六届中软杯/OFD Document/OFD.xml"); - OFD * i = t.getData(); - qDebug() << "从Document_0中收集到的ID数量: " << i->getDocuments()->at(0)->getIDTable()->size(); - qDebug() << "Document.xml中的MaxUnitID属性值: " << i->getDocuments()->at(0)->getCommonData()->getMaxUnitID(); -// OFDWriter w(i, "F:/第六届中软杯/OFD Writing Test 2/"); - } catch (Exception e) { - qDebug() << e.getMessage(); - } + QApplication a(argc, argv); + PassageMainWindow w; + w.show(); + + return a.exec(); } diff --git a/ofdEditor/test_pan/mainwindow.cpp b/ofdEditor/test_pan/mainwindow.cpp index 469836b..de8d8e1 100644 --- a/ofdEditor/test_pan/mainwindow.cpp +++ b/ofdEditor/test_pan/mainwindow.cpp @@ -2,6 +2,8 @@ #include "ui_mainwindow.h" #include #include +#include +#include using namespace std; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), diff --git a/ofdEditor/test_pan/mainwindow.h b/ofdEditor/test_pan/mainwindow.h index 91faf0b..cdc2229 100644 --- a/ofdEditor/test_pan/mainwindow.h +++ b/ofdEditor/test_pan/mainwindow.h @@ -15,21 +15,21 @@ class MainWindow : public QMainWindow public: explicit MainWindow(QWidget *parent = 0); - void start(); - void readOFD(); - void readDocument(); - void readCustomTags(); - void readPublicRes(); - void readPage(); - void readPageArea(); - void readContent(); +// void start(); +// void readOFD(); +// void readDocument(); +// void readCustomTags(); +// void readPublicRes(); +// void readPage(); +// void readPageArea(); +// void readContent(); ~MainWindow(); private: Ui::MainWindow *ui; - QFile *file; - //Page p; - QXmlStreamReader reader; +// QFile *file; +// Page p; +// QXmlStreamReader reader; }; -- Gitee From 4de21dd7469ec92aa1cc739986c52b15b2bf871e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sun, 25 Jun 2017 11:34:22 +0800 Subject: [PATCH 08/83] =?UTF-8?q?=E9=A2=84=E5=A4=87=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/Doc_OFDConvertor.cpp | 41 ++++++++++ ofdEditor/model/Doc/DocPassage.h | 4 +- ofdEditor/model/Doc/DocTextBlock.cpp | 78 ++++++++++++++++++++ ofdEditor/model/Doc/DocTextBlock.h | 4 +- 4 files changed, 124 insertions(+), 3 deletions(-) diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp index 80efd9e..0d46dc0 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include "DataTypes/basic_datatype.h" #include "DataTypes/document/ofd.h" @@ -234,9 +236,48 @@ void Doc_OFDConvertor::buildLayer(CT_Layer* ctLayer,DocLayer *layer) */ void Doc_OFDConvertor::buildText(CT_Layer* ctLayer,DocTextBlock *textBlock) { + if(textBlock->getContentLength() == 0) + { + // 如果文本框中没有内容 + qDebug() << "The textBlock has no content in it."; + return; + } + // 分析TextBlock textBlock->moveCursor(QTextCursor::Start); // 移动到块的开始 QTextCursor cursor = textBlock->textCursor(); + QTextDocument* document = cursor.document(); + int blockCount = document->blockCount(); // 获得Block的数量 + + qDebug() << "This textBlock has " << blockCount << " QTextBlocks"; + + for(int i =0; i #include #include +#include @@ -104,6 +105,32 @@ DocBlock *DocTextBlock::getBlock() return this->block; } +/** + * @Author Chaoqun + * @brief 获得TextBlock中的所有文本 + * @param void + * @return QString & + * @date 2017/06/25 + */ +QString &DocTextBlock::getContent() +{ + QString content = this->document()->toPlainText(); // 获得纯文本 + return content; +} + +/** + * @Author Chaoqun + * @brief 蝴蝶文字框内容长度 + * @param void + * @return int + * @date 2017/06/25 + */ +int DocTextBlock::getContentLength() +{ + QString content = this->document()->toPlainText(); + return content.length(); +} + /** * @Author Chaoqun * @brief 用来合并格式 @@ -334,6 +361,57 @@ void DocTextBlock::textUnderline() false:true); mergeFormatOnWordOrSelection(fmt); // 合并格式 + + +// /////test +// QTextCursor cursor = this->textCursor(); // 获取光标 +// cursor.movePosition(QTextCursor::Start); // 移动到文章开头 +// for(int i = 0 ; i < this->document()->blockCount(); i++) +// { +// QTextBlock block = cursor.block(); // 获得当前块 +// QTextCursor tempCursor = cursor; // 复制cursor + +// QTextBlock::Iterator iter = block.begin(); // 块的开始 +// QString lineContent; // 行内容 +// QString tempFragement; // 块 +// QTextFragment fragment; // 短句 + +// while(!iter.atEnd()) // 用来判断是否处理完了 +// { +// if(tempFragement == "") +// { +// // 如果处理字段为空 +// fragment = iter.fragment(); // 获得当前的 +// tempFragement = fragment.text(); // +// iter++; +// } +//// while(lineContent.length() < tempFragement.length()) +//// { +//// cursor.select(QTextCursor::LineUnderCursor); // 选择当前行 +//// QString currentLine = cursor.selectedText(); // 选中的文字 + +//// lineContent += currentLine; // 追加一行 +//// qDebug() << "Read Next Line: " << currentLine +//// << "LineContent: " << lineContent; +//// } +// if(lineContent == "") +// { +// cursor.select(QTextCursor::LineUnderCursor); // 选择当前行 +// QString currentLine = cursor.selectedText(); // 选中的文字 + +// lineContent += currentLine; // 追加一行 +// qDebug() << "Read Next Line: " << currentLine +// << "LineContent: " << lineContent; +// } + +// // 处理当前Fragment +//// if(fra) + + +// } + +// cursor.movePosition(QTextCursor::NextBlock); +// } } /** diff --git a/ofdEditor/model/Doc/DocTextBlock.h b/ofdEditor/model/Doc/DocTextBlock.h index 51815bc..7e1a8d7 100644 --- a/ofdEditor/model/Doc/DocTextBlock.h +++ b/ofdEditor/model/Doc/DocTextBlock.h @@ -33,8 +33,8 @@ public: DocPage* getPage(); // 获得页 DocLayer* getLayer(); // 获得层 DocBlock* getBlock(); // 获得Block - - + QString& getContent(); // 获得TextBlock中的所有文本 + int getContentLength(); // 获得内部文字长度 public slots: -- Gitee From 270f42584be394ac27e9676e5004efd42ac5f6c7 Mon Sep 17 00:00:00 2001 From: Pan Yanxing Date: Sun, 25 Jun 2017 11:37:08 +0800 Subject: [PATCH 09/83] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E5=BF=AB?= =?UTF-8?q?=E6=8D=B7=E5=9B=BE=E7=89=87=E6=A0=BC=E5=BC=8F=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocImageBlock.cpp | 3 +- ofdEditor/model/Doc/DocImageBlock.h | 6 ++-- ofdEditor/model/Doc/DocPage.cpp | 8 +++++ ofdEditor/model/Doc/DocPassage.h | 2 ++ .../model/Widget/imagepropertiesdialog.cpp | 35 +++++++++++-------- ofdEditor/start/ui/PassageMainWindow.cpp | 27 +++++++++++--- ofdEditor/start/ui/PassageMainWindow.h | 7 +++- 7 files changed, 64 insertions(+), 24 deletions(-) diff --git a/ofdEditor/model/Doc/DocImageBlock.cpp b/ofdEditor/model/Doc/DocImageBlock.cpp index 742b5df..afb1bef 100644 --- a/ofdEditor/model/Doc/DocImageBlock.cpp +++ b/ofdEditor/model/Doc/DocImageBlock.cpp @@ -34,7 +34,6 @@ DocImageBlock::DocImageBlock(QWidget *parent) this, SLOT(imagePropertiesChanged(double,double, double,double, bool))); - } /** @@ -96,7 +95,7 @@ double DocImageBlock::getWidthHeightRatio() void DocImageBlock::focusInEvent(QFocusEvent *e) { //qDebug() << "focus In Event"; - + emit signals_currrentImageBlock(this); this->setFrameShape(QFrame::Box); this->setLineWidth(1); QLabel::focusInEvent(e); diff --git a/ofdEditor/model/Doc/DocImageBlock.h b/ofdEditor/model/Doc/DocImageBlock.h index 909a075..8ac5f9e 100644 --- a/ofdEditor/model/Doc/DocImageBlock.h +++ b/ofdEditor/model/Doc/DocImageBlock.h @@ -28,6 +28,8 @@ public slots: double new_x, double new_y, bool ratio_locked); + void changeImage(); + void setImageProperties(); protected: void focusInEvent(QFocusEvent *ev); @@ -42,9 +44,6 @@ private: ImagePropertiesDialog * properties_dialog; bool width_height_ratio_locked; double width_height_ratio; -private slots: - void changeImage(); - void setImageProperties(); signals: void sendImageInfo(double image_width, @@ -54,6 +53,7 @@ signals: double page_width, double page_height, bool ratio_is_locked); + void signals_currrentImageBlock(DocImageBlock * textBlock); //当前操作的imageBlock }; #endif // DOCIMAGEBLOCK_H diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index 9b7053b..9788fdc 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -134,7 +134,15 @@ void DocPage::addBlock(DocBlock *block, DocPage::Layer layer) passage,SIGNAL(signals_currentCharFormatChanged(QTextCharFormat&))); connect(textBlock,SIGNAL(signals_currentTextBlock(DocTextBlock*)), passage,SIGNAL(signals_currentTextBlock(DocTextBlock*))); + } else if (block->isImageBlock()) + { + DocImageBlock * imageBlock = block->getImageBlock(); + DocPassage * passage = this->getPassage(); + //emit this->signals_insertImageBlock(); + //转发给passage + this->connect(imageBlock, SIGNAL(signals_currrentImageBlock(DocImageBlock*)), + passage, SIGNAL(signals_currentImageBlock(DocImageBlock*))); } // 分到层 diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index 0502ecb..76082f3 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -20,6 +20,7 @@ class CT_DocInfo; class CT_CommonData; class DocBlock; class DocTextBlock; +class DocImageBlock; /** * @Author Chaoqun @@ -105,6 +106,7 @@ signals: void signals_currentBlockFormatChanged( QTextBlockFormat& fmt); // 当前选择的block格式发生了变化 void signals_currentTextBlock(DocTextBlock* textBlock); // 当前操作的textBlock + void signals_currentImageBlock(DocImageBlock* imageBlock); //当前操作的imageBlock }; diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.cpp b/ofdEditor/model/Widget/imagepropertiesdialog.cpp index db6d99c..0ad83ec 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.cpp +++ b/ofdEditor/model/Widget/imagepropertiesdialog.cpp @@ -41,6 +41,12 @@ ImagePropertiesDialog::ImagePropertiesDialog(DocImageBlock * _block, QWidget *pa this->connect(ui->WidthInPixel, SIGNAL(valueChanged(double)), this, SLOT(Pixel2Percentage(double))); this->connect(ui->xInPixel, SIGNAL(valueChanged(double)), this, SLOT(Pixel2Percentage(double))); this->connect(ui->yInPixel, SIGNAL(valueChanged(double)), this, SLOT(Pixel2Percentage(double))); + this->connect(ui->WidthInPixel, + SIGNAL(valueChanged(double)), + this, SLOT(Width2HeightTrans(double))); + this->connect(ui->HeightInPixel, + SIGNAL(valueChanged(double)), + this, SLOT(Height2WidthTrans(double))); } /** * @Author Pan @@ -113,20 +119,16 @@ void ImagePropertiesDialog::emitMessage() */ void ImagePropertiesDialog::lockRatioStateChanged(int locked) { + qDebug() << "Waaaa"; if (locked == Qt::Checked && !ratio_locked) { -// qDebug() << "Set to Checked."; + qDebug() << "Set to Checked."; ratio_locked = true; - this->connect(ui->WidthInPixel, - SIGNAL(valueChanged(double)), - this, SLOT(Width2HeightTrans(double))); - this->connect(ui->HeightInPixel, - SIGNAL(valueChanged(double)), - this, SLOT(Height2WidthTrans(double))); + } else if (locked == Qt::Unchecked && ratio_locked) { -// qDebug() << "Set to Unchecked."; + qDebug() << "Set to Unchecked."; ratio_locked = false; this->disconnect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), @@ -147,8 +149,11 @@ void ImagePropertiesDialog::lockRatioStateChanged(int locked) void ImagePropertiesDialog::Width2HeightTrans(double value) { //qDebug() << "W2H"; - double ratio = initial_height / initial_width; - ui->HeightInPixel->setValue(value * ratio); + if (ratio_locked) + { + double ratio = initial_height / initial_width; + ui->HeightInPixel->setValue(value * ratio); + } } /** @@ -160,9 +165,11 @@ void ImagePropertiesDialog::Width2HeightTrans(double value) */ void ImagePropertiesDialog::Height2WidthTrans(double value) { - //qDebug() << "H2W"; - double ratio = initial_width / initial_height; - ui->WidthInPixel->setValue(value * ratio); + if (ratio_locked) + { + double ratio = initial_width / initial_height; + ui->WidthInPixel->setValue(value * ratio); + } } /** @@ -176,7 +183,7 @@ void ImagePropertiesDialog::Pixel2Percentage(double value) { // static int cnt = 1; // qDebug() << cnt++; - qDebug() << ui->HeightInPixel->value(); +// qDebug() << ui->HeightInPixel->value(); ui->HeightInPercentage->setValue(100.0 * ui->HeightInPixel->value() / initial_height); ui->WidthInPercentage->setValue(100.0 * ui->WidthInPixel->value() / initial_width); ui->xInPercentage->setValue(100.0 * ui->xInPixel->value() / page_width); diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index aa004e8..d3c2ff4 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -288,6 +288,9 @@ void PassageMainWindow::connectAction() connect(this->paragraphFormat,SIGNAL(triggered(bool)), this,SLOT(paragraphDialog())); // 修改段落 + connect(this->imageFormat, SIGNAL(triggered(bool)), + this, SLOT(imageDialog())); //修改图片 + connect(this->area, SIGNAL(subWindowActivated(QMdiSubWindow*)), this->connector, SLOT(updateActivePassage(QMdiSubWindow*))); // 检测ActivePassage更新 } @@ -355,7 +358,8 @@ void PassageMainWindow::openFile() */ void PassageMainWindow::fontDialog() { - this->textBlock->customFontDialog(); // 用自定义窗口修改字体 + if (textBlock) + this->textBlock->customFontDialog(); // 用自定义窗口修改字体 } /** @@ -367,7 +371,14 @@ void PassageMainWindow::fontDialog() */ void PassageMainWindow::paragraphDialog() { - this->textBlock->textParagraph(); // 用自定义段落窗口修改段落 + if (textBlock) + this->textBlock->textParagraph(); // 用自定义段落窗口修改段落 +} + +void PassageMainWindow::imageDialog() +{ + if (imageBlock) + this->imageBlock->setImageProperties(); } /** @@ -380,6 +391,7 @@ void PassageMainWindow::paragraphDialog() void PassageMainWindow::acceptTextBlock(DocTextBlock *textBlock) { this->textBlock = textBlock; // 修改引用 + this->imageBlock = NULL; } /** @@ -406,10 +418,15 @@ void PassageMainWindow::acceptTextBlockFormat(QTextBlockFormat &blockFormat) void PassageMainWindow::acceptTextCharFormat(QTextCharFormat &charFormat) { this->_currentCharFormat = &charFormat; // 留下引用 - // 更新界面显示 } +void PassageMainWindow::acceptImageBlock(DocImageBlock *imageBlock) +{ + this->imageBlock = imageBlock; + this->textBlock = NULL; +} + /** * @Author Chaoqun * @brief 获取激活的窗口 @@ -452,7 +469,9 @@ DocPassage *PassageMainWindow::addDocPassage(DocPassage *passage) // 处理变更的textBlock this->connect(passage,SIGNAL(signals_currentTextBlock(DocTextBlock*)), this,SLOT(acceptTextBlock(DocTextBlock*))); - + //处理变更的imageBlock + this->connect(passage, SIGNAL(signals_currentImageBlock(DocImageBlock*)), + this, SLOT(acceptImageBlock(DocImageBlock*))); return passage; } diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index d07719f..5b1364b 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -15,6 +15,7 @@ class DocTextBlock; class QTextCharFormat; class QTextBlockFormat; class ActionConnector; // 函数功能的中间件 +class DocImageBlock; // 编辑窗口的主界面 class PassageMainWindow @@ -66,6 +67,7 @@ private: QAction * insertTableAction; // 插入表格 // 格式 + QAction * pageFormat; // 页面格式调整 QAction * textFormat; // 文字格式调整 QAction * paragraphFormat; // 段落格式调整 QAction * imageFormat; // 图形格式调整 @@ -91,16 +93,19 @@ private: QTextCharFormat* _currentCharFormat; // 当前字符格式 QTextBlockFormat* _currentBlockFormat; // 当前块格式 + DocImageBlock *imageBlock; //图片块 + private slots: void openFile(); // 打开新文件 void fontDialog(); // 打开字体框 void paragraphDialog(); // 打开段落框 + void imageDialog(); // 打开图片框 void acceptTextBlock(DocTextBlock* textBlock); // 接受当前处理的文字块的更新 void acceptTextBlockFormat(QTextBlockFormat& blockFormat); // 接受当前处理的块格式 void acceptTextCharFormat(QTextCharFormat& charFormat); // 接受当前处理的字符格式 - + void acceptImageBlock(DocImageBlock * imageBlock); //接受当前处理的图片块 }; #endif // PASSAGEMAINWINDOW_H -- Gitee From 5c6ac45e51f5d05880f504066fd738a75501bb6d Mon Sep 17 00:00:00 2001 From: Pan Yanxing Date: Mon, 26 Jun 2017 22:47:23 +0800 Subject: [PATCH 10/83] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E5=A4=A7=E5=B0=8F=E6=8E=A7=E5=88=B6=E5=8A=9F=E8=83=BD?= =?UTF-8?q?:-D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocPage.cpp | 10 +- ofdEditor/model/Doc/DocPage.h | 15 +- ofdEditor/model/Doc/DocPassage.cpp | 95 +- ofdEditor/model/Doc/DocPassage.h | 28 + ofdEditor/model/Widget/PageDialog.cpp | 413 ++++++ ofdEditor/model/Widget/PageDialog.h | 67 + ofdEditor/model/Widget/PageDialog.ui | 1178 +++++++++++++++++ ofdEditor/model/model.pro | 9 +- .../start/ActionConnector/ActionConnector.cpp | 9 +- .../start/ActionConnector/ActionConnector.h | 1 + ofdEditor/start/ui/PassageMainWindow.cpp | 30 +- ofdEditor/start/ui/PassageMainWindow.h | 2 + 12 files changed, 1838 insertions(+), 19 deletions(-) create mode 100644 ofdEditor/model/Widget/PageDialog.cpp create mode 100644 ofdEditor/model/Widget/PageDialog.h create mode 100644 ofdEditor/model/Widget/PageDialog.ui diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index 4b8bfc0..b0785fe 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -28,10 +28,11 @@ // #include "DataTypes/page/CT_PageArea.h" // 页面大小 + DocPage::DocPage(QWidget *parent) - :QGraphicsView(parent) + : QGraphicsView(parent) { - this->setSize(210,297); // 默认A4纸张大小 + //this->setSize(210,297); // 默认A4纸张大小 this->scaleFactor = 1.0; this->init(); @@ -525,6 +526,11 @@ void DocPage::init() // this->setBackgroundRole(QPalette::Dark); this->insertBlockInfo = NULL; this->activeBlock = NULL; + + has_working_area = false; + working_area_width = this->size().width(); + working_area_height = this->size().height(); + working_area_x = working_area_y = 0; } void DocPage::addImage() diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index 2b219e9..0cc9d00 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -28,10 +28,17 @@ class MODELSHARED_EXPORT DocPage { Q_OBJECT public: + //Temporarily put here + bool has_working_area; + double working_area_width; + double working_area_height; + double working_area_x; + double working_area_y; + + enum Layer{Body,Foreground,Background}; // 分为三层 enum BlockFlag{none,draw,drawMove,blockMove, blockResize}; // 插入时的绘制状态 enum BlockType{text,image,table}; // 插入时的类型 - explicit DocPage(QWidget * parent = 0); DocPage(double width, double height, double scaleFactor,QWidget * parent = 0); @@ -49,7 +56,7 @@ public: DocLayer* getBackgroundLayer(); // 获得背景层 //Pan - void addImage(); + void addImage(); //添加图片 public slots: void setSize(double width, double height); // 设置页面大小 @@ -97,11 +104,13 @@ private: BlockFlag newBlockFlag; // 是否画块 DocBlock * activeBlock; // 正在活跃的那个DocBlock + signals: // 信号 void signals_insertTextBlock(DocTextBlock* textBlock ); // 插入文本框信号 void signals_removeTextBlock(DocTextBlock* textBlock ); // 移除文本框信号 - + void has_focused_page(); + void has_no_focused_page(); }; diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index 66e39e5..ec94c41 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -3,7 +3,7 @@ #include "DocPage.h" #include "DataTypes/document/CT_DocInfo.h" #include "DataTypes/document/ct_commondata.h" - +#include "../Widget/PageDialog.h" #include #include #include @@ -11,6 +11,7 @@ #include #include #include +#include "../Tool/UnitTool.h" /** * @Author Chaoqun @@ -29,7 +30,7 @@ DocPassage::DocPassage(QWidget *parent) // this->addPage(new DocPage()); // 添加一个空白页面 setAttribute(Qt::WA_DeleteOnClose); - + qDebug() << "DocPassage Constructor Finished."; } /** @@ -96,6 +97,15 @@ void DocPassage::addPage(DocPage *page) } // 先添加到 vector + page->setSize(default_width, default_height); + qDebug() << "!!Page width in pixel = " << page->size().width() + << "!!Page height in pixel = " << page->size().height(); + page->has_working_area = default_using_working_area; + page->working_area_height = default_working_height; + page->working_area_width = default_working_width; + page->working_area_x = default_working_x; + page->working_area_y = default_working_y; + this->pages.append(page); // 添加到ScrollArea this->adjustWidgetSize(); // 调整大小 @@ -105,7 +115,7 @@ void DocPassage::addPage(DocPage *page) page->setPassage(this); // 设置页所属的文章 - qDebug() << "You have added an new page"; +// qDebug() << "You have added an new page"; } @@ -295,7 +305,7 @@ void DocPassage::resetDocId() void DocPassage::resizeEvent(QResizeEvent *event) { this->adjustWidgetSize(); // 调整整体大小 - qDebug() << "DocPassage::resizeEvent Runs"; +// qDebug() << "DocPassage::resizeEvent Runs"; } /** @@ -340,6 +350,15 @@ void DocPassage::init() adjustScrollBar(this->horizontalScrollBar(), 1); adjustScrollBar(this->verticalScrollBar(),1); + this->page_dialog = new PageDialog(NULL, this); +// qDebug() << "Finished Initializing DocPassage..."; + default_width = 210; //默认宽度 + default_height = 297; //默认高度 + default_using_working_area = false; + default_working_width = 210; + default_working_height = 297; + default_working_x = 0; + default_working_y = 0; } /** @@ -415,7 +434,71 @@ void DocPassage::adjustWidgetSize() adjustScrollBar(this->verticalScrollBar(), this->scaleFactor); - qDebug() <<"widget's Size"<widget->size(); - qDebug() << "ScrollArea's Size" << this->size(); +// qDebug() <<"widget's Size"<widget->size(); +// qDebug() << "ScrollArea's Size" << this->size(); + +} + +void DocPassage::setDefaultPageSize(double default_width, double default_height) +{ + this->default_width = default_width; + this->default_height = default_height; +} +void DocPassage::activatePageDialog() +{ + DocPage * page = qobject_cast(focusWidget()); +// qDebug() << "page width in pixel = " << page->size().width() +// << "page height in pixel = " << page->size().height(); + if (page) + { + page_dialog->updateInformation(page, + default_width, + default_height, + default_using_working_area, + default_working_width, + default_working_height, + default_working_x, + default_working_y); + this->page_dialog->exec(); + } +} + +void DocPassage::updatePageSizeInformation(QVector &changed_pages, + double current_width, + double current_height, + bool current_using_working_area, + double current_working_width, + double current_working_height, + double current_working_x, + double current_working_y, + double default_height, + double default_width, + bool using_working_area, + double default_working_width, + double default_working_height, + double default_working_x, + double default_working_y) +{ + DocPage * cur_page; + for (int i = 0; i < changed_pages.size(); i++) { + cur_page = pages[changed_pages[i] - 1]; + cur_page->setSize(current_width, current_height); + cur_page->has_working_area = current_using_working_area; + cur_page->working_area_width = current_working_width; + cur_page->working_area_height = current_working_height; + cur_page->working_area_x = current_working_x; + cur_page->working_area_y = current_working_y; + } + this->default_width = default_width; + this->default_height = default_height; + this->default_using_working_area = using_working_area; + this->default_working_width = default_working_width; + this->default_working_height = default_working_height; + this->default_working_x = default_working_x; + this->default_working_y = default_working_y; +// qDebug() << "Current Page Width = " +// << UnitTool::pixelToMM(qobject_cast(focusWidget())->size().width()) +// << "Current Page Height = " +// << UnitTool::pixelToMM(qobject_cast(focusWidget())->size().height()); } diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index 2246bd1..855c293 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -23,6 +23,7 @@ class CT_CommonData; class DocBlock; class DocTextBlock; class DocImageBlock; +class PageDialog; /** * @Author Chaoqun @@ -74,6 +75,25 @@ public slots: void adjustWidgetSize(); // 根据页数来自动调整widget大小 + void setDefaultPageSize(double default_width, double default_height); //设置默认的页面尺寸 + + void activatePageDialog(); + + void updatePageSizeInformation(QVector & changed_pages, + double current_width, + double current_height, + bool current_using_working_area, + double current_working_width, + double current_working_height, + double current_working_x, + double current_working_y, + double default_height, + double default_width, + bool using_working_area, + double default_working_width, + double default_working_height, + double default_working_x, + double default_working_y); protected: void resizeEvent(QResizeEvent* event); void closeEvent(QCloseEvent *event); // 继承,关闭前提示保存 @@ -109,6 +129,14 @@ private: double factor); // 调整滑动条 void adjustScrollBarRange(); //调整滑动条范围 + PageDialog * page_dialog; //用于调整页面格式的对话框 + double default_width; //默认宽度 + double default_height; //默认高度 + bool default_using_working_area; + double default_working_width; + double default_working_height; + double default_working_x; + double default_working_y; signals: void signals_insertTextBlock(DocTextBlock* textBlock); // 用来转发信号 diff --git a/ofdEditor/model/Widget/PageDialog.cpp b/ofdEditor/model/Widget/PageDialog.cpp new file mode 100644 index 0000000..805e7cf --- /dev/null +++ b/ofdEditor/model/Widget/PageDialog.cpp @@ -0,0 +1,413 @@ +#include "PageDialog.h" +#include "ui_PageDialog.h" +#include "../Doc/DocPassage.h" +#include "../Doc/DocPage.h" +#include +#include "../Tool/UnitTool.h" + +int toNearestInt(double n) +{ + return n + 0.5; +} + +PageDialog::PageDialog(QWidget *parent, DocPassage * passage) : + QDialog(parent), + ui(new Ui::PageDialog), + changed_page_numbers() +{ + ui->setupUi(this); + this->passage = passage; + + //成员初始化 + current_page = NULL; + //组件初始化 + if (current_page) + { + ui->CurrentPageSizeWidth->setValue(current_page->size().width()); + ui->CurrentPageSizeHeight->setValue(current_page->size().height()); + } + ui->CurrentPageSizeWidth->setRange(0.0, 10000.0); + ui->CurrentPageSizeHeight->setRange(0.0, 10000.0); + ui->DefaultPageSizeWidth->setRange(0.0, 10000.0); + ui->DefaultPageSizeHeight->setRange(0.0, 10000.0); + ui->CurrentWorkingAreaWidth->setRange(0.0, 10000.0); + ui->CurrentWorkingAreaHeight->setRange(0.0, 10000.0); + ui->DefaultWorkingAreaWidth->setRange(0.0, 10000.0); + ui->DefaultWorkingAreaHeight->setRange(0.0, 10000.0); + ui->CurrentWorkingAreaX->setRange(0.0, 10000.0); + ui->CurrentWorkingAreaY->setRange(0.0, 10000.0); + ui->DefaultWorkingAreaX->setRange(0.0, 10000.0); + ui->DefaultWorkingAreaY->setRange(0.0, 10000.0); + + ui->CurrentSetWorkingAreaChecked->setChecked(false); + ui->CurrentWorkingAreaWidth->setEnabled(false); + ui->CurrentWorkingAreaHeight->setEnabled(false); + ui->CurrentWorkingAreaX->setEnabled(false); + ui->CurrentWorkingAreaY->setEnabled(false); + ui->CurrentWorkingAreaWidth->setValue(ui->CurrentPageSizeWidth->value()); + ui->CurrentWorkingAreaHeight->setValue(ui->CurrentPageSizeHeight->value()); + ui->CurrentWorkingAreaX->setValue(0.0); + ui->CurrentWorkingAreaY->setValue(0.0); + + ui->DefaultSetWorkingAreaChecked->setChecked(false); + ui->DefaultWorkingAreaWidth->setEnabled(false); + ui->DefaultWorkingAreaHeight->setEnabled(false); + ui->DefaultWorkingAreaX->setEnabled(false); + ui->DefaultWorkingAreaY->setEnabled(false); + ui->DefaultWorkingAreaWidth->setValue(ui->DefaultPageSizeWidth->value()); + ui->DefaultWorkingAreaHeight->setValue(ui->DefaultPageSizeHeight->value()); + ui->DefaultWorkingAreaX->setValue(0.0); + ui->DefaultWorkingAreaY->setValue(0.0); + + ui->CurrentSelectPageSize->setEditable(true); + ui->DefaultSelectPageSize->setEditable(true); + + ui->CurrentPageCheckBox->setChecked(true); + ui->AllPagesCheckBox->setChecked(false); + ui->PageRangeCheckBox->setChecked(false); + ui->SpecificPageCheckBox->setChecked(false); + + ui->PageRangeLowerBound->setEnabled(false); + ui->PageRangeUpperBound->setEnabled(false); + ui->PageRangeLowerBound->setValue(1); + ui->PageRangeUpperBound->setValue(passage->getPages().size()); + ui->SpecificPage->setEnabled(false); + //创建信号槽 + this->connect(ui->PageRangeCheckBox, + SIGNAL(clicked(bool)), + this, + SLOT(on_PageRangeCheckBox_toggled(bool))); + this->connect(ui->CurrentSelectPageSize, + SIGNAL(currentIndexChanged(QString)), + this, + SLOT(on_CurrentSelectPageSize_currentIndexChanged(QString))); + this->connect(ui->DefaultSelectPageSize, + SIGNAL(currentIndexChanged(QString)), + this, + SLOT(on_DefaultSelectPageSize_currentIndexChanged(QString))); + this->connect(ui->SpecificPageCheckBox, + SIGNAL(clicked(bool)), + this, + SLOT(on_SpecificPageCheckBox_clicked(bool))); + this->connect(ui->CurrentSetWorkingAreaChecked, + SIGNAL(clicked(bool)), + this, + SLOT(on_CurrentSetWorkingAreaChecked_clicked(bool))); + this->connect(ui->DefaultSetWorkingAreaChecked, + SIGNAL(clicked(bool)), + this, + SLOT(on_DefaultSetWorkingAreaChecked_clicked(bool))); + this->connect(ui->CurrentPageSizeHeight, + SIGNAL(editingFinished()), + this, + SLOT(on_CurrentPageSize_valueChanged())); + this->connect(ui->CurrentPageSizeWidth, + SIGNAL(editingFinished()), + this, + SLOT(on_CurrentPageSize_valueChanged())); + this->connect(ui->OkAndCancel, + SIGNAL(accepted()), + this, + SLOT(accept())); + this->connect(ui->OkAndCancel, + SIGNAL(rejected()), + this, + SLOT(reject())); + this->connect(ui->CurrentPageCheckBox, + SIGNAL(toggled(bool)), + this, + SLOT(on_CurrentPageCheckBox_toggled(bool))); + this->connect(ui->AllPagesCheckBox, + SIGNAL(toggled(bool)), + this, + SLOT(on_AllPagesCheckBox_toggled(bool))); + this->connect(ui->PageRangeLowerBound, + SIGNAL(valueChanged(int)), + this, + SLOT(page_range_range_changed())); + this->connect(ui->PageRangeUpperBound, + SIGNAL(valueChanged(int)), + this, + SLOT(page_range_range_changed())); + this->connect(ui->PageRangeLowerBound, + SIGNAL(valueChanged(int)), + this, + SLOT(changed_page_range_changed())); + this->connect(ui->PageRangeUpperBound, + SIGNAL(valueChanged(int)), + this, + SLOT(changed_page_range_changed())); + + this->connect(this, + SIGNAL(accepted()), + this, + SLOT(emitInformation())); +} + +PageDialog::~PageDialog() +{ + delete ui; +} + +void PageDialog::updateInformation(DocPage *current_page, + double default_width, + double default_height, + bool using_working_area, + double default_working_width, + double default_working_height, + double default_working_x, + double default_working_y) +{ + this->current_page = current_page; + if (current_page) + { +// qDebug() << "Current_page width in pixel = " << current_page->size().width(); +// qDebug() << "Current_page height in pixel = " << current_page->size().height(); + ui->CurrentPageSizeWidth->setValue(toNearestInt(UnitTool::pixelToMM(current_page->size().width()))); + ui->CurrentPageSizeHeight->setValue(toNearestInt(UnitTool::pixelToMM(current_page->size().height()))); + //Working area to be implemented!!!! + ui->CurrentWorkingAreaWidth->setValue(toNearestInt(current_page->working_area_width)); + ui->CurrentWorkingAreaHeight->setValue(toNearestInt(current_page->working_area_height)); + ui->CurrentWorkingAreaX->setValue(toNearestInt(current_page->working_area_x)); + ui->CurrentWorkingAreaY->setValue(toNearestInt(current_page->working_area_y)); + + ui->DefaultPageSizeWidth->setValue(toNearestInt(default_height)); + ui->DefaultPageSizeHeight->setValue(toNearestInt(default_width)); + //Working area to be implemented!!!! + ui->DefaultSetWorkingAreaChecked->setChecked(using_working_area); + ui->DefaultWorkingAreaWidth->setValue(toNearestInt(default_working_width)); + ui->DefaultWorkingAreaHeight->setValue(toNearestInt(default_working_height)); + ui->DefaultWorkingAreaX->setValue(toNearestInt(default_working_x)); + ui->DefaultWorkingAreaY->setValue(toNearestInt(default_working_y)); + + } +} + + + +void PageDialog::on_CurrentSelectPageSize_currentIndexChanged(const QString &arg1) +{ + if (arg1 == tr("A4")) + { + ui->CurrentPageSizeWidth->setValue(210); + ui->CurrentPageSizeHeight->setValue(297); + } else if (arg1 == tr("A3")) + { + ui->CurrentPageSizeWidth->setValue(297); + ui->CurrentPageSizeHeight->setValue(420); + } else if (arg1 == tr("A5")) + { + ui->CurrentPageSizeWidth->setValue(148); + ui->CurrentPageSizeHeight->setValue(210); + } else if (arg1 == tr("Letter")) + { + ui->CurrentPageSizeWidth->setValue(216); + ui->CurrentPageSizeHeight->setValue(279); + } else if (arg1 == tr("16K")) + { + ui->CurrentPageSizeWidth->setValue(184); + ui->CurrentPageSizeHeight->setValue(260); + } else if (arg1 == tr("32K")) + { + ui->CurrentPageSizeWidth->setValue(130); + ui->CurrentPageSizeHeight->setValue(184); + } +} + +void PageDialog::on_DefaultSelectPageSize_currentIndexChanged(const QString &arg1) +{ + if (arg1 == tr("A4")) + { + ui->DefaultPageSizeWidth->setValue(210); + ui->DefaultPageSizeHeight->setValue(297); + } else if (arg1 == tr("A3")) + { + ui->DefaultPageSizeWidth->setValue(297); + ui->DefaultPageSizeHeight->setValue(420); + } else if (arg1 == tr("A5")) + { + ui->DefaultPageSizeWidth->setValue(148); + ui->DefaultPageSizeHeight->setValue(210); + } else if (arg1 == tr("Letter")) + { + ui->DefaultPageSizeWidth->setValue(216); + ui->DefaultPageSizeHeight->setValue(279); + } else if (arg1 == tr("16K")) + { + ui->DefaultPageSizeWidth->setValue(184); + ui->DefaultPageSizeHeight->setValue(260); + } else if (arg1 == tr("32K")) + { + ui->DefaultPageSizeWidth->setValue(130); + ui->DefaultPageSizeHeight->setValue(184); + } +} + +void PageDialog::on_SpecificPageCheckBox_clicked(bool checked) +{ + if (checked) + { + ui->SpecificPage->setEnabled(true); +// !!!!!!!!!!!!!!!!!!!!!! + } + else + { + ui->SpecificPage->setText(""); + ui->SpecificPage->setEnabled(false); + } +} + +void PageDialog::on_CurrentSetWorkingAreaChecked_clicked(bool checked) +{ + if (checked) + { + ui->CurrentWorkingAreaWidth->setEnabled(true); + ui->CurrentWorkingAreaHeight->setEnabled(true); + ui->CurrentWorkingAreaX->setEnabled(true); + ui->CurrentWorkingAreaY->setEnabled(true); + } + else + { + ui->CurrentWorkingAreaWidth->setEnabled(false); + ui->CurrentWorkingAreaHeight->setEnabled(false); + ui->CurrentWorkingAreaX->setEnabled(false); + ui->CurrentWorkingAreaY->setEnabled(false); + ui->CurrentWorkingAreaWidth->setValue(ui->CurrentPageSizeWidth->value()); + ui->CurrentWorkingAreaHeight->setValue(ui->CurrentPageSizeHeight->value()); + ui->CurrentWorkingAreaX->setValue(0.0); + ui->CurrentWorkingAreaY->setValue(0.0); + } +} + +void PageDialog::on_DefaultSetWorkingAreaChecked_clicked(bool checked) +{ + if (checked) + { + ui->DefaultWorkingAreaWidth->setEnabled(true); + ui->DefaultWorkingAreaHeight->setEnabled(true); + ui->CurrentWorkingAreaX->setEnabled(true); + ui->CurrentWorkingAreaY->setEnabled(true); + } + else + { + ui->DefaultWorkingAreaWidth->setEnabled(false); + ui->DefaultWorkingAreaHeight->setEnabled(false); + ui->DefaultWorkingAreaX->setEnabled(false); + ui->DefaultWorkingAreaY->setEnabled(false); + ui->DefaultWorkingAreaWidth->setValue(ui->DefaultPageSizeWidth->value()); + ui->DefaultWorkingAreaHeight->setValue(ui->DefaultPageSizeHeight->value()); + ui->DefaultWorkingAreaX->setValue(0.0); + ui->DefaultWorkingAreaY->setValue(0.0); + } +} + +void PageDialog::on_CurrentPageSize_valueChanged() +{ + qDebug() << "Called"; + ui->CurrentSelectPageSize->setCurrentIndex(ui->CurrentSelectPageSize->findText(tr("Customized"))); +} + + + + +void PageDialog::on_PageRangeCheckBox_toggled(bool checked) +{ + if (checked) + { + ui->PageRangeLowerBound->setEnabled(true); + ui->PageRangeUpperBound->setEnabled(true); + int i; + if (current_page) + { + for (i = 0; i < passage->getPages().size(); i++) + if (passage->getPages()[i] == current_page) + break; + } + else i = 1; + ui->PageRangeLowerBound->setValue(i); + ui->PageRangeUpperBound->setValue(passage->getPages().size()); + ui->PageRangeLowerBound->setRange(1, ui->PageRangeUpperBound->value()); + ui->PageRangeUpperBound->setRange(ui->PageRangeLowerBound->value(), passage->getPages().size()); + for (int j = i; j <= passage->getPages().size(); j++) + changed_page_numbers.push_back(j); + } + else + { + ui->PageRangeLowerBound->setEnabled(false); + ui->PageRangeUpperBound->setEnabled(false); + + } +} + +void PageDialog::on_SpecificPageCheckBox_toggled(bool checked) +{ + if (checked) + { + ui->SpecificPage->setEnabled(true); + } + else + { + ui->SpecificPage->setEnabled(false); + } +} + +void PageDialog::on_CurrentPageCheckBox_toggled(bool checked) +{ + if (checked) + { + changed_page_numbers.clear(); + int i; + if (current_page) + { + for (i = 0; i < passage->getPages().size(); i++) + if (passage->getPages()[i] == current_page) + break; + } + else i = 1; + changed_page_numbers.push_back(i); + } +} + +void PageDialog::on_AllPagesCheckBox_toggled(bool checked) +{ + if (checked) + { + changed_page_numbers.clear(); + int i; + for (i = 0; i < passage->getPages().size(); i++) + changed_page_numbers.push_back(i + 1); + } +} + +void PageDialog::page_range_range_changed() +{ + ui->PageRangeLowerBound->setRange(1, ui->PageRangeUpperBound->value()); + ui->PageRangeUpperBound->setRange(ui->PageRangeLowerBound->value(), passage->getPages().size()); +} + +void PageDialog::changed_page_range_changed() +{ + changed_page_numbers.clear(); + for (int j = ui->PageRangeLowerBound->value(); j <= ui->PageRangeUpperBound->value(); j++) + changed_page_numbers.push_back(j); +} + +void PageDialog::emitInformation() +{ + passage->updatePageSizeInformation(changed_page_numbers, + ui->CurrentPageSizeWidth->value(), + ui->CurrentPageSizeHeight->value(), + ui->CurrentSetWorkingAreaChecked->isChecked(), + ui->CurrentWorkingAreaWidth->value(), + ui->CurrentWorkingAreaHeight->value(), + ui->CurrentWorkingAreaX->value(), + ui->CurrentWorkingAreaY->value(), + ui->DefaultPageSizeWidth->value(), + ui->DefaultPageSizeHeight->value(), + ui->DefaultSetWorkingAreaChecked->isChecked(), + ui->DefaultWorkingAreaWidth->value(), + ui->DefaultWorkingAreaHeight->value(), + ui->DefaultWorkingAreaX->value(), + ui->DefaultWorkingAreaY->value()); +} + diff --git a/ofdEditor/model/Widget/PageDialog.h b/ofdEditor/model/Widget/PageDialog.h new file mode 100644 index 0000000..8bf0e07 --- /dev/null +++ b/ofdEditor/model/Widget/PageDialog.h @@ -0,0 +1,67 @@ +#ifndef PAGEDIALOG_H +#define PAGEDIALOG_H + +#include +#include + +class DocPassage; +class DocPage; + + +namespace Ui { +class PageDialog; +} + +class PageDialog : public QDialog +{ + Q_OBJECT + +public: + explicit PageDialog(QWidget *parent = 0, DocPassage* passage = NULL); + ~PageDialog(); + void updateInformation(DocPage * current_page, + double default_width, + double default_height, + bool using_working_area, + double default_working_width, + double default_working_height, + double default_working_x, + double default_working_y); + +private slots: + + void on_CurrentSelectPageSize_currentIndexChanged(const QString &arg1); + + void on_DefaultSelectPageSize_currentIndexChanged(const QString &arg1); + + void on_SpecificPageCheckBox_clicked(bool checked); + + void on_CurrentSetWorkingAreaChecked_clicked(bool checked); + + void on_DefaultSetWorkingAreaChecked_clicked(bool checked); + + void on_CurrentPageSize_valueChanged(); + + + void on_PageRangeCheckBox_toggled(bool checked); + + void on_SpecificPageCheckBox_toggled(bool checked); + + + void on_CurrentPageCheckBox_toggled(bool checked); + + void on_AllPagesCheckBox_toggled(bool checked); + + void page_range_range_changed(); + + void changed_page_range_changed(); + + void emitInformation(); +private: + Ui::PageDialog *ui; + DocPassage *passage; + QVector changed_page_numbers; + DocPage * current_page; +}; + +#endif // PAGEDIALOG_H diff --git a/ofdEditor/model/Widget/PageDialog.ui b/ofdEditor/model/Widget/PageDialog.ui new file mode 100644 index 0000000..cd37c45 --- /dev/null +++ b/ofdEditor/model/Widget/PageDialog.ui @@ -0,0 +1,1178 @@ + + + PageDialog + + + + 0 + 0 + 433 + 490 + + + + Dialog + + + + + 0 + 0 + 441 + 441 + + + + 1 + + + + 当前页面 + + + + + 230 + 50 + 41 + 21 + + + + + 宋体 + 11 + + + + mm + + + + + + 155 + 160 + 62 + 22 + + + + + + + 114 + 299 + 89 + 16 + + + + 所有页 + + + AppliedRange + + + + + + 155 + 200 + 62 + 22 + + + + + + + 15 + 240 + 381 + 20 + + + + Qt::Horizontal + + + + + + 295 + 160 + 62 + 22 + + + + + + + 96 + 9 + 311 + 20 + + + + Qt::Horizontal + + + + + + 135 + 160 + 21 + 21 + + + + + 宋体 + 11 + + + + + + + + + + 282 + 49 + 21 + 21 + + + + + 宋体 + 11 + + + + + + + + + + 263 + 201 + 31 + 21 + + + + + 宋体 + 11 + + + + 垂直 + + + + + + 15 + 163 + 91 + 21 + + + + + 宋体 + 11 + + + + 工作区域尺寸 + + + + + + 114 + 359 + 89 + 16 + + + + 特定页数 + + + AppliedRange + + + + + + 14 + 269 + 71 + 21 + + + + + 宋体 + 11 + + + + 应用于 + + + + + + 15 + 133 + 101 + 16 + + + + 设置工作区域 + + + + + + 162 + 49 + 62 + 22 + + + + + + + 123 + 201 + 31 + 21 + + + + + 宋体 + 11 + + + + 水平 + + + + + + 223 + 161 + 41 + 21 + + + + + 宋体 + 11 + + + + mm + + + + + + 363 + 161 + 41 + 21 + + + + + 宋体 + 11 + + + + mm + + + + + + 22 + 49 + 71 + 21 + + + + + 宋体 + 11 + + + + 页面尺寸 + + + + + + 223 + 201 + 41 + 21 + + + + + 宋体 + 11 + + + + mm + + + + + + 15 + 203 + 91 + 21 + + + + + 宋体 + 11 + + + + 工作区域位置 + + + + + + 363 + 201 + 41 + 21 + + + + + 宋体 + 11 + + + + mm + + + + + + 295 + 200 + 62 + 22 + + + + + + + 302 + 49 + 62 + 22 + + + + + + + 142 + 49 + 21 + 21 + + + + + 宋体 + 11 + + + + + + + + + + 370 + 50 + 41 + 21 + + + + + 宋体 + 11 + + + + mm + + + + + + 254 + 359 + 131 + 20 + + + + + + + 21 + 8 + 71 + 21 + + + + + 宋体 + 12 + + + + 页面设置 + + + + + + 275 + 160 + 21 + 21 + + + + + 宋体 + 11 + + + + + + + + + + 114 + 269 + 89 + 16 + + + + 当前页 + + + AppliedRange + + + + + + 114 + 329 + 89 + 16 + + + + 页面范围 + + + AppliedRange + + + + + + 244 + 329 + 42 + 22 + + + + + + + 225 + 331 + 21 + 16 + + + + + Agency FB + 11 + + + + + + + + + + 295 + 331 + 21 + 16 + + + + + Agency FB + 11 + + + + + + + + + + 314 + 329 + 42 + 22 + + + + + + + 365 + 330 + 21 + 16 + + + + + Agency FB + 11 + + + + + + + + + + 220 + 360 + 31 + 16 + + + + + Agency FB + 11 + + + + 页码 + + + + + + 21 + 91 + 101 + 21 + + + + + 宋体 + 11 + + + + 选择尺寸 + + + + + + 140 + 90 + 121 + 22 + + + + + A4 + + + + + A3 + + + + + A5 + + + + + Letter + + + + + 16K + + + + + 32K + + + + + Customized + + + + + + + 默认页面 + + + + + 24 + 29 + 101 + 21 + + + + + 宋体 + 12 + + + + 默认页面设置 + + + + + + 128 + 30 + 281 + 20 + + + + Qt::Horizontal + + + + + + 162 + 79 + 62 + 22 + + + + + + + 302 + 199 + 62 + 22 + + + + + + + 22 + 79 + 71 + 21 + + + + + 宋体 + 11 + + + + 页面尺寸 + + + + + + 142 + 199 + 21 + 21 + + + + + 宋体 + 11 + + + + + + + + + + 370 + 80 + 41 + 21 + + + + + 宋体 + 11 + + + + mm + + + + + + 22 + 202 + 91 + 21 + + + + + 宋体 + 11 + + + + 工作区域尺寸 + + + + + + 162 + 199 + 62 + 22 + + + + + + + 270 + 240 + 31 + 21 + + + + + 宋体 + 11 + + + + 垂直 + + + + + + 370 + 240 + 41 + 21 + + + + + 宋体 + 11 + + + + mm + + + + + + 370 + 200 + 41 + 21 + + + + + 宋体 + 11 + + + + mm + + + + + + 230 + 80 + 41 + 21 + + + + + 宋体 + 11 + + + + mm + + + + + + 22 + 172 + 101 + 16 + + + + 设置工作区域 + + + + + + 230 + 200 + 41 + 21 + + + + + 宋体 + 11 + + + + mm + + + + + + 282 + 199 + 21 + 21 + + + + + 宋体 + 11 + + + + + + + + + + 142 + 79 + 21 + 21 + + + + + 宋体 + 11 + + + + + + + + + + 282 + 79 + 21 + 21 + + + + + 宋体 + 11 + + + + + + + + + + 302 + 79 + 62 + 22 + + + + + + + 22 + 242 + 91 + 21 + + + + + 宋体 + 11 + + + + 工作区域位置 + + + + + + 162 + 239 + 62 + 22 + + + + + + + 130 + 240 + 31 + 21 + + + + + 宋体 + 11 + + + + 水平 + + + + + + 302 + 239 + 62 + 22 + + + + + + + 230 + 240 + 41 + 21 + + + + + 宋体 + 11 + + + + mm + + + + + + 22 + 122 + 101 + 21 + + + + + 宋体 + 11 + + + + 选择尺寸 + + + + + + 141 + 121 + 121 + 22 + + + + + A4 + + + + + A3 + + + + + A5 + + + + + Letter + + + + + 16K + + + + + 32K + + + + + Customized + + + + + + + + + 70 + 450 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + false + + + + + + + + + true + + + + diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index 5cdc451..19a8a52 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -53,7 +53,8 @@ SOURCES += model.cpp \ Widget/DocInfoDialog.cpp \ Command/SetTextBlodCmd.cpp \ Doc/DocImageBlock.cpp \ - Widget/imagepropertiesdialog.cpp + Widget/imagepropertiesdialog.cpp \ + Widget/PageDialog.cpp HEADERS += model.h\ model_global.h \ @@ -86,7 +87,8 @@ HEADERS += model.h\ Widget/DocInfoDialog.h \ Command/SetTextBlodCmd.h \ Doc/DocImageBlock.h \ - Widget/imagepropertiesdialog.h + Widget/imagepropertiesdialog.h \ + Widget/PageDialog.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 @@ -115,4 +117,5 @@ FORMS += \ Widget/ParagraphFormatDialog.ui \ Widget/FontSettingDialog.ui \ Widget/DocInfoDialog.ui \ - Widget/imagepropertiesdialog.ui + Widget/imagepropertiesdialog.ui \ + Widget/PageDialog.ui diff --git a/ofdEditor/start/ActionConnector/ActionConnector.cpp b/ofdEditor/start/ActionConnector/ActionConnector.cpp index e9712e3..850f281 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.cpp +++ b/ofdEditor/start/ActionConnector/ActionConnector.cpp @@ -34,7 +34,7 @@ void ActionConnector::showAttribute() CT_DocInfo * docInfo = this->passage->getDocInfo(); DocInfoDialog* dialog = new DocInfoDialog(docInfo,this->mainWindow); // 设置窗口 dialog->exec(); // 运行 - qDebug() << "show Attribute"; +// qDebug() << "show Attribute"; } @@ -99,7 +99,7 @@ void ActionConnector::addNewBlock(InsertBlockInfo& blockInfo) else if (blockInfo.type == DocPage::image) { page->setInsertBlockType(blockInfo); // 设置插入文本框信息 - qDebug() << "!!!"; +// qDebug() << "!!!"; page->addImage(); } } @@ -177,6 +177,11 @@ void ActionConnector::updateActivePassage(QMdiSubWindow *window) } } +DocPage *ActionConnector::getActivePage() +{ + return qobject_cast(this->passage->focusWidget()); +} + void ActionConnector::init() { this->defaultLayer = DocPage::Body; diff --git a/ofdEditor/start/ActionConnector/ActionConnector.h b/ofdEditor/start/ActionConnector/ActionConnector.h index 878056b..4cb530d 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.h +++ b/ofdEditor/start/ActionConnector/ActionConnector.h @@ -41,6 +41,7 @@ public slots: void updateActivePassage(QMdiSubWindow * window ); // 更新当前操作的文章 + DocPage *getActivePage(); //获取当前操作的页面 private: PassageMainWindow * mainWindow; // 主窗口 DocPassage * passage; // 当前活跃文档 diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 0c17cf8..1378185 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -52,10 +52,13 @@ DocPassage *PassageMainWindow::createMdiChild() qDebug()<<"execute"; DocPassage * child = new DocPassage(this); +// qDebug() << "Creating new Passage Completed."; child->addPage(new DocPage()); // 添加一个空白页 - +// qDebug() << "Creating new Page Completed."; this->addDocPassage(child); // 加入到本视区 - +// qDebug() << "Passage has " << child->getPages().size() << " pages."; +// qDebug() << "Page width = " << child->getPages()[0]->size().width() +// << " Page Height = " <getPages()[0]->size().height(); return child; } @@ -84,6 +87,7 @@ void PassageMainWindow::init() this->setMinimumSize(960,720); this->setBackgroundRole(QPalette::Text); + } /** @@ -163,8 +167,12 @@ void PassageMainWindow::initAction() this->insertTableAction->setStatusTip(tr("Insert a table")); this->insertTableAction->setIcon(QIcon(":/icons/source/icons/insertTable.png")); + this->pageFormat = new QAction(tr("Page Format"), NULL); // 页面格式 + this->pageFormat->setStatusTip(tr("Set the page format")); + //this->textFormat->setIcon(QIcon()); + this->textFormat = new QAction(tr("Text Format"),NULL); // 文字格式 - this->textFormat->setStatusTip(tr("Set the selected texts' Format")); + this->textFormat->setStatusTip(tr("Set the selected texts' format")); this->textFormat->setIcon(QIcon(":/icons/source/icons/TextFormat.png")); this->paragraphFormat = new QAction(tr("Paragraph Format"),NULL); // 段落格式 @@ -213,6 +221,7 @@ void PassageMainWindow::initAction() this->formatMenu->addAction(this->paragraphFormat); this->formatMenu->addAction(this->imageFormat); this->formatMenu->addAction(this->tableFormat); + this->formatMenu->addAction(this->pageFormat); this->insertMenu->addAction(this->insertNewPageAction); this->insertMenu->addAction(this->insertTextBlockAction); @@ -289,6 +298,8 @@ void PassageMainWindow::connectAction() connect(this->textFormat,SIGNAL(triggered(bool)), this,SLOT(fontDialog())); // 修改字体 + connect(this->pageFormat, SIGNAL(triggered(bool)), + this, SLOT(pageDialog())); connect(this->paragraphFormat,SIGNAL(triggered(bool)), this,SLOT(paragraphDialog())); // 修改段落 @@ -386,6 +397,19 @@ void PassageMainWindow::imageDialog() this->imageBlock->setImageProperties(); } +void PassageMainWindow::pageDialog() +{ + DocPassage * passage = activeMdiChild(); + if (passage) + { + passage->activatePageDialog(); + } + else + { + qDebug() << "No active DocPassage."; + } +} + /** * @Author Chaoqun * @brief 接受当前处理的文字块的更新 diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index 63c032e..be5d0ec 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -97,11 +97,13 @@ private: DocImageBlock *imageBlock; //图片块 + private slots: void openFile(); // 打开新文件 void fontDialog(); // 打开字体框 void paragraphDialog(); // 打开段落框 void imageDialog(); // 打开图片框 + void pageDialog(); // 打开页面框 void acceptTextBlock(DocTextBlock* textBlock); // 接受当前处理的文字块的更新 void acceptTextBlockFormat(QTextBlockFormat& blockFormat); // 接受当前处理的块格式 -- Gitee From b62e1be8aa24f7c5bb96cfbf76484af11c8e5255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Tue, 27 Jun 2017 10:19:21 +0800 Subject: [PATCH 11/83] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 8e3f71443b3c07ba0e5648d4a777717b2d342c7d Author: 江超群 Date: Tue Jun 27 10:08:21 2017 +0800 无病呻吟 commit 594d84c298cc120943f3efe2e98a0b636f709e8a Author: 江超群 Date: Mon Jun 26 22:35:35 2017 +0800 保存文件 commit 6c2642998b55d02adeb434b4c69dc66afe074d2b Author: 江超群 Date: Mon Jun 26 20:13:41 2017 +0800 文档写出功能初步实现 commit d6cde1434ad572d17286deb8e0e56d99e443b7ab Author: 江超群 Date: Mon Jun 26 11:00:04 2017 +0800 关于文件写出,做一些修改,记录更改 # Conflicts: # ofdEditor/model/Doc/DocPassage.cpp --- ofdEditor/model/Convert/Doc_OFDConvertor.cpp | 269 +++++++++++++++--- ofdEditor/model/Convert/OFD_DocConvertor.cpp | 4 +- ofdEditor/model/Doc/DocPassage.cpp | 69 ++++- ofdEditor/model/Doc/DocPassage.h | 5 + ofdEditor/model/Doc/DocTextBlock.cpp | 50 ---- ofdEditor/model/Tool/UnitTool.cpp | 7 +- ofdEditor/ofd/DataTypes/basic_datatype.h | 7 +- ofdEditor/ofd/DataTypes/document/DocBody.h | 2 +- ofdEditor/ofd/DataTypes/document/Res.h | 2 +- ofdEditor/ofd/DataTypes/document/docbody.h | 2 +- .../ofd/DataTypes/image/CT_GraphicUnit.h | 4 + ofdEditor/ofd/DataTypes/page/Page.h | 2 +- ofdEditor/ofd/DataTypes/page/page.h | 2 +- ofdEditor/ofd/DataTypes/text/CT_Font.h | 1 + ofdEditor/ofd/DataTypes/text/CT_Text.h | 1 + ofdEditor/ofd/DataTypes/text/ct_text.h | 1 + ofdEditor/ofd/Loaders/ZipTool.cpp | 4 + ofdEditor/ofd/ofd_parser.cpp | 2 + ofdEditor/ofd/ofd_writer.cpp | 202 +++++++++---- ofdEditor/ofd/ofd_writer.h | 1 + .../start/ActionConnector/ActionConnector.cpp | 5 + .../start/ActionConnector/ActionConnector.h | 1 + ofdEditor/start/ui/PassageMainWindow.cpp | 115 +++++++- ofdEditor/start/ui/PassageMainWindow.h | 8 + 24 files changed, 593 insertions(+), 173 deletions(-) diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp index 0d46dc0..7ec91c0 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "DataTypes/basic_datatype.h" #include "DataTypes/document/ofd.h" @@ -28,7 +29,7 @@ #include "DataTypes/text/ct_text.h" #include "DataTypes/text/textcode.h" #include "DataTypes/basic_datatype.h" - +#include "Tool/UnitTool.h" Doc_OFDConvertor::Doc_OFDConvertor(QObject *parent) : QObject(parent) @@ -52,7 +53,9 @@ OFD *Doc_OFDConvertor::doc_to_ofd(DocPassage *passage) this->buildDocBody(); // 构建DocBody this->buildDocument(); // docment + qDebug() << "doc to ofd finished"; + return this->ofdFile; } @@ -66,12 +69,15 @@ OFD *Doc_OFDConvertor::doc_to_ofd(DocPassage *passage) void Doc_OFDConvertor::buildDocBody() { qDebug() << "exec buildDocbody"; - QVector docbodys; // 新建docbodys新建带有……的docbodys + + // 新建DocBody DocBody* docbody = new DocBody(this->passage->getDocInfo()); // 加入docbody - docbodys.append(docbody); // 新建DocBody - docbody->setDocRoot(QString("Doc_0/Document.xml")); // 设置文档根目录 + docbody->setDocRoot("Doc_0/Document.xml"); // 设置文档根目录 + this->ofdFile->getDocBodies()->append(docbody); // 设置ofd的docbobys + this->ofdFile->setDocType(this->passage->getDocType()); // 文档类型 + this->ofdFile->setOfdVersion(this->passage->getVersion()); // 文档类型 - this->ofdFile->setDocBodies( &docbodys); // 设置ofd的docbobys + qDebug() << "build docbody finished"; } @@ -85,26 +91,35 @@ void Doc_OFDConvertor::buildDocBody() void Doc_OFDConvertor::buildDocument() { qDebug() << "exec buildDocument"; - QVector documents; // 新建Documents +// QVector *documents = new QVector(); // 新建Documents Document* document = new Document(); // 新建Document - documents.append(document); // 添加到文件中 +// documents->append(document); // 添加到文件中 // 设置ID_Table this->table = document->getIDTable(); // 获得IDTable // 设置publicRes this->public_res = new Res(); - document->getPublicRes()->append(public_res); // 将公用资源加入到document + this->public_res->setBaseLoc("Res"); + document->getPublicRes()->append(this->public_res); // 将公用资源加入到document // 设置common_data CT_CommonData * commonData = new CT_CommonData(); document->setCommonData(commonData); + // 设置指向资源文件的 - commonData->getPublicRes()->append(ST_Loc(QString("PublicRes.xml"), - QString("PublicRes.xml"), - QString("PublicRes.xml"))); + commonData->getPublicRes()->append(ST_Loc("PublicRes.xml", + "PublicRes.xml", + "PublicRes.xml")); + this->buildPages(document); // 解析每一页 + + // this->ofdFile->setDocument(documents); + commonData->setMaxUnitID(this->table->size()); // 设置最大单元 + this->ofdFile->getDocuments()->append(document); + + qDebug() << "build document finished"; } /** @@ -120,7 +135,8 @@ void Doc_OFDConvertor::buildPages(Document* document) QVector docPages = this->passage->getPages(); // 获得页面 int pagesLength = docPages.size(); // 获得页面的数量 - if(pagesLength > 1) + // 公共页大小,之后改成从DocPassage读取 + if(pagesLength >= 1) { // 设置公共页大小 CT_CommonData* commonData = document->getCommonData(); @@ -146,15 +162,17 @@ void Doc_OFDConvertor::buildPages(Document* document) Page* ctPage = new Page(); ctPage->setID(this->table->size()+1,this->table); // 设置ID // 设置页的路径 - QString num; - num.setNum(i); - ctPage->setBaseLoc(QString("Pages/Page_") + num); + + ctPage->setBaseLoc(QString("Pages/Page_") + QString::number(i) + + "/Content.xml"); pages->append(ctPage); // 加入到OFD 文件中 this->buildPage(ctPage,page); // 单独处理每一页 } + qDebug() << "build Pages finished"; + } /** @@ -167,9 +185,15 @@ void Doc_OFDConvertor::buildPages(Document* document) */ void Doc_OFDConvertor::buildPage(Page *ctPage, DocPage *docPage) { - qDebug() << "exec buildPage"; + qDebug() << "exec buildPage:" << ctPage->getBaseLoc(); QVector *layers = ctPage->getContent(); + // pageArea + CT_PageArea *area = new CT_PageArea(); + area->setPhysicalBox(0,0, + docPage->getWidth(),docPage->getHeight()); + ctPage->setArea(area); + // 分成多个层,对每个层进行处理 DocLayer* foreground = docPage->getForegroundLayer(); // 获得前景层 CT_Layer* foreLayer = new CT_Layer(); // 处理前景层 @@ -195,6 +219,8 @@ void Doc_OFDConvertor::buildPage(Page *ctPage, DocPage *docPage) layers->append(backLayer); this->buildLayer(backLayer,background); + qDebug() << "build page Finished"; + } /** @@ -207,7 +233,7 @@ void Doc_OFDConvertor::buildPage(Page *ctPage, DocPage *docPage) */ void Doc_OFDConvertor::buildLayer(CT_Layer* ctLayer,DocLayer *layer) { - qDebug() << "Exec buildLayer"; + qDebug() << "Exec buildLayer" << ctLayer->getType(); QVector *blocks = layer->getBlocks(); int blocks_length = blocks->size(); @@ -246,39 +272,193 @@ void Doc_OFDConvertor::buildText(CT_Layer* ctLayer,DocTextBlock *textBlock) // 分析TextBlock textBlock->moveCursor(QTextCursor::Start); // 移动到块的开始 QTextCursor cursor = textBlock->textCursor(); - QTextDocument* document = cursor.document(); - int blockCount = document->blockCount(); // 获得Block的数量 - qDebug() << "This textBlock has " << blockCount << " QTextBlocks"; + QTextDocument* document = cursor.document(); // 获得文档 - for(int i =0; iblockCount(); i++) + { + QTextBlock block = cursor.block(); // 获得当前块 + QTextCursor tempCursor = cursor; // 复制cursor + + QTextBlock::Iterator iter = block.begin(); // 块的开始 + + while(!iter.atEnd() + || lineContent.length() != 0 + || tempFragment.length() !=0) // 用来判断是否处理完了 + { + if(tempFragment.size() == 0 && !iter.atEnd()) + { + // 如果处理字段为空 + fragment = iter.fragment(); // 获得当前的 + tempFragment = fragment.text(); + iter++; + } + + if(lineContent == "") + { + tempCursor.select(QTextCursor::LineUnderCursor); // 选择当前行 + QString currentLine = tempCursor.selectedText(); // 选中的文字 + + lineContent = currentLine; // 追加一行 + lineContent_backup = currentLine; // 当前行内容 + lineCount ++; + // qDebug() << "Read Next Line: " << currentLine + // << "LineContent: " << lineContent; + pixelContent = 0; // 使用新行,已用长度置空 + pixelContHeight = 0; // 使用新行,最大高度置零 + } + + QString nextEditContent; // 即将处理的字段 + + // 处理当前Fragment + if(tempFragment.length() < lineContent.length()) + { + // 当前小块的长度未达一页 + + // 删除重复的部分,用来循环 + lineContent.remove(0,tempFragment.length()); // 把重复的部分先从lineContent中删除 + qDebug() << "use TextFragement: " << tempFragment; + nextEditContent = tempFragment; // 设置待处理字段 + tempFragment.remove(0,tempFragment.length()); // 清空 + + } + else if(tempFragment.length() >= lineContent.length()) + { + // 当前行已完,但小块未完 + + // 删除重复的用来循环 + tempFragment.remove(0,lineContent.length()); + qDebug() << "use remaind lineContent: " << lineContent; + nextEditContent = lineContent; // 设置待处理字段 + lineContent.remove(0,lineContent.length()); // 清空 + } + + // 样式 + QTextCharFormat charFormat = fragment.charFormat(); // 字符格式 + QTextBlockFormat blockFormat = tempCursor.blockFormat();// 块格式 + QFont font = charFormat.font(); // 字体 + + + // 分析块的大小 + QFontMetricsF metrics(font); + + int pixelWidth = metrics.boundingRect(nextEditContent).width(); // 获得宽度 + int pixelHeight = metrics.boundingRect(nextEditContent).height(); // 获得高度 + + if(pixelContHeight < pixelHeight) + { + + // 如果小于最大行间距 + pixelLine = pixelLine + pixelHeight; // 纵向深度增加 + qDebug() << "pixelLine: "<< pixelLine + << " pixelHeight:" << pixelHeight; + } + + CT_Text* ct_text = new CT_Text(); + ct_text->setID(this->table->size() +1 ,this->table); // 设置ID + ctLayer->getTextObject()->append(ct_text); // 加入到layer + + // 设置颜色 + QBrush brush = charFormat.foreground(); // 获得画笔 + QColor color = brush.color(); // 获得颜色 + CT_ColorSpace *space = new CT_ColorSpace(); // 颜色空间 + space->setBitsPerComponent(8); + space->setType("RGB"); + int colorSpaceId = this->addColorSpace(space); + CT_Color* ct_color = new CT_Color(); + + ct_color->setValue(QString::number(color.red()) + " " + + QString::number(color.green()) + " " + + QString::number(color.blue())); + ct_color->setColorSpace(colorSpaceId,this->table); + + ct_text->setFillColor(ct_color); + + + // 加入字体 + CT_Font* ctfont = new CT_Font(); + ctfont->setFamilyName(font.family()); + ctfont->setFontName(font.family()); + int font_id = this->addFont(ctfont); // 添加字体ID + ct_text->setFont(font_id, this->table); // 设置字体引用 + + // 设置字体 + if(font.italic()) + { + // 如果斜体 + ct_text->setItalic( true); + } + if(font.weight() != 50) + { + // 字重 + ct_text->setWeight(font.weight() * 8); // 默认值400 + } + + // 设置字体大小 + // 这个只针对/通过 setPixelSize的才有效 +// double font_size = font.pixelSize(); // 获得字大小 +// qDebug() << "Font Size:" <setSize(UnitTool::pixelToMM(font_size)); +// int fontPixelSize = metrics.height(); // 获得像素高度 + ct_text->setSize(UnitTool::pixelToMM(pixelHeight)); + + qDebug() << "before setBoundary pixelLine: "<< pixelLine; + + // 边框 + ct_text->setBoundary(UnitTool::pixelToMM(textBlock->pos().rx() + + pixelContent), // 最左侧,向右偏移一定距离 + UnitTool::pixelToMM(textBlock->pos().ry() + + pixelLine), + UnitTool::pixelToMM(pixelWidth), + UnitTool::pixelToMM(pixelLine) + ); + + qDebug() << "After setBoundary pixelLine: "<< pixelLine; + + // 设置delta_x + TextCode* textCode = new TextCode(); // 文字内容 + textCode->setText(nextEditContent); // 设置文字内容 + textCode->setX(0); // 设置起始位置 + textCode->setY(UnitTool::pixelToMM(metrics.height())); + + if(nextEditContent.length()>1) + { + qDebug() << "font's wordSpacing:" << font.wordSpacing(); + QString delta_x_str; + // n个字符 n-1 个 delta_x + for(int delta_x = 0; delta_x < nextEditContent.length()-1; delta_x++) + { + + delta_x_str = delta_x_str + " " + + QString::number( + UnitTool::pixelToMM( + metrics.boundingRect( + nextEditContent.operator [](delta_x)).width())); + } + textCode->setDeltaX(delta_x_str); + } + + ct_text->getTextCode()->append(textCode); // 加入到textCode中 + + pixelContent += pixelWidth; // 将当前使用长度加入,进入下一次循环 + } + cursor.movePosition(QTextCursor::NextBlock); // + } + //// 将文本框按照 格式和行进行拆分 } @@ -377,3 +557,4 @@ int Doc_OFDConvertor::checkColorSpace(CT_ColorSpace *colorSpace) return -1; // 不存在已有的 } + diff --git a/ofdEditor/model/Convert/OFD_DocConvertor.cpp b/ofdEditor/model/Convert/OFD_DocConvertor.cpp index 1b75e10..a61073f 100644 --- a/ofdEditor/model/Convert/OFD_DocConvertor.cpp +++ b/ofdEditor/model/Convert/OFD_DocConvertor.cpp @@ -232,7 +232,7 @@ void OFD_DocConvertor::insertCT_Text(DocPage *page, DocPage::Layer layer, CT_Tex // qDebug() << "deal with current textcode:" << i; // 求出单个块的保卫面积 - double height = text->getSize(); // 高等于字体的高 + double height = text->getSize() + 5; // 高等于字体的高 double width = 0; // 所有deltax相加再加上一个字宽 double x = text->boundary.getX() + textCode->getX(); // 左上角 x坐标 double y = text->boundary.getY() + textCode->getY() - height; // 左上角y值 @@ -247,7 +247,7 @@ void OFD_DocConvertor::insertCT_Text(DocPage *page, DocPage::Layer layer, CT_Tex width += arrayDeltaX[j].toDouble(); // 计算宽度 } - width += height; // 假设为方块字吧 + width += height + 15; // 假设为方块字吧 // qDebug() << "has compute the boundary"; diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index ec94c41..b2c6a3c 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -11,7 +11,7 @@ #include #include #include -#include "../Tool/UnitTool.h" +#include /** * @Author Chaoqun @@ -186,6 +186,18 @@ void DocPassage::removePage(DocPage *page) } +/** + * @Author Chaoqun + * @brief 设置文件路径 + * @param QString filePath + * @return void + * @date 2017/06/26 + */ +void DocPassage::setFilePath(QString filePath) +{ + this->filePath = filePath; +} + /** * @Author Chaoqun * @brief 设置文档原信息 @@ -222,6 +234,48 @@ CT_DocInfo *DocPassage::getDocInfo() return this->docInfo; } +/** + * @Author Chaoqun + * @brief 获得文章的uuid + * @param void + * @return QString& + * @date 2017/06/xx + */ +QString DocPassage::getUUID() +{ + return this->docInfo->getDocID(); +} + +/** + * @Author Chaoqun + * @brief 获得用来存储文档时的临时路径 + * @param void + * @return QString + * @date 2017/06/26 + */ +QString DocPassage::getTempSavePath() +{ + QString temp = QDir::tempPath() + "/"; // 获得系统临时路径 + QString uuid = this->getUUID(); // 获得uuid + QString end = "-source"; + return temp + uuid + end; // 获得临时存放路径 +} + +/** + * @Author Chaoqun + * @brief 临时存储路劲 + * @param void + * @return QString + * @date 2017/06/26 + */ +QString DocPassage::getTempStorePath() +{ + QString temp = QDir::tempPath() + "/"; // 获得系统临时路径 + QString uuid = this->getUUID(); // 获得uuid + QString end = "-file"; + return temp + uuid + end; // 获得临时存放路径 +} + /** * @Author Chaoqun * @brief 获得文档中所有的页面 @@ -246,6 +300,19 @@ DocPage *DocPassage::getPage(int index) return this->pages[index]; } +/** + * @Author Chaoqun + * @brief 摘要 + * @param 参数 + * @return 返回值 + * @date 2017/06/26 + */ +QString DocPassage::getFilePath() +{ + // 获得文件路径 + return this->filePath; +} + /** * @Author Chaoqun * @brief 设置CommonData,深拷贝 diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index 855c293..cce08ce 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -41,10 +41,14 @@ public: ~DocPassage(); CT_DocInfo* getDocInfo(); // 获取CT_DocInfo数据 + QString getUUID(); // 获得文章的uuid + QString getTempSavePath(); // 获得文章保存前的临时路径 + QString getTempStorePath(); // 获得暂存资源的临时路径 QString getVersion( ){return this->version;} QString getDocType( ){return this->docType;} QVector& getPages(); // 获得文档中包含的所有页面 DocPage *getPage(int index); // 获得文档中的某一页 + QString getFilePath(); // 获得文档路径 QUndoStack *undoStack; // 撤销队列 public slots: @@ -54,6 +58,7 @@ public slots: void removePage(int index); // 移除某一页 void removePage(DocPage* page); // 移除某一页 + void setFilePath(QString filePath); // 设置文件路径 // DocInfo void setDocInfo( CT_DocInfo & docInfo ); diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 6368d1d..cace6a2 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -362,56 +362,6 @@ void DocTextBlock::textUnderline() mergeFormatOnWordOrSelection(fmt); // 合并格式 - -// /////test -// QTextCursor cursor = this->textCursor(); // 获取光标 -// cursor.movePosition(QTextCursor::Start); // 移动到文章开头 -// for(int i = 0 ; i < this->document()->blockCount(); i++) -// { -// QTextBlock block = cursor.block(); // 获得当前块 -// QTextCursor tempCursor = cursor; // 复制cursor - -// QTextBlock::Iterator iter = block.begin(); // 块的开始 -// QString lineContent; // 行内容 -// QString tempFragement; // 块 -// QTextFragment fragment; // 短句 - -// while(!iter.atEnd()) // 用来判断是否处理完了 -// { -// if(tempFragement == "") -// { -// // 如果处理字段为空 -// fragment = iter.fragment(); // 获得当前的 -// tempFragement = fragment.text(); // -// iter++; -// } -//// while(lineContent.length() < tempFragement.length()) -//// { -//// cursor.select(QTextCursor::LineUnderCursor); // 选择当前行 -//// QString currentLine = cursor.selectedText(); // 选中的文字 - -//// lineContent += currentLine; // 追加一行 -//// qDebug() << "Read Next Line: " << currentLine -//// << "LineContent: " << lineContent; -//// } -// if(lineContent == "") -// { -// cursor.select(QTextCursor::LineUnderCursor); // 选择当前行 -// QString currentLine = cursor.selectedText(); // 选中的文字 - -// lineContent += currentLine; // 追加一行 -// qDebug() << "Read Next Line: " << currentLine -// << "LineContent: " << lineContent; -// } - -// // 处理当前Fragment -//// if(fra) - - -// } - -// cursor.movePosition(QTextCursor::NextBlock); -// } } /** diff --git a/ofdEditor/model/Tool/UnitTool.cpp b/ofdEditor/model/Tool/UnitTool.cpp index 030175d..fed56d7 100644 --- a/ofdEditor/model/Tool/UnitTool.cpp +++ b/ofdEditor/model/Tool/UnitTool.cpp @@ -27,10 +27,10 @@ int UnitTool::mmToPixel(double mm) // QDesktopWidget *desktopWidget = QApplication::desktop(); // 获取桌面信息 double dotsPerInch = 96; // 暂时不知道如何获得屏幕具体信息 + int pixel = (int)(inch * dotsPerInch); - - return (int)(inch * dotsPerInch); // 返回像素大小 + return pixel; // 返回像素大小 } /** @@ -50,7 +50,8 @@ double UnitTool::pixelToMM(double pixel) double dotsPerInch = 96; double inch = pixel / dotsPerInch; // 获取像素单位对应的英寸单位 - return inch * 25.4; // 返回毫米单位 + double mm = inch * 25.4; + return mm; // 返回毫米单位 } /** diff --git a/ofdEditor/ofd/DataTypes/basic_datatype.h b/ofdEditor/ofd/DataTypes/basic_datatype.h index 785b364..97e64e9 100644 --- a/ofdEditor/ofd/DataTypes/basic_datatype.h +++ b/ofdEditor/ofd/DataTypes/basic_datatype.h @@ -48,8 +48,9 @@ public: // qDebug() << "cur = " << current_path << "rela = " << relative_path << endl; abs_path = current_path + relative_path; } //构造方法,包括对路径的解析 - ST_Loc(QString tag, QString _abs_path) : title(tag), abs_path(_abs_path) { //构造方法,在直接已有绝对路径时 - abs_path.replace("/", "\\"); + ST_Loc(QString tag, QString _abs_path) + : title(tag), abs_path(_abs_path) { //构造方法,在直接已有绝对路径时 + abs_path.replace("\\", "/"); } operator QString() { //可以直接把ST_Loc作为一个路径字符串使用 @@ -67,7 +68,7 @@ public: } bool isNull() { - return abs_path.isNull(); + return abs_path.length() == 0; } }; diff --git a/ofdEditor/ofd/DataTypes/document/DocBody.h b/ofdEditor/ofd/DataTypes/document/DocBody.h index dcbbced..975b017 100644 --- a/ofdEditor/ofd/DataTypes/document/DocBody.h +++ b/ofdEditor/ofd/DataTypes/document/DocBody.h @@ -40,7 +40,7 @@ public: } void setDocRoot(QString _doc_root_abs) { - ST_Loc p("DocRoot", _doc_root_abs); + ST_Loc p("DocRoot", _doc_root_abs,_doc_root_abs); doc_root = p; } diff --git a/ofdEditor/ofd/DataTypes/document/Res.h b/ofdEditor/ofd/DataTypes/document/Res.h index 59f9994..557d54f 100644 --- a/ofdEditor/ofd/DataTypes/document/Res.h +++ b/ofdEditor/ofd/DataTypes/document/Res.h @@ -43,7 +43,7 @@ public: } void setBaseLoc(QString _base_loc_abs) { - ST_Loc p("Resource", _base_loc_abs); + ST_Loc p("Resource", _base_loc_abs,_base_loc_abs); base_loc = p; } diff --git a/ofdEditor/ofd/DataTypes/document/docbody.h b/ofdEditor/ofd/DataTypes/document/docbody.h index dcbbced..975b017 100644 --- a/ofdEditor/ofd/DataTypes/document/docbody.h +++ b/ofdEditor/ofd/DataTypes/document/docbody.h @@ -40,7 +40,7 @@ public: } void setDocRoot(QString _doc_root_abs) { - ST_Loc p("DocRoot", _doc_root_abs); + ST_Loc p("DocRoot", _doc_root_abs,_doc_root_abs); doc_root = p; } diff --git a/ofdEditor/ofd/DataTypes/image/CT_GraphicUnit.h b/ofdEditor/ofd/DataTypes/image/CT_GraphicUnit.h index 0ae86be..ab51b9a 100644 --- a/ofdEditor/ofd/DataTypes/image/CT_GraphicUnit.h +++ b/ofdEditor/ofd/DataTypes/image/CT_GraphicUnit.h @@ -58,6 +58,8 @@ public: CT_Color * _fill_color = NULL, CT_Color * _stroke_color = NULL ) { + fill_color = NULL; + stroke_color = NULL; if (_start_x || _start_y || _delta_x || _delta_y) setBoundary(_start_x, _start_y, _delta_x, _delta_y); setName(_name); @@ -73,6 +75,8 @@ public: setAlpha(_alpha); setFillColor(_fill_color); setStrokeColor(_stroke_color); + + } ST_Box getBoundary() { diff --git a/ofdEditor/ofd/DataTypes/page/Page.h b/ofdEditor/ofd/DataTypes/page/Page.h index 2603a62..c02f827 100644 --- a/ofdEditor/ofd/DataTypes/page/Page.h +++ b/ofdEditor/ofd/DataTypes/page/Page.h @@ -28,7 +28,7 @@ public: } void setBaseLoc(QString _base_loc_abs) { - ST_Loc p("BaseLoc", _base_loc_abs); + ST_Loc p("BaseLoc", _base_loc_abs, _base_loc_abs); base_loc = p; } diff --git a/ofdEditor/ofd/DataTypes/page/page.h b/ofdEditor/ofd/DataTypes/page/page.h index 2603a62..c02f827 100644 --- a/ofdEditor/ofd/DataTypes/page/page.h +++ b/ofdEditor/ofd/DataTypes/page/page.h @@ -28,7 +28,7 @@ public: } void setBaseLoc(QString _base_loc_abs) { - ST_Loc p("BaseLoc", _base_loc_abs); + ST_Loc p("BaseLoc", _base_loc_abs, _base_loc_abs); base_loc = p; } diff --git a/ofdEditor/ofd/DataTypes/text/CT_Font.h b/ofdEditor/ofd/DataTypes/text/CT_Font.h index 237764f..5294793 100644 --- a/ofdEditor/ofd/DataTypes/text/CT_Font.h +++ b/ofdEditor/ofd/DataTypes/text/CT_Font.h @@ -15,6 +15,7 @@ class OFDSHARED_EXPORT CT_Font : public CT_Base { //字体声明类型 bool serif; bool fixed_width; //FontFile +public: CT_Font(){ charset = "GB18030"; italic = false; diff --git a/ofdEditor/ofd/DataTypes/text/CT_Text.h b/ofdEditor/ofd/DataTypes/text/CT_Text.h index 9498dea..9ec7ac6 100644 --- a/ofdEditor/ofd/DataTypes/text/CT_Text.h +++ b/ofdEditor/ofd/DataTypes/text/CT_Text.h @@ -66,6 +66,7 @@ public: void setSize(double _size) { size = _size; + size_used = true; } bool sizeUsed() { diff --git a/ofdEditor/ofd/DataTypes/text/ct_text.h b/ofdEditor/ofd/DataTypes/text/ct_text.h index 9498dea..9ec7ac6 100644 --- a/ofdEditor/ofd/DataTypes/text/ct_text.h +++ b/ofdEditor/ofd/DataTypes/text/ct_text.h @@ -66,6 +66,7 @@ public: void setSize(double _size) { size = _size; + size_used = true; } bool sizeUsed() { diff --git a/ofdEditor/ofd/Loaders/ZipTool.cpp b/ofdEditor/ofd/Loaders/ZipTool.cpp index d910294..fcb1da5 100644 --- a/ofdEditor/ofd/Loaders/ZipTool.cpp +++ b/ofdEditor/ofd/Loaders/ZipTool.cpp @@ -42,6 +42,10 @@ void ZipTool::extractDir(QString fileCompressed, QString dir) bool ZipTool::compressDir(QString fileCompressed, QString dir, bool deleteDir) { + QDir dirs; + if(dirs.exists(fileCompressed)) + deleteFolder(fileCompressed); + bool flag = false; flag = JlCompress::compressDir(fileCompressed,dir,true); // 递归 if(!flag) diff --git a/ofdEditor/ofd/ofd_parser.cpp b/ofdEditor/ofd/ofd_parser.cpp index a8e738d..5f1f58a 100644 --- a/ofdEditor/ofd/ofd_parser.cpp +++ b/ofdEditor/ofd/ofd_parser.cpp @@ -489,6 +489,8 @@ void OFDParser::readGraphicUnit(CT_GraphicUnit *data, QDomElement &root_node) { CT_Color * fill_color_data = new CT_Color(); data->fill_color = fill_color_data; readColor(fill_color_data, t); + if (root_node.hasAttribute("ID") && root_node.attribute("ID").toInt() == 3) + qDebug() << "In OFDParser: " << fill_color_data; } //Other members to be implemented diff --git a/ofdEditor/ofd/ofd_writer.cpp b/ofdEditor/ofd/ofd_writer.cpp index 39c683d..f7bc239 100644 --- a/ofdEditor/ofd/ofd_writer.cpp +++ b/ofdEditor/ofd/ofd_writer.cpp @@ -14,13 +14,13 @@ #include "DataTypes/image/CT_Image.h" OFDWriter::OFDWriter(OFD * _data, QString _path) : data(_data), - current_path("OFD", _path + "OFD.xml") { + current_path("OFD", _path + "OFD.xml") { writeOFD(); } void OFDWriter::createFile() { current_file = new QFile(current_path.getPath()); -// qDebug() << current_path.getPath() << endl; + qDebug() << current_path.getPath() << endl; if (!current_file->open(QFile::WriteOnly | QFile::Text)) { throw WritingFileException("无法打开或创建XML文件: " + current_path.getPath()); } @@ -29,6 +29,7 @@ void OFDWriter::createFile() { void OFDWriter::writeOFD() { createFile(); + // qDebug() << "Checkpoint 1"; writer.writeStartDocument(); writer.setAutoFormatting(true); //进入正文 @@ -37,26 +38,38 @@ void OFDWriter::writeOFD() { QXmlStreamAttributes a = getAttributes(data); writer.writeAttributes(a); //写DocBody + qDebug() << "DocBodys size: "<< data->getDocBodies()->size(); for (int i = 0; i < data->getDocBodies()->size(); i++) { - DocBody * cur_docbody = data->getDocBodies()->at(i); + DocBody * cur_docbody = data->getDocBodies()->operator [](i); writer.writeStartElement("ofd:DocBody"); CT_DocInfo * cur_docinfo = cur_docbody->getDocInfo(); writer.writeStartElement("ofd:DocInfo"); //写DocInfo + // qDebug() << "Checkpoint 1.1"; if (!cur_docinfo->getDocID().isNull()) { writer.writeTextElement("ofd:DocID", cur_docinfo->getDocID()); } else { - throw WritingFormatException("DocInfo类型数据缺少必要的成员DocID"); + qDebug("DocInfo类型数据缺少必要的成员DocID"); } + // qDebug() << "Checkpoint 1.2"; if (!cur_docinfo->getTitle().isNull()) { + // qDebug() << "Checkpoint 1.2.1"; + cur_docinfo->getTitle(); + // qDebug() << "Checkpoint 1.2.1.5"; writer.writeTextElement("ofd:Title", cur_docinfo->getTitle()); + // qDebug() << "Checkpoint 1.2.2"; } + // qDebug() << "Checkpoint 1.3"; if (!cur_docinfo->getAuthor().isNull()) { + // qDebug() << "Checkpoint 1.3.1"; writer.writeTextElement("ofd:Author", cur_docinfo->getAuthor()); + // qDebug() << "Checkpoint 1.3.2"; } + // qDebug() << "Checkpoint 1.4"; if (!cur_docinfo->getSubject().isNull()) { writer.writeTextElement("ofd:Subject", cur_docinfo->getSubject()); } + // qDebug() << "Checkpoint 1.5"; if (!cur_docinfo->getAbstract().isNull()) { writer.writeTextElement("ofd:Abstract", cur_docinfo->getAbstract()); } @@ -76,6 +89,7 @@ void OFDWriter::writeOFD() { if (!cur_docinfo->getCreatorVersion().isNull()) { writer.writeTextElement("ofd:CreatorVersion", cur_docinfo->getCreatorVersion()); } + // qDebug() << "Checkpoint 1.6"; //写CustomDatas QVector * cur_custom_datas = cur_docinfo->getCustomDatas(); if (cur_custom_datas->size() != 0) { @@ -93,10 +107,12 @@ void OFDWriter::writeOFD() { if (!cur_docbody->getDocRoot().isNull()) { ST_Loc root("", data->getRootPath().getPath().remove("OFD.xml")); writer.writeTextElement("ofd:DocRoot", cur_docbody->getDocRoot().getRelativePath()); + qDebug() << "DocRoot :" << cur_docbody->getDocRoot(); } writer.writeEndElement(); } //正文结束 + // qDebug() << "Checkpoint 1.3"; writer.writeEndDocument(); current_file->close(); //修改current_file @@ -105,13 +121,19 @@ void OFDWriter::writeOFD() { ST_Loc p("Document", data->getDocBodies()->at(i)->getDocRoot().getRelativePath(), cur_path); current_path = p; + // qDebug() << "Checkpoint 1.4"; + qDebug() << " current Path" + << current_path.getRelativePath(); makePath(current_path); - writeDocument(data->getDocuments()->at(i)); + // qDebug() << "Checkpoint 1.5"; + writeDocument(data->getDocuments()->operator [](i)); } } void OFDWriter::writeDocument(Document * data) { + qDebug() << "writeDocument"; createFile(); + // qDebug() << "Checkpoint 2"; //qDebug() << "Checkpoint 1 reached."; writer.writeStartDocument(); writer.setAutoFormatting(true); @@ -126,14 +148,16 @@ void OFDWriter::writeDocument(Document * data) { writer.writeTextElement("ofd:MaxUnitID", QString::number(cur_common_data->getMaxUnitID().getID())); } else { - throw WritingFormatException("CT_CommonData类型数据缺少必要的成员MaxUnitID"); + // qDebug("CT_CommonData类型数据缺少必要的成员MaxUnitID"); + qDebug() << "CT_CommonData类型数据缺少必要的成员MaxUnitID"; } if (cur_common_data->getPageArea()) { writer.writeStartElement("ofd:PageArea"); writePageArea(cur_common_data->getPageArea()); writer.writeEndElement(); //ofd:PageArea } else { - throw WritingFormatException("CT_CommonData类型数据缺少必要的成员PageArea"); + // qDebug("CT_CommonData类型数据缺少必要的成员PageArea"); + qDebug() << "CT_CommonData类型数据缺少必要的成员PageArea"; } for (int i = 0; i < data->getCommonData()->getPublicRes()->size(); i++) { @@ -143,7 +167,8 @@ void OFDWriter::writeDocument(Document * data) { //TemplatePage & DefaultCS to be implemented writer.writeEndElement(); //ofd:CommonData } else { - throw WritingFormatException("Document类型数据缺少必要的成员CommonData"); + // qDebug("Document类型数据缺少必要的成员CommonData"); + qDebug() << "Document类型数据缺少必要的成员CommonData"; } //写Pages if (data->getPages()) { @@ -158,35 +183,50 @@ void OFDWriter::writeDocument(Document * data) { } writer.writeEndElement(); //ofd:Pages } else { - throw WritingFormatException("Document类型数据缺少必要的成员Pages"); +// qDebug("Document类型数据缺少必要的成员Pages"); + qDebug() << "Document类型数据缺少必要的成员Pages"; } //写CustomTags if (!data->getCustomTags().isNull()) { writer.writeTextElement("ofd:CustomTags", data->getCustomTags().getRelativePath()); } + +// qDebug() << "Document main part finished"; + //Outlines, extensions, annotations to be implemented //正文结束 writer.writeEndDocument(); current_file->close(); ST_Loc cur_path = current_path; for (int i = 0; i < data->getPages()->getPages()->size(); i++) { - ST_Loc p("Page", data->getPages()->getPages()->at(i)-> + ST_Loc p("Page", data->getPages()->getPages()->operator [](i)-> getBaseLoc().getRelativePath(), cur_path); +// qDebug() << "Page" << i << " : " +// << data->getPages()->getPages()->operator [](i)->getBaseLoc().getRelativePath(); current_path = p; makePath(current_path); - writePage(data->getPages()->getPages()->at(i)); + writePage(data->getPages()->getPages()->operator [](i)); } +// qDebug() << "write pages finished"; + qDebug() << "PublicRes size = " << data->getPublicRes()->size(); for (int i = 0; i < data->getPublicRes()->size(); i++) { - ST_Loc p("PublicRes", data->getPublicRes()->at(i)->getBaseLoc().getRelativePath(), cur_path); + ST_Loc p("PublicRes", + (data->getCommonData()->getPublicRes()->operator [](i)).getRelativePath(), + cur_path); + qDebug() << "publicRes loc: " << p.getRelativePath(); current_path = p; makePath(current_path); - writeRes(data->getPublicRes()->at(i)); + qDebug() << "current path = " << current_path; + writeRes(data->getPublicRes()->operator [](i)); + qDebug() << "current res baseloc = " << (data->getPublicRes()->operator [](i))->getBaseLoc(); } +// qDebug() << "write publicRes finished"; //write CustomTags to be implemented } void OFDWriter::writePage(Page * data) { createFile(); + // qDebug() << "Checkpoint 3"; writer.writeStartDocument(); writer.setAutoFormatting(true); //进入正文 @@ -199,31 +239,36 @@ void OFDWriter::writePage(Page * data) { writePageArea(data->getArea()); writer.writeEndElement(); //ofd:Area } -// qDebug() << "Checkpoint 1 reached."; + // qDebug() << "Checkpoint 1 reached."; //写PageRes for (int i = 0; i < data->getPageResLocations()->size(); i++) { ST_Loc p = data->getPageResLocations()->at(i); writer.writeTextElement("ofd:PageRes", p.getRelativePath()); } -// qDebug() << "Checkpoint 2 reached."; + // qDebug() << "Checkpoint 2 reached."; //写Content if (data->getContent()->size()) { writer.writeStartElement("ofd:Content"); for (int i = 0; i < data->getContent()->size(); i++) { -// qDebug() << data->getContent()->size(); - CT_Layer * cur_layer = data->getContent()->at(i); - writer.writeStartElement("ofd:Layer"); - writeBase(cur_layer); -// qDebug() << "Checkpoint 2.1 reached."; - QXmlStreamAttributes a = getAttributes(cur_layer); - writer.writeAttributes(a); -// qDebug() << "Checkpoint 2.2 reached."; -// qDebug() << "???"; - //写文档页面的内容(QGraphicUnits的子类集合) - writePageBlock(cur_layer, true); + // qDebug() << data->getContent()->size(); + CT_Layer * cur_layer = data->getContent()->operator [](i); + if (cur_layer->getImageObject()->size() + cur_layer->getPathObject()->size() + +cur_layer->getTextObject()->size() + cur_layer->getPageBlock()->size() + > 0) { + writer.writeStartElement("ofd:Layer"); + writeBase(cur_layer); + // qDebug() << "Checkpoint 2.1 reached."; + QXmlStreamAttributes a = getAttributes(cur_layer); + writer.writeAttributes(a); + // qDebug() << "Checkpoint 2.2 reached."; + // qDebug() << "???"; + //写文档页面的内容(QGraphicUnits的子类集合) + writePageBlock(cur_layer, true); + writer.writeEndElement(); + } } writer.writeEndElement(); //ofd:Content - //qDebug() << "????"; + // qDebug() << "????"; } // qDebug() << "Checkpoint 3 reached."; //Actions to be implemented @@ -244,7 +289,8 @@ void OFDWriter::writeRes(Res * data) { if (!data->getBaseLoc().isNull()) { writer.writeAttribute("BaseLoc", data->getBaseLoc().getRelativePath()); } else { - throw WritingFormatException("Res类型数据缺少必要的属性BaseLoc"); + qDebug() << "class Res lack the required attribute baseloc"; +// qDebug("Res类型数据缺少必要的属性BaseLoc"); } //写成员 if (data->getColorSpaces()->size()) { @@ -293,7 +339,7 @@ void OFDWriter::writePageArea(CT_PageArea * cur_page_area) { QString::number(b.getDeltaX())+ " " + QString::number(b.getDeltaY())); } else { - throw WritingFormatException("CT_PageArea类型数据缺少必要的成员PhysicalBox"); + qDebug("CT_PageArea类型数据缺少必要的成员PhysicalBox"); } if (!cur_page_area->getApplicationBox().isNull()) { ST_Box b = cur_page_area->getApplicationBox(); @@ -322,20 +368,22 @@ void OFDWriter::writePageArea(CT_PageArea * cur_page_area) { } void OFDWriter::writePageBlock(CT_PageBlock * cur_page_block, bool is_layer) { - writeBase(cur_page_block); + if (!is_layer) + writeBase(cur_page_block); //文字内容 // qDebug() << "TextObject: " << cur_page_block->getTextObject()->size(); for (int i = 0; i < cur_page_block->getTextObject()->size(); i++) { - CT_Text * cur_text = cur_page_block->getTextObject()->at(i); + CT_Text * cur_text = cur_page_block->getTextObject()->operator [](i); writer.writeStartElement("ofd:TextObject"); +// qDebug() << "About to write Text Object."; writeTextObject(cur_text); writer.writeEndElement(); //ofd:TextObject } //矢量图内容 // qDebug() << "PathObject: " << cur_page_block->getPathObject()->size(); for (int i = 0; i < cur_page_block->getPathObject()->size(); i++) { - CT_Path * cur_path = cur_page_block->getPathObject()->at(i); + CT_Path * cur_path = cur_page_block->getPathObject()->operator [](i); writer.writeStartElement("ofd:PathObject"); writePathObject(cur_path); writer.writeEndElement(); //ofd:PathObject @@ -343,7 +391,7 @@ void OFDWriter::writePageBlock(CT_PageBlock * cur_page_block, bool is_layer) { //位图内容 // qDebug() << "ImageObject: " << cur_page_block->getImageObject()->size(); for (int i = 0; i < cur_page_block->getImageObject()->size(); i++) { - CT_Image * cur_image = cur_page_block->getImageObject()->at(i); + CT_Image * cur_image = cur_page_block->getImageObject()->operator [](i); writer.writeStartElement("ofd:ImageObject"); writeImageObject(cur_image); writer.writeEndElement(); //ofd:ImageObject @@ -351,7 +399,7 @@ void OFDWriter::writePageBlock(CT_PageBlock * cur_page_block, bool is_layer) { //PageBlock嵌套 // qDebug() << "PageBlock: " << cur_page_block->getPageBlock()->size(); for (int i = 0; i < cur_page_block->getPageBlock()->size(); i++) { - CT_PageBlock * cur_inner_page_block = cur_page_block->getPageBlock()->at(i); + CT_PageBlock * cur_inner_page_block = cur_page_block->getPageBlock()->operator [](i); writer.writeStartElement("ofd:PageBlock"); writePageBlock(cur_inner_page_block); writer.writeEndElement(); @@ -360,11 +408,16 @@ void OFDWriter::writePageBlock(CT_PageBlock * cur_page_block, bool is_layer) { void OFDWriter::writeTextObject(CT_Text * cur_text) { writeGraphicUnitAttributes(cur_text); -// qDebug() << "Checkpoint 4 reached."; +// qDebug() << "!!!!"; QXmlStreamAttributes a = getAttributes(cur_text); +// qDebug() << "!!!!????"; +// qDebug() << "cur_text->attributes is empty: " << a.isEmpty(); +// for (int i = 0; i < a.size(); i++) +// qDebug() << a.at(i).name() << " " << a.at(i).value(); writer.writeAttributes(a); // qDebug() << "Checkpoint 5 reached."; writeGraphicUnitMemebers(cur_text); +// qDebug() << "Checkpoint 6 reached."; //CGTransform to be implemented if (cur_text->getTextCode()) { QVector * cur_textcode = cur_text->getTextCode(); @@ -375,8 +428,9 @@ void OFDWriter::writeTextObject(CT_Text * cur_text) { writer.writeCharacters(cur_textcode->at(i)->getText()); writer.writeEndElement(); //ofd:TextCode } + // qDebug() << "Checkpoint 7 reached."; } else { - throw WritingFormatException("CT_Text类型数据缺少必要的成员TextObject"); + qDebug("CT_Text类型数据缺少必要的成员TextObject"); } } @@ -385,13 +439,13 @@ void OFDWriter::writePathObject(CT_Path * cur_path) { QXmlStreamAttributes a = getAttributes(cur_path); writer.writeAttributes(a); writeGraphicUnitMemebers(cur_path); -// qDebug() << "???"; + // qDebug() << "???"; if (!cur_path->getAbbreviatedData().isNull()) { writer.writeTextElement("ofd:AbbreviatedData", cur_path->getAbbreviatedData()); -// qDebug() << "????"; + // qDebug() << "????"; } else { - throw WritingFormatException("CT_Path类型数据缺少必要的成员AbbreviatedData"); + qDebug("CT_Path类型数据缺少必要的成员AbbreviatedData"); } } @@ -409,20 +463,28 @@ void OFDWriter::writeGraphicUnitAttributes(CT_GraphicUnit * cur_graphic_unit) { } void OFDWriter::writeGraphicUnitMemebers(CT_GraphicUnit * cur_graphic_unit) { +// qDebug() << "Checkpoint 10 reached."; +// qDebug() << cur_graphic_unit->getID(); +// qDebug() << "Checkpoint 10.1 reached."; if (cur_graphic_unit->getFillColor()) { writer.writeStartElement("ofd:FillColor"); writeColor(cur_graphic_unit->getFillColor()); writer.writeEndElement(); //ofd:FillColor } - //qDebug() << "Checkpoint 5 reached."; +// qDebug() << "Checkpoint 11 reached."; if (cur_graphic_unit->getStrokeColor()) { + qDebug() << "Checkpoint 11.1 reached."; writer.writeStartElement("ofd:StrokeColor"); writeColor(cur_graphic_unit->getStrokeColor()); + qDebug() << "Checkpoint 11.2 reached."; writer.writeEndElement(); //ofd:StrokeColor } + // qDebug() << "Checkpoint 12 reached."; } void OFDWriter::writeColor(CT_Color * cur_color) { +// qDebug() << "Checkpoint 20 reached."; + // qDebug() << "cur_color = " << cur_color; QXmlStreamAttributes a = getAttributes(cur_color); writer.writeAttributes(a); //Pattern and AxialShd / RadialShd to be implemented @@ -433,7 +495,7 @@ void OFDWriter::writeBase(CT_Base * cur_base) { if (!cur_base->getID().isNull()) { writer.writeAttribute("ID", QString::number(cur_base->getID().getID())); } else { - throw WritingFormatException("CT_Base类型数据缺少必要的属性ID"); + qDebug("CT_Base类型数据缺少必要的属性ID"); } } @@ -473,19 +535,19 @@ QXmlStreamAttributes getAttributes(OFD * data) { if (!data->getDocType().isNull()) { a.append("DocType", data->getDocType()); } else { - throw WritingFormatException("OFD类型数据缺少必要的属性DocType"); + qDebug("OFD类型数据缺少必要的属性DocType"); } if (!data->getOfdVersion().isNull()) { a.append("Version", data->getOfdVersion()); } else { - throw WritingFormatException("OFD类型数据缺少必要的属性Version"); + qDebug("OFD类型数据缺少必要的属性Version"); } return a; } QXmlStreamAttributes getAttributes(CT_Layer * cur_layer) { QXmlStreamAttributes a; - if (cur_layer->getType() != "Body") +// if (cur_layer->getType() != "Body") a.append("Type", cur_layer->getType()); if (!cur_layer->getDrawParam().isNull()) { a.append("DrawParam",QString::number(cur_layer->getDrawParam().getRefID())); @@ -495,7 +557,7 @@ QXmlStreamAttributes getAttributes(CT_Layer * cur_layer) { QXmlStreamAttributes getAttributes(CT_GraphicUnit * cur_graphic_unit) { QXmlStreamAttributes a; - +// qDebug() << "Boundary is null: " << cur_graphic_unit->getBoundary().isNull(); if (!cur_graphic_unit->getBoundary().isNull()) { ST_Box b = cur_graphic_unit->getBoundary(); a.append("Boundary", @@ -504,10 +566,11 @@ QXmlStreamAttributes getAttributes(CT_GraphicUnit * cur_graphic_unit) { QString::number(b.getDeltaX()) + " " + QString::number(b.getDeltaY())); } else { - throw WritingFormatException("CT_GraphicUnit类型数据缺少必要的属性Boundary"); + qDebug("CT_GraphicUnit类型数据缺少必要的属性Boundary"); } - - if (!cur_graphic_unit->getName().isNull()) { +// qDebug() << "CT_Graphic Unit Name: " << cur_graphic_unit->getName(); +// qDebug() << "CT_Graphic Unit Name is Null: " << cur_graphic_unit->getName().isNull(); + if (cur_graphic_unit->getName().length() != 0) { a.append("Name", cur_graphic_unit->getName()); } @@ -529,17 +592,21 @@ QXmlStreamAttributes getAttributes(CT_GraphicUnit * cur_graphic_unit) { QXmlStreamAttributes getAttributes(CT_Color *cur_color) { QXmlStreamAttributes a; - +// qDebug() << "Checkpoint 30 reached."; if (!cur_color->getValue().isNull()) { +// qDebug() << "Checkpoint 30.1 reached."; a.append("Value", cur_color->getValue().getAllContent()); } +// qDebug() << "Checkpoint 31 reached."; if (cur_color->indexUsed()) { a.append("Index", QString::number(cur_color->getIndex())); } +// qDebug() << "Checkpoint 32 reached."; if (!cur_color->getColorSpace().isNull()) { a.append("ColorSpace", QString::number(cur_color->getColorSpace().getRefID())); } //只有当Alpha值为非默认的255时才显示 +// qDebug() << "Checkpoint 33 reached."; if (cur_color->getAlpha() != 255) { a.append("Alpha", QString::number(cur_color->getAlpha())); } @@ -547,20 +614,26 @@ QXmlStreamAttributes getAttributes(CT_Color *cur_color) { return a; } -QXmlStreamAttributes getAttributes(CT_Text * cur_text) { +QXmlStreamAttributes getAttributes(CT_Text * cur_text) +{ +// qDebug() << "??"; QXmlStreamAttributes a; +// qDebug() << "???"; +// qDebug() << "cur_text->getFont().isNull(): " +// <getFont().isNull(); if (!cur_text->getFont().isNull()) { a.append("Font", QString::number(cur_text->getFont().getRefID())); } else { - throw WritingFormatException("CT_Text类型数据缺少必要的属性Font"); + qDebug("CT_Text类型数据缺少必要的属性Font"); } - - if (cur_text->sizeUsed()) { +// qDebug() << "cur_text size used: " << cur_text->sizeUsed(); +// qDebug() << "cur_text size: " << cur_text->getSize(); +// if (cur_text->sizeUsed()) { a.append("Size", QString::number(cur_text->getSize())); - } else { - throw WritingFormatException("CT_Text类型数据缺少必要的属性Size"); - } +// } else { +// qDebug() << "CT_Text类型数据缺少必要的属性Size"; +// } //Stroke属性不为默认值false时才显示 if (cur_text->getStroke()) { a.append("Stroke", "true"); @@ -620,7 +693,7 @@ QXmlStreamAttributes getAttributes(CT_Image * cur_image) { if (!cur_image->getResourceID().isNull()) { a.append("ResourceID", QString::number(cur_image->getResourceID().getRefID())); } else { - throw WritingFormatException("CT_Image类型数据缺少必要的属性ResourceID"); + qDebug("CT_Image类型数据缺少必要的属性ResourceID"); } if (!cur_image->getSubstitution().isNull()) { a.append("Substitution", QString::number(cur_image->getSubstitution().getRefID())); @@ -632,11 +705,14 @@ QXmlStreamAttributes getAttributes(CT_ColorSpace * cur_colorspace) { if (!cur_colorspace->getType().isNull()) { a.append("Type", cur_colorspace->getType()); } else { - throw WritingFormatException("CT_ColorSpace类型数据缺少必要的属性Type"); + qDebug("CT_ColorSpace类型数据缺少必要的属性Type"); } if (cur_colorspace->getBitsPerComponent() != 8) { a.append("BitsPerComponent", QString::number(cur_colorspace->getBitsPerComponent())); } +// qDebug() << "Colorspace Profile: " << cur_colorspace->getProfile(); +// qDebug() << "Colorspace Profile abs_path: " << cur_colorspace->getProfile().getPath(); +// qDebug() << "Colorspace Profile is NUll: " << cur_colorspace->getProfile().isNull(); if (!cur_colorspace->getProfile().isNull()) { ST_Loc p = cur_colorspace->getProfile(); a.append("Profile", p.getRelativePath()); @@ -673,12 +749,12 @@ QXmlStreamAttributes getAttributes(CT_DrawParam * cur_draw_param) { QXmlStreamAttributes getAttributes(CT_Font * cur_font) { QXmlStreamAttributes a; - if (!cur_font->getFontName().isNull()) { + if (cur_font->getFontName().length() != 0) { a.append("FontName", cur_font->getFontName()); } else { - throw WritingFormatException("CT_Font类型数据缺少必要的属性FontName"); + qDebug("CT_Font类型数据缺少必要的属性FontName"); } - if (!cur_font->getFamilyName().isNull()) { + if (cur_font->getFamilyName().length() != 0) { a.append("FamilyName", cur_font->getFamilyName()); } if (cur_font->getCharset() != "GB18030") { @@ -702,10 +778,10 @@ QXmlStreamAttributes getAttributes(CT_Font * cur_font) { void OFDWriter::makePath(ST_Loc path) { QString path_str = path.getPath(); int n = 0; - while (path_str[path_str.length() - n - 1] != '\\') + while (path_str[path_str.length() - n - 1] != '/') n++; path_str.chop(n); - //qDebug() << path_str; + qDebug() << path_str; if (!QDir().mkpath(path_str)) { throw WritingFileException("无法创建文件路径: " + path.getPath()); } diff --git a/ofdEditor/ofd/ofd_writer.h b/ofdEditor/ofd/ofd_writer.h index 9c62c45..6ea89ea 100644 --- a/ofdEditor/ofd/ofd_writer.h +++ b/ofdEditor/ofd/ofd_writer.h @@ -64,4 +64,5 @@ QXmlStreamAttributes getAttributes(CT_Path * cur_path); QXmlStreamAttributes getAttributes(CT_ColorSpace * cur_colorspace); QXmlStreamAttributes getAttributes(CT_DrawParam * cur_draw_param); QXmlStreamAttributes getAttributes(CT_Font * cur_font); +QXmlStreamAttributes getAttributes(CT_Text * cur_text); #endif // OFD_WRITER_H diff --git a/ofdEditor/start/ActionConnector/ActionConnector.cpp b/ofdEditor/start/ActionConnector/ActionConnector.cpp index 850f281..55008dd 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.cpp +++ b/ofdEditor/start/ActionConnector/ActionConnector.cpp @@ -22,6 +22,11 @@ ActionConnector::ActionConnector(PassageMainWindow *mainWindow) init(); } +DocPassage *ActionConnector::getActivedPassage() +{ + return this->passage; +} + void ActionConnector::showAttribute() { if(this->passage == NULL) diff --git a/ofdEditor/start/ActionConnector/ActionConnector.h b/ofdEditor/start/ActionConnector/ActionConnector.h index 4cb530d..10417f5 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.h +++ b/ofdEditor/start/ActionConnector/ActionConnector.h @@ -24,6 +24,7 @@ public: ActionConnector(PassageMainWindow * mainWindow); DocPage::Layer getDefaultLayer(){return this->defaultLayer;} + DocPassage *getActivedPassage(); // 获得活跃的文章 public slots: void showAttribute(); // 显示文档元信息 diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 1378185..b1fb1b2 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "Doc/DocPassage.h" @@ -28,6 +29,8 @@ #include "Doc/DocPage.h" #include "Doc/DocTextBlock.h" #include "Doc/DocImageBlock.h" +#include "Convert/Doc_OFDConvertor.h" +#include "ofd_writer.h" PassageMainWindow::PassageMainWindow(QWidget *parent) :QMainWindow(parent) @@ -82,8 +85,6 @@ void PassageMainWindow::init() QLabel * status = new QLabel(); this->statusBar()->addWidget(status); - - this->setMinimumSize(960,720); this->setBackgroundRole(QPalette::Text); @@ -272,6 +273,12 @@ void PassageMainWindow::connectAction() connect(this->openFileAtcion, SIGNAL(triggered(bool)), this, SLOT(openFile())); //打开文件 + connect(this->saveAction,SIGNAL(triggered(bool)), + this,SLOT(saveFile())); // 保存文件 + + connect(this->saveAsAction, SIGNAL(triggered(bool)), + this,SLOT(saveFileAs())); + connect(this->attributeAction, SIGNAL(triggered(bool)), this->connector, SLOT(showAttribute())); // 显示文档属性 @@ -356,15 +363,119 @@ void PassageMainWindow::openFile() OFDParser ofdParser(tempPath + "/OFD.xml"); // 新建临时路径 // OFDParser ofdParser("C:/Users/User/Desktop/表格/OFD.xml"); OFD* data = ofdParser.getData(); // 读取出OFD文件 + qDebug() << tempPath + "/OFD.xml"; + OFDWriter writer(data, "E:/temp/"); qDebug()<< "ofd file open"; OFD_DocConvertor convert; DocPassage* passage = convert.ofd_to_doc(data); + passage->setFilePath(path); // 设置文件路径 this->addDocPassage(passage); // 添加文章 } } +/** + * @Author Chaoqun + * @brief 文件保存测试 + * @param void + * @return void + * @date 2017/06/25 + */ +void PassageMainWindow::saveFile() +{ + + DocPassage* passage = this->connector->getActivedPassage(); + if(passage == NULL) + { + qDebug() << "Select NULL Passage"; + return; + } + QString filePath = passage->getFilePath(); // 获得文件路径 + if(filePath.size() == 0) + { + qDebug() << "passage filePath == 0"; + this->saveFileAs(); // 如果文件名不存在则使用另存为 + + return; + } + + Doc_OFDConvertor docToOfd; + OFD* ofdFile = docToOfd.doc_to_ofd(passage); + + QString tempPath = passage->getTempStorePath(); + ZipTool::deleteFolder(tempPath); // 删除文件夹 + QDir dir; + dir.mkdir(tempPath); // 生成文件夹 + OFDWriter writer(ofdFile, tempPath+"/"); // 写出文件 + + ZipTool::compressDir(filePath, + tempPath); // 将文件夹压缩为指定文件 + +} + +/** + * @Author Chaoqun + * @brief 文件另存为 + * @param void + * @return void + * @date 2017/06/26 + */ +void PassageMainWindow::saveFileAs() +{ + QFileDialog * fileDialog = new QFileDialog(this); // 新建一个QFileDialog + + fileDialog->setAcceptMode(QFileDialog::AcceptSave); // 设置对话框为保存文件类型 + fileDialog->setFileMode(QFileDialog::AnyFile); // 设置文件对话框能够显示任何文件 + fileDialog->setViewMode(QFileDialog::Detail); // 文件以细节形式显示出来 + fileDialog->setWindowTitle(tr("Save the passage content as a ofd file")); + + fileDialog->setNameFilter(tr("OFD files(*.ofd)")); // 设置文件过滤器 + if(fileDialog->exec() == QDialog::Accepted) + { + QString path = fileDialog->selectedFiles()[0]; // 用户选择文件名 + + + DocPassage* passage = this->connector->getActivedPassage(); + if(passage == NULL) + { + qDebug() << "Select NULL Passage"; + return; + } + + Doc_OFDConvertor docToOfd; + OFD* ofdFile = docToOfd.doc_to_ofd(passage); + + QString tempPath = passage->getTempStorePath(); + QDir dir; + if(dir.exists(tempPath)) + { + qDebug() << "the file is existing"; + // 如果文件夹已存在则要删除该文件夹 + ZipTool::deleteFolder(tempPath); // 删除文件夹 + } + + dir.mkdir(tempPath); // 生成文件夹 + OFDWriter writer(ofdFile, tempPath + "/"); // 写出文件 + + qDebug() << "temp Files Path:" << tempPath; + qDebug() << "selected ofd"<< path; + + bool flag = ZipTool::compressDir(path, + tempPath, false); // 将文件夹压缩为指定文件 + + if(flag == true) + { + passage->setFilePath(path); + } + else + { + qDebug() << "Save File Failed"; + } + } + +} + /** * @Author Chaoqun * @brief 打开字体框 diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index be5d0ec..be25681 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -79,6 +79,12 @@ private: QAction * aboutAppAction; // 关于本工程的介绍 QAction * helpAciton; // 帮助文档,如何使用本软件 + + // 工具栏部分 + QFontComboBox* fontCombox; // 字体选择框 + QComboBox* fontSizeCombox; // 字体大小设置框 + + QMdiArea * area; // 多窗口区域 QVectorpassages; // 存储所有的passage @@ -100,6 +106,8 @@ private: private slots: void openFile(); // 打开新文件 + void saveFile(); // 保存文件测试 + void saveFileAs(); // 将文件另存为 void fontDialog(); // 打开字体框 void paragraphDialog(); // 打开段落框 void imageDialog(); // 打开图片框 -- Gitee From 94762924401a7e4edff1406492b0969123f2d718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Tue, 27 Jun 2017 18:18:33 +0800 Subject: [PATCH 12/83] =?UTF-8?q?=E7=95=8C=E9=9D=A2=EF=BC=8C=E7=BF=BB?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocPage.cpp | 8 +- ofdEditor/model/Doc/DocPassage.h | 4 +- ofdEditor/model/Doc/DocTextBlock.h | 4 +- ofdEditor/model/model.pro | 2 + ofdEditor/start/icons.qrc | 9 + ofdEditor/start/main.cpp | 20 ++ ofdEditor/start/source/icons/attribute.png | Bin 0 -> 858 bytes ofdEditor/start/source/icons/bold.png | Bin 0 -> 646 bytes ofdEditor/start/source/icons/italic.png | Bin 0 -> 464 bytes ofdEditor/start/source/icons/justify.png | Bin 0 -> 484 bytes ofdEditor/start/source/icons/left.png | Bin 0 -> 393 bytes ofdEditor/start/source/icons/middle.png | Bin 0 -> 374 bytes ofdEditor/start/source/icons/pageFormat.png | Bin 0 -> 1108 bytes ofdEditor/start/source/icons/right.png | Bin 0 -> 381 bytes ofdEditor/start/source/icons/underline.png | Bin 0 -> 593 bytes ofdEditor/start/start.pro | 11 +- ofdEditor/start/ui/Editor.cpp | 14 + ofdEditor/start/ui/Editor.h | 22 ++ ofdEditor/start/ui/Editor.ui | 330 ++++++++++++++++++++ ofdEditor/start/ui/PassageMainWindow.cpp | 198 +++++++++++- ofdEditor/start/ui/PassageMainWindow.h | 22 +- 21 files changed, 617 insertions(+), 27 deletions(-) create mode 100644 ofdEditor/start/source/icons/attribute.png create mode 100644 ofdEditor/start/source/icons/bold.png create mode 100644 ofdEditor/start/source/icons/italic.png create mode 100644 ofdEditor/start/source/icons/justify.png create mode 100644 ofdEditor/start/source/icons/left.png create mode 100644 ofdEditor/start/source/icons/middle.png create mode 100644 ofdEditor/start/source/icons/pageFormat.png create mode 100644 ofdEditor/start/source/icons/right.png create mode 100644 ofdEditor/start/source/icons/underline.png create mode 100644 ofdEditor/start/ui/Editor.cpp create mode 100644 ofdEditor/start/ui/Editor.h create mode 100644 ofdEditor/start/ui/Editor.ui diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index b0785fe..ebb771c 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -166,10 +166,10 @@ void DocPage::addBlock(DocBlock *block, DocPage::Layer layer) emit this->signals_insertTextBlock(textBlock); // 发射信号 // 转发信号给passage - connect(textBlock,SIGNAL(signals_currentBlockFormatChanged(QTextBlockFormat&)), - passage,SIGNAL(signals_currentBlockFormatChanged(QTextBlockFormat&))); - connect(textBlock,SIGNAL(signals_currentCharFormatChanged(QTextCharFormat&)), - passage,SIGNAL(signals_currentCharFormatChanged(QTextCharFormat&))); + connect(textBlock,SIGNAL(signals_currentBlockFormatChanged(QTextBlockFormat)), + passage,SIGNAL(signals_currentBlockFormatChanged(QTextBlockFormat))); + connect(textBlock,SIGNAL(signals_currentCharFormatChanged(QTextCharFormat)), + passage,SIGNAL(signals_currentCharFormatChanged(QTextCharFormat))); connect(textBlock,SIGNAL(signals_currentTextBlock(DocTextBlock*)), passage,SIGNAL(signals_currentTextBlock(DocTextBlock*))); } else if (block->isImageBlock()) diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index cce08ce..551518e 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -148,9 +148,9 @@ signals: void signals_removeTextBlock(DocTextBlock* textBlock); // 用来转发信号 void signals_currentCharFormatChanged( - QTextCharFormat& fmt); // 当前选择的charFormat发生了变化 + QTextCharFormat fmt); // 当前选择的charFormat发生了变化 void signals_currentBlockFormatChanged( - QTextBlockFormat& fmt); // 当前选择的block格式发生了变化 + QTextBlockFormat fmt); // 当前选择的block格式发生了变化 void signals_currentTextBlock(DocTextBlock* textBlock); // 当前操作的textBlock void signals_currentImageBlock(DocImageBlock* imageBlock); //当前操作的imageBlock diff --git a/ofdEditor/model/Doc/DocTextBlock.h b/ofdEditor/model/Doc/DocTextBlock.h index 7e1a8d7..58a8e36 100644 --- a/ofdEditor/model/Doc/DocTextBlock.h +++ b/ofdEditor/model/Doc/DocTextBlock.h @@ -134,9 +134,9 @@ signals: void signals_setZValue(qreal z); // 设置Z值的信号 void signals_currentCharFormatChanged( - QTextCharFormat& fmt); // 当前选择的charFormat发生了变化 + QTextCharFormat fmt); // 当前选择的charFormat发生了变化 void signals_currentBlockFormatChanged( - QTextBlockFormat& fmt); // 当前选择的block格式发生了变化、 + QTextBlockFormat fmt); // 当前选择的block格式发生了变化、 void signals_currentTextBlock(DocTextBlock* textBlock); // 当前操作的textBlock }; diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index 19a8a52..2f54626 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -95,6 +95,8 @@ MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 RCC_DIR = ./rcc # .qrc 文件转换后存放路径 OBJECTS_DIR += ./tmp # .obj 文件存放路径 +TRANSLATIONS = cn_model.ts + INCLUDEPATH += $$PWD/../ofd \ $$PWD/../model diff --git a/ofdEditor/start/icons.qrc b/ofdEditor/start/icons.qrc index 75225fb..f7036a8 100644 --- a/ofdEditor/start/icons.qrc +++ b/ofdEditor/start/icons.qrc @@ -20,5 +20,14 @@ source/icons/tableFormat.png source/icons/TextFormat.png source/icons/undo.png + source/icons/attribute.png + source/icons/bold.png + source/icons/italic.png + source/icons/justify.png + source/icons/left.png + source/icons/middle.png + source/icons/pageFormat.png + source/icons/right.png + source/icons/underline.png diff --git a/ofdEditor/start/main.cpp b/ofdEditor/start/main.cpp index a2ae2ba..8a9f257 100644 --- a/ofdEditor/start/main.cpp +++ b/ofdEditor/start/main.cpp @@ -3,9 +3,29 @@ #include "ui/PassageMainWindow.h" #include #include <../ofd/ofdexceptions.h> +#include + int main(int argc, char *argv[]) { QApplication a(argc, argv); + + QTranslator model_translator; + if(model_translator.load("cn_model.qm")) + { + a.installTranslator(&model_translator); + } + QTranslator start_translator; + if(start_translator.load("cn_start.qm")) + { + a.installTranslator(&start_translator); + } + + QTranslator qt_translator; + if(qt_translator.load("qt_zh_CN.qm")) + { + a.installTranslator(&qt_translator); + } + PassageMainWindow w; w.show(); diff --git a/ofdEditor/start/source/icons/attribute.png b/ofdEditor/start/source/icons/attribute.png new file mode 100644 index 0000000000000000000000000000000000000000..fcb10c5c50a247c587aeef22121ae4be07803cdf GIT binary patch literal 858 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5Sk21sKV*~UvzEKMeFsnzQ^h=35ItENU_fG?3#wC}DVGiDA>N zC0i%R%y_hm`&yGG^R#JAr9P>-0YQ;BS`}92uz0%cJ*1|z@`)3R`O&v$&;Cn!wok>l zC}n?c+Wq{pdFAbQe|}@nvnbMxnwTy!=fbNug_*Am4oEeA&h2e1skzF$XJ_c-AENy~ z8XBf*)EzXoQ%G3Ys(+WkPGP|nlMQkcPy4-VaGRpMD8_^s;WXLD zjA^F#EDp?36S0-h$l9~h#$|!Mjl>1XqkGsF7#cClCM0O?iA$gIDPYSj-J8B4Ti(TP zyfa~1_OW>d2W7i@Z!UeRwM|lEX@>BjNWGbp%$VI*UENi^y_K!c$8&aLapB5ehv$oGR2t8ak_2KS{xy!Ew>!L|_6`Epd$~Nl7e8wMs5Z z1yT$~28QOk24=cO<{^eAR;HF##s=C37FGrZ24#v~C>nC}Q!>*kacgkYp7{-^fx*+& K&t;ucLK6V)xmsNS literal 0 HcmV?d00001 diff --git a/ofdEditor/start/source/icons/bold.png b/ofdEditor/start/source/icons/bold.png new file mode 100644 index 0000000000000000000000000000000000000000..daa1049c4bf0c89cb0f3dfb520a8bc85ed7a51cb GIT binary patch literal 646 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5Sk21sKV*~UvzEKMeFsnzW1pvsV@Srmx6^lfF*}O1?O$W&*|8ugIaN6+K;TH!K`&Qs zX>Dn5>G_H`elXZI=F-D1DR-004xycWT&+2bB3-R(7)7)rnKh0rIyK9-MSM&3 zIq?|@ThhNwcxobJ@!vGNZQ1!|!QBiGE?y{_e&}>nP|f{Uo7Nt^yp8dJUw7LZ=9-L) z-L(yi#O~f;pK*DS@ybnw_nU0i+Z$O2rY@D8@jNcN&1{k03-g?kJH|mtU3T|x=$Y=^ zsT$8-_GFei`wAny+xLz%2CHpm4bU)Kd}@~N@%~21=ElX@Ax~vFe)FyQ^q_cQia3J} z-jUbZm(?Y`-6nGbm0IkJV}-exw9|9e~FJ>?GVdGEUAO~dhhV%OhV zZSc5l{{Mn)?o0aF)eC27U z*mRQ>#oCtT>OinO2OC7#SFv>l&Ep8kvU} vnpl}yS{WN?8(3Hw7#Nf(dZB2@%}>cptHiCrQG4b$paup{S3j3^P6NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5Sk21sKV*~UvzEKMeFsnz!wpXt$B>MBZ)a@eJ!~Mr{B+F%&pjS(-exD2Hm&=l zAgXqk^TY20_A3gqJtwK0yt{eoeT$pJs;vLdyMBl5+ruZu;twq6$ZTc& zTK&NM@!EhnFHA4APcAQQVNZ~Lz;uIc2j3003SI`b3Wf$oIfjIW=Rka!A*q46LE-^} z0-FV&0^18-2euas6Bw-+QX1X?@hyh52CfFl1xyKSD`p?&xgf>Bdx61$*@WQ&LvHy3 zMla?Sj9d&^4NMJE1*z2^>=pMjS};cNO;GWiq;p%fwqB#m4SglnW7hphTQy=%(P0}8XUD}egkS? N@O1TaS?83{1OPrNkjDT3 literal 0 HcmV?d00001 diff --git a/ofdEditor/start/source/icons/justify.png b/ofdEditor/start/source/icons/justify.png new file mode 100644 index 0000000000000000000000000000000000000000..3bd70a0f743033892358758c83ad917383e70577 GIT binary patch literal 484 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5Sk21sKV*~UvzEKMeFsnz!y8W*$B>MBZ)a@uV{(*evG4tMN3}g{LdN048Oj%Lxd}79 zPvM`)#eqZ9OK?@blhd^^qZHkbdLV&%>9A9aB0>KzWb+-MHIRM8M#D9UfXO|(k>Mc4X0!onJVdrtrz zsM%@%N+-2-%gfGVK!2;2xJHzuB$lLFB^RXvDF!10LvvjNGhHL|5JM9yQ%fsj18oBf lD+2?AGDR;G4Y~O#nQ4`{H8^U|{07v(;OXk;vd$@?2>|yatF-_C literal 0 HcmV?d00001 diff --git a/ofdEditor/start/source/icons/left.png b/ofdEditor/start/source/icons/left.png new file mode 100644 index 0000000000000000000000000000000000000000..af36917c385c21e4cbc478bd80b4f9af02dca8da GIT binary patch literal 393 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5Sk21sKV*~UvzEKMeFsnz!$eOP$B>MBZ?75hIXDQkK2+73Uc@}TfSbKQQ9ZzG%DROi zni?)fQx&rBiTz(b^Vm6_lgdD+32m~DJABn7JpU|1>&ooo`({@aD#*@UIlJR|Ut(Q- z@R>FBb2LAxq%bfPeT&{;^=+QrmswJ)wB`Jv|saDBFsX&Us$iUEC*T78I$UMZ* v#LCpt%Gf~Lz{1MFz@SXg3q?b2eoAIqC2kFl+B3faH86O(`njxgN@xNA1Au+9 literal 0 HcmV?d00001 diff --git a/ofdEditor/start/source/icons/middle.png b/ofdEditor/start/source/icons/middle.png new file mode 100644 index 0000000000000000000000000000000000000000..3702908896773419626fdbcd0a52e261b18cb024 GIT binary patch literal 374 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5Sk21sKV*~UvzEKMeFsnzL!GCKV@Srmx7Q818Vq<^A1dtqzt*OuyW=ja;PR$Yfl@;e z6%*(G>%A8q_MSGSgMpzSS|!}}ujuW{@4k!=cdACNR+GQCmRY0g*k=2><2(GFxHw*& zR@D^te2BmLJVcZq}n@(1In||f46T_c_aTmN8f5jP`$e1-{Pc$oohF_V_*$TPu zA@hMQQ7v(eC`m~yNwrEYN(E93Mh1rFx&~&tM&==gCRV1FR>lU}1{PKZ1_ot{UML!J b^HVa@DsgLY)SmebsDZ)L)z4*}Q$iB}tbKQV literal 0 HcmV?d00001 diff --git a/ofdEditor/start/source/icons/pageFormat.png b/ofdEditor/start/source/icons/pageFormat.png new file mode 100644 index 0000000000000000000000000000000000000000..ca21c418b03a2f8e158922d75f666b05970d759a GIT binary patch literal 1108 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5SkVOQ!_~>REKp$zieQzHHyQb%PT%|065Ht(k0^KdE5O`zat!PD-S$e*l3XWOyjEX1-Ts!C0!wB zJ-2;wKV7@?(7O2O116WNj(D(rJAS1@Uvg8Xvd;`B1|iAR8Ed^fZ7`$5@(EA>nFa_jF*PV4M_ z^^QI}blx~%RZgw?ifps@Eb-mDgfH5}c}kpp#xnm5BWL=Z{S8iuucyyQHE-5bEN;H9 zXrZ{~Z1SnF&oh}6Hy^ZQ&g!TNReczyQT#H{!E%05jGEUD#hncAoiF%{-4?5HEdA(y zXzpV#pV;~Fi~?yB7Ek+R%vye>$lhD{Wr!P>XN9|2@0@K@Lg#M$_vp%pgnbWU4|spd zH9g8z*7@|GTiJc zmN`!g1tc59cHMB|kht=ql>2$_?y8B#`b>*Fu6tE$P4Hv4ee_q{o+)Z8%bOtUkID}3 z555+ix#}9z-}=KRU$9T>bTV4w&BriR=Xv{Vo)uM_1vuY4*}C*A>!P3gFTWLd!QHW- zgK_azk%nNk-Tgr~kIk>;So3<@v1_-Ocs4iN_-$%pWZ0GQ*t-4Y!_|G2B~pLWJ2*J% zru#^LyrnLa-V=6ePUpv)nrqGW@L2{w-WVPuu>03af&F(s{obXvT_=Cn{Lf87w<{aJ z-3+er^D*0fah`+wf`junT&ra&-YMwufphLole*_^{G8QW;toA}r0*fa_|5l4@-|>b zR4s9hC`m~yNwrEYN(E93Mh1rFx&~&tM&==gCRV1FR>lU}1{PKZ1_ot{UML!J^HVa@ XDsgLY)SmebsDZ)L)z4*}Q$iB}1jOMz literal 0 HcmV?d00001 diff --git a/ofdEditor/start/source/icons/right.png b/ofdEditor/start/source/icons/right.png new file mode 100644 index 0000000000000000000000000000000000000000..02cdf95147955235f45fd858d7ea002d791d18eb GIT binary patch literal 381 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5Sk21sKV*~UvzEKMeFsnzL#wBYV@Srmx7RlEHW=`@1U9coVDu_moW{tO!0onZky{TF zYp`CXQv*^rbWKam(`8U(K=4n(dGfT#ux~f`1hNdNdE0PbM%Jyqm{paG- zxf2)|p44dDt>IsD$F_SuXLk1Ee206SPZ|FR=WJX3n4x}(ndo^|ZGB5diPQTffUcL8 zGv;t!Il03W=pfY+*NBpo#FA92NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5Sk21sKV*~UvzEKMeFsnzW2C2xV@Srmx6}4|F*}O1?q4w@gD2v4hoi_*vjtnlrY)M< zV$+~M;oLnx6BeDE8vbbM+z^9Uoh=={T;3nkb;FLGe3w&p?T*GF+wD6yq(7@Me)EQJ zMTpi^ucwO-gq%D5|I5=l@9lkmzTOgXV1%Q8oCj9F{If1)^2S1DrV`)qF9pvvjvnLX zxL|g7Py27_PjOrij+N||dzX4Sw)*V5g|kWx^_T8C-?LqdbwdWD%#w=J)5;yW63)yr zNm$*#+2eRopBLkSI{rg(P1)1jPlrzLZhtA)(2!oHbiYM(mf-m*DhxSp%lKEH71gzq z@efOV%(%*rrF`w_^iW&qTB1 z{R*$8K`T?fa9WGY$Uc_4*#r!C)e_f;l9a@fRIB8oR3OD*WMF8nYhb2pWFBH@Vr6P+ rWo)2rU}0roU{I#$g`y!hKP5A*61N6N?U~setupUi(this); +} + +Editor::~Editor() +{ + delete ui; +} diff --git a/ofdEditor/start/ui/Editor.h b/ofdEditor/start/ui/Editor.h new file mode 100644 index 0000000..97482ef --- /dev/null +++ b/ofdEditor/start/ui/Editor.h @@ -0,0 +1,22 @@ +#ifndef EDITOR_H +#define EDITOR_H + +#include + +namespace Ui { +class Editor; +} + +class Editor : public QMainWindow +{ + Q_OBJECT + +public: + explicit Editor(QWidget *parent = 0); + ~Editor(); + +private: + Ui::Editor *ui; +}; + +#endif // EDITOR_H diff --git a/ofdEditor/start/ui/Editor.ui b/ofdEditor/start/ui/Editor.ui new file mode 100644 index 0000000..8a0e476 --- /dev/null +++ b/ofdEditor/start/ui/Editor.ui @@ -0,0 +1,330 @@ + + + Editor + + + + 0 + 0 + 800 + 600 + + + + MainWindow + + + QMainWindow::AllowTabbedDocks|QMainWindow::AnimatedDocks + + + + + + 0 + 0 + 800 + 23 + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + + + + + false + + + QDockWidget::NoDockWidgetFeatures + + + Qt::TopDockWidgetArea + + + 4 + + + + + + 0 + 0 + 189 + 22 + + + + + + + 190 + 0 + 69 + 22 + + + + + + + + + :/icons/source/icons/newFile.png + + + + 新建文件 + + + Ctrl+N + + + + + + :/icons/source/icons/openFile.png + + + + 打开文件 + + + Ctrl+O + + + + + + :/icons/source/icons/save.png + + + + 保存 + + + Ctrl+S + + + + + + :/icons/source/icons/saveAs.png + + + + 另存为 + + + Ctrl+Shift+S + + + + + + :/icons/source/icons/print.png + + + + 打印 + + + Ctrl+P + + + + + 文档属性 + + + + + + :/icons/source/icons/undo.png + + + + 撤销 + + + Ctrl+Z + + + + + + :/icons/source/icons/redo.png + + + + 重做 + + + Ctrl+Shift+Z + + + + + + :/icons/source/icons/copy.png + + + + 复制 + + + Backspace + + + + + + :/icons/source/icons/paste.png + + + + 粘贴 + + + + + + :/icons/source/icons/cut.png + + + + 剪切 + + + + + + :/icons/source/icons/insertNewPage.png + + + + 插入新页 + + + + + + :/icons/source/icons/insertTextBlock.png + + + + 插入文本框 + + + + + + :/icons/source/icons/insertImage.png + + + + 插入图片 + + + + + + :/icons/source/icons/insertTable.png + + + + 插入表格 + + + + + 页面设置 + + + + + + :/icons/source/icons/TextFormat.png + + + + 字体 + + + + + + :/icons/source/icons/paragraphFormat.png + + + + 段落 + + + + + + :/icons/source/icons/ImageFormat.png + + + + 图片设置 + + + + + + :/icons/source/icons/tableFormat.png + + + + 表格设置 + + + + + + :/icons/source/icons/AboutQpp.png + + + + 关于Qt + + + + + + :/icons/source/icons/help.png + + + + 关于本工程 + + + + + true + + + 加粗 + + + + + + diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index b1fb1b2..e1fc8e3 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -170,7 +170,7 @@ void PassageMainWindow::initAction() this->pageFormat = new QAction(tr("Page Format"), NULL); // 页面格式 this->pageFormat->setStatusTip(tr("Set the page format")); - //this->textFormat->setIcon(QIcon()); + this->pageFormat->setIcon(QIcon(":/icons/source/icons/pageFormat.png")); this->textFormat = new QAction(tr("Text Format"),NULL); // 文字格式 this->textFormat->setStatusTip(tr("Set the selected texts' format")); @@ -233,11 +233,107 @@ void PassageMainWindow::initAction() this->aboutMenu->addAction(this->aboutAppAction); this->aboutMenu->addAction(this->helpAciton); + // 文本操作工具栏部分/ + this->fontCombox = new QFontComboBox(); + this->fontSizeCombox = new QComboBox(); + this->fontSizeCombox->insertItem(0,tr("72")); + this->fontSizeCombox->insertItem(0,tr("48")); + this->fontSizeCombox->insertItem(0,tr("36")); + this->fontSizeCombox->insertItem(0,tr("28")); + this->fontSizeCombox->insertItem(0,tr("26")); + this->fontSizeCombox->insertItem(0,tr("24")); + this->fontSizeCombox->insertItem(0,tr("22")); + this->fontSizeCombox->insertItem(0,tr("20")); + this->fontSizeCombox->insertItem(0,tr("18")); + this->fontSizeCombox->insertItem(0,tr("16")); + this->fontSizeCombox->insertItem(0,tr("14")); + this->fontSizeCombox->insertItem(0,tr("12")); + this->fontSizeCombox->insertItem(0,tr("11")); + this->fontSizeCombox->insertItem(0,tr("10.5")); + this->fontSizeCombox->insertItem(0,tr("10")); + this->fontSizeCombox->insertItem(0,tr("9")); + this->fontSizeCombox->insertItem(0,tr("8")); + this->fontSizeCombox->insertItem(0,tr("7.5")); + this->fontSizeCombox->insertItem(0,tr("6.5")); + this->fontSizeCombox->insertItem(0,tr("5.5")); + this->fontSizeCombox->insertItem(0,tr("5")); + this->fontSizeCombox->insertItem(0,tr("4.5")); + this->fontSizeCombox->insertItem(0,tr("5.25")); + this->fontSizeCombox->insertItem(0,tr("6.5")); + this->fontSizeCombox->insertItem(0,tr("7.5")); + this->fontSizeCombox->insertItem(0,tr("9")); + this->fontSizeCombox->insertItem(0,tr("10.5")); + this->fontSizeCombox->insertItem(0,tr("12")); + this->fontSizeCombox->insertItem(0,tr("14")); + this->fontSizeCombox->insertItem(0,tr("15")); + this->fontSizeCombox->insertItem(0,tr("16")); + this->fontSizeCombox->insertItem(0,tr("18")); + this->fontSizeCombox->insertItem(0,tr("21")); + this->fontSizeCombox->insertItem(0,tr("24")); + this->fontSizeCombox->insertItem(0,tr("27.5")); + this->fontSizeCombox->insertItem(0,tr("36")); + this->fontSizeCombox->insertItem(0,tr("42")); + + + + // 加粗 + this->boldAction = new QAction(tr("Bold"), NULL); + this->boldAction->setStatusTip(tr("Set selected text Bold or not bold")); + this->boldAction->setIcon(QIcon(":/icons/source/icons/bold.png")); + this->boldAction->setCheckable(true); + + // 倾斜 + this->italicAction = new QAction(tr("Italic"), NULL); + this->italicAction->setStatusTip(tr("Set the selected text Italic")); + this->italicAction->setIcon(QIcon(":/icons/source/icons/italic.png")); + this->italicAction->setCheckable(true); + + // 下划线 + this->underlineAction = new QAction(tr("Underline" ),NULL); + this->underlineAction->setStatusTip( + tr("Set the selected text underline")); + this->underlineAction->setIcon(QIcon(":/icons/source/icons/underline.png")); + this->underlineAction->setCheckable(true); + + // 居中 + this->middleAction = new QAction(tr("middle"),NULL); + this->middleAction->setStatusTip( + tr("Set the selected paragraph align middle")); + this->middleAction->setIcon(QIcon(":/icons/source/icons/middle.png")); + this->middleAction->setCheckable(true); + + // 左对齐 + this->leftAction = new QAction(tr("Left"),NULL); + this->leftAction->setStatusTip( + tr("Set the selected paragraph align by left")); + this->leftAction->setIcon(QIcon(":/icons/source/icons/left.png")); + this->leftAction->setCheckable(true); + + + // 右对齐 + this->rightAction = new QAction(tr("Right"),NULL); + this->rightAction->setStatusTip( + tr("Set the selected paragraph align by right")); + this->rightAction->setIcon(QIcon(":/icons/source/icons/right.png")); + this->rightAction->setCheckable(true); + + // 两端对齐 + this->justifyAction = new QAction(tr("jutify"),NULL); + this->justifyAction->setStatusTip( + tr("Set the selected paragraph align by left and right")); + this->justifyAction->setIcon(QIcon(":/icons/source/icons/justify.png")); + this->justifyAction->setCheckable(true); + + /*---------------------------------------------------------------------*/ this->file_toolBar = this->addToolBar(tr("File")); + this->file_toolBar->setMovable(false); this->edit_toolBar = this->addToolBar(tr("Edit")); + this->edit_toolBar->setMovable(false); this->format_toolBar = this->addToolBar(tr("Format")); + this->format_toolBar->setMovable(false); this->insert_toolBar = this->addToolBar(tr("Insert")); + this->insert_toolBar->setMovable(false); this->file_toolBar->addAction(this->newFileAction); this->file_toolBar->addAction(this->openFileAtcion); @@ -256,6 +352,22 @@ void PassageMainWindow::initAction() this->insert_toolBar->addAction(this->insertImageAction); this->insert_toolBar->addAction(this->insertTableAction); + + // 添加工具栏 + this->textBlock_toolBar = this->addToolBar(tr("TextBlock")); + this->textBlock_toolBar->setMovable(false); + this->textBlock_toolBar->addWidget(this->fontCombox); // 字体选择 + this->textBlock_toolBar->addWidget(this->fontSizeCombox); // 字体大小设置 + this->textBlock_toolBar->addSeparator(); // 分隔符 + this->textBlock_toolBar->addAction(this->boldAction); // 字体加粗 + this->textBlock_toolBar->addAction(this->italicAction); // 斜体 + this->textBlock_toolBar->addAction(this->underlineAction); // 下划线 + this->textBlock_toolBar->addSeparator(); // 分隔符 + this->textBlock_toolBar->addAction(this->leftAction); // 左对齐 + this->textBlock_toolBar->addAction(this->middleAction); // 居中 + this->textBlock_toolBar->addAction(this->rightAction); // 居右 + this->textBlock_toolBar->addAction(this->justifyAction); // 两端对齐 + } /** @@ -541,11 +653,44 @@ void PassageMainWindow::acceptTextBlock(DocTextBlock *textBlock) * @return void * @date 2017/06/23 */ -void PassageMainWindow::acceptTextBlockFormat(QTextBlockFormat &blockFormat) +void PassageMainWindow::acceptTextBlockFormat(QTextBlockFormat blockFormat) { - this->_currentBlockFormat = &blockFormat; // 留下引用 + this->_currentBlockFormat = blockFormat; // 留下引用 + qDebug() << "PassageMainWindow::acceptTextBlockFormat(QTextBlockFormat blockFormat)"; // 更新界面显示 + Qt::Alignment align = blockFormat.alignment() & Qt::AlignHorizontal_Mask; + switch (align) + { + case Qt::AlignHCenter: + this->middleAction->setChecked(true); + this->leftAction->setChecked(false); + this->rightAction->setChecked(false); + this->justifyAction->setChecked(false); + break; + case Qt::AlignLeft: + this->middleAction->setChecked(false); + this->leftAction->setChecked(true); + this->rightAction->setChecked(false); + this->justifyAction->setChecked(false); + break; + case Qt::AlignRight: + this->middleAction->setChecked(false); + this->leftAction->setChecked(false); + this->rightAction->setChecked(true); + this->justifyAction->setChecked(false); + break; + case Qt::AlignJustify: + this->middleAction->setChecked(false); + this->leftAction->setChecked(false); + this->rightAction->setChecked(false); + this->justifyAction->setChecked(true); + break; + default: + break; + } + + } /** @@ -555,10 +700,45 @@ void PassageMainWindow::acceptTextBlockFormat(QTextBlockFormat &blockFormat) * @return void * @date 2017/06/23 */ -void PassageMainWindow::acceptTextCharFormat(QTextCharFormat &charFormat) +void PassageMainWindow::acceptTextCharFormat(QTextCharFormat charFormat) { - this->_currentCharFormat = &charFormat; // 留下引用 + this->_currentCharFormat = charFormat; // 留下引用 // 更新界面显示 + + // 字体 + this->fontCombox->setCurrentFont(charFormat.font()); + + // 粗体 + if(charFormat.fontWeight() >= 75) + { + this->boldAction->setChecked(true); + } + else + { + this->boldAction->setChecked(false); + } + + // 斜体 + if(charFormat.fontItalic()) + { + this->italicAction->setChecked(true); + } + else + { + this->italicAction->setChecked(false); + } + + // 下划线 + if(charFormat.fontUnderline()) + { + this->underlineAction->setChecked(true); + } + else + { + this->underlineAction->setChecked(false); + } + + // 字号 } void PassageMainWindow::acceptImageBlock(DocImageBlock *imageBlock) @@ -603,11 +783,11 @@ DocPassage *PassageMainWindow::addDocPassage(DocPassage *passage) passage->showMaximized(); // 处理变更的blockFormat - this->connect(passage,SIGNAL(signals_currentBlockFormatChanged(QTextBlockFormat&)), - this,SLOT(acceptTextBlockFormat(QTextBlockFormat&))); + this->connect(passage,SIGNAL(signals_currentBlockFormatChanged(QTextBlockFormat)), + this,SLOT(acceptTextBlockFormat(QTextBlockFormat))); // 处理变更的charFormat - this->connect(passage,SIGNAL(signals_currentCharFormatChanged(QTextCharFormat&)), - this,SLOT(acceptTextCharFormat(QTextCharFormat&))); + this->connect(passage,SIGNAL(signals_currentCharFormatChanged(QTextCharFormat)), + this,SLOT(acceptTextCharFormat(QTextCharFormat))); // 处理变更的textBlock this->connect(passage,SIGNAL(signals_currentTextBlock(DocTextBlock*)), this,SLOT(acceptTextBlock(DocTextBlock*))); diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index be25681..cfbf954 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -6,14 +6,14 @@ #include #include // 字体框 #include // 选择框 +#include +#include class QAction; class QMenu; class QMdiArea; class DocPassage; class DocTextBlock; -class QTextCharFormat; -class QTextBlockFormat; class ActionConnector; // 函数功能的中间件 class DocImageBlock; @@ -43,6 +43,7 @@ private: QToolBar* edit_toolBar; // 编辑 QToolBar* format_toolBar; // 格式 QToolBar* insert_toolBar; // 插入 + QToolBar* textBlock_toolBar; // 文本工具栏 // QAction @@ -80,10 +81,17 @@ private: QAction * helpAciton; // 帮助文档,如何使用本软件 - // 工具栏部分 + // 文本操作工具栏部分 QFontComboBox* fontCombox; // 字体选择框 QComboBox* fontSizeCombox; // 字体大小设置框 + QAction* boldAction; // 字体粗细 + QAction* italicAction; // 斜体 + QAction* underlineAction; // 下划线 + QAction* middleAction; // 居中 + QAction* leftAction; // 居左 + QAction* rightAction; // 居右 + QAction* justifyAction; // 两端对齐 QMdiArea * area; // 多窗口区域 QVectorpassages; // 存储所有的passage @@ -97,8 +105,8 @@ private: void disconnectAction(); // 断开事件响应 DocTextBlock *textBlock; // 文字块 - QTextCharFormat* _currentCharFormat; // 当前字符格式 - QTextBlockFormat* _currentBlockFormat; // 当前块格式 + QTextCharFormat _currentCharFormat; // 当前字符格式 + QTextBlockFormat _currentBlockFormat; // 当前块格式 DocImageBlock *imageBlock; //图片块 @@ -114,8 +122,8 @@ private slots: void pageDialog(); // 打开页面框 void acceptTextBlock(DocTextBlock* textBlock); // 接受当前处理的文字块的更新 - void acceptTextBlockFormat(QTextBlockFormat& blockFormat); // 接受当前处理的块格式 - void acceptTextCharFormat(QTextCharFormat& charFormat); // 接受当前处理的字符格式 + void acceptTextBlockFormat(QTextBlockFormat blockFormat); // 接受当前处理的块格式 + void acceptTextCharFormat(QTextCharFormat charFormat); // 接受当前处理的字符格式 void acceptImageBlock(DocImageBlock * imageBlock); //接受当前处理的图片块 }; -- Gitee From f0893924636a36fab9c8eefb81f0f86962fbfc00 Mon Sep 17 00:00:00 2001 From: Pan Yanxing Date: Tue, 27 Jun 2017 20:04:33 +0800 Subject: [PATCH 13/83] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20=E6=9F=A5=E8=AF=A2/?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocTextBlock.cpp | 2 +- ofdEditor/model/Doc/DocTextBlock.h | 2 +- ofdEditor/model/Widget/FindAndReplaceDock.cpp | 379 ++++++++++++++++++ ofdEditor/model/Widget/FindAndReplaceDock.h | 49 +++ ofdEditor/model/Widget/FindAndReplaceDock.ui | 231 +++++++++++ ofdEditor/model/model.pro | 9 +- .../start/ActionConnector/ActionConnector.cpp | 11 + .../start/ActionConnector/ActionConnector.h | 5 +- ofdEditor/start/ui/PassageMainWindow.cpp | 24 ++ ofdEditor/start/ui/PassageMainWindow.h | 8 + 10 files changed, 713 insertions(+), 7 deletions(-) create mode 100644 ofdEditor/model/Widget/FindAndReplaceDock.cpp create mode 100644 ofdEditor/model/Widget/FindAndReplaceDock.h create mode 100644 ofdEditor/model/Widget/FindAndReplaceDock.ui diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 6368d1d..8df2599 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -112,7 +112,7 @@ DocBlock *DocTextBlock::getBlock() * @return QString & * @date 2017/06/25 */ -QString &DocTextBlock::getContent() +QString DocTextBlock::getContent() { QString content = this->document()->toPlainText(); // 获得纯文本 return content; diff --git a/ofdEditor/model/Doc/DocTextBlock.h b/ofdEditor/model/Doc/DocTextBlock.h index 7e1a8d7..5d54078 100644 --- a/ofdEditor/model/Doc/DocTextBlock.h +++ b/ofdEditor/model/Doc/DocTextBlock.h @@ -33,7 +33,7 @@ public: DocPage* getPage(); // 获得页 DocLayer* getLayer(); // 获得层 DocBlock* getBlock(); // 获得Block - QString& getContent(); // 获得TextBlock中的所有文本 + QString getContent(); // 获得TextBlock中的所有文本 int getContentLength(); // 获得内部文字长度 public slots: diff --git a/ofdEditor/model/Widget/FindAndReplaceDock.cpp b/ofdEditor/model/Widget/FindAndReplaceDock.cpp new file mode 100644 index 0000000..3d226da --- /dev/null +++ b/ofdEditor/model/Widget/FindAndReplaceDock.cpp @@ -0,0 +1,379 @@ +#include "FindAndReplaceDock.h" +#include "ui_FindAndReplaceDock.h" +#include "../model/Doc/DocPassage.h" +#include "../model/Doc/DocPage.h" +#include "../model/Doc/DocLayer.h" +#include "../model/Doc/DocBlock.h" +#include "../model/DOc/DocTextBlock.h" +#include +#include +#include +#include + +FindAndReplaceDock::FindAndReplaceDock(QWidget *parent) : + QDockWidget(parent), + ui(new Ui::FindAndReplaceDock) +{ + ui->setupUi(this); + //初始化成员 + count = 0; + ui->CountLineEdit->setText("0"); + ui->CountLineEdit->setEnabled(false); + + ui->ReplaceButton->setEnabled(false); + ui->ReplaceAllButton->setEnabled(false); + //建立信号槽 + this->connect(ui->FindLineEdit, + SIGNAL(textChanged(QString)), + this, + SLOT(on_FindLineEdit_textChanged(QString))); + qDebug() << "Finished constructing FindAndReplaceDock"; + this->connect(ui->CountLineEdit, + SIGNAL(textChanged(QString)), + this, + SLOT(on_CountLineEdit_textChanged(QString))); + this->connect(ui->FindNextButton, + SIGNAL(clicked(bool)), + this, + SLOT(locateNextPlace())); + this->connect(ui->FindPreviousButton, + SIGNAL(clicked(bool)), + this, + SLOT(locatePreviousPlace())); + this->connect(ui->ReplaceButton, + SIGNAL(clicked(bool)), + this, + SLOT(replaceText())); + this->connect(ui->ReplaceAllButton, + SIGNAL(clicked(bool)), + this, + SLOT(replaceAll())); +} + + +FindAndReplaceDock::~FindAndReplaceDock() +{ + delete ui; +} + +/** + * @Author Pan + * @brief 设置当前活动的文档 + * @param DocPassage *current_passage + * @return void + * @date 2017/06/27 + */ +void FindAndReplaceDock::setCurrentPassage(DocPassage *current_passage) +{ + passage = current_passage; +} + +/** + * @Author Pan + * @brief 查找文本框的内容有改变后,就重新开始Find + * @param const QString &arg1 + * @return void + * @date 2017/06/27 + */ +void FindAndReplaceDock::on_FindLineEdit_textChanged(const QString &arg1) +{ + blocks_found.clear(); + blocks_flag.clear(); + count = 0; + + if (arg1.length() > 0) + findAllTargetTextBlock(arg1); + if (blocks_found.size() == 0) + { + ui->ReplaceButton->setEnabled(false); + ui->ReplaceAllButton->setEnabled(false); + } + else { + ui->ReplaceButton->setEnabled(true); + ui->ReplaceAllButton->setEnabled(true); + } + if (blocks_found.size() == 0) + { + ui->CountLineEdit->setText(QString::number(count)); + } + else + { + this->current_block_index = -1; + this->current_block_pos = -1; + ui->CountLineEdit->setText(QString::number(count)); + locateNextPlace(); + } +} + +/** + * @Author Pan + * @brief 找到所有包含目标字符串的DocTextBlock,并放到blocks_found容器中 + * @param const QString & str + * @return void + * @date 2017/06/27 + */ +void FindAndReplaceDock::findAllTargetTextBlock(const QString & str) +{ +// qDebug() << "Start finding all target blocks"; + for (int i = 0; i < passage->getPages().size(); i++) + { + DocPage * cur_page = passage->getPages()[i]; + DocLayer * foreground_layer = cur_page->getForegroundLayer(); + DocLayer * body_layer = cur_page->getBodyLayer(); + DocLayer * background_layer = cur_page->getBackgroundLayer(); + for (int j = 0; j < foreground_layer->getBlocks()->size(); j++) + { + DocBlock * cur_block = foreground_layer->getBlocks()->operator [](j); + if (cur_block->isTextBlock()) + { + if (cur_block->getTextBlock() + ->getContent().contains(str)) + { + blocks_found.push_back(cur_block->getTextBlock()); + blocks_flag.push_back(true); + QString sstr = cur_block->getTextBlock()->getContent(); + int i = -1; + do { + i = sstr.indexOf(str, i + 1); + if (i != -1) + count++; + } while (i != -1); + } + } + } +// qDebug() << "Finished processing all foreground layer blocks."; + for (int j = 0; j < body_layer->getBlocks()->size(); j++) + { + DocBlock * cur_block = body_layer->getBlocks()->operator [](j); + if (cur_block->isTextBlock()) + { +// qDebug() << "???"; + if (cur_block->getTextBlock() + ->getContent().contains(str)) + { +// qDebug() << "TextBlock Address = " << cur_block->getTextBlock(); + blocks_found.push_back(cur_block->getTextBlock()); + blocks_flag.push_back(true); +// qDebug() << "???"; + int i = -1; + do { + i = cur_block->getTextBlock()->getContent().indexOf(str, i + 1); +// qDebug() << " i = " << i; + if (i != -1) + count++; +// qDebug() << "Count++"; + } while (i != -1); +// qDebug() << "Finished processing a block"; + } + } + } +// qDebug() << "Finished processing all body layer blocks."; + for (int j = 0; j < background_layer->getBlocks()->size(); j++) + { + DocBlock * cur_block = body_layer->getBlocks()->operator [](j); + if (cur_block->isTextBlock()) + { + if (cur_block->getTextBlock() + ->getContent().contains(str)) + { + blocks_found.push_back(cur_block->getTextBlock()); + blocks_flag.push_back(true); + QString sstr = cur_block->getTextBlock()->getContent(); + int i = -1; + do { + i = sstr.indexOf(str, i + 1); + if (i != -1) + count++; + } while (i != -1); + } + } + } + } + qDebug() << "Finished finding all target blocks"; + qDebug() << blocks_found.size() << "blocks found."; +} + +/** + * @Author Pan + * @brief 聚焦、定位到当下的查找到的DocTextBlock中的文本 + * @param + * @return void + * @date 2017/06/27 + */ +void FindAndReplaceDock::focusOnFoundPart() +{ + DocTextBlock * current_block = blocks_found[current_block_index]; + current_block->setFocus(); + QTextCursor cursor = current_block->textCursor(); + cursor.setPosition(current_block_pos); + cursor.movePosition(QTextCursor::NextCharacter, + QTextCursor::KeepAnchor, + ui->FindLineEdit->text().length()); + current_block->setTextCursor(cursor); + QScrollBar * scroll_bar = passage->verticalScrollBar(); + + DocPassage * current_passage = current_block->getPassage(); + DocPage * current_page = current_block->getPage(); + int accumulated_height = 0; + for (int i = 0; i < current_passage->getPages().size(); i++) + { + if (current_passage->getPages()[i] == current_page) + break; + else + accumulated_height += 50 + current_passage->getPages()[i]->height(); + } + scroll_bar->setSliderPosition(accumulated_height + current_block->pos().ry()); +} + +/** + * @Author Pan + * @brief 辅助函数,通过blocks_flag找到下一个包含目标字符串的块 + * @param int cur_index + * @return int + * @date 2017/06/27 + */ +int FindAndReplaceDock::findNextAvaibleBlockIndex(int cur_index) +{ + int i = cur_index; + while (((++i) %= blocks_flag.size()) != cur_index) + { + if (blocks_flag[i] == true) + return i; + } + return -1; +} + +/** + * @Author Pan + * @brief 定位到上一处位置 + * @param + * @return void + * @date 2017/06/27 + */ +void FindAndReplaceDock::locatePreviousPlace() +{ + //To be implemented +} + +/** + * @Author Pan + * @brief 定位到下一处位置 + * @param + * @return void + * @date 2017/06/27 + */ +void FindAndReplaceDock::locateNextPlace() +{ + if (blocks_found.size() > 0) { + qDebug() << "locateNextPlace() called."; + // qDebug() << "Current_block_index = " << current_block_index; + // qDebug() << "Current_block_pos = " << current_block_pos; + DocTextBlock * cur_text_block; + QString str = ui->FindLineEdit->text(); + QString sstr; + if (current_block_index == -1 && current_block_pos == -1) { + current_block_index = 0; + cur_text_block = blocks_found[0]; + sstr = cur_text_block->getContent(); + current_block_pos = sstr.indexOf(str, 0); +// qDebug() << "In init str = " << str << " sstr = " << sstr; + } + else + { + qDebug() << "Output block_flags: "; + for (int i = 0; i < blocks_flag.size(); i++) + qDebug() << "blocks_flag at " << i << " = " << blocks_flag[i]; + qDebug() << "Current_block_index = " << current_block_index; + qDebug() << "Current_block_pos = " << current_block_pos; + qDebug() << "Next place position = " << sstr.indexOf(str, current_block_pos + 1); + qDebug() << "str = " << str << " sstr = " << sstr; + cur_text_block = blocks_found[current_block_index]; + sstr = cur_text_block->getContent(); + if (sstr.indexOf(str, current_block_pos + 1) != -1) { + current_block_pos = sstr.indexOf(str, current_block_pos + 1); + } + else { + qDebug() << "Current_block_index = " << current_block_index; + qDebug() << "Next available Index = " + << findNextAvaibleBlockIndex(current_block_index); + if ((current_block_index = + findNextAvaibleBlockIndex(current_block_index)) != -1) { + + cur_text_block = blocks_found[current_block_index]; + sstr = cur_text_block->getContent(); + current_block_pos = sstr.indexOf(str, 0); + } else { + QMessageBox::information(passage, "Message", "No text found.", "OK"); + return; + } + } + } + focusOnFoundPart(); + } else { + QMessageBox::information(passage, "Message", "No text found.", "OK"); + return; + } +} + +/** + * @Author Pan + * @brief 用ReplaceWithLineEdit中的文本替换当前选中的文本 + * @param + * @return void + * @date 2017/06/27 + */ +void FindAndReplaceDock::replaceText() +{ + if (blocks_found.size() > 0) + { + if (current_block_index >= 0 && current_block_pos >= 0) + { + DocTextBlock * cur_block = blocks_found[current_block_index]; + QTextCursor cursor = cur_block->textCursor(); + cursor.removeSelectedText(); + cursor.insertText(ui->ReplaceWithLineEdit->text()); + if (!cur_block->getContent().contains(ui->FindLineEdit->text())) + blocks_flag[current_block_index] = false; + locateNextPlace(); + } + } + else return; +} + +/** + * @Author Pan + * @brief 替换所有查找到的文本 + * @param + * @return void + * @date 2017/06/27 + */ +void FindAndReplaceDock::replaceAll() +{ + while (findNextAvaibleBlockIndex(0) >= 0) { + replaceText(); + } +} + +/** + * @Author Pan + * @brief 按钮的效果的槽函数 + * @param const QString &arg1 + * @return void + * @date 2017/06/27 + */ +void FindAndReplaceDock::on_CountLineEdit_textChanged(const QString &arg1) +{ + if (arg1.toInt() == 0) + { + ui->FindPreviousButton->setEnabled(false); + ui->FindNextButton->setEnabled(false); + } + else + { + ui->FindPreviousButton->setEnabled(true); + ui->FindNextButton->setEnabled(true); + } +} + + + diff --git a/ofdEditor/model/Widget/FindAndReplaceDock.h b/ofdEditor/model/Widget/FindAndReplaceDock.h new file mode 100644 index 0000000..61c4fff --- /dev/null +++ b/ofdEditor/model/Widget/FindAndReplaceDock.h @@ -0,0 +1,49 @@ +#ifndef FINDANDREPLACEDOCK_H +#define FINDANDREPLACEDOCK_H + +#include +#include +#include + +class DocTextBlock; +class DocPassage; + +namespace Ui { +class FindAndReplaceDock; +} + +class MODELSHARED_EXPORT FindAndReplaceDock : public QDockWidget +{ + Q_OBJECT + +public: + explicit FindAndReplaceDock(QWidget *parent = 0); + ~FindAndReplaceDock(); + + void setCurrentPassage(DocPassage * current_passage); +private slots: + void on_FindLineEdit_textChanged(const QString &arg1); + + void on_CountLineEdit_textChanged(const QString &arg1); + void locatePreviousPlace(); //定位到上一个位置 + void locateNextPlace(); //定位到下一个位置 + void replaceText(); //切换当前文本 + void replaceAll(); //切换所有文本 + +private: + Ui::FindAndReplaceDock *ui; + QVector blocks_found; + QVector blocks_flag; //记录blocks_find中的元素是否依然有效 + DocPassage * passage; + int count; //找到的文本数量 + + void findAllTargetTextBlock(const QString & str); + void focusOnFoundPart(); + int findNextAvaibleBlockIndex(int cur_index); + + int current_block_index; //当前选中的DocTextBlock的下边,-1表示将从头开始 + int current_block_pos; //当前选中的DocTextBlock的当前位置,-1表示将从头开始 + +}; + +#endif // FINDANDREPLACEDOCK_H diff --git a/ofdEditor/model/Widget/FindAndReplaceDock.ui b/ofdEditor/model/Widget/FindAndReplaceDock.ui new file mode 100644 index 0000000..2861f4d --- /dev/null +++ b/ofdEditor/model/Widget/FindAndReplaceDock.ui @@ -0,0 +1,231 @@ + + + FindAndReplaceDock + + + + 0 + 0 + 954 + 64 + + + + false + + + QDockWidget::DockWidgetClosable + + + Qt::BottomDockWidgetArea + + + Find/Replace + + + + + + 57 + 10 + 91 + 20 + + + + + + + 15 + 11 + 41 + 16 + + + + + Arial + 10 + + + + Find: + + + + + + 533 + 12 + 81 + 16 + + + + + Arial + 10 + + + + Replace With: + + + + + + 630 + 10 + 91 + 20 + + + + + + + 160 + 10 + 101 + 21 + + + + + Arial + 10 + + + + Find Previous + + + + + + 270 + 10 + 91 + 21 + + + + + Arial + 10 + + + + Find Next + + + + + + 733 + 9 + 91 + 23 + + + + + Arial + 10 + + + + Replace + + + + + + 839 + 9 + 101 + 23 + + + + + Arial + 10 + + + + Replace All + + + + + + 509 + 0 + 16 + 41 + + + + Qt::Vertical + + + + + + 370 + 13 + 61 + 16 + + + + + Arial + 10 + + + + Found in: + + + + + + 473 + 13 + 41 + 16 + + + + + Arial + 10 + + + + places. + + + + + + 431 + 12 + 31 + 20 + + + + + Arial + 10 + + + + + + + + diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index 19a8a52..6f1aeb7 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -54,7 +54,8 @@ SOURCES += model.cpp \ Command/SetTextBlodCmd.cpp \ Doc/DocImageBlock.cpp \ Widget/imagepropertiesdialog.cpp \ - Widget/PageDialog.cpp + Widget/PageDialog.cpp \ + Widget/FindAndReplaceDock.cpp HEADERS += model.h\ model_global.h \ @@ -88,7 +89,8 @@ HEADERS += model.h\ Command/SetTextBlodCmd.h \ Doc/DocImageBlock.h \ Widget/imagepropertiesdialog.h \ - Widget/PageDialog.h + Widget/PageDialog.h \ + Widget/FindAndReplaceDock.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 @@ -118,4 +120,5 @@ FORMS += \ Widget/FontSettingDialog.ui \ Widget/DocInfoDialog.ui \ Widget/imagepropertiesdialog.ui \ - Widget/PageDialog.ui + Widget/PageDialog.ui \ + Widget/FindAndReplaceDock.ui diff --git a/ofdEditor/start/ActionConnector/ActionConnector.cpp b/ofdEditor/start/ActionConnector/ActionConnector.cpp index 850f281..6e3d1ad 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.cpp +++ b/ofdEditor/start/ActionConnector/ActionConnector.cpp @@ -22,6 +22,11 @@ ActionConnector::ActionConnector(PassageMainWindow *mainWindow) init(); } +DocPassage *ActionConnector::getActivePassage() +{ + return passage; +} + void ActionConnector::showAttribute() { if(this->passage == NULL) @@ -177,6 +182,12 @@ void ActionConnector::updateActivePassage(QMdiSubWindow *window) } } +void ActionConnector::startFindAndReplace() +{ + mainWindow->activateFindAndReplaceDock(); + +} + DocPage *ActionConnector::getActivePage() { return qobject_cast(this->passage->focusWidget()); diff --git a/ofdEditor/start/ActionConnector/ActionConnector.h b/ofdEditor/start/ActionConnector/ActionConnector.h index 4cb530d..e3356d6 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.h +++ b/ofdEditor/start/ActionConnector/ActionConnector.h @@ -24,7 +24,8 @@ public: ActionConnector(PassageMainWindow * mainWindow); DocPage::Layer getDefaultLayer(){return this->defaultLayer;} - + DocPassage * getActivePassage(); //获取当前操作的文档 + DocPage *getActivePage(); //获取当前操作的页面 public slots: void showAttribute(); // 显示文档元信息 void setMainWindow(PassageMainWindow * mainWindow); // 设置主窗口 @@ -40,8 +41,8 @@ public slots: void setDefaultLayer(DocPage::Layer layer){this->defaultLayer = layer;} void updateActivePassage(QMdiSubWindow * window ); // 更新当前操作的文章 + void startFindAndReplace(); //打开查找和替换界面 - DocPage *getActivePage(); //获取当前操作的页面 private: PassageMainWindow * mainWindow; // 主窗口 DocPassage * passage; // 当前活跃文档 diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 1378185..b7e2a13 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -28,6 +28,7 @@ #include "Doc/DocPage.h" #include "Doc/DocTextBlock.h" #include "Doc/DocImageBlock.h" +#include "Widget/FindAndReplaceDock.h" PassageMainWindow::PassageMainWindow(QWidget *parent) :QMainWindow(parent) @@ -40,6 +41,15 @@ PassageMainWindow::~PassageMainWindow() } +void PassageMainWindow::activateFindAndReplaceDock() +{ + if (connector->getActivePassage()) + { + find_and_replace_dock->setCurrentPassage(connector->getActivePassage()); + this->find_and_replace_dock->show(); + } +} + /** * @Author Chaoqun * @brief 摘要 @@ -88,6 +98,11 @@ void PassageMainWindow::init() this->setBackgroundRole(QPalette::Text); + this->find_and_replace_dock = new FindAndReplaceDock(NULL); + this->addDockWidget(Qt::BottomDockWidgetArea, find_and_replace_dock); + this->find_and_replace_dock->setMaximumHeight(60); + this->find_and_replace_dock->setMinimumHeight(60); + this->find_and_replace_dock->setVisible(false); } /** @@ -151,6 +166,11 @@ void PassageMainWindow::initAction() this->pasteAction->setShortcut(QKeySequence::Paste); this->pasteAction->setIcon(QIcon(":/icons/source/icons/paste.png")); + this->find_and_replace = new QAction(tr("Find/Replace"), NULL); //查找和替换 + this->find_and_replace->setStatusTip(tr("Find specific text or replace them")); + this->find_and_replace->setShortcut(QKeySequence::Find); + //缺少Icon + this->insertNewPageAction = new QAction(tr("Insert New Page"),NULL); // 插入新页面 this->insertNewPageAction->setStatusTip(tr("Insert a new Page into document")); this->insertNewPageAction->setIcon(QIcon(":/icons/source/icons/insertNewPage.png")); @@ -216,6 +236,7 @@ void PassageMainWindow::initAction() this->editMenu->addAction(this->copyAction); this->editMenu->addAction(this->cutAction); this->editMenu->addAction(this->pasteAction); + this->editMenu->addAction(this->find_and_replace); this->formatMenu->addAction(this->textFormat); this->formatMenu->addAction(this->paragraphFormat); @@ -287,6 +308,9 @@ void PassageMainWindow::connectAction() //redo operation connect(this->redoAction,SIGNAL(triggered(bool)),this->connector,SLOT(redo())); + connect(this->find_and_replace, SIGNAL(triggered(bool)), + this->connector, SLOT(startFindAndReplace())); + connect(this->insertTextBlockAction, SIGNAL(triggered()), this->connector, SLOT(addTextBlock())); // 插入文本框 diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index be5d0ec..c4390cd 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -16,6 +16,7 @@ class QTextCharFormat; class QTextBlockFormat; class ActionConnector; // 函数功能的中间件 class DocImageBlock; +class FindAndReplaceDock; // 编辑窗口的主界面 class PassageMainWindow @@ -25,11 +26,14 @@ class PassageMainWindow public: explicit PassageMainWindow(QWidget *parent = 0); ~PassageMainWindow(); + + void activateFindAndReplaceDock(); public slots: DocPassage *createMdiChild(); // 创建一个新文档 DocPassage *activeMdiChild(); // 获取活动的窗口 DocPassage *addDocPassage(DocPassage * passage); + private: // 菜单栏 @@ -60,6 +64,7 @@ private: QAction * copyAction; // 复制 QAction * cutAction; // 剪切 QAction * pasteAction; // 粘贴 + QAction * find_and_replace; //查找和替换 // 插入 QAction * insertNewPageAction; // 插入新页面 @@ -96,6 +101,7 @@ private: DocImageBlock *imageBlock; //图片块 + FindAndReplaceDock * find_and_replace_dock; //查找 & 替换 private slots: @@ -109,6 +115,8 @@ private slots: void acceptTextBlockFormat(QTextBlockFormat& blockFormat); // 接受当前处理的块格式 void acceptTextCharFormat(QTextCharFormat& charFormat); // 接受当前处理的字符格式 void acceptImageBlock(DocImageBlock * imageBlock); //接受当前处理的图片块 + + }; #endif // PASSAGEMAINWINDOW_H -- Gitee From 12eba14782a83b35a9cd288976dd09c6fe860867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Tue, 27 Jun 2017 21:07:56 +0800 Subject: [PATCH 14/83] =?UTF-8?q?=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocBlock.h | 1 - ofdEditor/model/Doc/DocTable.h | 6 + ofdEditor/model/Widget/InsertTableDialog.cpp | 14 + ofdEditor/model/Widget/InsertTableDialog.h | 22 + ofdEditor/model/Widget/InsertTableDialog.ui | 254 +++++ ofdEditor/model/cn_model.ts | 1012 ++++++++++++++++++ ofdEditor/model/model.pro | 9 +- ofdEditor/start/cn_start.ts | 669 ++++++++++++ ofdEditor/start/icons.qrc | 6 + ofdEditor/start/source/icons/EditMode.png | Bin 0 -> 674 bytes ofdEditor/start/source/icons/Setting.png | Bin 0 -> 830 bytes ofdEditor/start/source/icons/ViewMode.png | Bin 0 -> 1192 bytes ofdEditor/start/source/icons/ZoomIn.png | Bin 0 -> 1194 bytes ofdEditor/start/source/icons/ZoomOut.png | Bin 0 -> 1165 bytes ofdEditor/start/source/icons/template.png | Bin 0 -> 690 bytes ofdEditor/start/ui/PassageMainWindow.cpp | 121 ++- ofdEditor/start/ui/PassageMainWindow.h | 10 + 17 files changed, 2103 insertions(+), 21 deletions(-) create mode 100644 ofdEditor/model/Widget/InsertTableDialog.cpp create mode 100644 ofdEditor/model/Widget/InsertTableDialog.h create mode 100644 ofdEditor/model/Widget/InsertTableDialog.ui create mode 100644 ofdEditor/model/cn_model.ts create mode 100644 ofdEditor/start/cn_start.ts create mode 100644 ofdEditor/start/source/icons/EditMode.png create mode 100644 ofdEditor/start/source/icons/Setting.png create mode 100644 ofdEditor/start/source/icons/ViewMode.png create mode 100644 ofdEditor/start/source/icons/ZoomIn.png create mode 100644 ofdEditor/start/source/icons/ZoomOut.png create mode 100644 ofdEditor/start/source/icons/template.png diff --git a/ofdEditor/model/Doc/DocBlock.h b/ofdEditor/model/Doc/DocBlock.h index eb126f9..76df54d 100644 --- a/ofdEditor/model/Doc/DocBlock.h +++ b/ofdEditor/model/Doc/DocBlock.h @@ -53,7 +53,6 @@ public slots: // 槽函数 void setWidget(DocTextBlock *textBlock); // SetWidget void setWidget(DocImageBlock * imageBlock); - protected: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, diff --git a/ofdEditor/model/Doc/DocTable.h b/ofdEditor/model/Doc/DocTable.h index 27a1500..beac60d 100644 --- a/ofdEditor/model/Doc/DocTable.h +++ b/ofdEditor/model/Doc/DocTable.h @@ -17,8 +17,14 @@ public: DocTable(QWidget *parent = NULL); ~DocTable(); +public slots: + +private slots: + private: // tableCell的内容估计使用QTextBlock + int rowCount; // 行数 + int colCount; // 列数 }; #endif // TABLE_H diff --git a/ofdEditor/model/Widget/InsertTableDialog.cpp b/ofdEditor/model/Widget/InsertTableDialog.cpp new file mode 100644 index 0000000..d2a39bb --- /dev/null +++ b/ofdEditor/model/Widget/InsertTableDialog.cpp @@ -0,0 +1,14 @@ +#include "InsertTableDialog.h" +#include "ui_InsertTableDialog.h" + +InsertTableDialog::InsertTableDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::InsertTableDialog) +{ + ui->setupUi(this); +} + +InsertTableDialog::~InsertTableDialog() +{ + delete ui; +} diff --git a/ofdEditor/model/Widget/InsertTableDialog.h b/ofdEditor/model/Widget/InsertTableDialog.h new file mode 100644 index 0000000..722c5a7 --- /dev/null +++ b/ofdEditor/model/Widget/InsertTableDialog.h @@ -0,0 +1,22 @@ +#ifndef INSERTTABLEDIALOG_H +#define INSERTTABLEDIALOG_H + +#include + +namespace Ui { +class InsertTableDialog; +} + +class InsertTableDialog : public QDialog +{ + Q_OBJECT + +public: + explicit InsertTableDialog(QWidget *parent = 0); + ~InsertTableDialog(); + +private: + Ui::InsertTableDialog *ui; +}; + +#endif // INSERTTABLEDIALOG_H diff --git a/ofdEditor/model/Widget/InsertTableDialog.ui b/ofdEditor/model/Widget/InsertTableDialog.ui new file mode 100644 index 0000000..9cf40cb --- /dev/null +++ b/ofdEditor/model/Widget/InsertTableDialog.ui @@ -0,0 +1,254 @@ + + + InsertTableDialog + + + + 0 + 0 + 411 + 507 + + + + 插入表格 + + + + + 30 + 460 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 20 + 20 + 361 + 431 + + + + 1 + + + + 表格 + + + + + 20 + 30 + 311 + 351 + + + + + + + 行数列数 + + + + + 20 + 40 + 261 + 91 + + + + + + + 行数: + + + + + + + + + + 列数: + + + + + + + + + + + + + + 总体尺寸 + + + + + 20 + 40 + 271 + 101 + + + + + + + 宽: + + + + + + + + + + mm + + + + + + + 高: + + + + + + + + + + mm + + + + + + + + + + + + + 高级 + + + + + 10 + 30 + 331 + 151 + + + + 单元格大小 + + + + + 20 + 30 + 271 + 101 + + + + + + + 宽: + + + + + + + + + + mm + + + + + + + 高: + + + + + + + + + + mm + + + + + + + + + + + + + buttonBox + accepted() + InsertTableDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + InsertTableDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/ofdEditor/model/cn_model.ts b/ofdEditor/model/cn_model.ts new file mode 100644 index 0000000..dad1a07 --- /dev/null +++ b/ofdEditor/model/cn_model.ts @@ -0,0 +1,1012 @@ + + + + + DocImageBlock + + + Change Image + 修改图片 + + + + Set Image Properties + 设置图片属性 + + + + Open File + 打开文件 + + + + OFD Editor + OFD Editor + + + + Cannot open file %1. + 无法打开文件 %1. + + + + DocInfoDialog + + + Dialog + 文档属性 + + + + 说明 + + + + + 文件: + + + + + 文档ID: + + + + + 更改 + + + + + 标题: + + + + + 作者: + + + + + 主题: + + + + + 摘要: + + + + + 关键字: + + + + + 文档类型: + + + + + 文档封面: + + + + + 创建日期: + + + + + 高级 + + + + + 最近修改时间: + + + + + 创建应用程序: + + + + + 应用程序版本: + + + + + DocPage + + + Open File + 打开文件 + + + + OFD Editor + + + + + Cannot open file %1. + + + + + DocTextBlock + + + Choose a Color + 选择颜色 + + + + Set the font + 设置字体 + + + + Bold + 加粗 + + + + Italic + 斜体 + + + + Underline + 下划线 + + + + Color + 颜色 + + + + Font + 字体 + + + + Paragraph + 段落 + + + + Remove + 移除 + + + + FontDialogTest + 字体 + + + + FontSettingDialog + + + Dialog + 字体设置窗口 + + + + + 字体 + + + + + 粗体 + + + + + 字号 + + + + + 下划线 + + + + + 字体效果预览 + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">文字测试样例</p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Text Demo</p></body></html> + + + + + 斜体 + + + + + 初号 + + + + + 小初 + + + + + 一号 + + + + + 小一 + + + + + 二号 + + + + + 小二 + + + + + 三号 + + + + + 小三 + + + + + 四号 + + + + + 小四 + + + + + 五号 + + + + + 小五 + + + + + 六号 + + + + + 小六 + + + + + 七号 + + + + + 八号 + + + + + 5 + + + + + 5.5 + + + + + 6.5 + + + + + 7.5 + + + + + 8 + + + + + 9 + + + + + 10 + + + + + 10.5 + + + + + 11 + + + + + 12 + + + + + 14 + + + + + 16 + + + + + 18 + + + + + 20 + + + + + 22 + + + + + 24 + + + + + 26 + + + + + 28 + + + + + 36 + + + + + 48 + + + + + 72 + + + + + 高级 + + + + + 字间距 + + + + + 拉伸字体 + + + + + 字体粗细 + + + + + 等宽字体 + + + + + ImagePropertiesDialog + + + Dialog + 图片属性设置 + + + + 图片尺寸 + + + + + 高度 + + + + + 宽度 + + + + + + + + 像素 + + + + + + %原尺寸 + + + + + 锁定纵横比 + + + + + 原始尺寸: + + + + + 122 ,122 + + + + + 图片位置 + + + + + 水平 + + + + + 垂直 + + + + + + %页面 + + + + + Width: + + + + + , Height: + + + + + PageDialog + + + Dialog + 页面设置 + + + + 当前页面 + + + + + + + + + + + + + + + + mm + + + + + 所有页 + + + + + + + + 宽 + + + + + + + + 高 + + + + + + 垂直 + + + + + + 工作区域尺寸 + + + + + 特定页数 + + + + + 应用于 + + + + + + 设置工作区域 + + + + + + 水平 + + + + + + 页面尺寸 + + + + + + 工作区域位置 + + + + + 页面设置 + + + + + 当前页 + + + + + 页面范围 + + + + + 从 + + + + + 到 + + + + + 页 + + + + + 页码 + + + + + + 选择尺寸 + + + + + + + + A4 + + + + + + + + A3 + + + + + + + + A5 + + + + + + + + Letter + + + + + + + + 16K + + + + + + + + 32K + + + + + + + Customized + + + + + 默认页面 + + + + + 默认页面设置 + + + + + ParagraphFormatDialog + + + Dialog + 段落属性设置 + + + + 对齐方式 + + + + + 水平 + + + + + 左对齐 + + + + + 右对齐 + + + + + + 居中 + + + + + 两端对齐 + + + + + 竖直 + + + + + 居上 + + + + + 居下 + + + + + 文字方向 + + + + + 左到右 + + + + + 右到左 + + + + + 缩进 + + + + + 整体缩进 + + + + + 首行缩进 + + + + + 间距 + + + + + 段前 + + + + + 段后 + + + + + 行距策略 + + + + + 单倍行距 + + + + + 多倍行距 + + + + + 固定值 + + + + + 最小值 + + + + + 值 + + + + + ParagraphFormatWidget + + + 段落属性 + + + + + 常规 + + + + + 对齐方式: + + + + + 左对齐 + + + + + 右对齐 + + + + + 居中 + + + + + 自动对齐 + + + + + 文字方向 + + + + + 自左向右 + + + + + 自右向左 + + + + + 缩进 + + + + + 整体缩进 + + + + + 首行缩进 + + + + + 间距 + + + + + 段前 + + + + + 段后 + + + + + 行高策略 + + + + + 单倍行高 + + + + + 多倍行高 + + + + + 固定值 + + + + + 最小值 + + + + + 行高值 + + + + + 边距 + + + + + 上边距 + + + + + 左边距 + + + + + 下边距 + + + + + 右边距 + + + + + 确定 + + + + + 取消 + + + + diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index 2f54626..09ad498 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -54,7 +54,8 @@ SOURCES += model.cpp \ Command/SetTextBlodCmd.cpp \ Doc/DocImageBlock.cpp \ Widget/imagepropertiesdialog.cpp \ - Widget/PageDialog.cpp + Widget/PageDialog.cpp \ + Widget/InsertTableDialog.cpp HEADERS += model.h\ model_global.h \ @@ -88,7 +89,8 @@ HEADERS += model.h\ Command/SetTextBlodCmd.h \ Doc/DocImageBlock.h \ Widget/imagepropertiesdialog.h \ - Widget/PageDialog.h + Widget/PageDialog.h \ + Widget/InsertTableDialog.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 @@ -120,4 +122,5 @@ FORMS += \ Widget/FontSettingDialog.ui \ Widget/DocInfoDialog.ui \ Widget/imagepropertiesdialog.ui \ - Widget/PageDialog.ui + Widget/PageDialog.ui \ + Widget/InsertTableDialog.ui diff --git a/ofdEditor/start/cn_start.ts b/ofdEditor/start/cn_start.ts new file mode 100644 index 0000000..acfe509 --- /dev/null +++ b/ofdEditor/start/cn_start.ts @@ -0,0 +1,669 @@ + + + + + Editor + + + MainWindow + + + + + toolBar + + + + + 新建文件 + + + + + Ctrl+N + + + + + 打开文件 + + + + + Ctrl+O + + + + + 保存 + + + + + Ctrl+S + + + + + 另存为 + + + + + Ctrl+Shift+S + + + + + 打印 + + + + + Ctrl+P + + + + + 文档属性 + + + + + 撤销 + + + + + Ctrl+Z + + + + + 重做 + + + + + Ctrl+Shift+Z + + + + + 复制 + + + + + Backspace + + + + + 粘贴 + + + + + 剪切 + + + + + 插入新页 + + + + + 插入文本框 + + + + + 插入图片 + + + + + 插入表格 + + + + + 页面设置 + + + + + 字体 + + + + + 段落 + + + + + 图片设置 + + + + + 表格设置 + + + + + 关于Qt + + + + + 关于本工程 + + + + + 加粗 + + + + + PassageMainWindow + + + New File + 新建文档 + + + + Create a new ofd file + 创建要给ofd文档 + + + + Open File + 打开 + + + + Open an existing ofd file + 打开一个存在的ofd文件 + + + + Save + 保存 + + + + Save file + 保存文件 + + + + + Save as + 另存为 + + + + Print + 打印 + + + + Print your document + 打印你的文档 + + + + Attribute + 文档属性 + + + + Show you the attribute of the actived passage + 查看你当前编辑的文档的属性 + + + + Undo + 撤销 + + + + Undo your last action + 插销你的上一步操作 + + + + Redo + 重做 + + + + Redo the action you undo + 重做你刚撤销的操作 + + + + Copy + 复制 + + + + Copy the content you selected + 复制你选择的内容 + + + + Cut + 剪切 + + + + Cut the content you selected + 剪切你选择的内容 + + + + Paste + 粘贴 + + + + Paste your pasteboard content + 粘贴你剪贴板里的内容 + + + + Insert New Page + 增加新页 + + + + Insert a new Page into document + 插入一个新页面到文档 + + + + Insert TextBlock + 插入文本框 + + + + Insert a new TextBlock + 插入一个新的文本框 + + + + Insert Image + 插入图片 + + + + Insert a image + 插入一个图片 + + + + Insert Table + 插入表格 + + + + Insert a table + 插入一个表格 + + + + Page Format + 页面格式 + + + + Set the page format + 设置页面格式 + + + + Text Format + 字体格式 + + + + Set the selected texts' format + 设置选择的文本的字体格式 + + + + Paragraph Format + 段落 + + + + Set this paragarph format + 设置选择的段落的格式 + + + + Image Format + 图片格式 + + + + Set the Selected image's format + 设置选择的图片的格式 + + + + Table Format + 表格格式 + + + + Set the selected table's format + 设置选择的表格的格式 + + + + about Qt + 关于Qt + + + + About App + 关于本应用 + + + + About this Application + 关于本应用 + + + + Help + 帮助 + + + + Show the help Window + 显示帮助页面 + + + + Files + 文件 + + + + + Edit + 编辑 + + + + + Format + 格式 + + + + + Insert + 插入 + + + + About + 关于 + + + + 72 + + + + + 48 + + + + + + 36 + + + + + 28 + + + + + 26 + + + + + + 24 + + + + + 22 + + + + + 20 + + + + + + 18 + + + + + + 16 + + + + + + 14 + + + + + + 12 + + + + + 11 + + + + + + 10.5 + + + + + 10 + + + + + + 9 + + + + + 8 + + + + + + 7.5 + + + + + + 6.5 + + + + + 5.5 + + + + + 5 + + + + + 4.5 + 八号 + + + + 5.25 + 七号 + + + + 15 + + + + + 21 + + + + + 27.5 + + + + + 42 + + + + + Bold + 加粗 + + + + Set selected text Bold or not bold + 将选择的文本加粗 + + + + Italic + 斜体 + + + + Set the selected text Italic + 设置选择的文本斜体 + + + + Underline + 下划线 + + + + Set the selected text underline + 设置选择的文本下划线 + + + + middle + 居中 + + + + Set the selected paragraph align middle + 设置选择的段落格式为居中 + + + + Left + 左对齐 + + + + Set the selected paragraph align by left + 设置选择的段落对齐样式为左对齐 + + + + Right + 右对齐 + + + + Set the selected paragraph align by right + 设置选中的段落的对齐样式为右对齐 + + + + jutify + 两端对齐 + + + + Set the selected paragraph align by left and right + 设置选择的文本的对齐样式为两端对齐 + + + + File + 文件 + + + + TextBlock + 文本框 + + + + JSON files(*.ofd) + OFD文件(*ofd) + + + + Choose an ofd document file! + 选择一个OFD文件! + + + + Save the passage content as a ofd file + 保存文件为一个ofd文件 + + + + OFD files(*.ofd) + + + + diff --git a/ofdEditor/start/icons.qrc b/ofdEditor/start/icons.qrc index f7036a8..e19c7a7 100644 --- a/ofdEditor/start/icons.qrc +++ b/ofdEditor/start/icons.qrc @@ -29,5 +29,11 @@ source/icons/pageFormat.png source/icons/right.png source/icons/underline.png + source/icons/EditMode.png + source/icons/Setting.png + source/icons/ViewMode.png + source/icons/ZoomIn.png + source/icons/ZoomOut.png + source/icons/template.png diff --git a/ofdEditor/start/source/icons/EditMode.png b/ofdEditor/start/source/icons/EditMode.png new file mode 100644 index 0000000000000000000000000000000000000000..cf05ce214162788f560e0f39052e2213ad2330ab GIT binary patch literal 674 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5Sk21sKV*{@;n8QkZ|A_kz_`lO#W5t~-rF0y{g@mjSRXW3R5A#2>uT&-q>+`J{8(5* z*+p>Tj0lPRPR@Ieo~piCgZ_~9~DoMYaFr?cdZDjFXM&ei*w!mKY~ zb0KV&YLe}{iw{>FnCRXbT`t;Zt956G7Q>v15QQ|crbQorUde5osTE*w?A)v$zGnIY zPkKLow%T{$+u!JvU5WE7AKy88{)JSxfAqeWqL2TiUgnr9&avs3Y50i^KQ#H{6e7|V z?w|SPA#0PW-u$eC+$`O@qPK2#UjAX(j#cfZzd4V->C~=|Il8{>^z$a?Zz`cSx!0wG zKmL3WAW%2=X#c8;Tl)7py6z`@Jgl`(LS|EXz|qV9-l~NB5$l!@_;_2#uCJVR|M5qS zYntpId^8M+`n207Zu7758GF7vr@g)L{L_JU{rVHne%JgIn$2!x_eXF(`>A*3dw<>d z=znJC!(7%=Gs;`d#VQ=H-Tgf`>Yc)h2U6VY9{!&(qjbt=r;}Nh@o|BTD-O)p7Etw? zlHd0-*d&1QT0Jl#RZCnWN>UO_QmvAUQh^kMk%6JPu7R1Zk$H%bft8_=m5I5wfrXWU j0r%I7Pf;}F=BH$)RpQoAwIVYTsDZ)L)z4*}Q$iB}8($b3 literal 0 HcmV?d00001 diff --git a/ofdEditor/start/source/icons/Setting.png b/ofdEditor/start/source/icons/Setting.png new file mode 100644 index 0000000000000000000000000000000000000000..1831744cf1e8fc12ee964f2724dcff4fecb88965 GIT binary patch literal 830 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5Sk21sKV*{@;n8QkZ|4A%ck^^{49U3nHqyH2kbyugpZsB-`AvO{+Y1=E(ibe|5?^p~ zMs~nVV*_VC2gmuw1wzjSGUqb!Y+G~n{4u4OHlZH7-|KGLr+t7&kFUe{X~Q(d>4FhI zy*bzlc$hm*CskL5i2wb_Fl*LV)ucY<^dC!43w}0g`J+9zeD%vD?TLQVb$6NjzmIzU z`n0;@4i3{JlQ%Wbo^+k#V0yO! z#&e=?ZAr9vpPF#Jl`YjGJlVV`uAJ%32KQdB_Owev04 z{Ezw<=vVwXo1tF3q0XE|T|4aM+Z#o74pS5_&J=8u6nbr`^g7b$b*0nmnU}Pj3_QZu zbDfY(Iek+=?>(zE^T!Kc_A1Ca&D2+0|LT*8Sm<8K&WkEXc;n9gi}$O~WsvVG4f?|n z_OjZi_Ey^pU?Nj3ag8WRNi0dVN-jzTQVd20hUU5kX1Ye^Aw~vPhDKH<=Gq1pRt5&# hUoSpI(U6;;l9^VCTSL`~%t)XH22WQ%mvv4FO#qXgKnef= literal 0 HcmV?d00001 diff --git a/ofdEditor/start/source/icons/ViewMode.png b/ofdEditor/start/source/icons/ViewMode.png new file mode 100644 index 0000000000000000000000000000000000000000..d4a38eb98eccedb5894dec59938ef2a0891d2eda GIT binary patch literal 1192 zcmV;Z1XufsP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 zVoOIv0063uBQgL01H(x~K~!ko<(OM&6jvC4zuk>V3W-4jT1}%OS`&?kQhcb1Qbny1 z^}!3aSbY#p1hb$Pl`2RyVnU!HFJ6L*6!AfPutgt4M6@j?*vo?!LBVTcR9ai5Xf!nA zL(cwtW_K<-JG0|M|9RN|{O7-X=ij-U8So>eY~^yHpBNry`Q0hy z4Gi8;0>x&EVC8S%{m&WrG&e@4Q{=8G+C^8@OWiAv)9uC9i))! zwnat(&}cJzje;NmzOyaAKzS6{dK~j#e!6XPgDK)=?=#IQc{BrnZKAbONQ7lB{wF9V z!aNyo@!NsqS`xU;jvYw+>v6I8>_9@UGN80B2d`e>{dG&PHDSlSE5 z6)mC-1B1<)Wg`6;Jflo3)e>1Fw&%*S)(lXsl^H44xC1~YVg)duEGx||`I%?pvP-lM zj|EfZWttWtqO^Zgo#$&SO+JWLnmTa7BS3^7FfceLWn+?SR;qK9*D`rXv;L_8wE64^ z6iTkD^vT6qspN@Np;@ba1C&ax^7P4=oFInj$@qz~?etw9CP;-6tLdedJqS|fNd6&K z(=iR;U`_xwy1lULJs6b(fTJq+Wjlu${|P{Q4gemj+>Q1w`n513;PUyB*0VF?mXSB_IAnx}9d4Wy-0pDg8pzo350RYT)dJtPnr-m@qH^46{ zQ=e>3T;*faZm8H-`C7@d#!J{f4d8s{ z6+o-R_hfTDZ7?CM^1S+XExIDR7Iv5r>ODkOaz~3?>mkx4d0a9fJYb<~OgUfDWr}Lf zppvZ=@S`c2_rv$@Y6z!%l;7&N{Ge>gvb_J-8IdxMdn)~kb?Ím_~Vr_u91^@s6 zC3HntbYx+4WjbSWWnpw>05UK!H!UzWEiyM$GB7$ZGCDLjD=;`ZFfa@C(d7UD03~!q zSaf7zbY(hiZ)9m^c>ppnF*hwRHZ3wYR5CC+F)}(dH!CnWIxsMLsA*XM0000004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 zVoOIv0063uBQgL01I0;1K~!ko#hFQLPEi!cf8SH8Rjr_gHfoF^h(`M%h6G6?rUYSQ zh%qb-NgIS%Nh}Zq3nEw%i4=)MtSUiLQ;iEsqQn$aA~dvyR4r(|d+&R9c;E9mcXQ9Z z=bZolocFzVhcAJRc$6`kBtt16lX{+Vm+RDU)5<#~>C0A{HSInNX#20g$8t{#{jiyh^yQcpZ&K;EWPzjiu*2#dEDY z{9+|Yv4eMSzDV99-QasF@P&>E?zZS~^=X*(U z^32d40NaGI4cv~9KfnuS3;J?9x2_WJ@YT&!0e~7IR)$RlW(p%S_z^MxpsYvPxYSy6 zwy6NZ+i=7TpCiC;(c0P(m?K2=^za`21^tw5r8RO<(DL=h9wP+(Nel!&@Xel6M+(6-}quL zuv~~BY566D@AhW}k9&e{cxkMpvyjGP6M;HGpBDoGaUcE8>|ncs+dhKFKD(19a1Yoe zj7&>0|6<`W9=37Gm3Bm7yIH#m+!11BVGs|f=a4W~kwX4+g~e^B?YFf^szEYh1^P&F zdYYks?^m9)Ul_eXQH1RCcqHh%g+(bu60Oc3m8!guMuxDewO_?KX|@x0rB8Vt^)CFU zD2KBW2k(9~N#0Z3OSn^^P@!C41j~HIbB8-TwBdph=%+E0G1MtuzuO*iT`6RRT+Efz zBfz=?%lQ-n-qMDdAQK9O^Gpn}y}^|~cSMCGL#<>fqspxc9(xQ~>Dujpv6Ze50;WfV zUr!=%e6RbpRVNNPf>-}Jg6s>Ny%>7=r;&afvjo5DI|X+Qv1y=}I|ayOsj$Awt&xq& z&VO8}b*Tzq_o0C#r6d_n5jiySiU-`JhRY$=bA`j1ICDBm9o%JeXce4qlcUOsPzuN0 zF7TpCrgU%UZ?$wu2Zb)$H)mivC=Ak4n3N6*leH9fih{VGE$@zq(a(7W&Z-VWq`O0OAsCa z001R)MObuXVRU6WV{&C-bY%cCFflhRFg7hRH&ik(Ix#XjG&d_SI65#e3-!_E0000b zbVXQnWMOn=I&E)cX=ZrR literal 0 HcmV?d00001 diff --git a/ofdEditor/start/source/icons/ZoomOut.png b/ofdEditor/start/source/icons/ZoomOut.png new file mode 100644 index 0000000000000000000000000000000000000000..6c0d590e7001be23643245c275f15c35920524ef GIT binary patch literal 1165 zcmV;81akX{P)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 zVoOIv0063uBQgL01E@(vK~!ko#hFWNOi>)he>2tAlu|TdJfesMRXXu#y&|!YAn}Mt zA{r76^;}Ra*szg^1tBaDiNt~gkw{p1gp_(GH1XP~6!l1&2t^}mF?Y^AGd*|iIrkpZ z|5@BQcfRlcefQiu=l;)`2>LOVDO6EO8O8jfg(e1 z<5{HTc8i2<@fiCx#Z&DX!%RgYp5IKTL2;uziA$@oPF+~I&PT9b#B;-dQbLHh{kLW>3li>%YUK~VsyjCf+vK&$vP$s5!I zfRUo_-mjVv(q{qqOB3V$3?##yx!f=-#?o6V&N%%>Z|USMNX>lTtPH&yADm;BH$u`t zzSH|<*+7SL%u-b(4YWJG63YgPonw}fO&a*@^a`?6$w6X-b8Pm8^vD48;=A+dumuA% zo#S(Vr>W<6ti|gu6j@h!gOa!4gXqt;XuzFap8A8IIbL5`G_YHYKu>@0x?ojYmT)VK z>pJkbfbX+pz%5M|=n?MgzdW_#jmW3DKyjB8hb+i15ZU(XQX(`9(&UixCBZ7}DH5$D zgnWdnBF{E6>PbO-NI_r&d!;pUz8ST*GzM2q$xiH$a*Q{pS4i~7#=nOs2POWVU;{Wm zt+ttJz#PKUjLK+NFbm7mk{r_-hbSAB#hKwln2LEBX$~+n3%V!kv($%L>!Pkv-X+mT zwo{pb8p>)Kd`r{~!7RkI_ekaTM0vJ0m<34i(nx+01>9186LiA|sN$xE^e2`$_(JX} z5vzh*fEYF0@sNH?eZ~%PjK@l(a^u6a3a(}trNroNS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5Sk21sKV*{@;n8QkZ|A_kz_`oP#W5t~-rE_5`Yetj4f~&pi0ds^Shd=eOL3t}$n=01 z^+2sHA|*%uGG0}6+9D$4cw}Lr-@?nC=lC6#3rr2YA-((fy*FvkzQt~QFZ$c)^Rs)~ z^Y87O8_g~r_;M2Oe5Mixh8d6A{U;svSkq2nbyz5uvn(>%#N+M!x;MB$8N~6->aMQ{rMwy0l|-cGnjrv ze@t35kzcCq!)cEi?jwvwijSpdm8#p^a{95KEvDB`(v8=4!jb7oEb~u)&@67qVv$#` z@!G>t${;E;|C~Dig)+nSjggrR(wPlWI`75BX0=C|FX~tOd%L4VS9?Wie&`doDW>Np zxE-0#RLJmIspQPGc1DSRIVFPkn?w}Wuq`uvJ+ESGt3r*+>l?ZqdV&99%Rf!@ncm11 z-e_&<&9-F5J4aa~j86Hn2)<{2#PD*W zPYrhvLt(?0;##f`yjvY!=x_e|$ru>1swJ)wB`Jv|saDBFsX&Us$iUEC*T78I$UMZz vz{=3b%EVmTz{1MFfcxvkrzje7^HVa@DsgM5T9FwE)WG2B>gTe~DWM4fjI;mN literal 0 HcmV?d00001 diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index e1fc8e3..8e04aa4 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -105,6 +105,11 @@ void PassageMainWindow::initAction() this->newFileAction->setShortcut(QKeySequence::New); this->newFileAction->setIcon(QIcon(":/icons/source/icons/newFile.png")); + // 模板 + this->templateAction = new QAction(tr("Template"), NULL); // 新建模板页 + this->templateAction->setStatusTip(tr("Use a template to create a new document")); + this->templateAction->setIcon(QIcon(":/icons/source/icons/template.png")); + this->openFileAtcion = new QAction(tr("Open File"),NULL); // 打开文件 this->openFileAtcion->setStatusTip(tr("Open an existing ofd file")); this->openFileAtcion->setShortcut(QKeySequence::Open); @@ -127,6 +132,29 @@ void PassageMainWindow::initAction() this->attributeAction = new QAction(tr("Attribute"),NULL); // 文档属性 this->attributeAction->setStatusTip(tr("Show you the attribute of the actived passage")); + // 程序首选项 + this->softwareSettingAction = new QAction(tr("Setting"),NULL); // setting + this->softwareSettingAction->setStatusTip(tr("Set the software's preference")); + this->softwareSettingAction->setIcon(QIcon(":/icons/source/icons/Setting.png")); + + // 编辑模式 + this->editModeAction = new QAction(tr("EditMode"), NULL); + this->editModeAction->setStatusTip(tr("change current state to edit mode")); + this->editModeAction->setIcon(QIcon(":/icons/source/icons/EditMode.png")); + + // 阅读模式 + this->viewModeAction = new QAction(tr("ViewMode"),NULL); + this->viewModeAction->setStatusTip(tr("change current state to edit mode")); + this->viewModeAction->setIcon(QIcon(":/icons/source/icons/ViewMode.png")); + + // 放大 + this->zoomInAction = new QAction(tr("ZoomIn"),NULL); + this->zoomInAction->setIcon(QIcon(":/icons/source/icons/ZoomIn.png")); + + // 缩小 + this->zoomOutAction = new QAction(tr("ZoomOut"), NULL); + this->zoomOutAction->setIcon(QIcon(":/icons/source/icons/ZoomOut.png")); + this->undoAction = new QAction(tr("Undo"),NULL); // 撤销操作 this->undoAction->setStatusTip(tr("Undo your last action")); this->undoAction->setShortcut(QKeySequence::Undo); @@ -205,18 +233,29 @@ void PassageMainWindow::initAction() this->aboutMenu = this->menuBar()->addMenu(tr("About")); this->filesMenu->addAction(this->newFileAction); + this->filesMenu->addAction(this->templateAction); // 模板 this->filesMenu->addAction(this->openFileAtcion); this->filesMenu->addAction(this->saveAction); this->filesMenu->addAction(this->saveAsAction); this->filesMenu->addAction(this->printAction); this->filesMenu->addAction(this->attributeAction); - + this->filesMenu->addSeparator(); + this->filesMenu->addAction(this->softwareSettingAction); // 软件设置 + + this->editMenu->addAction(this->editModeAction); // 编辑状态 + this->editMenu->addAction(this->viewModeAction); // 阅读状态 + this->editMenu->addSeparator(); + this->editMenu->addAction(this->zoomInAction); // 放大 + this->editMenu->addAction(this->zoomOutAction); // 缩小 + this->editMenu->addSeparator(); this->editMenu->addAction(this->undoAction); this->editMenu->addAction(this->redoAction); this->editMenu->addSeparator(); // 分割线 this->editMenu->addAction(this->copyAction); this->editMenu->addAction(this->cutAction); this->editMenu->addAction(this->pasteAction); + this->editMenu->addSeparator(); + this->formatMenu->addAction(this->textFormat); this->formatMenu->addAction(this->paragraphFormat); @@ -257,22 +296,22 @@ void PassageMainWindow::initAction() this->fontSizeCombox->insertItem(0,tr("6.5")); this->fontSizeCombox->insertItem(0,tr("5.5")); this->fontSizeCombox->insertItem(0,tr("5")); - this->fontSizeCombox->insertItem(0,tr("4.5")); - this->fontSizeCombox->insertItem(0,tr("5.25")); - this->fontSizeCombox->insertItem(0,tr("6.5")); - this->fontSizeCombox->insertItem(0,tr("7.5")); - this->fontSizeCombox->insertItem(0,tr("9")); - this->fontSizeCombox->insertItem(0,tr("10.5")); - this->fontSizeCombox->insertItem(0,tr("12")); - this->fontSizeCombox->insertItem(0,tr("14")); - this->fontSizeCombox->insertItem(0,tr("15")); - this->fontSizeCombox->insertItem(0,tr("16")); - this->fontSizeCombox->insertItem(0,tr("18")); - this->fontSizeCombox->insertItem(0,tr("21")); - this->fontSizeCombox->insertItem(0,tr("24")); - this->fontSizeCombox->insertItem(0,tr("27.5")); - this->fontSizeCombox->insertItem(0,tr("36")); - this->fontSizeCombox->insertItem(0,tr("42")); + this->fontSizeCombox->insertItem(0,tr("Size 8")); + this->fontSizeCombox->insertItem(0,tr("Size 7")); + this->fontSizeCombox->insertItem(0,tr("Size 6 Minor")); + this->fontSizeCombox->insertItem(0,tr("Size 6")); + this->fontSizeCombox->insertItem(0,tr("Size 5 Minor")); + this->fontSizeCombox->insertItem(0,tr("Size 5")); + this->fontSizeCombox->insertItem(0,tr("Size 4 Minor")); + this->fontSizeCombox->insertItem(0,tr("Size 4")); + this->fontSizeCombox->insertItem(0,tr("Size 3 Minor")); + this->fontSizeCombox->insertItem(0,tr("Size 3")); + this->fontSizeCombox->insertItem(0,tr("Size 2 Minor")); + this->fontSizeCombox->insertItem(0,tr("Size 2")); + this->fontSizeCombox->insertItem(0,tr("Size 1 Minor")); + this->fontSizeCombox->insertItem(0,tr("Size 1")); + this->fontSizeCombox->insertItem(0,tr("Prime Minor")); + this->fontSizeCombox->insertItem(0,tr("Prime")); @@ -339,8 +378,14 @@ void PassageMainWindow::initAction() this->file_toolBar->addAction(this->openFileAtcion); this->file_toolBar->addAction(this->saveAction); + this->edit_toolBar->addAction(this->editModeAction); + this->edit_toolBar->addAction(this->viewModeAction); + this->edit_toolBar->addSeparator(); this->edit_toolBar->addAction(this->undoAction); this->edit_toolBar->addAction(this->redoAction); + this->edit_toolBar->addSeparator(); + this->edit_toolBar->addAction(this->zoomInAction); + this->edit_toolBar->addAction(this->zoomOutAction); this->format_toolBar->addAction(this->textFormat); this->format_toolBar->addAction(this->paragraphFormat); @@ -426,6 +471,17 @@ void PassageMainWindow::connectAction() connect(this->imageFormat, SIGNAL(triggered(bool)), this, SLOT(imageDialog())); //修改图片 + connect(this->boldAction, SIGNAL(triggered(bool)), + this,SLOT(Bold())); // 加粗 + + connect(this->italicAction, SIGNAL(triggered(bool)), + this,SLOT(Italic())); // 斜体 + + connect(this->underlineAction, SIGNAL(triggered(bool)), + this,SLOT(underline())); // 下划线 + + + connect(this->area, SIGNAL(subWindowActivated(QMdiSubWindow*)), this->connector, SLOT(updateActivePassage(QMdiSubWindow*))); // 检测ActivePassage更新 } @@ -442,6 +498,37 @@ void PassageMainWindow::disconnectAction() } +/** + * @Author Chaoqun + * @brief 找到当前活跃的textblock,加粗 + * @param void + * @return void + * @date 2017/06/27 + */ +void PassageMainWindow::Bold() +{ + if(this->textBlock !=NULL) + { + this->textBlock->textBold(); // 加粗 + } +} + +void PassageMainWindow::Italic() +{ + if(this->textBlock != NULL) + { + this->textBlock->textItalic(); // 斜体 + } +} + +void PassageMainWindow::underline() +{ + if(this->textBlock != NULL) + { + this->textBlock->textUnderline(); // 下划线 + } +} + /** * @Author Chaoqun * @brief 打开 *.ofd 文件 diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index cfbf954..85ba408 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -49,11 +49,13 @@ private: // QAction // 文件 QAction * newFileAction; // 新建文件 + QAction * templateAction; // 新建模板项目 QAction * openFileAtcion; // 打开文件 QAction * saveAction; // 保存 QAction * saveAsAction; // 另存为 QAction * printAction; // 打印 QAction * attributeAction; // 文档属性 + QAction * softwareSettingAction; // 软件设置 // 编辑 QAction * undoAction; // 撤销 @@ -61,6 +63,10 @@ private: QAction * copyAction; // 复制 QAction * cutAction; // 剪切 QAction * pasteAction; // 粘贴 + QAction * viewModeAction; // 阅读模式 + QAction * editModeAction; // 编辑模式 + QAction * zoomInAction; // 放大 + QAction * zoomOutAction; // 缩小 // 插入 QAction * insertNewPageAction; // 插入新页面 @@ -121,6 +127,10 @@ private slots: void imageDialog(); // 打开图片框 void pageDialog(); // 打开页面框 + void Bold(); // 加粗事件 + void Italic(); // 斜体事件 + void underline(); // 下划线事件 + void acceptTextBlock(DocTextBlock* textBlock); // 接受当前处理的文字块的更新 void acceptTextBlockFormat(QTextBlockFormat blockFormat); // 接受当前处理的块格式 void acceptTextCharFormat(QTextCharFormat charFormat); // 接受当前处理的字符格式 -- Gitee From 9540c2c2d00b7acdd20f13401ada86a935c3348e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Wed, 28 Jun 2017 00:28:24 +0800 Subject: [PATCH 15/83] =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E7=BC=A9=E6=94=BE?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocBlock.cpp | 22 +++++--- ofdEditor/model/Doc/DocBlock.h | 3 +- ofdEditor/model/Doc/DocPage.cpp | 36 ++++++++++--- ofdEditor/model/Doc/DocPage.h | 1 + ofdEditor/model/Doc/DocPassage.cpp | 67 ++++++++++++++++++++++-- ofdEditor/model/Doc/DocPassage.h | 5 ++ ofdEditor/model/Tool/UnitTool.cpp | 42 +++++++++++++++ ofdEditor/model/Tool/UnitTool.h | 2 + ofdEditor/start/ui/PassageMainWindow.cpp | 44 +++++++++++++++- ofdEditor/start/ui/PassageMainWindow.h | 4 ++ 10 files changed, 206 insertions(+), 20 deletions(-) diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index ad7f8f6..e446b5b 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -248,6 +248,14 @@ void DocBlock::hoverMoveEvent(QGraphicsSceneHoverEvent *event) } +void DocBlock::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) +{ + + this->clearFocus(); + this->setFocus(); + +} + /** * @Author Chaoqun * @brief 鼠标按下时处理函数 @@ -401,8 +409,10 @@ bool DocBlock::isInResizeArea(const QPointF &pos) * @return RectAdjustStatus * @date 2017/05/19 */ -DocBlock::RectAdjustStatus DocBlock::currentStatus(const QPointF &pos) +DocBlock::RectAdjustStatus DocBlock::currentStatus( QPointF pos) { + qDebug() << "point: x:" << pos.rx() + << "y: " << pos.ry(); // qDebug() << "get current status."; if (isTextBlock()) { @@ -413,14 +423,14 @@ DocBlock::RectAdjustStatus DocBlock::currentStatus(const QPointF &pos) return blockResize; } // 画出可以移动的边缘 - qreal moveMargin = 5; // 边缘多少像素内可以移动 - QRectF left(0,0, + qreal moveMargin = 10; // 边缘多少像素内可以移动 + QRectF left(-5,0, moveMargin,this->blockSize.height()); - QRectF right(this->blockSize.width()-moveMargin,0, + QRectF right(this->blockSize.width()-moveMargin+5,0, moveMargin,this->blockSize.height()); - QRectF top(0,0, + QRectF top(0,-5, this->blockSize.width(),moveMargin); - QRectF bottom(0,this->blockSize.height() - moveMargin, + QRectF bottom(0,this->blockSize.height() - moveMargin+5, this->blockSize.width(),moveMargin); if(left.contains(pos) diff --git a/ofdEditor/model/Doc/DocBlock.h b/ofdEditor/model/Doc/DocBlock.h index 76df54d..3c2dcf6 100644 --- a/ofdEditor/model/Doc/DocBlock.h +++ b/ofdEditor/model/Doc/DocBlock.h @@ -34,7 +34,7 @@ public: DocPassage *getPassage(); // 获得所在文章 void paintHandle(QPainter& painter); // 绘制负责变换的控制器 qreal getZValue(){return this->realZValue;} // 获得当前块所在的Z值 - RectAdjustStatus currentStatus(const QPointF& pos); // 鼠标所在位置可以进行什么调整 + RectAdjustStatus currentStatus(QPointF pos); // 鼠标所在位置可以进行什么调整 bool isTextBlock(); // 判断是否DocBlock装的是否是DocTextBlock DocTextBlock *getTextBlock(); // 获得DocTextBlock @@ -62,6 +62,7 @@ protected: // 用来修改鼠标 void hoverMoveEvent (QGraphicsSceneHoverEvent *event); // 鼠标悬浮响应 + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); // 双击恢复正常 void mousePressEvent (QGraphicsSceneMouseEvent * event); void mouseMoveEvent (QGraphicsSceneMouseEvent *event); void mouseReleaseEvent (QGraphicsSceneMouseEvent * event); diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index ebb771c..ded13ee 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -263,6 +263,23 @@ void DocPage::remove() passage->removePage(this); } +// 设置页面的显示大小 +void DocPage::setScale(double scale) +{ + // 设置纸张大小 + + this->setFixedSize(scale * this->width(), + scale * this->height()); + + qDebug() << "Page Size after scale:" << this->width() + << " " << this->height(); + + // 缩放 + this->scale(scale,scale); + this->viewport()->update(); + this->update(); +} + /** * @Author Chaoqun @@ -281,7 +298,9 @@ void DocPage::paintEvent(QPaintEvent *event) QPainter painter(this->viewport()); // 坑,要画在viewport上 painter.setPen(Qt::blue); - QRectF rect = UnitTool::getBox(this->oldPos,this->newPos); + QRect rect = UnitTool::getBox( + mapFromScene(this->oldPos), + mapFromScene(this->newPos)); painter.drawRect(rect); painter.end(); // 结束 @@ -345,14 +364,15 @@ void DocPage::mousePressEvent(QMouseEvent *event) QPointF tempPoint = this->mapToScene(this->oldPos.rx(), this->oldPos.ry()); -// qDebug() <<"temp Point"<currentStatus( - block->mapFromScene(tempPoint)) - == DocBlock::blockMove) +// if(block->currentStatus( +// block->mapFromScene(tempPoint)) +// == DocBlock::blockMove) + if(block->cursor().shape() == Qt::SizeAllCursor) { -// qDebug()<<" Accepted Signal is blockMove"; + qDebug()<<" Accepted Signal is blockMove"; this->newBlockFlag = blockMove; } else if (block->currentStatus( @@ -417,6 +437,8 @@ void DocPage::mouseMoveEvent(QMouseEvent *event) } QPointF point = this->newPos - this->oldPos; + qDebug() << "Move x:" << point.rx() + << " y:" << point.ry(); this->activeBlock->moveBy(point.rx(),point.ry()); this->oldPos = this->mapToScene(event->pos()); diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index 0cc9d00..d4868c8 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -71,6 +71,7 @@ public slots: void setInsertBlockType(InsertBlockInfo& blockInfo); // 设置下一个要插入的block的信息 void remove(); // 移除本页 + void setScale(double scale); // 设置页面的显示大小 protected: void paintEvent(QPaintEvent *event); diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index b2c6a3c..d0ec7bf 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -407,6 +407,9 @@ void DocPassage::init() this->verticalWhite = 50; // 文章之间黑边 this->setAlignment(Qt::AlignHCenter); // 设置位置水平居中 + this->scaleFactor = 1.0; + + // 设置滚动条策略 this->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); this->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); @@ -475,12 +478,12 @@ void DocPassage::adjustWidgetSize() int length = this->pages.size(); for(int i = 0; i pages[i]->getSize().width()) + if(width < this->pages[i]->viewport()->width()) { - width = this->pages[i]->getSize().width(); + width = this->pages[i]->viewport()->width(); } - height += verticalWhite + this->pages[i]->getSize().height(); + height += verticalWhite + this->pages[i]->viewport()->height(); } height += verticalWhite; @@ -488,6 +491,10 @@ void DocPassage::adjustWidgetSize() // this->widget->setMinimumSize(width, height); // 设置内容大小 this->widget->resize(width,height); + this->widget->update(); + this->layout->update(); + this->update(); + this->viewport()->update(); // 保存计算结果 this->widgetWidth = width; @@ -567,5 +574,57 @@ void DocPassage::updatePageSizeInformation(QVector &changed_pages, // qDebug() << "Current Page Width = " // << UnitTool::pixelToMM(qobject_cast(focusWidget())->size().width()) // << "Current Page Height = " -// << UnitTool::pixelToMM(qobject_cast(focusWidget())->size().height()); + // << UnitTool::pixelToMM(qobject_cast(focusWidget())->size().height()); +} + +/** + * @Author Chaoqun + * @brief 放大页面 + * @param 参数 + * @return 返回值 + * @date 2017/06/27 + */ +void DocPassage::zoomIn() +{ + this->setScale(this->scaleFactor * 1.25); +} + +/** + * @Author Chaoqun + * @brief 缩小 + * @param 参数 + * @return 返回值 + * @date 2017/06/27 + */ +void DocPassage::zoomOut() +{ + this->setScale(this->scaleFactor * 0.8); +} + + +/** + * @Author Chaoqun + * @brief 设置文章的缩放 + * @param double scale + * @return void + * @date 2017/06/27 + */ +void DocPassage::setScale(double scale) +{ + // 重置DocPage的尺寸 + double scale_temp = scale / this->scaleFactor; // 获得需要缩小的增量 + + // 对每一页进行缩放 + int page_length = this->pages.size(); + + for(int i =0 ; i< page_length; i++) + { + pages[i]->setScale(scale_temp); // 进行缩放 + } + + // 调整页面的尺寸 + adjustWidgetSize(); + + this->scaleFactor = scale; + } diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index 551518e..0ca6591 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -99,6 +99,10 @@ public slots: double default_working_height, double default_working_x, double default_working_y); + void zoomIn(); // 缩小 + void zoomOut(); // 放大 + + void setScale(double scale); // 设置缩放 protected: void resizeEvent(QResizeEvent* event); void closeEvent(QCloseEvent *event); // 继承,关闭前提示保存 @@ -123,6 +127,7 @@ private: QWidget * widget; // 用widget做缓冲 double scaleFactor; // 表示缩放倍数 + double widgetWidth; // 内容的宽度 double widgetHeight; // 内容的高度 diff --git a/ofdEditor/model/Tool/UnitTool.cpp b/ofdEditor/model/Tool/UnitTool.cpp index fed56d7..062fbb5 100644 --- a/ofdEditor/model/Tool/UnitTool.cpp +++ b/ofdEditor/model/Tool/UnitTool.cpp @@ -97,6 +97,48 @@ QRectF UnitTool::getBox(QPointF &point1, QPointF &point2) return QRectF(x,y,w,h); } +/** + * @Author Chaoqun + * @brief 获得两个点组成的方形 + * @param 参数 + * @return 返回值 + * @date 2017/06/27 + */ +QRect UnitTool::getBox(QPoint point1, QPoint point2) +{ + int x1 = point1.x(); + int x2 = point2.x(); + + int y1 = point1.y(); + int y2 = point2.y(); + + int x,y,w,h; + + if(x1 < x2) + { + x = x1; + w = x2 - x1; + } + else + { + x = x2; + w = x1 - x2; + } + + if(y1 < y2) + { + y = y1; + h = y2 - y1; + } + else + { + y = y2; + h = y1 - y2; + } + + return QRect(x,y,w,h); +} + /** * @Author Chaoqun * @brief 判断两个数是否相等,因为公文的误差要求是 1mm, diff --git a/ofdEditor/model/Tool/UnitTool.h b/ofdEditor/model/Tool/UnitTool.h index 92b5552..6bdf13b 100644 --- a/ofdEditor/model/Tool/UnitTool.h +++ b/ofdEditor/model/Tool/UnitTool.h @@ -20,6 +20,8 @@ public: static QRectF getBox(QPointF& point1, QPointF& point2); // 获得两个点组成的方形 + static QRect getBox(QPoint point1, + QPoint point2); // 获得两个点组成的方形 static bool equal(double a, double b); // 因为double的误差,用来判断两个数是否相等 }; diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 641c281..98064a9 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -467,10 +467,20 @@ void PassageMainWindow::connectAction() // this->connector, &ActionConnector::addNewBlock); // 插入新块 //undo operation - connect(this->undoAction,SIGNAL(triggered(bool)),this->connector,SLOT(undo())); + connect(this->undoAction,SIGNAL(triggered(bool)), + this->connector,SLOT(undo())); //redo operation - connect(this->redoAction,SIGNAL(triggered(bool)),this->connector,SLOT(redo())); + connect(this->redoAction,SIGNAL(triggered(bool)), + this->connector,SLOT(redo())); + + // 放大 + connect(this->zoomInAction, SIGNAL(triggered(bool)), + this, SLOT(zoomIn())); + + // 缩小 + connect(this->zoomOutAction, SIGNAL(triggered(bool)), + this, SLOT(zooomOut())); connect(this->find_and_replace, SIGNAL(triggered(bool)), this->connector, SLOT(startFindAndReplace())); @@ -553,6 +563,36 @@ void PassageMainWindow::underline() } } +/** + * @Author Chaoqun + * @brief 放大函数 + * @param void + * @return void + * @date 2017/06/27 + */ +void PassageMainWindow::zoomIn() +{ +// DocPage* page = this->connector->getActivePage(); +// page->scale(2,2); + DocPassage* passage = this->connector->getActivePassage(); + passage->zoomIn(); +} + +/** + * @Author Chaoqun + * @brief 缩小函数/ + * @param void + * @return void + * @date 2017/06/27 + */ +void PassageMainWindow::zooomOut() +{ +// DocPage* page = this->connector->getActivePage(); +// page->scale(0.5,0.5); + DocPassage* passage = this->connector->getActivePassage(); + passage->zoomOut(); +} + /** * @Author Chaoqun * @brief 打开 *.ofd 文件 diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index 17282a6..62ce1dd 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -35,6 +35,7 @@ public slots: private: + double scale; // 菜单栏 QMenu * filesMenu; // 文件 @@ -137,6 +138,9 @@ private slots: void Italic(); // 斜体事件 void underline(); // 下划线事件 + void zoomIn(); // 放大 + void zooomOut(); // 缩小 + void acceptTextBlock(DocTextBlock* textBlock); // 接受当前处理的文字块的更新 void acceptTextBlockFormat(QTextBlockFormat blockFormat); // 接受当前处理的块格式 void acceptTextCharFormat(QTextCharFormat charFormat); // 接受当前处理的字符格式 -- Gitee From 3f6aaed985b452ea561579ca2bd57d3296a8980b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Wed, 28 Jun 2017 11:45:09 +0800 Subject: [PATCH 16/83] =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=BA=86=E4=BA=9B?= =?UTF-8?q?=E6=B2=A1=E7=94=A8=E7=9A=84=E6=96=87=E4=BB=B6=EF=BC=8C=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E4=BA=86=E4=B8=80=E4=B8=AA=E5=B0=8Fbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocBlock.cpp | 35 +-- ofdEditor/model/Doc/DocDrawParam.cpp | 6 - ofdEditor/model/Doc/DocDrawParam.h | 17 -- ofdEditor/model/Doc/DocImageBlock.h | 3 +- ofdEditor/model/Doc/DocLayer.cpp | 1 - ofdEditor/model/Doc/DocLayer.h | 3 - ofdEditor/model/Doc/DocPage.cpp | 10 +- ofdEditor/model/Doc/DocParaStyle.cpp | 13 - ofdEditor/model/Doc/DocParaStyle.h | 33 --- ofdEditor/model/Doc/DocParagraph.cpp | 6 - ofdEditor/model/Doc/DocParagraph.h | 21 -- ofdEditor/model/Doc/DocTableRow.cpp | 6 - ofdEditor/model/Doc/DocTableRow.h | 13 - ofdEditor/model/Doc/DocTemplate.cpp | 26 -- ofdEditor/model/Doc/DocTemplate.h | 24 -- ofdEditor/model/Doc/DocTextBlock.cpp | 1 - ofdEditor/model/model.pro | 10 - ofdEditor/start/app/APPInfo.cpp | 45 ---- ofdEditor/start/app/APPInfo.h | 30 --- ofdEditor/start/start.pro | 14 +- ofdEditor/start/ui/Editor.cpp | 14 - ofdEditor/start/ui/Editor.h | 22 -- ofdEditor/start/ui/Editor.ui | 330 ----------------------- ofdEditor/start/ui/PassageMainWindow.cpp | 4 +- 24 files changed, 24 insertions(+), 663 deletions(-) delete mode 100644 ofdEditor/model/Doc/DocDrawParam.cpp delete mode 100644 ofdEditor/model/Doc/DocDrawParam.h delete mode 100644 ofdEditor/model/Doc/DocParaStyle.cpp delete mode 100644 ofdEditor/model/Doc/DocParaStyle.h delete mode 100644 ofdEditor/model/Doc/DocParagraph.cpp delete mode 100644 ofdEditor/model/Doc/DocParagraph.h delete mode 100644 ofdEditor/model/Doc/DocTableRow.cpp delete mode 100644 ofdEditor/model/Doc/DocTableRow.h delete mode 100644 ofdEditor/model/Doc/DocTemplate.cpp delete mode 100644 ofdEditor/model/Doc/DocTemplate.h delete mode 100644 ofdEditor/start/app/APPInfo.cpp delete mode 100644 ofdEditor/start/app/APPInfo.h delete mode 100644 ofdEditor/start/ui/Editor.cpp delete mode 100644 ofdEditor/start/ui/Editor.h delete mode 100644 ofdEditor/start/ui/Editor.ui diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index e446b5b..516d349 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -226,6 +226,7 @@ void DocBlock::focusOutEvent(QFocusEvent *event) void DocBlock::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { // qDebug() << "Hovering."; + if (this->rectAdjust == blockResize || (this->currentStatus(event->pos()) == blockResize && this->isFocused)) @@ -238,12 +239,15 @@ void DocBlock::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { this->setCursor(Qt::SizeAllCursor); // 设置为移动样式 } - else if(this->cursor().shape() != Qt::IBeamCursor) + else if(this->rectAdjust == blockNone) { -// this->unsetCursor(); // 取消设置鼠标-效果不好 -// qDebug() <<"Redo hoverEnterEvent"; - QGraphicsProxyWidget::hoverEnterEvent(event); // 执行重新进入,设置鼠标 + if(this->isTextBlock()) + { + // 如果是文本框 + this->setCursor(Qt::IBeamCursor); + } } + QGraphicsProxyWidget::hoverMoveEvent(event); // 调用父类的调整函数 } @@ -265,18 +269,6 @@ void DocBlock::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) */ void DocBlock::mousePressEvent(QGraphicsSceneMouseEvent *event) { -// qDebug() << "Pressed."; - QPointF pos = event->pos(); // 获取鼠标位置 -// qDebug()<<"DocBlock Mouse Postion" << pos.x() -// << ", "<button() == Qt::LeftButton ) - { - // 如果按下的是鼠标左键,检测是否是可以修改大小或位置的状态 - this->rectAdjust = this->currentStatus(event->pos()); -// qDebug() << (rectAdjust == DocBlock::blockResize); - } -//qDebug() << (rectAdjust == DocBlock::blockResize); QGraphicsProxyWidget::mousePressEvent(event); } @@ -320,10 +312,9 @@ void DocBlock::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void DocBlock::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - if (event->button() == Qt::LeftButton && - this->rectAdjust != blockNone) + if(event->button() == Qt::LeftButton) { - this->rectAdjust = blockNone; + this->rectAdjust = this->currentStatus(event->pos()); } QGraphicsProxyWidget::mouseReleaseEvent(event); @@ -411,15 +402,11 @@ bool DocBlock::isInResizeArea(const QPointF &pos) */ DocBlock::RectAdjustStatus DocBlock::currentStatus( QPointF pos) { - qDebug() << "point: x:" << pos.rx() - << "y: " << pos.ry(); -// qDebug() << "get current status."; if (isTextBlock()) { if((pos.x() - this->size().width() + 15) > (this->size().height() - pos.y())) { - //qDebug() << "Mouse resizing."; return blockResize; } // 画出可以移动的边缘 @@ -437,7 +424,9 @@ DocBlock::RectAdjustStatus DocBlock::currentStatus( QPointF pos) || right.contains(pos) || top.contains(pos) || bottom.contains(pos)) + { return blockMove; + } // 如果未得出结果,则默认无操作 return blockNone; diff --git a/ofdEditor/model/Doc/DocDrawParam.cpp b/ofdEditor/model/Doc/DocDrawParam.cpp deleted file mode 100644 index 374e0cc..0000000 --- a/ofdEditor/model/Doc/DocDrawParam.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "DocDrawParam.h" - -DocDrawParam::DocDrawParam() -{ - -} diff --git a/ofdEditor/model/Doc/DocDrawParam.h b/ofdEditor/model/Doc/DocDrawParam.h deleted file mode 100644 index 5f715d1..0000000 --- a/ofdEditor/model/Doc/DocDrawParam.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef DOCDRAWPARAN_H -#define DOCDRAWPARAN_H - -#include "model_global.h" - -/** - * @Author Chaoqun - * @brief 结合渲染,因此这里的绘画模式要更接近于Qt的 - * @date 2017/04/30 - */ -class MODELSHARED_EXPORT DocDrawParam -{ -public: - DocDrawParam(); -}; - -#endif // DOCDRAWPARAN_H diff --git a/ofdEditor/model/Doc/DocImageBlock.h b/ofdEditor/model/Doc/DocImageBlock.h index 8ac5f9e..3e0fca9 100644 --- a/ofdEditor/model/Doc/DocImageBlock.h +++ b/ofdEditor/model/Doc/DocImageBlock.h @@ -12,7 +12,8 @@ class DocBlock; class ImagePropertiesDialog; -class MODELSHARED_EXPORT DocImageBlock : public QLabel +class MODELSHARED_EXPORT DocImageBlock + : public QLabel { Q_OBJECT public: diff --git a/ofdEditor/model/Doc/DocLayer.cpp b/ofdEditor/model/Doc/DocLayer.cpp index 07da660..86f8557 100644 --- a/ofdEditor/model/Doc/DocLayer.cpp +++ b/ofdEditor/model/Doc/DocLayer.cpp @@ -1,7 +1,6 @@ #include "DocLayer.h" #include "Doc/DocBlock.h" // 块 #include "Doc/DocTable.h" // 表格 -#include "Doc/DocDrawParam.h" #include "Doc/DocPage.h" #include "Doc/DocPassage.h" diff --git a/ofdEditor/model/Doc/DocLayer.h b/ofdEditor/model/Doc/DocLayer.h index d18bc3e..c8f4d36 100644 --- a/ofdEditor/model/Doc/DocLayer.h +++ b/ofdEditor/model/Doc/DocLayer.h @@ -8,7 +8,6 @@ class DocBlock; // 块 class DocTable; // 表格 -class DocDrawParam; // 默认绘画模式 class DocPassage; // 文章 /** @@ -44,8 +43,6 @@ private: QVector blocks; // 块 -文字块图形块的父类 QVector tables; // 表格 - DocDrawParam* drawParam; // 该层的默认绘画模式 - DocPage::Layer type; // 共三层 DocPage* parent; // 表明此层是哪一个页面的 diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index ded13ee..1d1fe54 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -364,15 +364,15 @@ void DocPage::mousePressEvent(QMouseEvent *event) QPointF tempPoint = this->mapToScene(this->oldPos.rx(), this->oldPos.ry()); - qDebug() <<"temp Point"<currentStatus( // block->mapFromScene(tempPoint)) // == DocBlock::blockMove) if(block->cursor().shape() == Qt::SizeAllCursor) { - qDebug()<<" Accepted Signal is blockMove"; + qDebug()<<" the cursor'shape is size all "; this->newBlockFlag = blockMove; } else if (block->currentStatus( @@ -437,8 +437,8 @@ void DocPage::mouseMoveEvent(QMouseEvent *event) } QPointF point = this->newPos - this->oldPos; - qDebug() << "Move x:" << point.rx() - << " y:" << point.ry(); +// qDebug() << "Move x:" << point.rx() +// << " y:" << point.ry(); this->activeBlock->moveBy(point.rx(),point.ry()); this->oldPos = this->mapToScene(event->pos()); diff --git a/ofdEditor/model/Doc/DocParaStyle.cpp b/ofdEditor/model/Doc/DocParaStyle.cpp deleted file mode 100644 index c1638e4..0000000 --- a/ofdEditor/model/Doc/DocParaStyle.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "DocParaStyle.h" -#include "Doc/DocImageBlock.h" - - -DocParaStyle::DocParaStyle() -{ - -} - -DocParaStyle::~DocParaStyle() -{ - -} diff --git a/ofdEditor/model/Doc/DocParaStyle.h b/ofdEditor/model/Doc/DocParaStyle.h deleted file mode 100644 index 8b63fa9..0000000 --- a/ofdEditor/model/Doc/DocParaStyle.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef DOCPARASTYLE_H -#define DOCPARASTYLE_H - -class DocImage; - - -class DocParaStyle -{ -public: - DocParaStyle(); - ~DocParaStyle(); -private: - double spaceAbove; // 段前间距 - double spaceBelow; // 段后间距 - - double indentFirstLine; // 首行缩进多少字符 - - double deltaLineSpace; // 行距 -- 和字体有关是一行高度的比例 - double fixedLineSpace; // 固定行距 -- 和字体无关,用毫米表示 - int LineSpaceType; // 0-deltaLineSpace - // 1-fixedlineSpace - - DocImage *background; // 段落可能需要背景颜色花纹等 - - // 大纲级别 -- 用来做大纲 - - enum ParaAlign{Left,Centered,Right,Fullness}; - // 段落缩进,居左,居中,居右,撑满 - ParaAlign alignment; - -}; - -#endif // DOCPARASTYLE_H diff --git a/ofdEditor/model/Doc/DocParagraph.cpp b/ofdEditor/model/Doc/DocParagraph.cpp deleted file mode 100644 index b35cdc9..0000000 --- a/ofdEditor/model/Doc/DocParagraph.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "DocParagraph.h" - -DocParagraph::DocParagraph() -{ - -} diff --git a/ofdEditor/model/Doc/DocParagraph.h b/ofdEditor/model/Doc/DocParagraph.h deleted file mode 100644 index 4dd38fc..0000000 --- a/ofdEditor/model/Doc/DocParagraph.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PARAGRAPH_H -#define PARAGRAPH_H - -#include "model_global.h" -#include - -class DocText; // 文字小段 - -class DocParaStyle; // 段落的样式 - -class MODELSHARED_EXPORT DocParagraph -{ -public: - DocParagraph(); -private: - DocParaStyle* paraStyle; // 段落的样式 - QVector texts; // 段落中的字体一致的几个文字 - -}; - -#endif // PARAGRAPH_H diff --git a/ofdEditor/model/Doc/DocTableRow.cpp b/ofdEditor/model/Doc/DocTableRow.cpp deleted file mode 100644 index 80b8354..0000000 --- a/ofdEditor/model/Doc/DocTableRow.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "DocTableRow.h" - -DocTableRow::DocTableRow() -{ - -} diff --git a/ofdEditor/model/Doc/DocTableRow.h b/ofdEditor/model/Doc/DocTableRow.h deleted file mode 100644 index 90fe403..0000000 --- a/ofdEditor/model/Doc/DocTableRow.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef DOCTABLEROW_H -#define DOCTABLEROW_H - -#include "model_global.h" // 导出lib使用 - - -class MODELSHARED_EXPORT DocTableRow -{ -public: - DocTableRow(); -}; - -#endif // DOCTABLEROW_H diff --git a/ofdEditor/model/Doc/DocTemplate.cpp b/ofdEditor/model/Doc/DocTemplate.cpp deleted file mode 100644 index 98ce4e9..0000000 --- a/ofdEditor/model/Doc/DocTemplate.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "DocTemplate.h" -// #include "DataTypes/page/CT_PageArea.h" // 页面大小 - -DocTemplate::DocTemplate() -{ - -} - -DocTemplate::~DocTemplate() -{ - // area空间释放 - - // 层空间释放 - int layers_length = layers.size(); - for(int i = 0; i < layers_length; i++) - // 挨个释放空间 - { - DocLayer* temp = this->layers.at(i); - if(temp != NULL) - { - delete temp; - (this->layers)[i] = NULL; - } - } - this->layers.clear(); // 清空层 -} diff --git a/ofdEditor/model/Doc/DocTemplate.h b/ofdEditor/model/Doc/DocTemplate.h deleted file mode 100644 index feecb49..0000000 --- a/ofdEditor/model/Doc/DocTemplate.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef DOCTEMPLATE_H -#define DOCTEMPLATE_H - -#include "model_global.h" // 导出lib使用 -#include - -// 类声明 -class DocLayer; -class CT_PageArea; - -class MODELSHARED_EXPORT DocTemplate -{ -public: - DocTemplate(); - ~DocTemplate(); -private: - QVector layers; // 模板的层 - - CT_PageArea* area; // 模板的页面大小 - - -}; - -#endif // DOCTEMPLATE_H diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 7d03adb..f29bdee 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -1,5 +1,4 @@ #include "DocTextBlock.h" -#include "Doc/DocParagraph.h" #include "Widget/ParagraphFormatDialog.h" #include "Widget/FontSettingDialog.h" #include "Doc/DocPage.h" diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index f34eb37..e85b559 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -29,17 +29,12 @@ SOURCES += model.cpp \ Doc/DocGraph.cpp \ Doc/DocLayer.cpp \ Doc/DocPage.cpp \ - Doc/DocParagraph.cpp \ Doc/DocPassage.cpp \ Doc/DocPicture.cpp \ Doc/DocTable.cpp \ Doc/DocTableCell.cpp \ - Doc/DocTableRow.cpp \ - Doc/DocTemplate.cpp \ Doc/DocText.cpp \ Doc/DocTextBlock.cpp \ - Doc/DocDrawParam.cpp \ - Doc/DocParaStyle.cpp \ Doc/DocTextStyle.cpp \ Tool/UnitTool.cpp \ Doc/DocPageScene.cpp \ @@ -64,18 +59,13 @@ HEADERS += model.h\ Doc/DocGraph.h \ Doc/DocLayer.h \ Doc/DocPage.h \ - Doc/DocParagraph.h \ Doc/DocPassage.h \ Doc/DocPicture.h \ Doc/DocTable.h \ Doc/DocTableCell.h \ - Doc/DocTableRow.h \ - Doc/DocTemplate.h \ Doc/DocText.h \ Doc/DocTextBlock.h \ - Doc/DocDrawParam.h \ Doc/DocBasicTypes.h \ - Doc/DocParaStyle.h \ Doc/DocTextStyle.h \ Tool/UnitTool.h \ Doc/DocPageScene.h \ diff --git a/ofdEditor/start/app/APPInfo.cpp b/ofdEditor/start/app/APPInfo.cpp deleted file mode 100644 index f0d377a..0000000 --- a/ofdEditor/start/app/APPInfo.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "APPInfo.h" -#include -#include -#include -#include - -APPInfo::APPInfo(QObject *parent) : QObject(parent) -{ - -} - -QString APPInfo::GetAppName() -{ - return this->appName; -} - -QString APPInfo::GetAppVersion() -{ - return this->appVersion; -} - -void APPInfo::initFromFile() -{ - QFile file(":/appInfo/source/appInfo.json"); // 将文件存在resource内 - if(!file.open(QIODevice::ReadOnly)) - { - qDebug() << "open app information file failed"; - return; - } - - QTextStream txtInput(&file); // 设置文件流 - QString str = txtInput.readAll(); // 读全部文件 - qDebug() << str; - -} - -void APPInfo::setAppName(QString &name) -{ - this->appName = name; -} - -void APPInfo::setAppVersion(QString &version) -{ - this->appVersion = version; -} diff --git a/ofdEditor/start/app/APPInfo.h b/ofdEditor/start/app/APPInfo.h deleted file mode 100644 index 5fe1839..0000000 --- a/ofdEditor/start/app/APPInfo.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef APPINFO_H -#define APPINFO_H - -#include -#include - -class APPInfo - : public QObject -{ - Q_OBJECT -public: - explicit APPInfo(QObject *parent = 0); - - QString GetAppName(); // 获得应用名称 - QString GetAppVersion(); // 获得应用版本号 - - void initFromFile(); // 从文件中获取版本信息 - -signals: - -public slots: - void setAppName(QString &name); // 设置名称 - void setAppVersion(QString &version); // 设置版本号 - -private: - QString appName; // 应用名称 - QString appVersion; // app版本 -}; - -#endif // APPINFO_H diff --git a/ofdEditor/start/start.pro b/ofdEditor/start/start.pro index 26e48ab..ae7a806 100644 --- a/ofdEditor/start/start.pro +++ b/ofdEditor/start/start.pro @@ -28,15 +28,11 @@ DEFINES += QT_DEPRECATED_WARNINGS SOURCES += main.cpp\ mainwindow.cpp \ ui/PassageMainWindow.cpp \ - ActionConnector/ActionConnector.cpp \ - app/APPInfo.cpp \ - ui/Editor.cpp + ActionConnector/ActionConnector.cpp HEADERS += mainwindow.h \ ui/PassageMainWindow.h \ - ActionConnector/ActionConnector.h \ - app/APPInfo.h \ - ui/Editor.h + ActionConnector/ActionConnector.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 @@ -57,10 +53,8 @@ win32{ } RESOURCES += \ - icons.qrc \ - appinfo.qrc + icons.qrc -FORMS += \ - ui/Editor.ui +FORMS += TRANSLATIONS = cn_start.ts diff --git a/ofdEditor/start/ui/Editor.cpp b/ofdEditor/start/ui/Editor.cpp deleted file mode 100644 index 7b4feb9..0000000 --- a/ofdEditor/start/ui/Editor.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "Editor.h" -#include "ui_Editor.h" - -Editor::Editor(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::Editor) -{ - ui->setupUi(this); -} - -Editor::~Editor() -{ - delete ui; -} diff --git a/ofdEditor/start/ui/Editor.h b/ofdEditor/start/ui/Editor.h deleted file mode 100644 index 97482ef..0000000 --- a/ofdEditor/start/ui/Editor.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef EDITOR_H -#define EDITOR_H - -#include - -namespace Ui { -class Editor; -} - -class Editor : public QMainWindow -{ - Q_OBJECT - -public: - explicit Editor(QWidget *parent = 0); - ~Editor(); - -private: - Ui::Editor *ui; -}; - -#endif // EDITOR_H diff --git a/ofdEditor/start/ui/Editor.ui b/ofdEditor/start/ui/Editor.ui deleted file mode 100644 index 8a0e476..0000000 --- a/ofdEditor/start/ui/Editor.ui +++ /dev/null @@ -1,330 +0,0 @@ - - - Editor - - - - 0 - 0 - 800 - 600 - - - - MainWindow - - - QMainWindow::AllowTabbedDocks|QMainWindow::AnimatedDocks - - - - - - 0 - 0 - 800 - 23 - - - - - - - toolBar - - - TopToolBarArea - - - false - - - - - - - - - - - - false - - - QDockWidget::NoDockWidgetFeatures - - - Qt::TopDockWidgetArea - - - 4 - - - - - - 0 - 0 - 189 - 22 - - - - - - - 190 - 0 - 69 - 22 - - - - - - - - - :/icons/source/icons/newFile.png - - - - 新建文件 - - - Ctrl+N - - - - - - :/icons/source/icons/openFile.png - - - - 打开文件 - - - Ctrl+O - - - - - - :/icons/source/icons/save.png - - - - 保存 - - - Ctrl+S - - - - - - :/icons/source/icons/saveAs.png - - - - 另存为 - - - Ctrl+Shift+S - - - - - - :/icons/source/icons/print.png - - - - 打印 - - - Ctrl+P - - - - - 文档属性 - - - - - - :/icons/source/icons/undo.png - - - - 撤销 - - - Ctrl+Z - - - - - - :/icons/source/icons/redo.png - - - - 重做 - - - Ctrl+Shift+Z - - - - - - :/icons/source/icons/copy.png - - - - 复制 - - - Backspace - - - - - - :/icons/source/icons/paste.png - - - - 粘贴 - - - - - - :/icons/source/icons/cut.png - - - - 剪切 - - - - - - :/icons/source/icons/insertNewPage.png - - - - 插入新页 - - - - - - :/icons/source/icons/insertTextBlock.png - - - - 插入文本框 - - - - - - :/icons/source/icons/insertImage.png - - - - 插入图片 - - - - - - :/icons/source/icons/insertTable.png - - - - 插入表格 - - - - - 页面设置 - - - - - - :/icons/source/icons/TextFormat.png - - - - 字体 - - - - - - :/icons/source/icons/paragraphFormat.png - - - - 段落 - - - - - - :/icons/source/icons/ImageFormat.png - - - - 图片设置 - - - - - - :/icons/source/icons/tableFormat.png - - - - 表格设置 - - - - - - :/icons/source/icons/AboutQpp.png - - - - 关于Qt - - - - - - :/icons/source/icons/help.png - - - - 关于本工程 - - - - - true - - - 加粗 - - - - - - diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 98064a9..515cf47 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -626,9 +626,7 @@ void PassageMainWindow::openFile() OFDParser ofdParser(tempPath + "/OFD.xml"); // 新建临时路径 // OFDParser ofdParser("C:/Users/User/Desktop/表格/OFD.xml"); OFD* data = ofdParser.getData(); // 读取出OFD文件 - qDebug() << tempPath + "/OFD.xml"; - OFDWriter writer(data, "E:/temp/"); - qDebug()<< "ofd file open"; + qDebug()<< "ofd file open" << tempPath + "/OFD.xml"; OFD_DocConvertor convert; DocPassage* passage = convert.ofd_to_doc(data); passage->setFilePath(path); // 设置文件路径 -- Gitee From 40dc495904708999d7ba791969bd410b0e9a6dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Wed, 28 Jun 2017 19:27:02 +0800 Subject: [PATCH 17/83] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=A7=BB=E9=99=A4DocBl?= =?UTF-8?q?ock=E6=B2=A1=E6=9C=89=E6=B8=85=E9=99=A4DocLayer=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/Doc_OFDConvertor.cpp | 2 +- ofdEditor/model/Convert/OFD_DocConvertor.cpp | 11 + ofdEditor/model/Doc/DocBlock.cpp | 5 + ofdEditor/model/Doc/DocLayer.cpp | 7 - ofdEditor/model/Doc/DocPassage.cpp | 3 + ofdEditor/model/Doc/DocTextBlock.cpp | 2 +- ofdEditor/model/Widget/DocInfoDialog.ui | 2 +- ofdEditor/model/Widget/FontSettingDialog.ui | 2 +- ofdEditor/model/Widget/InsertTableDialog.ui | 8 +- ofdEditor/model/Widget/PageDialog.ui | 2 +- .../model/Widget/ParagraphFormatDialog.ui | 18 +- .../model/Widget/ParagraphFormatWidget.cpp | 40 -- .../model/Widget/ParagraphFormatWidget.h | 34 -- .../model/Widget/ParagraphFormatWidget.ui | 383 ------------- .../model/Widget/imagepropertiesdialog.ui | 2 +- ofdEditor/model/cn_model.ts | 317 +++++------ ofdEditor/model/model.pro | 3 - ofdEditor/start/cn_start.ts | 515 ++++++++---------- ofdEditor/start/icons.qrc | 2 + ofdEditor/start/main.cpp | 1 + ofdEditor/start/source/icons/Find.png | Bin 0 -> 1427 bytes ofdEditor/start/source/icons/ofdEditor2.png | Bin 0 -> 21596 bytes ofdEditor/start/ui/PassageMainWindow.cpp | 10 + 23 files changed, 427 insertions(+), 942 deletions(-) delete mode 100644 ofdEditor/model/Widget/ParagraphFormatWidget.cpp delete mode 100644 ofdEditor/model/Widget/ParagraphFormatWidget.h delete mode 100644 ofdEditor/model/Widget/ParagraphFormatWidget.ui create mode 100644 ofdEditor/start/source/icons/Find.png create mode 100644 ofdEditor/start/source/icons/ofdEditor2.png diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp index 7ec91c0..cc30894 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp @@ -423,7 +423,7 @@ void Doc_OFDConvertor::buildText(CT_Layer* ctLayer,DocTextBlock *textBlock) UnitTool::pixelToMM(textBlock->pos().ry() + pixelLine), UnitTool::pixelToMM(pixelWidth), - UnitTool::pixelToMM(pixelLine) + UnitTool::pixelToMM(pixelLine) + 5 ); qDebug() << "After setBoundary pixelLine: "<< pixelLine; diff --git a/ofdEditor/model/Convert/OFD_DocConvertor.cpp b/ofdEditor/model/Convert/OFD_DocConvertor.cpp index a61073f..af53370 100644 --- a/ofdEditor/model/Convert/OFD_DocConvertor.cpp +++ b/ofdEditor/model/Convert/OFD_DocConvertor.cpp @@ -288,6 +288,17 @@ void OFD_DocConvertor::insertCT_Text(DocPage *page, DocPage::Layer layer, CT_Tex font.setPixelSize(UnitTool::mmToPixel(text->getSize())); // 字号 font.setFamily(textFont.family()); // 设置字体 + qDebug() << "italic " << text->getItalic(); + // 倾斜 + if(text->getItalic()) + { + font.setItalic(true); + } + + // 加粗 + int weight = text->getWeight(); // 获得粗细 + font.setWeight(weight / 8); + // 上下间距 blockFormat.setTopMargin(0); blockFormat.setBottomMargin(0); diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index 516d349..aa898aa 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -159,6 +159,11 @@ void DocBlock::remove() QGraphicsScene *scene = this->scene(); // 查找到本块所在的场景 scene->removeItem(this); // 从场景中移除该组件 + if(this->layer) + { + this->layer->removeBlock(this); + } + emit this->signals_blockRemoved(this); // 发出信号 } diff --git a/ofdEditor/model/Doc/DocLayer.cpp b/ofdEditor/model/Doc/DocLayer.cpp index 86f8557..cd6e820 100644 --- a/ofdEditor/model/Doc/DocLayer.cpp +++ b/ofdEditor/model/Doc/DocLayer.cpp @@ -45,13 +45,6 @@ DocLayer::~DocLayer() } this->tables.clear(); - // 释放绘制模式 - if(this->drawParam != NULL) - { - delete this->drawParam; - this->drawParam = NULL; - } - } /** diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index d0ec7bf..d61718e 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -208,6 +208,7 @@ void DocPassage::setFilePath(QString filePath) void DocPassage::setDocInfo(CT_DocInfo &docInfo) { this->docInfo->copy(docInfo); + this->setWindowTitle(this->docInfo->getTitle()); // 设置小窗口标题 } /** @@ -575,6 +576,8 @@ void DocPassage::updatePageSizeInformation(QVector &changed_pages, // << UnitTool::pixelToMM(qobject_cast(focusWidget())->size().width()) // << "Current Page Height = " // << UnitTool::pixelToMM(qobject_cast(focusWidget())->size().height()); + + this->adjustWidgetSize(); } /** diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index f29bdee..3c41138 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -682,7 +682,7 @@ void DocTextBlock::contextMenuEvent(QContextMenuEvent *event) this->ContextMenu->addAction(this->actionUnderline); // 下划线 this->ContextMenu->addAction(this->actionColor); // 颜色 this->ContextMenu->addSeparator(); // 分界线 - this->ContextMenu->addAction(this->actionFontSet); // 字体设置 +// this->ContextMenu->addAction(this->actionFontSet); // 字体设置 this->ContextMenu->addAction(this->actionParagraph); // 段落设置 this->ContextMenu->addAction(this->actionFontSetTest); // 字体 this->ContextMenu->addAction(this->actionRemove); // 移除操作 diff --git a/ofdEditor/model/Widget/DocInfoDialog.ui b/ofdEditor/model/Widget/DocInfoDialog.ui index 87d36cf..e1f7709 100644 --- a/ofdEditor/model/Widget/DocInfoDialog.ui +++ b/ofdEditor/model/Widget/DocInfoDialog.ui @@ -11,7 +11,7 @@ - Dialog + 文档信息 diff --git a/ofdEditor/model/Widget/FontSettingDialog.ui b/ofdEditor/model/Widget/FontSettingDialog.ui index 4a0f631..cfa097e 100644 --- a/ofdEditor/model/Widget/FontSettingDialog.ui +++ b/ofdEditor/model/Widget/FontSettingDialog.ui @@ -17,7 +17,7 @@ - Dialog + 字体设置窗口 diff --git a/ofdEditor/model/Widget/InsertTableDialog.ui b/ofdEditor/model/Widget/InsertTableDialog.ui index 9cf40cb..cf8a0ad 100644 --- a/ofdEditor/model/Widget/InsertTableDialog.ui +++ b/ofdEditor/model/Widget/InsertTableDialog.ui @@ -39,13 +39,13 @@ - 1 + 0 表格 - + 20 @@ -60,7 +60,7 @@ 行数列数 - + 20 @@ -99,7 +99,7 @@ 总体尺寸 - + 20 diff --git a/ofdEditor/model/Widget/PageDialog.ui b/ofdEditor/model/Widget/PageDialog.ui index cd37c45..396740a 100644 --- a/ofdEditor/model/Widget/PageDialog.ui +++ b/ofdEditor/model/Widget/PageDialog.ui @@ -11,7 +11,7 @@ - Dialog + 页面设置 diff --git a/ofdEditor/model/Widget/ParagraphFormatDialog.ui b/ofdEditor/model/Widget/ParagraphFormatDialog.ui index c5adafc..a70bc31 100644 --- a/ofdEditor/model/Widget/ParagraphFormatDialog.ui +++ b/ofdEditor/model/Widget/ParagraphFormatDialog.ui @@ -6,8 +6,8 @@ 0 0 - 480 - 640 + 448 + 511 @@ -17,17 +17,17 @@ - Dialog + 段落 false - + 10 30 - 451 + 411 451 @@ -37,7 +37,7 @@ 对齐方式 - + 10 @@ -146,7 +146,7 @@ 缩进 - + 10 @@ -193,12 +193,12 @@ 间距 - + 10 30 - 431 + 371 91 diff --git a/ofdEditor/model/Widget/ParagraphFormatWidget.cpp b/ofdEditor/model/Widget/ParagraphFormatWidget.cpp deleted file mode 100644 index 919781f..0000000 --- a/ofdEditor/model/Widget/ParagraphFormatWidget.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "ParagraphFormatWidget.h" -#include "ui_ParagraphFormatWidget.h" - -ParagraphFormatWidget::ParagraphFormatWidget(QWidget *parent) : - QWidget(parent), - ui(new Ui::ParagraphFormatWidget) -{ - ui->setupUi(this); // 安装ui文件 - this->init(); - this->setWindowFlags(Qt::Dialog); -} - -ParagraphFormatWidget::~ParagraphFormatWidget() -{ - delete ui; -} - -ParagraphFormatWidget::ParagraphFormatWidget( - const QTextBlockFormat &blockFormat, QWidget *parent) - :QWidget(parent),ui(new Ui::ParagraphFormatWidget) -{ - ui->setupUi(this); // 安装ui文件 - this->init(blockFormat); // 初始化 - -} - -void ParagraphFormatWidget::init() -{ - -} - -void ParagraphFormatWidget::init(const QTextBlockFormat &blockFormat) -{ - -} - -void ParagraphFormatWidget::closeWidget() -{ - -} diff --git a/ofdEditor/model/Widget/ParagraphFormatWidget.h b/ofdEditor/model/Widget/ParagraphFormatWidget.h deleted file mode 100644 index 1f0916c..0000000 --- a/ofdEditor/model/Widget/ParagraphFormatWidget.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef PARAGRAPHFORMATWIDGET_H -#define PARAGRAPHFORMATWIDGET_H - -#include - -#include - -namespace Ui { -class ParagraphFormatWidget; -} - -class ParagraphFormatWidget : public QWidget -{ - Q_OBJECT - -public: - explicit ParagraphFormatWidget(QWidget *parent = 0); - ~ParagraphFormatWidget(); - ParagraphFormatWidget(const QTextBlockFormat& blockFormat, - QWidget *parent = 0); - -signals: - void finished(int ok, QTextBlockFormat& blockFormat); // 信号 - -private: - Ui::ParagraphFormatWidget *ui; // 界面函数 - void init(); // 初始化函数 - void init( const QTextBlockFormat& blockFormat); // 初始化函数 - -private slots: - void closeWidget(); -}; - -#endif // PARAGRAPHFORMATWIDGET_H diff --git a/ofdEditor/model/Widget/ParagraphFormatWidget.ui b/ofdEditor/model/Widget/ParagraphFormatWidget.ui deleted file mode 100644 index a4b4401..0000000 --- a/ofdEditor/model/Widget/ParagraphFormatWidget.ui +++ /dev/null @@ -1,383 +0,0 @@ - - - ParagraphFormatWidget - - - Qt::NonModal - - - - 0 - 0 - 480 - 640 - - - - - 400 - 600 - - - - - 3940 - 2080 - - - - - 宋体 - 12 - - - - 段落属性 - - - - - 0 - 50 - 431 - 421 - - - - - - - - - - - 16 - - - - 常规 - - - Qt::AutoText - - - Qt::AlignCenter - - - - - - - 对齐方式: - - - - - - - QComboBox::AdjustToMinimumContentsLength - - - 10 - - - - 左对齐 - - - - - 右对齐 - - - - - 居中 - - - - - 自动对齐 - - - - - - - - 文字方向 - - - - - - - QComboBox::AdjustToMinimumContentsLength - - - 10 - - - - 自左向右 - - - - - 自右向左 - - - - - - - - Qt::Horizontal - - - - - - - - 宋体 - 16 - - - - 缩进 - - - Qt::AlignCenter - - - - - - - 整体缩进 - - - - - - - Qt::AlignCenter - - - - - - - 首行缩进 - - - - - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - - - - - - 宋体 - 16 - - - - 间距 - - - Qt::AlignCenter - - - - - - - 段前 - - - - - - - Qt::AlignCenter - - - - - - - 段后 - - - - - - - Qt::AlignCenter - - - - - - - 行高策略 - - - - - - - QComboBox::AdjustToMinimumContentsLength - - - 10 - - - - 单倍行高 - - - - - 多倍行高 - - - - - 固定值 - - - - - 最小值 - - - - - - - - 行高值 - - - - - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - - - - - - 宋体 - 16 - - - - 边距 - - - Qt::AlignCenter - - - - - - - 上边距 - - - - - - - Qt::AlignCenter - - - - - - - 左边距 - - - - - - - Qt::AlignCenter - - - - - - - 下边距 - - - - - - - Qt::AlignCenter - - - - - - - 右边距 - - - - - - - Qt::AlignCenter - - - - - - - 确定 - - - - - - - 取消 - - - - - - - - - diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.ui b/ofdEditor/model/Widget/imagepropertiesdialog.ui index e9fa6f1..d73ce0e 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.ui +++ b/ofdEditor/model/Widget/imagepropertiesdialog.ui @@ -11,7 +11,7 @@ - Dialog + 图片设置窗口 diff --git a/ofdEditor/model/cn_model.ts b/ofdEditor/model/cn_model.ts index dad1a07..943e11e 100644 --- a/ofdEditor/model/cn_model.ts +++ b/ofdEditor/model/cn_model.ts @@ -32,9 +32,13 @@ DocInfoDialog - Dialog - 文档属性 + 文档属性 + + + + 文档信息 + 文档信息 @@ -120,17 +124,17 @@ DocPage - + Open File 打开文件 - + OFD Editor - + Cannot open file %1. @@ -138,62 +142,114 @@ DocTextBlock - + Choose a Color 选择颜色 - + Set the font 设置字体 - + Bold 加粗 - + Italic 斜体 - + Underline 下划线 - + Color 颜色 - + Font 字体 - + Paragraph 段落 - + Remove 移除 - + FontDialogTest 字体 + + FindAndReplaceDock + + + Find/Replace + 查找或替换 + + + + Find: + 查找: + + + + Replace With: + 替换: + + + + Find Previous + 往前查找 + + + + Find Next + 往后查找 + + + + Replace + 替换 + + + + Replace All + 替换全部 + + + + Found in: + 找到: + + + + places. + 处。 + + FontSettingDialog - Dialog - 字体设置窗口 + 字体设置窗口 + + + + 字体设置窗口 + 字体 @@ -450,9 +506,13 @@ p, li { white-space: pre-wrap; } ImagePropertiesDialog - Dialog - 图片属性设置 + 图片属性设置 + + + + 图片设置窗口 + 图片设置 @@ -530,6 +590,69 @@ p, li { white-space: pre-wrap; } + + InsertTableDialog + + + 插入表格 + + + + + 表格 + + + + + 行数列数 + + + + + 行数: + + + + + 列数: + + + + + 总体尺寸 + + + + + + 宽: + + + + + + + + mm + + + + + + 高: + + + + + 高级 + + + + + 单元格大小 + + + PageDialog @@ -735,9 +858,13 @@ p, li { white-space: pre-wrap; } ParagraphFormatDialog - Dialog - 段落属性设置 + 段落属性设置 + + + + 段落 + @@ -861,152 +988,4 @@ p, li { white-space: pre-wrap; } - - ParagraphFormatWidget - - - 段落属性 - - - - - 常规 - - - - - 对齐方式: - - - - - 左对齐 - - - - - 右对齐 - - - - - 居中 - - - - - 自动对齐 - - - - - 文字方向 - - - - - 自左向右 - - - - - 自右向左 - - - - - 缩进 - - - - - 整体缩进 - - - - - 首行缩进 - - - - - 间距 - - - - - 段前 - - - - - 段后 - - - - - 行高策略 - - - - - 单倍行高 - - - - - 多倍行高 - - - - - 固定值 - - - - - 最小值 - - - - - 行高值 - - - - - 边距 - - - - - 上边距 - - - - - 左边距 - - - - - 下边距 - - - - - 右边距 - - - - - 确定 - - - - - 取消 - - - diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index e85b559..4bfdf05 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -38,7 +38,6 @@ SOURCES += model.cpp \ Doc/DocTextStyle.cpp \ Tool/UnitTool.cpp \ Doc/DocPageScene.cpp \ - Widget/ParagraphFormatWidget.cpp \ Widget/ParagraphFormatDialog.cpp \ Widget/FontSettingDialog.cpp \ Convert/OFD_DocConvertor.cpp \ @@ -69,7 +68,6 @@ HEADERS += model.h\ Doc/DocTextStyle.h \ Tool/UnitTool.h \ Doc/DocPageScene.h \ - Widget/ParagraphFormatWidget.h \ Widget/ParagraphFormatDialog.h \ Widget/FontSettingDialog.h \ Convert/OFD_DocConvertor.h \ @@ -109,7 +107,6 @@ win32{ } FORMS += \ - Widget/ParagraphFormatWidget.ui \ Widget/ParagraphFormatDialog.ui \ Widget/FontSettingDialog.ui \ Widget/DocInfoDialog.ui \ diff --git a/ofdEditor/start/cn_start.ts b/ofdEditor/start/cn_start.ts index acfe509..789b8fe 100644 --- a/ofdEditor/start/cn_start.ts +++ b/ofdEditor/start/cn_start.ts @@ -2,666 +2,607 @@ - Editor - - - MainWindow - - - - - toolBar - - - - - 新建文件 - - - - - Ctrl+N - - - - - 打开文件 - - - - - Ctrl+O - - - - - 保存 - - - - - Ctrl+S - - - - - 另存为 - - - - - Ctrl+Shift+S - - - - - 打印 - - - - - Ctrl+P - - - - - 文档属性 - - - - - 撤销 - - - - - Ctrl+Z - - - - - 重做 - - - - - Ctrl+Shift+Z - - - - - 复制 - - + PassageMainWindow - - Backspace - - - - - 粘贴 - - - - - 剪切 - + + OFD Editor + OFD版式文档编辑器 - - - 插入新页 - - - - - 插入文本框 - - - - - 插入图片 - - - - - 插入表格 - - - - - 页面设置 - - - - - 字体 - - - - - 段落 - - - - - 图片设置 - - - - - 表格设置 - - - - - 关于Qt - - - - - 关于本工程 - - - - - 加粗 - - - - - PassageMainWindow - + New File 新建文档 - + Create a new ofd file 创建要给ofd文档 - + + Template + 模板 + + + + Use a template to create a new document + 使用模板新建一个文档 + + + Open File 打开 - + Open an existing ofd file 打开一个存在的ofd文件 - + Save 保存 - + Save file 保存文件 - - + + Save as 另存为 - + Print 打印 - + Print your document 打印你的文档 - + Attribute 文档属性 - + Show you the attribute of the actived passage 查看你当前编辑的文档的属性 - + + Setting + 设置 + + + + Set the software's preference + 设置软件的首选项 + + + + EditMode + 编辑模式 + + + + + change current state to edit mode + 修改当前状态为编辑模式 + + + + ViewMode + 观察模式 + + + + ZoomIn + 放大 + + + + ZoomOut + 缩小 + + + Undo 撤销 - + Undo your last action 插销你的上一步操作 - + Redo 重做 - + Redo the action you undo 重做你刚撤销的操作 - + Copy 复制 - + Copy the content you selected 复制你选择的内容 - + Cut 剪切 - + Cut the content you selected 剪切你选择的内容 - + Paste 粘贴 - + Paste your pasteboard content 粘贴你剪贴板里的内容 - + + Find/Replace + 查找/替换 + + + + Find specific text or replace them + 查找给定文本,并可以替换 + + + Insert New Page 增加新页 - + Insert a new Page into document 插入一个新页面到文档 - + Insert TextBlock 插入文本框 - + Insert a new TextBlock 插入一个新的文本框 - + Insert Image 插入图片 - + Insert a image 插入一个图片 - + Insert Table 插入表格 - + Insert a table 插入一个表格 - + Page Format 页面格式 - + Set the page format 设置页面格式 - + Text Format 字体格式 - + Set the selected texts' format 设置选择的文本的字体格式 - + Paragraph Format 段落 - + Set this paragarph format 设置选择的段落的格式 - + Image Format 图片格式 - + Set the Selected image's format 设置选择的图片的格式 - + Table Format 表格格式 - + Set the selected table's format 设置选择的表格的格式 - + about Qt 关于Qt - + About App 关于本应用 - + About this Application 关于本应用 - + Help 帮助 - + Show the help Window 显示帮助页面 - + Files 文件 - - + + Edit 编辑 - - + + Format 格式 - - + + Insert 插入 - + About 关于 - + 72 - + 48 - - + 36 - + 28 - + 26 - - + 24 - + 22 - + 20 - - + 18 - - + 16 - - + 14 - - + 12 - + 11 - - + 10.5 - + 10 - - + 9 - + 8 - - + 7.5 - - + 6.5 - + 5.5 - + 5 - - 4.5 + + Size 8 八号 - - 5.25 + + Size 7 七号 - - 15 - + + Size 6 Minor + 小六 - - 21 - + + Size 6 + 六号 - - 27.5 - + + Size 5 Minor + 小五 - - 42 - + + Size 5 + 五号 - + + Size 4 Minor + 小四 + + + + Size 4 + 四号 + + + + Size 3 Minor + 小三 + + + + Size 3 + 三号 + + + + Size 2 Minor + 小二 + + + + Size 2 + 二号 + + + + Size 1 Minor + 小一 + + + + Size 1 + 一号 + + + + Prime Minor + 小初 + + + + Prime + 初号 + + + 4.5 + 八号 + + + 5.25 + 七号 + + + Bold 加粗 - + Set selected text Bold or not bold 将选择的文本加粗 - + Italic 斜体 - + Set the selected text Italic 设置选择的文本斜体 - + Underline 下划线 - + Set the selected text underline 设置选择的文本下划线 - + middle 居中 - + Set the selected paragraph align middle 设置选择的段落格式为居中 - + Left 左对齐 - + Set the selected paragraph align by left 设置选择的段落对齐样式为左对齐 - + Right 右对齐 - + Set the selected paragraph align by right 设置选中的段落的对齐样式为右对齐 - + jutify 两端对齐 - + Set the selected paragraph align by left and right 设置选择的文本的对齐样式为两端对齐 - + File 文件 - + TextBlock 文本框 - + JSON files(*.ofd) OFD文件(*ofd) - + Choose an ofd document file! 选择一个OFD文件! - + Save the passage content as a ofd file 保存文件为一个ofd文件 - + OFD files(*.ofd) diff --git a/ofdEditor/start/icons.qrc b/ofdEditor/start/icons.qrc index e19c7a7..2d109b3 100644 --- a/ofdEditor/start/icons.qrc +++ b/ofdEditor/start/icons.qrc @@ -35,5 +35,7 @@ source/icons/ZoomIn.png source/icons/ZoomOut.png source/icons/template.png + source/icons/Find.png + source/icons/ofdEditor2.png diff --git a/ofdEditor/start/main.cpp b/ofdEditor/start/main.cpp index 8a9f257..b7c188f 100644 --- a/ofdEditor/start/main.cpp +++ b/ofdEditor/start/main.cpp @@ -8,6 +8,7 @@ int main(int argc, char *argv[]) { QApplication a(argc, argv); + a.setWindowIcon(QIcon(":/icons/source/icons/ofdEditor2.png")); QTranslator model_translator; if(model_translator.load("cn_model.qm")) diff --git a/ofdEditor/start/source/icons/Find.png b/ofdEditor/start/source/icons/Find.png new file mode 100644 index 0000000000000000000000000000000000000000..a689a59d956bf72a4fa86cc8da0cfd4e7fb6d98b GIT binary patch literal 1427 zcmV;E1#J3>P)X5jDlHECq74OHveEUxXHPuUI9uU#>cs#ziySp1KBL*$gxz4^)%AbW0uTp}Semyf^3n4D!IDTIRNUIRA z>N`6-zd(3nrAq@a8#42G9LMh#fzcX-gM)+9jg5^z>Jr`p<4h^_x(v<6Az<~lx3}LA z5mvv{!_5B>(bVplxl2UfmFWmGiR1XEBCTi?f(Gz0&+Z{G?0Yhq^dBA`E(e3b&?c~y z@{pNdXb1X34wNA?zg9|}yV_6?1aASj4B5Okn0($qMF6z$Z}Z;a8b1hvV<80Oc;;%u z%r9N<285*n=z*`oFvMi$o&o^(%naermR$(IVCFL-vT6o1A1S4y zh?zgfaeP{2vx~sdzyShVuKB<;PD~KqA!u`ZWAWafqbNFd+594cJA4NG1$Ljz181p} zI!b@(6@s=^Xn{GA3#HWQvVs=%mr`0m2qE5uVF({GeSAZhGXprlD2fh!X@Ci)*Xx~i zIvoULnP)s6?s!?dmCXo1x^EjnJ=_S#2Wo3RBme^5%jm})}Vmo3`P z;S4isxad2pws$PZa5Nh2K_k6DKp;azpNvW0k4B?zQ)XZS3xeR%5=TrI#TNve27gOW zWHOn&zqz?79V%B{byq)|HY7WR7YH`$u0W-3Ve{T6rG#(D1X82X=-b*M=;QH!>B;Dj zy4$3{wy|tG1;XjtAvn}-=84+`p^xu>nr2!%1S#d5KhUSRrOyV-0<>wV5aOzK2#zrM zBn(4%=hh#~fpHB1JH*Oqf|T-;nbcW12&OsUINt~a{S2VS^a6(d{xP*Ey?5`OY>Yt!=A0 zI7?!Su5w=c95a|{L81v>%W$@A4hHs}Y04}8nPYp^1RXQjlCJn^7{~ETAK`QX092?m zxef0SGzeEE2pUoPGDR6v$-Df45ZPAwY6LG0)ZP}H!Qn&R^7n#H4q zP{j`_okjS1eaOh z?sOQ2Cy80C0tBmBq)Px#9s*X|a&Vib+E+#s5v))3mrClswp z8^5nLVXX;Y^^T;Je-Y768*13bn9TgEQtI#Y*hsYE_G$WGaNC$$V`JK`2&^IKg6vuo h*5>fFG{5qi@IUIxPPV$~{muXY002ovPDHLkV1iqYox%VB literal 0 HcmV?d00001 diff --git a/ofdEditor/start/source/icons/ofdEditor2.png b/ofdEditor/start/source/icons/ofdEditor2.png new file mode 100644 index 0000000000000000000000000000000000000000..ea3d118bae1dc74e8999512a34bb5ac9edffe46e GIT binary patch literal 21596 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 literal 0 HcmV?d00001 diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 515cf47..18265fd 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -98,9 +98,12 @@ void PassageMainWindow::init() this->setMinimumSize(960,720); this->setBackgroundRole(QPalette::Text); + this->setWindowTitle(tr("OFD Editor")); + this->setWindowIcon(QIcon(":/icons/source/icons/ofdEditor2.png")); this->find_and_replace_dock = new FindAndReplaceDock(NULL); this->addDockWidget(Qt::BottomDockWidgetArea, find_and_replace_dock); + this->find_and_replace_dock->setWindowIcon(QIcon(":/icons/source/icons/Find.png")); this->find_and_replace_dock->setMaximumHeight(60); this->find_and_replace_dock->setMinimumHeight(60); this->find_and_replace_dock->setVisible(false); @@ -156,11 +159,14 @@ void PassageMainWindow::initAction() this->editModeAction = new QAction(tr("EditMode"), NULL); this->editModeAction->setStatusTip(tr("change current state to edit mode")); this->editModeAction->setIcon(QIcon(":/icons/source/icons/EditMode.png")); + this->editModeAction->setCheckable(true); + this->editModeAction->setChecked(true); // 阅读模式 this->viewModeAction = new QAction(tr("ViewMode"),NULL); this->viewModeAction->setStatusTip(tr("change current state to edit mode")); this->viewModeAction->setIcon(QIcon(":/icons/source/icons/ViewMode.png")); + this->viewModeAction->setCheckable(true); // 放大 this->zoomInAction = new QAction(tr("ZoomIn"),NULL); @@ -195,9 +201,11 @@ void PassageMainWindow::initAction() this->pasteAction->setShortcut(QKeySequence::Paste); this->pasteAction->setIcon(QIcon(":/icons/source/icons/paste.png")); + // 查找 this->find_and_replace = new QAction(tr("Find/Replace"), NULL); //查找和替换 this->find_and_replace->setStatusTip(tr("Find specific text or replace them")); this->find_and_replace->setShortcut(QKeySequence::Find); + this->find_and_replace->setIcon(QIcon(":/icons/source/icons/Find.png")); //缺少Icon this->insertNewPageAction = new QAction(tr("Insert New Page"),NULL); // 插入新页面 @@ -407,6 +415,8 @@ void PassageMainWindow::initAction() this->edit_toolBar->addSeparator(); this->edit_toolBar->addAction(this->zoomInAction); this->edit_toolBar->addAction(this->zoomOutAction); + this->edit_toolBar->addSeparator(); + this->edit_toolBar->addAction(this->find_and_replace); this->format_toolBar->addAction(this->textFormat); this->format_toolBar->addAction(this->paragraphFormat); -- Gitee From 7fd039a15f938a3d915cd7a7418c9e59d56b4522 Mon Sep 17 00:00:00 2001 From: Pan Yanxing Date: Thu, 29 Jun 2017 15:40:42 +0800 Subject: [PATCH 18/83] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocImageBlock.cpp | 24 +- ofdEditor/model/Doc/DocImageBlock.h | 5 +- ofdEditor/model/Doc/DocPage.cpp | 8 +- ofdEditor/model/Doc/DocPassage.cpp | 14 +- ofdEditor/model/Tool/UnitTool.h | 4 +- ofdEditor/model/Widget/PageDialog.cpp | 2 +- .../model/Widget/SelectTemplateDialog.cpp | 73 ++++ ofdEditor/model/Widget/SelectTemplateDialog.h | 40 +++ .../model/Widget/SelectTemplateDialog.ui | 167 +++++++++ ofdEditor/model/cn_model.ts | 38 ++- ofdEditor/model/model.pro | 12 +- ofdEditor/model/resource.qrc | 9 + ofdEditor/model/template_icons/template_1.png | Bin 0 -> 41297 bytes .../model/template_icons/template_2 .png | Bin 0 -> 38409 bytes ofdEditor/model/template_icons/template_3.png | Bin 0 -> 36211 bytes ofdEditor/model/template_icons/template_4.png | Bin 0 -> 55274 bytes ofdEditor/model/template_icons/template_5.png | Bin 0 -> 30137 bytes .../start/ActionConnector/ActionConnector.cpp | 3 - ofdEditor/start/cn_start.ts | 323 +++++++++++------- ofdEditor/start/ui/PassageMainWindow.cpp | 232 ++++++++++++- ofdEditor/start/ui/PassageMainWindow.h | 9 +- 21 files changed, 803 insertions(+), 160 deletions(-) create mode 100644 ofdEditor/model/Widget/SelectTemplateDialog.cpp create mode 100644 ofdEditor/model/Widget/SelectTemplateDialog.h create mode 100644 ofdEditor/model/Widget/SelectTemplateDialog.ui create mode 100644 ofdEditor/model/resource.qrc create mode 100644 ofdEditor/model/template_icons/template_1.png create mode 100644 ofdEditor/model/template_icons/template_2 .png create mode 100644 ofdEditor/model/template_icons/template_3.png create mode 100644 ofdEditor/model/template_icons/template_4.png create mode 100644 ofdEditor/model/template_icons/template_5.png diff --git a/ofdEditor/model/Doc/DocImageBlock.cpp b/ofdEditor/model/Doc/DocImageBlock.cpp index afb1bef..37a9268 100644 --- a/ofdEditor/model/Doc/DocImageBlock.cpp +++ b/ofdEditor/model/Doc/DocImageBlock.cpp @@ -18,10 +18,17 @@ DocImageBlock::DocImageBlock(QWidget *parent) this->context_menu = new QMenu(this); change_image = new QAction(tr("Change Image"), NULL); set_image_properties = new QAction(tr("Set Image Properties"), NULL); + remove_image = new QAction(tr("Remove Image."), NULL); + remove_image->setShortcut(Qt::Key_Delete); + properties_dialog = new ImagePropertiesDialog(this, parent); width_height_ratio_locked = false; width_height_ratio = 0.0; + context_menu->addAction(this->change_image); + context_menu->addAction(this->set_image_properties); + context_menu->addAction(this->remove_image); + //signal-slots this->connect(this->change_image, SIGNAL(triggered()), this, SLOT(changeImage())); @@ -34,6 +41,10 @@ DocImageBlock::DocImageBlock(QWidget *parent) this, SLOT(imagePropertiesChanged(double,double, double,double, bool))); + this->connect(this->remove_image, + SIGNAL(triggered(bool)), + this, + SLOT(removeImage())); } /** @@ -85,6 +96,11 @@ double DocImageBlock::getWidthHeightRatio() return width_height_ratio; } +DocBlock *DocImageBlock::getBlock() +{ + return this->block; +} + /** * @Author Pan * @brief 焦点聚焦,显示边框 @@ -123,9 +139,6 @@ void DocImageBlock::focusOutEvent(QFocusEvent *e) */ void DocImageBlock::contextMenuEvent(QContextMenuEvent *ev) { - context_menu->addAction(this->change_image); - context_menu->addAction(this->set_image_properties); - context_menu->exec(ev->globalPos()); } @@ -170,6 +183,11 @@ void DocImageBlock::setImageProperties() properties_dialog->exec(); } +void DocImageBlock::removeImage() +{ + this->block->remove(); +} + /** * @Author Pan * @brief 槽函数,根据对话框的信息改动更新自身属性 diff --git a/ofdEditor/model/Doc/DocImageBlock.h b/ofdEditor/model/Doc/DocImageBlock.h index 3e0fca9..33275c7 100644 --- a/ofdEditor/model/Doc/DocImageBlock.h +++ b/ofdEditor/model/Doc/DocImageBlock.h @@ -22,7 +22,7 @@ public: void setBlock(DocBlock * _block); bool isWidthHeightRatioLocked(); double getWidthHeightRatio(); - + DocBlock * getBlock(); //获取代理它的DocBlock public slots: void imagePropertiesChanged(double new_width, double new_height, @@ -31,6 +31,7 @@ public slots: bool ratio_locked); void changeImage(); void setImageProperties(); + void removeImage(); protected: void focusInEvent(QFocusEvent *ev); @@ -42,10 +43,12 @@ private: QMenu * context_menu; //右键菜单 QAction * change_image; //更改图片 QAction * set_image_properties; //更改图片的位置和尺寸 + QAction * remove_image; //删除图片 ImagePropertiesDialog * properties_dialog; bool width_height_ratio_locked; double width_height_ratio; + signals: void sendImageInfo(double image_width, double image_height, diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index 1d1fe54..9203f87 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -271,8 +271,8 @@ void DocPage::setScale(double scale) this->setFixedSize(scale * this->width(), scale * this->height()); - qDebug() << "Page Size after scale:" << this->width() - << " " << this->height(); +// qDebug() << "Page Size after scale:" << this->width() +// << " " << this->height(); // 缩放 this->scale(scale,scale); @@ -372,7 +372,7 @@ void DocPage::mousePressEvent(QMouseEvent *event) // == DocBlock::blockMove) if(block->cursor().shape() == Qt::SizeAllCursor) { - qDebug()<<" the cursor'shape is size all "; +// qDebug()<<" the cursor'shape is size all "; this->newBlockFlag = blockMove; } else if (block->currentStatus( @@ -586,7 +586,7 @@ void DocPage::addImage() ratio *= 0.8; } else ratio = 1.0; - qDebug() << "Ratio = " << ratio; +// qDebug() << "Ratio = " << ratio; newBlock->setPos((page_width - image.width() * ratio) / 2, (page_height - image.height() * ratio) / 2); newBlock->resize(image.width() * ratio,image.height() * ratio); diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index d61718e..a4e3b2b 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -30,7 +30,7 @@ DocPassage::DocPassage(QWidget *parent) // this->addPage(new DocPage()); // 添加一个空白页面 setAttribute(Qt::WA_DeleteOnClose); - qDebug() << "DocPassage Constructor Finished."; +// qDebug() << "DocPassage Constructor Finished."; } /** @@ -91,15 +91,15 @@ void DocPassage::addPage(DocPage *page) { if(page == NULL) { - qDebug() << "DocPassage::addPage(DocPage* page) " - << "You have add a NULL pointer"; +// qDebug() << "DocPassage::addPage(DocPage* page) " +// << "You have add a NULL pointer"; return; } // 先添加到 vector page->setSize(default_width, default_height); - qDebug() << "!!Page width in pixel = " << page->size().width() - << "!!Page height in pixel = " << page->size().height(); +// qDebug() << "!!Page width in pixel = " << page->size().width() +// << "!!Page height in pixel = " << page->size().height(); page->has_working_area = default_using_working_area; page->working_area_height = default_working_height; page->working_area_width = default_working_width; @@ -220,7 +220,7 @@ void DocPassage::setDocInfo(CT_DocInfo &docInfo) */ void DocPassage::testMessage() { - qDebug()<<"passage success"; +// qDebug()<<"passage success"; } /** @@ -358,7 +358,7 @@ void DocPassage::resetDocId() docId.remove(docId.length() -21, 1); docId.remove(docId.length() - 25,1); docId.remove(0,1); - qDebug() << "uuid : " << docId; +// qDebug() << "uuid : " << docId; this->docInfo->setDocID(docId); } diff --git a/ofdEditor/model/Tool/UnitTool.h b/ofdEditor/model/Tool/UnitTool.h index 6bdf13b..7bfc2df 100644 --- a/ofdEditor/model/Tool/UnitTool.h +++ b/ofdEditor/model/Tool/UnitTool.h @@ -3,7 +3,7 @@ #include #include - +#include "model_global.h" /** * @Author Chaoqun @@ -11,7 +11,7 @@ * 或者是一些常用的工具函数 * @date 2017/05/01 */ -class UnitTool +class MODELSHARED_EXPORT UnitTool { public: UnitTool(); diff --git a/ofdEditor/model/Widget/PageDialog.cpp b/ofdEditor/model/Widget/PageDialog.cpp index 805e7cf..8f61892 100644 --- a/ofdEditor/model/Widget/PageDialog.cpp +++ b/ofdEditor/model/Widget/PageDialog.cpp @@ -303,7 +303,7 @@ void PageDialog::on_DefaultSetWorkingAreaChecked_clicked(bool checked) void PageDialog::on_CurrentPageSize_valueChanged() { - qDebug() << "Called"; +// qDebug() << "Called"; ui->CurrentSelectPageSize->setCurrentIndex(ui->CurrentSelectPageSize->findText(tr("Customized"))); } diff --git a/ofdEditor/model/Widget/SelectTemplateDialog.cpp b/ofdEditor/model/Widget/SelectTemplateDialog.cpp new file mode 100644 index 0000000..c558e9e --- /dev/null +++ b/ofdEditor/model/Widget/SelectTemplateDialog.cpp @@ -0,0 +1,73 @@ +#include "SelectTemplateDialog.h" +#include "ui_SelectTemplateDialog.h" +#include +# +SelectTemplateDialog::SelectTemplateDialog(QWidget *parent, PassageMainWindow * mainwindow) : + QDialog(parent), + ui(new Ui::SelectTemplateDialog) +{ + ui->setupUi(this); + this->mainwindow = mainwindow; + //初始化成员 + current_template_index = 0; + ui->CountLabel->setAlignment(Qt::AlignCenter); + //置入模板Icon + this->icons.push_back(new QPixmap(":/template_icon/template_icons/template_1.png")); +// qDebug() << "Icon 1 is null: " << icons[0]->isNull(); + this->icons.push_back(new QPixmap(":/template_icon/template_icons/template_2 .png")); + this->icons.push_back(new QPixmap(":/template_icon/template_icons/template_3.png")); + this->icons.push_back(new QPixmap(":/template_icon/template_icons/template_4.png")); + this->icons.push_back(new QPixmap(":/template_icon/template_icons/template_5.png")); + + ui->TemplateIcon->setPixmap(*(icons[current_template_index])); + ui->CountLabel->setText(QString::number(current_template_index + 1) + + "/" + QString::number(icons.size())); + + //链接信号槽 + this->connect(ui->NextTemplateButton, + SIGNAL(clicked(bool)), + this, + SLOT(nextTemplate())); + this->connect(ui->LastTemplateButton, + SIGNAL(clicked(bool)), + this, + SLOT(lastTemplate())); + this->connect(ui->buttonBox, + SIGNAL(accepted()), + this, + SLOT(emitCreateTemplateSignal())); +} + +SelectTemplateDialog::~SelectTemplateDialog() +{ + delete ui; +} + + +void SelectTemplateDialog::nextTemplate() +{ + if (current_template_index + 1 < icons.size()) + { + current_template_index++; + ui->TemplateIcon->setPixmap(*icons[current_template_index]); + ui->CountLabel->setText(QString::number(current_template_index + 1) + + "/" + QString::number(icons.size())); + } +} + +void SelectTemplateDialog::lastTemplate() +{ + if (current_template_index - 1 >= 0) + { + current_template_index--; + ui->TemplateIcon->setPixmap(*icons[current_template_index]); + ui->CountLabel->setText(QString::number(current_template_index + 1) + + "/" + QString::number(icons.size())); + } +} + +void SelectTemplateDialog::emitCreateTemplateSignal() +{ + qDebug() << "Emit create template signal."; + emit createTemplate(current_template_index); +} diff --git a/ofdEditor/model/Widget/SelectTemplateDialog.h b/ofdEditor/model/Widget/SelectTemplateDialog.h new file mode 100644 index 0000000..f6e92e7 --- /dev/null +++ b/ofdEditor/model/Widget/SelectTemplateDialog.h @@ -0,0 +1,40 @@ +#ifndef SELECTTEMPLATEDIALOG_H +#define SELECTTEMPLATEDIALOG_H + +#include +#include +#include +#include + +class PassageMainWindow; + +namespace Ui { +class SelectTemplateDialog; +} + +class MODELSHARED_EXPORT SelectTemplateDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SelectTemplateDialog(QWidget *parent, PassageMainWindow * mainwindow); + ~SelectTemplateDialog(); + +private: + Ui::SelectTemplateDialog *ui; + PassageMainWindow * mainwindow; + int current_template_index; + QVector icons; + +private slots: + void nextTemplate(); + void lastTemplate(); + void emitCreateTemplateSignal(); + + +signals: + void createTemplate(int index); +}; + + +#endif // SELECTTEMPLATEDIALOG_H diff --git a/ofdEditor/model/Widget/SelectTemplateDialog.ui b/ofdEditor/model/Widget/SelectTemplateDialog.ui new file mode 100644 index 0000000..82a0f0c --- /dev/null +++ b/ofdEditor/model/Widget/SelectTemplateDialog.ui @@ -0,0 +1,167 @@ + + + SelectTemplateDialog + + + + 0 + 0 + 401 + 459 + + + + Dialog + + + + + 29 + 406 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 97 + 70 + 201 + 291 + + + + + + + :/template_icons/source/templates/template_1.png + + + + + + 19 + 17 + 101 + 21 + + + + + Arial + 12 + 50 + false + + + + 选择页面模板 + + + + + + 124 + 21 + 251 + 16 + + + + Qt::Horizontal + + + + + + 35 + 410 + 75 + 23 + + + + 上一个 + + + + + + 118 + 410 + 75 + 23 + + + + 下一个 + + + + + + 158 + 370 + 71 + 16 + + + + + Arial + 11 + 50 + false + + + + + + + + + + + + + buttonBox + accepted() + SelectTemplateDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + SelectTemplateDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/ofdEditor/model/cn_model.ts b/ofdEditor/model/cn_model.ts index 943e11e..8b048ed 100644 --- a/ofdEditor/model/cn_model.ts +++ b/ofdEditor/model/cn_model.ts @@ -14,17 +14,22 @@ 设置图片属性 - + + Remove Image. + + + + Open File 打开文件 - + OFD Editor OFD Editor - + Cannot open file %1. 无法打开文件 %1. @@ -656,9 +661,8 @@ p, li { white-space: pre-wrap; } PageDialog - Dialog - 页面设置 + 页面设置 @@ -749,6 +753,7 @@ p, li { white-space: pre-wrap; } + 页面设置 @@ -988,4 +993,27 @@ p, li { white-space: pre-wrap; } + + SelectTemplateDialog + + + Dialog + + + + + 选择页面模板 + + + + + 上一个 + + + + + 下一个 + + + diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index 4bfdf05..8aa1141 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -50,7 +50,8 @@ SOURCES += model.cpp \ Widget/imagepropertiesdialog.cpp \ Widget/PageDialog.cpp \ Widget/InsertTableDialog.cpp \ - Widget/FindAndReplaceDock.cpp + Widget/FindAndReplaceDock.cpp \ + Widget/SelectTemplateDialog.cpp HEADERS += model.h\ model_global.h \ @@ -80,7 +81,8 @@ HEADERS += model.h\ Widget/imagepropertiesdialog.h \ Widget/PageDialog.h \ Widget/FindAndReplaceDock.h \ - Widget/InsertTableDialog.h + Widget/InsertTableDialog.h \ + Widget/SelectTemplateDialog.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 @@ -113,4 +115,8 @@ FORMS += \ Widget/imagepropertiesdialog.ui \ Widget/PageDialog.ui \ Widget/InsertTableDialog.ui \ - Widget/FindAndReplaceDock.ui + Widget/FindAndReplaceDock.ui \ + Widget/SelectTemplateDialog.ui + +RESOURCES += \ + resource.qrc diff --git a/ofdEditor/model/resource.qrc b/ofdEditor/model/resource.qrc new file mode 100644 index 0000000..1799847 --- /dev/null +++ b/ofdEditor/model/resource.qrc @@ -0,0 +1,9 @@ + + + template_icons/template_1.png + template_icons/template_2 .png + template_icons/template_3.png + template_icons/template_4.png + template_icons/template_5.png + + diff --git a/ofdEditor/model/template_icons/template_1.png b/ofdEditor/model/template_icons/template_1.png new file mode 100644 index 0000000000000000000000000000000000000000..318faec03a383616fdf188e0588e3a688f8f802c GIT binary patch literal 41297 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 literal 0 HcmV?d00001 diff --git a/ofdEditor/model/template_icons/template_3.png b/ofdEditor/model/template_icons/template_3.png new file mode 100644 index 0000000000000000000000000000000000000000..7ac12154b89ab2ed380fc29ce0904dfc62273d62 GIT binary patch literal 36211 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 literal 0 HcmV?d00001 diff --git a/ofdEditor/start/ActionConnector/ActionConnector.cpp b/ofdEditor/start/ActionConnector/ActionConnector.cpp index fa93f19..8aa7427 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.cpp +++ b/ofdEditor/start/ActionConnector/ActionConnector.cpp @@ -4,9 +4,6 @@ #include "Doc/DocPage.h" #include "DataTypes/document/ct_docinfo.h" #include "Widget/DocInfoDialog.h" - -#include "app/APPInfo.h" - #include #include diff --git a/ofdEditor/start/cn_start.ts b/ofdEditor/start/cn_start.ts index 789b8fe..ab83462 100644 --- a/ofdEditor/start/cn_start.ts +++ b/ofdEditor/start/cn_start.ts @@ -4,500 +4,577 @@ PassageMainWindow - + OFD Editor OFD版式文档编辑器 - + New File 新建文档 - + Create a new ofd file 创建要给ofd文档 - + Template 模板 - + Use a template to create a new document 使用模板新建一个文档 - + Open File 打开 - + Open an existing ofd file 打开一个存在的ofd文件 - + Save 保存 - + Save file 保存文件 - - + + Save as 另存为 - + Print 打印 - + Print your document 打印你的文档 - + Attribute 文档属性 - + Show you the attribute of the actived passage 查看你当前编辑的文档的属性 - + Setting 设置 - + Set the software's preference 设置软件的首选项 - + EditMode 编辑模式 - - + + change current state to edit mode 修改当前状态为编辑模式 - + ViewMode 观察模式 - + ZoomIn 放大 - + ZoomOut 缩小 - + Undo 撤销 - + Undo your last action 插销你的上一步操作 - + Redo 重做 - + Redo the action you undo 重做你刚撤销的操作 - + Copy 复制 - + Copy the content you selected 复制你选择的内容 - + Cut 剪切 - + Cut the content you selected 剪切你选择的内容 - + Paste 粘贴 - + Paste your pasteboard content 粘贴你剪贴板里的内容 - + Find/Replace 查找/替换 - + Find specific text or replace them 查找给定文本,并可以替换 - + Insert New Page 增加新页 - + Insert a new Page into document 插入一个新页面到文档 - + Insert TextBlock 插入文本框 - + Insert a new TextBlock 插入一个新的文本框 - + Insert Image 插入图片 - + Insert a image 插入一个图片 - + Insert Table 插入表格 - + Insert a table 插入一个表格 - + Page Format 页面格式 - + Set the page format 设置页面格式 - + Text Format 字体格式 - + Set the selected texts' format 设置选择的文本的字体格式 - + Paragraph Format 段落 - + Set this paragarph format 设置选择的段落的格式 - + Image Format 图片格式 - + Set the Selected image's format 设置选择的图片的格式 - + Table Format 表格格式 - + Set the selected table's format 设置选择的表格的格式 - + about Qt 关于Qt - + About App 关于本应用 - + About this Application 关于本应用 - + Help 帮助 - + Show the help Window 显示帮助页面 - + Files 文件 - - + + Edit 编辑 - - + + Format 格式 - - + + Insert 插入 - + About 关于 - + 72 - + 48 - + 36 - + 28 - + 26 - + 24 - + 22 - + 20 - + 18 - + 16 - + 14 - + 12 - + 11 - + 10.5 - + 10 - + 9 - + 8 - + 7.5 - + 6.5 - + 5.5 - + 5 - + Size 8 八号 - + Size 7 七号 - + Size 6 Minor 小六 - + Size 6 六号 - + Size 5 Minor 小五 - + Size 5 五号 - + Size 4 Minor 小四 - + Size 4 四号 - + Size 3 Minor 小三 - + Size 3 三号 - + Size 2 Minor 小二 - + Size 2 二号 - + Size 1 Minor 小一 - + Size 1 一号 - + Prime Minor 小初 - + Prime 初号 + + + JiMi 1Nian + 机密★1年 + + + + Te Ji + 特急 + + + + XXXXXWenJian + ×××××文件 + + + + XXX[2012]10Hao + ×××﹝2012﹞10号 + + + + XXXXXGuanYuXXXXXXDeTongZhi + ×××关于××××的通知 + + + + XXXXXXXX: + ×××××: + + + + OOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. +OOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. +OOOOXXXXXXXXXXXXXXXXXXXXXX. +OOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××。 + ×××××××××××××××××××××××××××××××××××。 + ××××××××××××××。 + ××××××××××××。×××××××××××××××××××××××××××××××××××××××××× + + + + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. +OOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. + ××××××××××××××××××××××××××××。 ×××××××××××××××××××××××××××××××××××××××××××。 + + + + XXXXXXXXXXXX + ×××××××××××× + + + + 2012Nian7Yue1Ri + 2012年7月1日 + + + + (XXXXXX) + (××××××) + + + + ChaoSong:XXXXXXX,XXXXX,XXXXXX + 抄送:×××××,××××××,××××××× + + + + XXXXXXXX + ×××××××××× + + + + 2012Nian7Yue1RiYinFa + 2012年7月1日印发 + 4.5 八号 @@ -507,102 +584,102 @@ 七号 - + Bold 加粗 - + Set selected text Bold or not bold 将选择的文本加粗 - + Italic 斜体 - + Set the selected text Italic 设置选择的文本斜体 - + Underline 下划线 - + Set the selected text underline 设置选择的文本下划线 - + middle 居中 - + Set the selected paragraph align middle 设置选择的段落格式为居中 - + Left 左对齐 - + Set the selected paragraph align by left 设置选择的段落对齐样式为左对齐 - + Right 右对齐 - + Set the selected paragraph align by right 设置选中的段落的对齐样式为右对齐 - + jutify 两端对齐 - + Set the selected paragraph align by left and right 设置选择的文本的对齐样式为两端对齐 - + File 文件 - + TextBlock 文本框 - + JSON files(*.ofd) OFD文件(*ofd) - + Choose an ofd document file! 选择一个OFD文件! - + Save the passage content as a ofd file 保存文件为一个ofd文件 - + OFD files(*.ofd) diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 18265fd..ebd9bfe 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -19,7 +19,6 @@ #include #include - #include "Doc/DocPassage.h" #include "ActionConnector/ActionConnector.h" #include "Loaders/ZipTool.h" // 压缩文件工具 @@ -32,6 +31,8 @@ #include "Widget/FindAndReplaceDock.h" #include "Convert/Doc_OFDConvertor.h" #include "ofd_writer.h" +#include "../model/Widget/SelectTemplateDialog.h" +#include "../model/Tool/UnitTool.h" PassageMainWindow::PassageMainWindow(QWidget *parent) :QMainWindow(parent) @@ -107,6 +108,11 @@ void PassageMainWindow::init() this->find_and_replace_dock->setMaximumHeight(60); this->find_and_replace_dock->setMinimumHeight(60); this->find_and_replace_dock->setVisible(false); + + this->select_template_dialog = new SelectTemplateDialog(NULL, this); + this->select_template_dialog->setFixedSize(select_template_dialog->size()); + connect(this->select_template_dialog, SIGNAL(createTemplate(int)), + this, SLOT(createTemplatePassage(int))); } /** @@ -493,7 +499,10 @@ void PassageMainWindow::connectAction() this, SLOT(zooomOut())); connect(this->find_and_replace, SIGNAL(triggered(bool)), - this->connector, SLOT(startFindAndReplace())); + this->connector, SLOT(startFindAndReplace()));//查找/替换 + + connect(this->templateAction, SIGNAL(triggered(bool)), + this, SLOT(templateDialog())); //模板选择 connect(this->insertTextBlockAction, SIGNAL(triggered()), this->connector, SLOT(addTextBlock())); // 插入文本框 @@ -525,9 +534,10 @@ void PassageMainWindow::connectAction() this,SLOT(underline())); // 下划线 - connect(this->area, SIGNAL(subWindowActivated(QMdiSubWindow*)), this->connector, SLOT(updateActivePassage(QMdiSubWindow*))); // 检测ActivePassage更新 + + } /** @@ -792,6 +802,11 @@ void PassageMainWindow::pageDialog() } } +void PassageMainWindow::templateDialog() +{ + this->select_template_dialog->exec(); +} + /** * @Author Chaoqun * @brief 接受当前处理的文字块的更新 @@ -906,6 +921,217 @@ void PassageMainWindow::acceptImageBlock(DocImageBlock *imageBlock) this->textBlock = NULL; } +void PassageMainWindow::createTemplatePassage(int index) +{ + qDebug() << "???"; + DocPassage * new_passage = new DocPassage(this); + //********************************************** + DocPage * new_page_1 = new DocPage(); + + new_passage->addPage(new_page_1); + //*********************************************** + QFont font1("SimHei", 15); + font1.setBold(false); + DocTextBlock * headtext_1 = new DocTextBlock(); + DocBlock * head_1 = new DocBlock(); + head_1->setWidget(headtext_1); + headtext_1->setContent("000001"); + head_1->setPos(UnitTool::mmToPixel(28), UnitTool::mmToPixel(37)); + head_1->resize(80, 30); + headtext_1->setFont(font1); + new_page_1->addBlock(head_1, DocPage::Body); + + DocTextBlock * headtext_2 = new DocTextBlock(); + DocBlock * head_2 = new DocBlock(); + head_2->setWidget(headtext_2); + headtext_2->setContent(tr("JiMi 1Nian")); + head_2->setPos(UnitTool::mmToPixel(28), UnitTool::mmToPixel(47)); + head_2->resize(120, 30); + headtext_2->setFont(font1); + new_page_1->addBlock(head_2, DocPage::Body); + + DocTextBlock * headtext_3 = new DocTextBlock(); + DocBlock * head_3 = new DocBlock(); + head_3->setWidget(headtext_3); + headtext_3->setContent(tr("Te Ji")); + head_3->setPos(UnitTool::mmToPixel(28), UnitTool::mmToPixel(57)); + head_3->resize(50, 30); + headtext_3->setFont(font1); + new_page_1->addBlock(head_3, DocPage::Body); + + QFont font2("SimSun", 43); + font2.setBold(true); + DocTextBlock * titletext_1 = new DocTextBlock(); + DocBlock * title_1 = new DocBlock(); + title_1->setWidget(titletext_1); + + titletext_1->setAlignment(Qt::AlignCenter); + title_1->setPos(UnitTool::mmToPixel(41), UnitTool::mmToPixel(73)); + title_1->resize(500, 80); + titletext_1->setFont(font2); + QTextCharFormat fmt; + fmt.setForeground(Qt::red); + titletext_1->mergeCurrentCharFormat(fmt); + titletext_1->setContent(tr("XXXXXWenJian")); + new_page_1->addBlock(title_1, DocPage::Body); + + QFont font3("FangSong", 15); + font3.setBold(false); + DocTextBlock * titletext_2 = new DocTextBlock(); + DocBlock * title_2 = new DocBlock(); + title_2->setWidget(titletext_2); + + titletext_2->setAlignment(Qt::AlignCenter); + title_2->setPos(UnitTool::mmToPixel(75), UnitTool::mmToPixel(104)); + title_2->resize(220, 35); + titletext_2->setFont(font3); + + titletext_2->setContent(tr("XXX[2012]10Hao")); + new_page_1->addBlock(title_2, DocPage::Body); + + QFont font4("SimSun", 27); + font4.setBold(false); + DocTextBlock * bodytext_1 = new DocTextBlock(); + DocBlock * body_1 = new DocBlock(); + body_1->setWidget(bodytext_1); + + bodytext_1->setAlignment(Qt::AlignCenter); + body_1->setPos(UnitTool::mmToPixel(40), UnitTool::mmToPixel(128)); + body_1->resize(500, 50); + bodytext_1->setFont(font4); + + bodytext_1->setContent(tr("XXXXXGuanYuXXXXXXDeTongZhi")); + new_page_1->addBlock(body_1, DocPage::Body); + + QFont font5("FangSong", 22); + font5.setBold(false); + DocTextBlock * bodytext_2 = new DocTextBlock(); + DocBlock * body_2 = new DocBlock(); + body_2->setWidget(bodytext_2); + + bodytext_2->setAlignment(Qt::AlignLeft); + body_2->setPos(UnitTool::mmToPixel(28), UnitTool::mmToPixel(150)); + body_2->resize(250, 35); + bodytext_2->setFont(font5); + + bodytext_2->setContent(tr("XXXXXXXX:")); + new_page_1->addBlock(body_2, DocPage::Body); + + DocTextBlock * bodytext_3 = new DocTextBlock(); + DocBlock * body_3 = new DocBlock(); + body_3->setWidget(bodytext_3); + + bodytext_3->setAlignment(Qt::AlignLeft); + body_3->setPos(UnitTool::mmToPixel(28), UnitTool::mmToPixel(160)); + body_3->resize(600, 400); + bodytext_3->setFont(font5); + + bodytext_3->setContent(tr("OOOOXXXXXXXXXXXXXXXXXXXXXX" + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX." + "\nOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + "XXXXXXXXXXXXXXXXXXX.\nOOOOXXXXXXXXX" + "XXXXXXXXXXXXX.\nOOOOXXXXXXXXXXXXXXX" + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")); + new_page_1->addBlock(body_3, DocPage::Body); + //*********************************************** + DocPage * new_page_2 = new DocPage(); + + new_passage->addPage(new_page_2); + //*********************************************** + DocTextBlock * bodytext_4 = new DocTextBlock(); + DocBlock * body_4 = new DocBlock(); + body_4->setWidget(bodytext_4); + + bodytext_4->setAlignment(Qt::AlignLeft); + body_4->setPos(UnitTool::mmToPixel(28), UnitTool::mmToPixel(37)); + body_4->resize(600, 200); + bodytext_4->setFont(font5); + + bodytext_4->setContent(tr("XXXXXXXXXXXXXXXXXXXXXX" + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX." + "\nOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + "XXXXXXXXXXXXXXXXXXX.")); + new_page_2->addBlock(body_4, DocPage::Body); + + DocTextBlock * bodytext_5 = new DocTextBlock(); + DocBlock * body_5 = new DocBlock(); + body_5->setWidget(bodytext_5); + + bodytext_5->setAlignment(Qt::AlignCenter); + body_5->setPos(UnitTool::mmToPixel(120), UnitTool::mmToPixel(85)); + body_5->resize(200, 35); + bodytext_5->setFont(font5); + + bodytext_5->setContent(tr("XXXXXXXXXXXX")); + new_page_2->addBlock(body_5, DocPage::Body); + + QFont font6("FangSong", 16); + DocTextBlock * bodytext_6 = new DocTextBlock(); + DocBlock * body_6 = new DocBlock(); + body_6->setWidget(bodytext_6); + + bodytext_6->setAlignment(Qt::AlignCenter); + body_6->setPos(UnitTool::mmToPixel(120), UnitTool::mmToPixel(95)); + body_6->resize(200, 35); + bodytext_6->setFont(font6); + + bodytext_6->setContent(tr("2012Nian7Yue1Ri")); + new_page_2->addBlock(body_6, DocPage::Body); + + DocTextBlock * bodytext_7 = new DocTextBlock(); + DocBlock * body_7 = new DocBlock(); + body_7->setWidget(bodytext_7); + + bodytext_7->setAlignment(Qt::AlignCenter); + body_7->setPos(UnitTool::mmToPixel(34), UnitTool::mmToPixel(108)); + body_7->resize(250, 35); + bodytext_7->setFont(font5); + + bodytext_7->setContent(tr("(XXXXXX)")); + new_page_2->addBlock(body_7, DocPage::Body); + + DocTextBlock * endtext_1 = new DocTextBlock(); + DocBlock * end_1 = new DocBlock(); + end_1->setWidget(endtext_1); + + endtext_1->setAlignment(Qt::AlignLeft); + end_1->setPos(UnitTool::mmToPixel(30), UnitTool::mmToPixel(230)); + end_1->resize(600, 35); + endtext_1->setFont(font6); + + endtext_1->setContent(tr("ChaoSong:XXXXXXX,XXXXX,XXXXXX")); + new_page_2->addBlock(end_1, DocPage::Body); + + DocTextBlock * endtext_2 = new DocTextBlock(); + DocBlock * end_2 = new DocBlock(); + end_2->setWidget(endtext_2); + + endtext_2->setAlignment(Qt::AlignLeft); + end_2->setPos(UnitTool::mmToPixel(30), UnitTool::mmToPixel(240)); + end_2->resize(250, 35); + endtext_2->setFont(font6); + + endtext_2->setContent(tr("XXXXXXXX")); + new_page_2->addBlock(end_2, DocPage::Body); + + DocTextBlock * endtext_3 = new DocTextBlock(); + DocBlock * end_3 = new DocBlock(); + end_3->setWidget(endtext_3); + + endtext_3->setAlignment(Qt::AlignCenter); + end_3->setPos(UnitTool::mmToPixel(110), UnitTool::mmToPixel(240)); + end_3->resize(300, 35); + endtext_3->setFont(font6); + + endtext_3->setContent(tr("2012Nian7Yue1RiYinFa")); + new_page_2->addBlock(end_3, DocPage::Body); + + addDocPassage(new_passage); + +} + /** * @Author Chaoqun * @brief 获取激活的窗口 diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index 62ce1dd..5bab185 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -17,6 +17,7 @@ class DocTextBlock; class ActionConnector; // 函数功能的中间件 class DocImageBlock; class FindAndReplaceDock; +class SelectTemplateDialog; // 编辑窗口的主界面 class PassageMainWindow @@ -33,7 +34,7 @@ public slots: DocPassage *activeMdiChild(); // 获取活动的窗口 DocPassage *addDocPassage(DocPassage * passage); - + void createTemplatePassage(int index); private: double scale; @@ -123,7 +124,7 @@ private: DocImageBlock *imageBlock; //图片块 FindAndReplaceDock * find_and_replace_dock; //查找 & 替换 - + SelectTemplateDialog * select_template_dialog; //选择模板对话框 private slots: void openFile(); // 打开新文件 @@ -133,7 +134,7 @@ private slots: void paragraphDialog(); // 打开段落框 void imageDialog(); // 打开图片框 void pageDialog(); // 打开页面框 - + void templateDialog(); //打开模板选择 void Bold(); // 加粗事件 void Italic(); // 斜体事件 void underline(); // 下划线事件 @@ -145,8 +146,6 @@ private slots: void acceptTextBlockFormat(QTextBlockFormat blockFormat); // 接受当前处理的块格式 void acceptTextCharFormat(QTextCharFormat charFormat); // 接受当前处理的字符格式 void acceptImageBlock(DocImageBlock * imageBlock); //接受当前处理的图片块 - - }; #endif // PASSAGEMAINWINDOW_H -- Gitee From ede782e9d9981accbf159c1ae4cc838408885315 Mon Sep 17 00:00:00 2001 From: Pan Yanxing Date: Thu, 29 Jun 2017 15:51:44 +0800 Subject: [PATCH 19/83] =?UTF-8?q?=E5=B0=8F=E6=94=B9=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/start/ui/PassageMainWindow.cpp | 14 ++++++++++++++ ofdEditor/start/ui/PassageMainWindow.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index ebd9bfe..ac77777 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -537,7 +537,11 @@ void PassageMainWindow::connectAction() connect(this->area, SIGNAL(subWindowActivated(QMdiSubWindow*)), this->connector, SLOT(updateActivePassage(QMdiSubWindow*))); // 检测ActivePassage更新 + connect(this->editModeAction, SIGNAL(triggered(bool)), + this, SLOT(switchToEditMode())); + connect(this->viewModeAction, SIGNAL(triggered(bool)), + this, SLOT(switchToViewMode())); } /** @@ -921,6 +925,16 @@ void PassageMainWindow::acceptImageBlock(DocImageBlock *imageBlock) this->textBlock = NULL; } +void PassageMainWindow::switchToEditMode() +{ + this->viewModeAction->setChecked(false); +} + +void PassageMainWindow::switchToViewMode() +{ + this->editModeAction->setChecked(false); +} + void PassageMainWindow::createTemplatePassage(int index) { qDebug() << "???"; diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index 5bab185..ca65ac0 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -146,6 +146,9 @@ private slots: void acceptTextBlockFormat(QTextBlockFormat blockFormat); // 接受当前处理的块格式 void acceptTextCharFormat(QTextCharFormat charFormat); // 接受当前处理的字符格式 void acceptImageBlock(DocImageBlock * imageBlock); //接受当前处理的图片块 + + void switchToEditMode(); //切换到编辑模式 + void switchToViewMode(); //切换到阅读模式 }; #endif // PASSAGEMAINWINDOW_H -- Gitee From d74e58e156d4aea4e94d9772eb8b7aba63eb12ce Mon Sep 17 00:00:00 2001 From: Pan Yanxing Date: Thu, 29 Jun 2017 15:53:54 +0800 Subject: [PATCH 20/83] =?UTF-8?q?=E5=8F=88=E4=B8=80=E7=82=B9=E5=B0=8F?= =?UTF-8?q?=E6=94=B9=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/start/ui/PassageMainWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index ac77777..b3a37a3 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -309,6 +309,7 @@ void PassageMainWindow::initAction() // 文本操作工具栏部分/ this->fontCombox = new QFontComboBox(); + this->fontCombox->setEditable(false); this->fontSizeCombox = new QComboBox(); this->fontSizeCombox->insertItem(0,tr("72")); this->fontSizeCombox->insertItem(0,tr("48")); -- Gitee From bae4c3ec3989ee56d214e2044622ee51c605461a Mon Sep 17 00:00:00 2001 From: Pan Yanxing Date: Thu, 29 Jun 2017 17:46:32 +0800 Subject: [PATCH 21/83] =?UTF-8?q?=E7=BB=99=E6=A8=A1=E6=9D=BF=E5=8A=A0?= =?UTF-8?q?=E4=BA=86=E4=B8=80=E6=9D=A1=E7=BA=A2=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/template_icons/red_line.png | Bin 0 -> 478 bytes ofdEditor/start/icons.qrc | 1 + ofdEditor/start/source/red_line.png | Bin 0 -> 439 bytes ofdEditor/start/ui/PassageMainWindow.cpp | 8 ++++++++ 4 files changed, 9 insertions(+) create mode 100644 ofdEditor/model/template_icons/red_line.png create mode 100644 ofdEditor/start/source/red_line.png diff --git a/ofdEditor/model/template_icons/red_line.png b/ofdEditor/model/template_icons/red_line.png new file mode 100644 index 0000000000000000000000000000000000000000..1a49a19e0f2a8878e79d0c06a3dd5708db71f90d GIT binary patch literal 478 zcmeAS@N?(olHy`uVBq!ia0vp^hk&@Bg9%8gyH36Wq!^2X+?^QKos)S9a~60+7BevL9R^{>boFyt I=akR{0Fr5eSpWb4 literal 0 HcmV?d00001 diff --git a/ofdEditor/start/icons.qrc b/ofdEditor/start/icons.qrc index 2d109b3..8cf40b4 100644 --- a/ofdEditor/start/icons.qrc +++ b/ofdEditor/start/icons.qrc @@ -37,5 +37,6 @@ source/icons/template.png source/icons/Find.png source/icons/ofdEditor2.png + source/red_line.png diff --git a/ofdEditor/start/source/red_line.png b/ofdEditor/start/source/red_line.png new file mode 100644 index 0000000000000000000000000000000000000000..2166424e7d6b86eb9213ef390c9999dd8717aa62 GIT binary patch literal 439 zcmeAS@N?(olHy`uVBq!ia0vp^hk&@Bg9%8gyH36Wq!^2X+?^QKos)S9a~60+7BevL9R^{>Rtz_RiE{>%@rEppP5 ziq0R5x8setContent(tr("2012Nian7Yue1RiYinFa")); new_page_2->addBlock(end_3, DocPage::Body); + DocImageBlock * line = new DocImageBlock(); + DocBlock * line_block = new DocBlock(); + line_block->setWidget(line); + line->setPixmap(QPixmap(":/icons/source/red_line.png")); + line_block->setPos(UnitTool::mmToPixel(28), UnitTool::mmToPixel(114)); + line_block->resize(580, 3); + new_page_1->addBlock(line_block, DocPage::Body); + addDocPassage(new_passage); } -- Gitee From ee4c796e535b2f0fd989ac9ec8bde591796c5b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Thu, 29 Jun 2017 19:57:58 +0800 Subject: [PATCH 22/83] =?UTF-8?q?=E8=A1=A8=E6=A0=BC=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Widget/InsertTableDialog.h | 3 +- .../model/Widget/SelectTemplateDialog.ui | 8 +- ofdEditor/model/cn_model.ts | 14 +- .../start/ActionConnector/ActionConnector.cpp | 8 +- ofdEditor/start/cn_start.ts | 150 +++++++++--------- 5 files changed, 93 insertions(+), 90 deletions(-) diff --git a/ofdEditor/model/Widget/InsertTableDialog.h b/ofdEditor/model/Widget/InsertTableDialog.h index 722c5a7..c92a639 100644 --- a/ofdEditor/model/Widget/InsertTableDialog.h +++ b/ofdEditor/model/Widget/InsertTableDialog.h @@ -1,5 +1,6 @@ #ifndef INSERTTABLEDIALOG_H #define INSERTTABLEDIALOG_H +#include "model_global.h" #include @@ -7,7 +8,7 @@ namespace Ui { class InsertTableDialog; } -class InsertTableDialog : public QDialog +class MODELSHARED_EXPORT InsertTableDialog : public QDialog { Q_OBJECT diff --git a/ofdEditor/model/Widget/SelectTemplateDialog.ui b/ofdEditor/model/Widget/SelectTemplateDialog.ui index 82a0f0c..ce61baf 100644 --- a/ofdEditor/model/Widget/SelectTemplateDialog.ui +++ b/ofdEditor/model/Widget/SelectTemplateDialog.ui @@ -11,7 +11,7 @@ - Dialog + 选择模版 @@ -42,7 +42,7 @@ - :/template_icons/source/templates/template_1.png + :/template_icons/source/templates/template_1.png @@ -127,9 +127,7 @@ - - - + buttonBox diff --git a/ofdEditor/model/cn_model.ts b/ofdEditor/model/cn_model.ts index 8b048ed..cf06f91 100644 --- a/ofdEditor/model/cn_model.ts +++ b/ofdEditor/model/cn_model.ts @@ -16,7 +16,7 @@ Remove Image. - + 移除图片。 @@ -995,25 +995,25 @@ p, li { white-space: pre-wrap; } SelectTemplateDialog - + - Dialog - + 选择模版 + 选择页面模板 - + 上一个 - + 下一个 - + diff --git a/ofdEditor/start/ActionConnector/ActionConnector.cpp b/ofdEditor/start/ActionConnector/ActionConnector.cpp index 8aa7427..d45808c 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.cpp +++ b/ofdEditor/start/ActionConnector/ActionConnector.cpp @@ -3,6 +3,7 @@ #include "ui/PassageMainWindow.h" #include "Doc/DocPage.h" #include "DataTypes/document/ct_docinfo.h" +#include "Widget/InsertTableDialog.h" #include "Widget/DocInfoDialog.h" #include #include @@ -127,8 +128,11 @@ void ActionConnector::addTableBlock() { if(this->passage == NULL) return; - InsertBlockInfo blockInfo(this->defaultLayer,DocPage::table); // 设置插入文本框信息 - this->addNewBlock(blockInfo); + +// InsertBlockInfo blockInfo(this->defaultLayer,DocPage::table); // 设置插入文本框信息 +// this->addNewBlock(blockInfo); + InsertTableDialog * tableDialog = new InsertTableDialog(0); + tableDialog->exec(); } void ActionConnector::undo() diff --git a/ofdEditor/start/cn_start.ts b/ofdEditor/start/cn_start.ts index ab83462..9f12fb4 100644 --- a/ofdEditor/start/cn_start.ts +++ b/ofdEditor/start/cn_start.ts @@ -292,19 +292,19 @@ - + Edit 编辑 - + Format 格式 - + Insert 插入 @@ -314,222 +314,222 @@ 关于 - + 72 - + 48 - + 36 - + 28 - + 26 - + 24 - + 22 - + 20 - + 18 - + 16 - + 14 - + 12 - + 11 - + 10.5 - + 10 - + 9 - + 8 - + 7.5 - + 6.5 - + 5.5 - + 5 - + Size 8 八号 - + Size 7 七号 - + Size 6 Minor 小六 - + Size 6 六号 - + Size 5 Minor 小五 - + Size 5 五号 - + Size 4 Minor 小四 - + Size 4 四号 - + Size 3 Minor 小三 - + Size 3 三号 - + Size 2 Minor 小二 - + Size 2 二号 - + Size 1 Minor 小一 - + Size 1 一号 - + Prime Minor 小初 - + Prime 初号 - + JiMi 1Nian 机密★1年 - + Te Ji 特急 - + XXXXXWenJian ×××××文件 - + XXX[2012]10Hao ×××﹝2012﹞10号 - + XXXXXGuanYuXXXXXXDeTongZhi ×××关于××××的通知 - + XXXXXXXX: ×××××: - + OOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. OOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. OOOOXXXXXXXXXXXXXXXXXXXXXX. @@ -540,38 +540,38 @@ OOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ××××××××××××。×××××××××××××××××××××××××××××××××××××××××× - + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. OOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ××××××××××××××××××××××××××××。 ×××××××××××××××××××××××××××××××××××××××××××。 - + XXXXXXXXXXXX ×××××××××××× - + 2012Nian7Yue1Ri 2012年7月1日 - + (XXXXXX) (××××××) - + ChaoSong:XXXXXXX,XXXXX,XXXXXX - 抄送:×××××,××××××,××××××× + 抄送:×××××,××××××,××××××× - + XXXXXXXX ×××××××××× - + 2012Nian7Yue1RiYinFa 2012年7月1日印发 @@ -584,102 +584,102 @@ OOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. 七号 - + Bold 加粗 - + Set selected text Bold or not bold 将选择的文本加粗 - + Italic 斜体 - + Set the selected text Italic 设置选择的文本斜体 - + Underline 下划线 - + Set the selected text underline 设置选择的文本下划线 - + middle 居中 - + Set the selected paragraph align middle 设置选择的段落格式为居中 - + Left 左对齐 - + Set the selected paragraph align by left 设置选择的段落对齐样式为左对齐 - + Right 右对齐 - + Set the selected paragraph align by right 设置选中的段落的对齐样式为右对齐 - + jutify 两端对齐 - + Set the selected paragraph align by left and right 设置选择的文本的对齐样式为两端对齐 - + File 文件 - + TextBlock 文本框 - + JSON files(*.ofd) OFD文件(*ofd) - + Choose an ofd document file! 选择一个OFD文件! - + Save the passage content as a ofd file 保存文件为一个ofd文件 - + OFD files(*.ofd) -- Gitee From 5925735ef41b9119d9a4f355bf0d477143a43af2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Fri, 30 Jun 2017 09:42:30 +0800 Subject: [PATCH 23/83] =?UTF-8?q?=E4=BF=AE=E6=94=B9readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 73 +++++++++++++++++++++++-------------------- doc/imgs/image1.png | Bin 0 -> 97855 bytes doc/imgs/image33.png | Bin 0 -> 11085 bytes doc/imgs/image34.png | Bin 0 -> 17099 bytes doc/imgs/image35.png | Bin 0 -> 10853 bytes doc/imgs/image36.png | Bin 0 -> 10820 bytes doc/imgs/image37.png | Bin 0 -> 9323 bytes doc/imgs/image38.png | Bin 0 -> 29762 bytes doc/imgs/image39.png | Bin 0 -> 49542 bytes doc/imgs/image40.png | Bin 0 -> 43241 bytes doc/imgs/image41.png | Bin 0 -> 13899 bytes doc/imgs/image42.png | Bin 0 -> 12156 bytes doc/imgs/image43.png | Bin 0 -> 34573 bytes doc/imgs/image44.png | Bin 0 -> 1881 bytes doc/imgs/image45.png | Bin 0 -> 43176 bytes doc/imgs/image46.png | Bin 0 -> 16055 bytes doc/imgs/image47.png | Bin 0 -> 12526 bytes doc/imgs/image48.png | Bin 0 -> 63925 bytes doc/imgs/image50.png | Bin 0 -> 99295 bytes doc/imgs/image51.png | Bin 0 -> 411300 bytes doc/imgs/image52.png | Bin 0 -> 139266 bytes doc/imgs/image53.png | Bin 0 -> 90254 bytes doc/imgs/image54.png | Bin 0 -> 12215 bytes doc/imgs/image55.png | Bin 0 -> 10131 bytes 24 files changed, 39 insertions(+), 34 deletions(-) create mode 100644 doc/imgs/image1.png create mode 100644 doc/imgs/image33.png create mode 100644 doc/imgs/image34.png create mode 100644 doc/imgs/image35.png create mode 100644 doc/imgs/image36.png create mode 100644 doc/imgs/image37.png create mode 100644 doc/imgs/image38.png create mode 100644 doc/imgs/image39.png create mode 100644 doc/imgs/image40.png create mode 100644 doc/imgs/image41.png create mode 100644 doc/imgs/image42.png create mode 100644 doc/imgs/image43.png create mode 100644 doc/imgs/image44.png create mode 100644 doc/imgs/image45.png create mode 100644 doc/imgs/image46.png create mode 100644 doc/imgs/image47.png create mode 100644 doc/imgs/image48.png create mode 100644 doc/imgs/image50.png create mode 100644 doc/imgs/image51.png create mode 100644 doc/imgs/image52.png create mode 100644 doc/imgs/image53.png create mode 100644 doc/imgs/image54.png create mode 100644 doc/imgs/image55.png diff --git a/README.md b/README.md index 113e6fd..a76ddde 100644 --- a/README.md +++ b/README.md @@ -11,16 +11,35 @@ win32 : Qt 4.8.6 + MinGW 4.8.2 `windows 10 ` `ubuntu 16.04` `中标麒麟6.0` ## 功能需求 -1. 创建文档:生成基本OFD框架; -2. 页面设置与分页:设置纸张形式和分页机制; -3. 文字录入:在控制区域内实现文字的增、改、删; -4. 版面控制:设置版心、字体、颜色、字号、行距、字距等; -5. 段落控制:实现段落缩进、居左、居中、居右、撑满等。 -6. 图像控制:实现图像的插入和文字环绕; -7. 表格编辑:实现表格插入、绘制和文字表格内排版。 -8. 账号管理:能够注册、登录、注销用户账号; -9. 文件云端备份功能:能够将文件备份在云端、实现多版本保存; -10. ~~协同编辑:两个或多个用户能够同时编辑同一份文档。~~ + +1. 创建文档 +>创建文当是本系统的最基本的功能,即新建一个OFD类型的文档。新建的文档应该是一个只有页空白页的,默认纸张大小、默认页边距的文档。 +为了方便用户使用,在创建OFD文档时,应考虑增加几个常用板式模板。这样比如用户,创建完成后,只需要简单的改改自己需要的部分即可。 + +2. 页面设置与分页 +>页面设置与分页也是比较常用的功能,它要做的是设置纸张的大小与形式,之后再设置纸张的分页机制。本系统在实现时,应该设置到能够快速切换到常用纸张大小,比如:A3、A4、A5等纸张大小。 + +3. 文字录入 +>文字录入功能可以说是OFD文档原型系统必须实现的功能。本系统需要实现的是如同记事本一样非常自然的输入方式,让用户能够录入文字后立马看到效果,并且要能够做到在通用的OFD阅读器上打开也具有同样的效果。 + +4. 版面控制 +>版面控制需要实现设置版心、字体、颜色、字号、行距、字距等功能,这些功能都是版面布局时所需要的。同样,版面控制的效果需要在所有的OFD阅读器上都能够看到。 + +5. 图像控制 +>图像控制功能,即实现插入图片,设置常用的文字环绕方式。这里我们需要能够设置图片的尺寸,长宽比;需要设置文字环绕方式为包围式、嵌入文本行中等。 + +6. 表格编辑 +>表格编辑功能,需要能够插入表格,在表格中调节文字排版。并且,插入表格时要能够设置表格的行列数量,在后面也要能够对表格的单元格进行大小调整,分离或合并不同单元格。 + +7. 撤销恢复功能 +>用户在操作中常常遇到需要撤销恢复的情况,为此需要设置撤销恢复功能,最好撤销恢复次数需要大于10次。撤销恢复的功能目前可以说是商用编辑软件的必备功能了。 + +8. 查找替换功能 +>用户在编辑文档时,当文档过于长时,需要用查找功能查询到某处关键字,或者是需要进行关键词的批量替换。 + +9. 视图缩放功能 +>有的用户可能会嫌弃页面显示的内容太小;有的用户会觉得应用内容文字过大;而有的用户需要快速的浏览文档的内容。为此,系统需要包含浏览视图的放大缩小功能。此功能能够方便用户浏览,为用户的使用提供很大的便利性。 + ## 工程布局(实时更新) 本工程将采用Qt 多工程组织的形式,将按文件功能将代码文件分为若干个不同的子工程。
@@ -29,30 +48,16 @@ win32 : Qt 4.8.6 + MinGW 4.8.2 ``` |-model -> 系统工作时的数据模型及显示渲染 |-ofd -> ofd,主要用与ofd文件读取导出,以及ofd读取初期所使用的数据结构 -|-start -> start,主要存放启动程序已经程序的一些基本的界面文件。 +|-start -> start,程序的启动工程,存放关于主界面相关的 -|-test_chaoqun -> 江超群的测试工程 -|-test_pan -> 潘言星的测试工程 -|-test_yang -> 杨语晨的测试工程 ``` -## Qt 帮助文档 -Qt的帮助文档极为丰富,看完之后能够对Qt的功能产生系统性的了解,这样设计软件时,思路就会更加的清晰。 - -| 文件名 | 作用 | -| --- | --- | -| Qt Data Types.pdf | Qt的一些基础数据类型 | -| Creating Custom Qt Types.pdf | 创建自定义的Qt 类 | -| MainWindow.pdf | 主窗口相关的 | -| Widget Tutorial.pdf | Widget 的简要教程 | -| Layout.pdf | 布局 | -| State Machine.pdf | 状态机 | -| Sighals and Slots.pdf | 信号槽 | -| Event System.pdf | 事件系统 | -| Drag and Drop.pdf | 拖拽操作处理 | -| Painting System.pdf | 绘画系统 | -| Qgraphics view framework.pdf | Qt的快速响应的图形渲染方式 | -| Qt 富文本框架.pdf | Qt富文本系统 | -| Creating Qt Plugins.pdf | 制作Qt插件 | -| Model View Programming.pdf | 模型视图结构编程 | -| Model View Tutorial.pdf | 模型视图结构教学 | +## 软件效果图 +![浏览样例](doc\imgs\image40.png) +![页面设置](doc\imgs\image41.png) +![查找替换](doc\imgs\image51.png) + +## 工程引用外部库 +工程引用了 `quazip 0.73`作为本工程的zip压缩工具,他人在编译本工程时,请预先配置好`quazip 0.73` 的环境,之后才可以正常编译本工程。 + +[QuaZip官网](http://quazip.sourceforge.net/) diff --git a/doc/imgs/image1.png b/doc/imgs/image1.png new file mode 100644 index 0000000000000000000000000000000000000000..1ae63bdb683779dde2480cf2cb4f3c9adc50e487 GIT binary patch literal 97855 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ℑWX{G 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 Ib37!NH~o92_l{uWP$VCW^yG9Aj)OD}9ej5iHcX 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 G!~O#v_^+)1 literal 0 HcmV?d00001 diff --git a/doc/imgs/image33.png b/doc/imgs/image33.png new file mode 100644 index 0000000000000000000000000000000000000000..b7399de910e22ad535602d8616230a776bd6c4cc GIT binary patch literal 11085 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 D$?hM- literal 0 HcmV?d00001 diff --git a/doc/imgs/image37.png b/doc/imgs/image37.png new file mode 100644 index 0000000000000000000000000000000000000000..32827ecc644c24a85ec16c6fb8ab40b3cd24f256 GIT binary patch literal 9323 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

6IDOW%Cx$*Zd(4vMYf9B1hkjKB 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

  • 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 z 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

    a6r?4kxJ!WZtM|{Tpq$$D@K5lPSNg%I!@+r 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� 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 T6ER@(J%+Np`pYU=v(Wzo=N@IP literal 0 HcmV?d00001 diff --git a/doc/imgs/image55.png b/doc/imgs/image55.png new file mode 100644 index 0000000000000000000000000000000000000000..eb50f782a5d36839f27bcdce39d4ddf19d9006dd GIT binary patch literal 10131 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 Date: Fri, 30 Jun 2017 09:52:07 +0800 Subject: [PATCH 24/83] =?UTF-8?q?=E4=BF=AE=E6=94=B9readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a76ddde..2c56ca5 100644 --- a/README.md +++ b/README.md @@ -53,11 +53,22 @@ win32 : Qt 4.8.6 + MinGW 4.8.2 ``` ## 软件效果图 -![浏览样例](doc\imgs\image40.png) -![页面设置](doc\imgs\image41.png) -![查找替换](doc\imgs\image51.png) +![浏览样例](doc/imgs/image40.png) +![页面设置](doc/imgs/image41.png) +![查找替换](doc/imgs/image51.png) ## 工程引用外部库 工程引用了 `quazip 0.73`作为本工程的zip压缩工具,他人在编译本工程时,请预先配置好`quazip 0.73` 的环境,之后才可以正常编译本工程。 +## 翻译文件 +本系统编写时设置语言为英文。在`model`和`start`工程下设置了翻译文件。 +``` +\ofdEditor + \-model + \-cn_model.ts + \-start + \-cn_start.ts +``` +编译时,使用Qt自带的Linguist程序生成relesae的翻译文件,放在编译完成的bin目录下。 + [QuaZip官网](http://quazip.sourceforge.net/) -- Gitee From dce6ff836b68204a498636d619401b626df4080d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 5 Aug 2017 10:44:16 +0800 Subject: [PATCH 25/83] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E5=8D=95=E4=BE=8B=E6=A8=A1=E5=BC=8F=E8=AE=BE=E8=AE=A1=E7=9A=84?= =?UTF-8?q?=E5=85=A8=E5=B1=80=E5=8F=98=E9=87=8F=20GlobalSetting=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/AppSetting.json | 31 + ofdEditor/libs/jsoncpp/json/json-forwards.h | 255 + ofdEditor/libs/jsoncpp/json/json.h | 1981 ++++++++ ofdEditor/libs/jsoncpp/jsoncpp.cpp | 4945 +++++++++++++++++++ ofdEditor/model/Command/SetTextBlodCmd.h | 3 +- ofdEditor/model/Core/GlobalSetting.cpp | 504 ++ ofdEditor/model/Core/GlobalSetting.h | 143 + ofdEditor/model/Widget/PageDialog.ui | 2 +- ofdEditor/model/model.pro | 9 +- ofdEditor/ofd/ofd.pro | 8 +- ofdEditor/start/ui/PassageMainWindow.cpp | 7 +- 11 files changed, 7877 insertions(+), 11 deletions(-) create mode 100644 ofdEditor/AppSetting.json create mode 100644 ofdEditor/libs/jsoncpp/json/json-forwards.h create mode 100644 ofdEditor/libs/jsoncpp/json/json.h create mode 100644 ofdEditor/libs/jsoncpp/jsoncpp.cpp create mode 100644 ofdEditor/model/Core/GlobalSetting.cpp create mode 100644 ofdEditor/model/Core/GlobalSetting.h diff --git a/ofdEditor/AppSetting.json b/ofdEditor/AppSetting.json new file mode 100644 index 0000000..2cd00f0 --- /dev/null +++ b/ofdEditor/AppSetting.json @@ -0,0 +1,31 @@ +{ + "App": { + "Creator": "OFDEditor", + "CreatorVersion": "1.0", + "DocType": "OFD", + "DocVersion": "1.0", + "ViewMode": "Edit" + }, + "Font": { + "FontFamily": "黑体", + "FontSize": 12 + }, + "Page": { + "Width": 230, + "Height": 330, + "WorkWidth": 230, + "WorkHeight": 330, + "WorkX": 0, + "WoekY": 0, + "PageType": "A4" + }, + "Paragraph": { + "Horizontal": "AlignLeft", + "ParaIndent": 0, + "FirstIndent": 0, + "SpaceBefore": 0, + "SpaceAfter": 0, + "LineHeight": "SingleHeight", + "LineHeightValue": 0 + } +} \ No newline at end of file diff --git a/ofdEditor/libs/jsoncpp/json/json-forwards.h b/ofdEditor/libs/jsoncpp/json/json-forwards.h new file mode 100644 index 0000000..ccbdb2b --- /dev/null +++ b/ofdEditor/libs/jsoncpp/json/json-forwards.h @@ -0,0 +1,255 @@ +/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/). +/// It is intended to be used with #include "json/json-forwards.h" +/// This header provides forward declaration for all JsonCpp types. + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is +released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur + +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. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + +#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED +# define JSON_FORWARD_AMALGATED_H_INCLUDED +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +#define JSON_IS_AMALGAMATION + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +#define JSON_CONFIG_H_INCLUDED + +/// If defined, indicates that json library is embedded in CppTL library. +//# define JSON_IN_CPPTL 1 + +/// If defined, indicates that json may leverage CppTL library +//# define JSON_USE_CPPTL 1 +/// If defined, indicates that cpptl vector based map should be used instead of +/// std::map +/// as Value container. +//# define JSON_USE_CPPTL_SMALLMAP 1 + +// If non-zero, the library uses exceptions to report bad input instead of C +// assertion macros. The default is to use exceptions. +#ifndef JSON_USE_EXCEPTION +#define JSON_USE_EXCEPTION 1 +#endif + +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgated header. +// #define JSON_IS_AMALGAMATION + +#ifdef JSON_IN_CPPTL +#include +#ifndef JSON_USE_CPPTL +#define JSON_USE_CPPTL 1 +#endif +#endif + +#ifdef JSON_IN_CPPTL +#define JSON_API CPPTL_API +#elif defined(JSON_DLL_BUILD) +#if defined(_MSC_VER) +#define JSON_API __declspec(dllexport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#elif defined(JSON_DLL) +#if defined(_MSC_VER) +#define JSON_API __declspec(dllimport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#endif // ifdef JSON_IN_CPPTL +#if !defined(JSON_API) +#define JSON_API +#endif + +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for +// integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 + +#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 +// Microsoft Visual Studio 6 only support conversion from __int64 to double +// (no conversion from unsigned __int64). +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' +// characters in the debug information) +// All projects I've ever seen with VS6 were using this globally (not bothering +// with pragma push/pop). +#pragma warning(disable : 4786) +#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 + +#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 +/// Indicates that the following function is deprecated. +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#elif defined(__clang__) && defined(__has_feature) +#if __has_feature(attribute_deprecated_with_message) +#define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) +#endif +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +#define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) +#elif defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) +#endif + +#if !defined(JSONCPP_DEPRECATED) +#define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +namespace Json { +typedef int Int; +typedef unsigned int UInt; +#if defined(JSON_NO_INT64) +typedef int LargestInt; +typedef unsigned int LargestUInt; +#undef JSON_HAS_INT64 +#else // if defined(JSON_NO_INT64) +// For Microsoft Visual use specific types as long long is not supported +#if defined(_MSC_VER) // Microsoft Visual Studio +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else // if defined(_MSC_VER) // Other platforms, use long long +typedef long long int Int64; +typedef unsigned long long int UInt64; +#endif // if defined(_MSC_VER) +typedef Int64 LargestInt; +typedef UInt64 LargestUInt; +#define JSON_HAS_INT64 +#endif // if defined(JSON_NO_INT64) +} // end namespace Json + +#endif // JSON_CONFIG_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +#define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// writer.h +class FastWriter; +class StyledWriter; + +// reader.h +class Reader; + +// features.h +class Features; + +// value.h +typedef unsigned int ArrayIndex; +class StaticString; +class Path; +class PathArgument; +class Value; +class ValueIteratorBase; +class ValueIterator; +class ValueConstIterator; + +} // namespace Json + +#endif // JSON_FORWARDS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + + + + + +#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED diff --git a/ofdEditor/libs/jsoncpp/json/json.h b/ofdEditor/libs/jsoncpp/json/json.h new file mode 100644 index 0000000..6859137 --- /dev/null +++ b/ofdEditor/libs/jsoncpp/json/json.h @@ -0,0 +1,1981 @@ +/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/). +/// It is intended to be used with #include "json/json.h" + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is +released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur + +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. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + +#ifndef JSON_AMALGATED_H_INCLUDED +# define JSON_AMALGATED_H_INCLUDED +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +#define JSON_IS_AMALGAMATION + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/version.h +// ////////////////////////////////////////////////////////////////////// + +// DO NOT EDIT. This file (and "version") is generated by CMake. +// Run CMake configure step to update it. +#ifndef JSON_VERSION_H_INCLUDED +# define JSON_VERSION_H_INCLUDED + +# define JSONCPP_VERSION_STRING "0.10.6" +# define JSONCPP_VERSION_MAJOR 0 +# define JSONCPP_VERSION_MINOR 10 +# define JSONCPP_VERSION_PATCH 6 +# define JSONCPP_VERSION_QUALIFIER +# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) + +#endif // JSON_VERSION_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/version.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +#define JSON_CONFIG_H_INCLUDED + +/// If defined, indicates that json library is embedded in CppTL library. +//# define JSON_IN_CPPTL 1 + +/// If defined, indicates that json may leverage CppTL library +//# define JSON_USE_CPPTL 1 +/// If defined, indicates that cpptl vector based map should be used instead of +/// std::map +/// as Value container. +//# define JSON_USE_CPPTL_SMALLMAP 1 + +// If non-zero, the library uses exceptions to report bad input instead of C +// assertion macros. The default is to use exceptions. +#ifndef JSON_USE_EXCEPTION +#define JSON_USE_EXCEPTION 1 +#endif + +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgated header. +// #define JSON_IS_AMALGAMATION + +#ifdef JSON_IN_CPPTL +#include +#ifndef JSON_USE_CPPTL +#define JSON_USE_CPPTL 1 +#endif +#endif + +#ifdef JSON_IN_CPPTL +#define JSON_API CPPTL_API +#elif defined(JSON_DLL_BUILD) +#if defined(_MSC_VER) +#define JSON_API __declspec(dllexport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#elif defined(JSON_DLL) +#if defined(_MSC_VER) +#define JSON_API __declspec(dllimport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#endif // ifdef JSON_IN_CPPTL +#if !defined(JSON_API) +#define JSON_API +#endif + +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for +// integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 + +#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 +// Microsoft Visual Studio 6 only support conversion from __int64 to double +// (no conversion from unsigned __int64). +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' +// characters in the debug information) +// All projects I've ever seen with VS6 were using this globally (not bothering +// with pragma push/pop). +#pragma warning(disable : 4786) +#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 + +#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 +/// Indicates that the following function is deprecated. +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#elif defined(__clang__) && defined(__has_feature) +#if __has_feature(attribute_deprecated_with_message) +#define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) +#endif +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +#define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) +#elif defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) +#endif + +#if !defined(JSONCPP_DEPRECATED) +#define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +namespace Json { +typedef int Int; +typedef unsigned int UInt; +#if defined(JSON_NO_INT64) +typedef int LargestInt; +typedef unsigned int LargestUInt; +#undef JSON_HAS_INT64 +#else // if defined(JSON_NO_INT64) +// For Microsoft Visual use specific types as long long is not supported +#if defined(_MSC_VER) // Microsoft Visual Studio +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else // if defined(_MSC_VER) // Other platforms, use long long +typedef long long int Int64; +typedef unsigned long long int UInt64; +#endif // if defined(_MSC_VER) +typedef Int64 LargestInt; +typedef UInt64 LargestUInt; +#define JSON_HAS_INT64 +#endif // if defined(JSON_NO_INT64) +} // end namespace Json + +#endif // JSON_CONFIG_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +#define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// writer.h +class FastWriter; +class StyledWriter; + +// reader.h +class Reader; + +// features.h +class Features; + +// value.h +typedef unsigned int ArrayIndex; +class StaticString; +class Path; +class PathArgument; +class Value; +class ValueIteratorBase; +class ValueIterator; +class ValueConstIterator; + +} // namespace Json + +#endif // JSON_FORWARDS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/features.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_FEATURES_H_INCLUDED +#define CPPTL_JSON_FEATURES_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +/** \brief Configuration passed to reader and writer. + * This configuration object can be used to force the Reader or Writer + * to behave in a standard conforming way. + */ +class JSON_API Features { +public: + /** \brief A configuration that allows all features and assumes all strings + * are UTF-8. + * - C & C++ comments are allowed + * - Root object can be any JSON value + * - Assumes Value strings are encoded in UTF-8 + */ + static Features all(); + + /** \brief A configuration that is strictly compatible with the JSON + * specification. + * - Comments are forbidden. + * - Root object must be either an array or an object value. + * - Assumes Value strings are encoded in UTF-8 + */ + static Features strictMode(); + + /** \brief Initialize the configuration like JsonConfig::allFeatures; + */ + Features(); + + /// \c true if comments are allowed. Default: \c true. + bool allowComments_; + + /// \c true if root must be either an array or an object value. Default: \c + /// false. + bool strictRoot_; +}; + +} // namespace Json + +#endif // CPPTL_JSON_FEATURES_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/features.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/value.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_H_INCLUDED +#define CPPTL_JSON_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include + +#ifndef JSON_USE_CPPTL_SMALLMAP +#include +#else +#include +#endif +#ifdef JSON_USE_CPPTL +#include +#endif + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +//Conditional NORETURN attribute on the throw functions would: +// a) suppress false positives from static code analysis +// b) possibly improve optimization opportunities. +#if !defined(JSONCPP_NORETURN) +# if defined(_MSC_VER) +# define JSONCPP_NORETURN __declspec(noreturn) +# elif defined(__GNUC__) +# define JSONCPP_NORETURN __attribute__ ((__noreturn__)) +# else +# define JSONCPP_NORETURN +# endif +#endif + +/** \brief JSON (JavaScript Object Notation). + */ +namespace Json { + +/** Base class for all exceptions we throw. + * + * We use nothing but these internally. Of course, STL can throw others. + */ +class JSON_API Exception : public std::exception { +public: + Exception(std::string const& msg); + virtual ~Exception() throw(); + virtual char const* what() const throw(); +protected: + std::string const msg_; +}; + +/** Exceptions which the user cannot easily avoid. + * + * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input + * + * \remark derived from Json::Exception + */ +class JSON_API RuntimeError : public Exception { +public: + RuntimeError(std::string const& msg); +}; + +/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. + * + * These are precondition-violations (user bugs) and internal errors (our bugs). + * + * \remark derived from Json::Exception + */ +class JSON_API LogicError : public Exception { +public: + LogicError(std::string const& msg); +}; + +/// used internally +JSONCPP_NORETURN void throwRuntimeError(std::string const& msg); +/// used internally +JSONCPP_NORETURN void throwLogicError(std::string const& msg); + +/** \brief Type of the value held by a Value object. + */ +enum ValueType { + nullValue = 0, ///< 'null' value + intValue, ///< signed integer value + uintValue, ///< unsigned integer value + realValue, ///< double value + stringValue, ///< UTF-8 string value + booleanValue, ///< bool value + arrayValue, ///< array value (ordered list) + objectValue ///< object value (collection of name/value pairs). +}; + +enum CommentPlacement { + commentBefore = 0, ///< a comment placed on the line before a value + commentAfterOnSameLine, ///< a comment just after a value on the same line + commentAfter, ///< a comment on the line after a value (only make sense for + /// root value) + numberOfCommentPlacement +}; + +//# ifdef JSON_USE_CPPTL +// typedef CppTL::AnyEnumerator EnumMemberNames; +// typedef CppTL::AnyEnumerator EnumValues; +//# endif + +/** \brief Lightweight wrapper to tag static string. + * + * Value constructor and objectValue member assignement takes advantage of the + * StaticString and avoid the cost of string duplication when storing the + * string or the member name. + * + * Example of usage: + * \code + * Json::Value aValue( StaticString("some text") ); + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ +class JSON_API StaticString { +public: + explicit StaticString(const char* czstring) : c_str_(czstring) {} + + operator const char*() const { return c_str_; } + + const char* c_str() const { return c_str_; } + +private: + const char* c_str_; +}; + +/** \brief Represents a JSON value. + * + * This class is a discriminated union wrapper that can represents a: + * - signed integer [range: Value::minInt - Value::maxInt] + * - unsigned integer (range: 0 - Value::maxUInt) + * - double + * - UTF-8 string + * - boolean + * - 'null' + * - an ordered list of Value + * - collection of name/value pairs (javascript object) + * + * The type of the held value is represented by a #ValueType and + * can be obtained using type(). + * + * Values of an #objectValue or #arrayValue can be accessed using operator[]() + * methods. + * Non-const methods will automatically create the a #nullValue element + * if it does not exist. + * The sequence of an #arrayValue will be automatically resized and initialized + * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. + * + * The get() methods can be used to obtain default value in the case the + * required element does not exist. + * + * It is possible to iterate over the list of a #objectValue values using + * the getMemberNames() method. + * + * \note #Value string-length fit in size_t, but keys must be < 2^30. + * (The reason is an implementation detail.) A #CharReader will raise an + * exception if a bound is exceeded to avoid security holes in your app, + * but the Value API does *not* check bounds. That is the responsibility + * of the caller. + */ +class JSON_API Value { + friend class ValueIteratorBase; +public: + typedef std::vector Members; + typedef ValueIterator iterator; + typedef ValueConstIterator const_iterator; + typedef Json::UInt UInt; + typedef Json::Int Int; +#if defined(JSON_HAS_INT64) + typedef Json::UInt64 UInt64; + typedef Json::Int64 Int64; +#endif // defined(JSON_HAS_INT64) + typedef Json::LargestInt LargestInt; + typedef Json::LargestUInt LargestUInt; + typedef Json::ArrayIndex ArrayIndex; + + static const Value& nullRef; +#if !defined(__ARMEL__) + /// \deprecated This exists for binary compatibility only. Use nullRef. + static const Value null; +#endif + /// Minimum signed integer value that can be stored in a Json::Value. + static const LargestInt minLargestInt; + /// Maximum signed integer value that can be stored in a Json::Value. + static const LargestInt maxLargestInt; + /// Maximum unsigned integer value that can be stored in a Json::Value. + static const LargestUInt maxLargestUInt; + + /// Minimum signed int value that can be stored in a Json::Value. + static const Int minInt; + /// Maximum signed int value that can be stored in a Json::Value. + static const Int maxInt; + /// Maximum unsigned int value that can be stored in a Json::Value. + static const UInt maxUInt; + +#if defined(JSON_HAS_INT64) + /// Minimum signed 64 bits int value that can be stored in a Json::Value. + static const Int64 minInt64; + /// Maximum signed 64 bits int value that can be stored in a Json::Value. + static const Int64 maxInt64; + /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. + static const UInt64 maxUInt64; +#endif // defined(JSON_HAS_INT64) + +private: +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + class CZString { + public: + enum DuplicationPolicy { + noDuplication = 0, + duplicate, + duplicateOnCopy + }; + CZString(ArrayIndex index); + CZString(char const* str, unsigned length, DuplicationPolicy allocate); + CZString(CZString const& other); + ~CZString(); + CZString& operator=(CZString other); + bool operator<(CZString const& other) const; + bool operator==(CZString const& other) const; + ArrayIndex index() const; + //const char* c_str() const; ///< \deprecated + char const* data() const; + unsigned length() const; + bool isStaticString() const; + + private: + void swap(CZString& other); + + struct StringStorage { + unsigned policy_: 2; + unsigned length_: 30; // 1GB max + }; + + char const* cstr_; // actually, a prefixed string, unless policy is noDup + union { + ArrayIndex index_; + StringStorage storage_; + }; + }; + +public: +#ifndef JSON_USE_CPPTL_SMALLMAP + typedef std::map ObjectValues; +#else + typedef CppTL::SmallMap ObjectValues; +#endif // ifndef JSON_USE_CPPTL_SMALLMAP +#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + +public: + /** \brief Create a default Value of the given type. + + This is a very useful constructor. + To create an empty array, pass arrayValue. + To create an empty object, pass objectValue. + Another Value can then be set to this one by assignment. +This is useful since clear() and resize() will not alter types. + + Examples: +\code +Json::Value null_value; // null +Json::Value arr_value(Json::arrayValue); // [] +Json::Value obj_value(Json::objectValue); // {} +\endcode + */ + Value(ValueType type = nullValue); + Value(Int value); + Value(UInt value); +#if defined(JSON_HAS_INT64) + Value(Int64 value); + Value(UInt64 value); +#endif // if defined(JSON_HAS_INT64) + Value(double value); + Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.) + Value(const char* begin, const char* end); ///< Copy all, incl zeroes. + /** \brief Constructs a value from a static string. + + * Like other value string constructor but do not duplicate the string for + * internal storage. The given string must remain alive after the call to this + * constructor. + * \note This works only for null-terminated strings. (We cannot change the + * size of this class, so we have nowhere to store the length, + * which might be computed later for various operations.) + * + * Example of usage: + * \code + * static StaticString foo("some text"); + * Json::Value aValue(foo); + * \endcode + */ + Value(const StaticString& value); + Value(const std::string& value); ///< Copy data() til size(). Embedded zeroes too. +#ifdef JSON_USE_CPPTL + Value(const CppTL::ConstString& value); +#endif + Value(bool value); + /// Deep copy. + Value(const Value& other); + ~Value(); + + /// Deep copy, then swap(other). + /// \note Over-write existing comments. To preserve comments, use #swapPayload(). + Value &operator=(const Value &other); + /// Swap everything. + void swap(Value& other); + /// Swap values but leave comments and source offsets in place. + void swapPayload(Value& other); + + ValueType type() const; + + /// Compare payload only, not comments etc. + bool operator<(const Value& other) const; + bool operator<=(const Value& other) const; + bool operator>=(const Value& other) const; + bool operator>(const Value& other) const; + bool operator==(const Value& other) const; + bool operator!=(const Value& other) const; + int compare(const Value& other) const; + + const char* asCString() const; ///< Embedded zeroes could cause you trouble! + std::string asString() const; ///< Embedded zeroes are possible. + /** Get raw char* of string-value. + * \return false if !string. (Seg-fault if str or end are NULL.) + */ + bool getString( + char const** begin, char const** end) const; +#ifdef JSON_USE_CPPTL + CppTL::ConstString asConstString() const; +#endif + Int asInt() const; + UInt asUInt() const; +#if defined(JSON_HAS_INT64) + Int64 asInt64() const; + UInt64 asUInt64() const; +#endif // if defined(JSON_HAS_INT64) + LargestInt asLargestInt() const; + LargestUInt asLargestUInt() const; + float asFloat() const; + double asDouble() const; + bool asBool() const; + + bool isNull() const; + bool isBool() const; + bool isInt() const; + bool isInt64() const; + bool isUInt() const; + bool isUInt64() const; + bool isIntegral() const; + bool isDouble() const; + bool isNumeric() const; + bool isString() const; + bool isArray() const; + bool isObject() const; + + bool isConvertibleTo(ValueType other) const; + + /// Number of values in array or object + ArrayIndex size() const; + + /// \brief Return true if empty array, empty object, or null; + /// otherwise, false. + bool empty() const; + + /// Return isNull() + bool operator!() const; + + /// Remove all object members and array elements. + /// \pre type() is arrayValue, objectValue, or nullValue + /// \post type() is unchanged + void clear(); + + /// Resize the array to size elements. + /// New elements are initialized to null. + /// May only be called on nullValue or arrayValue. + /// \pre type() is arrayValue or nullValue + /// \post type() is arrayValue + void resize(ArrayIndex size); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are + /// inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value& operator[](ArrayIndex index); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are + /// inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value& operator[](int index); + + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value& operator[](ArrayIndex index) const; + + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value& operator[](int index) const; + + /// If the array contains at least index+1 elements, returns the element + /// value, + /// otherwise returns defaultValue. + Value get(ArrayIndex index, const Value& defaultValue) const; + /// Return true if index < size(). + bool isValidIndex(ArrayIndex index) const; + /// \brief Append value to array at the end. + /// + /// Equivalent to jsonvalue[jsonvalue.size()] = value; + Value& append(const Value& value); + + /// Access an object value by name, create a null member if it does not exist. + /// \note Because of our implementation, keys are limited to 2^30 -1 chars. + /// Exceeding that will cause an exception. + Value& operator[](const char* key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const char* key) const; + /// Access an object value by name, create a null member if it does not exist. + /// \param key may contain embedded nulls. + Value& operator[](const std::string& key); + /// Access an object value by name, returns null if there is no member with + /// that name. + /// \param key may contain embedded nulls. + const Value& operator[](const std::string& key) const; + /** \brief Access an object value by name, create a null member if it does not + exist. + + * If the object has no entry for that name, then the member name used to store + * the new entry is not duplicated. + * Example of use: + * \code + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ + Value& operator[](const StaticString& key); +#ifdef JSON_USE_CPPTL + /// Access an object value by name, create a null member if it does not exist. + Value& operator[](const CppTL::ConstString& key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const CppTL::ConstString& key) const; +#endif + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + Value get(const char* key, const Value& defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + /// \note key may contain embedded nulls. + Value get(const char* begin, const char* end, const Value& defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + /// \param key may contain embedded nulls. + Value get(const std::string& key, const Value& defaultValue) const; +#ifdef JSON_USE_CPPTL + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + Value get(const CppTL::ConstString& key, const Value& defaultValue) const; +#endif + /// Most general and efficient version of isMember()const, get()const, + /// and operator[]const + /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 + Value const* find(char const* begin, char const* end) const; + /// Most general and efficient version of object-mutators. + /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 + /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. + Value const* demand(char const* begin, char const* end); + /// \brief Remove and return the named member. + /// + /// Do nothing if it did not exist. + /// \return the removed Value, or null. + /// \pre type() is objectValue or nullValue + /// \post type() is unchanged + /// \deprecated + Value removeMember(const char* key); + /// Same as removeMember(const char*) + /// \param key may contain embedded nulls. + /// \deprecated + Value removeMember(const std::string& key); + /// Same as removeMember(const char* begin, const char* end, Value* removed), + /// but 'key' is null-terminated. + bool removeMember(const char* key, Value* removed); + /** \brief Remove the named map member. + + Update 'removed' iff removed. + \param key may contain embedded nulls. + \return true iff removed (no exceptions) + */ + bool removeMember(std::string const& key, Value* removed); + /// Same as removeMember(std::string const& key, Value* removed) + bool removeMember(const char* begin, const char* end, Value* removed); + /** \brief Remove the indexed array element. + + O(n) expensive operations. + Update 'removed' iff removed. + \return true iff removed (no exceptions) + */ + bool removeIndex(ArrayIndex i, Value* removed); + + /// Return true if the object has a member named key. + /// \note 'key' must be null-terminated. + bool isMember(const char* key) const; + /// Return true if the object has a member named key. + /// \param key may contain embedded nulls. + bool isMember(const std::string& key) const; + /// Same as isMember(std::string const& key)const + bool isMember(const char* begin, const char* end) const; +#ifdef JSON_USE_CPPTL + /// Return true if the object has a member named key. + bool isMember(const CppTL::ConstString& key) const; +#endif + + /// \brief Return a list of the member names. + /// + /// If null, return an empty list. + /// \pre type() is objectValue or nullValue + /// \post if type() was nullValue, it remains nullValue + Members getMemberNames() const; + + //# ifdef JSON_USE_CPPTL + // EnumMemberNames enumMemberNames() const; + // EnumValues enumValues() const; + //# endif + + /// \deprecated Always pass len. + JSONCPP_DEPRECATED("Use setComment(std::string const&) instead.") + void setComment(const char* comment, CommentPlacement placement); + /// Comments must be //... or /* ... */ + void setComment(const char* comment, size_t len, CommentPlacement placement); + /// Comments must be //... or /* ... */ + void setComment(const std::string& comment, CommentPlacement placement); + bool hasComment(CommentPlacement placement) const; + /// Include delimiters and embedded newlines. + std::string getComment(CommentPlacement placement) const; + + std::string toStyledString() const; + + const_iterator begin() const; + const_iterator end() const; + + iterator begin(); + iterator end(); + +private: + void initBasic(ValueType type, bool allocated = false); + + Value& resolveReference(const char* key); + Value& resolveReference(const char* key, const char* end); + + struct CommentInfo { + CommentInfo(); + ~CommentInfo(); + + void setComment(const char* text, size_t len); + + char* comment_; + }; + + // struct MemberNamesTransform + //{ + // typedef const char *result_type; + // const char *operator()( const CZString &name ) const + // { + // return name.c_str(); + // } + //}; + + union ValueHolder { + LargestInt int_; + LargestUInt uint_; + double real_; + bool bool_; + char* string_; // actually ptr to unsigned, followed by str, unless !allocated_ + ObjectValues* map_; + } value_; + ValueType type_ : 8; + unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. + // If not allocated_, string_ must be null-terminated. + CommentInfo* comments_; +}; + +/** \brief Experimental and untested: represents an element of the "path" to + * access a node. + */ +class JSON_API PathArgument { +public: + friend class Path; + + PathArgument(); + PathArgument(ArrayIndex index); + PathArgument(const char* key); + PathArgument(const std::string& key); + +private: + enum Kind { + kindNone = 0, + kindIndex, + kindKey + }; + std::string key_; + ArrayIndex index_; + Kind kind_; +}; + +/** \brief Experimental and untested: represents a "path" to access a node. + * + * Syntax: + * - "." => root node + * - ".[n]" => elements at index 'n' of root node (an array value) + * - ".name" => member named 'name' of root node (an object value) + * - ".name1.name2.name3" + * - ".[0][1][2].name1[3]" + * - ".%" => member name is provided as parameter + * - ".[%]" => index is provied as parameter + */ +class JSON_API Path { +public: + Path(const std::string& path, + const PathArgument& a1 = PathArgument(), + const PathArgument& a2 = PathArgument(), + const PathArgument& a3 = PathArgument(), + const PathArgument& a4 = PathArgument(), + const PathArgument& a5 = PathArgument()); + + const Value& resolve(const Value& root) const; + Value resolve(const Value& root, const Value& defaultValue) const; + /// Creates the "path" to access the specified node and returns a reference on + /// the node. + Value& make(Value& root) const; + +private: + typedef std::vector InArgs; + typedef std::vector Args; + + void makePath(const std::string& path, const InArgs& in); + void addPathInArg(const std::string& path, + const InArgs& in, + InArgs::const_iterator& itInArg, + PathArgument::Kind kind); + void invalidPath(const std::string& path, int location); + + Args args_; +}; + +/** \brief base class for Value iterators. + * + */ +class JSON_API ValueIteratorBase { +public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef unsigned int size_t; + typedef int difference_type; + typedef ValueIteratorBase SelfType; + + bool operator==(const SelfType& other) const { return isEqual(other); } + + bool operator!=(const SelfType& other) const { return !isEqual(other); } + + difference_type operator-(const SelfType& other) const { + return other.computeDistance(*this); + } + + /// Return either the index or the member name of the referenced value as a + /// Value. + Value key() const; + + /// Return the index of the referenced Value, or -1 if it is not an arrayValue. + UInt index() const; + + /// Return the member name of the referenced Value, or "" if it is not an + /// objectValue. + /// \note Avoid `c_str()` on result, as embedded zeroes are possible. + std::string name() const; + + /// Return the member name of the referenced Value. "" if it is not an + /// objectValue. + /// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls. + JSONCPP_DEPRECATED("Use `key = name();` instead.") + char const* memberName() const; + /// Return the member name of the referenced Value, or NULL if it is not an + /// objectValue. + /// \note Better version than memberName(). Allows embedded nulls. + char const* memberName(char const** end) const; + +protected: + Value& deref() const; + + void increment(); + + void decrement(); + + difference_type computeDistance(const SelfType& other) const; + + bool isEqual(const SelfType& other) const; + + void copy(const SelfType& other); + +private: + Value::ObjectValues::iterator current_; + // Indicates that iterator is for a null value. + bool isNull_; + +public: + // For some reason, BORLAND needs these at the end, rather + // than earlier. No idea why. + ValueIteratorBase(); + explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); +}; + +/** \brief const iterator for object and array value. + * + */ +class JSON_API ValueConstIterator : public ValueIteratorBase { + friend class Value; + +public: + typedef const Value value_type; + //typedef unsigned int size_t; + //typedef int difference_type; + typedef const Value& reference; + typedef const Value* pointer; + typedef ValueConstIterator SelfType; + + ValueConstIterator(); + +private: +/*! \internal Use by Value to create an iterator. + */ + explicit ValueConstIterator(const Value::ObjectValues::iterator& current); +public: + SelfType& operator=(const ValueIteratorBase& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + + pointer operator->() const { return &deref(); } +}; + +/** \brief Iterator for object and array value. + */ +class JSON_API ValueIterator : public ValueIteratorBase { + friend class Value; + +public: + typedef Value value_type; + typedef unsigned int size_t; + typedef int difference_type; + typedef Value& reference; + typedef Value* pointer; + typedef ValueIterator SelfType; + + ValueIterator(); + ValueIterator(const ValueConstIterator& other); + ValueIterator(const ValueIterator& other); + +private: +/*! \internal Use by Value to create an iterator. + */ + explicit ValueIterator(const Value::ObjectValues::iterator& current); +public: + SelfType& operator=(const SelfType& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + + pointer operator->() const { return &deref(); } +}; + +} // namespace Json + + +namespace std { +/// Specialize std::swap() for Json::Value. +template<> +inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); } +} + + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // CPPTL_JSON_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/value.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/reader.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_READER_H_INCLUDED +#define CPPTL_JSON_READER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "features.h" +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +namespace Json { + +/** \brief Unserialize a JSON document into a + *Value. + * + * \deprecated Use CharReader and CharReaderBuilder. + */ +class JSON_API Reader { +public: + typedef char Char; + typedef const Char* Location; + + /** \brief Constructs a Reader allowing all features + * for parsing. + */ + Reader(); + + /** \brief Constructs a Reader allowing the specified feature set + * for parsing. + */ + Reader(const Features& features); + + /** \brief Read a Value from a JSON + * document. + * \param document UTF-8 encoded string containing the document to read. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param collectComments \c true to collect comment and allow writing them + * back during + * serialization, \c false to discard comments. + * This parameter is ignored if + * Features::allowComments_ + * is \c false. + * \return \c true if the document was successfully parsed, \c false if an + * error occurred. + */ + bool + parse(const std::string& document, Value& root, bool collectComments = true); + + /** \brief Read a Value from a JSON + document. + * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the + document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string of the + document to read. + * Must be >= beginDoc. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param collectComments \c true to collect comment and allow writing them + back during + * serialization, \c false to discard comments. + * This parameter is ignored if + Features::allowComments_ + * is \c false. + * \return \c true if the document was successfully parsed, \c false if an + error occurred. + */ + bool parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments = true); + + /// \brief Parse from input stream. + /// \see Json::operator>>(std::istream&, Json::Value&). + bool parse(std::istream& is, Value& root, bool collectComments = true); + + /** \brief Returns a user friendly string that list errors in the parsed + * document. + * \return Formatted error message with the list of errors with their location + * in + * the parsed document. An empty string is returned if no error + * occurred + * during parsing. + * \deprecated Use getFormattedErrorMessages() instead (typo fix). + */ + JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.") + std::string getFormatedErrorMessages() const; + + /** \brief Returns a user friendly string that list errors in the parsed + * document. + * \return Formatted error message with the list of errors with their location + * in + * the parsed document. An empty string is returned if no error + * occurred + * during parsing. + */ + std::string getFormattedErrorMessages() const; + +private: + enum TokenType { + tokenEndOfStream = 0, + tokenObjectBegin, + tokenObjectEnd, + tokenArrayBegin, + tokenArrayEnd, + tokenString, + tokenNumber, + tokenTrue, + tokenFalse, + tokenNull, + tokenArraySeparator, + tokenMemberSeparator, + tokenComment, + tokenError + }; + + class Token { + public: + TokenType type_; + Location start_; + Location end_; + }; + + class ErrorInfo { + public: + Token token_; + std::string message_; + Location extra_; + }; + + typedef std::deque Errors; + + bool readToken(Token& token); + void skipSpaces(); + bool match(Location pattern, int patternLength); + bool readComment(); + bool readCStyleComment(); + bool readCppStyleComment(); + bool readString(); + void readNumber(); + bool readValue(); + bool readObject(Token& token); + bool readArray(Token& token); + bool decodeNumber(Token& token); + bool decodeNumber(Token& token, Value& decoded); + bool decodeString(Token& token); + bool decodeString(Token& token, std::string& decoded); + bool decodeDouble(Token& token); + bool decodeDouble(Token& token, Value& decoded); + bool decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool addError(const std::string& message, Token& token, Location extra = 0); + bool recoverFromError(TokenType skipUntilToken); + bool addErrorAndRecover(const std::string& message, + Token& token, + TokenType skipUntilToken); + void skipUntilSpace(); + Value& currentValue(); + Char getNextChar(); + void + getLocationLineAndColumn(Location location, int& line, int& column) const; + std::string getLocationLineAndColumn(Location location) const; + void addComment(Location begin, Location end, CommentPlacement placement); + void skipCommentTokens(Token& token); + + typedef std::stack Nodes; + Nodes nodes_; + Errors errors_; + std::string document_; + Location begin_; + Location end_; + Location current_; + Location lastValueEnd_; + Value* lastValue_; + std::string commentsBefore_; + Features features_; + bool collectComments_; +}; // Reader + +/** Interface for reading JSON from a char array. + */ +class JSON_API CharReader { +public: + virtual ~CharReader() {} + /** \brief Read a Value from a JSON + document. + * The document must be a UTF-8 encoded string containing the document to read. + * + * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the + document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string of the + document to read. + * Must be >= beginDoc. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param errs [out] Formatted error messages (if not NULL) + * a user friendly string that lists errors in the parsed + * document. + * \return \c true if the document was successfully parsed, \c false if an + error occurred. + */ + virtual bool parse( + char const* beginDoc, char const* endDoc, + Value* root, std::string* errs) = 0; + + class Factory { + public: + virtual ~Factory() {} + /** \brief Allocate a CharReader via operator new(). + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual CharReader* newCharReader() const = 0; + }; // Factory +}; // CharReader + +/** \brief Build a CharReader implementation. + +Usage: +\code + using namespace Json; + CharReaderBuilder builder; + builder["collectComments"] = false; + Value value; + std::string errs; + bool ok = parseFromStream(builder, std::cin, &value, &errs); +\endcode +*/ +class JSON_API CharReaderBuilder : public CharReader::Factory { +public: + // Note: We use a Json::Value so that we can add data-members to this class + // without a major version bump. + /** Configuration of this builder. + These are case-sensitive. + Available settings (case-sensitive): + - `"collectComments": false or true` + - true to collect comment and allow writing them + back during serialization, false to discard comments. + This parameter is ignored if allowComments is false. + - `"allowComments": false or true` + - true if comments are allowed. + - `"strictRoot": false or true` + - true if root must be either an array or an object value + - `"allowDroppedNullPlaceholders": false or true` + - true if dropped null placeholders are allowed. (See StreamWriterBuilder.) + - `"allowNumericKeys": false or true` + - true if numeric object keys are allowed. + - `"allowSingleQuotes": false or true` + - true if '' are allowed for strings (both keys and values) + - `"stackLimit": integer` + - Exceeding stackLimit (recursive depth of `readValue()`) will + cause an exception. + - This is a security issue (seg-faults caused by deeply nested JSON), + so the default is low. + - `"failIfExtra": false or true` + - If true, `parse()` returns false when extra non-whitespace trails + the JSON value in the input string. + - `"rejectDupKeys": false or true` + - If true, `parse()` returns false when a key is duplicated within an object. + - `"allowSpecialFloats": false or true` + - If true, special float values (NaNs and infinities) are allowed + and their values are lossfree restorable. + + You can examine 'settings_` yourself + to see the defaults. You can also write and read them just like any + JSON Value. + \sa setDefaults() + */ + Json::Value settings_; + + CharReaderBuilder(); + virtual ~CharReaderBuilder(); + + virtual CharReader* newCharReader() const; + + /** \return true if 'settings' are legal and consistent; + * otherwise, indicate bad settings via 'invalid'. + */ + bool validate(Json::Value* invalid) const; + + /** A simple way to update a specific setting. + */ + Value& operator[](std::string key); + + /** Called by ctor, but you can use this to reset settings_. + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults + */ + static void setDefaults(Json::Value* settings); + /** Same as old Features::strictMode(). + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode + */ + static void strictMode(Json::Value* settings); +}; + +/** Consume entire stream and use its begin/end. + * Someday we might have a real StreamReader, but for now this + * is convenient. + */ +bool JSON_API parseFromStream( + CharReader::Factory const&, + std::istream&, + Value* root, std::string* errs); + +/** \brief Read from 'sin' into 'root'. + + Always keep comments from the input JSON. + + This can be used to read a file into a particular sub-object. + For example: + \code + Json::Value root; + cin >> root["dir"]["file"]; + cout << root; + \endcode + Result: + \verbatim + { + "dir": { + "file": { + // The input stream JSON would be nested here. + } + } + } + \endverbatim + \throw std::exception on parse error. + \see Json::operator<<() +*/ +JSON_API std::istream& operator>>(std::istream&, Value&); + +} // namespace Json + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // CPPTL_JSON_READER_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/reader.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/writer.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_WRITER_H_INCLUDED +#define JSON_WRITER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +namespace Json { + +class Value; + +/** + +Usage: +\code + using namespace Json; + void writeToStdout(StreamWriter::Factory const& factory, Value const& value) { + std::unique_ptr const writer( + factory.newStreamWriter()); + writer->write(value, &std::cout); + std::cout << std::endl; // add lf and flush + } +\endcode +*/ +class JSON_API StreamWriter { +protected: + std::ostream* sout_; // not owned; will not delete +public: + StreamWriter(); + virtual ~StreamWriter(); + /** Write Value into document as configured in sub-class. + Do not take ownership of sout, but maintain a reference during function. + \pre sout != NULL + \return zero on success (For now, we always return zero, so check the stream instead.) + \throw std::exception possibly, depending on configuration + */ + virtual int write(Value const& root, std::ostream* sout) = 0; + + /** \brief A simple abstract factory. + */ + class JSON_API Factory { + public: + virtual ~Factory(); + /** \brief Allocate a CharReader via operator new(). + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual StreamWriter* newStreamWriter() const = 0; + }; // Factory +}; // StreamWriter + +/** \brief Write into stringstream, then return string, for convenience. + * A StreamWriter will be created from the factory, used, and then deleted. + */ +std::string JSON_API writeString(StreamWriter::Factory const& factory, Value const& root); + + +/** \brief Build a StreamWriter implementation. + +Usage: +\code + using namespace Json; + Value value = ...; + StreamWriterBuilder builder; + builder["commentStyle"] = "None"; + builder["indentation"] = " "; // or whatever you like + std::unique_ptr writer( + builder.newStreamWriter()); + writer->write(value, &std::cout); + std::cout << std::endl; // add lf and flush +\endcode +*/ +class JSON_API StreamWriterBuilder : public StreamWriter::Factory { +public: + // Note: We use a Json::Value so that we can add data-members to this class + // without a major version bump. + /** Configuration of this builder. + Available settings (case-sensitive): + - "commentStyle": "None" or "All" + - "indentation": "" + - "enableYAMLCompatibility": false or true + - slightly change the whitespace around colons + - "dropNullPlaceholders": false or true + - Drop the "null" string from the writer's output for nullValues. + Strictly speaking, this is not valid JSON. But when the output is being + fed to a browser's Javascript, it makes for smaller output and the + browser can handle the output just fine. + - "useSpecialFloats": false or true + - If true, outputs non-finite floating point values in the following way: + NaN values as "NaN", positive infinity as "Infinity", and negative infinity + as "-Infinity". + + You can examine 'settings_` yourself + to see the defaults. You can also write and read them just like any + JSON Value. + \sa setDefaults() + */ + Json::Value settings_; + + StreamWriterBuilder(); + virtual ~StreamWriterBuilder(); + + /** + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual StreamWriter* newStreamWriter() const; + + /** \return true if 'settings' are legal and consistent; + * otherwise, indicate bad settings via 'invalid'. + */ + bool validate(Json::Value* invalid) const; + /** A simple way to update a specific setting. + */ + Value& operator[](std::string key); + + /** Called by ctor, but you can use this to reset settings_. + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults + */ + static void setDefaults(Json::Value* settings); +}; + +/** \brief Abstract class for writers. + * \deprecated Use StreamWriter. (And really, this is an implementation detail.) + */ +class JSON_API Writer { +public: + virtual ~Writer(); + + virtual std::string write(const Value& root) = 0; +}; + +/** \brief Outputs a Value in JSON format + *without formatting (not human friendly). + * + * The JSON document is written in a single line. It is not intended for 'human' + *consumption, + * but may be usefull to support feature such as RPC where bandwith is limited. + * \sa Reader, Value + * \deprecated Use StreamWriterBuilder. + */ +class JSON_API FastWriter : public Writer { + +public: + FastWriter(); + virtual ~FastWriter() {} + + void enableYAMLCompatibility(); + +public: // overridden from Writer + virtual std::string write(const Value& root); + +private: + void writeValue(const Value& value); + + std::string document_; + bool yamlCompatiblityEnabled_; +}; + +/** \brief Writes a Value in JSON format in a + *human friendly way. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + *line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + *types, + * and all the values fit on one lines, then print the array on a single + *line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + *#CommentPlacement. + * + * \sa Reader, Value, Value::setComment() + * \deprecated Use StreamWriterBuilder. + */ +class JSON_API StyledWriter : public Writer { +public: + StyledWriter(); + virtual ~StyledWriter() {} + +public: // overridden from Writer + /** \brief Serialize a Value in JSON format. + * \param root Value to serialize. + * \return String containing the JSON document that represents the root value. + */ + virtual std::string write(const Value& root); + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultineArray(const Value& value); + void pushValue(const std::string& value); + void writeIndent(); + void writeWithIndent(const std::string& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + bool hasCommentForValue(const Value& value); + static std::string normalizeEOL(const std::string& text); + + typedef std::vector ChildValues; + + ChildValues childValues_; + std::string document_; + std::string indentString_; + int rightMargin_; + int indentSize_; + bool addChildValues_; +}; + +/** \brief Writes a Value in JSON format in a + human friendly way, + to a stream rather than to a string. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + types, + * and all the values fit on one lines, then print the array on a single + line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + #CommentPlacement. + * + * \param indentation Each level will be indented by this amount extra. + * \sa Reader, Value, Value::setComment() + * \deprecated Use StreamWriterBuilder. + */ +class JSON_API StyledStreamWriter { +public: + StyledStreamWriter(std::string indentation = "\t"); + ~StyledStreamWriter() {} + +public: + /** \brief Serialize a Value in JSON format. + * \param out Stream to write to. (Can be ostringstream, e.g.) + * \param root Value to serialize. + * \note There is no point in deriving from Writer, since write() should not + * return a value. + */ + void write(std::ostream& out, const Value& root); + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultineArray(const Value& value); + void pushValue(const std::string& value); + void writeIndent(); + void writeWithIndent(const std::string& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + bool hasCommentForValue(const Value& value); + static std::string normalizeEOL(const std::string& text); + + typedef std::vector ChildValues; + + ChildValues childValues_; + std::ostream* document_; + std::string indentString_; + int rightMargin_; + std::string indentation_; + bool addChildValues_ : 1; + bool indented_ : 1; +}; + +#if defined(JSON_HAS_INT64) +std::string JSON_API valueToString(Int value); +std::string JSON_API valueToString(UInt value); +#endif // if defined(JSON_HAS_INT64) +std::string JSON_API valueToString(LargestInt value); +std::string JSON_API valueToString(LargestUInt value); +std::string JSON_API valueToString(double value); +std::string JSON_API valueToString(bool value); +std::string JSON_API valueToQuotedString(const char* value); + +/// \brief Output using the StyledStreamWriter. +/// \see Json::operator>>() +JSON_API std::ostream& operator<<(std::ostream&, const Value& root); + +} // namespace Json + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // JSON_WRITER_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/writer.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/assertions.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED +#define CPPTL_JSON_ASSERTIONS_H_INCLUDED + +#include +#include + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +/** It should not be possible for a maliciously designed file to + * cause an abort() or seg-fault, so these macros are used only + * for pre-condition violations and internal logic errors. + */ +#if JSON_USE_EXCEPTION + +// @todo <= add detail about condition in exception +# define JSON_ASSERT(condition) \ + {if (!(condition)) {Json::throwLogicError( "assert json failed" );}} + +# define JSON_FAIL_MESSAGE(message) \ + { \ + std::ostringstream oss; oss << message; \ + Json::throwLogicError(oss.str()); \ + abort(); \ + } + +#else // JSON_USE_EXCEPTION + +# define JSON_ASSERT(condition) assert(condition) + +// The call to assert() will show the failure message in debug builds. In +// release builds we abort, for a core-dump or debugger. +# define JSON_FAIL_MESSAGE(message) \ + { \ + std::ostringstream oss; oss << message; \ + assert(false && oss.str().c_str()); \ + abort(); \ + } + + +#endif + +#define JSON_ASSERT_MESSAGE(condition, message) \ + if (!(condition)) { \ + JSON_FAIL_MESSAGE(message); \ + } + +#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/assertions.h +// ////////////////////////////////////////////////////////////////////// + + + + + +#endif //ifndef JSON_AMALGATED_H_INCLUDED diff --git a/ofdEditor/libs/jsoncpp/jsoncpp.cpp b/ofdEditor/libs/jsoncpp/jsoncpp.cpp new file mode 100644 index 0000000..dd2a1e3 --- /dev/null +++ b/ofdEditor/libs/jsoncpp/jsoncpp.cpp @@ -0,0 +1,4945 @@ +/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/). +/// It is intended to be used with #include "json/json.h" + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is +released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur + +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. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + + +#include "json/json.h" + +#ifndef JSON_IS_AMALGAMATION +#error "Compile with -I PATH_TO_JSON_DIRECTORY" +#endif + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_tool.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED +#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED + +/* This header provides common string manipulation support, such as UTF-8, + * portable conversion from/to string... + * + * It is an internal header that must not be exposed. + */ + +namespace Json { + +/// Converts a unicode code-point to UTF-8. +static inline std::string codePointToUTF8(unsigned int cp) { + std::string result; + + // based on description from http://en.wikipedia.org/wiki/UTF-8 + + if (cp <= 0x7f) { + result.resize(1); + result[0] = static_cast(cp); + } else if (cp <= 0x7FF) { + result.resize(2); + result[1] = static_cast(0x80 | (0x3f & cp)); + result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); + } else if (cp <= 0xFFFF) { + result.resize(3); + result[2] = static_cast(0x80 | (0x3f & cp)); + result[1] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[0] = static_cast(0xE0 | (0xf & (cp >> 12))); + } else if (cp <= 0x10FFFF) { + result.resize(4); + result[3] = static_cast(0x80 | (0x3f & cp)); + result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); + result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); + } + + return result; +} + +/// Returns true if ch is a control character (in range [1,31]). +static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } + +enum { + /// Constant that specify the size of the buffer that must be passed to + /// uintToString. + uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 +}; + +// Defines a char buffer for use with uintToString(). +typedef char UIntToStringBuffer[uintToStringBufferSize]; + +/** Converts an unsigned integer to string. + * @param value Unsigned interger to convert to string + * @param current Input/Output string buffer. + * Must have at least uintToStringBufferSize chars free. + */ +static inline void uintToString(LargestUInt value, char*& current) { + *--current = 0; + do { + *--current = static_cast(value % 10U + static_cast('0')); + value /= 10; + } while (value != 0); +} + +/** Change ',' to '.' everywhere in buffer. + * + * We had a sophisticated way, but it did not work in WinCE. + * @see https://github.com/open-source-parsers/jsoncpp/pull/9 + */ +static inline void fixNumericLocale(char* begin, char* end) { + while (begin < end) { + if (*begin == ',') { + *begin = '.'; + } + ++begin; + } +} + +} // namespace Json { + +#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_tool.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_reader.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2011 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include "json_tool.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) +#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above +#define snprintf sprintf_s +#elif _MSC_VER >= 1900 // VC++ 14.0 and above +#define snprintf std::snprintf +#else +#define snprintf _snprintf +#endif +#elif defined(__ANDROID__) +#define snprintf snprintf +#elif __cplusplus >= 201103L +#define snprintf std::snprintf +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +// Disable warning about strdup being deprecated. +#pragma warning(disable : 4996) +#endif + +static int const stackLimit_g = 1000; +static int stackDepth_g = 0; // see readValue() + +namespace Json { + +#if __GNUC__ >= 6 +typedef std::scoped_ptr const CharReaderPtr; +#else +typedef std::auto_ptr CharReaderPtr; +#endif + +// Implementation of class Features +// //////////////////////////////// + +Features::Features() + : allowComments_(true), strictRoot_(false) +{} +Features Features::all() { return Features(); } + +Features Features::strictMode() { + Features features; + features.allowComments_ = false; + features.strictRoot_ = true; + return features; +} + +// Implementation of class Reader +// //////////////////////////////// + +static bool containsNewLine(Reader::Location begin, Reader::Location end) { + for (; begin < end; ++begin) + if (*begin == '\n' || *begin == '\r') + return true; + return false; +} + +// Class Reader +// ////////////////////////////////////////////////////////////////// + +Reader::Reader() + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(Features::all()), + collectComments_() {} + +Reader::Reader(const Features& features) + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(features), collectComments_() { +} + +bool +Reader::parse(const std::string& document, Value& root, bool collectComments) { + document_ = document; + const char* begin = document_.c_str(); + const char* end = begin + document_.length(); + return parse(begin, end, root, collectComments); +} + +bool Reader::parse(std::istream& sin, Value& root, bool collectComments) { + // std::istream_iterator begin(sin); + // std::istream_iterator end; + // Those would allow streamed input from a file, if parse() were a + // template function. + + // Since std::string is reference-counted, this at least does not + // create an extra copy. + std::string doc; + std::getline(sin, doc, (char)EOF); + return parse(doc, root, collectComments); +} + +bool Reader::parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments) { + if (!features_.allowComments_) { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = 0; + lastValue_ = 0; + commentsBefore_ = ""; + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + stackDepth_g = 0; // Yes, this is bad coding, but options are limited. + bool successful = readValue(); + Token token; + skipCommentTokens(token); + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { + if (!root.isArray() && !root.isObject()) { + // Set error location to start of doc, ideally should be first token found + // in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError( + "A valid JSON document must be either an array or an object value.", + token); + return false; + } + } + return successful; +} + +bool Reader::readValue() { + // This is a non-reentrant way to support a stackLimit. Terrible! + // But this deprecated class has a security problem: Bad input can + // cause a seg-fault. This seems like a fair, binary-compatible way + // to prevent the problem. + if (stackDepth_g >= stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue()."); + ++stackDepth_g; + + Token token; + skipCommentTokens(token); + bool successful = true; + + if (collectComments_ && !commentsBefore_.empty()) { + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_ = ""; + } + + switch (token.type_) { + case tokenObjectBegin: + successful = readObject(token); + break; + case tokenArrayBegin: + successful = readArray(token); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: + { + Value v(true); + currentValue().swapPayload(v); + } + break; + case tokenFalse: + { + Value v(false); + currentValue().swapPayload(v); + } + break; + case tokenNull: + { + Value v; + currentValue().swapPayload(v); + } + break; + // Else, fall through... + default: + return addError("Syntax error: value, object or array expected.", token); + } + + if (collectComments_) { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); + } + + --stackDepth_g; + return successful; +} + +void Reader::skipCommentTokens(Token& token) { + if (features_.allowComments_) { + do { + readToken(token); + } while (token.type_ == tokenComment); + } else { + readToken(token); + } +} + +bool Reader::readToken(Token& token) { + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); + bool ok = true; + switch (c) { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + token.type_ = tokenNumber; + readNumber(); + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if (!ok) + token.type_ = tokenError; + token.end_ = current_; + return true; +} + +void Reader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + ++current_; + else + break; + } +} + +bool Reader::match(Location pattern, int patternLength) { + if (end_ - current_ < patternLength) + return false; + int index = patternLength; + while (index--) + if (current_[index] != pattern[index]) + return false; + current_ += patternLength; + return true; +} + +bool Reader::readComment() { + Location commentBegin = current_ - 1; + Char c = getNextChar(); + bool successful = false; + if (c == '*') + successful = readCStyleComment(); + else if (c == '/') + successful = readCppStyleComment(); + if (!successful) + return false; + + if (collectComments_) { + CommentPlacement placement = commentBefore; + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (c != '*' || !containsNewLine(commentBegin, current_)) + placement = commentAfterOnSameLine; + } + + addComment(commentBegin, current_, placement); + } + return true; +} + +static std::string normalizeEOL(Reader::Location begin, Reader::Location end) { + std::string normalized; + normalized.reserve(end - begin); + Reader::Location current = begin; + while (current != end) { + char c = *current++; + if (c == '\r') { + if (current != end && *current == '\n') + // convert dos EOL + ++current; + // convert Mac EOL + normalized += '\n'; + } else { + normalized += c; + } + } + return normalized; +} + +void +Reader::addComment(Location begin, Location end, CommentPlacement placement) { + assert(collectComments_); + const std::string& normalized = normalizeEOL(begin, end); + if (placement == commentAfterOnSameLine) { + assert(lastValue_ != 0); + lastValue_->setComment(normalized, placement); + } else { + commentsBefore_ += normalized; + } +} + +bool Reader::readCStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') + break; + } + return getNextChar() == '/'; +} + +bool Reader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '\n') + break; + if (c == '\r') { + // Consume DOS EOL. It will be normalized in addComment. + if (current_ != end_ && *current_ == '\n') + getNextChar(); + // Break on Moc OS 9 EOL. + break; + } + } + return true; +} + +void Reader::readNumber() { + const char *p = current_; + char c = '0'; // stopgap for already consumed character + // integral part + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + // fractional part + if (c == '.') { + c = (current_ = p) < end_ ? *p++ : 0; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + } + // exponential part + if (c == 'e' || c == 'E') { + c = (current_ = p) < end_ ? *p++ : 0; + if (c == '+' || c == '-') + c = (current_ = p) < end_ ? *p++ : 0; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + } +} + +bool Reader::readString() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '"') + break; + } + return c == '"'; +} + +bool Reader::readObject(Token& /*tokenStart*/) { + Token tokenName; + std::string name; + Value init(objectValue); + currentValue().swapPayload(init); + while (readToken(tokenName)) { + bool initialTokenOk = true; + while (tokenName.type_ == tokenComment && initialTokenOk) + initialTokenOk = readToken(tokenName); + if (!initialTokenOk) + break; + if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object + return true; + name = ""; + if (tokenName.type_ == tokenString) { + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + } else { + break; + } + + Token colon; + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover( + "Missing ':' after object member name", colon, tokenObjectEnd); + } + Value& value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenObjectEnd); + + Token comma; + if (!readToken(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && + comma.type_ != tokenComment)) { + return addErrorAndRecover( + "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); + } + bool finalizeTokenOk = true; + while (comma.type_ == tokenComment && finalizeTokenOk) + finalizeTokenOk = readToken(comma); + if (comma.type_ == tokenObjectEnd) + return true; + } + return addErrorAndRecover( + "Missing '}' or object member name", tokenName, tokenObjectEnd); +} + +bool Reader::readArray(Token& /*tokenStart*/) { + Value init(arrayValue); + currentValue().swapPayload(init); + skipSpaces(); + if (*current_ == ']') // empty array + { + Token endArray; + readToken(endArray); + return true; + } + int index = 0; + for (;;) { + Value& value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenArrayEnd); + + Token token; + // Accept Comment after last item in the array. + ok = readToken(token); + while (token.type_ == tokenComment && ok) { + ok = readToken(token); + } + bool badTokenType = + (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); + if (!ok || badTokenType) { + return addErrorAndRecover( + "Missing ',' or ']' in array declaration", token, tokenArrayEnd); + } + if (token.type_ == tokenArrayEnd) + break; + } + return true; +} + +bool Reader::decodeNumber(Token& token) { + Value decoded; + if (!decodeNumber(token, decoded)) + return false; + currentValue().swapPayload(decoded); + return true; +} + +bool Reader::decodeNumber(Token& token, Value& decoded) { + // Attempts to parse the number as an integer. If the number is + // larger than the maximum supported value of an integer then + // we decode the number as a double. + Location current = token.start_; + bool isNegative = *current == '-'; + if (isNegative) + ++current; + // TODO: Help the compiler do the div and mod at compile time or get rid of them. + Value::LargestUInt maxIntegerValue = + isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 + : Value::maxLargestUInt; + Value::LargestUInt threshold = maxIntegerValue / 10; + Value::LargestUInt value = 0; + while (current < token.end_) { + Char c = *current++; + if (c < '0' || c > '9') + return decodeDouble(token, decoded); + Value::UInt digit(c - '0'); + if (value >= threshold) { + // We've hit or exceeded the max value divided by 10 (rounded down). If + // a) we've only just touched the limit, b) this is the last digit, and + // c) it's small enough to fit in that rounding delta, we're okay. + // Otherwise treat this number as a double to avoid overflow. + if (value > threshold || current != token.end_ || + digit > maxIntegerValue % 10) { + return decodeDouble(token, decoded); + } + } + value = value * 10 + digit; + } + if (isNegative && value == maxIntegerValue) + decoded = Value::minLargestInt; + else if (isNegative) + decoded = -Value::LargestInt(value); + else if (value <= Value::LargestUInt(Value::maxInt)) + decoded = Value::LargestInt(value); + else + decoded = value; + return true; +} + +bool Reader::decodeDouble(Token& token) { + Value decoded; + if (!decodeDouble(token, decoded)) + return false; + currentValue().swapPayload(decoded); + return true; +} + +bool Reader::decodeDouble(Token& token, Value& decoded) { + double value = 0; + std::string buffer(token.start_, token.end_); + std::istringstream is(buffer); + if (!(is >> value)) + return addError("'" + std::string(token.start_, token.end_) + + "' is not a number.", + token); + decoded = value; + return true; +} + +bool Reader::decodeString(Token& token) { + std::string decoded_string; + if (!decodeString(token, decoded_string)) + return false; + Value decoded(decoded_string); + currentValue().swapPayload(decoded); + return true; +} + +bool Reader::decodeString(Token& token, std::string& decoded) { + decoded.reserve(token.end_ - token.start_ - 2); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + while (current != end) { + Char c = *current++; + if (c == '"') + break; + else if (c == '\\') { + if (current == end) + return addError("Empty escape sequence in string", token, current); + Char escape = *current++; + switch (escape) { + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); + } + } else { + decoded += c; + } + } + return true; +} + +bool Reader::decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) { + // surrogate pairs + if (end - current < 6) + return addError( + "additional six characters expected to parse unicode surrogate pair.", + token, + current); + unsigned int surrogatePair; + if (*(current++) == '\\' && *(current++) == 'u') { + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } else + return false; + } else + return addError("expecting another \\u token to begin the second half of " + "a unicode surrogate pair", + token, + current); + } + return true; +} + +bool Reader::decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + if (end - current < 4) + return addError( + "Bad unicode escape sequence in string: four digits expected.", + token, + current); + unicode = 0; + for (int index = 0; index < 4; ++index) { + Char c = *current++; + unicode *= 16; + if (c >= '0' && c <= '9') + unicode += c - '0'; + else if (c >= 'a' && c <= 'f') + unicode += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + unicode += c - 'A' + 10; + else + return addError( + "Bad unicode escape sequence in string: hexadecimal digit expected.", + token, + current); + } + return true; +} + +bool +Reader::addError(const std::string& message, Token& token, Location extra) { + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back(info); + return false; +} + +bool Reader::recoverFromError(TokenType skipUntilToken) { + int errorCount = int(errors_.size()); + Token skip; + for (;;) { + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery + if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) + break; + } + errors_.resize(errorCount); + return false; +} + +bool Reader::addErrorAndRecover(const std::string& message, + Token& token, + TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); +} + +Value& Reader::currentValue() { return *(nodes_.top()); } + +Reader::Char Reader::getNextChar() { + if (current_ == end_) + return 0; + return *current_++; +} + +void Reader::getLocationLineAndColumn(Location location, + int& line, + int& column) const { + Location current = begin_; + Location lastLineStart = current; + line = 0; + while (current < location && current != end_) { + Char c = *current++; + if (c == '\r') { + if (*current == '\n') + ++current; + lastLineStart = current; + ++line; + } else if (c == '\n') { + lastLineStart = current; + ++line; + } + } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; +} + +std::string Reader::getLocationLineAndColumn(Location location) const { + int line, column; + getLocationLineAndColumn(location, line, column); + char buffer[18 + 16 + 16 + 1]; + snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); + return buffer; +} + +// Deprecated. Preserved for backward compatibility +std::string Reader::getFormatedErrorMessages() const { + return getFormattedErrorMessages(); +} + +std::string Reader::getFormattedErrorMessages() const { + std::string formattedMessage; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError) { + const ErrorInfo& error = *itError; + formattedMessage += + "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if (error.extra_) + formattedMessage += + "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; + } + return formattedMessage; +} + +// Reader +///////////////////////// + +// exact copy of Features +class OurFeatures { +public: + static OurFeatures all(); + OurFeatures(); + bool allowComments_; + bool strictRoot_; + bool allowDroppedNullPlaceholders_; + bool allowNumericKeys_; + bool allowSingleQuotes_; + bool failIfExtra_; + bool rejectDupKeys_; + bool allowSpecialFloats_; + int stackLimit_; +}; // OurFeatures + +// exact copy of Implementation of class Features +// //////////////////////////////// + +OurFeatures::OurFeatures() + : allowComments_(true), strictRoot_(false) + , allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) + , allowSingleQuotes_(false) + , failIfExtra_(false) + , allowSpecialFloats_(false) +{ +} + +OurFeatures OurFeatures::all() { return OurFeatures(); } + +// Implementation of class Reader +// //////////////////////////////// + +// exact copy of Reader, renamed to OurReader +class OurReader { +public: + typedef char Char; + typedef const Char* Location; + struct StructuredError { + size_t offset_start; + size_t offset_limit; + std::string message; + }; + + OurReader(OurFeatures const& features); + bool parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments = true); + std::string getFormattedErrorMessages() const; + +private: + OurReader(OurReader const&); // no impl + void operator=(OurReader const&); // no impl + + enum TokenType { + tokenEndOfStream = 0, + tokenObjectBegin, + tokenObjectEnd, + tokenArrayBegin, + tokenArrayEnd, + tokenString, + tokenNumber, + tokenTrue, + tokenFalse, + tokenNull, + tokenNaN, + tokenPosInf, + tokenNegInf, + tokenArraySeparator, + tokenMemberSeparator, + tokenComment, + tokenError + }; + + class Token { + public: + TokenType type_; + Location start_; + Location end_; + }; + + class ErrorInfo { + public: + Token token_; + std::string message_; + Location extra_; + }; + + typedef std::deque Errors; + + bool readToken(Token& token); + void skipSpaces(); + bool match(Location pattern, int patternLength); + bool readComment(); + bool readCStyleComment(); + bool readCppStyleComment(); + bool readString(); + bool readStringSingleQuote(); + bool readNumber(bool checkInf); + bool readValue(); + bool readObject(Token& token); + bool readArray(Token& token); + bool decodeNumber(Token& token); + bool decodeNumber(Token& token, Value& decoded); + bool decodeString(Token& token); + bool decodeString(Token& token, std::string& decoded); + bool decodeDouble(Token& token); + bool decodeDouble(Token& token, Value& decoded); + bool decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool addError(const std::string& message, Token& token, Location extra = 0); + bool recoverFromError(TokenType skipUntilToken); + bool addErrorAndRecover(const std::string& message, + Token& token, + TokenType skipUntilToken); + void skipUntilSpace(); + Value& currentValue(); + Char getNextChar(); + void + getLocationLineAndColumn(Location location, int& line, int& column) const; + std::string getLocationLineAndColumn(Location location) const; + void addComment(Location begin, Location end, CommentPlacement placement); + void skipCommentTokens(Token& token); + + typedef std::stack Nodes; + Nodes nodes_; + Errors errors_; + std::string document_; + Location begin_; + Location end_; + Location current_; + Location lastValueEnd_; + Value* lastValue_; + std::string commentsBefore_; + int stackDepth_; + + OurFeatures const features_; + bool collectComments_; +}; // OurReader + +// complete copy of Read impl, for OurReader + +OurReader::OurReader(OurFeatures const& features) + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(features), collectComments_() { +} + +bool OurReader::parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments) { + if (!features_.allowComments_) { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = 0; + lastValue_ = 0; + commentsBefore_ = ""; + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + stackDepth_ = 0; + bool successful = readValue(); + Token token; + skipCommentTokens(token); + if (features_.failIfExtra_) { + if (token.type_ != tokenError && token.type_ != tokenEndOfStream) { + addError("Extra non-whitespace after JSON value.", token); + return false; + } + } + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { + if (!root.isArray() && !root.isObject()) { + // Set error location to start of doc, ideally should be first token found + // in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError( + "A valid JSON document must be either an array or an object value.", + token); + return false; + } + } + return successful; +} + +bool OurReader::readValue() { + if (stackDepth_ >= features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue()."); + ++stackDepth_; + Token token; + skipCommentTokens(token); + bool successful = true; + + if (collectComments_ && !commentsBefore_.empty()) { + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_ = ""; + } + + switch (token.type_) { + case tokenObjectBegin: + successful = readObject(token); + break; + case tokenArrayBegin: + successful = readArray(token); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: + { + Value v(true); + currentValue().swapPayload(v); + } + break; + case tokenFalse: + { + Value v(false); + currentValue().swapPayload(v); + } + break; + case tokenNull: + { + Value v; + currentValue().swapPayload(v); + } + break; + case tokenNaN: + { + Value v(std::numeric_limits::quiet_NaN()); + currentValue().swapPayload(v); + } + break; + case tokenPosInf: + { + Value v(std::numeric_limits::infinity()); + currentValue().swapPayload(v); + } + break; + case tokenNegInf: + { + Value v(-std::numeric_limits::infinity()); + currentValue().swapPayload(v); + } + break; + case tokenArraySeparator: + case tokenObjectEnd: + case tokenArrayEnd: + if (features_.allowDroppedNullPlaceholders_) { + // "Un-read" the current token and mark the current value as a null + // token. + current_--; + Value v; + currentValue().swapPayload(v); + break; + } // else, fall through ... + default: + return addError("Syntax error: value, object or array expected.", token); + } + + if (collectComments_) { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); + } + + --stackDepth_; + return successful; +} + +void OurReader::skipCommentTokens(Token& token) { + if (features_.allowComments_) { + do { + readToken(token); + } while (token.type_ == tokenComment); + } else { + readToken(token); + } +} + +bool OurReader::readToken(Token& token) { + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); + bool ok = true; + switch (c) { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '\'': + if (features_.allowSingleQuotes_) { + token.type_ = tokenString; + ok = readStringSingleQuote(); + break; + } // else continue + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + token.type_ = tokenNumber; + readNumber(false); + break; + case '-': + if (readNumber(true)) { + token.type_ = tokenNumber; + } else { + token.type_ = tokenNegInf; + ok = features_.allowSpecialFloats_ && match("nfinity", 7); + } + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case 'N': + if (features_.allowSpecialFloats_) { + token.type_ = tokenNaN; + ok = match("aN", 2); + } else { + ok = false; + } + break; + case 'I': + if (features_.allowSpecialFloats_) { + token.type_ = tokenPosInf; + ok = match("nfinity", 7); + } else { + ok = false; + } + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if (!ok) + token.type_ = tokenError; + token.end_ = current_; + return true; +} + +void OurReader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + ++current_; + else + break; + } +} + +bool OurReader::match(Location pattern, int patternLength) { + if (end_ - current_ < patternLength) + return false; + int index = patternLength; + while (index--) + if (current_[index] != pattern[index]) + return false; + current_ += patternLength; + return true; +} + +bool OurReader::readComment() { + Location commentBegin = current_ - 1; + Char c = getNextChar(); + bool successful = false; + if (c == '*') + successful = readCStyleComment(); + else if (c == '/') + successful = readCppStyleComment(); + if (!successful) + return false; + + if (collectComments_) { + CommentPlacement placement = commentBefore; + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (c != '*' || !containsNewLine(commentBegin, current_)) + placement = commentAfterOnSameLine; + } + + addComment(commentBegin, current_, placement); + } + return true; +} + +void +OurReader::addComment(Location begin, Location end, CommentPlacement placement) { + assert(collectComments_); + const std::string& normalized = normalizeEOL(begin, end); + if (placement == commentAfterOnSameLine) { + assert(lastValue_ != 0); + lastValue_->setComment(normalized, placement); + } else { + commentsBefore_ += normalized; + } +} + +bool OurReader::readCStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') + break; + } + return getNextChar() == '/'; +} + +bool OurReader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '\n') + break; + if (c == '\r') { + // Consume DOS EOL. It will be normalized in addComment. + if (current_ != end_ && *current_ == '\n') + getNextChar(); + // Break on Moc OS 9 EOL. + break; + } + } + return true; +} + +bool OurReader::readNumber(bool checkInf) { + const char *p = current_; + if (checkInf && p != end_ && *p == 'I') { + current_ = ++p; + return false; + } + char c = '0'; // stopgap for already consumed character + // integral part + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + // fractional part + if (c == '.') { + c = (current_ = p) < end_ ? *p++ : 0; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + } + // exponential part + if (c == 'e' || c == 'E') { + c = (current_ = p) < end_ ? *p++ : 0; + if (c == '+' || c == '-') + c = (current_ = p) < end_ ? *p++ : 0; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + } + return true; +} +bool OurReader::readString() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '"') + break; + } + return c == '"'; +} + + +bool OurReader::readStringSingleQuote() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '\'') + break; + } + return c == '\''; +} + +bool OurReader::readObject(Token& /*tokenStart*/) { + Token tokenName; + std::string name; + Value init(objectValue); + currentValue().swapPayload(init); + while (readToken(tokenName)) { + bool initialTokenOk = true; + while (tokenName.type_ == tokenComment && initialTokenOk) + initialTokenOk = readToken(tokenName); + if (!initialTokenOk) + break; + if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object + return true; + name = ""; + if (tokenName.type_ == tokenString) { + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { + Value numberName; + if (!decodeNumber(tokenName, numberName)) + return recoverFromError(tokenObjectEnd); + name = numberName.asString(); + } else { + break; + } + + Token colon; + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover( + "Missing ':' after object member name", colon, tokenObjectEnd); + } + if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30"); + if (features_.rejectDupKeys_ && currentValue().isMember(name)) { + std::string msg = "Duplicate key: '" + name + "'"; + return addErrorAndRecover( + msg, tokenName, tokenObjectEnd); + } + Value& value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenObjectEnd); + + Token comma; + if (!readToken(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && + comma.type_ != tokenComment)) { + return addErrorAndRecover( + "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); + } + bool finalizeTokenOk = true; + while (comma.type_ == tokenComment && finalizeTokenOk) + finalizeTokenOk = readToken(comma); + if (comma.type_ == tokenObjectEnd) + return true; + } + return addErrorAndRecover( + "Missing '}' or object member name", tokenName, tokenObjectEnd); +} + +bool OurReader::readArray(Token& /*tokenStart*/) { + Value init(arrayValue); + currentValue().swapPayload(init); + skipSpaces(); + if (*current_ == ']') // empty array + { + Token endArray; + readToken(endArray); + return true; + } + int index = 0; + for (;;) { + Value& value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenArrayEnd); + + Token token; + // Accept Comment after last item in the array. + ok = readToken(token); + while (token.type_ == tokenComment && ok) { + ok = readToken(token); + } + bool badTokenType = + (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); + if (!ok || badTokenType) { + return addErrorAndRecover( + "Missing ',' or ']' in array declaration", token, tokenArrayEnd); + } + if (token.type_ == tokenArrayEnd) + break; + } + return true; +} + +bool OurReader::decodeNumber(Token& token) { + Value decoded; + if (!decodeNumber(token, decoded)) + return false; + currentValue().swapPayload(decoded); + return true; +} + +bool OurReader::decodeNumber(Token& token, Value& decoded) { + // Attempts to parse the number as an integer. If the number is + // larger than the maximum supported value of an integer then + // we decode the number as a double. + Location current = token.start_; + bool isNegative = *current == '-'; + if (isNegative) + ++current; + // TODO: Help the compiler do the div and mod at compile time or get rid of them. + Value::LargestUInt maxIntegerValue = + isNegative ? Value::LargestUInt(-Value::minLargestInt) + : Value::maxLargestUInt; + Value::LargestUInt threshold = maxIntegerValue / 10; + Value::LargestUInt value = 0; + while (current < token.end_) { + Char c = *current++; + if (c < '0' || c > '9') + return decodeDouble(token, decoded); + Value::UInt digit(c - '0'); + if (value >= threshold) { + // We've hit or exceeded the max value divided by 10 (rounded down). If + // a) we've only just touched the limit, b) this is the last digit, and + // c) it's small enough to fit in that rounding delta, we're okay. + // Otherwise treat this number as a double to avoid overflow. + if (value > threshold || current != token.end_ || + digit > maxIntegerValue % 10) { + return decodeDouble(token, decoded); + } + } + value = value * 10 + digit; + } + if (isNegative) + decoded = -Value::LargestInt(value); + else if (value <= Value::LargestUInt(Value::maxInt)) + decoded = Value::LargestInt(value); + else + decoded = value; + return true; +} + +bool OurReader::decodeDouble(Token& token) { + Value decoded; + if (!decodeDouble(token, decoded)) + return false; + currentValue().swapPayload(decoded); + return true; +} + +bool OurReader::decodeDouble(Token& token, Value& decoded) { + double value = 0; + std::string buffer( token.start_, token.end_ ); + std::istringstream is(buffer); + if (!(is >> value)) + return addError("'" + std::string(token.start_, token.end_) + + "' is not a number.", + token); + decoded = value; + return true; +} + +bool OurReader::decodeString(Token& token) { + std::string decoded_string; + if (!decodeString(token, decoded_string)) + return false; + Value decoded(decoded_string); + currentValue().swapPayload(decoded); + return true; +} + +bool OurReader::decodeString(Token& token, std::string& decoded) { + decoded.reserve(token.end_ - token.start_ - 2); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + while (current != end) { + Char c = *current++; + if (c == '"') + break; + else if (c == '\\') { + if (current == end) + return addError("Empty escape sequence in string", token, current); + Char escape = *current++; + switch (escape) { + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); + } + } else { + decoded += c; + } + } + return true; +} + +bool OurReader::decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) { + // surrogate pairs + if (end - current < 6) + return addError( + "additional six characters expected to parse unicode surrogate pair.", + token, + current); + unsigned int surrogatePair; + if (*(current++) == '\\' && *(current++) == 'u') { + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } else + return false; + } else + return addError("expecting another \\u token to begin the second half of " + "a unicode surrogate pair", + token, + current); + } + return true; +} + +bool OurReader::decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + if (end - current < 4) + return addError( + "Bad unicode escape sequence in string: four digits expected.", + token, + current); + unicode = 0; + for (int index = 0; index < 4; ++index) { + Char c = *current++; + unicode *= 16; + if (c >= '0' && c <= '9') + unicode += c - '0'; + else if (c >= 'a' && c <= 'f') + unicode += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + unicode += c - 'A' + 10; + else + return addError( + "Bad unicode escape sequence in string: hexadecimal digit expected.", + token, + current); + } + return true; +} + +bool +OurReader::addError(const std::string& message, Token& token, Location extra) { + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back(info); + return false; +} + +bool OurReader::recoverFromError(TokenType skipUntilToken) { + int errorCount = int(errors_.size()); + Token skip; + for (;;) { + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery + if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) + break; + } + errors_.resize(errorCount); + return false; +} + +bool OurReader::addErrorAndRecover(const std::string& message, + Token& token, + TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); +} + +Value& OurReader::currentValue() { return *(nodes_.top()); } + +OurReader::Char OurReader::getNextChar() { + if (current_ == end_) + return 0; + return *current_++; +} + +void OurReader::getLocationLineAndColumn(Location location, + int& line, + int& column) const { + Location current = begin_; + Location lastLineStart = current; + line = 0; + while (current < location && current != end_) { + Char c = *current++; + if (c == '\r') { + if (*current == '\n') + ++current; + lastLineStart = current; + ++line; + } else if (c == '\n') { + lastLineStart = current; + ++line; + } + } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; +} + +std::string OurReader::getLocationLineAndColumn(Location location) const { + int line, column; + getLocationLineAndColumn(location, line, column); + char buffer[18 + 16 + 16 + 1]; + snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); + return buffer; +} + +std::string OurReader::getFormattedErrorMessages() const { + std::string formattedMessage; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError) { + const ErrorInfo& error = *itError; + formattedMessage += + "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if (error.extra_) + formattedMessage += + "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; + } + return formattedMessage; +} + + +class OurCharReader : public CharReader { + bool const collectComments_; + OurReader reader_; +public: + OurCharReader( + bool collectComments, + OurFeatures const& features) + : collectComments_(collectComments) + , reader_(features) + {} + virtual bool parse( + char const* beginDoc, char const* endDoc, + Value* root, std::string* errs) { + bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); + if (errs) { + *errs = reader_.getFormattedErrorMessages(); + } + return ok; + } +}; + +CharReaderBuilder::CharReaderBuilder() +{ + setDefaults(&settings_); +} +CharReaderBuilder::~CharReaderBuilder() +{} +CharReader* CharReaderBuilder::newCharReader() const +{ + bool collectComments = settings_["collectComments"].asBool(); + OurFeatures features = OurFeatures::all(); + features.allowComments_ = settings_["allowComments"].asBool(); + features.strictRoot_ = settings_["strictRoot"].asBool(); + features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool(); + features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); + features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); + features.stackLimit_ = settings_["stackLimit"].asInt(); + features.failIfExtra_ = settings_["failIfExtra"].asBool(); + features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); + features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool(); + return new OurCharReader(collectComments, features); +} +static void getValidReaderKeys(std::set* valid_keys) +{ + valid_keys->clear(); + valid_keys->insert("collectComments"); + valid_keys->insert("allowComments"); + valid_keys->insert("strictRoot"); + valid_keys->insert("allowDroppedNullPlaceholders"); + valid_keys->insert("allowNumericKeys"); + valid_keys->insert("allowSingleQuotes"); + valid_keys->insert("stackLimit"); + valid_keys->insert("failIfExtra"); + valid_keys->insert("rejectDupKeys"); + valid_keys->insert("allowSpecialFloats"); +} +bool CharReaderBuilder::validate(Json::Value* invalid) const +{ + Json::Value my_invalid; + if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL + Json::Value& inv = *invalid; + std::set valid_keys; + getValidReaderKeys(&valid_keys); + Value::Members keys = settings_.getMemberNames(); + size_t n = keys.size(); + for (size_t i = 0; i < n; ++i) { + std::string const& key = keys[i]; + if (valid_keys.find(key) == valid_keys.end()) { + inv[key] = settings_[key]; + } + } + return 0u == inv.size(); +} +Value& CharReaderBuilder::operator[](std::string key) +{ + return settings_[key]; +} +// static +void CharReaderBuilder::strictMode(Json::Value* settings) +{ +//! [CharReaderBuilderStrictMode] + (*settings)["allowComments"] = false; + (*settings)["strictRoot"] = true; + (*settings)["allowDroppedNullPlaceholders"] = false; + (*settings)["allowNumericKeys"] = false; + (*settings)["allowSingleQuotes"] = false; + (*settings)["failIfExtra"] = true; + (*settings)["rejectDupKeys"] = true; + (*settings)["allowSpecialFloats"] = false; +//! [CharReaderBuilderStrictMode] +} +// static +void CharReaderBuilder::setDefaults(Json::Value* settings) +{ +//! [CharReaderBuilderDefaults] + (*settings)["collectComments"] = true; + (*settings)["allowComments"] = true; + (*settings)["strictRoot"] = false; + (*settings)["allowDroppedNullPlaceholders"] = false; + (*settings)["allowNumericKeys"] = false; + (*settings)["allowSingleQuotes"] = false; + (*settings)["stackLimit"] = 1000; + (*settings)["failIfExtra"] = false; + (*settings)["rejectDupKeys"] = false; + (*settings)["allowSpecialFloats"] = false; +//! [CharReaderBuilderDefaults] +} + +////////////////////////////////// +// global functions + +bool parseFromStream( + CharReader::Factory const& fact, std::istream& sin, + Value* root, std::string* errs) +{ + std::ostringstream ssin; + ssin << sin.rdbuf(); + std::string doc = ssin.str(); + char const* begin = doc.data(); + char const* end = begin + doc.size(); + // Note that we do not actually need a null-terminator. + CharReaderPtr const reader(fact.newCharReader()); + return reader->parse(begin, end, root, errs); +} + +std::istream& operator>>(std::istream& sin, Value& root) { + CharReaderBuilder b; + std::string errs; + bool ok = parseFromStream(b, sin, &root, &errs); + if (!ok) { + fprintf(stderr, + "Error from reader: %s", + errs.c_str()); + + throwRuntimeError("reader error"); + } + return sin; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_reader.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_valueiterator.inl +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +// included by json_value.cpp + +namespace Json { + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIteratorBase +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIteratorBase::ValueIteratorBase() + : current_(), isNull_(true) { +} + +ValueIteratorBase::ValueIteratorBase( + const Value::ObjectValues::iterator& current) + : current_(current), isNull_(false) {} + +Value& ValueIteratorBase::deref() const { + return current_->second; +} + +void ValueIteratorBase::increment() { + ++current_; +} + +void ValueIteratorBase::decrement() { + --current_; +} + +ValueIteratorBase::difference_type +ValueIteratorBase::computeDistance(const SelfType& other) const { +#ifdef JSON_USE_CPPTL_SMALLMAP + return other.current_ - current_; +#else + // Iterator for null value are initialized using the default + // constructor, which initialize current_ to the default + // std::map::iterator. As begin() and end() are two instance + // of the default std::map::iterator, they can not be compared. + // To allow this, we handle this comparison specifically. + if (isNull_ && other.isNull_) { + return 0; + } + + // Usage of std::distance is not portable (does not compile with Sun Studio 12 + // RogueWave STL, + // which is the one used by default). + // Using a portable hand-made version for non random iterator instead: + // return difference_type( std::distance( current_, other.current_ ) ); + difference_type myDistance = 0; + for (Value::ObjectValues::iterator it = current_; it != other.current_; + ++it) { + ++myDistance; + } + return myDistance; +#endif +} + +bool ValueIteratorBase::isEqual(const SelfType& other) const { + if (isNull_) { + return other.isNull_; + } + return current_ == other.current_; +} + +void ValueIteratorBase::copy(const SelfType& other) { + current_ = other.current_; + isNull_ = other.isNull_; +} + +Value ValueIteratorBase::key() const { + const Value::CZString czstring = (*current_).first; + if (czstring.data()) { + if (czstring.isStaticString()) + return Value(StaticString(czstring.data())); + return Value(czstring.data(), czstring.data() + czstring.length()); + } + return Value(czstring.index()); +} + +UInt ValueIteratorBase::index() const { + const Value::CZString czstring = (*current_).first; + if (!czstring.data()) + return czstring.index(); + return Value::UInt(-1); +} + +std::string ValueIteratorBase::name() const { + char const* keey; + char const* end; + keey = memberName(&end); + if (!keey) return std::string(); + return std::string(keey, end); +} + +char const* ValueIteratorBase::memberName() const { + const char* cname = (*current_).first.data(); + return cname ? cname : ""; +} + +char const* ValueIteratorBase::memberName(char const** end) const { + const char* cname = (*current_).first.data(); + if (!cname) { + *end = NULL; + return NULL; + } + *end = cname + (*current_).first.length(); + return cname; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueConstIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueConstIterator::ValueConstIterator() {} + +ValueConstIterator::ValueConstIterator( + const Value::ObjectValues::iterator& current) + : ValueIteratorBase(current) {} + +ValueConstIterator& ValueConstIterator:: +operator=(const ValueIteratorBase& other) { + copy(other); + return *this; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIterator::ValueIterator() {} + +ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) + : ValueIteratorBase(current) {} + +ValueIterator::ValueIterator(const ValueConstIterator& other) + : ValueIteratorBase(other) {} + +ValueIterator::ValueIterator(const ValueIterator& other) + : ValueIteratorBase(other) {} + +ValueIterator& ValueIterator::operator=(const SelfType& other) { + copy(other); + return *this; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_valueiterator.inl +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_value.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2011 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#ifdef JSON_USE_CPPTL +#include +#endif +#include // size_t +#include // min() + +#define JSON_ASSERT_UNREACHABLE assert(false) + +namespace Json { + +// This is a walkaround to avoid the static initialization of Value::null. +// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of +// 8 (instead of 4) as a bit of future-proofing. +#if defined(__ARMEL__) +#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) +#else +// This exists for binary compatibility only. Use nullRef. +const Value Value::null; +#define ALIGNAS(byte_alignment) +#endif +static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; +const unsigned char& kNullRef = kNull[0]; +const Value& Value::nullRef = reinterpret_cast(kNullRef); + +const Int Value::minInt = Int(~(UInt(-1) / 2)); +const Int Value::maxInt = Int(UInt(-1) / 2); +const UInt Value::maxUInt = UInt(-1); +#if defined(JSON_HAS_INT64) +const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); +const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); +const UInt64 Value::maxUInt64 = UInt64(-1); +// The constant is hard-coded because some compiler have trouble +// converting Value::maxUInt64 to a double correctly (AIX/xlC). +// Assumes that UInt64 is a 64 bits integer. +static const double maxUInt64AsDouble = 18446744073709551615.0; +#endif // defined(JSON_HAS_INT64) +const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); +const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); +const LargestUInt Value::maxLargestUInt = LargestUInt(-1); + +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +template +static inline bool InRange(double d, T min, U max) { + return d >= min && d <= max; +} +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +static inline double integerToDouble(Json::UInt64 value) { + return static_cast(Int64(value / 2)) * 2.0 + Int64(value & 1); +} + +template static inline double integerToDouble(T value) { + return static_cast(value); +} + +template +static inline bool InRange(double d, T min, U max) { + return d >= integerToDouble(min) && d <= integerToDouble(max); +} +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + +/** Duplicates the specified string value. + * @param value Pointer to the string to duplicate. Must be zero-terminated if + * length is "unknown". + * @param length Length of the value. if equals to unknown, then it will be + * computed using strlen(value). + * @return Pointer on the duplicate instance of string. + */ +static inline char* duplicateStringValue(const char* value, + size_t length) { + // Avoid an integer overflow in the call to malloc below by limiting length + // to a sane value. + if (length >= (size_t)Value::maxInt) + length = Value::maxInt - 1; + + char* newString = static_cast(malloc(length + 1)); + if (newString == NULL) { + throwRuntimeError( + "in Json::Value::duplicateStringValue(): " + "Failed to allocate string value buffer"); + } + memcpy(newString, value, length); + newString[length] = 0; + return newString; +} + +/* Record the length as a prefix. + */ +static inline char* duplicateAndPrefixStringValue( + const char* value, + unsigned int length) +{ + // Avoid an integer overflow in the call to malloc below by limiting length + // to a sane value. + JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U, + "in Json::Value::duplicateAndPrefixStringValue(): " + "length too big for prefixing"); + unsigned actualLength = length + static_cast(sizeof(unsigned)) + 1U; + char* newString = static_cast(malloc(actualLength)); + if (newString == 0) { + throwRuntimeError( + "in Json::Value::duplicateAndPrefixStringValue(): " + "Failed to allocate string value buffer"); + } + *reinterpret_cast(newString) = length; + memcpy(newString + sizeof(unsigned), value, length); + newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later + return newString; +} +inline static void decodePrefixedString( + bool isPrefixed, char const* prefixed, + unsigned* length, char const** value) +{ + if (!isPrefixed) { + *length = static_cast(strlen(prefixed)); + *value = prefixed; + } else { + *length = *reinterpret_cast(prefixed); + *value = prefixed + sizeof(unsigned); + } +} +/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue(). + */ +static inline void releaseStringValue(char* value) { free(value); } + +} // namespace Json + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ValueInternals... +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +#if !defined(JSON_IS_AMALGAMATION) + +#include "json_valueiterator.inl" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +Exception::Exception(std::string const& msg) + : msg_(msg) +{} +Exception::~Exception() throw() +{} +char const* Exception::what() const throw() +{ + return msg_.c_str(); +} +RuntimeError::RuntimeError(std::string const& msg) + : Exception(msg) +{} +LogicError::LogicError(std::string const& msg) + : Exception(msg) +{} +JSONCPP_NORETURN void throwRuntimeError(std::string const& msg) +{ + throw RuntimeError(msg); +} +JSONCPP_NORETURN void throwLogicError(std::string const& msg) +{ + throw LogicError(msg); +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CommentInfo +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +Value::CommentInfo::CommentInfo() : comment_(0) {} + +Value::CommentInfo::~CommentInfo() { + if (comment_) + releaseStringValue(comment_); +} + +void Value::CommentInfo::setComment(const char* text, size_t len) { + if (comment_) { + releaseStringValue(comment_); + comment_ = 0; + } + JSON_ASSERT(text != 0); + JSON_ASSERT_MESSAGE( + text[0] == '\0' || text[0] == '/', + "in Json::Value::setComment(): Comments must start with /"); + // It seems that /**/ style comments are acceptable as well. + comment_ = duplicateStringValue(text, len); +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CZString +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +// Notes: policy_ indicates if the string was allocated when +// a string is stored. + +Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {} + +Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate) + : cstr_(str) +{ + // allocate != duplicate + storage_.policy_ = allocate & 0x3; + storage_.length_ = ulength & 0x3FFFFFFF; +} + +Value::CZString::CZString(const CZString& other) + : cstr_(other.storage_.policy_ != noDuplication && other.cstr_ != 0 + ? duplicateStringValue(other.cstr_, other.storage_.length_) + : other.cstr_) +{ + storage_.policy_ = (other.cstr_ + ? (static_cast(other.storage_.policy_) == noDuplication + ? noDuplication : duplicate) + : static_cast(other.storage_.policy_)); + storage_.length_ = other.storage_.length_; +} + +Value::CZString::~CZString() { + if (cstr_ && storage_.policy_ == duplicate) + releaseStringValue(const_cast(cstr_)); +} + +void Value::CZString::swap(CZString& other) { + std::swap(cstr_, other.cstr_); + std::swap(index_, other.index_); +} + +Value::CZString& Value::CZString::operator=(CZString other) { + swap(other); + return *this; +} + +bool Value::CZString::operator<(const CZString& other) const { + if (!cstr_) return index_ < other.index_; + //return strcmp(cstr_, other.cstr_) < 0; + // Assume both are strings. + unsigned this_len = this->storage_.length_; + unsigned other_len = other.storage_.length_; + unsigned min_len = std::min(this_len, other_len); + int comp = memcmp(this->cstr_, other.cstr_, min_len); + if (comp < 0) return true; + if (comp > 0) return false; + return (this_len < other_len); +} + +bool Value::CZString::operator==(const CZString& other) const { + if (!cstr_) return index_ == other.index_; + //return strcmp(cstr_, other.cstr_) == 0; + // Assume both are strings. + unsigned this_len = this->storage_.length_; + unsigned other_len = other.storage_.length_; + if (this_len != other_len) return false; + int comp = memcmp(this->cstr_, other.cstr_, this_len); + return comp == 0; +} + +ArrayIndex Value::CZString::index() const { return index_; } + +//const char* Value::CZString::c_str() const { return cstr_; } +const char* Value::CZString::data() const { return cstr_; } +unsigned Value::CZString::length() const { return storage_.length_; } +bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; } + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::Value +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +/*! \internal Default constructor initialization must be equivalent to: + * memset( this, 0, sizeof(Value) ) + * This optimization is used in ValueInternalMap fast allocator. + */ +Value::Value(ValueType vtype) { + initBasic(vtype); + switch (vtype) { + case nullValue: + break; + case intValue: + case uintValue: + value_.int_ = 0; + break; + case realValue: + value_.real_ = 0.0; + break; + case stringValue: + value_.string_ = 0; + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(); + break; + case booleanValue: + value_.bool_ = false; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +Value::Value(Int value) { + initBasic(intValue); + value_.int_ = value; +} + +Value::Value(UInt value) { + initBasic(uintValue); + value_.uint_ = value; +} +#if defined(JSON_HAS_INT64) +Value::Value(Int64 value) { + initBasic(intValue); + value_.int_ = value; +} +Value::Value(UInt64 value) { + initBasic(uintValue); + value_.uint_ = value; +} +#endif // defined(JSON_HAS_INT64) + +Value::Value(double value) { + initBasic(realValue); + value_.real_ = value; +} + +Value::Value(const char* value) { + initBasic(stringValue, true); + value_.string_ = duplicateAndPrefixStringValue(value, static_cast(strlen(value))); +} + +Value::Value(const char* beginValue, const char* endValue) { + initBasic(stringValue, true); + value_.string_ = + duplicateAndPrefixStringValue(beginValue, static_cast(endValue - beginValue)); +} + +Value::Value(const std::string& value) { + initBasic(stringValue, true); + value_.string_ = + duplicateAndPrefixStringValue(value.data(), static_cast(value.length())); +} + +Value::Value(const StaticString& value) { + initBasic(stringValue); + value_.string_ = const_cast(value.c_str()); +} + +#ifdef JSON_USE_CPPTL +Value::Value(const CppTL::ConstString& value) { + initBasic(stringValue, true); + value_.string_ = duplicateAndPrefixStringValue(value, static_cast(value.length())); +} +#endif + +Value::Value(bool value) { + initBasic(booleanValue); + value_.bool_ = value; +} + +Value::Value(Value const& other) + : type_(other.type_), allocated_(false) + , + comments_(0) +{ + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + value_ = other.value_; + break; + case stringValue: + if (other.value_.string_ && other.allocated_) { + unsigned len; + char const* str; + decodePrefixedString(other.allocated_, other.value_.string_, + &len, &str); + value_.string_ = duplicateAndPrefixStringValue(str, len); + allocated_ = true; + } else { + value_.string_ = other.value_.string_; + allocated_ = false; + } + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(*other.value_.map_); + break; + default: + JSON_ASSERT_UNREACHABLE; + } + if (other.comments_) { + comments_ = new CommentInfo[numberOfCommentPlacement]; + for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { + const CommentInfo& otherComment = other.comments_[comment]; + if (otherComment.comment_) + comments_[comment].setComment( + otherComment.comment_, strlen(otherComment.comment_)); + } + } +} + +Value::~Value() { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + break; + case stringValue: + if (allocated_) + releaseStringValue(value_.string_); + break; + case arrayValue: + case objectValue: + delete value_.map_; + break; + default: + JSON_ASSERT_UNREACHABLE; + } + + if (comments_) + delete[] comments_; +} + +Value &Value::operator=(const Value &other) { + Value temp(other); + swap(temp); + return *this; +} + +void Value::swapPayload(Value& other) { + ValueType temp = type_; + type_ = other.type_; + other.type_ = temp; + std::swap(value_, other.value_); + int temp2 = allocated_; + allocated_ = other.allocated_; + other.allocated_ = temp2 & 0x1; +} + +void Value::swap(Value& other) { + swapPayload(other); + std::swap(comments_, other.comments_); +} + +ValueType Value::type() const { return type_; } + +int Value::compare(const Value& other) const { + if (*this < other) + return -1; + if (*this > other) + return 1; + return 0; +} + +bool Value::operator<(const Value& other) const { + int typeDelta = type_ - other.type_; + if (typeDelta) + return typeDelta < 0 ? true : false; + switch (type_) { + case nullValue: + return false; + case intValue: + return value_.int_ < other.value_.int_; + case uintValue: + return value_.uint_ < other.value_.uint_; + case realValue: + return value_.real_ < other.value_.real_; + case booleanValue: + return value_.bool_ < other.value_.bool_; + case stringValue: + { + if ((value_.string_ == 0) || (other.value_.string_ == 0)) { + if (other.value_.string_) return true; + else return false; + } + unsigned this_len; + unsigned other_len; + char const* this_str; + char const* other_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); + unsigned min_len = std::min(this_len, other_len); + int comp = memcmp(this_str, other_str, min_len); + if (comp < 0) return true; + if (comp > 0) return false; + return (this_len < other_len); + } + case arrayValue: + case objectValue: { + int delta = int(value_.map_->size() - other.value_.map_->size()); + if (delta) + return delta < 0; + return (*value_.map_) < (*other.value_.map_); + } + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool Value::operator<=(const Value& other) const { return !(other < *this); } + +bool Value::operator>=(const Value& other) const { return !(*this < other); } + +bool Value::operator>(const Value& other) const { return other < *this; } + +bool Value::operator==(const Value& other) const { + // if ( type_ != other.type_ ) + // GCC 2.95.3 says: + // attempt to take address of bit-field structure member `Json::Value::type_' + // Beats me, but a temp solves the problem. + int temp = other.type_; + if (type_ != temp) + return false; + switch (type_) { + case nullValue: + return true; + case intValue: + return value_.int_ == other.value_.int_; + case uintValue: + return value_.uint_ == other.value_.uint_; + case realValue: + return value_.real_ == other.value_.real_; + case booleanValue: + return value_.bool_ == other.value_.bool_; + case stringValue: + { + if ((value_.string_ == 0) || (other.value_.string_ == 0)) { + return (value_.string_ == other.value_.string_); + } + unsigned this_len; + unsigned other_len; + char const* this_str; + char const* other_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); + if (this_len != other_len) return false; + int comp = memcmp(this_str, other_str, this_len); + return comp == 0; + } + case arrayValue: + case objectValue: + return value_.map_->size() == other.value_.map_->size() && + (*value_.map_) == (*other.value_.map_); + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool Value::operator!=(const Value& other) const { return !(*this == other); } + +const char* Value::asCString() const { + JSON_ASSERT_MESSAGE(type_ == stringValue, + "in Json::Value::asCString(): requires stringValue"); + if (value_.string_ == 0) return 0; + unsigned this_len; + char const* this_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + return this_str; +} + +bool Value::getString(char const** str, char const** cend) const { + if (type_ != stringValue) return false; + if (value_.string_ == 0) return false; + unsigned length; + decodePrefixedString(this->allocated_, this->value_.string_, &length, str); + *cend = *str + length; + return true; +} + +std::string Value::asString() const { + switch (type_) { + case nullValue: + return ""; + case stringValue: + { + if (value_.string_ == 0) return ""; + unsigned this_len; + char const* this_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + return std::string(this_str, this_len); + } + case booleanValue: + return value_.bool_ ? "true" : "false"; + case intValue: + return valueToString(value_.int_); + case uintValue: + return valueToString(value_.uint_); + case realValue: + return valueToString(value_.real_); + default: + JSON_FAIL_MESSAGE("Type is not convertible to string"); + } +} + +#ifdef JSON_USE_CPPTL +CppTL::ConstString Value::asConstString() const { + unsigned len; + char const* str; + decodePrefixedString(allocated_, value_.string_, + &len, &str); + return CppTL::ConstString(str, len); +} +#endif + +Value::Int Value::asInt() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); + return Int(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); + return Int(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), + "double out of Int range"); + return Int(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to Int."); +} + +Value::UInt Value::asUInt() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); + return UInt(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); + return UInt(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), + "double out of UInt range"); + return UInt(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to UInt."); +} + +#if defined(JSON_HAS_INT64) + +Value::Int64 Value::asInt64() const { + switch (type_) { + case intValue: + return Int64(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); + return Int64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), + "double out of Int64 range"); + return Int64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to Int64."); +} + +Value::UInt64 Value::asUInt64() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); + return UInt64(value_.int_); + case uintValue: + return UInt64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), + "double out of UInt64 range"); + return UInt64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); +} +#endif // if defined(JSON_HAS_INT64) + +LargestInt Value::asLargestInt() const { +#if defined(JSON_NO_INT64) + return asInt(); +#else + return asInt64(); +#endif +} + +LargestUInt Value::asLargestUInt() const { +#if defined(JSON_NO_INT64) + return asUInt(); +#else + return asUInt64(); +#endif +} + +double Value::asDouble() const { + switch (type_) { + case intValue: + return static_cast(value_.int_); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast(value_.uint_); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return integerToDouble(value_.uint_); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return value_.real_; + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0 : 0.0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to double."); +} + +float Value::asFloat() const { + switch (type_) { + case intValue: + return static_cast(value_.int_); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast(value_.uint_); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return integerToDouble(value_.uint_); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return static_cast(value_.real_); + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0f : 0.0f; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to float."); +} + +bool Value::asBool() const { + switch (type_) { + case booleanValue: + return value_.bool_; + case nullValue: + return false; + case intValue: + return value_.int_ ? true : false; + case uintValue: + return value_.uint_ ? true : false; + case realValue: + // This is kind of strange. Not recommended. + return (value_.real_ != 0.0) ? true : false; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to bool."); +} + +bool Value::isConvertibleTo(ValueType other) const { + switch (other) { + case nullValue: + return (isNumeric() && asDouble() == 0.0) || + (type_ == booleanValue && value_.bool_ == false) || + (type_ == stringValue && asString() == "") || + (type_ == arrayValue && value_.map_->size() == 0) || + (type_ == objectValue && value_.map_->size() == 0) || + type_ == nullValue; + case intValue: + return isInt() || + (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || + type_ == booleanValue || type_ == nullValue; + case uintValue: + return isUInt() || + (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || + type_ == booleanValue || type_ == nullValue; + case realValue: + return isNumeric() || type_ == booleanValue || type_ == nullValue; + case booleanValue: + return isNumeric() || type_ == booleanValue || type_ == nullValue; + case stringValue: + return isNumeric() || type_ == booleanValue || type_ == stringValue || + type_ == nullValue; + case arrayValue: + return type_ == arrayValue || type_ == nullValue; + case objectValue: + return type_ == objectValue || type_ == nullValue; + } + JSON_ASSERT_UNREACHABLE; + return false; +} + +/// Number of values in array or object +ArrayIndex Value::size() const { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + case stringValue: + return 0; + case arrayValue: // size of the array is highest index + 1 + if (!value_.map_->empty()) { + ObjectValues::const_iterator itLast = value_.map_->end(); + --itLast; + return (*itLast).first.index() + 1; + } + return 0; + case objectValue: + return ArrayIndex(value_.map_->size()); + } + JSON_ASSERT_UNREACHABLE; + return 0; // unreachable; +} + +bool Value::empty() const { + if (isNull() || isArray() || isObject()) + return size() == 0u; + else + return false; +} + +bool Value::operator!() const { return isNull(); } + +void Value::clear() { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || + type_ == objectValue, + "in Json::Value::clear(): requires complex value"); + switch (type_) { + case arrayValue: + case objectValue: + value_.map_->clear(); + break; + default: + break; + } +} + +void Value::resize(ArrayIndex newSize) { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, + "in Json::Value::resize(): requires arrayValue"); + if (type_ == nullValue) + *this = Value(arrayValue); + ArrayIndex oldSize = size(); + if (newSize == 0) + clear(); + else if (newSize > oldSize) + (*this)[newSize - 1]; + else { + for (ArrayIndex index = newSize; index < oldSize; ++index) { + value_.map_->erase(index); + } + assert(size() == newSize); + } +} + +Value& Value::operator[](ArrayIndex index) { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == arrayValue, + "in Json::Value::operator[](ArrayIndex): requires arrayValue"); + if (type_ == nullValue) + *this = Value(arrayValue); + CZString key(index); + ObjectValues::iterator it = value_.map_->lower_bound(key); + if (it != value_.map_->end() && (*it).first == key) + return (*it).second; + + ObjectValues::value_type defaultValue(key, nullRef); + it = value_.map_->insert(it, defaultValue); + return (*it).second; +} + +Value& Value::operator[](int index) { + JSON_ASSERT_MESSAGE( + index >= 0, + "in Json::Value::operator[](int index): index cannot be negative"); + return (*this)[ArrayIndex(index)]; +} + +const Value& Value::operator[](ArrayIndex index) const { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == arrayValue, + "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); + if (type_ == nullValue) + return nullRef; + CZString key(index); + ObjectValues::const_iterator it = value_.map_->find(key); + if (it == value_.map_->end()) + return nullRef; + return (*it).second; +} + +const Value& Value::operator[](int index) const { + JSON_ASSERT_MESSAGE( + index >= 0, + "in Json::Value::operator[](int index) const: index cannot be negative"); + return (*this)[ArrayIndex(index)]; +} + +void Value::initBasic(ValueType vtype, bool allocated) { + type_ = vtype; + allocated_ = allocated; + comments_ = 0; +} + +// Access an object value by name, create a null member if it does not exist. +// @pre Type of '*this' is object or null. +// @param key is null-terminated. +Value& Value::resolveReference(const char* key) { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::resolveReference(): requires objectValue"); + if (type_ == nullValue) + *this = Value(objectValue); + CZString actualKey( + key, static_cast(strlen(key)), CZString::noDuplication); // NOTE! + ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) + return (*it).second; + + ObjectValues::value_type defaultValue(actualKey, nullRef); + it = value_.map_->insert(it, defaultValue); + Value& value = (*it).second; + return value; +} + +// @param key is not null-terminated. +Value& Value::resolveReference(char const* key, char const* cend) +{ + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::resolveReference(key, end): requires objectValue"); + if (type_ == nullValue) + *this = Value(objectValue); + CZString actualKey( + key, static_cast(cend-key), CZString::duplicateOnCopy); + ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) + return (*it).second; + + ObjectValues::value_type defaultValue(actualKey, nullRef); + it = value_.map_->insert(it, defaultValue); + Value& value = (*it).second; + return value; +} + +Value Value::get(ArrayIndex index, const Value& defaultValue) const { + const Value* value = &((*this)[index]); + return value == &nullRef ? defaultValue : *value; +} + +bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } + +Value const* Value::find(char const* key, char const* cend) const +{ + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::find(key, end, found): requires objectValue or nullValue"); + if (type_ == nullValue) return NULL; + CZString actualKey(key, static_cast(cend-key), CZString::noDuplication); + ObjectValues::const_iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) return NULL; + return &(*it).second; +} +const Value& Value::operator[](const char* key) const +{ + Value const* found = find(key, key + strlen(key)); + if (!found) return nullRef; + return *found; +} +Value const& Value::operator[](std::string const& key) const +{ + Value const* found = find(key.data(), key.data() + key.length()); + if (!found) return nullRef; + return *found; +} + +Value& Value::operator[](const char* key) { + return resolveReference(key, key + strlen(key)); +} + +Value& Value::operator[](const std::string& key) { + return resolveReference(key.data(), key.data() + key.length()); +} + +Value& Value::operator[](const StaticString& key) { + return resolveReference(key.c_str()); +} + +#ifdef JSON_USE_CPPTL +Value& Value::operator[](const CppTL::ConstString& key) { + return resolveReference(key.c_str(), key.end_c_str()); +} +Value const& Value::operator[](CppTL::ConstString const& key) const +{ + Value const* found = find(key.c_str(), key.end_c_str()); + if (!found) return nullRef; + return *found; +} +#endif + +Value& Value::append(const Value& value) { return (*this)[size()] = value; } + +Value Value::get(char const* key, char const* cend, Value const& defaultValue) const +{ + Value const* found = find(key, cend); + return !found ? defaultValue : *found; +} +Value Value::get(char const* key, Value const& defaultValue) const +{ + return get(key, key + strlen(key), defaultValue); +} +Value Value::get(std::string const& key, Value const& defaultValue) const +{ + return get(key.data(), key.data() + key.length(), defaultValue); +} + + +bool Value::removeMember(const char* key, const char* cend, Value* removed) +{ + if (type_ != objectValue) { + return false; + } + CZString actualKey(key, static_cast(cend-key), CZString::noDuplication); + ObjectValues::iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) + return false; + *removed = it->second; + value_.map_->erase(it); + return true; +} +bool Value::removeMember(const char* key, Value* removed) +{ + return removeMember(key, key + strlen(key), removed); +} +bool Value::removeMember(std::string const& key, Value* removed) +{ + return removeMember(key.data(), key.data() + key.length(), removed); +} +Value Value::removeMember(const char* key) +{ + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, + "in Json::Value::removeMember(): requires objectValue"); + if (type_ == nullValue) + return nullRef; + + Value removed; // null + removeMember(key, key + strlen(key), &removed); + return removed; // still null if removeMember() did nothing +} +Value Value::removeMember(const std::string& key) +{ + return removeMember(key.c_str()); +} + +bool Value::removeIndex(ArrayIndex index, Value* removed) { + if (type_ != arrayValue) { + return false; + } + CZString key(index); + ObjectValues::iterator it = value_.map_->find(key); + if (it == value_.map_->end()) { + return false; + } + *removed = it->second; + ArrayIndex oldSize = size(); + // shift left all items left, into the place of the "removed" + for (ArrayIndex i = index; i < (oldSize - 1); ++i){ + CZString keey(i); + (*value_.map_)[keey] = (*this)[i + 1]; + } + // erase the last one ("leftover") + CZString keyLast(oldSize - 1); + ObjectValues::iterator itLast = value_.map_->find(keyLast); + value_.map_->erase(itLast); + return true; +} + +#ifdef JSON_USE_CPPTL +Value Value::get(const CppTL::ConstString& key, + const Value& defaultValue) const { + return get(key.c_str(), key.end_c_str(), defaultValue); +} +#endif + +bool Value::isMember(char const* key, char const* cend) const +{ + Value const* value = find(key, cend); + return NULL != value; +} +bool Value::isMember(char const* key) const +{ + return isMember(key, key + strlen(key)); +} +bool Value::isMember(std::string const& key) const +{ + return isMember(key.data(), key.data() + key.length()); +} + +#ifdef JSON_USE_CPPTL +bool Value::isMember(const CppTL::ConstString& key) const { + return isMember(key.c_str(), key.end_c_str()); +} +#endif + +Value::Members Value::getMemberNames() const { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::getMemberNames(), value must be objectValue"); + if (type_ == nullValue) + return Value::Members(); + Members members; + members.reserve(value_.map_->size()); + ObjectValues::const_iterator it = value_.map_->begin(); + ObjectValues::const_iterator itEnd = value_.map_->end(); + for (; it != itEnd; ++it) { + members.push_back(std::string((*it).first.data(), + (*it).first.length())); + } + return members; +} +// +//# ifdef JSON_USE_CPPTL +// EnumMemberNames +// Value::enumMemberNames() const +//{ +// if ( type_ == objectValue ) +// { +// return CppTL::Enum::any( CppTL::Enum::transform( +// CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), +// MemberNamesTransform() ) ); +// } +// return EnumMemberNames(); +//} +// +// +// EnumValues +// Value::enumValues() const +//{ +// if ( type_ == objectValue || type_ == arrayValue ) +// return CppTL::Enum::anyValues( *(value_.map_), +// CppTL::Type() ); +// return EnumValues(); +//} +// +//# endif + +static bool IsIntegral(double d) { + double integral_part; + return modf(d, &integral_part) == 0.0; +} + +bool Value::isNull() const { return type_ == nullValue; } + +bool Value::isBool() const { return type_ == booleanValue; } + +bool Value::isInt() const { + switch (type_) { + case intValue: + return value_.int_ >= minInt && value_.int_ <= maxInt; + case uintValue: + return value_.uint_ <= UInt(maxInt); + case realValue: + return value_.real_ >= minInt && value_.real_ <= maxInt && + IsIntegral(value_.real_); + default: + break; + } + return false; +} + +bool Value::isUInt() const { + switch (type_) { + case intValue: + return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); + case uintValue: + return value_.uint_ <= maxUInt; + case realValue: + return value_.real_ >= 0 && value_.real_ <= maxUInt && + IsIntegral(value_.real_); + default: + break; + } + return false; +} + +bool Value::isInt64() const { +#if defined(JSON_HAS_INT64) + switch (type_) { + case intValue: + return true; + case uintValue: + return value_.uint_ <= UInt64(maxInt64); + case realValue: + // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a + // double, so double(maxInt64) will be rounded up to 2^63. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= double(minInt64) && + value_.real_ < double(maxInt64) && IsIntegral(value_.real_); + default: + break; + } +#endif // JSON_HAS_INT64 + return false; +} + +bool Value::isUInt64() const { +#if defined(JSON_HAS_INT64) + switch (type_) { + case intValue: + return value_.int_ >= 0; + case uintValue: + return true; + case realValue: + // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a + // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && + IsIntegral(value_.real_); + default: + break; + } +#endif // JSON_HAS_INT64 + return false; +} + +bool Value::isIntegral() const { +#if defined(JSON_HAS_INT64) + return isInt64() || isUInt64(); +#else + return isInt() || isUInt(); +#endif +} + +bool Value::isDouble() const { return type_ == realValue || isIntegral(); } + +bool Value::isNumeric() const { return isIntegral() || isDouble(); } + +bool Value::isString() const { return type_ == stringValue; } + +bool Value::isArray() const { return type_ == arrayValue; } + +bool Value::isObject() const { return type_ == objectValue; } + +void Value::setComment(const char* comment, size_t len, CommentPlacement placement) { + if (!comments_) + comments_ = new CommentInfo[numberOfCommentPlacement]; + if ((len > 0) && (comment[len-1] == '\n')) { + // Always discard trailing newline, to aid indentation. + len -= 1; + } + comments_[placement].setComment(comment, len); +} + +void Value::setComment(const char* comment, CommentPlacement placement) { + setComment(comment, strlen(comment), placement); +} + +void Value::setComment(const std::string& comment, CommentPlacement placement) { + setComment(comment.c_str(), comment.length(), placement); +} + +bool Value::hasComment(CommentPlacement placement) const { + return comments_ != 0 && comments_[placement].comment_ != 0; +} + +std::string Value::getComment(CommentPlacement placement) const { + if (hasComment(placement)) + return comments_[placement].comment_; + return ""; +} + +std::string Value::toStyledString() const { + StyledWriter writer; + return writer.write(*this); +} + +Value::const_iterator Value::begin() const { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->begin()); + break; + default: + break; + } + return const_iterator(); +} + +Value::const_iterator Value::end() const { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->end()); + break; + default: + break; + } + return const_iterator(); +} + +Value::iterator Value::begin() { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->begin()); + break; + default: + break; + } + return iterator(); +} + +Value::iterator Value::end() { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->end()); + break; + default: + break; + } + return iterator(); +} + +// class PathArgument +// ////////////////////////////////////////////////////////////////// + +PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} + +PathArgument::PathArgument(ArrayIndex index) + : key_(), index_(index), kind_(kindIndex) {} + +PathArgument::PathArgument(const char* key) + : key_(key), index_(), kind_(kindKey) {} + +PathArgument::PathArgument(const std::string& key) + : key_(key.c_str()), index_(), kind_(kindKey) {} + +// class Path +// ////////////////////////////////////////////////////////////////// + +Path::Path(const std::string& path, + const PathArgument& a1, + const PathArgument& a2, + const PathArgument& a3, + const PathArgument& a4, + const PathArgument& a5) { + InArgs in; + in.push_back(&a1); + in.push_back(&a2); + in.push_back(&a3); + in.push_back(&a4); + in.push_back(&a5); + makePath(path, in); +} + +void Path::makePath(const std::string& path, const InArgs& in) { + const char* current = path.c_str(); + const char* end = current + path.length(); + InArgs::const_iterator itInArg = in.begin(); + while (current != end) { + if (*current == '[') { + ++current; + if (*current == '%') + addPathInArg(path, in, itInArg, PathArgument::kindIndex); + else { + ArrayIndex index = 0; + for (; current != end && *current >= '0' && *current <= '9'; ++current) + index = index * 10 + ArrayIndex(*current - '0'); + args_.push_back(index); + } + if (current == end || *current++ != ']') + invalidPath(path, int(current - path.c_str())); + } else if (*current == '%') { + addPathInArg(path, in, itInArg, PathArgument::kindKey); + ++current; + } else if (*current == '.') { + ++current; + } else { + const char* beginName = current; + while (current != end && !strchr("[.", *current)) + ++current; + args_.push_back(std::string(beginName, current)); + } + } +} + +void Path::addPathInArg(const std::string& /*path*/, + const InArgs& in, + InArgs::const_iterator& itInArg, + PathArgument::Kind kind) { + if (itInArg == in.end()) { + // Error: missing argument %d + } else if ((*itInArg)->kind_ != kind) { + // Error: bad argument type + } else { + args_.push_back(**itInArg); + } +} + +void Path::invalidPath(const std::string& /*path*/, int /*location*/) { + // Error: invalid path. +} + +const Value& Path::resolve(const Value& root) const { + const Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || !node->isValidIndex(arg.index_)) { + // Error: unable to resolve path (array value expected at position... + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: unable to resolve path (object value expected at position...) + } + node = &((*node)[arg.key_]); + if (node == &Value::nullRef) { + // Error: unable to resolve path (object has no member named '' at + // position...) + } + } + } + return *node; +} + +Value Path::resolve(const Value& root, const Value& defaultValue) const { + const Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || !node->isValidIndex(arg.index_)) + return defaultValue; + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) + return defaultValue; + node = &((*node)[arg.key_]); + if (node == &Value::nullRef) + return defaultValue; + } + } + return *node; +} + +Value& Path::make(Value& root) const { + Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray()) { + // Error: node is not an array at position ... + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: node is not an object at position... + } + node = &((*node)[arg.key_]); + } + } + return *node; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_value.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_writer.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2011 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include "json_tool.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0 +#include +#define isfinite _finite +#elif defined(__sun) && defined(__SVR4) //Solaris +#include +#define isfinite finite +#else +#include +#define isfinite std::isfinite +#endif + +#if defined(_MSC_VER) +#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above +#define snprintf sprintf_s +#elif _MSC_VER >= 1900 // VC++ 14.0 and above +#define snprintf std::snprintf +#else +#define snprintf _snprintf +#endif +#elif defined(__ANDROID__) +#define snprintf snprintf +#elif __cplusplus >= 201103L +#define snprintf std::snprintf +#endif + +#if defined(__BORLANDC__) +#include +#define isfinite _finite +#define snprintf _snprintf +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +// Disable warning about strdup being deprecated. +#pragma warning(disable : 4996) +#endif + +namespace Json { + +#if __GNUC__ >= 6 +typedef std::scoped_ptr const StreamWriterPtr; +#else +typedef std::auto_ptr StreamWriterPtr; +#endif + +static bool containsControlCharacter(const char* str) { + while (*str) { + if (isControlCharacter(*(str++))) + return true; + } + return false; +} + +static bool containsControlCharacter0(const char* str, unsigned len) { + char const* end = str + len; + while (end != str) { + if (isControlCharacter(*str) || 0==*str) + return true; + ++str; + } + return false; +} + +std::string valueToString(LargestInt value) { + UIntToStringBuffer buffer; + char* current = buffer + sizeof(buffer); + if (value == Value::minLargestInt) { + uintToString(LargestUInt(Value::maxLargestInt) + 1, current); + *--current = '-'; + } else if (value < 0) { + uintToString(LargestUInt(-value), current); + *--current = '-'; + } else { + uintToString(LargestUInt(value), current); + } + assert(current >= buffer); + return current; +} + +std::string valueToString(LargestUInt value) { + UIntToStringBuffer buffer; + char* current = buffer + sizeof(buffer); + uintToString(value, current); + assert(current >= buffer); + return current; +} + +#if defined(JSON_HAS_INT64) + +std::string valueToString(Int value) { + return valueToString(LargestInt(value)); +} + +std::string valueToString(UInt value) { + return valueToString(LargestUInt(value)); +} + +#endif // # if defined(JSON_HAS_INT64) + +std::string valueToString(double value, bool useSpecialFloats, unsigned int precision) { + // Allocate a buffer that is more than large enough to store the 16 digits of + // precision requested below. + char buffer[32]; + int len = -1; + + char formatString[6]; + sprintf(formatString, "%%.%dg", precision); + + // Print into the buffer. We need not request the alternative representation + // that always has a decimal point because JSON doesn't distingish the + // concepts of reals and integers. + if (isfinite(value)) { + len = snprintf(buffer, sizeof(buffer), formatString, value); + } else { + // IEEE standard states that NaN values will not compare to themselves + if (value != value) { + len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null"); + } else if (value < 0) { + len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999"); + } else { + len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999"); + } + // For those, we do not need to call fixNumLoc, but it is fast. + } + assert(len >= 0); + fixNumericLocale(buffer, buffer + len); + return buffer; +} + +std::string valueToString(double value) { return valueToString(value, false, 17); } + +std::string valueToString(bool value) { return value ? "true" : "false"; } + +std::string valueToQuotedString(const char* value) { + if (value == NULL) + return ""; + // Not sure how to handle unicode... + if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && + !containsControlCharacter(value)) + return std::string("\"") + value + "\""; + // We have to walk value and escape any special characters. + // Appending to std::string is not efficient, but this should be rare. + // (Note: forward slashes are *not* rare, but I am not escaping them.) + std::string::size_type maxsize = + strlen(value) * 2 + 3; // allescaped+quotes+NULL + std::string result; + result.reserve(maxsize); // to avoid lots of mallocs + result += "\""; + for (const char* c = value; *c != 0; ++c) { + switch (*c) { + case '\"': + result += "\\\""; + break; + case '\\': + result += "\\\\"; + break; + case '\b': + result += "\\b"; + break; + case '\f': + result += "\\f"; + break; + case '\n': + result += "\\n"; + break; + case '\r': + result += "\\r"; + break; + case '\t': + result += "\\t"; + break; + // case '/': + // Even though \/ is considered a legal escape in JSON, a bare + // slash is also legal, so I see no reason to escape it. + // (I hope I am not misunderstanding something. + // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); + result += oss.str(); + } else { + result += *c; + } + break; + } + } + result += "\""; + return result; +} + +// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp +static char const* strnpbrk(char const* s, char const* accept, size_t n) { + assert((s || !n) && accept); + + char const* const end = s + n; + for (char const* cur = s; cur < end; ++cur) { + int const c = *cur; + for (char const* a = accept; *a; ++a) { + if (*a == c) { + return cur; + } + } + } + return NULL; +} +static std::string valueToQuotedStringN(const char* value, unsigned length) { + if (value == NULL) + return ""; + // Not sure how to handle unicode... + if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL && + !containsControlCharacter0(value, length)) + return std::string("\"") + value + "\""; + // We have to walk value and escape any special characters. + // Appending to std::string is not efficient, but this should be rare. + // (Note: forward slashes are *not* rare, but I am not escaping them.) + std::string::size_type maxsize = + length * 2 + 3; // allescaped+quotes+NULL + std::string result; + result.reserve(maxsize); // to avoid lots of mallocs + result += "\""; + char const* end = value + length; + for (const char* c = value; c != end; ++c) { + switch (*c) { + case '\"': + result += "\\\""; + break; + case '\\': + result += "\\\\"; + break; + case '\b': + result += "\\b"; + break; + case '\f': + result += "\\f"; + break; + case '\n': + result += "\\n"; + break; + case '\r': + result += "\\r"; + break; + case '\t': + result += "\\t"; + break; + // case '/': + // Even though \/ is considered a legal escape in JSON, a bare + // slash is also legal, so I see no reason to escape it. + // (I hope I am not misunderstanding something.) + // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); + result += oss.str(); + } else { + result += *c; + } + break; + } + } + result += "\""; + return result; +} + +// Class Writer +// ////////////////////////////////////////////////////////////////// +Writer::~Writer() {} + +// Class FastWriter +// ////////////////////////////////////////////////////////////////// + +FastWriter::FastWriter() + : yamlCompatiblityEnabled_(false) {} + +void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } + +std::string FastWriter::write(const Value& root) { + document_ = ""; + writeValue(root); + document_ += "\n"; + return document_; +} + +void FastWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + document_ += "null"; + break; + case intValue: + document_ += valueToString(value.asLargestInt()); + break; + case uintValue: + document_ += valueToString(value.asLargestUInt()); + break; + case realValue: + document_ += valueToString(value.asDouble()); + break; + case stringValue: + { + // Is NULL possible for value.string_? + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) document_ += valueToQuotedStringN(str, static_cast(end-str)); + break; + } + case booleanValue: + document_ += valueToString(value.asBool()); + break; + case arrayValue: { + document_ += '['; + int size = value.size(); + for (int index = 0; index < size; ++index) { + if (index > 0) + document_ += ','; + writeValue(value[index]); + } + document_ += ']'; + } break; + case objectValue: { + Value::Members members(value.getMemberNames()); + document_ += '{'; + for (Value::Members::iterator it = members.begin(); it != members.end(); + ++it) { + const std::string& name = *it; + if (it != members.begin()) + document_ += ','; + document_ += valueToQuotedStringN(name.data(), static_cast(name.length())); + document_ += yamlCompatiblityEnabled_ ? ": " : ":"; + writeValue(value[name]); + } + document_ += '}'; + } break; + } +} + +// Class StyledWriter +// ////////////////////////////////////////////////////////////////// + +StyledWriter::StyledWriter() + : rightMargin_(74), indentSize_(3), addChildValues_() {} + +std::string StyledWriter::write(const Value& root) { + document_ = ""; + addChildValues_ = false; + indentString_ = ""; + writeCommentBeforeValue(root); + writeValue(root); + writeCommentAfterValueOnSameLine(root); + document_ += "\n"; + return document_; +} + +void StyledWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: + { + // Is NULL possible for value.string_? + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) pushValue(valueToQuotedStringN(str, static_cast(end-str))); + else pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + const std::string& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + document_ += " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ','; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void StyledWriter::writeArrayValue(const Value& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + const Value& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + writeIndent(); + writeValue(childValue); + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ','; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + document_ += "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + document_ += ", "; + document_ += childValues_[index]; + } + document_ += " ]"; + } + } +} + +bool StyledWriter::isMultineArray(const Value& value) { + int size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (int index = 0; index < size && !isMultiLine; ++index) { + const Value& childValue = value[index]; + isMultiLine = + isMultiLine || ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (int index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += int(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void StyledWriter::pushValue(const std::string& value) { + if (addChildValues_) + childValues_.push_back(value); + else + document_ += value; +} + +void StyledWriter::writeIndent() { + if (!document_.empty()) { + char last = document_[document_.length() - 1]; + if (last == ' ') // already indented + return; + if (last != '\n') // Comments may add new-line + document_ += '\n'; + } + document_ += indentString_; +} + +void StyledWriter::writeWithIndent(const std::string& value) { + writeIndent(); + document_ += value; +} + +void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); } + +void StyledWriter::unindent() { + assert(int(indentString_.size()) >= indentSize_); + indentString_.resize(indentString_.size() - indentSize_); +} + +void StyledWriter::writeCommentBeforeValue(const Value& root) { + if (!root.hasComment(commentBefore)) + return; + + document_ += "\n"; + writeIndent(); + const std::string& comment = root.getComment(commentBefore); + std::string::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + document_ += *iter; + if (*iter == '\n' && + (iter != comment.end() && *(iter + 1) == '/')) + writeIndent(); + ++iter; + } + + // Comments are stripped of trailing newlines, so add one here + document_ += "\n"; +} + +void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { + if (root.hasComment(commentAfterOnSameLine)) + document_ += " " + root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + document_ += "\n"; + document_ += root.getComment(commentAfter); + document_ += "\n"; + } +} + +bool StyledWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +// Class StyledStreamWriter +// ////////////////////////////////////////////////////////////////// + +StyledStreamWriter::StyledStreamWriter(std::string indentation) + : document_(NULL), rightMargin_(74), indentation_(indentation), + addChildValues_() {} + +void StyledStreamWriter::write(std::ostream& out, const Value& root) { + document_ = &out; + addChildValues_ = false; + indentString_ = ""; + indented_ = true; + writeCommentBeforeValue(root); + if (!indented_) writeIndent(); + indented_ = true; + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *document_ << "\n"; + document_ = NULL; // Forget the stream, for safety. +} + +void StyledStreamWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: + { + // Is NULL possible for value.string_? + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) pushValue(valueToQuotedStringN(str, static_cast(end-str))); + else pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + const std::string& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + *document_ << " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void StyledStreamWriter::writeArrayValue(const Value& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + const Value& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + if (!indented_) writeIndent(); + indented_ = true; + writeValue(childValue); + indented_ = false; + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + *document_ << "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + *document_ << ", "; + *document_ << childValues_[index]; + } + *document_ << " ]"; + } + } +} + +bool StyledStreamWriter::isMultineArray(const Value& value) { + int size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (int index = 0; index < size && !isMultiLine; ++index) { + const Value& childValue = value[index]; + isMultiLine = + isMultiLine || ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (int index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += int(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void StyledStreamWriter::pushValue(const std::string& value) { + if (addChildValues_) + childValues_.push_back(value); + else + *document_ << value; +} + +void StyledStreamWriter::writeIndent() { + // blep intended this to look at the so-far-written string + // to determine whether we are already indented, but + // with a stream we cannot do that. So we rely on some saved state. + // The caller checks indented_. + *document_ << '\n' << indentString_; +} + +void StyledStreamWriter::writeWithIndent(const std::string& value) { + if (!indented_) writeIndent(); + *document_ << value; + indented_ = false; +} + +void StyledStreamWriter::indent() { indentString_ += indentation_; } + +void StyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); +} + +void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { + if (!root.hasComment(commentBefore)) + return; + + if (!indented_) writeIndent(); + const std::string& comment = root.getComment(commentBefore); + std::string::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + *document_ << *iter; + if (*iter == '\n' && + (iter != comment.end() && *(iter + 1) == '/')) + // writeIndent(); // would include newline + *document_ << indentString_; + ++iter; + } + indented_ = false; +} + +void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { + if (root.hasComment(commentAfterOnSameLine)) + *document_ << ' ' << root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + writeIndent(); + *document_ << root.getComment(commentAfter); + } + indented_ = false; +} + +bool StyledStreamWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +////////////////////////// +// BuiltStyledStreamWriter + +/// Scoped enums are not available until C++11. +struct CommentStyle { + /// Decide whether to write comments. + enum Enum { + None, ///< Drop all comments. + Most, ///< Recover odd behavior of previous versions (not implemented yet). + All ///< Keep all comments. + }; +}; + +struct BuiltStyledStreamWriter : public StreamWriter +{ + BuiltStyledStreamWriter( + std::string const& indentation, + CommentStyle::Enum cs, + std::string const& colonSymbol, + std::string const& nullSymbol, + std::string const& endingLineFeedSymbol, + bool useSpecialFloats, + unsigned int precision); + virtual int write(Value const& root, std::ostream* sout); +private: + void writeValue(Value const& value); + void writeArrayValue(Value const& value); + bool isMultineArray(Value const& value); + void pushValue(std::string const& value); + void writeIndent(); + void writeWithIndent(std::string const& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(Value const& root); + void writeCommentAfterValueOnSameLine(Value const& root); + static bool hasCommentForValue(const Value& value); + + typedef std::vector ChildValues; + + ChildValues childValues_; + std::string indentString_; + int rightMargin_; + std::string indentation_; + CommentStyle::Enum cs_; + std::string colonSymbol_; + std::string nullSymbol_; + std::string endingLineFeedSymbol_; + bool addChildValues_ : 1; + bool indented_ : 1; + bool useSpecialFloats_ : 1; + unsigned int precision_; +}; +BuiltStyledStreamWriter::BuiltStyledStreamWriter( + std::string const& indentation, + CommentStyle::Enum cs, + std::string const& colonSymbol, + std::string const& nullSymbol, + std::string const& endingLineFeedSymbol, + bool useSpecialFloats, + unsigned int precision) + : rightMargin_(74) + , indentation_(indentation) + , cs_(cs) + , colonSymbol_(colonSymbol) + , nullSymbol_(nullSymbol) + , endingLineFeedSymbol_(endingLineFeedSymbol) + , addChildValues_(false) + , indented_(false) + , useSpecialFloats_(useSpecialFloats) + , precision_(precision) +{ +} +int BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout) +{ + sout_ = sout; + addChildValues_ = false; + indented_ = true; + indentString_ = ""; + writeCommentBeforeValue(root); + if (!indented_) writeIndent(); + indented_ = true; + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *sout_ << endingLineFeedSymbol_; + sout_ = NULL; + return 0; +} +void BuiltStyledStreamWriter::writeValue(Value const& value) { + switch (value.type()) { + case nullValue: + pushValue(nullSymbol_); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_)); + break; + case stringValue: + { + // Is NULL is possible for value.string_? + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) pushValue(valueToQuotedStringN(str, static_cast(end-str))); + else pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + std::string const& name = *it; + Value const& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedStringN(name.data(), static_cast(name.length()))); + *sout_ << colonSymbol_; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *sout_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value); + if (isMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + Value const& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + if (!indented_) writeIndent(); + indented_ = true; + writeValue(childValue); + indented_ = false; + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *sout_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + *sout_ << "["; + if (!indentation_.empty()) *sout_ << " "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + *sout_ << ", "; + *sout_ << childValues_[index]; + } + if (!indentation_.empty()) *sout_ << " "; + *sout_ << "]"; + } + } +} + +bool BuiltStyledStreamWriter::isMultineArray(Value const& value) { + int size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (int index = 0; index < size && !isMultiLine; ++index) { + Value const& childValue = value[index]; + isMultiLine = + isMultiLine || ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (int index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += int(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void BuiltStyledStreamWriter::pushValue(std::string const& value) { + if (addChildValues_) + childValues_.push_back(value); + else + *sout_ << value; +} + +void BuiltStyledStreamWriter::writeIndent() { + // blep intended this to look at the so-far-written string + // to determine whether we are already indented, but + // with a stream we cannot do that. So we rely on some saved state. + // The caller checks indented_. + + if (!indentation_.empty()) { + // In this case, drop newlines too. + *sout_ << '\n' << indentString_; + } +} + +void BuiltStyledStreamWriter::writeWithIndent(std::string const& value) { + if (!indented_) writeIndent(); + *sout_ << value; + indented_ = false; +} + +void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; } + +void BuiltStyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); +} + +void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { + if (cs_ == CommentStyle::None) return; + if (!root.hasComment(commentBefore)) + return; + + if (!indented_) writeIndent(); + const std::string& comment = root.getComment(commentBefore); + std::string::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + *sout_ << *iter; + if (*iter == '\n' && + (iter != comment.end() && *(iter + 1) == '/')) + // writeIndent(); // would write extra newline + *sout_ << indentString_; + ++iter; + } + indented_ = false; +} + +void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) { + if (cs_ == CommentStyle::None) return; + if (root.hasComment(commentAfterOnSameLine)) + *sout_ << " " + root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + writeIndent(); + *sout_ << root.getComment(commentAfter); + } +} + +// static +bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +/////////////// +// StreamWriter + +StreamWriter::StreamWriter() + : sout_(NULL) +{ +} +StreamWriter::~StreamWriter() +{ +} +StreamWriter::Factory::~Factory() +{} +StreamWriterBuilder::StreamWriterBuilder() +{ + setDefaults(&settings_); +} +StreamWriterBuilder::~StreamWriterBuilder() +{} +StreamWriter* StreamWriterBuilder::newStreamWriter() const +{ + std::string indentation = settings_["indentation"].asString(); + std::string cs_str = settings_["commentStyle"].asString(); + bool eyc = settings_["enableYAMLCompatibility"].asBool(); + bool dnp = settings_["dropNullPlaceholders"].asBool(); + bool usf = settings_["useSpecialFloats"].asBool(); + unsigned int pre = settings_["precision"].asUInt(); + CommentStyle::Enum cs = CommentStyle::All; + if (cs_str == "All") { + cs = CommentStyle::All; + } else if (cs_str == "None") { + cs = CommentStyle::None; + } else { + throwRuntimeError("commentStyle must be 'All' or 'None'"); + } + std::string colonSymbol = " : "; + if (eyc) { + colonSymbol = ": "; + } else if (indentation.empty()) { + colonSymbol = ":"; + } + std::string nullSymbol = "null"; + if (dnp) { + nullSymbol = ""; + } + if (pre > 17) pre = 17; + std::string endingLineFeedSymbol = ""; + return new BuiltStyledStreamWriter( + indentation, cs, + colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre); +} +static void getValidWriterKeys(std::set* valid_keys) +{ + valid_keys->clear(); + valid_keys->insert("indentation"); + valid_keys->insert("commentStyle"); + valid_keys->insert("enableYAMLCompatibility"); + valid_keys->insert("dropNullPlaceholders"); + valid_keys->insert("useSpecialFloats"); + valid_keys->insert("precision"); +} +bool StreamWriterBuilder::validate(Json::Value* invalid) const +{ + Json::Value my_invalid; + if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL + Json::Value& inv = *invalid; + std::set valid_keys; + getValidWriterKeys(&valid_keys); + Value::Members keys = settings_.getMemberNames(); + size_t n = keys.size(); + for (size_t i = 0; i < n; ++i) { + std::string const& key = keys[i]; + if (valid_keys.find(key) == valid_keys.end()) { + inv[key] = settings_[key]; + } + } + return 0u == inv.size(); +} +Value& StreamWriterBuilder::operator[](std::string key) +{ + return settings_[key]; +} +// static +void StreamWriterBuilder::setDefaults(Json::Value* settings) +{ + //! [StreamWriterBuilderDefaults] + (*settings)["commentStyle"] = "All"; + (*settings)["indentation"] = "\t"; + (*settings)["enableYAMLCompatibility"] = false; + (*settings)["dropNullPlaceholders"] = false; + (*settings)["useSpecialFloats"] = false; + (*settings)["precision"] = 17; + //! [StreamWriterBuilderDefaults] +} + +std::string writeString(StreamWriter::Factory const& builder, Value const& root) { + std::ostringstream sout; + StreamWriterPtr const writer(builder.newStreamWriter()); + writer->write(root, &sout); + return sout.str(); +} + +std::ostream& operator<<(std::ostream& sout, Value const& root) { + StreamWriterBuilder builder; + StreamWriterPtr const writer(builder.newStreamWriter()); + writer->write(root, &sout); + return sout; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_writer.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + diff --git a/ofdEditor/model/Command/SetTextBlodCmd.h b/ofdEditor/model/Command/SetTextBlodCmd.h index 89f76b6..d53e31c 100644 --- a/ofdEditor/model/Command/SetTextBlodCmd.h +++ b/ofdEditor/model/Command/SetTextBlodCmd.h @@ -10,7 +10,8 @@ class DocTextBlock; class DocPage; class DocLayer; -class SetTextBlodCmd:public QUndoCommand +class SetTextBlodCmd: + public QUndoCommand { public: SetTextBlodCmd(DocTextBlock *docTextBlock,QTextCursor &cursor,QUndoCommand *parent=0); diff --git a/ofdEditor/model/Core/GlobalSetting.cpp b/ofdEditor/model/Core/GlobalSetting.cpp new file mode 100644 index 0000000..8a9f496 --- /dev/null +++ b/ofdEditor/model/Core/GlobalSetting.cpp @@ -0,0 +1,504 @@ +#include "GlobalSetting.h" + +#include +#include +#include +#include + +#include "json/json.h" +#include "json/json-forwards.h" +#include "jsoncpp.cpp" + +using std::string; +using Json::Reader; +using Json::Value; + +// 初始化静态成员变量 +GlobalSetting* GlobalSetting::m_instance = NULL; + +GlobalSetting::GlobalSetting(QObject *parent) + : QObject(parent) +{ + this->settingChanged = false; + this->filepath = "config.json"; + loadGlobalSetting(this->filepath); + +} + +/// +/// \brief GlobalSetting::loadGlobalSetting +/// 从给定的文件路径中读取系统的全局参数 +/// \param filePath 完整路径,以'/' 为分隔符 +/// \author chaoqun +/// \date 2017/08/04 +/// +void GlobalSetting::loadGlobalSetting(QString filePath) +{ + QFile qfile; + qfile.setFileName(filePath); // 设置文件路径 + + // 如果文件不存在,或者无法打开,使用默认配置 + if(!qfile.exists()) + { + qDebug() << "This global setting file is not exists," + << " program will use default setting"; + + this->setDefaultSetting(); // 使用默认配置 + this->SaveSetting(); // 保存配置 + return; + } + // 打开文件 + if(!qfile.open(QIODevice::ReadOnly | QIODevice::Text)) + { + qDebug() << "Program could not open this global setting file," + << " we will use default setting"; + + this->setDefaultSetting(); + this->SaveSetting(); // 保存配置 + return; + } + + QTextStream txtInput(&qfile); // 设置文件流 + QString qstr = txtInput.readAll(); // 读取文件的全部内容 + string str = qstr.toStdString(); // 读取出标准字符 + + Reader reader; // 解析器 + Value value; // 值 + + if(reader.parse(str,value)) + { + try + { + // 如果json 解析成功 + Value app = value["App"]; // App相关 + Value font = value["Font"]; // 字体相关 + Value page = value["Page"]; // 页面设置相关 + Value paragraph = value["Paragraph"]; // 段落设置相关 + + // App + string str_creator = app["Creator"].asString(); // 编辑器 + string str_creatorVersion = app["CreatorVersion"].asString(); // 软件版本 + string str_docType = app["DocType"].asString(); // 文档标准 + string str_docVersion = app["DocVersion"].asString(); // 文档标准版本 + string str_viewMode = app["ViewMode"].asString(); // 系统开启时默认的视图 + + this->creator= QString::fromStdString(str_creator); + this->creatorVersion = QString::fromStdString(str_creatorVersion); + this->docType = QString::fromStdString(str_docType); + this->docVersion = QString::fromStdString(str_docVersion); + this->viewMode = QString::fromStdString(str_viewMode); + + // Font + string str_fontFamily = font["FontFamily"].asString(); // 字体类型 + double double_fontSize = font["FontSize"].asDouble(); // 字号 + + this->fontFamily = QString::fromStdString(str_fontFamily); + this->fontSize = double_fontSize; + + // 页面设置相关 + double double_width = page["Width"].asDouble(); // 页面物理宽度 + double double_height = page["Height"].asDouble(); // 页面的物理高度 + double double_workWidth = page["WorkWidth"].asDouble(); // 页面的工作区宽度 + double double_workHeight = page["WorkHeight"].asDouble(); // 页面的工作区高度 + double double_workX = page["WorkX"].asDouble(); // x + double double_workY = page["WorkY"].asDouble(); // y + string str_pageType = page["PageType"].asString(); // 页面类型 + + this->physicalWidth = double_width; + this->physicalHeight = double_height; + this->contentWidth = double_workWidth; + this->contentHeight = double_workHeight; + this->contentX = double_workX; + this->contentY = double_workY; + this->pageType = QString::fromStdString(str_pageType); + + //段落相关 + string str_horizontal = paragraph["Horizontal"].asString(); // 水平对齐模式 + double double_paraIndent = paragraph["ParaIndent"].asDouble(); // 段落默认缩进 + double double_firstIndent = paragraph["FirstIndent"].asDouble(); // 段落首行缩进 + double double_spaceBefore = paragraph["SpaceBefore"].asDouble(); // 段前间距 + double double_spaceAfter = paragraph["SpaceAfter"].asDouble(); // 段后间距 + string str_lineHeight = paragraph["LineHeight"].asString(); // 行高类型 + double double_lineHeightValue = paragraph["LineHeightValue"].asDouble(); // 行高值 + + this->horizontal = QString::fromStdString(str_horizontal); + this->paraIndent = double_paraIndent; + this->firstIndent = double_firstIndent; + this->spaceBefore = double_spaceBefore; + this->spaceAfter = double_spaceAfter; + this->lineHeight = QString::fromStdString(str_lineHeight); + this->lineHeightValue = double_lineHeightValue; + + qDebug() << "The global setting file is explained successfully."; + + } + catch(...) + { + // 如果有抛出异常 + qDebug() << "Program explan this global setting file failed," + << "and program throws an exception," + << "we will use default setting."; + this->setDefaultSetting(); + this->SaveSetting(); // 保存配置 + } + + } + else + { + // 如果json解析失败 + qDebug() << "Program explan this global setting file failed," + << "we will use default setting."; + this->setDefaultSetting(); + this->SaveSetting(); // 保存配置 + } + + qfile.close(); // 关闭文件 +} + +/// +/// \brief GlobalSetting::exportGlobalSetting +/// 将当前系统的全局设置保存到指定文件 +/// \param filePath +/// \author chaoqun +/// \date 2017/08/04 +/// +void GlobalSetting::exportGlobalSetting(QString filePath) +{ + QFile qfile; + qfile.setFileName(filePath); + + if(!qfile.open(QIODevice::ReadWrite | QIODevice::Text)) + { + qDebug() << "Program could not creat the global setting file"; + return; + } + + QTextStream txtOutput(&qfile); // 用来作为输出流 + Json::StyledWriter swriter; // 用来将value转换为 string + + Value root; + Value app; // 应用程序 + Value font; // 字体 + Value page; // 页面 + Value paragraph; // 段落 + + // App + app["Creator"] = this->creator.toStdString(); + app["CreatorVersion"] = this->creatorVersion.toStdString(); + app["DocType"] = this->docType.toStdString(); + app["DocVersion"] = this->docVersion.toStdString(); + app["ViewMode"] = this->viewMode.toStdString(); + + // Font + font["FontFamily"] = this->fontFamily.toStdString(); + font["FontSize"] = this->fontSize; + + // Page + page["Width"] = this->physicalWidth; + page["Height"] = this->physicalHeight; + page["WorkWidth"] = this->contentWidth; + page["WorkHeight"] = this->contentHeight; + page["WorkX"] = this->contentX; + page["WorkY"] = this->contentY; + page["PageType"] = this->pageType.toStdString(); + + // Paragraph + paragraph["Horizontal"] = this->horizontal.toStdString(); + paragraph["ParaIndent"] = this->paraIndent; + paragraph["FirstIndent"] = this->firstIndent; + paragraph["SpaceBefore"] = this->spaceBefore; + paragraph["SpaceAfter"] = this->spaceAfter; + paragraph["LineHeight"] = this->lineHeight.toStdString(); + paragraph["LineHeightValue"] = this->lineHeightValue; + + root["App"] = app; + root["Font"] = font; + root["Page"] = page; + root["Paragraph"] = paragraph; + + txtOutput << QString::fromStdString(root.toStyledString()) <creator = QString::fromStdString("OFDEditor"); + this->creatorVersion = QString::fromStdString("1.0"); + this->docType = QString::fromStdString("OFD"); + this->docVersion = QString::fromStdString("1.0"); + this->viewMode = QString::fromStdString("Edit"); + + // Font + this->fontFamily = tr("Test"); + this->fontSize = 12; + + // Page + this->physicalWidth = 210; + this->physicalHeight = 297; + this->contentWidth = 210; + this->contentHeight = 297; + this->contentX = 0; + this->contentY = 0; + this->pageType = QString::fromStdString("A4"); + + //Paragraph + this->horizontal = QString::fromStdString("AlignLeft"); + this->paraIndent = 0; + this->firstIndent = 0; + this->spaceBefore = 0; + this->spaceAfter = 0; + this->lineHeight = QString::fromStdString("SingleHeight"); + this->lineHeightValue = 0; + +} + +/// +/// \brief GlobalSetting::getInstance +/// 获得唯一的全局设置对象实例 +/// \return +/// \author chaoqun +/// \date 2017/08/03 +GlobalSetting *GlobalSetting::getInstance() +{ + if( m_instance != NULL ) + { + return m_instance; + } + + m_instance = new GlobalSetting(); // 新建实例 + return m_instance; +} + +/// +/// \brief GlobalSetting::DestoryInstance +/// 销毁实例-估计用不上 +/// \author chaoqun +/// \date 2017/08/04 +/// +void GlobalSetting::DestoryInstance() +{ + delete m_instance; + m_instance = NULL; +} + +/// +/// \brief GlobalSetting::SaveSetting +/// 将软件设置的更改保存到文件中去 +/// \author chaoqun +/// \date 2017/08/04 +/// +void GlobalSetting::SaveSetting() +{ + this->exportGlobalSetting(this->filepath); +} + +void GlobalSetting::setCreator(QString creator) +{ + if(this->creator != creator) + { + this->settingChanged = true; + this->creator = creator; + } + +} + +void GlobalSetting::setCreatorVersion(QString creatorVersion) +{ + if(this->creatorVersion != creatorVersion) + { + this->settingChanged = true; + this->creatorVersion = creatorVersion; + } + +} + +void GlobalSetting::setDocType(QString docType) +{ + if(this->docType != docType) + { + this->settingChanged = true; + this->docType = docType; + } +} + +void GlobalSetting::setDocVersion(QString docVersion) +{ + if(this->docVersion != docVersion) + { + this->settingChanged = true; + this->docVersion = docVersion; + } + +} + +void GlobalSetting::setViewMode(QString viewMode) +{ + if(this->viewMode != viewMode) + { + this->settingChanged = true; + this->viewMode = viewMode; + } + +} + +void GlobalSetting::setFontFamily(QString fontFamily) +{ + if(this->fontFamily != fontFamily) + { + this->settingChanged = true; + this->fontFamily = fontFamily; + } + +} + +void GlobalSetting::setFontSize(double fontSize) +{ + if(this->fontSize != fontSize) + { + this->settingChanged = true; + this->fontSize = fontSize; + } + +} + +void GlobalSetting::setPhysicalWidth(double physicalWidth) +{ + if(this->physicalWidth != physicalWidth) + { + this->settingChanged = true; + this->physicalWidth = physicalWidth; + } + +} + +void GlobalSetting::setPhysicalHeight(double physicalHeight) +{ + if(this->physicalHeight != physicalHeight) + { + this->settingChanged = true; + this->physicalHeight = physicalHeight; + } + +} + +void GlobalSetting::setContentWidth(double contentWidth) +{ + if(this->contentWidth != contentWidth) + { + this->settingChanged = true; + this->contentWidth = contentWidth; + } + +} + +void GlobalSetting::setContentHeight(double contentHeight) +{ + if(this->contentX != contentHeight) + { + this->settingChanged = true; + this->contentHeight = contentHeight; + } +} + +void GlobalSetting::setContentX(double contentX) +{ + if(this->contentX != contentX) + { + this->settingChanged = true; + this->contentX = contentX; + } +} + +void GlobalSetting::setContentY(double contentY) +{ + if(this->contentY != contentY) + { + this->settingChanged = true; + this->contentY = contentY; + } +} + +void GlobalSetting::setPageType(QString pageType) +{ + if(this->pageType != pageType) + { + this->settingChanged = true; + this->pageType = pageType; + } +} + +void GlobalSetting::setHorizontal(QString horizontal) +{ + if(this->horizontal != horizontal) + { + this->settingChanged = true; + this->horizontal = horizontal; + } + +} + +void GlobalSetting::setParaIndent(double paraIndent) +{ + if(this->paraIndent != paraIndent) + { + this->settingChanged = true; + this->paraIndent = paraIndent; + } + +} + +void GlobalSetting::setFirstIndent(double firstIndent) +{ + if(this->firstIndent != firstIndent) + { + this->settingChanged = true; + this->firstIndent = firstIndent; + } +} + +void GlobalSetting::setSpaceBefore(double spaceBefore) +{ + if(this->spaceBefore != spaceBefore) + { + this->settingChanged = true; + this->spaceBefore = spaceBefore; + } +} + +void GlobalSetting::setSpaceAfter(double spaceAfter) +{ + if(this->spaceAfter != spaceAfter) + { + this->settingChanged = true; + this->spaceAfter = spaceAfter; + } +} + +void GlobalSetting::setLineHeight(QString lineHeight) +{ + if(this->lineHeight != lineHeight) + { + this->settingChanged = true; + this->lineHeight = lineHeight; + } +} + +void GlobalSetting::setLineHeightValue(double lineHeightValue) +{ + if(this->lineHeightValue != lineHeightValue) + { + this->settingChanged = true; + this->lineHeightValue = lineHeightValue; + } +} + +void GlobalSetting::setfilePath(QString path) +{ + this->filepath = path; +} diff --git a/ofdEditor/model/Core/GlobalSetting.h b/ofdEditor/model/Core/GlobalSetting.h new file mode 100644 index 0000000..019ef7e --- /dev/null +++ b/ofdEditor/model/Core/GlobalSetting.h @@ -0,0 +1,143 @@ +#ifndef GLOBALSETTING_H +#define GLOBALSETTING_H + +#include +#include +#include +#include "model_global.h" + +/// +/// \brief The GlobalSetting class +/// 用来做系统的全局设置,没有设置多线程的锁结构,因此多线程慎用 +/// +class MODELSHARED_EXPORT GlobalSetting + : public QObject +{ + Q_OBJECT +private: + explicit GlobalSetting(QObject *parent = 0); + + static GlobalSetting* m_instance; + + + void loadGlobalSetting(QString filePath);// 从文件中读取设置信息 + + void exportGlobalSetting(QString filePath);// 将设置信息写回文件 + void setDefaultSetting(); // 在代码中纪录默认设置,防止设置文件丢失 + +public: + static GlobalSetting* getInstance(); // 获得单例 + static void DestoryInstance(); // 销毁单例 + + + QString getFilePath(){return this->filepath;} // 返回配置文件的存储路径 + bool isChanged(){return this->settingChanged;} // 设置内容是否发生过改变 + // 获得各种类型的全局变量 + + // 应用程序信息 + QString getCreator(){return this->creator;} + QString getCreatorVersion(){return this->creatorVersion;} + QString getDocType(){return this->docType;} + QString getDocVersion(){return this->docVersion;} + QString getViewMode(){return this->viewMode;} + + // 字体 + QString getFontFamily(){return this->fontFamily;} + double getFontSize(){return this->fontSize;} + + // 纸张样式 + double getPhysicalWidth(){return this->physicalWidth;} + double getPhysicalHeight(){return this->physicalHeight;} + double getContentWidth(){return this->contentWidth;} + double getContentHeight(){return this->contentHeight;} + double getContentX(){return this->contentX;} + double getContentY(){return this->contentY;} + QString getPageType(){return this->pageType;} + + // 段落 + QString getHorizontal(){return this->horizontal;} + double getParaIndent(){return this->paraIndent;} + double getFirstIndent(){return this->firstIndent;} + double getSpaceBefore(){return this->spaceBefore;} + double getSpaceAfter(){return this->spaceAfter;} + QString getLineHeight(){return this->lineHeight;} + double getLineHeightValue(){return this->lineHeightValue;} + +public slots: + void setfilePath(QString path); // 设置文件路径 + void SaveSetting(); // 将设置保存回文件 + + // app + void setCreator(QString creator); + void setCreatorVersion(QString creatorVersion); + void setDocType(QString docType); + void setDocVersion(QString docVersion); + void setViewMode(QString viewMode); + + // font + void setFontFamily(QString fontFamily); + void setFontSize(double fontSize); + + // page + void setPhysicalWidth(double physicalWidth); + void setPhysicalHeight(double physicalHeight); + void setContentWidth(double contentWidth); + void setContentHeight(double contentHeight); + void setContentX(double contentX); + void setContentY(double contentY); + void setPageType(QString pageType); + + // paragraph + void setHorizontal(QString horizontal); + void setParaIndent(double paraIndent); + void setFirstIndent(double firstIndent); + void setSpaceBefore(double spaceBefore); + void setSpaceAfter(double spaceAfter); + void setLineHeight(QString lineHeight); + void setLineHeightValue(double lineHeightValue); + +private: + QString filepath; // 存放设置文件的路径 + QTextCharFormat charFormat; // 存放字体格式 + QTextBlockFormat blockFormat; // 段落格式 + + bool settingChanged; // 全局设置的内容是否发生改变 + + // App 信息 + QString creator; // 应用程序信息 + QString creatorVersion; // 应用程序版本 + QString docType; // 文档标准 + QString docVersion; // 文档标准版本 + QString viewMode; // 首次打开软件的阅读模式 + + // Font + QString fontFamily; // 字体类型 + double fontSize; // 字体大小 + + //Page + double physicalWidth; // 页面物理宽度 + double physicalHeight; // 页面物理高度 + double contentWidth; // 内容宽度 + double contentHeight; // 内容高度 + double contentX; // 内容水平位置 + double contentY; // 内容竖直位置 + QString pageType; // 页面大小类型 + + // Paragraph + QString horizontal; // 水平对齐策略 + double paraIndent; // 段落缩进 + double firstIndent; // 首行缩进 + double spaceBefore; // 段前空白 + double spaceAfter; // 段后空白 + QString lineHeight; // 行高策略 + double lineHeightValue; // 行高值 + + +signals: + +public slots: + +}; + + +#endif // GLOBALSETTING_H diff --git a/ofdEditor/model/Widget/PageDialog.ui b/ofdEditor/model/Widget/PageDialog.ui index 396740a..2d7d15f 100644 --- a/ofdEditor/model/Widget/PageDialog.ui +++ b/ofdEditor/model/Widget/PageDialog.ui @@ -23,7 +23,7 @@ - 1 + 0 diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index 8aa1141..b8dac64 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -51,7 +51,8 @@ SOURCES += model.cpp \ Widget/PageDialog.cpp \ Widget/InsertTableDialog.cpp \ Widget/FindAndReplaceDock.cpp \ - Widget/SelectTemplateDialog.cpp + Widget/SelectTemplateDialog.cpp \ + Core/GlobalSetting.cpp HEADERS += model.h\ model_global.h \ @@ -82,7 +83,8 @@ HEADERS += model.h\ Widget/PageDialog.h \ Widget/FindAndReplaceDock.h \ Widget/InsertTableDialog.h \ - Widget/SelectTemplateDialog.h + Widget/SelectTemplateDialog.h \ + Core/GlobalSetting.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 @@ -92,7 +94,8 @@ OBJECTS_DIR += ./tmp # .obj 文件存放路径 TRANSLATIONS = cn_model.ts INCLUDEPATH += $$PWD/../ofd \ - $$PWD/../model + $$PWD/../model \ + $$PWD/../libs/jsoncpp unix { target.path = /usr/lib diff --git a/ofdEditor/ofd/ofd.pro b/ofdEditor/ofd/ofd.pro index d98011f..d6c7837 100644 --- a/ofdEditor/ofd/ofd.pro +++ b/ofdEditor/ofd/ofd.pro @@ -33,8 +33,7 @@ SOURCES += \ ofd_writer.cpp \ Loaders/ZipTool.cpp \ ofdexceptions.cpp \ - DataTypes/page/CT_PageBlock.cpp - + DataTypes/page/CT_PageBlock.cpp \ HEADERS +=\ mainwindow.h \ @@ -72,7 +71,7 @@ HEADERS +=\ DataTypes/document/CT_Outlines.h \ DataTypes/document/CustomTags.h \ DataTypes/document/Res.h \ - DataTypes/text/CT_Font.h + DataTypes/text/CT_Font.h \ DESTDIR = ../bin # 生成文件在这 @@ -80,7 +79,8 @@ MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 RCC_DIR = ./rcc # .qrc 文件转换后存放路径 OBJECTS_DIR += ./tmp # .obj 文件存放路径 -INCLUDEPATH += $$PWD/../libs/quazip/includes # 引用quazip库 +INCLUDEPATH += $$PWD/../libs/quazip/includes \ # 引用quazip库 + $$PWD/../libs/jsoncpp # $$PWD表示当前pro对应的文件夹路径 FORMS += mainwindow.ui \ diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 2e7b004..12f3e86 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -31,8 +31,9 @@ #include "Widget/FindAndReplaceDock.h" #include "Convert/Doc_OFDConvertor.h" #include "ofd_writer.h" -#include "../model/Widget/SelectTemplateDialog.h" -#include "../model/Tool/UnitTool.h" +#include "Widget/SelectTemplateDialog.h" +#include "Tool/UnitTool.h" +#include "Core/GlobalSetting.h" PassageMainWindow::PassageMainWindow(QWidget *parent) :QMainWindow(parent) @@ -85,6 +86,8 @@ DocPassage *PassageMainWindow::createMdiChild() */ void PassageMainWindow::init() { + GlobalSetting *setting = GlobalSetting::getInstance(); + this->area = new QMdiArea(); this->setCentralWidget(this->area); -- Gitee From 10871bf490c63089caf347180b3a288266affbb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 5 Aug 2017 11:24:16 +0800 Subject: [PATCH 26/83] =?UTF-8?q?=E8=B0=83=E6=95=B4=E9=83=A8=E5=88=86?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Widget/DocInfoDialog.ui | 422 ++-- ofdEditor/model/Widget/FindAndReplaceDock.ui | 330 ++- ofdEditor/model/Widget/FontSettingDialog.ui | 979 ++++----- ofdEditor/model/Widget/InsertTableDialog.ui | 223 +- ofdEditor/model/Widget/PageDialog.ui | 1908 +++++++---------- .../model/Widget/ParagraphFormatDialog.ui | 484 ++--- .../model/Widget/imagepropertiesdialog.ui | 745 +++---- 7 files changed, 2065 insertions(+), 3026 deletions(-) diff --git a/ofdEditor/model/Widget/DocInfoDialog.ui b/ofdEditor/model/Widget/DocInfoDialog.ui index e1f7709..be76efa 100644 --- a/ofdEditor/model/Widget/DocInfoDialog.ui +++ b/ofdEditor/model/Widget/DocInfoDialog.ui @@ -6,240 +6,204 @@ 0 0 - 483 - 641 + 434 + 452 文档信息 - - - - 70 - 590 - 341 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 10 - 20 - 461 - 361 - - - - 说明 - - - - - 21 - 21 - 411 - 301 - - - - - - - 文件: - - - - - - - 文档ID: - - - - - - - 更改 - - - - - - - 标题: - - - - - - - - - - 作者: - - - - - - - - - - 主题: - - - - - - - - - - 摘要: - - - - - - - - - - 关键字: - - - - - - - - - - 文档类型: - - - - - - - - - - 文档封面: - - - - - - - - - - 创建日期: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10 - 420 - 461 - 151 - - - - 高级 - - - - - 20 - 30 - 431 - 111 - - - - - - - 最近修改时间: - - - - - - - - - - - - - - 创建应用程序: - - - - - - - - - - - - - - 应用程序版本: - - - - - - - - - - - - - + + + + + 说明 + + + + + + 文档ID: + + + + + + + + + + + + + + 文件: + + + + + + + 标题: + + + + + + + + + + + + + + 作者: + + + + + + + 主题: + + + + + + + + + + 更改 + + + + + + + + + + + + + 关键字: + + + + + + + + + + + + + 摘要: + + + + + + + 文档类型: + + + + + + + + + + + + + + 创建日期: + + + + + + + + + + + + + 文档封面: + + + + + + + + + + 高级 + + + + + + 最近修改时间: + + + + + + + + + + + + + + 创建应用程序: + + + + + + + + + + + + + + 应用程序版本: + + + + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + diff --git a/ofdEditor/model/Widget/FindAndReplaceDock.ui b/ofdEditor/model/Widget/FindAndReplaceDock.ui index 2861f4d..5b92a79 100644 --- a/ofdEditor/model/Widget/FindAndReplaceDock.ui +++ b/ofdEditor/model/Widget/FindAndReplaceDock.ui @@ -23,207 +23,135 @@ Find/Replace - - - - 57 - 10 - 91 - 20 - - - - - - - 15 - 11 - 41 - 16 - - - - - Arial - 10 - - - - Find: - - - - - - 533 - 12 - 81 - 16 - - - - - Arial - 10 - - - - Replace With: - - - - - - 630 - 10 - 91 - 20 - - - - - - - 160 - 10 - 101 - 21 - - - - - Arial - 10 - - - - Find Previous - - - - - - 270 - 10 - 91 - 21 - - - - - Arial - 10 - - - - Find Next - - - - - - 733 - 9 - 91 - 23 - - - - - Arial - 10 - - - - Replace - - - - - - 839 - 9 - 101 - 23 - - - - - Arial - 10 - - - - Replace All - - - - - - 509 - 0 - 16 - 41 - - - - Qt::Vertical - - - - - - 370 - 13 - 61 - 16 - - - - - Arial - 10 - - - - Found in: - - - - - - 473 - 13 - 41 - 16 - - - - - Arial - 10 - - - - places. - - - - - - 431 - 12 - 31 - 20 - - - - - Arial - 10 - - - + + + + + + Arial + 10 + + + + Find: + + + + + + + + + + + Arial + 10 + + + + Find Previous + + + + + + + + Arial + 10 + + + + Find Next + + + + + + + + Arial + 10 + + + + Found in: + + + + + + + + Arial + 10 + + + + + + + + + Arial + 10 + + + + places. + + + + + + + Qt::Vertical + + + + + + + + Arial + 10 + + + + Replace With: + + + + + + + + + + + Arial + 10 + + + + Replace + + + + + + + + Arial + 10 + + + + Replace All + + + + diff --git a/ofdEditor/model/Widget/FontSettingDialog.ui b/ofdEditor/model/Widget/FontSettingDialog.ui index cfa097e..f94c5fa 100644 --- a/ofdEditor/model/Widget/FontSettingDialog.ui +++ b/ofdEditor/model/Widget/FontSettingDialog.ui @@ -6,8 +6,8 @@ 0 0 - 481 - 606 + 336 + 469 @@ -19,587 +19,410 @@ 字体设置窗口 - - - - 20 - 20 - 451 - 571 - - - - - - - - 200 - 250 - - - - - 480 - 400 - - - - 字体 - - - - - 10 - 30 - 421 - 184 - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - 粗体 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - 字体 - - - Qt::AlignCenter - - - - - - - 字号 - - - Qt::AlignCenter - - - - - - - 下划线 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - 字体效果预览 - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + + + + + 字体 + + + + + + 字体 + + + Qt::AlignCenter + + + + + + + 字号 + + + Qt::AlignCenter + + + + + + + 粗体 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 字体效果预览 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 斜体 + + + + + + + 下划线 + + + + + + + QComboBox::AdjustToContents + + + + 初号 + + + + + 小初 + + + + + 一号 + + + + + 小一 + + + + + 二号 + + + + + 小二 + + + + + 三号 + + + + + 小三 + + + + + 四号 + + + + + 小四 + + + + + 五号 + + + + + 小五 + + + + + 六号 + + + + + 小六 + + + + + 七号 + + + + + 八号 + + + + + 5 + + + + + 5.5 + + + + + 6.5 + + + + + 7.5 + + + + + 8 + + + + + 9 + + + + + 10 + + + + + 10.5 + + + + + 11 + + + + + 12 + + + + + 14 + + + + + 16 + + + + + 18 + + + + + 20 + + + + + 22 + + + + + 24 + + + + + 26 + + + + + 28 + + + + + 36 + + + + + 48 + + + + + 72 + + + + + + + + QComboBox::AdjustToContents + + + + 黑体 + + + + + + + + + 150 + 100 + + + + + 200 + 100 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">文字测试样例</p> <p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Text Demo</p></body></html> - - - - - - - 斜体 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - QComboBox::AdjustToContents - - - - 初号 - - - - - 小初 - - - - - 一号 - - - - - 小一 - - - - - 二号 - - - - - 小二 - - - - - 三号 - - - - - 小三 - - - - - 四号 - - - - - 小四 - - - - - 五号 - - - - - 小五 - - - - - 六号 - - - - - 小六 - - - - - 七号 - - - - - 八号 - - - - - 5 - - - - - 5.5 - - - - - 6.5 - - - - - 7.5 - - - - - 8 - - - - - 9 - - - - - 10 - - - - - 10.5 - - - - - 11 - - - - - 12 - - - - - 14 - - - - - 16 - - - - - 18 - - - - - 20 - - - - - 22 - - - - - 24 - - - - - 26 - - - - - 28 - - - - - 36 - - - - - 48 - - - - - 72 - - - - - - - - QComboBox::AdjustToContents - - - - 黑体 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - 200 - 200 - - - - - 480 - 400 - - - - 高级 - - - - - 10 - 30 - 421 - 151 - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - 字间距 - - - Qt::AlignCenter - - - - - - - true - - - 拉伸字体 - - - Qt::AlignCenter - - - - - - - 字体粗细 - - - Qt::AlignCenter - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - 1000.000000000000000 - - - - - - - - - - 等宽字体 - - - - - - - 1 - - - 4000 - - - - - - - - - - - - 0 - 50 - - - - - 16777215 - 100 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 40 - - - - - - + + + + + + + + + + 高级 + + + + + + 1 + + + 4000 + + + + + + + 等宽字体 + + + + + + + + + + 字体粗细 + + + Qt::AlignCenter + + + + + + + 字间距 + + + Qt::AlignCenter + + + + + + + 1000.000000000000000 + + + + + + + true + + + 拉伸字体 + + + Qt::AlignCenter + + + + + + + + + + + 0 + 50 + + + + + 16777215 + 100 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + diff --git a/ofdEditor/model/Widget/InsertTableDialog.ui b/ofdEditor/model/Widget/InsertTableDialog.ui index cf8a0ad..1a7312e 100644 --- a/ofdEditor/model/Widget/InsertTableDialog.ui +++ b/ofdEditor/model/Widget/InsertTableDialog.ui @@ -6,70 +6,30 @@ 0 0 - 411 - 507 + 268 + 362 插入表格 - - - - 30 - 460 - 341 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 20 - 20 - 361 - 431 - - - - 0 - - - - 表格 - - - - - 20 - 30 - 311 - 351 - + + + + + 0 - - - - - 行数列数 - - - - - 20 - 40 - 261 - 91 - + + + 表格 + + + + + + 行数列数 - + @@ -92,21 +52,11 @@ - - - - - - 总体尺寸 - - - - - 20 - 40 - 271 - 101 - + + + + + 总体尺寸 @@ -145,76 +95,85 @@ - - - - - - - - 高级 - - - - - 10 - 30 - 331 - 151 - - - - 单元格大小 - - - - - 20 - 30 - 271 - 101 - - - - - - - 宽: - - - - - - - - - mm + + + + + 高级 + + + + + + 单元格大小 + + + + + 宽: + + + + + + + + + + mm + + + + + + + 高: + + + + + + + + + + mm + + + + - - - - 高: + + + + Qt::Vertical - - - - - - - - - mm + + + 20 + 40 + - + - - + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + diff --git a/ofdEditor/model/Widget/PageDialog.ui b/ofdEditor/model/Widget/PageDialog.ui index 2d7d15f..641c212 100644 --- a/ofdEditor/model/Widget/PageDialog.ui +++ b/ofdEditor/model/Widget/PageDialog.ui @@ -6,1165 +6,779 @@ 0 0 - 433 - 490 + 454 + 451 页面设置 - - - - 0 - 0 - 441 - 441 - - - - 0 - - - - 当前页面 - - - - - 230 - 50 - 41 - 21 - - - - - 宋体 - 11 - - - - mm - - - - - - 155 - 160 - 62 - 22 - - - - - - - 114 - 299 - 89 - 16 - - - - 所有页 - - - AppliedRange - - - - - - 155 - 200 - 62 - 22 - - - - - - - 15 - 240 - 381 - 20 - - + + + + + 0 + + + + 当前页面 + + + + + + + 宋体 + 11 + + + + + + + + + + + + 宋体 + 12 + + + + 页面设置 + + + + + + + + 宋体 + 11 + + + + 页面尺寸 + + + + + + + + 宋体 + 11 + + + + + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 11 + + + + 选择尺寸 + + + + + + + 设置工作区域 + + + + + + + + A4 + + + + + A3 + + + + + A5 + + + + + Letter + + + + + 16K + + + + + 32K + + + + + Customized + + + + + + + + + 宋体 + 11 + + + + 工作区域尺寸 + + + + + + + + 宋体 + 11 + + + + + + + + + + + + + + 特定页数 + + + AppliedRange + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + Qt::Horizontal + + + + + + + + Agency FB + 11 + + + + 页码 + + + + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + 当前页 + + + AppliedRange + + + + + + + + + + + 宋体 + 11 + + + + 水平 + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + + + + 宋体 + 11 + + + + 应用于 + + + + + + + + 宋体 + 11 + + + + 工作区域位置 + + + + + + + 所有页 + + + AppliedRange + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 11 + + + + + + + + + + + + + + 页面范围 + + + AppliedRange + + + + + + + + Agency FB + 11 + + + + + + + + + + + + Agency FB + 11 + + + + + + + + + + + + + + + + + + Agency FB + 11 + + + + + + + + + + + + 宋体 + 11 + + + + 垂直 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 默认页面 + + + + + + + + + + + + + 宋体 + 11 + + + + 工作区域位置 + + + + + + + + A4 + + + + + A3 + + + + + A5 + + + + + Letter + + + + + 16K + + + + + 32K + + + + + Customized + + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 11 + + + + 垂直 + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + + + + 宋体 + 11 + + + + + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 11 + + + + + + + + + + + + 宋体 + 11 + + + + 页面尺寸 + + + + + + + + 宋体 + 11 + + + + 水平 + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 12 + + + + 默认页面设置 + + + + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + + + + + + + 宋体 + 11 + + + + + + + + + + + + 宋体 + 11 + + + + 选择尺寸 + + + + + + + + 宋体 + 11 + + + + 工作区域尺寸 + + + + + + + + 宋体 + 11 + + + + + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + 设置工作区域 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + - Qt::Horizontal - - - - - - 295 - 160 - 62 - 22 - - - - - - - 96 - 9 - 311 - 20 - - - - Qt::Horizontal - - - - - - 135 - 160 - 21 - 21 - - - - - 宋体 - 11 - - - - - - - - - - 282 - 49 - 21 - 21 - - - - - 宋体 - 11 - - - - - - - - - - 263 - 201 - 31 - 21 - - - - - 宋体 - 11 - - - - 垂直 - - - - - - 15 - 163 - 91 - 21 - - - - - 宋体 - 11 - - - - 工作区域尺寸 - - - - - - 114 - 359 - 89 - 16 - - - - 特定页数 - - - AppliedRange - - - - - - 14 - 269 - 71 - 21 - - - - - 宋体 - 11 - - - - 应用于 - - - - - - 15 - 133 - 101 - 16 - - - - 设置工作区域 - - - - - - 162 - 49 - 62 - 22 - - - - - - - 123 - 201 - 31 - 21 - - - - - 宋体 - 11 - - - - 水平 - - - - - - 223 - 161 - 41 - 21 - - - - - 宋体 - 11 - - - - mm - - - - - - 363 - 161 - 41 - 21 - - - - - 宋体 - 11 - - - - mm - - - - - - 22 - 49 - 71 - 21 - - - - - 宋体 - 11 - - - - 页面尺寸 - - - - - - 223 - 201 - 41 - 21 - - - - - 宋体 - 11 - - - - mm - - - - - - 15 - 203 - 91 - 21 - - - - - 宋体 - 11 - - - - 工作区域位置 - - - - - - 363 - 201 - 41 - 21 - - - - - 宋体 - 11 - - - - mm - - - - - - 295 - 200 - 62 - 22 - - - - - - - 302 - 49 - 62 - 22 - - - - - - - 142 - 49 - 21 - 21 - - - - - 宋体 - 11 - - - - - - - - - - 370 - 50 - 41 - 21 - - - - - 宋体 - 11 - - - - mm - - - - - - 254 - 359 - 131 - 20 - - - - - - - 21 - 8 - 71 - 21 - - - - - 宋体 - 12 - - - - 页面设置 - - - - - - 275 - 160 - 21 - 21 - - - - - 宋体 - 11 - - - - - - - - - - 114 - 269 - 89 - 16 - - - - 当前页 - - - AppliedRange - - - - - - 114 - 329 - 89 - 16 - - - - 页面范围 - - - AppliedRange - - - - - - 244 - 329 - 42 - 22 - - - - - - - 225 - 331 - 21 - 16 - - - - - Agency FB - 11 - - - - - - - - - - 295 - 331 - 21 - 16 - - - - - Agency FB - 11 - - - - - - - - - - 314 - 329 - 42 - 22 - - - - - - - 365 - 330 - 21 - 16 - - - - - Agency FB - 11 - - - - - - - - - - 220 - 360 - 31 - 16 - - - - - Agency FB - 11 - - - - 页码 - - - - - - 21 - 91 - 101 - 21 - - - - - 宋体 - 11 - - - - 选择尺寸 - - - - - - 140 - 90 - 121 - 22 - - - - - A4 - - - - - A3 - - - - - A5 - - - - - Letter - - - - - 16K - - - - - 32K - - - - - Customized - - - - - - - 默认页面 - - - - - 24 - 29 - 101 - 21 - - - - - 宋体 - 12 - - - - 默认页面设置 - - - - - - 128 - 30 - 281 - 20 - - + Qt::Vertical + + + + 20 + 40 + + + + + + Qt::Horizontal - - - - - 162 - 79 - 62 - 22 - - - - - - - 302 - 199 - 62 - 22 - - - - - - - 22 - 79 - 71 - 21 - - - - - 宋体 - 11 - - - - 页面尺寸 - - - - - - 142 - 199 - 21 - 21 - - - - - 宋体 - 11 - - - - - - - - - - 370 - 80 - 41 - 21 - - - - - 宋体 - 11 - - - - mm - - - - - - 22 - 202 - 91 - 21 - - - - - 宋体 - 11 - - - - 工作区域尺寸 - - - - - - 162 - 199 - 62 - 22 - - - - - - - 270 - 240 - 31 - 21 - - - - - 宋体 - 11 - - - - 垂直 - - - - - - 370 - 240 - 41 - 21 - - - - - 宋体 - 11 - + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - mm + + false - - - - 370 - 200 - 41 - 21 - - - - - 宋体 - 11 - - - - mm - - - - - - 230 - 80 - 41 - 21 - - - - - 宋体 - 11 - - - - mm - - - - - - 22 - 172 - 101 - 16 - - - - 设置工作区域 - - - - - - 230 - 200 - 41 - 21 - - - - - 宋体 - 11 - - - - mm - - - - - - 282 - 199 - 21 - 21 - - - - - 宋体 - 11 - - - - - - - - - - 142 - 79 - 21 - 21 - - - - - 宋体 - 11 - - - - - - - - - - 282 - 79 - 21 - 21 - - - - - 宋体 - 11 - - - - - - - - - - 302 - 79 - 62 - 22 - - - - - - - 22 - 242 - 91 - 21 - - - - - 宋体 - 11 - - - - 工作区域位置 - - - - - - 162 - 239 - 62 - 22 - - - - - - - 130 - 240 - 31 - 21 - - - - - 宋体 - 11 - - - - 水平 - - - - - - 302 - 239 - 62 - 22 - - - - - - - 230 - 240 - 41 - 21 - - - - - 宋体 - 11 - - - - mm - - - - - - 22 - 122 - 101 - 21 - - - - - 宋体 - 11 - - - - 选择尺寸 - - - - - - 141 - 121 - 121 - 22 - - - - - A4 - - - - - A3 - - - - - A5 - - - - - Letter - - - - - 16K - - - - - 32K - - - - - Customized - - - - - - - - - 70 - 450 - 341 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - false - - + + diff --git a/ofdEditor/model/Widget/ParagraphFormatDialog.ui b/ofdEditor/model/Widget/ParagraphFormatDialog.ui index a70bc31..0f89b76 100644 --- a/ofdEditor/model/Widget/ParagraphFormatDialog.ui +++ b/ofdEditor/model/Widget/ParagraphFormatDialog.ui @@ -6,8 +6,8 @@ 0 0 - 448 - 511 + 428 + 457 @@ -22,279 +22,239 @@ false - - - - 10 - 30 - 411 - 451 - - - - - - - 对齐方式 - - - - - 10 - 30 - 261 - 91 - - - - - - - 水平 - - + + + + + 对齐方式 + + + + + + 水平 + + + + + + + 0 + + + QComboBox::AdjustToContents + + + + 左对齐 + - - - - 0 - - - QComboBox::AdjustToContents - - - - 左对齐 - - - - - 右对齐 - - - - - 居中 - - - - - 两端对齐 - - - + + + 右对齐 + - - - - 竖直 - - + + + 居中 + - - - - QComboBox::AdjustToContents - - - - 居上 - - - - - 居下 - - - - - 居中 - - - + + + 两端对齐 + - - - - 文字方向 - - + + + + + + 竖直 + + + + + + + QComboBox::AdjustToContents + + + + 居上 + - - - - QComboBox::AdjustToContents - - - - 左到右 - - - - - 右到左 - - - + + + 居下 + - - - - - - - - 缩进 - - - - - 10 - 30 - 261 - 81 - - - - - - - 整体缩进 - - + + + 居中 + - - - - 10000 - - + + + + + + 文字方向 + + + + + + + QComboBox::AdjustToContents + + + + 左到右 + - - - - 首行缩进 - - + + + 右到左 + - - - - 10000.000000000000000 - - + + + + + + + + + 缩进 + + + + + + 整体缩进 + + + + + + + 10000 + + + + + + + 首行缩进 + + + + + + + 10000.000000000000000 + + + + + + + + + + 间距 + + + + + + 段前 + + + + + + + 10000.000000000000000 + + + + + + + 段后 + + + + + + + 10000.000000000000000 + + + + + + + 行距策略 + + + + + + + QComboBox::AdjustToContents + + + + 单倍行距 + - - - - - - - - 间距 - - - - - 10 - 30 - 371 - 91 - - - - - - - 段前 - - + + + 多倍行距 + - - - - 10000.000000000000000 - - + + + 固定值 + - - - - 段后 - - + + + 最小值 + - - - - 10000.000000000000000 - - - - - - - 行距策略 - - - - - - - QComboBox::AdjustToContents - - - - 单倍行距 - - - - - 多倍行距 - - - - - 固定值 - - - - - 最小值 - - - - - - - - - - - - - - - 10000.000000000000000 - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - + + + + + + + + + + + + + 10000.000000000000000 + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.ui b/ofdEditor/model/Widget/imagepropertiesdialog.ui index d73ce0e..b8952ed 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.ui +++ b/ofdEditor/model/Widget/imagepropertiesdialog.ui @@ -6,488 +6,279 @@ 0 0 - 436 - 389 + 352 + 416 图片设置窗口 - - - - 70 - 340 - 341 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 30 - 40 - 54 - 12 - - - - - - - - - - 30 - 20 - 71 - 21 - - - - - 宋体 - 12 - - - - 图片尺寸 - - - - - - 130 - 60 - 71 - 22 - - - - - - - 280 - 60 - 62 - 22 - - - - - - - 100 - 22 - 311 - 16 - - - - Qt::Horizontal - - - - - - 40 - 60 - 41 - 20 - - - - - 宋体 - 12 - - - - 高度 - - - - - - 40 - 100 - 41 - 20 - - - - - 宋体 - 12 - - - - 宽度 - - - - - - 130 - 100 - 71 - 22 - - - - - - - 280 - 100 - 62 - 22 - - - - - - - 210 - 60 - 31 - 20 - - - - - 宋体 - 11 - false - - - - 像素 - - - - - - 210 - 100 - 31 - 20 - - - - - 宋体 - 11 - false - - - - 像素 - - - - - - 350 - 60 - 71 - 20 - - - - - 宋体 - 11 - false - - - - %原尺寸 - - - - - - 350 - 100 - 71 - 16 - - - - - 宋体 - 11 - false - - - - %原尺寸 - - - - - - 290 - 140 - 110 - 20 - - - - - 宋体 - 12 - - - - 锁定纵横比 - - - - - - 40 - 140 - 81 - 20 - - - - - 宋体 - 11 - - - - 原始尺寸: - - - - - - 130 - 140 - 101 - 16 - - - - - Agency FB - 11 - - - - QFrame::WinPanel - - - QFrame::Sunken - - - 122 ,122 - - - Qt::AlignCenter - - - - - - 30 - 180 - 71 - 21 - - - - - 宋体 - 12 - - - - 图片位置 - - - - - - 100 - 183 - 311 - 16 - - - - Qt::Horizontal - - - - - - 40 - 220 - 41 - 20 - - - - - 宋体 - 12 - - - - 水平 - - - - - - 40 - 260 - 41 - 20 - - - - - 宋体 - 12 - - - - 垂直 - - - - - - 130 - 220 - 71 - 22 - - - - - - - 210 - 220 - 31 - 20 - - - - - 宋体 - 11 - false - - - - 像素 - - - - - - 280 - 260 - 62 - 22 - - - - - - - 130 - 260 - 71 - 22 - - - - - - - 210 - 260 - 31 - 20 - - - - - 宋体 - 11 - false - - - - 像素 - - - - - - 350 - 220 - 71 - 20 - - - - - 宋体 - 11 - false - - - - %页面 - - - - - - 350 - 260 - 71 - 16 - - - - - 宋体 - 11 - false - - - - %页面 - - - - - - 280 - 220 - 62 - 22 - - - + + + + + 图片位置 + + + + + + + 宋体 + 12 + + + + 水平 + + + + + + + + + + + 宋体 + 11 + false + + + + 像素 + + + + + + + + + + + 宋体 + 11 + false + + + + %页面 + + + + + + + + 宋体 + 12 + + + + 垂直 + + + + + + + + + + + 宋体 + 11 + false + + + + 像素 + + + + + + + + + + + 宋体 + 11 + false + + + + %页面 + + + + + + + + + + 图片尺寸 + + + + + + + 宋体 + 12 + + + + 高度 + + + + + + + + + + + 宋体 + 11 + false + + + + 像素 + + + + + + + + + + + 宋体 + 11 + false + + + + %原尺寸 + + + + + + + + 宋体 + 12 + + + + 宽度 + + + + + + + + + + + 宋体 + 11 + false + + + + 像素 + + + + + + + + + + + 宋体 + 11 + false + + + + %原尺寸 + + + + + + + + 宋体 + 11 + + + + 原始尺寸: + + + + + + + + Agency FB + 11 + + + + QFrame::WinPanel + + + QFrame::Sunken + + + 122 ,122 + + + Qt::AlignCenter + + + + + + + + 宋体 + 12 + + + + 锁定纵横比 + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + -- Gitee From 7c40c239ab49262e720571cba6c76e8857a1c7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 5 Aug 2017 19:57:36 +0800 Subject: [PATCH 27/83] =?UTF-8?q?=E4=B8=80=E7=82=B9=E7=82=B9=E7=95=8C?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Core/GlobalSetting.cpp | 12 ++ ofdEditor/model/Core/GlobalSetting.h | 3 + ofdEditor/model/Doc/DocPassage.cpp | 14 +- ofdEditor/model/Doc/DocTextBlock.cpp | 4 + ofdEditor/model/Widget/DocInfoDialog.ui | 129 ++++++++++-------- ofdEditor/model/Widget/FontSettingDialog.ui | 91 ++++++------ ofdEditor/model/Widget/InsertTableDialog.ui | 28 +++- ofdEditor/model/Widget/PageDialog.ui | 78 +++++------ .../model/Widget/ParagraphFormatDialog.ui | 43 +++++- .../model/Widget/imagepropertiesdialog.ui | 28 +++- 10 files changed, 273 insertions(+), 157 deletions(-) diff --git a/ofdEditor/model/Core/GlobalSetting.cpp b/ofdEditor/model/Core/GlobalSetting.cpp index 8a9f496..6cc8ebf 100644 --- a/ofdEditor/model/Core/GlobalSetting.cpp +++ b/ofdEditor/model/Core/GlobalSetting.cpp @@ -87,6 +87,7 @@ void GlobalSetting::loadGlobalSetting(QString filePath) this->docType = QString::fromStdString(str_docType); this->docVersion = QString::fromStdString(str_docVersion); this->viewMode = QString::fromStdString(str_viewMode); + this->undoSize = app["UndoSize"].asInt(); // 读取撤销恢复的最大数量 // Font string str_fontFamily = font["FontFamily"].asString(); // 字体类型 @@ -188,6 +189,7 @@ void GlobalSetting::exportGlobalSetting(QString filePath) app["DocType"] = this->docType.toStdString(); app["DocVersion"] = this->docVersion.toStdString(); app["ViewMode"] = this->viewMode.toStdString(); + app["UndoSize"] = this->undoSize; // Font font["FontFamily"] = this->fontFamily.toStdString(); @@ -233,6 +235,7 @@ void GlobalSetting::setDefaultSetting() this->docType = QString::fromStdString("OFD"); this->docVersion = QString::fromStdString("1.0"); this->viewMode = QString::fromStdString("Edit"); + this->undoSize = 10; // Font this->fontFamily = tr("Test"); @@ -347,6 +350,15 @@ void GlobalSetting::setViewMode(QString viewMode) } +void GlobalSetting::setUndoSize(int undosize) +{ + if(this->undoSize != undosize) + { + this->settingChanged = true; + this->undoSize = undosize; + } +} + void GlobalSetting::setFontFamily(QString fontFamily) { if(this->fontFamily != fontFamily) diff --git a/ofdEditor/model/Core/GlobalSetting.h b/ofdEditor/model/Core/GlobalSetting.h index 019ef7e..b91726d 100644 --- a/ofdEditor/model/Core/GlobalSetting.h +++ b/ofdEditor/model/Core/GlobalSetting.h @@ -40,6 +40,7 @@ public: QString getDocType(){return this->docType;} QString getDocVersion(){return this->docVersion;} QString getViewMode(){return this->viewMode;} + int getUndoSize(){return this->undoSize;} // 字体 QString getFontFamily(){return this->fontFamily;} @@ -73,6 +74,7 @@ public slots: void setDocType(QString docType); void setDocVersion(QString docVersion); void setViewMode(QString viewMode); + void setUndoSize(int undosize); // font void setFontFamily(QString fontFamily); @@ -109,6 +111,7 @@ private: QString docType; // 文档标准 QString docVersion; // 文档标准版本 QString viewMode; // 首次打开软件的阅读模式 + int undoSize; // 撤销恢复栈的最大容量 0 为不限容量 // Font QString fontFamily; // 字体类型 diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index a4e3b2b..8afbe83 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -108,12 +108,11 @@ void DocPassage::addPage(DocPage *page) this->pages.append(page); // 添加到ScrollArea - this->adjustWidgetSize(); // 调整大小 this->layout->addWidget(page,0,Qt::AlignCenter); // 向layout中增加一页,并居中显示 this->layout->update(); // 更新 page->setPassage(this); // 设置页所属的文章 - + this->adjustWidgetSize(); // 调整大小 // qDebug() << "You have added an new page"; @@ -373,6 +372,7 @@ void DocPassage::resetDocId() void DocPassage::resizeEvent(QResizeEvent *event) { this->adjustWidgetSize(); // 调整整体大小 + QScrollArea::resizeEvent(event); // qDebug() << "DocPassage::resizeEvent Runs"; } @@ -445,6 +445,7 @@ void DocPassage::adjustScrollBar(QScrollBar *scrollBar, double factor) // 设置滚动条位置 scrollBar->setValue(int(factor * scrollBar->value() + ((factor -1) * scrollBar->pageStep()/2)) + 1); + scrollBar->update(); } void DocPassage::adjustScrollBarRange() @@ -461,6 +462,9 @@ void DocPassage::adjustScrollBarRange() this->verticalScrollBar()->setRange(0,widgetSize.height() - areaSize.height()); + this->horizontalScrollBar()->update(); + this->verticalScrollBar()->update(); + } @@ -476,11 +480,12 @@ void DocPassage::adjustWidgetSize() int width = 0; int height = 0; - int length = this->pages.size(); + int length = this->pages.size(); // 文章的页数 for(int i = 0; i pages[i]->viewport()->width()) { + // 最宽的一页的宽度 width = this->pages[i]->viewport()->width(); } @@ -496,11 +501,12 @@ void DocPassage::adjustWidgetSize() this->layout->update(); this->update(); this->viewport()->update(); + this->QScrollArea::update(); // 保存计算结果 this->widgetWidth = width; this->widgetHeight = height; - this->QScrollArea::update(); + adjustScrollBarRange(); // 调整进度条长度 diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 3c41138..f5d46cb 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -693,9 +693,13 @@ void DocTextBlock::contextMenuEvent(QContextMenuEvent *event) this->tempZValue = this->getBlock()->getZValue(); emit this->signals_setZValue(2000); +// QPointF global = this->getBlock()->mapToScene(event->globalPos()); // 获得场景坐标 +// this->ContextMenu->setParent(this->getPage()); + // 展示菜单 this->ContextMenu->exec(event->globalPos()); + } /** diff --git a/ofdEditor/model/Widget/DocInfoDialog.ui b/ofdEditor/model/Widget/DocInfoDialog.ui index be76efa..7515fa5 100644 --- a/ofdEditor/model/Widget/DocInfoDialog.ui +++ b/ofdEditor/model/Widget/DocInfoDialog.ui @@ -6,8 +6,8 @@ 0 0 - 434 - 452 + 363 + 472 @@ -20,95 +20,95 @@ 说明 - - - - 文档ID: - - + + - - + + - + 主题: - - + + - 文件: + 作者: - - + + - 标题: + 文档类型: - - + + - + 文件: - - + + - 作者: + 文档ID: - - + + - 主题: + 更改 + + + - - + + - 更改 + - - - - - + + - 关键字: + 摘要: - - - - - + + - 摘要: + 标题: - - + + - 文档类型: + + + + + + + + 关键字: @@ -148,15 +148,15 @@ 高级 - - + + - 最近修改时间: + - - + + @@ -169,30 +169,43 @@ - - + + - + 最近修改时间: - - + + - 应用程序版本: + - - + + - + 应用程序版本: + + + + Qt::Vertical + + + + 20 + 40 + + + + diff --git a/ofdEditor/model/Widget/FontSettingDialog.ui b/ofdEditor/model/Widget/FontSettingDialog.ui index f94c5fa..bb388b8 100644 --- a/ofdEditor/model/Widget/FontSettingDialog.ui +++ b/ofdEditor/model/Widget/FontSettingDialog.ui @@ -53,19 +53,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -73,33 +60,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - 斜体 - - - - - - - 下划线 - - - @@ -292,18 +252,6 @@ - - - - QComboBox::AdjustToContents - - - - 黑体 - - - - @@ -328,6 +276,32 @@ p, li { white-space: pre-wrap; } + + + + QComboBox::AdjustToContents + + + + 黑体 + + + + + + + + 斜体 + + + + + + + 下划线 + + + @@ -400,6 +374,19 @@ p, li { white-space: pre-wrap; } + + + + Qt::Vertical + + + + 20 + 40 + + + + diff --git a/ofdEditor/model/Widget/InsertTableDialog.ui b/ofdEditor/model/Widget/InsertTableDialog.ui index 1a7312e..b10aa2c 100644 --- a/ofdEditor/model/Widget/InsertTableDialog.ui +++ b/ofdEditor/model/Widget/InsertTableDialog.ui @@ -17,7 +17,7 @@ - 0 + 1 @@ -53,6 +53,19 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -96,6 +109,19 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + diff --git a/ofdEditor/model/Widget/PageDialog.ui b/ofdEditor/model/Widget/PageDialog.ui index 641c212..7eb133d 100644 --- a/ofdEditor/model/Widget/PageDialog.ui +++ b/ofdEditor/model/Widget/PageDialog.ui @@ -128,45 +128,6 @@ - - - - - A4 - - - - - A3 - - - - - A5 - - - - - Letter - - - - - 16K - - - - - 32K - - - - - Customized - - - - @@ -443,6 +404,45 @@ + + + + + A4 + + + + + A3 + + + + + A5 + + + + + Letter + + + + + 16K + + + + + 32K + + + + + Customized + + + + diff --git a/ofdEditor/model/Widget/ParagraphFormatDialog.ui b/ofdEditor/model/Widget/ParagraphFormatDialog.ui index 0f89b76..1df94cd 100644 --- a/ofdEditor/model/Widget/ParagraphFormatDialog.ui +++ b/ofdEditor/model/Widget/ParagraphFormatDialog.ui @@ -6,8 +6,8 @@ 0 0 - 428 - 457 + 418 + 505 @@ -122,6 +122,19 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -159,6 +172,19 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -244,6 +270,19 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.ui b/ofdEditor/model/Widget/imagepropertiesdialog.ui index b8952ed..cb62429 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.ui +++ b/ofdEditor/model/Widget/imagepropertiesdialog.ui @@ -7,7 +7,7 @@ 0 0 352 - 416 + 336 @@ -117,6 +117,19 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -268,6 +281,19 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + -- Gitee From 37ee6aaf9616c20ed83579b405bdfabe69a5b849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sun, 6 Aug 2017 10:16:23 +0800 Subject: [PATCH 28/83] =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E5=AD=97=E4=BD=93=E6=A1=86=E7=9A=84=E5=8D=95=E4=BE=8B=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocTextBlock.cpp | 5 +- ofdEditor/model/Widget/FontSettingDialog.cpp | 116 +++++++++++++------ ofdEditor/model/Widget/FontSettingDialog.h | 18 +-- 3 files changed, 97 insertions(+), 42 deletions(-) diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index f5d46cb..f94ed60 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -540,7 +540,10 @@ void DocTextBlock::textFontDialog() void DocTextBlock::customFontDialog() { - FontSettingDialog * font = new FontSettingDialog(this,0); +// FontSettingDialog * font = new FontSettingDialog(this,0); +// font->exec(); + FontSettingDialog* font = FontSettingDialog::getInstance(); // 获取实例 + font->init(this); font->exec(); } diff --git a/ofdEditor/model/Widget/FontSettingDialog.cpp b/ofdEditor/model/Widget/FontSettingDialog.cpp index 5b2f4a5..18f0e10 100644 --- a/ofdEditor/model/Widget/FontSettingDialog.cpp +++ b/ofdEditor/model/Widget/FontSettingDialog.cpp @@ -3,33 +3,61 @@ #include #include +#include #include "Doc/DocTextBlock.h" #include +FontSettingDialog* FontSettingDialog::m_instance = NULL; // 初始化静态变量 + FontSettingDialog::FontSettingDialog(QWidget *parent) : QDialog(parent), ui(new Ui::FontSettingDialog) { ui->setupUi(this); + init(); } -FontSettingDialog::FontSettingDialog(DocTextBlock *textBlock - , QWidget *parent) - :QDialog(parent), - ui(new Ui::FontSettingDialog) +/// +/// \brief FontSettingDialog::getInstance +/// 获得单例的实例 +/// \return +/// +FontSettingDialog *FontSettingDialog::getInstance() { - ui->setupUi(this); - this->textBlock = textBlock; // 记录下负责的DocTextBlock + if( m_instance != NULL) + { + return m_instance; + } + + m_instance = new FontSettingDialog(); // 新建字体设置窗口实例 + return m_instance; +} - this->connect(this,SIGNAL(signal_updatePreview(QTextCharFormat)), - this,SLOT(updatePreview(QTextCharFormat))); // 更新预览的链接 +/// +/// \brief FontSettingDialog::DestoryInstance +/// 用来销毁实例 +void FontSettingDialog::DestoryInstance() +{ + // Font窗口暂不释放,交由Qt机制处理 + m_instance = NULL; +} + +/// +/// \brief FontSettingDialog::init +/// 每次调出单例后可执行 +/// \param textBlock +/// +void FontSettingDialog::init(DocTextBlock *textBlock) +{ + this->textBlock = textBlock; // 纪录下当前操作的对象 + // 当用完后,记得将对象释放 + connect(this,SIGNAL(sendFont(QTextCharFormat&)), + this->textBlock,SLOT(setCharFormatOnSelection(QTextCharFormat&))); // 发送字体 QTextCursor cursor = this->textBlock->textCursor(); // 获得文本的光标 QTextCharFormat charFormat = cursor.charFormat(); // 获得光标的charFormat - this->init(charFormat); // 初始化字体窗口 - - initConnect(); // 初始化信号连接 + this->changeCharFormat(charFormat); // 更改字体窗口的当前字体 } FontSettingDialog::~FontSettingDialog() @@ -84,48 +112,56 @@ int FontSettingDialog::comboIndex(double pointSizeF) /** * @Author Chaoqun - * @brief 初始化链接 + * @brief 初始化链接 - 只需要执行一次 * @param void * @return void * @date 2017/05/26 */ void FontSettingDialog::initConnect() { + // 链接字体 this->connect(this->ui->comboFont, SIGNAL(currentFontChanged(QFont)), - this,SLOT(updateFontFamily(QFont))); // 链接字体 + this,SLOT(updateFontFamily(QFont))); + // 链接字号 this->connect(this->ui->comboFontSize, SIGNAL(currentIndexChanged(int)), this, SLOT(updateFontSizeF(int))); // 链接字体大小 - + // 链接粗体 connect(this->ui->checkBold, SIGNAL(stateChanged(int)), this,SLOT(updateBold(int))); // 链接加粗 + // 链接斜体 connect(this->ui->checkItalic, SIGNAL(stateChanged(int)), this,SLOT(updateItalic(int))); // 链接斜体 + // 链接下划线 connect(this->ui->checkUnderline, SIGNAL(stateChanged(int)), this,SLOT(updateUnderline(int))); // 链接下划线 + // 链接字宽 connect(this->ui->checkFixedWidth, SIGNAL(stateChanged(int)), this,SLOT(updatefixedPitch(int))); // 固定字宽 + // 链接字粗 connect(this->ui->intFontWeight, SIGNAL(valueChanged(int)), this,SLOT(updateWeight(int))); // 字体粗细 + // 字间距 connect(this->ui->doubleFontSpace, SIGNAL(valueChanged(double)), this,SLOT(updateWordSpacing(double))); // 字间距 + // 链接预览窗口 + connect(this, SIGNAL(signal_updatePreview(QTextCharFormat)), + this,SLOT(updatePreview(QTextCharFormat))); + // 当用户点击确认后,执行的函数 connect(this, SIGNAL(accepted()), this, SLOT(accept_slots())); // 窗口接受确认的信号 - connect(this,SIGNAL(sendFont(QTextCharFormat&)), - this->textBlock,SLOT(setCharFormatOnSelection(QTextCharFormat&))); // 发送字体 - } /** @@ -142,21 +178,11 @@ void FontSettingDialog::updatePreview(const QTextCharFormat &charFormat) cursor.setCharFormat(charFormat); // 设置格式 } -/** - * @Author Chaoqun - * @brief 初始化界面 - * @param const QTextCharFormat &charFormat - * @return void - * @date 2017/05/25 - */ -void FontSettingDialog::init(const QTextCharFormat &charFormat) +/// +/// \brief FontSettingDialog::init +/// 改成单例后,部分界面的初始化只需要做一次 +void FontSettingDialog::init() { - this->charFormat = new QTextCharFormat(charFormat); // 存下这个charFormat,后面可以使用 - - // 字体框 - QFont font = charFormat.font(); // 获得字体 - this->ui->comboFont->setCurrentFont(font); // 设置显示 - // 字体大小框 // 点大小与Index的对应关系 this->pointSizeTable.insert(0,42); // 初号 @@ -197,6 +223,25 @@ void FontSettingDialog::init(const QTextCharFormat &charFormat) this->pointSizeTable.insert(35,48); this->pointSizeTable.insert(36,72); + initConnect(); // 做链接 + + +} + +/** + * @Author Chaoqun + * @brief 初始化界面 + * @param const QTextCharFormat &charFormat + * @return void + * @date 2017/05/25 + */ +void FontSettingDialog::changeCharFormat(const QTextCharFormat &charFormat) +{ + this->charFormat = new QTextCharFormat(charFormat); // 存下这个charFormat,后面可以使用 + + // 字体框 + QFont font = charFormat.font(); // 获得字体 + this->ui->comboFont->setCurrentFont(font); // 设置显示 int fontsizeIndex = this->comboIndex(font.pointSizeF()); // 设置对应的字体大小 this->ui->comboFontSize->setCurrentIndex(fontsizeIndex); @@ -243,7 +288,6 @@ void FontSettingDialog::init(const QTextCharFormat &charFormat) this->ui->doubleFontStretch->setVisible(false); this->ui->checkFixedWidth->setVisible(false); - // weight int weight = font.weight(); this->ui->intFontWeight->setValue(weight); @@ -260,7 +304,6 @@ void FontSettingDialog::init(const QTextCharFormat &charFormat) emit signal_updatePreview(*this->charFormat); // 更新预览窗口 - } /** @@ -466,6 +509,11 @@ void FontSettingDialog::updateWeight(int i) * @date 2017/05/26 */ void FontSettingDialog::accept_slots() -{ +{ emit this->sendFont(*this->charFormat); + + // 释放链接 + disconnect(this,SIGNAL(sendFont(QTextCharFormat&)), + this->textBlock,SLOT(setCharFormatOnSelection(QTextCharFormat&))); + } diff --git a/ofdEditor/model/Widget/FontSettingDialog.h b/ofdEditor/model/Widget/FontSettingDialog.h index fb97adb..8fdc5c7 100644 --- a/ofdEditor/model/Widget/FontSettingDialog.h +++ b/ofdEditor/model/Widget/FontSettingDialog.h @@ -22,7 +22,10 @@ class MODELSHARED_EXPORT FontSettingDialog : public QDialog public: - FontSettingDialog(DocTextBlock* textBlock,QWidget *parent = 0); + static FontSettingDialog* getInstance(); // 获得单例--需要是静态的 + static void DestoryInstance(); // 销毁实例 + void init(DocTextBlock* textBlock); // 将窗口初始化 + ~FontSettingDialog(); signals: @@ -31,15 +34,16 @@ signals: private: explicit FontSettingDialog(QWidget *parent = 0); - Ui::FontSettingDialog *ui; + Ui::FontSettingDialog *ui; // 界面元素 + + static FontSettingDialog* m_instance; // 单例 DocTextBlock * textBlock; // 指向待调整文本框 QTextCharFormat* charFormat; // 预览框的格式 QTextCharFormat getQTextCharFormat(); // 获得更新后的字体 - - QMap pointSizeTable; // 字号与Index对应表 + QMap pointSizeTable; // 字号与Index对应表 double pointSizeF(int comboIndex); // 获取字号大小与Index的对应关系 int comboIndex(double pointSizeF); // 获得Index与pointSize的对应关系 void initConnect(); // 初始化各种函数的链接 @@ -48,9 +52,10 @@ private: private slots: void updatePreview(const QTextCharFormat& charFormat); // 设置为预览,用来更新预览文字的效果 - void init(const QTextCharFormat& charFormat); + void init(); // 初始化界面 + void changeCharFormat(const QTextCharFormat& charFormat); // 根据字体更新界面选项 - void updateFontFamily(const QFont &font); // 更新字体 + void updateFontFamily(const QFont &font); // 更新字体类别 void updateFontSizeF(int index); // 更新字体大小 void updateBold(int state); // 加粗 void updateItalic(int state); // 斜体 @@ -62,7 +67,6 @@ private slots: void accept_slots(); // 向DocTextBlock传递成功事件 - }; #endif // FONTSETTINGDIALOG_H -- Gitee From 12c4151de29c26861cc6b372bbc542f59fff74f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sun, 6 Aug 2017 16:23:47 +0800 Subject: [PATCH 29/83] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=AE=B5=E8=90=BD?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E7=AA=97=E5=8F=A3=E5=92=8C=E6=9F=A5=E6=89=BE?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E7=AA=97=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocTextBlock.cpp | 8 +- ofdEditor/model/Widget/FindAndReplaceDock.cpp | 56 ++++++- ofdEditor/model/Widget/FindAndReplaceDock.h | 27 ++-- .../model/Widget/ParagraphFormatDialog.cpp | 151 +++++++----------- .../model/Widget/ParagraphFormatDialog.h | 17 +- .../model/Widget/ParagraphFormatDialog.ui | 57 +------ ofdEditor/model/Widget/SelectTemplateDialog.h | 4 +- ofdEditor/start/ui/PassageMainWindow.cpp | 36 ++++- ofdEditor/start/ui/PassageMainWindow.h | 5 +- 9 files changed, 179 insertions(+), 182 deletions(-) diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index f94ed60..25e74a1 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -461,9 +461,13 @@ void DocTextBlock::textParagraph() QTextCursor cursor = this->textCursor(); QTextBlockFormat blockFormat = cursor.blockFormat(); - ParagraphFormatDialog * para = new ParagraphFormatDialog( - blockFormat,this); +// ParagraphFormatDialog * para = new ParagraphFormatDialog( +// blockFormat,this); +// para->exec(); + ParagraphFormatDialog* para = + ParagraphFormatDialog::getInstance(); // 获得实例 + para->init(blockFormat, this); para->exec(); } /** diff --git a/ofdEditor/model/Widget/FindAndReplaceDock.cpp b/ofdEditor/model/Widget/FindAndReplaceDock.cpp index 3d226da..2219a7b 100644 --- a/ofdEditor/model/Widget/FindAndReplaceDock.cpp +++ b/ofdEditor/model/Widget/FindAndReplaceDock.cpp @@ -10,11 +10,50 @@ #include #include +FindAndReplaceDock* FindAndReplaceDock::m_instance = NULL; // 初始化静态变量 + +/// +/// \brief FindAndReplaceDock::getInstance +/// 获得实例 +/// \return +/// +FindAndReplaceDock *FindAndReplaceDock::getInstance() +{ + if(m_instance != NULL) + { + return m_instance; + } + + m_instance = new FindAndReplaceDock(); + return m_instance; +} + +/// +/// \brief FindAndReplaceDock::DestoryInstance +/// 销毁实例 - 暂时交由QT处理 +void FindAndReplaceDock::DestoryInstance() +{ + m_instance = NULL; +} + +/// +/// \brief FindAndReplaceDock::FindAndReplaceDock +/// 默认构造函数 +/// \param parent +/// FindAndReplaceDock::FindAndReplaceDock(QWidget *parent) : QDockWidget(parent), ui(new Ui::FindAndReplaceDock) { - ui->setupUi(this); + ui->setupUi(this); // 初始化界面 + this->init(); // 初始化 +} + +/// +/// \brief FindAndReplaceDock::init +/// 初始化,主要用于单例的构造函数 +void FindAndReplaceDock::init() +{ //初始化成员 count = 0; ui->CountLineEdit->setText("0"); @@ -22,12 +61,22 @@ FindAndReplaceDock::FindAndReplaceDock(QWidget *parent) : ui->ReplaceButton->setEnabled(false); ui->ReplaceAllButton->setEnabled(false); - //建立信号槽 + + this->initConnect(); // 初始化信号槽链接 +} + +/// +/// \brief FindAndReplaceDock::initConnect +/// 初始化链接 +/// +void FindAndReplaceDock::initConnect() +{ + this->connect(ui->FindLineEdit, SIGNAL(textChanged(QString)), this, SLOT(on_FindLineEdit_textChanged(QString))); - qDebug() << "Finished constructing FindAndReplaceDock"; +// qDebug() << "Finished constructing FindAndReplaceDock"; this->connect(ui->CountLineEdit, SIGNAL(textChanged(QString)), this, @@ -48,6 +97,7 @@ FindAndReplaceDock::FindAndReplaceDock(QWidget *parent) : SIGNAL(clicked(bool)), this, SLOT(replaceAll())); + } diff --git a/ofdEditor/model/Widget/FindAndReplaceDock.h b/ofdEditor/model/Widget/FindAndReplaceDock.h index 61c4fff..1ac31ab 100644 --- a/ofdEditor/model/Widget/FindAndReplaceDock.h +++ b/ofdEditor/model/Widget/FindAndReplaceDock.h @@ -12,35 +12,42 @@ namespace Ui { class FindAndReplaceDock; } -class MODELSHARED_EXPORT FindAndReplaceDock : public QDockWidget +class MODELSHARED_EXPORT FindAndReplaceDock + : public QDockWidget { Q_OBJECT public: - explicit FindAndReplaceDock(QWidget *parent = 0); + static FindAndReplaceDock* getInstance(); // 获得实例 + static void DestoryInstance(); // 销毁实例 + ~FindAndReplaceDock(); void setCurrentPassage(DocPassage * current_passage); private slots: - void on_FindLineEdit_textChanged(const QString &arg1); - - void on_CountLineEdit_textChanged(const QString &arg1); + void on_FindLineEdit_textChanged(const QString &arg1); // 查找的内容变化了 + void on_CountLineEdit_textChanged(const QString &arg1); // 查找到的内容数量变化了 void locatePreviousPlace(); //定位到上一个位置 void locateNextPlace(); //定位到下一个位置 void replaceText(); //切换当前文本 void replaceAll(); //切换所有文本 private: - Ui::FindAndReplaceDock *ui; - QVector blocks_found; - QVector blocks_flag; //记录blocks_find中的元素是否依然有效 - DocPassage * passage; - int count; //找到的文本数量 + explicit FindAndReplaceDock(QWidget *parent = 0); + void init(); // 初始化 + void initConnect(); // 初始化信号槽 void findAllTargetTextBlock(const QString & str); void focusOnFoundPart(); int findNextAvaibleBlockIndex(int cur_index); + Ui::FindAndReplaceDock *ui; + static FindAndReplaceDock* m_instance; // 单例 + + QVector blocks_found; + QVector blocks_flag; //记录blocks_find中的元素是否依然有效 + DocPassage * passage; + int count; //找到的文本数量 int current_block_index; //当前选中的DocTextBlock的下边,-1表示将从头开始 int current_block_pos; //当前选中的DocTextBlock的当前位置,-1表示将从头开始 diff --git a/ofdEditor/model/Widget/ParagraphFormatDialog.cpp b/ofdEditor/model/Widget/ParagraphFormatDialog.cpp index 561eb2e..3368198 100644 --- a/ofdEditor/model/Widget/ParagraphFormatDialog.cpp +++ b/ofdEditor/model/Widget/ParagraphFormatDialog.cpp @@ -3,15 +3,62 @@ #include "Doc/DocTextBlock.h" +ParagraphFormatDialog* ParagraphFormatDialog::m_instance = NULL; // 初始化静态单例 + +/// +/// \brief ParagraphFormatDialog::getInstance +/// 获得实例 +/// \return +/// +ParagraphFormatDialog *ParagraphFormatDialog::getInstance() +{ + if( m_instance != NULL) + { + return m_instance; + } + + m_instance = new ParagraphFormatDialog(); + return m_instance; +} + +void ParagraphFormatDialog::DestoryInstance() +{ + // 考虑到是QT 组件,暂时不去释放内存 + m_instance = NULL; +} + +/// +/// \brief ParagraphFormatDialog::init +/// 每次使用单例时都需要将界面初始化一次s +/// \param blockFormat 需要进行设置的段落格式 +/// \param textBlock 留下文本框引用 +/// +void ParagraphFormatDialog::init( + QTextBlockFormat &blockFormat, + DocTextBlock *textBlock) +{ + + this->init(blockFormat); + this->textBlock = textBlock; // 留下引用,仅用来连接信号槽 + + connect(this, + SIGNAL(finished(QTextBlockFormat&)), + this->textBlock, + SLOT(setTextBlockFormat(QTextBlockFormat&))); // 连接信号和信号槽 + + +} + ParagraphFormatDialog::ParagraphFormatDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ParagraphFormatDialog) { - + ui->setupUi(this); // 设置默认选项 QTextBlockFormat blockformat; this->init(blockformat); + } ParagraphFormatDialog::~ParagraphFormatDialog() @@ -19,23 +66,25 @@ ParagraphFormatDialog::~ParagraphFormatDialog() delete ui; } +/// +/// \brief ParagraphFormatDialog::getQTextBlockFormat +/// 从设置页面中获得设置结果 +/// \return +/// QTextBlockFormat ParagraphFormatDialog::getQTextBlockFormat() { QTextBlockFormat blockFormat; // 用来纪录格式的 Qt::Alignment horizontalFlag; -// Qt::Alignment verticalFlag; // 水平布局 int comboHAlignIndex = ui->comboHAlignment->currentIndex(); switch (comboHAlignIndex) { case 0: -// horizontalFlag = (Qt::AlignLeft | Qt::AlignAbsolute); horizontalFlag = (Qt::AlignLeft); break; case 1: -// horizontalFlag = (Qt::AlignRight | Qt::AlignAbsolute); horizontalFlag = (Qt::AlignRight); break; case 2: @@ -49,43 +98,8 @@ QTextBlockFormat ParagraphFormatDialog::getQTextBlockFormat() } -// // 竖直布局 -// int comboVAlignIndex = ui->comboVAlignment->currentIndex(); -// switch (comboVAlignIndex) { -// case 0: -// verticalFlag = Qt::AlignTop; -// break; -// case 1: -// verticalFlag = Qt::AlignBottom; -// break; -// case 2: -// verticalFlag = Qt::AlignVCenter; -// break; -// default: -// break; -// } - - // 设置布局规则 -// blockFormat.setAlignment(verticalFlag | horizontalFlag); blockFormat.setAlignment(horizontalFlag); -// // 设置文字方向 - // 无法使用,仅对部分语言有效 -// Qt::LayoutDirection textDirection; -// int textDirectionIndex = ui->comboTextDirection->currentIndex(); -// switch (textDirectionIndex) { -// case 0: -// textDirection = Qt::LeftToRight; -// break; -// case 1: -// textDirection = Qt::RightToLeft; -// break; -// default: -// textDirection = Qt::LeftToRight; -// break; -// } -// blockFormat.setLayoutDirection(textDirection); - // 缩进规则 int paraIndent = ui->paraIndent->value(); double firstIndent = ui->doubleFirstIndent->value(); @@ -93,7 +107,6 @@ QTextBlockFormat ParagraphFormatDialog::getQTextBlockFormat() blockFormat.setIndent(paraIndent); blockFormat.setTextIndent(firstIndent); - // 设置段前段后 double spaceBefore = ui->doubleBefor->value(); double spaceAfter = ui->doubleAfter->value(); @@ -128,18 +141,6 @@ QTextBlockFormat ParagraphFormatDialog::getQTextBlockFormat() return blockFormat; } -ParagraphFormatDialog::ParagraphFormatDialog( - const QTextBlockFormat &blockFormat, - DocTextBlock *textBlock, QWidget *parent) - :QDialog(parent), - ui(new Ui::ParagraphFormatDialog) -{ - this->init(blockFormat); - this->textBlock = textBlock; // 留下引用,仅用来连接信号槽 - - connect(this, SIGNAL(finished(QTextBlockFormat&)), - this->textBlock, SLOT(setTextBlockFormat(QTextBlockFormat&))); // 连接信号和信号槽 -} /** * @Author Chaoqun @@ -150,7 +151,6 @@ ParagraphFormatDialog::ParagraphFormatDialog( */ void ParagraphFormatDialog::init(const QTextBlockFormat &blockFormat) { - ui->setupUi(this); // 此信号槽用来将accepted信号接收,然后通过函数发送finished信号 connect(this,SIGNAL(accepted()), @@ -159,10 +159,8 @@ void ParagraphFormatDialog::init(const QTextBlockFormat &blockFormat) // 设置对齐部分 Qt::Alignment flag = blockFormat.alignment(); // 先获取对齐的样式 Qt::Alignment horizontalFlag; -// Qt::Alignment verticalFlag; horizontalFlag = flag & Qt::AlignHorizontal_Mask; -// verticalFlag = flag & Qt::AlignVertical_Mask; // 水平对齐 switch (horizontalFlag) { @@ -183,43 +181,6 @@ void ParagraphFormatDialog::init(const QTextBlockFormat &blockFormat) break; } -// // 竖直对齐 -// switch (verticalFlag) { -// case Qt::AlignTop: -// ui->comboVAlignment->setCurrentIndex(0); -// break; -// case Qt::AlignBottom: -// ui->comboVAlignment->setCurrentIndex(1); -// break; -// case Qt::AlignCenter: -// ui->comboVAlignment->setCurrentIndex(2); -// break; -// default: -// ui->comboVAlignment->setCurrentIndex(-1); -// break; -// } - - // 因竖直对齐的调整并没有效果,这里选择去掉 - this->ui->comboVAlignment->setVisible(false); - this->ui->label_12->setVisible(false); - -// 因为文字方向无法使用,所以将其隐藏掉 -// //文字方向 -// Qt::LayoutDirection textDirection = blockFormat.layoutDirection(); -// switch (textDirection) { -// case Qt::LeftToRight: -// ui->comboTextDirection->setCurrentIndex(0); -// break; -// case Qt::RightToLeft: -// ui->comboTextDirection->setCurrentIndex(1); -// break; -// default: -// ui->comboTextDirection->setCurrentIndex(0); -// break; -// } - this->ui->comboTextDirection->setVisible(false); - this->ui->label_13->setVisible(false); - // 整段缩进 int indent = blockFormat.indent(); ui->paraIndent->setValue(indent); @@ -238,7 +199,6 @@ void ParagraphFormatDialog::init(const QTextBlockFormat &blockFormat) ui->doubleAfter->setValue(bottomMargin); // 行高 -// QTextBlockFormat::LineHeightTypes lineHeightTypes; int lineHeightTypes; lineHeightTypes = blockFormat.lineHeightType(); @@ -277,4 +237,9 @@ void ParagraphFormatDialog::accept_slots() { QTextBlockFormat blockFormat = this->getQTextBlockFormat(); emit this->finished(blockFormat); + + disconnect(this, + SIGNAL(finished(QTextBlockFormat&)), + this->textBlock, + SLOT(setTextBlockFormat(QTextBlockFormat&))); // 断开信号与槽链接 } diff --git a/ofdEditor/model/Widget/ParagraphFormatDialog.h b/ofdEditor/model/Widget/ParagraphFormatDialog.h index c440a7a..1fdd41d 100644 --- a/ofdEditor/model/Widget/ParagraphFormatDialog.h +++ b/ofdEditor/model/Widget/ParagraphFormatDialog.h @@ -4,7 +4,6 @@ #include "model_global.h" #include #include -//#include "Doc/DocTextBlock.h" class DocTextBlock; @@ -12,18 +11,23 @@ namespace Ui { class MODELSHARED_EXPORT ParagraphFormatDialog; } -class MODELSHARED_EXPORT ParagraphFormatDialog : public QDialog +/// +/// \brief The ParagraphFormatDialog class +/// +class MODELSHARED_EXPORT ParagraphFormatDialog + : public QDialog { Q_OBJECT public: + static ParagraphFormatDialog* getInstance(); // 获得实例 + static void DestoryInstance(); // 销毁实例 + void init(QTextBlockFormat &blockFormat, + DocTextBlock* textBlock); // 每次使用时的初始化 + // 构造函数 explicit ParagraphFormatDialog(QWidget *parent = 0); - ParagraphFormatDialog(const QTextBlockFormat& blockFormat, - DocTextBlock * textBlock, - QWidget *parent = 0); - ~ParagraphFormatDialog(); // 自定义信号 @@ -34,6 +38,7 @@ signals: private: Ui::ParagraphFormatDialog *ui; DocTextBlock * textBlock; // 引用,将该效果作用于哪个文字之上 + static ParagraphFormatDialog* m_instance; // 实例 QTextBlockFormat getQTextBlockFormat(); // 从选项中得到QTextBlockFormat diff --git a/ofdEditor/model/Widget/ParagraphFormatDialog.ui b/ofdEditor/model/Widget/ParagraphFormatDialog.ui index 1df94cd..a89f418 100644 --- a/ofdEditor/model/Widget/ParagraphFormatDialog.ui +++ b/ofdEditor/model/Widget/ParagraphFormatDialog.ui @@ -6,8 +6,8 @@ 0 0 - 418 - 505 + 340 + 494 @@ -66,59 +66,6 @@ - - - - 竖直 - - - - - - - QComboBox::AdjustToContents - - - - 居上 - - - - - 居下 - - - - - 居中 - - - - - - - - 文字方向 - - - - - - - QComboBox::AdjustToContents - - - - 左到右 - - - - - 右到左 - - - - diff --git a/ofdEditor/model/Widget/SelectTemplateDialog.h b/ofdEditor/model/Widget/SelectTemplateDialog.h index f6e92e7..f0a0359 100644 --- a/ofdEditor/model/Widget/SelectTemplateDialog.h +++ b/ofdEditor/model/Widget/SelectTemplateDialog.h @@ -12,7 +12,8 @@ namespace Ui { class SelectTemplateDialog; } -class MODELSHARED_EXPORT SelectTemplateDialog : public QDialog +class MODELSHARED_EXPORT SelectTemplateDialog + : public QDialog { Q_OBJECT @@ -31,7 +32,6 @@ private slots: void lastTemplate(); void emitCreateTemplateSignal(); - signals: void createTemplate(int index); }; diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 12f3e86..1eacf6a 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -46,12 +46,19 @@ PassageMainWindow::~PassageMainWindow() } +/// +/// \brief PassageMainWindow::activateFindAndReplaceDock +/// 激活查找替换窗口 +/// void PassageMainWindow::activateFindAndReplaceDock() { if (connector->getActivePassage()) { - find_and_replace_dock->setCurrentPassage(connector->getActivePassage()); - this->find_and_replace_dock->show(); + FindAndReplaceDock* find_and_replace_dock + = FindAndReplaceDock::getInstance(); // 获得单例 + find_and_replace_dock->setCurrentPassage( + connector->getActivePassage()); // 设置当前操作的文章 + find_and_replace_dock->show(); } } @@ -105,17 +112,30 @@ void PassageMainWindow::init() this->setWindowTitle(tr("OFD Editor")); this->setWindowIcon(QIcon(":/icons/source/icons/ofdEditor2.png")); - this->find_and_replace_dock = new FindAndReplaceDock(NULL); - this->addDockWidget(Qt::BottomDockWidgetArea, find_and_replace_dock); - this->find_and_replace_dock->setWindowIcon(QIcon(":/icons/source/icons/Find.png")); - this->find_and_replace_dock->setMaximumHeight(60); - this->find_and_replace_dock->setMinimumHeight(60); - this->find_and_replace_dock->setVisible(false); +// this->find_and_replace_dock = new FindAndReplaceDock(NULL); +// this->addDockWidget(Qt::BottomDockWidgetArea, find_and_replace_dock); +// this->find_and_replace_dock->setWindowIcon(QIcon(":/icons/source/icons/Find.png")); +// this->find_and_replace_dock->setMaximumHeight(60); +// this->find_and_replace_dock->setMinimumHeight(60); +// this->find_and_replace_dock->setVisible(false); + + FindAndReplaceDock* find_and_replace_dock + = FindAndReplaceDock::getInstance(); // 获得单例 + this->addDockWidget( + Qt::BottomDockWidgetArea, + find_and_replace_dock); // 设置容器 + + find_and_replace_dock->setWindowIcon( + QIcon(":/icons/source/icons/Find.png")); // 设置图标 + find_and_replace_dock->setMaximumHeight(60); + find_and_replace_dock->setMinimumHeight(60); + find_and_replace_dock->setVisible(false); this->select_template_dialog = new SelectTemplateDialog(NULL, this); this->select_template_dialog->setFixedSize(select_template_dialog->size()); connect(this->select_template_dialog, SIGNAL(createTemplate(int)), this, SLOT(createTemplatePassage(int))); + } /** diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index ca65ac0..70602f2 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -16,7 +16,6 @@ class DocPassage; class DocTextBlock; class ActionConnector; // 函数功能的中间件 class DocImageBlock; -class FindAndReplaceDock; class SelectTemplateDialog; // 编辑窗口的主界面 @@ -28,8 +27,9 @@ public: explicit PassageMainWindow(QWidget *parent = 0); ~PassageMainWindow(); - void activateFindAndReplaceDock(); + public slots: + void activateFindAndReplaceDock(); // 激活查找替换窗口 DocPassage *createMdiChild(); // 创建一个新文档 DocPassage *activeMdiChild(); // 获取活动的窗口 DocPassage *addDocPassage(DocPassage * passage); @@ -123,7 +123,6 @@ private: DocImageBlock *imageBlock; //图片块 - FindAndReplaceDock * find_and_replace_dock; //查找 & 替换 SelectTemplateDialog * select_template_dialog; //选择模板对话框 private slots: -- Gitee From 028e18b24adb6833f748a4b0d86a0534683fc565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sun, 6 Aug 2017 21:50:14 +0800 Subject: [PATCH 30/83] =?UTF-8?q?pageDialog=20=E4=BB=8D=E7=84=B6=E5=8F=AF?= =?UTF-8?q?=E8=83=BD=E5=AD=98=E5=9C=A8=E7=A9=BA=E6=8C=87=E9=92=88=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=20=E7=B4=AF=E4=BA=86=EF=BC=8C?= =?UTF-8?q?=E6=98=8E=E5=A4=A9=E5=86=8D=E5=BC=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocPage.cpp | 23 + ofdEditor/model/Doc/DocPage.h | 27 +- ofdEditor/model/Doc/DocPassage.cpp | 298 ++-- ofdEditor/model/Doc/DocPassage.h | 55 +- ofdEditor/model/Widget/DocInfoDialog.cpp | 59 +- ofdEditor/model/Widget/DocInfoDialog.h | 34 +- ofdEditor/model/Widget/PageDialog.cpp | 310 +++- ofdEditor/model/Widget/PageDialog.h | 61 +- ofdEditor/model/Widget/PageDialog.ui | 1419 ++++++++--------- ofdEditor/model/model.pro | 4 +- .../start/ActionConnector/ActionConnector.cpp | 5 +- ofdEditor/start/ui/PassageMainWindow.cpp | 23 +- ofdEditor/start/ui/PassageMainWindow.h | 3 - 13 files changed, 1331 insertions(+), 990 deletions(-) diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index 9203f87..9ef4baa 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -280,6 +280,29 @@ void DocPage::setScale(double scale) this->update(); } +/// +/// \brief DocPage::setWorkingArea +/// 设置工作区域 +/// \param isUsingWorkingArea +/// \param contentWidth +/// \param contentHeight +/// \param contentX +/// \param contentY +/// +void DocPage::setWorkingArea( + bool isUsingWorkingArea, + double contentWidth, + double contentHeight, + double contentX, + double contentY) +{ + this->has_working_area = isUsingWorkingArea; + this->working_area_width = contentWidth; + this->working_area_height = contentHeight; + this->working_area_x = contentX; + this->working_area_y = contentY; +} + /** * @Author Chaoqun diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index d4868c8..31ceace 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -28,12 +28,7 @@ class MODELSHARED_EXPORT DocPage { Q_OBJECT public: - //Temporarily put here - bool has_working_area; - double working_area_width; - double working_area_height; - double working_area_x; - double working_area_y; + enum Layer{Body,Foreground,Background}; // 分为三层 @@ -53,11 +48,17 @@ public: DocLayer *getForegroundLayer(); // 获得前景层 DocLayer* getBodyLayer(); // 获得正文层 - DocLayer* getBackgroundLayer(); // 获得背景层 + DocLayer* getBackgroundLayer(); // 获得背景层 //Pan void addImage(); //添加图片 + bool isUsingWorkArea(){return this->has_working_area;} + double getContentWidth(){return this->working_area_width;} + double getContentHeight(){return this->working_area_height;} + double getContentX(){return this->working_area_x;} + double getContentY(){return this->working_area_y;} + public slots: void setSize(double width, double height); // 设置页面大小 void setPassage(DocPassage * passage); // 设置文章 @@ -72,6 +73,12 @@ public slots: void setInsertBlockType(InsertBlockInfo& blockInfo); // 设置下一个要插入的block的信息 void remove(); // 移除本页 void setScale(double scale); // 设置页面的显示大小 + void setWorkingArea( + bool isUsingWorkingArea, + double contentWidth, + double contentHeight, + double contentX, + double contentY); // 设置工作区域 protected: void paintEvent(QPaintEvent *event); @@ -105,6 +112,12 @@ private: BlockFlag newBlockFlag; // 是否画块 DocBlock * activeBlock; // 正在活跃的那个DocBlock + bool has_working_area; + double working_area_width; + double working_area_height; + double working_area_x; + double working_area_y; + signals: // 信号 diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index 8afbe83..2314305 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -3,8 +3,10 @@ #include "DocPage.h" #include "DataTypes/document/CT_DocInfo.h" #include "DataTypes/document/ct_commondata.h" -#include "../Widget/PageDialog.h" +#include "Widget/PageDialog.h" +#include "Core/GlobalSetting.h" #include +#include #include #include #include @@ -13,70 +15,77 @@ #include #include +/// +/// \brief DocPassage::createNewPassage +/// 创建一个新的文章 +/// \return 新的文章 +/// +DocPassage *DocPassage::createNewPassage() +{ + DocPassage* passage = new DocPassage(0); + return passage; +} + +/// +/// \brief DocPassage::createEmptyPassage +/// 创建一个新的文章,空的,用来进行读取已有文章 +/// \return +/// +DocPassage *DocPassage::createEmptyPassage() +{ + DocPassage* passage = new DocPassage(); + return passage; +} + + /** * @Author Chaoqun * @brief 默认构造函数 * @date 2017/04/30 */ DocPassage::DocPassage(QWidget *parent) - :docType("OFD"),version("1.0"),QScrollArea(parent) + :QScrollArea(parent) { - undoStack=new QUndoStack(this); - this->scaleFactor = 1.0; // 缩放100% - this->docInfo = new CT_DocInfo(); // 文档元信息 -// this->commonData = new CT_CommonData(); - this->init(); // 初始化界面 + this->undoStack=new QUndoStack(this); // 用来来存储操作队列 + this->docInfo = new CT_DocInfo(); // 文档元信息 + this->initUI(); // 初始化界面 + this->initDocInfo(); // 初始化文章信息 // this->addPage(new DocPage()); // 添加一个空白页面 setAttribute(Qt::WA_DeleteOnClose); -// qDebug() << "DocPassage Constructor Finished."; + // qDebug() << "DocPassage Constructor Finished."; } -/** - * @Author Chaoqun - * @brief 含参构造函数 - * @date 2017/05/01 - */ -DocPassage::DocPassage(QWidget *parent, - QString version, QString docType, double scaleFactor) - :QScrollArea(parent) +/// +/// \brief DocPassage::DocPassage +/// 空的构造函数,用来创建空的文章 +DocPassage::DocPassage() + :QScrollArea(0) { - undoStack=new QUndoStack(this); - this->version = version; - this->docType = docType; - this->scaleFactor = scaleFactor; + this->undoStack = new QUndoStack(this); // 撤销恢复队列 + this->docInfo = new CT_DocInfo(); // 新建文章信息 + this->initUI(); // 初始化界面 + } +///** +// * @Author Chaoqun +// * @brief 含参构造函数 +// * @date 2017/05/01 +// */ +//DocPassage::DocPassage(QWidget *parent, +// QString version, QString docType, double scaleFactor) +// :QScrollArea(parent) +//{ +// undoStack=new QUndoStack(this); +// this->version = version; +// this->docType = docType; +// this->scaleFactor = scaleFactor; +//} + DocPassage::~DocPassage() { - // 释放根节点内容 -// if(this->docInfo != NULL) -// { -// delete this->docInfo; -// this->docInfo = NULL; -// } - - // 释放公共数据 -// if(this->commonData != NULL) -// { -// delete this->commonData; -// this->commonData = NULL; -// } - -// 释放this->pages -// int pages_length = this->pages.size(); -// for(int i = 0; i < pages_length; i++) -// { -// // 需要挨个释放内存空间 -// DocPage* temp = this->pages.at(i); -// if(temp != NULL) -// { -// delete temp; -// (this->pages)[i] = NULL; -// } -// } -// this->pages.clear(); } @@ -100,11 +109,12 @@ void DocPassage::addPage(DocPage *page) page->setSize(default_width, default_height); // qDebug() << "!!Page width in pixel = " << page->size().width() // << "!!Page height in pixel = " << page->size().height(); - page->has_working_area = default_using_working_area; - page->working_area_height = default_working_height; - page->working_area_width = default_working_width; - page->working_area_x = default_working_x; - page->working_area_y = default_working_y; + page->setWorkingArea( + default_using_working_area, + default_working_width, + default_working_height, + default_working_x, + default_working_y); this->pages.append(page); // 添加到ScrollArea @@ -210,17 +220,17 @@ void DocPassage::setDocInfo(CT_DocInfo &docInfo) this->setWindowTitle(this->docInfo->getTitle()); // 设置小窗口标题 } -/** - * @Author Chaoqun - * @brief 测试 - * @param 参数 - * @return 返回值 - * @date 2017/06/22 - */ -void DocPassage::testMessage() -{ -// qDebug()<<"passage success"; -} +///** +// * @Author Chaoqun +// * @brief 测试 +// * @param 参数 +// * @return 返回值 +// * @date 2017/06/22 +// */ +//void DocPassage::testMessage() +//{ +//// qDebug()<<"passage success"; +//} /** * @Author Chaoqun @@ -388,10 +398,13 @@ void DocPassage::closeEvent(QCloseEvent *event) QScrollArea::closeEvent(event); } -void DocPassage::init() +/// +/// \brief DocPassage::initUI +/// 与界面有关的初始化 +/// +void DocPassage::initUI() { - this->docInfo = new CT_DocInfo(); // 新建文档 元信息 - this->resetDocId(); // 设置UUID + this->layout = new QVBoxLayout; // 新建布局 // 新增widget @@ -410,7 +423,6 @@ void DocPassage::init() this->scaleFactor = 1.0; - // 设置滚动条策略 this->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); this->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); @@ -421,15 +433,37 @@ void DocPassage::init() adjustScrollBar(this->horizontalScrollBar(), 1); adjustScrollBar(this->verticalScrollBar(),1); - this->page_dialog = new PageDialog(NULL, this); // qDebug() << "Finished Initializing DocPassage..."; - default_width = 210; //默认宽度 - default_height = 297; //默认高度 + GlobalSetting* global = GlobalSetting::getInstance(); + default_width = global->getPhysicalWidth(); //默认宽度 + default_height = global->getPhysicalHeight(); //默认高度 default_using_working_area = false; - default_working_width = 210; - default_working_height = 297; - default_working_x = 0; - default_working_y = 0; + default_working_width = global->getContentWidth(); + default_working_height = global->getContentHeight(); + default_working_x = global->getContentX(); + default_working_y = global->getContentY(); + +} + +/// +/// \brief DocPassage::initDocInfo +/// 用来初始化文档相关的信息 +/// +void DocPassage::initDocInfo() +{ + this->docInfo = new CT_DocInfo(); // 新建文档 元信息 + this->resetDocId(); // 设置UUID + + GlobalSetting* globalSetting = GlobalSetting::getInstance(); + this->docInfo->setCreator(globalSetting->getCreator()); + this->docInfo->setCreatorVersion(globalSetting->getCreatorVersion()); + + this->docType = globalSetting->getDocType(); + this->version = globalSetting->getDocVersion(); + + QDateTime time = QDateTime::currentDateTime(); // 获得系统当前时间 + this->docInfo->setCreationDate( time.toString("yyyy-MM-dd hh:mm:ss")); + } /** @@ -533,57 +567,85 @@ void DocPassage::activatePageDialog() // << "page height in pixel = " << page->size().height(); if (page) { - page_dialog->updateInformation(page, - default_width, - default_height, - default_using_working_area, - default_working_width, - default_working_height, - default_working_x, - default_working_y); + PageDialog* page_dialog = PageDialog::getInstance(); + + page_dialog->init(page, + default_width, + default_height, + default_using_working_area, + default_working_width, + default_working_height, + default_working_x, + default_working_y); + this->page_dialog->exec(); } } -void DocPassage::updatePageSizeInformation(QVector &changed_pages, - double current_width, - double current_height, - bool current_using_working_area, - double current_working_width, - double current_working_height, - double current_working_x, - double current_working_y, - double default_height, - double default_width, - bool using_working_area, - double default_working_width, - double default_working_height, - double default_working_x, - double default_working_y) -{ - DocPage * cur_page; - for (int i = 0; i < changed_pages.size(); i++) { - cur_page = pages[changed_pages[i] - 1]; - cur_page->setSize(current_width, current_height); - cur_page->has_working_area = current_using_working_area; - cur_page->working_area_width = current_working_width; - cur_page->working_area_height = current_working_height; - cur_page->working_area_x = current_working_x; - cur_page->working_area_y = current_working_y; +/// +/// \brief DocPassage::modifyPageSize +/// 修改指定页面的尺寸 +/// \param choosed_pages +/// \param _width +/// \param _height +/// \param isUsingWorkingArea +/// \param contentWidth +/// \param contentHeight +/// \param contentX +/// \param contentY +/// +void DocPassage::modifyPageSize( + QVector *ch_pages, + double _width, + double _height, + bool isUsingWorkingArea, + double contentWidth, + double contentHeight, + double contentX, + double contentY) +{ + + DocPage * temp_page; // 临时变量使用的页面 + for (int i = 0; i < ch_pages->size(); i++) { + temp_page = this->pages[ch_pages->operator [](i) - 1]; + temp_page->setSize(_width, _height); + temp_page->setWorkingArea(isUsingWorkingArea, + contentWidth, + contentHeight, + contentX, + contentY); } + + this->adjustWidgetSize(); // 更新尺寸 +} + +/// +/// \brief DocPassage::modifyDefaultPageSize +/// 修改默认新增加页面时的尺寸 +/// \param default_width +/// \param default_height +/// \param default_isUsingWorkingArea +/// \param default_contentWidth +/// \param default_contentHeight +/// \param default_contentX +/// \param default_contentY +/// +void DocPassage::modifyDefaultPageSize( + double default_width, + double default_height, + bool default_isUsingWorkingArea, + double default_contentWidth, + double default_contentHeight, + double default_contentX, + double default_contentY) +{ this->default_width = default_width; this->default_height = default_height; - this->default_using_working_area = using_working_area; - this->default_working_width = default_working_width; - this->default_working_height = default_working_height; - this->default_working_x = default_working_x; - this->default_working_y = default_working_y; -// qDebug() << "Current Page Width = " -// << UnitTool::pixelToMM(qobject_cast(focusWidget())->size().width()) -// << "Current Page Height = " - // << UnitTool::pixelToMM(qobject_cast(focusWidget())->size().height()); - - this->adjustWidgetSize(); + this->default_using_working_area = default_isUsingWorkingArea; + this->default_working_width = default_contentWidth; + this->default_working_height = default_contentHeight; + this->default_working_x = default_contentX; + this->default_working_y = default_contentY; } /** diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index 0ca6591..df5ef36 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -35,9 +35,14 @@ class MODELSHARED_EXPORT DocPassage { Q_OBJECT public: - explicit DocPassage(QWidget* parent = 0); - DocPassage(QWidget *parent, QString version, - QString docType,double scaleFactor); + + static DocPassage *createNewPassage(); // 创建新的文章 + static DocPassage *createEmptyPassage(); // 创建空的文章 + + explicit DocPassage(QWidget* parent); + DocPassage(); // 空构造函数 +// DocPassage(QWidget *parent, QString version, +// QString docType,double scaleFactor); // 可能用不上了 ~DocPassage(); CT_DocInfo* getDocInfo(); // 获取CT_DocInfo数据 @@ -76,7 +81,7 @@ public slots: // docId void resetDocId(); // 重新设置DocId - void testMessage(); // 测试信号是否走通 +// void testMessage(); // 测试信号是否走通 void adjustWidgetSize(); // 根据页数来自动调整widget大小 @@ -84,21 +89,28 @@ public slots: void activatePageDialog(); - void updatePageSizeInformation(QVector & changed_pages, - double current_width, - double current_height, - bool current_using_working_area, - double current_working_width, - double current_working_height, - double current_working_x, - double current_working_y, - double default_height, - double default_width, - bool using_working_area, - double default_working_width, - double default_working_height, - double default_working_x, - double default_working_y); + // 更改指定页面的页面尺寸 + void modifyPageSize( + QVector * ch_pages, + double _width, + double _height, + bool isUsingWorkingArea, + double contentWidth, + double contentHeight, + double contentX, + double contentY); + + // 修改文章的默认尺寸 + void modifyDefaultPageSize( + double default_width, + double default_height, + bool default_isUsingWorkingArea, + double default_contentWidth, + double default_contentHeight, + double default_contentX, + double default_contentY + ); + void zoomIn(); // 缩小 void zoomOut(); // 放大 @@ -134,12 +146,15 @@ private: int horizontalWhite; // 白色页面左右两边的灰色区域 int verticalWhite; // 白色页面上下的灰色区域 - void init(); // 初始化 + void initUI(); // 初始化文章界面相关的 + void initDocInfo(); // 初始化文档信息 + void adjustScrollBar(QScrollBar *scrollBar, double factor); // 调整滑动条 void adjustScrollBarRange(); //调整滑动条范围 PageDialog * page_dialog; //用于调整页面格式的对话框 + // 默认的大小 double default_width; //默认宽度 double default_height; //默认高度 bool default_using_working_area; diff --git a/ofdEditor/model/Widget/DocInfoDialog.cpp b/ofdEditor/model/Widget/DocInfoDialog.cpp index d9d8601..d2fc000 100644 --- a/ofdEditor/model/Widget/DocInfoDialog.cpp +++ b/ofdEditor/model/Widget/DocInfoDialog.cpp @@ -5,22 +5,65 @@ #include #include -DocInfoDialog::DocInfoDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::DocInfoDialog) +DocInfoDialog* DocInfoDialog::m_instance = NULL; // 初始化静态变量 + +/// +/// \brief DocInfoDialog::getInstance +/// 获取实例 +/// \return +/// +DocInfoDialog *DocInfoDialog::getInstance() { - ui->setupUi(this); + if(m_instance != NULL) + { + return m_instance; + } + + m_instance = new DocInfoDialog(); + return m_instance; } -DocInfoDialog::DocInfoDialog(CT_DocInfo *docInfo,QWidget *parent = 0): - QDialog(parent), ui(new Ui::DocInfoDialog) +/// +/// \brief DocInfoDialog::DestoryInstance +/// 销毁实例 +void DocInfoDialog::DestoryInstance() +{ + m_instance = NULL; +} + +/// +/// \brief DocInfoDialog::init +/// 每次调用出单例后进行调用,来调整显示的内容 +/// \param docInfo +/// +void DocInfoDialog::init(CT_DocInfo *docInfo) { - ui->setupUi(this); this->docInfo = docInfo; - this->init(); this->initUi(); } +/// +/// \brief DocInfoDialog::DocInfoDialog +/// 构造函数 +/// \param parent +/// +DocInfoDialog::DocInfoDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::DocInfoDialog) +{ + ui->setupUi(this); + this->init(); // 初始化链接信号槽 +} + +//DocInfoDialog::DocInfoDialog(CT_DocInfo *docInfo,QWidget *parent = 0): +// QDialog(parent), ui(new Ui::DocInfoDialog) +//{ +// ui->setupUi(this); +// this->docInfo = docInfo; +// this->init(); +// this->initUi(); +//} + DocInfoDialog::~DocInfoDialog() { delete ui; diff --git a/ofdEditor/model/Widget/DocInfoDialog.h b/ofdEditor/model/Widget/DocInfoDialog.h index 97af86e..bf0e688 100644 --- a/ofdEditor/model/Widget/DocInfoDialog.h +++ b/ofdEditor/model/Widget/DocInfoDialog.h @@ -3,7 +3,7 @@ #include #include "model_global.h" -class CT_DocInfo; // ĵԪϢ +class CT_DocInfo; // 文档元信息 namespace Ui { class DocInfoDialog; @@ -14,26 +14,34 @@ class MODELSHARED_EXPORT DocInfoDialog : public QDialog Q_OBJECT public: - explicit DocInfoDialog(QWidget *parent = 0); - DocInfoDialog(CT_DocInfo* docInfo,QWidget *parent); + static DocInfoDialog* getInstance(); // 获得实例 + static void DestoryInstance(); // 销毁实例 + void init(CT_DocInfo* docInfo); // 初始化-每次调用窗口时使用 + + + +// DocInfoDialog(CT_DocInfo* docInfo,QWidget *parent); ~DocInfoDialog(); private: Ui::DocInfoDialog *ui; - CT_DocInfo* docInfo; // ĵԪϢ - void init(); // ʼ - void initUi(); // ʼui + static DocInfoDialog* m_instance; // 单例 + CT_DocInfo* docInfo; // 文档元信息 + + explicit DocInfoDialog(QWidget *parent = 0); + void init(); // 初始化 + void initUi(); // 初始化ui public slots: - void editTitle(const QString & text); // ޸ı - void editAuthor(const QString & text); // ޸ - void editSubject(const QString & text); // ޸ - void editAbstract(const QString & text); // ޸ժҪ - void editFileType(const QString & text); // ĵ - void editFileCover(const QString & text); // ĵ - void resetDocId(); // UUID + void editTitle(const QString & text); // 修改标题 + void editAuthor(const QString & text); // 修改作者 + void editSubject(const QString & text); // 修改主题 + void editAbstract(const QString & text); // 修改摘要 + void editFileType(const QString & text); // 文档类型 + void editFileCover(const QString & text); // 文档封面 + void resetDocId(); // 重置UUID }; diff --git a/ofdEditor/model/Widget/PageDialog.cpp b/ofdEditor/model/Widget/PageDialog.cpp index 8f61892..86a5c58 100644 --- a/ofdEditor/model/Widget/PageDialog.cpp +++ b/ofdEditor/model/Widget/PageDialog.cpp @@ -5,39 +5,144 @@ #include #include "../Tool/UnitTool.h" +PageDialog* PageDialog::m_instance = NULL; + int toNearestInt(double n) { return n + 0.5; } -PageDialog::PageDialog(QWidget *parent, DocPassage * passage) : - QDialog(parent), - ui(new Ui::PageDialog), - changed_page_numbers() +PageDialog *PageDialog::getInstance() { - ui->setupUi(this); - this->passage = passage; + if(m_instance != NULL) + { + return m_instance; + } + m_instance = new PageDialog(); + return m_instance; +} + +void PageDialog::DestoryInstance() +{ + m_instance = NULL; +} + +/// +/// \brief PageDialog::init +/// \param current_page +/// \param default_width +/// \param default_height +/// \param using_working_area +/// \param default_working_width +/// \param default_working_height +/// \param default_working_x +/// \param default_working_y +/// +void PageDialog::init( + DocPage *current_page, + double default_width, + double default_height, + bool using_working_area, + double default_working_width, + double default_working_height, + double default_working_x, + double default_working_y) +{ + this->current_page = current_page; - //成员初始化 - current_page = NULL; - //组件初始化 if (current_page) { - ui->CurrentPageSizeWidth->setValue(current_page->size().width()); - ui->CurrentPageSizeHeight->setValue(current_page->size().height()); +// qDebug() << "Current_page width in pixel = " << current_page->size().width(); +// qDebug() << "Current_page height in pixel = " << current_page->size().height(); + ui->CurrentPageSizeWidth->setValue(toNearestInt(UnitTool::pixelToMM(current_page->size().width()))); + ui->CurrentPageSizeHeight->setValue(toNearestInt(UnitTool::pixelToMM(current_page->size().height()))); + //Working area to be implemented!!!! + ui->CurrentWorkingAreaWidth->setValue(toNearestInt(current_page->getContentWidth())); + ui->CurrentWorkingAreaHeight->setValue(toNearestInt(current_page->getContentHeight())); + ui->CurrentWorkingAreaX->setValue(toNearestInt(current_page->getContentX())); + ui->CurrentWorkingAreaY->setValue(toNearestInt(current_page->getContentY())); + + ui->DefaultPageSizeWidth->setValue(toNearestInt(default_height)); + ui->DefaultPageSizeHeight->setValue(toNearestInt(default_width)); + //Working area to be implemented!!!! + ui->DefaultSetWorkingAreaChecked->setChecked(using_working_area); + ui->DefaultWorkingAreaWidth->setValue(toNearestInt(default_working_width)); + ui->DefaultWorkingAreaHeight->setValue(toNearestInt(default_working_height)); + ui->DefaultWorkingAreaX->setValue(toNearestInt(default_working_x)); + ui->DefaultWorkingAreaY->setValue(toNearestInt(default_working_y)); + + this->isDefaultPageSizeChanged = false; // 是否修改了默认尺寸 + + this->connect(this, + SIGNAL(modifyPageSize( + QVector*, + double, + double, + bool, + double, + double, + double, + double)), + this->passage, + SLOT(modifyPageSize( + QVector*, + double, + double, + bool, + double, + double, + double, + double))); + + this->connect(this, + SIGNAL(modifyDefaultPageSize( + double, + double, + bool, + double, + double, + double, + double)), + this->passage, + SLOT(modifyDefaultPageSize( + double, + double, + bool, + double, + double, + double, + double))); + + } - ui->CurrentPageSizeWidth->setRange(0.0, 10000.0); - ui->CurrentPageSizeHeight->setRange(0.0, 10000.0); - ui->DefaultPageSizeWidth->setRange(0.0, 10000.0); - ui->DefaultPageSizeHeight->setRange(0.0, 10000.0); - ui->CurrentWorkingAreaWidth->setRange(0.0, 10000.0); - ui->CurrentWorkingAreaHeight->setRange(0.0, 10000.0); - ui->DefaultWorkingAreaWidth->setRange(0.0, 10000.0); - ui->DefaultWorkingAreaHeight->setRange(0.0, 10000.0); - ui->CurrentWorkingAreaX->setRange(0.0, 10000.0); - ui->CurrentWorkingAreaY->setRange(0.0, 10000.0); - ui->DefaultWorkingAreaX->setRange(0.0, 10000.0); - ui->DefaultWorkingAreaY->setRange(0.0, 10000.0); +} + + +PageDialog::~PageDialog() +{ + delete ui; +} + + +/// +/// \brief PageDialog::PageDialog +/// \param parent +/// +PageDialog::PageDialog(QWidget *parent) + :QDialog(parent),ui(new Ui::PageDialog) +{ + ui->setupUi(this); + this->initUI(); + this->initConnect(); + + qDebug() << "Constructor executed finished"; +} + +/// +/// \brief PageDialog::initUI +/// 初始化界面 +void PageDialog::initUI() +{ ui->CurrentSetWorkingAreaChecked->setChecked(false); ui->CurrentWorkingAreaWidth->setEnabled(false); @@ -72,6 +177,15 @@ PageDialog::PageDialog(QWidget *parent, DocPassage * passage) : ui->PageRangeLowerBound->setValue(1); ui->PageRangeUpperBound->setValue(passage->getPages().size()); ui->SpecificPage->setEnabled(false); + +} + +/// +/// \brief PageDialog::initConnect +/// 初始化 信号槽 +/// +void PageDialog::initConnect() +{ //创建信号槽 this->connect(ui->PageRangeCheckBox, SIGNAL(clicked(bool)), @@ -138,53 +252,40 @@ PageDialog::PageDialog(QWidget *parent, DocPassage * passage) : this, SLOT(changed_page_range_changed())); + // 选择确定后的操作 this->connect(this, SIGNAL(accepted()), this, SLOT(emitInformation())); -} - -PageDialog::~PageDialog() -{ - delete ui; -} - -void PageDialog::updateInformation(DocPage *current_page, - double default_width, - double default_height, - bool using_working_area, - double default_working_width, - double default_working_height, - double default_working_x, - double default_working_y) -{ - this->current_page = current_page; - if (current_page) - { -// qDebug() << "Current_page width in pixel = " << current_page->size().width(); -// qDebug() << "Current_page height in pixel = " << current_page->size().height(); - ui->CurrentPageSizeWidth->setValue(toNearestInt(UnitTool::pixelToMM(current_page->size().width()))); - ui->CurrentPageSizeHeight->setValue(toNearestInt(UnitTool::pixelToMM(current_page->size().height()))); - //Working area to be implemented!!!! - ui->CurrentWorkingAreaWidth->setValue(toNearestInt(current_page->working_area_width)); - ui->CurrentWorkingAreaHeight->setValue(toNearestInt(current_page->working_area_height)); - ui->CurrentWorkingAreaX->setValue(toNearestInt(current_page->working_area_x)); - ui->CurrentWorkingAreaY->setValue(toNearestInt(current_page->working_area_y)); - ui->DefaultPageSizeWidth->setValue(toNearestInt(default_height)); - ui->DefaultPageSizeHeight->setValue(toNearestInt(default_width)); - //Working area to be implemented!!!! - ui->DefaultSetWorkingAreaChecked->setChecked(using_working_area); - ui->DefaultWorkingAreaWidth->setValue(toNearestInt(default_working_width)); - ui->DefaultWorkingAreaHeight->setValue(toNearestInt(default_working_height)); - ui->DefaultWorkingAreaX->setValue(toNearestInt(default_working_x)); - ui->DefaultWorkingAreaY->setValue(toNearestInt(default_working_y)); + // 判断是否修改过默认值 + this->connect(ui->DefaultPageSizeWidth, + SIGNAL(valueChanged(double)), + this, + SLOT(on_DefaultSizeChanged(double))); + this->connect(ui->DefaultPageSizeHeight, + SIGNAL(valueChanged(double)), + this, + SLOT(on_DefaultSizeChanged(double))); + this->connect(ui->DefaultWorkingAreaHeight, + SIGNAL(valueChanged(double)), + this, + SLOT(on_DefaultSizeChanged(double))); + this->connect(ui->DefaultWorkingAreaWidth, + SIGNAL(valueChanged(double)), + this, + SLOT(on_DefaultSizeChanged(double))); + this->connect(ui->DefaultWorkingAreaX, + SIGNAL(valueChanged(double)), + this, + SLOT(on_DefaultSizeChanged(double))); + this->connect(ui->DefaultWorkingAreaY, + SIGNAL(valueChanged(double)), + this, + SLOT(on_DefaultSizeChanged(double))); - } } - - void PageDialog::on_CurrentSelectPageSize_currentIndexChanged(const QString &arg1) { if (arg1 == tr("A4")) @@ -241,6 +342,7 @@ void PageDialog::on_DefaultSelectPageSize_currentIndexChanged(const QString &arg ui->DefaultPageSizeWidth->setValue(130); ui->DefaultPageSizeHeight->setValue(184); } + this->isDefaultPageSizeChanged = true; } void PageDialog::on_SpecificPageCheckBox_clicked(bool checked) @@ -299,6 +401,13 @@ void PageDialog::on_DefaultSetWorkingAreaChecked_clicked(bool checked) ui->DefaultWorkingAreaX->setValue(0.0); ui->DefaultWorkingAreaY->setValue(0.0); } + + this->isDefaultPageSizeChanged = true; +} + +void PageDialog::on_DefaultSizeChanged(double value) +{ + this->isDefaultPageSizeChanged = true; } void PageDialog::on_CurrentPageSize_valueChanged() @@ -394,20 +503,67 @@ void PageDialog::changed_page_range_changed() void PageDialog::emitInformation() { - passage->updatePageSizeInformation(changed_page_numbers, - ui->CurrentPageSizeWidth->value(), - ui->CurrentPageSizeHeight->value(), - ui->CurrentSetWorkingAreaChecked->isChecked(), - ui->CurrentWorkingAreaWidth->value(), - ui->CurrentWorkingAreaHeight->value(), - ui->CurrentWorkingAreaX->value(), - ui->CurrentWorkingAreaY->value(), - ui->DefaultPageSizeWidth->value(), - ui->DefaultPageSizeHeight->value(), - ui->DefaultSetWorkingAreaChecked->isChecked(), - ui->DefaultWorkingAreaWidth->value(), - ui->DefaultWorkingAreaHeight->value(), - ui->DefaultWorkingAreaX->value(), - ui->DefaultWorkingAreaY->value()); + + emit this->modifyPageSize(&changed_page_numbers, + ui->CurrentPageSizeWidth->value(), + ui->CurrentPageSizeHeight->value(), + ui->CurrentSetWorkingAreaChecked->isChecked(), + ui->CurrentWorkingAreaWidth->value(), + ui->CurrentWorkingAreaHeight->value(), + ui->CurrentWorkingAreaX->value(), + ui->CurrentWorkingAreaY->value()); + + if(isDefaultPageSizeChanged) + { + emit this->modifyDefaultPageSize( + ui->DefaultPageSizeWidth->value(), + ui->DefaultPageSizeHeight->value(), + ui->DefaultSetWorkingAreaChecked->isChecked(), + ui->DefaultWorkingAreaWidth->value(), + ui->DefaultWorkingAreaHeight->value(), + ui->DefaultWorkingAreaX->value(), + ui->DefaultWorkingAreaY->value()); + } + + // 断开链接 + this->disconnect(this, + SIGNAL(modifyPageSize( + QVector*, + double, + double, + bool, + double, + double, + double, + double)), + this->passage, + SLOT(modifyPageSize( + QVector*, + double, + double, + bool, + double, + double, + double, + double))); + + this->disconnect(this, + SIGNAL(modifyDefaultPageSize( + double, + double, + bool, + double, + double, + double, + double)), + this->passage, + SLOT(modifyDefaultPageSize( + double, + double, + bool, + double, + double, + double, + double))); } diff --git a/ofdEditor/model/Widget/PageDialog.h b/ofdEditor/model/Widget/PageDialog.h index 8bf0e07..839aa14 100644 --- a/ofdEditor/model/Widget/PageDialog.h +++ b/ofdEditor/model/Widget/PageDialog.h @@ -12,21 +12,35 @@ namespace Ui { class PageDialog; } -class PageDialog : public QDialog +/// +/// \brief The PageDialog class +/// +class PageDialog + : public QDialog { Q_OBJECT public: - explicit PageDialog(QWidget *parent = 0, DocPassage* passage = NULL); + + static PageDialog* getInstance(); // 获得单例 + static void DestoryInstance(); // 销毁实例 + void init(DocPage * current_page, + double default_width, + double default_height, + bool using_working_area, + double default_working_width, + double default_working_height, + double default_working_x, + double default_working_y); // 初始化时调用 + ~PageDialog(); - void updateInformation(DocPage * current_page, - double default_width, - double default_height, - bool using_working_area, - double default_working_width, - double default_working_height, - double default_working_x, - double default_working_y); + +private: + explicit PageDialog(QWidget *parent = 0); // 构造函数 + void initUI(); + void initConnect(); + + static PageDialog* m_instance; private slots: @@ -40,14 +54,14 @@ private slots: void on_DefaultSetWorkingAreaChecked_clicked(bool checked); - void on_CurrentPageSize_valueChanged(); + void on_DefaultSizeChanged(double value); // 用来判断是否有修改过默认值 + void on_CurrentPageSize_valueChanged(); void on_PageRangeCheckBox_toggled(bool checked); void on_SpecificPageCheckBox_toggled(bool checked); - void on_CurrentPageCheckBox_toggled(bool checked); void on_AllPagesCheckBox_toggled(bool checked); @@ -57,11 +71,34 @@ private slots: void changed_page_range_changed(); void emitInformation(); + +signals: + void modifyPageSize(QVector * ch_pages, + double _width, + double _height, + bool isUsingWorkingArea, + double contentWidth, + double contentHeight, + double contentX, + double contentY); + + void modifyDefaultPageSize( + double default_width, + double default_height, + bool default_isUsingWorkingArea, + double default_contentWidth, + double default_contentHeight, + double default_contentX, + double default_contentY + ); + private: Ui::PageDialog *ui; DocPassage *passage; QVector changed_page_numbers; DocPage * current_page; + + bool isDefaultPageSizeChanged; }; #endif // PAGEDIALOG_H diff --git a/ofdEditor/model/Widget/PageDialog.ui b/ofdEditor/model/Widget/PageDialog.ui index 7eb133d..c2c0917 100644 --- a/ofdEditor/model/Widget/PageDialog.ui +++ b/ofdEditor/model/Widget/PageDialog.ui @@ -6,8 +6,8 @@ 0 0 - 454 - 451 + 465 + 456 @@ -23,424 +23,412 @@ 当前页面 - - - - - - 宋体 - 11 - - - - - - - - - - - - 宋体 - 12 - - - + + + + 页面设置 - - - - - - - 宋体 - 11 - - - - 页面尺寸 - - - - - - - - 宋体 - 11 - - - - - - - - - - - - 宋体 - 11 - - - - mm - - - - - - - - - - - - - - 宋体 - 11 - - - - mm - - - - - - - - 宋体 - 11 - - - - 选择尺寸 - - - - - - - 设置工作区域 - - - - - - - - 宋体 - 11 - - - - 工作区域尺寸 - - - - - - - - 宋体 - 11 - - - - - - - - - - - - - - 特定页数 - - - AppliedRange - - - - - - - - 宋体 - 11 - - - - mm - - - - - - - Qt::Horizontal - - - - - - - - Agency FB - 11 - - - - 页码 - - - - - - - - - - - 宋体 - 11 - - - - mm - - - - - - - 当前页 - - - AppliedRange - - - - - - - - - - - 宋体 - 11 - - - - 水平 - - - - - - - - 宋体 - 11 - - - - mm - - - - - - - - - - - 宋体 - 11 - - - + + + + + + 宋体 + 11 + + + + 页面尺寸 + + + + + + + + 宋体 + 11 + + + + + + + + + + + 10000.000000000000000 + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 11 + + + + + + + + + + + 10000.000000000000000 + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 11 + + + + 选择尺寸 + + + + + + + + A4 + + + + + A3 + + + + + A5 + + + + + Letter + + + + + 16K + + + + + 32K + + + + + Customized + + + + + + + + 设置工作区域 + + + + + + + + 宋体 + 11 + + + + 工作区域尺寸 + + + + + + + + 宋体 + 11 + + + + + + + + + + + 10000.000000000000000 + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 11 + + + + + + + + + + + 10000.000000000000000 + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 11 + + + + 工作区域位置 + + + + + + + + 宋体 + 11 + + + + 水平 + + + + + + + 10000.000000000000000 + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 11 + + + + 垂直 + + + + + + + 10000.000000000000000 + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + + 应用于 - - - - - - - 宋体 - 11 - - - - 工作区域位置 - - - - - - - 所有页 - - - AppliedRange - - - - - - - - 宋体 - 11 - - - - mm - - - - - - - - 宋体 - 11 - - - - - - - - - - - - - - 页面范围 - - - AppliedRange - - - - - - - - Agency FB - 11 - - - - - - - - - - - - Agency FB - 11 - - - - - - - - - - - - - - - - - - Agency FB - 11 - - - - - - - - - - - - 宋体 - 11 - - - - 垂直 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - A4 - - - - - A3 - - - - - A5 - - - - - Letter - - - - - 16K - - - - - 32K - - - - - Customized - - + + + + + 10000 + + + + + + + 页面范围 + + + + + + + 当前页 + + + + + + + 所有页 + + + + + + + + Agency FB + 11 + + + + + + + + + + + + + + + Agency FB + 11 + + + + + + + + + + + 特定页数 + + + + + + + + Agency FB + 11 + + + + + + + + + + + + Agency FB + 11 + + + + 页码 + + + + + + + @@ -450,310 +438,317 @@ 默认页面 - - - - - - - - - - - 宋体 - 11 - - - - 工作区域位置 - - - - - - - - A4 - - - - - A3 - - - - - A5 - - - - - Letter - - - - - 16K - - - - - 32K - - - - - Customized - - - - - - - - - 宋体 - 11 - - - - mm - - - - - - - - 宋体 - 11 - - - - 垂直 - - - - - - - - 宋体 - 11 - - - - mm - - - - - - - - - - - 宋体 - 11 - - - - - - - - - - - - 宋体 - 11 - - - - mm - - - - - - - - 宋体 - 11 - - - - - - - - - - - - 宋体 - 11 - - - - 页面尺寸 - - - - - - - - 宋体 - 11 - - - - 水平 - - - - - - - - 宋体 - 11 - - - - mm - - - - - - - 宋体 - 12 - - - - 默认页面设置 - - - - - - - - - - - 宋体 - 11 - - - - mm - + + + + + + + + + + 宋体 + 11 + + + + 页面尺寸 + + + + + + + + 宋体 + 11 + + + + + + + + + + + 10000.000000000000000 + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 11 + + + + + + + + + + + 10000.000000000000000 + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 11 + + + + 选择尺寸 + + + + + + + + A4 + + + + + A3 + + + + + A5 + + + + + Letter + + + + + 16K + + + + + 32K + + + + + Customized + + + + + + + + 设置工作区域 + + + + + + + + 宋体 + 11 + + + + 工作区域尺寸 + + + + + + + + 宋体 + 11 + + + + + + + + + + + 10000.000000000000000 + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 11 + + + + + + + + + + + 10000.000000000000000 + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 11 + + + + 工作区域位置 + + + + + + + + 宋体 + 11 + + + + 水平 + + + + + + + 10000.000000000000000 + + + + + + + + 宋体 + 11 + + + + mm + + + + + + + + 宋体 + 11 + + + + 垂直 + + + + + + + 10000.000000000000000 + + + + + + + + 宋体 + 11 + + + + mm + + + + - - - - - - - - - - - 宋体 - 11 - - - - - - - - - - - - 宋体 - 11 - - - - 选择尺寸 - - - - - - - - 宋体 - 11 - - - - 工作区域尺寸 - - - - - - - - 宋体 - 11 - - - - - - - - - - - - 宋体 - 11 - - - - mm - - - - - - - 设置工作区域 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - + Qt::Vertical diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index b8dac64..f92c8c9 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -76,7 +76,6 @@ HEADERS += model.h\ Convert/MergeCT_Texts.h \ Convert/Doc_OFDConvertor.h \ Convert/Objects/MinTextUnit.h \ - Widget/DocInfoDialog.h \ Command/SetTextBlodCmd.h \ Doc/DocImageBlock.h \ Widget/imagepropertiesdialog.h \ @@ -84,7 +83,8 @@ HEADERS += model.h\ Widget/FindAndReplaceDock.h \ Widget/InsertTableDialog.h \ Widget/SelectTemplateDialog.h \ - Core/GlobalSetting.h + Core/GlobalSetting.h \ + Widget/DocInfoDialog.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 diff --git a/ofdEditor/start/ActionConnector/ActionConnector.cpp b/ofdEditor/start/ActionConnector/ActionConnector.cpp index d45808c..d79e5cb 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.cpp +++ b/ofdEditor/start/ActionConnector/ActionConnector.cpp @@ -33,11 +33,10 @@ void ActionConnector::showAttribute() return; } - CT_DocInfo * docInfo = this->passage->getDocInfo(); - DocInfoDialog* dialog = new DocInfoDialog(docInfo,this->mainWindow); // 设置窗口 + DocInfoDialog* dialog = DocInfoDialog::getInstance(); // 获得实例 + dialog->init(docInfo); // 设置窗口 dialog->exec(); // 运行 -// qDebug() << "show Attribute"; } diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 1eacf6a..afabd54 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -93,8 +93,6 @@ DocPassage *PassageMainWindow::createMdiChild() */ void PassageMainWindow::init() { - GlobalSetting *setting = GlobalSetting::getInstance(); - this->area = new QMdiArea(); this->setCentralWidget(this->area); @@ -112,25 +110,20 @@ void PassageMainWindow::init() this->setWindowTitle(tr("OFD Editor")); this->setWindowIcon(QIcon(":/icons/source/icons/ofdEditor2.png")); -// this->find_and_replace_dock = new FindAndReplaceDock(NULL); -// this->addDockWidget(Qt::BottomDockWidgetArea, find_and_replace_dock); -// this->find_and_replace_dock->setWindowIcon(QIcon(":/icons/source/icons/Find.png")); -// this->find_and_replace_dock->setMaximumHeight(60); -// this->find_and_replace_dock->setMinimumHeight(60); -// this->find_and_replace_dock->setVisible(false); - + // 配置查找替换窗口 FindAndReplaceDock* find_and_replace_dock = FindAndReplaceDock::getInstance(); // 获得单例 - this->addDockWidget( + this->addDockWidget( Qt::BottomDockWidgetArea, find_and_replace_dock); // 设置容器 - find_and_replace_dock->setWindowIcon( - QIcon(":/icons/source/icons/Find.png")); // 设置图标 - find_and_replace_dock->setMaximumHeight(60); - find_and_replace_dock->setMinimumHeight(60); - find_and_replace_dock->setVisible(false); + find_and_replace_dock->setWindowIcon( + QIcon(":/icons/source/icons/Find.png")); // 设置图标 + find_and_replace_dock->setMaximumHeight(60); + find_and_replace_dock->setMinimumHeight(60); + find_and_replace_dock->setVisible(false); + // 选择模板页面 this->select_template_dialog = new SelectTemplateDialog(NULL, this); this->select_template_dialog->setFixedSize(select_template_dialog->size()); connect(this->select_template_dialog, SIGNAL(createTemplate(int)), diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index 70602f2..69b5430 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -27,7 +27,6 @@ public: explicit PassageMainWindow(QWidget *parent = 0); ~PassageMainWindow(); - public slots: void activateFindAndReplaceDock(); // 激活查找替换窗口 DocPassage *createMdiChild(); // 创建一个新文档 @@ -51,7 +50,6 @@ private: QToolBar* insert_toolBar; // 插入 QToolBar* textBlock_toolBar; // 文本工具栏 - // QAction // 文件 QAction * newFileAction; // 新建文件 @@ -111,7 +109,6 @@ private: ActionConnector* connector; // 功能连接中间件 - void init(); // 初始化 void initAction(); // 初始化QAction void connectAction(); // 链接QAction的相应事件 -- Gitee From adea447b451ba1d52a19ccbf3d9c1fab10b927ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Mon, 7 Aug 2017 18:46:11 +0800 Subject: [PATCH 31/83] =?UTF-8?q?=E5=AF=B9PageDialog=E6=9B=B4=E5=8A=A0?= =?UTF-8?q?=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/Doc_OFDConvertor.cpp | 8 +- ofdEditor/model/Doc/DocPage.cpp | 16 +- ofdEditor/model/Doc/DocPage.h | 12 +- ofdEditor/model/Doc/DocPassage.cpp | 80 ++++- ofdEditor/model/Doc/DocPassage.h | 53 +-- ofdEditor/model/Widget/FindAndReplaceDock.cpp | 11 +- ofdEditor/model/Widget/FontSettingDialog.cpp | 15 +- ofdEditor/model/Widget/FontSettingDialog.h | 1 + ofdEditor/model/Widget/PageDialog.cpp | 337 +++++++++++------- ofdEditor/model/Widget/PageDialog.h | 66 ++-- ofdEditor/model/Widget/PageDialog.ui | 99 +++-- .../model/Widget/ParagraphFormatDialog.cpp | 14 +- .../model/Widget/ParagraphFormatDialog.h | 1 + 13 files changed, 442 insertions(+), 271 deletions(-) diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp index cc30894..1ac1435 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp @@ -132,8 +132,8 @@ void Doc_OFDConvertor::buildDocument() void Doc_OFDConvertor::buildPages(Document* document) { qDebug() << "exec buildPages"; - QVector docPages = this->passage->getPages(); // 获得页面 - int pagesLength = docPages.size(); // 获得页面的数量 + QVector* docPages = this->passage->getPages(); // 获得页面 + int pagesLength = docPages->size(); // 获得页面的数量 // 公共页大小,之后改成从DocPassage读取 if(pagesLength >= 1) @@ -143,7 +143,7 @@ void Doc_OFDConvertor::buildPages(Document* document) CT_PageArea *area = new CT_PageArea(); - DocPage* page = docPages[0]; + DocPage* page = docPages->operator [](0); area->setPhysicalBox(0,0, page->getWidth(),page->getHeight()); commonData->setPageArea(area); @@ -157,7 +157,7 @@ void Doc_OFDConvertor::buildPages(Document* document) // 遍历每个页面 for(int i=0; i< pagesLength;i++) { - DocPage* page = docPages.operator [](i); + DocPage* page = docPages->operator [](i); Page* ctPage = new Page(); ctPage->setID(this->table->size()+1,this->table); // 设置ID diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index 9ef4baa..eeb7ca2 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -387,12 +387,7 @@ void DocPage::mousePressEvent(QMouseEvent *event) QPointF tempPoint = this->mapToScene(this->oldPos.rx(), this->oldPos.ry()); -// qDebug() <<"temp Point"<currentStatus( -// block->mapFromScene(tempPoint)) -// == DocBlock::blockMove) if(block->cursor().shape() == Qt::SizeAllCursor) { // qDebug()<<" the cursor'shape is size all "; @@ -537,6 +532,17 @@ void DocPage::mouseReleaseEvent(QMouseEvent *event) QGraphicsView::mouseReleaseEvent(event); } +/// +/// \brief DocPage::focusInEvent +/// When this page been focused ,we will emit a message +/// \param event +/// +void DocPage::focusInEvent(QFocusEvent *event) +{ + QGraphicsView::focusInEvent(event); + emit signals_page_actived(this); +} + /** * @Author Chaoqun diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index 31ceace..b265e98 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -29,8 +29,6 @@ class MODELSHARED_EXPORT DocPage Q_OBJECT public: - - enum Layer{Body,Foreground,Background}; // 分为三层 enum BlockFlag{none,draw,drawMove,blockMove, blockResize}; // 插入时的绘制状态 enum BlockType{text,image,table}; // 插入时的类型 @@ -82,10 +80,11 @@ public slots: protected: void paintEvent(QPaintEvent *event); - void mouseDoubleClickEvent(QMouseEvent *event) ; - void mousePressEvent(QMouseEvent *event) ; - void mouseMoveEvent(QMouseEvent *event) ; - void mouseReleaseEvent(QMouseEvent *event) ; + void mouseDoubleClickEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void focusInEvent(QFocusEvent *event); private: @@ -125,6 +124,7 @@ signals: // 信号 void signals_removeTextBlock(DocTextBlock* textBlock ); // 移除文本框信号 void has_focused_page(); void has_no_focused_page(); + void signals_page_actived(DocPage* page); // 本页面被激活信号 }; diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index 2314305..21afd38 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -120,6 +120,11 @@ void DocPassage::addPage(DocPage *page) // 添加到ScrollArea this->layout->addWidget(page,0,Qt::AlignCenter); // 向layout中增加一页,并居中显示 + + // 接收当前操作页面的更新 + this->connect(page, SIGNAL(signals_page_actived(DocPage*)), + this, SLOT(setCurrentActivedPage(DocPage*))); + this->layout->update(); // 更新 page->setPassage(this); // 设置页所属的文章 this->adjustWidgetSize(); // 调整大小 @@ -293,9 +298,9 @@ QString DocPassage::getTempStorePath() * @return 返回值 * @date 2017/06/20 */ -QVector &DocPassage::getPages() +QVector *DocPassage::getPages() { - return this->pages; + return &this->pages; } /** @@ -323,6 +328,16 @@ QString DocPassage::getFilePath() return this->filePath; } +/// +/// \brief DocPassage::getLastedActivedPage +/// 获得最近更新的页面 +/// \return +/// +DocPage *DocPassage::getLastedActivedPage() +{ + return _lastActivedPage; +} + /** * @Author Chaoqun * @brief 设置CommonData,深拷贝 @@ -562,24 +577,39 @@ void DocPassage::setDefaultPageSize(double default_width, double default_height) void DocPassage::activatePageDialog() { - DocPage * page = qobject_cast(focusWidget()); -// qDebug() << "page width in pixel = " << page->size().width() -// << "page height in pixel = " << page->size().height(); - if (page) + +//// qDebug() << "page width in pixel = " << page->size().width() +//// << "page height in pixel = " << page->size().height(); + + int index = this->pages.indexOf(this->_lastActivedPage); + qDebug() << "The No." + << index + <<" page has been actived---" + << this->_lastActivedPage->getWidth(); + + if( this->_lastActivedPage!= NULL) { - PageDialog* page_dialog = PageDialog::getInstance(); - page_dialog->init(page, - default_width, - default_height, - default_using_working_area, - default_working_width, - default_working_height, - default_working_x, - default_working_y); + PageDialog* page_dialog = PageDialog::getInstance(); - this->page_dialog->exec(); + page_dialog->init( + this, + this->_lastActivedPage, + default_width, + default_height, + default_using_working_area, + default_working_width, + default_working_height, + default_working_x, + default_working_y); + + page_dialog->exec(); + } + else + { + qDebug() << "You should have clicked at least one page"; } + } /// @@ -605,6 +635,7 @@ void DocPassage::modifyPageSize( double contentY) { + qDebug() << "modifyPageSize"; DocPage * temp_page; // 临时变量使用的页面 for (int i = 0; i < ch_pages->size(); i++) { temp_page = this->pages[ch_pages->operator [](i) - 1]; @@ -699,3 +730,20 @@ void DocPassage::setScale(double scale) this->scaleFactor = scale; } + +/// +/// \brief DocPassage::setCurrentActivedPage +/// 设置当前活跃的页面 +/// 因为假设调用此函数的均为此文档下的页面,因此未作检测 +/// 通过信号槽调用 +/// \param page +/// +void DocPassage::setCurrentActivedPage(DocPage *page) +{ + this->_lastActivedPage = page; + + int index = this->pages.indexOf(this->_lastActivedPage); + qDebug() << "The No." + << index + <<" page has been actived" ; +} diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index df5ef36..675edf4 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -23,7 +23,7 @@ class CT_CommonData; class DocBlock; class DocTextBlock; class DocImageBlock; -class PageDialog; +//class PageDialog; /** * @Author Chaoqun @@ -51,10 +51,11 @@ public: QString getTempStorePath(); // 获得暂存资源的临时路径 QString getVersion( ){return this->version;} QString getDocType( ){return this->docType;} - QVector& getPages(); // 获得文档中包含的所有页面 + QVector* getPages(); // 获得文档中包含的所有页面 DocPage *getPage(int index); // 获得文档中的某一页 QString getFilePath(); // 获得文档路径 QUndoStack *undoStack; // 撤销队列 + DocPage* getLastedActivedPage(); // Get last actived page public slots: void addPage(DocPage *page); // 添加一个新页面 @@ -83,11 +84,13 @@ public slots: // void testMessage(); // 测试信号是否走通 - void adjustWidgetSize(); // 根据页数来自动调整widget大小 + void adjustWidgetSize();// 根据页数来自动调整widget大小 - void setDefaultPageSize(double default_width, double default_height); //设置默认的页面尺寸 + void setDefaultPageSize( + double default_width, + double default_height); //设置默认的页面尺寸 - void activatePageDialog(); + void activatePageDialog(); // 调出设置页面尺寸窗口 // 更改指定页面的页面尺寸 void modifyPageSize( @@ -115,18 +118,24 @@ public slots: void zoomOut(); // 放大 void setScale(double scale); // 设置缩放 + + // Set the current actived page + void setCurrentActivedPage(DocPage* page); + + protected: void resizeEvent(QResizeEvent* event); void closeEvent(QCloseEvent *event); // 继承,关闭前提示保存 + private: // 数据区 QString version; // OFD 版本默认 1.0 QString docType; // 类型默认是 OFD CT_DocInfo* docInfo; // 文档元数据结构 ofd/CT_DocInfo CT_CommonData* commonData; // 文档公用文档数据 - QVector pages; // 既作为数据,也作为渲染 + DocPage* _lastActivedPage; // 用来纪录最后操作过的页面 // 文件信息 QString filePath; @@ -139,21 +148,11 @@ private: QWidget * widget; // 用widget做缓冲 double scaleFactor; // 表示缩放倍数 - - double widgetWidth; // 内容的宽度 + double widgetWidth; // 文章内部的宽度 double widgetHeight; // 内容的高度 - int horizontalWhite; // 白色页面左右两边的灰色区域 int verticalWhite; // 白色页面上下的灰色区域 - void initUI(); // 初始化文章界面相关的 - void initDocInfo(); // 初始化文档信息 - - void adjustScrollBar(QScrollBar *scrollBar, - double factor); // 调整滑动条 - void adjustScrollBarRange(); //调整滑动条范围 - - PageDialog * page_dialog; //用于调整页面格式的对话框 // 默认的大小 double default_width; //默认宽度 double default_height; //默认高度 @@ -163,16 +162,28 @@ private: double default_working_x; double default_working_y; + void initUI(); // 初始化文章界面相关的 + void initDocInfo(); // 初始化文档信息 + void adjustScrollBar( + QScrollBar *scrollBar, + double factor); // 调整滑动条 + void adjustScrollBarRange(); //调整滑动条范围 + + signals: - void signals_insertTextBlock(DocTextBlock* textBlock); // 用来转发信号 - void signals_removeTextBlock(DocTextBlock* textBlock); // 用来转发信号 + void signals_insertTextBlock( + DocTextBlock* textBlock); // 用来转发信号 + void signals_removeTextBlock( + DocTextBlock* textBlock); // 用来转发信号 void signals_currentCharFormatChanged( QTextCharFormat fmt); // 当前选择的charFormat发生了变化 void signals_currentBlockFormatChanged( QTextBlockFormat fmt); // 当前选择的block格式发生了变化 - void signals_currentTextBlock(DocTextBlock* textBlock); // 当前操作的textBlock - void signals_currentImageBlock(DocImageBlock* imageBlock); //当前操作的imageBlock + void signals_currentTextBlock( + DocTextBlock* textBlock); // 当前操作的textBlock + void signals_currentImageBlock( + DocImageBlock* imageBlock); //当前操作的imageBlock }; diff --git a/ofdEditor/model/Widget/FindAndReplaceDock.cpp b/ofdEditor/model/Widget/FindAndReplaceDock.cpp index 2219a7b..f353912 100644 --- a/ofdEditor/model/Widget/FindAndReplaceDock.cpp +++ b/ofdEditor/model/Widget/FindAndReplaceDock.cpp @@ -165,9 +165,9 @@ void FindAndReplaceDock::on_FindLineEdit_textChanged(const QString &arg1) void FindAndReplaceDock::findAllTargetTextBlock(const QString & str) { // qDebug() << "Start finding all target blocks"; - for (int i = 0; i < passage->getPages().size(); i++) + for (int i = 0; i < passage->getPages()->size(); i++) { - DocPage * cur_page = passage->getPages()[i]; + DocPage * cur_page = passage->getPages()->operator [](i); DocLayer * foreground_layer = cur_page->getForegroundLayer(); DocLayer * body_layer = cur_page->getBodyLayer(); DocLayer * background_layer = cur_page->getBackgroundLayer(); @@ -265,12 +265,13 @@ void FindAndReplaceDock::focusOnFoundPart() DocPassage * current_passage = current_block->getPassage(); DocPage * current_page = current_block->getPage(); int accumulated_height = 0; - for (int i = 0; i < current_passage->getPages().size(); i++) + for (int i = 0; i < current_passage->getPages()->size(); i++) { - if (current_passage->getPages()[i] == current_page) + if (current_passage->getPages()->operator [](i) == current_page) break; else - accumulated_height += 50 + current_passage->getPages()[i]->height(); + accumulated_height += + 50 + current_passage->getPages()->operator [](i)->height(); } scroll_bar->setSliderPosition(accumulated_height + current_block->pos().ry()); } diff --git a/ofdEditor/model/Widget/FontSettingDialog.cpp b/ofdEditor/model/Widget/FontSettingDialog.cpp index 18f0e10..75ee1ba 100644 --- a/ofdEditor/model/Widget/FontSettingDialog.cpp +++ b/ofdEditor/model/Widget/FontSettingDialog.cpp @@ -162,6 +162,8 @@ void FontSettingDialog::initConnect() connect(this, SIGNAL(accepted()), this, SLOT(accept_slots())); // 窗口接受确认的信号 + connect(this,SIGNAL(finished(int)), + this,SLOT(finished_slots(int))); // 释放链接 } /** @@ -511,9 +513,18 @@ void FontSettingDialog::updateWeight(int i) void FontSettingDialog::accept_slots() { emit this->sendFont(*this->charFormat); +} +/// +/// \brief FontSettingDialog::finished_slots +/// \param result +/// +void FontSettingDialog::finished_slots(int result) +{ // 释放链接 - disconnect(this,SIGNAL(sendFont(QTextCharFormat&)), - this->textBlock,SLOT(setCharFormatOnSelection(QTextCharFormat&))); + disconnect(this, + SIGNAL(sendFont(QTextCharFormat&)), + this->textBlock, + SLOT(setCharFormatOnSelection(QTextCharFormat&))); } diff --git a/ofdEditor/model/Widget/FontSettingDialog.h b/ofdEditor/model/Widget/FontSettingDialog.h index 8fdc5c7..e720d1e 100644 --- a/ofdEditor/model/Widget/FontSettingDialog.h +++ b/ofdEditor/model/Widget/FontSettingDialog.h @@ -66,6 +66,7 @@ private slots: void updateWeight(int i); // 字体粗细 void accept_slots(); // 向DocTextBlock传递成功事件 + void finished_slots(int result); // 结束时释放链接 }; diff --git a/ofdEditor/model/Widget/PageDialog.cpp b/ofdEditor/model/Widget/PageDialog.cpp index 86a5c58..e42677f 100644 --- a/ofdEditor/model/Widget/PageDialog.cpp +++ b/ofdEditor/model/Widget/PageDialog.cpp @@ -7,11 +7,12 @@ PageDialog* PageDialog::m_instance = NULL; -int toNearestInt(double n) -{ - return n + 0.5; -} + +/// +/// \brief PageDialog::getInstance +/// \return +/// PageDialog *PageDialog::getInstance() { if(m_instance != NULL) @@ -39,6 +40,7 @@ void PageDialog::DestoryInstance() /// \param default_working_y /// void PageDialog::init( + DocPassage* passage, DocPage *current_page, double default_width, double default_height, @@ -48,28 +50,54 @@ void PageDialog::init( double default_working_x, double default_working_y) { + + this->passage = passage; this->current_page = current_page; + this->changed_page_numbers.clear(); + + ui->CurrentPageRadioButton->setChecked(true); // 选择 当前页 + ui->CurrentPageRadioButton->click(); // 点击,发送信号 + + ui->CurrentSelectPageSize->setCurrentIndex(0); // 暂时默认置零 - if (current_page) + if (this->current_page) { -// qDebug() << "Current_page width in pixel = " << current_page->size().width(); -// qDebug() << "Current_page height in pixel = " << current_page->size().height(); - ui->CurrentPageSizeWidth->setValue(toNearestInt(UnitTool::pixelToMM(current_page->size().width()))); - ui->CurrentPageSizeHeight->setValue(toNearestInt(UnitTool::pixelToMM(current_page->size().height()))); - //Working area to be implemented!!!! - ui->CurrentWorkingAreaWidth->setValue(toNearestInt(current_page->getContentWidth())); - ui->CurrentWorkingAreaHeight->setValue(toNearestInt(current_page->getContentHeight())); - ui->CurrentWorkingAreaX->setValue(toNearestInt(current_page->getContentX())); - ui->CurrentWorkingAreaY->setValue(toNearestInt(current_page->getContentY())); + ui->CurrentPageSizeWidth->setValue( + toNearestInt( + current_page->getWidth())); + ui->CurrentPageSizeHeight->setValue( + toNearestInt( + current_page->getHeight())); + +// //Working area to be implemented!!!! + ui->CurrentWorkingAreaWidth->setValue( + toNearestInt( + current_page->getContentWidth())); + ui->CurrentWorkingAreaHeight->setValue( + toNearestInt( + current_page->getContentHeight())); + ui->CurrentWorkingAreaX->setValue( + toNearestInt( + current_page->getContentX())); + ui->CurrentWorkingAreaY->setValue( + toNearestInt( + current_page->getContentY())); + + ui->DefaultPageSizeWidth->setValue( + toNearestInt(default_height)); + ui->DefaultPageSizeHeight->setValue( + toNearestInt(default_width)); - ui->DefaultPageSizeWidth->setValue(toNearestInt(default_height)); - ui->DefaultPageSizeHeight->setValue(toNearestInt(default_width)); //Working area to be implemented!!!! ui->DefaultSetWorkingAreaChecked->setChecked(using_working_area); - ui->DefaultWorkingAreaWidth->setValue(toNearestInt(default_working_width)); - ui->DefaultWorkingAreaHeight->setValue(toNearestInt(default_working_height)); - ui->DefaultWorkingAreaX->setValue(toNearestInt(default_working_x)); - ui->DefaultWorkingAreaY->setValue(toNearestInt(default_working_y)); + ui->DefaultWorkingAreaWidth->setValue( + toNearestInt(default_working_width)); + ui->DefaultWorkingAreaHeight->setValue( + toNearestInt(default_working_height)); + ui->DefaultWorkingAreaX->setValue( + toNearestInt(default_working_x)); + ui->DefaultWorkingAreaY->setValue( + toNearestInt(default_working_y)); this->isDefaultPageSizeChanged = false; // 是否修改了默认尺寸 @@ -132,52 +160,7 @@ PageDialog::PageDialog(QWidget *parent) :QDialog(parent),ui(new Ui::PageDialog) { ui->setupUi(this); - this->initUI(); this->initConnect(); - - qDebug() << "Constructor executed finished"; -} - -/// -/// \brief PageDialog::initUI -/// 初始化界面 -void PageDialog::initUI() -{ - - ui->CurrentSetWorkingAreaChecked->setChecked(false); - ui->CurrentWorkingAreaWidth->setEnabled(false); - ui->CurrentWorkingAreaHeight->setEnabled(false); - ui->CurrentWorkingAreaX->setEnabled(false); - ui->CurrentWorkingAreaY->setEnabled(false); - ui->CurrentWorkingAreaWidth->setValue(ui->CurrentPageSizeWidth->value()); - ui->CurrentWorkingAreaHeight->setValue(ui->CurrentPageSizeHeight->value()); - ui->CurrentWorkingAreaX->setValue(0.0); - ui->CurrentWorkingAreaY->setValue(0.0); - - ui->DefaultSetWorkingAreaChecked->setChecked(false); - ui->DefaultWorkingAreaWidth->setEnabled(false); - ui->DefaultWorkingAreaHeight->setEnabled(false); - ui->DefaultWorkingAreaX->setEnabled(false); - ui->DefaultWorkingAreaY->setEnabled(false); - ui->DefaultWorkingAreaWidth->setValue(ui->DefaultPageSizeWidth->value()); - ui->DefaultWorkingAreaHeight->setValue(ui->DefaultPageSizeHeight->value()); - ui->DefaultWorkingAreaX->setValue(0.0); - ui->DefaultWorkingAreaY->setValue(0.0); - - ui->CurrentSelectPageSize->setEditable(true); - ui->DefaultSelectPageSize->setEditable(true); - - ui->CurrentPageCheckBox->setChecked(true); - ui->AllPagesCheckBox->setChecked(false); - ui->PageRangeCheckBox->setChecked(false); - ui->SpecificPageCheckBox->setChecked(false); - - ui->PageRangeLowerBound->setEnabled(false); - ui->PageRangeUpperBound->setEnabled(false); - ui->PageRangeLowerBound->setValue(1); - ui->PageRangeUpperBound->setValue(passage->getPages().size()); - ui->SpecificPage->setEnabled(false); - } /// @@ -187,66 +170,75 @@ void PageDialog::initUI() void PageDialog::initConnect() { //创建信号槽 - this->connect(ui->PageRangeCheckBox, - SIGNAL(clicked(bool)), + + // 四种模式的选择 + // 当前页 + this->connect(ui->CurrentPageRadioButton, + SIGNAL(toggled(bool)), this, - SLOT(on_PageRangeCheckBox_toggled(bool))); - this->connect(ui->CurrentSelectPageSize, - SIGNAL(currentIndexChanged(QString)), + SLOT(onCurrentPageRadioButtonToggled(bool))); + // 所有页面 + this->connect(ui->AllPagesRadioButton, + SIGNAL(toggled(bool)), this, - SLOT(on_CurrentSelectPageSize_currentIndexChanged(QString))); - this->connect(ui->DefaultSelectPageSize, - SIGNAL(currentIndexChanged(QString)), + SLOT(onAllPagesRadioButtonToggled(bool))); + // 页面范围 + this->connect(ui->PageRangeRadioButton, + SIGNAL(toggled(bool)), this, - SLOT(on_DefaultSelectPageSize_currentIndexChanged(QString))); - this->connect(ui->SpecificPageCheckBox, - SIGNAL(clicked(bool)), + SLOT(onPageRangeRadioButtonToggled(bool))); + // 特殊页面 + this->connect(ui->SpecificPageRadioButton, + SIGNAL(toggled(bool)), this, - SLOT(on_SpecificPageCheckBox_clicked(bool))); + SLOT(onSpecificPageRadioButtonToggled(bool))); + + this->connect(ui->CurrentSetWorkingAreaChecked, SIGNAL(clicked(bool)), this, SLOT(on_CurrentSetWorkingAreaChecked_clicked(bool))); + this->connect(ui->DefaultSetWorkingAreaChecked, SIGNAL(clicked(bool)), this, SLOT(on_DefaultSetWorkingAreaChecked_clicked(bool))); + this->connect(ui->CurrentPageSizeHeight, SIGNAL(editingFinished()), this, SLOT(on_CurrentPageSize_valueChanged())); + this->connect(ui->CurrentPageSizeWidth, SIGNAL(editingFinished()), this, SLOT(on_CurrentPageSize_valueChanged())); + this->connect(ui->OkAndCancel, SIGNAL(accepted()), this, SLOT(accept())); + this->connect(ui->OkAndCancel, SIGNAL(rejected()), this, SLOT(reject())); - this->connect(ui->CurrentPageCheckBox, - SIGNAL(toggled(bool)), - this, - SLOT(on_CurrentPageCheckBox_toggled(bool))); - this->connect(ui->AllPagesCheckBox, - SIGNAL(toggled(bool)), - this, - SLOT(on_AllPagesCheckBox_toggled(bool))); + this->connect(ui->PageRangeLowerBound, SIGNAL(valueChanged(int)), this, SLOT(page_range_range_changed())); + this->connect(ui->PageRangeUpperBound, SIGNAL(valueChanged(int)), this, SLOT(page_range_range_changed())); + this->connect(ui->PageRangeLowerBound, SIGNAL(valueChanged(int)), this, SLOT(changed_page_range_changed())); + this->connect(ui->PageRangeUpperBound, SIGNAL(valueChanged(int)), this, @@ -263,22 +255,27 @@ void PageDialog::initConnect() SIGNAL(valueChanged(double)), this, SLOT(on_DefaultSizeChanged(double))); + this->connect(ui->DefaultPageSizeHeight, SIGNAL(valueChanged(double)), this, SLOT(on_DefaultSizeChanged(double))); + this->connect(ui->DefaultWorkingAreaHeight, SIGNAL(valueChanged(double)), this, SLOT(on_DefaultSizeChanged(double))); + this->connect(ui->DefaultWorkingAreaWidth, SIGNAL(valueChanged(double)), this, SLOT(on_DefaultSizeChanged(double))); + this->connect(ui->DefaultWorkingAreaX, SIGNAL(valueChanged(double)), this, SLOT(on_DefaultSizeChanged(double))); + this->connect(ui->DefaultWorkingAreaY, SIGNAL(valueChanged(double)), this, @@ -286,6 +283,46 @@ void PageDialog::initConnect() } +/// +/// \brief PageDialog::caculatePages +/// 计算选择了哪些页面 +/// +void PageDialog::caculatePages() +{ + if(ui->CurrentPageRadioButton->isChecked()) + { + // 当前页 + int i; + if (current_page) + { + for (i = 0; i < passage->getPages()->size(); i++) + if (passage->getPages()->operator [](i) == current_page) + break; + } + else i = 1; + changed_page_numbers.push_back(i+1); + } + else if(ui->AllPagesRadioButton->isChecked()) + { + // 所有页面 + for (int i = 0; i < passage->getPages()->size(); i++) + changed_page_numbers.push_back(i + 1); + } + else if(ui->PageRangeRadioButton->isChecked()) + { + // 页面范围 + int start = ui->PageRangeLowerBound->value(); // 开始 + int end = ui->PageRangeUpperBound->value(); // 截止 + for (int j = start ; j <= end; j++) + changed_page_numbers.push_back(j); + } + else if(ui->SpecificPageRadioButton->isChecked()) + { + // 特殊页面 + + } +} + void PageDialog::on_CurrentSelectPageSize_currentIndexChanged(const QString &arg1) { if (arg1 == tr("A4")) @@ -416,82 +453,101 @@ void PageDialog::on_CurrentPageSize_valueChanged() ui->CurrentSelectPageSize->setCurrentIndex(ui->CurrentSelectPageSize->findText(tr("Customized"))); } - - - -void PageDialog::on_PageRangeCheckBox_toggled(bool checked) +/// +/// \brief PageDialog::onCurrentPageRadioButtonToggled +/// 选择只选择当前页 +/// \param checked +/// +void PageDialog::onCurrentPageRadioButtonToggled(bool checked) { - if (checked) - { - ui->PageRangeLowerBound->setEnabled(true); - ui->PageRangeUpperBound->setEnabled(true); - int i; - if (current_page) - { - for (i = 0; i < passage->getPages().size(); i++) - if (passage->getPages()[i] == current_page) - break; - } - else i = 1; - ui->PageRangeLowerBound->setValue(i); - ui->PageRangeUpperBound->setValue(passage->getPages().size()); - ui->PageRangeLowerBound->setRange(1, ui->PageRangeUpperBound->value()); - ui->PageRangeUpperBound->setRange(ui->PageRangeLowerBound->value(), passage->getPages().size()); - for (int j = i; j <= passage->getPages().size(); j++) - changed_page_numbers.push_back(j); - } - else + if(checked) { + // 页码范围 ui->PageRangeLowerBound->setEnabled(false); ui->PageRangeUpperBound->setEnabled(false); + // 特定 + ui->SpecificPage->setEnabled(false); + ui->SpecificPage->setText(""); } } -void PageDialog::on_SpecificPageCheckBox_toggled(bool checked) +/// +/// \brief PageDialog::onAllPagesRadioButtonToggled +/// \param checked +/// +void PageDialog::onAllPagesRadioButtonToggled(bool checked) { - if (checked) - { - ui->SpecificPage->setEnabled(true); - } - else + if(checked) { + // 页码范围 + ui->PageRangeLowerBound->setEnabled(false); + ui->PageRangeUpperBound->setEnabled(false); + + // 特定 ui->SpecificPage->setEnabled(false); + ui->SpecificPage->setText(""); } } -void PageDialog::on_CurrentPageCheckBox_toggled(bool checked) +/// +/// \brief PageDialog::onPageRangeRadioButtonToggled +/// \param checked +/// +void PageDialog::onPageRangeRadioButtonToggled(bool checked) { - if (checked) + if(checked) { - changed_page_numbers.clear(); + // 页码范围 + ui->PageRangeLowerBound->setEnabled(true); + ui->PageRangeUpperBound->setEnabled(true); + int i; if (current_page) { - for (i = 0; i < passage->getPages().size(); i++) - if (passage->getPages()[i] == current_page) + for (i = 0; i < passage->getPages()->size(); i++) + if (passage->getPages()->operator [](i) == current_page) break; } else i = 1; - changed_page_numbers.push_back(i); + + ui->PageRangeLowerBound->setValue(i); + ui->PageRangeUpperBound->setValue( + passage->getPages()->size()); + ui->PageRangeLowerBound->setRange( + 1, + ui->PageRangeUpperBound->value()); + ui->PageRangeUpperBound->setRange( + ui->PageRangeLowerBound->value(), + passage->getPages()->size()); + + // 特定 + ui->SpecificPage->setEnabled(false); + ui->SpecificPage->setText(""); } } -void PageDialog::on_AllPagesCheckBox_toggled(bool checked) +void PageDialog::onSpecificPageRadioButtonToggled(bool checked) { - if (checked) + if(checked) { - changed_page_numbers.clear(); - int i; - for (i = 0; i < passage->getPages().size(); i++) - changed_page_numbers.push_back(i + 1); + // 页码范围 + ui->PageRangeLowerBound->setEnabled(false); + ui->PageRangeUpperBound->setEnabled(false); + + // 特定 + ui->SpecificPage->setEnabled(true); } } void PageDialog::page_range_range_changed() { - ui->PageRangeLowerBound->setRange(1, ui->PageRangeUpperBound->value()); - ui->PageRangeUpperBound->setRange(ui->PageRangeLowerBound->value(), passage->getPages().size()); + ui->PageRangeLowerBound->setRange( + 1, + ui->PageRangeUpperBound->value()); + ui->PageRangeUpperBound->setRange( + ui->PageRangeLowerBound->value(), + passage->getPages()->size()); } void PageDialog::changed_page_range_changed() @@ -501,17 +557,22 @@ void PageDialog::changed_page_range_changed() changed_page_numbers.push_back(j); } +/// +/// \brief PageDialog::emitInformation +/// void PageDialog::emitInformation() { - - emit this->modifyPageSize(&changed_page_numbers, - ui->CurrentPageSizeWidth->value(), - ui->CurrentPageSizeHeight->value(), - ui->CurrentSetWorkingAreaChecked->isChecked(), - ui->CurrentWorkingAreaWidth->value(), - ui->CurrentWorkingAreaHeight->value(), - ui->CurrentWorkingAreaX->value(), - ui->CurrentWorkingAreaY->value()); + this->caculatePages(); // 计算选择的页数 + + emit this->modifyPageSize( + &changed_page_numbers, + ui->CurrentPageSizeWidth->value(), + ui->CurrentPageSizeHeight->value(), + ui->CurrentSetWorkingAreaChecked->isChecked(), + ui->CurrentWorkingAreaWidth->value(), + ui->CurrentWorkingAreaHeight->value(), + ui->CurrentWorkingAreaX->value(), + ui->CurrentWorkingAreaY->value()); if(isDefaultPageSizeChanged) { diff --git a/ofdEditor/model/Widget/PageDialog.h b/ofdEditor/model/Widget/PageDialog.h index 839aa14..b649101 100644 --- a/ofdEditor/model/Widget/PageDialog.h +++ b/ofdEditor/model/Widget/PageDialog.h @@ -24,63 +24,57 @@ public: static PageDialog* getInstance(); // 获得单例 static void DestoryInstance(); // 销毁实例 - void init(DocPage * current_page, - double default_width, - double default_height, - bool using_working_area, - double default_working_width, - double default_working_height, - double default_working_x, - double default_working_y); // 初始化时调用 - + void init( + DocPassage* passage, + DocPage * current_page, + double default_width, + double default_height, + bool using_working_area, + double default_working_width, + double default_working_height, + double default_working_x, + double default_working_y); // 初始化时调用 ~PageDialog(); private: explicit PageDialog(QWidget *parent = 0); // 构造函数 - void initUI(); void initConnect(); + int toNearestInt(double n){ return n + 0.5; } static PageDialog* m_instance; + void caculatePages(); + private slots: void on_CurrentSelectPageSize_currentIndexChanged(const QString &arg1); - void on_DefaultSelectPageSize_currentIndexChanged(const QString &arg1); - void on_SpecificPageCheckBox_clicked(bool checked); - void on_CurrentSetWorkingAreaChecked_clicked(bool checked); - void on_DefaultSetWorkingAreaChecked_clicked(bool checked); - - void on_DefaultSizeChanged(double value); // 用来判断是否有修改过默认值 - + void on_DefaultSizeChanged(double value); // 用来判断是否有修改过默认值 void on_CurrentPageSize_valueChanged(); - void on_PageRangeCheckBox_toggled(bool checked); - - void on_SpecificPageCheckBox_toggled(bool checked); - - void on_CurrentPageCheckBox_toggled(bool checked); - - void on_AllPagesCheckBox_toggled(bool checked); + // 选择应用类型 + void onCurrentPageRadioButtonToggled(bool checked); + void onAllPagesRadioButtonToggled(bool checked); + void onPageRangeRadioButtonToggled(bool checked); + void onSpecificPageRadioButtonToggled(bool checked); void page_range_range_changed(); - void changed_page_range_changed(); - void emitInformation(); signals: - void modifyPageSize(QVector * ch_pages, - double _width, - double _height, - bool isUsingWorkingArea, - double contentWidth, - double contentHeight, - double contentX, - double contentY); + void modifyPageSize( + QVector * ch_pages, + double _width, + double _height, + bool isUsingWorkingArea, + double contentWidth, + double contentHeight, + double contentX, + double contentY); void modifyDefaultPageSize( double default_width, @@ -89,15 +83,13 @@ signals: double default_contentWidth, double default_contentHeight, double default_contentX, - double default_contentY - ); + double default_contentY); private: Ui::PageDialog *ui; DocPassage *passage; QVector changed_page_numbers; DocPage * current_page; - bool isDefaultPageSizeChanged; }; diff --git a/ofdEditor/model/Widget/PageDialog.ui b/ofdEditor/model/Widget/PageDialog.ui index c2c0917..b96b1af 100644 --- a/ofdEditor/model/Widget/PageDialog.ui +++ b/ofdEditor/model/Widget/PageDialog.ui @@ -6,8 +6,8 @@ 0 0 - 465 - 456 + 549 + 620 @@ -335,36 +335,73 @@ 应用于 - - - - 10000 + + + + 当前页 + + + + + + + 所有页 + + + 页面范围 + + + + 页面范围 - + + + + 所有页 + + + + + + + 10000 + + + + 当前页 + + true + + + false + - - + + + + + - 所有页 + 特定页数 - - + + Agency FB @@ -372,14 +409,11 @@ - + - - - - + @@ -392,15 +426,8 @@ - - - - 特定页数 - - - - - + + Agency FB @@ -408,11 +435,11 @@ - + - + @@ -425,9 +452,16 @@ - + + + + + 特定页数 + + + @@ -777,11 +811,4 @@ - - - - true - - - diff --git a/ofdEditor/model/Widget/ParagraphFormatDialog.cpp b/ofdEditor/model/Widget/ParagraphFormatDialog.cpp index 3368198..91c9937 100644 --- a/ofdEditor/model/Widget/ParagraphFormatDialog.cpp +++ b/ofdEditor/model/Widget/ParagraphFormatDialog.cpp @@ -156,6 +156,9 @@ void ParagraphFormatDialog::init(const QTextBlockFormat &blockFormat) connect(this,SIGNAL(accepted()), this,SLOT(accept_slots())); + connect(this,SIGNAL(finished(int)), + this,SLOT(finished_slots(int))); + // 设置对齐部分 Qt::Alignment flag = blockFormat.alignment(); // 先获取对齐的样式 Qt::Alignment horizontalFlag; @@ -238,8 +241,17 @@ void ParagraphFormatDialog::accept_slots() QTextBlockFormat blockFormat = this->getQTextBlockFormat(); emit this->finished(blockFormat); +} + +/// +/// \brief ParagraphFormatDialog::finished_slots +/// \param value +/// +void ParagraphFormatDialog::finished_slots(int value) +{ disconnect(this, SIGNAL(finished(QTextBlockFormat&)), this->textBlock, - SLOT(setTextBlockFormat(QTextBlockFormat&))); // 断开信号与槽链接 + SLOT(setTextBlockFormat(QTextBlockFormat&))); // 断开信号与槽链接 + } diff --git a/ofdEditor/model/Widget/ParagraphFormatDialog.h b/ofdEditor/model/Widget/ParagraphFormatDialog.h index 1fdd41d..dae164b 100644 --- a/ofdEditor/model/Widget/ParagraphFormatDialog.h +++ b/ofdEditor/model/Widget/ParagraphFormatDialog.h @@ -46,6 +46,7 @@ private: private slots: void accept_slots(); // 用来绑定 QDialog的 accepted信号 + void finished_slots(int value); // 用来做窗口关闭后的最后处理 }; #endif // PARAGRAPHFORMATDIALOG_H -- Gitee From 8aa5ffaf99c0dacfd7fcf827c877ebdae825dc60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Tue, 8 Aug 2017 11:01:25 +0800 Subject: [PATCH 32/83] =?UTF-8?q?=E9=9B=86=E4=B8=AD=E4=BA=8EDocPage?= =?UTF-8?q?=E7=9A=84=E5=8F=B3=E9=94=AE=E8=8F=9C=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocPage.cpp | 45 ++++++++++++- ofdEditor/model/Doc/DocPage.h | 1 + ofdEditor/model/Doc/DocPassage.cpp | 8 +-- ofdEditor/model/Doc/DocTextBlock.cpp | 32 +++++++++- ofdEditor/model/Doc/DocTextBlock.h | 2 + ofdEditor/model/Widget/PageDialog.ui | 64 +++++-------------- .../start/ActionConnector/ActionConnector.cpp | 7 +- 7 files changed, 98 insertions(+), 61 deletions(-) diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index eeb7ca2..ee0ab16 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -247,7 +248,7 @@ void DocPage::setInsertBlockType(InsertBlockInfo &blockInfo) this->insertBlockInfo->layer = blockInfo.layer; // 层 this->insertBlockInfo->type = blockInfo.type; // 类型 - // qDebug()<<"Set InsertBlockInfo successfully!"; +// qDebug()<<"Set InsertBlockInfo successfully!"; } /** @@ -331,7 +332,46 @@ void DocPage::paintEvent(QPaintEvent *event) // qDebug()<<"Moving QPainter is Drawing"; } -// qDebug()<<"QPainter is Drawing"; + // qDebug()<<"QPainter is Drawing"; +} + +/// +/// \brief DocPage::contextMenuEvent +/// 实现右键菜单 +/// \param event +/// +void DocPage::contextMenuEvent(QContextMenuEvent *event) +{ + // event->globalPos() 是相对于屏幕的 + // event->pos() 相对于页面左上角 +// qDebug() << "Global Position: x" +// << event->globalX() +// << " ,Y " +// << event->globalY(); + +// qDebug() << "Position x: " +// << event->x() +// << "y:" +// << event->y(); + + QPoint pos = event->pos(); // 获得相对于页面的 + QList items = this->items(pos); // 获得某鼠标下的所有块 + qDebug() << "There are" + << items.size() + << " items at position " + << event->pos() + << " scene:" + << this->mapToScene(event->pos()); + + for(int i = 0; i < items.size(); i++) + { +// DocBlock* block = qobject_cast(items[i]); + if(block != NULL) + { + qDebug() << "qt cast success"; + } + } + } /** @@ -355,6 +395,7 @@ void DocPage::mouseDoubleClickEvent(QMouseEvent *event) */ void DocPage::mousePressEvent(QMouseEvent *event) { +// qDebug() << "mouse Press"; // 如果是加入新块状态 if(this->newBlockFlag == draw) diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index b265e98..8a6e441 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -80,6 +80,7 @@ public slots: protected: void paintEvent(QPaintEvent *event); + void contextMenuEvent(QContextMenuEvent *event); // 右键菜单 void mouseDoubleClickEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index 21afd38..c956406 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -742,8 +742,8 @@ void DocPassage::setCurrentActivedPage(DocPage *page) { this->_lastActivedPage = page; - int index = this->pages.indexOf(this->_lastActivedPage); - qDebug() << "The No." - << index - <<" page has been actived" ; +// int index = this->pages.indexOf(this->_lastActivedPage); +// qDebug() << "The No." +// << index +// <<" page has been actived" ; } diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 25e74a1..5b22ef3 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -130,6 +130,31 @@ int DocTextBlock::getContentLength() return content.length(); } +/// +/// \brief DocTextBlock::getMenu +/// 将文本块中间所需的菜单返回出来 +/// \return +/// +QMenu *DocTextBlock::getMenu() +{ + this->ContextMenu = createStandardContextMenu(); // 拓展标准菜单 + this->ContextMenu->addAction(this->actionBold); // 加粗 + this->ContextMenu->addAction(this->actionItalic); // 斜体 + this->ContextMenu->addAction(this->actionUnderline); // 下划线 + this->ContextMenu->addAction(this->actionColor); // 颜色 + this->ContextMenu->addSeparator(); // 分界线 + this->ContextMenu->addAction(this->actionParagraph); // 段落设置 + this->ContextMenu->addAction(this->actionFontSetTest); // 字体 + this->ContextMenu->addAction(this->actionRemove); // 移除操作 + + connect(this->ContextMenu, SIGNAL(aboutToHide()), + this,SLOT(contextMenuAboutToHideEvent())); // 测试 + + this->tempZValue = this->getBlock()->getZValue(); + + return this->ContextMenu; // 返回ContextMenu +} + /** * @Author Chaoqun * @brief 用来合并格式 @@ -689,7 +714,6 @@ void DocTextBlock::contextMenuEvent(QContextMenuEvent *event) this->ContextMenu->addAction(this->actionUnderline); // 下划线 this->ContextMenu->addAction(this->actionColor); // 颜色 this->ContextMenu->addSeparator(); // 分界线 -// this->ContextMenu->addAction(this->actionFontSet); // 字体设置 this->ContextMenu->addAction(this->actionParagraph); // 段落设置 this->ContextMenu->addAction(this->actionFontSetTest); // 字体 this->ContextMenu->addAction(this->actionRemove); // 移除操作 @@ -700,8 +724,10 @@ void DocTextBlock::contextMenuEvent(QContextMenuEvent *event) this->tempZValue = this->getBlock()->getZValue(); emit this->signals_setZValue(2000); -// QPointF global = this->getBlock()->mapToScene(event->globalPos()); // 获得场景坐标 -// this->ContextMenu->setParent(this->getPage()); +// qDebug() << "Global Position: x" +// << event->globalX() +// << " ,Y " +// << event->globalY(); // 展示菜单 this->ContextMenu->exec(event->globalPos()); diff --git a/ofdEditor/model/Doc/DocTextBlock.h b/ofdEditor/model/Doc/DocTextBlock.h index 25976e1..65f9ed7 100644 --- a/ofdEditor/model/Doc/DocTextBlock.h +++ b/ofdEditor/model/Doc/DocTextBlock.h @@ -38,6 +38,8 @@ public: public slots: + QMenu* getMenu(); // 获得该块的菜单成分 + void textBold(); // 将光标选择的文字粗体 void textBold(QTextCursor& cursor, int mode = 0); // 将给定光标选择的文字设置为粗体 void textUnderline(); // 下划线 diff --git a/ofdEditor/model/Widget/PageDialog.ui b/ofdEditor/model/Widget/PageDialog.ui index b96b1af..fbe268c 100644 --- a/ofdEditor/model/Widget/PageDialog.ui +++ b/ofdEditor/model/Widget/PageDialog.ui @@ -6,8 +6,8 @@ 0 0 - 549 - 620 + 465 + 456 @@ -17,7 +17,7 @@ - 0 + 1 @@ -349,58 +349,24 @@ - - - - 页面范围 - - - - - - 页面范围 - - - - - + - 所有页 + 特定页数 - + 10000 - - - - 当前页 - - - true - - - false - - - - + - - - - 特定页数 - - - - + @@ -413,7 +379,7 @@ - + @@ -426,7 +392,7 @@ - + @@ -439,7 +405,7 @@ - + @@ -452,13 +418,13 @@ - + - - + + - 特定页数 + 页面范围 diff --git a/ofdEditor/start/ActionConnector/ActionConnector.cpp b/ofdEditor/start/ActionConnector/ActionConnector.cpp index d79e5cb..d4e1495 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.cpp +++ b/ofdEditor/start/ActionConnector/ActionConnector.cpp @@ -78,10 +78,11 @@ void ActionConnector::addNewBlock(InsertBlockInfo& blockInfo) } // this->updateActivePassage(); // 更新文章 - DocPage * page = qobject_cast(this->passage->focusWidget()); +// DocPage * page = qobject_cast(this->passage->focusWidget()); + DocPage *page = this->passage->getLastedActivedPage(); // 获得最近操作过的页面 if(page == NULL) { - qDebug() <<"No Focus Widget"; + qDebug() <<"NO Last actived page"; return; } else @@ -89,7 +90,7 @@ void ActionConnector::addNewBlock(InsertBlockInfo& blockInfo) //插入文本框 if (blockInfo.type == DocPage::text) { - qDebug() << "get Focus Sucess"; +// qDebug() << "get Focus Sucess"; page->setBlockFlag(DocPage::draw); // 进入绘画状态 // InsertBlockInfo blockInfo(type,layer); // 设置插入文本框信息 -- Gitee From 0ba920c38fe25d7e96e9e018804aa789cc566766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Tue, 8 Aug 2017 20:03:45 +0800 Subject: [PATCH 33/83] =?UTF-8?q?=E5=B0=86=E6=96=87=E6=9C=AC=E6=A1=86?= =?UTF-8?q?=E7=9A=84=E5=8F=B3=E9=94=AE=E8=8F=9C=E5=8D=95=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E5=88=B0=E9=A1=B5=E9=9D=A2=E4=B8=8A=E6=9D=A5=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocBlock.cpp | 8 +- ofdEditor/model/Doc/DocBlock.h | 16 +- ofdEditor/model/Doc/DocImageBlock.cpp | 5 + ofdEditor/model/Doc/DocImageBlock.h | 4 + ofdEditor/model/Doc/DocPage.cpp | 45 +++-- ofdEditor/model/Doc/DocTextBlock.cpp | 188 +++++++----------- ofdEditor/model/Doc/DocTextBlock.h | 18 +- ofdEditor/model/Widget/FontSettingDialog.cpp | 11 - ofdEditor/model/Widget/FontSettingDialog.h | 2 - .../model/Widget/ParagraphFormatDialog.cpp | 11 - .../model/Widget/ParagraphFormatDialog.h | 1 - 11 files changed, 141 insertions(+), 168 deletions(-) diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index aa898aa..18c5c5e 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -359,10 +359,10 @@ void DocBlock::setWidget(QWidget *widget) void DocBlock::setWidget(DocTextBlock *textBlock) { // 建立connect - connect(textBlock,SIGNAL(signals_remove(DocTextBlock*)), - this,SLOT(remove())); // 和块做移除连接 - connect(textBlock,SIGNAL(signals_setZValue(qreal)), - this,SLOT(setZValue(qreal))); // 建立设置Z值的信号连接 +// connect(textBlock,SIGNAL(signals_remove(DocTextBlock*)), +// this,SLOT(remove())); // 和块做移除连接 +// connect(textBlock,SIGNAL(signals_setZValue(qreal)), +// this,SLOT(setZValue(qreal))); // 建立设置Z值的信号连接 textBlock->setBlock(this); // 给DocTextBlock设置引用 this->textBlock = textBlock; // 给DocBlock设置引用 diff --git a/ofdEditor/model/Doc/DocBlock.h b/ofdEditor/model/Doc/DocBlock.h index 3c2dcf6..36c3ac8 100644 --- a/ofdEditor/model/Doc/DocBlock.h +++ b/ofdEditor/model/Doc/DocBlock.h @@ -25,9 +25,22 @@ class MODELSHARED_EXPORT DocBlock { Q_OBJECT public: + enum { Type = UserType + 1 }; + int type() const + { + // Enable the use of qgraphicsitem_cast with this item. + return Type; + } + DocBlock(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); - enum RectAdjustStatus{blockNone , blockResize , blockMove}; // 对块的大小状态进行调整 + enum RectAdjustStatus + { + blockNone , + blockResize , + blockMove + }; // 对块的大小状态进行调整 + RectAdjustStatus rectAdjust; // 用来标识当前修改尺寸的状态 DocLayer * getLayer(){return this->layer;} // 获得所在的层 DocPage * getPage(); // 获得所在页 @@ -69,6 +82,7 @@ protected: void contextMenuEvent (QGraphicsSceneContextMenuEvent *event); // 邮件菜单吧 private: + DocBox boundary; // 该块的外包矩形 DocLayer * layer; // 该块在哪一个层之中 QSizeF blockSize; // 用来纪录大小 diff --git a/ofdEditor/model/Doc/DocImageBlock.cpp b/ofdEditor/model/Doc/DocImageBlock.cpp index 37a9268..4820c3d 100644 --- a/ofdEditor/model/Doc/DocImageBlock.cpp +++ b/ofdEditor/model/Doc/DocImageBlock.cpp @@ -101,6 +101,11 @@ DocBlock *DocImageBlock::getBlock() return this->block; } +QString DocImageBlock::getType() +{ + return tr("DocImageBlock"); +} + /** * @Author Pan * @brief 焦点聚焦,显示边框 diff --git a/ofdEditor/model/Doc/DocImageBlock.h b/ofdEditor/model/Doc/DocImageBlock.h index 33275c7..674d292 100644 --- a/ofdEditor/model/Doc/DocImageBlock.h +++ b/ofdEditor/model/Doc/DocImageBlock.h @@ -16,13 +16,17 @@ class MODELSHARED_EXPORT DocImageBlock : public QLabel { Q_OBJECT + public: + DocImageBlock(QWidget *parent = NULL); void setImage(QPixmap & pixmap); void setBlock(DocBlock * _block); bool isWidthHeightRatioLocked(); double getWidthHeightRatio(); DocBlock * getBlock(); //获取代理它的DocBlock + QString getType(); // 获得标识,来区分不同的块 + public slots: void imagePropertiesChanged(double new_width, double new_height, diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index ee0ab16..db6963f 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -344,15 +344,7 @@ void DocPage::contextMenuEvent(QContextMenuEvent *event) { // event->globalPos() 是相对于屏幕的 // event->pos() 相对于页面左上角 -// qDebug() << "Global Position: x" -// << event->globalX() -// << " ,Y " -// << event->globalY(); - -// qDebug() << "Position x: " -// << event->x() -// << "y:" -// << event->y(); + QMenu* menu = new QMenu(this->passage); // 让passage作为父亲 QPoint pos = event->pos(); // 获得相对于页面的 QList items = this->items(pos); // 获得某鼠标下的所有块 @@ -363,15 +355,44 @@ void DocPage::contextMenuEvent(QContextMenuEvent *event) << " scene:" << this->mapToScene(event->pos()); + QMenu* seletion = new QMenu(); + seletion->setTitle(tr("seletion")); + for(int i = 0; i < items.size(); i++) { -// DocBlock* block = qobject_cast(items[i]); - if(block != NULL) + // 将qgraphicsItem造型成为DocBlock + if(items[i]->type() == DocBlock::Type) { - qDebug() << "qt cast success"; + DocBlock* block = qgraphicsitem_cast(items[i]); + if(block != NULL) + { + qDebug() << "qt cast success"; + if(block->isTextBlock()) + { + // 如果是文本框 + DocTextBlock* textBlock = block->getTextBlock(); +// seletion->addAction(textBlock->getType()); + menu->addMenu(textBlock->getMenu()); + } + else if(block->isImageBlock()) + { + // 如果是图片 + DocImageBlock* imageBlock = block->getImageBlock(); + seletion->addAction(imageBlock->getType()); + } + } + else + { + qDebug() << "is not a Docblock class"; + } } + } + menu->addMenu(seletion); // 添加子菜单 + + menu->exec(event->globalPos()); // 执行菜单 + } /** diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 5b22ef3..5db642b 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -15,8 +15,8 @@ #include #include #include - - +#include +#include DocTextBlock::DocTextBlock(QWidget *parent) :QTextEdit(parent) @@ -130,6 +130,16 @@ int DocTextBlock::getContentLength() return content.length(); } +/// +/// \brief DocTextBlock::getType +/// \return +/// +QString DocTextBlock::getType() +{ + QString summary = this->document()->toPlainText().left(5); + return tr("DocTextBlock") + summary; +} + /// /// \brief DocTextBlock::getMenu /// 将文本块中间所需的菜单返回出来 @@ -137,20 +147,17 @@ int DocTextBlock::getContentLength() /// QMenu *DocTextBlock::getMenu() { - this->ContextMenu = createStandardContextMenu(); // 拓展标准菜单 - this->ContextMenu->addAction(this->actionBold); // 加粗 - this->ContextMenu->addAction(this->actionItalic); // 斜体 - this->ContextMenu->addAction(this->actionUnderline); // 下划线 - this->ContextMenu->addAction(this->actionColor); // 颜色 - this->ContextMenu->addSeparator(); // 分界线 - this->ContextMenu->addAction(this->actionParagraph); // 段落设置 - this->ContextMenu->addAction(this->actionFontSetTest); // 字体 - this->ContextMenu->addAction(this->actionRemove); // 移除操作 - - connect(this->ContextMenu, SIGNAL(aboutToHide()), - this,SLOT(contextMenuAboutToHideEvent())); // 测试 - this->tempZValue = this->getBlock()->getZValue(); + // 检验粘贴键的状态 + QClipboard *board = QApplication::clipboard(); + if(board->text().length() <= 0) + { + this->actionPaste->setEnabled(false); + } + else + { + this->actionPaste->setEnabled(true); + } return this->ContextMenu; // 返回ContextMenu } @@ -533,44 +540,13 @@ void DocTextBlock::setTextColor(QTextCursor& cursor,QColor color) mergeFormatOnWordOrSelection(cursor,fmt); } -/** - * @Author Chaoqun - * @brief 通过字体小窗口设置字体 - * @param void - * @return void - * @date 2017/05/21 - */ -void DocTextBlock::textFontDialog() -{ - bool btn_ok; // 确认按键 - QTextCursor cursor = this->textCursor(); - QTextCharFormat currentFormat = cursor.charFormat(); -// QTextCharFormat currentFormat = -// this->currentCharFormat(); // 当前选择文字的样式 - QFont oldFont = currentFormat.font(); // 获取之前的字体样式 - - QFont newFont = QFontDialog::getFont( - &btn_ok, oldFont,NULL,tr("Set the font") - ); // 选择字体框 - - if(btn_ok) - { - this->setFont(newFont); // 设置字体 - } - else - { - // 用户取消了操作,不做处理 - qDebug() << "Cancel select Font!"; - } - - -} - +/// +/// \brief DocTextBlock::customFontDialog +/// 自定义的字体设置窗口 +/// void DocTextBlock::customFontDialog() { -// FontSettingDialog * font = new FontSettingDialog(this,0); -// font->exec(); FontSettingDialog* font = FontSettingDialog::getInstance(); // 获取实例 font->init(this); font->exec(); @@ -590,12 +566,11 @@ void DocTextBlock::setTextBlockFormat(QTextBlockFormat &blockFormat) { // 如果没有选择文字段落 cursor.select(QTextCursor::WordUnderCursor); - qDebug() << "cursor has no selection!"; +// qDebug() << "cursor has no selection!"; } cursor.setBlockFormat(blockFormat); - // 发出信号 emit this->signals_currentBlockFormatChanged(blockFormat); @@ -617,7 +592,7 @@ void DocTextBlock::setTextBlockFormat( { // 如果没有选择文字段落 cursor.select(QTextCursor::WordUnderCursor); - qDebug() << "cursor has no selection!"; +// qDebug() << "cursor has no selection!"; } cursor.setBlockFormat(blockFormat); @@ -639,7 +614,7 @@ void DocTextBlock::setCharFormatOnWordOrSelection( { // 如果没有选择文字段落 cursor.select(QTextCursor::WordUnderCursor); - qDebug() << "cursor has no selection!"; +// qDebug() << "cursor has no selection!"; } cursor.setCharFormat(format); // 设置光标下的 QTextCharFormat this->setCurrentCharFormat(format); // 合并当前的 QTextCharFormat @@ -698,43 +673,6 @@ void DocTextBlock::serCharFormatOnSelection( cursor.setCharFormat(format); // 设置字符格式 } -/** - * @Author Chaoqun - * @brief 显示右键菜单 - * @param QContextMenuEvent *event - * @return void - * @date 2017/05/20 - */ -void DocTextBlock::contextMenuEvent(QContextMenuEvent *event) -{ - - this->ContextMenu = createStandardContextMenu(); // 拓展标准菜单 - this->ContextMenu->addAction(this->actionBold); // 加粗 - this->ContextMenu->addAction(this->actionItalic); // 斜体 - this->ContextMenu->addAction(this->actionUnderline); // 下划线 - this->ContextMenu->addAction(this->actionColor); // 颜色 - this->ContextMenu->addSeparator(); // 分界线 - this->ContextMenu->addAction(this->actionParagraph); // 段落设置 - this->ContextMenu->addAction(this->actionFontSetTest); // 字体 - this->ContextMenu->addAction(this->actionRemove); // 移除操作 - - connect(this->ContextMenu, SIGNAL(aboutToHide()), - this,SLOT(contextMenuAboutToHideEvent())); // 测试 - - this->tempZValue = this->getBlock()->getZValue(); - emit this->signals_setZValue(2000); - -// qDebug() << "Global Position: x" -// << event->globalX() -// << " ,Y " -// << event->globalY(); - - // 展示菜单 - this->ContextMenu->exec(event->globalPos()); - - -} - /** * @Author Chaoqun * @brief 焦点聚焦,显示边框 @@ -765,19 +703,6 @@ void DocTextBlock::focusOutEvent(QFocusEvent *e) QTextEdit::focusOutEvent(e); } -/** - * @Author Chaoqun - * @brief 用来当右键菜单消失时,调整块的深度 - * @param 参数 - * @return 返回值 - * @date 2017/06/22 - */ -void DocTextBlock::contextMenuAboutToHideEvent() -{ - emit this->signals_setZValue(this->tempZValue); // 还原Z值 - this->focusInEvent(new QFocusEvent(QEvent::FocusIn)); // 关注它 -} - /** * @Author Chaoqun * @brief 用来检查当前的格式是否发生改变,并向外界发出信号 @@ -844,6 +769,11 @@ void DocTextBlock::emitFormatSignals() emit this->signals_currentTextBlock(this); } +void DocTextBlock::printTestMessage() +{ + qDebug() << "Click Right Button"; +} + /** * @Author Chaoqun * @brief 初始化函数 @@ -875,6 +805,7 @@ void DocTextBlock::init() this, SLOT(checkCurrentFormat())); this->initAcitons(); // 初始化QAction相关 + this->initMenu(); // 初始化右键菜单 } /** @@ -923,24 +854,11 @@ void DocTextBlock::initAcitons() this->connect(this->actionColor,SIGNAL(triggered()), this,SLOT(setTextColor())); - // 字体 - this->actionFontSet = new QAction(tr("Font"),NULL); - this->actionFontSet->setPriority(QAction::LowPriority); - - this->connect(this->actionFontSet,SIGNAL(triggered()), - this,SLOT(textFontDialog())); - // 段落 this->actionParagraph = new QAction(tr("Paragraph"),NULL); this->connect(this->actionParagraph,SIGNAL(triggered()), this,SLOT(textParagraph())); - // 移除文本框 - this->actionRemove = new QAction(tr("Remove"),NULL); - - this->connect(this->actionRemove,SIGNAL(triggered(bool)), - this,SLOT(remove())); // 链接信号,可以移除文本框 - // 字体窗口测试 this->actionFontSetTest = new QAction(tr("FontDialogTest"),NULL); this->connect(this->actionFontSetTest, SIGNAL(triggered()), @@ -965,3 +883,39 @@ void DocTextBlock::initFormat() this->mergeCurrentCharFormat(charFormat); } + +/// +/// \brief DocTextBlock::initMenu +/// 初始化右键菜单 +/// +void DocTextBlock::initMenu() +{ + this->ContextMenu = new QMenu(tr("DocTextBlock")); + + // 基本功能 + this->actionCut = this->ContextMenu->addAction(tr("Cut")); // 剪切 + this->actionCopy = this->ContextMenu->addAction(tr("Copy")); // 复制 + this->actionPaste = this->ContextMenu->addAction(tr("Paste")); // 粘贴 + this->actionSelectAll = this->ContextMenu->addAction(tr("SelectAll")); // 全选 + + connect(this->actionCut, SIGNAL(triggered(bool)), + this, SLOT(cut())); + connect(this->actionCopy, SIGNAL(triggered(bool)), + this, SLOT(copy())); + connect(this->actionPaste, SIGNAL(triggered(bool)), + this, SLOT(paste())); + connect(this->actionSelectAll, SIGNAL(triggered(bool)), + this, SLOT(selectAll())); + + this->ContextMenu->addSeparator(); // 增加分界线 + this->ContextMenu->addAction(this->actionBold); // 加粗 + this->ContextMenu->addAction(this->actionItalic); // 斜体 +// this->ContextMenu->addAction(this->actionUnderline); // 下划线 + this->ContextMenu->addAction(this->actionColor); // 颜色 + + this->ContextMenu->addSeparator(); // 分界线 + this->ContextMenu->addAction(this->actionFontSetTest); // 字体 + this->ContextMenu->addAction(this->actionParagraph); // 段落设置 + + +} diff --git a/ofdEditor/model/Doc/DocTextBlock.h b/ofdEditor/model/Doc/DocTextBlock.h index 65f9ed7..9228592 100644 --- a/ofdEditor/model/Doc/DocTextBlock.h +++ b/ofdEditor/model/Doc/DocTextBlock.h @@ -33,8 +33,9 @@ public: DocPage* getPage(); // 获得页 DocLayer* getLayer(); // 获得层 DocBlock* getBlock(); // 获得Block - QString getContent(); // 获得TextBlock中的所有文本 + QString getContent(); // 获得TextBlock中的所有文本 int getContentLength(); // 获得内部文字长度 + QString getType(); // 获得标识,来区分不同的块 public slots: @@ -96,38 +97,37 @@ public slots: void showBoundaryFrame(bool show); // 是否显示边界 protected: - - void contextMenuEvent(QContextMenuEvent *event); // 右键菜单重载 void focusInEvent(QFocusEvent *e); void focusOutEvent(QFocusEvent *e); private slots: - void contextMenuAboutToHideEvent(); // 右键菜单隐藏绑定事件 void checkCurrentFormat(); // 检查当前的格式是否发生改变 void emitFormatSignals(); // 发射格式的信号 + void printTestMessage(); // 测试右键信号是否畅通 private: QString content; // 文字内容 void init(); // 初始化 void initAcitons(); // 初始化事件 void initFormat(); // 初始化文字样式 + void initMenu(); // 初始化右键菜单 // QActions + QAction * actionCut; // 剪贴 + QAction * actionCopy; // 复制 + QAction * actionPaste; // 粘贴 + QAction * actionSelectAll; // 全选 + QAction * actionBold; // 加粗 QAction * actionUnderline; // 下划线 QAction * actionItalic; // 斜体 QAction * actionColor; // 设置颜色 - QAction * actionFontSet; // 设置字体 QAction * actionParagraph; // 设置段落 - QAction * actionRemove; // 移除文本框 - QAction * actionFontSetTest; // 新字体窗口测试 QMenu * ContextMenu; // 右键菜单 DocBlock* block; // 本类型所在的block - qreal tempZValue; // 存储临时Z值 - QTextBlockFormat _currentBlockFormat; // 当前BlockFormat QTextCharFormat _currentCharFormat; // 当前 diff --git a/ofdEditor/model/Widget/FontSettingDialog.cpp b/ofdEditor/model/Widget/FontSettingDialog.cpp index 75ee1ba..fe6118c 100644 --- a/ofdEditor/model/Widget/FontSettingDialog.cpp +++ b/ofdEditor/model/Widget/FontSettingDialog.cpp @@ -162,8 +162,6 @@ void FontSettingDialog::initConnect() connect(this, SIGNAL(accepted()), this, SLOT(accept_slots())); // 窗口接受确认的信号 - connect(this,SIGNAL(finished(int)), - this,SLOT(finished_slots(int))); // 释放链接 } /** @@ -513,18 +511,9 @@ void FontSettingDialog::updateWeight(int i) void FontSettingDialog::accept_slots() { emit this->sendFont(*this->charFormat); -} -/// -/// \brief FontSettingDialog::finished_slots -/// \param result -/// -void FontSettingDialog::finished_slots(int result) -{ - // 释放链接 disconnect(this, SIGNAL(sendFont(QTextCharFormat&)), this->textBlock, SLOT(setCharFormatOnSelection(QTextCharFormat&))); - } diff --git a/ofdEditor/model/Widget/FontSettingDialog.h b/ofdEditor/model/Widget/FontSettingDialog.h index e720d1e..2ae1f53 100644 --- a/ofdEditor/model/Widget/FontSettingDialog.h +++ b/ofdEditor/model/Widget/FontSettingDialog.h @@ -51,7 +51,6 @@ private: private slots: void updatePreview(const QTextCharFormat& charFormat); // 设置为预览,用来更新预览文字的效果 - void init(); // 初始化界面 void changeCharFormat(const QTextCharFormat& charFormat); // 根据字体更新界面选项 @@ -66,7 +65,6 @@ private slots: void updateWeight(int i); // 字体粗细 void accept_slots(); // 向DocTextBlock传递成功事件 - void finished_slots(int result); // 结束时释放链接 }; diff --git a/ofdEditor/model/Widget/ParagraphFormatDialog.cpp b/ofdEditor/model/Widget/ParagraphFormatDialog.cpp index 91c9937..72a2301 100644 --- a/ofdEditor/model/Widget/ParagraphFormatDialog.cpp +++ b/ofdEditor/model/Widget/ParagraphFormatDialog.cpp @@ -156,9 +156,6 @@ void ParagraphFormatDialog::init(const QTextBlockFormat &blockFormat) connect(this,SIGNAL(accepted()), this,SLOT(accept_slots())); - connect(this,SIGNAL(finished(int)), - this,SLOT(finished_slots(int))); - // 设置对齐部分 Qt::Alignment flag = blockFormat.alignment(); // 先获取对齐的样式 Qt::Alignment horizontalFlag; @@ -241,14 +238,6 @@ void ParagraphFormatDialog::accept_slots() QTextBlockFormat blockFormat = this->getQTextBlockFormat(); emit this->finished(blockFormat); -} - -/// -/// \brief ParagraphFormatDialog::finished_slots -/// \param value -/// -void ParagraphFormatDialog::finished_slots(int value) -{ disconnect(this, SIGNAL(finished(QTextBlockFormat&)), this->textBlock, diff --git a/ofdEditor/model/Widget/ParagraphFormatDialog.h b/ofdEditor/model/Widget/ParagraphFormatDialog.h index dae164b..1fdd41d 100644 --- a/ofdEditor/model/Widget/ParagraphFormatDialog.h +++ b/ofdEditor/model/Widget/ParagraphFormatDialog.h @@ -46,7 +46,6 @@ private: private slots: void accept_slots(); // 用来绑定 QDialog的 accepted信号 - void finished_slots(int value); // 用来做窗口关闭后的最后处理 }; #endif // PARAGRAPHFORMATDIALOG_H -- Gitee From b9a0184fc6c6170b82ecc29bc4cd9e6e7145037d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Tue, 8 Aug 2017 21:02:51 +0800 Subject: [PATCH 34/83] =?UTF-8?q?=E4=B8=8B=E9=9D=A2=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=EF=BC=8C=E5=B0=86Image=E5=AF=B9=E8=AF=9D=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E6=9B=B4=E6=94=B9=E4=B8=BA=E5=8D=95=E4=BE=8B=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=20=E8=A7=A3=E9=99=A4=E4=B8=80=E4=BA=9B=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E7=82=B9=E5=87=BB=E5=8F=96=E6=B6=88=E6=8C=89=E9=92=AE=E9=80=A0?= =?UTF-8?q?=E6=88=90=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocImageBlock.cpp | 76 ++++++----- ofdEditor/model/Doc/DocImageBlock.h | 7 +- ofdEditor/model/Doc/DocPage.cpp | 6 +- ofdEditor/model/Doc/DocTextBlock.h | 5 +- .../model/Widget/imagepropertiesdialog.cpp | 124 +++++++++++++++--- .../model/Widget/imagepropertiesdialog.h | 12 +- .../model/Widget/imagepropertiesdialog.ui | 52 ++++++-- .../start/ActionConnector/ActionConnector.cpp | 2 +- ofdEditor/start/ui/PassageMainWindow.cpp | 4 + 9 files changed, 217 insertions(+), 71 deletions(-) diff --git a/ofdEditor/model/Doc/DocImageBlock.cpp b/ofdEditor/model/Doc/DocImageBlock.cpp index 4820c3d..925c4d8 100644 --- a/ofdEditor/model/Doc/DocImageBlock.cpp +++ b/ofdEditor/model/Doc/DocImageBlock.cpp @@ -14,37 +14,19 @@ DocImageBlock::DocImageBlock(QWidget *parent) this->setFrameStyle(QFrame::NoFrame); this->setFocusPolicy(Qt::StrongFocus); - //Initialization - this->context_menu = new QMenu(this); - change_image = new QAction(tr("Change Image"), NULL); - set_image_properties = new QAction(tr("Set Image Properties"), NULL); - remove_image = new QAction(tr("Remove Image."), NULL); - remove_image->setShortcut(Qt::Key_Delete); + qDebug() << "DocImageBlock 1"; - properties_dialog = new ImagePropertiesDialog(this, parent); + //Initialization + this->properties_dialog = new ImagePropertiesDialog(this, parent); width_height_ratio_locked = false; width_height_ratio = 0.0; - context_menu->addAction(this->change_image); - context_menu->addAction(this->set_image_properties); - context_menu->addAction(this->remove_image); + qDebug() << "DocImageBlock 2"; + + this->initMenu(); // 初始化右键菜单 + + qDebug() << "DocImageBlock 3"; - //signal-slots - this->connect(this->change_image, SIGNAL(triggered()), - this, SLOT(changeImage())); - this->connect(this->set_image_properties, SIGNAL(triggered()), - this, SLOT(setImageProperties())); - this->connect(properties_dialog, - SIGNAL(changeImageProperties(double,double, - double,double, - bool)), - this, SLOT(imagePropertiesChanged(double,double, - double,double, - bool))); - this->connect(this->remove_image, - SIGNAL(triggered(bool)), - this, - SLOT(removeImage())); } /** @@ -106,6 +88,16 @@ QString DocImageBlock::getType() return tr("DocImageBlock"); } +/// +/// \brief DocImageBlock::getMenu +/// 获得图片块的右键菜单 +/// \return +/// +QMenu *DocImageBlock::getMenu() +{ + return this->context_menu; +} + /** * @Author Pan * @brief 焦点聚焦,显示边框 @@ -147,6 +139,33 @@ void DocImageBlock::contextMenuEvent(QContextMenuEvent *ev) context_menu->exec(ev->globalPos()); } +/// +/// \brief DocImageBlock::initMenu +/// 初始化右键菜单 +/// +void DocImageBlock::initMenu() +{ + this->context_menu = new QMenu(tr("DocImageBlock")); // 新建菜单 + + this->change_image = this->context_menu->addAction(tr("ChangeImage")); + this->set_image_properties = this->context_menu->addAction(tr("Property")); + + + + //signal-slots + this->connect(this->change_image, SIGNAL(triggered()), + this, SLOT(changeImage())); + this->connect(this->set_image_properties, SIGNAL(triggered()), + this, SLOT(setImageProperties())); + this->connect(properties_dialog, + SIGNAL(changeImageProperties(double,double, + double,double, + bool)), + this, SLOT(imagePropertiesChanged(double,double, + double,double, + bool))); +} + /** * @Author Pan * @brief 更换图片的槽函数 @@ -188,11 +207,6 @@ void DocImageBlock::setImageProperties() properties_dialog->exec(); } -void DocImageBlock::removeImage() -{ - this->block->remove(); -} - /** * @Author Pan * @brief 槽函数,根据对话框的信息改动更新自身属性 diff --git a/ofdEditor/model/Doc/DocImageBlock.h b/ofdEditor/model/Doc/DocImageBlock.h index 674d292..f9af112 100644 --- a/ofdEditor/model/Doc/DocImageBlock.h +++ b/ofdEditor/model/Doc/DocImageBlock.h @@ -25,7 +25,8 @@ public: bool isWidthHeightRatioLocked(); double getWidthHeightRatio(); DocBlock * getBlock(); //获取代理它的DocBlock - QString getType(); // 获得标识,来区分不同的块 + QString getType(); // 获得标识,来区分不同的块 + QMenu* getMenu(); // 获得图片块的菜单成分 public slots: void imagePropertiesChanged(double new_width, @@ -35,7 +36,6 @@ public slots: bool ratio_locked); void changeImage(); void setImageProperties(); - void removeImage(); protected: void focusInEvent(QFocusEvent *ev); @@ -47,11 +47,12 @@ private: QMenu * context_menu; //右键菜单 QAction * change_image; //更改图片 QAction * set_image_properties; //更改图片的位置和尺寸 - QAction * remove_image; //删除图片 ImagePropertiesDialog * properties_dialog; bool width_height_ratio_locked; double width_height_ratio; + void initMenu(); // 初始化右键菜单 + signals: void sendImageInfo(double image_width, diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index db6963f..8898f07 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -378,7 +378,8 @@ void DocPage::contextMenuEvent(QContextMenuEvent *event) { // 如果是图片 DocImageBlock* imageBlock = block->getImageBlock(); - seletion->addAction(imageBlock->getType()); +// seletion->addAction(imageBlock->getType()); + menu->addMenu(imageBlock->getMenu()); } } else @@ -648,7 +649,7 @@ void DocPage::init() void DocPage::addImage() { - //qDebug() << "???"; + qDebug() << "???"; //打开对话框,选取一个图片文件 QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), QDir::currentPath()); @@ -659,6 +660,7 @@ void DocPage::addImage() tr("Cannot open file %1.").arg(fileName)); return; } + //新建一个DocBlock DocBlock * newBlock = new DocBlock(); //新建一个图片框 diff --git a/ofdEditor/model/Doc/DocTextBlock.h b/ofdEditor/model/Doc/DocTextBlock.h index 9228592..bb4ea43 100644 --- a/ofdEditor/model/Doc/DocTextBlock.h +++ b/ofdEditor/model/Doc/DocTextBlock.h @@ -36,11 +36,10 @@ public: QString getContent(); // 获得TextBlock中的所有文本 int getContentLength(); // 获得内部文字长度 QString getType(); // 获得标识,来区分不同的块 + QMenu* getMenu(); // 获得该块的菜单成分 public slots: - QMenu* getMenu(); // 获得该块的菜单成分 - void textBold(); // 将光标选择的文字粗体 void textBold(QTextCursor& cursor, int mode = 0); // 将给定光标选择的文字设置为粗体 void textUnderline(); // 下划线 @@ -51,8 +50,6 @@ public slots: void setTextColor(QTextCursor& cursor,QColor color); // 设置颜色 void textParagraph(); // 设置段落 - - void textFontDialog(); // 通过字体小窗口设置字体 void customFontDialog(); // 自定义的字体窗口设置 void setTextBlockFormat( diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.cpp b/ofdEditor/model/Widget/imagepropertiesdialog.cpp index 0ad83ec..1da7750 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.cpp +++ b/ofdEditor/model/Widget/imagepropertiesdialog.cpp @@ -1,6 +1,39 @@ #include "imagepropertiesdialog.h" #include "ui_imagepropertiesdialog.h" #include + +ImagePropertiesDialog* ImagePropertiesDialog::m_instance = NULL; // 静态变量初始化 + +/// +/// \brief ImagePropertiesDialog::getInstance +/// 获得单例 +/// \return +/// +ImagePropertiesDialog *ImagePropertiesDialog::getInstance() +{ + if(m_instance != NULL) + { + return m_instance; + } + + m_instance = new ImagePropertiesDialog(); + return m_instance; +} + +void ImagePropertiesDialog::DestoryInstance() +{ + m_instance = NULL; +} + +void ImagePropertiesDialog::init(DocImageBlock *_block) +{ + // 建立连接 + this->connect(_block,SIGNAL(sendImageInfo(double,double,double,double,double,double,bool)), + this,SLOT(receiveImageInfo(double,double,double,double,double,double,bool))); + +} + + /** * @Author Pan * @brief 构造函数,完成了成员组件的初始化、设置,以及信号槽的连接 @@ -8,7 +41,8 @@ * @return * @date 2017/06/25 */ -ImagePropertiesDialog::ImagePropertiesDialog(DocImageBlock * _block, QWidget *parent) : +ImagePropertiesDialog::ImagePropertiesDialog( + DocImageBlock * _block, QWidget *parent) : QDialog(parent), ui(new Ui::ImagePropertiesDialog), block(_block) @@ -31,22 +65,30 @@ ImagePropertiesDialog::ImagePropertiesDialog(DocImageBlock * _block, QWidget *pa ui->HeightInPercentage->setRange(0.0, 10000.0); ui->xInPercentage->setRange(0.0, 100.0); ui->yInPercentage->setRange(0.0, 100.0); - this->connect(this, SIGNAL(accepted()), this, SLOT(emitMessage())); - this->connect(ui->LockRatio, SIGNAL(stateChanged(int)), this, SLOT(lockRatioStateChanged(int))); - this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), this, SLOT(Percentage2Pixel(double))); - this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), this, SLOT(Percentage2Pixel(double))); - this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), this, SLOT(Percentage2Pixel(double))); - this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), this, SLOT(Percentage2Pixel(double))); - this->connect(ui->HeightInPixel, SIGNAL(valueChanged(double)), this, SLOT(Pixel2Percentage(double))); - this->connect(ui->WidthInPixel, SIGNAL(valueChanged(double)), this, SLOT(Pixel2Percentage(double))); - this->connect(ui->xInPixel, SIGNAL(valueChanged(double)), this, SLOT(Pixel2Percentage(double))); - this->connect(ui->yInPixel, SIGNAL(valueChanged(double)), this, SLOT(Pixel2Percentage(double))); - this->connect(ui->WidthInPixel, - SIGNAL(valueChanged(double)), - this, SLOT(Width2HeightTrans(double))); - this->connect(ui->HeightInPixel, - SIGNAL(valueChanged(double)), - this, SLOT(Height2WidthTrans(double))); + this->connect(this, SIGNAL(accepted()), + this, SLOT(emitMessage())); + this->connect(ui->LockRatio, SIGNAL(stateChanged(int)), + this, SLOT(lockRatioStateChanged(int))); + this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2Pixel(double))); + this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2Pixel(double))); + this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2Pixel(double))); + this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2Pixel(double))); + this->connect(ui->HeightInPixel, SIGNAL(valueChanged(double)), + this, SLOT(Pixel2Percentage(double))); + this->connect(ui->WidthInPixel, SIGNAL(valueChanged(double)), + this, SLOT(Pixel2Percentage(double))); + this->connect(ui->xInPixel, SIGNAL(valueChanged(double)), + this, SLOT(Pixel2Percentage(double))); + this->connect(ui->yInPixel, SIGNAL(valueChanged(double)), + this, SLOT(Pixel2Percentage(double))); + this->connect(ui->WidthInPixel,SIGNAL(valueChanged(double)), + this, SLOT(Width2HeightTrans(double))); + this->connect(ui->HeightInPixel,SIGNAL(valueChanged(double)), + this, SLOT(Height2WidthTrans(double))); } /** * @Author Pan @@ -87,13 +129,53 @@ void ImagePropertiesDialog::receiveImageInfo(double image_width, } - - ImagePropertiesDialog::~ImagePropertiesDialog() { delete ui; } + +ImagePropertiesDialog::ImagePropertiesDialog(QWidget *parent) + :QDialog(parent), ui(new Ui::ImagePropertiesDialog) +{ + ui->setupUi(this); +} + +void ImagePropertiesDialog::init() +{ + +} + +void ImagePropertiesDialog::initConnect() +{ + // 确认 + this->connect(this, SIGNAL(accepted()), + this, SLOT(emitMessage())); + + this->connect(ui->LockRatio, SIGNAL(stateChanged(int)), + this, SLOT(lockRatioStateChanged(int))); + this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2Pixel(double))); + this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2Pixel(double))); + this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2Pixel(double))); + this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2Pixel(double))); + this->connect(ui->HeightInPixel, SIGNAL(valueChanged(double)), + this, SLOT(Pixel2Percentage(double))); + this->connect(ui->WidthInPixel, SIGNAL(valueChanged(double)), + this, SLOT(Pixel2Percentage(double))); + this->connect(ui->xInPixel, SIGNAL(valueChanged(double)), + this, SLOT(Pixel2Percentage(double))); + this->connect(ui->yInPixel, SIGNAL(valueChanged(double)), + this, SLOT(Pixel2Percentage(double))); + this->connect(ui->WidthInPixel,SIGNAL(valueChanged(double)), + this, SLOT(Width2HeightTrans(double))); + this->connect(ui->HeightInPixel,SIGNAL(valueChanged(double)), + this, SLOT(Height2WidthTrans(double))); +} + /** * @Author Pan * @brief 发送信号 @@ -108,6 +190,10 @@ void ImagePropertiesDialog::emitMessage() ui->xInPixel->value(), ui->yInPixel->value(), ui->LockRatio->isChecked()); + + this->disconnect(_block,SIGNAL(sendImageInfo(double,double,double,double,double,double,bool)), + this,SLOT(receiveImageInfo(double,double,double,double,double,double,bool))); + } /** diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.h b/ofdEditor/model/Widget/imagepropertiesdialog.h index 6faf7f5..fadb2c9 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.h +++ b/ofdEditor/model/Widget/imagepropertiesdialog.h @@ -2,7 +2,7 @@ #define IMAGEPROPERTIESDIALOG_H #include -#include "../Doc/DocImageBlock.h" +#include "Doc/DocImageBlock.h" class DocImageBlock; namespace Ui { @@ -14,17 +14,27 @@ class ImagePropertiesDialog : public QDialog Q_OBJECT public: + static ImagePropertiesDialog* getInstance(); // 获得单例 + static void DestoryInstance(); // 销毁单例 + void init(DocImageBlock* _block); // 使用时初始化 + explicit ImagePropertiesDialog(DocImageBlock * _block, QWidget *parent = 0); ~ImagePropertiesDialog(); private: + ImagePropertiesDialog(QWidget *parent = 0); Ui::ImagePropertiesDialog *ui; DocImageBlock * block; + static ImagePropertiesDialog* m_instance; double initial_width; double initial_height; bool ratio_locked; double page_width; double page_height; + + void init(); + void initConnect(); + private slots: void emitMessage(); void lockRatioStateChanged(int locked); diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.ui b/ofdEditor/model/Widget/imagepropertiesdialog.ui index cb62429..364845c 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.ui +++ b/ofdEditor/model/Widget/imagepropertiesdialog.ui @@ -6,8 +6,8 @@ 0 0 - 352 - 336 + 372 + 328 @@ -34,7 +34,11 @@ - + + + 10000.000000000000000 + + @@ -51,7 +55,11 @@ - + + + 10000.000000000000000 + + @@ -81,7 +89,11 @@ - + + + 10000.000000000000000 + + @@ -98,7 +110,11 @@ - + + + 10000.000000000000000 + + @@ -150,7 +166,11 @@ - + + + 10000.000000000000000 + + @@ -167,7 +187,11 @@ - + + + 10000.000000000000000 + + @@ -197,7 +221,11 @@ - + + + 10000.000000000000000 + + @@ -214,7 +242,11 @@ - + + + 10000.000000000000000 + + diff --git a/ofdEditor/start/ActionConnector/ActionConnector.cpp b/ofdEditor/start/ActionConnector/ActionConnector.cpp index d4e1495..a58b09f 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.cpp +++ b/ofdEditor/start/ActionConnector/ActionConnector.cpp @@ -78,7 +78,6 @@ void ActionConnector::addNewBlock(InsertBlockInfo& blockInfo) } // this->updateActivePassage(); // 更新文章 -// DocPage * page = qobject_cast(this->passage->focusWidget()); DocPage *page = this->passage->getLastedActivedPage(); // 获得最近操作过的页面 if(page == NULL) { @@ -121,6 +120,7 @@ void ActionConnector::addImageBlock() if(this->passage == NULL) return; InsertBlockInfo blockInfo(this->defaultLayer,DocPage::image); // 设置插入文本框信息 +// qDebug() << "add imageBlock"; this->addNewBlock(blockInfo); } diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index afabd54..bcb2ea3 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -98,6 +98,10 @@ void PassageMainWindow::init() this->connector = new ActionConnector(this); // 新建连接器 + // 初始化变量 + this->imageBlock = NULL; + this->textBlock = NULL; + initAction(); connectAction(); -- Gitee From a42a9680baa646a67783487e788ff1eb80187165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Wed, 9 Aug 2017 18:36:52 +0800 Subject: [PATCH 35/83] =?UTF-8?q?=E5=95=8A=E5=95=8A=E5=95=8A=EF=BC=8C=20?= =?UTF-8?q?=E6=88=91=E8=A2=AB=E8=9A=8A=E5=AD=90=E5=92=AC=E4=BA=86=EF=BC=8C?= =?UTF-8?q?=E6=88=91=E8=A6=81=E5=9B=9E=E5=AE=BF=E8=88=8D=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocImageBlock.cpp | 95 +++++-- ofdEditor/model/Doc/DocImageBlock.h | 48 ++-- ofdEditor/model/Doc/DocPage.cpp | 2 +- ofdEditor/model/Widget/DocInfoDialog.h | 2 - ofdEditor/model/Widget/FontSettingDialog.cpp | 27 +- ofdEditor/model/Widget/FontSettingDialog.h | 2 +- ofdEditor/model/Widget/PageDialog.cpp | 61 +++-- ofdEditor/model/Widget/PageDialog.h | 1 + ofdEditor/model/Widget/PageDialog.ui | 2 +- .../model/Widget/ParagraphFormatDialog.cpp | 25 +- .../model/Widget/ParagraphFormatDialog.h | 2 +- .../model/Widget/imagepropertiesdialog.cpp | 256 +++++++++--------- .../model/Widget/imagepropertiesdialog.h | 24 +- .../model/Widget/imagepropertiesdialog.ui | 212 ++++++++------- 14 files changed, 444 insertions(+), 315 deletions(-) diff --git a/ofdEditor/model/Doc/DocImageBlock.cpp b/ofdEditor/model/Doc/DocImageBlock.cpp index 925c4d8..15e6693 100644 --- a/ofdEditor/model/Doc/DocImageBlock.cpp +++ b/ofdEditor/model/Doc/DocImageBlock.cpp @@ -4,6 +4,7 @@ #include #include #include "DocPage.h" +#include "Tool/UnitTool.h" DocImageBlock::DocImageBlock(QWidget *parent) :QLabel(parent) @@ -17,7 +18,7 @@ DocImageBlock::DocImageBlock(QWidget *parent) qDebug() << "DocImageBlock 1"; //Initialization - this->properties_dialog = new ImagePropertiesDialog(this, parent); +// this->properties_dialog = new ImagePropertiesDialog(this, parent); width_height_ratio_locked = false; width_height_ratio = 0.0; @@ -38,6 +39,12 @@ DocImageBlock::DocImageBlock(QWidget *parent) */ void DocImageBlock::setImage(QPixmap & pixmap) { + + this->realWidth = UnitTool::pixelToMM( + pixmap.width()); // 保存实际宽度 + this->realHeight = UnitTool::pixelToMM( + pixmap.height()); // 保存实际高度 + this->setPixmap(pixmap); } @@ -78,6 +85,49 @@ double DocImageBlock::getWidthHeightRatio() return width_height_ratio; } +DocPassage *DocImageBlock::getPassage() +{ + DocBlock *block = this->block; + if(block == NULL) + return NULL; + + return block->getPassage(); + +} + +/// +/// \brief DocImageBlock::getPage +/// 获得图片框所属的页 +/// \return +/// +DocPage *DocImageBlock::getPage() +{ + DocBlock *block = this->block; + if(block == NULL) + return NULL; + + return block->getPage(); +} + +/// +/// \brief DocImageBlock::getLayer +/// 获得图片框所属的层 +/// \return +/// +DocLayer *DocImageBlock::getLayer() +{ + DocBlock *block = this->block; + if(block == NULL) + return NULL; + + return block->getLayer(); +} + +/// +/// \brief DocImageBlock::getBlock +/// 获得图片框所属的块 +/// \return +/// DocBlock *DocImageBlock::getBlock() { return this->block; @@ -98,6 +148,16 @@ QMenu *DocImageBlock::getMenu() return this->context_menu; } +double DocImageBlock::getRealWidth() +{ + return this->realWidth; +} + +double DocImageBlock::getRealHeight() +{ + return this->realHeight; +} + /** * @Author Pan * @brief 焦点聚焦,显示边框 @@ -157,13 +217,13 @@ void DocImageBlock::initMenu() this, SLOT(changeImage())); this->connect(this->set_image_properties, SIGNAL(triggered()), this, SLOT(setImageProperties())); - this->connect(properties_dialog, - SIGNAL(changeImageProperties(double,double, - double,double, - bool)), - this, SLOT(imagePropertiesChanged(double,double, - double,double, - bool))); +// this->connect(properties_dialog, +// SIGNAL(changeImageProperties(double,double, +// double,double, +// bool)), +// this, SLOT(imagePropertiesChanged(double,double, +// double,double, +// bool))); } /** @@ -197,14 +257,17 @@ void DocImageBlock::changeImage() */ void DocImageBlock::setImageProperties() { - emit sendImageInfo(this->width(), - this->height(), - this->pos().x(), - this->pos().y(), - this->block->getPage()->width(), - this->block->getPage()->height(), - this->width_height_ratio_locked); - properties_dialog->exec(); +// emit sendImageInfo(this->width(), +// this->height(), +// this->pos().x(), +// this->pos().y(), +// this->block->getPage()->width(), +// this->block->getPage()->height(), +// this->width_height_ratio_locked); +// properties_dialog->exec(); + ImagePropertiesDialog* dialog = ImagePropertiesDialog::getInstance(); + dialog->init(this); + dialog->exec(); } /** diff --git a/ofdEditor/model/Doc/DocImageBlock.h b/ofdEditor/model/Doc/DocImageBlock.h index f9af112..0afa700 100644 --- a/ofdEditor/model/Doc/DocImageBlock.h +++ b/ofdEditor/model/Doc/DocImageBlock.h @@ -20,22 +20,31 @@ class MODELSHARED_EXPORT DocImageBlock public: DocImageBlock(QWidget *parent = NULL); - void setImage(QPixmap & pixmap); - void setBlock(DocBlock * _block); + bool isWidthHeightRatioLocked(); double getWidthHeightRatio(); - DocBlock * getBlock(); //获取代理它的DocBlock + DocPassage *getPassage(); // 获得文章 + DocPage *getPage(); // 获得页 + DocLayer *getLayer(); // 获得层 + DocBlock *getBlock(); //获取代理它的DocBlock QString getType(); // 获得标识,来区分不同的块 QMenu* getMenu(); // 获得图片块的菜单成分 + // 单位为 mm + double getRealWidth(); // 获得图片真实大小 + double getRealHeight(); // 获得图片真实大小 + public slots: - void imagePropertiesChanged(double new_width, - double new_height, - double new_x, - double new_y, - bool ratio_locked); - void changeImage(); - void setImageProperties(); + void imagePropertiesChanged( + double new_width, + double new_height, + double new_x, + double new_y, + bool ratio_locked); // 修改图片属性 + void setImage(QPixmap & pixmap); // 设置图片 + void setBlock(DocBlock * _block); // 设置所属的块 + void changeImage(); // 修改图片 + void setImageProperties(); // 设置图片属性 protected: void focusInEvent(QFocusEvent *ev); @@ -47,21 +56,24 @@ private: QMenu * context_menu; //右键菜单 QAction * change_image; //更改图片 QAction * set_image_properties; //更改图片的位置和尺寸 - ImagePropertiesDialog * properties_dialog; +// ImagePropertiesDialog * properties_dialog; bool width_height_ratio_locked; double width_height_ratio; void initMenu(); // 初始化右键菜单 + double realWidth; // 图片实际宽度 + double realHeight; // 图片实际高度 + signals: - void sendImageInfo(double image_width, - double image_height, - double image_x, - double image_y, - double page_width, - double page_height, - bool ratio_is_locked); +// void sendImageInfo(double image_width, +// double image_height, +// double image_x, +// double image_y, +// double page_width, +// double page_height, +// bool ratio_is_locked); void signals_currrentImageBlock(DocImageBlock * textBlock); //当前操作的imageBlock }; diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index 8898f07..5cf7265 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -666,7 +666,7 @@ void DocPage::addImage() //新建一个图片框 DocImageBlock * new_image_block = new DocImageBlock(); newBlock->setWidget(new_image_block); - new_image_block->setImage(image); + new_image_block->setImage(image); // 设置图片 double page_width = this->width(), page_height = this->height(); // qDebug() << "Page Width: " << this->width(); // qDebug() << "Page Height: " << this->height(); diff --git a/ofdEditor/model/Widget/DocInfoDialog.h b/ofdEditor/model/Widget/DocInfoDialog.h index bf0e688..779001a 100644 --- a/ofdEditor/model/Widget/DocInfoDialog.h +++ b/ofdEditor/model/Widget/DocInfoDialog.h @@ -19,8 +19,6 @@ public: static void DestoryInstance(); // 销毁实例 void init(CT_DocInfo* docInfo); // 初始化-每次调用窗口时使用 - - // DocInfoDialog(CT_DocInfo* docInfo,QWidget *parent); ~DocInfoDialog(); diff --git a/ofdEditor/model/Widget/FontSettingDialog.cpp b/ofdEditor/model/Widget/FontSettingDialog.cpp index fe6118c..e7795d9 100644 --- a/ofdEditor/model/Widget/FontSettingDialog.cpp +++ b/ofdEditor/model/Widget/FontSettingDialog.cpp @@ -159,8 +159,8 @@ void FontSettingDialog::initConnect() this,SLOT(updatePreview(QTextCharFormat))); // 当用户点击确认后,执行的函数 - connect(this, SIGNAL(accepted()), - this, SLOT(accept_slots())); // 窗口接受确认的信号 + connect(this, SIGNAL(finished(int)), + this, SLOT(finished_slots(int))); // 窗口完成任务时 } @@ -501,19 +501,22 @@ void FontSettingDialog::updateWeight(int i) emit this->signal_updatePreview(*this->charFormat); } -/** - * @Author Chaoqun - * @brief 用户确定事件 - * @param void - * @return void -* @date 2017/05/26 - */ -void FontSettingDialog::accept_slots() -{ - emit this->sendFont(*this->charFormat); +/// +/// \brief FontSettingDialog::finished_slots +/// \param value +/// +void FontSettingDialog::finished_slots(int value) +{ + if(value = QDialog::Accepted) + { + // 如果点击的是确定键 + emit this->sendFont(*this->charFormat); + } disconnect(this, SIGNAL(sendFont(QTextCharFormat&)), this->textBlock, SLOT(setCharFormatOnSelection(QTextCharFormat&))); } + + diff --git a/ofdEditor/model/Widget/FontSettingDialog.h b/ofdEditor/model/Widget/FontSettingDialog.h index 2ae1f53..4e71e8f 100644 --- a/ofdEditor/model/Widget/FontSettingDialog.h +++ b/ofdEditor/model/Widget/FontSettingDialog.h @@ -64,7 +64,7 @@ private slots: void updatefixedPitch(int state); // 固定字宽 void updateWeight(int i); // 字体粗细 - void accept_slots(); // 向DocTextBlock传递成功事件 + void finished_slots( int value ); // 接受对话框的结果 }; diff --git a/ofdEditor/model/Widget/PageDialog.cpp b/ofdEditor/model/Widget/PageDialog.cpp index e42677f..83279fc 100644 --- a/ofdEditor/model/Widget/PageDialog.cpp +++ b/ofdEditor/model/Widget/PageDialog.cpp @@ -245,10 +245,8 @@ void PageDialog::initConnect() SLOT(changed_page_range_changed())); // 选择确定后的操作 - this->connect(this, - SIGNAL(accepted()), - this, - SLOT(emitInformation())); + this->connect(this, SIGNAL(finished(int)), + this,SLOT(finished_slots(int))); // 判断是否修改过默认值 this->connect(ui->DefaultPageSizeWidth, @@ -562,28 +560,41 @@ void PageDialog::changed_page_range_changed() /// void PageDialog::emitInformation() { - this->caculatePages(); // 计算选择的页数 - - emit this->modifyPageSize( - &changed_page_numbers, - ui->CurrentPageSizeWidth->value(), - ui->CurrentPageSizeHeight->value(), - ui->CurrentSetWorkingAreaChecked->isChecked(), - ui->CurrentWorkingAreaWidth->value(), - ui->CurrentWorkingAreaHeight->value(), - ui->CurrentWorkingAreaX->value(), - ui->CurrentWorkingAreaY->value()); - - if(isDefaultPageSizeChanged) + + +} + +/// +/// \brief PageDialog::finished_slots +/// \param value +/// +void PageDialog::finished_slots(int value) +{ + if(value == QDialog::Accepted) { - emit this->modifyDefaultPageSize( - ui->DefaultPageSizeWidth->value(), - ui->DefaultPageSizeHeight->value(), - ui->DefaultSetWorkingAreaChecked->isChecked(), - ui->DefaultWorkingAreaWidth->value(), - ui->DefaultWorkingAreaHeight->value(), - ui->DefaultWorkingAreaX->value(), - ui->DefaultWorkingAreaY->value()); + // 如果用户选择了确定 + this->caculatePages(); // 计算选择的页数 + emit this->modifyPageSize( + &changed_page_numbers, + ui->CurrentPageSizeWidth->value(), + ui->CurrentPageSizeHeight->value(), + ui->CurrentSetWorkingAreaChecked->isChecked(), + ui->CurrentWorkingAreaWidth->value(), + ui->CurrentWorkingAreaHeight->value(), + ui->CurrentWorkingAreaX->value(), + ui->CurrentWorkingAreaY->value()); + + if(isDefaultPageSizeChanged) + { + emit this->modifyDefaultPageSize( + ui->DefaultPageSizeWidth->value(), + ui->DefaultPageSizeHeight->value(), + ui->DefaultSetWorkingAreaChecked->isChecked(), + ui->DefaultWorkingAreaWidth->value(), + ui->DefaultWorkingAreaHeight->value(), + ui->DefaultWorkingAreaX->value(), + ui->DefaultWorkingAreaY->value()); + } } // 断开链接 diff --git a/ofdEditor/model/Widget/PageDialog.h b/ofdEditor/model/Widget/PageDialog.h index b649101..eacd315 100644 --- a/ofdEditor/model/Widget/PageDialog.h +++ b/ofdEditor/model/Widget/PageDialog.h @@ -64,6 +64,7 @@ private slots: void page_range_range_changed(); void changed_page_range_changed(); void emitInformation(); + void finished_slots(int value); // 完成使命 signals: void modifyPageSize( diff --git a/ofdEditor/model/Widget/PageDialog.ui b/ofdEditor/model/Widget/PageDialog.ui index fbe268c..c666631 100644 --- a/ofdEditor/model/Widget/PageDialog.ui +++ b/ofdEditor/model/Widget/PageDialog.ui @@ -17,7 +17,7 @@ - 1 + 0 diff --git a/ofdEditor/model/Widget/ParagraphFormatDialog.cpp b/ofdEditor/model/Widget/ParagraphFormatDialog.cpp index 72a2301..7b9c5eb 100644 --- a/ofdEditor/model/Widget/ParagraphFormatDialog.cpp +++ b/ofdEditor/model/Widget/ParagraphFormatDialog.cpp @@ -153,8 +153,8 @@ void ParagraphFormatDialog::init(const QTextBlockFormat &blockFormat) { // 此信号槽用来将accepted信号接收,然后通过函数发送finished信号 - connect(this,SIGNAL(accepted()), - this,SLOT(accept_slots())); + connect(this, SIGNAL(finished(int)), + this, SLOT(finished_slots(int))); // 设置对齐部分 Qt::Alignment flag = blockFormat.alignment(); // 先获取对齐的样式 @@ -226,21 +226,20 @@ void ParagraphFormatDialog::init(const QTextBlockFormat &blockFormat) } -/** - * @Author Chaoqun - * @brief 绑定accepted信号,用来向外界发送信号 - * @param void - * @return void - * @date 2017/05/22 - */ -void ParagraphFormatDialog::accept_slots() +/// +/// \brief ParagraphFormatDialog::finished_slots +/// \param value +/// +void ParagraphFormatDialog::finished_slots(int value) { - QTextBlockFormat blockFormat = this->getQTextBlockFormat(); - emit this->finished(blockFormat); + if(value == QDialog::Accepted) + { + QTextBlockFormat blockFormat = this->getQTextBlockFormat(); + emit this->finished(blockFormat); + } disconnect(this, SIGNAL(finished(QTextBlockFormat&)), this->textBlock, SLOT(setTextBlockFormat(QTextBlockFormat&))); // 断开信号与槽链接 - } diff --git a/ofdEditor/model/Widget/ParagraphFormatDialog.h b/ofdEditor/model/Widget/ParagraphFormatDialog.h index 1fdd41d..a921347 100644 --- a/ofdEditor/model/Widget/ParagraphFormatDialog.h +++ b/ofdEditor/model/Widget/ParagraphFormatDialog.h @@ -45,7 +45,7 @@ private: void init(const QTextBlockFormat & blockFormat); private slots: - void accept_slots(); // 用来绑定 QDialog的 accepted信号 + void finished_slots(int value); // 用户点击 }; #endif // PARAGRAPHFORMATDIALOG_H diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.cpp b/ofdEditor/model/Widget/imagepropertiesdialog.cpp index 1da7750..afe2253 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.cpp +++ b/ofdEditor/model/Widget/imagepropertiesdialog.cpp @@ -1,5 +1,8 @@ #include "imagepropertiesdialog.h" #include "ui_imagepropertiesdialog.h" +#include "Doc/DocPage.h" +#include "Doc/DocImageBlock.h" +#include "Tool/UnitTool.h" #include ImagePropertiesDialog* ImagePropertiesDialog::m_instance = NULL; // 静态变量初始化 @@ -27,107 +30,99 @@ void ImagePropertiesDialog::DestoryInstance() void ImagePropertiesDialog::init(DocImageBlock *_block) { + this->block = _block; // 记录下block // 建立连接 - this->connect(_block,SIGNAL(sendImageInfo(double,double,double,double,double,double,bool)), - this,SLOT(receiveImageInfo(double,double,double,double,double,double,bool))); + this->connect( this, SIGNAL(changeImageProperties(double,double,double,double,bool)), + this->block, SLOT(imagePropertiesChanged(double,double,double,double,bool))); + + // 设置界面显示 + ui->LockRatio->setChecked(this->block->isWidthHeightRatioLocked()); // 是否锁定纵横比 + // 图片实际尺寸 + ui->InitialSize->setText( + tr("Width: ") + + QString::number(this->block->getRealWidth()) + + tr(" mm") + + tr(", Height: ") + + QString::number(this->block->getRealHeight()) + + tr(" mm")); + + // 保存图片原始尺寸 + initial_width = this->block->getRealWidth(); + initial_height = this->block->getRealWidth(); + // 是否锁定纵横比 + ratio_locked = this->block->isWidthHeightRatioLocked(); + + // 页大小 + this->page_width = this->block->getPage()->getWidth(); + this->page_height = this->block->getPage()->getHeight(); + + // 像素大小?? + ui->WidthInPixel->setValue(this->block->width()); + ui->HeightInPixel->setValue(this->block->height()); + ui->xInPixel->setValue(this->block->x()); + ui->yInPixel->setValue(this->block->y()); + + // 图片采用毫米为单位 + ui->WidthInMM->setValue( + UnitTool::pixelToMM( + this->block->width())); + ui->HeightInMM->setValue( + UnitTool::pixelToMM( + this->block->height())); + + ui->xInMM->setValue( + UnitTool::pixelToMM( + this->block->x())); + ui->yInMM->setValue( + UnitTool::pixelToMM( + this->block->y())); + + // 求比例 + ui->WidthInPercentage->setValue( + this->block->width() / this->initial_width * 100.0); + ui->HeightInPercentage->setValue( + this->block->height() / this->initial_height * 100.0); + + ui->xInPercentage->setValue( + ui->xInMM->value() / this->page_width * 100.0); + ui->yInPercentage->setValue( + ui->yInMM->value() / this->page_height * 100.0); } - -/** - * @Author Pan - * @brief 构造函数,完成了成员组件的初始化、设置,以及信号槽的连接 - * @param DocImageBlock * _block, QWidget * parent - * @return - * @date 2017/06/25 - */ -ImagePropertiesDialog::ImagePropertiesDialog( - DocImageBlock * _block, QWidget *parent) : - QDialog(parent), - ui(new Ui::ImagePropertiesDialog), - block(_block) -{ - ui->setupUi(this); - this->connect(_block, - SIGNAL(sendImageInfo(double,double, - double,double, - double,double,bool)), - this, - SLOT(receiveImageInfo(double,double, - double,double, - double,double,bool))); - - ui->WidthInPixel->setRange(0.0, 100000); - ui->HeightInPixel->setRange(0.0, 100000); - ui->xInPixel->setRange(0.0, 10000); - ui->yInPixel->setRange(0.0, 10000); - ui->WidthInPercentage->setRange(0.0, 10000.0); - ui->HeightInPercentage->setRange(0.0, 10000.0); - ui->xInPercentage->setRange(0.0, 100.0); - ui->yInPercentage->setRange(0.0, 100.0); - this->connect(this, SIGNAL(accepted()), - this, SLOT(emitMessage())); - this->connect(ui->LockRatio, SIGNAL(stateChanged(int)), - this, SLOT(lockRatioStateChanged(int))); - this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2Pixel(double))); - this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2Pixel(double))); - this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2Pixel(double))); - this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2Pixel(double))); - this->connect(ui->HeightInPixel, SIGNAL(valueChanged(double)), - this, SLOT(Pixel2Percentage(double))); - this->connect(ui->WidthInPixel, SIGNAL(valueChanged(double)), - this, SLOT(Pixel2Percentage(double))); - this->connect(ui->xInPixel, SIGNAL(valueChanged(double)), - this, SLOT(Pixel2Percentage(double))); - this->connect(ui->yInPixel, SIGNAL(valueChanged(double)), - this, SLOT(Pixel2Percentage(double))); - this->connect(ui->WidthInPixel,SIGNAL(valueChanged(double)), - this, SLOT(Width2HeightTrans(double))); - this->connect(ui->HeightInPixel,SIGNAL(valueChanged(double)), - this, SLOT(Height2WidthTrans(double))); -} -/** - * @Author Pan - * @brief 槽函数,用语接收DocImageBlock的信号后更新自身的信息 - * @param 若干参数 - * @return void - * @date 2017/06/25 - */ -void ImagePropertiesDialog::receiveImageInfo(double image_width, - double image_height, - double image_x, - double image_y, - double page_width, - double page_height, - bool ratio_is_locked) { - ui->LockRatio->setChecked(ratio_is_locked); - ui->InitialSize->setText(tr("Width: ") + QString::number(image_width) + tr(", Height: ") + QString::number(image_height)); - initial_width = image_width; - initial_height = image_height; - ratio_locked = ratio_is_locked; - this->page_width = page_width; - this->page_height = page_height; - -// ui->WidthInPercentage->setValue(100.0); -// ui->HeightInPercentage->setValue(100.0); -// ui->xInPercentage->setValue(image_x / page_width * 100.0); -// ui->yInPercentage->setValue(image_y / page_height * 100.0); - - ui->WidthInPixel->setValue(image_width); - ui->HeightInPixel->setValue(image_height); - ui->xInPixel->setValue(image_x); - ui->yInPixel->setValue(image_y); - - ui->WidthInPercentage->setValue(ui->WidthInPixel->value() / image_width * 100.0); - ui->HeightInPercentage->setValue(ui->HeightInPixel->value() / image_height * 100.0); - ui->xInPercentage->setValue(ui->xInPixel->value() / page_width * 100.0); - ui->yInPercentage->setValue(ui->yInPixel->value() / page_width * 100.0); - -} +///** +// * @Author Pan +// * @brief 槽函数,用语接收DocImageBlock的信号后更新自身的信息 +// * @param 若干参数 +// * @return void +// * @date 2017/06/25 +// */ +//void ImagePropertiesDialog::receiveImageInfo(double image_width, +// double image_height, +// double image_x, +// double image_y, +// double page_width, +// double page_height, +// bool ratio_is_locked) { +// ui->LockRatio->setChecked(ratio_is_locked); +// ui->InitialSize->setText(tr("Width: ") + QString::number(image_width) + tr(", Height: ") + QString::number(image_height)); +// initial_width = image_width; +// initial_height = image_height; +// ratio_locked = ratio_is_locked; +// this->page_width = page_width; +// this->page_height = page_height; + +// ui->WidthInPixel->setValue(image_width); +// ui->HeightInPixel->setValue(image_height); +// ui->xInPixel->setValue(image_x); +// ui->yInPixel->setValue(image_y); + +// ui->WidthInPercentage->setValue(ui->WidthInPixel->value() / image_width * 100.0); +// ui->HeightInPercentage->setValue(ui->HeightInPixel->value() / image_height * 100.0); +// ui->xInPercentage->setValue(ui->xInPixel->value() / page_width * 100.0); +// ui->yInPercentage->setValue(ui->yInPixel->value() / page_width * 100.0); + +//} ImagePropertiesDialog::~ImagePropertiesDialog() { @@ -139,18 +134,15 @@ ImagePropertiesDialog::ImagePropertiesDialog(QWidget *parent) :QDialog(parent), ui(new Ui::ImagePropertiesDialog) { ui->setupUi(this); -} - -void ImagePropertiesDialog::init() -{ - + this->initConnect(); } void ImagePropertiesDialog::initConnect() { - // 确认 - this->connect(this, SIGNAL(accepted()), - this, SLOT(emitMessage())); + + // 关闭窗口后触发 + this->connect(this, SIGNAL(finished(int)), + this, SLOT(finished_slots(int))); this->connect(ui->LockRatio, SIGNAL(stateChanged(int)), this, SLOT(lockRatioStateChanged(int))); @@ -174,25 +166,47 @@ void ImagePropertiesDialog::initConnect() this, SLOT(Width2HeightTrans(double))); this->connect(ui->HeightInPixel,SIGNAL(valueChanged(double)), this, SLOT(Height2WidthTrans(double))); + } -/** - * @Author Pan - * @brief 发送信号 - * @param void - * @return void - * @date 2017/06/25 - */ -void ImagePropertiesDialog::emitMessage() +///** +// * @Author Pan +// * @brief 发送信号 +// * @param void +// * @return void +// * @date 2017/06/25 +// */ +//void ImagePropertiesDialog::emitMessage() +//{ +// emit changeImageProperties(ui->WidthInPixel->value(), +// ui->HeightInPixel->value(), +// ui->xInPixel->value(), +// ui->yInPixel->value(), +// ui->LockRatio->isChecked()); + +//// this->disconnect(_block,SIGNAL(sendImageInfo(double,double,double,double,double,double,bool)), +//// this,SLOT(receiveImageInfo(double,double,double,double,double,double,bool))); + +//} + +/// +/// \brief ImagePropertiesDialog::finished_slots +/// \param value +/// +void ImagePropertiesDialog::finished_slots(int value) { - emit changeImageProperties(ui->WidthInPixel->value(), - ui->HeightInPixel->value(), - ui->xInPixel->value(), - ui->yInPixel->value(), - ui->LockRatio->isChecked()); - - this->disconnect(_block,SIGNAL(sendImageInfo(double,double,double,double,double,double,bool)), - this,SLOT(receiveImageInfo(double,double,double,double,double,double,bool))); + if(value == QDialog::Accepted) + { + // 点击确认 + emit changeImageProperties(ui->WidthInPixel->value(), + ui->HeightInPixel->value(), + ui->xInPixel->value(), + ui->yInPixel->value(), + ui->LockRatio->isChecked()); + } + + this->disconnect( this, SIGNAL(changeImageProperties(double,double,double,double,bool)), + this->block, SLOT(imagePropertiesChanged(double,double,double,double,bool))); } diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.h b/ofdEditor/model/Widget/imagepropertiesdialog.h index fadb2c9..3d839b4 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.h +++ b/ofdEditor/model/Widget/imagepropertiesdialog.h @@ -2,7 +2,7 @@ #define IMAGEPROPERTIESDIALOG_H #include -#include "Doc/DocImageBlock.h" + class DocImageBlock; namespace Ui { @@ -18,7 +18,6 @@ public: static void DestoryInstance(); // 销毁单例 void init(DocImageBlock* _block); // 使用时初始化 - explicit ImagePropertiesDialog(DocImageBlock * _block, QWidget *parent = 0); ~ImagePropertiesDialog(); private: @@ -26,30 +25,31 @@ private: Ui::ImagePropertiesDialog *ui; DocImageBlock * block; static ImagePropertiesDialog* m_instance; + + // 使用毫米为单位 double initial_width; double initial_height; bool ratio_locked; double page_width; double page_height; - void init(); void initConnect(); private slots: - void emitMessage(); + void finished_slots(int value); // 完成窗口后执行 void lockRatioStateChanged(int locked); void Width2HeightTrans(double value); void Height2WidthTrans(double value); void Pixel2Percentage(double value); void Percentage2Pixel(double value); -public slots: - void receiveImageInfo(double image_width, - double image_height, - double image_x, - double image_y, - double page_width, - double page_height, - bool ratio_is_locked); +//public slots: +// void receiveImageInfo(double image_width, +// double image_height, +// double image_x, +// double image_y, +// double page_width, +// double page_height, +// bool ratio_is_locked); signals: void changeImageProperties(double new_width, double new_height, diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.ui b/ofdEditor/model/Widget/imagepropertiesdialog.ui index 364845c..4a7bb40 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.ui +++ b/ofdEditor/model/Widget/imagepropertiesdialog.ui @@ -6,8 +6,8 @@ 0 0 - 372 - 328 + 374 + 472 @@ -20,16 +20,17 @@ 图片位置 - - + + 宋体 - 12 + 11 + false - 水平 + mm @@ -40,22 +41,21 @@ - - + + 宋体 - 11 - false + 12 - 像素 + 水平 - - + + 10000.000000000000000 @@ -75,48 +75,48 @@ - - + + 宋体 - 12 + 11 + false - 垂直 + mm - - - - 10000.000000000000000 - - - - - + + 宋体 - 11 - false + 12 - 像素 + 垂直 + + + + + + + 10000.000000000000000 - + 10000.000000000000000 - + @@ -130,6 +130,20 @@ + + + + 10000.000000000000000 + + + + + + + 10000.000000000000000 + + + @@ -152,28 +166,44 @@ 图片尺寸 - - + + 宋体 - 12 + 11 + false - 高度 + mm - - - - 10000.000000000000000 + + + + + Agency FB + 11 + + + + QFrame::WinPanel + + + QFrame::Sunken + + + 200 ,200 + + + Qt::AlignCenter - - + + 宋体 @@ -182,33 +212,45 @@ - 像素 + %原尺寸 - - + + + + + 宋体 + 11 + + + + 原始尺寸: + + + + + 10000.000000000000000 - - + + 宋体 - 11 - false + 12 - %原尺寸 + 锁定纵横比 - - + + 宋体 @@ -216,19 +258,19 @@ - 宽度 + 高度 - - + + 10000.000000000000000 - - + + 宋体 @@ -237,19 +279,19 @@ - 像素 + mm - - + + 10000.000000000000000 - - + + 宋体 @@ -263,50 +305,36 @@ - + 宋体 - 11 + 12 - 原始尺寸: + 宽度 - - - - - Agency FB - 11 - - - - QFrame::WinPanel - - - QFrame::Sunken - - - 122 ,122 - - - Qt::AlignCenter + + + + 10000.000000000000000 - - - - - 宋体 - 12 - + + + + 10000.000000000000000 - - 锁定纵横比 + + + + + + 10000.000000000000000 -- Gitee From e54c5e5cd575eb5b5249185c810f66c24e779cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Wed, 9 Aug 2017 21:26:54 +0800 Subject: [PATCH 36/83] =?UTF-8?q?=E7=8E=B0=E6=9C=89bug=EF=BC=8C=E5=87=A0?= =?UTF-8?q?=E4=B8=AA=E4=BA=8B=E4=BB=B6=E7=9B=B8=E4=BA=92=E8=B0=83=E7=94=A8?= =?UTF-8?q?=EF=BC=8C=E9=80=A0=E6=88=90=E6=95=B0=E5=AD=97=E4=B8=8D=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocImageBlock.cpp | 77 +++--- ofdEditor/model/Doc/DocImageBlock.h | 2 +- ofdEditor/model/Doc/DocPage.cpp | 31 ++- .../model/Widget/imagepropertiesdialog.cpp | 255 +++++++++--------- .../model/Widget/imagepropertiesdialog.h | 22 +- .../model/Widget/imagepropertiesdialog.ui | 52 +--- 6 files changed, 201 insertions(+), 238 deletions(-) diff --git a/ofdEditor/model/Doc/DocImageBlock.cpp b/ofdEditor/model/Doc/DocImageBlock.cpp index 15e6693..09a5ef7 100644 --- a/ofdEditor/model/Doc/DocImageBlock.cpp +++ b/ofdEditor/model/Doc/DocImageBlock.cpp @@ -15,19 +15,13 @@ DocImageBlock::DocImageBlock(QWidget *parent) this->setFrameStyle(QFrame::NoFrame); this->setFocusPolicy(Qt::StrongFocus); - qDebug() << "DocImageBlock 1"; - //Initialization // this->properties_dialog = new ImagePropertiesDialog(this, parent); - width_height_ratio_locked = false; + width_height_ratio_locked = true; width_height_ratio = 0.0; - qDebug() << "DocImageBlock 2"; - this->initMenu(); // 初始化右键菜单 - qDebug() << "DocImageBlock 3"; - } /** @@ -44,6 +38,7 @@ void DocImageBlock::setImage(QPixmap & pixmap) pixmap.width()); // 保存实际宽度 this->realHeight = UnitTool::pixelToMM( pixmap.height()); // 保存实际高度 + this->width_height_ratio = this->realWidth / this->realHeight; this->setPixmap(pixmap); } @@ -83,6 +78,7 @@ double DocImageBlock::getWidthHeightRatio() { if (isWidthHeightRatioLocked()) return width_height_ratio; + else return -1; } DocPassage *DocImageBlock::getPassage() @@ -187,17 +183,17 @@ void DocImageBlock::focusOutEvent(QFocusEvent *e) QLabel::focusOutEvent(e); } -/** - * @Author Pan - * @brief 右键菜单 - * @param QContextMenuEvent *ev - * @return void - * @date 2017/06/24 - */ -void DocImageBlock::contextMenuEvent(QContextMenuEvent *ev) -{ - context_menu->exec(ev->globalPos()); -} +///** +// * @Author Pan +// * @brief 右键菜单 +// * @param QContextMenuEvent *ev +// * @return void +// * @date 2017/06/24 +// */ +//void DocImageBlock::contextMenuEvent(QContextMenuEvent *ev) +//{ +// context_menu->exec(ev->globalPos()); +//} /// /// \brief DocImageBlock::initMenu @@ -210,20 +206,13 @@ void DocImageBlock::initMenu() this->change_image = this->context_menu->addAction(tr("ChangeImage")); this->set_image_properties = this->context_menu->addAction(tr("Property")); - - //signal-slots this->connect(this->change_image, SIGNAL(triggered()), this, SLOT(changeImage())); + this->connect(this->set_image_properties, SIGNAL(triggered()), this, SLOT(setImageProperties())); -// this->connect(properties_dialog, -// SIGNAL(changeImageProperties(double,double, -// double,double, -// bool)), -// this, SLOT(imagePropertiesChanged(double,double, -// double,double, -// bool))); + } /** @@ -236,15 +225,18 @@ void DocImageBlock::initMenu() void DocImageBlock::changeImage() { QString fileName = QFileDialog::getOpenFileName(this, - tr("Open File"), QDir::currentPath()); - if (!fileName.isEmpty()) { + tr("Open File"), QDir::currentPath()); + if (!fileName.isEmpty()) + { QPixmap image(fileName); - if (image.isNull()) { + if (image.isNull()) + { QMessageBox::information(this, tr("OFD Editor"), tr("Cannot open file %1.").arg(fileName)); return; } - this->setPixmap(image); + this->setImage(image); + } } @@ -257,14 +249,6 @@ void DocImageBlock::changeImage() */ void DocImageBlock::setImageProperties() { -// emit sendImageInfo(this->width(), -// this->height(), -// this->pos().x(), -// this->pos().y(), -// this->block->getPage()->width(), -// this->block->getPage()->height(), -// this->width_height_ratio_locked); -// properties_dialog->exec(); ImagePropertiesDialog* dialog = ImagePropertiesDialog::getInstance(); dialog->init(this); dialog->exec(); @@ -277,14 +261,15 @@ void DocImageBlock::setImageProperties() * @return void * @date 2017/06/25 */ -void DocImageBlock::imagePropertiesChanged(double new_width, - double new_height, - double new_x, - double new_y, - bool ratio_locked) +void DocImageBlock::imagePropertiesChanged( + double new_width, + double new_height, + double new_x, + double new_y, + bool ratio_locked) { - this->resize(new_width, new_height); - this->move(new_x, new_y); + this->block->resize(new_width, new_height); + this->block->setPos(new_x, new_y); this->width_height_ratio_locked = ratio_locked; this->width_height_ratio = new_width / new_height; } diff --git a/ofdEditor/model/Doc/DocImageBlock.h b/ofdEditor/model/Doc/DocImageBlock.h index 0afa700..d7f14a6 100644 --- a/ofdEditor/model/Doc/DocImageBlock.h +++ b/ofdEditor/model/Doc/DocImageBlock.h @@ -49,7 +49,7 @@ public slots: protected: void focusInEvent(QFocusEvent *ev); void focusOutEvent(QFocusEvent *ev); - void contextMenuEvent(QContextMenuEvent *ev); +// void contextMenuEvent(QContextMenuEvent *ev); private: DocBlock * block; //对代理它的DocBlock的引用 diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index 5cf7265..e431410 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -442,8 +442,8 @@ void DocPage::mousePressEvent(QMouseEvent *event) // 不清楚为什么,造型函数在这里编译出错,因此我采取了强制类型转换 // DocBlock * block = qobject_cast(tempItem); - DocBlock * block = (DocBlock *)tempItem; - +// DocBlock * block = (DocBlock *)tempItem; + DocBlock* block = qgraphicsitem_cast(tempItem); if(block != NULL) { this->activeBlock = block; // 存下 block @@ -480,8 +480,6 @@ void DocPage::mousePressEvent(QMouseEvent *event) // qDebug() << "items.size:" <newPos = this->mapToScene(event->pos()); QPointF point = this->newPos - this->oldPos; if (!image_block->isWidthHeightRatioLocked()) + // 如果纵横比未锁定 this->activeBlock->resize(point.rx(),point.ry()); else { + // 如果纵横比锁定 double ratio = image_block->getWidthHeightRatio(); - if(point.rx() < - point.ry() * ratio) + if(point.rx() < point.ry() * ratio) this->activeBlock->resize(point.rx(), point.rx() / ratio); else this->activeBlock->resize(point.ry() * ratio, point.ry()); @@ -649,10 +648,10 @@ void DocPage::init() void DocPage::addImage() { - qDebug() << "???"; +// qDebug() << "Open a QDialog and load an img"; //打开对话框,选取一个图片文件 QString fileName = QFileDialog::getOpenFileName(this, - tr("Open File"), QDir::currentPath()); + tr("Open File"), QDir::homePath()); if (!fileName.isEmpty()) { QPixmap image(fileName); if (image.isNull()) { @@ -668,20 +667,30 @@ void DocPage::addImage() newBlock->setWidget(new_image_block); new_image_block->setImage(image); // 设置图片 double page_width = this->width(), page_height = this->height(); + // qDebug() << "Page Width: " << this->width(); // qDebug() << "Page Height: " << this->height(); // qDebug() << "Image Width: " << image.width(); // qDebug() << "Image Height: " << image.height(); + double ratio; if (image.width() > page_width || image.height() > page_height) { - ratio = std::min(page_width / image.width(), page_height / image.height()); + ratio = std::min( + page_width / image.width(), + page_height / image.height()); ratio *= 0.8; } else ratio = 1.0; + // qDebug() << "Ratio = " << ratio; - newBlock->setPos((page_width - image.width() * ratio) / 2, (page_height - image.height() * ratio) / 2); - newBlock->resize(image.width() * ratio,image.height() * ratio); + newBlock->setPos( + (page_width - image.width() * ratio) / 2, + (page_height - image.height() * ratio) / 2); + + newBlock->resize( + image.width() * ratio, + image.height() * ratio); this->addBlock(newBlock,this->insertBlockInfo->layer); } diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.cpp b/ofdEditor/model/Widget/imagepropertiesdialog.cpp index afe2253..d0d5e72 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.cpp +++ b/ofdEditor/model/Widget/imagepropertiesdialog.cpp @@ -49,26 +49,21 @@ void ImagePropertiesDialog::init(DocImageBlock *_block) // 保存图片原始尺寸 initial_width = this->block->getRealWidth(); initial_height = this->block->getRealWidth(); - // 是否锁定纵横比 - ratio_locked = this->block->isWidthHeightRatioLocked(); // 页大小 this->page_width = this->block->getPage()->getWidth(); this->page_height = this->block->getPage()->getHeight(); - // 像素大小?? - ui->WidthInPixel->setValue(this->block->width()); - ui->HeightInPixel->setValue(this->block->height()); - ui->xInPixel->setValue(this->block->x()); - ui->yInPixel->setValue(this->block->y()); + this->image_width = UnitTool::pixelToMM(this->block->width()); + this->image_height = UnitTool::pixelToMM(this->block->height()); // 图片采用毫米为单位 - ui->WidthInMM->setValue( - UnitTool::pixelToMM( - this->block->width())); - ui->HeightInMM->setValue( - UnitTool::pixelToMM( - this->block->height())); + ui->WidthInMM->setValue(this->image_width); + ui->HeightInMM->setValue(this->image_height); + + qDebug() << this->image_width + << " " + << this->image_height; ui->xInMM->setValue( UnitTool::pixelToMM( @@ -79,50 +74,44 @@ void ImagePropertiesDialog::init(DocImageBlock *_block) // 求比例 ui->WidthInPercentage->setValue( - this->block->width() / this->initial_width * 100.0); + this->image_width / this->initial_width * 100.0); ui->HeightInPercentage->setValue( - this->block->height() / this->initial_height * 100.0); + this->image_height / this->initial_height * 100.0); ui->xInPercentage->setValue( ui->xInMM->value() / this->page_width * 100.0); ui->yInPercentage->setValue( ui->yInMM->value() / this->page_height * 100.0); -} + // 是否锁定纵横比 + ratio_locked = this->block->isWidthHeightRatioLocked(); + if(ratio_locked) + { + this->connect(ui->WidthInMM,SIGNAL(valueChanged(double)), + this, SLOT(Width2HeightTrans(double))); + this->connect(ui->HeightInMM,SIGNAL(valueChanged(double)), + this, SLOT(Height2WidthTrans(double))); + } + + this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2mm(double))); + this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2mm(double))); + this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2mm(double))); + this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2mm(double))); -///** -// * @Author Pan -// * @brief 槽函数,用语接收DocImageBlock的信号后更新自身的信息 -// * @param 若干参数 -// * @return void -// * @date 2017/06/25 -// */ -//void ImagePropertiesDialog::receiveImageInfo(double image_width, -// double image_height, -// double image_x, -// double image_y, -// double page_width, -// double page_height, -// bool ratio_is_locked) { -// ui->LockRatio->setChecked(ratio_is_locked); -// ui->InitialSize->setText(tr("Width: ") + QString::number(image_width) + tr(", Height: ") + QString::number(image_height)); -// initial_width = image_width; -// initial_height = image_height; -// ratio_locked = ratio_is_locked; -// this->page_width = page_width; -// this->page_height = page_height; - -// ui->WidthInPixel->setValue(image_width); -// ui->HeightInPixel->setValue(image_height); -// ui->xInPixel->setValue(image_x); -// ui->yInPixel->setValue(image_y); - -// ui->WidthInPercentage->setValue(ui->WidthInPixel->value() / image_width * 100.0); -// ui->HeightInPercentage->setValue(ui->HeightInPixel->value() / image_height * 100.0); -// ui->xInPercentage->setValue(ui->xInPixel->value() / page_width * 100.0); -// ui->yInPercentage->setValue(ui->yInPixel->value() / page_width * 100.0); - -//} + this->connect(ui->HeightInMM, SIGNAL(valueChanged(double)), + this, SLOT(mm2Percentage(double))); + this->connect(ui->WidthInMM, SIGNAL(valueChanged(double)), + this, SLOT(mm2Percentage(double))); + this->connect(ui->xInMM, SIGNAL(valueChanged(double)), + this, SLOT(mm2Percentage(double))); + this->connect(ui->yInMM, SIGNAL(valueChanged(double)), + this, SLOT(mm2Percentage(double))); + +} ImagePropertiesDialog::~ImagePropertiesDialog() { @@ -144,50 +133,29 @@ void ImagePropertiesDialog::initConnect() this->connect(this, SIGNAL(finished(int)), this, SLOT(finished_slots(int))); + // 锁定纵横比 this->connect(ui->LockRatio, SIGNAL(stateChanged(int)), this, SLOT(lockRatioStateChanged(int))); - this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2Pixel(double))); - this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2Pixel(double))); - this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2Pixel(double))); - this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2Pixel(double))); - this->connect(ui->HeightInPixel, SIGNAL(valueChanged(double)), - this, SLOT(Pixel2Percentage(double))); - this->connect(ui->WidthInPixel, SIGNAL(valueChanged(double)), - this, SLOT(Pixel2Percentage(double))); - this->connect(ui->xInPixel, SIGNAL(valueChanged(double)), - this, SLOT(Pixel2Percentage(double))); - this->connect(ui->yInPixel, SIGNAL(valueChanged(double)), - this, SLOT(Pixel2Percentage(double))); - this->connect(ui->WidthInPixel,SIGNAL(valueChanged(double)), - this, SLOT(Width2HeightTrans(double))); - this->connect(ui->HeightInPixel,SIGNAL(valueChanged(double)), - this, SLOT(Height2WidthTrans(double))); -} +// this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); + +// this->connect(ui->HeightInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->connect(ui->WidthInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->connect(ui->xInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->connect(ui->yInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); -///** -// * @Author Pan -// * @brief 发送信号 -// * @param void -// * @return void -// * @date 2017/06/25 -// */ -//void ImagePropertiesDialog::emitMessage() -//{ -// emit changeImageProperties(ui->WidthInPixel->value(), -// ui->HeightInPixel->value(), -// ui->xInPixel->value(), -// ui->yInPixel->value(), -// ui->LockRatio->isChecked()); - -//// this->disconnect(_block,SIGNAL(sendImageInfo(double,double,double,double,double,double,bool)), -//// this,SLOT(receiveImageInfo(double,double,double,double,double,double,bool))); - -//} +} /// /// \brief ImagePropertiesDialog::finished_slots @@ -198,16 +166,46 @@ void ImagePropertiesDialog::finished_slots(int value) if(value == QDialog::Accepted) { // 点击确认 - emit changeImageProperties(ui->WidthInPixel->value(), - ui->HeightInPixel->value(), - ui->xInPixel->value(), - ui->yInPixel->value(), - ui->LockRatio->isChecked()); + emit changeImageProperties( + UnitTool::mmToPixel(ui->WidthInMM->value()), + UnitTool::mmToPixel(ui->HeightInMM->value()), + UnitTool::mmToPixel(ui->xInMM->value()), + UnitTool::mmToPixel(ui->yInMM->value()), + UnitTool::mmToPixel(ui->LockRatio->isChecked())); } this->disconnect( this, SIGNAL(changeImageProperties(double,double,double,double,bool)), this->block, SLOT(imagePropertiesChanged(double,double,double,double,bool))); + if(this->ratio_locked) + { + // 解除长和宽之间的关联 + this->disconnect(ui->WidthInPercentage, + SIGNAL(valueChanged(double)), + this, SLOT(Width2HeightTrans(double))); + + this->disconnect(ui->HeightInPercentage, + SIGNAL(valueChanged(double)), + this, SLOT(Height2WidthTrans(double))); + } + + this->disconnect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2mm(double))); + this->disconnect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2mm(double))); + this->disconnect(ui->xInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2mm(double))); + this->disconnect(ui->yInPercentage, SIGNAL(valueChanged(double)), + this, SLOT(Percentage2mm(double))); + + this->disconnect(ui->HeightInMM, SIGNAL(valueChanged(double)), + this, SLOT(mm2Percentage(double))); + this->disconnect(ui->WidthInMM, SIGNAL(valueChanged(double)), + this, SLOT(mm2Percentage(double))); + this->disconnect(ui->xInMM, SIGNAL(valueChanged(double)), + this, SLOT(mm2Percentage(double))); + this->disconnect(ui->yInMM, SIGNAL(valueChanged(double)), + this, SLOT(mm2Percentage(double))); } /** @@ -219,20 +217,33 @@ void ImagePropertiesDialog::finished_slots(int value) */ void ImagePropertiesDialog::lockRatioStateChanged(int locked) { - qDebug() << "Waaaa"; + qDebug() << "lockRatio "; if (locked == Qt::Checked && !ratio_locked) { qDebug() << "Set to Checked."; ratio_locked = true; + // 长和宽之间的关联 + this->connect(ui->WidthInPercentage, + SIGNAL(valueChanged(double)), + this, SLOT(Width2HeightTrans(double))); + + this->connect(ui->HeightInPercentage, + SIGNAL(valueChanged(double)), + this, SLOT(Height2WidthTrans(double))); + } else if (locked == Qt::Unchecked && ratio_locked) { + qDebug() << "Set to Unchecked."; ratio_locked = false; + + // 解除长和宽之间的关联 this->disconnect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), this, SLOT(Width2HeightTrans(double))); + this->disconnect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), this, SLOT(Height2WidthTrans(double))); @@ -252,7 +263,7 @@ void ImagePropertiesDialog::Width2HeightTrans(double value) if (ratio_locked) { double ratio = initial_height / initial_width; - ui->HeightInPixel->setValue(value * ratio); + ui->HeightInMM->setValue(value * ratio); } } @@ -268,42 +279,32 @@ void ImagePropertiesDialog::Height2WidthTrans(double value) if (ratio_locked) { double ratio = initial_width / initial_height; - ui->WidthInPixel->setValue(value * ratio); + ui->WidthInMM->setValue(value * ratio); } } -/** - * @Author Pan - * @brief 从像素量到比例量的同步 - * @param double value - * @return void - * @date 2017/06/25 - */ -void ImagePropertiesDialog::Pixel2Percentage(double value) +void ImagePropertiesDialog::mm2Percentage(double value) { -// static int cnt = 1; -// qDebug() << cnt++; -// qDebug() << ui->HeightInPixel->value(); - ui->HeightInPercentage->setValue(100.0 * ui->HeightInPixel->value() / initial_height); - ui->WidthInPercentage->setValue(100.0 * ui->WidthInPixel->value() / initial_width); - ui->xInPercentage->setValue(100.0 * ui->xInPixel->value() / page_width); - ui->yInPercentage->setValue(100.0 * ui->yInPixel->value() / page_height); + ui->HeightInPercentage->setValue( + 100.0 * ui->HeightInMM->value() / initial_height); + ui->WidthInPercentage->setValue( + 100.0 * ui->WidthInMM->value() / initial_width); + ui->xInPercentage->setValue( + 100.0 * ui->xInMM->value() / page_width); + ui->yInPercentage->setValue( + 100.0 * ui->yInMM->value() / page_height); + qDebug() << "execute 1"; } -/** - * @Author Pan - * @brief 从比例量到像素量的同步 - * @param double value - * @return void - * @date 2017/06/25 - */ -void ImagePropertiesDialog::Percentage2Pixel(double value) +void ImagePropertiesDialog::Percentage2mm(double value) { - ui->HeightInPixel->setValue(ui->HeightInPercentage->value() * initial_height / 100.0); - ui->WidthInPixel->setValue(ui->WidthInPercentage->value() * initial_width / 100.0); - ui->xInPixel->setValue(ui->xInPercentage->value() * page_width / 100.0); - ui->yInPixel->setValue(ui->yInPercentage->value() * page_height / 100.0); + ui->HeightInMM->setValue( + ui->HeightInPercentage->value() * initial_height / 100.0); + ui->WidthInMM->setValue( + ui->WidthInPercentage->value() * initial_width / 100.0); + ui->xInMM->setValue( + ui->xInPercentage->value() * page_width / 100.0); + ui->yInMM->setValue( + ui->yInPercentage->value() * page_height / 100.0); + qDebug() << "execute 2"; } - - - diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.h b/ofdEditor/model/Widget/imagepropertiesdialog.h index 3d839b4..d7f5e69 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.h +++ b/ofdEditor/model/Widget/imagepropertiesdialog.h @@ -32,24 +32,20 @@ private: bool ratio_locked; double page_width; double page_height; + double image_width; + double image_height; void initConnect(); private slots: void finished_slots(int value); // 完成窗口后执行 - void lockRatioStateChanged(int locked); - void Width2HeightTrans(double value); - void Height2WidthTrans(double value); - void Pixel2Percentage(double value); - void Percentage2Pixel(double value); -//public slots: -// void receiveImageInfo(double image_width, -// double image_height, -// double image_x, -// double image_y, -// double page_width, -// double page_height, -// bool ratio_is_locked); + void lockRatioStateChanged(int locked); // 当纵横比锁定发生改变时 + void Width2HeightTrans(double value); // 宽发生改变时作用于高 + void Height2WidthTrans(double value); // 高发生改变时作用于宽 + + void mm2Percentage(double value); // 毫米单位到百分比 + void Percentage2mm(double value); // 百分比单位到毫米 + signals: void changeImageProperties(double new_width, double new_height, diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.ui b/ofdEditor/model/Widget/imagepropertiesdialog.ui index 4a7bb40..d6f6a21 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.ui +++ b/ofdEditor/model/Widget/imagepropertiesdialog.ui @@ -6,8 +6,8 @@ 0 0 - 374 - 472 + 358 + 328 @@ -34,13 +34,6 @@ - - - - 10000.000000000000000 - - - @@ -54,13 +47,6 @@ - - - - 10000.000000000000000 - - - @@ -102,13 +88,6 @@ - - - - 10000.000000000000000 - - - @@ -137,7 +116,14 @@ - + + + + 10000.000000000000000 + + + + 10000.000000000000000 @@ -262,13 +248,6 @@ - - - - 10000.000000000000000 - - - @@ -283,13 +262,6 @@ - - - - 10000.000000000000000 - - - @@ -324,14 +296,14 @@ - + 10000.000000000000000 - + 10000.000000000000000 -- Gitee From b8706644282f98fa6932a5b8ca9891a26d72944a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Thu, 10 Aug 2017 17:11:29 +0800 Subject: [PATCH 37/83] =?UTF-8?q?=E6=9C=89=E9=97=AE=E9=A2=98=EF=BC=8C?= =?UTF-8?q?=E5=85=88=E7=85=A7=E8=BF=99=E4=B8=AA=E6=80=9D=E8=B7=AF=E5=81=9A?= =?UTF-8?q?=E4=B8=8B=E5=8E=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/Widget/imagepropertiesdialog.cpp | 486 ++++++++++++------ .../model/Widget/imagepropertiesdialog.h | 23 +- .../model/Widget/imagepropertiesdialog.ui | 84 +-- 3 files changed, 393 insertions(+), 200 deletions(-) diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.cpp b/ofdEditor/model/Widget/imagepropertiesdialog.cpp index d0d5e72..889c277 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.cpp +++ b/ofdEditor/model/Widget/imagepropertiesdialog.cpp @@ -31,40 +31,38 @@ void ImagePropertiesDialog::DestoryInstance() void ImagePropertiesDialog::init(DocImageBlock *_block) { this->block = _block; // 记录下block - // 建立连接 - this->connect( this, SIGNAL(changeImageProperties(double,double,double,double,bool)), - this->block, SLOT(imagePropertiesChanged(double,double,double,double,bool))); - - // 设置界面显示 - ui->LockRatio->setChecked(this->block->isWidthHeightRatioLocked()); // 是否锁定纵横比 - // 图片实际尺寸 - ui->InitialSize->setText( - tr("Width: ") - + QString::number(this->block->getRealWidth()) - + tr(" mm") - + tr(", Height: ") - + QString::number(this->block->getRealHeight()) - + tr(" mm")); + // 先更新数据,后建立连接 // 保存图片原始尺寸 - initial_width = this->block->getRealWidth(); - initial_height = this->block->getRealWidth(); + this->initial_width = this->block->getRealWidth(); + this->initial_height = this->block->getRealHeight(); // 页大小 this->page_width = this->block->getPage()->getWidth(); this->page_height = this->block->getPage()->getHeight(); + // 图片大小 this->image_width = UnitTool::pixelToMM(this->block->width()); this->image_height = UnitTool::pixelToMM(this->block->height()); + // 图片位置+++ + this->pos_x = UnitTool::pixelToMM( this->block->x()); + this->pos_y = UnitTool::pixelToMM( this->block->y()); + + // 修改界面显示内容 + // 图片实际尺寸 + ui->InitialSize->setText( + tr("Width: ") + + QString::number(this->image_width) + + tr(" mm") + + tr(", Height: ") + + QString::number(this->image_height) + + tr(" mm")); + // 图片采用毫米为单位 ui->WidthInMM->setValue(this->image_width); ui->HeightInMM->setValue(this->image_height); - qDebug() << this->image_width - << " " - << this->image_height; - ui->xInMM->setValue( UnitTool::pixelToMM( this->block->x())); @@ -85,31 +83,48 @@ void ImagePropertiesDialog::init(DocImageBlock *_block) // 是否锁定纵横比 ratio_locked = this->block->isWidthHeightRatioLocked(); - if(ratio_locked) - { - this->connect(ui->WidthInMM,SIGNAL(valueChanged(double)), - this, SLOT(Width2HeightTrans(double))); - this->connect(ui->HeightInMM,SIGNAL(valueChanged(double)), - this, SLOT(Height2WidthTrans(double))); - } +// if(ratio_locked) +// { +// this->connect(ui->WidthInMM,SIGNAL(valueChanged(double)), +// this, SLOT(Width2HeightTrans(double))); +// this->connect(ui->HeightInMM,SIGNAL(valueChanged(double)), +// this, SLOT(Height2WidthTrans(double))); +// } +// // 设置界面显示 + ui->LockRatio->setChecked( + this->block->isWidthHeightRatioLocked()); // 是否锁定纵横比 - this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2mm(double))); - this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2mm(double))); - this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2mm(double))); - this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2mm(double))); - - this->connect(ui->HeightInMM, SIGNAL(valueChanged(double)), - this, SLOT(mm2Percentage(double))); - this->connect(ui->WidthInMM, SIGNAL(valueChanged(double)), - this, SLOT(mm2Percentage(double))); - this->connect(ui->xInMM, SIGNAL(valueChanged(double)), - this, SLOT(mm2Percentage(double))); - this->connect(ui->yInMM, SIGNAL(valueChanged(double)), - this, SLOT(mm2Percentage(double))); + + // 建立连接 + this->connect( + this, + SIGNAL( + changeImageProperties( + double,double,double,double,bool)), + this->block, + SLOT( + imagePropertiesChanged( + double,double,double,double,bool))); + + +// // 初始化信号槽链接 +// this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); + +// this->connect(ui->HeightInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->connect(ui->WidthInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->connect(ui->xInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->connect(ui->yInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); } @@ -137,23 +152,29 @@ void ImagePropertiesDialog::initConnect() this->connect(ui->LockRatio, SIGNAL(stateChanged(int)), this, SLOT(lockRatioStateChanged(int))); -// this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); + // x mm + this->connect(ui->xInMM, SIGNAL(editingFinished()), + this, SLOT(editfinished_MM_x())); -// this->connect(ui->HeightInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->connect(ui->WidthInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->connect(ui->xInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->connect(ui->yInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); + // x percentage + this->connect(ui->xInPercentage, SIGNAL(editingFinished()), + this, SLOT(editfinished_percentage_x())); + + // y mm + this->connect(ui->yInMM, SIGNAL(editingFinished()), + this, SLOT(editfinished_MM_y())); + + // y percentage + this->connect(ui->yInPercentage, SIGNAL(editingFinished()), + this, SLOT(editfinished_percentage_y())); + + // 处理x改变 + this->connect(this, SIGNAL(valueChanged_x(double)), + this, SLOT(slots_valueChanged_x(double))); + + // 处理y改变 + this->connect(this, SIGNAL(valueChanged_y(double)), + this, SLOT(slots_valueChanged_y(double))); } @@ -177,35 +198,35 @@ void ImagePropertiesDialog::finished_slots(int value) this->disconnect( this, SIGNAL(changeImageProperties(double,double,double,double,bool)), this->block, SLOT(imagePropertiesChanged(double,double,double,double,bool))); - if(this->ratio_locked) - { - // 解除长和宽之间的关联 - this->disconnect(ui->WidthInPercentage, - SIGNAL(valueChanged(double)), - this, SLOT(Width2HeightTrans(double))); - - this->disconnect(ui->HeightInPercentage, - SIGNAL(valueChanged(double)), - this, SLOT(Height2WidthTrans(double))); - } +// if(this->ratio_locked) +// { +// // 解除长和宽之间的关联 +// this->disconnect(ui->WidthInPercentage, +// SIGNAL(valueChanged(double)), +// this, SLOT(Width2HeightTrans(double))); + +// this->disconnect(ui->HeightInPercentage, +// SIGNAL(valueChanged(double)), +// this, SLOT(Height2WidthTrans(double))); +// } - this->disconnect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2mm(double))); - this->disconnect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2mm(double))); - this->disconnect(ui->xInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2mm(double))); - this->disconnect(ui->yInPercentage, SIGNAL(valueChanged(double)), - this, SLOT(Percentage2mm(double))); - - this->disconnect(ui->HeightInMM, SIGNAL(valueChanged(double)), - this, SLOT(mm2Percentage(double))); - this->disconnect(ui->WidthInMM, SIGNAL(valueChanged(double)), - this, SLOT(mm2Percentage(double))); - this->disconnect(ui->xInMM, SIGNAL(valueChanged(double)), - this, SLOT(mm2Percentage(double))); - this->disconnect(ui->yInMM, SIGNAL(valueChanged(double)), - this, SLOT(mm2Percentage(double))); +// this->disconnect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->disconnect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->disconnect(ui->xInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->disconnect(ui->yInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); + +// this->disconnect(ui->HeightInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->disconnect(ui->WidthInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->disconnect(ui->xInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->disconnect(ui->yInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); } /** @@ -217,37 +238,102 @@ void ImagePropertiesDialog::finished_slots(int value) */ void ImagePropertiesDialog::lockRatioStateChanged(int locked) { - qDebug() << "lockRatio "; - if (locked == Qt::Checked && !ratio_locked) - { - qDebug() << "Set to Checked."; - ratio_locked = true; + this->ratio_locked = locked; +// qDebug() << "lockRatio "; +// if (locked == Qt::Checked && !ratio_locked) +// { +// qDebug() << "Set to Checked."; +// ratio_locked = true; + +// // 长和宽之间的关联 +// this->connect(ui->WidthInMM, +// SIGNAL(valueChanged(double)), +// this, SLOT(Width2HeightTrans(double))); + +// this->connect(ui->HeightInMM, +// SIGNAL(valueChanged(double)), +// this, SLOT(Height2WidthTrans(double))); + +// } +// else if (locked == Qt::Unchecked && ratio_locked) +// { + +// qDebug() << "Set to Unchecked."; +// ratio_locked = false; + +// // 解除长和宽之间的关联 +// this->disconnect(ui->WidthInMM, +// SIGNAL(valueChanged(double)), +// this, SLOT(Width2HeightTrans(double))); + +// this->disconnect(ui->HeightInMM, +// SIGNAL(valueChanged(double)), +// this, SLOT(Height2WidthTrans(double))); +// } +} - // 长和宽之间的关联 - this->connect(ui->WidthInPercentage, - SIGNAL(valueChanged(double)), - this, SLOT(Width2HeightTrans(double))); +/// +/// \brief ImagePropertiesDialog::editfinished_MM_x +/// 修改了 x mm +void ImagePropertiesDialog::editfinished_MM_x() +{ + this->pos_x = ui->xInMM->value(); + emit this->valueChanged_x(this->pos_x); - this->connect(ui->HeightInPercentage, - SIGNAL(valueChanged(double)), - this, SLOT(Height2WidthTrans(double))); +} - } - else if (locked == Qt::Unchecked && ratio_locked) - { +/// +/// \brief ImagePropertiesDialog::editfinished_MM_y +/// 修改了 y mm +/// +void ImagePropertiesDialog::editfinished_MM_y() +{ + this->pos_y = ui->yInMM->value(); + emit this->valueChanged_y(this->pos_y); +} - qDebug() << "Set to Unchecked."; - ratio_locked = false; +/// +/// \brief ImagePropertiesDialog::editfinished_percentage_x +/// 修改了 x percentage +/// +void ImagePropertiesDialog::editfinished_percentage_x() +{ + this->pos_x = ui->xInPercentage->value() * this->page_width / 100.0; + emit this->valueChanged_x(this->pos_x); +} + +/// +/// \brief ImagePropertiesDialog::editfinished_percentage_y +/// 修改了 y percentages +/// +void ImagePropertiesDialog::editfinished_percentage_y() +{ + this->pos_y = ui->yInPercentage->value() * this->page_height / 100.0; + emit this->valueChanged_y(this->pos_y); +} - // 解除长和宽之间的关联 - this->disconnect(ui->WidthInPercentage, - SIGNAL(valueChanged(double)), - this, SLOT(Width2HeightTrans(double))); +/// +/// \brief ImagePropertiesDialog::slots_valueChanged_x +/// 当x发生改变时进行处理 +/// \param x +/// +void ImagePropertiesDialog::slots_valueChanged_x(double x) +{ + ui->xInMM->setValue(x); + ui->xInPercentage->setValue( + 100.0 * x / this->page_width); +} - this->disconnect(ui->HeightInPercentage, - SIGNAL(valueChanged(double)), - this, SLOT(Height2WidthTrans(double))); - } +/// +/// \brief ImagePropertiesDialog::slots_valueChanged_y +/// 当y发生改变时触发 +/// \param y +/// +void ImagePropertiesDialog::slots_valueChanged_y(double y) +{ + ui->yInMM->setValue(y); + ui->yInPercentage->setValue( + 100.0 * y / this->page_height); } /** @@ -257,15 +343,21 @@ void ImagePropertiesDialog::lockRatioStateChanged(int locked) * @return void * @date 2017/06/25 */ -void ImagePropertiesDialog::Width2HeightTrans(double value) -{ - //qDebug() << "W2H"; - if (ratio_locked) - { - double ratio = initial_height / initial_width; - ui->HeightInMM->setValue(value * ratio); - } -} +//void ImagePropertiesDialog::Width2HeightTrans(double value) +//{ +// qDebug() << "W2H"; +// if (ratio_locked) +// { +// double ratio = initial_height / initial_width * 1.0; +// qDebug() << value +// <<" " +// << value * ratio +// << ratio +// << initial_width +// << initial_height; +// ui->HeightInMM->setValue(value * ratio); +// } +//} /** * @Author Pan @@ -274,37 +366,123 @@ void ImagePropertiesDialog::Width2HeightTrans(double value) * @return void * @date 2017/06/25 */ -void ImagePropertiesDialog::Height2WidthTrans(double value) -{ - if (ratio_locked) - { - double ratio = initial_width / initial_height; - ui->WidthInMM->setValue(value * ratio); - } -} +//void ImagePropertiesDialog::Height2WidthTrans(double value) +//{ +// qDebug() << "H2W";; +// if (ratio_locked) +// { +// double ratio = initial_width / initial_height * 1.0; +// qDebug() << value +// <<" " +// <WidthInMM->setValue(value * ratio); +// } +//} -void ImagePropertiesDialog::mm2Percentage(double value) -{ - ui->HeightInPercentage->setValue( - 100.0 * ui->HeightInMM->value() / initial_height); - ui->WidthInPercentage->setValue( - 100.0 * ui->WidthInMM->value() / initial_width); - ui->xInPercentage->setValue( - 100.0 * ui->xInMM->value() / page_width); - ui->yInPercentage->setValue( - 100.0 * ui->yInMM->value() / page_height); - qDebug() << "execute 1"; -} +/// +/// \brief ImagePropertiesDialog::mm2Percentage +/// 修改毫米值时将内容同步到百分比的值上 +/// \param value +/// +//void ImagePropertiesDialog::mm2Percentage(double value) +//{ +// // 修改百分比时先断开和毫米的链接 +// this->disconnect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->disconnect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->disconnect(ui->xInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->disconnect(ui->yInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->disconnect(ui->HeightInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->disconnect(ui->WidthInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->disconnect(ui->xInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->disconnect(ui->yInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); -void ImagePropertiesDialog::Percentage2mm(double value) -{ - ui->HeightInMM->setValue( - ui->HeightInPercentage->value() * initial_height / 100.0); - ui->WidthInMM->setValue( - ui->WidthInPercentage->value() * initial_width / 100.0); - ui->xInMM->setValue( - ui->xInPercentage->value() * page_width / 100.0); - ui->yInMM->setValue( - ui->yInPercentage->value() * page_height / 100.0); - qDebug() << "execute 2"; -} +// ui->HeightInPercentage->setValue( +// 100.0 * ui->HeightInMM->value() / initial_height); +// ui->WidthInPercentage->setValue( +// 100.0 * ui->WidthInMM->value() / initial_width); +// ui->xInPercentage->setValue( +// 100.0 * ui->xInMM->value() / page_width); +// ui->yInPercentage->setValue( +// 100.0 * ui->yInMM->value() / page_height); + +// this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->connect(ui->HeightInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->connect(ui->WidthInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->connect(ui->xInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->connect(ui->yInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); + +// qDebug() << "execute 1"; +//} + +/// +/// \brief ImagePropertiesDialog::Percentage2mm +/// 修改百分比的值时,将毫米的值也给修改了 +/// \param value +/// +//void ImagePropertiesDialog::Percentage2mm(double value) +//{ +// this->disconnect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->disconnect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->disconnect(ui->xInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->disconnect(ui->yInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->disconnect(ui->HeightInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->disconnect(ui->WidthInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->disconnect(ui->xInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->disconnect(ui->yInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); + +// ui->HeightInMM->setValue( +// ui->HeightInPercentage->value() * initial_height / 100.0); +// ui->WidthInMM->setValue( +// ui->WidthInPercentage->value() * initial_width / 100.0); +// ui->xInMM->setValue( +// ui->xInPercentage->value() * page_width / 100.0); +// ui->yInMM->setValue( +// ui->yInPercentage->value() * page_height / 100.0); + +// this->connect(ui->HeightInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->connect(ui->WidthInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->connect(ui->xInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); +// this->connect(ui->yInMM, SIGNAL(valueChanged(double)), +// this, SLOT(mm2Percentage(double))); + +// this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); +// this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), +// this, SLOT(Percentage2mm(double))); + +// qDebug() << "execute 2"; +//} diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.h b/ofdEditor/model/Widget/imagepropertiesdialog.h index d7f5e69..30422ea 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.h +++ b/ofdEditor/model/Widget/imagepropertiesdialog.h @@ -29,6 +29,8 @@ private: // 使用毫米为单位 double initial_width; double initial_height; + double pos_x; + double pos_y; bool ratio_locked; double page_width; double page_height; @@ -40,11 +42,18 @@ private: private slots: void finished_slots(int value); // 完成窗口后执行 void lockRatioStateChanged(int locked); // 当纵横比锁定发生改变时 - void Width2HeightTrans(double value); // 宽发生改变时作用于高 - void Height2WidthTrans(double value); // 高发生改变时作用于宽 +// void Width2HeightTrans(double value); // 宽发生改变时作用于高 +// void Height2WidthTrans(double value); // 高发生改变时作用于宽 - void mm2Percentage(double value); // 毫米单位到百分比 - void Percentage2mm(double value); // 百分比单位到毫米 +// void mm2Percentage(double value); // 毫米单位到百分比 +// void Percentage2mm(double value); // 百分比单位到毫米 + void editfinished_MM_x(); + void editfinished_MM_y(); + void editfinished_percentage_x(); + void editfinished_percentage_y(); + + void slots_valueChanged_x(double x); // 当x发生改变时处理 + void slots_valueChanged_y(double y); // 当y发生改变时处理 signals: void changeImageProperties(double new_width, @@ -52,6 +61,12 @@ signals: double new_x, double new_y, bool ratio_locked); + + void valueChanged_x(double x); // 图片位置被修改 + void valueChanged_y(double y); // 图片位置被修改 + + void valueChanged_width(double width); // 图片大小被修改 + void valueChanged_height(double height);// 图片大小被修改 }; #endif // IMAGEPROPERTIESDIALOG_H diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.ui b/ofdEditor/model/Widget/imagepropertiesdialog.ui index d6f6a21..1c13d50 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.ui +++ b/ofdEditor/model/Widget/imagepropertiesdialog.ui @@ -6,8 +6,8 @@ 0 0 - 358 - 328 + 508 + 407 @@ -152,21 +152,20 @@ 图片尺寸 - - + + 宋体 - 11 - false + 12 - mm + 宽度 - + @@ -188,54 +187,55 @@ - - + + + + 10000.000000000000000 + + + + + 宋体 11 - false - %原尺寸 + 原始尺寸: - - + + 宋体 11 + false - 原始尺寸: - - - - - - - 10000.000000000000000 + %原尺寸 - - + + 宋体 - 12 + 11 + false - 锁定纵横比 + mm - + @@ -248,7 +248,14 @@ - + + + + 10000.000000000000000 + + + + @@ -262,7 +269,7 @@ - + @@ -276,8 +283,8 @@ - - + + 宋体 @@ -285,31 +292,24 @@ - 宽度 + 锁定纵横比 - - + + 10000.000000000000000 - + 10000.000000000000000 - - - - 10000.000000000000000 - - - -- Gitee From 1d7dab0640980b43586ac977110fba09dc9c4e24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Thu, 10 Aug 2017 19:59:39 +0800 Subject: [PATCH 38/83] =?UTF-8?q?=E5=9B=BE=E7=89=87=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E7=AA=97=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/Widget/imagepropertiesdialog.cpp | 326 +++++------------- .../model/Widget/imagepropertiesdialog.h | 15 +- 2 files changed, 102 insertions(+), 239 deletions(-) diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.cpp b/ofdEditor/model/Widget/imagepropertiesdialog.cpp index 889c277..05ffb1e 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.cpp +++ b/ofdEditor/model/Widget/imagepropertiesdialog.cpp @@ -83,18 +83,11 @@ void ImagePropertiesDialog::init(DocImageBlock *_block) // 是否锁定纵横比 ratio_locked = this->block->isWidthHeightRatioLocked(); -// if(ratio_locked) -// { -// this->connect(ui->WidthInMM,SIGNAL(valueChanged(double)), -// this, SLOT(Width2HeightTrans(double))); -// this->connect(ui->HeightInMM,SIGNAL(valueChanged(double)), -// this, SLOT(Height2WidthTrans(double))); -// } -// // 设置界面显示 + + // 设置界面显示 ui->LockRatio->setChecked( this->block->isWidthHeightRatioLocked()); // 是否锁定纵横比 - // 建立连接 this->connect( this, @@ -106,26 +99,6 @@ void ImagePropertiesDialog::init(DocImageBlock *_block) imagePropertiesChanged( double,double,double,double,bool))); - -// // 初始化信号槽链接 -// this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); - -// this->connect(ui->HeightInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->connect(ui->WidthInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->connect(ui->xInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->connect(ui->yInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); - } ImagePropertiesDialog::~ImagePropertiesDialog() @@ -176,6 +149,30 @@ void ImagePropertiesDialog::initConnect() this->connect(this, SIGNAL(valueChanged_y(double)), this, SLOT(slots_valueChanged_y(double))); + // width mm + this->connect(ui->WidthInMM, SIGNAL(editingFinished()), + this, SLOT(editfinished_MM_width())); + + // width percentage + this->connect(ui->WidthInPercentage, SIGNAL(editingFinished()), + this, SLOT(editfinished_percentage_width())); + + // height mm + this->connect(ui->HeightInMM, SIGNAL(editingFinished()), + this, SLOT(editfinished_MM_height())); + + // height percentage + this->connect(ui->HeightInPercentage, SIGNAL(editingFinished()), + this,SLOT(editfinished_percentage_height())); + + // 处理width改变 + this->connect(this, SIGNAL(valueChanged_width(double)), + this, SLOT(slots_valueChanged_width(double))); + + // 处理height改变 + this->connect(this, SIGNAL(valueChanged_height(double)), + this, SLOT(slots_valueChanged_height(double))); + } /// @@ -198,35 +195,6 @@ void ImagePropertiesDialog::finished_slots(int value) this->disconnect( this, SIGNAL(changeImageProperties(double,double,double,double,bool)), this->block, SLOT(imagePropertiesChanged(double,double,double,double,bool))); -// if(this->ratio_locked) -// { -// // 解除长和宽之间的关联 -// this->disconnect(ui->WidthInPercentage, -// SIGNAL(valueChanged(double)), -// this, SLOT(Width2HeightTrans(double))); - -// this->disconnect(ui->HeightInPercentage, -// SIGNAL(valueChanged(double)), -// this, SLOT(Height2WidthTrans(double))); -// } - -// this->disconnect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->disconnect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->disconnect(ui->xInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->disconnect(ui->yInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); - -// this->disconnect(ui->HeightInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->disconnect(ui->WidthInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->disconnect(ui->xInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->disconnect(ui->yInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); } /** @@ -239,37 +207,7 @@ void ImagePropertiesDialog::finished_slots(int value) void ImagePropertiesDialog::lockRatioStateChanged(int locked) { this->ratio_locked = locked; -// qDebug() << "lockRatio "; -// if (locked == Qt::Checked && !ratio_locked) -// { -// qDebug() << "Set to Checked."; -// ratio_locked = true; - -// // 长和宽之间的关联 -// this->connect(ui->WidthInMM, -// SIGNAL(valueChanged(double)), -// this, SLOT(Width2HeightTrans(double))); - -// this->connect(ui->HeightInMM, -// SIGNAL(valueChanged(double)), -// this, SLOT(Height2WidthTrans(double))); - -// } -// else if (locked == Qt::Unchecked && ratio_locked) -// { - -// qDebug() << "Set to Unchecked."; -// ratio_locked = false; - -// // 解除长和宽之间的关联 -// this->disconnect(ui->WidthInMM, -// SIGNAL(valueChanged(double)), -// this, SLOT(Width2HeightTrans(double))); - -// this->disconnect(ui->HeightInMM, -// SIGNAL(valueChanged(double)), -// this, SLOT(Height2WidthTrans(double))); -// } + } /// @@ -312,6 +250,31 @@ void ImagePropertiesDialog::editfinished_percentage_y() emit this->valueChanged_y(this->pos_y); } +void ImagePropertiesDialog::editfinished_MM_width() +{ + this->image_width = ui->WidthInMM->value(); + emit this->valueChanged_width(this->image_width); + +} + +void ImagePropertiesDialog::editfinished_MM_height() +{ + this->image_height = ui->HeightInMM->value(); + emit this->valueChanged_height(this->image_height); +} + +void ImagePropertiesDialog::editfinished_percentage_width() +{ + this->image_width = ui->WidthInPercentage->value() * this->initial_width / 100.0; + emit this->valueChanged_width(this->image_width); +} + +void ImagePropertiesDialog::editfinished_percentage_height() +{ + this->image_height = ui->HeightInPercentage->value() / 100.0 * this->initial_height; + emit this->valueChanged_height(this->image_height); +} + /// /// \brief ImagePropertiesDialog::slots_valueChanged_x /// 当x发生改变时进行处理 @@ -336,153 +299,48 @@ void ImagePropertiesDialog::slots_valueChanged_y(double y) 100.0 * y / this->page_height); } -/** - * @Author Pan - * @brief 锁定纵横比时,宽度到高度的按比例同步 - * @param double value - * @return void - * @date 2017/06/25 - */ -//void ImagePropertiesDialog::Width2HeightTrans(double value) -//{ -// qDebug() << "W2H"; -// if (ratio_locked) -// { -// double ratio = initial_height / initial_width * 1.0; -// qDebug() << value -// <<" " -// << value * ratio -// << ratio -// << initial_width -// << initial_height; -// ui->HeightInMM->setValue(value * ratio); -// } -//} - -/** - * @Author Pan - * @brief 锁定纵横比时,高度到宽度的按比例同步 - * @param double value - * @return void - * @date 2017/06/25 - */ -//void ImagePropertiesDialog::Height2WidthTrans(double value) -//{ -// qDebug() << "H2W";; -// if (ratio_locked) -// { -// double ratio = initial_width / initial_height * 1.0; -// qDebug() << value -// <<" " -// <WidthInMM->setValue(value * ratio); -// } -//} - /// -/// \brief ImagePropertiesDialog::mm2Percentage -/// 修改毫米值时将内容同步到百分比的值上 -/// \param value +/// \brief ImagePropertiesDialog::slots_valueChanged_width +/// 处理当宽度发生改变时 +/// \param width /// -//void ImagePropertiesDialog::mm2Percentage(double value) -//{ -// // 修改百分比时先断开和毫米的链接 -// this->disconnect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->disconnect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->disconnect(ui->xInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->disconnect(ui->yInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->disconnect(ui->HeightInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->disconnect(ui->WidthInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->disconnect(ui->xInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->disconnect(ui->yInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); - -// ui->HeightInPercentage->setValue( -// 100.0 * ui->HeightInMM->value() / initial_height); -// ui->WidthInPercentage->setValue( -// 100.0 * ui->WidthInMM->value() / initial_width); -// ui->xInPercentage->setValue( -// 100.0 * ui->xInMM->value() / page_width); -// ui->yInPercentage->setValue( -// 100.0 * ui->yInMM->value() / page_height); - -// this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->connect(ui->HeightInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->connect(ui->WidthInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->connect(ui->xInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->connect(ui->yInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); - -// qDebug() << "execute 1"; -//} +void ImagePropertiesDialog::slots_valueChanged_width(double width) +{ + ui->WidthInMM->setValue(width); + ui->WidthInPercentage->setValue( + 100.0 * width / this->initial_width); + + // 如果锁定纵横比 + if(this->ratio_locked) + { + double ratio = initial_height / initial_width; + this->image_height = width * ratio; + + ui->HeightInMM->setValue(this->image_height); + ui->HeightInPercentage->setValue( + 100.0 * this->image_height / this->initial_height); + } +} /// -/// \brief ImagePropertiesDialog::Percentage2mm -/// 修改百分比的值时,将毫米的值也给修改了 -/// \param value +/// \brief ImagePropertiesDialog::slots_valueChanged_height +/// 处理当高度发生改变时 +/// \param height /// -//void ImagePropertiesDialog::Percentage2mm(double value) -//{ -// this->disconnect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->disconnect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->disconnect(ui->xInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->disconnect(ui->yInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->disconnect(ui->HeightInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->disconnect(ui->WidthInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->disconnect(ui->xInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->disconnect(ui->yInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); - -// ui->HeightInMM->setValue( -// ui->HeightInPercentage->value() * initial_height / 100.0); -// ui->WidthInMM->setValue( -// ui->WidthInPercentage->value() * initial_width / 100.0); -// ui->xInMM->setValue( -// ui->xInPercentage->value() * page_width / 100.0); -// ui->yInMM->setValue( -// ui->yInPercentage->value() * page_height / 100.0); - -// this->connect(ui->HeightInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->connect(ui->WidthInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->connect(ui->xInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); -// this->connect(ui->yInMM, SIGNAL(valueChanged(double)), -// this, SLOT(mm2Percentage(double))); - -// this->connect(ui->HeightInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->connect(ui->WidthInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->connect(ui->xInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); -// this->connect(ui->yInPercentage, SIGNAL(valueChanged(double)), -// this, SLOT(Percentage2mm(double))); - -// qDebug() << "execute 2"; -//} +void ImagePropertiesDialog::slots_valueChanged_height(double height) +{ + ui->HeightInMM->setValue(height); + ui->HeightInPercentage->setValue( + 100.0 * height / this->initial_height); + + // 如果锁定纵横比 + if(this->ratio_locked) + { + double ratio = this->initial_width / this-> initial_height; + this->image_width = height * ratio; + + ui->WidthInMM->setValue(this->image_width); + ui->WidthInPercentage->setValue( + 100.0 * this->image_width / this->initial_width); + } +} diff --git a/ofdEditor/model/Widget/imagepropertiesdialog.h b/ofdEditor/model/Widget/imagepropertiesdialog.h index 30422ea..f94a51f 100644 --- a/ofdEditor/model/Widget/imagepropertiesdialog.h +++ b/ofdEditor/model/Widget/imagepropertiesdialog.h @@ -15,7 +15,7 @@ class ImagePropertiesDialog : public QDialog public: static ImagePropertiesDialog* getInstance(); // 获得单例 - static void DestoryInstance(); // 销毁单例 + static void DestoryInstance(); // 销毁单例 void init(DocImageBlock* _block); // 使用时初始化 ~ImagePropertiesDialog(); @@ -42,19 +42,24 @@ private: private slots: void finished_slots(int value); // 完成窗口后执行 void lockRatioStateChanged(int locked); // 当纵横比锁定发生改变时 -// void Width2HeightTrans(double value); // 宽发生改变时作用于高 -// void Height2WidthTrans(double value); // 高发生改变时作用于宽 -// void mm2Percentage(double value); // 毫米单位到百分比 -// void Percentage2mm(double value); // 百分比单位到毫米 void editfinished_MM_x(); void editfinished_MM_y(); void editfinished_percentage_x(); void editfinished_percentage_y(); + + void editfinished_MM_width(); + void editfinished_MM_height(); + void editfinished_percentage_width(); + void editfinished_percentage_height(); + void slots_valueChanged_x(double x); // 当x发生改变时处理 void slots_valueChanged_y(double y); // 当y发生改变时处理 + void slots_valueChanged_width(double width); // 当width发生改变时触发 + void slots_valueChanged_height(double height); // 当height发生改变时触发 + signals: void changeImageProperties(double new_width, double new_height, -- Gitee From 29d4986f96dc481f9560a5c32afe25dff6323388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Thu, 10 Aug 2017 21:43:13 +0800 Subject: [PATCH 39/83] =?UTF-8?q?=E5=87=86=E5=A4=87=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E5=8F=B3=E9=94=AE=E8=8F=9C=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocPage.cpp | 13 +++++++------ ofdEditor/model/Doc/DocPage.h | 6 +++++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index e431410..85e2c9b 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -348,12 +348,12 @@ void DocPage::contextMenuEvent(QContextMenuEvent *event) QPoint pos = event->pos(); // 获得相对于页面的 QList items = this->items(pos); // 获得某鼠标下的所有块 - qDebug() << "There are" - << items.size() - << " items at position " - << event->pos() - << " scene:" - << this->mapToScene(event->pos()); +// qDebug() << "There are" +// << items.size() +// << " items at position " +// << event->pos() +// << " scene:" +// << this->mapToScene(event->pos()); QMenu* seletion = new QMenu(); seletion->setTitle(tr("seletion")); @@ -363,6 +363,7 @@ void DocPage::contextMenuEvent(QContextMenuEvent *event) // 将qgraphicsItem造型成为DocBlock if(items[i]->type() == DocBlock::Type) { + // 向下造型 DocBlock* block = qgraphicsitem_cast(items[i]); if(block != NULL) { diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index 8a6e441..aebf68b 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -8,6 +8,7 @@ #include #include #include +#include // 类声明 class DocLayer; @@ -69,7 +70,7 @@ public slots: void setBlockFlag(BlockFlag flag){this->newBlockFlag = flag;} void setInsertBlockType(InsertBlockInfo& blockInfo); // 设置下一个要插入的block的信息 - void remove(); // 移除本页 + void remove(); // 移除本页 void setScale(double scale); // 设置页面的显示大小 void setWorkingArea( bool isUsingWorkingArea, @@ -112,6 +113,9 @@ private: BlockFlag newBlockFlag; // 是否画块 DocBlock * activeBlock; // 正在活跃的那个DocBlock + + + bool has_working_area; double working_area_width; double working_area_height; -- Gitee From 18cd4311335208e3838d9989f7fbc670c430bde4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Fri, 11 Aug 2017 21:48:25 +0800 Subject: [PATCH 40/83] =?UTF-8?q?=E5=BD=A2=E6=88=90DocBlock=E8=8F=9C?= =?UTF-8?q?=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocBlock.cpp | 149 ++++++++++++++++++++++++++ ofdEditor/model/Doc/DocBlock.h | 30 +++++- ofdEditor/model/Doc/DocImageBlock.cpp | 11 +- ofdEditor/model/Doc/DocLayer.cpp | 11 ++ ofdEditor/model/Doc/DocLayer.h | 1 + ofdEditor/model/Doc/DocPage.cpp | 133 +++++++++++++++++++---- ofdEditor/model/Doc/DocPage.h | 25 ++++- ofdEditor/model/Doc/DocTextBlock.cpp | 68 ++++++++---- 8 files changed, 378 insertions(+), 50 deletions(-) diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index 18c5c5e..6abf8fb 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -32,6 +32,20 @@ DocBlock::DocBlock(QGraphicsItem *parent , Qt::WindowFlags wFlags) this->setAcceptHoverEvents(true); textBlock = NULL; imageBlock = NULL; + + this->initMenu(); +} + +/// +/// \brief DocBlock::Layer +/// \return +/// +DocPage::Layer DocBlock::Layer() +{ + if(this->layer != NULL) + return this->layer->getLayer(); + else + return DocPage::Body; } /** @@ -385,6 +399,15 @@ void DocBlock::setWidget(DocImageBlock * imageBlock) QGraphicsProxyWidget::setWidget(imageBlock); } +/// +/// \brief DocBlock::sizeAndPositionDialog +/// 大小位置调整窗口 +/// +void DocBlock::sizeAndPositionDialog() +{ + +} + /** * @Author Chaoqun * @brief 检查鼠标是否在重置大小区域 @@ -398,6 +421,73 @@ bool DocBlock::isInResizeArea(const QPointF &pos) (this->size().height() - pos.y()); } + +void DocBlock::initMenu() +{ + // 移动到前景层 + this->action_foreground = new QAction(tr("Foreground"), NULL); + + this->connect(this->action_foreground, SIGNAL(triggered(bool)), + this, SLOT(moveToForeground())); + + // 移动到正文层 + this->action_body = new QAction(tr("Body"), NULL); + + this->connect(this->action_body, SIGNAL(triggered(bool)), + this, SLOT(moveToBody())); + + // 移动到背景层 + this->action_background = new QAction(tr("Background"), NULL); + + this->connect(this->action_background, SIGNAL(triggered(bool)), + this, SLOT(moveToBackground())); + + // 删除 + this->action_delete = new QAction(tr("Delete"), NULL); + + this->connect(this->action_delete, SIGNAL(triggered(bool)), + this, SLOT(remove())); + + // 大小和位置调整 + this->action_geometry = new QAction(tr("size and position"), NULL); + + this->connect(this->action_geometry, SIGNAL(triggered(bool)), + this, SLOT(sizeAndPositionDialog())); +} + +/// +/// \brief DocBlock::moveToForeground +/// +void DocBlock::moveToForeground() +{ + if(this->Layer() != DocPage::Foreground) + { + this->getPage()->changeBlockLayer(this, DocPage::Foreground); + } +} + +/// +/// \brief DocBlock::moveToBody +/// +void DocBlock::moveToBody() +{ + if(this->Layer() != DocPage::Body) + { + this->getPage()->changeBlockLayer(this, DocPage::Body); + } +} + +/// +/// \brief DocBlock::moveToBackground +/// +void DocBlock::moveToBackground() +{ + if(this->Layer() != DocPage::Background) + { + this->getPage()->changeBlockLayer(this, DocPage::Background); + } +} + /** * @Author Chaoqun * @brief 检测当前状态是否可以移动块 @@ -456,6 +546,65 @@ DocBlock::RectAdjustStatus DocBlock::currentStatus( QPointF pos) } } +/// +/// \brief DocBlock::getMenu +/// 获得菜单 +/// \return +/// +QMenu *DocBlock::getMenu() +{ + QMenu * menu = new QMenu(); // 新建菜单 + QMenu * menu_layer = new QMenu(tr("Layer")); // 子菜单-层 + menu_layer->addAction(this->action_foreground); + menu_layer->addAction(this->action_body); + menu_layer->addAction(this->action_background); + + // 设置提醒状态 + if(this->Layer() == DocPage::Foreground) + { + this->action_foreground->setChecked(true); + this->action_body->setChecked(false); + this->action_background->setChecked(false); + } + else if(this->Layer() == DocPage::Body) + { + this->action_foreground->setChecked(false); + this->action_body->setChecked(true); + this->action_background->setChecked(false); + } + else if(this->Layer() == DocPage::Background) + { + this->action_foreground->setChecked(false); + this->action_body->setChecked(false); + this->action_background->setChecked(true); + } + + if(this->isTextBlock()) + { + // 文本框 + menu = this->textBlock->getMenu(); + menu->setTitle(this->textBlock->getType()); + + menu->addSeparator(); + menu->addAction(this->action_geometry); + menu->addMenu(menu_layer); + menu->addAction(this->action_delete); + + } + else if(this->isImageBlock()) + { + // 如果是图片 + menu = this->imageBlock->getMenu(); + menu->setTitle(this->imageBlock->getType()); + + menu->addSeparator(); + menu->addMenu(menu_layer); + menu->addAction(this->action_delete); + } + + return menu; +} + /** * @Author Chaoqun * @brief 判断是其中装的是否是DocTextBlock diff --git a/ofdEditor/model/Doc/DocBlock.h b/ofdEditor/model/Doc/DocBlock.h index 36c3ac8..b4ca0ae 100644 --- a/ofdEditor/model/Doc/DocBlock.h +++ b/ofdEditor/model/Doc/DocBlock.h @@ -5,6 +5,9 @@ #include "Doc/DocBasicTypes.h" #include #include +#include +#include +#include "Doc/DocPage.h" class DocLayer; class QPainter; @@ -43,17 +46,26 @@ public: RectAdjustStatus rectAdjust; // 用来标识当前修改尺寸的状态 DocLayer * getLayer(){return this->layer;} // 获得所在的层 + DocPage::Layer Layer(); // 获得所在的层的名称 DocPage * getPage(); // 获得所在页 DocPassage *getPassage(); // 获得所在文章 void paintHandle(QPainter& painter); // 绘制负责变换的控制器 qreal getZValue(){return this->realZValue;} // 获得当前块所在的Z值 RectAdjustStatus currentStatus(QPointF pos); // 鼠标所在位置可以进行什么调整 - bool isTextBlock(); // 判断是否DocBlock装的是否是DocTextBlock - DocTextBlock *getTextBlock(); // 获得DocTextBlock + QMenu *getMenu(); // 根据块和块内部的设置,增加设置窗口 + bool isTextBlock(); // 判断是否DocBlock装的是否是DocTextBlock + DocTextBlock *getTextBlock(); // 获得DocTextBlock bool isImageBlock(); DocImageBlock *getImageBlock(); //获得DocImageBlock + QAction *action_geometry; // 大小和位置 + QAction *action_delete; // 删除块 + + QAction *action_foreground; // 移动到前景 + QAction *action_body; // 移动到正文 + QAction *action_background; // 移动到背景 + public slots: // 槽函数 void setLayer(DocLayer * layer){this->layer = layer;} void resize(qreal w, qreal h); // 继承函数 @@ -62,10 +74,13 @@ public slots: // 槽函数 void setPos(qreal x, qreal y); // 设置位置 // 移动位置应该在所在的DocPage中吧…… void remove(); // 从场景中移除本框 + void setWidget(QWidget* widget); // 旧的函数 void setWidget(DocTextBlock *textBlock); // SetWidget void setWidget(DocImageBlock * imageBlock); + void sizeAndPositionDialog(); // 调整大小和位置窗口 + protected: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, @@ -88,17 +103,24 @@ private: QSizeF blockSize; // 用来纪录大小 QPointF blockOldPos; // 用来记录旧的位置 - DocTextBlock * textBlock; // 存下引用 + DocTextBlock * textBlock; // 存下引用 DocImageBlock * imageBlock; //同上 + qreal realZValue; // 真实的z值 bool isFocused; // 是否被聚焦 bool blockIsResizing; // 是否正在改变大小 bool isInResizeArea(const QPointF& pos); // 检查鼠标是否在重置大小区域 - qreal realZValue; // 真实的z值 + + void initMenu(); // 初始化 signals: void signals_blockRemoved(DocBlock* block); // 当本块被移除时发出信号 +private slots: + void moveToForeground(); // 移动到前景层 + void moveToBody(); // 移动到正文层 + void moveToBackground(); // 移动到背景层 + }; #endif // DOCBLOCK_H diff --git a/ofdEditor/model/Doc/DocImageBlock.cpp b/ofdEditor/model/Doc/DocImageBlock.cpp index 09a5ef7..cc1fab0 100644 --- a/ofdEditor/model/Doc/DocImageBlock.cpp +++ b/ofdEditor/model/Doc/DocImageBlock.cpp @@ -141,6 +141,10 @@ QString DocImageBlock::getType() /// QMenu *DocImageBlock::getMenu() { + this->context_menu->clear(); + this->context_menu->addAction(this->change_image); + this->context_menu->addAction(this->set_image_properties); + return this->context_menu; } @@ -203,8 +207,11 @@ void DocImageBlock::initMenu() { this->context_menu = new QMenu(tr("DocImageBlock")); // 新建菜单 - this->change_image = this->context_menu->addAction(tr("ChangeImage")); - this->set_image_properties = this->context_menu->addAction(tr("Property")); + this->change_image = new QAction(tr("Change Image"), this); + this->set_image_properties = new QAction(tr("Property"), this); + + this->context_menu->addAction(this->change_image); + this->context_menu->addAction(this->set_image_properties); //signal-slots this->connect(this->change_image, SIGNAL(triggered()), diff --git a/ofdEditor/model/Doc/DocLayer.cpp b/ofdEditor/model/Doc/DocLayer.cpp index cd6e820..3418945 100644 --- a/ofdEditor/model/Doc/DocLayer.cpp +++ b/ofdEditor/model/Doc/DocLayer.cpp @@ -153,3 +153,14 @@ DocPassage *DocLayer::getPassage() return NULL; return page->getPassage(); } + +/// +/// \brief DocLayer::hasBlock +/// 检查块中是否包含此元素 +/// \param block +/// \return +/// +bool DocLayer::hasBlock(DocBlock *block) +{ + return this->blocks.contains(block); +} diff --git a/ofdEditor/model/Doc/DocLayer.h b/ofdEditor/model/Doc/DocLayer.h index c8f4d36..34144f8 100644 --- a/ofdEditor/model/Doc/DocLayer.h +++ b/ofdEditor/model/Doc/DocLayer.h @@ -29,6 +29,7 @@ public: DocPage::Layer getLayer(){return type;} DocPage* getPage(); // 找到层所在的Page DocPassage *getPassage(); // 找到文章 + bool hasBlock(DocBlock* block); // 判断是否包含这个块 public slots: diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index 85e2c9b..8f789a3 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -108,6 +108,29 @@ QSize DocPage::getSize() UnitTool::mmToPixel(height_mm)); } +/// +/// \brief DocPage::hasBlock +/// 判断该页面中是否包含某个块 +/// \param block +/// \return +/// +bool DocPage::hasBlock(DocBlock *block) +{ + bool flag = false; + if(this->foregroundLayer->hasBlock(block)) + { + flag = true; + } + if(this->bodyLayer->hasBlock(block)) + { + flag = true; + } + if(this->backgroundLayer->hasBlock(block)) + { + flag = true; + } +} + /** * @Author Chaoqun * @brief 获得前景层 @@ -144,6 +167,28 @@ DocLayer *DocPage::getBackgroundLayer() return this->backgroundLayer; } +/// +/// \brief DocPage::getLayer +/// 获得层 +/// \param layer +/// \return +/// +DocLayer *DocPage::getLayer(DocPage::Layer layer) +{ + if(layer == Foreground) + { + return this->foregroundLayer; + } + else if(layer == Body) + { + return this->bodyLayer; + } + else if(layer == Background) + { + return this->backgroundLayer; + } +} + /** * @Author Chaoqun * @brief 添加一个新的块到页面之中 @@ -205,6 +250,34 @@ void DocPage::addBlock(DocBlock *block, DocPage::Layer layer) } +/// +/// \brief DocPage::changeBlockLayer +/// \param block +/// \param layer +/// +void DocPage::changeBlockLayer(DocBlock *block, DocPage::Layer layer) +{ + if(!this->hasBlock(block)) + { + // 如果本页中不包含此块 + return; + qDebug() << "this page does not has this block."; + } + + DocLayer *doclayer = block->getLayer(); // 获得层 + if(doclayer == NULL) + { + return; + qDebug() << "This block has no layer"; + } + + DocLayer* goalLayer = this->getLayer(layer); // 目标层 + + doclayer->removeBlock(block); // 从原有层中删除 + goalLayer->addBlock(block); // 加入到目标层中 + +} + /** * @Author Chaoqun * @brief 将item添加到scene中 @@ -355,9 +428,6 @@ void DocPage::contextMenuEvent(QContextMenuEvent *event) // << " scene:" // << this->mapToScene(event->pos()); - QMenu* seletion = new QMenu(); - seletion->setTitle(tr("seletion")); - for(int i = 0; i < items.size(); i++) { // 将qgraphicsItem造型成为DocBlock @@ -367,21 +437,7 @@ void DocPage::contextMenuEvent(QContextMenuEvent *event) DocBlock* block = qgraphicsitem_cast(items[i]); if(block != NULL) { - qDebug() << "qt cast success"; - if(block->isTextBlock()) - { - // 如果是文本框 - DocTextBlock* textBlock = block->getTextBlock(); -// seletion->addAction(textBlock->getType()); - menu->addMenu(textBlock->getMenu()); - } - else if(block->isImageBlock()) - { - // 如果是图片 - DocImageBlock* imageBlock = block->getImageBlock(); -// seletion->addAction(imageBlock->getType()); - menu->addMenu(imageBlock->getMenu()); - } + menu->addMenu(block->getMenu()); } else { @@ -391,8 +447,6 @@ void DocPage::contextMenuEvent(QContextMenuEvent *event) } - menu->addMenu(seletion); // 添加子菜单 - menu->exec(event->globalPos()); // 执行菜单 } @@ -645,6 +699,45 @@ void DocPage::init() working_area_width = this->size().width(); working_area_height = this->size().height(); working_area_x = working_area_y = 0; + + this->initMenu(); // 初始化菜单 +} + +/// +/// \brief DocPage::initMenu +/// +void DocPage::initMenu() +{ + this->menu_insert = new QMenu(tr("Insert")); + + // 插入文本框 + this->action_insertTextBlock = new QAction(tr("TextBlock"), NULL); + + // 插入图片 + this->action_insertImageBlock = new QAction(tr("ImageBlock"), NULL); + + // 插入表格 + this->action_insertTable = new QAction(tr("Table"), NULL); + + // 插入页 + this->action_insertPage = new QAction(tr("Page"), NULL); + + //删除本页 + this->action_deletePage = new QAction(tr("This Page"), NULL); + + // 页面设置 + this->action_pageSetting = new QAction(tr("Page Setting"), NULL); +} + +/// +/// \brief DocPage::getMenu +/// 根绝获得的物体生成菜单 +/// \param items +/// \return +/// +QMenu *DocPage::getMenu(QList &items) +{ + } void DocPage::addImage() diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index aebf68b..b0dda9b 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -31,7 +31,7 @@ class MODELSHARED_EXPORT DocPage public: enum Layer{Body,Foreground,Background}; // 分为三层 - enum BlockFlag{none,draw,drawMove,blockMove, blockResize}; // 插入时的绘制状态 + enum BlockFlag{none,draw,drawMove,blockMove, blockResize}; // 插入时的绘制状态 enum BlockType{text,image,table}; // 插入时的类型 explicit DocPage(QWidget * parent = 0); DocPage(double width, @@ -44,10 +44,12 @@ public: double getHeight(){return height_mm;} // 返回毫米单位高度 BlockFlag getBlockFlag(){return this->newBlockFlag;} + bool hasBlock(DocBlock* block); // 页面中是否有某个块 DocLayer *getForegroundLayer(); // 获得前景层 DocLayer* getBodyLayer(); // 获得正文层 DocLayer* getBackgroundLayer(); // 获得背景层 + DocLayer *getLayer(DocPage::Layer layer); // 获得层 //Pan void addImage(); //添加图片 @@ -59,10 +61,11 @@ public: double getContentY(){return this->working_area_y;} public slots: - void setSize(double width, double height); // 设置页面大小 - void setPassage(DocPassage * passage); // 设置文章 - void addBlock(DocBlock* block, DocPage::Layer layer); // 为页面添加一个新元素 + void setSize(double width, double height); // 设置页面大小 + void setPassage(DocPassage * passage); // 设置文章 + void addBlock(DocBlock* block, DocPage::Layer layer); // 为页面添加一个新元素 // void addBlock(DocTextBlock* textBlock, DocPage::Layer layer); // 为页面添加一个新元素 + void changeBlockLayer(DocBlock* block, DocPage::Layer layer); // 更换block的层 void addItem(QGraphicsItem *item); // 拓展接口 QGraphicsProxyWidget *addWidget(QWidget *widget, Qt::WindowFlags wFlags = Qt::WindowFlags()); @@ -91,6 +94,7 @@ protected: private: void init(); // 初始化UI + void initMenu(); // 初始化一些自有的菜单 DocPassage * passage; // 页所属文章 DocPageScene* docScene; // 场景数据 @@ -99,6 +103,7 @@ private: DocLayer* backgroundLayer; // 背景层 InsertBlockInfo * insertBlockInfo; // 下一个插入的Block的类型 + QMenu *getMenu(QList& items); // 根据获得的物体生成菜单 // 还应该有模板页 //CT_PageArea* area; // 页面大小描述 @@ -114,8 +119,20 @@ private: DocBlock * activeBlock; // 正在活跃的那个DocBlock + // QActions + QMenu *menu_insert; // 菜单 + QAction *action_insertTextBlock; // 插入文本框 + QAction *action_insertImageBlock; // 插入图片框 + QAction *action_insertTable; // 插入表格 + QAction *action_insertPage; // 插入页 + QAction *action_deletePage; // 删除本页 + + QAction *action_pageSetting; // 页面设置 + + + // 页面设置 bool has_working_area; double working_area_width; double working_area_height; diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 5db642b..9218ad1 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -147,6 +147,23 @@ QString DocTextBlock::getType() /// QMenu *DocTextBlock::getMenu() { + // 重建菜单 + this->ContextMenu->clear(); //清空菜单 + + this->ContextMenu->addAction(this->actionCut); + this->ContextMenu->addAction(this->actionCopy); + this->ContextMenu->addAction(this->actionPaste); + this->ContextMenu->addAction(this->actionSelectAll); + + this->ContextMenu->addSeparator(); // 增加分界线 + this->ContextMenu->addAction(this->actionBold); // 加粗 + this->ContextMenu->addAction(this->actionItalic); // 斜体 +// this->ContextMenu->addAction(this->actionUnderline); // 下划线 + this->ContextMenu->addAction(this->actionColor); // 颜色 + + this->ContextMenu->addSeparator(); // 分界线 + this->ContextMenu->addAction(this->actionFontSetTest); // 字体 + this->ContextMenu->addAction(this->actionParagraph); // 段落设置 // 检验粘贴键的状态 QClipboard *board = QApplication::clipboard(); @@ -817,8 +834,29 @@ void DocTextBlock::init() */ void DocTextBlock::initAcitons() { + + // 剪切 + this->actionCut = new QAction(tr("Cut"), this); + connect(this->actionCut, SIGNAL(triggered(bool)), + this, SLOT(cut())); + + // 复制 + this->actionCopy = new QAction(tr("Copy"), this); + connect(this->actionCopy, SIGNAL(triggered(bool)), + this, SLOT(copy())); + + // 粘贴 + this->actionPaste = new QAction(tr("Paste"), this); + connect(this->actionPaste, SIGNAL(triggered(bool)), + this, SLOT(paste())); + + // 全选 + this->actionSelectAll = new QAction(tr("Select All"), this); + connect(this->actionSelectAll, SIGNAL(triggered(bool)), + this, SLOT(selectAll())); + // 粗体 - this->actionBold = new QAction(tr("Bold"),NULL); + this->actionBold = new QAction(tr("Bold"), this); this->actionBold->setPriority(QAction::LowPriority); QFont bold; bold.setBold(true); @@ -828,7 +866,7 @@ void DocTextBlock::initAcitons() this,SLOT(textBold())); // 斜体 - this->actionItalic = new QAction(tr("Italic"),NULL); + this->actionItalic = new QAction(tr("Italic"), this); this->actionItalic->setPriority(QAction::LowPriority); QFont italic; italic.setItalic(true); @@ -838,7 +876,7 @@ void DocTextBlock::initAcitons() this,SLOT(textItalic())); // 下划线 - this->actionUnderline = new QAction(tr("Underline"),NULL); + this->actionUnderline = new QAction(tr("Underline"), this); this->actionUnderline->setPriority(QAction::LowPriority); QFont underline; underline.setUnderline(true); @@ -848,19 +886,19 @@ void DocTextBlock::initAcitons() this,SLOT(textUnderline())); // 设置字体颜色 - this->actionColor = new QAction(tr("Color"),NULL); + this->actionColor = new QAction(tr("Color"), this); this->actionColor->setPriority(QAction::LowPriority); this->connect(this->actionColor,SIGNAL(triggered()), this,SLOT(setTextColor())); // 段落 - this->actionParagraph = new QAction(tr("Paragraph"),NULL); + this->actionParagraph = new QAction(tr("Paragraph"), this); this->connect(this->actionParagraph,SIGNAL(triggered()), this,SLOT(textParagraph())); // 字体窗口测试 - this->actionFontSetTest = new QAction(tr("FontDialogTest"),NULL); + this->actionFontSetTest = new QAction(tr("FontDialogTest"), this); this->connect(this->actionFontSetTest, SIGNAL(triggered()), this, SLOT(customFontDialog())); @@ -893,19 +931,10 @@ void DocTextBlock::initMenu() this->ContextMenu = new QMenu(tr("DocTextBlock")); // 基本功能 - this->actionCut = this->ContextMenu->addAction(tr("Cut")); // 剪切 - this->actionCopy = this->ContextMenu->addAction(tr("Copy")); // 复制 - this->actionPaste = this->ContextMenu->addAction(tr("Paste")); // 粘贴 - this->actionSelectAll = this->ContextMenu->addAction(tr("SelectAll")); // 全选 - - connect(this->actionCut, SIGNAL(triggered(bool)), - this, SLOT(cut())); - connect(this->actionCopy, SIGNAL(triggered(bool)), - this, SLOT(copy())); - connect(this->actionPaste, SIGNAL(triggered(bool)), - this, SLOT(paste())); - connect(this->actionSelectAll, SIGNAL(triggered(bool)), - this, SLOT(selectAll())); + this->ContextMenu->addAction(this->actionCut); + this->ContextMenu->addAction(this->actionCopy); + this->ContextMenu->addAction(this->actionPaste); + this->ContextMenu->addAction(this->actionSelectAll); this->ContextMenu->addSeparator(); // 增加分界线 this->ContextMenu->addAction(this->actionBold); // 加粗 @@ -917,5 +946,4 @@ void DocTextBlock::initMenu() this->ContextMenu->addAction(this->actionFontSetTest); // 字体 this->ContextMenu->addAction(this->actionParagraph); // 段落设置 - } -- Gitee From 162291ba8f52b566d0759d07c37e3f7a6cbf90d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 12 Aug 2017 10:45:46 +0800 Subject: [PATCH 41/83] =?UTF-8?q?=E7=94=9F=E6=88=90=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E5=A4=A7=E8=87=B4=E5=A4=96=E8=A7=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocImageBlock.cpp | 1 + ofdEditor/model/Doc/DocPage.cpp | 99 ++++++++++++++++++--------- ofdEditor/model/Doc/DocPage.h | 2 +- ofdEditor/model/Doc/DocTextBlock.cpp | 1 + 4 files changed, 68 insertions(+), 35 deletions(-) diff --git a/ofdEditor/model/Doc/DocImageBlock.cpp b/ofdEditor/model/Doc/DocImageBlock.cpp index cc1fab0..2948a4b 100644 --- a/ofdEditor/model/Doc/DocImageBlock.cpp +++ b/ofdEditor/model/Doc/DocImageBlock.cpp @@ -142,6 +142,7 @@ QString DocImageBlock::getType() QMenu *DocImageBlock::getMenu() { this->context_menu->clear(); + this->context_menu->setTitle(this->getType()); this->context_menu->addAction(this->change_image); this->context_menu->addAction(this->set_image_properties); diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index 8f789a3..48201b5 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -417,35 +417,11 @@ void DocPage::contextMenuEvent(QContextMenuEvent *event) { // event->globalPos() 是相对于屏幕的 // event->pos() 相对于页面左上角 - QMenu* menu = new QMenu(this->passage); // 让passage作为父亲 +// QMenu* menu = new QMenu(this->passage); // 让passage作为父亲 QPoint pos = event->pos(); // 获得相对于页面的 QList items = this->items(pos); // 获得某鼠标下的所有块 -// qDebug() << "There are" -// << items.size() -// << " items at position " -// << event->pos() -// << " scene:" -// << this->mapToScene(event->pos()); - - for(int i = 0; i < items.size(); i++) - { - // 将qgraphicsItem造型成为DocBlock - if(items[i]->type() == DocBlock::Type) - { - // 向下造型 - DocBlock* block = qgraphicsitem_cast(items[i]); - if(block != NULL) - { - menu->addMenu(block->getMenu()); - } - else - { - qDebug() << "is not a Docblock class"; - } - } - - } + QMenu *menu = this->getMenu(items); menu->exec(event->globalPos()); // 执行菜单 @@ -676,8 +652,6 @@ void DocPage::init() this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - // 新建三个层 this->foregroundLayer = new DocLayer(Foreground); this->foregroundLayer->setPage(this); @@ -708,25 +682,31 @@ void DocPage::init() /// void DocPage::initMenu() { + this->menu_main = new QMenu(tr("Main")); this->menu_insert = new QMenu(tr("Insert")); // 插入文本框 - this->action_insertTextBlock = new QAction(tr("TextBlock"), NULL); + this->action_insertTextBlock = new QAction(tr("TextBlock"), this); // 插入图片 - this->action_insertImageBlock = new QAction(tr("ImageBlock"), NULL); + this->action_insertImageBlock = new QAction(tr("ImageBlock"), this); // 插入表格 - this->action_insertTable = new QAction(tr("Table"), NULL); + this->action_insertTable = new QAction(tr("Table"), this); // 插入页 - this->action_insertPage = new QAction(tr("Page"), NULL); + this->action_insertPage = new QAction(tr("Page"), this); //删除本页 - this->action_deletePage = new QAction(tr("This Page"), NULL); + this->action_deletePage = new QAction(tr("Delete This Page"), this); // 页面设置 - this->action_pageSetting = new QAction(tr("Page Setting"), NULL); + this->action_pageSetting = new QAction(tr("Page Setting"), this); + + this->menu_insert->addAction(this->action_insertTextBlock); + this->menu_insert->addAction(this->action_insertImageBlock); + this->menu_insert->addAction(this->action_insertTable); + this->menu_insert->addAction(this->action_insertPage); } /// @@ -737,6 +717,57 @@ void DocPage::initMenu() /// QMenu *DocPage::getMenu(QList &items) { + // 三种情况 + // 无元素、一个元素、多个元素 + int size = items.size(); // 鼠标下总共多少个元素 + QMenu *menu = this->menu_main; + menu->clear(); + + if(size == 0) + { + menu->addMenu(this->menu_insert); + menu->addAction(this->action_deletePage); + menu->addAction(this->action_pageSetting); + } + else if(size == 1) + { + + if(items[0]->type() == DocBlock::Type) + { + DocBlock* block = qgraphicsitem_cast(items[0]); + if(block != NULL) + { + menu = block->getMenu(); + } + } + + menu->addSeparator(); + menu->addMenu(this->menu_insert); + menu->addAction(this->action_deletePage); + menu->addAction(this->action_pageSetting); + } + else if(size > 1) + { + + for(int i = 0; i < items.size(); i++) + { + // 将qgraphicsItem造型成为DocBlock + if(items[i]->type() == DocBlock::Type) + { + // 向下造型 + DocBlock* block = qgraphicsitem_cast(items[i]); + QMenu* tempMenu = block->getMenu(); + menu->addMenu(tempMenu); + } + } + + menu->addSeparator(); + menu->addMenu(this->menu_insert); + menu->addAction(this->action_deletePage); + menu->addAction(this->action_pageSetting); + } + + return menu; } diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index b0dda9b..89747a6 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -118,8 +118,8 @@ private: BlockFlag newBlockFlag; // 是否画块 DocBlock * activeBlock; // 正在活跃的那个DocBlock - // QActions + QMenu *menu_main; // 菜单 QMenu *menu_insert; // 菜单 QAction *action_insertTextBlock; // 插入文本框 diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 9218ad1..302391f 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -149,6 +149,7 @@ QMenu *DocTextBlock::getMenu() { // 重建菜单 this->ContextMenu->clear(); //清空菜单 + this->ContextMenu->setTitle(this->getType()); this->ContextMenu->addAction(this->actionCut); this->ContextMenu->addAction(this->actionCopy); -- Gitee From 869fc902d97f74dd181688a238031f71926f0f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 12 Aug 2017 17:30:32 +0800 Subject: [PATCH 42/83] f --- ofdEditor/model/Doc/DocPage.cpp | 5 ++ ofdEditor/model/Doc/DocPage.h | 7 ++- ofdEditor/model/Doc/DocPassage.cpp | 20 +++++- ofdEditor/model/Doc/DocPassage.h | 2 + ofdEditor/model/Widget/InsertPageDialog.cpp | 14 +++++ ofdEditor/model/Widget/InsertPageDialog.h | 27 ++++++++ ofdEditor/model/Widget/InsertPageDialog.ui | 68 +++++++++++++++++++++ ofdEditor/model/model.pro | 9 ++- 8 files changed, 144 insertions(+), 8 deletions(-) create mode 100644 ofdEditor/model/Widget/InsertPageDialog.cpp create mode 100644 ofdEditor/model/Widget/InsertPageDialog.h create mode 100644 ofdEditor/model/Widget/InsertPageDialog.ui diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index 48201b5..a41c4d2 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -377,6 +377,11 @@ void DocPage::setWorkingArea( this->working_area_y = contentY; } +void DocPage::insertPageDialog() +{ + +} + /** * @Author Chaoqun diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index 89747a6..a1383df 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -73,14 +73,15 @@ public slots: void setBlockFlag(BlockFlag flag){this->newBlockFlag = flag;} void setInsertBlockType(InsertBlockInfo& blockInfo); // 设置下一个要插入的block的信息 - void remove(); // 移除本页 - void setScale(double scale); // 设置页面的显示大小 + void remove(); // 移除本页 + void setScale(double scale); // 设置页面的显示大小 void setWorkingArea( bool isUsingWorkingArea, double contentWidth, double contentHeight, double contentX, - double contentY); // 设置工作区域 + double contentY); // 设置工作区域 + void insertPageDialog(); // 插入页面 protected: void paintEvent(QPaintEvent *event); diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index c956406..9102e6f 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -119,7 +119,7 @@ void DocPassage::addPage(DocPage *page) this->pages.append(page); // 添加到ScrollArea this->layout->addWidget(page,0,Qt::AlignCenter); - // 向layout中增加一页,并居中显示 + // 向layout中增加一页,并居中显示 // 接收当前操作页面的更新 this->connect(page, SIGNAL(signals_page_actived(DocPage*)), @@ -127,7 +127,7 @@ void DocPassage::addPage(DocPage *page) this->layout->update(); // 更新 page->setPassage(this); // 设置页所属的文章 - this->adjustWidgetSize(); // 调整大小 + this->adjustWidgetSize(); // 调整大小 // qDebug() << "You have added an new page"; @@ -163,6 +163,11 @@ void DocPassage::appendNewPage(DocPage *page) this->addPage(page); // 此处调用addPage } +void DocPassage::insertPage(DocPage *page, int index) +{ + +} + /** * @Author Chaoqun * @brief 移除指定的页 @@ -338,6 +343,17 @@ DocPage *DocPassage::getLastedActivedPage() return _lastActivedPage; } +/// +/// \brief DocPassage::getPageIndex +/// \param page +/// \return +/// +int DocPassage::getPageIndex(DocPage *page) +{ + int index = this->pages.indexOf(page); // 查找页的序号 + return index; +} + /** * @Author Chaoqun * @brief 设置CommonData,深拷贝 diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index 675edf4..ad642d4 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -56,11 +56,13 @@ public: QString getFilePath(); // 获得文档路径 QUndoStack *undoStack; // 撤销队列 DocPage* getLastedActivedPage(); // Get last actived page + int getPageIndex(DocPage* page); // 获得页面的序号 public slots: void addPage(DocPage *page); // 添加一个新页面 void addPassage(QVector& passage); // 添加很多界面 void appendNewPage(DocPage *page = NULL); // 如果为空,则代表假如空白页 + void insertPage(DocPage* page, int index); // 在指定位置插入页面 void removePage(int index); // 移除某一页 void removePage(DocPage* page); // 移除某一页 diff --git a/ofdEditor/model/Widget/InsertPageDialog.cpp b/ofdEditor/model/Widget/InsertPageDialog.cpp new file mode 100644 index 0000000..1fcef99 --- /dev/null +++ b/ofdEditor/model/Widget/InsertPageDialog.cpp @@ -0,0 +1,14 @@ +#include "InsertPageDialog.h" +#include "ui_InsertPageDialog.h" + +InsertPageDialog::InsertPageDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::InsertPageDialog) +{ + ui->setupUi(this); +} + +InsertPageDialog::~InsertPageDialog() +{ + delete ui; +} diff --git a/ofdEditor/model/Widget/InsertPageDialog.h b/ofdEditor/model/Widget/InsertPageDialog.h new file mode 100644 index 0000000..fb4c77d --- /dev/null +++ b/ofdEditor/model/Widget/InsertPageDialog.h @@ -0,0 +1,27 @@ +#ifndef INSERTPAGEDIALOG_H +#define INSERTPAGEDIALOG_H + +#include + +namespace Ui { +class InsertPageDialog; +} + +/// +/// \brief The InsertPageDialog class +/// 用来在页面中弹出,插入页面的类 +/// +class InsertPageDialog + : public QDialog +{ + Q_OBJECT + +public: + explicit InsertPageDialog(QWidget *parent = 0); + ~InsertPageDialog(); + +private: + Ui::InsertPageDialog *ui; +}; + +#endif // INSERTPAGEDIALOG_H diff --git a/ofdEditor/model/Widget/InsertPageDialog.ui b/ofdEditor/model/Widget/InsertPageDialog.ui new file mode 100644 index 0000000..da1ac79 --- /dev/null +++ b/ofdEditor/model/Widget/InsertPageDialog.ui @@ -0,0 +1,68 @@ + + + InsertPageDialog + + + + 0 + 0 + 424 + 397 + + + + Dialog + + + + + 60 + 320 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + buttonBox + accepted() + InsertPageDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + InsertPageDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index f92c8c9..0ca650d 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -52,7 +52,8 @@ SOURCES += model.cpp \ Widget/InsertTableDialog.cpp \ Widget/FindAndReplaceDock.cpp \ Widget/SelectTemplateDialog.cpp \ - Core/GlobalSetting.cpp + Core/GlobalSetting.cpp \ + Widget/InsertPageDialog.cpp HEADERS += model.h\ model_global.h \ @@ -84,7 +85,8 @@ HEADERS += model.h\ Widget/InsertTableDialog.h \ Widget/SelectTemplateDialog.h \ Core/GlobalSetting.h \ - Widget/DocInfoDialog.h + Widget/DocInfoDialog.h \ + Widget/InsertPageDialog.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 @@ -119,7 +121,8 @@ FORMS += \ Widget/PageDialog.ui \ Widget/InsertTableDialog.ui \ Widget/FindAndReplaceDock.ui \ - Widget/SelectTemplateDialog.ui + Widget/SelectTemplateDialog.ui \ + Widget/InsertPageDialog.ui RESOURCES += \ resource.qrc -- Gitee From e64715d4be6a036267d535cb615b4a68b5fbe7a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sun, 20 Aug 2017 19:44:56 +0800 Subject: [PATCH 43/83] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E9=97=AE=E9=A2=98=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocPage.cpp | 60 ++++++++- ofdEditor/model/Doc/DocPage.h | 7 +- ofdEditor/model/Doc/DocPassage.cpp | 136 ++++++++++++++++----- ofdEditor/model/Doc/DocPassage.h | 3 + ofdEditor/model/Widget/InsertPageDialog.ui | 8 +- 5 files changed, 172 insertions(+), 42 deletions(-) diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index a41c4d2..a877e9f 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -382,6 +382,34 @@ void DocPage::insertPageDialog() } +/// +/// \brief DocPage::insertPageBefore +/// 在本页之前插入页面 +/// +void DocPage::insertPageBefore() +{ + int index = this->passage->getLastedActivedPageIndex(); + this->passage->insertPage(NULL,index); +} + +/// +/// \brief DocPage::insertPageAfter +/// 在本页之后插入页面 +/// +void DocPage::insertPageAfter() +{ + int index = this->passage->getLastedActivedPageIndex(); + this->passage->insertPage(NULL,index + 1); +} + +/// +/// \brief DocPage::dialogPageSetting +/// 调用文章的页面设置窗口 +void DocPage::dialogPageSetting() +{ + this->getPassage()->activatePageDialog(); +} + /** * @Author Chaoqun @@ -424,11 +452,12 @@ void DocPage::contextMenuEvent(QContextMenuEvent *event) // event->pos() 相对于页面左上角 // QMenu* menu = new QMenu(this->passage); // 让passage作为父亲 - QPoint pos = event->pos(); // 获得相对于页面的 + QPoint pos = event->pos(); // 获得相对于页面的 QList items = this->items(pos); // 获得某鼠标下的所有块 QMenu *menu = this->getMenu(items); + this->oldPos = pos; // 记录鼠标位置 - menu->exec(event->globalPos()); // 执行菜单 + menu->exec(event->globalPos()); // 执行菜单 } @@ -700,7 +729,14 @@ void DocPage::initMenu() this->action_insertTable = new QAction(tr("Table"), this); // 插入页 - this->action_insertPage = new QAction(tr("Page"), this); + this->menu_insertPage = new QMenu(tr("Page")); + this->action_insertPage = new QAction(tr("Setting"), this); + this->action_insertPageBefore = new QAction(tr("Before"), this); + this->action_insertPageAfter = new QAction(tr("After"), this); + + this->menu_insertPage->addAction(this->action_insertPageAfter); + this->menu_insertPage->addAction(this->action_insertPageBefore); + this->menu_insertPage->addAction(this->action_insertPage); //删除本页 this->action_deletePage = new QAction(tr("Delete This Page"), this); @@ -711,7 +747,23 @@ void DocPage::initMenu() this->menu_insert->addAction(this->action_insertTextBlock); this->menu_insert->addAction(this->action_insertImageBlock); this->menu_insert->addAction(this->action_insertTable); - this->menu_insert->addAction(this->action_insertPage); +// this->menu_insert->addAction(this->action_insertPage); + this->menu_insert->addMenu(this->menu_insertPage); + + + // 在本页之前插入 + connect(this->action_insertPageBefore, SIGNAL(triggered(bool)), + this, SLOT(insertPageBefore())); + // 在本页之后插入 + connect(this->action_insertPageAfter, SIGNAL(triggered(bool)), + this, SLOT(insertPageAfter())); + // 删除本页 + connect(this->action_deletePage, SIGNAL(triggered(bool)), + this, SLOT(remove())); + // 页面设置 + connect(this->action_pageSetting, SIGNAL(triggered(bool)), + this, SLOT(dialogPageSetting())); + } /// diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index a1383df..52ec7c7 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -82,6 +82,9 @@ public slots: double contentX, double contentY); // 设置工作区域 void insertPageDialog(); // 插入页面 + void insertPageBefore(); // 在本页之前插入页面 + void insertPageAfter(); // 在本页之后插入页面 + void dialogPageSetting(); // 页面设置窗口 protected: void paintEvent(QPaintEvent *event); @@ -122,14 +125,16 @@ private: // QActions QMenu *menu_main; // 菜单 QMenu *menu_insert; // 菜单 + QMenu *menu_insertPage; // 插入页 QAction *action_insertTextBlock; // 插入文本框 QAction *action_insertImageBlock; // 插入图片框 QAction *action_insertTable; // 插入表格 QAction *action_insertPage; // 插入页 + QAction *action_insertPageBefore; // 在本页之前插入页面 + QAction *action_insertPageAfter; // 在本页之后插入页面 QAction *action_deletePage; // 删除本页 - QAction *action_pageSetting; // 页面设置 diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index 9102e6f..651e128 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -163,8 +163,64 @@ void DocPassage::appendNewPage(DocPage *page) this->addPage(page); // 此处调用addPage } +/// +/// \brief DocPassage::insertPage +/// \param page 页面 +/// \param index 插入的位置 +/// void DocPassage::insertPage(DocPage *page, int index) { + if(page == NULL) + { + qDebug() << "page is null"; + page = new DocPage(); + } + + page->setSize(default_width, default_height); + page->setWorkingArea( + default_using_working_area, + default_working_width, + default_working_height, + default_working_x, + default_working_y); + int pos = -1; + + // 插入位置 + if(index >= this->pages.size()) + { + // 插入到最后一位 + pos = this->layout->indexOf( + this->pages.operator [](this->pages.size()-1)); + pos ++; + + this->pages.append(page); + + } + else if(index < 0) + { + // 插入到第一位 + pos = this->layout->indexOf( + this->pages.operator [](0)); + + this->pages.insert(0, page); + + } + else + { + pos = this->layout->indexOf( + this->pages.operator [](index)); + + this->pages.insert(index, page); + } + + this->layout->insertWidget(pos, page, 0, Qt::AlignCenter); + + this->connect(page, SIGNAL(signals_page_actived(DocPage*)), + this, SLOT(setCurrentActivedPage(DocPage*))); + + this->layout->update(); + page->setPassage(this); + this->adjustWidgetSize(); } @@ -195,7 +251,7 @@ void DocPassage::removePage(DocPage *page) // qDebug()<<"pages size" << this->pages.size(); this->layout->removeWidget(page); // 从场景中移除页面 - page->deleteLater(); // 移除页面 +// page->deleteLater(); // 移除页面 this->pages.remove(index); // 从数据中移除页面 // qDebug()<<"pages size" << this->pages.size(); @@ -343,6 +399,15 @@ DocPage *DocPassage::getLastedActivedPage() return _lastActivedPage; } +/// +/// \brief DocPassage::getLastedActivedPageIndex +/// \return +/// +int DocPassage::getLastedActivedPageIndex() +{ + return this->pages.indexOf(this->_lastActivedPage); +} + /// /// \brief DocPassage::getPageIndex /// \param page @@ -436,29 +501,34 @@ void DocPassage::closeEvent(QCloseEvent *event) void DocPassage::initUI() { - this->layout = new QVBoxLayout; // 新建布局 +// this->horizontalWhite = 100; // 文章两侧黑边 +// this->verticalWhite = 50; // 文章之间黑边 + this->marginWhite = 50; // 边缘留下50像素的留白 + this->spacingWhite = 50; // 纸张之间留下的留白 + + this->layout = new QVBoxLayout; // 新建布局 + this->layout->setMargin(this->marginWhite); // 边缘留至少50的空白 + this->layout->setSpacing(this->spacingWhite); // 纸张之间留下50像素的留白 + this->layout->setAlignment(Qt::AlignHCenter); // 纸张自动居中排列 // 新增widget - this->widget = new QWidget(this); + this->widget = new QWidget(); // 中间文档显示区域 this->widget->setLayout(this->layout); this->widget->setVisible(true); - this->widget->setBackgroundRole(QPalette::Dark); // 背景 + this->widget->setBackgroundRole(QPalette::Dark); // widget 背景 this->widget->setAutoFillBackground(true); - + this->setWidgetResizable(true); // 设置ScrollArea 可以影响到内部纸张 this->setWidget(this->widget); // 设置内置widget - this->setBackgroundRole(QPalette::Dark); // 背景 - - this->horizontalWhite = 100; // 文章两侧黑边 - this->verticalWhite = 50; // 文章之间黑边 - this->setAlignment(Qt::AlignHCenter); // 设置位置水平居中 + this->setBackgroundRole(QPalette::Dark); // ScrollArea 的背景 + this->setAlignment(Qt::AlignHCenter); // ScrollArea 设置位置水平居中 - this->scaleFactor = 1.0; + this->scaleFactor = 1.0; // 放大缩小比例 // 设置滚动条策略 this->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); this->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); - adjustScrollBarRange(); // 调整进度条长度 + adjustScrollBarRange(); // 调整进度条长度 // 设置滚动条位置 adjustScrollBar(this->horizontalScrollBar(), 1); @@ -541,37 +611,37 @@ void DocPassage::adjustScrollBarRange() */ void DocPassage::adjustWidgetSize() { - // 计算页面大小 - int width = 0; - int height = 0; +// // 计算页面大小 +// int width = 0; +// int height = 0; - int length = this->pages.size(); // 文章的页数 - for(int i = 0; i pages[i]->viewport()->width()) - { - // 最宽的一页的宽度 - width = this->pages[i]->viewport()->width(); - } +// int length = this->pages.size(); // 文章的页数 +// for(int i = 0; i pages[i]->viewport()->width()) +// { +// // 最宽的一页的宽度 +// width = this->pages[i]->viewport()->width(); +// } - height += verticalWhite + this->pages[i]->viewport()->height(); - } +// height += verticalWhite + this->pages[i]->viewport()->height(); +// } - height += verticalWhite; - width += 2*horizontalWhite; +// height += verticalWhite; +// width += 2*horizontalWhite; // this->widget->setMinimumSize(width, height); // 设置内容大小 - this->widget->resize(width,height); - this->widget->update(); - this->layout->update(); +// this->widget->resize(width,height); +// this->widget->update(); +// this->widget->updateGeometry(); +// this->layout->update(); this->update(); this->viewport()->update(); this->QScrollArea::update(); // 保存计算结果 - this->widgetWidth = width; - this->widgetHeight = height; - +// this->widgetWidth = width; +// this->widgetHeight = height; adjustScrollBarRange(); // 调整进度条长度 diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index ad642d4..40d711c 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -56,6 +56,7 @@ public: QString getFilePath(); // 获得文档路径 QUndoStack *undoStack; // 撤销队列 DocPage* getLastedActivedPage(); // Get last actived page + int getLastedActivedPageIndex(); // Get the id of last actived page int getPageIndex(DocPage* page); // 获得页面的序号 public slots: @@ -154,6 +155,8 @@ private: double widgetHeight; // 内容的高度 int horizontalWhite; // 白色页面左右两边的灰色区域 int verticalWhite; // 白色页面上下的灰色区域 + int marginWhite; // 边缘留白 + int spacingWhite; // 纸张之间的留白 // 默认的大小 double default_width; //默认宽度 diff --git a/ofdEditor/model/Widget/InsertPageDialog.ui b/ofdEditor/model/Widget/InsertPageDialog.ui index da1ac79..2c8b04f 100644 --- a/ofdEditor/model/Widget/InsertPageDialog.ui +++ b/ofdEditor/model/Widget/InsertPageDialog.ui @@ -6,8 +6,8 @@ 0 0 - 424 - 397 + 683 + 547 @@ -16,8 +16,8 @@ - 60 - 320 + 220 + 440 341 32 -- Gitee From 359d551548c38f2b024e2f3ee3d39cd68443a646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Mon, 21 Aug 2017 21:49:10 +0800 Subject: [PATCH 44/83] =?UTF-8?q?=E5=B0=86=E5=A4=9A=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E8=BD=AC=E5=8F=98=E4=B8=BA=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E9=A1=B5=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocPassage.cpp | 72 ++-------- ofdEditor/model/Doc/DocPassage.h | 7 +- .../start/ActionConnector/ActionConnector.cpp | 30 +--- .../start/ActionConnector/ActionConnector.h | 3 +- ofdEditor/start/ui/PassageMainWindow.cpp | 129 +++++++++++------- ofdEditor/start/ui/PassageMainWindow.h | 26 ++-- 6 files changed, 118 insertions(+), 149 deletions(-) diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index 651e128..31ddf17 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -286,17 +286,17 @@ void DocPassage::setDocInfo(CT_DocInfo &docInfo) this->setWindowTitle(this->docInfo->getTitle()); // 设置小窗口标题 } -///** -// * @Author Chaoqun -// * @brief 测试 -// * @param 参数 -// * @return 返回值 -// * @date 2017/06/22 -// */ -//void DocPassage::testMessage() -//{ -//// qDebug()<<"passage success"; -//} +/** + * @Author Chaoqun + * @brief 测试 + * @param 参数 + * @return 返回值 + * @date 2017/06/22 + */ +void DocPassage::testMessage() +{ + qDebug()<<"passage success "; +} /** * @Author Chaoqun @@ -492,6 +492,7 @@ void DocPassage::resizeEvent(QResizeEvent *event) void DocPassage::closeEvent(QCloseEvent *event) { QScrollArea::closeEvent(event); + qDebug() << "passage close request"; } /// @@ -588,7 +589,6 @@ void DocPassage::adjustScrollBarRange() QSize areaSize = this->viewport()->size(); // 视窗大小 QSize widgetSize = this->widget->size(); // 面板大小 - this->horizontalScrollBar()->setPageStep(areaSize.width()); this->horizontalScrollBar()->setRange(0,widgetSize.width() - areaSize.width()); @@ -600,7 +600,6 @@ void DocPassage::adjustScrollBarRange() this->horizontalScrollBar()->update(); this->verticalScrollBar()->update(); - } /** @@ -611,48 +610,17 @@ void DocPassage::adjustScrollBarRange() */ void DocPassage::adjustWidgetSize() { -// // 计算页面大小 -// int width = 0; -// int height = 0; - -// int length = this->pages.size(); // 文章的页数 -// for(int i = 0; i pages[i]->viewport()->width()) -// { -// // 最宽的一页的宽度 -// width = this->pages[i]->viewport()->width(); -// } - -// height += verticalWhite + this->pages[i]->viewport()->height(); -// } - -// height += verticalWhite; -// width += 2*horizontalWhite; - -// this->widget->setMinimumSize(width, height); // 设置内容大小 -// this->widget->resize(width,height); -// this->widget->update(); -// this->widget->updateGeometry(); -// this->layout->update(); + this->update(); this->viewport()->update(); this->QScrollArea::update(); - // 保存计算结果 -// this->widgetWidth = width; -// this->widgetHeight = height; - adjustScrollBarRange(); // 调整进度条长度 // 调整滚动条位置 adjustScrollBar(this->horizontalScrollBar(), this->scaleFactor); adjustScrollBar(this->verticalScrollBar(), this->scaleFactor); - -// qDebug() <<"widget's Size"<widget->size(); -// qDebug() << "ScrollArea's Size" << this->size(); - } void DocPassage::setDefaultPageSize(double default_width, double default_height) @@ -664,15 +632,6 @@ void DocPassage::setDefaultPageSize(double default_width, double default_height) void DocPassage::activatePageDialog() { -//// qDebug() << "page width in pixel = " << page->size().width() -//// << "page height in pixel = " << page->size().height(); - - int index = this->pages.indexOf(this->_lastActivedPage); - qDebug() << "The No." - << index - <<" page has been actived---" - << this->_lastActivedPage->getWidth(); - if( this->_lastActivedPage!= NULL) { @@ -827,9 +786,4 @@ void DocPassage::setScale(double scale) void DocPassage::setCurrentActivedPage(DocPage *page) { this->_lastActivedPage = page; - -// int index = this->pages.indexOf(this->_lastActivedPage); -// qDebug() << "The No." -// << index -// <<" page has been actived" ; } diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index 40d711c..382308f 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -85,7 +85,7 @@ public slots: // docId void resetDocId(); // 重新设置DocId -// void testMessage(); // 测试信号是否走通 + void testMessage(); // 测试信号是否走通 void adjustWidgetSize();// 根据页数来自动调整widget大小 @@ -125,12 +125,10 @@ public slots: // Set the current actived page void setCurrentActivedPage(DocPage* page); - protected: void resizeEvent(QResizeEvent* event); void closeEvent(QCloseEvent *event); // 继承,关闭前提示保存 - private: // 数据区 QString version; // OFD 版本默认 1.0 @@ -153,8 +151,7 @@ private: double scaleFactor; // 表示缩放倍数 double widgetWidth; // 文章内部的宽度 double widgetHeight; // 内容的高度 - int horizontalWhite; // 白色页面左右两边的灰色区域 - int verticalWhite; // 白色页面上下的灰色区域 + int marginWhite; // 边缘留白 int spacingWhite; // 纸张之间的留白 diff --git a/ofdEditor/start/ActionConnector/ActionConnector.cpp b/ofdEditor/start/ActionConnector/ActionConnector.cpp index a58b09f..e3742f8 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.cpp +++ b/ofdEditor/start/ActionConnector/ActionConnector.cpp @@ -152,35 +152,9 @@ void ActionConnector::setDocPassage(DocPassage *passage) this->passage = passage; } - - - -/** - * @Author Chaoqun - * @brief 更新当前的活跃窗口 - * @param 参数 - * @return 返回值 - * @date 2017/06/23 - */ -void ActionConnector::updateActivePassage(QMdiSubWindow *window) +void ActionConnector::updateActivePassage(DocPassage *passage) { - if(window == NULL) - { - qDebug() << "updateActivePassage NULL" - << "there's no actived window"; - this->passage = NULL; - return; - } - DocPassage* passage = qobject_cast(window->widget()); // 获得文档 - if(passage == NULL) - { - qDebug()<< "The active MdiWindow may not DocPassage"; - this->passage = NULL; - } - else - { - this->passage = passage; - } + this->passage = passage; } void ActionConnector::startFindAndReplace() diff --git a/ofdEditor/start/ActionConnector/ActionConnector.h b/ofdEditor/start/ActionConnector/ActionConnector.h index e3356d6..249ee21 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.h +++ b/ofdEditor/start/ActionConnector/ActionConnector.h @@ -40,7 +40,8 @@ public slots: void setDefaultLayer(DocPage::Layer layer){this->defaultLayer = layer;} - void updateActivePassage(QMdiSubWindow * window ); // 更新当前操作的文章 + void updateActivePassage(DocPassage* passage); // 更新当前操作的文章 + void startFindAndReplace(); //打开查找和替换界面 private: diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index bcb2ea3..d46a9ae 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -12,8 +12,7 @@ #include #include #include -#include -#include + #include #include #include @@ -46,6 +45,23 @@ PassageMainWindow::~PassageMainWindow() } +/// +/// \brief PassageMainWindow::activePassage +/// 获得当前被激活的文章 +/// \return +/// +DocPassage *PassageMainWindow::activedPassage() +{ + QWidget* widget = this->tabArea->currentWidget(); + if(widget == 0) + { + // 如果返回空指针 + return NULL; + } + + return qobject_cast(widget); +} + /// /// \brief PassageMainWindow::activateFindAndReplaceDock /// 激活查找替换窗口 @@ -57,33 +73,11 @@ void PassageMainWindow::activateFindAndReplaceDock() FindAndReplaceDock* find_and_replace_dock = FindAndReplaceDock::getInstance(); // 获得单例 find_and_replace_dock->setCurrentPassage( - connector->getActivePassage()); // 设置当前操作的文章 + this->activedPassage()); // 设置当前操作的文章 find_and_replace_dock->show(); } } -/** - * @Author Chaoqun - * @brief 摘要 - * @param 参数 - * @return 返回值 - * @date 2017/05/13 - */ -DocPassage *PassageMainWindow::createMdiChild() -{ - qDebug()<<"execute"; - - DocPassage * child = new DocPassage(this); -// qDebug() << "Creating new Passage Completed."; - child->addPage(new DocPage()); // 添加一个空白页 -// qDebug() << "Creating new Page Completed."; - this->addDocPassage(child); // 加入到本视区 -// qDebug() << "Passage has " << child->getPages().size() << " pages."; -// qDebug() << "Page width = " << child->getPages()[0]->size().width() -// << " Page Height = " <getPages()[0]->size().height(); - return child; -} - /** * @Author Chaoqun * @brief 初始化窗口 @@ -93,8 +87,12 @@ DocPassage *PassageMainWindow::createMdiChild() */ void PassageMainWindow::init() { - this->area = new QMdiArea(); - this->setCentralWidget(this->area); + + /// 标签页 + this->tabArea = new QTabWidget(); + this->setCentralWidget(this->tabArea); + this->tabArea->setTabsClosable(true); // 允许关闭标签页 + this->tabArea->setMovable(true); // 允许调整标签页的顺序 this->connector = new ActionConnector(this); // 新建连接器 @@ -483,7 +481,7 @@ void PassageMainWindow::initAction() void PassageMainWindow::connectAction() { connect(this->newFileAction, SIGNAL(triggered(bool)), - this,SLOT(createMdiChild())); // 新建窗口 + this,SLOT(createEmptyPassage())); // 新建窗口 connect(this->openFileAtcion, SIGNAL(triggered(bool)), this, SLOT(openFile())); //打开文件 @@ -554,13 +552,22 @@ void PassageMainWindow::connectAction() connect(this->underlineAction, SIGNAL(triggered(bool)), this,SLOT(underline())); // 下划线 + // 切换文章 + connect(this->tabArea, SIGNAL(currentChanged(int)), + this, SLOT(changeCurrentPassage(int))); - connect(this->area, SIGNAL(subWindowActivated(QMdiSubWindow*)), - this->connector, SLOT(updateActivePassage(QMdiSubWindow*))); // 检测ActivePassage更新 + connect(this, SIGNAL(updateActivedPassage(DocPassage*)), + this->connector, SLOT(updateActivePassage(DocPassage*))); + // 关闭文章 + connect(this->tabArea, SIGNAL(tabCloseRequested(int)), + this, SLOT(closePassageRequest(int))); + + // 切换为编辑模式 connect(this->editModeAction, SIGNAL(triggered(bool)), this, SLOT(switchToEditMode())); + // 切换为阅读模式 connect(this->viewModeAction, SIGNAL(triggered(bool)), this, SLOT(switchToViewMode())); } @@ -617,9 +624,7 @@ void PassageMainWindow::underline() */ void PassageMainWindow::zoomIn() { -// DocPage* page = this->connector->getActivePage(); -// page->scale(2,2); - DocPassage* passage = this->connector->getActivePassage(); + DocPassage* passage = this->activedPassage(); passage->zoomIn(); } @@ -634,7 +639,7 @@ void PassageMainWindow::zooomOut() { // DocPage* page = this->connector->getActivePage(); // page->scale(0.5,0.5); - DocPassage* passage = this->connector->getActivePassage(); + DocPassage* passage = this->activedPassage(); passage->zoomOut(); } @@ -691,7 +696,7 @@ void PassageMainWindow::openFile() void PassageMainWindow::saveFile() { - DocPassage* passage = this->connector->getActivePassage(); + DocPassage* passage = this->activedPassage(); if(passage == NULL) { qDebug() << "Select NULL Passage"; @@ -816,7 +821,7 @@ void PassageMainWindow::imageDialog() void PassageMainWindow::pageDialog() { - DocPassage * passage = activeMdiChild(); + DocPassage * passage = activedPassage(); if (passage) { passage->activatePageDialog(); @@ -956,6 +961,34 @@ void PassageMainWindow::switchToViewMode() this->editModeAction->setChecked(false); } +/// +/// \brief PassageMainWindow::changeCurrentPassage +/// 切换当前操作文档 +/// \param index +/// +void PassageMainWindow::changeCurrentPassage(int index) +{ + qDebug() << "index " << index; + if(index == -1) + { + // 如果没有则返回 NULL + emit updateActivedPassage(NULL); + return; + } + + emit updateActivedPassage( + qobject_cast( + this->tabArea->widget(index))); + + qobject_cast( + this->tabArea->widget(index))->testMessage(); +} + +void PassageMainWindow::closePassageRequest(int index) +{ + this->tabArea->removeTab(index); +} + void PassageMainWindow::createTemplatePassage(int index) { qDebug() << "???"; @@ -1175,18 +1208,18 @@ void PassageMainWindow::createTemplatePassage(int index) } -/** - * @Author Chaoqun - * @brief 获取激活的窗口 - * @param void - * @return DocPassage * - * @date 2017/05/13 - */ -DocPassage *PassageMainWindow::activeMdiChild() +/// +/// \brief PassageMainWindow::createEmptyPassage +/// 创建一个空的文章 +/// \return +/// +DocPassage *PassageMainWindow::createEmptyPassage() { - if (QMdiSubWindow *activeSubWindow = this->area->activeSubWindow()) - return qobject_cast(activeSubWindow->widget()); - return 0; + DocPassage* child = new DocPassage(); // 新建文章 + child->addPage(new DocPage()); // 增加空白页面 + + this->addDocPassage(child); // 添加页面 + return child; } /** @@ -1204,7 +1237,7 @@ DocPassage *PassageMainWindow::addDocPassage(DocPassage *passage) return NULL; } - this->area->addSubWindow(passage); // 插入子窗口 + this->tabArea->addTab(passage,tr("test")); this->connector->setDocPassage(passage); // 设置引用 passage->setVisible(true); // 设置可见 diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index 69b5430..078a07f 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -8,10 +8,10 @@ #include // 选择框 #include #include +#include // 标签页 class QAction; class QMenu; -class QMdiArea; class DocPassage; class DocTextBlock; class ActionConnector; // 函数功能的中间件 @@ -26,14 +26,16 @@ class PassageMainWindow public: explicit PassageMainWindow(QWidget *parent = 0); ~PassageMainWindow(); + DocPassage * activedPassage(); // 获取获取当前激活的文档 public slots: void activateFindAndReplaceDock(); // 激活查找替换窗口 - DocPassage *createMdiChild(); // 创建一个新文档 - DocPassage *activeMdiChild(); // 获取活动的窗口 - DocPassage *addDocPassage(DocPassage * passage); + + DocPassage *createEmptyPassage(); // 创建一个空的文章 + DocPassage *addDocPassage(DocPassage * passage); // 加入一个文章标签页 void createTemplatePassage(int index); + private: double scale; @@ -65,7 +67,7 @@ private: QAction * undoAction; // 撤销 QAction * redoAction; // 恢复操作 QAction * copyAction; // 复制 - QAction * cutAction; // 剪切 + QAction * cutAction; // 剪切 QAction * pasteAction; // 粘贴 QAction * viewModeAction; // 阅读模式 QAction * editModeAction; // 编辑模式 @@ -104,9 +106,10 @@ private: QAction* rightAction; // 居右 QAction* justifyAction; // 两端对齐 - QMdiArea * area; // 多窗口区域 QVectorpassages; // 存储所有的passage + QTabWidget* tabArea; // 使用标签页来表示多个文章 + ActionConnector* connector; // 功能连接中间件 void init(); // 初始化 @@ -138,13 +141,20 @@ private slots: void zoomIn(); // 放大 void zooomOut(); // 缩小 - void acceptTextBlock(DocTextBlock* textBlock); // 接受当前处理的文字块的更新 + void acceptTextBlock(DocTextBlock* textBlock); // 接受当前处理的文字块的更新 void acceptTextBlockFormat(QTextBlockFormat blockFormat); // 接受当前处理的块格式 void acceptTextCharFormat(QTextCharFormat charFormat); // 接受当前处理的字符格式 - void acceptImageBlock(DocImageBlock * imageBlock); //接受当前处理的图片块 + void acceptImageBlock(DocImageBlock * imageBlock); //接受当前处理的图片块 void switchToEditMode(); //切换到编辑模式 void switchToViewMode(); //切换到阅读模式 + + void changeCurrentPassage(int index); // 当活跃内容 切换为当前页面 + void closePassageRequest(int index); // 点击关闭时处理 + +signals: + void updateActivedPassage(DocPassage * passage); // 更新当前操作的文档对象 + }; #endif // PASSAGEMAINWINDOW_H -- Gitee From 9c8df87f4bb67026d4605eda8dc5542d47b2895c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Wed, 23 Aug 2017 15:41:16 +0800 Subject: [PATCH 45/83] =?UTF-8?q?=E6=9C=80=E8=BF=91=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/start/start.pro | 9 ++++--- ofdEditor/start/ui/RecentFiles.cpp | 14 ++++++++++ ofdEditor/start/ui/RecentFiles.h | 28 +++++++++++++++++++ ofdEditor/start/ui/RecentFiles.ui | 43 ++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 ofdEditor/start/ui/RecentFiles.cpp create mode 100644 ofdEditor/start/ui/RecentFiles.h create mode 100644 ofdEditor/start/ui/RecentFiles.ui diff --git a/ofdEditor/start/start.pro b/ofdEditor/start/start.pro index ae7a806..0c11f50 100644 --- a/ofdEditor/start/start.pro +++ b/ofdEditor/start/start.pro @@ -28,11 +28,13 @@ DEFINES += QT_DEPRECATED_WARNINGS SOURCES += main.cpp\ mainwindow.cpp \ ui/PassageMainWindow.cpp \ - ActionConnector/ActionConnector.cpp + ActionConnector/ActionConnector.cpp \ + ui/RecentFiles.cpp HEADERS += mainwindow.h \ ui/PassageMainWindow.h \ - ActionConnector/ActionConnector.h + ActionConnector/ActionConnector.h \ + ui/RecentFiles.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 @@ -55,6 +57,7 @@ win32{ RESOURCES += \ icons.qrc -FORMS += +FORMS += \ + ui/RecentFiles.ui TRANSLATIONS = cn_start.ts diff --git a/ofdEditor/start/ui/RecentFiles.cpp b/ofdEditor/start/ui/RecentFiles.cpp new file mode 100644 index 0000000..df84e93 --- /dev/null +++ b/ofdEditor/start/ui/RecentFiles.cpp @@ -0,0 +1,14 @@ +#include "RecentFiles.h" +#include "ui_RecentFiles.h" + +RecentFiles::RecentFiles(QWidget *parent) : + QWidget(parent), + ui(new Ui::RecentFiles) +{ + ui->setupUi(this); +} + +RecentFiles::~RecentFiles() +{ + delete ui; +} diff --git a/ofdEditor/start/ui/RecentFiles.h b/ofdEditor/start/ui/RecentFiles.h new file mode 100644 index 0000000..f9d63bb --- /dev/null +++ b/ofdEditor/start/ui/RecentFiles.h @@ -0,0 +1,28 @@ +#ifndef RECENTFILES_H +#define RECENTFILES_H + +#include + +namespace Ui { +class RecentFiles; +} + +/// +/// \brief The RecentFiles class +/// 程序初始打开后的关于最近文档的窗口 +/// +class RecentFiles + : public QWidget +{ + Q_OBJECT + +public: + explicit RecentFiles(QWidget *parent = 0); + ~RecentFiles(); + +private: + Ui::RecentFiles *ui; // 界面文件 + +}; + +#endif // RECENTFILES_H diff --git a/ofdEditor/start/ui/RecentFiles.ui b/ofdEditor/start/ui/RecentFiles.ui new file mode 100644 index 0000000..7378c8c --- /dev/null +++ b/ofdEditor/start/ui/RecentFiles.ui @@ -0,0 +1,43 @@ + + + RecentFiles + + + + 0 + 0 + 650 + 521 + + + + Form + + + + + + 0 + + + + 最近打开的文档 + + + + + + + + + + 新建文档 + + + + + + + + + -- Gitee From b4162316563980905fbc41eba175afd1c24c7f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Wed, 23 Aug 2017 22:02:07 +0800 Subject: [PATCH 46/83] =?UTF-8?q?=E5=88=9B=E5=BB=BA=E6=9C=80=E8=BF=91?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/OFD_DocConvertor.cpp | 3 +- ofdEditor/model/Core/GlobalSetting.cpp | 7 +- ofdEditor/model/Doc/DocPassage.cpp | 21 +- ofdEditor/model/Doc/DocPassage.h | 5 +- ofdEditor/start/Settings/RecentFileItem.cpp | 90 ++++++ ofdEditor/start/Settings/RecentFileItem.h | 67 ++++ ofdEditor/start/Settings/RecentFileList.cpp | 324 +++++++++++++++++++ ofdEditor/start/Settings/RecentFileList.h | 56 ++++ ofdEditor/start/start.pro | 11 +- ofdEditor/start/ui/PassageMainWindow.cpp | 14 + ofdEditor/start/ui/RecentFiles.ui | 2 +- 11 files changed, 573 insertions(+), 27 deletions(-) create mode 100644 ofdEditor/start/Settings/RecentFileItem.cpp create mode 100644 ofdEditor/start/Settings/RecentFileItem.h create mode 100644 ofdEditor/start/Settings/RecentFileList.cpp create mode 100644 ofdEditor/start/Settings/RecentFileList.h diff --git a/ofdEditor/model/Convert/OFD_DocConvertor.cpp b/ofdEditor/model/Convert/OFD_DocConvertor.cpp index af53370..14027b4 100644 --- a/ofdEditor/model/Convert/OFD_DocConvertor.cpp +++ b/ofdEditor/model/Convert/OFD_DocConvertor.cpp @@ -101,8 +101,9 @@ DocPage *OFD_DocConvertor::buildDocPage(DocPassage *passage, Page *ct_page) page = new DocPage(); } - passage->addPage(page); // 加入到文章中来 page->setVisible(false); // 先隐藏显示 + passage->addPage(page); // 加入到文章中来 + // 将每一层加入到页中 QVector* layers = ct_page->getContent(); // 获得文章中的层信息 diff --git a/ofdEditor/model/Core/GlobalSetting.cpp b/ofdEditor/model/Core/GlobalSetting.cpp index 6cc8ebf..12d3889 100644 --- a/ofdEditor/model/Core/GlobalSetting.cpp +++ b/ofdEditor/model/Core/GlobalSetting.cpp @@ -168,14 +168,16 @@ void GlobalSetting::exportGlobalSetting(QString filePath) QFile qfile; qfile.setFileName(filePath); - if(!qfile.open(QIODevice::ReadWrite | QIODevice::Text)) + if(!qfile.open(QIODevice::ReadWrite + | QIODevice::Text + | QIODevice::Truncate)) { qDebug() << "Program could not creat the global setting file"; return; } QTextStream txtOutput(&qfile); // 用来作为输出流 - Json::StyledWriter swriter; // 用来将value转换为 string +// Json::StyledWriter swriter; // 用来将value转换为 string Value root; Value app; // 应用程序 @@ -219,6 +221,7 @@ void GlobalSetting::exportGlobalSetting(QString filePath) root["Paragraph"] = paragraph; txtOutput << QString::fromStdString(root.toStyledString()) <isEdited = false; } /// @@ -66,24 +67,10 @@ DocPassage::DocPassage() this->undoStack = new QUndoStack(this); // 撤销恢复队列 this->docInfo = new CT_DocInfo(); // 新建文章信息 this->initUI(); // 初始化界面 + this->isEdited = false; } -///** -// * @Author Chaoqun -// * @brief 含参构造函数 -// * @date 2017/05/01 -// */ -//DocPassage::DocPassage(QWidget *parent, -// QString version, QString docType, double scaleFactor) -// :QScrollArea(parent) -//{ -// undoStack=new QUndoStack(this); -// this->version = version; -// this->docType = docType; -// this->scaleFactor = scaleFactor; -//} - DocPassage::~DocPassage() { @@ -502,8 +489,6 @@ void DocPassage::closeEvent(QCloseEvent *event) void DocPassage::initUI() { -// this->horizontalWhite = 100; // 文章两侧黑边 -// this->verticalWhite = 50; // 文章之间黑边 this->marginWhite = 50; // 边缘留下50像素的留白 this->spacingWhite = 50; // 纸张之间留下的留白 @@ -564,7 +549,7 @@ void DocPassage::initDocInfo() this->version = globalSetting->getDocVersion(); QDateTime time = QDateTime::currentDateTime(); // 获得系统当前时间 - this->docInfo->setCreationDate( time.toString("yyyy-MM-dd hh:mm:ss")); + this->docInfo->setCreationDate( time.toString("yyyy-MM-dd")); } diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index 382308f..e5f9686 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -41,8 +41,6 @@ public: explicit DocPassage(QWidget* parent); DocPassage(); // 空构造函数 -// DocPassage(QWidget *parent, QString version, -// QString docType,double scaleFactor); // 可能用不上了 ~DocPassage(); CT_DocInfo* getDocInfo(); // 获取CT_DocInfo数据 @@ -59,6 +57,8 @@ public: int getLastedActivedPageIndex(); // Get the id of last actived page int getPageIndex(DocPage* page); // 获得页面的序号 + bool isNeedSave(){return this->isEdited;} // 文档是否被修改,需要保存吗 + public slots: void addPage(DocPage *page); // 添加一个新页面 void addPassage(QVector& passage); // 添加很多界面 @@ -137,6 +137,7 @@ private: CT_CommonData* commonData; // 文档公用文档数据 QVector pages; // 既作为数据,也作为渲染 DocPage* _lastActivedPage; // 用来纪录最后操作过的页面 + bool isEdited; // 是否修改过 // 文件信息 QString filePath; diff --git a/ofdEditor/start/Settings/RecentFileItem.cpp b/ofdEditor/start/Settings/RecentFileItem.cpp new file mode 100644 index 0000000..45965fa --- /dev/null +++ b/ofdEditor/start/Settings/RecentFileItem.cpp @@ -0,0 +1,90 @@ +#include "RecentFileItem.h" +#include +#include + +RecentFileItem::RecentFileItem(QObject *parent) : QObject(parent) +{ + +} + +RecentFileItem::RecentFileItem( + QString fileName, + QString author, + QString recentEditTime, + QString recentOpenTime, + QString filePath): + QObject(0) +{ + this->fileName = fileName; + this->author = author; + this->recentEditTime = QDateTime::fromString( + recentOpenTime, + "yyyy-MM-dd"); + this->recentOpenTime = QDateTime::fromString( + recentEditTime, + "yyyy-MM-dd"); + this->filePath = filePath; +} + +void RecentFileItem::setRecentOpenTime(QString recentOpenTime) +{ + this->recentOpenTime = QDateTime::fromString( + recentOpenTime, + "yyyy-MM-dd"); +} + +void RecentFileItem::setRecentOpenTime(QDateTime recentOpenTime) +{ + this->recentOpenTime = recentOpenTime; +} + +void RecentFileItem::setRecentEditTime(QString recentEditTime) +{ + this->recentEditTime = QDateTime::fromString( + recentEditTime, + "yyyy-MM-dd"); +} + +void RecentFileItem::setRecentEditTime(QDateTime recentEditTime) +{ + this->recentEditTime = recentEditTime; +} + +void RecentFileItem::setFilePath(QString filePath) +{ + this->filePath = filePath; +} + +void RecentFileItem::init( + QString fileName, + QString author, + QString recentEditTime, + QString recentOpenTime, + QString filePath) +{ + this->fileName = fileName; + this->author = author; + this->recentOpenTime = QDateTime::fromString( + recentOpenTime, + "yyyy-MM-dd"); + this->recentOpenTime = QDateTime::fromString( + recentEditTime, + "yyyy-MM-dd"); + this->filePath = filePath; +} + +void RecentFileItem::print() +{ + qDebug() << "fileName " << this->fileName + << " author " << this->author + << " recent open time " << this->recentOpenTime.toString("yyyy-MM-dd") + << " recent edit time" << this->recentEditTime.toString("yyyy-MM-dd") + << " filePath" << this->filePath; +} + +bool RecentFileItem::isExist() +{ + QFile qfile; + qfile.setFileName(this->filePath); + return qfile.exists(); +} diff --git a/ofdEditor/start/Settings/RecentFileItem.h b/ofdEditor/start/Settings/RecentFileItem.h new file mode 100644 index 0000000..803c266 --- /dev/null +++ b/ofdEditor/start/Settings/RecentFileItem.h @@ -0,0 +1,67 @@ +#ifndef RECENTFILEITEM_H +#define RECENTFILEITEM_H + +#include +#include + +class RecentFileItem + : public QObject +{ + Q_OBJECT +public: + explicit RecentFileItem(QObject *parent = 0); + RecentFileItem( + QString fileName, + QString author, + QString recentEditTime, + QString recentOpenTime, + QString filePath); + + QString getFileName(){return this->fileName;} + QString getAuthor(){return this->author;} + QDateTime getRecentOpenTime(){return this->recentOpenTime;} + QString getRecentOpenTime_str(){ + return this->recentOpenTime.toString( + "yyyy-MM-dd");} + QDateTime getRecentEditTime(){return this->recentEditTime;} + QString getRecentEditTime_str(){ + return this->recentEditTime.toString( + "yyyy-MM-dd");} + QString getFilePath(){return this->filePath;} + + void setFileName(QString fileName){this->fileName = fileName;} + void setAuthor(QString author){this->author = author;} + void setRecentOpenTime(QString recentOpenTime); + void setRecentOpenTime(QDateTime recentOpenTime); + void setRecentEditTime(QString recentEditTime); + void setRecentEditTime(QDateTime recentEditTime); + void setFilePath(QString filePath); + + void init( + QString fileName, + QString author, + QString recentEditTime, + QString recentOpenTime, + QString filePath); + + void print(); // 通过qDebug方式输出 + bool isExist(); // 检查该文件是否存在 + + +private: + QString fileName; // 文件名 + QString author; // 作者 + + // 根据文件格式,资金修改的时间精确到天 + QDateTime recentOpenTime; // 最近打开文件时间 + QDateTime recentEditTime; // 最近编辑文件时间 + QString filePath; // 文件路径 + +signals: + +public slots: + + +}; + +#endif // RECENTFILEITEM_H diff --git a/ofdEditor/start/Settings/RecentFileList.cpp b/ofdEditor/start/Settings/RecentFileList.cpp new file mode 100644 index 0000000..a6c1d1d --- /dev/null +++ b/ofdEditor/start/Settings/RecentFileList.cpp @@ -0,0 +1,324 @@ +#include "RecentFileList.h" +#include "RecentFileItem.h" + + +#include "jsoncpp.cpp" + +#include +#include +#include +#include + +using std::string; + + +RecentFileList* RecentFileList::m_instance = NULL; + +/// +/// \brief RecentFileList::getInstance +/// 获得实例 +/// \return +/// +RecentFileList *RecentFileList::getInstance() +{ + if(m_instance == NULL) + { + m_instance = new RecentFileList(); + } + + return m_instance; +} + +/// +/// \brief RecentFileList::qDebugFileList +/// 通过qDebug方式输出文件列表 +/// +void RecentFileList::qDebugFileList() +{ + for(int i = 0 ; i < this->fileList.size(); i++) + { + this->fileList[i]->print(); + } +} + +/// +/// \brief RecentFileList::RecentFileList +/// 默认初始化函数 +/// \param parent +/// +RecentFileList::RecentFileList(QObject *parent) + : QObject(parent) +{ + this->filePath = "recent_log.json"; + this->loadRecentFileList(this->filePath); +} + +/// +/// \brief RecentFileList::loadRecentFileList +/// \param filepath 完整路径 +/// +void RecentFileList::loadRecentFileList(QString filepath) +{ + QFile qfile; + qfile.setFileName(filepath); // 设置文件路径 + this->fileList.clear(); + + // 如果文件不存在 + if(!qfile.exists()) + { + qDebug() << "Recent List is not exists."; + + this->setDefault(); + this->exportRecentFileList(filepath); + return; + } + + // 打开文件 + if(!qfile.open(QIODevice::ReadOnly | QIODevice::Text)) + { + qDebug() << "Recent list file opening failed"; + this->setDefault(); + this->exportRecentFileList(filepath); + return; + } + + QTextStream textInput(&qfile); // 设置文件流 + QString qstr = textInput.readAll(); // 读取文件的全部内容 + string str = qstr.toStdString(); // 转换为标准字符串 + + Reader reader; // json 解析器 + Value value; // 值 + + if(!reader.parse(str,value)) + { + // 如果解析失败 + this->setDefault(); + this->exportRecentFileList(filepath); + return; + } + + if(value.empty()) + { + this->setDefault(); + return; + } + Value files = value["files"]; + for(int i = 0; i < files.size(); i++) + { + RecentFileItem* item = this->JsonToRecentFileItem(files[i]); + if(item != NULL) + this->fileList.append(item); + } + + this->deleteEmptyItem(); // 清除已经失效的项 + +} + +/// +/// \brief RecentFileList::exportRecentFileList +/// 将文件导出 +/// \param filepath +/// +void RecentFileList::exportRecentFileList(QString filepath) +{ + QFile qfile; // qt 文件支持 + qfile.setFileName(filepath); // 设置文件路径 + + // 检查文件是否可用 + if(!qfile.open(QIODevice::ReadWrite + | QIODevice::Text + | QIODevice::Truncate)) + { + qDebug() << "Program open file failed."; + return; + } + + this->deleteEmptyItem(); // 删除已经失效的最近的文件 + + QTextStream textOutput(&qfile); // 用来写出文件 + Value root; // 根节点 + Value files; // 文件数组节点 + + for(int i = 0; i < this->fileList.size(); i++) + { + Value item = this->recentFileItemToJson( + this->fileList.operator [](i)); + if(item.empty()) + continue; + files.append(item); + } + + root["files"] = files; // 保存根节点 + textOutput << QString::fromStdString( + root.toStyledString()) + << endl; // 写出文件 + textOutput.flush(); + qfile.close(); +} + +/// +/// \brief RecentFileList::recentFileItemToJson +/// \param item +/// \return +/// +Json::Value RecentFileList::recentFileItemToJson(RecentFileItem *item) +{ + Value value; + if(item == NULL) + { + return value; + } + + value["fileName"] = item->getFileName().toStdString(); + value["author"] = item->getAuthor().toStdString(); + value["recentOpenTime"] = item->getRecentOpenTime_str().toStdString(); + value["recentEditTime"] = item->getRecentEditTime_str().toStdString(); + value["filePath"] = item->getFilePath().toStdString(); + + return value; + +} + +/// +/// \brief RecentFileList::JsonToRecentFileItem +/// \return +/// +RecentFileItem *RecentFileList::JsonToRecentFileItem(Json::Value value) +{ + if(value.empty()) + { + return NULL; + } + + RecentFileItem* item = new RecentFileItem(); + item->setFileName( + QString::fromStdString( + value["fileName"].asString())); + item->setAuthor( + QString::fromStdString( + value["author"].asString())); + item->setRecentOpenTime( + QString::fromStdString( + value["recentOpenTime"].asString())); + item->setRecentEditTime( + QString::fromStdString( + value["recentEditTime"].asString())); + item->setFilePath( + QString::fromStdString( + value["filePath"].asString())); + + return item; + +} + +void RecentFileList::deleteEmptyItem() +{ + // 检查,然后将那些项先输出后删除 + QVector::Iterator iter; + iter = this->fileList.begin(); + + qDebug() << "Empty item begin:"; + while(iter != this->fileList.end()) + { + RecentFileItem * item = *iter; + if(item->isExist() == false) + { + item->print(); + iter = this->fileList.erase(iter); + } + else + { + iter ++; + } + } + qDebug() << "Empty item end."; +} + +bool RecentFileList::isExisting(QString filePath) +{ + for(int i = 0; i < this->fileList.size(); i++) + { + if(this->fileList[i]->getFilePath() == filePath) + return true; + } + + return false; +} + +RecentFileItem *RecentFileList::item(QString filePath) +{ + for(int i = 0; i < this->fileList.size(); i++) + { + if(this->fileList[i]->getFilePath() == filePath) + return this->fileList[i]; + } + + return NULL; +} + +RecentFileItem *RecentFileList::remove(RecentFileItem *item) +{ + RecentFileItem* oldItem = this->item(item->getFilePath()); + this->fileList.remove(oldItem); + return oldItem; +} + +RecentFileItem *RecentFileList::remove(QString filePath) +{ + RecentFileItem *oldItem = this->item(filePath); + this->fileList.remove(oldItem); + return oldItem; +} + +/// +/// \brief RecentFileList::addItem +/// 加入一项到队列中,加入后自动保存 +/// \param item +/// +void RecentFileList::addItem(RecentFileItem *item) +{ + + if(this->isExisting(item)) + { + // 如果已经存在同样的项,先删除,后更新再插入 + this->fileList.remove(item); + this->fileList.append(item); + + } + else + { + // 如果是新项,则直接插入 + this->fileList.append(item); + } + this->exportRecentFileList(this->filePath); // 自动保存 +} + +/// +/// \brief RecentFileList::setDefault +/// 当没有文件时,可以用来生成默认文件 +/// +void RecentFileList::setDefault() +{ + this->filePath = "recent_log.json"; + this->fileList.clear(); + + // 以下部分为测试,实际使用时请删除 + RecentFileItem* item = new RecentFileItem( + "hhhhhh.ofd", + "chaoqun", + "2017-8-23", + "2017-8-23", + "E:/test.ofd"); + + RecentFileItem* item2 = new RecentFileItem( + "aaaaaa.ofd", + "chaoqun", + "2017-8-23", + "2017-8-23", + "E:/test2.ofd"); + + this->fileList.append(item); + this->fileList.append(item2); + + // 以上部分是测试,实际使用时请删除 +} diff --git a/ofdEditor/start/Settings/RecentFileList.h b/ofdEditor/start/Settings/RecentFileList.h new file mode 100644 index 0000000..b781ee8 --- /dev/null +++ b/ofdEditor/start/Settings/RecentFileList.h @@ -0,0 +1,56 @@ +#ifndef RECENTFILELIST_H +#define RECENTFILELIST_H + +#include +#include + +#include "json/json.h" +#include "json/json-forwards.h" +using Json::Reader; +using Json::Value; + +class RecentFileItem; + +class RecentFileList + : public QObject +{ + Q_OBJECT + +public: + static RecentFileList* getInstance(); // 获得实例 + static void destoryInstance(); // 销毁实例 + + QString getFilePath(){return this->filePath;} + void qDebugFileList(); // 输出文件列表 + void deleteEmptyItem(); // 检查是否有的最近打开文件已经被删除 + void clear(){this->fileList.clear();} // 嫌麻烦可以清除所有最近记录 + bool isExisting(QString filePath); // 检查某文件是否存在 + RecentFileItem *item(QString filePath); // 检查文件是否存在,返回该文件 + RecentFileItem *remove(RecentFileItem* item); // 从队列中清除某一项 + RecentFileItem *remove(QString filePath); // 从队列中清除某一项 + void addItem(RecentFileItem* item); // 添加新的项 + + void save(){this->exportRecentFileList(this->filePath);} // 保存到文件 + void load(){this->loadRecentFileList(this->filePath);} // 从文件中更新 + +private: + explicit RecentFileList(QObject *parent = 0); + static RecentFileList* m_instance; // 静态实例 + QString filePath; // 文件存储路径 + QVector fileList; // 最近的文档列表 + + void loadRecentFileList(QString filepath); // 读取文件 + void exportRecentFileList(QString filepath); // 导出文件 + + Value recentFileItemToJson(RecentFileItem* item); // 将元素转换为value + RecentFileItem* JsonToRecentFileItem(Value value); // 将value转换为item + + void setDefault(); // 设置默认值 + +signals: + +public slots: + +}; + +#endif // RECENTFILELIST_H diff --git a/ofdEditor/start/start.pro b/ofdEditor/start/start.pro index 0c11f50..046ede1 100644 --- a/ofdEditor/start/start.pro +++ b/ofdEditor/start/start.pro @@ -29,12 +29,16 @@ SOURCES += main.cpp\ mainwindow.cpp \ ui/PassageMainWindow.cpp \ ActionConnector/ActionConnector.cpp \ - ui/RecentFiles.cpp + ui/RecentFiles.cpp \ + Settings/RecentFileList.cpp \ + Settings/RecentFileItem.cpp HEADERS += mainwindow.h \ ui/PassageMainWindow.h \ ActionConnector/ActionConnector.h \ - ui/RecentFiles.h + ui/RecentFiles.h \ + Settings/RecentFileList.h \ + Settings/RecentFileItem.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 @@ -43,7 +47,8 @@ OBJECTS_DIR += ./tmp # .obj 文件存放路径 # 引用,可以直接使用 include<文件名> 方式引入头文件 INCLUDEPATH += ../model \ - ../ofd + ../ofd \ + $$PWD/../libs/jsoncpp unix{ diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index d46a9ae..58d97b9 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -34,6 +34,9 @@ #include "Tool/UnitTool.h" #include "Core/GlobalSetting.h" +#include "Settings/RecentFileList.h" +#include "Settings/RecentFileItem.h" + PassageMainWindow::PassageMainWindow(QWidget *parent) :QMainWindow(parent) { @@ -131,6 +134,10 @@ void PassageMainWindow::init() connect(this->select_template_dialog, SIGNAL(createTemplate(int)), this, SLOT(createTemplatePassage(int))); + // 测试 + RecentFileList * recentfilelist = RecentFileList::getInstance(); + recentfilelist->qDebugFileList(); + recentfilelist->save(); } /** @@ -984,6 +991,13 @@ void PassageMainWindow::changeCurrentPassage(int index) this->tabArea->widget(index))->testMessage(); } +/// +/// \brief PassageMainWindow::closePassageRequest +/// 关闭文件时需要处理的事情: +/// 1. 是否需要提示(保存文件) +/// 2. 是否需要更新最近打开文档 +/// \param index +/// void PassageMainWindow::closePassageRequest(int index) { this->tabArea->removeTab(index); diff --git a/ofdEditor/start/ui/RecentFiles.ui b/ofdEditor/start/ui/RecentFiles.ui index 7378c8c..e3a13ac 100644 --- a/ofdEditor/start/ui/RecentFiles.ui +++ b/ofdEditor/start/ui/RecentFiles.ui @@ -13,7 +13,7 @@ Form - + -- Gitee From 60c929e3e277d84e2a4dcebd7f15a80acf1be383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Thu, 24 Aug 2017 11:20:08 +0800 Subject: [PATCH 47/83] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AE=8C=E5=96=84remov?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/ofd/ofd.pro | 9 --------- ofdEditor/start/Settings/RecentFileList.cpp | 22 +++++++++++++++++---- ofdEditor/start/Settings/RecentFileList.h | 1 + ofdEditor/start/ui/PassageMainWindow.cpp | 16 +++++++++++++++ ofdEditor/start/ui/PassageMainWindow.h | 5 ++++- 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/ofdEditor/ofd/ofd.pro b/ofdEditor/ofd/ofd.pro index d6c7837..a925386 100644 --- a/ofdEditor/ofd/ofd.pro +++ b/ofdEditor/ofd/ofd.pro @@ -26,8 +26,6 @@ DEFINES += QT_DEPRECATED_WARNINGS #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ - main.cpp \ - mainwindow.cpp \ ofd_parser.cpp \ DataTypes/basic_datatypes.cpp \ ofd_writer.cpp \ @@ -36,20 +34,14 @@ SOURCES += \ DataTypes/page/CT_PageBlock.cpp \ HEADERS +=\ - mainwindow.h \ DataTypes/basic_datatype.h \ -# DataTypes/CT_Action.h \ -# DataTypes/Color/CT_AxialShd.h \ DataTypes/Color/CT_Color.h \ DataTypes/Color/CT_ColorSpace.h \ -# DataTypes/Color/CT_Pattern.h \ -# DataTypes/Color/CT_RadialShd.h \ DataTypes/document/CT_CommonData.h \ DataTypes/document/CT_DocInfo.h \ DataTypes/document/DocBody.h \ DataTypes/document/Document.h \ DataTypes/document/OFD.h \ -# DataTypes/image/CT_Clip.h \ DataTypes/image/CT_DrawParam.h \ DataTypes/image/CT_GraphicUnit.h \ DataTypes/image/CT_Image.h \ @@ -61,7 +53,6 @@ HEADERS +=\ DataTypes/page/CT_Pages.h \ DataTypes/page/Page.h \ ofd_parser.h \ -# DataTypes/text/CT_CGTransform.h \ DataTypes/text/TextCode.h \ ofd_global.h \ ofd_writer.h \ diff --git a/ofdEditor/start/Settings/RecentFileList.cpp b/ofdEditor/start/Settings/RecentFileList.cpp index a6c1d1d..2750c88 100644 --- a/ofdEditor/start/Settings/RecentFileList.cpp +++ b/ofdEditor/start/Settings/RecentFileList.cpp @@ -259,14 +259,16 @@ RecentFileItem *RecentFileList::item(QString filePath) RecentFileItem *RecentFileList::remove(RecentFileItem *item) { RecentFileItem* oldItem = this->item(item->getFilePath()); - this->fileList.remove(oldItem); + this->fileList.remove( + this->fileList.indexOf(oldItem)); return oldItem; } RecentFileItem *RecentFileList::remove(QString filePath) { RecentFileItem *oldItem = this->item(filePath); - this->fileList.remove(oldItem); + this->fileList.remove( + this->fileList.indexOf(oldItem)); return oldItem; } @@ -278,10 +280,10 @@ RecentFileItem *RecentFileList::remove(QString filePath) void RecentFileList::addItem(RecentFileItem *item) { - if(this->isExisting(item)) + if(this->isExisting(item->getFilePath())) { // 如果已经存在同样的项,先删除,后更新再插入 - this->fileList.remove(item); + this->remove(item); this->fileList.append(item); } @@ -293,6 +295,18 @@ void RecentFileList::addItem(RecentFileItem *item) this->exportRecentFileList(this->filePath); // 自动保存 } +int RecentFileList::indexOf(RecentFileItem *item) +{ + for(int i = 0; i < this->fileList.size(); i++) + { + if(this->fileList[i]->getFilePath() == filePath) + return i; + } + + return -1; + +} + /// /// \brief RecentFileList::setDefault /// 当没有文件时,可以用来生成默认文件 diff --git a/ofdEditor/start/Settings/RecentFileList.h b/ofdEditor/start/Settings/RecentFileList.h index b781ee8..b0fdc49 100644 --- a/ofdEditor/start/Settings/RecentFileList.h +++ b/ofdEditor/start/Settings/RecentFileList.h @@ -29,6 +29,7 @@ public: RecentFileItem *remove(RecentFileItem* item); // 从队列中清除某一项 RecentFileItem *remove(QString filePath); // 从队列中清除某一项 void addItem(RecentFileItem* item); // 添加新的项 + int indexOf(RecentFileItem* item); // item的位置 void save(){this->exportRecentFileList(this->filePath);} // 保存到文件 void load(){this->loadRecentFileList(this->filePath);} // 从文件中更新 diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 58d97b9..93630da 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -996,10 +996,13 @@ void PassageMainWindow::changeCurrentPassage(int index) /// 关闭文件时需要处理的事情: /// 1. 是否需要提示(保存文件) /// 2. 是否需要更新最近打开文档 +/// 3. 只有全部处理好的,才可以关闭该选项 /// \param index /// void PassageMainWindow::closePassageRequest(int index) { + + this->tabArea->removeTab(index); } @@ -1222,6 +1225,19 @@ void PassageMainWindow::createTemplatePassage(int index) } +/// +/// \brief PassageMainWindow::closeEvent +/// 关闭时要检查是否有文档需要保存,有需要保存的时候,要终止关闭窗口 +/// 1.关闭可以关闭的文档 +/// 2.一个一个提醒还没有保存的文档 +/// 3.全部完成后才可以关闭窗口 +/// \param event +/// +void PassageMainWindow::closeEvent(QCloseEvent *event) +{ + +} + /// /// \brief PassageMainWindow::createEmptyPassage /// 创建一个空的文章 diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index 078a07f..a1f9449 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -36,6 +36,9 @@ public slots: void createTemplatePassage(int index); +protected: + void closeEvent(QCloseEvent *event); // 关闭窗口时的响应事件 + private: double scale; @@ -61,7 +64,7 @@ private: QAction * saveAsAction; // 另存为 QAction * printAction; // 打印 QAction * attributeAction; // 文档属性 - QAction * softwareSettingAction; // 软件设置 + QAction * softwareSettingAction; // 软件设置 // 编辑 QAction * undoAction; // 撤销 -- Gitee From ed474b345f0be8f6c294c3fa1ea35d5d8872d6f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Thu, 24 Aug 2017 21:53:35 +0800 Subject: [PATCH 48/83] =?UTF-8?q?=E5=B0=BD=E5=8A=9B=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E6=9C=80=E8=BF=91=E6=96=87=E4=BB=B6=E7=AA=97=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocPassage.cpp | 13 ++ ofdEditor/model/Doc/DocPassage.h | 8 +- ofdEditor/start/Settings/RecentFileItem.cpp | 6 +- ofdEditor/start/Settings/RecentFileList.cpp | 21 +++ ofdEditor/start/Settings/RecentFileList.h | 2 + ofdEditor/start/main.cpp | 4 + ofdEditor/start/ui/PassageMainWindow.cpp | 179 +++++++++++++++----- ofdEditor/start/ui/PassageMainWindow.h | 64 ++++--- ofdEditor/start/ui/RecentFiles.cpp | 127 ++++++++++++++ ofdEditor/start/ui/RecentFiles.h | 16 ++ ofdEditor/start/ui/RecentFiles.ui | 124 +++++++++++++- 11 files changed, 490 insertions(+), 74 deletions(-) diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index 5149fd0..43c9eb2 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -67,6 +67,7 @@ DocPassage::DocPassage() this->undoStack = new QUndoStack(this); // 撤销恢复队列 this->docInfo = new CT_DocInfo(); // 新建文章信息 this->initUI(); // 初始化界面 + this->initDocInfo(); this->isEdited = false; } @@ -761,6 +762,18 @@ void DocPassage::setScale(double scale) } +/// +/// \brief DocPassage::updateEditTime +/// 更新修改文件的设置 +/// +void DocPassage::updateEditTime() +{ + QDateTime date = QDateTime::currentDateTime(); + QString str = date.toString("yyyy-MM-dd"); + + this->docInfo->setModDate(str); +} + /// /// \brief DocPassage::setCurrentActivedPage /// 设置当前活跃的页面 diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index e5f9686..7b16b79 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -47,18 +47,20 @@ public: QString getUUID(); // 获得文章的uuid QString getTempSavePath(); // 获得文章保存前的临时路径 QString getTempStorePath(); // 获得暂存资源的临时路径 + QString getFilePath(); // 获得文档路径 QString getVersion( ){return this->version;} QString getDocType( ){return this->docType;} QVector* getPages(); // 获得文档中包含的所有页面 DocPage *getPage(int index); // 获得文档中的某一页 - QString getFilePath(); // 获得文档路径 - QUndoStack *undoStack; // 撤销队列 + DocPage* getLastedActivedPage(); // Get last actived page int getLastedActivedPageIndex(); // Get the id of last actived page int getPageIndex(DocPage* page); // 获得页面的序号 bool isNeedSave(){return this->isEdited;} // 文档是否被修改,需要保存吗 + QUndoStack *undoStack; // 撤销队列 + public slots: void addPage(DocPage *page); // 添加一个新页面 void addPassage(QVector& passage); // 添加很多界面 @@ -121,6 +123,7 @@ public slots: void zoomOut(); // 放大 void setScale(double scale); // 设置缩放 + void updateEditTime(); // 更新修改文件日期 // Set the current actived page void setCurrentActivedPage(DocPage* page); @@ -139,6 +142,7 @@ private: DocPage* _lastActivedPage; // 用来纪录最后操作过的页面 bool isEdited; // 是否修改过 + // 文件信息 QString filePath; QString fileName; diff --git a/ofdEditor/start/Settings/RecentFileItem.cpp b/ofdEditor/start/Settings/RecentFileItem.cpp index 45965fa..ae7220d 100644 --- a/ofdEditor/start/Settings/RecentFileItem.cpp +++ b/ofdEditor/start/Settings/RecentFileItem.cpp @@ -1,5 +1,5 @@ #include "RecentFileItem.h" -#include +#include #include RecentFileItem::RecentFileItem(QObject *parent) : QObject(parent) @@ -18,10 +18,10 @@ RecentFileItem::RecentFileItem( this->fileName = fileName; this->author = author; this->recentEditTime = QDateTime::fromString( - recentOpenTime, + recentEditTime, "yyyy-MM-dd"); this->recentOpenTime = QDateTime::fromString( - recentEditTime, + recentOpenTime, "yyyy-MM-dd"); this->filePath = filePath; } diff --git a/ofdEditor/start/Settings/RecentFileList.cpp b/ofdEditor/start/Settings/RecentFileList.cpp index 2750c88..6013b13 100644 --- a/ofdEditor/start/Settings/RecentFileList.cpp +++ b/ofdEditor/start/Settings/RecentFileList.cpp @@ -245,6 +245,12 @@ bool RecentFileList::isExisting(QString filePath) return false; } +/// +/// \brief RecentFileList::item +/// 获得某一项 +/// \param filePath +/// \return +/// RecentFileItem *RecentFileList::item(QString filePath) { for(int i = 0; i < this->fileList.size(); i++) @@ -256,6 +262,20 @@ RecentFileItem *RecentFileList::item(QString filePath) return NULL; } +/// +/// \brief RecentFileList::item +/// 获得某一项 +/// \param i +/// \return +/// +RecentFileItem *RecentFileList::item(int i) +{ + if(i < 0 || i > this->fileList.size()) + return NULL; + + return this->fileList[i]; +} + RecentFileItem *RecentFileList::remove(RecentFileItem *item) { RecentFileItem* oldItem = this->item(item->getFilePath()); @@ -292,6 +312,7 @@ void RecentFileList::addItem(RecentFileItem *item) // 如果是新项,则直接插入 this->fileList.append(item); } + item->print(); this->exportRecentFileList(this->filePath); // 自动保存 } diff --git a/ofdEditor/start/Settings/RecentFileList.h b/ofdEditor/start/Settings/RecentFileList.h index b0fdc49..a42ffd9 100644 --- a/ofdEditor/start/Settings/RecentFileList.h +++ b/ofdEditor/start/Settings/RecentFileList.h @@ -26,10 +26,12 @@ public: void clear(){this->fileList.clear();} // 嫌麻烦可以清除所有最近记录 bool isExisting(QString filePath); // 检查某文件是否存在 RecentFileItem *item(QString filePath); // 检查文件是否存在,返回该文件 + RecentFileItem *item(int i); // 根据位置获得 RecentFileItem *remove(RecentFileItem* item); // 从队列中清除某一项 RecentFileItem *remove(QString filePath); // 从队列中清除某一项 void addItem(RecentFileItem* item); // 添加新的项 int indexOf(RecentFileItem* item); // item的位置 + int size(){return this->fileList.size();} // 获取队列大小 void save(){this->exportRecentFileList(this->filePath);} // 保存到文件 void load(){this->loadRecentFileList(this->filePath);} // 从文件中更新 diff --git a/ofdEditor/start/main.cpp b/ofdEditor/start/main.cpp index b7c188f..622932d 100644 --- a/ofdEditor/start/main.cpp +++ b/ofdEditor/start/main.cpp @@ -28,7 +28,11 @@ int main(int argc, char *argv[]) } PassageMainWindow w; + w.show(); +// PassageMainWindow* mainwindow = PassageMainWindow::getInstance(); +// mainwindow->show(); + return a.exec(); } diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 93630da..eb6a277 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -33,13 +33,29 @@ #include "Widget/SelectTemplateDialog.h" #include "Tool/UnitTool.h" #include "Core/GlobalSetting.h" +#include "DataTypes/document/CT_DocInfo.h" #include "Settings/RecentFileList.h" #include "Settings/RecentFileItem.h" +#include "ui/RecentFiles.h" + + +PassageMainWindow* PassageMainWindow::m_instance = NULL; + +PassageMainWindow *PassageMainWindow::getInstance() +{ + if(m_instance == NULL) + { + m_instance = new PassageMainWindow(); + } + + return m_instance; +} PassageMainWindow::PassageMainWindow(QWidget *parent) :QMainWindow(parent) { + m_instance = this; init(); } @@ -97,6 +113,11 @@ void PassageMainWindow::init() this->tabArea->setTabsClosable(true); // 允许关闭标签页 this->tabArea->setMovable(true); // 允许调整标签页的顺序 + // 最近打开文件 + RecentFiles* recentWidget = RecentFiles::getInstance(); + + this->tabArea->addTab(recentWidget,tr("Welcome!")); + this->connector = new ActionConnector(this); // 新建连接器 // 初始化变量 @@ -672,23 +693,7 @@ void PassageMainWindow::openFile() QString path = fileDialog->selectedFiles()[0]; // 用户选择文件名 qDebug() << path; - ZipTool zipTool; - QString tempPath = zipTool.FilePathToFloderPath(path); - qDebug() << "Temp path is :" << tempPath; - - ZipTool::extractDir(path,tempPath); // 解压到临时文件夹 - - // 解读文件 -// OFDParser ofdParser("C:\\Users\\User\\AppData\\Local\\Temp\\%表格.ofd%\\OFD.xml"); - OFDParser ofdParser(tempPath + "/OFD.xml"); // 新建临时路径 -// OFDParser ofdParser("C:/Users/User/Desktop/表格/OFD.xml"); - OFD* data = ofdParser.getData(); // 读取出OFD文件 - qDebug()<< "ofd file open" << tempPath + "/OFD.xml"; - OFD_DocConvertor convert; - DocPassage* passage = convert.ofd_to_doc(data); - passage->setFilePath(path); // 设置文件路径 - - this->addDocPassage(passage); // 添加文章 + this->openFile(path); // 调用打开文件 } } @@ -718,29 +723,42 @@ void PassageMainWindow::saveFile() return; } + passage->updateEditTime(); // 更新文件修改日期 + this->addRecentFile(passage); // 添加到最近打开的文件列表 + Doc_OFDConvertor docToOfd; OFD* ofdFile = docToOfd.doc_to_ofd(passage); QString tempPath = passage->getTempStorePath(); - ZipTool::deleteFolder(tempPath); // 删除文件夹 + ZipTool::deleteFolder(tempPath); // 删除文件夹 QDir dir; dir.mkdir(tempPath); // 生成文件夹 - OFDWriter writer(ofdFile, tempPath+"/"); // 写出文件 + OFDWriter writer(ofdFile, tempPath+"/"); // 写出文件 ZipTool::compressDir(filePath, - tempPath); // 将文件夹压缩为指定文件 + tempPath); // 将文件夹压缩为指定文件 } -/** - * @Author Chaoqun - * @brief 文件另存为 - * @param void - * @return void - * @date 2017/06/26 - */ +/// +/// \brief PassageMainWindow::saveFileAs +/// 另存为文件 +/// 先判断文件是否可以 +/// 弹出文件对话框 +/// 保存文件 +/// void PassageMainWindow::saveFileAs() { + // 检查文档 + DocPassage* passage = this->connector->getActivePassage(); + if(passage == NULL) + { + qDebug() << "Select NULL Passage"; + return; + } + passage->updateEditTime(); + + // 弹出保存文件对话框 QFileDialog * fileDialog = new QFileDialog(this); // 新建一个QFileDialog fileDialog->setAcceptMode(QFileDialog::AcceptSave); // 设置对话框为保存文件类型 @@ -753,14 +771,6 @@ void PassageMainWindow::saveFileAs() { QString path = fileDialog->selectedFiles()[0]; // 用户选择文件名 - - DocPassage* passage = this->connector->getActivePassage(); - if(passage == NULL) - { - qDebug() << "Select NULL Passage"; - return; - } - Doc_OFDConvertor docToOfd; OFD* ofdFile = docToOfd.doc_to_ofd(passage); @@ -770,10 +780,10 @@ void PassageMainWindow::saveFileAs() { qDebug() << "the file is existing"; // 如果文件夹已存在则要删除该文件夹 - ZipTool::deleteFolder(tempPath); // 删除文件夹 + ZipTool::deleteFolder(tempPath); // 删除文件夹 } - dir.mkdir(tempPath); // 生成文件夹 + dir.mkdir(tempPath); // 生成文件夹 OFDWriter writer(ofdFile, tempPath + "/"); // 写出文件 qDebug() << "temp Files Path:" << tempPath; @@ -784,7 +794,8 @@ void PassageMainWindow::saveFileAs() if(flag == true) { - passage->setFilePath(path); + passage->setFilePath(path); // 设置文件路径 + this->addRecentFile(passage); // 添加到最近文件 } else { @@ -1004,6 +1015,13 @@ void PassageMainWindow::closePassageRequest(int index) this->tabArea->removeTab(index); + + if(this->tabArea->count() == 0) + { + RecentFiles* recentWidget = RecentFiles::getInstance(); + recentWidget->init(); + this->tabArea->addTab(recentWidget,tr("Welcome!")); + } } void PassageMainWindow::createTemplatePassage(int index) @@ -1225,6 +1243,42 @@ void PassageMainWindow::createTemplatePassage(int index) } +/// +/// \brief PassageMainWindow::openFile +/// 打开文件 +/// \param filePath +/// +void PassageMainWindow::openFile(QString filePath) +{ + + QFile qfile; + qfile.setFileName(filePath); + if(!qfile.exists()) + { + // 如果文件不存在,则中断程序 + return; + } + + ZipTool zipTool; + QString tempPath = zipTool.FilePathToFloderPath(filePath); + qDebug() << "Temp path is :" << tempPath; + + ZipTool::extractDir(filePath,tempPath); // 解压到临时文件夹 + + // 解读文件 +// OFDParser ofdParser("C:\\Users\\User\\AppData\\Local\\Temp\\%表格.ofd%\\OFD.xml"); + OFDParser ofdParser(tempPath + "/OFD.xml"); // 新建临时路径 +// OFDParser ofdParser("C:/Users/User/Desktop/表格/OFD.xml"); + OFD* data = ofdParser.getData(); // 读取出OFD文件 + qDebug()<< "ofd file open" << tempPath + "/OFD.xml"; + OFD_DocConvertor convert; + DocPassage* passage = convert.ofd_to_doc(data); + passage->setFilePath(filePath); // 设置文件路径 + + this->addRecentFile(passage); // 添加到最近文件 + this->addDocPassage(passage); // 添加文章 +} + /// /// \brief PassageMainWindow::closeEvent /// 关闭时要检查是否有文档需要保存,有需要保存的时候,要终止关闭窗口 @@ -1267,7 +1321,11 @@ DocPassage *PassageMainWindow::addDocPassage(DocPassage *passage) return NULL; } - this->tabArea->addTab(passage,tr("test")); + this->tabArea->addTab( + passage, + passage->getFilePath().section('/',-1)); + this->tabArea->setCurrentIndex( + this->tabArea->count() - 1); this->connector->setDocPassage(passage); // 设置引用 passage->setVisible(true); // 设置可见 @@ -1288,3 +1346,46 @@ DocPassage *PassageMainWindow::addDocPassage(DocPassage *passage) return passage; } +/// +/// \brief PassageMainWindow::disableButtons +/// 禁用掉无关按钮,适用于尚未打开文件的状态 +/// +void PassageMainWindow::disableButtons() +{ + +} + +/// +/// \brief PassageMainWindow::enableButtons +/// 开启所有按钮,适用于已经打开文件的状态 +void PassageMainWindow::enableButtons() +{ + +} + +/// +/// \brief PassageMainWindow::addRecentFile +/// 增加最近文件记录 +/// 打开文件、保存文件时调用 +/// \param passages +/// +void PassageMainWindow::addRecentFile(DocPassage *passages) +{ + + CT_DocInfo * info = passages->getDocInfo(); + QDateTime date = QDateTime::currentDateTime(); + + RecentFileList* list = RecentFileList::getInstance(); + RecentFileItem* item = new RecentFileItem( + passages->getFilePath().section('/',-1), + info->getAuthor(), + info->getModDate(), + date.toString("yyyy-MM-dd"), + passages->getFilePath() + ); + + list->addItem(item); + + list->save(); // 保存到文件 +} + diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index a1f9449..e6056c9 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -24,22 +24,55 @@ class PassageMainWindow { Q_OBJECT public: + static PassageMainWindow* getInstance(); // 获得单例 + explicit PassageMainWindow(QWidget *parent = 0); ~PassageMainWindow(); - DocPassage * activedPassage(); // 获取获取当前激活的文档 + DocPassage * activedPassage(); // 获取获取当前激活的文档 public slots: - void activateFindAndReplaceDock(); // 激活查找替换窗口 + void activateFindAndReplaceDock(); // 激活查找替换窗口 - DocPassage *createEmptyPassage(); // 创建一个空的文章 + DocPassage *createEmptyPassage(); // 创建一个空的文章 DocPassage *addDocPassage(DocPassage * passage); // 加入一个文章标签页 + void disableButtons(); // 禁用掉无关的按钮 + void enableButtons(); // 开启所有按钮 + void addRecentFile(DocPassage* passages); // 增加最近文件记录 void createTemplatePassage(int index); + void openFile(QString filePath); // 打开文件 + void openFile(); // 打开新文件 + void saveFile(); // 保存文件测试 + void saveFileAs(); // 将文件另存为 + void fontDialog(); // 打开字体框 + void paragraphDialog(); // 打开段落框 + void imageDialog(); // 打开图片框 + void pageDialog(); // 打开页面框 + void templateDialog(); //打开模板选择 + void Bold(); // 加粗事件 + void Italic(); // 斜体事件 + void underline(); // 下划线事件 + + void zoomIn(); // 放大 + void zooomOut(); // 缩小 + + void acceptTextBlock(DocTextBlock* textBlock); // 接受当前处理的文字块的更新 + void acceptTextBlockFormat(QTextBlockFormat blockFormat); // 接受当前处理的块格式 + void acceptTextCharFormat(QTextCharFormat charFormat); // 接受当前处理的字符格式 + void acceptImageBlock(DocImageBlock * imageBlock); //接受当前处理的图片块 + + void switchToEditMode(); //切换到编辑模式 + void switchToViewMode(); //切换到阅读模式 + + void changeCurrentPassage(int index); // 当活跃内容 切换为当前页面 + void closePassageRequest(int index); // 点击关闭时处理 + protected: void closeEvent(QCloseEvent *event); // 关闭窗口时的响应事件 private: + static PassageMainWindow* m_instance; // 单例 double scale; // 菜单栏 @@ -128,32 +161,7 @@ private: SelectTemplateDialog * select_template_dialog; //选择模板对话框 -private slots: - void openFile(); // 打开新文件 - void saveFile(); // 保存文件测试 - void saveFileAs(); // 将文件另存为 - void fontDialog(); // 打开字体框 - void paragraphDialog(); // 打开段落框 - void imageDialog(); // 打开图片框 - void pageDialog(); // 打开页面框 - void templateDialog(); //打开模板选择 - void Bold(); // 加粗事件 - void Italic(); // 斜体事件 - void underline(); // 下划线事件 - void zoomIn(); // 放大 - void zooomOut(); // 缩小 - - void acceptTextBlock(DocTextBlock* textBlock); // 接受当前处理的文字块的更新 - void acceptTextBlockFormat(QTextBlockFormat blockFormat); // 接受当前处理的块格式 - void acceptTextCharFormat(QTextCharFormat charFormat); // 接受当前处理的字符格式 - void acceptImageBlock(DocImageBlock * imageBlock); //接受当前处理的图片块 - - void switchToEditMode(); //切换到编辑模式 - void switchToViewMode(); //切换到阅读模式 - - void changeCurrentPassage(int index); // 当活跃内容 切换为当前页面 - void closePassageRequest(int index); // 点击关闭时处理 signals: void updateActivedPassage(DocPassage * passage); // 更新当前操作的文档对象 diff --git a/ofdEditor/start/ui/RecentFiles.cpp b/ofdEditor/start/ui/RecentFiles.cpp index df84e93..7d02c57 100644 --- a/ofdEditor/start/ui/RecentFiles.cpp +++ b/ofdEditor/start/ui/RecentFiles.cpp @@ -1,14 +1,141 @@ #include "RecentFiles.h" #include "ui_RecentFiles.h" +#include "Settings/RecentFileList.h" +#include "Settings/RecentFileItem.h" +#include "ui/PassageMainWindow.h" + +#include + +RecentFiles* RecentFiles::m_instance = NULL; // 初始化静态变量 + +/// +/// \brief RecentFiles::getInstance +/// \return +/// +RecentFiles *RecentFiles::getInstance() +{ + if(m_instance == NULL) + { + m_instance = new RecentFiles(); + } + + m_instance->init(); + return m_instance; +} + +/// +/// \brief RecentFiles::destroyInstance +/// +void RecentFiles::destroyInstance() +{ + m_instance = NULL; +} + +/// +/// \brief RecentFiles::init +/// 每次使用时的初始化函数,用来重新初始化界面 +/// +void RecentFiles::init() +{ + RecentFileList* recentlist = RecentFileList::getInstance(); // 获得最近文件 + recentlist->load(); // 更新最近文件列表 + + this->clear(); + + ui->recent_table->horizontalHeader()->setVisible(true); + + int length = recentlist->size(); // 获得有效的列表长度 + for(int i = 0; i < length; i++) + { + this->appendItem(recentlist->item(i)); + } + +} RecentFiles::RecentFiles(QWidget *parent) : QWidget(parent), ui(new Ui::RecentFiles) { ui->setupUi(this); + // 最后一行自动适应宽度 + ui->recent_table->horizontalHeader()->setStretchLastSection(true); + // 设置每次可以选取一行 + ui->recent_table->setSelectionBehavior(QAbstractItemView::SelectRows); + // 设置只可以单选 + ui->recent_table->setSelectionMode(QAbstractItemView::SingleSelection); + ui->recent_table->horizontalHeader()->setVisible(true); + + // 双击打开文件 + this->connect(ui->recent_table, SIGNAL(cellDoubleClicked(int,int)), + this, SLOT(selectOpenFile(int,int))); + + // 绑定打开文件信号 + PassageMainWindow* mainWindow = PassageMainWindow::getInstance(); + this->connect(this, SIGNAL(openFile(QString)), + mainWindow, SLOT(openFile(QString))); + } RecentFiles::~RecentFiles() { delete ui; } + +/// +/// \brief RecentFiles::appendItem +/// 追加一项 +/// \param item +/// +void RecentFiles::appendItem(RecentFileItem *item) +{ +// int rows = ui->recent_table->rowCount(); // 共有多少行 + ui->recent_table->insertRow(0); + + QTableWidgetItem* fileName = new QTableWidgetItem(); + QTableWidgetItem* author = new QTableWidgetItem(); + QTableWidgetItem* recentOpenTime = new QTableWidgetItem(); + QTableWidgetItem* recentEditTime = new QTableWidgetItem(); + QTableWidgetItem* filePath = new QTableWidgetItem(); + + fileName->setText(item->getFileName()); + author->setText(item->getAuthor()); + recentOpenTime->setText(item->getRecentOpenTime_str()); + recentEditTime->setText(item->getRecentEditTime_str()); + filePath->setText(item->getFilePath()); + + ui->recent_table->setItem(0,0,fileName); + ui->recent_table->setItem(0,1,author); + ui->recent_table->setItem(0,2,recentOpenTime); + ui->recent_table->setItem(0,3,recentEditTime); + ui->recent_table->setItem(0,4,filePath); + +} + +/// +/// \brief RecentFiles::clear +/// 清空内容 +/// +void RecentFiles::clear() +{ +// ui->recent_table->clearContents(); // 清空内容 + int length = ui->recent_table->rowCount(); + for(int i = 0; i < length; i++) + { + ui->recent_table->removeRow(0); + } +} + +/// +/// \brief RecentFiles::selectOpenFile +/// 双击打开文件 +/// \param row +/// \param column +/// +void RecentFiles::selectOpenFile(int row, int column) +{ + QTableWidgetItem* filePath = ui->recent_table->item(row,4); + QString path = filePath->text(); // 获得路径信息 + + emit this->openFile(path); // 发出打开文件信号 + +} diff --git a/ofdEditor/start/ui/RecentFiles.h b/ofdEditor/start/ui/RecentFiles.h index f9d63bb..7c76ed4 100644 --- a/ofdEditor/start/ui/RecentFiles.h +++ b/ofdEditor/start/ui/RecentFiles.h @@ -7,6 +7,8 @@ namespace Ui { class RecentFiles; } +class RecentFileItem; // 最近文件项 + /// /// \brief The RecentFiles class /// 程序初始打开后的关于最近文档的窗口 @@ -17,12 +19,26 @@ class RecentFiles Q_OBJECT public: + static RecentFiles* getInstance(); // 获得单例 + static void destroyInstance(); // 销毁实例 + void init(); // 初始化 + +private: explicit RecentFiles(QWidget *parent = 0); ~RecentFiles(); + static RecentFiles* m_instance; // 单例 + + void appendItem(RecentFileItem* item); // 在显示界面上插入一项 + void clear(); // 清空列表 private: Ui::RecentFiles *ui; // 界面文件 +private slots: + void selectOpenFile(int row, int column); // 双击某行能够打开最近文件 + +signals: + void openFile(QString filePath); }; #endif // RECENTFILES_H diff --git a/ofdEditor/start/ui/RecentFiles.ui b/ofdEditor/start/ui/RecentFiles.ui index e3a13ac..9ffbb4c 100644 --- a/ofdEditor/start/ui/RecentFiles.ui +++ b/ofdEditor/start/ui/RecentFiles.ui @@ -13,7 +13,7 @@ Form - + @@ -25,7 +25,127 @@ - + + + + 0 + 0 + + + + + 宋体 + 14 + 50 + false + + + + Qt::LeftToRight + + + false + + + QFrame::Plain + + + 0 + + + QAbstractItemView::NoEditTriggers + + + true + + + false + + + false + + + Qt::DashLine + + + false + + + false + + + false + + + true + + + 130 + + + false + + + + New Row + + + + + 文件名 + + + + 14 + + + + + + 作者 + + + + 14 + + + + + + 最近打开时间 + + + + 14 + + + + + + 最近编辑时间 + + + + 14 + + + + + + 文件路径 + + + + 14 + + + + + + + + + -- Gitee From 37e40b934db51d6dc2703a14b453460d7e7696cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Fri, 25 Aug 2017 21:06:15 +0800 Subject: [PATCH 49/83] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E6=9C=80=E8=BF=91?= =?UTF-8?q?=E6=96=87=E4=BB=B6=EF=BC=8C=E5=B0=9D=E8=AF=95=E5=81=9A=E8=A1=A8?= =?UTF-8?q?=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocTable.cpp | 12 ++++++++ ofdEditor/model/Doc/DocTable.h | 15 +++++++++- ofdEditor/start/Settings/RecentFileItem.cpp | 8 ++--- ofdEditor/start/Settings/RecentFileItem.h | 2 +- ofdEditor/start/ui/PassageMainWindow.cpp | 2 +- ofdEditor/start/ui/RecentFiles.cpp | 16 ++++++++++ ofdEditor/start/ui/RecentFiles.h | 1 + ofdEditor/start/ui/RecentFiles.ui | 33 +++++++++++++++++++-- 8 files changed, 80 insertions(+), 9 deletions(-) diff --git a/ofdEditor/model/Doc/DocTable.cpp b/ofdEditor/model/Doc/DocTable.cpp index cbf53d5..a776bf5 100644 --- a/ofdEditor/model/Doc/DocTable.cpp +++ b/ofdEditor/model/Doc/DocTable.cpp @@ -8,7 +8,19 @@ DocTable::DocTable(QWidget *parent) } +DocTable::DocTable(int rows, int columns) + :QTextEdit(0) +{ + +} + DocTable::~DocTable() { } + +// 设置表格长和宽 +DocTable::setTable(int rows, int columns) +{ + +} diff --git a/ofdEditor/model/Doc/DocTable.h b/ofdEditor/model/Doc/DocTable.h index beac60d..cc3abc8 100644 --- a/ofdEditor/model/Doc/DocTable.h +++ b/ofdEditor/model/Doc/DocTable.h @@ -6,18 +6,30 @@ #include #include #include +#include +#include +#include +#include -// 这个类专门用来表示表格 +/// +/// \brief The DocTable class +/// 这个类专门表示表格 +/// 为一个QTextEdit、但内部内容仅有一个QTextTable +/// class MODELSHARED_EXPORT DocTable :public QTextEdit { Q_OBJECT public: DocTable(QWidget *parent = NULL); + DocTable(int rows, int columns); + + ~DocTable(); public slots: + setTable(int rows, int columns); // 设置表格长和宽 private slots: @@ -25,6 +37,7 @@ private: // tableCell的内容估计使用QTextBlock int rowCount; // 行数 int colCount; // 列数 + QTextTable* _table; // 该表格 }; #endif // TABLE_H diff --git a/ofdEditor/start/Settings/RecentFileItem.cpp b/ofdEditor/start/Settings/RecentFileItem.cpp index ae7220d..7c26391 100644 --- a/ofdEditor/start/Settings/RecentFileItem.cpp +++ b/ofdEditor/start/Settings/RecentFileItem.cpp @@ -22,7 +22,7 @@ RecentFileItem::RecentFileItem( "yyyy-MM-dd"); this->recentOpenTime = QDateTime::fromString( recentOpenTime, - "yyyy-MM-dd"); + "yyyy-MM-dd HH:mm:ss"); this->filePath = filePath; } @@ -30,7 +30,7 @@ void RecentFileItem::setRecentOpenTime(QString recentOpenTime) { this->recentOpenTime = QDateTime::fromString( recentOpenTime, - "yyyy-MM-dd"); + "yyyy-MM-dd HH:mm:ss"); } void RecentFileItem::setRecentOpenTime(QDateTime recentOpenTime) @@ -66,7 +66,7 @@ void RecentFileItem::init( this->author = author; this->recentOpenTime = QDateTime::fromString( recentOpenTime, - "yyyy-MM-dd"); + "yyyy-MM-dd HH:mm:ss"); this->recentOpenTime = QDateTime::fromString( recentEditTime, "yyyy-MM-dd"); @@ -77,7 +77,7 @@ void RecentFileItem::print() { qDebug() << "fileName " << this->fileName << " author " << this->author - << " recent open time " << this->recentOpenTime.toString("yyyy-MM-dd") + << " recent open time " << this->recentOpenTime.toString("yyyy-MM-dd HH:mm:ss") << " recent edit time" << this->recentEditTime.toString("yyyy-MM-dd") << " filePath" << this->filePath; } diff --git a/ofdEditor/start/Settings/RecentFileItem.h b/ofdEditor/start/Settings/RecentFileItem.h index 803c266..759f3ac 100644 --- a/ofdEditor/start/Settings/RecentFileItem.h +++ b/ofdEditor/start/Settings/RecentFileItem.h @@ -22,7 +22,7 @@ public: QDateTime getRecentOpenTime(){return this->recentOpenTime;} QString getRecentOpenTime_str(){ return this->recentOpenTime.toString( - "yyyy-MM-dd");} + "yyyy-MM-dd HH:mm:ss");} QDateTime getRecentEditTime(){return this->recentEditTime;} QString getRecentEditTime_str(){ return this->recentEditTime.toString( diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index eb6a277..e50ec32 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -1380,7 +1380,7 @@ void PassageMainWindow::addRecentFile(DocPassage *passages) passages->getFilePath().section('/',-1), info->getAuthor(), info->getModDate(), - date.toString("yyyy-MM-dd"), + date.toString("yyyy-MM-dd HH:mm:ss"), passages->getFilePath() ); diff --git a/ofdEditor/start/ui/RecentFiles.cpp b/ofdEditor/start/ui/RecentFiles.cpp index 7d02c57..31aeae9 100644 --- a/ofdEditor/start/ui/RecentFiles.cpp +++ b/ofdEditor/start/ui/RecentFiles.cpp @@ -74,6 +74,10 @@ RecentFiles::RecentFiles(QWidget *parent) : this->connect(this, SIGNAL(openFile(QString)), mainWindow, SLOT(openFile(QString))); + // 清空最近记录 + connect(ui->btn_cleanRecent, SIGNAL(released()), + this, SLOT(cleanRecentRecord())); + } RecentFiles::~RecentFiles() @@ -139,3 +143,15 @@ void RecentFiles::selectOpenFile(int row, int column) emit this->openFile(path); // 发出打开文件信号 } + + +/// +/// \brief RecentFiles::cleanRecentRecord +/// 与按钮绑定 +void RecentFiles::cleanRecentRecord() +{ + RecentFileList * list = RecentFileList::getInstance(); + list->clear(); + list->save(); + this->clear(); +} diff --git a/ofdEditor/start/ui/RecentFiles.h b/ofdEditor/start/ui/RecentFiles.h index 7c76ed4..56ae56e 100644 --- a/ofdEditor/start/ui/RecentFiles.h +++ b/ofdEditor/start/ui/RecentFiles.h @@ -36,6 +36,7 @@ private: private slots: void selectOpenFile(int row, int column); // 双击某行能够打开最近文件 + void cleanRecentRecord(); // 与按钮绑定,清空最近记录 signals: void openFile(QString filePath); diff --git a/ofdEditor/start/ui/RecentFiles.ui b/ofdEditor/start/ui/RecentFiles.ui index 9ffbb4c..3de5be8 100644 --- a/ofdEditor/start/ui/RecentFiles.ui +++ b/ofdEditor/start/ui/RecentFiles.ui @@ -74,13 +74,16 @@ false - false + true true - 130 + 150 + + + 50 false @@ -147,6 +150,32 @@ + + + + + + + 清空最近文件记录 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + -- Gitee From 1ca4b3fb836bfc034f802f03335027b7dfb511f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 26 Aug 2017 17:12:43 +0800 Subject: [PATCH 50/83] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=E6=96=87?= =?UTF-8?q?=E6=9C=AC=E6=A1=86=E5=A4=A7=E5=B0=8F=E9=9A=8F=E6=96=87=E6=9C=AC?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E8=87=AA=E5=8A=A8=E5=A2=9E=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocTable.cpp | 27 ++++++++++++++++++++--- ofdEditor/model/Doc/DocTable.h | 12 ++++++----- ofdEditor/model/Doc/DocTextBlock.cpp | 32 ++++++++++++++++++++++++++-- ofdEditor/model/Doc/DocTextBlock.h | 8 +++---- 4 files changed, 65 insertions(+), 14 deletions(-) diff --git a/ofdEditor/model/Doc/DocTable.cpp b/ofdEditor/model/Doc/DocTable.cpp index a776bf5..584865c 100644 --- a/ofdEditor/model/Doc/DocTable.cpp +++ b/ofdEditor/model/Doc/DocTable.cpp @@ -1,10 +1,13 @@ #include "DocTable.h" - +#include DocTable::DocTable(QWidget *parent) :QTextEdit(parent) { + QTextCursor cursor = this->textCursor(); // 获得光标 + this->_table = cursor.insertTable(3,4); // 插入一个表格 + } @@ -19,8 +22,26 @@ DocTable::~DocTable() } -// 设置表格长和宽 -DocTable::setTable(int rows, int columns) +/// +/// \brief DocTable::setTable +/// 设置表格行数列数 +/// \param rows +/// \param columns +/// +void DocTable::setTable(int rows, int columns) { } + +/// +/// \brief DocTable::setDefaultStyle +/// 将表格设置为默认的样式 +/// +void DocTable::setDefaultStyle() +{ + QTextDocument* doc = this->_table->document(); // 文档 + QTextFrame * rootFrame = doc->rootFrame(); // 根 框架 + + QTextFrame::iterator iter; + +} diff --git a/ofdEditor/model/Doc/DocTable.h b/ofdEditor/model/Doc/DocTable.h index cc3abc8..ff31337 100644 --- a/ofdEditor/model/Doc/DocTable.h +++ b/ofdEditor/model/Doc/DocTable.h @@ -10,7 +10,7 @@ #include #include #include - +#include /// /// \brief The DocTable class @@ -29,15 +29,17 @@ public: ~DocTable(); public slots: - setTable(int rows, int columns); // 设置表格长和宽 + void setTable(int rows, int columns); // 设置表格长和宽 + void setDefaultStyle(); // 设置默认样式 private slots: private: // tableCell的内容估计使用QTextBlock - int rowCount; // 行数 - int colCount; // 列数 - QTextTable* _table; // 该表格 + int rowCount; // 行数 + int colCount; // 列数 + QTextTable* _table; // 该表格 + QTextCursor tableCursor; // 记录指向表格的光标 }; #endif // TABLE_H diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 302391f..72aa7c3 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -787,9 +787,33 @@ void DocTextBlock::emitFormatSignals() emit this->signals_currentTextBlock(this); } -void DocTextBlock::printTestMessage() +/// +/// \brief DocTextBlock::textBlockSizeChanged +/// 当文字内容改变时,尝试调整文本框大小 +void DocTextBlock::textBlockSizeChanged() { - qDebug() << "Click Right Button"; + QTextDocument* doc = this->document(); // 获得文档 +// document()->adjustSize(); + + qDebug() << "Document.size.width" + << doc->size().width() + << "Document.textWidth" + << doc->textWidth(); + + int newHeight = doc->size().height() + 10; + + int oldWidth = (int)(this->block->size().width() + 0.5); + int oldHeight = (int)(this->block->size().height() + 0.5); + + if(oldHeight < newHeight) + { + // 如果需要调整大小 + this->block->resize(oldWidth, newHeight); + qDebug() << "Automatically resize edit size" + << oldWidth + << "," + << newHeight; + } } /** @@ -903,6 +927,10 @@ void DocTextBlock::initAcitons() this->connect(this->actionFontSetTest, SIGNAL(triggered()), this, SLOT(customFontDialog())); + // 自动调整窗口大小 + this->connect(this, SIGNAL(textChanged()), + this, SLOT(textBlockSizeChanged())); + } /** diff --git a/ofdEditor/model/Doc/DocTextBlock.h b/ofdEditor/model/Doc/DocTextBlock.h index bb4ea43..4272af0 100644 --- a/ofdEditor/model/Doc/DocTextBlock.h +++ b/ofdEditor/model/Doc/DocTextBlock.h @@ -98,9 +98,9 @@ protected: void focusOutEvent(QFocusEvent *e); private slots: - void checkCurrentFormat(); // 检查当前的格式是否发生改变 - void emitFormatSignals(); // 发射格式的信号 - void printTestMessage(); // 测试右键信号是否畅通 + void checkCurrentFormat(); // 检查当前的格式是否发生改变 + void emitFormatSignals(); // 发射格式的信号 + void textBlockSizeChanged(); // 当文字内容改变时自动调整文字大小 private: QString content; // 文字内容 @@ -120,7 +120,7 @@ private: QAction * actionItalic; // 斜体 QAction * actionColor; // 设置颜色 QAction * actionParagraph; // 设置段落 - QAction * actionFontSetTest; // 新字体窗口测试 + QAction * actionFontSetTest;// 新字体窗口测试 QMenu * ContextMenu; // 右键菜单 DocBlock* block; // 本类型所在的block -- Gitee From de26ac77d6435e601f507a6b7d002f2536c33ec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 26 Aug 2017 17:54:36 +0800 Subject: [PATCH 51/83] =?UTF-8?q?=E6=96=87=E5=AD=97=E5=A4=A7=E5=B0=8F?= =?UTF-8?q?=E8=87=AA=E9=80=82=E5=BA=94=EF=BC=8C=E5=8A=A0=E4=B8=8A=E6=A1=86?= =?UTF-8?q?=E4=B8=8D=E8=83=BD=E6=AF=94=E6=96=87=E5=AD=97=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocBlock.cpp | 35 +++++++++++++++++++++++++-- ofdEditor/model/Doc/DocBlock.h | 3 +++ ofdEditor/model/Doc/DocImageBlock.cpp | 19 +++------------ ofdEditor/model/Doc/DocImageBlock.h | 9 ------- ofdEditor/model/Doc/DocTextBlock.cpp | 35 +++++++++++++++------------ ofdEditor/model/Doc/DocTextBlock.h | 2 +- 6 files changed, 60 insertions(+), 43 deletions(-) diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index 6abf8fb..fc973c5 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -30,8 +30,9 @@ DocBlock::DocBlock(QGraphicsItem *parent , Qt::WindowFlags wFlags) this->setFlag(QGraphicsProxyWidget::ItemIsSelectable, true); // 可选择 this->setFlag(QGraphicsProxyWidget::ItemIsFocusable, true); // 可关注 this->setAcceptHoverEvents(true); - textBlock = NULL; - imageBlock = NULL; + this->textBlock = NULL; + this->imageBlock = NULL; + this->isShowBox = false; this->initMenu(); } @@ -118,6 +119,8 @@ void DocBlock::resize(qreal w, qreal h) QGraphicsProxyWidget::resize(w,h); this->blockSize.setWidth(w); this->blockSize.setHeight(h); + + emit this->signal_resize(this->x(),this->y(),w,h); } /** @@ -132,6 +135,8 @@ void DocBlock::resize(const QSizeF &size) QGraphicsProxyWidget::resize(size); this->blockSize.setWidth(size.width()); this->blockSize.setHeight(size.height()); + emit this->signal_resize(this->x(),this->y(), + size.width(),size.height()); } /** @@ -200,6 +205,22 @@ void DocBlock::paint(QPainter *painter, this->paintHandle(*painter); // 画出调整框 } + if(this->isShowBox) + { + // 如果需要花边框的话,为什么要在这里画呢 + // 因为如果需要绘制边框,直接用系统的显示边框会影响block内的尺寸 + + painter->setPen(Qt::black); + + // resize line + qreal w = this->blockSize.width(); + qreal h = this->blockSize.height(); + + painter->drawRect(0,0, + w,h); + + } + } /** @@ -408,6 +429,16 @@ void DocBlock::sizeAndPositionDialog() } +/// +/// \brief DocBlock::setShowBoundaryBox +/// 设置是否显示包围的边框 +/// \param flag +/// +void DocBlock::setShowBoundaryBox(bool flag) +{ + this->isShowBox = flag; +} + /** * @Author Chaoqun * @brief 检查鼠标是否在重置大小区域 diff --git a/ofdEditor/model/Doc/DocBlock.h b/ofdEditor/model/Doc/DocBlock.h index b4ca0ae..b2f9111 100644 --- a/ofdEditor/model/Doc/DocBlock.h +++ b/ofdEditor/model/Doc/DocBlock.h @@ -80,6 +80,7 @@ public slots: // 槽函数 void setWidget(DocImageBlock * imageBlock); void sizeAndPositionDialog(); // 调整大小和位置窗口 + void setShowBoundaryBox(bool flag); // 设置是否显示边框 protected: void paint(QPainter *painter, @@ -106,6 +107,7 @@ private: DocTextBlock * textBlock; // 存下引用 DocImageBlock * imageBlock; //同上 qreal realZValue; // 真实的z值 + bool isShowBox; // 是否显示边框 bool isFocused; // 是否被聚焦 bool blockIsResizing; // 是否正在改变大小 @@ -115,6 +117,7 @@ private: signals: void signals_blockRemoved(DocBlock* block); // 当本块被移除时发出信号 + void signal_resize(qreal x, qreal y, qreal width, qreal height); // 发送block大小改变信号 private slots: void moveToForeground(); // 移动到前景层 diff --git a/ofdEditor/model/Doc/DocImageBlock.cpp b/ofdEditor/model/Doc/DocImageBlock.cpp index 2948a4b..90eca2a 100644 --- a/ofdEditor/model/Doc/DocImageBlock.cpp +++ b/ofdEditor/model/Doc/DocImageBlock.cpp @@ -16,7 +16,6 @@ DocImageBlock::DocImageBlock(QWidget *parent) this->setFocusPolicy(Qt::StrongFocus); //Initialization -// this->properties_dialog = new ImagePropertiesDialog(this, parent); width_height_ratio_locked = true; width_height_ratio = 0.0; @@ -170,7 +169,8 @@ void DocImageBlock::focusInEvent(QFocusEvent *e) { //qDebug() << "focus In Event"; emit signals_currrentImageBlock(this); - this->setFrameShape(QFrame::Box); +// this->setFrameShape(QFrame::Box); + this->block->setShowBoundaryBox(true); this->setLineWidth(1); QLabel::focusInEvent(e); } @@ -184,22 +184,11 @@ void DocImageBlock::focusInEvent(QFocusEvent *e) */ void DocImageBlock::focusOutEvent(QFocusEvent *e) { - this->setFrameStyle(QFrame::NoFrame); +// this->setFrameStyle(QFrame::NoFrame); + this->block->setShowBoundaryBox(false); QLabel::focusOutEvent(e); } -///** -// * @Author Pan -// * @brief 右键菜单 -// * @param QContextMenuEvent *ev -// * @return void -// * @date 2017/06/24 -// */ -//void DocImageBlock::contextMenuEvent(QContextMenuEvent *ev) -//{ -// context_menu->exec(ev->globalPos()); -//} - /// /// \brief DocImageBlock::initMenu /// 初始化右键菜单 diff --git a/ofdEditor/model/Doc/DocImageBlock.h b/ofdEditor/model/Doc/DocImageBlock.h index d7f14a6..835aabe 100644 --- a/ofdEditor/model/Doc/DocImageBlock.h +++ b/ofdEditor/model/Doc/DocImageBlock.h @@ -49,14 +49,12 @@ public slots: protected: void focusInEvent(QFocusEvent *ev); void focusOutEvent(QFocusEvent *ev); -// void contextMenuEvent(QContextMenuEvent *ev); private: DocBlock * block; //对代理它的DocBlock的引用 QMenu * context_menu; //右键菜单 QAction * change_image; //更改图片 QAction * set_image_properties; //更改图片的位置和尺寸 -// ImagePropertiesDialog * properties_dialog; bool width_height_ratio_locked; double width_height_ratio; @@ -67,13 +65,6 @@ private: signals: -// void sendImageInfo(double image_width, -// double image_height, -// double image_x, -// double image_y, -// double page_width, -// double page_height, -// bool ratio_is_locked); void signals_currrentImageBlock(DocImageBlock * textBlock); //当前操作的imageBlock }; diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 72aa7c3..6843017 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -301,6 +301,8 @@ void DocTextBlock::setFont( void DocTextBlock::setBlock(DocBlock *block) { this->block = block; // 设置Block + this->connect(block, SIGNAL(signal_resize(qreal,qreal,qreal,qreal)), + this, SLOT(textBlockSizeChanged())); } /** @@ -324,14 +326,15 @@ void DocTextBlock::remove() */ void DocTextBlock::showBoundaryFrame(bool show) { - if(show) - { - this->setFrameStyle(QFrame::Box); // 显示边框 - } - else - { - this->setFrameStyle(QFrame::NoFrame); // 隐藏边框 - } +// if(show) +// { +// this->setFrameStyle(QFrame::Box); // 显示边框 +// } +// else +// { +// this->setFrameStyle(QFrame::NoFrame); // 隐藏边框 +// } + this->block->setShowBoundaryBox(show); } @@ -795,10 +798,10 @@ void DocTextBlock::textBlockSizeChanged() QTextDocument* doc = this->document(); // 获得文档 // document()->adjustSize(); - qDebug() << "Document.size.width" - << doc->size().width() - << "Document.textWidth" - << doc->textWidth(); +// qDebug() << "Document.size.width" +// << doc->size().width() +// << "Document.textWidth" +// << doc->textWidth(); int newHeight = doc->size().height() + 10; @@ -809,10 +812,10 @@ void DocTextBlock::textBlockSizeChanged() { // 如果需要调整大小 this->block->resize(oldWidth, newHeight); - qDebug() << "Automatically resize edit size" - << oldWidth - << "," - << newHeight; +// qDebug() << "Automatically resize edit size" +// << oldWidth +// << "," +// << newHeight; } } diff --git a/ofdEditor/model/Doc/DocTextBlock.h b/ofdEditor/model/Doc/DocTextBlock.h index 4272af0..adf7a84 100644 --- a/ofdEditor/model/Doc/DocTextBlock.h +++ b/ofdEditor/model/Doc/DocTextBlock.h @@ -27,7 +27,7 @@ class MODELSHARED_EXPORT DocTextBlock public: DocTextBlock(QWidget *parent = NULL); ~DocTextBlock(); - void setContent(QString str); // 设置内容 + void setContent(QString str); // 设置内容 DocPassage* getPassage(); // 获得文章 DocPage* getPage(); // 获得页 -- Gitee From 2c46ba31a29ff29f50481f741571b0a2b3cbdaa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 26 Aug 2017 18:38:29 +0800 Subject: [PATCH 52/83] =?UTF-8?q?=E6=94=B9=E5=8F=98=E6=9C=80=E8=BF=91?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=8F=92=E5=85=A5=E7=AD=96=E7=95=A5=EF=BC=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/start/ui/RecentFiles.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ofdEditor/start/ui/RecentFiles.cpp b/ofdEditor/start/ui/RecentFiles.cpp index 31aeae9..069ece0 100644 --- a/ofdEditor/start/ui/RecentFiles.cpp +++ b/ofdEditor/start/ui/RecentFiles.cpp @@ -45,7 +45,7 @@ void RecentFiles::init() ui->recent_table->horizontalHeader()->setVisible(true); int length = recentlist->size(); // 获得有效的列表长度 - for(int i = 0; i < length; i++) + for(int i = length-1; i >= 0; i--) { this->appendItem(recentlist->item(i)); } @@ -92,8 +92,8 @@ RecentFiles::~RecentFiles() /// void RecentFiles::appendItem(RecentFileItem *item) { -// int rows = ui->recent_table->rowCount(); // 共有多少行 - ui->recent_table->insertRow(0); + int rows = ui->recent_table->rowCount(); // 共有多少行 + ui->recent_table->insertRow(rows); QTableWidgetItem* fileName = new QTableWidgetItem(); QTableWidgetItem* author = new QTableWidgetItem(); @@ -107,11 +107,11 @@ void RecentFiles::appendItem(RecentFileItem *item) recentEditTime->setText(item->getRecentEditTime_str()); filePath->setText(item->getFilePath()); - ui->recent_table->setItem(0,0,fileName); - ui->recent_table->setItem(0,1,author); - ui->recent_table->setItem(0,2,recentOpenTime); - ui->recent_table->setItem(0,3,recentEditTime); - ui->recent_table->setItem(0,4,filePath); + ui->recent_table->setItem(rows,0,fileName); + ui->recent_table->setItem(rows,1,author); + ui->recent_table->setItem(rows,2,recentOpenTime); + ui->recent_table->setItem(rows,3,recentEditTime); + ui->recent_table->setItem(rows,4,filePath); } -- Gitee From 2ac9cad4b691dd31c3e107ac1f8e10bdc6a36d3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sun, 27 Aug 2017 21:00:09 +0800 Subject: [PATCH 53/83] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E8=A1=A8=E6=A0=BC?= =?UTF-8?q?=E2=80=A6=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocBlock.cpp | 30 +++- ofdEditor/model/Doc/DocBlock.h | 5 + ofdEditor/model/Doc/DocPage.cpp | 50 ++++-- ofdEditor/model/Doc/DocPage.h | 7 +- ofdEditor/model/Doc/DocTable.cpp | 148 +++++++++++++++++- ofdEditor/model/Doc/DocTable.h | 31 +++- ofdEditor/model/Doc/DocTextBlock.cpp | 8 - ofdEditor/model/Doc/DocTextBlock.h | 2 +- .../start/ActionConnector/ActionConnector.cpp | 33 ++-- .../start/ActionConnector/ActionConnector.h | 2 +- ofdEditor/start/ui/RecentFiles.ui | 2 +- 11 files changed, 271 insertions(+), 47 deletions(-) diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index fc973c5..8e169a3 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -15,6 +15,7 @@ #include "Doc/DocPage.h" #include "Doc/DocPassage.h" #include "Doc/DocImageBlock.h" +#include "Doc/DocTable.h" DocBlock::DocBlock(QGraphicsItem *parent , Qt::WindowFlags wFlags) :QGraphicsProxyWidget(parent,wFlags) @@ -24,6 +25,7 @@ DocBlock::DocBlock(QGraphicsItem *parent , Qt::WindowFlags wFlags) this->setZValue(200); this->isFocused = false; // 初始时设为false + this->blockIsResizing = false; this->rectAdjust = blockNone; // 一开始处于空状态 @@ -420,6 +422,18 @@ void DocBlock::setWidget(DocImageBlock * imageBlock) QGraphicsProxyWidget::setWidget(imageBlock); } +/// +/// \brief DocBlock::setWidget +/// 设置对象为表格 +/// \param table +/// +void DocBlock::setWidget(DocTable *table) +{ + table->setBlock(this); + this->_table = table; + QGraphicsProxyWidget::setWidget(table); +} + /// /// \brief DocBlock::sizeAndPositionDialog /// 大小位置调整窗口 @@ -528,7 +542,7 @@ void DocBlock::moveToBackground() */ DocBlock::RectAdjustStatus DocBlock::currentStatus( QPointF pos) { - if (isTextBlock()) + if (isTextBlock() || isTableBlock()) { if((pos.x() - this->size().width() + 15) > (this->size().height() - pos.y())) @@ -666,6 +680,7 @@ DocTextBlock *DocBlock::getTextBlock() { if (isTextBlock()) return this->textBlock; + return NULL; } /** @@ -691,4 +706,17 @@ DocImageBlock * DocBlock::getImageBlock() { if (isImageBlock()) return imageBlock; + return NULL; +} + +bool DocBlock::isTableBlock() +{ + return this->_table != NULL; +} + +DocTable *DocBlock::getTableBlock() +{ + if(this->isTableBlock()) + return this->_table; + return NULL; } diff --git a/ofdEditor/model/Doc/DocBlock.h b/ofdEditor/model/Doc/DocBlock.h index b2f9111..c998d96 100644 --- a/ofdEditor/model/Doc/DocBlock.h +++ b/ofdEditor/model/Doc/DocBlock.h @@ -15,6 +15,7 @@ class DocTextBlock; class DocPage; class DocPassage; class DocImageBlock; +class DocTable; /** * @Author Chaoqun @@ -58,6 +59,8 @@ public: DocTextBlock *getTextBlock(); // 获得DocTextBlock bool isImageBlock(); DocImageBlock *getImageBlock(); //获得DocImageBlock + bool isTableBlock(); + DocTable *getTableBlock(); // 获得DocTable QAction *action_geometry; // 大小和位置 QAction *action_delete; // 删除块 @@ -78,6 +81,7 @@ public slots: // 槽函数 void setWidget(QWidget* widget); // 旧的函数 void setWidget(DocTextBlock *textBlock); // SetWidget void setWidget(DocImageBlock * imageBlock); + void setWidget(DocTable* table); void sizeAndPositionDialog(); // 调整大小和位置窗口 void setShowBoundaryBox(bool flag); // 设置是否显示边框 @@ -106,6 +110,7 @@ private: DocTextBlock * textBlock; // 存下引用 DocImageBlock * imageBlock; //同上 + DocTable * _table; // 存下引用 qreal realZValue; // 真实的z值 bool isShowBox; // 是否显示边框 diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index a877e9f..07cb54a 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -218,7 +218,8 @@ void DocPage::addBlock(DocBlock *block, DocPage::Layer layer) passage,SIGNAL(signals_currentCharFormatChanged(QTextCharFormat))); connect(textBlock,SIGNAL(signals_currentTextBlock(DocTextBlock*)), passage,SIGNAL(signals_currentTextBlock(DocTextBlock*))); - } else if (block->isImageBlock()) + } + else if (block->isImageBlock()) { DocImageBlock * imageBlock = block->getImageBlock(); DocPassage * passage = this->getPassage(); @@ -228,6 +229,14 @@ void DocPage::addBlock(DocBlock *block, DocPage::Layer layer) this->connect(imageBlock, SIGNAL(signals_currrentImageBlock(DocImageBlock*)), passage, SIGNAL(signals_currentImageBlock(DocImageBlock*))); } + else if (block->isTableBlock()) + { + DocTable *table = block->getTableBlock(); + DocPassage *passage = this->getPassage(); + + // 之后可以做信号的转发 + + } // qDebug()<< "connect"; // 分到层 @@ -311,7 +320,7 @@ QGraphicsProxyWidget *DocPage::addWidget(QWidget *widget, * @return void * @date 2017/05/16 */ -void DocPage::setInsertBlockType(InsertBlockInfo &blockInfo) +void DocPage::setInsertBlockType(InsertBlockInfo blockInfo) { if(this->insertBlockInfo == NULL) { @@ -504,10 +513,6 @@ void DocPage::mousePressEvent(QMouseEvent *event) if( items.size()> 0) { QGraphicsItem* tempItem = items[0]; - - // 不清楚为什么,造型函数在这里编译出错,因此我采取了强制类型转换 -// DocBlock * block = qobject_cast(tempItem); -// DocBlock * block = (DocBlock *)tempItem; DocBlock* block = qgraphicsitem_cast(tempItem); if(block != NULL) { @@ -850,11 +855,6 @@ void DocPage::addImage() new_image_block->setImage(image); // 设置图片 double page_width = this->width(), page_height = this->height(); -// qDebug() << "Page Width: " << this->width(); -// qDebug() << "Page Height: " << this->height(); -// qDebug() << "Image Width: " << image.width(); -// qDebug() << "Image Height: " << image.height(); - double ratio; if (image.width() > page_width || image.height() > page_height) { @@ -877,3 +877,31 @@ void DocPage::addImage() this->addBlock(newBlock,this->insertBlockInfo->layer); } } + +/// +/// \brief DocPage::addTable +/// 在屏幕中央,插入一个由对话框大小的表格 +/// +void DocPage::addTable() +{ + qDebug() << "insert Table"; + // 暂时做测试,新建默认大小的表格 + DocTable * _table = new DocTable(); + DocBlock * newBlock = new DocBlock(); + newBlock->setWidget(_table); + + double page_width = this->width(), page_height = this->height(); + + double ratio = 1; + double table_width = page_width * 0.8; + double table_height = table_width; + + newBlock->setPos( + (page_width - table_width)/2, + (page_height - table_height)/2 ); + newBlock->resize( + table_width * ratio, + table_height * ratio); + + this->addBlock(newBlock, this->insertBlockInfo->layer); +} diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index 52ec7c7..4213d91 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -52,7 +52,7 @@ public: DocLayer *getLayer(DocPage::Layer layer); // 获得层 //Pan - void addImage(); //添加图片 + bool isUsingWorkArea(){return this->has_working_area;} double getContentWidth(){return this->working_area_width;} @@ -64,7 +64,8 @@ public slots: void setSize(double width, double height); // 设置页面大小 void setPassage(DocPassage * passage); // 设置文章 void addBlock(DocBlock* block, DocPage::Layer layer); // 为页面添加一个新元素 -// void addBlock(DocTextBlock* textBlock, DocPage::Layer layer); // 为页面添加一个新元素 + void addImage(); //添加图片 + void addTable(); // 用对话框来设置插入表格的大小 void changeBlockLayer(DocBlock* block, DocPage::Layer layer); // 更换block的层 void addItem(QGraphicsItem *item); // 拓展接口 QGraphicsProxyWidget *addWidget(QWidget *widget, @@ -72,7 +73,7 @@ public slots: void setBlockFlag(BlockFlag flag){this->newBlockFlag = flag;} - void setInsertBlockType(InsertBlockInfo& blockInfo); // 设置下一个要插入的block的信息 + void setInsertBlockType(InsertBlockInfo blockInfo); // 设置下一个要插入的block的信息 void remove(); // 移除本页 void setScale(double scale); // 设置页面的显示大小 void setWorkingArea( diff --git a/ofdEditor/model/Doc/DocTable.cpp b/ofdEditor/model/Doc/DocTable.cpp index 584865c..8c4cd44 100644 --- a/ofdEditor/model/Doc/DocTable.cpp +++ b/ofdEditor/model/Doc/DocTable.cpp @@ -1,6 +1,12 @@ #include "DocTable.h" #include - +#include "Doc/DocBlock.h" +#include "Doc/DocLayer.h" +#include "Doc/DocPage.h" +#include "Doc/DocPassage.h" +#include +#include +#include DocTable::DocTable(QWidget *parent) :QTextEdit(parent) @@ -8,20 +14,78 @@ DocTable::DocTable(QWidget *parent) QTextCursor cursor = this->textCursor(); // 获得光标 this->_table = cursor.insertTable(3,4); // 插入一个表格 + this->init(); + this->initConnection(); + } +/// +/// \brief DocTable::DocTable +/// 固定的行列数初始化表格 +/// \param rows +/// \param columns +/// DocTable::DocTable(int rows, int columns) :QTextEdit(0) { + QTextCursor cursor = this->textCursor(); // 获得光标 + this->_table = cursor.insertTable(rows, columns); // 插入一个表格 + + this->init(); + this->initConnection(); } + DocTable::~DocTable() { } +DocPassage *DocTable::getPassage() +{ + DocBlock *block = this->_block; + if(block == NULL) + return NULL; + + return block->getPassage(); +} + +DocPage *DocTable::getPage() +{ + DocBlock *block = this->_block; + if(block == NULL) + return NULL; + + return block->getPage(); +} + +DocLayer *DocTable::getLayer() +{ + DocBlock *block = this->_block; + if(block == NULL) + return NULL; + + return block->getLayer(); +} + +DocBlock *DocTable::getBlock() +{ + return this->_block; +} + + +/// +/// \brief DocTable::getMenu +/// 关于表格操作的菜单 +/// \return +/// +QMenu *DocTable::getMenu() +{ + +} + /// /// \brief DocTable::setTable /// 设置表格行数列数 @@ -39,9 +103,85 @@ void DocTable::setTable(int rows, int columns) /// void DocTable::setDefaultStyle() { - QTextDocument* doc = this->_table->document(); // 文档 - QTextFrame * rootFrame = doc->rootFrame(); // 根 框架 + int length = this->_table->columns(); + QVector colWidth; + + for(int i = 0; i < length; i++) + { + QTextLength l(QTextLength::PercentageLength, 1.0 / length * 100); + colWidth.append(l); + } + QTextTableFormat format = this->_table->format(); + format.setColumnWidthConstraints(colWidth); + + // 设置为单线 + QBrush blackBrush(Qt::SolidPattern); + format.setBorderBrush(blackBrush); + format.setBorder(1); + format.setBorderStyle(QTextFrameFormat::BorderStyle_Solid); + format.setCellSpacing(0); +// format.setCellPadding(0); + + this->_table->setFormat(format); +} + +/// +/// \brief DocTable::setBlock +/// \param block +/// +void DocTable::setBlock(DocBlock *block) +{ + this->_block = block; + this->connect(block, SIGNAL(signal_resize(qreal,qreal,qreal,qreal)), + this, SLOT(blockSizeChanged())); +// qDebug() << "set block success"; +} + +void DocTable::init() +{ + this->setFrameStyle(QFrame::NoFrame); + this->setMinimumSize(10,10); + + // 关闭滚动条 + this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + // 设置为背景透明 + this->viewport()->setAttribute(Qt::WA_TranslucentBackground, true); + this->setDefaultStyle(); // 设置默认样式 + +} + +void DocTable::initMenu() +{ + +} + +void DocTable::initConnection() +{ +// qDebug() << "init connection"; + this->connect(this, SIGNAL(textChanged()), + this, SLOT(blockSizeChanged())); +// qDebug() << "init connection success"; +} + +/// +/// \brief DocTable::blockSizeChanged +/// +void DocTable::blockSizeChanged() +{ + qDebug() << "block resize"; + + QTextDocument* doc = this->document(); // 获得文档 + int newHeight = doc->size().height(); + + int oldWidth = (int)(this->_block->size().width() + 0.5); + int oldHeight = (int)(this->_block->size().height() + 0.5); - QTextFrame::iterator iter; + if(oldHeight - newHeight > 5 + || oldHeight - newHeight < -5) + { + // 如果需要调整大小 + this->_block->resize(oldWidth, newHeight); + } } diff --git a/ofdEditor/model/Doc/DocTable.h b/ofdEditor/model/Doc/DocTable.h index ff31337..81aa157 100644 --- a/ofdEditor/model/Doc/DocTable.h +++ b/ofdEditor/model/Doc/DocTable.h @@ -11,6 +11,16 @@ #include #include #include +#include +#include +#include +#include +#include + +class DocBlock; +class DocPassage; +class DocPage; +class DocLayer; /// /// \brief The DocTable class @@ -25,21 +35,38 @@ public: DocTable(QWidget *parent = NULL); DocTable(int rows, int columns); - ~DocTable(); + DocPassage *getPassage(); + DocPage *getPage(); + DocLayer *getLayer(); + DocBlock *getBlock(); + + QMenu *getMenu(); + public slots: void setTable(int rows, int columns); // 设置表格长和宽 void setDefaultStyle(); // 设置默认样式 + void setBlock(DocBlock* block); // 设置块 + private slots: private: // tableCell的内容估计使用QTextBlock + DocBlock* _block; int rowCount; // 行数 int colCount; // 列数 QTextTable* _table; // 该表格 - QTextCursor tableCursor; // 记录指向表格的光标 + + void init(); // 通用的初始化部分 + void initMenu(); // 初始化菜单 + void initConnection(); // 初始化信号槽链接 + +private slots: + void blockSizeChanged(); // 根据文字内容自动调整块的大小 +signals: + void signals_currentTable(DocTable *table); // 当前操作的表格 }; #endif // TABLE_H diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 6843017..f0ffc93 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -326,14 +326,6 @@ void DocTextBlock::remove() */ void DocTextBlock::showBoundaryFrame(bool show) { -// if(show) -// { -// this->setFrameStyle(QFrame::Box); // 显示边框 -// } -// else -// { -// this->setFrameStyle(QFrame::NoFrame); // 隐藏边框 -// } this->block->setShowBoundaryBox(show); } diff --git a/ofdEditor/model/Doc/DocTextBlock.h b/ofdEditor/model/Doc/DocTextBlock.h index adf7a84..56dda1a 100644 --- a/ofdEditor/model/Doc/DocTextBlock.h +++ b/ofdEditor/model/Doc/DocTextBlock.h @@ -130,7 +130,7 @@ private: signals: void signals_remove(DocTextBlock* textBlock); // 移除文本框的信号。 - void signals_setZValue(qreal z); // 设置Z值的信号 + void signals_setZValue(qreal z); // 设置Z值的信号 void signals_currentCharFormatChanged( QTextCharFormat fmt); // 当前选择的charFormat发生了变化 diff --git a/ofdEditor/start/ActionConnector/ActionConnector.cpp b/ofdEditor/start/ActionConnector/ActionConnector.cpp index e3742f8..720b005 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.cpp +++ b/ofdEditor/start/ActionConnector/ActionConnector.cpp @@ -70,7 +70,7 @@ void ActionConnector::addNewPage() *@return 返回值 *@date 2017/05/15 */ -void ActionConnector::addNewBlock(InsertBlockInfo& blockInfo) +void ActionConnector::addNewBlock(InsertBlockInfo blockInfo) { if(this->passage == NULL) { @@ -86,24 +86,27 @@ void ActionConnector::addNewBlock(InsertBlockInfo& blockInfo) } else { - //插入文本框 + if (blockInfo.type == DocPage::text) { + //插入文本框 // qDebug() << "get Focus Sucess"; - page->setBlockFlag(DocPage::draw); // 进入绘画状态 - - // InsertBlockInfo blockInfo(type,layer); // 设置插入文本框信息 - page->setInsertBlockType(blockInfo); // 设置插入文本框信息 - - page->viewport()->setCursor(Qt::CrossCursor); // 将鼠标设置为加号形状 + page->setBlockFlag(DocPage::draw); // 进入绘画状态 + page->setInsertBlockType(blockInfo); // 设置插入文本框信息 + page->viewport()->setCursor(Qt::CrossCursor); // 将鼠标设置为加号形状 } - //插入图片框 else if (blockInfo.type == DocPage::image) { - page->setInsertBlockType(blockInfo); // 设置插入文本框信息 -// qDebug() << "!!!"; + //插入图片框 + page->setInsertBlockType(blockInfo); // 设置插入文本框信息 page->addImage(); } + else if( blockInfo.type == DocPage::table ) + { + // 插入表格 + page->setInsertBlockType(blockInfo); // 设置插入为表格 + page->addTable(); // 从对话框来设置 + } } } @@ -129,10 +132,10 @@ void ActionConnector::addTableBlock() if(this->passage == NULL) return; -// InsertBlockInfo blockInfo(this->defaultLayer,DocPage::table); // 设置插入文本框信息 -// this->addNewBlock(blockInfo); - InsertTableDialog * tableDialog = new InsertTableDialog(0); - tableDialog->exec(); + InsertBlockInfo blockInfo(this->defaultLayer,DocPage::table); // 设置插入文本框信息 + this->addNewBlock(blockInfo); +// InsertTableDialog * tableDialog = new InsertTableDialog(0); +// tableDialog->exec(); } void ActionConnector::undo() diff --git a/ofdEditor/start/ActionConnector/ActionConnector.h b/ofdEditor/start/ActionConnector/ActionConnector.h index 249ee21..f0c6a06 100644 --- a/ofdEditor/start/ActionConnector/ActionConnector.h +++ b/ofdEditor/start/ActionConnector/ActionConnector.h @@ -30,7 +30,7 @@ public slots: void showAttribute(); // 显示文档元信息 void setMainWindow(PassageMainWindow * mainWindow); // 设置主窗口 void addNewPage(); // 添加一个新页面 - void addNewBlock(InsertBlockInfo &blockInfo); // 插入一个块 + void addNewBlock(InsertBlockInfo blockInfo); // 插入一个块 void addTextBlock(); // 插入文本框 void addImageBlock(); // 插入图片框 void addTableBlock(); // 插入表格 diff --git a/ofdEditor/start/ui/RecentFiles.ui b/ofdEditor/start/ui/RecentFiles.ui index 3de5be8..a3b3f48 100644 --- a/ofdEditor/start/ui/RecentFiles.ui +++ b/ofdEditor/start/ui/RecentFiles.ui @@ -74,7 +74,7 @@ false - true + false true -- Gitee From 9f1c8f805a915e36899e9eace7cdb8ac64ee9ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sun, 27 Aug 2017 21:11:13 +0800 Subject: [PATCH 54/83] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E7=BB=A7=E6=89=BF?= =?UTF-8?q?=E6=96=87=E6=9C=AC=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocBlock.cpp | 2 +- ofdEditor/model/Doc/DocTable.cpp | 11 +++++------ ofdEditor/model/Doc/DocTable.h | 5 +++-- ofdEditor/model/Doc/DocTextBlock.cpp | 6 ++++++ ofdEditor/model/Doc/DocTextBlock.h | 5 +++-- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index 8e169a3..803e16a 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -624,7 +624,7 @@ QMenu *DocBlock::getMenu() this->action_background->setChecked(true); } - if(this->isTextBlock()) + if(this->isTextBlock() || this->isTableBlock()) { // 文本框 menu = this->textBlock->getMenu(); diff --git a/ofdEditor/model/Doc/DocTable.cpp b/ofdEditor/model/Doc/DocTable.cpp index 8c4cd44..b9f7f55 100644 --- a/ofdEditor/model/Doc/DocTable.cpp +++ b/ofdEditor/model/Doc/DocTable.cpp @@ -9,7 +9,7 @@ #include DocTable::DocTable(QWidget *parent) - :QTextEdit(parent) + :DocTextBlock(1.0) { QTextCursor cursor = this->textCursor(); // 获得光标 this->_table = cursor.insertTable(3,4); // 插入一个表格 @@ -17,7 +17,6 @@ DocTable::DocTable(QWidget *parent) this->init(); this->initConnection(); - } /// @@ -27,7 +26,7 @@ DocTable::DocTable(QWidget *parent) /// \param columns /// DocTable::DocTable(int rows, int columns) - :QTextEdit(0) + :DocTextBlock(1.0) { QTextCursor cursor = this->textCursor(); // 获得光标 this->_table = cursor.insertTable(rows, columns); // 插入一个表格 @@ -81,10 +80,10 @@ DocBlock *DocTable::getBlock() /// 关于表格操作的菜单 /// \return /// -QMenu *DocTable::getMenu() -{ +//QMenu *DocTable::getMenu() +//{ -} +//} /// /// \brief DocTable::setTable diff --git a/ofdEditor/model/Doc/DocTable.h b/ofdEditor/model/Doc/DocTable.h index 81aa157..93da249 100644 --- a/ofdEditor/model/Doc/DocTable.h +++ b/ofdEditor/model/Doc/DocTable.h @@ -16,6 +16,7 @@ #include #include #include +#include "Doc/DocTextBlock.h" class DocBlock; class DocPassage; @@ -28,7 +29,7 @@ class DocLayer; /// 为一个QTextEdit、但内部内容仅有一个QTextTable /// class MODELSHARED_EXPORT DocTable - :public QTextEdit + :public DocTextBlock { Q_OBJECT public: @@ -42,7 +43,7 @@ public: DocLayer *getLayer(); DocBlock *getBlock(); - QMenu *getMenu(); +// QMenu *getMenu(); public slots: void setTable(int rows, int columns); // 设置表格长和宽 diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index f0ffc93..d055564 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -22,6 +22,11 @@ DocTextBlock::DocTextBlock(QWidget *parent) :QTextEdit(parent) { this->init(); // 调用初始化函数 +} + +DocTextBlock::DocTextBlock(double i) + :QTextEdit(0) +{ } @@ -843,6 +848,7 @@ void DocTextBlock::init() this->initAcitons(); // 初始化QAction相关 this->initMenu(); // 初始化右键菜单 + qDebug() << "text block init finished"; } /** diff --git a/ofdEditor/model/Doc/DocTextBlock.h b/ofdEditor/model/Doc/DocTextBlock.h index 56dda1a..671a0bd 100644 --- a/ofdEditor/model/Doc/DocTextBlock.h +++ b/ofdEditor/model/Doc/DocTextBlock.h @@ -26,6 +26,7 @@ class MODELSHARED_EXPORT DocTextBlock Q_OBJECT public: DocTextBlock(QWidget *parent = NULL); + DocTextBlock(double i); // 假的构造函数 ~DocTextBlock(); void setContent(QString str); // 设置内容 @@ -97,12 +98,12 @@ protected: void focusInEvent(QFocusEvent *e); void focusOutEvent(QFocusEvent *e); -private slots: +protected slots: void checkCurrentFormat(); // 检查当前的格式是否发生改变 void emitFormatSignals(); // 发射格式的信号 void textBlockSizeChanged(); // 当文字内容改变时自动调整文字大小 -private: +protected: QString content; // 文字内容 void init(); // 初始化 void initAcitons(); // 初始化事件 -- Gitee From d9770a4d136e5975d82ebac407bf44db15acbb32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sun, 27 Aug 2017 23:22:55 +0800 Subject: [PATCH 55/83] =?UTF-8?q?=E5=B0=BD=E5=8A=9B=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E8=A1=A8=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocBlock.cpp | 32 +-- ofdEditor/model/Doc/DocBlock.h | 1 - ofdEditor/model/Doc/DocTable.cpp | 135 +++++++---- ofdEditor/model/Doc/DocTable.h | 20 +- ofdEditor/model/Doc/DocTextBlock.cpp | 17 +- ofdEditor/model/Doc/DocTextBlock.h | 1 + ofdEditor/model/Widget/InsertTableDialog.ui | 65 +---- .../Widget/TableInsertRowOrColDialog.cpp | 14 ++ .../model/Widget/TableInsertRowOrColDialog.h | 22 ++ .../model/Widget/TableInsertRowOrColDialog.ui | 120 ++++++++++ ofdEditor/model/Widget/TableSettingDialog.cpp | 14 ++ ofdEditor/model/Widget/TableSettingDialog.h | 22 ++ ofdEditor/model/Widget/TableSettingDialog.ui | 224 ++++++++++++++++++ ofdEditor/model/model.pro | 12 +- 14 files changed, 552 insertions(+), 147 deletions(-) create mode 100644 ofdEditor/model/Widget/TableInsertRowOrColDialog.cpp create mode 100644 ofdEditor/model/Widget/TableInsertRowOrColDialog.h create mode 100644 ofdEditor/model/Widget/TableInsertRowOrColDialog.ui create mode 100644 ofdEditor/model/Widget/TableSettingDialog.cpp create mode 100644 ofdEditor/model/Widget/TableSettingDialog.h create mode 100644 ofdEditor/model/Widget/TableSettingDialog.ui diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index 803e16a..709af3d 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -34,6 +34,7 @@ DocBlock::DocBlock(QGraphicsItem *parent , Qt::WindowFlags wFlags) this->setAcceptHoverEvents(true); this->textBlock = NULL; this->imageBlock = NULL; + this->_table = NULL; this->isShowBox = false; this->initMenu(); @@ -297,8 +298,8 @@ void DocBlock::hoverMoveEvent(QGraphicsSceneHoverEvent *event) void DocBlock::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { - this->clearFocus(); - this->setFocus(); +// this->clearFocus(); +// this->setFocus(); } @@ -362,18 +363,6 @@ void DocBlock::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) QGraphicsProxyWidget::mouseReleaseEvent(event); } -/** - * @Author Chaoqun - * @brief 可以实现右键菜单 - * @param 参数 - * @return 返回值 - * @date 2017/06/20 - */ -void DocBlock::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) -{ - QGraphicsProxyWidget::contextMenuEvent(event); -} - /** * @Author Chaoqun * @brief 设置内容 @@ -405,6 +394,7 @@ void DocBlock::setWidget(DocTextBlock *textBlock) this->textBlock = textBlock; // 给DocBlock设置引用 QGraphicsProxyWidget::setWidget(textBlock); + qDebug() <<"set widget text"; } @@ -432,6 +422,7 @@ void DocBlock::setWidget(DocTable *table) table->setBlock(this); this->_table = table; QGraphicsProxyWidget::setWidget(table); + qDebug() << "set Widget table"; } /// @@ -624,7 +615,7 @@ QMenu *DocBlock::getMenu() this->action_background->setChecked(true); } - if(this->isTextBlock() || this->isTableBlock()) + if(this->isTextBlock()) { // 文本框 menu = this->textBlock->getMenu(); @@ -636,6 +627,17 @@ QMenu *DocBlock::getMenu() menu->addAction(this->action_delete); } + else if(this->isTableBlock()) + { + // 这个是表格 + menu = this->_table->getMenu(); + menu->setTitle(this->_table->getType()); + + menu->addSeparator(); + menu->addAction(this->action_geometry); + menu->addMenu(menu_layer); + menu->addAction(this->action_delete); + } else if(this->isImageBlock()) { // 如果是图片 diff --git a/ofdEditor/model/Doc/DocBlock.h b/ofdEditor/model/Doc/DocBlock.h index c998d96..54aa0b6 100644 --- a/ofdEditor/model/Doc/DocBlock.h +++ b/ofdEditor/model/Doc/DocBlock.h @@ -99,7 +99,6 @@ protected: void mousePressEvent (QGraphicsSceneMouseEvent * event); void mouseMoveEvent (QGraphicsSceneMouseEvent *event); void mouseReleaseEvent (QGraphicsSceneMouseEvent * event); - void contextMenuEvent (QGraphicsSceneContextMenuEvent *event); // 邮件菜单吧 private: diff --git a/ofdEditor/model/Doc/DocTable.cpp b/ofdEditor/model/Doc/DocTable.cpp index b9f7f55..2960634 100644 --- a/ofdEditor/model/Doc/DocTable.cpp +++ b/ofdEditor/model/Doc/DocTable.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include DocTable::DocTable(QWidget *parent) :DocTextBlock(1.0) @@ -42,48 +44,52 @@ DocTable::~DocTable() } -DocPassage *DocTable::getPassage() -{ - DocBlock *block = this->_block; - if(block == NULL) - return NULL; - - return block->getPassage(); -} - -DocPage *DocTable::getPage() -{ - DocBlock *block = this->_block; - if(block == NULL) - return NULL; - - return block->getPage(); -} - -DocLayer *DocTable::getLayer() -{ - DocBlock *block = this->_block; - if(block == NULL) - return NULL; - - return block->getLayer(); -} - -DocBlock *DocTable::getBlock() +/// +/// \brief DocTable::getType +/// \return +/// +QString DocTable::getType() { - return this->_block; + return tr("DocTable"); } - /// /// \brief DocTable::getMenu /// 关于表格操作的菜单 /// \return /// -//QMenu *DocTable::getMenu() -//{ +QMenu *DocTable::getMenu() +{ + this->ContextMenu->clear(); //清空菜单 + this->ContextMenu->setTitle(this->getType()); + + this->ContextMenu->addAction(this->actionCut); + this->ContextMenu->addAction(this->actionCopy); + this->ContextMenu->addAction(this->actionPaste); + this->ContextMenu->addAction(this->actionSelectAll); + + this->ContextMenu->addSeparator(); // 增加分界线 + this->ContextMenu->addAction(this->actionBold); // 加粗 + this->ContextMenu->addAction(this->actionItalic); // 斜体 + this->ContextMenu->addAction(this->actionColor); // 颜色 + + this->ContextMenu->addSeparator(); // 分界线 + this->ContextMenu->addAction(this->actionFontSetTest); // 字体 + this->ContextMenu->addAction(this->actionParagraph); // 段落设置 + + // 检验粘贴键的状态 + QClipboard *board = QApplication::clipboard(); + if(board->text().length() <= 0) + { + this->actionPaste->setEnabled(false); + } + else + { + this->actionPaste->setEnabled(true); + } -//} + return this->ContextMenu; +} /// /// \brief DocTable::setTable @@ -93,7 +99,7 @@ DocBlock *DocTable::getBlock() /// void DocTable::setTable(int rows, int columns) { - + this->_table->resize(rows,columns); } /// @@ -130,37 +136,66 @@ void DocTable::setDefaultStyle() /// void DocTable::setBlock(DocBlock *block) { - this->_block = block; + this->block = block; this->connect(block, SIGNAL(signal_resize(qreal,qreal,qreal,qreal)), this, SLOT(blockSizeChanged())); -// qDebug() << "set block success"; +// qDebug() << "set block success table"; +} + +void DocTable::focusInEvent(QFocusEvent *e) +{ + emitFormatSignals(); + QTextEdit::focusInEvent(e); +} + +void DocTable::focusOutEvent(QFocusEvent *e) +{ + QTextEdit::focusOutEvent(e); } void DocTable::init() { - this->setFrameStyle(QFrame::NoFrame); - this->setMinimumSize(10,10); - - // 关闭滚动条 - this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - // 设置为背景透明 - this->viewport()->setAttribute(Qt::WA_TranslucentBackground, true); +// this->setFrameStyle(QFrame::NoFrame); + this->setMinimumSize(50,10); + +// // 关闭滚动条 +// this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); +// this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); +// // 设置为背景透明 +// this->viewport()->setAttribute(Qt::WA_TranslucentBackground, true); this->setDefaultStyle(); // 设置默认样式 + this->initMenu(); + } void DocTable::initMenu() { + this->ContextMenu = new QMenu(tr("DocTable")); + + // 基本功能 + this->ContextMenu->addAction(this->actionCut); + this->ContextMenu->addAction(this->actionCopy); + this->ContextMenu->addAction(this->actionPaste); + this->ContextMenu->addAction(this->actionSelectAll); + + this->ContextMenu->addSeparator(); // 增加分界线 + this->ContextMenu->addAction(this->actionBold); // 加粗 + this->ContextMenu->addAction(this->actionItalic); // 斜体 + this->ContextMenu->addAction(this->actionColor); // 颜色 + + this->ContextMenu->addSeparator(); // 分界线 + this->ContextMenu->addAction(this->actionFontSetTest); // 字体 + this->ContextMenu->addAction(this->actionParagraph); // 段落设置 + + qDebug() << "init Menu" <ContextMenu; } void DocTable::initConnection() { -// qDebug() << "init connection"; this->connect(this, SIGNAL(textChanged()), this, SLOT(blockSizeChanged())); -// qDebug() << "init connection success"; } /// @@ -168,19 +203,19 @@ void DocTable::initConnection() /// void DocTable::blockSizeChanged() { - qDebug() << "block resize"; +// qDebug() << "block resize"; QTextDocument* doc = this->document(); // 获得文档 int newHeight = doc->size().height(); - int oldWidth = (int)(this->_block->size().width() + 0.5); - int oldHeight = (int)(this->_block->size().height() + 0.5); + int oldWidth = (int)(this->block->size().width() + 0.5); + int oldHeight = (int)(this->block->size().height() + 0.5); if(oldHeight - newHeight > 5 || oldHeight - newHeight < -5) { // 如果需要调整大小 - this->_block->resize(oldWidth, newHeight); + this->block->resize(oldWidth, newHeight); } } diff --git a/ofdEditor/model/Doc/DocTable.h b/ofdEditor/model/Doc/DocTable.h index 93da249..dbb6466 100644 --- a/ofdEditor/model/Doc/DocTable.h +++ b/ofdEditor/model/Doc/DocTable.h @@ -36,26 +36,23 @@ public: DocTable(QWidget *parent = NULL); DocTable(int rows, int columns); - ~DocTable(); + ~DocTable(); - DocPassage *getPassage(); - DocPage *getPage(); - DocLayer *getLayer(); - DocBlock *getBlock(); - -// QMenu *getMenu(); + QString getType(); // 获得类型 + QMenu *getMenu(); public slots: void setTable(int rows, int columns); // 设置表格长和宽 void setDefaultStyle(); // 设置默认样式 void setBlock(DocBlock* block); // 设置块 +protected: + void focusInEvent(QFocusEvent *e); + void focusOutEvent(QFocusEvent *e); private slots: private: - // tableCell的内容估计使用QTextBlock - DocBlock* _block; int rowCount; // 行数 int colCount; // 列数 QTextTable* _table; // 该表格 @@ -64,6 +61,11 @@ private: void initMenu(); // 初始化菜单 void initConnection(); // 初始化信号槽链接 + QAction *actionDeleteRow; // 删除该行 + QAction *actionDeleteColumn; // 删除该列 + QAction *actionInsertRowOrCol; // 插入行或列-由对话框解决 + QAction *actionTableSetting; // 表格设置-对话框解决 + private slots: void blockSizeChanged(); // 根据文字内容自动调整块的大小 signals: diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index d055564..992cc10 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -22,12 +22,14 @@ DocTextBlock::DocTextBlock(QWidget *parent) :QTextEdit(parent) { this->init(); // 调用初始化函数 + + this->initNotUseInSun(); } DocTextBlock::DocTextBlock(double i) :QTextEdit(0) { - + this->init(); } DocTextBlock::~DocTextBlock() @@ -164,7 +166,6 @@ QMenu *DocTextBlock::getMenu() this->ContextMenu->addSeparator(); // 增加分界线 this->ContextMenu->addAction(this->actionBold); // 加粗 this->ContextMenu->addAction(this->actionItalic); // 斜体 -// this->ContextMenu->addAction(this->actionUnderline); // 下划线 this->ContextMenu->addAction(this->actionColor); // 颜色 this->ContextMenu->addSeparator(); // 分界线 @@ -825,6 +826,7 @@ void DocTextBlock::textBlockSizeChanged() */ void DocTextBlock::init() { + this->setMinimumSize(5,5); // 为了正确显示缩放标识 // 关闭滑动条 @@ -847,7 +849,6 @@ void DocTextBlock::init() this, SLOT(checkCurrentFormat())); this->initAcitons(); // 初始化QAction相关 - this->initMenu(); // 初始化右键菜单 qDebug() << "text block init finished"; } @@ -928,10 +929,16 @@ void DocTextBlock::initAcitons() this->connect(this->actionFontSetTest, SIGNAL(triggered()), this, SLOT(customFontDialog())); +} + +void DocTextBlock::initNotUseInSun() +{ + + this->initMenu(); // 初始化右键菜单 + // 自动调整窗口大小 this->connect(this, SIGNAL(textChanged()), this, SLOT(textBlockSizeChanged())); - } /** @@ -969,7 +976,7 @@ void DocTextBlock::initMenu() this->ContextMenu->addSeparator(); // 增加分界线 this->ContextMenu->addAction(this->actionBold); // 加粗 this->ContextMenu->addAction(this->actionItalic); // 斜体 -// this->ContextMenu->addAction(this->actionUnderline); // 下划线 +// this->ContextMenu->addAction(this->actionUnderline); // 下划线 this->ContextMenu->addAction(this->actionColor); // 颜色 this->ContextMenu->addSeparator(); // 分界线 diff --git a/ofdEditor/model/Doc/DocTextBlock.h b/ofdEditor/model/Doc/DocTextBlock.h index 671a0bd..85b4106 100644 --- a/ofdEditor/model/Doc/DocTextBlock.h +++ b/ofdEditor/model/Doc/DocTextBlock.h @@ -107,6 +107,7 @@ protected: QString content; // 文字内容 void init(); // 初始化 void initAcitons(); // 初始化事件 + void initNotUseInSun(); // 初始化函数,不应用在子类之中 void initFormat(); // 初始化文字样式 void initMenu(); // 初始化右键菜单 diff --git a/ofdEditor/model/Widget/InsertTableDialog.ui b/ofdEditor/model/Widget/InsertTableDialog.ui index b10aa2c..db807c6 100644 --- a/ofdEditor/model/Widget/InsertTableDialog.ui +++ b/ofdEditor/model/Widget/InsertTableDialog.ui @@ -17,7 +17,7 @@ - 1 + 0 @@ -124,69 +124,6 @@ - - - 高级 - - - - - - 单元格大小 - - - - - - 宽: - - - - - - - - - - mm - - - - - - - 高: - - - - - - - - - - mm - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - diff --git a/ofdEditor/model/Widget/TableInsertRowOrColDialog.cpp b/ofdEditor/model/Widget/TableInsertRowOrColDialog.cpp new file mode 100644 index 0000000..2439ff9 --- /dev/null +++ b/ofdEditor/model/Widget/TableInsertRowOrColDialog.cpp @@ -0,0 +1,14 @@ +#include "TableInsertRowOrColDialog.h" +#include "ui_TableInsertRowOrColDialog.h" + +TableInsertRowOrColDialog::TableInsertRowOrColDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::TableInsertRowOrColDialog) +{ + ui->setupUi(this); +} + +TableInsertRowOrColDialog::~TableInsertRowOrColDialog() +{ + delete ui; +} diff --git a/ofdEditor/model/Widget/TableInsertRowOrColDialog.h b/ofdEditor/model/Widget/TableInsertRowOrColDialog.h new file mode 100644 index 0000000..3c585c7 --- /dev/null +++ b/ofdEditor/model/Widget/TableInsertRowOrColDialog.h @@ -0,0 +1,22 @@ +#ifndef TABLEINSERTROWORCOLDIALOG_H +#define TABLEINSERTROWORCOLDIALOG_H + +#include + +namespace Ui { +class TableInsertRowOrColDialog; +} + +class TableInsertRowOrColDialog : public QDialog +{ + Q_OBJECT + +public: + explicit TableInsertRowOrColDialog(QWidget *parent = 0); + ~TableInsertRowOrColDialog(); + +private: + Ui::TableInsertRowOrColDialog *ui; +}; + +#endif // TABLEINSERTROWORCOLDIALOG_H diff --git a/ofdEditor/model/Widget/TableInsertRowOrColDialog.ui b/ofdEditor/model/Widget/TableInsertRowOrColDialog.ui new file mode 100644 index 0000000..07f3972 --- /dev/null +++ b/ofdEditor/model/Widget/TableInsertRowOrColDialog.ui @@ -0,0 +1,120 @@ + + + TableInsertRowOrColDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + 插入行或列 + + + + + + 插入行 + + + + + + + 插入列 + + + + + + + + + + Qt::PreventContextMenu + + + 0 + + + + + + + + + 30 + 20 + 120 + 80 + + + + 选择 + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + TableInsertRowOrColDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + TableInsertRowOrColDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/ofdEditor/model/Widget/TableSettingDialog.cpp b/ofdEditor/model/Widget/TableSettingDialog.cpp new file mode 100644 index 0000000..e9b1b1b --- /dev/null +++ b/ofdEditor/model/Widget/TableSettingDialog.cpp @@ -0,0 +1,14 @@ +#include "TableSettingDialog.h" +#include "ui_TableSettingDialog.h" + +TableSettingDialog::TableSettingDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::TableSettingDialog) +{ + ui->setupUi(this); +} + +TableSettingDialog::~TableSettingDialog() +{ + delete ui; +} diff --git a/ofdEditor/model/Widget/TableSettingDialog.h b/ofdEditor/model/Widget/TableSettingDialog.h new file mode 100644 index 0000000..9327dff --- /dev/null +++ b/ofdEditor/model/Widget/TableSettingDialog.h @@ -0,0 +1,22 @@ +#ifndef TABLESETTINGDIALOG_H +#define TABLESETTINGDIALOG_H + +#include + +namespace Ui { +class TableSettingDialog; +} + +class TableSettingDialog : public QDialog +{ + Q_OBJECT + +public: + explicit TableSettingDialog(QWidget *parent = 0); + ~TableSettingDialog(); + +private: + Ui::TableSettingDialog *ui; +}; + +#endif // TABLESETTINGDIALOG_H diff --git a/ofdEditor/model/Widget/TableSettingDialog.ui b/ofdEditor/model/Widget/TableSettingDialog.ui new file mode 100644 index 0000000..1703071 --- /dev/null +++ b/ofdEditor/model/Widget/TableSettingDialog.ui @@ -0,0 +1,224 @@ + + + TableSettingDialog + + + + 0 + 0 + 364 + 435 + + + + Dialog + + + + + + <html><head/><body><p>大小位置</p></body></html> + + + 1 + + + + 大小位置 + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 位置 + + + + + + 距左方 + + + + + + + + + + mm + + + + + + + 距上方 + + + + + + + + + + mm + + + + + + + + + + 总体大小 + + + + + + 宽: + + + + + + + + + + mm + + + + + + + 高: + + + + + + + + + + mm + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 列宽 + + + + + 30 + 50 + 91 + 18 + + + + 均分列宽 + + + + + + 30 + 80 + 91 + 18 + + + + 自定义列宽 + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + TableSettingDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + TableSettingDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index 0ca650d..80edce5 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -53,7 +53,9 @@ SOURCES += model.cpp \ Widget/FindAndReplaceDock.cpp \ Widget/SelectTemplateDialog.cpp \ Core/GlobalSetting.cpp \ - Widget/InsertPageDialog.cpp + Widget/InsertPageDialog.cpp \ + Widget/TableSettingDialog.cpp \ + Widget/TableInsertRowOrColDialog.cpp HEADERS += model.h\ model_global.h \ @@ -86,7 +88,9 @@ HEADERS += model.h\ Widget/SelectTemplateDialog.h \ Core/GlobalSetting.h \ Widget/DocInfoDialog.h \ - Widget/InsertPageDialog.h + Widget/InsertPageDialog.h \ + Widget/TableSettingDialog.h \ + Widget/TableInsertRowOrColDialog.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 @@ -122,7 +126,9 @@ FORMS += \ Widget/InsertTableDialog.ui \ Widget/FindAndReplaceDock.ui \ Widget/SelectTemplateDialog.ui \ - Widget/InsertPageDialog.ui + Widget/InsertPageDialog.ui \ + Widget/TableSettingDialog.ui \ + Widget/TableInsertRowOrColDialog.ui RESOURCES += \ resource.qrc -- Gitee From 9306cf3ff4e1ad17fb4aaba1fd53c704c6e23912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Mon, 28 Aug 2017 11:59:53 +0800 Subject: [PATCH 56/83] =?UTF-8?q?=E8=A1=A8=E6=A0=BC=E7=9A=84=E6=80=BB?= =?UTF-8?q?=E4=BD=93=E5=A4=A7=E6=A1=86=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocTable.cpp | 228 +++++++++++++++- ofdEditor/model/Doc/DocTable.h | 43 ++- ofdEditor/model/Widget/TableSettingDialog.ui | 268 +++++++++++++++---- 3 files changed, 475 insertions(+), 64 deletions(-) diff --git a/ofdEditor/model/Doc/DocTable.cpp b/ofdEditor/model/Doc/DocTable.cpp index 2960634..270ecbc 100644 --- a/ofdEditor/model/Doc/DocTable.cpp +++ b/ofdEditor/model/Doc/DocTable.cpp @@ -17,7 +17,7 @@ DocTable::DocTable(QWidget *parent) this->_table = cursor.insertTable(3,4); // 插入一个表格 this->init(); - this->initConnection(); + } @@ -34,8 +34,6 @@ DocTable::DocTable(int rows, int columns) this->_table = cursor.insertTable(rows, columns); // 插入一个表格 this->init(); - this->initConnection(); - } @@ -88,6 +86,27 @@ QMenu *DocTable::getMenu() this->actionPaste->setEnabled(true); } + // 选择表格的状态 + QTextCursor cursor = this->textCursor(); // 文本光标 +// int firstRow, numRows, firstColumn, numColumns; // 选择的 +// cursor.selectedTableCells( +// &firstRow, &numRows, &firstColumn, &numColumns); + this->selectedCells(cursor); + + qDebug() << "firstRow, numRows, firstColumn, numColumns" + << this->firstRow + << this->rows + << this->firstColumn + << this->columns; + + this->ContextMenu->addSeparator(); // ------------------ + this->ContextMenu->addAction(this->actionTableSetting); // 表格设置 + this->ContextMenu->addMenu(this->menu_insertRowOrCol); // 插入行或列 + this->ContextMenu->addAction(this->actionMergeCells); // 合并单元格 + this->ContextMenu->addAction(this->actionSplitCells); // 拆分单元格 + this->ContextMenu->addAction(this->actionDeleteRow); // 删除该行 + this->ContextMenu->addAction(this->actionDeleteColumn); // 删除该列 + return this->ContextMenu; } @@ -139,7 +158,96 @@ void DocTable::setBlock(DocBlock *block) this->block = block; this->connect(block, SIGNAL(signal_resize(qreal,qreal,qreal,qreal)), this, SLOT(blockSizeChanged())); -// qDebug() << "set block success table"; + // qDebug() << "set block success table"; +} + +/// +/// \brief DocTable::insertRowBefore +/// 在之前插入行 +/// +void DocTable::insertRowBefore() +{ + QTextCursor cursor = this->textCursor(); + this->insertRow(cursor, -1); +} + +/// +/// \brief DocTable::insertRow +/// 插入行 +/// \param cursor +/// \param flag +/// +void DocTable::insertRow(QTextCursor cursor, int flag) +{ + int firstRow, numRows, firstColumn, numColumns; // 选择的 + cursor.selectedTableCells( + &firstRow, &numRows, &firstColumn, &numColumns); + + // 插入行 + if(flag == -1) + { + // 在选择区域最左侧插入一行 + + } + else if(flag == 1) + { + + } + +} + +void DocTable::insertRowAfter() +{ + +} + +void DocTable::insertColBefore() +{ + +} + +void DocTable::insertColAfter() +{ + +} + +void DocTable::mergeCells() +{ + QTextCursor cursor = this->textCursor(); + this->_table->mergeCells(cursor); +} + +void DocTable::splitCells() +{ + +} + +void DocTable::delRow() +{ + +} + +void DocTable::delCol() +{ + +} + +void DocTable::tableSetting() +{ + +} + +void DocTable::updateStyle() +{ + + if(this->isDefaultStyle) + { + this->setDefaultStyle(); + } + else + { + // 按照设置的比例调节 + } } void DocTable::focusInEvent(QFocusEvent *e) @@ -153,19 +261,66 @@ void DocTable::focusOutEvent(QFocusEvent *e) QTextEdit::focusOutEvent(e); } +void DocTable::selectedCells(QTextCursor &cursor) +{ + // 这里可以检测是否复选单元格 + cursor.selectedTableCells( + &this->firstRow, + &this->rows, + &this->firstColumn, + &this->columns); + + if( + this->firstRow == -1 + && this->rows == -1 + && this->firstColumn == -1 + && this->columns == -1) + { + QTextTableCell cell = this->_table->cellAt(cursor); + this->firstRow = cell.row(); + this->rows = cell.rowSpan(); + this->firstColumn = cell.column(); + this->columns = cell.columnSpan(); + } + +} + void DocTable::init() { // this->setFrameStyle(QFrame::NoFrame); this->setMinimumSize(50,10); -// // 关闭滚动条 -// this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); -// this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); -// // 设置为背景透明 -// this->viewport()->setAttribute(Qt::WA_TranslucentBackground, true); - this->setDefaultStyle(); // 设置默认样式 + this->firstRow = 0; + this->firstColumn = 0; + this->rows = 1; + this->columns = 1; + + this->isDefaultStyle = true; + this->updateStyle(); // 更新样式 + this->initAction(); this->initMenu(); + this->initConnection(); + +} + +/// +/// \brief DocTable::initAction +/// 初始化QAction +void DocTable::initAction() +{ + // 插入 + this->actionInsertColAfter = new QAction(tr("insert Col After"), this); + this->actionInsertColBefore = new QAction(tr("insert Col Before"), this); + this->actionInsertRowAfter = new QAction(tr("insert row after"), this); + this->actionInsertRowBefore = new QAction(tr("insert row before"), this); + + this->actionMergeCells = new QAction(tr("Merge Cells"), this); // 合并单元格 + this->actionSplitCells = new QAction(tr("Split Cells"), this); // 拆分单元格 + + this->actionDeleteColumn = new QAction(tr("delete column"), this); // 删除列 + this->actionDeleteRow = new QAction(tr("delete row"), this); // 删除整行 + this->actionTableSetting = new QAction(tr("table setting"), this); // 表格设置 } @@ -188,12 +343,63 @@ void DocTable::initMenu() this->ContextMenu->addAction(this->actionFontSetTest); // 字体 this->ContextMenu->addAction(this->actionParagraph); // 段落设置 - qDebug() << "init Menu" <ContextMenu; + this->ContextMenu->addSeparator(); // ------------- + this->ContextMenu->addAction(this->actionTableSetting); // 表格设置 + + this->menu_insertRowOrCol = new QMenu(tr("Insert Row or Col")); // 插入行或列 + this->menu_insertRowOrCol->addAction(this->actionInsertRowBefore); + this->menu_insertRowOrCol->addAction(this->actionInsertRowAfter); + this->menu_insertRowOrCol->addAction(this->actionInsertColBefore); + this->menu_insertRowOrCol->addAction(this->actionInsertColAfter); + + this->ContextMenu->addMenu(this->menu_insertRowOrCol); + this->ContextMenu->addAction(this->actionMergeCells); // 合并单元格 + this->ContextMenu->addAction(this->actionSplitCells); // 拆分单元格 + this->ContextMenu->addAction(this->actionDeleteRow); // 删除该行 + this->ContextMenu->addAction(this->actionDeleteColumn); // 删除该列 } void DocTable::initConnection() { + + // 在当前单元格之前插入列 + this->connect(this->actionInsertColBefore, SIGNAL(triggered(bool)), + this, SLOT(insertColBefore())); + + // 在当前单元格之后插入列 + this->connect(this->actionInsertColAfter, SIGNAL(triggered(bool)), + this, SLOT(insertColAfter())); + + // 在当前单元格之前插入行 + this->connect(this->actionInsertRowBefore, SIGNAL(triggered(bool)), + this, SLOT(insertRowBefore())); + + // 在当前单元格之后插入 + this->connect(this->actionInsertRowAfter, SIGNAL(triggered(bool)), + this, SLOT(insertRowAfter())); + + // 合并单元格 + this->connect(this->actionMergeCells, SIGNAL(triggered(bool)), + this, SLOT(mergeCells())); + + // 拆分单元格-------我觉得拆分单元格要慎重-就只把原本合并的单元格分开就好了? + this->connect(this->actionSplitCells, SIGNAL(triggered(bool)), + this, SLOT(splitCells())); + + // 删除整行 + this->connect(this->actionDeleteRow, SIGNAL(triggered(bool)), + this, SLOT(delRow())); + + // 删除整列 + this->connect(this->actionDeleteColumn, SIGNAL(triggered(bool)), + this, SLOT(delCol())); + + // 表格设置 + this->connect(this->actionTableSetting, SIGNAL(triggered(bool)), + this, SLOT(tableSetting())); + + // 自动调整大小 this->connect(this, SIGNAL(textChanged()), this, SLOT(blockSizeChanged())); } diff --git a/ofdEditor/model/Doc/DocTable.h b/ofdEditor/model/Doc/DocTable.h index dbb6466..d482daa 100644 --- a/ofdEditor/model/Doc/DocTable.h +++ b/ofdEditor/model/Doc/DocTable.h @@ -46,24 +46,65 @@ public slots: void setDefaultStyle(); // 设置默认样式 void setBlock(DocBlock* block); // 设置块 + // 插入行或列 + void insertRowBefore(); + void insertRow( + QTextCursor cursor, + int flag); + void insertRowAfter(); + void insertColBefore(); + void insertColAfter(); + + // 合并单元格 + void mergeCells(); + + // 拆分单元格 + void splitCells(); + + // 删除 + void delRow(); + void delCol(); + + // 单元格设置 + void tableSetting(); + void updateStyle(); // 更新表格的样式 + protected: void focusInEvent(QFocusEvent *e); void focusOutEvent(QFocusEvent *e); private slots: + void selectedCells(QTextCursor& cursor); private: int rowCount; // 行数 int colCount; // 列数 QTextTable* _table; // 该表格 + QVector colWidth; // 列宽设置 + bool isDefaultStyle; + + // 选择的结果 + int firstRow; + int firstColumn; + int rows; + int columns; void init(); // 通用的初始化部分 + void initAction(); // 初始化Action void initMenu(); // 初始化菜单 void initConnection(); // 初始化信号槽链接 + QMenu *menu_insertRowOrCol; // 插入行或列 + QAction *actionInsertRowBefore; // 在当前单元格之前插入行 + QAction *actionInsertRowAfter; // 在当前单元格之后插入行 + QAction *actionInsertColBefore; // 在当前单元格之前插入列 + QAction *actionInsertColAfter; // 在当前单元格之后插入列 + + QAction *actionMergeCells; // 合并单元格 + QAction *actionSplitCells; // 拆分单元格 + QAction *actionDeleteRow; // 删除该行 QAction *actionDeleteColumn; // 删除该列 - QAction *actionInsertRowOrCol; // 插入行或列-由对话框解决 QAction *actionTableSetting; // 表格设置-对话框解决 private slots: diff --git a/ofdEditor/model/Widget/TableSettingDialog.ui b/ofdEditor/model/Widget/TableSettingDialog.ui index 1703071..101350f 100644 --- a/ofdEditor/model/Widget/TableSettingDialog.ui +++ b/ofdEditor/model/Widget/TableSettingDialog.ui @@ -6,8 +6,8 @@ 0 0 - 364 - 435 + 325 + 442 @@ -20,65 +20,51 @@ <html><head/><body><p>大小位置</p></body></html> - 1 + 2 大小位置 - - - - Qt::Vertical - - - - 20 - 40 - - - - - - + + - 位置 + 表格线条颜色 - - - - - 距左方 + + + + + Qt::Horizontal - - - - - - - - - mm + + + 40 + 20 + - + - - + + - 距上方 + 颜色 - - - - - - - mm + + + + Qt::Horizontal - + + + 40 + 20 + + + @@ -89,43 +75,203 @@ 总体大小 - + + + + mm + + + + 宽: - + - + mm - + 高: - + - - + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 位置 + + + + + + 距左方 + + + + + + + 距上方 + + + + + + + mm + + + + + mm + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -139,6 +285,19 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -172,6 +331,11 @@ + + + 单元格 + + -- Gitee From 40f556df78baee43be594ff32196ff577fcb8dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Mon, 28 Aug 2017 21:38:58 +0800 Subject: [PATCH 57/83] =?UTF-8?q?=E8=A1=A8=E6=A0=BC=E5=9F=BA=E6=9C=AC?= =?UTF-8?q?=E6=88=90=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocTable.cpp | 212 ++++++++++++-- ofdEditor/model/Doc/DocTable.h | 15 + .../Widget/BlockSizeAndPosSettingDialog.cpp | 14 + .../Widget/BlockSizeAndPosSettingDialog.h | 22 ++ .../Widget/BlockSizeAndPosSettingDialog.ui | 71 +++++ .../Widget/TableInsertRowOrColDialog.cpp | 14 - .../model/Widget/TableInsertRowOrColDialog.h | 22 -- .../model/Widget/TableInsertRowOrColDialog.ui | 120 -------- ofdEditor/model/Widget/TableSettingDialog.cpp | 226 +++++++++++++++ ofdEditor/model/Widget/TableSettingDialog.h | 42 ++- ofdEditor/model/Widget/TableSettingDialog.ui | 265 ++++++++++++------ ofdEditor/model/model.pro | 6 +- ofdEditor/start/ui/RecentFiles.cpp | 10 + 13 files changed, 771 insertions(+), 268 deletions(-) create mode 100644 ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.cpp create mode 100644 ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.h create mode 100644 ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.ui delete mode 100644 ofdEditor/model/Widget/TableInsertRowOrColDialog.cpp delete mode 100644 ofdEditor/model/Widget/TableInsertRowOrColDialog.h delete mode 100644 ofdEditor/model/Widget/TableInsertRowOrColDialog.ui diff --git a/ofdEditor/model/Doc/DocTable.cpp b/ofdEditor/model/Doc/DocTable.cpp index 270ecbc..fbe8c64 100644 --- a/ofdEditor/model/Doc/DocTable.cpp +++ b/ofdEditor/model/Doc/DocTable.cpp @@ -9,6 +9,7 @@ #include #include #include +#include "Widget/TableSettingDialog.h" DocTable::DocTable(QWidget *parent) :DocTextBlock(1.0) @@ -88,28 +89,49 @@ QMenu *DocTable::getMenu() // 选择表格的状态 QTextCursor cursor = this->textCursor(); // 文本光标 -// int firstRow, numRows, firstColumn, numColumns; // 选择的 -// cursor.selectedTableCells( -// &firstRow, &numRows, &firstColumn, &numColumns); this->selectedCells(cursor); - qDebug() << "firstRow, numRows, firstColumn, numColumns" - << this->firstRow - << this->rows - << this->firstColumn - << this->columns; +// qDebug() << "firstRow, numRows, firstColumn, numColumns" +// << this->firstRow +// << this->rows +// << this->firstColumn +// << this->columns; this->ContextMenu->addSeparator(); // ------------------ this->ContextMenu->addAction(this->actionTableSetting); // 表格设置 this->ContextMenu->addMenu(this->menu_insertRowOrCol); // 插入行或列 - this->ContextMenu->addAction(this->actionMergeCells); // 合并单元格 - this->ContextMenu->addAction(this->actionSplitCells); // 拆分单元格 + + if(this->rows > 1 || this->columns > 1) + { + this->ContextMenu->addAction(this->actionMergeCells); // 合并单元格 + this->ContextMenu->addAction(this->actionSplitCells); // 拆分单元格 + } + this->ContextMenu->addAction(this->actionDeleteRow); // 删除该行 this->ContextMenu->addAction(this->actionDeleteColumn); // 删除该列 return this->ContextMenu; } +/// +/// \brief DocTable::getTableColor +/// 获得表格线条的颜色 +/// \return +/// +QColor DocTable::getTableColor() +{ + QTextTableFormat format = this->_table->format(); + QBrush brush = format.borderBrush(); + return brush.color(); +} + +QVector DocTable::getColumnWidth() +{ + QTextTableFormat format = this->_table->format(); + QVector vector = format.columnWidthConstraints(); + return vector; +} + /// /// \brief DocTable::setTable /// 设置表格行数列数 @@ -145,10 +167,30 @@ void DocTable::setDefaultStyle() format.setBorderStyle(QTextFrameFormat::BorderStyle_Solid); format.setCellSpacing(0); // format.setCellPadding(0); +// format.setCellPadding(5); this->_table->setFormat(format); } +void DocTable::setDefaultStyle(bool flag) +{ + this->isDefaultStyle = flag; + if(flag == true) + updateStyle(); +} + +/// +/// \brief DocTable::setColumnWidth +/// 设置每列的宽度 +/// \param vector +/// +void DocTable::setColumnWidth(QVector &vector) +{ + this->colWidth.clear(); + this->colWidth = vector; + this->updateStyle(); +} + /// /// \brief DocTable::setBlock /// \param block @@ -161,6 +203,35 @@ void DocTable::setBlock(DocBlock *block) // qDebug() << "set block success table"; } +/// +/// \brief DocTable::setCellPadding +/// 设置单元格留白 +/// \param cellpadding +/// +void DocTable::setCellPadding(double cellpadding) +{ + QTextTableFormat format = this->_table->format(); + format.setCellPadding(cellpadding); + this->_table->setFormat(format); +} + +void DocTable::setTableColor(QColor color) +{ + QTextTableFormat format = this->_table->format(); + format.setBorderBrush(color); + this->_table->setFormat(format); +} + +/// +/// \brief DocTable::setTableWidth +/// 设置表格总体宽度 +/// \param width +/// +void DocTable::setTableWidth(double width) +{ + this->block->resize(width,this->block->size().rheight()); +} + /// /// \brief DocTable::insertRowBefore /// 在之前插入行 @@ -179,36 +250,74 @@ void DocTable::insertRowBefore() /// void DocTable::insertRow(QTextCursor cursor, int flag) { - int firstRow, numRows, firstColumn, numColumns; // 选择的 - cursor.selectedTableCells( - &firstRow, &numRows, &firstColumn, &numColumns); + this->selectedCells(cursor); // 插入行 if(flag == -1) { - // 在选择区域最左侧插入一行 - + // 在选择区域上方插入一行 + this->_table->insertRows(this->firstRow,1); } else if(flag == 1) { - + this->_table->insertRows(this->firstRow + 1, 1); } } +/// +/// \brief DocTable::insertRowAfter +/// void DocTable::insertRowAfter() { - + QTextCursor cursor = this->textCursor(); + this->insertRow(cursor, 1); } void DocTable::insertColBefore() { - + QTextCursor cursor = this->textCursor(); + this->insertCol(cursor, -1); } void DocTable::insertColAfter() { + QTextCursor cursor = this->textCursor(); + this->insertCol(cursor, 1); +} + +void DocTable::insertCol(QTextCursor cursor, int flag) +{ + this->selectedCells(cursor); + + // 插入行 + if(flag == -1) + { + // 在选择区域前 + this->_table->insertColumns(this->firstColumn,1); + } + else if(flag == 1) + { + this->_table->insertColumns(this->firstColumn + 1, 1); + } + if(!this->isDefaultStyle) + { + // 如果是自定义列宽 + double width = this->colWidth[this->firstColumn].rawValue(); + this->colWidth.remove(this->firstColumn); + this->colWidth.insert( + this->firstColumn, + QTextLength( + QTextLength::PercentageLength, + width / 2)); + this->colWidth.insert( + this->firstColumn, + QTextLength( + QTextLength::PercentageLength, + width / 2)); + } + this->updateStyle(); } void DocTable::mergeCells() @@ -217,24 +326,58 @@ void DocTable::mergeCells() this->_table->mergeCells(cursor); } +/// +/// \brief DocTable::splitCells +/// 将已经合并的项给分离开来 +/// void DocTable::splitCells() { + QTextCursor cursor = this->textCursor(); + this->selectedCells(cursor); + this->_table->splitCell( + this->firstRow, + this->firstColumn, + 1, + 1); +// qDebug() <<"split cells"; } +/// +/// \brief DocTable::delRow +/// 删除当前行 +/// void DocTable::delRow() { + QTextCursor cursor = this->textCursor(); + this->selectedCells(cursor); + this->_table->removeRows(this->firstRow, 1); } +/// +/// \brief DocTable::delCol +/// 删除当前列 +/// void DocTable::delCol() { + QTextCursor cursor = this->textCursor(); + this->selectedCells(cursor); + this->_table->removeColumns(this->firstColumn, 1); + this->updateStyle(); } +/// +/// \brief DocTable::tableSetting +/// 给出表格设置窗口,然后设置表格 +/// void DocTable::tableSetting() { + TableSettingDialog* dialog = TableSettingDialog::getInstance(); + dialog->init(this); + dialog->exec(); } void DocTable::updateStyle() @@ -247,6 +390,13 @@ void DocTable::updateStyle() else { // 按照设置的比例调节 + QTextTableFormat format = this->_table->format(); + if(format.columnWidthConstraints().size() == this->getColumns()) + { + format.setColumnWidthConstraints(this->colWidth); + this->_table->setFormat(format); + } + } } @@ -285,6 +435,25 @@ void DocTable::selectedCells(QTextCursor &cursor) } +/// +/// \brief DocTable::checkCursorInTable +/// 与光标改变事件相关联,如果光标出现在了表格外部, +/// 则将它重新移动回到表格内部 +/// +void DocTable::checkCursorInTable() +{ + QTextCursor cursor = this->textCursor(); + int cursorPosition = cursor.position(); // 光标位置 + + if(!(cursorPosition >= this->_table->firstPosition() + && cursorPosition <= this->_table->lastPosition())) + { + // 如果光标离开了表格的范围 + this->setTextCursor(this->_table->firstCursorPosition()); + } + +} + void DocTable::init() { // this->setFrameStyle(QFrame::NoFrame); @@ -297,11 +466,14 @@ void DocTable::init() this->isDefaultStyle = true; this->updateStyle(); // 更新样式 + this->setCellPadding(5); this->initAction(); this->initMenu(); this->initConnection(); +// this->setCellPadding(5); + } /// @@ -402,6 +574,10 @@ void DocTable::initConnection() // 自动调整大小 this->connect(this, SIGNAL(textChanged()), this, SLOT(blockSizeChanged())); + + // 防止光标移动到表格以外 + this->connect(this, SIGNAL(cursorPositionChanged()), + this, SLOT(checkCursorInTable())); } /// diff --git a/ofdEditor/model/Doc/DocTable.h b/ofdEditor/model/Doc/DocTable.h index d482daa..78acfd5 100644 --- a/ofdEditor/model/Doc/DocTable.h +++ b/ofdEditor/model/Doc/DocTable.h @@ -40,11 +40,22 @@ public: QString getType(); // 获得类型 QMenu *getMenu(); + bool isDefaultWidth(){return this->isDefaultStyle;} // 是否是均分宽度 + double cellPadding(){return this->_table->format().cellPadding();} + QColor getTableColor(); + QVector getColumnWidth(); // 获得行列宽度 + int getColumns(){return this->_table->columns();} + int getRows(){return this->_table->rows();} public slots: void setTable(int rows, int columns); // 设置表格长和宽 void setDefaultStyle(); // 设置默认样式 + void setDefaultStyle(bool flag); // 设置是否为默认样式 + void setColumnWidth(QVector& vector); // 设置每列的宽度 void setBlock(DocBlock* block); // 设置块 + void setCellPadding(double cellpadding); // 设置单元格留白 + void setTableColor(QColor color); // 设置表格颜色 + void setTableWidth(double width); // 设置表格整体宽度 // 插入行或列 void insertRowBefore(); @@ -54,6 +65,9 @@ public slots: void insertRowAfter(); void insertColBefore(); void insertColAfter(); + void insertCol( + QTextCursor cursor, + int flag); // 合并单元格 void mergeCells(); @@ -75,6 +89,7 @@ protected: private slots: void selectedCells(QTextCursor& cursor); + void checkCursorInTable(); // 确保光标永远在表格内部 private: int rowCount; // 行数 diff --git a/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.cpp b/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.cpp new file mode 100644 index 0000000..391a528 --- /dev/null +++ b/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.cpp @@ -0,0 +1,14 @@ +#include "BlockSizeAndPosSettingDialog.h" +#include "ui_BlockSizeAndPosSettingDialog.h" + +BlockSizeAndPosSettingDialog::BlockSizeAndPosSettingDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::BlockSizeAndPosSettingDialog) +{ + ui->setupUi(this); +} + +BlockSizeAndPosSettingDialog::~BlockSizeAndPosSettingDialog() +{ + delete ui; +} diff --git a/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.h b/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.h new file mode 100644 index 0000000..148d619 --- /dev/null +++ b/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.h @@ -0,0 +1,22 @@ +#ifndef BLOCKSIZEANDPOSSETTINGDIALOG_H +#define BLOCKSIZEANDPOSSETTINGDIALOG_H + +#include + +namespace Ui { +class BlockSizeAndPosSettingDialog; +} + +class BlockSizeAndPosSettingDialog : public QDialog +{ + Q_OBJECT + +public: + explicit BlockSizeAndPosSettingDialog(QWidget *parent = 0); + ~BlockSizeAndPosSettingDialog(); + +private: + Ui::BlockSizeAndPosSettingDialog *ui; +}; + +#endif // BLOCKSIZEANDPOSSETTINGDIALOG_H diff --git a/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.ui b/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.ui new file mode 100644 index 0000000..4ba81f1 --- /dev/null +++ b/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.ui @@ -0,0 +1,71 @@ + + + + + BlockSizeAndPosSettingDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + 30 + 240 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + buttonBox + accepted() + BlockSizeAndPosSettingDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + BlockSizeAndPosSettingDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/ofdEditor/model/Widget/TableInsertRowOrColDialog.cpp b/ofdEditor/model/Widget/TableInsertRowOrColDialog.cpp deleted file mode 100644 index 2439ff9..0000000 --- a/ofdEditor/model/Widget/TableInsertRowOrColDialog.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "TableInsertRowOrColDialog.h" -#include "ui_TableInsertRowOrColDialog.h" - -TableInsertRowOrColDialog::TableInsertRowOrColDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::TableInsertRowOrColDialog) -{ - ui->setupUi(this); -} - -TableInsertRowOrColDialog::~TableInsertRowOrColDialog() -{ - delete ui; -} diff --git a/ofdEditor/model/Widget/TableInsertRowOrColDialog.h b/ofdEditor/model/Widget/TableInsertRowOrColDialog.h deleted file mode 100644 index 3c585c7..0000000 --- a/ofdEditor/model/Widget/TableInsertRowOrColDialog.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef TABLEINSERTROWORCOLDIALOG_H -#define TABLEINSERTROWORCOLDIALOG_H - -#include - -namespace Ui { -class TableInsertRowOrColDialog; -} - -class TableInsertRowOrColDialog : public QDialog -{ - Q_OBJECT - -public: - explicit TableInsertRowOrColDialog(QWidget *parent = 0); - ~TableInsertRowOrColDialog(); - -private: - Ui::TableInsertRowOrColDialog *ui; -}; - -#endif // TABLEINSERTROWORCOLDIALOG_H diff --git a/ofdEditor/model/Widget/TableInsertRowOrColDialog.ui b/ofdEditor/model/Widget/TableInsertRowOrColDialog.ui deleted file mode 100644 index 07f3972..0000000 --- a/ofdEditor/model/Widget/TableInsertRowOrColDialog.ui +++ /dev/null @@ -1,120 +0,0 @@ - - - TableInsertRowOrColDialog - - - - 0 - 0 - 400 - 300 - - - - Dialog - - - - - - 插入行或列 - - - - - - 插入行 - - - - - - - 插入列 - - - - - - - - - - Qt::PreventContextMenu - - - 0 - - - - - - - - - 30 - 20 - 120 - 80 - - - - 选择 - - - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - TableInsertRowOrColDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - TableInsertRowOrColDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/ofdEditor/model/Widget/TableSettingDialog.cpp b/ofdEditor/model/Widget/TableSettingDialog.cpp index e9b1b1b..62081e8 100644 --- a/ofdEditor/model/Widget/TableSettingDialog.cpp +++ b/ofdEditor/model/Widget/TableSettingDialog.cpp @@ -1,11 +1,237 @@ #include "TableSettingDialog.h" #include "ui_TableSettingDialog.h" +#include "Doc/DocTable.h" +#include "Doc/DocBlock.h" +#include "Tool/UnitTool.h" +#include +#include +#include + +TableSettingDialog * TableSettingDialog::m_instance = NULL; TableSettingDialog::TableSettingDialog(QWidget *parent) : QDialog(parent), ui(new Ui::TableSettingDialog) { ui->setupUi(this); + + connect(ui->balanceCol, SIGNAL(clicked(bool)), + this, SLOT(slot_selectBalanceCol())); + + connect(ui->customCol, SIGNAL(clicked(bool)), + this, SLOT(slot_selectCustomCol())); + + connect(this, SIGNAL(finished(int)), + this, SLOT(finished_slots(int))); + + connect(ui->table_color, SIGNAL(clicked(bool)), + this, SLOT(setColor())); +} + +/// +/// \brief TableSettingDialog::slot_selectBalanceCol +/// +void TableSettingDialog::slot_selectBalanceCol() +{ + this->isDefaultCellWidth = true; + + ui->setTableCellWidth->clear(); + int length = this->_table->getColumns(); + ui->setTableCellWidth->setColumnCount(length); + ui->setTableCellWidth->horizontalHeader()->setResizeMode( + QHeaderView::Stretch); + + for(int i =0; i < length; i++) + { + this->cellWidth.append( + QTextLength( + QTextLength::PercentageLength,(100.0 / length))); + } + +} + +/// +/// \brief TableSettingDialog::slot_selectCustomCol +/// +void TableSettingDialog::slot_selectCustomCol() +{ + this->isDefaultCellWidth = false; + + ui->setTableCellWidth->clear(); + int length = this->_table->getColumns(); + this->cellWidth = this->_table->getColumnWidth(); + ui->setTableCellWidth->setColumnCount(length); + ui->setTableCellWidth->horizontalHeader()->setResizeMode( + QHeaderView::Interactive); + ui->setTableCellWidth->horizontalHeader()->setResizeMode( + length-1, QHeaderView::Stretch); + + for(int i = 0; i < length; i++) + { + ui->setTableCellWidth->setHorizontalHeaderItem( + i, new QTableWidgetItem(QString::number(i+1))); + ui->setTableCellWidth->setColumnWidth( + i, ui->setTableCellWidth->viewport()->width() *this->cellWidth[i].rawValue() / 100); + } + +} + +void TableSettingDialog::setColor() +{ + QColor color = QColorDialog::getColor(this->tableColor, + NULL, + tr("Choose table border color")); + if(color.isValid()) + { + this->tableColor = color; + } +} + +/// +/// \brief TableSettingDialog::finished_slots +/// \param value +/// +void TableSettingDialog::finished_slots(int value) +{ + this->tableWidth_mm = ui->tableWidth->value(); + this->cellPadding = ui->cellPadding->value(); + this->tableX_mm = ui->table_x->value(); + this->tableY_mm = ui->table_y->value(); + + if(!this->isDefaultCellWidth) + { + // 如果是自定义列宽的话 + int length = this->_table->getColumns(); + this->cellWidth.clear(); + for(int i=0; icellWidth.append( + QTextLength( + QTextLength::PercentageLength, + 1.0 * ui->setTableCellWidth->columnWidth(i) / ui->setTableCellWidth->width() * 100.0)); + } + } + + if(value = QDialog::Accepted) + { + this->_table->setTableWidth( + UnitTool::mmToPixel(this->tableWidth_mm)); + this->_table->setCellPadding( + UnitTool::mmToPixel(this->cellPadding)); + this->_table->getBlock()->setPos( + UnitTool::mmToPixel(this->tableX_mm), + UnitTool::mmToPixel(this->tableY_mm)); + this->_table->setTableColor(this->tableColor); + this->_table->setDefaultStyle(this->isDefaultCellWidth); + + if(!this->isDefaultCellWidth) + { + this->_table->setColumnWidth(this->cellWidth); + } + + this->_table->setTableColor(this->tableColor); + } + +} + +TableSettingDialog *TableSettingDialog::getInstance() +{ + if(m_instance == NULL) + { + m_instance = new TableSettingDialog(); + } + + return m_instance; +} + +void TableSettingDialog::destroyInstance() +{ + delete m_instance; + m_instance = NULL; +} + +TableSettingDialog *TableSettingDialog::getInstance(DocTable *table) +{ + if(m_instance == NULL) + { + m_instance = new TableSettingDialog(); + } + + m_instance->init(table); + return m_instance; +} + +void TableSettingDialog::init(DocTable *table) +{ + this->_table = table; + // 表格整体宽度 + this->tableWidth_mm = UnitTool::pixelToMM( + table->getBlock()->size().rwidth()); + + // 表格整体位置 + this->tableX_mm = UnitTool::pixelToMM( + table->getBlock()->x()); + this->tableY_mm = UnitTool::pixelToMM( + table->getBlock()->y()); + + // 单元格留白 + this->cellPadding = UnitTool::pixelToMM( + table->cellPadding()); + + // 颜色 + this->tableColor = table->getTableColor(); + + // 是否均分 + this->isDefaultCellWidth = table->isDefaultWidth(); + + this->cellWidth.clear(); + this->cellWidth = table->getColumnWidth(); + + + ui->tableWidth->setValue(this->tableWidth_mm); + ui->table_x->setValue(this->tableX_mm); + ui->table_y->setValue(this->tableY_mm); + + ui->cellPadding->setValue(this->cellPadding); + this->cellWidth.clear(); + if(this->isDefaultCellWidth) + { + ui->balanceCol->setChecked(true); + ui->setTableCellWidth->clear(); + int length = table->getColumns(); + ui->setTableCellWidth->setColumnCount(length); + ui->setTableCellWidth->horizontalHeader()->setResizeMode( + QHeaderView::Stretch); + + for(int i =0; i < length; i++) + { + this->cellWidth.append( + QTextLength( + QTextLength::PercentageLength,(100.0 / length))); + } + + } + else + { + ui->customCol->setChecked(true); + ui->setTableCellWidth->clear(); + int length = table->getColumns(); + this->cellWidth = table->getColumnWidth(); + ui->setTableCellWidth->setColumnCount(length); + ui->setTableCellWidth->horizontalHeader()->setResizeMode( + QHeaderView::Interactive); + ui->setTableCellWidth->horizontalHeader()->setStretchLastSection(true); + + for(int i = 0; i < length; i++) + { + ui->setTableCellWidth->setHorizontalHeaderItem( + i, new QTableWidgetItem(QString::number(i+1))); + ui->setTableCellWidth->setColumnWidth( + i, ui->setTableCellWidth->viewport()->width() *this->cellWidth[i].rawValue() / 100); + } + + } + } TableSettingDialog::~TableSettingDialog() diff --git a/ofdEditor/model/Widget/TableSettingDialog.h b/ofdEditor/model/Widget/TableSettingDialog.h index 9327dff..a95f014 100644 --- a/ofdEditor/model/Widget/TableSettingDialog.h +++ b/ofdEditor/model/Widget/TableSettingDialog.h @@ -2,21 +2,59 @@ #define TABLESETTINGDIALOG_H #include +#include +#include "model_global.h" +#include +#include + + +class DocTable; namespace Ui { class TableSettingDialog; } -class TableSettingDialog : public QDialog +class MODELSHARED_EXPORT TableSettingDialog + : public QDialog { Q_OBJECT public: - explicit TableSettingDialog(QWidget *parent = 0); + + static TableSettingDialog* getInstance(); + static void destroyInstance(); + static TableSettingDialog* getInstance(DocTable* table); + void init(DocTable* table); + ~TableSettingDialog(); private: + explicit TableSettingDialog(QWidget *parent = 0); Ui::TableSettingDialog *ui; + static TableSettingDialog* m_instance; // instance + DocTable* _table; // 存储下临时可用的表格 + + int rows; + int columns; + + double tableWidth_mm; // 表格宽度 mm + double tableX_mm; // 表格左上角位置 + double tableY_mm; + double cellPadding; //单元格留白 + QVector cellWidth; // 单元格的宽度 + bool isDefaultCellWidth; // 是否均分列宽 + + QColor tableColor; // 表格颜色 + +private slots: + + void slot_selectBalanceCol(); // 选择等分 + void slot_selectCustomCol(); // 选择自定义调整列宽 + void setColor(); // 点击按钮修改颜色 + + + void finished_slots( int value ); // 完成后调用 + }; #endif // TABLESETTINGDIALOG_H diff --git a/ofdEditor/model/Widget/TableSettingDialog.ui b/ofdEditor/model/Widget/TableSettingDialog.ui index 101350f..976102b 100644 --- a/ofdEditor/model/Widget/TableSettingDialog.ui +++ b/ofdEditor/model/Widget/TableSettingDialog.ui @@ -6,8 +6,8 @@ 0 0 - 325 - 442 + 334 + 574 @@ -20,14 +20,14 @@ <html><head/><body><p>大小位置</p></body></html> - 2 + 0 大小位置 - + 表格线条颜色 @@ -47,7 +47,7 @@ - + 颜色 @@ -75,22 +75,19 @@ 总体大小 - - - - mm - - - - 宽: + 表格宽度: - + + + 10000.000000000000000 + + @@ -99,42 +96,6 @@ - - - - 高: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - @@ -148,8 +109,8 @@ - - + + Qt::Horizontal @@ -164,7 +125,7 @@ - + 位置 @@ -199,10 +160,18 @@ - + + + 10000.000000000000000 + + - + + + 10000990000.000000000000000 + + @@ -259,7 +228,7 @@ - + Qt::Vertical @@ -272,7 +241,7 @@ - + Qt::Vertical @@ -285,7 +254,7 @@ - + Qt::Vertical @@ -298,43 +267,161 @@ + + + + 单元格留白 + + + + + + 10000.000000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 单元格留白 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + mm + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + 列宽 - - - - 30 - 50 - 91 - 18 - - - - 均分列宽 - - - - - - 30 - 80 - 91 - 18 - - - - 自定义列宽 - - - - - - 单元格 - + + + + + 列宽模式 + + + + + + 均等分列宽 + + + true + + + + + + + 自定义列宽 + + + + + + + + + + 100 + + + 10 + + + false + + + false + + + + New Row + + + + + New Column + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index 80edce5..57a700c 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -55,7 +55,7 @@ SOURCES += model.cpp \ Core/GlobalSetting.cpp \ Widget/InsertPageDialog.cpp \ Widget/TableSettingDialog.cpp \ - Widget/TableInsertRowOrColDialog.cpp + Widget/BlockSizeAndPosSettingDialog.cpp HEADERS += model.h\ model_global.h \ @@ -90,7 +90,7 @@ HEADERS += model.h\ Widget/DocInfoDialog.h \ Widget/InsertPageDialog.h \ Widget/TableSettingDialog.h \ - Widget/TableInsertRowOrColDialog.h + Widget/BlockSizeAndPosSettingDialog.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 @@ -128,7 +128,7 @@ FORMS += \ Widget/SelectTemplateDialog.ui \ Widget/InsertPageDialog.ui \ Widget/TableSettingDialog.ui \ - Widget/TableInsertRowOrColDialog.ui + Widget/BlockSizeAndPosSettingDialog.ui RESOURCES += \ resource.qrc diff --git a/ofdEditor/start/ui/RecentFiles.cpp b/ofdEditor/start/ui/RecentFiles.cpp index 069ece0..fda7236 100644 --- a/ofdEditor/start/ui/RecentFiles.cpp +++ b/ofdEditor/start/ui/RecentFiles.cpp @@ -59,6 +59,16 @@ RecentFiles::RecentFiles(QWidget *parent) : ui->setupUi(this); // 最后一行自动适应宽度 ui->recent_table->horizontalHeader()->setStretchLastSection(true); + ui->recent_table->horizontalHeader()->setResizeMode( + 0, QHeaderView::ResizeToContents); + ui->recent_table->horizontalHeader()->setResizeMode( + 1, QHeaderView::ResizeToContents); + ui->recent_table->horizontalHeader()->setResizeMode( + 2, QHeaderView::ResizeToContents); + ui->recent_table->horizontalHeader()->setResizeMode( + 3, QHeaderView::ResizeToContents); + ui->recent_table->horizontalHeader()->setResizeMode( + 4, QHeaderView::Stretch); // 设置每次可以选取一行 ui->recent_table->setSelectionBehavior(QAbstractItemView::SelectRows); // 设置只可以单选 -- Gitee From c3e6f4fe7debc42169071cf4caca4c69895874c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Tue, 29 Aug 2017 09:22:29 +0800 Subject: [PATCH 58/83] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E7=BF=BB=E8=AF=91?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Widget/BlockSizeAndPosSettingDialog.ui | 7 +- ofdEditor/model/Widget/InsertPageDialog.ui | 2 +- ofdEditor/model/Widget/TableSettingDialog.ui | 2 +- ofdEditor/model/cn_model.ts | 807 ++++++++++++------ ofdEditor/start/cn_start.ts | 333 +++++--- 5 files changed, 734 insertions(+), 417 deletions(-) diff --git a/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.ui b/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.ui index 4ba81f1..fa19128 100644 --- a/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.ui +++ b/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.ui @@ -1,7 +1,5 @@ + - - - BlockSizeAndPosSettingDialog @@ -13,7 +11,7 @@ - Dialog + 调整块的大小尺寸 @@ -32,7 +30,6 @@ - diff --git a/ofdEditor/model/Widget/InsertPageDialog.ui b/ofdEditor/model/Widget/InsertPageDialog.ui index 2c8b04f..8070138 100644 --- a/ofdEditor/model/Widget/InsertPageDialog.ui +++ b/ofdEditor/model/Widget/InsertPageDialog.ui @@ -11,7 +11,7 @@ - Dialog + 插入页 diff --git a/ofdEditor/model/Widget/TableSettingDialog.ui b/ofdEditor/model/Widget/TableSettingDialog.ui index 976102b..eee8205 100644 --- a/ofdEditor/model/Widget/TableSettingDialog.ui +++ b/ofdEditor/model/Widget/TableSettingDialog.ui @@ -11,7 +11,7 @@ - Dialog + 表格设置 diff --git a/ofdEditor/model/cn_model.ts b/ofdEditor/model/cn_model.ts index cf06f91..2f8c1e7 100644 --- a/ofdEditor/model/cn_model.ts +++ b/ofdEditor/model/cn_model.ts @@ -1,35 +1,85 @@ + + BlockSizeAndPosSettingDialog + + + 调整块的大小尺寸 + + + + + DocBlock + + + Foreground + 前景层 + + + + Body + 正文层 + + + + Background + 背景层 + + + + Delete + 移除 + + + + size and position + 大小与位置 + + + + Layer + + + DocImageBlock - + Change Image 修改图片 - Set Image Properties - 设置图片属性 + 设置图片属性 - Remove Image. - 移除图片。 + 移除图片。 + + + + + DocImageBlock + 图片块 + + + + Property + 属性 - + Open File 打开文件 - + OFD Editor OFD Editor - + Cannot open file %1. 无法打开文件 %1. @@ -46,52 +96,52 @@ 文档信息 - + 说明 - + 文件: - + 文档ID: - + 更改 - + 标题: - + 作者: - + 主题: - + 摘要: - + 关键字: - + 文档类型: @@ -101,27 +151,27 @@ - + 创建日期: - + 高级 - + 最近修改时间: - + 创建应用程序: - + 应用程序版本: @@ -129,70 +179,207 @@ DocPage - + + Main + 主菜单 + + + + Insert + 插入 + + + + TextBlock + 文本块 + + + + ImageBlock + 图片块 + + + + Table + 表格 + + + + Page + + + + + Setting + 设置 + + + + Before + 在当前页之前 + + + + After + 在当前页之后 + + + + Delete This Page + 删除页面 + + + + Page Setting + 页面设置 + + + Open File 打开文件 - + OFD Editor - + Cannot open file %1. + + DocTable + + + + DocTable + 表格 + + + + insert Col After + 在之后插入列 + + + + insert Col Before + 在之前插入列 + + + + insert row after + 在之后插入行 + + + + insert row before + 在之前插入行 + + + + Merge Cells + 合并单元格 + + + + Split Cells + 拆分单元格 + + + + delete column + 移除当前列 + + + + delete row + 移除当前行 + + + + table setting + 表格设置 + + + + Insert Row or Col + 插入行或列 + + DocTextBlock - + Choose a Color 选择颜色 - Set the font - 设置字体 + 设置字体 + + + + + DocTextBlock + 文本块 + + + + Cut + 剪切 + + + + Copy + 复制 - + + Paste + 粘贴 + + + + Select All + 全选 + + + Bold 加粗 - + Italic 斜体 - + Underline 下划线 - + Color 颜色 - Font - 字体 + 字体 - + Paragraph 段落 - Remove - 移除 + 移除 - + FontDialogTest 字体 @@ -205,42 +392,42 @@ 查找或替换 - + Find: 查找: - + Replace With: 替换: - + Find Previous 往前查找 - + Find Next 往后查找 - + Replace 替换 - + Replace All 替换全部 - + Found in: 找到: - + places. 处。 @@ -257,33 +444,33 @@ 字体 - - + + 字体 - + 粗体 - + 字号 - + 下划线 - + 字体效果预览 - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -293,221 +480,229 @@ p, li { white-space: pre-wrap; } - + 斜体 - + 初号 - + 小初 - + 一号 - + 小一 - + 二号 - + 小二 - + 三号 - + 小三 - + 四号 - + 小四 - + 五号 - + 小五 - + 六号 - + 小六 - + 七号 - + 八号 - + 5 - + 5.5 - + 6.5 - + 7.5 - + 8 - + 9 - + 10 - + 10.5 - + 11 - + 12 - + 14 - + 16 - + 18 - + 20 - + 22 - + 24 - + 26 - + 28 - + 36 - + 48 - + 72 - + 高级 - + 字间距 - + 拉伸字体 - + 字体粗细 - + 等宽字体 + + GlobalSetting + + + Test + 默认字体 + + ImagePropertiesDialog @@ -519,82 +714,96 @@ p, li { white-space: pre-wrap; } 图片设置窗口 图片设置 + + + + + + mm + mm + - + 图片尺寸 - - - 高度 + + + 200 ,200 - - 宽度 + + 高度 - - - - - 像素 + + 宽度 - - + + %原尺寸 - + 锁定纵横比 - + 原始尺寸: - - - 122 ,122 - - - + 图片位置 - + 水平 - + 垂直 - - + + %页面 - + Width: - + + + mm + mm + + + , Height: + + InsertPageDialog + + + 插入页 + + + InsertTableDialog @@ -603,60 +812,46 @@ p, li { white-space: pre-wrap; } - + 表格 - + 行数列数 - + 行数: - + 列数: - + 总体尺寸 - - + 宽: - - - - + + mm - - + 高: - - - 高级 - - - - - 单元格大小 - - PageDialog @@ -665,200 +860,195 @@ p, li { white-space: pre-wrap; } 页面设置 - + 当前页面 - + + + + - - - - - - - - - - + + + + + + + mm - + 所有页 - - - - + + + + - - - - + + + + - - + + 垂直 - - + + 工作区域尺寸 - + 特定页数 - + 应用于 - - + + 设置工作区域 - - + + 水平 - - + + 页面尺寸 - - + + 工作区域位置 - + 页面设置 - + 当前页 - + 页面范围 - + - + - + - + 页码 - - + + 选择尺寸 - - - - + + + + A4 - - - - + + + + A3 - - - - + + + + A5 - - - - + + + + Letter - - - - + + + + 16K - - - - + + + + 32K - - - + + + Customized - + 默认页面 - - - 默认页面设置 - - ParagraphFormatDialog @@ -872,123 +1062,92 @@ p, li { white-space: pre-wrap; } - + 对齐方式 - + 水平 - + 左对齐 - + 右对齐 - - + 居中 - + 两端对齐 - - 竖直 - - - - - 居上 - - - - - 居下 - - - - - 文字方向 - - - - - 左到右 - - - - - 右到左 - - - - + 缩进 - + 整体缩进 - + 首行缩进 - + 间距 - + 段前 - + 段后 - + 行距策略 - + 单倍行距 - + 多倍行距 - + 固定值 - + 最小值 - + @@ -1016,4 +1175,106 @@ p, li { white-space: pre-wrap; } + + TableSettingDialog + + + 表格设置 + + + + + <html><head/><body><p>大小位置</p></body></html> + + + + + 大小位置 + + + + + 表格线条颜色 + + + + + 颜色 + + + + + 总体大小 + + + + + 表格宽度: + + + + + + + + mm + + + + + 位置 + + + + + 距左方 + + + + + 距上方 + + + + + + 单元格留白 + + + + + 列宽 + + + + + 列宽模式 + + + + + 均等分列宽 + + + + + 自定义列宽 + + + + + New Row + + + + + New Column + + + + + Choose table border color + 选择表格线条颜色 + + diff --git a/ofdEditor/start/cn_start.ts b/ofdEditor/start/cn_start.ts index 9f12fb4..2ae1a3a 100644 --- a/ofdEditor/start/cn_start.ts +++ b/ofdEditor/start/cn_start.ts @@ -4,532 +4,538 @@ PassageMainWindow - + + + Welcome! + 欢迎页! + + + OFD Editor OFD版式文档编辑器 - + New File 新建文档 - + Create a new ofd file 创建要给ofd文档 - + Template 模板 - + Use a template to create a new document 使用模板新建一个文档 - + Open File 打开 - + Open an existing ofd file 打开一个存在的ofd文件 - + Save 保存 - + Save file 保存文件 - - + + Save as 另存为 - + Print 打印 - + Print your document 打印你的文档 - + Attribute 文档属性 - + Show you the attribute of the actived passage 查看你当前编辑的文档的属性 - + Setting 设置 - + Set the software's preference 设置软件的首选项 - + EditMode 编辑模式 - - + + change current state to edit mode 修改当前状态为编辑模式 - + ViewMode 观察模式 - + ZoomIn 放大 - + ZoomOut 缩小 - + Undo 撤销 - + Undo your last action 插销你的上一步操作 - + Redo 重做 - + Redo the action you undo 重做你刚撤销的操作 - + Copy 复制 - + Copy the content you selected 复制你选择的内容 - + Cut 剪切 - + Cut the content you selected 剪切你选择的内容 - + Paste 粘贴 - + Paste your pasteboard content 粘贴你剪贴板里的内容 - + Find/Replace 查找/替换 - + Find specific text or replace them 查找给定文本,并可以替换 - + Insert New Page 增加新页 - + Insert a new Page into document 插入一个新页面到文档 - + Insert TextBlock 插入文本框 - + Insert a new TextBlock 插入一个新的文本框 - + Insert Image 插入图片 - + Insert a image 插入一个图片 - + Insert Table 插入表格 - + Insert a table 插入一个表格 - + Page Format 页面格式 - + Set the page format 设置页面格式 - + Text Format 字体格式 - + Set the selected texts' format 设置选择的文本的字体格式 - + Paragraph Format 段落 - + Set this paragarph format 设置选择的段落的格式 - + Image Format 图片格式 - + Set the Selected image's format 设置选择的图片的格式 - + Table Format 表格格式 - + Set the selected table's format 设置选择的表格的格式 - + about Qt 关于Qt - + About App 关于本应用 - + About this Application 关于本应用 - + Help 帮助 - + Show the help Window 显示帮助页面 - + Files 文件 - - + + Edit 编辑 - - + + Format 格式 - - + + Insert 插入 - + About 关于 - + 72 - + 48 - + 36 - + 28 - + 26 - + 24 - + 22 - + 20 - + 18 - + 16 - + 14 - + 12 - + 11 - + 10.5 - + 10 - + 9 - + 8 - + 7.5 - + 6.5 - + 5.5 - + 5 - + Size 8 八号 - + Size 7 七号 - + Size 6 Minor 小六 - + Size 6 六号 - + Size 5 Minor 小五 - + Size 5 五号 - + Size 4 Minor 小四 - + Size 4 四号 - + Size 3 Minor 小三 - + Size 3 三号 - + Size 2 Minor 小二 - + Size 2 二号 - + Size 1 Minor 小一 - + Size 1 一号 - + Prime Minor 小初 - + Prime 初号 - + JiMi 1Nian 机密★1年 - + Te Ji 特急 - + XXXXXWenJian ×××××文件 - + XXX[2012]10Hao ×××﹝2012﹞10号 - + XXXXXGuanYuXXXXXXDeTongZhi ×××关于××××的通知 - + XXXXXXXX: ×××××: - + OOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. OOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. OOOOXXXXXXXXXXXXXXXXXXXXXX. @@ -540,38 +546,38 @@ OOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ××××××××××××。×××××××××××××××××××××××××××××××××××××××××× - + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. OOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ××××××××××××××××××××××××××××。 ×××××××××××××××××××××××××××××××××××××××××××。 - + XXXXXXXXXXXX ×××××××××××× - + 2012Nian7Yue1Ri 2012年7月1日 - + (XXXXXX) (××××××) - + ChaoSong:XXXXXXX,XXXXX,XXXXXX 抄送:×××××,××××××,××××××× - + XXXXXXXX ×××××××××× - + 2012Nian7Yue1RiYinFa 2012年7月1日印发 @@ -584,104 +590,157 @@ OOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. 七号 - + Bold 加粗 - + Set selected text Bold or not bold 将选择的文本加粗 - + Italic 斜体 - + Set the selected text Italic 设置选择的文本斜体 - + Underline 下划线 - + Set the selected text underline 设置选择的文本下划线 - + middle 居中 - + Set the selected paragraph align middle 设置选择的段落格式为居中 - + Left 左对齐 - + Set the selected paragraph align by left 设置选择的段落对齐样式为左对齐 - + Right 右对齐 - + Set the selected paragraph align by right 设置选中的段落的对齐样式为右对齐 - + jutify 两端对齐 - + Set the selected paragraph align by left and right 设置选择的文本的对齐样式为两端对齐 - + File 文件 - + TextBlock 文本框 - + JSON files(*.ofd) OFD文件(*ofd) - + Choose an ofd document file! 选择一个OFD文件! - + Save the passage content as a ofd file 保存文件为一个ofd文件 - + OFD files(*.ofd) + + RecentFiles + + + Form + + + + + 最近打开的文档 + + + + + New Row + + + + + 文件名 + + + + + 作者 + + + + + 最近打开时间 + + + + + 最近编辑时间 + + + + + 文件路径 + + + + + 清空最近文件记录 + + + + + 新建文档 + + + -- Gitee From 6ea6008edcdd80a0c1f1eb30412f5e5dc034dab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Tue, 29 Aug 2017 11:23:18 +0800 Subject: [PATCH 59/83] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=A4=9A=E5=AA=92=E4=BD=93-=E5=9B=BE=E7=89=87=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocImageBlock.h | 1 + ofdEditor/ofd/DataTypes/document/Res.h | 2 + .../ofd/DataTypes/image/CT_MultiMedia.cpp | 6 + ofdEditor/ofd/DataTypes/image/CT_MultiMedia.h | 22 ++ ofdEditor/ofd/ofd.pro | 2 + ofdEditor/ofd/ofd_parser.cpp | 197 +++++++++++++----- 6 files changed, 179 insertions(+), 51 deletions(-) create mode 100644 ofdEditor/ofd/DataTypes/image/CT_MultiMedia.cpp create mode 100644 ofdEditor/ofd/DataTypes/image/CT_MultiMedia.h diff --git a/ofdEditor/model/Doc/DocImageBlock.h b/ofdEditor/model/Doc/DocImageBlock.h index 835aabe..cc36a98 100644 --- a/ofdEditor/model/Doc/DocImageBlock.h +++ b/ofdEditor/model/Doc/DocImageBlock.h @@ -57,6 +57,7 @@ private: QAction * set_image_properties; //更改图片的位置和尺寸 bool width_height_ratio_locked; double width_height_ratio; + QString temp_store; void initMenu(); // 初始化右键菜单 diff --git a/ofdEditor/ofd/DataTypes/document/Res.h b/ofdEditor/ofd/DataTypes/document/Res.h index 557d54f..01058d8 100644 --- a/ofdEditor/ofd/DataTypes/document/Res.h +++ b/ofdEditor/ofd/DataTypes/document/Res.h @@ -5,6 +5,7 @@ #include "../Color/CT_ColorSpace.h" #include "../image/CT_DrawParam.h" #include "../../ofd_global.h" // 生成库文件需要 +#include "DataTypes/image/CT_MultiMedia.h" class OFDSHARED_EXPORT Res { //属性 @@ -13,6 +14,7 @@ class OFDSHARED_EXPORT Res { QVector * fonts; QVector * colorspaces; QVector * draw_params; + QVector multMedias; //Other resource collections to be implemented public: diff --git a/ofdEditor/ofd/DataTypes/image/CT_MultiMedia.cpp b/ofdEditor/ofd/DataTypes/image/CT_MultiMedia.cpp new file mode 100644 index 0000000..40533d8 --- /dev/null +++ b/ofdEditor/ofd/DataTypes/image/CT_MultiMedia.cpp @@ -0,0 +1,6 @@ +#include "CT_MultiMedia.h" + +CT_MultiMedia::CT_MultiMedia() +{ + +} diff --git a/ofdEditor/ofd/DataTypes/image/CT_MultiMedia.h b/ofdEditor/ofd/DataTypes/image/CT_MultiMedia.h new file mode 100644 index 0000000..71bc3c4 --- /dev/null +++ b/ofdEditor/ofd/DataTypes/image/CT_MultiMedia.h @@ -0,0 +1,22 @@ +#ifndef CT_MULTIMEDIA_H +#define CT_MULTIMEDIA_H + +#include "ofd_global.h" +#include "DataTypes/basic_datatype.h" +#include + + +class OFDSHARED_EXPORT CT_MultiMedia + :public CT_Base +{ +public: + friend class OFDParser; + CT_MultiMedia(); + + // 属性 + QString Type; // 多媒体资源主类型 + QString Format; // 多媒体资源格式 + QString MediaFile; // 多媒体文件路径 +}; + +#endif // CT_MULTIMEDIA_H diff --git a/ofdEditor/ofd/ofd.pro b/ofdEditor/ofd/ofd.pro index a925386..a918cce 100644 --- a/ofdEditor/ofd/ofd.pro +++ b/ofdEditor/ofd/ofd.pro @@ -32,6 +32,7 @@ SOURCES += \ Loaders/ZipTool.cpp \ ofdexceptions.cpp \ DataTypes/page/CT_PageBlock.cpp \ + DataTypes/image/CT_MultiMedia.cpp HEADERS +=\ DataTypes/basic_datatype.h \ @@ -63,6 +64,7 @@ HEADERS +=\ DataTypes/document/CustomTags.h \ DataTypes/document/Res.h \ DataTypes/text/CT_Font.h \ + DataTypes/image/CT_MultiMedia.h DESTDIR = ../bin # 生成文件在这 diff --git a/ofdEditor/ofd/ofd_parser.cpp b/ofdEditor/ofd/ofd_parser.cpp index 5f1f58a..e41328a 100644 --- a/ofdEditor/ofd/ofd_parser.cpp +++ b/ofdEditor/ofd/ofd_parser.cpp @@ -1,7 +1,5 @@ #include "ofd_parser.h" #include - - #include "DataTypes/document/OFD.h" #include "DataTypes/document/DocBody.h" #include "DataTypes/document/CT_DocInfo.h" @@ -12,6 +10,7 @@ #include "DataTypes/text/CT_Text.h" #include "DataTypes/image/CT_Path.h" #include "DataTypes/image/CT_Image.h" +#include "DataTypes/image/CT_MultiMedia.h" OFDParser::OFDParser(QString _path) : current_path("OFD", _path) { document = new QDomDocument(); @@ -21,7 +20,7 @@ OFDParser::OFDParser(QString _path) : current_path("OFD", _path) { void OFDParser::openFile() { QFile ofd_file(current_path.getPath()); if (!ofd_file.open(QFile::ReadOnly | QFile::Text)) { //检查文件是否存在&正常打开 - throw ParsingFileException("无法打开XML文件: " + current_path.getPath()); + qDebug() << "无法打开XML文件: " + current_path.getPath(); } if (document->setContent(&ofd_file, //解析OFD文档并将树状内容存在document文件中 false, @@ -30,7 +29,7 @@ void OFDParser::openFile() { &error_column)) { ofd_file.close(); } else { - throw ParsingFileException("XML文件格式有错误: " + current_path.getPath()); + qDebug() << "XML文件格式有错误: " + current_path.getPath(); } } @@ -43,11 +42,13 @@ OFD * OFDParser::readOFD() { if (new_ofd.hasAttribute("DocType")) ofd_data->doc_type = new_ofd.attribute("DocType"); else - throw ParsingFormatException("OFD类型的数据中中缺少必要的DocType属性\n位于" + current_path.getRelativePath()); + qDebug() << "OFD类型的数据中中缺少必要的DocType属性\n位于" + << current_path.getRelativePath(); if (new_ofd.hasAttribute("Version")) ofd_data->version = new_ofd.attribute("Version"); else - throw ParsingFormatException("OFD类型的数据中中缺少必要的Version属性\n位于" + current_path.getRelativePath()); + qDebug() << "OFD类型的数据中中缺少必要的Version属性\n位于" + << current_path.getRelativePath(); ofd_data->root_path = current_path; QDomElement new_docbody = new_ofd.firstChildElement("ofd:DocBody"); @@ -91,20 +92,23 @@ OFD * OFDParser::readOFD() { } } } else { - throw ParsingFormatException("DocBody类型的数据中中缺少必要的DocInfo成员\n位于" + current_path.getRelativePath()); + qDebug() << "DocBody类型的数据中中缺少必要的DocInfo成员\n位于" + << current_path.getRelativePath(); } QDomElement new_docroot = new_docbody.firstChildElement("ofd:DocRoot"); if (!new_docroot.isNull()) { ST_Loc p("Document", new_docroot.text(), current_path); docbody_data->doc_root = p; } else { - throw ParsingFormatException("DocBody类型的数据中中缺少必要的DocInfo成员\n位于" + current_path.getRelativePath()); + qDebug() << "DocBody类型的数据中中缺少必要的DocInfo成员\n位于" + << current_path.getRelativePath(); } new_docbody = new_ofd.nextSiblingElement("ofd:DocBody"); } } else { - throw ParsingFormatException("OFD类型的数据中中缺少必要的DocBody成员\n位于" + current_path.getRelativePath()); + qDebug() << "OFD类型的数据中中缺少必要的DocBody成员\n位于" + << current_path.getRelativePath(); } if (ofd_data) { for (int i = 0; i < ofd_data->docbodys->size(); i++) { @@ -132,7 +136,7 @@ Document * OFDParser::readDocument() { if (!(t = new_commondata.firstChildElement("ofd:MaxUnitID")).isNull()) { commondata_data->max_unit_id = t.text().toInt(); } else { - throw ParsingFormatException("缺少MaxID"); + qDebug("缺少MaxID"); //Error } @@ -141,7 +145,7 @@ Document * OFDParser::readDocument() { commondata_data->page_area = pagearea_data; readPageArea(pagearea_data, t); } else { - throw ParsingFormatException("PageArea"); + qDebug("PageArea"); } qDebug() << "Checkpoint 1.1.1..."; t = new_commondata.firstChildElement("ofd:PublicRes"); @@ -157,7 +161,7 @@ Document * OFDParser::readDocument() { } } else { - throw ParsingFormatException("Document类型的数据中中缺少必要的CommonData成员\n位于Document.xml"); + qDebug("Document类型的数据中中缺少必要的CommonData成员\n位于Document.xml"); } qDebug() << "Checkpoint 1.2..."; QDomElement new_pages = new_document.firstChildElement("ofd:Pages"); @@ -176,7 +180,7 @@ Document * OFDParser::readDocument() { new_page = new_page.nextSiblingElement("ofd:Page"); } } else { - throw ParsingFormatException("Document类型的数据中中缺少必要的Pages成员\n位于Document.xml"); + qDebug("Document类型的数据中中缺少必要的Pages成员\n位于Document.xml"); } document_data->pages = pages_data; qDebug() << "Checkpoint 1.3..."; @@ -202,7 +206,8 @@ Document * OFDParser::readDocument() { } } else { - throw ParsingFormatException("Document.xml文档中缺少必要的Document标签\n位于" + current_path.getRelativePath()); + qDebug() << "Document.xml文档中缺少必要的Document标签\n位于" + << current_path.getRelativePath(); } //访问资源 for (int i = 0; i < document_data->common_data->public_res->size(); i++) { @@ -258,7 +263,8 @@ void OFDParser::readPage(Page * page_data) { ST_ID i(new_layer.attribute("ID").toInt()); layer_data->setID(i, id_table); } else { - throw ParsingFormatException("CT_Layer类型数据中缺少必要的ID属性\n位于" + current_path.getRelativePath()); + qDebug() << "CT_Layer类型数据中缺少必要的ID属性\n位于" + << current_path.getRelativePath(); } if (new_layer.hasAttribute("DrawParam")) { ST_RefID ri(new_layer.attribute("DrawParam").toInt()); @@ -266,7 +272,8 @@ void OFDParser::readPage(Page * page_data) { layer_data->draw_param = ri; else { qDebug() << "Checkpoint ID 1..."; - throw ParsingIDException("Layer类型数据的DrawParam属性引用了未注册的ID 位于" + current_path.getRelativePath()); + qDebug() << "Layer类型数据的DrawParam属性引用了未注册的ID 位于" + << current_path.getRelativePath(); } } // qDebug() << "Checkpoint 2.2"; @@ -287,23 +294,29 @@ void OFDParser::readPage(Page * page_data) { text_data->font = ri; else { qDebug() << "Checkpoint ID 2..."; - throw ParsingIDException("CT_Text类型数据的Font属性引用了未注册的ID:" + QString::number(ri.getRefID()) + " 位于" + current_path.getRelativePath()); + qDebug() << "CT_Text类型数据的Font属性引用了未注册的ID:" + << QString::number(ri.getRefID()) + << " 位于" + << current_path.getRelativePath(); } } else { - throw ParsingFormatException("CT_Text类型数据中缺少必要的Font属性\n位于" + current_path.getRelativePath()); + qDebug() << "CT_Text类型数据中缺少必要的Font属性\n位于" + << current_path.getRelativePath(); } if (t.hasAttribute("Size")) { text_data->size = t.attribute("Size").toDouble(); text_data->size_used = true; } else { - throw ParsingFormatException("CT_Text类型数据中缺少必要的Size属性\n位于" + current_path.getRelativePath()); + qDebug() << "CT_Text类型数据中缺少必要的Size属性\n位于" + << current_path.getRelativePath(); } // qDebug() << "Checkpoint 2.3"; //many optional attributes to be implemented QDomElement t2 = t.firstChildElement("ofd:TextCode"); if (t2.isNull()) { - throw ParsingFormatException("CT_Text类型数据中缺少必要的TextCode成员\n位于" + current_path.getRelativePath()); + qDebug() << "CT_Text类型数据中缺少必要的TextCode成员\n位于" + << current_path.getRelativePath(); } // qDebug() << "Checkpoint 2.3.1"; while(!t2.isNull()) { @@ -319,7 +332,8 @@ void OFDParser::readPage(Page * page_data) { if (!is_first_textcode_x && !is_first_textcode_y) text_code_data->x = last_x; else { - throw ParsingFormatException("TextCode类型数据中缺少第一个X值\n位于" + current_path.getRelativePath()); + qDebug() << "TextCode类型数据中缺少第一个X值\n位于" + << current_path.getRelativePath(); } } // qDebug() << "Checkpoint 2.3.2"; @@ -331,7 +345,8 @@ void OFDParser::readPage(Page * page_data) { if (!is_first_textcode_x && !is_first_textcode_y) text_code_data->y = last_y; else { - throw ParsingFormatException("TextCode类型数据中缺少第一个Y值\n位于" + current_path.getRelativePath()); + qDebug() << "TextCode类型数据中缺少第一个Y值\n位于" + << current_path.getRelativePath(); } } if (t2.hasAttribute("DeltaX")) { @@ -367,13 +382,17 @@ void OFDParser::readPage(Page * page_data) { else if (t.attribute("Rule") == "Even-Odd") path_data->rule = "Even-Odd"; else { - throw ParsingFormatException("CT_Path类型数据中的Rule属性值为非法值\n位于" + current_path.getRelativePath() + " 值为" + t.attribute("Rule")); + qDebug() << "CT_Path类型数据中的Rule属性值为非法值\n位于" + << current_path.getRelativePath() + << " 值为" + << t.attribute("Rule"); } } if (!t.firstChildElement("ofd:AbbreviatedData").isNull()) { path_data->abbreviated_data = t.firstChildElement("ofd:AbbreviatedData").text(); } else { - throw ParsingFormatException("CT_Path类型数据中缺少必要的AbbreviatedData成员\n位于" + current_path.getRelativePath()); + qDebug() << "CT_Path类型数据中缺少必要的AbbreviatedData成员\n位于" + << current_path.getRelativePath(); } t = t.nextSiblingElement("ofd:PathObject"); } @@ -391,10 +410,12 @@ void OFDParser::readPage(Page * page_data) { else { qDebug() << ri.getRefID(); qDebug() << "Checkpoint ID 3..."; - //throw ParsingIDException("CT_Image类型数据的ResourceID属性引用了未注册的ID 位于" + current_path.getRelativePath()); + //qDebug("CT_Image类型数据的ResourceID属性引用了未注册的ID 位于" + current_path.getRelativePath()); } +// image_data->resource_id = ri; } else { - throw ParsingFormatException("CT_Image类型数据中缺少必要的ResourceID属性\n位于" + current_path.getRelativePath()); + qDebug() << "CT_Image类型数据中缺少必要的ResourceID属性\n位于" + << current_path.getRelativePath(); } if (t.hasAttribute("Substitution")) { ST_RefID ri(t.attribute("Substitution").toInt()); @@ -402,7 +423,8 @@ void OFDParser::readPage(Page * page_data) { image_data->substitution = ri; else { qDebug() << "Checkpoint ID 4..."; - throw ParsingIDException("CT_Image类型数据的Substitution属性引用了未注册的ID 位于" + current_path.getRelativePath()); + qDebug() << "CT_Image类型数据的Substitution属性引用了未注册的ID 位于" + << current_path.getRelativePath(); } } t = t.nextSiblingElement("ofd:ImageObject"); @@ -413,14 +435,15 @@ void OFDParser::readPage(Page * page_data) { } } } else { - throw ParsingFormatException("Content.xml文档中缺少必要的Page标签\n位于" + current_path.getRelativePath()); + qDebug() << "Content.xml文档中缺少必要的Page标签\n位于" + << current_path.getRelativePath(); } // qDebug() << "Checkpoint 3"; } void OFDParser::readPageArea(CT_PageArea * data, QDomElement & root_node) { QDomElement t; - qDebug() << "Checkpoint PA 1..."; +// qDebug() << "Checkpoint PA 1..."; if (!(t = root_node.firstChildElement("ofd:PhysicalBox")).isNull()) { QStringList values = t.text().split(" "); //qDebug() << values[0] << values[1] << values[2] << endl; @@ -428,27 +451,31 @@ void OFDParser::readPageArea(CT_PageArea * data, QDomElement & root_node) { data->physical_box = ST_Box(values[0].toDouble(), values[1].toDouble(), values[2].toDouble(), values[3].toDouble()); } else { - throw ParsingFormatException("CT_PageArea类型数据的PhysicalBox成员的值的数目错误\n位于" + current_path.getRelativePath()); + qDebug() << "CT_PageArea类型数据的PhysicalBox成员的值的数目错误\n位于" + << current_path.getRelativePath(); } } else { - throw ParsingFormatException("CT_PageArea类型的数据中中缺少必要的PhysicalBox成员\n位于" + current_path.getRelativePath()); + qDebug() << "CT_PageArea类型的数据中中缺少必要的PhysicalBox成员\n位于" + << current_path.getRelativePath(); } - qDebug() << "Checkpoint PA 2..."; +// qDebug() << "Checkpoint PA 2..."; if (!(t = root_node.firstChildElement("ofd:ApplicationBox")).isNull()) { QStringList values = t.text().split(" "); if (values.size() == 4) data->application_box = ST_Box(values[0].toDouble(), values[1].toDouble(), values[2].toDouble(), values[3].toDouble()); else { - throw ParsingFormatException("CT_PageArea类型数据的ApplicationBox成员的值的数目错误\n位于" + current_path.getRelativePath()); + qDebug() << "CT_PageArea类型数据的ApplicationBox成员的值的数目错误\n位于" + << current_path.getRelativePath(); } } - qDebug() << "Checkpoint PA 3..."; +// qDebug() << "Checkpoint PA 3..."; if (!(t = root_node.firstChildElement("ofd:ContentBox")).isNull()) { QStringList values = t.text().split(" "); if (values.size() == 4) data->content_box = ST_Box(values[0].toDouble(), values[1].toDouble(), values[2].toDouble(), values[3].toDouble()); else - throw ParsingFormatException("CT_PageArea类型数据的ContentBox成员的值的数目错误\n位于" + current_path.getRelativePath()); + qDebug() << "CT_PageArea类型数据的ContentBox成员的值的数目错误\n位于" + << current_path.getRelativePath(); } if (!(t = root_node.firstChildElement("ofd:BleedBox")).isNull()) { @@ -456,7 +483,8 @@ void OFDParser::readPageArea(CT_PageArea * data, QDomElement & root_node) { if (values.size() == 4) data->bleed_box = ST_Box(values[0].toDouble(), values[1].toDouble(), values[2].toDouble(), values[3].toDouble()); else { - throw ParsingFormatException("CT_PageArea类型数据的BleedBox成员的值的数目错误\n位于" + current_path.getRelativePath()); + qDebug() << "CT_PageArea类型数据的BleedBox成员的值的数目错误\n位于" + << current_path.getRelativePath(); } } } @@ -468,7 +496,8 @@ void OFDParser::readGraphicUnit(CT_GraphicUnit *data, QDomElement &root_node) { data->setID(i, id_table); } else { - throw ParsingFormatException("CT_GraphicUnit类型数据中缺少必要的ID属性\n位于" + current_path.getRelativePath()); + qDebug() << "CT_GraphicUnit类型数据中缺少必要的ID属性\n位于" + << current_path.getRelativePath(); } if (root_node.hasAttribute("Boundary")) { @@ -477,10 +506,12 @@ void OFDParser::readGraphicUnit(CT_GraphicUnit *data, QDomElement &root_node) { data->boundary = ST_Box(values[0].toDouble(), values[1].toDouble(), values[2].toDouble(), values[3].toDouble()); } else { - throw ParsingFormatException("CT_GraphicUnit类型数据的Boundary成员的值的数目错误\n位于" + current_path.getRelativePath()); + qDebug() << "CT_GraphicUnit类型数据的Boundary成员的值的数目错误\n位于" + << current_path.getRelativePath(); } } else { - throw ParsingFormatException("CT_GraphicUnit类型数据中缺少必要的ID属性\n位于" + current_path.getRelativePath()); + qDebug() << "CT_GraphicUnit类型数据中缺少必要的ID属性\n位于" + << current_path.getRelativePath(); } //读取成员 @@ -497,6 +528,7 @@ void OFDParser::readGraphicUnit(CT_GraphicUnit *data, QDomElement &root_node) { } void OFDParser::readResource(Res * res_data) { + qDebug() << "read res-----------"; openFile(); QDomElement new_res = document->firstChildElement("ofd:Res"); if (!new_res.isNull()) { @@ -505,9 +537,11 @@ void OFDParser::readResource(Res * res_data) { ST_Loc new_baseloc("BaseLoc", new_res.attribute("BaseLoc"), current_path); res_data->base_loc = new_baseloc; } else { - throw ParsingFormatException("Res类型数据中缺少必要的BaseLoc属性\n位于" + current_path.getRelativePath()); + qDebug() << "Res类型数据中缺少必要的BaseLoc属性\n位于" + << current_path.getRelativePath(); } - //读取成员 + + //读取成员--font QDomElement t; if (!(t = new_res.firstChildElement("ofd:Fonts")).isNull()) { QDomElement t2 = t.firstChildElement("ofd:Font"); @@ -519,6 +553,7 @@ void OFDParser::readResource(Res * res_data) { } } + // colorSpaces if (!(t = new_res.firstChildElement("ofd:ColorSpaces")).isNull()) { QDomElement t2 = t.firstChildElement("ofd:ColorSpace"); while (!t2.isNull()) { @@ -529,6 +564,7 @@ void OFDParser::readResource(Res * res_data) { } } + // DrawParams if (!(t = new_res.firstChildElement("ofd:DrawParams")).isNull()) { QDomElement t2 = t.firstChildElement("ofd:DrawParam"); while (!t2.isNull()) { @@ -538,10 +574,58 @@ void OFDParser::readResource(Res * res_data) { t2 = t2.nextSiblingElement("ofd:DrawParam"); } } + + // MultMedia + if (!(t = new_res.firstChildElement("ofd:MultiMedias")).isNull()) { + qDebug() << "multmedia flag read"; + + QDomElement t2 = t.firstChildElement("ofd:MultiMedia"); + while (!t2.isNull()) { + + CT_MultiMedia *multimedia = new CT_MultiMedia(); + + // 属性 + if(t2.hasAttribute("ID")) + { + ST_ID i(t2.attribute("ID").toInt()); + multimedia->setID(i, id_table); + } + else + { + qDebug() << "multimedia don't has ID attribute"; + continue; + } + if(t2.hasAttribute("Type")) + { + multimedia->Type = t2.attribute("Type"); + continue; + } + else + { + qDebug() << "Multimedia has no Type attribute"; + continue; + } + + // 子节点 + QDomElement mediaFile = t2.firstChildElement("ofd:MediaFile"); + multimedia->MediaFile = mediaFile.text(); // 文件路径 + res_data->multMedias.append(multimedia); // 插入 + + qDebug() << multimedia->getID().getID() + << multimedia->Type + << multimedia->MediaFile; + + t2 = t2.nextSiblingElement("ofd:MultiMedia"); + } + } + //Other stuff to be implemented } else { - throw ParsingFormatException("Resource.xml文档中缺少必要的Res标签\n位于" + current_path.getRelativePath()); + qDebug() << "Resource.xml文档中缺少必要的Res标签\n位于" + << current_path.getRelativePath(); } + + qDebug() << "read res-----------end"; //qDebug() << "End of reading Resourse..." << endl; } @@ -555,7 +639,10 @@ void OFDParser::readColor(CT_Color *data, QDomElement & root_node) { if (id_table->contains(colorspace_data.getRefID())) data->color_space = colorspace_data; else { - throw ParsingIDException("CT_Color类型数据的ColorSpace属性引用了未注册的ID:" + QString::number(colorspace_data.getRefID()) + " 位于" + current_path.getRelativePath()); + qDebug() << "CT_Color类型数据的ColorSpace属性引用了未注册的ID:" + << QString::number(colorspace_data.getRefID()) + << " 位于" + << current_path.getRelativePath(); } } @@ -573,12 +660,14 @@ void OFDParser::readFont(CT_Font * data, QDomElement & root_node) { ST_ID i(root_node.attribute("ID").toInt()); data->setID(i, id_table); } else { - throw ParsingFormatException("CT_Font类型数据中缺少必要的ID属性\n位于" + current_path.getRelativePath()); + qDebug() << "CT_Font类型数据中缺少必要的ID属性\n位于" + << current_path.getRelativePath(); } if (root_node.hasAttribute("FontName")) { data->font_name = root_node.attribute("FontName"); } else { - throw ParsingFormatException("CT_Font类型数据中缺少必要的FontName属性\n位于" + current_path.getRelativePath()); + qDebug() << "CT_Font类型数据中缺少必要的FontName属性\n位于" + << current_path.getRelativePath(); } if (root_node.hasAttribute("FamilyName")) { data->family_name = root_node.attribute("FamilyName"); @@ -603,12 +692,14 @@ void OFDParser::readColorSpace(CT_ColorSpace * data, QDomElement & root_node) { ST_ID i(root_node.attribute("ID").toInt()); data->setID(i, id_table); } else { - throw ParsingFormatException("CT_ColorSpace类型数据中缺少必要的ID属性\n位于" + current_path.getRelativePath()); + qDebug() << "CT_ColorSpace类型数据中缺少必要的ID属性\n位于" + << current_path.getRelativePath(); } if (root_node.hasAttribute("Type")) { data->type = root_node.attribute("Type"); } else { - throw ParsingFormatException("CT_ColorSpace类型数据中缺少必要的Type属性\n位于" + current_path.getRelativePath()); + qDebug() << "CT_ColorSpace类型数据中缺少必要的Type属性\n位于" + << current_path.getRelativePath(); } if (root_node.hasAttribute("BitsPerComponent")) { data->bits_per_component = root_node.attribute("BitsPerComponent").toInt(); @@ -624,14 +715,16 @@ void OFDParser::readDrawParam(CT_DrawParam * data, QDomElement & root_node) { ST_ID i(root_node.attribute("ID").toInt()); data->setID(i, id_table); } else { - throw ParsingFormatException("CT_DrawParam类型数据中缺少必要的ID属性\n位于" + current_path.getRelativePath()); + qDebug() << "CT_DrawParam类型数据中缺少必要的ID属性\n位于" + << current_path.getRelativePath(); } if (root_node.hasAttribute("Relative")) { ST_RefID i(root_node.attribute("Relative").toInt()); if (id_table->contains(i.getRefID())) data->relative = i; else { - throw ParsingIDException("CT_DrawParam类型数据的Relative属性引用了未注册的ID 位于" + current_path.getRelativePath()); + qDebug() << "CT_DrawParam类型数据的Relative属性引用了未注册的ID 位于" + << current_path.getRelativePath(); } } @@ -643,7 +736,8 @@ void OFDParser::readDrawParam(CT_DrawParam * data, QDomElement & root_node) { if (j == "Miter" || j == "Round" || j == "Bevel") data->join = j; else { - throw ParsingFormatException("CT_DrawParam类型数据中的Join属性值为非法值\n位于" + current_path.getRelativePath()); + qDebug() << "CT_DrawParam类型数据中的Join属性值为非法值\n位于" + << current_path.getRelativePath(); } } if (root_node.hasAttribute("Cap")) { @@ -651,7 +745,8 @@ void OFDParser::readDrawParam(CT_DrawParam * data, QDomElement & root_node) { if (c == "Butt" || c == "Round" || c == "Square") data->cap = c; else { - throw ParsingFormatException("CT_DrawParam类型数据中的Cap属性值为非法值\n位于" + current_path.getRelativePath()); + qDebug() << "CT_DrawParam类型数据中的Cap属性值为非法值\n位于" + << current_path.getRelativePath(); } } if (root_node.hasAttribute("DashOffset")) { -- Gitee From 62321e9cc5f37c0e503c4380784e8d3451f0539d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Tue, 29 Aug 2017 22:08:59 +0800 Subject: [PATCH 60/83] =?UTF-8?q?=E4=BF=9D=E5=AD=98=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E9=82=A3=E9=87=8C=E4=BE=9D=E7=84=B6=E6=9C=89=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/libs/jsoncpp/jsoncpp.cpp | 86 ++- ofdEditor/model/Convert/Doc_OFDConvertor.cpp | 67 +- ofdEditor/model/Convert/Doc_OFDConvertor.h | 12 +- ofdEditor/model/Convert/OFD_DocConvertor.cpp | 46 +- ofdEditor/model/Doc/DocImageBlock.cpp | 50 ++ ofdEditor/model/Doc/DocImageBlock.h | 14 +- ofdEditor/model/Doc/DocPassage.cpp | 13 +- .../ofd/DataTypes/document/CT_CommonData.h | 2 + ofdEditor/ofd/DataTypes/document/Document.h | 16 +- ofdEditor/ofd/DataTypes/document/Res.h | 49 +- .../ofd/DataTypes/document/ct_commondata.h | 2 + ofdEditor/ofd/DataTypes/document/document.h | 16 +- ofdEditor/ofd/DataTypes/image/CT_Image.h | 1 - ofdEditor/ofd/ofd_parser.cpp | 535 ++++++++++---- ofdEditor/ofd/ofd_writer.cpp | 675 ++++++++++++------ ofdEditor/ofd/ofd_writer.h | 10 +- ofdEditor/start/ui/PassageMainWindow.cpp | 5 +- 17 files changed, 1175 insertions(+), 424 deletions(-) diff --git a/ofdEditor/libs/jsoncpp/jsoncpp.cpp b/ofdEditor/libs/jsoncpp/jsoncpp.cpp index dd2a1e3..e61e84f 100644 --- a/ofdEditor/libs/jsoncpp/jsoncpp.cpp +++ b/ofdEditor/libs/jsoncpp/jsoncpp.cpp @@ -6,28 +6,28 @@ // ////////////////////////////////////////////////////////////////////// /* -The JsonCpp library's source code, including accompanying documentation, +The JsonCpp library's source code, including accompanying documentation, tests and demonstration applications, are licensed under the following conditions... -The author (Baptiste Lepilleur) explicitly disclaims copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, this software is released into the Public Domain. In jurisdictions which do not recognize Public Domain property (e.g. Germany as of 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is released under the terms of the MIT License (see below). -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual Public Domain/MIT License conditions described here, as they choose. The MIT License is about as close to Public Domain as a license can get, and is described in clear, concise terms at: http://en.wikipedia.org/wiki/MIT_License - + The full text of the MIT License follows: ======================================================================== @@ -126,6 +126,65 @@ static inline std::string codePointToUTF8(unsigned int cp) { result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); } +/* + if (cp <= 0x7f) + { + result.resize(1); + result[0] = static_cast(cp); + } + else if (cp <= 0x7FF) + { + result.resize(2); + result[1] = static_cast(0x80 | (0x3f & cp)); + result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); + } + else if (cp <= 0xFFFF) + { + if ( + (cp >= 0x4E00 && cp <= 0x9FA5) + || (cp >= 0xF900 && cp <= 0xFA2D) + || cp == 0x3002 + || cp == 0xFF1F + || cp == 0xFF01 + || cp == 0xFF0C + || cp == 0x3001 + || cp == 0xFF1B + || cp == 0xFF1A + || cp == 0x300C + || cp == 0x300D + || cp == 0x300E + || cp == 0x300F || cp == 0x2018 || cp == 0x2019 || cp == 0x201C + || cp == 0x201D || cp == 0xFF08 || cp == 0xFF09 || cp == 0x3014 + || cp == 0x3015 || cp == 0x3010 || cp == 0x3011 || cp == 0x2014 + || cp == 0x2026 || cp == 0x2013 || cp == 0xFF0E || cp == 0x300A + || cp == 0x300B || cp == 0x3008 || cp == 0x3009) + { + wchar_t src[2] = { 0 }; + char dest[5] = { 0 }; + src[0] = static_cast(cp); + std::string curLocale = setlocale(LC_ALL, NULL); + setlocale(LC_ALL, "chs"); + wcstombs_s(NULL, dest, 5, src, 2); + result = dest; + setlocale(LC_ALL, curLocale.c_str()); + } + else + { + result.resize(3); + result[2] = static_cast(0x80 | (0x3f & cp)); + //result[1] = static_cast(0x80 | (0x3f & (cp >> 6))); + //result[0] = static_cast(0xE0 | (0xf & (cp >> 12))); + result[1] = 0x80 | static_cast((0x3f & (cp >> 6))); + result[0] = 0xE0 | static_cast((0xf & (cp >> 12))); + } + } else if (cp <= 0x10FFFF) { + result.resize(4); + result[3] = static_cast(0x80 | (0x3f & cp)); + result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); + result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); + } */ + return result; } @@ -207,7 +266,7 @@ static inline void fixNumericLocale(char* begin, char* end) { #include #if defined(_MSC_VER) -#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above +#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above #define snprintf sprintf_s #elif _MSC_VER >= 1900 // VC++ 14.0 and above #define snprintf std::snprintf @@ -3773,7 +3832,7 @@ Value& Path::make(Value& root) const { #endif #if defined(_MSC_VER) -#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above +#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above #define snprintf sprintf_s #elif _MSC_VER >= 1900 // VC++ 14.0 and above #define snprintf std::snprintf @@ -3786,7 +3845,7 @@ Value& Path::make(Value& root) const { #define snprintf std::snprintf #endif -#if defined(__BORLANDC__) +#if defined(__BORLANDC__) #include #define isfinite _finite #define snprintf _snprintf @@ -4849,7 +4908,7 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const std::string cs_str = settings_["commentStyle"].asString(); bool eyc = settings_["enableYAMLCompatibility"].asBool(); bool dnp = settings_["dropNullPlaceholders"].asBool(); - bool usf = settings_["useSpecialFloats"].asBool(); + bool usf = settings_["useSpecialFloats"].asBool(); unsigned int pre = settings_["precision"].asUInt(); CommentStyle::Enum cs = CommentStyle::All; if (cs_str == "All") { @@ -4938,8 +4997,3 @@ std::ostream& operator<<(std::ostream& sout, Value const& root) { // ////////////////////////////////////////////////////////////////////// // End of content of file: src/lib_json/json_writer.cpp // ////////////////////////////////////////////////////////////////////// - - - - - diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp index 1ac1435..7b04293 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp @@ -4,6 +4,7 @@ #include "Doc/DocBlock.h" #include "Doc/DocTextBlock.h" #include "Doc/DocLayer.h" +#include "Doc/DocImageBlock.h" #include #include @@ -30,6 +31,8 @@ #include "DataTypes/text/textcode.h" #include "DataTypes/basic_datatype.h" #include "Tool/UnitTool.h" +#include "DataTypes/image/CT_Image.h" +#include "DataTypes/image/CT_MultiMedia.h" Doc_OFDConvertor::Doc_OFDConvertor(QObject *parent) : QObject(parent) @@ -98,20 +101,24 @@ void Doc_OFDConvertor::buildDocument() // 设置ID_Table this->table = document->getIDTable(); // 获得IDTable - // 设置publicRes + // 设置publicRes\documentRes this->public_res = new Res(); this->public_res->setBaseLoc("Res"); + this->document_res = new Res(); + this->document_res->setBaseLoc("Res"); document->getPublicRes()->append(this->public_res); // 将公用资源加入到document - + document->document_res->append(this->document_res); // 设置common_data CT_CommonData * commonData = new CT_CommonData(); document->setCommonData(commonData); - // 设置指向资源文件的 + // 设置指向资源文件的 commonData->getPublicRes()->append(ST_Loc("PublicRes.xml", - "PublicRes.xml", - "PublicRes.xml")); - + "PublicRes.xml", + "PublicRes.xml")); + commonData->document_res->append(ST_Loc("DocumentRes.xml", + "DocumentRes.xml", + "DocumentRes.xml")); this->buildPages(document); // 解析每一页 @@ -246,7 +253,14 @@ void Doc_OFDConvertor::buildLayer(CT_Layer* ctLayer,DocLayer *layer) if(block->isTextBlock()) { // 进入文字框处理模式 - this->buildText(ctLayer,block->getTextBlock()); + this->buildText(ctLayer, block->getTextBlock()); + } + + // 如果是图片对象 + if(block->isImageBlock()) + { + // 将图片移动到资源文件夹,存下路径再结束 + this->buildImage(ctLayer, block->getImageBlock()); } } @@ -462,6 +476,45 @@ void Doc_OFDConvertor::buildText(CT_Layer* ctLayer,DocTextBlock *textBlock) } +/// +/// \brief Doc_OFDConvertor::buildImage +/// \param ctLayer +/// \param imageBlock +/// +void Doc_OFDConvertor::buildImage(CT_Layer *ctLayer, DocImageBlock *imageBlock) +{ + // 新建所需的对象,设置ID + CT_Image *ctimage = new CT_Image(); // iamgeobject + CT_MultiMedia *multiMedia = new CT_MultiMedia(); // 多媒体 + multiMedia->setID(this->table->size() + 1, + this->table); + ctimage->setID(this->table->size() + 1, + this->table); + + // 设置多媒体引用的标签 + multiMedia->Format = "Image"; + multiMedia->Type = "Jpeg"; + multiMedia->MediaFile = imageBlock->getFileName(); + + // 将图片存储到临时文件夹去 + QString fileName = this->passage->getTempSavePath() + + "/" + multiMedia->MediaFile; + imageBlock->saveImage(fileName); + + DocBlock* block = imageBlock->getBlock(); + + // 设置边界 + ctimage->setBoundary( + UnitTool::pixelToMM(block->x()), + UnitTool::pixelToMM(block->y()), + UnitTool::pixelToMM(block->size().width()), + UnitTool::pixelToMM(block->size().height())); + + + this->document_res->getMultiMedia()->push_back(multiMedia); // 追加到资源文件内 + ctLayer->image_object->push_back(ctimage); +} + /** * @Author Chaoqun * @brief 加入字体 diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.h b/ofdEditor/model/Convert/Doc_OFDConvertor.h index ccf6da4..80cbb59 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.h +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.h @@ -18,6 +18,7 @@ class CT_ColorSpace; // 颜色空间 class Page; class Document; class CT_Layer; +class DocImageBlock; /** @@ -41,14 +42,16 @@ private: void buildDocBody(); // 生成DocBody void buildDocument(); // 生成Document - void buildPages(Document *document); // 处理页面S + void buildPages(Document *document); // 处理页面S void buildPage(Page* ctPage, - DocPage* docPage); // 处理其中某一页 + DocPage* docPage); // 处理其中某一页 void buildLayer(CT_Layer* ctLayer, - DocLayer* layer); // 将一层中的信息存储出来 - void buildText(CT_Layer* ctLayer,DocTextBlock* textBlock); // 将DocTextBlock中的信息转换处理 + DocLayer* layer); // 将一层中的信息存储出来 + void buildText(CT_Layer* ctLayer,DocTextBlock* textBlock); // 将DocTextBlock中的信息转换处理 + void buildImage(CT_Layer* ctLayer, DocImageBlock *imageBlock); // 处理图片 + int addFont(CT_Font* font); // 添加字体类型到资源 int addColorSpace(CT_ColorSpace* colorSpace); // 添加颜色空间 @@ -60,6 +63,7 @@ private: DocPassage* passage; // 文章 OFD* ofdFile; // OFD 对象 Res* public_res; // Res 公共资源文件 + Res* document_res; // 放图片等多媒体资源的res ID_Table* table; // ID table diff --git a/ofdEditor/model/Convert/OFD_DocConvertor.cpp b/ofdEditor/model/Convert/OFD_DocConvertor.cpp index 14027b4..a0f94fe 100644 --- a/ofdEditor/model/Convert/OFD_DocConvertor.cpp +++ b/ofdEditor/model/Convert/OFD_DocConvertor.cpp @@ -10,6 +10,7 @@ #include "DataTypes/page/page.h" #include "Doc/DocTextBlock.h" #include "Doc/DocBlock.h" +#include "Doc/DocImageBlock.h" #include "Tool/UnitTool.h" #include "DataTypes/text/TextCode.h" #include "DataTypes/text/CT_Text.h" @@ -18,6 +19,8 @@ #include "Convert/Objects/MinTextUnit.h" #include "DataTypes/page/CT_PageArea.h" #include "DataTypes/document/ct_commondata.h" +#include "DataTypes/image/CT_Image.h" +#include "DataTypes/image/CT_MultiMedia.h" OFD_DocConvertor::OFD_DocConvertor() { @@ -61,6 +64,7 @@ DocPassage *OFD_DocConvertor::ofd_to_doc(OFD *ofd) { // 生成每一页 +// qDebug() << "build Page" << i; DocPage * newPage = this->buildDocPage(passage, (*pages)[i]); newPage->setVisible(true); } @@ -188,6 +192,14 @@ void OFD_DocConvertor::insertPageBlock(DocPage *page, // 处理 CT_Path // 处理 CT_Image + QVector *images = pageBlock->getImageObject(); + for(int i = 0; i < images->size(); i++) + { + this->insertCT_Image( + page, + doctype, + images->operator [](i)); + } } @@ -327,9 +339,41 @@ void OFD_DocConvertor::insertCT_Path(DocPage *page, CT_Layer *layer, CT_Path *pa } -void OFD_DocConvertor::insertCT_Image(DocPage *page, DocPage::Layer layer, CT_Image *image) +/// +/// \brief OFD_DocConvertor::insertCT_Image +/// \param page +/// \param layer +/// \param image +/// +void OFD_DocConvertor::insertCT_Image( + DocPage *page, + DocPage::Layer layer, + CT_Image *image) { + DocImageBlock *imageBlock = new DocImageBlock(); + // 获得多媒体资源 + CT_Base* base_media = + this->ofdFile->getDocuments()->operator [](0) + ->getIDTable()->getItem( + image->getResourceID()); + CT_MultiMedia* multMedia = (CT_MultiMedia *)base_media; + + qDebug() << multMedia->MediaFile; + imageBlock->setImage(multMedia->MediaFile); // 设置图片 + imageBlock->setWidthHeightRatioLocked(false); // 先不要锁定纵横比 + DocBlock * block = new DocBlock(); + + block->setWidget(imageBlock); + ST_Box box = image->boundary; // 获得位置大小 + block->resize( + UnitTool::mmToPixel(box.getDeltaX()), + UnitTool::mmToPixel(box.getDeltaY())); + block->setPos( + UnitTool::mmToPixel(box.getX()), + UnitTool::mmToPixel(box.getY())); + + page->addBlock(block, layer); // 加入到页面中 } /** diff --git a/ofdEditor/model/Doc/DocImageBlock.cpp b/ofdEditor/model/Doc/DocImageBlock.cpp index 90eca2a..48322c7 100644 --- a/ofdEditor/model/Doc/DocImageBlock.cpp +++ b/ofdEditor/model/Doc/DocImageBlock.cpp @@ -5,6 +5,7 @@ #include #include "DocPage.h" #include "Tool/UnitTool.h" +#include DocImageBlock::DocImageBlock(QWidget *parent) :QLabel(parent) @@ -148,6 +149,38 @@ QMenu *DocImageBlock::getMenu() return this->context_menu; } +QString DocImageBlock::getFileName() +{ + if(this->fileName.size() == 0) + { + // 如果没有设置文件名,则随机生成文件名 + QUuid uuid = QUuid::createUuid(); // 创建uuid + QString imageName = uuid.toString(); // 转换为字符串 + + // 去掉字符串的链接符号 {0142d46f-60b5-47cf-8310-50008cc7cb3a} + // 0142d46f60b547cf831050008cc7cb3a + imageName.remove(imageName.length()-1, 1); + imageName.remove(imageName.length() -13, 1); + imageName.remove(imageName.length() -17,1); + imageName.remove(imageName.length() -21, 1); + imageName.remove(imageName.length() - 25,1); + imageName.remove(0,1); + + this->fileName = imageName + ".jpg"; + } + return this->fileName; +} + +/// +/// \brief DocImageBlock::saveImage +/// 将图片保存到指定路径 +/// \param filepath +/// +void DocImageBlock::saveImage(QString filepath) +{ + this->pixmap()->save(filepath, 0, 100); +} + double DocImageBlock::getRealWidth() { return this->realWidth; @@ -270,3 +303,20 @@ void DocImageBlock::imagePropertiesChanged( this->width_height_ratio_locked = ratio_locked; this->width_height_ratio = new_width / new_height; } + +void DocImageBlock::setFileName(QString fileName) +{ + this->fileName = fileName; +} + +/// +/// \brief DocImageBlock::setImage +/// 直接用文件路径设置图片块 +/// \param filePath +/// +void DocImageBlock::setImage(QString filePath) +{ + QPixmap image(filePath); + this->fileName = filePath.section("/", -1); // 获取文件名部分 + this->setImage(image); +} diff --git a/ofdEditor/model/Doc/DocImageBlock.h b/ofdEditor/model/Doc/DocImageBlock.h index cc36a98..4bed26a 100644 --- a/ofdEditor/model/Doc/DocImageBlock.h +++ b/ofdEditor/model/Doc/DocImageBlock.h @@ -26,9 +26,11 @@ public: DocPassage *getPassage(); // 获得文章 DocPage *getPage(); // 获得页 DocLayer *getLayer(); // 获得层 - DocBlock *getBlock(); //获取代理它的DocBlock - QString getType(); // 获得标识,来区分不同的块 - QMenu* getMenu(); // 获得图片块的菜单成分 + DocBlock *getBlock(); //获取代理它的DocBlock + QString getType(); // 获得标识,来区分不同的块 + QMenu* getMenu(); // 获得图片块的菜单成分 + QString getFileName(); // 获得图片的文件名 + void saveImage( QString filepath ); // 保存文件 // 单位为 mm double getRealWidth(); // 获得图片真实大小 @@ -41,10 +43,13 @@ public slots: double new_x, double new_y, bool ratio_locked); // 修改图片属性 + void setFileName(QString fileName); // 设置图片文件名 + void setImage(QString filePath); // 直接使用路径设置图片 void setImage(QPixmap & pixmap); // 设置图片 void setBlock(DocBlock * _block); // 设置所属的块 void changeImage(); // 修改图片 void setImageProperties(); // 设置图片属性 + void setWidthHeightRatioLocked(bool flag){this->width_height_ratio_locked = flag;} protected: void focusInEvent(QFocusEvent *ev); @@ -57,7 +62,8 @@ private: QAction * set_image_properties; //更改图片的位置和尺寸 bool width_height_ratio_locked; double width_height_ratio; - QString temp_store; + + QString fileName; // 图片的文件名 ---- uuid + 后缀名 void initMenu(); // 初始化右键菜单 diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index 43c9eb2..b02781d 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -321,7 +321,14 @@ QString DocPassage::getTempSavePath() { QString temp = QDir::tempPath() + "/"; // 获得系统临时路径 QString uuid = this->getUUID(); // 获得uuid - QString end = "-source"; + QString end = "_source"; + + QDir dir(temp + uuid + end); + if(!dir.exists()) + { + dir.mkpath(temp + uuid + end); + } + return temp + uuid + end; // 获得临时存放路径 } @@ -336,7 +343,9 @@ QString DocPassage::getTempStorePath() { QString temp = QDir::tempPath() + "/"; // 获得系统临时路径 QString uuid = this->getUUID(); // 获得uuid - QString end = "-file"; + QString end = "_file"; + + return temp + uuid + end; // 获得临时存放路径 } diff --git a/ofdEditor/ofd/DataTypes/document/CT_CommonData.h b/ofdEditor/ofd/DataTypes/document/CT_CommonData.h index 799c40f..2eadbb2 100644 --- a/ofdEditor/ofd/DataTypes/document/CT_CommonData.h +++ b/ofdEditor/ofd/DataTypes/document/CT_CommonData.h @@ -9,6 +9,7 @@ public: ST_ID max_unit_id; //当前文档中所有对象使用的最大标识 CT_PageArea *page_area; //指定多个页面区域的大小和位置 QVector *public_res; //公共资源序列,每个资源指向OFD包内部的一个XML文件 + QVector *document_res; //vector template_page; //模板页序列 ST_RefID default_cs; //缺省颜色空间 public: @@ -16,6 +17,7 @@ public: CT_CommonData() { public_res = new QVector(); + document_res = new QVector(); page_area = NULL; } diff --git a/ofdEditor/ofd/DataTypes/document/Document.h b/ofdEditor/ofd/DataTypes/document/Document.h index 0448abe..d91c432 100644 --- a/ofdEditor/ofd/DataTypes/document/Document.h +++ b/ofdEditor/ofd/DataTypes/document/Document.h @@ -10,13 +10,15 @@ class OFDSHARED_EXPORT Document { public: - CT_CommonData * common_data; //文档公共数据,定义了默认页面单位、页面区域定义、公共资源等数据 - CT_Outlines * outlines; //大纲树 - ST_Loc custom_tags; //指向自定义标引文件 - ST_Loc extensions; //指向拓展文件 - ST_Loc annotations; //指向注释文件 - ID_Table * id_table; //记录所有CT_Base的ID信息 + CT_CommonData * common_data; //文档公共数据,定义了默认页面单位、页面区域定义、公共资源等数据 + CT_Outlines * outlines; //大纲树 + ST_Loc custom_tags; //指向自定义标引文件 + ST_Loc extensions; //指向拓展文件 + ST_Loc annotations; //指向注释文件 + ID_Table * id_table; //记录所有CT_Base的ID信息 QVector * public_res; + QVector * document_res; + CT_Pages *pages; @@ -49,6 +51,8 @@ public: if (!_id_table) id_table = new ID_Table; else id_table = _id_table; + + document_res = new QVector(); } CT_CommonData * getCommonData() { diff --git a/ofdEditor/ofd/DataTypes/document/Res.h b/ofdEditor/ofd/DataTypes/document/Res.h index 01058d8..12cce59 100644 --- a/ofdEditor/ofd/DataTypes/document/Res.h +++ b/ofdEditor/ofd/DataTypes/document/Res.h @@ -7,14 +7,15 @@ #include "../../ofd_global.h" // 生成库文件需要 #include "DataTypes/image/CT_MultiMedia.h" -class OFDSHARED_EXPORT Res { +class OFDSHARED_EXPORT Res +{ //属性 ST_Loc base_loc; //定义此资源描述文件的通用数据存储路径 //成员 - QVector * fonts; - QVector * colorspaces; - QVector * draw_params; - QVector multMedias; + QVector* fonts; + QVector* colorspaces; + QVector* draw_params; + QVector* multMedias; //Other resource collections to be implemented public: @@ -23,7 +24,8 @@ public: Res(QString _base_loc = "", QVector * _fonts = NULL, QVector * _colorspaces = NULL, - QVector * _draw_params = NULL) { + QVector * _draw_params = NULL) + { if (!_base_loc.isNull()) setBaseLoc(_base_loc); if (!_fonts) @@ -38,22 +40,34 @@ public: draw_params = new QVector(); else draw_params = _draw_params; + + multMedias = new QVector(); + } - ST_Loc getBaseLoc() { + ST_Loc getBaseLoc() + { return base_loc; } - void setBaseLoc(QString _base_loc_abs) { + void setBaseLoc(QString _base_loc_abs) + { ST_Loc p("Resource", _base_loc_abs,_base_loc_abs); base_loc = p; } - QVector * getFonts() { + QVector * getFonts() + { return fonts; } - void setFonts(QVector * _fonts) { + QVector *getMultiMedia() + { + return this->multMedias; + } + + void setFonts(QVector * _fonts) + { if (!_fonts) throw InvalidValueException("Invalid value in Fonts in Res: null pointer"); for (int i = 0; i < fonts->size(); i++) @@ -62,11 +76,13 @@ public: fonts = _fonts; } - QVector * getColorSpaces() { + QVector * getColorSpaces() + { return colorspaces; } - void setColorSpaces(QVector * _colorspaces) { + void setColorSpaces(QVector * _colorspaces) + { if (!_colorspaces) throw InvalidValueException("Invalid value in ColorSpaces in Res: null pointer"); for (int i = 0; i < colorspaces->size(); i++) @@ -75,11 +91,13 @@ public: colorspaces = _colorspaces; } - QVector * getDrawParams() { + QVector * getDrawParams() + { return draw_params; } - void setDrawParams(QVector * _draw_params) { + void setDrawParams(QVector * _draw_params) + { if (!_draw_params) throw InvalidValueException("Invalid value in DrawParams in Res: null pointer"); for (int i = 0; i < draw_params->size(); i++) @@ -88,7 +106,8 @@ public: draw_params = _draw_params; } - ~Res() { + ~Res() + { for (int i = 0; i < fonts->size(); i++) delete fonts->at(i); for (int i = 0; i < colorspaces->size(); i++) diff --git a/ofdEditor/ofd/DataTypes/document/ct_commondata.h b/ofdEditor/ofd/DataTypes/document/ct_commondata.h index 799c40f..2eadbb2 100644 --- a/ofdEditor/ofd/DataTypes/document/ct_commondata.h +++ b/ofdEditor/ofd/DataTypes/document/ct_commondata.h @@ -9,6 +9,7 @@ public: ST_ID max_unit_id; //当前文档中所有对象使用的最大标识 CT_PageArea *page_area; //指定多个页面区域的大小和位置 QVector *public_res; //公共资源序列,每个资源指向OFD包内部的一个XML文件 + QVector *document_res; //vector template_page; //模板页序列 ST_RefID default_cs; //缺省颜色空间 public: @@ -16,6 +17,7 @@ public: CT_CommonData() { public_res = new QVector(); + document_res = new QVector(); page_area = NULL; } diff --git a/ofdEditor/ofd/DataTypes/document/document.h b/ofdEditor/ofd/DataTypes/document/document.h index 0448abe..d91c432 100644 --- a/ofdEditor/ofd/DataTypes/document/document.h +++ b/ofdEditor/ofd/DataTypes/document/document.h @@ -10,13 +10,15 @@ class OFDSHARED_EXPORT Document { public: - CT_CommonData * common_data; //文档公共数据,定义了默认页面单位、页面区域定义、公共资源等数据 - CT_Outlines * outlines; //大纲树 - ST_Loc custom_tags; //指向自定义标引文件 - ST_Loc extensions; //指向拓展文件 - ST_Loc annotations; //指向注释文件 - ID_Table * id_table; //记录所有CT_Base的ID信息 + CT_CommonData * common_data; //文档公共数据,定义了默认页面单位、页面区域定义、公共资源等数据 + CT_Outlines * outlines; //大纲树 + ST_Loc custom_tags; //指向自定义标引文件 + ST_Loc extensions; //指向拓展文件 + ST_Loc annotations; //指向注释文件 + ID_Table * id_table; //记录所有CT_Base的ID信息 QVector * public_res; + QVector * document_res; + CT_Pages *pages; @@ -49,6 +51,8 @@ public: if (!_id_table) id_table = new ID_Table; else id_table = _id_table; + + document_res = new QVector(); } CT_CommonData * getCommonData() { diff --git a/ofdEditor/ofd/DataTypes/image/CT_Image.h b/ofdEditor/ofd/DataTypes/image/CT_Image.h index e3cd5bf..02c8686 100644 --- a/ofdEditor/ofd/DataTypes/image/CT_Image.h +++ b/ofdEditor/ofd/DataTypes/image/CT_Image.h @@ -12,7 +12,6 @@ class OFDSHARED_EXPORT CT_Image : public CT_GraphicUnit ST_RefID resource_id; // 指向资源文件中定义的多媒体对象的ID ST_RefID substitution; // (可选)指定可替换图像, // 用于某些情况如高分辨率输出时进行图像替换。 - public: friend class OFDParser; diff --git a/ofdEditor/ofd/ofd_parser.cpp b/ofdEditor/ofd/ofd_parser.cpp index e41328a..9b60d7e 100644 --- a/ofdEditor/ofd/ofd_parser.cpp +++ b/ofdEditor/ofd/ofd_parser.cpp @@ -127,12 +127,15 @@ Document * OFDParser::readDocument() { if (!new_document.isNull()) { document_data = new Document(); id_table = document_data->id_table; + // commonData QDomElement new_commondata = new_document.firstChildElement("ofd:CommonData"); if (!new_commondata.isNull()) { CT_CommonData * commondata_data = new CT_CommonData(); document_data->common_data = commondata_data; - qDebug() << "Checkpoint 1.1..."; + qDebug() << "Checkpoint 1.1..."; QDomElement t; + + // MaxUnitID if (!(t = new_commondata.firstChildElement("ofd:MaxUnitID")).isNull()) { commondata_data->max_unit_id = t.text().toInt(); } else { @@ -140,6 +143,7 @@ Document * OFDParser::readDocument() { //Error } + // PageArea if (!(t = new_commondata.firstChildElement("ofd:PageArea")).isNull()) { CT_PageArea *pagearea_data = new CT_PageArea(); commondata_data->page_area = pagearea_data; @@ -147,7 +151,9 @@ Document * OFDParser::readDocument() { } else { qDebug("PageArea"); } - qDebug() << "Checkpoint 1.1.1..."; + qDebug() << "Checkpoint 1.1.1..."; + + // publicRes t = new_commondata.firstChildElement("ofd:PublicRes"); while (!t.isNull()) { ST_Loc p("PublicRes", t.text(), current_path); @@ -156,6 +162,16 @@ Document * OFDParser::readDocument() { t = t.nextSiblingElement("ofd:PublicRes"); } + // documentRes + t = new_commondata.firstChildElement("ofd:DocumentRes"); + while (!t.isNull()) { + ST_Loc p("DocumentRes", t.text(), current_path); + //qDebug() << "PublicRes = " << t.text(); + commondata_data->document_res->push_back(p); + t = t.nextSiblingElement("ofd:DocumentRes"); + } + + if (!(t = new_commondata.firstChildElement("ofd:DefaultCS")).isNull()) { //to be implemented } @@ -163,7 +179,9 @@ Document * OFDParser::readDocument() { } else { qDebug("Document类型的数据中中缺少必要的CommonData成员\n位于Document.xml"); } - qDebug() << "Checkpoint 1.2..."; + + qDebug() << "Checkpoint 1.2..."; + // Pages QDomElement new_pages = new_document.firstChildElement("ofd:Pages"); CT_Pages *pages_data; if (!new_pages.isNull()) { @@ -183,7 +201,7 @@ Document * OFDParser::readDocument() { qDebug("Document类型的数据中中缺少必要的Pages成员\n位于Document.xml"); } document_data->pages = pages_data; - qDebug() << "Checkpoint 1.3..."; + qDebug() << "Checkpoint 1.3..."; QDomElement new_outlines = new_document.firstChildElement("ofd:Outlines"); if (!new_outlines.isNull()) { //to be implemented @@ -209,7 +227,8 @@ Document * OFDParser::readDocument() { qDebug() << "Document.xml文档中缺少必要的Document标签\n位于" << current_path.getRelativePath(); } - //访问资源 + + // publicRes for (int i = 0; i < document_data->common_data->public_res->size(); i++) { current_path = document_data->common_data->public_res->at(i); Res * res_data = new Res(); @@ -217,6 +236,14 @@ Document * OFDParser::readDocument() { document_data->public_res->push_back(res_data); } + // documentRes + for (int i = 0; i < document_data->common_data->document_res->size(); i++) { + current_path = document_data->common_data->document_res->operator [](i); + Res * res_data = new Res(); + readResource(res_data); + document_data->public_res->push_back(res_data); + } + //访问页面 for (int i = 0; i < document_data->pages->pages->size(); i++) { current_path = document_data->pages->pages->at(i)->base_loc; @@ -231,20 +258,31 @@ Document * OFDParser::readDocument() { return document_data; } +/// +/// \brief OFDParser::readPage +/// 解析页 +/// \param page_data +/// void OFDParser::readPage(Page * page_data) { openFile(); QDomElement new_page = document->firstChildElement("ofd:Page"); qDebug() << "Checkpoint 2: Entering Page..."; - if (!new_page.isNull()) { + if (!new_page.isNull()) + { QDomElement t; - if (!(t = new_page.firstChildElement("ofd:Area")).isNull()) { + + // pageArea + if (!(t = new_page.firstChildElement("ofd:Area")).isNull()) + { CT_PageArea * area_data = new CT_PageArea(); readPageArea(area_data, t); page_data->area = area_data; } + // pageRes t = new_page.firstChildElement("ofd:PageRes"); - while (!t.isNull()) { + while (!t.isNull()) + { ST_Loc p("PageRes", t.text(), current_path); Res * new_res = new Res(); current_path = p; @@ -253,107 +291,151 @@ void OFDParser::readPage(Page * page_data) { t = t.nextSiblingElement("ofd:PageRes"); } - if (!(t = new_page.firstChildElement("ofd:Content")).isNull()) { -// qDebug() << "Checkpoint 2.1"; + // Content + if (!(t = new_page.firstChildElement("ofd:Content")).isNull()) + { + // qDebug() << "Checkpoint 2.1"; + // layer QDomElement new_layer = t.firstChildElement("ofd:Layer"); - while (!new_layer.isNull()) { + while (!new_layer.isNull()) + { CT_Layer * layer_data = new CT_Layer(); + // ID page_data->getContent()->push_back(layer_data); - if (new_layer.hasAttribute("ID")) { + if (new_layer.hasAttribute("ID")) + { ST_ID i(new_layer.attribute("ID").toInt()); layer_data->setID(i, id_table); - } else { + } + else + { qDebug() << "CT_Layer类型数据中缺少必要的ID属性\n位于" << current_path.getRelativePath(); } - if (new_layer.hasAttribute("DrawParam")) { + + // Type + if(new_layer.hasAttribute("Type")) + { + QString tempType = new_layer.attribute("Type"); + layer_data->setType(tempType); + } + + // DrawParam + if (new_layer.hasAttribute("DrawParam")) + { ST_RefID ri(new_layer.attribute("DrawParam").toInt()); if (id_table->contains(ri.getRefID())) layer_data->draw_param = ri; - else { - qDebug() << "Checkpoint ID 1..."; + else + { + qDebug() << "Checkpoint ID 1..."; qDebug() << "Layer类型数据的DrawParam属性引用了未注册的ID 位于" << current_path.getRelativePath(); } } -// qDebug() << "Checkpoint 2.2"; + // qDebug() << "Checkpoint 2.2"; QDomElement t; //解析文字对象 bool is_first_textcode_x = true, is_first_textcode_y = true; double last_x = 0.0, last_y = 0.0; + + // TextObject t = new_layer.firstChildElement("ofd:TextObject"); - while (!t.isNull()) { + while (!t.isNull()) + { //qDebug() << "Start to read TextObject..." << endl; CT_Text * text_data = new CT_Text(); layer_data->text_object->push_back(text_data); + readGraphicUnit(text_data, t); //Read TextObject attributes - if (t.hasAttribute("Font")) { + if (t.hasAttribute("Font")) + { ST_RefID ri(t.attribute("Font").toInt()); if (id_table->contains(ri.getRefID())) text_data->font = ri; - else { + else + { qDebug() << "Checkpoint ID 2..."; qDebug() << "CT_Text类型数据的Font属性引用了未注册的ID:" << QString::number(ri.getRefID()) << " 位于" << current_path.getRelativePath(); } - } else { + } + else + { qDebug() << "CT_Text类型数据中缺少必要的Font属性\n位于" << current_path.getRelativePath(); } - if (t.hasAttribute("Size")) { + // size + if (t.hasAttribute("Size")) + { text_data->size = t.attribute("Size").toDouble(); text_data->size_used = true; - } else { + } + else + { qDebug() << "CT_Text类型数据中缺少必要的Size属性\n位于" << current_path.getRelativePath(); } -// qDebug() << "Checkpoint 2.3"; + // qDebug() << "Checkpoint 2.3"; //many optional attributes to be implemented + // textCode QDomElement t2 = t.firstChildElement("ofd:TextCode"); - if (t2.isNull()) { + if (t2.isNull()) + { qDebug() << "CT_Text类型数据中缺少必要的TextCode成员\n位于" << current_path.getRelativePath(); } -// qDebug() << "Checkpoint 2.3.1"; - while(!t2.isNull()) { + // qDebug() << "Checkpoint 2.3.1"; + while(!t2.isNull()) + { TextCode * text_code_data = new TextCode(); -// qDebug() << "Checkpoint 2.3.1.0"; + // qDebug() << "Checkpoint 2.3.1.0"; text_data->text_code->push_back(text_code_data); -// qDebug() << "Checkpoint 2.3.1.1"; - if (t2.hasAttribute("X")) { + // qDebug() << "Checkpoint 2.3.1.1"; + if (t2.hasAttribute("X")) + { last_x = text_code_data->x = t2.attribute("X").toDouble(); if (is_first_textcode_x) is_first_textcode_x = false; - } else { + } + else + { if (!is_first_textcode_x && !is_first_textcode_y) text_code_data->x = last_x; - else { - qDebug() << "TextCode类型数据中缺少第一个X值\n位于" - << current_path.getRelativePath(); + else + { + qDebug() << "TextCode类型数据中缺少第一个X值\n位于" + << current_path.getRelativePath(); } } -// qDebug() << "Checkpoint 2.3.2"; - if (t2.hasAttribute("Y")) { + // qDebug() << "Checkpoint 2.3.2"; + if (t2.hasAttribute("Y")) + { last_y = text_code_data->y = t2.attribute("Y").toDouble(); if (is_first_textcode_y) is_first_textcode_y = false; - } else { + } + else + { if (!is_first_textcode_x && !is_first_textcode_y) text_code_data->y = last_y; - else { - qDebug() << "TextCode类型数据中缺少第一个Y值\n位于" - << current_path.getRelativePath(); + else + { + qDebug() << "TextCode类型数据中缺少第一个Y值\n位于" + << current_path.getRelativePath(); } } - if (t2.hasAttribute("DeltaX")) { + if (t2.hasAttribute("DeltaX")) + { ST_Array delta_x_data("DeltaX", t2.attribute("DeltaX")); text_code_data->delta_x = delta_x_data; } - if (t2.hasAttribute("DeltaY")) { + if (t2.hasAttribute("DeltaY")) + { ST_Array delta_y_data("DeltaX", t2.attribute("DeltaY")); text_code_data->delta_y = delta_y_data; } @@ -363,34 +445,44 @@ void OFDParser::readPage(Page * page_data) { } t = t.nextSiblingElement("ofd:TextObject"); } -// qDebug() << "Checkpoint 2.4"; + // qDebug() << "Checkpoint 2.4"; + //解析矢量图对象 t = new_layer.firstChildElement("ofd:PathObject"); - while (!t.isNull()) { + while (!t.isNull()) + { CT_Path * path_data = new CT_Path(); layer_data->path_object->push_back(path_data); readGraphicUnit(path_data, t); - if (t.hasAttribute("Stroke")) { + if (t.hasAttribute("Stroke")) + { path_data->stroke = t.attribute("Stroke") == "false" ? false : true; } - if (t.hasAttribute("Fill")) { + if (t.hasAttribute("Fill")) + { path_data->fill = t.attribute("Fill") == "false" ? false : true; } - if (t.hasAttribute("Rule")) { + if (t.hasAttribute("Rule")) + { if (t.attribute("Rule") == "NonZero") path_data->rule = "NonZero"; else if (t.attribute("Rule") == "Even-Odd") path_data->rule = "Even-Odd"; - else { + else + { qDebug() << "CT_Path类型数据中的Rule属性值为非法值\n位于" - << current_path.getRelativePath() - << " 值为" - << t.attribute("Rule"); + << current_path.getRelativePath() + << " 值为" + << t.attribute("Rule"); } } - if (!t.firstChildElement("ofd:AbbreviatedData").isNull()) { + // 图形变换的描述 + if (!t.firstChildElement("ofd:AbbreviatedData").isNull()) + { path_data->abbreviated_data = t.firstChildElement("ofd:AbbreviatedData").text(); - } else { + } + else + { qDebug() << "CT_Path类型数据中缺少必要的AbbreviatedData成员\n位于" << current_path.getRelativePath(); } @@ -398,30 +490,38 @@ void OFDParser::readPage(Page * page_data) { } //解析位图对象 + // ImageObject t = new_layer.firstChildElement("ofd:ImageObject"); - while (!t.isNull()) { + while (!t.isNull()) + { CT_Image * image_data = new CT_Image(); layer_data->image_object->push_back(image_data); - readGraphicUnit(image_data, t); - if (t.hasAttribute("ResourceID")) { + readGraphicUnit(image_data, t); // 读取图元里的共用的数据 + if (t.hasAttribute("ResourceID")) + { ST_RefID ri(t.attribute("ResourceID").toInt()); if (id_table->contains(ri.getRefID())) image_data->resource_id = ri; - else { + else + { qDebug() << ri.getRefID(); qDebug() << "Checkpoint ID 3..."; //qDebug("CT_Image类型数据的ResourceID属性引用了未注册的ID 位于" + current_path.getRelativePath()); } -// image_data->resource_id = ri; - } else { + } + else + { qDebug() << "CT_Image类型数据中缺少必要的ResourceID属性\n位于" << current_path.getRelativePath(); } - if (t.hasAttribute("Substitution")) { + + if (t.hasAttribute("Substitution")) + { ST_RefID ri(t.attribute("Substitution").toInt()); if (id_table->contains(ri.getRefID())) image_data->substitution = ri; - else { + else + { qDebug() << "Checkpoint ID 4..."; qDebug() << "CT_Image类型数据的Substitution属性引用了未注册的ID 位于" << current_path.getRelativePath(); @@ -434,118 +534,178 @@ void OFDParser::readPage(Page * page_data) { new_layer = new_layer.nextSiblingElement("ofd:Layer"); } } - } else { + } + else + { qDebug() << "Content.xml文档中缺少必要的Page标签\n位于" << current_path.getRelativePath(); } -// qDebug() << "Checkpoint 3"; + // qDebug() << "Checkpoint 3"; } void OFDParser::readPageArea(CT_PageArea * data, QDomElement & root_node) { QDomElement t; -// qDebug() << "Checkpoint PA 1..."; - if (!(t = root_node.firstChildElement("ofd:PhysicalBox")).isNull()) { + // qDebug() << "Checkpoint PA 1..."; + if (!(t = root_node.firstChildElement("ofd:PhysicalBox")).isNull()) + { QStringList values = t.text().split(" "); //qDebug() << values[0] << values[1] << values[2] << endl; - if (values.size() == 4) { - data->physical_box = ST_Box(values[0].toDouble(), values[1].toDouble(), values[2].toDouble(), values[3].toDouble()); + if (values.size() == 4) + { + data->physical_box = ST_Box( + values[0].toDouble(), + values[1].toDouble(), + values[2].toDouble(), + values[3].toDouble()); } - else { + else + { qDebug() << "CT_PageArea类型数据的PhysicalBox成员的值的数目错误\n位于" << current_path.getRelativePath(); } - } else { + } + else + { qDebug() << "CT_PageArea类型的数据中中缺少必要的PhysicalBox成员\n位于" << current_path.getRelativePath(); } -// qDebug() << "Checkpoint PA 2..."; - if (!(t = root_node.firstChildElement("ofd:ApplicationBox")).isNull()) { + // qDebug() << "Checkpoint PA 2..."; + if (!(t = root_node.firstChildElement("ofd:ApplicationBox")).isNull()) + { QStringList values = t.text().split(" "); if (values.size() == 4) - data->application_box = ST_Box(values[0].toDouble(), values[1].toDouble(), values[2].toDouble(), values[3].toDouble()); - else { + data->application_box = ST_Box( + values[0].toDouble(), + values[1].toDouble(), + values[2].toDouble(), + values[3].toDouble()); + else + { qDebug() << "CT_PageArea类型数据的ApplicationBox成员的值的数目错误\n位于" << current_path.getRelativePath(); } } -// qDebug() << "Checkpoint PA 3..."; - if (!(t = root_node.firstChildElement("ofd:ContentBox")).isNull()) { + // qDebug() << "Checkpoint PA 3..."; + if (!(t = root_node.firstChildElement("ofd:ContentBox")).isNull()) + { QStringList values = t.text().split(" "); if (values.size() == 4) - data->content_box = ST_Box(values[0].toDouble(), values[1].toDouble(), values[2].toDouble(), values[3].toDouble()); + data->content_box = ST_Box( + values[0].toDouble(), + values[1].toDouble(), + values[2].toDouble(), + values[3].toDouble()); else qDebug() << "CT_PageArea类型数据的ContentBox成员的值的数目错误\n位于" << current_path.getRelativePath(); } - if (!(t = root_node.firstChildElement("ofd:BleedBox")).isNull()) { + if (!(t = root_node.firstChildElement("ofd:BleedBox")).isNull()) + { QStringList values = t.text().split(" "); if (values.size() == 4) - data->bleed_box = ST_Box(values[0].toDouble(), values[1].toDouble(), values[2].toDouble(), values[3].toDouble()); - else { + data->bleed_box = ST_Box( + values[0].toDouble(), + values[1].toDouble(), + values[2].toDouble(), + values[3].toDouble()); + else + { qDebug() << "CT_PageArea类型数据的BleedBox成员的值的数目错误\n位于" << current_path.getRelativePath(); } } } -void OFDParser::readGraphicUnit(CT_GraphicUnit *data, QDomElement &root_node) { - //读取属性 - if (root_node.hasAttribute("ID")) { +/// +/// \brief OFDParser::readGraphicUnit +/// \param data +/// \param root_node +/// +void OFDParser::readGraphicUnit(CT_GraphicUnit *data, QDomElement &root_node) +{ + // ID + if (root_node.hasAttribute("ID")) + { ST_ID i(root_node.attribute("ID").toInt()); data->setID(i, id_table); - } else { + } + else + { qDebug() << "CT_GraphicUnit类型数据中缺少必要的ID属性\n位于" << current_path.getRelativePath(); } - if (root_node.hasAttribute("Boundary")) { + // Boundary + if (root_node.hasAttribute("Boundary")) + { QStringList values = root_node.attribute("Boundary").split(" "); - if (values.size() == 4) { - data->boundary = ST_Box(values[0].toDouble(), values[1].toDouble(), values[2].toDouble(), values[3].toDouble()); + if (values.size() == 4) + { + data->boundary = ST_Box( + values[0].toDouble(), + values[1].toDouble(), + values[2].toDouble(), + values[3].toDouble()); } - else { + else + { qDebug() << "CT_GraphicUnit类型数据的Boundary成员的值的数目错误\n位于" << current_path.getRelativePath(); } - } else { + } + else + { qDebug() << "CT_GraphicUnit类型数据中缺少必要的ID属性\n位于" << current_path.getRelativePath(); } //读取成员 QDomElement t; - if (!(t = root_node.firstChildElement("ofd:FillColor")).isNull()) { + if (!(t = root_node.firstChildElement("ofd:FillColor")).isNull()) + { CT_Color * fill_color_data = new CT_Color(); data->fill_color = fill_color_data; readColor(fill_color_data, t); - if (root_node.hasAttribute("ID") && root_node.attribute("ID").toInt() == 3) + if (root_node.hasAttribute("ID") + && root_node.attribute("ID").toInt() == 3) qDebug() << "In OFDParser: " << fill_color_data; } //Other members to be implemented } +/// +/// \brief OFDParser::readResource +/// 解析资源文件 +/// \param res_data +/// void OFDParser::readResource(Res * res_data) { qDebug() << "read res-----------"; openFile(); QDomElement new_res = document->firstChildElement("ofd:Res"); - if (!new_res.isNull()) { + if (!new_res.isNull()) + { //读取属性 - if (new_res.hasAttribute("BaseLoc")) { + if (new_res.hasAttribute("BaseLoc")) + { ST_Loc new_baseloc("BaseLoc", new_res.attribute("BaseLoc"), current_path); res_data->base_loc = new_baseloc; - } else { + } + else + { qDebug() << "Res类型数据中缺少必要的BaseLoc属性\n位于" << current_path.getRelativePath(); } //读取成员--font QDomElement t; - if (!(t = new_res.firstChildElement("ofd:Fonts")).isNull()) { + if (!(t = new_res.firstChildElement("ofd:Fonts")).isNull()) + { QDomElement t2 = t.firstChildElement("ofd:Font"); - while (!t2.isNull()) { + while (!t2.isNull()) + { CT_Font * font_data = new CT_Font(); res_data->fonts->push_back(font_data); readFont(font_data, t2); @@ -554,9 +714,11 @@ void OFDParser::readResource(Res * res_data) { } // colorSpaces - if (!(t = new_res.firstChildElement("ofd:ColorSpaces")).isNull()) { + if (!(t = new_res.firstChildElement("ofd:ColorSpaces")).isNull()) + { QDomElement t2 = t.firstChildElement("ofd:ColorSpace"); - while (!t2.isNull()) { + while (!t2.isNull()) + { CT_ColorSpace * colorspace_data = new CT_ColorSpace(); res_data->colorspaces->push_back(colorspace_data); readColorSpace(colorspace_data, t2); @@ -565,9 +727,11 @@ void OFDParser::readResource(Res * res_data) { } // DrawParams - if (!(t = new_res.firstChildElement("ofd:DrawParams")).isNull()) { + if (!(t = new_res.firstChildElement("ofd:DrawParams")).isNull()) + { QDomElement t2 = t.firstChildElement("ofd:DrawParam"); - while (!t2.isNull()) { + while (!t2.isNull()) + { CT_DrawParam * draw_param_data = new CT_DrawParam(); res_data->draw_params->push_back(draw_param_data); readDrawParam(draw_param_data, t2); @@ -576,29 +740,34 @@ void OFDParser::readResource(Res * res_data) { } // MultMedia - if (!(t = new_res.firstChildElement("ofd:MultiMedias")).isNull()) { - qDebug() << "multmedia flag read"; + if (!(t = new_res.firstChildElement("ofd:MultiMedias")).isNull()) + { +// qDebug() << "multmedias flag read"; QDomElement t2 = t.firstChildElement("ofd:MultiMedia"); - while (!t2.isNull()) { + while (!t2.isNull()) + { CT_MultiMedia *multimedia = new CT_MultiMedia(); - // 属性 + // ID if(t2.hasAttribute("ID")) { - ST_ID i(t2.attribute("ID").toInt()); + ST_ID i(t2.attribute("ID").toLong()); +// qDebug() << "multimedia set id"; multimedia->setID(i, id_table); +// qDebug() << "multimedia set id"; } else { qDebug() << "multimedia don't has ID attribute"; continue; } + + // Type if(t2.hasAttribute("Type")) { multimedia->Type = t2.attribute("Type"); - continue; } else { @@ -606,21 +775,24 @@ void OFDParser::readResource(Res * res_data) { continue; } - // 子节点 + // mediaFile QDomElement mediaFile = t2.firstChildElement("ofd:MediaFile"); - multimedia->MediaFile = mediaFile.text(); // 文件路径 - res_data->multMedias.append(multimedia); // 插入 + // 直接转换为了绝对路径 + multimedia->MediaFile = res_data->base_loc + "/" + mediaFile.text(); // 文件路径 + res_data->multMedias->push_back(multimedia); // 插入 - qDebug() << multimedia->getID().getID() - << multimedia->Type - << multimedia->MediaFile; +// qDebug() << multimedia->getID().getID() +// << multimedia->Type +// << multimedia->MediaFile; t2 = t2.nextSiblingElement("ofd:MultiMedia"); } } //Other stuff to be implemented - } else { + } + else + { qDebug() << "Resource.xml文档中缺少必要的Res标签\n位于" << current_path.getRelativePath(); } @@ -630,15 +802,18 @@ void OFDParser::readResource(Res * res_data) { } void OFDParser::readColor(CT_Color *data, QDomElement & root_node) { - if (root_node.hasAttribute("Value")) { + if (root_node.hasAttribute("Value")) + { ST_Array value_data("Value", root_node.attribute("Value")); data->value = value_data; } - if (root_node.hasAttribute("ColorSpace")) { + if (root_node.hasAttribute("ColorSpace")) + { ST_RefID colorspace_data(root_node.attribute("ColorSpace").toInt()); if (id_table->contains(colorspace_data.getRefID())) data->color_space = colorspace_data; - else { + else + { qDebug() << "CT_Color类型数据的ColorSpace属性引用了未注册的ID:" << QString::number(colorspace_data.getRefID()) << " 位于" @@ -646,128 +821,188 @@ void OFDParser::readColor(CT_Color *data, QDomElement & root_node) { } } - if (root_node.hasAttribute("Index")) { + if (root_node.hasAttribute("Index")) + { data->index = root_node.attribute("Index").toInt(); data->index_used = true; } - if (root_node.hasAttribute("Alpha")) { + if (root_node.hasAttribute("Alpha")) + { data->alpha = root_node.attribute("Alpha").toInt(); } //Other stuff to be implemented } -void OFDParser::readFont(CT_Font * data, QDomElement & root_node) { - if (root_node.hasAttribute("ID")) { +void OFDParser::readFont(CT_Font * data, QDomElement & root_node) +{ + if (root_node.hasAttribute("ID")) + { ST_ID i(root_node.attribute("ID").toInt()); data->setID(i, id_table); - } else { + } + else + { qDebug() << "CT_Font类型数据中缺少必要的ID属性\n位于" << current_path.getRelativePath(); } - if (root_node.hasAttribute("FontName")) { + + if (root_node.hasAttribute("FontName")) + { data->font_name = root_node.attribute("FontName"); - } else { + } + else + { qDebug() << "CT_Font类型数据中缺少必要的FontName属性\n位于" << current_path.getRelativePath(); } - if (root_node.hasAttribute("FamilyName")) { + + if (root_node.hasAttribute("FamilyName")) + { data->family_name = root_node.attribute("FamilyName"); } - if (root_node.hasAttribute("Charset")) { + + if (root_node.hasAttribute("Charset")) + { data->charset = root_node.attribute("Charset"); } - if (root_node.hasAttribute("Italic")) { + + if (root_node.hasAttribute("Italic")) + { data->italic = root_node.attribute("Italic") == "true" ? true : false; } - if (root_node.hasAttribute("Bold")) { + + if (root_node.hasAttribute("Bold")) + { data->bold = root_node.attribute("Bold") == "true" ? true : false; - }if (root_node.hasAttribute("Serif")) { + } + + if (root_node.hasAttribute("Serif")) + { data->serif = root_node.attribute("Serif") == "true" ? true : false; } - if (root_node.hasAttribute("FixedWidth")) { + + if (root_node.hasAttribute("FixedWidth")) + { data->fixed_width = root_node.attribute("FixedWidth") == "true" ? true : false; } } -void OFDParser::readColorSpace(CT_ColorSpace * data, QDomElement & root_node) { - if (root_node.hasAttribute("ID")) { +void OFDParser::readColorSpace(CT_ColorSpace * data, QDomElement & root_node) +{ + if (root_node.hasAttribute("ID")) + { ST_ID i(root_node.attribute("ID").toInt()); data->setID(i, id_table); - } else { + } + else + { qDebug() << "CT_ColorSpace类型数据中缺少必要的ID属性\n位于" << current_path.getRelativePath(); } - if (root_node.hasAttribute("Type")) { + + if (root_node.hasAttribute("Type")) + { data->type = root_node.attribute("Type"); - } else { + } + else + { qDebug() << "CT_ColorSpace类型数据中缺少必要的Type属性\n位于" << current_path.getRelativePath(); } - if (root_node.hasAttribute("BitsPerComponent")) { + + if (root_node.hasAttribute("BitsPerComponent")) + { data->bits_per_component = root_node.attribute("BitsPerComponent").toInt(); } - if (root_node.hasAttribute("Profile")) { + + if (root_node.hasAttribute("Profile")) + { ST_Loc p("Profile", root_node.attribute("Profile"), current_path); data->profile = p; } //Some other stuff to be implemented } -void OFDParser::readDrawParam(CT_DrawParam * data, QDomElement & root_node) { - if (root_node.hasAttribute("ID")) { +void OFDParser::readDrawParam(CT_DrawParam * data, QDomElement & root_node) +{ + if (root_node.hasAttribute("ID")) + { ST_ID i(root_node.attribute("ID").toInt()); data->setID(i, id_table); - } else { + } + else + { qDebug() << "CT_DrawParam类型数据中缺少必要的ID属性\n位于" << current_path.getRelativePath(); } - if (root_node.hasAttribute("Relative")) { + + if (root_node.hasAttribute("Relative")) + { ST_RefID i(root_node.attribute("Relative").toInt()); if (id_table->contains(i.getRefID())) data->relative = i; - else { + else + { qDebug() << "CT_DrawParam类型数据的Relative属性引用了未注册的ID 位于" << current_path.getRelativePath(); } } - if (root_node.hasAttribute("LineWidth")) { + + if (root_node.hasAttribute("LineWidth")) + { data->line_width = root_node.attribute("LineWidth").toDouble(); } - if (root_node.hasAttribute("Join")) { + + if (root_node.hasAttribute("Join")) + { QString j = root_node.attribute("Join"); if (j == "Miter" || j == "Round" || j == "Bevel") data->join = j; - else { + else + { qDebug() << "CT_DrawParam类型数据中的Join属性值为非法值\n位于" << current_path.getRelativePath(); } } - if (root_node.hasAttribute("Cap")) { + + if (root_node.hasAttribute("Cap")) + { QString c = root_node.attribute("Cap"); if (c == "Butt" || c == "Round" || c == "Square") data->cap = c; - else { + else + { qDebug() << "CT_DrawParam类型数据中的Cap属性值为非法值\n位于" << current_path.getRelativePath(); } } - if (root_node.hasAttribute("DashOffset")) { + + if (root_node.hasAttribute("DashOffset")) + { data->dash_offset = root_node.attribute("DashOffset").toDouble(); } - if (root_node.hasAttribute("DashPattern")) { + + if (root_node.hasAttribute("DashPattern")) + { ST_Array d("DashPattern", root_node.attribute("DashPattern")); data->dash_pattern = d; } - if (root_node.hasAttribute("MiterLimit")) { + + if (root_node.hasAttribute("MiterLimit")) + { if (data->getJoin() == "Miter") data->miter_limit = root_node.attribute("MiterLimit").toDouble(); } - if (!root_node.firstChildElement("ofd:FillColor").isNull()) { + + if (!root_node.firstChildElement("ofd:FillColor").isNull()) + { CT_Color * fill_color_data = new CT_Color(); delete data->fill_color; data->fill_color = fill_color_data; readColor(fill_color_data, root_node); data->fill_color_used = true; } - if (!root_node.firstChildElement("ofd:StrokeColor").isNull()) { + + if (!root_node.firstChildElement("ofd:StrokeColor").isNull()) + { CT_Color * stroke_color_data = new CT_Color(); delete data->stroke_color; data->stroke_color = stroke_color_data; diff --git a/ofdEditor/ofd/ofd_writer.cpp b/ofdEditor/ofd/ofd_writer.cpp index f7bc239..d94c812 100644 --- a/ofdEditor/ofd/ofd_writer.cpp +++ b/ofdEditor/ofd/ofd_writer.cpp @@ -13,46 +13,59 @@ #include "DataTypes/image/CT_Path.h" #include "DataTypes/image/CT_Image.h" -OFDWriter::OFDWriter(OFD * _data, QString _path) : data(_data), - current_path("OFD", _path + "OFD.xml") { - writeOFD(); +OFDWriter::OFDWriter(OFD * _data, QString _path) + : data(_data), current_path("OFD", _path + "OFD.xml") +{ +// writeOFD(); } -void OFDWriter::createFile() { +void OFDWriter::createFile() +{ current_file = new QFile(current_path.getPath()); qDebug() << current_path.getPath() << endl; - if (!current_file->open(QFile::WriteOnly | QFile::Text)) { + if (!current_file->open(QFile::WriteOnly | QFile::Text)) + { throw WritingFileException("无法打开或创建XML文件: " + current_path.getPath()); } writer.setDevice(current_file); } -void OFDWriter::writeOFD() { +void OFDWriter::writeOFD() +{ createFile(); // qDebug() << "Checkpoint 1"; writer.writeStartDocument(); writer.setAutoFormatting(true); + //进入正文 writer.writeStartElement("ofd:OFD"); writer.writeAttribute("xmlns:ofd", "http://www.ofdspec.org"); QXmlStreamAttributes a = getAttributes(data); writer.writeAttributes(a); + //写DocBody qDebug() << "DocBodys size: "<< data->getDocBodies()->size(); - for (int i = 0; i < data->getDocBodies()->size(); i++) { + for (int i = 0; i < data->getDocBodies()->size(); i++) + { DocBody * cur_docbody = data->getDocBodies()->operator [](i); writer.writeStartElement("ofd:DocBody"); CT_DocInfo * cur_docinfo = cur_docbody->getDocInfo(); writer.writeStartElement("ofd:DocInfo"); + //写DocInfo // qDebug() << "Checkpoint 1.1"; - if (!cur_docinfo->getDocID().isNull()) { + if (!cur_docinfo->getDocID().isNull()) + { writer.writeTextElement("ofd:DocID", cur_docinfo->getDocID()); - } else { - qDebug("DocInfo类型数据缺少必要的成员DocID"); } + else + { + qDebug("DocInfo类型数据缺少必要的成员DocID"); + } + // qDebug() << "Checkpoint 1.2"; - if (!cur_docinfo->getTitle().isNull()) { + if (!cur_docinfo->getTitle().isNull()) + { // qDebug() << "Checkpoint 1.2.1"; cur_docinfo->getTitle(); // qDebug() << "Checkpoint 1.2.1.5"; @@ -60,41 +73,51 @@ void OFDWriter::writeOFD() { // qDebug() << "Checkpoint 1.2.2"; } // qDebug() << "Checkpoint 1.3"; - if (!cur_docinfo->getAuthor().isNull()) { + if (!cur_docinfo->getAuthor().isNull()) + { // qDebug() << "Checkpoint 1.3.1"; writer.writeTextElement("ofd:Author", cur_docinfo->getAuthor()); // qDebug() << "Checkpoint 1.3.2"; } // qDebug() << "Checkpoint 1.4"; - if (!cur_docinfo->getSubject().isNull()) { + if (!cur_docinfo->getSubject().isNull()) + { writer.writeTextElement("ofd:Subject", cur_docinfo->getSubject()); } // qDebug() << "Checkpoint 1.5"; - if (!cur_docinfo->getAbstract().isNull()) { + if (!cur_docinfo->getAbstract().isNull()) + { writer.writeTextElement("ofd:Abstract", cur_docinfo->getAbstract()); } - if (!cur_docinfo->getCreationDate().isNull()) { + if (!cur_docinfo->getCreationDate().isNull()) + { writer.writeTextElement("ofd:CreationDate", cur_docinfo->getCreationDate()); } - if (!cur_docinfo->getModDate().isNull()) { + if (!cur_docinfo->getModDate().isNull()) + { writer.writeTextElement("ofd:ModDate", cur_docinfo->getModDate()); } - if (!cur_docinfo->getDocUsage().isNull()) { + if (!cur_docinfo->getDocUsage().isNull()) + { writer.writeTextElement("ofd:DocUsage", cur_docinfo->getDocUsage()); } //Cover, keywords to be implmented - if (!cur_docinfo->getCreator().isNull()) { + if (!cur_docinfo->getCreator().isNull()) + { writer.writeTextElement("ofd:Creator", cur_docinfo->getCreator()); } - if (!cur_docinfo->getCreatorVersion().isNull()) { + if (!cur_docinfo->getCreatorVersion().isNull()) + { writer.writeTextElement("ofd:CreatorVersion", cur_docinfo->getCreatorVersion()); } // qDebug() << "Checkpoint 1.6"; //写CustomDatas QVector * cur_custom_datas = cur_docinfo->getCustomDatas(); - if (cur_custom_datas->size() != 0) { + if (cur_custom_datas->size() != 0) + { writer.writeStartElement("ofd:CustomDatas"); - for (int i = 0; i < cur_custom_datas->size(); i++) { + for (int i = 0; i < cur_custom_datas->size(); i++) + { writer.writeStartElement("ofd:CustomData"); writer.writeAttribute("Name", cur_custom_datas->at(i).at(0)); writer.writeCharacters(cur_custom_datas->at(i).at(1)); @@ -104,7 +127,8 @@ void OFDWriter::writeOFD() { } writer.writeEndElement(); //写DocRoot - if (!cur_docbody->getDocRoot().isNull()) { + if (!cur_docbody->getDocRoot().isNull()) + { ST_Loc root("", data->getRootPath().getPath().remove("OFD.xml")); writer.writeTextElement("ofd:DocRoot", cur_docbody->getDocRoot().getRelativePath()); qDebug() << "DocRoot :" << cur_docbody->getDocRoot(); @@ -117,9 +141,11 @@ void OFDWriter::writeOFD() { current_file->close(); //修改current_file ST_Loc cur_path = current_path; - for (int i = 0; i < data->getDocBodies()->size(); i++) { + for (int i = 0; i < data->getDocBodies()->size(); i++) + { ST_Loc p("Document", - data->getDocBodies()->at(i)->getDocRoot().getRelativePath(), cur_path); + data->getDocBodies()->at(i)->getDocRoot().getRelativePath(), + cur_path); current_path = p; // qDebug() << "Checkpoint 1.4"; qDebug() << " current Path" @@ -128,9 +154,11 @@ void OFDWriter::writeOFD() { // qDebug() << "Checkpoint 1.5"; writeDocument(data->getDocuments()->operator [](i)); } + qDebug() << "Document write finished"; } -void OFDWriter::writeDocument(Document * data) { +void OFDWriter::writeDocument(Document * data) +{ qDebug() << "writeDocument"; createFile(); // qDebug() << "Checkpoint 2"; @@ -141,40 +169,52 @@ void OFDWriter::writeDocument(Document * data) { writer.writeStartElement("ofd:Document"); writer.writeAttribute("xmlns:ofd", "http://www.ofdspec.org"); //写CommonData - if (data->getCommonData() != NULL) { + if (data->getCommonData() != NULL) + { writer.writeStartElement("ofd:CommonData"); CT_CommonData * cur_common_data = data->getCommonData(); - if (!cur_common_data->getMaxUnitID().isNull()) { + if (!cur_common_data->getMaxUnitID().isNull()) + { writer.writeTextElement("ofd:MaxUnitID", QString::number(cur_common_data->getMaxUnitID().getID())); - } else { + } + else + { // qDebug("CT_CommonData类型数据缺少必要的成员MaxUnitID"); qDebug() << "CT_CommonData类型数据缺少必要的成员MaxUnitID"; } - if (cur_common_data->getPageArea()) { + if (cur_common_data->getPageArea()) + { writer.writeStartElement("ofd:PageArea"); writePageArea(cur_common_data->getPageArea()); writer.writeEndElement(); //ofd:PageArea - } else { + } + else + { // qDebug("CT_CommonData类型数据缺少必要的成员PageArea"); qDebug() << "CT_CommonData类型数据缺少必要的成员PageArea"; } - for (int i = 0; i < data->getCommonData()->getPublicRes()->size(); i++) { + for (int i = 0; i < data->getCommonData()->getPublicRes()->size(); i++) + { ST_Loc p = data->getCommonData()->getPublicRes()->at(i); writer.writeTextElement("ofd:PublicRes", p.getRelativePath()); } //TemplatePage & DefaultCS to be implemented writer.writeEndElement(); //ofd:CommonData - } else { + } + else + { // qDebug("Document类型数据缺少必要的成员CommonData"); qDebug() << "Document类型数据缺少必要的成员CommonData"; } //写Pages - if (data->getPages()) { + if (data->getPages()) + { CT_Pages * cur_pages = data->getPages(); writer.writeStartElement("ofd:Pages"); - for (int i = 0; i < cur_pages->getPages()->size(); i++) { + for (int i = 0; i < cur_pages->getPages()->size(); i++) + { Page * cur_page = cur_pages->getPages()->at(i); writer.writeStartElement("ofd:Page"); writeBase(cur_page); @@ -182,34 +222,39 @@ void OFDWriter::writeDocument(Document * data) { writer.writeEndElement(); } writer.writeEndElement(); //ofd:Pages - } else { -// qDebug("Document类型数据缺少必要的成员Pages"); + } + else + { + // qDebug("Document类型数据缺少必要的成员Pages"); qDebug() << "Document类型数据缺少必要的成员Pages"; } //写CustomTags - if (!data->getCustomTags().isNull()) { + if (!data->getCustomTags().isNull()) + { writer.writeTextElement("ofd:CustomTags", data->getCustomTags().getRelativePath()); } -// qDebug() << "Document main part finished"; + // qDebug() << "Document main part finished"; //Outlines, extensions, annotations to be implemented //正文结束 writer.writeEndDocument(); current_file->close(); ST_Loc cur_path = current_path; - for (int i = 0; i < data->getPages()->getPages()->size(); i++) { + for (int i = 0; i < data->getPages()->getPages()->size(); i++) + { ST_Loc p("Page", data->getPages()->getPages()->operator [](i)-> - getBaseLoc().getRelativePath(), cur_path); -// qDebug() << "Page" << i << " : " -// << data->getPages()->getPages()->operator [](i)->getBaseLoc().getRelativePath(); + getBaseLoc().getRelativePath(), cur_path); + // qDebug() << "Page" << i << " : " + // << data->getPages()->getPages()->operator [](i)->getBaseLoc().getRelativePath(); current_path = p; makePath(current_path); writePage(data->getPages()->getPages()->operator [](i)); } -// qDebug() << "write pages finished"; + // qDebug() << "write pages finished"; qDebug() << "PublicRes size = " << data->getPublicRes()->size(); - for (int i = 0; i < data->getPublicRes()->size(); i++) { + for (int i = 0; i < data->getPublicRes()->size(); i++) + { ST_Loc p("PublicRes", (data->getCommonData()->getPublicRes()->operator [](i)).getRelativePath(), cur_path); @@ -220,11 +265,27 @@ void OFDWriter::writeDocument(Document * data) { writeRes(data->getPublicRes()->operator [](i)); qDebug() << "current res baseloc = " << (data->getPublicRes()->operator [](i))->getBaseLoc(); } -// qDebug() << "write publicRes finished"; + // qDebug() << "write publicRes finished"; + + qDebug() << "DocumentRes size " <document_res->size(); + for (int i = 0; i < data->document_res->size(); i++) + { + ST_Loc p("DocumentRes", + (data->getCommonData()->document_res->operator [](i)).getRelativePath(), + cur_path); + qDebug() << "DocumentRes loc: " << p.getRelativePath(); + current_path = p; + makePath(current_path); + qDebug() << "current path = " << current_path; + writeRes(data->document_res->operator [](i)); + qDebug() << "current res baseloc = " << (data->document_res->operator [](i))->getBaseLoc(); + } + //write CustomTags to be implemented } -void OFDWriter::writePage(Page * data) { +void OFDWriter::writePage(Page * data) +{ createFile(); // qDebug() << "Checkpoint 3"; writer.writeStartDocument(); @@ -234,27 +295,32 @@ void OFDWriter::writePage(Page * data) { writer.writeAttribute("xmlns:ofd", "http://www.ofdspec.org"); //Template to be implemented //写Area - if (data->getArea()) { + if (data->getArea()) + { writer.writeStartElement("ofd:Area"); writePageArea(data->getArea()); writer.writeEndElement(); //ofd:Area } // qDebug() << "Checkpoint 1 reached."; //写PageRes - for (int i = 0; i < data->getPageResLocations()->size(); i++) { + for (int i = 0; i < data->getPageResLocations()->size(); i++) + { ST_Loc p = data->getPageResLocations()->at(i); writer.writeTextElement("ofd:PageRes", p.getRelativePath()); } // qDebug() << "Checkpoint 2 reached."; //写Content - if (data->getContent()->size()) { + if (data->getContent()->size()) + { writer.writeStartElement("ofd:Content"); - for (int i = 0; i < data->getContent()->size(); i++) { + for (int i = 0; i < data->getContent()->size(); i++) + { // qDebug() << data->getContent()->size(); CT_Layer * cur_layer = data->getContent()->operator [](i); if (cur_layer->getImageObject()->size() + cur_layer->getPathObject()->size() +cur_layer->getTextObject()->size() + cur_layer->getPageBlock()->size() - > 0) { + > 0) + { writer.writeStartElement("ofd:Layer"); writeBase(cur_layer); // qDebug() << "Checkpoint 2.1 reached."; @@ -270,7 +336,7 @@ void OFDWriter::writePage(Page * data) { writer.writeEndElement(); //ofd:Content // qDebug() << "????"; } -// qDebug() << "Checkpoint 3 reached."; + // qDebug() << "Checkpoint 3 reached."; //Actions to be implemented writer.writeEndElement(); //ofd:Page //正文结束 @@ -278,59 +344,114 @@ void OFDWriter::writePage(Page * data) { current_file->close(); } -void OFDWriter::writeRes(Res * data) { +void OFDWriter::writeRes(Res * data) +{ createFile(); writer.writeStartDocument(); writer.setAutoFormatting(true); //进入正文 writer.writeStartElement("ofd:Res"); writer.writeAttribute("xmlns:ofd", "http://www.ofdspec.org"); + QString resFloderPath; + //写属性 - if (!data->getBaseLoc().isNull()) { + if (!data->getBaseLoc().isNull()) + { writer.writeAttribute("BaseLoc", data->getBaseLoc().getRelativePath()); - } else { + + resFloderPath = current_path.getPath().left(current_path.getPath().lastIndexOf('/') + 1) + + data->getBaseLoc().getPath(); // 获得绝对路径 + qDebug() << "Res "<< resFloderPath; + + if(!QDir(resFloderPath).exists()) + { + this->makePath(ST_Loc(resFloderPath, + resFloderPath, + resFloderPath)); + } + } + else + { qDebug() << "class Res lack the required attribute baseloc"; -// qDebug("Res类型数据缺少必要的属性BaseLoc"); + // qDebug("Res类型数据缺少必要的属性BaseLoc"); } //写成员 - if (data->getColorSpaces()->size()) { + // colorSpaces + if (data->getColorSpaces()->size()) + { + qDebug() << "Res Save colorspaces"; writer.writeStartElement("ofd:ColorSpaces"); - for (int i = 0; i < data->getColorSpaces()->size(); i++) { - CT_ColorSpace * cur_colorspace = data->getColorSpaces()->at(i); + for (int i = 0; i < data->getColorSpaces()->size(); i++) + { + CT_ColorSpace * cur_colorspace = data->getColorSpaces()->operator [](i); writer.writeStartElement("ofd:ColorSpace"); writeColorSpace(cur_colorspace); writer.writeEndElement(); //ofd:ColorSpace } writer.writeEndElement(); //ofd:ColorSpaces } - if (data->getDrawParams()->size()) { + + // drawParams + if (data->getDrawParams()->size()) + { + qDebug() << "Res save drawparams"; writer.writeStartElement("ofd:DrawParams"); - for (int i = 0; i < data->getDrawParams()->size(); i++) { - CT_DrawParam * cur_draw_param = data->getDrawParams()->at(i); + for (int i = 0; i < data->getDrawParams()->size(); i++) + { + CT_DrawParam * cur_draw_param = data->getDrawParams()->operator [](i); writer.writeStartElement("ofd:DrawParam"); writeDrawParam(cur_draw_param); writer.writeEndElement(); //ofd:DrawParam } writer.writeEndElement(); //ofd:DrawParams } - if (data->getFonts()->size()) { + + // font + if (data->getFonts()->size()) + { + qDebug() << "Res Save fonts"; writer.writeStartElement("ofd:Fonts"); - for (int i = 0; i < data->getFonts()->size(); i++) { - CT_Font * cur_font = data->getFonts()->at(i); + for (int i = 0; i < data->getFonts()->size(); i++) + { + CT_Font * cur_font = data->getFonts()->operator [](i); writer.writeStartElement("ofd:Font"); writeFont(cur_font); writer.writeEndElement(); //ofd:Font } writer.writeEndElement(); //ofd:Fonts } + //MultiMedias & CompositeGraphicUnits to be implemented + if (data->getMultiMedia()->size()) + { + qDebug() << "Res Save multimedia"; + writer.writeStartElement("ofd:MultiMedias"); + for(int i = 0; i < data->getMultiMedia()->size(); i++) + { + CT_MultiMedia* multMedia = data->getMultiMedia()->operator [](i); + writer.writeStartElement("ofd:MultiMedia"); + writeMultiMedia(multMedia); + writer.writeEndElement(); // ofd:MultiMedia + qDebug() << this->tempPath + "/" + multMedia->MediaFile; + qDebug() << current_path.getPath().left(current_path.getPath().lastIndexOf('/') + 1) + + data->getBaseLoc().getRelativePath() + "/" + multMedia->MediaFile; + + // 将图片拷贝过去 + qDebug() << QFile::copy(this->tempPath + "/" + multMedia->MediaFile, + resFloderPath + "/" + multMedia->MediaFile); + } + writer.writeEndElement(); // ofd:MultiMedias + + } + writer.writeEndElement(); //ofd:Res //正文结束 writer.writeEndDocument(); current_file->close(); } -void OFDWriter::writePageArea(CT_PageArea * cur_page_area) { +void OFDWriter::writePageArea(CT_PageArea * cur_page_area) +{ if (!cur_page_area->getPhysicalBox().isNull()) { ST_Box b = cur_page_area->getPhysicalBox(); writer.writeTextElement("ofd:PhysicalBox", @@ -338,10 +459,13 @@ void OFDWriter::writePageArea(CT_PageArea * cur_page_area) { QString::number(b.getY()) + " " + QString::number(b.getDeltaX())+ " " + QString::number(b.getDeltaY())); - } else { - qDebug("CT_PageArea类型数据缺少必要的成员PhysicalBox"); } - if (!cur_page_area->getApplicationBox().isNull()) { + else + { + qDebug("CT_PageArea类型数据缺少必要的成员PhysicalBox"); + } + if (!cur_page_area->getApplicationBox().isNull()) + { ST_Box b = cur_page_area->getApplicationBox(); writer.writeTextElement("ofd:ApplicationBox", QString::number(b.getX()) + " " + @@ -349,7 +473,8 @@ void OFDWriter::writePageArea(CT_PageArea * cur_page_area) { QString::number(b.getDeltaX())+ " " + QString::number(b.getDeltaY())); } - if (!cur_page_area->getContentBox().isNull()) { + if (!cur_page_area->getContentBox().isNull()) + { ST_Box b = cur_page_area->getContentBox(); writer.writeTextElement("ofd:ContentBox", QString::number(b.getX()) + " " + @@ -357,7 +482,8 @@ void OFDWriter::writePageArea(CT_PageArea * cur_page_area) { QString::number(b.getDeltaX())+ " " + QString::number(b.getDeltaY())); } - if (!cur_page_area->getBleedBox().isNull()) { + if (!cur_page_area->getBleedBox().isNull()) + { ST_Box b = cur_page_area->getBleedBox(); writer.writeTextElement("ofd:BleedBox", QString::number(b.getX()) + " " + @@ -367,38 +493,43 @@ void OFDWriter::writePageArea(CT_PageArea * cur_page_area) { } } -void OFDWriter::writePageBlock(CT_PageBlock * cur_page_block, bool is_layer) { +void OFDWriter::writePageBlock(CT_PageBlock * cur_page_block, bool is_layer) +{ if (!is_layer) writeBase(cur_page_block); //文字内容 -// qDebug() << "TextObject: " << cur_page_block->getTextObject()->size(); - for (int i = 0; i < cur_page_block->getTextObject()->size(); i++) { + // qDebug() << "TextObject: " << cur_page_block->getTextObject()->size(); + for (int i = 0; i < cur_page_block->getTextObject()->size(); i++) + { CT_Text * cur_text = cur_page_block->getTextObject()->operator [](i); writer.writeStartElement("ofd:TextObject"); -// qDebug() << "About to write Text Object."; + // qDebug() << "About to write Text Object."; writeTextObject(cur_text); writer.writeEndElement(); //ofd:TextObject } //矢量图内容 -// qDebug() << "PathObject: " << cur_page_block->getPathObject()->size(); - for (int i = 0; i < cur_page_block->getPathObject()->size(); i++) { + // qDebug() << "PathObject: " << cur_page_block->getPathObject()->size(); + for (int i = 0; i < cur_page_block->getPathObject()->size(); i++) + { CT_Path * cur_path = cur_page_block->getPathObject()->operator [](i); writer.writeStartElement("ofd:PathObject"); writePathObject(cur_path); writer.writeEndElement(); //ofd:PathObject } //位图内容 -// qDebug() << "ImageObject: " << cur_page_block->getImageObject()->size(); - for (int i = 0; i < cur_page_block->getImageObject()->size(); i++) { + // qDebug() << "ImageObject: " << cur_page_block->getImageObject()->size(); + for (int i = 0; i < cur_page_block->getImageObject()->size(); i++) + { CT_Image * cur_image = cur_page_block->getImageObject()->operator [](i); writer.writeStartElement("ofd:ImageObject"); writeImageObject(cur_image); writer.writeEndElement(); //ofd:ImageObject } //PageBlock嵌套 -// qDebug() << "PageBlock: " << cur_page_block->getPageBlock()->size(); - for (int i = 0; i < cur_page_block->getPageBlock()->size(); i++) { + // qDebug() << "PageBlock: " << cur_page_block->getPageBlock()->size(); + for (int i = 0; i < cur_page_block->getPageBlock()->size(); i++) + { CT_PageBlock * cur_inner_page_block = cur_page_block->getPageBlock()->operator [](i); writer.writeStartElement("ofd:PageBlock"); writePageBlock(cur_inner_page_block); @@ -406,22 +537,25 @@ void OFDWriter::writePageBlock(CT_PageBlock * cur_page_block, bool is_layer) { } } -void OFDWriter::writeTextObject(CT_Text * cur_text) { +void OFDWriter::writeTextObject(CT_Text * cur_text) +{ writeGraphicUnitAttributes(cur_text); -// qDebug() << "!!!!"; + // qDebug() << "!!!!"; QXmlStreamAttributes a = getAttributes(cur_text); -// qDebug() << "!!!!????"; -// qDebug() << "cur_text->attributes is empty: " << a.isEmpty(); -// for (int i = 0; i < a.size(); i++) -// qDebug() << a.at(i).name() << " " << a.at(i).value(); + // qDebug() << "!!!!????"; + // qDebug() << "cur_text->attributes is empty: " << a.isEmpty(); + // for (int i = 0; i < a.size(); i++) + // qDebug() << a.at(i).name() << " " << a.at(i).value(); writer.writeAttributes(a); -// qDebug() << "Checkpoint 5 reached."; + // qDebug() << "Checkpoint 5 reached."; writeGraphicUnitMemebers(cur_text); -// qDebug() << "Checkpoint 6 reached."; + // qDebug() << "Checkpoint 6 reached."; //CGTransform to be implemented - if (cur_text->getTextCode()) { + if (cur_text->getTextCode()) + { QVector * cur_textcode = cur_text->getTextCode(); - for (int i = 0; i < cur_textcode->size(); i++) { + for (int i = 0; i < cur_textcode->size(); i++) + { writer.writeStartElement("ofd:TextCode"); QXmlStreamAttributes a = getAttributes(cur_textcode->at(i)); writer.writeAttributes(a); @@ -429,50 +563,61 @@ void OFDWriter::writeTextObject(CT_Text * cur_text) { writer.writeEndElement(); //ofd:TextCode } // qDebug() << "Checkpoint 7 reached."; - } else { - qDebug("CT_Text类型数据缺少必要的成员TextObject"); + } + else + { + qDebug("CT_Text类型数据缺少必要的成员TextObject"); } } -void OFDWriter::writePathObject(CT_Path * cur_path) { +void OFDWriter::writePathObject(CT_Path * cur_path) +{ writeGraphicUnitAttributes(cur_path); QXmlStreamAttributes a = getAttributes(cur_path); writer.writeAttributes(a); writeGraphicUnitMemebers(cur_path); // qDebug() << "???"; - if (!cur_path->getAbbreviatedData().isNull()) { + if (!cur_path->getAbbreviatedData().isNull()) + { writer.writeTextElement("ofd:AbbreviatedData", cur_path->getAbbreviatedData()); // qDebug() << "????"; - } else { - qDebug("CT_Path类型数据缺少必要的成员AbbreviatedData"); + } + else + { + qDebug("CT_Path类型数据缺少必要的成员AbbreviatedData"); } } -void OFDWriter::writeImageObject(CT_Image * cur_image) { +void OFDWriter::writeImageObject(CT_Image * cur_image) +{ writeGraphicUnitAttributes(cur_image); QXmlStreamAttributes a = getAttributes(cur_image); writer.writeAttributes(a); writeGraphicUnitMemebers(cur_image); } -void OFDWriter::writeGraphicUnitAttributes(CT_GraphicUnit * cur_graphic_unit) { +void OFDWriter::writeGraphicUnitAttributes(CT_GraphicUnit * cur_graphic_unit) +{ writeBase(cur_graphic_unit); QXmlStreamAttributes a = getAttributes(cur_graphic_unit); writer.writeAttributes(a); } -void OFDWriter::writeGraphicUnitMemebers(CT_GraphicUnit * cur_graphic_unit) { -// qDebug() << "Checkpoint 10 reached."; -// qDebug() << cur_graphic_unit->getID(); -// qDebug() << "Checkpoint 10.1 reached."; - if (cur_graphic_unit->getFillColor()) { +void OFDWriter::writeGraphicUnitMemebers(CT_GraphicUnit * cur_graphic_unit) +{ + // qDebug() << "Checkpoint 10 reached."; + // qDebug() << cur_graphic_unit->getID(); + // qDebug() << "Checkpoint 10.1 reached."; + if (cur_graphic_unit->getFillColor()) + { writer.writeStartElement("ofd:FillColor"); writeColor(cur_graphic_unit->getFillColor()); writer.writeEndElement(); //ofd:FillColor } -// qDebug() << "Checkpoint 11 reached."; - if (cur_graphic_unit->getStrokeColor()) { + // qDebug() << "Checkpoint 11 reached."; + if (cur_graphic_unit->getStrokeColor()) + { qDebug() << "Checkpoint 11.1 reached."; writer.writeStartElement("ofd:StrokeColor"); writeColor(cur_graphic_unit->getStrokeColor()); @@ -482,106 +627,142 @@ void OFDWriter::writeGraphicUnitMemebers(CT_GraphicUnit * cur_graphic_unit) { // qDebug() << "Checkpoint 12 reached."; } -void OFDWriter::writeColor(CT_Color * cur_color) { -// qDebug() << "Checkpoint 20 reached."; +void OFDWriter::writeColor(CT_Color * cur_color) +{ + + // qDebug() << "Checkpoint 20 reached."; // qDebug() << "cur_color = " << cur_color; QXmlStreamAttributes a = getAttributes(cur_color); writer.writeAttributes(a); //Pattern and AxialShd / RadialShd to be implemented } -void OFDWriter::writeBase(CT_Base * cur_base) { +void OFDWriter::writeBase(CT_Base * cur_base) +{ //qDebug() << "Base???"; - if (!cur_base->getID().isNull()) { + if (!cur_base->getID().isNull()) + { writer.writeAttribute("ID", QString::number(cur_base->getID().getID())); - } else { - qDebug("CT_Base类型数据缺少必要的属性ID"); + } + else + { + qDebug("CT_Base类型数据缺少必要的属性ID"); } } -void OFDWriter::writeColorSpace(CT_ColorSpace * cur_colorspace) { +void OFDWriter::writeColorSpace(CT_ColorSpace * cur_colorspace) +{ writeBase(cur_colorspace); QXmlStreamAttributes a = getAttributes(cur_colorspace); writer.writeAttributes(a); //Palette to be implemented } -void OFDWriter::writeDrawParam(CT_DrawParam * cur_draw_param) { +void OFDWriter::writeDrawParam(CT_DrawParam * cur_draw_param) +{ writeBase(cur_draw_param); QXmlStreamAttributes a = getAttributes(cur_draw_param); writer.writeAttributes(a); - if (cur_draw_param->fillColorUsed()) { + if (cur_draw_param->fillColorUsed()) + { writer.writeStartElement("ofd:FillColor"); writeColor(cur_draw_param->getFillColor()); writer.writeEndElement(); //ofd:FillColor } - if (cur_draw_param->strokeColorUsed()) { + if (cur_draw_param->strokeColorUsed()) + { writer.writeStartElement("ofd:StrokeColor"); writeColor(cur_draw_param->getStrokeColor()); writer.writeEndElement(); //ofd:StrokeColor } } -void OFDWriter::writeFont(CT_Font * cur_font) { +void OFDWriter::writeFont(CT_Font * cur_font) +{ + writeBase(cur_font); QXmlStreamAttributes a = getAttributes(cur_font); writer.writeAttributes(a); //FontFile to be implemented } -QXmlStreamAttributes getAttributes(OFD * data) { +void OFDWriter::writeMultiMedia(CT_MultiMedia *cur_multiMedia) +{ + writeBase(cur_multiMedia); + QXmlStreamAttributes a = getAttributes(cur_multiMedia); + writer.writeAttributes(a); +// qDebug() << "writemultimedia finished"; +} + +QXmlStreamAttributes getAttributes(OFD * data) +{ QXmlStreamAttributes a; - if (!data->getDocType().isNull()) { + if (!data->getDocType().isNull()) + { a.append("DocType", data->getDocType()); - } else { - qDebug("OFD类型数据缺少必要的属性DocType"); } - if (!data->getOfdVersion().isNull()) { + else + { + qDebug("OFD类型数据缺少必要的属性DocType"); + } + if (!data->getOfdVersion().isNull()) + { a.append("Version", data->getOfdVersion()); - } else { - qDebug("OFD类型数据缺少必要的属性Version"); + } + else + { + qDebug("OFD类型数据缺少必要的属性Version"); } return a; } -QXmlStreamAttributes getAttributes(CT_Layer * cur_layer) { +QXmlStreamAttributes getAttributes(CT_Layer * cur_layer) +{ QXmlStreamAttributes a; -// if (cur_layer->getType() != "Body") - a.append("Type", cur_layer->getType()); - if (!cur_layer->getDrawParam().isNull()) { + // if (cur_layer->getType() != "Body") + a.append("Type", cur_layer->getType()); + if (!cur_layer->getDrawParam().isNull()) + { a.append("DrawParam",QString::number(cur_layer->getDrawParam().getRefID())); } return a; } -QXmlStreamAttributes getAttributes(CT_GraphicUnit * cur_graphic_unit) { +QXmlStreamAttributes getAttributes(CT_GraphicUnit * cur_graphic_unit) +{ QXmlStreamAttributes a; -// qDebug() << "Boundary is null: " << cur_graphic_unit->getBoundary().isNull(); - if (!cur_graphic_unit->getBoundary().isNull()) { + // qDebug() << "Boundary is null: " << cur_graphic_unit->getBoundary().isNull(); + if (!cur_graphic_unit->getBoundary().isNull()) + { ST_Box b = cur_graphic_unit->getBoundary(); a.append("Boundary", QString::number(b.getX()) + " " + QString::number(b.getY()) + " " + QString::number(b.getDeltaX()) + " " + QString::number(b.getDeltaY())); - } else { - qDebug("CT_GraphicUnit类型数据缺少必要的属性Boundary"); } -// qDebug() << "CT_Graphic Unit Name: " << cur_graphic_unit->getName(); -// qDebug() << "CT_Graphic Unit Name is Null: " << cur_graphic_unit->getName().isNull(); - if (cur_graphic_unit->getName().length() != 0) { + else + { + qDebug("CT_GraphicUnit类型数据缺少必要的属性Boundary"); + } + // qDebug() << "CT_Graphic Unit Name: " << cur_graphic_unit->getName(); + // qDebug() << "CT_Graphic Unit Name is Null: " << cur_graphic_unit->getName().isNull(); + if (cur_graphic_unit->getName().length() != 0) + { a.append("Name", cur_graphic_unit->getName()); } //当Visible为false时才写出 - if (!cur_graphic_unit->getVisible()) { + if (!cur_graphic_unit->getVisible()) + { a.append("Visible", "false"); } //CTM to be implemented - if (!cur_graphic_unit->getDrawParam().isNull()) { + if (!cur_graphic_unit->getDrawParam().isNull()) + { a.append("DrawParam", QString::number(cur_graphic_unit->getDrawParam())); } @@ -590,24 +771,29 @@ QXmlStreamAttributes getAttributes(CT_GraphicUnit * cur_graphic_unit) { } -QXmlStreamAttributes getAttributes(CT_Color *cur_color) { +QXmlStreamAttributes getAttributes(CT_Color *cur_color) +{ QXmlStreamAttributes a; -// qDebug() << "Checkpoint 30 reached."; - if (!cur_color->getValue().isNull()) { -// qDebug() << "Checkpoint 30.1 reached."; + // qDebug() << "Checkpoint 30 reached."; + if (!cur_color->getValue().isNull()) + { + // qDebug() << "Checkpoint 30.1 reached."; a.append("Value", cur_color->getValue().getAllContent()); } -// qDebug() << "Checkpoint 31 reached."; - if (cur_color->indexUsed()) { + // qDebug() << "Checkpoint 31 reached."; + if (cur_color->indexUsed()) + { a.append("Index", QString::number(cur_color->getIndex())); } -// qDebug() << "Checkpoint 32 reached."; - if (!cur_color->getColorSpace().isNull()) { + // qDebug() << "Checkpoint 32 reached."; + if (!cur_color->getColorSpace().isNull()) + { a.append("ColorSpace", QString::number(cur_color->getColorSpace().getRefID())); } //只有当Alpha值为非默认的255时才显示 -// qDebug() << "Checkpoint 33 reached."; - if (cur_color->getAlpha() != 255) { + // qDebug() << "Checkpoint 33 reached."; + if (cur_color->getAlpha() != 255) + { a.append("Alpha", QString::number(cur_color->getAlpha())); } @@ -616,173 +802,242 @@ QXmlStreamAttributes getAttributes(CT_Color *cur_color) { QXmlStreamAttributes getAttributes(CT_Text * cur_text) { -// qDebug() << "??"; + // qDebug() << "??"; QXmlStreamAttributes a; -// qDebug() << "???"; -// qDebug() << "cur_text->getFont().isNull(): " -// <getFont().isNull(); + // qDebug() << "???"; + // qDebug() << "cur_text->getFont().isNull(): " + // <getFont().isNull(); - if (!cur_text->getFont().isNull()) { + if (!cur_text->getFont().isNull()) + { a.append("Font", QString::number(cur_text->getFont().getRefID())); - } else { - qDebug("CT_Text类型数据缺少必要的属性Font"); - } -// qDebug() << "cur_text size used: " << cur_text->sizeUsed(); -// qDebug() << "cur_text size: " << cur_text->getSize(); -// if (cur_text->sizeUsed()) { - a.append("Size", QString::number(cur_text->getSize())); -// } else { -// qDebug() << "CT_Text类型数据缺少必要的属性Size"; -// } + } + else + { + qDebug("CT_Text类型数据缺少必要的属性Font"); + } + // qDebug() << "cur_text size used: " << cur_text->sizeUsed(); + // qDebug() << "cur_text size: " << cur_text->getSize(); + // if (cur_text->sizeUsed()) { + a.append("Size", QString::number(cur_text->getSize())); + // } else { + // qDebug() << "CT_Text类型数据缺少必要的属性Size"; + // } //Stroke属性不为默认值false时才显示 - if (cur_text->getStroke()) { + if (cur_text->getStroke()) + { a.append("Stroke", "true"); } //Fill属性不为默认值true时才显示 - if (!cur_text->getFill()) { + if (!cur_text->getFill()) + { a.append("Fill", "false"); } //HScale属性不为默认值1.0时才显示 - if (abs(cur_text->getHScale() - 1.0) > 0.00000001) { + if (abs(cur_text->getHScale() - 1.0) > 0.00000001) + { a.append("HScale", QString::number(cur_text->getHScale())); } - if (cur_text->getReadDirection() != 0) { + if (cur_text->getReadDirection() != 0) + { a.append("ReadDirection", QString::number(cur_text->getReadDirection())); } - if (cur_text->getWeight() != 400) { + if (cur_text->getWeight() != 400) + { a.append("ReadDirection", QString::number(cur_text->getWeight())); } - if (cur_text->getItalic()) { + if (cur_text->getItalic()) + { a.append("Italic", "true"); } return a; } -QXmlStreamAttributes getAttributes(TextCode * cur_textcode) { +QXmlStreamAttributes getAttributes(TextCode * cur_textcode) +{ QXmlStreamAttributes a; a.append("X", QString::number(cur_textcode->getX())); a.append("Y", QString::number(cur_textcode->getY())); - if (!cur_textcode->getDeltaX().isNull()) { + if (!cur_textcode->getDeltaX().isNull()) + { a.append("DeltaX", cur_textcode->getDeltaX().getAllContent()); } - if (!cur_textcode->getDeltaY().isNull()) { + if (!cur_textcode->getDeltaY().isNull()) + { a.append("DeltaY", cur_textcode->getDeltaY().getAllContent()); } return a; } -QXmlStreamAttributes getAttributes(CT_Path * cur_path) { +QXmlStreamAttributes getAttributes(CT_Path * cur_path) +{ QXmlStreamAttributes a; //Stroke属性为非默认值false时才显示。下同 - if (!cur_path->getStroke()) { + if (!cur_path->getStroke()) + { a.append("Stroke", "false"); } - if (cur_path->getFill()) { + if (cur_path->getFill()) + { a.append("Fill", "true"); } - if (cur_path->getRule() != "NonZero") { + if (cur_path->getRule() != "NonZero") + { a.append("Rule", cur_path->getRule()); } return a; } -QXmlStreamAttributes getAttributes(CT_Image * cur_image) { +QXmlStreamAttributes getAttributes(CT_Image * cur_image) +{ + QXmlStreamAttributes a; - if (!cur_image->getResourceID().isNull()) { + if (!cur_image->getResourceID().isNull()) + { a.append("ResourceID", QString::number(cur_image->getResourceID().getRefID())); - } else { - qDebug("CT_Image类型数据缺少必要的属性ResourceID"); } - if (!cur_image->getSubstitution().isNull()) { + else + { + qDebug("CT_Image类型数据缺少必要的属性ResourceID"); + } + if (!cur_image->getSubstitution().isNull()) + { a.append("Substitution", QString::number(cur_image->getSubstitution().getRefID())); } } -QXmlStreamAttributes getAttributes(CT_ColorSpace * cur_colorspace) { +QXmlStreamAttributes getAttributes(CT_ColorSpace * cur_colorspace) +{ QXmlStreamAttributes a; - if (!cur_colorspace->getType().isNull()) { + if (!cur_colorspace->getType().isNull()) + { a.append("Type", cur_colorspace->getType()); - } else { - qDebug("CT_ColorSpace类型数据缺少必要的属性Type"); } - if (cur_colorspace->getBitsPerComponent() != 8) { + else + { + qDebug("CT_ColorSpace类型数据缺少必要的属性Type"); + } + if (cur_colorspace->getBitsPerComponent() != 8) + { a.append("BitsPerComponent", QString::number(cur_colorspace->getBitsPerComponent())); } -// qDebug() << "Colorspace Profile: " << cur_colorspace->getProfile(); -// qDebug() << "Colorspace Profile abs_path: " << cur_colorspace->getProfile().getPath(); -// qDebug() << "Colorspace Profile is NUll: " << cur_colorspace->getProfile().isNull(); - if (!cur_colorspace->getProfile().isNull()) { + // qDebug() << "Colorspace Profile: " << cur_colorspace->getProfile(); + // qDebug() << "Colorspace Profile abs_path: " << cur_colorspace->getProfile().getPath(); + // qDebug() << "Colorspace Profile is NUll: " << cur_colorspace->getProfile().isNull(); + if (!cur_colorspace->getProfile().isNull()) + { ST_Loc p = cur_colorspace->getProfile(); a.append("Profile", p.getRelativePath()); } return a; } -QXmlStreamAttributes getAttributes(CT_DrawParam * cur_draw_param) { +QXmlStreamAttributes getAttributes(CT_DrawParam * cur_draw_param) +{ QXmlStreamAttributes a; - if (!cur_draw_param->getRelative().isNull()) { + if (!cur_draw_param->getRelative().isNull()) + { ST_RefID p = cur_draw_param->getRelative(); a.append("Relative", QString::number(p.getRefID())); } - if (abs(cur_draw_param->getLineWidth() - 0.353) > 0.0000001) { + if (abs(cur_draw_param->getLineWidth() - 0.353) > 0.0000001) + { a.append("LineWidth", QString::number(cur_draw_param->getLineWidth())); } - if (cur_draw_param->getJoin() != "Miter") { + if (cur_draw_param->getJoin() != "Miter") + { a.append("Join", cur_draw_param->getJoin()); } - if (cur_draw_param->getCap() != "Butt") { + if (cur_draw_param->getCap() != "Butt") + { a.append("Cap", cur_draw_param->getCap()); } - if (abs(cur_draw_param->getDashOffset() - 0.0) > 0.0000001) { + if (abs(cur_draw_param->getDashOffset() - 0.0) > 0.0000001) + { a.append("DashOffset", QString::number(cur_draw_param->getDashOffset())); } - if (!cur_draw_param->getDashPattern().isNull()) { + if (!cur_draw_param->getDashPattern().isNull()) + { a.append("DashPattern", cur_draw_param->getDashPattern().getAllContent()); } - if (abs(cur_draw_param->getMiterLimit() - 3.528) > 0.0000001) { + if (abs(cur_draw_param->getMiterLimit() - 3.528) > 0.0000001) + { a.append("MiterLimit", QString::number(cur_draw_param->getMiterLimit())); } return a; } -QXmlStreamAttributes getAttributes(CT_Font * cur_font) { +QXmlStreamAttributes getAttributes(CT_Font * cur_font) +{ QXmlStreamAttributes a; - if (cur_font->getFontName().length() != 0) { + if (cur_font->getFontName().length() != 0) + { a.append("FontName", cur_font->getFontName()); - } else { - qDebug("CT_Font类型数据缺少必要的属性FontName"); } - if (cur_font->getFamilyName().length() != 0) { + else + { + qDebug("CT_Font类型数据缺少必要的属性FontName"); + } + if (cur_font->getFamilyName().length() != 0) + { a.append("FamilyName", cur_font->getFamilyName()); } - if (cur_font->getCharset() != "GB18030") { + if (cur_font->getCharset() != "GB18030") + { a.append("Charset", cur_font->getCharset()); } - if (cur_font->getItalic()) { + if (cur_font->getItalic()) + { a.append("Italic", "true"); } - if (cur_font->getBold()) { + if (cur_font->getBold()) + { a.append("Bold", "true"); } - if (cur_font->getSerif()) { + if (cur_font->getSerif()) + { a.append("Serif", "true"); } - if (cur_font->getFixedWidth()) { + if (cur_font->getFixedWidth()) + { a.append("FixedWidth", "true"); } return a; } -void OFDWriter::makePath(ST_Loc path) { +void OFDWriter::makePath(ST_Loc path) +{ QString path_str = path.getPath(); int n = 0; while (path_str[path_str.length() - n - 1] != '/') n++; path_str.chop(n); qDebug() << path_str; - if (!QDir().mkpath(path_str)) { + if (!QDir().mkpath(path_str)) + { throw WritingFileException("无法创建文件路径: " + path.getPath()); } } + +QXmlStreamAttributes getAttributes(CT_MultiMedia *cur_multiMedia) +{ + QXmlStreamAttributes a; + if(cur_multiMedia->Format.size() != 0) + { + a.append("Format", cur_multiMedia->Format); + } + + if(cur_multiMedia->Type.size() != 0) + { + a.append("Type" ,cur_multiMedia->Type); + } + + if(cur_multiMedia->MediaFile.size() != 0) + { + a.append("MediaFile",cur_multiMedia->MediaFile); + } + + return a; +} diff --git a/ofdEditor/ofd/ofd_writer.h b/ofdEditor/ofd/ofd_writer.h index 6ea89ea..e38d2c3 100644 --- a/ofdEditor/ofd/ofd_writer.h +++ b/ofdEditor/ofd/ofd_writer.h @@ -24,6 +24,7 @@ class CT_DrawParam; class CT_Font; class Res; class CT_PageArea; +class CT_MultiMedia; class OFDSHARED_EXPORT OFDWriter { @@ -32,9 +33,11 @@ private: ST_Loc current_path; //当前文档节点的路径 QFile * current_file; //当前输出的文件 QXmlStreamWriter writer; + QString tempPath; // 临时文件夹 + void makePath(ST_Loc path); void createFile(); - void writeOFD(); + void writeDocument(Document * data); void writePage(Page * data); void writeRes(Res * data); @@ -44,6 +47,7 @@ private: void writeColor(CT_Color * cur_color); void writeColorSpace(CT_ColorSpace * cur_colorspace); void writeFont(CT_Font * cur_font); + void writeMultiMedia(CT_MultiMedia* cur_multiMedia); void writeDrawParam(CT_DrawParam * cur_draw_param); void writeTextObject(CT_Text * cur_text); void writePathObject(CT_Path * cur_path); @@ -53,6 +57,9 @@ private: void writeBase(CT_Base * cur_base); public: OFDWriter(OFD * _data, QString _path); + void writeOFD(); + void setTempPath(QString tmpPath){ this->tempPath = tmpPath;} + QString getTempPath(){ return this->tempPath; } // 转换时,将临时路径的图片等资源文件拷贝过来 }; QXmlStreamAttributes getAttributes(OFD * data); //返回OFD类型标签的属性,方便书写 @@ -65,4 +72,5 @@ QXmlStreamAttributes getAttributes(CT_ColorSpace * cur_colorspace); QXmlStreamAttributes getAttributes(CT_DrawParam * cur_draw_param); QXmlStreamAttributes getAttributes(CT_Font * cur_font); QXmlStreamAttributes getAttributes(CT_Text * cur_text); +QXmlStreamAttributes getAttributes(CT_MultiMedia* cur_multiMedia); #endif // OFD_WRITER_H diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index e50ec32..bac5f3a 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -734,6 +734,8 @@ void PassageMainWindow::saveFile() QDir dir; dir.mkdir(tempPath); // 生成文件夹 OFDWriter writer(ofdFile, tempPath+"/"); // 写出文件 + writer.setTempPath(passage->getTempSavePath()); // 保存着图片的临时路径 + writer.writeOFD(); ZipTool::compressDir(filePath, tempPath); // 将文件夹压缩为指定文件 @@ -785,6 +787,8 @@ void PassageMainWindow::saveFileAs() dir.mkdir(tempPath); // 生成文件夹 OFDWriter writer(ofdFile, tempPath + "/"); // 写出文件 + writer.setTempPath(passage->getTempSavePath()); + writer.writeOFD(); qDebug() << "temp Files Path:" << tempPath; qDebug() << "selected ofd"<< path; @@ -1385,7 +1389,6 @@ void PassageMainWindow::addRecentFile(DocPassage *passages) ); list->addItem(item); - list->save(); // 保存到文件 } -- Gitee From bf145aa7c817d24733becd0f69abee2c95033775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Tue, 29 Aug 2017 23:37:54 +0800 Subject: [PATCH 61/83] =?UTF-8?q?=E5=9B=BE=E7=89=87=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=E6=9C=89=E6=89=80=E7=BC=93=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/Doc_OFDConvertor.cpp | 1 + ofdEditor/ofd/ofd_writer.cpp | 26 +++++++++++++++----- ofdEditor/ofd/ofd_writer.h | 1 + 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp index 7b04293..cad4c83 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp @@ -490,6 +490,7 @@ void Doc_OFDConvertor::buildImage(CT_Layer *ctLayer, DocImageBlock *imageBlock) this->table); ctimage->setID(this->table->size() + 1, this->table); + ctimage->setResourceID(multiMedia->getID().getID(), this->table); // 设置多媒体引用的标签 multiMedia->Format = "Image"; diff --git a/ofdEditor/ofd/ofd_writer.cpp b/ofdEditor/ofd/ofd_writer.cpp index d94c812..a52c1aa 100644 --- a/ofdEditor/ofd/ofd_writer.cpp +++ b/ofdEditor/ofd/ofd_writer.cpp @@ -25,6 +25,7 @@ void OFDWriter::createFile() qDebug() << current_path.getPath() << endl; if (!current_file->open(QFile::WriteOnly | QFile::Text)) { + qDebug() << "can't open or write file"; throw WritingFileException("无法打开或创建XML文件: " + current_path.getPath()); } writer.setDevice(current_file); @@ -200,6 +201,12 @@ void OFDWriter::writeDocument(Document * data) ST_Loc p = data->getCommonData()->getPublicRes()->at(i); writer.writeTextElement("ofd:PublicRes", p.getRelativePath()); } + + for(int i = 0; i < data->getCommonData()->document_res->size(); i++) + { + ST_Loc p = data->getCommonData()->document_res->operator [](i); + writer.writeTextElement("ofd:DocumentRes", p.getRelativePath()); + } //TemplatePage & DefaultCS to be implemented writer.writeEndElement(); //ofd:CommonData } @@ -360,14 +367,14 @@ void OFDWriter::writeRes(Res * data) writer.writeAttribute("BaseLoc", data->getBaseLoc().getRelativePath()); resFloderPath = current_path.getPath().left(current_path.getPath().lastIndexOf('/') + 1) - + data->getBaseLoc().getPath(); // 获得绝对路径 + + data->getBaseLoc().getPath() + "/"; // 获得绝对路径 qDebug() << "Res "<< resFloderPath; if(!QDir(resFloderPath).exists()) { this->makePath(ST_Loc(resFloderPath, resFloderPath, - resFloderPath)); + "")); } } else @@ -431,6 +438,10 @@ void OFDWriter::writeRes(Res * data) CT_MultiMedia* multMedia = data->getMultiMedia()->operator [](i); writer.writeStartElement("ofd:MultiMedia"); writeMultiMedia(multMedia); + writer.writeStartElement("ofd:MediaFile"); + writer.writeCharacters(multMedia->MediaFile); + writer.writeEndElement(); // mediafile + writer.writeEndElement(); // ofd:MultiMedia qDebug() << this->tempPath + "/" + multMedia->MediaFile; qDebug() << current_path.getPath().left(current_path.getPath().lastIndexOf('/') + 1) @@ -902,10 +913,13 @@ QXmlStreamAttributes getAttributes(CT_Image * cur_image) { qDebug("CT_Image类型数据缺少必要的属性ResourceID"); } + if (!cur_image->getSubstitution().isNull()) { a.append("Substitution", QString::number(cur_image->getSubstitution().getRefID())); } + + return a; } QXmlStreamAttributes getAttributes(CT_ColorSpace * cur_colorspace) @@ -1034,10 +1048,10 @@ QXmlStreamAttributes getAttributes(CT_MultiMedia *cur_multiMedia) a.append("Type" ,cur_multiMedia->Type); } - if(cur_multiMedia->MediaFile.size() != 0) - { - a.append("MediaFile",cur_multiMedia->MediaFile); - } +// if(cur_multiMedia->MediaFile.size() != 0) +// { +// a.append("MediaFile",cur_multiMedia->MediaFile); +// } return a; } diff --git a/ofdEditor/ofd/ofd_writer.h b/ofdEditor/ofd/ofd_writer.h index e38d2c3..a068d84 100644 --- a/ofdEditor/ofd/ofd_writer.h +++ b/ofdEditor/ofd/ofd_writer.h @@ -72,5 +72,6 @@ QXmlStreamAttributes getAttributes(CT_ColorSpace * cur_colorspace); QXmlStreamAttributes getAttributes(CT_DrawParam * cur_draw_param); QXmlStreamAttributes getAttributes(CT_Font * cur_font); QXmlStreamAttributes getAttributes(CT_Text * cur_text); +QXmlStreamAttributes getAttributes(CT_Image * cur_image); QXmlStreamAttributes getAttributes(CT_MultiMedia* cur_multiMedia); #endif // OFD_WRITER_H -- Gitee From 0b93ac3f179f1eb34ea304eb12929f49b59e2bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Wed, 30 Aug 2017 14:38:09 +0800 Subject: [PATCH 62/83] =?UTF-8?q?=E5=87=86=E5=A4=87=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E6=96=87=E5=AD=97=E5=9D=97=E7=9A=84=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/Doc_OFDConvertor.cpp | 65 +++++---- ofdEditor/model/Doc/DocLayer.cpp | 14 -- ofdEditor/model/Doc/DocLayer.h | 3 +- ofdEditor/model/Doc/DocPassage.h | 1 + ofdEditor/model/Doc/DocTextBlock.cpp | 11 +- ofdEditor/ofd/DataTypes/basic_datatype.h | 109 ++++++++++----- .../ofd/DataTypes/image/CT_GraphicUnit.h | 129 +++++++++++------- ofdEditor/ofd/ofd_writer.cpp | 9 ++ ofdEditor/start/ui/PassageMainWindow.cpp | 59 ++++++++ ofdEditor/start/ui/PassageMainWindow.h | 2 + 10 files changed, 268 insertions(+), 134 deletions(-) diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp index cad4c83..02e4438 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp @@ -203,28 +203,37 @@ void Doc_OFDConvertor::buildPage(Page *ctPage, DocPage *docPage) // 分成多个层,对每个层进行处理 DocLayer* foreground = docPage->getForegroundLayer(); // 获得前景层 - CT_Layer* foreLayer = new CT_Layer(); // 处理前景层 - foreLayer->setType("Foreground"); // 设置类型 - foreLayer->setID(this->table->size()+1,this->table); // 设置ID - layers->append(foreLayer); // 加入到Page中 - this->buildLayer(foreLayer,foreground); // 处理该层的信息 - + if(foreground->size() > 0) + { + CT_Layer* foreLayer = new CT_Layer(); // 处理前景层 + foreLayer->setType("Foreground"); // 设置类型 + foreLayer->setID(this->table->size()+1,this->table); // 设置ID + layers->append(foreLayer); // 加入到Page中 + this->buildLayer(foreLayer,foreground); // 处理该层的信息 + } // 处理正文层 DocLayer* body = docPage->getBodyLayer(); - CT_Layer* bodyLayer = new CT_Layer(); - bodyLayer->setType("Body"); - bodyLayer->setID(this->table->size()+1,this->table); - layers->append(bodyLayer); - this->buildLayer(bodyLayer,body); + if(body->size() > 0) + { + CT_Layer* bodyLayer = new CT_Layer(); + bodyLayer->setType("Body"); + bodyLayer->setID(this->table->size()+1,this->table); + layers->append(bodyLayer); + this->buildLayer(bodyLayer,body); + } + // 背景层 DocLayer* background = docPage->getBackgroundLayer(); - CT_Layer* backLayer = new CT_Layer(); - backLayer->setType("Background"); - backLayer->setID(this->table->size()+1,this->table); - layers->append(backLayer); - this->buildLayer(backLayer,background); + if(background->size() > 0) + { + CT_Layer* backLayer = new CT_Layer(); + backLayer->setType("Background"); + backLayer->setID(this->table->size()+1,this->table); + layers->append(backLayer); + this->buildLayer(backLayer,background); + } qDebug() << "build page Finished"; @@ -291,14 +300,12 @@ void Doc_OFDConvertor::buildText(CT_Layer* ctLayer,DocTextBlock *textBlock) cursor.movePosition(QTextCursor::Start); // 移动到文章开头 - - - QString lineContent; // 行内容 - QString lineContent_backup; // 当前行内容备份 - int pixelContent = 0; // 当前行已经使用的像素长度 - int pixelContHeight = 0; // 当前行的最大高度 - int pixelLine = 0; // 当前纵向已经进入的深度 - QString tempFragment; // 块 + QString lineContent; // 行内容 + QString lineContent_backup; // 当前行内容备份 + int pixelContent = 0; // 当前行已经使用的像素长度 + int pixelContHeight = 0; // 当前行的最大高度 + int pixelLine = 0; // 当前纵向已经进入的深度 + QString tempFragment; // 块 QTextFragment fragment; // 短句 // lineCount记录当前处理到的行数,第一行从0开始算起 @@ -381,7 +388,7 @@ void Doc_OFDConvertor::buildText(CT_Layer* ctLayer,DocTextBlock *textBlock) << " pixelHeight:" << pixelHeight; } - CT_Text* ct_text = new CT_Text(); + CT_Text* ct_text = new CT_Text(); // 新建文本块 ct_text->setID(this->table->size() +1 ,this->table); // 设置ID ctLayer->getTextObject()->append(ct_text); // 加入到layer @@ -486,15 +493,15 @@ void Doc_OFDConvertor::buildImage(CT_Layer *ctLayer, DocImageBlock *imageBlock) // 新建所需的对象,设置ID CT_Image *ctimage = new CT_Image(); // iamgeobject CT_MultiMedia *multiMedia = new CT_MultiMedia(); // 多媒体 - multiMedia->setID(this->table->size() + 1, - this->table); ctimage->setID(this->table->size() + 1, this->table); + multiMedia->setID(this->table->size() + 1, + this->table); ctimage->setResourceID(multiMedia->getID().getID(), this->table); // 设置多媒体引用的标签 - multiMedia->Format = "Image"; - multiMedia->Type = "Jpeg"; + multiMedia->Format = ""; + multiMedia->Type = "Image"; multiMedia->MediaFile = imageBlock->getFileName(); // 将图片存储到临时文件夹去 diff --git a/ofdEditor/model/Doc/DocLayer.cpp b/ofdEditor/model/Doc/DocLayer.cpp index 3418945..aa8a3d7 100644 --- a/ofdEditor/model/Doc/DocLayer.cpp +++ b/ofdEditor/model/Doc/DocLayer.cpp @@ -31,20 +31,6 @@ DocLayer::~DocLayer() } this->blocks.clear(); - // 释放表格 - int tables_length = this->tables.size(); - for(int i = 0; i < tables_length; i++) - { - // 挨个释放表格的空间 - DocTable* temp = this->tables.at(i); - if(temp != NULL) - { - delete temp; - (this->tables)[i]=NULL; - } - } - this->tables.clear(); - } /** diff --git a/ofdEditor/model/Doc/DocLayer.h b/ofdEditor/model/Doc/DocLayer.h index 34144f8..ff1062a 100644 --- a/ofdEditor/model/Doc/DocLayer.h +++ b/ofdEditor/model/Doc/DocLayer.h @@ -30,6 +30,7 @@ public: DocPage* getPage(); // 找到层所在的Page DocPassage *getPassage(); // 找到文章 bool hasBlock(DocBlock* block); // 判断是否包含这个块 + int size(){return this->blocks.size();} // 判断层中包含多少个块 public slots: @@ -39,10 +40,8 @@ void removeBlock(DocBlock* block); // 移除Block void setLayer(DocPage::Layer layer){this->type = layer;} void setPage(DocPage* page); // 设置page - private: QVector blocks; // 块 -文字块图形块的父类 - QVector tables; // 表格 DocPage::Layer type; // 共三层 DocPage* parent; // 表明此层是哪一个页面的 diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index 7b16b79..b5262ee 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -56,6 +56,7 @@ public: DocPage* getLastedActivedPage(); // Get last actived page int getLastedActivedPageIndex(); // Get the id of last actived page int getPageIndex(DocPage* page); // 获得页面的序号 + int pageCount(){return this->pages.size();} // 共有多少页面 bool isNeedSave(){return this->isEdited;} // 文档是否被修改,需要保存吗 diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 992cc10..095b4f7 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -950,12 +950,11 @@ void DocTextBlock::initNotUseInSun() */ void DocTextBlock::initFormat() { - QTextCursor cursor = this->textCursor(); // 获得当前光标 - - QTextCharFormat charFormat = cursor.charFormat(); // 字符格式 - charFormat.setVerticalAlignment(QTextCharFormat::AlignMiddle); - - this->mergeCurrentCharFormat(charFormat); + this->document()->setDocumentMargin(0); // 清空文档的边界 + QTextFrameFormat frameFormat = this->document()->rootFrame()->frameFormat(); + frameFormat.setMargin(0); // 设置边缘 + frameFormat.setPadding(0); // 设置留白 + this->document()->rootFrame()->setFrameFormat(frameFormat); // 设置格式 } diff --git a/ofdEditor/ofd/DataTypes/basic_datatype.h b/ofdEditor/ofd/DataTypes/basic_datatype.h index 97e64e9..7897961 100644 --- a/ofdEditor/ofd/DataTypes/basic_datatype.h +++ b/ofdEditor/ofd/DataTypes/basic_datatype.h @@ -9,34 +9,41 @@ #include "../ofdexceptions.h" //6种基本数据类型 -class OFDSHARED_EXPORT ST_Loc { +class OFDSHARED_EXPORT ST_Loc +{ QString title; //该路径的标签,比如资源路径为"Res",页面路径为"Page"(与XML的标签等同) QString abs_path; //绝对路径 QString rela_path; public: ST_Loc(){} ST_Loc(QString tag, QString relative_path, QString current_path) : //构造方法,包括对路径的解析 - title(tag), rela_path(relative_path) { - // qDebug() << "cur = " << current_path << "rela = " << relative_path << endl; + title(tag), rela_path(relative_path) + { + // qDebug() << "cur = " << current_path << "rela = " << relative_path << endl; current_path.replace("\\", "/"); //路径分隔符标准化 - // qDebug() << "cur = " << current_path << endl; - if (relative_path.startsWith("../")) { //从父路径开始 + // qDebug() << "cur = " << current_path << endl; + if (relative_path.startsWith("../")) + { //从父路径开始 int i, cnt = 0; - for (i = current_path.length() - 1; i >= 0; i--) { + for (i = current_path.length() - 1; i >= 0; i--) + { if (current_path[i] == '/') - cnt++; - // qDebug() <<"Cnt = " << cnt << endl; + cnt++; + // qDebug() <<"Cnt = " << cnt << endl; if (cnt == 2) break; } current_path.chop(current_path.length() - i - 1); - // qDebug() <<"chop = " << current_path.length() - i << endl; + // qDebug() <<"chop = " << current_path.length() - i << endl; relative_path.remove(0, 3); - } else { //从当前路径开始 + } + else + { //从当前路径开始 int i, cnt = 0; - for (i = current_path.length() - 1; i >= 0; i--) { + for (i = current_path.length() - 1; i >= 0; i--) + { if (current_path[i] == '/') - cnt++; - // qDebug() <<"Cnt = " << cnt << endl; + cnt++; + // qDebug() <<"Cnt = " << cnt << endl; if (cnt == 1) break; } current_path.chop(current_path.length() - i - 1); //消去当前路径后面的无用内容 @@ -45,34 +52,46 @@ public: else if (relative_path.startsWith("/")) relative_path.remove(0, 1); } - // qDebug() << "cur = " << current_path << "rela = " << relative_path << endl; + // qDebug() << "cur = " << current_path << "rela = " << relative_path << endl; abs_path = current_path + relative_path; } //构造方法,包括对路径的解析 + ST_Loc(QString tag, QString _abs_path) - : title(tag), abs_path(_abs_path) { //构造方法,在直接已有绝对路径时 + : title(tag), abs_path(_abs_path) + { //构造方法,在直接已有绝对路径时 abs_path.replace("\\", "/"); } - operator QString() { //可以直接把ST_Loc作为一个路径字符串使用 + operator QString() + { //可以直接把ST_Loc作为一个路径字符串使用 return abs_path; } - QString getPath() { //返回绝对路径,以“\\”为分隔符 + + QString getPath() + { //返回绝对路径,以“\\”为分隔符 return abs_path; } - QString getRelativePath() { + + QString getRelativePath() + { return rela_path; } - QString getTitle() { //返回当该路径的标签 + QString getTitle() + { //返回当该路径的标签 return title; } - bool isNull() { + bool isNull() + { return abs_path.length() == 0; } }; -class OFDSHARED_EXPORT ST_Array { //以QStringList的形式来实现(因为容器类型的多样性,不如返回QString,具体的类型留给调用者去处理) +class OFDSHARED_EXPORT ST_Array +{ + //以QStringList的形式来实现(因为容器类型的多样性,不如返回QString,具体的类型留给调用者去处理) +public: QString title; QStringList elements; QString all_content; @@ -107,48 +126,59 @@ public: //对QStringList的一些简单封装(在有需要时再拓展接口 }; -class OFDSHARED_EXPORT ST_ID { +class OFDSHARED_EXPORT ST_ID +{ long id; bool is_null; public: - ST_ID() { + + ST_ID() + { is_null = true; id = 0; } - ST_ID(int _id) { + ST_ID(int _id) + { id = _id; is_null = false; } operator long() { return id; } long getID() { return id; } - bool isNull() { + bool isNull() + { return is_null; } }; -class OFDSHARED_EXPORT ST_RefID { +class OFDSHARED_EXPORT ST_RefID +{ long ref_id; bool is_null; public: - ST_RefID() { + ST_RefID() + { is_null = true; ref_id = 0; } - ST_RefID(int _ref_id) { + ST_RefID(int _ref_id) + { ref_id = _ref_id; is_null = false; } operator long() { return ref_id; } long getRefID() { return ref_id; } - bool isNull() { + bool isNull() + { return is_null; } }; -class OFDSHARED_EXPORT ST_Pos { //坐标位置,简单封装即可 +class OFDSHARED_EXPORT ST_Pos +{ + //坐标位置,简单封装即可 double x, y; bool is_null; public: @@ -162,13 +192,15 @@ public: bool isNull() { return is_null; } }; -class OFDSHARED_EXPORT ST_Box { //坐标位置+边长,简单封装即可 +class OFDSHARED_EXPORT ST_Box +{ + //坐标位置+边长,简单封装即可 double start_x, start_y, delta_x, delta_y; bool is_null; public: ST_Box() { is_null = true; start_x = start_y = delta_x = delta_y = 0; } ST_Box(double _start_x, double _start_y, double _delta_x, double _delta_y) : - start_x(_start_x), start_y(_start_y), delta_x(_delta_x), delta_y(_delta_y), is_null(false) {} + start_x(_start_x), start_y(_start_y), delta_x(_delta_x), delta_y(_delta_y), is_null(false) {} double getX() { return start_x; } double getY() { return start_y; } double getDeltaX() { return delta_x; } @@ -182,7 +214,9 @@ public: class CT_Base; -class OFDSHARED_EXPORT ID_Table { //为方便ID的管理,为两者建一个基类 +class OFDSHARED_EXPORT ID_Table +{ + //为方便ID的管理,为两者建一个基类 private: QMap id_pool; //凡是出现过的ID,全都在其中记录 public: @@ -205,15 +239,18 @@ public: bool registerItem(int key, CT_Base * value); //重载 }; -class OFDSHARED_EXPORT CT_Base { //所有含有ID属性的元素的基类 +class OFDSHARED_EXPORT CT_Base +{ //所有含有ID属性的元素的基类 ST_ID id; public: - ST_ID getID() { + ST_ID getID() + { return id; } - void setID(ST_ID new_id, ID_Table * _id_table) { + void setID(ST_ID new_id, ID_Table * _id_table) + { if (_id_table->contains(new_id.getID())) throw InvalidIDException("试图注册重复的ID: " + QString::number(new_id)); id = new_id; diff --git a/ofdEditor/ofd/DataTypes/image/CT_GraphicUnit.h b/ofdEditor/ofd/DataTypes/image/CT_GraphicUnit.h index ab51b9a..6e1bcd2 100644 --- a/ofdEditor/ofd/DataTypes/image/CT_GraphicUnit.h +++ b/ofdEditor/ofd/DataTypes/image/CT_GraphicUnit.h @@ -40,32 +40,37 @@ public: public: friend class OFDParser; - CT_GraphicUnit(double _start_x = 0, - double _start_y = 0, - double _delta_x = 0, - double _delta_y = 0, - QString _name = "", - bool _visible = true, - int _draw_param = 0, - ID_Table * _id_table = NULL, - double _line_width = 0.353, - QString _cap = "Butt", - QString _join = "Miter", - double _miter_limit = 3.528, - double _dash_offset = 0.0, - QString _dash_pattern = "", - int _alpha = 255, - CT_Color * _fill_color = NULL, - CT_Color * _stroke_color = NULL - ) { + CT_GraphicUnit( + double _start_x = 0, + double _start_y = 0, + double _delta_x = 0, + double _delta_y = 0, + QString _name = "", + bool _visible = true, + int _draw_param = 0, + ID_Table * _id_table = NULL, + double _line_width = 0.353, + QString _cap = "Butt", + QString _join = "Miter", + double _miter_limit = 3.528, + double _dash_offset = 0.0, + QString _dash_pattern = "", + int _alpha = 255, + CT_Color * _fill_color = NULL, + CT_Color * _stroke_color = NULL) + { fill_color = NULL; stroke_color = NULL; + if (_start_x || _start_y || _delta_x || _delta_y) setBoundary(_start_x, _start_y, _delta_x, _delta_y); + setName(_name); setVisible(_visible); + if (_draw_param && _id_table) setDrawParam(_draw_param, _id_table); + setLineWidth(_line_width); setCap(_cap); setJoin(_join); @@ -79,54 +84,68 @@ public: } - ST_Box getBoundary() { + ST_Box getBoundary() + { return boundary; } - void setBoundary(double _start_x, double _start_y, double _delta_x, double _delta_y) { + void setBoundary(double _start_x, double _start_y, double _delta_x, double _delta_y) + { ST_Box b(_start_x, _start_y, _delta_x, _delta_y); boundary = b; } - QString getName() { + QString getName() + { return name; } - void setName(QString _name) { + void setName(QString _name) + { name = _name; } - bool getVisible() { + bool getVisible() + { return visible; } - void setVisible(bool _visible) { + void setVisible(bool _visible) + { visible = _visible; } - ST_RefID getDrawParam() { + ST_RefID getDrawParam() + { return draw_param; } - void setDrawParam(int _draw_param, ID_Table * _id_table) { + void setDrawParam(int _draw_param, ID_Table * _id_table) + { if (!_id_table->contains(_draw_param)) - throw InvalidIDException("CT_GraphicUnit对象中的DrawParam属性引用了未注册的ID: " + QString::number(_draw_param)); + throw InvalidIDException("CT_GraphicUnit对象中的DrawParam属性引用了未注册的ID: " + + QString::number(_draw_param)); + ST_RefID rd(_draw_param); draw_param = rd; } - double getLineWidth() { + double getLineWidth() + { return line_width; } - void setLineWidth(double _line_width) { + void setLineWidth(double _line_width) + { line_width = _line_width; } - QString getJoin() { + QString getJoin() + { return join; } - void setJoin(QString _join) { + void setJoin(QString _join) + { QStringList possible_values; possible_values.append("Miter"); possible_values.append("Round"); @@ -137,11 +156,13 @@ public: throw InvalidValueException("CT_GraphicUnit对象的Join属性使用了非法的值: " + _join); } - QString getCap() { + QString getCap() + { return cap; } - void setCap(QString _cap) { + void setCap(QString _cap) + { QStringList possible_values; possible_values.append("Butt"); possible_values.append("Round"); @@ -152,68 +173,82 @@ public: throw InvalidValueException("CT_GraphicUnit对象的Cap属性使用了非法的值: " + _cap); } - double getDashOffset() { + double getDashOffset() + { return dash_offset; } - void setDashOffset(double _dash_offset) { + void setDashOffset(double _dash_offset) + { if (dash_pattern.isNull()) throw InvalidValueException("CT_GraphicUnit对象的DashOffset属性,在DashPattern未出现时设置"); dash_offset = _dash_offset; } - ST_Array getDashPattern() { + ST_Array getDashPattern() + { return dash_pattern; } - void setDashPattern(QString _dash_pattern) { + void setDashPattern(QString _dash_pattern) + { ST_Array a("DashPattern", _dash_pattern); dash_pattern = a; } - double getMiterLimit() { + double getMiterLimit() + { return miter_limit; } - void setMiterLimit(double _miter_limit) { + void setMiterLimit(double _miter_limit) + { if (join != "Miter") throw InvalidValueException("Try to set set MiterLimit in CT_GraphicUnit, when its Join is not Miter"); miter_limit = _miter_limit; } - int getAlpha() { + int getAlpha() + { return alpha; } - void setAlpha(int _alpha) { + void setAlpha(int _alpha) + { if (_alpha < 0 || _alpha > 255) - throw InvalidValueException("CT_GraphicUnit的Alpha属性使用了无效的属性值: " + QString::number(_alpha)); + throw InvalidValueException("CT_GraphicUnit的Alpha属性使用了无效的属性值: " + + QString::number(_alpha)); alpha = _alpha; } - CT_Color * getFillColor() { + CT_Color * getFillColor() + { return fill_color; } - void setFillColor(CT_Color * _fill_color) { + void setFillColor(CT_Color * _fill_color) + { if (_fill_color) { delete fill_color; fill_color = _fill_color; } } - CT_Color * getStrokeColor() { + CT_Color * getStrokeColor() + { return stroke_color; } - void setStrokeColor(CT_Color * _stroke_color) { + void setStrokeColor(CT_Color * _stroke_color) + { if (_stroke_color) { delete stroke_color; stroke_color = _stroke_color; } } - ~CT_GraphicUnit() { + ~CT_GraphicUnit() + { delete fill_color; delete stroke_color; } diff --git a/ofdEditor/ofd/ofd_writer.cpp b/ofdEditor/ofd/ofd_writer.cpp index a52c1aa..7c7f3ff 100644 --- a/ofdEditor/ofd/ofd_writer.cpp +++ b/ofdEditor/ofd/ofd_writer.cpp @@ -919,6 +919,15 @@ QXmlStreamAttributes getAttributes(CT_Image * cur_image) a.append("Substitution", QString::number(cur_image->getSubstitution().getRefID())); } + // 图片对象似乎需要插入CTM + double width = cur_image->boundary.getDeltaX(); + double height = cur_image->boundary.getDeltaY(); + + a.append( + "CTM", + QString::number(width) + " 0 0 " + +QString::number(height) + " 0 0"); + return a; } diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index bac5f3a..5e1f068 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -12,6 +12,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -520,6 +524,10 @@ void PassageMainWindow::connectAction() connect(this->saveAsAction, SIGNAL(triggered(bool)), this,SLOT(saveFileAs())); + // 打印文章 + connect(this->printAction, SIGNAL(triggered(bool)), + this, SLOT(printPassage())); + connect(this->attributeAction, SIGNAL(triggered(bool)), this->connector, SLOT(showAttribute())); // 显示文档属性 @@ -643,6 +651,57 @@ void PassageMainWindow::underline() } } +/// +/// \brief PassageMainWindow::printPassage +/// 弹出打印机设置 +/// +void PassageMainWindow::printPassage() +{ + QPrinter printer(QPrinter::HighResolution); + QPrintDialog printDialog(&printer, this); + + printDialog.setOptions(QAbstractPrintDialog::PrintToFile + | QAbstractPrintDialog::PrintSelection + | QAbstractPrintDialog::PrintPageRange + | QAbstractPrintDialog::PrintShowPageSize + | QAbstractPrintDialog::PrintCollateCopies + | QAbstractPrintDialog::PrintCurrentPage); + + DocPassage* passage = this->activedPassage(); + printDialog.setMinMax(1,passage->pageCount()); + + if(printDialog.exec() == QDialog::Accepted) + { + // 接受打印机设置 -- 全部打印 + printer.setPageSize(QPrinter::A4); + QPainter painterPixmap; + painterPixmap.begin(&printer); + + for(int i =0; i < passage->pageCount(); i++) + { + QPixmap pixmap = QPixmap::grabWidget( + passage->getPage(i)); + + // 调整比例 + QRect rect = painterPixmap.viewport(); + QSize size = passage->getPage(i)->size(); + size.scale(rect.size(), Qt::KeepAspectRatio); //此处保证图片显示完整 + painterPixmap.setViewport(rect.x(), rect.y(), + size.width(), size.height()); + painterPixmap.setWindow(passage->getPage(i)->rect()); + painterPixmap.drawPixmap(0,0,pixmap); + + // 防止多增加一页 + if(i != passage->pageCount() - 1) + printer.newPage(); + + } + + painterPixmap.end(); + + } +} + /** * @Author Chaoqun * @brief 放大函数 diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index e6056c9..880a572 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -53,6 +53,8 @@ public slots: void Italic(); // 斜体事件 void underline(); // 下划线事件 + void printPassage(); // 打印文章 + void zoomIn(); // 放大 void zooomOut(); // 缩小 -- Gitee From 08404eb7fabe2a5ae663a82d9b1405f98a8a590f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Wed, 30 Aug 2017 21:57:44 +0800 Subject: [PATCH 63/83] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E6=9C=89=E6=A0=BC=E5=BC=8F=E7=9A=84=E6=96=87=E6=9C=AC=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/Doc_OFDConvertor.cpp | 141 +++++++++++++++++- ofdEditor/model/Convert/Doc_OFDConvertor.h | 17 ++- .../model/Widget/ParagraphFormatDialog.cpp | 5 + 3 files changed, 159 insertions(+), 4 deletions(-) diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp index 02e4438..63e09bd 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp @@ -263,6 +263,7 @@ void Doc_OFDConvertor::buildLayer(CT_Layer* ctLayer,DocLayer *layer) { // 进入文字框处理模式 this->buildText(ctLayer, block->getTextBlock()); + this->buildTextBlock(ctLayer, block->getTextBlock()); } // 如果是图片对象 @@ -271,6 +272,12 @@ void Doc_OFDConvertor::buildLayer(CT_Layer* ctLayer,DocLayer *layer) // 将图片移动到资源文件夹,存下路径再结束 this->buildImage(ctLayer, block->getImageBlock()); } + + // 如果是表格文件 + if(block->isTableBlock()) + { + // 除了保存文字,还要画线 + } } } @@ -467,7 +474,7 @@ void Doc_OFDConvertor::buildText(CT_Layer* ctLayer,DocTextBlock *textBlock) + QString::number( UnitTool::pixelToMM( metrics.boundingRect( - nextEditContent.operator [](delta_x)).width())); + nextEditContent.mid(delta_x,1)).width())); } textCode->setDeltaX(delta_x_str); } @@ -483,6 +490,138 @@ void Doc_OFDConvertor::buildText(CT_Layer* ctLayer,DocTextBlock *textBlock) } +/// +/// \brief Doc_OFDConvertor::buildTextBlock +/// \param CT_Layer +/// \param textBlock +/// 处理 DocTextBlock 实际相当于计算 QTextEdit中的文本的位置大小 +/// +void Doc_OFDConvertor::buildTextBlock(CT_Layer *CT_Layer, DocTextBlock *textBlock) +{ + DocBlock *block = textBlock->getBlock(); // 获得Block可以获得文本块的总大小 + double block_pos_x = block->x(); + double block_pos_y = block->y(); + double block_width = block->size().width(); + double block_height = block->size().height(); + + int lineCount = 0; // 用来计算共有多少行 + textBlock->moveCursor(QTextCursor::Start); // 将鼠标移动到文档开始 + QTextCursor cursor = textBlock->textCursor(); // 光标 + + // 计算每行的文字的最大高度 + QVector lineHeight_Font; // 每个字体的实际高度 + QVector lineHeight_Real; // 经过段落格式后的高度 + + QVector end_of_line_pos; // 纪录每一行结尾的地方 + QVector start_of_fragment; // 每一个QTextFragment开始的位置 + + QTextBlock::iterator it_fragment = cursor.block().begin(); + + QString tempFragment; + // 一行一行的进行遍历 + while(!cursor.atEnd()) + { + lineCount ++; + cursor.movePosition(QTextCursor::EndOfLine); // 移动到当前行尾,纪录位置 + end_of_line_pos.push_back(cursor.position()); // 将该行的结尾位置发出来 + cursor.movePosition(QTextCursor::Right); + + // 先用每块的字体初始化一下 lineHeight_Font + QTextCharFormat charFormat = cursor.charFormat(); + QFontMetrics fontMetrics(charFormat.font()); + + lineHeight_Font.push_back( + fontMetrics.ascent() + fontMetrics.descent() + fontMetrics.leading() + 1); + } + + QTextFrame::iterator it = textBlock->document()->rootFrame()->begin(); // 遍历rootFrame + while (!it.atEnd()) + { + // QTextBlock + QTextBlock block = it.currentBlock(); // 当前block + qDebug() << "block "<< block.text(); + QTextBlock::iterator block_it = block.begin(); + while(!block_it.atEnd()) + { + // 没有到结尾 + QTextFragment fragment = block_it.fragment(); + start_of_fragment.push_back(fragment.position()); + + // 判断 fragment 影响哪几行的高度 + int lineHeight_fragment = 0; + QFontMetricsF fontMetrics(fragment.charFormat().font()); + lineHeight_fragment = fontMetrics.ascent() + fontMetrics.descent() + fontMetrics.leading() + 1; + + // 利用快的起点和重点,判断影响了哪几行 + int start_pos = fragment.position(); + int end_pos = fragment.position() + fragment.length(); + int start_line = 0; + int end_line = 0; + + for(int line = 0; line < end_of_line_pos.size(); line ++) + { + if(start_pos > end_of_line_pos[line]) + { + start_line = line + 1; + } + + if(end_pos < end_of_line_pos[line]) + { + end_line = line; + break; + } + } + qDebug() << "fragment pos"< lineHeight_Font[line]) + { + lineHeight_Font[line] = lineHeight_fragment; + } + } + + block_it ++; + } // 遍历fragment + it ++; + } // 遍历block + + // 遍历每行,根据行高规则计算行高 + for(int line = 0 ; line < end_of_line_pos.size(); line ++) + { + + } + + qDebug() << "lineCount" << lineCount << endl + << "end of line" << end_of_line_pos << endl + << " start of fragements" << start_of_fragment << endl + << "line height font" << lineHeight_Font << endl; + + +} + +/// +/// \brief Doc_OFDConvertor::buildQTextBlock +/// \param ctlayer +/// \param textBlock +/// \param pos_x +/// \param pos_y +/// \param width +/// \param height +/// 使用提供的大小做为QTextBlock的大小进行处理文本 +/// +void Doc_OFDConvertor::buildQTextBlock( + CT_Layer *ctlayer, + QTextBlock *textBlock, + double pos_x, + double pos_y, + double width, + double height) +{ + +} + /// /// \brief Doc_OFDConvertor::buildImage /// \param ctLayer diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.h b/ofdEditor/model/Convert/Doc_OFDConvertor.h index 80cbb59..7aefa30 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.h +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.h @@ -3,6 +3,7 @@ #include #include "model_global.h" +#include class DocPassage; // 文章 class DocPage; // 页 @@ -48,9 +49,18 @@ private: DocPage* docPage); // 处理其中某一页 void buildLayer(CT_Layer* ctLayer, - DocLayer* layer); // 将一层中的信息存储出来 - void buildText(CT_Layer* ctLayer,DocTextBlock* textBlock); // 将DocTextBlock中的信息转换处理 - void buildImage(CT_Layer* ctLayer, DocImageBlock *imageBlock); // 处理图片 + DocLayer* layer); // 将一层中的信息存储出来 + void buildText(CT_Layer* ctLayer, DocTextBlock* textBlock); // 将DocTextBlock中的信息转换处理 + void buildTextBlock(CT_Layer *CT_Layer, DocTextBlock *textBlock); // 处理文本块,方案二 + void buildQTextBlock( + CT_Layer *ctlayer, + QTextBlock *textBlock, + double pos_x, + double pos_y, + double width, + double height); // 处理一个 QTextBlock + void buildImage(CT_Layer* ctLayer, DocImageBlock *imageBlock); // 处理图片 + int addFont(CT_Font* font); // 添加字体类型到资源 @@ -59,6 +69,7 @@ private: int checkFont(CT_Font* font); // 检查publicRes中是否存在该字体 int checkColorSpace(CT_ColorSpace* colorSpace); // 检查是否存在该颜色空间 + private: DocPassage* passage; // 文章 OFD* ofdFile; // OFD 对象 diff --git a/ofdEditor/model/Widget/ParagraphFormatDialog.cpp b/ofdEditor/model/Widget/ParagraphFormatDialog.cpp index 7b9c5eb..324216e 100644 --- a/ofdEditor/model/Widget/ParagraphFormatDialog.cpp +++ b/ofdEditor/model/Widget/ParagraphFormatDialog.cpp @@ -2,6 +2,7 @@ #include "ui_ParagraphFormatDialog.h" #include "Doc/DocTextBlock.h" +#include ParagraphFormatDialog* ParagraphFormatDialog::m_instance = NULL; // 初始化静态单例 @@ -224,6 +225,10 @@ void ParagraphFormatDialog::init(const QTextBlockFormat &blockFormat) double lineHeightValue = blockFormat.lineHeight(); ui->doubleLineHight->setValue(lineHeightValue); + qDebug() << "LineHeightType" << lineHeightTypes + << "Value" << lineHeightValue; + + } /// -- Gitee From 7c38604c18ceccce17788e0f365ce08bfa41d4d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Wed, 30 Aug 2017 23:29:01 +0800 Subject: [PATCH 64/83] =?UTF-8?q?=E5=A4=A7=E7=BA=A6=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E4=BA=86=E8=A1=8C=E8=B7=9D=E7=9A=84=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/Doc_OFDConvertor.cpp | 46 ++++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp index 63e09bd..7c7dec0 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp @@ -540,10 +540,11 @@ void Doc_OFDConvertor::buildTextBlock(CT_Layer *CT_Layer, DocTextBlock *textBloc // QTextBlock QTextBlock block = it.currentBlock(); // 当前block qDebug() << "block "<< block.text(); + QTextBlock::iterator block_it = block.begin(); while(!block_it.atEnd()) { - // 没有到结尾 + // 遍历QTextFragment QTextFragment fragment = block_it.fragment(); start_of_fragment.push_back(fragment.position()); @@ -572,9 +573,9 @@ void Doc_OFDConvertor::buildTextBlock(CT_Layer *CT_Layer, DocTextBlock *textBloc } } qDebug() << "fragment pos"< lineHeight_Font[line]) { @@ -587,16 +588,53 @@ void Doc_OFDConvertor::buildTextBlock(CT_Layer *CT_Layer, DocTextBlock *textBloc it ++; } // 遍历block + lineHeight_Real = lineHeight_Font; // 复制内容 + // 遍历每行,根据行高规则计算行高 for(int line = 0 ; line < end_of_line_pos.size(); line ++) { + cursor.setPosition(end_of_line_pos[line]); + QTextBlockFormat blockFormat = cursor.blockFormat(); + + int lineHeightType = blockFormat.lineHeightType(); + int lineHeightValue = blockFormat.lineHeight(); + switch (lineHeightType) + { + case QTextBlockFormat::SingleHeight: + // 单倍行距不用改 + break; + case QTextBlockFormat::MinimumHeight: + // 最小值 + if(lineHeight_Font[line] < lineHeightValue) + { + lineHeight_Real[line] = lineHeightValue; + } + else + { + lineHeight_Real[line] = lineHeight_Font[line]; + } + break; + case QTextBlockFormat::FixedHeight: + // 固定值 + lineHeight_Real[line] = lineHeightValue; + break; + case QTextBlockFormat::ProportionalHeight: + // 多倍行距 + lineHeight_Real[line] = (int)(1.0 * lineHeightValue / 100 * lineHeight_Font[line]); + break; + default: + break; + } } qDebug() << "lineCount" << lineCount << endl << "end of line" << end_of_line_pos << endl << " start of fragements" << start_of_fragment << endl - << "line height font" << lineHeight_Font << endl; + << "line height font" << lineHeight_Font << endl + << "line height real" << lineHeight_Real << endl; + + // ---------------- 行高计算完毕,下面应该做啥子 } -- Gitee From d78088d990bd01e355f479d22c419c7e91c03e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Thu, 31 Aug 2017 10:48:18 +0800 Subject: [PATCH 65/83] =?UTF-8?q?=E8=AE=A1=E7=AE=97=E5=9D=97=E7=9A=84?= =?UTF-8?q?=E5=A4=A7=E5=B0=8F=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/Doc_OFDConvertor.cpp | 39 +++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp index 7c7dec0..81e9d4b 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp @@ -513,17 +513,19 @@ void Doc_OFDConvertor::buildTextBlock(CT_Layer *CT_Layer, DocTextBlock *textBloc QVector lineHeight_Real; // 经过段落格式后的高度 QVector end_of_line_pos; // 纪录每一行结尾的地方 + QVector start_of_line_Pos; // 记录每行开始的位置 QVector start_of_fragment; // 每一个QTextFragment开始的位置 - QTextBlock::iterator it_fragment = cursor.block().begin(); - - QString tempFragment; - // 一行一行的进行遍历 + // 一行一行的进行遍历-记录每行的开始位置和行数 while(!cursor.atEnd()) { lineCount ++; + cursor.movePosition(QTextCursor::StartOfLine); // 移动到每行开始的位置 + start_of_line_Pos.push_back(cursor.position()); + cursor.movePosition(QTextCursor::EndOfLine); // 移动到当前行尾,纪录位置 end_of_line_pos.push_back(cursor.position()); // 将该行的结尾位置发出来 + cursor.movePosition(QTextCursor::Right); // 先用每块的字体初始化一下 lineHeight_Font @@ -531,9 +533,13 @@ void Doc_OFDConvertor::buildTextBlock(CT_Layer *CT_Layer, DocTextBlock *textBloc QFontMetrics fontMetrics(charFormat.font()); lineHeight_Font.push_back( - fontMetrics.ascent() + fontMetrics.descent() + fontMetrics.leading() + 1); + fontMetrics.ascent() + + fontMetrics.descent() + + fontMetrics.leading() + 1); + } + // 计算每行的行高---------------------------------------------- QTextFrame::iterator it = textBlock->document()->rootFrame()->begin(); // 遍历rootFrame while (!it.atEnd()) { @@ -588,6 +594,7 @@ void Doc_OFDConvertor::buildTextBlock(CT_Layer *CT_Layer, DocTextBlock *textBloc it ++; } // 遍历block + // 结合行高策略,计算每行的行高--------------------------------------------- lineHeight_Real = lineHeight_Font; // 复制内容 // 遍历每行,根据行高规则计算行高 @@ -634,7 +641,27 @@ void Doc_OFDConvertor::buildTextBlock(CT_Layer *CT_Layer, DocTextBlock *textBloc << "line height font" << lineHeight_Font << endl << "line height real" << lineHeight_Real << endl; - // ---------------- 行高计算完毕,下面应该做啥子 + double current_height = 0; + QTextFrame::iterator it_block = textBlock->document()->rootFrame()->begin(); // 遍历block + while(!it_block.atEnd()) + { + QTextBlock block = it_block.currentBlock(); // 遍历block + QTextBlockFormat blockFormat = block.blockFormat(); // 当前的blockFormat + + if(block != textBlock->document()->firstBlock()) + { + // 如果不是第一个块,要加上上一个块的段前和这一个段的段后 + double last_bottom_margin = block.previous().blockFormat().bottomMargin()+0.5; + double this_top_margin = block.blockFormat().topMargin()+0.5; + current_height = current_height + last_bottom_margin + this_top_margin; + } + + double current_x_start = blockFormat.indent() * textBlock->document()->indentWidth(); + + cursor.setPosition(block.position()); // 将光标移动到块开始的地方 + + } + } -- Gitee From bb59ca9aa147bc9a2731be9fd11652d467176ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Thu, 31 Aug 2017 21:14:37 +0800 Subject: [PATCH 66/83] =?UTF-8?q?=E5=B0=9A=E6=9C=AA=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E9=97=AE=E9=A2=98=EF=BC=8C=E5=85=88=E5=A4=87?= =?UTF-8?q?=E4=BB=BD=E4=B8=80=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/BuildTextBlock.cpp | 358 +++++++++++++++++++ ofdEditor/model/Convert/BuildTextBlock.h | 61 ++++ ofdEditor/model/Convert/Doc_OFDConvertor.cpp | 304 +++++++++++++++- ofdEditor/model/model.pro | 6 +- 4 files changed, 722 insertions(+), 7 deletions(-) create mode 100644 ofdEditor/model/Convert/BuildTextBlock.cpp create mode 100644 ofdEditor/model/Convert/BuildTextBlock.h diff --git a/ofdEditor/model/Convert/BuildTextBlock.cpp b/ofdEditor/model/Convert/BuildTextBlock.cpp new file mode 100644 index 0000000..2aa384a --- /dev/null +++ b/ofdEditor/model/Convert/BuildTextBlock.cpp @@ -0,0 +1,358 @@ +#include "BuildTextBlock.h" +#include "DataTypes/page/CT_Layer.h" + +BuildTextBlock::BuildTextBlock() +{ + +} + +void BuildTextBlock::buildText( + DocTextBlock *textblock, + CT_Layer *layer, + ID_Table *table, + Doc_OFDConvertor *convertor) +{ + this->textBlock = textblock; + this->layer = layer; + this->table = table; + this->convertor = convertor; + + this->caculateLineHeight(); // 先计算行高 + caculateBlockLine(); //计算每块的行数 + caculateLineContentWidth(); +} + +/// +/// \brief BuildTextBlock::caculateLineHeight +/// +void BuildTextBlock::caculateLineHeight() +{ + int lineCount = 0; + this->textBlock->moveCursor(QTextCursor::Start); + QTextCursor cursor = this->textBlock->textCursor(); + + + // 一行一行的进行遍历-记录每行的开始位置和行数 + while(!cursor.atEnd()) + { + lineCount ++; + cursor.movePosition(QTextCursor::StartOfLine); // 移动到每行开始的位置 + this->start_of_line_Pos.push_back(cursor.position()); + +// cursor.select(QTextCursor::LineUnderCursor); +// this->every_line_text.push_back(cursor.selectedText()); +// cursor.movePosition(QTextCursor::NoMove); + + cursor.movePosition(QTextCursor::EndOfLine); // 移动到当前行尾,纪录位置 + this->end_of_line_pos.push_back(cursor.position()); // 将该行的结尾位置发出来 + + + cursor.movePosition(QTextCursor::Right); + + // 先用每块的字体初始化一下 lineHeight_Font + QTextCharFormat charFormat = cursor.charFormat(); + QFontMetrics fontMetrics(charFormat.font()); + + lineHeight_Font.push_back( + fontMetrics.ascent() + + fontMetrics.descent() + + fontMetrics.leading() + 1); + + } + cursor.movePosition(QTextCursor::Start); + while(!cursor.atEnd()) + { + cursor.select(QTextCursor::LineUnderCursor); + this->every_line_text.push_back(cursor.selectedText()); + cursor.movePosition(QTextCursor::Right); + } + + // 计算每行的行高---------------------------------------------- + QTextFrame::iterator it = textBlock->document()->rootFrame()->begin(); // 遍历rootFrame + while (!it.atEnd()) + { + // QTextBlock + QTextBlock block = it.currentBlock(); // 当前block + qDebug() << "block "<< block.text(); + + QTextBlock::iterator block_it = block.begin(); + while(!block_it.atEnd()) + { + // 遍历QTextFragment + QTextFragment fragment = block_it.fragment(); + start_of_fragment.push_back(fragment.position()); + + // 判断 fragment 影响哪几行的高度 + int lineHeight_fragment = 0; + QFontMetricsF fontMetrics(fragment.charFormat().font()); + lineHeight_fragment = fontMetrics.ascent() + fontMetrics.descent() + fontMetrics.leading() + 1; + + // 利用快的起点和重点,判断影响了哪几行 + int start_pos = fragment.position(); + int end_pos = fragment.position() + fragment.length() - 1; + int start_line = 0; + int end_line = 0; + + for(int line = 0; line < end_of_line_pos.size(); line ++) + { + if(start_pos > end_of_line_pos[line]) + { + start_line = line + 1; + } + + if(end_pos < end_of_line_pos[line]) + { + end_line = line; + break; + } + } + qDebug() << "fragment pos"< lineHeight_Font[line]) + { + lineHeight_Font[line] = lineHeight_fragment; + } + } + + block_it ++; + } // 遍历fragment + it ++; + } // 遍历block + + // 结合行高策略,计算每行的行高--------------------------------------------- + lineHeight_Real = lineHeight_Font; // 复制内容 + + // 遍历每行,根据行高规则计算行高 + for(int line = 0 ; line < end_of_line_pos.size(); line ++) + { + cursor.setPosition(end_of_line_pos[line]); + QTextBlockFormat blockFormat = cursor.blockFormat(); + + int lineHeightType = blockFormat.lineHeightType(); + int lineHeightValue = blockFormat.lineHeight(); + + switch (lineHeightType) + { + case QTextBlockFormat::SingleHeight: + // 单倍行距不用改 + break; + case QTextBlockFormat::MinimumHeight: + // 最小值 + if(lineHeight_Font[line] < lineHeightValue) + { + lineHeight_Real[line] = lineHeightValue; + } + else + { + lineHeight_Real[line] = lineHeight_Font[line]; + } + break; + case QTextBlockFormat::FixedHeight: + // 固定值 + lineHeight_Real[line] = lineHeightValue; + break; + case QTextBlockFormat::ProportionalHeight: + // 多倍行距 + lineHeight_Real[line] = (int)(1.0 * lineHeightValue / 100 * lineHeight_Font[line]); + break; + default: + break; + } + } + + qDebug() << "lineCount" << lineCount << endl + << "end of line" << end_of_line_pos << endl + << " start of fragements" << start_of_fragment << endl + << "line height font" << lineHeight_Font << endl + << "line height real" << lineHeight_Real << endl + << "every line text" << every_line_text << endl; + +} + +void BuildTextBlock::caculateBlockLine() +{ + QTextFrame::iterator iter = this->textBlock->document()->rootFrame()->begin(); // 开始的位置 + QTextCursor cursor = this->textBlock->textCursor(); + cursor.movePosition(QTextCursor::Start); + + int blockNum = 0; + while(!iter.atEnd()) + { + QTextBlock block = iter.currentBlock(); + cursor.setPosition(block.position()); + int startPos = cursor.position(); + int startLine = this->start_of_line_Pos.indexOf(startPos); + + cursor.movePosition(QTextCursor::EndOfBlock); + int endLine = this->end_of_line_pos.indexOf(cursor.position()); + + qDebug() << "block" << blockNum + << "startLine" << startLine + << "endLine" << endLine + << "blockNum" << blockNum + << "blockNumber" << block.blockNumber(); + + this->blockStartLineNum.push_back(startLine); + this->blockEndLineNum.push_back(endLine); + + blockNum ++; // 记录块数 + iter ++; + } + + // 计算每一个块开始的位置 + int startY = 0; + blockNum = 0; + double margin = 0; + iter = this->textBlock->document()->rootFrame()->begin(); + while(!iter.atEnd()) + { + // 两个block直接的距离 + if(iter.currentBlock() != this->textBlock->document()->firstBlock()) + { + // 比较Margin + double topMargin = iter.currentBlock().blockFormat().topMargin(); + if(topMargin > margin) + { + margin = topMargin; + } + startY += margin; + } + + this->blockStartY.push_back(startY); // 第一个块从0开始 + this->blockStartX.push_back( + iter.currentBlock().blockFormat().indent() * this->textBlock->document()->indentWidth()); + + double height = 0; + for(int i = this->blockStartLineNum[blockNum]; i <= this->blockEndLineNum[blockNum]; i++) + { + height += lineHeight_Real[i]; + } + + startY += height; // 将行的高度加入到 startY中 + + blockNum ++; + iter++; + } + + qDebug() << "block start Y" << blockStartY + << "block start X" << blockStartX; +} + +/// +/// \brief BuildTextBlock::caculateLineContentWidth +/// +void BuildTextBlock::caculateLineContentWidth() +{ + QTextFrame::iterator iter = this->textBlock->document()->rootFrame()->begin(); // 开始的位置 + int blockNum = 0; + // 循环每个块,循环处理每个语句,来生成这个行宽度的内容 + while(!iter.atEnd()) + { + int currentLine = blockStartLineNum[blockNum]; // 从这行开始 + QString lineContent; // 临时的行内容 + QString fragmentContent; // 临时的片段内容 + QTextBlock::iterator it_fragment = iter.currentBlock().begin(); + QTextFragment fragment = it_fragment.fragment(); + fragmentContent = fragment.text(); + + for(int i = currentLine; i <= blockEndLineNum[blockNum] && !it_fragment.atEnd(); i++) + { + lineContent = every_line_text[i]; + double width = 0; + while(fragmentContent.size() < lineContent.size()) + { + qDebug() << "fragmentContent " << fragmentContent; + + QFontMetricsF fontMetric(fragment.charFormat().font()); + width += fontMetric.boundingRect(fragmentContent).width(); + it_fragment ++; + lineContent.remove(0,fragmentContent.size()); + fragment = it_fragment.fragment(); + fragmentContent = fragment.text(); + + } + + qDebug() << "lineContent" << lineContent; + + QFontMetricsF fontMetirc(fragment.charFormat().font()); + width += fontMetirc.boundingRect(lineContent).width(); + lineWidth_content.push_back(width); + fragmentContent.remove(0,lineContent.size()); + } + + iter ++; + blockNum ++; + } + + qDebug() << "line Width" << lineWidth_content; +} + +/// +/// \brief BuildTextBlock::build +/// +void BuildTextBlock::build() +{ + QTextFrame::iterator iter = this->textBlock->document()->rootFrame()->begin(); // 开始的位置 + int blockNum = 0; + // 循环每个块,循环处理每个语句,来生成这个行宽度的内容 + while(!iter.atEnd()) + { + QTextBlock block = iter.currentBlock(); + QTextBlock::iterator it_fragment = block.begin(); + QTextFragment fragment = it_fragment.fragment(); + QString lineContent; + QString fragmentContent; + double temp_x = 0; + double temp_y = 0; + int currentLine = blockStartLineNum[blockNum]; + + while(currentLine < blockEndLineNum[blockNum] + || !it_fragment.atEnd() + || fragmentContent.size() != 0) + { + if(lineContent.size() == 0) + { + // 如果当前行没内容了 + lineContent = every_line_text[currentLine]; + temp_y += lineHeight_Real[currentLine]; + temp_x = 0; + currentLine ++; + continue; + } + if(fragmentContent.size() == 0) + { + // 如果当前处理的块内容用完了 + fragment = it_fragment.fragment(); + fragmentContent = fragment.text(); + it_fragment ++; + continue; + } + + QString editContent; + if(lineContent.size() <= fragmentContent) + { + editContent = lineContent; + fragmentContent.remove(0,lineContent.size()); + lineContent = ""; + } + else + { + editContent = fragmentContent; + lineContent.remove(0,fragmentContent.size()); + fragmentContent = ""; + } + + } + + + iter++; + blockNum++; + } + + qDebug() << "line Width" << lineWidth_content; +} + + diff --git a/ofdEditor/model/Convert/BuildTextBlock.h b/ofdEditor/model/Convert/BuildTextBlock.h new file mode 100644 index 0000000..9369e4b --- /dev/null +++ b/ofdEditor/model/Convert/BuildTextBlock.h @@ -0,0 +1,61 @@ +#ifndef BUILDTEXTBLOCK_H +#define BUILDTEXTBLOCK_H + +#include "model_global.h" +#include "DataTypes/page/CT_Layer.h" +#include "DataTypes/basic_datatype.h" +#include "DataTypes/text/ct_text.h" +#include "DataTypes/document/Res.h" +#include "DataTypes/text/CT_Font.h" +#include "DataTypes/text/TextCode.h" +#include "Doc/DocTextBlock.h" +#include "Doc/DocBlock.h" +#include "Tool/UnitTool.h" +#include "Doc_OFDConvertor.h" + +#include +#include +#include +#include +#include +#include +#include + +class MODELSHARED_EXPORT BuildTextBlock +{ +public: + BuildTextBlock(); + + void buildText( + DocTextBlock* textblock, + CT_Layer *layer, + ID_Table *table, + Doc_OFDConvertor *convertor); + + void caculateLineHeight(); + void caculateBlockLine(); // 计算每个块开始于第几行,结束于第几行 + void caculateLineContentWidth(); // 计算每行文本所占的文字的宽度 + void build(); // 开始构建真正的内容 + + DocTextBlock *textBlock; + CT_Layer *layer; + ID_Table *table; + Doc_OFDConvertor* convertor; + + QVector lineHeight_Font; // 每个字体的实际高度 + QVector lineHeight_Real; // 经过段落格式后的高度 + QVector end_of_line_pos; // 纪录每一行结尾的地方 + QVector start_of_line_Pos; // 记录每行开始的位置 + QVector start_of_fragment; // 每一个QTextFragment开始的位置 + QVector every_line_text; // 记录每行的文字的内容 + + QVector blockStartLineNum; // 块开始于第几行 + QVector blockEndLineNum; // 块结束于第几行 + + QVector blockStartY; // 每个块从哪个y值开始 + QVector blockStartX; // 每个块从哪个x值开始 + + QVector lineWidth_content; // 某行内容的宽度--通过QFontMetricsF 计算 +}; + +#endif // BUILDTEXTBLOCK_H diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp index 81e9d4b..112c359 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp @@ -5,6 +5,7 @@ #include "Doc/DocTextBlock.h" #include "Doc/DocLayer.h" #include "Doc/DocImageBlock.h" +#include "Convert/BuildTextBlock.h" #include #include @@ -262,8 +263,14 @@ void Doc_OFDConvertor::buildLayer(CT_Layer* ctLayer,DocLayer *layer) if(block->isTextBlock()) { // 进入文字框处理模式 - this->buildText(ctLayer, block->getTextBlock()); - this->buildTextBlock(ctLayer, block->getTextBlock()); +// this->buildText(ctLayer, block->getTextBlock()); +// this->buildTextBlock(ctLayer, block->getTextBlock()); + BuildTextBlock buildTextBlock; + buildTextBlock.buildText( + block->getTextBlock(), + ctLayer, + this->table, + this); } // 如果是图片对象 @@ -504,6 +511,9 @@ void Doc_OFDConvertor::buildTextBlock(CT_Layer *CT_Layer, DocTextBlock *textBloc double block_width = block->size().width(); double block_height = block->size().height(); + qDebug() << "block boundary" + << block_pos_x << block_pos_y << block_width << block_height; + int lineCount = 0; // 用来计算共有多少行 textBlock->moveCursor(QTextCursor::Start); // 将鼠标移动到文档开始 QTextCursor cursor = textBlock->textCursor(); // 光标 @@ -641,13 +651,17 @@ void Doc_OFDConvertor::buildTextBlock(CT_Layer *CT_Layer, DocTextBlock *textBloc << "line height font" << lineHeight_Font << endl << "line height real" << lineHeight_Real << endl; - double current_height = 0; + // 处理----------------------------------------------------------------------------------- + + double current_height = 0; // 当前左上角的位置 + int current_line = -1; // 用来标记当前处理到了第几行 QTextFrame::iterator it_block = textBlock->document()->rootFrame()->begin(); // 遍历block while(!it_block.atEnd()) { QTextBlock block = it_block.currentBlock(); // 遍历block QTextBlockFormat blockFormat = block.blockFormat(); // 当前的blockFormat + // 处理段前段后的问题 if(block != textBlock->document()->firstBlock()) { // 如果不是第一个块,要加上上一个块的段前和这一个段的段后 @@ -656,10 +670,290 @@ void Doc_OFDConvertor::buildTextBlock(CT_Layer *CT_Layer, DocTextBlock *textBloc current_height = current_height + last_bottom_margin + this_top_margin; } - double current_x_start = blockFormat.indent() * textBlock->document()->indentWidth(); + if(block.text().size() ==0) + { + // 因为如果是空行的话,则没有QTextFragment + current_height = current_height + lineHeight_Real[current_line]; + current_line ++; // 行数 +1 + it_block ++; // 进入下一个块 + continue; + } + + // 计算每行的文本宽度 然后根据对齐的规则,可以获得每个字符的额外间距 + //-------------------------------------------------------- + QVector block_line_content_width; // 每行的不计算布局的纯文本的宽度 + QVectorblock_line_content_count; // 每行的文字的数量 + { + QString lineContent; // 行内容 + QString lineContent_backup; // 行内容备份 + QString tempFragment; + QTextFragment fragment; + QTextCursor tempCursor = textBlock->textCursor(); + + QTextBlock::iterator iter = block.begin(); + + while(!iter.atEnd() + || lineContent.size() != 0 + || tempFragment.size() != 0) + { + if(tempFragment.size() == 0 && !iter.atEnd()) + { + // 如果处理字段为空了 + fragment = iter.fragment(); // 获得新的字段 + tempFragment = fragment.text(); // 留存内容 + iter ++; + } + else if(tempFragment.size() == 0 && iter.atEnd()) + { + break; + } + + if(lineContent.size() == 0) + { + // 如果当前行处理完了 + tempCursor.select(QTextCursor::LineUnderCursor); // 选择当前行 + lineContent = tempCursor.selectedText(); + lineContent_backup = lineContent; + + block_line_content_width.push_back(0); + block_line_content_count.push_back(lineContent.size()); + + } + + QString nextEditContent; // 即将处理的字段 + + // 处理当前fragment + if(tempFragment.size() < lineContent.size()) + { + // 当前小块的长度没有达到行的长度 + lineContent.remove(0, tempFragment.length()); + qDebug() << " tempFragment "<< tempFragment ; + + nextEditContent = tempFragment; + tempFragment.remove(0,tempFragment.size()); + + } + else if(tempFragment.size() >= lineContent.size()) + { + // 当前块跨越了好几行 + tempFragment.remove(0,lineContent.size()); + qDebug() << "use remaind lineContent: "<< lineContent; + + nextEditContent = lineContent; + lineContent.remove(0,lineContent.size()); + + } + + QFontMetricsF fontMetrics(fragment.charFormat().font()); + double width = fontMetrics.boundingRect(nextEditContent).width(); + block_line_content_width[block_line_content_width.size() - 1 ] = + block_line_content_width[block_line_content_width.size() - 1 ] + width; + + } + + } + + qDebug() << "blockLine Width" << block_line_content_width; + QVector block_line_space = block_line_content_width; // 每行空白的位置 + QVector block_line_word_space = block_line_content_width; // 每行中空白位置除以每行中每个字的位置 + + for(int i = 0; i < block_line_space.size(); i++) + { + block_line_space[i] = block_width - block_line_content_width[i]; + block_line_word_space[i] = (block_width - block_line_content_width[i]) / (block_line_content_count[i] - 1); + } + + // 处理一般化的块的问题 + double block_indent = blockFormat.indent() * textBlock->document()->indentWidth(); // 整体缩进 + + // 解析文本内容 + //-------------------------------------------------------- + { + QString lineContent; // 行内容 + QString lineContent_backup; // 行内容备份 + int blockLineCount = -1; + QString tempFragment; + QTextFragment fragment; + QTextCursor tempCursor = textBlock->textCursor(); + QTextBlock::iterator iter = block.begin(); + bool blockFirstLine = true; + double current_x = 0; // 填充字符的x值 + current_x = blockFormat.textIndent(); // 初始化为首行缩进 + + while(!iter.atEnd() + || lineContent.size() != 0 + || tempFragment.size() != 0) + { + if(tempFragment.size() == 0 && !iter.atEnd()) + { + // 如果处理字段为空了 + fragment = iter.fragment(); // 获得新的字段 + tempFragment = fragment.text(); // 留存内容 + iter ++; + } + else if(tempFragment.size() == 0 && iter.atEnd()) + break; + + if(lineContent.size() == 0) + { + // 如果当前行处理完了 + tempCursor.select(QTextCursor::LineUnderCursor); // 选择当前行 + lineContent = tempCursor.selectedText(); + lineContent_backup = lineContent; + block_line_content_width.push_back(0); + + // 每到新的一行,设置开始文字位置 + switch(blockFormat.alignment()) + { + case Qt::AlignLeft: + current_x = block_indent; + break; + case Qt::AlignRight: + current_x = block_indent + block_line_space[blockLineCount]; + break; + case Qt::AlignHCenter: + current_x = block_indent + block_line_space[blockLineCount] / 2 ; + break; + case Qt::AlignJustify: + current_x = block_indent; + break; + } + + if(blockFirstLine) // 如果是本段落的第一行 + { + blockFirstLine = false; + current_x += blockFormat.textIndent(); + blockLineCount = 0; + } + if(current_line != 0) + { + current_height += lineHeight_Real[current_line -1]; + } + current_x = block_indent; + current_line ++; + blockLineCount ++; + } + + QString nextEditContent; // 即将处理的字段 + + // 处理当前fragment + if(tempFragment.size() < lineContent.size()) + { + // 当前小块的长度没有达到行的长度 + lineContent.remove(0, tempFragment.length()); + nextEditContent = tempFragment; + tempFragment.remove(0,tempFragment.size()); + + } + else if(tempFragment.size() >= lineContent.size()) + { + // 当前块跨越了好几行 + tempFragment.remove(0,lineContent.size()); + nextEditContent = lineContent; + lineContent.remove(0,lineContent.size()); + + } + + // 样式 + QTextCharFormat charFormat = fragment.charFormat(); // 字符格式 + QTextBlockFormat blockFormat = tempCursor.blockFormat();// 块格式 + QFont font = charFormat.font(); // 字体 + QFontMetrics fontMetics(font); + + // 新建 CT_Text + CT_Text* ct_text = new CT_Text(); // 新建文本块 + ct_text->setID(this->table->size() +1 ,this->table); // 设置ID + CT_Layer->getTextObject()->append(ct_text); // 加入到layer + + // 设置颜色 + QBrush brush = charFormat.foreground(); // 获得画笔 + QColor color = brush.color(); // 获得颜色 + CT_ColorSpace *space = new CT_ColorSpace(); // 颜色空间 + space->setBitsPerComponent(8); + space->setType("RGB"); + int colorSpaceId = this->addColorSpace(space); + CT_Color* ct_color = new CT_Color(); + + ct_color->setValue(QString::number(color.red()) + " " + + QString::number(color.green()) + " " + + QString::number(color.blue())); + ct_color->setColorSpace(colorSpaceId,this->table); + + ct_text->setFillColor(ct_color); + + + // 加入字体 + CT_Font* ctfont = new CT_Font(); + ctfont->setFamilyName(font.family()); + ctfont->setFontName(font.family()); + int font_id = this->addFont(ctfont); // 添加字体ID + ct_text->setFont(font_id, this->table); // 设置字体引用 + + // 设置字体 + if(font.italic()) + { + // 如果斜体 + ct_text->setItalic(true); + } + if(font.weight() != 50) + { + // 字重 + ct_text->setWeight(font.weight() * 8); // 默认值400 + } + + ct_text->setSize( + UnitTool::pixelToMM( + fontMetics.height())); // 设置字体大小 + + ct_text->setBoundary( + UnitTool::pixelToMM(block_pos_x + current_x), + UnitTool::pixelToMM(block_pos_y + current_height), + UnitTool::pixelToMM(block_width), + UnitTool::pixelToMM(lineHeight_Real[lineCount])); - cursor.setPosition(block.position()); // 将光标移动到块开始的地方 + // 设置delta_x + TextCode* textCode = new TextCode(); // 文字内容 + textCode->setText(nextEditContent); // 设置文字内容 + textCode->setX(0); // 设置起始位置 + textCode->setY(UnitTool::pixelToMM(lineHeight_Font[lineCount])); + + if(nextEditContent.length()>1) + { + QString delta_x_str; + // n个字符 n-1 个 delta_x + for(int delta_x = 0; delta_x < nextEditContent.length()-1; delta_x++) + { + + if(blockFormat.alignment() == Qt::AlignJustify) + { + delta_x_str = delta_x_str + " " + + QString::number( + UnitTool::pixelToMM( + fontMetics.boundingRect( + nextEditContent.mid(delta_x,1)).width() + + block_line_word_space[blockLineCount])); + } + else + { + delta_x_str = delta_x_str + " " + + QString::number( + UnitTool::pixelToMM( + fontMetics.boundingRect( + nextEditContent.mid(delta_x,1)).width())); + } + + } + textCode->setDeltaX(delta_x_str); + } + + ct_text->getTextCode()->append(textCode); // 加入到textCode中 + + + } + + } + it_block ++; } diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index 57a700c..782a021 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -55,7 +55,8 @@ SOURCES += model.cpp \ Core/GlobalSetting.cpp \ Widget/InsertPageDialog.cpp \ Widget/TableSettingDialog.cpp \ - Widget/BlockSizeAndPosSettingDialog.cpp + Widget/BlockSizeAndPosSettingDialog.cpp \ + Convert/BuildTextBlock.cpp HEADERS += model.h\ model_global.h \ @@ -90,7 +91,8 @@ HEADERS += model.h\ Widget/DocInfoDialog.h \ Widget/InsertPageDialog.h \ Widget/TableSettingDialog.h \ - Widget/BlockSizeAndPosSettingDialog.h + Widget/BlockSizeAndPosSettingDialog.h \ + Convert/BuildTextBlock.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 -- Gitee From a2f5cf8dc073c19c078a0663b4727380de1584f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Thu, 31 Aug 2017 22:18:23 +0800 Subject: [PATCH 67/83] =?UTF-8?q?=E7=BB=A7=E7=BB=AD=E4=BF=AE=E6=94=B9=20?= =?UTF-8?q?=E6=96=87=E5=AD=97=E5=86=85=E5=AE=B9=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/BuildTextBlock.cpp | 168 ++++++++++++++++++++- ofdEditor/model/Convert/BuildTextBlock.h | 2 + ofdEditor/model/Convert/Doc_OFDConvertor.h | 6 +- 3 files changed, 172 insertions(+), 4 deletions(-) diff --git a/ofdEditor/model/Convert/BuildTextBlock.cpp b/ofdEditor/model/Convert/BuildTextBlock.cpp index 2aa384a..8ee48b7 100644 --- a/ofdEditor/model/Convert/BuildTextBlock.cpp +++ b/ofdEditor/model/Convert/BuildTextBlock.cpp @@ -20,6 +20,7 @@ void BuildTextBlock::buildText( this->caculateLineHeight(); // 先计算行高 caculateBlockLine(); //计算每块的行数 caculateLineContentWidth(); + build(); } /// @@ -301,6 +302,7 @@ void BuildTextBlock::build() while(!iter.atEnd()) { QTextBlock block = iter.currentBlock(); + QTextBlockFormat blockFormat = block.blockFormat(); QTextBlock::iterator it_fragment = block.begin(); QTextFragment fragment = it_fragment.fragment(); QString lineContent; @@ -318,7 +320,16 @@ void BuildTextBlock::build() // 如果当前行没内容了 lineContent = every_line_text[currentLine]; temp_y += lineHeight_Real[currentLine]; - temp_x = 0; + if(currentLine == blockStartLineNum[blockNum]) + { + int indent = blockFormat.indent() * this->textBlock->document()->indentWidth() + + blockFormat.textIndent(); + + temp_x = calculateTemp_x(currentLine,blockFormat.alignment(),indent); + } + else + temp_x = calculateTemp_x(currentLine, blockFormat.alignment(), + blockFormat.indent() * this->textBlock->document()->indentWidth()); currentLine ++; continue; } @@ -332,7 +343,7 @@ void BuildTextBlock::build() } QString editContent; - if(lineContent.size() <= fragmentContent) + if(lineContent.size() <= fragmentContent.size()) { editContent = lineContent; fragmentContent.remove(0,lineContent.size()); @@ -345,6 +356,15 @@ void BuildTextBlock::build() fragmentContent = ""; } + double width =buildSmall_cttext( + editContent, + fragment.charFormat().font(), + this->textBlock->getBlock()->x() + temp_x, + this->textBlock->getBlock()->y() + blockStartY[currentLine] + temp_y, + currentLine, + blockFormat.alignment()); + + temp_x = temp_x + width; } @@ -355,4 +375,148 @@ void BuildTextBlock::build() qDebug() << "line Width" << lineWidth_content; } +double BuildTextBlock::calculateTemp_x(int lineNum, int align, double indent) +{ + double contentWidth = lineWidth_content[lineNum]; + double blockwidth = this->textBlock->getBlock()->size().width(); + + switch (align) { + case Qt::AlignLeft: + // 左对齐的开始位置 + return indent; + break; + case Qt::AlignRight: + return blockwidth - contentWidth; + break; + case Qt::AlignHCenter: + return (blockwidth - contentWidth) / 2.0; + break; + case Qt::AlignJustify: + return indent; + break; + default: + break; + } +} + +/// +/// \brief BuildTextBlock::buildSmall_cttext +/// \param content +/// \param font +/// \param x +/// \param y +/// \param lineNum +/// \param align +/// \return +/// +double BuildTextBlock::buildSmall_cttext( + QString content, QFont font, double x, double y, int lineNum, Qt::Alignment align) +{ + qDebug() <<"build small cttext " <setID(this->table->size() +1, this->table); + this->layer->getTextObject()->append(ct_text); + + CT_Font* ctfont = new CT_Font(); + ctfont->setFamilyName(font.family()); + ctfont->setFontName(font.family()); + int font_id = this->convertor->addFont(ctfont); + ct_text->setFont(font_id, this->table); + + // 设置字体 + if(font.italic()) + { + ct_text->setItalic(true); + } + if(font.weight() != 50) + { + ct_text->setWeight(font.weight() * 8); + } + + QFontMetricsF fontMetrics(font); + + ct_text->setSize( + UnitTool::pixelToMM(fontMetrics.boundingRect(content).height())); + + + double width = 0; + + switch (align) + { + case Qt::AlignLeft: + case Qt::AlignRight: + case Qt::AlignHCenter: + // 左对齐右对齐,居中,字间距不会变 + ct_text->setBoundary( + UnitTool::pixelToMM(x), + UnitTool::pixelToMM(y), + UnitTool::pixelToMM(fontMetrics.boundingRect(content).width() + 10), + UnitTool::pixelToMM(lineHeight_Real[lineNum] + 5)); + + TextCode *txtCode = new TextCode(); // 文字内容 + txtCode->setText(content); + txtCode->setX( + UnitTool::pixelToMM(1)); + txtCode->setY( + UnitTool::pixelToMM(lineHeight_Font[lineNum])); + if(content.size() > 1) + { + QString delta_x; + for(int delta = 0; delta setDeltaX(delta_x); + } + width = fontMetrics.boundingRect(content).width(); + + ct_text->getTextCode()->append(txtCode); + + break; + +// case Qt::AlignJustify: + +// double delta_delta_x = 1.0 * +// (this->textBlock->getBlock()->size().width() - lineWidth_content[lineNum]) +// /( every_line_text[lineNum].size() -1); +// ct_text->setBoundary( +// UnitTool::pixelToMM(x), +// UnitTool::pixelToMM(y), +// UnitTool::pixelToMM(fontMetrics.boundingRect(content).width() +// + content.length() * delta_delta_x), +// UnitTool::pixelToMM(lineHeight_Real[lineNum] + 5)); + +// TextCode *textCode = new TextCode(); // 文字内容 +// textCode->setText(content); +// textCode->setX( +// UnitTool::pixelToMM(1)); +// textCode->setY( +// UnitTool::pixelToMM(lineHeight_Font[lineNum])); + +// if(content.size() > 1) +// { +// QString delta_x; +// for(int delta = 0; delta setDeltaX(delta_x); +// } +// ct_text->getTextCode()->append(txtCode); + +// width = fontMetrics.boundingRect(content).width() + delta_delta_x * content.size(); + +// break; + } + + return width; +} + diff --git a/ofdEditor/model/Convert/BuildTextBlock.h b/ofdEditor/model/Convert/BuildTextBlock.h index 9369e4b..159e49e 100644 --- a/ofdEditor/model/Convert/BuildTextBlock.h +++ b/ofdEditor/model/Convert/BuildTextBlock.h @@ -36,6 +36,8 @@ public: void caculateBlockLine(); // 计算每个块开始于第几行,结束于第几行 void caculateLineContentWidth(); // 计算每行文本所占的文字的宽度 void build(); // 开始构建真正的内容 + double calculateTemp_x(int lineNum, int align, double indent); // 根据现有信息,计算出temp_x + double buildSmall_cttext(QString content, QFont font, double x, double y, int lineNum, Qt::Alignment align); DocTextBlock *textBlock; CT_Layer *layer; diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.h b/ofdEditor/model/Convert/Doc_OFDConvertor.h index 7aefa30..08d175b 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.h +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.h @@ -35,6 +35,10 @@ public: explicit Doc_OFDConvertor(QObject *parent = 0); OFD *doc_to_ofd(DocPassage* passage); // 执行程序入口 + + int addFont(CT_Font* font); // 添加字体类型到资源 + int addColorSpace(CT_ColorSpace* colorSpace); // 添加颜色空间 + signals: public slots: @@ -63,8 +67,6 @@ private: - int addFont(CT_Font* font); // 添加字体类型到资源 - int addColorSpace(CT_ColorSpace* colorSpace); // 添加颜色空间 int checkFont(CT_Font* font); // 检查publicRes中是否存在该字体 int checkColorSpace(CT_ColorSpace* colorSpace); // 检查是否存在该颜色空间 -- Gitee From 37643b2354b853b1406280b5ec887ead17ee0816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Thu, 31 Aug 2017 22:41:54 +0800 Subject: [PATCH 68/83] =?UTF-8?q?=E5=BE=88=E6=9C=89bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/BuildTextBlock.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ofdEditor/model/Convert/BuildTextBlock.cpp b/ofdEditor/model/Convert/BuildTextBlock.cpp index 8ee48b7..2a6ba69 100644 --- a/ofdEditor/model/Convert/BuildTextBlock.cpp +++ b/ofdEditor/model/Convert/BuildTextBlock.cpp @@ -516,6 +516,7 @@ double BuildTextBlock::buildSmall_cttext( // break; } + qDebug() <<"build small cttext " < Date: Fri, 1 Sep 2017 11:32:40 +0800 Subject: [PATCH 69/83] =?UTF-8?q?=E6=96=87=E5=AD=97=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E7=A8=8D=E6=9C=89=E8=BF=9B=E5=B1=95=EF=BC=8C=E4=BD=86=E4=BB=8D?= =?UTF-8?q?=E6=9C=89=E5=BE=88=E5=A4=9A=E9=97=AE=E9=A2=98=E6=9C=89=E5=BE=85?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=EF=BC=8C=E5=8C=85=E6=8B=AC=E7=9B=AE=E5=89=8D?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E7=9A=84=E6=96=87=E4=BB=B6=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E6=89=93=E4=B8=8D=E5=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/BuildTextBlock.cpp | 143 ++++++++++++------- ofdEditor/model/Convert/BuildTextBlock.h | 2 +- ofdEditor/model/Convert/OFD_DocConvertor.cpp | 6 +- ofdEditor/model/Tool/UnitTool.cpp | 5 + ofdEditor/model/Tool/UnitTool.h | 1 + 5 files changed, 101 insertions(+), 56 deletions(-) diff --git a/ofdEditor/model/Convert/BuildTextBlock.cpp b/ofdEditor/model/Convert/BuildTextBlock.cpp index 2a6ba69..52e1617 100644 --- a/ofdEditor/model/Convert/BuildTextBlock.cpp +++ b/ofdEditor/model/Convert/BuildTextBlock.cpp @@ -309,15 +309,22 @@ void BuildTextBlock::build() QString fragmentContent; double temp_x = 0; double temp_y = 0; - int currentLine = blockStartLineNum[blockNum]; + int currentLine = blockStartLineNum[blockNum] - 1; - while(currentLine < blockEndLineNum[blockNum] + while(currentLine <= blockEndLineNum[blockNum] || !it_fragment.atEnd() || fragmentContent.size() != 0) { if(lineContent.size() == 0) { // 如果当前行没内容了 + currentLine ++; + if(currentLine > blockEndLineNum[blockNum]) + { + // 放止因为fragment 而出现问题 + break; + } + lineContent = every_line_text[currentLine]; temp_y += lineHeight_Real[currentLine]; if(currentLine == blockStartLineNum[blockNum]) @@ -330,7 +337,6 @@ void BuildTextBlock::build() else temp_x = calculateTemp_x(currentLine, blockFormat.alignment(), blockFormat.indent() * this->textBlock->document()->indentWidth()); - currentLine ++; continue; } if(fragmentContent.size() == 0) @@ -356,11 +362,14 @@ void BuildTextBlock::build() fragmentContent = ""; } + qDebug() << "Line " << currentLine + << "Deal:" << editContent; + double width =buildSmall_cttext( editContent, - fragment.charFormat().font(), + fragment.charFormat(), this->textBlock->getBlock()->x() + temp_x, - this->textBlock->getBlock()->y() + blockStartY[currentLine] + temp_y, + this->textBlock->getBlock()->y() + blockStartY[blockNum] + temp_y, currentLine, blockFormat.alignment()); @@ -392,6 +401,7 @@ double BuildTextBlock::calculateTemp_x(int lineNum, int align, double indent) return (blockwidth - contentWidth) / 2.0; break; case Qt::AlignJustify: + qDebug() <<"Justify"; return indent; break; default: @@ -410,8 +420,10 @@ double BuildTextBlock::calculateTemp_x(int lineNum, int align, double indent) /// \return /// double BuildTextBlock::buildSmall_cttext( - QString content, QFont font, double x, double y, int lineNum, Qt::Alignment align) + QString content, QTextCharFormat charFormat, double x, double y, int lineNum, Qt::Alignment align) { + QFont font = charFormat.font(); + qDebug() <<"build small cttext " <setWeight(font.weight() * 8); } + // 设置颜色 + QColor color = charFormat.foreground().color(); // 获得颜色 + CT_ColorSpace *space = new CT_ColorSpace(); + space->setBitsPerComponent(8); + space->setType("RGB"); + int colorSpaceId = this->convertor->addColorSpace(space); + CT_Color* ct_color = new CT_Color(); + ct_color->setValue(QString::number(color.red()) + + " " + QString::number(color.green()) + + " " + QString::number(color.blue())); + ct_color->setColorSpace(colorSpaceId,this->table); + QFontMetricsF fontMetrics(font); - ct_text->setSize( - UnitTool::pixelToMM(fontMetrics.boundingRect(content).height())); + // qDebug() << "font pointsize" + // << font.pointSizeF() + // << "font pixel Size" + // << font.pixelSize() << UnitTool::pixelToMM(font.pixelSize()) + // << "pixelToMM" << UnitTool::pixelToMM( + // fontMetrics.ascent() + fontMetrics.descent() + 1) + // << "test" << font.pointSizeF() * 0.35146; + if(font.pointSizeF() != -1) + { + ct_text->setSize( + UnitTool::pointSizeToMM(font.pointSizeF())); + } + else if(font.pixelSize() != -1) + { + ct_text->setSize( + UnitTool::pixelToMM(font.pixelSize())); + } + // ct_text->setSize( + // UnitTool::pixelToMM( + // fontMetrics.ascent() + fontMetrics.descent() + 1)); double width = 0; - switch (align) + + + if(align ==Qt::AlignLeft + || align == Qt::AlignRight + || align == Qt::AlignHCenter) { - case Qt::AlignLeft: - case Qt::AlignRight: - case Qt::AlignHCenter: - // 左对齐右对齐,居中,字间距不会变 ct_text->setBoundary( UnitTool::pixelToMM(x), UnitTool::pixelToMM(y), @@ -457,7 +499,7 @@ double BuildTextBlock::buildSmall_cttext( TextCode *txtCode = new TextCode(); // 文字内容 txtCode->setText(content); txtCode->setX( - UnitTool::pixelToMM(1)); + UnitTool::pixelToMM(0)); txtCode->setY( UnitTool::pixelToMM(lineHeight_Font[lineNum])); if(content.size() > 1) @@ -472,48 +514,45 @@ double BuildTextBlock::buildSmall_cttext( } txtCode->setDeltaX(delta_x); } - width = fontMetrics.boundingRect(content).width(); + width = fontMetrics.boundingRect(content).width(); ct_text->getTextCode()->append(txtCode); + } + else if(align == Qt::AlignJustify) + { + double delta_delta_x = 1.0 * + (this->textBlock->getBlock()->size().width() - lineWidth_content[lineNum]) + /( every_line_text[lineNum].size() -1); - break; + ct_text->setBoundary( + UnitTool::pixelToMM(x), + UnitTool::pixelToMM(y), + UnitTool::pixelToMM(fontMetrics.boundingRect(content).width() + + content.length() * delta_delta_x), + UnitTool::pixelToMM(lineHeight_Real[lineNum] + 5)); + + TextCode *textCode = new TextCode(); // 文字内容 + textCode->setText(content); + textCode->setX( + UnitTool::pixelToMM(1)); + textCode->setY( + UnitTool::pixelToMM(lineHeight_Font[lineNum])); + + if(content.size() > 1) + { + QString delta_x; + for(int delta = 0; delta setDeltaX(delta_x); + } + ct_text->getTextCode()->append(textCode); -// case Qt::AlignJustify: - -// double delta_delta_x = 1.0 * -// (this->textBlock->getBlock()->size().width() - lineWidth_content[lineNum]) -// /( every_line_text[lineNum].size() -1); -// ct_text->setBoundary( -// UnitTool::pixelToMM(x), -// UnitTool::pixelToMM(y), -// UnitTool::pixelToMM(fontMetrics.boundingRect(content).width() -// + content.length() * delta_delta_x), -// UnitTool::pixelToMM(lineHeight_Real[lineNum] + 5)); - -// TextCode *textCode = new TextCode(); // 文字内容 -// textCode->setText(content); -// textCode->setX( -// UnitTool::pixelToMM(1)); -// textCode->setY( -// UnitTool::pixelToMM(lineHeight_Font[lineNum])); - -// if(content.size() > 1) -// { -// QString delta_x; -// for(int delta = 0; delta setDeltaX(delta_x); -// } -// ct_text->getTextCode()->append(txtCode); - -// width = fontMetrics.boundingRect(content).width() + delta_delta_x * content.size(); - -// break; + width = fontMetrics.boundingRect(content).width() + delta_delta_x * content.size(); } qDebug() <<"build small cttext " <buildDocPage(passage, (*pages)[i]); newPage->setVisible(true); } @@ -114,7 +114,7 @@ DocPage *OFD_DocConvertor::buildDocPage(DocPassage *passage, Page *ct_page) for(int i = 0; i < layers->size(); i++) { CT_Layer* layer = (*layers)[i]; -// qDebug() << "excute insertLayer: " << i; + qDebug() << "excute insertLayer: " << i; this->insertLayer(page,layer); // 将该层的内容加入到页面中 } @@ -238,7 +238,7 @@ void OFD_DocConvertor::insertCT_Text(DocPage *page, DocPage::Layer layer, CT_Tex // 处理每一个textCode QVector* textCodes = text->getTextCode(); // 获得文字内容 int length = textCodes->size(); // 数量 -// qDebug() << "textCodes' length:" << length; + qDebug() << "textCodes' length:" << length; for(int i = 0 ; i< length; i++) { TextCode* textCode = (*textCodes)[i]; // 当前处理的块 diff --git a/ofdEditor/model/Tool/UnitTool.cpp b/ofdEditor/model/Tool/UnitTool.cpp index 062fbb5..2eb317b 100644 --- a/ofdEditor/model/Tool/UnitTool.cpp +++ b/ofdEditor/model/Tool/UnitTool.cpp @@ -139,6 +139,11 @@ QRect UnitTool::getBox(QPoint point1, QPoint point2) return QRect(x,y,w,h); } +double UnitTool::pointSizeToMM(double pointsize) +{ + return pointsize * 0.35146; +} + /** * @Author Chaoqun * @brief 判断两个数是否相等,因为公文的误差要求是 1mm, diff --git a/ofdEditor/model/Tool/UnitTool.h b/ofdEditor/model/Tool/UnitTool.h index 7bfc2df..bf00306 100644 --- a/ofdEditor/model/Tool/UnitTool.h +++ b/ofdEditor/model/Tool/UnitTool.h @@ -22,6 +22,7 @@ public: QPointF& point2); // 获得两个点组成的方形 static QRect getBox(QPoint point1, QPoint point2); // 获得两个点组成的方形 + static double pointSizeToMM(double pointsize); // 点大小转换为毫米单位 static bool equal(double a, double b); // 因为double的误差,用来判断两个数是否相等 }; -- Gitee From 789d97c8903798f19bf3f0bd2b8129e8c41aabd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Fri, 1 Sep 2017 21:32:14 +0800 Subject: [PATCH 70/83] =?UTF-8?q?=E6=83=B3=E5=88=B0=E4=BA=86=20=E6=83=B3?= =?UTF-8?q?=E5=88=B0=E4=BA=86=E4=BF=9D=E5=AD=98=E8=A1=A8=E6=A0=BC=E7=9A=84?= =?UTF-8?q?=E4=B8=80=E7=A7=8D=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/BuildTextBlock.cpp | 31 +++++++-- ofdEditor/model/Convert/BuildTextBlock.h | 1 + ofdEditor/model/Convert/BuildTextTable.cpp | 67 ++++++++++++++++++++ ofdEditor/model/Convert/BuildTextTable.h | 50 +++++++++++++++ ofdEditor/model/Convert/Doc_OFDConvertor.cpp | 11 +++- ofdEditor/model/Convert/OFD_DocConvertor.cpp | 14 +++- ofdEditor/model/Convert/OFD_DocConvertor.h | 2 + ofdEditor/model/Doc/DocTable.h | 1 + ofdEditor/model/model.pro | 6 +- ofdEditor/ofd/DataTypes/text/CT_Text.h | 6 +- ofdEditor/ofd/DataTypes/text/ct_text.h | 6 +- ofdEditor/ofd/ofd_parser.cpp | 19 ++++++ ofdEditor/ofd/ofd_writer.cpp | 3 +- 13 files changed, 204 insertions(+), 13 deletions(-) create mode 100644 ofdEditor/model/Convert/BuildTextTable.cpp create mode 100644 ofdEditor/model/Convert/BuildTextTable.h diff --git a/ofdEditor/model/Convert/BuildTextBlock.cpp b/ofdEditor/model/Convert/BuildTextBlock.cpp index 52e1617..7308f14 100644 --- a/ofdEditor/model/Convert/BuildTextBlock.cpp +++ b/ofdEditor/model/Convert/BuildTextBlock.cpp @@ -440,11 +440,10 @@ double BuildTextBlock::buildSmall_cttext( if(font.italic()) { ct_text->setItalic(true); + qDebug() << "italic -------------------------------------"; } - if(font.weight() != 50) - { - ct_text->setWeight(font.weight() * 8); - } + // 设置字重 + ct_text->setWeight(this->getWeight(font.weight())); // 设置颜色 QColor color = charFormat.foreground().color(); // 获得颜色 @@ -457,6 +456,7 @@ double BuildTextBlock::buildSmall_cttext( + " " + QString::number(color.green()) + " " + QString::number(color.blue())); ct_color->setColorSpace(colorSpaceId,this->table); + ct_text->setFillColor(ct_color); QFontMetricsF fontMetrics(font); @@ -511,6 +511,10 @@ double BuildTextBlock::buildSmall_cttext( + QString::number( UnitTool::pixelToMM( fontMetrics.boundingRect(content.mid(delta,1)).width())); +// delta_x = delta_x + " " +// + QString::number( +// UnitTool::pixelToMM( +// fontMetrics.maxWidth())); } txtCode->setDeltaX(delta_x); } @@ -560,3 +564,22 @@ double BuildTextBlock::buildSmall_cttext( } +/// +/// \brief BuildTextBlock::getWeight +/// 将 +/// \param width +/// \return +/// +int BuildTextBlock::getWeight(double weight) +{ + if( weight < 63 ) + { + return 400; + } + else + { + return 500; + } +} + + diff --git a/ofdEditor/model/Convert/BuildTextBlock.h b/ofdEditor/model/Convert/BuildTextBlock.h index f64d664..bc49ed6 100644 --- a/ofdEditor/model/Convert/BuildTextBlock.h +++ b/ofdEditor/model/Convert/BuildTextBlock.h @@ -38,6 +38,7 @@ public: void build(); // 开始构建真正的内容 double calculateTemp_x(int lineNum, int align, double indent); // 根据现有信息,计算出temp_x double buildSmall_cttext(QString content, QTextCharFormat charFormat, double x, double y, int lineNum, Qt::Alignment align); + int getWeight(double width); // 将Qt中的字重转换为ofd的字重 DocTextBlock *textBlock; CT_Layer *layer; diff --git a/ofdEditor/model/Convert/BuildTextTable.cpp b/ofdEditor/model/Convert/BuildTextTable.cpp new file mode 100644 index 0000000..3c85104 --- /dev/null +++ b/ofdEditor/model/Convert/BuildTextTable.cpp @@ -0,0 +1,67 @@ +#include "BuildTextTable.h" + +#include "Doc_OFDConvertor.h" +#include "Doc/DocPassage.h" +#include "Doc/DocPage.h" +#include "Doc/DocBlock.h" +#include "Doc/DocTextBlock.h" +#include "Doc/DocLayer.h" +#include "Doc/DocImageBlock.h" +#include "Doc/DocTable.h" +#include "Convert/BuildTextBlock.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DataTypes/basic_datatype.h" +#include "DataTypes/document/ofd.h" +#include "DataTypes/document/Res.h" +#include "DataTypes/document/docbody.h" +#include "DataTypes/document/ct_docinfo.h" +#include "DataTypes/document/document.h" +#include "DataTypes/page/ct_pages.h" +#include "DataTypes/page/page.h" +#include "DataTypes/page/ct_layer.h" +#include "DataTypes/page/CT_PageArea.h" +#include "DataTypes/Color/CT_Color.h" +#include "DataTypes/Color/CT_ColorSpace.h" +#include "DataTypes/text/CT_Font.h" +#include "DataTypes/text/ct_text.h" +#include "DataTypes/text/textcode.h" +#include "DataTypes/basic_datatype.h" +#include "Tool/UnitTool.h" +#include "DataTypes/image/CT_Image.h" +#include "DataTypes/image/CT_MultiMedia.h" + +BuildTextTable::BuildTextTable() +{ + +} + +/// +/// \brief BuildTextTable::buildTable +/// \param table_block +/// \param layer +/// \param id_table +/// \param convertor +/// +void BuildTextTable::buildTable( + DocTable *table_block, CT_Layer *layer, ID_Table *id_table, Doc_OFDConvertor *convertor) +{ + this->table_block =table_block; + this->layer = layer; + this->id_table = id_table; + this->convertor = convertor; + +} + +void BuildTextTable::saveAsImage() +{ + DocBlock *block = this->table_block->getBlock(); +} diff --git a/ofdEditor/model/Convert/BuildTextTable.h b/ofdEditor/model/Convert/BuildTextTable.h new file mode 100644 index 0000000..398b45c --- /dev/null +++ b/ofdEditor/model/Convert/BuildTextTable.h @@ -0,0 +1,50 @@ +#ifndef BUILDTEXTTABLE_H +#define BUILDTEXTTABLE_H + +#include +#include "model_global.h" +#include +#include "Doc_OFDConvertor.h" +class DocPassage; // 文章 +class DocPage; // 页 +class DocLayer; // 层 +class DocBlock; // 块 +class DocTextBlock; // 文本框 + +class OFD; // OFD文件模型 +class Res; // 资源描述 +class ID_Table; // id table表 +class CT_Font; // ct_font +class CT_ColorSpace; // 颜色空间 +class Page; +class Document; +class CT_Layer; +class DocImageBlock; +class DocTable; + + +/// +/// \brief The BuildTextTable class +/// 暂行方式,保存成图片 +/// + +class MODELSHARED_EXPORT BuildTextTable +{ +public: + BuildTextTable(); + + DocTable *table_block; + CT_Layer *layer; + ID_Table *id_table; + Doc_OFDConvertor *convertor; + + void buildTable( + DocTable *table_block, + CT_Layer *layer, + ID_Table *id_table, + Doc_OFDConvertor *convertor); + void saveAsImage(); + +}; + +#endif // BUILDTEXTTABLE_H diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp index 112c359..9c93cd0 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.cpp +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.cpp @@ -6,6 +6,7 @@ #include "Doc/DocLayer.h" #include "Doc/DocImageBlock.h" #include "Convert/BuildTextBlock.h" +#include "Convert/BuildTextTable.h" #include #include @@ -280,10 +281,16 @@ void Doc_OFDConvertor::buildLayer(CT_Layer* ctLayer,DocLayer *layer) this->buildImage(ctLayer, block->getImageBlock()); } - // 如果是表格文件 + // 如果是表格 if(block->isTableBlock()) { - // 除了保存文字,还要画线 + // 处理表格 + BuildTextTable buildTextTable; + buildTextTable.buildTable( + block->getTableBlock(), + ctLayer, + this->table, + this); } } diff --git a/ofdEditor/model/Convert/OFD_DocConvertor.cpp b/ofdEditor/model/Convert/OFD_DocConvertor.cpp index eb8bd25..9aaf703 100644 --- a/ofdEditor/model/Convert/OFD_DocConvertor.cpp +++ b/ofdEditor/model/Convert/OFD_DocConvertor.cpp @@ -301,7 +301,7 @@ void OFD_DocConvertor::insertCT_Text(DocPage *page, DocPage::Layer layer, CT_Tex font.setPixelSize(UnitTool::mmToPixel(text->getSize())); // 字号 font.setFamily(textFont.family()); // 设置字体 - qDebug() << "italic " << text->getItalic(); + qDebug() << "italic ------------------------------------" << text->getItalic(); // 倾斜 if(text->getItalic()) { @@ -310,7 +310,7 @@ void OFD_DocConvertor::insertCT_Text(DocPage *page, DocPage::Layer layer, CT_Tex // 加粗 int weight = text->getWeight(); // 获得粗细 - font.setWeight(weight / 8); + font.setWeight(this->getWeight(weight)); // 上下间距 blockFormat.setTopMargin(0); @@ -387,6 +387,8 @@ QColor OFD_DocConvertor::ctColorToQColor(CT_Color *ct_color) { QColor defaultColor(Qt::black); // 设置默认颜色 + if(ct_color == NULL) + return defaultColor; Document* document = (*this->ofdFile->getDocuments())[0]; ID_Table* table = document->getIDTable(); @@ -460,3 +462,11 @@ QColor OFD_DocConvertor::ctColorToQColor(CT_Color *ct_color) } } + +int OFD_DocConvertor::getWeight(int weight) +{ + if(weight < 500) + return 50; + else + return 75; +} diff --git a/ofdEditor/model/Convert/OFD_DocConvertor.h b/ofdEditor/model/Convert/OFD_DocConvertor.h index f330308..2ad1139 100644 --- a/ofdEditor/model/Convert/OFD_DocConvertor.h +++ b/ofdEditor/model/Convert/OFD_DocConvertor.h @@ -60,6 +60,8 @@ private: QColor ctColorToQColor(CT_Color* ct_color); // 颜色转换 + int getWeight(int weight); // ofd的weight 转化 QText的weight + }; #endif // OFD_DOCCONVERTOR_H diff --git a/ofdEditor/model/Doc/DocTable.h b/ofdEditor/model/Doc/DocTable.h index 78acfd5..fe26728 100644 --- a/ofdEditor/model/Doc/DocTable.h +++ b/ofdEditor/model/Doc/DocTable.h @@ -46,6 +46,7 @@ public: QVector getColumnWidth(); // 获得行列宽度 int getColumns(){return this->_table->columns();} int getRows(){return this->_table->rows();} + QTextTable* getTable(); // 获得QTextTable表格的指针 public slots: void setTable(int rows, int columns); // 设置表格长和宽 diff --git a/ofdEditor/model/model.pro b/ofdEditor/model/model.pro index 782a021..19953da 100644 --- a/ofdEditor/model/model.pro +++ b/ofdEditor/model/model.pro @@ -56,7 +56,8 @@ SOURCES += model.cpp \ Widget/InsertPageDialog.cpp \ Widget/TableSettingDialog.cpp \ Widget/BlockSizeAndPosSettingDialog.cpp \ - Convert/BuildTextBlock.cpp + Convert/BuildTextBlock.cpp \ + Convert/BuildTextTable.cpp HEADERS += model.h\ model_global.h \ @@ -92,7 +93,8 @@ HEADERS += model.h\ Widget/InsertPageDialog.h \ Widget/TableSettingDialog.h \ Widget/BlockSizeAndPosSettingDialog.h \ - Convert/BuildTextBlock.h + Convert/BuildTextBlock.h \ + Convert/BuildTextTable.h DESTDIR = ../bin # 生成文件在这 MOC_DIR = ./moc # Q_OBJECT 类转换后的文件 diff --git a/ofdEditor/ofd/DataTypes/text/CT_Text.h b/ofdEditor/ofd/DataTypes/text/CT_Text.h index 9ec7ac6..b2b2614 100644 --- a/ofdEditor/ofd/DataTypes/text/CT_Text.h +++ b/ofdEditor/ofd/DataTypes/text/CT_Text.h @@ -120,8 +120,12 @@ public: void setWeight(int _weight) { if (_weight == 1000) weight = 900; - else if (_weight % 100 != 0 || _weight > 1000 || _weight <= 0) + else if (_weight % 100 != 0 + || _weight > 1000 + || _weight <= 0) weight = 400; + else + weight = _weight; } bool getItalic() { diff --git a/ofdEditor/ofd/DataTypes/text/ct_text.h b/ofdEditor/ofd/DataTypes/text/ct_text.h index 9ec7ac6..b2b2614 100644 --- a/ofdEditor/ofd/DataTypes/text/ct_text.h +++ b/ofdEditor/ofd/DataTypes/text/ct_text.h @@ -120,8 +120,12 @@ public: void setWeight(int _weight) { if (_weight == 1000) weight = 900; - else if (_weight % 100 != 0 || _weight > 1000 || _weight <= 0) + else if (_weight % 100 != 0 + || _weight > 1000 + || _weight <= 0) weight = 400; + else + weight = _weight; } bool getItalic() { diff --git a/ofdEditor/ofd/ofd_parser.cpp b/ofdEditor/ofd/ofd_parser.cpp index 9b60d7e..76492bc 100644 --- a/ofdEditor/ofd/ofd_parser.cpp +++ b/ofdEditor/ofd/ofd_parser.cpp @@ -380,6 +380,25 @@ void OFDParser::readPage(Page * page_data) { qDebug() << "CT_Text类型数据中缺少必要的Size属性\n位于" << current_path.getRelativePath(); } + + // Italic + if(t.hasAttribute("Italic")) + { + QString italic = t.attribute("Italic"); + italic = italic.toLower(); + if(italic == "true") + { + text_data->italic = true; + } + } + + // Weight + if(t.hasAttribute("Weight")) + { + text_data->weight = t.attribute("Weight").toInt(); + } + + // qDebug() << "Checkpoint 2.3"; //many optional attributes to be implemented // textCode diff --git a/ofdEditor/ofd/ofd_writer.cpp b/ofdEditor/ofd/ofd_writer.cpp index 7c7f3ff..0dd53b4 100644 --- a/ofdEditor/ofd/ofd_writer.cpp +++ b/ofdEditor/ofd/ofd_writer.cpp @@ -853,9 +853,10 @@ QXmlStreamAttributes getAttributes(CT_Text * cur_text) { a.append("ReadDirection", QString::number(cur_text->getReadDirection())); } + qDebug() << "weight ------" << cur_text->getWeight(); if (cur_text->getWeight() != 400) { - a.append("ReadDirection", QString::number(cur_text->getWeight())); + a.append("Weight", QString::number(cur_text->getWeight())); } if (cur_text->getItalic()) { -- Gitee From ea30ddcaaa7a97050828c7ff88833e72bb66bcec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 2 Sep 2017 11:19:38 +0800 Subject: [PATCH 71/83] =?UTF-8?q?=E5=8B=89=E5=8B=89=E5=BC=BA=E5=BC=BA?= =?UTF-8?q?=E5=B0=86=E8=A1=A8=E6=A0=BC=E4=BB=A5=E5=9B=BE=E7=89=87=E5=BD=A2?= =?UTF-8?q?=E5=BC=8F=E8=BF=9B=E8=A1=8C=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/BuildTextTable.cpp | 56 ++++++++++++++++++++++ ofdEditor/model/Convert/BuildTextTable.h | 3 +- ofdEditor/model/Convert/Doc_OFDConvertor.h | 6 ++- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/ofdEditor/model/Convert/BuildTextTable.cpp b/ofdEditor/model/Convert/BuildTextTable.cpp index 3c85104..b95deaa 100644 --- a/ofdEditor/model/Convert/BuildTextTable.cpp +++ b/ofdEditor/model/Convert/BuildTextTable.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "DataTypes/basic_datatype.h" #include "DataTypes/document/ofd.h" @@ -59,9 +60,64 @@ void BuildTextTable::buildTable( this->id_table = id_table; this->convertor = convertor; + this->saveAsImage(); } void BuildTextTable::saveAsImage() { DocBlock *block = this->table_block->getBlock(); + + QString fileName; // 将要保存的图片的文件名 + QUuid uuid = QUuid::createUuid(); // 创建uuid + QString imageName = uuid.toString(); // 转换为字符串 + + // 去掉字符串的链接符号 {0142d46f-60b5-47cf-8310-50008cc7cb3a} + // 0142d46f60b547cf831050008cc7cb3a + imageName.remove(imageName.length()-1, 1); + imageName.remove(imageName.length() -13, 1); + imageName.remove(imageName.length() -17,1); + imageName.remove(imageName.length() -21, 1); + imageName.remove(imageName.length() - 25,1); + imageName.remove(0,1); + + fileName = imageName + ".jpg"; + + CT_Image *ctimage = new CT_Image(); + CT_MultiMedia *multiMedia = new CT_MultiMedia(); + + ctimage->setID(this->id_table->size() + 1 , this->id_table ); + multiMedia->setID(this->id_table->size() + 1, this->id_table ); + ctimage->setResourceID(multiMedia->getID().getID(), this->id_table); + + // 设置多媒体引用的标签 + multiMedia->Format = ""; + multiMedia->Type = "Image"; + multiMedia->MediaFile = fileName; + + QString filePath = convertor->passage->getTempSavePath() + + "/" + fileName; + + // 设置为背景透明 +// this->table_block->viewport()->setAttribute(Qt::WA_TranslucentBackground, false); +// QPixmap pixmap = QPixmap::grabWidget(this->table_block,0,0,block->size().width(),block->size().height()); +// pixmap.save(filePath,"JPEG",100); +// this->table_block->viewport()->setAttribute(Qt::WA_TranslucentBackground, true); + + QPixmap pixmap = QPixmap::grabWidget( + this->table_block->getPage(), + block->x()+1, + block->y()+1, + block->size().width()+1 , + block->size().height()+1); + + pixmap.save(filePath,"JPEG",100); + + ctimage->setBoundary( + UnitTool::pixelToMM(block->x()), + UnitTool::pixelToMM(block->y()), + UnitTool::pixelToMM(block->size().width()), + UnitTool::pixelToMM(block->size().height())); + + convertor->document_res->getMultiMedia()->push_back(multiMedia); + this->layer->image_object->push_back(ctimage); } diff --git a/ofdEditor/model/Convert/BuildTextTable.h b/ofdEditor/model/Convert/BuildTextTable.h index 398b45c..89547a3 100644 --- a/ofdEditor/model/Convert/BuildTextTable.h +++ b/ofdEditor/model/Convert/BuildTextTable.h @@ -1,10 +1,11 @@ #ifndef BUILDTEXTTABLE_H #define BUILDTEXTTABLE_H +#include "Doc_OFDConvertor.h" #include #include "model_global.h" #include -#include "Doc_OFDConvertor.h" + class DocPassage; // 文章 class DocPage; // 页 class DocLayer; // 层 diff --git a/ofdEditor/model/Convert/Doc_OFDConvertor.h b/ofdEditor/model/Convert/Doc_OFDConvertor.h index 08d175b..f07e225 100644 --- a/ofdEditor/model/Convert/Doc_OFDConvertor.h +++ b/ofdEditor/model/Convert/Doc_OFDConvertor.h @@ -30,6 +30,8 @@ class DocImageBlock; class MODELSHARED_EXPORT Doc_OFDConvertor : public QObject { + + Q_OBJECT public: explicit Doc_OFDConvertor(QObject *parent = 0); @@ -39,6 +41,8 @@ public: int addFont(CT_Font* font); // 添加字体类型到资源 int addColorSpace(CT_ColorSpace* colorSpace); // 添加颜色空间 + + signals: public slots: @@ -72,7 +76,7 @@ private: int checkColorSpace(CT_ColorSpace* colorSpace); // 检查是否存在该颜色空间 -private: +public: DocPassage* passage; // 文章 OFD* ofdFile; // OFD 对象 Res* public_res; // Res 公共资源文件 -- Gitee From d8da8991be88ac2109aa0c2d9234201db3afe162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 2 Sep 2017 17:19:03 +0800 Subject: [PATCH 72/83] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E9=BE=99=E8=8A=AF=E4=B8=8A=E5=88=9B=E5=BB=BA=20Res=20=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=A4=B9=E5=A4=B1=E8=B4=A5=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/ofd/ofd_writer.cpp | 31 +++++++- ofdEditor/ofd/ofd_writer.h | 1 + ofdEditor/start/start.pro | 9 ++- ofdEditor/start/ui/ProgramSettingDialog.cpp | 14 ++++ ofdEditor/start/ui/ProgramSettingDialog.h | 22 ++++++ ofdEditor/start/ui/ProgramSettingDialog.ui | 81 +++++++++++++++++++++ 6 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 ofdEditor/start/ui/ProgramSettingDialog.cpp create mode 100644 ofdEditor/start/ui/ProgramSettingDialog.h create mode 100644 ofdEditor/start/ui/ProgramSettingDialog.ui diff --git a/ofdEditor/ofd/ofd_writer.cpp b/ofdEditor/ofd/ofd_writer.cpp index 0dd53b4..66bf08d 100644 --- a/ofdEditor/ofd/ofd_writer.cpp +++ b/ofdEditor/ofd/ofd_writer.cpp @@ -31,6 +31,34 @@ void OFDWriter::createFile() writer.setDevice(current_file); } +/// +/// \brief OFDWriter::makePath +/// Res文件夹创建的时候有bug,尝试通过创建文件来创建文件夹 +/// \param path +/// +void OFDWriter::makePath(QString path) +{ + int lastIndex = path.lastIndexOf('/'); + path = path.left(lastIndex +1) + "text.txt"; + + QFile file(path); + if(!file.exists()) + { + if(file.open(QFile::ReadWrite | QFile::Text)) + { + qDebug() << "create file success" << path; + file.close(); + } + else + { + qDebug() << "create file failed" << path; + } + } + + + +} + void OFDWriter::writeOFD() { createFile(); @@ -375,6 +403,7 @@ void OFDWriter::writeRes(Res * data) this->makePath(ST_Loc(resFloderPath, resFloderPath, "")); + this->makePath(resFloderPath); } } else @@ -1041,7 +1070,7 @@ void OFDWriter::makePath(ST_Loc path) qDebug() << path_str; if (!QDir().mkpath(path_str)) { - throw WritingFileException("无法创建文件路径: " + path.getPath()); + qDebug() << "can't mkPath:"<setupUi(this); +} + +ProgramSettingDialog::~ProgramSettingDialog() +{ + delete ui; +} diff --git a/ofdEditor/start/ui/ProgramSettingDialog.h b/ofdEditor/start/ui/ProgramSettingDialog.h new file mode 100644 index 0000000..a12d3f8 --- /dev/null +++ b/ofdEditor/start/ui/ProgramSettingDialog.h @@ -0,0 +1,22 @@ +#ifndef PROGRAMSETTINGDIALOG_H +#define PROGRAMSETTINGDIALOG_H + +#include + +namespace Ui { +class ProgramSettingDialog; +} + +class ProgramSettingDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ProgramSettingDialog(QWidget *parent = 0); + ~ProgramSettingDialog(); + +private: + Ui::ProgramSettingDialog *ui; +}; + +#endif // PROGRAMSETTINGDIALOG_H diff --git a/ofdEditor/start/ui/ProgramSettingDialog.ui b/ofdEditor/start/ui/ProgramSettingDialog.ui new file mode 100644 index 0000000..c6ebb8c --- /dev/null +++ b/ofdEditor/start/ui/ProgramSettingDialog.ui @@ -0,0 +1,81 @@ + + + ProgramSettingDialog + + + + 0 + 0 + 537 + 504 + + + + 程序设置 + + + + + + 0 + + + + 程序设置 + + + + + 默认页面设置 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + ProgramSettingDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + ProgramSettingDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + -- Gitee From 094b35ad254f85cfe1cfd659a3663d176b809026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 2 Sep 2017 18:55:06 +0800 Subject: [PATCH 73/83] =?UTF-8?q?=E5=86=8D=E6=AC=A1=E5=B0=9D=E8=AF=95?= =?UTF-8?q?=E8=A7=A3=E5=86=B3Res=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/ofd/ofd_writer.cpp | 22 ++++++++++++++++------ ofdEditor/start/ui/PassageMainWindow.cpp | 8 +++++++- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/ofdEditor/ofd/ofd_writer.cpp b/ofdEditor/ofd/ofd_writer.cpp index 66bf08d..de5edc4 100644 --- a/ofdEditor/ofd/ofd_writer.cpp +++ b/ofdEditor/ofd/ofd_writer.cpp @@ -23,10 +23,16 @@ void OFDWriter::createFile() { current_file = new QFile(current_path.getPath()); qDebug() << current_path.getPath() << endl; - if (!current_file->open(QFile::WriteOnly | QFile::Text)) + if(current_file->exists()) + { + QFile::remove(current_path.getPath()); // 删除文件夹 + qDebug() << "remove exists file"; + } + else + qDebug() <<"file not exists"; + if (!current_file->open(QFile::ReadWrite | QFile::Text)) { qDebug() << "can't open or write file"; - throw WritingFileException("无法打开或创建XML文件: " + current_path.getPath()); } writer.setDevice(current_file); } @@ -275,6 +281,7 @@ void OFDWriter::writeDocument(Document * data) //正文结束 writer.writeEndDocument(); current_file->close(); + ST_Loc cur_path = current_path; for (int i = 0; i < data->getPages()->getPages()->size(); i++) { @@ -1063,10 +1070,13 @@ QXmlStreamAttributes getAttributes(CT_Font * cur_font) void OFDWriter::makePath(ST_Loc path) { QString path_str = path.getPath(); - int n = 0; - while (path_str[path_str.length() - n - 1] != '/') - n++; - path_str.chop(n); +// int n = 0; +// while (path_str[path_str.length() - n - 1] != '/') +// n++; +// path_str.chop(n); + int index = path_str.lastIndexOf('/'); + path_str = path_str.left(index + 1); + qDebug() << path_str; if (!QDir().mkpath(path_str)) { diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 5e1f068..9df89c2 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -789,8 +789,14 @@ void PassageMainWindow::saveFile() OFD* ofdFile = docToOfd.doc_to_ofd(passage); QString tempPath = passage->getTempStorePath(); - ZipTool::deleteFolder(tempPath); // 删除文件夹 + QDir dir; + if(dir.exists(tempPath)) + { + qDebug() << "the file is existing"; + // 如果文件夹已存在则要删除该文件夹 + ZipTool::deleteFolder(tempPath); // 删除文件夹 + } dir.mkdir(tempPath); // 生成文件夹 OFDWriter writer(ofdFile, tempPath+"/"); // 写出文件 writer.setTempPath(passage->getTempSavePath()); // 保存着图片的临时路径 -- Gitee From feb83ef6ba6bde60caf7ed1775e0411b39b55349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 2 Sep 2017 19:03:15 +0800 Subject: [PATCH 74/83] =?UTF-8?q?=E6=94=B9=E5=8F=98=E5=88=9B=E5=BB=BARes?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=A4=B9=E7=9A=84=E6=96=B9=E5=BC=8F=EF=BC=8C?= =?UTF-8?q?=E5=86=8D=E5=81=9A=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/ofd/ofd_writer.cpp | 25 +++++++------------------ ofdEditor/ofd/ofd_writer.h | 2 +- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/ofdEditor/ofd/ofd_writer.cpp b/ofdEditor/ofd/ofd_writer.cpp index de5edc4..8f1bad1 100644 --- a/ofdEditor/ofd/ofd_writer.cpp +++ b/ofdEditor/ofd/ofd_writer.cpp @@ -42,25 +42,17 @@ void OFDWriter::createFile() /// Res文件夹创建的时候有bug,尝试通过创建文件来创建文件夹 /// \param path /// -void OFDWriter::makePath(QString path) +void OFDWriter::makePath(QString path_str) { - int lastIndex = path.lastIndexOf('/'); - path = path.left(lastIndex +1) + "text.txt"; + // path_str.chop(n); + int index = path_str.lastIndexOf('/'); + path_str = path_str.left(index + 1); - QFile file(path); - if(!file.exists()) - { - if(file.open(QFile::ReadWrite | QFile::Text)) - { - qDebug() << "create file success" << path; - file.close(); - } - else + qDebug() << path_str; + if (!QDir().mkpath(path_str)) { - qDebug() << "create file failed" << path; + qDebug() << "can't mkPath:"<makePath(ST_Loc(resFloderPath, - resFloderPath, - "")); this->makePath(resFloderPath); } } diff --git a/ofdEditor/ofd/ofd_writer.h b/ofdEditor/ofd/ofd_writer.h index ae4ec49..9acaef5 100644 --- a/ofdEditor/ofd/ofd_writer.h +++ b/ofdEditor/ofd/ofd_writer.h @@ -37,7 +37,7 @@ private: void makePath(ST_Loc path); void createFile(); - void makePath(QString path); + void makePath(QString path_str); void writeDocument(Document * data); void writePage(Page * data); -- Gitee From 3baa428659d64ff29446e98950e39eba89c1d761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 2 Sep 2017 19:15:31 +0800 Subject: [PATCH 75/83] =?UTF-8?q?=E5=9B=BE=E7=89=87=E5=B7=B2=E7=BB=8F?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E4=BF=9D=E5=AD=98=EF=BC=8C=E4=BD=86=E5=B7=B2?= =?UTF-8?q?=E7=BB=8F=E4=BF=9D=E5=AD=98=E7=9A=84=E6=96=87=E4=BB=B6=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E5=86=8D=E6=AC=A1=E4=BF=9D=E5=AD=98=EF=BC=8C=E6=80=80?= =?UTF-8?q?=E7=96=91=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=E5=A4=B9=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=9C=A8linux=E4=B8=8A=E4=B8=8D=E5=A4=AA=E5=AF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/ofd/Loaders/ZipTool.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofdEditor/ofd/Loaders/ZipTool.cpp b/ofdEditor/ofd/Loaders/ZipTool.cpp index fcb1da5..805651d 100644 --- a/ofdEditor/ofd/Loaders/ZipTool.cpp +++ b/ofdEditor/ofd/Loaders/ZipTool.cpp @@ -86,6 +86,7 @@ bool ZipTool::compressDir(QString fileCompressed, */ void ZipTool::deleteFolder(const QString &folderFullPath) { + qDebug() << "deleteFolder"; QDir dir(folderFullPath); QFileInfoList fileList; QFileInfo curFile; @@ -140,6 +141,7 @@ void ZipTool::deleteFolder(const QString &folderFullPath) } } dir.rmdir("."); + qDebug() << "deleteFolder succeed"; /*删除目标文件夹, * 如果只是清空文件夹folderFullPath的内容 * 而不删除folderFullPath本身,则删掉本行即可 */ -- Gitee From cb9254e87635447e4abeb915503bd7ba7447e4aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 2 Sep 2017 19:44:58 +0800 Subject: [PATCH 76/83] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E7=9A=84=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E8=BF=9B=E8=A1=8CLinux=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/ofd/Loaders/ZipTool.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ofdEditor/ofd/Loaders/ZipTool.cpp b/ofdEditor/ofd/Loaders/ZipTool.cpp index 805651d..b11c1e6 100644 --- a/ofdEditor/ofd/Loaders/ZipTool.cpp +++ b/ofdEditor/ofd/Loaders/ZipTool.cpp @@ -124,7 +124,8 @@ void ZipTool::deleteFolder(const QString &folderFullPath) if(fileListTemp.size() == 0) /* 下层没有文件或文件夹 则直接删除 */ { - dirTemp.rmdir("."); +// dirTemp.rmdir("."); + dirTemp.rmdir(QDir::toNativeSeparators(dirTemp.path())); fileList.removeAt(i); } else /* 下层有文件夹或文件 则将信息添加到列表 */ @@ -140,7 +141,9 @@ void ZipTool::deleteFolder(const QString &folderFullPath) } } } - dir.rmdir("."); +// dir.rmdir("."); + dir.rmdir(QDir::toNativeSeparators(dir.path())); + qDebug() << "deleteFolder succeed"; /*删除目标文件夹, * 如果只是清空文件夹folderFullPath的内容 -- Gitee From 179efdfdbab52326df37537caff5da076d40b369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sat, 2 Sep 2017 19:54:45 +0800 Subject: [PATCH 77/83] =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=A1=A8=E6=A0=BC?= =?UTF-8?q?=E7=9A=84=E4=BF=9D=E5=AD=98=E8=B5=B7=E5=A7=8B=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/BuildTextTable.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ofdEditor/model/Convert/BuildTextTable.cpp b/ofdEditor/model/Convert/BuildTextTable.cpp index b95deaa..d3e83ba 100644 --- a/ofdEditor/model/Convert/BuildTextTable.cpp +++ b/ofdEditor/model/Convert/BuildTextTable.cpp @@ -105,8 +105,8 @@ void BuildTextTable::saveAsImage() QPixmap pixmap = QPixmap::grabWidget( this->table_block->getPage(), - block->x()+1, - block->y()+1, + block->x(), + block->y(), block->size().width()+1 , block->size().height()+1); -- Gitee From 25708ff035507bf341e7d415e846fad216f9186d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sun, 3 Sep 2017 10:36:39 +0800 Subject: [PATCH 78/83] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=B1=82=E3=80=81?= =?UTF-8?q?=E8=A7=82=E5=AF=9F=E8=A7=86=E5=9B=BE=E3=80=81=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E8=A7=86=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocBlock.cpp | 10 ++++- ofdEditor/model/Doc/DocPage.cpp | 54 ++++++++++++++++++++++-- ofdEditor/model/Doc/DocPage.h | 9 +++- ofdEditor/model/Doc/DocPassage.cpp | 6 +++ ofdEditor/model/Doc/DocPassage.h | 1 + ofdEditor/model/Doc/DocTextBlock.cpp | 9 +++- ofdEditor/start/ui/PassageMainWindow.cpp | 51 ++++++++++++++++++++++ ofdEditor/start/ui/PassageMainWindow.h | 12 +++++- 8 files changed, 142 insertions(+), 10 deletions(-) diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index 709af3d..b0a11f8 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -235,6 +235,9 @@ void DocBlock::paint(QPainter *painter, */ void DocBlock::focusInEvent(QFocusEvent *event) { + if(!this->getPage()->getEditable()) + return; + QGraphicsProxyWidget::focusInEvent(event); this->isFocused = true; @@ -252,6 +255,8 @@ void DocBlock::focusInEvent(QFocusEvent *event) */ void DocBlock::focusOutEvent(QFocusEvent *event) { + if(!this->getPage()->getEditable()) + return; QGraphicsProxyWidget::focusOutEvent(event); this->isFocused = false; QGraphicsProxyWidget::setZValue(this->realZValue); // 还原到真实的Z坐标 @@ -462,18 +467,19 @@ void DocBlock::initMenu() { // 移动到前景层 this->action_foreground = new QAction(tr("Foreground"), NULL); - + this->action_foreground->setCheckable(true); this->connect(this->action_foreground, SIGNAL(triggered(bool)), this, SLOT(moveToForeground())); // 移动到正文层 this->action_body = new QAction(tr("Body"), NULL); - + this->action_body->setCheckable(true); this->connect(this->action_body, SIGNAL(triggered(bool)), this, SLOT(moveToBody())); // 移动到背景层 this->action_background = new QAction(tr("Background"), NULL); + this->action_background->setCheckable(true); this->connect(this->action_background, SIGNAL(triggered(bool)), this, SLOT(moveToBackground())); diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index 07cb54a..e799b12 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -129,6 +129,7 @@ bool DocPage::hasBlock(DocBlock *block) { flag = true; } + return flag; } /** @@ -269,15 +270,15 @@ void DocPage::changeBlockLayer(DocBlock *block, DocPage::Layer layer) if(!this->hasBlock(block)) { // 如果本页中不包含此块 - return; qDebug() << "this page does not has this block."; + return; } DocLayer *doclayer = block->getLayer(); // 获得层 if(doclayer == NULL) { - return; qDebug() << "This block has no layer"; + return; } DocLayer* goalLayer = this->getLayer(layer); // 目标层 @@ -419,6 +420,23 @@ void DocPage::dialogPageSetting() this->getPassage()->activatePageDialog(); } +/// +/// \brief DocPage::setEditedAble +/// \param flag +/// +void DocPage::setEditedAble(bool flag) +{ + if(flag) + { + this->isEditable = flag; + } + else + { + this->isEditable = flag; + this->newBlockFlag = none; + } +} + /** * @Author Chaoqun @@ -461,6 +479,9 @@ void DocPage::contextMenuEvent(QContextMenuEvent *event) // event->pos() 相对于页面左上角 // QMenu* menu = new QMenu(this->passage); // 让passage作为父亲 + if(!this->isEditable) + return; + QPoint pos = event->pos(); // 获得相对于页面的 QList items = this->items(pos); // 获得某鼠标下的所有块 QMenu *menu = this->getMenu(items); @@ -479,6 +500,8 @@ void DocPage::contextMenuEvent(QContextMenuEvent *event) */ void DocPage::mouseDoubleClickEvent(QMouseEvent *event) { + if(!this->isEditable) + return; QGraphicsView::mouseDoubleClickEvent(event); } @@ -493,6 +516,9 @@ void DocPage::mousePressEvent(QMouseEvent *event) { // qDebug() << "mouse Press"; + if(!this->isEditable) + return; + // 如果是加入新块状态 if(this->newBlockFlag == draw) { @@ -566,6 +592,9 @@ void DocPage::mousePressEvent(QMouseEvent *event) void DocPage::mouseMoveEvent(QMouseEvent *event) { + if(!this->isEditable) + return; + QGraphicsView::mouseMoveEvent(event); if(this->newBlockFlag == drawMove) @@ -625,6 +654,9 @@ void DocPage::mouseMoveEvent(QMouseEvent *event) */ void DocPage::mouseReleaseEvent(QMouseEvent *event) { + if(!this->isEditable) + return; + if(this->newBlockFlag == drawMove) { @@ -671,10 +703,20 @@ void DocPage::mouseReleaseEvent(QMouseEvent *event) /// void DocPage::focusInEvent(QFocusEvent *event) { - QGraphicsView::focusInEvent(event); + if(this->isEditable) + { + QGraphicsView::focusInEvent(event); + } + emit signals_page_actived(this); } +void DocPage::focusOutEvent(QFocusEvent *event) +{ + if(this->isEditable) + QGraphicsView::focusOutEvent(event); +} + /** * @Author Chaoqun @@ -683,6 +725,8 @@ void DocPage::focusInEvent(QFocusEvent *event) */ void DocPage::init() { + this->isEditable = true; // 是否可以编辑 + this->setWindowFlags(Qt::Widget); this->docScene = new DocPageScene(); // 新建 @@ -729,9 +773,13 @@ void DocPage::initMenu() // 插入图片 this->action_insertImageBlock = new QAction(tr("ImageBlock"), this); + this->connect(action_insertImageBlock, SIGNAL(triggered(bool)), + this, SLOT(addImage())); // 插入表格 this->action_insertTable = new QAction(tr("Table"), this); + this->connect(action_insertTable, SIGNAL(triggered(bool)), + this, SLOT(addTable())); // 插入页 this->menu_insertPage = new QMenu(tr("Page")); diff --git a/ofdEditor/model/Doc/DocPage.h b/ofdEditor/model/Doc/DocPage.h index 4213d91..00f80dd 100644 --- a/ofdEditor/model/Doc/DocPage.h +++ b/ofdEditor/model/Doc/DocPage.h @@ -50,8 +50,7 @@ public: DocLayer* getBodyLayer(); // 获得正文层 DocLayer* getBackgroundLayer(); // 获得背景层 DocLayer *getLayer(DocPage::Layer layer); // 获得层 - - //Pan + bool getEditable(){return this->isEditable;} bool isUsingWorkArea(){return this->has_working_area;} @@ -86,6 +85,8 @@ public slots: void insertPageBefore(); // 在本页之前插入页面 void insertPageAfter(); // 在本页之后插入页面 void dialogPageSetting(); // 页面设置窗口 + void setEditedAble(bool flag); // 设置是否可以编辑 + protected: void paintEvent(QPaintEvent *event); @@ -95,6 +96,7 @@ protected: void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void focusInEvent(QFocusEvent *event); + void focusOutEvent(QFocusEvent *event); private: @@ -138,6 +140,9 @@ private: QAction *action_deletePage; // 删除本页 QAction *action_pageSetting; // 页面设置 + // 是否可以编辑 + bool isEditable; + // 页面设置 bool has_working_area; diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index b02781d..c8cbf97 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -113,6 +113,9 @@ void DocPassage::addPage(DocPage *page) this->connect(page, SIGNAL(signals_page_actived(DocPage*)), this, SLOT(setCurrentActivedPage(DocPage*))); + this->connect(this, SIGNAL(signals_setEditable(bool)), + page, SLOT(setEditedAble(bool))); + this->layout->update(); // 更新 page->setPassage(this); // 设置页所属的文章 this->adjustWidgetSize(); // 调整大小 @@ -206,6 +209,9 @@ void DocPassage::insertPage(DocPage *page, int index) this->connect(page, SIGNAL(signals_page_actived(DocPage*)), this, SLOT(setCurrentActivedPage(DocPage*))); + this->connect(this, SIGNAL(signals_setEditable(bool)), + page, SLOT(setEditedAble(bool))); + this->layout->update(); page->setPassage(this); this->adjustWidgetSize(); diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index b5262ee..0ce0402 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -192,6 +192,7 @@ signals: DocTextBlock* textBlock); // 当前操作的textBlock void signals_currentImageBlock( DocImageBlock* imageBlock); //当前操作的imageBlock + void signals_setEditable(bool flag); // 通知自己页面是否可以编辑 }; diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 095b4f7..0c20ec3 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -701,8 +701,11 @@ void DocTextBlock::serCharFormatOnSelection( */ void DocTextBlock::focusInEvent(QFocusEvent *e) { - this->showBoundaryFrame(true); + if(!this->getPage()->getEditable()) + return; + + this->showBoundaryFrame(true); emitFormatSignals(); // 当鼠标移进时,必须发出信号 QTextEdit::focusInEvent(e); @@ -717,8 +720,10 @@ void DocTextBlock::focusInEvent(QFocusEvent *e) */ void DocTextBlock::focusOutEvent(QFocusEvent *e) { - this->showBoundaryFrame(false); + if(!this->getPage()->getEditable()) + return; + this->showBoundaryFrame(false); QTextEdit::focusOutEvent(e); } diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 9df89c2..727f2ba 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -98,6 +98,8 @@ void PassageMainWindow::activateFindAndReplaceDock() find_and_replace_dock->setCurrentPassage( this->activedPassage()); // 设置当前操作的文章 find_and_replace_dock->show(); + find_and_replace_dock->update(); + find_and_replace_dock->setBackgroundRole(QPalette::Window); } } @@ -111,6 +113,8 @@ void PassageMainWindow::activateFindAndReplaceDock() void PassageMainWindow::init() { + this->isEditable = true; + /// 标签页 this->tabArea = new QTabWidget(); this->setCentralWidget(this->tabArea); @@ -702,6 +706,16 @@ void PassageMainWindow::printPassage() } } +void PassageMainWindow::undo() +{ + +} + +void PassageMainWindow::redo() +{ + +} + /** * @Author Chaoqun * @brief 放大函数 @@ -924,6 +938,11 @@ void PassageMainWindow::templateDialog() this->select_template_dialog->exec(); } +void PassageMainWindow::tableSetting() +{ + +} + /** * @Author Chaoqun * @brief 接受当前处理的文字块的更新 @@ -935,6 +954,7 @@ void PassageMainWindow::acceptTextBlock(DocTextBlock *textBlock) { this->textBlock = textBlock; // 修改引用 this->imageBlock = NULL; + this->tableBlock = NULL; } /** @@ -1036,16 +1056,32 @@ void PassageMainWindow::acceptImageBlock(DocImageBlock *imageBlock) { this->imageBlock = imageBlock; this->textBlock = NULL; + this->tableBlock = NULL; +} + +void PassageMainWindow::acceptTableBlock(DocTable *table) +{ + this->tableBlock = table; + this->textBlock = NULL; + this->imageBlock = NULL; } void PassageMainWindow::switchToEditMode() { this->viewModeAction->setChecked(false); + this->editModeAction->setChecked(true); + + this->isEditable = true; + emit this->setEditable(this->isEditable); } void PassageMainWindow::switchToViewMode() { this->editModeAction->setChecked(false); + this->viewModeAction->setChecked(true); + + this->isEditable = false; + emit this->setEditable(this->isEditable); } /// @@ -1093,6 +1129,16 @@ void PassageMainWindow::closePassageRequest(int index) } } +/// +/// \brief PassageMainWindow::setStatusMessage +/// \param msg +/// 在状态栏中显示信息 +/// +void PassageMainWindow::setStatusMessage(QString msg) +{ + +} + void PassageMainWindow::createTemplatePassage(int index) { qDebug() << "???"; @@ -1412,6 +1458,11 @@ DocPassage *PassageMainWindow::addDocPassage(DocPassage *passage) //处理变更的imageBlock this->connect(passage, SIGNAL(signals_currentImageBlock(DocImageBlock*)), this, SLOT(acceptImageBlock(DocImageBlock*))); + this->connect(this, SIGNAL(setEditable(bool)), + passage, SIGNAL(signals_setEditable(bool))); // 转发设置可以编辑 + + emit this->setEditable(this->isEditable); + return passage; } diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index 880a572..649f055 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -17,6 +17,7 @@ class DocTextBlock; class ActionConnector; // 函数功能的中间件 class DocImageBlock; class SelectTemplateDialog; +class DocTable; // 编辑窗口的主界面 class PassageMainWindow @@ -49,12 +50,17 @@ public slots: void imageDialog(); // 打开图片框 void pageDialog(); // 打开页面框 void templateDialog(); //打开模板选择 + void tableSetting(); // 打开表格设置 + void Bold(); // 加粗事件 void Italic(); // 斜体事件 void underline(); // 下划线事件 void printPassage(); // 打印文章 + void undo(); + void redo(); + void zoomIn(); // 放大 void zooomOut(); // 缩小 @@ -62,13 +68,14 @@ public slots: void acceptTextBlockFormat(QTextBlockFormat blockFormat); // 接受当前处理的块格式 void acceptTextCharFormat(QTextCharFormat charFormat); // 接受当前处理的字符格式 void acceptImageBlock(DocImageBlock * imageBlock); //接受当前处理的图片块 + void acceptTableBlock(DocTable* table); // 接受当前表格 void switchToEditMode(); //切换到编辑模式 void switchToViewMode(); //切换到阅读模式 void changeCurrentPassage(int index); // 当活跃内容 切换为当前页面 void closePassageRequest(int index); // 点击关闭时处理 - + void setStatusMessage(QString msg); protected: void closeEvent(QCloseEvent *event); // 关闭窗口时的响应事件 @@ -76,6 +83,7 @@ protected: private: static PassageMainWindow* m_instance; // 单例 double scale; + bool isEditable; // 菜单栏 QMenu * filesMenu; // 文件 @@ -160,6 +168,7 @@ private: QTextBlockFormat _currentBlockFormat; // 当前块格式 DocImageBlock *imageBlock; //图片块 + DocTable *tableBlock; // 表格块 SelectTemplateDialog * select_template_dialog; //选择模板对话框 @@ -167,6 +176,7 @@ private: signals: void updateActivedPassage(DocPassage * passage); // 更新当前操作的文档对象 + void setEditable(bool flag); // 设置是否可以编辑 }; -- Gitee From e359806e15e998709debbcd0235e29dcbc0304df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sun, 3 Sep 2017 11:37:11 +0800 Subject: [PATCH 79/83] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E5=B0=8F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocPage.cpp | 6 ++++++ ofdEditor/model/Doc/DocPassage.cpp | 3 +++ ofdEditor/model/Doc/DocPassage.h | 3 +++ ofdEditor/model/Doc/DocTable.cpp | 12 ++++++++++++ ofdEditor/model/Doc/DocTable.h | 3 +++ ofdEditor/start/ui/PassageMainWindow.cpp | 20 +++++++++++++++++++- 6 files changed, 46 insertions(+), 1 deletion(-) diff --git a/ofdEditor/model/Doc/DocPage.cpp b/ofdEditor/model/Doc/DocPage.cpp index e799b12..9a44f39 100644 --- a/ofdEditor/model/Doc/DocPage.cpp +++ b/ofdEditor/model/Doc/DocPage.cpp @@ -236,6 +236,12 @@ void DocPage::addBlock(DocBlock *block, DocPage::Layer layer) DocPassage *passage = this->getPassage(); // 之后可以做信号的转发 + connect(table, SIGNAL(signals_currentBlockFormatChanged(QTextBlockFormat)), + passage, SIGNAL(signals_currentBlockFormatChanged(QTextBlockFormat))); + connect(table, SIGNAL(signals_currentCharFormatChanged(QTextCharFormat)), + passage, SIGNAL(signals_currentCharFormatChanged(QTextCharFormat))); + connect(table ,SIGNAL(signals_currentTable(DocTable*)), + passage, SIGNAL(signals_currentTableBlock(DocTable*))); } // qDebug()<< "connect"; diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index c8cbf97..ffc9b71 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -14,6 +14,9 @@ #include #include #include +#include "Doc/DocTable.h" +#include "Doc/DocTextBlock.h" +#include "Doc/DocImageBlock.h" /// /// \brief DocPassage::createNewPassage diff --git a/ofdEditor/model/Doc/DocPassage.h b/ofdEditor/model/Doc/DocPassage.h index 0ce0402..96bd91d 100644 --- a/ofdEditor/model/Doc/DocPassage.h +++ b/ofdEditor/model/Doc/DocPassage.h @@ -23,6 +23,7 @@ class CT_CommonData; class DocBlock; class DocTextBlock; class DocImageBlock; +class DocTable; //class PageDialog; /** @@ -192,6 +193,8 @@ signals: DocTextBlock* textBlock); // 当前操作的textBlock void signals_currentImageBlock( DocImageBlock* imageBlock); //当前操作的imageBlock + void signals_currentTableBlock( + DocTable* tableBlock); void signals_setEditable(bool flag); // 通知自己页面是否可以编辑 }; diff --git a/ofdEditor/model/Doc/DocTable.cpp b/ofdEditor/model/Doc/DocTable.cpp index fbe8c64..ea3cc94 100644 --- a/ofdEditor/model/Doc/DocTable.cpp +++ b/ofdEditor/model/Doc/DocTable.cpp @@ -411,6 +411,18 @@ void DocTable::focusOutEvent(QFocusEvent *e) QTextEdit::focusOutEvent(e); } +void DocTable::emitFormatSignals() +{ + QTextCursor cursor = this->textCursor(); // 光标 + this->_currentBlockFormat = cursor.blockFormat(); // 获得块格式 + this->_currentCharFormat = cursor.charFormat(); // 获得字符格式 + + // 发射三个信号 + emit this->signals_currentBlockFormatChanged(this->_currentBlockFormat); + emit this->signals_currentCharFormatChanged(this->_currentCharFormat); + emit this->signals_currentTable(this); +} + void DocTable::selectedCells(QTextCursor &cursor) { // 这里可以检测是否复选单元格 diff --git a/ofdEditor/model/Doc/DocTable.h b/ofdEditor/model/Doc/DocTable.h index fe26728..9cdd904 100644 --- a/ofdEditor/model/Doc/DocTable.h +++ b/ofdEditor/model/Doc/DocTable.h @@ -88,6 +88,9 @@ protected: void focusInEvent(QFocusEvent *e); void focusOutEvent(QFocusEvent *e); +protected slots: + void emitFormatSignals(); + private slots: void selectedCells(QTextCursor& cursor); void checkCursorInTable(); // 确保光标永远在表格内部 diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index 727f2ba..cb6603d 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -38,6 +38,7 @@ #include "Tool/UnitTool.h" #include "Core/GlobalSetting.h" #include "DataTypes/document/CT_DocInfo.h" +#include "Doc/DocTable.h" #include "Settings/RecentFileList.h" #include "Settings/RecentFileItem.h" @@ -131,6 +132,7 @@ void PassageMainWindow::init() // 初始化变量 this->imageBlock = NULL; this->textBlock = NULL; + this->tableBlock = NULL; initAction(); connectAction(); @@ -583,6 +585,10 @@ void PassageMainWindow::connectAction() connect(this->imageFormat, SIGNAL(triggered(bool)), this, SLOT(imageDialog())); //修改图片 + // 设置表格 + connect(this->tableFormat, SIGNAL(triggered(bool)), + this, SLOT(tableSetting())); + connect(this->boldAction, SIGNAL(triggered(bool)), this,SLOT(Bold())); // 加粗 @@ -899,6 +905,8 @@ void PassageMainWindow::fontDialog() { if (textBlock) this->textBlock->customFontDialog(); // 用自定义窗口修改字体 + else if(this->tableBlock) + this->tableBlock->customFontDialog(); } /** @@ -912,6 +920,8 @@ void PassageMainWindow::paragraphDialog() { if (textBlock) this->textBlock->textParagraph(); // 用自定义段落窗口修改段落 + else if(this->tableBlock) + this->tableBlock->customFontDialog(); } void PassageMainWindow::imageDialog() @@ -940,7 +950,10 @@ void PassageMainWindow::templateDialog() void PassageMainWindow::tableSetting() { - + if(this->tableBlock != NULL) + { + this->tableBlock->tableSetting(); + } } /** @@ -1458,6 +1471,11 @@ DocPassage *PassageMainWindow::addDocPassage(DocPassage *passage) //处理变更的imageBlock this->connect(passage, SIGNAL(signals_currentImageBlock(DocImageBlock*)), this, SLOT(acceptImageBlock(DocImageBlock*))); + + // 转发tableBlock + this->connect(passage, SIGNAL(signals_currentTableBlock(DocTable*)), + this, SLOT(acceptTableBlock(DocTable*))); + this->connect(this, SIGNAL(setEditable(bool)), passage, SIGNAL(signals_setEditable(bool))); // 转发设置可以编辑 -- Gitee From 904ef2309b30e0660533e3dfd241dd99d7ab8f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sun, 3 Sep 2017 16:22:09 +0800 Subject: [PATCH 80/83] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E6=94=BE?= =?UTF-8?q?=E5=A4=A7=E7=BC=A9=E5=B0=8F=E3=80=81=E5=AD=97=E4=BD=93=E6=AE=B5?= =?UTF-8?q?=E8=90=BD=E7=9A=84=E4=B8=80=E4=BA=9B=E6=8E=A7=E5=88=B6=E3=80=81?= =?UTF-8?q?=E6=92=A4=E9=94=80=E6=81=A2=E5=A4=8D=E7=AD=89=E5=B0=8Fbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocPassage.cpp | 5 ++ ofdEditor/model/Doc/DocTextBlock.cpp | 20 ++++-- ofdEditor/model/Doc/DocTextBlock.h | 1 + ofdEditor/start/ui/PassageMainWindow.cpp | 87 ++++++++++++++++++++++-- ofdEditor/start/ui/PassageMainWindow.h | 10 ++- 5 files changed, 112 insertions(+), 11 deletions(-) diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index ffc9b71..9b14a4a 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -123,6 +123,8 @@ void DocPassage::addPage(DocPage *page) page->setPassage(this); // 设置页所属的文章 this->adjustWidgetSize(); // 调整大小 + page->setScale(this->scaleFactor); + // qDebug() << "You have added an new page"; } @@ -217,6 +219,9 @@ void DocPassage::insertPage(DocPage *page, int index) this->layout->update(); page->setPassage(this); + + page->setScale(this->scaleFactor); + this->adjustWidgetSize(); } diff --git a/ofdEditor/model/Doc/DocTextBlock.cpp b/ofdEditor/model/Doc/DocTextBlock.cpp index 0c20ec3..13484a0 100644 --- a/ofdEditor/model/Doc/DocTextBlock.cpp +++ b/ofdEditor/model/Doc/DocTextBlock.cpp @@ -222,7 +222,7 @@ void DocTextBlock::mergeFormatOnWordOrSelection( if(!cursor.hasSelection()) { // 如果没有选择文字段落 - cursor.select(QTextCursor::WordUnderCursor); +// cursor.select(QTextCursor::WordUnderCursor); qDebug() << "cursor has no selection!"; } cursor.mergeCharFormat(format); // 合并光标下的 QTextCharFormat @@ -240,10 +240,10 @@ void DocTextBlock::mergeBlockFormatOnBlock( QTextBlockFormat &blockFormat) { QTextCursor cursor = this->textCursor(); // 光标 - if(!cursor.hasSelection()) - { - cursor.select(QTextCursor::BlockUnderCursor); // 选择光标下的块 - } +// if(!cursor.hasSelection()) +// { +// cursor.select(QTextCursor::BlockUnderCursor); // 选择光标下的块 +// } cursor.mergeBlockFormat(blockFormat); } @@ -297,6 +297,16 @@ void DocTextBlock::setFont( mergeFormatOnWordOrSelection(cursor, currentFormat); // 合并给定光标下的字体样式 } +void DocTextBlock::setFont(QString fontName) +{ + QTextCursor cursor = this->textCursor(); + QTextCharFormat charformat = cursor.charFormat(); + QFont font = charformat.font(); + font.setFamily(fontName); + charformat.setFont(font); + mergeFormatOnWordOrSelection(cursor,charformat); +} + /** * @Author Chaoqun * @brief 设置block diff --git a/ofdEditor/model/Doc/DocTextBlock.h b/ofdEditor/model/Doc/DocTextBlock.h index 85b4106..4a95347 100644 --- a/ofdEditor/model/Doc/DocTextBlock.h +++ b/ofdEditor/model/Doc/DocTextBlock.h @@ -88,6 +88,7 @@ public slots: void setFont( QTextCursor& cursor, const QFont &font); // 设置给定光标下的字体格式 + void setFont(QString fontName); // 关于框的一些其他部分 void setBlock(DocBlock* block); // 设置Block diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index cb6603d..f49a9c5 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -455,6 +455,12 @@ void PassageMainWindow::initAction() this->justifyAction->setIcon(QIcon(":/icons/source/icons/justify.png")); this->justifyAction->setCheckable(true); + // 添加成组 + this->alignGroup = new QActionGroup(0); + this->alignGroup->addAction(this->middleAction); + this->alignGroup->addAction(this->leftAction); + this->alignGroup->addAction(this->rightAction); + this->alignGroup->addAction(this->justifyAction); /*---------------------------------------------------------------------*/ this->file_toolBar = this->addToolBar(tr("File")); @@ -496,7 +502,7 @@ void PassageMainWindow::initAction() this->textBlock_toolBar = this->addToolBar(tr("TextBlock")); this->textBlock_toolBar->setMovable(false); this->textBlock_toolBar->addWidget(this->fontCombox); // 字体选择 - this->textBlock_toolBar->addWidget(this->fontSizeCombox); // 字体大小设置 +// this->textBlock_toolBar->addWidget(this->fontSizeCombox); // 字体大小设置 this->textBlock_toolBar->addSeparator(); // 分隔符 this->textBlock_toolBar->addAction(this->boldAction); // 字体加粗 this->textBlock_toolBar->addAction(this->italicAction); // 斜体 @@ -545,11 +551,11 @@ void PassageMainWindow::connectAction() //undo operation connect(this->undoAction,SIGNAL(triggered(bool)), - this->connector,SLOT(undo())); + this,SLOT(undo())); //redo operation connect(this->redoAction,SIGNAL(triggered(bool)), - this->connector,SLOT(redo())); + this,SLOT(redo())); // 放大 connect(this->zoomInAction, SIGNAL(triggered(bool)), @@ -616,6 +622,13 @@ void PassageMainWindow::connectAction() // 切换为阅读模式 connect(this->viewModeAction, SIGNAL(triggered(bool)), this, SLOT(switchToViewMode())); + + // 字体选择 + connect(this->fontCombox, SIGNAL(currentFontChanged(QFont)), + this, SLOT(slots_setFont(QFont))); + // 对其样式 + connect(this->alignGroup, SIGNAL(triggered(QAction*)), + this, SLOT(slots_selectAlign(QAction*))); } /** @@ -630,6 +643,57 @@ void PassageMainWindow::disconnectAction() } +void PassageMainWindow::slots_selectAlign(QAction *action) +{ + Qt::Alignment alignment; + if(action == this->leftAction) + { + alignment = Qt::AlignLeft; + } + else if(action == this->rightAction) + { + alignment = Qt::AlignRight; + } + else if(action == this->middleAction) + { + alignment = Qt::AlignHCenter; + } + else if(action == this->justifyAction) + { + alignment = Qt::AlignJustify; + } + + if(this->textBlock) + { + QTextBlockFormat blockFormat; + blockFormat.setAlignment(alignment); + this->textBlock->mergeBlockFormatOnBlock(blockFormat); + } + else if(this->tableBlock) + { + QTextBlockFormat blockFormat; + blockFormat.setAlignment(alignment); + this->tableBlock->mergeBlockFormatOnBlock(blockFormat); + } +} + +/// +/// \brief PassageMainWindow::slots_setFont +/// 快速设定字体 +/// \param font +/// +void PassageMainWindow::slots_setFont(const QFont &font) +{ + if(this->textBlock != NULL) + { + this->textBlock->setFont(font.family()); + } + else if(this->tableBlock != NULL) + { + this->tableBlock->setFont(font.family()); + } +} + /** * @Author Chaoqun * @brief 找到当前活跃的textblock,加粗 @@ -714,12 +778,27 @@ void PassageMainWindow::printPassage() void PassageMainWindow::undo() { - + if(this->textBlock != NULL) + { + this->textBlock->undo(); + } + else if(this->tableBlock != NULL) + { + this->tableBlock->undo(); + } } void PassageMainWindow::redo() { + if(this->textBlock != NULL) + { + this->textBlock->redo(); + } + else if(this->tableBlock != NULL) + { + this->tableBlock->redo(); + } } /** diff --git a/ofdEditor/start/ui/PassageMainWindow.h b/ofdEditor/start/ui/PassageMainWindow.h index 649f055..8a67f57 100644 --- a/ofdEditor/start/ui/PassageMainWindow.h +++ b/ofdEditor/start/ui/PassageMainWindow.h @@ -9,6 +9,7 @@ #include #include #include // 标签页 +#include class QAction; class QMenu; @@ -58,8 +59,8 @@ public slots: void printPassage(); // 打印文章 - void undo(); - void redo(); + void undo(); // 撤销 + void redo(); // 恢复 void zoomIn(); // 放大 void zooomOut(); // 缩小 @@ -151,6 +152,7 @@ private: QAction* leftAction; // 居左 QAction* rightAction; // 居右 QAction* justifyAction; // 两端对齐 + QActionGroup *alignGroup; // 对齐选项组 QVectorpassages; // 存储所有的passage @@ -174,6 +176,10 @@ private: +private slots: + void slots_selectAlign(QAction *action); + void slots_setFont( const QFont & font ); + signals: void updateActivedPassage(DocPassage * passage); // 更新当前操作的文档对象 void setEditable(bool flag); // 设置是否可以编辑 -- Gitee From 26f028339ea8fe34cb9cb18567a563ec7c82712e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sun, 3 Sep 2017 19:14:06 +0800 Subject: [PATCH 81/83] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=A4=A7=E5=B0=8F?= =?UTF-8?q?=E4=B8=8E=E4=BD=8D=E7=BD=AE=E7=AA=97=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocBlock.cpp | 5 +- .../Widget/BlockSizeAndPosSettingDialog.cpp | 66 +++++++ .../Widget/BlockSizeAndPosSettingDialog.h | 28 ++- .../Widget/BlockSizeAndPosSettingDialog.ui | 186 ++++++++++++++++-- 4 files changed, 264 insertions(+), 21 deletions(-) diff --git a/ofdEditor/model/Doc/DocBlock.cpp b/ofdEditor/model/Doc/DocBlock.cpp index b0a11f8..1bab670 100644 --- a/ofdEditor/model/Doc/DocBlock.cpp +++ b/ofdEditor/model/Doc/DocBlock.cpp @@ -16,6 +16,7 @@ #include "Doc/DocPassage.h" #include "Doc/DocImageBlock.h" #include "Doc/DocTable.h" +#include "Widget/BlockSizeAndPosSettingDialog.h" DocBlock::DocBlock(QGraphicsItem *parent , Qt::WindowFlags wFlags) :QGraphicsProxyWidget(parent,wFlags) @@ -436,7 +437,9 @@ void DocBlock::setWidget(DocTable *table) /// void DocBlock::sizeAndPositionDialog() { - + BlockSizeAndPosSettingDialog* dialog = BlockSizeAndPosSettingDialog::getInstance(); + dialog->init(this); + dialog->exec(); } /// diff --git a/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.cpp b/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.cpp index 391a528..8206919 100644 --- a/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.cpp +++ b/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.cpp @@ -1,11 +1,77 @@ #include "BlockSizeAndPosSettingDialog.h" #include "ui_BlockSizeAndPosSettingDialog.h" +#include "Doc/DocBlock.h" +#include "Tool/UnitTool.h" + +BlockSizeAndPosSettingDialog *BlockSizeAndPosSettingDialog::m_instance = NULL; + BlockSizeAndPosSettingDialog::BlockSizeAndPosSettingDialog(QWidget *parent) : QDialog(parent), ui(new Ui::BlockSizeAndPosSettingDialog) { ui->setupUi(this); + + connect(this, SIGNAL(finished(int)), + this, SLOT(slot_finished(int))); +} + +void BlockSizeAndPosSettingDialog::setUI(int width, int height, int x, int y) +{ + ui->widthValue->setValue(width); + ui->heightValue->setValue(height); + ui->xValue->setValue(x); + ui->yValue->setValue(y); +} + +void BlockSizeAndPosSettingDialog::slot_finished(int value) +{ + if(value == QDialog::Accepted) + { + int height = ui->heightValue->value(); + int width = ui->widthValue->value(); + int x = ui->xValue->value(); + int y = ui->yValue->value(); + + this->_block->resize( + UnitTool::mmToPixel(width), + UnitTool::mmToPixel(height)); + + this->_block->setPos( + UnitTool::mmToPixel(x), + UnitTool::mmToPixel(y)); + } + else if(value == QDialog::Rejected) + { + + } +} + +BlockSizeAndPosSettingDialog *BlockSizeAndPosSettingDialog::getInstance() +{ + if(m_instance == NULL) + { + m_instance = new BlockSizeAndPosSettingDialog(); + } + + return m_instance; +} + +void BlockSizeAndPosSettingDialog::DestoryInsatance() +{ + m_instance = NULL; +} + +void BlockSizeAndPosSettingDialog::init(DocBlock *block) +{ + this->_block = block; // 记录操作的对象 + + this->setUI( + UnitTool::pixelToMM( block->size().width()), + UnitTool::pixelToMM( block->size().height()), + UnitTool::pixelToMM( block->x()), + UnitTool::pixelToMM( block->y())); + } BlockSizeAndPosSettingDialog::~BlockSizeAndPosSettingDialog() diff --git a/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.h b/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.h index 148d619..455886a 100644 --- a/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.h +++ b/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.h @@ -2,21 +2,45 @@ #define BLOCKSIZEANDPOSSETTINGDIALOG_H #include +#include "model_global.h" + + +class DocBlock; namespace Ui { class BlockSizeAndPosSettingDialog; } -class BlockSizeAndPosSettingDialog : public QDialog +class MODELSHARED_EXPORT BlockSizeAndPosSettingDialog + : public QDialog { Q_OBJECT public: - explicit BlockSizeAndPosSettingDialog(QWidget *parent = 0); + + static BlockSizeAndPosSettingDialog *getInstance(); // 获得单例 + static void DestoryInsatance(); // 销毁单例 + void init(DocBlock* block); + + ~BlockSizeAndPosSettingDialog(); private: + explicit BlockSizeAndPosSettingDialog(QWidget *parent = 0); Ui::BlockSizeAndPosSettingDialog *ui; + + static BlockSizeAndPosSettingDialog* m_instance; + DocBlock *_block; + + + void setUI( + int width, + int height, + int x, + int y); + +public slots: + void slot_finished(int value); }; #endif // BLOCKSIZEANDPOSSETTINGDIALOG_H diff --git a/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.ui b/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.ui index fa19128..a8031fc 100644 --- a/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.ui +++ b/ofdEditor/model/Widget/BlockSizeAndPosSettingDialog.ui @@ -6,29 +6,179 @@ 0 0 - 400 - 300 + 282 + 328 调整块的大小尺寸 - - - - 30 - 240 - 341 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - + + + + + 大小 + + + + + + + + + + + + + 1000.000000000000000 + + + + + + + mm + + + + + + + + + + + + + + 1000.000000000000000 + + + + + + + mm + + + + + + + + + + 位置 + + + + + + 距离左边 + + + + + + + 1000.000000000000000 + + + + + + + mm + + + + + + + 距离顶部 + + + + + + + 1000.000000000000000 + + + + + + + mm + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + -- Gitee From cd96c7095be3a5e5cad570a6666fbb9819b41ab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sun, 3 Sep 2017 19:21:29 +0800 Subject: [PATCH 82/83] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=A8=A1=E7=89=88?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Doc/DocPassage.cpp | 6 ++---- ofdEditor/model/Widget/SelectTemplateDialog.cpp | 3 ++- ofdEditor/start/ui/PassageMainWindow.cpp | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/ofdEditor/model/Doc/DocPassage.cpp b/ofdEditor/model/Doc/DocPassage.cpp index 9b14a4a..ed750ed 100644 --- a/ofdEditor/model/Doc/DocPassage.cpp +++ b/ofdEditor/model/Doc/DocPassage.cpp @@ -121,9 +121,8 @@ void DocPassage::addPage(DocPage *page) this->layout->update(); // 更新 page->setPassage(this); // 设置页所属的文章 - this->adjustWidgetSize(); // 调整大小 - page->setScale(this->scaleFactor); + this->adjustWidgetSize(); // 调整大小 // qDebug() << "You have added an new page"; @@ -220,8 +219,7 @@ void DocPassage::insertPage(DocPage *page, int index) this->layout->update(); page->setPassage(this); - page->setScale(this->scaleFactor); - + page->setScale(this->scaleFactor); // 调整到合适的缩放比例 this->adjustWidgetSize(); } diff --git a/ofdEditor/model/Widget/SelectTemplateDialog.cpp b/ofdEditor/model/Widget/SelectTemplateDialog.cpp index c558e9e..693b981 100644 --- a/ofdEditor/model/Widget/SelectTemplateDialog.cpp +++ b/ofdEditor/model/Widget/SelectTemplateDialog.cpp @@ -69,5 +69,6 @@ void SelectTemplateDialog::lastTemplate() void SelectTemplateDialog::emitCreateTemplateSignal() { qDebug() << "Emit create template signal."; - emit createTemplate(current_template_index); +// emit createTemplate(current_template_index); + emit createTemplate(0); } diff --git a/ofdEditor/start/ui/PassageMainWindow.cpp b/ofdEditor/start/ui/PassageMainWindow.cpp index f49a9c5..e64ca71 100644 --- a/ofdEditor/start/ui/PassageMainWindow.cpp +++ b/ofdEditor/start/ui/PassageMainWindow.cpp @@ -1234,7 +1234,7 @@ void PassageMainWindow::setStatusMessage(QString msg) void PassageMainWindow::createTemplatePassage(int index) { qDebug() << "???"; - DocPassage * new_passage = new DocPassage(this); + DocPassage * new_passage = new DocPassage(); //********************************************** DocPage * new_page_1 = new DocPage(); @@ -1383,7 +1383,7 @@ void PassageMainWindow::createTemplatePassage(int index) body_6->setWidget(bodytext_6); bodytext_6->setAlignment(Qt::AlignCenter); - body_6->setPos(UnitTool::mmToPixel(120), UnitTool::mmToPixel(95)); + body_6->setPos(UnitTool::mmToPixel(120), UnitTool::mmToPixel(108)); body_6->resize(200, 35); bodytext_6->setFont(font6); -- Gitee From 49f83c3b3633b8caa1e109347fa945013125d07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E8=B6=85=E7=BE=A4?= Date: Sun, 3 Sep 2017 19:30:04 +0800 Subject: [PATCH 83/83] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=88=AA=E5=8F=96?= =?UTF-8?q?=E7=9A=84=E8=A1=A8=E6=A0=BC=E7=9A=84=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdEditor/model/Convert/BuildTextTable.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ofdEditor/model/Convert/BuildTextTable.cpp b/ofdEditor/model/Convert/BuildTextTable.cpp index d3e83ba..bc01e1c 100644 --- a/ofdEditor/model/Convert/BuildTextTable.cpp +++ b/ofdEditor/model/Convert/BuildTextTable.cpp @@ -107,8 +107,8 @@ void BuildTextTable::saveAsImage() this->table_block->getPage(), block->x(), block->y(), - block->size().width()+1 , - block->size().height()+1); + block->size().width()+4 , + block->size().height()+4); pixmap.save(filePath,"JPEG",100); -- Gitee

  • YxI_KoTTD?*?5v172Hbt0-h=^`-f%li|olq4|2^UPrrYPuZrJNPK@rVTzkqzYW zm{d(+L}T^H%SsWSdn1pXcNxeZT&O(bANb9WgT`fJ*$qdG2OSkIbVSudjFgbM4qrQ* zo~hA(Hk6T69AsucgM^!g3YNhjT5dQCmH=3-w)Qc6{Ma=8V?W49wT{#GagKaP12s-A z%(8rY7}gLJ5#r;+rV#9__?47j71_$AJ`2&E^|e*qn$|KR;J8+}K?E-2TJYG{nrnmv zWmn;hT6O?LfmVM>JtkZ`1w*+mGCbtjSR0LTk3!aAR2c4AO~W|S9UI|qKATc#<0+y9 z&z`Q^w610#N@0lLtrrk9F;Q802L zJUcP2$eD=%u@SLQYW(EymNdAxhHXMIRs6NXA+RkI49dHWeMp*%Ur@Y&mqF=6gn{DZ z(E-yWOO$TKF=WD|{17L5{J}r+T%uOwmmm?3@F6d=UIJ;S#eU+e=}K_kL@>Q+G?7VT zLwBcns}?oAk+V*j39Z}`so{Fj1LgV8hgvHP-d8Uv-oxcgF7w~mr_my`gro-0CmSqk z`LIq`JgsMJjG`r)@`==qiNIH*1SsRsiGtQ!K(z`)3e=CsFl`D*0OJ2A1d*N?mYIOyf_k;29&c?GFA8UuicdX9%{-+aeX7!iXapQURPQ15O3Ap7m+zh?Y| zXu-gV5~7M?f|Q+4(Ii;R^}zwkC+`Wfrg4IyjwP+TMDO)DxB5Rvag!oI%O>r7aFQ4f z2s;a@Oa|>fk5?bNW+>NI*6%Cz=E|YrQ%0Jap&+FZ^6#!e=r~WnuwVWsTn5(-fjoxi zL{%(s2cM0SLHLhC;eJSt00u=y@E^;qZr`O!9p@Pdyq&kKp(wmRCHDH_?8d!Nwq!$s zp43Y-4?8M+k~7r?k`YoueX&U>FBo!$d81M`PLgy_@HoUFa32VCF-R61#TART`x6fR z1X6L9l$4}ZV`!kE0dI~-yURxsfOStzPQ(@!DJcZ4owA<*rk1cU*;+{l`N1uv;mfki z&ZmVksYJku&alpzT<=H{>bpa4i@-?55(ml>3;FQ$&>(+8#z4Zj47z*`C9((Q(U{@l zVlR1@Q>%;WH)!Ksv3it!)lu5L$#rpA^0vmiaFzNDY%e6sjF0-j`|BQmVmhIX(YfoK zK%eclx=GwUDE?u+N7!U0=%is+BQ0n%$%c#KLLcKy30kxG7&&uL#9GNv*+x5ht7ImC z@S6;<7$JS{Wrm{&K+)$WyEWWFidA^!u%p6o(12BlO5}Ku3q2Fw`Qx1kd%9$m@soz(cVCp_II`E1Lx|Ya(Dp>_s8$;T~-#rN^fswK4xS8jX^wj~#^SweoEa6VeWok5M*S~+un&IML ztA!XY(RP33OAuTr@ygRc`^8V|&`zOSV`(#!6$iqf=)%HjL?z-v;Vvd*N)HIMW)X4{ zxf&+(j~>qlR`JL`J4a!$N??5QPB_G|&#TTprYj?1(~V6#BklN5uHR`^80K||flVTC zI%1A0KX!PX54I5;ZfUYOw42BTy*Sv`Fd~UL)ENuJ(SL{qU*)dy^!p_ak1}KRd zJNk-eu<*3CH79$Hh-K;ao9AiQ46_M}Pj`8{XI1p>=O2p}*zC_HM`Ivnsy7AeOR>>C?4)J12mh|mv!iw#ZK#3Ng^;)Nf<|d6o0C=bLdA_lCLl~ zBSzM;-@+z}aQDMW%t|{p!?~Rba_r3LOI?EweinAbg}Vp;$88-+?Doz4M}W0IhkJ1U sM}UPIQj!ugeh^^)*Xe&z1P}h=T7t9r2y)UN2Zo?zBoxJ~MU8|02h5ev9smFU literal 0 HcmV?d00001 diff --git a/doc/imgs/image38.png b/doc/imgs/image38.png new file mode 100644 index 0000000000000000000000000000000000000000..12519fd615481c3d924a8694e59fa576682b8c54 GIT binary patch literal 29762 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 KxgWCTLH`MFU?lJW literal 0 HcmV?d00001 diff --git a/doc/imgs/image39.png b/doc/imgs/image39.png new file mode 100644 index 0000000000000000000000000000000000000000..561dcb9760034020fde327fce8367119d83c55b1 GIT binary patch literal 49542 zcmeFZc{JP4|3BJIwOUjaEk#?UMN5^?+IL;-TkO%QEtb?yG*Q)-QnW=CweN`twbhbn zi)z&t5^7CL5eY&iLL%I}Klgj@xBdM7`Q3AW_ug~v`5Y&&#GILV%{=Eh^L)&6o{xEE zX>P*HBg(U9&mP{JHw>-!>^ZQrXV1QsL;E->wf8JkIbVB2tWEUyRQI1=!7j9XevCmFu-roNHCC;BFD@#Q2NqG2t)HEkCA`j`o+F0fj+jr>9!##gIHh7lYA%u!keRPH1c3qXm?vv(hYL_*X|bIe%X| zb{y7D&jscF-hl)(|1@WRi?$D-?KH0Y*2n`K=A9HH5 zjh{=~ZhVwov3q|m?u~`Lf2_{^?I%`a`nQxA*KK-x`rbx;%%`LZZ%0I;vI7SW3;ZFy zg4_cSa9xc2zVyLLblcVQa56s~NY6Nbp2^1tqGc&=&%Ab~j)yKLd-#>N#XL1L(FQE9#dy=R0Ld)POkwqnW~k+JKs;y>=YH580%G4ZmsuIqaq8a*fe#$nSW zgk^RVA0fSU;;-QveDhGm^}+7YcPqgdW}`LrVQ>wuVgDp!)lwT;E{-0ikp3ED#{ds8iQdlkAq02rOJr>FBgb){rRzl3;g zF{`w6|4U6{H-xUy1`T4ci{2TFqrcqPg*yoC%on8Ar7mvQrYH&yt>v;G zrr6G$N1`!CaqyU!^?YI^ez$GC#5-n{RyvVQxaaFf>{{%zL}ACK+%R{|DlXMu zhrp=ZQ&}m^b;X$dIpg;79*f@x2g`!f{H~y0PdKS1C;LjmYG_2cmc%y9+v?n{n0%MI zs4>g(iCt*iY#Es==WA7<$NC4CBh}ZJ9`&8ZYn3#iz7GvktK>ZwnukXtl>Tj`+@I)r zG6OUji5zXx4#MRT-@aerkJwp;Gbj$hABrWKyA^iZ7N!+J4+!wo=+56BBia~-%lg16 zKdhL!dh?yOiDkhycZ#d(4^zltu`IFR7yYH*TD#TW;4pz6KF##-Vx2%4u@lH*^Gtpx zZEw%^du-e_}fjT`@8@l@>_xq|;w`wqzBC7}SERQH3vX2^`3C zTh9N~le-EIpJi6AVS}?>F_HHQuAa-(nbsiAQzU?Pp}XjJH=)Cp$DKEf{#bWn_Z|7= z4X@lMH6jPSLCa+?=c1#!Y$O^d%y%&m7C-!Io##fsYk1U;iG!(aUd$1Z_KimdDJ~v6 zj<5~s2EG**Yo*I|PG`;9jUI)V4_9bvX%W29=bslWtQbB52^C8fQp&t!BSmo;y@SrI zZBE}>pBX`Zd=<@p3!8;gH2iPS*yFpdtpn4oxs0rQHdC#M zxE9|UHi?Xh`Uct!A21RD(WiwJPhVf3o0sH0$fr}vRJGtmuU$6&6)qDl=IaqKK9-ep zb}WF7dUG-gH`pVs{$8KNoZB%cOxJ3NT+X5>E^FjJ^1VKSxYKksVjwU`PTiN=Ksz*U2->pP{99AaHrR zEPJAZ8jr@GHtb>UzKq%ExH>n2)j|#50OLA!cQvAVXAU)LP7I$|4y3V{L=*{NW5!ey z`^ySDe{9%yXN;l5j||363rS7QW+1sMZQg0D5hm-ca9yDWKWGWQsku{Ewem9oL*cs1 zZ5WU2{m?r}0Y4tzBF-%#ZQ>&kc~qDyGjw6lp;P~+(1k0P8)36kNrVD1e|oMG8x6F` zl<7qbk)72~Cy5b)T7L`tX~1egXRe{`W*61YGvO<3qq+Adhco>1gF4|%5o-Q=Kb(-4 zItk#bn^1Rh8mwr`5LQp*!>$iYx6b;1TdpPJmm+gZzI|;vQQX>^`%_`}6=wReE%Qhz z)%UWW%A&-bYWDldzVFL-mjcUTf*ch1j!LS2V`M)`noMoAQBnk{k48tw-pD-lxixTW zJ3srmMw1JgVg9fyd1ms~Qrw>wyic$~mHa+R`eN>4O$XnRYL9zE=p6+1(_=&8f)4Aj z_uG+)X5z|iP>sXx47+Z7F8=(r?niUca;?HZ1+jZ6P41)3-zhs?ySC&+ioMLIfs5!QrD+`h_1)<|-ZP zN7)J5)z1pQp@!r$9sb^1Ba8w?oAGj$$Nh-BB*_w>a6|~8og-Hg+D!w zJYPs*kohSR+mlwyY29x(OSL4{eyCw~d!@6hCiGOHV=s3Dqkm@`<;;X_ zHSb!Uj^46v+`f>64 z(i*n+*=YT#XPibADKh>XQqHUXFI75N3uA?UL*AhOWq9`Nw&NMPev&*JPq2b}ZnH7;^e zao;wck1-iSEn+iBiQ5Z5E@&|&cef+j!2h7YqvrNw5y3Uyq2W7J8Ezz1lCJ;og1 z^1fn{rGav8eBw-aHKGplGz=0H4^+RQO8;}$W6ht64m4x9B0sF(iH z-Hl1*E1gPpi#%nVlSy#H1t@Zq+Fjs@0ECHG?tBq95Kvgu4r%UJLEnlT(9WCM}8fpK3u+^x;7Ps?u_j+0o$Nbb(Rl5~UYG|#t?91-98 zV7Fi&X^w$Rc>uF7&_$==o>gUEgu(Ts>|+k&WZ(R^|Ap(Q;c>I#J_`OV*ZYDdjqTBU zgNMI6cz!EsFI1V=vO%E1&WH(hZ_KRMil^AEh2`L8WZUE2-?QMD!sihsSyQ1KTG&-CF%TXF`Wd`{%1%T545JM(8R2Y+iD( zm{;i9wEkranypm;bj$hhAFarZdT>_n^!rYh|LLW%cXzAvjzEQ3$GB9kT)m1>Pku@y zSs!%T!N>%n$66H@I#nP1H6wWBe>99h#q&JujjoR^EzY@7E!w1(R^v5x!`oS5m#+V? zN}cq`jF}FhW-4OA?cG{;x0L+yr=zR47M=r$$zj@REc=qGt(Crzs0jBD;!a5X`+J^p z20GE*w|Fb(+SD-PI!`htUM+dy*R<*W;c;Ygm(;rB#B(}bTLPIFqEXo#_00Enczk<{ z8D{0igi=#w6MkFc+Nm#(w2J$Sq=%j5<~MJJ8rRjC65Oy+V=|sw!OmO4?6uFoZ!A2~ zN}bB(e$C5^av5^(K({M=bkMj~=UxD*Y~6ZPi)E&%PY2-7cAEUTJQiH$lB)~6!brTw zo$1+Hw~S_7WVGyJI`|k<3oaWSO~hKyjID(wJH;du;PuAP;2J;n??j~v<^JDc^1`j% zRtsaDFj&Wc&c9$EvVSN}tgJQjQjqhDf8oAKPY&*L4f{5grp9~OX;7&JTZ=7y`pfg1 zX%@5_AFMU%JJDNL8j?!y4-?opSMUlnde?j1RI{fBldj9kokL`o(TD883W|g;j%2UE z-M6k_&xl*C8`VBFKO^o$EDS|GaGkJeDWFfR-u%;))aal2PPnepeUL&Hqliu3iH~1y z9FCz*?8N2w`e$K6GF>G$8$U{+v#|6oH0H+(snItv_W7`zE(TA|H=VN0fu2?LnWu=(umh+Mnuw;z9 z+qK~NZ+$wVN8fJWGP4UHR=wSexLXCu6~Alt!rq2*_sJ)BB$e8$k42W>PO~n>lQkq~ z1zTteVi&!Mk@9;@B(xC(;74Fb<-){Wf~so(rqa;vV#8c(_p-Q6ci<4@oMyQ3A9Ex& zdtXLY^L#&6+>~{{!G1>ke*(KEh4cjbtvvPg+9#tt7gQD^*6bZ>QNCvi^S~GAa8}a$ zb3wJU_HJg`v+(Mm@U|YF&LHs8a$QYF9kqD+K<}-@K%z&4qg1kPc<;V$I%F;lx*xLO z1e0N0&I}cxc8+_zH^i%=S#9r%iUavP%KV$){*`)X`gxEV zY$JKVuBZJ~`XVM^+_PguY^aiA+8$ClYI_GR?|K)slZ)JZaNUDwvh=rO>YmKt8rege z@yJ`}=X;J*>RK0FIYN^qoj(a>pUM&{mgcrMcdomLy4mDpz27|X&;B0zrTe3CB5)#_ zikTJZTq5>bEZ3~}YwUP!@V8F~n{?_p{bqdBpq^|OO7LbK`4t_~HW}mz=!OpF7%r&}#wT-Xe&&&w~ShL0R2`8~el~h|ATaZ%_Z~7zY@l_C2Sg zpq`4&zg~&7{orbJizE~5_f7VqFq50JM5n#|DgRaCIO#p5y7l29q4%_*+d{CWfTV1e zsQLk(vmg2<$G<(+*+B{YSo$w;rb|n1;chD@G>m$`FI!XM-p&ydh^^vEaC1CjA}JZO z?JWOc?7zCCyU#R4h@yHelCkTxW>FPVC-`sD@YrWa{Jg!X@^8s2T*A-kuI+F(u$@UL z@tnRBFTS%7v$N0#fv?9&ZvQCBH;dTK%F3dk+jpj;sma<)1`@wtc?~|m8)OD14B)aN=X3a1bZKi*+AI04)Qh0eMrlrm9*%=x4wZ^TB+Eu7|kZhwv`r&_V!PHQ23bVE_1Zq z^lV={zAdUgZY9>nLJLqKiu>uvy}Ong^I$ev&G_LGM~z!zC08GEcbc@$B+8qsFP1RN zf(HZI?sg@5q+FL_hVE{5>+G!O?{+G_8nbDaIR`g=8Xw=j*`+uV0m+4AO6ZT%Cj`AZa`_4~^? z(uiJZUg+1LzRk|I9vW=dT)M+=lW3Cx;`COB8a06Y`i3U93yEP(#7WQ!Sj62OK`Nb50g%kAjkI@|_}TW7czsZ3|k|twoC%1k0rrL)B?t7yF0|) zq{Y*d%clk+pTZyM>r{_p){-H3M#pWp-^VedS6B~b1oH<)ZpXyL&`yOZKlrDiKOP;? zW;73M4M7@6rTKT~>N)z&t+8C67NJgb3{|GAsIPSjhC#Y_D<5!_8#W!au=pnR!7nMl zr{UD+as!e(tK7NfIxs$MrWAw`LTnopLE=gtXg2K&+m`qm;Cl7)Nz1I?!S@gFod1!E17+CZ zY2IZ^))-_6&y(zlAT}AO2wzLu{hitVhFqa{lfM``gO7W^B`EzmNfGNXu!f_X(UQ@_ zn7PXktDLXJ67&jN1+#{@?HxutaLW%{z6#SUQs^l~LkYp^1s;K|Su}w)KAU zk%E$v8^zr;*YL49&dmPx&28hII-+dCxv6itiMTV;gr!#$r$9dm=Kb*emumTqR@?oE z+U$_r85@8%wzg{YuNhFTs;iS(RZd@1v^E@aDP=i<>RZ3kGSpApw%ya9n&a$hWF5}r zG{0)>i*&&Z7nM9{5`&Sw_UnZ~dR5-~+Xa&GZ$xo=*v}^-(5}cSid*@yIrf6Q+Zqr1 zz~K!9vbu*UQ~9|fGjx3BO#DjmQ^$b97-U+0zg8SHXvukL+vnmwfZg_{`09A{#6y5 ze(*fSws^C|JcBZVa(;L3W-n5B&ChL(YNQCoQQ-^?!2QK$mye$r2Y;F9FkhON3p)YO zi^c$c-Ziy3Fe22Z3K<_UqM)MR)su`UK zJ8YkH*9S1`jq;JEVp1V$>_en;h=Hi>4bzYVFs?=ETsLXkBy5uKW$XL&sqJS)=s=@} zUC7wG(s#XtBC2nBZrRhjFma;ZM4bob~%Yk)OG1 zBTt}2(9DlCcwB|#W9S`2Ly#RRY& z8~o0YQ_!iTGIR@VCTt<*E?sta%OY9e%g5Oprpra-UsYzw{uvr13)*V=k3u+%sXy8Q znzgf38~?|)gFpChTLz^Rc-u<{OdZd33BLK3EwzCw#EW_bqsOc8PdQ%_*-t#wb&y-P zPZ=n&@^`n(tv_;}3!4`R0_hjRUMEZWZ$)ah5Yv}oiu<=yo6ZR0(-X_DE zqb*zX@ggVCT=o;3c=bf|fEMGqP3sTsTaC<)gj1)|lL0EJ~L*|6gBegH<0zYnRu`&}awba>O$%pYRTL1{P>`O6PD0M3dh z@mkfmKH!&I#3w(u_3WN0eP?mHuqXm#im3G!Cp~4;6qO?zPEt`nlwa!nJugE8?%y@(bS}J#+KUKR|iJdh$x{cdQ2Oviig52t!=DBLc9miOs z(L4`$VwneKj6q?_!&2|^5QKR_XxSSaP_KW~rNCRHA>#@5`Y;H#cpGGmbnokL%D@3F zZZls$hiB6e1$?n&J;d4c#1t%)AP$4HE`El<7nQs7+J2`@1V%AFAkCPtnKXW_-5E)i zIWCfB*M4j6Sl{(3?z>%@7}-N^x!D4@ljWdqMx?K_*W>RYYO$h?D0@%o*ym*m>qY4P z3Y&^O&c?Q)e^vj^igJD+hinq#O@#bT`dM+zG1pnOn+(NO()7RjwWMUCbN4SZeg_-0L5r{ zCrw{(R37(y1h6k@r~pSMX;1aFYULLW51X7**X(|V6~z}^ zLp4c|b9Xpc-9-nHh|UhW+&@v|9t*hPydJp-w~ya9b>X8MCD{Zt!d%xAsPDHmqR03$;B#((;>@ShBpf*RKeTRi!_nu8&5CV7^*I@zl)E z?E?U=hwu%$wVlD&-r3Hc4Ea8_ayR0rnuzHL4oLltFE3k}ux_Uats`JAQzUZW%7_x( z?zB=yrTRf|;AqPN7hddZLex$CN>Ni9K*Y4tK8RNrd0iMC7^0n^8@CUYiWLwV1ipeV z(dR4YMdiXwK)Gz?{H^DCyZEV5;45YkH9&25KYx12$E(2+OOG&60U6$6gm{ zRt8SAq&1j3!`^^X?U)3X9!45>`ZqR0k~5xtcT3?s*@k8oAHZssI)~;0v<@#Gk;}&c zp9^HYCOH!Wyt>Q%6R}JgrS=k2;zbyeB=U9#*gi=wMl@wry1b*t?6O32iaW@LNuQhM_r9zNk*aA5D{j*_Pccn9S-|BS19T_=nbIf=-eEdxG2}!VbF#8wV+?X8=^5of{uT%5)sdqXi3XxT!Ckrd zl}f=%)Xm`_id`v$%U8(Q*KA#RQO$Fx&L{8!%y4~$6hl`*XSMW}8RgM0h#tAOGpv#Y zzE^OwO;lZM!LVh2#(A@EZ(1&p#$hkn9O7jIU!9%SX zp|beR;y8+3`m`$jJqG_`D51T#Ojo4Muhne zvN*+xIfn!ejHg=xR87zoG>Y4RhcA0(@Y}xis`yM0&};26*~4}Yd?{>~A3(}tLlY{WX>=X_$uCr*JhPwgc5H77IP93@l(D#9DTa4 z&V5B5lT^i8hWh}*4sVQkOG1p5!X&J=Jg|fzLwnKG09D?iVb;~K;nf|(+=nXH+Zg%e zfQlwxr;&b^AVwrX5pC)murA(tTZ6gY6O$UFuu*UPq1D?ox%Znu-6C-vWQMwdhMSJ# zrwjz|_>dlNJvq4^c0ZJhZf~xY*Q@Omued8JibsrwD5)v8-V)ErK1GYZK3{gBRNefJ zc2S1j-4P?RTLRv=zJjl3Xx}-mIG|h@FqZ!u=ZKlWHvnF-X^oA5_MI&mQBE#Ioi=OP z-CfQFtW&}A%?Jt#b%P3%j6HjQ41iM#%&>Z{;Y{^dzAClP|vlq|up zj4^WS2-wbkEmXbXs_bFE6KSIFX&1bF?dkqNsYZC8-+`3lMtzB-ug)U+?Vp5%@P=Ma zuaE)I&e7<=Fw6*=mu`Y8UJoa|%y@*?vTNtlp%wBQi8x3l;kD6MH-#St1jjEJ3s0e{ z+#9}D=xbnzx6}Pz9iq1lTKM$w4UBi^ z@K`y1dj5;?S%wtvWaHp_PR+(PEMbtPVHP%PR$0Wb5j_d&Rsj~GT4lc4HZq3}xvXo{ z>1sTdu>(oPH1G{f=e~f(Y`!VI)$;yjmc_Me$)!(kEsCcx4Z2^l6=353kN}}R!0|9weTWJ&zgtf zYfjWUVDbovA zo?)$O$}`EWrO{&6b)Ye*&IR!~giJ9$Y@#S?SW+JDdZ;0v6!A>8FBBqk)HX(cPK)5= zU8TrGOq8fwkJOf>?<;}ZeBRywvQXoZ6rU$H9hDMMcKSpij-7BQbALyY)>^zOBI#!(n3i0V00|oeGtLr=7hMX(P{Q6911Q>?9=YJQE zwg>|!Z0cG58irh&GQtw)%u=v@`9B>koU-c;6vb&27d>+wS)SY3ORjyQyalb3K~ zn&3|{+H@q1Fp%r^bFoG}$<3IAwL4PBtRn^EpJP$kKbxJ(=v-p^Z;Oy*G;>uJPGH}j zYJ0~)X~6yyprlS&yD1zHlG&TumPb)Zxru&FYZu)-hDkT?{dNcbp`lKqmWCPKr0xs* z#R0s%W!jgpS4o@9tE0e{=`W*~+_pjQ0sI6R4bp85UrNG-Vq#&?NIpdHCL&8M79pM| zgp@PMTx4UM>eE~0cCYk1DPnmj^xav>-ObJBQCdba(XeWG(VH%Wj(l?Uq5h2;=LQK= zK&0KrGf+U|=IG*vb0E)GOfI)i0_5!)X8M`RrKqL!c&Km z8)s^FrXIUV%L`VUrVe!PYrLb{kT(ky zb=hcWD=F9N?bqp7d5j-%{PvS}3|<&N+Of_UvBOly)UT9IIa(Li(|GIR9O1r7WO%O(IjyaFP{82RNHFU+G7{nVRF(})OW zpNu=k#14nF2_JdZAC`f_lIx3I%2k`d$V6Z6hFM=8;k09-zH~eOg~DQJ23-C&mMF+) zyD}9*g@N6G#G?b`m>k) zIaWCzM1QbBHy$Z@C-+b$)y`X=E@7MM$vY&Nz2kanLUW9tpC6fj$FRjlDrcrN3X~UW zlU6x{5ng!iD8l805gKX6o86FU`AE}iNJn@y{*JqEnlEo;!V3|ulB_yQ}%1q0p+#$ zS6eB?aBJupbol+S5WinPyt=AdpjzNe|+LO!B2}8TDC{D3i(yJP56pgWHGTS@g7fb&pI;96woas=m_wq5Feo;PbEiIj-vLW zrH%Z9U~C|J7P(5UuB>~La2)ewMEX4(^R!%U<(9FYehClZs_lmnR1q-=x{UhS$J~n} zjOO)h6wYFDPQ(1{Fu3;7Ih*~J5;bxnjdnixht^u%KD})P`Z3!X2k8=q9iKu@!k!ex zYi1Bhq;l)^>y_CuA1E_qSbQbqEy+)Uhi-QK!IOLN*L}}Ph0aAJL%^1KKFcNnn0$7rPX?0)cR|O|FBYNGuO(Fjqaz3NtU)xUEzva@pUwqD#~EzFMF1@dxKu!)#R=@Jq!@F*)_@JlnNwew+S!)0lCN$m- z;+BjZIenBFP=clpX3Lc(n_ke3E-C_-}un%o(G1hbTGPl`~A7vX_Ja&g(9S> zp{wnAI`2rA-7Wkf1HcwSzya+*ROO;hYc)!2IAEU7SNF2u>{n+9_MB^YgHUC1bHiDG`b* zXfnszDS(YZT2oL+CQZEP2#VVU4Q!mwTs$?ElWSz*_0NGBolOnP9PDU1xZa&VkMIf! zoa4&~UDN0uIp7_yd8G3hwy#~u`Z-pvO_X#ZjAl?$c}}!hc$%~E78qfX>RZm`EXo0l z4LpZ$>jDnH3423>+bE6^9A(V2I4(20P&~E!n#rLl6A1ep^O0}09$gi|`T?b$S~@f@ zZYDiiXEtTvPy298z0hf@bT01D38R935>oOy=JD{QtB7)m2BGum_f_8C-gQRJLsf?c zYTjk(>u=xL12!IJeaW`rQPW|PDf5@n96Qk7HiV?ks`Fo?42$THm1@VM`^q2Tfau$R z3kbJ+h+S~6$N@0QE&^0)mh6j1KQ4&rO(+Gni?YfWnn@(&EakbAh^+;N{8iBD24;nD z?+4V$uFY2a@Z}5+Hf*pjES)#i$AwwN-@^c|xEc#_*$GVfGR1v4qpzeQ=KyQzO){Ob zh1MP~&+U1EXm-f50Suw<&?`s8B8ICg;{5?F;9K5Sq~BRxMd@UM769to`esx*QjgG9 zrRt`|O#;z|%RN2t%{S_zDw)ur0?E(rCZVh%v~d@uD>3gV{(SWj1aKDGJ4AVwfIcHN z7Kj6;dbTWMp6xG+QT~_fkox=@4p?l2w=MGgrBY;(mhWfUFn$dG(i(IG{1zu<#fS!I zP>`nRMAP;3F^*OMenhsP2|YdMO+U2;#a5hS?yN~v(zU8id4`Ea+UzHBTS5wE3_--D zzK@GlrtbsHM@LAMPsB#cf^ik#XtJn-u0?CMnK-Id1|&d4+D@j@}7ps0#H4 z+^0ZixVy3M7}}{xj(|GnD@-y!;dkXqH`v{_)$DEYBF<7ofB6NWC9`w)^Jwey*%S@) z4k+CZP``IfJ~g;Nzo7ay=|0~SfA$?`Se%rws-?Y^h^M&aUSpi=KsU}?rM%ivWX@VE z!B3gD#%owsg}(&B0g8L4;;gy-r(B=8Js@9qmb5xp?J{@6S1$}_Y71QfzEySY&e#%~ zmonZSsk;3ZNnI|!QDDbQdr;uE|KrD>8%ChH2X#IuCQVL6cB)eP3dg0%Q9;vEZ7;Ax zMdxV7kn9Yta=4s!x>7{Y%gh(zw{vvB4T*-|px2dAhq9Z}u-$lPH%Jv{c&2`lp=ab9 zXxT3pobH;5{|Y@!TQ8N=4I|i(8p5)CES6_^<&dXf>zW;Ph_P4GC;(bqw|zEQAn&yReNhkI=6~4g!xoM){taFhi$#19%zyBG-L1uCSCe+9p}ToYPJ*)=oHjLh zEpx*%#KcVA^I>s{`mNNQ>>8!e1w(<`R2v}|fbBc4#KAmhkzL-=JX`s)if^@z37>N8 zLDB}f=0}DeHy-8Ik!V){vj~(sY`#It9U~j6@DQ+h+~|oHUv--}yQj=a$QG8X@2iIb zPk*GJFO2Q+YLR7UIDTqzBFv1I&TF}cTUHDXWI}l>K8`V7%9s#0ZQkbu8~17mIWY#q zU>Ypij4g$nX8^mnxboF;?PK%ow6~C(ICpamI-hxD_05HWxijajxSD z;<%j4@B^0X1-9VG}g%FWF?cTN~kp;_hhuvnx&`6NZ`?a6me zv4k->xJJmF9!eK~MiwY6$AcV`hK4q#I8Y}l8 z`@){7L@+m>cudYMSGjM+%82%dkK#WY+qY)5w)VC{*Z5eSowlRpXK{sCSX@;jr&#aWJ^#U;F@1AwO{%CEE=Fz&*fy|R zk&WtW6RP92Y5xeAGVXkK&MPuy_lWuBEIR67`Av1a?4`0e;}oBk7jHCJ;luuil*-Rq z0{aqTJJqYO^%RL4Rf@YOT3bg=K9(P=ka?j`vs)ot4PrhTmI|g}swGR_D6Y26kXx^r zpTQyZmVL49uZ%%`h@!1%GsWDV%j(P>=D2+SNp+c>=k7)F1Kh$_Uh z9n2DNxyE>ln*nb`e^##Aqpnn%RAo2VuMql&O(r9K$saN zxeESmq{`{7IBh~7Bh&_RZMhCOd~Y?`!YS;TO^HksQ}ryf+O^f*27zDVpXtB>Ur79} zudv{7XaQvg9ZN99(DZscDG0dK=RSsiNH%?sLA&XLe8O!W`q;>oXe~--bIQ00q*Z0? zy<6Dg6JVz;*e%{0lY(~;Ql7-jmzg+BRgnFQO4|{ANVKCEUbn=%Y||n*JJy1K?VtE+BHvkCwUZ};z8KmW?tu`mMb&-A-Fkv z7GjzxzXsNq;yMWEC1c=6kcbO%LI%o2pD(4xnO**L!Ut6?ZSr;N)MrlLr+_;o5+y7$ z#nI0!CJdJvBc#j(t7%;V7dZ{5h^Xh;$CP@9hAG+#CL50#9Ze6|QNtER53LHODRs46 zgpdR#O;1#sK?3fYbDb!!=(#Xma97-sEw1urjPY@><>FB1b$F+?=qu5s`jKCx33nkd zd@?ktf>j!9Xrc&9m3_~N5wm}N){16l!OM2HSIwbV61E$zWRyL$W~c&sM_dj$b>l2B zqE-OOR;I0qTF@I3GO{w}S;##b5Jq$msT<~zl7JmIQ=G?3IxA~;S}ZYxhF{V>OMQ(1 z!cN5RqNT^%2AR{AmJE9;KH8M7JbI~YT7Lw*HWC?a*Y{u~^e2v`M|I6{(!?+5+|5R2 zM~G;gu{;!8k|ZWnWIZNywJSb;iRbG}0o{Vb`;HW$Phm@=*70YA+4Uu3q4;YByLKc( z8O?#=;UkxU7tC>5R-xIV5}++tLxk*eOq_-#Ue|{B*To|Jz z=LfptF*az;whYSMaGvBST$n?08$q#h`!sR%yJt5x}+cgkSOg`(h)D2eBPzp~rHUojd!&WT-H`$;w^%!HCl z7U*h9M1Ij>0hlqn0&H!Q+yabihZKG}6caW%C_Q}KMajg@*GX^g9;#1ROVh1`4#?KE z89;{qVDW zq;6JmemcGXowYYF=9r4-utk(DLv7QubCii;t=HilGTaTwhZfIwy#h)74C#`syz5TxAu7SRFB&lXJz&`yzp ze;~S*a;7?mHSCCqyLjVb>_xSws`sCa7)j-eJ;#EbhmQ(k6FZ}5K$|@HqjLxNv^U*7 zXG5O_N2-*90PBc}Ck%5#&{Jj*^15IS6h!%Eh+<JLnb`rBHd(=kuhCpOF^K@{LS*KBO%x{x?l-4 z1QW69h5~O-F&E|wjZbClt$6N! z{nEZCf~zLPPj+Wo_br@ddI2?3ChhlWGMhGnXH#SRxUT&lRMQ&|NzQcDis#s|Df#Zx ztJEdF{+9w*_8Fo_rVsxeNo+{0h<;dZ2iLC>_~8|}T-qtQJHm56{J)q7FCJ=S9Qq%w zJPT^yy328$3lXdY=C^YHXY_GtHe^0G(DDYSwZxA4~`choW^VRPKu`5OYEreL& zfPF5Yh3eKyxO6inX16h50=#11+|j&%_N;=OQ~E1f|DTxaygj(4$kFG=|Bdo?{`eWD z%*SS6MXe})Z!=Uc-5lEw!(=MoC` z=o`^0N`A=Za4T78C4k`{M2x)$#$6tgCg#=l5KR6`UgF$`F&>j#dG;^) zaQbOTRBhi|q5W5~d;1>T=#HN$@88l^<ApO$Veu|2 zQ2>?{8Y?UR7lwPNE6%}o>VxB(Qgvy?#c^I@xo=T>U;229%MY{DBqs3z)(t3EoGSKg z#h;kD>ln$QH9WxZCS)8sx>(L9R4kW%)j4+T>&G4JS|!(oMTs}xRYt^urwuhSts#%% zE==hxe#9_M`NC<*8dFlrIZxH=y5>lKBGnpl6%NK2N0k};y)h{zsJ(Pxt!Q5VZr6{Q zn%Y0!((0PTx%Vg!=RON5$_;yC%CLa0Hv4fh6i@z5_EhCu`4;fMvG<-)O>Rx!xS|N6 z6h%PkiUm*Yu4z@-5K9{YVVh# z*%E6PQckc3rSihor`>41Wp1o#_&z3(K`BkCE+W#et8$RB>-AEWH^U=NQ->-Yb&x}(QS*tD$+(-7gO=6q39D+Ds9`X?L-tPvF9UUdM{_( z?RRnpxc^*B0^jW=_t$rG#dQ{**zSpzDFD9*0h3Qzd7-$XqSrR?ZZ0?2!#MD-*X3A- za<}h!!zHl3`{wpJPq^UvpFD=<=W%@=-?+vtihDEla=SyodPsbQe>VB{qd)wC9f8Ne zryVz)E=1afkHC4rv@ZU&9bI!1ceXpHomYUjb5fwV5$^4(RH=Lmuua)tY@@{YNNhVv z$!Oq?+-<`wr%B6N$&=k?z8(9())GA$pa-V*VQXr=zGiiQxG+%Q3oGm`E=)ho6yidv zNy~~4)h5T<+I)Ug9MJS!fGK#}W&3}4%@1t&pcbAn^WxHc|Hh?PzsutDgxd6r0>-3Q zVr*^v&TYwEtl7@(E}sJ*aLc?OH)B426o-Y^$*4^Xq5AL4i`=ECG6lfR_ZpHjS3F?j zm)GjwN^GweqLs7zHL0jrc=_zj(T1v>ghvM7EuKeOuEdET4&q$&c-p_;gv!uSj*P7Wi4G%8$UXTQKFFStB4>@(hY*<&39H&3!p%x&_YI~$Sm6&VzE7U6wrrvI6HFoiL z!CL6Xk6iVi&E>fMycIA0P7HjJe-7)3Z8E+!@n3+!V)mY4``6|4U*S6%6*b$Qz5kcb z_UM=vz4k@a^FOfx_8}cWCBgpUwe120$X@_{pY^w@i`$lVOG(X304nwP#N*pV3ZM<2 zf!dS1Kb-il;blN&WYqN5!R_n_P@9{8MLy@c-1^t>8lbY^DlNJ9U+2Y1zz{d@Dog%r z*dI_?F5>_2uWR_?ykNmjW(yzM&dxkq;+lZUn)$x#|3X{d1%n0SHU96i|G!ywRAAYZ z!yYySuV~U;zttpMRwW z#@Q$?0u7PrqW(N363UB6Ec4yA^MMaI06^%~V|sUD{Iusj=`sffHju^BLs@U!*I-i7 zI+81D)GRW~MlmNL(!4aEkhk-=#vcNB8(>+q@GC5FA<-Wet-ea~v{>t`mSj0Tk35hb z{JMr_rF`R~=SK~7ygw+$po0vCKlCu(AyO}8q{DCHQk#2?w2L?96+6k@Tt#CW<7wRl zJbF{oqgwBt3zYH8VFMk@6PM}i&K=f!OwPkrs8u4vU=IkKR3rP8~E_p z!wtWe1g{bG&{;j%g;JuZ=powK{t=PDSb*iZ`UiGqJOMgZ;icnbH0C*@N-98^85|sV z(1`gUbidwLukQ$lyh0t$HlMis$FzYIa1HLE62U`Q2_2r=0=^P{%E<9fw(>*{+ip`n_#ryZ&F&f zkOmW`>pb#&rtHV!yL_v#Il-O6UqAD^SL``eT(eDmHY@_ME+Df$*kOBTbgl@iRHO5DtES*uZT8PtX(tNz?+PU);;?%=Tv65{Hv>_Lq(f2Q{a_71YU$Kj6R8VyDOr%?l)SogwKJ{oy zVp8M`#4+ctd`d@bb=OpC2mMqW@uA!>U6q*Bg2v>IFG^Dmn?RI4YBnj$8+RV8{V)an z;!tO*Q-XW*;92%7rOG31<}$@T3eRxsnkw56S#d@1aoy%`y7^P{^4c8Y;^O3Dh?c|^ z+%j1=X*SY+Mc!}0+>BQ9iquqq{@{LN-1E@`>qygU#N5n6N?H^uO+9a3;KZ&?PMKj;|TB+?`bN zQI^x9zaY;ugU}pWINbYryU`_Qo$rts@{mQXfhbp-F7_W1GP(l%D73jzSSe;nbqvS>yB^@61`g_u5JAG zfQL=jgj8rIgYeaZ3o-v{*Xs9~nu?9A$sIw^U)gKs?vvER*{H5Xk-TpcZCLbVAk7hK zm3Cb_+uB^_F8=D<)iae!m1@c*+YaQ0Ua*vlq>W%W`P_1Go~rw9lnJj$Lsy5{kjFif z_EP<{jT(#ZCl`x*;;ZMLcz8IbB4<7c_zT?hPb+w!h&*}MOsSM*ZdG1~B|}NDtu!$` z@4eH#Nrhp~jVO~TNnefJm7zZ>&rTl&sC)QithThkaq4($+Dp62)h2dwo?PAgoj-}R z2)>P>60gu0?@>XY8!3LHW+pZiy1RR!{TaI~jLTB%EH#Z(r63s4(=L>!?F-?Ifps=qkI+1=oLK|K*Nu()IK z`k2D2Fa(ELHpRj)vzszmQU9iWQV(G?aX9;NbWLeJilch}CZ}=$aZa(TJ!byIfYUb8 z;;=JyGLCS2Y(EVE<}xxi!^I*K?N zSJ-5!`8o0vEgI&M)2Wi2Qox3yERgzUDvo_%)?#;e=> zMX8SU55t-RY=HES$8hJPr`kR|!^QXtc$_p|iu)|&Z${l+FJ~{G^c4^`t{ib0FtW!) z&-UaX&=qJ4{<VD&C?nS6bdlqlLCkmQxv^YTfLc8gR9HCi)${Ow1a`4@S&)SMExnLbplO3%P! z!Pzcxt0G-U*um_3wawZTqew%Xhd_Yo*VOKZzTU-$7L8_#H0Shq=3soQH&t&$;~rLF zP#<54{3E7sj{WVvTHCFzt`ZPk#;$}akvjDN=|M`Ta0Mq|Qbd8kJbo zg36AsPuq(r_C7P3C$%1WtwFGDQolQF@MTrh9O@}iQp^t$X+srkY}52Fnu|F-@bc0i z+bH`sPLMYdZyvi5GX zIG#;^!+fBj+)Q^yc)`gv@84|}`JNh!bw<}YyQAhlPF1h}UE~QY=+hIxuDBuds5~@QsRaKt_AUAMSEOBLI?C^RjG>X3)6x^IUh#QZf|c8SlR(|AGOW56 z0$KG{(-|E{(PLsvyH@-S4nyI%ge06f3+z=Fj|>uf`J zwpQrZOF%{7W8kH2M%Gr)`q3${V0F4oa4M%C;X5KMelayr?_md zuxCZL&9`%rZ3Hm4uFkS*Oi$Scd@SMA(>6>lHQ2PpzA&FY9QoYB&%#1PeanMlh^CbN zIwZ248JYkRhR*CTuAH#!j^Sq*GaBpv4c$IT8+aBMGUUOghF5jLm%u7+X_`dR}2JzQH zT;tclx%~s?&;0LExxDg!9+f3DH31#Alhzg9s+Uu6%ij;j$X<|L`;o2sgW&e*o^?Dm zPZ)!5{0(sukMikVG7a!y!gB;Y$8$C&U-^a(gm(qr}pU(L~J4E8U22~V|Z{Qj| zAEb3XD@nZQSsl$;*YxGhMe?x0O9f8Y=~pP9)zymXL7x7d_R!Wy z{q1t6HM#o&f&sEyXy5opYVarHIi{ZoE3Oz<^wJ`NhbMddo7^4tuVQzFhHn$%cM^d& zQ)EG%V7Igd(+{6((?l!awh%K<&&<@`0Q*2{$2G*hXfYI~=BCr_rWJF8SGGt-}0%Y^!bhz?52|%tC?|rRP-DvFaaj``&WL z#|c~Hm79zt@Dx*6FGz%&jAlgh25id?(W(O|gfdwxS^()`_{GEbchz+7iz?@!xw`Tn z-I~tLb1Y9PKu;I3JKG{yli(*5tAS@m=d3?4;C!9|oQHGFk0_xzu%z=z?c3Nh(0AV> zLBG!k;logNFJD|j|UC-Y=U3S;%jI2F6 z>JIlzuO^f+zO&?BvAWhz@N}@2 z5n!g`>+aYeRsK8k?=K-sJ*!2B9?8dYw<+g0Ap+ge6y(jO@gmcC3)}Hm)WC?~&(jZw zeY4M#-W2DlM4F~mk9(Ge)4M1H@u+R#8F7$_RUH?B)|$DXxauM6d@#E~wMctGvqVlC z$Nu?y)>o&v%MUN}@m{WX5KR!AnYOuw{DG*mqa-~1Lo#Imn-`Uy{V8n-`s_@1 zDV|QQzban~Zpf&IS6SzUa-kfANVV=BmY;k}_&-)K^f;N!{jVI=MJ&?L11|@k`&4!x z$%v!`{ZY8J%sVg)Z{MbEIFH79#`#aYV{jOr3)ZqzPs&71u0(q-gsGkD4{gG##Y96o z0mF|x=DB#$f>`hFvB*^viYM*L+zC@pw|B^&bJ?{WW!E~p6I361@F1OIXRRb81z~|bil>!U z%Q-%2O)iUSHVFK)imki}2pm0fI-}QS()qyf1V!(B*ms#f3`H#oATQeVrL)`k3%sDU z6Bu}`g}R3h{I6{MWsD{s0H&FQw=e&{hIareEau1G{1IAW7jJkCEQJH=8Xf^E9igUddP1tVggMTFX6j0eA5PWR=N&t%TAPj-H5?=qW;X_&=uk~rj zl>`4WpanqyK_R))=3m1c;=s2ryPEv^k9FC>5(+G0p~k_ye+{z&yPCi6*zJF{x(d_= z3l=&yXR>XlfnEw^0aW%mMMxg|*ZTf<+5fxj|K;}oDw+Q(ng3hee*D1FsAlAphz~Vj zO=2-;t5`fj3LF5<`}FaDtMovA_WfKcr{c%frje%;iZRt*)YVwknVZYG!d#$RBEbJl z-OgwJZTlWFytnEx%A4S%v2uHqyeVzV`G9ZLYSV?Z3>__9h<(oG;=eX{S1h=w*=lnl z*7;T549PKPV;cF;|8){QKw}((eQ9(+0y_dsmD{MP{7hSItM6aWL6oMs*-2-ZJ9NF{{gk--*rC)1n@GA!y8pF{)<5?2sWd+7l*A&dkf%^J8ON|78xvw_mpOT-Gst zzbsX40&RLHH~VsiU=w-m@hB9TwVL4zt{ymm{q1yvWd0pFJY?K=KHND>xx#7%ljBk{ zg(e-kwGgqfW}|~8wHA01tCt4^M6A*uL)kiLD(~s<=E*e!w-lI+ zG>`wB|F?t#BlWpXW2~i&OCC3l!cED&MaOp;&5-B-l#!B*2-z> zmrG`T%r2Z#Tm1WDPqnr#Ak+ja@BG^c;JMNFbXT`%UHLS|%01a z%nYb<4xm-J!ETq3g=m6Oh(Jj*#J*`{Oj>@WAip9Ocq{WK0kYM_m!$TexiwUfJA3HBcViK%$; zK=E&bMcgOwBe7;L)LF4-$lTv+F};3dKd2qO)pMm4TEn653L>`hH#t=5vGY`EiBJMD!mc<>P`W4*Jcqk_tMrU|W2@2-~~^7i?4 zIaVTkKQ7Svjnn`dbcZ9x;h#qGi*fW^5>RPUA#N^c*3A!xMYAs=m?c&R5R!7hE;ImU zJ7{?FjuRb0Mw~{$%2!Durwy6(k(~l70I(|oocT?U=NX)ZlcWHWD zbO;?|eV!Oqxaz3G*;tjZGG{k}7UOlVHR7EV+Z>scmRp)m3~qG*qI zSX;9%{`2htnA}J_e3#ckOwY>`wb4QJlKanH>5U7aFjK*y6S8)_^YPw0lhg*&GNaS2 zAl{fzP?l55O8nQ$e|+pAsOj3G_guesKd90H}xe-$RNC3lL!f)r7Qx7 z3n^kRKluLS(3w08>uMPiD*n{`kvvtwXb2sPsar3<&65i}GW&(rG)ML;du@OJco^nP zCr6p>Yo4*%7|^JkJeuiZAf^X#H#XzA(6etXZbnJKJh$&17D}eB=Lk*v#>L7O{aF5` z(}eYGP04JmX&WtlISvaotP~lQT!T4!U(lGlVpAP${dA1@)&)0X0-iFNWKW?XB-!s` z4`Cyn)Xik}c6qgxB*RnE-ahXlts2)7J39zxod%7CLFQjJ zaKKGHuVwPEoM#nX($djaH3%k~dmKO42&KeY+$?`}w~r-!RVDA$Ve}%QVVA zV4m0WihZt6o~a)!=dIUEp&qE`x1&Kz+)eN4m>`!lRG+*uN<^pJx-nVXUT}25XR3ek zMVo#o(*D{Caauu<+3TA}KDRnOngPx3OuguwbtFIxBD6;}u0U$t(k)`u`gq|u;wt{- zvw^mJBOl|F-_zA=8%thQ;Ib_xCLSlZ5q@G&-uk|?&p#U)66Y?DdQiqi*ZMN#UTIq~ zR$u=j;-va|3P02_XIv-(f4|z>hRTcr8eh48LTQ`?Yqcbp{e%LE=QW7_KoP{ z7()pkjOKmOCY-XLt9}mJ zWl2A#W6^NA8Taaw0>WT5uX7i&usq-rbI^BnrMpt{y4^o+ zzFWD>C$5xf_a>c7{liM^=>c{+n}99s0ezURp`Xch#8L-s_il zwD28k*Br=55oUPk5suuV>Q=S?>~U+}L%u78k;vIx)%2{QWFxT`SXc z99H~NVMx;S?DwAK#bXMgJaeJJ4WO@c7BY7XinD@D|BQ@pDeXUQx7Ss8x5J^k?vyc- z&$Mx#_4@jH*TEchXWFv89Rs_!nv1<%hNp266ZqkC!Fm=**R&FP@6&p~(d8?o2nH)L z?ZTlCam8hy_$hQ{G9@eG)Y6lz-#HMX!GbF;%NRQiLtKEr)LSw;bv}yUYHz{!NlDZD z87GQh={b}|%--m)j;oMCmS;tt_39!}leV?)Goh~wtcclrEj~i#ptsg{X|CHX74EOg=F34j_BjyvsgqB4v0H8QC2lk(R4-HHNhDKemB zG4D3|0vH9w#dgLDN{@H7kg^tg$DEx%!}F!qvn*gCxZR2;YLcQobl}%kT60~Y4w$QN zePcRdQ9cIdG{`uyC5w*PqZPW3Cj=S!K6>{)z3|w4%cNEN^YJI$)^*b|7$R4u6RHA} zFdQe;6D?!*j1F~q*(lzpbSog{XOfSIwPXkpTS3Dd+^&4Jc2I^}BX{J`?8rNuiLS>M z_5xtneNP%CFR+-f%PX&=qF&HnOmx)@nF$V2=CQxWVFvuCnT|aZI6_VcN&@s6;`fo) zT!(LD@#?W>;#V|v^!IlOXP!*AayK#xx;eA62a~b~REnnsvMHoD8Pzwf(J@g-x4kWv zqg^dhIWo8o=-c!w*wgq+Y=-tcB>$T&ELLFl3Lt~(b-P@n)k}{(w?jOWpBvJ$>lc~n z4M~@gk8%pX1q9~zy8L*i-P=1soav&YF6W7&OFo-)NLiiA+(i~ld;U|8St<+=PSaCm zcd3*PSL@v_k`1xW``mGockBO^+23s zFFJI!^`@Hl4$eB2l+lq^%%qI}ikL%Pp%v#RL!Y)bGEJ6j`C8J#wjwds0V>4AoM@mg zB#)DPV=P4>Hs(*iy*J*kLBHjBu<(>dqu1JCj}pvPP>R!RR#1+?Klr)+=4i29&Th^I z24aQZi29l0SS*Z+t0tU=!~Gnv4u`(1ug`>yDAA=MXKkSOM2U81pPtlYB2ecpHRlC6 z#we;P_8y*B4EIfq334~-0Dcu8%jdAIP|?797d_BGzTpKOvtuENdzrJPC9!N_{^Mxf z$w~TZx@Hl!yZm;9cT4la7twDnc*xQ9EKkBn#Ju_v$HmG07|bIPKS4Rx>}dbiGpbP( zyWwlKFMax7Zd{kNwR@E=5%w$JC78SS1s!xTQmKEUt^2J}4F2pXf7rf^;Iz8@grzH9 zveLH;;6}CjExi|U2lyoXs#PZ+qB3TPGuZXHsl|qSJv7?vcg#;Sxp!A@qSGcn4H%j+ zTIYaa&pcF~Sumk02(rRKivMSAD;2d$@9^l-Y2zNYwCZ(sU>os6>$Gbw#nXraQ908`cC0{*RXA^V}7 zfu(y5Z;(yRjP|BRC?`P9<50eSF`aYrBKEbXZ<=NpO0Q?xB}dRP{(j!OOXsf#)V4J0 ziLf#|F)txuD(-kXM&=nO+6t0q8$Ea zjImTZY7D3ad{rq?c<&Fve|14RRort|GgeKCzFfU*Tx1wCGIqx^yn>LK`R?JE5FXzM zd-(X&Nw^{Hp_psBJ9|${&hU|qV#u)?Vk zuj*s#S>LlP`IZ&rL`fqmX;^#}7)d8m);qucw8{f$fvUf~t?hKDEQLtJ9l?G@aihAXEl%X-D8i~Ll*HgKRw{E-zI0JbAH8mlZ@Y{z5d8wzk9`A1a>xCuC^6p?iB-nX_;MRw)_{Vu>^@bqtYq(Px3-81W1an})^lv;C!I>ZO zud!V_u@1jD*hbcPv|$uF1u6nbQj;C*(yX8eto2RExhr&DVtr#(j9)`Pj(R^c!&)r##Li0&eC{I>^3hMz!T*Y`-{@c-y=9+fcz?}RlTie6;iF!PB4|0H&iV!qiT8)dXytKck}=3;6~!uIxVPaKHU8|oIq0dr zPR-znl&Jb=F*TsK7+!S7ldNhb=|0RZeIE~p-*=_rDe{e2#1B2UtL-3z#sw4+s9isi z{FFW4JQ0YONg{p7dxp4iy>!O!=(MRc&aQ@~CC9wexKjkjvxt#;r00z>P5!oMjb- z#S<7c2Q4JFx(&sGxTLGcMM*A}za0F|#k?QZGL5JEUj;+JT(Qt4gZ)7FpS>xvr@Vq0WKGN?}Oa|Byx47ZE|M8 z9Fcss#|PU9{NhH?Mqc4upYW4=U%!sE>JOtg`je(Besfjz0vM&N6kHQ40lv$?maa=! zOXWrR*#KuT_;Z6IxP}n6J8z+`2y?HA~5|luFfQsa8$^?v)tp=W#QSXS)XV9YM;l)h6u=M!y5{rW;w#; zprxIP^N3f@*{t4YMkj67qfYwd^(kJxA;Wg+>W)CEtu#J>9ln<4(Oh@zoyxhA%%)0R z1W*#HvkH~|d1)M$1XEpAfH=UTVK3EH3zo*2AO+YeWNi2~viZ!8+V#9@8ILE1)62pR ztF3B8K>?mv`q+0dk5{kGHoi^(ZSON1>k?LD$pa-bw6K}hgBM@+`trI3%!Rm9w2`l$ z#aO>VLH?cZPW~4usV^&M4Np*wlJHyphAcHO+HdP0vAp_2UO#NBT2% zq=sdq{8|Wh-lwD=KZ4RA_>f5ddewT9FW+!Uf!Py%rX8#2f4l!0CpkCa1S_oO4~{n7 zSU0-$5n211(#g;@unBEm^yzr)s2>Qh%z$}r-?HhW$Y%ai>r%|Dxm$kMe7nAjj&Q9& zI|CJhyy0JSVr%uRSjvlP2M_stfAx--pNqI*Tt=ZAMj=X31${4g2Mizhi{Te=7OI;G zE8Zu8U_hv15%1!}wO<4~<%BO^C~DD<{jMeh7Qu7K^rapR z5EQT(K36bC$IKCNzG*3T_xxhwqxc*SA*Z^)kMV6P6FXN4sFq&h z?f$D<*ZXKPS3jGW`47P$Hp3bH))p(B@3@hx7iLXoAgt9&N3;v94Pd=h2;b6)n}MxarT%`usJ8cKZ8Y*&bw8R9Jb%t` zGbHsrTb39z8&IFIyLeUU1Pgn9AOQV2WiA+95#JXGA6IPmPt$lJVEL)=fOyCS8}Ayp zs|H5GY8XB0Z)bZiy~hks7b;b6DM;BF>kTLPV50q>i<@p-mjE4Ih$B+48{~_jaUL!~ z0rt+Yn1b(IX6G*Bt(Q4u%!Mtis5gIE+dw0u^RakmBlniJ{an51@(NUp)HvGmQq(#D zG&yLC+sYpJ1%k#gJEelIBtmy*rBSOUFdYlYA;OFqM3A)ny0Njjm-b)>XfNea=Ct*= zN|WYHdqFhKL5mc?#|d9)D9RJJmicb`2~cat7_K%ONOPm=h}w1aB+cxketdfJ;%l--9d%z)Q@>ri;eZ zqsERpBKSnpmH3vkd(RW9#uH1!)#iew$9QvCqc!FumhUi`C35X2dgMDz8rvLDyQX4Y z-;0W`uM>siHeEPYB5%#6*=|EeKanZfYsL>QDd(o@S3Z5C#; z4xKK(wdO|HRz2=XL{qPs7azSK!?ZJ?&b3pLDae~fh2Ot+V+lSlXGQ=B%KZ zb-h?Lthw4KC;5UuOL;m!i~9$FkrvjwUG?{zs+&BzIm4sv)|q-s zMta%+ySXV%D2!BK9j&?1pS`T~0?DH0z8AETf`7dE@PWI)vI5cGAjCdW5jr^Kw{Qjz zUz)otW~zUn<>E?XxQAxO#c!q^CHNScA~CCkrs4^&z~sOYCR@d~9&KgvUW$5ntU;9J zBy(d-=Qh687t2xhMr%6vbGHw($7nK(RV~Ulr}V4Hx$cmhZXu#ly7jrHv$o|Y5ZK)p zieP?MFo=T&E9+A>*la)Dv=2Uf=V(L%+z(mW2qmvrol(RxjXO?j8~DcgI8MKTN6hx2 z+t^BGELZbR(~@W%rv4pW^5?riU)9lmNZUHne^6#;VsNcl$#`6gTztQ+g*Rel8r@nT z?Z41u3a<+T*?X@^*u2pi_CuzLrZmn)#(EiBH|vdTeR5KfqEdgBpohHg+{jB z;lhAJ7r#-pea>DJUNf=7g7Bhu9E zemBBfInA2o_q2)HXJl=~q)g8?d{J;Cy(qfVlh4R$)<@7_@Q{m2pxD+Ao{VT8E2at| z6b3bm;^rB70zbCY5M;XM#G7L6PCJP5f#}!6$PMzCTM1!s@LMu94M7p z!@VbN#D)s>*rpo+->3MQy^NLmPO~DTYGQiq00^PcFz@d5-5#_YMxBrT@?ykt{nnWJ zYZ?z!aH>mm;V{87m{R`Lq4~@?D*2f82nZca#q zISHJ?6!1rAv#_NzVN7d=bsJjt4KNgIjs4uqxa#=PVY`4yi4bcY2oKob0YzHoAM!GT zQtk?csPp_XzSnA!vP#37)wMirHhy zh-~Wy;lc1v)D`2&Q$^R-Uj_dn+Qg43*tA=t%mBtm}Iw3Un~ zwY>Rpzz>^}f(uJ5;--syTG+XX3Nu3rPp#Ir=KH+jJ^Jp}|6Cq<0ejwaz}7VoRRq&8 zO}xaN=`%f?Zkku&RjKMQxoj@SynZom*YimaIOPoIe#-L{s99|{rixaY*Hwo3C_$R8 z)buD3c=HpDwWb+8Zl$GD^oSgD2&A8VoWaP*k#j1{tRarW6Qap&k4Vr3+C+TO#)=v& zC;lsOA#R^W+5xiQ(SyZyN0RQ*TICy8GC`o^V~pvW@dM#bi(U20y-Y!ohrYj#vX1oz z^uG)<9R%=383!mZ!1poYx_EB)h$p<`k#xr$rP5MSHp_M8wyz5o;Y^h(EoWrSCU7Q z>CFauarWr6_T3S#3Y@4hp>I5#bH%YG4~fP8G{hzfQYAAkA;Aa?3YnE!o;=b?IL(%I z=850Fw4us#{xn8a_K@tmzPDCYfivDPf4H&DwFe`XGh@XmAJ(2niq3oq>N2xjAH{aG zWMq6!mQwT+$_R_1z7squ7Q13rU2o}pHHWNg@9{(dPk}q3j$TsVY<-R83ulbbzl6K5 za@zGsgdU>|)Sp-MD}gt>KsLWsP**?C&4ce+r;XZ9KLGaJFH7-euKKNGAzWa(>BYdDxC~l??u0OFW`#{Ujp7$f*tsd9}11rlxMVF@uD(1X>R0&#E ztFVcV$;=uQ**Rr?3}Q%URrPu%kc+)9r-~)0A0ld z=b?50kSPI3iP}EX^k(qtwF6q<%5JeMt}01KMLiXM?-R1QM*ljwJgDeHNPKPoL>*Bo zY|nYPiv$&&k@8a-GU|GO0A82ET=Qcrfu`mg-Z7sO@_7vZGdiN-&WbaqwX)kD>+UP9 zyjq?q%gpkCFB&p={BAEP)c(MnF2^^8gYH|r&+}9;WWr~syP8&l+`?;FEiqpOO3S!* z5cpA4OnJ9`I4k7hj==pOr}M~wi|uX)9^2zg)QaZ#HOH0KW6>n&<@7L3(vxvQM7RC! z{JQ2WBY)0X=d9ZSRe?V{1p%|80khWxj3sS&V@{=a!aI4X8P^9>Lzsi;baelGV>O9SiR%vNUM;2LD9IiZ{G(`qE0ZGuXt2*QFy3i_T_ z5kX;CH0)?Oj+L>KB0j4`FhHdZ-Q6;~`oUCRl3y5ZOPyz}-~G_eCqBr>X)UMwR;k=xC|J5NgvMI= zW|ZeRppb=L&LPcldeT!s94C-jntpg(F$xUh9%bkq(-E6)E1Z-e*q5b!9GUgdHBXfY zce7lFZ>H0GmP)A0o3}6PgeRK5;No6M|m75ba2VKw6(V zrBVB8h;0_5bssz`MZ6YulM-BWy-_pQ_hsy9#;NE{7X0?w1$$G}_6zjmQ3)1y|3J0t zQtT5pT)BYh9fI zJB}UL4A@i*9|xUJ?BzfBBL(cX*nX6KFN8b>2ONd9+Mt^n=#y?j&P7Q;Azc$)KublLBUzjLQSuBfX!uJm}> zXnyKc{wV7y-wV++LxXu3jKj9B9dy_($`be8n)+QI4PJ({-qKE^UJY4eP`;&KClh*6 zV&OMel-V%pT(cAW00>D*p&=qMr&e#e;v#OZ5N9vxgeH)nR0|@J_U+fpUbiTGya9e% zF2R|~`NfF$UbZZA4-0z>Ncy219GE#^D;791WI4F})<#K4QAKrnsIB!d3^Hz;GpObO z1zogI*U1tRVb%x+;yQVPEr)Gg&7pQn%>aV|O|8=lAlg_1bx|$tHEVl^1~F>oerc)- z>54?I{x}uOt6x*iaes@-ir{9p=S~z?4`F>!ENqYNWZh{RI=JMSpH}IFt*+d-%)r2_ z0deDQF}CYrT6=&X?7yXaoaO2vTWcCbqv{-WC3+!|Z5f}Rk%=nGuS3`q(8HDn&@?Oj z;(o4`GuTlDsKe@VJ%L{W@BVfGHV8Zkf4YPXd3`P6Q=EJJ^373n%z)VGNcBA0sPNhR z;vKds^u9Ye07!@?(=h?~Ug{j#cx_py()W2^lbnruHSvLU+Oa!4mqcPxf?) zfAX)aj0+4jMpI9YTBan?SMj)_+ENk}Su3yp3Eg~#f?fs8=b0bvPDh`>acOoJEp|RI z%DI+y0@Ni!HH+W62Sg%JR`jZlxJV%A1!k}^s!6r@rKA6aG_6W?R+Z1gspou27a% zkz~<%F!UY>JcDwRcem}cGgR~e-j&5qpKLX><7`R?IJT00q|MgExPd#uJ&n$sZ_Bo; z9nQ&n1zo;7wyqyEif(s3xcd!A+>@?~N{(fJB+<|bzyNx(fHJ&_J;y5R>eE*5lsTW; zZd0K6fnJdiXaxuG!030ft+9%}jLgD^lz59sw#^qkcjz;5%n6-F9NB7tZI? z93u=_*rO=Dmh$l=RF5oOL)6xiI7y$LD;-@{|KQ*1I@CpVoS42%{VgA{8lm$lyC>}n z&6ILRDGpzkT(pDAkO5gx%fqshs_AhF$A&w-EHe36?0_HL+yV~2LpQ~_i`w30wk4Y) zpN+#XrEsN$s*YIf@Rlg&mHIE{(RRbir)!ZOs#g_lsxNQJ@@uO!tI!PwLXkREunwnT zMjWt+8Ekfn-m1F=(&h;aW3ZHQeetT(U|CtjmHxg4!l-ltp*N9EdSkpz#=5IxH?Mdx`u-(e{< z$9Z&Alf3=Y-sejSeEO3QN8uOG;$9G_H2?mwk-d)3T6-M*t7_g^*RBZ^pH{Q?R$F%) zQ!?#VLYhUwdO6fBcuB(Z6?$GkEQ`1B=v{#xd=0!&lr{ze3sm;u>gb~C_7#e(Q97v= z6XP7w@`a+9;DiCZkL_j2I3U~JGdGnN_npgr&+9#6E7s!nMgT~io^V+xOA*B<(oA>X zy)Rohp+BL;?U&&SOskXvDJIHg?1b*Q;jFj?ED}mwJj$llw_`Kr^_HX+vT3$Y_huV4 z1LOPi*j3A1vX_gW8%$AP1Xu@NQej5M97;E}Y$}GkQ+S6K?#HUK6 zuTI&Ngz8=wfwp^4dn^tZ=B1;sc;Llc9EXLhNYy-v5nSn=3p;tQFumc}c~ieCGoK>x zxMg{-z7sB@Z6sTFp*aB<*6sUwn)g}op7t@bcg3B4rBdQgPg%Iy#G+fJo8&5y=9n6- z-9H&nO93)km0K-CgZF!zSSu_@WE)e>5rU*7PkzCHq>TmAG;rh&1-Et`Qwk?Q=q9=DZJnYb?fQfEJdJ3+Q`cMEv4NT1fJCU z#Jbiw*S`+}mLtYP5ATsBqEFn(5XV$@pb;P~YGHk*B(&e_7qNG+q?a|L5+DBx@;y%! z6;oulflv>bJUDceiF%_s7Yxj19}c|pX>V!M7B%jk$b^*-F$(x$@D!Ec`*k5Ayl^vF zIfwqdxh9Dt+%J0}GC>KxQ43^Mu!J_z`voMQ@$ zHkidK9P(-ZedfOF>LSM!IE5%@ZG(gdJnq~wbVS(9fDSVax8f|C>RPc^?*kA#UJEp{ zJ%u6t55yw!##3?;7*yXlG9DWZ9*$XVFps=$u@hhQ*y%SFCFbDE#`(EqzUrOx^H8xO znuP5)(VwM#@&)c<=Nj2$$=$bq*=;QKzP<#n!44QZHKtr)WFc)rPqkE;p`z8=PiK1RpYfBf~7gPTaK4da0zHLuQ{-2a42`jz0(t>?O&5x?|l zMwk@zpfU4BLpSCC17wlh7^HTtF#kW%&Hr4rQa*5N%5Y}#Ik$(N($Um7gV2QQNt&yl^PV^l z%ulR`yoy8i#%AjfM*hF{&io(h?SJ4m64kY28Bx0JMYe=7$u+kkg-J-ZK@=IwWG8z! zR6>ifZ^>Ycu|zbvW67Ga4Q4EjrEJ+nS)-BoRB59wt3#qH=W^CtvNIUZ(ZohG2CMZv?^)?U9c3ZExMO90SZ$7XkzqE1t5-u|N zZ?I8fP?9FXVC?JB%!QZ$IfC`59(17pt|2P<+U=f~)!Ip6g;YCre6D}bb<1_&?mO{;-8ndZ zjz1|IvYu=hsJKffvn|gj=%Q3X8m#>8`%v?Vd8olK-73OWL*8^Ky3Ca~bFCrF{^5Pp zN>AatM2JZv1!qrPRA!h zyO$mrl95j5sFc@L>Crx=kSXHjPJ=DbeWWZ+3FtYMg|wYIe;U71AJ#(D0GwUQW6%?4 z%@lY11V|A1TF%q}Gd8u&So0$3J~%0qwu**^CZkK`D-12A!m$zdJ!7V>PfRBCix_iR zeb|5X1Sab?=;J(qXR@nxON0E3Bo_<>QPNBOoIUTb?Ia_h9Nx=PN4$DYk3^X;^w|9S zT=AR6p8VQd2y4{7Z|N^mlbqDUx%&o)`ge*5tM{6LMiTDBiWM7~% z{6R;3Lke8Fw=SJt0y>ZMBYnHu5^7a@jfkyFjp%P2KCRE_Id7r8pS~^DHc>7pD^Jsx zMJEa(T$V?tWGxz%R-=mVH4w1bB~CBqvaa3KZAazn&1u@?2f2GT9k;f*;uj9GAG-j0 ztN=Rv`}zy%mCBMeS(F?|W9THV0hKV+hH#1Is(+uZZlR!) z?2+X1-eF46w7$I8wFTsnG?6hB$b@}1#M+H#dZJ>^s;<66Hhw}*J7*B%4UUZ$dKaDS2VNwJIbSnN3!q<<2fz}ShZJ! z)yqHk0F-OsL14LsdQus&`OM5?c}+OUhN@K`r4MI+6fJYvi}vZhT!L?r@?jIOO}zPuFu`|wt*}ZXWot10TD91qu7?U&~N-(L6tPNj=Np>&O5VyTL-?l#IPC6WASsom}DjJ13J zbHMF7u)Aa(A_KSEdOG^_c*i3IBAh3VkWuIsS)AnO;9IE|Uho=UpujPh%`^vKjNSF( zM;-ZfNiaMvTk7`}Vq;`$lAlxPAcKylJ6M*Fnw3Tlk{y_QJ3fY>=rK%$Ai)?hu}5Re zA_f_Ye>^D5@JM2Ovk~LW^_8L?Dk|;GTTU?+Awg=ADvWEdjF?Qbt2nLnH-)2`4PR*( z#LS$_LcBsu9EOUN@B2vFP(2?78kn35oTp>c6IxzEn@^5@O#@s%EhBH-D)$Vf^j_auEbTh7sZ1?xI6ze z^*&eIvpi5UEAbh2@q<8q`(3V;mDonTp3su9rNhZg;CCJpSo3&@MEi&LEE$OjO zrf@N%9gQU4fgZpXuDN67DY($T3**9W)v;VXUc=964$a|~ahe=HR3P`ldrJcD!&+Vk z@0542c*Y=d`BBMARe8IoxuJfN7}BbUI$k?4*qavgp!6fjD&F8UUWhzUrj9#fk^1(S z<#s9ek<=qksLv_Tnr0{yh&#zh-|jeZnFMxHGi>?nDDj23y^xaDY86inA{6ozFYvWu8QwRl*`|AiuBJMVw8V5N6594rOlIF! zy&k+&CZO5=0PfKFVCC+y<34AjvN)1^BIY#DlLx26w=l-K(bV0`q z-NfnwWXVyslWbYR@lnpx^MK>~Nob*eXHMyFZ{)|(9=^m5C%XH24tnFM3h(+G<{5Gi ziOQIdwsoeOLz(~hS*`AzJ}jfvkbJK?&HRsSIg{!}rUjWZ@nA7Te3K zv_8`J99kV-?oWF5@@cpIcq3_!K7b!^=W=f|GMuH7@9Cm@aOy8}#dW^DJ-ql}R7`KN z(NQx9+a`5mp{`!U!Da3=T1I;!n?QHZ5zm7(`CyQVN=yVa{5i1qgWi}5GO#XOyE32p zX`a*9p3?3mcPMK+@g}vBbRE07RpN&ATa#rHbUM%fGh-B70x2O>ao^|z)c$w-gDTT% zQhU43VR4Ci#|1-}dEB>7Fnn1^M+rcGDcZ4>E$bZ#HE9n*!g4W`&jDg{1Inv>QPWJQ}PgFegKovC$*3(%eg8uEqO2PJDgjXuoaT zdge9{WA+DH1AIdK^9C5>=Lrr8wk&HmIbv~=QQ}!mWBT7VTd?4H}%!@PK#-LL#Dvx7A| zHLi>P>4oCt%4=xK9)$`RVGa^XV4=}cCKFl_m!*t|2$S1Y)AYxEC&QM$DlT8haDSr2 z2R`FpR|k-TZ$M>`LrdgklM1s?U=Y^AbnD}=YlEYID1YANay6z38?hK*{Yoyeal|HH zRCH|8Ih~5Vu4Y>MAewneV+T}Vos^R?p1vPn+t{cw`}-qfBj-JN9L8wufqpeT zXhgN)Q|K-;(7w#Le0PJwF;TPD&VRagj@%1(>z+w$J+8%`ae3)QzTwfH!IG-j*u8|9 z#(FIqtTyRIkKd;@6J2T15T;R+2LdqdD%8?;fGIc+>agM{8ZxVph5pe#VaN6fmsDr8 z*Fn6*3omkk3RW+#JLuxb8QZ-_q@ubg)Jnak_Akp+e8;s0>sQWik)s{R@eX9Xr^P|x z$5B=Fk=x>^VY3BHW$F=yW;)3NmKIkMGR>DE z>$dOo-x1jAR#>5>-_Wt z?8!>R0{qpL!tFdlMRq93#D_#`eX8OICl9vlZRGk|rdpT)>H0t1He7{4@UUCmhRae@ z6~d+~y(hJo6B+1j zem@*HM|{o6ORNVxuXyXD+tSAoWd$!*<2tkI7b)+!+jg$Vc<>O~J=-2n*gZwRAUu7y zLts2TdGCaI+2P7g6N&RRlBX*{-4C3)`H8Ao%VW$z*>I#$SQ5}$p9g`4kxIiM8VaKx zvYop{^1uYc_d=$2f@AFLg?mYc)m%_L3+7^$&gF;v9reDfqzBQk=773n zL`&51^p@Ri=hjvFc`ERMn-w-xKQ7E@K<7~3)fg8dr+zEXo)%;D^{mwUR#qK4621v` zkW&5ocMRWZs=}0B->mjouwN)gbOzP+U6ww=q(o;*|2%$9*YRg5b9!X?D8Ci6G)&+; ze~hLp)eb4u{6^dxp!W2OEep;%15o6fnZQDn2U3L)o3Hg)8a zaH;9NPDzDO$*{G?6PnYI)L_+)Gd#-7Vc%50L*uZlGTyOy>W#8JhHW(OwF9Z`kiZG( z0%efA%BXH*c;K<^mz&wSLJM3Nroyko1sI{D8jn5Z(VXrChQV#~zQywMix&3uAAFV> zu*%T?doZUH*qa}_iyL=z5%Ogjpd-Mr#DY^oYm|#LLo~ojq;WOH<(5DN^y(EJ2E?S3 zk!AF?URP%Q-^^=(;(rM|WvumPK$M*`h_V|Jjv3nsm;=w?^Cfcrc=-C=fC>ZZeH!}( z;`XtgHZiIOF&gpT>wZ1-SD*e8ssFJVWszS#Gn1F=UZG0iId2|1y(NpGDgHeT?v&Aq zbvx%G0}B1d2W+ZkOxqa)DkCrO`w~ED;Qbr#+HX-%URQS?mlW+yQpIH}iX}OeZqMAq zdI<@Blg8ahVlbur_vrk!SyMdo#1EMP9Tc6sNe6+Xjwjxr&>vKDg-XP{!>}&+K+*Aa zg33{;#%I1f=S8~FZq*_^dN7}?XwyEG+)zXF3lc2w#vr~<|L?0iuQZ(zZaohYm`9dG zuP{=eHt57aL7>pZ_d9P!jGqB6m^mM}{>dAWp0b7XlzMhu$gWUiT<_E6^2 zzHCNmeH@f%x=CNq2famcPSSwtKE7jLy*ggp)-#O>`-E$OtGa)4ri-1$h5k?11@N zT%nf!kmW(Zm0jW2uakDs*>>lSgFCit*|O8# z?%d@qTegX8*&<5aE-L)yS+(u7@IwTA+4jtq8l2LCa7QxC&KdK%650jK2x;$q$AqIP?IX?^(opPmd0#^L@w(J5|r5t17{b1y{BFa=9B z@QJcA=+$*6d}I`iQ;+baEib$Wqbph}pi$1HW{kiV-Gey%w047b1naSQPMD@?=;?oN=YKK z6)VeSlmOY@0@ekXbbQ_jhA>_#{X8*XmGRm?2+201U-F3&dpa!FKE9X_)dIfB= z0!aU48`U+*4S*KH4*I26v(~U3yx%LKcV#5pRzXl^aUG8 z&Z|(ySs+~sxbeAGkKZ=!T1#uCseNI8)koG7adThEveNC;In0y2oE6R9ih#|`AtUAe zgzG_+_R{m_dY3)hPz4S-E}`BQ^>xrYCz#e@!Dz;(J_m3|G_7>R8 zD9WO4Qou;&1J>u3y(JC9Xr6S#4s_K zNictz$oZbd86^WRb5W25(?n)FDq@vHFMVP#O6pmnW4(RqESsLL5=t9e)uoItZw_j| zsxD-EuWOTPXR)VqbMv#iw*u+WK zN5iBQ2Ay9R@^M70_Vz36g(i?24Rrn9*uCU=-gwqn<-}hRwM?WGSq^VMjdmfbdLnBQzvX#%n?&R zQ{ZUZvsdeHIOUn9-tu@4B-WXi zypDY+Hl(m4g!0BGa`RI>PxglH|K|1|v4LtQ26NFM>&WNz7Xj>c4wyn zEi;VRKG8nm3XZB8*Hk8=|G6WAHrI1bQQEZ!>EAxU{ef$zbfdtTUlDg?G&KXu zFuAvedG1{l$)1r}F3QF{B<9-9ko8}4Uke`ZZ9`?7=d(g7!8}%1_Z!E|WUw2cb#t_x z=UT(e>i%_(Jih)$Te2BTNDU==nZVEr9yA>!U(>Yd`pWya_=&2;>Yw!z-8HNbKBYO$ zl%-%?;cZ+I32Nc33>wRLuKvDU@_*oAow#kY`kX7b4NWn-jU`-p-b&r699N$RSi$gQ zYaxgLE1o)W(+4P!!thgw8`aB`b3o20kzZ<@ILtyXt9U0;N2P#`8##(82{iMeGGy)8 ze0=^Ta9KF`che8;WJS)>apSK^=J{8wTH`4Yqq38m8*^0lFG?`J)Di>CYYBwezfE8p zooz1_fv}*jeE7_%)(nrC4oYh*Qtwm~Uh|2jEGWo1E2KK5n}(KEO)rqI7-u?mN@*MrLpFUwBdIoPoR-GE;O$HVU~L=^Q(8EHs4~Yo%jy_M8390cWfE5agn5L?AAL9 z^0^n5SbTSddc)vMYl49Kd9tK6yZ}INZGM*bO7_W=^61Um8{XS-H3@hm)Wo25or?OI zDS~%j{C(OWC1I8H2_?O%tSm91RqhYM5N>!?;!VN=!DX2zN5hxA{wlCesE(=gAD*a- zv#=ckx;lcV4qCgE)~v#NMnhm41Z}fRg1&?{j(L7($diJmveX9FJxk5IVWQCHo(P8b zSo`kLftZj6vJ36}vufiH0WAr!uose+1nfA7W?kjqmp^M=h_u|up?iwZU*bk zZq`EWvfCZ|!hSfsIh7@FI||3Vcz%IK;_BlUpXySt-VDjWjZWOBsLPe$GEFB_Yf zCP8B~5S}}4By6t83RXU6oj!g$jDL5wPgrzd3o}-e+dwE27N54+qgm1q8inb>7E`bN z9!aVYMB>b-kj0B1+r`ea7@-W6XlkQa&XT0rOGB$GM3M)csiWC$EaX&rA+wt41vn(> zObnK(r(q(03)#rRsW)bbxtSF0{VVBjj)~@gJtFRXXP9=dr!Iv&wE}El5dtK7W_)5U zi?@zp?iPCvTCJ~5CHM1VtTnWQ6;FX_*5XX3B=on*cd^q-l~{T-uE|j3R9A|H6`F?^k0D>gw&g6TeFim zwNjRcF8tW>_gQuw{-7_Ucl-bH#Qz_?6H)kW@L!DkLwD+r9u~tpxCCnci$nHwJo(rD zuEKpH3bEJXZn;5V>u z5eb2j!AAvgH)Xr7F=Gf-gibeNkqjX*z_D&b*_<+QX7$O{m1DtFQ61(-Vim4idO77* z=F&PX)lc@jN)zR&UMIkzv@P}jP*}L}W?LDP2V4Q;IYl&#ARPn8Kz_b*X%Ij-EUwc+ zrjnisvL&h_{A0}gNLwO{t_nW%Vr@HT#1Z))?x^1XYiSzW&CFxB3x4AtQN~G@Qi0~~ zQdNJbqY_FK+dbA?#|x`Cdz3oe{ct5ishzb%2nnly=a}hH%?#493UY3_MIKxC87OGV zE!>UEfm<2+VtX`iTX5N>VvR*nuQh}}sAuz!% zBGBg*xT-E;zG1d==w9dz!aYKD_e`e$20F5}k;qOMzVYhg2<3&F{6+Hf;CGftrpHPD zrRB_2?DByJRGTqWfykmFPounGG_Z28!(c+}Gky;FPVMjHj+cT^+_+dKf^KtOnkxO- ziVh1Xq|UwHY5V^=agw;vS9ErG3Y49WTjFcxSnXpkP^S07wY* zOqfmkwX;=1V;3#8=hCMbZ9K9rp!`VaK)`*Yw1hZQRlKq6p4_BLPf}W*6swksWOTfq z(fhJRx3+q`9jbJ;^I>4z9X;!W!B)#%R@q=b#n8WC^m&sgWtG76oX@^se^bw)Ni2+` zS?UoxDp8u4MQdfeCvISgag|6jFkkEsPEZcxm(7#3qxhheB?>@-M_OG8{EXCJ5cVn-cU`CJC*xEMlY6P$p#pV&R@b|Fa{S&U0~yGP!BGD}^g;q4nPq4BG9`@dN*M%56;o08b#CZ}MttbC89Juli*f0HDY3DH5J~j1g z66{Uv;g$8)>U~vD?ka8EDyyBZi@h7CzqKIY90NqSjg&*xjsK&pnM{P+u)SMFRJAv6$qA>yyIBwwSskj zaefnwAs2VxyT=55(r14e@1s2FF%Tb5i#c9TYhN8F6g>V}^f)>DYs;?7;4JL8y1l+9 z)EDihPDD1l2%Dc&!FB0Ts_gK@GDB^~P&cH&)I`2zshZ+fET>RBlwIs{zR#;KbNY1e zD-1Jw6m1#;PV68B&xeUgxQQqKH*=T|h^`n8eMOSq@)#^H~sqKKo_XJwaUWupo~W%Zkyt(sd2q zuAamEMB`8T7>p%UemsdjHa2!Xx?rwC#p*~*_$yO~xCKa{UgWA;IaAx9#**FQN_aN> zWwFlGLcXOv;|E_oiB#kc2bQu2V)BavBQy6T6&tKgV|g}Fz<=Hs{`SiF!HoC36m5B1 zdLj#RUQQW(!)t8cBbFlnL)n`w)op(hrW4Ld0Q(ao{5k#DWjQOV77O(x zFUMu){hs)5ARY_B`NMJn>2Id~#nuL04y(4fhCdFUluK~yPGT8`{q#ES@?ZS=Q-c@P zSHkon+ZU^w{&lGJ&8T>77b{;>vMs4_;cX6lG<=YDbFo-!KX{REy^m;Jh0ac1Y=O^8s0Ro&jxVcWsD_E)rS-}N@n zItw+J1>|qAAb8f*;4UGEHvl;Sf@R`{B5Wp$_Yrt)z5S~PG$4TdvlhCp!tGR%o>&&J z1U#4uD_n(jEp+|b!}KUzGVbuo>b1t-quPA3M_!2(FU7cRij9ZySuo+?cfj=u^kyYy zQx!;8?H?u&Ln*@(z2-{xIv_V%^*&=pM8wCHn5db9xP$$}pAKrpOt?nTB3kc}c zr(_`Amfy46gO!hLn}cz)1mPSeB}g#Qo)Ca5VLzAMe6A!Y(DT{^z({y$%eQ7Ms|H=m z%1sVNzyYpb0j{3~uARL*F4zPKv=L|&3Z*2APo#nos~G`nfnIo2^ScfNHwPBs`xL<& zK_vdFFFQpiXfiWv<9}A7sY__8CXB8Lqp_g1Z+%w_UP!p?m^~0X!6=Kl9@XJFAH=nV z&e}rR1+cg+Jwpiono>t7!zlEMGUbm{idl2SL^hmPi8ugik6&j11q=xqRlp|-I3!~X z3X=CYn|;b)(kEiBFAv5DC&nE&`(!JMSmW=7^>$~0aaPE^UBMQ}T8i<i24+_WWbRukjr^Igy#lT8-v*&Nj66&1k@ zEaSS{`1cYZuR^f)D$8n<%pXH2qDC<*QkWH2(7G#d^A)gY#v;}Id(=@Dl}cR#2{wV; z&p>Wr7Q0ZMxniWd+6YK{wk3FRW37oKc6h%A{Oen0cRXv#^Ujl zlhWL#P)<`?FeU3O{d&_#NLMR*sg*S3#SPFCQ9DXfMPLxO#V1BbH)#SMrXbSFbNQ9< z{0zxOHnV{$g`Sk6^HvH3bP#Uala~X30$&HDJFbLaQl)KHUBB0e$Qvgn-iZ&T z8LYE2i5r>AdMY`BH3a_(hFLxUWLui-{Xj!8hqa9Uw38p)c%?v9Boi0PfE z45_b#+z!)|jpAPvw>tU`=~C6P9b>D}r0Y|C;O$5Hs7ca6NudOyV7Y-5Fp1ZK?QOIG zKk}b4g`Fkem6)J2C-@B8kcIJtl~W$Ql5G0I398tJRpC#mI8RBNKt>7@NA4eh=qPNk zV6+RNykDV=1}h)jLt#~?lA+WbtA!jsUcd&P2OECLt^ZyUPs(W9uz%Ulg3?%|N6@eY z?ZowfnE#2{jF)ZX1T^_$yu@fKg$qCACAZjCN_QeaM7P*NvK1kC)Ou2iW8^gp|_apMZ;~Rehjx?4w&t7 zIVl4upBn!@ch`C;kzMNk*+TT)#MG;n0P!C6hqAmu*$ZDbrC?L~v)1>FHN%$(7#@M} zb7L9LUw-|L34@MSB;K$(os>Az?`=eV_*%uM=GUC7I4S@x{gd>Qfe$q!`a z_3!ioE+bi)nVFvI3tOFfp$a<7AZ{0^1b)a=gOeyfx9FW>le6?)Uq7}}%AskK#x2F< zoHda1rejd|uF<_r51>~SF$Tl#R>DlM0Poyv*9Pr2ov>p10GaI*OYIIJsAKt+n(RIO zng#++rx1rziHc+g#bvkVz%6YQgiGJYAfnB7p*Zv>{SBhtu5oxjmLQM!ZHaok5q;t2 z%dJmL#VUf+wwhjYbXFY1LBZsR_?RzoKNMPe6(BgK!*R{MbG|G`^sJ+JhPaBQ7-mYS zOwH%%Z*<7AKj^nJqb#+JOvGSaZjkfcx%_nue^{uw0OV2xT!esO`cV(Z7yN+)dvo@_ zjS{j2`A;5-BU`v`0)76pzJHME99YYDY*oYbI72sdyd{dyWoNe=O|lXrCN-hcn*6?6 zu0u*&#DlU&Ls43@!s!J?<9-81Vj-p%)9X{|wOf}hj%j~0`+D8qiUpa;5^Q9VpZ5XB zQD9A#)EA1h5q*{QODaFtyJr_+0%5NI325~(G_$c5domNhS%o(%DR^wK@&gi&zQl-P&!~-U;YN#N6^9J_g4*1~x^JTpr=8ekVZ+SeY`qX(Ka*eK9 z(zTzyFSjxZRX(UMhOkU9l5AR~A;Bi>yOJn+CusJuVU&<3k)Jba{zX&hG zv#aoZ**=HeI{Pxjn+YFnela^T=xl7oA~W~5A-^xlAwGpiF{7Ce)%67@VqHGrz2zK^xI^N`Kk zCgebsHB_;jk`w*=^)VdCf!R*rO-mHE_mq2F@~KC2DoL z%V{2)Hgjp0+?M0K$9+yc8Rh7;H~PHITES)s1e^g_sh%yeC0>Q= z&d#2CW}f;*NRVXnwSdo^jPh1L9^DeKSNqky^ILEu;IPMW-xPK^{#*nJrA7T-D{x{6BcBs-*pih)etw^=qovMTP>l-0Y#9b_V z#!+W6ed2`j`cdOO1q;cu?VZMczN)COoT)kK;Q(tZ2D^Vuuh>zu3;AWrY<3dAo(>%< zOueRI8!JO&#b&XN4Yhps+Y`?CEK+HtrWWurVYP4U@xXYGCX$!aU!YI^f#D$(hOxXA zl+z%;cRQodCh(t_-G>L&FM7VBvHL{#zY3o#h&3wI?oTC_ReHfSh8T!Gn)dLIy7Xrt z45t-ieiMW;wCeDk2hJhc_cJR^T^EcjM?n^3AOcY6M{=sMe)Su7>QRUX0pmbxZO z;rxQ+YLd!ElEO!&6EY=u4;!_J;|NZt8S<&F=7E5&g0lKaL!F$b7P)+V-WyD=?%tez zVB?wfrC|_vT3+^$2hPN%+m+83vJ^|r^D5y=8^$nR6pRc8E(}BCj9vRY=P{dIZs-kK z;sv*};#pz=CVHm^GQO0Y(g68we6*A)x$^nL>z^o10Kw^S@8N*a?~JwffjNAMT!3_a zkF)85MN;@=Nn3e;U2Ei(O>JWj8B4bFR9SHE=v7ok_7SwwOZ)A?kEF{4zq5GPL&EX9 z;*TJHl=iFiHuMfGtiAZ^dg-v^GruQ^A-4ytmj;n)NdZ=1amSn%33F@`b6%puQH3%sH>L2j2Z00FS>8XQ1DOyh{a=)^LOi4EC=u`NVd+$4< zZIBb-1|e_2_@|tUg~6z9r^0J&Kn2kxtY-Uc<*Q1*JMHk4Y3k76giBI}HEA$@e97DR z2XNb-iN`6k)8{dn$o|<5{+|#ey?+1w_59~z>~Ji)5^O>K$)K)!f({7X5lV;1?@NN5 zu&W6wzsvR{pB+}dfqx!T^PpTJ0jHYXc{P3F2(8U z3fBHmOa)CPGkqjLjNG6FDtPFkO}NnG+3BQ*4bJa<>P0zdDu&^o!f+FbtJR>5x#0<6 zqsV_ahd*|EMS}NEHerFqw;R@bQkDdmGfYy`-bWrViPJBTmSN!rtMYE;m$+6)Jtlf9 zoWt@uP>tp@18G}*Zjh@=lj^@NAKlk8LK%G4UKVWs2p0=|nQ+ofVn8-va#@?mG0gxs z+f>b_YPv~WCJem7>7}66r!*^12E08!tR*h5JgQGYVz_hqF8Z*=3g|tVADx5&{Vu1g zxLZ#T54+a|h&#swh|C^~x?rnPl*HKGpO?Jm_9p5>>i0bT6KLs@q@j}N$U_X2ocXK9 zt}UcNH$7M1>}c}K+j0H(QGl=n(haunO6EDdW_6~Hwrd_ycRTl?q!RCUf zu-+G`siKW?g+XEk&&ZkB8C%himo`OHfaM zqwxkaxDM3Y0(T=-m3+1rqHUN)fnPVKZ;5S!*G`KpmHEHFx&OhTxZRzeMM@u{?Zt0K zz$4~;u5F&OV3qG|zYyvR4pj>~mn7NOA$B91Ru18Vb??oqUbn$@jBt?9B_!$G2|!Zo zJ;NK~P+l#suKVrOIwWIGCD*n zDwi$^&7Ll}YT$94c$~ehK!DX}L9T+`8P{8ug-lscLWr&#Sw5B%#lYB(EH?vIE-e~$ z(Xgm<&EPb zZ8fp^nDa)M7J7fx0h#xsk4t(=j^{+Cl z{C3kk+m_?^L>5;q(!Q$HR@a?ff3wa-hRpb#ei_O`6|E?mTb$io$X@hCSOB@k|@>%rl|yeE!Uv zp0JBXWr3Gb|G=e;;qj$OYh2nYb?zSz$2tncFEAB$nH$!zYjyY1BqeI^yjhT0R!MKD zbGgG@L1@isa^8m`LUcs+aSRn~743;JiTL?^Bf5_gI*0$Ffe0zTR|rmX64UwhN?}TU z3;xHq%U`=?;!jeq6LO+1)OXy4tAh;zMvlf6zWZyB!#vJdAyHZlPB%>^{H@rdpkO>i zuZeq>$np|wA_O@BR!h7Iie)PBv>I!g^z60!cC&{q3Vn*f*q?OWK2%iM;i6)<{tnXR zaOyei_#xnm81N!go|4Vx6)EGfE%2RrN9v?^smH36Y34k^g}K*&+NSr_zHKPDjrI!< zy;tMu4^3D-PI^Vc{hS7-bM6^p8xIWXp~5a52YG7XJ?c7VDI&Ggy-ubfuWqbof4Q$A z?=$1~Yt`XZ_V27fcalT<3CU!@UDNSWLFuDDrH?XkoPOePBTpwa#;KQsG95S@PQT6>=*p-bC%bncV8 zMo0rJ`|fG?%V-_~{!d~5y}0Av98HwJ9ZT3qrsz#QBNZ?eFjL+SjH3C3`qo!uUi1*-+yBv7E0P7tl5#5NuRScJ1wL z`MbRpLVIX)*|jBFnIF=pb>qtHdYgQM?sf>feBaK0N}4j6eT{j~iYGI-I$PiDDY~w( zWx(!CtFn98v6;Ild=ulzPymoKV#+wym)oXda!F0|Bz%0BCIU$HD09qn&(Tm#6}xCg zKI7Kd?^LYwE@Gpy`n%`+)=6yycy(v3c^I9yEW4SbAfmkMzB&0!z}}NfXXcDBYE#mw zq*guPlKunT`QNRR!io_}b7ZaoyJFiEvr#%V%@uLf!^qyX(!WgdZ z@|;T@AYJ3imUtY8GLqk52G9lE$=4o9+o=%Xyk6IuVXnT1>|7xoH>cU9>J3=1{5;A| zM6^ck(M>T@tC(E)hpXq}-}BtvplOVj2j+RQaaGG)e$UmPyGc>3v54u5{xu}lG?4#Q z5F3^ZW?iybzLHua(Ob6SIseL{4OySWyH>MkDsM*IqlIvkg)2NGOc;v7L7(Bd#p$A^ zg#O07Dn_pMVc|s;m7oU2^81h1XJ0EnqNXIXaX;X}Sv^})EY2+)?UjzVTQ%GCoL73p zruJ3ix(+^$`w_Q4yT>yFawZj*>cpPkUh>GM_D_68{^?NJDch{3Q zR*DKx>Br@Z4IgS1#I)w?9D1QGr^Q$@ROtvhA?Gw&@sDcI``G?wp^x}p*KCftw>#k# z!dSHXnX~DY1E0Kv6g1d^j%|S36&^`7#P)6*p%Yrh@z?&)Kr)}*ESVL#)ViHdpD6>a{w#ARR#AyA(<2-6*EX4RKsX-@r$usb^R1v)Os>^kHk8 zNWh}`r)JNT%V28p!RYmycJl#7-woe2n3xa*>Uzf~evnjK@J znMt0+Kk)GD3%IJgAV-_hl`0A zg4;4^I@h;D1-1EW`s!BK+O`@dk;=QCsq9?J2B@C-GIhya^EE@Rra~a@dL0m=@PtG&75ETh+~bz zY%{hH?BD#_JjH)<=!Sd?sF~tmvaM?5n`T&1gkkIaj*`@b=sV&e!;Ay9S-J0i_9&PX zz#nHpa7z*CS85FAU|^RolbWl!%TK1o%08KP^|2Wt>1)ORxW2Bs zEffb7Lk)wnkJJq~)oh;paaBLAD#QDMElK^!uKVdt(uobO#d^J(#HO@&UE5dgyQRPY z5=XYtIcTTnx<+}|W=#jYj8Cu#jy7#MFvD!nzNX(dH<3$ur>h(EeD1(OrP~YokMg2R z@&31MeoX`crQUOId9t!^*{jTrf~jM;&K$h6-tV~}otW<=>ZXz+T(3AZyX2HV_I+n2 zC9c?J;xdVu`EuY+A-ksEAb+MlwtdmHwol9M+Sy}#K&RErzE{DhB`^4nXZju7P!eW# z`Vu^E>OGZZijQ-S2-S$3P1xwpRAhg``?c2OA>W5Ee)ku&sWi6}qd&dt&mH!WFYenJ zoiaf$Fp~K??jzk1u3UZ1&+Hhc6&!9FqcoehCOolZ2P&kvpXxVZ)!?MpC+}w%ure=V zLg?MLY2PhY${X2wvdcfNM2$^*6r=-@%|O4_43oD?j!&^ZXLW|?xA@g zpRcmgDcM0=9bhSpc6tf(>)!2<0d3{c{7(4T$zr9#iVyyoZ_0}M2E(13Xp)33Eqw*3c z9ufZG+u9ekAHMBn$MppCHmQw}%)*&@3g--ZMe>dPmrsJ5qj~a@4hImb@hQ+`Y;y8xb*W@40k{ zTO*P2rowRDtblPv=h@6ztJ$+HMiHN8Iy8auW}>L*r&L_0+?#>yo^w?-sCoNOC`itc zzA=NJH0}AlLU?6H*t{pm?#Bh_X7;f`t6Kf)#SqiI_+xqid9&2p-}w@-6$uq@g(Kl+ zDifYp(rxg7yjNLb@~I#_r`bx?b^N~e=u;YCrDn_JXp?RGMo24PhG(!A>X`Jsia8zk zCzefR#$2IJ5}zk;WE#noWI_D%8}&uV@_x`RGC_m54?Y#OVSm@P6Kr_RsplYfV}xFe z^ ztZP60>fop0g@IuY`kNxOUSv17%&pzWPeAk{hpAcG zVwwkheV>z6A@N2gWGejk2)gdK?3<+#I|Lh!fCH+b!-pABh}vq4+Pc`4(H@13cLE0H z8ZcqiEgFihzlM)zjwlkDG~!HqnQOVA#V`yfFP9Y23lNK^(e-G1-f}II0_OkmOG%@1 zG~9MXq%x;?GG(HQ9o`FX-|OzTQW@a! zIJwmfgi1bzGB&i|d*njPlUv!*GI`tw1Ia66qNTES@j!JsdcuSp^pisD^`Wdy+5%b{ zPI9Vbh@kAVPzxtDPoiqAE?NTlY00R=*&bgtPl!pV2PC|My~uI#+YfU9q^lut*yOC2 z?ZPfSJi0J6`}1)2V|>KNC-Hc!=l!kua!bItX5`s8J))LfdYZR&37Pa^zoHI&B7CuNIP z>dcXE&W%ZpK8ZbQ2Vi*U9E=*%PZWh7cgtuy>?5m$1nmAcchF0i{k#}4oy(JgF z*f8vUld9B#*+|C}CWHe-Zgoh6+5Gx)@M%&i)I1O0p^(&T?5feP-U9n`i^>05%*5A1 zZ5b5z$NJNZ7YZg7C`!K*TgKj&?1Z$uWiF44sGIQaQ?IxK;xvMaX#(cf$0f<+6ahW( z_Rd3-6rDkPH|WIj#jtG}?$4dXt=M8S2LNHm5l32m%OL;Mm3+Ch`I6^533&v*wb|^i zB_HS^taLwg-NXP!7cIKAUK57!H+lY)@2#*mXWq z<+O7){g$(x+f(yDR=w&T8l-*9sT8x{E zec=pv9^(Gfmd%T3J`0#ExkN14HLK5Fn|lX<$K<}jeCK+e?nzx;QCeTo15^8`Je!gp2>LrAg>&ZN;&{&2RQz>L0&)Pe zh0jV1J^D>=n;lin;rW;43KsF_GxaxL>i1P+*t}7&9m)%__0#LlHAlRMRfL7F7u88o zdByY5qx=DHoOq6J_7wP~MQm1AO=^?6$fNec*NoM>nD8W#~>e|G0KT(_4oakD3Nb9pz^kd9pYC!vlWZ zMmt?L^cyuU+llSSY14}=iaRa`N@bRc&d3!C#ow>sz4BpTNiE`41rAo59BYetXsj8_ zK7-5eM|5P=&a?=-XZaBH$9~zLq}z$Zp{a6}u--#+5fFGNCrH<4T}(MSZ#{4*4L)-% z0^`*cak;=C@7sj%iH&aEi>6{RuE##tqhwz&%38AVHhrGN*Uz%C{k<1)vk`Nl^CdrX z@Ex_>UX^}q$K9Sk3c6s!1ziG!aZ6K(Qo}!2$`nkrY7UI{-P@tCMd4oFi4{`>!_<^E zV3=ho<<@rt^{HrUF+nS}J1uwMUGRgssZvssHaxRr_?UbT@yDX}@@$Bo^68Z4trHQS6q>o8Xy+{@bT0p_r&uCnJulx46UQxHfX@s@ z>4#5ylGgUiau00wZTBV3A`6<1_hkun)@SOV`>5=QSe?0lSYoolXW&BN`<>J2ftOmP zIfo2621q+!qjNQ8>aygB0RIZIp}P}(jdWDpB}iPk?`22O4kveUD{kUtr*d5lxw-U^ zN8VKKC;g^h6ON?g0mq5k2?HJxt9k*ug$@}+jbup5LbuTFbCP6hkB-!SfTsEz`}ZTPyxFx{->I70DCuWlk|FI7H_*7AYp4vM*FTF8X;^%(?YCGZo#eCIIDjB!6pq@lo;cR)!damZ!XiRiaid7RzYl%Dxar2!DM|jTy?-^SW6Fl+6 zWVA9s99RB0U?kv=w&3VjQIyxj0m6HC?PZ1aMbF^3prr`qG4P5}{}JEI zbCX4yV&v0R>^H6pr>$HG-|I;Vruc7k1`vZRbbpdF1}@az?pI{d@Ctm&Qtn*Nne;13 zN{q*B=B9W{ydd3($mll&zpUB?DZb)BW^Jb z9EiD!766RZ+?@R;>4&Ok)wVlb5XWsB`AnRZY)9FYXg@@$jW<4p#&Jay3^6+ygeGpe znWK$We`KE0&w(kz1u@EDiKjV!h9ox;O1H0iXuP(*PCqYHO!jt6gGn!G5p*hdEmD329tG$l#lz6fu z%E_>|>r<`{y63(Bq)unHD=b~oqO`VCVS@}}59wd$ap|_dThU|yW}y}Op%Q|TE|L4C zb2Ja$t8i7x0-<)L(C|IH)jDT-)0OnQ{@36&%`N1c2Ry5;8w9SrN|6bjY97sw3J1r% z;l2G00g(>|L&s%;Z@@*_jnCLp6yhyYllsWnDM#SfpZSKaW>dl?k3Ah(mdxwFKniAO zUrT9%P75_QK+kZ&r6B@(vmL=H^t; zDaz#{9ab31-=1(kve_sM6u|VoTPwy&S^q^utw)uLaAXg&BpBuVfxOkTsTcR5vel8@I8t;Q|QX}M! z@b4R(#n+n`T_NO?JR8}xw1O_}THuh}=`TxtD5n(TvbrVfFdFdza- z==VPQTJkZKaYlH5KEp4s%MOf*M1KT}^-n#)v26AvaI~JIp2M}~-8l_B>*b6javAqz zb!@1?J5Bi=1o?48@oa*Kcvae|wfW2Ut#!BlQ7-pq9t5dptn>t@T1y z`|c$u994vj=DvwB^n5C~u!+?+h?r%3^SK-BJZ|`;fN%v+Q#e$0JNYxT(j_1>zvQW3 zlXu9%!1X}qu87L+DR=9KfE9f{w-UXu>6Tl|HOCMVxSt!Ty}G>aq;xFlq?s(+uE?Qc zRtE(JneM~EZ`WL#%{A!9OG9@MPbRLbgnAe<0K-3(g;EN#NPOQVa4GU+&pw z-fc`0E1QAM?j&t`d0P_85_$lYN8MP4uv$y8Hyh9%in4G4U)H_+GuTo#Ty$`~qgR9v z?|Y`#FW2TU5tnyryIdjT4zd$DNY3Yv-Fd1pd-wa?@Ra_w7KaNF+vnW1c%#Kfrad)! zPQBXg-}lCW-G@b9!-EXmbC&-sEURzvNJ1#?H_SYG>aPCQLzPa%p1jVNA?)0_?h?-( zI?4_Co4$J-%JB^qv3tAvlmx0O&J%W%d$&Dd#Y}4%`Hr=Up9;A}(7Y(0G@)S9h*$ci zBboCpEgL_M+vS&XFy)CN;=Use>dmJY1n9Q@Sw^UfYAt!>r&a6AFI!hBNphs#4*MwN z-8Afpgl^04TB*pKbeS}?sk~Cl9p-=R9Z{pw;WUHq%t@*psJ6@x2@X|DJ9lX5 z4c|0Nofpcb8BKnsk84tLd$%Zz^=sa_-vKUTlsuZ9Q7`JKRu`^_GL|zKmA9q)6=o3z z{RoBz<{%9P0c}UeS-|yp3wX6JMsr98O1gHsDD;!(Y3;HNul2m8Vw4+jX}5H&&ovcn zW42R}p2B$g1;3Ot=-LQ_H$)w(bV$Ir^;zz;xhdi~1VI)($2k~CE$^*p1ec#3Ev(V< z@2W7=LX22@W##IFxo)nP%R1DyE753Q?C*RlT-4TBu^Jr1w)8CXE|6hA=9uDRE z{|z%_i73jxRElIz*0Hrw5sHw#6xnxUXYwhZ651rY79`mcGh-bIWzWu-L1SlZgR#5M z8R?VnaX-iL9QX74-Ov3T&!@kxF4tVwdA`s0@;cw!d8&M`-dQ>Ut4SxnblTgYZ3LIi zbv@x**L>xS2@o`4MKjjaUk9Z$2F*Ws{$jms|u~aP;B+lJk+!E7r zPIUO^>kqZfU4o zew~@e*Ju9chs zH@gZ)+Y@%({jm2N`g-+?-P0@vH@yi;i@W9G1DNM^ng6K#%>g$p0(8rEPyPcK)pebJ zhq_D1{-x@_y!x+L{j040)vNznt6hfSU&H$UL%5Q9Jg)@9d#g{q_IL5DzBV;C@+CIC zm6qYyMvj%D=Sai)dYmk$kv#O-EHVUl8P`L)zo<56Hu}4KRwoB^4MYXKwWVcX-rsE= zSJ7&MA$M|VN+K#qNfPK=-M2~^(4ZmPBFhd+*Wd@ZTX`v7nf;X?9J@HFz+2yCG31MhP`#q4NSYW#wX-q#XLz<2)}uHdo0Zm|YE|o~`-A}KO0N5s z%EPs%W>7QU=mvlKyXwC_m--tZHhe-)Zb5wwK8&Vnx3~lxhHuQw9lH-3i@g&pMC4? zi27Jk@YswMYGVkhO3V)VNmTz?w=`cfa!r;Nye*((ym!}9@MEOO-B`Fyzy_`xQ-pXxQ{5jLpV4!^ z(vpX549iVgpInOJowQKLO{I7$xb`U`zn^qVP{?soc$u5sblvayr{DgXT0l@i#CrnZ zlXyry%qKn<>d0hK*d6q9wK}596;?W(WMygT(l@z&wcs23#@SiWvQWX5m9cVzE*936 z+plxq#j>JhwBt~>-t(67oz0*Dc&nZ_$$<}^dFY$?SgDIjIkr1^U6YtQxkiKZ1cevP z52Vb?i}SZYOOXJgE&kf1dak8JaPXoB%wxJ+=cwD+snq?6R4OTzxT;)o(>x55(SN;OWp_r%yk~kUs~$b3DEKCP4PL<;OvCh?6f7~k3ZrEzkyqy+R&AriBpVWUO}0jI^}>{5j%7*i(Eu-DbEw{1`c%axx19H zC4l}XxU)Arqx*V$dVSxS3GtTs7UTzt%&iS#l992uNXfp-VL}o`-pc&exjRZK9_-iU z2#OuT8makf=fz&(0*oMwt#{}yb7!#2EWC3f+4u~``NUV6V=S<_u)3kC=@}735@>LyBP1m?c$H(_73Rx64iyF=@VY}Hmkq5B z{ANA;{wMJ0b3f!6_ABmzcV4b<>?$iUUV1i(HWhan3hvv8Yf_MEvZ{b(DtRSP4`Ca5 zwTavim!?>kk&dHnk}ggJ(32`4eD+Ik(qjQu!C;qkd?%eCF0!w521&#X?aR85@@38@ zc6*NK$6$)Gy>szbQl}w}yk49y6Amo)bv*9Jl~u%n!848e=RSx@2$e;xJQQ&`os#_G z`}f8!ACK9<$*Y%%jpKEW#_Yi*be?O&10P*uc*E<5`io_=c8rvDFKDW3KY5jKM4A^; z{dJ`CjY)Rl$7dJm^i z%0m!%mVt958crA;Ddg1L#kHk>L{xw*qW7raJbR~b6(xCr&Wq?&SK{D>(dH%XPbeu; zWoKGIv{l8Aa+t3OX$;rhovF;XqS~IXc+fPIqE|Jfbg+M|3b@fP^iKpx*fFG9M;CZtt_$7mUJcg2fJ!} zZJIZmg^-TUe({*z#MZ4ERaZsVJs3cBEYUoKZhDM?ED5 zd?u$H&?B~`IE{pMB-X62Z{njgKb(_=Am&{?2_H*MCslGKq!ySe?WClv)S#`&r4M(M z_P{Yf;OF{9tPt87u{@NAY8bkUCF&inwA*y^Lx2-<1^=_doOcpb<<4ZE3QA2cfo9u@ z@SAU(3@b5%cJV+}r~8x4%&~b!oxV^^=Z<>OVgn5Lb+nO|A@KvcPpE6!yq-OTQ$bn4 zq5b1kPo#YFuyc-YhteH?_qSz-J6~6v)`GFh3C9(YCYpn`UcU(c@$;I_-UGi}#5JJT zax`^^FynqjQ8=o)x=g7qfOU}2=PuyYZg>BqWrt(bv=8={N{$high1>^!j3ER0btB? z4-f8gG{Z#?Jb`Dt6Os$tApnJ%|33Pg0@nBT$Qw5$-sn-$uM|*M?hdtum)gVbC8Rn0 zHc2*Mb!%xI3&85WKz~84lvxmpEF(RcR%U+AtmIC2jnq{qMBX3vj7(~zk$SrPPPrj? z2S;WA7@3k@9>jiF8i3B#`%Lt;9KhxMTIcHD=S!3)5)C`QmV=wx0As@y}BMAKgyT=w+LU|3k`n!;X~nwlbsmJ}ps zrysB*tPDD3zv1m_JHmj5Q70Vjm>h^FrXZC0ot3VMnQE)Jj>=TjM<&3eX1sDXOA&yy zvR%#ITj#o3o8wL;#pEsFTGpehm%8VlI*@h9{=@nPa4oCP(_fM4K^eWWC!WY%v0C~R z8{@iMkg_qwS+S5GTe^a(f!Dtky%dW6%FvKKlGFe3uR{0nK&_;BeCbA4IL^Gn%|?Vh z9p=&?rTQaLvCMPrXZ26lM(#FJu2rJ?GJ5c#efFc@yEndsQ073V7xL#r(U!@L(T?wwtcX57&=m_(1$u6=}YnE{N z+~z#@*SqZS+!6e<^Zidt(7Zb;y^t+W(kr`I`;MI@y0}F)gn^2zSm82zO*s7@Bjv9Q zAjy5}4fIs6+h=v&&-t1LKKNT>&@!}Jf_6c@u-A0INld=bxCG4Nu@|@gcn~ah0Jyni z@t%73-D?_jl8k9w|M6B05E$ch*rm)FUL1S^*FGz{13b44Kq2Q7xMTl)o5=a~qGNNX%*jJ7 zr?;2lPvQgN$H0$?^1p=O1?MX>Cv(fYP9hPuFA9fVIjv-qq*lJ-S+^vm-~8(NNQ&x1Gc$_IcXBMn2b_{oWPdHFIdHo-imDV>JOd-rYQ3|2|5h#r z%=9^EmaKPK?>#+5s$X4&Ye}j*EywWMXpJQ@lm!ydsncbIk)R6BQC_=agZZQ|ejuO& zp8;fTdxo&0P)8&6xHRdaO~^6i4Hlv=k_pVL;C4}LRhnjBS! zX9C5L@ySf?5f$(rbvsL@VE7W0qtfquvGer9JVnSU#l$7Xzq1m~IQ87%`LpmzbNqVn z_xtt3(?yNavl?kB2trE>@ zK!uhgdFAcJVKN1$qxr(vLnGYt5;(QY@7?t{DXS#+aCFGf*2Cf2=D9$7)b*tSEGno! znJO?}$zF-+a!TgGFc@za=3H5QWJj2z8No|@Iq(vdWWV2K0B%!lfv>GmS;w1kKcHAg z_J(&@6h|0_S~1EIiseo{HcfdmTk-eIhN1R%LkD7RMes(_v+}SOU1o-GQX|X8Ps$)Y z>2-?cGAlMy3cD2xX-ZQ|lD(h3|oyMYpU|zIJa0F@u7@@D8P25vwmDgO z#$LwPL}VET*ih#laP~5mrLvG`cvN4m`>~LD;Utv8PmlM9)plvISF^==W``eE-8}zL zsNBZdXVCoNd{~5+8k?xhx~zBG%jqP1dHwnxwErx}m8~5HG9*uG?>WZ)| z_hEjX6J$?T8tB^qH$KOzI{-HfaD#;raS!(loC3f|EG%tQMpjfj;$cc-7oia@I30C8 zKEZGCt`%)KJ-nm{0n5reGw@a^Kmo9#1JDg!@7@}c&##HOcg1d`!N$5q0n&FPD_C@L zNQ^8)&4AO-I$Y~x3nVV3HhYbR1!k#cj2DG>Co?bBi+E+;brMwLC2t}?+0iMtODD);FI@?tztOj_@XyiqjX?;^#n*)=g2fA=#NRKSpr4uCrVQp!oCfsso;h44QW&cBI5VmwOR z=Njz44s0t6Ybv#2wRq;2+SNkOSoZCKsnw3n3%w2Q^WoJtj-TOoT4$-=ixpKEIx-P_$&@rWvNENVm=I;gDJTr5|7O z#4WLA+>;~KQDSoR##KBk0@%K*fx)Q!B3UOcKSX{jPbvRuhHvq;1HGfHvHh&*3kPJD z&sR_p$OkjUfF-QEjU!Lz5}V>d`$u)&wF6l8Od>@$w~A4vmP$*Fs0AIG*sSg~<5DV1`9|NN zOXfB_Slq{gRPlPD8rgeR&&LZKa4gSPn&wiWaNPncI->3Ku56G3nB??e+`aU8WKU z00h&{ZEo!-3{$t5{fv9KR(JIXS%t*{6=t!KDF-eqG^#JQ$=;HiDN}jbwQXQksiO0v zg&(CgA5kEE!$E#jS4dewqcRo+>Ia>LC|^$k6!cokGCFWrIt?OpA-?SILZaL0W#44% zsci+$6I$C!p8pIx3WJp1a^vv2Jbd+%Sc1XoN{2Xk2Co=^)jwK%<~W&*X9pObrlS^B z=tj6~W+`Lv_)Hbp5On&gcu>?dwh_RfS+~=QGRt2sBQ zYRKXt#ar)0d4kPld?_NO+a+aH98!{!{L4C34F5Ga{~C&oftp5$W8az zZz^4*l58-QL81ziY9{(lJl?iPd?FMSRTXaRxk-$xiTSB?k*P7v&1Oy`(=gaB+a~5C zVdT~bD0;rsJvDY!EeA*0sbYag*5)2yDY*kC=1xP+bEPBk38s9aRGf!iZ37TyB}EwT zq!{a{x>T;*s5(i7VbqA%3EM+6dJTeizE?*Z8-r_7Gfe1Wm3$Y;jgH)DUt{-F8u{A}H28_xoz z8~z9f@p7??Ddsa6cCvH;c1_M>xyrxIyjLKN3jyiwbC*3=vflOU1iRoi%v@N$^xg7& z{jus2a`uuyxnF_%+%3;f3$6R&eBz^coPiZbn}9))JDGwP0tUJQ$JPMX@&YDtWj!@6 zSnCzMU-t{Wt=3GI?WJt`Y>C*2j)ER;Q;P2w@M|9aSL9Vu4gS%;(BrkcZMnOQY>F98 z#rOB;Y}I1B1D?6rYS|gUKHciv%>KfNw$OHn>3(*U!tnp746^J-T{x_5X>pfjUDCoe zv81mQkKjt?zc~PN^X4eHWhBO|;CeC#dAYCbmg+=9UAa@=vWY)dlg#K^V4EIQmfl2u zr-pSa?MS>{cpagH@qN~f8HaU)=UUy>;4qwkXJTr%*DP-l&)P^3a}a-xUV_fIlh5b4 z4hZn!R^6{Y=!*yMrY}5wkS@EgB#t1)0_|eIluhR3MZn4Juzb25r!M(hq3C3Qh4i=g z^^~szHG2a%cJ0zK3U?oOciXy_JV(l}C>Q^a4)gopaN5f^bU|xd@9x7?fJprEF8-Rb z?FGPrG0B~Oc3)=z;D(>(kC_7Ei2>q$T=?v>i+F%^T>p~pU()@S3vkBJ{{q)Zn_I(R zh!Xv1!F~NvtQo)umY>aYo}uD%h|Y%J6TU3-Fk93 zuB%cIA&+~zCkWx0Cr>lkD%q=jS3hXJ1|+34Sy)(LySsaPyYFspb<~eGH#YO5Je{|N zM~8fjr>N>{0WemOUxTVHK*ai=uf{Gib@4`v3(RxFR+{*yg}`4>Yn`@1v1Zn#vUKR{H6?IY)mW4d=p4Ehp2b@> z*&?3rw>ENa1f;>Xp z*E&oYvycdsDoK1E~BC8an?3m(?VUYn9L#02dF``y+mB*ozvIs@1QVveeW}KsW-PjDS*n~Aa zjHq|K1dnvs`2sWe0++rsCA}r;*pof)Urt*D%nq1#l~r!YD^Jg-@jidlSN^#JN*#;4 zxL2Ud=fjj|j_;kq91P4eoM`L#BWEPb&vh2f-FJQI4FGju+=||S;oD0z_K+7L)gblI z-H5|IHs79dw^L6CU^)$SD#}P9Dsun&duK4Smj94427B{b0uE- zp?Yf;S&tBV%F|curLKo3bRBv4la#B*CyovJS;Kz8zr47!J3!}}>=hh82Yk&rqbpdU zD@8FttZMjNZ44A=UZ{quaa%LL|3uY>{^JPQdTFTc`CUCSdBd+zSlaV<(o}<-Ss0_v z-x`{*1XzQBzjIC^s(UVUV0~>K_s~I-qr4f8=9vpp{?R_|iU`7XD(}qaEpUUQ;TA~h9z>2gB{NY}-{nYGg zL$*s_vCnlX0n*c(Yh>1U1C=hb-xDxG6pnfiN1LYwL^`${zP>GYR{%zF2a1RC*KITZ zUw$Ip|AMvH8PUHO{u)<}fdPLvPKS&agkc*Oc@Z-)*fnf|0wUo~0HJtF{spvHBP#(UZFHMV6=wgOy}PhM zqM7;rWInPcEh{U6KI$D?_yu=yW)-%jsJ7ukvpcM{Z`-=ReE*fME28bv~g?Tv1xPi zf3H#CI=zI1Tr17rI`j<3>k^}PtGw_>T$rcfX@5Qrf`zy$PBCPqw?k`Wjl+X^AK{zm z34pfFh&X(iVtAYgZ@izJ6n0)4gojSUv5yoKUy53#>tvk!K7Tx-5Mf>zh*L!PJ1cF$ zh)cFw8$Kz%rAn(^0d9FAAuJ3sT8a!GFf%OSvP05h1EpJ8vbT_U!iipw{8fsMX{)dnbGFGLp06J zxoc-<0WggE_H@=jl{$KqixG<$tORevAT8j;~P2Bx8eK4g;|6Hn8uvy+EES#m*c{& zuKmspf)^`jI8vwi;l#l}bM5A|jyL^K#QkEO z)u!bIo&!cdIW(?fbFK`Xkl?tE3DBOIU@6D0{8jEam7WMjQ?Dd?!TKnzX1O4!oc?>$ zfbm!A#o|eMX+uL6^aV_9exnU`Ds}OprW3KnQauWUuNhb!RpvIlsYpl%=wX_f+~^MR z`Q_oNtow-7n=O}Hv0CS%5BBzMtmLG~%j6R@Q*Sq;E_?)L)(1R_DVle(*iR!Dab1x1cv_5>PiQx9ZMl(^Bq+@QNtb!NKwx zFdRZIjd<;K461;heucGXlx65KJIO-K@uHQtUWfp$FzoVak+USE=*nH*MM?>SA~@7{ z*|3}N0w}z5=Pnqn+p8XWU;D1%nt$27x~qsD5hMO8TWvY}kN4v_`9`#{N!T@0^wk3s z9ac6U2$cdZSXQ+uf#oK|XCq&iexty-x|ow$P5ab}J&flE1KMi+HMZS_kFS7Sn*1NV z(jc1gib<8Oow4_J?ZGzN)DLb2Hd~s2?|Lw=)n!-?16s+F(pveL>XpdVIsO=FQE-Zq8#D3okPw@t@LGVv*Nq+77h z7jVX4KnN@LXkysVtVCVo+sUb#s&TH7vwAJ05qINi^D#U}p(@1YAeW!yXJ(Ze%Y1uC ztt3cXhmOB<&SN-K&xE;=mEm-dxATF!QvrWg6yn1LgSx)4xEuA@W_NyYK=wF+rD|%G zoIZvXo^F`(N`klMSY(5uu zE#v1YwMVY|4E1w7#K@d4zDRfn$FYwrJDluPD#YInm&O zpS2e6kVRW_lpF$WDB>*Jnj}2o4^@;n#PL{Gqu<7t)chqyWvKR0&nE7 zc0?pfs|i~ci^qR3w_B1`r@j^NWtRtKjDQ%@ zLycy|A5SF^T3q`CYUS7Vd=N5P)Q}nx{m7kTR$}^?)R=8)R_+%R1pB1y&sT)+9$8*> z)G6feYvhhl)lZE%*PNodT=iV(+M~?9T}?RT6MG(ZAFt%cp=IPf{|GsC1FFBsxc@y0 z9jch0A|cp!BZq@L_DZOP$ zmy(_Gkf)1>v%q@sokd#a)3gu3unu^Uvtry4#sFTwxFkwna3?b(mpSr;kdvp*byZ*H z+mUalX%iuFG$ln(;Ij|^=BBJTkbR(f>_d2`MySyNxg&<_mASUGxReih$ozs%q~9Gi z!7KR6s)2PVfN;WE0Kz4f>$3wir=1$J60c|Qy|wO~l~R}F%Wpi1d%z^xoplljPK(p4 ztuciA!_aU!Q&C@NbGYg-mkP^Y?oOV88*=HrEUL=^9CszO3*B7GyVR#`Gv}G?aulZf zP=T)FgC_`IhI8WD?4)wB_E$<$>S;n1ax9gNRfg^k&I@g*Kg;IrjLj`n|LmF7SUoxa zW9n6Q%goc-w}tH`WT(nN_Z}7A@$O5`PtaW8%KkAjBX3;AJ#9_67G8M5pj;=8rl-K1 zzvgq#8{voI+T0KUFQru9)4C7(r~6DT#N8XMD;{zuI>x%F>e#KJWo@&(R~7dIQy^@Q za&bmf++KNBUFT9X_Eg1kWx%wdF?>cqjYqlUllP5u80frIu5Ik%qF#!8@l2Z}X;or6 zf&A|4hJPBlsb%7b7=;QN^eKm$#fS=6P4!&tP%~sV=`DCFoM&M8P(z)%S<}Ob%ppFI z7>Jvxae5%ggw;P@A1mI8^BA9xyYGK<^Cy-Fql*rgav91QyAKW|k09E`PwtON@GUM` z`?^|pU)E0Yw3S^vXg2fhW~NPs*W0BcBl3Hmw^`xeJ9p7U%)fh+94*p|_3Mt|9wuPp zxVMt@sC0RP6jKh<6e60iCCPYUh3OpEk#2i60-{+AUrB6aVgNNbjmE~P#+Vf`#?f$r z9;|r@;cmE5CSLCdc`K(VN$vSMTD#SUO#jq)4bQrX^~Hc#n1IthE`LnFt(80i$cz=cE(hZRS}Wmg6#e#S_&rg^MFz!`bxEE=h$V zgsY1}01^Gu{=#^5q+>l3H)Q&9rl;RzQ&Rotj3vrLrdHR|ZneU6OHDmwBiLpW?d#?# zyo?R@Jj9_eefzXF#%OXxa(D$qalE8lL;!Fmbx{Rd|WbAsRMX zsx4*Tk*w_`@Rik*Q|na^n`pA+5Xh$ik313XsD#|;w1@K7&JIisTUvbb_0H(O@buW= zNX!!e*3^RH#EzG_=1HCMvV?+DRz7A+NQsEgRIqe?j?0CzyE&d+EIbq5eCui;!adWt zaU^$o>h>EiMz#wSex;@DV-19S^EornO}+vt$6lrolohe2%rmwQo7|J}Ebe`=Yz3#X zZWjL%R1AW$_QY@Y2=V6?oR#Azc&X2NExa{q_!}TByLWHp$iXi;&Tpmdk&)LX*%w{M z`rc5P6RT1+J6xj<3(kdRUv<1r&byO6VlBC#<5i%!D>9@(d)qpknoJ(BlG`q%f5T<} zhRgnqGy;GCgJZF$B)a)co$kUrU2I{{J1=5(IyLDOgUHgj>bqc2>dgUmwDIZ%pOikf z++RuKrD5u6vKFj8@=K_!m4T5SAJfV{EL{RzAZAcUm=w$3l_is$Be{tc1%>&F7r*<^ ztu;&^NFUyoLbMkEb8Q_drsu4M_s~^$l~Jvy>Yxjf;#2}p$CLdk0Om@NOHNkJ92s@8 zG-j5IIYVJ}v;${re9{*gen|e3W{o2t_`?PsW`j>J7nh(~6Cp`dD#n@jiwyp0h^0{m zhUdQ++Y8DSE)Lubbfz1KfOVY&M>0$n;T45`=>#2+TC9?-nq@(2YiKQ1UIdx#bSMO| zol_VkUn+u2PHwL2OaHwcj|KeVf7PnBp9h-vl2)cLHRR47c~|ouOB0jsa*wZe8{JLk z=0@JHg4X@u|8xJ*(X9@l82o#azz7XZS zqq=mhKw8>{nm!18L|w90M;4`P!1~(Eyop6^5=8*T6qS~Cnp=N7nNG=aB5(1(gDt*D zmU{aGD)`ksEVNy>gw{w4Ifkg{4j=y|bl*fxjYIXJA}zw@nVl&=z6vswgmSL1A9lM2 zQN1^LQKs8R_e1RzIgf$7PHvzF*{oRMS|0^hg$Js1nR24V?g4f!lFoLa%_ET!#xA&0zu`CDucOEF z3c0seaG;&`cLYSwdCLc!Zg~jarLs~ps_t4?2YqqejTzE-1oY@9i1+(h-}q=lRR}6~ zgs%_$;LL`~B)2zRm4aZ&b>w=gi-yNzcOn)waIx2-I)ErQ4t^_c0p_c(Ctq?we5qWX zl9&M(We4%gkLTpbGsW+Jm0)IWp6ICNRku@Lr0)ojb0;=qhq&AH(Er2K{Xcmk8jcIY`EDOz0?;N6Y%FGI$z?j!;ZwVN&HrQ+RZ9*PzV+QjK$QwNv$$vtZDVVs^X` zk3SU7&c5SLK094-_f#N!#w78 z+d(<+X&-M9jZ`{Ff&yD8Cr42(b8u&K%ggR2>!WIc4}$-uJLtB~ccD1|tct!Yn7%E4 zdNJ@uU$*uf)^Xgs(3wXsyw5&{z|82INDom8=2NE;JaIkC^*Y&wjs5|s`rz)B?R=792?hbSq!aR!8jS{SFzFHpgA=pY3^do`ufMgB1v11_Im-+xC8f#tM z0wMK^PdARxVRY|PRjurQiLae25Rq;r>FulVzfLYdJ`UuD?IO9j4Z!p00hwzm1xa<( z4?OAPz@wfT8q7IM7jjNhL)yfE7umJnftwnVA=IMaYxvl%NcL9fU>}01in9Kgt9fDUmYRdlky+6zCE@j8Hd zxpE-XSh~AupbEaN2*x*XuO3;k@SFjx2ihs-34x9l_WQ^9o0oK3$S~s!u!Kv|2b$h~ zwXTiEXY?Va-UXG{b(o5h=b{JZVwI99Lk&^gQ>-Tl+tCFlANJ@LzN%eGjRg$YcJS59 z<_l?3diTll!}&X+vruektjgGc{9QeYX9!EEP#^LcUs|s&afF&>bwJz#@I_TUbDqmw zv#3{%&DA;^t$vgUz1@dexuVV;bC)Jux||kWHq_W0Los&)FM!aU;%`yD(r>AF7NqFk zf*#i;DQ#y_PIgXg>$D}J zv`Ivb!+>UX12kz4OBba`UGUH@~t=PY*pGrpDdSppSnF< zO=U@B?PK2 z9Cy1DV8NMXw{_;=Ci#?cV%!_61M%eI908yJrt%K!i%>Vy=NPzVijl!V`xP`1KG|tA z0c`_+R%yfL&h573n!o{m>T=z0XhFU}p9Y$-ttF!O7qIyC$2&mz{U7|ObvWP#;(AYj#Ax_G9V%1z@9Z#!7Cbh-thYwO?>mL- z^@rWpXT%8M(>ZO)w?8aFWX!m!zo*xP@7+zH zO&(h*2M3m~27BvFl4=&VMq17S=N?&~5H`E~AqGdJ$4+}mQK@tB&F-bca0e>R4z@`Q z5ar7Hc@5_3&jmf4^oEj!7;At#!;!9pu;q6%6##A!8HZA@5S27q|eR9 zC{r=27p#(I(_N z;)$bfBYULG13G1sEn_D>h`_lyeH)*<25u6K?D%fF5lP{FlGx-5UzoFRmQ9Tfae-i~=XjcLX>hDnP7U2W-< z@pW8nwEQA4!Fq8sS;2RN3Cl{C%_bHtxsjF|X+^S<+b-~$Xud`f>7d>C-~r}Oe9%4# zerXi|HZ!!sx`4b$NpkT*)M3zaBVBHfzhgJe^9NH^J`WO8Jp~ws0L_>KQw@ggv}M@ufGG3@8MV6E=^d73&HdHRP-hjWiEimD2Qcn(yl?3I4?>lNxTz=mq< z1ANcp_3R`YxgtSh_C(!G^}tF@<6fYzPttNVh3Apgh$=jDc~f+*BZ~oy%K-$DyYkvV z&l0!`T%gkCov$r4hK6~ROqE4)?4w>2syZe`D#*R%``@4$ZXIX349ZTdxP7}3Y3+vbUB#_LE7G%Vg3 zupqx+R7z!Y&xmZ0n!$qDSpzapodXJhpM!Sd*uVZnHU=0fK`tu%W0%d*Gq+|V3^R*JCNB_E+^=k7W3%UTW%ZCDdTH3 zEk`MDy#wC*GQbMMs1u_B9>$v6>%w)ZlC#=%f2oA{PJBjd_{E##rw>bi|7XAO-28&K zkVdM+Y`jSSGHBBb;Xa)ApCF;WNOoBoFPorN9!Ty_0h%|%ZmBGmeS{kb<$eCV&~Bi2 z-J$89meZ8JVzQgwmQ=Qv4; zi#u6yuYXK=edSY9<$3bMWAs{NGJwI30~GL%^kntGVf_n#ZV7tc|Jo8rZHhZBnNBK09DC^vi!fmdOEYx3UgT!?qiQSww0AAqz*o{1&U zV#9s!!ajjR_&CC2u23ZeZTjqTPwCw9a8h>Uh@<1^JYLKE&a|TX0=eQ2{4xq46hZ1{ zGq7=>f@47<>CI+pmn)B404^}Jpx}a69e6vC?n<;H3FfK7me#Rrn)gHo#Pkl4Wp&^i zWwqs^A?l~z?%S_;WM^-<_?M5Z0^qbFjr6lpayeL2i$uUVR>e4EVTUPwV+8s%({>ZR zw!X?OJ8kA$9WaUs+NeseGRndVg^BVkeKMex`brZ$px(RDKphvmKZeQ6> zuM}bg37JFo7&9|o%}}lR?RIak&Vwam3%HO(9_?>GhBY5pcSS?z-32Maz>}2x)$*zc zg*SGd<^p-3DlFGA+aDp1hpg`|fpT?`eB<`t&6+6ht^uCB=yM(Nl=c7R+R(6O1JLWz z)FJPk)-Bs_a0h&f*Dt)X>tlZm_k96yPQ>-jut>;%)^JoPk~K+SO~FCbtnQR&kaY^$ z3$RyPPcCS0gSKa!%8_bJxzWSNrqU_ZAcf^J`3AOns(<_NtJA1k2S%-Lc$)U7ERid1 zpMxN=UQLfB&=-f`sE+KU!V*sUuLC2Dt1(1akvs=|TsKRK8a_5kFeSI#iobTTOh&A~ z3zWS8cc(eZBQ5I;ID4F2te-Vn2)uN_QQ^e{{F;J5)m#vAvU9VWr@#>JzbtrXyk3MArmt*v6C$5YBJ8y zqu_Lgw6wI0Wd9E!kBVk?M=xb>9XJmbntfO;Jqhf$5uD_6Yaey%K73V+l6pqo z&Ffg%8|tx*R6FkOc#}5o!*}H~U>R-tkD+Kq1id>`##e#b$!bSM=hURLQns*Prr4 zq)*VOuM9m;{PPE3zU}1XkNBMS{kvYp1!~u!=XX77Z3Gm_jd6RzE*bwnrJ^j|U|=}g z*bW1t6I1rtyOl^4*!I6A*JS=f5%BmqGbub!4JE%jUu~QS`?k6Xgx3m2*V!)3lXSZk?2i4q;#}^q;fq$1S=$_9xYklv306U&z AX#fBK literal 0 HcmV?d00001 diff --git a/doc/imgs/image41.png b/doc/imgs/image41.png new file mode 100644 index 0000000000000000000000000000000000000000..e16d914c40de0a1c3cffe56d9c35e4697eaddc7f GIT binary patch literal 13899 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 G`M&|@VI3d< literal 0 HcmV?d00001 diff --git a/doc/imgs/image44.png b/doc/imgs/image44.png new file mode 100644 index 0000000000000000000000000000000000000000..ea8387acad19e1fa84006014a42e569730b34821 GIT binary patch literal 1881 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 literal 0 HcmV?d00001 diff --git a/doc/imgs/image46.png b/doc/imgs/image46.png new file mode 100644 index 0000000000000000000000000000000000000000..6acdd455c217b17c5d15167250e14e8e39346d60 GIT binary patch literal 16055 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 Q4)^kaWmROVq)dbV2f3-C{r~^~ literal 0 HcmV?d00001 diff --git a/doc/imgs/image51.png b/doc/imgs/image51.png new file mode 100644 index 0000000000000000000000000000000000000000..072d0b321a268467edb9cfd620049a50fdcaffef GIT binary patch literal 411300 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 )Uk?pOZQ1^>?=ga3|# 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