/* * Quackle -- Crossword game artificial intelligence and analysis tool * Copyright (C) 2005-2019 Jason Katz-Brown, John O'Laughlin, and John Fultz. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include "history.h" #include "geometry.h" History::History(QWidget *parent) : HistoryView(parent) { m_vlayout = new QVBoxLayout(this); Geometry::setupFramedLayout(m_vlayout); m_tableWidget = new QTableWidget(this); m_tableWidget->setHorizontalScrollMode(QTableView::ScrollPerPixel); connect(m_tableWidget, SIGNAL(itemActivated(QTableWidgetItem *)), this, SLOT(itemActivated(QTableWidgetItem *))); setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); m_vlayout->addWidget(m_tableWidget); } void History::historyChanged(const Quackle::History &history) { m_tableWidget->clear(); const Quackle::PlayerList players(history.players()); QStringList columnLabels; QStringList rowLabels; for (int i = 1; i <= history.maximumTurnNumber(); ++i) rowLabels.push_back(QString::number(i)); Quackle::GamePosition lastPosition(history.lastPosition()); lastPosition.setCurrentPlayer(lastPosition.playerOnTurn().id()); const bool gameOver = lastPosition.gameOver(); if (gameOver) rowLabels.push_back(tr("Final")); m_tableWidget->setRowCount(rowLabels.size()); m_tableWidget->setColumnCount((int)players.size()); Quackle::PlayerList currentScores(lastPosition.endgameAdjustedScores()); QTableWidgetItem *currentItem = 0; int playerCountFromZero = 0; Quackle::PlayerList::const_iterator currentScoresIt = currentScores.begin(); for (Quackle::PlayerList::const_iterator it = players.begin(); it != players.end(); ++it, ++currentScoresIt, ++playerCountFromZero) { columnLabels.push_back(QuackleIO::Util::uvStringToQString((*it).name())); const Quackle::PositionList positions(history.positionsFacedBy((*it).id())); for (Quackle::PositionList::const_iterator pit = positions.begin(); pit != positions.end(); ++pit) { QTableWidgetItem *item = createItem(*pit, history.currentPosition().currentPlayer()); const int row = /* make zero indexed */ (*pit).turnNumber() - 1; const int column = playerCountFromZero; m_tableWidget->setItem(row, column, item); Quackle::HistoryLocation location((*it).id(), (*pit).turnNumber()); m_locationMap.insert(location, item); if (location == history.currentLocation()) { currentItem = m_tableWidget->item(row, column); m_tableWidget->setCurrentItem(currentItem); } } if (gameOver) { QString scoreString(QString::number((*currentScoresIt).score())); QTableWidgetItem *item = createPlainItem(scoreString); m_tableWidget->setItem(rowLabels.size() - 1, playerCountFromZero, item); if (history.currentPosition().gameOver()) currentItem = item; } if (!positions.empty()) m_tableWidget->resizeColumnToContents(playerCountFromZero); } m_tableWidget->setHorizontalHeaderLabels(columnLabels); m_tableWidget->setVerticalHeaderLabels(rowLabels); m_tableWidget->scrollToItem(currentItem); } QTableWidgetItem *History::createItem(const Quackle::GamePosition &position, const Quackle::Player ¤tPlayer) { const Quackle::Move committedMove(position.committedMove()); QString contentString; if (committedMove.action == Quackle::Move::Nonmove) contentString = tr("*TO PLAY*"); else { const QString moveString = (position.currentPlayer() == currentPlayer? QuackleIO::Util::moveToDetailedString(committedMove) : QuackleIO::Util::moveToSensitiveString(committedMove)); const int score = position.currentPlayer().score() + committedMove.effectiveScore(); const QString scoreString = QString("+%2/%3").arg(committedMove.effectiveScore()).arg(score); // Pad scoreString to 8 chars, because '+117/381' is 8 chars, and this // helps the words kinda line up with each other. contentString = QString("%1 %2").arg(moveString).arg(scoreString, 8); } return createPlainItem(contentString); } QTableWidgetItem *History::createPlainItem(const QString &contentString) { QTableWidgetItem *ret = new QTableWidgetItem(contentString); ret->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); // make scores line up with each other ret->setTextAlignment(Qt::AlignRight); return ret; } void History::itemActivated(QTableWidgetItem *item) { for (QMap::iterator it = m_locationMap.begin(); it != m_locationMap.end(); ++it) { if (it.value() == item) { emit goToHistoryLocation(&it.key()); break; } } }