/** * @file PaiLineEdit.cpp * @brief PaiLineEdit是P.A.I系统定制发布的单行文本框控件 * @date 2011-10-21 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "PaiLineEdit.h" #include "SmartCompleter.h" using namespace pai::gui; #define DEFAULT_HEIGHT 18 ///< 默认高度 PaiLineEdit::PaiLineEdit(QWidget *pParent) : QLineEdit(pParent) { Init(); } PaiLineEdit::PaiLineEdit(const QString & strText, QWidget *pParent) : QLineEdit(strText, pParent) { Init(); } void PaiLineEdit::InsertCompletion(const QString& completion) { setText(completion); selectAll(); } void PaiLineEdit::SetSmartCompleter(pai::SmartCompleter *pComleter) { if (m_pCompleter) { QObject::disconnect(m_pCompleter, 0, this, 0); } m_pCompleter = pComleter; if (!m_pCompleter) { return; } m_pCompleter->setWidget(this); connect(m_pCompleter, SIGNAL(activated(const QString&)), this, SLOT(InsertCompletion(const QString&))); } pai::SmartCompleter *PaiLineEdit::SmartCompleter() const { return m_pCompleter; } void PaiLineEdit::Init() { m_pCompleter = NULL; m_PromptType = PT_NULL; m_pDelayTimer = new QTimer(this); m_pDelayTimer->setInterval(300); this->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop); m_pRightPBtn = NULL; setMinimumHeight(DEFAULT_HEIGHT); // 该值不在style sheet中设置,否则会造成其它位置不能设置该值 connect(this, SIGNAL(editingFinished()), this, SLOT(TextEditingFinished())); connect(this, SIGNAL(textChanged(const QString&)), m_pDelayTimer, SLOT(start())); connect(m_pDelayTimer, SIGNAL(timeout()), this, SLOT(EmitEditingStoped())); } void PaiLineEdit::SetRightIcon(const QString & iconPath) { QPixmap pixmap(iconPath); // 添加右边按钮控件 if(m_pRightPBtn == NULL) { m_pRightPBtn = new QPushButton; } m_pRightPBtn->setIcon(QIcon(pixmap)); QSize size = QSize(pixmap.size().width() + 6, pixmap.size().height() + 4); m_pRightPBtn->setMinimumSize(size); m_pRightPBtn->setMaximumSize(size); // 设置按钮的大小为图片的大小 m_pRightPBtn->setFocusPolicy(Qt::NoFocus); // 得到焦点的时候,不显示虚线框 m_pRightPBtn->setFlat(true); m_pRightPBtn->setDefault(true); QHBoxLayout *pHLayout = new QHBoxLayout(); pHLayout->setContentsMargins(0, 0, 0, 0); pHLayout->addStretch(); pHLayout->addWidget(m_pRightPBtn); // 设置输入框中文件输入区, 不让输入的文字被藏在按钮下 setLayout(pHLayout); setTextMargins(0, 1, pixmap.size().width(), 1); // 触发信号 connect(m_pRightPBtn, SIGNAL(clicked()), this, SIGNAL(RightIconClicked())); } void PaiLineEdit::SetValidatorFailureMessage(const QString & validateFailure) { m_ValidateMessage = validateFailure; } void PaiLineEdit::SetExceedMaxLengthMessage(const QString & exceedMaxLength) { m_ExceedMaxLengthMessage = exceedMaxLength; } void PaiLineEdit::setPlaceholderText(const QString & text) { m_PlaceholderText = text; } QString PaiLineEdit::placeholderText() const { return m_PlaceholderText; } void PaiLineEdit::paintEvent(QPaintEvent *pEvent) { QPainter p(this); QLineEdit::paintEvent(pEvent); QPainter painter(this); // draw placeholder text as needed if(!m_PlaceholderText.isEmpty() && text().isEmpty()) { QRect phRect = rect(); phRect.adjust(4, 0, 0, 0); painter.setPen(Qt::gray); painter.drawText(phRect, Qt::AlignTop | Qt::AlignLeft, m_PlaceholderText); } // 当错误模式时显示红线,请勿使用style sheet来设置,以避免重复设置带来的问题 if(m_PromptType == PT_Error) { painter.setPen(QColor("#CC0000")); painter.drawRect(rect().adjusted(0, 0, -1, -1)); } } void PaiLineEdit::keyReleaseEvent(QKeyEvent *pEvent) { QLineEdit::keyReleaseEvent(pEvent); } void PaiLineEdit::keyPressEvent(QKeyEvent *pEvent) { QString orgText = text();//输入前的文本 int selStart = selectionStart();//输入前选中文本的偏移量 int cursPos = cursorPosition();//输入前鼠标所在文本位置偏移量 QString selText = selectedText();//输入前选中文本 if (m_pCompleter && m_pCompleter->popup()->isVisible()) { // The following keys are forwarded by the completer to the widget switch (pEvent->key()) { case Qt::Key_Enter: case Qt::Key_Return: case Qt::Key_Escape: case Qt::Key_Tab: case Qt::Key_Backtab: pEvent->ignore(); return; // Let the completer do default behavior break; default: break; } } QLineEdit::keyPressEvent(pEvent); // Don't send the shortcut (CTRL-E) to the text edit. if (m_pCompleter != NULL && (pEvent->key() != Qt::Key_Alt)) { m_pCompleter->Update(text()); m_pCompleter->popup()->setCurrentIndex(m_pCompleter->completionModel()->index(0, 0)); } if((pEvent->key() == Qt::Key_Backspace) || (pEvent->key() == Qt::Key_Delete)) { return; } if(((pEvent->key() == Qt::Key_C) || (pEvent->key() == Qt::Key_A) || (pEvent->key() == Qt::Key_Z) || (pEvent->key() == Qt::Key_S)) && (pEvent->modifiers() & Qt::ControlModifier)) { return; } if(!((pEvent->key() == Qt::Key_V) && (pEvent->modifiers() & Qt::ControlModifier))) { CheckInput(pEvent->text()); } if((pEvent->key() == Qt::Key_V) && (pEvent->modifiers() & Qt::ControlModifier)) { QClipboard *pClipboard = QApplication::clipboard(); if(selStart == -1) { // 全部粘贴成功 if(orgText.insert(cursPos, pClipboard->text()) == text()) { return; } if(orgText.size() > maxLength()) { ShowPromptMessge(m_ExceedMaxLengthMessage, PaiLineEdit::PT_Warning); return; } } else { // 全部替换成功 orgText.remove(selStart, selText.size()); if(orgText.insert(selStart, pClipboard->text()) == text()) { return; } if(orgText.size() > maxLength()) { ShowPromptMessge(m_ExceedMaxLengthMessage, PaiLineEdit::PT_Warning); return; } } } // 处理键盘的上下键和回车键 DealDirectionKey(pEvent->key()); } void PaiLineEdit::TextEditingFinished() { emit EditingStoped(text()); emit EditingFinished(text()); } PaiLineEdit::~PaiLineEdit() { int a; } void PaiLineEdit::inputMethodEvent(QInputMethodEvent *pEvent) { QLineEdit::inputMethodEvent(pEvent); if (m_pCompleter != NULL) { m_pCompleter->Update(text()); m_pCompleter->popup()->setCurrentIndex(m_pCompleter->completionModel()->index(0, 0)); } CheckInput(pEvent->commitString()); } void PaiLineEdit::CheckInput(const QString & inputText) { QString ckText = text() + inputText; const QValidator *pValidator = validator(); int pos = cursorPosition(); if(ckText.size() > maxLength()) { ShowPromptMessge(m_ExceedMaxLengthMessage, PaiLineEdit::PT_Warning); } else if(pValidator && (pValidator->validate(ckText, pos) == QValidator::Invalid)) { ShowPromptMessge(m_ValidateMessage, PaiLineEdit::PT_Warning); } } void PaiLineEdit::ShowPromptMessge(const QString & message, PromptType type) { m_PromptMessage = message; m_PromptType = type; } void PaiLineEdit::EmitEditingStoped() { m_pDelayTimer->stop(); emit EditingStoped(text()); } QSize PaiLineEdit::sizeHint() const { QSize LineEditSizeHint = QLineEdit::sizeHint(); QFontMetrics fontWidth(font()); return QSize(fontWidth.width(m_ExceedMaxLengthMessage) + 30, LineEditSizeHint.height()); } void PaiLineEdit::mousePressEvent(QMouseEvent *pEvent) { if(pEvent->button() == Qt::LeftButton) { emit LeftMousePress(); } QLineEdit::mousePressEvent(pEvent); } bool PaiLineEdit::IsEmpty() { return text().isEmpty(); } void PaiLineEdit::SetEditStopDuration(int duration) { m_pDelayTimer->setInterval(duration); } void PaiLineEdit::DealDirectionKey(int key) { QCompleter *pCompleter = m_pCompleter != NULL ? m_pCompleter : completer(); if(pCompleter) { QAbstractItemView *pPopupView = pCompleter->popup(); if(pPopupView && !pPopupView->isHidden()) { // int key = event->key(); int count = pPopupView->model()->rowCount(); QModelIndex currentIndex = pPopupView->currentIndex(); if(Qt::Key_Down == key) { // 按向下方向键时,移动光标选中下一个完成列表中的项 int row = currentIndex.row() + 1; if(row >= count) { row = 0; } QModelIndex index = pPopupView->model()->index(row, 0); pPopupView->setCurrentIndex(index); } else if(Qt::Key_Up == key) { // 按向下方向键时,移动光标选中上一个完成列表中的项 int row = currentIndex.row() - 1; if(row < 0) { row = count - 1; } QModelIndex index = pPopupView->model()->index(row, 0); pPopupView->setCurrentIndex(index); } else if(Qt::Key_Escape == key) { // 按下Esc键时,隐藏完成列表 pPopupView->hide(); } else if((Qt::Key_Enter == key) || (Qt::Key_Return == key)) { // 按下回车键时,使用完成列表中选中的项,并隐藏完成列表 if(currentIndex.isValid()) { QString text = pPopupView->currentIndex().data().toString(); setText(text); } pPopupView->hide(); } } else { // 其他情况,隐藏完成列表,并使用QLineEdit的键盘按下事件 pPopupView->hide(); } } } void PaiLineEdit::contextMenuEvent(QContextMenuEvent *pEvent) { QString orgText = text();//输入前的文本 int selStart = selectionStart();//输入前选中文本的偏移量 int cursPos = cursorPosition();//输入前鼠标所在文本位置偏移量 QString selText = selectedText();//输入前选中文本 //系统默认的右键菜单 QMenu *pDefaultMenu = createStandardContextMenu(); if(pDefaultMenu) { //菜单中被选中的action QAction *pSelectedAction = pDefaultMenu->exec(pEvent->globalPos()); if(pSelectedAction) { QString actionText = pSelectedAction->iconText(); if(actionText.contains(tr("Paste")) || actionText.contains(tr("Ctrl+V"))) { QClipboard *pClipboard = QApplication::clipboard(); if(selStart == -1) { // 粘贴板中内容插入文本框 if(orgText.insert(cursPos, pClipboard->text()) == text()) { delete pDefaultMenu; pDefaultMenu = NULL; return; } // 粘贴后输入框中内容长度大于100显示警告 if(orgText.size() > maxLength()) { ShowPromptMessge(m_ExceedMaxLengthMessage, PaiLineEdit::PT_Warning); delete pDefaultMenu; pDefaultMenu = NULL; return; } } else { // 移除鼠标选中的文本,插入粘贴板中的文本 orgText.remove(selStart, selText.size()); if(orgText.insert(selStart, pClipboard->text()) == text()) { delete pDefaultMenu; pDefaultMenu = NULL; return; } // 粘贴后输入框中内容长度大于100显示警告 if(orgText.size() > maxLength()) { ShowPromptMessge(m_ExceedMaxLengthMessage, PaiLineEdit::PT_Warning); delete pDefaultMenu; pDefaultMenu = NULL; return; } } // 校验是否有不合法的字符 const QValidator *pValidator = validator(); int pos = cursorPosition(); if(pValidator && (pValidator->validate(orgText, pos) == QValidator::Invalid)) { ShowPromptMessge(m_ValidateMessage, PaiLineEdit::PT_Warning); } } } } delete pDefaultMenu; pDefaultMenu = NULL; }