diff --git a/libTextEdit/README.md b/libTextEdit/README.md index 2481237..27fd9b0 100644 --- a/libTextEdit/README.md +++ b/libTextEdit/README.md @@ -25,4 +25,12 @@ ## 开发路线图 1. 基本的源码展示控件(WsTextPresent) 2. 基本的源码编辑控件(WsTextEdit) -3. 富文本渲染控件(WsRichTextPresent) \ No newline at end of file +3. 富文本渲染控件(WsRichTextPresent) + +## WsTextPresent项目开发 +### 设计思路 +1. 纯文本输入和输出,除了换行符进行内建处理,其他的文本元素一视同仁; +2. 多视角设计:基础内存模型视角,元素排版视角、文本编辑视角; +3. 多线程语法高亮 +4. 统一文档内存模型 +5. 纸稿排版逻辑,基于预设排版位置 \ No newline at end of file diff --git a/libTextEdit/blockdatas.cpp b/libTextEdit/blockdatas.cpp deleted file mode 100644 index 4131340..0000000 --- a/libTextEdit/blockdatas.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "blockdatas.h" - -using namespace PresentDatas; - -DisplayGroup::DisplayGroup(const QString &uid) : SpecificEntityData(EntityType::DISPLAY_GROUP, uid) {} - -QString DisplayGroup::styledText() const { - QString retvs = QString("\n").arg(this->uID()); - for (auto &i : children()) - retvs += i->styledText(); - - retvs += "\n"; - return retvs; -} - -QString DisplayGroup::plainText() const { - QString retvs = ""; - for (auto &i : children()) - retvs += i->plainText(); - retvs += "\n"; - return retvs; -} - -TextRange::TextRange(const QString &uid) : SpecificEntityData(EntityType::TEXT_RANGE, uid) {} diff --git a/libTextEdit/blockdatas.h b/libTextEdit/blockdatas.h deleted file mode 100644 index 100b7a7..0000000 --- a/libTextEdit/blockdatas.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef BLOCKDATAS_H -#define BLOCKDATAS_H - -#include "entitydata.h" - -namespace PresentDatas { - /* enum class EntityType { - TEXT_RANGE, // 字符集合,包含段落和句子 - IMAGE_CUBE, // 图片展示块 - HREF_FRAGS, // 超链接 - TABLE_VIEW, // 表格视图 - LIST_VIEW, // 列表视图 - INTERACTIVE_EXTENSION, // 交互式拓展插件视图 - DISPLAY_GROUP, // 元素混合组织成包 - DOCUMENT_ENTITY - };*/ - - class DisplayGroup : public SpecificEntityData { - public: - DisplayGroup(const QString &uid); - - public: - // EntityData interface - public: - virtual QString styledText() const override; - virtual QString plainText() const override; - }; - - class TextRange : public SpecificEntityData { - public: - TextRange(const QString &uid); - - void setStyledText(const QString &content); - void setPlainText(const QString &content); - - // EntityData interface - public: - virtual QString styledText() const override; - virtual QString plainText() const override; - - private: - }; - -} // namespace PresentDatas - -#endif // BLOCKDATAS_H diff --git a/libTextEdit/entitydata.cpp b/libTextEdit/entitydata.cpp deleted file mode 100644 index 78edd9f..0000000 --- a/libTextEdit/entitydata.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "entitydata.h" -#include -using namespace PresentDatas; - -SpecificEntityData::SpecificEntityData(EntityType type, const QString &uid) : type_store(type), document_id(uid) { - visible_bool = true; - oritation_store = MemberOri::H_LEFT_TO_RIGHT; -} - -void SpecificEntityData::resetContentLayout(MemberOri oritation, MemberType child_type) { - this->oritation_store = oritation; - this->layout_type = child_type; - this->layout_type = MemberType::BLOCKS; - this->anchor_info = std::make_tuple(AnchorTarget::NONE, nullptr, AnchorPos::POINT_LEFT_TOP, 0, 0); - this->size_min = QSizeF(20, 20); -} - -void SpecificEntityData::setVisible(bool state){ - this->visible_bool = state; -} - -void SpecificEntityData::setAnchorTo(AnchorTarget type, EntityData *tptr) { - anchor_info = std::make_tuple(type, tptr, std::get<2>(anchor_info), std::get<3>(anchor_info), std::get<4>(anchor_info)); -} - -void SpecificEntityData::setAnchorPos(AnchorPos point, offset_h hoffset, offset_v v_offset) { - anchor_info = std::make_tuple(std::get<0>(anchor_info), std::get<1>(anchor_info), point, hoffset, v_offset); -} - -void SpecificEntityData::insertChild(EntityData *inst, int index) { - if (index >= 0 && index < children_store.size()) - this->children_store.insert(index, inst); - else - this->children_store.append(inst); -} - -void SpecificEntityData::removeChild(EntityData *inst) { this->children_store.removeAll(inst); } - -void SpecificEntityData::setMinSizeHint(const QSizeF &hint) { this->size_min = hint; } - -void SpecificEntityData::setMaxSizeHint(const QSizeF &hint) { this->size_max = hint; } - -void SpecificEntityData::setStretchHint(const std::pair &hint) { this->stretch_pair = hint; } - -QString SpecificEntityData::uID() const { return document_id; } - -EntityType SpecificEntityData::type() const { return type_store; } - -MemberOri SpecificEntityData::oritation() const { return oritation_store; } - -MemberType SpecificEntityData::displayType() const { return layout_type; } - -std::pair SpecificEntityData::anchorTarget() const { - return std::make_pair(std::get<0>(anchor_info), std::get<1>(anchor_info)); -} - -std::tuple SpecificEntityData::anchorPos() const { - return std::make_tuple(std::get<2>(anchor_info), std::get<3>(anchor_info), std::get<4>(anchor_info)); -} - -QList SpecificEntityData::children() const { return children_store; } - -bool SpecificEntityData::isVisible() const { return visible_bool; } - -QSizeF SpecificEntityData::minSizeHint() const { return this->size_min; } - -QSizeF SpecificEntityData::maxSizeHint() const { return this->size_max; } - -std::pair SpecificEntityData::sizeStretchHint() const { return stretch_pair; } - -Document::Document(const QString &name) : SpecificEntityData(EntityType::DOCUMENT_ENTITY, "Document-Unique") { - resetContentLayout(MemberOri::H_LEFT_TO_RIGHT, MemberType::BLOCKS); -} - -QString Document::styledText() const -{ - QString values = "\n"; - for(auto &i : children()) - values += i->styledText(); - values += ""; - - return values; -} - -QString Document::plainText() const -{ - QString values = ""; - for(auto &i : children()) - if(i->isVisible()) - values += i->plainText(); - - return values; -} - - - -void Document::resetContentLayout(MemberOri oritation, MemberType) { SpecificEntityData::resetContentLayout(oritation, MemberType::BLOCKS); } diff --git a/libTextEdit/entitydata.h b/libTextEdit/entitydata.h deleted file mode 100644 index e4f2ba2..0000000 --- a/libTextEdit/entitydata.h +++ /dev/null @@ -1,241 +0,0 @@ -#ifndef ENTITYDATA_H -#define ENTITYDATA_H - -#include -#include -#include -#include - -namespace PresentDatas { - - enum class EntityType { - TEXT_RANGE, // 字符集合,包含段落和句子 - IMAGE_CUBE, // 图片展示块 - HREF_FRAGS, // 超链接 - TABLE_VIEW, // 表格视图 - LIST_VIEW, // 列表视图 - INTERACTIVE_EXTENSION, // 交互式拓展插件视图 - DISPLAY_GROUP, // 元素混合组织成包 - DOCUMENT_ENTITY - }; - - enum class MemberOri { - H_LEFT_TO_RIGHT, // 从左到右横向排版 - H_RIGHT_TO_LEFT, // 从右到左横向排版 - H_CENTER_IN, // 中央对准横向排布 - V_LEFT_TO_RIGHT, // 从左到右纵向排布 - V_RIGHT_TO_LEFT, // 从右到左纵向排布 - V_CENTER_IN // 中央对准纵向排布 - }; - - enum class MemberType { - BLOCKS, // 成员被视为块元素 - INLINES // 成员被视图行内元素 - }; - - enum class AnchorTarget { - NONE, // 文档二维平面排版 - WINDOW, // 窗口相对偏移定位 - DOCUMENT, // 文档相对偏移定位 - ELEMENT //元素相对偏移定位 - }; - - enum class AnchorPos { - NONE, - - POINT_LEFT_TOP, - POINT_LEFT_CENTER, - POINT_LEFT_BOTTOM, - - POINT_CENTER_TOP, - POINT_CENTER_BOTH, - POINT_CENTER_BOTTOM, - - POINT_RIGHT_TOP, - POINT_RIGHT_CENTER, - POINT_RIGHT_BOTTOM - }; - - /** - * @brief 基础实体数据 - */ - class EntityData { - public: - virtual ~EntityData() = default; - - // 标定相关 ================================================================= - /** - * @brief 获取实体的ID - * @return - */ - virtual QString uID() const = 0; - - /** - * @brief 内容文本 - * @return - */ - virtual QString styledText() const = 0; - - /** - * @brief 不带格式的普通文本 - * @return - */ - virtual QString plainText() const = 0; - // 实体属性 =================================================================== - /** - * @brief 获取元素可视性 - * @return - */ - virtual bool isVisible() const = 0; - - /** - * @brief 本实体的种类 - * @return - */ - virtual EntityType type() const = 0; - - // 排版相关 =================================================================== - /** - * @brief 成员排布朝向 - * @return - */ - virtual MemberOri oritation() const = 0; - - /** - * @brief 成员排版类型 - * @return - */ - virtual MemberType displayType() const = 0; - - /** - * @brief 获取元素锚定位置 - * // pair 文档二维平面排版 - * // pair 浮动排版,文档元素定位 - * // pair 浮动排版,窗口偏移定位 - * // pair 浮动排版,文档偏移定位 - * @return - */ - virtual std::pair anchorTarget() const = 0; - - typedef float offset_h; - typedef float offset_v; - /** - * @brief 锚定偏移位置 - * @return - */ - virtual std::tuple anchorPos() const = 0; - - virtual QSizeF minSizeHint() const = 0; - virtual QSizeF maxSizeHint() const = 0; - virtual std::pair sizeStretchHint() const = 0; - - /** - * @brief 子元素数据,安装元素书序 - * @return - */ - virtual QList children() const = 0; - }; - - /** - * 具体化的实体数据类型,实现共同的接口逻辑 - */ - class SpecificEntityData : public EntityData { - public: - SpecificEntityData(EntityType type, const QString &uid); - virtual ~SpecificEntityData() = default; - - /** - * @brief 设置内容排版约束信息 - * @param oritation - * @param child_type - */ - virtual void resetContentLayout(MemberOri oritation, MemberType child_type); - - /** - * @brief 设置显示标志 - * @param state - */ - virtual void setVisible(bool state); - - /** - * @brief 设置相对布局元素 - * @param type - * @param tptr - */ - virtual void setAnchorTo(AnchorTarget type, EntityData *tptr = nullptr); - - /** - * @brief 设置相对布局偏移量 - * @param point - * @param hoffset - * @param v_offset - */ - virtual void setAnchorPos(AnchorPos point, EntityData::offset_h hoffset, EntityData::offset_v v_offset); - - /** - * @brief 在指定位置插入子元素 - * @param inst - * @param index -1:尾缀位置 - */ - virtual void insertChild(EntityData *inst, int index = -1); - /** - * @brief 移除指定子元素 - * @param inst - */ - virtual void removeChild(EntityData *inst); - - virtual void setMinSizeHint(const QSizeF &hint); - virtual void setMaxSizeHint(const QSizeF &hint); - virtual void setStretchHint(const std::pair &hint); - - virtual void setStyledText(const QString &content) = 0; - virtual void setPlainText(const QString &content) = 0; - - // EntityData ==================================================== - virtual QString uID() const override; - virtual EntityType type() const override; - virtual MemberOri oritation() const override; - virtual MemberType displayType() const override; - virtual std::pair anchorTarget() const override; - virtual std::tuple anchorPos() const override; - virtual QList children() const override; - virtual bool isVisible() const override; - virtual QSizeF minSizeHint() const override; - virtual QSizeF maxSizeHint() const override; - virtual std::pair sizeStretchHint() const override; - - private: - bool visible_bool; - EntityType type_store; - QString document_id; - MemberOri oritation_store; - MemberType layout_type; - std::tuple anchor_info; - QList children_store; - QSizeF size_min, size_max; - std::pair stretch_pair; - - protected: - float appoint_layout_minvalue() const; - }; - - /** - * @brief 文档数据模型 - */ - class Document : public SpecificEntityData { - public: - Document(const QString &name); - - // EntityData interface - public: - virtual QString styledText() const override; - virtual QString plainText() const override; - - // SpecificEntityData interface - public: - virtual void resetContentLayout(MemberOri oritation, MemberType) override; - }; - -} // namespace PresentDatas - -#endif // ENTITYDATA_H diff --git a/libTextEdit/libTextEdit.pro b/libTextEdit/libTextEdit.pro index 52c6dc8..a980c5f 100644 --- a/libTextEdit/libTextEdit.pro +++ b/libTextEdit/libTextEdit.pro @@ -1,4 +1,4 @@ -QT -= gui +QT += gui TEMPLATE = lib DEFINES += LIBTEXTEDIT_LIBRARY @@ -10,15 +10,15 @@ CONFIG += c++11 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ - blockdatas.cpp \ - entitydata.cpp \ - libtextedit.cpp + libtextedit.cpp \ + text_modelx.cpp \ + text_present.cpp HEADERS += \ - blockdatas.h \ - entitydata.h \ - libTextEdit_global.h \ - libtextedit.h + libtextedit.h \ + libtextedit_global.h \ + text_modelx.h \ + text_present.h msvc { QMAKE_CFLAGS += /utf-8 @@ -33,3 +33,10 @@ unix { DISTFILES += \ README.md + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../libConfig/release/ -llibConfig +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../libConfig/debug/ -llibConfig +else:unix: LIBS += -L$$OUT_PWD/../libConfig/ -llibConfig + +INCLUDEPATH += $$PWD/../libConfig +DEPENDPATH += $$PWD/../libConfig diff --git a/libTextEdit/libtextedit.h b/libTextEdit/libtextedit.h index dbe672d..4b0cffb 100644 --- a/libTextEdit/libtextedit.h +++ b/libTextEdit/libtextedit.h @@ -1,7 +1,7 @@ #ifndef LIBTEXTEDIT_H #define LIBTEXTEDIT_H -#include "libTextEdit_global.h" +#include "libtextedit_global.h" class LIBTEXTEDIT_EXPORT LibTextEdit { diff --git a/libTextEdit/libTextEdit_global.h b/libTextEdit/libtextedit_global.h similarity index 100% rename from libTextEdit/libTextEdit_global.h rename to libTextEdit/libtextedit_global.h diff --git a/libTextEdit/text_modelx.cpp b/libTextEdit/text_modelx.cpp new file mode 100644 index 0000000..6de1c42 --- /dev/null +++ b/libTextEdit/text_modelx.cpp @@ -0,0 +1 @@ +#include "text_model.h" diff --git a/libTextEdit/text_modelx.h b/libTextEdit/text_modelx.h new file mode 100644 index 0000000..ad365ba --- /dev/null +++ b/libTextEdit/text_modelx.h @@ -0,0 +1,11 @@ +#ifndef TEXT_MODELX_H +#define TEXT_MODELX_H + +#include "text_present.h" + +namespace text_model +{ + // 涓枃鍐呭 +} + +#endif // TEXT_MODELX_H diff --git a/libTextEdit/text_present.cpp b/libTextEdit/text_present.cpp new file mode 100644 index 0000000..99586ba --- /dev/null +++ b/libTextEdit/text_present.cpp @@ -0,0 +1,314 @@ +#include "text_present.h" +#include + +using namespace std; +using namespace model_text; + +CharStream CharSetU16::combineToU(const QString &buffer) { + QList retvs; + + if (buffer.size() == 0) + return retvs; + + tuple combine_current; + auto aval = buffer[0]; + if (buffer.size() < 2) + combine_current = std::make_tuple(aval.unicode(), 1); + + else if (buffer.size() >= 2) { + auto bval = buffer[1]; + if (aval.isHighSurrogate() && bval.isLowSurrogate()) { + uint32_t avalx = aval.unicode(); + combine_current = std::make_tuple((avalx << 16) + bval.unicode(), 2); + } else { + combine_current = std::make_tuple(aval.unicode(), 1); + } + } + + retvs.append(std::get<0>(combine_current)); + retvs.append(combineToU(buffer.mid(std::get<1>(combine_current)))); + return retvs; +} + +QString CharSetU16::splitToC(const CharStream &buffer) { + if (!buffer.size()) + return ""; + + QString acc_str = ""; + auto head = buffer[0]; + if (head > 0xffffu) { + auto high_v = (head & 0xffff0000u) >> 16; + auto low_v = head & 0xffffu; + + auto hc = QChar((ushort)high_v); + auto lc = QChar((ushort)low_v); + acc_str.append(hc); + acc_str.append(lc); + } else { + acc_str.append(QChar((ushort)head & 0xffffu)); + } + + acc_str.append(splitToC(buffer.mid(1))); + return acc_str; +} + +bool CharSetU16::contains(uint32_t code) { + if (code <= 0xffffu) + return true; + else { + auto high_v = (code & 0xffff0000u) >> 16; + auto low_v = code & 0xffffu; + + auto hc = QChar((ushort)high_v); + auto lc = QChar((ushort)low_v); + return hc.isHighSurrogate() && lc.isLowSurrogate(); + } +} + +uint CharSetU16::size() { return 1114111u; } + +void WsDocument::bindFormat(std::shared_ptr f) { this->document_format = f; } + +std::shared_ptr WsDocument::getFormat() const { return this->document_format; } + +uint32_t WsDocument::blockCount() const +{ + return this->block_store.size(); +} + +QList > WsDocument::getBlocks(uint32_t offset, uint32_t count) const +{ + QList> retvs; + + for (auto idx = offset; idx < this->block_store.size(); ++idx) + retvs << this->block_store.at(idx); + + return retvs; +} + +void WsDocument::delBlocks(uint32_t offset, uint32_t count) +{ + for(auto idx=offset; idxblock_store.size();){ + this->block_store.removeAt(idx); + } +} + +void WsDocument::addBlocks(const QList> &blks, uint32_t offset) +{ + if(offset < this->block_store.size()){ + for(auto ptr : blks) + this->block_store.insert(offset, ptr); + } + else{ + this->block_store.append(blks); + } +} + +QString WsDocument::toPlainText() const +{ + QString text_content; + for(auto idx=0; idxtoText(); + } + return text_content; +} + +void WsDocument::setPlainText(const QString &text) +{ + auto sections = text.split("\n"); + QList> blocks; + for(auto &t : sections){ + auto binst = std::make_shared(); + blocks.append(binst); + + // 转换文本为内存实例 + auto codes = CharSetU16::combineToU(t); + auto chars = WsChar::convertFrom(codes); + + // 填充段落实例 + QList buffers; + for(auto &ptr : chars){ + ptr->bindFormat(this->getFormat()->defaultCharFormat()); + ptr->refer(binst); + buffers.append(ptr); + } + binst->addElements(buffers); + } + + addBlocks(blocks); +} + +void WsBlock::addElements(const QList &text, uint32_t offset){ + if(offset < this->element_store.size()){ + for(auto *ptr : text) + this->element_store.insert(offset, ptr); + } + else{ + this->element_store.append(text); + } +} + +QList WsBlock::getElements(uint32_t offset, uint32_t count) const +{ + QList retvs; + + for (auto idx = offset; idx < this->element_store.size(); ++idx) + retvs << this->element_store.at(idx); + + return retvs; +} + +void WsBlock::delElements(uint32_t offset, uint32_t count) +{ + for(auto idx=offset; idxelement_store.size();){ + delete element_store.at(idx); + this->element_store.removeAt(idx); + } +} + +QString WsBlock::toText() const +{ + QString text_content; + for(auto &it : element_store) + text_content += it->toText(); + return text_content; +} + +DocFormat::DocFormat(){} + +DocFormat::DocFormat(const DocFormat &other){ + this->char_format = other.char_format; + this->line_height = other.line_height; + this-> indent_char_count = other.indent_char_count; + this-> margins_store = other.margins_store; + this-> visible_of_additional = other.visible_of_additional; +} + +double DocFormat::lineHeight() const { return line_height; } + +QMargins DocFormat::margins() const { return margins_store; } + +double DocFormat::indentChars() const { return indent_char_count; } + +bool DocFormat::additionalVisible() const { return visible_of_additional; } + +std::shared_ptr DocFormat::defaultCharFormat() const { return this->char_format; } + +void DocFormat::setLineHeight(double val) { this->line_height = val; } + +void DocFormat::setMargins(const QMargins &val) { this->margins_store = val; } + +void DocFormat::setIndentChars(double n) { this->indent_char_count = n; } + +void DocFormat::setAdditionalVisible(bool ste) { this->visible_of_additional = ste; } + +void DocFormat::setDefaultCharFormat(std::shared_ptr format) { this->char_format = format; } + +DocFormat &DocFormat::operator=(const DocFormat &other){ + this->char_format = other.char_format; + this->line_height = other.line_height; + this-> indent_char_count = other.indent_char_count; + this-> margins_store = other.margins_store; + this-> visible_of_additional = other.visible_of_additional; + return *this; +} + +CharFormat::CharFormat(qulonglong format_id){ + this->unique_id = format_id; +} + +CharFormat::CharFormat(const CharFormat &other){ + this->unique_id = other.unique_id; + + this->point_size = other.point_size; + this->fontfamily_store = other.fontfamily_store; + this->bold_store = other.bold_store; + this->italic_flag = other.italic_flag; + this->kerning_flag = other.kerning_flag; + this->overline_flag = other.overline_flag; + this->underline_flag = other.underline_flag; + this->float_Height = other.float_Height; + this->weight_store = other.weight_store; +} + +qulonglong CharFormat::formatID() const { return unique_id; } + +uint32_t CharFormat::pointSize() const { return point_size; } + +QString CharFormat::fontFamily() const { return fontfamily_store; } + +bool CharFormat::bold() const { return bold_store; } + +bool CharFormat::italic() const { return italic_flag; } + +bool CharFormat::kerning() const { return kerning_flag; } + +bool CharFormat::overline() const { return overline_flag; } + +bool CharFormat::underline() const { return underline_flag; } + +double CharFormat::floatHeight() const { return float_Height; } + +QFont::Weight CharFormat::weight() const { return weight_store; } + +void CharFormat::setPointSize(uint32_t val){this->point_size = val;} + +void CharFormat::setFontFamily(const QString &name){this->fontfamily_store = name;} + +void CharFormat::setBold(bool ste){this->bold_store = ste;} + +void CharFormat::setItalic(bool ste){this->italic_flag = ste;} + +void CharFormat::setKerning(bool ste){this->kerning_flag = ste;} + +void CharFormat::setOverline(bool ste){this->overline_flag = ste;} + +void CharFormat::setUnderline(bool ste){this->underline_flag = ste;} + +void CharFormat::setFloatHeight(double val){this->float_Height = val;} + +void CharFormat::setWeight(QFont::Weight val){this->weight_store = val;} + +bool CharFormat::operator==(const CharFormat &other){ + return this->point_size == other.point_size && + this->fontfamily_store == other.fontfamily_store && + this->bold_store == other.bold_store && + this->italic_flag == other.italic_flag && + this->kerning_flag == other.kerning_flag && + this->overline_flag == other.overline_flag && + this->underline_flag == other.underline_flag && + this->float_Height == other.float_Height && + this->weight_store == other.weight_store; +} + +CharFormat &CharFormat::operator=(const CharFormat &other) { + this->point_size = other.point_size; + this->fontfamily_store = other.fontfamily_store; + this->bold_store = other.bold_store; + this->italic_flag = other.italic_flag; + this->kerning_flag = other.kerning_flag; + this->overline_flag = other.overline_flag; + this->underline_flag = other.underline_flag; + this->float_Height = other.float_Height; + this->weight_store = other.weight_store; + + return *this; +} + +QList WsChar::convertFrom(const CharStream &codes) +{ + QList buffers; + for(auto &c : codes) + buffers << new WsChar(c); + return buffers; +} + +uint32_t WsChar::blockIndex() const +{ + return blockRefer()->blockIndex(); +} + +void WsPart::insertChars(const QList &text, uint32_t offset) +{ + +} diff --git a/libTextEdit/text_present.h b/libTextEdit/text_present.h new file mode 100644 index 0000000..9272383 --- /dev/null +++ b/libTextEdit/text_present.h @@ -0,0 +1,337 @@ +#ifndef TEXT_PRESENT_H +#define TEXT_PRESENT_H + +#include "libtextedit.h" +#include +#include +#include +#include + +namespace model_text { + typedef QList CharStream; + + /** + * @brief UTF-16瀛楃闆嗛殣鍠 */ + class LIBTEXTEDIT_EXPORT CharSetU16 { + public: + static CharStream combineToU(const QString &buffer); + static QString splitToC(const CharStream &buffer); + static bool contains(uint32_t code); + static uint size(); + }; + + /** + * @brief 璁剧疆鍗曚釜瀛楃鐨勬牸寮忥紝榛樿浠庡乏鍒板彸鎺掑竷 + */ + class LIBTEXTEDIT_EXPORT CharFormat { + private: + qulonglong unique_id; + + uint32_t point_size; + QString fontfamily_store; + bool bold_store; + bool italic_flag; + bool kerning_flag; + bool overline_flag; + bool underline_flag; + double float_Height; + QFont::Weight weight_store; + + public: + CharFormat(qulonglong format_id); + CharFormat(const CharFormat& other); + + qulonglong formatID() const; + + uint32_t pointSize() const; + QString fontFamily() const; + bool bold() const; + bool italic() const; + bool kerning() const; + bool overline() const; + bool underline() const; + double floatHeight() const; + QFont::Weight weight() const; + + void setPointSize(uint32_t val); + void setFontFamily(const QString &name); + void setBold(bool ste); + void setItalic(bool ste); + void setKerning(bool ste); + void setOverline(bool ste); + void setUnderline(bool ste); + void setFloatHeight(double val); + void setWeight(QFont::Weight val); + + bool operator==(const CharFormat &other); + CharFormat &operator=(const CharFormat &other); + }; + /** + * @brief 瀹氫箟鏂囨。鏍煎紡锛岄粯璁ゆ帓甯冧粠宸﹀埌鍙筹紝浠庝笂鍒颁笅 + */ + class LIBTEXTEDIT_EXPORT DocFormat { + private: + std::shared_ptr char_format; + double line_height = 20; + double indent_char_count = 2; + QMargins margins_store = QMargins(5,5,5,5); + bool visible_of_additional = false; + + public: + DocFormat(); + DocFormat(const DocFormat &other); + + double lineHeight() const; + QMargins margins() const; + double indentChars() const; + bool additionalVisible() const; + std::shared_ptr defaultCharFormat() const; + + void setLineHeight(double val); + void setMargins(const QMargins &val); + void setIndentChars(double n); + void setAdditionalVisible(bool ste); + void setDefaultCharFormat(std::shared_ptr format); + + DocFormat& operator=(const DocFormat &other); + }; + + class WsBlock; + /** + * @brief 琛屽唴鍏冪礌 + */ + class Element { + public: + enum class Type{ + Char, Set + }; + + virtual ~Element() = default; + + virtual void refer(std::weak_ptr ptr) = 0; + virtual std::weak_ptr blockRefer() const = 0; + + /** + * @brief 鑾峰彇鍏冪礌鎵€鍦ㄧ殑娈佃惤绱㈠紩 + * @return + */ + virtual uint32_t blockIndex() const = 0; + + /** + * @brief 鍏冪礌缁戝畾瀛楃鏍煎紡 + * @return + */ + virtual std::shared_ptr getFormat() const = 0; + /** + * @brief 缁戝畾瀛楃鏍煎紡 + * @param format + */ + virtual void bindFormat(std::shared_ptr format) = 0; + + /** + * @brief 鍏冪礌绫诲瀷 + * @return + */ + virtual Type type() const = 0; + /** + * @brief 鏂囨。灞傛鍐咃紝鍏ㄥ眬璧峰绱㈠紩 + * @return + */ + virtual uint32_t index() const = 0; + /** + * @brief 鑾峰彇鏂囨湰鍐呭琛ㄧず + * @return + */ + virtual QString toText() const = 0; + /** + * @brief 瀛愬厓绱犳暟閲 * @return + */ + virtual uint32_t childCount() const = 0; + }; + + + /** + * @brief 鍗曚釜瀛楃鍐呭瓨妯″瀷 + */ + class LIBTEXTEDIT_EXPORT WsChar : public Element { + private: + uint32_t code_store; + std::shared_ptr char_format_refer; + + public: + explicit WsChar(uint32_t code){this->code_store = code;} + virtual ~WsChar() = default; + + uint32_t code() const { return code_store; } + + static QList convertFrom(const CharStream &codes); + + // Element interface + public: + virtual std::shared_ptr getFormat() const override { return this->char_format_refer; } + virtual void bindFormat(std::shared_ptr format) override{this->char_format_refer = format;} + virtual Type type() const override { return Type::Char; } + virtual uint32_t blockIndex() const override; + virtual uint32_t index() const override; + virtual QString toText() const override { return CharSetU16::splitToC(QList() << code_store); } + virtual uint32_t childCount() const override { return 0; } + virtual void refer(std::weak_ptr ptr) override; + virtual std::weak_ptr blockRefer() const override; + }; + + + /** + * @brief 鏂囧瓧鐗囨鍐呭瓨妯″瀷 + */ + class LIBTEXTEDIT_EXPORT WsPart : public Element { + public: + /** + * @brief 鎻掑叆鏂囨湰鐗囨 + * @param text 鏂囨湰鍐呭 + * @param index + */ + void insertChars(const QList &text, uint32_t offset = -1); + /** + * @brief 鑾峰彇鏂囨湰鐗囨鍐呭 + * @param offset 璧峰绱㈠紩 + * @param count 鏁伴噺 + * @return + */ + QList getChars(uint32_t offset, uint32_t count) const; + /** + * @brief 鍒犻櫎鏂囨湰鐗囨鍐呭 + * @param offset + * @param count + */ + void delChars(uint32_t offset, uint32_t count); + }; + + /** + * @brief 鏂囨。鍧楋紙娈佃惤锛夊厓绱犲唴瀛樺疄渚 */ + class LIBTEXTEDIT_EXPORT WsBlock { + private: + QList element_store; + + public: + uint32_t blockIndex() const; + /** + * @brief 鎻掑叆鍏冪礌闆嗗悎 + * @param text 鏂囨湰鍐呭 + * @param index + */ + void addElements(const QList &text, uint32_t offset = UINT32_MAX); + /** + * @brief 鑾峰彇鏂囨湰鐗囨鍐呭 + * @param offset + * @param count + * @return + */ + QList getElements(uint32_t offset, uint32_t count) const; + /** + * @brief 鍒犻櫎鏂囨湰鐗囨鍐呭 + * @param offset + * @param count + */ + void delElements(uint32_t offset, uint32_t count); + /** + * @brief 鑾峰彇娈佃惤鐨勬枃鏈〃绀 * @return + */ + QString toText() const; + }; + + /** + * @brief 鏂囨。鍐呭瓨瀹炰緥 + */ + class LIBTEXTEDIT_EXPORT WsDocument : public QObject { + Q_OBJECT + private: + std::shared_ptr document_format; + QList> block_store; + + public: + /** + * @brief 缁戝畾鏂囨。鏍煎紡 + * @param f + */ + void bindFormat(std::shared_ptr f); + /** + * @brief 鑾峰彇鏂囨。鏍煎紡 + * @return + */ + std::shared_ptr getFormat() const; + + // 鍐呭瓨鏂囨。缁撴瀯鎺ュ彛 =================================================== + /** + * @brief 鎻掑叆娈佃惤 + * @param blks + * @param offset + */ + void addBlocks(const QList> &blks, uint32_t offset = UINT32_MAX); + /** + * @brief 娈佃惤鏁伴噺 + * @return + */ + uint32_t blockCount() const; + /** + * @brief 鑾峰彇娈佃惤寮曠敤 + * @param offset + * @param count + * @return + */ + QList> getBlocks(uint32_t offset, uint32_t count = 1) const; + /** + * @brief 鍒犻櫎鎸囧畾鑼冨洿鍐呯殑娈佃惤 + * @param offset 璧峰绱㈠紩 + * @param count 娈佃惤鏁伴噺 + */ + void delBlocks(uint32_t offset, uint32_t count = 1); + + // // 鍐呭瓨鏂囨湰鎿嶄綔鎺ュ彛 =================================================== + // /** + // * @brief 鎸囧畾浣嶇疆鎻掑叆鏂囨湰 + // * @param part 鏂囨湰鐗囨 + // * @param index 璧峰绱㈠紩锛宨ndex<0琛ㄧず杩藉姞 + // */ + // void insertText(QList part, uint32_t index = -1); + // /** + // * @brief 鑾峰彇鎸囧畾浣嶇疆鐨勬枃鏈 // * @param index 璧峰绱㈠紩 + // * @param count 鏂囨湰鏁伴噺 + // * @return + // */ + // QList getText(uint32_t index, uint32_t count); + // /** + // * @brief 鍒犻櫎鎸囧畾浣嶇疆鐨勬枃鏈 // * @param index 璧峰绱㈠紩锛岃秴鍑烘湁鏁堣寖鍥存墽琛屾棤鏁堟灉 + // * @param count 鍒犻櫎鏁伴噺 + // */ + // void delText(uint32_t index, uint32_t count); + + // // 閫夋嫨鎿嶄綔鎺ュ彛 ====================================================== + // void select(uint32_t index, uint32_t count); + + // 鍐呭瓨鏂囨湰瀛樺彇鎺ュ彛 =================================================== + QString toPlainText() const; + void setPlainText(const QString &text); + + // signals: + // void blockHasbeenInserted(uint32_t index); + // /** + // * @brief 鐗囨灏嗚琚垹闄 // * @param index + // */ + // void blockAboutTobeDelete(uint32_t index); + // /** + // * @brief 鐗囨宸茬粡琚慨鏀 // * @param index + // */ + // void blockHasbeenChanged(uint32_t index); + + // void redoAvaliable(); + // void undoAvaliable(); + // /** + // * @brief 鍏夋爣浣嶇疆宸茬粡鍙樺寲 + // * @param index 鍏夋爣浣嶇疆 + // */ + // void cursorPosChanged(uint32_t index); + // void selectionChanged(uint32_t index, uint32_t count); + }; +} + +#endif // TEXT_PRESENT_H