#include "sqlitehelper.h"

#include <complex.h>
#include <QMessageBox>
#include "globalvariables.h"
#include "MyButton.h"
#include <Windows.h>
#include <ShObjIdl.h>
#include <PropKey.h>
#include <ShlObj.h>
#include <QtXml/QtXml>
#include <QtSvg/QtSvg>
#include "navbar.h"
#include "config.h"
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QFile>
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383

#ifdef _DEBUG
#pragma comment (lib,"Qt5Xmld.lib")
#else
#pragma comment (lib,"Qt5Xml.lib")
#endif
#pragma comment (lib,"Shell32.lib")
#if _MSC_VER >=1936
#include <filesystem>
namespace fs = std::filesystem;
#else
#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif

bool getMenu(std::wstring &path_str,QHash<QString,QString> *paths)
{
	fs::directory_iterator* it = new fs::directory_iterator(path_str);
	for (auto file : *it)
	{
		Record record;
		if (fs::is_regular_file(file))
		{
			if (file.path().extension().wstring() == L".lnk")
			{
				HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
				if (SUCCEEDED(hr))
				{
					IShellLink* pShellItem;
					hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
						IID_IShellLink, (void**)&pShellItem);
					if (SUCCEEDED(hr))
					{
						IPersistFile* pPersistFile;
						hr = pShellItem->QueryInterface(IID_IPersistFile, (void**)&pPersistFile);
						if (SUCCEEDED(hr))
						{
							WCHAR szTargetPath[MAX_PATH];
							LPOLESTR pszTargetPath = szTargetPath;
							hr = pPersistFile->Load(file.path().wstring().c_str(), STGM_READ);
							if (SUCCEEDED(hr))
							{
								WIN32_FIND_DATA  fd;
								hr = pShellItem->GetPath(szTargetPath, sizeof(szTargetPath), &fd, 0); ;
								if (SUCCEEDED(hr))
								{
									QString filename = file.path().filename().string().c_str();
									*paths->insert(filename,QString::fromWCharArray(szTargetPath));
								}
								else
								{
									pPersistFile->Release();
									pShellItem->Release();
									CoUninitialize();
									return false;
								}
							}
							else
							{
								pPersistFile->Release();
								pShellItem->Release();
								CoUninitialize();
								return false;
							}
							pPersistFile->Release();
						}
						else
						{
							pShellItem->Release();
							pShellItem->Release();
							CoUninitialize();
							return false;
						}
						pShellItem->Release();
					}
					else
					{
						CoUninitialize();
						return false;
					}
					CoUninitialize();


				}
			}
		}else if(fs::is_directory(file))
		{
			getMenu(file.path().wstring(), paths);
		}
		
	}
	delete it;
	return true;
}
SQLiteHelper::SQLiteHelper(QObject *parent)
	: QObject(parent)
{
	if (QSqlDatabase::contains("mydb"))
	{
		db = QSqlDatabase::database("mydb");
	}
	else
	{
		db = QSqlDatabase::addDatabase("QSQLITE","mydb");
		QString name = QApplication::applicationDirPath() + "/identifier.sqlite";
		db.setDatabaseName(name);
	}
	if (!db.open())
	{
		QMessageBox::critical(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("无法打开数据库"));
		exit_manager.exit(1);
	}
}

SQLiteHelper::~SQLiteHelper()
{
}

bool SQLiteHelper::update_software()
{
	HKEY hKeyUninstall = nullptr;
	QHash<QString,QString>* paths = new QHash<QString, QString>;
	/*QSqlQuery query;
	QString sql = "select * from kmd_menu;";
	query.exec(sql);
	while(query.next())
	{
		Record record;
		record.id = query.value("id").toInt();
		record.sort = query.value("sort").toInt();
		record.app_id = query.value("app_id").toString();
		record.locked = query.value("locked").toBool();
		record.type = query.value("type").toString();
		record.category_id = query.value("category_id").toString();
		record.name = query.value("name").toString();
		record.orig_name = query.value("orig_name").toString();
		record.version = query.value("version").toString();
		record.dev = query.value("dev").toString();
		record.create_time = query.value("create_time").toLongLong();
		record.use_time = query.value("use_time").toLongLong();
		record.op = query.value("op").toString();
		record.func = query.value("func").toString();
		record.path = query.value("path").toString();
		record.url = query.value("url").toString();
		QStringList path_list = record.path.split("\\");
		path_list.removeLast();
		QString path;
		for(auto str : path_list)
		{
			path.append(str);
			path.append("\\");
		}
		path.remove(path.length() - 1, 1);
		records.insert(path, record);
	}*/
	//开始菜单中已安装软件列表
	WCHAR path[MAX_PATH];
	HRESULT hr = SHGetFolderPathW(nullptr, CSIDL_COMMON_PROGRAMS, nullptr, 0, path);//获取ProgramData中开始菜单的路径
	std::wstring path_str(path);
	getMenu(path_str, paths);
	
	for(int i=0;i<sizeof(path)/sizeof(wchar_t);i++)
	{
		path[i] = 0;
	}
	hr = SHGetFolderPathW(nullptr, CSIDL_PROGRAMS, nullptr, 0, path);//获取用户文件夹中开始菜单的路径
	path_str.clear();
	path_str = std::wstring(path);
	getMenu(path_str, paths); 
	// 打开注册表中的已安装软件列表
	QHash<QString, Record> reg_records;
	HKEY hKey;
	if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
		L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
		0, KEY_READ, &hKey) == ERROR_SUCCESS)
	{
		TCHAR    achKey[MAX_KEY_LENGTH];   // buffer for subkey name
		DWORD    cbName;                   // size of name string 
		TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name 
		DWORD    cchClassName = MAX_PATH;  // size of class string 
		DWORD    cSubKeys = 0;               // number of subkeys 
		DWORD    cbMaxSubKey;              // longest subkey size 
		DWORD    cchMaxClass;              // longest class string 
		DWORD    cValues;              // number of values for key 
		DWORD    cchMaxValue;          // longest value name 
		DWORD    cbMaxValueData;       // longest value data 
		DWORD    cbSecurityDescriptor; // size of security descriptor 
		FILETIME ftLastWriteTime;      // last write time 

		DWORD i, retCode;

		TCHAR  achValue[MAX_VALUE_NAME];
		DWORD cchValue = MAX_VALUE_NAME;

		// Get the class name and the value count. 
		retCode = RegQueryInfoKey(
			hKey,                    // key handle 
			achClass,                // buffer for class name 
			&cchClassName,           // size of class string 
			NULL,                    // reserved 
			&cSubKeys,               // number of subkeys 
			&cbMaxSubKey,            // longest subkey size 
			&cchMaxClass,            // longest class string 
			&cValues,                // number of values for this key 
			&cchMaxValue,            // longest value name 
			&cbMaxValueData,         // longest value data 
			&cbSecurityDescriptor,   // security descriptor 
			&ftLastWriteTime);       // last write time 

		// 枚举该列表下所有子键
		for (DWORD i = 0; i<cSubKeys; i++)
		{
			WCHAR szSubKey[MAX_PATH] = { 0 };
			DWORD dwSize = MAX_PATH;
			if (RegEnumKeyExW(hKey, i, szSubKey, &dwSize, NULL, NULL, NULL, NULL)
				== ERROR_SUCCESS)
			{
				// 读取软件属性值
				HKEY hSubKey;
				if (RegOpenKeyExW(hKey, szSubKey, 0, KEY_READ| KEY_WOW64_64KEY, &hSubKey) == ERROR_SUCCESS)
				{
					Record record;
					WCHAR szProductPath[MAX_PATH] = { 0 };
					WCHAR buffer[MAX_PATH] = { 0 };
					DWORD buffer_num;
					dwSize = MAX_PATH * sizeof(WCHAR);
					//安装文件夹
					if (RegQueryValueExW(hSubKey, L"InstallLocation", NULL, NULL,
						(LPBYTE)szProductPath, &dwSize) != ERROR_SUCCESS)
					{
						RegCloseKey(hSubKey);
						continue;
					}
					QString path = QString::fromWCharArray(szProductPath);
					//软件名
					if (RegQueryValueExW(hSubKey, L"DisplayName", NULL, NULL,
						(LPBYTE)buffer, &dwSize) != ERROR_SUCCESS)
					{
						RegCloseKey(hSubKey);
						continue;
					}
					record.name = QString::fromWCharArray(buffer);
					record.orig_name = QString::fromWCharArray(buffer);
					//图标
					RegQueryValueExW(hSubKey, L"DisplayIcon", NULL, NULL,
						(LPBYTE)buffer, &dwSize);
					record.logo = QString::fromWCharArray(buffer);
					//主版本号
					RegQueryValueExW(hSubKey, L"VersionMajor", NULL, NULL,
						(LPBYTE)&buffer_num, &dwSize);
					QString versionMajor = QString::number(buffer_num);
					//次版本号
					RegQueryValueExW(hSubKey, L"VersionMinor", NULL, NULL,
						(LPBYTE)&buffer_num, &dwSize);
					QString versionMinor = QString::number(buffer_num);
					//将主版本号和次版本号拼接在一起
					QString version = versionMajor + "." + versionMinor;
					record.version = version;
					//开发者
					RegQueryValueExW(hSubKey, L"Publisher", NULL, NULL,
						(LPBYTE)buffer, &dwSize);
					record.dev = QString::fromWCharArray(buffer);
					record.type = "app";
					record.status = true;
					record.op = "soft";
					record.locked = false;
					RegCloseKey(hSubKey);
					if(!path.isEmpty())
					{
						reg_records.insert(path, record);
					}
					
				}
			}
			else
			{
				break;
			}
		}
		RegCloseKey(hKey);
	}
	HKEY hkey2;
	if (RegOpenKeyExW(HKEY_CURRENT_USER,
		L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
		0, KEY_READ, &hkey2) == ERROR_SUCCESS)
	{
		TCHAR    achKey[MAX_KEY_LENGTH];   // buffer for subkey name
		DWORD    cbName;                   // size of name string 
		TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name 
		DWORD    cchClassName = MAX_PATH;  // size of class string 
		DWORD    cSubKeys = 0;               // number of subkeys 
		DWORD    cbMaxSubKey;              // longest subkey size 
		DWORD    cchMaxClass;              // longest class string 
		DWORD    cValues;              // number of values for key 
		DWORD    cchMaxValue;          // longest value name 
		DWORD    cbMaxValueData;       // longest value data 
		DWORD    cbSecurityDescriptor; // size of security descriptor 
		FILETIME ftLastWriteTime;      // last write time 

		DWORD i, retCode;

		TCHAR  achValue[MAX_VALUE_NAME];
		DWORD cchValue = MAX_VALUE_NAME;

		// Get the class name and the value count. 
		retCode = RegQueryInfoKey(
			hkey2,                    // key handle 
			achClass,                // buffer for class name 
			&cchClassName,           // size of class string 
			NULL,                    // reserved 
			&cSubKeys,               // number of subkeys 
			&cbMaxSubKey,            // longest subkey size 
			&cchMaxClass,            // longest class string 
			&cValues,                // number of values for this key 
			&cchMaxValue,            // longest value name 
			&cbMaxValueData,         // longest value data 
			&cbSecurityDescriptor,   // security descriptor 
			&ftLastWriteTime);       // last write time 

		// 枚举该列表下所有子键
		for (DWORD i = 0;i<cSubKeys ; i++)
		{
			WCHAR szSubKey[MAX_PATH] = { 0 };
			DWORD dwSize = MAX_PATH;
			if (RegEnumKeyExW(hkey2, i, szSubKey, &dwSize, NULL, NULL, NULL, NULL)
				== ERROR_SUCCESS)
			{
				// 读取软件属性值
				HKEY hSubKey;
				if (RegOpenKeyExW(hkey2, szSubKey, 0, KEY_READ | KEY_WOW64_64KEY, &hSubKey) == ERROR_SUCCESS)
				{
					Record record;
					WCHAR szProductPath[MAX_PATH] = { 0 };
					WCHAR buffer[MAX_PATH] = { 0 };
					DWORD buffer_num;
					dwSize = MAX_PATH * sizeof(WCHAR);
					//安装文件夹
					if (RegQueryValueExW(hSubKey, L"InstallLocation", NULL, NULL,
						(LPBYTE)szProductPath, &dwSize) != ERROR_SUCCESS)
					{
						RegCloseKey(hSubKey);
						continue;
					}
					QString path = QString::fromWCharArray(szProductPath);
					//软件名
					if (RegQueryValueExW(hSubKey, L"DisplayName", NULL, NULL,
						(LPBYTE)buffer, &dwSize) != ERROR_SUCCESS)
					{
						RegCloseKey(hSubKey);
						continue;
					}
					record.name = QString::fromWCharArray(buffer);
					record.orig_name = QString::fromWCharArray(buffer);
					//图标
					RegQueryValueExW(hSubKey, L"DisplayIcon", NULL, NULL,
						(LPBYTE)buffer, &dwSize);
					record.logo = QString::fromWCharArray(buffer);
					//主版本号
					RegQueryValueExW(hSubKey, L"VersionMajor", NULL, NULL,
						(LPBYTE)&buffer_num, &dwSize);
					QString versionMajor = QString::number(buffer_num);
					//次版本号
					RegQueryValueExW(hSubKey, L"VersionMinor", NULL, NULL,
						(LPBYTE)&buffer_num, &dwSize);
					QString versionMinor = QString::number(buffer_num);
					//将主版本号和次版本号拼接在一起
					QString version = versionMajor + "." + versionMinor;
					record.version = version;
					//开发者
					RegQueryValueExW(hSubKey, L"Publisher", NULL, NULL,
						(LPBYTE)buffer, &dwSize);
					record.dev = QString::fromWCharArray(buffer);
					record.type = "app";
					record.status = true;
					record.op = "soft";
					record.locked = false;
					RegCloseKey(hSubKey);
					reg_records.insert(path, record);
				}
			}
			else
			{
				break;
			}
		}
		RegCloseKey(hkey2);
	}
	BOOL isWow64;
	if(IsWow64Process(GetCurrentProcess(),&isWow64))
	{
		HKEY hkey3;
		if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
			L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
			0, KEY_READ|KEY_WOW64_64KEY, &hkey3) == ERROR_SUCCESS)
		{
			TCHAR    achKey[MAX_KEY_LENGTH];   // buffer for subkey name
			DWORD    cbName;                   // size of name string 
			TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name 
			DWORD    cchClassName = MAX_PATH;  // size of class string 
			DWORD    cSubKeys = 0;               // number of subkeys 
			DWORD    cbMaxSubKey;              // longest subkey size 
			DWORD    cchMaxClass;              // longest class string 
			DWORD    cValues;              // number of values for key 
			DWORD    cchMaxValue;          // longest value name 
			DWORD    cbMaxValueData;       // longest value data 
			DWORD    cbSecurityDescriptor; // size of security descriptor 
			FILETIME ftLastWriteTime;      // last write time 

			DWORD i, retCode;

			TCHAR  achValue[MAX_VALUE_NAME];
			DWORD cchValue = MAX_VALUE_NAME;

			// Get the class name and the value count. 
			retCode = RegQueryInfoKey(
				hkey3,                    // key handle 
				achClass,                // buffer for class name 
				&cchClassName,           // size of class string 
				NULL,                    // reserved 
				&cSubKeys,               // number of subkeys 
				&cbMaxSubKey,            // longest subkey size 
				&cchMaxClass,            // longest class string 
				&cValues,                // number of values for this key 
				&cchMaxValue,            // longest value name 
				&cbMaxValueData,         // longest value data 
				&cbSecurityDescriptor,   // security descriptor 
				&ftLastWriteTime);       // last write time 

			// 枚举该列表下所有子键
			for (DWORD i = 0;i<cSubKeys ; i++)
			{
				WCHAR szSubKey[MAX_PATH] = { 0 };
				DWORD dwSize = MAX_PATH;
				if (RegEnumKeyExW(hkey3, i, szSubKey, &dwSize, NULL, NULL, NULL, NULL)
					== ERROR_SUCCESS)
				{
					// 读取软件属性值
					HKEY hSubKey;
					if (RegOpenKeyExW(hkey3, szSubKey, 0, KEY_READ | KEY_WOW64_64KEY, &hSubKey) == ERROR_SUCCESS)
					{
						Record record;
						WCHAR szProductPath[MAX_PATH] = { 0 };
						WCHAR buffer[MAX_PATH] = { 0 };
						DWORD buffer_num;
						dwSize = MAX_PATH * sizeof(WCHAR);
						//安装文件夹
						if (RegQueryValueExW(hSubKey, L"InstallLocation", NULL, NULL,
							(LPBYTE)szProductPath, &dwSize) != ERROR_SUCCESS)
						{
							RegCloseKey(hSubKey);
							continue;
						}
						QString path = QString::fromWCharArray(szProductPath);
						//软件名
						if (RegQueryValueExW(hSubKey, L"DisplayName", NULL, NULL,
							(LPBYTE)buffer, &dwSize) != ERROR_SUCCESS)
						{
							RegCloseKey(hSubKey);
							continue;
						}
						record.name = QString::fromWCharArray(buffer);
						record.orig_name = QString::fromWCharArray(buffer);
						//图标
						RegQueryValueExW(hSubKey, L"DisplayIcon", NULL, NULL,
							(LPBYTE)buffer, &dwSize);
						record.logo = QString::fromWCharArray(buffer);
						//主版本号
						RegQueryValueExW(hSubKey, L"VersionMajor", NULL, NULL,
							(LPBYTE)&buffer_num, &dwSize);
						QString versionMajor = QString::number(buffer_num);
						//次版本号
						RegQueryValueExW(hSubKey, L"VersionMinor", NULL, NULL,
							(LPBYTE)&buffer_num, &dwSize);
						QString versionMinor = QString::number(buffer_num);
						//将主版本号和次版本号拼接在一起
						QString version = versionMajor + "." + versionMinor;
						record.version = version;
						//开发者
						RegQueryValueExW(hSubKey, L"Publisher", NULL, NULL,
							(LPBYTE)buffer, &dwSize);
						record.dev = QString::fromWCharArray(buffer);
						record.type = "app";
						record.status = true;
						record.op = "soft";
						record.locked = false;
						RegCloseKey(hSubKey);
						reg_records.insert(path, record);
					}
				}
				else
				{
					break;
				}
			}
			RegCloseKey(hkey3);
		}
		HKEY hkey4;
		if (RegOpenKeyExW(HKEY_CURRENT_USER,
			L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
			0, KEY_READ | KEY_WOW64_64KEY, &hkey4) == ERROR_SUCCESS)
		{
			TCHAR    achKey[MAX_KEY_LENGTH];   // buffer for subkey name
			DWORD    cbName;                   // size of name string 
			TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name 
			DWORD    cchClassName = MAX_PATH;  // size of class string 
			DWORD    cSubKeys = 0;               // number of subkeys 
			DWORD    cbMaxSubKey;              // longest subkey size 
			DWORD    cchMaxClass;              // longest class string 
			DWORD    cValues;              // number of values for key 
			DWORD    cchMaxValue;          // longest value name 
			DWORD    cbMaxValueData;       // longest value data 
			DWORD    cbSecurityDescriptor; // size of security descriptor 
			FILETIME ftLastWriteTime;      // last write time 

			DWORD i, retCode;

			TCHAR  achValue[MAX_VALUE_NAME];
			DWORD cchValue = MAX_VALUE_NAME;

			// Get the class name and the value count. 
			retCode = RegQueryInfoKey(
				hkey3,                    // key handle 
				achClass,                // buffer for class name 
				&cchClassName,           // size of class string 
				NULL,                    // reserved 
				&cSubKeys,               // number of subkeys 
				&cbMaxSubKey,            // longest subkey size 
				&cchMaxClass,            // longest class string 
				&cValues,                // number of values for this key 
				&cchMaxValue,            // longest value name 
				&cbMaxValueData,         // longest value data 
				&cbSecurityDescriptor,   // security descriptor 
				&ftLastWriteTime);       // last write time 

			// 枚举该列表下所有子键
			for (DWORD i = 0; i < cSubKeys; i++)
				for (DWORD i = 0; ; i++)
				{
					WCHAR szSubKey[MAX_PATH] = { 0 };
					DWORD dwSize = MAX_PATH;
					if (RegEnumKeyExW(hkey4, i, szSubKey, &dwSize, NULL, NULL, NULL, NULL)
						== ERROR_SUCCESS)
					{
						//读取软件属性值
						HKEY hSubKey;
						if (RegOpenKeyExW(hkey3, szSubKey, 0, KEY_READ | KEY_WOW64_64KEY, &hSubKey) == ERROR_SUCCESS)
						{
							Record record;
							WCHAR szProductPath[MAX_PATH] = { 0 };
							WCHAR buffer[MAX_PATH] = { 0 };
							DWORD buffer_num;
							dwSize = MAX_PATH * sizeof(WCHAR);
							//安装文件夹
							if (RegQueryValueExW(hSubKey, L"InstallLocation", NULL, NULL,
								(LPBYTE)szProductPath, &dwSize) != ERROR_SUCCESS)
							{
								RegCloseKey(hSubKey);
								continue;
							}
							QString path = QString::fromWCharArray(szProductPath);
							//软件名
							if (RegQueryValueExW(hSubKey, L"DisplayName", NULL, NULL,
								(LPBYTE)buffer, &dwSize) != ERROR_SUCCESS)
							{
								RegCloseKey(hSubKey);
								continue;
							}
							record.name = QString::fromWCharArray(buffer);
							record.orig_name = QString::fromWCharArray(buffer);
							//图标
							RegQueryValueExW(hSubKey, L"DisplayIcon", NULL, NULL,
								(LPBYTE)buffer, &dwSize);
							record.logo = QString::fromWCharArray(buffer);
							//主版本号
							RegQueryValueExW(hSubKey, L"VersionMajor", NULL, NULL,
								(LPBYTE)&buffer_num, &dwSize);
							QString versionMajor = QString::number(buffer_num);
							//次版本号
							RegQueryValueExW(hSubKey, L"VersionMinor", NULL, NULL,
								(LPBYTE)&buffer_num, &dwSize);
							QString versionMinor = QString::number(buffer_num);
							//将主版本号和次版本号拼接在一起
							QString version = versionMajor + "." + versionMinor;
							record.version = version;
							//开发者
							RegQueryValueExW(hSubKey, L"Publisher", NULL, NULL,
								(LPBYTE)buffer, &dwSize);
							record.dev = QString::fromWCharArray(buffer);
							record.type = "app";
							record.locked = false;
							record.status = true;
							record.op = "soft";
							RegCloseKey(hSubKey);
							reg_records.insert(path, record);
						}
					}
					else
					{
						break;
					}
				}
			RegCloseKey(hkey4);
		}
	}

	//对比两个路径，找出公共部分（划掉）
	QHash<QString, Record> public_programs_list;
	/*for(auto path:*paths)
	{
		QStringList path_list = path.split("\\");
		path_list.removeLast();
		QString path2;
		for(auto str : path_list)
		{
			path2.append(str);
			path2.append("\\");
		}
		if(reg_records.contains(path2))
		{
			reg_records[path2].path = path;
			public_programs_list.insert(reg_records[path2].orig_name, reg_records[path2]);
		}
		path2.remove(path2.length() - 1, 1);
		if(reg_records.contains(path2))
		{
			reg_records[path2].path = path;
			public_programs_list.insert(reg_records[path2].orig_name, reg_records[path2]);
		}
	}
	delete paths;*/
	for(auto key :reg_records.keys())
	{
		public_programs_list.insert(reg_records[key].orig_name, reg_records[key]);
	}
	//进行网络请求，补全字段
	SoftwareRequest software_request;
	bool ok=software_request.sendRequest(*paths,&public_programs_list);
	if(!ok)
	{
		return false;

	}

	QSqlQuery begin(db);
	if (!begin.exec("begin;"))
	{
		return false;
	}
	for(auto key : public_programs_list.keys())
	{
		
		QString sql_find = "select sort from kmd_menu where orig_name='";
		sql_find += key;
		sql_find += "';";
		QSqlQuery query_find(db);
		if(!query_find.exec(sql_find))
		{
			QSqlQuery rollback(db);
			rollback.exec("rollback;");
			return false;
		}
		QString sql;
		if(query_find.next())
		{
			sql = "update kmd_menu set";
			sql += " path='";
			sql += public_programs_list[key].path;
			sql += "'";
			sql += " ,op='";
			sql += public_programs_list[key].op;
			sql += "' ,func='";
			sql += public_programs_list[key].func;
			sql += "' ,url='";
			sql += public_programs_list[key].url;
			sql += "' where orig_name='";
			sql += key;
			sql += "';";
		}
		else
		{
			sql = "insert into kmd_menu (sort,app_id,locked,type,category_id,name,orig_name,version,dev,create_time,use_time,op,func,path,url,status) values (";
			sql += "50";
			sql += ",'";
			sql += public_programs_list[key].app_id;
			sql += "',";
			sql += QString::number(public_programs_list[key].locked);
			sql += ",'";
			sql += public_programs_list[key].type;
			sql += "','";
			sql += QString::number(OTHERS, 10);
			sql += "','";
			sql += public_programs_list[key].name;
			sql += "','";
			sql += public_programs_list[key].orig_name;
			sql += "','";
			sql += public_programs_list[key].version;
			sql += "','";
			sql += public_programs_list[key].dev;
			sql += "',";
			sql += QString::number(public_programs_list[key].create_time);
			sql += ",";
			sql += QString::number(public_programs_list[key].use_time);
			sql += ",'";
			sql += public_programs_list[key].op;
			sql += "','";
			sql += public_programs_list[key].func;
			sql += "','";
			sql += public_programs_list[key].path;
			sql += "','";
			sql += public_programs_list[key].url;
			sql += "','";
			sql += public_programs_list[key].status;
			sql += "');";
		}
		QSqlQuery query(db);
		if(!query.exec(sql))
		{
			QSqlQuery rollback("rollback;");
			rollback.exec();
			return false;
		}
	}
	QSqlQuery find(db);

	find.exec("select orig_name,op from kmd_menu;");
	while(find.next())
	{
		if(!public_programs_list.contains(find.value("orig_name").toString()))
		{
			if (find.value("op").toString() == "soft")
			{
				QSqlQuery del(db);
				del.prepare("update kmd_menu set status=0 where orig_name=:orig_name;");
				del.bindValue(":orig_value", find.value("orig_name"));
				del.exec();
			}
		}
	}
	find.clear();
	find.exec("select id from kmd_menu where status=0;");
	if(find.size()>=100)
	{
		QSqlQuery del(db);
		del.exec("delete from kmd_menu where status=0;");
	}
	QSqlQuery commit(db);
	commit.exec("commit;");
	return true;
}
void SetSVGBackColor(QDomElement& elem, QString strtagname, QString strattr, QString strattrval)
{
	if (elem.tagName().compare(strtagname) == 0)
	{
		QString before_color = elem.attribute(strattr);
		elem.setAttribute(strattr, strattrval);
		QString color = elem.attribute(strattr);
	}
	for (int i = 0; i < elem.childNodes().count(); i++)
	{
		if (!elem.childNodes().at(i).isElement())
		{
			continue;
		}
		SetSVGBackColor(elem.childNodes().at(i).toElement(), strtagname, strattr, strattrval);
	}
}
bool SQLiteHelper::get_software(QList<ButtonStruct>* buttons, ConfigResponse* config_response)
{
	QSqlQuery query(db);
	QString sql = "select * from kmd_menu where type='navbar' order by sort,orig_name asc ;";
	if (!query.exec(sql))
	{
		return false;
	}
	QString background_color;
	QString title_color;
	QString title_cover_color;
	if(config_response->succeed)
	{
		background_color = config_response->basic.backgroud_color;
		title_color = config_response->basic.title_color;
		title_cover_color = config_response->basic.title_cover_color;
	}
	else
	{
		background_color = DEFAULT_BACKGROUND_COLOR;
		title_color = DEFAULT_TEXT_COLOR;
		title_cover_color = DEFAULT_COVER_COLOR;
	}
	QByteArray* buffer = new QByteArray;
	QHash<QString, ButtonStruct> button_map;
	for(auto menu : config_response->buttons)
	{
		
	}
	while (query.next())
	{
		QString icon = QApplication::applicationDirPath() + "/images/software/" + query.value("orig_name").toString() + ".svg";
		ButtonStruct button_struct;
		button_struct.path = query.value("path").toString();
		button_struct.text = query.value("name").toString();
		button_struct.orig_name = query.value("orig_name").toString();
		button_struct.op = query.value("op").toString();
		button_struct.func = query.value("func").toString();
		button_struct.url = query.value("url").toString();
		button_struct.initial_position = query.value("initial_position").toString();
		QImage* image = new QImage(200, 200, QImage::Format_ARGB32);
		QImage* image_cover = new QImage(200, 200, QImage::Format_ARGB32);
		QFile file(icon);
		if (file.open(QIODevice::ReadOnly))
		{
			QByteArray svg_buffer = file.readAll();
			file.close();
			QSvgRenderer* render_image = new QSvgRenderer(svg_buffer);
			QPainter painter_image(image);
			painter_image.setCompositionMode(QPainter::CompositionMode_Clear); // 清除画布
			painter_image.fillRect(image->rect(), Qt::transparent); // 填充透明色
			painter_image.setCompositionMode(QPainter::CompositionMode_SourceOver);     // 恢复默认值
			render_image->render(&painter_image);
			//修改颜色
			QDomDocument doc;
			doc.setContent(svg_buffer);
			SetSVGBackColor(doc.documentElement(), "path", "fill",title_cover_color);
			QSvgRenderer* render_image_cover = new QSvgRenderer(doc.toByteArray());
			QPainter painter_image_cover(image_cover);
			painter_image_cover.setCompositionMode(QPainter::CompositionMode_Clear); // 清除画布
			painter_image_cover.fillRect(image_cover->rect(), Qt::transparent); // 填充透明色
			painter_image_cover.setCompositionMode(QPainter::CompositionMode_SourceOver);     // 恢复默认值
			render_image_cover->render(&painter_image_cover);

			delete render_image;
			delete render_image_cover;
		}else
		{
			icon = QApplication::applicationDirPath() + DEFAULT_IMAGE;
			QFile file(icon);
			if (file.open(QIODevice::ReadOnly))
			{
				QByteArray svg_buffer = file.readAll();
				file.close();
				QSvgRenderer* render_image = new QSvgRenderer(svg_buffer);
				QPainter painter_image(image);
				painter_image.setCompositionMode(QPainter::CompositionMode_Clear); // 清除画布
				painter_image.fillRect(image->rect(), Qt::transparent); // 填充透明色
				painter_image.setCompositionMode(QPainter::CompositionMode_SourceOver);     // 恢复默认值
				render_image->render(&painter_image);
				//修改颜色
				QDomDocument doc;
				doc.setContent(svg_buffer);
				SetSVGBackColor(doc.documentElement(), "path", "fill", title_cover_color);
				QSvgRenderer* render_image_cover = new QSvgRenderer(doc.toByteArray());
				QPainter painter_image_cover(image_cover);
				painter_image_cover.setCompositionMode(QPainter::CompositionMode_Clear); // 清除画布
				painter_image_cover.fillRect(image_cover->rect(), Qt::transparent); // 填充透明色
				painter_image_cover.setCompositionMode(QPainter::CompositionMode_SourceOver);     // 恢复默认值
				render_image_cover->render(&painter_image_cover);

				delete render_image;
				delete render_image_cover;
			}
		}
		button_struct.image = image;
		button_struct.image_cover = image_cover;
		button_struct.background_color = background_color;
		button_struct.text_color = QColor(title_color);
		button_struct.text_cover_color = QColor(title_cover_color);
		*buttons << button_struct;
	}

	return true;
}

void SQLiteHelper::cancelDownload() {
	disconnect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
	eventLoop.quit();
	reply->abort();
	downloadSuccess = false;
}
bool SQLiteHelper::update_app()
{
	QString app_path = QApplication::applicationDirPath()+"/app";
	for(auto dir: fs::directory_iterator(fs::path(app_path.toStdString())))
	{
		if(fs::is_directory(dir))
		{
			QString config_path = QString::fromWCharArray(dir.path().wstring().c_str())+"/kmd_config.json";
			config_path.replace("/", "\\");
			QFile config_file(config_path);
			if(!config_file.open(QIODevice::Text|QIODevice::ReadOnly))
			{
				continue;
			}
			QByteArray buffer = config_file.readAll();
			config_file.close();
			QJsonDocument document = QJsonDocument::fromJson(buffer);
			if(!document.isObject())
			{
				continue;
			}
			QJsonObject obj_root = document.object();
			
			QSqlQuery query_sel(db);
			QString sql_sel = "select sort from kmd_menu where orig_name = '";
			sql_sel += obj_root.value("orig_name").toString();
			sql_sel += "';";
			query_sel.exec(sql_sel);
			if(!query_sel.next()){
				QSqlQuery query(db);
				time_t create_time;
				time(&create_time);
				QString sql = "insert into kmd_menu "
					"(sort, app_id, locked, type, category_id, name, orig_name,"
					" version, dev, create_time, op, func, path, url, "
					"logo, initial_position,status) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);";
				query.prepare(sql);
				query.addBindValue(50);
				query.addBindValue(obj_root.value("app_id").toString());
				query.addBindValue(obj_root.value("locked").toBool());
				query.addBindValue(obj_root.value("type").toString());
				query.addBindValue(obj_root.value("category_id").toString());
				query.addBindValue(obj_root.value("name").toString());
				query.addBindValue(obj_root.value("orig_name").toString());
				query.addBindValue(obj_root.value("version").toString());
				query.addBindValue(obj_root.value("dev").toString());
				query.addBindValue(create_time);
				query.addBindValue(obj_root.value("op").toString());
				query.addBindValue(obj_root.value("func").toString());
				query.addBindValue(obj_root.value("path").toString());
				query.addBindValue(obj_root.value("url").toString());
				query.addBindValue(obj_root.value("logo").toString());
				query.addBindValue(obj_root.value("initial_position").toString());
				query.addBindValue(obj_root.value("status").toBool());
				query.exec();
			}
			

		}
	}
	return true;
}

bool SQLiteHelper::get_buttons(QList<ButtonStruct> &buttons)
{
	QSqlQuery query(db);
	if(!query.exec("select * from kmd_menu where type='app_manage'and status=1 order by sort asc"))
	{
		return false;
	}
	while(query.next())
	{
		ButtonStruct button_struct;
		button_struct.text = query.value("name").toString();
		button_struct.op= query.value("op").toString();
		button_struct.func = query.value("func").toString();
		button_struct.path = query.value("path").toString();
		button_struct.url = query.value("url").toString();
		button_struct.text_color = DEFAULT_TEXT_COLOR;
		button_struct.background_color = DEFAULT_COVER_COLOR;
		buttons << button_struct;
	}
	return true;
}
bool SQLiteHelper::insert_software(QString name, QString orig_name, QString path, QString sort,bool *categories) {
	QSqlQuery query(db);
	QString categories_str="";
	for(int i=0;i<8;i++)
	{
		if(categories[i])
		{
			categories_str = categories_str + QString::number(i + 1) + ",";
		}
	}
	QString sql = "insert into kmd_menu "
		"(sort, app_id, locked, type, category_id, name, orig_name,"
		" create_time, op, func, path, url, "
		"initial_position,status) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?);";
	query.prepare(sql);
	query.addBindValue(sort.toInt());
	query.addBindValue("");
	query.addBindValue(false);
	query.addBindValue("app");
	query.addBindValue(categories_str);
	query.addBindValue(name);
	query.addBindValue(name);
	time_t create_time;
	time(&create_time);
	query.addBindValue(create_time);
	query.addBindValue("soft");
	query.addBindValue("");
	query.addBindValue(path);
	query.addBindValue("");
	query.addBindValue("");
	query.addBindValue(true);
	if(!query.exec())
	{
		//QMessageBox::critical(nullptr, QString::fromLocal8Bit("错误"), QString::fromLocal8Bit("写入数据库失败"));
		return false;
	}
	return true;
}

bool SQLiteHelper::set_category(QList<Categrory>& categrories)
{
	QSqlQuery work(db);
	work.exec("begin;");
	for(Categrory categrory:categrories)
	{
		QSqlQuery query(db);
		query.prepare("update kmd_category set name=:name,sort=:sort,status=:status where id=:id;");
		query.bindValue(":name", categrory.name);
		query.bindValue(":status", categrory.display);
		query.bindValue(":sort", categrory.sort);
		query.bindValue(":id", categrory.id);
		if (!query.exec())
		{
			qDebug() << query.lastError();
			work.exec("rollback;");
			return false;
		}
	}
	QSqlQuery work2(db);
	work2.exec("commit;");
	qDebug() << work.lastError();
	return true;
}
bool SQLiteHelper::get_category(QList<Categrory>& categrories)
{
	QSqlQuery query(db);
	if(!query.exec("select id,name,status,sort from kmd_category"))
	{
		return false;
	}
	while(query.next())
	{
		if(query.value("name")==QString::fromLocal8Bit("全部"))
		{
			continue;
		}
		Categrory categrory;
		categrory.name = query.value("name").toString();
		categrory.id = query.value("id").toInt();
		categrory.sort = query.value("sort").toInt();
		categrory.display = query.value("status").toBool();
		categrories << categrory;
	}
	return true;
}

bool SQLiteHelper::get_all_software(QList<Record> &softwares,int category)
{
	QString sql;
	if(category==ALL)
	{
		sql = "select * from kmd_menu where status=1 and not type='app_manage' and not op='self' order by sort;";
	}
	else
	{
		sql = "select * from kmd_menu where category_id like '%";
		sql += QString::number(category, 10);
		sql += "%' and not type='app_manage' and status=1 order by sort;";
	}
	QSqlQuery query(db);
	if(!query.exec(sql))
	{
		return false;
	}
	while(query.next())
	{

		Record record;
		record.id = query.value("id").toInt();
		record.sort = query.value("sort").toInt();
		record.app_id = query.value("app_id").toString();
		record.locked = query.value("locked").toBool();
		record.type = query.value("type").toString();
		record.category_id = query.value("category_id").toString();
		record.name = query.value("name").toString();
		record.orig_name = query.value("orig_name").toString();
		record.version = query.value("version").toString();
		record.dev = query.value("dev").toString();
		record.create_time = query.value("create_time").toLongLong();
		record.use_time = query.value("use_time").toLongLong();
		record.op = query.value("op").toString();
		record.func = query.value("func").toString();
		record.path = query.value("path").toString();
		record.url = query.value("url").toString();
		softwares << record;
	}
	return true;
}

bool SQLiteHelper::edit_software(QString name, QString orig_name, QString path, QString sort, bool* categories, QString type)
{
	if (type.isEmpty())
	{
		QString sql = "update kmd_menu set name=:name,path=:path,sort=:sort,category_id=:categories where orig_name=:orig_name;";
		QSqlQuery query(db);
		query.prepare(sql);
		query.bindValue(":name", name);
		query.bindValue(":path", path);
		query.bindValue(":sort", sort.toInt());
		QString categories_str = "";
		for (int i = 0; i < 8; i++)
		{
			if (categories[i])
			{
				categories_str += QString::number(i + 1) + ",";
			}
		}
		query.bindValue(":categories", categories_str);
		query.bindValue(":orig_name", orig_name);
		if (!query.exec())
		{
			return false;
		}
		return true;
	}else
	{

		QString sql = "update kmd_menu set name=:name,path=:path,sort=:sort,category_id=:categories,type=:type where orig_name=:orig_name;";
		QSqlQuery query(db);
		query.prepare(sql);
		query.bindValue(":name", name);
		query.bindValue(":path", path);
		query.bindValue(":sort", sort.toInt());
		QString categories_str = "";
		for (int i = 0; i < 8; i++)
		{
			if (categories[i])
			{
				categories_str += QString::number(i + 1) + ",";
			}
		}
		query.bindValue(":type", type);
		query.bindValue(":categories", categories_str);
		query.bindValue(":orig_name", orig_name);
		if (!query.exec())
		{
			return false;
		}
		return true;
	}
}
