File indexing completed on 2024-04-21 05:54:05

0001 /*
0002     SPDX-FileCopyrightText: 2005-2006, 2009-2010 Tom Albers <toma@kde.org>
0003     SPDX-FileCopyrightText: 2006 Bram Schoenmakers <bramschoenmakers@kde.nl>
0004     SPDX-FileCopyrightText: 2010 Juan Luis Baptiste <juan.baptiste@gmail.com>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #include "rsiwidget.h"
0010 #include "grayeffect.h"
0011 #include "plasmaeffect.h"
0012 #include "popupeffect.h"
0013 #include "rsidock.h"
0014 #include "rsiglobals.h"
0015 #include "rsirelaxpopup.h"
0016 #include "rsitimer.h"
0017 #include "rsiwidgetadaptor.h"
0018 #include "slideshoweffect.h"
0019 
0020 #include <QDebug>
0021 #include <QDesktopWidget>
0022 #include <QPainter>
0023 #include <QTimer>
0024 
0025 #include <KConfigGroup>
0026 #include <KLocalizedString>
0027 #include <KMessageBox>
0028 #include <KNotification>
0029 #include <KSharedConfig>
0030 #include <QDBusInterface>
0031 #include <QTemporaryFile>
0032 
0033 #include <KFormat>
0034 #include <math.h>
0035 #include <time.h>
0036 
0037 RSIObject::RSIObject(QWidget *parent)
0038     : QObject(parent)
0039     , m_timer(nullptr)
0040     , m_effect(nullptr)
0041     , m_useImages(false)
0042     , m_usePlasma(false)
0043     , m_usePlasmaRO(false)
0044 {
0045     // Keep these 2 lines _above_ the messagebox, so the text actually is right.
0046     m_tray = new RSIDock(this);
0047     m_tray->setIconByName("rsibreak0");
0048 
0049     new RsiwidgetAdaptor(this);
0050     QDBusConnection dbus = QDBusConnection::sessionBus();
0051     dbus.registerObject("/rsibreak", this);
0052 
0053     m_relaxpopup = new RSIRelaxPopup(nullptr);
0054     connect(m_relaxpopup, &RSIRelaxPopup::lock, this, &RSIObject::slotLock);
0055 
0056     connect(m_tray, &RSIDock::configChanged, RSIGlobals::instance(), &RSIGlobals::slotReadConfig);
0057     connect(m_tray, &RSIDock::configChanged, this, &RSIObject::readConfig);
0058     connect(m_tray, &RSIDock::configChanged, m_relaxpopup, &RSIRelaxPopup::slotReadConfig);
0059     connect(m_tray, &RSIDock::suspend, m_relaxpopup, &RSIRelaxPopup::setSuspended);
0060 
0061     readConfig();
0062 
0063     setIcon(0);
0064 
0065     QTimer::singleShot(2000, this, &RSIObject::slotWelcome);
0066 }
0067 
0068 RSIObject::~RSIObject()
0069 {
0070     delete m_effect;
0071     delete RSIGlobals::instance();
0072     delete m_timer;
0073 }
0074 
0075 void RSIObject::slotWelcome()
0076 {
0077     if (KMessageBox::shouldBeShownContinue("dont_show_welcome_again_for_001")) {
0078         KMessageBox::information(nullptr,
0079                                  i18n("<p>Welcome to RSIBreak</p>\n<p>"
0080                                       "In your tray you can now see RSIBreak.</p>\n")
0081                                      + i18n("<p>When you right-click on that you will see a menu, from which "
0082                                             "you can go to the configuration for example.</p>\n<p>When you want to "
0083                                             "know when the next break is, hover over the icon.</p>\n<p>Use RSIBreak "
0084                                             "wisely.</p>"),
0085                                  i18n("Welcome"),
0086                                  "dont_show_welcome_again_for_001");
0087     }
0088 }
0089 
0090 void RSIObject::minimize()
0091 {
0092     m_effect->deactivate();
0093 }
0094 
0095 void RSIObject::maximize()
0096 {
0097     m_effect->activate();
0098 }
0099 
0100 void RSIObject::slotLock()
0101 {
0102     m_effect->deactivate();
0103     m_timer->slotLock();
0104 
0105     QDBusInterface lock("org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver");
0106     lock.call("Lock");
0107 }
0108 
0109 void RSIObject::setCounters(int timeleft)
0110 {
0111     if (timeleft > 0) {
0112         m_effect->setLabel(KFormat().formatSpelloutDuration(timeleft * 1000));
0113     } else if (m_timer->isSuspended()) {
0114         m_effect->setLabel(i18n("Suspended"));
0115     } else {
0116         m_effect->setLabel(QString());
0117     }
0118 }
0119 
0120 void RSIObject::updateIdleAvg(double idleAvg)
0121 {
0122     if (idleAvg == 0.0)
0123         setIcon(0);
0124     else if (idleAvg > 0 && idleAvg < 30)
0125         setIcon(1);
0126     else if (idleAvg >= 30 && idleAvg < 60)
0127         setIcon(2);
0128     else if (idleAvg >= 60 && idleAvg < 90)
0129         setIcon(3);
0130     else
0131         setIcon(4);
0132 }
0133 
0134 void RSIObject::setIcon(int level)
0135 {
0136     QString newIcon = "rsibreak" + (m_timer->isSuspended() ? QString("x") : QString::number(level));
0137 
0138     if (newIcon != m_currentIcon) {
0139         m_tray->setIconByName(newIcon);
0140         m_tray->setToolTipIconByName(newIcon);
0141         m_currentIcon = newIcon;
0142     }
0143 }
0144 
0145 // ------------------- Popup for skipping break ------------- //
0146 
0147 void RSIObject::tinyBreakSkipped()
0148 {
0149     m_notificator.onShortTimerReset();
0150 }
0151 
0152 void RSIObject::bigBreakSkipped()
0153 {
0154     m_notificator.onTimersReset();
0155 }
0156 
0157 //--------------------------- CONFIG ----------------------------//
0158 
0159 void RSIObject::configureTimer()
0160 {
0161     if (m_timer != nullptr) {
0162         m_timer->updateConfig();
0163         return;
0164     }
0165     m_timer = new RSITimer(this);
0166 
0167     connect(m_timer, &RSITimer::breakNow, this, &RSIObject::maximize, Qt::QueuedConnection);
0168     connect(m_timer, &RSITimer::updateWidget, this, &RSIObject::setCounters, Qt::QueuedConnection);
0169     connect(m_timer, &RSITimer::updateToolTip, m_tray, &RSIDock::setCounters, Qt::QueuedConnection);
0170     connect(m_timer, &RSITimer::updateIdleAvg, this, &RSIObject::updateIdleAvg, Qt::QueuedConnection);
0171     connect(m_timer, &RSITimer::minimize, this, &RSIObject::minimize, Qt::QueuedConnection);
0172     connect(m_timer, &RSITimer::relax, m_relaxpopup, &RSIRelaxPopup::relax, Qt::QueuedConnection);
0173     connect(m_timer, &RSITimer::tinyBreakSkipped, this, &RSIObject::tinyBreakSkipped, Qt::QueuedConnection);
0174     connect(m_timer, &RSITimer::bigBreakSkipped, this, &RSIObject::bigBreakSkipped, Qt::QueuedConnection);
0175     connect(m_timer, &RSITimer::startLongBreak, &m_notificator, &Notificator::onStartLongBreak);
0176     connect(m_timer, &RSITimer::endLongBreak, &m_notificator, &Notificator::onEndLongBreak);
0177     connect(m_timer, &RSITimer::startShortBreak, &m_notificator, &Notificator::onStartShortBreak);
0178     connect(m_timer, &RSITimer::endShortBreak, &m_notificator, &Notificator::onEndShortBreak);
0179 
0180     connect(m_tray, &RSIDock::dialogEntered, m_timer, &RSITimer::slotStop);
0181     connect(m_tray, &RSIDock::dialogLeft, m_timer, &RSITimer::slotStart);
0182     connect(m_tray, &RSIDock::suspend, m_timer, &RSITimer::slotSuspended);
0183 
0184     connect(m_relaxpopup, &RSIRelaxPopup::skip, m_timer, &RSITimer::skipBreak);
0185     connect(m_relaxpopup, &RSIRelaxPopup::postpone, m_timer, &RSITimer::postponeBreak);
0186 }
0187 
0188 void RSIObject::readConfig()
0189 {
0190     KConfigGroup config = KSharedConfig::openConfig()->group("General Settings");
0191 
0192     m_relaxpopup->setSkipButtonHidden(config.readEntry("HideMinimizeButton", false));
0193     m_relaxpopup->setLockButtonHidden(config.readEntry("HideLockButton", false));
0194     m_relaxpopup->setPostponeButtonHidden(config.readEntry("HidePostponeButton", false));
0195 
0196     m_usePlasma = config.readEntry("UsePlasma", false);
0197     m_usePlasmaRO = config.readEntry("UsePlasmaReadOnly", false);
0198 
0199     m_useImages = config.readEntry("ShowImages", false);
0200     int slideInterval = config.readEntry("SlideInterval", 10);
0201     bool recursive = config.readEntry("SearchRecursiveCheck", false);
0202     bool showSmallImages = config.readEntry("ShowSmallImagesCheck", true);
0203     const bool expandImageToFullScreen = config.readEntry("ExpandImageToFullScreen", true);
0204     QString path = config.readEntry("ImageFolder");
0205 
0206     configureTimer();
0207 
0208     int effect = config.readEntry("Effect", 0);
0209 
0210     delete m_effect;
0211     switch (effect) {
0212     case Plasma: {
0213         m_effect = new PlasmaEffect(nullptr);
0214         m_effect->setReadOnly(m_usePlasmaRO);
0215         break;
0216     }
0217     case SlideShow: {
0218         SlideEffect *slide = new SlideEffect(nullptr);
0219         slide->reset(path, recursive, showSmallImages, expandImageToFullScreen, slideInterval);
0220         if (slide->hasImages())
0221             m_effect = slide;
0222         else {
0223             delete slide;
0224             m_effect = new GrayEffect(nullptr);
0225         }
0226         break;
0227     }
0228     case Popup: {
0229         PopupEffect *effect = new PopupEffect(nullptr);
0230         m_effect = effect;
0231         break;
0232     }
0233     case SimpleGray:
0234     default: {
0235         GrayEffect *effect = new GrayEffect(nullptr);
0236         effect->setLevel(config.readEntry("Graylevel", 80));
0237         m_effect = effect;
0238         break;
0239     }
0240     }
0241     connect(m_effect, &BreakBase::skip, m_timer, &RSITimer::skipBreak);
0242     connect(m_effect, &BreakBase::lock, this, &RSIObject::slotLock);
0243     connect(m_effect, &BreakBase::postpone, m_timer, &RSITimer::postponeBreak);
0244 
0245     m_effect->showMinimize(!config.readEntry("HideMinimizeButton", false));
0246     m_effect->showLock(!config.readEntry("HideLockButton", false));
0247     m_effect->showPostpone(!config.readEntry("HidePostponeButton", false));
0248     m_effect->disableShortcut(config.readEntry("DisableAccel", false));
0249 }
0250 
0251 void RSIObject::resume()
0252 {
0253     m_tray->doResume();
0254 }
0255 
0256 void RSIObject::suspend()
0257 {
0258     m_tray->doSuspend();
0259 }