File indexing completed on 2024-04-28 08:46:42
0001 /* 0002 SPDX-FileCopyrightText: 2002-2003 Koos Vriezen <koos.vriezen@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only 0005 */ 0006 0007 #include <cstdio> 0008 #include <cmath> 0009 0010 #include "config-kmplayer.h" 0011 // include files for Qt 0012 #include <QStyle> 0013 #include <QTimer> 0014 #include <QPainter> 0015 #include <QMetaObject> 0016 #include <QLayout> 0017 #include <QPixmap> 0018 #include <QTextEdit> 0019 #include <QToolTip> 0020 #include <QApplication> 0021 #include <QCursor> 0022 #include <QKeySequence> 0023 #include <QSlider> 0024 #include <QLabel> 0025 #include <QDataStream> 0026 #include <QContextMenuEvent> 0027 #include <QMimeData> 0028 #include <QDropEvent> 0029 #include <QAction> 0030 #include <QDragEnterEvent> 0031 #include <QFontDatabase> 0032 #include <QTextDocument> 0033 #include <QTextCursor> 0034 #include <QCursor> 0035 #include <QClipboard> 0036 #include <QMainWindow> 0037 #include <QStatusBar> 0038 #include <QDockWidget> 0039 0040 #include <KIconLoader> 0041 #include <KLocalizedString> 0042 #include <KActionCollection> 0043 0044 #include "kmplayercommon_log.h" 0045 #include "kmplayerview.h" 0046 #include "kmplayercontrolpanel.h" 0047 #include "playlistview.h" 0048 #include "viewarea.h" 0049 0050 /* mouse invisible: define the time (in 1/1000 seconds) before mouse goes invisible */ 0051 0052 0053 using namespace KMPlayer; 0054 0055 //------------------------------------------------------------------------- 0056 0057 PictureWidget::PictureWidget (QWidget * parent, View * view) 0058 : QWidget (parent), m_view (view) { 0059 setAutoFillBackground (true); 0060 } 0061 0062 void PictureWidget::mousePressEvent (QMouseEvent *) { 0063 m_view->emitPictureClicked (); 0064 } 0065 0066 void PictureWidget::mouseMoveEvent (QMouseEvent *e) { 0067 if (e->buttons () == Qt::NoButton) 0068 m_view->mouseMoved (e->x (), e->y ()); 0069 } 0070 0071 //----------------------------------------------------------------------------- 0072 0073 TextEdit::TextEdit (QWidget * parent, View * view) : QTextEdit (parent), m_view (view) { 0074 setAttribute (Qt::WA_NativeWindow); 0075 setAttribute(Qt::WA_DontCreateNativeAncestors); 0076 setReadOnly (true); 0077 QPalette p=palette(); 0078 p.setColor (QPalette::Active, QPalette::Base, QColor (Qt::black)); 0079 p.setColor (QPalette::Active, QPalette::Foreground, (QColor (0xB2, 0xB2, 0xB2))); 0080 setPalette (p); 0081 } 0082 0083 void TextEdit::contextMenuEvent (QContextMenuEvent * e) { 0084 m_view->controlPanel ()->popupMenu->exec (e->globalPos ()); 0085 } 0086 0087 //----------------------------------------------------------------------------- 0088 0089 InfoWindow::InfoWindow (QWidget *, View * view) 0090 : m_view (view) { 0091 setReadOnly (true); 0092 //setLinkUnderline (false); 0093 } 0094 0095 void InfoWindow::contextMenuEvent (QContextMenuEvent * e) { 0096 m_view->controlPanel ()->popupMenu->exec (e->globalPos ()); 0097 } 0098 0099 //----------------------------------------------------------------------------- 0100 0101 View::View (QWidget *parent) 0102 : KMediaPlayer::View (parent), 0103 m_control_panel (nullptr), 0104 m_status_bar (nullptr), 0105 m_controlpanel_mode (CP_Show), 0106 m_old_controlpanel_mode (CP_Show), 0107 m_statusbar_mode (SB_Hide), 0108 controlbar_timer (0), 0109 infopanel_timer (0), 0110 m_restore_state_timer(0), 0111 m_powerManagerStopSleep( -1 ), 0112 m_inhibitIface("org.freedesktop.PowerManagement.Inhibit", 0113 "/org/freedesktop/PowerManagement/Inhibit", 0114 QDBusConnection::sessionBus()), 0115 m_keepsizeratio (false), 0116 m_playing (false), 0117 m_tmplog_needs_eol (false), 0118 m_revert_fullscreen (false), 0119 m_no_info (false), 0120 m_edit_mode (false) 0121 { 0122 setAttribute (Qt::WA_NoSystemBackground, true); 0123 setAutoFillBackground (false); 0124 setAcceptDrops(true); 0125 } 0126 0127 void View::dropEvent (QDropEvent * de) { 0128 QList<QUrl> uris = de->mimeData()->urls(); 0129 if (uris.isEmpty() || !uris[0].isValid()) { 0130 const QUrl url = QUrl::fromUserInput(de->mimeData()->text()); 0131 if (url.isValid ()) 0132 uris.push_back(url); 0133 } 0134 if (uris.size () > 0) { 0135 //m_widgetstack->currentWidget ()->setFocus (); 0136 Q_EMIT urlDropped (uris); 0137 de->accept (); 0138 } 0139 } 0140 0141 void View::dragEnterEvent (QDragEnterEvent* dee) { 0142 if (m_playlist->isDragValid (dee)) 0143 dee->accept (); 0144 } 0145 0146 void View::initDock (QWidget *central) { 0147 m_dockarea = new QMainWindow; 0148 m_dockarea->setDockNestingEnabled(true); 0149 m_dockarea->setCentralWidget (central); 0150 central->setVisible (true); 0151 0152 m_dock_playlist = new QDockWidget (i18n ("Playlist")); 0153 if (central != m_playlist) 0154 m_dock_playlist->setWidget (m_playlist); 0155 m_dock_playlist->setObjectName ("playlist"); 0156 0157 m_dock_infopanel = new QDockWidget (i18n ("Information")); 0158 if (central != m_infopanel) 0159 m_dock_infopanel->setWidget (m_infopanel); 0160 m_dock_infopanel->setObjectName ("infopanel"); 0161 0162 m_dock_playlist->hide (); 0163 m_dock_infopanel->hide (); 0164 0165 m_dockarea->addDockWidget (Qt::BottomDockWidgetArea, m_dock_infopanel); 0166 m_dockarea->addDockWidget (Qt::LeftDockWidgetArea, m_dock_playlist); 0167 0168 layout ()->addWidget (m_dockarea); 0169 0170 m_dockarea->setWindowFlags (Qt::SubWindow); 0171 m_dockarea->show (); 0172 0173 m_view_area->resizeEvent (nullptr); 0174 } 0175 0176 void View::init (KActionCollection *action_collection, bool transparent) { 0177 QVBoxLayout * viewbox = new QVBoxLayout; 0178 viewbox->setContentsMargins (0, 0, 0, 0); 0179 setLayout (viewbox); 0180 m_view_area = new ViewArea (nullptr, this, !transparent); 0181 m_playlist = new PlayListView (nullptr, this, action_collection); 0182 0183 m_picture = new PictureWidget (m_view_area, this); 0184 m_picture->hide (); 0185 m_control_panel = new ControlPanel (m_view_area, this); 0186 m_control_panel->setMaximumHeight(controlPanel ()->maximumSize ().height ()); 0187 m_status_bar = new StatusBar (m_view_area); 0188 m_status_bar->clearMessage(); 0189 m_status_bar->setAutoFillBackground (true); 0190 QSize sbsize = m_status_bar->sizeHint (); 0191 m_status_bar->hide (); 0192 m_status_bar->setMaximumHeight(sbsize.height ()); 0193 setVideoWidget (m_view_area); 0194 0195 m_multiedit = new TextEdit (m_view_area, this); 0196 QFont fnt = QFontDatabase::systemFont(QFontDatabase::FixedFont); 0197 m_multiedit->setFont (fnt); 0198 m_multiedit->hide (); 0199 0200 m_infopanel = new InfoWindow (nullptr, this); 0201 0202 connect (m_control_panel->scale_slider, &QSlider::valueChanged, 0203 m_view_area, &ViewArea::scale); 0204 setFocusPolicy (Qt::ClickFocus); 0205 0206 setAcceptDrops (true); 0207 } 0208 0209 View::~View () { 0210 if (m_view_area->parent () != this) 0211 delete m_view_area; 0212 } 0213 0214 void View::setEraseColor (const QColor & /*color*/) { 0215 /*KMediaPlayer::View::setEraseColor (color); 0216 if (statusBar ()) { 0217 statusBar ()->setEraseColor (color); 0218 controlPanel ()->setEraseColor (color); 0219 }*/ 0220 } 0221 0222 void View::setInfoMessage (const QString & msg) { 0223 bool ismain = m_dockarea->centralWidget () == m_infopanel; 0224 if (msg.isEmpty ()) { 0225 if (!ismain && !m_edit_mode && !infopanel_timer) 0226 infopanel_timer = startTimer (0); 0227 m_infopanel->clear (); 0228 } else if (ismain || !m_no_info) { 0229 if (!ismain && !m_edit_mode && !m_dock_infopanel->isVisible ()) 0230 m_dock_infopanel->show (); 0231 if (m_edit_mode) 0232 m_infopanel->setPlainText (msg); 0233 else 0234 m_infopanel->setHtml (msg); 0235 } 0236 } 0237 0238 void View::setStatusMessage (const QString & msg) { 0239 if (m_statusbar_mode != SB_Hide) 0240 m_status_bar->showMessage(msg); 0241 } 0242 0243 void View::toggleShowPlaylist () { 0244 if (m_controlpanel_mode == CP_Only) 0245 return; 0246 if (m_dock_playlist->isVisible ()) 0247 m_dock_playlist->hide (); 0248 else 0249 m_dock_playlist->show(); 0250 /*if (m_dock_playlist->mayBeShow ()) { 0251 if (m_dock_playlist->isDockBackPossible ()) 0252 m_dock_playlist->dockBack (); 0253 else { 0254 bool horz = true; 0255 QStyle *style = m_playlist->style (); 0256 int h = style->pixelMetric (QStyle::PM_ScrollBarExtent, NULL, m_playlist); 0257 h += style->pixelMetric (QStyle::PM_DockWidgetFrameWidth, NULL, m_playlist); 0258 h +=style->pixelMetric (QStyle::PM_DockWidgetHandleExtent, NULL, m_playlist); 0259 for (Q3ListViewItem *i=m_playlist->firstChild();i;i=i->itemBelow()) { 0260 h += i->height (); 0261 if (h > int (0.25 * height ())) { 0262 horz = false; 0263 break; 0264 } 0265 } 0266 int perc = 30; 0267 if (horz && 100 * h / height () < perc) 0268 perc = 100 * h / height (); 0269 m_dock_playlist->manualDock (m_dock_video, horz ? K3DockWidget::DockTop : K3DockWidget::DockLeft, perc); 0270 } 0271 } else 0272 m_dock_playlist->undock ();*/ 0273 } 0274 0275 void View::setViewOnly () { 0276 m_dock_playlist->hide (); 0277 m_dock_infopanel->hide (); 0278 } 0279 0280 void View::setEditMode (TopPlayItem *ri, bool enable) { 0281 m_edit_mode = enable; 0282 m_infopanel->setReadOnly (!m_edit_mode); 0283 if (m_edit_mode && !m_dock_infopanel->isVisible ()) 0284 m_dock_infopanel->show (); 0285 //if (m_edit_mode && m_dock_infopanel->mayBeShow ()) 0286 // m_dock_infopanel->manualDock(m_dock_video,K3DockWidget::DockBottom,50); 0287 m_playlist->showAllNodes (ri, m_edit_mode); 0288 } 0289 0290 #ifndef KMPLAYER_WITH_CAIRO 0291 bool View::setPicture (const QString & path) { 0292 if (path.isEmpty ()) 0293 m_image = QImage (); 0294 else { 0295 m_image = QImage (path); 0296 if (m_image.isNull ()) 0297 qCDebug(LOG_KMPLAYER_COMMON) << "View::setPicture failed " << path; 0298 else if (m_image.depth () < 24) 0299 m_image = m_image.convertToFormat (QImage::Format_RGB32); 0300 } 0301 m_picture->setVisible (!m_image.isNull ()); 0302 if (m_image.isNull ()) { 0303 m_view_area->setVideoWidgetVisible (true); 0304 } else { 0305 QPalette palette = m_picture->palette (); 0306 palette.setColor (m_picture->backgroundRole(), viewArea()->palette ().color (backgroundRole ())); 0307 palette.setBrush (m_picture->backgroundRole(), QBrush (m_image)); 0308 m_picture->setPalette (palette); 0309 m_view_area->setVideoWidgetVisible (false); 0310 controlPanel ()->raise (); 0311 setControlPanelMode (CP_AutoHide); 0312 } 0313 return !m_image.isNull (); 0314 } 0315 #endif 0316 0317 void View::toggleVideoConsoleWindow () { 0318 if (m_multiedit->isVisible ()) { 0319 m_multiedit->hide (); 0320 m_view_area->setVideoWidgetVisible (true); 0321 m_control_panel->videoConsoleAction->setIcon(QIcon::fromTheme(("konsole"))); 0322 m_control_panel->videoConsoleAction->setText (i18n ("Con&sole")); 0323 delayedShowButtons (false); 0324 } else { 0325 m_control_panel->videoConsoleAction->setIcon(QIcon::fromTheme("video")); 0326 m_control_panel->videoConsoleAction->setText (i18n ("V&ideo")); 0327 m_multiedit->show (); 0328 m_multiedit->raise (); 0329 m_view_area->setVideoWidgetVisible (false); 0330 addText (QString (""), false); 0331 if (m_controlpanel_mode == CP_AutoHide && m_playing) 0332 m_control_panel->show(); 0333 } 0334 updateLayout (); 0335 Q_EMIT windowVideoConsoleToggled (m_multiedit->isVisible ()); 0336 } 0337 0338 void View::setControlPanelMode (ControlPanelMode m) { 0339 if (controlbar_timer) { 0340 killTimer (controlbar_timer); 0341 controlbar_timer = 0L; 0342 } 0343 m_old_controlpanel_mode = m_controlpanel_mode = m; 0344 if (m_playing && isFullScreen()) 0345 m_controlpanel_mode = CP_AutoHide; 0346 if ((m_controlpanel_mode == CP_Show || m_controlpanel_mode == CP_Only) && 0347 !m_control_panel->isVisible ()) { 0348 m_control_panel->show (); 0349 } else if (m_controlpanel_mode == CP_AutoHide) { 0350 if (!m_image.isNull () || (m_playing && !m_multiedit->isVisible ())) 0351 delayedShowButtons (false); 0352 else if (!m_control_panel->isVisible ()) { 0353 m_control_panel->show (); 0354 } 0355 } else if (m_controlpanel_mode == CP_Hide) { 0356 bool vis = m_control_panel->isVisible(); 0357 m_control_panel->hide (); 0358 if (vis) 0359 m_view_area->resizeEvent (nullptr); 0360 } 0361 m_view_area->resizeEvent (nullptr); 0362 } 0363 0364 void View::setStatusBarMode (StatusBarMode m) { 0365 m_statusbar_mode = m; 0366 m_status_bar->setVisible (m != SB_Hide); 0367 m_view_area->resizeEvent (nullptr); 0368 } 0369 0370 void View::delayedShowButtons (bool show) { 0371 if ((show && m_control_panel->isVisible ()) || 0372 (!show && !m_control_panel->isVisible ())) { 0373 if (controlbar_timer) { 0374 killTimer (controlbar_timer); 0375 controlbar_timer = 0; 0376 } 0377 if (!show) 0378 m_control_panel->hide (); // for initial race 0379 } else if (m_controlpanel_mode == CP_AutoHide && 0380 (m_playing || !m_image.isNull ()) && 0381 !m_multiedit->isVisible () && !controlbar_timer) { 0382 controlbar_timer = startTimer (500); 0383 } 0384 } 0385 0386 void View::mouseMoved (int, int y) { 0387 int h = m_view_area->height (); 0388 int vert_buttons_pos = h - statusBarHeight (); 0389 int cp_height = controlPanel ()->maximumSize ().height (); 0390 if (cp_height > int (0.25 * h)) 0391 cp_height = int (0.25 * h); 0392 delayedShowButtons (y > vert_buttons_pos-cp_height && y < vert_buttons_pos); 0393 } 0394 0395 void View::updateLayout () { 0396 if (m_controlpanel_mode == CP_Only) 0397 m_control_panel->setMaximumHeight(height()); 0398 m_view_area->resizeEvent (nullptr); 0399 } 0400 0401 void View::setKeepSizeRatio (bool b) { 0402 if (m_keepsizeratio != b) { 0403 m_keepsizeratio = b; 0404 updateLayout (); 0405 m_view_area->update (); 0406 } 0407 } 0408 0409 void View::timerEvent (QTimerEvent * e) { 0410 if (e->timerId () == controlbar_timer) { 0411 controlbar_timer = 0; 0412 if (m_playing || !m_image.isNull ()) { 0413 int vert_buttons_pos = m_view_area->height()-statusBarHeight (); 0414 QPoint mouse_pos = m_view_area->mapFromGlobal (QCursor::pos ()); 0415 int cp_height = m_control_panel->maximumSize ().height (); 0416 bool mouse_on_buttons = (//m_view_area->hasMouse () && 0417 mouse_pos.y () >= vert_buttons_pos-cp_height && 0418 mouse_pos.y ()<= vert_buttons_pos && 0419 mouse_pos.x () > 0 && 0420 mouse_pos.x () < m_control_panel->width()); 0421 if (mouse_on_buttons && !m_control_panel->isVisible ()) { 0422 m_control_panel->show (); 0423 m_view_area->resizeEvent (nullptr); 0424 } else if (!mouse_on_buttons && m_control_panel->isVisible ()) { 0425 m_control_panel->hide (); 0426 m_view_area->resizeEvent (nullptr); 0427 } 0428 } 0429 } else if (e->timerId () == infopanel_timer) { 0430 if (m_infopanel->document ()->isEmpty ()) 0431 m_dock_infopanel->hide (); 0432 //m_dock_infopanel->undock (); 0433 infopanel_timer = 0; 0434 } else if (e->timerId () == m_restore_state_timer) { 0435 m_view_area->setVisible(true); 0436 setControlPanelMode (m_old_controlpanel_mode); 0437 m_dockarea->restoreState(m_dock_state); 0438 m_restore_state_timer = 0; 0439 } 0440 killTimer (e->timerId ()); 0441 } 0442 0443 void View::addText (const QString & str, bool eol) { 0444 if (m_tmplog_needs_eol) 0445 tmplog += QChar ('\n'); 0446 tmplog += str; 0447 m_tmplog_needs_eol = eol; 0448 if (!m_multiedit->isVisible () && tmplog.size () < 7500) 0449 return; 0450 if (eol) { 0451 if (m_multiedit->document ()->isEmpty ()) 0452 m_multiedit->setPlainText (tmplog); 0453 else 0454 m_multiedit->append (tmplog); 0455 tmplog.truncate (0); 0456 m_tmplog_needs_eol = false; 0457 } else { 0458 int pos = tmplog.lastIndexOf (QChar ('\n')); 0459 if (pos >= 0) { 0460 m_multiedit->append (tmplog.left (pos)); 0461 tmplog = tmplog.mid (pos+1); 0462 } 0463 } 0464 QTextCursor cursor = m_multiedit->textCursor (); 0465 cursor.movePosition (QTextCursor::End); 0466 cursor.movePosition (QTextCursor::PreviousBlock, QTextCursor::MoveAnchor, 5000); 0467 cursor.movePosition (QTextCursor::Start, QTextCursor::KeepAnchor); 0468 cursor.removeSelectedText (); 0469 cursor.movePosition (QTextCursor::End); 0470 m_multiedit->setTextCursor (cursor); 0471 } 0472 0473 void View::videoStart () { 0474 if (!isFullScreen () && m_dockarea->centralWidget () != m_view_area) { 0475 // restore from an info or playlist only setting 0476 if (m_dockarea->centralWidget () == m_playlist) 0477 m_dock_playlist->setWidget (m_playlist); 0478 else if (m_dockarea->centralWidget () == m_infopanel) 0479 m_dock_infopanel->setWidget (m_infopanel); 0480 else 0481 m_status_bar->setVisible (false); 0482 m_dockarea->setCentralWidget (m_view_area); 0483 } 0484 if (m_controlpanel_mode == CP_Only) { 0485 m_control_panel->setMaximumHeight(controlPanel()->preferredHeight()); 0486 setControlPanelMode (CP_Show); 0487 } 0488 } 0489 0490 void View::playingStart () { 0491 if (m_playing) 0492 return; //FIXME: make symetric with playingStop 0493 m_playing = true; 0494 m_revert_fullscreen = !isFullScreen(); 0495 setControlPanelMode (m_old_controlpanel_mode); 0496 } 0497 0498 void View::playingStop () { 0499 if (m_controlpanel_mode == CP_AutoHide && m_image.isNull ()) { 0500 m_control_panel->show (); 0501 //m_view_area->setMouseTracking (false); 0502 } 0503 if (controlbar_timer) { 0504 killTimer (controlbar_timer); 0505 controlbar_timer = 0; 0506 } 0507 m_playing = false; 0508 m_view_area->resizeEvent (nullptr); 0509 } 0510 0511 void View::leaveEvent (QEvent *) { 0512 delayedShowButtons (false); 0513 } 0514 0515 void View::reset () { 0516 if (m_revert_fullscreen && isFullScreen ()) 0517 m_control_panel->fullscreenAction->activate (QAction::Trigger); 0518 //m_view_area->fullScreen (); 0519 playingStop (); 0520 } 0521 0522 bool View::isFullScreen () const { 0523 return m_view_area->isFullScreen (); 0524 } 0525 0526 void View::fullScreen () { 0527 if (m_restore_state_timer) { 0528 killTimer (m_restore_state_timer); 0529 m_restore_state_timer = 0; 0530 } 0531 if (!m_view_area->isFullScreen()) { 0532 m_sreensaver_disabled = false; 0533 QDBusReply<uint> reply = m_inhibitIface.Inhibit(QCoreApplication::applicationName(), "KMplayer: watching a film"); 0534 0535 m_powerManagerStopSleep = reply.isValid() ? reply : -1; 0536 0537 /*QByteArray data, replydata; 0538 QCString replyType; 0539 if (kapp->dcopClient ()->call ("kdesktop", "KScreensaverIface", 0540 "isEnabled()", data, replyType, replydata)) { 0541 bool enabled; 0542 QDataStream replystream (replydata, IO_ReadOnly); 0543 replystream >> enabled; 0544 if (enabled) 0545 m_sreensaver_disabled = kapp->dcopClient()->send 0546 ("kdesktop", "KScreensaverIface", "enable(bool)", "false"); 0547 }*/ 0548 //if (m_keepsizeratio && m_viewer->aspect () < 0.01) 0549 // m_viewer->setAspect (1.0 * m_viewer->width() / m_viewer->height()); 0550 m_dock_state = m_dockarea->saveState(); 0551 m_dock_playlist->hide(); 0552 m_dock_infopanel->hide(); 0553 m_view_area->fullScreen(); 0554 m_control_panel->zoomAction->setVisible (false); 0555 //if (m_viewer->isVisible ()) 0556 // m_viewer->setFocus (); 0557 } else { 0558 m_inhibitIface.UnInhibit(m_powerManagerStopSleep); 0559 // if (m_sreensaver_disabled) 0560 // m_sreensaver_disabled = !kapp->dcopClient()->send 0561 // ("kdesktop", "KScreensaverIface", "enable(bool)", "true"); 0562 m_view_area->fullScreen(); 0563 m_control_panel->zoomAction->setVisible (true); 0564 m_restore_state_timer = startTimer(100); //dockArea()->restoreState(m_dock_state); 0565 } 0566 setControlPanelMode (m_old_controlpanel_mode); 0567 Q_EMIT fullScreenChanged (); 0568 } 0569 0570 int View::statusBarHeight () const { 0571 if (statusBar()->isVisible () && !viewArea()->isFullScreen ()) { 0572 if (statusBarMode () == SB_Only) 0573 return height (); 0574 else 0575 return statusBar()->maximumSize ().height (); 0576 } 0577 return 0; 0578 } 0579 0580 #include "moc_kmplayerview.cpp"