theshell/shell/infopanedropdown.cpp
2019-03-23 19:20:07 +11:00

3646 lines
141 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/****************************************
*
* theShell - Desktop Environment
* Copyright (C) 2019 Victor Tran
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* *************************************/
#include "infopanedropdown.h"
#include "ui_infopanedropdown.h"
#include "internationalisation.h"
#include <QScroller>
#include <tvirtualkeyboard.h>
#include "location/locationdaemon.h"
#include <notificationsdbusadaptor.h>
#include "animatedstackedwidget.h"
#include "upowerdbus.h"
#include "endsessionwait.h"
#include "audiomanager.h"
#include "nativeeventfilter.h"
#include "dbussignals.h"
#include <QShortcut>
#include <QMenu>
#include <QAction>
#include "location/locationservices.h"
extern void playSound(QUrl, bool = false);
extern QIcon getIconFromTheme(QString name, QColor textColor);
extern void EndSession(EndSessionWait::shutdownType type);
extern QString calculateSize(quint64 size);
extern AudioManager* AudioMan;
extern NativeEventFilter* NativeFilter;
extern QTranslator *qtTranslator, *tsTranslator;
extern float getDPIScaling();
extern QDBusServiceWatcher* dbusServiceWatcher;
extern QDBusServiceWatcher* dbusServiceWatcherSystem;
extern UPowerDBus* updbus;
extern DBusSignals* dbusSignals;
extern LocationServices* locationServices;
extern LocationDaemon* geolocation;
extern bool startSafe;
#define LOWER_INFOPANE InfoPaneNotOnTopLocker locker(this);
class InfoPaneDropdownPrivate {
public:
InfoPaneDropdownPrivate(InfoPaneDropdown* parent) {
lockScreenSettings = new QSettings("theSuite", "tsscreenlock", parent);
themeSettings = new QSettings("theSuite", "ts-qtplatform", parent);
sessionSettings = new QSettings("theSuite", "ts-startsession", parent);
notificationAppSettings = new QSettings("theSuite", "theShell-notifications", parent);
gtk3Settings = new QSettings(QDir::homePath() + "/.config/gtk-3.0/settings.ini", QSettings::IniFormat, parent);
locationSettings = new QSettings("theSuite", "theShell-location", parent);
}
bool isRedshiftOn = false;
bool isNewRedshift = true;
int mouseClickPoint;
int initialPoint;
bool mouseMovedUp = false;
QRect dragRect;
bool effectiveRedshiftOn = false;
bool draggingInfoPane = false;
int overrideRedshift = 0;
QMap<QString, QFrame*> printersFrames;
QMap<QString, QLabel*> printersStats;
QMap<QString, QFrame*> printersStatFrames;
QMap<QString, QString> connectedNetworks;
QMap<QWidget*, StatusCenterPaneObject*> pluginObjects;
QMap<StatusCenterPaneObject*, ClickableLabel*> pluginLabels;
QList<StatusCenterPane*> loadedPlugins;
int pluginsSettingsStartIndex;
QList<StatusCenterPaneObject*> loadedSettingsPlugins;
QTimer* eventTimer;
QTime startTime;
QTimer* networkCheckTimer;
InfoPaneDropdown::networkAvailability networkOk = InfoPaneDropdown::Ok;
QSettings settings;
QSettings* lockScreenSettings;
QSettings* themeSettings;
QSettings* sessionSettings;
QSettings* notificationAppSettings;
QSettings* gtk3Settings;
QSettings* locationSettings;
QWidget* overviewFrame = nullptr;
QString editingUserPath;
bool networkListUpdating = false;
QMediaPlayer* ringtone;
QChart* batteryChart;
QDateTimeAxis* xAxis;
bool chartScrolling = false;
int startValue;
QMap<uint, Switch*> pluginSwitches;
uint numberOfSwitches = 0;
QVector<int> previousDrags;
WId MainWindowId;
QDBusObjectPath geoclueClientPath;
QVariantAnimation slice1, slice2, slice3, slice4;
QJsonObject timezoneData;
QNetworkAccessManager mgr;
QMap<QString, QString> keyboardLayouts;
void broadcastMessage(QString name, QVariantList args = QVariantList()) {
//Go through each plugin to make sure plugins registered as daemons also get sent messages
for (StatusCenterPane* plugin : loadedPlugins) {
for (StatusCenterPaneObject* pane : plugin->availablePanes()) {
pane->message(name, args);
}
}
}
};
InfoPaneDropdown::InfoPaneDropdown(WId MainWindowId, QWidget *parent) :
QDialog(parent),
ui(new Ui::InfoPaneDropdown)
{
if (false) {
Q_UNUSED(QT_TR_NOOP("Location"));
}
ui->setupUi(this);
d = new InfoPaneDropdownPrivate(this);
this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
ui->settingsList->setIconSize(QSize(32 * getDPIScaling(), 32 * getDPIScaling()));
ui->settingsListContainer->setFixedWidth(250 * getDPIScaling());
d->startTime.start();
ui->copyrightNotice->setText(tr("Copyright © Victor Tran %1. Licensed under the terms of the GNU General Public License, version 3 or later.").arg("2019"));
ui->usesLocation->setPixmap(QIcon::fromTheme("gps").pixmap(16 * getDPIScaling(), 16 * getDPIScaling()));
d->MainWindowId = MainWindowId;
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateSysInfo()));
timer->setInterval(1000);
timer->start();
connect(updbus, &UPowerDBus::powerStretchChanged, [=](bool isOn) {
ui->PowerStretchSwitch->setChecked(isOn);
emit batteryStretchChanged(isOn);
doNetworkCheck();
if (isOn) {
d->slice1.pause();
d->slice2.pause();
} else {
d->slice1.resume();
d->slice2.resume();
}
});
ui->PowerStretchSwitch->setChecked(updbus->powerStretch());
emit batteryStretchChanged(updbus->powerStretch());
ui->BatteryChargeScrollBar->setVisible(false);
ui->appNotificationsConfigureLock->setVisible(false);
//ui->networkKey->setVisible(false);
//ui->networkConnect->setVisible(false);
ui->resetButton->setProperty("type", "destructive");
ui->userSettingsDeleteUser->setProperty("type", "destructive");
ui->userSettingsDeleteUserAndData->setProperty("type", "destructive");
ui->userSettingsDeleteUserOnly->setProperty("type", "destructive");
ui->resetDeviceButton->setProperty("type", "destructive");
ui->partFrame->installEventFilter(this);
ui->pageStack->setCurrentAnimation(tStackedWidget::SlideHorizontal);
ui->settingsTabs->setCurrentAnimation(tStackedWidget::Lift);
//Set up shortcuts
QShortcut* leftShortcut = new QShortcut(Qt::Key_Left, this);
connect(leftShortcut, &QShortcut::activated, [=] {
ui->pushButton_5->click();
});
QShortcut* rightShortcut = new QShortcut(Qt::Key_Right, this);
connect(rightShortcut, &QShortcut::activated, [=] {
ui->pushButton_6->click();
});
QShortcut* escShortcut = new QShortcut(Qt::Key_Escape, this);
connect(escShortcut, &QShortcut::activated, [=] {
ui->pushButton->click();
});
QPalette powerStretchPalette = ui->PowerStretchSwitch->palette();
QPalette flightModePalette = ui->FlightSwitch->palette();
QColor background = this->palette().color(QPalette::Background);
int averageCol = (background.red() + background.green() + background.blue()) / 3;
if (averageCol < 127) {
powerStretchPalette.setColor(QPalette::Highlight, QColor(255, 100, 0));
powerStretchPalette.setColor(QPalette::WindowText, Qt::white);
flightModePalette.setColor(QPalette::Highlight, QColor(0, 0, 200));
flightModePalette.setColor(QPalette::WindowText, Qt::white);
} else {
powerStretchPalette.setColor(QPalette::Highlight, QColor(255, 200, 0));
powerStretchPalette.setColor(QPalette::WindowText, Qt::black);
flightModePalette.setColor(QPalette::Highlight, QColor(100, 200, 255));
flightModePalette.setColor(QPalette::WindowText, Qt::black);
}
ui->PowerStretchSwitch->setPalette(powerStretchPalette);
ui->FlightSwitch->setPalette(flightModePalette);
//Set up battery chart
d->batteryChart = new QChart();
d->batteryChart->setBackgroundVisible(false);
d->batteryChart->legend()->hide();
QChartView* batteryChartView = new QChartView(d->batteryChart);
batteryChartView->setRenderHint(QPainter::Antialiasing);
((QBoxLayout*) ui->batteryGraph->layout())->insertWidget(1, batteryChartView);
updateBatteryChart();
//Check Redshift
QProcess* redshiftQuery = new QProcess;
redshiftQuery->start("redshift -V");
connect(redshiftQuery, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [=](int exitCode, QProcess::ExitStatus exitStatus) {
QString output = redshiftQuery->readAll().trimmed();
output.remove("redshift ");
QStringList parts = output.split(".");
for (int i = 0; i < parts.count(); i++) {
int version = parts.at(i).toInt();
if (i == 0) {
if (version > 1) {
break;
} else if (version < 1) {
d->isNewRedshift = false;
break;
}
} else if (i == 1) {
if (version < 11) {
d->isNewRedshift = false;
}
break;
}
}
redshiftQuery->deleteLater();
});
if (!QFile("/usr/bin/scallop").exists()) {
ui->resetDeviceButton->setVisible(false);
}
//Load icons into icon theme box
{
QString currentIconTheme = d->themeSettings->value("icons/theme", "contemporary").toString();
QDir iconPath("/usr/share/icons");
for (QString iconDir : iconPath.entryList(QDir::NoDotAndDotDot | QDir::Dirs)) {
QFile themeFile("/usr/share/icons/" + iconDir + "/index.theme");
if (themeFile.exists()) {
themeFile.open(QFile::ReadOnly);
QString iconThemeName = "";
while (!themeFile.atEnd()) {
QString line = themeFile.readLine();
if (line.startsWith("Name")) {
iconThemeName = line.mid(line.indexOf("=") + 1).remove("\n");
break;
}
}
themeFile.close();
if (iconThemeName != "") {
ui->systemIconTheme->addItem(iconThemeName);
ui->systemIconTheme->setItemData(ui->systemIconTheme->count() - 1, iconDir);
if (currentIconTheme == iconDir) {
ui->systemIconTheme->setCurrentIndex(ui->systemIconTheme->count() - 1);
}
}
}
}
}
//Load widget themes into widget theme box
{
ui->systemWidgetTheme->blockSignals(true);
QString currentWidgetTheme = d->themeSettings->value("style/name", "contemporary").toString();
QStringList keys = QStyleFactory::keys();
for (QString key : keys) {
ui->systemWidgetTheme->addItem(key);
ui->systemWidgetTheme->setItemData(ui->systemWidgetTheme->count() - 1, key);
if (key.toLower() == currentWidgetTheme.toLower()) {
ui->systemWidgetTheme->setCurrentIndex(ui->systemWidgetTheme->count() - 1);
}
}
ui->systemWidgetTheme->blockSignals(false);
}
//Load GTK3 themes into GTK3 theme box
{
ui->systemGTK3Theme->blockSignals(true);
QString currentWidgetTheme = d->gtk3Settings->value("Settings/gtk-theme-name", "Contemporary").toString();
QStringList themes;
QString themeSearchDirectory = "/usr/share/themes/";
QDir themeDir(themeSearchDirectory);
QStringList themeDirEntries = themeDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
for (QString entry : themeDirEntries) {
if (QDir(themeSearchDirectory + entry + "/gtk-3.0/").exists()) {
themes.append(entry);
}
}
for (QString theme : themes) {
ui->systemGTK3Theme->addItem(theme);
ui->systemGTK3Theme->setItemData(ui->systemGTK3Theme->count() - 1, theme);
if (theme.toLower() == currentWidgetTheme.toLower()) {
ui->systemGTK3Theme->setCurrentIndex(ui->systemGTK3Theme->count() - 1);
}
}
ui->systemGTK3Theme->blockSignals(false);
}
QString redshiftStart = d->settings.value("display/redshiftStart", "").toString();
if (redshiftStart == "") {
redshiftStart = ui->startRedshift->time().toString();
d->settings.setValue("display/redshiftStart", redshiftStart);
}
ui->startRedshift->setTime(QTime::fromString(redshiftStart));
QString redshiftEnd = d->settings.value("display/redshiftEnd", "").toString();
if (redshiftEnd == "") {
redshiftEnd = ui->endRedshift->time().toString();
d->settings.setValue("display/redshiftEnd", redshiftEnd);
}
ui->endRedshift->setTime(QTime::fromString(redshiftEnd));
QString redshiftVal = d->settings.value("display/redshiftIntensity", "").toString();
if (redshiftVal == "") {
redshiftVal = ui->endRedshift->time().toString();
d->settings.setValue("display/redshiftIntensity", redshiftVal);
}
ui->redshiftIntensity->setValue(redshiftVal.toInt());
if (d->settings.value("ui/useFullScreenEndSession", false).toBool()) {
ui->endSessionConfirmFullScreen->setChecked(true);
ui->endSessionConfirmInMenu->setChecked(false);
} else {
ui->endSessionConfirmFullScreen->setChecked(false);
ui->endSessionConfirmInMenu->setChecked(true);
}
if (d->settings.contains("notifications/lockScreen")) {
if (d->settings.value("notifications/lockScreen").toString() == "contents") {
ui->showNotificationsContents->setChecked(true);
} else if (d->settings.value("notifications/lockScreen").toString() == "none") {
ui->showNotificationsNo->setChecked(true);
} else {
ui->showNotificationsOnly->setChecked(true);
}
} else {
ui->showNotificationsOnly->setChecked(true);
}
QString themeType = d->themeSettings->value("color/type", "dark").toString();
if (themeType == "light") {
ui->lightColorThemeRadio->setChecked(true);
} else if (themeType == "dark") {
ui->darkColorThemeRadio->setChecked(true);
} else if (themeType == "gray") {
ui->grayColorThemeRadio->setChecked(true);
} else if (themeType == "decorative") {
ui->decorativeColorThemeRadio->setChecked(true);
}
int dpi = d->settings.value("screen/dpi", 96).toInt();
switch (dpi) {
case 96:
ui->dpi100->setChecked(true);
break;
case 144:
ui->dpi150->setChecked(true);
break;
case 192:
ui->dpi200->setChecked(true);
break;
case 288:
ui->dpi300->setChecked(true);
break;
}
//Populate the language box
Internationalisation::fillLanguageBox(ui->localeList);
ui->lockScreenBackground->setText(d->lockScreenSettings->value("background", "/usr/share/tsscreenlock/triangles.svg").toString());
//ui->lineEdit_2->setText(d->settings.value("startup/autostart", "").toString());
ui->redshiftPause->setChecked(!d->settings.value("display/redshiftPaused", true).toBool());
ui->TextSwitch->setChecked(d->settings.value("bar/showText", true).toBool());
ui->windowManager->setText(d->settings.value("startup/WindowManagerCommand", "kwin_x11 --no-kactivities").toString());
ui->barDesktopsSwitch->setChecked(d->settings.value("bar/showWindowsFromOtherDesktops", true).toBool());
ui->MediaSwitch->setChecked(d->settings.value("notifications/mediaInsert", true).toBool());
ui->StatusBarSwitch->setChecked(d->settings.value("bar/statusBar", false).toBool());
ui->SuspendLockScreen->setChecked(d->settings.value("lockScreen/showOnSuspend", true).toBool());
ui->LargeTextSwitch->setChecked(d->themeSettings->value("accessibility/largeText", false).toBool());
ui->HighContrastSwitch->setChecked(d->themeSettings->value("accessibility/highcontrast", false).toBool());
ui->systemAnimationsAccessibilitySwitch->setChecked(d->themeSettings->value("accessibility/systemAnimations", true).toBool());
ui->CapsNumLockBellSwitch->setChecked(d->themeSettings->value("accessibility/bellOnCapsNumLock", false).toBool());
ui->TwentyFourHourSwitch->setChecked(d->settings.value("time/use24hour", true).toBool());
ui->AttenuateSwitch->setChecked(d->settings.value("notifications/attenuate", true).toBool());
ui->BarOnBottom->setChecked(!d->settings.value("bar/onTop", true).toBool());
ui->AutoShowBarSwitch->setChecked(d->settings.value("bar/autoshow", true).toBool());
ui->SoundFeedbackSoundSwitch->setChecked(d->settings.value("sound/feedbackSound", true).toBool());
ui->VolumeOverdriveSwitch->setChecked(d->settings.value("sound/volumeOverdrive", true).toBool());
ui->batteryScreenOff->setValue(d->settings.value("power/batteryScreenOff", 15).toInt());
ui->batterySuspend->setValue(d->settings.value("power/batterySuspend", 30).toInt());
ui->powerScreenOff->setValue(d->settings.value("power/powerScreenOff", 30).toInt());
ui->powerSuspend->setValue(d->settings.value("power/powerSuspend", 90).toInt());
ui->sunlightRedshift->setChecked(d->settings.value("display/redshiftSunlightCycle", false).toBool());
ui->EmphasiseAppSwitch->setChecked(d->settings.value("notifications/emphasiseApp", true).toBool());
ui->CompactBarSwitch->setChecked(d->settings.value("bar/compact", false).toBool());
ui->LocationMasterSwitch->setChecked(d->locationSettings->value("master/master", true).toBool());
ui->powerButtonPressed->setCurrentIndex(d->settings.value("power/onPowerButtonPressed", 0).toInt());
ui->notifyOnConnectPower->setChecked(d->settings.value("power/notifyConnectPower", true).toBool());
ui->notifyOnUnplug->setChecked(d->settings.value("power/notifyUnplugPower", true).toBool());
updateAccentColourBox();
updateRedshiftTime();
on_StatusBarSwitch_toggled(ui->StatusBarSwitch->isChecked());
if (QFile(QDir::homePath() + "/.theshell/mousepassword").exists()) {
ui->removeMousePassword->setVisible(true);
} else {
ui->removeMousePassword->setVisible(false);
}
QString defaultFont;
if (QFontDatabase().families().contains("Contemporary")) {
defaultFont = "Contemporary";
} else {
defaultFont = "Noto Sans";
}
ui->systemFont->setCurrentFont(QFont(d->themeSettings->value("fonts/defaultFamily", defaultFont).toString(), d->themeSettings->value("font/defaultSize", 10).toInt()));
ui->systemFontSize->setValue(d->themeSettings->value("font/defaultSize", 10).toInt());
QString gtk3FontString = d->gtk3Settings->value("Settings/gtk-font-name", "Contemporary 10").toString();
QString gtk3FontFamily = gtk3FontString.left(gtk3FontString.lastIndexOf(" "));
QString gtk3FontSize = gtk3FontString.mid(gtk3FontString.lastIndexOf(" ") + 1);
ui->systemGTK3Font->setCurrentFont(QFont(gtk3FontFamily, gtk3FontSize.toInt()));
ui->systemGTK3FontSize->setValue(gtk3FontSize.toInt());
switch (d->settings.value("power/suspendMode", 0).toInt()) {
case 0:
ui->powerSuspendNormally->setChecked(true);
break;
case 1:
ui->powerSuspendTurnOffScreen->setChecked(true);
break;
case 2:
ui->powerSuspendHibernate->setChecked(true);
break;
}
d->eventTimer = new QTimer(this);
d->eventTimer->setInterval(1000);
connect(d->eventTimer, SIGNAL(timeout()), this, SLOT(processTimer()));
d->eventTimer->start();
d->networkCheckTimer = new QTimer(this);
d->networkCheckTimer->setInterval(60000);
connect(d->networkCheckTimer, SIGNAL(timeout()), this, SLOT(doNetworkCheck()));
d->networkCheckTimer->start();
doNetworkCheck();
QObjectList allObjects;
allObjects.append(this);
ui->notificationSoundBox->blockSignals(true);
ui->notificationSoundBox->addItem("Triple Ping");
ui->notificationSoundBox->addItem("Upside Down");
ui->notificationSoundBox->addItem("Echo");
QString notificationSound = d->settings.value("notifications/sound", "tripleping").toString();
if (notificationSound == "tripleping") {
ui->notificationSoundBox->setCurrentIndex(0);
} else if (notificationSound == "upsidedown") {
ui->notificationSoundBox->setCurrentIndex(1);
} else if (notificationSound == "echo") {
ui->notificationSoundBox->setCurrentIndex(2);
}
ui->notificationSoundBox->blockSignals(false);
//Get distribution information
{
QString osreleaseFile = "";
if (QFile("/etc/os-release").exists()) {
osreleaseFile = "/etc/os-release";
} else if (QFile("/usr/lib/os-release").exists()) {
osreleaseFile = "/usr/lib/os-release";
}
if (osreleaseFile != "") {
QFile information(osreleaseFile);
information.open(QFile::ReadOnly);
while (!information.atEnd()) {
QString line = information.readLine();
if (line.startsWith("pretty_name=", Qt::CaseInsensitive)) {
ui->distroName->setText(line.remove("pretty_name=", Qt::CaseInsensitive).remove("\"").remove("\n"));
} else if (line.startsWith("home_url=", Qt::CaseInsensitive)) {
ui->distroWebpage->setText(line.remove("home_url=", Qt::CaseInsensitive).remove("\"").remove("\n"));
} else if (line.startsWith("support_url=", Qt::CaseInsensitive)) {
ui->distroSupport->setText(line.remove("support_url=", Qt::CaseInsensitive).remove("\"").remove("\n"));
}
}
information.close();
}
struct sysinfo* info = new struct sysinfo;
if (sysinfo(info) == 0) {
ui->availableMemory->setText(calculateSize(info->totalram));
ui->availableSwap->setText(calculateSize(info->totalswap));
} else {
}
delete info;
ui->kernelVersion->setText(QSysInfo::kernelVersion());
ui->qtVersion->setText(qVersion());
QFile cpuInfoFile("/proc/cpuinfo");
cpuInfoFile.open(QFile::ReadOnly);
QByteArray cpuInfoBuf = cpuInfoFile.readAll();
QBuffer cpuInfo(&cpuInfoBuf);
cpuInfo.open(QBuffer::ReadOnly);
QStringList knownCpus;
while (!cpuInfo.atEnd()) {
QString line = cpuInfo.readLine();
if (line.startsWith("model name")) {
QString cpu = line.mid(line.indexOf(":") + 1).trimmed();
knownCpus.append(cpu);
}
}
QStringList shownCpus;
while (knownCpus.length() > 0) {
QString cpu = knownCpus.value(0);
int numberOfThisCpu = knownCpus.count(cpu);
knownCpus.removeAll(cpu);
if (numberOfThisCpu == 1) {
shownCpus.append(cpu);
} else {
shownCpus.append(QString::number(numberOfThisCpu) + " × " + cpu);
}
}
if (shownCpus.length() == 0) {
ui->processorType->setText(tr("Unknown"));
} else {
ui->processorType->setText(shownCpus.join(" · "));
}
}
#ifdef BLUEPRINT
ui->tsVersion->setText(tr("theShell %1 - Blueprint").arg(TS_VERSION));
ui->compileDate->setText(tr("You compiled theShell on %1").arg(__DATE__));
#else
ui->tsVersion->setText(tr("theShell %1").arg(TS_VERSION));
ui->compileDate->setVisible(false);
#endif
//Update keyboard layouts
(new tPromise<QMap<QString, QString>>([=](QString& error) {
QMap<QString, QString> retval;
QDir xkbLayouts("/usr/share/X11/xkb/symbols");
for (QFileInfo layoutInfo : xkbLayouts.entryInfoList()) {
if (layoutInfo.isDir()) continue;
QString layout = layoutInfo.baseName();
QFile file(layoutInfo.filePath());
file.open(QFile::ReadOnly);
QString currentSubLayout = "";
while (!file.atEnd()) {
QString line = file.readLine().trimmed();
if (line.startsWith("xkb_symbols") && line.endsWith("{")) {
QRegExp lineRx("\".+\"");
lineRx.indexIn(line);
if (lineRx.capturedTexts().count() != 0) {
currentSubLayout = lineRx.capturedTexts().first().remove("\"");
} else {
currentSubLayout = "";
}
} else if (line.startsWith("name")) {
QRegExp lineRx("\".+\"");
lineRx.indexIn(line);
if (lineRx.capturedTexts().count() != 0 && currentSubLayout != "") {
retval.insert(layout + "(" + currentSubLayout + ")", lineRx.capturedTexts().first().remove("\""));
} else {
currentSubLayout = "";
}
}
}
file.close();
}
return retval;
}))->then([=](QMap<QString, QString> layouts) {
d->keyboardLayouts = layouts;
setKeyboardLayout(d->settings.value("input/currentLayout", "us(basic)").toString());
});
//Set up timer ringtones
d->ringtone = new QMediaPlayer(this, QMediaPlayer::LowLatency);
connect(AudioMan, &AudioManager::QuietModeChanged, [=](AudioManager::quietMode mode) {
d->broadcastMessage("quiet-mode-changed", {(int) mode});
});
d->slice1.setStartValue((float) (this->width() - 250 * getDPIScaling()));
d->slice1.setEndValue((float) (this->width() - 300 * getDPIScaling()));
d->slice1.setEasingCurve(QEasingCurve::OutCubic);
d->slice1.setDuration(15000);
connect(&d->slice1, &tVariantAnimation::finished, [=] {
d->slice1.setStartValue(d->slice1.endValue());
if (d->slice1.endValue() == this->width() - 300 * getDPIScaling()) {
d->slice1.setEndValue(this->width() - 250 * getDPIScaling());
} else {
d->slice1.setEndValue(this->width() - 300 * getDPIScaling());
}
d->slice1.setEasingCurve(QEasingCurve::InOutCubic);
d->slice1.start();
});
connect(&d->slice1, SIGNAL(valueChanged(QVariant)), ui->partFrame, SLOT(repaint()));
d->slice1.start();
QTimer::singleShot(2500, [=] {
d->slice2.setStartValue((float) (this->width() - 300 * getDPIScaling()));
d->slice2.setEndValue((float) (this->width() - 350 * getDPIScaling()));
d->slice2.setEasingCurve(QEasingCurve::OutCubic);
d->slice2.setDuration(15000);
connect(&d->slice2, &tVariantAnimation::finished, [=] {
d->slice2.setStartValue(d->slice2.endValue());
if (d->slice2.endValue() == this->width() - 350 * getDPIScaling()) {
d->slice2.setEndValue(this->width() - 300 * getDPIScaling());
} else {
d->slice2.setEndValue(this->width() - 350 * getDPIScaling());
}
d->slice2.setEasingCurve(QEasingCurve::InOutCubic);
d->slice2.start();
});
d->slice2.start();
});
//Load plugins
if (!startSafe) {
QList<QDir> searchDirs;
QJsonArray errors;
searchDirs.append(QApplication::applicationDirPath() + "/../statuscenter/");
searchDirs.append(QApplication::applicationDirPath() + "/../daemons/");
#ifdef BLUEPRINT
searchDirs.append(QDir("/usr/lib/theshellb/panes"));
searchDirs.append(QDir("/usr/lib/theshellb/daemons"));
#else
searchDirs.append(QDir("/usr/lib/theshell/panes"));
searchDirs.append(QDir("/usr/lib/theshell/daemons"));
#endif
QStringList loadedPanes, loadedSettings;
d->pluginsSettingsStartIndex = ui->settingsList->count() - 3;
for (QDir pluginsDir : searchDirs) {
QDirIterator pluginsIterator(pluginsDir, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
while (pluginsIterator.hasNext()) {
pluginsIterator.next();
if (pluginsIterator.fileInfo().suffix() != "so" && pluginsIterator.fileInfo().suffix() != "a") continue;
QPluginLoader loader(pluginsIterator.filePath());
QJsonObject metadata = loader.metaData();
if (!metadata.contains("name")) {
metadata.insert("name", pluginsIterator.fileName());
}
QObject* plugin = loader.instance();
if (plugin == nullptr) {
metadata.insert("error", loader.errorString());
errors.append(metadata);
} else {
StatusCenterPane* p = qobject_cast<StatusCenterPane*>(plugin);
if (p) {
qDebug() << "Loading" << metadata.value("name").toString();
p->loadLanguage(QLocale().name());
for (StatusCenterPaneObject* pane : p->availablePanes()) {
if (pane->position() == -1000 && pane->type().testFlag(StatusCenterPaneObject::Informational)) {
if (!loadedPanes.contains("Overview")) {
//Special handling for Overview pane
d->overviewFrame = pane->mainWidget();
d->overviewFrame->setAutoFillBackground(true);
ui->pageStack->insertWidget(0, d->overviewFrame);
loadedPanes.append("Overview");
}
} else {
if (pane->type().testFlag(StatusCenterPaneObject::Informational)) {
if (!loadedPanes.contains(pane->name())) {
ClickableLabel* label = new ClickableLabel(this);
label->setText(pane->name());
ui->InformationalPluginsLayout->addWidget(label);
ui->pageStack->insertWidget(ui->pageStack->count() - 1, pane->mainWidget());
pane->mainWidget()->setAutoFillBackground(true);
connect(label, &ClickableLabel::clicked, [=] {
changeDropDown(pane->mainWidget(), label);
if (ui->lightColorThemeRadio->isChecked()) {
setHeaderColour(pane->informationalAttributes.lightColor);
} else {
setHeaderColour(pane->informationalAttributes.darkColor);
}
});
loadedPanes.append(pane->name());
d->pluginLabels.insert(pane, label);
}
}
if (pane->type().testFlag(StatusCenterPaneObject::Setting)) {
if (!loadedSettings.contains(pane->name())) {
QListWidgetItem* item = new QListWidgetItem();
item->setText(pane->name());
item->setIcon(pane->settingAttributes.icon);
item->setData(Qt::UserRole, -1);
ui->settingsList->insertItem(d->pluginsSettingsStartIndex + loadedSettings.count(), item);
if (pane->settingAttributes.menuWidget != nullptr) {
int settingNumber = ui->settingsListStack->addWidget(pane->settingAttributes.menuWidget);
pane->settingAttributes.menuWidget->setAutoFillBackground(true);
item->setData(Qt::UserRole, settingNumber);
}
ui->settingsTabs->insertWidget(d->pluginsSettingsStartIndex + loadedSettings.count(), pane->mainWidget());
pane->mainWidget()->setAutoFillBackground(true);
loadedSettings.append(pane->name());
d->loadedSettingsPlugins.append(pane);
}
}
}
pane->sendMessage = [=](QString message, QVariantList args) {
this->pluginMessage(message, args, pane);
};
pane->getProperty = [=](QString key) {
return this->pluginProperty(key);
};
d->pluginObjects.insert(pane->mainWidget(), pane);
}
d->loadedPlugins.append(p);
}
}
}
}
if (!loadedPanes.contains("Overview")) {
qWarning() << "Could not load Overview pane";
qWarning() << "theShell may not work properly";
}
if (errors.count() == 0) {
ui->settingsTabs->removeWidget(ui->UnavailablePanesPage);
delete ui->settingsList->takeItem(ui->settingsList->count() - 3);
} else {
ui->settingsUnavailableTable->setColumnCount(2);
ui->settingsUnavailableTable->setRowCount(errors.count());
ui->settingsUnavailableTable->setHorizontalHeaderLabels(QStringList() << "Name" << "Reason");
ui->settingsUnavailableTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
ui->settingsUnavailableTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
for (int i = 0; i < errors.count(); i++) {
QJsonObject o = errors.at(i).toObject();
ui->settingsUnavailableTable->setItem(i, 0, new QTableWidgetItem(o.value("name").toString()));
ui->settingsUnavailableTable->setItem(i, 1, new QTableWidgetItem(o.value("error").toString()));
}
}
} else {
//We're starting in safe mode; hide the overview label
ui->clockLabel->setVisible(false);
ui->unavailablePaneMessage->setText(tr("No plugins were loaded because you've started theShell in Safe Mode."));
}
//Don't forget to change settings pane setup things
ui->settingsList->item(ui->settingsList->count() - 1)->setSelected(true);
ui->settingsTabs->setCurrentIndex(ui->settingsTabs->count() - 1);
QScroller::grabGesture(ui->settingsList, QScroller::LeftMouseButtonGesture);
QScroller::grabGesture(ui->timezoneCityList, QScroller::LeftMouseButtonGesture);
QScroller::grabGesture(ui->timezoneList, QScroller::LeftMouseButtonGesture);
QScroller::grabGesture(ui->appsGraph, QScroller::LeftMouseButtonGesture);
QScroller::grabGesture(ui->autostartAppList, QScroller::LeftMouseButtonGesture);
connect(tVirtualKeyboard::instance(), &tVirtualKeyboard::keyboardVisibleChanged, [=](bool visible) {
QRect screenGeometry = QApplication::desktop()->screenGeometry();
if (visible) {
this->setFixedHeight(screenGeometry.height() - tVirtualKeyboard::instance()->height());
} else {
this->setFixedHeight(screenGeometry.height() + 1);
}
});
updateStruts();
updateAutostart();
//Turn on flight mode if needed
if (d->settings.value("flightmode/on", false).toBool()) {
ui->FlightSwitch->setChecked(true);
}
/*QTimer::singleShot(5000, [=] {
this->setProperty("aw", 0);
QTimer* timer = new QTimer();
timer->setInterval(1000);
connect(timer, &QTimer::timeout, [=] {
int number = this->property("aw").toInt();
number++;
if (number == 100) {
timer->stop();
emit statusBarProgressFinished("Copied", "lirios-2018-04-28.iso");
} else {
emit statusBarProgress("Copying", "lirios-2018.04.28.iso", number);
}
this->setProperty("aw", number);
});
timer->start();
});*/
}
InfoPaneDropdown::~InfoPaneDropdown()
{
delete d;
delete ui;
}
InfoPaneNotOnTopLocker::InfoPaneNotOnTopLocker(InfoPaneDropdown *infoPane) {
this->infoPane = infoPane;
infoPane->setWindowFlags(Qt::FramelessWindowHint);
}
InfoPaneNotOnTopLocker::~InfoPaneNotOnTopLocker() {
infoPane->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
infoPane->showNoAnimation();
}
void InfoPaneDropdown::processTimer() {
QTime time = QTime::currentTime();
{
int currentMsecs = time.msecsSinceStartOfDay();
int startMsecs = ui->startRedshift->time().msecsSinceStartOfDay();
int endMsecs = ui->endRedshift->time().msecsSinceStartOfDay();
int endIntensity = ui->redshiftIntensity->value();
const int oneHour = 3600000;
QString redshiftCommand;
if (ui->redshiftPause->isChecked()) {
//Calculate redshift value
//Transition to redshift is 1 hour from the start.
int intensity;
if (startMsecs > endMsecs) { //Start time is later then end time
if (currentMsecs < endMsecs || currentMsecs > startMsecs) {
intensity = endIntensity;
} else if (currentMsecs < startMsecs && currentMsecs > startMsecs - oneHour) {
int timeFrom = currentMsecs - (startMsecs - oneHour);
float percentage = ((float) timeFrom / (float) oneHour);
int progress = (6500 - endIntensity) * percentage;
intensity = 6500 - progress;
} else if (currentMsecs > endMsecs && currentMsecs < endMsecs + oneHour) {
int timeFrom = endMsecs - (currentMsecs - oneHour);
float percentage = ((float) timeFrom / (float) oneHour);
int progress = (6500 - endIntensity) * percentage;
intensity = 6500 - progress;
} else {
intensity = 6500;
}
} else { //Start time is earlier then end time
if (currentMsecs < endMsecs && currentMsecs > startMsecs) {
intensity = endIntensity;
} else if (currentMsecs < startMsecs && currentMsecs > startMsecs - oneHour) {
int timeFrom = currentMsecs - (startMsecs - oneHour);
float percentage = ((float) timeFrom / (float) oneHour);
int progress = (6500 - endIntensity) * percentage;
intensity = 6500 - progress;
} else if (currentMsecs > endMsecs && currentMsecs < endMsecs + oneHour) {
int timeFrom = endMsecs - (currentMsecs - oneHour);
float percentage = ((float) timeFrom / (float) oneHour);
int progress = (6500 - endIntensity) * percentage;
intensity = 6500 - progress;
} else {
intensity = 6500;
}
}
//Check Redshift override
if (d->overrideRedshift != 0) {
if (intensity == 6500 && d->overrideRedshift == 1) {
d->overrideRedshift = 0; //Reset Redshift override
} else if (intensity != 6500 && d->overrideRedshift == 2) {
d->overrideRedshift = 0; //Reset Redshift override
} else {
if (d->overrideRedshift == 1) {
intensity = 6500;
} else {
intensity = endIntensity;
}
}
}
redshiftCommand = "redshift -O " + QString::number(intensity);
d->isRedshiftOn = true;
if (intensity == 6500 && d->effectiveRedshiftOn) {
d->effectiveRedshiftOn = false;
ui->redshiftSwitch->setChecked(false);
emit redshiftEnabledChanged(false);
} else if (intensity != 6500 && !d->effectiveRedshiftOn) {
d->effectiveRedshiftOn = true;
ui->redshiftSwitch->setChecked(true);
emit redshiftEnabledChanged(true);
}
} else {
//Check Redshift Override
if (d->overrideRedshift == 2) {
redshiftCommand = "redshift -O " + QString::number(endIntensity);
} else {
redshiftCommand = "redshift -O 6500";
}
if (d->isRedshiftOn) {
d->isRedshiftOn = false;
d->effectiveRedshiftOn = false;
ui->redshiftSwitch->setChecked(false);
emit redshiftEnabledChanged(false);
}
}
if (d->isNewRedshift) {
redshiftCommand += " -P";
}
QProcess* redshiftAdjust = new QProcess();
redshiftAdjust->start(redshiftCommand);
connect(redshiftAdjust, SIGNAL(finished(int)), redshiftAdjust, SLOT(deleteLater()));
}
/*{
cups_dest_t *destinations;
int destinationCount = cupsGetDests(&destinations);
for (int i = 0; i < destinationCount; i++) {
cups_dest_t currentDestination = destinations[i];
if (!printersFrames.keys().contains(currentDestination.name)) {
QFrame* frame = new QFrame();
QHBoxLayout* layout = new QHBoxLayout();
layout->setMargin(0);
frame->setLayout(layout);
QFrame* statFrame = new QFrame();
QHBoxLayout* statLayout = new QHBoxLayout();
statLayout->setMargin(0);
statFrame->setLayout(statLayout);
layout->addWidget(statFrame);
QLabel* iconLabel = new QLabel();
QPixmap icon = QIcon::fromTheme("printer").pixmap(22 * getDPIScaling(), 22 * getDPIScaling());
if (currentDestination.is_default) {
QPainter *p = new QPainter();
p->begin(&icon);
p->drawPixmap(10 * getDPIScaling(), 10 * getDPIScaling(), 12 * getDPIScaling(), 12 * getDPIScaling(), QIcon::fromTheme("emblem-checked").pixmap(12 * getDPIScaling(), 12 * getDPIScaling()));
p->end();
}
iconLabel->setPixmap(icon);
statLayout->addWidget(iconLabel);
QLabel* nameLabel = new QLabel();
nameLabel->setText(currentDestination.name);
QFont font = nameLabel->font();
font.setBold(true);
nameLabel->setFont(font);
statLayout->addWidget(nameLabel);
QLabel* statLabel = new QLabel();
statLabel->setText(tr("Idle"));
statLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
statLayout->addWidget(statLabel);
/*QPushButton* button = new QPushButton();
button->setIcon(QIcon::fromTheme("window-close"));
connect(button, &QPushButton::clicked, [=]() {
emit closeNotification(id);
});
layout->addWidget(button);
ui->printersList->layout()->addWidget(frame);
printersFrames.insert(currentDestination.name, frame);
printersStatFrames.insert(currentDestination.name, frame);
printersStats.insert(currentDestination.name, statLabel);
}
QString state = "";
QString stateReasons = "";
for (int i = 0; i < currentDestination.num_options; i++) {
cups_option_t currentOption = currentDestination.options[i];
if (strncmp(currentOption.name, "printer-state", strlen(currentOption.name)) == 0) {
if (strncmp(currentOption.value, "3", 1) == 0) {
state = tr("Idle");
printersStatFrames.value(currentDestination.name)->setEnabled(true);
} else if (strncmp(currentOption.value, "4", 1) == 0) {
state = tr("Printing");
printersStatFrames.value(currentDestination.name)->setEnabled(true);
} else if (strncmp(currentOption.value, "5", 1) == 0) {
state = tr("Stopped");
printersStatFrames.value(currentDestination.name)->setEnabled(false);
}
} else if (strncmp(currentOption.name, "printer-state-reasons", strlen(currentOption.name)) == 0) {
stateReasons = QString::fromUtf8(currentOption.value, strlen(currentOption.value));
}
}
printersStats.value(currentDestination.name)->setText(state + " / " + stateReasons);
}
cupsFreeDests(destinationCount, destinations);
}*/
}
void InfoPaneDropdown::show(dropdownType showWith) {
if (showWith != None) {
changeDropDown(showWith, false);
}
if (!this->isVisible()) {
QRect screenGeometry = QApplication::desktop()->screenGeometry();
if (d->settings.value("bar/onTop", true).toBool()) {
this->setGeometry(screenGeometry.x(), screenGeometry.y() - screenGeometry.height(), screenGeometry.width(), screenGeometry.height() + 1);
} else {
this->setGeometry(screenGeometry.x(), screenGeometry.bottom(), screenGeometry.width(), screenGeometry.height() + 1);
}
Atom DesktopWindowTypeAtom;
DesktopWindowTypeAtom = XInternAtom(QX11Info::display(), "_NET_WM_WINDOW_TYPE_NORMAL", False);
XChangeProperty(QX11Info::display(), this->winId(), XInternAtom(QX11Info::display(), "_NET_WM_WINDOW_TYPE", False),
XA_ATOM, 32, PropModeReplace, (unsigned char*) &DesktopWindowTypeAtom, 1); //Change Window Type
unsigned long desktop = 0xFFFFFFFF;
XChangeProperty(QX11Info::display(), this->winId(), XInternAtom(QX11Info::display(), "_NET_WM_DESKTOP", False),
XA_CARDINAL, 32, PropModeReplace, (unsigned char*) &desktop, 1); //Set visible on all desktops
QDialog::show();
this->setFixedWidth(screenGeometry.width());
if (tVirtualKeyboard::instance()->keyboardVisible()) {
this->setFixedHeight(screenGeometry.height() - tVirtualKeyboard::instance()->height());
} else {
this->setFixedHeight(screenGeometry.height() + 1);
}
if (d->settings.value("bar/onTop", true).toBool()) {
d->previousDrags.prepend(-1);
} else {
d->previousDrags.prepend(screenGeometry.bottom());
}
completeDragDown();
}
//Get Current Brightness
QProcess* backlight = new QProcess(this);
backlight->start("xbacklight -get");
backlight->waitForFinished();
float output = ceil(QString(backlight->readAll()).toFloat());
delete backlight;
ui->brightnessSlider->setValue((int) output);
}
void InfoPaneDropdown::showNoAnimation() {
QDialog::show();
d->previousDrags.prepend(-1);
completeDragDown();
}
void InfoPaneDropdown::close() {
QRect screenGeometry = QApplication::desktop()->screenGeometry();
tPropertyAnimation* a = new tPropertyAnimation(this, "geometry");
a->setStartValue(this->geometry());
if (d->settings.value("bar/onTop", true).toBool()) {
a->setEndValue(QRect(screenGeometry.x(), screenGeometry.y() - screenGeometry.height() + 1, this->width(), this->height()));
} else {
a->setEndValue(QRect(screenGeometry.x(), screenGeometry.bottom() + 1, this->width(), this->height()));
}
a->setEasingCurve(QEasingCurve::OutCubic);
a->setDuration(500);
connect(a, &tPropertyAnimation::finished, [=] {
for (StatusCenterPaneObject* plugin : d->pluginObjects.values()) {
plugin->message("hide");
plugin->showing = false;
}
QDialog::hide();
});
connect(a, SIGNAL(finished()), a, SLOT(deleteLater()));
a->start();
}
void InfoPaneDropdown::changeDropDown(dropdownType changeTo, bool doAnimation) {
//Switch to the requested frame
switch (changeTo) {
case Clock:
changeDropDown(d->overviewFrame, ui->clockLabel, doAnimation);
if (ui->lightColorThemeRadio->isChecked()) {
setHeaderColour(QColor(0, 150, 0));
} else {
setHeaderColour(QColor(0, 50, 0));
}
break;
case Battery:
changeDropDown(ui->statusFrame, ui->batteryLabel, doAnimation);
updateBatteryChart();
if (ui->lightColorThemeRadio->isChecked()) {
setHeaderColour(QColor(200, 150, 0));
} else {
setHeaderColour(QColor(100, 50, 0));
}
break;
case Settings:
changeDropDown(ui->settingsFrame, nullptr, doAnimation);
if (ui->lightColorThemeRadio->isChecked()) {
setHeaderColour(QColor(0, 150, 255));
} else {
setHeaderColour(QColor(0, 50, 100));
}
break;
}
}
void InfoPaneDropdown::changeDropDown(QWidget *changeTo, ClickableLabel* label, bool doAnimation) {
for (StatusCenterPaneObject* plugin : d->pluginObjects.values()) {
plugin->message("hide");
plugin->showing = false;
}
if (d->pluginObjects.contains(changeTo)) {
d->pluginObjects.value(changeTo)->message("show");
d->pluginObjects.value(changeTo)->showing = true;
}
//Switch to the requested frame
if (ui->pageStack->currentWidget() == changeTo) return; //Do nothing
ui->pageStack->setCurrentWidget(changeTo, doAnimation);
if (changeTo == d->overviewFrame) {
if (ui->lightColorThemeRadio->isChecked()) {
setHeaderColour(QColor(0, 150, 0));
} else {
setHeaderColour(QColor(0, 50, 0));
}
} else if (changeTo == ui->statusFrame) {
updateBatteryChart();
if (ui->lightColorThemeRadio->isChecked()) {
setHeaderColour(QColor(200, 150, 0));
} else {
setHeaderColour(QColor(100, 50, 0));
}
} else if (changeTo == ui->settingsFrame) {
if (ui->lightColorThemeRadio->isChecked()) {
setHeaderColour(QColor(0, 150, 255));
} else {
setHeaderColour(QColor(0, 50, 100));
}
}
//Plugin'd panes are handled in the click handler for the label
//Set the correct label
for (int i = 0; i < ui->InformationalPluginsLayout->count(); i++) {
((ClickableLabel*) ui->InformationalPluginsLayout->itemAt(i)->widget())->setShowDisabled(true);
}
if (label != nullptr) {
label->setShowDisabled(false);
}
//Determine the last frame
int lastFrame = 0;
for (int i = ui->pageStack->count() - 1; i >= 0; i--) {
QWidget* w = ui->pageStack->widget(i);
if (w != ui->settingsFrame) {
lastFrame = i;
break;
}
}
if (changeTo == ui->settingsFrame) {
ui->pushButton_5->setEnabled(false);
ui->pushButton_6->setEnabled(false);
} else if (ui->pageStack->indexOf(changeTo) == 0) { //First item
ui->pushButton_5->setEnabled(false);
ui->pushButton_6->setEnabled(true);
} else if (ui->pageStack->indexOf(changeTo) == lastFrame) { //Last item
ui->pushButton_5->setEnabled(true);
ui->pushButton_6->setEnabled(false);
} else {
ui->pushButton_5->setEnabled(true);
ui->pushButton_6->setEnabled(true);
}
}
void InfoPaneDropdown::on_pushButton_clicked()
{
this->close();
}
void InfoPaneDropdown::on_pushButton_5_clicked()
{
int change = ui->pageStack->currentIndex() - 1;
changeDropDown(ui->pageStack->widget(change), (ClickableLabel*) ui->InformationalPluginsLayout->itemAt(change)->widget());
}
void InfoPaneDropdown::on_pushButton_6_clicked()
{
int change = ui->pageStack->currentIndex() + 1;
changeDropDown(ui->pageStack->widget(change), (ClickableLabel*) ui->InformationalPluginsLayout->itemAt(change)->widget());
}
void InfoPaneDropdown::on_clockLabel_clicked()
{
changeDropDown(Clock);
}
void InfoPaneDropdown::on_batteryLabel_clicked()
{
changeDropDown(Battery);
}
void InfoPaneDropdown::on_pushButton_7_clicked()
{
changeDropDown(Settings);
}
void InfoPaneDropdown::setGeometry(int x, int y, int w, int h) { //Use wmctrl command because KWin has a problem with moving windows offscreen.
QDialog::setGeometry(x, y, w, h);
QProcess::execute("wmctrl -r " + this->windowTitle() + " -e 0," +
QString::number(x) + "," + QString::number(y) + "," +
QString::number(w) + "," + QString::number(h));
}
void InfoPaneDropdown::setGeometry(QRect geometry) {
this->setGeometry(geometry.x(), geometry.y(), geometry.width(), geometry.height());
}
void InfoPaneDropdown::on_resolutionButton_clicked()
{
QProcess::startDetached("kcmshell5 kcm_kscreen");
this->close();
}
void InfoPaneDropdown::on_startRedshift_timeChanged(const QTime &time)
{
d->settings.setValue("display/redshiftStart", time.toString());
processTimer();
}
void InfoPaneDropdown::on_endRedshift_timeChanged(const QTime &time)
{
d->settings.setValue("display/redshiftEnd", time.toString());
processTimer();
}
void InfoPaneDropdown::on_redshiftIntensity_sliderMoved(int position)
{
if (d->isNewRedshift) {
QProcess::startDetached("redshift -P -O " + QString::number(position));
} else {
QProcess::startDetached("redshift -O " + QString::number(position));
}
}
void InfoPaneDropdown::on_redshiftIntensity_sliderReleased()
{
if (!d->isRedshiftOn) {
if (d->isNewRedshift) {
QProcess::startDetached("redshift -P -O 6500");
} else {
QProcess::startDetached("redshift -O 6500");
}
}
}
void InfoPaneDropdown::on_redshiftIntensity_valueChanged(int value)
{
d->settings.setValue("display/redshiftIntensity", value);
}
void InfoPaneDropdown::on_redshiftPause_toggled(bool checked)
{
processTimer();
d->settings.setValue("display/redshiftPaused", !checked);
}
void InfoPaneDropdown::updateSysInfo() {
ui->currentBattery->setText(tr("Current Battery Percentage: %1").arg(QString::number(updbus->currentBattery()).append("%")));
QTime uptime(0, 0);
uptime = uptime.addMSecs(d->startTime.elapsed());
ui->theshellUptime->setText(tr("theShell Uptime: %1").arg(uptime.toString("hh:mm:ss")));
struct sysinfo* info = new struct sysinfo;
if (sysinfo(info) == 0) {
QTime sysUptime(0, 0);
sysUptime = sysUptime.addSecs(info->uptime);
QString uptimeString;
if (info->uptime > 86400) {
int days = info->uptime / 86400;
uptimeString = tr("%n days", NULL, days) + " " + sysUptime.toString("hh:mm:ss");
} else {
uptimeString = sysUptime.toString("hh:mm:ss");
}
ui->systemUptime->setText(tr("System Uptime: %1").arg(uptimeString));
} else {
ui->systemUptime->setText(tr("Couldn't get system uptime"));
}
delete info;
}
void InfoPaneDropdown::on_resetButton_clicked()
{
if (QMessageBox::warning(this, tr("Reset theShell"),
tr("All settings will be reset to default, and you will be logged out. "
"Are you sure you want to do this?"), QMessageBox::Yes | QMessageBox::No,
QMessageBox::No) == QMessageBox::Yes) {
d->settings.clear();
EndSession(EndSessionWait::logout);
}
}
void InfoPaneDropdown::mousePressEvent(QMouseEvent *event) {
d->mouseClickPoint = event->localPos().toPoint().y();
d->initialPoint = d->mouseClickPoint;
d->dragRect = this->geometry();
d->mouseMovedUp = false;
d->draggingInfoPane = true;
event->accept();
}
void InfoPaneDropdown::mouseMoveEvent(QMouseEvent *event) {
if (d->draggingInfoPane) {
QRect screenGeometry = QApplication::desktop()->screenGeometry();
if (event->globalY() < d->mouseClickPoint) {
d->mouseMovedUp = true;
} else {
d->mouseMovedUp = false;
}
//dragRect.translate(0, event->localPos().toPoint().y() - mouseClickPoint + this->y());
d->dragRect = screenGeometry;
d->dragRect.translate(0, event->globalY() - (d->initialPoint + screenGeometry.top()));
//innerRect.translate(event->localPos().toPoint().y() - mouseClickPoint, 0);
if (d->settings.value("bar/onTop", true).toBool()) {
if (d->dragRect.bottom() >= screenGeometry.bottom()) {
d->dragRect.moveTo(screenGeometry.left(), screenGeometry.top());
}
} else {
if (d->dragRect.top() <= screenGeometry.top() - 1) {
d->dragRect.moveTo(screenGeometry.left(), screenGeometry.top() - 1);
}
}
this->setGeometry(d->dragRect);
d->mouseClickPoint = event->globalY();
event->accept();
}
}
void InfoPaneDropdown::mouseReleaseEvent(QMouseEvent *event) {
if (d->draggingInfoPane) {
QRect screenGeometry = QApplication::desktop()->screenGeometry();
if (d->initialPoint - 5 > d->mouseClickPoint && d->initialPoint + 5 < d->mouseClickPoint) {
tPropertyAnimation* a = new tPropertyAnimation(this, "geometry");
a->setStartValue(this->geometry());
a->setEndValue(QRect(screenGeometry.x(), screenGeometry.y() - (d->settings.value("bar/onTop", true).toBool() ? 0 : 1), this->width(), this->height()));
a->setEasingCurve(QEasingCurve::OutCubic);
a->setDuration(500);
connect(a, SIGNAL(finished()), a, SLOT(deleteLater()));
a->start();
} else {
/*if ((mouseMovedUp && d->settings.value("bar/onTop", true).toBool()) ||
(!mouseMovedUp && !d->settings.value("bar/onTop", true).toBool())) {*/
if (d->mouseMovedUp == d->settings.value("bar/onTop", true).toBool()) {
this->close();
} else {
tPropertyAnimation* a = new tPropertyAnimation(this, "geometry");
a->setStartValue(this->geometry());
a->setEndValue(QRect(screenGeometry.x(), screenGeometry.y() - (d->settings.value("bar/onTop", true).toBool() ? 0 : 1), this->width(), this->height()));
a->setEasingCurve(QEasingCurve::OutCubic);
a->setDuration(500);
connect(a, SIGNAL(finished()), a, SLOT(deleteLater()));
a->start();
}
}
event->accept();
d->initialPoint = 0;
d->draggingInfoPane = false;
}
}
void InfoPaneDropdown::on_TouchFeedbackSwitch_toggled(bool checked)
{
d->settings.setValue("input/touchFeedbackSound", checked);
}
void InfoPaneDropdown::on_brightnessSlider_sliderMoved(int position)
{
QProcess* backlight = new QProcess(this);
backlight->start("xbacklight -set " + QString::number(position));
connect(backlight, SIGNAL(finished(int)), backlight, SLOT(deleteLater()));
}
void InfoPaneDropdown::on_brightnessSlider_valueChanged(int value)
{
on_brightnessSlider_sliderMoved(value);
}
void InfoPaneDropdown::on_settingsList_currentRowChanged(int currentRow)
{
ui->settingsTabs->setCurrentIndex(currentRow);
//Set up settings
if (ui->settingsTabs->currentWidget() == ui->NotificationsSettings) { //Notifications
setupNotificationsSettingsPane();
} else if (currentRow == 5) { //Location
setupLocationSettingsPane();
} else if (currentRow == ui->settingsTabs->indexOf(ui->UserSettings)) { //Users
setupUsersSettingsPane();
} else if (currentRow == ui->settingsTabs->indexOf(ui->DateTimeSettings)) { //Date and Time
setupDateTimeSettingsPane();
}
}
void InfoPaneDropdown::setupNotificationsSettingsPane() {
ui->AppNotifications->clear();
QStringList knownApplications;
int amount = d->notificationAppSettings->beginReadArray("notifications/knownApplications");
for (int i = 0; i < amount; i++) {
d->notificationAppSettings->setArrayIndex(i);
knownApplications.append(d->notificationAppSettings->value("appname").toString());
}
d->notificationAppSettings->endArray();
for (QString app : knownApplications) {
QListWidgetItem* item = new QListWidgetItem();
item->setText(app);
ui->AppNotifications->addItem(item);
}
}
void InfoPaneDropdown::on_settingsTabs_currentChanged(int arg1)
{
ui->settingsList->item(arg1)->setSelected(true);
}
void InfoPaneDropdown::on_lockScreenBackgroundBrowse_clicked()
{
QFileDialog dialog(this);
dialog.setAcceptMode(QFileDialog::AcceptOpen);
dialog.setNameFilter("Images (*.jpg *.jpeg *.bmp *.png *.gif *.svg)");
if (dialog.exec() == QDialog::Accepted) {
d->lockScreenSettings->setValue("background", dialog.selectedFiles().first());
ui->lockScreenBackground->setText(dialog.selectedFiles().first());
}
}
void InfoPaneDropdown::on_lockScreenBackground_textEdited(const QString &arg1)
{
d->lockScreenSettings->setValue("background", arg1);
}
void InfoPaneDropdown::on_TextSwitch_toggled(bool checked)
{
d->settings.setValue("bar/showText", checked);
}
void InfoPaneDropdown::on_windowManager_textEdited(const QString &arg1)
{
d->settings.setValue("startup/WindowManagerCommand", arg1);
}
void InfoPaneDropdown::on_barDesktopsSwitch_toggled(bool checked)
{
d->settings.setValue("bar/showWindowsFromOtherDesktops", checked);
}
void InfoPaneDropdown::on_SuperkeyGatewaySwitch_toggled(bool checked)
{
d->settings.setValue("input/superkeyGateway", checked);
}
void InfoPaneDropdown::reject() {
this->close();
}
void InfoPaneDropdown::on_endSessionConfirmFullScreen_toggled(bool checked)
{
if (checked) {
d->settings.setValue("ui/useFullScreenEndSession", true);
}
}
void InfoPaneDropdown::on_endSessionConfirmInMenu_toggled(bool checked)
{
if (checked) {
d->settings.setValue("ui/useFullScreenEndSession", false);
}
}
void InfoPaneDropdown::on_pageStack_switchingFrame(int switchTo)
{
QWidget* switchingWidget = ui->pageStack->widget(switchTo);
ui->clockLabel->setShowDisabled(true);
ui->batteryLabel->setShowDisabled(true);
//ui->printLabel->setShowDisabled(true);
if (switchingWidget == d->overviewFrame) {
ui->clockLabel->setShowDisabled(false);
} else if (switchingWidget == ui->statusFrame) {
ui->batteryLabel->setShowDisabled(false);
/*} else if (switchingWidget == ui->printFrame) {
ui->printLabel->setShowDisabled(false);*/
}
}
void InfoPaneDropdown::on_showNotificationsContents_toggled(bool checked)
{
if (checked) {
d->settings.setValue("notifications/lockScreen", "contents");
}
}
void InfoPaneDropdown::on_showNotificationsOnly_toggled(bool checked)
{
if (checked) {
d->settings.setValue("notifications/lockScreen", "noContents");
}
}
void InfoPaneDropdown::on_showNotificationsNo_toggled(bool checked)
{
if (checked) {
d->settings.setValue("notifications/lockScreen", "none");
}
}
void InfoPaneDropdown::on_MediaSwitch_toggled(bool checked)
{
d->settings.setValue("notifications/mediaInsert", checked);
}
void InfoPaneDropdown::on_lightColorThemeRadio_toggled(bool checked)
{
if (checked) {
d->themeSettings->setValue("color/type", "light");
updateAccentColourBox();
resetStyle();
changeDropDown(Settings, false);
}
}
void InfoPaneDropdown::on_darkColorThemeRadio_toggled(bool checked)
{
if (checked) {
d->themeSettings->setValue("color/type", "dark");
updateAccentColourBox();
resetStyle();
changeDropDown(Settings, false);
}
}
void InfoPaneDropdown::on_themeButtonColor_currentIndexChanged(int index)
{
d->themeSettings->setValue("color/accent", index);
resetStyle();
}
void InfoPaneDropdown::on_systemFont_currentFontChanged(const QFont &f)
{
d->themeSettings->setValue("fonts/defaultFamily", f.family());
d->themeSettings->setValue("fonts/smallFamily", f.family());
ui->systemFontSize->setValue(d->themeSettings->value("font/defaultSize", 10).toInt());
//ui->systemFont->setFont(QFont(d->themeSettings->value("font/defaultFamily", defaultFont).toString(), d->themeSettings->value("font/defaultSize", 10).toInt()));
}
void InfoPaneDropdown::on_batteryChartUpdateButton_clicked()
{
updateBatteryChart();
}
//DBus Battery Info Structure
struct BatteryInfo {
uint time, state;
double value;
};
Q_DECLARE_METATYPE(BatteryInfo)
const QDBusArgument &operator<<(QDBusArgument &argument, const BatteryInfo &info) {
argument.beginStructure();
argument << info.time << info.value << info.state;
argument.endStructure();
return argument;
}
const QDBusArgument &operator>>(const QDBusArgument &argument, BatteryInfo &info) {
argument.beginStructure();
argument >> info.time >> info.value >> info.state;
argument.endStructure();
return argument;
}
//DBus WakeupsInfo Structure
struct WakeupsInfo {
bool process = false;
uint pid;
double wakeups;
QString path, description;
};
Q_DECLARE_METATYPE(WakeupsInfo)
const QDBusArgument &operator<<(QDBusArgument &argument, const WakeupsInfo &info) {
argument.beginStructure();
argument << info.process << info.pid << info.wakeups << info.path << info.description;
argument.endStructure();
return argument;
}
const QDBusArgument &operator>>(const QDBusArgument &argument, WakeupsInfo &info) {
argument.beginStructure();
argument >> info.process >> info.pid >> info.wakeups >> info.path >> info.description;
argument.endStructure();
return argument;
}
void InfoPaneDropdown::updateBatteryChart() {
if (ui->appsGraphButton->isChecked()) {
QDBusMessage dataMessage = QDBusMessage::createMethodCall("org.freedesktop.UPower", "/org/freedesktop/UPower/Wakeups", "org.freedesktop.UPower.Wakeups", "GetData");
QDBusReply<QDBusArgument> dataMessageArgument = QDBusConnection::systemBus().call(dataMessage);
QList<WakeupsInfo> wakeups;
if (dataMessageArgument.isValid()) {
QDBusArgument arrayArgument = dataMessageArgument.value();
arrayArgument.beginArray();
while (!arrayArgument.atEnd()) {
WakeupsInfo info;
arrayArgument >> info;
if (info.process) {
int min = 0, max = wakeups.count();
int insertIndex;
while (max != min) {
insertIndex = ((max - min) / 2) + min;
if (wakeups.at(insertIndex).wakeups == info.wakeups) { //Goes here
break;
} else if (wakeups.at(insertIndex).wakeups < info.wakeups) { //Needs to go on left hand side
max = insertIndex - 1;
} else if (wakeups.at(insertIndex).wakeups > info.wakeups) { //Needs to go on right hand side
min = insertIndex + 1;
}
}
wakeups.insert(insertIndex, info);
}
}
arrayArgument.endArray();
ui->appsGraph->clear();
for (WakeupsInfo wakeup : wakeups) {
QListWidgetItem* item = new QListWidgetItem;
item->setText("[" + QString::number(wakeup.pid) + "] " + wakeup.path + " (" + wakeup.description + ")");
ui->appsGraph->insertItem(0, item);
}
}
} else {
for (QAbstractAxis* axis : d->batteryChart->axes()) {
d->batteryChart->removeAxis(axis);
axis->deleteLater();
}
QDBusMessage historyMessage = QDBusMessage::createMethodCall("org.freedesktop.UPower", updbus->defaultBattery().path(), "org.freedesktop.UPower.Device", "GetHistory");
QVariantList historyMessageArguments;
if (ui->chargeGraphButton->isChecked()) {
historyMessageArguments.append("charge");
} else {
historyMessageArguments.append("rate");
}
historyMessageArguments.append((uint) 0); //Get surplus data so we can plot some data off the left of the graph
historyMessageArguments.append((uint) 10000);
historyMessage.setArguments(historyMessageArguments);
QDBusReply<QDBusArgument> historyArgument = QDBusConnection::systemBus().call(historyMessage);
QLineSeries* batteryChartData = new QLineSeries;
QPen dataPen;
dataPen.setColor(this->palette().color(QPalette::Highlight));
dataPen.setWidth(2 * getDPIScaling());
batteryChartData->setPen(dataPen);
QLineSeries* batteryChartTimeRemainingData = new QLineSeries;
//batteryChartTimeRemainingData->setColor(this->palette().color(QPalette::Disabled, QPalette::WindowText));
batteryChartTimeRemainingData->setBrush(QBrush(this->palette().color(QPalette::Disabled, QPalette::WindowText)));
QPen remainingTimePen;
remainingTimePen.setColor(this->palette().color(QPalette::Disabled, QPalette::Highlight));
remainingTimePen.setDashPattern(QVector<qreal>() << 3 << 3);
remainingTimePen.setDashOffset(3);
remainingTimePen.setWidth(2 * getDPIScaling());
batteryChartTimeRemainingData->setPen(remainingTimePen);
QDateTime remainingTime = updbus->batteryTimeRemaining();
int firstDateTime = QDateTime::currentSecsSinceEpoch() / 60;
qint64 msecsSinceFull = -1;
uint lastState = -1;
bool takeNextSinceLastFull = false;
if (historyArgument.isValid()) {
const QDBusArgument arrayArgument = historyArgument.value();
arrayArgument.beginArray();
while (!arrayArgument.atEnd()) {
BatteryInfo info;
arrayArgument >> info;
qint64 msecs = info.time;
msecs = msecs * 1000;
if (info.value >= 90 && info.state == 2 && lastState == 1 && msecsSinceFull < msecs) {
takeNextSinceLastFull = true;
} else if (takeNextSinceLastFull) {
takeNextSinceLastFull = false;
msecsSinceFull = msecs;
}
lastState = info.state;
if (info.value != 0 && info.state != 0) {
batteryChartData->append(msecs, info.value);
if (firstDateTime > info.time / 60) {
firstDateTime = info.time / 60;
}
}
}
arrayArgument.endArray();
batteryChartData->append(QDateTime::currentMSecsSinceEpoch(), batteryChartData->at(batteryChartData->count() - 1).y());
if (remainingTime.isValid() && ui->batteryChartShowProjected->isChecked() && ui->chargeGraphButton->isChecked()) {
QDateTime lastDateTime = QDateTime::fromMSecsSinceEpoch(batteryChartData->at(batteryChartData->count() - 1).x());
batteryChartTimeRemainingData->append(batteryChartData->at(batteryChartData->count() - 1));
QDateTime endDateTime = lastDateTime.addMSecs(remainingTime.toMSecsSinceEpoch());
if (updbus->charging()) {
batteryChartTimeRemainingData->append(endDateTime.toMSecsSinceEpoch(), 100);
} else {
batteryChartTimeRemainingData->append(endDateTime.toMSecsSinceEpoch(), 0);
}
}
}
d->batteryChart->removeAllSeries();
d->batteryChart->addSeries(batteryChartData);
d->batteryChart->addSeries(batteryChartTimeRemainingData);
d->xAxis = new QDateTimeAxis;
if (ui->chargeGraphButton->isChecked()) {
if (remainingTime.isValid() && ui->batteryChartShowProjected->isChecked()) {
d->xAxis->setMax(QDateTime::fromMSecsSinceEpoch(batteryChartData->at(batteryChartData->count() - 1).x()).addMSecs(remainingTime.toMSecsSinceEpoch()));
} else {
d->xAxis->setMax(QDateTime::currentDateTime());
}
QDateTime oneDay = d->xAxis->max().addDays(-1);
if (msecsSinceFull == -1 || msecsSinceFull < oneDay.toMSecsSinceEpoch()) {
d->xAxis->setMin(oneDay);
} else {
d->xAxis->setMin(QDateTime::fromMSecsSinceEpoch(msecsSinceFull));
}
} else {
d->xAxis->setMax(QDateTime::currentDateTime());
d->xAxis->setMin(d->xAxis->max().addSecs(-43200)); //Half a day
}
d->batteryChart->addAxis(d->xAxis, Qt::AlignBottom);
d->xAxis->setLabelsColor(this->palette().color(QPalette::WindowText));
d->xAxis->setFormat("hh:mm");
d->xAxis->setTickCount(9);
batteryChartData->attachAxis(d->xAxis);
batteryChartTimeRemainingData->attachAxis(d->xAxis);
/*connect(xAxis, &QDateTimeAxis::rangeChanged, [=](QDateTime min, QDateTime max) {
ui->BatteryChargeScrollBar->setMaximum(max.toMSecsSinceEpoch() - min.toMSecsSinceEpoch());
});*/
d->chartScrolling = true;
int currentSecsSinceEpoch = QDateTime::currentSecsSinceEpoch();
ui->BatteryChargeScrollBar->setMinimum(0);
ui->BatteryChargeScrollBar->setMaximum(currentSecsSinceEpoch / 60 - firstDateTime);
ui->BatteryChargeScrollBar->setValue(currentSecsSinceEpoch / 60 - firstDateTime);
d->startValue = currentSecsSinceEpoch / 60 - firstDateTime;
d->chartScrolling = false;
QValueAxis* yAxis = new QValueAxis;
if (ui->chargeGraphButton->isChecked()) {
yAxis->setLabelFormat("%i%%");
yAxis->setMax(100);
} else {
yAxis->setLabelFormat("%i W");
yAxis->setMax(40);
}
yAxis->setMin(0);
yAxis->setLabelsColor(this->palette().color(QPalette::WindowText));
d->batteryChart->addAxis(yAxis, Qt::AlignLeft);
batteryChartData->attachAxis(yAxis);
batteryChartTimeRemainingData->attachAxis(yAxis);
ui->batteryChartLastUpdate->setText(tr("Last updated %1").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
}
}
void InfoPaneDropdown::on_batteryChartShowProjected_toggled(bool checked)
{
Q_UNUSED(checked)
updateBatteryChart();
}
void InfoPaneDropdown::on_upArrow_clicked()
{
this->close();
}
void InfoPaneDropdown::on_PowerStretchSwitch_toggled(bool checked)
{
updbus->setPowerStretch(checked);
emit batteryStretchChanged(checked);
}
void InfoPaneDropdown::doNetworkCheck() {
if (updbus->powerStretch()) {
//Always set networkOk to ok because we don't update when power stretch is on
d->networkOk = Ok;
} else {
//Do some network checks to see if network is working
QDBusInterface i("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager", QDBusConnection::systemBus(), this);
int connectivity = i.property("Connectivity").toUInt();
if (connectivity == 2) {
if (d->networkOk != BehindPortal) {
//Notify user that they are behind a portal.
//Wait 10 seconds for startup or for connection notification
QTimer::singleShot(10000, [=] {
QStringList actions;
actions.append("login");
actions.append(tr("Log in to network"));
QVariantMap hints;
hints.insert("category", "network.connected");
hints.insert("transient", true);
NotificationsDBusAdaptor::Notify("theShell", 0, "", tr("Network Login"),
tr("Your connection to the internet is blocked by a login page."),
actions, hints, 30000)->then([=](uint notificationId) {
connect(NotificationsDBusAdaptor::instance(), &NotificationsDBusAdaptor::ActionInvoked, [=](uint id, QString key) {
if (notificationId == id && key == "login") {
QProcess::startDetached("xdg-open http://nmcheck.gnome.org/");
}
});
});
});
}
d->networkOk = BehindPortal;
//Reload the connectivity status
i.asyncCall("CheckConnectivity");
return;
} else if (connectivity == 3) {
d->networkOk = Unspecified;
//Reload the connectivity status
i.asyncCall("CheckConnectivity");
return;
} else {
d->networkOk = Ok;
}
if (d->mgr.networkAccessible() == QNetworkAccessManager::NotAccessible) {
d->networkOk = Unspecified;
//Reload the connectivity status
i.asyncCall("CheckConnectivity");
return;
}
//For some reason this crashes theShell so let's not do this (for now)
/*connect(manager, &QNetworkAccessManager::finished, [=](QNetworkReply* reply) {
if (reply->error() != QNetworkReply::NoError) {
networkOk = false;
} else {
networkOk = true;
}
manager->deleteLater();
});
manager->get(QNetworkRequest(QUrl("http://vicr123.github.io/")));*/
//Reload the connectivity status
i.asyncCall("CheckConnectivity");
}
}
void InfoPaneDropdown::dragDown(dropdownType showWith, int y) {
changeDropDown(showWith, false);
QRect screenGeometry = QApplication::desktop()->screenGeometry();
if (d->settings.value("bar/onTop", true).toBool()) {
this->setGeometry(screenGeometry.x(), screenGeometry.y() - screenGeometry.height() + y, screenGeometry.width(), screenGeometry.height() + 1);
} else {
this->setGeometry(screenGeometry.x(), screenGeometry.top() + y + screenGeometry.y(), screenGeometry.width(), screenGeometry.height() + 1);
}
Atom DesktopWindowTypeAtom;
DesktopWindowTypeAtom = XInternAtom(QX11Info::display(), "_NET_WM_WINDOW_TYPE_NORMAL", False);
XChangeProperty(QX11Info::display(), this->winId(), XInternAtom(QX11Info::display(), "_NET_WM_WINDOW_TYPE", False),
XA_ATOM, 32, PropModeReplace, (unsigned char*) &DesktopWindowTypeAtom, 1); //Change Window Type
unsigned long desktop = 0xFFFFFFFF;
XChangeProperty(QX11Info::display(), this->winId(), XInternAtom(QX11Info::display(), "_NET_WM_DESKTOP", False),
XA_CARDINAL, 32, PropModeReplace, (unsigned char*) &desktop, 1); //Set visible on all desktops
QDialog::show();
this->setFixedWidth(screenGeometry.width());
if (tVirtualKeyboard::instance()->keyboardVisible()) {
this->setFixedHeight(screenGeometry.height() - tVirtualKeyboard::instance()->height());
} else {
this->setFixedHeight(screenGeometry.height() + 1);
}
//Get Current Brightness
QProcess* backlight = new QProcess(this);
backlight->start("xbacklight -get");
backlight->waitForFinished();
float output = ceil(QString(backlight->readAll()).toFloat());
delete backlight;
ui->brightnessSlider->setValue((int) output);
d->previousDrags.prepend(y);
if (d->previousDrags.count() > 10) d->previousDrags.removeLast();
}
void InfoPaneDropdown::completeDragDown() {
QRect screenGeometry = QApplication::desktop()->screenGeometry();
if (d->previousDrags.isEmpty() || (QCursor::pos().y() - screenGeometry.top() < d->previousDrags.last() && d->settings.value("bar/onTop", true).toBool()) ||
(QCursor::pos().y() - screenGeometry.top() > d->previousDrags.last() && !d->settings.value("bar/onTop", true).toBool())) {
this->close();
} else {
tPropertyAnimation* a = new tPropertyAnimation(this, "geometry");
a->setStartValue(this->geometry());
a->setEndValue(QRect(screenGeometry.x(), screenGeometry.y() - (d->settings.value("bar/onTop", true).toBool() ? 0 : 1), this->width(), screenGeometry.height() + 1));
a->setEasingCurve(QEasingCurve::OutCubic);
a->setDuration(500);
connect(a, SIGNAL(finished()), a, SLOT(deleteLater()));
a->start();
}
d->previousDrags.clear();
}
void InfoPaneDropdown::on_notificationSoundBox_currentIndexChanged(int index)
{
QSoundEffect* sound = new QSoundEffect();
switch (index) {
case 0:
d->settings.setValue("notifications/sound", "tripleping");
sound->setSource(QUrl("qrc:/sounds/notifications/tripleping.wav"));
break;
case 1:
d->settings.setValue("notifications/sound", "upsidedown");
sound->setSource(QUrl("qrc:/sounds/notifications/upsidedown.wav"));
break;
case 2:
d->settings.setValue("notifications/sound", "echo");
sound->setSource(QUrl("qrc:/sounds/notifications/echo.wav"));
break;
}
sound->play();
connect(sound, SIGNAL(playingChanged()), sound, SLOT(deleteLater()));
}
void InfoPaneDropdown::setupUsersSettingsPane() {
ui->availableUsersWidget->clear();
QDBusMessage getUsersMessage = QDBusMessage::createMethodCall("org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts", "ListCachedUsers");
QDBusReply<QList<QDBusObjectPath>> allUsers = QDBusConnection::systemBus().call(getUsersMessage);
if (allUsers.isValid()) {
for (QDBusObjectPath obj : allUsers.value()) {
QDBusInterface interface("org.freedesktop.Accounts", obj.path(), "org.freedesktop.Accounts.User", QDBusConnection::systemBus());
QListWidgetItem* item = new QListWidgetItem();
QString name = interface.property("RealName").toString();
if (name == "") {
name = interface.property("UserName").toString();
}
item->setText(name);
item->setIcon(QIcon::fromTheme("user"));
item->setData(Qt::UserRole, obj.path());
ui->availableUsersWidget->addItem(item);
}
QListWidgetItem* item = new QListWidgetItem();
item->setIcon(QIcon::fromTheme("list-add"));
item->setText(tr("Add New User"));
item->setData(Qt::UserRole, "new");
ui->availableUsersWidget->addItem(item);
}
}
void InfoPaneDropdown::on_userSettingsNextButton_clicked()
{
if (ui->availableUsersWidget->selectedItems().count() != 0) {
//Check Polkit authorization
PolkitQt1::Authority::Result r = PolkitQt1::Authority::instance()->checkAuthorizationSync("org.freedesktop.accounts.user-administration", PolkitQt1::UnixProcessSubject(QApplication::applicationPid()), PolkitQt1::Authority::None);
if (r == PolkitQt1::Authority::No) {
QMessageBox::warning(this, tr("Unauthorized"), tr("Polkit does not allow you to manage users on the system."), QMessageBox::Ok, QMessageBox::Ok);
return;
} else if (r == PolkitQt1::Authority::Challenge) {
LOWER_INFOPANE
PolkitQt1::Authority::Result r = PolkitQt1::Authority::instance()->checkAuthorizationSync("org.freedesktop.accounts.user-administration", PolkitQt1::UnixProcessSubject(QApplication::applicationPid()), PolkitQt1::Authority::AllowUserInteraction);
if (r != PolkitQt1::Authority::Yes) {
return;
}
}
d->editingUserPath = ui->availableUsersWidget->selectedItems().first()->data(Qt::UserRole).toString();
if (d->editingUserPath == "new") {
ui->userSettingsEditUserLabel->setText(tr("New User"));
ui->userSettingsFullName->setText("");
ui->userSettingsUserName->setText("");
ui->userSettingsPassword->setPlaceholderText(tr("(none)"));
ui->userSettingsPasswordCheck->setPlaceholderText(tr("(none)"));
ui->userSettingsDeleteUser->setVisible(false);
ui->userSettingsStandardAccount->setChecked(true);
ui->userSettingsAdminAccount->setChecked(false);
} else {
ui->userSettingsEditUserLabel->setText(tr("Edit User"));
QDBusInterface interface("org.freedesktop.Accounts", d->editingUserPath, "org.freedesktop.Accounts.User", QDBusConnection::systemBus());
int passwordMode = interface.property("PasswordMode").toInt();
if (passwordMode == 0) {
ui->userSettingsPassword->setPlaceholderText(tr("(unchanged)"));
ui->userSettingsPasswordCheck->setPlaceholderText(tr("(unchanged)"));
} else if (passwordMode == 1) {
ui->userSettingsPassword->setPlaceholderText(tr("(set at next login)"));
ui->userSettingsPasswordCheck->setPlaceholderText(tr("(set at next login)"));
} else {
ui->userSettingsPassword->setPlaceholderText(tr("(none)"));
ui->userSettingsPasswordCheck->setPlaceholderText(tr("(none)"));
}
if (interface.property("AccountType").toInt() == 0) {
ui->userSettingsStandardAccount->setChecked(true);
ui->userSettingsAdminAccount->setChecked(false);
} else {
ui->userSettingsStandardAccount->setChecked(false);
ui->userSettingsAdminAccount->setChecked(true);
}
ui->userSettingsFullName->setText(interface.property("RealName").toString());
ui->userSettingsUserName->setText(interface.property("UserName").toString());
ui->userSettingsPasswordHint->setText(interface.property("PasswordHint").toString());
ui->userSettingsDeleteUser->setVisible(true);
}
ui->userSettingsPassword->setText("");
ui->userSettingsPasswordCheck->setText("");
ui->userSettingsStackedWidget->setCurrentIndex(1);
}
}
void InfoPaneDropdown::on_userSettingsCancelButton_clicked()
{
ui->userSettingsStackedWidget->setCurrentIndex(0);
}
void InfoPaneDropdown::on_userSettingsApplyButton_clicked()
{
if (ui->userSettingsPasswordCheck->text() != ui->userSettingsPassword->text()) {
QMessageBox::warning(this, tr("Password Check"), tr("The passwords don't match."), QMessageBox::Ok, QMessageBox::Ok);
return;
}
if (ui->userSettingsUserName->text().contains(" ")) {
QMessageBox::warning(this, tr("Username"), tr("The username must not contain spaces."), QMessageBox::Ok, QMessageBox::Ok);
return;
}
if (ui->userSettingsUserName->text().toLower() != ui->userSettingsUserName->text()) {
QMessageBox::warning(this, tr("Username"), tr("The username must not contain capital letters."), QMessageBox::Ok, QMessageBox::Ok);
return;
}
if (d->editingUserPath == "new") {
QDBusMessage createMessage = QDBusMessage::createMethodCall("org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts", "CreateUser");
QVariantList args;
args.append(ui->userSettingsUserName->text());
args.append(ui->userSettingsFullName->text());
args.append(0);
createMessage.setArguments(args);
QDBusReply<QDBusObjectPath> newUser = QDBusConnection::systemBus().call(createMessage);
if (newUser.error().isValid()) {
tToast* toast = new tToast();
toast->setTitle("Couldn't create user");
toast->setText(newUser.error().message());
connect(toast, SIGNAL(dismissed()), toast, SLOT(deleteLater()));
toast->show(this);
return;
} else {
d->editingUserPath = newUser.value().path();
}
}
QDBusInterface interface("org.freedesktop.Accounts", d->editingUserPath, "org.freedesktop.Accounts.User", QDBusConnection::systemBus());
QDBusMessage setUserNameMessage = interface.call("SetUserName", ui->userSettingsUserName->text());
if (setUserNameMessage.errorMessage() != "") {
tToast* toast = new tToast();
toast->setTitle("Couldn't create user");
toast->setText(setUserNameMessage.errorMessage());
connect(toast, SIGNAL(dismissed()), toast, SLOT(deleteLater()));
toast->show(this);
return;
}
interface.call("SetRealName", ui->userSettingsFullName->text());
if (ui->userSettingsAdminAccount->isChecked()) {
interface.call("SetAccountType", 1);
} else {
interface.call("SetAccountType", 0);
}
if (ui->userSettingsPassword->text() != "") {
interface.call("SetPasswordMode", 0);
//Crypt password
QByteArray characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz./";
QByteArray salt("$6$");
for (int i = 0; i < 16; i++) {
salt.append(characters.at((qrand() % characters.count())));
}
QString cryptedPassword = QString::fromLatin1(crypt(ui->userSettingsPassword->text().toUtf8(), salt.constData()));
interface.call("SetPassword", cryptedPassword, ui->userSettingsPasswordHint->text());
} else {
if (d->editingUserPath == "new") {
interface.call("SetPasswordMode", 2);
interface.call("SetPasswordHint", ui->userSettingsPasswordHint->text());
}
}
setupUsersSettingsPane();
ui->userSettingsStackedWidget->setCurrentIndex(0);
}
void InfoPaneDropdown::on_userSettingsFullName_textEdited(const QString &arg1)
{
ui->userSettingsUserName->setText(arg1.toLower().split(" ").first());
}
void InfoPaneDropdown::on_userSettingsDeleteUser_clicked()
{
ui->userSettingsStackedWidget->setCurrentIndex(2);
}
void InfoPaneDropdown::on_userSettingsCancelDeleteUser_clicked()
{
ui->userSettingsStackedWidget->setCurrentIndex(1);
}
void InfoPaneDropdown::on_userSettingsDeleteUserOnly_clicked()
{
QDBusInterface interface("org.freedesktop.Accounts", d->editingUserPath, "org.freedesktop.Accounts.User", QDBusConnection::systemBus());
qlonglong uid = interface.property("Uid").toLongLong();
QDBusMessage deleteMessage = QDBusMessage::createMethodCall("org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts", "DeleteUser");
QVariantList args;
args.append(uid);
args.append(false);
deleteMessage.setArguments(args);
QDBusConnection::systemBus().call(deleteMessage);
setupUsersSettingsPane();
ui->userSettingsStackedWidget->setCurrentIndex(0);
}
void InfoPaneDropdown::on_userSettingsDeleteUserAndData_clicked()
{
QDBusInterface interface("org.freedesktop.Accounts", d->editingUserPath, "org.freedesktop.Accounts.User", QDBusConnection::systemBus());
qlonglong uid = interface.property("Uid").toLongLong();
QDBusMessage deleteMessage = QDBusMessage::createMethodCall("org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts", "DeleteUser");
QVariantList args;
args.append(uid);
args.append(true);
deleteMessage.setArguments(args);
QDBusConnection::systemBus().call(deleteMessage);
setupUsersSettingsPane();
ui->userSettingsStackedWidget->setCurrentIndex(0);
}
void InfoPaneDropdown::setupDateTimeSettingsPane() {
launchDateTimeService();
QDateTime current = QDateTime::currentDateTime();
ui->dateTimeSetDate->setSelectedDate(current.date());
ui->dateTimeSetTime->setTime(current.time());
QDBusInterface dateTimeInterface("org.freedesktop.timedate1", "/org/freedesktop/timedate1", "org.freedesktop.timedate1", QDBusConnection::systemBus());
bool isNTPEnabled = dateTimeInterface.property("NTP").toBool();
ui->DateTimeNTPSwitch->setChecked(isNTPEnabled);
}
void InfoPaneDropdown::launchDateTimeService() {
QDBusMessage getMessage = QDBusMessage::createMethodCall("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "ListActivatableNames");
QDBusReply<QStringList> reply = QDBusConnection::systemBus().call(getMessage);
if (!reply.value().contains("org.freedesktop.timedate1")) {
qDebug() << "Can't set date and time";
return;
}
QDBusConnection::systemBus().interface()->startService("org.freedesktop.timedate1");
}
void InfoPaneDropdown::on_dateTimeSetDateTimeButton_clicked()
{
QDateTime newTime;
newTime.setDate(ui->dateTimeSetDate->selectedDate());
newTime.setTime(ui->dateTimeSetTime->time());
qlonglong time = newTime.toMSecsSinceEpoch() * 1000;
launchDateTimeService();
QDBusMessage setMessage = QDBusMessage::createMethodCall("org.freedesktop.timedate1", "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "SetTime");
QVariantList args;
args.append(time);
args.append(false);
args.append(true);
setMessage.setArguments(args);
QDBusConnection::systemBus().call(setMessage);
setupDateTimeSettingsPane();
}
void InfoPaneDropdown::on_DateTimeNTPSwitch_toggled(bool checked)
{
if (checked) {
ui->dateTimeSetDate->setEnabled(false);
ui->dateTimeSetTime->setEnabled(false);
ui->dateTimeSetDateTimeButton->setEnabled(false);
} else {
ui->dateTimeSetDate->setEnabled(true);
ui->dateTimeSetTime->setEnabled(true);
ui->dateTimeSetDateTimeButton->setEnabled(true);
}
launchDateTimeService();
QDBusMessage setMessage = QDBusMessage::createMethodCall("org.freedesktop.timedate1", "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "SetNTP");
QVariantList args;
args.append(checked);
args.append(true);
setMessage.setArguments(args);
QDBusConnection::systemBus().call(setMessage);
setupDateTimeSettingsPane();
}
void InfoPaneDropdown::on_localeList_currentRowChanged(int currentRow)
{
if (currentRow == -1) return;
//Show the splash screen (if available)
emit dbusSignals->ShowSplash();
d->settings.setValue("locale/language", ui->localeList->item(currentRow)->data(Qt::UserRole).toString());
QString localeName = d->settings.value("locale/language", "en_US").toString();
qputenv("LANGUAGE", localeName.toUtf8());
QLocale defaultLocale(localeName);
QLocale::setDefault(defaultLocale);
if (defaultLocale.language() == QLocale::Arabic || defaultLocale.language() == QLocale::Hebrew) {
//Reverse the layout direction
QApplication::setLayoutDirection(Qt::RightToLeft);
} else {
//Set normal layout direction
QApplication::setLayoutDirection(Qt::LeftToRight);
}
qtTranslator->load("qt_" + defaultLocale.name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
QApplication::installTranslator(qtTranslator);
if (defaultLocale.name() == "C") {
tsTranslator->load(localeName, QString(SHAREDIR) + "translations");
} else {
tsTranslator->load(defaultLocale.name(), QString(SHAREDIR) + "translations");
}
QApplication::installTranslator(tsTranslator);
//Tell all plugins to update translator
for (StatusCenterPane* plugin : d->loadedPlugins) {
plugin->loadLanguage(defaultLocale.name());
}
//Process all events
QApplication::processEvents();
//Hide the splash screen since the language change is complete
emit dbusSignals->HideSplash();
}
void InfoPaneDropdown::on_StatusBarSwitch_toggled(bool checked)
{
d->settings.setValue("bar/statusBar", checked);
updateStruts();
ui->AutoShowBarLabel->setEnabled(checked);
ui->AutoShowBarSwitch->setEnabled(checked);
ui->AutoShowBarExplanation->setEnabled(checked);
}
void InfoPaneDropdown::on_TouchInputSwitch_toggled(bool checked)
{
d->settings.setValue("input/touch", checked);
}
void InfoPaneDropdown::on_SuspendLockScreen_toggled(bool checked)
{
d->settings.setValue("lockScreen/showOnSuspend", checked);
}
void InfoPaneDropdown::on_BatteryChargeScrollBar_valueChanged(int value)
{
if (!d->chartScrolling) {
d->chartScrolling = true;
d->batteryChart->scroll(value - d->startValue, 0);
d->startValue = value;
d->chartScrolling = false;
}
}
void InfoPaneDropdown::on_chargeGraphButton_clicked()
{
ui->chargeGraphButton->setChecked(true);
ui->rateGraphButton->setChecked(false);
ui->appsGraphButton->setChecked(false);
ui->batteryGraphStack->setCurrentIndex(0);
ui->batteryChartHeader->setText(tr("Charge History"));
ui->batteryChartShowProjected->setVisible(true);
updateBatteryChart();
}
void InfoPaneDropdown::on_rateGraphButton_clicked()
{
ui->chargeGraphButton->setChecked(false);
ui->rateGraphButton->setChecked(true);
ui->appsGraphButton->setChecked(false);
ui->batteryGraphStack->setCurrentIndex(0);
ui->batteryChartHeader->setText(tr("Rate History"));
ui->batteryChartShowProjected->setVisible(false);
updateBatteryChart();
}
void InfoPaneDropdown::on_appsGraphButton_clicked()
{
ui->chargeGraphButton->setChecked(false);
ui->rateGraphButton->setChecked(false);
ui->appsGraphButton->setChecked(true);
ui->batteryGraphStack->setCurrentIndex(1);
ui->batteryChartHeader->setText(tr("Application Power Usage"));
ui->batteryChartShowProjected->setVisible(false);
updateBatteryChart();
}
void InfoPaneDropdown::on_LargeTextSwitch_toggled(bool checked)
{
d->themeSettings->setValue("accessibility/largeText", checked);
}
void InfoPaneDropdown::on_HighContrastSwitch_toggled(bool checked)
{
d->themeSettings->setValue("accessibility/highcontrast", checked);
setHeaderColour(QColor(0, 100, 255));
}
void InfoPaneDropdown::on_systemAnimationsAccessibilitySwitch_toggled(bool checked)
{
d->themeSettings->setValue("accessibility/systemAnimations", checked);
}
void InfoPaneDropdown::on_CapsNumLockBellSwitch_toggled(bool checked)
{
d->themeSettings->setValue("accessibility/bellOnCapsNumLock", checked);
}
void InfoPaneDropdown::on_FlightSwitch_toggled(bool checked)
{
//Set flags that persist between changes
d->settings.setValue("flightmode/on", checked);
if (checked) {
//Tell everyone that we're going into flight mode
d->broadcastMessage("flight-mode-changed", {true});
} else {
//Tell everyone that we're leaving flight mode
d->broadcastMessage("flight-mode-changed", {false});
}
emit flightModeChanged(checked);
//Don't disable the switch as they may be switched on during flight
}
void InfoPaneDropdown::on_TwentyFourHourSwitch_toggled(bool checked)
{
d->settings.setValue("time/use24hour", checked);
}
void InfoPaneDropdown::on_systemIconTheme_currentIndexChanged(int index)
{
d->themeSettings->setValue("icons/theme", ui->systemIconTheme->itemData(index).toString());
}
void InfoPaneDropdown::on_AttenuateSwitch_toggled(bool checked)
{
d->settings.setValue("notifications/attenuate", checked);
}
void InfoPaneDropdown::on_BarOnBottom_toggled(bool checked)
{
d->settings.setValue("bar/onTop", !checked);
updateStruts();
}
void InfoPaneDropdown::updateStruts() {
emit updateStrutsSignal();
if (d->settings.value("bar/onTop", true).toBool()) {
((QBoxLayout*) this->layout())->setDirection(QBoxLayout::TopToBottom);
((QBoxLayout*) ui->partFrame->layout())->setDirection(QBoxLayout::TopToBottom);
((QBoxLayout*) ui->settingsFrame->layout())->setDirection(QBoxLayout::TopToBottom);
ui->upArrow->setPixmap(QIcon::fromTheme("go-up").pixmap(16 * getDPIScaling(), 16 * getDPIScaling()));
} else {
((QBoxLayout*) this->layout())->setDirection(QBoxLayout::BottomToTop);
((QBoxLayout*) ui->partFrame->layout())->setDirection(QBoxLayout::BottomToTop);
((QBoxLayout*) ui->settingsFrame->layout())->setDirection(QBoxLayout::BottomToTop);
ui->upArrow->setPixmap(QIcon::fromTheme("go-down").pixmap(16 * getDPIScaling(), 16 * getDPIScaling()));
}
}
void InfoPaneDropdown::on_systemWidgetTheme_currentIndexChanged(int index)
{
d->themeSettings->setValue("style/name", ui->systemWidgetTheme->itemData(index).toString());
resetStyle();
}
void InfoPaneDropdown::resetStyle() {
emit dbusSignals->ThemeChanged();
}
void InfoPaneDropdown::on_decorativeColorThemeRadio_toggled(bool checked)
{
if (checked) {
d->themeSettings->setValue("color/type", "decorative");
updateAccentColourBox();
resetStyle();
}
}
void InfoPaneDropdown::on_SoundFeedbackSoundSwitch_toggled(bool checked) {
d->settings.setValue("sound/feedbackSound", checked);
}
void InfoPaneDropdown::on_VolumeOverdriveSwitch_toggled(bool checked) {
d->settings.setValue("sound/volumeOverdrive", checked);
}
void InfoPaneDropdown::updateAccentColourBox() {
//Set up theme button combo box
int themeAccentColorIndex = d->themeSettings->value("color/accent", 0).toInt();
ui->themeButtonColor->clear();
if (d->themeSettings->value("color/type", "dark") == "decorative") {
if (themeAccentColorIndex > 1) themeAccentColorIndex = 0;
ui->themeButtonColor->addItem(tr("Oxygen"));
ui->themeButtonColor->addItem(tr("Breeze"));
} else {
if (themeAccentColorIndex > 4) themeAccentColorIndex = 0;
ui->themeButtonColor->addItem(tr("Blue"));
ui->themeButtonColor->addItem(tr("Green"));
ui->themeButtonColor->addItem(tr("Orange"));
ui->themeButtonColor->addItem(tr("Pink"));
ui->themeButtonColor->addItem(tr("Turquoise"));
ui->themeButtonColor->setCurrentIndex(themeAccentColorIndex);
}
}
void InfoPaneDropdown::on_dpi100_toggled(bool checked)
{
if (checked) {
d->settings.setValue("screen/dpi", 96);
}
}
void InfoPaneDropdown::on_dpi150_toggled(bool checked)
{
if (checked) {
d->settings.setValue("screen/dpi", 144);
}
}
void InfoPaneDropdown::on_dpi200_toggled(bool checked)
{
if (checked) {
d->settings.setValue("screen/dpi", 192);
}
}
void InfoPaneDropdown::on_dpi300_toggled(bool checked)
{
if (checked) {
d->settings.setValue("screen/dpi", 288);
}
}
void InfoPaneDropdown::on_AutoShowBarSwitch_toggled(bool checked)
{
d->settings.setValue("bar/autoshow", checked);
}
void InfoPaneDropdown::on_userSettingsAdminAccount_toggled(bool checked)
{
if (checked) {
ui->userSettingsStandardAccount->setChecked(false);
ui->userSettingsAdminAccount->setChecked(true);
}
}
void InfoPaneDropdown::on_userSettingsStandardAccount_toggled(bool checked)
{
if (checked) {
ui->userSettingsStandardAccount->setChecked(true);
ui->userSettingsAdminAccount->setChecked(false);
}
}
void InfoPaneDropdown::updateAutostart() {
ui->autostartList->clear();
QDir autostartDir(QDir::homePath() + "/.config/autostart");
for (QString fileName : autostartDir.entryList(QDir::NoDotAndDotDot | QDir::Files)) {
QString file = QDir::homePath() + "/.config/autostart/" + fileName;
QFile autostartFile(file);
autostartFile.open(QFile::ReadOnly);
QString data = autostartFile.readAll();
autostartFile.close();
QString name = fileName;
QString icon = "";
bool enabled = true;
bool validEntry = true;
for (QString line : data.split("\n")) {
QString data = line.mid(line.indexOf("=") + 1);
if (line.startsWith("name=", Qt::CaseInsensitive)) {
name = data;
} else if (line.startsWith("onlyshowin=", Qt::CaseInsensitive)) {
if (!data.contains("theshell", Qt::CaseInsensitive)) {
validEntry = false;
}
} else if (line.startsWith("notshowin=", Qt::CaseInsensitive)) {
if (data.contains("theshell", Qt::CaseInsensitive)) {
validEntry = false;
}
} else if (line.startsWith("hidden=", Qt::CaseInsensitive)) {
if (data.toLower() == "true") {
enabled = false;
}
} else if (line.startsWith("icon=")) {
icon = data;
}
}
if (validEntry) {
QListWidgetItem* item = new QListWidgetItem();
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
if (enabled) {
item->setCheckState(Qt::Checked);
} else {
item->setCheckState(Qt::Unchecked);
}
if (icon != "") {
item->setIcon(QIcon::fromTheme(icon));
}
item->setText(name);
item->setData(Qt::UserRole, file);
ui->autostartList->addItem(item);
}
}
}
void InfoPaneDropdown::on_autostartList_itemChanged(QListWidgetItem *item)
{
QFile file(item->data(Qt::UserRole).toString());
file.open(QFile::ReadOnly);
QString data = file.readAll();
file.close();
QString rewriteData;
for (QString line : data.split("\n")) {
if (!line.startsWith("hidden", Qt::CaseInsensitive)) {
rewriteData.append(line + "\n");
}
}
if (item->checkState() == Qt::Unchecked) {
rewriteData.append("Hidden=true\n");
}
file.open(QFile::WriteOnly);
file.write(rewriteData.toUtf8());
file.close();
this->updateAutostart();
}
void InfoPaneDropdown::on_backAutoStartApps_clicked()
{
ui->startupStack->setCurrentIndex(0);
}
void InfoPaneDropdown::on_pushButton_4_clicked()
{
ui->startupStack->setCurrentIndex(1);
AppsListModel* appsListModel = new AppsListModel();
ui->autostartAppList->setModel(appsListModel);
ui->autostartAppList->setItemDelegate(new AppsDelegate(nullptr, false));
}
void InfoPaneDropdown::on_backAutoStartNewApp_clicked()
{
ui->startupStack->setCurrentIndex(1);
}
void InfoPaneDropdown::on_autostartAppList_clicked(const QModelIndex &index)
{
App app = index.data(Qt::UserRole + 3).value<App>();
ui->autostartAppName->setText(app.name());
ui->autostartAppCommand->setText(app.command().trimmed());
ui->autostartInTheshell->setChecked(false);
ui->startupStack->setCurrentIndex(2);
}
void InfoPaneDropdown::on_enterCommandAutoStartApps_clicked()
{
ui->autostartAppName->setText("");
ui->autostartAppCommand->setText("");
ui->autostartInTheshell->setChecked(false);
ui->startupStack->setCurrentIndex(2);
}
void InfoPaneDropdown::on_addAutostartApp_clicked()
{
QString desktopEntryData;
desktopEntryData.append("[Desktop Entry]\n");
desktopEntryData.append("Type=Application\n");
desktopEntryData.append("Version=1.0\n");
desktopEntryData.append("Name=" + ui->autostartAppName->text() + "\n");
desktopEntryData.append("Exec=" + ui->autostartAppCommand->text() + "\n");
desktopEntryData.append("Terminal=false\n");
if (ui->autostartInTheshell->isChecked()) {
desktopEntryData.append("OnlyShowIn=theshell;");
}
QFile desktopEntry(QDir::homePath() + "/.config/autostart/" + ui->autostartAppName->text().toLower().replace(" ", "_").append(".desktop"));
if (desktopEntry.exists()) {
if (QMessageBox::warning(this, "Autostart Definition", "There is already an autostart definition for this app. Do you want to overwrite it?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) {
return;
}
}
desktopEntry.open(QFile::WriteOnly);
desktopEntry.write(desktopEntryData.toUtf8());
desktopEntry.close();
updateAutostart();
ui->startupStack->setCurrentIndex(0);
}
void InfoPaneDropdown::on_redshiftSwitch_toggled(bool checked)
{
if (d->effectiveRedshiftOn) {
if (checked) { //Turn Redshift back on
d->overrideRedshift = 0;
} else { //Temporarily disable Redshift
d->overrideRedshift = 1;
}
} else {
if (checked) { //Temporarily enable Redshift
d->overrideRedshift = 2;
} else { //Turn Redshift back off
d->overrideRedshift = 0;
}
}
}
void InfoPaneDropdown::on_grayColorThemeRadio_toggled(bool checked)
{
if (checked) {
d->themeSettings->setValue("color/type", "gray");
updateAccentColourBox();
resetStyle();
changeDropDown(Settings, false);
}
}
void InfoPaneDropdown::on_AppNotifications_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
if (current == NULL) {
ui->appNotificationsPane->setEnabled(false);
ui->appNotificationsConfigureLock->setVisible(false);
} else {
ui->appNotificationsTitle->setText(tr("Notifications for %1").arg(current->text()));
ui->appAllowNotifications->setChecked(d->notificationAppSettings->value(current->text() + "/allow", true).toBool());
ui->appAllowSounds->setChecked(d->notificationAppSettings->value(current->text() + "/sounds", true).toBool());
ui->appAllowPopup->setChecked(d->notificationAppSettings->value(current->text() + "/popup", true).toBool());
ui->appBypassQuiet->setChecked(d->notificationAppSettings->value(current->text() + "/bypassQuiet", false).toBool());
if (current->text() == "theShell") {
ui->appNotificationsPane->setEnabled(false);
ui->appNotificationsConfigureLock->setText(tr("You can't configure notifications for %1").arg(current->text()));
ui->appNotificationsConfigureLock->setVisible(true);
} else {
ui->appNotificationsPane->setEnabled(true);
ui->appNotificationsConfigureLock->setVisible(false);
}
}
}
void InfoPaneDropdown::on_appAllowNotifications_toggled(bool checked)
{
if (ui->AppNotifications->currentItem() != NULL) {
d->notificationAppSettings->setValue(ui->AppNotifications->currentItem()->text() + "/allow", checked);
}
}
void InfoPaneDropdown::on_appAllowSounds_toggled(bool checked)
{
if (ui->AppNotifications->currentItem() != NULL) {
d->notificationAppSettings->setValue(ui->AppNotifications->currentItem()->text() + "/sounds", checked);
}
}
void InfoPaneDropdown::on_appAllowPopup_toggled(bool checked)
{
if (ui->AppNotifications->currentItem() != NULL) {
d->notificationAppSettings->setValue(ui->AppNotifications->currentItem()->text() + "/popup", checked);
}
}
void InfoPaneDropdown::on_appBypassQuiet_toggled(bool checked)
{
if (ui->AppNotifications->currentItem() != NULL) {
d->notificationAppSettings->setValue(ui->AppNotifications->currentItem()->text() + "/bypassQuiet", checked);
}
}
void InfoPaneDropdown::on_SetSystemTimezoneButton_clicked()
{
ui->TimezoneStackedWidget->setCurrentIndex(1);
launchDateTimeService();
QDBusInterface dateTimeInterface("org.freedesktop.timedate1", "/org/freedesktop/timedate1", "org.freedesktop.timedate1", QDBusConnection::systemBus());
QString currentTimezone = dateTimeInterface.property("Timezone").toString();
d->timezoneData = QJsonObject();
ui->timezoneList->clear();
QFile tzInfo("/usr/share/zoneinfo/zone.tab");
tzInfo.open(QFile::ReadOnly);
while (!tzInfo.atEnd()) {
QString tzLine = tzInfo.readLine();
if (!tzLine.startsWith("#")) {
QStringList parts = tzLine.trimmed().split("\t", QString::SkipEmptyParts);
if (parts.length() >= 3) {
QString region = parts.at(2).left(parts.at(2).indexOf("/"));
QString city = parts.at(2).mid(parts.at(2).indexOf("/") + 1);
if (!d->timezoneData.contains(region)) {
QListWidgetItem* i = new QListWidgetItem();
i->setText(region);
ui->timezoneList->addItem(i);
d->timezoneData.insert(region, QJsonArray());
}
QJsonObject cityData;
cityData.insert("name", city);
cityData.insert("country", parts.at(0).toLower());
cityData.insert("descriptor", parts.at(2));
if (parts.at(2) == currentTimezone) {
cityData.insert("selected", true);
} else {
cityData.insert("selected", false);
}
QJsonArray a = d->timezoneData.value(region).toArray();
a.append(cityData);
d->timezoneData.insert(region, a);
}
}
}
tzInfo.close();
ui->setTimezoneButton->setEnabled(false);
ui->timezoneCityList->clear();
}
void InfoPaneDropdown::on_backTimezone_clicked()
{
ui->TimezoneStackedWidget->setCurrentIndex(0);
}
void InfoPaneDropdown::on_setTimezoneButton_clicked()
{
ui->TimezoneStackedWidget->setCurrentIndex(0);
//Set the timezone
LOWER_INFOPANE
launchDateTimeService();
QDBusInterface dateTimeInterface("org.freedesktop.timedate1", "/org/freedesktop/timedate1", "org.freedesktop.timedate1", QDBusConnection::systemBus());
QDBusPendingCallWatcher* w = new QDBusPendingCallWatcher(dateTimeInterface.asyncCall("SetTimezone", ui->timezoneCityList->currentItem()->data(Qt::UserRole), true));
connect(w, SIGNAL(finished(QDBusPendingCallWatcher*)), w, SLOT(deleteLater()));
connect(w, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(updateDSTNotification()));
}
void InfoPaneDropdown::on_timezoneList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
ui->timezoneCityList->clear();
if (current != nullptr) {
QJsonArray a = d->timezoneData.value(current->text()).toArray();
for (QJsonValue v : a) {
QListWidgetItem* i = new QListWidgetItem();
QJsonObject cityData = v.toObject();
i->setText(cityData.value("name").toString().replace("_", " "));
i->setData(Qt::UserRole, cityData.value("descriptor").toString());
i->setIcon(QIcon::fromTheme("flag-" + cityData.value("country").toString(), QIcon::fromTheme("flag")));
ui->timezoneCityList->addItem(i);
if (cityData.value("selected").toBool()) {
i->setSelected(true);
}
}
}
}
void InfoPaneDropdown::on_timezoneCityList_currentRowChanged(int currentRow)
{
if (currentRow == -1) {
ui->setTimezoneButton->setEnabled(false);
} else {
ui->setTimezoneButton->setEnabled(true);
}
}
void InfoPaneDropdown::on_batteryScreenOff_valueChanged(int value)
{
d->settings.setValue("power/batteryScreenOff", value);
if (value == 121) {
ui->batteryScreenOffLabel->setText(tr("Never"));
} else {
ui->batteryScreenOffLabel->setText(tr("%n min(s)", NULL, value));
}
}
void InfoPaneDropdown::on_batterySuspend_valueChanged(int value)
{
d->settings.setValue("power/batterySuspend", value);
if (value == 121) {
ui->batterySuspendLabel->setText(tr("Never"));
} else {
ui->batterySuspendLabel->setText(tr("%n min(s)", NULL, value));
}
}
void InfoPaneDropdown::on_powerScreenOff_valueChanged(int value)
{
d->settings.setValue("power/powerScreenOff", value);
if (value == 121) {
ui->powerScreenOffLabel->setText(tr("Never"));
} else {
ui->powerScreenOffLabel->setText(tr("%n min(s)", NULL, value));
}
}
void InfoPaneDropdown::on_powerSuspend_valueChanged(int value)
{
d->settings.setValue("power/powerSuspend", value);
if (value == 121) {
ui->powerSuspendLabel->setText(tr("Never"));
} else {
ui->powerSuspendLabel->setText(tr("%n min(s)", NULL, value));
}
}
void InfoPaneDropdown::on_removeAutostartButton_clicked()
{
if (ui->autostartList->currentItem() != nullptr) {
tToast* toast = new tToast();
toast->setText("Autostart item has been removed.");
toast->setTitle("Remove Autostart Item");
QMap<QString, QString> actions;
actions.insert("undo", "Undo");
toast->setActions(actions);
QListWidgetItem* i = ui->autostartList->takeItem(ui->autostartList->currentIndex().row());
bool* deleteItem = new bool(true);
connect(toast, &tToast::dismissed, [=] {
if (*deleteItem) {
QFile(i->data(Qt::UserRole).toString()).remove();
delete i;
}
delete deleteItem;
toast->deleteLater();
});
connect(toast, &tToast::actionClicked, [=](QString key) {
*deleteItem = false;
ui->autostartList->addItem(i);
});
toast->show(this);
}
}
void InfoPaneDropdown::on_resetDeviceButton_clicked()
{
QProcess::startDetached("scallop --reset");
this->close();
}
void InfoPaneDropdown::changeEvent(QEvent *event) {
if (event->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
for (int i = 0; i < d->loadedSettingsPlugins.count(); i++) {
ui->settingsList->item(d->pluginsSettingsStartIndex + i)->setText(d->loadedSettingsPlugins.at(i)->name());
}
int currentTranslateIndex = d->pluginsSettingsStartIndex + d->loadedSettingsPlugins.count();
if (ui->settingsTabs->indexOf(ui->UnavailablePanesPage) != -1) {
ui->settingsList->item(currentTranslateIndex)->setText(tr("Unavailable Panes"));
currentTranslateIndex++;
}
ui->settingsList->item(currentTranslateIndex)->setText(tr("Advanced"));
currentTranslateIndex++;
ui->settingsList->item(currentTranslateIndex)->setText(tr("About"));
currentTranslateIndex++;
}
QDialog::changeEvent(event);
}
void InfoPaneDropdown::on_sunlightRedshift_toggled(bool checked)
{
d->settings.setValue("display/redshiftSunlightCycle", checked);
updateRedshiftTime();
}
void InfoPaneDropdown::updateRedshiftTime() {
if (!d->settings.value("display/redshiftSunlightCycle", false).toBool()) {
//Don't grab location if user doesn't want
ui->startRedshift->setEnabled(true);
ui->endRedshift->setEnabled(true);
return;
}
ui->startRedshift->setEnabled(false);
ui->endRedshift->setEnabled(false);
geolocation->singleShot()->then([=](Geolocation loc) {
QNetworkAccessManager* manager = new QNetworkAccessManager();
QNetworkRequest sunriseApi(QUrl(QString("https://api.sunrise-sunset.org/json?lat=%1&lng=%2&formatted=0").arg(loc.latitude).arg(loc.longitude)));
sunriseApi.setHeader(QNetworkRequest::UserAgentHeader, QString("theShell/%1").arg(TS_VERSION));
QNetworkReply* reply = manager->get(sunriseApi);
connect(reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error),
[=](QNetworkReply::NetworkError code){
qDebug() << "Error";
});
connect(reply, &QNetworkReply::finished, [=] {
QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
QJsonObject root = doc.object();
if (root.value("status").toString() != "OK") {
qDebug() << root.value("status").toString();
return;
}
//The time returned should be midway into the transition period, add/remove 30 minutes to compensate
QJsonObject results = root.value("results").toObject();
QDateTime sunrise = QDateTime::fromString(results.value("sunrise").toString(), Qt::ISODate).toLocalTime().addSecs(-1800);
QDateTime sunset = QDateTime::fromString(results.value("sunset").toString(), Qt::ISODate).toLocalTime().addSecs(1800);
ui->startRedshift->setDateTime(sunset);
ui->endRedshift->setDateTime(sunrise);
reply->deleteLater();
manager->deleteLater();
});
});
}
void InfoPaneDropdown::paintEvent(QPaintEvent *event) {
QPainter painter(this);
painter.setPen(this->palette().color(QPalette::WindowText));
if (d->settings.value("bar/onTop", true).toBool()) {
painter.drawLine(0, this->height() - 1, this->width(), this->height() - 1);
} else {
painter.drawLine(0, 0, this->width(), 0);
}
event->accept();
}
void InfoPaneDropdown::on_systemGTK3Theme_currentIndexChanged(int index)
{
d->gtk3Settings->setValue("Settings/gtk-theme-name", ui->systemGTK3Theme->itemText(index));
}
void InfoPaneDropdown::on_systemFontSize_valueChanged(int arg1)
{
d->themeSettings->setValue("font/defaultSize", arg1);
}
void InfoPaneDropdown::on_systemGTK3Font_currentFontChanged(const QFont &f)
{
d->gtk3Settings->setValue("Settings/gtk-font-name", f.family() + " " + QString::number(ui->systemGTK3FontSize->value()));
}
void InfoPaneDropdown::on_systemGTK3FontSize_valueChanged(int arg1)
{
d->gtk3Settings->setValue("Settings/gtk-font-name", ui->systemGTK3Font->currentFont().family() + " " + QString::number(arg1));
}
void InfoPaneDropdown::on_useSystemFontForGTKButton_clicked()
{
ui->systemGTK3Font->setCurrentFont(ui->systemFont->currentFont());
ui->systemGTK3FontSize->setValue(ui->systemFontSize->value());
}
void InfoPaneDropdown::setHeaderColour(QColor col) {
if (ui->HighContrastSwitch->isChecked()) {
ui->partFrame->setPalette(QApplication::palette(ui->partFrame));
} else {
QPalette pal = ui->partFrame->palette();
tVariantAnimation* anim = new tVariantAnimation();
anim->setStartValue(pal.color(QPalette::Window));
anim->setEndValue(col);
anim->setDuration(250);
anim->setEasingCurve(QEasingCurve::OutCubic);
connect(anim, &tVariantAnimation::valueChanged, [=](QVariant value) {
QPalette pal = ui->partFrame->palette();
QColor col = value.value<QColor>();
pal.setColor(QPalette::Window, col);
//if ((col.red() + col.green() + col.blue()) / 3 < 127) {
pal.setColor(QPalette::WindowText, Qt::white);
pal.setColor(QPalette::Disabled, QPalette::WindowText, col.lighter(150));
/*} else {
pal.setColor(QPalette::WindowText, Qt::black);
pal.setColor(QPalette::Disabled, QPalette::WindowText, col.darker(150));
}*/
ui->partFrame->setPalette(pal);
pal.setColor(QPalette::Window, col.lighter(120));
ui->pushButton_7->setPalette(pal);
for (int i = 0; i < ui->InformationalPluginsLayout->count(); i++) {
ClickableLabel* l = (ClickableLabel*) ui->InformationalPluginsLayout->itemAt(i)->widget();
l->setShowDisabled(l->showDisabled());
}
});
connect(anim, SIGNAL(finished()), anim, SLOT(deleteLater()));
anim->start();
}
}
bool InfoPaneDropdown::eventFilter(QObject *obj, QEvent *e) {
if (obj == ui->partFrame) {
if (e->type() == QEvent::Paint) {
QPainter p(ui->partFrame);
QPalette pal = ui->partFrame->palette();
p.setRenderHint(QPainter::Antialiasing);
p.setBrush(pal.color(QPalette::Window));
p.setPen(Qt::transparent);
p.drawRect(0, 0, ui->partFrame->width(), ui->partFrame->height());
if (QApplication::layoutDirection() == Qt::RightToLeft) {
int width = ui->partFrame->width();
QPolygonF firstPoly;
firstPoly.append(QPointF(width - d->slice1.currentValue().toFloat(), 0));
firstPoly.append(QPointF(width - d->slice2.currentValue().toFloat(), ui->partFrame->height()));
firstPoly.append(QPointF(0, ui->partFrame->height()));
firstPoly.append(QPointF(0, 0));
p.setBrush(pal.color(QPalette::Window).lighter(110));
p.drawPolygon(firstPoly);
QPolygonF secondPoly;
secondPoly.append(QPointF(width - ui->partFrame->width() * 0.85, 0));
secondPoly.append(QPointF(width - ui->partFrame->width() * 0.825, ui->partFrame->height()));
secondPoly.append(QPointF(0, ui->partFrame->height()));
secondPoly.append(QPointF(0, 0));
p.setBrush(pal.color(QPalette::Window).lighter(120));
p.drawPolygon(secondPoly);
} else {
QPolygonF firstPoly;
firstPoly.append(QPointF(d->slice1.currentValue().toFloat(), 0));
firstPoly.append(QPointF(d->slice2.currentValue().toFloat(), ui->partFrame->height()));
firstPoly.append(QPointF(ui->partFrame->width(), ui->partFrame->height()));
firstPoly.append(QPointF(ui->partFrame->width(), 0));
p.setBrush(pal.color(QPalette::Window).lighter(110));
p.drawPolygon(firstPoly);
QPolygonF secondPoly;
secondPoly.append(QPointF(ui->partFrame->width() * 0.85, 0));
secondPoly.append(QPointF(ui->partFrame->width() * 0.825, ui->partFrame->height()));
secondPoly.append(QPointF(ui->partFrame->width(), ui->partFrame->height()));
secondPoly.append(QPointF(ui->partFrame->width(), 0));
p.setBrush(pal.color(QPalette::Window).lighter(120));
p.drawPolygon(secondPoly);
}
return true;
}
}
return false;
}
void InfoPaneDropdown::on_EmphasiseAppSwitch_toggled(bool checked)
{
d->settings.setValue("notifications/emphasiseApp", checked);
}
void InfoPaneDropdown::on_CompactBarSwitch_toggled(bool checked)
{
if (d->settings.value("bar/compact") != checked) {
d->settings.setValue("bar/compact", checked);
QMap<QString, QString> actions;
actions.insert("logout", tr("Log Out Now"));
tToast* t = new tToast();
t->setTitle(tr("Logoff Required"));
if (checked) {
t->setText(tr("In order to enable the Compact Bar, you'll need to log out and then log back on."));
} else {
t->setText(tr("In order to disable the Compact Bar, you'll need to log out and then log back on."));
}
t->setActions(actions);
t->setTimeout(10000);
connect(t, &tToast::actionClicked, [=](QString key) {
if (key == "logout") {
EndSession(EndSessionWait::logout);
}
});
connect(t, SIGNAL(dismissed()), t, SLOT(deleteLater()));
t->show(this);
}
}
void InfoPaneDropdown::keyPressEvent(QKeyEvent *event) {
}
void InfoPaneDropdown::on_blackColorThemeRadio_toggled(bool checked)
{
if (checked) {
d->themeSettings->setValue("color/type", "black");
updateAccentColourBox();
resetStyle();
changeDropDown(Settings, false);
}
}
void InfoPaneDropdown::changeSettingsPane(int pane) {
ui->settingsList->setCurrentRow(pane);
}
void InfoPaneDropdown::on_allowGeoclueAgent_clicked()
{
//Automatically edit the geoclue file
LOWER_INFOPANE
QProcess::execute("pkexec sed \"/whitelist=.*/ s/$/;theshell/\" -i /etc/geoclue/geoclue.conf");
locationServices->reloadAuthorizationRequired();
QTimer::singleShot(500, [=] {
on_settingsList_currentRowChanged(6);
});
}
void InfoPaneDropdown::on_LocationMasterSwitch_toggled(bool checked)
{
d->locationSettings->setValue("master/master", checked);
}
void InfoPaneDropdown::setupLocationSettingsPane() {
if (locationServices->requiresAuthorization()) {
ui->locationStack->setCurrentIndex(0);
} else {
ui->locationStack->setCurrentIndex(1);
ui->LocationAppsList->clear();
QStringList availableApps = d->locationSettings->childGroups();
availableApps.removeOne("master");
for (QString app : availableApps) {
d->locationSettings->beginGroup(app);
bool allow = d->locationSettings->value("allow").toBool();
App a = App::invalidApp();
if (QFile("/usr/share/applications/" + app + ".desktop").exists()) {
a = AppsListModel::readAppFile("/usr/share/applications/" + app + ".desktop");
} else if (QFile(QDir::homePath() + "/.local/share/applications" + app + ".desktop").exists()) {
a = AppsListModel::readAppFile(QDir::homePath() + "/.local/share/applications" + app + ".desktop");
}
QListWidgetItem* i = new QListWidgetItem();
if (a.invalid()) {
i->setText(app);
} else {
i->setIcon(a.icon());
i->setText(a.name());
}
i->setFlags(i->flags() | Qt::ItemIsUserCheckable);
if (allow) {
i->setCheckState(Qt::Checked);
} else {
i->setCheckState(Qt::Unchecked);
}
i->setData(Qt::UserRole, app);
ui->LocationAppsList->addItem(i);
d->locationSettings->endGroup();
}
}
}
void InfoPaneDropdown::on_LocationAppsList_itemChanged(QListWidgetItem *item)
{
if (item->checkState() == Qt::Checked) {
d->locationSettings->setValue(item->data(Qt::UserRole).toString() + "/allow", true);
} else {
d->locationSettings->setValue(item->data(Qt::UserRole).toString() + "/allow", false);
}
}
void InfoPaneDropdown::loadNewKeyboardLayoutMenu() {
//Check to see if current keyboard layout is included in list, and if not, select first
QString currentLayout = d->settings.value("input/currentLayout", "us(basic)").toString();
QStringList currentLayouts = d->settings.value("input/layout", "us(basic)").toString().split(",");
if (!currentLayouts.contains(currentLayout)) {
setKeyboardLayout(currentLayouts.first());
return;
}
QStringList selectedLayouts = d->settings.value("input/layout", "us(basic)").toString().split(",");
if (selectedLayouts.count() == 1) {
emit newKeyboardLayoutMenuAvailable(nullptr);
} else {
QMenu* menu = new QMenu();
menu->addSection(tr("Keyboard Layout"));
for (QString item : selectedLayouts) {
QAction* action = menu->addAction(d->keyboardLayouts.value(item), [=] {
setKeyboardLayout(item);
});
action->setCheckable(true);
if (item == currentLayout) {
action->setChecked(true);
}
}
emit newKeyboardLayoutMenuAvailable(menu);
}
QApplication::processEvents();
}
void InfoPaneDropdown::setKeyboardLayout(QString layout) {
d->settings.setValue("input/currentLayout", layout);
QProcess::startDetached("setxkbmap " + layout);
loadNewKeyboardLayoutMenu();
emit keyboardLayoutChanged(layout.split("(").first().toUpper());
}
QString InfoPaneDropdown::setNextKeyboardLayout() {
QString currentLayout = d->settings.value("input/currentLayout", "us(basic)").toString();
QStringList currentLayouts = d->settings.value("input/layout", "us(basic)").toString().split(",");
int currentIndex = currentLayouts.indexOf(currentLayout);
currentIndex++;
if (currentIndex == currentLayouts.count()) currentIndex = 0;
QString layout = currentLayouts.at(currentIndex);
QTimer::singleShot(0, [=] {
setKeyboardLayout(layout);
});
return d->keyboardLayouts.value(layout);
}
void InfoPaneDropdown::on_setupMousePassword_clicked()
{
//Check Polkit authorization
PolkitQt1::Authority::Result r = PolkitQt1::Authority::instance()->checkAuthorizationSync("org.thesuite.theshell.configure-mouse-password", PolkitQt1::UnixProcessSubject(QApplication::applicationPid()), PolkitQt1::Authority::None);
if (r == PolkitQt1::Authority::No) {
QMessageBox::warning(this, tr("Unauthorized"), tr("Polkit does not allow you to set up a mouse password."), QMessageBox::Ok, QMessageBox::Ok);
return;
} else if (r == PolkitQt1::Authority::Challenge) {
LOWER_INFOPANE
PolkitQt1::Authority::Result r = PolkitQt1::Authority::instance()->checkAuthorizationSync("org.thesuite.theshell.configure-mouse-password", PolkitQt1::UnixProcessSubject(QApplication::applicationPid()), PolkitQt1::Authority::AllowUserInteraction);
if (r != PolkitQt1::Authority::Yes) {
return;
}
}
ui->lockScreenStack->setCurrentIndex(1);
}
void InfoPaneDropdown::on_removeMousePassword_clicked()
{
if (QMessageBox::question(this, tr("Remove Mouse Password?"), tr("Do you want to remove the Mouse Password for this account?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) {
//Check Polkit authorization
PolkitQt1::Authority::Result r = PolkitQt1::Authority::instance()->checkAuthorizationSync("org.thesuite.theshell.configure-mouse-password", PolkitQt1::UnixProcessSubject(QApplication::applicationPid()), PolkitQt1::Authority::None);
if (r == PolkitQt1::Authority::No) {
QMessageBox::warning(this, tr("Unauthorized"), tr("Polkit does not allow you to set up a mouse password."), QMessageBox::Ok, QMessageBox::Ok);
return;
} else if (r == PolkitQt1::Authority::Challenge) {
LOWER_INFOPANE
PolkitQt1::Authority::Result r = PolkitQt1::Authority::instance()->checkAuthorizationSync("org.thesuite.theshell.configure-mouse-password", PolkitQt1::UnixProcessSubject(QApplication::applicationPid()), PolkitQt1::Authority::AllowUserInteraction);
if (r != PolkitQt1::Authority::Yes) {
return;
}
}
//Remove the mouse password
QProcess* proc = new QProcess();
QDir::home().mkdir(".theshell");
QString executable = "/usr/lib/ts-mousepass-change";
#ifdef BLUEPRINT
executable += "b";
#endif
proc->start(executable + " --remove --passfile=" + QDir::homePath() + "/.theshell/mousepassword");
proc->waitForFinished();
if (proc->exitCode() == 0) {
tToast* toast = new tToast();
toast->setTitle(tr("Mouse Password"));
toast->setText(tr("Mouse Password was removed successfully"));
connect(toast, SIGNAL(dismissed()), toast, SLOT(deleteLater()));
toast->show(this);
} else {
tToast* toast = new tToast();
toast->setTitle(tr("Mouse Password"));
toast->setText(tr("Mouse Password couldn't be removed"));
connect(toast, SIGNAL(dismissed()), toast, SLOT(deleteLater()));
toast->show(this);
}
proc->deleteLater();
}
}
void InfoPaneDropdown::on_MousePasswordSetup_exit()
{
ui->lockScreenStack->setCurrentIndex(0);
if (QFile(QDir::homePath() + "/.theshell/mousepassword").exists()) {
ui->removeMousePassword->setVisible(true);
} else {
ui->removeMousePassword->setVisible(false);
}
}
void InfoPaneDropdown::on_websiteButton_clicked()
{
QProcess::startDetached("xdg-open https://vicr123.github.io/theshell");
this->close();
}
void InfoPaneDropdown::on_bugButton_clicked()
{
QProcess::startDetached("xdg-open https://github.com/vicr123/theshell/issues");
this->close();
}
void InfoPaneDropdown::on_distroWebpage_clicked()
{
QProcess::startDetached("xdg-open " + ui->distroWebpage->text());
this->close();
}
void InfoPaneDropdown::on_distroSupport_clicked()
{
QProcess::startDetached("xdg-open " + ui->distroSupport->text());
this->close();
}
void InfoPaneDropdown::on_sourcesButton_clicked()
{
QProcess::startDetached("xdg-open https://github.com/vicr123/theshell");
this->close();
}
void InfoPaneDropdown::pluginMessage(QString message, QVariantList args, StatusCenterPaneObject* caller) {
if (message == "main-menu") {
if (ui->settingsListContainer->width() == 0) pluginMessage("show-menu", QVariantList(), caller);
ui->settingsListStack->setCurrentIndex(0);
} else if (message == "hide-menu") {
tVariantAnimation* anim = new tVariantAnimation();
anim->setStartValue(ui->settingsListContainer->width());
anim->setEndValue(0);
anim->setDuration(500);
anim->setEasingCurve(QEasingCurve::OutCubic);
connect(anim, &tVariantAnimation::valueChanged, [=](QVariant value) {
ui->settingsListContainer->setFixedWidth(value.toInt());
});
anim->start(tVariantAnimation::DeleteWhenStopped);
} else if (message == "show-menu") {
tVariantAnimation* anim = new tVariantAnimation();
anim->setStartValue(ui->settingsListContainer->width());
anim->setEndValue((int) (250 * getDPIScaling()));
anim->setDuration(500);
anim->setEasingCurve(QEasingCurve::OutCubic);
connect(anim, &tVariantAnimation::valueChanged, [=](QVariant value) {
ui->settingsListContainer->setFixedWidth(value.toInt());
});
anim->start(tVariantAnimation::DeleteWhenStopped);
} else if (message == "register-switch") {
uint thisSwitchId = d->numberOfSwitches;
d->numberOfSwitches++;
QBoxLayout* layout = new QBoxLayout(QBoxLayout::LeftToRight);
QFrame* line = new QFrame();
line->setFrameShape(QFrame::VLine);
line->setFrameShadow(QFrame::Sunken);
layout->addWidget(line);
QLabel* switchLabel = new QLabel();
switchLabel->setText(args.first().toString());
layout->addWidget(switchLabel);
Switch* s = new Switch();
connect(s, &Switch::toggled, [=](bool checked) {
caller->message("switch-toggled", QVariantList() << thisSwitchId << checked);
});
connect(s, &Switch::destroyed, [=] {
ui->customSwitches->removeItem(layout);
switchLabel->deleteLater();
line->deleteLater();
});
if (args.count() >= 2) {
s->setChecked(args.at(1).toBool());
}
layout->addWidget(s);
d->pluginSwitches.insert(thisSwitchId, s);
ui->customSwitches->addLayout(layout);
if (args.count() >= 3) {
caller->message("switch-registered", QVariantList() << thisSwitchId << args.at(2));
} else {
caller->message("switch-registered", QVariantList() << thisSwitchId << args.first().toString());
}
} else if (message == "toggle-switch") {
Switch* s = d->pluginSwitches.value(args.first().toUInt());
s->setChecked(args.last().toBool());
} else if (message == "set-switch") {
Switch* s = d->pluginSwitches.value(args.first().toUInt());
s->setChecked(args.at(1).toBool());
} else if (message == "deregister-switch") {
d->pluginSwitches.value(args.first().toUInt())->deleteLater();
} else if (message == "attenuate") {
if (args.first() == true) {
AudioMan->attenuateStreams();
} else {
AudioMan->restoreStreams();
}
} else if (message == "location") {
geolocation->singleShot()->then([=](Geolocation loc) {
caller->message("location", QVariantList() << loc.latitude << loc.longitude);
});
} else if (message == "jobDone") {
emit statusBarProgressFinished(args.first().toString(), args.at(1).toString());
} else if (message == "jobUpdate") {
emit statusBarProgress(args.first().toString(), args.at(1).toString(), args.at(2).toUInt());
} else if (message == "set-quiet-mode") {
AudioMan->setQuietMode((AudioManager::quietMode) args.first().toInt());
} else if (message == "show") {
if (caller->type() == StatusCenterPaneObject::Informational) {
this->show(None);
this->changeDropDown(caller->mainWidget(), d->pluginLabels.value(caller), false);
if (ui->lightColorThemeRadio->isChecked()) {
setHeaderColour(caller->informationalAttributes.lightColor);
} else {
setHeaderColour(caller->informationalAttributes.darkColor);
}
} else {
this->show(Settings);
int row = ui->settingsTabs->indexOf(caller->mainWidget());
ui->settingsList->setCurrentRow(row);
on_settingsList_itemActivated(ui->settingsList->item(row));
}
} else if (message == "register-chunk") {
emit newChunk(args.first().value<QWidget*>());
} else if (message == "register-snack") {
emit newSnack(args.first().value<QWidget*>());
} else if (message == "reload-keyboard-layouts") {
loadNewKeyboardLayoutMenu();
}
}
QVariant InfoPaneDropdown::pluginProperty(QString key) {
if (key == "current-quiet-mode-description") {
return AudioMan->getCurrentQuietModeDescription();
}
return QVariant();
}
void InfoPaneDropdown::on_settingsList_itemActivated(QListWidgetItem *item)
{
QVariant setting = item->data(Qt::UserRole);
if (!setting.isNull() && setting.toInt() != -1) {
QWidget* settingWidget = ui->settingsListStack->widget(setting.toInt());
if (!settingWidget->property("STATUSCENTER_notavailable").toBool()) {
ui->settingsListStack->setCurrentIndex(setting.toInt());
}
}
}
void InfoPaneDropdown::on_powerSuspendNormally_toggled(bool checked)
{
if (checked) {
d->settings.setValue("power/suspendMode", 0);
}
}
void InfoPaneDropdown::on_powerSuspendTurnOffScreen_toggled(bool checked)
{
if (checked) {
d->settings.setValue("power/suspendMode", 1);
}
}
void InfoPaneDropdown::on_powerSuspendHibernate_toggled(bool checked)
{
if (checked) {
d->settings.setValue("power/suspendMode", 2);
}
}
void InfoPaneDropdown::on_powerButtonPressed_currentIndexChanged(int index)
{
d->settings.setValue("power/onPowerButtonPressed", index);
}
void InfoPaneDropdown::on_notifyOnConnectPower_toggled(bool checked)
{
d->settings.setValue("power/notifyConnectPower", checked);
}
void InfoPaneDropdown::on_notifyOnUnplug_toggled(bool checked)
{
d->settings.setValue("power/notifyUnplugPower", checked);
}