Merge pull request #5099 from chennes/spreadsheetAutoReturn

[Spreadsheet] Refactor keyboard handling
This commit is contained in:
Chris Hennes
2021-10-12 11:01:10 -05:00
committed by GitHub
12 changed files with 394 additions and 182 deletions

View File

@@ -982,6 +982,14 @@ void PropertySheet::getSpans(CellAddress address, int & rows, int & cols) const
}
}
App::CellAddress Spreadsheet::PropertySheet::getAnchor(App::CellAddress address) const
{
if (auto anchor = mergedCells.find(address); anchor != mergedCells.end())
return anchor->second;
else
return address;
}
bool PropertySheet::isMergedCell(CellAddress address) const
{
return mergedCells.find(address) != mergedCells.end();

View File

@@ -148,6 +148,8 @@ public:
void getSpans(App::CellAddress address, int &rows, int &cols) const;
App::CellAddress getAnchor(App::CellAddress address) const;
bool isMergedCell(App::CellAddress address) const;
bool isHidden(App::CellAddress address) const;

View File

@@ -1063,6 +1063,11 @@ bool Sheet::isMergedCell(CellAddress address) const
return cells.isMergedCell(address);
}
App::CellAddress Spreadsheet::Sheet::getAnchor(App::CellAddress address) const
{
return cells.getAnchor(address);
}
/**
* @brief Set column with of column \a col to \a width-
* @param col Index of column.

View File

@@ -110,6 +110,8 @@ public:
bool isMergedCell(App::CellAddress address) const;
App::CellAddress getAnchor(App::CellAddress address) const;
void setColumnWidth(int col, int width);
int getColumnWidth(int col) const;

View File

@@ -26,68 +26,58 @@
# include <QKeyEvent>
#endif
#include <QCoreApplication>
#include "LineEdit.h"
using namespace SpreadsheetGui;
LineEdit::LineEdit(QWidget *parent)
: Gui::ExpressionLineEdit(parent, false, true)
, current()
, deltaCol(0)
, deltaRow(0)
, lastKeyPressed(0)
, lastModifiers(0)
{
setFocusPolicy(Qt::FocusPolicy::ClickFocus);
}
bool LineEdit::eventFilter(QObject* object, QEvent* event)
{
if (event && event->type() == QEvent::KeyPress) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Tab) {
// Special tab handling -- must be done via a QApplication event filter, otherwise the widget
// system will always grab the tab events
if (completerActive()) {
hideCompleter();
event->accept();
return true; // To make sure this tab press doesn't do anything else
}
else {
lastKeyPressed = keyEvent->key();
lastModifiers = keyEvent->modifiers();
}
}
}
return false; // We don't usually actually "handle" the tab event, we just keep track of it
}
bool LineEdit::event(QEvent *event)
{
if (event && event->type() == QEvent::KeyPress) {
if (event && event->type() == QEvent::FocusIn) {
qApp->installEventFilter(this);
}
else if (event && event->type() == QEvent::FocusOut) {
qApp->removeEventFilter(this);
if (lastKeyPressed)
Q_EMIT finishedWithKey(lastKeyPressed, lastModifiers);
lastKeyPressed = 0;
}
else if (event && event->type() == QEvent::KeyPress && !completerActive()) {
QKeyEvent * kevent = static_cast<QKeyEvent*>(event);
if (kevent->key() == Qt::Key_Tab) {
if (kevent->modifiers() == 0) {
deltaCol = 1;
deltaRow = 0;
Q_EMIT returnPressed();
return true;
}
}
else if (kevent->key() == Qt::Key_Backtab) {
if (kevent->modifiers() == Qt::ShiftModifier) {
deltaCol = -1;
deltaRow = 0;
Q_EMIT returnPressed();
return true;
}
}
else if (kevent->key() == Qt::Key_Enter || kevent->key() == Qt::Key_Return) {
if (kevent->modifiers() == 0) {
deltaCol = 0;
deltaRow = 1;
Q_EMIT returnPressed();
return true;
}
else if (kevent->modifiers() == Qt::ShiftModifier) {
deltaCol = 0;
deltaRow = -1;
Q_EMIT returnPressed();
return true;
}
}
lastKeyPressed = kevent->key();
lastModifiers = kevent->modifiers();
}
return Gui::ExpressionLineEdit::event(event);
}
void LineEdit::setIndex(QModelIndex _current)
{
current = _current;
}
QModelIndex LineEdit::next() const
{
const QAbstractItemModel * m = current.model();
return m->index(qMin(qMax(0, current.row() + deltaRow), m->rowCount() - 1 ),
qMin(qMax(0, current.column() + deltaCol), m->columnCount() - 1 ) );
}
#include "moc_LineEdit.cpp"

View File

@@ -36,13 +36,17 @@ public:
explicit LineEdit(QWidget *parent = 0);
bool event(QEvent *event);
void setIndex(QModelIndex _current);
QModelIndex next() const;
Q_SIGNALS:
void finishedWithKey(int key, Qt::KeyboardModifiers modifiers);
private:
QModelIndex current;
int deltaCol;
int deltaRow;
bool eventFilter(QObject* object, QEvent* event);
private:
int lastKeyPressed;
Qt::KeyboardModifiers lastModifiers;
};
}

View File

@@ -101,6 +101,7 @@ static std::pair<int, int> selectedMinMaxColumns(QModelIndexList list)
SheetTableView::SheetTableView(QWidget *parent)
: QTableView(parent)
, sheet(0)
, tabCounter(0)
{
setHorizontalHeader(new SheetViewHeader(this,Qt::Horizontal));
setVerticalHeader(new SheetViewHeader(this,Qt::Vertical));
@@ -319,7 +320,7 @@ void SheetTableView::insertColumnsAfter()
{
assert(sheet != 0);
const auto columns = selectionModel()->selectedColumns();
const auto & [min, max] = selectedMinMaxColumns(columns);
const auto& [min, max] = selectedMinMaxColumns(columns);
assert(max - min == columns.size() - 1);
Q_UNUSED(min)
@@ -345,7 +346,7 @@ void SheetTableView::removeColumns()
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Remove rows"));
for (std::vector<int>::const_iterator it = sortedColumns.begin(); it != sortedColumns.end(); ++it)
Gui::cmdAppObjectArgs(sheet, "removeColumns('%s', %d)",
columnName(*it).c_str(), 1);
columnName(*it).c_str(), 1);
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
@@ -365,7 +366,7 @@ void SheetTableView::updateCellSpan(CellAddress address)
setSpan(address.row(), address.col(), rows, cols);
}
void SheetTableView::setSheet(Sheet * _sheet)
void SheetTableView::setSheet(Sheet* _sheet)
{
sheet = _sheet;
cellSpanChangedConnection = sheet->cellSpanChanged.connect(bind(&SheetTableView::updateCellSpan, this, bp::_1));
@@ -399,57 +400,45 @@ void SheetTableView::setSheet(Sheet * _sheet)
}
void SheetTableView::commitData ( QWidget * editor )
void SheetTableView::commitData(QWidget* editor)
{
QTableView::commitData(editor);
}
bool SheetTableView::edit ( const QModelIndex & index, EditTrigger trigger, QEvent * event )
bool SheetTableView::edit(const QModelIndex& index, EditTrigger trigger, QEvent* event)
{
if (trigger & (QAbstractItemView::DoubleClicked | QAbstractItemView::AnyKeyPressed | QAbstractItemView::EditKeyPressed) )
if (trigger & (QAbstractItemView::DoubleClicked | QAbstractItemView::AnyKeyPressed | QAbstractItemView::EditKeyPressed))
currentEditIndex = index;
return QTableView::edit(index, trigger, event);
}
bool SheetTableView::event(QEvent *event)
bool SheetTableView::event(QEvent* event)
{
/* Catch key presses for navigating the table; Enter/Return (+Shift), and Tab (+Shift) */
if (event && event->type() == QEvent::KeyPress) {
QKeyEvent * kevent = static_cast<QKeyEvent*>(event);
if (kevent->key() == Qt::Key_Tab) {
QModelIndex c = currentIndex();
if (kevent->modifiers() == 0) {
setCurrentIndex(model()->index(c.row(), qMin(c.column() + 1, model()->columnCount() -1)));
return true;
}
}
else if (kevent->key() == Qt::Key_Backtab) {
QModelIndex c = currentIndex();
if (kevent->modifiers() == Qt::ShiftModifier) {
setCurrentIndex(model()->index(c.row(), qMax(c.column() - 1, 0)));
return true;
}
}
else if (kevent->key() == Qt::Key_Enter || kevent->key() == Qt::Key_Return) {
QModelIndex c = currentIndex();
if (kevent->modifiers() == 0) {
setCurrentIndex(model()->index(qMin(c.row() + 1, model()->rowCount() - 1), c.column()));
return true;
}
else if (kevent->modifiers() == Qt::ShiftModifier) {
setCurrentIndex(model()->index(qMax(c.row() - 1, 0), c.column()));
return true;
}
}
else if (kevent->key() == Qt::Key_Delete) {
if (event && event->type() == QEvent::KeyPress && this->hasFocus()) {
// If this widget has focus, look for keyboard events that represent movement shortcuts
// and handle them.
QKeyEvent* kevent = static_cast<QKeyEvent*>(event);
switch (kevent->key()) {
case Qt::Key_Return: [[fallthrough]];
case Qt::Key_Enter: [[fallthrough]];
case Qt::Key_Home: [[fallthrough]];
case Qt::Key_End: [[fallthrough]];
case Qt::Key_Left: [[fallthrough]];
case Qt::Key_Right: [[fallthrough]];
case Qt::Key_Up: [[fallthrough]];
case Qt::Key_Down: [[fallthrough]];
case Qt::Key_Tab: [[fallthrough]];
case Qt::Key_Backtab:
finishEditWithMove(kevent->key(), kevent->modifiers(), true);
return true;
// Also handle the delete key here:
case Qt::Key_Delete:
deleteSelection();
return true;
default:
break;
}
else if (kevent->matches(QKeySequence::Cut)) {
if (kevent->matches(QKeySequence::Cut)) {
cutSelection();
return true;
}
@@ -468,18 +457,19 @@ bool SheetTableView::event(QEvent *event)
kevent->modifiers() == Qt::ShiftModifier ||
kevent->modifiers() == Qt::KeypadModifier) {
switch (kevent->key()) {
case Qt::Key_Return:
case Qt::Key_Enter:
case Qt::Key_Delete:
case Qt::Key_Home:
case Qt::Key_End:
case Qt::Key_Backspace:
case Qt::Key_Left:
case Qt::Key_Right:
case Qt::Key_Up:
case Qt::Key_Down:
case Qt::Key_Return: [[fallthrough]];
case Qt::Key_Enter: [[fallthrough]];
case Qt::Key_Delete: [[fallthrough]];
case Qt::Key_Home: [[fallthrough]];
case Qt::Key_End: [[fallthrough]];
case Qt::Key_Backspace: [[fallthrough]];
case Qt::Key_Left: [[fallthrough]];
case Qt::Key_Right: [[fallthrough]];
case Qt::Key_Up: [[fallthrough]];
case Qt::Key_Down: [[fallthrough]];
case Qt::Key_Tab:
kevent->accept();
break;
default:
break;
}
@@ -614,13 +604,239 @@ void SheetTableView::pasteClipboard()
}
}
void SheetTableView::closeEditor(QWidget * editor, QAbstractItemDelegate::EndEditHint hint)
void SheetTableView::finishEditWithMove(int keyPressed, Qt::KeyboardModifiers modifiers, bool handleTabMotion)
{
SpreadsheetGui::LineEdit * le = qobject_cast<SpreadsheetGui::LineEdit*>(editor);
// A utility lambda for finding the beginning and ending of data regions
auto scanForRegionBoundary = [this](int& r, int& c, int dr, int dc) {
auto startAddress = CellAddress(r, c);
auto startCell = sheet->getCell(startAddress);
bool startedAtEmptyCell = startCell ? !startCell->isUsed() : true;
const int maxRow = this->model()->rowCount() - 1;
const int maxCol = this->model()->columnCount() - 1;
while (c + dc >= 0 && r + dr >= 0 && c + dc <= maxCol && r + dr <= maxRow) {
r += dr;
c += dc;
auto cell = sheet->getCell(CellAddress(r, c));
auto cellIsEmpty = cell ? !cell->isUsed() : true;
if (cellIsEmpty && !startedAtEmptyCell) {
// Don't stop at the empty cell, stop at the last non-empty cell
r -= dr;
c -= dc;
break;
}
else if (!cellIsEmpty && startedAtEmptyCell) {
break;
}
}
if (r == startAddress.row() && c == startAddress.col()) {
// Always move at least one cell:
r += dr;
c += dc;
}
r = std::max(0, std::min(r, maxRow));
c = std::max(0, std::min(c, maxCol));
};
currentEditIndex = QModelIndex();
int targetRow = currentIndex().row();
int targetColumn = currentIndex().column();
int colSpan;
int rowSpan;
sheet->getSpans(CellAddress(targetRow, targetColumn), rowSpan, colSpan);
switch (keyPressed) {
case Qt::Key_Return:
case Qt::Key_Enter:
if (modifiers == Qt::NoModifier) {
targetRow += rowSpan;
targetColumn -= tabCounter;
}
else if (modifiers == Qt::ShiftModifier) {
targetRow -= 1;
targetColumn -= tabCounter;
}
else {
// For an unrecognized modifier, just go down
targetRow += rowSpan;
}
tabCounter = 0;
break;
case Qt::Key_Home:
// Home: row 1, same column
// Ctrl-Home: row 1, column 1
targetRow = 0;
if (modifiers == Qt::ControlModifier)
targetColumn = 0;
tabCounter = 0;
break;
case Qt::Key_End:
{
// End should take you to the last occupied cell in the current column
// Ctrl-End takes you to the last cell in the sheet
auto usedCells = sheet->getCells()->getUsedCells();
for (const auto& cell : usedCells) {
if (modifiers == Qt::NoModifier) {
if (cell.col() == targetColumn)
targetRow = std::max(targetRow, cell.row());
}
else if (modifiers == Qt::ControlModifier) {
targetRow = std::max(targetRow, cell.row());
targetColumn = std::max(targetColumn, cell.col());
}
}
tabCounter = 0;
break;
}
case Qt::Key_Left:
if (targetColumn == 0)
break; // Nothing to do, we're already in the first column
if (modifiers == Qt::NoModifier || modifiers == Qt::ShiftModifier)
targetColumn--;
else if (modifiers == Qt::ControlModifier ||
modifiers == (Qt::ControlModifier | Qt::ShiftModifier))
scanForRegionBoundary(targetRow, targetColumn, 0, -1);
else
targetColumn--; //Unrecognized modifier combination: default to just moving one cell
tabCounter = 0;
break;
case Qt::Key_Right:
if (targetColumn >= this->model()->columnCount() - 1)
break; // Nothing to do, we're already in the last column
if (modifiers == Qt::NoModifier || modifiers == Qt::ShiftModifier)
targetColumn += colSpan;
else if (modifiers == Qt::ControlModifier ||
modifiers == (Qt::ControlModifier | Qt::ShiftModifier))
scanForRegionBoundary(targetRow, targetColumn, 0, 1);
else
targetColumn += colSpan; //Unrecognized modifier combination: default to just moving one cell
tabCounter = 0;
break;
case Qt::Key_Up:
if (targetRow == 0)
break; // Nothing to do, we're already in the first column
if (modifiers == Qt::NoModifier || modifiers == Qt::ShiftModifier)
targetRow--;
else if (modifiers == Qt::ControlModifier ||
modifiers == (Qt::ControlModifier | Qt::ShiftModifier))
scanForRegionBoundary(targetRow, targetColumn, -1, 0);
else
targetRow--; //Unrecognized modifier combination: default to just moving one cell
tabCounter = 0;
break;
case Qt::Key_Down:
if (targetRow >= this->model()->rowCount() - 1)
break; // Nothing to do, we're already in the last row
if (modifiers == Qt::NoModifier || modifiers == Qt::ShiftModifier)
targetRow += rowSpan;
else if (modifiers == Qt::ControlModifier ||
modifiers == (Qt::ControlModifier | Qt::ShiftModifier))
scanForRegionBoundary(targetRow, targetColumn, 1, 0);
else
targetRow += rowSpan; //Unrecognized modifier combination: default to just moving one cell
tabCounter = 0;
break;
case Qt::Key_Tab:
if (modifiers == Qt::NoModifier) {
tabCounter++;
if (handleTabMotion)
targetColumn += colSpan;
}
else if (modifiers == Qt::ShiftModifier) {
tabCounter = 0;
if (handleTabMotion)
targetColumn--;
}
break;
case Qt::Key_Backtab:
if (modifiers == Qt::NoModifier) {
targetColumn--;
}
tabCounter = 0;
break;
default:
break;
}
if (this->sheet->isMergedCell(CellAddress(targetRow, targetColumn))) {
auto anchor = this->sheet->getAnchor(CellAddress(targetRow, targetColumn));
targetRow = anchor.row();
targetColumn = anchor.col();
}
// Overflow/underflow protection:
const int maxRow = this->model()->rowCount() - 1;
const int maxCol = this->model()->columnCount() - 1;
targetRow = std::max(0, std::min(targetRow, maxRow));
targetColumn = std::max(0, std::min(targetColumn, maxCol));
if (!(modifiers & Qt::ShiftModifier) || keyPressed == Qt::Key_Tab || keyPressed == Qt::Key_Enter || keyPressed == Qt::Key_Return) {
// We have to use this method so that Ctrl-modifier combinations don't result in multiple selection
this->selectionModel()->setCurrentIndex(model()->index(targetRow, targetColumn),
QItemSelectionModel::ClearAndSelect);
}
else if (modifiers & Qt::ShiftModifier) {
// With shift down, this motion becomes a block selection command, rather than just simple motion:
ModifyBlockSelection(targetRow, targetColumn);
}
}
void SheetTableView::ModifyBlockSelection(int targetRow, int targetCol)
{
int startingRow = currentIndex().row();
int startingCol = currentIndex().column();
// Get the current block selection size:
auto selection = this->selectionModel()->selection();
for (const auto& range : selection) {
if (range.contains(currentIndex())) {
// This range contains the current cell, so it's the one we're going to modify (assuming we're at one of the corners)
int rangeMinRow = range.top();
int rangeMaxRow = range.bottom();
int rangeMinCol = range.left();
int rangeMaxCol = range.right();
if ((startingRow == rangeMinRow || startingRow == rangeMaxRow) &&
(startingCol == rangeMinCol || startingCol == rangeMaxCol)) {
if (range.contains(model()->index(targetRow, targetCol))) {
// If the range already contains the target cell, then we're making the range smaller
if (startingRow == rangeMinRow)
rangeMinRow = targetRow;
if (startingRow == rangeMaxRow)
rangeMaxRow = targetRow;
if (startingCol == rangeMinCol)
rangeMinCol = targetCol;
if (startingCol == rangeMaxCol)
rangeMaxCol = targetCol;
}
else {
// We're making the range bigger
rangeMinRow = std::min(rangeMinRow, targetRow);
rangeMaxRow = std::max(rangeMaxRow, targetRow);
rangeMinCol = std::min(rangeMinCol, targetCol);
rangeMaxCol = std::max(rangeMaxCol, targetCol);
}
QItemSelection oldRange(range.topLeft(), range.bottomRight());
this->selectionModel()->select(oldRange, QItemSelectionModel::Deselect);
QItemSelection newRange(model()->index(rangeMinRow, rangeMinCol), model()->index(rangeMaxRow, rangeMaxCol));
this->selectionModel()->select(newRange, QItemSelectionModel::Select);
}
break;
}
}
this->selectionModel()->setCurrentIndex(model()->index(targetRow, targetCol), QItemSelectionModel::Current);
}
void SheetTableView::closeEditor(QWidget * editor, QAbstractItemDelegate::EndEditHint hint)
{
QTableView::closeEditor(editor, hint);
setCurrentIndex(le->next());
}
void SheetTableView::mousePressEvent(QMouseEvent* event)
{
tabCounter = 0;
QTableView::mousePressEvent(event);
}
void SheetTableView::edit ( const QModelIndex & index )

View File

@@ -62,6 +62,9 @@ public:
void copySelection();
void cutSelection();
void pasteClipboard();
void finishEditWithMove(int keyPressed, Qt::KeyboardModifiers modifiers, bool handleTabMotion = false);
void ModifyBlockSelection(int targetRow, int targetColumn);
protected Q_SLOTS:
void commitData(QWidget *editor);
@@ -77,8 +80,10 @@ protected:
bool edit(const QModelIndex &index, EditTrigger trigger, QEvent *event);
bool event(QEvent *event);
void closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint);
void mousePressEvent(QMouseEvent* event);
QModelIndex currentEditIndex;
int tabCounter;
Spreadsheet::Sheet * sheet;
boost::signals2::scoped_connection cellSpanChangedConnection;

View File

@@ -47,28 +47,11 @@ QWidget *SpreadsheetDelegate::createEditor(QWidget *parent,
const QModelIndex &index) const
{
SpreadsheetGui::LineEdit *editor = new SpreadsheetGui::LineEdit(parent);
editor->setIndex(index);
editor->setDocumentObject(sheet);
connect(editor, SIGNAL(returnPressed()), this, SLOT(commitAndCloseEditor()));
connect(editor, &SpreadsheetGui::LineEdit::finishedWithKey, this, &SpreadsheetDelegate::on_editorFinishedWithKey);
return editor;
}
void SpreadsheetDelegate::commitAndCloseEditor()
{
Gui::ExpressionLineEdit *editor = qobject_cast<Gui::ExpressionLineEdit *>(sender());
if (editor->completerActive()) {
editor->hideCompleter();
return;
}
// See https://forum.freecadweb.org/viewtopic.php?f=3&t=41694
// It looks like the slot commitAndCloseEditor() is not needed any more and even
// causes a crash when doing so because the LineEdit is still accessed after its destruction.
//Q_EMIT commitData(editor);
//Q_EMIT closeEditor(editor);
}
void SpreadsheetDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
@@ -89,6 +72,11 @@ void SpreadsheetDelegate::setModelData(QWidget *editor,
}
}
void SpreadsheetDelegate::on_editorFinishedWithKey(int key, Qt::KeyboardModifiers modifiers)
{
Q_EMIT finishedWithKey(key, modifiers);
}
QSize SpreadsheetDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
{
Q_UNUSED(option);

View File

@@ -45,8 +45,10 @@ public:
const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
Q_SIGNALS:
void finishedWithKey(int key, Qt::KeyboardModifiers modifiers);
private Q_SLOTS:
void commitAndCloseEditor();
void on_editorFinishedWithKey(int key, Qt::KeyboardModifiers modifiers);
private:
Spreadsheet::Sheet * sheet;
};

View File

@@ -98,9 +98,12 @@ SheetView::SheetView(Gui::Document *pcDocument, App::DocumentObject *docObj, QWi
connect(ui->cells->verticalHeader(), SIGNAL(sectionResized ( int, int, int ) ),
this, SLOT(rowResized(int, int, int)));
connect(ui->cellContent, SIGNAL(returnPressed()), this, SLOT( editingFinished() ));
connect(ui->cellAlias, SIGNAL(returnPressed()), this, SLOT( editingFinished() ));
connect(ui->cellAlias, SIGNAL(textEdited(QString)), this, SLOT(aliasChanged(QString)));
connect(delegate, &SpreadsheetDelegate::finishedWithKey, this, &SheetView::editingFinishedWithKey);
connect(ui->cellContent, &LineEdit::finishedWithKey, this, [this](int, Qt::KeyboardModifiers) {confirmContentChanged(ui->cellContent->text()); });
connect(ui->cellContent, &LineEdit::returnPressed, this, [this]() {confirmContentChanged(ui->cellContent->text()); });
connect(ui->cellAlias, &LineEdit::finishedWithKey, this, [this](int, Qt::KeyboardModifiers) {confirmAliasChanged(ui->cellAlias->text()); });
connect(ui->cellAlias, &LineEdit::returnPressed, this, [this]() {confirmAliasChanged(ui->cellAlias->text()); });
connect(ui->cellAlias, &LineEdit::textEdited, this, &SheetView::aliasChanged);
columnWidthChangedConnection = sheet->columnWidthChanged.connect(bind(&SheetView::resizeColumn, this, bp::_1, bp::_2));
rowHeightChangedConnection = sheet->rowHeightChanged.connect(bind(&SheetView::resizeRow, this, bp::_1, bp::_2));
@@ -215,20 +218,6 @@ void SheetView::setCurrentCell(QString str)
updateAliasLine();
}
void SheetView::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Delete) {
if (event->modifiers() == 0) {
//model()->setData(currentIndex(), QVariant(), Qt::EditRole);
}
else if (event->modifiers() == Qt::ControlModifier) {
//model()->setData(currentIndex(), QVariant(), Qt::EditRole);
}
}
else
Gui::MDIView::keyPressEvent(event);
}
void SheetView::updateContentLine()
{
QModelIndex i = ui->cells->currentIndex();
@@ -238,7 +227,6 @@ void SheetView::updateContentLine()
if (const auto * cell = sheet->getCell(CellAddress(i.row(), i.column())))
(void)cell->getStringContent(str);
ui->cellContent->setText(QString::fromUtf8(str.c_str()));
ui->cellContent->setIndex(i);
ui->cellContent->setEnabled(true);
// Update completer model; for the time being, we do this by setting the document object of the input line.
@@ -255,7 +243,6 @@ void SheetView::updateAliasLine()
if (const auto * cell = sheet->getCell(CellAddress(i.row(), i.column())))
(void)cell->getAlias(str);
ui->cellAlias->setText(QString::fromUtf8(str.c_str()));
ui->cellAlias->setIndex(i);
ui->cellAlias->setEnabled(true);
// Update completer model; for the time being, we do this by setting the document object of the input line.
@@ -322,51 +309,53 @@ void SheetView::resizeRow(int col, int newSize)
ui->cells->setRowHeight(col, newSize);
}
void SheetView::editingFinished()
void SheetView::editingFinishedWithKey(int key, Qt::KeyboardModifiers modifiers)
{
if (ui->cellContent->completerActive()) {
ui->cellContent->hideCompleter();
return;
}
if (ui->cellAlias->completerActive()) {
ui->cellAlias->hideCompleter();
return;
}
QModelIndex i = ui->cells->currentIndex();
if (i.isValid()) {
QString str = ui->cellAlias->text();
bool aliasOkay = true;
if (str.length()!= 0 && !sheet->isValidAlias(Base::Tools::toStdString(str))){
aliasOkay = false;
}
ui->cellAlias->setDocumentObject(sheet);
ui->cells->model()->setData(i, QVariant(ui->cellContent->text()), Qt::EditRole);
ui->cells->finishEditWithMove(key, modifiers);
}
}
if (const auto * cell = sheet->getCell(CellAddress(i.row(), i.column()))){
if (!aliasOkay){
//do not show error message if failure to set new alias is because it is already the same string
std::string current_alias;
(void)cell->getAlias(current_alias);
if (str != QString::fromUtf8(current_alias.c_str())){
Base::Console().Error("Unable to set alias: %s\n", Base::Tools::toStdString(str).c_str());
}
} else {
std::string address = CellAddress(i.row(), i.column()).toString();
Gui::cmdAppObjectArgs(sheet, "setAlias('%s', '%s')",
address, str.toStdString());
Gui::cmdAppDocument(sheet->getDocument(), "recompute()");
void SheetView::confirmAliasChanged(const QString& text)
{
bool aliasOkay = true;
ui->cellAlias->setDocumentObject(sheet);
if (text.length() != 0 && !sheet->isValidAlias(Base::Tools::toStdString(text))) {
aliasOkay = false;
}
QModelIndex i = ui->cells->currentIndex();
if (const auto* cell = sheet->getCell(CellAddress(i.row(), i.column()))) {
if (!aliasOkay) {
//do not show error message if failure to set new alias is because it is already the same string
std::string current_alias;
(void)cell->getAlias(current_alias);
if (text != QString::fromUtf8(current_alias.c_str())) {
Base::Console().Error("Unable to set alias: %s\n", Base::Tools::toStdString(text).c_str());
}
}
ui->cells->setCurrentIndex(ui->cellContent->next());
ui->cells->setFocus();
else {
std::string address = CellAddress(i.row(), i.column()).toString();
Gui::cmdAppObjectArgs(sheet, "setAlias('%s', '%s')",
address, text.toStdString());
Gui::cmdAppDocument(sheet->getDocument(), "recompute()");
ui->cells->setFocus();
}
}
}
void SheetView::confirmContentChanged(const QString& text)
{
QModelIndex i = ui->cells->currentIndex();
ui->cells->model()->setData(i, QVariant(ui->cellContent->text()), Qt::EditRole);
ui->cells->setFocus();
}
void SheetView::aliasChanged(const QString& text)
{
// check live the input and highlight if the user input invalid characters

View File

@@ -82,8 +82,10 @@ public:
virtual void deleteSelf();
protected Q_SLOTS:
void editingFinished();
void editingFinishedWithKey(int key, Qt::KeyboardModifiers modifiers);
void confirmAliasChanged(const QString& text);
void aliasChanged(const QString& text);
void confirmContentChanged(const QString& text);
void currentChanged( const QModelIndex & current, const QModelIndex & previous );
void columnResized(int col, int oldSize, int newSize);
void rowResized(int row, int oldSize, int newSize);
@@ -94,7 +96,6 @@ protected:
void updateContentLine();
void updateAliasLine();
void setCurrentCell(QString str);
void keyPressEvent(QKeyEvent *event);
void resizeColumn(int col, int newSize);
void resizeRow(int col, int newSize);