mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
Add insert table toolbar button
This commit is contained in:
parent
70caa4d932
commit
70374607bb
95
src/dialog/vinserttabledialog.cpp
Normal file
95
src/dialog/vinserttabledialog.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
#include "vinserttabledialog.h"
|
||||
|
||||
#include <QSpinBox>
|
||||
#include <QRadioButton>
|
||||
#include <QGridLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include <QButtonGroup>
|
||||
|
||||
VInsertTableDialog::VInsertTableDialog(QWidget *p_parent)
|
||||
: QDialog(p_parent),
|
||||
m_alignment(VTable::None)
|
||||
{
|
||||
setupUI();
|
||||
}
|
||||
|
||||
void VInsertTableDialog::setupUI()
|
||||
{
|
||||
m_rowCount = new QSpinBox(this);
|
||||
m_rowCount->setToolTip(tr("Number of rows of the table body"));
|
||||
m_rowCount->setMaximum(1000);
|
||||
m_rowCount->setMinimum(0);
|
||||
|
||||
m_colCount = new QSpinBox(this);
|
||||
m_colCount->setToolTip(tr("Number of columns of the table"));
|
||||
m_colCount->setMaximum(1000);
|
||||
m_colCount->setMinimum(1);
|
||||
|
||||
QRadioButton *noneBtn = new QRadioButton(tr("None"), this);
|
||||
QRadioButton *leftBtn = new QRadioButton(tr("Left"), this);
|
||||
QRadioButton *centerBtn = new QRadioButton(tr("Center"), this);
|
||||
QRadioButton *rightBtn = new QRadioButton(tr("Right"), this);
|
||||
QHBoxLayout *alignLayout = new QHBoxLayout();
|
||||
alignLayout->addWidget(noneBtn);
|
||||
alignLayout->addWidget(leftBtn);
|
||||
alignLayout->addWidget(centerBtn);
|
||||
alignLayout->addWidget(rightBtn);
|
||||
alignLayout->addStretch();
|
||||
|
||||
noneBtn->setChecked(true);
|
||||
|
||||
QButtonGroup *bg = new QButtonGroup(this);
|
||||
bg->addButton(noneBtn, VTable::None);
|
||||
bg->addButton(leftBtn, VTable::Left);
|
||||
bg->addButton(centerBtn, VTable::Center);
|
||||
bg->addButton(rightBtn, VTable::Right);
|
||||
connect(bg, static_cast<void(QButtonGroup::*)(int, bool)>(&QButtonGroup::buttonToggled),
|
||||
this, [this](int p_id, bool p_checked){
|
||||
if (p_checked) {
|
||||
m_alignment = static_cast<VTable::Alignment>(p_id);
|
||||
}
|
||||
});
|
||||
|
||||
QGridLayout *topLayout = new QGridLayout();
|
||||
topLayout->addWidget(new QLabel(tr("Row:")), 0, 0, 1, 1);
|
||||
topLayout->addWidget(m_rowCount, 0, 1, 1, 1);
|
||||
topLayout->addWidget(new QLabel(tr("Column:")), 0, 2, 1, 1);
|
||||
topLayout->addWidget(m_colCount, 0, 3, 1, 1);
|
||||
|
||||
topLayout->addWidget(new QLabel(tr("Alignment:")), 1, 0, 1, 1);
|
||||
topLayout->addLayout(alignLayout, 1, 1, 1, 3);
|
||||
|
||||
// Ok is the default button.
|
||||
m_btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(m_btnBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(m_btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok);
|
||||
okBtn->setProperty("SpecialBtn", true);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout();
|
||||
mainLayout->addLayout(topLayout);
|
||||
mainLayout->addWidget(m_btnBox);
|
||||
|
||||
setLayout(mainLayout);
|
||||
setWindowTitle(tr("Insert Table"));
|
||||
}
|
||||
|
||||
int VInsertTableDialog::getRowCount() const
|
||||
{
|
||||
return m_rowCount->value();
|
||||
}
|
||||
|
||||
int VInsertTableDialog::getColumnCount() const
|
||||
{
|
||||
return m_colCount->value();
|
||||
}
|
||||
|
||||
VTable::Alignment VInsertTableDialog::getAlignment() const
|
||||
{
|
||||
return m_alignment;
|
||||
}
|
32
src/dialog/vinserttabledialog.h
Normal file
32
src/dialog/vinserttabledialog.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef VINSERTTABLEDIALOG_H
|
||||
#define VINSERTTABLEDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "../vtable.h"
|
||||
|
||||
class QDialogButtonBox;
|
||||
class QSpinBox;
|
||||
|
||||
class VInsertTableDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VInsertTableDialog(QWidget *p_parent = nullptr);
|
||||
|
||||
int getRowCount() const;
|
||||
int getColumnCount() const;
|
||||
VTable::Alignment getAlignment() const;
|
||||
|
||||
private:
|
||||
void setupUI();
|
||||
|
||||
QSpinBox *m_rowCount;
|
||||
QSpinBox *m_colCount;
|
||||
|
||||
QDialogButtonBox *m_btnBox;
|
||||
|
||||
VTable::Alignment m_alignment;
|
||||
};
|
||||
|
||||
#endif // VINSERTTABLEDIALOG_H
|
@ -96,6 +96,8 @@ Insert inline code. Press `Ctrl+;` again to exit. Current selected text will be
|
||||
Insert fenced code block. Press `Ctrl+M` again to exit. Current selected text will be wrapped into a code block if exists.
|
||||
- `Ctrl+L`
|
||||
Insert link.
|
||||
- `Ctrl+.`
|
||||
Insert table.
|
||||
- `Ctrl+'`
|
||||
Insert image.
|
||||
- `Ctrl+H`
|
||||
|
@ -96,6 +96,8 @@
|
||||
插入代码块;再次按`Ctrl+M`退出。如果已经选择文本,则将当前选择文本嵌入到代码块中。
|
||||
- `Ctrl+L`
|
||||
插入链接。
|
||||
- `Ctrl+.`
|
||||
插入表格。
|
||||
- `Ctrl+'`
|
||||
插入图片。
|
||||
- `Ctrl+H`
|
||||
|
9
src/resources/icons/table.svg
Normal file
9
src/resources/icons/table.svg
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
|
||||
<path style="fill:#000000" d="M409.6,64H102.4C81.3,64,64,81.3,64,102.4v307.2c0,21.1,17.3,38.4,38.4,38.4h307.2c21.1,0,38.4-17.3,38.4-38.4V102.4
|
||||
C448,81.3,430.7,64,409.6,64z M179.2,409.6h-76.8v-76.8h76.8V409.6z M179.2,294.4h-76.8v-76.8h76.8V294.4z M179.2,179.2h-76.8v-76.8
|
||||
h76.8V179.2z M294.4,409.6h-76.8v-76.8h76.8V409.6z M294.4,294.4h-76.8v-76.8h76.8V294.4z M294.4,179.2h-76.8v-76.8h76.8V179.2z
|
||||
M409.6,409.6h-76.8v-76.8h76.8V409.6z M409.6,294.4h-76.8v-76.8h76.8V294.4z M409.6,179.2h-76.8v-76.8h76.8V179.2z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 862 B |
@ -159,7 +159,8 @@ SOURCES += main.cpp\
|
||||
vfilelistwidget.cpp \
|
||||
widgets/vcombobox.cpp \
|
||||
vtablehelper.cpp \
|
||||
vtable.cpp
|
||||
vtable.cpp \
|
||||
dialog/vinserttabledialog.cpp
|
||||
|
||||
HEADERS += vmainwindow.h \
|
||||
vdirectorytree.h \
|
||||
@ -304,7 +305,8 @@ HEADERS += vmainwindow.h \
|
||||
vfilelistwidget.h \
|
||||
widgets/vcombobox.h \
|
||||
vtablehelper.h \
|
||||
vtable.h
|
||||
vtable.h \
|
||||
dialog/vinserttabledialog.h
|
||||
|
||||
RESOURCES += \
|
||||
vnote.qrc \
|
||||
|
@ -419,7 +419,7 @@ void VDirectoryTree::contextMenuRequested(QPoint pos)
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
QAction *reloadAct = new QAction(tr("&Reload From Disk"), &menu);
|
||||
QAction *reloadAct = new QAction(tr("Reload From Disk"), &menu);
|
||||
reloadAct->setToolTip(tr("Reload the content of this folder (or notebook) from disk"));
|
||||
connect(reloadAct, &QAction::triggered,
|
||||
this, &VDirectoryTree::reloadFromDisk);
|
||||
|
@ -72,6 +72,9 @@ public:
|
||||
// User requests to insert a link.
|
||||
void insertLink();
|
||||
|
||||
// User requests to insert a table.
|
||||
virtual void insertTable() = 0;
|
||||
|
||||
// Used for incremental search.
|
||||
// User has enter the content to search, but does not enter the "find" button yet.
|
||||
bool peekText(const QString &p_text, uint p_options, bool p_forward = true);
|
||||
|
@ -136,6 +136,10 @@ void VEditTab::insertLink()
|
||||
{
|
||||
}
|
||||
|
||||
void VEditTab::insertTable()
|
||||
{
|
||||
}
|
||||
|
||||
void VEditTab::applySnippet(const VSnippet *p_snippet)
|
||||
{
|
||||
Q_UNUSED(p_snippet);
|
||||
|
@ -56,6 +56,9 @@ public:
|
||||
// User requests to insert link.
|
||||
virtual void insertLink();
|
||||
|
||||
// User requests to table.
|
||||
virtual void insertTable();
|
||||
|
||||
// Search @p_text in current note.
|
||||
virtual void findText(const QString &p_text, uint p_options, bool p_peek,
|
||||
bool p_forward = true) = 0;
|
||||
|
@ -573,6 +573,19 @@ QToolBar *VMainWindow::initEditToolBar(QSize p_iconSize)
|
||||
|
||||
m_editToolBar->addAction(codeBlockAct);
|
||||
|
||||
QAction *tableAct = new QAction(VIconUtils::toolButtonIcon(":/resources/icons/table.svg"),
|
||||
tr("Table\t%1").arg(VUtils::getShortcutText("Ctrl+.")),
|
||||
this);
|
||||
tableAct->setStatusTip(tr("Insert a table"));
|
||||
connect(tableAct, &QAction::triggered,
|
||||
this, [this](){
|
||||
if (m_curTab) {
|
||||
m_curTab->insertTable();
|
||||
}
|
||||
});
|
||||
|
||||
m_editToolBar->addAction(tableAct);
|
||||
|
||||
// Insert link.
|
||||
QAction *insetLinkAct = new QAction(VIconUtils::toolButtonIcon(":/resources/icons/link.svg"),
|
||||
tr("Insert Link\t%1").arg(VUtils::getShortcutText("Ctrl+L")),
|
||||
|
@ -543,6 +543,17 @@ bool VMdEditOperations::handleKeyPressEvent(QKeyEvent *p_event)
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::Key_Period:
|
||||
{
|
||||
if (modifiers == Qt::ControlModifier) {
|
||||
m_editor->insertTable();
|
||||
p_event->accept();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "vmdtab.h"
|
||||
#include "vdownloader.h"
|
||||
#include "vtablehelper.h"
|
||||
#include "dialog/vinserttabledialog.h"
|
||||
|
||||
extern VWebUtils *g_webUtils;
|
||||
|
||||
@ -2211,3 +2212,40 @@ void VMdEditor::handleLinkToAttachmentAction(QAction *p_act)
|
||||
m_editOps->insertLink(linkText, linkUrl);
|
||||
}
|
||||
}
|
||||
|
||||
void VMdEditor::insertTable()
|
||||
{
|
||||
// Get the dialog info.
|
||||
VInsertTableDialog td(this);
|
||||
if (td.exec() != QDialog::Accepted) {
|
||||
return;
|
||||
}
|
||||
|
||||
int rowCount = td.getRowCount();
|
||||
int colCount = td.getColumnCount();
|
||||
VTable::Alignment alignment = td.getAlignment();
|
||||
|
||||
QTextCursor cursor = textCursorW();
|
||||
if (cursor.hasSelection()) {
|
||||
cursor.clearSelection();
|
||||
setTextCursorW(cursor);
|
||||
}
|
||||
|
||||
bool newBlock = !cursor.atBlockEnd();
|
||||
if (!newBlock && !cursor.atBlockStart()) {
|
||||
QString text = cursor.block().text().trimmed();
|
||||
if (!text.isEmpty() && text != ">") {
|
||||
// Insert a new block before inserting table.
|
||||
newBlock = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (newBlock) {
|
||||
VEditUtils::insertBlock(cursor, false);
|
||||
VEditUtils::indentBlockAsBlock(cursor, false);
|
||||
setTextCursorW(cursor);
|
||||
}
|
||||
|
||||
// Insert table right at cursor.
|
||||
m_tableHelper->insertTable(rowCount, colCount, alignment);
|
||||
}
|
||||
|
@ -84,6 +84,8 @@ public:
|
||||
|
||||
void updateFontAndPalette() Q_DECL_OVERRIDE;
|
||||
|
||||
void insertTable() Q_DECL_OVERRIDE;
|
||||
|
||||
public slots:
|
||||
bool jumpTitle(bool p_forward, int p_relativeLevel, int p_repeat) Q_DECL_OVERRIDE;
|
||||
|
||||
|
@ -696,6 +696,16 @@ void VMdTab::insertLink()
|
||||
m_editor->insertLink();
|
||||
}
|
||||
|
||||
void VMdTab::insertTable()
|
||||
{
|
||||
if (!m_isEditMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
Q_ASSERT(m_editor);
|
||||
m_editor->insertTable();
|
||||
}
|
||||
|
||||
void VMdTab::findText(const QString &p_text, uint p_options, bool p_peek,
|
||||
bool p_forward)
|
||||
{
|
||||
|
@ -44,6 +44,8 @@ public:
|
||||
|
||||
void insertImage() Q_DECL_OVERRIDE;
|
||||
|
||||
void insertTable() Q_DECL_OVERRIDE;
|
||||
|
||||
void insertLink() Q_DECL_OVERRIDE;
|
||||
|
||||
// Search @p_text in current note.
|
||||
|
@ -277,5 +277,6 @@
|
||||
<file>resources/docs/welcome_zh.md</file>
|
||||
<file>resources/icons/256x256/vnote.png</file>
|
||||
<file>utils/markdown-it/markdown-it-container.min.js</file>
|
||||
<file>resources/icons/table.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
131
src/vtable.cpp
131
src/vtable.cpp
@ -7,14 +7,73 @@
|
||||
|
||||
const QString VTable::c_defaultDelimiter = "---";
|
||||
|
||||
const QChar VTable::c_borderChar = '|';
|
||||
|
||||
enum { HeaderRowIndex = 0, DelimiterRowIndex = 1 };
|
||||
|
||||
VTable::VTable(VEditor *p_editor, const VTableBlock &p_block)
|
||||
: m_editor(p_editor)
|
||||
: m_editor(p_editor),
|
||||
m_exist(true),
|
||||
m_spaceWidth(10),
|
||||
m_minusWidth(10),
|
||||
m_colonWidth(10),
|
||||
m_defaultDelimiterWidth(10)
|
||||
{
|
||||
parseFromTableBlock(p_block);
|
||||
}
|
||||
|
||||
VTable::VTable(VEditor *p_editor, int p_nrBodyRow, int p_nrCol, VTable::Alignment p_alignment)
|
||||
: m_editor(p_editor),
|
||||
m_exist(false),
|
||||
m_spaceWidth(10),
|
||||
m_minusWidth(10),
|
||||
m_colonWidth(10),
|
||||
m_defaultDelimiterWidth(10)
|
||||
{
|
||||
Q_ASSERT(p_nrBodyRow >= 0 && p_nrCol > 0);
|
||||
m_rows.resize(p_nrBodyRow + 2);
|
||||
|
||||
// PreText for each row.
|
||||
QString preText;
|
||||
QTextCursor cursor = m_editor->textCursorW();
|
||||
Q_ASSERT(cursor.atBlockEnd());
|
||||
if (!cursor.atBlockStart()) {
|
||||
preText = cursor.block().text();
|
||||
}
|
||||
|
||||
QString core(c_defaultDelimiter);
|
||||
switch (p_alignment) {
|
||||
case Alignment::Left:
|
||||
core[0] = ':';
|
||||
break;
|
||||
|
||||
case Alignment::Center:
|
||||
core[0] = ':';
|
||||
core[core.size() - 1] = ':';
|
||||
break;
|
||||
|
||||
case Alignment::Right:
|
||||
core[core.size() - 1] = ':';
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const QString delimiterCell = generateFormattedText(core, 0);
|
||||
const QString contentCell = generateFormattedText(QString(c_defaultDelimiter.size(), ' '), 0);
|
||||
|
||||
for (int rowIdx = 0; rowIdx < m_rows.size(); ++rowIdx) {
|
||||
auto & row = m_rows[rowIdx];
|
||||
row.m_preText = preText;
|
||||
row.m_cells.resize(p_nrCol);
|
||||
|
||||
const QString &content = isDelimiterRow(rowIdx) ? delimiterCell : contentCell;
|
||||
for (auto & cell : row.m_cells) {
|
||||
cell.m_text = content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool VTable::isValid() const
|
||||
{
|
||||
return header() && header()->isValid()
|
||||
@ -82,6 +141,13 @@ bool VTable::parseOneRow(const QTextBlock &p_block,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get pre text.
|
||||
int firstCellOffset = p_borders[p_borderIdx] - startPos;
|
||||
if (text[firstCellOffset] != c_borderChar) {
|
||||
return false;
|
||||
}
|
||||
p_row.m_preText = text.left(firstCellOffset);
|
||||
|
||||
for (; p_borderIdx < p_borders.size(); ++p_borderIdx) {
|
||||
int border = p_borders[p_borderIdx];
|
||||
if (border >= endPos) {
|
||||
@ -89,7 +155,7 @@ bool VTable::parseOneRow(const QTextBlock &p_block,
|
||||
}
|
||||
|
||||
int offset = border - startPos;
|
||||
if (text[offset] != '|') {
|
||||
if (text[offset] != c_borderChar) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -101,7 +167,7 @@ bool VTable::parseOneRow(const QTextBlock &p_block,
|
||||
}
|
||||
|
||||
int nextOffset = p_borders[nextIdx] - startPos;
|
||||
if (text[nextOffset] != '|') {
|
||||
if (text[nextOffset] != c_borderChar) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -186,7 +252,7 @@ void VTable::formatOneColumn(int p_idx, int p_cursorRowIdx, int p_cursorPib)
|
||||
fetchCellInfoOfColumn(p_idx, cells, targetWidth);
|
||||
|
||||
// Get the alignment of this column.
|
||||
const VTable::Alignment align = getColumnAlignment(p_idx);
|
||||
const Alignment align = getColumnAlignment(p_idx);
|
||||
|
||||
// Calculate the formatted text of each cell.
|
||||
for (int rowIdx = 0; rowIdx < cells.size(); ++rowIdx) {
|
||||
@ -246,10 +312,7 @@ void VTable::formatOneColumn(int p_idx, int p_cursorRowIdx, int p_cursorPib)
|
||||
break;
|
||||
}
|
||||
|
||||
Alignment fakeAlign = align == Alignment::None ? Alignment::Left : align;
|
||||
cell.m_formattedText = generateFormattedText(core,
|
||||
0,
|
||||
fakeAlign);
|
||||
cell.m_formattedText = generateFormattedText(core, 0);
|
||||
}
|
||||
} else {
|
||||
Alignment fakeAlign = align;
|
||||
@ -385,7 +448,8 @@ QString VTable::generateFormattedText(const QString &p_core,
|
||||
rightSpaces = 0;
|
||||
}
|
||||
|
||||
return QString("| %1%2%3 ").arg(QString(leftSpaces, ' '))
|
||||
return QString("%1 %2%3%4 ").arg(c_borderChar)
|
||||
.arg(QString(leftSpaces, ' '))
|
||||
.arg(p_core)
|
||||
.arg(QString(rightSpaces, ' '));
|
||||
}
|
||||
@ -450,7 +514,7 @@ bool VTable::isCellWellFormatted(const Row &p_row,
|
||||
const Cell &p_cell,
|
||||
const CellInfo &p_info,
|
||||
int p_targetWidth,
|
||||
VTable::Alignment p_align) const
|
||||
Alignment p_align) const
|
||||
{
|
||||
Q_ASSERT(p_align != Alignment::None);
|
||||
|
||||
@ -507,6 +571,15 @@ bool VTable::isCellWellFormatted(const Row &p_row,
|
||||
}
|
||||
|
||||
void VTable::write()
|
||||
{
|
||||
if (m_exist) {
|
||||
writeExist();
|
||||
} else {
|
||||
writeNonExist();
|
||||
}
|
||||
}
|
||||
|
||||
void VTable::writeExist()
|
||||
{
|
||||
bool changed = false;
|
||||
QTextCursor cursor = m_editor->textCursorW();
|
||||
@ -535,14 +608,7 @@ void VTable::write()
|
||||
}
|
||||
|
||||
// Construct the block text.
|
||||
QString newBlockText;
|
||||
int firstOffset = row.m_cells.first().m_offset;
|
||||
if (firstOffset > 0) {
|
||||
// Get the prefix text.
|
||||
QString text = row.m_block.text();
|
||||
newBlockText = text.left(firstOffset);
|
||||
}
|
||||
|
||||
QString newBlockText(row.m_preText);
|
||||
for (auto & cell : row.m_cells) {
|
||||
int pos = newBlockText.size();
|
||||
if (cell.m_formattedText.isEmpty()) {
|
||||
@ -560,7 +626,7 @@ void VTable::write()
|
||||
}
|
||||
}
|
||||
|
||||
newBlockText += "|";
|
||||
newBlockText += c_borderChar;
|
||||
|
||||
// Replace the whole block.
|
||||
cursor.setPosition(row.m_block.position());
|
||||
@ -583,3 +649,30 @@ void VTable::write()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VTable::writeNonExist()
|
||||
{
|
||||
// Generate the text of the whole table.
|
||||
QString tableText;
|
||||
for (int rowIdx = 0; rowIdx < m_rows.size(); ++rowIdx) {
|
||||
const auto & row = m_rows[rowIdx];
|
||||
tableText += row.m_preText;
|
||||
for (auto & cell : row.m_cells) {
|
||||
tableText += cell.m_text;
|
||||
}
|
||||
|
||||
tableText += c_borderChar;
|
||||
|
||||
if (rowIdx < m_rows.size() - 1) {
|
||||
tableText += '\n';
|
||||
}
|
||||
}
|
||||
|
||||
QTextCursor cursor = m_editor->textCursorW();
|
||||
int pos = cursor.position() + 2;
|
||||
cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
|
||||
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
|
||||
cursor.insertText(tableText);
|
||||
cursor.setPosition(pos);
|
||||
m_editor->setTextCursorW(cursor);
|
||||
}
|
||||
|
61
src/vtable.h
61
src/vtable.h
@ -10,6 +10,25 @@ class VEditor;
|
||||
class VTable
|
||||
{
|
||||
public:
|
||||
enum Alignment {
|
||||
None,
|
||||
Left,
|
||||
Center,
|
||||
Right
|
||||
};
|
||||
|
||||
VTable(VEditor *p_editor, const VTableBlock &p_block);
|
||||
|
||||
VTable(VEditor *p_editor, int p_nrBodyRow, int p_nrCol, VTable::Alignment p_alignment);
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
void format();
|
||||
|
||||
// Write a formatted table.
|
||||
void write();
|
||||
|
||||
private:
|
||||
struct Cell
|
||||
{
|
||||
Cell()
|
||||
@ -53,12 +72,13 @@ public:
|
||||
|
||||
bool isValid() const
|
||||
{
|
||||
return m_block.isValid();
|
||||
return !m_cells.isEmpty();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_block = QTextBlock();
|
||||
m_preText.clear();
|
||||
m_cells.clear();
|
||||
}
|
||||
|
||||
@ -75,31 +95,11 @@ public:
|
||||
}
|
||||
|
||||
QTextBlock m_block;
|
||||
// Text before table row.
|
||||
QString m_preText;
|
||||
QVector<Cell> m_cells;
|
||||
};
|
||||
|
||||
enum Alignment
|
||||
{
|
||||
None,
|
||||
Left,
|
||||
Center,
|
||||
Right
|
||||
};
|
||||
|
||||
VTable(VEditor *p_editor, const VTableBlock &p_block);
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
void format();
|
||||
|
||||
// Write a formatted table.
|
||||
void write();
|
||||
|
||||
VTable::Row *header() const;
|
||||
|
||||
VTable::Row *delimiter() const;
|
||||
|
||||
private:
|
||||
// Used to hold info about a cell when formatting a column.
|
||||
struct CellInfo
|
||||
{
|
||||
@ -163,10 +163,21 @@ private:
|
||||
const Cell &p_cell,
|
||||
const CellInfo &p_info,
|
||||
int p_targetWidth,
|
||||
VTable::Alignment p_align) const;
|
||||
Alignment p_align) const;
|
||||
|
||||
void writeExist();
|
||||
|
||||
void writeNonExist();
|
||||
|
||||
VTable::Row *header() const;
|
||||
|
||||
VTable::Row *delimiter() const;
|
||||
|
||||
VEditor *m_editor;
|
||||
|
||||
// Whether this table exist already.
|
||||
bool m_exist;
|
||||
|
||||
// Header, delimiter, and body.
|
||||
QVector<Row> m_rows;
|
||||
|
||||
@ -176,6 +187,8 @@ private:
|
||||
int m_defaultDelimiterWidth;
|
||||
|
||||
static const QString c_defaultDelimiter;
|
||||
|
||||
static const QChar c_borderChar;
|
||||
};
|
||||
|
||||
#endif // VTABLE_H
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "vtablehelper.h"
|
||||
|
||||
#include "veditor.h"
|
||||
#include "vtable.h"
|
||||
|
||||
VTableHelper::VTableHelper(VEditor *p_editor, QObject *p_parent)
|
||||
: QObject(p_parent),
|
||||
@ -52,3 +51,13 @@ int VTableHelper::currentCursorTableBlock(const QVector<VTableBlock> &p_blocks)
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void VTableHelper::insertTable(int p_nrRow, int p_nrCol, VTable::Alignment p_alignment)
|
||||
{
|
||||
VTable table(m_editor, p_nrRow, p_nrCol, p_alignment);
|
||||
if (!table.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
table.write();
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <QObject>
|
||||
|
||||
#include "markdownhighlighterdata.h"
|
||||
#include "vtable.h"
|
||||
|
||||
class VEditor;
|
||||
|
||||
@ -13,6 +14,9 @@ class VTableHelper : public QObject
|
||||
public:
|
||||
explicit VTableHelper(VEditor *p_editor, QObject *p_parent = nullptr);
|
||||
|
||||
// Insert table right at current cursor.
|
||||
void insertTable(int p_nrRow, int p_nrCol, VTable::Alignment p_alignment);
|
||||
|
||||
public slots:
|
||||
void updateTableBlocks(const QVector<VTableBlock> &p_blocks);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user