File indexing completed on 2025-01-05 03:53:06

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2021-07-24
0007  * Description : MJPEG Stream configuration dialog - Views methods
0008  *
0009  * SPDX-FileCopyrightText: 2021-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText: 2021      by Quoc Hưng Tran <quochungtran1999 at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "mjpegstreamdlg_p.h"
0017 
0018 namespace DigikamGenericMjpegStreamPlugin
0019 {
0020 
0021 QWidget* MjpegStreamDlg::setupItemsView()
0022 {
0023     d->albumSupport   = (d->settings.iface && d->settings.iface->supportAlbums());
0024     QWidget* itemsSel = nullptr;
0025 
0026     if (d->albumSupport)
0027     {
0028         d->albumSelector = d->settings.iface->albumChooser(this);
0029         itemsSel         = d->albumSelector;
0030 
0031         connect(d->settings.iface, SIGNAL(signalAlbumChooserSelectionChanged()),
0032                 this, SLOT(slotSelectionChanged()));
0033     }
0034     else
0035     {
0036         d->listView = new DItemsList(this);
0037         d->listView->setObjectName(QLatin1String("MjpegStream ImagesList"));
0038         d->listView->setControlButtonsPlacement(DItemsList::ControlButtonsRight);
0039         d->listView->setIface(d->settings.iface);
0040 
0041         // Add all items currently loaded in application.
0042 
0043         d->listView->loadImagesFromCurrentSelection();
0044 
0045         // Replug the previous shared items list.
0046 
0047         d->listView->slotAddImages(d->mngr->itemsList());
0048         itemsSel    = d->listView;
0049 
0050         connect(d->listView, SIGNAL(signalImageListChanged()),
0051                 this, SLOT(slotSelectionChanged()));
0052     }
0053 
0054     return itemsSel;
0055 }
0056 
0057 void MjpegStreamDlg::setupServerView()
0058 {
0059     QWidget* const serverSettings = new QWidget(d->tabView);
0060 
0061     QLabel* const portLbl         = new QLabel(i18nc("@label", "Server Port:"), serverSettings);
0062     d->srvPort                    = new DIntNumInput(serverSettings);
0063     d->srvPort->setDefaultValue(8080);
0064     d->srvPort->setRange(1025, 65535, 1);
0065     d->srvPort->setWhatsThis(i18nc("@info", "The MJPEG server IP port."));
0066     portLbl->setBuddy(d->srvPort);
0067 
0068     d->startOnStartup             = new QCheckBox(i18nc("@option", "Start Server at Startup"));
0069     d->startOnStartup->setWhatsThis(i18nc("@info", "Set this option to turn-on the MJPEG server at application start-up automatically"));
0070     d->startOnStartup->setChecked(true);
0071 
0072     // ---
0073 
0074     QLabel* const explanation     = new QLabel(serverSettings);
0075     explanation->setOpenExternalLinks(true);
0076     explanation->setWordWrap(true);
0077     explanation->setFrameStyle(QFrame::Box | QFrame::Plain);
0078 
0079     explanation->setText(i18nc("@info",
0080         "The %1 server allows to share items through the local network using a web browser. "
0081         "Motion JPEG is a video compression format in which each video frame is compressed "
0082         "separately as a JPEG image. MJPEG streams is a standard which allows network clients to be "
0083         "connected without additional module. Most major web browsers and players support MJPEG stream. "
0084         "To access to stream from your browser, just use http://address:port as url, with address "       // krazy:exclude=insecurenet
0085         "the MJPEG server IP, and port the server port set in this config dialog.",
0086         QLatin1String("<a href='https://en.wikipedia.org/wiki/Motion_JPEG'>Motion JPEG</a>")));
0087 
0088     d->srvButton                  = new QPushButton(serverSettings);
0089     d->srvStatus                  = new QLabel(serverSettings);
0090     d->aStats                     = new QLabel(serverSettings);
0091     d->separator                  = new QLabel(QLatin1String(" / "), serverSettings);
0092     d->iStats                     = new QLabel(serverSettings);
0093     d->progress                   = new WorkingWidget(serverSettings);
0094     d->srvPreview                 = new QPushButton(i18nc("@action: button", "Preview..."), serverSettings);
0095     d->srvPreview->setWhatsThis(i18nc("@info", "Press this button to preview the stream on your computer with your browser."));
0096 
0097     QGridLayout* const grid3      = new QGridLayout(serverSettings);
0098     grid3->addWidget(portLbl,           0, 0, 1, 1);
0099     grid3->addWidget(d->srvPort,        0, 1, 1, 1);
0100     grid3->addWidget(d->startOnStartup, 0, 2, 1, 5);
0101     grid3->addWidget(d->srvButton,      1, 0, 1, 1);
0102     grid3->addWidget(d->srvStatus,      1, 1, 1, 1);
0103     grid3->addWidget(d->aStats,         1, 2, 1, 1);
0104     grid3->addWidget(d->separator,      1, 3, 1, 1);
0105     grid3->addWidget(d->iStats,         1, 4, 1, 1);
0106     grid3->addWidget(d->progress,       1, 5, 1, 1);
0107     grid3->addWidget(d->srvPreview,     1, 6, 1, 1);
0108     grid3->addWidget(explanation,       2, 0, 1, 7);
0109     grid3->setSpacing(d->spacing);
0110 
0111     d->tabView->insertTab(Private::Server, serverSettings, i18nc("@title", "Server"));
0112 
0113     connect(d->srvButton, SIGNAL(clicked()),
0114             this, SLOT(slotToggleMjpegServer()));
0115 
0116     connect(d->srvPort, SIGNAL(valueChanged(int)),
0117             this, SLOT(slotSettingsChanged()));
0118 
0119     connect(d->srvPreview, SIGNAL(clicked()),
0120             this, SLOT(slotOpenPreview()));
0121 }
0122 
0123 void MjpegStreamDlg::setupStreamView()
0124 {
0125     d->streamSettings         = new QWidget(d->tabView);
0126 
0127     QLabel* const qualityLbl  = new QLabel(i18nc("@label", "JPEG Quality:"), d->streamSettings);
0128     d->quality                = new DIntNumInput(d->streamSettings);
0129     d->quality->setDefaultValue(75);
0130     d->quality->setRange(50, 100, 1);
0131     d->quality->setWhatsThis(i18nc("@info", "The JPEG quality [50:lower - 100:higher]. "
0132                                             "Warning: better quality require more network bandwidth"));
0133 
0134     qualityLbl->setBuddy(d->quality);
0135 
0136     // ---
0137 
0138     QLabel* const typeLabel   = new QLabel(d->streamSettings);
0139     typeLabel->setWordWrap(false);
0140     typeLabel->setText(i18nc("@label", "JPEG Size:"));
0141     d->typeVal                = new DComboBox(d->streamSettings);
0142     d->typeVal->combo()->setEditable(false);
0143 
0144     QMap<VidSlideSettings::VidType, QString> map                = VidSlideSettings::videoTypeNames();
0145     QMap<VidSlideSettings::VidType, QString>::const_iterator it = map.constBegin();
0146 
0147     while (it != map.constEnd())
0148     {
0149         d->typeVal->addItem(it.value(), (int)it.key());
0150         ++it;
0151     }
0152 
0153     d->typeVal->setDefaultIndex(VidSlideSettings::BLUERAY);
0154     d->typeVal->setWhatsThis(i18nc("@info", "The JPEG image size in pixels, using standard screen resolutions. "
0155                                             "Warning: larger size require more network bandwidth"));
0156     typeLabel->setBuddy(d->typeVal);
0157 
0158     // ---
0159 
0160     QLabel* const delayLbl    = new QLabel(i18nc("@label", "Delay in Seconds:"), d->streamSettings);
0161     d->delay                  = new DIntNumInput(d->streamSettings);
0162     d->delay->setDefaultValue(5);
0163     d->delay->setRange(1, 3600, 1);
0164     d->delay->setWhatsThis(i18nc("@info", "The delay in seconds between images."));
0165     delayLbl->setBuddy(d->delay);
0166 
0167     QLabel* const rateLbl     = new QLabel(i18nc("@label", "Frames by Second:"), d->streamSettings);
0168     d->rate                   = new DIntNumInput(d->streamSettings);
0169     d->rate->setDefaultValue(10);
0170     d->rate->setRange(5, 24, 1);
0171     d->rate->setWhatsThis(i18nc("@info", "The number of frames by second to render the stream. "
0172                                          "Warning: larger rate require more network bandwidth"));
0173     rateLbl->setBuddy(d->rate);
0174 
0175     d->streamLoop             = new QCheckBox(i18nc("@option:check", "Stream in Loop"), d->streamSettings);
0176     d->streamLoop->setChecked(true);
0177     d->streamLoop->setWhatsThis(i18nc("@info", "The MJPEG stream will be played in loop instead once."));
0178 
0179     QGridLayout* const grid2  = new QGridLayout(d->streamSettings);
0180     grid2->addWidget(qualityLbl,    0, 0, 1, 1);
0181     grid2->addWidget(d->quality,    0, 1, 1, 1);
0182     grid2->addWidget(typeLabel,     1, 0, 1, 1);
0183     grid2->addWidget(d->typeVal,    1, 1, 1, 1);
0184     grid2->addWidget(delayLbl,      2, 0, 1, 1);
0185     grid2->addWidget(d->delay,      2, 1, 1, 1);
0186     grid2->addWidget(rateLbl,       3, 0, 1, 1);
0187     grid2->addWidget(d->rate,       3, 1, 1, 1);
0188     grid2->addWidget(d->streamLoop, 4, 0, 1, 2);
0189     grid2->setSpacing(d->spacing);
0190 
0191     d->tabView->insertTab(Private::Stream, d->streamSettings, i18nc("@title", "Stream"));
0192 
0193     connect(d->delay, SIGNAL(valueChanged(int)),
0194             this, SLOT(slotSettingsChanged()));
0195 
0196     connect(d->rate, SIGNAL(valueChanged(int)),
0197             this, SLOT(slotSettingsChanged()));
0198 
0199     connect(d->quality, SIGNAL(valueChanged(int)),
0200             this, SLOT(slotSettingsChanged()));
0201 
0202     connect(d->streamLoop, SIGNAL(stateChanged(int)),
0203             this, SLOT(slotSettingsChanged()));
0204 
0205     connect(d->typeVal, SIGNAL(currentIndexChanged(int)),
0206             this, SLOT(slotSettingsChanged()));
0207 }
0208 
0209 void MjpegStreamDlg::setupTransitionView()
0210 {
0211     QWidget* const transitionSettings = new QWidget(d->tabView);
0212 
0213     QLabel* const transLabel          = new QLabel(transitionSettings);
0214     transLabel->setWordWrap(false);
0215     transLabel->setText(i18nc("@label", "Type:"));
0216     d->transVal                       = new DComboBox(transitionSettings);
0217     d->transVal->combo()->setEditable(false);
0218 
0219     QMap<TransitionMngr::TransType, QString> map4                = TransitionMngr::transitionNames();
0220     QMap<TransitionMngr::TransType, QString>::const_iterator it4 = map4.constBegin();
0221 
0222     while (it4 != map4.constEnd())
0223     {
0224         d->transVal->addItem(it4.value(), (int)it4.key());
0225         ++it4;
0226     }
0227 
0228     d->transVal->setDefaultIndex(TransitionMngr::None);
0229     transLabel->setBuddy(d->transVal);
0230 
0231     QLabel* const transNote  = new QLabel(transitionSettings);
0232     transNote->setWordWrap(true);
0233     transNote->setText(i18nc("@label", "A transition is an visual effect applied between two images. "
0234                                        "For some effects, the duration can depend of random values and "
0235                                        "can change while the stream."));
0236 
0237     d->transPreview              = new TransitionPreview(transitionSettings);
0238     d->transPreview->setImagesList(QList<QUrl>());
0239 
0240     QGridLayout* const transGrid = new QGridLayout(transitionSettings);
0241     transGrid->setSpacing(d->spacing);
0242     transGrid->addWidget(transLabel,      0, 0, 1, 1);
0243     transGrid->addWidget(d->transVal,     0, 1, 1, 1);
0244     transGrid->addWidget(transNote,       1, 0, 1, 2);
0245     transGrid->addWidget(d->transPreview, 0, 2, 2, 1);
0246     transGrid->setColumnStretch(1, 10);
0247     transGrid->setRowStretch(1, 10);
0248 
0249     d->tabView->insertTab(Private::Transition, transitionSettings, i18nc("@title", "Transition"));
0250 
0251     connect(d->transVal, SIGNAL(currentIndexChanged(int)),
0252             this, SLOT(slotSettingsChanged()));
0253 }
0254 
0255 void MjpegStreamDlg::setupEffectView()
0256 {
0257     QWidget* const effectSettings = new QWidget(d->tabView);
0258 
0259     QLabel* const effLabel        = new QLabel(effectSettings);
0260     effLabel->setWordWrap(false);
0261     effLabel->setText(i18nc("@label", "Type:"));
0262     d->effVal                     = new DComboBox(effectSettings);
0263     d->effVal->combo()->setEditable(false);
0264 
0265     QMap<EffectMngr::EffectType, QString> map6                = EffectMngr::effectNames();
0266     QMap<EffectMngr::EffectType, QString>::const_iterator it6 = map6.constBegin();
0267 
0268     while (it6 != map6.constEnd())
0269     {
0270         d->effVal->insertItem((int)it6.key(), it6.value(), (int)it6.key());
0271         ++it6;
0272     }
0273 
0274     d->effVal->setDefaultIndex(EffectMngr::None);
0275     effLabel->setBuddy(d->effVal);
0276 
0277     QLabel* const effNote      = new QLabel(effectSettings);
0278     effNote->setWordWrap(true);
0279     effNote->setText(i18nc("@label", "An effect is an visual panning or zooming applied while an image "
0280                                      "is displayed in MJPEG stream."));
0281 
0282     d->effPreview              = new EffectPreview(effectSettings);
0283     d->effPreview->setImagesList(QList<QUrl>());
0284 
0285     QGridLayout* const effGrid = new QGridLayout(effectSettings);
0286     effGrid->setSpacing(d->spacing);
0287     effGrid->addWidget(effLabel,      0, 0, 1, 1);
0288     effGrid->addWidget(d->effVal,     0, 1, 1, 1);
0289     effGrid->addWidget(effNote,       1, 0, 1, 2);
0290     effGrid->addWidget(d->effPreview, 0, 2, 2, 1);
0291     effGrid->setColumnStretch(1, 10);
0292     effGrid->setRowStretch(1, 10);
0293 
0294     d->tabView->insertTab(Private::Effect, effectSettings, i18nc("@title", "Effect"));
0295 
0296     connect(d->effVal, SIGNAL(currentIndexChanged(int)),
0297             this, SLOT(slotSettingsChanged()));
0298 }
0299 
0300 void MjpegStreamDlg::setupOSDView()
0301 {
0302     d->frameOsdWidget = new FrameOsdWidget(d->tabView);
0303 
0304     d->tabView->insertTab(Private::OSD, d->frameOsdWidget,
0305                           i18nc("@title: On Screen Display", "OSD"));
0306 
0307     connect(d->frameOsdWidget, SIGNAL(signalSettingsChanged()),
0308             this, SLOT(slotSettingsChanged()));
0309 }
0310 
0311 } // namespace DigikamGenericMjpegStreamPlugin