File indexing completed on 2024-05-12 05:47:30

0001 /*
0002  * SPDX-FileCopyrightText: 2012 Peter Penz <peter.penz19@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kitemlistroleeditor.h"
0008 
0009 #include <KIO/Global>
0010 
0011 KItemListRoleEditor::KItemListRoleEditor(QWidget *parent)
0012     : KTextEdit(parent)
0013     , m_role()
0014     , m_blockFinishedSignal(false)
0015 {
0016     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
0017     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
0018     setAcceptRichText(false);
0019     enableFindReplace(false);
0020     document()->setDocumentMargin(0);
0021     setCheckSpellingEnabled(false);
0022 
0023     if (parent) {
0024         parent->installEventFilter(this);
0025     }
0026 
0027     connect(this, &KItemListRoleEditor::textChanged, this, &KItemListRoleEditor::autoAdjustSize);
0028 }
0029 
0030 KItemListRoleEditor::~KItemListRoleEditor()
0031 {
0032 }
0033 
0034 void KItemListRoleEditor::setRole(const QByteArray &role)
0035 {
0036     m_role = role;
0037 }
0038 
0039 QByteArray KItemListRoleEditor::role() const
0040 {
0041     return m_role;
0042 }
0043 
0044 void KItemListRoleEditor::setAllowUpDownKeyChainEdit(bool allowChainEdit)
0045 {
0046     m_allowUpDownKeyChainEdit = allowChainEdit;
0047 }
0048 
0049 bool KItemListRoleEditor::eventFilter(QObject *watched, QEvent *event)
0050 {
0051     if (watched == parentWidget() && event->type() == QEvent::Resize) {
0052         emitRoleEditingFinished();
0053     }
0054 
0055     return KTextEdit::eventFilter(watched, event);
0056 }
0057 
0058 bool KItemListRoleEditor::event(QEvent *event)
0059 {
0060     if (event->type() == QEvent::FocusOut) {
0061         QFocusEvent *focusEvent = static_cast<QFocusEvent *>(event);
0062         if (focusEvent->reason() != Qt::PopupFocusReason) {
0063             emitRoleEditingFinished();
0064         }
0065     }
0066     return KTextEdit::event(event);
0067 }
0068 
0069 void KItemListRoleEditor::keyPressEvent(QKeyEvent *event)
0070 {
0071     switch (event->key()) {
0072     case Qt::Key_Escape:
0073         // Emitting the signal roleEditingCanceled might result
0074         // in losing the focus. Per default losing the focus emits
0075         // a roleEditingFinished signal (see KItemListRoleEditor::event),
0076         // which is not wanted in this case.
0077         m_blockFinishedSignal = true;
0078         Q_EMIT roleEditingCanceled(m_role, KIO::encodeFileName(toPlainText()));
0079         m_blockFinishedSignal = false;
0080         event->accept();
0081         return;
0082     case Qt::Key_Enter:
0083     case Qt::Key_Return:
0084         emitRoleEditingFinished();
0085         event->accept();
0086         return;
0087     case Qt::Key_Tab:
0088     case Qt::Key_Down:
0089         if (m_allowUpDownKeyChainEdit || event->key() == Qt::Key_Tab) {
0090             emitRoleEditingFinished(EditNext);
0091             event->accept();
0092             return;
0093         }
0094         break;
0095     case Qt::Key_Backtab:
0096     case Qt::Key_Up:
0097         if (m_allowUpDownKeyChainEdit || event->key() == Qt::Key_Backtab) {
0098             emitRoleEditingFinished(EditPrevious);
0099             event->accept();
0100             return;
0101         }
0102         break;
0103     case Qt::Key_Left:
0104     case Qt::Key_Right: {
0105         QTextCursor cursor = textCursor();
0106         if (event->modifiers() == Qt::NoModifier && cursor.hasSelection()) {
0107             if (event->key() == Qt::Key_Left) {
0108                 cursor.setPosition(cursor.selectionStart());
0109             } else {
0110                 cursor.setPosition(cursor.selectionEnd());
0111             }
0112             cursor.clearSelection();
0113             setTextCursor(cursor);
0114             event->accept();
0115             return;
0116         }
0117         break;
0118     }
0119     case Qt::Key_Home:
0120     case Qt::Key_End: {
0121         if (event->modifiers() == Qt::NoModifier || event->modifiers() == Qt::ShiftModifier) {
0122             const QTextCursor::MoveOperation op = event->key() == Qt::Key_Home ? QTextCursor::Start : QTextCursor::End;
0123             const QTextCursor::MoveMode mode = event->modifiers() == Qt::NoModifier ? QTextCursor::MoveAnchor : QTextCursor::KeepAnchor;
0124             QTextCursor cursor = textCursor();
0125             cursor.movePosition(op, mode);
0126             setTextCursor(cursor);
0127             event->accept();
0128             return;
0129         }
0130         break;
0131     }
0132     default:
0133         break;
0134     }
0135 
0136     KTextEdit::keyPressEvent(event);
0137 }
0138 
0139 void KItemListRoleEditor::autoAdjustSize()
0140 {
0141     const qreal frameBorder = 2 * frameWidth();
0142 
0143     document()->adjustSize();
0144     const qreal requiredWidth = document()->size().width();
0145     const qreal availableWidth = size().width() - frameBorder;
0146     if (requiredWidth > availableWidth) {
0147         qreal newWidth = requiredWidth + frameBorder;
0148         if (parentWidget() && pos().x() + newWidth > parentWidget()->width()) {
0149             newWidth = parentWidget()->width() - pos().x();
0150         }
0151         resize(newWidth, size().height());
0152     }
0153 
0154     const qreal requiredHeight = document()->size().height();
0155     const qreal availableHeight = size().height() - frameBorder;
0156     if (requiredHeight > availableHeight) {
0157         qreal newHeight = requiredHeight + frameBorder;
0158         if (parentWidget() && pos().y() + newHeight > parentWidget()->height()) {
0159             newHeight = parentWidget()->height() - pos().y();
0160         }
0161         resize(size().width(), newHeight);
0162     }
0163 }
0164 
0165 void KItemListRoleEditor::emitRoleEditingFinished(EditResultDirection direction)
0166 {
0167     QVariant ret;
0168     ret.setValue(EditResult{KIO::encodeFileName(toPlainText()), direction});
0169 
0170     if (!m_blockFinishedSignal) {
0171         Q_EMIT roleEditingFinished(m_role, ret);
0172     }
0173 }
0174 
0175 #include "moc_kitemlistroleeditor.cpp"