From b7480210fd33393c6a716cca1b0692f9d0450c0a Mon Sep 17 00:00:00 2001 From: Eivind Kvedalen Date: Sun, 8 Nov 2015 11:15:20 +0100 Subject: [PATCH] Spreadsheet: Issue #2301: Handle enter/return and tab keys the same as e.g OpenOffice and Excel. --- src/Mod/Spreadsheet/Gui/CMakeLists.txt | 3 + src/Mod/Spreadsheet/Gui/LineEdit.cpp | 93 +++++++++++++++++++ src/Mod/Spreadsheet/Gui/LineEdit.h | 28 ++++++ src/Mod/Spreadsheet/Gui/Sheet.ui | 6 +- src/Mod/Spreadsheet/Gui/SheetModel.cpp | 3 - src/Mod/Spreadsheet/Gui/SheetTableView.cpp | 59 +++++++++++- src/Mod/Spreadsheet/Gui/SheetTableView.h | 3 + .../Spreadsheet/Gui/SpreadsheetDelegate.cpp | 4 +- src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp | 5 + 9 files changed, 192 insertions(+), 12 deletions(-) create mode 100644 src/Mod/Spreadsheet/Gui/LineEdit.cpp create mode 100644 src/Mod/Spreadsheet/Gui/LineEdit.h diff --git a/src/Mod/Spreadsheet/Gui/CMakeLists.txt b/src/Mod/Spreadsheet/Gui/CMakeLists.txt index 8a9a12cd3..913045790 100644 --- a/src/Mod/Spreadsheet/Gui/CMakeLists.txt +++ b/src/Mod/Spreadsheet/Gui/CMakeLists.txt @@ -16,6 +16,7 @@ set(SpreadsheetGui_LIBS ) set(SpreadsheetGui_MOC_HDRS + LineEdit.h SpreadsheetView.h SheetModel.h SheetTableView.h @@ -55,6 +56,8 @@ SET(SpreadsheetGui_SRCS AppSpreadsheetGui.cpp AppSpreadsheetGuiPy.cpp Command.cpp + LineEdit.h + LineEdit.cpp ViewProviderSpreadsheet.cpp ViewProviderSpreadsheet.h Resources/Spreadsheet.qrc diff --git a/src/Mod/Spreadsheet/Gui/LineEdit.cpp b/src/Mod/Spreadsheet/Gui/LineEdit.cpp new file mode 100644 index 000000000..bd171f84a --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/LineEdit.cpp @@ -0,0 +1,93 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +#endif + +#include "LineEdit.h" + +using namespace SpreadsheetGui; + +LineEdit::LineEdit(QWidget *parent) + : Gui::ExpressionLineEdit(parent) + , current() + , deltaCol(0) + , deltaRow(0) +{ +} + +bool LineEdit::event(QEvent *event) +{ + if (event && event->type() == QEvent::KeyPress) { + QKeyEvent * kevent = static_cast(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; + } + } + } + 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" diff --git a/src/Mod/Spreadsheet/Gui/LineEdit.h b/src/Mod/Spreadsheet/Gui/LineEdit.h new file mode 100644 index 000000000..f32d6128d --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/LineEdit.h @@ -0,0 +1,28 @@ +#ifndef LINEEDIT_H +#define LINEEDIT_H + +#include +#include +#include + +namespace SpreadsheetGui { + +class LineEdit : public Gui::ExpressionLineEdit +{ + Q_OBJECT +public: + explicit LineEdit(QWidget *parent = 0); + + bool event(QEvent *event); + void setIndex(QModelIndex _current); + QModelIndex next() const; + +private: + QModelIndex current; + int deltaCol; + int deltaRow; +}; + +} + +#endif // LINEEDIT_H diff --git a/src/Mod/Spreadsheet/Gui/Sheet.ui b/src/Mod/Spreadsheet/Gui/Sheet.ui index 06f9e0437..bbdf5c24c 100644 --- a/src/Mod/Spreadsheet/Gui/Sheet.ui +++ b/src/Mod/Spreadsheet/Gui/Sheet.ui @@ -27,7 +27,7 @@ - + false @@ -47,9 +47,9 @@
SheetTableView.h
- Gui::ExpressionLineEdit + SpreadsheetGui::LineEdit QLineEdit -
Gui/ExpressionCompleter.h
+
SpreadsheetView.h
diff --git a/src/Mod/Spreadsheet/Gui/SheetModel.cpp b/src/Mod/Spreadsheet/Gui/SheetModel.cpp index e1ebfd369..88d1141d5 100644 --- a/src/Mod/Spreadsheet/Gui/SheetModel.cpp +++ b/src/Mod/Spreadsheet/Gui/SheetModel.cpp @@ -413,7 +413,6 @@ bool SheetModel::setData(const QModelIndex & index, const QVariant & value, int try { std::string strAddress = address.toString(); - std::string next_address = CellAddress(address.row() + 1, address.col()).toString(); QString str = value.toString(); std::string content; Cell * cell = sheet->getCell(address); @@ -426,8 +425,6 @@ bool SheetModel::setData(const QModelIndex & index, const QVariant & value, int Gui::Command::openCommand("Edit cell"); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.set('%s', '%s')", sheet->getNameInDocument(), strAddress.c_str(), str.toUtf8().constData()); - Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setPosition('%s')", sheet->getNameInDocument(), - next_address.c_str()); Gui::Command::commitCommand(); Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); } diff --git a/src/Mod/Spreadsheet/Gui/SheetTableView.cpp b/src/Mod/Spreadsheet/Gui/SheetTableView.cpp index c059f9b78..29a14afaf 100644 --- a/src/Mod/Spreadsheet/Gui/SheetTableView.cpp +++ b/src/Mod/Spreadsheet/Gui/SheetTableView.cpp @@ -22,16 +22,17 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include +# include #endif -#include "SheetTableView.h" -#include -#include #include -#include "PropertiesDialog.h" +#include #include "../App/Utils.h" #include "../App/Range.h" -#include +#include "SheetTableView.h" +#include "LineEdit.h" +#include "PropertiesDialog.h" using namespace SpreadsheetGui; using namespace Spreadsheet; @@ -70,6 +71,7 @@ SheetTableView::SheetTableView(QWidget *parent) addAction(cellProperties); setContextMenuPolicy(Qt::ActionsContextMenu); + setTabKeyNavigation(false); connect(cellProperties, SIGNAL(triggered()), this, SLOT(cellProperties())); } @@ -290,6 +292,53 @@ bool SheetTableView::edit ( const QModelIndex & index, EditTrigger trigger, QEve return QTableView::edit(index, trigger, 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(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; + } + } + } + return QTableView::event(event); +} + +void SheetTableView::closeEditor(QWidget * editor, QAbstractItemDelegate::EndEditHint hint) +{ + SpreadsheetGui::LineEdit * le = qobject_cast(editor); + + currentEditIndex = QModelIndex(); + QTableView::closeEditor(editor, hint); + setCurrentIndex(le->next()); +} + void SheetTableView::edit ( const QModelIndex & index ) { currentEditIndex = index; diff --git a/src/Mod/Spreadsheet/Gui/SheetTableView.h b/src/Mod/Spreadsheet/Gui/SheetTableView.h index 4959000f0..aa6986878 100644 --- a/src/Mod/Spreadsheet/Gui/SheetTableView.h +++ b/src/Mod/Spreadsheet/Gui/SheetTableView.h @@ -25,6 +25,7 @@ #include #include +#include #include #include "PreCompiled.h" #include @@ -64,6 +65,8 @@ protected Q_SLOTS: void cellProperties(); protected: bool edit(const QModelIndex &index, EditTrigger trigger, QEvent *event); + bool event(QEvent *event); + void closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint); QModelIndex currentEditIndex; Spreadsheet::Sheet * sheet; diff --git a/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.cpp b/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.cpp index d43a89df2..b21ec6e9c 100644 --- a/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.cpp +++ b/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.cpp @@ -29,6 +29,7 @@ #endif #include "SpreadsheetDelegate.h" +#include "LineEdit.h" #include #include #include @@ -45,7 +46,8 @@ QWidget *SpreadsheetDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const { - Gui::ExpressionLineEdit *editor = new Gui::ExpressionLineEdit(parent); + SpreadsheetGui::LineEdit *editor = new SpreadsheetGui::LineEdit(parent); + editor->setIndex(index); editor->setDocumentObject(sheet); connect(editor, SIGNAL(returnPressed()), this, SLOT(commitAndCloseEditor())); diff --git a/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp b/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp index 17f8072d9..88ab91867 100644 --- a/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp +++ b/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp @@ -50,6 +50,7 @@ #include #include #include "qtcolorpicker.h" +#include #include "ui_Sheet.h" @@ -198,6 +199,7 @@ void SheetView::updateContentLine() if (cell) 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. @@ -289,6 +291,9 @@ void SheetView::editingFinished() // Update data in cell ui->cells->model()->setData(i, QVariant(ui->cellContent->text()), Qt::EditRole); + + ui->cells->setCurrentIndex(ui->cellContent->next()); + ui->cells->setFocus(); } void SheetView::currentChanged ( const QModelIndex & current, const QModelIndex & previous )