📄 nlistview.cpp
字号:
// position edit widget int x, y, w, h; areaFor(m_selpos).rect(&x, &y, &w, &h); int xofs= m_src->indent(m_selpos) + 4 + 18; x+= xofs; w-= xofs; m_ledit->resize(w, h); addChild(m_ledit, x, y); // show edit widget m_ledit->show(); m_ledit->setFocus(); // Global::showInputMethod();}/*! Reimplemented to respond to the user finishing to edit an entry.*/bool NListView::eventFilter(QObject *o, QEvent *e) { if(o == m_ledit) { if(e->type() == QEvent::KeyRelease || e->type() == QEvent::KeyPress) { QKeyEvent *ke= (QKeyEvent*) e; if(ke->key() == Key_Return) { if(ke->type() == QEvent::KeyPress && !ke->isAutoRepeat()) {// Global::hideInputMethod(); m_ledit->hide(); emit selectionEdited(m_ledit->text()); } return true; } } return false; } else { return QScrollView::eventFilter(o, e); }}/*! @brief Returns the index of the entry at the given vertical coordinate. @note The returned index can be greater than the number of entries.*/uint NListView::indexAt(int ypos) const { return QMAX(ypos/ m_item_height, 0);}/*! @brief Returns the area covered by the given entries. @param index Position of the first entry. @param cnt Number of entries.*/QRect NListView::areaFor(int index, int cnt) const { restrictRange(index, cnt); return QRect(0, index* m_item_height, width(), cnt* m_item_height);}void NListView::onItemsChanged(uint index, uint span) { assert(index + span <= m_src->count()); if(m_selpos >= index && m_selpos < index + span) { // restart animation m->anim_timer.stop(); m->anim_prepared= false; QTimer::singleShot(400, this, SLOT(prepareAnimation())); emit selected(m_selpos); } updateContents(areaFor(index, span));}/*! @brief Scrolls the contents so that the selected entries are visible.*/void NListView::ensureSelectionVisible() { ensureVisible(0, areaFor(m_selpos, m_selcnt).top(), 0, 2* m_item_height); ensureVisible(0, areaFor(m_selpos, m_selcnt).bottom(), 0, 2* m_item_height);}/*! @brief Handles key events for selection and activation of entries.*/void NListView::keyPressEvent(QKeyEvent *evt) { int newsel= m_selpos; switch(evt->key()) { case Key_Up : newsel--; if(newsel < 0) newsel+= m_src->count(); break; case Key_Down : newsel++; if(newsel >= (int) m_src->count()) newsel-= m_src->count(); break; case Key_PageUp : newsel-= height()/ m_item_height - 1; newsel= QMAX(newsel, 0); break; case Key_PageDown : newsel+= height()/ m_item_height - 1; newsel= QMIN(newsel, (int) m_src->count() - 1); break; case Key_Return : if(m_selpos < m_src->count() && !evt->isAutoRepeat()) { emit activated(m_selpos); return; } break; default: if(isalnum(evt->key())) { select(QChar(evt->key())); } else { evt->ignore(); } break; } if(newsel != (int) m_selpos) setSelection(newsel, 1);}void NListView::contentsMousePressEvent(QMouseEvent *evt) { if(m_ledit != NULL && m_ledit->isVisible()) { m_ledit->hide();// Global::hideInputMethod(); } m_tapped_index= indexAt(evt->y()); if(m_tapped_index < m_src->count()) { m_tapped_border= !isOnText(evt->pos()); setSelection(m_tapped_index, 1, false); }}void NListView::contentsMouseMoveEvent(QMouseEvent *evt) { // extend or reduce selection if(m_tapped_border) { uint pos= QMIN(indexAt(evt->pos().y()), m_src->count() - 1); if(pos != m_tapped_index + m_selcnt - 1 && pos >= m_tapped_index) { uint oldcnt= m_selcnt; m_selcnt= pos - m_tapped_index + 1; int start= m_tapped_index + QMIN(oldcnt, m_selcnt) - 1; updateContents(areaFor(start, QABS(int(m_selcnt) - int(oldcnt)) + 1));// QTimer::singleShot(200, this, SLOT(ensureSelectionVisible())); } }}void NListView::contentsMouseDoubleClickEvent(QMouseEvent *evt) { uint index= indexAt(evt->y()); if(index < m_src->count()) emit activated(index);}void NListView::resizeEvent(QResizeEvent *e) { if(width() > m->bgnd_pix.width()) { // prepare background pixmap m->bgnd_pix= QPixmap(width(), m_item_height); QColorGroup cg= colorGroup(); QPainter pixp(&m->bgnd_pix, this); pixp.fillRect(m->bgnd_pix.rect(), cg.base()); pixp.setPen(cg.midlight()); for(uint y= 0; y < m_item_height; y+= 3) pixp.drawLine(0, y + 1, width(), y + 1); } resizeContents(width(), m_src->count()* m_item_height); if(e->oldSize().height() != height()) { // tweak scrollbar behaviour verticalScrollBar()->setPageStep(height() - (height()% m_item_height)); emit resizedContents(contentsWidth(), contentsHeight()); ensureSelectionVisible(); }}void NListView::onItemCountChanged(uint cnt) { resizeContents(width(), cnt* m_item_height); int selpos= m_selpos, selcnt= m_selcnt; restrictRange(selpos, selcnt); if(selpos != int(m_selpos) || selcnt != int(m_selcnt)) setSelection(selpos, selcnt); updateContents(0, 0, contentsWidth(), contentsHeight()); emit resizedContents(contentsWidth(), contentsHeight());}/*! @brief Returns whether the given position is over the text of the first column. This is needed to decide whether a multiple selection is to be started.*/bool NListView::isOnText(const QPoint &pos) const { uint index= indexAt(pos.y()); if(index < m_src->count()) { int xofs= m_src->indent(index) + 4 + 18; int tlength= QFontMetrics(font()).width(m_src->text(index)); return (pos.x() < xofs + tlength) && (pos.x() < columnWidth(0) - 16); } else { return false; }}// with double bufferingvoid NListView::drawContents(QPainter *p, int, int y, int, int h) { QColorGroup cg= palette().inactive(); bool suppress_selection= !hasFocus() && cg.highlight() == cg.base(); uint start= indexAt(y); uint end= (y + h - 1)/ m_item_height; QPixmap pix(visibleWidth(), m_item_height); QPainter pixp(&pix, this); for(uint i= start; i <= end; i++) { if(i < m_src->count()) { renderItem(&pixp, i, i >= m_selpos && i < m_selpos + m_selcnt && !suppress_selection); pixp.flush(); p->drawPixmap(0, i* m_item_height, pix); } else { p->drawPixmap(0, i* m_item_height, m->bgnd_pix); } }//p->setPen(QColor(255, 0, 0));//p->drawRect(m->animr.nextHull()); if(m->animr.framesLeft()) { m->animr.nextFrame(); QTimer::singleShot(10, this, SLOT(animate())); }}/*// without double bufferingvoid NListView::drawContents(QPainter *p, int, int y, int, int h) { uint start= indexAt(y); uint end= (y + h - 1)/ m_item_height; p->translate(0, start* m_item_height); for(uint i= start; i <= end; i++) { if(i < m_src->count()) { renderItem(p, i, i >= m_selpos && i < m_selpos + m_selcnt && hasFocus()); } else { p->drawPixmap(0, 0, m->bgnd_pix); } p->translate(0, m_item_height); } p->resetXForm();}*/void NListView::renderItem(QPainter *p, uint index, bool selected) { assert(index < m_src->count()); if(selected) { QFont f= font();// f.setBold(true);// f.setPixelSize(14); p->setFont(f); } QColorGroup cg= colorGroup(); p->setPen(selected ? cg.highlightedText() : cg.text()); QFontMetrics fm(p->font()); // draw bgnd int left= 4 + m_src->indent(index); if(selected) { p->drawPixmap(0, 0, m->bgnd_pix); int tw= QMIN(columnWidth(0), fm.width(m_src->text(index)) + 18 + 2); tw= QMIN(tw, columnWidth(0) - (left - 1)); //p->fillRect(QRect(left - 1, 0, tw, m_item_height), QBrush(cg.highlight()));// AStyle::get()->drawSelection(p, QRect(left - 3, 2, tw + 3, m_item_height)); //p->drawPixmap(left + tw, 0, m->bgnd_pix); } else { p->drawPixmap(0, 0, m->bgnd_pix); } // draw selection int sx, sy, sw, sh; m->animr.currentFrame().rect(&sx, &sy, &sw, &sh); AStyle::get()->drawSelection(p, QRect(sx, sy - index* m_item_height + 2, sw, sh)); // draw icon QPixmap pix= m_src->icon(index); p->drawPixmap(left, (m_item_height - pix.height())/ 2, pix); // draw text QRect textr= QRect(left + 18, 0, columnWidth(0) - left - 18, m_item_height); if(selected && m_selcnt == 1 && hasFocus()) { p->setPen(QColor(255, 255, 0)); p->drawText(textr, AlignLeft| AlignVCenter, m_src->text(index)); } else { p->drawText(textr, AlignLeft| AlignVCenter, fitString(fm, m_src->text(index), textr.width())); } p->setPen(cg.text()); for(uint col= 1; col < m->colcnt; col++) { textr.setX(textr.x() + textr.width()); textr.setWidth(columnWidth(col)); p->drawText(textr, AlignRight| AlignVCenter, m_src->text(index, col)); } if(selected) p->setFont(font());}QRect NListView::selectionArea(QPainter *p) const { if(m_selpos >= m_src->count()) return QRect(); QFontMetrics fm(p->font()); int left= 4 + m_src->indent(m_selpos); int tw= QMIN(columnWidth(0), fm.width(m_src->text(m_selpos)) + 18 + 2); tw= QMIN(tw, columnWidth(0) - (left - 1)); return QRect(left - 3, areaFor(m_selpos).y(), tw + 3, m_item_height);}void NListView::animate() { repaintContents(m->animr.nextHull());}void NListView::prepareAnimation() { if(m->anim_prepared || m_selcnt == 0) return; QFont f= font();// f.setBold(true);// f.setPixelSize(14); QFontMetrics fm(f); QString text= m_src->text(m_selpos); m->anim_pix= QPixmap(fm.width(text), m_item_height); if(!m->anim_pix.isNull()) { QColorGroup cg= colorGroup(); QPainter p(&m->anim_pix);// p.fillRect(m->anim_pix.rect(), QBrush(cg.highlight())); AStyle::get()->drawSelection(&p, m->anim_pix.rect()); p.setFont(f); p.setPen(cg.highlightedText()); p.drawText(m->anim_pix.rect(), AlignRight| AlignVCenter, text); } m->anim_offset= 0; m->anim_delta= 1; m->anim_prepared= true; if(hasFocus()) m->anim_timer.start(50);}void NListView::animateSelection() { int left= m_src->indent(m_selpos) + 4 + 18; int maxofs= m->anim_pix.rect().width() - (columnWidth(0) - left); if(m->anim_offset > maxofs + 8) m->anim_delta= -m->anim_delta; if(m->anim_offset < -8) m->anim_delta= -m->anim_delta; m->anim_offset+= m->anim_delta; if(maxofs > 0 && m->anim_prepared) { QPoint lt(left, m_selpos* m_item_height); QRect textr(contentsToViewport(lt), QSize(columnWidth(0) - left, m_item_height)); int offset= QMAX(QMIN(m->anim_offset, maxofs), 0); QPainter p(viewport()); p.setClipRect(textr); p.drawPixmap(textr.x() - offset, textr.y(), m->anim_pix); }}void NListView::focusInEvent(QFocusEvent*) { m->anim_timer.stop(); m->anim_prepared= false; updateContents(areaFor(m_selpos, m_selcnt)); QTimer::singleShot(400, this, SLOT(prepareAnimation())); }void NListView::focusOutEvent(QFocusEvent*) { m->anim_timer.stop(); updateContents(areaFor(m_selpos, m_selcnt));}void NListView::restrictRange(int &index, int &cnt) const { if(cnt < 0) { index+= cnt + 1; cnt= -cnt; } if(index >= (int) m_src->count()) { index= m_src->count() - 1; cnt= 0; } if(index < 0) { cnt+= index; index= 0; } if(index + cnt > (int) m_src->count()) { cnt= m_src->count() - index; } if(cnt < 1) cnt= QMIN(m_src->count(), 1); assert(index >= 0 && (index + cnt <= (int) m_src->count()));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -