426 lines
16 KiB
C++
426 lines
16 KiB
C++
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||
*
|
||
* Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd.
|
||
*
|
||
* 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 2 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, write to the Free Software
|
||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
*
|
||
*/
|
||
#include "homepagewidget.h"
|
||
#include "ui_homepagewidget.h"
|
||
|
||
#include <QLabel>
|
||
#include <QSignalMapper>
|
||
#include <QHBoxLayout>
|
||
#include <QVBoxLayout>
|
||
#include <QListWidget>
|
||
#include <QDBusInterface>
|
||
#include <QDebug>
|
||
#include <QScrollBar>
|
||
#include <QStringList>
|
||
|
||
#include <QSvgRenderer>
|
||
#include "mainwindow.h"
|
||
#include "utils/functionselect.h"
|
||
#include "interface/ukcccommon.h"
|
||
using namespace ukcc;
|
||
#include "flowlayout.h"
|
||
#include "utils/modulefactory.h"
|
||
|
||
#define STYLE_FONT_SCHEMA "org.ukui.style"
|
||
|
||
const QStringList KexcludeModule{"update","security","application","search_f"};
|
||
|
||
HomePageWidget::HomePageWidget(QWidget *parent, QMap<QString, QGSettings *> map) :
|
||
QWidget(parent),
|
||
vecGsettins(map),
|
||
ui(new Ui::HomePageWidget)
|
||
{
|
||
qApp->installEventFilter(this);
|
||
ui->setupUi(this);
|
||
// 获取主窗口
|
||
this->setParent(parent);
|
||
pmainWindow = (MainWindow *)parentWidget();
|
||
|
||
// 初始化首页
|
||
initUI();
|
||
ui->scrollArea->viewport()->setAttribute(Qt::WA_TranslucentBackground);
|
||
ui->scrollArea->setStyleSheet("QScrollArea{background-color: transparent;}");
|
||
ui->scrollArea->verticalScrollBar()->setProperty("drawScrollBarGroove", false);
|
||
ui->scrollArea->verticalScrollBar()->setVisible(false);
|
||
|
||
}
|
||
|
||
HomePageWidget::~HomePageWidget()
|
||
{
|
||
delete ui;
|
||
ui = nullptr;
|
||
}
|
||
|
||
void HomePageWidget::initUI() {
|
||
FlowLayout * flowLayout = new FlowLayout(ui->widget_2, true, 0);
|
||
flowLayout->setContentsMargins(70, 0, 70, 0);
|
||
mModuleMap = UkccCommon::getModuleHideStatus();
|
||
|
||
QSignalMapper * moduleSignalMapper = new QSignalMapper(this);
|
||
int totalModule = ModulesFactory::size();
|
||
for(int index = 0; index < totalModule; index++) {
|
||
ModuleInfo *curModuleInfo = ModulesFactory::getModuleInfoByIndex(index);
|
||
if (curModuleInfo == nullptr) {
|
||
continue;
|
||
}
|
||
//获取当前模块名
|
||
const QString locale = QLocale::system().name();
|
||
QString modulenamei18nString = curModuleInfo->getModuleNameLocale(locale);
|
||
QString modulenameString = curModuleInfo->moduleName;
|
||
|
||
if ((mModuleMap.keys().contains(modulenameString) && !mModuleMap[modulenameString].toBool())
|
||
|| (UkccCommon::isTablet() && KexcludeModule.contains(modulenameString))) {
|
||
continue;
|
||
}
|
||
|
||
// pangw无安全模块-不显示 社区无更新和安全-不显示
|
||
if ((modulenameString == "security" || modulenameString == "update") && UkccCommon::isCommunity()) {
|
||
continue;
|
||
}
|
||
|
||
//三权分立下非root用户,不可设置网络、时间语言、更新
|
||
#ifdef WITHKYSEC
|
||
if (!kysec_is_disabled() && kysec_get_3adm_status() && (getuid() || geteuid())){
|
||
if (modulenameString == "network" || modulenameString == "datetime" || modulenameString == "update") {
|
||
continue;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
//构建首页10个模块
|
||
//基础Widget
|
||
QWidget * baseWidget = new QWidget();
|
||
baseWidget->setAttribute(Qt::WA_DeleteOnClose);
|
||
baseWidget->setObjectName("itemBaseWidget");
|
||
//baseWidget 的顶级布局
|
||
QVBoxLayout * baseVerLayout = new QVBoxLayout(baseWidget);
|
||
baseVerLayout->setMargin(0);
|
||
baseVerLayout->setSpacing(0);
|
||
//包含显示内容的布局
|
||
QBoxLayout * majorHorLayout = new QHBoxLayout();
|
||
majorHorLayout->setMargin(0);
|
||
majorHorLayout->setSpacing(0);
|
||
|
||
//内容Widget的构建
|
||
QPushButton * widget = new QPushButton();
|
||
QString picModuleName = modulenameString;
|
||
widget->setMinimumWidth(300);
|
||
widget->setMinimumHeight(97);
|
||
widget->setAttribute(Qt::WA_DeleteOnClose);
|
||
widget->setProperty("useButtonPalette", true);
|
||
|
||
if (picModuleName == "search_f") {
|
||
picModuleName = "search";
|
||
}
|
||
widget->setObjectName("itemWidget");
|
||
widget->setFlat(true);
|
||
QHBoxLayout * mainHorLayout = new QHBoxLayout(widget);
|
||
mainHorLayout->setMargin(16);
|
||
mainHorLayout->setSpacing(16);
|
||
|
||
QLabel * logoLabel = new QLabel(widget);
|
||
logoLabel->setFixedSize(48, 48);
|
||
logoLabel->setObjectName("logoLabel");
|
||
logoLabel->setScaledContents(true);
|
||
QString themeIconName = curModuleInfo->themeIconName;
|
||
QString localIconName = curModuleInfo->localIconName;
|
||
logoLabel->setPixmap(QIcon::fromTheme(themeIconName,QIcon(localIconName))
|
||
.pixmap(logoLabel->size()));
|
||
const QByteArray settingId(STYLE_FONT_SCHEMA);
|
||
if (QGSettings::isSchemaInstalled(settingId)) {
|
||
QGSettings *mQtSettings = new QGSettings(settingId, QByteArray(), this);
|
||
connect(mQtSettings, &QGSettings::changed, this, [=](QString key) {
|
||
if (key == "iconThemeName") {
|
||
logoLabel->setPixmap(QIcon::fromTheme(themeIconName,QIcon(localIconName))
|
||
.pixmap(logoLabel->size()));
|
||
}
|
||
});
|
||
}
|
||
QVBoxLayout * rightVerLayout = new QVBoxLayout();
|
||
rightVerLayout->setContentsMargins(0, 2, 0, 0);
|
||
rightVerLayout->setSpacing(8);
|
||
|
||
QLabel * titleLabel = new QLabel(widget);
|
||
titleLabel->setObjectName("mptitleLabel");
|
||
titleLabel->setText(modulenamei18nString);
|
||
|
||
QHBoxLayout * funcHorLayout = new QHBoxLayout();
|
||
funcHorLayout->setSpacing(8);
|
||
|
||
uint AllWidth = 0;
|
||
QList<TristateLabel *> Labels;
|
||
QList<PluginInfo> tmpList = curModuleInfo->pluginInfoList;
|
||
int showModuleCount = 0;
|
||
for (int funcIndex = 0; funcIndex < tmpList.size(); funcIndex++){
|
||
PluginInfo single = tmpList.at(funcIndex);
|
||
|
||
//跳过不在首页显示的功能
|
||
if (!single.mainShow)
|
||
continue;
|
||
if (mModuleMap.keys().contains(single.nameString.toLower())) {
|
||
if (!mModuleMap[single.nameString.toLower()].toBool()) {
|
||
continue;
|
||
}
|
||
}
|
||
QObject* pluginObj = ModulesFactory::getPluginObjectByName(single.namei18nString);
|
||
if (pluginObj == nullptr) {
|
||
continue;
|
||
}
|
||
|
||
QString textName = single.namei18nString;
|
||
TristateLabel *label = new TristateLabel(textName, widget);
|
||
|
||
if (single.isEnable) {
|
||
Labels.append(label);
|
||
AllWidth += label->width() + funcHorLayout->spacing();
|
||
}
|
||
// 显示后总label宽度大导致显示不全,隐藏后加载显示的label
|
||
if (!single.isEnable || AllWidth > 198) {
|
||
label->setVisible(false);
|
||
}
|
||
|
||
// 监听该插件是否启用
|
||
if (vecGsettins.contains(single.oriNameString)) {
|
||
// 插件未启用直接隐藏该label
|
||
if (!vecGsettins[single.oriNameString]->get(SHOW_KEY).toBool())
|
||
label->setVisible(false);
|
||
|
||
connect(vecGsettins[single.oriNameString], &QGSettings::changed,[=](QString key){
|
||
if (key == SHOW_KEY) {
|
||
CommonInterface* pluginInstance = qobject_cast<CommonInterface*>(pluginObj);
|
||
bool isShow = pluginInstance->isEnable() && vecGsettins[single.oriNameString]->get(SHOW_KEY).toBool();
|
||
// 动态调整在首页显示的插件池
|
||
if (isShow) {
|
||
if (!mLabels[index].contains(label)) {
|
||
mLabels[index].insert(funcIndex, label);
|
||
}
|
||
int MWidth = 0;
|
||
for (TristateLabel * label : mLabels[index]) {
|
||
if ((MWidth += label->width() + funcHorLayout->spacing()) < 198) {
|
||
label->setVisible(true);
|
||
} else {
|
||
label->setVisible(false);
|
||
}
|
||
}
|
||
} else {
|
||
if (mLabels[index].contains(label)) {
|
||
mLabels[index].removeOne(label);
|
||
}
|
||
label->setVisible(false);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
connect(label, SIGNAL(clicked()), moduleSignalMapper, SLOT(map()));
|
||
moduleSignalMapper->setMapping(label, pluginObj);
|
||
|
||
funcHorLayout->addWidget(label);
|
||
++showModuleCount;
|
||
}
|
||
mLabels.append(Labels);
|
||
funcHorLayout->addStretch();
|
||
|
||
// 下属无插件,不显示
|
||
if (curModuleInfo->pluginInfoList.size() == 0 || showModuleCount == 0) {
|
||
widget->setVisible(false);
|
||
continue;
|
||
}
|
||
|
||
const QByteArray styleID(STYLE_FONT_SCHEMA);
|
||
QGSettings *stylesettings = new QGSettings(styleID, QByteArray(), this);
|
||
connect(stylesettings,&QGSettings::changed, [=](QString key) {
|
||
if ("systemFont" == key || "systemFontSize" == key) {
|
||
int MWidth = 0;
|
||
for (TristateLabel * label : Labels) {
|
||
QFontMetrics fontMetrics(this->font());
|
||
int fontSize = fontMetrics.width(label->text());
|
||
label->setFixedWidth(fontSize);
|
||
if ((MWidth += label->width() + funcHorLayout->spacing()) < 198) {
|
||
label->setVisible(true);
|
||
} else {
|
||
label->setVisible(false);
|
||
}
|
||
}
|
||
}
|
||
});
|
||
connect(widget, &QPushButton::clicked, [=]() {
|
||
//获取模块的第一项跳转
|
||
QString firstFunc;
|
||
QList<PluginInfo> tmpList = curModuleInfo->pluginInfoList;
|
||
for (PluginInfo tmpStruct : tmpList) {
|
||
bool isIntel = UkccCommon::isTablet();
|
||
|
||
if ((isIntel && tmpStruct.namei18nString == "User Info")
|
||
|| (!isIntel && tmpStruct.namei18nString == "User Info Intel")) {
|
||
continue;
|
||
}
|
||
|
||
if (!tmpStruct.isEnable) {
|
||
continue;
|
||
}
|
||
QObject* pluginObj = ModulesFactory::getPluginObjectByName(tmpStruct.namei18nString);
|
||
if (pluginObj == nullptr) {
|
||
continue;
|
||
}
|
||
|
||
// 若该插件不启用,跳转为下一项
|
||
if (vecGsettins.contains(tmpStruct.nameString)) {
|
||
QGSettings *msettings = vecGsettins[tmpStruct.nameString];
|
||
if (msettings) {
|
||
if (!msettings->get(SHOW_KEY).toBool()) {
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
if (mModuleMap.isEmpty() || !mModuleMap.contains(tmpStruct.nameString.toLower()) || mModuleMap[tmpStruct.nameString.toLower()].toBool()) {
|
||
firstFunc = tmpStruct.namei18nString;
|
||
UkccCommon::buriedSettings(tmpStruct.nameString, nullptr, "home clicked");
|
||
//跳转
|
||
pmainWindow->functionBtnClicked(pluginObj);
|
||
break;
|
||
}
|
||
}
|
||
});
|
||
|
||
rightVerLayout->addStretch();
|
||
rightVerLayout->addWidget(titleLabel);
|
||
rightVerLayout->addLayout(funcHorLayout);
|
||
rightVerLayout->addStretch();
|
||
|
||
mainHorLayout->addWidget(logoLabel);
|
||
mainHorLayout->addLayout(rightVerLayout);
|
||
mainHorLayout->addStretch();
|
||
|
||
widget->setLayout(mainHorLayout);
|
||
|
||
majorHorLayout->addWidget(widget);
|
||
majorHorLayout->addStretch();
|
||
|
||
baseVerLayout->addLayout(majorHorLayout);
|
||
baseVerLayout->addStretch();
|
||
|
||
baseWidget->setLayout(baseVerLayout);
|
||
|
||
flowLayout->addWidget(baseWidget);
|
||
}
|
||
connect(moduleSignalMapper, SIGNAL(mapped(QObject*)), pmainWindow, SLOT(pluginBtnClicked(QObject*)));
|
||
}
|
||
|
||
QGSettings *HomePageWidget::setGsettingsPath(QList<char *> list , QString name)
|
||
{
|
||
// 为每个插件创建动态QGSettings对象,用于监听插件是否隐藏
|
||
QByteArray ba;
|
||
char *path;
|
||
ba = (QString("%1%2").arg(name).arg("/")).toUtf8();
|
||
path = ba.data();
|
||
const QByteArray id(PLUGINS_SCHEMA);
|
||
if (!QGSettings::isSchemaInstalled(id)) {
|
||
return nullptr;
|
||
}
|
||
QGSettings *settings = nullptr;
|
||
QString plugin = QString("%1%2%3").arg(PLUGINS_PATH).arg(name).arg("/");
|
||
settings = new QGSettings(id, plugin.toUtf8().data(), this);
|
||
|
||
//判断是否已存在该路径,不存在则赋初值
|
||
for (int j = 0; j < list.count(); j++) {
|
||
if (!qstrcmp(path, list.at(j))){
|
||
return settings;
|
||
}
|
||
}
|
||
settings->set(PLUGIN_NAME , name);
|
||
settings->set(SHOW_KEY , true);
|
||
return settings;
|
||
}
|
||
|
||
const QPixmap HomePageWidget::loadSvg(const QString &fileName, COLOR color)
|
||
{
|
||
int size = 48;
|
||
const auto ratio = qApp->devicePixelRatio();
|
||
if ( 2 == ratio) {
|
||
size = 96;
|
||
} else if (3 == ratio) {
|
||
size = 144;
|
||
}
|
||
QPixmap pixmap(size, size);
|
||
QSvgRenderer renderer(fileName);
|
||
pixmap.fill(Qt::transparent);
|
||
|
||
QPainter painter;
|
||
painter.begin(&pixmap);
|
||
renderer.render(&painter);
|
||
painter.end();
|
||
|
||
pixmap.setDevicePixelRatio(ratio);
|
||
return drawSymbolicColoredPixmap(pixmap, color);
|
||
}
|
||
|
||
QPixmap HomePageWidget::drawSymbolicColoredPixmap(const QPixmap &source, COLOR cgColor)
|
||
{
|
||
QImage img = source.toImage();
|
||
for (int x = 0; x < img.width(); x++) {
|
||
for (int y = 0; y < img.height(); y++) {
|
||
auto color = img.pixelColor(x, y);
|
||
if (color.alpha() > 0) {
|
||
if ( WHITE == cgColor) {
|
||
color.setRed(255);
|
||
color.setGreen(255);
|
||
color.setBlue(255);
|
||
img.setPixelColor(x, y, color);
|
||
} else if( BLACK == cgColor) {
|
||
color.setRed(0);
|
||
color.setGreen(0);
|
||
color.setBlue(0);
|
||
img.setPixelColor(x, y, color);
|
||
} else if (GRAY == cgColor) {
|
||
color.setRed(152);
|
||
color.setGreen(163);
|
||
color.setBlue(164);
|
||
img.setPixelColor(x, y, color);
|
||
} else if(HIGHLIGHT == cgColor){
|
||
QColor highLightColor = palette().color(QPalette::Highlight);
|
||
color.setRed(highLightColor.red());
|
||
color.setGreen(highLightColor.green());
|
||
color.setBlue(highLightColor.blue());
|
||
img.setPixelColor(x, y, color);
|
||
}
|
||
else {
|
||
return source;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return QPixmap::fromImage(img);
|
||
}
|
||
|
||
|
||
bool HomePageWidget::eventFilter(QObject *watched, QEvent *event)
|
||
{
|
||
if (event->type() == QEvent::MouseMove) {
|
||
if (ui->scrollArea->geometry().contains(this->mapFromGlobal(QCursor::pos()))) {
|
||
ui->scrollArea->verticalScrollBar()->setVisible(true);
|
||
} else {
|
||
ui->scrollArea->verticalScrollBar()->setVisible(false);
|
||
}
|
||
}
|
||
return QObject::eventFilter(watched, event);
|
||
}
|
||
|