📄 ktreelist.cpp
字号:
case Key_Up: // make previous item current, scroll up if necessary if(currentItem() > 0) { setCurrentItem(currentItem() - 1); if(currentItem() < topCell()) setTopCell(currentItem()); } break; case Key_Down: // make next item current, scroll down if necessary if(currentItem() < visibleCount() - 1) { setCurrentItem(currentItem() + 1); if(currentItem() > lastRowVisible()) setTopCell(topCell() + currentItem() - lastRowVisible()); } break; case Key_Next: // move highlight one page down and scroll down delta = currentItem() - topCell(); pageSize = lastRowVisible() - topCell(); setTopCell(QMIN(topCell() + pageSize, visibleCount() - 1)); setCurrentItem(QMIN(topCell() + delta, visibleCount() - 1)); break; case Key_Prior: // move highlight one page up and scroll up delta = currentItem() - topCell(); pageSize = lastRowVisible() - topCell(); setTopCell(QMAX(topCell() - pageSize, 0)); setCurrentItem(QMAX(topCell() + delta, 0)); break; case Key_Plus: // if current item has subtree and is collapsed, expand it if(currentItem() >= 0) expandItem(currentItem()); break; case Key_Minus: // if current item has subtree and is expanded, collapse it if(currentItem() >= 0) collapseItem(currentItem()); break; case Key_Return: case Key_Enter: // select the current item if(currentItem() >= 0) emit selected(currentItem()); break; default: break; }}// move specified item down one slot in parent's subtreevoid KTreeList::lowerItem(KTreeListItem *item){ KTreeListItem *itemParent = item->getParent(); uint itemChildIndex = itemParent->childIndex(item); if(itemChildIndex < itemParent->childCount() - 1) { bool autoU = autoUpdate(); setAutoUpdate(FALSE); takeItem(item); insertItem(itemParent->childAt(itemChildIndex), item, FALSE); if(autoU && isVisible()) repaint(); setAutoUpdate(autoU); }}// handle mouse double click events by selecting the clicked item// and emitting the signalvoid KTreeList::mouseDoubleClickEvent(QMouseEvent *e){ // find out which row has been clicked QPoint mouseCoord = e->pos(); int itemClicked = findRow(mouseCoord.y()); // if a valid row was not clicked, do nothing if(itemClicked == -1) return; KTreeListItem *item = itemAt(itemClicked); if(!item) return; // translate mouse coord to cell coord int cellX, cellY; colXPos(0, &cellX); rowYPos(itemClicked, &cellY); QPoint cellCoord(mouseCoord.x() - cellX, mouseCoord.y() - cellY); // hit test item if(item->boundingRect(fontMetrics()).contains(cellCoord)) emit selected(itemClicked);}// handle mouse movement eventsvoid KTreeList::mouseMoveEvent(QMouseEvent *e){ // in rubberband_mode we actually scroll the window now if (rubberband_mode) { move_rubberband(e->pos()); }}// handle single mouse pressesvoid KTreeList::mousePressEvent(QMouseEvent *e){ // first: check which button was pressed if (e->button() == MidButton) { // RB: the MMB is hardcoded to the "rubberband" scroll mode if (!rubberband_mode) { start_rubberband(e->pos()); } return; } else if (rubberband_mode) { // another button was pressed while rubberbanding, stop the move. // RB: if we allow other buttons while rubberbanding the tree can expand // while rubberbanding - we then need to reclaculate and resize the // rubberband rect and show the new size) end_rubberband(); return; // should we process the button press? } // find out which row has been clicked QPoint mouseCoord = e->pos(); int itemClicked = findRow(mouseCoord.y()); // if a valid row was not clicked, do nothing if(itemClicked == -1) return; KTreeListItem *item = itemAt(itemClicked); if(!item) return; // translate mouse coord to cell coord int cellX, cellY; colXPos(0, &cellX); rowYPos(itemClicked, &cellY); QPoint cellCoord(mouseCoord.x() - cellX, mouseCoord.y() - cellY); // hit test item if(item->boundingRect(fontMetrics()).contains(cellCoord)){ setCurrentItem(itemClicked); emit singleSelected(itemClicked); // ettrich } // hit test expand button else if(item->hasChild()) { if(item->expandButtonClicked(cellCoord)) { expandOrCollapse(item); setCurrentItem(itemClicked); } }}// handle mouse release eventsvoid KTreeList::mouseReleaseEvent(QMouseEvent *e){ // if it's the MMB end rubberbanding if (rubberband_mode && e->button()==MidButton) { end_rubberband(); }}// rubberband move: draw the rubberbandvoid KTreeList::draw_rubberband(){ // RB: I'm using a white pen because of the XorROP mode. I would prefer to // draw the rectangle in red but I don't now how to get a pen which // draws red in XorROP mode (this depends on the background). In fact // the color should be configurable. if (!rubberband_mode) return; QPainter paint(this); paint.setPen(white); paint.setRasterOp(XorROP); paint.drawRect(xOffset()*viewWidth()/totalWidth(), yOffset()*viewHeight()/totalHeight(), rubber_width+1, rubber_height+1); paint.end();}// rubberband move: start movevoid KTreeList::start_rubberband(const QPoint& where){ if (rubberband_mode) { // Oops! end_rubberband(); } // RB: Don't now, if this check is necessary if (!viewWidth() || !viewHeight()) return; if (!totalWidth() || !totalHeight()) return; // calculate the size of the rubberband rectangle rubber_width = viewWidth()*viewWidth()/totalWidth(); if (rubber_width > viewWidth()) rubber_width = viewWidth(); rubber_height = viewHeight()*viewHeight()/totalHeight(); if (rubber_height > viewHeight()) rubber_height = viewHeight(); // remember the cursor position and the actual offset rubber_startMouse = where; rubber_startX = xOffset(); rubber_startY = yOffset(); rubberband_mode=TRUE; draw_rubberband();}// rubberband move: end movevoid KTreeList::end_rubberband(){ if (!rubberband_mode) return; draw_rubberband(); rubberband_mode = FALSE;}// rubberband move: hanlde mouse movesvoid KTreeList::move_rubberband(const QPoint& where){ if (!rubberband_mode) return; // look how much the mouse moved and calc the new scroll position QPoint delta = where - rubber_startMouse; int nx = rubber_startX + delta.x() * totalWidth() / viewWidth(); int ny = rubber_startY + delta.y() * totalHeight() / viewHeight(); // check the new position (and make it valid) if (nx < 0) nx = 0; else if (nx > maxXOffset()) nx = maxXOffset(); if (ny < 0) ny = 0; else if (ny > maxYOffset()) ny = maxYOffset(); // redraw the rubberband at the new position draw_rubberband(); setOffset(nx,ny); draw_rubberband();}// paints the cell at the specified row and col// col is ignored for now since there is only onevoid KTreeList::paintCell(QPainter *p, int row, int){ KTreeListItem *item = itemAt(row); if(!item) return; // if current item, draw highlight and item with reverse text if(current == row) { if(item->drawText()) paintHighlight(p, item); paintItem(p, item, TRUE); } // else just paint the item else paintItem(p, item, FALSE);}// paint the highlight void KTreeList::paintHighlight(QPainter *p, KTreeListItem *item){ p->save(); // save state of painter QColorGroup cg = colorGroup(); QColor fc; if(style() == WindowsStyle) fc = QApplication::winStyleHighlightColor(); else fc = cg.text(); QRect textRect = item->itemBoundingRect(p->fontMetrics()); int t,l,b,r; textRect.coords(&l, &t, &r, &b); p->fillRect(textRect, fc); // draw base highlight if(hasFocus()) { // As far as I can tell, Qt doesn't make much of a distinction between // Windows and Motif style in this particular case.// if(style() == WindowsStyle) { // draw Windows style highlight// textRect.setCoords(l - 1, t - 1, r + 1, b + 1);// p->setPen(QPen(yellow, 0, DotLine));// p->setBackgroundColor(fc);// p->setBackgroundMode(OpaqueMode);// p->drawRect(textRect);// textRect.setCoords(l - 2, t - 2, r + 2, b + 2);// p->setPen(fc);// p->drawRect(textRect);// }// else { // draw Motif style highlight// p->setBackgroundMode(OpaqueMode); textRect.setCoords(l - 2, t - 2, r + 2, b + 1); p->drawRect(textRect);// } } p->restore(); // restore painter}// paint the items contentvoid KTreeList::paintItem(QPainter *p, KTreeListItem *item, bool highlighted){ p->save(); // save state of painter QColorGroup cg = colorGroup(); item->paint(p, cg, highlighted); p->restore();}// raise the specified item up one slot in parent's subtreevoid KTreeList::raiseItem(KTreeListItem *item){ KTreeListItem *itemParent = item->getParent(); int itemChildIndex = itemParent->childIndex(item); if(itemChildIndex > 0) { bool autoU = autoUpdate(); setAutoUpdate(FALSE); takeItem(item); insertItem(itemParent->childAt(--itemChildIndex), item, TRUE); if(autoU && isVisible()) repaint(); setAutoUpdate(autoU); }}// descend the path recursively and find the item at the end if// there is oneKTreeListItem *KTreeList::recursiveFind (KTreeListItem *subRoot, KPath *path){ KTreeListItem *retVal = 0; // get the next key QString *searchString = path->pop(); KTreeListItem *currentSubTree = subRoot, *nextSubTree = 0; // iterate through all branches at same level until // we find the one we're looking for or run out while(currentSubTree) { if(strcmp(*searchString, currentSubTree->getText()) == 0) { if(path->isEmpty()) { retVal = currentSubTree; // found match and end of path nextSubTree = 0; break; } if(!currentSubTree->hasChild() && !path->isEmpty()) break; // not end of path but no more subtrees // not end of path, find next level nextSubTree = currentSubTree->getChild(); break; } // not in this branch, search next branch currentSubTree = currentSubTree->getSibling(); } // search the next level if(nextSubTree) return recursiveFind(nextSubTree, path); return retVal;}// called by setExpandLevel for each item in treebool KTreeList::setItemExpanded(KTreeListItem *item, void *){ if(item->getBranch() < expansion) { if(item->hasChild() && !item->isExpanded()) expandSubTree(item); else item->setExpanded(TRUE); } else { if(item->hasChild() && item->isExpanded()) collapseSubTree(item); else item->setExpanded(FALSE); } return FALSE;}// called by setExpandButtonDrawing for every item in treebool KTreeList::setItemExpandButtonDrawing(KTreeListItem *item, void *){ item->setDrawExpandButton(drawExpandButton); return FALSE;}// called by setIndentSpacing for every item in treebool KTreeList::setItemIndent(KTreeListItem *item, void *){ item->setIndent(indent); return FALSE;}// called by setShowItemText for every item in treebool KTreeList::setItemShowText(KTreeListItem *item, void *){ item->setDrawText(showText); return FALSE;}// called by setTreeDrawing for every item in treebool KTreeList::setItemTreeDrawing(KTreeListItem *item, void *){ item->setDrawTree(drawTree); return FALSE;}// makes the item a child of the item above it, splitting// the tree into a new branchvoid KTreeList::split(KTreeListItem *item){ KTreeListItem *itemParent = item->getParent(); int itemChildIndex = itemParent->childIndex(item); if(itemChildIndex == 0) return; bool autoU = autoUpdate(); setAutoUpdate(FALSE); takeItem(item); addChildItem(itemParent->childAt(--itemChildIndex), item); if(autoU && isVisible()) repaint(); setAutoUpdate(autoU);}// removes the item from the tree without deleting itvoid KTreeList::takeItem(KTreeListItem *item){ int index = itemIndex(item); KTreeListItem *parentItem = item->getParent(); parentItem->removeChild(item); item->setSibling(0); if(parentItem->isExpanded() || parentItem->childCount() == 0) { bool autoU = autoUpdate(); setAutoUpdate(FALSE); setNumRows(visibleCount()); // If we're not clearing the entire tree, make sure this item is not // the last one and current, or current item index will be invalid! If it // is, then set current to last item. if(!clearing) if(index == currentItem() && index > numRows() - 1) setCurrentItem(numRows() - 1); if(autoU && isVisible()) repaint(); setAutoUpdate(autoU); }}// visits each item, calculates the maximum width // and updates QTableViewvoid KTreeList::updateCellWidth(){ int maxW = 0; forEveryVisibleItem(&KTreeList::getMaxItemWidth, &maxW); setCellWidth(maxW);}#include "ktreelist.moc"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -