File indexing completed on 2024-04-28 05:38:13

0001 /***************************************************************************
0002  *  Copyright (C) 2007 by Romain Campioni                  *
0003  *  Copyright (C) 2009 by Renaud Guezennec                             *
0004  *   https://rolisteam.org/contact                   *
0005  *                                                                         *
0006  *   rolisteam is free software; you can redistribute it and/or modify  *
0007  *   it under the terms of the GNU General Public License as published by  *
0008  *   the Free Software Foundation; either version 2 of the License, or     *
0009  *   (at your option) any later version.                                   *
0010  *                                                                         *
0011  *   This program is distributed in the hope that it will be useful,       *
0012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0014  *   GNU General Public License for more details.                          *
0015  *                                                                         *
0016  *   You should have received a copy of the GNU General Public License     *
0017  *   along with this program; if not, write to the                         *
0018  *   Free Software Foundation, Inc.,                                       *
0019  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0020  ***************************************************************************/
0021 
0022 #include <QDebug>
0023 #include <QScrollBar>
0024 #include <QShortcut>
0025 #include <QtGui>
0026 
0027 #include "controller/view_controller/imagecontroller.h"
0028 #include "image.h"
0029 #include "network/clientconnection.h"
0030 #include "network/networkmessagewriter.h"
0031 //#include "widgets/onlinepicturedialog.h"
0032 
0033 /********************************************************************/
0034 /* Constructeur                                                     */
0035 /********************************************************************/
0036 Image::Image(ImageController* ctrl, QWidget* parent)
0037     : MediaContainer(ctrl, MediaContainer::ContainerType::ImageContainer, parent)
0038     , m_ctrl(ctrl)
0039     , m_imageLabel(new QLabel())
0040     , m_widgetArea(new QScrollArea())
0041     , m_NormalSize(0, 0)
0042 {
0043     setObjectName("Image");
0044     connect(m_ctrl, &ImageController::zoomLevelChanged, this, &Image::resizeLabel);
0045     connect(m_ctrl, &ImageController::fitWindowChanged, this, &Image::fitWindow);
0046     connect(m_ctrl, &ImageController::pixmapChanged, this, &Image::initImage);
0047     connect(m_ctrl, &ImageController::cursorChanged, this, [this]() { m_imageLabel->setCursor(m_ctrl->cursor()); });
0048 
0049     setWindowIcon(QIcon::fromTheme("image-x-generic"));
0050     createActions();
0051 
0052     if(m_ctrl && m_ctrl->isMovie())
0053         addAction(m_playAct);
0054 
0055     connect(m_ctrl, &ImageController::nameChanged, this,
0056             [this]() { setWindowTitle(tr("%1 - Image").arg(m_ctrl->name())); });
0057 
0058     m_widgetArea->setAlignment(Qt::AlignCenter);
0059     m_imageLabel->setLineWidth(0);
0060     m_imageLabel->setFrameStyle(QFrame::NoFrame);
0061     m_widgetArea->setWidget(m_imageLabel);
0062     m_fitWindowAct->setChecked(m_preferences->value("PictureAdjust", true).toBool());
0063     setWidget(m_widgetArea.get());
0064     initImage();
0065     if(m_ctrl)
0066         setWindowTitle(tr("%1 - Image").arg(m_ctrl->name()));
0067 }
0068 
0069 Image::~Image()= default;
0070 
0071 void Image::initImage()
0072 {
0073     if(!m_ctrl || m_ctrl->pixmap().isNull())
0074         return;
0075 
0076     auto pixmap= m_ctrl->pixmap();
0077 
0078     m_imageLabel->setPixmap(m_ctrl->scaledPixmap());
0079     m_imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
0080     m_imageLabel->setScaledContents(true);
0081     m_imageLabel->resize(pixmap.size());
0082     fitWorkSpace();
0083     fitWindow();
0084 }
0085 
0086 void Image::mousePressEvent(QMouseEvent* event)
0087 {
0088     if(event->button() == Qt::LeftButton)
0089     {
0090         m_allowedMove= true;
0091         m_startingPoint= event->pos();
0092         m_horizontalStart= m_widgetArea->horizontalScrollBar()->value();
0093         m_verticalStart= m_widgetArea->verticalScrollBar()->value();
0094     }
0095     QMdiSubWindow::mousePressEvent(event);
0096 }
0097 
0098 void Image::mouseReleaseEvent(QMouseEvent* event)
0099 {
0100     if(event->button() == Qt::LeftButton)
0101     {
0102         m_allowedMove= false;
0103     }
0104 
0105     QMdiSubWindow::mouseReleaseEvent(event);
0106 }
0107 
0108 void Image::mouseMoveEvent(QMouseEvent* event)
0109 {
0110     if(m_allowedMove)
0111     {
0112         QPoint diff= m_startingPoint - event->pos();
0113         m_widgetArea->horizontalScrollBar()->setValue(m_horizontalStart + diff.x());
0114         m_widgetArea->verticalScrollBar()->setValue(m_verticalStart + diff.y());
0115     }
0116     QMdiSubWindow::mouseMoveEvent(event);
0117 }
0118 
0119 void Image::resizeLabel()
0120 {
0121     if(m_fitWindowAct->isChecked())
0122     {
0123         int w= m_widgetArea->viewport()->rect().width();
0124         int h= m_widgetArea->viewport()->rect().height();
0125         if(w > h * m_ctrl->ratioV())
0126         {
0127             m_imageLabel->resize(static_cast<int>(h * m_ctrl->ratioV()), h);
0128         }
0129         else
0130         {
0131             m_imageLabel->resize(w, static_cast<int>(w * m_ctrl->ratioH()));
0132         }
0133     }
0134     else if((m_NormalSize.height() != 0) && (m_NormalSize.width() != 0))
0135     {
0136         m_imageLabel->resize(m_ctrl->zoomLevel() * m_NormalSize);
0137     }
0138     else
0139     {
0140         m_imageLabel->resize(m_ctrl->zoomLevel() * m_ctrl->pixmap().size());
0141         m_NormalSize= widget()->size();
0142     }
0143 }
0144 
0145 void Image::fitWorkSpace()
0146 {
0147     /* Better computation
0148      * if(nullptr!=parentWidget())
0149     {
0150         QSize windowsize = parentWidget()->size();//right size
0151         while((windowsize.height()<(m_zoomLevel * m_pixMap.height()))||(windowsize.width()<(m_zoomLevel *
0152     m_pixMap.width())))
0153         {
0154             m_zoomLevel -= 0.05;
0155         }
0156         setGeometry(0,0,m_pixMap.width()*m_zoomLevel,m_pixMap.height()*m_zoomLevel);
0157         m_imageLabel->resize(m_pixMap.size());
0158         m_NormalSize = QSize(0,0);
0159         resizeLabel();
0160         m_zoomLevel = 1.0;
0161     }*/
0162 
0163     if(nullptr == parentWidget() || m_ctrl->isMovie())
0164         return;
0165 
0166     auto pixmap= m_ctrl->pixmap();
0167 
0168     QSize windowsize= parentWidget()->size(); // right size
0169     while((windowsize.height() < (m_ctrl->zoomLevel() * pixmap.height()))
0170           || (windowsize.width() < (m_ctrl->zoomLevel() * pixmap.width())))
0171     {
0172         m_ctrl->zoomOut(0.1);
0173     }
0174     m_imageLabel->resize(pixmap.size());
0175     m_NormalSize= QSize(0, 0);
0176     resizeLabel();
0177     setGeometry(m_imageLabel->rect().adjusted(0, 0, 4, 4));
0178     m_ctrl->setZoomLevel(1.0);
0179 }
0180 void Image::wheelEvent(QWheelEvent* event)
0181 {
0182     if(event->modifiers() == Qt::ControlModifier)
0183     {
0184         int delta= event->angleDelta().y();
0185         (delta > 0) ? m_ctrl->zoomIn() : m_ctrl->zoomOut();
0186         event->ignore();
0187     }
0188     QMdiSubWindow::wheelEvent(event);
0189 }
0190 
0191 void Image::paintEvent(QPaintEvent* event)
0192 {
0193     QMdiSubWindow::paintEvent(event);
0194     if(m_ctrl->fitWindow())
0195     {
0196         resizeLabel();
0197     }
0198     else if((m_NormalSize * m_ctrl->zoomLevel()) != m_imageLabel->size())
0199     {
0200         m_NormalSize= m_imageLabel->size() / m_ctrl->zoomLevel();
0201         m_windowSize= size();
0202     }
0203 }
0204 
0205 void Image::updateTitle()
0206 {
0207     setWindowTitle(tr("%1 - (Picture)").arg(m_ctrl->name()));
0208 }
0209 
0210 void Image::createActions()
0211 {
0212     m_actionZoomIn= new QAction(tr("Zoom In"), this);
0213     m_actionZoomIn->setToolTip(tr("increase zoom level"));
0214     m_actionZoomIn->setIcon(QIcon::fromTheme("zoom-in-32"));
0215     connect(m_actionZoomIn, &QAction::triggered, this, [this] { m_ctrl->zoomIn(); });
0216 
0217     m_zoomInShort= new QShortcut(QKeySequence(tr("Ctrl++", "Zoom In")), this);
0218     m_zoomInShort->setContext(Qt::WidgetWithChildrenShortcut);
0219     connect(m_zoomInShort, &QShortcut::activated, this, [this] { m_ctrl->zoomIn(); });
0220     m_actionZoomIn->setShortcut(m_zoomInShort->key());
0221 
0222     m_actionZoomOut= new QAction(tr("Zoom out"), this);
0223     m_actionZoomOut->setIcon(QIcon::fromTheme("zoom-out-32"));
0224     m_actionZoomOut->setToolTip(tr("Reduce zoom level"));
0225     connect(m_actionZoomOut, &QAction::triggered, this, [this] { m_ctrl->zoomOut(); });
0226 
0227     m_zoomOutShort= new QShortcut(QKeySequence(tr("Ctrl+-", "Zoom Out")), this);
0228     m_zoomOutShort->setContext(Qt::WidgetWithChildrenShortcut);
0229     connect(m_zoomOutShort, &QShortcut::activated, this, [this] { m_ctrl->zoomOut(); });
0230     m_actionZoomOut->setShortcut(m_zoomOutShort->key());
0231 
0232     auto fitWorkspace= [this] {
0233         m_imageLabel->resize(parentWidget()->size());
0234         fitWorkSpace();
0235     };
0236 
0237     m_actionfitWorkspace= new QAction(tr("Fit the workspace"), this);
0238     m_actionfitWorkspace->setIcon(QIcon::fromTheme("fit-page"));
0239     m_actionfitWorkspace->setToolTip(tr("The window and the image fit the workspace"));
0240     connect(m_actionfitWorkspace, &QAction::triggered, this, fitWorkspace);
0241 
0242     m_fitShort= new QShortcut(QKeySequence(tr("Ctrl+m", "Fit the workspace")), this);
0243     m_fitShort->setContext(Qt::WidgetWithChildrenShortcut);
0244     connect(m_fitShort, &QShortcut::activated, this, fitWorkspace);
0245     m_actionfitWorkspace->setShortcut(m_fitShort->key());
0246 
0247     auto setFitWindow= [this] { m_ctrl->setFitWindow(!m_ctrl->fitWindow()); };
0248 
0249     m_fitWindowAct= new QAction(tr("Fit Window"), this);
0250     m_fitWindowAct->setCheckable(true);
0251     connect(m_ctrl, &ImageController::fitWindowChanged, this,
0252             [this] { m_fitWindowAct->setChecked(m_ctrl->fitWindow()); });
0253     m_fitWindowAct->setIcon(QIcon::fromTheme("fit-window"));
0254     m_fitWindowAct->setToolTip(tr("Image will take the best dimension to fit the window."));
0255     connect(m_fitWindowAct, &QAction::triggered, this, setFitWindow);
0256 
0257     m_fitWindowShort= new QShortcut(QKeySequence(tr("Ctrl+f", "Fit the window")), this);
0258     m_fitWindowShort->setContext(Qt::WidgetWithChildrenShortcut);
0259     connect(m_fitWindowShort, &QShortcut::activated, this, setFitWindow);
0260     m_fitWindowAct->setShortcut(m_fitWindowShort->key());
0261 
0262     auto zoomLittle= [this] { m_ctrl->setZoomLevel(0.2); };
0263 
0264     m_actionlittleZoom= new QAction(tr("Little"), this);
0265     m_actionlittleZoom->setToolTip(tr("Set the zoom level at 20% "));
0266     connect(m_actionlittleZoom, &QAction::triggered, this, zoomLittle);
0267 
0268     m_littleShort= new QShortcut(QKeySequence(tr("Ctrl+l", "Set the zoom level at 20%")), this);
0269     m_littleShort->setContext(Qt::WidgetWithChildrenShortcut);
0270     connect(m_littleShort, &QShortcut::activated, this, zoomLittle);
0271     m_actionlittleZoom->setShortcut(m_littleShort->key());
0272 
0273     auto zoomNormal= [this] { m_ctrl->setZoomLevel(1.0); };
0274 
0275     m_actionNormalZoom= new QAction(tr("Normal"), this);
0276     m_actionNormalZoom->setToolTip(tr("No Zoom"));
0277     connect(m_actionNormalZoom, &QAction::triggered, this, zoomNormal);
0278 
0279     m_normalShort= new QShortcut(QKeySequence(tr("Ctrl+n", "Normal")), this);
0280     m_normalShort->setContext(Qt::WidgetWithChildrenShortcut);
0281     connect(m_normalShort, &QShortcut::activated, this, zoomNormal);
0282     m_actionNormalZoom->setShortcut(m_normalShort->key());
0283 
0284     auto zoomBig= [this] { m_ctrl->setZoomLevel(4.0); };
0285 
0286     m_actionBigZoom= new QAction(tr("Big"), this);
0287     m_actionBigZoom->setToolTip(tr("Set the zoom level at 400%"));
0288     connect(m_actionBigZoom, &QAction::triggered, this, zoomBig);
0289 
0290     m_bigShort= new QShortcut(QKeySequence(tr("Ctrl+b", "Zoom Out")), this);
0291     m_bigShort->setContext(Qt::WidgetWithChildrenShortcut);
0292     connect(m_bigShort, &QShortcut::activated, this, zoomBig);
0293     m_actionBigZoom->setShortcut(m_bigShort->key());
0294 
0295 
0296     m_rename = new QAction(tr("Rename"), this);
0297     m_rename->setShortcut(Qt::Key_F2);
0298     connect(m_rename, &QAction::triggered, this, [this](){
0299         auto text = QInputDialog::getText(this, tr("Define the new name"), tr("New name:"),QLineEdit::Normal,m_ctrl->name());
0300         if(text.isEmpty())
0301             return;
0302         m_ctrl->setName(text);
0303     });
0304 
0305     m_playAct= new QAction(tr("Play"), this);
0306     m_playAct->setShortcut(Qt::Key_Space);
0307     m_stopAct= new QAction(tr("Stop"), this);
0308 
0309     connect(m_ctrl, &ImageController::statusChanged, this, [this](ImageController::Status status) {
0310         switch(status)
0311         {
0312         case ImageController::Playing:
0313             m_playAct->setText(tr("Pause"));
0314             m_stopAct->setEnabled(true);
0315             break;
0316         case ImageController::Paused:
0317             m_playAct->setText(tr("Play"));
0318             m_stopAct->setEnabled(true);
0319             break;
0320         case ImageController::Stopped:
0321             m_stopAct->setEnabled(false);
0322             m_playAct->setText(tr("Play"));
0323             break;
0324         }
0325     });
0326 
0327     connect(m_playAct, &QAction::triggered, m_ctrl, &ImageController::play);
0328     connect(m_stopAct, &QAction::triggered, m_ctrl, &ImageController::stop);
0329 }
0330 void Image::contextMenuEvent(QContextMenuEvent* event)
0331 {
0332     QMenu menu(this);
0333 
0334     if(m_ctrl->isMovie())
0335     {
0336         menu.addAction(m_playAct);
0337         menu.addAction(m_stopAct);
0338         menu.addSeparator();
0339     }
0340 
0341     menu.addAction(m_rename);
0342     menu.addSeparator();
0343     menu.addAction(m_actionZoomIn);
0344     menu.addAction(m_actionZoomOut);
0345     menu.addSeparator();
0346     menu.addAction(m_actionfitWorkspace);
0347     menu.addAction(m_fitWindowAct);
0348     addActionToMenu(menu);
0349     menu.addSeparator();
0350     menu.addAction(m_actionlittleZoom);
0351     menu.addAction(m_actionNormalZoom);
0352     menu.addAction(m_actionBigZoom);
0353 
0354     menu.exec(event->globalPos() /*event->pos()*/);
0355 }
0356 void Image::fitWindow()
0357 {
0358     auto fit= m_fitWindowAct->isChecked();
0359     resizeLabel();
0360     if(fit)
0361     {
0362         m_widgetArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
0363         m_widgetArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
0364     }
0365     else
0366     {
0367         m_widgetArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
0368         m_widgetArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
0369     }
0370     m_actionZoomIn->setEnabled(!fit);
0371     m_actionZoomOut->setEnabled(!fit);
0372     m_actionlittleZoom->setEnabled(!fit);
0373     m_actionNormalZoom->setEnabled(!fit);
0374     m_actionBigZoom->setEnabled(!fit);
0375 
0376     update();
0377 }
0378 void Image::resizeEvent(QResizeEvent* event)
0379 {
0380     if(m_fitWindowAct->isChecked())
0381     {
0382         resizeLabel();
0383     }
0384 
0385     QMdiSubWindow::resizeEvent(event);
0386 }
0387 
0388 void Image::setParent(QWidget* parent)
0389 {
0390     QMdiSubWindow::setParent(parent);
0391     fitWorkSpace();
0392 }