#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 <QtNetwork/QtNetwork>
#include <QtSvg/QtSvg>
#include "navbar.h"
#include "config.h"
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <fstream>
#include <QFile>
#include "applicationmanager.h"
#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")

#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
#include <iostream>
#include <experimental/filesystem>
namespace fs= std::experimental::filesystem;



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>;
	//开始菜单中已安装软件列表
	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 key : reg_records.keys())
	{
		public_programs_list.insert(reg_records[key].orig_name, reg_records[key]);
	}
	QSqlQuery find2(db);
	QJsonArray array;
	if (find2.exec("select * from kmd_menu where status=1;")) {
		while (find2.next()) {
			QJsonObject obj;
			obj.insert("sort", find2.value("sort").toInt());
			obj.insert("app_id", find2.value("app_id").toString());
			obj.insert("locked", find2.value("locked").toBool());
			obj.insert("type", find2.value("type").toString());
			obj.insert("category_id", find2.value("category_id").toString());
			obj.insert("name", find2.value("name").toString());
			obj.insert("orig_name", find2.value("orig_name").toString());
			obj.insert("version", find2.value("version").toString());
			obj.insert("dev", find2.value("dev").toString());
			obj.insert("create_time", find2.value("create_time").toInt());
			obj.insert("use_time", find2.value("use_time").toInt());
			obj.insert("op", find2.value("op").toString());
			obj.insert("func", find2.value("func").toString());
			obj.insert("path", find2.value("path").toString());
			obj.insert("url", find2.value("url").toString());
			obj.insert("initial_position", find2.value("initial_position").toString());
			obj.insert("logo", find2.value("logo").toString());
			obj.insert("status", find2.value("status").toBool());
			obj.insert("is_navbar", find2.value("is_navbar").toBool());
			obj.insert("is_elite", find2.value("is_elite").toBool());
			array.append(obj);
		}
	}
	
	//进行网络请求，补全字段
	SoftwareRequest software_request;
	bool ok=software_request.sendRequest(*paths,&public_programs_list,array);
	if(!ok)
	{
		return false;

	}

	QSqlQuery begin(db);
	if (!begin.exec("begin;"))
	{
		return false;
	}
	for(auto key : public_programs_list.keys())
	{
		QSqlQuery query(db);
		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
		{
			public_programs_list[key].img.replace(QApplication::applicationDirPath(), "");
			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,is_navbar,is_elite) values "
				"(:sort,:app_id,:locked,:type,:category_id,:name,:orig_name,:version,:dev,:create_time,:use_time,:op,:func,:path,:url,:status,:is_navbar,:is_elite); ";
			query.prepare(sql);
			query.bindValue(":sort", 50);
			query.bindValue(":app_id", public_programs_list[key].app_id);
			query.bindValue(":locked", public_programs_list[key].locked);
			query.bindValue(":type", public_programs_list[key].type);
			query.bindValue(":category_id", public_programs_list[key].category_id);
			query.bindValue(":name", public_programs_list[key].name);
			query.bindValue(":orig_name", public_programs_list[key].orig_name);
			query.bindValue(":version", public_programs_list[key].version);
			query.bindValue(":dev", public_programs_list[key].dev);
			query.bindValue(":create_time", public_programs_list[key].create_time);
			query.bindValue(":use_time", public_programs_list[key].use_time);
			query.bindValue(":op", public_programs_list[key].op);
			query.bindValue(":func", public_programs_list[key].func);
			query.bindValue(":path", public_programs_list[key].path);
			query.bindValue(":url", public_programs_list[key].url);
			query.bindValue(":is_navbar", public_programs_list[key].is_navbar);
			query.bindValue(":is_elite", public_programs_list[key].is_elite);
			query.bindValue(":status", true);
			bool categories[CATEGORIES_NUM] = { false };
			categories[ALL - 1] = true;
			categories[SOFT - 1] = true;
		}
		update_total();
		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();
				bool categories[CATEGORIES_NUM] = { false };
				categories[ALL - 1] = true;
				categories[SOFT - 1] = true;
				update_total();
			}
		}
	}
	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>* button_structs, ConfigResponse* config_response)
{
	QSqlQuery query(db);
	QString sql = "select * from kmd_menu where is_navbar=1 order by sort,orig_name asc ;";
	
	QString title_color;
	QString title_cover_color;
	QList<Button> buttons = config_response->buttons;
	if (config_response->succeed)
	{
		background_color = config_response->basic.backgroud_color;
		text_color = config_response->basic.title_color;
		text_cover_color = config_response->basic.title_cover_color;
		title_color = config_response->basic.title_color;
		title_cover_color = config_response->basic.title_cover_color;

	}
	else
	{
		QFile file(QApplication::applicationDirPath() + DEFAULT_NAVBAR_FILLE);
		if (file.open(QIODevice::ReadOnly | QIODevice::Text))
		{
			QByteArray buffer;
			buffer = file.readAll();
			QJsonDocument result;
			result = QJsonDocument::fromJson(buffer);
			//如果数据完整
			if (result.isObject()) {
				QJsonObject obj_root = result.object();
				QJsonArray array;

				array = obj_root.value("data").toObject().value("menu").toArray();
				qDebug() << array;
				QJsonObject obj_data = obj_root.value("data").toObject();
				QJsonObject obj_basic = obj_data.value("basic").toObject();
				background_color = obj_basic.value("backgroud_color").toString();
				title_color = obj_basic.value("title_color").toString();
				text_color = obj_basic.value("title_color").toString();
				title_cover_color = obj_basic.value("title_cover_color").toString();
			}
			else {
				background_color = DEFAULT_BACKGROUND_COLOR;
				title_color = DEFAULT_TEXT_COLOR;
				text_color = DEFAULT_TEXT_COLOR;
				title_cover_color = DEFAULT_COVER_COLOR;
			}
		}
	}

	QByteArray* buffer = new QByteArray;
	QHash<QString, ButtonStruct> button_map;
	QNetworkAccessManager* manager;
	for (auto menu : buttons)
	{
		ButtonStruct button_struct;
		button_struct.text = menu.name;
		button_struct.orig_name = menu.orig_name;
		button_struct.op = menu.op;
		button_struct.func = menu.func;
		button_struct.url = menu.url;
		QImage* image = new QImage(200, 200, QImage::Format_ARGB32);
		QImage* image_cover = new QImage(200, 200, QImage::Format_ARGB32);
		downloadSuccess = true;
		QUrl url_logo(menu.img);
		QNetworkRequest* request_logo = new QNetworkRequest(url_logo);
		manager = new QNetworkAccessManager;
		reply = manager->get(*request_logo);
		QTimer timer;
		timer.setInterval(5000);
		connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
		connect(&timer, &QTimer::timeout, this, &SQLiteHelper::cancelDownload);
		eventLoop.exec();
		timer.stop();
		buffer = new QByteArray;
		*buffer = reply->readAll();
		delete request_logo;
		reply->close();
		QString svg_path = QApplication::applicationDirPath() + DEFAULT_SVG_PATH + menu.img_name + ".svg";;
		if ((reply->error() == QNetworkReply::NoError)&&(downloadSuccess == true)) {
			QFile file(QApplication::applicationDirPath() + DEFAULT_SVG_PATH + menu.img_name+".svg");
			if (file.open(QIODevice::Text | QIODevice::WriteOnly))
			{
				file.write(*buffer);
				file.close();
			}
		}
		else
		{
			QString icon = QApplication::applicationDirPath() + DEFAULT_SVG_PATH + menu.img_name+".svg";
			QFile file(icon);
			if (file.open(QIODevice::ReadOnly | QIODevice::Text))
			{
				//QByteArray* buffer = new QByteArray;
				*buffer = file.readAll();
				file.close();
			}
			else
			{
				icon = QApplication::applicationDirPath() + DEFAULT_IMAGE;
				if (file.open(QIODevice::ReadOnly | QIODevice::Text))
				{
					//QByteArray* buffer = new QByteArray;
					*buffer = file.readAll();
					file.close();
				}
			}
		}
		delete manager;
		manager = nullptr;
		QUrl url_png(menu.png);
		QNetworkRequest* request_png = new QNetworkRequest(url_png);
		manager = new QNetworkAccessManager;
		reply = manager->get(*request_png);
		QTimer timer_png;
		timer_png.setInterval(5000);
		connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
		connect(&timer_png, &QTimer::timeout, this, &SQLiteHelper::cancelDownload);
		eventLoop.exec();
		timer_png.stop();
		QByteArray buffer_png;
		buffer_png = reply->readAll();
		delete request_png;
		QString png_path = QApplication::applicationDirPath() + DEFAULT_PNG_PATH + menu.img_name + ".png";;
		if ((reply->error() == QNetworkReply::NoError) && (downloadSuccess == true))
		{
			//没仔细研究QFile，貌似读写二进制文件挺麻烦，先用标准库吧
			std::ofstream out(png_path.toStdString(), std::ios::binary);
			if(out.is_open())
			{
				out.write(buffer_png.data(), buffer_png.size());
				out.close();
			}
		}
		else
		{
			QString icon = QApplication::applicationDirPath() + DEFAULT_PNG_PATH + menu.img_name + ".png";
			QFile file(icon);
			if (file.open(QIODevice::ReadOnly))
			{
				buffer_png = file.readAll();
				file.close();
			}
			else
			{
				icon = QApplication::applicationDirPath() + DEFAULT_PNG;
				if (file.open(QIODevice::ReadOnly))
				{
					buffer_png = file.readAll();
					file.close();
				}
			}
		}
		reply->close();
		delete manager;
		manager = nullptr;
		bool categories[CATEGORIES_NUM] = { false };
		for(int i=0;i<CATEGORIES_NUM;i++)
		{
			if (menu.categroy_id.contains(QString::number(i+1)))
			{
				categories[i] = true;
			}
		}
		if(menu.is_delete)
		{
			delete_software(menu.orig_name);
		}else
		{
			insert_software(menu.name, menu.orig_name, "", QString::number(menu.sort),
				categories, DEFAULT_SVG_PATH + menu.img_name + ".svg",
				DEFAULT_PNG_PATH + menu.img_name + ".png", menu.type,
				menu.locked, menu.op, menu.func, menu.url, menu.is_navbar, menu.is_elite, menu.dev);
		}
		
	}
	if (!query.exec(sql))
	{
		return false;
	}
	while (query.next())
	{
		QString icon;
		if(query.value("logo").toString().contains(":"))
		{
			icon = query.value("logo").toString();
		}else
		{
			icon = QApplication::applicationDirPath() +query.value("logo").toString();
		}
		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();
			QDomDocument doc;
			doc.setContent(svg_buffer);
			SetSVGBackColor(doc.documentElement(), "path", "fill", title_color);
			QSvgRenderer* render_image = new QSvgRenderer(doc.toByteArray());
			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);
			//修改颜色
			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();
				QDomDocument doc;
				doc.setContent(svg_buffer);
				SetSVGBackColor(doc.documentElement(), "path", "fill", title_color);
				QSvgRenderer* render_image = new QSvgRenderer(doc.toByteArray());
				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);
				//修改颜色
				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;
			}
		}
		QFile png(QApplication::applicationDirPath() + query.value("img").toString());
		if(png.exists())
		{
			button_struct.png = new QImage(QApplication::applicationDirPath() + query.value("img").toString());
		}else
		{
			button_struct.png = new QImage(QApplication::applicationDirPath()+DEFAULT_PNG);
		}
		
		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);
		*button_structs << button_struct;
	}
	QSqlQuery begin_query(db);
	begin_query.exec("BEGIN;");
	update_total();
	QSqlQuery commit_query(db);
	commit_query.exec("COMMIT;");
	return true;
}
bool SQLiteHelper::get_software(QList<ButtonStruct>* button_structs,QString background_color,QString title_color,QString title_cover_color)
{
	QSqlQuery query(db);
	QString sql = "select * from kmd_menu where is_navbar=1 order by sort,orig_name asc ;";
	if (!query.exec(sql))
	{
		return false;
	}
	while (query.next())
	{
		QString icon = QApplication::applicationDirPath() + query.value("logo").toString();
		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();
			QDomDocument doc;
			doc.setContent(svg_buffer);
			SetSVGBackColor(doc.documentElement(), "path", "fill", title_color);
			QSvgRenderer* render_image = new QSvgRenderer(doc.toByteArray());
			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);
			//修改颜色
			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();
				QDomDocument doc;
				doc.setContent(svg_buffer);
				SetSVGBackColor(doc.documentElement(), "path", "fill", title_color);
				QSvgRenderer* render_image = new QSvgRenderer(doc.toByteArray());
				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);
				//修改颜色
				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;
			}
		}
		QFile png(QApplication::applicationDirPath() + query.value("img").toString());
		if (png.exists())
		{
			button_struct.png = new QImage(QApplication::applicationDirPath() + query.value("img").toString());
		}
		else
		{
			button_struct.png = new QImage(QApplication::applicationDirPath() + DEFAULT_PNG);
		}
		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);
		*button_structs << button_struct;
	}
	QSqlQuery begin_query(db);
	begin_query.exec("BEGIN;");
	update_total();
	QSqlQuery commit_query(db);
	commit_query.exec("COMMIT;");
	return true;
}

void SQLiteHelper::cancelDownload() {
	disconnect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
	eventLoop.quit();
	reply->abort();
	downloadSuccess = false;
}
bool SQLiteHelper::update_app()
{
	QSqlQuery work(db);
	work.exec("begin;");
	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/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,img,is_navbar,is_elite) 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.addBindValue(obj_root.value("img").toString());
				query.addBindValue(false);
				query.addBindValue(false);
				query.exec();
				bool categories[CATEGORIES_NUM]={false};
				categories[ALL - 1] = true;
				categories[INNER - 1] = true;
				update_total();
			}
		}
	}
	work.exec("commit;");
	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, QString logo, QString img,QString type,bool locked,QString op,QString func,QString url,bool is_navbar,bool is_elite,QString dev) {
	QSqlQuery begin(db);
	begin.exec("BEGIN;");
	QSqlQuery query(db);
	QString categories_str="";
	categories[ALL - 1] = true;
	if(is_elite)
	{
		categories[ELITE - 1] = true;
	}
	for(int i=0;i< CATEGORIES_NUM;i++)
	{
		if(categories[i])
		{
			categories_str = categories_str + QString::number(i + 1) + ",";
		}
	}
	if(logo.isEmpty())
	{
		logo = QApplication::applicationDirPath()+DEFAULT_IMAGE;
	}
	if(img.isEmpty())
	{
		img = QApplication::applicationDirPath()+DEFAULT_PNG;
	}

	QSqlQuery query_sel(db);
	query_sel.prepare("select id from kmd_menu where orig_name = :orig_name;");
	query_sel.bindValue(":orig_name", orig_name);
	if (query_sel.exec())
	{
		if (query_sel.next())
		{
			QString sql = "update kmd_menu"
				" set sort=:sort,locked=:locked,type=:type,category_id=:category_id,"
				"name=:name,orig_name=:orig_name,op=:op,"
				"func=:func,path=:path,url=:url,logo=:logo,img=:img,is_navbar=:is_navbar,is_elite=:is_elite,dev=:dev where orig_name=:orig_name;";
			query.prepare(sql);
			query.bindValue(":sort", sort);
			query.bindValue(":locked", locked);
			query.bindValue(":type", type);
			query.bindValue(":category_id", categories_str);
			query.bindValue(":name", name);
			query.bindValue(":orig_name", orig_name);
			query.bindValue(":op", op);
			query.bindValue(":func", func);
			query.bindValue(":path", path);
			query.bindValue(":url", url);
			query.bindValue(":logo", logo);
			query.bindValue(":img", img);
			query.bindValue(":is_navbar", is_navbar);
			query.bindValue(":is_elite", is_elite);
			query.bindValue(":dev", dev);
			if (!query.exec())
			{
				QSqlQuery rollback(db);
				rollback.exec("ROLLBACK;");
				return false;
			}

			return true;
		}
	}
	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,logo,img,is_navbar,is_elite,dev) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);";
	query.prepare(sql);
	query.addBindValue(sort.toInt());
	query.addBindValue("");
	query.addBindValue(locked);
	query.addBindValue(type);
	query.addBindValue(categories_str);
	query.addBindValue(name);
	query.addBindValue(orig_name);
	time_t create_time;
	time(&create_time);
	query.addBindValue(create_time);
	query.addBindValue(op);
	query.addBindValue(func);
	query.addBindValue(path);
	query.addBindValue(url);
	query.addBindValue("");
	query.addBindValue(true);
	query.addBindValue(logo);
	query.addBindValue(img);
	query.addBindValue(is_navbar);
	query.addBindValue(is_elite);
	query.addBindValue(dev);
	if(!query.exec())
	{
		QSqlQuery rollback(db);
		rollback.exec("ROLLBACK;");
		return false;
	}
	update_total();
	QSqlQuery commit(db);
	commit.exec("COMMIT;");

	return true;
}
bool SQLiteHelper::insert_software(QString name, QString orig_name, QString path, QString sort, bool* categories) {
	QSqlQuery begin(db);
	begin.exec("BEGIN;");
	QSqlQuery query(db);
	QString categories_str = "";
	categories[ALL - 1] = true;
	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,logo,img,is_navbar,is_elite,dev) 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(orig_name);
	time_t create_time;
	time(&create_time);
	query.addBindValue(create_time);
	query.addBindValue("app");
	query.addBindValue("open");
	query.addBindValue(path);
	query.addBindValue("");
	query.addBindValue("");
	query.addBindValue(true);
	query.addBindValue(QApplication::applicationDirPath() + DEFAULT_IMAGE);
	query.addBindValue(QApplication::applicationDirPath() + DEFAULT_PNG);
	query.addBindValue(false);
	query.addBindValue(false);
	query.addBindValue("");
	if (!query.exec())
	{
		QSqlQuery rollback(db);
		rollback.exec("ROLLBACK;");
		return false;
	}
	update_total();
	QSqlQuery commit(db);
	commit.exec("COMMIT;");

	return true;
}
bool SQLiteHelper::set_category(QList<Categrory>& categrories)
{
	QSqlQuery work(db);
	work.exec("begin;");
	QSqlQuery query2(db);
	bool ok=query2.exec("update kmd_category set status=0;");
	Categrory categrory_all;
	categrory_all.id = ALL;
	categrory_all.name = QString::fromLocal8Bit("全部");
	categrory_all.sort = 0;
	categrory_all.display = true;
	categrories << categrory_all;
	Categrory categrory_elite;
	categrory_elite.id = ELITE;
	categrory_elite.name = QString::fromLocal8Bit("推荐");
	categrory_elite.sort = 1;
	categrory_elite.display = true;
	categrories << categrory_elite;
	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,bool is_edit,bool all)
{
	QSqlQuery query(db);
	if(is_edit)
	{
		if (!query.exec("select id,name,status,sort,total from kmd_category where is_edit=1;"))
		{
			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();
			categrory.total = query.value("total").toInt();
			categrories << categrory;
		}
	}
	else if (all&&(!is_edit)) {
		if (!query.exec("select id,name,status,sort,total from kmd_category;"))
		{
			return false;
		}
		while (query.next())
		{
			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();
			categrory.total = query.value("total").toInt();
			categrories << categrory;
		}
	}
	else
	{
		if (!query.exec("select id,name,status,sort,total from kmd_category where status=1 order by sort;"))
		{
			return false;
		}
		while (query.next())
		{
			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();
			categrory.total = query.value("total").toInt();
			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 type='app' and status=1 order by is_navbar desc,sort asc;";
	}
	else if(category==ELITE)
	{
		sql = "select * from kmd_menu where type='app' and status=1 and is_elite=1 order by is_navbar desc,sort asc;";
	}
	else
	{
		sql = "select * from kmd_menu where category_id like '%";
		sql += QString::number(category, 10);
		sql += "%' and type='app' and status=1 order by is_navbar desc,sort asc;";
	}
	QSqlQuery query(db);
	if(!query.exec(sql))
	{
		return false;
	}
	while(query.next())
	{

		Record record;
		record.id = query.value("id").toInt();
		record.logo=query.value("logo").toString();
		record.is_navbar=query.value("is_navbar").toBool();
		record.img = QApplication::applicationDirPath()+query.value("img").toString();
		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)
{
	QSqlQuery begin(db);
	begin.exec("begin;");
	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);
		QString categories_str = "";
		for (int i = 0; i < CATEGORIES_NUM; i++)
		{
			if (categories[i])
			{
				categories_str += QString::number(i + 1) + ",";
			}
		}
		query.bindValue(":categories", categories_str);
		query.bindValue(":orig_name", orig_name);
		if (!query.exec())
		{
			QSqlQuery rollback(db);
			rollback.exec("rollback;");
			return false;
		}
		qDebug() << query.lastError();
		QSqlQuery categories_sql(db);
		update_total();
		QSqlQuery commit(db);
		commit.exec("commit;");
		return true;
	}else
	{

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

		update_total();
		QSqlQuery commit(db);
		commit.exec("commit;");
		return true;
	}
}

bool SQLiteHelper::delete_software(QString orig_name)
{
	QSqlQuery query(db);;
	query.prepare("delete from kmd_menu where orig_name=:orig_name;");
	query.bindValue(":orig_name", orig_name);
	if(!query.exec())
	{
		return false;
	}
	else
	{
		return true;
	}
}
bool SQLiteHelper::get_a_software(QString orig_name, Record2 *record) {
	QString sql = "select * from kmd_menu where orig_name=:orig_name;";
	QSqlQuery query(db);
	query.prepare(sql);
	query.bindValue(":orig_name", orig_name);
	if (!query.exec())
	{
		return false;
	}
	if (query.next())
	{
		for (int i = 0; i < 8; i++) {
			if (query.value("category_id").toString().contains(QString::number(i + 1))) {
				record->categories[i] = true;
			}
			else {
				record->categories[i] = false;
			}
		}
		record->sort = query.value("sort").toInt();
		record->name = query.value("name").toString();
		record->orig_name = query.value("orig_name").toString();
		record->op = query.value("op").toString();
		record->func = query.value("func").toString();
		record->exe_file = query.value("path").toString();
		record->url = query.value("url").toString();
		return true;
	}
	return false;
}

//警告：这个函数必须用于事务中
inline bool SQLiteHelper::update_total()
{
	
	for (int i = 0; i < CATEGORIES_NUM; i++)
	{
		QSqlQuery query2(db);
		if(i==ELITE-1)
		{
			query2.prepare("SELECT COUNT(*) AS total FROM kmd_menu WHERE is_elite=1 AND type='app';");
		}
		else if(i==ALL-1)
		{
			query2.prepare("SELECT COUNT(*) AS total FROM kmd_menu WHERE type='app';");
		}
		else
		{
			query2.prepare("SELECT COUNT(*) AS total FROM kmd_menu WHERE category_id LIKE :categoryId AND type='app';");
			query2.bindValue(":categoryId", "%" + QString::number(i + 1) + "%");
		}
		if (query2.exec() && query2.first())
		{
			int total = query2.value("total").toInt();
			query2.prepare("UPDATE kmd_category SET total=:total WHERE id=:id;");
			query2.bindValue(":total", total);
			query2.bindValue(":id", i + 1);
			if (!query2.exec())
			{
				QSqlQuery rollback(db);
				rollback.exec("ROLLBACK;");
				return false;
			}
		}
	}
	return true;
}

bool SQLiteHelper::use_software(QString orig_name)
{
	QSqlQuery query(db);
	query.prepare("update kmd_menu set use_time=:use_time where orig_name=:orig_name;");
	query.bindValue(":use_time", QDateTime::currentDateTime().toTime_t());
	query.bindValue(":orig_name", orig_name);
	if (!query.exec())
	{
		return false;
	}
	return true;
}