diff options
author | Friedemann Kleint <Friedemann.Kleint@theqtcompany.com> | 2016-01-20 10:05:26 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@theqtcompany.com> | 2016-01-27 09:14:32 +0000 |
commit | fa4bd6f3aae782aa810033688ee4f45aa9db1546 (patch) | |
tree | ecda7a4878d70b50bdabc2d641028cef4e5baff4 | |
parent | 81a83108b0b16af4f4ff6cfd42182a4b879f213f (diff) | |
download | qttools-fa4bd6f3aae782aa810033688ee4f45aa9db1546.tar.gz |
Polish PixelTool.
- Use Qt 5 connection syntax, streamline context menu code accordingly.
- Streamline code, use constructor initialization, Q_DECL_OVERRIDE.
- Introduce QCommandLineParser, add an option to turn off scaling.
- Fix image file dialog.
- Fix the cursor position display to always display native pixels.
Change-Id: I534eed2144acf6c6c868af725ac6e01ab93bdd88
Reviewed-by: Alessandro Portale <alessandro.portale@theqtcompany.com>
-rw-r--r-- | src/pixeltool/main.cpp | 47 | ||||
-rw-r--r-- | src/pixeltool/pixeltool.pro | 2 | ||||
-rw-r--r-- | src/pixeltool/qpixeltool.cpp | 218 | ||||
-rw-r--r-- | src/pixeltool/qpixeltool.h | 27 |
4 files changed, 169 insertions, 125 deletions
diff --git a/src/pixeltool/main.cpp b/src/pixeltool/main.cpp index a9377ad91..810d3a474 100644 --- a/src/pixeltool/main.cpp +++ b/src/pixeltool/main.cpp @@ -34,24 +34,57 @@ #include "qpixeltool.h" #include <qapplication.h> +#include <qcommandlineparser.h> +#include <qcommandlineoption.h> #include <qfileinfo.h> QT_USE_NAMESPACE +static bool isOptionSet(int argc, char *argv[], const char *option) +{ + for (int i = 1; i < argc; ++i) { + if (!qstrcmp(argv[i], option)) + return true; + } + return false; +} + int main(int argc, char **argv) { + if (isOptionSet(argc, argv, "--no-scaling")) + QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); + QApplication app(argc, argv); + QCoreApplication::setApplicationName(QLatin1String("PixelTool")); + QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); + QCoreApplication::setOrganizationName(QLatin1String("QtProject")); + + QCommandLineParser parser; + parser.addHelpOption(); + parser.addVersionOption(); + QCommandLineOption noScalingDummy(QStringLiteral("no-scaling"), + QStringLiteral("Set Qt::AA_DisableHighDpiScaling.")); + parser.addOption(noScalingDummy); + parser.addPositionalArgument(QLatin1String("preview"), + QLatin1String("The preview image to show.")); + + parser.process(app); - QPixelTool pt; + QPixelTool pixelTool; - if (app.arguments().size() > 1 && QFileInfo(app.arguments().at(1)).exists()) { - pt.setPreviewImage(QImage(app.arguments().at(1))); + if (!parser.positionalArguments().isEmpty()) { + const QString previewImageFileName = parser.positionalArguments().first(); + if (QFileInfo(previewImageFileName).exists()) { + QImage previewImage(previewImageFileName); + if (!previewImage.size().isEmpty()) + pixelTool.setPreviewImage(previewImage); + } } - pt.show(); + pixelTool.show(); - QObject::connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit())); + QObject::connect(&app, &QApplication::lastWindowClosed, + &app, &QCoreApplication::quit); - int ret = app.exec(); - return ret; + return app.exec(); } diff --git a/src/pixeltool/pixeltool.pro b/src/pixeltool/pixeltool.pro index 82db6e48f..f3d1bf436 100644 --- a/src/pixeltool/pixeltool.pro +++ b/src/pixeltool/pixeltool.pro @@ -1,4 +1,4 @@ -QT += widgets +QT += core-private gui-private widgets mac { QMAKE_INFO_PLIST=Info_mac.plist diff --git a/src/pixeltool/qpixeltool.cpp b/src/pixeltool/qpixeltool.cpp index eac447c0a..b381c2e9c 100644 --- a/src/pixeltool/qpixeltool.cpp +++ b/src/pixeltool/qpixeltool.cpp @@ -35,6 +35,7 @@ #include <qapplication.h> #include <qdesktopwidget.h> +#include <qdir.h> #include <qapplication.h> #include <qscreen.h> #ifndef QT_NO_CLIPBOARD @@ -43,9 +44,13 @@ #include <qpainter.h> #include <qevent.h> #include <qfiledialog.h> +#include <qmessagebox.h> #include <qsettings.h> #include <qmenu.h> #include <qactiongroup.h> +#include <qimagewriter.h> +#include <qstandardpaths.h> +#include <private/qhighdpiscaling_p.h> #include <qdebug.h> @@ -53,30 +58,21 @@ QT_BEGIN_NAMESPACE QPixelTool::QPixelTool(QWidget *parent) : QWidget(parent) + , m_freeze(false) + , m_displayZoom(false) + , m_displayGridSize(false) + , m_mouseDown(false) + , m_preview_mode(false) + , m_displayZoomId(0) + , m_displayGridSizeId(0) + , m_currentColor(0) { - setWindowTitle(QLatin1String("PixelTool")); + setWindowTitle(QCoreApplication::applicationName()); QSettings settings(QLatin1String("QtProject"), QLatin1String("QPixelTool")); - - m_freeze = false; - m_autoUpdate = settings.value(QLatin1String("autoUpdate"), 0).toBool(); - m_gridSize = settings.value(QLatin1String("gridSize"), 1).toInt(); m_gridActive = settings.value(QLatin1String("gridActive"), 1).toInt(); - m_displayGridSize = false; - m_displayGridSizeId = 0; - m_zoom = settings.value(QLatin1String("zoom"), 4).toInt(); - - m_displayZoom = false; - m_displayZoomId = 0; - - m_preview_mode = false; - - m_currentColor = 0; - - m_mouseDown = false; - m_initialSize = settings.value(QLatin1String("initialSize"), QSize(250, 200)).toSize(); move(settings.value(QLatin1String("position")).toPoint()); @@ -174,13 +170,13 @@ void QPixelTool::paintEvent(QPaintEvent *) if (m_displayZoom) { render_string(&p, w, h, - QString::fromLatin1("Zoom: x%1").arg(m_zoom), + QLatin1String("Zoom: x") + QString::number(m_zoom), Qt::AlignTop | Qt::AlignRight); } if (m_displayGridSize) { render_string(&p, w, h, - QString::fromLatin1("Grid size: %1").arg(m_gridSize), + QLatin1String("Grid size: ") + QString::number(m_gridSize), Qt::AlignBottom | Qt::AlignLeft); } @@ -307,99 +303,88 @@ void QPixelTool::mouseReleaseEvent(QMouseEvent *) m_mouseDown = false; } +static QAction *addCheckableAction(QMenu &menu, const QString &title, + bool value, const QKeySequence &key) +{ + QAction *result = menu.addAction(title); + result->setCheckable(true); + result->setChecked(value); + result->setShortcut(key); + return result; +} + +static QAction *addCheckableAction(QMenu &menu, const QString &title, + bool value, const QKeySequence &key, + QActionGroup *group) +{ + QAction *result = addCheckableAction(menu, title, value, key); + result->setActionGroup(group); + return result; +} + void QPixelTool::contextMenuEvent(QContextMenuEvent *e) { - bool tmpFreeze = m_freeze; + const bool tmpFreeze = m_freeze; m_freeze = true; QMenu menu; - - QAction title(QLatin1String("Qt Pixel Zooming Tool"), &menu); - title.setEnabled(false); + menu.addAction(QLatin1String("Qt Pixel Zooming Tool"))->setEnabled(false); + menu.addSeparator(); // Grid color options... - QActionGroup gridGroup(this); - QAction whiteGrid(QLatin1String("White grid"), &gridGroup); - whiteGrid.setCheckable(true); - whiteGrid.setChecked(m_gridActive == 2); - whiteGrid.setShortcut(QKeySequence(Qt::Key_G)); - QAction blackGrid(QLatin1String("Black grid"), &gridGroup); - blackGrid.setCheckable(true); - blackGrid.setChecked(m_gridActive == 1); - blackGrid.setShortcut(QKeySequence(Qt::Key_G)); - QAction noGrid(QLatin1String("No grid"), &gridGroup); - noGrid.setCheckable(true); - noGrid.setChecked(m_gridActive == 0); - noGrid.setShortcut(QKeySequence(Qt::Key_G)); + QActionGroup *gridGroup = new QActionGroup(&menu); + addCheckableAction(menu, QLatin1String("White grid"), m_gridActive == 2, + Qt::Key_W, gridGroup); + QAction *blackGrid = addCheckableAction(menu, QLatin1String("Black grid"), + m_gridActive == 1, Qt::Key_B, gridGroup); + QAction *noGrid = addCheckableAction(menu, QLatin1String("No grid"), m_gridActive == 0, + Qt::Key_N, gridGroup); + menu.addSeparator(); // Grid size options - QAction incrGrid(QLatin1String("Increase grid size"), &menu); - incrGrid.setShortcut(QKeySequence(Qt::Key_PageUp)); - connect(&incrGrid, SIGNAL(triggered()), this, SLOT(increaseGridSize())); - QAction decrGrid(QLatin1String("Decrease grid size"), &menu); - decrGrid.setShortcut(QKeySequence(Qt::Key_PageDown)); - connect(&decrGrid, SIGNAL(triggered()), this, SLOT(decreaseGridSize())); + menu.addAction(QLatin1String("Increase grid size"), + this, &QPixelTool::increaseGridSize, Qt::Key_PageUp); + menu.addAction(QLatin1String("Decrease grid size"), + this, &QPixelTool::decreaseGridSize, Qt::Key_PageDown); + menu.addSeparator(); // Zoom options - QAction incrZoom(QLatin1String("Zoom in"), &menu); - incrZoom.setShortcut(QKeySequence(Qt::Key_Plus)); - connect(&incrZoom, SIGNAL(triggered()), this, SLOT(increaseZoom())); - QAction decrZoom(QLatin1String("Zoom out"), &menu); - decrZoom.setShortcut(QKeySequence(Qt::Key_Minus)); - connect(&decrZoom, SIGNAL(triggered()), this, SLOT(decreaseZoom())); + menu.addAction(QLatin1String("Zoom in"), + this, &QPixelTool::increaseZoom, Qt::Key_Plus); + menu.addAction(QLatin1String("Zoom out"), + this, &QPixelTool::decreaseZoom, Qt::Key_Minus); + menu.addSeparator(); // Freeze / Autoupdate - QAction freeze(QLatin1String("Frozen"), &menu); - freeze.setCheckable(true); - freeze.setChecked(tmpFreeze); - freeze.setShortcut(QKeySequence(Qt::Key_Space)); - QAction autoUpdate(QLatin1String("Continuous update"), &menu); - autoUpdate.setCheckable(true); - autoUpdate.setChecked(m_autoUpdate); - autoUpdate.setShortcut(QKeySequence(Qt::Key_A)); + QAction *freeze = addCheckableAction(menu, QLatin1String("Frozen"), + tmpFreeze, Qt::Key_Space); + QAction *autoUpdate = addCheckableAction(menu, QLatin1String("Continuous update"), + m_autoUpdate, Qt::Key_A); + menu.addSeparator(); // Copy to clipboard / save - QAction save(QLatin1String("Save as image"), &menu); - save.setShortcut(QKeySequence(QLatin1String("Ctrl+S"))); - connect(&save, SIGNAL(triggered()), this, SLOT(saveToFile())); + menu.addAction(QLatin1String("Save as image..."), + this, &QPixelTool::saveToFile, QKeySequence::SaveAs); #ifndef QT_NO_CLIPBOARD - QAction copy(QLatin1String("Copy to clipboard"), &menu); - copy.setShortcut(QKeySequence(QLatin1String("Ctrl+C"))); - connect(©, SIGNAL(triggered()), this, SLOT(copyToClipboard())); + menu.addAction(QLatin1String("Copy to clipboard"), + this, &QPixelTool::copyToClipboard, QKeySequence::Copy); #endif - menu.addAction(&title); - menu.addSeparator(); - menu.addAction(&whiteGrid); - menu.addAction(&blackGrid); - menu.addAction(&noGrid); - menu.addSeparator(); - menu.addAction(&incrGrid); - menu.addAction(&decrGrid); - menu.addSeparator(); - menu.addAction(&incrZoom); - menu.addAction(&decrZoom); menu.addSeparator(); - menu.addAction(&freeze); - menu.addAction(&autoUpdate); - menu.addSeparator(); - menu.addAction(&save); -#ifndef QT_NO_CLIPBOARD - menu.addAction(©); -#endif + menu.addAction(QLatin1String("About Qt"), qApp, &QApplication::aboutQt); menu.exec(mapToGlobal(e->pos())); // Read out grid settings - if (noGrid.isChecked()) m_gridActive = 0; - else if (blackGrid.isChecked()) m_gridActive = 1; - else m_gridActive = 2; - - m_autoUpdate = autoUpdate.isChecked(); - tmpFreeze = freeze.isChecked(); - + if (noGrid->isChecked()) + m_gridActive = 0; + else if (blackGrid->isChecked()) + m_gridActive = 1; + else + m_gridActive = 2; - m_freeze = tmpFreeze; + m_autoUpdate = autoUpdate->isChecked(); + m_freeze = freeze->isChecked(); } QSize QPixelTool::sizeHint() const @@ -407,6 +392,17 @@ QSize QPixelTool::sizeHint() const return m_initialSize; } +static inline QString pixelToolTitle(QPoint pos) +{ + if (QHighDpiScaling::isActive()) { + const int screenNumber = QApplication::desktop()->screenNumber(pos); + pos = QHighDpi::toNativePixels(pos, QGuiApplication::screens().at(screenNumber)); + } + return QCoreApplication::applicationName() + QLatin1String(" [") + + QString::number(pos.x()) + + QLatin1String(", ") + QString::number(pos.y()) + QLatin1Char(']'); +} + void QPixelTool::grabScreen() { if (m_preview_mode) { @@ -421,10 +417,8 @@ void QPixelTool::grabScreen() if (mousePos == m_lastMousePos && !m_autoUpdate) return; - if (m_lastMousePos != mousePos) { - setWindowTitle(QString::fromLatin1("PixelTool [%1, %2] ") - .arg(mousePos.x()).arg(mousePos.y())); - } + if (m_lastMousePos != mousePos) + setWindowTitle(pixelToolTitle(mousePos)); int w = int(width() / float(m_zoom)); int h = int(height() / float(m_zoom)); @@ -437,13 +431,15 @@ void QPixelTool::grabScreen() int x = mousePos.x() - w/2; int y = mousePos.y() - h/2; - QScreen *screen = qApp->screens().at(qApp->desktop()->screenNumber()); - m_buffer = screen->grabWindow(qApp->desktop()->winId(), x, y, w, h); + const QDesktopWidget *desktopWidget = QApplication::desktop(); + + QScreen *screen = QGuiApplication::screens().at(desktopWidget->screenNumber(this)); + m_buffer = screen->grabWindow(desktopWidget->winId(), x, y, w, h); QRegion geom(x, y, w, h); QRect screenRect; - for (int i=0; i<qApp->desktop()->numScreens(); ++i) - screenRect |= qApp->desktop()->screenGeometry(i); + for (int i = 0; i < desktopWidget->numScreens(); ++i) + screenRect |= desktopWidget->screenGeometry(i); geom -= screenRect; QVector<QRect> rects = geom.rects(); if (rects.size() > 0) { @@ -524,8 +520,7 @@ void QPixelTool::setGridSize(int gridSize) #ifndef QT_NO_CLIPBOARD void QPixelTool::copyToClipboard() { - QClipboard *cb = QApplication::clipboard(); - cb->setPixmap(m_buffer); + QGuiApplication::clipboard()->setPixmap(m_buffer); } #endif @@ -533,11 +528,26 @@ void QPixelTool::saveToFile() { bool oldFreeze = m_freeze; m_freeze = true; - QString name = QFileDialog::getSaveFileName(this, QLatin1String("Save as image"), QString(), QLatin1String("*.png")); - if (!name.isEmpty()) { - if (!name.endsWith(QLatin1String(".png"))) - name.append(QLatin1String(".png")); - m_buffer.save(name, "PNG"); + + QFileDialog fileDialog(this); + fileDialog.setWindowTitle(QLatin1String("Save as image")); + fileDialog.setAcceptMode(QFileDialog::AcceptSave); + fileDialog.setDirectory(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); + QStringList mimeTypes; + foreach (const QByteArray &mimeTypeB, QImageWriter::supportedMimeTypes()) + mimeTypes.append(QString::fromLatin1(mimeTypeB)); + fileDialog.setMimeTypeFilters(mimeTypes); + const QString pngType = QLatin1String("image/png"); + if (mimeTypes.contains(pngType)) { + fileDialog.selectMimeTypeFilter(pngType); + fileDialog.setDefaultSuffix(QLatin1String("png")); + } + + while (fileDialog.exec() == QDialog::Accepted + && !m_buffer.save(fileDialog.selectedFiles().first())) { + QMessageBox::warning(this, QLatin1String("Unable to write image"), + QLatin1String("Unable to write ") + + QDir::toNativeSeparators(fileDialog.selectedFiles().first())); } m_freeze = oldFreeze; } diff --git a/src/pixeltool/qpixeltool.h b/src/pixeltool/qpixeltool.h index 71be2ee6d..2b62daa78 100644 --- a/src/pixeltool/qpixeltool.h +++ b/src/pixeltool/qpixeltool.h @@ -43,23 +43,13 @@ class QPixelTool : public QWidget { Q_OBJECT public: - QPixelTool(QWidget *parent = 0); + explicit QPixelTool(QWidget *parent = Q_NULLPTR); ~QPixelTool(); - void timerEvent(QTimerEvent *event); - void paintEvent(QPaintEvent *event); - void keyPressEvent(QKeyEvent *event); - void keyReleaseEvent(QKeyEvent *event); - void resizeEvent(QResizeEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void contextMenuEvent(QContextMenuEvent *event); - - QSize sizeHint() const; - void setPreviewImage(const QImage &image); + QSize sizeHint() const Q_DECL_OVERRIDE; + public slots: void setZoom(int zoom); void setGridSize(int gridSize); @@ -75,6 +65,17 @@ public slots: void increaseZoom() { setZoom(m_zoom + 1); } void decreaseZoom() { setZoom(m_zoom - 1); } +protected: + void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE; + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE; + void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE; + void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; + void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void contextMenuEvent(QContextMenuEvent *event) Q_DECL_OVERRIDE; + private: void grabScreen(); void startZoomVisibleTimer(); |