Import Upstream version 1.0.30.1

This commit is contained in:
谢炜 2022-06-17 17:12:22 +08:00
commit 940dfcf3fa
1186 changed files with 502161 additions and 0 deletions

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# kylin-tablet-desktop-general
通用平板桌面

View File

@ -0,0 +1,16 @@
CONFIG += c++11 console
CONFIG -= app_bundle
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
# Default rules for deployment.
config.files = $$PWD/../data/99qtquick-scene-graph-backend-config
config.path = /etc/X11/Xsession.d
target.path = /usr/bin
INSTALLS += target \
config

View File

@ -0,0 +1,14 @@
#include <QGuiApplication>
#include <QOpenGLContext>
#include <iostream>
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);
if (QOpenGLContext::supportsThreadedOpenGL()) {
std::cout << "threaded" << std::endl;
} else {
std::cout << "non-threaded" << std::endl;
}
return 1;
}

9
common/common.pri Normal file
View File

@ -0,0 +1,9 @@
INCLUDEPATH += \
$$PWD
SOURCES += \
$$PWD/logger.cpp
HEADERS += \
$$PWD/logger.h \
$$PWD/singleton.h

74
common/logger.cpp Normal file
View File

@ -0,0 +1,74 @@
#include "logger.h"
#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QTextStream>
#include <QDebug>
#if 0
#include <spdlog/spdlog.h>
#endif
namespace common {
#if 0
Logger::Logger(QObject *parent) : QObject(parent) {}
void Logger::outputMessage(QtMsgType type,
const QMessageLogContext &context,
const QString &msg) {
Q_UNUSED(context)
switch (type) {
case QtDebugMsg: {
logger()->debug(msg.toStdString());
break;
}
case QtWarningMsg: {
logger()->warn(msg.toStdString());
break;
}
case QtCriticalMsg: {
logger()->critical(msg.toStdString());
break;
}
case QtInfoMsg: {
logger()->info(msg.toStdString());
break;
}
default:
break;
}
logger()->flush();
}
std::shared_ptr<spdlog::logger> Logger::logger() {
QString logFileName =
qgetenv("HOME") + "/.cache/kylin/kylin-tablet-desktop/daily.txt";
static auto logger = spdlog::daily_logger_mt(
"daily_logger", logFileName.toStdString().c_str(), 2, 30);
logger->set_level(spdlog::level::debug);
return logger;
}
#endif
void QmlLogger::debug(const QString &msg)
{
qDebug() << msg;
}
void QmlLogger::info(const QString &msg)
{
qInfo() << msg;
}
void QmlLogger::warning(const QString &msg)
{
qWarning() << msg;
}
void QmlLogger::critical(const QString &msg)
{
qCritical() << msg;
}
} // namespace utils

40
common/logger.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef LOGGER_H
#define LOGGER_H
#if 0
#include <spdlog/logger.h>
#include <spdlog/sinks/daily_file_sink.h>
#endif
#include <QObject>
namespace common {
#if 0
class Logger : public QObject
{
Q_OBJECT
public:
explicit Logger(QObject *parent = nullptr);
static void outputMessage(QtMsgType type, const QMessageLogContext &context,
const QString &msg);
private:
static std::shared_ptr<spdlog::logger> logger();
};
#endif
class QmlLogger :public QObject
{
Q_OBJECT
public:
Q_INVOKABLE void debug(const QString &msg);
Q_INVOKABLE void info(const QString &msg);
Q_INVOKABLE void warning(const QString &msg);
Q_INVOKABLE void critical(const QString &msg);
};
}; // namespace utils
#endif // LOGGER_H

23
common/singleton.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef SINGLETON_H
#define SINGLETON_H
namespace common {
template<typename T>
class Singleton {
public:
static T& GetInstance() {
static T instance;
return instance;
}
protected:
virtual ~Singleton() {}
Singleton() {}
Singleton(const Singleton&) {}
Singleton& operator =(const Singleton&) {}
};
} // namespace common
#endif // SINGLETON_H

View File

@ -0,0 +1,8 @@
CHECK_TOOL=check-qtqtuick-scene-render-loop
QT_QUICK_BACKEND="software"
if which $CHECK_TOOL >/dev/null 2>&1; then
render_loop=`/usr/bin/check-qtqtuick-scene-render-loop 2>/dev/null`
if [ $render_loop == "non-threaded" ];then
export QT_QUICK_BACKEND
fi
fi

View File

@ -0,0 +1,14 @@
[Desktop Entry]
Name=Kylin Tablet General Desktop
GenericName=Tablet Desktop
GenericName[zh_CN]=Kylin通用平板桌面
Name[zh_CN]=Kylin通用平板桌面
Exec=/usr/bin/kylin-tablet-desktop
Terminal=false
Type=Application
X-UKUI-AutoRestart=true
Categories=System;Settings;Security;
Keywords=file;desktop;
OnlyShowIn=UKUI;
NoDisplay=true;

View File

@ -0,0 +1,32 @@
#include "appnamesort.h"
#include <QLocale>
#include <QCollator>
AppNameSort::AppNameSort(QString appName) : m_appName(appName)
{
}
bool AppNameSort::operator < (const AppNameSort &other) const
{
QLocale local;
QString language = local.languageToString(local.language());
if (QString::compare(language, "Chinese") == 0) {
local = QLocale(QLocale::Chinese);
} else {
local = QLocale(QLocale::English);
}
QCollator collator(local);
if (collator.compare(m_appName, other.getAppName()) < 0) {
return true;
} else {
return false;
}
}
QString AppNameSort::getAppName() const
{
return m_appName;
}

View File

@ -0,0 +1,17 @@
#ifndef APPNAMESORT_H
#define APPNAMESORT_H
#include <QString>
class AppNameSort
{
public:
AppNameSort(QString appName);
// 重载操作符
bool operator < (const AppNameSort &other) const;
QString getAppName() const;
private:
QString m_appName;
};
#endif // APPNAMESORT_H

View File

@ -0,0 +1,26 @@
QT += core KIOCore KIOFileWidgets KIOWidgets KNTLM sql KIconThemes
INCLUDEPATH += $$PWD
CONFIG += link_pkgconfig
PKGCONFIG += gsettings-qt
SOURCES += \
$$PWD/database-operation.cpp \
$$PWD/icon-theme.cpp \
$$PWD/appnamesort.cpp \
$$PWD/kylin-tablet-desktop-backend.cpp \
$$PWD/utils.cpp \
$$PWD/ukuisettings.cpp
HEADERS += \
$$PWD/database-operation.h \
$$PWD/types.h \
$$PWD/icon-theme.h \
$$PWD/appnamesort.h \
$$PWD/kylin-tablet-desktop-backend_global.h \
$$PWD/kylin-tablet-desktop-backend.h \
$$PWD/utils.h \
$$PWD/ukuisettings.h
message($$PWD)

View File

@ -0,0 +1,521 @@
#include "database-operation.h"
#include "utils.h"
#include <QSqlQuery>
#include <QSqlError>
#include <QDate>
#include <QFile>
#include <QRect>
#include <QStandardPaths>
#include <QDebug>
dataBaseOperation::dataBaseOperation(QObject *parent) : QObject(parent), idleItemId(0)
{
if (!QSqlDatabase::drivers().contains("QSQLITE")) {
qDebug() << "Unable to load database, this demo needs the SQLITE3 driver ! ! !";
return;
}
QString dbPath = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation)[0] + "/ukui/appList.db";
// 创建一个数据库连接,指定数据库驱动
db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(dbPath);
}
dataBaseOperation::~dataBaseOperation()
{
db.close();
}
bool dataBaseOperation::openDataBase()
{
if (!db.open()) {
qDebug() << db.lastError().text();
return false;
}
else {
if (!isTableExist("itemlist")) {
createDefaultTable();
createItemsData();
}
qDebug() << "DataBase Tables: " << db.tables();
return true;
}
}
void dataBaseOperation::createDefaultTable()
{
QSqlQuery sqlQuery;
if (!sqlQuery.exec(QLatin1String("CREATE TABLE itemlist (id integer primary key, itemId integer, desktopName varchar, name varchar, iconName varchar, type integer, placeholder varchar, categories varchar)")))
qDebug() << sqlQuery.lastError().text();
if (!sqlQuery.exec(QLatin1String("CREATE TABLE sets (id integer primary key, setId integer, sequence varchar, scrollable integer)")))
qDebug() << sqlQuery.lastError().text();
if (!sqlQuery.exec(QLatin1String("CREATE TABLE page (id integer primary key, pageId integer, sequence varchar)")))
qDebug() << sqlQuery.lastError().text();
}
void dataBaseOperation::createItemsData()
{
QString desktopName("widgetPlugin1");
QString sql = "SELECT * FROM itemlist WHERE desktopName=:desktopName";
QSqlQuery sqlQuery;
sqlQuery.prepare(sql);
sqlQuery.bindValue(":desktopName", desktopName);
sqlQuery.exec();
while(sqlQuery.next())
{
quint32 id = 0;
id = sqlQuery.value(0).toUInt();
if(id > 0)
return;
}
// addItem(getIdleItemID(), QLatin1String("widgetPlugin 1"), QString("登录"), QLatin1String(""), 4, {4,2});
// addItem(getIdleItemID(), "container1", "翻页分组", "", 3, {2,2});
// addItem(getIdleItemID(), "container2", "滚动分组", "", 3, {2,2});
// addItem(getIdleItemID(), QLatin1String("/usr/share/applications/peony.desktop"), QString("文件管理器"),
// QLatin1String("system-file-manager.png"), 1, {1,1}, {9});
// addItem(getIdleItemID(), QLatin1String("/usr/share/applications/kylin-video.desktop"), QString("影音"),
// QLatin1String("kylin-video.png"), 1, {1,1}, {7});
// QList<quint32> pageList = {1,2,3};
// addFlipSet(2, {{4}});
// addScrollSet(3, {5});
// addPage(1, pageList);
addItem(0, QLatin1String("taskbar"), "taskbar", "", 3, {1, 1});
addScrollSet(0, {});
}
void dataBaseOperation::updatePageTable()
{
}
bool dataBaseOperation::isTableExist(const QString &tableName)
{
if(db.tables().contains(tableName, Qt::CaseInsensitive))
return true;
else
return false;
}
quint32 dataBaseOperation::getIdleItemID()
{
idleItemId = 0;
QVector<quint32> itemIdList;
QSqlQuery sqlQuery;
sqlQuery.exec("SELECT * FROM itemlist");
if (!sqlQuery.exec())
qDebug() << sqlQuery.lastError();
else
{
while (sqlQuery.next())
{
quint32 itemId = sqlQuery.value(1).toUInt();
itemIdList.append(itemId);
}
}
qSort(itemIdList);
for (int var = 0; var < itemIdList.size(); ++var) {
if (itemIdList[var] != var) {
idleItemId = var;
break;
}
}
if (!idleItemId)
idleItemId = itemIdList.size();
qDebug() << "idleItemId =" << idleItemId;
return idleItemId;
}
QMap<quint32, UKUI::BaseItem *> dataBaseOperation::queryAllItemData()
{
QMap<quint32, UKUI::BaseItem *> itemList;
QSqlQuery sqlQuery;
sqlQuery.exec("SELECT * FROM itemlist");
if(!sqlQuery.exec())
qDebug() << sqlQuery.lastError();
else
{
while(sqlQuery.next())
{
quint32 id = sqlQuery.value(1).toUInt();
QString desktopName = sqlQuery.value(2).toString();
QString name = sqlQuery.value(3).toString();
QString iconName = sqlQuery.value(4).toString();
int type = sqlQuery.value(5).toInt();
QStringList list = sqlQuery.value(6).toString().split(',');
QString x_placeholder = list.at(0);
QString y_placeholder = list.at(1);
QList<int> placeHolder = {x_placeholder.toInt(), y_placeholder.toInt()};
QStringList categories = sqlQuery.value(7).toString().split(',');
QList<int> category_list;
foreach (auto category, categories) {
category_list.append(category.toInt());
}
// qDebug() << QString("desktopName:%1 name:%2 id:%3 iconName:%4 type:%5").arg(desktopName).arg(name).arg(id).arg(iconName).arg(type)
// << "placeHolder:" << placeHolder;
// QString absoluteIconName = getAbsoluteIconPath(iconName);
switch (type) {
case 1:
itemList[id] = new UKUI::IconItem(desktopName, name, id, iconName, category_list);
break;
case 2:
itemList[id] = new UKUI::GroupItem(name, id);
break;
case 3:
itemList[id] = new UKUI::ContainerItem(name, id, placeHolder);
break;
case 4:
itemList[id] = new UKUI::Widget(name, id, placeHolder);
break;
default:
break;
}
}
}
return itemList;
}
QMap<quint32, QList<QList<quint32>>> dataBaseOperation::queryAllFlipSetData()
{
QMap<quint32, QList<QList<quint32>>> allSets;
QSqlQuery sqlQuery;
sqlQuery.exec("SELECT * FROM sets");
if(!sqlQuery.exec())
qDebug() << sqlQuery.lastError();
else
{
while(sqlQuery.next())
{
if (sqlQuery.value(3).toInt() == 0) {
int setId = sqlQuery.value(1).toInt();
QStringList sequence = sqlQuery.value(2).toString().split(';');
for (int i = 0; i < sequence.size(); ++i) {
QStringList setPageItem = sequence.at(i).split(",");
QList<quint32> itemList;
for (int j = 0; j < setPageItem.size(); ++j) {
itemList.append(setPageItem.at(j).toUInt());
}
allSets[setId].append(itemList);
}
}
}
}
// qDebug() << __func__ << "Sets:" << allSets;
return allSets;
}
QMap<quint32, QList<quint32>> dataBaseOperation::queryAllScrollSetData()
{
QMap<quint32, QList<quint32>> allSets;
QSqlQuery sqlQuery;
sqlQuery.exec("SELECT * FROM sets");
if(!sqlQuery.exec())
qDebug() << sqlQuery.lastError();
else
{
while(sqlQuery.next())
{
if (sqlQuery.value(3).toInt() == 1)
{
int setId = sqlQuery.value(1).toInt();
QString sequence = sqlQuery.value(2).toString();
if (sequence.isEmpty())
{
allSets[setId];
continue;
}
else {
QStringList setAllItem = sequence.split(",");
foreach (auto item, setAllItem) {
allSets[setId].append(item.toUInt());
}
}
}
}
}
return allSets;
}
QMap<quint32, QList<quint32>> dataBaseOperation::queryAllPageData()
{
QMap<quint32, QList<quint32>> allPage;
QSqlQuery sqlQuery;
sqlQuery.exec("SELECT * FROM page");
if(!sqlQuery.exec())
qDebug() << sqlQuery.lastError();
else
{
while(sqlQuery.next())
{
int setId = sqlQuery.value(1).toInt();
QStringList sequence = sqlQuery.value(2).toString().split(',');
for (int i = 0; i < sequence.size(); ++i) {
QString itemId = sequence.at(i);
allPage[setId].append(itemId.toUInt());
}
}
}
// qDebug() << __func__ << "Page:" << allPage;
return allPage;
}
void dataBaseOperation::queryItemDataFromID(int id)
{
QString sql = "SELECT * FROM itemlist WHERE id=:id";
QSqlQuery sqlQuery;
sqlQuery.prepare(sql);
sqlQuery.bindValue(":id", id);
sqlQuery.exec();
while(sqlQuery.next())
{
QString desktopName = sqlQuery.value(2).toString();
QString name = sqlQuery.value(3).toString();
QString iconName = sqlQuery.value(4).toString();
int type = sqlQuery.value(5).toInt();
int parent_id = sqlQuery.value(10).toInt();
int page = sqlQuery.value(11).toInt();
QRect geometry = QRect(sqlQuery.value(6).toInt(), sqlQuery.value(7).toInt(), sqlQuery.value(8).toInt(), sqlQuery.value(9).toInt());
qDebug() << endl << QString("id:%1 name:%2 type:%3 parent_id:%4 page:%5 desktopName:%6 iconName:%7").arg(id).arg(name).arg(type).arg(parent_id).arg(page).arg(desktopName).arg(iconName)
<< " geometry =" << geometry << endl;
}
}
QList<quint32> dataBaseOperation::queryPageDataFromID(int pageId)
{
QList<quint32> itemList;
QString sql = "SELECT * FROM page WHERE pageId=:pageId";
QSqlQuery sqlQuery;
sqlQuery.prepare(sql);
sqlQuery.bindValue(":pageId", pageId);
sqlQuery.exec();
while(sqlQuery.next())
{
QStringList itemListStr = sqlQuery.value(2).toString().split(',');
if(itemListStr.size() == 1 && itemListStr.at(0).isEmpty())
return itemList;
for(int i = 0; i < itemListStr.size(); i++) {
itemList.append(static_cast<QString>(itemListStr.at(i)).toUInt());
}
return itemList;
}
return itemList;
}
quint32 dataBaseOperation::queryIdFromDesktopName(QString desktopName)
{
QString sql = "SELECT * FROM itemlist WHERE desktopName=:desktopName";
QSqlQuery sqlQuery;
sqlQuery.prepare(sql);
sqlQuery.bindValue(":desktopName", desktopName);
sqlQuery.exec();
while(sqlQuery.next())
{
quint32 id = sqlQuery.value(1).toUInt();
// qDebug() << __func__ << "id =" << id;
return id;
}
return 0;
}
QVariant dataBaseOperation::addItem(quint32 itemId, const QString &desktopName, const QString &name, const QString &iconName, const QVariant &type,
const QList<quint32> &_placeholder, const QList<int> &_categories)
{
QString placeholder = UKUI::fromQListUIntToString(_placeholder);
QString categories = UKUI::fromQListIntToString(_categories);
QSqlQuery sqlQuery;
if (!sqlQuery.prepare(QLatin1String("INSERT INTO itemlist (itemId, desktopName, name, iconName, type, placeholder, categories) "
"VALUES (?, ?, ?, ?, ?, ?, ?)")))
qDebug() << sqlQuery.lastError().text();
sqlQuery.addBindValue(itemId);
sqlQuery.addBindValue(desktopName);
sqlQuery.addBindValue(name);
sqlQuery.addBindValue(iconName);
sqlQuery.addBindValue(type);
sqlQuery.addBindValue(placeholder);
sqlQuery.addBindValue(categories);
sqlQuery.exec();
return sqlQuery.lastInsertId();
}
void dataBaseOperation::modifyItemData(quint32 id, const QString &desktopName, const QString &name, const QString &iconName, const QList<int> &_categories)
{
QString categories = UKUI::fromQListIntToString(_categories);
QSqlQuery sqlQuery;
sqlQuery.prepare("UPDATE itemlist SET desktopName=?, name=?, iconName=?, categories=? WHERE itemId=?");
sqlQuery.addBindValue(desktopName);
sqlQuery.addBindValue(name);
sqlQuery.addBindValue(iconName);
sqlQuery.addBindValue(categories);
sqlQuery.addBindValue(id);
if(!sqlQuery.exec())
qDebug() << sqlQuery.lastError();
}
QVariant dataBaseOperation::addFlipSet(quint32 setId, const QList<QList<quint32>> &sequence)
{
QString itemSequence;
if(!sequence.isEmpty()) {
itemSequence += UKUI::fromQListUIntToString(sequence.first());
for(int i = 1; i < sequence.size(); i++) {
QList<quint32> setPageItemSeq = sequence.at(i);
itemSequence += QString(";") += UKUI::fromQListUIntToString(setPageItemSeq);
}
}
qDebug() << __func__ << itemSequence;
QSqlQuery sqlQuery;
if (!sqlQuery.prepare(QLatin1String("INSERT INTO sets (setId, sequence, scrollable) VALUES (?, ?, ?)")))
qDebug() << sqlQuery.lastError().text();
sqlQuery.addBindValue(setId);
sqlQuery.addBindValue(itemSequence);
sqlQuery.addBindValue(0);
sqlQuery.exec();
return sqlQuery.lastInsertId();
}
QVariant dataBaseOperation::addScrollSet(quint32 setId, const QList<quint32> &sequence)
{
QString itemSequence;
if(!sequence.isEmpty())
itemSequence = UKUI::fromQListUIntToString(sequence);
QSqlQuery sqlQuery;
if (!sqlQuery.prepare(QLatin1String("INSERT INTO sets (setId, sequence, scrollable) VALUES (?, ?, ?)")))
qDebug() << sqlQuery.lastError().text();
sqlQuery.addBindValue(setId);
sqlQuery.addBindValue(itemSequence);
sqlQuery.addBindValue(1);
sqlQuery.exec();
return sqlQuery.lastInsertId();
}
void dataBaseOperation::modifyFlipSetData(quint32 setId, const QList<QList<quint32>> &sequence)
{
QString itemSequence;
if(!sequence.isEmpty()) {
itemSequence += UKUI::fromQListUIntToString(sequence.first());
for(int i = 1; i < sequence.size(); i++) {
QList<quint32> setPageItemSeq = sequence.at(i);
itemSequence += QString(";") += UKUI::fromQListUIntToString(setPageItemSeq);
}
}
qDebug() << __func__ << "itemSequence:" << itemSequence;
QSqlQuery sqlQuery;
sqlQuery.prepare("UPDATE sets SET sequence=? WHERE setId=?");
sqlQuery.addBindValue(itemSequence);
sqlQuery.addBindValue(setId);
if(!sqlQuery.exec())
qDebug() << __func__ << __LINE__ << sqlQuery.lastError();
}
void dataBaseOperation::modifyScrollSetData(quint32 setId, const QList<quint32> &sequence)
{
QString itemSequence;
if(!sequence.isEmpty())
itemSequence = UKUI::fromQListUIntToString(sequence);
qDebug() << __func__ << itemSequence << setId;
QSqlQuery sqlQuery;
sqlQuery.prepare("UPDATE sets SET sequence=? WHERE setId=?");
sqlQuery.addBindValue(itemSequence);
sqlQuery.addBindValue(setId);
if(!sqlQuery.exec())
qDebug() << __func__ << __LINE__ << sqlQuery.lastError();
}
bool dataBaseOperation::modifySetName(quint32 setId, QString name)
{
if(name.isEmpty())
return false;
QSqlQuery sqlQuery;
sqlQuery.prepare("UPDATE itemlist SET name=? WHERE setId=?");
sqlQuery.addBindValue(name);
sqlQuery.addBindValue(setId);
if(!sqlQuery.exec()) {
qDebug() << sqlQuery.lastError();
return false;
}
return true;
}
void dataBaseOperation::addPage(quint32 pageId, const QList<quint32> &sequence)
{
QString itemSequence = UKUI::fromQListUIntToString(sequence);
QSqlQuery sqlQuery;
if (!sqlQuery.prepare(QLatin1String("INSERT INTO page (pageId, sequence) VALUES (?, ?)")))
qDebug() << sqlQuery.lastError().text();
sqlQuery.addBindValue(pageId);
sqlQuery.addBindValue(itemSequence);
sqlQuery.exec();
// return sqlQuery.lastInsertId();
}
void dataBaseOperation::modifyPageData(quint32 pageId, const QList<quint32> &sequence)
{
QString itemSequence = UKUI::fromQListUIntToString(sequence);
qDebug() << __func__ << itemSequence << pageId;
QSqlQuery sqlQuery;
sqlQuery.prepare("UPDATE page SET sequence=? WHERE pageId=?");
sqlQuery.addBindValue(itemSequence);
sqlQuery.addBindValue(pageId);
if(!sqlQuery.exec())
qDebug() << __func__ << __LINE__ << sqlQuery.lastError();
}
void dataBaseOperation::deleteItemListData(int id)
{
if(isTableExist("itemlist")) {
QSqlQuery sqlQuery;
if(!sqlQuery.exec(QString("DELETE FROM itemlist WHERE itemId = %1").arg(id)))
qDebug() << sqlQuery.lastError();
else
qDebug() << "Delete ItemList Data success ! ! !" << "Id:" << id;
}
}
void dataBaseOperation::deletePageData(int id)
{
if (id < 0) {
qDebug() << "param id error" << id;
return;
}
if(isTableExist("page"))
{
QSqlQuery sqlQuery;
if(!sqlQuery.exec(QString("DELETE FROM page WHERE pageId = %1").arg(id)))
qDebug() << sqlQuery.lastError();
else
qDebug() << "Delete Page Data success ! ! !" << "PageId:" << id;
}
else
return;
}
void dataBaseOperation::deleteSetsData(int id)
{
if(isTableExist("sets")) {
QSqlQuery sqlQuery;
if(!sqlQuery.exec(QString("DELETE FROM sets WHERE setId = %1").arg(id)))
qDebug() << sqlQuery.lastError();
else
qDebug() << "Delete Data success ! ! !";
}
else
return;
}
void dataBaseOperation::deleteTable(const QString &tableName)
{
QSqlQuery sqlQuery;
if(!sqlQuery.exec(QString("DROP TABLE %1").arg(tableName)))
qDebug() << sqlQuery.lastError();
else
qDebug() << "Delete Table success ! ! !";
}
void dataBaseOperation::closeDataBase()
{
db.close();
}

View File

@ -0,0 +1,184 @@
#ifndef DATABASEOPERATION_H
#define DATABASEOPERATION_H
#include "types.h"
#include <QObject>
#include <QSqlDatabase>
class dataBaseOperation : public QObject
{
Q_OBJECT
public:
explicit dataBaseOperation(QObject *parent = nullptr);
~dataBaseOperation();
///
/// \brief openDataBase打开数据库
/// \return 成功 or 失败
///
bool openDataBase();
///
/// \brief 关闭数据库
///
void closeDataBase();
public:
///
/// \brief getIdleItemID获取未被使用的 item 的 ID
/// \return
///
quint32 getIdleItemID();
///
/// \brief queryAllItemData查询系统中全部的 Item 数据
/// \warning 注意指针数组一定要进行释放
/// \return 存储所有应用指针的map
///
QMap<quint32, UKUI::BaseItem *> queryAllItemData();
///
/// \brief queryAllSetData查询可以翻页的 Sets 中全部的 Item 数据
/// \return 存储 Sets 中所有的 Item 指针 <setId, <Set第一页的idlistSet第二页的idlist>>
///
QMap<quint32, QList<QList<quint32>>> queryAllFlipSetData();
///
/// \brief queryAllScrollSetData查询可以滚动的 Sets 中全部的 Item 数据
/// \return
///
QMap<quint32, QList<quint32>> queryAllScrollSetData();
///
/// \brief queryAllPageData查询 Page 中全部的 Item 数据
/// \return 存储 Page 中所有的 Item 指针 <pageId, <itemId>>
///
QMap<quint32, QList<quint32>> queryAllPageData();
///
/// \brief queryItemDataFromID根据 ID 查询全部 Item 数据
/// \param id应用的 id
///
void queryItemDataFromID(int id);
///
/// \brief queryPageDataFromID根据 ID 查询第 page 页的数据
/// \param pageIdpage 页的 id
/// \return pageId 页的所有 item
///
QList<quint32> queryPageDataFromID(int pageId);
///
/// \brief queryIdFromDesktopName根据 desktop 名字查询 id
/// \param desktopName应用的 desktop 名字
/// \return 应用的 id
///
quint32 queryIdFromDesktopName(QString desktopName);
///
/// \brief addItem在数据库中插入 Item 对象
/// \param desktopNameitem的 desktop 名字
/// \param nameitem 的名字
/// \param iconNameitem 图标的名字
/// \param typeitem 的类型
/// \param _placeholderitem 的占位符
/// \param _categoriesitem 的分类
/// \return
///
QVariant addItem(quint32 itemId, const QString &desktopName, const QString &name, const QString &iconName, const QVariant &type,
const QList<quint32> &_placeholder = {1, 1}, const QList<int> &_categories = {-1});
///
/// \brief addFlipSet在数据库中添加 container 或 group 数据
/// \param setId可翻页的set 的 id
/// \param sequenceset 内的应用列表
/// \return
///
QVariant addFlipSet(quint32 setId, const QList<QList<quint32>> &sequence);
///
/// \brief addScrollSet在数据库中添加 container 或 group 数据
/// \param setId可滚动的set 的 id
/// \param sequence
/// \return
///
QVariant addScrollSet(quint32 setId, const QList<quint32> &sequence);
///
/// \brief addPage在数据库中添加 page 数据
/// \param pageIdpage 页的 id
/// \param sequencepage 内的应用列表
///
void addPage(quint32 pageId, const QList<quint32> &sequence);
///
/// \brief modifyItemData修改应用的数据
/// \param id应用 id
/// \param desktopName应用的 desktop 名字
/// \param name应用显示的名字
/// \param iconName应用图标的名字
/// \param _categories应用的分类
///
void modifyItemData(quint32 id, const QString &desktopName, const QString &name, const QString &iconName, const QList<int> &_categories);
///
/// \brief modifyFlipSetData修改 container 或者 group 里的应用列表
/// \param setIdcontainer 或 group 的 id
/// \param sequence应用列表
///
void modifyFlipSetData(quint32 setId, const QList<QList<quint32>> &sequence);
///
/// \brief modifyScrollSetData
/// \param setId
/// \param sequence
///
void modifyScrollSetData(quint32 setId, const QList<quint32> &sequence);
///
/// \brief modifySetName修改 container 或者 group 的名字
/// \param setId待修改的 group/container 的id
/// \param nameSet的名字
/// \return true为修改成功false修改失败
///
bool modifySetName(quint32 setId, QString name);
///
/// \brief modifyPageData 修改 page 页的数据
/// \param pageId page 页的 id
/// \param sequence page 页即将存储的应用列表
///
void modifyPageData(quint32 pageId, const QList<quint32> &sequence);
///
/// \brief deleteItemListData 从列表中删除应用
/// \param id 应用的 id
///
void deleteItemListData(int id);
///
/// \brief deletePageData 删除页数据
/// \param id 页的 id
///
void deletePageData(int id);
///
/// \brief deleteSetsData 删除分组数据
/// \param id 分组的 id
///
void deleteSetsData(int id);
///
/// \brief 删除数据表
/// \param tableName 数据表名字
///
void deleteTable(const QString &tableName);
private:
///
/// \brief createDefaultTable创建默认数据表
///
void createDefaultTable();
///
/// \brief createItemsData创建默认的 item 数据
///
void createItemsData();
///
/// \brief updatePageTable根据 item 表和 sets 表确定 page 表
///
void updatePageTable();
///
/// \brief isTableExist判断数据表是否存在
/// \param tableName表的名字
/// \return 存在 or 不存在
///
bool isTableExist(const QString &tableName);
signals:
private:
QSqlDatabase db;
quint32 idleItemId;
};
#endif // DATABASEOPERATION_H

View File

@ -0,0 +1,45 @@
#include "icon-theme.h"
#include <KIconTheme>
#include <QGSettings>
#include <QIcon>
#include <QDebug>
namespace UKUI {
static IconTheme* g_icon_theme;
IconTheme::IconTheme()
{
initConnect();
}
IconTheme* IconTheme::getInstance()
{
if (!g_icon_theme)
g_icon_theme = new IconTheme();
return g_icon_theme;
}
QString IconTheme::getPathFromName(QString iconName, uint iconSize)
{
KIconTheme iconInfo(QIcon::themeName());
return iconInfo.iconPathByName(iconName, iconSize, KIconLoader::MatchBest);
}
void IconTheme::initConnect()
{
if (!QGSettings::isSchemaInstalled("org.ukui.style")) {
qWarning() << __FUNCTION__ << __FILE__ << "can not find schema org.ukui.style";
return;
}
QGSettings* iconThemeSettings = new QGSettings("org.ukui.style", "/org/ukui/style/");
connect(iconThemeSettings, &QGSettings::changed, [&](const QString& value) {
if (value == "iconThemeName") {
emit iconThemeChanged();
}
});
}
} // namespace UKUI

View File

@ -0,0 +1,34 @@
#ifndef ICONTHEME_H
#define ICONTHEME_H
#include <QObject>
namespace UKUI {
class IconTheme : public QObject
{
Q_OBJECT
public:
static IconTheme* getInstance();
/*!
* \brief getPathFromName
* \details get picture file path from icon name
* \param icon name
* \return absolute path of picture file
* \sa KIconTheme
*/
QString getPathFromName(QString iconName, uint iconSize);
signals:
//! \brief send while icon theme gsetting changed
void iconThemeChanged();
private:
IconTheme();
void initConnect();
};
} // namespace UKUI
#endif // ICONTHEME_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,380 @@
#ifndef KYLINTABLETDESKTOPBACKEND_H
#define KYLINTABLETDESKTOPBACKEND_H
#include "database-operation.h"
#include "kylin-tablet-desktop-backend_global.h"
#include "types.h"
#include "icon-theme.h"
#include "ukuisettings.h"
#include <QGSettings>
#include <QObject>
#include <KDirLister>
#include <QFileSystemWatcher>
class QString;
///
/// \brief 应用转换存储位置,该结构体中存储着需要传递给前端的内容信息
///
typedef struct appChangePositionInfo
{
bool isTaskbarDeleteApp = false; //taskbar是否是删除应用操作false不是删除操作是增加操作 true是删除操作
bool isDesktopDeleteApp = false; //desktop是否是删除应用操作false不是删除操作是增加操作 true是删除操作
bool isExchangePosition = false; //任务栏的应用是否交换位置
int itemId; //应用在数据库中的id
int itemFromPage; //应用来自于哪页
int itemToPage; //应用移动到哪页
int itemFromPageIndex; //应用来自于哪页的那个位置
int itemToPageIndex; //应用移动到哪页的哪个位置
int itemFromSet; //返回来自哪个集合id,-1代表非集合其他数字代表集合id
int itemToSet; //返回移动到哪个集合的id
}appChangeInfo;
namespace UKUI {
/*
* Readme
* 1. num1 x num2
*/
class KYLINTABLETDESKTOPBACKEND_EXPORT kylinTabletDesktopBackend : public QObject
{
Q_OBJECT
public:
explicit kylinTabletDesktopBackend();
~kylinTabletDesktopBackend();
public:
///
/// \brief getLauncherLine获取Launcher界面的行数
/// \return
///
quint32 getLauncherLine() {
return m_line;
}
///
/// \brief getLauncherColumn获取Launcher界面的列数
/// \return
///
quint32 getLauncherColumn() {
return m_column;
}
///
/// \brief 获取所有 item 信息,包括 icon、group、container、widget等
///
QMap<quint32, BaseItem *> getAllItemData() {
return m_baseItemList;
}
///
/// \brief 获取所有 page 页的 item id列表
///
QMap<quint32, QList<quint32>> getAllPageData() {
return allPage;
}
///
/// \brief getAllFlipSetsData获取所有可以翻页的 container 或者 group 的 item id 列表
///
QMap<quint32, QList<QList<quint32>>> getAllFlipSetsData() {
return allFlipSets;
}
///
/// \brief getAllScrollSetsData获取所有可以滚动的 container 或者 group 的 item id 列表
/// \return
///
QMap<quint32, QList<quint32>> getAllScrollSetsData() {
return allScrollSets;
}
///
/// \brief 获取所有应用分类
/// \return 返回分类的列表 和 图标名称
///
QMap<Categories, QString> getAllAppCategories();
///
/// \brief 根据传入的分类类型获取应用 id 列表
/// \param type 分类类型
/// \return 应用 id 列表
///
QList<quint32> getAppIdListAccordingCategory(Categories type);
///
/// \brief 获取所有应用的 id 列表,列表按字母排序
/// \return id 列表
///
QList<quint32> getAllAppIdList();
///
/// \brief 根据传入的图标名字从主题获取图标的绝对路径
/// \param iconName 图标名字
/// \param size 图标大小例如16x1616x16@2x24x2432x3248x4864x6496x96128x128256x256
/// \return 图标的绝对路径
///
QString getAbsoluteIconPath(QString iconName, quint32 size);
///
/// \brief 后台数据库新建应用页
/// \param page 新加页的页数
///
void addLauncherPage(int page);
///
/// \brief 当 page 页为空时,删除该应用页
/// \param page 删除页的页数
///
void deleteLauncherPage(int page);
///
/// \brief 修改第 pageId 页的itemList
/// \param pageID 修改的 page 页的页数
/// \param itemIdList page页的item id列表
///
///
///
/// \brief 同页内移动图标 / 组时
/// 前台可以直接调用 modifyPageData(quint32 pageId, const QList<quint32> &itemList)
///
/// \brief 不同页间移动图标 / 组时
/// 前台可以直接调用 modifyPageData(quint32 fromPageId, const QList<quint32> &itemList)
/// 和 modifyPageData(quint32 toPageId, const QList<quint32> &itemList)
///
void modifyPageData(quint32 pageId, const QList<quint32> &itemIdList);
///
/// \brief 修改 id 为 setId 的 sets 页的 itemIdList存放到Set中的应用通过翻页查找
/// \param setId 待修改的 group/container 的id
/// \param itemIdList group/container 的item id列表
///
void modifyFlipSetData(quint32 setId, const QList<QList<quint32>> &itemIdList);
///
/// \brief 修改 id 为 setId 的 sets 页的 itemIdList存放到Set中的应用可以上下滑动查找
/// \param setId 待修改的 group/container 的id
/// \param itemIdList group/container 的item id列表
///
void modifyScrollSetData(quint32 setId, const QList<quint32> &itemIdList);
///
/// \brief 修改 container 或者 group 的名字
/// \param setId 待修改的 group/container 的id
/// \return true为修改成功 false修改失败
///
bool modifySetName(quint32 setId, QString name);
///
/// \brief updateExistIdlePage更新第一个空闲位置的 Item 所在的页数
/// \return 返回存在空闲位置的page页的空闲位置个数
///
quint32 updateExistIdlePage();
///
/// \brief updateTaskBarAppList更新任务栏的应用列表
///
void updateTaskBarAppList();
///
/// \brief getIdleItemID获取未被使用的 item 的 ID
/// \return
///
quint32 getIdleItemID();
///
/// \brief createGroup两个应用合并时新建分组
/// \param groupId
/// \param itemIdList
/// \param groupName
/// \param scrollable
///
void createGroup(quint32 groupId, QList<quint32> itemIdList, const QString groupName = QString(), bool scrollable = false);
///
/// \brief createGroup两个应用合并时新建分组
/// \param fromItemId
/// \param toItemId
/// \param groupName分组的名字可以为空
/// \return
///
// quint32 createGroup(quint32 fromItemId, quint32 toItemId, const QString &groupName = QString(), bool scrollable = false);
///
/// \brief deleteGroup delete group
/// \param setId
///
void deleteGroup(quint32 setId);
public slots:
///
/// \brief taskbarAppChange 任务栏的应用变化
///
void taskBarAppChange();
///
/// \brief taskbarAppChange 任务栏的应用变化
///
void taskBarAppChange(QList<quint32> &taskBarAppData);
private slots:
///
/// \brief 将应用存储到数据库
///
void onItemsAdded(const QUrl &directoryUrl, const KFileItemList &items);
void onItemsDeleted(const KFileItemList &items);
signals:
void filechanged();
///
/// \brief 新建 page 页后触发此信号,现在未使用该信号,
/// 新安装的应用在上报时参数会传递页的id所以前台可以在也不存在时新建即可
///
void pageAdded(quint32 page);
///
/// \brief 删除 page 页后触发此信号
///
void pageDeleted(quint32 page);
///
/// \brief 新增 item 后触发此信号
///
void itemAdded(quint32 id, quint32 pageId);
///
/// \brief 从 Page 页删除 item 后触发此信号
///
void itemDeletedFromPage(quint32 id, quint32 pageId);
///
/// \brief 从 Sets 删除 item 后触发此信号
///
void itemDeletedFromSet(quint32 id, quint32 setId);
///
/// \brief 删除 set 的 page 页后触发此信号
/// \param id 删除 page 页的set的id注意不是页数
///
void setsPageDeleted(quint32 id);
///
/// \brief 图标主题改变信号
///
void iconThemeChanged();
///
/// \brief 所有应用遍历完成后发送此信号, 后台专用,前台没必要监听
///
void firstTraversalCompleted();
///
/// \brief taskBarAppChanged任务栏应用数据改变信号
/// 结构体存储被移动的应用信息
///
void taskBarAppChanged(struct appChangePositionInfo &appChangePosition);
private:
///创建结构体对象
// appChangeInfo appChangePositionData;
///
/// \brief 监听 desktop 文件的增删
///
void desktopFileWatcher();
///
/// \brief panelConfFileWatcher 监听panel.conf的变化
///
void panelConfFileWatcher();
///
/// \brief 读取数据库,获取应用信息
///
void loadPositions();
///
/// \brief loadTaskBarData加载任务栏的应用数据如果有变化的话同步修改到数据库
///
void loadTaskBarData();
///
/// \brief 当图标主题发生变化时,修改内存中保存的图标路径;并向前台发送信号;
///
void monitorIconThemeChange();
///
/// \brief 删除 / 增加空白页
///
void refreshPageDataBase();
///
/// \brief 更新应用信息到数据库
///
void refreshAllLocation();
///
/// \brief 用来过滤掉不应该显示到桌面的应用比如fcitx、wps配置应用驱动应用等
///
QStringList getBlackListApp();
///
/// \brief 匹配应用 Category
/// \param 应用的分类
/// \param 教育、网络、社交等分类列表
/// \return
///
bool matchingAppCategories(QString category, QStringList categorylist);
///
/// \brief sortAppIdAccordingLetter
/// \param unorderedIdList 无序AppId列表
/// \return 有序AppId列表
///
QList<quint32> sortAppIdAccordingLetter(QList<quint32> &unorderedIdList);
///
/// \brief 获取数据库中的所有被删除应用的 id要将这部分应用从数据库中删除
///
void checkIfDatabaseExistDeletedApp();
///
/// \brief 删除该项时,可能出现删除页该项后为空的情况,所以需要判断是否存在空页
/// 如果出现空页,删除空页,并更新位置配置文件
/// \param id baseItem 的id
///
void removeLauncherItem(quint32 id);
quint32 getAppIdAccordingString(const QString desktopName);
///
/// \brief readPanelConf 读取.cache/ukui/panel.conf
///
QList<quint32> readPanelConf();
private:
///
/// \brief m_idlePosPage存在空余位置的 page 页 id
///
qint32 m_idlePosPage;
QMap<quint32, BaseItem *> m_baseItemList;
QMap<quint32, QList<quint32>> allPage;
QMap<quint32, QList<QList<quint32>>> allFlipSets; // 所有的可翻页的应用分组
QMap<quint32, QList<quint32>> allScrollSets; // 所有可滚动的应用分组,任务栏数据存储到可滚动应用分组里
QList<quint32> m_shoudBeRemovedApp; // 存储平板桌面后台没有监测到删除或者没有删除成功的应用 ID在启动初期将这些应用删除
QList<quint32> m_allItemList;
KDirLister *m_appListener;
QFileSystemWatcher *m_Filewatcher; // 监听panel.conf变化
dataBaseOperation* m_database;
quint32 m_line;
quint32 m_column;
qint32 m_maxPage;
IconTheme* m_icon_theme;
quint32 m_loadCount;
quint32 m_notEmptyDir;
QGSettings *m_tabletLauncher;
Settings *m_panelSettings;
bool isFirstStart;
};
}
#endif // KYLINTABLETDESKTOPBACKEND_H

View File

@ -0,0 +1,66 @@
QT -= gui
QT += core KIOCore KIOFileWidgets KIOWidgets KNTLM sql KIconThemes
TEMPLATE = lib
CONFIG += plugin
DEFINES += KYLINTABLETDESKTOPBACKEND_LIBRARY
CONFIG += c++11
CONFIG += link_pkgconfig
PKGCONFIG += gsettings-qt
# include(baseHead.pri)
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
appnamesort.cpp \
database-operation.cpp \
icon-theme.cpp \
kylin-tablet-desktop-backend.cpp \
ukuisettings.cpp \
utils.cpp
HEADERS += \
appnamesort.h \
database-operation.h \
icon-theme.h \
types.h \
kylin-tablet-desktop-backend_global.h \
kylin-tablet-desktop-backend.h \
ukuisettings.h \
utils.h
TRANSLATIONS += \
translations/zh_CN.ts
isEmpty(PREFIX) {
PREFIX = /usr
}
schemas.files += *.xml
schemas.path = /usr/share/glib-2.0/schemas/
qm_files.path = $${PREFIX}/share/kylin-tablet-desktop-backend/translations
qm_files.files = translations/*
CONFIG(release, debug|release) {
!system($$PWD/translate_generation.sh): error("Failed to generate translation")
}
INSTALLS += \
qm_files \
schemas
# Default rules for deployment.
unix {
target.path = /usr/lib
}
!isEmpty(target.path): INSTALLS += target

View File

@ -0,0 +1,12 @@
#ifndef KYLINTABLETDESKTOPBACKEND_GLOBAL_H
#define KYLINTABLETDESKTOPBACKEND_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(KYLINTABLETDESKTOPBACKEND_LIBRARY)
# define KYLINTABLETDESKTOPBACKEND_EXPORT Q_DECL_EXPORT
#else
# define KYLINTABLETDESKTOPBACKEND_EXPORT Q_DECL_IMPORT
#endif
#endif // KYLINTABLETDESKTOPBACKEND_GLOBAL_H

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
<schema id="org.kylin-tablet-desktop" path="/org/kylin-tablet-desktop/">
<key name="is-first-start" type="b">
<default>true</default>
<summary>is kylin tablet desktop start firstly</summary>
<description>Is kylin tablet desktop start firstly.</description>
</key>
<key name="line" type="i">
<default>4</default>
<summary>line number of launcher</summary>
<description>The line number of kylin desktop launcher</description>
</key>
<key name="column" type="i">
<default>6</default>
<summary>column number of launcher</summary>
<description>The column number of kylin desktop launcher</description>
</key>
</schema>
</schemalist>

View File

@ -0,0 +1,15 @@
#!/bin/bash
ts_list=(`ls translations/*.ts`)
source /etc/os-release
version=(`echo $ID`)
for ts in "${ts_list[@]}"
do
printf "\nprocess ${ts}\n"
if [ "$version" == "fedora" ] || [ "$version" == "opensuse-leap" ] || [ "$version" == "opensuse-tumbleweed" ];then
lrelease-qt5 "${ts}"
else
lrelease "${ts}"
fi
done

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN">
<context>
<name>UKUI::kylinTabletDesktopBackend</name>
<message>
<source>education</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../kylin-tablet-desktop-backend.cpp" line="426"/>
<source>Mobile</source>
<translation></translation>
</message>
<message>
<location filename="../kylin-tablet-desktop-backend.cpp" line="427"/>
<source>Internet</source>
<translation></translation>
</message>
<message>
<location filename="../kylin-tablet-desktop-backend.cpp" line="428"/>
<source>Social</source>
<translation></translation>
</message>
<message>
<location filename="../kylin-tablet-desktop-backend.cpp" line="429"/>
<source>Video</source>
<translation></translation>
</message>
<message>
<location filename="../kylin-tablet-desktop-backend.cpp" line="430"/>
<source>Development</source>
<translation></translation>
</message>
<message>
<location filename="../kylin-tablet-desktop-backend.cpp" line="431"/>
<source>Image</source>
<translation></translation>
</message>
<message>
<location filename="../kylin-tablet-desktop-backend.cpp" line="432"/>
<source>Game</source>
<translation></translation>
</message>
<message>
<location filename="../kylin-tablet-desktop-backend.cpp" line="433"/>
<source>Office</source>
<translation></translation>
</message>
<message>
<location filename="../kylin-tablet-desktop-backend.cpp" line="434"/>
<source>Education</source>
<translation></translation>
</message>
<message>
<location filename="../kylin-tablet-desktop-backend.cpp" line="435"/>
<source>System</source>
<translation></translation>
</message>
<message>
<location filename="../kylin-tablet-desktop-backend.cpp" line="436"/>
<source>Others</source>
<translation></translation>
</message>
</context>
</TS>

View File

@ -0,0 +1,10 @@
#include "types.h"
namespace UKUI {
BaseItem::BaseItem(Position pos, QString name, qint32 id, Type type) :
m_location(pos), m_name(name), m_identify(id), m_type(type) {}
//BaseItem::~BaseItem() {}
}

View File

@ -0,0 +1,140 @@
#ifndef TYPES_H
#define TYPES_H
#include <QtGlobal>
#include <QRect>
#include <QString>
#include <QList>
#include <QDebug>
namespace UKUI {
enum class Categories {
Android = 0, // 0 安卓
Network, // 1 网络
Messaging, // 2 社交
Audio, // 3 影音
Development, // 4 开发
Graphics, // 5 图像
Game, // 6 游戏
Office, // 7 办公
Education, // 8 教育
System, // 9 系统
Other // 10 其他
};
enum class Type {
Icon = 1,
Group,
Container,
Widget,
Unknown
};
class BaseItem {
public:
BaseItem(QString name, qint32 id, QList<int> categories = {-1}, Type type = Type::Unknown, QList<int> placeholder = {1,1}) :
m_name(name), m_identify(id), m_type(type), m_placeholder(placeholder), m_categories(categories) {}
virtual ~BaseItem() {}
void setName(QString name) {
m_name = name;
}
QString getName() {
return m_name;
}
void setId(qint32 id) {
m_identify = id;
}
quint32 getId() {
return m_identify;
}
void setType(Type type) {
m_type = type;
}
Type getType() {
return m_type;
}
void setPlaceHolder(QList<int> place) {
m_placeholder = place;
}
QList<int> getPlaceHolder() {
return m_placeholder;
}
void setCategories(QList<int> categories) {
m_categories = categories;
}
QList<int> getCategories() {
return m_categories;
}
private:
QString m_name;
quint32 m_identify;
Type m_type;
QList<int> m_placeholder;
QList<int> m_categories;
};
class IconItem : public BaseItem
{
public:
IconItem(QString desktopName, QString name, qint32 id, QString iconName, QList<int> categories, Type type = Type::Icon) :
BaseItem(name, id, categories, type), m_desktopName(desktopName), m_icon(iconName) {}
~IconItem() {}
QString getDesktopName() {
return m_desktopName;
}
const QString getIconName() {
return m_icon;
}
void setIconName(QString name) {
m_icon = name;
}
private:
QString m_desktopName;
QString m_icon;
};
class Widget : public BaseItem
{
public:
Widget(QString name, qint32 id, QList<int> placeholder, Type type = Type::Widget) :
BaseItem(name, id, {-1}, type, placeholder) {}
~Widget() {}
};
class GroupItem : public BaseItem
{
public:
GroupItem(QString name, qint32 id, Type type = Type::Group, bool isScrollable = false) :
BaseItem(name, id, {-1}, type) {}
bool isScrollLayout() {
return isScrollable;
}
void setScrollLayout(bool scroll) {
isScrollable = scroll;
}
~GroupItem() {}
private:
bool isScrollable;
};
class ContainerItem : public BaseItem
{
public:
ContainerItem(QString name, qint32 id, QList<int> placeholder = {2,2}, Type type = Type::Container, bool isScrollable = false) :
BaseItem(name, id, {-1}, type, placeholder) {}
~ContainerItem() {}
bool isScrollLayout() {
return isScrollable;
}
void setScrollLayout(bool scroll) {
isScrollable = scroll;
}
private:
bool isScrollable;
};
}
#endif // TYPES_H

View File

@ -0,0 +1,129 @@
#include "ukuisettings.h"
#include <QDebug>
Settings::Settings(const QString &fileName, Format format, const QString group, QObject *parent) :
QSettings(fileName, format, parent)
, m_group(group)
{
}
QString Settings::group() const
{
return m_group;
}
void Settings::setGroup(const QString &group)
{
m_group = group;
}
Settings::~Settings()
{
}
QVariant Settings::value(const QString &key, const QVariant &defaultValue)
{
QSettings::beginGroup(m_group);
QVariant value = QSettings::value(key, defaultValue);
QSettings::endGroup();
return value;
}
void Settings::setValue(const QString &key, const QVariant &value)
{
QSettings::beginGroup(m_group);
QSettings::setValue(key, value);
QSettings::endGroup();
emit settingsChanged();
}
void Settings::remove(const QString &key)
{
QSettings::beginGroup(m_group);
QSettings::remove(key);
QSettings::endGroup();
emit settingsChanged();
}
bool Settings::contains(const QString &key)
{
QSettings::beginGroup(m_group);
bool ret = QSettings::contains(key);
QSettings::endGroup();
return ret;
}
QList<QMap<QString, QVariant> > Settings::readArray(const QString& prefix)
{
QSettings::beginGroup(m_group);
QList<QMap<QString, QVariant> > array;
int size = QSettings::beginReadArray(prefix);
for (int i = 0; i < size; ++i)
{
QSettings::setArrayIndex(i);
QMap<QString, QVariant> map;
const auto keys = QSettings::childKeys();
for (const QString &key : keys) {
map[key] = QSettings::value(key);
}
if (array.contains(map)) {
continue;
} else {
array << map;
}
}
QSettings::endArray();
QSettings::endGroup();
return array;
}
void Settings::setArray(const QString &prefix, const QList<QMap<QString, QVariant> > &hashList)
{
QSettings::beginGroup(m_group);
QSettings::beginWriteArray(prefix);
// 清空原来的所有key/value
QSettings::remove("");
int size = hashList.size();
for (int i = 0; i < size; ++i)
{
QSettings::setArrayIndex(i);
QMapIterator<QString, QVariant> it(hashList.at(i));
while (it.hasNext())
{
it.next();
QSettings::setValue(it.key(), it.value());
}
}
QSettings::endArray();
QSettings::endGroup();
emit settingsChanged();
}
void Settings::clear()
{
QSettings::beginGroup(m_group);
QSettings::clear();
QSettings::endGroup();
emit settingsChanged();
}
QStringList Settings::allKeys()
{
QSettings::beginGroup(m_group);
QStringList keys = QSettings::allKeys();
QSettings::endGroup();
return keys;
}
QStringList Settings::childGroups()
{
QSettings::beginGroup(m_group);
QStringList groups = QSettings::childGroups();
QSettings::endGroup();
return groups;
}
bool Settings::event(QEvent *event)
{
return QSettings::event(event);
}

View File

@ -0,0 +1,42 @@
#ifndef SETTINGS_H
#define SETTINGS_H
#include <QObject>
#include <QSettings>
class Settings : public QSettings
{
Q_OBJECT
public:
Settings(const QString &fileName, Format format, const QString group, QObject *parent = nullptr);
~Settings();
QString group() const;
void setGroup(const QString &group);
QVariant value(const QString &key, const QVariant &defaultValue = QVariant());
void setValue(const QString &key, const QVariant &value);
void remove(const QString &key);
bool contains(const QString &key);
QList<QMap<QString, QVariant> > readArray(const QString &prefix);
void setArray(const QString &prefix, const QList<QMap<QString, QVariant> > &hashList);
void clear();
QStringList allKeys();
QStringList childGroups();
signals:
void settingsChanged();
protected:
bool event(QEvent *event);
private:
QString m_group;
};
#endif // SETTINGS_H

View File

@ -0,0 +1,31 @@
#include "utils.h"
namespace UKUI {
QString fromQListIntToString(const QList<int> sequence)
{
QString itemSequence;
if(!sequence.isEmpty()) {
itemSequence = QString::number(sequence.first());
for(int i = 1; i < sequence.size(); i++) {
itemSequence += QString(",") += QString::number(sequence.at(i));
}
}
return itemSequence;
}
QString fromQListUIntToString(const QList<quint32> sequence)
{
QString itemSequence;
if(!sequence.isEmpty()) {
itemSequence = QString::number(sequence.first());
for(int i = 1; i < sequence.size(); i++) {
itemSequence += QString(",") += QString::number(sequence.at(i));
}
}
return itemSequence;
}
}

View File

@ -0,0 +1,27 @@
#ifndef UTILS_H
#define UTILS_H
#include <QString>
#include <QList>
namespace UKUI {
///
/// \brief fromQListIntToString将QList<int>转为以逗号分割的字符串
/// \param QList<int>
/// \return 以逗号分割的字符串
///
QString fromQListIntToString(const QList<int> sequence);
///
/// \brief fromQListUIntToString将QList<uint>转为以逗号分割的字符串
/// \param QList<uint>
/// \return 以逗号分割的字符串
///
QString fromQListUIntToString(const QList<quint32> sequence);
// TODO: 以二进制格式存储到数据库
}
#endif // UTILS_H

View File

@ -0,0 +1,13 @@
TEMPLATE = subdirs
CONFIG += debug_and_release
SUBDIRS += \
check-qtqtuick-scene-render-loop \
kylin-tablet-desktop \
kylin-tablet-desktop-backend
CONFIG(debug, debug|release) {
SUBDIRS += \
# tests
} else {
}

View File

@ -0,0 +1,38 @@
QT += quick quick-private core-private
CONFIG += c++11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
# $$PWD/kquickflickable.cpp \
# $$PWD/kquickgridview.cpp \
# $$PWD/kquickitemview.cpp \
# $$PWD/kquickitemviewfxitem.cpp \
# $$PWD/kquicklistview.cpp \
# $$PWD/kquicksmoothedanimation.cpp \
# $$PWD/kquicktimeline.cpp
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
HEADERS += \
# $$PWD/kquickflickable.h \
# $$PWD/kquickflickable_p.h \
# $$PWD/kquickflickablebehavior_p.h \
# $$PWD/kquickgridview.h \
# $$PWD/kquickitemview.h \
# $$PWD/kquickitemview_p.h \
# $$PWD/kquickitemviewfxitem_p.h \
# $$PWD/kquicklistview.h \
# $$PWD/kquicksmoothedanimation.h \
# $$PWD/kquicksmoothedanimation_p.h \
# $$PWD/kquicktimeline.h
message($$PWD)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,277 @@
#ifndef KQUICKFLICKABLE_H
#define KQUICKFLICKABLE_H
#include "qquickitem.h"
#include <private/qtquickglobal_p.h>
QT_BEGIN_NAMESPACE
class KQuickFlickablePrivate;
class KQuickFlickableVisibleArea;
class KQuickFlickable : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged)
Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged)
Q_PROPERTY(qreal contentX READ contentX WRITE setContentX NOTIFY contentXChanged)
Q_PROPERTY(qreal contentY READ contentY WRITE setContentY NOTIFY contentYChanged)
Q_PROPERTY(QQuickItem *contentItem READ contentItem CONSTANT)
Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
Q_PROPERTY(qreal originY READ originY NOTIFY originYChanged)
Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
Q_PROPERTY(qreal originX READ originX NOTIFY originXChanged)
Q_PROPERTY(qreal horizontalVelocity READ horizontalVelocity NOTIFY horizontalVelocityChanged)
Q_PROPERTY(qreal verticalVelocity READ verticalVelocity NOTIFY verticalVelocityChanged)
Q_PROPERTY(BoundsBehavior boundsBehavior READ boundsBehavior WRITE setBoundsBehavior NOTIFY boundsBehaviorChanged)
Q_PROPERTY(BoundsMovement boundsMovement READ boundsMovement WRITE setBoundsMovement NOTIFY boundsMovementChanged REVISION 10)
Q_PROPERTY(QQuickTransition *rebound READ rebound WRITE setRebound NOTIFY reboundChanged)
Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity NOTIFY maximumFlickVelocityChanged)
Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged)
Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged)
Q_PROPERTY(bool movingHorizontally READ isMovingHorizontally NOTIFY movingHorizontallyChanged)
Q_PROPERTY(bool movingVertically READ isMovingVertically NOTIFY movingVerticallyChanged)
Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged)
Q_PROPERTY(bool flickingHorizontally READ isFlickingHorizontally NOTIFY flickingHorizontallyChanged)
Q_PROPERTY(bool flickingVertically READ isFlickingVertically NOTIFY flickingVerticallyChanged)
Q_PROPERTY(bool dragging READ isDragging NOTIFY draggingChanged)
Q_PROPERTY(bool draggingHorizontally READ isDraggingHorizontally NOTIFY draggingHorizontallyChanged)
Q_PROPERTY(bool draggingVertically READ isDraggingVertically NOTIFY draggingVerticallyChanged)
Q_PROPERTY(FlickableDirection flickableDirection READ flickableDirection WRITE setFlickableDirection NOTIFY flickableDirectionChanged)
Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged)
Q_PROPERTY(int pressDelay READ pressDelay WRITE setPressDelay NOTIFY pressDelayChanged)
Q_PROPERTY(bool atXEnd READ isAtXEnd NOTIFY atXEndChanged)
Q_PROPERTY(bool atYEnd READ isAtYEnd NOTIFY atYEndChanged)
Q_PROPERTY(bool atXBeginning READ isAtXBeginning NOTIFY atXBeginningChanged)
Q_PROPERTY(bool atYBeginning READ isAtYBeginning NOTIFY atYBeginningChanged)
Q_PROPERTY(KQuickFlickableVisibleArea *visibleArea READ visibleArea CONSTANT)
Q_PROPERTY(bool pixelAligned READ pixelAligned WRITE setPixelAligned NOTIFY pixelAlignedChanged)
Q_PROPERTY(bool synchronousDrag READ synchronousDrag WRITE setSynchronousDrag NOTIFY synchronousDragChanged REVISION 12)
Q_PROPERTY(qreal horizontalOvershoot READ horizontalOvershoot NOTIFY horizontalOvershootChanged REVISION 9)
Q_PROPERTY(qreal verticalOvershoot READ verticalOvershoot NOTIFY verticalOvershootChanged REVISION 9)
Q_PROPERTY(QQmlListProperty<QObject> flickableData READ flickableData)
Q_PROPERTY(QQmlListProperty<QQuickItem> flickableChildren READ flickableChildren)
Q_CLASSINFO("DefaultProperty", "flickableData")
public:
KQuickFlickable(QQuickItem *parent=nullptr);
~KQuickFlickable();
QQmlListProperty<QObject> flickableData();
QQmlListProperty<QQuickItem> flickableChildren();
enum BoundsBehaviorFlag {
StopAtBounds = 0x0,
DragOverBounds = 0x1,
OvershootBounds = 0x2,
DragAndOvershootBounds = DragOverBounds | OvershootBounds
};
Q_DECLARE_FLAGS(BoundsBehavior, BoundsBehaviorFlag)
Q_FLAG(BoundsBehavior)
BoundsBehavior boundsBehavior() const;
void setBoundsBehavior(BoundsBehavior);
enum BoundsMovement {
// StopAtBounds = 0x0,
FollowBoundsBehavior = 0x1
};
Q_ENUM(BoundsMovement)
BoundsMovement boundsMovement() const;
void setBoundsMovement(BoundsMovement movement);
QQuickTransition *rebound() const;
void setRebound(QQuickTransition *transition);
qreal contentWidth() const;
void setContentWidth(qreal);
qreal contentHeight() const;
void setContentHeight(qreal);
qreal contentX() const;
virtual void setContentX(qreal pos);
qreal contentY() const;
virtual void setContentY(qreal pos);
qreal topMargin() const;
void setTopMargin(qreal m);
qreal bottomMargin() const;
void setBottomMargin(qreal m);
qreal leftMargin() const;
void setLeftMargin(qreal m);
qreal rightMargin() const;
void setRightMargin(qreal m);
virtual qreal originY() const;
virtual qreal originX() const;
bool isMoving() const;
bool isMovingHorizontally() const;
bool isMovingVertically() const;
bool isFlicking() const;
bool isFlickingHorizontally() const;
bool isFlickingVertically() const;
bool isDragging() const;
bool isDraggingHorizontally() const;
bool isDraggingVertically() const;
int pressDelay() const;
void setPressDelay(int delay);
qreal maximumFlickVelocity() const;
void setMaximumFlickVelocity(qreal);
qreal flickDeceleration() const;
void setFlickDeceleration(qreal);
bool isInteractive() const;
void setInteractive(bool);
qreal horizontalVelocity() const;
qreal verticalVelocity() const;
bool isAtXEnd() const;
bool isAtXBeginning() const;
bool isAtYEnd() const;
bool isAtYBeginning() const;
QQuickItem *contentItem() const;
enum FlickableDirection { AutoFlickDirection=0x0, HorizontalFlick=0x1, VerticalFlick=0x2, HorizontalAndVerticalFlick=0x3,
AutoFlickIfNeeded=0xc };
Q_ENUM(FlickableDirection)
FlickableDirection flickableDirection() const;
void setFlickableDirection(FlickableDirection);
bool pixelAligned() const;
void setPixelAligned(bool align);
bool synchronousDrag() const;
void setSynchronousDrag(bool v);
qreal horizontalOvershoot() const;
qreal verticalOvershoot() const;
Q_INVOKABLE void resizeContent(qreal w, qreal h, QPointF center);
Q_INVOKABLE void returnToBounds();
Q_INVOKABLE void flick(qreal xVelocity, qreal yVelocity);
Q_INVOKABLE void cancelFlick();
Q_SIGNALS:
void contentWidthChanged();
void contentHeightChanged();
void contentXChanged();
void contentYChanged();
void topMarginChanged();
void bottomMarginChanged();
void leftMarginChanged();
void rightMarginChanged();
void originYChanged();
void originXChanged();
void movingChanged();
void movingHorizontallyChanged();
void movingVerticallyChanged();
void flickingChanged();
void flickingHorizontallyChanged();
void flickingVerticallyChanged();
void draggingChanged();
void draggingHorizontallyChanged();
void draggingVerticallyChanged();
void horizontalVelocityChanged();
void verticalVelocityChanged();
void isAtBoundaryChanged();
void flickableDirectionChanged();
void interactiveChanged();
void boundsBehaviorChanged();
Q_REVISION(10) void boundsMovementChanged();
void reboundChanged();
void maximumFlickVelocityChanged();
void flickDecelerationChanged();
void pressDelayChanged();
void movementStarted();
void movementEnded();
void flickStarted();
void flickEnded();
void dragStarted();
void dragEnded();
void pixelAlignedChanged();
Q_REVISION(12) void synchronousDragChanged();
Q_REVISION(9) void horizontalOvershootChanged();
Q_REVISION(9) void verticalOvershootChanged();
// The next four signals should be marked as Q_REVISION(12). See QTBUG-71243
void atXEndChanged();
void atYEndChanged();
void atXBeginningChanged();
void atYBeginningChanged();
protected:
bool childMouseEventFilter(QQuickItem *, QEvent *) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
#if QT_CONFIG(wheelevent)
void wheelEvent(QWheelEvent *event) override;
#endif
void timerEvent(QTimerEvent *event) override;
KQuickFlickableVisibleArea *visibleArea();
protected Q_SLOTS:
void movementStarting();
void movementEnding();
void movementEnding(bool hMovementEnding, bool vMovementEnding);
void velocityTimelineCompleted();
void timelineCompleted();
protected:
virtual qreal minXExtent() const;
virtual qreal minYExtent() const;
virtual qreal maxXExtent() const;
virtual qreal maxYExtent() const;
qreal vWidth() const;
qreal vHeight() const;
void componentComplete() override;
virtual void viewportMoved(Qt::Orientations orient);
void geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry) override;
void mouseUngrabEvent() override;
bool filterMouseEvent(QQuickItem *receiver, QMouseEvent *event);
bool xflick() const;
bool yflick() const;
protected:
KQuickFlickable(KQuickFlickablePrivate &dd, QQuickItem *parent);
private:
Q_DISABLE_COPY(KQuickFlickable)
Q_DECLARE_PRIVATE(KQuickFlickable)
friend class KQuickFlickableContentItem;
friend class KQuickFlickableVisibleArea;
friend class KQuickFlickableReboundTransition;
};
QT_END_NAMESPACE
QML_DECLARE_TYPE(KQuickFlickable)
#endif // KQUICKFLICKABLE_H

View File

@ -0,0 +1,266 @@
#ifndef KQUICKFLICKABLE_P_H
#define KQUICKFLICKABLE_P_H
#include "kquickflickable.h"
#include <private/qquickitem_p.h>
#include <private/qquickitemchangelistener_p.h>
#include <QtQml/qqml.h>
#include <QtCore/qdatetime.h>
#include "qplatformdefs.h"
#include "kquicktimeline.h"
#include <private/qquickanimation_p_p.h>
#include <private/qquicktransitionmanager_p_p.h>
#include <private/qpodvector_p.h>
QT_BEGIN_NAMESPACE
// Really slow flicks can be annoying.
const qreal MinimumFlickVelocity = 75.0;
class KQuickFlickableVisibleArea;
class QQuickTransition;
class KQuickFlickableReboundTransition;
class KQuickFlickablePrivate : public QQuickItemPrivate, public QQuickItemChangeListener
{
Q_DECLARE_PUBLIC(KQuickFlickable)
public:
static inline KQuickFlickablePrivate *get(KQuickFlickable *o) { return o->d_func(); }
KQuickFlickablePrivate();
void init();
struct Velocity : public KQuickTimeLineValue
{
Velocity(KQuickFlickablePrivate *p)
: parent(p) {}
void setValue(qreal v) override {
if (v != value()) {
KQuickTimeLineValue::setValue(v);
parent->updateVelocity();
}
}
KQuickFlickablePrivate *parent;
};
struct AxisData {
AxisData(KQuickFlickablePrivate *fp, void (KQuickFlickablePrivate::*func)(qreal))
: move(fp, func)
, transitionToBounds(nullptr)
, viewSize(-1), lastPos(0), previousDragDelta(0), velocity(0), startMargin(0), endMargin(0)
, origin(0), overshoot(0)
, transitionTo(0)
, continuousFlickVelocity(0), velocityTime(), vTime(0)
, smoothVelocity(fp), atEnd(false), atBeginning(true)
, transitionToSet(false)
, fixingUp(false), inOvershoot(false), inRebound(false), moving(false), flicking(false)
, dragging(false), extentsChanged(false)
, explicitValue(false), minExtentDirty(true), maxExtentDirty(true)
, unused(0)
{}
~AxisData();
void reset() {
velocityBuffer.clear();
dragStartOffset = 0;
fixingUp = false;
inOvershoot = false;
}
void markExtentsDirty() {
minExtentDirty = true;
maxExtentDirty = true;
extentsChanged = true;
}
void resetTransitionTo() {
transitionTo = 0;
transitionToSet = false;
}
void addVelocitySample(qreal v, qreal maxVelocity);
void updateVelocity();
KQuickTimeLineValueProxy<KQuickFlickablePrivate> move;
KQuickFlickableReboundTransition *transitionToBounds;
qreal viewSize;
qreal pressPos;
qreal lastPos;
qreal dragStartOffset;
qreal dragMinBound;
qreal dragMaxBound;
qreal previousDragDelta;
qreal velocity;
qreal flickTarget;
qreal startMargin;
qreal endMargin;
qreal origin;
qreal overshoot;
qreal transitionTo;
qreal continuousFlickVelocity;
QElapsedTimer velocityTime;
int vTime;
KQuickFlickablePrivate::Velocity smoothVelocity;
QPODVector<qreal,10> velocityBuffer;
bool atEnd : 1;
bool atBeginning : 1;
bool transitionToSet : 1;
bool fixingUp : 1;
bool inOvershoot : 1;
bool inRebound : 1;
bool moving : 1;
bool flicking : 1;
bool dragging : 1;
bool extentsChanged : 1;
bool explicitValue : 1;
mutable bool minExtentDirty : 1;
mutable bool maxExtentDirty : 1;
uint unused : 19;
};
bool flickX(qreal velocity);
bool flickY(qreal velocity);
virtual bool flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
KQuickTimeLineCallback::Callback fixupCallback, qreal velocity);
void flickingStarted(bool flickingH, bool flickingV);
void fixupX();
void fixupY();
virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
void adjustContentPos(AxisData &data, qreal toPos);
void resetTimeline(AxisData &data);
void clearTimeline();
void updateBeginningEnd();
bool isInnermostPressDelay(QQuickItem *item) const;
void captureDelayedPress(QQuickItem *item, QMouseEvent *event);
void clearDelayedPress();
void replayDelayedPress();
void setViewportX(qreal x);
void setViewportY(qreal y);
qreal overShootDistance(qreal size) const;
void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) override;
void draggingStarting();
void draggingEnding();
bool isViewMoving() const;
void cancelInteraction();
void addPointerHandler(QQuickPointerHandler *h) override;
public:
QQuickItem *contentItem;
AxisData hData;
AxisData vData;
KQuickTimeLine timeline;
bool hMoved : 1;
bool vMoved : 1;
bool stealMouse : 1;
bool pressed : 1;
bool scrollingPhase : 1;
bool interactive : 1;
bool calcVelocity : 1;
bool pixelAligned : 1;
bool syncDrag : 1;
QElapsedTimer timer;
qint64 lastPosTime;
qint64 lastPressTime;
QPointF lastPos;
QPointF pressPos;
QVector2D accumulatedWheelPixelDelta;
qreal deceleration;
qreal maxVelocity;
qreal reportedVelocitySmoothing;
QMouseEvent *delayedPressEvent;
QBasicTimer delayedPressTimer;
int pressDelay;
int fixupDuration;
qreal flickBoost;
enum FixupMode { Normal, Immediate, ExtentChanged };
FixupMode fixupMode;
static void fixupY_callback(void *);
static void fixupX_callback(void *);
void updateVelocity();
int vTime;
KQuickTimeLine velocityTimeline;
KQuickFlickableVisibleArea *visibleArea;
KQuickFlickable::FlickableDirection flickableDirection;
KQuickFlickable::BoundsBehavior boundsBehavior;
KQuickFlickable::BoundsMovement boundsMovement;
QQuickTransition *rebound;
void viewportAxisMoved(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
KQuickTimeLineCallback::Callback fixupCallback);
void handleMousePressEvent(QMouseEvent *);
void handleMouseMoveEvent(QMouseEvent *);
void handleMouseReleaseEvent(QMouseEvent *);
void maybeBeginDrag(qint64 currentTimestamp, const QPointF &pressPosn);
void drag(qint64 currentTimestamp, QEvent::Type eventType, const QPointF &localPos,
const QVector2D &deltas, bool overThreshold, bool momentum,
bool velocitySensitiveOverBounds, const QVector2D &velocity);
qint64 computeCurrentTime(QInputEvent *event) const;
qreal devicePixelRatio() const;
// flickableData property
static void data_append(QQmlListProperty<QObject> *, QObject *);
static int data_count(QQmlListProperty<QObject> *);
static QObject *data_at(QQmlListProperty<QObject> *, int);
static void data_clear(QQmlListProperty<QObject> *);
};
class KQuickFlickableVisibleArea : public QObject
{
Q_OBJECT
Q_PROPERTY(qreal xPosition READ xPosition NOTIFY xPositionChanged)
Q_PROPERTY(qreal yPosition READ yPosition NOTIFY yPositionChanged)
Q_PROPERTY(qreal widthRatio READ widthRatio NOTIFY widthRatioChanged)
Q_PROPERTY(qreal heightRatio READ heightRatio NOTIFY heightRatioChanged)
public:
KQuickFlickableVisibleArea(KQuickFlickable *parent=nullptr);
qreal xPosition() const;
qreal widthRatio() const;
qreal yPosition() const;
qreal heightRatio() const;
void updateVisible();
Q_SIGNALS:
void xPositionChanged(qreal xPosition);
void yPositionChanged(qreal yPosition);
void widthRatioChanged(qreal widthRatio);
void heightRatioChanged(qreal heightRatio);
private:
KQuickFlickable *flickable;
qreal m_xPosition;
qreal m_widthRatio;
qreal m_yPosition;
qreal m_heightRatio;
};
QT_END_NAMESPACE
QML_DECLARE_TYPE(KQuickFlickableVisibleArea)
#endif // KQUICKFLICKABLE_P_H

View File

@ -0,0 +1,55 @@
#ifndef KQUICKFLICKABLEBEHAVIOR_P_H
#define KQUICKFLICKABLEBEHAVIOR_P_H
// The maximum number of pixels a flick can overshoot
#ifndef QML_FLICK_OVERSHOOT
#define QML_FLICK_OVERSHOOT 150
#endif
// The number of samples to use in calculating the velocity of a flick
#ifndef QML_FLICK_SAMPLEBUFFER
#define QML_FLICK_SAMPLEBUFFER 3
#endif
// The number of samples to discard when calculating the flick velocity.
// Touch panels often produce inaccurate results as the finger is lifted.
#ifndef QML_FLICK_DISCARDSAMPLES
#define QML_FLICK_DISCARDSAMPLES 0
#endif
// The default maximum velocity of a flick.
#ifndef QML_FLICK_DEFAULTMAXVELOCITY
# define QML_FLICK_DEFAULTMAXVELOCITY 2500
#endif
// The default deceleration of a flick.
#ifndef QML_FLICK_DEFAULTDECELERATION
# define QML_FLICK_DEFAULTDECELERATION 1500
#endif
// How much faster to decelerate when overshooting
#ifndef QML_FLICK_OVERSHOOTFRICTION
#define QML_FLICK_OVERSHOOTFRICTION 8
#endif
// Multiflick acceleration minimum flick velocity threshold
#ifndef QML_FLICK_MULTIFLICK_THRESHOLD
#define QML_FLICK_MULTIFLICK_THRESHOLD 1250
#endif
// If the time (ms) between the last move and the release exceeds this, then velocity will be zero.
#ifndef QML_FLICK_VELOCITY_DECAY_TIME
#define QML_FLICK_VELOCITY_DECAY_TIME 50
#endif
// Multiflick acceleration minimum contentSize/viewSize ratio
#ifndef QML_FLICK_MULTIFLICK_RATIO
#define QML_FLICK_MULTIFLICK_RATIO 10
#endif
// Multiflick acceleration maximum velocity multiplier
#ifndef QML_FLICK_MULTIFLICK_MAXBOOST
#define QML_FLICK_MULTIFLICK_MAXBOOST 3.0
#endif
#endif // KQUICKFLICKABLEBEHAVIOR_P_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,90 @@
#ifndef KQUICKGRIDVIEW_H
#define KQUICKGRIDVIEW_H
#include <QtQuick/private/qtquickglobal_p.h>
#include "kquickitemview.h"
QT_BEGIN_NAMESPACE
class KQuickGridViewAttached;
class KQuickGridViewPrivate;
class KQuickGridView : public KQuickItemView
{
Q_OBJECT
Q_DECLARE_PRIVATE(KQuickGridView)
Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
Q_PROPERTY(qreal cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellWidthChanged)
Q_PROPERTY(qreal cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellHeightChanged)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
Q_CLASSINFO("DefaultProperty", "data")
public:
enum Flow {
FlowLeftToRight = LeftToRight,
FlowTopToBottom = TopToBottom
};
Q_ENUM(Flow)
KQuickGridView(QQuickItem *parent=nullptr);
~KQuickGridView();
void setHighlightFollowsCurrentItem(bool) override;
void setHighlightMoveDuration(int) override;
Flow flow() const;
void setFlow(Flow);
qreal cellWidth() const;
void setCellWidth(qreal);
qreal cellHeight() const;
void setCellHeight(qreal);
enum SnapMode { NoSnap, SnapToRow, SnapOneRow };
Q_ENUM(SnapMode)
SnapMode snapMode() const;
void setSnapMode(SnapMode mode);
static KQuickGridViewAttached *qmlAttachedProperties(QObject *);
public Q_SLOTS:
void moveCurrentIndexUp();
void moveCurrentIndexDown();
void moveCurrentIndexLeft();
void moveCurrentIndexRight();
Q_SIGNALS:
void cellWidthChanged();
void cellHeightChanged();
void highlightMoveDurationChanged();
void flowChanged();
void snapModeChanged();
protected:
void viewportMoved(Qt::Orientations) override;
void keyPressEvent(QKeyEvent *) override;
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
void initItem(int index, QObject *item) override;
};
class KQuickGridViewAttached : public KQuickItemViewAttached
{
Q_OBJECT
public:
KQuickGridViewAttached(QObject *parent)
: KQuickItemViewAttached(parent) {}
~KQuickGridViewAttached() {}
};
QT_END_NAMESPACE
QML_DECLARE_TYPE(KQuickGridView)
QML_DECLARE_TYPEINFO(KQuickGridView, QML_HAS_ATTACHED_PROPERTIES)
#endif // KQUICKGRIDVIEW_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,387 @@
#ifndef KQUICKITEMVIEW_H
#define KQUICKITEMVIEW_H
#include "kquickflickable.h"
#include <QtQuick/private/qtquickglobal_p.h>
#include "kquickflickable_p.h"
#include <qpointer.h>
#include <QtCore/QLoggingCategory>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcItemViewDelegateLifecycle)
class QQmlChangeSet;
class KQuickItemViewPrivate;
class KQuickItemView : public KQuickFlickable
{
Q_OBJECT
Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
Q_PROPERTY(QQuickItem *currentItem READ currentItem NOTIFY currentItemChanged)
Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged)
Q_PROPERTY(bool keyNavigationEnabled READ isKeyNavigationEnabled WRITE setKeyNavigationEnabled NOTIFY keyNavigationEnabledChanged REVISION 7)
Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
Q_PROPERTY(int displayMarginBeginning READ displayMarginBeginning WRITE setDisplayMarginBeginning NOTIFY displayMarginBeginningChanged REVISION 2)
Q_PROPERTY(int displayMarginEnd READ displayMarginEnd WRITE setDisplayMarginEnd NOTIFY displayMarginEndChanged REVISION 2)
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
Q_PROPERTY(VerticalLayoutDirection verticalLayoutDirection READ verticalLayoutDirection WRITE setVerticalLayoutDirection NOTIFY verticalLayoutDirectionChanged)
Q_PROPERTY(QQmlComponent *header READ header WRITE setHeader NOTIFY headerChanged)
Q_PROPERTY(QQuickItem *headerItem READ headerItem NOTIFY headerItemChanged)
Q_PROPERTY(QQmlComponent *footer READ footer WRITE setFooter NOTIFY footerChanged)
Q_PROPERTY(QQuickItem *footerItem READ footerItem NOTIFY footerItemChanged)
Q_PROPERTY(QQuickTransition *populate READ populateTransition WRITE setPopulateTransition NOTIFY populateTransitionChanged)
Q_PROPERTY(QQuickTransition *add READ addTransition WRITE setAddTransition NOTIFY addTransitionChanged)
Q_PROPERTY(QQuickTransition *addDisplaced READ addDisplacedTransition WRITE setAddDisplacedTransition NOTIFY addDisplacedTransitionChanged)
Q_PROPERTY(QQuickTransition *move READ moveTransition WRITE setMoveTransition NOTIFY moveTransitionChanged)
Q_PROPERTY(QQuickTransition *moveDisplaced READ moveDisplacedTransition WRITE setMoveDisplacedTransition NOTIFY moveDisplacedTransitionChanged)
Q_PROPERTY(QQuickTransition *remove READ removeTransition WRITE setRemoveTransition NOTIFY removeTransitionChanged)
Q_PROPERTY(QQuickTransition *removeDisplaced READ removeDisplacedTransition WRITE setRemoveDisplacedTransition NOTIFY removeDisplacedTransitionChanged)
Q_PROPERTY(QQuickTransition *displaced READ displacedTransition WRITE setDisplacedTransition NOTIFY displacedTransitionChanged)
Q_PROPERTY(QQmlComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
Q_PROPERTY(QQuickItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem NOTIFY highlightFollowsCurrentItemChanged)
Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged RESET resetPreferredHighlightBegin)
Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd)
Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
public:
// this holds all layout enum values so they can be referred to by other enums
// to ensure consistent values - e.g. QML references to GridView.TopToBottom flow
// and GridView.TopToBottom vertical layout direction should have same value
enum LayoutDirection {
LeftToRight = Qt::LeftToRight,
RightToLeft = Qt::RightToLeft,
VerticalTopToBottom,
VerticalBottomToTop
};
Q_ENUM(LayoutDirection)
enum VerticalLayoutDirection {
TopToBottom = VerticalTopToBottom,
BottomToTop = VerticalBottomToTop
};
Q_ENUM(VerticalLayoutDirection)
KQuickItemView(KQuickFlickablePrivate &dd, QQuickItem *parent = nullptr);
~KQuickItemView();
QVariant model() const;
void setModel(const QVariant &);
QQmlComponent *delegate() const;
void setDelegate(QQmlComponent *);
int count() const;
int currentIndex() const;
void setCurrentIndex(int idx);
QQuickItem *currentItem() const;
bool isWrapEnabled() const;
void setWrapEnabled(bool);
bool isKeyNavigationEnabled() const;
void setKeyNavigationEnabled(bool);
int cacheBuffer() const;
void setCacheBuffer(int);
int displayMarginBeginning() const;
void setDisplayMarginBeginning(int);
int displayMarginEnd() const;
void setDisplayMarginEnd(int);
Qt::LayoutDirection layoutDirection() const;
void setLayoutDirection(Qt::LayoutDirection);
Qt::LayoutDirection effectiveLayoutDirection() const;
VerticalLayoutDirection verticalLayoutDirection() const;
void setVerticalLayoutDirection(VerticalLayoutDirection layoutDirection);
QQmlComponent *footer() const;
void setFooter(QQmlComponent *);
QQuickItem *footerItem() const;
QQmlComponent *header() const;
void setHeader(QQmlComponent *);
QQuickItem *headerItem() const;
QQuickTransition *populateTransition() const;
void setPopulateTransition(QQuickTransition *transition);
QQuickTransition *addTransition() const;
void setAddTransition(QQuickTransition *transition);
QQuickTransition *addDisplacedTransition() const;
void setAddDisplacedTransition(QQuickTransition *transition);
QQuickTransition *moveTransition() const;
void setMoveTransition(QQuickTransition *transition);
QQuickTransition *moveDisplacedTransition() const;
void setMoveDisplacedTransition(QQuickTransition *transition);
QQuickTransition *removeTransition() const;
void setRemoveTransition(QQuickTransition *transition);
QQuickTransition *removeDisplacedTransition() const;
void setRemoveDisplacedTransition(QQuickTransition *transition);
QQuickTransition *displacedTransition() const;
void setDisplacedTransition(QQuickTransition *transition);
QQmlComponent *highlight() const;
void setHighlight(QQmlComponent *);
QQuickItem *highlightItem() const;
bool highlightFollowsCurrentItem() const;
virtual void setHighlightFollowsCurrentItem(bool);
enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
Q_ENUM(HighlightRangeMode)
HighlightRangeMode highlightRangeMode() const;
void setHighlightRangeMode(HighlightRangeMode mode);
qreal preferredHighlightBegin() const;
void setPreferredHighlightBegin(qreal);
void resetPreferredHighlightBegin();
qreal preferredHighlightEnd() const;
void setPreferredHighlightEnd(qreal);
void resetPreferredHighlightEnd();
int highlightMoveDuration() const;
virtual void setHighlightMoveDuration(int);
enum PositionMode { Beginning, Center, End, Visible, Contain, SnapPosition };
Q_ENUM(PositionMode)
Q_INVOKABLE void positionViewAtIndex(int index, int mode);
Q_INVOKABLE int indexAt(qreal x, qreal y) const;
Q_INVOKABLE QQuickItem *itemAt(qreal x, qreal y) const;
Q_INVOKABLE void positionViewAtBeginning();
Q_INVOKABLE void positionViewAtEnd();
Q_REVISION(1) Q_INVOKABLE void forceLayout();
void setContentX(qreal pos) override;
void setContentY(qreal pos) override;
qreal originX() const override;
qreal originY() const override;
Q_SIGNALS:
void modelChanged();
void delegateChanged();
void countChanged();
void currentIndexChanged();
void currentItemChanged();
void keyNavigationWrapsChanged();
Q_REVISION(7) void keyNavigationEnabledChanged();
void cacheBufferChanged();
void displayMarginBeginningChanged();
void displayMarginEndChanged();
void layoutDirectionChanged();
void effectiveLayoutDirectionChanged();
void verticalLayoutDirectionChanged();
void headerChanged();
void footerChanged();
void headerItemChanged();
void footerItemChanged();
void populateTransitionChanged();
void addTransitionChanged();
void addDisplacedTransitionChanged();
void moveTransitionChanged();
void moveDisplacedTransitionChanged();
void removeTransitionChanged();
void removeDisplacedTransitionChanged();
void displacedTransitionChanged();
void highlightChanged();
void highlightItemChanged();
void highlightFollowsCurrentItemChanged();
void highlightRangeModeChanged();
void preferredHighlightBeginChanged();
void preferredHighlightEndChanged();
void highlightMoveDurationChanged();
protected:
void updatePolish() override;
void componentComplete() override;
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
qreal minYExtent() const override;
qreal maxYExtent() const override;
qreal minXExtent() const override;
qreal maxXExtent() const override;
protected Q_SLOTS:
void destroyRemoved();
void createdItem(int index, QObject *item);
virtual void initItem(int index, QObject *item);
void modelUpdated(const QQmlChangeSet &changeSet, bool reset);
void destroyingItem(QObject *item);
void animStopped();
void trackedPositionChanged();
private:
Q_DECLARE_PRIVATE(KQuickItemView)
};
class KQuickItemViewAttached : public QObject
{
Q_OBJECT
Q_PROPERTY(KQuickItemView *view READ view NOTIFY viewChanged)
Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged)
Q_PROPERTY(QString section READ section NOTIFY sectionChanged)
Q_PROPERTY(QString previousSection READ prevSection NOTIFY prevSectionChanged)
Q_PROPERTY(QString nextSection READ nextSection NOTIFY nextSectionChanged)
Q_PROPERTY(int rowSpan READ rowSpan WRITE setRowSpan NOTIFY rowSpanChanged)
Q_PROPERTY(int columnSpan READ columnSpan WRITE setColumnSpan NOTIFY columnSpanChanged)
public:
KQuickItemViewAttached(QObject *parent)
: QObject(parent), m_isCurrent(false), m_delayRemove(false) {}
~KQuickItemViewAttached() {}
KQuickItemView *view() const { return m_view; }
void setView(KQuickItemView *view) {
if (view != m_view) {
m_view = view;
Q_EMIT viewChanged();
}
}
bool isCurrentItem() const { return m_isCurrent; }
void setIsCurrentItem(bool c) {
if (m_isCurrent != c) {
m_isCurrent = c;
Q_EMIT currentItemChanged();
}
}
bool delayRemove() const { return m_delayRemove; }
void setDelayRemove(bool delay) {
if (m_delayRemove != delay) {
m_delayRemove = delay;
Q_EMIT delayRemoveChanged();
}
}
QString section() const { return m_section; }
void setSection(const QString &sect) {
if (m_section != sect) {
m_section = sect;
Q_EMIT sectionChanged();
}
}
QString prevSection() const { return m_prevSection; }
void setPrevSection(const QString &sect) {
if (m_prevSection != sect) {
m_prevSection = sect;
Q_EMIT prevSectionChanged();
}
}
int rowSpan() const { return m_rowSpan; }
void setRowSpan(const int &rowSpan) {
if (m_rowSpan != rowSpan) {
m_rowSpan = rowSpan;
Q_EMIT rowSpanChanged();
}
}
int columnSpan() const { return m_columnSpan; }
void setColumnSpan(const int &columnSpan) {
if (m_columnSpan != columnSpan) {
m_columnSpan = columnSpan;
Q_EMIT columnSpanChanged();
}
}
QString nextSection() const { return m_nextSection; }
void setNextSection(const QString &sect) {
if (m_nextSection != sect) {
m_nextSection = sect;
Q_EMIT nextSectionChanged();
}
}
void setSections(const QString &prev, const QString &sect, const QString &next) {
bool prevChanged = prev != m_prevSection;
bool sectChanged = sect != m_section;
bool nextChanged = next != m_nextSection;
m_prevSection = prev;
m_section = sect;
m_nextSection = next;
if (prevChanged)
Q_EMIT prevSectionChanged();
if (sectChanged)
Q_EMIT sectionChanged();
if (nextChanged)
Q_EMIT nextSectionChanged();
}
void emitAdd() { Q_EMIT add(); }
void emitRemove() { Q_EMIT remove(); }
Q_SIGNALS:
void viewChanged();
void currentItemChanged();
void delayRemoveChanged();
void add();
void remove();
void sectionChanged();
void prevSectionChanged();
void nextSectionChanged();
void rowSpanChanged();
void columnSpanChanged();
public:
QPointer<KQuickItemView> m_view;
bool m_isCurrent : 1;
bool m_delayRemove : 1;
// current only used by list view
mutable QString m_section;
QString m_prevSection;
QString m_nextSection;
int m_rowSpan;
int m_columnSpan;
};
QT_END_NAMESPACE
#endif // KQUICKITEMVIEW_H

View File

@ -0,0 +1,317 @@
#ifndef KQUICKITEMVIEW_P_H
#define KQUICKITEMVIEW_P_H
#include <QtQuick/private/qtquickglobal_p.h>
#include "kquickitemview.h"
#include "kquickitemviewfxitem_p.h"
#include <QtQuick/private/qquickitemviewtransition_p.h>
#include "kquickflickable_p.h"
#include <QtQml/private/qqmlobjectmodel_p.h>
#include <QtQml/private/qqmldelegatemodel_p.h>
#include <QtQml/private/qqmlchangeset_p.h>
QT_BEGIN_NAMESPACE
class FxViewItem : public KQuickItemViewFxItem
{
public:
FxViewItem(QQuickItem *, KQuickItemView *, bool own, KQuickItemViewAttached *attached);
KQuickItemView *view;
KQuickItemViewAttached *attached;
};
class KQuickItemViewChangeSet
{
public:
KQuickItemViewChangeSet();
bool hasPendingChanges() const;
void prepare(int currentIndex, int count);
void reset();
void applyChanges(const QQmlChangeSet &changeSet);
void applyBufferedChanges(const KQuickItemViewChangeSet &other);
int itemCount;
int newCurrentIndex;
QQmlChangeSet pendingChanges;
QHash<QQmlChangeSet::MoveKey, FxViewItem *> removedItems;
bool active : 1;
bool currentChanged : 1;
bool currentRemoved : 1;
};
class KQuickItemViewPrivate : public KQuickFlickablePrivate, public QQuickItemViewTransitionChangeListener, public QAnimationJobChangeListener
{
Q_DECLARE_PUBLIC(KQuickItemView)
public:
KQuickItemViewPrivate();
~KQuickItemViewPrivate();
static inline KQuickItemViewPrivate *get(KQuickItemView *o) { return o->d_func(); }
struct ChangeResult {
QQmlNullableValue<qreal> visiblePos;
bool changedFirstItem;
qreal sizeChangesBeforeVisiblePos;
qreal sizeChangesAfterVisiblePos;
int countChangeBeforeVisible;
int countChangeAfterVisibleItems;
ChangeResult()
: visiblePos(0), changedFirstItem(false),
sizeChangesBeforeVisiblePos(0), sizeChangesAfterVisiblePos(0),
countChangeBeforeVisible(0), countChangeAfterVisibleItems(0) {}
ChangeResult(const QQmlNullableValue<qreal> &p)
: visiblePos(p), changedFirstItem(false),
sizeChangesBeforeVisiblePos(0), sizeChangesAfterVisiblePos(0),
countChangeBeforeVisible(0), countChangeAfterVisibleItems(0) {}
ChangeResult &operator+=(const ChangeResult &other) {
if (&other == this)
return *this;
changedFirstItem &= other.changedFirstItem;
sizeChangesBeforeVisiblePos += other.sizeChangesBeforeVisiblePos;
sizeChangesAfterVisiblePos += other.sizeChangesAfterVisiblePos;
countChangeBeforeVisible += other.countChangeBeforeVisible;
countChangeAfterVisibleItems += other.countChangeAfterVisibleItems;
return *this;
}
void reset() {
changedFirstItem = false;
sizeChangesBeforeVisiblePos = 0.0;
sizeChangesAfterVisiblePos = 0.0;
countChangeBeforeVisible = 0;
countChangeAfterVisibleItems = 0;
}
};
enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
enum MovementReason { Other, SetIndex, Mouse };
bool isValid() const;
qreal position() const;
qreal size() const;
qreal startPosition() const;
qreal endPosition() const;
qreal contentStartOffset() const;
int findLastVisibleIndex(int defaultValue = -1) const;
FxViewItem *visibleItem(int modelIndex) const;
FxViewItem *firstVisibleItem() const;
int findLastIndexInView() const;
int mapFromModel(int modelIndex) const;
virtual void init();
virtual void clear();
virtual void updateViewport();
void regenerate(bool orientationChanged=false);
void layout();
void animationFinished(QAbstractAnimationJob *) override;
void refill();
void refill(qreal from, qreal to);
void mirrorChange() override;
FxViewItem *createItem(int modelIndex,QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested);
virtual bool releaseItem(FxViewItem *item);
QQuickItem *createHighlightItem() const;
QQuickItem *createComponentItem(QQmlComponent *component, qreal zValue, bool createDefault = false) const;
void updateCurrent(int modelIndex);
void updateTrackedItem();
void updateUnrequestedIndexes();
void updateUnrequestedPositions();
void updateVisibleIndex();
void positionViewAtIndex(int index, int mode);
qreal minExtentForAxis(const AxisData &axisData, bool forXAxis) const;
qreal maxExtentForAxis(const AxisData &axisData, bool forXAxis) const;
qreal calculatedMinExtent() const;
qreal calculatedMaxExtent() const;
void applyPendingChanges();
bool applyModelChanges(ChangeResult *insertionResult, ChangeResult *removalResult);
bool applyRemovalChange(const QQmlChangeSet::Change &removal, ChangeResult *changeResult, int *removedCount);
void removeItem(FxViewItem *item, const QQmlChangeSet::Change &removal, ChangeResult *removeResult);
virtual void updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult);
void repositionFirstItem(FxViewItem *prevVisibleItemsFirst, qreal prevVisibleItemsFirstPos,
FxViewItem *prevFirstVisible, ChangeResult *insertionResult, ChangeResult *removalResult);
void createTransitioner();
void prepareVisibleItemTransitions();
void prepareRemoveTransitions(QHash<QQmlChangeSet::MoveKey, FxViewItem *> *removedItems);
bool prepareNonVisibleItemTransition(FxViewItem *item, const QRectF &viewBounds);
void viewItemTransitionFinished(QQuickItemViewTransitionableItem *item) override;
int findMoveKeyIndex(QQmlChangeSet::MoveKey key, const QVector<QQmlChangeSet::Change> &changes) const;
void checkVisible() const;
void showVisibleItems() const;
void markExtentsDirty() {
if (layoutOrientation() == Qt::Vertical)
vData.markExtentsDirty();
else
hData.markExtentsDirty();
}
bool hasPendingChanges() const {
return currentChanges.hasPendingChanges()
|| bufferedChanges.hasPendingChanges()
||runDelayedRemoveTransition;
}
void refillOrLayout() {
if (hasPendingChanges())
layout();
else
refill();
}
void forceLayoutPolish() {
Q_Q(KQuickItemView);
forceLayout = true;
q->polish();
}
void releaseVisibleItems() {
// make a copy and clear the visibleItems first to avoid destroyed
// items being accessed during the loop (QTBUG-61294)
const QList<FxViewItem *> oldVisible = visibleItems;
visibleItems.clear();
for (FxViewItem *item : oldVisible)
releaseItem(item);
}
QPointer<QQmlInstanceModel> model;
QVariant modelVariant;
int itemCount;
int buffer;
int bufferMode;
int displayMarginBeginning;
int displayMarginEnd;
Qt::LayoutDirection layoutDirection;
KQuickItemView::VerticalLayoutDirection verticalLayoutDirection;
MovementReason moveReason;
QList<FxViewItem *> visibleItems;
int visibleIndex;
int currentIndex;
FxViewItem *currentItem;
FxViewItem *trackedItem;
QHash<QQuickItem*,int> unrequestedItems;
int requestedIndex;
KQuickItemViewChangeSet currentChanges;
KQuickItemViewChangeSet bufferedChanges;
QPauseAnimationJob bufferPause;
QQmlComponent *highlightComponent;
FxViewItem *highlight;
int highlightRange; // enum value
qreal highlightRangeStart;
qreal highlightRangeEnd;
int highlightMoveDuration;
QQmlComponent *headerComponent;
FxViewItem *header;
QQmlComponent *footerComponent;
FxViewItem *footer;
struct MovedItem {
FxViewItem *item;
QQmlChangeSet::MoveKey moveKey;
MovedItem(FxViewItem *i, QQmlChangeSet::MoveKey k)
: item(i), moveKey(k) {}
};
QQuickItemViewTransitioner *transitioner;
QVector<FxViewItem *> releasePendingTransition;
mutable qreal minExtent;
mutable qreal maxExtent;
bool ownModel : 1;
bool wrap : 1;
bool keyNavigationEnabled : 1;
bool explicitKeyNavigationEnabled : 1;
bool inLayout : 1;
bool inViewportMoved : 1;
bool forceLayout : 1;
bool currentIndexCleared : 1;
bool haveHighlightRange : 1;
bool autoHighlight : 1;
bool highlightRangeStartValid : 1;
bool highlightRangeEndValid : 1;
bool fillCacheBuffer : 1;
bool inRequest : 1;
bool runDelayedRemoveTransition : 1;
bool delegateValidated : 1;
protected:
virtual Qt::Orientation layoutOrientation() const = 0;
virtual bool isContentFlowReversed() const = 0;
virtual qreal positionAt(int index) const = 0;
virtual qreal endPositionAt(int index) const = 0;
virtual qreal originPosition() const = 0;
virtual qreal lastPosition() const = 0;
virtual qreal headerSize() const = 0;
virtual qreal footerSize() const = 0;
virtual bool showHeaderForIndex(int index) const = 0;
virtual bool showFooterForIndex(int index) const = 0;
virtual void updateHeader() = 0;
virtual void updateFooter() = 0;
virtual bool hasStickyHeader() const { return false; }
virtual bool hasStickyFooter() const { return false; }
virtual void createHighlight() = 0;
virtual void updateHighlight() = 0;
virtual void resetHighlightPosition() = 0;
virtual bool movingFromHighlight() { return false; }
virtual void setPosition(qreal pos) = 0;
virtual void fixupPosition() = 0;
virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer) = 0;
virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) = 0;
virtual void visibleItemsChanged() {}
virtual FxViewItem *newViewItem(int index, QQuickItem *item) = 0;
virtual void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) = 0;
virtual void repositionPackageItemAt(QQuickItem *item, int index) = 0;
virtual void resetFirstItemPosition(qreal pos = 0.0) = 0;
virtual void adjustFirstItem(qreal forwards, qreal backwards, int changeBeforeVisible) = 0;
virtual void layoutVisibleItems(int fromModelIndex = 0) = 0;
virtual void changedVisibleIndex(int newIndex) = 0;
virtual bool applyInsertionChange(const QQmlChangeSet::Change &insert, ChangeResult *changeResult,
QList<FxViewItem *> *newItems, QList<MovedItem> *movingIntoView) = 0;
virtual bool needsRefillForAddedOrRemovedIndex(int) const { return false; }
virtual void translateAndTransitionItemsAfter(int afterIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult) = 0;
virtual void initializeViewItem(FxViewItem *) {}
virtual void initializeCurrentItem() {}
virtual void updateSectionCriteria() {}
virtual void updateSections() {}
void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) override;
};
QT_END_NAMESPACE
#endif // KQUICKITEMVIEW_P_H

View File

@ -0,0 +1,127 @@
#include "kquickitemviewfxitem_p.h"
#include <private/qquickitem_p.h>
#include "kquickitemview_p.h"
QT_BEGIN_NAMESPACE
KQuickItemViewFxItem::KQuickItemViewFxItem(QQuickItem *item, bool ownItem, QQuickItemChangeListener* changeListener)
: item(item)
, ownItem(ownItem)
, changeListener(changeListener)
, transitionableItem(nullptr)
, releaseAfterTransition(false)
, trackGeom(false)
{
}
KQuickItemViewFxItem::~KQuickItemViewFxItem()
{
delete transitionableItem;
transitionableItem = nullptr;
if (ownItem && item) {
trackGeometry(false);
item->setParentItem(0);
item->deleteLater();
}
}
qreal KQuickItemViewFxItem::itemX() const
{
return transitionableItem ? transitionableItem->itemX() : (item ? item->x() : 0);
}
qreal KQuickItemViewFxItem::itemY() const
{
return transitionableItem ? transitionableItem->itemY() : (item ? item->y() : 0);
}
void KQuickItemViewFxItem::moveTo(const QPointF &pos, bool immediate)
{
if (transitionableItem)
transitionableItem->moveTo(pos, immediate);
else if (item)
item->setPosition(pos);
}
void KQuickItemViewFxItem::setVisible(bool visible)
{
if (!visible && transitionableItem && transitionableItem->transitionScheduledOrRunning())
return;
if (item)
QQuickItemPrivate::get(item)->setCulled(!visible);
}
void KQuickItemViewFxItem::trackGeometry(bool track)
{
if (track) {
if (!trackGeom) {
if (item) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
itemPrivate->addItemChangeListener(changeListener, QQuickItemPrivate::Geometry);
}
trackGeom = true;
}
} else {
if (trackGeom) {
if (item) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
itemPrivate->removeItemChangeListener(changeListener, QQuickItemPrivate::Geometry);
}
trackGeom = false;
}
}
}
QRectF KQuickItemViewFxItem::geometry() const
{
return QRectF(item->position(), item->size());
}
void KQuickItemViewFxItem::setGeometry(const QRectF &geometry)
{
item->setPosition(geometry.topLeft());
item->setSize(geometry.size());
}
QQuickItemViewTransitioner::TransitionType KQuickItemViewFxItem::scheduledTransitionType() const
{
return transitionableItem ? transitionableItem->nextTransitionType : QQuickItemViewTransitioner::NoTransition;
}
bool KQuickItemViewFxItem::transitionScheduledOrRunning() const
{
return transitionableItem ? transitionableItem->transitionScheduledOrRunning() : false;
}
bool KQuickItemViewFxItem::transitionRunning() const
{
return transitionableItem ? transitionableItem->transitionRunning() : false;
}
bool KQuickItemViewFxItem::isPendingRemoval() const
{
return transitionableItem ? transitionableItem->isPendingRemoval() : false;
}
void KQuickItemViewFxItem::transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget)
{
if (!transitioner)
return;
if (!transitionableItem)
transitionableItem = new QQuickItemViewTransitionableItem(item);
transitioner->transitionNextReposition(transitionableItem, type, asTarget);
}
bool KQuickItemViewFxItem::prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds)
{
return transitionableItem ? transitionableItem->prepareTransition(transitioner, index, viewBounds) : false;
}
void KQuickItemViewFxItem::startTransition(QQuickItemViewTransitioner *transitioner)
{
if (transitionableItem)
transitionableItem->startTransition(transitioner, index);
}
QT_END_NAMESPACE

View File

@ -0,0 +1,60 @@
#ifndef KQUICKITEMVIEWFXITEM_P_H
#define KQUICKITEMVIEWFXITEM_P_H
#include <QtQuick/private/qtquickglobal_p.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickitemviewtransition_p.h>
#include <private/qanimationjobutil_p.h>
QT_REQUIRE_CONFIG(quick_itemview);
QT_BEGIN_NAMESPACE
class Q_AUTOTEST_EXPORT KQuickItemViewFxItem
{
public:
KQuickItemViewFxItem(QQuickItem *item, bool ownItem, QQuickItemChangeListener *changeListener);
virtual ~KQuickItemViewFxItem();
qreal itemX() const;
qreal itemY() const;
inline qreal itemWidth() const { return item ? item->width() : 0; }
inline qreal itemHeight() const { return item ? item->height() : 0; }
void moveTo(const QPointF &pos, bool immediate);
void setVisible(bool visible);
void trackGeometry(bool track);
QRectF geometry() const;
void setGeometry(const QRectF &geometry);
QQuickItemViewTransitioner::TransitionType scheduledTransitionType() const;
bool transitionScheduledOrRunning() const;
bool transitionRunning() const;
bool isPendingRemoval() const;
void transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget);
bool prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds);
void startTransition(QQuickItemViewTransitioner *transitioner);
// these are positions and sizes along the current direction of scrolling/flicking
virtual qreal position() const = 0;
virtual qreal endPosition() const = 0;
virtual qreal size() const = 0;
virtual qreal sectionSize() const = 0;
virtual bool contains(qreal x, qreal y) const = 0;
SelfDeletable m_selfDeletable;
int index = -1;
QPointer<QQuickItem> item;
bool ownItem;
QQuickItemChangeListener *changeListener;
QQuickItemViewTransitionableItem *transitionableItem;
bool releaseAfterTransition;
bool trackGeom;
};
QT_END_NAMESPACE
#endif // KQUICKITEMVIEWFXITEM_P_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,172 @@
#ifndef KQUICKLISTVIEW_H
#define KQUICKLISTVIEW_H
#include <private/qtquickglobal_p.h>
#include "kquickitemview.h"
#include <private/qtquickglobal_p.h>
QT_BEGIN_NAMESPACE
class KQuickListView;
class KQuickListViewPrivate;
class KQuickViewSection : public QObject
{
Q_OBJECT
Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY propertyChanged)
Q_PROPERTY(SectionCriteria criteria READ criteria WRITE setCriteria NOTIFY criteriaChanged)
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
Q_PROPERTY(int labelPositioning READ labelPositioning WRITE setLabelPositioning NOTIFY labelPositioningChanged)
public:
KQuickViewSection(KQuickListView *parent=nullptr);
QString property() const { return m_property; }
void setProperty(const QString &);
enum SectionCriteria { FullString, FirstCharacter };
Q_ENUM(SectionCriteria)
SectionCriteria criteria() const { return m_criteria; }
void setCriteria(SectionCriteria);
QQmlComponent *delegate() const { return m_delegate; }
void setDelegate(QQmlComponent *delegate);
QString sectionString(const QString &value);
enum LabelPositioning { InlineLabels = 0x01, CurrentLabelAtStart = 0x02, NextLabelAtEnd = 0x04 };
Q_ENUM(LabelPositioning)
int labelPositioning() const { return m_labelPositioning; }
void setLabelPositioning(int pos);
Q_SIGNALS:
void sectionsChanged();
void propertyChanged();
void criteriaChanged();
void delegateChanged();
void labelPositioningChanged();
private:
QString m_property;
SectionCriteria m_criteria;
QQmlComponent *m_delegate;
int m_labelPositioning;
KQuickListViewPrivate *m_view;
};
class QQmlInstanceModel;
class KQuickListViewAttached;
class KQuickListView : public KQuickItemView
{
Q_OBJECT
Q_DECLARE_PRIVATE(KQuickListView)
Q_PROPERTY(qreal highlightMoveVelocity READ highlightMoveVelocity WRITE setHighlightMoveVelocity NOTIFY highlightMoveVelocityChanged)
Q_PROPERTY(qreal highlightResizeVelocity READ highlightResizeVelocity WRITE setHighlightResizeVelocity NOTIFY highlightResizeVelocityChanged)
Q_PROPERTY(int highlightResizeDuration READ highlightResizeDuration WRITE setHighlightResizeDuration NOTIFY highlightResizeDurationChanged)
Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
Q_PROPERTY(KQuickViewSection *section READ sectionCriteria CONSTANT)
Q_PROPERTY(QString currentSection READ currentSection NOTIFY currentSectionChanged)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
Q_PROPERTY(HeaderPositioning headerPositioning READ headerPositioning WRITE setHeaderPositioning NOTIFY headerPositioningChanged REVISION 2)
Q_PROPERTY(FooterPositioning footerPositioning READ footerPositioning WRITE setFooterPositioning NOTIFY footerPositioningChanged REVISION 2)
Q_CLASSINFO("DefaultProperty", "data")
public:
KQuickListView(QQuickItem *parent=nullptr);
~KQuickListView();
qreal spacing() const;
void setSpacing(qreal spacing);
enum Orientation { Horizontal = Qt::Horizontal, Vertical = Qt::Vertical };
Q_ENUM(Orientation)
Orientation orientation() const;
void setOrientation(Orientation);
KQuickViewSection *sectionCriteria();
QString currentSection() const;
void setHighlightFollowsCurrentItem(bool) override;
qreal highlightMoveVelocity() const;
void setHighlightMoveVelocity(qreal);
qreal highlightResizeVelocity() const;
void setHighlightResizeVelocity(qreal);
int highlightResizeDuration() const;
void setHighlightResizeDuration(int);
void setHighlightMoveDuration(int) override;
enum SnapMode { NoSnap, SnapToItem, SnapOneItem };
Q_ENUM(SnapMode)
SnapMode snapMode() const;
void setSnapMode(SnapMode mode);
enum HeaderPositioning { InlineHeader, OverlayHeader, PullBackHeader };
Q_ENUM(HeaderPositioning)
HeaderPositioning headerPositioning() const;
void setHeaderPositioning(HeaderPositioning positioning);
enum FooterPositioning { InlineFooter, OverlayFooter, PullBackFooter };
Q_ENUM(FooterPositioning)
FooterPositioning footerPositioning() const;
void setFooterPositioning(FooterPositioning positioning);
static KQuickListViewAttached *qmlAttachedProperties(QObject *);
public Q_SLOTS:
void incrementCurrentIndex();
void decrementCurrentIndex();
Q_SIGNALS:
void spacingChanged();
void orientationChanged();
void currentSectionChanged();
void highlightMoveVelocityChanged();
void highlightResizeVelocityChanged();
void highlightResizeDurationChanged();
void snapModeChanged();
Q_REVISION(2) void headerPositioningChanged();
Q_REVISION(2) void footerPositioningChanged();
protected:
void viewportMoved(Qt::Orientations orient) override;
void keyPressEvent(QKeyEvent *) override;
void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry) override;
void initItem(int index, QObject *item) override;
qreal maxYExtent() const override;
qreal maxXExtent() const override;
};
class KQuickListViewAttached : public KQuickItemViewAttached
{
Q_OBJECT
public:
KQuickListViewAttached(QObject *parent)
: KQuickItemViewAttached(parent), m_sectionItem(nullptr) {}
~KQuickListViewAttached() {}
public:
QPointer<QQuickItem> m_sectionItem;
};
QT_END_NAMESPACE
QML_DECLARE_TYPEINFO(KQuickListView, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPE(KQuickListView)
QML_DECLARE_TYPE(KQuickViewSection)
#endif // KQUICKLISTVIEW_H

View File

@ -0,0 +1,531 @@
#include "kquicksmoothedanimation.h"
#include "kquicksmoothedanimation_p.h"
#include <private/qquickanimation_p_p.h>
#include "private/qcontinuinganimationgroupjob_p.h"
#include <qmath.h>
#include <qqmlproperty.h>
#include <private/qqmlproperty_p.h>
#include <private/qqmlglobal_p.h>
#include <QtCore/qdebug.h>
#define DELAY_STOP_TIMER_INTERVAL 32
QT_BEGIN_NAMESPACE
KSmoothedAnimationTimer::KSmoothedAnimationTimer(KSmoothedAnimation *animation, QObject *parent)
: QTimer(parent)
, m_animation(animation)
{
connect(this, SIGNAL(timeout()), this, SLOT(stopAnimation()));
}
KSmoothedAnimationTimer::~KSmoothedAnimationTimer()
{
}
void KSmoothedAnimationTimer::stopAnimation()
{
m_animation->stop();
}
KSmoothedAnimation::KSmoothedAnimation(KQuickSmoothedAnimationPrivate *priv)
: QAbstractAnimationJob(), to(0), velocity(200), userDuration(-1), maximumEasingTime(-1),
reversingMode(KQuickSmoothedAnimation::Eased), initialVelocity(0),
trackVelocity(0), initialValue(0), invert(false), finalDuration(-1), lastTime(0),
skipUpdate(false), delayedStopTimer(new KSmoothedAnimationTimer(this)), animationTemplate(priv)
{
delayedStopTimer->setInterval(DELAY_STOP_TIMER_INTERVAL);
delayedStopTimer->setSingleShot(true);
}
KSmoothedAnimation::~KSmoothedAnimation()
{
delete delayedStopTimer;
if (animationTemplate) {
if (target.object()) {
QHash<QQmlProperty, KSmoothedAnimation* >::iterator it =
animationTemplate->activeAnimations.find(target);
if (it != animationTemplate->activeAnimations.end() && it.value() == this)
animationTemplate->activeAnimations.erase(it);
} else {
//target is no longer valid, need to search linearly
QHash<QQmlProperty, KSmoothedAnimation* >::iterator it;
for (it = animationTemplate->activeAnimations.begin(); it != animationTemplate->activeAnimations.end(); ++it) {
if (it.value() == this) {
animationTemplate->activeAnimations.erase(it);
break;
}
}
}
}
}
void KSmoothedAnimation::restart()
{
initialVelocity = trackVelocity;
if (isRunning())
init();
else
start();
}
void KSmoothedAnimation::prepareForRestart()
{
initialVelocity = trackVelocity;
if (isRunning()) {
//we are joining a new wrapper group while running, our times need to be restarted
skipUpdate = true;
init();
lastTime = 0;
} else {
skipUpdate = false;
//we'll be started when the group starts, which will force an init()
}
}
void KSmoothedAnimation::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State /*oldState*/)
{
if (newState == QAbstractAnimationJob::Running)
init();
}
void KSmoothedAnimation::delayedStop()
{
if (!delayedStopTimer->isActive())
delayedStopTimer->start();
}
int KSmoothedAnimation::duration() const
{
return -1;
}
bool KSmoothedAnimation::recalc()
{
s = to - initialValue;
vi = initialVelocity;
s = (invert? -1.0: 1.0) * s;
if (userDuration >= 0 && velocity > 0) {
tf = s / velocity;
if (tf > (userDuration / 1000.)) tf = (userDuration / 1000.);
} else if (userDuration >= 0) {
tf = userDuration / 1000.;
} else if (velocity > 0) {
tf = s / velocity;
} else {
return false;
}
finalDuration = qCeil(tf * 1000.0);
if (maximumEasingTime == 0) {
a = 0;
d = 0;
tp = 0;
td = tf;
vp = velocity;
sp = 0;
sd = s;
} else if (maximumEasingTime != -1 && tf > (maximumEasingTime / 1000.)) {
qreal met = maximumEasingTime / 1000.;
/* tp| |td
* vp_ _______
* / \
* vi_ / \
* \
* \ _ 0
* |ta| |ta|
*/
qreal ta = met / 2.;
a = (s - (vi * tf - 0.5 * vi * ta)) / (tf * ta - ta * ta);
vp = vi + a * ta;
d = vp / ta;
tp = ta;
sp = vi * ta + 0.5 * a * tp * tp;
sd = sp + vp * (tf - 2 * ta);
td = tf - ta;
} else {
qreal c1 = 0.25 * tf * tf;
qreal c2 = 0.5 * vi * tf - s;
qreal c3 = -0.25 * vi * vi;
qreal a1 = (-c2 + qSqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
qreal tp1 = 0.5 * tf - 0.5 * vi / a1;
qreal vp1 = a1 * tp1 + vi;
qreal sp1 = 0.5 * a1 * tp1 * tp1 + vi * tp1;
a = a1;
d = a1;
tp = tp1;
td = tp1;
vp = vp1;
sp = sp1;
sd = sp1;
}
return true;
}
qreal KSmoothedAnimation::easeFollow(qreal time_seconds)
{
qreal value;
if (time_seconds < tp) {
trackVelocity = vi + time_seconds * a;
value = 0.5 * a * time_seconds * time_seconds + vi * time_seconds;
} else if (time_seconds < td) {
time_seconds -= tp;
trackVelocity = vp;
value = sp + time_seconds * vp;
} else if (time_seconds < tf) {
time_seconds -= td;
trackVelocity = vp - time_seconds * a;
value = sd - 0.5 * d * time_seconds * time_seconds + vp * time_seconds;
} else {
trackVelocity = 0;
value = s;
delayedStop();
}
// to normalize 's' between [0..1], divide 'value' by 's'
return value;
}
void KSmoothedAnimation::updateCurrentTime(int t)
{
if (skipUpdate) {
skipUpdate = false;
return;
}
if (!isRunning() && !isPaused()) // This can happen if init() stops the animation in some cases
return;
qreal time_seconds = qreal(t - lastTime) / 1000.;
qreal value = easeFollow(time_seconds);
value *= (invert? -1.0: 1.0);
QQmlPropertyPrivate::write(target, initialValue + value,
QQmlPropertyData::BypassInterceptor
| QQmlPropertyData::DontRemoveBinding);
}
void KSmoothedAnimation::init()
{
if (velocity == 0) {
stop();
return;
}
if (delayedStopTimer->isActive())
delayedStopTimer->stop();
initialValue = target.read().toReal();
lastTime = this->currentTime();
if (to == initialValue) {
stop();
return;
}
bool hasReversed = trackVelocity != 0. &&
((!invert) == ((initialValue - to) > 0));
if (hasReversed) {
switch (reversingMode) {
default:
case KQuickSmoothedAnimation::Eased:
initialVelocity = -trackVelocity;
break;
case KQuickSmoothedAnimation::Sync:
QQmlPropertyPrivate::write(target, to,
QQmlPropertyData::BypassInterceptor
| QQmlPropertyData::DontRemoveBinding);
trackVelocity = 0;
stop();
return;
case KQuickSmoothedAnimation::Immediate:
initialVelocity = 0;
break;
}
}
trackVelocity = initialVelocity;
invert = (to < initialValue);
if (!recalc()) {
QQmlPropertyPrivate::write(target, to,
QQmlPropertyData::BypassInterceptor
| QQmlPropertyData::DontRemoveBinding);
stop();
return;
}
}
void KSmoothedAnimation::debugAnimation(QDebug d) const
{
d << "SmoothedAnimationJob(" << hex << (const void *) this << dec << ")" << "duration:" << userDuration
<< "velocity:" << velocity << "target:" << target.object() << "property:" << target.name()
<< "to:" << to << "current velocity:" << trackVelocity;
}
/*!
\qmltype SmoothedAnimation
\instantiates KQuickSmoothedAnimation
\inqmlmodule QtQuick
\ingroup qtquick-transitions-animations
\inherits NumberAnimation
\brief Allows a property to smoothly track a value.
A SmoothedAnimation animates a property's value to a set target value
using an ease in/out quad easing curve. When the target value changes,
the easing curves used to animate between the old and new target values
are smoothly spliced together to create a smooth movement to the new
target value that maintains the current velocity.
The follow example shows one \l Rectangle tracking the position of another
using SmoothedAnimation. The green rectangle's \c x and \c y values are
bound to those of the red rectangle. Whenever these values change, the
green rectangle smoothly animates to its new position:
\snippet qml/smoothedanimation.qml 0
A SmoothedAnimation can be configured by setting the \l velocity at which the
animation should occur, or the \l duration that the animation should take.
If both the \l velocity and \l duration are specified, the one that results in
the quickest animation is chosen for each change in the target value.
For example, animating from 0 to 800 will take 4 seconds if a velocity
of 200 is set, will take 8 seconds with a duration of 8000 set, and will
take 4 seconds with both a velocity of 200 and a duration of 8000 set.
Animating from 0 to 20000 will take 10 seconds if a velocity of 200 is set,
will take 8 seconds with a duration of 8000 set, and will take 8 seconds
with both a velocity of 200 and a duration of 8000 set.
The default velocity of SmoothedAnimation is 200 units/second. Note that if the range of the
value being animated is small, then the velocity will need to be adjusted
appropriately. For example, the opacity of an item ranges from 0 - 1.0.
To enable a smooth animation in this range the velocity will need to be
set to a value such as 0.5 units/second. Animating from 0 to 1.0 with a velocity
of 0.5 will take 2000 ms to complete.
Like any other animation type, a SmoothedAnimation can be applied in a
number of ways, including transitions, behaviors and property value
sources. The \l {Animation and Transitions in Qt Quick} documentation shows a
variety of methods for creating animations.
\sa SpringAnimation, NumberAnimation, {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
*/
KQuickSmoothedAnimation::KQuickSmoothedAnimation(QObject *parent)
: QQuickNumberAnimation(*(new KQuickSmoothedAnimationPrivate), parent)
{
}
KQuickSmoothedAnimation::~KQuickSmoothedAnimation()
{
}
KQuickSmoothedAnimationPrivate::KQuickSmoothedAnimationPrivate()
: anim(new KSmoothedAnimation)
{
}
KQuickSmoothedAnimationPrivate::~KQuickSmoothedAnimationPrivate()
{
typedef QHash<QQmlProperty, KSmoothedAnimation* >::iterator ActiveAnimationsHashIt;
delete anim;
for (ActiveAnimationsHashIt it = activeAnimations.begin(), end = activeAnimations.end(); it != end; ++it)
it.value()->clearTemplate();
}
void KQuickSmoothedAnimationPrivate::updateRunningAnimations()
{
for (KSmoothedAnimation *ease : qAsConst(activeAnimations)) {
ease->maximumEasingTime = anim->maximumEasingTime;
ease->reversingMode = anim->reversingMode;
ease->velocity = anim->velocity;
ease->userDuration = anim->userDuration;
ease->init();
}
}
QAbstractAnimationJob* KQuickSmoothedAnimation::transition(QQuickStateActions &actions,
QQmlProperties &modified,
TransitionDirection direction,
QObject *defaultTarget)
{
Q_UNUSED(direction);
Q_D(KQuickSmoothedAnimation);
const QQuickStateActions dataActions = QQuickPropertyAnimation::createTransitionActions(actions, modified, defaultTarget);
QContinuingAnimationGroupJob *wrapperGroup = new QContinuingAnimationGroupJob();
if (!dataActions.isEmpty()) {
QSet<QAbstractAnimationJob*> anims;
for (int i = 0; i < dataActions.size(); i++) {
KSmoothedAnimation *ease;
bool isActive;
if (!d->activeAnimations.contains(dataActions[i].property)) {
ease = new KSmoothedAnimation(d);
d->activeAnimations.insert(dataActions[i].property, ease);
ease->target = dataActions[i].property;
isActive = false;
} else {
ease = d->activeAnimations.value(dataActions[i].property);
isActive = true;
}
wrapperGroup->appendAnimation(initInstance(ease));
ease->to = dataActions[i].toValue.toReal();
// copying public members from main value holder animation
ease->maximumEasingTime = d->anim->maximumEasingTime;
ease->reversingMode = d->anim->reversingMode;
ease->velocity = d->anim->velocity;
ease->userDuration = d->anim->userDuration;
ease->initialVelocity = ease->trackVelocity;
if (isActive)
ease->prepareForRestart();
anims.insert(ease);
}
const auto copy = d->activeAnimations;
for (KSmoothedAnimation *ease : copy) {
if (!anims.contains(ease)) {
ease->clearTemplate();
d->activeAnimations.remove(ease->target);
}
}
}
return wrapperGroup;
}
/*!
\qmlproperty enumeration QtQuick::SmoothedAnimation::reversingMode
Sets how the SmoothedAnimation behaves if an animation direction is reversed.
Possible values are:
\list
\li SmoothedAnimation.Eased (default) - the animation will smoothly decelerate, and then reverse direction
\li SmoothedAnimation.Immediate - the animation will immediately begin accelerating in the reverse direction, beginning with a velocity of 0
\li SmoothedAnimation.Sync - the property is immediately set to the target value
\endlist
*/
KQuickSmoothedAnimation::ReversingMode KQuickSmoothedAnimation::reversingMode() const
{
Q_D(const KQuickSmoothedAnimation);
return (KQuickSmoothedAnimation::ReversingMode) d->anim->reversingMode;
}
void KQuickSmoothedAnimation::setReversingMode(ReversingMode m)
{
Q_D(KQuickSmoothedAnimation);
if (d->anim->reversingMode == m)
return;
d->anim->reversingMode = m;
emit reversingModeChanged();
d->updateRunningAnimations();
}
/*!
\qmlproperty int QtQuick::SmoothedAnimation::duration
This property holds the animation duration, in msecs, used when tracking the source.
Setting this to -1 (the default) disables the duration value.
If the velocity value and the duration value are both enabled, then the animation will
use whichever gives the shorter duration.
*/
int KQuickSmoothedAnimation::duration() const
{
Q_D(const KQuickSmoothedAnimation);
return d->anim->userDuration;
}
void KQuickSmoothedAnimation::setDuration(int duration)
{
Q_D(KQuickSmoothedAnimation);
if (duration != -1)
QQuickNumberAnimation::setDuration(duration);
if(duration == d->anim->userDuration)
return;
d->anim->userDuration = duration;
d->updateRunningAnimations();
}
qreal KQuickSmoothedAnimation::velocity() const
{
Q_D(const KQuickSmoothedAnimation);
return d->anim->velocity;
}
/*!
\qmlproperty real QtQuick::SmoothedAnimation::velocity
This property holds the average velocity allowed when tracking the 'to' value.
The default velocity of SmoothedAnimation is 200 units/second.
Setting this to -1 disables the velocity value.
If the velocity value and the duration value are both enabled, then the animation will
use whichever gives the shorter duration.
*/
void KQuickSmoothedAnimation::setVelocity(qreal v)
{
Q_D(KQuickSmoothedAnimation);
if (d->anim->velocity == v)
return;
d->anim->velocity = v;
emit velocityChanged();
d->updateRunningAnimations();
}
/*!
\qmlproperty int QtQuick::SmoothedAnimation::maximumEasingTime
This property specifies the maximum time, in msecs, any "eases" during the follow should take.
Setting this property causes the velocity to "level out" after at a time. Setting
a negative value reverts to the normal mode of easing over the entire animation
duration.
The default value is -1.
*/
int KQuickSmoothedAnimation::maximumEasingTime() const
{
Q_D(const KQuickSmoothedAnimation);
return d->anim->maximumEasingTime;
}
void KQuickSmoothedAnimation::setMaximumEasingTime(int v)
{
Q_D(KQuickSmoothedAnimation);
if(v == d->anim->maximumEasingTime)
return;
d->anim->maximumEasingTime = v;
emit maximumEasingTimeChanged();
d->updateRunningAnimations();
}
QT_END_NAMESPACE

View File

@ -0,0 +1,55 @@
#ifndef KQUICKSMOOTHEDANIMATION_H
#define KQUICKSMOOTHEDANIMATION_H
#include <qqml.h>
#include <private/qquickanimation_p.h>
#include <QtCore/qobject.h>
QT_BEGIN_NAMESPACE
class QQmlProperty;
class KQuickSmoothedAnimationPrivate;
class Q_AUTOTEST_EXPORT KQuickSmoothedAnimation : public QQuickNumberAnimation
{
Q_OBJECT
Q_DECLARE_PRIVATE(KQuickSmoothedAnimation)
Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity NOTIFY velocityChanged)
Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode NOTIFY reversingModeChanged)
Q_PROPERTY(qreal maximumEasingTime READ maximumEasingTime WRITE setMaximumEasingTime NOTIFY maximumEasingTimeChanged)
public:
enum ReversingMode { Eased, Immediate, Sync };
Q_ENUM(ReversingMode)
KQuickSmoothedAnimation(QObject *parent = nullptr);
~KQuickSmoothedAnimation();
ReversingMode reversingMode() const;
void setReversingMode(ReversingMode);
int duration() const override;
void setDuration(int) override;
qreal velocity() const;
void setVelocity(qreal);
int maximumEasingTime() const;
void setMaximumEasingTime(int);
QAbstractAnimationJob* transition(QQuickStateActions &actions,
QQmlProperties &modified,
TransitionDirection direction,
QObject *defaultTarget = nullptr) override;
Q_SIGNALS:
void velocityChanged();
void reversingModeChanged();
void maximumEasingTimeChanged();
};
QT_END_NAMESPACE
QML_DECLARE_TYPE(KQuickSmoothedAnimation)
#endif // KQUICKSMOOTHEDANIMATION_H

View File

@ -0,0 +1,101 @@
#ifndef KQUICKSMOOTHEDANIMATION_P_H
#define KQUICKSMOOTHEDANIMATION_P_H
#include "kquicksmoothedanimation.h"
#include <private/qquickanimation_p.h>
#include <private/qquickanimation_p_p.h>
#include <private/qobject_p.h>
#include <QBasicTimer>
QT_BEGIN_NAMESPACE
class KSmoothedAnimation;
class KSmoothedAnimationTimer : public QTimer
{
Q_OBJECT
public:
explicit KSmoothedAnimationTimer(KSmoothedAnimation *animation, QObject *parent = nullptr);
~KSmoothedAnimationTimer();
public Q_SLOTS:
void stopAnimation();
private:
KSmoothedAnimation *m_animation;
};
class KQuickSmoothedAnimationPrivate;
class Q_AUTOTEST_EXPORT KSmoothedAnimation : public QAbstractAnimationJob
{
Q_DISABLE_COPY(KSmoothedAnimation)
public:
KSmoothedAnimation(KQuickSmoothedAnimationPrivate * = nullptr);
~KSmoothedAnimation();
qreal to;
qreal velocity;
int userDuration;
int maximumEasingTime;
KQuickSmoothedAnimation::ReversingMode reversingMode;
qreal initialVelocity;
qreal trackVelocity;
QQmlProperty target;
int duration() const override;
void restart();
void init();
void prepareForRestart();
void clearTemplate() { animationTemplate = nullptr; }
protected:
void updateCurrentTime(int) override;
void updateState(QAbstractAnimationJob::State, QAbstractAnimationJob::State) override;
void debugAnimation(QDebug d) const override;
private:
qreal easeFollow(qreal);
qreal initialValue;
bool invert;
int finalDuration;
// Parameters for use in updateCurrentTime()
qreal a; // Acceleration
qreal d; // Deceleration
qreal tf; // Total time
qreal tp; // Time at which peak velocity occurs
qreal td; // Time at which deceleration begins
qreal vp; // Velocity at tp
qreal sp; // Displacement at tp
qreal sd; // Displacement at td
qreal vi; // "Normalized" initialvelocity
qreal s; // Total s
int lastTime;
bool skipUpdate;
bool recalc();
void delayedStop();
KSmoothedAnimationTimer *delayedStopTimer;
KQuickSmoothedAnimationPrivate *animationTemplate;
};
class KQuickSmoothedAnimationPrivate : public QQuickPropertyAnimationPrivate
{
Q_DECLARE_PUBLIC(KQuickSmoothedAnimation)
public:
KQuickSmoothedAnimationPrivate();
~KQuickSmoothedAnimationPrivate();
void updateRunningAnimations();
KSmoothedAnimation *anim;
QHash<QQmlProperty, KSmoothedAnimation*> activeAnimations;
};
QT_END_NAMESPACE
#endif // KQUICKSMOOTHEDANIMATION_P_H

View File

@ -0,0 +1,917 @@
#include "kquicktimeline.h"
#include <QDebug>
#include <QMutex>
#include <QThread>
#include <QWaitCondition>
#include <QEvent>
#include <QCoreApplication>
#include <QEasingCurve>
#include <QTime>
#include <QtCore/private/qnumeric_p.h>
#include <algorithm>
QT_BEGIN_NAMESPACE
struct Update {
Update(KQuickTimeLineValue *_g, qreal _v)
: g(_g), v(_v) {}
Update(const KQuickTimeLineCallback &_e)
: g(nullptr), v(0), e(_e) {}
KQuickTimeLineValue *g;
qreal v;
KQuickTimeLineCallback e;
};
struct KQuickTimeLinePrivate
{
KQuickTimeLinePrivate(KQuickTimeLine *);
struct Op {
enum Type {
Pause,
Set,
Move,
MoveBy,
Accel,
AccelDistance,
Execute
};
Op() {}
Op(Type t, int l, qreal v, qreal v2, int o,
const KQuickTimeLineCallback &ev = KQuickTimeLineCallback(), const QEasingCurve &es = QEasingCurve())
: type(t), length(l), value(v), value2(v2), order(o), event(ev),
easing(es) {}
Op(const Op &o)
: type(o.type), length(o.length), value(o.value), value2(o.value2),
order(o.order), event(o.event), easing(o.easing) {}
Op &operator=(const Op &o) {
type = o.type; length = o.length; value = o.value;
value2 = o.value2; order = o.order; event = o.event;
easing = o.easing;
return *this;
}
Type type;
int length;
qreal value;
qreal value2;
int order;
KQuickTimeLineCallback event;
QEasingCurve easing;
};
struct TimeLine
{
TimeLine() {}
QList<Op> ops;
int length = 0;
int consumedOpLength = 0;
qreal base = 0.;
};
int length;
int syncPoint;
typedef QHash<KQuickTimeLineObject *, TimeLine> Ops;
Ops ops;
KQuickTimeLine *q;
void add(KQuickTimeLineObject &, const Op &);
qreal value(const Op &op, int time, qreal base, bool *) const;
int advance(int);
bool clockRunning;
int prevTime;
int order;
KQuickTimeLine::SyncMode syncMode;
int syncAdj;
QList<QPair<int, Update> > *updateQueue;
};
KQuickTimeLinePrivate::KQuickTimeLinePrivate(KQuickTimeLine *parent)
: length(0), syncPoint(0), q(parent), clockRunning(false), prevTime(0), order(0), syncMode(KQuickTimeLine::LocalSync), syncAdj(0), updateQueue(nullptr)
{
}
void KQuickTimeLinePrivate::add(KQuickTimeLineObject &g, const Op &o)
{
if (g._t && g._t != q) {
qWarning() << "KQuickTimeLine: Cannot modify a KQuickTimeLineValue owned by"
<< "another timeline.";
return;
}
g._t = q;
Ops::Iterator iter = ops.find(&g);
if (iter == ops.end()) {
iter = ops.insert(&g, TimeLine());
if (syncPoint > 0)
q->pause(g, syncPoint);
}
if (!iter->ops.isEmpty() &&
o.type == Op::Pause &&
iter->ops.constLast().type == Op::Pause) {
iter->ops.last().length += o.length;
iter->length += o.length;
} else {
iter->ops.append(o);
iter->length += o.length;
}
if (iter->length > length)
length = iter->length;
if (!clockRunning) {
q->stop();
prevTime = 0;
clockRunning = true;
if (syncMode == KQuickTimeLine::LocalSync) {
syncAdj = -1;
} else {
syncAdj = 0;
}
q->start();
/* q->tick(0);
if (syncMode == KQuickTimeLine::LocalSync) {
syncAdj = -1;
} else {
syncAdj = 0;
}
*/
}
}
qreal KQuickTimeLinePrivate::value(const Op &op, int time, qreal base, bool *changed) const
{
Q_ASSERT(time >= 0);
Q_ASSERT(time <= op.length);
*changed = true;
switch(op.type) {
case Op::Pause:
*changed = false;
return base;
case Op::Set:
return op.value;
case Op::Move:
if (time == 0) {
return base;
} else if (time == (op.length)) {
return op.value;
} else {
qreal delta = op.value - base;
qreal pTime = (qreal)(time) / (qreal)op.length;
if (op.easing.type() == QEasingCurve::Linear)
return base + delta * pTime;
else
return base + delta * op.easing.valueForProgress(pTime);
}
case Op::MoveBy:
if (time == 0) {
return base;
} else if (time == (op.length)) {
return base + op.value;
} else {
qreal delta = op.value;
qreal pTime = (qreal)(time) / (qreal)op.length;
if (op.easing.type() == QEasingCurve::Linear)
return base + delta * pTime;
else
return base + delta * op.easing.valueForProgress(pTime);
}
case Op::Accel:
if (time == 0) {
return base;
} else {
qreal t = (qreal)(time) / 1000.0f;
qreal delta = op.value * t + 0.5f * op.value2 * t * t;
return base + delta;
}
case Op::AccelDistance:
if (time == 0) {
return base;
} else if (time == (op.length)) {
return base + op.value2;
} else {
qreal t = (qreal)(time) / 1000.0f;
qreal accel = -1.0f * 1000.0f * op.value / (qreal)op.length;
qreal delta = op.value * t + 0.5f * accel * t * t;
return base + delta;
}
case Op::Execute:
op.event.d0(op.event.d1);
*changed = false;
return -1;
}
return base;
}
/*!
\internal
\class KQuickTimeLine
\brief The KQuickTimeLine class provides a timeline for controlling animations.
KQuickTimeLine is similar to QTimeLine except:
\list
\li It updates KQuickTimeLineValue instances directly, rather than maintaining a single
current value.
For example, the following animates a simple value over 200 milliseconds:
\code
KQuickTimeLineValue v(<starting value>);
KQuickTimeLine tl;
tl.move(v, 100., 200);
tl.start()
\endcode
If your program needs to know when values are changed, it can either
connect to the KQuickTimeLine's updated() signal, or inherit from KQuickTimeLineValue
and reimplement the KQuickTimeLineValue::setValue() method.
\li Supports multiple KQuickTimeLineValue, arbitrary start and end values and allows
animations to be strung together for more complex effects.
For example, the following animation moves the x and y coordinates of
an object from wherever they are to the position (100, 100) in 50
milliseconds and then further animates them to (100, 200) in 50
milliseconds:
\code
KQuickTimeLineValue x(<starting value>);
KQuickTimeLineValue y(<starting value>);
KQuickTimeLine tl;
tl.start();
tl.move(x, 100., 50);
tl.move(y, 100., 50);
tl.move(y, 200., 50);
\endcode
\li All KQuickTimeLine instances share a single, synchronized clock.
Actions scheduled within the same event loop tick are scheduled
synchronously against each other, regardless of the wall time between the
scheduling. Synchronized scheduling applies both to within the same
KQuickTimeLine and across separate KQuickTimeLine's within the same process.
\endlist
Currently easing functions are not supported.
*/
/*!
Construct a new KQuickTimeLine with the specified \a parent.
*/
KQuickTimeLine::KQuickTimeLine(QObject *parent)
: QObject(parent)
{
d = new KQuickTimeLinePrivate(this);
}
/*!
Destroys the time line. Any inprogress animations are canceled, but not
completed.
*/
KQuickTimeLine::~KQuickTimeLine()
{
for (KQuickTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
iter != d->ops.end();
++iter)
iter.key()->_t = nullptr;
delete d; d = nullptr;
}
/*!
\enum KQuickTimeLine::SyncMode
*/
/*!
Return the timeline's synchronization mode.
*/
KQuickTimeLine::SyncMode KQuickTimeLine::syncMode() const
{
return d->syncMode;
}
/*!
Set the timeline's synchronization mode to \a syncMode.
*/
void KQuickTimeLine::setSyncMode(SyncMode syncMode)
{
d->syncMode = syncMode;
}
/*!
Pause \a obj for \a time milliseconds.
*/
void KQuickTimeLine::pause(KQuickTimeLineObject &obj, int time)
{
if (time <= 0) return;
KQuickTimeLinePrivate::Op op(KQuickTimeLinePrivate::Op::Pause, time, 0., 0., d->order++);
d->add(obj, op);
}
/*!
Execute the \a event.
*/
void KQuickTimeLine::callback(const KQuickTimeLineCallback &callback)
{
KQuickTimeLinePrivate::Op op(KQuickTimeLinePrivate::Op::Execute, 0, 0, 0., d->order++, callback);
d->add(*callback.callbackObject(), op);
}
/*!
Set the \a value of \a timeLineValue.
*/
void KQuickTimeLine::set(KQuickTimeLineValue &timeLineValue, qreal value)
{
KQuickTimeLinePrivate::Op op(KQuickTimeLinePrivate::Op::Set, 0, value, 0., d->order++);
d->add(timeLineValue, op);
}
/*!
Decelerate \a timeLineValue from the starting \a velocity to zero at the
given \a acceleration rate. Although the \a acceleration is technically
a deceleration, it should always be positive. The KQuickTimeLine will ensure
that the deceleration is in the opposite direction to the initial velocity.
*/
int KQuickTimeLine::accel(KQuickTimeLineValue &timeLineValue, qreal velocity, qreal acceleration)
{
if (qFuzzyIsNull(acceleration) || qt_is_nan(acceleration))
return -1;
if ((velocity > 0.0f) == (acceleration > 0.0f))
acceleration = acceleration * -1.0f;
int time = static_cast<int>(-1000 * velocity / acceleration);
if (time <= 0) return -1;
KQuickTimeLinePrivate::Op op(KQuickTimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
d->add(timeLineValue, op);
return time;
}
/*!
\overload
Decelerate \a timeLineValue from the starting \a velocity to zero at the
given \a acceleration rate over a maximum distance of maxDistance.
If necessary, KQuickTimeLine will reduce the acceleration to ensure that the
entire operation does not require a move of more than \a maxDistance.
\a maxDistance should always be positive.
*/
int KQuickTimeLine::accel(KQuickTimeLineValue &timeLineValue, qreal velocity, qreal acceleration, qreal maxDistance)
{
if (qFuzzyIsNull(maxDistance) || qt_is_nan(maxDistance) || qFuzzyIsNull(acceleration) || qt_is_nan(acceleration))
return -1;
Q_ASSERT(acceleration > 0.0f && maxDistance > 0.0f);
qreal maxAccel = (velocity * velocity) / (2.0f * maxDistance);
if (maxAccel > acceleration)
acceleration = maxAccel;
if ((velocity > 0.0f) == (acceleration > 0.0f))
acceleration = acceleration * -1.0f;
int time = static_cast<int>(-1000 * velocity / acceleration);
if (time <= 0) return -1;
KQuickTimeLinePrivate::Op op(KQuickTimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
d->add(timeLineValue, op);
return time;
}
/*!
Decelerate \a timeLineValue from the starting \a velocity to zero over the given
\a distance. This is like accel(), but the KQuickTimeLine calculates the exact
deceleration to use.
\a distance should be positive.
*/
int KQuickTimeLine::accelDistance(KQuickTimeLineValue &timeLineValue, qreal velocity, qreal distance)
{
if (qFuzzyIsNull(distance) || qt_is_nan(distance) || qFuzzyIsNull(velocity) || qt_is_nan(velocity))
return -1;
Q_ASSERT((distance >= 0.0f) == (velocity >= 0.0f));
int time = static_cast<int>(1000 * (2.0f * distance) / velocity);
if (time <= 0) return -1;
KQuickTimeLinePrivate::Op op(KQuickTimeLinePrivate::Op::AccelDistance, time, velocity, distance, d->order++);
d->add(timeLineValue, op);
return time;
}
/*!
Linearly change the \a timeLineValue from its current value to the given
\a destination value over \a time milliseconds.
*/
void KQuickTimeLine::move(KQuickTimeLineValue &timeLineValue, qreal destination, int time)
{
if (time <= 0) return;
KQuickTimeLinePrivate::Op op(KQuickTimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++);
d->add(timeLineValue, op);
}
/*!
Change the \a timeLineValue from its current value to the given \a destination
value over \a time milliseconds using the \a easing curve.
*/
void KQuickTimeLine::move(KQuickTimeLineValue &timeLineValue, qreal destination, const QEasingCurve &easing, int time)
{
if (time <= 0) return;
KQuickTimeLinePrivate::Op op(KQuickTimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++, KQuickTimeLineCallback(), easing);
d->add(timeLineValue, op);
}
/*!
Linearly change the \a timeLineValue from its current value by the \a change amount
over \a time milliseconds.
*/
void KQuickTimeLine::moveBy(KQuickTimeLineValue &timeLineValue, qreal change, int time)
{
if (time <= 0) return;
KQuickTimeLinePrivate::Op op(KQuickTimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++);
d->add(timeLineValue, op);
}
/*!
Change the \a timeLineValue from its current value by the \a change amount over
\a time milliseconds using the \a easing curve.
*/
void KQuickTimeLine::moveBy(KQuickTimeLineValue &timeLineValue, qreal change, const QEasingCurve &easing, int time)
{
if (time <= 0) return;
KQuickTimeLinePrivate::Op op(KQuickTimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++, KQuickTimeLineCallback(), easing);
d->add(timeLineValue, op);
}
/*!
Cancel (but don't complete) all scheduled actions for \a timeLineValue.
*/
void KQuickTimeLine::reset(KQuickTimeLineValue &timeLineValue)
{
if (!timeLineValue._t)
return;
if (timeLineValue._t != this) {
qWarning() << "KQuickTimeLine: Cannot reset a KQuickTimeLineValue owned by another timeline.";
return;
}
remove(&timeLineValue);
timeLineValue._t = nullptr;
}
int KQuickTimeLine::duration() const
{
return -1;
}
/*!
Synchronize the end point of \a timeLineValue to the endpoint of \a syncTo
within this timeline.
Following operations on \a timeLineValue in this timeline will be scheduled after
all the currently scheduled actions on \a syncTo are complete. In
pseudo-code this is equivalent to:
\code
KQuickTimeLine::pause(timeLineValue, min(0, length_of(syncTo) - length_of(timeLineValue)))
\endcode
*/
void KQuickTimeLine::sync(KQuickTimeLineValue &timeLineValue, KQuickTimeLineValue &syncTo)
{
KQuickTimeLinePrivate::Ops::Iterator iter = d->ops.find(&syncTo);
if (iter == d->ops.end())
return;
int length = iter->length;
iter = d->ops.find(&timeLineValue);
if (iter == d->ops.end()) {
pause(timeLineValue, length);
} else {
int glength = iter->length;
pause(timeLineValue, length - glength);
}
}
/*!
Synchronize the end point of \a timeLineValue to the endpoint of the longest
action cursrently scheduled in the timeline.
In pseudo-code, this is equivalent to:
\code
KQuickTimeLine::pause(timeLineValue, length_of(timeline) - length_of(timeLineValue))
\endcode
*/
void KQuickTimeLine::sync(KQuickTimeLineValue &timeLineValue)
{
KQuickTimeLinePrivate::Ops::Iterator iter = d->ops.find(&timeLineValue);
if (iter == d->ops.end()) {
pause(timeLineValue, d->length);
} else {
pause(timeLineValue, d->length - iter->length);
}
}
/*
Synchronize all currently and future scheduled values in this timeline to
the longest action currently scheduled.
For example:
\code
value1->setValue(0.);
value2->setValue(0.);
value3->setValue(0.);
KQuickTimeLine tl;
...
tl.move(value1, 10, 200);
tl.move(value2, 10, 100);
tl.sync();
tl.move(value2, 20, 100);
tl.move(value3, 20, 100);
\endcode
will result in:
\table
\header \li \li 0ms \li 50ms \li 100ms \li 150ms \li 200ms \li 250ms \li 300ms
\row \li value1 \li 0 \li 2.5 \li 5.0 \li 7.5 \li 10 \li 10 \li 10
\row \li value2 \li 0 \li 5.0 \li 10.0 \li 10.0 \li 10.0 \li 15.0 \li 20.0
\row \li value2 \li 0 \li 0 \li 0 \li 0 \li 0 \li 10.0 \li 20.0
\endtable
*/
/*void KQuickTimeLine::sync()
{
for (KQuickTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
iter != d->ops.end();
++iter)
pause(*iter.key(), d->length - iter->length);
d->syncPoint = d->length;
}*/
/*!
\internal
Temporary hack.
*/
void KQuickTimeLine::setSyncPoint(int sp)
{
d->syncPoint = sp;
}
/*!
\internal
Temporary hack.
*/
int KQuickTimeLine::syncPoint() const
{
return d->syncPoint;
}
/*!
Returns true if the timeline is active. An active timeline is one where
KQuickTimeLineValue actions are still pending.
*/
bool KQuickTimeLine::isActive() const
{
return !d->ops.isEmpty();
}
/*!
Completes the timeline. All queued actions are played to completion, and then discarded. For example,
\code
KQuickTimeLineValue v(0.);
KQuickTimeLine tl;
tl.move(v, 100., 1000.);
// 500 ms passes
// v.value() == 50.
tl.complete();
// v.value() == 100.
\endcode
*/
void KQuickTimeLine::complete()
{
d->advance(d->length);
}
/*!
Resets the timeline. All queued actions are discarded and KQuickTimeLineValue's retain their current value. For example,
\code
KQuickTimeLineValue v(0.);
KQuickTimeLine tl;
tl.move(v, 100., 1000.);
// 500 ms passes
// v.value() == 50.
tl.clear();
// v.value() == 50.
\endcode
*/
void KQuickTimeLine::clear()
{
for (KQuickTimeLinePrivate::Ops::const_iterator iter = d->ops.cbegin(), cend = d->ops.cend(); iter != cend; ++iter)
iter.key()->_t = nullptr;
d->ops.clear();
d->length = 0;
d->syncPoint = 0;
//XXX need stop here?
}
int KQuickTimeLine::time() const
{
return d->prevTime;
}
/*!
\fn void KQuickTimeLine::updated()
Emitted each time the timeline modifies KQuickTimeLineValues. Even if multiple
KQuickTimeLineValues are changed, this signal is only emitted once for each clock tick.
*/
void KQuickTimeLine::updateCurrentTime(int v)
{
if (d->syncAdj == -1)
d->syncAdj = v;
v -= d->syncAdj;
int timeChanged = v - d->prevTime;
#if 0
if (!timeChanged)
return;
#endif
d->prevTime = v;
d->advance(timeChanged);
emit updated();
// Do we need to stop the clock?
if (d->ops.isEmpty()) {
stop();
d->prevTime = 0;
d->clockRunning = false;
emit completed();
} /*else if (pauseTime > 0) {
GfxClock::cancelClock();
d->prevTime = 0;
GfxClock::pauseFor(pauseTime);
d->syncAdj = 0;
d->clockRunning = false;
}*/ else if (/*!GfxClock::isActive()*/ state() != Running) {
stop();
d->prevTime = 0;
d->clockRunning = true;
d->syncAdj = 0;
start();
}
}
void KQuickTimeLine::debugAnimation(QDebug d) const
{
d << "QuickTimeLine(" << hex << (const void *) this << dec << ")";
}
bool operator<(const QPair<int, Update> &lhs,
const QPair<int, Update> &rhs)
{
return lhs.first < rhs.first;
}
int KQuickTimeLinePrivate::advance(int t)
{
int pauseTime = -1;
// XXX - surely there is a more efficient way?
do {
pauseTime = -1;
// Minimal advance time
int advanceTime = t;
for (Ops::const_iterator iter = ops.constBegin(), cend = ops.constEnd(); iter != cend; ++iter) {
const TimeLine &tl = *iter;
const Op &op = tl.ops.first();
int length = op.length - tl.consumedOpLength;
if (length < advanceTime) {
advanceTime = length;
if (advanceTime == 0)
break;
}
}
t -= advanceTime;
// Process until then. A zero length advance time will only process
// sets.
QList<QPair<int, Update> > updates;
for (Ops::Iterator iter = ops.begin(); iter != ops.end(); ) {
KQuickTimeLineValue *v = static_cast<KQuickTimeLineValue *>(iter.key());
TimeLine &tl = *iter;
Q_ASSERT(!tl.ops.isEmpty());
do {
Op &op = tl.ops.first();
if (advanceTime == 0 && op.length != 0)
continue;
if (tl.consumedOpLength == 0 &&
op.type != Op::Pause &&
op.type != Op::Execute)
tl.base = v->value();
if ((tl.consumedOpLength + advanceTime) == op.length) {
if (op.type == Op::Execute) {
updates << qMakePair(op.order, Update(op.event));
} else {
bool changed = false;
qreal val = value(op, op.length, tl.base, &changed);
if (changed)
updates << qMakePair(op.order, Update(v, val));
}
tl.length -= qMin(advanceTime, tl.length);
tl.consumedOpLength = 0;
tl.ops.removeFirst();
} else {
tl.consumedOpLength += advanceTime;
bool changed = false;
qreal val = value(op, tl.consumedOpLength, tl.base, &changed);
if (changed)
updates << qMakePair(op.order, Update(v, val));
tl.length -= qMin(advanceTime, tl.length);
break;
}
} while(!tl.ops.isEmpty() && advanceTime == 0 && tl.ops.first().length == 0);
if (tl.ops.isEmpty()) {
iter = ops.erase(iter);
v->_t = nullptr;
} else {
if (tl.ops.first().type == Op::Pause && pauseTime != 0) {
int opPauseTime = tl.ops.first().length - tl.consumedOpLength;
if (pauseTime == -1 || opPauseTime < pauseTime)
pauseTime = opPauseTime;
} else {
pauseTime = 0;
}
++iter;
}
}
length -= qMin(length, advanceTime);
syncPoint -= advanceTime;
std::sort(updates.begin(), updates.end());
updateQueue = &updates;
for (int ii = 0; ii < updates.count(); ++ii) {
const Update &v = updates.at(ii).second;
if (v.g) {
v.g->setValue(v.v);
} else {
v.e.d0(v.e.d1);
}
}
updateQueue = nullptr;
} while(t);
return pauseTime;
}
void KQuickTimeLine::remove(KQuickTimeLineObject *v)
{
KQuickTimeLinePrivate::Ops::Iterator iter = d->ops.find(v);
Q_ASSERT(iter != d->ops.end());
int len = iter->length;
d->ops.erase(iter);
if (len == d->length) {
// We need to recalculate the length
d->length = 0;
for (KQuickTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
iter != d->ops.end();
++iter) {
if (iter->length > d->length)
d->length = iter->length;
}
}
if (d->ops.isEmpty()) {
stop();
d->clockRunning = false;
} else if (state() != Running) { // was !GfxClock::isActive()
stop();
d->prevTime = 0;
d->clockRunning = true;
if (d->syncMode == KQuickTimeLine::LocalSync) {
d->syncAdj = -1;
} else {
d->syncAdj = 0;
}
start();
}
if (d->updateQueue) {
for (int ii = 0; ii < d->updateQueue->count(); ++ii) {
if (d->updateQueue->at(ii).second.g == v ||
d->updateQueue->at(ii).second.e.callbackObject() == v) {
d->updateQueue->removeAt(ii);
--ii;
}
}
}
}
/*!
\internal
\class KQuickTimeLineValue
\brief The KQuickTimeLineValue class provides a value that can be modified by KQuickTimeLine.
*/
/*!
\fn KQuickTimeLineValue::KQuickTimeLineValue(qreal value = 0)
Construct a new KQuickTimeLineValue with an initial \a value.
*/
/*!
\fn qreal KQuickTimeLineValue::value() const
Return the current value.
*/
/*!
\fn void KQuickTimeLineValue::setValue(qreal value)
Set the current \a value.
*/
/*!
\fn KQuickTimeLine *KQuickTimeLineValue::timeLine() const
If a KQuickTimeLine is operating on this value, return a pointer to it,
otherwise return null.
*/
KQuickTimeLineObject::KQuickTimeLineObject()
: _t(nullptr)
{
}
KQuickTimeLineObject::~KQuickTimeLineObject()
{
if (_t) {
_t->remove(this);
_t = nullptr;
}
}
KQuickTimeLineCallback::KQuickTimeLineCallback()
: d0(nullptr), d1(nullptr), d2(nullptr)
{
}
KQuickTimeLineCallback::KQuickTimeLineCallback(KQuickTimeLineObject *b, Callback f, void *d)
: d0(f), d1(d), d2(b)
{
}
KQuickTimeLineCallback::KQuickTimeLineCallback(const KQuickTimeLineCallback &o)
: d0(o.d0), d1(o.d1), d2(o.d2)
{
}
KQuickTimeLineCallback &KQuickTimeLineCallback::operator=(const KQuickTimeLineCallback &o)
{
d0 = o.d0;
d1 = o.d1;
d2 = o.d2;
return *this;
}
KQuickTimeLineObject *KQuickTimeLineCallback::callbackObject() const
{
return d2;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,149 @@
#ifndef KQUICKTIMELINE_H
#define KQUICKTIMELINE_H
#include <QtCore/QObject>
#include "private/qabstractanimationjob_p.h"
QT_BEGIN_NAMESPACE
class QEasingCurve;
class KQuickTimeLineValue;
class KQuickTimeLineCallback;
struct KQuickTimeLinePrivate;
class KQuickTimeLineObject;
class KQuickTimeLine : public QObject, QAbstractAnimationJob
{
Q_OBJECT
public:
KQuickTimeLine(QObject *parent = nullptr);
~KQuickTimeLine();
enum SyncMode { LocalSync, GlobalSync };
SyncMode syncMode() const;
void setSyncMode(SyncMode);
void pause(KQuickTimeLineObject &, int);
void callback(const KQuickTimeLineCallback &);
void set(KQuickTimeLineValue &, qreal);
int accel(KQuickTimeLineValue &, qreal velocity, qreal accel);
int accel(KQuickTimeLineValue &, qreal velocity, qreal accel, qreal maxDistance);
int accelDistance(KQuickTimeLineValue &, qreal velocity, qreal distance);
void move(KQuickTimeLineValue &, qreal destination, int time = 500);
void move(KQuickTimeLineValue &, qreal destination, const QEasingCurve &, int time = 500);
void moveBy(KQuickTimeLineValue &, qreal change, int time = 500);
void moveBy(KQuickTimeLineValue &, qreal change, const QEasingCurve &, int time = 500);
void sync();
void setSyncPoint(int);
int syncPoint() const;
void sync(KQuickTimeLineValue &);
void sync(KQuickTimeLineValue &, KQuickTimeLineValue &);
void reset(KQuickTimeLineValue &);
void complete();
void clear();
bool isActive() const;
int time() const;
int duration() const override;
Q_SIGNALS:
void updated();
void completed();
protected:
void updateCurrentTime(int) override;
void debugAnimation(QDebug d) const override;
private:
void remove(KQuickTimeLineObject *);
friend class KQuickTimeLineObject;
friend struct KQuickTimeLinePrivate;
KQuickTimeLinePrivate *d;
};
class KQuickTimeLineObject
{
public:
KQuickTimeLineObject();
virtual ~KQuickTimeLineObject();
protected:
friend class KQuickTimeLine;
friend struct KQuickTimeLinePrivate;
KQuickTimeLine *_t;
};
class KQuickTimeLineValue : public KQuickTimeLineObject
{
public:
KQuickTimeLineValue(qreal v = 0.) : _v(v) {}
virtual qreal value() const { return _v; }
virtual void setValue(qreal v) { _v = v; }
KQuickTimeLine *timeLine() const { return _t; }
operator qreal() const { return _v; }
KQuickTimeLineValue &operator=(qreal v) { setValue(v); return *this; }
private:
friend class KQuickTimeLine;
friend struct KQuickTimeLinePrivate;
qreal _v;
};
class KQuickTimeLineCallback
{
public:
typedef void (*Callback)(void *);
KQuickTimeLineCallback();
KQuickTimeLineCallback(KQuickTimeLineObject *b, Callback, void * = nullptr);
KQuickTimeLineCallback(const KQuickTimeLineCallback &o);
KQuickTimeLineCallback &operator=(const KQuickTimeLineCallback &o);
KQuickTimeLineObject *callbackObject() const;
private:
friend struct KQuickTimeLinePrivate;
Callback d0;
void *d1;
KQuickTimeLineObject *d2;
};
template<class T>
class KQuickTimeLineValueProxy : public KQuickTimeLineValue
{
public:
KQuickTimeLineValueProxy(T *cls, void (T::*func)(qreal), qreal v = 0.)
: KQuickTimeLineValue(v), _class(cls), _setFunctionReal(func), _setFunctionInt(nullptr)
{
Q_ASSERT(_class);
}
KQuickTimeLineValueProxy(T *cls, void (T::*func)(int), qreal v = 0.)
: KQuickTimeLineValue(v), _class(cls), _setFunctionReal(0), _setFunctionInt(func)
{
Q_ASSERT(_class);
}
void setValue(qreal v) override
{
KQuickTimeLineValue::setValue(v);
if (_setFunctionReal) (_class->*_setFunctionReal)(v);
else if (_setFunctionInt) (_class->*_setFunctionInt)((int)v);
}
private:
T *_class;
void (T::*_setFunctionReal)(qreal);
void (T::*_setFunctionInt)(int);
};
QT_END_NAMESPACE
#endif // KQUICKTIMELINE_H

View File

@ -0,0 +1,164 @@
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Window 2.0
import QtQml.Models 2.2
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
ListView {
id: listView
anchors.fill: parent
snapMode: ListView.SnapOneItem
model: modelManager.launcherModel
orientation: ListView.Horizontal
highlightRangeMode: ListView.StrictlyEnforceRange
boundsBehavior:Flickable.StopAtBounds
delegate:
DropArea {
width: listView.width
height: listView.height
Rectangle {
id: parentRect
width: listView.width
height: listView.height
color: index%2 ? "grey":"yellow"
Label{
anchors.centerIn: parent
font.pointSize: 100
text: index
}
GridView {
id: gridview
width: 400
height: 400
cellWidth: 80
cellHeight: 80
interactive: true
model: modelData
add: Transition {
NumberAnimation { properties: "x,y"; duration: 500 }
}
addDisplaced: Transition {
NumberAnimation { properties: "x,y"; duration: 500 }
}
move: Transition {
NumberAnimation { properties: "x,y"; duration: 500 }
}
moveDisplaced: Transition {
NumberAnimation { properties: "x,y"; duration: 500 }
}
remove: Transition {
NumberAnimation { properties: "x,y"; duration: 500 }
}
removeDisplaced: Transition {
NumberAnimation { properties: "x,y"; duration: 500 }
}
displaced: Transition {
NumberAnimation { properties: "x,y"; duration: 500 }
}
delegate:
DropArea {
id: dragArea
width: 80
height: 80
onEntered: {
console.log(drag.source.visualIndex, drag.source.pageIndex,
visualIndex, pageIndex)
if (drag.source.pageIndex !== pageIndex) {
modelManager.moveItem(drag.source.visualIndex, drag.source.pageIndex,
visualIndex, pageIndex)
}
}
onDropped: {
console.log("===onDropped")
}
property int visualIndex: model.index
property int pageIndex: modelData.pageIndex
Binding { target: item; property: "visualIndex"; value: visualIndex }
Binding { target: item; property: "pageIndex"; value: pageIndex }
MouseArea {
id: mouseAreaHandle
property int pageIndex: model.modelData.pageIndex
property int visualIndex: visualIndex
property bool held: false
property bool changed: false
drag.target: item
hoverEnabled: true
width: listView.width
height: listView.height
onPositionChanged: {
console.log("移动的矩形x坐标: " + item.mapToItem(listView,0,0))
var pos = item.mapToItem(listView,0,0)
console.log("pos.x: " + pos.x)
if (item.x >= 400 && !changed) {
listView.currentIndex++
changed = true
console.log("currentIndex" + listView.currentIndex)
}
if (item.x < 0 && !changed) {
listView.currentIndex--
changed = true
console.log("currentIndex" + listView.currentIndex)
}
}
}
Rectangle {
id: item
width: 72
height: 72
color: modelData.name
property int visualIndex: 0
property int pageIndex: 0
Text {
id: text
text: index
}
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
DragHandler {
id: dragHandler
}
Drag.active: dragHandler.active
Drag.source: item
Drag.hotSpot.x: 36
Drag.hotSpot.y: 36
states: [
State {
when: item.Drag.active
ParentChange {
target: item
parent: listView
}
AnchorChanges {
target: item
anchors.horizontalCenter: undefined
anchors.verticalCenter: undefined
}
}
]
}
}
}
}
}
}

View File

@ -0,0 +1,77 @@
#include "basemodel.h"
#include "basemodel_p.h"
namespace Internal {
// class BaseModel
BaseModel::BaseModel(QObject *parent)
: QAbstractListModel(parent)
, d_ptr(new BaseModelPrivate())
{
d_ptr->q_ptr = this;
}
BaseModel::~BaseModel()
{
}
QHash<int, QByteArray> BaseModel::roleNames() const
{
#ifdef Q_COMPILER_INITIALIZER_LISTS
QHash<int, QByteArray> roleNames { { BaseModel::ModelDataRole, "modelData" } };
#else
QHash<int, QByteArray> roleNames;
roleNames[BaseModel::ModelDataRole] = "modelData";
#endif // Q_COMPILER_INITIALIZER_LISTS
return roleNames;
}
void BaseModel::_q_resetCount()
{
Q_D(BaseModel);
if (d->countEnabled) {
int count = rowCount();
if (count != d->count) {
d->count = count;
emit countChanged();
}
}
}
bool BaseModel::isCountEnabled() const
{
Q_D(const BaseModel);
return d->countEnabled;
}
void BaseModel::setCountEnabled(bool y)
{
Q_D(BaseModel);
if (y != d->countEnabled) {
d->countEnabled = y;
if (!d->countEnabled) {
d->count = -1;
}
emit countEnabledChanged();
}
}
// class BaseModelPrivate
BaseModelPrivate::BaseModelPrivate()
: q_ptr(nullptr)
, countEnabled(false)
, count(-1)
{
}
BaseModelPrivate::~BaseModelPrivate()
{
}
} // namespace Internal

View File

@ -0,0 +1,573 @@
#ifndef BASEMODEL_H
#define BASEMODEL_H
#include <QPoint>
#include <QAbstractListModel>
#include <QList>
#if defined(QT_TESTLIB_LIB)
# define BaseModel_ASSERT(x)
#else
# define BaseModel_ASSERT(x) Q_ASSERT(x)
#endif
namespace Internal {
template <typename T>
struct QBaseModelListGuard
{
};
class BaseModelPrivate;
class BaseModel : public QAbstractListModel
{
Q_OBJECT
Q_DECLARE_PRIVATE(BaseModel)
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
Q_PROPERTY(bool countEnabled READ isCountEnabled NOTIFY countEnabledChanged)
public:
explicit BaseModel(QObject *parent = nullptr);
virtual ~BaseModel();
protected:
QScopedPointer<BaseModelPrivate> d_ptr;
public:
enum ModelDataRoles {
ModelDataRole = Qt::UserRole + 1,
};
QHash<int, QByteArray> roleNames() const override;
signals:
void countChanged();
protected:
void _q_resetCount();
signals:
void countEnabledChanged();
public:
bool isCountEnabled() const;
void setCountEnabled(bool y);
};
} // namespace Internal
template <typename T>
class BaseModel : public Internal::BaseModel, public QList<T>
{
public:
BaseModel(const QList<T> &l, QObject *parent = nullptr)
: Internal::BaseModel(parent), QList<T>(l) { }
explicit BaseModel(QObject *parent = nullptr)
: Internal::BaseModel(parent) { }
BaseModel(const BaseModel<T> &other);
public:
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
public:
T value(const QModelIndex &index) const;
T value(const QModelIndex &index, const T &defaultValue) const;
T value(int i) const;
T value(int i, const T &defaultValue) const;
public:
void append(const QList<T> &l);
void prepend(const T &t);
void append(const T &t);
void push_front(const T &t);
void push_back(const T &t);
void replace(int i, const T &t);
void insert(int i, const T &t);
bool removeOne(const T &t);
int removeAll(const T &t);
void pop_front();
void pop_back();
void removeAt(int i);
void removeFirst();
void removeLast();
T takeAt(int i);
T takeFirst();
T takeLast();
void swap(int i, int j);
void swap(QList<T> &list);
void move(int from, int to);
void clear();
public: // Extra methods
void deleteAll();
public: // Disabled stl methods
typedef typename QList<T>::iterator Iterator;
typedef typename QList<T>::reverse_iterator ReverseIterator;
/// \todo 实现以下接口
// Iterator begin(); // Not Implemented
// Iterator end(); // Not Implemented
// ReverseIterator rbegin(); // Not Implemented
// ReverseIterator rend(); // Not Implemented
// Iterator insert(Iterator before, const T &t); // Not Implemented
// Iterator erase(Iterator pos); // No Implemented
// Iterator erase(Iterator begin, Iterator end); // Not Implemented
public:
BaseModel<T> &operator=(const QList<T> &l);
inline QList<T> operator+(const QList<T> &others) const
{ QList<T> l = *this; l.append(others); return l; }
inline bool operator==(const QList<T> &other) const
{ return QList<T>::operator==(other); }
inline bool operator!=(const QList<T> &other) const
{ return QList<T>::operator!=(other); }
inline BaseModel<T> &operator+=(const QList<T> &l)
{ append(l); return *this; }
inline BaseModel<T> &operator<<(const QList<T> &l)
{ append(l); return *this; }
inline BaseModel<T> &operator+=(const T &t)
{ append(t); return *this; }
inline BaseModel<T> &operator<<(const T &t)
{ append(t); return *this; }
public:
inline const QList<T> &ref() const { return *this; }
};
template<typename T>
BaseModel<T>::BaseModel(const BaseModel<T> &other)
{
beginResetModel();
QList<T> tmp(other);
tmp.swap(*this);
endResetModel();
_q_resetCount();
}
template <typename T>
int BaseModel<T>::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : QList<T>::count();
}
template <typename T>
QVariant BaseModel<T>::data(const QModelIndex &index, int role) const
{
if ((ModelDataRole != role)
|| !index.isValid()
|| (index.model() != this)
|| (index.row() >= QList<T>::count())) {
return QVariant();
}
return QVariant::fromValue(QList<T>::at(index.row()));
}
template<typename T>
QModelIndex BaseModel<T>::index(int row, int column, const QModelIndex &parent) const
{
if ((row < 0)
|| (column != 0)
|| (row >= QList<T>::count())
|| parent.isValid()) {
return QModelIndex();
}
return createIndex(row, 0);
}
template<typename T>
T BaseModel<T>::value(const QModelIndex &index) const
{
BaseModel_ASSERT(index.model() == this);
return QList<T>::value(index.row());
}
template<typename T>
T BaseModel<T>::value(const QModelIndex &index, const T &defaultValue) const
{
BaseModel_ASSERT(index.model() == this);
return QList<T>::value(index.row(), defaultValue);
}
template<typename T>
T BaseModel<T>::value(int i) const
{
return QList<T>::value(i);
}
template<typename T>
T BaseModel<T>::value(int i, const T &defaultValue) const
{
return QList<T>::value(i, defaultValue);
}
template <typename T>
void BaseModel<T>::append(const QList<T> &l)
{
if (l.isEmpty())
return;
int f = QList<T>::count();
int t = f + l.count() - 1;
beginInsertRows(QModelIndex(), f, t);
QList<T>::append(l);
endInsertRows();
_q_resetCount();
}
template <typename T>
void BaseModel<T>::prepend(const T &t)
{
beginInsertRows(QModelIndex(), 0, 0);
QList<T>::prepend(t);
endInsertRows();
_q_resetCount();
}
template <typename T>
void BaseModel<T>::append(const T &t)
{
int r = QList<T>::count();
beginInsertRows(QModelIndex(), r, r);
QList<T>::append(t);
endInsertRows();
_q_resetCount();
}
template <typename T>
void BaseModel<T>::push_front(const T &t)
{
beginInsertRows(QModelIndex(), 0, 0);
QList<T>::push_front(t);
endInsertRows();
_q_resetCount();
}
template <typename T>
void BaseModel<T>::push_back(const T &t)
{
int r = QList<T>::count();
beginInsertRows(QModelIndex(), r, r);
QList<T>::push_back(t);
endInsertRows();
_q_resetCount();
}
template <typename T>
void BaseModel<T>::replace(int i, const T &t)
{
BaseModel_ASSERT(i >= 0);
BaseModel_ASSERT(i < QList<T>::count());
QModelIndex x = index(i, 0);
if (!x.isValid()) {
return;
}
beginResetModel();
QList<T>::replace(i, t);
endResetModel();
emit dataChanged(x, x);
}
template <typename T>
void BaseModel<T>::insert(int i, const T &t)
{
BaseModel_ASSERT(i >= 0);
BaseModel_ASSERT(i <= QList<T>::count());
beginInsertRows(QModelIndex(), i, i);
QList<T>::insert(i, t);
endInsertRows();
_q_resetCount();
}
template <typename T>
bool BaseModel<T>::removeOne(const T &t)
{
typename QList<T>::iterator p = QList<T>::begin();
typename QList<T>::iterator end = QList<T>::end();
for (int i = 0; p != end; ++p, ++i) {
if (*p == t) {
beginRemoveRows(QModelIndex(), i, i);
QList<T>::erase(p);
endRemoveRows();
_q_resetCount();
return true;
}
}
return false;
}
template <typename T>
int BaseModel<T>::removeAll(const T &t)
{
typename QList<T>::iterator null;
typename QList<T>::iterator f = null;
typename QList<T>::iterator l = null;
typename QList<T>::iterator p = QList<T>::begin();
typename QList<T>::iterator end = QList<T>::end();
int c = 0;
int fpos = 0;
int lpos = 0;
for (int i = 0; p != end; ++p, ++i) {
if (t == *p) {
if (f == null) {
fpos = i;
f = p;
}
lpos = i;
l = p;
} else if (f != null) {
beginRemoveRows(QModelIndex(), fpos - c, lpos - c);
QList<T>::erase(f, ++l);
endRemoveRows();
c += lpos - fpos + 1;
f = null;
l = null;
}
}
if (f != null) {
beginRemoveRows(QModelIndex(), fpos - c, lpos - c);
QList<T>::erase(f, ++l);
endRemoveRows();
c += lpos - fpos + 1;
}
_q_resetCount();
return c;
}
template <typename T>
void BaseModel<T>::pop_front()
{
BaseModel_ASSERT(QList<T>::count() > 0);
beginRemoveRows(QModelIndex(), 0, 0);
QList<T>::pop_front();
endRemoveRows();
_q_resetCount();
}
template <typename T>
void BaseModel<T>::pop_back()
{
BaseModel_ASSERT(QList<T>::count() > 0);
int r = QList<T>::count() - 1;
beginRemoveRows(QModelIndex(), r, r);
QList<T>::pop_back();
endRemoveRows();
_q_resetCount();
}
template <typename T>
void BaseModel<T>::removeAt(int i)
{
BaseModel_ASSERT(i >= 0);
BaseModel_ASSERT(i < QList<T>::count());
beginRemoveRows(QModelIndex(), i, i);
QList<T>::removeAt(i);
endRemoveRows();
_q_resetCount();
}
template <typename T>
void BaseModel<T>::removeFirst()
{
BaseModel_ASSERT(QList<T>::count() > 0);
beginRemoveRows(QModelIndex(), 0, 0);
QList<T>::removeFirst();
endRemoveRows();
_q_resetCount();
}
template <typename T>
void BaseModel<T>::removeLast()
{
BaseModel_ASSERT(QList<T>::count() > 0);
int r = QList<T>::count() - 1;
beginRemoveRows(QModelIndex(), r, r);
QList<T>::removeLast();
endRemoveRows();
_q_resetCount();
}
template <typename T>
T BaseModel<T>::takeAt(int i)
{
BaseModel_ASSERT(i >= 0);
BaseModel_ASSERT(i < QList<T>::count());
beginRemoveRows(QModelIndex(), i, i);
T t = QList<T>::takeAt(i);
endRemoveRows();
_q_resetCount();
return t;
}
template <typename T>
T BaseModel<T>::takeFirst()
{
BaseModel_ASSERT(QList<T>::count() > 0);
beginRemoveRows(QModelIndex(), 0, 0);
T t = QList<T>::takeFirst();
endRemoveRows();
_q_resetCount();
return t;
}
template <typename T>
T BaseModel<T>::takeLast()
{
BaseModel_ASSERT(QList<T>::count() > 0);
int r = QList<T>::count() - 1;
beginRemoveRows(QModelIndex(), r, r);
T t = QList<T>::takeLast();
endRemoveRows();
_q_resetCount();
return t;
}
template <typename T>
void BaseModel<T>::swap(int i, int j)
{
if (i == j) {
return;
}
BaseModel_ASSERT(i >= 0);
BaseModel_ASSERT(i < QList<T>::count());
BaseModel_ASSERT(j >= 0);
BaseModel_ASSERT(j < QList<T>::count());
QList<T>::swap(i, j);
QModelIndex ii = index(i, 0); emit dataChanged(ii, ii);
QModelIndex ji = index(j, 0); emit dataChanged(ji, ji);
}
template <typename T>
void BaseModel<T>::swap(QList<T> &l)
{
/*
if (l.d == this->d) {
return *this;
}
*/
beginResetModel();
QList<T>::swap(l);
endResetModel();
_q_resetCount();
}
template <typename T>
void BaseModel<T>::move(int from, int to)
{
if (from == to) {
return;
}
BaseModel_ASSERT(from >= 0);
BaseModel_ASSERT(from < QList<T>::count());
BaseModel_ASSERT(to >= 0);
BaseModel_ASSERT(to < QList<T>::count());
QModelIndex p;
int t = (from < to) ? (to + 1) : to;
if (beginMoveRows(p, from, from, p, t)) {
QList<T>::move(from, to);
endMoveRows();
}
}
template<typename T>
void BaseModel<T>::clear()
{
if (QList<T>::isEmpty()) {
return;
}
beginResetModel();
QList<T>::clear();
endResetModel();
_q_resetCount();
}
template<typename T>
void BaseModel<T>::deleteAll()
{
if (QList<T>::isEmpty()) {
return;
}
beginResetModel();
qDeleteAll(ref());
QList<T>::clear();
endResetModel();
_q_resetCount();
}
template<typename T>
BaseModel<T> &BaseModel<T>::operator=(const QList<T> &l)
{
/*
if (l.d == this->d) {
return *this;
}
*/
beginResetModel();
QList<T> tmp(l);
tmp.swap(*this);
endResetModel();
_q_resetCount();
return *this;
}
//template<typename T>
//BaseModel::Iterator BaseModel<T>::begin()
//{
//}
#endif // BASEMODEL_H

View File

@ -0,0 +1,27 @@
#ifndef BASEMODEL_P_H
#define BASEMODEL_P_H
#include <QMutex>
#include "basemodel.h"
namespace Internal {
class BaseModelPrivate
{
Q_DECLARE_PUBLIC(BaseModel)
public:
BaseModelPrivate();
virtual ~BaseModelPrivate();
protected:
BaseModel *q_ptr;
protected:
bool countEnabled;
int count;
};
} // namespace Internal
#endif // BASEMODEL_P_H

View File

@ -0,0 +1,88 @@
#include "categoryitem.h"
class CategoryItemPrivate {
public:
int category;
QString name;
QString icon;
QString normalIcon;
QString clickIcon;
int pageCount;
};
CategoryItem::CategoryItem(QObject *parent)
: QObject(parent)
, p(new CategoryItemPrivate)
{
}
CategoryItem::~CategoryItem()
{
delete p;
}
int CategoryItem::category() const
{
return p->category;
}
void CategoryItem::setCategory(const int &category)
{
if (p->category != category) {
p->category = category;
Q_EMIT categoryChanged();
}
}
QString CategoryItem::name() const
{
return p->name;
}
void CategoryItem::setName(const QString &name)
{
if (p->name != name) {
p->name = name;
Q_EMIT nameChanged();
}
}
QString CategoryItem::normalIcon() const
{
return p->normalIcon;
}
void CategoryItem::setNormalIcon(const QString &icon)
{
if (p->normalIcon != icon) {
p->normalIcon = icon;
Q_EMIT normalIconChanged();
}
}
QString CategoryItem::clickIcon() const
{
return p->clickIcon;
}
void CategoryItem::setClickIcon(const QString &icon)
{
if (p->clickIcon != icon) {
p->clickIcon = icon;
Q_EMIT clickIconChanged();
}
}
int CategoryItem::pageCount() const
{
return p->pageCount;
}
void CategoryItem::setPageCount(const int &pageCount)
{
if (p->pageCount != pageCount) {
p->pageCount = pageCount;
Q_EMIT pageCountChanged();
}
}

View File

@ -0,0 +1,69 @@
#ifndef CATEGORYITEM_H
#define CATEGORYITEM_H
#include <QObject>
#include <QtQml>
class CategoryItemPrivate;
class CategoryItem : public QObject
{
Q_OBJECT
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
QML_ELEMENT
#endif
Q_PROPERTY(int category READ category WRITE setCategory NOTIFY categoryChanged)
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QString normalIcon READ normalIcon WRITE setNormalIcon NOTIFY normalIconChanged)
Q_PROPERTY(QString clickIcon READ clickIcon WRITE setClickIcon NOTIFY clickIconChanged)
Q_PROPERTY(int pageCount READ pageCount WRITE setPageCount NOTIFY pageCountChanged)
public:
enum Category {
All,
Android,
Network,
Messaging,
Audio,
Development,
Graphics,
Game,
Office,
Education,
System,
Other
};
Q_ENUMS(Category)
Q_ENUM(Category)
explicit CategoryItem(QObject *parent = nullptr);
~CategoryItem();
int category() const;
void setCategory(const int &category);
QString name() const;
void setName(const QString &name);
QString normalIcon() const;
void setNormalIcon(const QString &icon);
QString clickIcon() const;
void setClickIcon(const QString &icon);
int pageCount() const;
void setPageCount(const int &pageCount);
Q_SIGNALS:
void categoryChanged();
void nameChanged();
void iconChanged();
void normalIconChanged();
void clickIconChanged();
void pageCountChanged();
private:
CategoryItemPrivate *p;
};
#endif // CATEGORYITEM_H

View File

@ -0,0 +1,229 @@
#include "launcheritem.h"
struct LauncherItemPrivate {
QString name;
int id;
int type;
int index;
int pageIndex = -1;
QString icon;
QString desktopFile;
int location;
int rowSpan;
int columnSpan;
int state = LauncherItem::Normal;
bool editable = false;
bool selected = false;
bool appOpen = false;
int windowId = -1;
};
LauncherItem::LauncherItem(QObject *parent)
: QObject(parent)
, p(new LauncherItemPrivate())
{
}
LauncherItem::LauncherItem(const LauncherItem &other)
{
this->setName(other.name());
this->setId(other.id());
this->setType(other.type());
this->setPageIndex(other.pageIndex());
this->setIcon(other.icon());
this->setDesktopFile(other.desktopFile());
this->setLocation(other.location());
this->setRowSpan(other.rowSpan());
this->setColumnSpan(other.columnSpan());
this->setState(other.state());
this->setEditable(other.editable());
this->setSelected(other.selected());
this->setAppOpen(other.appOpen());
this->setWindowId(other.windowId());
}
LauncherItem::~LauncherItem()
{
delete p;
}
QString LauncherItem::name() const
{
return p->name;
}
void LauncherItem::setName(const QString &name)
{
if (p->name != name) {
p->name = name;
Q_EMIT nameChanged();
}
}
int LauncherItem::id() const
{
return p->id;
}
void LauncherItem::setId(const int &id)
{
if (p->id != id) {
p->id = id;
Q_EMIT idChanged();
}
}
int LauncherItem::type() const
{
return p->type;
}
void LauncherItem::setType(const int &type)
{
if (p->type != type) {
p->type = type;
Q_EMIT typeChanged();
}
}
int LauncherItem::pageIndex() const
{
return p->pageIndex;
}
void LauncherItem::setPageIndex(const int &pageIndex)
{
if (p->pageIndex != pageIndex) {
p->pageIndex = pageIndex;
Q_EMIT pageIndexChanged();
}
}
QString LauncherItem::icon() const
{
return p->icon;
}
void LauncherItem::setIcon(const QString &icon)
{
if (p->icon != icon) {
p->icon = icon;
Q_EMIT iconChanged();
}
}
QString LauncherItem::desktopFile() const
{
return p->desktopFile;
}
void LauncherItem::setDesktopFile(const QString &desktopFile)
{
if (p->desktopFile != desktopFile) {
p->desktopFile = desktopFile;
Q_EMIT desktopFileChanged();
}
}
int LauncherItem::location() const
{
return p->location;
}
void LauncherItem::setLocation(const int &location)
{
if (p->location != location) {
p->location = location;
Q_EMIT locationChanged();
}
}
int LauncherItem::rowSpan() const
{
return p->rowSpan;
}
void LauncherItem::setRowSpan(const int &rowSpan)
{
if (p->rowSpan != rowSpan) {
p->rowSpan = rowSpan;
Q_EMIT rowSpanChanged();
}
}
int LauncherItem::columnSpan() const
{
return p->columnSpan;
}
void LauncherItem::setColumnSpan(const int &columnSpan)
{
if (p->columnSpan != columnSpan) {
p->columnSpan = columnSpan;
Q_EMIT columnSpanChanged();
}
}
int LauncherItem::state() const
{
return p->state;
}
void LauncherItem::setState(const int &state)
{
if (p->state != state) {
p->state = state;
Q_EMIT stateChanged();
}
}
bool LauncherItem::editable() const
{
return p->editable;
}
void LauncherItem::setEditable(const bool &editable)
{
if (p->editable != editable) {
p->editable = editable;
Q_EMIT editableChanged();
}
}
bool LauncherItem::selected() const
{
return (p->selected && p->state == LauncherItem::Selectable);
}
void LauncherItem::setSelected(bool selected)
{
if (p->selected != selected && p->state == LauncherItem::Selectable) {
p->selected = selected;
Q_EMIT selectedChanged();
}
}
bool LauncherItem::appOpen() const
{
return p->appOpen;
}
void LauncherItem::setAppOpen(const bool &appOpen)
{
if (p->appOpen != appOpen) {
p->appOpen = appOpen;
Q_EMIT appOpenChanged();
}
}
int LauncherItem::windowId() const
{
return p->windowId;
}
void LauncherItem::setWindowId(const int &windowId)
{
if (p->windowId != windowId) {
p->windowId = windowId;
Q_EMIT windowIdChanged();
}
}

View File

@ -0,0 +1,133 @@
#ifndef LAUNCHERITEM_H
#define LAUNCHERITEM_H
#include <QObject>
#include <QtQml>
struct LauncherItemPrivate;
class LauncherItem : public QObject
{
Q_OBJECT
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
QML_ELEMENT
#endif
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged)
Q_PROPERTY(int type READ type WRITE setType NOTIFY typeChanged)
Q_PROPERTY(int pageIndex READ pageIndex WRITE setPageIndex NOTIFY pageIndexChanged)
Q_PROPERTY(QString icon READ icon WRITE setIcon NOTIFY iconChanged)
Q_PROPERTY(QString desktopFile READ desktopFile WRITE setDesktopFile NOTIFY desktopFileChanged)
Q_PROPERTY(int location READ location WRITE setLocation NOTIFY locationChanged)
Q_PROPERTY(int rowSpan READ rowSpan WRITE setRowSpan NOTIFY rowSpanChanged)
Q_PROPERTY(int columnSpan READ columnSpan WRITE setColumnSpan NOTIFY columnSpanChanged)
Q_PROPERTY(int state READ state WRITE setState NOTIFY stateChanged)
Q_PROPERTY(bool editable READ editable WRITE setEditable NOTIFY editableChanged)
Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectedChanged)
Q_PROPERTY(bool appOpen READ appOpen WRITE setAppOpen NOTIFY appOpenChanged)
Q_PROPERTY(int windowId READ windowId WRITE setWindowId NOTIFY windowIdChanged)
public:
enum ItemType {
AppIcon,
Group,
Container,
Widget,
Placeholder,
AddIcon,
};
enum ItemState {
Normal,
Editable,
Selectable,
};
Q_ENUMS(ItemType)
Q_ENUMS(ItemState)
explicit LauncherItem(QObject *parent = nullptr);
LauncherItem(const LauncherItem &other);
~LauncherItem();
LauncherItem &operator= (const LauncherItem &other) {
this->setName(other.name());
this->setId(other.id());
this->setType(other.type());
this->setPageIndex(other.pageIndex());
this->setIcon(other.icon());
this->setDesktopFile(other.desktopFile());
this->setLocation(other.location());
this->setRowSpan(other.rowSpan());
this->setColumnSpan(other.columnSpan());
this->setState(other.state());
this->setEditable(other.editable());
this->setSelected(other.selected());
this->setAppOpen(other.appOpen());
this->setWindowId(other.windowId());
return *this;
}
QString name() const;
void setName(const QString &name);
int id() const;
void setId(const int &id);
int type() const;
void setType(const int &type);
int pageIndex() const;
void setPageIndex(const int &pageIndex);
QString icon() const;
void setIcon(const QString &icon);
QString desktopFile() const;
void setDesktopFile(const QString &desktopFile);
int location() const;
void setLocation(const int &location);
int rowSpan() const;
void setRowSpan(const int &rowSpan);
int columnSpan() const;
void setColumnSpan(const int &columnSpan);
int state() const;
void setState(const int &state);
bool editable() const;
void setEditable(const bool &editable);
bool selected() const;
void setSelected(bool selected);
bool appOpen() const;
void setAppOpen(const bool &appOpen);
int windowId() const;
void setWindowId(const int &windowId);
Q_SIGNALS:
void nameChanged();
void idChanged();
void typeChanged();
void indexChanged();
void pageIndexChanged();
void iconChanged();
void desktopFileChanged();
void locationChanged();
void rowSpanChanged();
void columnSpanChanged();
void stateChanged();
void editableChanged();
void selectedChanged();
void appOpenChanged();
void windowIdChanged();
private:
LauncherItemPrivate *p;
};
#endif // LAUNCHERITEM_H

View File

@ -0,0 +1,36 @@
#include <QDBusConnection>
#include <QProcess>
#include <QDebug>
#include "sidebarstate.h"
SidebarState::SidebarState(QObject *parent) : QObject(parent)
{
//sidebar
QDBusConnection::sessionBus().connect(QString("org.ukui.Sidebar"),
QString("/org/ukui/Sidebar"),
QString("org.ukui.Sidebar"),
QString("sidebarStateChange"), this, SLOT(setSidebarState(QString)));
}
bool SidebarState::sidebarState()
{
return sidebarValue;
}
void SidebarState::setSidebarShow()
{
if (!sidebarValue) {
QProcess::startDetached("ukui-sidebar -state");
}
}
void SidebarState::setSidebarState(QString state)
{
if (state == "show") {
sidebarValue = true;
}
if (state == "hide") {
sidebarValue = false;
}
}

View File

@ -0,0 +1,30 @@
#ifndef SIDEBARSTATE_H
#define SIDEBARSTATE_H
#include <QObject>
#include <QtQml>
class SidebarState : public QObject
{
Q_OBJECT
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
QML_ELEMENT
#endif
Q_PROPERTY(bool sidebarState READ sidebarState)
public:
explicit SidebarState(QObject *parent = nullptr);
Q_INVOKABLE void setSidebarShow();
bool sidebarState();
bool sidebarValue = false;
signals:
public slots:
void setSidebarState(QString state);
};
#endif // SIDEBARSTATE_H

View File

@ -0,0 +1,452 @@
#include "trayicon.h"
#include <QDBusInterface>
#include <QDBusReply>
TrayIcon::TrayIcon(QObject *parent)
: m_type(0)
{
//sound
if (QGSettings::isSchemaInstalled("org.ukui.quick-operation.panel"))
{
sound = new QGSettings("org.ukui.quick-operation.panel");
connect(sound, &QGSettings::changed, this, &TrayIcon::getSoundValue);
}
//wifi
getWifiValue();
QDBusConnection::systemBus().connect(QString("org.freedesktop.NetworkManager"),
QString("/org/freedesktop/NetworkManager"),
QString("org.freedesktop.NetworkManager"),
QString("PropertiesChanged"), this, SLOT(getWifiValue()));
//message
QDBusConnection::sessionBus().connect(QString("org.ukui.Sidebar"),
QString("/org/ukui/Sidebar/notification"),
QString("org.ukui.Sidebar.notification"),
QString("Sig_NotificationNumChange"), this, SLOT(getMessageValue()));
//power
initPowerDbusaddrest();
initPowerValue();
QDBusConnection::systemBus().connect(QString("org.freedesktop.UPower"), powerpath,
"org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(initPowerValue()));
//bluetooth
if (QGSettings::isSchemaInstalled("org.ukui.bluetooth"))
{
bluetoothSetting = new QGSettings("org.ukui.bluetooth");
connect(bluetoothSetting, &QGSettings::changed, this, &TrayIcon::getBluetoothSwitch);
}
//time
if (QGSettings::isSchemaInstalled("org.ukui.control-center.panel.plugins"))
{
timeSetting = new QGSettings("org.ukui.control-center.panel.plugins");
connect(timeSetting, &QGSettings::changed, this, &TrayIcon::getTimeDateState);
}
getTimeDateState();
}
QIcon TrayIcon::icon()
{
return m_icon;
}
QString TrayIcon::source()
{
return m_source;
}
void TrayIcon::setSource(const QString &source)
{
m_icon = QIcon::fromTheme(source, QIcon(source));
m_source = source;
emit sourceChanged();
update();
}
int TrayIcon::type()
{
return m_type;
}
void TrayIcon::setType(const int &type)
{
m_type = type;
switch (m_type) {
case Sound:
getSoundValue();
break;
case Power: {
initPowerValue();
break;
}
case Message: {
getMessageValue();
break;
}
case Wifi: {
getWifiValue();
break;
}
case Bluetooth: {
getBluetoothSwitch();
break;
}
default:
break;
}
update();
emit typeChanged();
}
void TrayIcon::paint(QPainter *painter)
{
m_icon.paint(painter, boundingRect().toRect());
}
QString TrayIcon::timeformat()
{
return m_timeformat;
}
void TrayIcon::settimeformat(const QString &timeformat)
{
if (m_timeformat != timeformat) {
m_timeformat = timeformat;
emit timeformatChanged();
}
}
QString TrayIcon::dateformat()
{
return m_dateformat;
}
void TrayIcon::setdateformat(const QString &dateformat)
{
if (m_dateformat != dateformat) {
m_dateformat = dateformat;
emit dateformatChanged();
}
}
void TrayIcon::getSoundValue()
{
if (QGSettings::isSchemaInstalled("org.ukui.quick-operation.panel"))
{
int soundValue = 0;
if (sound->keys().contains("soundstate")) {
bool soundState = sound->get("soundstate").toBool();
if (soundState)
{
soundValue = 0;
}
else
{
soundValue = sound->get("volumesize").toInt();
}
setVolumeIcon(soundValue);
}
else
{
if (sound->keys().contains("volumesize")) {
soundValue = sound->get("volumesize").toInt();
setVolumeIcon(soundValue);
}
}
}
}
void TrayIcon::initPowerDbusaddrest()
{
QStringList users;
QDBusInterface m_interface1("org.freedesktop.UPower",
"/org/freedesktop/UPower",
"org.freedesktop.UPower",
QDBusConnection::systemBus() );
if (!m_interface1.isValid()) {
qDebug() << "dbus接口初始化失败";
return;
}
QDBusReply<QList<QDBusObjectPath>> obj_reply = m_interface1.call("EnumerateDevices");
if (obj_reply.isValid()) {
for (QDBusObjectPath op : obj_reply.value()){
users << op.path();
}
if (users.size() == 1 || users.size() == 0){
return;
}
powerpath = users.at(1);
}
}
void TrayIcon::getMessageValue()
{
QDBusInterface interfaceMess("org.ukui.Sidebar",
"/org/ukui/Sidebar/notification",
"org.ukui.Sidebar.notification",
QDBusConnection::sessionBus());
QDBusReply<int> result = interfaceMess.call("getNotificationNum");
if (result == 0) {
setMessageIcon(false);
} else {
setMessageIcon(true);
}
qDebug() << "message count" <<result;
}
void TrayIcon::initPowerValue()
{
QDBusInterface m_interface( "org.freedesktop.UPower",
powerpath,
"org.freedesktop.DBus.Properties",
QDBusConnection::systemBus() );
if (!m_interface.isValid()) {
qDebug() << "dbus接口初始化失败";
}
QDBusReply<QVariant> obj_reply = m_interface.call("Get","org.freedesktop.UPower.Device","Percentage");
QDBusReply<QVariant> obj_state = m_interface.call("Get","org.freedesktop.UPower.Device","State");
if (obj_reply.isValid() && obj_state.isValid()) {
if (obj_state.value().toUInt() == 2 || obj_state.value().toUInt() == 3)
{
setPowerIcon(obj_reply.value().toInt());
}
else {
setPowerChargeIcon(obj_reply.value().toInt());
}
}
emit powerValueChanged();
}
void TrayIcon::getBluetoothSwitch()
{
QProcess p;
p.start("hciconfig");
p.waitForFinished(3000);
QString bluetoothInfo = p.readAll();
if (bluetoothInfo.isEmpty()) {
setBluetoothIcon(false);
return;
}
if (QGSettings::isSchemaInstalled("org.ukui.bluetooth")) {
if (bluetoothSetting->keys().contains("switch")) {
bool bluetoothSwitch = bluetoothSetting->get("switch").toBool();
setBluetoothIcon(bluetoothSwitch);
}
} else {
setBluetoothIcon(false);
}
}
void TrayIcon::getTimeDateState()
{
if (QGSettings::isSchemaInstalled("org.ukui.control-center.panel.plugins"))
{
if (timeSetting->keys().contains("hoursystem"))
{
QString timeState = timeSetting->get("hoursystem").toString();
settimeformat(timeState);
}
if (timeSetting->keys().contains("hoursystem"))
{
QString dateState = timeSetting->get("date").toString();
setdateformat(dateState);
}
}
}
void TrayIcon::getWifiValue()
{
netconnectType = 0;
QDBusInterface interface( "org.freedesktop.NetworkManager",
"/org/freedesktop/NetworkManager",
"org.freedesktop.DBus.Properties",
QDBusConnection::systemBus());
//获取已经连接了那些网络,及这些网络对应的网络类型(ethernet or wifi)
QDBusMessage result = interface.call("Get", "org.freedesktop.NetworkManager", "ActiveConnections");
QList<QVariant> outArgs = result.arguments();
QVariant first = outArgs.at(0);
QDBusVariant dbvFirst = first.value<QDBusVariant>();
QVariant vFirst = dbvFirst.variant();
QDBusArgument dbusArgs = vFirst.value<QDBusArgument>();
QDBusArgument dbusArgshelp = vFirst.value<QDBusArgument>();
QDBusObjectPath objPath;
dbusArgs.beginArray();
while (!dbusArgs.atEnd()) {
dbusArgs >> objPath;
QDBusInterface interfacePath( "org.freedesktop.NetworkManager",
objPath.path(),
"org.freedesktop.DBus.Properties",
QDBusConnection::systemBus() );
QDBusReply<QVariant> replyConnectType = interfacePath.call("Get", "org.freedesktop.NetworkManager.Connection.Active", "Type");
QDBusReply<QVariant> replyConnectivity = interface.call("Get", "org.freedesktop.NetworkManager", "Connectivity");
int connectivityState = replyConnectivity.value().toInt();
// qDebug() << "connect type" <<replyConnectType.value().toString();
if (replyConnectType.value().toString() == "802-3-ethernet") {
netconnectType = 1;
if (connectivityState == 4) {
setNetIcon(-1, true); //有网
return;
} else {
setNetIcon(-2, true); //无网
}
}
if (replyConnectType.value().toString() == "802-11-wireless") {
netconnectType = 2;
QDBusReply<QVariant> replyConnectivity = interface.call("Get", "org.freedesktop.NetworkManager", "Connectivity");
if (connectivityState == 4) {
QDBusMessage resultSpecificObject = interfacePath.call("Get", "org.freedesktop.NetworkManager.Connection.Active", "SpecificObject");
QList<QVariant> outArgsSpecificObject = resultSpecificObject.arguments();
QVariant firstSpecificObject = outArgsSpecificObject.at(0);
QDBusVariant dbvFirstSpecificObject = firstSpecificObject.value<QDBusVariant>();
QVariant vFirstSpecificObject = dbvFirstSpecificObject.variant();
QDBusObjectPath objPathSpecificObject = vFirstSpecificObject.value<QDBusObjectPath>();
QDBusInterface interfaceAP( "org.freedesktop.NetworkManager",
objPathSpecificObject.path(),
"org.freedesktop.DBus.Properties",
QDBusConnection::systemBus() );
QDBusReply<QVariant> replyStrength = interfaceAP.call("Get", "org.freedesktop.NetworkManager.AccessPoint", "Strength"); //signal
QByteArray sesultStrength = replyStrength.value().toByteArray();
int wifiSignal = sesultStrength[0] & 0x000000FF;
wifiSignal |= ((sesultStrength[1] << 8) & 0x0000FF00);
wifiSignal |= ((sesultStrength[2] << 16) & 0x00FF0000);
wifiSignal |= ((sesultStrength[3] << 24) & 0xFF000000);
setNetIcon(wifiSignal, true);
} else {
setNetIcon(-2, true);
}
}
}
if (netconnectType == 0) {
setNetIcon(-1, false);
}
emit wifiStateChanged();
}
void TrayIcon::setVolumeIcon(int value)
{
if (type() == 0) {
if (value <= 0) {
setSource("audio-volume-muted-symbolic");
} else if (value > 0 && value <= 33) {
setSource("audio-volume-low-symbolic");
} else if (value > 33 && value <= 66) {
setSource("audio-volume-medium-symbolic");
} else {
setSource("audio-volume-high-symbolic");
}
}
}
void TrayIcon::setPowerIcon(int value)
{
if (type() == 1) {
if (value == 100) {
setSource("battery-full-symbolic");
} else {
int val;
setSource("battery-level-50-symbolic");
for(int i = 0; i <= 100; i += 10) {
if (value <= i) {
val = i;
break;
}
}
QString valueString = QString("battery-level-%1-symbolic").arg(val);
setSource(valueString);
}
}
}
void TrayIcon::setPowerChargeIcon(int value)
{
if (type() == 1) {
if (value == 0) {
setSource("battery-empty-charging-symbolic");
} else if (value == 100) {
setSource("battery-level-100-charging-symbolic");
} else {
int val;
for(int i = 10; i <= 100; i += 10) {
if (value <= i) {
val = i;
break;
}
}
QString valueString = QString("battery-level-%1-charging-symbolic").arg(val);
setSource(valueString);
}
}
}
void TrayIcon::setMessageIcon(bool value)
{
if(type() == 2) {
if (value) {
setSource("kylin-tool-box-null");
} else {
setSource("kylin-tool-box");
}
}
}
void TrayIcon::setNetIcon(int value, bool state)
{
if (type() == 3) {
if (state) {
if (netconnectType == 1) {
// qDebug() << "wire" <<"value:" <<value<<"state:" <<state;
if (value == -1) {
setSource("network-wired-symbolic");
} else {
setSource("network-error-symbolic");
}
}
if (netconnectType == 2) {
if (value < 0) {
// qDebug() << "wifi no net" <<"value:" <<value<<"state:" <<state;
setSource("network-wired-symbolic");
} else {
//无线网络状态改变
// qDebug() << "wifi" <<"value:" <<value<<"state:" <<state;
if (value >= 75) {
setSource("network-wireless-signal-excellent-symbolic");
} else if (value >= 55 && value < 75) {
setSource("network-wireless-signal-good-symbolic");
} else if (value >= 35 && value < 55) {
setSource("network-wireless-signal-ok-symbolic");
} else if(value >= 15 && value < 35) {
setSource("network-wireless-signal-weak-symbolic");
} else {
setSource("network-wired-disconnected-symbolic");//network-cellular-signal-none-symbolic
}
}
}
} else {
// qDebug() << "no net" <<"value:" <<value<<"state:";
setSource("network-wired-disconnected-symbolic");
}
}
}
void TrayIcon::setBluetoothIcon(bool state)
{
if (type() == 4) {
if (state) {
setSource("ukui-bluetooth-on-symbolic");
} else {
setSource("ukui-bluetooth-off-symbolic");
}
}
}

View File

@ -0,0 +1,99 @@
#ifndef TRAYICON_H
#define TRAYICON_H
#include <QQuickItem>
#include <QQuickPaintedItem>
#include <QIcon>
#include <QPainter>
#include <QGSettings/QGSettings>
#include <QGSettings>
#include <QProcess>
#include <QtQml>
class TrayIcon : public QQuickPaintedItem
{
Q_OBJECT
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
QML_ELEMENT
#endif
Q_PROPERTY(QIcon icon READ icon)
Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(int type READ type WRITE setType NOTIFY typeChanged)
Q_PROPERTY(QString timeformat READ timeformat WRITE settimeformat NOTIFY timeformatChanged)
Q_PROPERTY(QString dateformat READ dateformat WRITE setdateformat NOTIFY dateformatChanged)
public:
enum IconType {
Sound,
Power,
Message,
Wifi,
Bluetooth,
};
Q_ENUMS(IconType)
TrayIcon(QObject *parent = nullptr);
QIcon icon();
QString source();
void setSource(const QString &source);
int type();
void setType(const int &type);
void paint(QPainter *painter);
QString timeformat();
void settimeformat(const QString &timeformat);
QString dateformat();
void setdateformat(const QString &dateformat);
void getSoundValue();
Q_INVOKABLE void initPowerDbusaddrest();
void getBluetoothSwitch();
void getTimeDateState();
void setVolumeIcon(int value);
void setPowerIcon(int value);
void setPowerChargeIcon(int value);
void setMessageIcon(bool value);
void setNetIcon(int value, bool state);
void setBluetoothIcon(bool state);
private:
QIcon m_icon;
QString m_source;
int m_type;
QString m_timeformat;
QString m_dateformat;
QGSettings *sound;
QGSettings *messageSetting;
QGSettings *bluetoothSetting;
QGSettings *timeSetting;
QString powerpath;
int netconnectType = 0; //wire = 1, wifi = 2
bool messageState;
signals:
void sourceChanged();
void typeChanged();
void timeformatChanged();
void dateformatChanged();
void soundValueChanged();
void wifiStateChanged();
void messageStateChanged();
void powerValueChanged();
void powerChargeValueChanged(int powerValue);
public slots:
void initPowerValue();
void getWifiValue();
void getMessageValue();
};
#endif // TRAYICON_H

View File

@ -0,0 +1,123 @@
#include "appmanager.h"
#include <QDBusError>
AppManager::AppManager(QObject *parent)
: QObject(parent)
, m_appManagerInterface(new AppManagerInterface("com.kylin.AppManager", "/com/kylin/AppManager", QDBusConnection::sessionBus()))
{
if (!m_appManagerInterface->isValid()) {
qWarning() << "Connect to com.kylin.AppManager dbus service failed!" << m_appManagerInterface->lastError();
}
m_userName = getUserName();
}
void AppManager::runApplication(const QString &desktopFile)
{
qDebug()<<"---dcf---"<<desktopFile;
bool ret = m_appManagerInterface->LaunchApp(desktopFile);;
if (!ret) {
qWarning() << "Run Application failed!" << desktopFile;
}
}
QList<quint32> AppManager::runningApplications()
{
QList<quint32> runningAppWids;
return runningAppWids;
}
void AppManager::removeApplication(const QString &desktopFile)
{
Q_UNUSED(desktopFile);
// 区分apt安装或者apk安装方式分别调用各自的卸载接口
qDebug() <<__FUNCTION__<< desktopFile;
QSettings desktop(desktopFile, QSettings::IniFormat);
QString desktopCmd = desktop.value("Desktop Entry/Exec").toString();
// kmre应用卸载
if (desktopCmd.contains("/usr/bin/startapp")) {
qDebug() << " ---kmre应用卸载---分支";
if (!QDBusConnection::sessionBus().isConnected()) {
qDebug()<<"Cannot connect to the cn.kylinos.Kmre.Manager D-Bus sessionBus.";
return;
}
//调用系统cn.kylinos.Kmre.Manager服务
QDBusInterface apkRemoveFace("cn.kylinos.Kmre.Manager",
"/cn/kylinos/Kmre/Manager",
"cn.kylinos.Kmre.Manager",
QDBusConnection::sessionBus());
if (apkRemoveFace.isValid()) {
qDebug()<<"---apkRemoveFace---";
QStringList strList = desktopCmd.split(" ");
apkRemoveFace.asyncCall("uninstallApp", strList.at(1));
} else {
qDebug()<<"apkRemoveFace 无法调用到PurgePackages方法";
}
} else {
qDebug() << " ---apt应用卸载---分支";
if (!QDBusConnection::systemBus().isConnected()) {
qDebug()<<"Cannot connect to the com.kylin.systemupgrade D-Bus systemBus.";
return;
}
//调用系统com.kylin.systemupgrade服务
QDBusInterface aptRemoveFace("com.kylin.systemupgrade",
"/com/kylin/systemupgrade",
"com.kylin.systemupgrade.interface",
QDBusConnection::systemBus());
if (aptRemoveFace.isValid()) {
qDebug()<<"---aptRemoveFace---"<<desktopFile;
QString pkgName = getPkgNameByDesktop(desktopFile);
qDebug()<<"---pkgName---"<<pkgName;
QStringList purgeList;
purgeList.append(pkgName);
qDebug()<<"---m_userName---"<<m_userName;
aptRemoveFace.asyncCall("PurgePackages", purgeList, m_userName);
} else {
qDebug()<<"aptRemoveFace 无法调用到PurgePackages方法";
}
}
}
void AppManager::runApplicationConfig(const QString &desktopFile, const QStringList &Config)
{
bool retConfig = m_appManagerInterface->LaunchAppWithArguments(desktopFile, Config);
qDebug()<<"===retConfig"<<retConfig;
if (!retConfig) {
qWarning() << "Run ApplicationConfig failed!" << desktopFile;
}
}
QString AppManager::AppDesktopFileNameByPid(qlonglong pid)
{
return m_appManagerInterface->AppDesktopFileNameByPid(pid);
}
QString AppManager::getUserName()
{
QString userName = qgetenv("USER");
qDebug() <<"1---userName---"<< userName;
if (userName.isEmpty()){
userName = qgetenv("USERNAME");
qDebug() <<"2---userName---"<< userName;
}
return userName;
}
QString AppManager::getPkgNameByDesktop(const QString &desktopFile)
{
qDebug()<<"---getPkgNameByDesktop---"<<desktopFile;
std::string packName = "dpkg -S " + desktopFile.toStdString();
char nameBuff[100] = "";
FILE* fp = popen(packName.c_str(),"r");
fgets(nameBuff, 100, fp);
pclose(fp);
std::string pkgInfo = nameBuff;
if(pkgInfo.empty()){
qDebug()<<"---pkgInfo.isEmpty()---";
}
std::string pkg = std::string(pkgInfo.begin(),pkgInfo.begin() + pkgInfo.find(':'));
qDebug()<<"---pkg---"<<pkg.c_str();
// m_pkgName = QString::fromStdString(pkg);
QString pkgName = QString::fromStdString(pkg);
return pkgName;
}

View File

@ -0,0 +1,27 @@
#ifndef APPMANAGER_H
#define APPMANAGER_H
#include <QObject>
#include "dbusinterfaces/appmanagerinterface.h"
#include <QGSettings>
class AppManager : public QObject
{
Q_OBJECT
public:
explicit AppManager(QObject *parent = nullptr);
Q_INVOKABLE void runApplication(const QString &desktopFile);
Q_INVOKABLE QList<quint32> runningApplications();
Q_INVOKABLE void removeApplication(const QString &desktopFile);
Q_INVOKABLE void runApplicationConfig(const QString &desktopFile, const QStringList &Config);
Q_INVOKABLE QString AppDesktopFileNameByPid(qlonglong pid);
private:
AppManagerInterface *m_appManagerInterface;
QString getUserName();
QString getPkgNameByDesktop(const QString &desktopFile);
QString m_userName;
};
#endif // APPMANAGER_H

View File

@ -0,0 +1,296 @@
#include "desktopdatahandler.h"
#include <QThread>
#include <QDebug>
DesktopDataHandler::DesktopDataHandler(QObject *parent)
: QObject(parent)
//, m_dataBackend(new UKUI::kylinTabletDesktopBackend(this))
{
qRegisterMetaType<QMap<quint32,QList<quint32> >>("QMap<quint32,QList<quint32> >");
qRegisterMetaType<QMap<quint32,QList<quint32> >>("QMap<quint32, QList<QList<quint32>>>");
qRegisterMetaType<QMap<quint32,UKUI::BaseItem*>>("QMap<quint32,UKUI::BaseItem*>");
qRegisterMetaType<QMap<UKUI::Categories, QList<quint32>>>("QMap<UKUI::Categories, QList<quint32>>");
qRegisterMetaType<QList<QList<quint32> >>("QList<QList<quint32> >");
}
DesktopDataHandler::~DesktopDataHandler()
{
m_dataBackend->deleteLater();
}
QString DesktopDataHandler::categoryName(int category) const
{
if (!m_categories.contains(static_cast<UKUI::Categories>(category))) {
return QString();
}
return m_categories.value(static_cast<UKUI::Categories>(category));
}
QList<quint32> DesktopDataHandler::apps() const
{
return m_apps;
}
QMap<quint32, UKUI::BaseItem *> DesktopDataHandler::items() const
{
return m_itemsData;
}
QMap<UKUI::Categories, QString> DesktopDataHandler::categories() const
{
return m_categories;
}
QMap<UKUI::Categories, QList<quint32>> DesktopDataHandler::categoriesItems() const
{
return m_categoriesItems;
}
void DesktopDataHandler::init()
{
m_dataBackend = new UKUI::kylinTabletDesktopBackend();
m_pageData = m_dataBackend->getAllPageData();
m_setData = m_dataBackend->getAllFlipSetsData();
// taskbar data
QList<QList<quint32>> taskBarData;
taskBarData.push_back(m_dataBackend->getAllScrollSetsData().value(0));
m_setData[0] = taskBarData;
m_itemsData = m_dataBackend->getAllItemData();
Q_EMIT desktopData(m_pageData, m_setData, m_itemsData);
m_apps = m_dataBackend->getAllAppIdList();
m_categories = m_dataBackend->getAllAppCategories();
m_categoriesItems.clear();
auto it = m_categories.constBegin();
while (it != m_categories.constEnd()) {
m_categoriesItems.insert(it.key(), m_dataBackend->getAppIdListAccordingCategory(it.key()));
++ it;
}
Q_EMIT categoriesData(m_categoriesItems);
connect(m_dataBackend, &UKUI::kylinTabletDesktopBackend::itemAdded,
this, &DesktopDataHandler::addItem);
connect(m_dataBackend, &UKUI::kylinTabletDesktopBackend::iconThemeChanged,
this, &DesktopDataHandler::iconThemeChanged);
connect(m_dataBackend, &UKUI::kylinTabletDesktopBackend::itemDeletedFromPage, [this](quint32 id, quint32 pageId) {
Q_UNUSED(pageId)
int groupId = groupIdOfItem(id);
if (groupId > 0) {
Q_EMIT appUninstalledFromGroup(id, groupId);
} else {
Q_EMIT appUninstalled(id);
}
/// \todo
/// 需要优化,仅更新改动的数据即可
updateDekstopData();
});
connect(m_dataBackend, &UKUI::kylinTabletDesktopBackend::itemDeletedFromSet, [this](quint32 id, quint32 setId) {
updateDekstopData();
Q_EMIT appUninstalledFromGroup(id, setId);
});
connect(m_dataBackend, &UKUI::kylinTabletDesktopBackend::pageDeleted, this, &DesktopDataHandler::removePage);
connect(m_dataBackend, &UKUI::kylinTabletDesktopBackend::taskBarAppChanged, this, &DesktopDataHandler::changeTaskBarApp);
}
#if 0
void DesktopDataHandler::moveItem(int from, int to, int page, int groupId)
{
if (groupId > 0) {
m_setData[groupId][page].move(from, to);
m_dataBackend->modifySetData(groupId, m_setData.value(groupId));
}
}
void DesktopDataHandler::removeItem(int index, int page, int groupId)
{
if (groupId > 0) {
m_setData[groupId][page].removeAt(index);
if (m_setData.value(groupId).at(page).isEmpty()) {
m_setData[groupId].removeAt(page);
}
m_dataBackend->modifySetData(groupId, m_setData.value(groupId));
}
}
void DesktopDataHandler::insertItem(int index, int page, int itemId, int groupId)
{
if (groupId > 0) {
// 将图标拖动至新建的页
if (m_setData[groupId].count() == page) {
m_setData[groupId].push_back(QList<quint32>());
}
m_setData[groupId][page].insert(index, itemId);
m_dataBackend->modifySetData(groupId, m_setData.value(groupId));
}
}
#endif
void DesktopDataHandler::setGroupName(const QString &name, int groupId)
{
Q_ASSERT(groupId > 0);
m_dataBackend->modifySetName(groupId, name);
}
void DesktopDataHandler::updateGroup(const QList<QList<quint32> > &ids, int groupId)
{
Q_ASSERT(groupId >= -1);
// main page group
if (groupId == -1) {
/// \note from 0 index
int pageIndex = 0;
for (auto &pageIds : ids) {
m_pageData[pageIndex] = pageIds;
m_dataBackend->modifyPageData(pageIndex, pageIds);
++ pageIndex;
}
//应用移动后出现的空白页,要调用后台接口删除
int removePageCount = m_pageData.count() - ids.count();
for (int i = 0; i < removePageCount; i++) {
qDebug() << "删除空白页--->" << m_pageData.count() - 1 << m_pageData.lastKey();
m_dataBackend->deleteLauncherPage(m_pageData.count() - 1);
m_pageData.remove(m_pageData.lastKey());
}
} else {
m_setData[groupId] = ids;
// task bar
if (groupId == 0) {
if (ids.isEmpty()) {
qDebug() << "task bar data udpate: " << ids;
m_dataBackend->modifyScrollSetData(0, QList<quint32>());
return;
}
qDebug() << "task bar data udpate: " << ids.first();
m_dataBackend->modifyScrollSetData(0, ids.first());
} else if (groupId > 0){
m_dataBackend->modifyFlipSetData(groupId, ids);
}
}
}
void DesktopDataHandler::updateDekstopData()
{
m_pageData = m_dataBackend->getAllPageData();
m_setData = m_dataBackend->getAllFlipSetsData();
m_itemsData = m_dataBackend->getAllItemData();
QList<QList<quint32>> taskBarData;
taskBarData.push_back(m_dataBackend->getAllScrollSetsData().value(0));
m_setData[0] = taskBarData;
m_apps = m_dataBackend->getAllAppIdList();
m_categories = m_dataBackend->getAllAppCategories();
m_categoriesItems.clear();
auto it = m_categories.constBegin();
while (it != m_categories.constEnd()) {
m_categoriesItems.insert(it.key(), m_dataBackend->getAppIdListAccordingCategory(it.key()));
++ it;
}
}
void DesktopDataHandler::addItem(quint32 itemId, int page)
{
bool newCategory = false;
int indexOfAllCategory = 0;
int indexOfCategory = 0;
int category = 0;
auto it = m_categories.constBegin();
while (it != m_categories.constEnd()) {
auto newCategoryItems = m_dataBackend->getAppIdListAccordingCategory(it.key());
if (m_categoriesItems.value(it.key()) != newCategoryItems) {
if (m_categoriesItems.value(it.key()).isEmpty()) {
newCategory = true;
} else {
indexOfCategory = newCategoryItems.indexOf(itemId);
}
category = 1 + static_cast<int>(it.key());
break;
}
++ it;
}
updateDekstopData();
indexOfAllCategory = m_apps.indexOf(itemId);
Q_EMIT appInstalled(itemId, indexOfAllCategory, indexOfCategory, page, newCategory, category);
}
void DesktopDataHandler::removeItem(quint32 itemId, int page)
{
Q_UNUSED(itemId)
Q_UNUSED(page)
#if 0
Q_ASSERT(m_pageData.contains(page) &&m_pageData.value(page).contains(itemId));
m_pageData[page].removeOne(itemId);
Q_EMIT itemRemoved(itemId, page);
#endif
updateDekstopData();
}
void DesktopDataHandler::iconThemeChanged()
{
m_itemsData = m_dataBackend->getAllItemData();
Q_EMIT iconChanged();
}
void DesktopDataHandler::removePage(int page)
{
// m_pageData.remove(page);
Q_EMIT pageRemoved(page, -1);
}
void DesktopDataHandler::changeTaskBarApp(appChangeInfo appChangeData)
{
qDebug() << "--->taskbarAppChangeData remove app itemid,changefromindex,toindex--->"
<< appChangeData.itemId << appChangeData.itemFromPage << appChangeData.itemFromPageIndex
<< appChangeData.itemToPage << appChangeData.itemToPageIndex;
//任务栏移除应用
if (appChangeData.isTaskbarDeleteApp && !appChangeData.isDesktopDeleteApp && !appChangeData.isExchangePosition) {
m_setData[0][0].removeAt(appChangeData.itemFromPageIndex);
m_pageData[appChangeData.itemToPage].push_back(appChangeData.itemId);
Q_EMIT taskbarDataChange(appChangeData);
}
//任务栏添加应用
if (!appChangeData.isTaskbarDeleteApp && appChangeData.isDesktopDeleteApp && !appChangeData.isExchangePosition) {
for (int i = 0; i < m_pageData[appChangeData.itemFromPage].count(); i++) {
if (m_pageData[appChangeData.itemFromPage].at(i) == appChangeData.itemId) {
m_pageData[appChangeData.itemFromPage].removeAt(i);
break;
}
}
m_setData[0][0].insert(appChangeData.itemToPageIndex, appChangeData.itemId);
Q_EMIT taskbarDataChange(appChangeData);
}
//任务栏交换应用
if (!appChangeData.isTaskbarDeleteApp && !appChangeData.isDesktopDeleteApp && appChangeData.isExchangePosition) {
m_setData[0][0].move(appChangeData.itemFromPageIndex, appChangeData.itemToPageIndex);
Q_EMIT taskbarDataChange(appChangeData);
}
}
int DesktopDataHandler::groupIdOfItem(int itemId)
{
auto it = m_setData.constBegin();
while(it != m_setData.constEnd()) {
for (const auto &page : it.value()) {
if (page.contains(itemId)) {
return it.key();
}
}
++ it;
}
return -1;
}

View File

@ -0,0 +1,87 @@
#ifndef DESKTOPDATAHANDLER_H
#define DESKTOPDATAHANDLER_H
#include <QObject>
#include "modelmanager.h"
#include "kylin-tablet-desktop-backend.h"
#include "types.h"
struct App
{
};
class DesktopDataHandler : public QObject
{
Q_OBJECT
public:
explicit DesktopDataHandler(QObject *parent = nullptr);
~DesktopDataHandler();
QString categoryName(int category) const;
QList<quint32> apps() const;
QMap<quint32, UKUI::BaseItem *> items() const;
QMap<UKUI::Categories, QString> categories() const;
QMap<UKUI::Categories, QList<quint32>> categoriesItems() const;
public Q_SLOTS:
void init();
#if 0
void moveItem(int from, int to, int page, int groupId);
void removeItem(int index, int page, int groupId);
void insertItem(int index, int page, int itemId, int groupId);
#endif
void setGroupName(const QString &name,int groupId);
void updateGroup(const QList<QList<quint32> > &ids, int groupId);
private Q_SLOTS:
void updateDekstopData();
void addItem(quint32 itemId, int page);
void removeItem(quint32 itemId, int page);
void iconThemeChanged();
void removePage(int page);
void changeTaskBarApp(appChangeInfo appChangeData);
Q_SIGNALS:
void finished();
void desktopData(const QMap<quint32, QList<quint32>> &pageData,
const QMap<quint32, QList<QList<quint32>>> &setData,
const QMap<quint32, UKUI::BaseItem *> &itemData);
void categoriesData(QMap<UKUI::Categories, QList<quint32>> categoriesItems);
void itemAdded(int itemId, QList<int> categories);
void appUninstalledFromGroup(int itemId, int group);
void appUninstalled(int itemId);
///
/// \brief appInstalled 有新的应用安装完成之后发出该信号
/// \param itemId 新应用的id
/// \param indexOfAllCategory 新应用在‘全部’分类中的索引
/// \param indexOfCategory 新应用在本身所在分类中的索引
/// \param page 如果是非大屏项目的话,该参数不能为-1
/// \param newCategory 是否是新的分类
/// \param category 新分类
///
void appInstalled(int itemId,
int indexOfAllCategory,
int indexOfCategory,
int page = -1,
bool newCategory = false,
int category = CategoryItem::All);
void iconChanged();
void pageRemoved(int page, int groupId);
void taskbarDataChange(appChangeInfo appChangeData);
private:
int groupIdOfItem(int itemId);
private:
UKUI::kylinTabletDesktopBackend *m_dataBackend;
QMap<quint32, QList<quint32>> m_pageData;
QMap<quint32, QList<QList<quint32>>> m_setData;
QMap<quint32, UKUI::BaseItem *> m_itemsData;
QMap<UKUI::Categories, QString> m_categories;
QMap<UKUI::Categories, QList<quint32>> m_categoriesItems;
QList<quint32> m_apps;
};
#endif // DESKTOPDATAHANDLER_H

View File

@ -0,0 +1,70 @@
#include "kylintabletdekstopplugin.h"
#include <QtQml/qqml.h>
#include <QQmlContext>
#include <QDebug>
#include "modelmanager.h"
#include "appmanager.h"
#include "utils/getscreenshot.h"
//#include "KylinItemView/kquickgridview.h"
#include "base/launcheritem.h"
#include "base/categoryitem.h"
#include "core/modelmanager.h"
#include "core/appmanager.h"
#include "core/pluginitem.h"
#include "logger.h"
#include "utils/getscreenshot.h"
#include "utils/desktopbackground.h"
#include "ukui-log4qt.h"
#include "utils/generalsetting.h"
#include "utils/wirelessstatus.h"
#include "utils/wiredlinkstate.h"
#include "utils/accountlogout.h"
#include "utils/blurhelper.h"
#include "utils/gettaskbarvalue.h"
#include "base/trayicon.h"
#include "base/sidebarstate.h"
#include "utils/taskbarmask.h"
void KylinTabletDekstopPlugin::registerTypes(const char *uri)
{
Q_UNUSED(uri)
#if QT_VERSION <= QT_VERSION_CHECK(5,12,8)
qmlRegisterType<LauncherItem>("com.kylin.tablet", 1, 0, "LauncherItem");
qmlRegisterType<CategoryItem>("com.kylin.tablet", 1, 0, "CategoryItem");
qmlRegisterType<GetScreenShot>("com.kylin.tablet", 1, 0, "ScreenShot");
qmlRegisterType<DesktopBackground>("com.kylin.tablet", 1, 0, "Background");
// qmlRegisterType<KQuickGridView>("com.kylin.tablet", 1, 0, "KGridView");
qmlRegisterType<LauncherItem>("com.kylin.tablet", 1, 0, "LauncherItem");
qmlRegisterType<CGeneralSetting>("MyGeneralSetting", 1, 0, "CGeneralSetting");
qmlRegisterType<WirelessStatus>("com.kylin.tablet", 1, 0, "WirelessStatus");
qmlRegisterType<WiredLinkState>("com.kylin.tablet", 1, 0, "WiredLinkState");
qmlRegisterType<AccountLogout>("com.kylin.tablet", 1, 0, "AccountLogout");
qmlRegisterType<BlurHelper>("com.kylin.tablet", 1, 0, "BlurHelper");
qmlRegisterType<PluginItem>("com.kylin.tablet", 1, 0, "PluginItem");
qmlRegisterType<TrayIcon>("com.kylin.tablet", 1, 0, "TrayIcon");
qmlRegisterType<TaskbarMask>("com.kylin.tablet", 1, 0, "TaskbarMask");
#endif
}
void KylinTabletDekstopPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
{
Q_UNUSED(uri)
ModelManager *modelManager = new ModelManager(this);
engine->rootContext()->setContextProperty("modelManager", modelManager);
AppManager *appMgr = new AppManager(this);
engine->rootContext()->setContextProperty("appManager", appMgr);
#if 0
GetTaskbarValue *taskbarValue = new GetTaskbarValue;
taskbarValue->taskbarModelManager = modelManager;
engine->rootContext()->setContextProperty("getTaskbarValue", taskbarValue);
#endif
TrayIcon *trayIcon = new TrayIcon();
engine->rootContext()->setContextProperty("trayIcon", trayIcon);
SidebarState *sidebarState = new SidebarState();
engine->rootContext()->setContextProperty("sidebarState", sidebarState);
}

View File

@ -0,0 +1,16 @@
#ifndef KYLINTABLETDEKSTOPPLUGIN_H
#define KYLINTABLETDEKSTOPPLUGIN_H
#include <QQmlExtensionPlugin>
class KylinTabletDekstopPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri) override;
void initializeEngine(QQmlEngine *engine, const char *uri) override;
};
#endif // KYLINTABLETDEKSTOPPLUGIN_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,295 @@
#ifndef MODELMANAGER_H
#define MODELMANAGER_H
#include <QObject>
#include "base/basemodel.h"
#include "base/categoryitem.h"
#include "dbusinterfaces/appmanagerinterface.h"
#include "types.h"
#include "kylin-tablet-desktop-backend.h"
#include "windowmanager/windowmanager.h"
using namespace kdk;
class LauncherItem;
class ModelManagerPrivate;
typedef BaseModel<LauncherItem *> PageModel;
typedef BaseModel<PageModel *> MultiPageModel;
typedef BaseModel<CategoryItem *> CategoryModel;
class ModelManager : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(ModelManager)
Q_DECLARE_PRIVATE(ModelManager)
Q_PROPERTY(QAbstractListModel * launcherModel READ launcherModel NOTIFY launcherModelChanged)
Q_PROPERTY(QAbstractListModel * categoryModel READ categoryModel NOTIFY categoryModelChanged)
Q_PROPERTY(QAbstractListModel * categoryItemsModel READ categoryItemsModel NOTIFY categoryItemsModelChanged)
Q_PROPERTY(QAbstractListModel * taskbarModel READ taskbarModel NOTIFY taskbarModelChanged)
public:
explicit ModelManager(QObject *parent = nullptr);
~ModelManager();
enum ItemParentType {
Page,
Group,
Container,
};
///
/// \brief launcherModel 获取整个桌面的整体model
/// \return
///
Q_INVOKABLE QAbstractListModel* launcherModel() const;
///
/// \brief groupModel 获取每个分组或者Container的model
/// \param id 分组或者Container的id
/// \return
///
Q_INVOKABLE QAbstractListModel* groupModel(const quint32 &id) const;
///
/// \brief categoryModel 返回应用分类的model
/// \return
///
Q_INVOKABLE QAbstractListModel* categoryModel() const;
///
/// \brief categoryItemsModel 返回所有的分类的对应的item的model
/// \return
///
Q_INVOKABLE QAbstractListModel* categoryItemsModel() const;
///
/// \brief groupPageItemCount 获取分组或者Container指定页的item的数量
/// \param groupId 分组或者Container的id
/// \param pageIndex 分组或者Container的页
/// \return
///
Q_INVOKABLE int groupPageItemCount(int groupId, int pageIndex);
///
/// \brief launcerPageItemCount 返回当前页的item的数量
/// \param pageIndex
/// \return
///
Q_INVOKABLE int launcerPageItemCount(int pageIndex) const;
///
/// \brief moveItem 移动 item,\note 只适用于同一页面中的 item 移动.
/// 跨页拖动时, 数据对于 GridView 来说是不同的 model, 因此并不适合 move.
/// \param from 开始移动的 item 的 index
/// \param to 要移动到的位置的 item 的 index
/// \param page 当前移动的 item 所在的页的 index
/// \param groupId 默认为 -1, 即不是分组内的 item
/// \todo group->page的移动和page->group的移动
///
Q_INVOKABLE void moveItem(int from, int to, int page, int groupId = -1);
///
/// \brief addPlaceholderItem 添加占位 item, 跨页拖动 item 时(未释放),
/// 首先在目标 page 添加一个占位 item 来指示将要添加到的位置
/// \param index 占位 item 所在页的 item index
/// \param pageIndex 占位 item 所在的 page index
/// \param rowSpan 占位 item 所跨的行数
/// \param columnSpan 占位 item 所跨的列数
/// \param groupId 当前所在的分组 id
///
Q_INVOKABLE void addPlaceholderItem(int index,
int pageIndex,
int rowSpan = 1,
int columnSpan = 1,
int groupId = -1);
///
/// \brief removePlaceholderItem 删除占位 item, 比如从第 0 页拖动 item 至第 1 页,
/// 此时调用 \memberof addPlaceholderItem, 未释放 item 接着返回第 0 页, 则调用该函数删除占位 item
///
Q_INVOKABLE void removePlaceholderItem();
///
/// \brief replacePlaceholderItem 替换占位 item, 当移动 item 至相应位置释放该 item 时, 调用该函数,
/// 将拖动的 item 的数据拷贝至占位 item
/// \param fromIndex 拖动的 item 的 index
/// \param fromPage 拖动的 item 所在的页
/// \param groupId 拖动的 item 所在的分组, 默认为 -1, 即不是分组内的 item
///
Q_INVOKABLE void replacePlaceholderItem(int fromIndex, int fromPage, int groupId = -1);
///
/// \brief replacePlaceholderItemTaskbar 替换占位 item(占位 item与拖动 item的groupId不同), 当移动 item 至相应位置释放该 item 时, 调用该函数,
/// 将拖动的 item 的数据拷贝至占位 item
/// \param fromIndex 拖动的 item 的 index
/// \param fromPage 拖动的 item 所在的页
/// \param fromgroupId 拖动的 item 所在的分组, 默认为 -1, 即不是分组内的 item
/// \param togroupId 占位 item 所在的分组, 默认为 -1
///
Q_INVOKABLE void replacePlaceholderItemTaskbar(int fromIndex, int fromPage, int fromgroupId = -1, int togroupId= -1);
///
/// \brief removeItem 删除 item, 比如卸载应用完成之后
/// \param index item 的 index
/// \param page item 所在页的 index
/// \param groupId 如果 item 不在 Group 中, 则为 -1
///
Q_INVOKABLE void removeItem(int index, int page, int groupId = -1);
///
/// \brief setItemState 设置item的状态, \see LauncherItem::ItemSate
/// \param state LauncherItem::ItemSate
/// \param groupId
///
Q_INVOKABLE void setItemState(int state, int groupId = -1);
///
/// \brief setGroupName 设置分组的名称
/// \param name 分组名称
/// \param groupId 分组id
///
Q_INVOKABLE void setGroupName(const QString &name, int groupId);
///
/// \brief setAddAppCategory 设置添加应用界面的数据
/// \param category 默认打卡的分类
/// \param groupId 添加应用的分组
///
Q_INVOKABLE void setAddAppCategory(int category, int groupId);
///
/// \brief updateCachedData 每次操作完成之后,需要前端主动调用该函数进行缓存数据更新至数据库
/// \param groupId 当前操作的分组id
///
Q_INVOKABLE void updateCachedData(int groupId = -1);
///
/// \brief groupEditable 分组是否可编辑,包括名称、删除和添加应用
/// \param groupId 分组的id
/// \return
///
Q_INVOKABLE bool groupEditable(int groupId);
///
/// \brief updateGroupItems 更新分组item的数据信息主要用于添加应用界面的数据操作
/// 每次点击“确认”按钮时需要调用该函数进行数据的更新
/// \param groupId 当前分组的id
/// \param pageIndex 打开添加应用界面时所在的page
///
Q_INVOKABLE void updateGroupItems(int groupId, int pageIndex);
Q_INVOKABLE void setItemSelectState(int itemId, int pageIndex, bool selected);
///获取任务栏model
Q_INVOKABLE QAbstractListModel* taskbarModel() ;//const;
///
/// \brief setAppOpenState 设置item为打开状态
/// \param desktopName item的desktopName
/// \param wid item的wid
///
void setAppOpenState(QString desktopName, int wid);
///
/// \brief setAppCloseState 设置item为关闭状态
/// \param desktopName item的desktopName
///
void setAppCloseState(QString desktopName);
///
/// \brief addWindowIconToTaskbar 打开一个桌面应用将桌面item图标加入任务栏
/// \param iconPath item的图标路径
/// \param desktopName item的desktopName
/// \param wid item的wid
///
void addWindowIconToTaskbar(QString iconPath, QString desktopName, int wid);
void removeWindowIconFromTaskbar(QString iconPath);
///
/// \brief removeAppIconFromTaskBar 关闭一个桌面应用将桌面item图标从任务栏移除
/// \param desktopFileName item的desktopFileName
///
void removeAppIconFromTaskBar(const QString &desktopFileName);
///
/// \brief findIconPath 根据desktopName查找item的图标路径
/// \param desktopName item的desktopName
///
QString findIconPath(QString desktopName);
///
/// \brief findDesktopName 根据desktopName从桌面查找完整的desktop路径
/// \param desktopName item的desktopName
///
QString findDesktopName(QString desktopName);
///
/// \brief findDesktopNameFromTaskbar 根据desktopName从任务栏查找完整的desktop路径
/// \param desktopName item的desktopName
///
QString findDesktopNameFromTaskbar(QString desktopName);
///
/// \brief activeWindow 激活窗口
/// \param wid item的wid
///
Q_INVOKABLE void activeWindow(quint32 wid);
///
/// \brief changeAppWindowWid 修改item保存的wid
/// \param desktopName item被移除的wid
/// \param newWid item保存的wid
///
void changeAppWindowWid(QString desktopName, int wid, int newWid);
void setPageModel(const MultiPageModel &pageModel);
void setGroupModel(const QMap<int, MultiPageModel *> &groupModel);
Q_SIGNALS:
void launcherModelChanged();
void categoryModelChanged();
void categoryItemsModelChanged();
void categoryRemoved(int category);
void categoryAdded(int category);
void categoryPageAdded(int category);
void categoryPageRemoved(int category);
void taskbarModelChanged();
#if 0
void itemMoved(int from, int to, int page, int groupId);
void itemRemoved(int index, int page, int groupId);
void itemInserted(int index, int page, int itemId, int groupId);
#endif
void groupNameChanged(const QString &title, int groupId);
void updateGroup(const QList<QList<quint32> > &ids, int groupId);
private Q_SLOTS:
void desktopData(const QMap<quint32, QList<quint32>> &pageData,
const QMap<quint32, QList<QList<quint32>>> &setData,
const QMap<quint32, UKUI::BaseItem *> &itemData);
void categories(const QMap<UKUI::Categories, QList<quint32>> categories);
void removeItemFromGroup(int itemId, int groupId);
void removeItemWithoutGroup(int itemId);
void itemInstalled(int itemId,
int indexOfAllCategory,
int indexOfCategory,
int page = -1,
bool newCategory = false,
int category = CategoryItem::All);
void iconThemeChanged();
void pageRemoved(int page, int groupId);
void changeTaskbarData(appChangeInfo appChangeData);
private:
ModelManagerPrivate *d_ptr;
AppManagerInterface *appManagerInterface;
};
#endif // MODELMANAGER_H

View File

@ -0,0 +1,145 @@
#include "pluginitem.h"
#include <QWindow>
#include <QSGNinePatchNode>
#include <QQuickWindow>
#include <QDebug>
#include <QPushButton>
#include <QTimer>
#include <QBitmap>
#include "qwidgetpluginmanager.h"
PluginItem::PluginItem(QQuickItem *parent)
: QQuickItem(parent),
m_widgetVisible(true),
m_index(0)
{
setFlag(QQuickItem::ItemHasContents, true);
setAcceptedMouseButtons(Qt::AllButtons);
connect(this, &PluginItem::xChanged, [this] {
auto pos = parentItem()->mapToItem(m_mapItem, QPointF(x(), y()));
m_widgetImage = QImage();
polish();
pluginMgr.movePlugin(m_pluginName, pos.x(), pos.y());
pluginMgr.showPlugin(m_pluginName);
});
}
PluginItem::~PluginItem()
{
}
bool PluginItem::widgetVisible() const
{
return m_widgetVisible;
}
QQuickItem *PluginItem::mapItem() const
{
return m_mapItem;
}
QQuickWindow *PluginItem::rootWindow() const
{
return m_rootWindow;
}
int PluginItem::index() const
{
return m_index;
}
QString PluginItem::pluginName() const
{
return m_pluginName;
}
void PluginItem::setWidgetVisible(bool widgetVisible)
{
if (!pluginMgr.containsPlugin(m_pluginName)) {
return;
}
if (m_widgetVisible != widgetVisible) {
m_widgetVisible = widgetVisible;
if (widgetVisible) {
auto pos = parentItem()->mapToItem(m_mapItem, QPointF(x(), y()));
polish();
pluginMgr.movePlugin(m_pluginName, pos.x(), pos.y());
pluginMgr.showPlugin(m_pluginName);
} else {
polish();
pluginMgr.hidePlugin(m_pluginName);
}
Q_EMIT widgetVisibleChanged();
}
}
void PluginItem::setMapItem(QQuickItem *item)
{
if (m_mapItem != item) {
m_mapItem = item;
Q_EMIT mapItemChanged();
}
}
void PluginItem::setIndex(int index)
{
if (m_index != index) {
m_index = index;
Q_EMIT indexChanged();
}
}
void PluginItem::setPluginName(const QString &pluginName)
{
if (m_pluginName != pluginName) {
m_pluginName = pluginName;
Q_EMIT pluginNameChanged();
}
}
void PluginItem::setRootWindow(QQuickWindow *rootWindow)
{
m_rootWindow = rootWindow;
pluginMgr.createPlugin(m_pluginName, this->width(), this->height());
pluginMgr.plugin(m_pluginName)->setFixedSize(this->width(), this->height());
pluginMgr.setPluginRootWindow(m_pluginName, rootWindow);
if (m_widgetVisible && m_mapItem) {
auto pos = parentItem()->mapToItem(m_mapItem, QPointF(x(), y()));
polish();
pluginMgr.movePlugin(m_pluginName, pos.x(), pos.y());
pluginMgr.showPlugin(m_pluginName);
}
}
void PluginItem::updatePolish()
{
if (!pluginMgr.containsPlugin(m_pluginName)) {
return;
}
QPixmap pixmap = pluginMgr.plugin(m_pluginName)->plugin()->grab();
m_widgetImage = pixmap.toImage();
QQuickItem::update();
}
QSGNode *PluginItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
{
if (m_widgetImage.isNull()) {
delete node;
return nullptr;
}
QSGNinePatchNode *styleNode = static_cast<QSGNinePatchNode *>(node);
if (!styleNode) {
styleNode = window()->createNinePatchNode();
}
styleNode->setTexture(window()->createTextureFromImage(m_widgetImage, QQuickWindow::TextureHasAlphaChannel));
styleNode->setBounds(boundingRect());
styleNode->setDevicePixelRatio(window()->devicePixelRatio());
styleNode->update();
return styleNode;
}

View File

@ -0,0 +1,61 @@
#ifndef PLUGINITEM_H
#define PLUGINITEM_H
#include <QQuickItem>
#include <QImage>
#include <QtQml>
#include "singleton.h"
#include "qwidgetpluginmanager.h"
class QmlWidget;
class PluginItem : public QQuickItem
{
Q_OBJECT
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
QML_ELEMENT
#endif
Q_PROPERTY(bool widgetVisible READ widgetVisible WRITE setWidgetVisible NOTIFY widgetVisibleChanged)
Q_PROPERTY(QQuickItem* mapItem READ mapItem WRITE setMapItem NOTIFY mapItemChanged)
Q_PROPERTY(int mIndex READ index WRITE setIndex NOTIFY indexChanged)
Q_PROPERTY(QString pluginName READ pluginName WRITE setPluginName NOTIFY pluginNameChanged)
Q_PROPERTY(QQuickWindow* rootWindow READ rootWindow WRITE setRootWindow NOTIFY rootWindowChanged)
public:
PluginItem(QQuickItem *parent = nullptr);
~PluginItem();
bool widgetVisible() const;
QQuickItem* mapItem() const;
QQuickWindow* rootWindow() const;
int index() const;
QString pluginName() const;
void setWidgetVisible(bool widgetVisible);
void setMapItem(QQuickItem *item);
void setIndex(int index);
void setPluginName(const QString &pluginName);
void setRootWindow(QQuickWindow* rootWindow);
protected:
virtual void updatePolish() override;
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) override;
Q_SIGNALS:
void widgetVisibleChanged();
void mapItemChanged();
void indexChanged();
void pluginNameChanged();
void rootWindowChanged();
private:
bool m_widgetVisible;
QImage m_widgetImage;
QQuickItem *m_mapItem = nullptr;
QQuickWindow *m_rootWindow = nullptr;
int m_index;
QString m_pluginName;
QWidgetPluginManager &pluginMgr = common::Singleton<QWidgetPluginManager>::GetInstance();
};
#endif // PLUGINITEM_H

View File

@ -0,0 +1,130 @@
#include "qwidgetpluginmanager.h"
#include <QQuickWindow>
#include <QPluginLoader>
#include <QPushButton>
#include <QWidget>
#include <QPainter>
#include <QGuiApplication>
#include <QScreen>
#include <QDebug>
#include <QGSettings>
QWidgetPluginContainer::QWidgetPluginContainer(QWidget *parent)
: QWidget(parent)
{
if (QGSettings::isSchemaInstalled("org.mate.background")) {
m_backgroundGSettings = new QGSettings("org.mate.background");
setBackground(m_backgroundGSettings->get("pictureFilename").toString());
connect(m_backgroundGSettings, &QGSettings::changed, [this](const QString &key) {
if (key == "pictureFilename") {
setBackground(m_backgroundGSettings->get("pictureFilename").toString());
}
});
}
setWindowFlag(Qt::FramelessWindowHint);
}
void QWidgetPluginContainer::setPlugin(QWidget *plugin)
{
m_plugin = plugin;
if (!m_plugin) {
return;
}
m_plugin->setWindowFlag(Qt::FramelessWindowHint);
m_plugin->setAttribute(Qt::WA_TranslucentBackground);
m_plugin->setParent(this);
}
QWidget *QWidgetPluginContainer::plugin() const
{
return m_plugin;
}
void QWidgetPluginContainer::updateBackgroundPosition()
{
m_containerBackgroundImg = m_desktopBackgroundImg.copy(this->geometry());
update();
}
void QWidgetPluginContainer::paintEvent(QPaintEvent *event)
{
QPainter p(this);
m_containerBackgroundImg = m_desktopBackgroundImg.copy(this->geometry());
p.drawImage(this->rect(), m_containerBackgroundImg);
return QWidget::paintEvent(event);
}
void QWidgetPluginContainer::setBackground(const QString &background)
{
auto rect = QGuiApplication::primaryScreen()->geometry();
m_desktopBackgroundImg = QImage(background).scaled(rect.width(), rect.height());
m_containerBackgroundImg = m_desktopBackgroundImg.copy(this->geometry());
update();
}
QWidgetPluginManager::QWidgetPluginManager(QObject *parent)
: QObject{parent}
{
}
void QWidgetPluginManager::createPlugin(const QString &pluginName, int width, int height)
{
if (m_plugins.contains(pluginName)) {
return;
}
QPluginLoader loader("/opt/small-plugin/bin/libsmall-plugin-manage.so");
QObject * plugin=loader.instance();
if (plugin) {
KySmallPluginInterface * app = qobject_cast<KySmallPluginInterface *>(plugin);
QWidget *widget = app->createWidget(nullptr);
widget->setFixedSize(width, height);
QWidgetPluginContainer *pluginContainer = new QWidgetPluginContainer();
pluginContainer->setFixedSize(width, height);
pluginContainer->setPlugin(widget);
m_plugins.insert(pluginName, pluginContainer);
}
}
void QWidgetPluginManager::setPluginRootWindow(const QString &pluginName, QQuickWindow *rootWindow)
{
m_rootWindow = rootWindow;
m_plugins.value(pluginName)->winId();
m_plugins.value(pluginName)->windowHandle()->setParent(rootWindow);
}
void QWidgetPluginManager::movePlugin(const QString &pluginName, int x, int y)
{
m_plugins.value(pluginName)->move(x, y);
}
void QWidgetPluginManager::showPlugin(const QString &pluginName)
{
m_plugins.value(pluginName)->show();
}
void QWidgetPluginManager::hidePlugin(const QString &pluginName)
{
if (!m_plugins.contains(pluginName)) {
return;
}
m_plugins.value(pluginName)->hide();
}
bool QWidgetPluginManager::containsPlugin(const QString &pluginName)
{
return m_plugins.contains(pluginName);
}
QWidgetPluginContainer *QWidgetPluginManager::plugin(const QString &pluginName)
{
if (m_plugins.contains(pluginName)) {
return m_plugins.value(pluginName);
} else {
return nullptr;
}
}

View File

@ -0,0 +1,80 @@
#ifndef QWIDGETPLUGINMANAGER_H
#define QWIDGETPLUGINMANAGER_H
#include <QObject>
#include <QMap>
#include <QtPlugin>
#include <functional>
#include <QString>
#include <QObject>
#include <QWidget>
class QWidget;
class KySmallPluginInterface
{
public:
virtual ~KySmallPluginInterface() {}
virtual const QString name() const= 0;
virtual const QString nameCN() const= 0;
virtual const QString description() const= 0;
virtual int sortNum() const= 0;
virtual QWidget *createWidget(QWidget *parent)=0;
};
QT_BEGIN_NAMESPACE
/*
* Q_DECLARE_INTERFACE Qt
* Q_DECLARE_INTERFACE(, )
* 使
*/
#define SP_PLUGIN_IID "org.Kylin.SmallPlugin.widgetInterface/1.0"
Q_DECLARE_INTERFACE (KySmallPluginInterface, SP_PLUGIN_IID)
QT_END_NAMESPACE
class QGSettings;
class QWidgetPluginContainer : public QWidget
{
Q_OBJECT
public:
QWidgetPluginContainer(QWidget *parent = nullptr);
void setPlugin(QWidget *plugin);
QWidget *plugin() const;
void updateBackgroundPosition();
protected:
virtual void paintEvent(QPaintEvent *event);
private:
void setBackground(const QString &background);
private:
QGSettings* m_backgroundGSettings;
QString m_background;
QImage m_desktopBackgroundImg;
QImage m_containerBackgroundImg;
QWidget *m_plugin;
};
class QQuickWindow;
class QWidgetPluginManager : public QObject
{
Q_OBJECT
public:
explicit QWidgetPluginManager(QObject *parent = nullptr);
void createPlugin(const QString &pluginName, int width, int height);
void setPluginRootWindow(const QString &pluginName, QQuickWindow *rootWindow);
void movePlugin(const QString &pluginName, int x, int y);
void showPlugin(const QString &pluginName);
void hidePlugin(const QString &pluginName);
bool containsPlugin(const QString &pluginName);
QWidgetPluginContainer *plugin(const QString &pluginName);
private:
QMap<QString, QWidgetPluginContainer *> m_plugins;
QQuickWindow *m_rootWindow;
};
#endif // QWIDGETPLUGINMANAGER_H

View File

@ -0,0 +1,26 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp com.kylin.AppManager.xml -p appmanagerinterface -c AppManagerInterface
*
* qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "appmanagerinterface.h"
/*
* Implementation of interface class AppManagerInterface
*/
AppManagerInterface::AppManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
{
}
AppManagerInterface::~AppManagerInterface()
{
}

View File

@ -0,0 +1,96 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp com.kylin.AppManager.xml -p appmanagerinterface -c AppManagerInterface
*
* qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef APPMANAGERINTERFACE_H
#define APPMANAGERINTERFACE_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
/*
* Proxy class for interface com.kylin.AppManager
*/
class AppManagerInterface: public QDBusAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "com.kylin.AppManager"; }
public:
AppManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~AppManagerInterface();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<bool> AddToWhiteList(const QString &desktopFile, const QString &option)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(desktopFile) << QVariant::fromValue(option);
return asyncCallWithArgumentList(QStringLiteral("AddToWhiteList"), argumentList);
}
inline QDBusPendingReply<QString> AppDesktopFileNameByPid(qlonglong pid)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(pid);
return asyncCallWithArgumentList(QStringLiteral("AppDesktopFileNameByPid"), argumentList);
}
inline QDBusPendingReply<bool> LaunchApp(const QString &desktopFile)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(desktopFile);
return asyncCallWithArgumentList(QStringLiteral("LaunchApp"), argumentList);
}
inline QDBusPendingReply<bool> LaunchAppWithArguments(const QString &desktopFile, const QStringList &args)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(desktopFile) << QVariant::fromValue(args);
return asyncCallWithArgumentList(QStringLiteral("LaunchAppWithArguments"), argumentList);
}
inline QDBusPendingReply<bool> RemoveFromWhiteList(const QString &desktopFile, const QString &option)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(desktopFile) << QVariant::fromValue(option);
return asyncCallWithArgumentList(QStringLiteral("RemoveFromWhiteList"), argumentList);
}
inline QDBusPendingReply<> SetPowerSavingModeEnable(bool enable)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(enable);
return asyncCallWithArgumentList(QStringLiteral("SetPowerSavingModeEnable"), argumentList);
}
inline QDBusPendingReply<QStringList> WhiteListsOfApp(const QString &desktopFile)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(desktopFile);
return asyncCallWithArgumentList(QStringLiteral("WhiteListsOfApp"), argumentList);
}
Q_SIGNALS: // SIGNALS
};
namespace com {
namespace kylin {
typedef ::AppManagerInterface AppManager;
}
}
#endif

View File

@ -0,0 +1,38 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/com/kylin/AppManager">
<interface name="com.kylin.AppManager">
<method name="LaunchApp">
<arg name="desktopFile" type="s" direction="in"></arg>
<arg name="succeed" type="b" direction="out"></arg>
</method>
<method name="LaunchAppWithArguments">
<arg name="desktopFile" type="s" direction="in"></arg>
<arg name="args" type="as" direction="in"></arg>
<arg name="succeed" type="b" direction="out"></arg>
</method>
<method name="AppDesktopFileNameByPid">
<arg name="pid" type="x" direction="in"></arg>
<arg name="desktopFileName" type="s" direction="out"></arg>
</method>
<method name="SetPowerSavingModeEnable">
<arg name="enable" type="b" direction="in"></arg>
</method>
<method name="AddToWhiteList">
<arg name="desktopFile" type="s" direction="in"></arg>
<arg name="option" type="s" direction="in"></arg>
<arg name="succeed" type="b" direction="out"></arg>
</method>
<method name="RemoveFromWhiteList">
<arg name="desktopFile" type="s" direction="in"></arg>
<arg name="option" type="s" direction="in"></arg>
<arg name="succeed" type="b" direction="out"></arg>
</method>
<method name="WhiteListsOfApp">
<arg name="desktopFile" type="s" direction="in"></arg>
<arg name="whiteLists" type="as" direction="out"></arg>
</method>
</interface>
</node>

View File

@ -0,0 +1,91 @@
CONFIG(debug, debug|release) {
SOURCES += \
main.cpp
} else {
TEMPLATE = lib
TARGET = kylin-tablet-desktop-plugin
}
equals(QT_MAJOR_VERSION, 5) | equals(QT_MINOR_VERSION, 15) {
CONFIG += qmltypes
QML_IMPORT_NAME = com.kylin.tablet
QML_IMPORT_MAJOR_VERSION = 1
INCLUDEPATH += base core utils
}
QT += quick quickcontrols2
CONFIG += c++11 qt plugin
QMAKE_CXXFLAGS += -g
#include($$PWD/KylinItemView/KylinItemView.pri)
include($$PWD/src.pri)
#if (contains(QMAKE_HOST.arch, x86_64) || contains(QMAKE_HOST.arch, aarch64)) {
# include($$PWD/../qBreakpad/qBreakpad.pri)
#} else {
#}
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
qml.files = $$files(ui/qml/* )
qml.prefix =
RESOURCES += qml
images.files += $$files(ui/images/*.svg) \
$$files(ui/images/categories/*.svg) \
$$files(ui/images/*.png)
images.prefix =
RESOURCES += images
qmldir.files = ui/qml/qmldir
RESOURCES += qmldir
DISTFILES = qmldir \
ui/images/uninstall.svg \
ui/images/uninstallbtn.png
qmldir_plugin.files = qmldir
RESOURCES += qmldir_plugin
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
desktopFile.files = $$PWD/../data/kylin-tablet-desktop-general.desktop
desktopFile.path = /etc/xdg/autostart
pluginFile.files = $$PWD/../kylin-tablet-desktop/libkylin-tablet-desktop-plugin.so
#dirFile.files = $$PWD/../kylin-tablet-desktop/qmldir
#dirFile.path = $$[QT_INSTALL_QML]/com/kylin/tablet
qml.path = /usr/share/ukui/tablet/contents/ui
qmldir.path = /usr/share/ukui/tablet/contents/ui
target.path = /usr/bin
INSTALLS += \
target \
desktopFile \
qmldir \
qml
unix {
uri = com.kylin.tablet
installPath = $$[QT_INSTALL_QML]/$$replace(uri, \., /)
qmldir_plugin.path = $$installPath
target.path = $$installPath
INSTALLS += target qmldir_plugin qml
}
LIBS += -lukui-log4qt

View File

@ -0,0 +1,99 @@
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QtPlatformHeaders/QXcbWindowFunctions>
#include <QQuickView>
#if 0
#if defined (Q_PROCESSOR_X86_64) || defined (Q_PROCESSOR_ARM_64)
#include <QBreakpadHandler.h>
#endif
#endif
#include "base/launcheritem.h"
#include "base/categoryitem.h"
#include "core/modelmanager.h"
#include "core/appmanager.h"
#include "core/pluginitem.h"
#include "logger.h"
//#include "KylinItemView/kquickgridview.h"
#include "utils/getscreenshot.h"
#include "utils/desktopbackground.h"
#include "ukui-log4qt.h"
#include "utils/generalsetting.h"
#include "utils/wirelessstatus.h"
#include "utils/wiredlinkstate.h"
#include "utils/accountlogout.h"
#include "utils/blurhelper.h"
#include "utils/gettaskbarvalue.h"
#include "base/trayicon.h"
#include "utils/taskbarmask.h"
#include "base/sidebarstate.h"
#include <QQuickStyle>
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif
QApplication app(argc, argv);
#if 0
#if defined (Q_PROCESSOR_X86_64) || defined (Q_PROCESSOR_ARM_64)
QBreakpadInstance.setDumpPath(QLatin1String("/tmp/kylin-tablet-desktop-general"));
#endif
#endif
#ifndef QT_DEBUG
initUkuiLog4qt("kylin-tablet-desktop");
#endif
QQuickView qmlView;
QQuickStyle::setStyle("org.kylin.style");
// qml logger
// usage in qml:
// QmlLogger.debug(msg);QmlLogger.warning(msg); ...
common::QmlLogger qmlLogger;
qmlView.engine()->addImportPath("qrc:/ui/qml");
qmlView.engine()->rootContext()->setContextProperty("qmlLogger", &qmlLogger);
ModelManager modelMgr;
qmlView.engine()->rootContext()->setContextProperty("modelManager", &modelMgr);
AppManager appMgr;
qmlView.engine()->rootContext()->setContextProperty("appManager", &appMgr);
TrayIcon trayIcon;
qmlView.engine()->rootContext()->setContextProperty("trayIcon", &trayIcon);
SidebarState sidebarState;
qmlView.engine()->rootContext()->setContextProperty("sidebarState", &sidebarState);
// qml js:
// if (type == LauncherItem.AppIcon) {} ...
#if QT_VERSION <= QT_VERSION_CHECK(5,12,8)
qmlRegisterType<LauncherItem>("com.kylin.tablet", 1, 0, "LauncherItem");
qmlRegisterType<CategoryItem>("com.kylin.tablet", 1, 0, "CategoryItem");
qmlRegisterType<GetScreenShot>("com.kylin.tablet", 1, 0, "ScreenShot");
qmlRegisterType<DesktopBackground>("com.kylin.tablet", 1, 0, "Background");
// qmlRegisterType<KQuickGridView>("com.kylin.tablet", 1, 0, "KGridView");
qmlRegisterType<LauncherItem>("com.kylin.tablet", 1, 0, "LauncherItem");
qmlRegisterType<CGeneralSetting>("MyGeneralSetting", 1, 0, "CGeneralSetting");
qmlRegisterType<WirelessStatus>("com.kylin.tablet", 1, 0, "WirelessStatus");
qmlRegisterType<WiredLinkState>("com.kylin.tablet", 1, 0, "WiredLinkState");
qmlRegisterType<AccountLogout>("com.kylin.tablet", 1, 0, "AccountLogout");
qmlRegisterType<BlurHelper>("com.kylin.tablet", 1, 0, "BlurHelper");
qmlRegisterType<PluginItem>("com.kylin.tablet", 1, 0, "PluginItem");
qmlRegisterType<TrayIcon>("com.kylin.tablet", 1, 0, "TrayIcon");
qmlRegisterType<TaskbarMask>("com.kylin.tablet", 1, 0, "TaskbarMask");
#endif
qmlView.setSource(QUrl("qrc:/ui/qml/main.qml"));
QXcbWindowFunctions::setWmWindowType(&qmlView, QXcbWindowFunctions::Desktop);
qmlView.showFullScreen();
qmlView.resize(1920, 1080);
qmlView.rootObject()->setState("Show");
return app.exec();
}

View File

@ -0,0 +1,18 @@
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQml 2.12
Window {
id: root
width: 640
height: 480
visible: true
Loader {
id: load;
}
Component.onCompleted: {
load.source = "TabletDesktopWindow";
}
}

View File

@ -0,0 +1,2 @@
module com.kylin.tablet
plugin kylin-tablet-desktop-plugin

View File

@ -0,0 +1,70 @@
QT += quick gui KWindowSystem widgets core
QT += KWindowSystem KWaylandClient
CONFIG += c++11 link_pkgconfig
PKGCONFIG += kysdk-waylandhelper
equals(QT_MAJOR_VERSION, 5) | equals(QT_MINOR_VERSION, 15) {
CONFIG += qmltypes
QML_IMPORT_NAME = com.kylin.tablet
QML_IMPORT_MAJOR_VERSION = 1
INCLUDEPATH += base core utils
}
include($$PWD/../common/common.pri)
include($$PWD/../kylin-tablet-desktop-backend/baseHead.pri)
INCLUDEPATH += \
$$PWD
SOURCES += \
$$PWD/base/launcheritem.cpp \
$$PWD/base/basemodel.cpp \
$$PWD/base/categoryitem.cpp \
$$PWD/base/sidebarstate.cpp \
$$PWD/base/trayicon.cpp \
$$PWD/core/appmanager.cpp \
$$PWD/core/desktopdatahandler.cpp \
$$PWD/core/modelmanager.cpp \
$$PWD/core/pluginitem.cpp \
$$PWD/core/qwidgetpluginmanager.cpp \
$$PWD/utils/desktopbackground.cpp \
$$PWD/utils/getscreenshot.cpp \
$$PWD/utils/generalsetting.cpp \
$$PWD/utils/accountlogout.cpp \
$$PWD/utils/gettaskbarvalue.cpp \
$$PWD/utils/taskbarmask.cpp \
$$PWD/utils/wiredlinkstate.cpp \
$$PWD/utils/wirelessstatus.cpp \
$$PWD/utils/blurhelper.cpp \
$$PWD/dbusinterfaces/appmanagerinterface.cpp \
$$PWD/core/kylintabletdekstopplugin.cpp
HEADERS += \
$$PWD/base/basemodel.h \
$$PWD/base/basemodel_p.h \
$$PWD/base/categoryitem.h \
$$PWD/base/sidebarstate.h \
$$PWD/base/trayicon.h \
$$PWD/core/desktopdatahandler.h \
$$PWD/core/appmanager.h \
$$PWD/core/modelmanager.h \
$$PWD/core/pluginitem.h \
$$PWD/core/qwidgetpluginmanager.h \
$$PWD/base/launcheritem.h \
$$PWD/utils/desktopbackground.h \
$$PWD/utils/getscreenshot.h \
$$PWD/utils/generalsetting.h \
$$PWD/utils/accountlogout.h \
$$PWD/utils/gettaskbarvalue.h \
$$PWD/utils/taskbarmask.h \
$$PWD/utils/wiredlinkstate.h \
$$PWD/utils/wirelessstatus.h \
$$PWD/utils/blurhelper.h \
$$PWD/dbusinterfaces/appmanagerinterface.h \
$$PWD/core/kylintabletdekstopplugin.h
CONFIG += link_pkgconfig
PKGCONFIG += gsettings-qt

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui_all_click</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" opacity="0.8">
<g id="细节规范" transform="translate(-139.000000, -1660.000000)" fill-rule="nonzero">
<g id="编组-6备份-3" transform="translate(110.000000, 1645.000000)">
<g id="ukui_all_click" transform="translate(29.000000, 15.000000)">
<rect id="矩形" x="0" y="0" width="40" height="40"></rect>
<g id="图层_2" transform="translate(6.000000, 6.000000)" fill="#1F2022">
<path d="M26,22 L26,26 L22,26 L22,22 L26,22 M26,20 L22,20 C20.8,20 20,20.8 20,22 L20,26 C20,27.2 20.8,28 22,28 L26,28 C27.2,28 28,27.2 28,26 L28,22 C28,20.8 27.2,20 26,20 L26,20 Z" id="形状"></path>
<path d="M16,22 L16,26 L12,26 L12,22 L16,22 M16,20 L12,20 C10.8,20 10,20.8 10,22 L10,26 C10,27.2 10.8,28 12,28 L16,28 C17.2,28 18,27.2 18,26 L18,22 C18,20.8 17.2,20 16,20 L16,20 Z" id="形状"></path>
<path d="M6,22 L6,26 L2,26 L2,22 L6,22 M6,20 L2,20 C0.8,20 0,20.8 0,22 L0,26 C0,27.2 0.8,28 2,28 L6,28 C7.2,28 8,27.2 8,26 L8,22 C8,20.8 7.2,20 6,20 L6,20 Z" id="形状"></path>
<path d="M26,12 L26,16 L22,16 L22,12 L26,12 M26,10 L22,10 C20.8,10 20,10.8 20,12 L20,16 C20,17.2 20.8,18 22,18 L26,18 C27.2,18 28,17.2 28,16 L28,12 C28,10.8 27.2,10 26,10 L26,10 Z" id="形状"></path>
<path d="M16,12 L16,16 L12,16 L12,12 L16,12 M16,10 L12,10 C10.8,10 10,10.8 10,12 L10,16 C10,17.2 10.8,18 12,18 L16,18 C17.2,18 18,17.2 18,16 L18,12 C18,10.8 17.2,10 16,10 L16,10 Z" id="形状"></path>
<path d="M6,12 L6,16 L2,16 L2,12 L6,12 M6,10 L2,10 C0.8,10 0,10.8 0,12 L0,16 C0,17.2 0.8,18 2,18 L6,18 C7.2,18 8,17.2 8,16 L8,12 C8,10.8 7.2,10 6,10 L6,10 Z" id="形状"></path>
<path d="M26,2 L26,6 L22,6 L22,2 L26,2 M26,0 L22,0 C20.8,0 20,0.8 20,2 L20,6 C20,7.2 20.8,8 22,8 L26,8 C27.2,8 28,7.2 28,6 L28,2 C28,0.8 27.2,0 26,0 L26,0 Z" id="形状"></path>
<path d="M16,2 L16,6 L12,6 L12,2 L16,2 M16,0 L12,0 C10.8,0 10,0.8 10,2 L10,6 C10,7.2 10.8,8 12,8 L16,8 C17.2,8 18,7.2 18,6 L18,2 C18,0.8 17.2,0 16,0 L16,0 Z" id="形状"></path>
<path d="M6,2 L6,6 L2,6 L2,2 L6,2 M6,0 L2,0 C0.8,0 0,0.8 0,2 L0,6 C0,7.2 0.8,8 2,8 L6,8 C7.2,8 8,7.2 8,6 L8,2 C8,0.8 7.2,0 6,0 L6,0 Z" id="形状"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui_all_default</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-139.000000, -1541.000000)" fill-rule="nonzero">
<g id="编组-6" transform="translate(110.000000, 1492.000000)">
<g id="ukui_all_default" transform="translate(29.000000, 49.000000)">
<rect id="矩形" x="0" y="0" width="40" height="40"></rect>
<g id="input-dialpad-symbolic" transform="translate(6.000000, 6.000000)" fill="#FFFFFF" opacity="0.8">
<g id="图层_2">
<path d="M26,22 L26,26 L22,26 L22,22 L26,22 M26,20 L22,20 C20.8,20 20,20.8 20,22 L20,26 C20,27.2 20.8,28 22,28 L26,28 C27.2,28 28,27.2 28,26 L28,22 C28,20.8 27.2,20 26,20 L26,20 Z" id="形状"></path>
<path d="M16,22 L16,26 L12,26 L12,22 L16,22 M16,20 L12,20 C10.8,20 10,20.8 10,22 L10,26 C10,27.2 10.8,28 12,28 L16,28 C17.2,28 18,27.2 18,26 L18,22 C18,20.8 17.2,20 16,20 L16,20 Z" id="形状"></path>
<path d="M6,22 L6,26 L2,26 L2,22 L6,22 M6,20 L2,20 C0.8,20 0,20.8 0,22 L0,26 C0,27.2 0.8,28 2,28 L6,28 C7.2,28 8,27.2 8,26 L8,22 C8,20.8 7.2,20 6,20 L6,20 Z" id="形状"></path>
<path d="M26,12 L26,16 L22,16 L22,12 L26,12 M26,10 L22,10 C20.8,10 20,10.8 20,12 L20,16 C20,17.2 20.8,18 22,18 L26,18 C27.2,18 28,17.2 28,16 L28,12 C28,10.8 27.2,10 26,10 L26,10 Z" id="形状"></path>
<path d="M16,12 L16,16 L12,16 L12,12 L16,12 M16,10 L12,10 C10.8,10 10,10.8 10,12 L10,16 C10,17.2 10.8,18 12,18 L16,18 C17.2,18 18,17.2 18,16 L18,12 C18,10.8 17.2,10 16,10 L16,10 Z" id="形状"></path>
<path d="M6,12 L6,16 L2,16 L2,12 L6,12 M6,10 L2,10 C0.8,10 0,10.8 0,12 L0,16 C0,17.2 0.8,18 2,18 L6,18 C7.2,18 8,17.2 8,16 L8,12 C8,10.8 7.2,10 6,10 L6,10 Z" id="形状"></path>
<path d="M26,2 L26,6 L22,6 L22,2 L26,2 M26,0 L22,0 C20.8,0 20,0.8 20,2 L20,6 C20,7.2 20.8,8 22,8 L26,8 C27.2,8 28,7.2 28,6 L28,2 C28,0.8 27.2,0 26,0 L26,0 Z" id="形状"></path>
<path d="M16,2 L16,6 L12,6 L12,2 L16,2 M16,0 L12,0 C10.8,0 10,0.8 10,2 L10,6 C10,7.2 10.8,8 12,8 L16,8 C17.2,8 18,7.2 18,6 L18,2 C18,0.8 17.2,0 16,0 L16,0 Z" id="形状"></path>
<path d="M6,2 L6,6 L2,6 L2,2 L6,2 M6,0 L2,0 C0.8,0 0,0.8 0,2 L0,6 C0,7.2 0.8,8 2,8 L6,8 C7.2,8 8,7.2 8,6 L8,2 C8,0.8 7.2,0 6,0 L6,0 Z" id="形状"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui-apple-ipad-click</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-745.000000, -1834.000000)" fill-rule="nonzero">
<g id="其他" transform="translate(468.000000, 1820.000000)">
<g id="ukui-apple-ipad-click" transform="translate(277.000000, 14.000000)">
<rect id="矩形" x="0" y="0" width="40" height="40"></rect>
<g id="编组-11" transform="translate(7.000000, 4.000000)" fill="#4F4F4F">
<path d="M22,2 C23.2,2 24,2.8 24,4 L24,28 C24,29.2 23.2,30 22,30 L4,30 C2.8,30 2,29.2 2,28 L2,4 C2,2.8 2.8,2 4,2 L22,2 M22,0 L4,0 C1.8,0 0,1.8 0,4 L0,28 C0,30.2 1.8,32 4,32 L22,32 C24.2,32 26,30.2 26,28 L26,4 C26,1.8 24.2,0 22,0 L22,0 Z" id="形状"></path>
<path d="M20,5 C20.6,5 21,5.4 21,6 L21,22 C21,22.6 20.6,23 20,23 L6,23 C5.4,23 5,22.6 5,22 L5,6 C5,5.4 5.4,5 6,5 L20,5 M20,4 L6,4 C4.8,4 4,4.8 4,6 L4,22 C4,23.2 4.8,24 6,24 L20,24 C21.2,24 22,23.2 22,22 L22,6 C22,4.8 21.2,4 20,4 L20,4 Z" id="形状"></path>
<circle id="椭圆形" cx="13" cy="27" r="1"></circle>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui-apple-ipad-symbolic</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-625.000000, -1834.000000)" fill-rule="nonzero">
<g id="其他" transform="translate(468.000000, 1820.000000)">
<g id="ukui-apple-ipad-symbolic" transform="translate(157.000000, 14.000000)">
<rect id="矩形" x="0" y="0" width="40" height="40"></rect>
<g id="编组-10" transform="translate(6.000000, 4.000000)" fill="#FFFFFF" fill-opacity="0.75">
<path d="M22,2 C23.2,2 24,2.8 24,4 L24,28 C24,29.2 23.2,30 22,30 L4,30 C2.8,30 2,29.2 2,28 L2,4 C2,2.8 2.8,2 4,2 L22,2 M22,0 L4,0 C1.8,0 0,1.8 0,4 L0,28 C0,30.2 1.8,32 4,32 L22,32 C24.2,32 26,30.2 26,28 L26,4 C26,1.8 24.2,0 22,0 L22,0 Z" id="形状"></path>
<path d="M20,5 C20.6,5 21,5.4 21,6 L21,22 C21,22.6 20.6,23 20,23 L6,23 C5.4,23 5,22.6 5,22 L5,6 C5,5.4 5.4,5 6,5 L20,5 M20,4 L6,4 C4.8,4 4,4.8 4,6 L4,22 C4,23.2 4.8,24 6,24 L20,24 C21.2,24 22,23.2 22,22 L22,6 C22,4.8 21.2,4 20,4 L20,4 Z" id="形状"></path>
<circle id="椭圆形" cx="13" cy="27" r="1"></circle>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui_video_click</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-616.000000, -1660.000000)" fill-rule="nonzero">
<g id="编组-6备份-3" transform="translate(108.000000, 1645.000000)">
<g id="影音娱乐" transform="translate(480.000000, 1.000000)">
<g id="ukui_video_click" transform="translate(28.000000, 14.000000)">
<rect id="矩形" x="0" y="0" width="40" height="40"></rect>
<g id="video-x-generic-symbolic" opacity="0.8" transform="translate(4.000000, 6.000000)" fill="#262626">
<path d="M27,2 C28.6568542,2 30,3.34314575 30,5 L30,23 C30,24.6568542 28.6568542,26 27,26 L5,26 C3.34314575,26 2,24.6568542 2,23 L2,5 C2,3.34314575 3.34314575,2 5,2 L27,2 M27,0 L5,0 C2.23857625,0 0,2.23857625 0,5 L0,23 C0,25.7614237 2.23857625,28 5,28 L27,28 C29.7614237,28 32,25.7614237 32,23 L32,5 C32,2.23857625 29.7614237,0 27,0 Z" id="形状"></path>
<path d="M21.64,13.2 L13.46,8 C13.1666349,7.82091606 12.7999131,7.81233291 12.4984908,7.97749579 C12.1970686,8.14265868 12.0069431,8.45636363 12,8.8 L12,19.2 C12.0069431,19.5436364 12.1970686,19.8573413 12.4984908,20.0225042 C12.7999131,20.1876671 13.1666349,20.1790839 13.46,20 L21.64,14.8 C21.9174859,14.6288056 22.0864415,14.3260459 22.0864415,14 C22.0864415,13.6739541 21.9174859,13.3711944 21.64,13.2 L21.64,13.2 Z" id="路径"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui_video_default</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-616.000000, -1541.000000)" fill-rule="nonzero">
<g id="编组-6" transform="translate(108.000000, 1526.000000)">
<g id="影音娱乐" transform="translate(480.000000, 1.000000)">
<g id="ukui_video_default" transform="translate(28.000000, 14.000000)">
<rect id="矩形" x="0" y="0" width="40" height="40"></rect>
<g id="video-x-generic-symbolic" transform="translate(4.000000, 6.000000)" fill="#FFFFFF" opacity="0.75">
<g id="编组">
<path d="M27,2 C28.6568542,2 30,3.34314575 30,5 L30,23 C30,24.6568542 28.6568542,26 27,26 L5,26 C3.34314575,26 2,24.6568542 2,23 L2,5 C2,3.34314575 3.34314575,2 5,2 L27,2 M27,0 L5,0 C2.23857625,0 0,2.23857625 0,5 L0,23 C0,25.7614237 2.23857625,28 5,28 L27,28 C29.7614237,28 32,25.7614237 32,23 L32,5 C32,2.23857625 29.7614237,0 27,0 Z" id="形状"></path>
<path d="M21.64,13.2 L13.46,8 C13.1666349,7.82091606 12.7999131,7.81233291 12.4984908,7.97749579 C12.1970686,8.14265868 12.0069431,8.45636363 12,8.8 L12,19.2 C12.0069431,19.5436364 12.1970686,19.8573413 12.4984908,20.0225042 C12.7999131,20.1876671 13.1666349,20.1790839 13.46,20 L21.64,14.8 C21.9174859,14.6288056 22.0864415,14.3260459 22.0864415,14 C22.0864415,13.6739541 21.9174859,13.3711944 21.64,13.2 L21.64,13.2 Z" id="路径"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui-terminal-app-click</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-496.000000, -1834.000000)" fill-rule="nonzero">
<g id="ukui-terminal-app-click" transform="translate(496.000000, 1834.000000)">
<rect id="矩形" x="0" y="0" width="40" height="40"></rect>
<g id="编组" opacity="0.75" transform="translate(4.000000, 6.000000)" fill="#3A3A3A">
<path d="M27,2 C28.6568542,2 30,3.34314575 30,5 L30,23.16 C29.989101,24.7239519 28.7239519,25.989101 27.16,26 L4.84,26 C3.27604808,25.989101 2.01089902,24.7239519 2,23.16 L2,4.84 C2.01089902,3.27604808 3.27604808,2.01089902 4.84,2 L27,2 M27,0 L4.84,0 C2.16694181,0 0,2.16694181 0,4.84 L0,23.16 C0,25.8330582 2.16694181,28 4.84,28 L27.16,28 C29.8330582,28 32,25.8330582 32,23.16 L32,5 C32,2.23857625 29.7614237,0 27,0 Z" id="形状"></path>
<path d="M13.4,10.2285714 L9,6.45714286 C8.61340067,6.12577202 7.98659933,6.12577202 7.60000001,6.45714287 C7.21340069,6.78851371 7.21340068,7.32577201 7.6,7.65714286 L12,11.4285714 L7.4,15.3714286 C7.20664555,15.5269714 7.09696271,15.7441384 7.09696271,15.9714286 C7.09696271,16.1987187 7.20664555,16.4158857 7.4,16.5714286 C7.6,16.7428571 7.8,16.7428571 8.2,16.7428571 C8.6,16.7428571 8.8,16.7428571 9,16.5714286 L13.6,12.6285714 C13.8502212,12.2642371 13.9878937,11.8512196 14,11.4285714 C14.0142835,10.9726223 13.7950491,10.5341535 13.4,10.2285714 Z" id="路径"></path>
<path d="M23,15.7142857 L15,15.7142857 C14.4477153,15.7142857 14,16.0980416 14,16.5714286 C14,17.0448155 14.4477153,17.4285714 15,17.4285714 L23,17.4285714 C23.5522847,17.4285714 24,17.0448155 24,16.5714286 C24,16.0980416 23.5522847,15.7142857 23,15.7142857 Z" id="路径"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32px" height="28px" viewBox="0 0 32 28" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui-terminal-app-symbolic</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" opacity="0.75">
<g id="细节规范" transform="translate(-385.000000, -1840.000000)" fill="#FFFFFF" fill-rule="nonzero">
<g id="系统备份" transform="translate(353.000000, 1822.000000)">
<g id="编组" transform="translate(32.000000, 18.000000)">
<path d="M27,2 C28.6568542,2 30,3.34314575 30,5 L30,23.16 C29.989101,24.7239519 28.7239519,25.989101 27.16,26 L4.84,26 C3.27604808,25.989101 2.01089902,24.7239519 2,23.16 L2,4.84 C2.01089902,3.27604808 3.27604808,2.01089902 4.84,2 L27,2 M27,0 L4.84,0 C2.16694181,0 0,2.16694181 0,4.84 L0,23.16 C0,25.8330582 2.16694181,28 4.84,28 L27.16,28 C29.8330582,28 32,25.8330582 32,23.16 L32,5 C32,2.23857625 29.7614237,0 27,0 Z" id="形状"></path>
<path d="M12.4,8.22857143 L8,4.45714286 C7.61340067,4.12577202 6.98659933,4.12577202 6.60000001,4.45714287 C6.21340069,4.78851371 6.21340068,5.32577201 6.6,5.65714286 L11,9.42857143 L6.4,13.3714286 C6.20664555,13.5269714 6.09696271,13.7441384 6.09696271,13.9714286 C6.09696271,14.1987187 6.20664555,14.4158857 6.4,14.5714286 C6.6,14.7428571 6.8,14.7428571 7.2,14.7428571 C7.6,14.7428571 7.8,14.7428571 8,14.5714286 L12.6,10.6285714 C12.8502212,10.2642371 12.9878937,9.85121958 13,9.42857143 C13.0142835,8.97262231 12.7950491,8.53415347 12.4,8.22857143 Z" id="路径"></path>
<path d="M22,13.7142857 L14,13.7142857 C13.4477153,13.7142857 13,14.0980416 13,14.5714286 C13,15.0448155 13.4477153,15.4285714 14,15.4285714 L22,15.4285714 C22.5522847,15.4285714 23,15.0448155 23,14.5714286 C23,14.0980416 22.5522847,13.7142857 22,13.7142857 Z" id="路径"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>view-dual-click</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-258.000000, -1834.000000)" fill-rule="nonzero">
<g id="view-dual-click" transform="translate(258.000000, 1834.000000)">
<rect id="矩形" x="0" y="0" width="40" height="40"></rect>
<path d="M4,10 L4,28 C4,30.2 5.8,32 8,32 L16,32 C17.6,32.2 19,33 20,34 C21.2,33 22.6,32.2 24,32 L32,32 C34.2,32 36,30.2 36,28 L36,10 C36,7.8 34.2,6 32,6 L24,6 C22.6,6 21.2,6.6 20,7.6 C18.8,6.6 17.4,6 16,6 L8,6 C5.8,6 4,7.8 4,10 Z M6,10 C6,8.8 6.8,8 8,8 L16,8 C17.6,8.2 19,9 20,10 C21,9 22.4,8.2 24,8 L32,8 C33.2,8 34,8.8 34,10 L34,28 C34,29.2 33.2,30 32,30 L24,30 C22.6,30 21.2,30.6 20,31.6 C19,30.6 17.4,30 16,30 L8,30 C6.8,30 6,29.2 6,28 L6,10 Z M8,12 L8,14 L16,14 L16,12 L8,12 Z M24,12 L24,14 L32,14 L32,12 L24,12 Z M8,16 L8,18 L16,18 L16,16 L8,16 Z M24,16 L24,18 L32,18 L32,16 L24,16 Z M8,20 L8,22 L16,22 L16,20 L8,20 Z M24,20 L24,22 L32,22 L32,20 L24,20 Z M8,24 L8,26 L16,26 L16,24 L8,24 Z M24,24 L24,26 L32,26 L32,24 L24,24 Z" id="形状" fill="#4F4F4F" opacity="0.75"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>view-dual-default</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-139.000000, -1834.000000)" fill-rule="nonzero">
<g id="系统备份-2" transform="translate(111.000000, 1820.000000)">
<g id="view-dual-default" transform="translate(28.000000, 14.000000)">
<rect id="矩形" x="0" y="0" width="40" height="40"></rect>
<path d="M4,10 L4,28 C4,30.2 5.8,32 8,32 L16,32 C17.6,32.2 19,33 20,34 C21.2,33 22.6,32.2 24,32 L32,32 C34.2,32 36,30.2 36,28 L36,10 C36,7.8 34.2,6 32,6 L24,6 C22.6,6 21.2,6.6 20,7.6 C18.8,6.6 17.4,6 16,6 L8,6 C5.8,6 4,7.8 4,10 Z M6,10 C6,8.8 6.8,8 8,8 L16,8 C17.6,8.2 19,9 20,10 C21,9 22.4,8.2 24,8 L32,8 C33.2,8 34,8.8 34,10 L34,28 C34,29.2 33.2,30 32,30 L24,30 C22.6,30 21.2,30.6 20,31.6 C19,30.6 17.4,30 16,30 L8,30 C6.8,30 6,29.2 6,28 L6,10 Z M8,12 L8,14 L16,14 L16,12 L8,12 Z M24,12 L24,14 L32,14 L32,12 L24,12 Z M8,16 L8,18 L16,18 L16,16 L8,16 Z M24,16 L24,18 L32,18 L32,16 L24,16 Z M8,20 L8,22 L16,22 L16,20 L8,20 Z M24,20 L24,22 L32,22 L32,20 L24,20 Z M8,24 L8,26 L16,26 L16,24 L8,24 Z M24,24 L24,26 L32,26 L32,24 L24,24 Z" id="形状" fill="#FFFFFF" opacity="0.75"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui_gaming_click</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-856.000000, -1660.000000)" fill-rule="nonzero">
<g id="编组-6备份-3" transform="translate(108.000000, 1645.000000)">
<g id="游戏娱乐" transform="translate(720.000000, 1.000000)">
<g id="ukui_gaming_click" transform="translate(28.000000, 14.000000)">
<rect id="矩形" x="0" y="0" width="40" height="40"></rect>
<g id="input-gaming-symbolic" opacity="0.8" transform="translate(4.474171, 6.000000)" fill="#262626">
<path d="M14.725829,8 L14.725829,14 L7.37582895,14 C7.37582895,14 7.16582895,14 7.16582895,14 C4.01582895,14 1.07582895,16.2 0.235828954,19.2 C-0.604171046,22.2 0.865828954,25.4 3.59582895,27 C6.53582895,28.6 10.105829,28.2 12.415829,26 L18.925829,26 C21.235829,28.2 24.805829,28.6 27.745829,27 C30.685829,25.4 31.945829,22.2 31.105829,19.2 C30.475829,16.2 27.535829,14 24.385829,14 C24.385829,14 24.175829,14 24.175829,14 L16.825829,14 L16.825829,8 L14.725829,8 Z M7.37582895,16 L24.175829,16 C26.485829,16 28.585829,17.6 29.215829,19.8 C29.845829,22 28.795829,24.2 26.695829,25.4 C24.805829,26.4 22.285829,26.2 20.605829,24.8 C20.395829,24.6 20.185829,24 19.765829,24 L11.785829,24 C11.365829,24 10.945829,24.6 10.735829,24.8 C9.05582895,26.2 6.53582895,26.4 4.64582895,25.4 C2.54582895,24.2 1.49582895,22 2.12582895,19.8 C2.96582895,17.6 5.06582895,16 7.37582895,16 Z M6.32582895,18 L6.32582895,20 L4.22582895,20 L4.22582895,22 L6.32582895,22 L6.32582895,24 L8.42582895,24 L8.42582895,22 L10.525829,22 L10.525829,20 L8.42582895,20 L8.42582895,18 L6.32582895,18 Z M24.175829,18 C23.545829,18 23.125829,18.4 23.125829,19 C23.125829,19.6 23.545829,20 24.175829,20 C24.805829,20 25.225829,19.6 25.225829,19 C25.225829,18.4 24.805829,18 24.175829,18 Z M22.075829,20 C21.445829,20 21.025829,20.4 21.025829,21 C21.025829,21.6 21.445829,22 22.075829,22 C22.705829,22 23.125829,21.6 23.125829,21 C23.125829,20.4 22.705829,20 22.075829,20 Z M26.275829,20 C25.645829,20 25.225829,20.4 25.225829,21 C25.225829,21.6 25.645829,22 26.275829,22 C26.905829,22 27.325829,21.6 27.325829,21 C27.325829,20.4 26.905829,20 26.275829,20 Z M24.175829,22 C23.545829,22 23.125829,22.4 23.125829,23 C23.125829,23.6 23.545829,24 24.175829,24 C24.805829,24 25.225829,23.6 25.225829,23 C25.225829,22.4 24.805829,22 24.175829,22 Z" id="形状"></path>
<rect id="矩形" x="14.725829" y="4" width="2.1" height="2"></rect>
<rect id="矩形" x="14.725829" y="0" width="2.1" height="2"></rect>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui_gaming_default</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-856.000000, -1541.000000)" fill-rule="nonzero">
<g id="编组-6" transform="translate(108.000000, 1526.000000)">
<g id="游戏娱乐" transform="translate(720.000000, 1.000000)">
<g id="ukui_gaming_default" transform="translate(28.000000, 14.000000)">
<rect id="矩形" x="0" y="0" width="40" height="40"></rect>
<g id="input-gaming-symbolic" opacity="0.733049665" transform="translate(4.000000, 6.000000)" fill="#FFFFFF">
<path d="M15.2,8 L15.2,14 L7.85,14 C7.85,14 7.64,14 7.64,14 C4.49,14 1.55,16.2 0.71,19.2 C-0.13,22.2 1.34,25.4 4.07,27 C7.01,28.6 10.58,28.2 12.89,26 L19.4,26 C21.71,28.2 25.28,28.6 28.22,27 C31.16,25.4 32.42,22.2 31.58,19.2 C30.95,16.2 28.01,14 24.86,14 C24.86,14 24.65,14 24.65,14 L17.3,14 L17.3,8 L15.2,8 Z M7.85,16 L24.65,16 C26.96,16 29.06,17.6 29.69,19.8 C30.32,22 29.27,24.2 27.17,25.4 C25.28,26.4 22.76,26.2 21.08,24.8 C20.87,24.6 20.66,24 20.24,24 L12.26,24 C11.84,24 11.42,24.6 11.21,24.8 C9.53,26.2 7.01,26.4 5.12,25.4 C3.02,24.2 1.97,22 2.6,19.8 C3.44,17.6 5.54,16 7.85,16 Z M6.8,18 L6.8,20 L4.7,20 L4.7,22 L6.8,22 L6.8,24 L8.9,24 L8.9,22 L11,22 L11,20 L8.9,20 L8.9,18 L6.8,18 Z M24.65,18 C24.02,18 23.6,18.4 23.6,19 C23.6,19.6 24.02,20 24.65,20 C25.28,20 25.7,19.6 25.7,19 C25.7,18.4 25.28,18 24.65,18 Z M22.55,20 C21.92,20 21.5,20.4 21.5,21 C21.5,21.6 21.92,22 22.55,22 C23.18,22 23.6,21.6 23.6,21 C23.6,20.4 23.18,20 22.55,20 Z M26.75,20 C26.12,20 25.7,20.4 25.7,21 C25.7,21.6 26.12,22 26.75,22 C27.38,22 27.8,21.6 27.8,21 C27.8,20.4 27.38,20 26.75,20 Z M24.65,22 C24.02,22 23.6,22.4 23.6,23 C23.6,23.6 24.02,24 24.65,24 C25.28,24 25.7,23.6 25.7,23 C25.7,22.4 25.28,22 24.65,22 Z" id="形状"></path>
<rect id="矩形" x="15.2" y="4" width="2.1" height="2"></rect>
<rect id="矩形" x="15.2" y="0" width="2.1" height="2"></rect>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui_image_click</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-736.000000, -1660.000000)" fill-rule="nonzero">
<g id="编组-6备份-3" transform="translate(108.000000, 1645.000000)">
<g id="图像" transform="translate(600.000000, 1.000000)">
<g id="ukui_image_click" transform="translate(28.000000, 14.000000)">
<rect id="矩形" x="0" y="0" width="40" height="40"></rect>
<g id="image-x-generic-symbolic" opacity="0.8" transform="translate(4.000000, 6.000000)" fill="#262626">
<path d="M28,0 L4,0 C1.790861,0 0,1.790861 0,4 L0,24 C0,26.209139 1.790861,28 4,28 L28,28 C30.209139,28 32,26.209139 32,24 L32,4 C32,1.790861 30.209139,0 28,0 Z M4,2 L28,2 C29.1045695,2 30,2.8954305 30,4 L30,18.58 L25.7,14.3 C25.5185333,14.1066455 25.2651718,13.9969627 25,13.9969627 C24.7348282,13.9969627 24.4814667,14.1066455 24.3,14.3 L19.06,19.52 L9.76,8.36 C9.55947479,8.15073716 9.28894785,8.02259282 9,8 C8.69432586,7.99524608 8.40466349,8.13636365 8.22,8.38 L2,16.14 L2,4 C2,2.8954305 2.8954305,2 4,2 Z M28,26 L4,26 C2.8954305,26 2,25.1045695 2,24 L2,19.36 L9.02,10.58 L18.24,21.64 C18.4189709,21.8555648 18.6801656,21.9861621 18.96,22 L18.96,22 C19.2252077,22.0032331 19.4794393,21.8942767 19.66,21.7 L25,16.42 L30,21.42 L30,24 C30,25.1045695 29.1045695,26 28,26 Z" id="形状"></path>
<path d="M23.1111111,11.6666667 C25.4020701,11.6666667 27.2592593,9.83849606 27.2592593,7.58333333 C27.2592593,5.3281706 25.4020701,3.5 23.1111111,3.5 C20.8201521,3.5 18.962963,5.3281706 18.962963,7.58333333 C18.962963,9.83849606 20.8201521,11.6666667 23.1111111,11.6666667 Z M23.1111111,5.54166667 C24.2565906,5.54166667 25.1851852,6.45575197 25.1851852,7.58333333 C25.1851852,8.7109147 24.2565906,9.625 23.1111111,9.625 C21.9656316,9.625 21.037037,8.7109147 21.037037,7.58333333 C21.037037,6.45575197 21.9656316,5.54166667 23.1111111,5.54166667 Z" id="形状"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui_image_default</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-736.000000, -1541.000000)" fill-rule="nonzero">
<g id="编组-6" transform="translate(108.000000, 1526.000000)">
<g id="图像" transform="translate(600.000000, 1.000000)">
<g id="ukui_image_default" transform="translate(28.000000, 14.000000)">
<rect id="矩形" x="0" y="0" width="40" height="40"></rect>
<g id="image-x-generic-symbolic" opacity="0.747628348" transform="translate(4.000000, 6.000000)" fill="#FFFFFF">
<path d="M28,0 L4,0 C1.790861,0 0,1.790861 0,4 L0,24 C0,26.209139 1.790861,28 4,28 L28,28 C30.209139,28 32,26.209139 32,24 L32,4 C32,1.790861 30.209139,0 28,0 Z M4,2 L28,2 C29.1045695,2 30,2.8954305 30,4 L30,18.58 L25.7,14.3 C25.5185333,14.1066455 25.2651718,13.9969627 25,13.9969627 C24.7348282,13.9969627 24.4814667,14.1066455 24.3,14.3 L19.06,19.52 L9.76,8.36 C9.55947479,8.15073716 9.28894785,8.02259282 9,8 C8.69432586,7.99524608 8.40466349,8.13636365 8.22,8.38 L2,16.14 L2,4 C2,2.8954305 2.8954305,2 4,2 Z M28,26 L4,26 C2.8954305,26 2,25.1045695 2,24 L2,19.36 L9.02,10.58 L18.24,21.64 C18.4189709,21.8555648 18.6801656,21.9861621 18.96,22 L18.96,22 C19.2252077,22.0032331 19.4794393,21.8942767 19.66,21.7 L25,16.42 L30,21.42 L30,24 C30,25.1045695 29.1045695,26 28,26 Z" id="形状"></path>
<path d="M23.1111111,11.6666667 C25.4020701,11.6666667 27.2592593,9.83849606 27.2592593,7.58333333 C27.2592593,5.3281706 25.4020701,3.5 23.1111111,3.5 C20.8201521,3.5 18.962963,5.3281706 18.962963,7.58333333 C18.962963,9.83849606 20.8201521,11.6666667 23.1111111,11.6666667 Z M23.1111111,5.54166667 C24.2565906,5.54166667 25.1851852,6.45575197 25.1851852,7.58333333 C25.1851852,8.7109147 24.2565906,9.625 23.1111111,9.625 C21.9656316,9.625 21.037037,8.7109147 21.037037,7.58333333 C21.037037,6.45575197 21.9656316,5.54166667 23.1111111,5.54166667 Z" id="形状"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui_messaging_click</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-496.000000, -1660.000000)">
<g id="编组-6备份-3" transform="translate(108.000000, 1645.000000)">
<g id="社交" transform="translate(360.000000, 1.000000)">
<g id="ukui_messaging_click" transform="translate(28.000000, 14.000000)">
<rect id="矩形" fill-rule="nonzero" x="0" y="0" width="40" height="40"></rect>
<g id="messaging-app-symbolic" opacity="0.8" transform="translate(5.000000, 5.000000)" fill="#262626">
<g id="图层_1">
<path d="M15,2 C22.2,2 28,7.2 28,13.4 C28,19.6 22.2,24.8 15,24.8 C14,24.8 12.8,24.6 11.8,24.4 L11,24.2 L10.2,24.8 L6,28 L6,22.6 L6,21.6 L5.4,21 C3.2,19.2 2,16.4 2,13.4 C2,7.2 7.8,2 15,2 M15,0 C6.8,0 0,6 0,13.4 C0,16.8 1.4,20.2 4,22.4 L4,30 C4,30.6 4.4,31 5,31 C5.2,31 5.4,31 5.6,30.8 L11.4,26.4 C12.6,26.6 13.8,26.8 15,26.8 C23.2,26.8 30,20.8 30,13.4 C30,6 23.2,0 15,0 L15,0 Z" id="形状" fill-rule="nonzero"></path>
<rect id="矩形" x="8" y="9.6" width="14.4" height="2" rx="1"></rect>
<rect id="矩形备份-104" x="8" y="15.6" width="8" height="2" rx="1"></rect>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui_messaging_default</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-496.000000, -1541.000000)">
<g id="编组-6" transform="translate(108.000000, 1526.000000)">
<g id="社交" transform="translate(360.000000, 1.000000)">
<g id="ukui_messaging_default" transform="translate(28.000000, 14.000000)">
<rect id="矩形" fill-rule="nonzero" x="0" y="0" width="40" height="40"></rect>
<g id="messaging-app-symbolic" transform="translate(4.000000, 5.000000)" fill="#FFFFFF" opacity="0.8">
<g id="图层_1">
<path d="M15,2 C22.2,2 28,7.2 28,13.4 C28,19.6 22.2,24.8 15,24.8 C14,24.8 12.8,24.6 11.8,24.4 L11,24.2 L10.2,24.8 L6,28 L6,22.6 L6,21.6 L5.4,21 C3.2,19.2 2,16.4 2,13.4 C2,7.2 7.8,2 15,2 M15,0 C6.8,0 0,6 0,13.4 C0,16.8 1.4,20.2 4,22.4 L4,30 C4,30.6 4.4,31 5,31 C5.2,31 5.4,31 5.6,30.8 L11.4,26.4 C12.6,26.6 13.8,26.8 15,26.8 C23.2,26.8 30,20.8 30,13.4 C30,6 23.2,0 15,0 L15,0 Z" id="形状" fill-rule="nonzero"></path>
<rect id="矩形" x="8" y="9.6" width="14.4" height="2" rx="1"></rect>
<rect id="矩形备份-104" x="8" y="15.6" width="8" height="2" rx="1"></rect>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui_network_click</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-376.000000, -1660.000000)">
<g id="编组-6备份-3" transform="translate(108.000000, 1645.000000)">
<g id="网络" transform="translate(240.000000, 0.000000)">
<g id="ukui_network_click" transform="translate(28.000000, 15.000000)">
<rect id="矩形" fill-rule="nonzero" x="0" y="0" width="40" height="40"></rect>
<g id="编组" opacity="0.8" transform="translate(5.000000, 5.000000)">
<g id="circle4880" fill="#262626" fill-rule="nonzero">
<path d="M15.5,1.72222222 C23.1307692,1.72222222 29.2777778,7.86923077 29.2777778,15.5 C29.2777778,23.1307692 23.1307692,29.2777778 15.5,29.2777778 C7.86923077,29.2777778 1.72222222,23.1307692 1.72222222,15.5 C1.72222222,7.86923077 7.86923077,1.72222222 15.5,1.72222222 M15.5,0 C7.02666667,0 0,7.02666667 0,15.5 C0,23.9733333 7.02666667,31 15.5,31 C23.9733333,31 31,23.9733333 31,15.5 C31,7.02666667 23.9733333,0 15.5,0 L15.5,0 Z" id="形状"></path>
</g>
<polygon id="path4882" fill="#262626" points="1 15 1 17 30 17 30 15"></polygon>
<path d="M15,30 C20.1333333,25.4428571 22,20.6785714 22,15.5 C22,10.3214286 20.1333333,5.55714286 15,1" id="path4884_1_" stroke="#262626" stroke-width="2" stroke-linecap="round"></path>
<path d="M16,1 C10.8666667,5.55714286 9,10.5285714 9,15.5 C9,20.6785714 10.8666667,25.2357143 16,30" id="path4886_1_" stroke="#262626" stroke-width="2" stroke-linecap="round"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui_network_default</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-376.000000, -1541.000000)">
<g id="编组-6" transform="translate(108.000000, 1526.000000)">
<g id="网络" transform="translate(240.000000, 0.000000)">
<g id="ukui_network_default" transform="translate(28.000000, 15.000000)">
<rect id="矩形" fill-rule="nonzero" x="0" y="0" width="40" height="40"></rect>
<g id="编组" opacity="0.75" transform="translate(5.000000, 5.000000)">
<g id="circle4880" fill="#FFFFFF" fill-rule="nonzero">
<path d="M15.5,1.72222222 C23.1307692,1.72222222 29.2777778,7.86923077 29.2777778,15.5 C29.2777778,23.1307692 23.1307692,29.2777778 15.5,29.2777778 C7.86923077,29.2777778 1.72222222,23.1307692 1.72222222,15.5 C1.72222222,7.86923077 7.86923077,1.72222222 15.5,1.72222222 M15.5,0 C7.02666667,0 0,7.02666667 0,15.5 C0,23.9733333 7.02666667,31 15.5,31 C23.9733333,31 31,23.9733333 31,15.5 C31,7.02666667 23.9733333,0 15.5,0 L15.5,0 Z" id="形状"></path>
</g>
<polygon id="path4882" fill="#FFFFFF" points="1 15 1 17 30 17 30 15"></polygon>
<path d="M15,30 C20.1333333,25.4428571 22,20.6785714 22,15.5 C22,10.3214286 20.1333333,5.55714286 15,1" id="path4884_1_" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round"></path>
<path d="M16,1 C10.8666667,5.55714286 9,10.5285714 9,15.5 C9,20.6785714 10.8666667,25.2357143 16,30" id="path4886_1_" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ukui_office_click</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="细节规范" transform="translate(-976.000000, -1660.000000)" fill-rule="nonzero">
<g id="编组-6备份-3" transform="translate(108.000000, 1645.000000)">
<g id="办公" transform="translate(840.000000, 1.000000)">
<g id="ukui_office_click" transform="translate(28.000000, 14.000000)">
<rect id="矩形" x="0" y="0" width="40" height="40"></rect>
<g id="video-display-symbolic" opacity="0.8" transform="translate(4.000000, 6.000000)" fill="#262626">
<path d="M22,26.6905567 C21.2660108,26.7691907 20.5362526,26.5086618 20.0181812,25.9830334 C19.5001097,25.4574049 19.2503854,24.7241638 19.34,23.9917559 L12.62,23.9917559 C12.6928641,24.7419088 12.420342,25.4844528 11.879447,26.0095492 C11.338552,26.5346455 10.5880394,26.785255 9.84,26.6905567 L9.84,26.6905567 C8.88,26.6905567 8.76,27.9899793 9.84,27.9899793 L22,27.9899793 C22.259426,28.0356401 22.5211727,27.9227352 22.6659056,27.7027397 C22.8106385,27.4827443 22.8106385,27.1977917 22.6659056,26.9777963 C22.5211727,26.7578009 22.259426,26.644896 22,26.6905567 L22,26.6905567 Z" id="路径"></path>
<path d="M27,1.99911169 C28.6568542,1.99911169 30,3.34166087 30,4.99777922 L30,16.9924493 C30,18.6485677 28.6568542,19.9911169 27,19.9911169 L5,19.9911169 C3.34314575,19.9911169 2,18.6485677 2,16.9924493 L2,4.99777922 C2,3.34166087 3.34314575,1.99911169 5,1.99911169 L27,1.99911169 M27,0 L5,0 C2.23857625,0 0,2.23758197 0,4.99777922 L0,16.9924493 C0,19.7526466 2.23857625,21.9902286 5,21.9902286 L27,21.9902286 C28.3260824,21.9902286 29.597852,21.4636783 30.5355339,20.5264129 C31.4732158,19.5891475 32,18.3179428 32,16.9924493 L32,4.99777922 C32,2.23758197 29.7614237,0 27,0 Z" id="形状"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Some files were not shown because too many files have changed in this diff Show More