| |
| |
| #include "imageviewer.h" |
| |
| |
| #include "tapp.h" |
| #include "menubarcommandids.h" |
| #include "flipbook.h" |
| #include "histogrampopup.h" |
| #include "sceneviewer.h" // ToggleCommandHandler |
| #include "mainwindow.h" //RecentFiles |
| |
| |
| #include "tools/toolcommandids.h" |
| #include "tools/cursors.h" |
| #include "tools/cursormanager.h" |
| #include "tools/stylepicker.h" |
| |
| |
| #include "toonzqt/menubarcommand.h" |
| #include "toonzqt/viewcommandids.h" |
| #include "toonzqt/imageutils.h" |
| |
| |
| #include "toonz/tscenehandle.h" |
| #include "toonz/toonzscene.h" |
| #include "toonz/sceneproperties.h" |
| #include "toonz/palettecontroller.h" |
| #include "toonz/tpalettehandle.h" |
| |
| |
| #include "tgl.h" |
| |
| |
| #include <QMenu> |
| #include <QAction> |
| #include <QMouseEvent> |
| #include <QWheelEvent> |
| |
| |
| |
| extern ToggleCommandHandler safeAreaToggle; |
| extern void getSafeAreaData(double &_smallSize, double &_largeSize); |
| |
| extern void getSafeAreaSizeList(QList<QList<double>> &_sizeList); |
| |
| |
| |
| |
| |
| |
| |
| namespace |
| { |
| |
| void drawSafeArea(const TRectD box) |
| { |
| glPushMatrix(); |
| glLoadIdentity(); |
| |
| tglColor(TPixel32::Red); |
| glLineStipple(1, 0xCCCC); |
| glEnable(GL_LINE_STIPPLE); |
| |
| tglDrawRect(box); |
| |
| QList<QList<double>> sizeList; |
| |
| getSafeAreaSizeList(sizeList); |
| |
| for (int i = 0; i < sizeList.size(); i++) { |
| QList<double> curSize = sizeList.at(i); |
| if (curSize.size() == 5) |
| tglColor(TPixel((int)curSize.at(2), (int)curSize.at(3), (int)curSize.at(4))); |
| else |
| tglColor(TPixel32::Red); |
| |
| double facX = -0.5 * (1 - curSize.at(0) / 100.0); |
| double facY = -0.5 * (1 - curSize.at(1) / 100.0); |
| tglDrawRect(box.enlarge(facX * box.getLx(), facY * box.getLy())); |
| } |
| |
| glDisable(GL_LINE_STIPPLE); |
| glPopMatrix(); |
| } |
| |
| |
| |
| inline TRect getImageBounds(const TImageP &img) |
| { |
| if (TRasterImageP ri = img) |
| return ri->getRaster()->getBounds(); |
| else if (TToonzImageP ti = img) |
| return ti->getRaster()->getBounds(); |
| else { |
| TVectorImageP vi = img; |
| return convert(vi->getBBox()); |
| } |
| } |
| |
| |
| |
| inline TRectD getImageBoundsD(const TImageP &img) |
| { |
| if (TRasterImageP ri = img) |
| return TRectD(0, 0, ri->getRaster()->getLx(), ri->getRaster()->getLy()); |
| else if (TToonzImageP ti = img) |
| return TRectD(0, 0, ti->getSize().lx, ti->getSize().ly); |
| else { |
| TVectorImageP vi = img; |
| return vi->getBBox(); |
| } |
| } |
| |
| |
| |
| class FlipZoomer : public ImageUtils::ShortcutZoomer |
| { |
| public: |
| FlipZoomer(ImageViewer *parent) : ShortcutZoomer(parent) {} |
| |
| bool zoom(bool zoomin, bool resetZoom) |
| { |
| static_cast<ImageViewer *>(getWidget())->zoomQt(zoomin, resetZoom); |
| return true; |
| } |
| |
| bool fit() |
| { |
| static_cast<ImageViewer *>(getWidget())->fitView(); |
| return true; |
| } |
| |
| bool toggleFullScreen(bool quit) |
| { |
| if (ImageUtils::FullScreenWidget *fsWidget = |
| dynamic_cast<ImageUtils::FullScreenWidget *>(getWidget()->parentWidget())) |
| return fsWidget->toggleFullScreen(quit); |
| |
| return false; |
| } |
| }; |
| |
| |
| |
| class ImageViewerShortcutReceiver |
| { |
| FlipBook *m_flipbook; |
| |
| public: |
| ImageViewerShortcutReceiver(FlipBook *flipbook) : m_flipbook(flipbook) {} |
| ~ImageViewerShortcutReceiver() {} |
| |
| bool exec(QKeyEvent *event) |
| { |
| CommandManager *cManager = CommandManager::instance(); |
| |
| if (event->key() == cManager->getKeyFromId(MI_FreezePreview)) { |
| m_flipbook->isFreezed() ? m_flipbook->unfreezePreview() : m_flipbook->freezePreview(); |
| return true; |
| } |
| |
| if (event->key() == cManager->getKeyFromId(MI_ClonePreview)) { |
| m_flipbook->clonePreview(); |
| return true; |
| } |
| |
| if (event->key() == cManager->getKeyFromId(MI_RegeneratePreview)) { |
| m_flipbook->regenerate(); |
| return true; |
| } |
| |
| if (event->key() == cManager->getKeyFromId(MI_RegenerateFramePr)) { |
| m_flipbook->regenerateFrame(); |
| return true; |
| } |
| |
| return false; |
| } |
| }; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| ImageViewer::ImageViewer(QWidget *parent, FlipBook *flipbook, bool showHistogram) |
| : QOpenGLWidget(parent) |
| , m_pressedMousePos(0, 0) |
| , m_mouseButton(Qt::NoButton) |
| , m_draggingZoomSelection(false) |
| , m_image() |
| , m_FPS(0) |
| , m_viewAff() |
| , m_pos(0, 0) |
| , m_visualSettings() |
| , m_compareSettings() |
| , m_isHistogramEnable(showHistogram) |
| , m_flipbook(flipbook) |
| , m_isColorModel(false) |
| , m_histogramPopup(0) |
| , m_isRemakingPreviewFx(false) |
| , m_rectRGBPick(false) |
| { |
| m_visualSettings.m_sceneProperties = TApp::instance()->getCurrentScene()->getScene()->getProperties(); |
| m_visualSettings.m_drawExternalBG = true; |
| setAttribute(Qt::WA_KeyCompression); |
| setFocusPolicy(Qt::StrongFocus); |
| |
| setMouseTracking(true); |
| |
| if (m_isHistogramEnable) |
| m_histogramPopup = new HistogramPopup(tr("Flipbook Histogram")); |
| |
| |
| |
| |
| } |
| |
| |
| |
| void ImageViewer::contextMenuEvent(QContextMenuEvent *event) |
| { |
| if (!m_flipbook) |
| return; |
| |
| QAction *action; |
| |
| if (m_isColorModel) { |
| event->ignore(); |
| return; |
| } |
| |
| QMenu *menu = new QMenu(this); |
| |
| if (m_flipbook->getPreviewedFx()) { |
| if (!(windowState() & Qt::WindowFullScreen)) { |
| action = menu->addAction(tr("Clone Preview")); |
| action->setShortcut(QKeySequence(CommandManager::instance()->getKeyFromId(MI_ClonePreview))); |
| connect(action, SIGNAL(triggered()), m_flipbook, SLOT(clonePreview())); |
| } |
| |
| if (m_flipbook->isFreezed()) { |
| action = menu->addAction(tr("Unfreeze Preview")); |
| action->setShortcut(QKeySequence(CommandManager::instance()->getKeyFromId(MI_FreezePreview))); |
| connect(action, SIGNAL(triggered()), m_flipbook, SLOT(unfreezePreview())); |
| } else { |
| action = menu->addAction(tr("Freeze Preview")); |
| action->setShortcut(QKeySequence(CommandManager::instance()->getKeyFromId(MI_FreezePreview))); |
| connect(action, SIGNAL(triggered()), m_flipbook, SLOT(freezePreview())); |
| } |
| |
| action = menu->addAction(tr("Regenerate Preview")); |
| action->setShortcut(QKeySequence(CommandManager::instance()->getKeyFromId(MI_RegeneratePreview))); |
| connect(action, SIGNAL(triggered()), m_flipbook, SLOT(regenerate())); |
| |
| action = menu->addAction(tr("Regenerate Frame Preview")); |
| action->setShortcut(QKeySequence(CommandManager::instance()->getKeyFromId(MI_RegenerateFramePr))); |
| connect(action, SIGNAL(triggered()), m_flipbook, SLOT(regenerateFrame())); |
| |
| menu->addSeparator(); |
| } |
| |
| action = menu->addAction(tr("Load / Append Images")); |
| connect(action, SIGNAL(triggered()), m_flipbook, SLOT(loadImages())); |
| |
| |
| action = CommandManager::instance()->getAction(MI_LoadRecentImage); |
| menu->addAction(action); |
| action->setParent(m_flipbook); |
| |
| if (m_flipbook->isSavable()) { |
| action = menu->addAction(tr("Save Images")); |
| connect(action, SIGNAL(triggered()), m_flipbook, SLOT(saveImages())); |
| } |
| menu->addSeparator(); |
| |
| QAction *reset = menu->addAction(tr("Reset View")); |
| reset->setShortcut(QKeySequence(CommandManager::instance()->getKeyFromId(V_ZoomReset))); |
| connect(reset, SIGNAL(triggered()), SLOT(resetView())); |
| |
| QAction *fit = menu->addAction(tr("Fit To Window")); |
| fit->setShortcut(QKeySequence(CommandManager::instance()->getKeyFromId(V_ZoomFit))); |
| connect(fit, SIGNAL(triggered()), SLOT(fitView())); |
| |
| #ifdef _WIN32 |
| |
| if (ImageUtils::FullScreenWidget *fsWidget = |
| dynamic_cast<ImageUtils::FullScreenWidget *>(parentWidget())) { |
| bool isFullScreen = (fsWidget->windowState() & Qt::WindowFullScreen) != 0; |
| |
| action = menu->addAction(isFullScreen ? tr("Exit Full Screen Mode") : tr("Full Screen Mode")); |
| |
| action->setShortcut(QKeySequence(CommandManager::instance()->getKeyFromId(V_ShowHideFullScreen))); |
| connect(action, SIGNAL(triggered()), fsWidget, SLOT(toggleFullScreen())); |
| } |
| |
| #endif |
| |
| bool addedSep = false; |
| |
| if (m_isHistogramEnable && visibleRegion().contains(event->pos())) { |
| menu->addSeparator(); |
| addedSep = true; |
| action = menu->addAction(tr("Show Histogram")); |
| connect(action, SIGNAL(triggered()), SLOT(showHistogram())); |
| } |
| |
| if (m_visualSettings.m_doCompare) { |
| if (!addedSep) |
| menu->addSeparator(); |
| action = menu->addAction(tr("Swap Compared Images")); |
| connect(action, SIGNAL(triggered()), SLOT(swapCompared())); |
| } |
| |
| menu->exec(event->globalPos()); |
| |
| action = CommandManager::instance()->getAction(MI_LoadRecentImage); |
| action->setParent(0); |
| |
| delete menu; |
| update(); |
| } |
| |
| |
| |
| void ImageViewer::setVisual(const ImagePainter::VisualSettings &settings) |
| { |
| m_visualSettings = settings; |
| m_visualSettings.m_sceneProperties = TApp::instance()->getCurrentScene()->getScene()->getProperties(); |
| m_visualSettings.m_drawExternalBG = true; |
| } |
| |
| |
| |
| ImageViewer::~ImageViewer() |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
| |
| |
| |
| |
| void ImageViewer::setImage(TImageP image) |
| { |
| m_image = image; |
| |
| if (m_isHistogramEnable && m_histogramPopup->isVisible()) |
| m_histogramPopup->setImage(image); |
| if (!isColorModel()) |
| repaint(); |
| else |
| update(); |
| } |
| |
| |
| |
| void ImageViewer::setHistogramTitle(QString levelName) |
| { |
| if (m_isHistogramEnable && m_histogramPopup->isVisible()) { |
| QString histogramTitle = QString("Histogram :: ") + levelName; |
| m_histogramPopup->setTitle(histogramTitle); |
| } |
| } |
| |
| |
| void ImageViewer::setHistogramEnable(bool enable) |
| { |
| m_isHistogramEnable = enable; |
| if (m_isHistogramEnable && !m_histogramPopup) |
| m_histogramPopup = new HistogramPopup(tr("Flipbook Histogram")); |
| } |
| |
| |
| |
| void ImageViewer::hideHistogram() |
| { |
| if (!m_isHistogramEnable) |
| return; |
| m_histogramPopup->setImage(TImageP()); |
| if (m_histogramPopup->isVisible()) { |
| m_histogramPopup->hide(); |
| m_histogramPopup->setTitle(tr("Flipbook Histogram")); |
| } |
| } |
| |
| |
| |
| void ImageViewer::initializeGL() |
| { |
| |
| glClear(GL_COLOR_BUFFER_BIT); |
| |
| |
| |
| |
| } |
| |
| |
| |
| void ImageViewer::resizeGL(int w, int h) |
| { |
| glViewport(0, 0, w, h); |
| glMatrixMode(GL_PROJECTION); |
| glLoadIdentity(); |
| double nearPlane = 100; |
| double farPlane = 2500; |
| double centerPlane = 1100; |
| glOrtho(0, w, 0, h, -4000, 4000); |
| glMatrixMode(GL_MODELVIEW); |
| glLoadIdentity(); |
| glTranslatef(0.375, 0.375, 0.0); |
| glTranslated(w * 0.5, h * 0.5, 0); |
| |
| |
| |
| |
| } |
| |
| |
| |
| void ImageViewer::paintGL() |
| { |
| |
| |
| |
| |
| TDimension viewerSize(width(), height()); |
| TAffine aff = m_viewAff; |
| |
| |
| |
| |
| TDimension imageSize; |
| TRect loadbox; |
| |
| if (m_flipbook) { |
| QString title = (!m_image) ? m_flipbook->getTitle() + tr(" :: Zoom : ") + QString::number(tround(sqrt(m_viewAff.det()) * 100)) + " %" |
| : m_flipbook->getLevelZoomTitle() + tr(" :: Zoom : ") + QString::number(tround(sqrt(m_viewAff.det()) * 100)) + " %"; |
| m_flipbook->parentWidget()->setWindowTitle(title); |
| imageSize = m_flipbook->getImageSize(); |
| if (m_visualSettings.m_useLoadbox && m_flipbook->getLoadbox() != TRect()) |
| loadbox = m_flipbook->getLoadbox(); |
| } |
| m_visualSettings.m_sceneProperties = TApp::instance()->getCurrentScene()->getScene()->getProperties(); |
| |
| m_visualSettings.m_useChecks = m_isColorModel; |
| ImagePainter::paintImage(m_image, imageSize, viewerSize, aff, m_visualSettings, m_compareSettings, loadbox); |
| |
| |
| |
| if (m_isRemakingPreviewFx) { |
| glPushMatrix(); |
| glLoadIdentity(); |
| glColor3d(1.0, 0.0, 0.0); |
| |
| glBegin(GL_LINE_LOOP); |
| glVertex2d(5, 5); |
| glVertex2d(5, height() - 5); |
| glVertex2d(width() - 5, height() - 5); |
| glVertex2d(width() - 5, 5); |
| glEnd(); |
| |
| glBegin(GL_LINE_LOOP); |
| glVertex2d(10, 10); |
| glVertex2d(10, height() - 10); |
| glVertex2d(width() - 10, height() - 10); |
| glVertex2d(width() - 10, 10); |
| glEnd(); |
| glPopMatrix(); |
| } |
| |
| if (!m_image) { |
| |
| |
| |
| |
| return; |
| } |
| |
| if (safeAreaToggle.getStatus() && !m_isColorModel) { |
| TRasterImageP rimg = (TRasterImageP)m_image; |
| TVectorImageP vimg = (TVectorImageP)m_image; |
| TToonzImageP timg = (TToonzImageP)m_image; |
| TRect bbox; |
| |
| TPointD centerD; |
| TRect bounds; |
| if (rimg) { |
| centerD = rimg->getRaster()->getCenterD(); |
| bounds = rimg->getRaster()->getBounds(); |
| } else if (timg) { |
| centerD = timg->getRaster()->getCenterD(); |
| bounds = timg->getRaster()->getBounds(); |
| } |
| |
| if (!vimg) { |
| TAffine aff = TTranslation(viewerSize.lx * 0.5, viewerSize.ly * 0.5) * m_viewAff * TTranslation(-centerD); |
| TRectD bbox = aff * TRectD(0, 0, bounds.getLx() - 1, bounds.getLy() - 1); |
| drawSafeArea(bbox); |
| } |
| } |
| TPoint fromPos, toPos; |
| |
| if (m_visualSettings.m_defineLoadbox && m_flipbook) { |
| TRect loadbox = convert(getImgToWidgetAffine() * convert(m_flipbook->getLoadbox())); |
| if (loadbox != TRect()) { |
| TPoint p00 = loadbox.getP00(); |
| TPoint p11 = loadbox.getP11(); |
| fromPos = TPoint(p00.x - width() * 0.5, height() * 0.5 - p00.y); |
| toPos = TPoint(p11.x - width() * 0.5, height() * 0.5 - p11.y); |
| } |
| } else if (m_draggingZoomSelection || m_rectRGBPick) { |
| fromPos = TPoint(m_pressedMousePos.x - width() * 0.5, height() * 0.5 - m_pressedMousePos.y); |
| toPos = TPoint(m_pos.x() - width() * 0.5, height() * 0.5 - m_pos.y()); |
| } |
| if (fromPos != TPoint() || toPos != TPoint()) { |
| if (m_rectRGBPick) { |
| tglColor(TPixel32::Red); |
| |
| glLineStipple(1, 0x3F33); |
| glEnable(GL_LINE_STIPPLE); |
| |
| glBegin(GL_LINE_STRIP); |
| |
| int margin = (fromPos.y < toPos.y) ? -3 : 3; |
| glVertex2i(toPos.x, toPos.y + margin); |
| glVertex2i(toPos.x, fromPos.y); |
| glVertex2i(fromPos.x, fromPos.y); |
| glVertex2i(fromPos.x, toPos.y); |
| margin = (fromPos.x < toPos.x) ? -3 : 3; |
| glVertex2i(toPos.x + margin, toPos.y); |
| glEnd(); |
| glDisable(GL_LINE_STIPPLE); |
| } else { |
| tglColor(m_draggingZoomSelection ? TPixel32::Red : TPixel32::Blue); |
| glBegin(GL_LINE_STRIP); |
| glVertex2i(fromPos.x, fromPos.y); |
| glVertex2i(fromPos.x, toPos.y); |
| glVertex2i(toPos.x, toPos.y); |
| glVertex2i(toPos.x, fromPos.y); |
| glVertex2i(fromPos.x, fromPos.y); |
| glEnd(); |
| } |
| } |
| |
| |
| |
| |
| } |
| |
| |
| |
| |
| void ImageViewer::panQt(const QPoint &delta) |
| { |
| if (delta == QPoint()) |
| return; |
| |
| |
| QPoint delta_(delta.x(), delta.y()); |
| |
| TToonzImageP timg = (TToonzImageP)m_image; |
| TRasterImageP rimg = (TRasterImageP)m_image; |
| if (timg || rimg) { |
| bool isXPlus = delta.x() > 0; |
| bool isYPlus = delta.y() > 0; |
| |
| TDimension imgSize((timg) ? timg->getSize() : rimg->getRaster()->getSize()); |
| int subSampling = (timg) ? timg->getSubsampling() : rimg->getSubsampling(); |
| |
| TPointD cornerPos = TPointD(imgSize.lx * ((isXPlus) ? -1 : 1), imgSize.ly * ((isYPlus) ? 1 : -1)) * (0.5 / (double)subSampling); |
| cornerPos = m_viewAff * cornerPos; |
| |
| if ((cornerPos.x > 0) == isXPlus) |
| delta_.setX(0); |
| if ((cornerPos.y < 0) == isYPlus) |
| delta_.setY(0); |
| } |
| |
| setViewAff(TTranslation(delta_.x(), -delta_.y()) * m_viewAff); |
| |
| update(); |
| } |
| |
| |
| |
| |
| |
| |
| void ImageViewer::zoomQt(const QPoint ¢er, double factor) |
| { |
| if (factor == 1.0) |
| return; |
| TPointD delta(center.x(), center.y()); |
| |
| setViewAff(TTranslation(delta) * TScale(factor) * TTranslation(-delta) * m_viewAff); |
| update(); |
| } |
| |
| |
| |
| void ImageViewer::zoomQt(bool forward, bool reset) |
| { |
| double scale2 = m_viewAff.det(); |
| if (reset) |
| setViewAff(TAffine()); |
| else if (((scale2 < 100000 || !forward) && (scale2 > 0.001 * 0.05 || forward))) { |
| double oldZoomScale = sqrt(scale2); |
| double zoomScale = reset ? 1 : ImageUtils::getQuantizedZoomFactor(oldZoomScale, forward); |
| setViewAff(TScale(zoomScale / oldZoomScale) * m_viewAff); |
| } |
| update(); |
| } |
| |
| |
| |
| void ImageViewer::dragCompare(const QPoint &dp) |
| { |
| if (m_compareSettings.m_dragCompareX) |
| m_compareSettings.m_compareX += ((double)dp.x()) / width(); |
| else if (m_compareSettings.m_dragCompareY) |
| m_compareSettings.m_compareY -= ((double)dp.y()) / height(); |
| |
| m_compareSettings.m_compareX = tcrop(m_compareSettings.m_compareX, 0.0, 1.0); |
| m_compareSettings.m_compareY = tcrop(m_compareSettings.m_compareY, 0.0, 1.0); |
| |
| update(); |
| } |
| |
| |
| |
| void ImageViewer::updateLoadbox(const TPoint &curPos) |
| { |
| TAffine aff = getImgToWidgetAffine(); |
| TRect r = m_flipbook->getLoadbox(); |
| if (m_dragType == eDrawRect) |
| r = convert(aff.inv() * convert(TRect(m_pressedMousePos, curPos))); |
| else if (m_dragType == eMoveRect) |
| r = r + (TPoint(curPos.x, -curPos.y) - TPoint(m_pos.x(), -m_pos.y())); |
| else { |
| double fac = sqrt(1.0 / fabs(aff.det())); |
| |
| if (m_dragType & eMoveLeft) |
| r.x0 += fac * (curPos.x - m_pos.x()); |
| if (m_dragType & eMoveRight) |
| r.x1 += fac * (curPos.x - m_pos.x()); |
| if (m_dragType & eMoveDown) |
| r.y1 -= fac * (curPos.y - m_pos.y()); |
| if (m_dragType & eMoveUp) |
| r.y0 -= fac * (curPos.y - m_pos.y()); |
| } |
| m_flipbook->setLoadbox(r); |
| } |
| |
| |
| void ImageViewer::updateCursor(const TPoint &curPos) |
| { |
| int dragType = getDragType(curPos, convert(getImgToWidgetAffine() * convert(m_flipbook->getLoadbox()))); |
| |
| switch (dragType) { |
| case eMoveRect: |
| setCursor(Qt::SizeAllCursor); |
| break; |
| case eMoveLeft: |
| case eMoveRight: |
| setCursor(Qt::SizeHorCursor); |
| break; |
| case eMoveDown: |
| case eMoveUp: |
| setCursor(Qt::SizeVerCursor); |
| break; |
| case eMoveLeft | eMoveUp: |
| case eMoveRight | eMoveDown: |
| setCursor(Qt::SizeBDiagCursor); |
| break; |
| case eMoveLeft | eMoveDown: |
| case eMoveRight | eMoveUp: |
| setCursor(Qt::SizeFDiagCursor); |
| break; |
| default: |
| setCursor(Qt::ArrowCursor); |
| break; |
| } |
| } |
| |
| |
| |
| |
| void ImageViewer::mouseMoveEvent(QMouseEvent *event) |
| { |
| TPoint curPos = TPoint(event->pos().x(), event->pos().y()); |
| |
| if (m_visualSettings.m_defineLoadbox && m_flipbook) { |
| |
| if (m_mouseButton == Qt::LeftButton) |
| updateLoadbox(curPos); |
| else if (m_mouseButton == Qt::MidButton) |
| panQt(event->pos() - m_pos); |
| else |
| updateCursor(curPos); |
| update(); |
| event->ignore(); |
| m_pos = event->pos(); |
| return; |
| } |
| |
| |
| if (!m_isColorModel) { |
| |
| if (m_isHistogramEnable && m_histogramPopup->isVisible()) |
| setToolCursor(this, ToolCursor::PickerRGB); |
| else |
| setCursor(Qt::ArrowCursor); |
| } |
| |
| if (m_visualSettings.m_doCompare && m_mouseButton == Qt::NoButton) { |
| if (fabs(curPos.x - width() * m_compareSettings.m_compareX) < 20) |
| setToolCursor(this, ToolCursor::ScaleHCursor); |
| else if (fabs((height() - curPos.y) - height() * m_compareSettings.m_compareY) < 20) |
| setToolCursor(this, ToolCursor::ScaleVCursor); |
| } |
| |
| if (m_compareSettings.m_dragCompareX || m_compareSettings.m_dragCompareY) |
| dragCompare(event->pos() - m_pos); |
| else if (m_mouseButton == Qt::MidButton) |
| panQt(event->pos() - m_pos); |
| |
| m_pos = event->pos(); |
| |
| |
| if (m_isHistogramEnable && m_histogramPopup->isVisible() && !m_isColorModel) { |
| |
| if (m_mouseButton == Qt::LeftButton && (event->modifiers() & Qt::ControlModifier)) { |
| if (!m_rectRGBPick && !m_visualSettings.m_defineLoadbox && |
| (abs(m_pos.x() - m_pressedMousePos.x) > 10 || |
| abs(m_pos.y() - m_pressedMousePos.y) > 10) && |
| !(m_compareSettings.m_dragCompareX || m_compareSettings.m_dragCompareY) && |
| m_flipbook) |
| m_rectRGBPick = true; |
| |
| if (m_rectRGBPick) { |
| update(); |
| rectPickColor(); |
| } |
| } |
| |
| update(); |
| pickColor(event); |
| return; |
| } |
| |
| if (m_mouseButton == Qt::LeftButton && !m_isColorModel && (event->modifiers() & Qt::AltModifier)) { |
| if (!m_draggingZoomSelection && !m_visualSettings.m_defineLoadbox && |
| (abs(m_pos.x() - m_pressedMousePos.x) > 10 || |
| abs(m_pos.y() - m_pressedMousePos.y) > 10) && |
| !(m_compareSettings.m_dragCompareX || m_compareSettings.m_dragCompareY) && |
| m_flipbook) |
| m_draggingZoomSelection = true; |
| |
| if (m_draggingZoomSelection) |
| update(); |
| } else |
| m_draggingZoomSelection = false; |
| |
| if (m_isColorModel && m_mouseButton == Qt::LeftButton) { |
| event->ignore(); |
| } |
| } |
| |
| |
| |
| |
| void ImageViewer::setPickedColorToStyleEditor(const TPixel32 &color) |
| { |
| |
| TPaletteHandle *ph = TApp::instance()->getPaletteController()->getCurrentPalette(); |
| if (ph->getStyleIndex() == 0) |
| return; |
| |
| TApp::instance()->getPaletteController()->setColorSample(color); |
| } |
| |
| |
| |
| |
| void ImageViewer::pickColor(QMouseEvent *event, bool putValueToStyleEditor) |
| { |
| if (!m_isHistogramEnable) |
| return; |
| if (!m_histogramPopup->isVisible()) |
| return; |
| |
| |
| if ((!m_image) || |
| !rect().contains(event->pos())) { |
| |
| m_histogramPopup->updateInfo(TPixel32::Transparent, TPointD(-1, -1)); |
| return; |
| } |
| |
| StylePicker picker(m_image); |
| |
| TPoint mousePos = TPoint(event->pos().x(), height() - 1 - event->pos().y()); |
| TRectD area = TRectD(mousePos.x, mousePos.y, mousePos.x, mousePos.y); |
| |
| |
| |
| |
| |
| const TPixel32 pix = picker.pickColor(area); |
| |
| |
| |
| |
| |
| QPoint viewP = mapFrom(this, event->pos()); |
| TPointD pos = getViewAff().inv() * TPointD(viewP.x() - width() / 2, |
| -viewP.y() + height() / 2); |
| TPointD imagePos = TPointD(0.5 * m_image->getBBox().getLx() + pos.x, |
| 0.5 * m_image->getBBox().getLy() + pos.y); |
| if (m_image->getBBox().contains(imagePos)) { |
| |
| m_histogramPopup->updateInfo(pix, imagePos); |
| |
| if (putValueToStyleEditor) |
| setPickedColorToStyleEditor(pix); |
| } else { |
| |
| m_histogramPopup->updateInfo(TPixel32::Transparent, TPointD(-1, -1)); |
| } |
| } |
| |
| |
| |
| |
| void ImageViewer::rectPickColor(bool putValueToStyleEditor) |
| { |
| if (!m_isHistogramEnable) |
| return; |
| if (!m_histogramPopup->isVisible()) |
| return; |
| |
| StylePicker picker(m_image); |
| |
| TPoint startPos = TPoint(m_pressedMousePos.x, height() - 1 - m_pressedMousePos.y); |
| TPoint endPos = TPoint(m_pos.x(), height() - 1 - m_pos.y()); |
| TRectD area = TRectD(convert(startPos), convert(endPos)); |
| area = area.enlarge(-1, -1); |
| if (area.getLx() < 2 || area.getLy() < 2) { |
| m_histogramPopup->updateAverageColor(TPixel32::Transparent); |
| return; |
| } |
| |
| |
| |
| |
| |
| const TPixel32 pix = picker.pickColor(area.enlarge(-1, -1)); |
| |
| |
| |
| |
| |
| |
| m_histogramPopup->updateAverageColor(pix); |
| |
| if (putValueToStyleEditor) |
| setPickedColorToStyleEditor(pix); |
| } |
| |
| |
| |
| |
| |
| |
| int ImageViewer::getDragType(const TPoint &pos, const TRect &loadbox) |
| { |
| if (loadbox == TRect()) |
| return eDrawRect; |
| |
| int ret = 0, dx = std::min(abs(loadbox.x0 - pos.x), abs(loadbox.x1 - pos.x)), |
| dy = std::min(abs(loadbox.y0 - pos.y), abs(loadbox.y1 - pos.y)); |
| |
| if (dx > 10 && dy > 10) |
| return (loadbox.contains(pos)) ? eMoveRect : eDrawRect; |
| |
| if (dx <= 10 && pos.y >= loadbox.y0 - 10 && pos.y <= loadbox.y1 + 10) { |
| if (dx == abs(loadbox.x0 - pos.x)) |
| ret = eMoveLeft; |
| else if (dx == abs(loadbox.x1 - pos.x)) |
| ret = eMoveRight; |
| } else if (dy <= 10 && pos.x >= loadbox.x0 - 10 && pos.x <= loadbox.x1 + 10) { |
| if (dy == abs(loadbox.y0 - pos.y)) |
| return eMoveDown; |
| else |
| return eMoveUp; |
| } else |
| return eDrawRect; |
| |
| if (dy > 10) |
| return ret; |
| |
| return ret | (dy == (abs(loadbox.y0 - pos.y)) ? eMoveDown : eMoveUp); |
| } |
| |
| |
| void ImageViewer::mouseDoubleClickEvent(QMouseEvent *event) |
| { |
| if (m_visualSettings.m_defineLoadbox && m_flipbook) { |
| m_flipbook->setLoadbox(TRect()); |
| update(); |
| event->ignore(); |
| } |
| } |
| |
| |
| |
| void ImageViewer::mousePressEvent(QMouseEvent *event) |
| { |
| m_pos = event->pos(); |
| m_pressedMousePos = TPoint(m_pos.x(), m_pos.y()); |
| m_mouseButton = event->button(); |
| m_draggingZoomSelection = false; |
| |
| if (m_mouseButton != Qt::LeftButton) { |
| event->ignore(); |
| return; |
| } |
| if (m_visualSettings.m_defineLoadbox && m_flipbook) |
| m_dragType = getDragType(m_pressedMousePos, convert(getImgToWidgetAffine() * convert(m_flipbook->getLoadbox()))); |
| else if (m_visualSettings.m_doCompare) { |
| if (fabs(m_pos.x() - width() * m_compareSettings.m_compareX) < 20) { |
| m_compareSettings.m_dragCompareX = true; |
| m_compareSettings.m_dragCompareY = false; |
| m_compareSettings.m_compareY = ImagePainter::DefaultCompareValue; |
| update(); |
| } else if (fabs((height() - m_pos.y()) - height() * m_compareSettings.m_compareY) < 20) { |
| m_compareSettings.m_dragCompareY = true; |
| m_compareSettings.m_dragCompareX = false; |
| m_compareSettings.m_compareX = ImagePainter::DefaultCompareValue; |
| update(); |
| } else |
| m_compareSettings.m_dragCompareX = m_compareSettings.m_dragCompareY = false; |
| } |
| |
| |
| if (m_isHistogramEnable && m_histogramPopup->isVisible() && !m_isColorModel && !(event->modifiers() & Qt::ControlModifier)) |
| { |
| update(); |
| pickColor(event, true); |
| } |
| |
| event->ignore(); |
| } |
| |
| |
| |
| |
| void ImageViewer::mouseReleaseEvent(QMouseEvent *event) |
| { |
| if (m_draggingZoomSelection && !m_visualSettings.m_defineLoadbox) { |
| m_draggingZoomSelection = false; |
| |
| int left, right, top, bottom; |
| if (m_pos.x() < m_pressedMousePos.x) |
| left = m_pos.x(), right = m_pressedMousePos.x; |
| else |
| right = m_pos.x(), left = m_pressedMousePos.x; |
| if (m_pos.y() < m_pressedMousePos.y) |
| top = m_pos.y(), bottom = m_pressedMousePos.y; |
| else |
| bottom = m_pos.y(), top = m_pressedMousePos.y; |
| |
| adaptView(QRect(QPoint(left, top), QPoint(right, bottom))); |
| } |
| |
| if (m_rectRGBPick) { |
| |
| rectPickColor(true); |
| |
| m_rectRGBPick = false; |
| update(); |
| } |
| |
| m_pos = QPoint(0, 0); |
| m_mouseButton = Qt::NoButton; |
| m_compareSettings.m_dragCompareX = m_compareSettings.m_dragCompareY = false; |
| |
| event->ignore(); |
| } |
| |
| |
| |
| |
| void ImageViewer::wheelEvent(QWheelEvent *event) |
| { |
| if (event->orientation() == Qt::Horizontal) |
| return; |
| int delta = event->delta() > 0 ? 120 : -120; |
| QPoint center(event->pos().x() - width() / 2, -event->pos().y() + height() / 2); |
| zoomQt(center, exp(0.001 * delta)); |
| } |
| |
| |
| |
| void ImageViewer::swapCompared() |
| { |
| m_compareSettings.m_swapCompared = !m_compareSettings.m_swapCompared; |
| update(); |
| } |
| |
| |
| |
| void ImageViewer::setViewAff(TAffine viewAff) |
| { |
| m_viewAff = viewAff; |
| update(); |
| if (m_flipbook && m_flipbook->getPreviewedFx()) |
| |
| m_flipbook->schedulePreviewedFxUpdate(); |
| } |
| |
| |
| |
| void ImageViewer::resetView() |
| { |
| zoomQt(false, true); |
| } |
| |
| |
| |
| void ImageViewer::fitView() |
| { |
| if (!m_image) |
| return; |
| TRect imgBounds(getImageBounds(m_image)); |
| adaptView(imgBounds, imgBounds); |
| } |
| |
| |
| |
| |
| |
| void ImageViewer::updateImageViewer() |
| { |
| setViewAff(TAffine()); |
| m_pos = QPoint(0, 0); |
| update(); |
| } |
| |
| |
| |
| TAffine ImageViewer::getImgToWidgetAffine() const |
| { |
| assert(m_image); |
| return getImgToWidgetAffine(getImageBoundsD(m_image)); |
| } |
| |
| |
| |
| |
| TAffine ImageViewer::getImgToWidgetAffine(const TRectD &geom) const |
| { |
| TPointD geomCenter((geom.x0 + geom.x1) * 0.5, (geom.y0 + geom.y1) * 0.5); |
| |
| QRect widGeom(geometry()); |
| TPointD viewerCenter( |
| (widGeom.left() + widGeom.right() + 1) * 0.5, |
| (widGeom.top() + widGeom.bottom() + 1) * 0.5); |
| |
| return TAffine( |
| TAffine(1.0, 0.0, 0.0, 0.0, -1.0, height()) * |
| TTranslation(viewerCenter) * |
| m_viewAff * |
| TTranslation(-geomCenter)); |
| } |
| |
| |
| |
| |
| void ImageViewer::adaptView(const TRect &imgRect, const TRect &viewRect) |
| { |
| QRect viewerRect(geometry()); |
| |
| double imageScale = |
| std::min(viewerRect.width() / (double)viewRect.getLx(), |
| viewerRect.height() / (double)viewRect.getLy()); |
| |
| TPointD viewRectCenter((viewRect.x0 + viewRect.x1 + 1) * 0.5, (viewRect.y0 + viewRect.y1 + 1) * 0.5); |
| TPointD imgRectCenter((imgRect.x0 + imgRect.x1 + 1) * 0.5, (imgRect.y0 + imgRect.y1 + 1) * 0.5); |
| |
| TAffine newViewAff(TScale(imageScale, imageScale) * TTranslation(imgRectCenter - viewRectCenter)); |
| setViewAff(newViewAff); |
| } |
| |
| |
| |
| |
| void ImageViewer::adaptView(const QRect &geomRect) |
| { |
| if (!m_image) |
| return; |
| |
| |
| TRect imgBounds(getImageBounds(m_image)); |
| TRectD imgBoundsD(imgBounds.x0, imgBounds.y0, imgBounds.x1 + 1, imgBounds.y1 + 1); |
| |
| TRectD geomRectD(geomRect.left(), geomRect.top(), geomRect.right() + 1, geomRect.bottom() + 1); |
| TRectD viewRectD(getImgToWidgetAffine().inv() * geomRectD); |
| TRect viewRect(tfloor(viewRectD.x0), tfloor(viewRectD.y0), tceil(viewRectD.x1) - 1, tceil(viewRectD.y1) - 1); |
| |
| adaptView(imgBounds, viewRect); |
| } |
| |
| void ImageViewer::doSwapBuffers() { |
| glFlush(); |
| } |
| |
| void ImageViewer::changeSwapBehavior(bool enable) { |
| setUpdateBehavior(enable ? PartialUpdate : NoPartialUpdate); |
| } |
| |
| |
| |
| void ImageViewer::keyPressEvent(QKeyEvent *event) |
| { |
| if (FlipZoomer(this).exec(event)) |
| return; |
| |
| ImageViewerShortcutReceiver(m_flipbook).exec(event); |
| } |
| |
| |
| |
| |
| class LoadRecentFlipbookImagesCommandHandler : public MenuItemHandler |
| { |
| public: |
| LoadRecentFlipbookImagesCommandHandler() : MenuItemHandler(MI_LoadRecentImage) {} |
| void execute() |
| { |
| QAction *act = CommandManager::instance()->getAction(MI_LoadRecentImage); |
| |
| |
| FlipBook *flip = qobject_cast<FlipBook *>(act->parentWidget()); |
| if (!flip) |
| return; |
| |
| DVMenuAction *menu = dynamic_cast<DVMenuAction *>(act->menu()); |
| int index = menu->getTriggeredActionIndex(); |
| QString path = RecentFiles::instance()->getFilePath(index, RecentFiles::Flip); |
| |
| TFilePath fp(path.toStdWString()); |
| |
| |
| ::viewFile(fp, -1, -1, -1, 1, 0, flip, false); |
| |
| RecentFiles::instance()->moveFilePath(index, 0, RecentFiles::Flip); |
| } |
| } loadRecentFlipbookImagesCommandHandler; |
| |
| |
| |
| |
| class ClearRecentFlipbookImagesCommandHandler : public MenuItemHandler |
| { |
| public: |
| ClearRecentFlipbookImagesCommandHandler() : MenuItemHandler(MI_ClearRecentImage) {} |
| void execute() |
| { |
| RecentFiles::instance()->clearRecentFilesList(RecentFiles::Flip); |
| } |
| } clearRecentFlipbookImagesCommandHandler; |
| |