From ffda8d3ccc1b503820a0dca42f2f1a8f723045b2 Mon Sep 17 00:00:00 2001 From: Robert Knight Date: Sun, 17 Jun 2007 22:05:45 +0000 Subject: [PATCH] Implement saving of key binding changes. Adapt Pty changes to use Konsole's more verbose variable naming style. svn path=/trunk/KDE/kdebase/apps/konsole/; revision=676902 --- src/EditProfileDialog.cpp | 1 + src/KeyBindingEditor.cpp | 16 +++++- src/KeyboardTranslator.cpp | 100 +++++++++++++++++++++++++++++++++++-- src/KeyboardTranslator.h | 38 ++++++++++++++ src/Pty.cpp | 33 +++++++----- src/Pty.h | 8 +-- src/TerminalDisplay.cpp | 10 ++++ 7 files changed, 185 insertions(+), 21 deletions(-) diff --git a/src/EditProfileDialog.cpp b/src/EditProfileDialog.cpp index 04aa17f41..80c622c87 100644 --- a/src/EditProfileDialog.cpp +++ b/src/EditProfileDialog.cpp @@ -652,6 +652,7 @@ void EditProfileDialog::showKeyBindingEditor(bool isNewTranslator) if ( isNewTranslator ) newTranslator->setName(newTranslator->description()); + qDebug() << "Adding new or modified translator to manager"; KeyboardTranslatorManager::instance()->addTranslator( newTranslator ); updateKeyBindingsList(); diff --git a/src/KeyBindingEditor.cpp b/src/KeyBindingEditor.cpp index a3ce45ee8..d163cda5b 100644 --- a/src/KeyBindingEditor.cpp +++ b/src/KeyBindingEditor.cpp @@ -120,12 +120,24 @@ KeyboardTranslator* KeyBindingEditor::translator() const void KeyBindingEditor::bindingTableItemChanged(QTableWidgetItem* item) { - QString condition = _ui->keyBindingTable->item( item->row() , 0 )->text(); + QTableWidgetItem* key = _ui->keyBindingTable->item( item->row() , 0 ); + KeyboardTranslator::Entry existing = key->data(Qt::UserRole).value(); + + QString condition = key->text(); QString result = _ui->keyBindingTable->item( item->row() , 1 )->text(); KeyboardTranslator::Entry entry = KeyboardTranslatorReader::createEntry(condition,result); qDebug() << "Created entry: " << entry.conditionToString() << " , " << entry.resultToString(); + + _translator->replaceEntry(existing,entry); + + // block signals to prevent this slot from being called repeatedly + _ui->keyBindingTable->blockSignals(true); + + key->setData(Qt::UserRole,QVariant::fromValue(existing)); + + _ui->keyBindingTable->blockSignals(false); } void KeyBindingEditor::setupKeyBindingTable(const KeyboardTranslator* translator) @@ -142,6 +154,8 @@ void KeyBindingEditor::setupKeyBindingTable(const KeyboardTranslator* translator const KeyboardTranslator::Entry& entry = entries.at(row); QTableWidgetItem* keyItem = new QTableWidgetItem(entry.conditionToString()); + keyItem->setData( Qt::UserRole , QVariant::fromValue(entry) ); + QTableWidgetItem* textItem = new QTableWidgetItem(QString(entry.resultToString())); _ui->keyBindingTable->setItem(row,0,keyItem); diff --git a/src/KeyboardTranslator.cpp b/src/KeyboardTranslator.cpp index 1e504209d..cf63a0568 100644 --- a/src/KeyboardTranslator.cpp +++ b/src/KeyboardTranslator.cpp @@ -84,6 +84,37 @@ const KeyboardTranslator* KeyboardTranslatorManager::findTranslator(const QStrin return translator; } +bool KeyboardTranslatorManager::saveTranslator(const KeyboardTranslator* translator) +{ + const QString path = KGlobal::dirs()->saveLocation("data","konsole/")+translator->name() + +".keytab"; + + qDebug() << "Saving translator to" << path; + + QFile destination(path); + + if (!destination.open(QIODevice::WriteOnly | QIODevice::Text)) + { + qWarning() << "Unable to save keyboard translation:" + << destination.errorString(); + + return false; + } + + { + KeyboardTranslatorWriter writer(&destination); + writer.writeHeader(translator->description()); + + QListIterator iter(translator->entries()); + while ( iter.hasNext() ) + writer.writeEntry(iter.next()); + } + + destination.close(); + + return true; +} + KeyboardTranslator* KeyboardTranslatorManager::loadTranslator(const QString& name) { KeyboardTranslator* translator = new KeyboardTranslator(name); @@ -91,7 +122,7 @@ KeyboardTranslator* KeyboardTranslatorManager::loadTranslator(const QString& nam const QString& path = findTranslatorPath(name); QFile source(path); - source.open(QIODevice::ReadOnly); + source.open(QIODevice::ReadOnly | QIODevice::Text); KeyboardTranslatorReader reader(&source); translator->setDescription( reader.description() ); @@ -111,6 +142,33 @@ KeyboardTranslator* KeyboardTranslatorManager::loadTranslator(const QString& nam } } +KeyboardTranslatorWriter::KeyboardTranslatorWriter(QIODevice* destination) +: _destination(destination) +{ + Q_ASSERT( destination && destination->isWritable() ); + + _writer = new QTextStream(_destination); +} +KeyboardTranslatorWriter::~KeyboardTranslatorWriter() +{ + delete _writer; +} +void KeyboardTranslatorWriter::writeHeader( const QString& description ) +{ + *_writer << "keyboard \"" << description << '\"' << '\n'; +} +void KeyboardTranslatorWriter::writeEntry( const KeyboardTranslator::Entry& entry ) +{ + QString result; + + if ( entry.command() != KeyboardTranslator::NoCommand ) + result = entry.resultToString(); + else + result = '\"' + entry.resultToString() + '\"'; + + *_writer << "key " << entry.conditionToString() << " : " << result << '\n'; +} + // each line of the keyboard translation file is one of: // @@ -578,6 +636,17 @@ QKeySequence KeyboardTranslator::Entry::keySequence() const } #endif +bool KeyboardTranslator::Entry::operator==(const Entry& rhs) +{ + return _keyCode == rhs._keyCode && + _modifiers == rhs._modifiers && + _modifierMask == rhs._modifierMask && + _state == rhs._state && + _stateMask == rhs._stateMask && + _command == rhs._command && + _text == rhs._text; +} + bool KeyboardTranslator::Entry::matches(int keyCode , Qt::KeyboardModifier modifiers, State state) const { @@ -639,6 +708,8 @@ QByteArray KeyboardTranslator::Entry::escapedText() const case 13 : replacement = 'r'; break; case 10 : replacement = 'n'; break; default: + // any character which is not printable is replaced by an equivalent + // \xhh escape sequence (where 'hh' are the corresponding hex digits) if ( !QChar(ch).isPrint() ) replacement = 'x'; } @@ -828,7 +899,15 @@ void KeyboardTranslator::addEntry(const Entry& entry) const int keyCode = entry.keyCode(); _entries.insert(keyCode,entry); } - +void KeyboardTranslator::replaceEntry(const Entry& existing , const Entry& replacement) +{ + _entries.remove(existing.keyCode(),existing); + _entries.insert(replacement.keyCode(),replacement); +} +void KeyboardTranslator::removeEntry(const Entry& entry) +{ + _entries.remove(entry.keyCode(),entry); +} KeyboardTranslator::Entry KeyboardTranslator::findEntry(int keyCode, Qt::KeyboardModifier modifiers, State state) const { //qDebug() << "Searching for entry for key code =" << keyCode << ", modifiers =" << modifiers; @@ -860,11 +939,24 @@ KeyboardTranslator::Entry KeyboardTranslator::findEntry(int keyCode, Qt::Keyboar } void KeyboardTranslatorManager::addTranslator(KeyboardTranslator* translator) { - qWarning() << __FUNCTION__ << ": Not implemented"; + _translators.insert(translator->name(),translator); + + if ( !saveTranslator(translator) ) + qWarning() << "Unable to save translator" << translator->name() + << "to disk."; } void KeyboardTranslatorManager::deleteTranslator(const QString& name) { - qWarning() << __FUNCTION__ << ": Not implemented"; + Q_ASSERT( _translators.contains(name) ); + + _translators.remove(name); + + // locate and delete + QString path = findTranslatorPath(name); + if ( QFile::remove(path) ) + qDebug() << "Removed translator - " << path; + else + qDebug() << "Failed to remove translator - " << path; } void KeyboardTranslatorManager::setInstance(KeyboardTranslatorManager* instance) { diff --git a/src/KeyboardTranslator.h b/src/KeyboardTranslator.h index 296eb6ca2..b4e899f00 100644 --- a/src/KeyboardTranslator.h +++ b/src/KeyboardTranslator.h @@ -30,6 +30,7 @@ #include class QIODevice; +class QTextStream; namespace Konsole { @@ -201,6 +202,7 @@ public: */ bool matches( int keyCode , Qt::KeyboardModifier modifiers , State flags ) const; + bool operator==(const Entry& rhs); private: void insertModifier( QString& item , int modifier ) const; @@ -253,6 +255,16 @@ public: */ void addEntry(const Entry& entry); + /** + * Replaces an entry in the translator. + */ + void replaceEntry(const Entry& existing , const Entry& replacement); + + /** + * Removes an entry from the table. + */ + void removeEntry(const Entry& entry); + /** Returns a list of all entries in the translator. */ QList entries() const; @@ -357,6 +369,30 @@ private: bool _hasNext; }; +/** Writes a keyboard translation to disk. */ +class KeyboardTranslatorWriter +{ +public: + /** + * Constructs a new writer which saves data into @p destination. + * The caller is responsible for closing the device when writing is complete. + */ + KeyboardTranslatorWriter(QIODevice* destination); + ~KeyboardTranslatorWriter(); + + /** + * Writes the header for the keyboard translator. + * @param description Description of the keyboard translator. + */ + void writeHeader( const QString& description ); + /** Writes a translator entry. */ + void writeEntry( const KeyboardTranslator::Entry& entry ); + +private: + QIODevice* _destination; + QTextStream* _writer; +}; + /** * Manages the keyboard translations available for use by terminal sessions, * see KeyboardTranslator. @@ -413,6 +449,7 @@ private: KeyboardTranslator* loadTranslator(const QString& name); // loads the translator // with the given name + bool saveTranslator(const KeyboardTranslator* translator); QString findTranslatorPath(const QString& name); QHash _translators; // maps translator-name -> KeyboardTranslator @@ -465,6 +502,7 @@ inline KeyboardTranslator::State KeyboardTranslator::Entry::stateMask() const { } +Q_DECLARE_METATYPE(Konsole::KeyboardTranslator::Entry); Q_DECLARE_METATYPE(const Konsole::KeyboardTranslator*) #endif // KEYBOARDTRANSLATOR_H diff --git a/src/Pty.cpp b/src/Pty.cpp index bacb73886..953c398de 100644 --- a/src/Pty.cpp +++ b/src/Pty.cpp @@ -46,20 +46,22 @@ void Pty::donePty() void Pty::setWindowSize(int lines, int cols) { - wsX = cols; - wsY = lines; + _windowColumns = cols; + _windowLines = lines; + if (pty()->masterFd() >= 0) pty()->setWinSize(lines, cols); } -void Pty::setXonXoff(bool on) +void Pty::setXonXoff(bool enable) { - xonXoff = on; + _xonXoff = enable; + if (pty()->masterFd() >= 0) { struct ::termios ttmode; pty()->tcGetAttr(&ttmode); - if (!on) + if (!enable) ttmode.c_iflag &= ~(IXOFF | IXON); else ttmode.c_iflag |= (IXOFF | IXON); @@ -68,15 +70,16 @@ void Pty::setXonXoff(bool on) } } -void Pty::setUtf8Mode(bool on) +void Pty::setUtf8Mode(bool enable) { #ifdef IUTF8 // XXX not a reasonable place to check it. - utf8 = on; + _utf8 = enable; + if (pty()->masterFd() >= 0) { struct ::termios ttmode; pty()->tcGetAttr(&ttmode); - if (!on) + if (!enable) ttmode.c_iflag &= ~IUTF8; else ttmode.c_iflag |= IUTF8; @@ -88,7 +91,8 @@ void Pty::setUtf8Mode(bool on) void Pty::setErase(char erase) { - this->erase = erase; + _eraseChar = erase; + if (pty()->masterFd() >= 0) { struct ::termios ttmode; @@ -127,22 +131,25 @@ int Pty::start(const QString& program, setUsePty(All, addToUtmp); pty()->open(); + struct ::termios ttmode; pty()->tcGetAttr(&ttmode); - if (!xonXoff) + if (!_xonXoff) ttmode.c_iflag &= ~(IXOFF | IXON); else ttmode.c_iflag |= (IXOFF | IXON); #ifdef IUTF8 // XXX not a reasonable place to check it. - if (!utf8) + if (!_utf8) ttmode.c_iflag &= ~IUTF8; else ttmode.c_iflag |= IUTF8; #endif - ttmode.c_cc[VERASE] = erase; + ttmode.c_cc[VERASE] = _eraseChar; + if (!pty()->tcSetAttr(&ttmode)) qWarning("Unable to set terminal attributes."); - pty()->setWinSize(wsY, wsX); + + pty()->setWinSize(_windowLines, _windowColumns); if ( K3Process::start(NotifyOnExit, (Communication) (Stdin | Stdout)) == false ) return -1; diff --git a/src/Pty.h b/src/Pty.h index 9775ff236..9f2a86ecc 100644 --- a/src/Pty.h +++ b/src/Pty.h @@ -210,9 +210,11 @@ Q_OBJECT QList _pendingSendJobs; bool _bufferFull; - int wsX, wsY; - char erase; - bool xonXoff, utf8; + int _windowColumns; + int _windowLines; + char _eraseChar; + bool _xonXoff; + bool _utf8; }; } diff --git a/src/TerminalDisplay.cpp b/src/TerminalDisplay.cpp index e2932dcbb..c047d232e 100644 --- a/src/TerminalDisplay.cpp +++ b/src/TerminalDisplay.cpp @@ -1137,6 +1137,16 @@ FilterChain* TerminalDisplay::filterChain() const void TerminalDisplay::paintFilters(QPainter& painter) { + // get color of character under mouse and use it to draw + // lines for filters + QPoint cursorPos = mapFromGlobal(QCursor::pos()); + int cursorLine; + int cursorColumn; + characterPosition( cursorPos , cursorLine , cursorColumn ); + Character cursorCharacter = _image[loc(cursorColumn,cursorLine)]; + + painter.setPen( QPen(cursorCharacter.foregroundColor.color(colorTable())) ); + // iterate over hotspots identified by the display's currently active filters // and draw appropriate visuals to indicate the presence of the hotspot