"Fossies" - the Fresh Open Source Software Archive

Member "src/mainwindow.cpp" (28 Sep 2008, 31860 Bytes) of package /windows/misc/PosteRazor-1.9.5-Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "mainwindow.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2     PosteRazor - Make your own poster!
    3     Copyright (C) 2005-2008 by Alessandro Portale
    4     http://posterazor.sourceforge.net/
    5 
    6     This file is part of PosteRazor
    7 
    8     PosteRazor is free software; you can redistribute it and/or modify
    9     it under the terms of the GNU General Public License as published by
   10     the Free Software Foundation, either version 3 of the License, or
   11     (at your option) any later version.
   12 
   13     PosteRazor is distributed in the hope that it will be useful,
   14     but WITHOUT ANY WARRANTY; without even the implied warranty of
   15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16     GNU General Public License for more details.
   17 
   18     You should have received a copy of the GNU General Public License
   19     along with PosteRazor; if not, write to the Free Software
   20     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
   21 */
   22 
   23 #include "mainwindow.h"
   24 #include <QSignalMapper>
   25 #include <QFileDialog>
   26 #include <QTranslator>
   27 #include <QtDebug>
   28 #include <QVBoxLayout>
   29 #include <QDialogButtonBox>
   30 #include <QTextBrowser>
   31 #include <QMessageBox>
   32 
   33 static QString applicationNameWithVersion()
   34 {
   35     return
   36         QCoreApplication::applicationName()
   37 #if QT_VERSION >= 0x040400
   38         + QLatin1Char(' ') + QCoreApplication::applicationVersion()
   39 #endif
   40     ;
   41 }
   42 
   43 MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags)
   44     : QMainWindow(parent, flags)
   45 {
   46     setupUi(this);
   47 
   48     m_imageInfoGroup->setVisible(false);
   49 
   50     m_unitOfLengthActions = new QActionGroup(m_menuSettings);
   51 
   52     m_actionLoadInputImage->setShortcuts(
   53         QList<QKeySequence>() << (Qt::ControlModifier | Qt::Key_L) << (Qt::ControlModifier | Qt::Key_O));
   54     m_actionSavePoster->setShortcut(Qt::ControlModifier | Qt::Key_S);
   55     m_actionExit->setShortcut(Qt::ControlModifier | Qt::Key_Q);
   56     m_actionPosteRazorManual->setShortcut(Qt::Key_F1);
   57 
   58     m_imageLoadButton->setIcon(QApplication::style()->standardPixmap(QStyle::SP_DirOpenIcon)); // SP_DialogOpenButton looks ugly
   59     m_stepHelpButton->setMinimumSize(m_imageLoadButton->sizeHint()); // Same size. Looks better
   60     m_savePosterButton->setIcon(QApplication::style()->standardPixmap(QStyle::SP_DialogSaveButton));
   61     m_actionLoadInputImage->setIcon(m_imageLoadButton->icon());
   62     m_actionSavePoster->setIcon(m_savePosterButton->icon());
   63     m_actionSavePoster->setEnabled(false);
   64 
   65     setWindowIcon(QIcon(":/Icons/posterazor.png"));
   66 
   67     const struct {
   68         QAbstractButton *sender;
   69         Qt::Alignment alignment;
   70     } alignmentMap[] = {
   71         {m_posterAlignmentTopLeftButton,     Qt::AlignTop | Qt::AlignLeft        },
   72         {m_posterAlignmentTopButton,         Qt::AlignTop | Qt::AlignHCenter     },
   73         {m_posterAlignmentTopRightButton,    Qt::AlignTop | Qt::AlignRight       },
   74         {m_posterAlignmentLeftButton,        Qt::AlignVCenter | Qt::AlignLeft    },
   75         {m_posterAlignmentCenterButton,      Qt::AlignCenter                     },
   76         {m_posterAlignmentRightButton,       Qt::AlignVCenter | Qt::AlignRight   },
   77         {m_posterAlignmentBottomLeftButton,  Qt::AlignBottom | Qt::AlignLeft     },
   78         {m_posterAlignmentBottomButton,      Qt::AlignBottom | Qt::AlignHCenter  },
   79         {m_posterAlignmentBottomRightButton, Qt::AlignBottom | Qt::AlignRight    }
   80     };
   81     const int alignmentMapCount = (int)sizeof(alignmentMap)/sizeof(alignmentMap[0]);
   82     for (int i = 0; i < alignmentMapCount; i++)
   83         m_alignmentButtons.insert(alignmentMap[i].alignment, alignmentMap[i].sender);
   84 
   85     const struct {
   86         QAbstractButton *sender;
   87         Qt::Alignment alignment;
   88     } overlappingMap[] = {
   89         {m_overlappingPositionTopLeftButton,     Qt::AlignTop | Qt::AlignLeft     },
   90         {m_overlappingPositionTopRightButton,    Qt::AlignTop | Qt::AlignRight    },
   91         {m_overlappingPositionBottomLeftButton,  Qt::AlignBottom | Qt::AlignLeft  },
   92         {m_overlappingPositionBottomRightButton, Qt::AlignBottom | Qt::AlignRight }
   93     };
   94     const int overlappingMapCount = (int)sizeof(overlappingMap)/sizeof(overlappingMap[0]);
   95     for (int i = 0; i < overlappingMapCount; i++)
   96         m_overlappingButtons.insert(overlappingMap[i].alignment, overlappingMap[i].sender);
   97 
   98     setWindowTitle(applicationNameWithVersion());
   99     m_steps->setCurrentIndex(0);
  100     createConnections();
  101     populateUI();
  102     updatePosterSizeGroupsState();
  103     retranslateUi();
  104 }
  105 
  106 void MainWindow::changeEvent(QEvent *event)
  107 {
  108     if (event->type() == QEvent::LanguageChange)
  109         retranslateUi();
  110     QMainWindow::changeEvent(event);
  111 }
  112 
  113 void MainWindow::retranslateUi()
  114 {
  115     // TODO: Add shortcut and trailing "..." for load and save action. Enhance cleanString and use it in WizardController
  116     m_actionLoadInputImage->setText(                QCoreApplication::translate("Help", "Load an input image"));
  117     m_actionSavePoster->setText(                    QCoreApplication::translate("Help", "Save the Poster"));
  118     m_actionPosteRazorManual->setText(              QCoreApplication::translate("Help", "&Manual"));
  119     m_actionPosteRazorWebSite->setText(             QCoreApplication::translate("Help", "PosteRazor &website"));
  120     m_actionAboutPosteRazor->setText(               QCoreApplication::translate("Help", "&About PosteRazor"));
  121     m_actionAboutQt->setText(                       QCoreApplication::translate("Help", "About &Qt"));
  122     m_actionExit->setText(                          QCoreApplication::translate("Main window", "E&xit"));
  123 
  124     m_imageInfoGroup->setTitle(                     QCoreApplication::translate("Main window", "Image Informations"));
  125     m_imageInformationColorTypeLabel->setText(      QCoreApplication::translate("Main window", "Color type:"));
  126     m_imageInformationResolutionLabel->setText(     QCoreApplication::translate("Main window", "Resolution:"));
  127     m_imageInformationSizeInPixelsLabel->setText(   QCoreApplication::translate("Main window", "Size (in pixels):"));
  128     m_inputImageGroup->setTitle(                    QCoreApplication::translate("Main window", "Input Image"));
  129     m_launchPDFApplicationCheckBox->setText(        QCoreApplication::translate("Main window", "Open PDF after saving"));
  130     m_menuFile->setTitle(                           QCoreApplication::translate("Main window", "&File"));
  131     m_menuSettings->setTitle(                       QCoreApplication::translate("Main window", "&Settings"));
  132     m_stepNextButton->setText(                      QCoreApplication::translate("Main window", "Next"));
  133     m_overlappingHeightLabel->setText(              QCoreApplication::translate("Main window", "Height:"));
  134     m_overlappingPositionBottomLeftButton->setText( QCoreApplication::translate("Main window", "Bottom left"));
  135     m_overlappingPositionBottomRightButton->setText(QCoreApplication::translate("Main window", "Bottom right"));
  136     m_overlappingPositionGroup->setTitle(           QCoreApplication::translate("Main window", "Overlapping position"));
  137     m_overlappingPositionTopLeftButton->setText(    QCoreApplication::translate("Main window", "Top left"));
  138     m_overlappingPositionTopRightButton->setText(   QCoreApplication::translate("Main window", "Top right"));
  139     m_overlappingSizeGroup->setTitle(               QCoreApplication::translate("Main window", "Overlapping size"));
  140     m_overlappingWidthLabel->setText(               QCoreApplication::translate("Main window", "Width:"));
  141     m_paperBordersBottomLabel->setText(             QCoreApplication::translate("Main window", "Bottom"));
  142     m_paperBordersLeftLabel->setText(               QCoreApplication::translate("Main window", "Left"));
  143     m_paperBordersRightLabel->setText(              QCoreApplication::translate("Main window", "Right"));
  144     m_paperBordersTopLabel->setText(                QCoreApplication::translate("Main window", "Top"));
  145     m_paperCustomHeightLabel->setText(              QCoreApplication::translate("Main window", "Height:"));
  146     m_paperCustomWidthLabel->setText(               QCoreApplication::translate("Main window", "Width:"));
  147     m_paperFormatLabel->setText(                    QCoreApplication::translate("Main window", "Format:"));
  148     m_paperFormatTypeTabs->setTabText(m_paperFormatTypeTabs->indexOf(m_paperFormatCustomTab),
  149                                                     QCoreApplication::translate("Main window", "Custom"));
  150     m_paperFormatTypeTabs->setTabText(m_paperFormatTypeTabs->indexOf(m_paperFormatStandardTab),
  151                                                     QCoreApplication::translate("Main window", "Standard"));
  152     m_paperOrientationLabel->setText(               QCoreApplication::translate("Main window", "Orientation:"));
  153     m_paperOrientationLandscapeRadioButton->setText(QCoreApplication::translate("Main window", "Landscape"));
  154     m_paperOrientationPortraitRadioButton->setText( QCoreApplication::translate("Main window", "Portrait"));
  155     m_paperSizeGroup->setTitle(                     QCoreApplication::translate("Main window", "Paper size"));
  156     m_posterAbsoluteHeightLabel->setText(           QCoreApplication::translate("Main window", "Height:"));
  157     m_posterAbsoluteWidthLabel->setText(            QCoreApplication::translate("Main window", "Width:"));
  158     m_posterAlignmentGroup->setTitle(               QCoreApplication::translate("Main window", "Image alignment"));
  159     m_posterPagesHeightDimensionUnitLabel->setText( QCoreApplication::translate("Main window", "pages"));
  160     m_posterPagesHeightLabel->setText(              QCoreApplication::translate("Main window", "Height:"));
  161     m_posterPagesWidthDimensionUnitLabel->setText(  QCoreApplication::translate("Main window", "pages"));
  162     m_posterPagesWidthLabel->setText(               QCoreApplication::translate("Main window", "Width:"));
  163     m_posterPercentualSizeLabel->setText(           QCoreApplication::translate("Main window", "Size:"));
  164     m_posterSizeAbsoluteRadioButton->setText(       QCoreApplication::translate("Main window", "Absolute size:"));
  165     m_posterSizeGroup->setTitle(                    QCoreApplication::translate("Main window", "Image size"));
  166     m_posterSizeInPagesRadioButton->setText(        QCoreApplication::translate("Main window", "Size in pages:"));
  167     m_posterSizePercentualRadioButton->setText(     QCoreApplication::translate("Main window", "Size in percent:"));
  168     m_stepPrevButton->setText(                      QCoreApplication::translate("Main window", "Back"));
  169     m_savePosterGroup->setTitle(                    QCoreApplication::translate("Main window", "Save the poster"));
  170     retranslateUiWithDimensionUnit();
  171 }
  172 
  173 void MainWindow::retranslateUiWithDimensionUnit()
  174 {
  175     const QString unitOfLength = QString(QLatin1String(" (%1)")).arg(m_currentUnitOfLength);
  176     m_imageInformationSizeLabel->setText(           QCoreApplication::translate("Main window", "Size (in %1):").arg(m_currentUnitOfLength));
  177     m_paperBordersGroup->setTitle(                  QCoreApplication::translate("Main window", "Borders") + unitOfLength);
  178 }
  179 
  180 void MainWindow::setPaperFormat(const QString &format)
  181 {
  182     const int index = m_paperFormatComboBox->findData(format, Qt::DisplayRole);
  183     m_paperFormatComboBox->setCurrentIndex(index);
  184 }
  185 
  186 void MainWindow::setPaperOrientation(QPrinter::Orientation orientation)
  187 {
  188     (
  189         orientation == QPrinter::Landscape?m_paperOrientationLandscapeRadioButton
  190         :m_paperOrientationPortraitRadioButton
  191     )->setChecked(true);
  192 }
  193 
  194 void MainWindow::setPaperBorderTop(double border)
  195 {
  196     m_paperBorderTopInput->setValue(border);
  197 }
  198 
  199 void MainWindow::setPaperBorderRight(double border)
  200 {
  201     m_paperBorderRightInput->setValue(border);
  202 }
  203 
  204 void MainWindow::setPaperBorderBottom(double border)
  205 {
  206     m_paperBorderBottomInput->setValue(border);
  207 }
  208 
  209 void MainWindow::setPaperBorderLeft(double border)
  210 {
  211     m_paperBorderLeftInput->setValue(border);
  212 }
  213 
  214 void MainWindow::setCustomPaperSize(const QSizeF &size)
  215 {
  216     m_paperCustomWidthSpinner->setValue(size.width());
  217     m_paperCustomHeightSpinner->setValue(size.height());
  218 }
  219 
  220 void MainWindow::setUseCustomPaperSize(bool useIt)
  221 {
  222     m_paperFormatTypeTabs->setCurrentWidget(useIt?m_paperFormatCustomTab:m_paperFormatStandardTab);
  223 }
  224 
  225 void MainWindow::setOverlappingWidth(double width)
  226 {
  227     m_overlappingWidthInput->setValue(width);
  228 }
  229 
  230 void MainWindow::setOverlappingHeight(double height)
  231 {
  232     m_overlappingHeightInput->setValue(height);
  233 }
  234 
  235 void MainWindow::setOverlappingPosition(Qt::Alignment position)
  236 {
  237     if (m_overlappingButtons.contains(position))
  238         m_overlappingButtons.value(position)->setChecked(true);
  239 }
  240 
  241 void MainWindow::setPosterWidthAbsolute(double width)
  242 {
  243     m_posterAbsoluteWidthInput->setValue(width);
  244 }
  245 
  246 void MainWindow::setPosterHeightAbsolute(double height)
  247 {
  248     m_posterAbsoluteHeightInput->setValue(height);
  249 }
  250 
  251 void MainWindow::setPosterWidthPages(double width)
  252 {
  253     m_posterPagesWidthInput->setValue(width);
  254 }
  255 
  256 void MainWindow::setPosterHeightPages(double height)
  257 {
  258     m_posterPagesHeightInput->setValue(height);
  259 }
  260 
  261 void MainWindow::setPosterSizePercentual(double percent)
  262 {
  263     m_posterPercentualSizeInput->setValue(percent);
  264 }
  265 
  266 void MainWindow::setPosterSizeMode(Types::PosterSizeModes mode)
  267 {
  268     (
  269         mode == Types::PosterSizeModeAbsolute?m_posterSizeAbsoluteRadioButton
  270         :mode == Types::PosterSizeModePages?m_posterSizeInPagesRadioButton
  271         :m_posterSizePercentualRadioButton
  272     )->setChecked(true);
  273     updatePosterSizeGroupsState();
  274 }
  275 
  276 void MainWindow::setPosterAlignment(Qt::Alignment alignment)
  277 {
  278     if (m_alignmentButtons.contains(alignment))
  279         m_alignmentButtons.value(alignment)->setChecked(true);
  280 }
  281 
  282 void MainWindow::setLaunchPDFApplication(bool launch)
  283 {
  284     m_launchPDFApplicationCheckBox->setCheckState(launch?Qt::Checked:Qt::Unchecked);
  285 }
  286 
  287 void MainWindow::updatePreview()
  288 {
  289     m_paintCanvas->repaint();
  290 }
  291 
  292 void MainWindow::showImageFileName(const QString &fileName)
  293 {
  294     m_inputFileNameLabel->setText(QFileInfo(fileName).fileName());
  295 }
  296 
  297 void MainWindow::updateImageInfoFields(const QSize &inputImageSizeInPixels, const QSizeF &imageSize, double verticalDpi, double horizontalDpi, Types::ColorTypes colorType, int bitsPerPixel)
  298 {
  299     Q_UNUSED(horizontalDpi)
  300 
  301     m_imageInformationSizeInPixelsValue->setText(QString("%1 x %2").arg(inputImageSizeInPixels.width()).arg(inputImageSizeInPixels.height()));
  302     m_imageInformationSizeValue->setText(QString("%1 x %2").arg(imageSize.width(), 0, 'f', 2).arg(imageSize.height(), 0, 'f', 2));
  303     m_imageInformationResolutionValue->setText(QString("%1 dpi").arg(verticalDpi, 0, 'f', 1));
  304     const QString colorTypeString = (
  305         colorType==Types::ColorTypeMonochrome?QCoreApplication::translate("Main window", "Monochrome"):
  306         colorType==Types::ColorTypeGreyscale?QCoreApplication::translate("Main window", "Gray scale"):
  307         colorType==Types::ColorTypePalette?QCoreApplication::translate("Main window", "Palette"):
  308         colorType==Types::ColorTypeRGB?QCoreApplication::translate("Main window", "RGB"):
  309         colorType==Types::ColorTypeRGBA?QCoreApplication::translate("Main window", "RGBA"):
  310         /*colorType==ColorTypeCMYK?*/ QCoreApplication::translate("Main window", "CMYK")
  311     ) + QString(" %1bpp").arg(bitsPerPixel);
  312     m_imageInformationColorTypeValue->setText(colorTypeString);
  313     m_imageInfoGroup->setVisible(true);
  314     m_actionSavePoster->setEnabled(true);
  315     emit imageLoaded();
  316 }
  317 
  318 void MainWindow::setCurrentTranslation(const QString &translation)
  319 {
  320     QAction *translationAction = NULL;
  321     translationAction = m_translationActions.value(translation);
  322     if (!translationAction) {
  323         // On a Swiss system 'translation' may be "de_CH". So let's fall back to "de"
  324         const QString translationLanguage = translation.split(QLatin1Char('_')).first();
  325         translationAction = m_translationActions.value(translationLanguage);
  326     }
  327     if (translationAction)
  328         translationAction->setChecked(true);
  329 }
  330 
  331 void MainWindow::setCurrentUnitOfLength(const QString &unit)
  332 {
  333     m_currentUnitOfLength = unit;
  334     foreach (QAction *action, m_unitOfLengthActions->actions()) {
  335         if (action->text() == unit) {
  336             action->setChecked(true);
  337             break;
  338         }
  339     }
  340     retranslateUiWithDimensionUnit();
  341     m_posterAbsoluteWidthDimensionUnitLabel->setText(unit);
  342     m_posterAbsoluteHeightDimensionUnitLabel->setText(unit);
  343     m_overlappingWidthDimensionUnitLabel->setText(unit);
  344     m_overlappingHeightDimensionUnitLabel->setText(unit);
  345     m_paperCustomWidthDimensionUnitLabel->setText(unit);
  346     m_paperCustomHeightDimensionUnitLabel->setText(unit);
  347 }
  348 
  349 void MainWindow::addAboutDialogAction(QAction *action)
  350 {   
  351     m_menuAbout->addAction(action);
  352 }
  353 
  354 void MainWindow::setPrevButtonEnabled(bool enabled)
  355 {
  356     m_stepPrevButton->setDisabled(!enabled);
  357 }
  358 
  359 void MainWindow::setNextButtonEnabled(bool enabled)
  360 {
  361     m_stepNextButton->setDisabled(!enabled);
  362 }
  363 
  364 void MainWindow::setWizardStep(int step)
  365 {
  366     m_steps->setCurrentIndex(step);
  367 }
  368 
  369 void MainWindow::setWizardStepDescription(const QString &number, const QString &description)
  370 {
  371     m_stepNumberLabel->setText(number);
  372     m_stepDescriptionLabel->setText(description);
  373 }
  374 
  375 void MainWindow::setPreviewState(const QString &state)
  376 {
  377     m_paintCanvas->setState(state);
  378 }
  379 
  380 
  381 void MainWindow::setPreviewImage(const QImage &image)
  382 {
  383     m_paintCanvas->setImage(image);
  384 }
  385 
  386 void MainWindow::showWizardStepHelp(const QString &title, const QString &text)
  387 {
  388     QMessageBox box(this);
  389     box.setWindowTitle(title);
  390     QString helpText = text;
  391 #if defined(Q_WS_MAC)
  392     // Hack. Since QMessageBoxPrivate sets the whole font to bold on Q_WS_MAC (no matter which style),
  393     // we put emphasis on the key words by setting them to italic and into single quotes.
  394     helpText.replace("<b>", "<i>'");
  395     helpText.replace("</b>", "'</i>");
  396 #endif
  397     box.setText(helpText);
  398     box.setTextFormat(Qt::RichText);
  399     box.addButton(QMessageBox::Ok);
  400     box.exec();
  401 }
  402 
  403 void MainWindow::showManual(const QString &title, const QString &text)
  404 {
  405     QDialog *dialog = new QDialog(this);
  406     dialog->setModal(true);
  407     dialog->setWindowTitle(title);
  408     dialog->setAttribute(Qt::WA_DeleteOnClose, true);
  409     dialog->setWindowFlags(dialog->windowFlags() ^ Qt::WindowContextHelpButtonHint);
  410     dialog->resize(500, 400);
  411     dialog->setLayout(new QVBoxLayout);
  412     QTextBrowser *browser = new QTextBrowser;
  413     browser->setOpenExternalLinks(true);
  414     browser->document()->setDefaultStyleSheet(
  415         "dt {font-weight: bold;}"
  416         "dd {margin-left: 15px;}"
  417         "p {text-indent: 7px;}"
  418         "p, dd {margin-top: 0px; margin-bottom: 6px;}"
  419         "h2 {margin-top: 18px; margin-bottom: 6px;}");
  420     browser->setHtml(text);
  421     dialog->layout()->addWidget(browser);
  422     QDialogButtonBox *buttonBox = new QDialogButtonBox;
  423     buttonBox->setStandardButtons(QDialogButtonBox::Ok);
  424     connect(buttonBox, SIGNAL(accepted ()), dialog, SLOT(accept()));
  425     dialog->layout()->addWidget(buttonBox);
  426     dialog->show();
  427 }
  428 
  429 void MainWindow::handlePaperFormatTabChanged(int index)
  430 {
  431     emit useCustomPaperSizeChanged(index == 1);
  432 }
  433 
  434 void MainWindow::handlePaperOrientationPortraitSelected()
  435 {
  436     emit paperOrientationChanged(QPrinter::Portrait);
  437 }
  438 
  439 void MainWindow::handlePaperOrientationLandscapeSelected()
  440 {
  441     emit paperOrientationChanged(QPrinter::Landscape);
  442 }
  443 
  444 void MainWindow::handleTranslationAction(QAction *action) const
  445 {
  446     emit translationChanged(action->data().toString());
  447 }
  448 
  449 void MainWindow::handleUnitOfLengthAction(QAction *action) const
  450 {
  451     emit unitOfLengthChanged(action->text());
  452 }
  453 
  454 void MainWindow::createConnections()
  455 {
  456     connect(m_actionExit,                           SIGNAL(triggered()),                SLOT(close()));
  457     connect(m_stepNextButton,                       SIGNAL(clicked()),                  SIGNAL(nextButtonPressed()));
  458     connect(m_stepPrevButton,                       SIGNAL(clicked()),                  SIGNAL(prevButtonPressed()));
  459     connect(m_stepHelpButton,                       SIGNAL(clicked()),                  SIGNAL(wizardStepHelpSignal()));
  460     connect(m_paperFormatTypeTabs,                  SIGNAL(currentChanged(int)),        SLOT(handlePaperFormatTabChanged(int)));
  461     connect(m_paperFormatComboBox,                  SIGNAL(activated(const QString &)), SIGNAL(paperFormatChanged(const QString &)));
  462     connect(m_paperOrientationPortraitRadioButton,  SIGNAL(clicked()),                  SLOT(handlePaperOrientationPortraitSelected()));
  463     connect(m_paperOrientationLandscapeRadioButton, SIGNAL(clicked()),                  SLOT(handlePaperOrientationLandscapeSelected()));
  464     connect(m_paperCustomWidthSpinner,              SIGNAL(valueEdited(double)),        SIGNAL(paperCustomWidthChanged(double)));
  465     connect(m_paperCustomHeightSpinner,             SIGNAL(valueEdited(double)),        SIGNAL(paperCustomHeightChanged(double)));
  466     connect(m_paperBorderTopInput,                  SIGNAL(valueEdited(double)),        SIGNAL(paperBorderTopChanged(double)));
  467     connect(m_paperBorderRightInput,                SIGNAL(valueEdited(double)),        SIGNAL(paperBorderRightChanged(double)));
  468     connect(m_paperBorderBottomInput,               SIGNAL(valueEdited(double)),        SIGNAL(paperBorderBottomChanged(double)));
  469     connect(m_paperBorderLeftInput,                 SIGNAL(valueEdited(double)),        SIGNAL(paperBorderLeftChanged(double)));
  470     connect(m_actionLoadInputImage,                 SIGNAL(triggered()),                SIGNAL(loadImageSignal()));
  471     connect(m_imageLoadButton,                      SIGNAL(clicked()),                  SIGNAL(loadImageSignal()));
  472     connect(m_posterSizeAbsoluteRadioButton,        SIGNAL(clicked()),                  SLOT(updatePosterSizeGroupsState()));
  473     connect(m_posterSizeInPagesRadioButton,         SIGNAL(clicked()),                  SLOT(updatePosterSizeGroupsState()));
  474     connect(m_posterSizePercentualRadioButton,      SIGNAL(clicked()),                  SLOT(updatePosterSizeGroupsState()));
  475     connect(m_overlappingWidthInput,                SIGNAL(valueEdited(double)),        SIGNAL(overlappingWidthChanged(double)));
  476     connect(m_overlappingHeightInput,               SIGNAL(valueEdited(double)),        SIGNAL(overlappingHeightChanged(double)));
  477     QSignalMapper *overlappingMapper = new QSignalMapper(this);
  478     foreach (const Qt::Alignment alignment, m_overlappingButtons.keys()) {
  479         QAbstractButton *sender = m_overlappingButtons.value(alignment);
  480         connect(sender, SIGNAL(clicked()), overlappingMapper, SLOT(map()));
  481         overlappingMapper->setMapping(sender, alignment);
  482     }
  483     connect(overlappingMapper, SIGNAL(mapped(int)), SLOT(emitOverlappingPositionChange(int)));
  484     connect(m_posterAbsoluteWidthInput,             SIGNAL(valueEdited(double)),        SIGNAL(posterWidthAbsoluteChanged(double)));
  485     connect(m_posterAbsoluteHeightInput,            SIGNAL(valueEdited(double)),        SIGNAL(posterHeightAbsoluteChanged(double)));
  486     connect(m_posterPagesWidthInput,                SIGNAL(valueEdited(double)),        SIGNAL(posterWidthPagesChanged(double)));
  487     connect(m_posterPagesHeightInput,               SIGNAL(valueEdited(double)),        SIGNAL(posterHeightPagesChanged(double)));
  488     connect(m_posterPercentualSizeInput,            SIGNAL(valueEdited(double)),        SIGNAL(posterSizePercentualChanged(double)));
  489     QSignalMapper *alignmentMapper = new QSignalMapper(this);
  490     foreach (const Qt::Alignment alignment, m_alignmentButtons.keys()) {
  491         QAbstractButton *sender = m_alignmentButtons.value(alignment);
  492         connect(sender, SIGNAL(clicked()), alignmentMapper, SLOT(map()));
  493         alignmentMapper->setMapping(sender, alignment);
  494     }
  495     connect(alignmentMapper, SIGNAL(mapped(int)),   SLOT(emitPosterAlignmentChange(int)));
  496     connect(m_actionSavePoster,                     SIGNAL(triggered()),                SIGNAL(savePosterSignal()));
  497     connect(m_savePosterButton,                     SIGNAL(clicked()),                  SIGNAL(savePosterSignal()));
  498     connect(m_launchPDFApplicationCheckBox,         SIGNAL(toggled(bool)),              SIGNAL(launchPDFApplicationChanged(bool)));
  499     connect(m_paintCanvas,                          SIGNAL(needsPaint(PaintCanvasInterface*, const QVariant&)), SIGNAL(needsPaint(PaintCanvasInterface*, const QVariant&)));
  500     connect(m_actionPosteRazorWebSite,              SIGNAL(triggered()),                SIGNAL(openPosteRazorWebsiteSignal()));
  501     connect(m_actionAboutQt,                        SIGNAL(triggered()),                SLOT(showAboutQtDialog()));
  502     connect(m_actionAboutPosteRazor,                SIGNAL(triggered()),                SLOT(showAboutPosteRazorDialog()));
  503     connect(m_actionPosteRazorManual,               SIGNAL(triggered()),                SIGNAL(manualSignal()));
  504 }
  505 
  506 void MainWindow::populateUI()
  507 {
  508     connect (m_unitOfLengthActions, SIGNAL(triggered(QAction*)), SLOT(handleUnitOfLengthAction(QAction*)));
  509     m_unitOfLengthActions->setExclusive(true);
  510     const int unitsOfLengthCount = Types::unitsOfLength().count();
  511     for (int i = 0; i < unitsOfLengthCount; i++) {
  512         const QString unitOfLength = Types::unitsOfLength().value((Types::UnitsOfLength)i).first;
  513         QAction *unitOfLengthAction = m_unitOfLengthActions->addAction(unitOfLength);
  514         unitOfLengthAction->setCheckable(true);
  515     }
  516     m_menuSettings->addActions(m_unitOfLengthActions->actions());
  517 
  518     m_menuSettings->addSeparator();
  519 
  520     QActionGroup *translationActions = new QActionGroup(m_menuSettings);
  521     connect (translationActions, SIGNAL(triggered(QAction*)), SLOT(handleTranslationAction(QAction*)));
  522     translationActions->setExclusive(true);
  523     QDir translationDir(":/Translations/");
  524     foreach (const QFileInfo &translation, translationDir.entryInfoList(QDir::Files)) {
  525         QTranslator translator;
  526         translator.load(translation.absoluteFilePath());
  527         QAction *languageAction = translationActions->addAction(translator.translate("Main window", "Language name"));
  528         // TODO: Find out why the menu entries are empty on Mac (and maybe on Linux?)
  529         const QString localeString(translation.baseName());
  530         languageAction->setData(localeString);
  531         languageAction->setCheckable(true);
  532         m_translationActions.insert(localeString, languageAction);
  533     }
  534     m_menuSettings->addActions(translationActions->actions());
  535 
  536     QStringList formats = Types::paperFormats().keys();
  537     formats.sort();
  538     m_paperFormatComboBox->addItems(formats);
  539 }
  540 
  541 void MainWindow::emitOverlappingPositionChange(int alignmentInt) const
  542 {
  543     emit overlappingPositionChanged((Qt::Alignment)alignmentInt);
  544 }
  545 
  546 void MainWindow::emitPosterAlignmentChange(int alignmentInt) const
  547 {
  548     emit posterAlignmentChanged((Qt::Alignment)alignmentInt);
  549 }
  550 
  551 void MainWindow::updatePosterSizeGroupsState()
  552 {
  553     const bool absolute = m_posterSizeAbsoluteRadioButton->isChecked();
  554     m_posterAbsoluteWidthLabel->setEnabled(absolute);
  555     m_posterAbsoluteWidthInput->setEnabled(absolute);
  556     m_posterAbsoluteWidthDimensionUnitLabel->setEnabled(absolute);
  557     m_posterAbsoluteHeightLabel->setEnabled(absolute);
  558     m_posterAbsoluteHeightInput->setEnabled(absolute);
  559     m_posterAbsoluteHeightDimensionUnitLabel->setEnabled(absolute);
  560 
  561     const bool inPages = m_posterSizeInPagesRadioButton->isChecked();
  562     m_posterPagesWidthLabel->setEnabled(inPages);
  563     m_posterPagesWidthInput->setEnabled(inPages);
  564     m_posterPagesWidthDimensionUnitLabel->setEnabled(inPages);
  565     m_posterPagesHeightLabel->setEnabled(inPages);
  566     m_posterPagesHeightInput->setEnabled(inPages);
  567     m_posterPagesHeightDimensionUnitLabel->setEnabled(inPages);
  568 
  569     const bool percentual = m_posterSizePercentualRadioButton->isChecked();
  570     m_posterPercentualSizeLabel->setEnabled(percentual);
  571     m_posterPercentualSizeInput->setEnabled(percentual);
  572     m_posterPercentualSizeUnitLabel->setEnabled(percentual);
  573 }
  574 
  575 void MainWindow::showAboutQtDialog() const
  576 {
  577     QApplication::aboutQt();
  578 }
  579 
  580 void MainWindow::showAboutPosteRazorDialog()
  581 {
  582     const QString title = Types::cleanString(QCoreApplication::translate("Help", "&About PosteRazor"));
  583     const QString webpageAnchor = QString(QLatin1String("<a href=\"%1\">posterazor.sourceforge.net</a>"))
  584         .arg(QCoreApplication::translate("Help", "http://posterazor.sourceforge.net/", "Only translate, if the website has this language."));
  585     const QString aboutText =
  586         QLatin1String("<h1>") + applicationNameWithVersion() +
  587         QLatin1String("</h1>") +
  588         Types::newlineToParagraph(QCoreApplication::translate("Help",
  589             "The PosteRazor cuts a raster image into pieces which can be printed on a printer and be put together to a poster.\n"
  590             "As an input image, raster files of various image file formats are supported. Instead of directly printing the poster, the PosteRazor produces a multi page PDF file which contains the poster tiles.\n"
  591             "It is an open source program which depends on other open source projects. The PosteRazor is hosted on %1.")
  592             .arg(webpageAnchor)) +
  593         QLatin1String("<h2>Code from third parties</h2>"
  594             "<dl>"
  595             "<dt>Qt</dt>"
  596             "<dd>Extensive use of <a href=\"http://www.trolltech.com/\">Trolltech</a>s amazing cross-platform application framework</dd>"
  597             "<dt>FreeImage</dt>"
  598             "<dd>Easy and powerful image format support. See the <a href=\"http://freeimage.sourceforge.net/\">FreeImage website</a></dd>"
  599             "</dl>") +
  600         QLatin1String("<h2>Translations</h2>"
  601             "<p>In order of appearance</p>"
  602             "<dl>"
  603             "<dt>English</dt><dd>Alessandro Portale (author)</dd>"
  604             "<dt>German</dt><dd>Alessandro Portale (author)</dd>"
  605             "<dt>Polish</dt><dd>Grzegorz Wacikowski</dd>"
  606             "<dt>French</dt><dd>Martin Loyer</dd>"
  607             "<dt>Italian</dt><dd>Stefano Nosei</dd>"
  608             "<dt>Dutch/Belgian</dt><dd>Erik Wijkamp</dd>"
  609             "<dt>Spanish</dt><dd><a href=\"http://hispanicoweb.net/\">Hispánico Web</a></dd>"
  610             "<dt>Brazilian Portuguese</dt><dd>Éderson Gomes dos Santos</dd>"
  611             "<dt>Simplified Chinese</dt><dd>Sun Li</dd>"
  612             "<dt>Finnish</dt><dd>Olli</dd>"
  613             "</dl>") +
  614         QLatin1String("<h2>License</h2>"
  615             "<p>PosteRazor - Make your own poster!<br/>"
  616             "posterazor.sourceforge.net<br/>"
  617             "Copyright (C) 2005-2008 by Alessandro Portale</p>"
  618             "<p>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.</p>"
  619             "<p>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.</p>"
  620             "<p>You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p>");
  621     showManual(title, aboutText);
  622 }