00001 #include "mythmainwindow.h"
00002 #include "mythmainwindow_internal.h"
00003
00004
00005 #include <cmath>
00006
00007
00008 #include <algorithm>
00009 #include <vector>
00010 using namespace std;
00011
00012
00013 #ifdef USE_OPENGL_PAINTER
00014 #include <QGLWidget>
00015 #endif
00016
00017 #include <QWaitCondition>
00018 #include <QApplication>
00019 #include <QTimer>
00020 #include <QDesktopWidget>
00021 #include <QHash>
00022 #include <QFile>
00023 #include <QDir>
00024 #include <QEvent>
00025 #include <QKeyEvent>
00026 #include <QKeySequence>
00027 #include <QSize>
00028
00029
00030 #include "unistd.h"
00031 #ifdef QWS
00032 #include <qwindowsystem_qws.h>
00033 #endif
00034 #ifdef Q_WS_MACX_OLDQT
00035 #include <HIToolbox/Menus.h>
00036 #endif
00037
00038
00039 #include "mythdb.h"
00040 #include "mythlogging.h"
00041 #include "mythevent.h"
00042 #include "mythdirs.h"
00043 #include "compat.h"
00044 #include "mythsignalingtimer.h"
00045 #include "mythcorecontext.h"
00046 #include "mythmedia.h"
00047
00048
00049 #include "myththemebase.h"
00050 #include "screensaver.h"
00051 #include "lirc.h"
00052 #include "lircevent.h"
00053 #include "mythudplistener.h"
00054 #include "mythrender_base.h"
00055 #include "mythuistatetracker.h"
00056
00057 #ifdef USING_APPLEREMOTE
00058 #include "AppleRemoteListener.h"
00059 #endif
00060
00061 #ifdef USE_JOYSTICK_MENU
00062 #include "jsmenu.h"
00063 #include "jsmenuevent.h"
00064 #endif
00065
00066 #ifdef USING_LIBCEC
00067 #include "cecadapter.h"
00068 #endif
00069
00070 #include "mythscreentype.h"
00071 #include "mythpainter.h"
00072 #ifdef USE_OPENGL_PAINTER
00073 #include "mythpainter_ogl.h"
00074 #endif
00075 #include "mythpainter_qt.h"
00076 #include "mythgesture.h"
00077 #include "mythuihelper.h"
00078 #include "mythdialogbox.h"
00079
00080 #ifdef USING_MINGW
00081 #include "mythpainter_d3d9.h"
00082 #endif
00083
00084 #define GESTURE_TIMEOUT 1000
00085 #define STANDBY_TIMEOUT 90 // Minutes
00086
00087 #define LOC QString("MythMainWindow: ")
00088
00089 class KeyContext
00090 {
00091 public:
00092 void AddMapping(int key, QString action)
00093 {
00094 actionMap[key].append(action);
00095 }
00096
00097 bool GetMapping(int key, QStringList &actions)
00098 {
00099 if (actionMap.count(key) > 0)
00100 {
00101 actions += actionMap[key];
00102 return true;
00103 }
00104 return false;
00105 }
00106
00107 QMap<int, QStringList> actionMap;
00108 };
00109
00110 struct JumpData
00111 {
00112 void (*callback)(void);
00113 QString destination;
00114 QString description;
00115 bool exittomain;
00116 QString localAction;
00117 };
00118
00119 struct MPData {
00120 QString description;
00121 MediaPlayCallback playFn;
00122 };
00123
00124 class MythMainWindowPrivate
00125 {
00126 public:
00127 MythMainWindowPrivate() :
00128 wmult(1.0f), hmult(1.0f),
00129 screenwidth(0), screenheight(0),
00130 xbase(0), ybase(0),
00131 does_fill_screen(false),
00132 ignore_lirc_keys(false),
00133 ignore_joystick_keys(false),
00134 lircThread(NULL),
00135 #ifdef USE_JOYSTICK_MENU
00136 joystickThread(NULL),
00137 #endif
00138
00139 #ifdef USING_APPLEREMOTE
00140 appleRemoteListener(NULL),
00141 appleRemote(NULL),
00142 #endif
00143
00144 #ifdef USING_LIBCEC
00145 cecAdapter(NULL),
00146 #endif
00147
00148 exitingtomain(false),
00149 popwindows(false),
00150
00151 m_useDB(true),
00152
00153 exitmenucallback(NULL),
00154
00155 exitmenumediadevicecallback(NULL),
00156 mediadeviceforcallback(NULL),
00157
00158 escapekey(0),
00159
00160 sysEventHandler(NULL),
00161
00162 drawInterval(1000 / 70),
00163 drawTimer(NULL),
00164 mainStack(NULL),
00165
00166 painter(NULL),
00167 render(NULL),
00168
00169 AllowInput(true),
00170
00171 gesture(MythGesture()),
00172 gestureTimer(NULL),
00173 hideMouseTimer(NULL),
00174
00175 paintwin(NULL),
00176
00177 oldpaintwin(NULL),
00178 oldpainter(NULL),
00179 oldrender(NULL),
00180
00181 m_drawDisabledDepth(0),
00182 m_drawEnabled(true),
00183
00184 m_themeBase(NULL),
00185
00186 m_udpListener(NULL),
00187
00188 m_pendingUpdate(false),
00189
00190 idleTimer(NULL),
00191 standby(false),
00192 enteringStandby(false)
00193 {
00194 }
00195
00196 int TranslateKeyNum(QKeyEvent *e);
00197
00198 float wmult, hmult;
00199 int screenwidth, screenheight;
00200
00201 QRect screenRect;
00202 QRect uiScreenRect;
00203
00204 int xbase, ybase;
00205 bool does_fill_screen;
00206
00207 bool ignore_lirc_keys;
00208 bool ignore_joystick_keys;
00209
00210 LIRC *lircThread;
00211
00212 #ifdef USE_JOYSTICK_MENU
00213 JoystickMenuThread *joystickThread;
00214 #endif
00215
00216 #ifdef USING_APPLEREMOTE
00217 AppleRemoteListener *appleRemoteListener;
00218 AppleRemote *appleRemote;
00219 #endif
00220
00221 #ifdef USING_LIBCEC
00222 CECAdapter* cecAdapter;
00223 #endif
00224
00225 bool exitingtomain;
00226 bool popwindows;
00227
00228 bool m_useDB;
00229
00230 QHash<QString, KeyContext *> keyContexts;
00231 QMap<int, JumpData*> jumpMap;
00232 QMap<QString, JumpData> destinationMap;
00233 QMap<QString, MPData> mediaPluginMap;
00234
00235 void (*exitmenucallback)(void);
00236
00237 void (*exitmenumediadevicecallback)(MythMediaDevice* mediadevice);
00238 MythMediaDevice * mediadeviceforcallback;
00239
00240 int escapekey;
00241
00242 QObject *sysEventHandler;
00243
00244 int drawInterval;
00245 MythSignalingTimer *drawTimer;
00246 QVector<MythScreenStack *> stackList;
00247 MythScreenStack *mainStack;
00248
00249 MythPainter *painter;
00250 MythRender *render;
00251
00252
00253 bool AllowInput;
00254
00255 QRegion repaintRegion;
00256
00257 MythGesture gesture;
00258 QTimer *gestureTimer;
00259 QTimer *hideMouseTimer;
00260
00261
00262 std::vector<QWidget *> widgetList;
00263
00264 QWidget *paintwin;
00265
00266 QWidget *oldpaintwin;
00267 MythPainter *oldpainter;
00268 MythRender *oldrender;
00269
00270 QMutex m_drawDisableLock;
00271 QMutex m_setDrawEnabledLock;
00272 QWaitCondition m_setDrawEnabledWait;
00273 uint m_drawDisabledDepth;
00274 bool m_drawEnabled;
00275
00276 MythThemeBase *m_themeBase;
00277 MythUDPListener *m_udpListener;
00278
00279 bool m_pendingUpdate;
00280
00281 QTimer *idleTimer;
00282 bool standby;
00283 bool enteringStandby;
00284 };
00285
00286
00287 int MythMainWindowPrivate::TranslateKeyNum(QKeyEvent* e)
00288 {
00289 int keynum = e->key();
00290
00291 if ((keynum != Qt::Key_Shift ) && (keynum !=Qt::Key_Control ) &&
00292 (keynum != Qt::Key_Meta ) && (keynum !=Qt::Key_Alt ) &&
00293 (keynum != Qt::Key_Super_L) && (keynum !=Qt::Key_Super_R ) &&
00294 (keynum != Qt::Key_Hyper_L) && (keynum !=Qt::Key_Hyper_R ) &&
00295 (keynum != Qt::Key_AltGr ) && (keynum !=Qt::Key_CapsLock ) &&
00296 (keynum != Qt::Key_NumLock) && (keynum !=Qt::Key_ScrollLock ))
00297 {
00298 Qt::KeyboardModifiers modifiers;
00299
00300 if ((modifiers = e->modifiers()) != Qt::NoModifier)
00301 {
00302 int modnum = (((modifiers & Qt::ShiftModifier) &&
00303 (keynum > 0x7f) &&
00304 (keynum != Qt::Key_Backtab)) ? Qt::SHIFT : 0) |
00305 ((modifiers & Qt::ControlModifier) ? Qt::CTRL : 0) |
00306 ((modifiers & Qt::MetaModifier) ? Qt::META : 0) |
00307 ((modifiers & Qt::AltModifier) ? Qt::ALT : 0);
00308 modnum &= ~Qt::UNICODE_ACCEL;
00309 return (keynum |= modnum);
00310 }
00311 }
00312
00313 return keynum;
00314 }
00315
00316 static MythMainWindow *mainWin = NULL;
00317 static QMutex mainLock;
00318
00327 MythMainWindow *MythMainWindow::getMainWindow(const bool useDB)
00328 {
00329 if (mainWin)
00330 return mainWin;
00331
00332 QMutexLocker lock(&mainLock);
00333
00334 if (!mainWin)
00335 {
00336 mainWin = new MythMainWindow(useDB);
00337 gCoreContext->SetGUIObject(mainWin);
00338 }
00339
00340 return mainWin;
00341 }
00342
00343 void MythMainWindow::destroyMainWindow(void)
00344 {
00345 if (gCoreContext)
00346 gCoreContext->SetGUIObject(NULL);
00347 delete mainWin;
00348 mainWin = NULL;
00349 }
00350
00351 MythMainWindow *GetMythMainWindow(void)
00352 {
00353 return MythMainWindow::getMainWindow();
00354 }
00355
00356 bool HasMythMainWindow(void)
00357 {
00358 return (mainWin);
00359 }
00360
00361 void DestroyMythMainWindow(void)
00362 {
00363 MythMainWindow::destroyMainWindow();
00364 }
00365
00366 MythPainter *GetMythPainter(void)
00367 {
00368 return MythMainWindow::getMainWindow()->GetCurrentPainter();
00369 }
00370
00371 #ifdef USE_OPENGL_PAINTER
00372 MythPainterWindowGL::MythPainterWindowGL(MythMainWindow *win,
00373 MythMainWindowPrivate *priv,
00374 MythRenderOpenGL *rend)
00375 : QGLWidget(rend, win),
00376 parent(win), d(priv), render(rend)
00377 {
00378 setAutoBufferSwap(false);
00379 }
00380
00381 void MythPainterWindowGL::paintEvent(QPaintEvent *pe)
00382 {
00383 d->repaintRegion = d->repaintRegion.unite(pe->region());
00384 parent->drawScreen();
00385 }
00386 #endif
00387
00388 #ifdef USING_MINGW
00389 MythPainterWindowD3D9::MythPainterWindowD3D9(MythMainWindow *win,
00390 MythMainWindowPrivate *priv)
00391 : QGLWidget(win),
00392 parent(win), d(priv)
00393 {
00394 setAutoBufferSwap(false);
00395 }
00396
00397 void MythPainterWindowD3D9::paintEvent(QPaintEvent *pe)
00398 {
00399 d->repaintRegion = d->repaintRegion.unite(pe->region());
00400 parent->drawScreen();
00401 }
00402 #endif
00403
00404 MythPainterWindowQt::MythPainterWindowQt(MythMainWindow *win,
00405 MythMainWindowPrivate *priv)
00406 : QWidget(win),
00407 parent(win), d(priv)
00408 {
00409 }
00410
00411 void MythPainterWindowQt::paintEvent(QPaintEvent *pe)
00412 {
00413 d->repaintRegion = d->repaintRegion.unite(pe->region());
00414 parent->drawScreen();
00415 }
00416
00417 MythMainWindow::MythMainWindow(const bool useDB)
00418 : QWidget(NULL)
00419 {
00420 d = new MythMainWindowPrivate;
00421
00422 setObjectName("mainwindow");
00423
00424 d->AllowInput = false;
00425
00426
00427 d->m_useDB = useDB;
00428 d->painter = NULL;
00429 d->paintwin = NULL;
00430 d->oldpainter = NULL;
00431 d->oldpaintwin = NULL;
00432 d->oldrender = NULL;
00433
00434
00435
00436 d->ignore_lirc_keys = false;
00437 d->ignore_joystick_keys = false;
00438 d->exitingtomain = false;
00439 d->popwindows = true;
00440 d->exitmenucallback = NULL;
00441 d->exitmenumediadevicecallback = NULL;
00442 d->mediadeviceforcallback = NULL;
00443 d->escapekey = Qt::Key_Escape;
00444 d->mainStack = NULL;
00445 d->sysEventHandler = NULL;
00446
00447 installEventFilter(this);
00448
00449 d->lircThread = NULL;
00450 StartLIRC();
00451
00452 #ifdef USE_JOYSTICK_MENU
00453 d->ignore_joystick_keys = false;
00454
00455 QString joy_config_file = GetConfDir() + "/joystickmenurc";
00456
00457 d->joystickThread = NULL;
00458 d->joystickThread = new JoystickMenuThread(this);
00459 if (!d->joystickThread->Init(joy_config_file))
00460 d->joystickThread->start();
00461 #endif
00462
00463 #ifdef USING_APPLEREMOTE
00464 d->appleRemoteListener = new AppleRemoteListener(this);
00465 d->appleRemote = AppleRemote::Get();
00466
00467 d->appleRemote->setListener(d->appleRemoteListener);
00468 d->appleRemote->startListening();
00469 if (d->appleRemote->isListeningToRemote())
00470 d->appleRemote->start();
00471 #endif
00472
00473 #ifdef USING_LIBCEC
00474 d->cecAdapter = new CECAdapter();
00475 if (!d->cecAdapter->IsValid())
00476 {
00477 delete d->cecAdapter;
00478 d->cecAdapter = NULL;
00479 }
00480 #endif
00481
00482 d->m_udpListener = new MythUDPListener();
00483
00484 InitKeys();
00485
00486 d->gestureTimer = new QTimer(this);
00487 connect(d->gestureTimer, SIGNAL(timeout()), this, SLOT(mouseTimeout()));
00488 d->hideMouseTimer = new QTimer(this);
00489 d->hideMouseTimer->setSingleShot(true);
00490 d->hideMouseTimer->setInterval(3000);
00491 connect(d->hideMouseTimer, SIGNAL(timeout()), SLOT(HideMouseTimeout()));
00492
00493 d->drawTimer = new MythSignalingTimer(this, SLOT(animate()));
00494 d->drawTimer->start(d->drawInterval);
00495
00496 d->AllowInput = true;
00497
00498 d->repaintRegion = QRegion(QRect(0,0,0,0));
00499
00500 d->m_drawEnabled = true;
00501
00502 connect(this, SIGNAL(signalRemoteScreenShot(QString,int,int)),
00503 this, SLOT(doRemoteScreenShot(QString,int,int)),
00504 Qt::BlockingQueuedConnection);
00505
00506
00507 gCoreContext->addListener(this);
00508
00509 int idletime = gCoreContext->GetNumSetting("FrontendIdleTimeout",
00510 STANDBY_TIMEOUT);
00511 if (idletime <= 0)
00512 idletime = STANDBY_TIMEOUT;
00513
00514 d->idleTimer = new QTimer(this);
00515 d->idleTimer->setSingleShot(false);
00516 d->idleTimer->setInterval(1000 * 60 * idletime);
00517 connect(d->idleTimer, SIGNAL(timeout()), SLOT(IdleTimeout()));
00518 d->idleTimer->start();
00519 }
00520
00521 MythMainWindow::~MythMainWindow()
00522 {
00523 gCoreContext->removeListener(this);
00524
00525 d->drawTimer->stop();
00526
00527 while (!d->stackList.isEmpty())
00528 {
00529 MythScreenStack *stack = d->stackList.back();
00530 d->stackList.pop_back();
00531
00532 if (stack == d->mainStack)
00533 d->mainStack = NULL;
00534
00535 delete stack;
00536 }
00537
00538 delete d->m_themeBase;
00539
00540 while (!d->keyContexts.isEmpty())
00541 {
00542 KeyContext *context = *d->keyContexts.begin();
00543 d->keyContexts.erase(d->keyContexts.begin());
00544 delete context;
00545 }
00546
00547 #ifdef USE_LIRC
00548 if (d->lircThread)
00549 {
00550 d->lircThread->deleteLater();
00551 d->lircThread = NULL;
00552 }
00553 #endif
00554
00555 #ifdef USE_JOYSTICK_MENU
00556 if (d->joystickThread)
00557 {
00558 if (d->joystickThread->isRunning())
00559 {
00560 d->joystickThread->Stop();
00561 d->joystickThread->wait();
00562 }
00563
00564 delete d->joystickThread;
00565 d->joystickThread = NULL;
00566 }
00567 #endif
00568
00569 #ifdef USING_APPLEREMOTE
00570
00571
00572 if (d->appleRemote->isRunning())
00573 d->appleRemote->stopListening();
00574
00575 delete d->appleRemoteListener;
00576 #endif
00577
00578 #ifdef USING_LIBCEC
00579 if (d->cecAdapter)
00580 delete d->cecAdapter;
00581 #endif
00582
00583 delete d;
00584 }
00585
00586 MythPainter *MythMainWindow::GetCurrentPainter(void)
00587 {
00588 return d->painter;
00589 }
00590
00591 QWidget *MythMainWindow::GetPaintWindow(void)
00592 {
00593 return d->paintwin;
00594 }
00595
00596 void MythMainWindow::ShowPainterWindow(void)
00597 {
00598 if (d->paintwin)
00599 d->paintwin->show();
00600 if (d->render)
00601 d->render->Release();
00602 }
00603
00604 void MythMainWindow::HidePainterWindow(void)
00605 {
00606 if (d->paintwin)
00607 {
00608 d->paintwin->clearMask();
00609 if (!(d->render && d->render->IsShared()))
00610 d->paintwin->hide();
00611 }
00612 }
00613
00614 void MythMainWindow::ResizePainterWindow(const QSize &size)
00615 {
00616 if (!d->paintwin)
00617 return;
00618 d->paintwin->setFixedSize(size);
00619 d->paintwin->resize(size);
00620 }
00621
00622 MythRender *MythMainWindow::GetRenderDevice()
00623 {
00624 return d->render;
00625 }
00626
00627 void MythMainWindow::AddScreenStack(MythScreenStack *stack, bool main)
00628 {
00629 d->stackList.push_back(stack);
00630 if (main)
00631 d->mainStack = stack;
00632 }
00633
00634 void MythMainWindow::PopScreenStack()
00635 {
00636 delete d->stackList.back();
00637 d->stackList.pop_back();
00638 }
00639
00640 int MythMainWindow::GetStackCount(void)
00641 {
00642 return d->stackList.size();
00643 }
00644
00645 MythScreenStack *MythMainWindow::GetMainStack(void)
00646 {
00647 return d->mainStack;
00648 }
00649
00650 MythScreenStack *MythMainWindow::GetStack(const QString &stackname)
00651 {
00652 QVector<MythScreenStack *>::Iterator it;
00653 for (it = d->stackList.begin(); it != d->stackList.end(); ++it)
00654 {
00655 if ((*it)->objectName() == stackname)
00656 return *it;
00657 }
00658 return NULL;
00659 }
00660
00661 MythScreenStack* MythMainWindow::GetStackAt(int pos)
00662 {
00663 if (pos >= 0 && pos < d->stackList.size())
00664 return d->stackList.at(pos);
00665
00666 return NULL;
00667 }
00668
00669 void MythMainWindow::animate(void)
00670 {
00671
00672 if (currentWidget() || !d->m_drawEnabled)
00673 return;
00674
00675 if (!d->paintwin)
00676 return;
00677
00678 d->drawTimer->blockSignals(true);
00679
00680 bool redraw = false;
00681
00682 if (!d->repaintRegion.isEmpty())
00683 redraw = true;
00684
00685 QVector<MythScreenStack *>::Iterator it;
00686 for (it = d->stackList.begin(); it != d->stackList.end(); ++it)
00687 {
00688 QVector<MythScreenType *> drawList;
00689 (*it)->GetDrawOrder(drawList);
00690
00691 QVector<MythScreenType *>::Iterator screenit;
00692 for (screenit = drawList.begin(); screenit != drawList.end();
00693 ++screenit)
00694 {
00695 (*screenit)->Pulse();
00696
00697 if ((*screenit)->NeedsRedraw())
00698 {
00699 QRegion topDirty = (*screenit)->GetDirtyArea();
00700 (*screenit)->ResetNeedsRedraw();
00701 d->repaintRegion = d->repaintRegion.unite(topDirty);
00702 redraw = true;
00703 }
00704 }
00705 }
00706
00707 if (redraw && !(d->render && d->render->IsShared()))
00708 d->paintwin->update(d->repaintRegion);
00709
00710 for (it = d->stackList.begin(); it != d->stackList.end(); ++it)
00711 (*it)->ScheduleInitIfNeeded();
00712
00713 d->drawTimer->blockSignals(false);
00714 }
00715
00716 void MythMainWindow::drawScreen(void)
00717 {
00718
00719 if (currentWidget() || !d->m_drawEnabled)
00720 return;
00721
00722 if (!d->painter->SupportsClipping())
00723 d->repaintRegion = d->repaintRegion.unite(d->uiScreenRect);
00724 else
00725 {
00726
00727
00728 d->repaintRegion = d->repaintRegion.intersect(d->uiScreenRect);
00729
00730
00731
00732 QVector<MythScreenStack *>::Iterator it;
00733 for (it = d->stackList.begin(); it != d->stackList.end(); ++it)
00734 {
00735 QVector<MythScreenType *> redrawList;
00736 (*it)->GetDrawOrder(redrawList);
00737
00738 QVector<MythScreenType *>::Iterator screenit;
00739 for (screenit = redrawList.begin(); screenit != redrawList.end();
00740 ++screenit)
00741 {
00742 if ((*screenit)->NeedsRedraw())
00743 {
00744 QRegion topDirty = (*screenit)->GetDirtyArea();
00745 QVector<QRect> wrects = topDirty.rects();
00746 for (int i = 0; i < wrects.size(); i++)
00747 {
00748 bool foundThisRect = false;
00749 QVector<QRect> drects = d->repaintRegion.rects();
00750 for (int j = 0; j < drects.size(); j++)
00751 {
00752 if (drects[j].contains(wrects[i]))
00753 {
00754 foundThisRect = true;
00755 break;
00756 }
00757 }
00758
00759 if (!foundThisRect)
00760 return;
00761 }
00762 }
00763 }
00764 }
00765 }
00766
00767 if (!(d->render && d->render->IsShared()))
00768 draw();
00769
00770 d->repaintRegion = QRegion(QRect(0, 0, 0, 0));
00771 }
00772
00773 void MythMainWindow::draw(void)
00774 {
00775 if (!d->painter)
00776 return;
00777
00778 d->painter->Begin(d->paintwin);
00779
00780 QVector<QRect> rects = d->repaintRegion.rects();
00781
00782 for (int i = 0; i < rects.size(); i++)
00783 {
00784 if (rects[i].width() == 0 || rects[i].height() == 0)
00785 continue;
00786
00787 if (rects[i] != d->uiScreenRect)
00788 d->painter->SetClipRect(rects[i]);
00789
00790 QVector<MythScreenStack *>::Iterator it;
00791 for (it = d->stackList.begin(); it != d->stackList.end(); ++it)
00792 {
00793 QVector<MythScreenType *> redrawList;
00794 (*it)->GetDrawOrder(redrawList);
00795
00796 QVector<MythScreenType *>::Iterator screenit;
00797 for (screenit = redrawList.begin(); screenit != redrawList.end();
00798 ++screenit)
00799 {
00800 (*screenit)->Draw(d->painter, 0, 0, 255, rects[i]);
00801 }
00802 }
00803 }
00804
00805 d->painter->End();
00806 }
00807
00808 void MythMainWindow::closeEvent(QCloseEvent *e)
00809 {
00810 if (e->spontaneous())
00811 {
00812 QKeyEvent *key = new QKeyEvent(QEvent::KeyPress, d->escapekey,
00813 Qt::NoModifier);
00814 QCoreApplication::postEvent(this, key);
00815 e->ignore();
00816 }
00817 else
00818 QWidget::closeEvent(e);
00819 }
00820
00821 void MythMainWindow::GrabWindow(QImage &image)
00822 {
00823 WId winid;
00824 QWidget *active = QApplication::activeWindow();
00825 if (active)
00826 winid = active->winId();
00827 else
00828 winid = QApplication::desktop()->winId();
00829
00830 QPixmap p = QPixmap::grabWindow(winid);
00831 image = p.toImage();
00832 }
00833
00834
00835
00836
00837
00838 void MythMainWindow::doRemoteScreenShot(QString filename, int x, int y)
00839 {
00840
00841 QStringList args;
00842 args << QString::number(x);
00843 args << QString::number(y);
00844 args << filename;
00845
00846 MythEvent me(MythEvent::MythEventMessage, ACTION_SCREENSHOT, args);
00847 qApp->sendEvent(this, &me);
00848 }
00849
00850 void MythMainWindow::RemoteScreenShot(QString filename, int x, int y)
00851 {
00852
00853
00854 emit signalRemoteScreenShot(filename, x, y);
00855 }
00856
00857 bool MythMainWindow::SaveScreenShot(const QImage &image, QString filename)
00858 {
00859 if (filename.isEmpty())
00860 {
00861 QString fpath = GetMythDB()->GetSetting("ScreenShotPath", "/tmp");
00862 filename = QString("%1/myth-screenshot-%2.png").arg(fpath)
00863 .arg(QDateTime::currentDateTime().toString("yyyy-MM-ddThh-mm-ss.zzz"));
00864 }
00865
00866 QString extension = filename.section('.', -1, -1);
00867 if (extension == "jpg")
00868 extension = "JPEG";
00869 else
00870 extension = "PNG";
00871
00872 LOG(VB_GENERAL, LOG_INFO, QString("Saving screenshot to %1 (%2x%3)")
00873 .arg(filename).arg(image.width()).arg(image.height()));
00874
00875 if (image.save(filename, extension.toAscii(), 100))
00876 {
00877 LOG(VB_GENERAL, LOG_INFO, "MythMainWindow::screenShot succeeded");
00878 return true;
00879 }
00880
00881 LOG(VB_GENERAL, LOG_INFO, "MythMainWindow::screenShot Failed!");
00882 return false;
00883 }
00884
00885 bool MythMainWindow::ScreenShot(int w, int h, QString filename)
00886 {
00887 QImage img;
00888 GrabWindow(img);
00889 if (w <= 0)
00890 w = img.width();
00891 if (h <= 0)
00892 h = img.height();
00893
00894 img = img.scaled(w, h, Qt::KeepAspectRatio, Qt::SmoothTransformation);
00895 return SaveScreenShot(img, filename);
00896 }
00897
00898 bool MythMainWindow::event(QEvent *e)
00899 {
00900 if (!updatesEnabled() && (e->type() == QEvent::UpdateRequest))
00901 d->m_pendingUpdate = true;
00902
00903 if (e->type() == QEvent::Show && !e->spontaneous())
00904 {
00905 QCoreApplication::postEvent(
00906 this, new QEvent(MythEvent::kMythPostShowEventType));
00907 }
00908
00909 if (e->type() == MythEvent::kMythPostShowEventType)
00910 {
00911 raise();
00912 activateWindow();
00913 return true;
00914 }
00915
00916 #ifdef USING_APPLEREMOTE
00917 if (d->appleRemote)
00918 {
00919 if (e->type() == QEvent::WindowActivate)
00920 d->appleRemote->startListening();
00921
00922 if (e->type() == QEvent::WindowDeactivate)
00923 d->appleRemote->stopListening();
00924 }
00925 #endif
00926
00927 return QWidget::event(e);
00928 }
00929
00930 void MythMainWindow::Init(void)
00931 {
00932 GetMythUI()->GetScreenSettings(d->xbase, d->screenwidth, d->wmult,
00933 d->ybase, d->screenheight, d->hmult);
00934
00935 if (GetMythDB()->GetNumSetting("GuiOffsetX") > 0 ||
00936 GetMythDB()->GetNumSetting("GuiWidth") > 0 ||
00937 GetMythDB()->GetNumSetting("GuiOffsetY") > 0 ||
00938 GetMythDB()->GetNumSetting("GuiHeight") > 0)
00939 d->does_fill_screen = false;
00940 else
00941 d->does_fill_screen = true;
00942
00943
00944 Qt::WindowFlags flags = Qt::Window;
00945
00946 if (!GetMythDB()->GetNumSetting("RunFrontendInWindow", 0))
00947 {
00948 LOG(VB_GENERAL, LOG_INFO, "Using Frameless Window");
00949 flags |= Qt::FramelessWindowHint;
00950 }
00951
00952
00953 #ifdef _WIN32
00954 flags |= Qt::MSWindowsOwnDC;
00955 #endif
00956
00957 setWindowFlags(flags);
00958
00959 if (d->does_fill_screen && !GetMythUI()->IsGeometryOverridden())
00960 {
00961 LOG(VB_GENERAL, LOG_INFO, "Using Full Screen Window");
00962 setWindowState(Qt::WindowFullScreen);
00963 }
00964
00965 d->screenRect = QRect(d->xbase, d->ybase, d->screenwidth, d->screenheight);
00966 d->uiScreenRect = QRect(0, 0, d->screenwidth, d->screenheight);
00967
00968 setGeometry(d->xbase, d->ybase, d->screenwidth, d->screenheight);
00969 setFixedSize(QSize(d->screenwidth, d->screenheight));
00970
00971 GetMythUI()->ThemeWidget(this);
00972 Show();
00973
00974 if (!GetMythDB()->GetNumSetting("HideMouseCursor", 0))
00975 setMouseTracking(true);
00976
00977 ShowMouseCursor(false);
00978
00979 move(d->xbase, d->ybase);
00980
00981 if (d->paintwin)
00982 {
00983 d->oldpaintwin = d->paintwin;
00984 d->paintwin = NULL;
00985 d->drawTimer->stop();
00986 }
00987
00988 if (d->painter)
00989 {
00990 d->oldpainter = d->painter;
00991 d->painter = NULL;
00992 }
00993
00994 if (d->render)
00995 {
00996 d->oldrender = d->render;
00997 d->render = NULL;
00998 }
00999
01000 QString painter = GetMythDB()->GetSetting("ThemePainter", "qt");
01001 #ifdef USING_MINGW
01002 if (painter == "auto" || painter == "d3d9")
01003 {
01004 LOG(VB_GENERAL, LOG_INFO, "Using the D3D9 painter");
01005 d->painter = new MythD3D9Painter();
01006 d->paintwin = new MythPainterWindowD3D9(this, d);
01007 }
01008 #endif
01009 #ifdef USE_OPENGL_PAINTER
01010 if ((painter == "auto" && (!d->painter && !d->paintwin)) ||
01011 painter.contains("opengl"))
01012 {
01013 LOG(VB_GENERAL, LOG_INFO, "Trying the OpenGL painter");
01014 d->painter = new MythOpenGLPainter();
01015 d->render = MythRenderOpenGL::Create(painter);
01016 MythRenderOpenGL *gl = dynamic_cast<MythRenderOpenGL*>(d->render);
01017 d->paintwin = new MythPainterWindowGL(this, d, gl);
01018 QGLWidget *qgl = dynamic_cast<QGLWidget *>(d->paintwin);
01019 if (qgl)
01020 {
01021 bool teardown = false;
01022 if (!qgl->isValid())
01023 {
01024 LOG(VB_GENERAL, LOG_ERR, "Failed to create OpenGL painter. "
01025 "Check your OpenGL installation.");
01026 teardown = true;
01027 }
01028 else if (painter == "auto" && gl && !gl->IsRecommendedRenderer())
01029 {
01030 LOG(VB_GENERAL, LOG_WARNING,
01031 "OpenGL painter not recommended with this system's "
01032 "hardware/drivers. Falling back to Qt painter.");
01033 teardown = true;
01034 }
01035 if (teardown)
01036 {
01037 delete d->painter;
01038 d->painter = NULL;
01039 delete d->paintwin;
01040 d->paintwin = NULL;
01041 d->render = NULL;
01042 }
01043 else
01044 gl->Init();
01045 }
01046 }
01047 #endif
01048
01049 if (!d->painter && !d->paintwin)
01050 {
01051 LOG(VB_GENERAL, LOG_INFO, "Using the Qt painter");
01052 d->painter = new MythQtPainter();
01053 d->paintwin = new MythPainterWindowQt(this, d);
01054 }
01055
01056 if (!d->paintwin)
01057 {
01058 LOG(VB_GENERAL, LOG_ERR, "MythMainWindow failed to create a "
01059 "painter window.");
01060 return;
01061 }
01062
01063 if (d->painter->GetName() != "Qt")
01064 {
01065 setAttribute(Qt::WA_NoSystemBackground);
01066 setAutoFillBackground(false);
01067 }
01068
01069 d->paintwin->move(0, 0);
01070 ResizePainterWindow(size());
01071 d->paintwin->raise();
01072 ShowPainterWindow();
01073 if (!GetMythDB()->GetNumSetting("HideMouseCursor", 0))
01074 d->paintwin->setMouseTracking(true);
01075
01076 GetMythUI()->UpdateImageCache();
01077 if (d->m_themeBase)
01078 d->m_themeBase->Reload();
01079 else
01080 d->m_themeBase = new MythThemeBase();
01081 }
01082
01083 void MythMainWindow::InitKeys()
01084 {
01085 RegisterKey("Global", ACTION_UP, QT_TRANSLATE_NOOP("MythControls",
01086 "Up Arrow"), "Up");
01087 RegisterKey("Global", ACTION_DOWN, QT_TRANSLATE_NOOP("MythControls",
01088 "Down Arrow"), "Down");
01089 RegisterKey("Global", ACTION_LEFT, QT_TRANSLATE_NOOP("MythControls",
01090 "Left Arrow"), "Left");
01091 RegisterKey("Global", ACTION_RIGHT, QT_TRANSLATE_NOOP("MythControls",
01092 "Right Arrow"), "Right");
01093 RegisterKey("Global", "NEXT", QT_TRANSLATE_NOOP("MythControls",
01094 "Move to next widget"), "Tab");
01095 RegisterKey("Global", "PREVIOUS", QT_TRANSLATE_NOOP("MythControls",
01096 "Move to preview widget"), "Backtab");
01097 RegisterKey("Global", ACTION_SELECT, QT_TRANSLATE_NOOP("MythControls",
01098 "Select"), "Return,Enter,Space");
01099 RegisterKey("Global", "BACKSPACE", QT_TRANSLATE_NOOP("MythControls",
01100 "Backspace"), "Backspace");
01101 RegisterKey("Global", "ESCAPE", QT_TRANSLATE_NOOP("MythControls",
01102 "Escape"), "Esc");
01103 RegisterKey("Global", "MENU", QT_TRANSLATE_NOOP("MythControls",
01104 "Pop-up menu"), "M");
01105 RegisterKey("Global", "INFO", QT_TRANSLATE_NOOP("MythControls",
01106 "More information"), "I");
01107 RegisterKey("Global", "DELETE", QT_TRANSLATE_NOOP("MythControls",
01108 "Delete"), "D");
01109 RegisterKey("Global", "EDIT", QT_TRANSLATE_NOOP("MythControls",
01110 "Edit"), "E");
01111 RegisterKey("Global", ACTION_SCREENSHOT, QT_TRANSLATE_NOOP("MythControls",
01112 "Save screenshot"), "");
01113 RegisterKey("Global", ACTION_HANDLEMEDIA, QT_TRANSLATE_NOOP("MythControls",
01114 "Play a media resource"), "");
01115
01116 RegisterKey("Global", "PAGEUP", QT_TRANSLATE_NOOP("MythControls",
01117 "Page Up"), "PgUp");
01118 RegisterKey("Global", "PAGEDOWN", QT_TRANSLATE_NOOP("MythControls",
01119 "Page Down"), "PgDown");
01120 RegisterKey("Global", "PAGETOP", QT_TRANSLATE_NOOP("MythControls",
01121 "Page to top of list"), "");
01122 RegisterKey("Global", "PAGEMIDDLE", QT_TRANSLATE_NOOP("MythControls",
01123 "Page to middle of list"), "");
01124 RegisterKey("Global", "PAGEBOTTOM", QT_TRANSLATE_NOOP("MythControls",
01125 "Page to bottom of list"), "");
01126
01127 RegisterKey("Global", "PREVVIEW", QT_TRANSLATE_NOOP("MythControls",
01128 "Previous View"), "Home");
01129 RegisterKey("Global", "NEXTVIEW", QT_TRANSLATE_NOOP("MythControls",
01130 "Next View"), "End");
01131
01132 RegisterKey("Global", "HELP", QT_TRANSLATE_NOOP("MythControls",
01133 "Help"), "F1");
01134 RegisterKey("Global", "EJECT", QT_TRANSLATE_NOOP("MythControls"
01135 ,"Eject Removable Media"), "");
01136
01137 RegisterKey("Global", "CUT", QT_TRANSLATE_NOOP("MythControls",
01138 "Cut text from textedit"), "Ctrl+X");
01139 RegisterKey("Global", "COPY", QT_TRANSLATE_NOOP("MythControls"
01140 ,"Copy text from textedit"), "Ctrl+C");
01141 RegisterKey("Global", "PASTE", QT_TRANSLATE_NOOP("MythControls",
01142 "Paste text into textedit"), "Ctrl+V");
01143 RegisterKey("Global", "UNDO", QT_TRANSLATE_NOOP("MythControls",
01144 "Undo"), "Ctrl+Z");
01145 RegisterKey("Global", "REDO", QT_TRANSLATE_NOOP("MythControls",
01146 "Redo"), "Ctrl+Y");
01147 RegisterKey("Global", "SEARCH", QT_TRANSLATE_NOOP("MythControls",
01148 "Show incremental search dialog"), "Ctrl+S");
01149
01150 RegisterKey("Global", ACTION_0, QT_TRANSLATE_NOOP("MythControls","0"), "0");
01151 RegisterKey("Global", ACTION_1, QT_TRANSLATE_NOOP("MythControls","1"), "1");
01152 RegisterKey("Global", ACTION_2, QT_TRANSLATE_NOOP("MythControls","2"), "2");
01153 RegisterKey("Global", ACTION_3, QT_TRANSLATE_NOOP("MythControls","3"), "3");
01154 RegisterKey("Global", ACTION_4, QT_TRANSLATE_NOOP("MythControls","4"), "4");
01155 RegisterKey("Global", ACTION_5, QT_TRANSLATE_NOOP("MythControls","5"), "5");
01156 RegisterKey("Global", ACTION_6, QT_TRANSLATE_NOOP("MythControls","6"), "6");
01157 RegisterKey("Global", ACTION_7, QT_TRANSLATE_NOOP("MythControls","7"), "7");
01158 RegisterKey("Global", ACTION_8, QT_TRANSLATE_NOOP("MythControls","8"), "8");
01159 RegisterKey("Global", ACTION_9, QT_TRANSLATE_NOOP("MythControls","9"), "9");
01160
01161 RegisterKey("Global", ACTION_TVPOWERON, QT_TRANSLATE_NOOP("MythControls",
01162 "Turn the display on"), "");
01163 RegisterKey("Global", ACTION_TVPOWEROFF, QT_TRANSLATE_NOOP("MythControls",
01164 "Turn the display off"), "");
01165
01166 RegisterKey("Global", "SYSEVENT01", QT_TRANSLATE_NOOP("MythControls",
01167 "Trigger System Key Event #1"), "");
01168 RegisterKey("Global", "SYSEVENT02", QT_TRANSLATE_NOOP("MythControls",
01169 "Trigger System Key Event #2"), "");
01170 RegisterKey("Global", "SYSEVENT03", QT_TRANSLATE_NOOP("MythControls",
01171 "Trigger System Key Event #3"), "");
01172 RegisterKey("Global", "SYSEVENT04", QT_TRANSLATE_NOOP("MythControls",
01173 "Trigger System Key Event #4"), "");
01174 RegisterKey("Global", "SYSEVENT05", QT_TRANSLATE_NOOP("MythControls",
01175 "Trigger System Key Event #5"), "");
01176 RegisterKey("Global", "SYSEVENT06", QT_TRANSLATE_NOOP("MythControls",
01177 "Trigger System Key Event #6"), "");
01178 RegisterKey("Global", "SYSEVENT07", QT_TRANSLATE_NOOP("MythControls",
01179 "Trigger System Key Event #7"), "");
01180 RegisterKey("Global", "SYSEVENT08", QT_TRANSLATE_NOOP("MythControls",
01181 "Trigger System Key Event #8"), "");
01182 RegisterKey("Global", "SYSEVENT09", QT_TRANSLATE_NOOP("MythControls",
01183 "Trigger System Key Event #9"), "");
01184 RegisterKey("Global", "SYSEVENT10", QT_TRANSLATE_NOOP("MythControls",
01185 "Trigger System Key Event #10"), "");
01186
01187
01188 RegisterKey("Browser", "ZOOMIN", QT_TRANSLATE_NOOP("MythControls",
01189 "Zoom in on browser window"), ".,>");
01190 RegisterKey("Browser", "ZOOMOUT", QT_TRANSLATE_NOOP("MythControls",
01191 "Zoom out on browser window"), ",,<");
01192 RegisterKey("Browser", "TOGGLEINPUT", QT_TRANSLATE_NOOP("MythControls",
01193 "Toggle where keyboard input goes to"), "F1");
01194
01195 RegisterKey("Browser", "MOUSEUP", QT_TRANSLATE_NOOP("MythControls",
01196 "Move mouse pointer up"), "2");
01197 RegisterKey("Browser", "MOUSEDOWN", QT_TRANSLATE_NOOP("MythControls",
01198 "Move mouse pointer down"), "8");
01199 RegisterKey("Browser", "MOUSELEFT", QT_TRANSLATE_NOOP("MythControls",
01200 "Move mouse pointer left"), "4");
01201 RegisterKey("Browser", "MOUSERIGHT", QT_TRANSLATE_NOOP("MythControls",
01202 "Move mouse pointer right"), "6");
01203 RegisterKey("Browser", "MOUSELEFTBUTTON", QT_TRANSLATE_NOOP("MythControls",
01204 "Mouse Left button click"), "5");
01205
01206 RegisterKey("Browser", "PAGEDOWN", QT_TRANSLATE_NOOP("MythControls",
01207 "Scroll down half a page"), "9");
01208 RegisterKey("Browser", "PAGEUP", QT_TRANSLATE_NOOP("MythControls",
01209 "Scroll up half a page"), "3");
01210 RegisterKey("Browser", "PAGELEFT", QT_TRANSLATE_NOOP("MythControls",
01211 "Scroll left half a page"), "7");
01212 RegisterKey("Browser", "PAGERIGHT", QT_TRANSLATE_NOOP("MythControls",
01213 "Scroll right half a page"), "1");
01214
01215 RegisterKey("Browser", "NEXTLINK", QT_TRANSLATE_NOOP("MythControls",
01216 "Move selection to next link"), "Z");
01217 RegisterKey("Browser", "PREVIOUSLINK", QT_TRANSLATE_NOOP("MythControls",
01218 "Move selection to previous link"), "Q");
01219 RegisterKey("Browser", "FOLLOWLINK", QT_TRANSLATE_NOOP("MythControls",
01220 "Follow selected link"), "Return,Space,Enter");
01221 RegisterKey("Browser", "HISTORYBACK", QT_TRANSLATE_NOOP("MythControls",
01222 "Go back to previous page"), "R,Backspace");
01223 RegisterKey("Browser", "HISTORYFORWARD", QT_TRANSLATE_NOOP("MythControls",
01224 "Go forward to previous page"), "F");
01225
01226 RegisterKey("Main Menu", "EXITPROMPT", QT_TRANSLATE_NOOP("MythControls",
01227 "Display System Exit Prompt"), "Esc");
01228 RegisterKey("Main Menu", "EXIT", QT_TRANSLATE_NOOP("MythControls",
01229 "System Exit"), "");
01230 }
01231
01232 void MythMainWindow::ReloadKeys()
01233 {
01234 ClearKeyContext("Global");
01235 ClearKeyContext("Browser");
01236 ClearKeyContext("Main Menu");
01237 InitKeys();
01238 }
01239
01240 void MythMainWindow::ReinitDone(void)
01241 {
01242 delete d->oldpainter;
01243 d->oldpainter = NULL;
01244
01245 delete d->oldpaintwin;
01246 d->oldpaintwin = NULL;
01247
01248
01249
01250 d->oldrender = NULL;
01251
01252 d->paintwin->move(0, 0);
01253 d->paintwin->setFixedSize(size());
01254 d->paintwin->raise();
01255 ShowPainterWindow();
01256
01257 d->drawTimer->start(1000 / 70);
01258 }
01259
01260 void MythMainWindow::Show(void)
01261 {
01262 show();
01263 #ifdef Q_WS_MACX_OLDQT
01264 if (d->does_fill_screen)
01265 HideMenuBar();
01266 else
01267 ShowMenuBar();
01268 #endif
01269 }
01270
01271
01272 void MythMainWindow::attach(QWidget *child)
01273 {
01274 #ifdef USING_MINGW
01275 # ifdef _MSC_VER
01276 # pragma message( "TODO FIXME MythMainWindow::attach() does not always work on MS Windows!")
01277 # else
01278 # warning TODO FIXME MythMainWindow::attach() does not always work on MS Windows!
01279 # endif
01280
01281
01282
01283
01284 LOG(VB_GENERAL, LOG_ERR,
01285 QString("MythMainWindow::attach old: %1, new: %2, thread: %3")
01286 .arg(currentWidget() ? currentWidget()->objectName() : "none")
01287 .arg(child->objectName())
01288 .arg(::GetCurrentThreadId()));
01289 #endif
01290 if (currentWidget())
01291 currentWidget()->setEnabled(false);
01292
01293 d->widgetList.push_back(child);
01294 #ifndef Q_WS_MACX
01295 child->winId();
01296 #endif
01297 child->raise();
01298 child->setFocus();
01299 child->setMouseTracking(true);
01300 }
01301
01302 void MythMainWindow::detach(QWidget *child)
01303 {
01304 std::vector<QWidget*>::iterator it =
01305 std::find(d->widgetList.begin(), d->widgetList.end(), child);
01306
01307 if (it == d->widgetList.end())
01308 {
01309 LOG(VB_GENERAL, LOG_ERR, "Could not find widget to detach");
01310 return;
01311 }
01312
01313 d->widgetList.erase(it);
01314 QWidget *current = currentWidget();
01315
01316 if (current)
01317 {
01318 current->setEnabled(true);
01319 current->setFocus();
01320 current->setMouseTracking(true);
01321 }
01322
01323 if (d->exitingtomain)
01324 {
01325 QCoreApplication::postEvent(
01326 this, new QEvent(MythEvent::kExitToMainMenuEventType));
01327 }
01328 }
01329
01330 QWidget *MythMainWindow::currentWidget(void)
01331 {
01332 if (d->widgetList.size() > 0)
01333 return d->widgetList.back();
01334 return NULL;
01335 }
01336
01337
01338 uint MythMainWindow::PushDrawDisabled(void)
01339 {
01340 QMutexLocker locker(&d->m_drawDisableLock);
01341 d->m_drawDisabledDepth++;
01342 if (d->m_drawDisabledDepth && d->m_drawEnabled)
01343 SetDrawEnabled(false);
01344 return d->m_drawDisabledDepth;
01345 }
01346
01347 uint MythMainWindow::PopDrawDisabled(void)
01348 {
01349 QMutexLocker locker(&d->m_drawDisableLock);
01350 if (d->m_drawDisabledDepth)
01351 {
01352 d->m_drawDisabledDepth--;
01353 if (!d->m_drawDisabledDepth && !d->m_drawEnabled)
01354 SetDrawEnabled(true);
01355 }
01356 return d->m_drawDisabledDepth;
01357 }
01358
01359 void MythMainWindow::SetDrawEnabled(bool enable)
01360 {
01361 QMutexLocker locker(&d->m_setDrawEnabledLock);
01362
01363 if (!gCoreContext->IsUIThread())
01364 {
01365 QCoreApplication::postEvent(
01366 this, new MythEvent(
01367 (enable) ?
01368 MythEvent::kEnableDrawingEventType :
01369 MythEvent::kDisableDrawingEventType));
01370
01371 while (QCoreApplication::hasPendingEvents())
01372 d->m_setDrawEnabledWait.wait(&d->m_setDrawEnabledLock);
01373
01374 return;
01375 }
01376
01377 setUpdatesEnabled(enable);
01378 d->m_drawEnabled = enable;
01379
01380 if (enable)
01381 {
01382 if (d->m_pendingUpdate)
01383 {
01384 QApplication::postEvent(this, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
01385 d->m_pendingUpdate = false;
01386 }
01387 d->drawTimer->start(1000 / 70);
01388 ShowPainterWindow();
01389 }
01390 else
01391 {
01392 HidePainterWindow();
01393 d->drawTimer->stop();
01394 }
01395
01396 d->m_setDrawEnabledWait.wakeAll();
01397 }
01398
01399 void MythMainWindow::SetEffectsEnabled(bool enable)
01400 {
01401 QVector<MythScreenStack *>::Iterator it;
01402 for (it = d->stackList.begin(); it != d->stackList.end(); ++it)
01403 {
01404 if (enable)
01405 (*it)->EnableEffects();
01406 else
01407 (*it)->DisableEffects();
01408 }
01409 }
01410
01411 bool MythMainWindow::IsExitingToMain(void) const
01412 {
01413 return d->exitingtomain;
01414 }
01415
01416 void MythMainWindow::ExitToMainMenu(void)
01417 {
01418 bool jumpdone = !(d->popwindows);
01419
01420 d->exitingtomain = true;
01421
01422
01423 QWidget *current = currentWidget();
01424 if (current && d->exitingtomain && d->popwindows)
01425 {
01426 if (current->objectName() != QString("mainmenu"))
01427 {
01428 if (current->objectName() == QString("video playback window"))
01429 {
01430 MythEvent *me = new MythEvent("EXIT_TO_MENU");
01431 QCoreApplication::postEvent(current, me);
01432 }
01433 else if (current->inherits("MythDialog"))
01434 {
01435 QKeyEvent *key = new QKeyEvent(QEvent::KeyPress, d->escapekey,
01436 Qt::NoModifier);
01437 QObject *key_target = getTarget(*key);
01438 QCoreApplication::postEvent(key_target, key);
01439 }
01440 return;
01441 }
01442 else
01443 jumpdone = true;
01444 }
01445
01446 MythScreenStack *toplevel = GetMainStack();
01447 if (toplevel && d->popwindows)
01448 {
01449 MythScreenType *screen = toplevel->GetTopScreen();
01450 if (screen && screen->objectName() != QString("mainmenu"))
01451 {
01452 MythEvent xe("EXIT_TO_MENU");
01453 gCoreContext->dispatch(xe);
01454 if (screen->objectName() == QString("video playback window"))
01455 {
01456 MythEvent *me = new MythEvent("EXIT_TO_MENU");
01457 QCoreApplication::postEvent(screen, me);
01458 }
01459 else
01460 {
01461 QKeyEvent *key = new QKeyEvent(QEvent::KeyPress, d->escapekey,
01462 Qt::NoModifier);
01463 QCoreApplication::postEvent(this, key);
01464 }
01465 return;
01466 }
01467 else
01468 jumpdone = true;
01469 }
01470
01471 if (jumpdone)
01472 {
01473 d->exitingtomain = false;
01474 d->popwindows = true;
01475 if (d->exitmenucallback)
01476 {
01477 void (*callback)(void) = d->exitmenucallback;
01478 d->exitmenucallback = NULL;
01479 callback();
01480 }
01481 else if (d->exitmenumediadevicecallback)
01482 {
01483 void (*callback)(MythMediaDevice*) = d->exitmenumediadevicecallback;
01484 MythMediaDevice * mediadevice = d->mediadeviceforcallback;
01485 d->mediadeviceforcallback = NULL;
01486 callback(mediadevice);
01487 }
01488 }
01489 }
01490
01501 bool MythMainWindow::TranslateKeyPress(const QString &context,
01502 QKeyEvent *e, QStringList &actions,
01503 bool allowJumps)
01504 {
01505 actions.clear();
01506
01507
01508
01509 if (e->key() == 0 && !e->text().isEmpty() &&
01510 e->modifiers() == Qt::NoModifier)
01511 {
01512 QString action = e->text();
01513
01514 if (!d->destinationMap.contains(action))
01515 {
01516 actions.append(action);
01517 return false;
01518 }
01519
01520 if (allowJumps)
01521 {
01522
01523
01524
01525
01526
01527 JumpTo(action);
01528 return true;
01529 }
01530
01531 return false;
01532 }
01533
01534 int keynum = d->TranslateKeyNum(e);
01535
01536 QStringList localActions;
01537 if (allowJumps && (d->jumpMap.count(keynum) > 0) &&
01538 (!d->jumpMap[keynum]->localAction.isEmpty()) &&
01539 (d->keyContexts.value(context)) &&
01540 (d->keyContexts.value(context)->GetMapping(keynum, localActions)))
01541 {
01542 if (localActions.contains(d->jumpMap[keynum]->localAction))
01543 allowJumps = false;
01544 }
01545
01546 if (allowJumps && d->jumpMap.count(keynum) > 0 &&
01547 !d->jumpMap[keynum]->exittomain && d->exitmenucallback == NULL)
01548 {
01549 void (*callback)(void) = d->jumpMap[keynum]->callback;
01550 callback();
01551 return true;
01552 }
01553
01554 if (allowJumps &&
01555 d->jumpMap.count(keynum) > 0 && d->exitmenucallback == NULL)
01556 {
01557 d->exitingtomain = true;
01558 d->exitmenucallback = d->jumpMap[keynum]->callback;
01559 QCoreApplication::postEvent(
01560 this, new QEvent(MythEvent::kExitToMainMenuEventType));
01561 return true;
01562 }
01563
01564 if (d->keyContexts.value(context))
01565 d->keyContexts.value(context)->GetMapping(keynum, actions);
01566
01567 if (context != "Global")
01568 d->keyContexts.value("Global")->GetMapping(keynum, actions);
01569
01570 return false;
01571 }
01572
01573 void MythMainWindow::ClearKey(const QString &context, const QString &action)
01574 {
01575 KeyContext * keycontext = d->keyContexts.value(context);
01576 if (keycontext == NULL) return;
01577
01578 QMutableMapIterator<int, QStringList> it(keycontext->actionMap);
01579 while (it.hasNext())
01580 {
01581 it.next();
01582 QStringList list = it.value();
01583
01584 list.removeAll(action);
01585 if (list.isEmpty())
01586 it.remove();
01587 }
01588 }
01589
01590 void MythMainWindow::ClearKeyContext(const QString &context)
01591 {
01592 KeyContext *keycontext = d->keyContexts.value(context);
01593 if (keycontext != NULL)
01594 keycontext->actionMap.clear();
01595 }
01596
01597 void MythMainWindow::BindKey(const QString &context, const QString &action,
01598 const QString &key)
01599 {
01600 QKeySequence keyseq(key);
01601
01602 if (!d->keyContexts.contains(context))
01603 d->keyContexts.insert(context, new KeyContext());
01604
01605 for (unsigned int i = 0; i < keyseq.count(); i++)
01606 {
01607 int keynum = keyseq[i];
01608 keynum &= ~Qt::UNICODE_ACCEL;
01609
01610 QStringList dummyaction("");
01611 if (d->keyContexts.value(context)->GetMapping(keynum, dummyaction))
01612 {
01613 LOG(VB_GENERAL, LOG_WARNING,
01614 QString("Key %1 is bound to multiple actions in context %2.")
01615 .arg(key).arg(context));
01616 }
01617
01618 d->keyContexts.value(context)->AddMapping(keynum, action);
01619 #if 0
01620 LOG(VB_GENERAL, LOG_DEBUG, QString("Binding: %1 to action: %2 (%3)")
01621 .arg(key).arg(action).arg(context));
01622 #endif
01623
01624 if (action == "ESCAPE" && context == "Global" && i == 0)
01625 d->escapekey = keynum;
01626 }
01627 }
01628
01629 void MythMainWindow::RegisterKey(const QString &context, const QString &action,
01630 const QString &description, const QString &key)
01631 {
01632 QString keybind = key;
01633
01634 MSqlQuery query(MSqlQuery::InitCon());
01635
01636 if (d->m_useDB && query.isConnected())
01637 {
01638 query.prepare("SELECT keylist, description FROM keybindings WHERE "
01639 "context = :CONTEXT AND action = :ACTION AND "
01640 "hostname = :HOSTNAME ;");
01641 query.bindValue(":CONTEXT", context);
01642 query.bindValue(":ACTION", action);
01643 query.bindValue(":HOSTNAME", GetMythDB()->GetHostName());
01644
01645 if (query.exec() && query.next())
01646 {
01647 keybind = query.value(0).toString();
01648 QString db_description = query.value(1).toString();
01649
01650
01651 if (db_description != description)
01652 {
01653 LOG(VB_GENERAL, LOG_NOTICE,
01654 "Updating keybinding description...");
01655 query.prepare(
01656 "UPDATE keybindings "
01657 "SET description = :DESCRIPTION "
01658 "WHERE context = :CONTEXT AND "
01659 " action = :ACTION AND "
01660 " hostname = :HOSTNAME");
01661
01662 query.bindValue(":DESCRIPTION", description);
01663 query.bindValue(":CONTEXT", context);
01664 query.bindValue(":ACTION", action);
01665 query.bindValue(":HOSTNAME", GetMythDB()->GetHostName());
01666
01667 if (!query.exec() && !(GetMythDB()->SuppressDBMessages()))
01668 {
01669 MythDB::DBError("Update Keybinding", query);
01670 }
01671 }
01672 }
01673 else
01674 {
01675 QString inskey = keybind;
01676
01677 query.prepare("INSERT INTO keybindings (context, action, "
01678 "description, keylist, hostname) VALUES "
01679 "( :CONTEXT, :ACTION, :DESCRIPTION, :KEYLIST, "
01680 ":HOSTNAME );");
01681 query.bindValue(":CONTEXT", context);
01682 query.bindValue(":ACTION", action);
01683 query.bindValue(":DESCRIPTION", description);
01684 query.bindValue(":KEYLIST", inskey);
01685 query.bindValue(":HOSTNAME", GetMythDB()->GetHostName());
01686
01687 if (!query.exec() && !(GetMythDB()->SuppressDBMessages()))
01688 {
01689 MythDB::DBError("Insert Keybinding", query);
01690 }
01691 }
01692 }
01693
01694 BindKey(context, action, keybind);
01695 }
01696
01697 QString MythMainWindow::GetKey(const QString &context,
01698 const QString &action) const
01699 {
01700 MSqlQuery query(MSqlQuery::InitCon());
01701 if (!query.isConnected())
01702 return "?";
01703
01704 query.prepare("SELECT keylist "
01705 "FROM keybindings "
01706 "WHERE context = :CONTEXT AND "
01707 " action = :ACTION AND "
01708 " hostname = :HOSTNAME");
01709 query.bindValue(":CONTEXT", context);
01710 query.bindValue(":ACTION", action);
01711 query.bindValue(":HOSTNAME", GetMythDB()->GetHostName());
01712
01713 if (!query.exec() || !query.isActive() || !query.next())
01714 return "?";
01715
01716 return query.value(0).toString();
01717 }
01718
01719 void MythMainWindow::ClearJump(const QString &destination)
01720 {
01721
01722 if (d->destinationMap.find(destination) == d->destinationMap.end())
01723 {
01724 LOG(VB_GENERAL, LOG_ERR,
01725 "Cannot clear ficticious jump point" + destination);
01726 return;
01727 }
01728
01729 QMutableMapIterator<int, JumpData*> it(d->jumpMap);
01730 while (it.hasNext())
01731 {
01732 it.next();
01733 JumpData *jd = it.value();
01734 if (jd->destination == destination)
01735 it.remove();
01736 }
01737 }
01738
01739
01740 void MythMainWindow::BindJump(const QString &destination, const QString &key)
01741 {
01742
01743 if (d->destinationMap.find(destination) == d->destinationMap.end())
01744 {
01745 LOG(VB_GENERAL, LOG_ERR,
01746 "Cannot bind to ficticious jump point" + destination);
01747 return;
01748 }
01749
01750 QKeySequence keyseq(key);
01751
01752 for (unsigned int i = 0; i < keyseq.count(); i++)
01753 {
01754 int keynum = keyseq[i];
01755 keynum &= ~Qt::UNICODE_ACCEL;
01756
01757 if (d->jumpMap.count(keynum) == 0)
01758 {
01759 #if 0
01760 LOG(VB_GENERAL, LOG_DEBUG, QString("Binding: %1 to JumpPoint: %2")
01761 .arg(keybind).arg(destination));
01762 #endif
01763
01764 d->jumpMap[keynum] = &d->destinationMap[destination];
01765 }
01766 else
01767 {
01768 LOG(VB_GENERAL, LOG_WARNING,
01769 QString("Key %1 is already bound to a jump point.").arg(key));
01770 }
01771 }
01772 #if 0
01773 else
01774 LOG(VB_GENERAL, LOG_DEBUG,
01775 QString("JumpPoint: %2 exists, no keybinding") .arg(destination));
01776 #endif
01777 }
01778
01779 void MythMainWindow::RegisterJump(const QString &destination,
01780 const QString &description,
01781 const QString &key, void (*callback)(void),
01782 bool exittomain, QString localAction)
01783 {
01784 QString keybind = key;
01785
01786 MSqlQuery query(MSqlQuery::InitCon());
01787 if (query.isConnected())
01788 {
01789 query.prepare("SELECT keylist FROM jumppoints WHERE "
01790 "destination = :DEST and hostname = :HOST ;");
01791 query.bindValue(":DEST", destination);
01792 query.bindValue(":HOST", GetMythDB()->GetHostName());
01793
01794 if (query.exec() && query.next())
01795 {
01796 keybind = query.value(0).toString();
01797 }
01798 else
01799 {
01800 QString inskey = keybind;
01801
01802 query.prepare("INSERT INTO jumppoints (destination, description, "
01803 "keylist, hostname) VALUES ( :DEST, :DESC, :KEYLIST, "
01804 ":HOST );");
01805 query.bindValue(":DEST", destination);
01806 query.bindValue(":DESC", description);
01807 query.bindValue(":KEYLIST", inskey);
01808 query.bindValue(":HOST", GetMythDB()->GetHostName());
01809
01810 if (!query.exec() || !query.isActive())
01811 {
01812 MythDB::DBError("Insert Jump Point", query);
01813 }
01814 }
01815 }
01816
01817 JumpData jd =
01818 { callback, destination, description, exittomain, localAction };
01819 d->destinationMap[destination] = jd;
01820
01821 BindJump(destination, keybind);
01822 }
01823
01824 void MythMainWindow::ClearAllJumps()
01825 {
01826 QList<QString> destinations = d->destinationMap.keys();
01827 QList<QString>::Iterator it;
01828 for (it = destinations.begin(); it != destinations.end(); ++it)
01829 ClearJump(*it);
01830 }
01831
01832 void MythMainWindow::JumpTo(const QString& destination, bool pop)
01833 {
01834 if (d->destinationMap.count(destination) > 0 && d->exitmenucallback == NULL)
01835 {
01836 d->exitingtomain = true;
01837 d->popwindows = pop;
01838 d->exitmenucallback = d->destinationMap[destination].callback;
01839 QCoreApplication::postEvent(
01840 this, new QEvent(MythEvent::kExitToMainMenuEventType));
01841 return;
01842 }
01843 }
01844
01845 bool MythMainWindow::DestinationExists(const QString& destination) const
01846 {
01847 return (d->destinationMap.count(destination) > 0) ? true : false;
01848 }
01849
01850 QStringList MythMainWindow::EnumerateDestinations(void) const
01851 {
01852 return d->destinationMap.keys();
01853 }
01854
01855 void MythMainWindow::RegisterMediaPlugin(const QString &name,
01856 const QString &desc,
01857 MediaPlayCallback fn)
01858 {
01859 if (d->mediaPluginMap.count(name) == 0)
01860 {
01861 LOG(VB_GENERAL, LOG_NOTICE,
01862 QString("Registering %1 as a media playback plugin.").arg(name));
01863 MPData mpd = {desc, fn};
01864 d->mediaPluginMap[name] = mpd;
01865 }
01866 else
01867 {
01868 LOG(VB_GENERAL, LOG_NOTICE,
01869 QString("%1 is already registered as a media playback plugin.")
01870 .arg(name));
01871 }
01872 }
01873
01874 bool MythMainWindow::HandleMedia(const QString &handler, const QString &mrl,
01875 const QString &plot, const QString &title,
01876 const QString &subtitle,
01877 const QString &director, int season,
01878 int episode, const QString &inetref,
01879 int lenMins, const QString &year,
01880 const QString &id, bool useBookmarks)
01881 {
01882 QString lhandler(handler);
01883 if (lhandler.isEmpty())
01884 lhandler = "Internal";
01885
01886
01887 if (d->mediaPluginMap.count(lhandler))
01888 {
01889 d->mediaPluginMap[lhandler].playFn(mrl, plot, title, subtitle,
01890 director, season, episode,
01891 inetref, lenMins, year, id,
01892 useBookmarks);
01893 return true;
01894 }
01895
01896 return false;
01897 }
01898
01899 void MythMainWindow::HandleTVPower(bool poweron)
01900 {
01901 #ifdef USING_LIBCEC
01902 if (d->cecAdapter)
01903 d->cecAdapter->Action((poweron) ? ACTION_TVPOWERON : ACTION_TVPOWEROFF);
01904 #else
01905 (void) poweron;
01906 #endif
01907 }
01908
01909 void MythMainWindow::AllowInput(bool allow)
01910 {
01911 d->AllowInput = allow;
01912 }
01913
01914 void MythMainWindow::mouseTimeout(void)
01915 {
01916 MythGestureEvent *e;
01917
01918
01919 if (d->gesture.recording())
01920 {
01921 d->gesture.stop();
01922 }
01923
01924
01925 e = d->gesture.gesture();
01926
01927 if (e->gesture() < MythGestureEvent::Click)
01928 QCoreApplication::postEvent(this, e);
01929 }
01930
01931 bool MythMainWindow::eventFilter(QObject *, QEvent *e)
01932 {
01933 MythGestureEvent *ge;
01934
01935
01936 if (!d->AllowInput)
01937 return true;
01938
01939 switch (e->type())
01940 {
01941 case QEvent::KeyPress:
01942 {
01943 ResetIdleTimer();
01944 QKeyEvent *ke = dynamic_cast<QKeyEvent*>(e);
01945
01946
01947 if (!ke)
01948 ke = static_cast<QKeyEvent *>(e);
01949
01950 if (currentWidget())
01951 {
01952 ke->accept();
01953 QWidget *current = currentWidget();
01954 if (current && current->isEnabled())
01955 qApp->notify(current, ke);
01956
01957 break;
01958 }
01959
01960 QVector<MythScreenStack *>::Iterator it;
01961 for (it = d->stackList.end()-1; it != d->stackList.begin()-1; --it)
01962 {
01963 MythScreenType *top = (*it)->GetTopScreen();
01964 if (top)
01965 {
01966 if (top->keyPressEvent(ke))
01967 return true;
01968
01969
01970
01971 if ((*it)->objectName() == "popup stack")
01972 break;
01973 }
01974 }
01975 break;
01976 }
01977 case QEvent::MouseButtonPress:
01978 {
01979 ResetIdleTimer();
01980 ShowMouseCursor(true);
01981 if (!d->gesture.recording())
01982 {
01983 d->gesture.start();
01984 d->gesture.record(dynamic_cast<QMouseEvent*>(e)->pos());
01985
01986
01987 d->gestureTimer->start(GESTURE_TIMEOUT);
01988
01989 return true;
01990 }
01991 break;
01992 }
01993 case QEvent::MouseButtonRelease:
01994 {
01995 ResetIdleTimer();
01996 ShowMouseCursor(true);
01997 if (d->gestureTimer->isActive())
01998 d->gestureTimer->stop();
01999
02000 if (currentWidget())
02001 break;
02002
02003 if (d->gesture.recording())
02004 {
02005 d->gesture.stop();
02006 ge = d->gesture.gesture();
02007
02008
02009 if (ge->gesture() == MythGestureEvent::Click)
02010 {
02011 QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(e);
02012 if (!mouseEvent)
02013 return false;
02014
02015 QVector<MythScreenStack *>::iterator it;
02016 QPoint p = mouseEvent->pos();
02017
02018 ge->SetPosition(p);
02019
02020 MythGestureEvent::Button button = MythGestureEvent::NoButton;
02021 switch (mouseEvent->button())
02022 {
02023 case Qt::LeftButton :
02024 button = MythGestureEvent::LeftButton;
02025 break;
02026 case Qt::RightButton :
02027 button = MythGestureEvent::RightButton;
02028 break;
02029 case Qt::MidButton :
02030 button = MythGestureEvent::MiddleButton;
02031 break;
02032 case Qt::XButton1 :
02033 button = MythGestureEvent::Aux1Button;
02034 break;
02035 case Qt::XButton2 :
02036 button = MythGestureEvent::Aux2Button;
02037 break;
02038 default :
02039 button = MythGestureEvent::NoButton;
02040 }
02041
02042 ge->SetButton(button);
02043
02044 for (it = d->stackList.end()-1; it != d->stackList.begin()-1;
02045 --it)
02046 {
02047 MythScreenType *screen = (*it)->GetTopScreen();
02048
02049 if (!screen || !screen->ContainsPoint(p))
02050 continue;
02051
02052 if (screen->gestureEvent(ge))
02053 break;
02054
02055
02056
02057
02058
02059
02060
02061
02062 if ((*it)->objectName() == "popup stack")
02063 break;
02064 }
02065
02066 delete ge;
02067 }
02068 else
02069 QCoreApplication::postEvent(this, ge);
02070
02071 return true;
02072 }
02073 break;
02074 }
02075 case QEvent::MouseMove:
02076 {
02077 ResetIdleTimer();
02078 ShowMouseCursor(true);
02079 if (d->gesture.recording())
02080 {
02081
02082 d->gestureTimer->stop();
02083 d->gestureTimer->start(GESTURE_TIMEOUT);
02084
02085 d->gesture.record(static_cast<QMouseEvent*>(e)->pos());
02086 return true;
02087 }
02088 break;
02089 }
02090 case QEvent::Wheel:
02091 {
02092 ResetIdleTimer();
02093 ShowMouseCursor(true);
02094 QWheelEvent* qmw = static_cast<QWheelEvent*>(e);
02095 int delta = qmw->delta();
02096 if (delta>0)
02097 {
02098 qmw->accept();
02099 QKeyEvent *key = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up,
02100 Qt::NoModifier);
02101 QObject *key_target = getTarget(*key);
02102 if (!key_target)
02103 QCoreApplication::postEvent(this, key);
02104 else
02105 QCoreApplication::postEvent(key_target, key);
02106 }
02107 if (delta<0)
02108 {
02109 qmw->accept();
02110 QKeyEvent *key = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down,
02111 Qt::NoModifier);
02112 QObject *key_target = getTarget(*key);
02113 if (!key_target)
02114 QCoreApplication::postEvent(this, key);
02115 else
02116 QCoreApplication::postEvent(key_target, key);
02117 }
02118 break;
02119 }
02120 default:
02121 break;
02122 }
02123
02124 return false;
02125 }
02126
02127 void MythMainWindow::customEvent(QEvent *ce)
02128 {
02129 if (ce->type() == MythGestureEvent::kEventType)
02130 {
02131 MythGestureEvent *ge = static_cast<MythGestureEvent*>(ce);
02132 MythScreenStack *toplevel = GetMainStack();
02133 if (toplevel && !currentWidget())
02134 {
02135 MythScreenType *screen = toplevel->GetTopScreen();
02136 if (screen)
02137 screen->gestureEvent(ge);
02138 }
02139 LOG(VB_GUI, LOG_DEBUG, QString("Gesture: %1") .arg(QString(*ge)));
02140 }
02141 else if (ce->type() == MythEvent::kExitToMainMenuEventType &&
02142 d->exitingtomain)
02143 {
02144 ExitToMainMenu();
02145 }
02146 else if (ce->type() == ExternalKeycodeEvent::kEventType)
02147 {
02148 ExternalKeycodeEvent *eke = static_cast<ExternalKeycodeEvent *>(ce);
02149 int keycode = eke->getKeycode();
02150
02151 QKeyEvent key(QEvent::KeyPress, keycode, Qt::NoModifier);
02152
02153 QObject *key_target = getTarget(key);
02154 if (!key_target)
02155 QCoreApplication::sendEvent(this, &key);
02156 else
02157 QCoreApplication::sendEvent(key_target, &key);
02158 }
02159 #if defined(USE_LIRC) || defined(USING_APPLEREMOTE)
02160 else if (ce->type() == LircKeycodeEvent::kEventType &&
02161 !d->ignore_lirc_keys)
02162 {
02163 LircKeycodeEvent *lke = static_cast<LircKeycodeEvent *>(ce);
02164
02165 if (LircKeycodeEvent::kLIRCInvalidKeyCombo == lke->modifiers())
02166 {
02167 LOG(VB_GENERAL, LOG_WARNING,
02168 QString("Attempt to convert LIRC key sequence '%1' "
02169 "to a Qt key sequence failed.")
02170 .arg(lke->lirctext()));
02171 }
02172 else
02173 {
02174 GetMythUI()->ResetScreensaver();
02175 if (GetMythUI()->GetScreenIsAsleep())
02176 return;
02177
02178 QKeyEvent key(lke->keytype(), lke->key(),
02179 lke->modifiers(), lke->text());
02180
02181 QObject *key_target = getTarget(key);
02182 if (!key_target)
02183 QCoreApplication::sendEvent(this, &key);
02184 else
02185 QCoreApplication::sendEvent(key_target, &key);
02186 }
02187 }
02188 #endif
02189 #ifdef USE_JOYSTICK_MENU
02190 else if (ce->type() == JoystickKeycodeEvent::kEventType &&
02191 !d->ignore_joystick_keys)
02192 {
02193 JoystickKeycodeEvent *jke = static_cast<JoystickKeycodeEvent *>(ce);
02194 int keycode = jke->getKeycode();
02195
02196 if (keycode)
02197 {
02198 GetMythUI()->ResetScreensaver();
02199 if (GetMythUI()->GetScreenIsAsleep())
02200 return;
02201
02202 Qt::KeyboardModifiers mod = Qt::KeyboardModifiers(keycode & Qt::MODIFIER_MASK);
02203 int k = (keycode & ~Qt::MODIFIER_MASK);
02204 QString text;
02205
02206 if (k & Qt::UNICODE_ACCEL)
02207 {
02208 QChar c(k & ~Qt::UNICODE_ACCEL);
02209 text = QString(c);
02210 }
02211
02212 QKeyEvent key(jke->isKeyDown() ? QEvent::KeyPress :
02213 QEvent::KeyRelease, k, mod, text);
02214
02215 QObject *key_target = getTarget(key);
02216 if (!key_target)
02217 QCoreApplication::sendEvent(this, &key);
02218 else
02219 QCoreApplication::sendEvent(key_target, &key);
02220 }
02221 else
02222 {
02223 LOG(VB_GENERAL, LOG_WARNING,
02224 QString("attempt to convert '%1' to a key sequence failed. "
02225 "Fix your key mappings.")
02226 .arg(jke->getJoystickMenuText()));
02227 }
02228 }
02229 #endif
02230 else if (ce->type() == MythMediaEvent::kEventType)
02231 {
02232 MythMediaEvent *me = static_cast<MythMediaEvent*>(ce);
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247 QVector<MythScreenStack *>::Iterator it;
02248 for (it = d->stackList.begin(); it != d->stackList.end(); ++it)
02249 {
02250 QVector<MythScreenType *> screenList;
02251 (*it)->GetScreenList(screenList);
02252 QVector<MythScreenType *>::Iterator sit;
02253 for (sit = screenList.begin(); sit != screenList.end(); ++sit)
02254 {
02255 MythScreenType *screen = (*sit);
02256 if (screen)
02257 screen->mediaEvent(me);
02258 }
02259 }
02260
02261
02262 MythMediaDevice *device = me->getDevice();
02263 if (device)
02264 {
02265 LOG(VB_GENERAL, LOG_DEBUG, QString("Media Event: %1 - %2")
02266 .arg(device->getDevicePath()).arg(device->getStatus()));
02267 }
02268 }
02269 else if (ce->type() == ScreenSaverEvent::kEventType)
02270 {
02271 ScreenSaverEvent *sse = static_cast<ScreenSaverEvent *>(ce);
02272 switch (sse->getSSEventType())
02273 {
02274 case ScreenSaverEvent::ssetDisable:
02275 {
02276 GetMythUI()->DoDisableScreensaver();
02277 break;
02278 }
02279 case ScreenSaverEvent::ssetRestore:
02280 {
02281 GetMythUI()->DoRestoreScreensaver();
02282 break;
02283 }
02284 case ScreenSaverEvent::ssetReset:
02285 {
02286 GetMythUI()->DoResetScreensaver();
02287 break;
02288 }
02289 default:
02290 {
02291 LOG(VB_GENERAL, LOG_ERR,
02292 QString("Unknown ScreenSaverEvent type: %1")
02293 .arg(sse->getSSEventType()));
02294 }
02295 }
02296 }
02297 else if (ce->type() == MythEvent::kPushDisableDrawingEventType)
02298 {
02299 PushDrawDisabled();
02300 }
02301 else if (ce->type() == MythEvent::kPopDisableDrawingEventType)
02302 {
02303 PopDrawDisabled();
02304 }
02305 else if (ce->type() == MythEvent::kDisableDrawingEventType)
02306 {
02307 SetDrawEnabled(false);
02308 }
02309 else if (ce->type() == MythEvent::kEnableDrawingEventType)
02310 {
02311 SetDrawEnabled(true);
02312 }
02313 else if (ce->type() == MythEvent::kLockInputDevicesEventType)
02314 {
02315 LockInputDevices(true);
02316 }
02317 else if (ce->type() == MythEvent::kUnlockInputDevicesEventType)
02318 {
02319 LockInputDevices(false);
02320 }
02321 else if ((MythEvent::Type)(ce->type()) == MythEvent::MythEventMessage)
02322 {
02323 MythEvent *me = (MythEvent *)ce;
02324 QString message = me->Message();
02325
02326 if (message.startsWith(ACTION_HANDLEMEDIA))
02327 {
02328 if (me->ExtraDataCount() == 1)
02329 HandleMedia("Internal", me->ExtraData(0));
02330 else if (me->ExtraDataCount() >= 11)
02331 {
02332 bool usebookmark = true;
02333 if (me->ExtraDataCount() >= 12)
02334 usebookmark = me->ExtraData(11).toInt();
02335 HandleMedia("Internal", me->ExtraData(0),
02336 me->ExtraData(1), me->ExtraData(2),
02337 me->ExtraData(3), me->ExtraData(4),
02338 me->ExtraData(5).toInt(), me->ExtraData(6).toInt(),
02339 me->ExtraData(7), me->ExtraData(8).toInt(),
02340 me->ExtraData(9), me->ExtraData(10),
02341 usebookmark);
02342 }
02343 else
02344 LOG(VB_GENERAL, LOG_ERR, "Failed to handle media");
02345 }
02346 else if (message.startsWith(ACTION_SCREENSHOT))
02347 {
02348 int width = 0;
02349 int height = 0;
02350 QString filename;
02351
02352 if (me->ExtraDataCount() >= 2)
02353 {
02354 width = me->ExtraData(0).toInt();
02355 height = me->ExtraData(1).toInt();
02356
02357 if (me->ExtraDataCount() == 3)
02358 filename = me->ExtraData(2);
02359 }
02360 ScreenShot(width, height, filename);
02361 }
02362 else if (message == ACTION_GETSTATUS)
02363 {
02364 QVariantMap state;
02365 state.insert("state", "idle");
02366 state.insert("menutheme",
02367 GetMythDB()->GetSetting("menutheme", "defaultmenu"));
02368 state.insert("currentlocation", GetMythUI()->GetCurrentLocation());
02369 MythUIStateTracker::SetState(state);
02370 }
02371 }
02372 else if ((MythEvent::Type)(ce->type()) == MythEvent::MythUserMessage)
02373 {
02374 MythEvent *me = (MythEvent *)ce;
02375 QString message = me->Message();
02376
02377 if (!message.isEmpty())
02378 ShowOkPopup(message);
02379 }
02380 }
02381
02382 QObject *MythMainWindow::getTarget(QKeyEvent &key)
02383 {
02384 QObject *key_target = NULL;
02385
02386 if (!currentWidget())
02387 return key_target;
02388
02389 key_target = QWidget::keyboardGrabber();
02390
02391 if (!key_target)
02392 {
02393 QWidget *focus_widget = qApp->focusWidget();
02394 if (focus_widget && focus_widget->isEnabled())
02395 {
02396 key_target = focus_widget;
02397
02398
02399
02400 if (key.key() == d->escapekey && focus_widget->topLevelWidget())
02401 key_target = focus_widget->topLevelWidget();
02402 }
02403 }
02404
02405 if (!key_target)
02406 key_target = this;
02407
02408 return key_target;
02409 }
02410
02411 int MythMainWindow::NormalizeFontSize(int pointSize)
02412 {
02413 float floatSize = pointSize;
02414 float desired = 100.0;
02415
02416 #ifdef USING_MINGW
02417
02418 int logicalDpiY = 100;
02419 HDC hdc = GetDC(NULL);
02420 if (hdc)
02421 {
02422 logicalDpiY = GetDeviceCaps(hdc, LOGPIXELSY);
02423 ReleaseDC(NULL, hdc);
02424 }
02425 #else
02426 int logicalDpiY = this->logicalDpiY();
02427 #endif
02428
02429
02430 floatSize = floatSize * desired / logicalDpiY;
02431
02432 floatSize = floatSize * d->hmult;
02433
02434 pointSize = (int)(floatSize + 0.5);
02435
02436 return pointSize;
02437 }
02438
02439 MythRect MythMainWindow::NormRect(const MythRect &rect)
02440 {
02441 MythRect ret;
02442 ret.setWidth((int)(rect.width() * d->wmult));
02443 ret.setHeight((int)(rect.height() * d->hmult));
02444 ret.moveTopLeft(QPoint((int)(rect.x() * d->wmult),
02445 (int)(rect.y() * d->hmult)));
02446 ret = ret.normalized();
02447
02448 return ret;
02449 }
02450
02451 QPoint MythMainWindow::NormPoint(const QPoint &point)
02452 {
02453 QPoint ret;
02454 ret.setX((int)(point.x() * d->wmult));
02455 ret.setY((int)(point.y() * d->hmult));
02456
02457 return ret;
02458 }
02459
02460 QSize MythMainWindow::NormSize(const QSize &size)
02461 {
02462 QSize ret;
02463 ret.setWidth((int)(size.width() * d->wmult));
02464 ret.setHeight((int)(size.height() * d->hmult));
02465
02466 return ret;
02467 }
02468
02469 int MythMainWindow::NormX(const int x)
02470 {
02471 return (int)(x * d->wmult);
02472 }
02473
02474 int MythMainWindow::NormY(const int y)
02475 {
02476 return (int)(y * d->hmult);
02477 }
02478
02479 void MythMainWindow::SetScalingFactors(float wmult, float hmult)
02480 {
02481 d->wmult = wmult;
02482 d->hmult = hmult;
02483 }
02484
02485 QRect MythMainWindow::GetUIScreenRect(void)
02486 {
02487 return d->uiScreenRect;
02488 }
02489
02490 void MythMainWindow::SetUIScreenRect(QRect &rect)
02491 {
02492 d->uiScreenRect = rect;
02493 }
02494
02495 int MythMainWindow::GetDrawInterval() const
02496 {
02497 return d->drawInterval;
02498 }
02499
02500 void MythMainWindow::StartLIRC(void)
02501 {
02502 #ifdef USE_LIRC
02503 if (d->lircThread)
02504 {
02505 d->lircThread->deleteLater();
02506 d->lircThread = NULL;
02507 }
02508
02509 QString config_file = GetConfDir() + "/lircrc";
02510 if (!QFile::exists(config_file))
02511 config_file = QDir::homePath() + "/.lircrc";
02512
02513
02514 QString lirc_socket = "/dev/lircd";
02515 if (!QFile::exists(lirc_socket))
02516 lirc_socket = "/var/run/lirc/lircd";
02517
02518 d->lircThread = new LIRC(
02519 this,
02520 GetMythDB()->GetSetting("LircSocket", lirc_socket),
02521 "mythtv", config_file);
02522
02523 if (d->lircThread->Init())
02524 {
02525 d->lircThread->start();
02526 }
02527 else
02528 {
02529 d->lircThread->deleteLater();
02530 d->lircThread = NULL;
02531 }
02532 #endif
02533 }
02534
02535 void MythMainWindow::LockInputDevices( bool locked )
02536 {
02537 if( locked )
02538 LOG(VB_GENERAL, LOG_INFO, "Locking input devices");
02539 else
02540 LOG(VB_GENERAL, LOG_INFO, "Unlocking input devices");
02541
02542 #ifdef USE_LIRC
02543 d->ignore_lirc_keys = locked;
02544 #endif
02545
02546 #ifdef USE_JOYSTICK_MENU
02547 d->ignore_joystick_keys = locked;
02548 #endif
02549 }
02550
02551 void MythMainWindow::ShowMouseCursor(bool show)
02552 {
02553 if (show && GetMythDB()->GetNumSetting("HideMouseCursor", 0))
02554 return;
02555 #ifdef QWS
02556 QWSServer::setCursorVisible(show);
02557 #endif
02558
02559 setCursor(show ? (Qt::ArrowCursor) : (Qt::BlankCursor));
02560
02561 if (show)
02562 d->hideMouseTimer->start();
02563 }
02564
02565 void MythMainWindow::HideMouseTimeout(void)
02566 {
02567 ShowMouseCursor(false);
02568 }
02569
02570 void MythMainWindow::ResetIdleTimer(void)
02571 {
02572 if (!d->idleTimer->isActive() ||
02573 (d->standby && d->enteringStandby))
02574 return;
02575
02576 if (d->standby)
02577 ExitStandby(false);
02578
02579 d->idleTimer->start();
02580 }
02581
02582 void MythMainWindow::PauseIdleTimer(bool pause)
02583 {
02584 if (pause)
02585 {
02586 LOG(VB_GENERAL, LOG_NOTICE, "Suspending idle timer");
02587 d->idleTimer->stop();
02588 }
02589 else
02590 {
02591 LOG(VB_GENERAL, LOG_NOTICE, "Resuming idle timer");
02592 d->idleTimer->start();
02593 }
02594
02595
02596 }
02597
02598 void MythMainWindow::IdleTimeout(void)
02599 {
02600 d->enteringStandby = false;
02601
02602 int idletimeout = gCoreContext->GetNumSetting("FrontendIdleTimeout",
02603 STANDBY_TIMEOUT);
02604
02605 if (idletimeout > 0 && !d->standby)
02606 {
02607 LOG(VB_GENERAL, LOG_NOTICE, QString("Entering standby mode after "
02608 "%1 minutes of inactivity")
02609 .arg(idletimeout));
02610 EnterStandby(false);
02611 if (gCoreContext->GetNumSetting("idleTimeoutSecs", 0))
02612 {
02613 d->enteringStandby = true;
02614 JumpTo("Standby Mode");
02615 }
02616 }
02617 }
02618
02619 void MythMainWindow::EnterStandby(bool manual)
02620 {
02621 if (manual && d->enteringStandby)
02622 d->enteringStandby = false;
02623
02624 if (d->standby)
02625 return;
02626
02627
02628
02629 if (manual)
02630 {
02631 PauseIdleTimer(true);
02632 LOG(VB_GENERAL, LOG_NOTICE, QString("Entering standby mode"));
02633 }
02634
02635 d->standby = true;
02636 gCoreContext->AllowShutdown();
02637 }
02638
02639 void MythMainWindow::ExitStandby(bool manual)
02640 {
02641 if (d->enteringStandby)
02642 return;
02643
02644 if (manual)
02645 PauseIdleTimer(false);
02646 else if (gCoreContext->GetNumSetting("idleTimeoutSecs", 0))
02647 JumpTo("Main Menu");
02648
02649 if (!d->standby)
02650 return;
02651
02652 LOG(VB_GENERAL, LOG_NOTICE, "Leaving standby mode");
02653
02654 d->standby = false;
02655 gCoreContext->BlockShutdown();
02656 }
02657
02658
02659