diff --git a/qt/eliot.qrc b/qt/eliot.qrc index 56bf4f6..a375dae 100644 --- a/qt/eliot.qrc +++ b/qt/eliot.qrc @@ -7,6 +7,7 @@ images/go-next.png images/go-last.png images/go-jump.png + images/print-preview.png images/printer.png images/preferences.png images/playlist_16px.png diff --git a/qt/images/print-preview.png b/qt/images/print-preview.png new file mode 100644 index 0000000..741c318 Binary files /dev/null and b/qt/images/print-preview.png differ diff --git a/qt/main_window.cpp b/qt/main_window.cpp index 36e8f99..9b80b77 100644 --- a/qt/main_window.cpp +++ b/qt/main_window.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -376,6 +377,7 @@ void MainWindow::updateForGame(PublicGame *iGame) if (iGame == NULL) { m_actionGameSaveAs->setEnabled(false); + m_actionGamePrintPreview->setEnabled(false); m_actionGamePrint->setEnabled(false); m_actionHistoryFirstTurn->setEnabled(false); m_actionHistoryPrevTurn->setEnabled(false); @@ -412,6 +414,7 @@ void MainWindow::updateForGame(PublicGame *iGame) } else { + m_actionGamePrintPreview->setEnabled(true); m_actionGamePrint->setEnabled(true); m_actionGameSaveAs->setEnabled(true); m_actionSettingsDefineTables->setEnabled(iGame->getMode() == PublicGame::kARBITRATION); @@ -801,6 +804,9 @@ void MainWindow::createMenu() m_actionGameSaveAs = addMenuAction(menuFile, _q("&Save as..."), _q("Ctrl+S"), _q("Save the current game"), SLOT(onGameSaveAs())); menuFile->addSeparator(); + m_actionGamePrintPreview = addMenuAction(menuFile, _q("&Print preview..."), QString(""), + _q("Print preview"), SLOT(onGamePrintPreview()), + false, QIcon(":/images/print-preview.png")); m_actionGamePrint = addMenuAction(menuFile, _q("&Print..."), _q("Ctrl+P"), _q("Print the current game"), SLOT(onGamePrint()), false, QIcon(":/images/printer.png")); @@ -1014,152 +1020,169 @@ void MainWindow::onGamePrint() QPrinter printer(QPrinter::HighResolution); QPrintDialog printDialog(&printer, this); - if (printDialog.exec() == QDialog::Accepted) + if (printDialog.exec() != QDialog::Accepted) + return; + + LOG_INFO("Printing game"); + print(&printer); +} + + +void MainWindow::onGamePrintPreview() +{ + LOG_INFO("Print preview"); + QPrintPreviewDialog previewDialog; + QObject::connect(&previewDialog, SIGNAL(paintRequested(QPrinter *)), + this, SLOT(print(QPrinter*))); + previewDialog.exec(); +} + + +void MainWindow::print(QPrinter *printer) +{ + ASSERT(m_game != NULL, "No game in progress"); + + QPainter painter(printer); + const History &history = m_game->getHistory(); + + // Printing parameters (XXX: these could be configurable by the users) + // Number of pixels virtually present on the page width. The bigger + // this number, the smaller the print result + static const int TOTAL_WIDTH = 700; + // Distance between 2 horizontal lines + static const int LINE_HEIGHT = 16; + // Font size, in pixels + static const int FONT_SIZE = 10; + // Width of the pen used to draw the grid lines + static const int PEN_WIDTH = 1; + // Offset of the text from the previous vertical line, in pixels + static const int TEXT_OFFSET = 10; + // Indicate whether the rack and the solution should be aligned + static const bool SHOULD_ALIGN = false; + // Columns widths + static const int colWidths[] = { 30, 120, 120, 35, 35 }; + // Columns titles + static const char *colTitles[] = { _("N."), _("RACK"), _("SOLUTION"), _("REF"), _("PTS") }; + + static const unsigned int nbCols = sizeof(colWidths) / sizeof(int); + const unsigned int nbRows = history.getSize() + (SHOULD_ALIGN ? 1 : 2); + + double scale = printer->pageRect().width() / double(TOTAL_WIDTH); + painter.scale(scale, scale); + + QPen pen(painter.pen()); + pen.setWidth(PEN_WIDTH); + painter.setPen(pen); + + QFont font; + font.setPixelSize(FONT_SIZE); + painter.setFont(font); + + int maxRight = 0; + for (unsigned int i = 0; i < nbCols; ++i) + maxRight += colWidths[i]; + int maxBottom = LINE_HEIGHT * (nbRows + 1); + + // Draw the horizontal lines + for (unsigned int i = 0; i <= nbRows + 1; ++i) + painter.drawLine(0, LINE_HEIGHT * i, maxRight, LINE_HEIGHT * i); + + // Draw the vertical lines + painter.drawLine(0, 0, 0, maxBottom); + int curWidth = 0; + for (unsigned int i = 0; i < nbCols; ++i) { - LOG_INFO("Printing game"); - - QPainter painter(&printer); - const History &history = m_game->getHistory(); - - // Printing parameters (XXX: these could be configurable by the users) - // Number of pixels virtually present on the page width. The bigger - // this number, the smaller the print result - static const int TOTAL_WIDTH = 700; - // Distance between 2 horizontal lines - static const int LINE_HEIGHT = 16; - // Font size, in pixels - static const int FONT_SIZE = 10; - // Width of the pen used to draw the grid lines - static const int PEN_WIDTH = 1; - // Offset of the text from the previous vertical line, in pixels - static const int TEXT_OFFSET = 10; - // Indicate whether the rack and the solution should be aligned - static const bool SHOULD_ALIGN = false; - // Columns widths - static const int colWidths[] = { 30, 120, 120, 35, 35 }; - // Columns titles - static const char *colTitles[] = { _("N."), _("RACK"), _("SOLUTION"), _("REF"), _("PTS") }; - - static const unsigned int nbCols = sizeof(colWidths) / sizeof(int); - const unsigned int nbRows = history.getSize() + (SHOULD_ALIGN ? 1 : 2); - - double scale = printer.pageRect().width() / double(TOTAL_WIDTH); - painter.scale(scale, scale); - - QPen pen(painter.pen()); - pen.setWidth(PEN_WIDTH); - painter.setPen(pen); - - QFont font; - font.setPixelSize(FONT_SIZE); - painter.setFont(font); - - int maxRight = 0; - for (unsigned int i = 0; i < nbCols; ++i) - maxRight += colWidths[i]; - int maxBottom = LINE_HEIGHT * (nbRows + 1); - - // Draw the horizontal lines - for (unsigned int i = 0; i <= nbRows + 1; ++i) - painter.drawLine(0, LINE_HEIGHT * i, maxRight, LINE_HEIGHT * i); - - // Draw the vertical lines - painter.drawLine(0, 0, 0, maxBottom); - int curWidth = 0; - for (unsigned int i = 0; i < nbCols; ++i) - { - curWidth += colWidths[i]; - painter.drawLine(curWidth, 0, curWidth, maxBottom); - } - - // Draw the titles - QFontMetrics fm = painter.fontMetrics(); - int textHeight = fm.boundingRect('A').height(); - curWidth = 0; - int curHeight = (LINE_HEIGHT + textHeight + 1) / 2; - for (unsigned int i = 0; i < nbCols; ++i) - { - int textWidth = fm.width(colTitles[i]); - painter.drawText(curWidth + (colWidths[i] - textWidth) / 2, - curHeight, colTitles[i]); - curWidth += colWidths[i]; - } - - // Draw the history of the game - int score = 0; - int nextHeight; - if (SHOULD_ALIGN) - nextHeight = curHeight; - else - nextHeight = curHeight + LINE_HEIGHT; - for (unsigned int i = 0; i < history.getSize(); ++i) - { - const TurnData &t = history.getTurn(i); - const Move &m = t.getMove(); - - curWidth = TEXT_OFFSET; - curHeight += LINE_HEIGHT; - nextHeight += LINE_HEIGHT; - - // Turn number - painter.drawText(curWidth, curHeight, QString("%1").arg(i + 1)); - curWidth += colWidths[0]; - - // Rack - painter.drawText(curWidth, curHeight, - qfw(t.getPlayedRack().toString())); - curWidth += colWidths[1]; - - // Word and coordinates - if (m.isValid()) - { - const Round &r = m.getRound(); - painter.drawText(curWidth, nextHeight, qfw(r.getWord())); - curWidth += colWidths[2]; - painter.drawText(curWidth, nextHeight, - qfw(r.getCoord().toString())); - curWidth += colWidths[3]; - } - else if (m.isInvalid()) - { - painter.drawText(curWidth, nextHeight, - "<" + qfw(m.getBadWord()) + ">"); - curWidth += colWidths[2]; - painter.drawText(curWidth, nextHeight, qfw(m.getBadCoord())); - curWidth += colWidths[3]; - } - else if (m.isNull()) - { - painter.drawText(curWidth, nextHeight, _q("(NO MOVE)")); - curWidth += colWidths[2]; - curWidth += colWidths[3]; - } - else if (m.isPass()) - { - painter.drawText(curWidth, nextHeight, _q("(PASS)")); - curWidth += colWidths[2]; - curWidth += colWidths[3]; - } - else - { - painter.drawText(curWidth, nextHeight, - "[-" + qfw(m.getChangedLetters()) + "]"); - curWidth += colWidths[2]; - curWidth += colWidths[3]; - } - - // Score - painter.drawText(curWidth, nextHeight, - QString("%1").arg(m.getScore())); - score += m.getScore(); - } - - // Total score - nextHeight += LINE_HEIGHT; - painter.drawText(curWidth, nextHeight, QString("%1").arg(score)); - - LOG_INFO("Game printed"); + curWidth += colWidths[i]; + painter.drawLine(curWidth, 0, curWidth, maxBottom); } + + // Draw the titles + QFontMetrics fm = painter.fontMetrics(); + int textHeight = fm.boundingRect('A').height(); + curWidth = 0; + int curHeight = (LINE_HEIGHT + textHeight + 1) / 2; + for (unsigned int i = 0; i < nbCols; ++i) + { + int textWidth = fm.width(colTitles[i]); + painter.drawText(curWidth + (colWidths[i] - textWidth) / 2, + curHeight, colTitles[i]); + curWidth += colWidths[i]; + } + + // Draw the history of the game + int score = 0; + int nextHeight; + if (SHOULD_ALIGN) + nextHeight = curHeight; + else + nextHeight = curHeight + LINE_HEIGHT; + for (unsigned int i = 0; i < history.getSize(); ++i) + { + const TurnData &t = history.getTurn(i); + const Move &m = t.getMove(); + + curWidth = TEXT_OFFSET; + curHeight += LINE_HEIGHT; + nextHeight += LINE_HEIGHT; + + // Turn number + painter.drawText(curWidth, curHeight, QString("%1").arg(i + 1)); + curWidth += colWidths[0]; + + // Rack + painter.drawText(curWidth, curHeight, + qfw(t.getPlayedRack().toString())); + curWidth += colWidths[1]; + + // Word and coordinates + if (m.isValid()) + { + const Round &r = m.getRound(); + painter.drawText(curWidth, nextHeight, qfw(r.getWord())); + curWidth += colWidths[2]; + painter.drawText(curWidth, nextHeight, + qfw(r.getCoord().toString())); + curWidth += colWidths[3]; + } + else if (m.isInvalid()) + { + painter.drawText(curWidth, nextHeight, + "<" + qfw(m.getBadWord()) + ">"); + curWidth += colWidths[2]; + painter.drawText(curWidth, nextHeight, qfw(m.getBadCoord())); + curWidth += colWidths[3]; + } + else if (m.isNull()) + { + painter.drawText(curWidth, nextHeight, _q("(NO MOVE)")); + curWidth += colWidths[2]; + curWidth += colWidths[3]; + } + else if (m.isPass()) + { + painter.drawText(curWidth, nextHeight, _q("(PASS)")); + curWidth += colWidths[2]; + curWidth += colWidths[3]; + } + else + { + painter.drawText(curWidth, nextHeight, + "[-" + qfw(m.getChangedLetters()) + "]"); + curWidth += colWidths[2]; + curWidth += colWidths[3]; + } + + // Score + painter.drawText(curWidth, nextHeight, + QString("%1").arg(m.getScore())); + score += m.getScore(); + } + + // Total score + nextHeight += LINE_HEIGHT; + painter.drawText(curWidth, nextHeight, QString("%1").arg(score)); + + LOG_INFO("Game printed"); } diff --git a/qt/main_window.h b/qt/main_window.h index a8190dc..7c4a39b 100644 --- a/qt/main_window.h +++ b/qt/main_window.h @@ -48,6 +48,7 @@ class AuxWindow; class TimerModel; class QLabel; class QAction; +class QPrinter; class MainWindow: public QMainWindow { @@ -75,6 +76,7 @@ private slots: void onGameLoad(); void onGameLoadAutoSave(); void onGameSaveAs(); + void onGamePrintPreview(); void onGamePrint(); void onGameQuit(); void onSettingsChooseDic(); @@ -97,6 +99,9 @@ private slots: void onHistoryLastTurn(); void onHistoryReplayTurn(); + /// Print the game using the given printer + void print(QPrinter *printer); + /// Simply emit a beep with the system speakers void beep(); @@ -158,6 +163,7 @@ private: ScoreWidget *m_scoresWidget; /// Actions enabled or disabled depending on the game state + QAction *m_actionGamePrintPreview; QAction *m_actionGamePrint; QAction *m_actionGameSaveAs; QAction *m_actionHistoryPrevTurn;