-void ChatScene::setHandleXLimits() {
- _firstColHandle->setXLimits(0, _secondColHandle->sceneLeft());
- _secondColHandle->setXLimits(_firstColHandle->sceneRight(), width() - minContentsWidth);
-}
-
-void ChatScene::setSelectingItem(ChatItem *item) {
- if(_selectingItem) _selectingItem->clearSelection();
- _selectingItem = item;
-}
-
-void ChatScene::startGlobalSelection(ChatItem *item, const QPointF &itemPos) {
- _selectionStart = _selectionEnd = _firstSelectionRow = item->row();
- _selectionStartCol = _selectionMinCol = item->column();
- _isSelecting = true;
- _lines[_selectionStart]->setSelected(true, (ChatLineModel::ColumnType)_selectionMinCol);
- updateSelection(item->mapToScene(itemPos));
-}
-
-void ChatScene::updateSelection(const QPointF &pos) {
- // This is somewhat hacky... we look at the contents item that is at the cursor's y position (ignoring x), since
- // it has the full height. From this item, we can then determine the row index and hence the ChatLine.
- ChatItem *contentItem = static_cast<ChatItem *>(itemAt(QPointF(_secondColHandle->sceneRight() + 1, pos.y())));
- if(!contentItem) return;
-
- int curRow = contentItem->row();
- int curColumn;
- if(pos.x() > _secondColHandle->sceneRight()) curColumn = ChatLineModel::ContentsColumn;
- else if(pos.x() > _firstColHandlePos) curColumn = ChatLineModel::SenderColumn;
- else curColumn = ChatLineModel::TimestampColumn;
-
- ChatLineModel::ColumnType minColumn = (ChatLineModel::ColumnType)qMin(curColumn, _selectionStartCol);
- if(minColumn != _selectionMinCol) {
- _selectionMinCol = minColumn;
- for(int l = qMin(_selectionStart, _selectionEnd); l <= qMax(_selectionStart, _selectionEnd); l++) {
- _lines[l]->setSelected(true, minColumn);
- }
- }
- int newstart = qMin(curRow, _firstSelectionRow);
- int newend = qMax(curRow, _firstSelectionRow);
- if(newstart < _selectionStart) {
- for(int l = newstart; l < _selectionStart; l++)
- _lines[l]->setSelected(true, minColumn);
- }
- if(newstart > _selectionStart) {
- for(int l = _selectionStart; l < newstart; l++)
- _lines[l]->setSelected(false);
- }
- if(newend > _selectionEnd) {
- for(int l = _selectionEnd+1; l <= newend; l++)
- _lines[l]->setSelected(true, minColumn);
- }
- if(newend < _selectionEnd) {
- for(int l = newend+1; l <= _selectionEnd; l++)
- _lines[l]->setSelected(false);
- }
-
- _selectionStart = newstart;
- _selectionEnd = newend;
-
- if(newstart == newend && minColumn == ChatLineModel::ContentsColumn) {
- if(!_selectingItem) {
- // _selectingItem has been removed already
- return;
- }
- _lines[curRow]->setSelected(false);
- _isSelecting = false;
- _selectingItem->continueSelecting(_selectingItem->mapFromScene(pos));
- }
-}
-
-bool ChatScene::isScrollingAllowed() const {
- if(_isSelecting)
+
+void ChatScene::secondHandlePositionChanged(qreal xpos)
+{
+ if (_secondColHandlePos == xpos)
+ return;
+
+ _secondColHandlePos = xpos;
+ ChatViewSettings viewSettings(this);
+ viewSettings.setValue("SecondColumnHandlePos", _secondColHandlePos);
+ ChatViewSettings defaultSettings;
+ defaultSettings.setValue("SecondColumnHandlePos", _secondColHandlePos);
+
+ // clock_t startT = clock();
+
+ // disabling the index while doing this complex updates is about
+ // 2 to 10 times faster!
+ //setItemIndexMethod(QGraphicsScene::NoIndex);
+
+ QList<ChatLine *>::iterator lineIter = _lines.end();
+ QList<ChatLine *>::iterator lineIterBegin = _lines.begin();
+ qreal linePos = _sceneRect.y() + _sceneRect.height();
+ qreal senderWidth = secondColumnHandle()->sceneLeft() - firstColumnHandle()->sceneRight();
+ qreal contentsWidth = _sceneRect.width() - secondColumnHandle()->sceneRight();
+ QPointF contentsPos(secondColumnHandle()->sceneRight(), 0);
+ while (lineIter != lineIterBegin) {
+ lineIter--;
+ (*lineIter)->setSecondColumn(senderWidth, contentsWidth, contentsPos, linePos);
+ }
+ //setItemIndexMethod(QGraphicsScene::BspTreeIndex);
+
+ updateSceneRect();
+ setHandleXLimits();
+ emit layoutChanged();
+
+// clock_t endT = clock();
+// qDebug() << "resized" << _lines.count() << "in" << (float)(endT - startT) / CLOCKS_PER_SEC << "sec";
+}
+
+
+void ChatScene::setHandleXLimits()
+{
+ _firstColHandle->setXLimits(0, _secondColHandle->sceneLeft());
+ _secondColHandle->setXLimits(_firstColHandle->sceneRight(), width() - minContentsWidth);
+ update();
+}
+
+
+void ChatScene::setSelectingItem(ChatItem *item)
+{
+ if (_selectingItem) _selectingItem->clearSelection();
+ _selectingItem = item;
+}
+
+
+void ChatScene::startGlobalSelection(ChatItem *item, const QPointF &itemPos)
+{
+ _selectionStart = _selectionEnd = _firstSelectionRow = item->row();
+ _selectionStartCol = _selectionMinCol = item->column();
+ _isSelecting = true;
+ _lines[_selectionStart]->setSelected(true, (ChatLineModel::ColumnType)_selectionMinCol);
+ updateSelection(item->mapToScene(itemPos));
+}
+
+
+void ChatScene::updateSelection(const QPointF &pos)
+{
+ int curRow = rowByScenePos(pos);
+ if (curRow < 0) return;
+ int curColumn = (int)columnByScenePos(pos);
+ ChatLineModel::ColumnType minColumn = (ChatLineModel::ColumnType)qMin(curColumn, _selectionStartCol);
+ if (minColumn != _selectionMinCol) {
+ _selectionMinCol = minColumn;
+ for (int l = qMin(_selectionStart, _selectionEnd); l <= qMax(_selectionStart, _selectionEnd); l++) {
+ _lines[l]->setSelected(true, minColumn);
+ }
+ }
+ int newstart = qMin(curRow, _firstSelectionRow);
+ int newend = qMax(curRow, _firstSelectionRow);
+ if (newstart < _selectionStart) {
+ for (int l = newstart; l < _selectionStart; l++)
+ _lines[l]->setSelected(true, minColumn);
+ }
+ if (newstart > _selectionStart) {
+ for (int l = _selectionStart; l < newstart; l++)
+ _lines[l]->setSelected(false);
+ }
+ if (newend > _selectionEnd) {
+ for (int l = _selectionEnd+1; l <= newend; l++)
+ _lines[l]->setSelected(true, minColumn);
+ }
+ if (newend < _selectionEnd) {
+ for (int l = newend+1; l <= _selectionEnd; l++)
+ _lines[l]->setSelected(false);
+ }
+
+ _selectionStart = newstart;
+ _selectionEnd = newend;
+
+ if (newstart == newend && minColumn == ChatLineModel::ContentsColumn) {
+ if (!_selectingItem) {
+ // _selectingItem has been removed already
+ return;
+ }
+ _lines[curRow]->setSelected(false);
+ _isSelecting = false;
+ _selectionStart = -1;
+ _selectingItem->continueSelecting(_selectingItem->mapFromScene(pos));
+ }
+}
+
+
+bool ChatScene::isPosOverSelection(const QPointF &pos) const
+{
+ ChatItem *chatItem = chatItemAt(pos);
+ if (!chatItem)
+ return false;
+ if (hasGlobalSelection()) {
+ int row = chatItem->row();
+ if (row >= qMin(_selectionStart, _selectionEnd) && row <= qMax(_selectionStart, _selectionEnd))
+ return columnByScenePos(pos) >= _selectionMinCol;
+ }
+ else {
+ return chatItem->isPosOverSelection(chatItem->mapFromScene(pos));
+ }